import React, { useState, useRef } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { Upload, Library, Play, Pause, RefreshCw, Wand2, Users, Check, ReplaceAll, X } from 'lucide-react'; import { cn } from '@/public/lib/utils'; import { GlassIconButton } from './glass-icon-button'; import { ReplaceCharacterModal } from './replace-character-modal'; import { Slider } from './slider'; import CharacterEditor from './character-editor'; import ImageBlurTransition from './ImageBlurTransition'; import FloatingGlassPanel from './FloatingGlassPanel'; import { ReplaceCharacterPanel, mockShots, mockCharacter } from './replace-character-panel'; import { ImageWave } from '@/components/ui/ImageWave'; 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[]; } 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-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-1.jpg', 'https://d3phaj0sisr2ct.cloudfront.net/app/gen4/object-reference/welcome-ref-2.jpg', ]; export function CharacterTabContent({ taskSketch, currentRoleIndex, onSketchSelect, roles = [mockRole] }: CharacterTabContentProps) { const [isReplaceModalOpen, setIsReplaceModalOpen] = useState(false); const [activeReplaceMethod, setActiveReplaceMethod] = useState('upload'); const [newTag, setNewTag] = useState(''); const [localRole, setLocalRole] = useState(mockRole); const [currentRole, setCurrentRole] = useState(roles[currentRoleIndex]); const [isReplacePanelOpen, setIsReplacePanelOpen] = useState(false); const [replacePanelKey, setReplacePanelKey] = useState(0); const [ignoreReplace, setIgnoreReplace] = useState(false); const [isReplaceLibraryOpen, setIsReplaceLibraryOpen] = useState(false); const [replaceLibraryKey, setReplaceLibraryKey] = useState(0); const textareaRef = useRef(null); const handleReplaceCharacter = (url: string) => { setCurrentRole({ ...currentRole, url: url }); setIsReplacePanelOpen(true); }; const handleConfirmReplace = (selectedShots: string[], addToLibrary: boolean) => { // 处理替换确认逻辑 console.log('Selected shots:', selectedShots); console.log('Add to library:', addToLibrary); setIsReplacePanelOpen(false); }; const handleCloseReplacePanel = () => { setIsReplacePanelOpen(false); setIgnoreReplace(true); }; const handleChangeRole = (index: number) => { if (currentRole.url !== roles[currentRoleIndex].url && !ignoreReplace) { // 提示 角色已修改,弹出替换角色面板 if (isReplacePanelOpen) { setReplacePanelKey(replacePanelKey + 1); } else { setIsReplacePanelOpen(true); } return; } onSketchSelect(index); setCurrentRole(roles[index]); }; // 如果没有角色数据,显示占位内容 if (!roles || roles.length === 0) { return (

No character data

); } return (
{/* 上部分:角色缩略图 */}
{roles.map((role, index) => ( handleChangeRole(index)} whileHover={{ scale: 1.05 }} whileTap={{ scale: 0.95 }} > {role.name}
{role.name}
))}
{/* 下部分:角色详情 */} {/* 左列:角色预览 */}
{/* 角色预览图 */}
{/* 应用角色按钮 */}
setIsReplaceLibraryOpen(true)} >
{/* 右列:角色信息 */}
{ setLocalRole({ ...localRole, roleDescription: description }); }} onAttributesChange={(attributes) => { const newRole = { ...localRole }; attributes.forEach(attr => { switch (attr.key) { case 'age': newRole.age = parseInt(attr.value); break; case 'gender': if (attr.value === '男性') { newRole.gender = 'male'; } else if (attr.value === '女性') { newRole.gender = 'female'; } else { newRole.gender = 'other'; } break; case 'hair': newRole.appearance.hairStyle = attr.value; break; case 'skin': newRole.appearance.skinTone = attr.value; break; case 'build': newRole.appearance.bodyType = attr.value; break; } }); setLocalRole(newRole); }} onReplaceCharacter={(url) => { handleReplaceCharacter(url); }} /> {/* 重新生成按钮、替换形象按钮 */}
console.log('Replace')} 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 console.log('Regenerate')} 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" whileHover={{ scale: 1.02 }} whileTap={{ scale: 0.98 }} > Regenerate
handleCloseReplacePanel()} onConfirm={handleConfirmReplace} /> {/* 从角色库中选择角色 */} {/* 标题 从角色库中选择角色 */}
Role Library
{/* 内容 */} { console.log('index', index); }} /> {/* 操作按钮 */}
); }