# 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 是事实源。**
