From b6f0ab48d831c1bf95673d871bc8adf520f3cfbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=BE=B7=E5=AE=87?= Date: Wed, 5 Aug 2026 13:26:02 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=B6=E5=8F=A3=E8=A7=92=E8=89=B2=E5=8A=A8?= =?UTF-8?q?=E4=BD=9C=E6=8F=90=E4=BA=A4=E5=89=8D=E6=A0=A1=E9=AA=8C=E5=BC=82?= =?UTF-8?q?=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将角色动作提交计划构建纳入失败状态处理 仅在计划校验通过后切换生成中状态 补充损坏动作来源的用户错误回归测试 --- ...anvasGenerationSubmissionWorkflow.test.tsx | 35 ++++++++++ ...ImageCanvasGenerationSubmissionWorkflow.ts | 66 +++++++++---------- 2 files changed, 68 insertions(+), 33 deletions(-) diff --git a/src/components/image-editor/useImageCanvasGenerationSubmissionWorkflow.test.tsx b/src/components/image-editor/useImageCanvasGenerationSubmissionWorkflow.test.tsx index 9ce92fd4f..e5853d598 100644 --- a/src/components/image-editor/useImageCanvasGenerationSubmissionWorkflow.test.tsx +++ b/src/components/image-editor/useImageCanvasGenerationSubmissionWorkflow.test.tsx @@ -2976,6 +2976,41 @@ describe('useImageCanvasGenerationSubmissionWorkflow', () => { expect(generateEditorCharacterAnimationMock).not.toHaveBeenCalled(); }); + it('reports stale character animation source validation failures', async () => { + render( + , + ); + + await act(async () => { + fireEvent.click(screen.getByRole('button', { name: '提交角色动画' })); + }); + + await waitFor(() => { + expect(screen.getByTestId('character-animation').textContent).toBe( + 'character-layer:failed:跑步:角色动作缺少正式序列首帧,无法继续生成。:-', + ); + }); + expect(generateEditorCharacterAnimationMock).not.toHaveBeenCalled(); + }); + it('creates an action layer for dialog-driven character animation submissions', async () => { generateEditorCharacterAnimationMock.mockResolvedValueOnce({ taskId: 'animation-task-dialog', diff --git a/src/components/image-editor/useImageCanvasGenerationSubmissionWorkflow.ts b/src/components/image-editor/useImageCanvasGenerationSubmissionWorkflow.ts index adf9b5253..2862f76bd 100644 --- a/src/components/image-editor/useImageCanvasGenerationSubmissionWorkflow.ts +++ b/src/components/image-editor/useImageCanvasGenerationSubmissionWorkflow.ts @@ -2166,40 +2166,39 @@ export function useImageCanvasGenerationSubmissionWorkflow({ ) { return; } - const submissionPlan = buildCharacterAnimationSubmissionPlan({ - panel: characterAnimationPanel, - sourceLayer: characterAnimationSourceLayer, - }); const canvasDialog = characterAnimationDialog; - if (canvasDialog?.mode === 'character-animation') { - updateCanvasGenerationDialogById(canvasDialog.id, (currentDialog) => ({ - ...currentDialog, - prompt: submissionPlan.promptText, - characterAnimationResolution: characterAnimationPanel.resolution, - characterAnimationRatio: characterAnimationPanel.ratio, - characterAnimationFrameCount: characterAnimationPanel.frameCount, - characterAnimationDurationSeconds: - characterAnimationPanel.durationSeconds, - assetLabel: submissionPlan.resultTitle, - characterAnimationResult: undefined, - status: 'generating', - composerOpen: false, - errorMessage: undefined, - })); - } - const nextPanel = { - ...characterAnimationPanel, - promptText: submissionPlan.promptText, - assetLabel: submissionPlan.resultTitle, - status: 'generating' as const, - errorMessage: undefined, - result: undefined, - }; - if (!canvasDialog) { - setCharacterAnimationPanel(nextPanel); - } - try { + const submissionPlan = buildCharacterAnimationSubmissionPlan({ + panel: characterAnimationPanel, + sourceLayer: characterAnimationSourceLayer, + }); + if (canvasDialog?.mode === 'character-animation') { + updateCanvasGenerationDialogById(canvasDialog.id, (currentDialog) => ({ + ...currentDialog, + prompt: submissionPlan.promptText, + characterAnimationResolution: characterAnimationPanel.resolution, + characterAnimationRatio: characterAnimationPanel.ratio, + characterAnimationFrameCount: characterAnimationPanel.frameCount, + characterAnimationDurationSeconds: + characterAnimationPanel.durationSeconds, + assetLabel: submissionPlan.resultTitle, + characterAnimationResult: undefined, + status: 'generating', + composerOpen: false, + errorMessage: undefined, + })); + } + const nextPanel = { + ...characterAnimationPanel, + promptText: submissionPlan.promptText, + assetLabel: submissionPlan.resultTitle, + status: 'generating' as const, + errorMessage: undefined, + result: undefined, + }; + if (!canvasDialog) { + setCharacterAnimationPanel(nextPanel); + } const generationInputs = buildCharacterAnimationGenerationInputs( submissionPlan.promptText, characterAnimationSourceLayer, @@ -2283,7 +2282,7 @@ export function useImageCanvasGenerationSubmissionWorkflow({ if (canvasDialog) { updateCanvasGenerationDialogById(canvasDialog.id, (currentDialog) => ({ ...currentDialog, - prompt: submissionPlan.promptText, + prompt: characterAnimationPanel.promptText.trim(), characterAnimationResolution: characterAnimationPanel.resolution, characterAnimationRatio: characterAnimationPanel.ratio, characterAnimationFrameCount: characterAnimationPanel.frameCount, @@ -2302,6 +2301,7 @@ export function useImageCanvasGenerationSubmissionWorkflow({ currentPanel ? { ...currentPanel, + promptText: characterAnimationPanel.promptText.trim(), status: 'failed', errorMessage: resolveImageGenerationErrorMessage( error,