"use client"; import { useEffect, useRef, useState } from "react"; import { Modal, Tooltip, Popconfirm, Upload, Dropdown } from "antd"; import { ImagePlay, Sparkles, Trash2 } from "lucide-react"; import { useRouter } from "next/navigation"; import GlobalLoad from "../common/GlobalLoad"; import { ActionButton } from "../common/ActionButton"; import { HighlightEditor } from "../common/HighlightEditor"; import { useImageStoryServiceHook } from "@/app/service/Interaction/ImageStoryService"; import { useLoadScriptText } from "@/app/service/domain/service"; import { AspectRatioSelector, AspectRatioValue } from "./AspectRatioSelector"; type ConfigOptions = { mode: "auto" | "manual"; resolution: "720p" | "1080p" | "4k"; language: string; videoDuration: string; }; export const PcPhotoStoryModal = ({ isCreating, setIsCreating, isPhotoCreating, setIsPhotoCreating, isOpen, onClose, configOptions = { mode: "auto", resolution: "720p", language: "english", videoDuration: "1min", }, }: { isOpen: boolean; onClose: () => void; isCreating: boolean; setIsCreating: (value: boolean) => void; isPhotoCreating: boolean; setIsPhotoCreating: (value: boolean) => void; configOptions?: ConfigOptions; }) => { const { activeImageUrl, storyContent, potentialGenres, selectedCategory, isLoading, hasAnalyzed, taskProgress, updateStoryType, updateStoryContent, updateCharacterName, resetImageStory, triggerFileSelection, avatarComputed, uploadAndAnalyzeImage, setCharactersAnalysis, originalUserDescription, actionMovie, uploadCharacterAvatarAndAnalyzeFeatures, } = useImageStoryServiceHook(); const { loadingText } = useLoadScriptText(isLoading); const [localLoading, setLocalLoading] = useState(0); const [aspectUI, setAspectUI] = useState("VIDEO_ASPECT_RATIO_LANDSCAPE"); const router = useRouter(); const taskProgressRef = useRef(taskProgress); const [cursorPosition, setCursorPosition] = useState(0); const handleCursorPositionChange = (position: number) => { setCursorPosition(position); }; useEffect(() => { taskProgressRef.current = taskProgress; }, [taskProgress]); const handleClose = () => { onClose(); }; const handleImageUpload = async (e: any) => { const target = e.target as HTMLImageElement; if (!(target.tagName == "IMG" || e.target.dataset.alt == "image-upload-area")) { return; } e.preventDefault(); e.stopPropagation(); try { await triggerFileSelection(); } catch (error) { console.error("Failed to upload image:", error); } }; const handleConfirm = async () => { try { setIsCreating(true); const User = JSON.parse(localStorage.getItem("currentUser") || "{}"); if (!User.id) { console.error("用户未登录"); return; } const episodeResponse = await actionMovie( String(User.id), configOptions.mode as "auto" | "manual", configOptions.resolution as "720p" | "1080p" | "4k", configOptions.language, aspectUI as AspectRatioValue ); if (!episodeResponse) return; const episodeId = episodeResponse.project_id; router.push(`/movies/work-flow?episodeId=${episodeId}`); handleClose(); } catch (error) { setIsCreating(false); console.error("创建电影项目失败:", error); } }; const handleAnalyzeImage = async () => { if (isPhotoCreating || isLoading) return; setIsPhotoCreating(true); let timeout = 100; let timer: NodeJS.Timeout; timer = setInterval(() => { const currentProgress = taskProgressRef.current; setLocalLoading((prev) => { if (prev >= currentProgress && currentProgress != 0) { return currentProgress; } return prev + 0.1; }); }, timeout); try { await uploadAndAnalyzeImage(); } catch (error) { console.error("分析图片失败:", error); setIsPhotoCreating(false); } finally { clearInterval(timer); setLocalLoading(0); } }; return ( × } > 0} progress={localLoading}>

Movie Generation from Image

{activeImageUrl ? (
Story inspiration { resetImageStory(); }} okText="Yes" cancelText="No" showCancel={false} okType="default" placement="top" classNames={{ root: "text-white event-pointer", body: "text-white border rounded-lg bg-white/[0.04] [&_.ant-popconfirm-description]:!text-white [&_.ant-popconfirm-title]:!text-white [&_.ant-btn]:!text-white", }} >
) : (

Upload

)}
{hasAnalyzed && avatarComputed.length > 0 && (
{avatarComputed.map((avatar, index) => (
{avatar.name} { const target = e.target as HTMLImageElement; target.src = activeImageUrl; }} />
{ const newName = e.target.value.trim(); if (newName && newName !== avatar.name) { updateCharacterName(avatar.name, newName); } }} className="w-16 text-center text-sm text-white/80 bg-transparent border-none outline-none focus:ring-1 focus:ring-blue-400/50 rounded px-1 py-0.5 transition-all duration-200" style={{ textAlign: "center" }} />
))}
)}
{hasAnalyzed && potentialGenres.length > 0 && (
{[...potentialGenres].map((genre) => ( ))}
)}
{originalUserDescription && (
Your Provided Text:{originalUserDescription}
)}
{/* 横/竖屏选择 */} {!hasAnalyzed ? ( } disabled={isLoading || isPhotoCreating} /> ) : ( } disabled={isCreating} /> )}
); };