fix(canvas): 预演合并 - 场景时间戳采用服务端快照,带 id 数组按条目合并

每次预演变更都会改 updatedAt,不再把它当成用户编辑冲突;带 id 的对象数组按条目合并,仅刷新场景时保留本地视口。
This commit is contained in:
ddcat666
2026-10-08 10:54:41 +08:00
parent 0907fe0e6b
commit cd4bfb9c54
3 changed files with 124 additions and 9 deletions

View File

@@ -113,6 +113,42 @@ test("automatic focus and panning do not block Agent updates or reset the local
expect(useCanvasStore.getState().projects[0].viewport).toEqual(viewport);
});
test("refresh-only Previs mutations do not conflict with an editor-only viewport change", async () => {
const scene = {
id: "scene-1",
version: 1 as const,
title: "镜头",
background: "#111111",
environmentIntensity: 0.7,
environment: { mode: "color" as const },
gridVisible: true,
objects: [],
cameras: [],
lights: [],
shots: [],
activeShotId: "shot-1",
createdAt: "2026-09-13T00:00:00Z",
updatedAt: "2026-09-13T00:00:00Z",
};
const local = { ...initial, previsScenes: [scene] };
local.remoteContentHash = await canvasContentHash(local);
const remoteWithPrevis = {
...local,
revision: 2,
previsScenes: [{ ...scene, updatedAt: "2026-09-13T12:00:00Z", objects: [{ id: "actor-1", name: "Agent 演员" }] }],
};
useCanvasStore.setState({ projects: [local] });
await initializeRemoteUserDataSession("agent-user");
const mock = spyOn(http, "get").mockResolvedValue({ project: remoteWithPrevis });
restore = () => mock.mockRestore();
const viewport = { x: -640, y: -280, k: 0.68 };
useCanvasStore.setState({ projects: [{ ...local, viewport, updatedAt: "2026-09-13T12:01:00Z" }] });
await refreshCanvasAfterAgent(local.id);
expect(useCanvasStore.getState().projects[0].viewport).toEqual(viewport);
expect(useCanvasStore.getState().projects[0].previsScenes).toEqual(remoteWithPrevis.previsScenes);
expect(useSyncProgressStore.getState().syncingProjects[local.id].phase).toBe("done");
});
test("replayed completion events do not reapply unchanged canvas nodes", async () => {
await setup();
let deliveries = 0;