637 lines
27 KiB
TypeScript
637 lines
27 KiB
TypeScript
import React, { useState } from 'react';
|
||
import {
|
||
Send,
|
||
Search,
|
||
History,
|
||
Bot,
|
||
Sparkles,
|
||
Database,
|
||
Layers,
|
||
FileText,
|
||
Bookmark,
|
||
ChevronRight,
|
||
Cpu,
|
||
Target,
|
||
MessageSquare,
|
||
Zap,
|
||
CheckCircle,
|
||
} from 'lucide-react';
|
||
import { useTheme } from '../contexts/ThemeContext';
|
||
import { PageType } from '../components/Sidebar';
|
||
|
||
interface Agent {
|
||
id: string;
|
||
name: string;
|
||
category: string;
|
||
tags: string[];
|
||
description: string;
|
||
skills: string[];
|
||
dataSources: string[];
|
||
functions: string[];
|
||
outputFields: string[];
|
||
}
|
||
|
||
interface Message {
|
||
id: string;
|
||
role: 'user' | 'assistant';
|
||
content: string;
|
||
timestamp: Date;
|
||
agentName?: string;
|
||
skills?: string[];
|
||
dataSources?: string[];
|
||
functions?: string[];
|
||
structuredOutput?: Record<string, any>;
|
||
}
|
||
|
||
const AgentQA: React.FC<{ onNavigate: (page: PageType) => void }> = ({ onNavigate }) => {
|
||
const { theme } = useTheme();
|
||
const isDark = theme === 'dark';
|
||
|
||
// 模拟智能体列表
|
||
const agents: Agent[] = [
|
||
{
|
||
id: 'audience-agent',
|
||
name: 'AudienceAgent',
|
||
category: '受众分析',
|
||
tags: ['受众分层', '画像抽取', '行为预测'],
|
||
description: '专业的受众分析智能体,能够识别目标受众特征并生成画像',
|
||
skills: ['受众分层', '核心受众识别', '画像抽取', '行为预测'],
|
||
dataSources: ['知识库', 'Y系统', 'A系统'],
|
||
functions: ['信息抽取器', '标签聚类器', '结构化输出器'],
|
||
outputFields: ['core_audience', 'key_traits', 'barriers', 'opportunities'],
|
||
},
|
||
{
|
||
id: 'brand-agent',
|
||
name: 'BrandAgent',
|
||
category: '品牌分析',
|
||
tags: ['品牌定位', '传播策略', '调性分析'],
|
||
description: '专注品牌建设与传播策略的智能体',
|
||
skills: ['品牌定位分析', '传播路径规划', '品牌调性设计'],
|
||
dataSources: ['知识库', '行业数据库'],
|
||
functions: ['品牌诊断器', '策略生成器'],
|
||
outputFields: ['brand_position', 'communication_path', 'tone_guide'],
|
||
},
|
||
{
|
||
id: 'content-agent',
|
||
name: 'ContentAgent',
|
||
category: '内容创作',
|
||
tags: ['文案撰写', '创意生成', '多形式内容'],
|
||
description: '智能内容创作助手,支持多种形式的内容生成',
|
||
skills: ['文案撰写', '创意生成', '多形式内容', 'A/B测试文案'],
|
||
dataSources: ['知识库', '优秀案例库'],
|
||
functions: ['文案生成器', '风格适配器', '质量评估器'],
|
||
outputFields: ['headlines', 'body_copy', 'call_to_action', 'variants'],
|
||
},
|
||
{
|
||
id: 'channel-agent',
|
||
name: 'ChannelAgent',
|
||
category: '渠道规划',
|
||
tags: ['渠道选择', '投放策略', '效果评估'],
|
||
description: '专业的渠道分析与规划智能体',
|
||
skills: ['渠道选择', '投放策略规划', '效果评估', '预算分配'],
|
||
dataSources: ['Y系统', 'A系统', '行业数据'],
|
||
functions: ['渠道分析器', '投放优化器', 'ROI预测器'],
|
||
outputFields: ['recommended_channels', 'budget_allocation', 'expected_roi'],
|
||
},
|
||
];
|
||
|
||
// 状态
|
||
const [selectedAgent, setSelectedAgent] = useState<Agent>(agents[0]);
|
||
const [searchQuery, setSearchQuery] = useState('');
|
||
const [messages, setMessages] = useState<Message[]>([]);
|
||
const [inputValue, setInputValue] = useState('');
|
||
const [isLoading, setIsLoading] = useState(false);
|
||
|
||
// 过滤智能体
|
||
const filteredAgents = agents.filter(agent =>
|
||
agent.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||
agent.category.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||
agent.tags.some(tag => tag.toLowerCase().includes(searchQuery.toLowerCase()))
|
||
);
|
||
|
||
// 处理发送消息
|
||
const handleSend = () => {
|
||
if (!inputValue.trim()) return;
|
||
|
||
setIsLoading(true);
|
||
|
||
const userMessage: Message = {
|
||
id: Date.now().toString(),
|
||
role: 'user',
|
||
content: inputValue,
|
||
timestamp: new Date(),
|
||
};
|
||
|
||
setMessages([...messages, userMessage]);
|
||
setInputValue('');
|
||
|
||
// 模拟AI响应
|
||
setTimeout(() => {
|
||
const response: Message = {
|
||
id: (Date.now() + 1).toString(),
|
||
role: 'assistant',
|
||
content: `基于${selectedAgent.name}的专业能力,我来为您分析:\n\n根据您的问题,我识别到核心受众特征如下:\n\n**核心受众识别**:\n- 主要年龄段:25-35岁\n- 职业特征:都市白领\n- 消费能力:中高端\n- 关注点:品质生活、个人成长\n\n**关键特质**:\n1. 追求个性化表达\n2. 注重社交认同\n3. 愿意为品质付费\n\n**可能存在的阻力**:\n- 价格敏感度较高\n- 对品牌忠诚度有限\n\n以上分析是否满足您的需求?如需调整维度,请继续补充信息。`,
|
||
timestamp: new Date(),
|
||
agentName: selectedAgent.name,
|
||
skills: selectedAgent.skills,
|
||
dataSources: selectedAgent.dataSources,
|
||
functions: selectedAgent.functions,
|
||
structuredOutput: {
|
||
core_audience: '25-35岁都市白领',
|
||
key_traits: ['追求个性化', '注重社交认同', '品质导向'],
|
||
barriers: ['价格敏感', '品牌忠诚度有限'],
|
||
opportunities: ['社交媒体影响大', '口碑传播效果好'],
|
||
},
|
||
};
|
||
|
||
setMessages(prev => [...prev, response]);
|
||
setIsLoading(false);
|
||
}, 1500);
|
||
};
|
||
|
||
const handleKeyDown = (e: React.KeyboardEvent) => {
|
||
if (e.key === 'Enter' && !e.shiftKey) {
|
||
e.preventDefault();
|
||
handleSend();
|
||
}
|
||
};
|
||
|
||
const handleSaveRecord = () => {
|
||
alert('问答记录已保存');
|
||
};
|
||
|
||
const handleCollect = () => {
|
||
alert('已添加到收藏');
|
||
};
|
||
|
||
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>
|
||
<div className={`flex items-center gap-2 px-3 py-1.5 rounded-lg ${isDark ? 'bg-slate-700/50' : 'bg-red-50'}`}>
|
||
<Bot className={`w-4 h-4 ${isDark ? 'text-blue-400' : 'text-red-500'}`} />
|
||
<span className={`text-sm ${isDark ? 'text-slate-300' : 'text-gray-700'}`}>
|
||
当前智能体:
|
||
</span>
|
||
<span className={`text-sm font-medium ${isDark ? 'text-blue-400' : 'text-red-600'}`}>
|
||
{selectedAgent.name}
|
||
</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="flex items-center gap-2">
|
||
<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>
|
||
|
||
{/* 主体内容区 */}
|
||
<div className="flex-1 flex overflow-hidden">
|
||
{/* 左侧智能体区 */}
|
||
<div className={`w-72 border-r flex-shrink-0 overflow-y-auto ${isDark ? 'border-slate-700/50 bg-slate-800/30' : 'border-red-100 bg-gray-50/50'}`}>
|
||
{/* 智能体搜索 */}
|
||
<div className="p-4">
|
||
<div className={`relative ${isDark ? 'bg-slate-700/50' : 'bg-white'} rounded-lg`}>
|
||
<Search className={`absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 ${isDark ? 'text-slate-400' : 'text-gray-400'}`} />
|
||
<input
|
||
type="text"
|
||
value={searchQuery}
|
||
onChange={(e) => setSearchQuery(e.target.value)}
|
||
placeholder="搜索智能体..."
|
||
className={`w-full pl-10 pr-4 py-2 rounded-lg text-sm focus:outline-none ${
|
||
isDark
|
||
? 'bg-transparent text-white placeholder-slate-500'
|
||
: 'bg-transparent text-gray-800 placeholder-gray-400'
|
||
}`}
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
{/* 智能体列表 */}
|
||
<div className="px-4 pb-4">
|
||
<h3 className={`text-xs font-medium uppercase tracking-wider mb-3 ${isDark ? 'text-slate-500' : 'text-gray-400'}`}>
|
||
智能体列表
|
||
</h3>
|
||
<div className="space-y-2">
|
||
{filteredAgents.map((agent) => (
|
||
<button
|
||
key={agent.id}
|
||
onClick={() => setSelectedAgent(agent)}
|
||
className={`w-full text-left p-3 rounded-lg transition-all ${
|
||
selectedAgent.id === agent.id
|
||
? isDark
|
||
? 'bg-blue-600/20 border border-blue-500/50'
|
||
: 'bg-red-50 border border-red-200'
|
||
: isDark
|
||
? 'bg-slate-700/30 border border-transparent hover:bg-slate-700/50'
|
||
: 'bg-white border border-gray-200 hover:bg-gray-50'
|
||
}`}
|
||
>
|
||
<div className="flex items-center gap-3">
|
||
<div className={`w-10 h-10 rounded-lg flex items-center justify-center ${
|
||
selectedAgent.id === agent.id
|
||
? isDark
|
||
? 'bg-blue-600 text-white'
|
||
: 'bg-red-500 text-white'
|
||
: isDark
|
||
? 'bg-slate-600 text-slate-300'
|
||
: 'bg-gray-100 text-gray-600'
|
||
}`}>
|
||
<Bot 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>
|
||
<ChevronRight className={`w-4 h-4 ${isDark ? 'text-slate-500' : 'text-gray-400'}`} />
|
||
</div>
|
||
</button>
|
||
))}
|
||
</div>
|
||
</div>
|
||
|
||
{/* 当前智能体能力摘要 */}
|
||
<div className={`p-4 border-t ${isDark ? 'border-slate-700/50' : 'border-red-100'}`}>
|
||
<h3 className={`text-xs font-medium uppercase tracking-wider mb-3 ${isDark ? 'text-slate-500' : 'text-gray-400'}`}>
|
||
能力摘要
|
||
</h3>
|
||
|
||
{/* 核心职责 */}
|
||
<div className="mb-4">
|
||
<div className={`flex items-center gap-2 mb-2 ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>
|
||
<Target className="w-4 h-4" />
|
||
<span className="text-xs">核心职责</span>
|
||
</div>
|
||
<p className={`text-sm ${isDark ? 'text-slate-300' : 'text-gray-700'}`}>
|
||
{selectedAgent.description}
|
||
</p>
|
||
</div>
|
||
|
||
{/* 已启用技能 */}
|
||
<div className="mb-4">
|
||
<div className={`flex items-center gap-2 mb-2 ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>
|
||
<Sparkles className="w-4 h-4" />
|
||
<span className="text-xs">已启用技能</span>
|
||
</div>
|
||
<div className="flex flex-wrap gap-1">
|
||
{selectedAgent.skills.map((skill, idx) => (
|
||
<span
|
||
key={idx}
|
||
className={`px-2 py-0.5 rounded text-xs ${
|
||
isDark ? 'bg-blue-600/30 text-blue-400' : 'bg-blue-100 text-blue-600'
|
||
}`}
|
||
>
|
||
{skill}
|
||
</span>
|
||
))}
|
||
</div>
|
||
</div>
|
||
|
||
{/* 可访问数据源 */}
|
||
<div className="mb-4">
|
||
<div className={`flex items-center gap-2 mb-2 ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>
|
||
<Database className="w-4 h-4" />
|
||
<span className="text-xs">可访问数据源</span>
|
||
</div>
|
||
<div className="flex flex-wrap gap-1">
|
||
{selectedAgent.dataSources.map((source, idx) => (
|
||
<span
|
||
key={idx}
|
||
className={`px-2 py-0.5 rounded text-xs ${
|
||
isDark ? 'bg-green-600/30 text-green-400' : 'bg-green-100 text-green-600'
|
||
}`}
|
||
>
|
||
{source}
|
||
</span>
|
||
))}
|
||
</div>
|
||
</div>
|
||
|
||
{/* 可调用功能 */}
|
||
<div>
|
||
<div className={`flex items-center gap-2 mb-2 ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>
|
||
<Layers className="w-4 h-4" />
|
||
<span className="text-xs">可调用功能</span>
|
||
</div>
|
||
<div className="flex flex-wrap gap-1">
|
||
{selectedAgent.functions.map((func, idx) => (
|
||
<span
|
||
key={idx}
|
||
className={`px-2 py-0.5 rounded text-xs ${
|
||
isDark ? 'bg-purple-600/30 text-purple-400' : 'bg-purple-100 text-purple-600'
|
||
}`}
|
||
>
|
||
{func}
|
||
</span>
|
||
))}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* 中间对话区 */}
|
||
<div className="flex-1 flex flex-col overflow-hidden">
|
||
{/* 消息列表 */}
|
||
<div className="flex-1 overflow-y-auto p-4 space-y-4">
|
||
{messages.length === 0 ? (
|
||
<div className={`h-full flex flex-col items-center justify-center ${isDark ? 'text-slate-500' : 'text-gray-400'}`}>
|
||
<Bot className="w-16 h-16 mb-4 opacity-50" />
|
||
<p className="text-lg">开始与{selectedAgent.name}对话</p>
|
||
<p className="text-sm mt-2">基于智能体专业能力获取精准回答</p>
|
||
</div>
|
||
) : (
|
||
messages.map((msg) => (
|
||
<div key={msg.id} className="space-y-3">
|
||
{/* 用户消息 */}
|
||
<div className={`flex gap-3 ${msg.role === 'user' ? 'justify-end' : ''}`}>
|
||
{msg.role === 'assistant' && (
|
||
<div className={`w-8 h-8 rounded-lg flex items-center justify-center flex-shrink-0 ${
|
||
isDark ? 'bg-blue-600/20 text-blue-400' : 'bg-red-100 text-red-500'
|
||
}`}>
|
||
<Bot className="w-4 h-4" />
|
||
</div>
|
||
)}
|
||
<div className={`max-w-[70%] rounded-xl px-4 py-3 ${
|
||
msg.role === 'user'
|
||
? isDark
|
||
? 'bg-blue-600/30 text-white'
|
||
: 'bg-red-500 text-white'
|
||
: isDark
|
||
? 'bg-slate-700/50 text-slate-200'
|
||
: 'bg-gray-100 text-gray-800'
|
||
}`}>
|
||
<p className="whitespace-pre-wrap">{msg.content}</p>
|
||
</div>
|
||
{msg.role === 'user' && (
|
||
<div className={`w-8 h-8 rounded-lg flex items-center justify-center flex-shrink-0 ${
|
||
isDark ? 'bg-slate-700 text-slate-300' : 'bg-gray-200 text-gray-600'
|
||
}`}>
|
||
<div className="w-4 h-4 rounded-full bg-current" />
|
||
</div>
|
||
)}
|
||
</div>
|
||
|
||
{/* 智能体执行详情 */}
|
||
{msg.role === 'assistant' && (
|
||
<div className={`ml-11 p-3 rounded-xl ${isDark ? 'bg-slate-800/50' : 'bg-gray-50'}`}>
|
||
{/* 本轮启用技能 */}
|
||
<div className="mb-3">
|
||
<h4 className={`text-xs font-medium mb-2 ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>
|
||
本轮启用技能
|
||
</h4>
|
||
<div className="flex flex-wrap gap-1">
|
||
{msg.skills?.map((skill, idx) => (
|
||
<span
|
||
key={idx}
|
||
className={`px-2 py-0.5 rounded text-xs ${
|
||
isDark ? 'bg-blue-600/30 text-blue-400' : 'bg-blue-100 text-blue-600'
|
||
}`}
|
||
>
|
||
{skill}
|
||
</span>
|
||
))}
|
||
</div>
|
||
</div>
|
||
|
||
{/* 本轮访问数据源 */}
|
||
<div className="mb-3">
|
||
<h4 className={`text-xs font-medium mb-2 ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>
|
||
本轮访问数据源
|
||
</h4>
|
||
<div className="flex flex-wrap gap-1">
|
||
{msg.dataSources?.map((source, idx) => (
|
||
<span
|
||
key={idx}
|
||
className={`px-2 py-0.5 rounded text-xs ${
|
||
isDark ? 'bg-green-600/30 text-green-400' : 'bg-green-100 text-green-600'
|
||
}`}
|
||
>
|
||
{source}
|
||
</span>
|
||
))}
|
||
</div>
|
||
</div>
|
||
|
||
{/* 本轮调用功能 */}
|
||
<div className="mb-3">
|
||
<h4 className={`text-xs font-medium mb-2 ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>
|
||
本轮调用功能
|
||
</h4>
|
||
<div className="flex flex-wrap gap-1">
|
||
{msg.functions?.map((func, idx) => (
|
||
<span
|
||
key={idx}
|
||
className={`px-2 py-0.5 rounded text-xs ${
|
||
isDark ? 'bg-purple-600/30 text-purple-400' : 'bg-purple-100 text-purple-600'
|
||
}`}
|
||
>
|
||
{func}
|
||
</span>
|
||
))}
|
||
</div>
|
||
</div>
|
||
|
||
{/* 结构化输出 */}
|
||
{msg.structuredOutput && (
|
||
<div>
|
||
<h4 className={`text-xs font-medium mb-2 ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>
|
||
结构化输出
|
||
</h4>
|
||
<div className={`p-3 rounded-lg ${isDark ? 'bg-slate-700/50' : 'bg-white'}`}>
|
||
{Object.entries(msg.structuredOutput).map(([key, value]) => (
|
||
<div key={key} className="flex items-start gap-2 mb-1 last:mb-0">
|
||
<span className={`text-xs font-mono ${isDark ? 'text-blue-400' : 'text-blue-600'}`}>
|
||
{key}:
|
||
</span>
|
||
<span className={`text-xs ${isDark ? 'text-slate-300' : 'text-gray-600'}`}>
|
||
{Array.isArray(value) ? value.join(', ') : String(value)}
|
||
</span>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
)}
|
||
</div>
|
||
)}
|
||
</div>
|
||
))
|
||
)}
|
||
|
||
{isLoading && (
|
||
<div className="flex gap-3">
|
||
<div className={`w-8 h-8 rounded-lg flex items-center justify-center ${
|
||
isDark ? 'bg-blue-600/20 text-blue-400' : 'bg-red-100 text-red-500'
|
||
}`}>
|
||
<Bot className="w-4 h-4" />
|
||
</div>
|
||
<div className={`max-w-[70%] rounded-xl px-4 py-3 ${isDark ? 'bg-slate-700/50' : 'bg-gray-100'}`}>
|
||
<div className="flex gap-1">
|
||
<div className={`w-2 h-2 rounded-full animate-bounce ${isDark ? 'bg-slate-500' : 'bg-gray-400'}`} style={{ animationDelay: '0ms' }} />
|
||
<div className={`w-2 h-2 rounded-full animate-bounce ${isDark ? 'bg-slate-500' : 'bg-gray-400'}`} style={{ animationDelay: '150ms' }} />
|
||
<div className={`w-2 h-2 rounded-full animate-bounce ${isDark ? 'bg-slate-500' : 'bg-gray-400'}`} style={{ animationDelay: '300ms' }} />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
)}
|
||
</div>
|
||
|
||
{/* 底部输入区 */}
|
||
<div className={`border-t p-4 ${isDark ? 'border-slate-700/50' : 'border-red-100'}`}>
|
||
<div className={`flex items-end gap-3 rounded-xl p-3 ${isDark ? 'bg-slate-700/50' : 'bg-gray-100'}`}>
|
||
<textarea
|
||
value={inputValue}
|
||
onChange={(e) => setInputValue(e.target.value)}
|
||
onKeyDown={handleKeyDown}
|
||
placeholder="输入问题或任务要求..."
|
||
rows={1}
|
||
className={`flex-1 bg-transparent resize-none focus:outline-none ${
|
||
isDark ? 'text-white placeholder-slate-500' : 'text-gray-800 placeholder-gray-400'
|
||
}`}
|
||
/>
|
||
|
||
<div className="flex items-center gap-2">
|
||
<button
|
||
onClick={handleSaveRecord}
|
||
className={`p-2 rounded-lg transition-colors ${
|
||
isDark ? 'hover:bg-slate-600 text-slate-400' : 'hover:bg-gray-200 text-gray-500'
|
||
}`}
|
||
title="保存记录"
|
||
>
|
||
<Bookmark className="w-5 h-5" />
|
||
</button>
|
||
|
||
<button
|
||
onClick={handleCollect}
|
||
className={`p-2 rounded-lg transition-colors ${
|
||
isDark ? 'hover:bg-slate-600 text-slate-400' : 'hover:bg-gray-200 text-gray-500'
|
||
}`}
|
||
title="加入收藏"
|
||
>
|
||
<Bookmark className="w-5 h-5" />
|
||
</button>
|
||
|
||
<button
|
||
onClick={handleSend}
|
||
disabled={!inputValue.trim() || isLoading}
|
||
className={`px-4 py-2 rounded-lg font-medium transition-all flex items-center gap-2 ${
|
||
inputValue.trim() && !isLoading
|
||
? isDark
|
||
? 'bg-blue-600 hover:bg-blue-700 text-white'
|
||
: 'bg-red-500 hover:bg-red-600 text-white'
|
||
: isDark
|
||
? 'bg-slate-600 text-slate-400'
|
||
: 'bg-gray-300 text-gray-500'
|
||
}`}
|
||
>
|
||
<Send className="w-4 h-4" />
|
||
发送
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* 右侧执行详情区 */}
|
||
<div className={`w-72 border-l flex-shrink-0 overflow-y-auto p-4 ${
|
||
isDark ? 'border-slate-700/50 bg-slate-800/30' : 'border-red-100 bg-gray-50/50'
|
||
}`}>
|
||
<h3 className={`text-sm font-medium mb-4 ${isDark ? 'text-slate-300' : 'text-gray-700'}`}>
|
||
执行详情
|
||
</h3>
|
||
|
||
{/* 本轮启用技能 */}
|
||
<div className="mb-6">
|
||
<div className={`flex items-center gap-2 mb-3 ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>
|
||
<Sparkles className="w-4 h-4" />
|
||
<span className="text-xs font-medium">本轮启用技能</span>
|
||
</div>
|
||
<div className={`p-3 rounded-xl ${isDark ? 'bg-slate-700/50' : 'bg-white'}`}>
|
||
<div className="space-y-2">
|
||
{selectedAgent.skills.map((skill, idx) => (
|
||
<div key={idx} className="flex items-center gap-2">
|
||
<CheckCircle className={`w-3 h-3 ${isDark ? 'text-blue-400' : 'text-green-500'}`} />
|
||
<span className={`text-sm ${isDark ? 'text-slate-300' : 'text-gray-600'}`}>{skill}</span>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* 本轮访问数据源 */}
|
||
<div className="mb-6">
|
||
<div className={`flex items-center gap-2 mb-3 ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>
|
||
<Database className="w-4 h-4" />
|
||
<span className="text-xs font-medium">本轮访问数据源</span>
|
||
</div>
|
||
<div className={`p-3 rounded-xl ${isDark ? 'bg-slate-700/50' : 'bg-white'}`}>
|
||
<div className="space-y-2">
|
||
{selectedAgent.dataSources.map((source, idx) => (
|
||
<div key={idx} className="flex items-center gap-2">
|
||
<Database className={`w-3 h-3 ${isDark ? 'text-green-400' : 'text-green-500'}`} />
|
||
<span className={`text-sm ${isDark ? 'text-slate-300' : 'text-gray-600'}`}>{source}</span>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* 本轮调用功能 */}
|
||
<div className="mb-6">
|
||
<div className={`flex items-center gap-2 mb-3 ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>
|
||
<Layers className="w-4 h-4" />
|
||
<span className="text-xs font-medium">本轮调用功能</span>
|
||
</div>
|
||
<div className={`p-3 rounded-xl ${isDark ? 'bg-slate-700/50' : 'bg-white'}`}>
|
||
<div className="space-y-2">
|
||
{selectedAgent.functions.map((func, idx) => (
|
||
<div key={idx} className="flex items-center gap-2">
|
||
<Cpu className={`w-3 h-3 ${isDark ? 'text-purple-400' : 'text-purple-500'}`} />
|
||
<span className={`text-sm ${isDark ? 'text-slate-300' : 'text-gray-600'}`}>{func}</span>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* 结构化输出字段 */}
|
||
<div>
|
||
<div className={`flex items-center gap-2 mb-3 ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>
|
||
<FileText className="w-4 h-4" />
|
||
<span className="text-xs font-medium">输出字段</span>
|
||
</div>
|
||
<div className={`p-3 rounded-xl ${isDark ? 'bg-slate-700/50' : 'bg-white'}`}>
|
||
<div className="space-y-2">
|
||
{selectedAgent.outputFields.map((field, idx) => (
|
||
<div key={idx} className="flex items-center gap-2">
|
||
<Zap className={`w-3 h-3 ${isDark ? 'text-yellow-400' : 'text-yellow-500'}`} />
|
||
<span className={`text-xs font-mono ${isDark ? 'text-blue-400' : 'text-blue-600'}`}>{field}</span>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default AgentQA;
|