diff --git a/apps/web/src/pages/generate/GeneratePage.tsx b/apps/web/src/pages/generate/GeneratePage.tsx index a2f377d64..f27a2a8fd 100644 --- a/apps/web/src/pages/generate/GeneratePage.tsx +++ b/apps/web/src/pages/generate/GeneratePage.tsx @@ -1,11 +1,11 @@ /** * 智能剪辑页面 — 前端实时预览架构 - * 7 步向导:选择模板 → 素材 → 配音 → 标题 → 预览 → 封面 → 确认生成 + * 6 步向导:选择模板 → 素材 → 配音 → 标题(含预览) → 封面 → 确认生成 * 左右布局:左侧 generate-form + 右侧 generate-preview * * 架构: - * - 步骤 4-6 右侧显示 FrontendPreviewPlayer 实时预览 - * - 步骤 7 右侧内联播放生成的最终视频 + * - 步骤 4-5 右侧显示 FrontendPreviewPlayer 实时预览 + * - 步骤 6 右侧内联播放生成的最终视频 * - 点"确认生成"时调用 createGenerationTask 创建一次服务器渲染任务 */ import React, { useMemo, useState, useEffect, useRef } from "react" @@ -163,7 +163,16 @@ const GeneratePage: React.FC = () => { /* ── 加载素材详情(供前端预览播放器使用 + 配音时长校验) ── */ const previewAssetsEnabled = previewAssetIds.length > 0 - const { assets: previewAssets } = usePreviewAssets(previewAssetIds, previewAssetsEnabled) + const { assets: previewAssets, ready: previewAssetsReady } = usePreviewAssets( + previewAssetIds, + previewAssetsEnabled, + ) + + /* ── 预览就绪:素材已加载,且有模板 ── */ + const previewReady = useMemo( + () => previewAssetsReady && !!currentTemplate, + [previewAssetsReady, currentTemplate], + ) /* ── 视频总时长计算 ── */ const totalVideoDuration = useMemo(() => { @@ -181,6 +190,7 @@ const GeneratePage: React.FC = () => { selectedMaterials, smartSelectedIds, titleSettings, + previewReady, }) /* ── 视频生成核心逻辑 ── */ @@ -296,9 +306,9 @@ const GeneratePage: React.FC = () => { /> - {/* ════ 右侧:步骤 4-6 实时预览,步骤 7 最终视频 ════ */} + {/* ════ 右侧:步骤 4-5 实时预览,步骤 6 最终视频 ════ */}
- {currentStep >= 4 && currentStep <= 6 && !!currentTemplate && ( + {currentStep >= 4 && currentStep <= 5 && !!currentTemplate && ( { }} /> )} - {currentStep === 7 && generated && generatedVideos.length > 0 && ( + {currentStep === 6 && generated && generatedVideos.length > 0 && (
) } diff --git a/apps/web/src/pages/generate/components/Step5GeneratePreview.tsx b/apps/web/src/pages/generate/components/Step5GeneratePreview.tsx deleted file mode 100644 index 47f22274b..000000000 --- a/apps/web/src/pages/generate/components/Step5GeneratePreview.tsx +++ /dev/null @@ -1,83 +0,0 @@ -/** - * Step 5 预览设置组件 - * - * 前端实时预览架构: - * - 右侧面板使用 FrontendPreviewPlayer 实时播放素材片段 - * - 标题样式可实时调整,CSS 层即时叠加预览 - * - 点"确认生成"时触发一次服务器渲染 - */ -import React from "react" -import { PlayCircleOutlined } from "@ant-design/icons" -import { POSITION_OPTIONS, FONT_OPTIONS } from "../constants" -import type { TitleSettings } from "../types" -import TitleStylePanel from "./title/TitleStylePanel" - -interface Step5GeneratePreviewProps { - titleSettings: TitleSettings - 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 }[] -} - -const Step5GeneratePreview: React.FC = ({ - titleSettings, - onUpdatePosition, - onUpdateFont, - onUpdateSize, - onToggleBold, - onToggleItalic, - onToggleStroke, - onToggleShadow, - onApplyPreset, - activePreset, - titlePresets, -}) => { - return ( -
-

🎬 预览设置

- -
- - - 右侧为实时预览,选完素材即可播放。确认生成后服务器渲染最终视频 - -
- - -
- ) -} - -export default Step5GeneratePreview diff --git a/apps/web/src/pages/generate/constants.ts b/apps/web/src/pages/generate/constants.ts index 6810c6c49..c6a9bf764 100644 --- a/apps/web/src/pages/generate/constants.ts +++ b/apps/web/src/pages/generate/constants.ts @@ -33,9 +33,8 @@ export const STEPS = [ { key: 2, label: "选择素材" }, { key: 3, label: "选择配音" }, { key: 4, label: "选择标题" }, - { key: 5, label: "生成预览" }, - { key: 6, label: "选择封面" }, - { key: 7, label: "确认生成" }, + { key: 5, label: "选择封面" }, + { key: 6, label: "确认生成" }, ] /* ── 标题位置选项 ── */ diff --git a/apps/web/src/pages/generate/hooks/useStepNavigation.ts b/apps/web/src/pages/generate/hooks/useStepNavigation.ts index 7a92e266c..02c46a14b 100644 --- a/apps/web/src/pages/generate/hooks/useStepNavigation.ts +++ b/apps/web/src/pages/generate/hooks/useStepNavigation.ts @@ -1,9 +1,9 @@ /** * GeneratePage 步骤导航 * 管理步骤切换与各步骤的前置校验 - * 步骤顺序:模板(1) → 素材(2) → 配音(3) → 标题(4) → 预览(5) → 封面(6) → 确认(7) + * 步骤顺序(6步):模板(1) → 素材(2) → 配音(3) → 标题(4) → 封面(5) → 确认(6) * - * 前端实时预览架构:Step5 无需等待服务器渲染 + * 原 Step4(标题) + Step5(预览) 已合并为 Step4 */ import { message } from "antd" import type { TitleSettings } from "../types" @@ -16,6 +16,8 @@ export interface UseStepNavigationOptions { selectedMaterials: string[] smartSelectedIds: string[] titleSettings: TitleSettings + /** 预览是否已就绪(素材已加载,可播放) */ + previewReady: boolean } export interface UseStepNavigationReturn { @@ -32,6 +34,7 @@ export const useStepNavigation = (options: UseStepNavigationOptions): UseStepNav selectedMaterials, smartSelectedIds, titleSettings, + previewReady, } = options const goNext = () => { @@ -47,11 +50,18 @@ export const useStepNavigation = (options: UseStepNavigationOptions): UseStepNav message.warning("请先进行智能匹配并选择素材") return } - if (currentStep === 4 && !titleSettings.title.trim()) { - message.warning("请选择或输入标题") - return + // Step4(合并后的标题+预览):标题必填 + 预览必须已生成 + if (currentStep === 4) { + if (!titleSettings.title.trim()) { + message.warning("请选择或输入标题") + return + } + if (!previewReady) { + message.warning("预览视频正在加载,请稍候") + return + } } - if (currentStep < 7) { + if (currentStep < 6) { setCurrentStep((s) => s + 1) } } diff --git a/apps/web/src/test/pages/generate/smoke.test.tsx b/apps/web/src/test/pages/generate/smoke.test.tsx index 5433a0291..ef10ff4d5 100755 --- a/apps/web/src/test/pages/generate/smoke.test.tsx +++ b/apps/web/src/test/pages/generate/smoke.test.tsx @@ -17,7 +17,6 @@ import "@/api/generation/types" // 直接引入所有 Step 组件,建立完整依赖链 import "@/pages/generate/GeneratePage" import "@/pages/generate/components/Step2MaterialSelect" -import "@/pages/generate/components/Step5GeneratePreview" import "@/pages/generate/components/Step4TitleSettings" import "@/pages/generate/components/Step5VoiceSelect" import "@/pages/generate/components/PreviewVideoPanel" diff --git a/apps/web/src/test/pages/generate/step5-preview.smoke.test.tsx b/apps/web/src/test/pages/generate/step5-preview.smoke.test.tsx index 4b8fb7723..a8dfcf8ec 100644 --- a/apps/web/src/test/pages/generate/step5-preview.smoke.test.tsx +++ b/apps/web/src/test/pages/generate/step5-preview.smoke.test.tsx @@ -1,10 +1,9 @@ /** - * Step5GeneratePreview smoke test + * Step4+5 merged preview smoke test * 确保 vitest related 模式能匹配到第5步预览生成相关文件的改动 */ import { describe, it, expect } from "vitest" -import "@/pages/generate/components/Step5GeneratePreview" import "@/pages/generate/hooks/usePreviewAssets" import "@/pages/generate/hooks/useSegmentScheduler" import "@/pages/generate/components/FrontendPreviewPlayer" @@ -12,8 +11,8 @@ import "@/pages/generate/hooks/useStepNavigation" import "@/pages/generate/components/GenerateStepContent" import "@/pages/generate/GeneratePage" -describe("Step5GeneratePreview module smoke test", () => { - it("should load all step5 preview modules", () => { +describe("Merged Step4+5 preview module smoke test", () => { + it("should load all merged step4+5 preview modules", () => { expect(true).toBe(true) }) })