fix(canvas): 解决画布节点撤销操作后图片丢失问题
- 添加 cleanupCanvasFiles 回调函数用于清理画布资源 - 将 cleanupAssetImages 替换为 cleanupCanvasFiles 以统一资源清理逻辑 - 在节点变更和画布清空时使用新的清理函数 - 修复撤销操作后节点信息恢复但本地图片数据被清理的错误
This commit is contained in:
@@ -3,6 +3,7 @@
|
|||||||
- 画布项目导出改为下载 `.zip` 压缩包,包内包含 `projects.json` 和当前画布引用到的本地图片、视频文件,避免只导出 JSON 时丢失媒体内容。
|
- 画布项目导出改为下载 `.zip` 压缩包,包内包含 `projects.json` 和当前画布引用到的本地图片、视频文件,避免只导出 JSON 时丢失媒体内容。
|
||||||
- 画布库支持多选后一键导出多个画布项目,导出的压缩包可一次恢复多个项目。
|
- 画布库支持多选后一键导出多个画布项目,导出的压缩包可一次恢复多个项目。
|
||||||
- 画布项目导入改为读取新版 `.zip` 压缩包,会先按 `projects.json` 中的文件映射恢复图片、视频到本地存储,再插入画布项目,导入成功后仍停留在画布库。
|
- 画布项目导入改为读取新版 `.zip` 压缩包,会先按 `projects.json` 中的文件映射恢复图片、视频到本地存储,再插入画布项目,导入成功后仍停留在画布库。
|
||||||
|
- 修复删除画布图片节点或清空画布后撤销时,节点信息恢复但本地图片数据已被清理导致图片丢失的问题。
|
||||||
- “我的素材”类型筛选区右侧新增文本样式的导出素材和导入素材入口,可将全部素材导出为包含 `assets.json` 与图片、视频文件的压缩包,并从压缩包恢复素材。
|
- “我的素材”类型筛选区右侧新增文本样式的导出素材和导入素材入口,可将全部素材导出为包含 `assets.json` 与图片、视频文件的压缩包,并从压缩包恢复素材。
|
||||||
- 未登录状态下,画布右上角不再显示用户头像菜单、用户名称、算力点余额和退出登录入口,改为显示登录入口;快捷键入口仍可直接打开。
|
- 未登录状态下,画布右上角不再显示用户头像菜单、用户名称、算力点余额和退出登录入口,改为显示登录入口;快捷键入口仍可直接打开。
|
||||||
- 生图工作台的图片参数区复用画布里的紧凑版图像设置面板,尺寸、质量、生成张数的交互保持一致;工作台仍保留独立的模型选择。
|
- 生图工作台的图片参数区复用画布里的紧凑版图像设置面板,尺寸、质量、生成张数的交互保持一致;工作台仍保留独立的模型选择。
|
||||||
|
|||||||
@@ -292,6 +292,13 @@ function InfiniteCanvasPage() {
|
|||||||
[activeChatId, backgroundMode, chatSessions, showImageInfo],
|
[activeChatId, backgroundMode, chatSessions, showImageInfo],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const cleanupCanvasFiles = useCallback(
|
||||||
|
(extra?: unknown) => {
|
||||||
|
cleanupAssetImages({ extra, history: historyRef.current, lastHistory: lastHistoryRef.current });
|
||||||
|
},
|
||||||
|
[cleanupAssetImages],
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!hydrated) return;
|
if (!hydrated) return;
|
||||||
setProjectLoaded(false);
|
setProjectLoaded(false);
|
||||||
@@ -649,9 +656,9 @@ function InfiniteCanvasPage() {
|
|||||||
setPreviewNodeId((current) => (current && allIds.has(current) ? null : current));
|
setPreviewNodeId((current) => (current && allIds.has(current) ? null : current));
|
||||||
setRunningNodeId((current) => (current && allIds.has(current) ? null : current));
|
setRunningNodeId((current) => (current && allIds.has(current) ? null : current));
|
||||||
setContextMenu((current) => (current && allIds.has(current.nodeId) ? null : current));
|
setContextMenu((current) => (current && allIds.has(current.nodeId) ? null : current));
|
||||||
cleanupAssetImages({ projectId, nodes: nodesRef.current.filter((node) => !allIds.has(node.id)), chatSessions });
|
cleanupCanvasFiles({ projectId, nodes: nodesRef.current.filter((node) => !allIds.has(node.id)), chatSessions });
|
||||||
},
|
},
|
||||||
[chatSessions, cleanupAssetImages, projectId],
|
[chatSessions, cleanupCanvasFiles, projectId],
|
||||||
);
|
);
|
||||||
|
|
||||||
const deselectCanvas = useCallback(() => {
|
const deselectCanvas = useCallback(() => {
|
||||||
@@ -676,8 +683,8 @@ function InfiniteCanvasPage() {
|
|||||||
setRunningNodeId(null);
|
setRunningNodeId(null);
|
||||||
deselectCanvas();
|
deselectCanvas();
|
||||||
setClearConfirmOpen(false);
|
setClearConfirmOpen(false);
|
||||||
cleanupAssetImages({ projectId, nodes: [], chatSessions: [] });
|
cleanupCanvasFiles({ projectId, nodes: [], chatSessions: [] });
|
||||||
}, [cleanupAssetImages, deselectCanvas, projectId]);
|
}, [cleanupCanvasFiles, deselectCanvas, projectId]);
|
||||||
|
|
||||||
const duplicateNode = useCallback((nodeId: string) => {
|
const duplicateNode = useCallback((nodeId: string) => {
|
||||||
const source = nodesRef.current.find((node) => node.id === nodeId);
|
const source = nodesRef.current.find((node) => node.id === nodeId);
|
||||||
|
|||||||
Reference in New Issue
Block a user