Files
mnote/design/10-review/05-tree.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

155 lines
8.3 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.
> 执行状态:本文是 10-review 阶段的树域判断记录,不再作为待办清单直接执行。Resource Tree / File Tree / Page Tree 真源合同已由 `/mnt/Data1T/mnote/design/04-tree-domain/done/4-24-resource-tree-filetree-pagetree-source-contract-checklist-v1.md` 承接;主编辑区 Object Tab、mindmap object editor、`index.md` 隔离已由 `/mnt/Data1T/mnote/design/05-editor-mainline/done/5-12-main-editor-object-tab-resource-alignment-checklist-v1.md` 承接。后续只需按 `06-execution-checklist-and-acceptance.md` 保留 smoke 防回归。
结论
我基本同意你的方向,但要把“文件树为根源”说得更精确:不应让“文件树 UI 组件”成为真源,而应让 Rust kernel 中的 workspace resource tree / file tree projection 背后
的资源层级 成为页面、附件、mindmap、OnlyOffice 等对象的组织根源。页面树则是从这棵资源/对象树派生出的导航投影,类似快捷方式、收藏视图或文档视图。
对当前 bug 来说,最核心的规则应固定为:
1. index.md 只代表页面正文,即 Page Aggregate body。
2. mindmap 不是主编辑区正文替身,而是页面内某个 block 关联的 object / asset editor。
3. 文件树点击 mindmap 应打开 mindmap object editor,不能被 index.md 吞掉,也不能用临时 mindmap-only bootstrap 覆盖真实页面正文。
4. 页面树不应再持有独立结构真相,只显示“文档导航关系”;文件树显示“资源组织关系”。
主编辑区与插件
主编辑区应该是一个工作区 tab host,而不是只等于文档正文编辑器。index.md 是其中一种 tabmindmap、OnlyOffice、附件预览、代码附件都是其他 object tab/model。
Siyuan 这里值得借鉴:doc 和 asset 是不同 model/tabasset 打开不伪装成 doc 正文;插件、widgets、assets、.sy 文档也在存储层分开。mnote 也应采用类似原则:插件/附
件/mindmap 可以嵌入页面,但它们的持久化真源不能变成页面正文本身,只能通过 block-asset relation 被 Page Aggregate 引用。
文件树与页面树
我建议改成三层表述:
- Resource Tree:长期 canonical 对象组织树,Rust kernel 持有语义,Convex 只是底层存储。
- File TreeResource Tree 的主组织投影,展示页面文件夹、index.md、附件、mindmap、OnlyOffice、代码附件等。
- Page Tree:面向阅读/导航的快捷投影,只显示页面关系,不拥有排序、父子、附件归属的最终真相。
这样你的“文件树为根源”可以落地,但不会和现有 tree-first graph kernel 冲突。更准确地说:文件树背后的 resource hierarchy 是根源,页面树是它的页面导航视图。
建议路线
短期先修当前 bug:保留 /mindmap/{doc}/{asset} 作为 object editor,但彻底隔离草稿 key、保存 command 和 Page Aggregate bodysmoke 必须真实网页验证“点击 mindmap、
编辑长中文、保存、切回 index.md、再打开 mindmap 内容仍在”。
中期做主编辑区 asset tabindex.md | mindmap.json | xxx.docx,每个 tab 有自己的 object identity 和保存命令。
长期补 resource projection / block-asset relation:文件树 row、页面内 mindmap block、mindmap projection 必须来自同一关系索引,而不是前端临时按路由拼。
推荐路线
我建议采用“分阶段收口 Resource Tree”的方案,不做一次性大重构。
可选方案有三种:
- 只修 mindmap bug:最快,但会继续留下页面树/文件树真源分裂。
- 分阶段建立 Resource Tree -> File Tree/Page Tree projection:最稳,能解决当前 bug,也能承接附件、OnlyOffice、插件对象。
- 全量重写 tree/page/resource 模型:理论干净,但当前工作区和主链都很活跃,风险太高。
我推荐第二种。
阶段 0:冻结合同
先把 design/10-review/05-tree.md 升级为正式设计合同,建议后续移动或补一份到:
- design/04-tree-domain/process/4-24-resource-tree-filetree-pagetree-source-contract-v1.md
- 或 design/05-editor-mainline/process/5-11-main-editor-object-tab-resource-tree-alignment-v1.md
合同里固定四句话:
- Resource Tree 是组织真源。
- File Tree 是资源组织主投影。
- Page Tree 是页面导航投影/快捷视图。
- index.md、mindmap、OnlyOffice、附件是不同 object model,不能互相伪装。
阶段 1:先关闭当前 mindmap bug
目标:文件树 mindmap 仍可编辑保存,但不污染 index.md。
重点文件:
- rust/crates/mnote-web/src/ssr/pages/layout.rs
- rust/crates/mnote-web/src/routes/mindmap_shell.rs
- rust/spikes/leptos-tiptap-spike/src/lib.rs
- scripts/task169-mindmap-realtime-smoke.js
验收必须是真实浏览器链路:
1. 从文件树点击 mindmap asset。
2. 进入明确的 mindmap object editor。
3. 输入长中文并保存。
4. 切回同页 index.md,正文仍是 Page Aggregate body。
5. 再打开 mindmap,刚才内容仍在。
6. 确认没有用真实 documentId 写 standalone 草稿 key。
阶段 2:补 Resource Projection 协议
在 Rust 协议层明确资源节点和 block-asset 关系。
建议新增或扩展:
- ResourceNode
- ResourceKind: page | index | mindmap | attachment | onlyoffice | code
- ObjectIdentity: { objectKind, documentId, blockId?, assetId? }
- BlockAssetRelation: { documentId, blockId, assetId, assetKind }
落点优先看:
- rust/crates/core-protocol/
- rust/crates/bridge-runtime/
- rust/crates/mnote-web/src/tree_shell/
这个阶段不要求立刻迁移所有数据,只要协议和 projection 能表达清楚。
阶段 3:让 File Tree 从 Resource Tree 派生
当前 file tree 已有 resourceMeta、assetKind、file_tree projection 基础。下一步是收口为:
- 页面节点下面固定有 index.md
- mindmap/附件/OnlyOffice 都是同一 Resource Tree 下的 child resource
- 文件树 row 不再临时从多份前端数据拼出第二真相
同时保留 tree.asset.open,但它必须只表达 object open intent,不直接决定“把谁当正文”。
阶段 4:Page Tree 降级为导航投影
Page Tree 不再拥有资源归属、附件归属、mindmap 归属。它只显示页面导航关系:
- 页面标题
- 页面层级
- 快捷入口/收藏/最近打开这类导航语义
如果页面树需要显示某个资源状态,也只读 Resource Projection,不自己维护。
阶段 5:主编辑区变成 Object Tab Host
这是中期关键体验:
- index.md tab:加载 Page Aggregate body。
- mindmap.json tab:加载 mindmap projection/command。
- xxx.docx tab:打开 OnlyOffice object editor。
- attachment tab:预览/代码编辑/外部打开。
这样 mindmap 不会被 index.md 吞掉,也不会伪装成正文。
阶段 6:命令面统一
后续命令应逐步收口到:
- tree.asset.attach
- tree.asset.detach
- tree.resource.rename
- tree.resource.move
- page.body.save
- mindmap.command.apply
关键规则:改资源关系走 tree/resource command,改页面正文走 page command,改导图内容走 mindmap command。
落地入口
以上判断已落实到两个主线 done checklist
- /mnt/Data1T/mnote/design/04-tree-domain/done/4-24-resource-tree-filetree-pagetree-source-contract-checklist-v1.md
用于冻结 Resource Tree / File Tree / Page Tree 的真源合同和 projection / command 边界。
- /mnt/Data1T/mnote/design/05-editor-mainline/done/5-12-main-editor-object-tab-resource-alignment-checklist-v1.md
用于落实主编辑区 Object Tab、mindmap object editor、草稿隔离和真实浏览器 smoke 验收。
执行顺序固定为:
1. 先完成 4-24:协议、projection、command 边界必须能表达 `index.md`、mindmap、OnlyOffice、附件、代码附件的不同 object identity,并确认 Page Tree 只是页面导航投影。
2. 再完成 5-12:主编辑区只消费 4-24 输出的 object identity / resourceMeta / open intent,先关闭 mindmap 污染 `index.md` 的 P0 bug,再推进 Object Tab Host。
3. 验收以真实浏览器 smoke 为准,尤其是 `scripts/task169-mindmap-realtime-smoke.js` 覆盖“打开 mindmap、长中文编辑、保存、切页、回 `index.md`、再开 mindmap”的链路。