fix: persist canvas deletions before refresh
This commit is contained in:
parent
d68928233a
commit
ddadac3a67
@ -133,7 +133,7 @@ export default function CanvasEditorPage({ params }: PageProps) {
|
||||
const [negativePrompt, setNegativePrompt] = useState("");
|
||||
const [aspectRatio, setAspectRatio] = useState("1:1");
|
||||
const [imageCount, setImageCount] = useState(1);
|
||||
const previousNodeCountRef = useRef(0);
|
||||
const previousNodeIdsRef = useRef<Set<string>>(new Set());
|
||||
|
||||
// 获取选中的图片节点
|
||||
const selectedImageNode = selectedNodeIds.length === 1
|
||||
@ -174,15 +174,26 @@ export default function CanvasEditorPage({ params }: PageProps) {
|
||||
loadProject();
|
||||
}, [id]); // 只依赖 id,使用 getState() 直接调用 store actions
|
||||
|
||||
const persistCanvasState = useCallback(
|
||||
async (reason: "autosave" | "delete" | "beforeunload") => {
|
||||
const canvasData = getCanvasState();
|
||||
const result = await canvasService.saveCanvasState(id, canvasData);
|
||||
if (!result.success) {
|
||||
console.error(`[Canvas] ${reason} save failed:`, result.error);
|
||||
}
|
||||
return result.success;
|
||||
},
|
||||
[getCanvasState, id]
|
||||
);
|
||||
|
||||
// 自动保存逻辑
|
||||
useEffect(() => {
|
||||
if (isLoading) return;
|
||||
|
||||
const saveTimer = setTimeout(async () => {
|
||||
setIsSaving(true);
|
||||
const canvasData = getCanvasState();
|
||||
try {
|
||||
await canvasService.saveCanvasState(id, canvasData);
|
||||
await persistCanvasState("autosave");
|
||||
} catch (error) {
|
||||
console.error("Auto save failed:", error);
|
||||
}
|
||||
@ -190,24 +201,30 @@ export default function CanvasEditorPage({ params }: PageProps) {
|
||||
}, 3000); // 3秒自动保存
|
||||
|
||||
return () => clearTimeout(saveTimer);
|
||||
}, [nodes, id, isLoading, getCanvasState]);
|
||||
}, [nodes, isLoading, persistCanvasState]);
|
||||
|
||||
// 删除节点时立即保存,避免用户立刻刷新后看到被删除节点又出现
|
||||
// 删除节点时立即保存(按节点ID差集检测),避免删除后快速刷新被回滚
|
||||
useEffect(() => {
|
||||
if (isLoading) {
|
||||
previousNodeCountRef.current = nodes.length;
|
||||
previousNodeIdsRef.current = new Set(nodes.map((node) => node.id));
|
||||
return;
|
||||
}
|
||||
|
||||
const previousCount = previousNodeCountRef.current;
|
||||
const currentCount = nodes.length;
|
||||
previousNodeCountRef.current = currentCount;
|
||||
const previousIds = previousNodeIdsRef.current;
|
||||
const currentIds = new Set(nodes.map((node) => node.id));
|
||||
const removedIds: string[] = [];
|
||||
previousIds.forEach((nodeId) => {
|
||||
if (!currentIds.has(nodeId)) {
|
||||
removedIds.push(nodeId);
|
||||
}
|
||||
});
|
||||
previousNodeIdsRef.current = currentIds;
|
||||
|
||||
if (previousCount > currentCount) {
|
||||
if (removedIds.length > 0) {
|
||||
const persistAfterDelete = async () => {
|
||||
setIsSaving(true);
|
||||
try {
|
||||
await canvasService.saveCanvasState(id, getCanvasState());
|
||||
await persistCanvasState("delete");
|
||||
} catch (error) {
|
||||
console.error("Delete immediate save failed:", error);
|
||||
}
|
||||
@ -215,7 +232,33 @@ export default function CanvasEditorPage({ params }: PageProps) {
|
||||
};
|
||||
void persistAfterDelete();
|
||||
}
|
||||
}, [nodes.length, id, isLoading, getCanvasState]);
|
||||
}, [nodes, isLoading, persistCanvasState]);
|
||||
|
||||
// 页面关闭/刷新前尝试做一次 keepalive 保存,降低“刚删就刷新”回滚概率
|
||||
useEffect(() => {
|
||||
if (isLoading) return;
|
||||
|
||||
const handleBeforeUnload = () => {
|
||||
try {
|
||||
const canvasData = getCanvasState();
|
||||
void fetch(`/api/canvas/${id}`, {
|
||||
method: "PUT",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ canvasData }),
|
||||
keepalive: true,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("[Canvas] beforeunload save failed:", error);
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener("beforeunload", handleBeforeUnload);
|
||||
window.addEventListener("pagehide", handleBeforeUnload);
|
||||
return () => {
|
||||
window.removeEventListener("beforeunload", handleBeforeUnload);
|
||||
window.removeEventListener("pagehide", handleBeforeUnload);
|
||||
};
|
||||
}, [getCanvasState, id, isLoading]);
|
||||
|
||||
// 智能命名与缩略图逻辑
|
||||
useEffect(() => {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user