67 lines
6.7 KiB
Markdown
67 lines
6.7 KiB
Markdown
# 阶段 0 · 产品架构设计
|
||
|
||
> 对齐需求文档 §1–§19。本文件是阶段 1–7 的施工图:模块边界、数据流、关键机制。
|
||
> 界面结构与操作逻辑按需求 §3 定稿,本文件不复述菜单清单,只定实现结构。
|
||
|
||
## 1. 总体结构
|
||
|
||
```text
|
||
┌──────────────────────────── Tauri 2 应用 ────────────────────────────┐
|
||
│ 前端 (React + TS) │
|
||
│ ├─ app/ 窗口装配:标题栏、菜单、标签页、侧边栏、状态栏 │
|
||
│ ├─ editor/ 编辑器装配层(Milkdown Kit 组装、命令、装饰、序列化) │
|
||
│ ├─ features/ 文件树 / 大纲 / 查找替换 / 图片 / 导出 / 主题 / 设置 │
|
||
│ └─ stores/ 文档会话状态(每标签一份 EditorSession) │
|
||
│ │ invoke / event(Tauri IPC) │
|
||
│ 后端 (Rust) │
|
||
│ ├─ fs 命令 读/写(临时文件+原子替换)、目录遍历、监听外部变更 │
|
||
│ ├─ sqlite 设置 / 最近文件 / 工作区 / 恢复记录(不存正文) │
|
||
│ └─ export PDF 打印管线、DOCX 生成等重活与系统能力 │
|
||
└───────────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
职责红线:正文只在前端编辑器文档模型与磁盘 .md 之间流动;Rust 侧不解析 Markdown 结构(导出管线除外);SQLite 永不成为正文唯一副本。
|
||
|
||
## 2. 编辑器装配层(核心)
|
||
|
||
阶段 0 原型 `prototype/src/editor.ts` 即装配层的雏形,正式版按此扩展:
|
||
|
||
- **创建工厂**:`createMarkdownEditor(root, markdown, onUpdate)` —— commonmark + gfm + history + listener + clipboard + indent。阶段 2/3 在同一工厂按序叠加:源码模式桥、数学、Mermaid、代码高亮装饰、表格浮动工具栏、图片节点视图。UI 与测试共用工厂,保证测过的即交付的。
|
||
- **文档模型**:ProseMirror Node 树为唯一编辑态;Markdown 文本只是它的序列化投影。打开 = remark 解析建模;保存 = serializer 序列化。禁止任何模块绕过模型直接拼接 md 文本修改文档(查找替换、标题拖拽排序等结构操作一律走事务)。
|
||
- **序列化策略**:`remarkStringifyOptionsCtx` 统一配置(当前 `bullet: '-'`);序列化只在保存/导出/源码模式切换时全量执行,编辑期仅 listener 节流通知脏状态,不逐键全量序列化(性能纪律)。
|
||
- **输入规则与标记显隐**:Typora 式「当前节点显示标记、其余隐藏」用 ProseMirror Decoration 按选区所在节点动态切换(阶段 2 核心工作),不触发文档事务、不进历史栈。
|
||
- **IME**:不拦截 composition 事件、不在 composition 期间跑输入规则(ProseMirror View 原生语义 + 装配层显式守卫,阶段 2 写进编辑器测试清单并在 Windows 真机用微软拼音/搜狗各验一轮)。
|
||
- **历史**:history 插件独立栈;格式切换、结构命令均以单事务提交,保证一次 Ctrl+Z = 一次用户动作。
|
||
|
||
## 3. 文档会话与数据安全(需求 §8/§17)
|
||
|
||
- 每个标签页 = 一个 `EditorSession`:{ 文件路径 | 未命名、文档模型、脏标记、编码/换行符、上次保存哈希 }。
|
||
- **保存**:序列化 → 写同目录临时文件 → 原子替换 → 更新哈希。全程失败(权限/磁盘满)向用户明确报错,保留脏状态与恢复记录,绝不静默丢弃。
|
||
- **自动保存**:可配置延迟(默认停顿 2s 后、仅对已命名且无外部冲突的文档),走同一保存管线。
|
||
- **恢复记录**:每次编辑节流写入 SQLite recovery_records(文档键 + 序列化全文 + 时间戳);正常关闭清除;异常启动时提示恢复。
|
||
- **外部修改检测**:Rust 监听已打开文件;外部变更且本地无修改 → 静默重载;本地已修改 → 弹窗三选(重载丢弃 / 保留本地另存 / 对比),不自动覆盖任何一方。
|
||
- **编码**:读入探测 UTF-8 / UTF-8 BOM / GBK(Rust 侧解码),内部统一 UTF-8;保存默认 UTF-8(保留原 BOM 策略可配置),换行符 LF/CRLF 按原文或设置。
|
||
|
||
## 4. UI 结构(需求 §3 的实现映射)
|
||
|
||
- **窗口**:Tauri 自定义标题栏(decorations 关闭 + 前端标题栏组件),拖动区、双击最大化、最小/最大/关闭走 window API;Win10/11 同一实现。
|
||
- **布局**:菜单栏(原生菜单语义的自绘实现,保证快捷键与禁用态一致)→ 标签栏 → [可折叠侧边栏 | 编辑区] → 状态栏。侧边栏宽度/状态持久化;编辑区正文容器限宽居中(主题变量控制),侧边栏开合不改变正文宽度设定。
|
||
- **侧边栏双模式**:文件树(Rust 目录遍历 + 懒加载)/ 大纲(由文档模型标题节点实时投影,点击定位、跟随光标高亮、拖拽排序转结构事务)。
|
||
- **主题**:两层——应用 UI 主题(CSS 变量)与文档主题(作用域限定在 `.editor-doc` 容器内的 CSS,自定义主题 CSS 经作用域重写后注入,无法污染应用 UI,对应需求 §11.2 红线)。内置 7 主题阶段 5 自行实现。
|
||
- **设置中心**:左分类右内容,全部落 SQLite settings 表,重启生效;快捷键表独立存储并做冲突检测(需求 §14/§15)。
|
||
|
||
## 5. 导入导出(需求 §12/§13,阶段 5)
|
||
|
||
- 导出 HTML:由文档模型经 remark 管线生成 + 当前文档主题 CSS 内联,图片相对路径可选打包为独立文件目录或 base64 单文件。
|
||
- 导出 PDF / 打印:隐藏打印视图 + 专用 print CSS,WebView2 打印管线;页眉页脚/页码走打印参数。
|
||
- 导出 DOCX:Rust 侧(docx 生成库)按模型结构映射标题/列表/表格/图片。
|
||
- 导入 TXT/HTML:转 Markdown 后建模;DOCX/EPUB 排后续阶段。
|
||
|
||
## 6. 目录结构
|
||
|
||
按需求 §22 建议落地,阶段 1 建仓时创建(`src/editor/` 内部细分为 core/extensions/markdown/commands/decorations/serializers)。阶段 0 仓库当前只有 `docs/`、`prototype/`、`samples/`,不预铺正式工程空架子。
|
||
|
||
## 7. 阶段门禁
|
||
|
||
每阶段:构建通过 + 该阶段自动化测试 + 人工验收清单(见 03 号报告模板)→ 大王确认 → 下一阶段。编辑器相关阶段额外要求:往返稳定性测试套件(阶段 0 已建)必须全绿,新增语法支持必须先给套件加用例。
|