2025-09-20 16:16:27 +08:00

159 lines
6.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use client'
import React, { useMemo } from 'react'
import { TaskObject } from '@/api/DTO/movieEdit'
import { GlassIconButton } from '@/components/ui/glass-icon-button'
import { Pencil, RotateCcw, Download, ArrowDownWideNarrow, Scissors, Maximize, Minimize, MessageCircleMore } from 'lucide-react'
interface H5TaskInfoProps {
/** 标题文案 */
title: string
/** 当前分镜序号从1开始 */
current: number
/** 任务对象(用于读取总数等信息) */
taskObject: TaskObject
/** video聊天编辑 */
onEditWithChat?: () => void
/** 下载:全部分镜 */
onDownloadAll?: () => void
/** 下载:最终成片 */
onDownloadFinal?: () => void
/** 下载:当前分镜视频 */
onDownloadCurrent?: () => void
/** video失败时显示重试 */
showRetry?: boolean
onRetry?: () => void
className?: string
}
const H5TaskInfo: React.FC<H5TaskInfoProps> = ({
title,
current,
taskObject,
onEditWithChat,
onDownloadAll,
onDownloadFinal,
onDownloadCurrent,
showRetry,
onRetry,
className
}) => {
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])
return (
<div
data-alt="h5-header"
className={`absolute top-0 left-0 right-0 z-[50] pr-2 ${className || ''}`}
>
<div
data-alt="h5-header-bar"
className="flex items-start justify-between"
>
<div data-alt="title-area" className="flex flex-col min-w-0 bg-gradient-to-b from-slate-900/80 via-slate-900/40 to-transparent backdrop-blur-sm rounded-lg p-4">
<h1
data-alt="title"
className="text-white text-lg font-bold"
title={title}
>
{title || '...'}
</h1>
{shouldShowCount && (
<span data-alt="shot-count" className="flex items-center gap-4 text-sm text-slate-300">
{displayCurrent}/{Math.max(total, 1)}
</span>
)}
</div>
<div data-alt="actions" className="flex flex-col items-center gap-2">
{taskObject.currentStage === 'final_video' && (
<div data-alt="final-video-actions" className="flex flex-col items-center gap-2">
<GlassIconButton
data-alt="download-all-button"
className="w-10 h-10 bg-gradient-to-br from-purple-500/80 to-purple-600/80 backdrop-blur-xl border border-purple-400/30 rounded-full flex items-center justify-center hover:from-purple-400/80 hover:to-purple-500/80 transition-all"
icon={ArrowDownWideNarrow}
size="sm"
aria-label="download-all"
onClick={onDownloadAll}
/>
<GlassIconButton
data-alt="download-final-button"
className="w-10 h-10 bg-gradient-to-br from-amber-500/80 to-yellow-600/80 backdrop-blur-xl border border-amber-400/30 rounded-full flex items-center justify-center hover:from-amber-400/80 hover:to-yellow-500/80 transition-all"
icon={Download}
size="sm"
aria-label="download-final"
onClick={onDownloadFinal}
/>
</div>
)}
{taskObject.currentStage === 'video' && (
<div data-alt="video-actions" className="flex flex-col items-center gap-2">
<GlassIconButton
data-alt="edit-with-chat-button"
className="w-10 h-10 bg-gradient-to-br from-blue-500/80 to-blue-600/80 backdrop-blur-xl border border-blue-400/30 rounded-full flex items-center justify-center hover:from-blue-400/80 hover:to-blue-500/80 transition-all"
icon={MessageCircleMore}
size="sm"
aria-label="edit-with-chat"
onClick={onEditWithChat}
/>
<GlassIconButton
data-alt="download-all-button"
className="w-10 h-10 bg-gradient-to-br from-purple-500/80 to-purple-600/80 backdrop-blur-xl border border-purple-400/30 rounded-full flex items-center justify-center hover:from-purple-400/80 hover:to-purple-500/80 transition-all"
icon={ArrowDownWideNarrow}
size="sm"
aria-label="download-all"
onClick={onDownloadAll}
/>
<GlassIconButton
data-alt="download-current-button"
className="w-10 h-10 bg-gradient-to-br from-amber-500/80 to-yellow-600/80 backdrop-blur-xl border border-amber-400/30 rounded-full flex items-center justify-center hover:from-amber-400/80 hover:to-yellow-500/80 transition-all"
icon={Download}
size="sm"
aria-label="download-current"
onClick={onDownloadCurrent}
/>
{showRetry && (
<GlassIconButton
data-alt="retry-button"
className="w-10 h-10 bg-gradient-to-br from-purple-500/80 to-purple-600/80 backdrop-blur-xl border border-purple-400/30 rounded-full flex items-center justify-center hover:from-purple-400/80 hover:to-purple-500/80 transition-all"
icon={RotateCcw}
size="sm"
aria-label="retry"
onClick={onRetry}
/>
)}
</div>
)}
</div>
</div>
</div>
)
}
export default H5TaskInfo