- wire SQLite control-plane access/session paths into Rust web local-folder routes - preserve local Markdown attachment semantics across upload, reload, and secondary-pane resource tabs - refresh design governance docs, Reasonix task templates, and bug records - retire root .mcp.json local MCP config
439 lines
16 KiB
Markdown
439 lines
16 KiB
Markdown
# 6 [reference] Mindmap Kernel Phase 6:leptos-mindmap Projection Editor v1
|
||
|
||
> 更新时间:2026-05-10
|
||
>
|
||
> 当前状态:`reference`。本文保留 mindmap Phase 6 总设计;已完成 UI shell reuse 归档到 `design/06-mindmap/done/`,后续新工作需另拆小 checklist。
|
||
>
|
||
> 当前口径:`leptos-mindmap`
|
||
>
|
||
> 旧稿归档:
|
||
> - `/mnt/Data1T/mnote/recycle/design/06-mindmap/process/6-mindmap-kernel-phase6-projection-editor-v1.rust-native-2026-05-10.md`
|
||
>
|
||
> 当前主线依据:
|
||
> - `/mnt/Data1T/mnote/design/01-05-current-priority-overview.md`
|
||
> - `/mnt/Data1T/mnote/design/01-tree-first-graph-kernel/reference/1-tree-first-graph-kernel-v1.md`
|
||
> - `/mnt/Data1T/mnote/design/03-rust-web/reference/3-rust-web-long-term-architecture-v1.md`
|
||
> - `/mnt/Data1T/mnote/design/05-editor-mainline/reference/5-5-page-aggregate-single-truth-alignment-v1.md`
|
||
>
|
||
> 参考实现:
|
||
> - `/mnt/Data1T/mnote/design/05-editor-mainline/reference-code/lx-doc/mind-map`
|
||
> - `/mnt/Data1T/mnote/design/05-editor-mainline/reference-code/kmind-plugin`
|
||
> - `/mnt/Data1T/mnote/design/05-editor-mainline/reference-code/siyuan-kmind-plugin`
|
||
|
||
## 1. 文档目的
|
||
|
||
这份文档重新修正 Mindmap Phase 6 的落地口径。
|
||
|
||
旧稿把 Phase 6 定义为 `Rust / Leptos 原生 Projection Editor`,并把 `simple-mind-map` 排除在本轮 runtime 主链之外。该口径在长期上最干净,但在当前阶段等同于用 Rust 重写 `lx-doc/mind-map` / `simple-mind-map` 的编辑器和布局引擎,短期会继续产出可验证但不可用的导图纵切。
|
||
|
||
当前口径改为:
|
||
|
||
> **leptos-mindmap:Rust kernel 持有导图事实源与命令语义,`simple-mind-map` / KMind-like runtime 作为 Leptos 文档页中的编辑器 adapter。**
|
||
|
||
这份文档回答的是:
|
||
|
||
> **如何在不放弃 tree-first graph kernel 的前提下,先交付接近 KMind 可用度的导图编辑器。**
|
||
|
||
## 2. 先给结论
|
||
|
||
Phase 6 不再以 Rust 自绘导图 renderer 为第一目标。
|
||
|
||
Phase 6 的主目标是建立:
|
||
|
||
```text
|
||
kernel truth
|
||
-> mindmap.kernel_projection.v1
|
||
-> mindmap.simple_mind_map_scene.v1
|
||
-> leptos-mindmap editor island
|
||
-> simple-mind-map / KMind-like runtime
|
||
-> adapter diff / command bridge
|
||
-> kernel command
|
||
```
|
||
|
||
其中:
|
||
|
||
- Rust kernel 是事实源。
|
||
- `simple-mind-map` 是显示与交互 runtime。
|
||
- `leptos-mindmap` 是二者之间的稳定 adapter。
|
||
- `lx-doc/mind-map` 和 KMind 插件是行为、视觉、工具栏、侧栏和主题的参考实现。
|
||
- 旧 React `MindmapBlock.tsx` 只能作为 legacy/compat 参考,不作为当前文档页主链。
|
||
- TypeScript NodeView / bridge 只允许作为 `leptos-tiptap` 与 `simple-mind-map` 的薄兼容层;toolbar、sidebar、navigator、context menu 等 UI shell 的长期归属应逐步迁到 Leptos/Rust 组件,避免继续扩散 React/Vue/TS UI 运行时。
|
||
|
||
这不是“直接嵌入 `lx-doc/mind-map` 保存 blob”,也不是“立即 Rust 重写 `lx-doc/mind-map`”。它是中间路线:
|
||
|
||
> **Rust 内核 + lx-doc/KMind 级显示编辑体验。**
|
||
|
||
## 3. 三条路线的定位
|
||
|
||
### 3.1 Rust 重写 lx-doc/mind-map
|
||
|
||
这是长期最干净的路线。
|
||
|
||
优点:
|
||
|
||
- kernel、projection、layout、hit-test、selection、history 都能完全统一。
|
||
- AI/CLI 可直接操作导图内核,不被前端库字段绑架。
|
||
- 长期不受 `simple-mind-map` 事件粒度、数据格式和插件边界限制。
|
||
|
||
问题:
|
||
|
||
- 实际上要重写的是 `simple-mind-map` 引擎,而不只是 `lx-doc/mind-map` 的 Vue UI。
|
||
- 需要自研布局、节点测量、连线、概要、外框、关联线、拖拽、快捷键、导入导出、主题、MiniMap、富文本等完整编辑器能力。
|
||
- 短期会牺牲可用体验。
|
||
|
||
结论:
|
||
|
||
> 保留为长期方向和后续 Rust-native engine 路线,但不再作为 Phase 6 的主验收。
|
||
|
||
### 3.2 Rust 内核 + lx-doc/mind-map 显示
|
||
|
||
这是当前推荐路线,即 `leptos-mindmap`。
|
||
|
||
优点:
|
||
|
||
- 能快速获得接近 KMind 的可用编辑体验。
|
||
- Rust kernel 仍然持有事实源、projection 和 command。
|
||
- 可以逐步把 `simple-mind-map` 字段提升为 kernel-native 语义。
|
||
- 与 `leptos-tiptap` 的定位一致:前端编辑器是 runtime,不是系统事实源。
|
||
|
||
问题:
|
||
|
||
- `simple-mind-map` 的事件不一定足够细,需要 adapter diff。
|
||
- 高级能力短期可能需要 `compat_payload`。
|
||
- 必须严格防止回退成“保存整棵前端 blob”。
|
||
|
||
结论:
|
||
|
||
> 作为 Phase 6 主线。
|
||
|
||
### 3.3 直接嵌入 lx-doc/mind-map
|
||
|
||
这是最快路线,但不作为主线。
|
||
|
||
优点:
|
||
|
||
- 最快得到完整 UI。
|
||
- 迁移成本看起来最低。
|
||
|
||
问题:
|
||
|
||
- `lx-doc/mind-map` 会重新成为事实源。
|
||
- 长期仍保存 `simple-mind-map` blob。
|
||
- kernel、AI、Page Aggregate、tree realtime 只能在外围补偿。
|
||
|
||
结论:
|
||
|
||
> 只可作为短期 demo 或对照,不作为 mnote 主线。
|
||
|
||
## 4. leptos-mindmap 的边界
|
||
|
||
`leptos-mindmap` 是一个编辑器 adapter,不是新的事实源。
|
||
|
||
它负责:
|
||
|
||
- 在 `leptos-tiptap` NodeView 中挂载导图编辑器。
|
||
- 把 kernel projection 转成 `simple-mind-map` 可消费的数据。
|
||
- 初始化并管理 `simple-mind-map` runtime 和必要插件。
|
||
- 监听导图数据与视图变化。
|
||
- 把变化转成 kernel command 或 adapter diff。
|
||
- 渲染 KMind-like toolbar、右侧样式栏、底部工具和错误状态。
|
||
- 承载 floating overlay canvas shell,并逐步把 UI shell 从临时 TypeScript DOM 渲染迁回 Leptos/Rust 组件边界。
|
||
|
||
它不负责:
|
||
|
||
- 长期保存整棵导图 blob。
|
||
- 绕过 kernel command 直接把前端 runtime 数据写成 canonical truth。
|
||
- 在 UI 层创造第二套树真相、顺序真相或引用边真相。
|
||
- 把 `window.__mindmapInstance`、React mount 点或占位 DOM 作为完成判定。
|
||
- 把 TypeScript NodeView 扩写成长期 UI 框架;TS 只保留 tiptap / runtime bridge、动态加载、事件转发和最小 DOM mount 职责。
|
||
|
||
## 5. 数据分层
|
||
|
||
### 5.1 kernel truth
|
||
|
||
长期事实源应表达:
|
||
|
||
- `Mindmap`
|
||
- `MindmapNode`
|
||
- parent / child order
|
||
- collapsed state
|
||
- summary / generalization
|
||
- associative line
|
||
- node style
|
||
- link / reference edge
|
||
- theme / layout / view state
|
||
|
||
这些字段应属于 kernel 或 kernel projection,不能只存在于 `simple-mind-map` blob。
|
||
|
||
### 5.2 mindmap.kernel_projection.v1
|
||
|
||
这是稳定投影,供 AI、CLI、独立页、文档页和后续 Rust-native renderer 使用。
|
||
|
||
它应包含:
|
||
|
||
- `schema`
|
||
- `documentId`
|
||
- `mindmapId`
|
||
- `rootNodeId`
|
||
- `revision`
|
||
- `nodes`
|
||
- `edges`
|
||
- `summaries`
|
||
- `associativeLines`
|
||
- `layout`
|
||
- `theme`
|
||
- `view`
|
||
- `capabilities`
|
||
- `source`
|
||
|
||
### 5.3 mindmap.simple_mind_map_scene.v1
|
||
|
||
这是 adapter projection,只服务 `simple-mind-map` runtime。
|
||
|
||
它应包含:
|
||
|
||
- `root`
|
||
- `layout`
|
||
- `theme`
|
||
- `themeConfig`
|
||
- `view`
|
||
- `config`
|
||
- `compatPayload`
|
||
- `projectionRevision`
|
||
- `kernelRevision`
|
||
|
||
注意:这层可以长得像 `simple-mind-map`,但它不是 canonical truth。
|
||
|
||
### 5.4 compat_payload
|
||
|
||
短期无法语义化的字段进入 `compat_payload`。
|
||
|
||
允许先放入:
|
||
|
||
- 高级节点样式
|
||
- 图片
|
||
- 公式
|
||
- 附件
|
||
- 富文本片段
|
||
- 第三方插件私有字段
|
||
- KMind 专有扩展
|
||
|
||
但每个字段必须有提升策略,不能无限期成为黑箱。
|
||
|
||
## 6. 命令桥接
|
||
|
||
Phase 6 最小命令集:
|
||
|
||
- `mindmap.node.update_text`
|
||
- `mindmap.node.insert_child`
|
||
- `mindmap.node.insert_sibling_after`
|
||
- `mindmap.node.delete`
|
||
- `mindmap.node.move`
|
||
- `mindmap.view.patch`
|
||
- `mindmap.layout.set`
|
||
- `mindmap.theme.set`
|
||
- `mindmap.summary.set`
|
||
- `mindmap.associative_line.upsert`
|
||
|
||
桥接方式分两级。
|
||
|
||
### 6.1 直接命令
|
||
|
||
如果 toolbar 或快捷键能明确知道用户意图,直接发 kernel command。
|
||
|
||
示例:
|
||
|
||
- 点击“子节点” -> `mindmap.node.insert_child`
|
||
- 点击“同级节点” -> `mindmap.node.insert_sibling_after`
|
||
- 节点文本提交 -> `mindmap.node.update_text`
|
||
- 删除节点 -> `mindmap.node.delete`
|
||
|
||
### 6.2 adapter diff
|
||
|
||
如果 `simple-mind-map` 只给出 `data_change`,则对比上一份 adapter projection 和当前 runtime data。
|
||
|
||
diff 输出:
|
||
|
||
- 可识别变化转 kernel command。
|
||
- 暂不可识别变化转 `compat_payload.patch`,并打上 `source="adapter-diff"`。
|
||
|
||
禁止把整棵 runtime data 直接作为 canonical success。
|
||
|
||
## 7. UI 对标范围
|
||
|
||
第一阶段对标 `image copy 60.png` 和 KMind/lx-doc 体验,但不追全量功能。
|
||
|
||
必须有:
|
||
|
||
- 顶部工具栏:撤销、重做、编辑节点、同级节点、子节点、删除节点、标签、超链接、备注、图片、图标、概要、关联线、公式、格式刷、导入、导出。
|
||
- 中央画布:真实节点、连线、pan、zoom、选择、双击编辑、键盘基本操作。
|
||
- 右侧触发栏:节点样式、导图样式、主题、结构、大纲。
|
||
- 底部工具:节点数/字数、回到根节点、搜索、缩放百分比、全屏或只读入口。
|
||
- 错误状态:projection 获取失败、command 失败、adapter diff 失败要可定位。
|
||
|
||
可延期:
|
||
|
||
- 完整主题设计器。
|
||
- 多根节点。
|
||
- 思源块悬浮预览。
|
||
- 镜像块。
|
||
- MOC 模式。
|
||
- PDF 标注跳转。
|
||
- 全量 XMind/Freemind 导入导出。
|
||
|
||
## 8. 代码落点建议
|
||
|
||
### 8.1 Rust 协议层
|
||
|
||
- `rust/crates/core-protocol/src/mindmap.rs`
|
||
- 定义 kernel projection DTO。
|
||
- 定义 adapter projection DTO。
|
||
- 定义 command DTO。
|
||
- 标记旧 `MindmapTreeNode` / `MindmapOp` 为 compat。
|
||
|
||
### 8.2 Rust runtime 层
|
||
|
||
- `rust/crates/bridge-runtime/src/lib.rs`
|
||
- 构建 `mindmap.kernel_projection.v1`。
|
||
- 构建 `mindmap.simple_mind_map_scene.v1`。
|
||
- 执行 kernel command。
|
||
- 维护 compat snapshot。
|
||
|
||
### 8.3 Rust Web 层
|
||
|
||
- `rust/crates/mnote-web/`
|
||
- 暴露 projection / command route。
|
||
- 保持 3000 是前端公开入口。
|
||
- 不在 Rust Web 内联第三方编辑器业务逻辑。
|
||
|
||
### 8.4 Leptos / Tiptap 层
|
||
|
||
- `rust/spikes/leptos-tiptap-spike/src/lib.rs`
|
||
- 提供 mindmap NodeView。
|
||
- 挂载 `leptos-mindmap` island。
|
||
- Tiptap 节点只保存 `mindmapId/rootNodeId/projectionVersion` 等引用。
|
||
|
||
### 8.5 前端 adapter 层
|
||
|
||
建议新增或收口到:
|
||
|
||
- `wolai-frontend/src/lib/mindmap/leptos-mindmap-adapter.ts`
|
||
- `wolai-frontend/src/lib/mindmap/simple-mind-map-bridge.ts`
|
||
- `wolai-frontend/src/lib/mindmap/mindmap-command-diff.ts`
|
||
|
||
实际目录可随现有 runtime 打包方式调整,但职责必须清楚。
|
||
|
||
## 9. 验收标准
|
||
|
||
Phase 6 新验收不再要求 Rust 自绘 scene。
|
||
|
||
必须验证:
|
||
|
||
- 文档页 `/` 插入 mindmap block 后进入 `leptos-tiptap` NodeView。
|
||
- NodeView 挂载 `leptos-mindmap`。
|
||
- 画布由 `simple-mind-map` / KMind-like runtime 渲染真实节点与连线。
|
||
- 默认骨架可见 `KMIND`、`二级节点`、两个 `分支主题` 和 `概要`。
|
||
- 修改节点文本后通过 kernel command 回写。
|
||
- reload 后从 kernel projection 恢复修改结果。
|
||
- smoke 输出结构化 JSON 和截图。
|
||
- 失败时能定位到 projection、adapter init、runtime render、diff、command 或 reload 阶段。
|
||
|
||
明确不通过:
|
||
|
||
- 只看到标题或空容器。
|
||
- 只断言 React mount 点。
|
||
- 只断言 `window.__mindmapInstance`。
|
||
- 只保存整棵 blob 且无 kernel command。
|
||
- 把 `simple-mind-map` runtime data 当成唯一事实源。
|
||
|
||
## 10. 2026-05-10 现实复核:当前实现差距
|
||
|
||
当前代码已打通 `mindmap.simple_mind_map_scene.get`、`mindmap.command.apply`、reload 后文本保留和最小 smoke,但这只能证明 projection / command 的纵切闭环。
|
||
|
||
它还不能证明 `leptos-mindmap` 已完成。
|
||
|
||
已确认的差距:
|
||
|
||
- `leptos-tiptap` NodeView 当前仍在 `tiptap_paragraph.ts` 内手写 DOM。
|
||
- 当前所谓 `simple-mind-map-runtime` 只是一个带 `data-runtime="simple-mind-map"` 的容器,不是 `new MindMap(...)` 创建的真实实例。
|
||
- 节点是手写 `<button data-testid="mindmap-node">`。
|
||
- 连线是手写 `<svg><path>`,坐标来自 adapter projection 的简化布局,因此会出现错位。
|
||
- toolbar、右侧栏和底部栏只是静态 KMind-like chrome,并未真正绑定 `simple-mind-map` runtime 的 active node、history、scale、search、style、theme、layout 等能力。
|
||
- 当前 smoke 断言的是伪 DOM/SVG 可见,而不是 runtime 布局、runtime 连线或真实 `MindMap` instance。
|
||
|
||
因此,当前状态应被标记为:
|
||
|
||
> **Phase 6-A:projection / command 最小闭环通过;Phase 6.1:真实 simple-mind-map runtime cutover 尚未完成。**
|
||
|
||
后续执行必须先完成 Phase 6.1,不能继续把手写 DOM/SVG 画布美化成最终实现。
|
||
|
||
Phase 6.1 的硬性完成判定:
|
||
|
||
- NodeView 只创建 mount element,不再手写节点和连线。
|
||
- browser-side adapter bundle 调用 `createLeptosMindmapAdapter()` 或同等桥接入口。
|
||
- adapter 内部真实执行 `new MindMap({ el, data, layout, theme, viewData, config })`。
|
||
- 节点、连线、概要、外框、关联线由 `simple-mind-map` runtime 负责布局和渲染。
|
||
- smoke 能证明真实 runtime 存在,且不再以 `.mnote-mindmap-node` / 手写 `<path data-testid="mindmap-edge">` 作为成功条件。
|
||
|
||
### 10.1 2026-05-10 Phase 6.1 首轮落地状态
|
||
|
||
本轮已经完成真实 runtime cutover 的首轮落地:
|
||
|
||
- `leptos-tiptap` NodeView 不再手写默认节点和连线,而是挂载 `data-testid="simple-mind-map-runtime"`。
|
||
- NodeView 通过 `createLeptosMindmapAdapter()` 初始化真实 `simple-mind-map` runtime。
|
||
- `simple-mind-map-bridge` 真实执行 `new MindMap(...)`,并注册到 `window.__MNOTE_LEPTOS_MINDMAP_BRIDGES__` 供 smoke 验证。
|
||
- `task166-mindmap-phase6-block-smoke.js` 已改为检查真实 runtime、bridge snapshot、非零节点树和 reload 后文本保留,不再依赖 `.mnote-mindmap-node` / `mindmap-edge`。
|
||
- 最新 smoke 输出:`/mnt/Data1T/mnote/tmp/task166-mindmap-phase6-block-smoke/result.json`,截图包括 `01-after-insert.png`、`02-after-edit.png`、`03-after-reload.png`。
|
||
|
||
仍未视为完成的尾项:
|
||
|
||
- `view_data_change` 还没有持久化为 kernel command;当前只记录 view event,避免拖拽/缩放造成 POST -> remount 循环。
|
||
- toolbar 缩放按钮还没有真正绑定 runtime zoom command。
|
||
- `RichText` 插件暂不默认启用;它会把纯文本节点转换成 HTML 字符串,当前先保护 Rust kernel 文本语义。
|
||
- 视觉上已经是真实 `simple-mind-map` 工作台,但还未达到 `image copy 60.png` / `image copy 70.png` 的完整 KMind 体验对齐。
|
||
|
||
### 10.2 2026-05-11 UI shell reuse 收口状态
|
||
|
||
Phase 6 后续 UI 可用度收口转入:
|
||
|
||
- `/mnt/Data1T/mnote/design/06-mindmap/done/6-mindmap-phase6-leptos-ui-shell-reuse-checklist-v1.md`
|
||
|
||
本轮已经把默认宿主修正为 floating overlay canvas shell,并把 toolbar、sidebar、count、navigator 迁到 Leptos/Rust shell 边界:
|
||
|
||
- `simple-mind-map` runtime 充满块内画布底层。
|
||
- toolbar、右侧栏、统计、navigator、MiniMap 作为 overlay 浮在画布上,不再挤压 runtime。
|
||
- TypeScript NodeView 保留为 Tiptap NodeView、runtime bridge、事件转发和 context menu 过渡层,不再作为长期 UI shell 宿主。
|
||
- `simple-mind-map-bridge` 默认尊重 `fit:true`,初始视口能看到完整示例导图。
|
||
- `task166-mindmap-phase6-block-smoke.js` 已覆盖 toolbar/sidebar/navigator/context menu、command bridge、compat patch、reload 与截图证据。
|
||
- 2026-05-11 最新截图:`/mnt/Data1T/mnote/tmp/task166-mindmap-phase6-block-smoke/01-after-insert-floating-overlay.png`、`04-after-reload.png`。
|
||
|
||
剩余视觉差异不改变 kernel-first 主合同:默认主题色、图标体系、工具栏分组密度和高级面板内容仍需继续对齐 KMind/lx-doc。
|
||
|
||
## 11. 后续 Rust-native 路线
|
||
|
||
Rust 重写仍然是长期可选路线,但应独立成后续阶段。
|
||
|
||
后续可以启动:
|
||
|
||
- Rust mindmap engine candidate spike。
|
||
- 布局 crate 评估:`diagramma-layout`、`dagre/dugong`、`manatee`。
|
||
- Headless Rust layout engine。
|
||
- Rust scene renderer。
|
||
- Rust hit-test / selection / history。
|
||
|
||
这些不再阻塞 Phase 6 的可用编辑器交付。
|
||
|
||
## 12. 迁移原则
|
||
|
||
- 先保证可用编辑体验,再逐步提升语义。
|
||
- adapter 可以兼容 `simple-mind-map` 字段,但字段所有权要写清楚。
|
||
- 每个从 blob 中提升出来的语义,都要有 kernel command 和 projection 表达。
|
||
- 不把 `lx-doc/mind-map` 的 Vue2 应用结构直接搬入 mnote。
|
||
- 可以参考 KMind 的 UI 与行为,但不要复制它的思源插件耦合。
|
||
|
||
## 13. 当前执行口径
|
||
|
||
当前 Phase 6 的一句话口径:
|
||
|
||
> **用 leptos-mindmap 把 Rust kernel projection 接到 KMind-like 导图编辑器上,先得到可用体验,同时保持 kernel 是事实源。**
|