/** * Admin 后台 - 评估汇总页(报刊风) * * 功能: * - 按 provider / model / prompt_version / mode / league_code 筛选 * - 展示汇总统计卡片(已结算/已评估/跳过数) * - 准确率对比表格 * - 空态与加载态 */ import { useCallback, useEffect, useState } from 'react' import { fetchEvalSummary, fetchLeagues } from '../dal' import type { EvalSummary } from '../types' import { Card, CardBody, CardHeader, StatCard, Badge, DataTable, Alert, Spinner, EmptyState } from '../components' interface Filters { provider: string model: string prompt_version: string mode: string league_code: string } const EMPTY_FILTERS: Filters = { provider: '', model: '', prompt_version: '', mode: '', league_code: '' } export default function EvalPage() { const [filters, setFilters] = useState(EMPTY_FILTERS) const [leagues, setLeagues] = useState>([]) const [data, setData] = useState(null) const [loading, setLoading] = useState(false) const [error, setError] = useState(null) useEffect(() => { fetchLeagues() .then(l => setLeagues(l.map(x => ({ code: x.code, name: x.name })))) .catch(() => setLeagues([])) }, []) const load = useCallback(async () => { setLoading(true) setError(null) try { const params: Record = {} if (filters.provider) params.provider = filters.provider if (filters.model) params.model = filters.model if (filters.prompt_version) params.prompt_version = filters.prompt_version if (filters.mode) params.mode = filters.mode if (filters.league_code) params.league_code = filters.league_code const result = await fetchEvalSummary(params) setData(result) } catch (err: unknown) { setError(err instanceof Error ? err.message : '加载失败') } finally { setLoading(false) } }, [filters]) useEffect(() => { load() }, [load]) const handleChange = (key: keyof Filters) => (e: React.ChangeEvent) => { setFilters(f => ({ ...f, [key]: e.target.value })) } const handleReset = () => setFilters(EMPTY_FILTERS) const summary = data?.summary ?? [] return (
{/* 筛选控件 */}
{/* 错误态 */} {error && } {/* 汇总统计 */} {data && (
)} {/* 准确率表格 */} {loading ? (
) : summary.length === 0 ? ( ) : ( ( {row.accuracy_1x2 != null ? `${row.accuracy_1x2}%` : '—'} ) }, { key: 'avg_score_rmse', label: '比分 RMSE', render: (row: any) => ( {row.avg_score_rmse != null ? row.avg_score_rmse.toFixed(2) : '—'} ) }, { key: 'avg_subjective_confidence', label: '平均置信度', render: (row: any) => ( {row.avg_subjective_confidence != null ? row.avg_subjective_confidence.toFixed(2) : '—'} ) }, ]} data={summary} rowKey={(row: any) => `${row.provider}-${row.model}`} emptyText="暂无评估数据" /> )}
) }