阶段 1 可靠性设计与验证
- 阶段 1 的目标是让文档在写盘失败、应用退出、异常中断和外部修改时都有明确且可恢复的状态。
- 本阶段不引入自动保存到用户原文件;恢复稿与用户主动保存仍保持不同语义。
保存与编码策略
原子保存
保存流程如下:
- 在目标文件同一目录创建唯一临时文件。
- 写入全部内容并调用文件刷盘。
- 尽可能保留现有文件权限。
- 使用原子重命名替换目标文件。
- 对支持目录刷盘的平台同步目录项。
- 任一步失败都删除临时文件并保留原目标文件。
Windows 文件被其他程序占用、目录无写入权限或磁盘空间不足时,保存会失败并显示错误,不会改写编辑器中的唯一内容。用户可使用“另存为”选择其他位置。
UTF-8 与换行
- 只读取有效 UTF-8;无效字节会明确报错,不使用替换字符悄悄改变正文。
- 编辑器内部统一使用 LF。
- 已有文件保存时保留 UTF-8 BOM 状态以及主要的 LF/CRLF 风格。
- 新文档默认使用无 BOM UTF-8 和 LF。
- 状态栏显示当前文档的编码、BOM 和换行风格。
会话与恢复稿
- 打开的标签、活动标签、正文、脏状态和编码元数据按笔记库分别保存到 Electron
userData/recovery/session-<笔记库路径哈希>.json。 - 切换笔记库时先保存当前标签,再载入目标笔记库的标签。
- 未打开笔记库时,标签只保留在当前进程内存中,不读取或写入恢复会话。
- 恢复数据使用原子写入,单文档上限 20 MB、单会话上限 50 MB、最多 50 个文档。
- 输入停止约 300 ms 后更新恢复会话;窗口关闭前再次强制刷新。
- 刷新失败时阻止关闭并让用户决定继续关闭还是返回编辑器。
- 下次启动时,未保存内容从恢复稿恢复;干净的磁盘文件重新读取最新版。
- 损坏的恢复文件会被隔离为对应的
session-<哈希>.corrupt-时间戳.json,不会阻塞应用启动。 - 用户明确关闭并确认丢弃某个标签后,该标签会从恢复会话移除。
恢复稿位于当前操作系统用户的应用数据目录,依赖操作系统账户和磁盘加密保护。本阶段不宣称提供端到端加密。
外部文件修改
主进程监听已打开文档所在目录,并对文件事件去抖:
- 应用自身原子保存产生的事件通过内容签名忽略。
- 每次保存前再次比较打开时的磁盘基线签名;即使文件监听事件尚未到达,也会拒绝覆盖已变化的磁盘版本。
- 文档无本地修改时,自动载入磁盘新版本。
- 编辑器与磁盘同时修改时,显示左右双版本对比。
- 冲突时可保留编辑器版本、载入磁盘版本,或将编辑器版本另存为新文件。
- 磁盘文件被删除时,编辑器内容转为未保存恢复稿,不会自动丢弃。
- 文件监听失败时保留当前内容,并在状态信息中记录错误。
冲突处理不进行自动文本合并,因为 Markdown 结构的错误合并可能破坏代码块、列表和引用。
预览与交互
- 输入事件立即更新文档状态和恢复稿调度,但 Markdown 预览等待 120 ms 去抖。
- 每次新输入都会使旧渲染令牌失效;过期 IPC 返回结果不会覆盖最新预览。
- 标签使用标准
tablist/tab语义,并支持左右方向键切换。 - 所有交互控件提供键盘焦点样式;冲突对话框拥有标题、版本区域和明确操作按钮。
- 工具栏“另存为”按钮执行另存为;
Alt+Shift+S为系统级主窗口热键:已显示且激活时最小化,否则恢复显示并激活。
自动化覆盖
- UTF-8、BOM、LF/CRLF 检测与原子写入。
- 文件读写、图片复制、路径授权和 IPC 保存。
- 恢复会话原子写入、读取及损坏隔离。
- 文件监听的自身写入过滤、外部变化和删除。
- 文档状态快照、恢复和外部版本应用。
- 保存前磁盘基线变化检测,确认外部版本不会被竞态覆盖。
- Electron 冒烟测试覆盖最新预览、未保存关闭确认、关闭前恢复稿刷新和基础无障碍语义。
人工故障验证
在发布制品上补充以下平台测试:
- 使用另一个编辑器修改无本地改动的已打开文件,确认自动重载。
- 两边同时修改,确认出现双版本对比且三个处理选项均不丢内容。
- 删除已打开文件,确认当前正文被保留为恢复稿。
- 将目标文件设为只读或占用,确认保存失败后原文件与编辑器正文都完整。
- 强制结束应用进程,重新启动并确认未保存标签恢复。
- 分别打开 BOM/无 BOM、LF/CRLF 文件,保存后确认格式保持。
- 用键盘完成标签切换、保存、另存为、预览开关和冲突处理。
