import React, { useEffect, useState, useCallback } from 'react'; import { Brain, Clock, CheckCircle, XCircle, AlertCircle, Pause, Play, Square, TrendingUp, BarChart3, Eye, Star, Target } from 'lucide-react'; import { useVideoClassificationStore } from '../store/videoClassificationStore'; import type { QueueStats, TaskProgress, ClassificationStats } from '../store/videoClassificationStore'; interface VideoClassificationProgressProps { materialId?: string; projectId?: string; autoRefresh?: boolean; refreshInterval?: number; } /** * AI视频分类进度显示组件 * 遵循前端开发规范的UI设计,提供优美的动画效果和用户体验 */ export const VideoClassificationProgress: React.FC = ({ materialId, projectId, autoRefresh = true, refreshInterval = 3000, }) => { const { queueStats, taskProgress, refreshQueueStatus, refreshTaskProgress, getProjectQueueStatus, getProjectTaskProgress, getClassificationStats, error, clearError, } = useVideoClassificationStore(); // Type assertions to satisfy TypeScript const typedQueueStats: QueueStats | null = queueStats; const typedTaskProgress: Record = taskProgress; const [stats, setStats] = useState(null); const [isExpanded, setIsExpanded] = useState(false); // 刷新队列状态的方法 const refreshQueueStats = useCallback(async () => { if (projectId) { return await getProjectQueueStatus(projectId); } else { return await refreshQueueStatus(); } }, [projectId, getProjectQueueStatus, refreshQueueStatus]); // 刷新任务进度的方法 const refreshProgress = useCallback(async () => { if (projectId) { await getProjectTaskProgress(projectId); } else { await refreshTaskProgress(); } }, [projectId, getProjectTaskProgress, refreshTaskProgress]); // 自动刷新 useEffect(() => { if (!autoRefresh) return; const interval = setInterval(async () => { await refreshQueueStats(); await refreshProgress(); if (projectId) { try { const classificationStats = await getClassificationStats(projectId); setStats(classificationStats); } catch (error) { console.error('获取分类统计失败:', error); } } }, refreshInterval); return () => clearInterval(interval); }, [autoRefresh, refreshInterval, projectId, refreshQueueStats, refreshProgress, getClassificationStats]); // 初始加载 useEffect(() => { refreshQueueStats(); refreshProgress(); if (projectId) { getClassificationStats(projectId).then(setStats).catch(console.error); } }, [projectId, refreshQueueStats, refreshProgress, getClassificationStats]); // 获取状态颜色和图标 const getStatusInfo = (status: string) => { switch (status) { case 'Running': return { color: 'text-green-600 bg-green-50', icon: Play, text: '运行中' }; case 'Paused': return { color: 'text-yellow-600 bg-yellow-50', icon: Pause, text: '已暂停' }; case 'Stopped': return { color: 'text-gray-600 bg-gray-50', icon: Square, text: '已停止' }; default: return { color: 'text-gray-600 bg-gray-50', icon: Square, text: '未知' }; } }; // 获取任务状态信息 const getTaskStatusInfo = (status: string) => { switch (status) { case 'Pending': return { color: 'text-blue-600', icon: Clock, text: '等待中' }; case 'Uploading': return { color: 'text-purple-600', icon: TrendingUp, text: '上传中' }; case 'Analyzing': return { color: 'text-indigo-600', icon: Brain, text: '分析中' }; case 'Completed': return { color: 'text-green-600', icon: CheckCircle, text: '已完成' }; case 'Failed': return { color: 'text-red-600', icon: XCircle, text: '失败' }; case 'Cancelled': return { color: 'text-gray-600', icon: AlertCircle, text: '已取消' }; default: return { color: 'text-gray-600', icon: Clock, text: '未知' }; } }; // 计算进度百分比 const getOverallProgress = () => { if (!typedQueueStats || typedQueueStats.total_tasks === 0) return 0; return Math.round(((typedQueueStats.completed_tasks + typedQueueStats.failed_tasks) / typedQueueStats.total_tasks) * 100); }; // 过滤相关任务 const relevantTasks = materialId ? Object.values(typedTaskProgress).filter(task => task.task_id.includes(materialId)) : Object.values(typedTaskProgress); if (!typedQueueStats && !relevantTasks.length && !stats) { return null; } const statusInfo = typedQueueStats ? getStatusInfo(typedQueueStats.status) : null; const overallProgress = getOverallProgress() return (
{/* 错误提示 */} {error && (
{error}
)} {/* 主要状态显示 */}

AI视频分类

{statusInfo && ( {statusInfo.text} )}
{/* 队列控制按钮 */} {typedQueueStats && (
状态: {typedQueueStats.status}
)}
{/* 整体进度条 */} {typedQueueStats && typedQueueStats.total_tasks > 0 && (
整体进度 {overallProgress}%
)} {/* 统计信息网格 */} {typedQueueStats && (
{typedQueueStats.pending_tasks}
等待中
{typedQueueStats.processing_tasks}
处理中
{typedQueueStats.completed_tasks}
已完成
{typedQueueStats.failed_tasks}
失败
)} {/* 处理速率 */} {typedQueueStats && typedQueueStats.processing_rate > 0 && (
处理速率: {typedQueueStats.processing_rate.toFixed(1)} 任务/分钟
)} {/* 展开/收起详细信息 */} {relevantTasks.length > 0 && ( )}
{/* 详细任务列表 */} {isExpanded && relevantTasks.length > 0 && (
{relevantTasks.map((task) => { const taskStatusInfo = getTaskStatusInfo(task.status); return (
任务 #{task.task_id.slice(-8)}
{taskStatusInfo.text}
{task.current_step}
{task.progress_percentage > 0 && (
)} {task.error_message && (
{task.error_message}
)}
); })}
)} {/* 分类统计 */} {stats && (
分类统计
总分类: {stats.total_classifications}
平均置信度: {(stats.average_confidence * 100).toFixed(1)}%
平均质量: {(stats.average_quality_score * 100).toFixed(1)}%
)}
); };