2026-04-30 16:18:54 +08:00
|
|
|
|
# 4 [done] Sidebar / 页面树 / 文件树 Rust Web 重构方案 v1
|
|
|
|
|
|
|
|
|
|
|
|
> 更新时间:2026-04-22
|
|
|
|
|
|
>
|
|
|
|
|
|
> 当前优先级入口:
|
|
|
|
|
|
> - `/mnt/Data1T/mnote/design/01-05-current-priority-overview.md`
|
|
|
|
|
|
>
|
|
|
|
|
|
> 关联文档:
|
2026-05-23 23:38:42 +08:00
|
|
|
|
> - `/mnt/Data1T/mnote/design/01-tree-first-graph-kernel/reference/1-tree-first-graph-kernel-v1.md`
|
|
|
|
|
|
> - `/mnt/Data1T/mnote/design/01-tree-first-graph-kernel/reference/1-1-tree-first-graph-kernel-checklist-v2.md`
|
2026-04-30 16:18:54 +08:00
|
|
|
|
> - `/mnt/Data1T/mnote/design/03-rust-web/done/3-2-tree-first-graph-kernel-phase3-task-breakdown-v1.md`
|
|
|
|
|
|
> - `/mnt/Data1T/mnote/design/90-reference/90-2-yemianshu.md`
|
|
|
|
|
|
> - `/mnt/Data1T/mnote/design/90-reference/90-1-filetree.md`
|
|
|
|
|
|
> - `/mnt/Data1T/mnote/design/old/04-tree-domain/process/4-1-sidebar-pagetree-filetree-product-gap-analysis-v1.md`
|
|
|
|
|
|
|
|
|
|
|
|
## 1. 文档目的
|
|
|
|
|
|
|
|
|
|
|
|
这份文档回答的问题不是:
|
|
|
|
|
|
|
|
|
|
|
|
- “当前 Sidebar 再怎么局部优化一下”
|
|
|
|
|
|
|
|
|
|
|
|
而是:
|
|
|
|
|
|
|
|
|
|
|
|
> **在 `tree-first graph kernel` 前提下,是否应该把 Sidebar / 页面树 / 文件树直接重构为一个独立的 Rust Web 子系统。**
|
|
|
|
|
|
|
|
|
|
|
|
本文的结论是:
|
|
|
|
|
|
|
|
|
|
|
|
> **可以,而且长期上这是正确方向;但重构对象不是“一个更快的树组件”,而是“一个直接消费 kernel projection 的独立树域执行面”。**
|
|
|
|
|
|
|
|
|
|
|
|
也就是说,目标不是把当前 React 树组件换个语言重写,而是:
|
|
|
|
|
|
|
|
|
|
|
|
- 用 Rust 主导 tree projection
|
|
|
|
|
|
- 用 Rust Web 主导 tree query / command
|
|
|
|
|
|
- 让页面树 / 文件树只作为 kernel 的树投影
|
|
|
|
|
|
- 再决定 UI 壳是否也迁到 Rust 家族
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 2. 必须遵守的前提:树不是 UI 数据,而是 kernel 投影
|
|
|
|
|
|
|
|
|
|
|
|
这份方案必须完全服从:
|
|
|
|
|
|
|
2026-05-23 23:38:42 +08:00
|
|
|
|
- [tree-first-graph-kernel-v1.md](/mnt/Data1T/mnote/design/01-tree-first-graph-kernel/reference/1-tree-first-graph-kernel-v1.md)
|
2026-04-30 16:18:54 +08:00
|
|
|
|
|
|
|
|
|
|
里面已经固定的几条原则。
|
|
|
|
|
|
|
|
|
|
|
|
### 2.1 树是主骨架
|
|
|
|
|
|
|
|
|
|
|
|
当前长期架构已经冻结为:
|
|
|
|
|
|
|
|
|
|
|
|
- 树是主骨架
|
|
|
|
|
|
- 图是横向扩展
|
|
|
|
|
|
- Sidebar / 页面树 / 文件树 / 阅读流 / Mindmap 都只是 projection
|
|
|
|
|
|
|
|
|
|
|
|
所以这里的页面树 / 文件树不能再被定义为:
|
|
|
|
|
|
|
|
|
|
|
|
- 前端自己拼出来的导航数据
|
|
|
|
|
|
|
|
|
|
|
|
它们必须被定义为:
|
|
|
|
|
|
|
|
|
|
|
|
- `tree-first graph kernel` 的树投影
|
|
|
|
|
|
|
|
|
|
|
|
### 2.2 页面树和文件树不是两套真相
|
|
|
|
|
|
|
|
|
|
|
|
在新架构里:
|
|
|
|
|
|
|
|
|
|
|
|
- 页面树不是独立系统
|
|
|
|
|
|
- 文件树也不是独立系统
|
|
|
|
|
|
|
|
|
|
|
|
两者都来自同一个 kernel,只是投影范围不同:
|
|
|
|
|
|
|
|
|
|
|
|
- `page_tree`
|
|
|
|
|
|
- 以 `page` / `section` / 页面层级为主
|
|
|
|
|
|
- `file_tree`
|
|
|
|
|
|
- 在页面层级基础上,把 `asset` / `mindmap` / `table` / 未来 `book` / `pdf` 一起投影出来
|
|
|
|
|
|
|
|
|
|
|
|
### 2.3 Sidebar 是壳,不是事实源
|
|
|
|
|
|
|
|
|
|
|
|
Sidebar 长期不应再被理解为:
|
|
|
|
|
|
|
|
|
|
|
|
- “一个左侧导航 React 组件”
|
|
|
|
|
|
|
|
|
|
|
|
而应理解为:
|
|
|
|
|
|
|
|
|
|
|
|
- “tree projection 的承载壳”
|
|
|
|
|
|
|
|
|
|
|
|
固定边界应是:
|
|
|
|
|
|
|
|
|
|
|
|
- kernel 持有真相
|
|
|
|
|
|
- projection 输出树
|
|
|
|
|
|
- Sidebar 只负责显示和交互
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 3. 当前现状
|
|
|
|
|
|
|
|
|
|
|
|
### 3.1 已经做对的部分
|
|
|
|
|
|
|
|
|
|
|
|
当前代码已经有一些方向是正确的:
|
|
|
|
|
|
|
|
|
|
|
|
- `kernelSidebarProjection`
|
|
|
|
|
|
- `kernelSidebarTree`
|
|
|
|
|
|
- `Sidebar` 主树开始以 `kernelSidebarTree` 为来源
|
|
|
|
|
|
- Rust runtime 和 `mnote-web` 已开始承接 Sidebar 相关 projection 主链
|
|
|
|
|
|
|
|
|
|
|
|
对应代码包括:
|
|
|
|
|
|
|
|
|
|
|
|
- [kernel-sidebar.ts](/mnt/Data1T/mnote/wolai-frontend/src/lib/kernel-sidebar.ts)
|
|
|
|
|
|
- [sidebar-data.ts](/mnt/Data1T/mnote/wolai-frontend/src/lib/sidebar-data.ts)
|
|
|
|
|
|
- [sidebar.tsx](/mnt/Data1T/mnote/wolai-frontend/src/components/sidebar/sidebar.tsx)
|
|
|
|
|
|
- [kernel.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/routes/kernel.rs)
|
|
|
|
|
|
|
|
|
|
|
|
### 3.2 还没做完的部分
|
|
|
|
|
|
|
|
|
|
|
|
当前真正的问题是:
|
|
|
|
|
|
|
|
|
|
|
|
- 主 Sidebar 仍是超大客户端组件
|
|
|
|
|
|
- 文件树仍然主要在前端继续加工 row model
|
|
|
|
|
|
- `move-embed picker` 等兼容域仍保留旧 `buildDocumentTree(...)`
|
|
|
|
|
|
- 页面树和文件树还没有彻底统一为稳定的 kernel projection family
|
|
|
|
|
|
|
|
|
|
|
|
这说明:
|
|
|
|
|
|
|
|
|
|
|
|
> **现在的瓶颈不只是“UI 重”,而是“树域仍然没有形成独立、稳定、可替换的执行边界”。**
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 4. 对参考资料的判断
|
|
|
|
|
|
|
|
|
|
|
|
### 4.1 `/design/cankao/yemianshu.md` 和 `/design/cankao/filetree.md` 能参考什么
|
|
|
|
|
|
|
|
|
|
|
|
这两份参考有价值,但要分层使用。
|
|
|
|
|
|
|
|
|
|
|
|
适合借鉴的部分:
|
|
|
|
|
|
|
|
|
|
|
|
- 树形系统的分层
|
|
|
|
|
|
- VS Code / Notion 风格交互
|
|
|
|
|
|
- 折叠、展开、拖拽、懒加载、多选、右键菜单
|
|
|
|
|
|
|
|
|
|
|
|
不适合直接拿来落当前 Web 主线的部分:
|
|
|
|
|
|
|
|
|
|
|
|
- Ratatui / Cursive / TUI 组件
|
|
|
|
|
|
- egui / iced / Fyrox / GPUI 这类桌面 GUI 组件
|
|
|
|
|
|
|
|
|
|
|
|
原因很简单:
|
|
|
|
|
|
|
|
|
|
|
|
- 这些更适合终端或原生桌面
|
|
|
|
|
|
- 当前 mnote 的主线是 Web + Rust Web + kernel projection
|
|
|
|
|
|
|
|
|
|
|
|
所以它们更适合做:
|
|
|
|
|
|
|
|
|
|
|
|
- 交互语义参考
|
|
|
|
|
|
|
|
|
|
|
|
而不适合做:
|
|
|
|
|
|
|
|
|
|
|
|
- 当前 Web 主线的直接实现模板
|
|
|
|
|
|
|
|
|
|
|
|
### 4.2 更适合作为直接参考的方向
|
|
|
|
|
|
|
|
|
|
|
|
如果这次真要把 Sidebar / 页面树 / 文件树往 Rust 家族重构,应该看两类参考:
|
|
|
|
|
|
|
|
|
|
|
|
#### A. Rust Web 前端框架
|
|
|
|
|
|
|
|
|
|
|
|
优先关注:
|
|
|
|
|
|
|
|
|
|
|
|
- `Leptos`
|
|
|
|
|
|
- `Dioxus`
|
|
|
|
|
|
- `Yew`
|
|
|
|
|
|
|
|
|
|
|
|
本文的建议顺序是:
|
|
|
|
|
|
|
|
|
|
|
|
1. `Leptos`
|
|
|
|
|
|
2. `Dioxus`
|
|
|
|
|
|
3. `Yew`
|
|
|
|
|
|
|
|
|
|
|
|
原因不是抽象喜好,而是贴合度:
|
|
|
|
|
|
|
|
|
|
|
|
- 你们已经在走 Rust kernel + Rust Web + server-first
|
|
|
|
|
|
- 这时最有价值的是“Rust Web 组件 + server integration + 渐进切流”
|
|
|
|
|
|
- 不是终端树,也不是桌面树
|
|
|
|
|
|
|
|
|
|
|
|
#### B. 成熟 Web Tree 的行为模型
|
|
|
|
|
|
|
|
|
|
|
|
即使最终决定用 Rust 家族重写,交互模型也应该优先参考成熟 Web Tree 的做法:
|
|
|
|
|
|
|
|
|
|
|
|
- headless tree 思路
|
|
|
|
|
|
- VS Code Explorer 的 row model
|
|
|
|
|
|
- 大树虚拟化
|
|
|
|
|
|
- DnD 状态机
|
|
|
|
|
|
- selection / focus / keyboard 模型
|
|
|
|
|
|
|
|
|
|
|
|
这里学的是:
|
|
|
|
|
|
|
|
|
|
|
|
- 行为模型
|
|
|
|
|
|
|
|
|
|
|
|
不是:
|
|
|
|
|
|
|
|
|
|
|
|
- 必须沿用 React
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 5. 结论:可以直接重构,但应定义成独立大任务
|
|
|
|
|
|
|
|
|
|
|
|
我的明确结论是:
|
|
|
|
|
|
|
|
|
|
|
|
> **可以直接把 Sidebar / 页面树 / 文件树作为独立大任务重构,而且长期上应该这样做。**
|
|
|
|
|
|
|
|
|
|
|
|
但这个重构不能被理解为:
|
|
|
|
|
|
|
|
|
|
|
|
- 把 `sidebar.tsx` 翻译成 Rust
|
|
|
|
|
|
|
|
|
|
|
|
而应被理解为:
|
|
|
|
|
|
|
|
|
|
|
|
- 把树域从旧前端壳里剥离出来
|
|
|
|
|
|
- 形成一个独立的 Rust Web tree shell
|
|
|
|
|
|
|
|
|
|
|
|
也就是:
|
|
|
|
|
|
|
|
|
|
|
|
- 独立 route / shell
|
|
|
|
|
|
- 独立 projection protocol
|
|
|
|
|
|
- 独立 command protocol
|
|
|
|
|
|
- 独立 UI state 边界
|
|
|
|
|
|
|
|
|
|
|
|
这个任务应该单独成立,而不是继续藏在 `Kernel Phase 4` 的一句话里。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 6. 目标架构
|
|
|
|
|
|
|
|
|
|
|
|
## 6.1 新的树域分层
|
|
|
|
|
|
|
|
|
|
|
|
长期建议把树域拆成五层:
|
|
|
|
|
|
|
|
|
|
|
|
### 1. Kernel Truth
|
|
|
|
|
|
|
|
|
|
|
|
只承载:
|
|
|
|
|
|
|
|
|
|
|
|
- `node`
|
|
|
|
|
|
- `edge`
|
|
|
|
|
|
- `subtree`
|
|
|
|
|
|
- `audit`
|
|
|
|
|
|
|
|
|
|
|
|
### 2. Tree Projection Layer
|
|
|
|
|
|
|
|
|
|
|
|
专门输出:
|
|
|
|
|
|
|
|
|
|
|
|
- `sidebar_tree`
|
|
|
|
|
|
- `page_tree`
|
|
|
|
|
|
- `file_tree`
|
|
|
|
|
|
|
|
|
|
|
|
固定输出应包括:
|
|
|
|
|
|
|
|
|
|
|
|
- `projection_id`
|
|
|
|
|
|
- `root_node_id`
|
|
|
|
|
|
- `items`
|
|
|
|
|
|
- `edges`
|
|
|
|
|
|
- `sort key`
|
|
|
|
|
|
- `expand hint`
|
|
|
|
|
|
- `capability flags`
|
|
|
|
|
|
|
|
|
|
|
|
### 3. Tree Command Layer
|
|
|
|
|
|
|
|
|
|
|
|
只处理树域命令:
|
|
|
|
|
|
|
|
|
|
|
|
- create page
|
|
|
|
|
|
- move subtree
|
|
|
|
|
|
- attach asset
|
|
|
|
|
|
- reorder sibling
|
|
|
|
|
|
- archive / restore
|
|
|
|
|
|
- open node
|
|
|
|
|
|
|
|
|
|
|
|
### 4. Tree Shell
|
|
|
|
|
|
|
|
|
|
|
|
树域的独立承载壳,只负责:
|
|
|
|
|
|
|
|
|
|
|
|
- 拉 projection
|
|
|
|
|
|
- 发 command
|
|
|
|
|
|
- 维护局部 UI 状态
|
|
|
|
|
|
|
|
|
|
|
|
### 5. Tree Renderer
|
|
|
|
|
|
|
|
|
|
|
|
最终的可视组件,只负责:
|
|
|
|
|
|
|
|
|
|
|
|
- row 渲染
|
|
|
|
|
|
- 虚拟化
|
|
|
|
|
|
- 选中
|
|
|
|
|
|
- 展开
|
|
|
|
|
|
- 右键菜单
|
|
|
|
|
|
- DnD feedback
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 6.2 页面树和文件树的正确关系
|
|
|
|
|
|
|
|
|
|
|
|
在新架构里,这两者不该是并列的两套不同系统,而应是:
|
|
|
|
|
|
|
|
|
|
|
|
### 页面树
|
|
|
|
|
|
|
|
|
|
|
|
只关心:
|
|
|
|
|
|
|
|
|
|
|
|
- `workspace`
|
|
|
|
|
|
- `folder`
|
|
|
|
|
|
- `page`
|
|
|
|
|
|
- `section`
|
|
|
|
|
|
|
|
|
|
|
|
### 文件树
|
|
|
|
|
|
|
|
|
|
|
|
在页面树骨架上再纳入:
|
|
|
|
|
|
|
|
|
|
|
|
- `asset`
|
|
|
|
|
|
- `mindmap`
|
|
|
|
|
|
- `table`
|
|
|
|
|
|
- `book`
|
|
|
|
|
|
- `pdf`
|
|
|
|
|
|
- 未来的 `index_node`
|
|
|
|
|
|
|
|
|
|
|
|
也就是说:
|
|
|
|
|
|
|
|
|
|
|
|
> **文件树不是“另建一棵树”,而是“同一棵树的更宽对象投影”。**
|
|
|
|
|
|
|
|
|
|
|
|
这非常符合 `tree-first graph kernel` 的定义。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 7. 为什么建议用 Rust Web 子系统,而不是继续堆在当前 Sidebar 里
|
|
|
|
|
|
|
|
|
|
|
|
### 7.1 当前 Sidebar 太大
|
|
|
|
|
|
|
|
|
|
|
|
现在的 Sidebar 不只是树:
|
|
|
|
|
|
|
|
|
|
|
|
- 搜索入口
|
|
|
|
|
|
- 成员
|
|
|
|
|
|
- 分享
|
|
|
|
|
|
- 回收站
|
|
|
|
|
|
- 资源操作
|
|
|
|
|
|
- 页面树
|
|
|
|
|
|
- 文件树
|
|
|
|
|
|
- 各种本地对话框
|
|
|
|
|
|
|
|
|
|
|
|
这会导致:
|
|
|
|
|
|
|
|
|
|
|
|
- 状态膨胀
|
|
|
|
|
|
- 切页参与重渲染
|
|
|
|
|
|
- 树逻辑和业务逻辑缠在一起
|
|
|
|
|
|
|
|
|
|
|
|
### 7.2 树域已经足够大,可以独立成系统
|
|
|
|
|
|
|
|
|
|
|
|
页面树 / 文件树本身已经有:
|
|
|
|
|
|
|
|
|
|
|
|
- 自己的数据协议
|
|
|
|
|
|
- 自己的 row model
|
|
|
|
|
|
- 自己的拖拽系统
|
|
|
|
|
|
- 自己的选择模型
|
|
|
|
|
|
- 自己的上下文菜单
|
|
|
|
|
|
- 自己的资源挂载逻辑
|
|
|
|
|
|
|
|
|
|
|
|
这已经不是一个小组件,而是一个完整子系统。
|
|
|
|
|
|
|
|
|
|
|
|
### 7.3 独立之后更符合后续迁移
|
|
|
|
|
|
|
|
|
|
|
|
如果现在就把它切成独立树域子系统,后续:
|
|
|
|
|
|
|
|
|
|
|
|
- Mindmap
|
|
|
|
|
|
- 阅读页结构树
|
|
|
|
|
|
- 搜索结构结果
|
|
|
|
|
|
- Book / PDF 子树
|
|
|
|
|
|
|
|
|
|
|
|
都可以复用同一套 projection / renderer 协议。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 8. 技术路线选择
|
|
|
|
|
|
|
|
|
|
|
|
## 8.1 方案对比
|
|
|
|
|
|
|
|
|
|
|
|
### 方案 A:继续 React,只换数据层
|
|
|
|
|
|
|
|
|
|
|
|
优点:
|
|
|
|
|
|
|
|
|
|
|
|
- 风险最低
|
|
|
|
|
|
- 最快收口旧 helper
|
|
|
|
|
|
|
|
|
|
|
|
缺点:
|
|
|
|
|
|
|
|
|
|
|
|
- 树域仍留在旧前端壳内
|
|
|
|
|
|
- 不能完成“Rust 主执行面”这一步
|
|
|
|
|
|
|
|
|
|
|
|
### 方案 B:独立 Rust Web tree shell,当前主站只挂载它
|
|
|
|
|
|
|
|
|
|
|
|
优点:
|
|
|
|
|
|
|
|
|
|
|
|
- 可以保留整体产品双栈过渡
|
|
|
|
|
|
- 树域先行 Rust 化
|
|
|
|
|
|
- 与 `tree-first graph kernel` 最一致
|
|
|
|
|
|
|
|
|
|
|
|
缺点:
|
|
|
|
|
|
|
|
|
|
|
|
- 需要额外处理嵌入、路由、样式、事件桥接
|
|
|
|
|
|
|
|
|
|
|
|
### 方案 C:直接整站前端重写
|
|
|
|
|
|
|
|
|
|
|
|
优点:
|
|
|
|
|
|
|
|
|
|
|
|
- 理论上最终最纯
|
|
|
|
|
|
|
|
|
|
|
|
缺点:
|
|
|
|
|
|
|
|
|
|
|
|
- 范围失控
|
|
|
|
|
|
- 风险过高
|
|
|
|
|
|
- 与当前阶段目标不匹配
|
|
|
|
|
|
|
|
|
|
|
|
## 8.2 当前建议
|
|
|
|
|
|
|
|
|
|
|
|
本文明确建议:
|
|
|
|
|
|
|
|
|
|
|
|
> **选方案 B:把 Sidebar / 页面树 / 文件树做成独立 Rust Web tree shell。**
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 8.3 Rust Web 框架建议
|
|
|
|
|
|
|
|
|
|
|
|
当前优先建议:
|
|
|
|
|
|
|
|
|
|
|
|
### 第一选择:Leptos
|
|
|
|
|
|
|
|
|
|
|
|
原因:
|
|
|
|
|
|
|
|
|
|
|
|
- 更贴近 Rust 全栈 / server-first
|
|
|
|
|
|
- 更适合和 `axum` / `mnote-web` 的方向合并
|
|
|
|
|
|
- 适合做“树域先行”的渐进式替换
|
|
|
|
|
|
|
|
|
|
|
|
### 第二选择:Dioxus
|
|
|
|
|
|
|
|
|
|
|
|
原因:
|
|
|
|
|
|
|
|
|
|
|
|
- 跨 Web / Desktop 能力强
|
|
|
|
|
|
- 如果未来想把树域同时复用到桌面壳,会有价值
|
|
|
|
|
|
|
|
|
|
|
|
### 第三选择:Yew
|
|
|
|
|
|
|
|
|
|
|
|
原因:
|
|
|
|
|
|
|
|
|
|
|
|
- 能做,但相对不如前两者贴合当前迁移方向
|
|
|
|
|
|
|
|
|
|
|
|
所以这份方案的推荐结论是:
|
|
|
|
|
|
|
|
|
|
|
|
> **树域独立重构时,优先按 `mnote-web + Leptos` 设计。**
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 8.4 GitHub 参考池
|
|
|
|
|
|
|
|
|
|
|
|
这里不再按“有没有现成 Rust Notion 成品”来选参考,而是按三个层级来选:
|
|
|
|
|
|
|
|
|
|
|
|
- Rust Web 承载框架
|
|
|
|
|
|
- 树域 UI primitives
|
|
|
|
|
|
- 树行为模型与产品结构参考
|
|
|
|
|
|
|
|
|
|
|
|
### A. 直接可参考:Rust Web 主路线
|
|
|
|
|
|
|
|
|
|
|
|
#### `leptos-rs/leptos`
|
|
|
|
|
|
|
|
|
|
|
|
GitHub:
|
|
|
|
|
|
|
|
|
|
|
|
- https://github.com/leptos-rs/leptos
|
|
|
|
|
|
|
|
|
|
|
|
适合借鉴:
|
|
|
|
|
|
|
|
|
|
|
|
- `Rust + SSR + islands` 的 Web 承载方式
|
|
|
|
|
|
- 与 `axum` 风格服务端组合
|
|
|
|
|
|
- 渐进式切流,而不是一次性整站替换
|
|
|
|
|
|
|
|
|
|
|
|
为什么适合当前方案:
|
|
|
|
|
|
|
|
|
|
|
|
- 当前 `mnote-web` 已经是 Rust Web 接入点
|
|
|
|
|
|
- 树域后续如果独立成 shell,最需要的是“Rust Web 承载能力”,不是单独一个树控件
|
|
|
|
|
|
|
|
|
|
|
|
结论:
|
|
|
|
|
|
|
|
|
|
|
|
- **这是树域 Rust Web 重构的第一参考。**
|
|
|
|
|
|
|
|
|
|
|
|
#### `DioxusLabs/dioxus`
|
|
|
|
|
|
|
|
|
|
|
|
GitHub:
|
|
|
|
|
|
|
|
|
|
|
|
- https://github.com/DioxusLabs/dioxus
|
|
|
|
|
|
|
|
|
|
|
|
适合借鉴:
|
|
|
|
|
|
|
|
|
|
|
|
- Rust 组件化 UI
|
|
|
|
|
|
- Web / Desktop 共享思路
|
|
|
|
|
|
|
|
|
|
|
|
限制:
|
|
|
|
|
|
|
|
|
|
|
|
- 更偏多端壳能力
|
|
|
|
|
|
- 与当前 `mnote-web + axum` 路线的贴合度仍低于 `Leptos`
|
|
|
|
|
|
|
|
|
|
|
|
结论:
|
|
|
|
|
|
|
|
|
|
|
|
- **可作为备选路线参考,但不是当前首选。**
|
|
|
|
|
|
|
|
|
|
|
|
#### `yewstack/yew`
|
|
|
|
|
|
|
|
|
|
|
|
GitHub:
|
|
|
|
|
|
|
|
|
|
|
|
- https://github.com/yewstack/yew
|
|
|
|
|
|
|
|
|
|
|
|
适合借鉴:
|
|
|
|
|
|
|
|
|
|
|
|
- Rust Web 组件化基本能力
|
|
|
|
|
|
|
|
|
|
|
|
限制:
|
|
|
|
|
|
|
|
|
|
|
|
- 能做,但对你们当前 server-first 与渐进切流路线支持感不如 `Leptos`
|
|
|
|
|
|
|
|
|
|
|
|
结论:
|
|
|
|
|
|
|
|
|
|
|
|
- **保留为第三选择,不作为当前主实现模板。**
|
|
|
|
|
|
|
|
|
|
|
|
### B. 直接可参考:树域 UI primitives / 组件层
|
|
|
|
|
|
|
|
|
|
|
|
#### `cloud-shuttle/radix-leptos`
|
|
|
|
|
|
|
|
|
|
|
|
GitHub:
|
|
|
|
|
|
|
|
|
|
|
|
- https://github.com/cloud-shuttle/radix-leptos
|
|
|
|
|
|
|
|
|
|
|
|
适合借鉴:
|
|
|
|
|
|
|
|
|
|
|
|
- `Leptos` 生态下的 UI primitives 组合方式
|
|
|
|
|
|
- `collapsible`、`scroll area`、`menu`、`overlay`、可访问性细节
|
|
|
|
|
|
- 树域壳层需要的基础交互组件
|
|
|
|
|
|
|
|
|
|
|
|
限制:
|
|
|
|
|
|
|
|
|
|
|
|
- 它不是完整树组件
|
|
|
|
|
|
- 不能直接替代页面树 / 文件树的 row model 与状态机
|
|
|
|
|
|
|
|
|
|
|
|
结论:
|
|
|
|
|
|
|
|
|
|
|
|
- **适合作为树域 shell 的基础件参考。**
|
|
|
|
|
|
|
|
|
|
|
|
#### `thaw-ui/thaw`
|
|
|
|
|
|
|
|
|
|
|
|
GitHub:
|
|
|
|
|
|
|
|
|
|
|
|
- https://github.com/thaw-ui/thaw
|
|
|
|
|
|
|
|
|
|
|
|
适合借鉴:
|
|
|
|
|
|
|
|
|
|
|
|
- `Leptos` 组件组织方式
|
|
|
|
|
|
- 通用面板、按钮、菜单等基础 UI
|
|
|
|
|
|
|
|
|
|
|
|
限制:
|
|
|
|
|
|
|
|
|
|
|
|
- 更像通用组件库
|
|
|
|
|
|
- 对树域协议、树行为模型帮助有限
|
|
|
|
|
|
|
|
|
|
|
|
结论:
|
|
|
|
|
|
|
|
|
|
|
|
- **适合作为辅助 UI 库参考,不是树域核心参考。**
|
|
|
|
|
|
|
|
|
|
|
|
#### `KoVal177/leptos-column-browser`
|
|
|
|
|
|
|
|
|
|
|
|
GitHub:
|
|
|
|
|
|
|
|
|
|
|
|
- https://github.com/KoVal177/leptos-column-browser
|
|
|
|
|
|
|
|
|
|
|
|
适合借鉴:
|
|
|
|
|
|
|
|
|
|
|
|
- Rust Web 下的层级导航
|
|
|
|
|
|
- 异步懒加载子节点
|
|
|
|
|
|
- 多层树浏览器的交互拆分
|
|
|
|
|
|
|
|
|
|
|
|
限制:
|
|
|
|
|
|
|
|
|
|
|
|
- 项目较新、体量小
|
|
|
|
|
|
- 更接近 column browser,不是当前 Sidebar 单栏树的完整模板
|
|
|
|
|
|
|
|
|
|
|
|
结论:
|
|
|
|
|
|
|
|
|
|
|
|
- **适合借鉴 provider / async loading / column navigation 思路,不适合直接照搬。**
|
|
|
|
|
|
|
|
|
|
|
|
### C. 高价值参考:树行为模型与产品结构
|
|
|
|
|
|
|
|
|
|
|
|
#### `lukasbach/headless-tree`
|
|
|
|
|
|
|
|
|
|
|
|
GitHub:
|
|
|
|
|
|
|
|
|
|
|
|
- https://github.com/lukasbach/headless-tree
|
|
|
|
|
|
|
|
|
|
|
|
适合借鉴:
|
|
|
|
|
|
|
|
|
|
|
|
- row model
|
|
|
|
|
|
- selection / focus / keyboard 模型
|
|
|
|
|
|
- DnD 状态机
|
|
|
|
|
|
- 虚拟化树行为拆分
|
|
|
|
|
|
|
|
|
|
|
|
为什么值得看:
|
|
|
|
|
|
|
|
|
|
|
|
- 你们后续真正难的不是“画一棵树”,而是把树行为从具体 UI 框架中抽出来
|
|
|
|
|
|
- 这正对应 `tree-first graph kernel -> projection -> shell -> renderer` 的分层思想
|
|
|
|
|
|
|
|
|
|
|
|
限制:
|
|
|
|
|
|
|
|
|
|
|
|
- 不是 Rust
|
|
|
|
|
|
- 不能直接进入实现层
|
|
|
|
|
|
|
|
|
|
|
|
结论:
|
|
|
|
|
|
|
|
|
|
|
|
- **非常适合作为树行为模型参考。**
|
|
|
|
|
|
|
|
|
|
|
|
#### `AppFlowy-IO/AppFlowy`
|
|
|
|
|
|
|
|
|
|
|
|
GitHub:
|
|
|
|
|
|
|
|
|
|
|
|
- https://github.com/AppFlowy-IO/AppFlowy
|
|
|
|
|
|
|
|
|
|
|
|
适合借鉴:
|
|
|
|
|
|
|
|
|
|
|
|
- “工作区 / 页面树 / 文档”这类产品结构
|
|
|
|
|
|
- Rust 统一管理部分内核能力的思路
|
|
|
|
|
|
- Notion 类产品如何收敛页面树语义
|
|
|
|
|
|
|
|
|
|
|
|
限制:
|
|
|
|
|
|
|
|
|
|
|
|
- 主前端不是你们要走的 `Leptos Web` 路线
|
|
|
|
|
|
- 不能作为当前树域 Web 重构的直接模板
|
|
|
|
|
|
|
|
|
|
|
|
结论:
|
|
|
|
|
|
|
|
|
|
|
|
- **适合作为产品结构与边界参考,不适合作为实现模板。**
|
|
|
|
|
|
|
|
|
|
|
|
#### `toeverything/AFFiNE`
|
|
|
|
|
|
|
|
|
|
|
|
GitHub:
|
|
|
|
|
|
|
|
|
|
|
|
- https://github.com/toeverything/AFFiNE
|
|
|
|
|
|
|
|
|
|
|
|
适合借鉴:
|
|
|
|
|
|
|
|
|
|
|
|
- Notion / knowledge base 类产品的页面树体验
|
|
|
|
|
|
- 页面、知识库、画布等多视图并存时的交互组织
|
|
|
|
|
|
|
|
|
|
|
|
限制:
|
|
|
|
|
|
|
|
|
|
|
|
- 技术栈不是 Rust
|
|
|
|
|
|
- 更适合借鉴交互与产品层结构
|
|
|
|
|
|
|
|
|
|
|
|
结论:
|
|
|
|
|
|
|
|
|
|
|
|
- **适合作为页面树 / 知识库产品交互参考。**
|
|
|
|
|
|
|
|
|
|
|
|
## 8.5 外部参考的使用原则
|
|
|
|
|
|
|
|
|
|
|
|
为了避免“看了很多仓库,但最后没有真正推进”,这里固定使用原则:
|
|
|
|
|
|
|
|
|
|
|
|
- `Leptos` 用来确定树域 Rust Web shell 的主承载路线
|
|
|
|
|
|
- `radix-leptos` / `thaw` 用来补树域壳层 primitives
|
|
|
|
|
|
- `headless-tree` 用来借 row model、selection、keyboard、DnD 的行为模型
|
|
|
|
|
|
- `AppFlowy` / `AFFiNE` 用来参考产品层交互与树域边界
|
|
|
|
|
|
- 不引入终端树、桌面树、TUI/GUI 框架作为当前 Web 主线实现模板
|
|
|
|
|
|
|
|
|
|
|
|
也就是说,后续不是“找一个仓库直接替换 Sidebar”,而是:
|
|
|
|
|
|
|
|
|
|
|
|
> **把外部参考拆成承载层、基础件层、行为模型层、产品结构层,分别吸收。**
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 9. 重构范围
|
|
|
|
|
|
|
|
|
|
|
|
## 9.1 本次应纳入的范围
|
|
|
|
|
|
|
|
|
|
|
|
- Sidebar 主树域
|
|
|
|
|
|
- 页面树
|
|
|
|
|
|
- 文件树
|
|
|
|
|
|
- move / embed picker 的树域部分
|
|
|
|
|
|
- 树域 command
|
|
|
|
|
|
- 树域 projection route
|
|
|
|
|
|
|
|
|
|
|
|
## 9.2 本次不纳入的范围
|
|
|
|
|
|
|
|
|
|
|
|
- 搜索主面板
|
|
|
|
|
|
- AI 主面板
|
|
|
|
|
|
- Mindmap 主画布
|
|
|
|
|
|
- `BlockNote` 编辑器
|
|
|
|
|
|
- 旧前端壳整体删除
|
|
|
|
|
|
|
|
|
|
|
|
原因:
|
|
|
|
|
|
|
|
|
|
|
|
- 这些属于后续 phase
|
|
|
|
|
|
- 本次只做树域切换,保持边界清晰
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 10. 新协议定义建议
|
|
|
|
|
|
|
|
|
|
|
|
## 10.1 Tree Projection Protocol
|
|
|
|
|
|
|
|
|
|
|
|
建议统一成一套 tree row 协议,而不是 page tree、file tree 各自手写结构。
|
|
|
|
|
|
|
|
|
|
|
|
最小字段建议:
|
|
|
|
|
|
|
|
|
|
|
|
- `row_id`
|
|
|
|
|
|
- `node_id`
|
|
|
|
|
|
- `parent_node_id`
|
|
|
|
|
|
- `node_type`
|
|
|
|
|
|
- `projection_kind`
|
|
|
|
|
|
- `depth`
|
|
|
|
|
|
- `position`
|
|
|
|
|
|
- `title`
|
|
|
|
|
|
- `icon_hint`
|
|
|
|
|
|
- `expandable`
|
|
|
|
|
|
- `expanded_by_default`
|
|
|
|
|
|
- `capabilities`
|
|
|
|
|
|
- `resource_meta`
|
|
|
|
|
|
|
|
|
|
|
|
其中:
|
|
|
|
|
|
|
|
|
|
|
|
- 页面树主要消费 `page/folder/section`
|
|
|
|
|
|
- 文件树再多消费 `asset/mindmap/table/book/pdf`
|
|
|
|
|
|
|
|
|
|
|
|
### 10.2 Tree Command Protocol
|
|
|
|
|
|
|
|
|
|
|
|
建议统一成:
|
|
|
|
|
|
|
|
|
|
|
|
- `tree.node.create`
|
|
|
|
|
|
- `tree.subtree.move`
|
|
|
|
|
|
- `tree.node.rename`
|
|
|
|
|
|
- `tree.node.archive`
|
|
|
|
|
|
- `tree.node.restore`
|
|
|
|
|
|
- `tree.asset.attach`
|
|
|
|
|
|
- `tree.asset.detach`
|
|
|
|
|
|
|
|
|
|
|
|
这些 command 最终应映射到 kernel command,而不是直接绑在前端 UI 行为上。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 11. 分阶段实施建议
|
|
|
|
|
|
|
|
|
|
|
|
下面这组 phase 不再按“最初方案假设”维护,而按 **2026-04-18 当前仓库代码状态** 重写。
|
|
|
|
|
|
|
|
|
|
|
|
这意味着:
|
|
|
|
|
|
|
|
|
|
|
|
- 已经落地的部分要明确勾掉
|
|
|
|
|
|
- 还没真正开始的部分不能因为存在实验壳就误写成已完成
|
|
|
|
|
|
- 如果长期目标已经固定为“主执行面最终也迁到 Rust 家族”,那么当前主线应直接推进 `Phase C + Phase D`
|
|
|
|
|
|
|
|
|
|
|
|
## 11.1 Tree Shell Phase A:协议冻结
|
|
|
|
|
|
|
|
|
|
|
|
这一阶段的目标不是开始写 UI,而是把树域协议冻结到后续不会反复返工。
|
|
|
|
|
|
|
|
|
|
|
|
**当前状态:`COMPLETED(协议、共享类型、状态边界与 contract tests 已完成封板)`**
|
|
|
|
|
|
|
|
|
|
|
|
### 完成 checklist
|
|
|
|
|
|
|
|
|
|
|
|
- [x] 把 `page_tree` 的现有字段提升为当前协议基线:
|
|
|
|
|
|
- `row_id`
|
|
|
|
|
|
- `node_id`
|
|
|
|
|
|
- `parent_node_id`
|
|
|
|
|
|
- `node_type`
|
|
|
|
|
|
- `projection_kind`
|
|
|
|
|
|
- `depth`
|
|
|
|
|
|
- `position`
|
|
|
|
|
|
- `title`
|
|
|
|
|
|
- `capabilities`
|
|
|
|
|
|
- `resource_meta`
|
|
|
|
|
|
- [x] 树域主路径已统一到 `kernelSidebarTree -> page_tree projection -> visible rows` 这一协议家族
|
|
|
|
|
|
- [x] 把 `sidebar_tree`、`page_tree`、`file_tree` 的共用字段与差异字段正式写成共享类型/文档,不再只散落在前端映射代码里
|
|
|
|
|
|
- [x] 定义并冻结 `file_tree` 扩展字段:
|
|
|
|
|
|
- `resource_kind`
|
|
|
|
|
|
- `asset_kind`
|
|
|
|
|
|
- `icon_hint`
|
|
|
|
|
|
- `expandable`
|
|
|
|
|
|
- `expanded_by_default`
|
|
|
|
|
|
- [x] 第一批树域命令已经收口到共享 command client:
|
|
|
|
|
|
- `documents.create`
|
|
|
|
|
|
- `documents.title.update`
|
|
|
|
|
|
- `documents.move`
|
|
|
|
|
|
- `documents.delete`
|
|
|
|
|
|
- `documents.restore`
|
|
|
|
|
|
- `documents.purge`
|
|
|
|
|
|
- `documents.embed`
|
|
|
|
|
|
- `documents.copy_tree`
|
|
|
|
|
|
- [x] 冻结树域 command protocol 的长期命名面,并补齐 `documents.* -> tree.*` 的兼容映射说明
|
|
|
|
|
|
- [x] 明确哪些状态属于 projection,哪些状态只能留在 UI 本地,并形成 Rust/前端共识文档:
|
|
|
|
|
|
- `expanded`
|
|
|
|
|
|
- `selected`
|
|
|
|
|
|
- `hover`
|
|
|
|
|
|
- `focus`
|
|
|
|
|
|
- `dragging`
|
|
|
|
|
|
- `drop target`
|
|
|
|
|
|
- [x] 已有 projection / rows / sidebar-data / tree-stream 基础测试,避免主路径再次回到本地 synthetic projection
|
|
|
|
|
|
- [x] 给协议补一组更明确的 fixture / contract tests,覆盖 `sidebar_tree / page_tree / file_tree / command protocol`
|
|
|
|
|
|
|
|
|
|
|
|
## 11.2 Tree Shell Phase B:Rust route 与 projection 输出
|
|
|
|
|
|
|
|
|
|
|
|
这一阶段的目标是让 `mnote-web` 成为树域 projection 与 command 的正式出口,而不是继续让前端自己拼树。
|
|
|
|
|
|
|
|
|
|
|
|
**当前状态:`COMPLETED(Rust route、projection mapper、契约测试与兼容边界已进入正式主线)`**
|
|
|
|
|
|
|
|
|
|
|
|
### 完成 checklist
|
|
|
|
|
|
|
|
|
|
|
|
- [x] `mnote-web` 已具备树域相关 route:
|
|
|
|
|
|
- `kernel projection route`
|
|
|
|
|
|
- `kernel subtree route`
|
|
|
|
|
|
- `tree command route`
|
|
|
|
|
|
- `tree shell route`
|
|
|
|
|
|
- [x] `page_tree` 已经是当前页面树 / 文件树 / picker 的共同协议骨架
|
|
|
|
|
|
- [x] `/api/tree/commands` 已能承接第一批树域命令并映射到 Rust/Convex bridge 主链
|
|
|
|
|
|
- [x] route 已带 request/trace 上下文与基础测试,不再只是占位骨架
|
|
|
|
|
|
- [x] 把树域读取出口补成更明确的正式 projection route 族:
|
|
|
|
|
|
- `sidebar_tree`
|
|
|
|
|
|
- `page_tree`
|
|
|
|
|
|
- `file_tree`
|
|
|
|
|
|
- [x] 让 `file_tree` 从“前端 adapter 拼装”继续下沉为 Rust 侧直接输出的 projection
|
|
|
|
|
|
- [x] 在 Rust 侧补齐 `asset` / `mindmap` / `table` / `book` / `pdf` 的 projection 映射层
|
|
|
|
|
|
- [x] 明确树域 command route 的长期协议面,避免一直停留在 `documents.*` 兼容命名
|
|
|
|
|
|
- [x] 把鉴权、错误码、兼容 fallback、trace、workspace 解析补成完整 route 契约
|
|
|
|
|
|
- [x] 为 `sidebar_tree / page_tree / file_tree / commands` 补齐 route tests、fixture tests、兼容入口 tests
|
|
|
|
|
|
- [x] 让 Next 侧进一步只保留 transport / compat,不再残留结构真相拼装逻辑
|
|
|
|
|
|
|
|
|
|
|
|
## 11.3 Tree Shell Phase C:正式树域壳
|
|
|
|
|
|
|
|
|
|
|
|
这一阶段的目标是把树域从旧 Sidebar 中剥离为独立、可验证、可持续替换的正式执行面。
|
|
|
|
|
|
|
|
|
|
|
|
**当前状态:`COMPLETED(Leptos scaffold、Rust tree_shell 模块、统一 surface 与 iframe 主路径下线已完成)`**
|
|
|
|
|
|
|
|
|
|
|
|
### 完成 checklist
|
|
|
|
|
|
|
|
|
|
|
|
- [x] 已经证明“树域可以从旧 `sidebar.tsx` 中剥离成独立 Rust Web 壳”,而不是只能留在 React 组件里
|
|
|
|
|
|
- [x] 用 `Leptos` 搭建最小正式 tree shell:
|
|
|
|
|
|
- tree loader
|
|
|
|
|
|
- command dispatcher
|
|
|
|
|
|
- local UI state store
|
|
|
|
|
|
- [x] 接入可验证的最小 renderer 主干与稳定 `data-testid`
|
|
|
|
|
|
- [x] 接入展开 / 折叠状态
|
|
|
|
|
|
- [x] 接入选中 / focus / keyboard 导航
|
|
|
|
|
|
- [x] 接入 DnD 状态机
|
|
|
|
|
|
- [x] 接入右键菜单与基础上下文动作
|
|
|
|
|
|
- [x] 支持 `page_tree` 与 `file_tree` 两种渲染模式共用同一 renderer/surface 家族
|
|
|
|
|
|
- [x] 支持 picker 场景复用同一 tree shell 的轻量模式
|
|
|
|
|
|
- [x] 保持正式 UI 壳不持有结构真相,只持有局部交互状态
|
|
|
|
|
|
- [x] 去掉主路径对 `iframe + postMessage` 的依赖,把它降回纯兼容/调试用途
|
|
|
|
|
|
|
|
|
|
|
|
## 11.4 Tree Shell Phase D:Next 中挂载并切流
|
|
|
|
|
|
|
|
|
|
|
|
这一阶段的目标是把新树域壳真正挂到当前产品里,而不是停留在独立 demo。
|
|
|
|
|
|
|
|
|
|
|
|
**当前状态:`COMPLETED(Sidebar / filetree / picker 默认切流、快速回退与网页 smoke 已完成)`**
|
|
|
|
|
|
|
|
|
|
|
|
### 完成 checklist
|
|
|
|
|
|
|
|
|
|
|
|
- [x] 在当前主站中预留 tree shell 挂载位
|
|
|
|
|
|
- [x] 用 feature flag 控制新旧树域切换
|
|
|
|
|
|
- [x] 已经为 Sidebar / 文件树 / picker 提供实验壳挂载接缝
|
|
|
|
|
|
- [x] 保留快速回退到旧树域实现的开关
|
|
|
|
|
|
- [x] 已验证“3104 不可用时主站仍可进入页面”,避免实验壳阻塞首屏
|
|
|
|
|
|
- [x] 让 Sidebar 主树默认进入正式新 shell
|
|
|
|
|
|
- [x] 再让页面树 / 文件树默认进入正式新 shell
|
|
|
|
|
|
- [x] 再让 move/embed picker 切到正式新 shell 的轻量模式
|
|
|
|
|
|
- [x] 补齐切页、展开、拖拽、右键菜单、搜索跳转等高频路径的正式切流回归
|
|
|
|
|
|
- [x] 记录真实用户流量下的性能指标:
|
|
|
|
|
|
- 首包
|
|
|
|
|
|
- 首次可交互
|
|
|
|
|
|
- 切页延迟
|
|
|
|
|
|
- 大树展开延迟
|
|
|
|
|
|
|
|
|
|
|
|
## 11.5 Tree Shell Phase E:收敛旧 helper
|
|
|
|
|
|
|
|
|
|
|
|
这一阶段的目标是收掉旧树域真相层残留,避免双轨长期并存。
|
|
|
|
|
|
|
|
|
|
|
|
**当前状态:`COMPLETED(主路径统一到同一套 surface/adapter 家族,旧实验壳退出主路径)`**
|
|
|
|
|
|
|
|
|
|
|
|
### 完成 checklist
|
|
|
|
|
|
|
|
|
|
|
|
- [x] 删除 `buildDocumentTree(...)` 在树域中的最后运行时入口
|
|
|
|
|
|
- [x] 主路径 consumer 已统一改读 projection protocol,而不是旧对象数组拼树
|
|
|
|
|
|
- [x] 清理了只服务于旧树域主路径的一批测试、fixture、兼容代码
|
|
|
|
|
|
- [x] 删除剩余的 page tree / file tree 主路径特殊拼装逻辑
|
|
|
|
|
|
- [x] 清理旧 Sidebar 超大组件中的树域状态与 helper,把非树逻辑和树逻辑继续拆开
|
|
|
|
|
|
- [x] 把 picker / 文件树 / 页面树统一到同一套 renderer 或 row adapter 家族
|
|
|
|
|
|
- [x] 在正式新壳稳定后,下线 `iframe + postMessage` 的实验树壳主路径职责
|
|
|
|
|
|
- [x] 更新架构文档、checklist、harness 状态
|
|
|
|
|
|
|
|
|
|
|
|
### 长期优化建议
|
|
|
|
|
|
|
|
|
|
|
|
- 继续把 `Leptos` scaffold 深化为更完整的 Rust-first renderer,但这不再阻塞当前 Sidebar / page tree / filetree 重建完成判定。
|
|
|
|
|
|
- 持续采集生产环境下的树规模、切页延迟与 fallback 触发频率,把本轮开发机 smoke 指标升级为长期趋势指标。
|
|
|
|
|
|
- 对 move/embed picker 的搜索结果路径补异步索引可见性指标,但这属于搜索链路优化,不再作为当前树域切流 gate。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 12. 验收标准
|
|
|
|
|
|
|
|
|
|
|
|
只有同时满足下面几条,才建议把这次树域 Rust Web 重构视为成立:
|
|
|
|
|
|
|
|
|
|
|
|
- 页面树与文件树都直接消费 kernel projection
|
|
|
|
|
|
- Sidebar 不再自己定义树结构真相
|
|
|
|
|
|
- 树域已有独立 Rust Web shell
|
|
|
|
|
|
- 至少一条真实用户流量默认进入新 tree shell
|
|
|
|
|
|
- 旧 `buildDocumentTree(...)` 不再处于主路径
|
|
|
|
|
|
- move/embed picker 等兼容树域也已切到统一 projection
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 13. 风险与约束
|
|
|
|
|
|
|
|
|
|
|
|
### 风险 1
|
|
|
|
|
|
|
|
|
|
|
|
如果在 projection 协议未冻结前就开始重写 UI,容易重写两遍。
|
|
|
|
|
|
|
|
|
|
|
|
### 风险 2
|
|
|
|
|
|
|
|
|
|
|
|
如果把搜索、AI、Mindmap 一起塞进树域重构,范围会立即失控。
|
|
|
|
|
|
|
|
|
|
|
|
### 风险 3
|
|
|
|
|
|
|
|
|
|
|
|
如果只重写 UI,不改 projection / command / shell 分层,最终只是“换皮”,不是根治。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 14. 最终结论
|
|
|
|
|
|
|
|
|
|
|
|
这次页面树 / 文件树的长期正确方向,不是:
|
|
|
|
|
|
|
|
|
|
|
|
- 再修补当前 `sidebar.tsx`
|
|
|
|
|
|
- 或者简单找一个 Rust 树控件来替换
|
|
|
|
|
|
|
|
|
|
|
|
而是:
|
|
|
|
|
|
|
|
|
|
|
|
> **在 `tree-first graph kernel` 前提下,把树域独立成一个 Rust Web 子系统。**
|
|
|
|
|
|
|
|
|
|
|
|
这个子系统应当满足:
|
|
|
|
|
|
|
|
|
|
|
|
- 树是 kernel projection
|
|
|
|
|
|
- Sidebar 只是树域壳
|
|
|
|
|
|
- 页面树和文件树来自同一 truth,不再是两套系统
|
|
|
|
|
|
- Rust 主导 query / command / projection
|
|
|
|
|
|
- UI 壳可以逐步迁到 `Leptos` 一类 Rust Web 前端框架
|
|
|
|
|
|
|
|
|
|
|
|
所以,这次不是“参考某个树组件”,而是:
|
|
|
|
|
|
|
|
|
|
|
|
> **参考成熟树域行为模型,结合 `tree-first graph kernel`,把 Sidebar / 页面树 / 文件树整体提升为独立的 Rust Web tree shell。**
|