Files
mnote/design/old/04-tree-domain/process/4-1-sidebar-pagetree-filetree-product-gap-analysis-v1.md
T

13 KiB
Raw Blame History

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 shell
  • mnote-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_tree
  • file_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 产品结构参考

推荐参考:

  • AppFlowy
  • AFFiNE

主要借鉴内容:

  • Sidebar 与页面树的产品层边界
  • 工作区 / 页面 / 文档之间的协作关系
  • 页面树如何作为知识产品的导航层

不建议直接借:

  • 大量样式实现细节
  • 与当前架构不一致的事实源模型

7.3 Rust Web UI 参考

推荐参考:

  • Leptos
  • radix-leptos
  • thaw

主要用途:

  • 实现正式 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 中的新树实现,定义为过渡验证层
  • 下一阶段任务,定义为产品级树域控件重建

只有这样,团队后续的修改方向才不会继续发散。