- 补齐 design/10-review 执行清单、验收标准与相关设计治理记录 - 迁移已完成的 tree、mindmap、runtime fallback、AI kernel 等设计和缺陷条目 - 推进 Rust Web runtime、tree/sidebar、page aggregate、mindmap 与 OnlyOffice 路由侧验证支撑 - 增加 task177-task180 smoke/audit 脚本及前端相关测试覆盖
155 lines
8.3 KiB
Markdown
155 lines
8.3 KiB
Markdown
> 执行状态:本文是 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 是其中一种 tab,mindmap、OnlyOffice、附件预览、代码附件都是其他 object tab/model。
|
||
|
||
Siyuan 这里值得借鉴:doc 和 asset 是不同 model/tab,asset 打开不伪装成 doc 正文;插件、widgets、assets、.sy 文档也在存储层分开。mnote 也应采用类似原则:插件/附
|
||
件/mindmap 可以嵌入页面,但它们的持久化真源不能变成页面正文本身,只能通过 block-asset relation 被 Page Aggregate 引用。
|
||
|
||
文件树与页面树
|
||
我建议改成三层表述:
|
||
|
||
- Resource Tree:长期 canonical 对象组织树,Rust kernel 持有语义,Convex 只是底层存储。
|
||
- File Tree:Resource Tree 的主组织投影,展示页面文件夹、index.md、附件、mindmap、OnlyOffice、代码附件等。
|
||
- Page Tree:面向阅读/导航的快捷投影,只显示页面关系,不拥有排序、父子、附件归属的最终真相。
|
||
|
||
这样你的“文件树为根源”可以落地,但不会和现有 tree-first graph kernel 冲突。更准确地说:文件树背后的 resource hierarchy 是根源,页面树是它的页面导航视图。
|
||
|
||
建议路线
|
||
短期先修当前 bug:保留 /mindmap/{doc}/{asset} 作为 object editor,但彻底隔离草稿 key、保存 command 和 Page Aggregate body,smoke 必须真实网页验证“点击 mindmap、
|
||
编辑长中文、保存、切回 index.md、再打开 mindmap 内容仍在”。
|
||
|
||
中期做主编辑区 asset tab:index.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”的链路。
|