'use client'; import React, { useRef, useEffect, useState } from 'react'; import { motion } from 'framer-motion'; import { Skeleton } from '@/components/ui/skeleton'; import { ProgressiveReveal, presets } from '@/components/ui/progressive-reveal'; interface ThumbnailGridProps { isLoading: boolean; currentStep: string; currentSketchIndex: number; taskSketch: any[]; taskVideos: any[]; isGeneratingSketch: boolean; isGeneratingVideo: boolean; sketchCount: number; totalSketchCount: number; onSketchSelect: (index: number) => void; } export function ThumbnailGrid({ isLoading, currentStep, currentSketchIndex, taskSketch, taskVideos, isGeneratingSketch, isGeneratingVideo, sketchCount, totalSketchCount, onSketchSelect }: ThumbnailGridProps) { const thumbnailsRef = useRef(null); const [isDragging, setIsDragging] = useState(false); const [startX, setStartX] = useState(0); const [scrollLeft, setScrollLeft] = useState(0); // 监听当前选中索引变化,自动滚动到对应位置 useEffect(() => { if (thumbnailsRef.current && taskSketch.length > 0) { const container = thumbnailsRef.current; const thumbnailWidth = container.offsetWidth / 4; // 每个缩略图宽度(包含间距) const scrollPosition = currentSketchIndex * thumbnailWidth; container.scrollTo({ left: scrollPosition, behavior: 'smooth' }); } }, [currentSketchIndex, taskSketch.length]); // 处理鼠标/触摸拖动事件 const handleMouseDown = (e: React.MouseEvent) => { setIsDragging(true); setStartX(e.pageX - thumbnailsRef.current!.offsetLeft); setScrollLeft(thumbnailsRef.current!.scrollLeft); }; const handleMouseMove = (e: React.MouseEvent) => { if (!isDragging) return; e.preventDefault(); const x = e.pageX - thumbnailsRef.current!.offsetLeft; const walk = (x - startX) * 2; thumbnailsRef.current!.scrollLeft = scrollLeft - walk; }; const handleMouseUp = (e: React.MouseEvent) => { setIsDragging(false); if (!isDragging) return; const container = thumbnailsRef.current!; const thumbnailWidth = container.offsetWidth / 4; const currentScroll = container.scrollLeft; const nearestIndex = Math.round(currentScroll / thumbnailWidth); // 只有在拖动距离较小时才触发选中 const x = e.pageX - container.offsetLeft; const walk = Math.abs(x - startX); if (walk < 10) { return; // 如果拖动距离太小,保持原有的点击选中逻辑 } onSketchSelect(Math.min(Math.max(0, nearestIndex), taskSketch.length - 1)); }; // 渲染加载状态 if (isLoading) { return ( <> ); } // 最终成片阶段不显示缩略图 if (Number(currentStep) === 6) { return null; } // 渲染生成中的缩略图 const renderGeneratingThumbnail = () => { const currentSketch = taskSketch[currentSketchIndex]; const defaultBgColors = ['RGB(45, 50, 70)', 'RGB(75, 80, 100)', 'RGB(105, 110, 130)']; const bgColors = currentSketch?.bg_rgb || defaultBgColors; return ( {/* 动态渐变背景 */} {/* 动态光效 */}
Scene {sketchCount + 1}
); }; // 渲染视频阶段的缩略图 const renderVideoThumbnails = () => ( taskSketch.map((sketch, index) => { const defaultBgColors = ['RGB(45, 50, 70)', 'RGB(75, 80, 100)', 'RGB(105, 110, 130)']; const bgColors = sketch?.bg_rgb || defaultBgColors; return (
!isDragging && onSketchSelect(index)} > {/* 底层草图,始终显示 */}
{`Thumbnail
{/* 视频层,只在有视频时用ProgressiveReveal动画显示 */} {taskVideos[index] && (
{isGeneratingVideo ? (
) : ( /* 生成完成后直接显示视频,不使用ProgressiveReveal */
)}
)}
Scene {index + 1}
); }) ); // 渲染分镜草图阶段的缩略图 const renderSketchThumbnails = () => ( <> {taskSketch.map((sketch, index) => { const defaultBgColors = ['RGB(45, 50, 70)', 'RGB(75, 80, 100)', 'RGB(105, 110, 130)']; const bgColors = sketch?.bg_rgb || defaultBgColors; return (
!isDragging && onSketchSelect(index)} > {/* 只在生成过程中或没有分镜图片时使用ProgressiveReveal */} {(isGeneratingSketch || !sketch) ? (
{`Thumbnail
) : ( /* 生成完成后直接显示,不使用ProgressiveReveal */
{`Thumbnail
)}
Scene {index + 1}
); })} {isGeneratingSketch && sketchCount < totalSketchCount && renderGeneratingThumbnail()} ); return (
setIsDragging(false)} > {Number(currentStep) > 2 && Number(currentStep) < 6 ? renderVideoThumbnails() : renderSketchThumbnails() }
); }