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

527 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 中的新树实现,定义为**过渡验证层**
- 下一阶段任务,定义为**产品级树域控件重建**
只有这样,团队后续的修改方向才不会继续发散。