import { useState } from 'react' import { Button, Empty, Form, Input, InputNumber, Select, Space, Table, Tag, Tooltip, message, } from 'antd' import type { ColumnsType } from 'antd/es/table' import { PlusOutlined, ReloadOutlined, EyeOutlined, FileTextOutlined } from '@ant-design/icons' import FormDrawer from '../components/FormDrawer' import PageWrapper from '../components/PageWrapper' import EvalDetail from '../components/intelligent_eval/EvalDetail' import EvalReport from '../components/intelligent_eval/EvalReport' import { EVAL_STATUS } from '../components/intelligent_eval/status' import { usePolling } from '../hooks/usePolling' import { useResource } from '../hooks/useResource' import { intelligentEvalsApi, targetsApi, type CreateIntelligentEvalPayload, type IntelligentEval, type Target, } from '../api' import { colors } from '../tokens' import { formatDateTime } from '../utils/date' type View = 'list' | 'detail' | 'report' interface CreateFormValues { name: string target_id: string goal: string intent?: string role_description?: string seeds_json?: string time_window_hours: number } export default function IntelligentEvalsPage() { const [view, setView] = useState('list') const [selectedId, setSelectedId] = useState(null) const [detailTick, setDetailTick] = useState(0) const [createOpen, setCreateOpen] = useState(false) const [submitting, setSubmitting] = useState(false) const [form] = Form.useForm() const { data: evals, loading, reload } = useResource( () => intelligentEvalsApi.list().then((r) => r.data.intelligent_evals), { tabPath: '/intelligent-evals' }, ) const { data: targets } = useResource( () => targetsApi.list().then((r) => r.data), { tabPath: '/intelligent-evals' }, ) const { data: selected, reload: reloadSelected } = useResource( () => (selectedId ? intelligentEvalsApi.get(selectedId).then((r) => r.data) : Promise.resolve(null)), { deps: [selectedId, detailTick] }, ) const pollActive = view === 'detail' && selected != null && (selected.status === 'planning' || selected.status === 'executing' || selected.status === 'pending_approval') usePolling(() => void reloadSelected(true), 5000, pollActive) const targetName = (id: string) => targets?.find((t) => t.id === id)?.name ?? id.slice(0, 8) const openDetail = (id: string) => { setSelectedId(id) setView('detail') } const openReport = (id: string) => { setSelectedId(id) setView('report') } const submitCreate = async () => { const values = await form.validateFields() let seeds: Record = {} const raw = (values.seeds_json ?? '').trim() if (raw) { try { const parsed = JSON.parse(raw) as unknown if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) { message.error('种子集必须是 JSON 对象') return } seeds = parsed as Record } catch { message.error('种子集不是合法 JSON') return } } const payload: CreateIntelligentEvalPayload = { name: values.name, target_id: values.target_id, goal: values.goal, seeds, intent: values.intent ?? '', role_description: values.role_description ?? '', time_window_hours: values.time_window_hours, } setSubmitting(true) try { await intelligentEvalsApi.create(payload) message.success('已创建,OpenClaw 开始规划') setCreateOpen(false) form.resetFields() void reload() } finally { setSubmitting(false) } } const columns: ColumnsType = [ { title: '名称', dataIndex: 'name', key: 'name', render: (name: string) => {name}, }, { title: '评测对象', dataIndex: 'target_id', key: 'target', width: 180, render: (id: string) => targetName(id), }, { title: '状态', dataIndex: 'status', key: 'status', width: 110, render: (status: IntelligentEval['status']) => { const meta = EVAL_STATUS[status] ?? { label: status, color: 'default' } return {meta.label} }, }, { title: '会话进度', key: 'progress', width: 120, render: (_, ev) => `${ev.completed_sessions}/${ev.session_count}`, }, { title: '创建时间', dataIndex: 'created_at', key: 'created_at', width: 170, render: (v: string | null) => (v ? formatDateTime(v) : '—'), }, { title: '操作', key: 'action', width: 110, fixed: 'right' as const, render: (_, ev) => ( } >
20 ? { pageSize: 20, showTotal: (t) => `共 ${t} 个` } : false} locale={{ emptyText: }} /> setCreateOpen(false)} onSubmit={submitCreate} submitting={submitting} okText="创建并开始规划" >