代码修改
This commit is contained in:
1 parent
8f5af46ec2
commit
8f75e12871
168 files changed
+76575
No files matched your search
@@ -0,0 +1,626 @@
|
||||
import React, { useState } from 'react';
|
||||
import {
|
||||
ArrowLeft,
|
||||
Bot,
|
||||
Users,
|
||||
Play,
|
||||
Pause,
|
||||
Download,
|
||||
CheckCircle,
|
||||
ChevronRight,
|
||||
MessageSquare,
|
||||
Send,
|
||||
Star,
|
||||
AlertCircle,
|
||||
FileText,
|
||||
Settings,
|
||||
Lightbulb,
|
||||
Zap,
|
||||
Check,
|
||||
X,
|
||||
Minus,
|
||||
} from 'lucide-react';
|
||||
import { useTheme } from '@/contexts/ThemeContext';
|
||||
import { PageType } from '@/components/Sidebar';
|
||||
|
||||
interface TaskConsultProps {
|
||||
onNavigate: (page: PageType) => void;
|
||||
}
|
||||
|
||||
// 模拟参与智能体
|
||||
const participants = [
|
||||
{
|
||||
id: 'goal',
|
||||
name: 'GoalAgent',
|
||||
role: '目标分析专家',
|
||||
color: 'blue',
|
||||
status: 'idle' as const,
|
||||
lastOpinion: '建议聚焦提升品牌认知度这一核心目标',
|
||||
},
|
||||
{
|
||||
id: 'audience',
|
||||
name: 'AudienceAgent',
|
||||
role: '受众分析专家',
|
||||
color: 'cyan',
|
||||
status: 'speaking' as const,
|
||||
lastOpinion: '核心受众应为18-25岁基层青年群体',
|
||||
},
|
||||
{
|
||||
id: 'narrative',
|
||||
name: 'NarrativeAgent',
|
||||
role: '叙事策略专家',
|
||||
color: 'purple',
|
||||
status: 'idle' as const,
|
||||
lastOpinion: '应采用真实、有态度的青年故事叙事',
|
||||
},
|
||||
{
|
||||
id: 'risk',
|
||||
name: 'RiskAgent',
|
||||
role: '风险评估专家',
|
||||
color: 'red',
|
||||
status: 'idle' as const,
|
||||
lastOpinion: '需注意UGC质量不稳定和话题热度维持的风险',
|
||||
},
|
||||
];
|
||||
|
||||
// 模拟讨论记录
|
||||
const discussionRecords = [
|
||||
{
|
||||
id: 1,
|
||||
agentId: 'goal',
|
||||
agentName: 'GoalAgent',
|
||||
agentRole: '目标分析专家',
|
||||
color: 'blue',
|
||||
content: `从目标分析角度看,这次五四青年节宣传活动应聚焦以下核心目标:
|
||||
|
||||
**主目标**:提升品牌在Z世代用户中的认知度
|
||||
|
||||
**量化指标建议**:
|
||||
- 曝光量:500万+
|
||||
- 互动率:5%+
|
||||
- UGC数量:1000+
|
||||
|
||||
**优先级判断**:
|
||||
建议优先聚焦品牌认知度提升,短期内不追求直接转化。这样可以更好地与目标受众建立情感连接。`,
|
||||
time: '14:30',
|
||||
tags: ['核心目标', '品牌认知'],
|
||||
markedAs: null as string | null,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
agentId: 'audience',
|
||||
agentName: 'AudienceAgent',
|
||||
agentRole: '受众分析专家',
|
||||
color: 'cyan',
|
||||
content: `基于受众分析,我建议:
|
||||
|
||||
**核心受众画像**:
|
||||
- 年龄:18-25岁
|
||||
- 身份:学生、基层青年工作者
|
||||
- 地域:一二线城市为主
|
||||
|
||||
**关键洞察**:
|
||||
这部分群体是社交媒体重度用户,注重"真实感"和"态度感",反感过度营销。需要用平等对话的方式,而非说教式传播。
|
||||
|
||||
**内容偏好**:
|
||||
真实故事 > 精致包装
|
||||
态度表达 > 信息堆砌
|
||||
参与互动 > 被动观看`,
|
||||
time: '14:32',
|
||||
tags: ['受众画像', '内容偏好'],
|
||||
markedAs: 'valuable' as string | null,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
agentId: 'narrative',
|
||||
agentName: 'NarrativeAgent',
|
||||
agentRole: '叙事策略专家',
|
||||
color: 'purple',
|
||||
content: `从叙事策略角度,我建议采用以下框架:
|
||||
|
||||
**叙事主题**:真实、有态度的青年故事
|
||||
|
||||
**叙事结构**:
|
||||
1. 讲述真实的人物故事
|
||||
2. 引发情感共鸣
|
||||
3. 传递品牌价值观
|
||||
4. 激发用户参与
|
||||
|
||||
**关键要素**:
|
||||
- 真实感 > 精致感
|
||||
- 态度感 > 说教感
|
||||
- 参与感 > 观看感
|
||||
|
||||
**内容类型建议**:
|
||||
- 人物专访型:真实青年故事
|
||||
- 事件记录型:青年节活动现场
|
||||
- 观点表达型:青年态度宣言`,
|
||||
time: '14:35',
|
||||
tags: ['叙事框架', '内容类型'],
|
||||
markedAs: null as string | null,
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
agentId: 'risk',
|
||||
agentName: 'RiskAgent',
|
||||
agentRole: '风险评估专家',
|
||||
color: 'red',
|
||||
content: `我需要提醒以下风险:
|
||||
|
||||
**高风险项**:
|
||||
1. 内容质量不稳定
|
||||
- 风险:UGC质量参差不齐
|
||||
- 对策:建立内容审核机制
|
||||
|
||||
**中风险项**:
|
||||
2. 预算控制难度大
|
||||
- 风险:投放效果不可控
|
||||
- 对策:分阶段预算分配
|
||||
|
||||
3. 青年群体注意力分散
|
||||
- 风险:话题热度难维持
|
||||
- 对策:多波次内容规划
|
||||
|
||||
**建议**:重点关注内容质量风险,建立审核机制。`,
|
||||
time: '14:38',
|
||||
tags: ['风险识别', '应对建议'],
|
||||
markedAs: 'pending' as string | null,
|
||||
},
|
||||
];
|
||||
|
||||
const TaskConsult: React.FC<TaskConsultProps> = ({ onNavigate }) => {
|
||||
const { theme } = useTheme();
|
||||
const isDark = theme === 'dark';
|
||||
const [isPaused, setIsPaused] = useState(false);
|
||||
const [currentRound, setCurrentRound] = useState(2);
|
||||
const [currentTopic, setCurrentTopic] = useState('宣传策略方向选择');
|
||||
const [humanInput, setHumanInput] = useState('');
|
||||
const [consensusPoints] = useState([
|
||||
'核心受众应聚焦18-25岁基层青年',
|
||||
'内容应以真实、有态度为核心',
|
||||
]);
|
||||
const [disputedPoints] = useState([
|
||||
'叙事角度:事件叙事 vs 人物叙事',
|
||||
'传播渠道:短视频平台 vs 社交媒体',
|
||||
]);
|
||||
const [humanNotes, setHumanNotes] = useState('');
|
||||
|
||||
const getColorClasses = (color: string) => {
|
||||
const colors: Record<string, { bg: string; border: string; text: string }> = {
|
||||
blue: { bg: isDark ? 'bg-blue-500/20' : 'bg-blue-50', border: isDark ? 'border-blue-500/50' : 'border-blue-200', text: isDark ? 'text-blue-400' : 'text-blue-600' },
|
||||
cyan: { bg: isDark ? 'bg-cyan-500/20' : 'bg-cyan-50', border: isDark ? 'border-cyan-500/50' : 'border-cyan-200', text: isDark ? 'text-cyan-400' : 'text-cyan-600' },
|
||||
green: { bg: isDark ? 'bg-green-500/20' : 'bg-green-50', border: isDark ? 'border-green-500/50' : 'border-green-200', text: isDark ? 'text-green-400' : 'text-green-600' },
|
||||
yellow: { bg: isDark ? 'bg-yellow-500/20' : 'bg-yellow-50', border: isDark ? 'border-yellow-500/50' : 'border-yellow-200', text: isDark ? 'text-yellow-400' : 'text-yellow-600' },
|
||||
purple: { bg: isDark ? 'bg-purple-500/20' : 'bg-purple-50', border: isDark ? 'border-purple-500/50' : 'border-purple-200', text: isDark ? 'text-purple-400' : 'text-purple-600' },
|
||||
red: { bg: isDark ? 'bg-red-500/20' : 'bg-red-50', border: isDark ? 'border-red-500/50' : 'border-red-200', text: isDark ? 'text-red-400' : 'text-red-600' },
|
||||
};
|
||||
return colors[color] || colors.blue;
|
||||
};
|
||||
|
||||
const getStatusConfig = (status: string) => {
|
||||
switch (status) {
|
||||
case 'speaking':
|
||||
return { label: '发言中', color: isDark ? 'bg-green-500/20 text-green-400' : 'bg-green-100 text-green-700', dot: isDark ? 'bg-green-400' : 'bg-green-500' };
|
||||
case 'completed':
|
||||
return { label: '已完成', color: isDark ? 'bg-slate-500/20 text-slate-400' : 'bg-gray-100 text-gray-600', dot: isDark ? 'bg-slate-400' : 'bg-gray-400' };
|
||||
default:
|
||||
return { label: '待发言', color: isDark ? 'bg-slate-500/20 text-slate-400' : 'bg-gray-100 text-gray-600', dot: isDark ? 'bg-slate-400' : 'bg-gray-400' };
|
||||
}
|
||||
};
|
||||
|
||||
const handleNextRound = () => {
|
||||
setCurrentRound(currentRound + 1);
|
||||
};
|
||||
|
||||
const handleFinishConsult = () => {
|
||||
onNavigate('task-consult-result');
|
||||
};
|
||||
|
||||
// 主题颜色类
|
||||
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';
|
||||
|
||||
return (
|
||||
<div className="h-[calc(100vh-140px)] flex flex-col space-y-4">
|
||||
{/* 顶部信息栏 */}
|
||||
<div className={`${cardBg} backdrop-blur-xl border ${cardBorder} rounded-xl p-4 flex-shrink-0`}>
|
||||
<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-red-200'}`} />
|
||||
<div>
|
||||
<h1 className={`${textPrimary} font-bold text-lg`}>五四青年节宣传策略会商</h1>
|
||||
<p className={`${textSecondary} text-sm`}>多智能体会商任务 · 第 {currentRound} 轮</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="flex items-center gap-4 text-sm">
|
||||
<span className={textSecondary}>
|
||||
模式:<span className={isDark ? 'text-purple-400' : 'text-purple-600'}>受控交叉讨论</span>
|
||||
</span>
|
||||
<span className={textSecondary}>
|
||||
参与:<span className={isDark ? 'text-cyan-400' : 'text-cyan-600'}>{participants.length} 个智能体</span>
|
||||
</span>
|
||||
<span className={textSecondary}>
|
||||
创建:<span className={textPrimary}>2026-03-19 14:30</span>
|
||||
</span>
|
||||
</div>
|
||||
<div className={`h-8 w-px ${isDark ? 'bg-blue-800/30' : 'bg-red-200'}`} />
|
||||
<div className="flex items-center gap-2">
|
||||
<button
|
||||
onClick={() => setIsPaused(!isPaused)}
|
||||
className={`flex items-center gap-2 px-3 py-1.5 rounded-lg text-sm transition-colors ${
|
||||
isPaused
|
||||
? (isDark ? 'bg-green-500/20 hover:bg-green-500/30 border-green-500/50 text-green-400' : 'bg-green-100 hover:bg-green-200 border-green-300 text-green-700')
|
||||
: (isDark ? 'bg-yellow-500/20 hover:bg-yellow-500/30 border-yellow-500/50 text-yellow-400' : 'bg-yellow-100 hover:bg-yellow-200 border-yellow-300 text-yellow-700')
|
||||
}`}
|
||||
>
|
||||
{isPaused ? <Play className="w-4 h-4" /> : <Pause className="w-4 h-4" />}
|
||||
{isPaused ? '继续会商' : '暂停会商'}
|
||||
</button>
|
||||
<button className={`flex items-center gap-2 px-3 py-1.5 ${btnSecondary} rounded-lg text-sm transition-colors`}>
|
||||
<Download className="w-4 h-4" />
|
||||
导出纪要
|
||||
</button>
|
||||
<button
|
||||
onClick={handleFinishConsult}
|
||||
className="flex items-center gap-2 px-3 py-1.5 bg-orange-600 hover:bg-orange-500 text-white rounded-lg text-sm transition-colors"
|
||||
>
|
||||
<CheckCircle className="w-4 h-4" />
|
||||
结束并整合
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 三栏主体区域 */}
|
||||
<div className="flex-1 grid grid-cols-12 gap-4 min-h-0">
|
||||
{/* 左栏:参与智能体与议题导航 */}
|
||||
<div className="col-span-3 flex flex-col gap-4 min-h-0">
|
||||
{/* 参与智能体 */}
|
||||
<div className={`${cardBg} backdrop-blur-xl border ${cardBorder} rounded-xl p-4 flex-1 overflow-hidden flex flex-col`}>
|
||||
<h3 className={`${textPrimary} font-semibold text-sm mb-3 flex items-center gap-2`}>
|
||||
<Users className={`w-4 h-4 ${isDark ? 'text-purple-400' : 'text-purple-600'}`} />
|
||||
参与智能体
|
||||
</h3>
|
||||
<div className="space-y-2 flex-1 overflow-y-auto">
|
||||
{participants.map((agent) => {
|
||||
const colors = getColorClasses(agent.color);
|
||||
const statusConfig = getStatusConfig(agent.status);
|
||||
return (
|
||||
<div
|
||||
key={agent.id}
|
||||
className={`p-3 rounded-lg border transition-all ${
|
||||
agent.status === 'speaking'
|
||||
? `${colors.bg} ${colors.border}`
|
||||
: isDark ? 'bg-slate-900/50 border-blue-800/30' : 'bg-gray-50 border-gray-200'
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-center justify-between mb-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className={`w-8 h-8 rounded-lg ${colors.bg} flex items-center justify-center`}>
|
||||
<Bot className={`w-4 h-4 ${colors.text}`} />
|
||||
</div>
|
||||
<div>
|
||||
<p className={`text-sm font-medium ${agent.status === 'speaking' ? colors.text : textPrimary}`}>
|
||||
{agent.name}
|
||||
</p>
|
||||
<p className={`${textMuted} text-xs`}>{agent.role}</p>
|
||||
</div>
|
||||
</div>
|
||||
<span className={`px-1.5 py-0.5 rounded text-xs ${statusConfig.color}`}>
|
||||
{statusConfig.label}
|
||||
</span>
|
||||
</div>
|
||||
{agent.lastOpinion && (
|
||||
<p className={`${textSecondary} text-xs line-clamp-2 pl-10`}>{agent.lastOpinion}</p>
|
||||
)}
|
||||
<button
|
||||
className={`mt-2 w-full px-2 py-1.5 rounded text-xs transition-colors ${
|
||||
agent.status === 'speaking'
|
||||
? (isDark ? 'bg-slate-700/50 text-slate-400 cursor-not-allowed' : 'bg-gray-200 text-gray-500 cursor-not-allowed')
|
||||
: (isDark ? 'bg-purple-500/20 hover:bg-purple-500/30 text-purple-400' : 'bg-purple-100 hover:bg-purple-200 text-purple-700')
|
||||
}`}
|
||||
disabled={agent.status === 'speaking'}
|
||||
>
|
||||
点名发言
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 会商议题导航 */}
|
||||
<div className={`${cardBg} backdrop-blur-xl border ${cardBorder} rounded-xl p-4`}>
|
||||
<h3 className={`${textPrimary} font-semibold text-sm mb-3 flex items-center gap-2`}>
|
||||
<MessageSquare className={`w-4 h-4 ${isDark ? 'text-blue-400' : 'text-blue-600'}`} />
|
||||
会商议题
|
||||
</h3>
|
||||
<div className="space-y-2">
|
||||
<div className={`p-3 rounded-lg border ${isDark ? 'bg-green-500/20 border-green-500/50' : 'bg-green-50 border-green-300'}`}>
|
||||
<p className={`text-sm font-medium ${isDark ? 'text-green-400' : 'text-green-700'}`}>当前议题</p>
|
||||
<p className={`${textPrimary} text-sm mt-1`}>{currentTopic}</p>
|
||||
</div>
|
||||
<div className={`p-3 rounded-lg border ${isDark ? 'bg-slate-900/50 border-blue-800/30' : 'bg-gray-50 border-gray-200'}`}>
|
||||
<p className={`${textMuted} text-xs mb-1`}>待讨论</p>
|
||||
<p className={isDark ? 'text-slate-300 text-sm' : 'text-gray-700 text-sm'}>渠道策略选择</p>
|
||||
<p className={isDark ? 'text-slate-300 text-sm' : 'text-gray-700 text-sm'}>预算分配方案</p>
|
||||
</div>
|
||||
<div className={`p-3 rounded-lg border ${isDark ? 'bg-slate-900/50 border-blue-800/30' : 'bg-gray-50 border-gray-200'}`}>
|
||||
<p className={`${textMuted} text-xs mb-1`}>已讨论</p>
|
||||
<p className={`${textMuted} text-sm line-through`}>受众定位</p>
|
||||
<p className={`${textMuted} text-sm line-through`}>目标设定</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-3 flex gap-2">
|
||||
<button className={`flex-1 px-2 py-1.5 ${btnSecondary} rounded-lg text-xs transition-colors`}>
|
||||
切换议题
|
||||
</button>
|
||||
<button className={`flex-1 px-2 py-1.5 ${btnSecondary} rounded-lg text-xs transition-colors`}>
|
||||
结束议题
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 中栏:会商讨论区 */}
|
||||
<div className="col-span-6 flex flex-col gap-4 min-h-0">
|
||||
{/* 当前议题卡 */}
|
||||
<div className={`${cardBg} backdrop-blur-xl border ${cardBorder} rounded-xl p-4 flex-shrink-0`}>
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className={`${textSecondary} text-xs`}>当前议题</p>
|
||||
<p className={`${textPrimary} font-medium mt-0.5`}>{currentTopic}</p>
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<span className={`px-2 py-1 rounded text-xs ${isDark ? 'bg-purple-500/20 text-purple-400' : 'bg-purple-100 text-purple-700'}`}>
|
||||
受控交叉讨论模式
|
||||
</span>
|
||||
<span className={`px-2 py-1 rounded text-xs ${isDark ? 'bg-blue-500/20 text-blue-400' : 'bg-blue-100 text-blue-700'}`}>
|
||||
第 {currentRound} 轮
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 讨论流 */}
|
||||
<div className={`${cardBg} backdrop-blur-xl border ${cardBorder} rounded-xl overflow-hidden flex flex-col`}>
|
||||
<div className={`p-4 border-b ${isDark ? 'border-blue-800/30' : 'border-gray-200'} flex items-center justify-between`}>
|
||||
<h3 className={`${textPrimary} font-semibold text-sm`}>讨论记录</h3>
|
||||
<button
|
||||
onClick={handleNextRound}
|
||||
className={`flex items-center gap-2 px-3 py-1.5 ${btnPrimary} bg-opacity-20 hover:bg-opacity-30 ${isDark ? 'border border-blue-500/30 text-blue-400' : 'border border-red-400 text-red-600'} rounded-lg text-xs transition-colors`}
|
||||
>
|
||||
<ChevronRight className="w-4 h-4" />
|
||||
下一轮
|
||||
</button>
|
||||
</div>
|
||||
<div className="flex-1 overflow-y-auto p-4 space-y-4">
|
||||
{discussionRecords.map((record) => {
|
||||
const colors = getColorClasses(record.color);
|
||||
return (
|
||||
<div
|
||||
key={record.id}
|
||||
className={`p-4 rounded-xl border ${
|
||||
record.markedAs === 'valuable'
|
||||
? (isDark ? 'bg-green-500/10 border-green-500/30' : 'bg-green-50 border-green-300')
|
||||
: record.markedAs === 'pending'
|
||||
? (isDark ? 'bg-yellow-500/10 border-yellow-500/30' : 'bg-yellow-50 border-yellow-300')
|
||||
: (isDark ? 'bg-slate-900/50 border-blue-800/30' : 'bg-gray-50 border-gray-200')
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-start justify-between mb-3">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className={`w-10 h-10 rounded-lg ${colors.bg} flex items-center justify-center`}>
|
||||
<Bot className={`w-5 h-5 ${colors.text}`} />
|
||||
</div>
|
||||
<div>
|
||||
<div className="flex items-center gap-2">
|
||||
<p className={`text-sm font-medium ${colors.text}`}>{record.agentName}</p>
|
||||
{record.markedAs === 'valuable' && (
|
||||
<span className={`px-1.5 py-0.5 rounded text-xs flex items-center gap-0.5 ${isDark ? 'bg-green-500/20 text-green-400' : 'bg-green-100 text-green-700'}`}>
|
||||
<Star className="w-3 h-3" /> 有价值
|
||||
</span>
|
||||
)}
|
||||
{record.markedAs === 'pending' && (
|
||||
<span className={`px-1.5 py-0.5 rounded text-xs flex items-center gap-0.5 ${isDark ? 'bg-yellow-500/20 text-yellow-400' : 'bg-yellow-100 text-yellow-700'}`}>
|
||||
<AlertCircle className="w-3 h-3" /> 待验证
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<p className={`${textMuted} text-xs`}>{record.agentRole} · {record.time}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-1">
|
||||
<button
|
||||
className={`p-1.5 rounded transition-colors ${isDark ? 'hover:bg-green-500/20' : 'hover:bg-green-100'}`}
|
||||
title="标记为有价值"
|
||||
>
|
||||
<Star className={`w-4 h-4 ${isDark ? 'text-slate-400 hover:text-green-400' : 'text-gray-500 hover:text-green-600'}`} />
|
||||
</button>
|
||||
<button
|
||||
className={`p-1.5 rounded transition-colors ${isDark ? 'hover:bg-yellow-500/20' : 'hover:bg-yellow-100'}`}
|
||||
title="标记为待验证"
|
||||
>
|
||||
<AlertCircle className={`w-4 h-4 ${isDark ? 'text-slate-400 hover:text-yellow-400' : 'text-gray-500 hover:text-yellow-600'}`} />
|
||||
</button>
|
||||
<button
|
||||
className={`p-1.5 rounded transition-colors ${isDark ? 'hover:bg-red-500/20' : 'hover:bg-red-100'}`}
|
||||
title="暂不采纳"
|
||||
>
|
||||
<X className={`w-4 h-4 ${isDark ? 'text-slate-400 hover:text-red-400' : 'text-gray-500 hover:text-red-600'}`} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="pl-13">
|
||||
<div className={`${isDark ? 'text-slate-300' : 'text-gray-700'} text-sm whitespace-pre-wrap leading-relaxed`}>
|
||||
{record.content}
|
||||
</div>
|
||||
<div className="flex items-center gap-2 mt-3">
|
||||
{record.tags.map((tag) => (
|
||||
<span key={tag} className={`px-2 py-0.5 rounded text-xs ${isDark ? 'bg-blue-500/20 text-blue-400' : 'bg-blue-100 text-blue-700'}`}>
|
||||
{tag}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
<div className="flex items-center gap-2 mt-3">
|
||||
<button className={`flex items-center gap-1 px-2 py-1 ${btnSecondary} rounded text-xs transition-colors`}>
|
||||
<FileText className="w-3 h-3" />
|
||||
引用到整合区
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 人工发言区 */}
|
||||
<div className={`${cardBg} backdrop-blur-xl border ${cardBorder} rounded-xl p-4 flex-shrink-0`}>
|
||||
<div className="flex items-start gap-3">
|
||||
<div className={`w-10 h-10 rounded-lg flex items-center justify-center flex-shrink-0 ${isDark ? 'bg-blue-500/20' : 'bg-blue-100'}`}>
|
||||
<Users className={`w-5 h-5 ${isDark ? 'text-blue-400' : 'text-blue-600'}`} />
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<textarea
|
||||
value={humanInput}
|
||||
onChange={(e) => setHumanInput(e.target.value)}
|
||||
placeholder="输入您的评论、问题或指令... (可点名某个智能体:@GoalAgent)"
|
||||
rows={2}
|
||||
className={`w-full px-4 py-2.5 ${inputBg} border ${inputBorder} rounded-lg ${textPrimary} text-sm ${isDark ? 'placeholder-slate-500' : 'placeholder-gray-400'} focus:outline-none ${isDark ? 'focus:border-blue-500/50' : 'focus:border-red-400'} transition-colors resize-none`}
|
||||
/>
|
||||
<div className="flex items-center justify-between mt-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<button className={`px-2 py-1 ${btnSecondary} rounded text-xs transition-colors`}>
|
||||
点名提问
|
||||
</button>
|
||||
<button className={`px-2 py-1 ${btnSecondary} rounded text-xs transition-colors`}>
|
||||
发起对比问题
|
||||
</button>
|
||||
<button className={`px-2 py-1 ${btnSecondary} rounded text-xs transition-colors`}>
|
||||
要求补充说明
|
||||
</button>
|
||||
</div>
|
||||
<button
|
||||
disabled={!humanInput.trim()}
|
||||
className={`flex items-center gap-2 px-4 py-2 ${btnPrimary} disabled:${isDark ? 'bg-slate-700 text-slate-500' : 'bg-gray-300 text-gray-500'} text-white rounded-lg text-sm transition-colors`}
|
||||
>
|
||||
<Send className="w-4 h-4" />
|
||||
发送
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 右栏:观点整合区 */}
|
||||
<div className="col-span-3 flex flex-col gap-4 min-h-0">
|
||||
{/* 各智能体核心观点 */}
|
||||
<div className={`${cardBg} backdrop-blur-xl border ${cardBorder} rounded-xl p-4 flex-1 overflow-hidden flex flex-col`}>
|
||||
<h3 className={`${textPrimary} font-semibold text-sm mb-3 flex items-center gap-2`}>
|
||||
<Bot className={`w-4 h-4 ${isDark ? 'text-cyan-400' : 'text-cyan-600'}`} />
|
||||
各方观点
|
||||
</h3>
|
||||
<div className="space-y-3 flex-1 overflow-y-auto">
|
||||
{participants.map((agent) => {
|
||||
const colors = getColorClasses(agent.color);
|
||||
return (
|
||||
<div key={agent.id} className={`p-3 rounded-lg ${isDark ? 'bg-slate-900/50 border-blue-800/30' : 'bg-gray-50 border-gray-200'}`}>
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
<Bot className={`w-4 h-4 ${colors.text}`} />
|
||||
<span className={`text-sm font-medium ${colors.text}`}>{agent.name}</span>
|
||||
</div>
|
||||
<p className={`${textSecondary} text-xs line-clamp-3`}>{agent.lastOpinion}</p>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 共识观点 */}
|
||||
<div className={`${cardBg} backdrop-blur-xl border ${isDark ? 'border-green-800/30' : 'border-green-300'} rounded-xl p-4`}>
|
||||
<h3 className={`${textPrimary} font-semibold text-sm mb-3 flex items-center gap-2`}>
|
||||
<Check className={`w-4 h-4 ${isDark ? 'text-green-400' : 'text-green-600'}`} />
|
||||
共识观点
|
||||
<span className={`px-1.5 py-0.5 rounded text-xs ml-auto ${isDark ? 'bg-green-500/20 text-green-400' : 'bg-green-100 text-green-700'}`}>
|
||||
{consensusPoints.length} 条
|
||||
</span>
|
||||
</h3>
|
||||
<div className="space-y-2">
|
||||
{consensusPoints.map((point, index) => (
|
||||
<div key={index} className={`p-2 rounded-lg ${isDark ? 'bg-green-500/10 border border-green-500/30' : 'bg-green-50 border border-green-200'}`}>
|
||||
<p className={isDark ? 'text-green-300 text-sm' : 'text-green-800 text-sm'}>{point}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 分歧观点 */}
|
||||
<div className={`${cardBg} backdrop-blur-xl border ${isDark ? 'border-yellow-800/30' : 'border-yellow-300'} rounded-xl p-4`}>
|
||||
<h3 className={`${textPrimary} font-semibold text-sm mb-3 flex items-center gap-2`}>
|
||||
<Minus className={`w-4 h-4 ${isDark ? 'text-yellow-400' : 'text-yellow-600'}`} />
|
||||
分歧观点
|
||||
<span className={`px-1.5 py-0.5 rounded text-xs ml-auto ${isDark ? 'bg-yellow-500/20 text-yellow-400' : 'bg-yellow-100 text-yellow-700'}`}>
|
||||
{disputedPoints.length} 条
|
||||
</span>
|
||||
</h3>
|
||||
<div className="space-y-2">
|
||||
{disputedPoints.map((point, index) => (
|
||||
<div key={index} className={`p-2 rounded-lg ${isDark ? 'bg-yellow-500/10 border border-yellow-500/30' : 'bg-yellow-50 border border-yellow-200'}`}>
|
||||
<p className={isDark ? 'text-yellow-300 text-sm' : 'text-yellow-800 text-sm'}>{point}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 人工整合区 */}
|
||||
<div className={`${cardBg} backdrop-blur-xl border ${isDark ? 'border-purple-800/30' : 'border-purple-300'} rounded-xl p-4 flex-1 overflow-hidden flex flex-col`}>
|
||||
<h3 className={`${textPrimary} font-semibold text-sm mb-3 flex items-center gap-2`}>
|
||||
<Zap className={`w-4 h-4 ${isDark ? 'text-purple-400' : 'text-purple-600'}`} />
|
||||
人工整合
|
||||
</h3>
|
||||
<textarea
|
||||
value={humanNotes}
|
||||
onChange={(e) => setHumanNotes(e.target.value)}
|
||||
placeholder="记录您的判断、暂定方向、待确认事项..."
|
||||
className={`flex-1 min-h-[120px] px-3 py-2 ${inputBg} border ${inputBorder} rounded-lg ${textPrimary} text-sm ${isDark ? 'placeholder-slate-500' : 'placeholder-gray-400'} focus:outline-none ${isDark ? 'focus:border-blue-500/50' : 'focus:border-red-400'} transition-colors resize-none`}
|
||||
/>
|
||||
<div className="flex flex-col gap-2 mt-3">
|
||||
<button className={`w-full flex items-center justify-center gap-2 px-3 py-2 ${isDark ? 'bg-purple-600 hover:bg-purple-500' : 'bg-purple-600 hover:bg-purple-500'} text-white rounded-lg text-xs font-medium transition-colors`}>
|
||||
<Lightbulb className="w-4 h-4" />
|
||||
生成会商结论
|
||||
</button>
|
||||
<button className={`w-full flex items-center justify-center gap-2 px-3 py-2 ${btnSecondary} rounded-lg text-xs transition-colors`}>
|
||||
<FileText className="w-4 h-4" />
|
||||
转为任务摘要
|
||||
</button>
|
||||
<button className={`w-full flex items-center justify-center gap-2 px-3 py-2 ${btnSecondary} rounded-lg text-xs transition-colors`}>
|
||||
<Settings className="w-4 h-4" />
|
||||
转为场景任务输入
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TaskConsult;
|
||||
Reference in new issue
Block a user