()
| 18 | } from '../lib/utils'; |
| 19 | |
| 20 | export function Overview() { |
| 21 | const { data: overview, isLoading, refetch, isFetching } = useOverview('24h'); |
| 22 | const { data: events } = useRecentEvents(10); |
| 23 | |
| 24 | return ( |
| 25 | <div className="flex flex-col h-full"> |
| 26 | <Header |
| 27 | title="Overview" |
| 28 | subtitle="系统概览和关键指标" |
| 29 | isRefreshing={isFetching} |
| 30 | onRefresh={() => refetch()} |
| 31 | lastUpdated={overview ? new Date(overview.updated_at) : undefined} |
| 32 | /> |
| 33 | |
| 34 | <div className="flex-1 overflow-auto p-6"> |
| 35 | {isLoading ? ( |
| 36 | <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4"> |
| 37 | {[...Array(4)].map((_, i) => ( |
| 38 | <div |
| 39 | key={i} |
| 40 | className="card h-32 animate-pulse-slow bg-[var(--color-surface)]" |
| 41 | /> |
| 42 | ))} |
| 43 | </div> |
| 44 | ) : overview ? ( |
| 45 | <div className="space-y-6"> |
| 46 | {/* Stat Cards */} |
| 47 | <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4"> |
| 48 | <StatCard |
| 49 | title="活跃 Agents" |
| 50 | value={overview.active_agents} |
| 51 | icon={Users} |
| 52 | color="primary" |
| 53 | /> |
| 54 | <StatCard |
| 55 | title="活跃会话" |
| 56 | value={overview.active_sessions} |
| 57 | icon={Activity} |
| 58 | color="accent" |
| 59 | /> |
| 60 | <StatCard |
| 61 | title="总请求数" |
| 62 | value={formatNumber(overview.total_requests)} |
| 63 | icon={Zap} |
| 64 | color="success" |
| 65 | /> |
| 66 | <StatCard |
| 67 | title="错误率" |
| 68 | value={formatPercent(overview.error_rate)} |
| 69 | icon={AlertTriangle} |
| 70 | color={overview.error_rate > 0.05 ? 'error' : 'success'} |
| 71 | /> |
| 72 | </div> |
| 73 | |
| 74 | {/* Token & Cost Summary */} |
| 75 | <div className="grid grid-cols-1 lg:grid-cols-2 gap-4"> |
| 76 | <div className="card"> |
| 77 | <h3 className="text-sm font-medium text-[var(--color-text-muted)] mb-4"> |
nothing calls this directly
no test coverage detected