'use client' import React, { useEffect, useMemo, useState } from 'react' import { TaskObject } from '@/api/DTO/movieEdit' import { motion } from 'framer-motion' import { Heart, Camera, Film, Scissors, type LucideIcon } from 'lucide-react' interface H5TaskInfoProps { /** 标题文案 */ title: string /** 当前分镜序号(从1开始) */ current: number /** 任务对象(用于读取总数等信息) */ taskObject: TaskObject className?: string currentLoadingText: string /** 选中视图:final 或 video */ selectedView?: 'final' | 'video' | null } const H5TaskInfo: React.FC = ({ title, current, taskObject, className, currentLoadingText, selectedView }) => { type StageIndex = 0 | 1 | 2 | 3 const [currentStage, setCurrentStage] = useState(0) const stageIconMap: Record = { 0: { icon: Heart, color: '#8b5cf6' }, 1: { icon: Camera, color: '#06b6d4' }, 2: { icon: Film, color: '#10b981' }, 3: { icon: Scissors, color: '#f59e0b' } } const computeStage = (text: string): StageIndex => { if (text.includes('initializing...') || text.includes('script') || text.includes('character')) return 0 if (text.includes('sketch') && !text.includes('shot sketch')) return 1 if (!text.includes('Post-production') && (text.includes('shot sketch') || text.includes('video'))) return 2 if (text.includes('Post-production')) return 3 return 0 } useEffect(() => { setCurrentStage(computeStage(currentLoadingText)) }, [currentLoadingText]) const stageColor = useMemo(() => stageIconMap[currentStage].color, [currentStage]) const total = useMemo(() => { if (taskObject.currentStage === 'video' || taskObject.currentStage === 'final_video') { return taskObject.videos?.total_count || taskObject.videos?.data?.length || 0 } if (taskObject.currentStage === 'scene' || taskObject.currentStage === 'character') { const rolesTotal = taskObject.roles?.total_count || taskObject.roles?.data?.length || 0 const scenesTotal = taskObject.scenes?.total_count || taskObject.scenes?.data?.length || 0 return rolesTotal + scenesTotal } return 0 }, [taskObject]) const shouldShowCount = taskObject.currentStage !== 'script' const displayCurrent = useMemo(() => { if (taskObject.currentStage === 'video' || taskObject.currentStage === 'final_video') { return Math.max(current, 1) } if (taskObject.currentStage === 'scene' || taskObject.currentStage === 'character') { const bounded = Math.min(Math.max(current, 1), Math.max(total, 1)) return bounded } return 0 }, [taskObject, current, total]) // 构造副标题文本:优先根据 selectedView 覆盖 const subtitle = useMemo(() => { if (selectedView === 'final' && taskObject.final?.url) { return 'Final 1/1' } if (selectedView === 'video' && !['scene', 'character'].includes(taskObject.currentStage)) { const videosTotal = taskObject.videos?.total_count || taskObject.videos?.data?.length || 0 return `Shots ${Math.max(displayCurrent, 1)}/${Math.max(videosTotal, 1)}` } // 回退到原有逻辑 if (taskObject.currentStage === 'video' || taskObject.currentStage === 'final_video') { return `Shots ${Math.max(displayCurrent, 1)}/${Math.max(total, 1)}` } if (taskObject.currentStage === 'scene' || taskObject.currentStage === 'character') { return `Roles & Scenes ${Math.max(displayCurrent, 1)}/${Math.max(total, 1)}` } return null }, [selectedView, taskObject, displayCurrent, total]) return (

{title || '...'}

{shouldShowCount && subtitle && ( {subtitle} )}
) } export default H5TaskInfo