'use client'; import React, { useState, useEffect } from 'react'; import { Badge, IconButton, Tooltip, CircularProgress, Menu, MenuItem, Divider, ListItemIcon } from '@mui/material'; import TaskAltIcon from '@mui/icons-material/TaskAlt'; import ListAltIcon from '@mui/icons-material/ListAlt'; import QuizIcon from '@mui/icons-material/Quiz'; import AssessmentIcon from '@mui/icons-material/Assessment'; import CleaningServicesIcon from '@mui/icons-material/CleaningServices'; import { useTranslation } from 'react-i18next'; import { useRouter, usePathname } from 'next/navigation'; import useFileProcessingStatus from '@/hooks/useFileProcessingStatus'; import { useAtomValue } from 'jotai/index'; import { selectedModelInfoAtom } from '@/lib/store'; import axios from 'axios'; import { toast } from 'sonner'; export default function TaskIcon({ projectId, theme }) { const { t, i18n } = useTranslation(); const router = useRouter(); const pathname = usePathname(); const [tasks, setTasks] = useState([]); const [menuAnchorEl, setMenuAnchorEl] = useState(null); const isMenuOpen = Boolean(menuAnchorEl); const selectedModel = useAtomValue(selectedModelInfoAtom); const { setTaskFileProcessing, setTask } = useFileProcessingStatus(); const fetchPendingTasks = async () => { if (!projectId) return; try { const response = await axios.get(`/api/projects/${projectId}/tasks/list?status=0`); if (response.data?.code === 0) { const pendingTasks = response.data.data || []; setTasks(pendingTasks); const hasActiveFileTask = pendingTasks.some( task => task.projectId === projectId && task.taskType === 'file-processing' ); setTaskFileProcessing(hasActiveFileTask); if (hasActiveFileTask) { const activeTask = pendingTasks.find( task => task.projectId === projectId && task.taskType === 'file-processing' ); try { const detailInfo = JSON.parse(activeTask?.detail || '{}'); setTask(detailInfo); } catch { setTask(null); } } } } catch (error) { console.error('Failed to fetch task list:', error); } }; useEffect(() => { if (!projectId) return; fetchPendingTasks(); const intervalId = setInterval(() => { fetchPendingTasks(); }, 10000); return () => { clearInterval(intervalId); }; }, [projectId]); useEffect(() => { setMenuAnchorEl(null); }, [pathname]); const handleOpenTaskList = () => { setMenuAnchorEl(null); router.push(`/projects/${projectId}/tasks`); }; const handleMenuOpen = event => { if (isMenuOpen) { setMenuAnchorEl(null); return; } setMenuAnchorEl(event.currentTarget); }; const handleMenuClose = () => { setMenuAnchorEl(null); }; const createBatchTask = async (taskType, detail) => { if (!projectId || !selectedModel?.id) { toast.error(t('textSplit.selectModelFirst')); return; } try { const response = await axios.post(`/api/projects/${projectId}/tasks`, { taskType, modelInfo: selectedModel, language: i18n.language, detail }); if (response.data?.code === 0) { toast.success(t('tasks.createSuccess')); await fetchPendingTasks(); } else { toast.error(`${t('tasks.createFailed')}: ${response.data?.message || ''}`); } } catch (error) { console.error('Create batch task failed:', error); toast.error(`${t('tasks.createFailed')}: ${error.message}`); } }; const handleCreateAutoQuestionTask = async () => { await createBatchTask('question-generation', '批量生成问题任务'); handleMenuClose(); }; const handleCreateAutoEvalTask = async () => { await createBatchTask('eval-generation', '批量生成评估集任务'); handleMenuClose(); }; const handleCreateAutoCleaningTask = async () => { await createBatchTask('data-cleaning', '批量数据清洗任务'); handleMenuClose(); }; const renderTaskIcon = () => { const pendingTasks = tasks.filter(task => task.status === 0); if (pendingTasks.length > 0) { return ( ); } return ; }; const getTooltipText = () => { const pendingTasks = tasks.filter(task => task.status === 0); if (pendingTasks.length > 0) { return t('tasks.pending', { count: pendingTasks.length }); } return t('tasks.completed'); }; if (!projectId) return null; return ( <> {renderTaskIcon()} {t('tasks.title')} {t('textSplit.autoGenerateQuestions', { defaultValue: '自动提取问题' })} {t('textSplit.autoEvalGeneration', { defaultValue: '自动生成评估集' })} {t('textSplit.autoDataCleaning', { defaultValue: '自动数据清洗' })} ); }