/** * GeneratePage 步骤内容渲染 * 步骤顺序(6步,Issue #1677 修正):模板(1) → 素材(2) → 配音(3) → 标题(4) → 确认生成(5) → 封面(6) * 步骤4预览(Canvas 网格)与步骤5进度(批量渲染网格)由 GeneratePage 直接渲染在左侧大区域。 */ import React from "react" import type { EditingTemplate } from "@/api/editing-planner" import type { EditPlanClip } from "@/api/template-editor" import type { CoverConfig } from "../types/cover" import type { TitleSettings } from "../types" import Step1TemplateSelect from "../components/Step1TemplateSelect" import Step2MaterialSelect from "../components/Step2MaterialSelect" import Step3VoiceWithMode from "./Step3VoiceWithMode" import Step4TitleSettings from "../components/Step4TitleSettings" import Step6CoverSettings from "../components/Step6CoverSettings" import BatchGenerationGrid from "./BatchGenerationGrid" import type { BatchTaskState } from "../hooks/generate-video/useGenerationPolling" import type { GeneratedVideo } from "@/api/template-editor" export interface GenerateStepContentProps { currentStep: number /* 模板 */ userTemplates: EditingTemplate[] selectedTemplate: string onSelectTemplate: (id: string) => void /* 素材 */ materialMode: "manual" | "auto" onMaterialModeChange: (mode: "manual" | "auto") => void selectedMaterials: string[] onSelectedMaterialsChange: (ids: string[]) => void smartSelectedIds: string[] onSmartSelectedIdsChange: (ids: string[]) => void /* 标题 */ titleSettings: TitleSettings onTitleSettingsChange: (settings: TitleSettings) => void onUpdatePosition: (position: string) => void onUpdateFont: (font: string) => void onUpdateSize: (size: number) => void onToggleBold: () => void onToggleItalic: () => void onToggleStroke: () => void onToggleShadow: () => void onApplyPreset: (presetKey: string) => void activePreset: string | null titlePresets: { key: string; label: string; previewStyle: React.CSSProperties }[] /* 封面 */ coverSettings: CoverConfig onCoverSettingsChange: (settings: CoverConfig) => void /* 配音 */ selectedVoice: string onSelectedVoiceChange: (id: string) => void onServerClipsChange: (clips: EditPlanClip[]) => void /* 生成 */ generating: boolean generated: boolean generateError: string | null progress: number generatedVideos: GeneratedVideo[] onRetry: () => void onRetryBatchTask: (taskId: string) => void onDismissError: () => void /** 批量:每个正式生成任务的独立状态(步骤5进度网格) */ batchTasks: BatchTaskState[] /** BGM 开关 */ bgm: boolean /** BGM 配置(来自模板) */ bgmConfig?: { enabled: boolean; music_id?: string } /* ── 批量生成(#1677)── */ previewCount: number previewTitles: string[] onPreviewTitlesChange: (titles: string[]) => void voiceModePerVideo: boolean onVoiceModePerVideoChange: (v: boolean) => void voiceLibraryIds: string[] onVoiceLibraryIdsChange: (ids: string[]) => void previewCovers: string[] onPreviewCoversChange: (urls: string[]) => void /** 批量模式勾选的变体索引(封面卡片按勾选顺序展示) */ selectedVariantIds?: number[] } export const GenerateStepContent: React.FC = (props) => { const { currentStep, userTemplates, selectedTemplate, onSelectTemplate, materialMode, onMaterialModeChange, selectedMaterials, onSelectedMaterialsChange, smartSelectedIds, onSmartSelectedIdsChange, titleSettings, onTitleSettingsChange, onUpdatePosition, onUpdateFont, onUpdateSize, onToggleBold, onToggleItalic, onToggleStroke, onToggleShadow, onApplyPreset, activePreset, titlePresets, coverSettings, onCoverSettingsChange, selectedVoice, onSelectedVoiceChange, onServerClipsChange, generating, generated, generateError, progress, onRetry, generatedVideos, batchTasks, onRetryBatchTask, previewCount, previewTitles, onPreviewTitlesChange, voiceModePerVideo, onVoiceModePerVideoChange, voiceLibraryIds, onVoiceLibraryIdsChange, previewCovers, onPreviewCoversChange, selectedVariantIds, } = props /* 当前模板的 segments,传给 Step2 构建 clips */ const currentTemplate = userTemplates.find((t) => t.id === selectedTemplate) const templateSegments = currentTemplate?.segments switch (currentStep) { case 1: return ( ) case 2: return ( ) case 3: return ( ) case 4: return ( ) case 5: /* 确认生成页:批量=逐任务进度网格;单视频=进度状态卡(成片播放器在左侧大区域) */ if (previewCount > 1) { return ( ) } /* 单视频:渲染进度 / 失败重试 / 完成提示(成片播放器在右侧栏) */ return (

🎬 确认生成

{generating && (
⏳ 视频渲染中… {Math.round(progress)}%
生成过程中可以切换到其他页面,完成后可在任务历史查看
)} {generateError && !generating && (
生成失败
{generateError}
)} {generated && !generating && (
✅ 视频生成完成!
右侧可预览成片,点击「下一步」选择封面
)}
) case 6: return ( ) default: return null } } export default GenerateStepContent