76 lines
2.8 KiB
TypeScript
76 lines
2.8 KiB
TypeScript
'use client'
|
|
import { useState, useEffect } from 'react'
|
|
import StatsOverview from '@/components/dashboard/StatsOverview'
|
|
import TrendChart from '@/components/dashboard/TrendChart'
|
|
import CategoryChart from '@/components/dashboard/CategoryChart'
|
|
import { Card } from '@/components/ui'
|
|
|
|
interface StatsData {
|
|
overview: {
|
|
total: number
|
|
open: number
|
|
in_progress: number
|
|
resolved: number
|
|
closed: number
|
|
thisMonth: number
|
|
avgDuration: number
|
|
slaRate: number
|
|
}
|
|
categories: Array<{ fault_category: string; count: number }>
|
|
monthlyTrend: Array<{ month: string; tickets: number; avg_duration: number }>
|
|
}
|
|
|
|
export default function DashboardPage() {
|
|
const [stats, setStats] = useState<StatsData | null>(null)
|
|
const [loading, setLoading] = useState(true)
|
|
|
|
useEffect(() => {
|
|
fetch('/api/stats')
|
|
.then(r => r.json())
|
|
.then(data => { if (data.overview) setStats(data) })
|
|
.catch(() => {})
|
|
.finally(() => setLoading(false))
|
|
}, [])
|
|
|
|
if (loading) return <div className="text-center py-12 text-slate-500 dark:text-slate-400">加载中...</div>
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
<div>
|
|
<h1 className="text-2xl font-bold text-slate-900 dark:text-slate-100">仪表盘</h1>
|
|
<p className="text-slate-500 dark:text-slate-400 mt-1">工单统计概览与趋势分析</p>
|
|
</div>
|
|
|
|
<StatsOverview stats={stats?.overview || null} />
|
|
|
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
<TrendChart data={stats?.monthlyTrend || []} />
|
|
<CategoryChart data={stats?.categories || []} />
|
|
</div>
|
|
|
|
{/* Recent tickets summary */}
|
|
<Card className="p-5">
|
|
<h3 className="text-sm font-semibold text-slate-700 dark:text-slate-300 mb-2">快速概要</h3>
|
|
<div className="grid grid-cols-2 md:grid-cols-4 gap-4 text-sm">
|
|
<div>
|
|
<span className="text-slate-500 dark:text-slate-400">待处理工单</span>
|
|
<p className="text-lg font-bold text-red-500">{stats?.overview.open || 0}</p>
|
|
</div>
|
|
<div>
|
|
<span className="text-slate-500 dark:text-slate-400">处理中工单</span>
|
|
<p className="text-lg font-bold text-amber-500">{stats?.overview.in_progress || 0}</p>
|
|
</div>
|
|
<div>
|
|
<span className="text-slate-500 dark:text-slate-400">本月工单数</span>
|
|
<p className="text-lg font-bold text-blue-500">{stats?.overview.thisMonth || 0}</p>
|
|
</div>
|
|
<div>
|
|
<span className="text-slate-500 dark:text-slate-400">整体服务可用性</span>
|
|
<p className={`text-lg font-bold ${(stats?.overview.slaRate || 0) >= 90 ? 'text-emerald-500' : 'text-amber-500'}`}>{stats?.overview.slaRate || 0}%</p>
|
|
</div>
|
|
</div>
|
|
</Card>
|
|
</div>
|
|
)
|
|
}
|