From 4d1c9d9b1b110b760ae81204eb84112fde10f40b Mon Sep 17 00:00:00 2001 From: suzmii Date: Sat, 15 Aug 2026 17:02:52 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=B6=E7=B4=A7=E5=BA=8F=E5=88=97=E5=B8=A7?= =?UTF-8?q?=E9=A2=84=E8=A7=88=E6=81=A2=E5=A4=8D=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit taskId 缺失时不恢复关联预览视频 补充序列帧与预览任务标识缺失的恢复测试 --- .../ImageCanvasEditorModel.test.ts | 43 +++++++++++++++++++ .../image-editor/ImageCanvasEditorModel.ts | 4 +- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/src/components/image-editor/ImageCanvasEditorModel.test.ts b/src/components/image-editor/ImageCanvasEditorModel.test.ts index 015fef6cb..259731a6f 100644 --- a/src/components/image-editor/ImageCanvasEditorModel.test.ts +++ b/src/components/image-editor/ImageCanvasEditorModel.test.ts @@ -1398,6 +1398,49 @@ describe('ImageCanvasEditorModel', () => { }); }); + it('does not hydrate a preview video when either task id is missing', () => { + const frames = [ + { imageSrc: '/generated/sequence/frame-1.png', width: 480, height: 480 }, + { imageSrc: '/generated/sequence/frame-2.png', width: 480, height: 480 }, + ]; + + for (const [animationTaskId, previewTaskId] of [ + [undefined, 'animation-task-1'], + ['animation-task-1', undefined], + [undefined, undefined], + ] as const) { + const sequenceResource = { + imageSrc: frames[0]!.imageSrc, + assetKind: 'character-animation' as const, + imageSequenceFrames: frames, + imageSequenceDurationMs: 4_000, + ...(animationTaskId ? { taskId: animationTaskId } : {}), + sourceResourceId: 'resource-preview-video', + }; + const previewResource = { + imageSrc: '/generated/video/preview.mp4', + objectKey: 'generated/video/preview.mp4', + assetKind: 'video' as const, + ...(previewTaskId ? { taskId: previewTaskId } : {}), + }; + + const resources: Parameters[1] = new Map(); + resources.set('resource-sequence', sequenceResource); + resources.set('resource-preview-video', previewResource); + const hydrated = hydrateLayer( + { + layerId: 'layer-sequence', + resourceId: 'resource-sequence', + title: '角色动作', + sourceType: 'generated', + }, + resources, + ); + + expect(hydrated?.previewVideoPath).toBeNull(); + } + }); + it('does not hydrate an older action reference as a generated preview video', () => { const frames = [ { imageSrc: '/generated/sequence/frame-1.png', width: 480, height: 480 }, diff --git a/src/components/image-editor/ImageCanvasEditorModel.ts b/src/components/image-editor/ImageCanvasEditorModel.ts index a5813b635..1bc8412df 100644 --- a/src/components/image-editor/ImageCanvasEditorModel.ts +++ b/src/components/image-editor/ImageCanvasEditorModel.ts @@ -1450,8 +1450,8 @@ export function hydrateLayer( const animationTaskId = stringOrNull(resource?.taskId); const previewTaskId = stringOrNull(previewResource.taskId); if ( - animationTaskId && - previewTaskId && + !animationTaskId || + !previewTaskId || animationTaskId !== previewTaskId ) { return undefined;