import React, { useState, useEffect } from 'react'; import { X, Sparkles, Loader2, Check, History, Plus } from 'lucide-react'; import { apiService } from '../services/api'; interface CharacterCustomizationDialogProps { isOpen: boolean; onClose: () => void; onGenerate: (preferences: CharacterPreferences) => Promise; onSelectHistory: (imageUrl: string) => void; currentPreferences?: CharacterPreferences; currentImageUrl?: string; } export interface CharacterPreferences { color: string; personality: string; appearance: string; role: string; } interface HistoricalImage { filename: string; url: string; color: string; personality: string; timestamp: string; created_at: number; size: number; } const COLOR_OPTIONS = [ { value: '温暖粉', label: '温暖粉', color: 'bg-pink-200' }, { value: '天空蓝', label: '天空蓝', color: 'bg-blue-200' }, { value: '薄荷绿', label: '薄荷绿', color: 'bg-green-200' }, { value: '奶油黄', label: '奶油黄', color: 'bg-yellow-200' }, { value: '薰衣草紫', label: '薰衣草紫', color: 'bg-purple-200' }, { value: '珊瑚橙', label: '珊瑚橙', color: 'bg-orange-200' }, { value: '纯白', label: '纯白', color: 'bg-white border border-gray-300' }, { value: '浅灰', label: '浅灰', color: 'bg-gray-200' }, ]; const PERSONALITY_OPTIONS = [ { value: '活泼', label: '活泼', emoji: '😄' }, { value: '温柔', label: '温柔', emoji: '😊' }, { value: '聪明', label: '聪明', emoji: '🤓' }, { value: '慵懒', label: '慵懒', emoji: '😴' }, { value: '勇敢', label: '勇敢', emoji: '💪' }, { value: '害羞', label: '害羞', emoji: '😳' }, ]; const APPEARANCE_OPTIONS = [ { value: '戴眼镜', label: '戴眼镜', emoji: '👓' }, { value: '戴帽子', label: '戴帽子', emoji: '🎩' }, { value: '戴围巾', label: '戴围巾', emoji: '🧣' }, { value: '戴蝴蝶结', label: '戴蝴蝶结', emoji: '🎀' }, { value: '无配饰', label: '无配饰', emoji: '✨' }, ]; const ROLE_OPTIONS = [ { value: '陪伴式朋友', label: '陪伴式朋友', emoji: '🤝' }, { value: '温柔照顾型长辈', label: '温柔照顾型长辈', emoji: '🤗' }, { value: '引导型老师', label: '引导型老师', emoji: '👨‍🏫' }, ]; export const CharacterCustomizationDialog: React.FC = ({ isOpen, onClose, onGenerate, onSelectHistory, currentPreferences, currentImageUrl, }) => { const [mode, setMode] = useState<'history' | 'create'>('history'); const [preferences, setPreferences] = useState({ color: '温暖粉', personality: '温柔', appearance: '无配饰', role: '陪伴式朋友', }); const [isGenerating, setIsGenerating] = useState(false); const [step, setStep] = useState(1); const [error, setError] = useState(null); const [historyImages, setHistoryImages] = useState([]); const [loadingHistory, setLoadingHistory] = useState(false); const [selectedHistoryImage, setSelectedHistoryImage] = useState(null); useEffect(() => { if (currentPreferences) { setPreferences(currentPreferences); } }, [currentPreferences]); useEffect(() => { if (isOpen && mode === 'history') { loadHistory(); } }, [isOpen, mode]); const loadHistory = async () => { setLoadingHistory(true); try { const response = await apiService.getCharacterHistory(); setHistoryImages(response.images); } catch (error) { console.error('Failed to load history:', error); } finally { setLoadingHistory(false); } }; const handleSelectHistoryImage = async (image: HistoricalImage) => { setSelectedHistoryImage(image.filename); try { const response = await apiService.selectCharacter(image.filename); onSelectHistory(response.image_url); setTimeout(() => { onClose(); setMode('history'); setStep(1); setError(null); setSelectedHistoryImage(null); }, 500); } catch (error: any) { console.error('Failed to select character:', error); setError(error.message || '选择失败,请重试'); setSelectedHistoryImage(null); } }; if (!isOpen) return null; const handleGenerate = async () => { setIsGenerating(true); setError(null); try { await onGenerate(preferences); setTimeout(() => { onClose(); setMode('history'); setStep(1); setError(null); }, 1000); } catch (error: any) { console.error('Failed to generate character:', error); let errorMessage = '生成失败,请重试'; if (error.message) { if (error.message.includes('MiniMax API 未配置')) { errorMessage = 'MiniMax API 未配置,请在 .env 文件中配置 MINIMAX_API_KEY'; } else if (error.message.includes('invalid api key')) { errorMessage = 'API 密钥无效,请检查 MINIMAX_API_KEY 配置'; } else if (error.message.includes('配额不足')) { errorMessage = 'API 配额不足,请充值或等待配额恢复'; } else if (error.message.includes('timeout') || error.message.includes('超时')) { errorMessage = '请求超时,图像生成时间较长(约60-90秒),请耐心等待或稍后重试'; } else if (error.message.includes('Failed to fetch') || error.message.includes('fetch')) { errorMessage = '网络连接失败,请检查:\n1. 后端服务是否运行\n2. 网络连接是否正常\n3. 防火墙是否允许访问'; } else { errorMessage = error.message; } } setError(errorMessage); } finally { setIsGenerating(false); } }; const renderHistoryView = () => (
{loadingHistory ? (
) : historyImages.length === 0 ? (

还没有历史形象

) : (
{historyImages.map((image) => ( ))}
)}
); const renderStep1 = () => (

选择颜色

{COLOR_OPTIONS.map((option) => ( ))}

选择性格

{PERSONALITY_OPTIONS.map((option) => ( ))}
); const renderStep2 = () => (

选择外观

{APPEARANCE_OPTIONS.map((option) => ( ))}

选择角色

{ROLE_OPTIONS.map((option) => ( ))}
); return (

AI 形象定制

{mode === 'create' && currentImageUrl && (
Current character

当前形象

🎨 {preferences.color}

😊 {preferences.personality}

✨ {preferences.appearance}

🎭 {preferences.role}

)} {mode === 'history' ? ( renderHistoryView() ) : ( <>
1
2
{step === 1 ? renderStep1() : renderStep2()}
{step === 2 && ( )} {step === 1 ? ( ) : ( )}
)} {error && (

{error}

)}

{mode === 'history' ? '点击历史形象即可切换,或创建新形象' : isGenerating ? '正在生成你的专属 AI 形象,请稍候(约 30-60 秒)...' : currentImageUrl ? '修改选项后点击"重新生成"更新形象' : '选择你喜欢的风格,生成专属的 AI 陪伴形象' }

); };