import { useEffect, useMemo, useState } from 'react'; import { BarChart3 } from 'lucide-react'; import { adminApi, type DashboardResponse } from '@/api/adminApi'; import { Breadcrumb, Button, Chart, Tag } from '@/components/ui'; import { createBarOption, createPieOption } from '@/theme/chartOptions'; export function AdminAnalyticsPage() { const [dashboard, setDashboard] = useState(null); const [tenantStats, setTenantStats] = useState>([]); const [channelStats, setChannelStats] = useState>([]); const [error, setError] = useState(''); function loadData() { Promise.all([ adminApi.getDashboard(), adminApi.listStatistics({ groupBy: 'tenantId' }), adminApi.listStatistics({ groupBy: 'channelId' }), ]) .then(([dashboardData, tenantData, channelData]) => { setDashboard(dashboardData); setTenantStats((Array.isArray(tenantData) ? tenantData : []) as Array<{ tenantId: string | null; _count: { _all: number }; _sum: { amountCents?: number | null } }>); setChannelStats((Array.isArray(channelData) ? channelData : []) as Array<{ channelId: string | null; _count: { _all: number }; _sum: { amountCents?: number | null } }>); setError(''); }) .catch((failure: Error) => setError(failure.message || '统计数据加载失败')); } useEffect(() => { loadData(); }, []); const tenantOption = useMemo(() => createBarOption({ labels: tenantStats.map((item) => item.tenantId ?? '未绑定企业'), series: [{ name: '发送量', data: tenantStats.map((item) => item._count._all) }], }), [tenantStats]); const channelOption = useMemo(() => createPieOption({ data: channelStats.map((item) => ({ name: item.channelId ?? '未分配通道', value: item._count._all })), }), [channelStats]); return (
{error ?

{error}

: null}
今日发送量 {dashboard?.today.sent.toLocaleString('zh-CN') ?? 0} 真实消息记录
成功率 {dashboard?.today.successRate ?? 0}% 今日已回执
待审核 {dashboard?.pendingAuditCount ?? 0} 企业/签名/模板/风控

企业发送排行

按真实短信消息记录聚合。

企业

通道占比

按通道消息记录聚合。

通道
); }