13 KiB
4-1 [recycle] Sidebar / 页面树 / 文件树 产品级差距分析 v1
更新时间:2026-04-17
关联文档:
/mnt/Data1T/mnote/design/04-tree-domain/process/4-sidebar-pagetree-filetree-rust-web-rebuild-v1.md/mnt/Data1T/mnote/design/01-tree-first-graph-kernel/process/1-tree-first-graph-kernel-v1.md/mnt/Data1T/mnote/design/01-tree-first-graph-kernel/process/1-1-tree-first-graph-kernel-checklist-v2.md
1. 文档目的
这份文档不回答:
- “当前新树能不能先凑合继续用”
- “再补一点样式是不是就够了”
这份文档回答的是:
当前 git 中已经接入的 Rust Web tree shell,距离“文件树对标 VS Code、页面树对标 Wolai / Notion”的产品目标还差什么,以及下一步应该如何推进。
结论先固定:
- 当前方向没有跑偏
- 当前实现仍然只是过渡 shell,不是产品级树控件
- 下一步重点不是继续修饰过渡 shell,而是进入“产品级树域控件重建”
2. 当前实现所处阶段
根据当前 git 中未提交改动,现状应被定义为:
- 已完成 tree shell 挂载位
- 已完成
mnote-web /tree路由与基本 command 回写 - 已完成 Sidebar / 文件树 / picker 的渐进切流入口
- 尚未完成产品级树交互能力重建
也就是说,当前完成的是:
- 协议验证
- 切流验证
- 最小可运行壳验证
而不是:
- VS Code 级文件树
- Wolai / Notion 级页面树
2.1 当前代码中已经成立的部分
wolai-frontend已经可以把树域挂到mnote-web tree shellmnote-web已经可以输出基础 tree projection 并承接 create / rename / move- 新旧树之间已经有 feature flag 与 fallback
对应实现可参考:
/mnt/Data1T/mnote/wolai-frontend/src/components/sidebar/sidebar.tsx/mnt/Data1T/mnote/wolai-frontend/src/components/sidebar/MnoteWebTreeShell.tsx/mnt/Data1T/mnote/rust/crates/mnote-web/src/routes/tree.rs
2.2 当前实现不能被误判为“已完成重构”的原因
当前 mnote-web tree shell 仍然具有明显过渡壳特征:
- 通过
iframe + postMessage + fallback接入主站 - 壳内 UI 仍是手写 HTML / CSS / DOM 逻辑
- 交互动作仍大量依赖
prompt/alert - 没有完成稳定的 row model / focus model / selection model / keyboard model / DnD state machine
这类实现适合做:
- 协议对齐
- route 验证
- 真机切流
不适合直接作为:
- 最终产品树控件
3. 现阶段的关键判断
3.1 方向没有错
当前路线与长期架构是一致的:
- 树真相继续下沉到 kernel / projection
- 页面树与文件树继续作为 projection family
- Sidebar 继续降级为树域承载壳
所以,“把树域逐步从旧 React 组件中剥离出来”这个方向是对的。
3.2 体验回退是阶段性真实现象
用户现在觉得新树在操作和界面上与目标产品差距很大,这个判断是正确的。
原因不是:
- 目标错了
而是:
- 当前切进去的是过渡 shell
- 旧 React 树实际上已经沉淀了一部分成熟交互
- 新 Rust Web 壳还没有把这些产品交互能力重新建起来
3.3 当前最危险的误区
当前最应该避免的,不是“改慢一点”,而是下面两个误区:
- 误区 A:把过渡 shell 继续当最终产品打磨
- 误区 B:看到效果差,就退回“继续长期维持旧树 + 新协议双轨”
正确做法是:
- 承认当前只是过渡壳
- 用它验证协议与切流
- 然后进入产品级树控件重建
4. 当前实现与目标产品的差距矩阵
4.1 文件树:目标应对标 VS Code Explorer
这里的“对标”不是抄界面,而是对标:
- 行为模型
- 信息密度
- 交互反馈
- 结构表达
当前已经具备的部分
- 已有文件树入口
- 已有页面与附件的基础层级表达
- 已有打开页面 / 打开附件的最小动作链路
- 主站旧文件树中已沉淀部分 VS Code 风格拖放语义
当前缺失的关键能力
- 缺少稳定的文件树专用 row model
- 缺少真实的
filetree模式闭环 - 缺少多选与连续选择
- 缺少键盘导航
- 缺少目录型拖放状态机
- 缺少重命名内联编辑
- 缺少右键菜单体系
- 缺少 hover 工具动作
- 缺少大树虚拟化与增量展开策略
- 缺少图标语义与资源类型区分
当前与 VS Code 的本质差距
当前新壳更像:
- “能渲染树结构的调试页”
而 VS Code Explorer 是:
- “高密度、可键盘驱动、可多选、可拖放、可重命名、可上下文操作的文件资源管理器”
所以文件树下一阶段不应再以“补几个按钮”为目标,而应以“重建 Explorer 行为模型”为目标。
4.2 页面树:目标应对标 Wolai / Notion
这里的“对标”不是纯视觉复刻,而是对标:
- 页面层级表达方式
- hover 操作节奏
- 新建 / 展开 / 拖拽 / 上下文动作的一致性
- 页面树作为知识库导航入口的轻量感
当前已经具备的部分
- 已有页面树 projection 主链
- 已有基础展开 / 新建 / 重命名 / 上下移动作
- 已有主站切流挂载位
当前缺失的关键能力
- 缺少 hover 暴露的轻量动作区
- 缺少更细的页面类型 / 状态表达
- 缺少更自然的层级拖拽交互
- 缺少键盘导航与 focus 管理
- 缺少右键菜单与上下文操作体系
- 缺少行级局部状态管理
- 缺少高密度列表的稳定渲染与滚动体验
- 缺少与搜索、跳转、最近访问状态的联动边界
当前与 Wolai / Notion 的本质差距
当前新壳更像:
- “展示树数据并支持几个命令”
而 Wolai / Notion 页面树更接近:
- “低干扰导航器 + 轻量页面管理器”
所以页面树下一阶段的重心不是“增加更多按钮”,而是:
- 让操作默认隐藏、按需显现
- 让层级结构更轻
- 让拖拽、展开、新建、上下文菜单进入一致的节奏
4.3 Sidebar:目标不是单独对标某产品,而是成为稳定壳
在长期架构中,Sidebar 的任务不是持有树真相,而是:
- 承载 projection
- 承载搜索入口
- 承载快速切换
- 承载少量工作区级操作
所以 Sidebar 的核心问题不是“左栏长什么样”,而是:
- 树域壳与主站其它能力之间的耦合是否被切干净
当前 Sidebar 仍然偏重,说明下一阶段除了树控件本身,还要继续做:
- Sidebar 壳职责收敛
- 树域与其它面板解耦
- 搜索 / AI / 树域三者的边界整理
5. 当前代码中的具体偏差
5.1 filetree 模式闭环仍不完整
当前主站已向新壳传入 mode=\"filetree\",但 Rust route 与壳内脚本对模式的识别还没有完整闭环。
这意味着当前“文件树已切到新壳”不能简单视为已经完成。
这一点必须优先修正,因为它会直接影响:
- 文件树功能判断
- 测试结果判断
- 后续重构任务拆分
5.2 新壳仍是协议验证页,不是产品树控件
当前树壳使用:
- 手写 HTML 模板
- 手写 DOM 生成树节点
- 手写按钮动作
这在协议验证阶段是合理的,但不应继续长期积累。
如果继续在这一层追加:
- hover 细节
- 菜单
- 多选
- DnD
- keyboard
最终只会把过渡壳演化成难维护的第二套前端。
5.3 旧树的成熟交互能力尚未被系统迁移
旧文件树与旧页面树中,已经沉淀出一部分成熟能力:
- 文件树的拖放反馈
- 文件树的多选与内部拖放
- 页面树的虚拟化
- 页面树的拖拽排序
这些能力现在还没有以“协议化行为模型”的方式迁移进新树域,而是仍然留在旧 React 实现里。
这意味着下一阶段不能只盯新壳,还要做一件关键工作:
- 把旧树中已经证明有效的交互经验抽象成正式产品合同
6. 下一阶段应如何指导修改
6.1 原则一:停止把过渡 shell 当最终实现打磨
接下来不应继续以如下方式推进:
- “再补几个按钮”
- “再修一版样式”
- “再把这个 iframe 页面做像一点”
这些动作只能缓解表面问题,不能得到产品级树控件。
正确方式是:
- 把当前壳明确标记为过渡验证层
- 只修协议、切流、阻塞性错误
- 不在这里继续堆复杂交互
6.2 原则二:先冻结产品交互合同,再进入 Rust Web 正式实现
下一阶段首先要做的,不是直接写更多 UI,而是冻结两份合同:
- 文件树产品交互合同
- 页面树产品交互合同
这两份合同至少应明确:
- 行模型
- 层级缩进规则
- active / selected / focused / dragging 的区别
- hover 暴露策略
- 右键菜单入口
- 键盘导航规则
- 多选规则
- 拖放语义
- 内联重命名规则
- 空白区与容器区行为
6.3 原则三:旧树不是要照抄,而是要提炼成熟行为
当前仓库里旧树实现仍然有直接参考价值:
/mnt/Data1T/mnote/wolai-frontend/src/components/sidebar/file-tree.tsx/mnt/Data1T/mnote/wolai-frontend/src/components/sidebar/private-tree.tsx
它们的价值不在于:
- 继续长期保留 React 版本
而在于:
- 可以作为“已在当前产品中验证过的交互基线”
下一阶段应从它们中提炼:
- 哪些交互是必须保留的
- 哪些只是过渡做法
- 哪些要升级成正式协议字段或 UI 状态机
6.4 原则四:文件树与页面树应共用一套树行为骨架
下一阶段不要再走两套完全独立实现。
应采用:
- 同一套 tree row model
- 同一套 selection / focus / keyboard / drag state
- 同一套 command dispatch
然后在 projection 层区分:
page_treefile_tree
这样才能保持:
- 文件树不是孤立系统
- 页面树不是孤立系统
- 两者继续服从
tree-first graph kernel
6.5 原则五:最终目标应是产品级 Rust Web tree shell,而不是长期 iframe 壳
长期上,目标应当是:
- Rust Web 正式树控件
- 直接消费 projection protocol
- 直接发 command protocol
- 主站以内嵌挂载或原生整合方式承载
而不是:
- 长期保留
iframe + postMessage + fallback作为正式方案
iframe 在当前阶段的价值是:
- 降风险切流
- 降低对主站的侵入
它不应成为最终交付形态。
7. 建议采用的参考体系
7.1 最值得参考:行为模型参考
优先级最高的不是某个“现成树组件”,而是行为模型参考。
推荐优先参考:
headless-tree
主要借鉴内容:
- row model
- selection
- focus
- keyboard
- drag and drop 状态拆分
这类参考最适合解决:
- 为什么树一旦复杂就开始失控
- 为什么文件树与页面树经常需要重复写交互
7.2 产品结构参考
推荐参考:
AppFlowyAFFiNE
主要借鉴内容:
- Sidebar 与页面树的产品层边界
- 工作区 / 页面 / 文档之间的协作关系
- 页面树如何作为知识产品的导航层
不建议直接借:
- 大量样式实现细节
- 与当前架构不一致的事实源模型
7.3 Rust Web UI 参考
推荐参考:
Leptosradix-leptosthaw
主要用途:
- 实现正式 Rust Web tree shell
- 补齐 collapsible / menu / scroll area / overlay 等 primitives
7.4 不建议作为主导参考的对象
以下可以看,但不应成为主导路线:
- 终端树组件
- 桌面 GUI 树组件
- 纯列浏览器方案
原因是它们无法直接回答当前最核心的问题:
- 如何在 Web 主站中实现产品级页面树 / 文件树
8. 下一阶段的任务拆分建议
8.1 阶段 A:修正当前过渡壳中的协议闭环问题
只处理阻塞项:
- 修正
filetree模式闭环 - 校正 projection / mode / consumer 对应关系
- 补齐最小测试
这一阶段不做:
- 大规模 UI 打磨
- 新交互堆叠
8.2 阶段 B:产出页面树 / 文件树产品交互合同
必须单独落文档,至少包含:
- 文件树对标 VS Code 的功能矩阵
- 页面树对标 Wolai / Notion 的功能矩阵
- 当前已实现 / 未实现 / 不做 的判定
- 对 projection 和 command 的新增要求
8.3 阶段 C:实现正式 tree row model 与状态骨架
这一阶段要优先完成:
- row model
- selection model
- focus model
- keyboard model
- drag state
- context menu entry model
这一层最好先独立,再挂 UI。
8.4 阶段 D:实现产品级 Rust Web tree shell
这一阶段才进入正式 UI:
- 页面树 renderer
- 文件树 renderer
- picker renderer
- 统一 shell 挂载
8.5 阶段 E:收敛旧树实现
最后再做:
- 旧文件树 helper 清理
- 旧页面树 helper 清理
- 旧 Sidebar 树域状态清理
- 旧 consumer 收口
9. 最终结论
当前实现与设计之间,不存在“方向性错误”,但存在明显的“阶段性落差”。
这个落差的本质不是:
- 少几个按钮
- 样式还不够像
而是:
- 当前完成的是树域过渡 shell
- 目标要求的是产品级树控件系统
因此,接下来应明确口径:
- 当前 git 中的新树实现,定义为过渡验证层
- 下一阶段任务,定义为产品级树域控件重建
只有这样,团队后续的修改方向才不会继续发散。