81 lines
3.9 KiB
Markdown
81 lines
3.9 KiB
Markdown
# 4-42 [done][bug] tree move live delta sortOrder 被 SSR shell 忽略 v1
|
||||
|
|
|
|||
|
|
> 更新时间:2026-05-16
|
|||
|
|
>
|
|||
|
|
> 分类归属:
|
|||
|
|
> - `04-tree-domain/done`
|
|||
|
|
>
|
|||
|
|
> 关联文档:
|
|||
|
|
> - `/mnt/Data1T/mnote/design/10-review/process/08-kernel-architecture-next-priority-review-and-checklist.md`
|
|||
|
|
> - `/mnt/Data1T/mnote/design/03-rust-web/process/3-3-rust-web-tree-realtime-event-stream-v1.md`
|
|||
|
|
|
|||
|
|
## 1. 问题定义
|
|||
|
|
|
|||
|
|
`/api/tree/events` 的 `tree:delta move_document` 已携带 `sortOrder`,但 Rust SSR 文档 shell 在 B 端应用 live delta 时只移动到目标父节点末尾,没有按 `sortOrder` 重排直系子节点。
|
|||
|
|
|
|||
|
|
真实双浏览器 RED smoke:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
MNOTE_UI_BASE_URL=http://127.0.0.1:3000 MNOTE_AUTH_BASE_URL=http://127.0.0.1:3000 node scripts/task447-tree-move-order-dual-browser-live-smoke.js
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
失败证据:
|
|||
|
|
|
|||
|
|
- `tmp/tree-live-cache-smoke/20260516-task447-move-order/result.json`
|
|||
|
|
- RED fixture:同父级初始顺序 `A/B/C`,A 端执行 `move C -> parent=root, sortOrder=1`,预期 B 端顺序 `A/C/B`。
|
|||
|
|
- RED 结果:B 端收到 `tree:delta`、`op=move_document`、`sortOrder=1`,`liveApplied=delta` 且 `liveError=""`,但 Page Tree / File Tree DOM 顺序仍保持 `A/B/C`,直到 `waitForExpectedOrder` 超时。
|
|||
|
|
|
|||
|
|
## 2. 根因
|
|||
|
|
|
|||
|
|
`rust/crates/mnote-web/src/ssr/pages/layout.rs` 中:
|
|||
|
|
|
|||
|
|
- `applyMoveDocumentDelta(data)` 只读取 `documentId` 与 `parentId`,未读取 `sortOrder`。
|
|||
|
|
- `moveDocumentRowForMode(mode, documentId, parentId)` 无排序参数,最终固定 `targetContainer.appendChild(node)`。
|
|||
|
|
- `tree:local-command` 的 optimistic move 分支也只传 `{ documentId, parentId }`,会在本地命令成功后先把节点放到末尾。
|
|||
|
|
|
|||
|
|
事件生成链路不是根因:`tree.subtree.move` command payload、domain event `streamDelta` 与 `/api/tree/events` delta 均已携带 `sortOrder=1`。
|
|||
|
|
|
|||
|
|
## 3. 修复
|
|||
|
|
|
|||
|
|
`rust/crates/mnote-web/src/ssr/pages/layout.rs` 已补齐:
|
|||
|
|
|
|||
|
|
- `sortOrderFromDelta(data)`:兼容读取 `sortOrder` / `sort_order`。
|
|||
|
|
- `insertTreeNodeAtSortOrder(targetContainer, node, sortOrder)`:按目标父节点直系 `.tree-node` sibling index 插入,缺少排序时保持 append 行为。
|
|||
|
|
- `moveDocumentRowForMode(mode, documentId, parentId, sortOrder)`:消费排序参数。
|
|||
|
|
- `applyMoveDocumentDelta(data)`:把同一 `sortOrder` 同步应用到 Page Tree 与 File Tree。
|
|||
|
|
- `tree:local-command` move 分支:把 `body.sortOrder` 传入 `applyMoveDocumentDelta`。
|
|||
|
|
|
|||
|
|
同时补充字符串合同测试,防止后续再次丢失排序消费。
|
|||
|
|
|
|||
|
|
## 4. 验证
|
|||
|
|
|
|||
|
|
已通过:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
node --check scripts/task447-tree-move-order-dual-browser-live-smoke.js
|
|||
|
|
cargo test --manifest-path rust/Cargo.toml -p mnote-web sidebar_tree_runtime_handles_navigation_drag_and_filetree_actions -- --nocapture
|
|||
|
|
cargo test --manifest-path rust/Cargo.toml -p mnote-web tree_command_move_returns_structured_payload -- --nocapture
|
|||
|
|
cargo test --manifest-path rust/Cargo.toml -p mnote-web tree_command_response_includes_rust_artifact_plan_for_domain_event -- --nocapture
|
|||
|
|
MNOTE_UI_BASE_URL=http://127.0.0.1:3000 MNOTE_AUTH_BASE_URL=http://127.0.0.1:3000 node scripts/task447-tree-move-order-dual-browser-live-smoke.js
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
GREEN smoke 证据:
|
|||
|
|
|
|||
|
|
- `tmp/tree-live-cache-smoke/20260516-task447-move-order/result.json`
|
|||
|
|
- `tmp/tree-live-cache-smoke/20260516-task447-move-order/b-document-after-move.png`
|
|||
|
|
- `tmp/tree-live-cache-smoke/20260516-task447-move-order/b-filetree-after-move.png`
|
|||
|
|
|
|||
|
|
验证结果:
|
|||
|
|
|
|||
|
|
- B 文档页和 B File Tree 页面均收到 `/api/tree/events`。
|
|||
|
|
- `tree:delta move_document` payload 含 `sortOrder=1`。
|
|||
|
|
- B 文档页 Page Tree / File Tree direct child order 均为 `A/C/B`。
|
|||
|
|
- B File Tree 页面 Page Tree / File Tree direct child order 均为 `A/C/B`。
|
|||
|
|
- move 后 `navigationEvents=[]`,确认没有通过刷新或跳转掩盖 live order 更新。
|
|||
|
|
|
|||
|
|
## 5. 状态
|
|||
|
|
|
|||
|
|
当前状态:`done`
|
|||
|
|
|
|||
|
|
该缺陷已在真实代码中修复,并通过 Rust 合同测试与真实 3000 双浏览器 smoke 验证。
|