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

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