修复音频生成面板布局
对齐生成游戏音效面板底部参数、模型与生成按钮布局。 固定展示音效 Vidu 模型和背景音乐 Suno 模型。 补充音频生成面板布局回归测试并更新设计文档。
This commit is contained in:
@@ -517,8 +517,25 @@ describe('ImageCanvasGenerationComposerView', () => {
|
||||
render(<AudioHarness />);
|
||||
|
||||
const panel = screen.getByRole('dialog', { name: '生成游戏音效' });
|
||||
const footer = panel.querySelector(
|
||||
'.image-canvas-editor__generation-composer-footer',
|
||||
);
|
||||
expect(footer).toBeTruthy();
|
||||
expect(footer?.children[0]?.className).toContain(
|
||||
'image-canvas-editor__option-popover-anchor--dimensions',
|
||||
);
|
||||
expect(footer?.children[1]?.className).toContain(
|
||||
'image-canvas-editor__option-popover-anchor--model',
|
||||
);
|
||||
expect(footer?.children[2]?.className).toContain(
|
||||
'image-canvas-editor__generation-submit',
|
||||
);
|
||||
expect(within(panel).getByRole('textbox', { name: 'prompt' })).toBeTruthy();
|
||||
expect(screen.getByLabelText('当前音效模型').textContent).toBe('audio1.0');
|
||||
const soundModelButton = within(panel).getByRole('button', {
|
||||
name: '音效模型 Vidu',
|
||||
});
|
||||
expect((soundModelButton as HTMLButtonElement).disabled).toBe(true);
|
||||
expect(within(panel).getByText('Vidu')).toBeTruthy();
|
||||
expect(within(panel).queryByText(/Suno/u)).toBeNull();
|
||||
expect(
|
||||
@@ -570,6 +587,23 @@ describe('ImageCanvasGenerationComposerView', () => {
|
||||
expect(
|
||||
within(panel).getByRole('textbox', { name: 'gpt_description_prompt' }),
|
||||
).toBeTruthy();
|
||||
const footer = panel.querySelector(
|
||||
'.image-canvas-editor__generation-composer-footer',
|
||||
);
|
||||
expect(footer).toBeTruthy();
|
||||
expect(footer?.children[0]?.className).toContain(
|
||||
'image-canvas-editor__option-popover-anchor--model',
|
||||
);
|
||||
expect(footer?.children[1]?.className).toContain(
|
||||
'image-canvas-editor__generation-submit',
|
||||
);
|
||||
const backgroundMusicModelButton = within(panel).getByRole('button', {
|
||||
name: '背景音乐模型 Suno',
|
||||
});
|
||||
expect((backgroundMusicModelButton as HTMLButtonElement).disabled).toBe(
|
||||
true,
|
||||
);
|
||||
expect(within(panel).getByText('Suno')).toBeTruthy();
|
||||
expect(within(panel).queryByText('make_instrumental')).toBeNull();
|
||||
expect(within(panel).getByRole('button', { name: '生成游戏背景音乐' }).textContent).toBe(
|
||||
'生成5泥点',
|
||||
|
||||
@@ -670,6 +670,10 @@ function ImageCanvasAudioGenerationComposerView({
|
||||
const soundDuration = normalizeSoundDuration(dialog.soundDurationSeconds);
|
||||
const soundOptionLabel = `${soundDuration}秒`;
|
||||
const dialogLabel = isSoundEffect ? '生成游戏音效' : '生成游戏背景音乐';
|
||||
const fixedModelLabel = isSoundEffect ? currentSoundModel.label : 'Suno';
|
||||
const fixedModelAriaLabel = isSoundEffect
|
||||
? `音效模型 ${fixedModelLabel}`
|
||||
: `背景音乐模型 ${fixedModelLabel}`;
|
||||
const cost = isSoundEffect
|
||||
? calculateEditorSoundEffectPrice(soundModel)
|
||||
: calculateEditorBackgroundMusicPrice(DEFAULT_BACKGROUND_MUSIC_MODEL);
|
||||
@@ -737,65 +741,65 @@ function ImageCanvasAudioGenerationComposerView({
|
||||
) : null}
|
||||
<div className="image-canvas-editor__generation-composer-footer">
|
||||
{isSoundEffect ? (
|
||||
<>
|
||||
<div className="image-canvas-editor__option-popover-anchor image-canvas-editor__option-popover-anchor--dimensions">
|
||||
<PlatformInlineOptionButton
|
||||
ref={soundModelButtonRef}
|
||||
className="image-canvas-editor__option-cluster image-canvas-editor__option-cluster--model"
|
||||
aria-label={`音效模型 ${currentSoundModel.label}`}
|
||||
ref={soundOptionsButtonRef}
|
||||
className="image-canvas-editor__option-cluster image-canvas-editor__option-cluster--dimensions"
|
||||
aria-label={`音效时长 ${soundOptionLabel}`}
|
||||
aria-expanded={isSoundOptionsOpen}
|
||||
disabled={isGenerating}
|
||||
trailingIcon={<ChevronDown className="h-3 w-3" />}
|
||||
onClick={() => setIsSoundOptionsOpen((isOpen) => !isOpen)}
|
||||
>
|
||||
<span className="image-canvas-editor__model-trigger-label">
|
||||
<span
|
||||
className="image-canvas-editor__model-icon"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<Music />
|
||||
</span>
|
||||
<span>{currentSoundModel.label}</span>
|
||||
</span>
|
||||
{soundOptionLabel}
|
||||
</PlatformInlineOptionButton>
|
||||
<div className="image-canvas-editor__option-popover-anchor image-canvas-editor__option-popover-anchor--dimensions">
|
||||
<PlatformInlineOptionButton
|
||||
ref={soundOptionsButtonRef}
|
||||
className="image-canvas-editor__option-cluster image-canvas-editor__option-cluster--dimensions"
|
||||
aria-label={`音效时长 ${soundOptionLabel}`}
|
||||
aria-expanded={isSoundOptionsOpen}
|
||||
disabled={isGenerating}
|
||||
trailingIcon={<ChevronDown className="h-3 w-3" />}
|
||||
onClick={() => setIsSoundOptionsOpen((isOpen) => !isOpen)}
|
||||
>
|
||||
{soundOptionLabel}
|
||||
</PlatformInlineOptionButton>
|
||||
{isSoundOptionsOpen
|
||||
? renderEditorPortal(
|
||||
<PlatformFloatingMenu
|
||||
className="image-canvas-editor__option-popover image-canvas-editor__option-popover--audio-options image-canvas-editor__portal-menu"
|
||||
label="音效时长选项"
|
||||
placement="top-start"
|
||||
style={buildPortalMenuStyle(
|
||||
soundOptionsButtonRef.current,
|
||||
'above',
|
||||
)}
|
||||
>
|
||||
<div className="image-canvas-editor__option-popover-items image-canvas-editor__audio-type-options">
|
||||
{SOUND_EFFECT_DURATION_OPTIONS.map((option) => (
|
||||
<VideoOptionChoice
|
||||
key={option}
|
||||
selected={soundDuration === option}
|
||||
disabled={isGenerating}
|
||||
ariaLabel={`时长 ${option}秒`}
|
||||
onClick={() => updateSoundDuration(option)}
|
||||
>
|
||||
{option}秒
|
||||
</VideoOptionChoice>
|
||||
))}
|
||||
</div>
|
||||
</PlatformFloatingMenu>,
|
||||
)
|
||||
: null}
|
||||
</div>
|
||||
</>
|
||||
{isSoundOptionsOpen
|
||||
? renderEditorPortal(
|
||||
<PlatformFloatingMenu
|
||||
className="image-canvas-editor__option-popover image-canvas-editor__option-popover--audio-options image-canvas-editor__portal-menu"
|
||||
label="音效时长选项"
|
||||
placement="top-start"
|
||||
style={buildPortalMenuStyle(
|
||||
soundOptionsButtonRef.current,
|
||||
'above',
|
||||
)}
|
||||
>
|
||||
<div className="image-canvas-editor__option-popover-items image-canvas-editor__audio-type-options">
|
||||
{SOUND_EFFECT_DURATION_OPTIONS.map((option) => (
|
||||
<VideoOptionChoice
|
||||
key={option}
|
||||
selected={soundDuration === option}
|
||||
disabled={isGenerating}
|
||||
ariaLabel={`时长 ${option}秒`}
|
||||
onClick={() => updateSoundDuration(option)}
|
||||
>
|
||||
{option}秒
|
||||
</VideoOptionChoice>
|
||||
))}
|
||||
</div>
|
||||
</PlatformFloatingMenu>,
|
||||
)
|
||||
: null}
|
||||
</div>
|
||||
) : null}
|
||||
<div className="image-canvas-editor__option-popover-anchor image-canvas-editor__option-popover-anchor--model image-canvas-editor__readonly-generation-option">
|
||||
<PlatformInlineOptionButton
|
||||
ref={soundModelButtonRef}
|
||||
className="image-canvas-editor__option-cluster image-canvas-editor__option-cluster--model"
|
||||
aria-label={fixedModelAriaLabel}
|
||||
disabled
|
||||
>
|
||||
<span className="image-canvas-editor__model-trigger-label">
|
||||
<span
|
||||
className="image-canvas-editor__model-icon"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<Music />
|
||||
</span>
|
||||
<span>{fixedModelLabel}</span>
|
||||
</span>
|
||||
</PlatformInlineOptionButton>
|
||||
</div>
|
||||
<PlatformActionButton
|
||||
type="submit"
|
||||
tone="secondary"
|
||||
|
||||
Reference in New Issue
Block a user