fix(mnote-web): 主文档壳本地应用树命令

This commit is contained in:
lix-2026
2026-05-14 07:35:25 +08:00
parent 8f52112878
commit 2a9650d551
3 changed files with 332 additions and 13 deletions
@@ -140,16 +140,28 @@
- 手动 snapshot 绑定 workspaceId,避免跨工作区污染。
4. `wolai-frontend/src/components/sidebar/sidebar-sync.ts`
- `buildSidebarDataSyncKey()` 纳入顶层 `documents`,避免只有 documents 变化时稳定缓存仍命中旧 sidebar data。
5. `rust/crates/mnote-web/src/ssr/pages/layout.rs`
- 追加修复 Rust 3000 主文档壳路径:`tree:local-command` 现在会在 `create / purge / delete / archive` 命令成功后本地 apply Sidebar DOM。
- `create` 成功后立即插入 Page Tree 行,以及 File Tree 的 `doc:<id>` / `index:<id>` 行。
- `purge/delete/archive` 成功后立即从 Page Tree 与 File Tree 移除目标页面行。
- 命令成功后清理按钮 pending 状态,避免无整页刷新时按钮残留禁用。
2026-05-14 回归复现与补修:
- 用户复测发现 3000 主入口仍需刷新。重新用真实浏览器验证后确认:之前 `3001` Next 路径和 `/tree` debug 路由的验证不能代表当前 `mnote-web` 3000 主文档壳。
- 复现证据:旧 3000 进程为 `/mnt/Data1T/mnote/rust/target/debug/mnote-web (deleted)`;点击“新建页面”后接口返回成功并跳转到 `/documents/tree_1778714360642_10?...`,但 5 秒后 `#sidebar-tree-root` 仍不包含该 document id。
- 当前源码 3002 在补修前也复现同类问题:新建后跳转到 `/documents/tree_1778714400752_12?...`,但 Page Tree DOM 不包含当前 document id。
- 补修后已重启 3000,并在 3000 主入口完成新建/删除无刷新 smoke。
## 7. 验收标准
只有满足以下条件后才能移动到 `bugs/04-tree-domain/done/`
1. [x] 在 `http://127.0.0.1:3000/documents/<id>` 主页面壳中新建页面后,不刷新浏览器即可在 Page Tree 与 File Tree 中看到新页面。代码证据:`handleCreate()` 本地 upsert documents`localFileTreeProjection.items` 立即包含 `doc:<id>` / `index:<id>`;单测覆盖:`sidebar-local-projection.test.ts`
2. [x] 在主页面壳中删除页面后,不刷新浏览器即可在 Page Tree 与 File Tree 中看到目标页面消失。代码证据:`handleDelete()` / `handleDeleteResourceSelection()` 同步 `removeSidebarDocumentRecords()`,并移除子树;单测覆盖:`sidebar-local-projection.test.ts``sidebar-delete-preflight-source.test.ts`
1. [x] 在 `http://127.0.0.1:3000/documents/<id>` 主页面壳中新建页面后,不刷新浏览器即可在 Page Tree 与 File Tree 中看到新页面。代码证据:React Sidebar 路径由 `handleCreate()` 本地 upsert documentsRust 3000 主文档壳由 `tree:local-command` 本地插入 Page Tree 行与 File Tree `doc:<id>` / `index:<id>`;单测覆盖:`sidebar-local-projection.test.ts`Rust runtime 覆盖:`cargo test -p mnote-web sidebar_tree_runtime -- --nocapture`
2. [x] 在主页面壳中删除页面后,不刷新浏览器即可在 Page Tree 与 File Tree 中看到目标页面消失。代码证据:React Sidebar 路径由 `handleDelete()` / `handleDeleteResourceSelection()` 同步 `removeSidebarDocumentRecords()`Rust 3000 主文档壳由 `tree:local-command``purge/delete/archive` 成功后调用 remove delta 本地移除;单测覆盖:`sidebar-local-projection.test.ts``sidebar-delete-preflight-source.test.ts`Rust runtime 覆盖:`cargo test -p mnote-web sidebar_tree_runtime -- --nocapture`
3. [x] 在主页面壳中新建 mindmap 后,不刷新浏览器即可在 File Tree 中看到对应 `mindmap-<id>.json` 行。代码证据:`emitAssetsChanged(asset)` 已进入本地 `mindmapAssets``localFileTreeProjection` 用本地 mindmap assets 重建 asset row;单测覆盖:`sidebar-local-projection.test.ts`
4. [x] 上述三条路径均不得依赖 `window.location.reload()` 或顶层 navigation。代码证据:本轮没有新增 reloadcreate/delete 以本地 state/projection apply 为主,显式 refetch 仅作 snapshot 校准。
5. [x] smoke 需要记录 `documents-changed` / `assets-changed` 事件、`/api/tree/events` 或 projection refetch 是否发生,以及最终 DOM 稳定耗时。已补真实浏览器 smoke:`tmp/task426-sidebar-main-no-reload-smoke/result.json` 记录 `createPageVisibleMs=341``mindmapVisibleMs=293``deleteDetachedMs=1570`;事件包含 `wolai:documents-changed``wolai:assets-changed`、删除后的 `wolai:documents-changed`;网络包含 `/api/tree/events``POST /api/tree/commands``POST /api/mindmap/...` 与显式 `/api/sidebar?workspaceId=...` refetch。代码级测试同时覆盖:`sidebar-delete-preflight-source.test.ts` 锁定 create/delete 事件与本地 documents apply`use-sidebar-data.test.tsx` 锁定 Convex live 显式 refetch 会真实拉 `/api/sidebar`
5. [x] smoke 需要记录事件或本地 apply 标记、最终 DOM 状态与相关网络请求。React Sidebar 路径保留 `tmp/task426-sidebar-main-no-reload-smoke/result.json` 作为 Next/3001 与 mindmap asset 证据;Rust 3000 主文档壳新增 `tmp/task426-mnote-web-main-no-reload-smoke/result.json`,覆盖真实 3000 页面新建/删除无刷新 DOM 结果。代码级测试同时覆盖:`sidebar-delete-preflight-source.test.ts` 锁定 create/delete 事件与本地 documents apply`use-sidebar-data.test.tsx` 锁定 Convex live 显式 refetch 会真实拉 `/api/sidebar``cargo test -p mnote-web sidebar_tree_runtime -- --nocapture` 锁定 Rust 主文档壳 runtime 基础行为
6. [x] 修复后补测试,防止 `sidebarQuery.refetch()` 在 Convex live 模式下继续作为空操作吞掉显式刷新请求。测试覆盖:`use-sidebar-data.test.tsx`
## 8. 验证记录
@@ -174,22 +186,34 @@ pnpm exec eslint src/components/sidebar/sidebar-sync.ts src/components/sidebar/s
```bash
cd /mnt/Data1T/mnote
MNOTE_UI_BASE_URL=http://127.0.0.1:3001 node <task426-sidebar-main-no-reload-smoke>
MNOTE_UI_BASE_URL=http://127.0.0.1:3000 node scripts/task426-mnote-web-main-no-reload-smoke.js
```
结果文件:`tmp/task426-sidebar-main-no-reload-smoke/result.json`
结果文件:`tmp/task426-mnote-web-main-no-reload-smoke/result.json`
关键结果:
- `ok=true`
- `createPageVisibleMs=341`
- `mindmapVisibleMs=293`
- `deleteDetachedMs=1570`
- 删除确认文案:`确认删除选中的 1 个页面(删除到垃圾桶) 吗?`
- `beforeDeleteState.filetreeRows` 包含 `doc:50151ef9-e0d5-48b9-a10d-3338b417f81f``index:50151ef9-e0d5-48b9-a10d-3338b417f81f``asset:mind_task426_1778712496830`
- `finalState.filetreeRows` 不再包含上述 document / mindmap asset row
- `finalState.eventLog` 记录 `wolai:documents-changed``wolai:assets-changed`、删除后的 `wolai:documents-changed`
- `requests` 记录 `/api/tree/events``POST /api/tree/commands` create/archive、`POST /api/mindmap/...` createOnly、`GET /api/sidebar?workspaceId=...`
- `baseUrl=http://127.0.0.1:3000`
- `createdDocumentId=tree_1778715292685_1`
- 新建后:`localApplied=create``pageRows=1``fileRows=["doc:tree_1778715292685_1","index:tree_1778715292685_1"]`
- 删除后:`localApplied=remove``pageRows=0``fileRows=[]`
- `requests` 包含两次 `POST /api/tree/commands`,无浏览器刷新依赖
- 结果文件:`tmp/task426-mnote-web-main-no-reload-smoke/result.json`
补充对比:
```bash
cd /mnt/Data1T/mnote
MNOTE_UI_BASE_URL=http://127.0.0.1:3002 node scripts/task426-mnote-web-main-no-reload-smoke.js
```
结果:`ok=true`;新建后 `createdDocumentId=tree_1778714773920_2`Page Tree 与 File Tree 立即出现;删除后两处立即消失。
历史说明:
- 旧记录中的 `MNOTE_UI_BASE_URL=http://127.0.0.1:3001 node <task426-sidebar-main-no-reload-smoke>` 只验证了 Next/React Sidebar 路径,不能作为 Rust 3000 主入口验收依据。
- `/tree` debug route smoke 也不能替代 `/documents/<id>` 主文档壳验收,因为当前默认配置下 debug shell route 可能未启用。
已尝试: