diff --git a/apps/web/src/pages/editing-planner/EditingPlanner.tsx b/apps/web/src/pages/editing-planner/EditingPlanner.tsx index 045af65c6..d0647d730 100755 --- a/apps/web/src/pages/editing-planner/EditingPlanner.tsx +++ b/apps/web/src/pages/editing-planner/EditingPlanner.tsx @@ -417,8 +417,16 @@ const EditingPlanner: React.FC = () => { */ useEffect(() => { if (!loadedPlanId) return; - getEditPlan(loadedPlanId) - .then((plan) => { + + // 并行加载计划基本信息 + 片段列表 + Promise.all([ + getEditPlan(loadedPlanId), + getEditPlanClips(loadedPlanId, { limit: 500 }).catch(() => ({ + items: [], + total: 0, + })), + ]) + .then(([plan, clipsRes]) => { // 设置关联的模板(触发模板加载 effect) setLoadedTemplateId(plan.template_id); @@ -458,8 +466,41 @@ const EditingPlanner: React.FC = () => { })); } - // 还原片段 — 延迟设置,等模板加载 effect 先执行 resetClips - if (cfg.segments && cfg.segments.length > 0) { + // 还原片段:优先从后端 clips 表,其次从 config.segments 兜底 + const backendClips = clipsRes?.items || []; + if (backendClips.length > 0) { + // 从后端 clips 表还原 + const sorted = [...backendClips].sort( + (a, b) => a.order - b.order, + ); + const mapped: ClipData[] = sorted.map((clip) => ({ + id: clip.id, + template_segment_id: + (clip.config?.template_segment_id as string) || "", + type: (clip.clip_type === "voiceover" + ? "voice" + : "pip") as ClipType, + duration: clip.duration || 3, + startOffset: 0, + script_text: clip.text_content || "", + order: clip.order, + media_asset_id: clip.asset_id || undefined, + transition: + clip.transition_effect && clip.transition_effect !== "none" + ? { + type: clip.transition_effect as TransitionEffect["type"], + duration: clip.transition_duration || 0.3, + } + : undefined, + speed: clip.playback_speed + ? { rate: clip.playback_speed, pitchCorrection: true } + : undefined, + tts_config: (clip.config?.tts_config as TtsConfig) || undefined, + trim_config: (clip.config?.trim_config as TrimConfig) || undefined, + })); + setTimeout(() => resetClips(mapped), 100); + } else if (cfg.segments && cfg.segments.length > 0) { + // 兜底:从 config.segments 还原(老数据兼容) const mapped: ClipData[] = cfg.segments.map((seg, idx) => ({ id: `seg-${idx}`, template_segment_id: `seg-${idx}`,