From 60c545ab78e797a57d2a66587bbfcc7b20741601 Mon Sep 17 00:00:00 2001 From: sinohqb Date: Tue, 18 Aug 2026 10:48:13 +0800 Subject: [PATCH] fix(intelligent-eval): task queue all-count + unresolved filter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 任务队列全部任务计数把派生的 unresolved 字段也求和了(stats 含 pending/assigned/completed/failed/unresolved),导致显示 9 而实际 8 条。 - 全部任务 = 四态之和(排除 unresolved),与后端 stats 对齐 - 改为一次拉取全部 + 前端过滤(unresolved 是 pending+assigned 并集, 后端 status 单选无法表达);筛选/分页为前端状态,筛选变化重置到第 1 页 tsc 0 错误 vitest 16 passed --- .../intelligent_eval/TaskQueueMonitor.tsx | 31 +++++++++++++++---- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/frontend/web/src/components/intelligent_eval/TaskQueueMonitor.tsx b/frontend/web/src/components/intelligent_eval/TaskQueueMonitor.tsx index f4fa073..24c40e1 100644 --- a/frontend/web/src/components/intelligent_eval/TaskQueueMonitor.tsx +++ b/frontend/web/src/components/intelligent_eval/TaskQueueMonitor.tsx @@ -31,14 +31,15 @@ export default function TaskQueueMonitor() { pending: number; assigned: number; completed: number; failed: number; unresolved: number } | null>(null) const [filter, setFilter] = useState('all') + const [page, setPage] = useState(1) const [loading, setLoading] = useState(false) + // 一次拉取全部任务,筛选在前端完成(数据量小;unresolved 是 pending+assigned 并集, + // 后端 status 筛选无法一次表达,且 stats 含派生的 unresolved,不能直接求和当总数)。 const loadData = async () => { setLoading(true) try { - const res = await intelligentEvalsApi.listTasks( - filter === 'all' || filter === 'unresolved' ? undefined : { status: filter }, - ) + const res = await intelligentEvalsApi.listTasks() setTasks(res.data.tasks) setStats(res.data.stats) } catch { @@ -48,16 +49,31 @@ export default function TaskQueueMonitor() { } } - // Initial fetch + reload on filter change (usePolling owns the 5s interval). + // Initial fetch (usePolling owns the 5s interval). 筛选/分页为前端状态。 useEffect(() => { void loadData() // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) + + // 筛选变化时回到第 1 页 + useEffect(() => { + setPage(1) }, [filter]) usePolling(() => { void loadData() }, 5000, true) + const allTasks = tasks ?? [] + const visibleTasks = filter === 'all' + ? allTasks + : filter === 'unresolved' + ? allTasks.filter((t) => t.status === 'pending' || t.status === 'assigned') + : allTasks.filter((t) => t.status === filter) + + // 全部任务 = 四态之和(不含派生的 unresolved);与后端 stats 对齐 + const totalAll = stats ? stats.pending + stats.assigned + stats.completed + stats.failed : allTasks.length + const chipMeta: { key: FilterKey; label: string; color?: string; get: () => number }[] = [ - { key: 'all', label: '全部任务', get: () => (stats ? Object.values(stats).reduce((a, b) => a + b, 0) : (tasks?.length ?? 0)) }, + { key: 'all', label: '全部任务', get: () => totalAll }, { key: 'unresolved', label: '待处理', color: colors.warning, get: () => stats?.unresolved ?? 0 }, { key: 'pending', label: '待认领', get: () => stats?.pending ?? 0 }, { key: 'assigned', label: '执行中', color: colors.primary, get: () => stats?.assigned ?? 0 }, @@ -132,13 +148,16 @@ export default function TaskQueueMonitor() { `共 ${t} 条`, + onChange: (p) => setPage(p), }} locale={{ emptyText: }} />