From 2281c64ee8ae00970a87e3df4a396885cac4b692 Mon Sep 17 00:00:00 2001 From: seaislee1209 Date: Tue, 14 Apr 2026 14:10:39 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E9=9F=B3=E9=A2=91=E4=B8=8D=E8=83=BD?= =?UTF-8?q?=E4=BD=9C=E4=B8=BA=E5=94=AF=E4=B8=80=E5=8F=82=E8=80=83=E7=B4=A0?= =?UTF-8?q?=E6=9D=90=20=E2=80=94=20=E5=89=8D=E7=AB=AF=E6=A0=A1=E9=AA=8C=20?= =?UTF-8?q?+=20toast=20=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Seedance API 不支持"纯音频"和"文本+音频"输入,必须搭配图片或视频。 - canSubmit() 校验同时检查 references 和 assetMentions - Toolbar 点击禁用按钮时弹出 toast 提示原因 Co-Authored-By: Claude Opus 4.6 (1M context) --- web/src/components/Toolbar.tsx | 10 +++++++++- web/src/store/inputBar.ts | 17 +++++++++++++---- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/web/src/components/Toolbar.tsx b/web/src/components/Toolbar.tsx index 5bda6e9..2f431a5 100644 --- a/web/src/components/Toolbar.tsx +++ b/web/src/components/Toolbar.tsx @@ -3,6 +3,7 @@ import { useInputBarStore } from '../store/inputBar'; import { useGenerationStore } from '../store/generation'; import { useAuthStore } from '../store/auth'; import { Dropdown } from './Dropdown'; +import { showToast } from './Toast'; import type { CreationMode, AspectRatio, Duration, GenerationType, ModelOption } from '../types'; import styles from './Toolbar.module.css'; @@ -145,7 +146,14 @@ export function Toolbar() { }, [estimatedTokens, model, references, team]); const handleSend = useCallback(() => { - if (!isSubmittable) return; + if (!isSubmittable) { + const s = useInputBarStore.getState(); + if (s.mode === 'universal' && s.references.some((r) => r.type === 'audio') + && !s.references.some((r) => r.type === 'image' || r.type === 'video')) { + showToast('音频不能作为唯一的参考素材,请同时添加图片或视频'); + } + return; + } addTask(); }, [isSubmittable, addTask]); diff --git a/web/src/store/inputBar.ts b/web/src/store/inputBar.ts index dc3900d..b434f51 100644 --- a/web/src/store/inputBar.ts +++ b/web/src/store/inputBar.ts @@ -285,10 +285,19 @@ export const useInputBarStore = create((set, get) => ({ ? state.references.length > 0 : state.firstFrame !== null || state.lastFrame !== null; if (!hasText && !hasFiles) return false; - // Audio cannot be sent alone — must have image or video - if (state.mode === 'universal' && state.references.length > 0) { - const hasImageOrVideo = state.references.some((r) => r.type === 'image' || r.type === 'video'); - if (!hasImageOrVideo && !hasText) return false; + // Audio cannot be the only reference — Seedance API requires image or video alongside + if (state.mode === 'universal') { + const hasAudioRef = state.references.some((r) => r.type === 'audio'); + const hasAudioAsset = (state.assetMentions || []).some((m: Record) => + (m.assetType || '').toLowerCase() === 'audio'); + if (hasAudioRef || hasAudioAsset) { + const hasImageOrVideoRef = state.references.some((r) => r.type === 'image' || r.type === 'video'); + const hasImageOrVideoAsset = (state.assetMentions || []).some((m: Record) => { + const t = (m.assetType || '').toLowerCase(); + return t === 'image' || t === 'video'; + }); + if (!hasImageOrVideoRef && !hasImageOrVideoAsset) return false; + } } // Block submit if any reference is still uploading or failed if (state.references.some((r) => r.uploading || r.uploadError)) return false;