+
+ {/* CSS 标题实时预览层 — 与 FFmpeg ASS 渲染坐标对齐 */}
+ {titleSettings && }
diff --git a/apps/web/src/pages/generate/components/Step4TitleSettings.tsx b/apps/web/src/pages/generate/components/Step4TitleSettings.tsx
index 698dbe5d0..d01dbf48d 100644
--- a/apps/web/src/pages/generate/components/Step4TitleSettings.tsx
+++ b/apps/web/src/pages/generate/components/Step4TitleSettings.tsx
@@ -1,13 +1,13 @@
/**
* Step 4 标题设置组件
+ * 仅包含标题文字输入 + AI 标题生成
+ * 标题样式面板已迁移到 Step5(生成预览页面)
*/
import React from "react"
import { AutoComplete } from "antd"
-import { POSITION_OPTIONS, FONT_OPTIONS } from "../constants"
import type { TitleSettings } from "../types"
import { useStep4Title } from "../hooks/useStep4Title"
import AiTitleGenerator from "./title/AiTitleGenerator"
-import TitleStylePanel from "./title/TitleStylePanel"
interface Step4TitleSettingsProps {
titleSettings: TitleSettings
@@ -110,23 +110,6 @@ const Step4TitleSettings: React.FC = (props) => {
>
)}
-
- {/* 样式面板始终可见,两种模式下都可调整标题展示样式 */}
-
)
}
diff --git a/apps/web/src/pages/generate/components/Step5GeneratePreview.tsx b/apps/web/src/pages/generate/components/Step5GeneratePreview.tsx
index 598e1b770..d91cf1f4c 100644
--- a/apps/web/src/pages/generate/components/Step5GeneratePreview.tsx
+++ b/apps/web/src/pages/generate/components/Step5GeneratePreview.tsx
@@ -2,6 +2,7 @@
* Step 5 生成预览组件(支持多预览)
* 调用后端预览生成接口,展示预览生成状态
* 预览视频由右侧 PreviewVideoPanel 展示,本组件不重复显示预览网格
+ * 标题样式面板(TitleStylePanel)在此展示,用户可实时调整标题样式
*/
import React from "react"
import {
@@ -12,7 +13,10 @@ import {
ClockCircleOutlined,
} from "@ant-design/icons"
import { InputNumber } from "antd"
+import { POSITION_OPTIONS, FONT_OPTIONS } from "../constants"
+import type { TitleSettings } from "../types"
import type { PreviewItem, PreviewStatus } from "../hooks/useStep5Preview"
+import TitleStylePanel from "./title/TitleStylePanel"
interface Step5GeneratePreviewProps {
previewCount: number
@@ -24,6 +28,18 @@ interface Step5GeneratePreviewProps {
anyGenerating: boolean
onGeneratePreview: () => void
onRegeneratePreview: () => void
+ /* 标题样式 */
+ 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 }[]
}
/** 预览数量选项 */
@@ -43,6 +59,17 @@ const Step5GeneratePreview: React.FC
= ({
anyGenerating,
onGeneratePreview,
onRegeneratePreview,
+ titleSettings,
+ onUpdatePosition,
+ onUpdateFont,
+ onUpdateSize,
+ onToggleBold,
+ onToggleItalic,
+ onToggleStroke,
+ onToggleShadow,
+ onApplyPreset,
+ activePreset,
+ titlePresets,
}) => {
const isIdle = overallStatus === "idle"
const isError = overallStatus === "error" && !items.some((it) => it.status === "ready")
@@ -51,6 +78,23 @@ const Step5GeneratePreview: React.FC = ({
🎬 生成预览
+ {/* 标题样式面板 — 用户可实时调整标题样式,右侧预览同步更新 */}
+
+
{/* 预览数量选择器(仅在 idle 状态显示) */}
{isIdle && (
diff --git a/apps/web/src/pages/generate/hooks/useStep6Cover.ts b/apps/web/src/pages/generate/hooks/useStep6Cover.ts
index 9b8b804b2..53473da54 100644
--- a/apps/web/src/pages/generate/hooks/useStep6Cover.ts
+++ b/apps/web/src/pages/generate/hooks/useStep6Cover.ts
@@ -109,26 +109,30 @@ export function useStep6Cover({
console.error("[Step6] 智能封面生成失败:", err)
// 提取详细错误信息
- let errorMsg = "封面生成失败"
- const e = err as {
- response?: { data?: { detail?: string; message?: string }; status?: number }
- request?: unknown
- message?: string
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ const anyErr = err as any
+ // 如果 API 拦截器已经弹出了后端返回的具体错误信息,这里跳过重复 toast
+ if (anyErr?.__msgShown) {
+ // 拦截器已处理,不再重复弹出
+ } else {
+ let errorMsg = "封面生成失败"
+ const e = anyErr as {
+ response?: { data?: { detail?: string; message?: string }; status?: number }
+ request?: unknown
+ message?: string
+ }
+ if (e.response) {
+ const detail = e.response.data?.detail || e.response.data?.message || ""
+ errorMsg = detail || `后端错误 (${e.response.status})`
+ console.error("[Step6] 后端返回:", e.response.data)
+ } else if (e.request) {
+ errorMsg = "服务器无响应,请检查网络连接"
+ console.error("[Step6] 请求无响应:", e.request)
+ } else if (e.message) {
+ errorMsg = e.message
+ }
+ message.error(errorMsg)
}
- if (e.response) {
- // 后端返回错误
- const detail = e.response.data?.detail || e.response.data?.message || ""
- errorMsg = detail || `后端错误 (${e.response.status})`
- console.error("[Step6] 后端返回:", e.response.data)
- } else if (e.request) {
- // 请求已发送但无响应
- errorMsg = "服务器无响应,请检查网络连接"
- console.error("[Step6] 请求无响应:", e.request)
- } else if (e.message) {
- errorMsg = e.message
- }
-
- message.error(errorMsg)
} finally {
clearTimeout(timeoutId)
setGenerating(false)