import React, { useState, useRef, useEffect } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { ImageUp, Library, Play, Pause, RefreshCw, Wand2, Users, Check, ReplaceAll, X, TriangleAlert, Loader2 } from 'lucide-react'; import { cn } from '@/public/lib/utils'; import { CharacterEditor } from './character-editor'; import ImageBlurTransition from './ImageBlurTransition'; import FloatingGlassPanel from './FloatingGlassPanel'; import { ReplaceCharacterPanel } from './replace-character-panel'; import { CharacterLibrarySelector } from './character-library-selector'; import HorizontalScroller from './HorizontalScroller'; import { useEditData } from '@/components/pages/work-flow/use-edit-data'; import { useSearchParams } from 'next/navigation'; import { RoleEntity } from '@/app/service/domain/Entities'; interface Appearance { hairStyle: string; skinTone: string; facialFeatures: string; bodyType: string; } interface Role { name: string; url: string; sound: string; soundDescription: string; roleDescription: string; age: number; gender: 'male' | 'female' | 'other'; ethnicity: string; appearance: Appearance; // 新增标签数组 tags: string[]; } // Mock 数据 const mockRole: Role = { name: "青春女学生", url: "/assets/3dr_chihiro.png", sound: "", soundDescription: "", roleDescription: "一位充满活力和梦想的高中女生,蓝色长发随风飘扬,眼神中透露着对未来的憧憬。她身着整洁的校服,举止优雅而不失活力。", age: 16, gender: 'female', ethnicity: '亚洲人', appearance: { hairStyle: "鲜艳蓝色长发", skinTone: "白皙", facialFeatures: "大眼睛,清秀五官", bodyType: "苗条" }, tags: ['高中生', '校服', '蓝色长发', '大眼睛', '清秀五官', '苗条'] }; interface CharacterTabContentProps { taskSketch: any[]; currentRoleIndex: number; onSketchSelect: (index: number) => void; roles: Role[]; } export function CharacterTabContent({ taskSketch, currentRoleIndex, onSketchSelect, roles = [mockRole] }: CharacterTabContentProps) { const [isReplacePanelOpen, setIsReplacePanelOpen] = useState(false); const [replacePanelKey, setReplacePanelKey] = useState(0); const [ignoreReplace, setIgnoreReplace] = useState(false); const [isReplaceLibraryOpen, setIsReplaceLibraryOpen] = useState(false); const [isRemindReplacePanelOpen, setIsRemindReplacePanelOpen] = useState(false); const fileInputRef = useRef(null); const [enableAnimation, setEnableAnimation] = useState(true); const [showAddToLibrary, setShowAddToLibrary] = useState(true); const characterEditorRef = useRef(null); const [isInitialized, setIsInitialized] = useState(false); const [isRegenerate, setIsRegenerate] = useState(false); const [isLoadingShots, setIsLoadingShots] = useState(false); const [isLoadingLibrary, setIsLoadingLibrary] = useState(false); const [isUploading, setIsUploading] = useState(false); const { loading, roleData, selectRole, selectedRole, userRoleLibrary, optimizeRoleText, updateRoleText, regenerateRole, fetchUserRoleLibrary, uploadImageAndUpdateRole, // role shot shotSelectionList, fetchRoleShots, applyRoleToSelectedShots, saveRoleToLibrary } = useEditData('role'); const searchParams = useSearchParams(); const episodeId = searchParams.get('episodeId'); useEffect(() => { console.log('-==========roleData===========-', roleData); // 只在初始化且有角色数据时执行 if (!isInitialized && roleData.length > 0) { selectRole(roleData[0]); setIsInitialized(true); } }, [roleData, isInitialized]); useEffect(() => { console.log('获取选中项数据', selectedRole); }, [selectedRole]); useEffect(() => { console.log('获取角色库数据', userRoleLibrary); }, [userRoleLibrary]); const handleSmartPolish = (text: string) => { // 然后调用优化角色文本 optimizeRoleText(text); }; const handleStartReplaceCharacter = async () => { setIsLoadingShots(true); setIsReplacePanelOpen(true); // 获取当前角色对应的视频片段 await fetchRoleShots(selectedRole?.name || ''); // 打开替换角色面板 setIsLoadingShots(false); }; const handleConfirmGotoReplace = () => { setIsRemindReplacePanelOpen(false); setIsReplacePanelOpen(true); }; const handleCloseRemindReplacePanel = () => { setIsRemindReplacePanelOpen(false); setIgnoreReplace(true); }; // President Alfred King Samuel Ryan const handleConfirmReplace = (selectedShots: string[], addToLibrary: boolean) => { // 处理替换确认逻辑 console.log('Selected shots:', selectedShots); console.log('Add to library:', addToLibrary); applyRoleToSelectedShots(selectedRole || {} as RoleEntity); setIsReplacePanelOpen(false); if(addToLibrary){ saveRoleToLibrary(); } }; // 取消替换 const handleCloseReplacePanel = () => { setIsReplacePanelOpen(false); }; const handleChangeRole = (index: number) => { const oldRole = roleData.find(role => role.id === selectedRole?.id); console.log('切换角色前对比', selectedRole?.imageUrl, oldRole?.imageUrl); if (selectedRole?.imageUrl !== oldRole?.imageUrl && !ignoreReplace) { // 提示 角色已修改,弹出替换角色面板 setIsRemindReplacePanelOpen(true); return; } // 重置替换规则 setEnableAnimation(false); setIgnoreReplace(false); setIsRegenerate(false); selectRole(roleData[index]); }; // 从角色库中选择角色 const handleSelectCharacter = (index: number) => { console.log('选择的角色索引:', index); console.log('选择的角色数据:', userRoleLibrary[index]); setIsReplaceLibraryOpen(false); setShowAddToLibrary(false); // 使用真实的角色数据 const selectedRole = userRoleLibrary[index]; if (selectedRole) { handleStartReplaceCharacter(); } }; const handleOpenReplaceLibrary = async () => { setIsLoadingLibrary(true); setIsReplaceLibraryOpen(true); setShowAddToLibrary(true); await fetchUserRoleLibrary(); setIsLoadingLibrary(false); }; const handleRegenerate = async () => { console.log('Regenerate'); setIsRegenerate(true); // const text = characterEditorRef.current.getRoleText(); // console.log('-==========text===========-', text); // // 重生前 更新 当前项 generateText // updateRoleText(text); // 然后调用重新生成角色 await regenerateRole(); setIsRegenerate(false); handleStartReplaceCharacter(); }; const handleUploadClick = () => { fileInputRef.current?.click(); }; const handleFileChange = (event: React.ChangeEvent) => { const file = event.target.files?.[0]; if (!file) { setIsUploading(false); return; }; // 检查文件类型 if (!file.type.startsWith('image/')) { alert('请选择图片文件'); setIsUploading(false); return; } setIsUploading(true); uploadImageAndUpdateRole(file).then((data) => { console.log('上传图片成功', data); // 清空input的值,这样同一个文件可以重复选择 event.target.value = ''; setIsUploading(false); }); }; // 如果loading 显示loading状态 if (loading) { return (

Loading...

); } // 如果没有角色数据,显示占位内容 if (roleData.length === 0) { return (

No role data

); } return (
{/* 隐藏的文件输入框 */} {/* 上部分:角色缩略图 */}
role.id === selectedRole?.id)} onItemClick={(i: number) => handleChangeRole(i)} > {roleData.map((role, index) => ( {role.name}
{role.name}
))}
{/* 下部分:角色详情 */} {/* 左列:角色预览 */}
{/* 角色预览图 */}
{/* 应用角色按钮 */}
{isUploading ? : } handleOpenReplaceLibrary()} >
{/* 右列:角色信息 */}
updateRoleText(text)} /> {/* 重新生成按钮、替换形象按钮 */}
handleStartReplaceCharacter()} className="flex items-center justify-center gap-2 px-4 py-3 bg-pink-500/10 hover:bg-pink-500/20 text-pink-500 rounded-lg transition-colors" whileHover={{ scale: 1.02 }} whileTap={{ scale: 0.98 }} > Replace handleRegenerate()} className="flex items-center justify-center gap-2 px-4 py-3 bg-blue-500/10 hover:bg-blue-500/20 text-blue-500 rounded-lg transition-colors disabled:opacity-50 disabled:cursor-not-allowed" whileHover={{ scale: 1.02 }} whileTap={{ scale: 0.98 }} disabled={isRegenerate} > {isRegenerate ? 'Regenerating...' : 'Regenerate'}
handleCloseReplacePanel()} > handleCloseReplacePanel()} onConfirm={handleConfirmReplace} /> {/* 从角色库中选择角色 */} {/* 提醒用户角色已修改 是否需要替换 */}

角色已修改,是否需要替换?

); }