自动封面和标题更新会推进画布版本,但页面未同步,导致后续节点保存持续冲突。元数据写入返回前一版本,客户端仅在与本地版本衔接时推进版本,并与画布保存共用队列;处理结果在合并成功后才更新本地版本。视频画布导入也按节点保存、标题更新顺序执行。 验证:17 项画布能力与同步测试通过,包含封面更新后的保存、不覆盖未同步的远端改动、结果合并冲突和切换画布;TypeScript 检查通过。
41 lines
1.8 KiB
TypeScript
41 lines
1.8 KiB
TypeScript
import type { CanvasCapabilityClientCommand } from "@/lib/canvas/capabilities/client-command";
|
|
import { mergeCanvasSnapshots } from "@/lib/video-canvas/merge-snapshot";
|
|
import { useCanvasStore } from "@/store/canvas";
|
|
|
|
/** Runs after the editor has saved and while its save queue is reserved. */
|
|
export async function executeCanvasToolbarCapability(
|
|
command: CanvasCapabilityClientCommand,
|
|
) {
|
|
const projectId = command.projectId!;
|
|
const before = useCanvasStore.getState();
|
|
if (before.projectId !== projectId) throw new Error("画布已切换,请重新选择图片");
|
|
const base = JSON.stringify({ canvasData: before.getCanvasState() });
|
|
const response = await fetch(`/api/canvas/${projectId}/capabilities`, {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify(command),
|
|
});
|
|
const payload = await response.json().catch(() => ({}));
|
|
if (!response.ok || payload?.success !== true) {
|
|
throw new Error(payload?.error || "图片处理失败");
|
|
}
|
|
|
|
const projectResponse = await fetch(`/api/canvas/${projectId}`);
|
|
const result = await projectResponse.json();
|
|
if (!projectResponse.ok || !result.success || !result.data?.canvasData) {
|
|
throw new Error(result.error || "结果已生成,但画布同步失败");
|
|
}
|
|
const current = useCanvasStore.getState();
|
|
if (current.projectId !== projectId) return;
|
|
const merged = mergeCanvasSnapshots(
|
|
base,
|
|
JSON.stringify({ canvasData: current.getCanvasState() }),
|
|
JSON.stringify({ canvasData: result.data.canvasData }),
|
|
);
|
|
if (merged.conflicts.length > 0) {
|
|
throw new Error("结果已生成,但画布有冲突;请保留本地改动后刷新查看结果");
|
|
}
|
|
current.loadCanvas(JSON.parse(merged.snapshot).canvasData);
|
|
current.setCanvasRevision(String(result.data.updatedAt), String(result.data.updatedAt));
|
|
}
|