// ============================================================ // 仪表盘页面 // ============================================================ import { useQuery } from '@tanstack/react-query' import { Card, Col, Row, Statistic, Table, Tag, Typography, Spin, Alert } from 'antd' import { TeamOutlined, CloudServerOutlined, ApiOutlined, ThunderboltOutlined, ColumnWidthOutlined, } from '@ant-design/icons' import { statsService } from '@/services/stats' import { logService } from '@/services/logs' import type { OperationLog } from '@/types' const { Title } = Typography const actionLabels: Record = { login: '登录', logout: '登出', create_account: '创建账号', update_account: '更新账号', delete_account: '删除账号', create_provider: '创建服务商', update_provider: '更新服务商', delete_provider: '删除服务商', create_model: '创建模型', update_model: '更新模型', delete_model: '删除模型', create_token: '创建密钥', revoke_token: '撤销密钥', update_config: '更新配置', create_prompt: '创建提示词', update_prompt: '更新提示词', archive_prompt: '归档提示词', desktop_audit: '桌面端审计', } const actionColors: Record = { login: 'green', logout: 'default', create_account: 'blue', update_account: 'orange', delete_account: 'red', create_provider: 'blue', update_provider: 'orange', delete_provider: 'red', create_model: 'blue', update_model: 'orange', delete_model: 'red', create_token: 'blue', revoke_token: 'red', update_config: 'orange', create_prompt: 'blue', update_prompt: 'orange', archive_prompt: 'red', desktop_audit: 'default', } export default function Dashboard() { const { data: stats, isLoading: statsLoading, error: statsError } = useQuery({ queryKey: ['dashboard-stats'], queryFn: ({ signal }) => statsService.dashboard(signal), }) const { data: logsData, isLoading: logsLoading } = useQuery({ queryKey: ['recent-logs'], queryFn: ({ signal }) => logService.list({ page: 1, page_size: 10 }, signal), }) if (statsError) { return } const statCards = [ { title: '总账号', value: stats?.total_accounts ?? 0, icon: , color: '#1677ff' }, { title: '活跃服务商', value: stats?.active_providers ?? 0, icon: , color: '#52c41a' }, { title: '活跃模型', value: stats?.active_models ?? 0, icon: , color: '#722ed1' }, { title: '今日请求', value: stats?.tasks_today ?? 0, icon: , color: '#fa8c16' }, { title: '今日 Token', value: ((stats?.tokens_today_input ?? 0) + (stats?.tokens_today_output ?? 0)), icon: , color: '#eb2f96' }, ] const logColumns = [ { title: '操作类型', dataIndex: 'action', key: 'action', width: 140, render: (action: string) => ( {actionLabels[action] || action} ), }, { title: '目标类型', dataIndex: 'target_type', key: 'target_type', width: 100, render: (v: string | null) => v || '-' }, { title: '时间', dataIndex: 'created_at', key: 'created_at', width: 180, render: (v: string) => new Date(v).toLocaleString('zh-CN'), }, ] return (
仪表盘 {statsLoading ? ( ) : ( statCards.map((card) => ( {card.icon}} /> )) )} columns={logColumns} dataSource={logsData?.items ?? []} loading={logsLoading} rowKey="id" pagination={false} size="small" />
) }