import React, { useEffect, useState } from 'react' import { Table, Button, Modal, Form, Input, Select, InputNumber, Tag, Space, Popconfirm, message, Checkbox, Tooltip, Divider } from 'antd' import { PlusOutlined, DeleteOutlined, EyeOutlined, ReloadOutlined, QuestionCircleOutlined } from '@ant-design/icons' import { useNavigate, useSearchParams } from 'react-router-dom' import { taskApi, datasetApi, configApi } from '../../services/api' import { METRICS, RETRIEVAL_METRICS, GENERATION_METRICS, ALL_METRIC_KEYS } from '../../constants/metrics' const { Option } = Select const STATUS_COLOR: Record = { pending: 'default', running: 'processing', done: 'success', failed: 'error', } export default function Task() { const [tasks, setTasks] = useState([]) const [datasets, setDatasets] = useState([]) const [platforms, setPlatforms] = useState([]) const [judges, setJudges] = useState([]) const [modal, setModal] = useState(false) const [form] = Form.useForm() const navigate = useNavigate() const [searchParams] = useSearchParams() const [selectedRowKeys, setSelectedRowKeys] = useState([]) const load = async () => { const res = await taskApi.list() as any setTasks(res.data || []) } useEffect(() => { load() datasetApi.list().then((r: any) => { const ds = r.data || [] setDatasets(ds) const datasetId = searchParams.get('dataset_id') if (datasetId) { // 检查数据集是否存在 const found = ds.find((d: any) => d.id === datasetId) if (found) { form.setFieldsValue({ dataset_id: datasetId }) // 自动打开新建任务模态框 setModal(true) } } }) configApi.listPlatforms().then((r: any) => setPlatforms(r.data || [])) configApi.listJudges().then((r: any) => setJudges(r.data || [])) }, []) const runTask = async () => { const vals = await form.validateFields() await taskApi.run(vals) message.success('评测任务已启动') setModal(false) form.resetFields() load() } // ── 批量删除 ──────────────────────────────────────────────────────────────── const handleBatchDelete = async () => { if (selectedRowKeys.length === 0) { message.warning('请先选择要删除的任务') return } Modal.confirm({ title: `确认删除选中的 ${selectedRowKeys.length} 个评测任务?`, content: '删除后将无法恢复,相关评测结果也会被删除。', okText: '确认删除', okType: 'danger', cancelText: '取消', async onOk() { try { await Promise.all(selectedRowKeys.map(id => taskApi.delete(id as string))) message.success(`成功删除 ${selectedRowKeys.length} 个任务`) setSelectedRowKeys([]) load() } catch (e: any) { message.error(e?.message || '批量删除失败') } }, }) } const columns = [ { title: '任务名称', dataIndex: 'name', render: (v: string, r: any) => v || r.id.slice(0, 8) + '...', }, { title: '数据集', dataIndex: 'dataset_id', ellipsis: true }, { title: '评测指标', render: (_: any, r: any) => { const metrics = r.selected_metrics || [] if (metrics.length === 0) { // 向后兼容:显示检索/生成标签 const tags = [] if (r.eval_retrieval) tags.push(检索) if (r.eval_generation) tags.push(生成) return <>{tags} } return {metrics.length} 项指标 }, }, { title: '状态', dataIndex: 'status', render: (v: string) => {v}, }, { title: '进度', render: (_: any, r: any) => r.total > 0 ? `${r.progress} / ${r.total}` : '-', }, { title: '创建时间', dataIndex: 'created_at', render: (v: string) => v?.slice(0, 19) }, { title: '操作', render: (_: any, r: any) => ( {r.status === 'done' && ( )} taskApi.delete(r.id).then(load)}> )} setModal(false)} width={700}>
评测指标选择
检索层指标
{RETRIEVAL_METRICS.map(m => ( {m.cn} ({m.en}) {m.desc} ))}
生成层指标
{GENERATION_METRICS.map(m => ( {m.cn} ({m.en}) {m.desc} ))}
) }