video-flow-b/components/ui/edit-modal.tsx
2025-06-30 12:48:25 +08:00

220 lines
7.4 KiB
TypeScript

'use client';
import React, { useState, useEffect } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { X, FileText, Users, Video, Music, Scissors, Settings } from 'lucide-react';
import { cn } from '@/public/lib/utils';
import { ScriptTabContent } from './script-tab-content';
import { VideoTabContent } from './video-tab-content';
import { SettingsTabContent } from './settings-tab-content';
import { CharacterTabContent } from './character-tab-content';
import { MusicTabContent } from './music-tab-content';
interface EditModalProps {
isOpen: boolean;
onClose: () => void;
activeEditTab: string;
taskStatus: string;
taskSketch: any[];
sketchVideo: any[];
currentSketchIndex: number;
onSketchSelect: (index: number) => void;
}
const tabs = [
{ id: '1', label: '脚本', icon: FileText },
{ id: '2', label: '角色', icon: Users },
{ id: '3', label: '分镜视频', icon: Video },
{ id: '4', label: '音乐', icon: Music },
// { id: '5', label: '剪辑', icon: Scissors },
{ id: 'settings', label: '设置', icon: Settings },
];
export function EditModal({
isOpen,
onClose,
activeEditTab,
taskStatus,
taskSketch,
sketchVideo,
currentSketchIndex,
onSketchSelect
}: EditModalProps) {
const [activeTab, setActiveTab] = useState(activeEditTab);
// 当 activeEditTab 改变时更新 activeTab
useEffect(() => {
setActiveTab(activeEditTab);
}, [activeEditTab]);
const isTabDisabled = (tabId: string) => {
if (tabId === 'settings') return false;
return parseInt(tabId) > parseInt(taskStatus);
};
const renderTabContent = () => {
switch (activeTab) {
case '1':
return (
<ScriptTabContent
taskSketch={taskSketch}
currentSketchIndex={currentSketchIndex}
onSketchSelect={onSketchSelect}
/>
);
case '2':
return (
<CharacterTabContent
taskSketch={taskSketch}
currentSketchIndex={currentSketchIndex}
onSketchSelect={onSketchSelect}
/>
);
case '3':
return (
<VideoTabContent
taskSketch={sketchVideo}
currentSketchIndex={currentSketchIndex}
onSketchSelect={onSketchSelect}
isPlaying={false}
/>
);
case '4':
return (
<MusicTabContent
taskSketch={taskSketch}
currentSketchIndex={currentSketchIndex}
onSketchSelect={onSketchSelect}
/>
);
case 'settings':
return (
<SettingsTabContent
onSettingChange={(key, value) => {
console.log('Setting changed:', key, value);
// TODO: 实现设置更新逻辑
}}
/>
);
default:
return (
<div className="min-h-[400px] flex items-center justify-center text-white/50">
{tabs.find(tab => tab.id === activeTab)?.label}
</div>
);
}
};
return (
<AnimatePresence>
{isOpen && (
<>
{/* 背景遮罩 */}
<motion.div
className="fixed inset-0 bg-black/60 backdrop-blur-sm z-50"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
onClick={onClose}
/>
{/* 弹窗内容 */}
<div className="fixed inset-x-0 bottom-0 z-50 flex justify-center">
<motion.div
className="w-[66%] min-w-[800px] bg-[#1a1b1e] rounded-t-2xl overflow-hidden"
initial={{ y: '100%' }}
animate={{ y: 0 }}
exit={{ y: '100%' }}
transition={{
type: 'spring',
damping: 25,
stiffness: 200,
}}
>
{/* 标签栏 */}
<div className="flex items-center gap-1 p-2 overflow-x-auto hide-scrollbar bg-white/5">
<div className="flex-1 flex gap-1">
{tabs.map((tab) => {
const Icon = tab.icon;
const disabled = isTabDisabled(tab.id);
return (
<motion.button
key={tab.id}
className={cn(
'flex items-center gap-2 px-4 py-2 rounded-lg transition-colors relative',
activeTab === tab.id ? 'text-white' : 'text-white/50',
disabled ? 'opacity-50 cursor-not-allowed' : 'hover:bg-white/10',
)}
onClick={() => !disabled && setActiveTab(tab.id)}
whileHover={disabled ? undefined : { scale: 1.02 }}
whileTap={disabled ? undefined : { scale: 0.98 }}
>
<Icon className="w-4 h-4" />
<span>{tab.label}</span>
{activeTab === tab.id && (
<motion.div
className="absolute bottom-0 left-0 right-0 h-0.5 bg-blue-500"
layoutId="activeTab"
transition={{ type: 'spring', damping: 20 }}
/>
)}
</motion.button>
);
})}
</div>
{/* 关闭按钮 */}
<div className="pl-4 border-l border-white/10">
<motion.button
className="p-2 rounded-full hover:bg-white/10 transition-colors"
onClick={onClose}
whileHover={{ rotate: 90 }}
whileTap={{ scale: 0.9 }}
>
<X className="w-5 h-5 text-white/70" />
</motion.button>
</div>
</div>
{/* 内容区域 */}
<div className="h-[80vh] overflow-y-auto p-4">
<AnimatePresence mode="wait">
<motion.div
key={activeTab}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -20 }}
transition={{ duration: 0.2 }}
>
{renderTabContent()}
</motion.div>
</AnimatePresence>
</div>
{/* 底部操作栏 */}
<div className="p-4 border-t border-white/10 bg-black/20">
<div className="flex justify-end gap-3">
<motion.button
className="px-4 py-2 rounded-lg bg-white/10 text-white hover:bg-white/20 transition-colors"
whileHover={{ scale: 1.02 }}
whileTap={{ scale: 0.98 }}
onClick={onClose}
>
</motion.button>
<motion.button
className="px-4 py-2 rounded-lg bg-blue-500 text-white hover:bg-blue-600 transition-colors"
whileHover={{ scale: 1.02 }}
whileTap={{ scale: 0.98 }}
>
</motion.button>
</div>
</div>
</motion.div>
</div>
</>
)}
</AnimatePresence>
);
}