import React, { useState, useEffect, useRef, useCallback } from 'react'; import { evolutionAPI } from '@/api'; import type { EvolutionSkill, EvolutionEvent, EvolutionProfile, SkillTreeData, StatisticsData, SkillState } from '@/types'; import html2canvas from 'html2canvas'; import jsPDF from 'jspdf'; import './EvolutionDashboard.css'; import { formatBjTime } from '@/utils/datetime'; // ==================== SVG Icons ==================== const Icon: React.FC<{ children: React.ReactNode; size?: number; className?: string }> = ({ children, size = 16, className }) => ( {children} ); const panelIcons: Record = { 'skill-tree': , timeline: , statistics: , profile: , reports: , }; const panelLabels: Record = { 'skill-tree': '技能图谱', timeline: '进化时间线', statistics: '技能使用统计', profile: 'AI能力画像', reports: '进化报告', }; // ==================== Config ==================== const stateConfig: Record = { baby: { label: '萌芽', color: '#E8922C', bg: '#FEF4E8', dot: '#E8922C' }, main: { label: '成熟', color: '#219B5E', bg: '#E6F7EE', dot: '#219B5E' }, staging: { label: '验证', color: '#8B5CF6', bg: '#F3F0FF', dot: '#8B5CF6' }, frozen: { label: '冻结', color: '#8B919E', bg: '#F1F3F7', dot: '#BFC4CE' }, }; const eventTypeConfig: Record = { created: { label: '诞生', color: '#E8922C', icon: }, promoted: { label: '晋升', color: '#219B5E', icon: }, rejected: { label: '退回', color: '#D9383A', icon: }, frozen: { label: '冻结', color: '#8B919E', icon: }, unfrozen: { label: '解冻', color: '#3B82F6', icon: }, edited: { label: '更新', color: '#5B5FED', icon: }, deleted: { label: '删除', color: '#D9383A', icon: }, milestone: { label: '里程碑', color: '#8B5CF6', icon: }, rolled_back: { label: '回滚', color: '#D9383A', icon: }, }; const shareThemes = [ { id: 'deep', name: '深空蓝', bg: 'linear-gradient(135deg, #1A1A3E 0%, #2D2D6B 50%, #1A1A2E 100%)', accent: '#8185F5', text: '#E8E6FF' }, { id: 'aurora', name: '极光绿', bg: 'linear-gradient(135deg, #0A2E1F 0%, #0F4A33 50%, #0A2E1F 100%)', accent: '#219B5E', text: '#D1FAE5' }, { id: 'sunset', name: '暖阳橙', bg: 'linear-gradient(135deg, #3D1F00 0%, #5C2D0E 50%, #3D1F00 100%)', accent: '#E8922C', text: '#FEF3C7' }, ]; // ==================== Real API version history ==================== // Version history is now fetched from the real API via evolutionAPI.getSkillHistory() // ==================== Panel A: Skill Tree ==================== const SkillTreePanel: React.FC<{ skills: EvolutionSkill[]; animEnabled: boolean; onToggleAnim: () => void; }> = ({ skills, animEnabled, onToggleAnim }) => { const [hoveredSkill, setHoveredSkill] = useState(null); const [selectedSkill, setSelectedSkill] = useState(null); const [showVersionHistory, setShowVersionHistory] = useState(false); const [showRollbackConfirm, setShowRollbackConfirm] = useState<{ version: number } | null>(null); const [showPublishModal, setShowPublishModal] = useState(false); const [publishPrice, setPublishPrice] = useState(0); const [publishDesc, setPublishDesc] = useState(''); const [rollbackMsg, setRollbackMsg] = useState(''); const [publishMsg, setPublishMsg] = useState(''); const [versionHistory, setVersionHistory] = useState([]); const [loadingHistory, setLoadingHistory] = useState(false); const categories = [...new Set(skills.map(s => s.category))]; const groupedByCategory = categories.map(cat => ({ category: cat, skills: skills.filter(s => s.category === cat), })); // Fetch real version history from API const loadVersionHistory = async (skillName: string) => { setLoadingHistory(true); try { const res = await evolutionAPI.getSkillHistory(skillName); if (res?.data) { const events = Array.isArray(res.data) ? res.data : (res.data as any)?.events || []; setVersionHistory(events); } else { setVersionHistory([]); } } catch { setVersionHistory([]); } finally { setLoadingHistory(false); } }; const handleRollback = async (targetVersion: number) => { if (!selectedSkill) return; try { await evolutionAPI.rollbackSkill(selectedSkill.skill_name, targetVersion); setRollbackMsg(`技能 "${selectedSkill.skill_name}" 已回滚到版本 v${targetVersion}`); setShowVersionHistory(false); setShowRollbackConfirm(null); setSelectedSkill(prev => prev ? { ...prev, version: targetVersion } : null); setTimeout(() => setRollbackMsg(''), 3000); } catch (err: any) { setRollbackMsg(`回滚失败: ${err.message || '未知错误'}`); setTimeout(() => setRollbackMsg(''), 3000); } }; const handlePublish = async () => { if (!selectedSkill) return; try { await evolutionAPI.publishSkill(selectedSkill.skill_name, { price: publishPrice, market_description: publishDesc }); setPublishMsg(`技能 "${selectedSkill.skill_name}" 已发布到应用市场`); setShowPublishModal(false); setTimeout(() => setPublishMsg(''), 3000); } catch (err: any) { setPublishMsg(`发布失败: ${err.message || '未知错误'}`); setTimeout(() => setPublishMsg(''), 3000); } }; return (
{/* Rollback toast */} {rollbackMsg &&
{rollbackMsg}
} {/* Publish toast */} {publishMsg &&
{publishMsg}
} {/* Anim Toggle */}
{/* Skill detail modal */} {selectedSkill && !showVersionHistory && (
setSelectedSkill(null)}>
e.stopPropagation()}>
{stateConfig[selectedSkill.state].label}

{selectedSkill.skill_name}

{selectedSkill.description}

版本 v{selectedSkill.version}
使用次数 {selectedSkill.use_count.toLocaleString()}
分类 {selectedSkill.category}
创建日期 {new Date(selectedSkill.created_at).toLocaleDateString()}
{selectedSkill.tags.map(t => {t})}
{selectedSkill.state === 'main' && ( )}
)} {/* Version History Modal */} {selectedSkill && showVersionHistory && (
{ setShowVersionHistory(false); setShowRollbackConfirm(null); }}>
e.stopPropagation()}>

版本历史 - {selectedSkill.skill_name}

当前版本: v{selectedSkill.version}

{loadingHistory ? (

加载中...

) : (
{versionHistory.length > 0 ? versionHistory.map((entry, idx) => { const ec = eventTypeConfig[entry.event_type] || eventTypeConfig.edited; const entryVersion = entry.version_after || entry.version_before || 1; const isCurrent = entryVersion === selectedSkill.version; return (
{ec.icon}
{idx < versionHistory.length - 1 &&
}
v{entryVersion} {isCurrent && 当前} {ec.label}

{entry.description}

{new Date(entry.created_at).toLocaleDateString()} {!isCurrent && ( )}
); }) : (

暂无版本历史

)}
)}
)} {/* Rollback Confirm Modal */} {showRollbackConfirm && selectedSkill && (
setShowRollbackConfirm(null)}>
e.stopPropagation()}>

确认回滚?

确认回滚到版本 v{showRollbackConfirm.version}?当前版本 v{selectedSkill.version} 的修改将被撤销。

)} {/* Publish to Market Modal */} {showPublishModal && selectedSkill && (
setShowPublishModal(false)}>
e.stopPropagation()}>

发布到应用市场

将进化技能 "{selectedSkill.skill_name}" 发布到应用市场Skills分类

setPublishPrice(Number(e.target.value))} />