715 lines
29 KiB
TypeScript
715 lines
29 KiB
TypeScript
import React, { useState } from 'react';
|
|
import {
|
|
Plus,
|
|
Search,
|
|
Eye,
|
|
Play,
|
|
Pause,
|
|
Clock,
|
|
User,
|
|
ChevronRight,
|
|
Filter,
|
|
FileText,
|
|
AlertTriangle,
|
|
CheckCircle,
|
|
XCircle,
|
|
MoreHorizontal,
|
|
Edit,
|
|
Download,
|
|
Bot,
|
|
Users,
|
|
Workflow,
|
|
X,
|
|
ArrowRight,
|
|
Target,
|
|
Layers,
|
|
} from 'lucide-react';
|
|
import { useTheme } from '@/contexts/ThemeContext';
|
|
import { PageType } from '@/components/Sidebar';
|
|
|
|
interface TaskListPageProps {
|
|
title: string;
|
|
category: string;
|
|
subCategory: string;
|
|
onNavigate: (page: PageType) => void;
|
|
}
|
|
|
|
type TaskType = 'single' | 'consultation' | 'scene' | 'multi-agent';
|
|
type TaskStatus = 'draft' | 'pending' | 'running' | 'paused' | 'blocked' | 'completed';
|
|
type ColumnType = 'unanalyzed' | 'analyzing' | 'completed';
|
|
|
|
interface Task {
|
|
id: string;
|
|
name: string;
|
|
type: TaskType;
|
|
status: TaskStatus;
|
|
agent?: string;
|
|
scene?: string;
|
|
participants?: string[];
|
|
currentPhase?: string;
|
|
currentRound?: number;
|
|
summary?: string;
|
|
creator: string;
|
|
createTime: string;
|
|
updateTime: string;
|
|
column: ColumnType;
|
|
}
|
|
|
|
const TaskListPage: React.FC<TaskListPageProps> = ({ title, category, subCategory, onNavigate }) => {
|
|
const { theme } = useTheme();
|
|
const isDark = theme === 'dark';
|
|
|
|
// 主题颜色变量
|
|
const cardBg = isDark ? 'bg-slate-800/30' : 'bg-white';
|
|
const cardBorder = isDark ? 'border-blue-800/30' : 'border-red-100';
|
|
const textPrimary = isDark ? 'text-white' : 'text-gray-900';
|
|
const textSecondary = isDark ? 'text-slate-400' : 'text-gray-600';
|
|
const textMuted = isDark ? 'text-slate-500' : 'text-gray-400';
|
|
const inputBg = isDark ? 'bg-slate-900/50' : 'bg-white';
|
|
|
|
// 生成模拟数据
|
|
const [tasks] = useState<Task[]>([
|
|
// 未分析列
|
|
{
|
|
id: '2026-0320-001',
|
|
name: '端午节品牌传播方案',
|
|
type: 'scene',
|
|
scene: '宣传策略生成',
|
|
status: 'draft',
|
|
column: 'unanalyzed',
|
|
summary: '针对端午节品牌活动制定完整传播策略方案',
|
|
creator: '李策划',
|
|
createTime: '2026-03-20 10:00',
|
|
updateTime: '2026-03-20 10:00',
|
|
},
|
|
{
|
|
id: '2026-0320-002',
|
|
name: '新品上市用户调研',
|
|
type: 'single',
|
|
agent: 'AudienceAgent',
|
|
status: 'pending',
|
|
column: 'unanalyzed',
|
|
summary: '对新品目标用户进行画像分析',
|
|
creator: '王运营',
|
|
createTime: '2026-03-20 09:30',
|
|
updateTime: '2026-03-20 09:30',
|
|
},
|
|
// 分析中列
|
|
{
|
|
id: '2026-0319-001',
|
|
name: '五四青年节宣传活动策略',
|
|
type: 'scene',
|
|
scene: '宣传策略生成',
|
|
status: 'running',
|
|
currentPhase: '行为分析',
|
|
column: 'analyzing',
|
|
summary: '正在按场景模板执行目标、受众、行为、叙事等分析...',
|
|
creator: '张策略',
|
|
createTime: '2026-03-19 10:30',
|
|
updateTime: '2026-03-20 09:45',
|
|
},
|
|
{
|
|
id: '2026-0319-002',
|
|
name: '青年传播方向会商分析',
|
|
type: 'consultation',
|
|
participants: ['GoalAgent', 'AudienceAgent', 'NarrativeAgent'],
|
|
status: 'running',
|
|
currentRound: 2,
|
|
column: 'analyzing',
|
|
summary: '围绕宣传方向、叙事方式和受众切入点开展多视角会商...',
|
|
creator: '王策划',
|
|
createTime: '2026-03-19 14:00',
|
|
updateTime: '2026-03-20 09:00',
|
|
},
|
|
{
|
|
id: '2026-0318-001',
|
|
name: '年度品牌升级方案推演',
|
|
type: 'scene',
|
|
scene: '宣传方案推演',
|
|
status: 'paused',
|
|
currentPhase: '叙事分析',
|
|
column: 'analyzing',
|
|
summary: '任务已暂停,等待人工介入确认叙事方向',
|
|
creator: '王策划',
|
|
createTime: '2026-03-18 14:00',
|
|
updateTime: '2026-03-20 08:30',
|
|
},
|
|
// 已完成列
|
|
{
|
|
id: '2026-0318-002',
|
|
name: '核心受众画像分析',
|
|
type: 'single',
|
|
agent: 'AudienceAgent',
|
|
status: 'completed',
|
|
column: 'completed',
|
|
summary: '已完成目标受众识别、关切提炼和阻力分析',
|
|
creator: '赵运营',
|
|
createTime: '2026-03-18 09:00',
|
|
updateTime: '2026-03-18 16:30',
|
|
},
|
|
{
|
|
id: '2026-0319-003',
|
|
name: '五四青年节宣传策略',
|
|
type: 'scene',
|
|
scene: '宣传策略生成',
|
|
status: 'completed',
|
|
column: 'completed',
|
|
summary: '已完成宣传策略方案生成',
|
|
creator: '张策略',
|
|
createTime: '2026-03-19 10:00',
|
|
updateTime: '2026-03-19 18:00',
|
|
},
|
|
{
|
|
id: '2026-0319-004',
|
|
name: '青年品牌传播路径会商',
|
|
type: 'consultation',
|
|
participants: ['GoalAgent', 'NarrativeAgent', 'RiskAgent'],
|
|
status: 'completed',
|
|
column: 'completed',
|
|
summary: '已完成多智能体会商,形成结论与分歧报告',
|
|
creator: '王策划',
|
|
createTime: '2026-03-19 14:30',
|
|
updateTime: '2026-03-19 17:00',
|
|
},
|
|
]);
|
|
|
|
const [searchQuery, setSearchQuery] = useState('');
|
|
const [modeFilter, setModeFilter] = useState<string>('all');
|
|
const [showAnalysisModal, setShowAnalysisModal] = useState(false);
|
|
const [selectedTaskForAnalysis, setSelectedTaskForAnalysis] = useState<Task | null>(null);
|
|
|
|
// 获取任务类型配置
|
|
const getTypeConfig = (type: TaskType) => {
|
|
if (isDark) {
|
|
switch (type) {
|
|
case 'single':
|
|
return { label: '单智能体', color: 'bg-cyan-500/20 text-cyan-400', icon: Bot };
|
|
case 'scene':
|
|
return { label: '场景执行', color: 'bg-purple-500/20 text-purple-400', icon: Workflow };
|
|
case 'consultation':
|
|
return { label: '多智能体会商', color: 'bg-orange-500/20 text-orange-400', icon: Users };
|
|
case 'multi-agent':
|
|
return { label: '多智能体协同', color: 'bg-green-500/20 text-green-400', icon: Layers };
|
|
}
|
|
} else {
|
|
switch (type) {
|
|
case 'single':
|
|
return { label: '单智能体', color: 'bg-blue-100 text-blue-600', icon: Bot };
|
|
case 'scene':
|
|
return { label: '场景执行', color: 'bg-purple-100 text-purple-600', icon: Workflow };
|
|
case 'consultation':
|
|
return { label: '多智能体会商', color: 'bg-orange-100 text-orange-600', icon: Users };
|
|
case 'multi-agent':
|
|
return { label: '多智能体协同', color: 'bg-green-100 text-green-600', icon: Layers };
|
|
}
|
|
}
|
|
};
|
|
|
|
// 获取状态配置
|
|
const getStatusConfig = (status: TaskStatus, column: ColumnType) => {
|
|
if (column === 'unanalyzed') {
|
|
switch (status) {
|
|
case 'draft':
|
|
return { label: '草稿', color: isDark ? 'bg-slate-500/20 text-slate-400' : 'bg-gray-100 text-gray-600' };
|
|
case 'pending':
|
|
return { label: '待启动', color: isDark ? 'bg-slate-500/20 text-slate-400' : 'bg-gray-100 text-gray-600' };
|
|
default:
|
|
return { label: '待配置', color: isDark ? 'bg-yellow-500/20 text-yellow-400' : 'bg-yellow-100 text-yellow-600' };
|
|
}
|
|
} else if (column === 'analyzing') {
|
|
switch (status) {
|
|
case 'running':
|
|
return { label: '运行中', color: isDark ? 'bg-blue-500/20 text-blue-400' : 'bg-red-100 text-red-600' };
|
|
case 'paused':
|
|
return { label: '已暂停', color: isDark ? 'bg-yellow-500/20 text-yellow-400' : 'bg-yellow-100 text-yellow-600' };
|
|
case 'blocked':
|
|
return { label: '阻塞中', color: isDark ? 'bg-red-500/20 text-red-400' : 'bg-orange-100 text-orange-600' };
|
|
default:
|
|
return { label: '待处理', color: isDark ? 'bg-purple-500/20 text-purple-400' : 'bg-purple-100 text-purple-600' };
|
|
}
|
|
} else {
|
|
return { label: '已完成', color: isDark ? 'bg-green-500/20 text-green-400' : 'bg-green-100 text-green-600' };
|
|
}
|
|
};
|
|
|
|
// 筛选任务
|
|
const filteredTasks = tasks.filter(task => {
|
|
const matchesSearch = task.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
|
task.id.toLowerCase().includes(searchQuery.toLowerCase());
|
|
const matchesMode = modeFilter === 'all' || task.type === modeFilter;
|
|
return matchesSearch && matchesMode;
|
|
});
|
|
|
|
const unanalyzedTasks = filteredTasks.filter(t => t.column === 'unanalyzed');
|
|
const analyzingTasks = filteredTasks.filter(t => t.column === 'analyzing');
|
|
const completedTasks = filteredTasks.filter(t => t.column === 'completed');
|
|
|
|
// 统计数据
|
|
const stats = {
|
|
total: tasks.length,
|
|
unanalyzed: unanalyzedTasks.length,
|
|
analyzing: analyzingTasks.length,
|
|
completed: completedTasks.length,
|
|
};
|
|
|
|
// 处理开始分析按钮点击
|
|
const handleStartAnalysis = (task: Task) => {
|
|
setSelectedTaskForAnalysis(task);
|
|
setShowAnalysisModal(true);
|
|
};
|
|
|
|
// 处理分析模式选择
|
|
const handleSelectAnalysisMode = (mode: TaskType) => {
|
|
setShowAnalysisModal(false);
|
|
if (mode === 'single') {
|
|
onNavigate('task-single');
|
|
} else if (mode === 'scene') {
|
|
onNavigate('task-scene');
|
|
} else if (mode === 'consultation') {
|
|
onNavigate('task-consult-create');
|
|
} else if (mode === 'multi-agent') {
|
|
onNavigate('multi-agent-qa');
|
|
}
|
|
};
|
|
|
|
// 处理卡片点击
|
|
const handleTaskClick = (task: Task) => {
|
|
if (task.column === 'completed') {
|
|
if (task.type === 'consultation') {
|
|
onNavigate('task-consult-result');
|
|
} else {
|
|
onNavigate('strategy-result');
|
|
}
|
|
} else if (task.column === 'analyzing') {
|
|
if (task.type === 'scene') {
|
|
onNavigate('task-scene');
|
|
} else if (task.type === 'consultation') {
|
|
onNavigate('task-consult');
|
|
} else {
|
|
onNavigate('task-single');
|
|
}
|
|
}
|
|
};
|
|
|
|
// 渲染任务卡片
|
|
const TaskCard = ({ task }: { task: Task }) => {
|
|
const typeConfig = getTypeConfig(task.type);
|
|
const statusConfig = getStatusConfig(task.status, task.column);
|
|
const TypeIcon = typeConfig.icon;
|
|
|
|
return (
|
|
<div
|
|
className={`rounded-xl p-4 hover:shadow-md transition-all duration-200 cursor-pointer group theme-card border ${
|
|
isDark
|
|
? 'bg-slate-800/40 backdrop-blur-xl border-blue-800/30 hover:border-blue-500/50'
|
|
: 'bg-white border-red-100 hover:shadow-md shadow-red-100'
|
|
}`}
|
|
onClick={() => handleTaskClick(task)}
|
|
>
|
|
{/* 卡片头部:模式标签 + 状态标签 */}
|
|
<div className="flex items-center justify-between mb-2">
|
|
<span className={`inline-flex items-center gap-1.5 px-2 py-0.5 rounded text-xs font-medium ${typeConfig.color}`}>
|
|
<TypeIcon className="w-3 h-3" />
|
|
{typeConfig.label}
|
|
</span>
|
|
<span className={`inline-flex items-center px-2 py-0.5 rounded text-xs font-medium ${statusConfig.color}`}>
|
|
{statusConfig.label}
|
|
</span>
|
|
</div>
|
|
|
|
{/* 任务名称 */}
|
|
<h3 className={`font-semibold text-sm mb-1 line-clamp-2 group-hover:text-red-500 transition-colors ${textPrimary}`}>
|
|
{task.name}
|
|
</h3>
|
|
|
|
{/* 任务编号 */}
|
|
<p className={`text-xs mb-2 ${textMuted}`}>TASK-{task.id}</p>
|
|
|
|
{/* 任务摘要 */}
|
|
<p className={`text-xs mb-3 line-clamp-2 ${textSecondary}`}>{task.summary}</p>
|
|
|
|
{/* 补充信息区 */}
|
|
<div className="space-y-1 mb-3">
|
|
{task.type === 'single' && task.agent && (
|
|
<div className="flex items-center gap-2 text-xs">
|
|
<Bot className={`w-3 h-3 ${isDark ? 'text-cyan-400' : 'text-red-500'}`} />
|
|
<span className={textSecondary}>执行智能体:</span>
|
|
<span className={isDark ? 'text-cyan-400' : 'text-red-600'}>{task.agent}</span>
|
|
</div>
|
|
)}
|
|
{task.type === 'scene' && task.scene && (
|
|
<div className="flex items-center gap-2 text-xs">
|
|
<Workflow className={`w-3 h-3 ${isDark ? 'text-purple-400' : 'text-red-500'}`} />
|
|
<span className={textSecondary}>关联场景:</span>
|
|
<span className={isDark ? 'text-purple-400' : 'text-red-600'}>{task.scene}</span>
|
|
</div>
|
|
)}
|
|
{task.type === 'consultation' && (
|
|
<>
|
|
<div className="flex items-center gap-2 text-xs">
|
|
<Users className={`w-3 h-3 ${isDark ? 'text-orange-400' : 'text-red-500'}`} />
|
|
<span className={textSecondary}>参与智能体:</span>
|
|
<span className={isDark ? 'text-orange-400' : 'text-red-600'}>{task.participants?.length || 0}个</span>
|
|
</div>
|
|
{task.currentRound && (
|
|
<div className="flex items-center gap-2 text-xs">
|
|
<Clock className={`w-3 h-3 ${textMuted}`} />
|
|
<span className={textSecondary}>当前轮次:</span>
|
|
<span className={textPrimary}>第{task.currentRound}轮</span>
|
|
</div>
|
|
)}
|
|
</>
|
|
)}
|
|
{task.column === 'analyzing' && task.currentPhase && (
|
|
<div className="flex items-center gap-2 text-xs">
|
|
<Target className={`w-3 h-3 ${textMuted}`} />
|
|
<span className={textSecondary}>当前阶段:</span>
|
|
<span className={textPrimary}>{task.currentPhase}</span>
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{/* 时间信息 */}
|
|
<div className={`flex items-center justify-between text-xs pt-3 border-t ${
|
|
isDark ? 'border-blue-800/30 text-slate-500' : 'border-red-100 text-gray-400'
|
|
}`}>
|
|
<div className="flex items-center gap-1.5">
|
|
<User className="w-3 h-3" />
|
|
<span>{task.creator}</span>
|
|
</div>
|
|
<span>{task.column === 'completed' ? `完成于 ${task.updateTime}` : `更新于 ${task.updateTime}`}</span>
|
|
</div>
|
|
|
|
{/* 操作按钮区 */}
|
|
<div className={`flex items-center gap-2 mt-3 pt-3 border-t ${
|
|
isDark ? 'border-blue-800/30' : 'border-red-100'
|
|
}`}>
|
|
{task.column === 'unanalyzed' && (
|
|
<>
|
|
<button
|
|
onClick={(e) => { e.stopPropagation(); handleStartAnalysis(task); }}
|
|
className={`flex-1 flex items-center justify-center gap-1.5 px-3 py-1.5 text-white rounded-lg text-xs font-medium transition-colors ${
|
|
isDark
|
|
? 'bg-blue-600 hover:bg-blue-500'
|
|
: 'bg-red-600 hover:bg-red-500 shadow-md'
|
|
}`}
|
|
>
|
|
<Play className="w-3 h-3" />
|
|
开始分析
|
|
</button>
|
|
<button
|
|
onClick={(e) => { e.stopPropagation(); onNavigate('task-create'); }}
|
|
className={`p-1.5 rounded-lg transition-colors ${
|
|
isDark ? 'hover:bg-slate-700/50' : 'hover:bg-red-50'
|
|
}`}
|
|
title="编辑"
|
|
>
|
|
<Edit className={`w-4 h-4 ${isDark ? 'text-slate-400' : 'text-red-400'}`} />
|
|
</button>
|
|
</>
|
|
)}
|
|
{task.column === 'analyzing' && (
|
|
<>
|
|
<button
|
|
onClick={(e) => { e.stopPropagation(); handleTaskClick(task); }}
|
|
className={`flex-1 flex items-center justify-center gap-1.5 px-3 py-1.5 text-white rounded-lg text-xs font-medium transition-colors ${
|
|
isDark
|
|
? 'bg-blue-600 hover:bg-blue-500'
|
|
: 'bg-red-600 hover:bg-red-500 shadow-md'
|
|
}`}
|
|
>
|
|
<Play className="w-3 h-3" />
|
|
继续处理
|
|
</button>
|
|
<button
|
|
onClick={(e) => { e.stopPropagation(); handleTaskClick(task); }}
|
|
className={`px-2 py-1.5 rounded-lg text-xs transition-colors ${
|
|
isDark
|
|
? 'hover:bg-slate-700/50 border border-blue-800/30 text-slate-300'
|
|
: 'hover:bg-red-50 border border-red-200 text-red-600'
|
|
}`}
|
|
>
|
|
查看进展
|
|
</button>
|
|
</>
|
|
)}
|
|
{task.column === 'completed' && (
|
|
<>
|
|
<button
|
|
onClick={(e) => { e.stopPropagation(); handleTaskClick(task); }}
|
|
className={`flex-1 flex items-center justify-center gap-1.5 px-3 py-1.5 text-white rounded-lg text-xs font-medium transition-colors ${
|
|
isDark
|
|
? 'bg-green-600 hover:bg-green-500'
|
|
: 'bg-green-600 hover:bg-green-500 shadow-md'
|
|
}`}
|
|
>
|
|
<Eye className="w-3 h-3" />
|
|
查看结果
|
|
</button>
|
|
<button className={`px-2 py-1.5 rounded-lg text-xs transition-colors ${
|
|
isDark
|
|
? 'hover:bg-slate-700/50 border border-blue-800/30 text-slate-300'
|
|
: 'hover:bg-red-50 border border-red-200 text-red-600'
|
|
}`}>
|
|
<Download className="w-4 h-4" />
|
|
</button>
|
|
</>
|
|
)}
|
|
<button className={`p-1.5 rounded-lg transition-colors ${
|
|
isDark ? 'hover:bg-slate-700/50' : 'hover:bg-red-50'
|
|
}`} title="更多">
|
|
<MoreHorizontal className={`w-4 h-4 ${isDark ? 'text-slate-400' : 'text-red-400'}`} />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
// 渲染看板列
|
|
const KanbanColumn = ({ title, count, color, tasks }: { title: string; count: number; color: string; tasks: Task[] }) => (
|
|
<div className="flex flex-col min-h-0 flex-1">
|
|
<div className="flex items-center justify-between mb-4">
|
|
<div className="flex items-center gap-2">
|
|
<div className={`w-2 h-2 rounded-full ${color}`} />
|
|
<h2 className={`font-semibold text-sm ${textPrimary}`}>{title}</h2>
|
|
<span className={`px-2 py-0.5 rounded-full text-xs ${
|
|
isDark ? 'bg-slate-700/50 text-slate-400' : 'bg-red-50 text-red-500'
|
|
}`}>{count}</span>
|
|
</div>
|
|
<button className={`p-1 rounded transition-colors ${
|
|
isDark ? 'hover:bg-slate-700/50' : 'hover:bg-red-50'
|
|
}`}>
|
|
<ChevronRight className={`w-4 h-4 ${textMuted}`} />
|
|
</button>
|
|
</div>
|
|
<div className="flex-1 overflow-y-auto space-y-3 pr-1 scrollbar-thin">
|
|
{tasks.length === 0 ? (
|
|
<div className={`flex flex-col items-center justify-center py-8 ${textMuted}`}>
|
|
<FileText className="w-8 h-8 mb-2 opacity-50" />
|
|
<p className="text-sm">暂无任务</p>
|
|
</div>
|
|
) : (
|
|
tasks.map(task => <TaskCard key={task.id} task={task} />)
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
|
|
return (
|
|
<div className="h-full flex flex-col">
|
|
{/* 顶部工具栏 */}
|
|
<div className={`rounded-xl p-4 flex-shrink-0 mb-4 ${cardBg} border ${cardBorder}`}>
|
|
<div className="flex items-center justify-between mb-4">
|
|
<div>
|
|
<div className="flex items-center gap-2 mb-1">
|
|
<span className={`px-2 py-0.5 rounded text-xs ${isDark ? 'bg-blue-500/20 text-blue-400' : 'bg-red-100 text-red-600'}`}>
|
|
{category}
|
|
</span>
|
|
<span className={`text-xs ${textMuted}`}>/</span>
|
|
<span className={`px-2 py-0.5 rounded text-xs ${isDark ? 'bg-cyan-500/20 text-cyan-400' : 'bg-red-100 text-red-600'}`}>
|
|
{subCategory}
|
|
</span>
|
|
</div>
|
|
<h1 className={`text-xl font-bold ${textPrimary}`}>任务中心</h1>
|
|
</div>
|
|
<button
|
|
onClick={() => onNavigate('task-create')}
|
|
className={`flex items-center gap-2 px-4 py-2 text-white rounded-lg text-sm font-medium transition-colors ${
|
|
isDark
|
|
? 'bg-blue-600 hover:bg-blue-500'
|
|
: 'bg-red-600 hover:bg-red-500 shadow-md'
|
|
}`}
|
|
>
|
|
<Plus className="w-4 h-4" />
|
|
新建任务
|
|
</button>
|
|
</div>
|
|
|
|
{/* 搜索和筛选 */}
|
|
<div className="flex items-center gap-4">
|
|
<div className="relative flex-1 max-w-md">
|
|
<Search className={`absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 ${textMuted}`} />
|
|
<input
|
|
type="text"
|
|
placeholder="搜索任务名称 / 任务编号 / 关键词"
|
|
value={searchQuery}
|
|
onChange={(e) => setSearchQuery(e.target.value)}
|
|
className={`w-full pl-10 pr-4 py-2 border rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-red-500/20 transition-colors ${inputBg} ${cardBorder} ${textPrimary} placeholder:${textMuted}`}
|
|
/>
|
|
</div>
|
|
<select
|
|
value={modeFilter}
|
|
onChange={(e) => setModeFilter(e.target.value)}
|
|
className={`px-4 py-2 border rounded-lg text-sm focus:outline-none cursor-pointer ${inputBg} ${cardBorder} ${textSecondary}`}
|
|
>
|
|
<option value="all">全部模式</option>
|
|
<option value="single">单智能体</option>
|
|
<option value="multi-agent">多智能体协同</option>
|
|
<option value="consultation">多智能体会商</option>
|
|
<option value="scene">场景执行</option>
|
|
</select>
|
|
<button className={`flex items-center gap-2 px-4 py-2 border rounded-lg text-sm transition-colors ${inputBg} ${cardBorder} ${textSecondary}`}>
|
|
<Clock className="w-4 h-4" />
|
|
时间范围
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
{/* 统计概览栏 */}
|
|
<div className="grid grid-cols-4 gap-4 mb-4 flex-shrink-0">
|
|
<button
|
|
onClick={() => { setModeFilter('all'); }}
|
|
className={`p-4 rounded-xl border transition-all ${cardBg} ${cardBorder} hover:border-red-400`}
|
|
>
|
|
<p className={`text-2xl font-bold ${textPrimary}`}>{stats.total}</p>
|
|
<p className={`text-sm ${textSecondary}`}>全部任务</p>
|
|
</button>
|
|
<button
|
|
className={`p-4 rounded-xl border transition-all ${cardBg} ${cardBorder} hover:border-red-400`}
|
|
>
|
|
<p className={`text-2xl font-bold ${textPrimary}`}>{stats.unanalyzed}</p>
|
|
<p className={`text-sm ${textSecondary}`}>未分析</p>
|
|
</button>
|
|
<button
|
|
className={`p-4 rounded-xl border transition-all ${cardBg} ${cardBorder} hover:border-red-400`}
|
|
>
|
|
<p className={`text-2xl font-bold ${isDark ? 'text-blue-400' : 'text-red-600'}`}>{stats.analyzing}</p>
|
|
<p className={`text-sm ${textSecondary}`}>分析中</p>
|
|
</button>
|
|
<button
|
|
className={`p-4 rounded-xl border transition-all ${cardBg} ${cardBorder} hover:border-red-400`}
|
|
>
|
|
<p className={`text-2xl font-bold ${isDark ? 'text-green-400' : 'text-green-600'}`}>{stats.completed}</p>
|
|
<p className={`text-sm ${textSecondary}`}>已完成</p>
|
|
</button>
|
|
</div>
|
|
|
|
{/* 看板区 */}
|
|
<div className="flex-1 grid grid-cols-3 gap-4 min-h-0 overflow-hidden">
|
|
<KanbanColumn title="未分析" count={unanalyzedTasks.length} color={isDark ? 'bg-yellow-400' : 'bg-yellow-400'} tasks={unanalyzedTasks} />
|
|
<KanbanColumn title="分析中" count={analyzingTasks.length} color={isDark ? 'bg-blue-400' : 'bg-red-400'} tasks={analyzingTasks} />
|
|
<KanbanColumn title="已完成" count={completedTasks.length} color={isDark ? 'bg-green-400' : 'bg-green-400'} tasks={completedTasks} />
|
|
</div>
|
|
|
|
{/* 选择分析模式弹窗 */}
|
|
{showAnalysisModal && selectedTaskForAnalysis && (
|
|
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50" onClick={() => setShowAnalysisModal(false)}>
|
|
<div
|
|
className={`w-full max-w-lg rounded-2xl p-6 ${cardBg} border ${cardBorder} shadow-xl`}
|
|
onClick={(e) => e.stopPropagation()}
|
|
>
|
|
<div className="flex items-center justify-between mb-6">
|
|
<div>
|
|
<h2 className={`text-xl font-bold ${textPrimary}`}>选择分析模式</h2>
|
|
<p className={`text-sm ${textMuted} mt-1`}>为任务「{selectedTaskForAnalysis.name}」选择分析方式</p>
|
|
</div>
|
|
<button
|
|
onClick={() => setShowAnalysisModal(false)}
|
|
className={`p-2 rounded-lg hover:bg-slate-700/50 ${textSecondary}`}
|
|
>
|
|
<X className="w-5 h-5" />
|
|
</button>
|
|
</div>
|
|
|
|
<div className="space-y-3">
|
|
{/* 单智能体分析 */}
|
|
<button
|
|
onClick={() => handleSelectAnalysisMode('single')}
|
|
className={`w-full p-4 rounded-xl border transition-all duration-200 text-left hover:shadow-md ${
|
|
isDark
|
|
? 'bg-slate-700/50 border-blue-800/30 hover:border-cyan-500/50'
|
|
: 'bg-white border-red-100 hover:border-red-300 hover:shadow-md'
|
|
}`}
|
|
>
|
|
<div className="flex items-center gap-4">
|
|
<div className={`w-12 h-12 rounded-xl flex items-center justify-center ${
|
|
isDark ? 'bg-cyan-500/20' : 'bg-red-100'
|
|
}`}>
|
|
<Bot className={`w-6 h-6 ${isDark ? 'text-cyan-400' : 'text-red-500'}`} />
|
|
</div>
|
|
<div className="flex-1">
|
|
<h3 className={`font-semibold ${textPrimary}`}>单智能体分析</h3>
|
|
<p className={`text-sm ${textSecondary}`}>选择一个AI智能体完成单一维度的专项分析</p>
|
|
</div>
|
|
<ArrowRight className={`w-5 h-5 ${textMuted}`} />
|
|
</div>
|
|
</button>
|
|
|
|
{/* 多智能体协同分析 */}
|
|
<button
|
|
onClick={() => handleSelectAnalysisMode('multi-agent')}
|
|
className={`w-full p-4 rounded-xl border transition-all duration-200 text-left hover:shadow-md ${
|
|
isDark
|
|
? 'bg-slate-700/50 border-blue-800/30 hover:border-green-500/50'
|
|
: 'bg-white border-red-100 hover:border-red-300 hover:shadow-md'
|
|
}`}
|
|
>
|
|
<div className="flex items-center gap-4">
|
|
<div className={`w-12 h-12 rounded-xl flex items-center justify-center ${
|
|
isDark ? 'bg-green-500/20' : 'bg-green-100'
|
|
}`}>
|
|
<Layers className={`w-6 h-6 ${isDark ? 'text-green-400' : 'text-green-600'}`} />
|
|
</div>
|
|
<div className="flex-1">
|
|
<h3 className={`font-semibold ${textPrimary}`}>多智能体协同分析</h3>
|
|
<p className={`text-sm ${textSecondary}`}>多个AI智能体并行分析,输出各自的判断和结论</p>
|
|
</div>
|
|
<ArrowRight className={`w-5 h-5 ${textMuted}`} />
|
|
</div>
|
|
</button>
|
|
|
|
{/* 多智能体会商 */}
|
|
<button
|
|
onClick={() => handleSelectAnalysisMode('consultation')}
|
|
className={`w-full p-4 rounded-xl border transition-all duration-200 text-left hover:shadow-md ${
|
|
isDark
|
|
? 'bg-slate-700/50 border-blue-800/30 hover:border-orange-500/50'
|
|
: 'bg-white border-red-100 hover:border-red-300 hover:shadow-md'
|
|
}`}
|
|
>
|
|
<div className="flex items-center gap-4">
|
|
<div className={`w-12 h-12 rounded-xl flex items-center justify-center ${
|
|
isDark ? 'bg-orange-500/20' : 'bg-red-100'
|
|
}`}>
|
|
<Users className={`w-6 h-6 ${isDark ? 'text-orange-400' : 'text-red-500'}`} />
|
|
</div>
|
|
<div className="flex-1">
|
|
<h3 className={`font-semibold ${textPrimary}`}>多智能体会商</h3>
|
|
<p className={`text-sm ${textSecondary}`}>多个AI智能体从不同视角开展讨论并形成共识</p>
|
|
</div>
|
|
<ArrowRight className={`w-5 h-5 ${textMuted}`} />
|
|
</div>
|
|
</button>
|
|
|
|
{/* 场景执行 */}
|
|
<button
|
|
onClick={() => handleSelectAnalysisMode('scene')}
|
|
className={`w-full p-4 rounded-xl border transition-all duration-200 text-left hover:shadow-md ${
|
|
isDark
|
|
? 'bg-slate-700/50 border-blue-800/30 hover:border-purple-500/50'
|
|
: 'bg-white border-red-100 hover:border-red-300 hover:shadow-md'
|
|
}`}
|
|
>
|
|
<div className="flex items-center gap-4">
|
|
<div className={`w-12 h-12 rounded-xl flex items-center justify-center ${
|
|
isDark ? 'bg-purple-500/20' : 'bg-red-100'
|
|
}`}>
|
|
<Workflow className={`w-6 h-6 ${isDark ? 'text-purple-400' : 'text-red-500'}`} />
|
|
</div>
|
|
<div className="flex-1">
|
|
<h3 className={`font-semibold ${textPrimary}`}>场景执行</h3>
|
|
<p className={`text-sm ${textSecondary}`}>按照预设场景模板自动执行多阶段策略分析</p>
|
|
</div>
|
|
<ArrowRight className={`w-5 h-5 ${textMuted}`} />
|
|
</div>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default TaskListPage;
|