Files
mnote/design/06-mindmap/done/6-mindmap-phase6-kmind-parity-detail-checklist-v1.md
T
lix-2026 96e03645f7 chore: 收口 review 执行清单与 runtime 验证
- 补齐 design/10-review 执行清单、验收标准与相关设计治理记录

- 迁移已完成的 tree、mindmap、runtime fallback、AI kernel 等设计和缺陷条目

- 推进 Rust Web runtime、tree/sidebar、page aggregate、mindmap 与 OnlyOffice 路由侧验证支撑

- 增加 task177-task180 smoke/audit 脚本及前端相关测试覆盖
2026-05-14 05:52:08 +08:00

31 KiB
Raw Blame History

6 [done] Mindmap Phase 6 KMind/simple-mind-map Parity Detail Checklist v1

日期:2026-05-11

当前阶段:Phase 6 leptos-mindmap 已完成真实 simple-mind-map runtime + Leptos/Rust floating overlay shell 的第一轮收口;本 checklist 是后续细节优化入口。

执行规则:每完成一个节点,必须基于代码、测试、截图或人工复核证据勾选对应项。未验证的实现不得勾选。

0. 目标与结论

**目标:**把当前 mindmap shell 从“可运行的 Leptos/Rust 浮动 UI 壳”推进到接近 KMind 与 simple-mind-map 官方编辑器的工作台体验。

当前不需要改变 Phase 6 的大方向:

Rust kernel truth
  -> mindmap.simple_mind_map_scene.v1
  -> leptos-tiptap NodeView
  -> simple-mind-map runtime
  -> Leptos/Rust floating UI shell
  -> command bridge / compatPayload.patch

本轮要修正的是 UI 与交互细节,而不是回退到以下路线:

  • 不直接嵌入完整 Vue lx-doc/mind-map 应用。
  • 不恢复旧 React MindmapBlock.tsx 为 3000 文档页默认主链。
  • 不启动 Rust-native renderer 重写。
  • 不把 simple-mind-map runtime data 保存为 canonical truth。
  • 不把 TypeScript NodeView 扩写成长期 toolbar/sidebar/navigator UI 框架;长期 UI shell 继续归到 Leptos/Rust。

1. 本次取证结论

1.1 当前实现差距

已对照:

  • 当前实现截图:/mnt/Data1T/mnote/tmp/image copy 80.png
  • KMind 目标截图:/mnt/Data1T/mnote/tmp/image copy 81.png
  • 隐藏 chrome 目标截图:/mnt/Data1T/mnote/tmp/image copy 82.png
  • 右侧详细设置栏目标截图:/mnt/Data1T/mnote/tmp/image copy 83.png

当前主要差距:

  • Toolbar 当前视觉上仍是三行:rust/spikes/leptos-tiptap-spike/src/lib.rs.mnote-mindmap-command-toolbar.mnote-mindmap-toolbar-primary 都允许 flex-wrap: wrap,并且每个分组都带文字分组名,导致不可能稳定保持 KMind/simple-mind-map 的单行工具组。
  • Toolbar 当前没有真正的 更多 溢出模型。lx-doc Toolbar.vue 通过测量工具栏宽度,把可见按钮放入 horizontalList,把溢出按钮放入 verticalList,这比单纯 CSS 横向滚动更接近目标。
  • 当前没有完整全屏状态。lx-doc Fullscreen.vue 同时提供“全屏查看”和“全屏编辑”,并在 fullscreen change 后调用 mindMap.resize()
  • 当前没有“鼠标移出后隐藏 chrome,鼠标移入不自动恢复,点击才恢复”的状态机。KMind changelog 明确提到 floating toolbar 会在特定场景自动隐藏,并推荐结合 Zen mode 获得更大的编辑视图。
  • 当前右侧栏只是窄 tab + 148px 简化 bodyKMind/simple-mind-map 是“右侧触发条 + 可隐藏把手 + 约 300px 详细抽屉”,结构面板中有布局卡片,设置项密度明显更高。
  • 当前 navigator 是文字按钮和常驻搜索输入框;目标是底部右侧图标工具条,搜索按需展开,全屏、小地图、只读、缩放、鼠标行为、设置等是同一条浮动控件。

1.2 参考实现证据

  • design/05-editor-mainline/reference-code/lx-doc/mind-map/src/pages/Edit/components/Toolbar.vue

    • computeToolbarShow() 根据宽度计算单行 horizontalListverticalList
    • showMoreBtn 显示 更多 popover。
  • design/05-editor-mainline/reference-code/lx-doc/mind-map/src/pages/Edit/components/ToolbarNodeBtnList.vue

    • 记录 toolbar action、禁用状态、active node 规则和 runtime command。
  • design/05-editor-mainline/reference-code/lx-doc/mind-map/src/pages/Edit/components/SidebarTrigger.vue

    • 右侧触发条有 show 状态和 toggleShowBtn 隐藏把手。
    • 激活 panel 后容器从 right: 0 推到 right: 305px
  • design/05-editor-mainline/reference-code/lx-doc/mind-map/src/pages/Edit/components/NavigatorToolbar.vue

    • 底部 navigator 是图标工具条,不是常驻表单。
    • 包含回根、搜索、鼠标行为、小地图、只读、全屏、缩放、暗色、源码、演示等入口。
  • design/05-editor-mainline/reference-code/lx-doc/mind-map/src/pages/Edit/components/Fullscreen.vue

    • 区分 fullscreenShowfullscreenEdit
  • 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/kmind-plugin/README_en_US.md

    • 明确提到 desktop floating toolbar、Zen mode、自动隐藏 UI、全局配置。
  • 已完成当前实现、截图和参考代码的首轮取证。

2. 文件职责边界

2.1 主要运行代码

  • rust/spikes/leptos-tiptap-spike/src/lib.rs
    • 当前 Leptos/Rust shell、CSS、mount/unmount、toolbar/sidebar/navigator 渲染集中在此。
    • 下一阶段应优先把 mindmap shell 拆出到专门模块,避免 lib.rs 继续膨胀。
  • wolai-frontend/src/lib/mindmap/mindmap-ui-schema.ts
    • 当前 action、toolbar group、sidebar panel、navigator item、context menu 的 schema 来源。
    • 下一阶段需要扩展为可表达单行 toolbar、溢出、全屏、chrome visibility、详细 panel controls 的中立 schema。
  • wolai-frontend/src/lib/mindmap/mindmap-action-map.ts
    • UI action 到 runtime/local/kernel/compat 的映射。
    • 下一阶段需要补全 fullscreentoggleChrometoggleSidebartoggleSearchsetScalesetMouseBehavior 等 local view action。
  • wolai-frontend/src/lib/mindmap/mindmap-ui-state.ts
    • 当前只覆盖 active node、readonly、capability、disabled state。
    • 下一阶段需要补 chrome visibility、fullscreen、sidebar open、search open、toolbar overflow、navigator active state。
  • wolai-frontend/src/lib/mindmap/simple-mind-map-bridge.ts
    • 当前 runtime bridge。
    • 下一阶段需要确保 fullscreen/resize、search、minimap、scale input、sidebar style 写入都能通过 bridge 安全触达 runtime。
  • wolai-frontend/src/lib/mindmap/leptos-mindmap-adapter.ts
    • projection/command endpoint 与 adapter 初始化。
    • 下一阶段继续保持薄桥接,不承载 UI 细节。
  • scripts/task166-mindmap-phase6-block-smoke.js
    • 当前 Phase 6 smoke。
    • 下一阶段建议新增或扩展为 KMind parity smoke,保存对齐截图证据。

2.2 建议新增/拆分文件

  • Create: rust/spikes/leptos-tiptap-spike/src/mindmap_shell.rs
    • Leptos/Rust shell 组件、状态结构、事件派发。
  • Create: rust/spikes/leptos-tiptap-spike/src/mindmap_shell_style.rs 或保留同模块内常量
    • 如果现有 CSS 继续增长,单独收口 mindmap shell 样式字符串。
  • Create: scripts/task167-mindmap-kmind-parity-smoke.js
    • 专门覆盖 toolbar 单行、全屏、chrome hide、右侧抽屉、截图对比。
  • Output: tmp/task167-mindmap-kmind-parity-smoke/*.png
    • 保存每个视觉验收节点截图。

3. 状态模型先行

后续 UI 不应继续靠 CSS 和零散按钮状态拼凑。先把 shell state 定义清楚。

Task 1: 扩展 Mindmap Shell State Contract

Files:

  • Modify: wolai-frontend/src/lib/mindmap/mindmap-ui-schema.ts

  • Modify: wolai-frontend/src/lib/mindmap/mindmap-ui-state.ts

  • Modify: wolai-frontend/src/lib/mindmap/mindmap-ui-state.test.ts

  • Modify/Create: rust/spikes/leptos-tiptap-spike/src/mindmap_shell.rs

  • 定义 MindmapChromeVisibilityState

    • visible
    • hiddenByPointerLeave
    • hiddenByToggle
    • hiddenByFullscreen
  • 定义 MindmapToolbarOverflowState

    • availableWidth
    • visibleActionIds
    • overflowActionIds
    • moreOpen
  • 定义 MindmapFullscreenState

    • mode: "none" | "canvas" | "page"
    • isFullscreen
    • target: "mindmap-root" | "document-body"
  • 定义 MindmapSidebarState

    • triggerVisible
    • panelOpen
    • activePanelId
    • drawerWidth
    • collapsedByToggle
  • 定义 MindmapNavigatorState

    • searchOpen
    • minimapOpen
    • readonly
    • zoomPercent
    • mouseBehavior
  • TS 单测覆盖:鼠标移出后为 hiddenByPointerLeave;再次 mouseenter 不恢复;点击画布或点击显式恢复按钮才回到 visible

  • TS 单测覆盖:sidebar toggle 隐藏触发条后,不会清空 activePanelId;再次显示后保留最近面板。

  • Rust/Leptos shell options 能接收上述 state,并向 DOM 输出稳定 data-* 标记,供 smoke 断言。

  • 验证:cd /mnt/Data1T/mnote/wolai-frontend && pnpm test -- mindmap-ui-state

    • 2026-05-11 通过:mindmap-ui-state.test.ts 6 项通过;同时复核 npm run typechecknpm run buildcargo checknode scripts/build-leptos-tiptap-island.js 均通过。

4. 单行 Toolbar 与更多菜单

目标:对齐 /mnt/Data1T/mnote/tmp/image copy 81.png 与 lx-doc Toolbar.vue,主 toolbar 只占一行;溢出进入 更多 菜单;不要回到当前 /mnt/Data1T/mnote/tmp/image copy 80.png 的三行状态。

Task 2: 设计单行 Toolbar Schema

Files:

  • Modify: wolai-frontend/src/lib/mindmap/mindmap-ui-schema.ts

  • Modify: wolai-frontend/src/lib/mindmap/mindmap-ui-schema.test.ts

  • 为 toolbar action 增加 iconKeyshortLabellongLabelpriorityoverflowGroup

  • 移除默认渲染中强依赖的分组文字标签;分组仅作为视觉分隔线和溢出归类,不占据单行宽度。

  • 把 import/export/historyRecord 规划为右侧独立 toolbar cluster,避免和节点编辑按钮互相挤压。

  • 增加 more 虚拟 action,只有存在 overflowActionIds 时显示。

  • 单测断言默认 toolbar 主按钮顺序与 lx-doc/KMind 对齐:undo、redo、editNode、insertSiblingAfter、deleteNode、insertChild、tag、hyperlink、note、image、icon、summary、associativeLine、formula、more。

  • 单测断言 action id 不重复,且每个可见 action 都能映射到 action map。

  • 验证:cd /mnt/Data1T/mnote/wolai-frontend && pnpm test -- mindmap-ui-schema mindmap-action-map

    • 2026-05-11 通过:mindmap-ui-schema.test.ts 11 项通过;同轮 mindmap-action-map.test.ts 4 项通过。

Task 3: 实现 Leptos 单行 Toolbar Layout

Files:

  • Modify/Create: rust/spikes/leptos-tiptap-spike/src/mindmap_shell.rs

  • Modify: rust/spikes/leptos-tiptap-spike/src/lib.rs

  • Modify: scripts/task167-mindmap-kmind-parity-smoke.js

  • Toolbar CSS 改为单行:flex-wrap: nowrap,固定按钮宽高,禁用 group 内换行。

  • 顶部 toolbar 分为左/中/右 cluster:主编辑工具、导入导出/历史、更多。

  • ResizeObserver 或等价测量机制计算可见按钮与溢出按钮;窄宽度下不允许撑成第二行。

  • 更多 点击后打开浮层菜单,菜单内纵向列出溢出 action。

  • 更多 菜单失焦、点击菜单项或按 Escape 后关闭。

  • 按钮视觉从“英文 icon 名 + 中文文字”修正为图标主导、短文字辅助;不得把 palette/sliders/layout 这类内部 icon key 作为可见正文。

  • Smoke 断言 toolbar 高度不超过 72pxtoolbarRows <= 1 或等价 DOM 断言通过。

  • Screenshottmp/task167-mindmap-kmind-parity-smoke/01-toolbar-single-row.png,肉眼能看到 toolbar 单行而不是三行。

  • 验证:cd /mnt/Data1T/mnote/design/05-editor-mainline/reference-code/leptos-tiptap/tiptap && npm run typecheck && npm run build

  • 验证:cd /mnt/Data1T/mnote/wolai-frontend && node scripts/build-leptos-tiptap-island.js

  • 验证:cd /mnt/Data1T/mnote && node scripts/task167-mindmap-kmind-parity-smoke.js --stage toolbar

    • 2026-05-11 通过:桌面 toolbar height=56toolbarRows=1;窄宽度 toolbar height=56toolbarRows=1,并产生 overflowActionsEscape 后 moreOpen=falsetoolbarRows=1

5. 全屏与大画布模式

目标:至少提供 KMind/simple-mind-map 级别的全屏按钮与状态。优先做 block/canvas fullscreen,随后再补 page fullscreen。

Task 4: 增加 Fullscreen Action Contract

Files:

  • Modify: wolai-frontend/src/lib/mindmap/mindmap-ui-schema.ts

  • Modify: wolai-frontend/src/lib/mindmap/mindmap-action-map.ts

  • Modify: wolai-frontend/src/lib/mindmap/mindmap-ui-state.ts

  • Modify: wolai-frontend/src/lib/mindmap/mindmap-action-map.test.ts

  • 新增 actionfullscreenCanvas,对应 lx-doc 的“全屏查看”。

  • 新增 actionfullscreenPage,对应 lx-doc 的“全屏编辑”,第一阶段先作为 schema/action contract 保留。

  • 新增 actionexitFullscreen

  • fullscreenCanvas/fullscreenPage/exitFullscreen 均标记为 localView,不得产生 kernel command。

  • Fullscreen API 不可用时,action disabled,并在 UI 有稳定 data-disabled-reason="fullscreen-unavailable"

  • 单测覆盖 fullscreen action 不依赖 active nodereadonly 下仍可使用。

  • 验证:cd /mnt/Data1T/mnote/wolai-frontend && pnpm test -- mindmap-action-map mindmap-ui-state

    • 2026-05-11 通过:mindmap-action-map.test.ts 新增 fullscreen localView 合同与 readonly 断言;mindmap-ui-state.test.ts 断言 readonly/无 active node 下 fullscreen 仍可用。

Task 5: 实现全屏按钮与 resize

Files:

  • Modify/Create: rust/spikes/leptos-tiptap-spike/src/mindmap_shell.rs

  • Modify: rust/spikes/leptos-tiptap-spike/src/lib.rs

  • Modify: wolai-frontend/src/lib/mindmap/simple-mind-map-bridge.ts

  • Modify: scripts/task167-mindmap-kmind-parity-smoke.js

  • 底部 navigator 增加全屏图标按钮,默认显示 canvas fullscreen。

  • 点击后对 data-testid="mnote-mindmap-editor-root" 或等价 canvas root 调用 Fullscreen API。

  • 监听 fullscreenchange,退出时同步 shell state。

  • fullscreen change 后调用 mindMap.resize() 或 bridge 暴露的 resize 方法,并居中或保持当前 view transform。

  • 全屏时保持 toolbar/sidebar/navigator 浮动在画布上;不出现文档页滚动条错位。

  • 全屏模式下 Escape 退出后,toolbar/sidebar/navigator 状态恢复到进入前状态。

  • Smoke 断言点击全屏后 document.fullscreenElement 为 mindmap root 或其包含节点。

  • Screenshottmp/task167-mindmap-kmind-parity-smoke/02-fullscreen-canvas.png

  • 验证:cd /mnt/Data1T/mnote && node scripts/task167-mindmap-kmind-parity-smoke.js --stage fullscreen

    • 2026-05-11 通过:fullscreenElementIsRoot=trueshellFullscreenActive=trueEscape 退出后 document.fullscreenElement === nullshellFullscreenActive=false

6. 鼠标移出隐藏 Chrome,点击恢复

目标:对齐 /mnt/Data1T/mnote/tmp/image copy 82.png。鼠标移出后隐藏 toolbar/sidebar/navigator 等菜单;鼠标重新移入不自动恢复;用户点击画布或显式按钮才恢复。

Task 6: 实现 Chrome Visibility State Machine

Files:

  • Modify/Create: rust/spikes/leptos-tiptap-spike/src/mindmap_shell.rs

  • Modify: rust/spikes/leptos-tiptap-spike/src/lib.rs

  • Modify: scripts/task167-mindmap-kmind-parity-smoke.js

  • 在 mindmap root 上监听 pointer enter/leave/click,不依赖 document 全局 hover。

  • pointer leave root 后进入 hiddenByPointerLeave,隐藏 toolbar、sidebar drawer、sidebar trigger、navigator、minimapcount 可保留或按 KMind 目标隐藏,需在 smoke 固定判定。

  • pointer enter root 不改变 hiddenByPointerLeave

  • 点击画布空白区或节点后恢复 visible

  • 点击恢复后不触发误插入、不改变 active node,除非点击目标本身就是节点选择。

  • 打开 更多 菜单或右侧 drawer 时,pointer leave 先关闭弹层,再隐藏 chrome,避免残留孤立菜单。

  • fullscreen 模式与 hidden state 组合时,退出 fullscreen 不强制显示 chrome,除非进入 fullscreen 前是 visible。

  • Smoke 操作:移动鼠标到 root 外 -> 断言 toolbar/sidebar/navigator hidden;移动回 root -> 仍 hidden;点击 root -> visible。

  • Screenshottmp/task167-mindmap-kmind-parity-smoke/03-chrome-hidden-after-leave.png

  • Screenshottmp/task167-mindmap-kmind-parity-smoke/04-chrome-restored-after-click.png

  • 验证:cd /mnt/Data1T/mnote && node scripts/task167-mindmap-kmind-parity-smoke.js --stage chrome-hide

    • 2026-05-11 通过:sceneChromeVisibility/shellChromeVisibilityvisible -> hiddenByPointerLeave -> hiddenByPointerLeave -> visibletoolbar/sidebar/navigator 与截图状态一致。
    • 2026-05-11 补充通过:fullscreen stage 已覆盖 visible -> enter fullscreen -> exit -> visiblehiddenByPointerLeave -> enter fullscreen -> exit -> hiddenByPointerLeave,退出 fullscreen 不再强制显示 chrome。

7. 右侧详细设置栏与隐藏把手

目标:对齐 /mnt/Data1T/mnote/tmp/image copy 83.png。右侧不只是简化 tab,而是完整 panel drawer;触发条可以隐藏;隐藏后有把手可恢复。

Task 7: 扩展 Sidebar Schema 到详细控件

Files:

  • Modify: wolai-frontend/src/lib/mindmap/mindmap-ui-schema.ts

  • Modify: wolai-frontend/src/lib/mindmap/mindmap-action-map.ts

  • Modify: wolai-frontend/src/lib/mindmap/mindmap-ui-schema.test.ts

  • Modify: wolai-frontend/src/lib/mindmap/mindmap-action-map.test.ts

  • Sidebar panel 增加 kindnodeStylebaseStylethemestructureoutlineshortcutKeysettings

  • Sidebar option 增加控件类型:buttonswatchsegmentedslidernumberInputselectlayoutCardtreeItemtoggle

  • structure panel 定义布局卡片:逻辑结构图、思维导图、组织结构图、目录组织图、时间轴、鱼骨图。

  • theme panel 定义主题卡片,至少包含 classic、classic4/KMind-like、simple、dark 入口。

  • nodeStyle panel 定义节点填充、文字颜色、字号、加粗、斜体、形状、边框、线条颜色、线条宽度。

  • baseStyle panel 定义连线风格、曲线/直线、彩虹线条、背景、节点间距、概要样式。

  • outline panel 从 projection/runtime 派生树,不允许成为第二套树真相。

  • settingsshortcutKey panel 第一阶段可显示只读内容,但需要在 schema 中有位置。

  • 单测覆盖:每个 sidebar option 要么有 actionId,要么是只读控件;可写控件必须有 compat path 或 kernel command 映射。

  • 验证:cd /mnt/Data1T/mnote/wolai-frontend && pnpm test -- mindmap-ui-schema mindmap-action-map

    • 2026-05-11 通过:mindmap-ui-schema.test.ts 13 项通过;同轮 mindmap-action-map.test.ts 5 项通过。

Task 8: 实现右侧 Trigger、Drawer、隐藏把手

Files:

  • Modify/Create: rust/spikes/leptos-tiptap-spike/src/mindmap_shell.rs

  • Modify: rust/spikes/leptos-tiptap-spike/src/lib.rs

  • Modify: scripts/task167-mindmap-kmind-parity-smoke.js

  • 右侧 trigger 宽度对齐 KMind/simple-mind-map:约 60px,图标在上、文字在下。

  • trigger active 状态使用蓝色强调条或蓝色文字,不再用整块按钮边框作为主要视觉。

  • drawer 打开时宽度约 300px,右侧固定,覆盖画布,不挤压 runtime。

  • drawer 顶部包含 panel 标题和关闭按钮。

  • trigger 左侧或 drawer 边缘提供隐藏把手,点击后隐藏整个 trigger。

  • 隐藏后保留一个小把手;鼠标移入不自动展开,点击把手才恢复。

  • 点击 active trigger:若 drawer 已打开同一 panel,则关闭 drawer;若点击不同 panel,则切换 drawer 内容。

  • 结构 panel 的布局卡片使用稳定尺寸,不能因文字或 hover 导致布局跳动。

  • 右侧 drawer 打开时,底部 navigator 与 drawer 不重叠;必要时 navigator 向左避让或保持在 drawer 左侧。

  • Smoke 断言:打开 structure panel 后可见标题“结构”,可见至少 6 个布局卡片,存在关闭按钮和隐藏把手。

  • Screenshottmp/task167-mindmap-kmind-parity-smoke/05-sidebar-structure-drawer.png

  • Screenshottmp/task167-mindmap-kmind-parity-smoke/06-sidebar-hidden-handle.png

  • 验证:cd /mnt/Data1T/mnote && node scripts/task167-mindmap-kmind-parity-smoke.js --stage sidebar

    • 2026-05-11 通过:drawerWidth=300title=结构structureCardCount=6close/hide/restore 均通过。

Task 9: 打通右侧设置到 Runtime/Kernel/Compat

Files:

  • Modify: wolai-frontend/src/lib/mindmap/mindmap-action-map.ts

  • Modify: wolai-frontend/src/lib/mindmap/simple-mind-map-bridge.ts

  • Modify: wolai-frontend/src/lib/mindmap/leptos-mindmap-adapter.ts

  • Modify: wolai-frontend/src/lib/mindmap/mindmap-command-diff.ts

  • Modify: scripts/task167-mindmap-kmind-parity-smoke.js

  • setLayout 走 kernel command,并刷新 adapter projection。

  • setTheme 走 kernel command,并刷新 adapter projection。

  • 节点样式类 action 先走 runtime 预览,再以 compatPayload.patch 保存样式字段。

  • 基础样式类 action 先走 runtime config/themeConfig,再以 compatPayload.patch 保存无法语义化字段。

  • option 点击失败时显示 command_failed 或等价错误层,不能只改变 UI 本地状态。

  • Smoke 点击结构卡片后 reload,断言 projection layout 保持。

  • Smoke 点击主题卡片后 reload,断言 theme 保持。

  • Smoke 点击节点样式后 reload,断言 compatPayload patch 可见或节点样式保留。

  • 验证:cd /mnt/Data1T/mnote/wolai-frontend && pnpm test -- mindmap-action-map simple-mind-map-bridge

  • 验证:cd /mnt/Data1T/mnote && node scripts/task167-mindmap-kmind-parity-smoke.js --stage sidebar-actions

    • 2026-05-11 通过:sidebarActions.beforeReload/afterReload 均为 layout=mindMaptheme=darkrootFillColor=#dbeafe;同时修正 metadata-only 本地 put 误分流,统一回到 mindmap.command.apply -> mnote-web server-side apply -> mindmaps.put 主链。

8. 底部 Navigator 图标化与 MiniMap/Search

目标:对齐 KMind/simple-mind-map 底部右侧工具条。搜索不应长期占用输入框宽度;全屏、只读、小地图、缩放应统一成 icon/action。

Task 10: Navigator Schema 与 UI 重排

Files:

  • Modify: wolai-frontend/src/lib/mindmap/mindmap-ui-schema.ts

  • Modify/Create: rust/spikes/leptos-tiptap-spike/src/mindmap_shell.rs

  • Modify: scripts/task167-mindmap-kmind-parity-smoke.js

  • Navigator item 改为图标按钮为主:回根、搜索、小地图、只读/编辑、全屏、缩小、缩放值、放大、设置。

  • 搜索默认只显示图标;点击后展开输入框;再次点击或 Escape 收起。

  • 缩放值允许输入百分比;非法输入恢复上一次有效值。

  • 小地图打开后显示在 navigator 上方或右下安全位置,不遮挡 drawer。

  • 只读状态显示明确 active 状态,并同步 mindMap.setMode("readonly" | "edit")

  • Count 固定在左下角,文本保持简短:字数 17节点 4

  • Smoke 断言默认 navigator 没有常驻搜索输入框;点击搜索后输入框出现。

  • Screenshottmp/task167-mindmap-kmind-parity-smoke/07-navigator-icons.png

  • Screenshottmp/task167-mindmap-kmind-parity-smoke/08-search-expanded.png

  • 验证:cd /mnt/Data1T/mnote && node scripts/task167-mindmap-kmind-parity-smoke.js --stage navigator

    • 2026-05-11 通过:默认 searchOpen=false、无常驻输入框;展开搜索后截图已保存;最终 minimapOpen=truereadonly=true、非法缩放输入恢复为 100%

9. Context Menu 与快捷键基础对齐

目标:当前右键菜单已有第一阶段能力,但要对齐 KMind/simple-mind-map 的禁用状态、显示位置和隐藏行为。

Task 11: Context Menu Parity

Files:

  • Modify: wolai-frontend/src/lib/mindmap/mindmap-ui-schema.ts

  • Modify: wolai-frontend/src/lib/mindmap/mindmap-action-map.ts

  • Modify/Create: rust/spikes/leptos-tiptap-spike/src/mindmap_shell.rs

  • Modify: scripts/task167-mindmap-kmind-parity-smoke.js

  • 区分节点右键菜单与画布右键菜单。

  • 节点菜单包含插入子节点、插入同级、删除、展开/收起、概要、关联线、复制文本。

  • 画布菜单包含回根、适应画布、搜索、只读切换、显示菜单。

  • root/generalization 等特殊节点禁用不适用 action。

  • 右键菜单打开时 pointer leave 不立即隐藏 chrome;点击菜单项、Escape、点击画布空白后关闭。

  • 菜单位置不能超出 mindmap root 边界。

  • Smoke 断言节点右键菜单与画布右键菜单的 action 列表不同。

  • Screenshottmp/task167-mindmap-kmind-parity-smoke/09-node-context-menu.png

  • 验证:cd /mnt/Data1T/mnote && node scripts/task167-mindmap-kmind-parity-smoke.js --stage context-menu

    • 2026-05-11 通过:节点菜单仅包含 node actionsroot 节点 insertSiblingAfter/deleteNode 为 disabled;画布菜单为 centerRoot/fitView/search/readonly/showMenupointer leave 后菜单与 chrome 保持可见,Escape 后关闭。

10. KMind 视觉基线

目标:不要只实现功能按钮,要让默认观感接近 KMind/simple-mind-map 工作台。

Task 12: 默认 Theme/Layout 视觉对齐

Files:

  • Modify: rust/crates/bridge-runtime/src/lib.rs

  • Modify: wolai-frontend/src/lib/mindmap/simple-mind-map-bridge.ts

  • Modify: wolai-frontend/src/lib/mindmap/mindmap-projection.ts

  • Modify: scripts/task167-mindmap-kmind-parity-smoke.js

  • 默认 root 节点使用红色/橙红色背景、白色粗体文字,接近 KMind 截图。

  • 默认二级节点使用蓝色背景、白色文字。

  • 分支主题使用蓝色文字,概要括号线使用红色或主题强调色。

  • 默认 layout 选择与 KMind 截图一致的右向逻辑结构。

  • 连线位置不再错位;节点中心线、概要括号线和子节点垂直中心对齐。

  • Smoke 读取 canvas/svg 或截图像素,确认节点和连线非空、可见、位置不重叠。

  • Screenshottmp/task167-mindmap-kmind-parity-smoke/10-kmind-theme-baseline.png

  • 验证:cd /mnt/Data1T/mnote && node scripts/task167-mindmap-kmind-parity-smoke.js --stage theme

    • 2026-05-11 通过:runtime 默认 layout=logicalStructuretheme=defaultthemeConfig 生效为 root 红底白字、二级蓝底白字、分支蓝字、红色概要线;smoke 读取到 nodeCount=5pathCount=9overlaps=0

11. 验证体系

Task 13: 新增 KMind Parity Smoke

Files:

  • Create: scripts/task167-mindmap-kmind-parity-smoke.js

  • Output: tmp/task167-mindmap-kmind-parity-smoke/result.json

  • Output: tmp/task167-mindmap-kmind-parity-smoke/*.png

  • 启动前检查 http://127.0.0.1:3000/ 可用,不强制重启已存在服务。

  • 使用默认测试账号登录。

  • 新建或打开临时文档,插入 mindmap block。

  • 断言 simple-mind-map runtime 存在,canvas rect 非零。

  • 断言 Leptos/Rust shell 来源为 data-ui-shell-source="leptos-rust-shell"

  • 断言 toolbar 单行。

  • 断言 fullscreen 按钮存在并可进入/退出。

  • 断言 pointer leave 隐藏 chrome、pointer enter 不恢复、click 恢复。

  • 断言右侧 drawer 可打开、关闭、隐藏 trigger、点击把手恢复。

  • 断言 navigator 搜索按需展开,小地图可打开。

  • 断言 reload 后 layout/theme/view/compat patch 不丢。

  • 输出 result.json,至少包含 okbaseUrldocumentIdmindmapIdtoolbarRowsfullscreenOkchromeHideOksidebarDrawerOknavigatorOkscreenshots

  • 验证:cd /mnt/Data1T/mnote && node scripts/task167-mindmap-kmind-parity-smoke.js

    • 2026-05-11 通过:默认执行 all stageresult.json 输出 ok/baseUrl/documentId/mindmapId/toolbarRows/fullscreenOk/chromeHideOk/sidebarDrawerOk/navigatorOk/contextMenuOk/themeOk/reloadOk/screenshots,截图 01-10 全量生成。

Task 14: 回归现有 Phase 6 Smoke

Files:

  • Modify: scripts/task166-mindmap-phase6-block-smoke.js only if needed

  • task167 新增后,task166 继续保持 runtime/projection/command/reload 基础验证,不与视觉 parity 重复过多。

  • task166 不因 toolbar 单行、drawer、fullscreen 变化而误判旧 testid 缺失。

  • task166task167 输出目录分离。

  • 验证:cd /mnt/Data1T/mnote && node scripts/task166-mindmap-phase6-block-smoke.js

    • 2026-05-11 通过:task166 保持基础链路验证,兼容 navigator 搜索折叠与 zoom 输入框;result.json 输出在 tmp/task166-mindmap-phase6-block-smoke/,与 task167 分离。

12. 执行顺序建议

建议按以下顺序执行,避免先做 CSS 后返工状态模型:

  1. Task 1:状态模型。
  2. Task 2-3:单行 toolbar 与更多菜单。
  3. Task 4-5:全屏。
  4. Task 6chrome hide/click restore。
  5. Task 7-9:右侧详细设置栏与持久化。
  6. Task 10navigator 图标化。
  7. Task 11context menu。
  8. Task 12:视觉主题与连线对齐。
  9. Task 13-14smoke 与回归。

每次实现完成后,至少保存对应截图,再勾选节点。

13. 阶段验收标准

本 checklist 视为完成时,必须同时满足:

  • /mnt/Data1T/mnote/tmp/task167-mindmap-kmind-parity-smoke/01-toolbar-single-row.png 显示单行 toolbar。
  • /mnt/Data1T/mnote/tmp/task167-mindmap-kmind-parity-smoke/02-fullscreen-canvas.png 显示全屏画布与浮动 chrome。
  • /mnt/Data1T/mnote/tmp/task167-mindmap-kmind-parity-smoke/03-chrome-hidden-after-leave.png 显示鼠标移出后的隐藏状态。
  • /mnt/Data1T/mnote/tmp/task167-mindmap-kmind-parity-smoke/05-sidebar-structure-drawer.png 显示详细右侧结构面板。
  • /mnt/Data1T/mnote/tmp/task167-mindmap-kmind-parity-smoke/07-navigator-icons.png 显示图标化底部 navigator。
  • node scripts/task166-mindmap-phase6-block-smoke.js 通过。
  • node scripts/task167-mindmap-kmind-parity-smoke.js 通过。
  • pnpm test -- mindmap-ui-schema mindmap-action-map mindmap-ui-state simple-mind-map-bridge 通过。
  • npm run typecheck && npm run builddesign/05-editor-mainline/reference-code/leptos-tiptap/tiptap 通过。
  • Rust page.body.save 主链保存 mindmap block 后,/api/documents/content 读回仍为 type: "mindmap",不再退化成 paragraph
    • 2026-05-12 通过:新增 cargo test -p core-protocol preserves_mindmap_paragraph_placeholdercargo test -p core-protocol tiptap_mindmap_placeholder_round_trip_preserves_mindmap_attrscargo test -p bridge-runtime documents_save_command_plan_preserves_mindmap_placeholder;同时在真实 http://127.0.0.1:3000 上手工验证 content[0].type === "mindmap"pageSubtree.subtree.nodes[1].metadata.blockType === "mindmap"
  • GET /documents/{documentId}?workspaceId=... 对有效导图文档返回 HTML 页面壳,而不是 documents.content.get 未返回文档内容 的错误 JSON。
    • 2026-05-12 通过:在前台 mnote-web 实例上重新创建临时导图文档后复测,返回 200 text/html; charset=utf-8,首屏 HTML 正常包含 document shell。
  • 3000 文档页默认主链仍为 Leptos/Rust shell,不加载旧 React mindmap 主链。

14. 明确延期项

以下能力可参考 KMind,但不进入本 checklist 的完成条件:

  • 多根节点。
  • MOC 模式。
  • 思源块预览、镜像块、PDF 标注跳转。
  • Freemind/XMind 全量导入导出。
  • 主题设计器与主题分享。
  • 完整快捷键自定义配置。
  • 演示模式。
  • Rust-native renderer。