forked from 77media/video-flow
151 lines
5.6 KiB
TypeScript
151 lines
5.6 KiB
TypeScript
'use client';
|
|
|
|
import React, { useState } from 'react';
|
|
import { motion, AnimatePresence } from 'framer-motion';
|
|
import { X, ChevronDown } from 'lucide-react';
|
|
import { cn } from '@/public/lib/utils';
|
|
|
|
interface GenerateVideoModalProps {
|
|
isOpen: boolean;
|
|
onClose: () => void;
|
|
onGenerate: (params: { text: string; duration: string }) => void;
|
|
}
|
|
|
|
export function GenerateVideoModal({
|
|
isOpen,
|
|
onClose,
|
|
onGenerate
|
|
}: GenerateVideoModalProps) {
|
|
const [text, setText] = useState('');
|
|
const [duration, setDuration] = useState('5');
|
|
const [videoUrl, setVideoUrl] = useState('');
|
|
|
|
const handleGenerate = () => {
|
|
onGenerate({ text, duration });
|
|
};
|
|
|
|
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 justify-between p-4 border-b border-white/10">
|
|
<div className="flex items-center gap-2">
|
|
<button
|
|
className="p-1 hover:bg-white/10 rounded-full transition-colors"
|
|
onClick={onClose}
|
|
>
|
|
<ChevronDown className="w-5 h-5" />
|
|
</button>
|
|
<h2 className="text-lg font-medium">生成视频</h2>
|
|
</div>
|
|
</div>
|
|
|
|
{/* 主要内容区域 */}
|
|
<div className="p-6 space-y-6 h-[80vh] flex flex-col overflow-y-auto hide-scrollbar">
|
|
{/* 文本输入区域 */}
|
|
<div className="space-y-2 flex-shrink-0">
|
|
<label className="text-sm text-white/70">描述场景</label>
|
|
<textarea
|
|
className="w-full h-32 p-4 bg-white/5 border border-white/10 rounded-lg
|
|
text-white placeholder-white/30 resize-none focus:outline-none focus:border-blue-500"
|
|
placeholder="描述你想要生成的视频场景..."
|
|
value={text}
|
|
onChange={(e) => setText(e.target.value)}
|
|
/>
|
|
</div>
|
|
|
|
{/* 时长选择 */}
|
|
{/* <div className="space-y-2">
|
|
<label className="text-sm text-white/70">视频时长(秒)</label>
|
|
<div className="flex gap-2">
|
|
{['5', '10', '15', '30'].map((value) => (
|
|
<motion.button
|
|
key={value}
|
|
className={cn(
|
|
'px-4 py-2 rounded-lg transition-colors',
|
|
duration === value
|
|
? 'bg-blue-500 text-white'
|
|
: 'bg-white/5 hover:bg-white/10'
|
|
)}
|
|
onClick={() => setDuration(value)}
|
|
whileHover={{ scale: 1.05 }}
|
|
whileTap={{ scale: 0.95 }}
|
|
>
|
|
{value}秒
|
|
</motion.button>
|
|
))}
|
|
</div>
|
|
</div> */}
|
|
|
|
{/* 生成按钮 */}
|
|
<div className="flex justify-end flex-shrink-0">
|
|
<motion.button
|
|
className="px-6 py-2 bg-blue-500 hover:bg-blue-600 rounded-lg
|
|
transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
|
|
onClick={handleGenerate}
|
|
disabled={!text.trim()}
|
|
whileHover={{ scale: 1.02 }}
|
|
whileTap={{ scale: 0.98 }}
|
|
>
|
|
生成视频
|
|
</motion.button>
|
|
</div>
|
|
|
|
{/* 生成视频预览 */}
|
|
<div className="flex justify-center flex-1 min-h-[450px]">
|
|
<div className="w-[80%] bg-white/5 rounded-lg">
|
|
<video src={videoUrl} className="w-full object-cover" autoPlay />
|
|
</div>
|
|
</div>
|
|
</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>
|
|
);
|
|
}
|