import React, { useState, useRef } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { Upload, Library, Play, Pause, RefreshCw, Wand2 } from 'lucide-react'; import { cn } from '@/public/lib/utils'; import { GlassIconButton } from './glass-icon-button'; import { ReplaceCharacterModal } from './replace-character-modal'; interface CharacterTabContentProps { taskSketch: any[]; currentSketchIndex: number; onSketchSelect: (index: number) => void; } // 模拟角色数据 const MOCK_CHARACTERS = [ { id: 1, name: '雪 (YUKI)', avatar: '/assets/3dr_chihiro.png', voiceDescription: '年轻女性,温柔而坚定的声线,语速适中,带有轻微的感性色彩。', characterDescription: '一位接近二十岁或二十出头的年轻女性,东亚裔,拥有深色长发和刘海,五官柔和且富有表现力。', voiceUrl: 'https://example.com/voice-sample.mp3' }, { id: 2, name: '春 (HARU)', avatar: '/assets/3dr_mono.png', voiceDescription: '年轻男性,清澈而温和的声线,语速从容,带有知性的特质。', characterDescription: '一位接近二十岁或二十出头的年轻男性,东亚裔,拥有深色、发型整洁的中长发和深思的气质。', voiceUrl: 'https://example.com/voice-sample.mp3' }, ]; export function CharacterTabContent({ taskSketch, currentSketchIndex, onSketchSelect }: CharacterTabContentProps) { const [selectedCharacterIndex, setSelectedCharacterIndex] = useState(0); const [isReplaceModalOpen, setIsReplaceModalOpen] = useState(false); const [activeReplaceMethod, setActiveReplaceMethod] = useState('upload'); const [isPlaying, setIsPlaying] = useState(false); const [progress, setProgress] = useState(0); const [editingField, setEditingField] = useState<{ type: 'name' | 'voiceDescription' | 'characterDescription' | null; value: string; }>({ type: null, value: '' }); const audioRef = useRef(null); // 处理音频播放进度 const handleTimeUpdate = () => { if (audioRef.current) { const progress = (audioRef.current.currentTime / audioRef.current.duration) * 100; setProgress(progress); } }; // 处理播放/暂停 const togglePlay = () => { if (audioRef.current) { if (isPlaying) { audioRef.current.pause(); } else { audioRef.current.play(); } setIsPlaying(!isPlaying); } }; // 处理进度条点击 const handleProgressClick = (e: React.MouseEvent) => { if (audioRef.current) { const rect = e.currentTarget.getBoundingClientRect(); const x = e.clientX - rect.left; const percentage = (x / rect.width) * 100; const time = (percentage / 100) * audioRef.current.duration; audioRef.current.currentTime = time; setProgress(percentage); } }; return (
{/* 上部分:角色缩略图 */}
{MOCK_CHARACTERS.map((character, index) => ( setSelectedCharacterIndex(index)} whileHover={{ scale: 1.05 }} whileTap={{ scale: 0.95 }} > {character.name}
{character.name}
))}
{/* 中间部分:替换角色 */}

替换角色

{ setActiveReplaceMethod('upload'); setIsReplaceModalOpen(true); }} whileHover={{ scale: 1.02 }} whileTap={{ scale: 0.98 }} > 上传角色 { setActiveReplaceMethod('library'); setIsReplaceModalOpen(true); }} whileHover={{ scale: 1.02 }} whileTap={{ scale: 0.98 }} > 角色库
{/* 下部分:角色详情 */} {/* 左列:角色信息 */}
{/* 角色姓名 */}
console.log('name changed:', e.target.value)} className="w-full px-3 py-2 bg-white/5 border border-white/10 rounded-lg focus:outline-none focus:border-blue-500" />
{/* 声音描述 */}