赛博日记本——我的开源桌面应用

简约无双

项目地址

github(欢迎大家点star)

gitlink(国内网络友好)

项目简介

  • 是什么:以日历的形式统计和查看日记文件的electron应用,完全本地运行,充分保护用户隐私;
  • 面向谁:用本地文件写日记,并想在本地直观查看日记统计数据和方便地预览日记,同时不想把自己的日记上传到云端的用户;
  • 主要功能:
    1. 以日历视图方便快捷地查看日记,不仅有助于用户查看日记分布,还便于用户回忆写日记时的情景。日历视图对应日期的预览功能可以帮用户快速定位日记或回忆相应时期的情景。日期下方的小方块的大小可以直观反映当天日记的字数。同时日记查看支持渲染markdown标准语法。
      预览图
    2. 可以通过搜索功能模块或右上方的搜索栏根据日记内容快速搜索对应日记,用户根据预览内容对应到想查找的日记可通过点击快速定位到日历视图进行日记查看,同时便于用户回忆对应日期附近的情景。让用户可以通过碎片化记忆回忆起当时的具体场景。
    3. 日记统计界面不仅能统计所有日记的总体数据,下方的折线图还可以直观展现每天都日记字数、每周、每月和每年的日记数量以及日记字数。点击折线图对应节点的小圆圈也可快速跳转到对应的日历视图,便于快速查看相应日记详情。
      预览图
  • 创作思路
    • 灵感来源:有些运动记录会通过日历视图来直观地统计运动量,于是我便想把这种直观的统计视图运用到日记上;
    • 想解决的问题:不上传到云端便能方便地查找、预览、统计本地日记;
    • 为什么做这个方向:我在用markdown写了上百篇日记之后查找日记和方便的预览日记成了一件非常麻烦的事情,而且也无法直观地查看日记的统计数据,而具有类似功能的应用普遍需要把日记上传到云端,对于日记这种私密文件,有泄漏隐私的风险,于是便想做一款应用来解决这些问题。

开发与迭代过程

这个项目是我的第一个开源的桌面应用,开发这个应用的过程中也大量使用了vibe coding。

因为我本身也在大量使用markdown写日记,但一直没找到一款合适的日记预览和查找工具(至少为目前还没找到),每次想查看日记都得挨个打开,搜索日记里面的内容时也得借助其他比较臃肿的工具,而且还无法看到日记的统计数据。于是我便萌生了自己开发一款工具的想法。

最初本来是打算做一款自用的node.js应用,但后来觉得这款应用正好补齐了用本地文件写日记但又找不到合适的工具的市场缺口。于是我便把这个软件开源了,还顺便参加了字节跳动举办的trae创造力大赛,并且拿到了先锋探索者奖,奖品是一个领夹式麦克风,拿到奖品的时候还是挺开心的。

后来我也把这款应用分享给了我的一些朋友,但很多没有web开发经历的人不知道node.js应用应该如何使用,于是我便又把这个应用用和node.js相近的electron技术栈重构成了一个桌面应用,这样使用起来就方便多了,这也是这个项目的v4.0大版本升级的地方。不过由于我平时基本只用linux系统,所以我没做windows系统和macos系统的适配,github release页面也只有appimage打包文件。如果有其他系统的适配需求,欢迎给这个项目提PR

另外这款应用对不同屏幕比例的适配还不是很完善,目前电脑屏幕的适配没什么问题,但其他比例的屏幕我还没做兼容性测试。

这个项目前前后后打磨了有一个月左右,目前已经进入一个比较稳定的阶段了,因为功能比较简单,所以我也没有继续打磨的计划了。但由于我每天也在使用这个应用,所以我仍会持续关注和维护的。

应用生态位

现在市面上绝大部分日记软件为了留住用户,把用户所在自己的生态之中,都会把日记文件内置在软件中,无法导出源文件,即使可以导出源文件,也是这款软件的私有格式,无法用其他软件打开和编辑。这也导致日记的迁移几乎不可能。像日记这种需要长期积累的东西,一旦被绑定到某款软件中,几乎只能一直使用下去。这不符合去中心化的理念。

要想多设备同步日记,不仅需要付费,还只能使用这款软件提供的服务器,对于日记这种隐私性很强的文件,这点足以劝退很多人。

目前也有一些开源的日记软件同样采用了markdown作为日记的文件格式,但却把所有日记放到了同一个markdown文件中。当日记越记越多之后,优化不好的编辑器势必无法打开,这时想查看或修改日记将非常困难。将所有日记放到同一个文件中的做法显然还有很多隐患,在此不一一列举。

而我开发的这款日记软件,每天的日记都是一个markdown文件,即使用记事本都可以轻松查看和编辑其中的内容,想查找某天的日记也非常方便,直接搜索对应日期的文件名就可以。而这种底层源文件完全开放的做法不仅方便用户迁移自己的日记,还能通过脚本等实现一些比较高级的批量操作。同时,这也使得多设备同步日记变得易如反掌,比如使用syncthing等用p2p协议进行文件同步等。其他好处请自行体会。

README

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
# 赛博日记本

一个基于 Electron 的本地可视化日记管理桌面应用,将 Markdown 格式的日记文件转换为精美的交互式网页,支持日历视图、全文搜索和数据统计功能。所有数据存储在本地,无需联网,完全掌控你的日记文件。

![现代](./resources/1.png)

![复古](./resources/2.png)

---

## 目录

- [技术栈](#技术栈)
- [功能特性](#功能特性)
- [安装步骤](#安装步骤)
- [使用方法](#使用方法)
- [界面风格](#界面风格)
- [常见问题](#常见问题)
- [项目结构](#项目结构)

---

## 技术栈

| 层级 | 技术 | 说明 |
|---|---|---|
| 桌面框架 | Electron 43+ | 主进程预渲染 HTML,渲染进程 `loadFile()` 加载本地页面,菜单交互无 IPC/preload |
| 构建脚本 | Node.js CommonJS | `index.js` 读取 `diary/*.md`,注入 JSON 到 `template.html` |
| 模板引擎 | 原生字符串替换 | `{{DIARIES_DATA}}` / `{{STATS_DATA}}` 构建时替换 |
| Markdown 渲染 | markdown-it 14+ | 支持 HTML、链接、typographer |
| 图表库 | Chart.js 4.4.7 | 本地 `libs/chart.min.js`,不依赖 CDN |
| 打包工具 | electron-builder 26+ | 支持 macOS / Windows / Linux 打包 |

---

## 功能特性

### 1. 日历视图
- 以月历形式展示所有日记
- 有日记的日期显示紫色方块标记
- 方块大小根据日记字数动态变化(字数越多,方块越大)
- 点击日期可查看日记详情

### 2. 日记详情面板
- 右侧弹出详情面板
- 支持 Markdown 渲染(包括图片、链接等)
- 日记中引用同一级 `resources/` 目录的图片:`![描述](resources/xxx.jpg)`
- 显示日记字数统计

### 3. 全文搜索
- 顶部搜索框支持按内容搜索
- 搜索结果显示日记预览(200 字)
- 实时匹配高亮

### 4. 统计图表
- **每日统计**:按日期统计字数
- **每周统计**:按周统计日记数量和字数
- **每月统计**:按月统计日记数量和字数
- **每年统计**:按年统计日记数量和字数
- 无日记的日期显示为 0
- 可点击图例小圆点快速跳转到对应日记

### 5. 年份/月份导航
- 年份/月份下拉选择器
- 上一月/下一月快捷切换
- 支持快速跳转到任意年月

### 6. 主题切换
- **赛博朋克**:默认紫色赛博朋克风格(深色背景 + 紫色主色调)
- **21th 简约**:浅色背景 + 蓝色强调色
- 主题切换后保持当前页面不变

---

## 安装步骤

### 环境要求

- **Node.js** 14+(推荐 18+)
- **npm**(随 Node.js 自带)

### 克隆仓库

git clone <repository-url>
cd cyber-diary

### 安装依赖

npm install

> 安装完成后 `postinstall` 会自动执行 `npm run prepare`,将 Chart.js 复制到 `libs/` 目录。

---

## 使用方法

### 开发模式(推荐)

npm run dev

该命令会:
1. 执行 `npm run build`,读取 `diary/*.md`,生成 `build/index.html` 并复制 `resources/`
2. 启动 Electron,加载本地 `build/index.html`
3. 自动打开 DevTools

开发模式下数据目录为项目内的 `diary/`,你可以直接编辑其中的 Markdown 文件。

### 菜单操作

应用顶部菜单栏提供以下操作:

| 菜单 | 功能 | 说明 |
|------|------|------|
| 文件 → 选择日记文件夹... | 打开文件夹选择对话框 | 选择任意目录作为日记源,立即重新构建 |
| 文件 → 重新构建 | 手动触发构建 | 重新读取当前日记文件夹并刷新页面 |

选择新日记文件夹后,应用会:
1. 读取新目录下的 `.md` 文件
2. 从新目录同级查找 `resources/`,复制到构建输出
3. 将选择的路径写入配置文件(下次启动自动恢复)
4. 刷新页面显示新的日记内容

图片路径约定:日记文件中可以使用 `resources/xxx.jpg``../resources/xxx.jpg` 两种方式引用同级目录下的资源,构建时会自动将路径统一处理为正确的相对位置。

### 首次启动与文件夹记忆

**首次启动**时,应用没有已保存的日记路径,会自动弹出系统文件夹选择框,让你指定日记存放目录。选择后该路径会被记录下来。

**以后每次启动**,应用会自动读取上一次选择的日记路径,直接使用该目录下的 `.md` 文件构建页面,无需再次选择。

记忆数据保存在 `app.getPath('userData')/config.json`,格式如下:

{
"lastDiaryDir": "/home/user/我的日记"
}

> 如果已保存的路径被删除或不再可用,下次启动时会重新弹出文件夹选择框。

### 构建 HTML(不启动 Electron)

npm run build

输出:
- `build/index.html` — 包含所有日记数据和统计信息的单页应用
- `build/resources/` — 复制自 `resources/`

### CLI 模式(兼容旧用法)

node index.js --dir /path/to/custom-diary

不传入 `--dir` 时默认使用项目内 `diary/` 目录。

### 打包成桌面应用

npm run dist

打包产物位于 `dist/` 目录:
- **macOS**`.dmg` 文件
- **Windows**`.exe` 安装包
- **Linux**`.AppImage` 文件

打包配置说明:
- `asar: true` — 源码打包为 asar
- `asarUnpack: diary/**/*` — 开发模板数据不打包进 asar
- `extraResources: [{ from: 'diary', to: 'diary' }]` — 包含初始日记模板

### 生产环境数据目录

打包应用只在 `userData` 存放构建产物和第三方库,不复制日记文件和资源:

| 路径 | 内容 | 来源 |
|------|------|------|
| `app.getPath('userData')/build/` | 构建输出的 `index.html` | 每次构建生成 |
| `app.getPath('userData')/libs/` | Chart.js 等第三方库 | 首次从 asar 复制 |

日记文件和资源(图片等)直接从用户选择的文件夹读取,每次构建时重新读取,不复制到 `userData`

在 Linux 上,`userData` 默认为 `~/.config/cyber-diary/`

### 运行时构建流程

每次点击「重新构建」或选择新日记文件夹时:

1. `main.js` 调用 `index.js.build(diaryDir, { buildDir })`
2. 读取 `diaryDir` 下的所有 `.md` 文件,渲染为 HTML
3.`diaryDir/../resources/` 复制资源到 `build/resources/`
4. 窗口加载新的 `build/index.html`

> **注意**:`resources/` 和 `diary/` 必须始终同级。无论选择哪个文件夹作为日记源,其上级目录中的 `resources/` 都会被同步到构建输出。支持任意层级的子目录嵌套。

---

## 日记文件规范

`diary/` 文件夹中创建 Markdown 格式的日记文件,文件名必须遵循以下格式:

**格式一**

yyyyMMdd.md

例如:
- `20260606.md`(2026年6月6日)
- `20260705.md`(2026年7月5日)

**格式二**

yyMMdd.md

例如:
- `260606.md`(自动转换为2026年6月6日)
- `260705.md`(自动转换为2026年7月5日)

> **提示**:6 位日期格式会自动添加 `"20"` 前缀,转换为 `20xx` 年的日期。

**注意**
- 文件名必须是纯数字的日期格式
- 文件内容使用标准 Markdown 语法
- 支持标题、列表、加粗、链接等 Markdown 特性

### 示例日记内容

# 今天的心情

今天天气很好,阳光明媚。

## 工作
- 完成了项目报告
- 参加了团队会议

## 生活
晚上和朋友一起吃了火锅,很开心!

> 生活不止眼前的苟且,还有诗和远方。

---

## 界面风格

### 紫色赛博朋克风格(默认)
- **主题色**:紫色(`#9b59b6`
- **背景**:深色赛博朋克风格,带渐变光晕效果(`#0a0a0f`
- **卡片**:半透明毛玻璃效果(`rgba(255,255,255,0.05)`
- **页面风格**:半透明方角设计
- **下拉菜单**:紫色半透明边框,毛玻璃效果

### 21th 简约风格
- **主题色**:蓝色(`#0040ff`
- **背景**:浅色简约风格(`#c5c9c9`
- **卡片**:白色背景,深色边框
- **字体**:Geist 字体
- **页面风格**:方角设计,带阴影效果

---

## 常见问题

### Q:如何更新日记?
A:修改 `diary/` 文件夹中的 Markdown 文件后,重新运行 `npm run build` 或重启应用即可更新。

### Q:打包后日记数据存在哪里?
A:日记文件和资源(图片等)**不复制到 `userData`**,直接从你选择的文件夹读取。`userData` 下只存放构建产物(`build/`)和 Chart.js 等第三方库(`libs/`)。完整的目录结构请见[生产环境数据目录](#生产环境数据目录)。

### Q:如何更换日记文件夹?
A:在菜单栏点击 **文件 → 选择日记文件夹...**,选择任意包含 `.md` 日记文件的目录。系统会自动重新构建并刷新页面。每次更换都会同步该目录同级的 `resources/` 资源。选择后路径会被记忆,下次启动自动恢复。

### Q:可以管理多个日记文件夹吗?
A:可以。每次通过 **文件 → 选择日记文件夹...** 切换即可。应用会记住最后使用的路径,下次启动时自动加载。可以通过修改 `~/.config/cyber-diary/config.json` 中的 `lastDiaryDir` 字段手动指定。

### Q:日记中的图片如何引用?
A:使用相对路径引用同级 `resources/` 目录中的文件,例如 `![照片](resources/photo.jpg)``![照片](../resources/photo.jpg)` 均可。支持任意层级的子目录嵌套,例如 `![图标](resources/images/icons/star.png)` 也会被正确复制到构建输出。

### Q:为什么某些日期没有显示?
A:系统会自动填充第一篇和最后一篇日记之间的所有日期。如果日期超出这个范围,则不会显示。

### Q:搜索结果预览字数可以调整吗?
A:可以在 `index.js` 第 38 行修改预览字数。

### Q:如何删除日记?
A:直接删除 `diary/` 文件夹中对应的 `.md` 文件,重新构建即可。

### Q:应用可以离线使用吗?
A:可以。Chart.js 已本地化到 `libs/chart.min.js`,不依赖任何 CDN,完全离线可用。

---

## 项目结构

cyber-diary/
├── main.js # Electron 主进程入口(菜单、文件对话框、构建调度)
├── index.js # 构建脚本,导出 build(diaryDir)
├── prepare.js # 复制 Chart.js 到 libs/
├── template.html # HTML 模板(自包含 CSS+JS)
├── package.json # 项目配置 + electron-builder 配置
├── diary/ # 日记文件存放目录(开发环境)
├── resources/ # 静态资源(图片等,与 diary/ 同级)
├── build/ # 生成的 HTML 文件(git-ignored)
│ ├── index.html # 构建输出
│ └── resources/ # 复制自 resources/
├── libs/ # 本地第三方库
│ └── chart.min.js # Chart.js 本地副本
└── extra/ # 实验性备用模板

### 生产环境运行时目录(AppImage 首次启动后)

~/.config/cyber-diary/
├── config.json # 配置信息(最近使用的日记文件夹路径)
├── build/
│ ├── index.html # 构建输出
│ └── resources/ # 复制自 diaryDir/../resources/
└── libs/
└── chart.min.js

日记文件和资源(图片等)**不复制到 `userData`**,直接从用户选择的文件夹读取。

---

## 开发说明

### 数据流

开发模式:
diary/*.md → index.js (markdown-it render + stats) → build/index.html
resources/ → 从 diary/ 同级复制 → build/resources/

生产模式(菜单选择文件夹):
任意文件夹/*.md → main.js 调用 index.js.build() → userData/build/index.html
任意文件夹/../resources/ → 从 diaryDir 同级复制 → userData/build/resources/

`template.html` 中的 `{{DIARIES_DATA}}``{{STATS_DATA}}` 在构建时被替换为 JSON 数据。

### 重要约束

- `build/` 已被 `.gitignore` 忽略,修改 `template.html` 或 JS 后需运行 `npm run build` 再提交
- `diary/*.md` 内容不得删除或修改(除非明确要求)
- `template.html` 中 Chart.js 必须保持本地路径 `../libs/chart.min.js`,不得改回 CDN
- 不要添加框架、bundler 或 transpiler(除非明确要求)
- `resources/` 始终与 `diary/` 同级,构建时会自动同步到构建输出
- 生产环境菜单栏提供「选择日记文件夹...」和「重新构建」功能,无需修改配置文件

## License

This project is licensed under the **PolyForm Noncommercial License 1.0.0**.

- Free for personal study, hobby, academic research, non-profit & government organizations.
- **Commercial use, corporate internal production deployment, paid SaaS, commercial bundling are strictly prohibited.**
- If you need commercial licensing, contact: <jianyuewushuang@163.com>.

See the full legal terms in [LICENSE](./LICENSE).
  • 标题: 赛博日记本——我的开源桌面应用
  • 作者: 简约无双
  • 创建于 : 2026-08-31 16:49:00
  • 更新于 : 2026-09-12 23:34:42
  • 链接: https://blog.jianyuewushuang.top/2026/08/31/赛博日记本/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论
目录
赛博日记本——我的开源桌面应用