# 4-37 [done] 垃圾箱改为居中弹窗工作台 v1 > 更新时间:2026-05-15 > > 背景: > - 用户建议:垃圾箱应做成弹窗,而不是单一页面。 > - 当前 `/trash` 是完整页面入口;在本地文件夹 / 云空间切换异常时,用户会通过垃圾箱“找回”原空间页面,这进一步暴露垃圾箱作为导航页面会改变当前工作区上下文。 ## 1. 设计目标 把垃圾箱从“离开当前工作区的独立页面”逐步改为“当前工作区内的居中弹窗工作台”。 弹窗形态以 Wolai 居中对话框为准:遮罩覆盖页面,工作台面板在视口中心显示,左右和上下都保留留白;不要做成靠右侧贴边的 drawer / 抽屉。 目标体验: - 用户点击左下角“垃圾箱”时,不离开当前页面和当前文件树上下文。 - 垃圾箱以居中 modal 打开,不贴右侧边缘,不改变当前 URL。 - 弹窗内展示页面垃圾箱与资源垃圾箱。 - 恢复、彻底删除、清空操作完成后,当前 Sidebar / File Tree / Page Tree 实时同步。 - 关闭弹窗后,用户回到原页面、原选中 row、原滚动位置。 ## 2. 非目标 - 本稿不改变删除、恢复、彻底删除的底层命令语义。 - 本稿不一次性废弃 `/trash`;`/trash` 可作为兼容、直接链接和测试入口保留。 - 本稿不扩大到全局搜索、模板中心等其它 footer 入口。 ## 3. 最小实现切片 P0:入口形态 - 左下角“垃圾箱”从普通导航改为打开弹窗。 - 弹窗复用现有 `mnote-trash-workbench` DOM 与 API。 - 打开弹窗不改变当前 URL;如需要可用 `?trash=1` 或 history state,但默认不跳整页。 P1:上下文保持 - 弹窗打开前记录当前 `sourceKind`、`workspaceId`、`rootUri`、active row、scrollTop。 - 关闭弹窗后恢复原 File Tree / Page Tree 视图状态。 - 本地文件夹场景下,垃圾箱只展示本地 `.mnote/trash` 能力;Convex 云空间展示 Convex trash。 P2:实时同步 - 页面 restore / purge / empty 后,当前 Sidebar 通过 tree event 或本地 apply 更新。 - 资源 restore / purge / empty 后,File Tree 对应资源 row 同步恢复或消失。 ## 4. 验收标准 - 点击“垃圾箱”不会离开当前文档 URL。 - 垃圾箱面板在视口中心显示,左右居中偏差不超过 8px,并保留可见的上下留白。 - 弹窗内能恢复页面、彻底删除页面、清空页面垃圾箱。 - 弹窗内能恢复/彻底删除/清空附件、mindmap、table 等资源。 - 关闭弹窗后,原页面仍打开,File Tree 滚动位置和选中 row 不被无关重置。 - `/trash` 兼容入口仍可访问并通过现有 smoke。 ## 5. 当前状态 当前状态:`done` 2026-05-15 已完成最小可用实现: - 左下角“垃圾箱”入口保留 `href="/trash"` 作为兼容 fallback,但主壳点击会拦截为 `data-mnote-action="open-trash-modal"`。 - `PageLayout` 新增垃圾箱 modal:打开后 fetch `/trash?workspaceId=...`,解析并挂载现有 `mnote-trash-workbench`,不改变当前 URL。 - modal 关闭时会关闭 workbench EventSource,并恢复 File Tree `scrollTop`;不改变原页面、active row 或当前文档 URL。 - `/trash` 独立页面继续保留,作为直接链接、兼容入口和现有 smoke 的验证对象。 - 本地文件夹上下文下,modal 保持在本地 source,不跳回 Convex;当前先展示 `.mnote/trash` / `trash-index.json` 的本地垃圾箱说明,后续如需完整 local trash list 可继续扩展。 - 2026-05-15 根据用户参考图修正 modal 形态:从右侧 drawer 改为居中对话框,并在 smoke 中增加居中与上下留白断言,避免后续重复退回侧栏抽屉形态。 代码落点: - `rust/crates/mnote-web/src/workspace_shell.rs` - `rust/crates/mnote-web/src/ssr/pages/layout.rs` - `rust/crates/mnote-web/src/ssr/styles.rs` - `rust/crates/mnote-web/src/routes/gateway.rs` - `scripts/task442-trash-modal-workbench-smoke.js` 已通过验证: ```bash cargo test --manifest-path rust/Cargo.toml -p mnote-web sidebar_tree_runtime -- --nocapture cargo test --manifest-path rust/Cargo.toml -p mnote-web workspace_shell -- --nocapture cargo test --manifest-path rust/Cargo.toml -p mnote-web trash_entry -- --nocapture MNOTE_UI_BASE_URL=http://127.0.0.1:3428 node scripts/task442-trash-modal-workbench-smoke.js MNOTE_UI_BASE_URL=http://127.0.0.1:3428 node scripts/task432-filetree-trash-page-dual-browser-no-refresh-smoke.js ``` 结果文件: - `tmp/task442-trash-modal-workbench-smoke/result.json` - `tmp/task432-filetree-trash-page-dual-browser-no-refresh-smoke/result.json`