fix(#1341): 修复智能剪辑封面生成的 3 个问题 #1345

Closed
xiaoxia wants to merge 1 commits from fix/cover-generation-issues-1341 into develop
4 changed files with 37 additions and 5 deletions
@@ -118,6 +118,10 @@ export interface EditPlanConfig {
generate_count?: number
/** 素材模式 */
material_mode?: string
/** 预览视频 URL(封面生成用) */
rendered_storage_key?: string
/** 生成任务 ID */
generation_task_id?: string
}
/* ── 模板草稿主体 ── */
@@ -1,4 +1,5 @@
import React from "react"
import { Modal, Spin } from "antd"
import type { CoverConfig } from "../../editing-planner/types"
import { useStep6Cover } from "../hooks/useStep6Cover"
import Button from "@/components/ui/Button"
@@ -18,6 +19,7 @@ interface Step6CoverSettingsProps {
const Step6CoverSettings: React.FC<Step6CoverSettingsProps> = (props) => {
const {
coverSettings,
generating,
generateAutoCover,
showCoverSettings,
setShowCoverSettings,
@@ -95,6 +97,14 @@ const Step6CoverSettings: React.FC<Step6CoverSettingsProps> = (props) => {
template={editingTemplate}
onSave={handleSaveTemplate}
/>
{/* AI 生成封面进度弹窗 */}
<Modal open={generating} closable={false} footer={null} centered>
<div style={{ textAlign: "center", padding: "24px 0" }}>
<Spin size="large" />
<p style={{ marginTop: 16, fontSize: 14, color: "#666" }}>AI ...</p>
</div>
</Modal>
</div>
)
}
@@ -4,6 +4,7 @@
*/
import { useState, useCallback, useMemo, useEffect, useRef } from "react"
import { createPreview, getPreviewStatus } from "@/api/generation"
import { updateEditPlan } from "@/api/template-editor/editPlans"
import type { PreviewTaskResponse, PreviewStatus as ApiPreviewStatus } from "@/api/generation"
import type { EditingTemplate } from "@/api/editing-planner"
import { safeExtractError } from "./generate-video/errorUtils"
@@ -250,6 +251,15 @@ export function useStep4Preview({
it.index === index ? { ...it, status: "ready", result, progress: 100 } : it,
),
)
// 保存预览视频 URL 到 plan config,供封面生成使用
if (result.videoUrl && selectedTemplate) {
updateEditPlan(selectedTemplate, {
config: { rendered_storage_key: result.videoUrl } as any,
}).catch((err) => {
console.warn("[Step4] 保存预览视频URL到plan config失败:", err)
})
}
return
}
@@ -30,7 +30,7 @@ export function useStep6Cover({
assetIds = [],
selectedTemplate = "",
}: UseStep6CoverProps) {
const generatingRef = useRef(false)
const [generating, setGenerating] = useState(false)
// ── 封面设置弹窗状态 ──
const [showCoverSettings, setShowCoverSettings] = useState(false)
@@ -67,7 +67,7 @@ export function useStep6Cover({
/** 调用后端智能封面 API,生成封面并更新预览 */
const generateAutoCover = useCallback(async () => {
if (generatingRef.current) {
if (generating) {
message.warning("封面正在生成中,请稍候...")
return
}
@@ -82,12 +82,17 @@ export function useStep6Cover({
return
}
generatingRef.current = true
setGenerating(true)
// 超时保护:300 秒后强制重置,防止 state 卡死导致按钮永久失效
const timeoutId = setTimeout(() => {
setGenerating(false)
}, 300000)
try {
const response = await generateCover(selectedTemplate, {
asset_ids: assetIds,
cover_type: "ai_frame",
})
clearTimeout(timeoutId)
const thumbnailUrl = response.cover?.image_url || ""
if (thumbnailUrl) {
onCoverSettingsChange({
@@ -100,12 +105,14 @@ export function useStep6Cover({
message.warning("封面生成未返回图片,请重试")
}
} catch (err) {
clearTimeout(timeoutId)
console.warn("[Step6] 智能封面生成失败:", err)
message.error("封面生成失败,请稍后重试")
} finally {
generatingRef.current = false
clearTimeout(timeoutId)
setGenerating(false)
}
}, [selectedTemplate, assetIds, coverSettings, onCoverSettingsChange])
}, [selectedTemplate, assetIds, coverSettings, onCoverSettingsChange, generating])
// ── 模板操作方法 ──
const handleSelectTemplate = useCallback((id: string) => {
@@ -165,6 +172,7 @@ export function useStep6Cover({
return {
coverSettings,
generating,
generateAutoCover,
totalDuration,
showCoverSettings,