diff --git a/frontend/web/src/pages/Home.tsx b/frontend/web/src/pages/Home.tsx index f5e955b..fd9a3c2 100644 --- a/frontend/web/src/pages/Home.tsx +++ b/frontend/web/src/pages/Home.tsx @@ -216,6 +216,11 @@ function RecentRunRow({ run, onOpen }: { run: Run; onOpen: () => void }) { {run.scenario_name || run.scenario_id.slice(0, 8)} · {run.target_name || run.target_id.slice(0, 8)} + {run.scenario_version != null && ( + + v{run.scenario_version} + + )} {trigger !== 'manual' && ( {triggerLabels[trigger] ?? trigger} diff --git a/frontend/web/src/pages/Reports.tsx b/frontend/web/src/pages/Reports.tsx index 8c563e4..25d2d94 100644 --- a/frontend/web/src/pages/Reports.tsx +++ b/frontend/web/src/pages/Reports.tsx @@ -159,15 +159,26 @@ export default function ReportsPage() { clearSelection() } - // 场景筛选项:从 run 列表聚合(含各场景 run 数量) + // 场景筛选项:从 run 列表聚合(含各场景 run 数量与出现过的考纲版本) const scenarioOptions = useMemo(() => { - const map = new Map() + const map = new Map }>() for (const r of runs) { const entry = map.get(r.scenario_id) - if (entry) entry.count += 1 - else map.set(r.scenario_id, { name: r.scenario_name || r.scenario_id.slice(0, 8), count: 1 }) + if (entry) { + entry.count += 1 + entry.versions.add(r.scenario_version ?? 1) + } else { + map.set(r.scenario_id, { + name: r.scenario_name || r.scenario_id.slice(0, 8), + count: 1, + versions: new Set([r.scenario_version ?? 1]), + }) + } } - return [...map.entries()].map(([id, s]) => ({ value: id, label: `${s.name}(${s.count})` })) + return [...map.entries()].map(([id, s]) => { + const versions = [...s.versions].sort((a, b) => a - b).map((v) => `v${v}`).join('/') + return { value: id, label: `${s.name}(${s.count} · ${versions})` } + }) }, [runs]) const filteredRuns = useMemo( @@ -179,15 +190,17 @@ export default function ReportsPage() { const passRate = (r.summary as Record)?.pass_rate as number | undefined const pct = passRate != null ? `${Math.round(passRate * 100)}%` : '-' const scenario = r.scenario_name || r.scenario_id.slice(0, 8) + const version = `v${r.scenario_version ?? 1}` const target = r.target_name || r.target_id.slice(0, 8) const time = r.started_at ? formatDateTime(r.started_at) : '' const trigger = r.triggered_by ?? 'manual' return { value: r.id, - searchText: `${scenario} ${target} ${time} ${r.id} ${triggerLabels[trigger] ?? trigger}`.toLowerCase(), + searchText: `${scenario} ${version} ${target} ${time} ${r.id} ${triggerLabels[trigger] ?? trigger}`.toLowerCase(), label: ( {scenario} + {version} · {target} {time} (opt?.label as string ?? '').toLowerCase().includes(input.toLowerCase())} placeholder="选择评测场景" - options={scenarios.map((s) => ({ label: s.name, value: s.id }))} + options={scenarios.map((s) => ({ label: `${s.name}(v${s.version ?? 1})`, value: s.id }))} style={{ flex: 1 }} size="middle" /> diff --git a/frontend/web/src/pages/Scenarios.tsx b/frontend/web/src/pages/Scenarios.tsx index 9d4f665..e242d85 100644 --- a/frontend/web/src/pages/Scenarios.tsx +++ b/frontend/web/src/pages/Scenarios.tsx @@ -248,7 +248,7 @@ export default function ScenariosPage() { setDrawerOpen(false)} width={720} @@ -329,7 +329,7 @@ export default function ScenariosPage() { setPreviewOpen(false)} footer={null}