fix(#1197): useStep3Preview增加预览生成逻辑(mock),预留后端接口位置

This commit is contained in:
2026-07-30 14:01:21 +08:00
parent 406fd20e0e
commit 2a92d83a4b
@@ -1,8 +1,9 @@
/**
* Step 3 生成预览 Hook
* 封装预览信息计算逻辑
* 封装预览信息计算 + 预览生成逻辑
* TODO: 后端预览接口对齐后,替换 mock 逻辑为真实 API 调用
*/
import { useMemo } from "react"
import { useState, useCallback, useMemo } from "react"
import type { EditingTemplate } from "@/api/editing-planner"
interface UseStep3PreviewProps {
@@ -15,6 +16,22 @@ interface UseStep3PreviewProps {
videoRatio: string
}
export type PreviewStatus = "idle" | "generating" | "ready" | "error"
/** 预览生成结果 */
export interface PreviewResult {
/** 预计片段数 */
clipCount: number
/** 预计转场数 */
transitionCount: number
/** 素材使用率 */
materialUsage: number
/** 预览视频URL(后端接口出来后填充) */
previewVideoUrl: string | null
/** 生成耗时(秒) */
generateDuration: number
}
export function useStep3Preview({
templates,
selectedTemplate,
@@ -36,11 +53,70 @@ export function useStep3Preview({
return `${selectedMaterials.length} 个素材`
}, [materialMode, selectedMaterials.length, smartSelectedIds.length])
const materialTotal = materialMode === "auto" ? smartSelectedIds.length : selectedMaterials.length
/* ── 预览生成状态 ── */
const [previewStatus, setPreviewStatus] = useState<PreviewStatus>("idle")
const [previewResult, setPreviewResult] = useState<PreviewResult | null>(null)
const [previewError, setPreviewError] = useState<string>("")
/**
* 生成预览
* TODO: 后端 /generation-preview 接口对齐后替换此处 mock 逻辑
* 预计接口:POST /generate-preview
* 入参:template_id, material_ids, duration, video_ratio, style
* 出参:preview_id, status, clip_count, preview_video_url
*/
const generatePreview = useCallback(async () => {
if (!selectedTemplate) return
if (materialTotal === 0) return
setPreviewStatus("generating")
setPreviewError("")
try {
// TODO: 替换为真实后端接口调用
// const res = await generatePreviewAPI({ templateId: selectedTemplate, ... })
await new Promise((resolve) => setTimeout(resolve, 1500))
// Mock 结果
const estimatedClips = Math.max(3, Math.min(materialTotal * 2, 20))
const result: PreviewResult = {
clipCount: estimatedClips,
transitionCount: estimatedClips - 1,
materialUsage: Math.min(100, Math.round((materialTotal / Math.max(estimatedClips, 1)) * 100)),
previewVideoUrl: null, // 后端接口出来后填充
generateDuration: 1.5,
}
setPreviewResult(result)
setPreviewStatus("ready")
} catch (e) {
setPreviewError(e instanceof Error ? e.message : "预览生成失败")
setPreviewStatus("error")
}
}, [selectedTemplate, materialTotal])
/** 重新生成预览 */
const regeneratePreview = useCallback(() => {
generatePreview()
}, [generatePreview])
/** 是否可以下一步(预览已生成) */
const canProceed = previewStatus === "ready"
return {
templateName,
materialCount,
duration,
videoRatio,
// 预览生成状态
previewStatus,
previewResult,
previewError,
canProceed,
generatePreview,
regeneratePreview,
}
}