import { useState, useEffect } from 'react' import { Users, FileText, MessageSquare, Clock, TrendingUp, Calendar, CalendarDays, CalendarRange } from 'lucide-react' import { StatsCard } from '@/components/StatsCard' import { ActivityChart } from '@/components/ActivityChart' import { RetentionChart } from '@/components/RetentionChart' import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card' import { Badge } from '@/components/ui/badge' import { Button } from '@/components/ui/button' import { dashboardApi } from '@/api' import type { DashboardStatsData, ActivityTrendData, PendingContent } from '@/api/dashboard' export default function Dashboard() { const [stats, setStats] = useState(null) const [activityData, setActivityData] = useState([]) const [pendingContent, setPendingContent] = useState([]) const [isLoading, setIsLoading] = useState(true) const [activityDays] = useState(7) useEffect(() => { loadDashboardData() }, []) useEffect(() => { loadActivityData(activityDays) }, [activityDays]) const loadDashboardData = async () => { setIsLoading(true) try { const [statsRes, pendingRes] = await Promise.all([ dashboardApi.getStats(), dashboardApi.getPendingContent(5), ]) if (statsRes.data.data) { setStats(statsRes.data.data) } if (pendingRes.data.data) { setPendingContent(pendingRes.data.data) } } catch (error) { console.error('加载Dashboard数据失败:', error) } finally { setIsLoading(false) } } const loadActivityData = async (days: number) => { try { const res = await dashboardApi.getUserActivityTrend(days) if (res.data.data) { setActivityData(res.data.data) } } catch (error) { console.error('加载活跃度数据失败:', error) } } const formatTime = (dateStr: string) => { const date = new Date(dateStr) const now = new Date() const diff = now.getTime() - date.getTime() const minutes = Math.floor(diff / 60000) const hours = Math.floor(diff / 3600000) if (minutes < 60) return `${minutes}分钟前` if (hours < 24) return `${hours}小时前` return `${Math.floor(hours / 24)}天前` } const retentionData = stats ? [ { name: '次日留存', value: stats.retention_1_day || 0, color: '#8884d8' }, { name: '7日留存', value: stats.retention_7_day || 0, color: '#82ca9d' }, { name: '30日留存', value: stats.retention_30_day || 0, color: '#ffc658' }, ] : [] return (

Dashboard

欢迎来到 Carrot BBS 管理后台

{/* 统计卡片 */}
0 ? 'border-orange-300' : ''} />
{/* 活跃用户统计 */}
{/* 留存率统计 */}
40 ? { value: stats.retention_1_day, label: '%', isPositive: true } : undefined} />

系统状态

正常运行

{/* 图表区域 */}
{/* 最新待审核内容 */}
最新待审核内容 需要审核的帖子或评论
{isLoading ? (
加载中...
) : pendingContent.length === 0 ? (
暂无待审核内容
) : (
{pendingContent.map((item) => (
{item.type === 'post' ? '帖子' : '评论'} {item.author.nickname || item.author.username} {formatTime(item.created_at)}

{item.title || item.content}

))}
)}
) }