提交当前顶层 mnote Git 工作区,范围集中在 04-tree-domain 的 resource/trash/filetree 生命周期、mnote-web resource_trash 路由、Convex/Next 兼容接口、sidebar/file-tree 客户端适配、smoke 脚本与对应设计/bug 记录。 不包含被 ignore 的 design/05-editor-mainline/reference-code/leptos-tiptap 嵌套仓库改动。新增 smoke 的测试密码改为运行时读取 MNOTE_E2E_PASSWORD,避免提交明文 credential assignment。
4.3 KiB
4.3 KiB
4-28 Trash Restore Location Reveal Focus v1
状态:process 创建时间:2026-05-15 所属主线:04-tree-domain / VSCode Explorer 文件树与垃圾箱闭环 来源:
design/10-review/07-vscode-explorer-filetree-trash-gap-review.md阶段 6
1. 目标
页面进入垃圾箱前必须记录可恢复的位置快照;恢复时优先回到删除前父节点与排序位置,并在 UI 中 reveal / focus 恢复对象。若原父节点已不存在或仍在垃圾箱,应显式 fallback 到根目录并提示用户。
2. 已落地范围
documentsschema 新增restore_parent_id与restore_sort_order。documents.softDelete对页面子树写入删除前parent_id / sort_order快照。documents.restore:- 读取同 workspace 当前文档集合。
- 父节点仍存在或属于本次级联恢复子树时,恢复到原父节点。
- 父节点已不存在或仍在垃圾箱时,恢复到根目录。
- 恢复时回写
parent_id / sort_order,并对目标父级兄弟节点重新编号,避免恢复到原排序位时产生重复sort_order。 - 清空恢复位置快照。
- 返回
restore_location.parent_id / sort_order / fallback_reason。
/api/tree/commands restore读取页面 meta 时允许包含已删除页面,避免垃圾箱页面在进入 restore mutation 前被getMeta过滤成 404。restoreDocumentCommand透传恢复位置结果。- Sidebar 垃圾箱恢复后刷新数据、展开恢复父链、滚动并 focus 恢复行;发生 fallback 时提示“原父页面已不存在,已恢复到根目录”。
3. 设计口径
- 当前记录的是稳定数据位置:
parent_id / sort_order。view path / expanded path不持久化到 Convex,恢复后由 Sidebar 根据当前父链展开得到。 - 子树恢复只恢复与父节点同一
deleted_at批次的子节点,避免把更早独立删除的子页面误恢复。 - fallback 策略先固定为“恢复到根目录 + 明示提示”,不在本阶段引入位置选择弹窗。
sort_order会按当前兄弟数量 clamp;如果原位置越界,则放到可解释的最近位置。
4. 已验证
cd /mnt/Data1T/mnote/wolai-frontend
pnpm test src/lib/documents/tree-command-client.test.ts src/lib/documents/restore-location.test.ts src/components/sidebar/tree-shell-host.test.tsx src/components/sidebar/sidebar-sync.test.ts
结果:4 个测试文件通过,20 项测试通过。
补充 route 与排序回归:
cd /mnt/Data1T/mnote/wolai-frontend
pnpm test src/lib/documents/tree-command-client.test.ts src/lib/documents/restore-location.test.ts src/components/sidebar/tree-shell-host.test.tsx src/components/sidebar/sidebar-sync.test.ts src/app/api/tree/commands/route.test.ts
结果:5 个测试文件通过,32 项测试通过。
真实浏览器 smoke:
cd /mnt/Data1T/mnote/wolai-frontend
npx convex dev --once --tail-logs disable --env-file ../.env.all --run ping:ping
cd /mnt/Data1T/mnote
node scripts/task429-trash-restore-location-reveal-smoke.js
结果:通过。脚本使用一次性用户 / workspace,在 3000 主入口验证:
- 删除子页面后通过
tree.node.restore恢复,返回restore_location.parent_id为原父页面、sort_order为原排序位。 - 原排序位已被兄弟页面占用时,兄弟页面被后移,Convex 中不产生重复
sort_order。 - 当前浏览器页面不刷新,恢复后的页面行重新出现在侧边栏树中。
- 构造
restore_parent_id指向缺失父节点的历史数据,恢复后返回fallback_reason: parent_missing_or_deleted,并落到根目录。
局部 TypeScript 筛查:
cd /mnt/Data1T/mnote/wolai-frontend
pnpm exec tsc --noEmit --pretty false 2>&1 | rg "convex/documents.ts\\((160|161|162|163|164|165|166|167|168|169|170|171|172|173|174|175)"
结果:阶段 6 修改附近无新增 TypeScript 报错。全量 tsc 仍受仓库既有错误影响,未作为本阶段完成条件。
5. 待补
- React Sidebar Drawer 的恢复后 DOM focus 仍需在 React 入口可稳定渲染页面树时补浏览器证据;当前 3000 主壳 smoke 已覆盖“恢复后无需刷新可见 / reveal”,fallback 提示仍由 React Drawer 代码路径负责。
- 双浏览器 no-refresh:A 恢复页面后,B 不刷新即可看到位置变化;该项归入阶段 8 的实时刷新矩阵。