From 11c1cdf8cc2005c82f6dc6e35814a8699456381f Mon Sep 17 00:00:00 2001 From: seaislee1209 Date: Tue, 12 May 2026 18:24:28 +0800 Subject: [PATCH] =?UTF-8?q?fix(records):=20TeamAssetsPage=20=E9=87=8D?= =?UTF-8?q?=E6=96=B0=E7=BC=96=E8=BE=91=20prompt=20=E4=B8=A2=E5=A4=B1=20?= =?UTF-8?q?=E2=80=94=20VideoDetailModal=20fallback=20=E8=A1=A5=20editorHtm?= =?UTF-8?q?l?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 根因(4 层叠加): 1. TeamAssetsPage 没传 onReEdit prop 给 VideoDetailModal → 走 modal 内部 fallback 2. fallback 只 setPrompt(task.prompt),没设 editorHtml 3. PromptInput 是 contenteditable,渲染依据是 editorHtml,不是 prompt 4. assetVideoToTask 把 editorHtml 显式置 '' → fallback 拿到的就是空串 修法:fallback 跟 store/generation.ts:reEdit 对齐, 用 useInputBarStore.setState 一次性批量灌入所有字段, 关键补 editorHtml: task.editorHtml || task.prompt || '', 让 PromptInput 渲染 + rebuildMentionSpans 走完整路径 (原文 + assetMentions 重建带缩略图的 @ 标签)。 附带顺手补: - mode 用 switchMode 而不是 setMode(switchMode 会清 keyframe 状态) - assetMentions: task.assetMentions || [] - references 用 setState 批量传(原代码用 setState 又用 setX 混用,不一致) 影响范围: - 团管 /team/assets → 任意视频 → "重新编辑" → /app prompt 文本框有内容 ✓ - 超管 /admin/assets → 同上 ✓ - 用户 /user-assets → reEdit 走的是另一条路(generation.ts:reEdit),不受影响 Co-Authored-By: Claude Opus 4.7 (1M context) --- web/src/components/VideoDetailModal.tsx | 37 ++++++++++++++----------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/web/src/components/VideoDetailModal.tsx b/web/src/components/VideoDetailModal.tsx index 52d1358..4276831 100644 --- a/web/src/components/VideoDetailModal.tsx +++ b/web/src/components/VideoDetailModal.tsx @@ -212,29 +212,34 @@ export function VideoDetailModal({ task, onClose, onReEdit, onRegenerate, onDele onReEdit(task.id); onClose(); } else { - // Fallback: load task into input bar and navigate to generation page + // Fallback (asset page → reEdit): 跟 store/generation.ts:reEdit 对齐, + // 用 setState 一次性批量灌入所有相关字段。 + // 关键 bug 修复:之前只 setPrompt 不写 editorHtml,PromptInput 渲染 editorHtml, + // 所以编辑器是空的(只回填了图片素材)。 const store = useInputBarStore.getState(); store.reset(); - store.setPrompt(task.prompt || ''); - if (task.mode) store.setMode(task.mode as 'universal' | 'keyframe'); - if (task.model) store.setModel(task.model as 'seedance_2.0' | 'seedance_2.0_fast'); - if (task.aspectRatio) store.setAspectRatio(task.aspectRatio as any); - if (task.duration) store.setDuration(task.duration); - if (task.resolution) store.setResolution(task.resolution); - // Load references from task (exclude asset library refs — they restore via @mentions in editorHtml) - if (task.references && task.references.length > 0) { - const refs = task.references.filter(r => r.previewUrl && !r.isAssetRef).map(r => ({ + if (task.mode && store.mode !== task.mode) { + store.switchMode(task.mode as 'universal' | 'keyframe'); + } + const refs = (task.references || []) + .filter(r => r.previewUrl && !r.isAssetRef) + .map(r => ({ id: r.id, - file: null as unknown as File, - previewUrl: r.previewUrl, type: r.type as 'image' | 'video' | 'audio', + previewUrl: r.previewUrl, label: r.label, tosUrl: r.previewUrl, })); - if (refs.length > 0) { - useInputBarStore.setState({ references: refs }); - } - } + useInputBarStore.setState({ + prompt: task.prompt || '', + editorHtml: task.editorHtml || task.prompt || '', + model: (task.model as 'seedance_2.0' | 'seedance_2.0_fast') || 'seedance_2.0', + aspectRatio: (task.aspectRatio as any) || '16:9', + duration: task.duration ?? 5, + resolution: task.resolution || '720p', + references: refs, + assetMentions: task.assetMentions || [], + }); onClose(); navigate('/app'); }