代码修改
This commit is contained in:
1 parent
8f5af46ec2
commit
8f75e12871
168 files changed
+76575
No files matched your search
@@ -0,0 +1,189 @@
|
||||
import React, { useState } from 'react';
|
||||
import { CheckCircle, ChevronLeft, ChevronRight, History, MessageCircle, Users } from 'lucide-react';
|
||||
import { useTheme } from '../../contexts/ThemeContext';
|
||||
import { PageType } from '../../components/Sidebar';
|
||||
import { ChatMessage, EmptyChatState, QAComposer, TypingIndicator } from './QACommon';
|
||||
|
||||
interface CollaborativeQAProps {
|
||||
onNavigate: (page: PageType) => void;
|
||||
}
|
||||
|
||||
interface CollaborativeMessage {
|
||||
id: string;
|
||||
role: 'user' | 'assistant';
|
||||
content: string;
|
||||
timestamp: Date;
|
||||
agentName?: string;
|
||||
}
|
||||
|
||||
const collaborativeAgents = [
|
||||
{ id: 'goal-agent', name: 'GoalAgent', category: '目标规划', color: 'blue' },
|
||||
{ id: 'audience-agent', name: 'AudienceAgent', category: '受众分析', color: 'green' },
|
||||
{ id: 'risk-agent', name: 'RiskAgent', category: '风险识别', color: 'purple' },
|
||||
];
|
||||
|
||||
/**
|
||||
* 多智能体协同问答组件
|
||||
* 多个智能体从不同视角联合分析问题,生成综合建议
|
||||
* @param onNavigate - 页面导航函数
|
||||
*/
|
||||
const CollaborativeQA: React.FC<CollaborativeQAProps> = ({ onNavigate }) => {
|
||||
const { theme } = useTheme();
|
||||
const isDark = theme === 'dark';
|
||||
const [messages, setMessages] = useState<CollaborativeMessage[]>([]);
|
||||
const [inputValue, setInputValue] = useState('');
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [selectedAgents, setSelectedAgents] = useState(collaborativeAgents.map((agent) => agent.id));
|
||||
const [isLeftSidebarCollapsed, setIsLeftSidebarCollapsed] = useState(false);
|
||||
|
||||
const activeAgents = collaborativeAgents.filter((agent) => selectedAgents.includes(agent.id));
|
||||
|
||||
const handleSend = () => {
|
||||
if (!inputValue.trim()) return;
|
||||
|
||||
const userMessage: CollaborativeMessage = {
|
||||
id: `user-${Date.now()}`,
|
||||
role: 'user',
|
||||
content: inputValue,
|
||||
timestamp: new Date(),
|
||||
};
|
||||
|
||||
setMessages((prev) => [...prev, userMessage]);
|
||||
setInputValue('');
|
||||
setIsLoading(true);
|
||||
|
||||
setTimeout(() => {
|
||||
const agentNames = activeAgents.map((agent) => agent.name).join('、');
|
||||
const assistantMessage: CollaborativeMessage = {
|
||||
id: `assistant-${Date.now()}`,
|
||||
role: 'assistant',
|
||||
content: `已组织 ${agentNames || '默认协同组'} 完成一轮联合研判:\n\n1. GoalAgent 建议先明确任务目标与阶段性 KPI,避免讨论发散。\n2. AudienceAgent 认为应优先锁定核心受众画像,并补充行为触点数据。\n3. RiskAgent 提醒需要同步评估内容合规、舆情扩散和资源约束。\n\n综合建议:先形成“目标-受众-风险”三列表,再进入方案细化与执行拆解。`,
|
||||
timestamp: new Date(),
|
||||
agentName: '协同编排助手',
|
||||
};
|
||||
setMessages((prev) => [...prev, assistantMessage]);
|
||||
setIsLoading(false);
|
||||
}, 1800);
|
||||
};
|
||||
|
||||
const handleStop = () => {
|
||||
setIsLoading(false);
|
||||
};
|
||||
|
||||
const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
||||
if (e.key === 'Enter' && !e.shiftKey) {
|
||||
e.preventDefault();
|
||||
handleSend();
|
||||
}
|
||||
};
|
||||
|
||||
const toggleAgent = (agentId: string) => {
|
||||
setSelectedAgents((prev) =>
|
||||
prev.includes(agentId) ? prev.filter((id) => id !== agentId) : [...prev, agentId]
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={`h-[calc(100vh-120px)] flex flex-col theme-bg rounded-xl ${isDark ? 'bg-slate-800/50' : 'bg-white'} border ${isDark ? 'border-slate-700/50' : 'border-red-100'}`}>
|
||||
<div className={`flex items-center justify-between px-6 py-4 border-b ${isDark ? 'border-slate-700/50' : 'border-red-100'}`}>
|
||||
<div className="flex items-center gap-4">
|
||||
<h1 className={`text-lg font-semibold ${isDark ? 'text-white' : 'text-gray-900'}`}>多智能体协同问答</h1>
|
||||
<span className={`text-sm ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>多角色联合研判、共识汇总与风险补充</span>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => onNavigate('qa-records')}
|
||||
className={`flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-medium transition-all ${
|
||||
isDark ? 'bg-slate-700/50 text-slate-300 hover:bg-slate-600/50' : 'bg-gray-100 text-gray-700 hover:bg-gray-200'
|
||||
}`}
|
||||
>
|
||||
<History className="w-4 h-4" />
|
||||
历史记录
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="flex-1 flex overflow-hidden">
|
||||
<aside className={`${isLeftSidebarCollapsed ? 'w-14 p-2' : 'w-72 p-4'} border-r flex-shrink-0 overflow-y-auto transition-all duration-300 ${isDark ? 'border-slate-700/50 bg-slate-800/30' : 'border-red-100 bg-gray-50/50'}`}>
|
||||
<div className={`flex items-center ${isLeftSidebarCollapsed ? 'justify-center' : 'justify-between'} mb-4`}>
|
||||
{!isLeftSidebarCollapsed && (
|
||||
<h3 className={`text-sm font-medium ${isDark ? 'text-slate-300' : 'text-gray-700'}`}>参与智能体</h3>
|
||||
)}
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setIsLeftSidebarCollapsed(!isLeftSidebarCollapsed)}
|
||||
className={`p-2 rounded-lg transition-all ${
|
||||
isDark
|
||||
? 'text-slate-400 hover:text-white hover:bg-slate-700/50'
|
||||
: 'text-gray-500 hover:text-red-600 hover:bg-red-50'
|
||||
}`}
|
||||
title={isLeftSidebarCollapsed ? '展开侧边栏' : '收起侧边栏'}
|
||||
>
|
||||
{isLeftSidebarCollapsed ? <ChevronRight className="w-4 h-4" /> : <ChevronLeft className="w-4 h-4" />}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{!isLeftSidebarCollapsed && (<>
|
||||
<div className="space-y-2">
|
||||
{collaborativeAgents.map((agent) => {
|
||||
const active = selectedAgents.includes(agent.id);
|
||||
return (
|
||||
<button
|
||||
key={agent.id}
|
||||
onClick={() => toggleAgent(agent.id)}
|
||||
className={`w-full p-3 rounded-xl text-left border transition-all ${
|
||||
active
|
||||
? isDark ? 'bg-blue-600/20 border-blue-500/50' : 'bg-red-50 border-red-200'
|
||||
: isDark ? 'bg-slate-700/30 border-transparent hover:bg-slate-700/50' : 'bg-white border-gray-200 hover:bg-gray-50'
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className={`w-10 h-10 rounded-2xl flex items-center justify-center ${active ? 'bg-gradient-to-br from-red-500 to-orange-400 text-white' : isDark ? 'bg-slate-600 text-slate-300' : 'bg-gray-100 text-gray-600'}`}>
|
||||
<Users className="w-5 h-5" />
|
||||
</div>
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className={`text-sm font-medium truncate ${isDark ? 'text-white' : 'text-gray-900'}`}>{agent.name}</div>
|
||||
<div className={`text-xs ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>{agent.category}</div>
|
||||
</div>
|
||||
{active && <CheckCircle className={`w-4 h-4 ${isDark ? 'text-blue-400' : 'text-red-500'}`} />}
|
||||
</div>
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</>)}
|
||||
</aside>
|
||||
|
||||
<section className="flex-1 flex flex-col overflow-hidden">
|
||||
<div className="flex-1 overflow-y-auto p-4 space-y-4">
|
||||
{messages.length === 0 ? (
|
||||
<EmptyChatState
|
||||
icon={<MessageCircle className="w-11 h-11 opacity-60" />}
|
||||
title="发起一次协同会商"
|
||||
description="输入任务背景,多个智能体会从不同视角生成联合建议"
|
||||
/>
|
||||
) : (
|
||||
messages.map((message) => (
|
||||
<ChatMessage key={message.id} message={message} assistantLabel={message.agentName || '协同编排助手'} />
|
||||
))
|
||||
)}
|
||||
{isLoading && <TypingIndicator label="多智能体正在协同分析并汇总观点" assistantLabel="协同编排助手" />}
|
||||
</div>
|
||||
|
||||
<QAComposer
|
||||
value={inputValue}
|
||||
onChange={setInputValue}
|
||||
onKeyDown={handleKeyDown}
|
||||
onSubmit={handleSend}
|
||||
onStop={handleStop}
|
||||
onSave={() => alert('问答记录已保存')}
|
||||
onCollect={() => alert('已添加到收藏')}
|
||||
isLoading={isLoading}
|
||||
placeholder="输入协同研判主题或任务背景..."
|
||||
showUpload={false}
|
||||
/>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CollaborativeQA;
|
||||
Reference in new issue
Block a user