/** * RVW审稿系统 - 主Dashboard页面 */ import { useState, useEffect, useCallback } from 'react'; import { message } from 'antd'; import { Sidebar, Header, FilterChips, TaskTable, BatchToolbar, AgentModal, ReportDetail, TaskDetail, } from '../components'; import * as api from '../api'; import type { ReviewTask, ReviewReport, TaskFilters, AgentType } from '../types'; import '../styles/index.css'; export default function Dashboard() { // ==================== State ==================== const [currentView, setCurrentView] = useState<'dashboard' | 'archive'>('dashboard'); const [tasks, setTasks] = useState([]); const [loading, setLoading] = useState(true); const [selectedIds, setSelectedIds] = useState([]); const [filters, setFilters] = useState({ status: 'all', timeRange: 'all' }); const [agentModalVisible, setAgentModalVisible] = useState(false); const [pendingTaskForRun, setPendingTaskForRun] = useState(null); // 报告详情 const [reportDetail, setReportDetail] = useState(null); // 任务详情(支持进度显示) const [viewingTask, setViewingTask] = useState(null); const [currentJobId, setCurrentJobId] = useState(null); // ==================== 数据加载 ==================== const loadTasks = useCallback(async () => { try { setLoading(true); const data = await api.getTasks(filters.status !== 'all' ? filters.status : undefined); // 时间筛选 let filtered = data; if (filters.timeRange === 'today') { const today = new Date().toDateString(); filtered = data.filter(t => new Date(t.createdAt).toDateString() === today); } else if (filters.timeRange === 'week') { const weekAgo = Date.now() - 7 * 24 * 60 * 60 * 1000; filtered = data.filter(t => new Date(t.createdAt).getTime() > weekAgo); } setTasks(filtered); } catch (error) { console.error('加载任务失败:', error); message.error('加载任务列表失败'); } finally { setLoading(false); } }, [filters]); useEffect(() => { loadTasks(); }, [loadTasks]); // 轮询更新进行中的任务 useEffect(() => { const processingTasks = tasks.filter(t => t.status === 'extracting' || t.status === 'reviewing' ); if (processingTasks.length === 0) return; const interval = setInterval(async () => { for (const task of processingTasks) { try { const updated = await api.getTask(task.id); setTasks(prev => prev.map(t => t.id === updated.id ? updated : t)); } catch (error) { console.error('更新任务状态失败:', error); } } }, 3000); return () => clearInterval(interval); }, [tasks]); // ==================== 统计数据 ==================== const counts = { all: tasks.length, pending: tasks.filter(t => t.status === 'pending').length, completed: tasks.filter(t => t.status === 'completed').length, }; // ==================== 事件处理 ==================== const handleUpload = async (files: FileList) => { const uploadPromises = Array.from(files).map(async (file) => { try { message.loading({ content: `正在上传 ${file.name}...`, key: file.name }); await api.uploadManuscript(file); message.success({ content: `${file.name} 上传成功`, key: file.name, duration: 2 }); } catch (error: any) { message.error({ content: `${file.name} 上传失败: ${error.message}`, key: file.name, duration: 3 }); } }); await Promise.all(uploadPromises); loadTasks(); }; const handleRunTask = (task: ReviewTask) => { setPendingTaskForRun(task); setAgentModalVisible(true); }; const handleRunBatch = () => { setPendingTaskForRun(null); // 批量模式 setAgentModalVisible(true); }; const handleConfirmRun = async (agents: AgentType[]) => { // 🔥 保存到局部变量,避免onClose后丢失 const taskToRun = pendingTaskForRun; // 立即关闭弹窗 setAgentModalVisible(false); setPendingTaskForRun(null); try { if (taskToRun) { // 单个任务 - 启动后跳转到详情页显示进度 message.loading({ content: '正在启动审查...', key: 'run' }); const { jobId } = await api.runTask(taskToRun.id, agents); message.success({ content: '审查已启动', key: 'run', duration: 2 }); // 更新任务状态后跳转到详情页(传递jobId) const updatedTask = await api.getTask(taskToRun.id); setCurrentJobId(jobId); setViewingTask(updatedTask); return; } else { // 批量任务 const pendingIds = selectedIds.filter(id => { const task = tasks.find(t => t.id === id); return task && task.status === 'pending'; }); if (pendingIds.length === 0) { message.warning('没有待处理的任务'); return; } message.loading({ content: `正在启动 ${pendingIds.length} 个任务...`, key: 'run' }); await api.batchRunTasks(pendingIds, agents); message.success({ content: `${pendingIds.length} 个任务已启动`, key: 'run', duration: 2 }); setSelectedIds([]); } loadTasks(); } catch (error: any) { message.error({ content: error.message || '启动失败', key: 'run', duration: 3 }); } }; const handleViewReport = async (task: ReviewTask) => { // 直接使用TaskDetail视图(支持进度和报告) setViewingTask(task); }; const handleDeleteTask = async (task: ReviewTask) => { if (!window.confirm(`确定要删除 "${task.fileName}" 吗?`)) { return; } try { message.loading({ content: '正在删除...', key: 'delete' }); await api.deleteTask(task.id); message.success({ content: '删除成功', key: 'delete', duration: 2 }); loadTasks(); } catch (error: any) { message.error({ content: error.message || '删除失败', key: 'delete', duration: 3 }); } }; const handleBackToList = () => { setReportDetail(null); }; // 返回列表并刷新 const handleBackFromDetail = () => { setViewingTask(null); setCurrentJobId(null); loadTasks(); }; // ==================== 渲染 ==================== // 任务详情视图(支持进度显示) if (viewingTask) { return (
); } // 报告详情视图(旧版,保留兼容) if (reportDetail) { return (
); } // 主仪表盘视图 return (
{/* 顶部操作区 */}
{/* 列表区域 */}
{loading ? (
) : ( )}
{/* 批量操作工具栏 */} setSelectedIds([])} /> {/* 智能体选择弹窗 */} { setAgentModalVisible(false); setPendingTaskForRun(null); }} onConfirm={handleConfirmRun} />
); }