'use client'; import React, { useRef, useEffect, useState } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { Trash2, RefreshCw, Play, Pause, Volume2, VolumeX, Upload, Library, Video, User, MapPin, Settings, Loader2, X, Plus } from 'lucide-react'; import { GlassIconButton } from './glass-icon-button'; import { cn } from '@/public/lib/utils'; import { ReplaceVideoModal } from './replace-video-modal'; import { MediaPropertiesModal } from './media-properties-modal'; import { DramaLineChart } from './drama-line-chart'; import { PersonDetection, PersonDetectionScene } from './person-detection'; import ShotEditor from './shot-editor/ShotEditor'; import { CharacterLibrarySelector } from './character-library-selector'; import FloatingGlassPanel from './FloatingGlassPanel'; import { ReplaceCharacterPanel, mockShots, mockCharacter } from './replace-character-panel'; import HorizontalScroller from './HorizontalScroller'; interface ShotTabContentProps { taskSketch: any[]; currentSketchIndex: number; onSketchSelect: (index: number) => void; isPlaying?: boolean; roles?: any[]; } export function ShotTabContent({ taskSketch = [], currentSketchIndex = 0, onSketchSelect, isPlaying: externalIsPlaying = true, roles = [] }: ShotTabContentProps) { const editorRef = useRef(null); const videoPlayerRef = useRef(null); const [isPlaying, setIsPlaying] = React.useState(externalIsPlaying); const [isMediaPropertiesModalOpen, setIsMediaPropertiesModalOpen] = React.useState(false); const [detections, setDetections] = useState([]); const [scanState, setScanState] = useState<'idle' | 'scanning' | 'detected'>('idle'); const [isReplaceLibraryOpen, setIsReplaceLibraryOpen] = useState(false); const [isReplacePanelOpen, setIsReplacePanelOpen] = useState(false); const [shots, setShots] = useState([]); // 监听外部播放状态变化 useEffect(() => { setIsPlaying(externalIsPlaying); }, [externalIsPlaying]); // 确保 taskSketch 是数组 const sketches = Array.isArray(taskSketch) ? taskSketch : []; // 视频播放控制 useEffect(() => { if (videoPlayerRef.current) { if (isPlaying) { videoPlayerRef.current.play().catch(() => { // 处理自动播放策略限制 setIsPlaying(false); }); } else { // videoPlayerRef.current.pause(); } } }, [isPlaying, currentSketchIndex]); // 处理扫描开始 const handleScan = () => { if (scanState === 'detected') { // 如果已经有检测结果,点击按钮退出检测状态 setScanState('idle'); setDetections([]); // 清除检测结果 return; } setScanState('scanning'); // 模拟检测过程 setTimeout(() => { const mockDetections: PersonDetection[] = [ { id: '1', name: '人物1', position: { top: 0, left: 100, width: 100, height: 200 } } ]; setDetections(mockDetections); }, 5000); }; // 处理扫描超时/失败 const handleScanTimeout = () => { setScanState('idle'); setDetections([]); }; // 处理检测到结果 const handleDetectionsChange = (newDetections: PersonDetection[]) => { if (newDetections.length > 0 && scanState === 'scanning') { setScanState('detected'); } }; // 处理人物点击 打开角色库 const handlePersonClick = (person: PersonDetection) => { console.log('person', person); setIsReplaceLibraryOpen(true); }; // 从角色库中选择角色 const handleSelectCharacter = (index: number) => { console.log('index', index); setIsReplaceLibraryOpen(false); // 模拟打开替换面板 setTimeout(() => { setIsReplacePanelOpen(true); }, 1000); }; // 确认替换角色 const handleConfirmReplace = (selectedShots: string[], addToLibrary: boolean) => { }; // 切换选择分镜 const handleSelectShot = (index: number) => { // 切换前 判断数据是否发生变化 onSketchSelect(index); }; // 如果没有数据,显示空状态 if (sketches.length === 0) { return (

No sketch data

); } return (
{/* 上部分 */} {/* 分镜缩略图行 */}
handleSelectShot(i)} > {sketches.map((sketch, index) => ( ))}
{/* 视频描述行 - 单行滚动 */}
handleSelectShot(i)} > {sketches.map((video, index) => { const isActive = currentSketchIndex === index; return (
Shot {index + 1} {index < sketches.length - 1 && ( | )}
); })}
{/* 渐变遮罩 */}
{/* 下部分 */} {/* 视频预览和操作 */}
{/* 选中的视频预览 */} {/*
{/* 基础配置 */}
{ // 可以在这里添加其他逻辑 console.log('分镜添加成功'); }} onCharacterClick={(attrs) => { console.log('attrs', attrs); setIsReplaceLibraryOpen(true); }} /> {/* 重新生成按钮、新增分镜按钮 */}
editorRef.current?.addSegment()} className="flex items-center justify-center gap-2 px-4 py-3 bg-pink-500/10 hover:bg-pink-500/20 text-pink-500 rounded-lg transition-colors" whileHover={{ scale: 1.02 }} whileTap={{ scale: 0.98 }} > Add Shot console.log('Regenerate')} className="flex items-center justify-center gap-2 px-4 py-3 bg-blue-500/10 hover:bg-blue-500/20 text-blue-500 rounded-lg transition-colors" whileHover={{ scale: 1.02 }} whileTap={{ scale: 0.98 }} > Regenerate
{/* Media Properties 弹窗 */} setIsMediaPropertiesModalOpen(false)} taskSketch={taskSketch} currentSketchIndex={currentSketchIndex} onSketchSelect={onSketchSelect} /> setIsReplacePanelOpen(false)} > setIsReplacePanelOpen(false)} onConfirm={handleConfirmReplace} />
); }