import React, { useState, useEffect, useMemo } from 'react'; import { useNavigate } from 'react-router-dom'; import { adminAPI } from '@/api'; const SVGIcon: React.FC<{ children: React.ReactNode; size?: number }> = ({ children, size = 20 }) => ( {children} ); const quickEntries = [ { path: '/admin/models', label: '大模型库', desc: '管理AI模型与供应商', icon: }, { path: '/admin/settings', label: '网站设置', desc: '品牌、邮件、短信配置', icon: }, { path: '/admin/payment', label: '支付配置', desc: '微信、支付宝渠道配置', icon: }, { path: '/admin/services', label: '增值服务', desc: '服务管理与定制订单', icon: }, { path: '/admin/membership', label: '会员体系', desc: '订阅计划与自动化规则', icon: }, { path: '/admin/market', label: '应用市场', desc: '应用审核与优惠券管理', icon: }, { path: '/admin/logs', label: '日志风控', desc: '操作/调用/付费日志与风控', icon: }, ]; const Dashboard: React.FC = () => { const navigate = useNavigate(); const [stats, setStats] = useState({ active_users: 0, enabled_models: 0, today_orders: 0, today_tokens: 0, total_tokens: 0 }); const [operationLogs, setOperationLogs] = useState([]); const [auditLogs, setAuditLogs] = useState([]); const [loading, setLoading] = useState(true); useEffect(() => { const fetchData = async () => { setLoading(true); try { const [statsRes, logsRes, auditRes] = await Promise.all([ adminAPI.getStats(), adminAPI.getRecentLogs(), adminAPI.getRecentAudit(), ]); if (statsRes.data) setStats(statsRes.data); if (logsRes.data) setOperationLogs(Array.isArray(logsRes.data) ? logsRes.data : []); if (auditRes.data) setAuditLogs(Array.isArray(auditRes.data) ? auditRes.data : []); } catch (err) { console.error('Dashboard数据加载失败:', err); } finally { setLoading(false); } }; fetchData(); }, []); const formatDate = (d: string) => { if (!d) return '-'; const dt = new Date(d); if (isNaN(dt.getTime())) return d.slice(0, 19) || '-'; return dt.toLocaleDateString('zh-CN', { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' }); }; const formatTokens = (n: number): string => { if (n >= 10000) return (n / 10000).toFixed(1) + '万'; return n.toLocaleString('en-US'); }; const statCards = [ { label: '用户总数', value: stats.active_users.toLocaleString(), color: '#6C63FF', bg: '#EEEDFF', icon: }, { label: '活跃模型数', value: stats.enabled_models.toString(), color: '#219B5E', bg: '#E6F7EE', icon: }, { label: '今日订单数', value: stats.today_orders.toString(), color: '#E8922C', bg: '#FEF4E8', icon: }, { label: '今日Token消耗', value: formatTokens(stats.today_tokens), color: '#3B82F6', bg: '#EBF2FE', icon: }, ]; if (loading) { return (
加载仪表盘数据...
); } return (

平台驾驶舱

{/* Stats Cards */}
{statCards.map((s, i) => (
{s.icon}
{s.label}
{s.value}
))}
{/* Platform Cumulative Token Stats */}

{' '}平台累计Token消耗

{[ { label: '今日消耗', value: formatTokens(stats.today_tokens), unit: 'Tokens', color: '#3B82F6' }, { label: '累计总消耗', value: formatTokens(stats.total_tokens || 0), unit: 'Tokens', color: '#6C63FF' }, { label: '日均消耗(近30天)', value: formatTokens(Math.round((stats.total_tokens || 0) / 30)), unit: 'Tokens', color: '#219B5E' }, { label: '活跃调用模型', value: stats.enabled_models.toString(), unit: '个', color: '#E8922C' }, ].map((item, i) => (
{item.value}
{item.label}
{item.unit}
))}
{/* Quick Entry Cards */}
{quickEntries.map((entry) => (
navigate(entry.path)} style={{ background: '#FFFFFF', borderRadius: 'var(--radius-xl)', border: '1px solid var(--color-border)', padding: 'var(--space-xl)', cursor: 'pointer', transition: 'all var(--transition-fast)', display: 'flex', flexDirection: 'column', alignItems: 'center', textAlign: 'center', gap: 'var(--space-sm)', }} onMouseEnter={(e) => { e.currentTarget.style.borderColor = 'var(--color-accent)'; e.currentTarget.style.boxShadow = 'var(--shadow-md)'; }} onMouseLeave={(e) => { e.currentTarget.style.borderColor = 'var(--color-border)'; e.currentTarget.style.boxShadow = 'none'; }} >
{entry.icon}
{entry.label}
{entry.desc}
))}
{/* Recent Operation Logs */}

最近操作日志

{operationLogs.length > 0 ? operationLogs.map(log => ( )) : ( )}
用户 操作 目标 详情 IP 时间
{log.username} {log.action} {log.target} {log.detail} {log.ip} {formatDate(log.created_at)}
暂无操作日志
{/* Recent Audit Logs */}

最近审计日志

{auditLogs.length > 0 ? auditLogs.map(log => ( )) : ( )}
操作人 操作类型 目标类型 详情 时间
{log.admin_name} {log.action} {log.target_type} {log.detail} {formatDate(log.created_at)}
暂无审计日志
); }; export default Dashboard;