'use client'; import { useState } from 'react'; import { Card, CardContent, Box, Typography, Chip, IconButton, LinearProgress, Menu, MenuItem, ListItemIcon, Avatar, useTheme } from '@mui/material'; import MoreVertIcon from '@mui/icons-material/MoreVert'; import DeleteIcon from '@mui/icons-material/Delete'; import StopIcon from '@mui/icons-material/Stop'; import VisibilityIcon from '@mui/icons-material/Visibility'; import CheckCircleIcon from '@mui/icons-material/CheckCircle'; import ErrorIcon from '@mui/icons-material/Error'; import PauseCircleIcon from '@mui/icons-material/PauseCircle'; import HourglassEmptyIcon from '@mui/icons-material/HourglassEmpty'; import SmartToyIcon from '@mui/icons-material/SmartToy'; import QuizIcon from '@mui/icons-material/Quiz'; import { useTranslation } from 'react-i18next'; import { getModelIcon } from '@/lib/util/modelIcon'; import styles from '../styles'; const STATUS_CONFIG = { 0: { label: 'evalTasks.statusProcessing', color: 'info', icon: HourglassEmptyIcon }, 1: { label: 'evalTasks.statusCompleted', color: 'success', icon: CheckCircleIcon }, 2: { label: 'evalTasks.statusFailed', color: 'error', icon: ErrorIcon }, 3: { label: 'evalTasks.statusInterrupted', color: 'warning', icon: PauseCircleIcon } }; export default function EvalTaskCard({ task, onView, onDelete, onInterrupt }) { const { t } = useTranslation(); const theme = useTheme(); const [anchorEl, setAnchorEl] = useState(null); const open = Boolean(anchorEl); const { modelInfo, detail, status, completedCount, totalCount, createAt } = task; const statusConfig = STATUS_CONFIG[status] || STATUS_CONFIG[0]; const StatusIcon = statusConfig.icon; const progress = totalCount > 0 ? (completedCount / totalCount) * 100 : 0; const finalScore = detail?.finalScore; const handleMenuClick = e => { e.stopPropagation(); setAnchorEl(e.currentTarget); }; const handleMenuClose = () => setAnchorEl(null); const handleAction = action => () => { handleMenuClose(); action?.(task); }; const getScoreColor = score => { if (score >= 80) return 'success'; if (score >= 60) return 'info'; if (score >= 40) return 'warning'; return 'error'; }; return ( {/* 头部 */} {modelInfo?.modelId {modelInfo?.modelName || modelInfo?.modelId} {modelInfo?.providerName || modelInfo?.providerId} {/* 状态和得分 */} } label={t(statusConfig.label)} color={statusConfig.color} size="small" variant="outlined" sx={{ height: 24, '& .MuiChip-label': { px: 1, fontSize: '0.7rem' } }} /> {finalScore !== undefined && status === 1 && ( )} {/* 进度条 */} {status === 0 && ( {t('evalTasks.progress')} {completedCount}/{totalCount} )} {/* 统计信息 */} } label={`${totalCount} ${t('evalTasks.questions')}`} size="small" variant="outlined" sx={{ height: 22, '& .MuiChip-label': { px: 0.75, fontSize: '0.7rem' } }} /> {detail?.hasSubjectiveQuestions && ( )} {/* 时间 */} {new Date(createAt).toLocaleString()} {/* 菜单 */} e.stopPropagation()}> {t('datasets.viewDetails')} {status === 0 && ( {t('evalTasks.interrupt')} )} {t('common.delete')} ); }