diff --git a/src/components/image-editor/ImageCanvasBasicGenerationComposerView.test.tsx b/src/components/image-editor/ImageCanvasBasicGenerationComposerView.test.tsx index 1b9739b81..abf08dfb1 100644 --- a/src/components/image-editor/ImageCanvasBasicGenerationComposerView.test.tsx +++ b/src/components/image-editor/ImageCanvasBasicGenerationComposerView.test.tsx @@ -156,6 +156,49 @@ describe('ImageCanvasBasicGenerationComposerView', () => { expect(screen.queryByText('参考图A')).toBeNull(); }); + it('removes only the selected reference when multiple references are present', () => { + const submitGeneration = vi.fn(); + render( + , + ); + + fireEvent.click(screen.getByRole('button', { name: '删除参考图B' })); + expect(screen.queryByText('参考图B')).toBeNull(); + expect(screen.getByText('参考图A')).toBeTruthy(); + expect(screen.getByText('参考图C')).toBeTruthy(); + + fireEvent.click(screen.getByRole('button', { name: '生成' })); + expect(submitGeneration).toHaveBeenCalledWith( + expect.objectContaining({ + generationReferences: [ + expect.objectContaining({ id: 'ref-a' }), + expect.objectContaining({ id: 'ref-c' }), + ], + }), + ); + }); + it('shows only current image options and opens upward option panels', () => { render(); diff --git a/src/components/image-editor/ImageCanvasEditorView.tsx b/src/components/image-editor/ImageCanvasEditorView.tsx index 3ff601c19..047f5d0fe 100644 --- a/src/components/image-editor/ImageCanvasEditorView.tsx +++ b/src/components/image-editor/ImageCanvasEditorView.tsx @@ -1666,8 +1666,14 @@ export function ImageCanvasEditorView({ return generateDialog?.mode === 'spec' ? { label: '规范参考图', - currentCount: 0, - limit: 1, + currentCount: + generateDialog.specType === 'icon' + ? 0 + : imageReferenceCount(generateDialog.generationReferences), + limit: + generateDialog.specType === 'icon' + ? 1 + : resolveDialogExtraImageReferenceLimit(generateDialog), contextId: generateDialogContextId, } : null; diff --git a/src/components/image-editor/ImageCanvasGenerationDialogModel.ts b/src/components/image-editor/ImageCanvasGenerationDialogModel.ts index 9c2bcf69e..85910c912 100644 --- a/src/components/image-editor/ImageCanvasGenerationDialogModel.ts +++ b/src/components/image-editor/ImageCanvasGenerationDialogModel.ts @@ -1017,12 +1017,22 @@ function createNormalizedGenerationDialogDraft({ characterView: getNormalizedString(sourceLayer, 'characterView'), customPrompt: getNormalizedString(sourceLayer, 'customPrompt'), }, - specReference: - resolveNormalizedReferences( - sourceLayer, - 'reference', - availableLayers, - )[0] ?? null, + ...(specType === 'icon' + ? { + specReference: + resolveNormalizedReferences( + sourceLayer, + 'reference', + availableLayers, + )[0] ?? null, + } + : { + generationReferences: resolveNormalizedReferences( + sourceLayer, + 'reference', + availableLayers, + ), + }), }, sourceLayer, ); @@ -2104,7 +2114,15 @@ export function appendGenerationReference( } return { ...resetFailedGenerationDialog(dialog), - specReference: createCanvasLayerReference(layer), + ...(dialog.specType === 'icon' || dialog.specType === undefined + ? { specReference: createCanvasLayerReference(layer) } + : { + generationReferences: appendLimitedImageReferences( + dialog.generationReferences, + [createCanvasLayerReference(layer)], + resolveDialogExtraImageReferenceLimit(dialog), + ), + }), composerOpen: true, }; } diff --git a/src/components/image-editor/ImageCanvasGenerationModel.ts b/src/components/image-editor/ImageCanvasGenerationModel.ts index 409572301..724ff72b1 100644 --- a/src/components/image-editor/ImageCanvasGenerationModel.ts +++ b/src/components/image-editor/ImageCanvasGenerationModel.ts @@ -1875,12 +1875,18 @@ export function buildSpecGenerationInputs( specType: SpecGenerationType, values: SpecFormValues, reference?: CharacterReferenceImage | null, + extraReferences: CharacterReferenceImage[] = [], ): CanvasGenerationInputs { - const references = reference - ? createGenerationInputReference('参考图', reference, { - id: 'reference', - }) - : []; + const references = [ + ...(reference ? [reference] : []), + ...extraReferences, + ].flatMap((item, index) => + createGenerationInputReference( + index === 0 ? '参考图' : `参考图${index + 1}`, + item, + { id: index === 0 ? 'reference' : `reference-${index + 1}` }, + ), + ); if (specType === 'custom') { return { version: 2, diff --git a/src/components/image-editor/ImageCanvasGenerationSubmissionModel.ts b/src/components/image-editor/ImageCanvasGenerationSubmissionModel.ts index 14edd6af1..7068dab9a 100644 --- a/src/components/image-editor/ImageCanvasGenerationSubmissionModel.ts +++ b/src/components/image-editor/ImageCanvasGenerationSubmissionModel.ts @@ -756,6 +756,11 @@ export function buildImageGenerationSubmissionPlan({ }, }; } + const specReferences = dialog.generationReferences?.length + ? dialog.generationReferences + : dialog.specReference + ? [dialog.specReference] + : []; return { kind: 'image', normalizedPrompt, @@ -763,18 +768,18 @@ export function buildImageGenerationSubmissionPlan({ prompt: buildSpecPrompt( specType, specValues, - Boolean(dialog.specReference?.src), + specReferences.some((reference) => Boolean(reference.src)), ), size: SPEC_GENERATION_SIZE, model: SPEC_GENERATION_MODEL, aspectRatio: SPEC_GENERATION_ASPECT_RATIO, imageSize: SPEC_GENERATION_IMAGE_SIZE, kind: 'spec', - ...(dialog.specReference?.src + ...(specReferences.length ? { - referenceImageSrcs: [ - resolveImageReferenceSubmissionSource(dialog.specReference), - ], + referenceImageSrcs: specReferences.map( + resolveImageReferenceSubmissionSource, + ), } : {}), }, @@ -787,7 +792,8 @@ export function buildImageGenerationSubmissionPlan({ generationInputs: buildSpecGenerationInputs( specType, specValues, - dialog.specReference, + specReferences[0], + specReferences.slice(1), ), }, }; diff --git a/src/components/image-editor/ImageCanvasSpecGenerationPanelView.tsx b/src/components/image-editor/ImageCanvasSpecGenerationPanelView.tsx index 19e960295..a06c11152 100644 --- a/src/components/image-editor/ImageCanvasSpecGenerationPanelView.tsx +++ b/src/components/image-editor/ImageCanvasSpecGenerationPanelView.tsx @@ -144,7 +144,13 @@ export function ImageCanvasSpecGenerationPanelView({ : 'spec-reference'; const reference = isUiDesignDialog ? dialog.uiDesignSpecReference - : dialog.specReference; + : dialog.specType === 'icon' + ? dialog.specReference + : null; + const extraSpecReferences = + !isUiDesignDialog && dialog.specType !== 'icon' + ? (dialog.generationReferences ?? []) + : []; const isGenerating = dialog.status === 'generating'; const isIconSpec = dialog.mode === 'spec' && dialog.specType === 'icon'; const [playSettingOptimization, setPlaySettingOptimization] = @@ -278,7 +284,7 @@ export function ImageCanvasSpecGenerationPanelView({ onPointerDown={(event) => event.stopPropagation()} >
- {isUiDesignDialog || dialog.specType ? ( + {isUiDesignDialog || dialog.specType === 'icon' ? ( ) : null} + {extraSpecReferences.map((item, index) => ( +