573 lines
26 KiB
TypeScript
573 lines
26 KiB
TypeScript
import React, { useState } from 'react';
|
|
import {
|
|
ArrowLeft,
|
|
Bot,
|
|
Users,
|
|
Settings,
|
|
FileText,
|
|
Upload,
|
|
Play,
|
|
Save,
|
|
Search,
|
|
CheckCircle,
|
|
MessageSquare,
|
|
Lightbulb,
|
|
Target,
|
|
AlertCircle,
|
|
Sparkles,
|
|
} from 'lucide-react';
|
|
import { useTheme } from '@/contexts/ThemeContext';
|
|
import { PageType } from '@/components/Sidebar';
|
|
|
|
interface TaskConsultCreateProps {
|
|
onNavigate: (page: PageType) => void;
|
|
}
|
|
|
|
// 可选智能体列表
|
|
const availableAgents = [
|
|
{
|
|
id: 'goal',
|
|
name: 'GoalAgent',
|
|
role: '目标分析专家',
|
|
description: '分析业务目标,提取核心KPI和成功标准',
|
|
color: 'blue',
|
|
tags: ['目标分解', 'KPI提取'],
|
|
recommended: true,
|
|
},
|
|
{
|
|
id: 'audience',
|
|
name: 'AudienceAgent',
|
|
role: '受众分析专家',
|
|
description: '定义目标受众画像,分析用户特征和需求',
|
|
color: 'cyan',
|
|
tags: ['用户画像', '行为分析'],
|
|
recommended: true,
|
|
},
|
|
{
|
|
id: 'behavior',
|
|
name: 'BehaviorAgent',
|
|
role: '行为设计专家',
|
|
description: '设计用户行为路径和转化漏斗',
|
|
color: 'green',
|
|
tags: ['行为设计', '转化路径'],
|
|
recommended: true,
|
|
},
|
|
{
|
|
id: 'driver',
|
|
name: 'DriverAgent',
|
|
role: '驱动因素专家',
|
|
description: '分析影响用户决策的核心驱动因素',
|
|
color: 'yellow',
|
|
tags: ['驱动分析', '动机挖掘'],
|
|
recommended: false,
|
|
},
|
|
{
|
|
id: 'narrative',
|
|
name: 'NarrativeAgent',
|
|
role: '叙事策略专家',
|
|
description: '设计品牌叙事框架和内容策略',
|
|
color: 'purple',
|
|
tags: ['故事设计', '内容策略'],
|
|
recommended: true,
|
|
},
|
|
{
|
|
id: 'risk',
|
|
name: 'RiskAgent',
|
|
role: '风险评估专家',
|
|
description: '识别项目风险,制定应对策略',
|
|
color: 'red',
|
|
tags: ['风险识别', '应对策略'],
|
|
recommended: true,
|
|
},
|
|
];
|
|
|
|
const TaskConsultCreate: React.FC<TaskConsultCreateProps> = ({ 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-200';
|
|
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-500';
|
|
const btnSecondary = isDark ? 'bg-slate-700/50 hover:bg-slate-600/50 border-blue-800/30 text-slate-300' : 'bg-gray-100 hover:bg-gray-200 border-gray-300 text-gray-700';
|
|
const btnPrimary = isDark ? 'bg-blue-600 hover:bg-blue-500' : 'bg-red-600 hover:bg-red-500';
|
|
const inputBg = isDark ? 'bg-slate-900/50' : 'bg-gray-50';
|
|
const inputBorder = isDark ? 'border-blue-800/30' : 'border-gray-300';
|
|
|
|
const [taskName, setTaskName] = useState('');
|
|
const [taskTheme, setTaskTheme] = useState('');
|
|
const [taskDescription, setTaskDescription] = useState('');
|
|
const [selectedAgents, setSelectedAgents] = useState<string[]>(['goal', 'audience', 'narrative', 'risk']);
|
|
const [consultMode, setConsultMode] = useState<'parallel' | 'cross' | 'human'>('parallel');
|
|
const [maxRounds, setMaxRounds] = useState(3);
|
|
const [allowAgentQuestion, setAllowAgentQuestion] = useState(true);
|
|
const [allowHumanIntervene, setAllowHumanIntervene] = useState(true);
|
|
const [autoSummary, setAutoSummary] = useState(true);
|
|
const [allowConvertToScene, setAllowConvertToScene] = useState(true);
|
|
const [searchQuery, setSearchQuery] = useState('');
|
|
|
|
const toggleAgent = (agentId: string) => {
|
|
if (selectedAgents.includes(agentId)) {
|
|
if (selectedAgents.length > 2) {
|
|
setSelectedAgents(selectedAgents.filter((id) => id !== agentId));
|
|
}
|
|
} else {
|
|
if (selectedAgents.length < 8) {
|
|
setSelectedAgents([...selectedAgents, agentId]);
|
|
}
|
|
}
|
|
};
|
|
|
|
const selectRecommended = () => {
|
|
const recommendedIds = availableAgents.filter((a) => a.recommended).map((a) => a.id);
|
|
setSelectedAgents(recommendedIds);
|
|
};
|
|
|
|
const handleStartConsult = () => {
|
|
if (taskName && selectedAgents.length >= 2) {
|
|
onNavigate('task-consult');
|
|
}
|
|
};
|
|
|
|
const filteredAgents = availableAgents.filter(
|
|
(agent) =>
|
|
agent.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
|
agent.role.toLowerCase().includes(searchQuery.toLowerCase())
|
|
);
|
|
|
|
const getColorClasses = (color: string) => {
|
|
const colors: Record<string, { bg: string; border: string; text: string; ring: string }> = {
|
|
blue: { bg: 'bg-blue-500/20', border: 'border-blue-500/50', text: 'text-blue-400', ring: 'ring-blue-500/50' },
|
|
cyan: { bg: 'bg-cyan-500/20', border: 'border-cyan-500/50', text: 'text-cyan-400', ring: 'ring-cyan-500/50' },
|
|
green: { bg: 'bg-green-500/20', border: 'border-green-500/50', text: 'text-green-400', ring: 'ring-green-500/50' },
|
|
yellow: { bg: 'bg-yellow-500/20', border: 'border-yellow-500/50', text: 'text-yellow-400', ring: 'ring-yellow-500/50' },
|
|
purple: { bg: 'bg-purple-500/20', border: 'border-purple-500/50', text: 'text-purple-400', ring: 'ring-purple-500/50' },
|
|
red: { bg: 'bg-red-500/20', border: 'border-red-500/50', text: 'text-red-400', ring: 'ring-red-500/50' },
|
|
};
|
|
return colors[color] || colors.blue;
|
|
};
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
{/* 顶部操作栏 */}
|
|
<div className={`${cardBg} backdrop-blur-xl ${cardBorder} rounded-xl p-4`}>
|
|
<div className="flex items-center justify-between">
|
|
<div className="flex items-center gap-4">
|
|
<button
|
|
onClick={() => onNavigate('task-list')}
|
|
className={`flex items-center gap-2 px-3 py-2 ${btnSecondary} rounded-lg text-sm transition-colors`}
|
|
>
|
|
<ArrowLeft className="w-4 h-4" />
|
|
返回
|
|
</button>
|
|
<div className={`h-8 w-px ${isDark ? 'bg-blue-800/30' : 'bg-gray-200'}`} />
|
|
<div>
|
|
<h1 className={`${textPrimary} font-bold text-lg`}>新建多智能体会商任务</h1>
|
|
<p className={`${textSecondary} text-sm`}>多视角分析 + 人机共判 + 会商整合</p>
|
|
</div>
|
|
</div>
|
|
<div className="flex items-center gap-3">
|
|
<span className={`px-3 py-1.5 ${isDark ? 'bg-orange-500/20 text-orange-400' : 'bg-orange-100 text-orange-600'} rounded-full text-sm font-medium flex items-center gap-1.5`}>
|
|
<Users className="w-4 h-4" />
|
|
会商研判模式
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-12 gap-6">
|
|
{/* 左侧:基础信息和智能体选择 */}
|
|
<div className="col-span-8 space-y-6">
|
|
{/* 基础信息区 */}
|
|
<div className={`${cardBg} backdrop-blur-xl ${cardBorder} rounded-xl p-5`}>
|
|
<h3 className={`${textPrimary} font-semibold text-sm mb-4 flex items-center gap-2`}>
|
|
<FileText className="w-4 h-4 text-blue-400" />
|
|
基础信息
|
|
</h3>
|
|
<div className="space-y-4">
|
|
<div className="grid grid-cols-2 gap-4">
|
|
<div>
|
|
<label className={`block ${textSecondary} text-sm mb-2`}>任务名称</label>
|
|
<input
|
|
type="text"
|
|
value={taskName}
|
|
onChange={(e) => setTaskName(e.target.value)}
|
|
placeholder="例如:五四青年节宣传策略会商"
|
|
className={`w-full px-4 py-2.5 ${inputBg} ${inputBorder} rounded-lg ${textPrimary} text-sm ${textMuted} focus:outline-none focus:border-blue-500/50 transition-colors`}
|
|
/>
|
|
</div>
|
|
<div>
|
|
<label className={`block ${textSecondary} text-sm mb-2`}>会商主题</label>
|
|
<input
|
|
type="text"
|
|
value={taskTheme}
|
|
onChange={(e) => setTaskTheme(e.target.value)}
|
|
placeholder="例如:宣传策略前期研判"
|
|
className={`w-full px-4 py-2.5 ${inputBg} ${inputBorder} rounded-lg ${textPrimary} text-sm ${textMuted} focus:outline-none focus:border-blue-500/50 transition-colors`}
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<label className={`block ${textSecondary} text-sm mb-2`}>任务描述</label>
|
|
<textarea
|
|
value={taskDescription}
|
|
onChange={(e) => setTaskDescription(e.target.value)}
|
|
placeholder="详细描述本次会商要解决的问题和目标..."
|
|
rows={3}
|
|
className={`w-full px-4 py-2.5 ${inputBg} ${inputBorder} rounded-lg ${textPrimary} text-sm ${textMuted} focus:outline-none focus:border-blue-500/50 transition-colors resize-none`}
|
|
/>
|
|
</div>
|
|
<div>
|
|
<label className={`block ${textSecondary} text-sm mb-2`}>背景材料上传</label>
|
|
<div className={`border-2 border-dashed ${inputBorder} rounded-lg p-6 text-center hover:border-blue-500/50 transition-colors cursor-pointer`}>
|
|
<Upload className={`w-8 h-8 ${textMuted} mx-auto mb-2`} />
|
|
<p className={`${textSecondary} text-sm`}>点击或拖拽上传文件</p>
|
|
<p className={`${textMuted} text-xs mt-1`}>支持 PDF、Word、图片等格式</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* 智能体选择区 */}
|
|
<div className={`${cardBg} backdrop-blur-xl ${cardBorder} rounded-xl p-5`}>
|
|
<div className="flex items-center justify-between mb-4">
|
|
<h3 className={`${textPrimary} font-semibold text-sm flex items-center gap-2`}>
|
|
<Bot className="w-4 h-4 text-purple-400" />
|
|
选择参与智能体
|
|
<span className={`${textMuted} font-normal text-xs ml-2`}>
|
|
(已选 {selectedAgents.length} 个,建议 3-6 个)
|
|
</span>
|
|
</h3>
|
|
<div className="flex items-center gap-2">
|
|
<button
|
|
onClick={selectRecommended}
|
|
className={`px-3 py-1.5 bg-purple-500/20 hover:bg-purple-500/30 border border-purple-500/30 text-purple-400 rounded-lg text-xs transition-colors`}
|
|
>
|
|
一键选择推荐组合
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
{/* 搜索和筛选 */}
|
|
<div className="relative mb-4">
|
|
<Search className={`absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 ${textMuted}`} />
|
|
<input
|
|
type="text"
|
|
value={searchQuery}
|
|
onChange={(e) => setSearchQuery(e.target.value)}
|
|
placeholder="搜索智能体..."
|
|
className={`w-full pl-10 pr-4 py-2 ${inputBg} ${inputBorder} rounded-lg ${textPrimary} text-sm ${textMuted} focus:outline-none focus:border-blue-500/50 transition-colors`}
|
|
/>
|
|
</div>
|
|
|
|
{/* 智能体卡片列表 */}
|
|
<div className="grid grid-cols-2 gap-3 max-h-[320px] overflow-y-auto pr-2">
|
|
{filteredAgents.map((agent) => {
|
|
const isSelected = selectedAgents.includes(agent.id);
|
|
const colors = getColorClasses(agent.color);
|
|
return (
|
|
<button
|
|
key={agent.id}
|
|
onClick={() => toggleAgent(agent.id)}
|
|
className={`p-4 rounded-xl border transition-all text-left ${
|
|
isSelected
|
|
? `${colors.bg} ${colors.border} ring-1 ${colors.ring}`
|
|
: `${inputBg} ${inputBorder} hover:border-blue-500/30`
|
|
}`}
|
|
>
|
|
<div className="flex items-start gap-3">
|
|
<div className={`w-10 h-10 rounded-lg ${colors.bg} flex items-center justify-center flex-shrink-0`}>
|
|
<Bot className={`w-5 h-5 ${colors.text}`} />
|
|
</div>
|
|
<div className="flex-1 min-w-0">
|
|
<div className="flex items-center gap-2">
|
|
<p className={`text-sm font-medium ${isSelected ? colors.text : textPrimary}`}>
|
|
{agent.name}
|
|
</p>
|
|
{agent.recommended && (
|
|
<span className={`px-1.5 py-0.5 ${isDark ? 'bg-green-500/20 text-green-400' : 'bg-green-100 text-green-600'} rounded text-xs`}>
|
|
推荐
|
|
</span>
|
|
)}
|
|
</div>
|
|
<p className={`${textSecondary} text-xs mt-0.5`}>{agent.role}</p>
|
|
<p className={`${textMuted} text-xs mt-1 line-clamp-2`}>{agent.description}</p>
|
|
<div className="flex flex-wrap gap-1 mt-2">
|
|
{agent.tags.map((tag) => (
|
|
<span
|
|
key={tag}
|
|
className={`px-1.5 py-0.5 ${isSelected ? colors.bg : isDark ? 'bg-slate-700/50' : 'bg-gray-100'} ${
|
|
isSelected ? colors.text : textSecondary
|
|
} rounded text-xs`}
|
|
>
|
|
{tag}
|
|
</span>
|
|
))}
|
|
</div>
|
|
</div>
|
|
<div
|
|
className={`w-5 h-5 rounded border flex items-center justify-center flex-shrink-0 ${
|
|
isSelected ? `${colors.bg} ${colors.border}` : isDark ? 'border-slate-600' : 'border-gray-300'
|
|
}`}
|
|
>
|
|
{isSelected && <CheckCircle className={`w-3.5 h-3.5 ${colors.text}`} />}
|
|
</div>
|
|
</div>
|
|
</button>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* 右侧:会商规则设置和预览 */}
|
|
<div className="col-span-4 space-y-6">
|
|
{/* 会商规则设置 */}
|
|
<div className={`${cardBg} backdrop-blur-xl ${cardBorder} rounded-xl p-5`}>
|
|
<h3 className={`${textPrimary} font-semibold text-sm mb-4 flex items-center gap-2`}>
|
|
<Settings className="w-4 h-4 text-green-400" />
|
|
会商规则设置
|
|
</h3>
|
|
<div className="space-y-4">
|
|
{/* 会商模式 */}
|
|
<div>
|
|
<label className={`block ${textSecondary} text-sm mb-2`}>会商模式</label>
|
|
<div className="space-y-2">
|
|
{[
|
|
{
|
|
id: 'parallel',
|
|
label: '并行独立分析',
|
|
desc: '首轮各智能体独立发言',
|
|
icon: MessageSquare,
|
|
},
|
|
{
|
|
id: 'cross',
|
|
label: '受控交叉讨论',
|
|
desc: '主持人指定智能体互相回应',
|
|
icon: Users,
|
|
},
|
|
{
|
|
id: 'human',
|
|
label: '人机共判模式',
|
|
desc: '人类主导,全程可控',
|
|
icon: Sparkles,
|
|
},
|
|
].map((mode) => (
|
|
<button
|
|
key={mode.id}
|
|
onClick={() => setConsultMode(mode.id as typeof consultMode)}
|
|
className={`w-full p-3 rounded-lg border transition-all text-left ${
|
|
consultMode === mode.id
|
|
? 'bg-green-500/20 border-green-500/50'
|
|
: `${inputBg} ${inputBorder} hover:border-blue-500/30`
|
|
}`}
|
|
>
|
|
<div className="flex items-center gap-3">
|
|
<mode.icon
|
|
className={`w-5 h-5 ${
|
|
consultMode === mode.id ? 'text-green-400' : textSecondary
|
|
}`}
|
|
/>
|
|
<div>
|
|
<p
|
|
className={`text-sm font-medium ${
|
|
consultMode === mode.id ? 'text-green-400' : textPrimary
|
|
}`}
|
|
>
|
|
{mode.label}
|
|
</p>
|
|
<p className={`${textMuted} text-xs`}>{mode.desc}</p>
|
|
</div>
|
|
</div>
|
|
</button>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
{/* 最大轮数 */}
|
|
<div>
|
|
<label className={`block ${textSecondary} text-sm mb-2`}>
|
|
最大讨论轮数 <span className={textMuted}>(1-10)</span>
|
|
</label>
|
|
<input
|
|
type="number"
|
|
min={1}
|
|
max={10}
|
|
value={maxRounds}
|
|
onChange={(e) => setMaxRounds(Math.min(10, Math.max(1, parseInt(e.target.value) || 1)))}
|
|
className={`w-full px-4 py-2.5 ${inputBg} ${inputBorder} rounded-lg ${textPrimary} text-sm focus:outline-none focus:border-blue-500/50 transition-colors`}
|
|
/>
|
|
</div>
|
|
|
|
{/* 开关设置 */}
|
|
<div className="space-y-3 pt-2">
|
|
<label className="flex items-center justify-between cursor-pointer">
|
|
<div>
|
|
<p className={`${textPrimary} text-sm`}>允许智能体互相提问</p>
|
|
<p className={`${textMuted} text-xs`}>智能体可主动向其他智能体发起讨论</p>
|
|
</div>
|
|
<div
|
|
onClick={() => setAllowAgentQuestion(!allowAgentQuestion)}
|
|
className={`w-11 h-6 rounded-full transition-colors relative ${
|
|
allowAgentQuestion ? 'bg-green-500' : isDark ? 'bg-slate-600' : 'bg-gray-400'
|
|
}`}
|
|
>
|
|
<div
|
|
className={`w-5 h-5 bg-white rounded-full absolute top-0.5 transition-transform ${
|
|
allowAgentQuestion ? 'translate-x-5.5' : 'translate-x-0.5'
|
|
}`}
|
|
/>
|
|
</div>
|
|
</label>
|
|
|
|
<label className="flex items-center justify-between cursor-pointer">
|
|
<div>
|
|
<p className={`${textPrimary} text-sm`}>允许人工插话</p>
|
|
<p className={`${textMuted} text-xs`}>用户可随时打断并发表意见</p>
|
|
</div>
|
|
<div
|
|
onClick={() => setAllowHumanIntervene(!allowHumanIntervene)}
|
|
className={`w-11 h-6 rounded-full transition-colors relative ${
|
|
allowHumanIntervene ? 'bg-green-500' : isDark ? 'bg-slate-600' : 'bg-gray-400'
|
|
}`}
|
|
>
|
|
<div
|
|
className={`w-5 h-5 bg-white rounded-full absolute top-0.5 transition-transform ${
|
|
allowHumanIntervene ? 'translate-x-5.5' : 'translate-x-0.5'
|
|
}`}
|
|
/>
|
|
</div>
|
|
</label>
|
|
|
|
<label className="flex items-center justify-between cursor-pointer">
|
|
<div>
|
|
<p className={`${textPrimary} text-sm`}>自动生成摘要</p>
|
|
<p className={`${textMuted} text-xs`}>每轮结束后自动提炼观点</p>
|
|
</div>
|
|
<div
|
|
onClick={() => setAutoSummary(!autoSummary)}
|
|
className={`w-11 h-6 rounded-full transition-colors relative ${
|
|
autoSummary ? 'bg-green-500' : isDark ? 'bg-slate-600' : 'bg-gray-400'
|
|
}`}
|
|
>
|
|
<div
|
|
className={`w-5 h-5 bg-white rounded-full absolute top-0.5 transition-transform ${
|
|
autoSummary ? 'translate-x-5.5' : 'translate-x-0.5'
|
|
}`}
|
|
/>
|
|
</div>
|
|
</label>
|
|
|
|
<label className="flex items-center justify-between cursor-pointer">
|
|
<div>
|
|
<p className={`${textPrimary} text-sm`}>支持转为场景任务</p>
|
|
<p className={`${textMuted} text-xs`}>会商结束后可转入场景执行</p>
|
|
</div>
|
|
<div
|
|
onClick={() => setAllowConvertToScene(!allowConvertToScene)}
|
|
className={`w-11 h-6 rounded-full transition-colors relative ${
|
|
allowConvertToScene ? 'bg-green-500' : isDark ? 'bg-slate-600' : 'bg-gray-400'
|
|
}`}
|
|
>
|
|
<div
|
|
className={`w-5 h-5 bg-white rounded-full absolute top-0.5 transition-transform ${
|
|
allowConvertToScene ? 'translate-x-5.5' : 'translate-x-0.5'
|
|
}`}
|
|
/>
|
|
</div>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* 会商流程预览 */}
|
|
<div className={`${cardBg} backdrop-blur-xl ${cardBorder} rounded-xl p-5`}>
|
|
<h3 className={`${textPrimary} font-semibold text-sm mb-4 flex items-center gap-2`}>
|
|
<Target className="w-4 h-4 text-orange-400" />
|
|
会商流程预览
|
|
</h3>
|
|
<div className="space-y-2">
|
|
{[
|
|
{ step: 1, label: '首轮独立发言', desc: '各智能体各抒己见' },
|
|
{ step: 2, label: '交叉讨论', desc: '按模式互动回应' },
|
|
{ step: 3, label: '观点提炼', desc: '系统自动汇总' },
|
|
{ step: 4, label: '人工整合', desc: '人类主导判断' },
|
|
{ step: 5, label: '输出结论', desc: '生成会商纪要' },
|
|
].map((item, index) => (
|
|
<div key={item.step} className="flex items-center gap-3">
|
|
<div className="flex flex-col items-center">
|
|
<div className={`w-6 h-6 rounded-full ${isDark ? 'bg-orange-500/20 border-orange-500/50' : 'bg-orange-100 border-orange-200'} flex items-center justify-center`}>
|
|
<span className={`${isDark ? 'text-orange-400' : 'text-orange-600'} text-xs font-medium`}>{item.step}</span>
|
|
</div>
|
|
{index < 4 && <div className={`w-px h-4 ${isDark ? 'bg-blue-800/30' : 'bg-gray-200'}`} />}
|
|
</div>
|
|
<div className="flex-1">
|
|
<p className={`${textPrimary} text-sm`}>{item.label}</p>
|
|
<p className={`${textMuted} text-xs`}>{item.desc}</p>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
{/* 选中智能体预览 */}
|
|
{selectedAgents.length > 0 && (
|
|
<div className={`${cardBg} backdrop-blur-xl ${isDark ? 'border-purple-800/30' : 'border-purple-200'} rounded-xl p-5`}>
|
|
<h3 className={`${textPrimary} font-semibold text-sm mb-3`}>
|
|
已选智能体 ({selectedAgents.length})
|
|
</h3>
|
|
<div className="flex flex-wrap gap-2">
|
|
{selectedAgents.map((agentId) => {
|
|
const agent = availableAgents.find((a) => a.id === agentId);
|
|
if (!agent) return null;
|
|
const colors = getColorClasses(agent.color);
|
|
return (
|
|
<span
|
|
key={agentId}
|
|
className={`px-2 py-1 ${colors.bg} ${colors.text} rounded-lg text-xs flex items-center gap-1`}
|
|
>
|
|
<Bot className="w-3 h-3" />
|
|
{agent.name}
|
|
</span>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{/* 操作按钮 */}
|
|
<div className="space-y-3">
|
|
<button
|
|
onClick={handleStartConsult}
|
|
disabled={!taskName || selectedAgents.length < 2}
|
|
className={`w-full flex items-center justify-center gap-2 px-4 py-3 ${btnPrimary} disabled:${isDark ? 'bg-slate-700 text-slate-500' : 'bg-gray-300 text-gray-500'} text-white rounded-xl text-sm font-medium transition-colors`}
|
|
>
|
|
<Play className="w-4 h-4" />
|
|
开始会商
|
|
</button>
|
|
<button className={`w-full flex items-center justify-center gap-2 px-4 py-3 ${btnSecondary} rounded-xl text-sm transition-colors`}>
|
|
<Save className="w-4 h-4" />
|
|
保存草稿
|
|
</button>
|
|
</div>
|
|
|
|
{/* 提示信息 */}
|
|
<div className={`${isDark ? 'bg-blue-500/10 border-blue-500/30' : 'bg-blue-50 border-blue-200'} rounded-lg p-3`}>
|
|
<div className="flex items-start gap-2">
|
|
<Lightbulb className={`w-4 h-4 text-blue-400 flex-shrink-0 mt-0.5`} />
|
|
<div className={`text-xs ${textSecondary}`}>
|
|
<p className={`${isDark ? 'text-blue-400' : 'text-blue-600'} font-medium mb-1`}>小提示</p>
|
|
<p>会商任务不追求自动闭环,而是帮助您更好地判断。建议在任务前期研判、多方案比较、争议问题讨论等场景使用。</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default TaskConsultCreate;
|