diff --git a/app/create/script-to-video/page.tsx b/app/create/script-to-video/page.tsx deleted file mode 100644 index 2e38915..0000000 --- a/app/create/script-to-video/page.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import { ScriptToVideo } from '@/components/pages/script-to-video'; - -export default function ScriptToVideoPage() { - return ; -} \ No newline at end of file diff --git a/app/create/video-to-video/page.tsx b/app/create/video-to-video/page.tsx deleted file mode 100644 index 9a8685b..0000000 --- a/app/create/video-to-video/page.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import { VideoToVideo } from '@/components/pages/video-to-video'; - -export default function VideoToVideoPage() { - return ; -} \ No newline at end of file diff --git a/app/history/page.tsx b/app/history/page.tsx index 300dd4d..cf84544 100644 --- a/app/history/page.tsx +++ b/app/history/page.tsx @@ -1,10 +1,11 @@ import { DashboardLayout } from '@/components/layout/dashboard-layout'; -import { HistoryPage } from '@/components/pages/history-page'; export default function History() { return ( - +
+

History

+
); } \ No newline at end of file diff --git a/components/common/EmptyStateAnimation.tsx b/components/common/EmptyStateAnimation.tsx deleted file mode 100644 index 86254fd..0000000 --- a/components/common/EmptyStateAnimation.tsx +++ /dev/null @@ -1,328 +0,0 @@ -"use client"; - -import React, { useState, useEffect, useRef, useCallback } from 'react'; -import { ArrowUp } from 'lucide-react'; -import gsap from 'gsap'; -import { ImageWave } from '@/components/ui/ImageWave'; - -interface AnimationStageProps { - shouldStart: boolean; - onComplete: () => void; -} - -// 动画1:模拟输入和点击 -const InputAnimation: React.FC = ({ shouldStart, onComplete }) => { - const containerRef = useRef(null); - const inputRef = useRef(null); - const cursorRef = useRef(null); - const buttonRef = useRef(null); - const mouseRef = useRef(null); - const [displayText, setDisplayText] = useState(''); - - const demoText = "a cute capybara with an orange on its head"; - - useEffect(() => { - if (!shouldStart || !containerRef.current) return; - - // 重置状态 - setDisplayText(''); - - const tl = gsap.timeline({ - onComplete: () => { - setTimeout(onComplete, 500); - } - }); - - // 1. 显示输入框和鼠标 - tl.fromTo([inputRef.current, mouseRef.current], { - scale: 0.9, - opacity: 0 - }, { - scale: 1, - opacity: 1, - duration: 0.3, - ease: "back.out(1.7)", - stagger: 0.1 - }); - - // 2. 鼠标移动到输入框中心 - tl.to(mouseRef.current, { - x: 20, - y: 0, - duration: 0.3 - }); - - // 3. 输入框聚焦效果 - tl.to(inputRef.current, { - scale: 1.02, - boxShadow: '0 0 0 2px rgba(59, 130, 246, 0.5)', - duration: 0.2 - }); - - // 4. 打字动画 - const typingDuration = demoText.length * 0.05; - tl.to({}, { - duration: typingDuration, - onUpdate: function() { - const progress = this.progress(); - const targetChar = Math.floor(progress * demoText.length); - setDisplayText(demoText.slice(0, targetChar)); - } - }); - - // 6. 鼠标移动到按钮位置(调整移动时间和缓动函数) - tl.to(mouseRef.current, { - x: 650, - y: 0, - duration: 0.8, - ease: "power2.inOut" - }); - - // 7. 等待一小段时间 - tl.to({}, { duration: 0.2 }); - - // 8. 点击效果 - tl.to(mouseRef.current, { - scale: 0.8, - duration: 0.1, - yoyo: true, - repeat: 1 - }).to(buttonRef.current, { - scale: 0.95, - duration: 0.1, - yoyo: true, - repeat: 1 - }, "<"); - - // 9. 等待一小段时间 - tl.to({}, { duration: 0.3 }); - - // 10. 整体淡出 - tl.to(containerRef.current, { - opacity: 0, - y: -20, - duration: 0.3 - }); - - }, [shouldStart, onComplete]); - - return ( -
-
-
- - {displayText} - -
-
- - - -
- - - -
-
-
- ); -}; - -// 动画2:ImageWave 动画展示 -const WaveAnimation: React.FC = ({ shouldStart, onComplete }) => { - const containerRef = useRef(null); - const [showWave, setShowWave] = useState(false); - const [autoAnimate, setAutoAnimate] = useState(false); - - const imageUrls = [ - 'https://d3phaj0sisr2ct.cloudfront.net/app/gen4/object-reference/welcome-ref-1.jpg', - 'https://d3phaj0sisr2ct.cloudfront.net/app/gen4/object-reference/welcome-ref-2.jpg', - 'https://d3phaj0sisr2ct.cloudfront.net/app/gen4/object-reference/welcome-ref-3.jpg', - 'https://d3phaj0sisr2ct.cloudfront.net/app/gen4/object-reference/welcome-ref-4.jpg', - 'https://d3phaj0sisr2ct.cloudfront.net/app/gen4/object-reference/welcome-ref-1.jpg', - 'https://d3phaj0sisr2ct.cloudfront.net/app/gen4/object-reference/welcome-ref-2.jpg', - 'https://d3phaj0sisr2ct.cloudfront.net/app/gen4/object-reference/welcome-ref-3.jpg', - 'https://d3phaj0sisr2ct.cloudfront.net/app/gen4/object-reference/welcome-ref-4.jpg', - 'https://d3phaj0sisr2ct.cloudfront.net/app/gen4/object-reference/welcome-ref-3.jpg', - 'https://d3phaj0sisr2ct.cloudfront.net/app/gen4/object-reference/welcome-ref-2.jpg', - 'https://d3phaj0sisr2ct.cloudfront.net/app/gen4/object-reference/welcome-ref-1.jpg', - ]; - - useEffect(() => { - if (!shouldStart) { - setShowWave(false); - setAutoAnimate(false); - return; - } - - // 显示 ImageWave - setShowWave(true); - - // 延迟开始自动动画 - const startTimeout = setTimeout(() => { - setAutoAnimate(true); - }, 300); - - return () => { - clearTimeout(startTimeout); - }; - }, [shouldStart]); - - const handleAnimationComplete = () => { - // 动画完成后淡出并触发完成回调 - gsap.to(containerRef.current, { - opacity: 0, - scale: 0.9, - duration: 0.3, - onComplete: () => { - setAutoAnimate(false); - setShowWave(false); - onComplete(); - } - }); - }; - - return ( -
- -
- ); -}; - -// 动画3:图片墙打破,显示视频 -const FinalAnimation: React.FC = ({ shouldStart, onComplete }) => { - const containerRef = useRef(null); - const videoRef = useRef(null); - const [showVideo, setShowVideo] = useState(false); - - const videoUrl = 'https://cdn.qikongjian.com/videos/1750385931_99a8fb42-af89-4ae9-841a-a49869f026bd_text_to_video_0.mp4'; - - useEffect(() => { - if (!shouldStart || !containerRef.current) return; - - const tl = gsap.timeline({ - onComplete: () => { - setTimeout(() => { - // 淡出视频 - gsap.to(containerRef.current, { - opacity: 0, - scale: 0.9, - duration: 0.3, - onComplete - }); - }, 3000); - } - }); - - // 显示容器 - tl.fromTo(containerRef.current, - { opacity: 0, scale: 0.9 }, - { opacity: 1, scale: 1, duration: 0.3 } - ); - - // 显示视频 - setShowVideo(true); - - }, [shouldStart, onComplete]); - - return ( -
- {showVideo && ( -
- ); -}; - -// 主组件 -export const EmptyStateAnimation = ({ className }: { className: string }) => { - const [currentStage, setCurrentStage] = useState<'input' | 'wave' | 'final'>('input'); - const [animationCycle, setAnimationCycle] = useState(0); - const [isReady, setIsReady] = useState(true); - - const handleStageComplete = useCallback(() => { - // 先将当前阶段标记为不可执行 - setIsReady(false); - - // 延迟切换到下一个阶段 - setTimeout(() => { - switch (currentStage) { - case 'input': - setCurrentStage('wave'); - break; - case 'wave': - setCurrentStage('final'); - break; - case 'final': - setAnimationCycle(prev => prev + 1); - setCurrentStage('input'); - break; - } - - // 给下一个阶段一些准备时间 - setTimeout(() => { - setIsReady(true); - }, 100); - }, 300); - }, [currentStage]); - - return ( -
- - - -
- ); -}; \ No newline at end of file diff --git a/components/pages/history-page.tsx b/components/pages/history-page.tsx deleted file mode 100644 index c590883..0000000 --- a/components/pages/history-page.tsx +++ /dev/null @@ -1,224 +0,0 @@ -"use client"; - -import { useState, useEffect } from 'react'; -import { Card } from '@/components/ui/card'; -import { Button } from '@/components/ui/button'; -import { Badge } from '@/components/ui/badge'; -import { Input } from '@/components/ui/input'; -import { - Search, - Filter, - Video, - Calendar, - Eye, - Edit, - Trash2, - MoreHorizontal, - Play -} from 'lucide-react'; -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuTrigger -} from '@/components/ui/dropdown-menu'; - -interface HistoryItem { - id: number; - title: string; - type: 'script-to-video' | 'video-to-video'; - status: 'completed' | 'processing' | 'failed'; - createdAt: string; - duration?: string; - thumbnail?: string; -} - -export function HistoryPage() { - const [searchTerm, setSearchTerm] = useState(''); - const [historyItems, setHistoryItems] = useState([]); - const [filteredItems, setFilteredItems] = useState([]); - - // Mock data - replace with actual API call - useEffect(() => { - const mockData: HistoryItem[] = [ - { - id: 1, - title: "Sample Script Video", - type: "script-to-video", - status: "completed", - createdAt: "2024-01-15", - duration: "2:30", - thumbnail: "/assets/empty_video.png" - }, - { - id: 2, - title: "Video Enhancement Project", - type: "video-to-video", - status: "processing", - createdAt: "2024-01-14", - duration: "1:45" - }, - { - id: 3, - title: "Marketing Video", - type: "script-to-video", - status: "completed", - createdAt: "2024-01-13", - duration: "3:15", - thumbnail: "/assets/empty_video.png" - } - ]; - setHistoryItems(mockData); - setFilteredItems(mockData); - }, []); - - // Filter items based on search term - useEffect(() => { - const filtered = historyItems.filter(item => - item.title.toLowerCase().includes(searchTerm.toLowerCase()) - ); - setFilteredItems(filtered); - }, [searchTerm, historyItems]); - - const getStatusBadgeVariant = (status: string) => { - switch (status) { - case 'completed': - return 'default'; - case 'processing': - return 'secondary'; - case 'failed': - return 'destructive'; - default: - return 'default'; - } - }; - - const getTypeIcon = (type: string) => { - return type === 'script-to-video' ? '📝' : '🎥'; - }; - - return ( -
- {/* Header */} -
-
-

Project History

-

View and manage your video projects

-
- - {/* Search and Filter */} -
-
- - setSearchTerm(e.target.value)} - className="pl-10 bg-white/5 border-white/20 text-white placeholder:text-white/40" - /> -
- -
-
- - {/* Project Grid */} - {filteredItems.length === 0 ? ( - - - ) : ( -
- {filteredItems.map((item) => ( - - {/* Thumbnail */} -
- {item.thumbnail ? ( - {item.title} - ) : ( -
-
- )} - - {/* Play overlay */} -
- -
- - {/* Type indicator */} -
- {getTypeIcon(item.type)} -
- - {/* Duration */} - {item.duration && ( -
- {item.duration} -
- )} -
- - {/* Content */} -
-
-

- {item.title} -

- - - - - - - - View - - - - Edit - - - - Delete - - - -
- -
-
- - {item.createdAt} -
- - {item.status} - -
-
-
- ))} -
- )} -
- ); -} \ No newline at end of file diff --git a/components/pages/home-page2.tsx b/components/pages/home-page2.tsx index 77b8644..9a55abf 100644 --- a/components/pages/home-page2.tsx +++ b/components/pages/home-page2.tsx @@ -88,8 +88,8 @@ export function HomePage2() { const projectData: CreateScriptProjectRequest = { title: "script default", // 默认剧本名称 project_type: projectType, - mode: ModeEnum.MANUAL, - resolution: ResolutionEnum.FULL_HD_1080P + mode: ModeEnum.MANUAL === 'manual' ? 1 : 2, // 1 表示手动模式,2 表示自动模式 + resolution: 1080 // 1080p 分辨率 }; const projectResponse = await createScriptProject(projectData); @@ -121,7 +121,7 @@ export function HomePage2() { {/* 工具栏-列表形式切换 */}
{ + onClick={(e: React.MouseEvent) => { e.stopPropagation(); handleToolChange(activeTool === "stretch" ? "right" : "left"); }} diff --git a/components/pages/script-to-video.tsx b/components/pages/script-to-video.tsx deleted file mode 100644 index bf8f914..0000000 --- a/components/pages/script-to-video.tsx +++ /dev/null @@ -1,168 +0,0 @@ -"use client"; - -import { useState } from 'react'; -import { Button } from '@/components/ui/button'; -import { Card } from '@/components/ui/card'; -import { Textarea } from '@/components/ui/textarea'; -import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; -import { ArrowLeft, Loader2 } from 'lucide-react'; -import { useRouter } from 'next/navigation'; -import { ModeEnum, ResolutionEnum } from "@/app/model/enums"; -import { createScriptEpisode, CreateScriptEpisodeRequest, updateScriptEpisode, UpdateScriptEpisodeRequest } from "@/api/script_episode"; -import { convertScriptToScene } from "@/api/video_flow"; - -export function ScriptToVideo() { - const router = useRouter(); - const [script, setScript] = useState(''); - const [selectedMode, setSelectedMode] = useState(ModeEnum.AUTOMATIC); - const [selectedResolution, setSelectedResolution] = useState(ResolutionEnum.HD_720P); - const [isCreating, setIsCreating] = useState(false); - - const handleBack = () => { - router.push('/create'); - }; - - const handleCreate = async () => { - if (!script.trim()) { - alert('请输入剧本内容'); - return; - } - - try { - setIsCreating(true); - - // Create episode - const episodeData: CreateScriptEpisodeRequest = { - title: "Script Episode", - script_id: 0, // This should come from a project - status: 1, - summary: script - }; - - const episodeResponse = await createScriptEpisode(episodeData); - if (episodeResponse.code !== 0) { - alert(`创建剧集失败: ${episodeResponse.message}`); - return; - } - - const episodeId = episodeResponse.data.id; - - // Convert script to scenes - const convertResponse = await convertScriptToScene(script, episodeId, 0); - - if (convertResponse.code === 0) { - // Update episode with generated data - const updateEpisodeData: UpdateScriptEpisodeRequest = { - id: episodeId, - atmosphere: convertResponse.data.atmosphere, - summary: convertResponse.data.summary, - scene: convertResponse.data.scene, - characters: convertResponse.data.characters, - }; - - await updateScriptEpisode(updateEpisodeData); - - // Navigate to workflow - router.push(`/create/work-flow?episodeId=${episodeId}`); - } else { - alert(`转换失败: ${convertResponse.message}`); - } - } catch (error) { - console.error('创建过程出错:', error); - alert("创建项目时发生错误,请稍后重试"); - } finally { - setIsCreating(false); - } - }; - - return ( -
-
- {/* Header */} -
- -

Script to Video

-
- - {/* Main Content */} - -
- {/* Script Input */} -
- -