Files
mnote/design/06-mindmap/process/6-mindmap-leptos-adapter-reference-notes-v1.md
T
lix-2026 1956a8a21a chore: align mvp design governance
- 统一 local-first MVP 后阶段架构口径,补充 process 执行总序和 Reasonix 协作记录

- 归档已完成的 design checklist,标注参考型 process,更新 AGENTS/REASONIX/架构文档

- 补充文件树/主编辑器下载与上下文菜单相关实现、bug 记录和 smoke 脚本

验证:git diff --check;codegraph sync .;cargo test -p mnote-web;node --check scripts/task476-filetree-editor-context-menu-download-smoke.js
2026-05-21 09:04:13 +08:00

225 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 6 [process] Mindmap leptos adapter reference notes v1
> 日期:2026-05-10
>
> 当前状态:`process-reference`。本文是 adapter/reference 审计笔记,不作为当前执行 checklistmindmap 实施状态以 `6-mindmap-phase6-leptos-ui-shell-reuse-checklist-v1` 和 `done/6-mindmap-phase6-kmind-parity-detail-checklist-v1.md` 为准。
>
> 目的:记录 `lx-doc/mind-map` 与 KMind 插件审计结果,为 Phase 6 `leptos-mindmap` 的 simple-mind-map bridge、command bridge 和第一阶段 UI 复刻定界。
## 1. 参考入口
- `design/05-editor-mainline/reference-code/lx-doc/mind-map/src/pages/Edit/components/Edit.vue`
- 注册 `simple-mind-map` 插件。
- 初始化 `new MindMap({ el, data, layout, theme, themeConfig, viewData, config })`
- 承接 `execCommand`、关联线、图片上传、富文本、滚动条等 runtime 行为。
- `design/05-editor-mainline/reference-code/lx-doc/mind-map/src/pages/Edit/components/ToolbarNodeBtnList.vue`
- 提供节点编辑工具栏命令和禁用状态参考。
- `design/05-editor-mainline/reference-code/lx-doc/mind-map/src/pages/Edit/components/SidebarTrigger.vue`
- 提供右侧栏触发器参考。
- `design/05-editor-mainline/reference-code/lx-doc/mind-map/src/config/zh.js`
- `sidebarTriggerList` 定义 `nodeStyle/baseStyle/theme/structure/outline/shortcutKey`
- `design/05-editor-mainline/reference-code/lx-doc/mind-map/src/pages/Edit/components/NavigatorToolbar.vue`
- 提供底部导航工具参考。
- `design/05-editor-mainline/reference-code/kmind-plugin/README.md`
- 提供 KMind 的思源耦合能力与延期边界参考。
## 2. 本轮需要注册的插件
第一阶段必须注册:
- `Drag`:画布拖拽、节点拖拽编辑的基础能力。
- `KeyboardNavigation`:方向键、基础键盘导航。
- `Export`:导出入口的基础能力,先保留 UI 与 runtime 能力,不把导出结果当 kernel truth。
- `Select`:框选、多选与 active node 状态。
- `AssociativeLine`:关联线渲染与创建入口。
- `Search`:底部搜索入口需要。
- `OuterFrame`:外框按钮与已有 KMind/lx-doc 视觉能力对齐。
第一阶段建议按能力开关注册:
- `RichText`:仅在节点富文本开启时加载;富文本 HTML 进入 `compatPayload`,同时保留纯文本到 kernel node text。
- `Scrollbar`:仅在配置开启时加载,避免小画布重复滚动 UI。
- `MiniMap`:底部按钮可以延期显示,但 bridge 应保留插件注册能力。
- `Painter`:格式刷属于 toolbar 第一阶段按钮,样式变更先走 `compatPayload.patch`
- `Formula`:公式先作为节点扩展字段进入 `compatPayload`
第一阶段不作为必须注册:
- `ExportPDF` / `ExportXMind`:导出格式能力可保留在独立页或后续任务,不阻塞 block 内编辑。
- `Watermark`:不属于当前 mnote 主体验。
- `TouchEvent`:移动端可用性后续补齐。
- `RainbowLines` / `Demonstrate` / `HandDrawnLikeStyle` / `Notation`:作为高级视觉或演示能力延期。
- `NodeImgAdjust`:图片字段先兼容保存,图片尺寸调整后续再语义化。
## 3. Toolbar 到 kernel command 的映射
直接发 kernel command
- `INSERT_CHILD_NODE` -> `mindmap.node.insert_child`
- `INSERT_NODE` -> `mindmap.node.insert_sibling_after`
- `REMOVE_NODE` -> `mindmap.node.delete`
- 节点文本提交 -> `mindmap.node.update_text`
- 节点拖拽换父或重排 -> `mindmap.node.move`
- 结构切换 -> `mindmap.layout.set`
- 主题切换 -> `mindmap.theme.set`
- 缩放、平移、只读状态以外的 view 变化 -> `mindmap.view.patch`
需要 bridge 或 diff 二次确认:
- `BACK` / `FORWARD`:第一阶段作为 runtime history 操作;后续若 kernel history 接管,再提升为 kernel undo/redo。
- `ADD_GENERALIZATION`:映射到 `mindmap.summary.set`,当前 Rust DTO 最小集未完全覆盖时先进入 `compatPayload.patch` 并记录字段路径。
- `createAssociativeLine`:映射到 `mindmap.associative_line.upsert`,当前 Rust DTO 最小集未完全覆盖时先进入 `compatPayload.patch`
- `ADD_OUTER_FRAME`:第一阶段进入 `compatPayload.patch`,后续提升为 outer frame kernel 语义。
第一阶段作为 compat 字段处理:
- 图片、图标、标签、超链接、备注、公式、附件、标记、格式刷产生的节点样式。
- 这些入口可以出现在 UI 中,但保存路径必须经过 command bridge;不可直接把整棵 runtime data 保存为 canonical truth。
## 4. 右侧栏第一阶段保留项
第一阶段保留:
- `nodeStyle`:节点样式。可编辑项先进入节点 `compatPayload`,基础文本仍回写 kernel。
- `baseStyle`:导图样式。概要、关联线、间距等暂未语义化字段进入 `compatPayload`
- `theme`:主题切换,能识别的主题名走 `mindmap.theme.set`
- `structure`:结构切换,走 `mindmap.layout.set`
- `outline`:大纲只作为 projection 派生视图,不创建第二套树真相。
第一阶段不放入右侧栏:
- `shortcutKey`:快捷键说明可以后续做文档或设置面板,不阻塞编辑器主链。
- KMind 全局配置、主题设计器、主题分享:后续独立配置任务处理。
## 5. 底部工具第一阶段保留项
第一阶段保留:
- 节点数 / 字数:从 adapter projection 或 runtime 派生,只读展示。
- 回根节点:调用 `mindMap.renderer.setRootNodeCenter()`,同时可记录 view patch。
- 搜索:调用 `Search` 插件或事件入口。
- 缩放百分比:监听 `scale`,通过 `view_data_change` / `mindmap.view.patch` 保存必要 view state。
- 全屏或只读:block 内优先保留只读切换;独立页可提供全屏。
第一阶段可延期:
- 鼠标行为高级配置。
- MiniMap 展示按钮。
- 暗色主题切换。
- 源码编辑。
- 演示模式。
- 多语言切换和帮助链接。
## 6. 必须进入 compatPayload 的字段
节点级字段:
- `image``imageTitle``imageSize`
- `icon`
- `tag`
- `hyperlink``hyperlinkTitle`
- `note`
- `richText`
- `generalization` 中尚未进入 kernel summary DTO 的私有样式字段
- `formula`
- `attachment`
- `notation`
- 节点自定义样式、内外边距、背景、字体、边框、图片调整状态
- `customLeft``customTop` 等自由布局坐标
导图级字段:
- `theme.config` 中无法映射到 kernel theme 的细项。
- `config` 中 runtime 私有行为配置,如鼠标行为、粘贴拆分、图片上传默认值。
- `view` 中无法映射到稳定 view DTO 的细项。
- `outerFrame`、高级关联线样式、概要样式。
- 插件私有状态,如 `MiniMap``Painter``Demonstrate``Notation`
保存约束:
- `compatPayload` 只能承接暂未语义化字段。
- 每次 `compatPayload.patch` 必须记录字段路径、来源事件和 kernel revision。
- 不允许把 `root` 整棵 runtime data 作为唯一成功保存结果。
## 7. KMind 专有能力延期
延期到 Phase 6 之后:
- 多根节点。
- MOC 模式。
- 文档树导图。
- 思源块拖拽、渲染、悬浮预览。
- 节点镜像块与导图镜像块。
- 思源 PDF 标注跳转与移除 PDF 关联。
- 思源全局搜索对接。
- 子文档快捷打开位置。
- KMind 全局配置、自动禅模式、默认主题与默认结构。
- 主题设计器、主题分享。
- 历史版本、固定历史版本、自动历史清理。
- Freemind / XMind 全量导入导出。
- 右键菜单中的思源专有导出、复制镜像块、复制节点为图片等高级项。
这些能力可以影响长期设计,但不能改变 Phase 6 的主合同:`simple-mind-map` 是 editor adapterRust kernel projection / command 才是事实源。
## 8. 历史自研 React UI 壳复用清单
> 2026-05-11 复核:历史 React UI 壳比 `/mnt/Data1T/mnote-rust/components/editor/blocks` 的简化宿主完整得多。下一阶段迁移应优先抽取历史 React 组件族的配置和 action 语义,不应继续在 NodeView 内手写按钮。
>
> 2026-05-11 执行记录:上述能力清单已转为 `mindmap-ui-schema.ts` / `mindmap-action-map.ts` / Leptos/Rust shell 的第一阶段输入;旧 React 组件族已补 legacy/reference/compat 注释,默认 3000 文档页不运行旧 React mindmap 主链。
### 8.1 Toolbar
| 分组 / action | 旧来源 | 旧 runtime 调用或意图 | active node | 第一阶段 |
|---|---|---|---|---|
| 工具栏元信息 | `wolai-frontend/src/components/editor/blocks/mindmapToolbarConfig.ts``NodeToolbarKey``FileToolbarKey``nodeToolbarOrder``fileToolbarOrder``nodeToolbarMeta``fileToolbarMeta` | 定义按钮 key、label、iconClass 和顺序 | 视 action | schema-only |
| toolbar UI 分组 | `MindmapToolbar.tsx``nodeHandlers``fileHandlers` | 左侧节点操作、右侧文件/导入/导出;能力由 props 注入 | 视 action | must |
| undo / redo | `MindmapBlock.tsx``handleUndo``handleRedo` | `mindmap.execCommand("BACK" / "FORWARD")` | 否 | must |
| 同级 / 子节点 | `MindmapBlock.tsx``handleSibling``handleChild` | `SET_NODE_ACTIVE``INSERT_NODE` / `INSERT_CHILD_NODE`;无 active 时 `ensureActiveBefore` 选 root | 是 | must |
| 删除 / 概要 / 关联线 / 外框 | `MindmapBlock.tsx``handleDelete``handleSummary``handleAssociativeLine``handleOuterFrame` | `REMOVE_NODE``ADD_GENERALIZATION``ADD_ASSOCIATIVE_LINE``ADD_OUTER_FRAME` | 是 | must |
| 图片 | `MindmapBlock.tsx``handleImage``handleImageConfirm` | 输入/上传图片后 `SET_NODE_IMAGE` + `SET_NODE_STYLES imgPlacement` | 是 | must |
| 超链接 / 标签 / 备注 / 附件 | `MindmapBlock.tsx``handleLink``handleTag``handleNoteConfirm``handleAttachment` | `SET_NODE_HYPERLINK``SET_NODE_TAG``SET_NODE_NOTE``SET_NODE_ATTACHMENT` | 是 | must |
| 图标 / 公式 | `MindmapBlock.tsx``handleIcon``handleFormula` | 打开 sidebar `icons` / `formula` | 是 | schema-only / defer |
| 格式刷 | `MindmapBlock.tsx``handlePainter` | `mindmap.painter.startPainter()` | 否,依赖 Painter 插件 | defer |
| 导入 / 新建 / 本地恢复 / 导出 / 删除导图 | `MindmapBlock.tsx``handleImport``handleDeleteMindmap` | `.json/.smm/.xmind/.mmap/.md` 导入;`setData``clearHistory``persistData`;导出 JSON/PNG/SVG/PDF/MD/TXT/XMind;删除走 `/api/mindmap/{docId}/{mindmapId}` | 否 | must |
### 8.2 Sidebar
| panel | 旧来源 | 旧 runtime 调用或意图 | active node | 第一阶段 |
|---|---|---|---|---|
| trigger 配置 | `mindmapSidebarConfig.ts``SidebarPanel``sidebarTriggers` | `style/base/theme/structure/outline/settings/icons/formula/note/ai` | 视 panel | schema-only |
| 触发条 UI | `MindmapSidebarTrigger.tsx``MindmapSidebarTrigger` | 右侧竖条,`onSelect(isActive ? null : target)` | 否 | must |
| panel 路由 | `MindmapSidebar.tsx``MindmapSidebar` switch | `activeTab` 分发到各 panel | 视 panel | must |
| 节点样式 | `MindmapSidebar.tsx``StylePanel` | `node.getStyle(prop,false)` 读取,`node.setStyle(prop,value)` 写入文字、边框、填充、连线样式 | 是 | must |
| 基础样式 | `MindmapSidebar.tsx``BaseStylePanel` | `mindmap.getThemeConfig` / `mindmap.setThemeConfig` | 否 | must |
| 主题 | `MindmapSidebar.tsx``ThemePanel` | `mindmap.setTheme(theme)` | 否 | must |
| 结构 | `MindmapSidebar.tsx``StructurePanel` | `mindmap.setLayout(layout)` | 否 | must |
| 图标/贴纸 | `MindmapSidebar.tsx``IconPanel` | 动态加载 simple-mind-map icons`node.setIcon``node.setImage` | 是 | must |
| 大纲 | `MindmapSidebar.tsx``OutlinePanel` | 从 `mindmap.renderer.renderTree._node` 遍历;点击后设置 active 并 `setRootNodeCenter` | 否 | must |
| 设置 | `MindmapSidebar.tsx``SettingsPanel` | `mindmap.updateConfig``mindmap.reRender``watermark.updateWatermark` | 否 | schema-only |
| 备注 | `MindmapSidebar.tsx``NotePanel` | 读取 active `note`,保存/清除走 `SET_NODE_NOTE` | 是 | must |
| 公式 / AI | `FormulaPanel``MindmapAiAgentPanel` | `INSERT_FORMULA` 或 AI panel | 是 / 部分 | defer |
### 8.3 Navigator / MiniMap / Count
| 能力 | 旧来源 | 旧 runtime 调用或意图 | active node | 第一阶段 |
|---|---|---|---|---|
| 宿主挂载 | `MindmapBlock.tsx` 全屏和内嵌 stage | 同时挂 `MindmapNavigator``MindmapCount``MindmapMiniMap``MindmapContextMenu` | 否 | must |
| 缩放 / 居中 / 只读 / 全屏 / 小地图按钮 | `MindmapNavigator.tsx``MindmapNavigator` | `view.enlarge``view.narrow``view.setScale``renderer.setRootNodeCenter``setMode("readonly"/"edit")``onToggleMiniMap``toggleFullscreen` | 否 | must |
| MiniMap | `MindmapMiniMap.tsx``MindmapMiniMap` | `mindmap.miniMap.calculationMiniMap`;监听 `data_change/view_data_change/node_tree_render_end/mini_map_view_box_position_change` | 否 | must |
| Count | `MindmapCount.tsx``MindmapCount` | `mindmap.getData()` + `data_change`,递归统计节点数和去 HTML 文本长度 | 否 | must |
### 8.4 Context Menu
| action / 组 | 旧来源 | 旧 runtime 调用或意图 | active node | 第一阶段 |
|---|---|---|---|---|
| 菜单项配置 | `MindmapContextMenu.tsx``NODE_MENU_ITEMS` | 插入、移动、展开、删除、复制剪切粘贴、移除属性、导出节点、AI 续写 | 是 | schema-only |
| 禁用规则 | `MindmapContextMenu.tsx``isItemDisabled` | root/generalization 禁用部分插入、复制剪切、移动;首尾节点禁用上移/下移 | 是 | must |
| 捕获右键目标 | `MindmapContextMenu.tsx` contextmenu listener | 监听 `mindmap-canvas`,目标取 `renderer.activeNodeList[0] ?? lastActiveNodeList[0]` | 是 | must |
| 插入/移动/删除等默认命令 | `MindmapContextMenu.tsx``executeCommand` default | 多数 action 直接 `mindmap.execCommand(key)` | 是 | must |
| 复制/剪切/粘贴 | `MindmapContextMenu.tsx` | `mindmap.renderer.copy/cut/paste` | 是 | must |
| 移除超链接/备注 | `MindmapContextMenu.tsx` | `targetNode.setHyperlink("", "")``targetNode.setNote("")` | 是 | must |
| 展开/收起下级 | `MindmapContextMenu.tsx` | `UNEXPAND_ALL``EXPAND_ALL` | 是 | must |
| 导出当前节点 PNG / AI 续写 | `MindmapContextMenu.tsx` | `doExport.export("png", ..., targetNode)``mindmap-ai-continue` custom event | 是 | defer |
`/mnt/Data1T/mnote-rust/components/editor/blocks` 只保留基础 toolbar、theme/structure/view sidebar 和简化 runtime 宿主,可作为 adapter 最小结构参考,但不能替代当前仓旧 React UI 壳的完整能力清单。