import React, { useEffect, useState } from 'react'; import { Card, Col, Row, Typography, DatePicker, Button, Space } from 'antd'; import { UserOutlined, ProjectOutlined, PlayCircleOutlined, FileTextOutlined, DollarOutlined, WalletOutlined, ArrowUpOutlined, CalendarOutlined, } from '@ant-design/icons'; import { getAdminStats, getSystemConfigs } from '../api'; import type { AdminStats, SystemConfig } from '../types'; import dayjs from 'dayjs'; import 'dayjs/locale/zh-cn'; dayjs.locale('zh-cn'); const AdminDashboard: React.FC = () => { const [stats, setStats] = useState(null); const [loading, setLoading] = useState(true); const [startDate, setStartDate] = useState<[dayjs.Dayjs | null, dayjs.Dayjs | null]>([dayjs().startOf('day'), dayjs()]); const [siteName, setSiteName] = useState('数据概览'); const load = async () => { setLoading(true); try { const start = startDate[0]?.format('YYYY-MM-DD') || undefined; const end = startDate[1]?.format('YYYY-MM-DD') || undefined; const data = await getAdminStats(start, end); setStats(data); } catch { /* auth error handled by client */ } setLoading(false); }; const loadSiteName = async () => { try { const configs = await getSystemConfigs(); const siteConfig = configs.find((c: SystemConfig) => c.key === 'site_name'); if (siteConfig) { const title = `${siteConfig.value} 管理后台`; setSiteName(title); document.title = title; } } catch { setSiteName('数据概览'); document.title = '数据概览'; } }; useEffect(() => { load(); loadSiteName(); }, []); const handleToday = () => { const dates: [dayjs.Dayjs, dayjs.Dayjs] = [dayjs().startOf('day'), dayjs()]; setStartDate(dates); loadWithDates(dates); }; const handleYesterday = () => { const yesterday = dayjs().subtract(1, 'day'); const dates: [dayjs.Dayjs, dayjs.Dayjs] = [yesterday.startOf('day'), yesterday.endOf('day')]; setStartDate(dates); loadWithDates(dates); }; const handleWeek = () => { const dates: [dayjs.Dayjs, dayjs.Dayjs] = [dayjs().startOf('week'), dayjs()]; setStartDate(dates); loadWithDates(dates); }; const handleMonth = () => { const dates: [dayjs.Dayjs, dayjs.Dayjs] = [dayjs().startOf('month'), dayjs()]; setStartDate(dates); loadWithDates(dates); }; const loadWithDates = (dates: [dayjs.Dayjs, dayjs.Dayjs]) => { const start = dates[0]?.format('YYYY-MM-DD') || undefined; const end = dates[1]?.format('YYYY-MM-DD') || undefined; setLoading(true); getAdminStats(start, end).then(data => { setStats(data); setLoading(false); }).catch(() => { setLoading(false); }); }; const handleDateChange = (dates: any) => { if (dates) { setStartDate([dates[0], dates[1]]); loadWithDates([dates[0], dates[1]]); } }; const baseStats = stats ? [ { title: '用户数量', value: stats.totalUsers, lastPeriodValue: stats.lastPeriodUsers, icon: , gradient: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)', prefix: '', suffix: '位用户', description: '平台注册用户总数' }, { title: '总项目数', value: stats.totalProjects, lastPeriodValue: stats.lastPeriodProjects, icon: , gradient: 'linear-gradient(135deg, #00d4ff 0%, #0099cc 100%)', prefix: '', suffix: '个项目', description: '创建的项目总数' }, { title: '项目记录', value: stats.totalRecords, lastPeriodValue: stats.lastPeriodRecords, icon: , gradient: 'linear-gradient(135deg, #10b981 0%, #059669 100%)', prefix: '', suffix: '条记录', description: '项目记录总数' }, { title: '创作记录', value: stats.totalGenerations, lastPeriodValue: stats.lastPeriodGenerations, icon: , gradient: 'linear-gradient(135deg, #f59e0b 0%, #d97706 100%)', prefix: '', suffix: '次创作', description: 'AI创作记录总数' }, ] : []; const financeStats = stats ? [ { title: '支付宝收入', value: stats.todayAlipayRevenue, icon: , gradient: 'linear-gradient(135deg, #22c55e 0%, #16a34a 100%)', prefix: '¥', suffix: '', description: '支付宝收款', tag: '支付宝' }, { title: '微信收入', value: stats.todayWechatRevenue, icon: , gradient: 'linear-gradient(135deg, #3b82f6 0%, #2563eb 100%)', prefix: '¥', suffix: '', description: '微信收款', tag: '微信支付' }, { title: '总收入', value: stats.totalRevenue, lastPeriodValue: stats.lastPeriodRevenue, icon: , gradient: 'linear-gradient(135deg, #ec4899 0%, #be185d 100%)', prefix: '¥', suffix: '', description: '平台总收入', tag: '总收入' }, { title: '消耗积分', value: stats.creditsConsumedToday, lastPeriodValue: stats.lastPeriodCreditsConsumed, icon: , gradient: 'linear-gradient(135deg, #ef4444 0%, #dc2626 100%)', prefix: '', suffix: '积分', description: '用户消耗积分', tag: '积分消耗' }, ] : []; const StatCard: React.FC<{ title: string; value: number; lastPeriodValue?: number; icon: React.ReactNode; gradient: string; prefix?: string; suffix?: string; description?: string; tag?: string; }> = ({ title, value, lastPeriodValue, icon, gradient, prefix = '', suffix = '', description, tag }) => { const change = lastPeriodValue !== undefined && lastPeriodValue > 0 ? ((value - lastPeriodValue) / lastPeriodValue * 100).toFixed(1) : null; const isPositive = change !== null && parseFloat(change) >= 0; return (
{icon}
{title} {tag && ( {tag} )}
{prefix}{typeof value === 'number' ? value.toLocaleString() : value}{suffix}
{description && ( {description} )} {change !== null && lastPeriodValue !== undefined && (
上一周期: {prefix}{lastPeriodValue.toLocaleString()}{suffix} {isPositive ? '↑' : '↓'} {Math.abs(parseFloat(change))}%
)}
); }; return (
{siteName} 欢迎回来,查看平台运营数据统计
核心数据 平台基础运营指标
{baseStats.map((s) => ( ))}
财务统计 收入与消耗数据
{financeStats.map((s) => ( ))}
); }; export default AdminDashboard;