'use client'; import React from 'react'; import { TaskStatistics } from '@/api/video_flow'; interface TaskStatusChartProps { statistics: TaskStatistics[]; } export default function TaskStatusChart({ statistics }: TaskStatusChartProps) { // 聚合所有项目的状态数据 const aggregatedData = React.useMemo(() => { if (statistics.length === 0) { return []; } const totals = statistics.reduce( (acc, stat) => ({ completed: acc.completed + stat.status_stats.completed, in_progress: acc.in_progress + stat.status_stats.in_progress, pending: acc.pending + stat.status_stats.pending, failed: acc.failed + stat.status_stats.failed, blocked: acc.blocked + stat.status_stats.blocked, }), { completed: 0, in_progress: 0, pending: 0, failed: 0, blocked: 0, } ); const total = Object.values(totals).reduce((sum, val) => sum + val, 0); return [ { name: '已完成', value: totals.completed, color: '#10b981', percentage: total > 0 ? (totals.completed / total) * 100 : 0 }, { name: '进行中', value: totals.in_progress, color: '#3b82f6', percentage: total > 0 ? (totals.in_progress / total) * 100 : 0 }, { name: '等待中', value: totals.pending, color: '#f59e0b', percentage: total > 0 ? (totals.pending / total) * 100 : 0 }, { name: '失败', value: totals.failed, color: '#ef4444', percentage: total > 0 ? (totals.failed / total) * 100 : 0 }, { name: '阻塞', value: totals.blocked, color: '#f97316', percentage: total > 0 ? (totals.blocked / total) * 100 : 0 }, ].filter(item => item.value > 0); }, [statistics]); // 简单的饼图实现 const PieChart = ({ data }: { data: typeof aggregatedData }) => { const total = data.reduce((sum, item) => sum + item.value, 0); let cumulativePercentage = 0; return (
{data.map((item, index) => { const percentage = (item.value / total) * 100; const strokeDasharray = `${percentage * 5.03} 502`; const strokeDashoffset = -cumulativePercentage * 5.03; cumulativePercentage += percentage; return ( ); })} {/* 中心文字 */}
{total.toLocaleString()}
总任务数
); }; // 柱状图实现 const BarChart = ({ data }: { data: typeof aggregatedData }) => { const maxValue = Math.max(...data.map(item => item.value)); return (
{data.map((item, index) => (
{item.name}
0 ? (item.value / maxValue) * 100 : 0}%`, }} />
{item.value} {item.percentage.toFixed(1)}%
))}
); }; if (statistics.length === 0) { return (

任务状态分布

📊
暂无数据
); } return (

任务状态分布

{statistics.length > 1 ? `${statistics.length} 个项目` : '单项目视图'}
{/* 饼图 */}

状态占比

{/* 柱状图 */}

详细数据

{/* 图例 */}
{aggregatedData.map((item, index) => (
{item.name} ({item.value})
))}
{/* 多项目详情 */} {statistics.length > 1 && (

项目详情

{statistics.map((stat, index) => (
{stat.project_name || stat.project_id}
{stat.total_tasks}
✓{stat.status_stats.completed} ⚡{stat.status_stats.in_progress} ⏳{stat.status_stats.pending} ✗{stat.status_stats.failed} {stat.status_stats.blocked > 0 && ( 🚫{stat.status_stats.blocked} )}
))}
)}
); }