import React, { useState, useEffect } from 'react'; import { Row, Col, Card, Typography, Spin } from 'antd'; import { UserOutlined, MobileOutlined, AppstoreOutlined, InboxOutlined, CheckCircleOutlined, DatabaseOutlined, } from '@ant-design/icons'; import { Pie, Column } from '@ant-design/charts'; import request from '../../api/request'; import { statColors } from '../../theme/tokens'; const { Title } = Typography; interface DashboardStats { user_count: number; device_count: number; device_type_count: number; batch_count: number; bound_device_count: number; in_stock_device_count: number; } const getDashboardStats = async (): Promise => { const res = await request.get('/api/admin/dashboard/stats/'); return res.data; }; const Dashboard: React.FC = () => { const [loading, setLoading] = useState(true); const [stats, setStats] = useState({ user_count: 0, device_count: 0, device_type_count: 0, batch_count: 0, bound_device_count: 0, in_stock_device_count: 0, }); useEffect(() => { loadStats(); }, []); const loadStats = async () => { try { const data = await getDashboardStats(); setStats(data); } catch (error) { // 静默失败,使用默认值 } finally { setLoading(false); } }; const statCards = [ { title: '用户总数', value: stats.user_count, icon: , color: statColors.primary, bgColor: 'rgba(99, 102, 241, 0.08)', }, { title: '设备总数', value: stats.device_count, icon: , color: statColors.success, bgColor: 'rgba(16, 185, 129, 0.08)', }, { title: '设备类型', value: stats.device_type_count, icon: , color: statColors.purple, bgColor: 'rgba(139, 92, 246, 0.08)', }, { title: '入库批次', value: stats.batch_count, icon: , color: statColors.warning, bgColor: 'rgba(245, 158, 11, 0.08)', }, { title: '已绑定设备', value: stats.bound_device_count, icon: , color: statColors.cyan, bgColor: 'rgba(6, 182, 212, 0.08)', }, { title: '库存设备', value: stats.in_stock_device_count, icon: , color: statColors.pink, bgColor: 'rgba(236, 72, 153, 0.08)', }, ]; // 设备状态分布数据 const otherCount = Math.max(0, stats.device_count - stats.in_stock_device_count - stats.bound_device_count); const pieData = [ { type: '库存中', value: stats.in_stock_device_count }, { type: '已绑定', value: stats.bound_device_count }, ...(otherCount > 0 ? [{ type: '其他', value: otherCount }] : []), ]; const pieConfig = { data: pieData, angleField: 'value', colorField: 'type', radius: 0.85, innerRadius: 0.6, color: [statColors.primary, statColors.success, statColors.warning], label: { text: (d: { type: string; value: number }) => `${d.type}\n${d.value}`, style: { fontSize: 12, fontWeight: 500 }, }, legend: { color: { position: 'bottom' as const, layout: { justifyContent: 'center' as const }, }, }, interaction: { elementHighlight: true, }, }; // 数据概览柱状图 const columnData = [ { name: '用户', value: stats.user_count, type: '数量' }, { name: '设备', value: stats.device_count, type: '数量' }, { name: '已绑定', value: stats.bound_device_count, type: '数量' }, { name: '库存', value: stats.in_stock_device_count, type: '数量' }, { name: '批次', value: stats.batch_count, type: '数量' }, { name: '类型', value: stats.device_type_count, type: '数量' }, ]; const columnConfig = { data: columnData, xField: 'name', yField: 'value', color: statColors.primary, style: { radiusTopLeft: 6, radiusTopRight: 6, fill: statColors.primary, fillOpacity: 0.85, }, label: { text: (d: { value: number }) => `${d.value}`, textBaseline: 'bottom' as const, style: { dy: -4, fontSize: 12 }, }, axis: { y: { title: false }, x: { title: false }, }, }; return (
仪表盘 {/* Stat Cards */} {statCards.map((stat, index) => (
{stat.icon}
{stat.title}
{stat.value.toLocaleString()}
))}
{/* Charts */}
{stats.device_count > 0 ? ( ) : (
暂无设备数据
)}
); }; export default Dashboard;