From 4a12b090b54db9b45ba3bbd3ce3eef5ef5266fca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=94=E9=A6=99=E4=B8=B8=E5=AD=90?= <15518898337@163.com> Date: Wed, 24 Jun 2026 16:19:01 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=90=84=E5=85=83=E7=B4=A0?= =?UTF-8?q?=E8=BE=93=E5=85=A5=E6=A1=86=E4=B8=AD=E7=9A=84=E5=90=AF=E5=8F=91?= =?UTF-8?q?=E6=8F=90=E7=A4=BA=E6=96=87=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 音效、背景音乐和图标素材改为空值加灰色启发提示。 角色规范、图标规范和自定义规范输入框补充灰色启发提示。 同步更新相关前端组件测试。 --- .../ImageCanvasGenerationComposerView.tsx | 4 +- .../ImageCanvasGenerationDialogModel.test.ts | 39 +++++++++++------ .../ImageCanvasGenerationDialogModel.ts | 24 ++++++----- ...CanvasIconSpritesheetComposerView.test.tsx | 12 ++++++ ...ImageCanvasIconSpritesheetComposerView.tsx | 5 +-- ...mageCanvasSpecGenerationPanelView.test.tsx | 42 +++++++++++++++++++ .../ImageCanvasSpecGenerationPanelView.tsx | 16 +++++++ src/index.css | 8 ++++ 8 files changed, 122 insertions(+), 28 deletions(-) diff --git a/src/components/image-editor/ImageCanvasGenerationComposerView.tsx b/src/components/image-editor/ImageCanvasGenerationComposerView.tsx index d7573c6ed..c0753550c 100644 --- a/src/components/image-editor/ImageCanvasGenerationComposerView.tsx +++ b/src/components/image-editor/ImageCanvasGenerationComposerView.tsx @@ -779,8 +779,8 @@ function ImageCanvasAudioGenerationComposerView({ disabled={isGenerating} placeholder={ isSoundEffect - ? '描述需要生成的游戏音效' - : '描述需要生成的游戏背景音乐' + ? '你希望生成什么音效?' + : '你希望生成什么音乐?' } size="sm" density="compact" diff --git a/src/components/image-editor/ImageCanvasGenerationDialogModel.test.ts b/src/components/image-editor/ImageCanvasGenerationDialogModel.test.ts index e40487f25..6eb956973 100644 --- a/src/components/image-editor/ImageCanvasGenerationDialogModel.test.ts +++ b/src/components/image-editor/ImageCanvasGenerationDialogModel.test.ts @@ -74,6 +74,28 @@ describe('ImageCanvasGenerationDialogModel', () => { originalHeight: 1024, }, }); + expect( + createSpecDialogDraft({ canvasSize, viewport, specType: 'character' }), + ).toMatchObject({ + mode: 'spec', + specType: 'character', + specValues: { + playSetting: '', + artStyle: '', + bodyRatio: '3', + }, + }); + expect( + createSpecDialogDraft({ canvasSize, viewport, specType: 'ui' }), + ).toMatchObject({ + mode: 'spec', + specType: 'ui', + specValues: { + playSetting: '', + artStyle: '', + bodyRatio: '3', + }, + }); expect( createSpecDialogDraft({ canvasSize, viewport, specType: 'icon' }), ).toMatchObject({ @@ -153,16 +175,9 @@ describe('ImageCanvasGenerationDialogModel', () => { imageModel: 'unknown-model', aspectRatio: '1:1', imageSize: '1K', - prompt: '返回按钮\n设置按钮\n下一关按钮\n提示按钮\n原图按钮\n冻结按钮', + prompt: '', iconSpecReference: null, - iconDescriptions: [ - '返回按钮', - '设置按钮', - '下一关按钮', - '提示按钮', - '原图按钮', - '冻结按钮', - ], + iconDescriptions: [], placeholder: { x: 300, y: 180, @@ -228,8 +243,7 @@ describe('ImageCanvasGenerationDialogModel', () => { expect(createSoundEffectGenerationDialogDraft({ canvasSize, viewport })) .toMatchObject({ mode: 'audio-sound-effect', - prompt: - '短促清脆的游戏交互音效,带轻微闪光质感,干净收尾,适合按钮确认或收集奖励。', + prompt: '', status: 'idle', composerOpen: true, soundModel: 'audio1.0', @@ -246,8 +260,7 @@ describe('ImageCanvasGenerationDialogModel', () => { expect(createBackgroundMusicGenerationDialogDraft({ canvasSize, viewport })) .toMatchObject({ mode: 'audio-background-music', - prompt: - '适合轻松冒险游戏的循环背景音乐,温暖明亮,旋律简洁,不包含人声。', + prompt: '', status: 'idle', composerOpen: true, makeInstrumental: true, diff --git a/src/components/image-editor/ImageCanvasGenerationDialogModel.ts b/src/components/image-editor/ImageCanvasGenerationDialogModel.ts index c54fc5dd5..e08aad069 100644 --- a/src/components/image-editor/ImageCanvasGenerationDialogModel.ts +++ b/src/components/image-editor/ImageCanvasGenerationDialogModel.ts @@ -50,11 +50,6 @@ const VIDEO_REFERENCE_LIMITS = { video: 3, audio: 3, } as const; -const DEFAULT_SOUND_EFFECT_PROMPT = - '短促清脆的游戏交互音效,带轻微闪光质感,干净收尾,适合按钮确认或收集奖励。'; -const DEFAULT_BACKGROUND_MUSIC_PROMPT = - '适合轻松冒险游戏的循环背景音乐,温暖明亮,旋律简洁,不包含人声。'; - function getViewportWorldCenter({ canvasSize, viewport, @@ -194,6 +189,10 @@ export function createGenerateDialogDraft({ }; } +function shouldUseSpecPlaceholderValues(specType: SpecGenerationType) { + return specType === 'character' || specType === 'ui'; +} + export function createSpecDialogDraft({ canvasSize, viewport, @@ -210,7 +209,12 @@ export function createSpecDialogDraft({ status: 'idle', composerOpen: true, specType, - specValues: { ...DEFAULT_SPEC_FORM_VALUES[specType] }, + specValues: { + ...DEFAULT_SPEC_FORM_VALUES[specType], + ...(shouldUseSpecPlaceholderValues(specType) + ? { playSetting: '', artStyle: '' } + : {}), + }, placeholder: { x: worldCenter.x - SPEC_FRAME_ORIGINAL_SIZE.width / 2, y: worldCenter.y - SPEC_FRAME_ORIGINAL_SIZE.height / 2, @@ -274,11 +278,11 @@ export function createIconGenerationDialogDraft({ const dimensionDefaults = resolveImageDimensionDefaults(normalizedImageModel); return { mode: 'icon', - prompt: formatIconDescriptionsText(DEFAULT_ICON_DESCRIPTIONS), + prompt: '', status: 'idle', composerOpen: true, iconSpecReference: null, - iconDescriptions: [...DEFAULT_ICON_DESCRIPTIONS], + iconDescriptions: [], imageModel: normalizedImageModel, aspectRatio: dimensionDefaults.aspectRatio, imageSize: dimensionDefaults.imageSize, @@ -373,7 +377,7 @@ export function createSoundEffectGenerationDialogDraft({ const worldCenter = getViewportWorldCenter({ canvasSize, viewport }); return { mode: 'audio-sound-effect', - prompt: DEFAULT_SOUND_EFFECT_PROMPT, + prompt: '', status: 'idle', composerOpen: true, soundModel: DEFAULT_SOUND_EFFECT_MODEL, @@ -399,7 +403,7 @@ export function createBackgroundMusicGenerationDialogDraft({ const worldCenter = getViewportWorldCenter({ canvasSize, viewport }); return { mode: 'audio-background-music', - prompt: DEFAULT_BACKGROUND_MUSIC_PROMPT, + prompt: '', status: 'idle', composerOpen: true, makeInstrumental: true, diff --git a/src/components/image-editor/ImageCanvasIconSpritesheetComposerView.test.tsx b/src/components/image-editor/ImageCanvasIconSpritesheetComposerView.test.tsx index df6449cf4..2bafdbee3 100644 --- a/src/components/image-editor/ImageCanvasIconSpritesheetComposerView.test.tsx +++ b/src/components/image-editor/ImageCanvasIconSpritesheetComposerView.test.tsx @@ -103,6 +103,18 @@ describe('ImageCanvasIconSpritesheetComposerView', () => { expect(requestUpload).toHaveBeenCalledWith('icon-spec'); }); + it('uses a grey hint instead of default icon text for new icon drafts', () => { + render( + , + ); + + const input = screen.getByLabelText('素材描述') as HTMLTextAreaElement; + expect(input.value).toBe(''); + expect(input.placeholder).toBe('你需要哪些图标?'); + }); + it('keeps the spec reference as a single first-row card without extra source buttons', () => { render(); diff --git a/src/components/image-editor/ImageCanvasIconSpritesheetComposerView.tsx b/src/components/image-editor/ImageCanvasIconSpritesheetComposerView.tsx index 2f984da58..360ca7732 100644 --- a/src/components/image-editor/ImageCanvasIconSpritesheetComposerView.tsx +++ b/src/components/image-editor/ImageCanvasIconSpritesheetComposerView.tsx @@ -63,8 +63,7 @@ export function ImageCanvasIconSpritesheetComposerView({ onSubmit, }: ImageCanvasIconSpritesheetComposerViewProps) { const descriptionText = - dialog.prompt || - (dialog.iconDescriptions ?? DEFAULT_ICON_DESCRIPTIONS).join('\n'); + dialog.prompt || (dialog.iconDescriptions ?? []).join('\n'); useImageCanvasFloatingOptionDismiss({ isOpen: isIconSpecMenuOpen, boundaryRefs: [iconSpecButtonRef], @@ -176,7 +175,7 @@ export function ImageCanvasIconSpritesheetComposerView({ aria-label="素材描述" value={descriptionText} disabled={dialog.status === 'generating'} - placeholder="描述要生成的多个素材,每行一个。" + placeholder="你需要哪些图标?" size="sm" density="compact" className="image-canvas-editor__generation-prompt image-canvas-editor__generation-prompt--borderless" diff --git a/src/components/image-editor/ImageCanvasSpecGenerationPanelView.test.tsx b/src/components/image-editor/ImageCanvasSpecGenerationPanelView.test.tsx index b4fb4bf76..0df94fd83 100644 --- a/src/components/image-editor/ImageCanvasSpecGenerationPanelView.test.tsx +++ b/src/components/image-editor/ImageCanvasSpecGenerationPanelView.test.tsx @@ -161,6 +161,13 @@ describe('ImageCanvasSpecGenerationPanelView', () => { onUpdateSpecFormValue: updateSpecFormValue, }); + expect( + (screen.getByLabelText('玩法设定') as HTMLInputElement).placeholder, + ).toBe('这是什么类型的游戏?'); + expect( + (screen.getByLabelText('美术风格') as HTMLInputElement).placeholder, + ).toBe('游戏的画风是怎样的?'); + fireEvent.change(screen.getByLabelText('玩法设定'), { target: { value: '战棋玩法' }, }); @@ -183,6 +190,34 @@ describe('ImageCanvasSpecGenerationPanelView', () => { ); }); + it('uses gameplay and art style hints for icon specs', () => { + renderPanel({ + dialog: createSpecDialog({ + specType: 'ui', + specValues: { + playSetting: '', + artStyle: '', + bodyRatio: '3', + characterView: '右向斜侧身站姿', + customPrompt: '', + }, + }), + }); + + expect((screen.getByLabelText('玩法设定') as HTMLInputElement).value).toBe( + '', + ); + expect( + (screen.getByLabelText('玩法设定') as HTMLInputElement).placeholder, + ).toBe('这是什么类型的游戏?'); + expect((screen.getByLabelText('美术风格') as HTMLInputElement).value).toBe( + '', + ); + expect( + (screen.getByLabelText('美术风格') as HTMLInputElement).placeholder, + ).toBe('游戏的画风是怎样的?'); + }); + it('renders custom prompt and hides reference upload for icon specs', () => { const updateSpecFormValue = vi.fn(); renderPanel({ @@ -199,6 +234,13 @@ describe('ImageCanvasSpecGenerationPanelView', () => { onUpdateSpecFormValue: updateSpecFormValue, }); + const customPrompt = screen.getByLabelText( + '自定义规范提示词', + ) as HTMLTextAreaElement; + expect(customPrompt.placeholder).toBe( + '写下你想要的任何内容,陶泥儿帮你形成新的约束', + ); + fireEvent.change(screen.getByLabelText('自定义规范提示词'), { target: { value: '新的规范提示' }, }); diff --git a/src/components/image-editor/ImageCanvasSpecGenerationPanelView.tsx b/src/components/image-editor/ImageCanvasSpecGenerationPanelView.tsx index 79158b7b2..fcb12a296 100644 --- a/src/components/image-editor/ImageCanvasSpecGenerationPanelView.tsx +++ b/src/components/image-editor/ImageCanvasSpecGenerationPanelView.tsx @@ -60,6 +60,10 @@ type ImageCanvasSpecGenerationPanelViewProps = { onSubmit: (dialog: GenerateDialogState) => void; }; +function shouldShowSpecInputPlaceholders(dialog: GenerateDialogState) { + return dialog.specType === 'character' || dialog.specType === 'ui'; +} + export function ImageCanvasSpecGenerationPanelView({ dialog, style, @@ -77,6 +81,7 @@ export function ImageCanvasSpecGenerationPanelView({ onSubmit, }: ImageCanvasSpecGenerationPanelViewProps) { const isUiDesignDialog = dialog.mode === 'ui-design'; + const showSpecInputPlaceholders = shouldShowSpecInputPlaceholders(dialog); const specSizeLabel = resolveEditorImageSizeLabel({ aspectRatio: SPEC_GENERATION_ASPECT_RATIO, imageSize: SPEC_GENERATION_IMAGE_SIZE, @@ -237,6 +242,7 @@ export function ImageCanvasSpecGenerationPanelView({ variant="textarea" aria-label="自定义规范提示词" value={dialog.specValues?.customPrompt ?? ''} + placeholder="写下你想要的任何内容,陶泥儿帮你形成新的约束" disabled={isGenerating} size="sm" density="compact" @@ -258,6 +264,11 @@ export function ImageCanvasSpecGenerationPanelView({