fix(#1197): useStep3Preview增加预览生成逻辑(mock),预留后端接口位置
This commit is contained in:
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user