import { useEffect, useState } from 'react'; import { Table, Typography, Button, Space, Empty, Tooltip } from 'antd'; import { FolderOpen, FileText, ArrowLeft } from 'lucide-react'; import { queryEvaluationFilesUsingGet, queryEvaluationItemsUsingGet } from '../../evaluation.api'; import useFetchData from '@/hooks/useFetchData'; const { Text } = Typography; const COLUMN_WIDTH = 520; const MONO_FONT = 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace'; const codeBlockStyle = { fontFamily: MONO_FONT, fontSize: 12, lineHeight: '20px', color: '#334155', backgroundColor: '#f8fafc', border: '1px solid #f0f0f0', borderRadius: 6, padding: 8, } as const; type EvalFile = { taskId: string; fileId: string; fileName: string; totalCount: number; evaluatedCount: number; pendingCount: number; }; type EvalItem = { id: string; taskId: string; itemId: string; fileId: string; evalContent: any; evalScore?: number | null; evalResult: any; status?: string; }; export default function EvaluationItems({ task }: { task: any }) { const [selectedFile, setSelectedFile] = useState<{ fileId: string; fileName: string } | null>(null); // 文件列表数据(使用 useFetchData),pageOffset=0 表示后端分页为 1 基 const { loading: loadingFiles, tableData: files, pagination: filePagination, setSearchParams: setFileSearchParams, } = useFetchData( (params) => queryEvaluationFilesUsingGet({ taskId: task?.id, ...params }), (d) => d as unknown as EvalFile, 30000, false, [], 0 ); // 评估条目数据(使用 useFetchData),依赖选中文件 const { loading: loadingItems, tableData: items, pagination: itemPagination, setSearchParams: setItemSearchParams, fetchData: fetchItems, } = useFetchData( (params) => { if (!task?.id || !selectedFile?.fileId) { return Promise.resolve({ data: { content: [], totalElements: 0 } }); } return queryEvaluationItemsUsingGet({ taskId: task.id, file_id: selectedFile.fileId, ...params }); }, (d) => d as unknown as EvalItem, 30000, false, [], 0 ); // 当选择文件变化时,主动触发一次条目查询,避免仅依赖 searchParams 变更导致未触发 useEffect(() => { if (task?.id && selectedFile?.fileId) { setItemSearchParams((prev: any) => ({ ...prev, current: 1 })); // 立即拉取一次,保证点击后立刻出现数据 fetchItems(); } }, [task?.id, selectedFile?.fileId]); const fileColumns = [ { title: '文件名', dataIndex: 'fileName', key: 'fileName', render: (_: any, record: EvalFile) => ( { e.stopPropagation(); setSelectedFile({ fileId: record.fileId, fileName: record.fileName }); }} style={{ cursor: 'pointer' }}> ), }, { title: '总条目', dataIndex: 'totalCount', key: 'totalCount', width: 120, }, { title: '已评估', dataIndex: 'evaluatedCount', key: 'evaluatedCount', width: 120, }, { title: '待评估', dataIndex: 'pendingCount', key: 'pendingCount', width: 120, }, ]; const renderEvalObject = (rec: EvalItem) => { const c = rec.evalContent; let jsonString = ''; try { if (typeof c === 'string') { // 尝试将字符串解析为 JSON,失败则按原字符串显示 try { jsonString = JSON.stringify(JSON.parse(c), null, 2); } catch { jsonString = JSON.stringify({ value: c }, null, 2); } } else { jsonString = JSON.stringify(c, null, 2); } } catch { jsonString = 'null'; } return ( {jsonString}} overlayInnerStyle={{ maxHeight: 600, overflow: 'auto', width: COLUMN_WIDTH }} >
{jsonString}
); }; const renderEvalResult = (rec: EvalItem) => { const r = rec.evalResult; let jsonString = ''; try { if (typeof r === 'string') { try { jsonString = JSON.stringify(JSON.parse(r), null, 2); } catch { jsonString = JSON.stringify({ value: r, score: rec.evalScore ?? undefined }, null, 2); } } else { const withScore = rec.evalScore !== undefined && rec.evalScore !== null ? { ...r, evalScore: rec.evalScore } : r; jsonString = JSON.stringify(withScore, null, 2); } } catch { jsonString = 'null'; } // 判空展示未评估 const isEmpty = !r || (typeof r === 'string' && r.trim() === '') || (typeof r === 'object' && r !== null && Object.keys(r).length === 0); if (isEmpty) { return 未评估; } return ( {jsonString}} overlayInnerStyle={{ maxHeight: 600, overflow: 'auto' }} >
{jsonString}
); }; const itemColumns = [ { title: '评估对象', dataIndex: 'evalContent', key: 'evalContent', render: (_: any, record: EvalItem) => renderEvalObject(record), width: COLUMN_WIDTH, }, { title: '评估结果', dataIndex: 'evalResult', key: 'evalResult', render: (_: any, record: EvalItem) => renderEvalResult(record), width: COLUMN_WIDTH, }, ]; if (!task?.id) return ; return (
{!selectedFile ? ( r.fileId} columns={fileColumns} dataSource={files} loading={loadingFiles} size="middle" onRow={(record) => ({ onClick: () => { setSelectedFile({ fileId: record.fileId, fileName: record.fileName }); // 切换文件时,重置条目表到第一页 setItemSearchParams((prev: any) => ({ ...prev, current: 1 })); }, })} pagination={filePagination} /> ) : (
{selectedFile.fileName} 文件ID:{selectedFile.fileId} 共 {itemPagination.total} 条
r.id} columns={itemColumns} dataSource={items} loading={loadingItems} size="middle" pagination={itemPagination} /> )} ); }