878 lines
50 KiB
TypeScript
878 lines
50 KiB
TypeScript
import React, { useState } from 'react';
|
||
import { useTheme } from '../contexts/ThemeContext';
|
||
import {
|
||
ArrowLeft,
|
||
Save,
|
||
RotateCcw,
|
||
Power,
|
||
Trash2,
|
||
Copy,
|
||
ChevronDown,
|
||
ChevronRight,
|
||
Bot,
|
||
Target,
|
||
Brain,
|
||
Database,
|
||
Box,
|
||
Route,
|
||
FileOutput,
|
||
Sparkles,
|
||
Lightbulb,
|
||
MessageSquare,
|
||
Play,
|
||
Send,
|
||
Plus,
|
||
X,
|
||
Check,
|
||
AlertCircle,
|
||
Wrench,
|
||
Layers,
|
||
Zap,
|
||
Clock,
|
||
} from 'lucide-react';
|
||
|
||
interface AgentDetailProps {
|
||
agentId: string | null;
|
||
onBack: () => void;
|
||
}
|
||
|
||
interface ExpandedSection {
|
||
basic: boolean;
|
||
responsibility: boolean;
|
||
skills: boolean;
|
||
datasource: boolean;
|
||
function: boolean;
|
||
thinking: boolean;
|
||
output: boolean;
|
||
}
|
||
|
||
const AgentDetail: React.FC<AgentDetailProps> = ({ agentId, onBack }) => {
|
||
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 [isEnabled, setIsEnabled] = useState(true);
|
||
const [expandedSections, setExpandedSections] = useState<ExpandedSection>({
|
||
basic: true,
|
||
responsibility: true,
|
||
skills: true,
|
||
datasource: true,
|
||
function: true,
|
||
thinking: true,
|
||
output: true,
|
||
});
|
||
const [chatMessages, setChatMessages] = useState<{role: 'user' | 'agent'; content: string}[]>([
|
||
{ role: 'agent', content: '核心受众应聚焦18-25岁基层青年群体,原因是该群体社交媒体活跃度高、注重性价比、偏好真实有态度的品牌叙事。' }
|
||
]);
|
||
const [chatInput, setChatInput] = useState('');
|
||
const [aiSuggestion, setAiSuggestion] = useState('');
|
||
const [showGeneratedConfig, setShowGeneratedConfig] = useState(false);
|
||
|
||
const toggleSection = (section: keyof ExpandedSection) => {
|
||
setExpandedSections(prev => ({ ...prev, [section]: !prev[section] }));
|
||
};
|
||
|
||
const skills = [
|
||
{ name: '受众分层', type: '分析类', enabled: true, trigger: '自动', priority: 1 },
|
||
{ name: '核心受众识别', type: '推断类', enabled: true, trigger: '自动', priority: 1 },
|
||
{ name: '受众画像抽取', type: '抽取类', enabled: true, trigger: '条件触发', priority: 2 },
|
||
{ name: '阻力因素提炼', type: '分析类', enabled: true, trigger: '手动', priority: 3 },
|
||
];
|
||
|
||
const dataSources = [
|
||
{ name: '宣传知识库', type: '知识库', status: 'connected', permission: '只读', trigger: '自动', access: '品牌案例、活动方法论、历史策略' },
|
||
{ name: 'Y系统', type: '业务系统', status: 'connected', permission: '只读', trigger: '条件触发', access: '用户标签、传播数据' },
|
||
{ name: 'A系统', type: '业务系统', status: 'disconnected', permission: '无', trigger: '不可用', access: '—' },
|
||
{ name: '市场数据库', type: '外部数据源', status: 'connected', permission: '只读', trigger: '手动', access: '市场报告、用户研究摘要' },
|
||
];
|
||
|
||
const functions = [
|
||
{ name: '信息抽取器', type: '抽取', enabled: true, trigger: '自动', usage: '提取任务中的受众相关信息' },
|
||
{ name: '标签聚类器', type: '分析', enabled: true, trigger: '条件触发', usage: '辅助进行受众分层' },
|
||
{ name: '案例检索器', type: '检索', enabled: true, trigger: '手动', usage: '调用历史案例进行参照' },
|
||
{ name: '结构化输出器', type: '格式化', enabled: true, trigger: '自动', usage: '输出标准JSON字段' },
|
||
];
|
||
|
||
const thinkingSteps = [
|
||
{ step: 1, name: '识别任务中的目标对象', desc: '提取任务中明确或隐含的目标受众信息', required: true, skill: '受众分层', func: '信息抽取器', ds: '无' },
|
||
{ step: 2, name: '判断是否需要分层', desc: '根据任务目标判断是否区分核心/次级/影响者受众', required: true, skill: '核心受众识别', func: '标签聚类器', ds: 'Y系统' },
|
||
{ step: 3, name: '提取核心受众特征', desc: '分析年龄、身份、关切与行为特征', required: true, skill: '画像抽取', func: '结构化输出器', ds: '宣传知识库' },
|
||
{ step: 4, name: '输出结构化结果', desc: '形成标准受众分析输出', required: true, skill: '—', func: '结构化输出器', ds: '—' },
|
||
];
|
||
|
||
const outputFields = [
|
||
{ name: 'core_audience', type: '文本', required: true },
|
||
{ name: 'secondary_audience', type: '文本', required: false },
|
||
{ name: 'key_traits', type: '数组', required: true },
|
||
{ name: 'concerns', type: '数组', required: false },
|
||
{ name: 'barriers', type: '数组', required: false },
|
||
{ name: 'trust_sources', type: '数组', required: false },
|
||
];
|
||
|
||
const aiOptimizations = [
|
||
{ issue: '当前已配置"受众画像抽取"技能,但未配置对应输出字段', canFix: true },
|
||
{ issue: '思考路径中"判断是否需要分层"步骤未绑定功能调用', canFix: true },
|
||
{ issue: '已绑定A系统,但当前无任何步骤使用该数据源', canFix: false },
|
||
];
|
||
|
||
const executionDetails = {
|
||
dataSources: ['宣传知识库', 'Y系统'],
|
||
skills: ['受众分层', '核心受众识别', '画像抽取'],
|
||
functions: ['信息抽取器', '标签聚类器', '结构化输出器'],
|
||
outputs: ['core_audience', 'key_traits', 'barriers'],
|
||
};
|
||
|
||
const handleSendMessage = () => {
|
||
if (chatInput.trim()) {
|
||
setChatMessages([...chatMessages, { role: 'user', content: chatInput }]);
|
||
setChatInput('');
|
||
setTimeout(() => {
|
||
setChatMessages(prev => [...prev, {
|
||
role: 'agent',
|
||
content: '核心受众应聚焦18-25岁基层青年群体,原因是该群体社交媒体活跃度高、注重性价比、偏好真实有态度的品牌叙事。'
|
||
}]);
|
||
}, 1000);
|
||
}
|
||
};
|
||
|
||
const handleGenerateConfig = () => {
|
||
setAiSuggestion('正在分析职责、技能、数据源...');
|
||
setTimeout(() => {
|
||
setShowGeneratedConfig(true);
|
||
setAiSuggestion('');
|
||
}, 1500);
|
||
};
|
||
|
||
const SectionHeader = ({
|
||
title,
|
||
subtitle,
|
||
icon: Icon,
|
||
section,
|
||
children
|
||
}: {
|
||
title: string;
|
||
subtitle: string;
|
||
icon: React.ElementType;
|
||
section: keyof ExpandedSection;
|
||
children: React.ReactNode;
|
||
}) => (
|
||
<div className={`${cardBg} backdrop-blur-xl ${cardBorder} rounded-xl`}>
|
||
<button
|
||
onClick={() => toggleSection(section)}
|
||
className={`w-full flex items-center justify-between p-4 ${isDark ? 'hover:bg-slate-800/50' : 'hover:bg-gray-100'} transition-colors sticky top-0 z-10 ${cardBg} backdrop-blur-xl`}
|
||
>
|
||
<div className="flex items-center gap-3">
|
||
<div className={`w-10 h-10 rounded-lg ${isDark ? 'bg-blue-500/20' : 'bg-red-100'} flex items-center justify-center`}>
|
||
<Icon className={`w-5 h-5 ${isDark ? 'text-blue-400' : 'text-red-500'}`} />
|
||
</div>
|
||
<div className="text-left">
|
||
<h3 className={`${textPrimary} font-semibold`}>{title}</h3>
|
||
<p className={`${textMuted} text-xs`}>{subtitle}</p>
|
||
</div>
|
||
</div>
|
||
{expandedSections[section] ? (
|
||
<ChevronDown className={`w-5 h-5 ${textSecondary}`} />
|
||
) : (
|
||
<ChevronRight className={`w-5 h-5 ${textSecondary}`} />
|
||
)}
|
||
</button>
|
||
{expandedSections[section] && (
|
||
<div className="px-4 pb-4">
|
||
{children}
|
||
</div>
|
||
)}
|
||
</div>
|
||
);
|
||
|
||
return (
|
||
<div className="h-[calc(100vh-140px)] flex flex-col overflow-hidden">
|
||
{/* 顶部操作栏 */}
|
||
<div className={`${cardBg} backdrop-blur-xl ${cardBorder} p-4 flex-shrink-0`}>
|
||
<div className="flex items-center justify-between">
|
||
<div className="flex items-center gap-4">
|
||
<button onClick={onBack} className={`p-2 ${isDark ? 'hover:bg-slate-700/50' : 'hover:bg-gray-200'} rounded-lg transition-colors`}>
|
||
<ArrowLeft className={`w-5 h-5 ${textSecondary}`} />
|
||
</button>
|
||
<div>
|
||
<p className={`${textSecondary} text-xs`}>智能体能力配置</p>
|
||
<div className="flex items-center gap-2 mt-0.5">
|
||
<Bot className={`w-4 h-4 ${isDark ? 'text-blue-400' : 'text-red-500'}`} />
|
||
<span className={`${textPrimary} font-semibold`}>AudienceAgent</span>
|
||
<span className={`px-2 py-0.5 rounded-full text-xs font-medium ${
|
||
isEnabled
|
||
? isDark ? 'bg-green-500/20 text-green-400' : 'bg-green-100 text-green-600'
|
||
: isDark ? 'bg-slate-500/20 text-slate-400' : 'bg-gray-200 text-gray-500'
|
||
}`}>
|
||
{isEnabled ? '启用' : '停用'}
|
||
</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div className="flex items-center gap-2">
|
||
<button className={`flex items-center gap-2 px-4 py-2 ${btnPrimary} text-white rounded-lg text-sm transition-colors`}>
|
||
<Save className="w-4 h-4" />
|
||
保存
|
||
</button>
|
||
<button className={`flex items-center gap-2 px-4 py-2 ${btnSecondary} rounded-lg text-sm transition-colors`}>
|
||
<RotateCcw className="w-4 h-4" />
|
||
重置
|
||
</button>
|
||
<button
|
||
onClick={() => setIsEnabled(!isEnabled)}
|
||
className={`flex items-center gap-2 px-4 py-2 rounded-lg text-sm transition-colors ${
|
||
isEnabled
|
||
? isDark ? 'bg-amber-500/20 hover:bg-amber-500/30 border border-amber-500/30 text-amber-400' : 'bg-amber-100 hover:bg-amber-200 border border-amber-200 text-amber-600'
|
||
: isDark ? 'bg-green-500/20 hover:bg-green-500/30 border border-green-500/30 text-green-400' : 'bg-green-100 hover:bg-green-200 border border-green-200 text-green-600'
|
||
}`}
|
||
>
|
||
<Power className="w-4 h-4" />
|
||
{isEnabled ? '停用' : '启用'}
|
||
</button>
|
||
<button className={`flex items-center gap-2 px-4 py-2 ${btnSecondary} ${isDark ? 'hover:text-red-400' : 'hover:text-red-500'} rounded-lg text-sm transition-colors`}>
|
||
<Trash2 className="w-4 h-4" />
|
||
删除
|
||
</button>
|
||
<button className={`flex items-center gap-2 px-4 py-2 ${btnSecondary} rounded-lg text-sm transition-colors`}>
|
||
<Copy className="w-4 h-4" />
|
||
复制
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* 主内容区:三栏布局 */}
|
||
<div className="flex-1 grid grid-cols-12 gap-4 mt-4 min-h-0">
|
||
{/* 左侧主配置区 (65%) - 带自定义滚动条 */}
|
||
<div className="col-span-8 flex flex-col gap-4 h-full overflow-y-auto scrollbar-thin scrollbar-thumb-slate-600 scrollbar-track-transparent hover:scrollbar-thumb-slate-500">
|
||
{/* 模块1:基本信息 */}
|
||
<SectionHeader
|
||
title="基本信息"
|
||
subtitle="定义智能体的基本身份、用途和交互属性"
|
||
icon={Bot}
|
||
section="basic"
|
||
>
|
||
<div className="space-y-4 pt-2">
|
||
<div className="grid grid-cols-2 gap-4">
|
||
<div>
|
||
<label className={`block ${textSecondary} text-sm mb-2`}>智能体名称</label>
|
||
<input
|
||
type="text"
|
||
defaultValue="AudienceAgent"
|
||
className={`w-full px-4 py-2.5 ${inputBg} ${inputBorder} rounded-lg ${textPrimary} text-sm focus:outline-none ${isDark ? 'focus:border-blue-500/50' : 'focus:border-red-400'}`}
|
||
/>
|
||
</div>
|
||
<div>
|
||
<label className={`block ${textSecondary} text-sm mb-2`}>智能体编码</label>
|
||
<input
|
||
type="text"
|
||
defaultValue="AGENT_AUDIENCE_001"
|
||
className={`w-full px-4 py-2.5 ${inputBg} ${inputBorder} rounded-lg ${textPrimary} text-sm focus:outline-none ${isDark ? 'focus:border-blue-500/50' : 'focus:border-red-400'}`}
|
||
/>
|
||
</div>
|
||
</div>
|
||
<div className="grid grid-cols-2 gap-4">
|
||
<div>
|
||
<label className={`block ${textSecondary} text-sm mb-2`}>智能体分类</label>
|
||
<select className={`w-full px-4 py-2.5 ${inputBg} ${inputBorder} rounded-lg ${textPrimary} text-sm focus:outline-none ${isDark ? 'focus:border-blue-500/50' : 'focus:border-red-400'}`}>
|
||
<option>分析类</option>
|
||
<option>编排类</option>
|
||
<option>叙事类</option>
|
||
<option>校验类</option>
|
||
<option>成稿类</option>
|
||
</select>
|
||
</div>
|
||
<div>
|
||
<label className={`block ${textSecondary} text-sm mb-2`}>默认交互模式</label>
|
||
<select className={`w-full px-4 py-2.5 ${inputBg} ${inputBorder} rounded-lg ${textPrimary} text-sm focus:outline-none ${isDark ? 'focus:border-blue-500/50' : 'focus:border-red-400'}`}>
|
||
<option>分析式</option>
|
||
<option>对话式</option>
|
||
<option>指令式</option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<label className={`block ${textSecondary} text-sm mb-2`}>智能体说明</label>
|
||
<textarea
|
||
rows={2}
|
||
defaultValue="负责分析核心受众特征,输出受众画像和行为特征,为后续策略制定提供数据支持"
|
||
className={`w-full px-4 py-2.5 ${inputBg} ${inputBorder} rounded-lg ${textPrimary} text-sm focus:outline-none ${isDark ? 'focus:border-blue-500/50' : 'focus:border-red-400'} resize-none`}
|
||
/>
|
||
</div>
|
||
<div className="grid grid-cols-2 gap-4">
|
||
<div>
|
||
<label className={`block ${textSecondary} text-sm mb-2`}>专业标签</label>
|
||
<div className={`flex flex-wrap gap-2 p-3 ${inputBg} ${inputBorder} rounded-lg min-h-[46px]`}>
|
||
{['受众分析', '用户画像', '分层识别'].map((tag) => (
|
||
<span key={tag} className={`px-2 py-1 ${isDark ? 'bg-blue-500/20 text-blue-400' : 'bg-red-100 text-red-600'} rounded text-xs flex items-center gap-1`}>
|
||
{tag}
|
||
<button className={`hover:${isDark ? 'text-blue-300' : 'text-red-400'}`}><X className="w-3 h-3" /></button>
|
||
</span>
|
||
))}
|
||
<button className={`px-2 py-1 ${textSecondary} hover:${textPrimary} text-xs flex items-center gap-1`}>
|
||
<Plus className="w-3 h-3" /> 添加
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<label className={`block ${textSecondary} text-sm mb-2`}>适用任务关键词</label>
|
||
<div className={`flex flex-wrap gap-2 p-3 ${inputBg} ${inputBorder} rounded-lg min-h-[46px]`}>
|
||
{['宣传对象分析', '核心人群识别'].map((tag) => (
|
||
<span key={tag} className={`px-2 py-1 ${isDark ? 'bg-cyan-500/20 text-cyan-400' : 'bg-orange-100 text-orange-600'} rounded text-xs flex items-center gap-1`}>
|
||
{tag}
|
||
<button className={`hover:${isDark ? 'text-cyan-300' : 'text-orange-400'}`}><X className="w-3 h-3" /></button>
|
||
</span>
|
||
))}
|
||
<button className={`px-2 py-1 ${textSecondary} hover:${textPrimary} text-xs flex items-center gap-1`}>
|
||
<Plus className="w-3 h-3" /> 添加
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div className={`flex items-center gap-6 pt-2 border-t ${cardBorder}`}>
|
||
<div className="flex items-center gap-3">
|
||
<span className={`${textSecondary} text-sm`}>支持单独问答</span>
|
||
<label className="relative inline-flex items-center cursor-pointer">
|
||
<input type="checkbox" className="sr-only peer" defaultChecked />
|
||
<div className={`w-11 h-6 ${isDark ? 'bg-slate-700' : 'bg-gray-300'} peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all ${isDark ? 'peer-checked:bg-blue-600' : 'peer-checked:bg-red-500'}`}></div>
|
||
</label>
|
||
</div>
|
||
<div className="flex items-center gap-3">
|
||
<span className={`${textSecondary} text-sm`}>支持单独任务执行</span>
|
||
<label className="relative inline-flex items-center cursor-pointer">
|
||
<input type="checkbox" className="sr-only peer" defaultChecked />
|
||
<div className={`w-11 h-6 ${isDark ? 'bg-slate-700' : 'bg-gray-300'} peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all ${isDark ? 'peer-checked:bg-blue-600' : 'peer-checked:bg-red-500'}`}></div>
|
||
</label>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</SectionHeader>
|
||
|
||
{/* 模块2:职责与边界 */}
|
||
<SectionHeader
|
||
title="职责与边界"
|
||
subtitle="明确智能体的工作范围、边界与禁止事项"
|
||
icon={Target}
|
||
section="responsibility"
|
||
>
|
||
<div className="space-y-4 pt-2">
|
||
<div className="grid grid-cols-2 gap-4">
|
||
<div>
|
||
<label className={`block ${textSecondary} text-sm mb-2`}>核心职责</label>
|
||
<textarea
|
||
rows={3}
|
||
defaultValue="识别任务中的关键受众群体,对受众进行分层,并提炼特征、关切与阻力,形成完整的受众画像报告。"
|
||
className={`w-full px-4 py-2.5 ${inputBg} ${inputBorder} rounded-lg ${textPrimary} text-sm focus:outline-none ${isDark ? 'focus:border-blue-500/50' : 'focus:border-red-400'} resize-none`}
|
||
/>
|
||
</div>
|
||
<div>
|
||
<label className={`block ${textSecondary} text-sm mb-2`}>职责边界</label>
|
||
<textarea
|
||
rows={3}
|
||
defaultValue="不直接生成叙事方案;不负责风险最终审核;不替代行为分析;不在缺少依据时擅自扩大受众范围。"
|
||
className={`w-full px-4 py-2.5 ${inputBg} ${inputBorder} rounded-lg ${textPrimary} text-sm focus:outline-none ${isDark ? 'focus:border-blue-500/50' : 'focus:border-red-400'} resize-none`}
|
||
/>
|
||
</div>
|
||
</div>
|
||
<div className="grid grid-cols-2 gap-4">
|
||
<div>
|
||
<label className={`block ${textSecondary} text-sm mb-2`}>禁止事项</label>
|
||
<textarea
|
||
rows={2}
|
||
defaultValue="不得在缺少依据时擅自扩大受众范围;不得输出与任务无关的人群判断;不得更改任务目标。"
|
||
className={`w-full px-4 py-2.5 ${inputBg} ${inputBorder} rounded-lg ${textPrimary} text-sm focus:outline-none ${isDark ? 'focus:border-blue-500/50' : 'focus:border-red-400'} resize-none`}
|
||
/>
|
||
</div>
|
||
<div>
|
||
<label className={`block ${textSecondary} text-sm mb-2`}>典型任务</label>
|
||
<textarea
|
||
rows={2}
|
||
defaultValue="分析某宣传任务的核心受众是谁;输出受众画像;识别影响者与阻力群体;提炼受众关切与信任来源。"
|
||
className={`w-full px-4 py-2.5 ${inputBg} ${inputBorder} rounded-lg ${textPrimary} text-sm focus:outline-none ${isDark ? 'focus:border-blue-500/50' : 'focus:border-red-400'} resize-none`}
|
||
/>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<label className={`block ${textSecondary} text-sm mb-2`}>不处理的问题</label>
|
||
<textarea
|
||
rows={2}
|
||
defaultValue="不负责撰写传播文案;不负责渠道投放建议;不生成具体执行方案;不进行风险评估。"
|
||
className={`w-full px-4 py-2.5 ${inputBg} ${inputBorder} rounded-lg ${textPrimary} text-sm focus:outline-none ${isDark ? 'focus:border-blue-500/50' : 'focus:border-red-400'} resize-none`}
|
||
/>
|
||
</div>
|
||
<div className={`flex items-center gap-2 pt-2 border-t ${cardBorder}`}>
|
||
<button className={`flex items-center gap-2 px-3 py-1.5 ${isDark ? 'bg-blue-500/20 hover:bg-blue-500/30 border border-blue-500/30 text-blue-400' : 'bg-red-100 hover:bg-red-200 border border-red-200 text-red-600'} rounded-lg text-xs transition-colors`}>
|
||
<Sparkles className="w-3 h-3" /> AI生成职责
|
||
</button>
|
||
<button className={`flex items-center gap-2 px-3 py-1.5 ${btnSecondary} rounded-lg text-xs transition-colors`}>
|
||
<Lightbulb className="w-3 h-3" /> AI补全边界
|
||
</button>
|
||
<button className={`flex items-center gap-2 px-3 py-1.5 ${btnSecondary} rounded-lg text-xs transition-colors`}>
|
||
<AlertCircle className="w-3 h-3" /> AI发现冲突
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</SectionHeader>
|
||
|
||
{/* 模块3:技能配置 */}
|
||
<SectionHeader
|
||
title="技能配置"
|
||
subtitle="定义智能体当前启用的技能及其触发方式"
|
||
icon={Layers}
|
||
section="skills"
|
||
>
|
||
<div className="space-y-3 pt-2">
|
||
{skills.map((skill, index) => (
|
||
<div key={index} className={`p-3 ${inputBg} ${inputBorder} rounded-lg`}>
|
||
<div className="flex items-center justify-between">
|
||
<div className="flex items-center gap-3">
|
||
<div className={`w-8 h-8 rounded ${isDark ? 'bg-purple-500/20' : 'bg-purple-100'} flex items-center justify-center`}>
|
||
<Brain className={`w-4 h-4 ${isDark ? 'text-purple-400' : 'text-purple-600'}`} />
|
||
</div>
|
||
<div>
|
||
<p className={`${textPrimary} text-sm font-medium`}>{skill.name}</p>
|
||
<p className={`${textMuted} text-xs`}>类型:{skill.type} · 触发:{skill.trigger} · 优先级:{skill.priority}</p>
|
||
</div>
|
||
</div>
|
||
<div className="flex items-center gap-2">
|
||
<button className={`p-1.5 ${isDark ? 'hover:bg-slate-700/50' : 'hover:bg-gray-200'} rounded transition-colors`}>
|
||
<Wrench className={`w-4 h-4 ${textSecondary}`} />
|
||
</button>
|
||
<label className="relative inline-flex items-center cursor-pointer">
|
||
<input type="checkbox" className="sr-only peer" defaultChecked={skill.enabled} />
|
||
<div className={`w-9 h-5 ${isDark ? 'bg-slate-700' : 'bg-gray-300'} peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all ${isDark ? 'peer-checked:bg-green-600' : 'peer-checked:bg-green-500'}`}></div>
|
||
</label>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
))}
|
||
<div className={`flex items-center gap-2 pt-2 border-t ${cardBorder}`}>
|
||
<button className={`flex items-center gap-2 px-3 py-1.5 ${btnSecondary} rounded-lg text-xs transition-colors`}>
|
||
<Plus className="w-3 h-3" /> 新增Skill
|
||
</button>
|
||
<button className={`flex items-center gap-2 px-3 py-1.5 ${isDark ? 'bg-blue-500/20 hover:bg-blue-500/30 border border-blue-500/30 text-blue-400' : 'bg-red-100 hover:bg-red-200 border border-red-200 text-red-600'} rounded-lg text-xs transition-colors`}>
|
||
<Sparkles className="w-3 h-3" /> AI推荐Skill
|
||
</button>
|
||
<button className={`flex items-center gap-2 px-3 py-1.5 ${btnSecondary} rounded-lg text-xs transition-colors`}>
|
||
<Zap className="w-3 h-3" /> AI生成技能组
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</SectionHeader>
|
||
|
||
{/* 模块4:数据源访问 */}
|
||
<SectionHeader
|
||
title="数据源访问"
|
||
subtitle="定义智能体可读取的知识与系统数据"
|
||
icon={Database}
|
||
section="datasource"
|
||
>
|
||
<div className="space-y-3 pt-2">
|
||
{dataSources.map((ds, index) => (
|
||
<div key={index} className={`p-3 ${inputBg} ${inputBorder} rounded-lg`}>
|
||
<div className="flex items-center justify-between">
|
||
<div className="flex items-center gap-3">
|
||
<div className={`w-8 h-8 rounded flex items-center justify-center ${
|
||
ds.status === 'connected' ? (isDark ? 'bg-green-500/20' : 'bg-green-100') : (isDark ? 'bg-slate-500/20' : 'bg-gray-200')
|
||
}`}>
|
||
<Database className={`w-4 h-4 ${ds.status === 'connected' ? (isDark ? 'text-green-400' : 'text-green-600') : textSecondary}`} />
|
||
</div>
|
||
<div>
|
||
<p className={`${textPrimary} text-sm font-medium`}>{ds.name}</p>
|
||
<p className={`${textMuted} text-xs`}>类型:{ds.type} · 权限:{ds.permission} · 调用:{ds.trigger}</p>
|
||
</div>
|
||
</div>
|
||
<span className={`px-2 py-0.5 rounded text-xs ${
|
||
ds.status === 'connected'
|
||
? isDark ? 'bg-green-500/20 text-green-400' : 'bg-green-100 text-green-600'
|
||
: isDark ? 'bg-slate-500/20 text-slate-400' : 'bg-gray-200 text-gray-500'
|
||
}`}>
|
||
{ds.status === 'connected' ? '已连接' : '未连接'}
|
||
</span>
|
||
</div>
|
||
<p className={`${textSecondary} text-xs mt-2`}>可访问:{ds.access}</p>
|
||
</div>
|
||
))}
|
||
<div className={`flex items-center gap-2 pt-2 border-t ${cardBorder}`}>
|
||
<button className={`flex items-center gap-2 px-3 py-1.5 ${btnSecondary} rounded-lg text-xs transition-colors`}>
|
||
<Plus className="w-3 h-3" /> 绑定数据源
|
||
</button>
|
||
<button className={`flex items-center gap-2 px-3 py-1.5 ${isDark ? 'bg-blue-500/20 hover:bg-blue-500/30 border border-blue-500/30 text-blue-400' : 'bg-red-100 hover:bg-red-200 border border-red-200 text-red-600'} rounded-lg text-xs transition-colors`}>
|
||
<Sparkles className="w-3 h-3" /> AI推荐数据源
|
||
</button>
|
||
<button className={`flex items-center gap-2 px-3 py-1.5 ${btnSecondary} rounded-lg text-xs transition-colors`}>
|
||
<AlertCircle className="w-3 h-3" /> AI识别缺失
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</SectionHeader>
|
||
|
||
{/* 模块5:功能调用 */}
|
||
<SectionHeader
|
||
title="功能调用"
|
||
subtitle="定义智能体可调配的处理功能与工具能力"
|
||
icon={Box}
|
||
section="function"
|
||
>
|
||
<div className="space-y-3 pt-2">
|
||
{functions.map((func, index) => (
|
||
<div key={index} className={`p-3 ${inputBg} ${inputBorder} rounded-lg`}>
|
||
<div className="flex items-center justify-between">
|
||
<div className="flex items-center gap-3">
|
||
<div className={`w-8 h-8 rounded ${isDark ? 'bg-cyan-500/20' : 'bg-cyan-100'} flex items-center justify-center`}>
|
||
<Box className={`w-4 h-4 ${isDark ? 'text-cyan-400' : 'text-cyan-600'}`} />
|
||
</div>
|
||
<div>
|
||
<p className={`${textPrimary} text-sm font-medium`}>{func.name}</p>
|
||
<p className={`${textMuted} text-xs`}>类型:{func.type} · 调用:{func.trigger}</p>
|
||
</div>
|
||
</div>
|
||
<label className="relative inline-flex items-center cursor-pointer">
|
||
<input type="checkbox" className="sr-only peer" defaultChecked={func.enabled} />
|
||
<div className={`w-9 h-5 ${isDark ? 'bg-slate-700' : 'bg-gray-300'} peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all ${isDark ? 'peer-checked:bg-green-600' : 'peer-checked:bg-green-500'}`}></div>
|
||
</label>
|
||
</div>
|
||
<p className={`${textSecondary} text-xs mt-2`}>用途:{func.usage}</p>
|
||
</div>
|
||
))}
|
||
<div className={`flex items-center gap-2 pt-2 border-t ${cardBorder}`}>
|
||
<button className={`flex items-center gap-2 px-3 py-1.5 ${btnSecondary} rounded-lg text-xs transition-colors`}>
|
||
<Plus className="w-3 h-3" /> 新增功能
|
||
</button>
|
||
<button className={`flex items-center gap-2 px-3 py-1.5 ${isDark ? 'bg-blue-500/20 hover:bg-blue-500/30 border border-blue-500/30 text-blue-400' : 'bg-red-100 hover:bg-red-200 border border-red-200 text-red-600'} rounded-lg text-xs transition-colors`}>
|
||
<Sparkles className="w-3 h-3" /> AI推荐功能
|
||
</button>
|
||
<button className={`flex items-center gap-2 px-3 py-1.5 ${btnSecondary} rounded-lg text-xs transition-colors`}>
|
||
<Zap className="w-3 h-3" /> AI检查冗余
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</SectionHeader>
|
||
|
||
{/* 模块6:思考路径 */}
|
||
<SectionHeader
|
||
title="思考路径"
|
||
subtitle="定义智能体处理任务时的默认分析顺序"
|
||
icon={Route}
|
||
section="thinking"
|
||
>
|
||
<div className="space-y-3 pt-2">
|
||
{thinkingSteps.map((step) => (
|
||
<div key={step.step} className={`p-3 ${inputBg} ${inputBorder} rounded-lg`}>
|
||
<div className="flex items-start gap-3">
|
||
<div className={`w-6 h-6 rounded-full flex items-center justify-center text-xs font-bold flex-shrink-0 mt-0.5 ${
|
||
step.step <= 2
|
||
? isDark ? 'bg-green-500 text-white' : 'bg-green-500 text-white'
|
||
: isDark ? 'bg-blue-500 text-white' : 'bg-blue-500 text-white'
|
||
}`}>
|
||
{step.step}
|
||
</div>
|
||
<div className="flex-1">
|
||
<div className="flex items-center justify-between">
|
||
<p className={`${textPrimary} text-sm font-medium`}>{step.name}</p>
|
||
{step.required && (
|
||
<span className={`px-1.5 py-0.5 ${isDark ? 'bg-red-500/20 text-red-400' : 'bg-red-100 text-red-600'} rounded text-[10px]`}>必选</span>
|
||
)}
|
||
</div>
|
||
<p className={`${textSecondary} text-xs mt-1`}>{step.desc}</p>
|
||
<div className="flex items-center gap-4 mt-2 text-xs">
|
||
<span className={`${textMuted}`}>Skill: <span className={isDark ? 'text-purple-400' : 'text-purple-600'}>{step.skill}</span></span>
|
||
<span className={`${textMuted}`}>功能: <span className={isDark ? 'text-cyan-400' : 'text-cyan-600'}>{step.func}</span></span>
|
||
<span className={`${textMuted}`}>数据源: <span className={isDark ? 'text-green-400' : 'text-green-600'}>{step.ds}</span></span>
|
||
</div>
|
||
</div>
|
||
<button className={`p-1.5 ${isDark ? 'hover:bg-slate-700/50' : 'hover:bg-gray-200'} rounded transition-colors`}>
|
||
<Wrench className={`w-4 h-4 ${textSecondary}`} />
|
||
</button>
|
||
</div>
|
||
</div>
|
||
))}
|
||
<div className={`flex items-center gap-2 pt-2 border-t ${cardBorder}`}>
|
||
<button className={`flex items-center gap-2 px-3 py-1.5 ${btnSecondary} rounded-lg text-xs transition-colors`}>
|
||
<Plus className="w-3 h-3" /> 新增步骤
|
||
</button>
|
||
<button className={`flex items-center gap-2 px-3 py-1.5 ${isDark ? 'bg-blue-500/20 hover:bg-blue-500/30 border border-blue-500/30 text-blue-400' : 'bg-red-100 hover:bg-red-200 border border-red-200 text-red-600'} rounded-lg text-xs transition-colors`}>
|
||
<Sparkles className="w-3 h-3" /> AI生成思考路径
|
||
</button>
|
||
<button className={`flex items-center gap-2 px-3 py-1.5 ${btnSecondary} rounded-lg text-xs transition-colors`}>
|
||
<Route className="w-3 h-3" /> AI优化顺序
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</SectionHeader>
|
||
|
||
{/* 模块7:输出结构 */}
|
||
<SectionHeader
|
||
title="输出结构"
|
||
subtitle="定义对话输出、结构化输出与可复用片段"
|
||
icon={FileOutput}
|
||
section="output"
|
||
>
|
||
<div className="space-y-4 pt-2">
|
||
<div className={`p-3 ${isDark ? 'bg-blue-500/10 border border-blue-500/30' : 'bg-red-50 border border-red-200'} rounded-lg`}>
|
||
<p className={`${isDark ? 'text-blue-400' : 'text-red-600'} text-sm font-medium mb-2`}>A. 对话摘要输出</p>
|
||
<p className={`${textSecondary} text-xs`}>核心受众结论 · 结论理由摘要</p>
|
||
</div>
|
||
<div>
|
||
<p className={`${isDark ? 'text-cyan-400' : 'text-orange-600'} text-sm font-medium mb-3`}>B. 结构化输出字段</p>
|
||
<div className="space-y-2">
|
||
{outputFields.map((field, index) => (
|
||
<div key={index} className={`flex items-center gap-3 p-2 ${inputBg} ${inputBorder} rounded-lg`}>
|
||
<input
|
||
type="text"
|
||
defaultValue={field.name}
|
||
className={`flex-1 px-3 py-1.5 ${isDark ? 'bg-slate-800/50' : 'bg-white'} ${inputBorder} rounded ${isDark ? 'text-cyan-400' : 'text-orange-600'} text-sm font-mono focus:outline-none ${isDark ? 'focus:border-blue-500/50' : 'focus:border-red-400'}`}
|
||
/>
|
||
<select className={`px-3 py-1.5 ${isDark ? 'bg-slate-800/50' : 'bg-white'} ${inputBorder} rounded ${textPrimary} text-xs`}>
|
||
<option selected={field.type === '文本'}>文本</option>
|
||
<option selected={field.type === '数组'}>数组</option>
|
||
<option>对象</option>
|
||
</select>
|
||
<label className="flex items-center gap-2 cursor-pointer">
|
||
<span className={`${textSecondary} text-xs`}>{field.required ? '必填' : '可选'}</span>
|
||
<input type="checkbox" className="sr-only peer" defaultChecked={field.required} />
|
||
<div className={`w-9 h-5 ${isDark ? 'bg-slate-700' : 'bg-gray-300'} peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all ${isDark ? 'peer-checked:bg-blue-600' : 'peer-checked:bg-red-500'}`}></div>
|
||
</label>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
<div className={`p-3 ${inputBg} ${inputBorder} rounded-lg`}>
|
||
<p className={`${isDark ? 'text-green-400' : 'text-green-600'} text-sm font-medium mb-2`}>C. 报告片段输出</p>
|
||
<div className="space-y-2">
|
||
<div>
|
||
<label className={`${textMuted} text-xs`}>字段名</label>
|
||
<input
|
||
type="text"
|
||
defaultValue="audience_analysis_paragraph"
|
||
className={`w-full px-3 py-1.5 ${isDark ? 'bg-slate-800/50' : 'bg-white'} ${inputBorder} rounded ${isDark ? 'text-cyan-400' : 'text-orange-600'} text-sm font-mono focus:outline-none ${isDark ? 'focus:border-blue-500/50' : 'focus:border-red-400'}`}
|
||
/>
|
||
</div>
|
||
<div>
|
||
<label className={`${textMuted} text-xs`}>用途说明</label>
|
||
<input
|
||
type="text"
|
||
defaultValue={'用于写入正式方案中的"受众分析"段落'}
|
||
className={`w-full px-3 py-1.5 ${isDark ? 'bg-slate-800/50' : 'bg-white'} ${inputBorder} rounded ${textPrimary} text-sm focus:outline-none ${isDark ? 'focus:border-blue-500/50' : 'focus:border-red-400'}`}
|
||
/>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div className={`flex items-center gap-2 pt-2 border-t ${cardBorder}`}>
|
||
<button className={`flex items-center gap-2 px-3 py-1.5 ${isDark ? 'bg-blue-500/20 hover:bg-blue-500/30 border border-blue-500/30 text-blue-400' : 'bg-red-100 hover:bg-red-200 border border-red-200 text-red-600'} rounded-lg text-xs transition-colors`}>
|
||
<Sparkles className="w-3 h-3" /> AI生成输出字段
|
||
</button>
|
||
<button className={`flex items-center gap-2 px-3 py-1.5 ${btnSecondary} rounded-lg text-xs transition-colors`}>
|
||
<Lightbulb className="w-3 h-3" /> AI补全字段说明
|
||
</button>
|
||
<button className={`flex items-center gap-2 px-3 py-1.5 ${btnSecondary} rounded-lg text-xs transition-colors`}>
|
||
<Check className="w-3 h-3" /> AI校验完整性
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</SectionHeader>
|
||
</div>
|
||
|
||
{/* 右侧辅助区 (35%) */}
|
||
<div className="col-span-4 flex flex-col gap-4 min-h-0 overflow-y-auto pl-2">
|
||
{/* 卡片1:AI辅助生成 */}
|
||
<div className={`${isDark ? 'bg-gradient-to-br from-purple-600/20 to-blue-600/20' : 'bg-gradient-to-br from-purple-100 to-blue-100'} backdrop-blur-xl ${isDark ? 'border border-purple-500/30' : 'border border-purple-300'} rounded-xl p-4`}>
|
||
<h3 className={`${textPrimary} font-semibold mb-3 flex items-center gap-2`}>
|
||
<Sparkles className={`w-4 h-4 ${isDark ? 'text-purple-400' : 'text-purple-600'}`} />
|
||
AI辅助生成
|
||
</h3>
|
||
<div className="space-y-3">
|
||
<div>
|
||
<label className={`block ${textSecondary} text-xs mb-1.5`}>一句话描述</label>
|
||
<textarea
|
||
rows={2}
|
||
placeholder="例如:这是一个负责识别宣传任务核心受众并输出画像的分析型智能体..."
|
||
className={`w-full px-3 py-2 ${inputBg} ${isDark ? 'border-purple-500/30' : 'border-purple-300'} rounded-lg ${textPrimary} text-xs focus:outline-none ${isDark ? 'focus:border-purple-500/50' : 'focus:border-purple-400'} resize-none`}
|
||
/>
|
||
</div>
|
||
<div>
|
||
<label className={`block ${textSecondary} text-xs mb-1.5`}>示例任务</label>
|
||
<textarea
|
||
rows={2}
|
||
placeholder="例如:请分析某青年节宣传活动的核心受众、次级受众及其主要关切..."
|
||
className={`w-full px-3 py-2 ${inputBg} ${isDark ? 'border-purple-500/30' : 'border-purple-300'} rounded-lg ${textPrimary} text-xs focus:outline-none ${isDark ? 'focus:border-purple-500/50' : 'focus:border-purple-400'} resize-none`}
|
||
/>
|
||
</div>
|
||
<button
|
||
onClick={handleGenerateConfig}
|
||
className={`w-full px-4 py-2 ${isDark ? 'bg-purple-600 hover:bg-purple-500' : 'bg-purple-500 hover:bg-purple-400'} text-white rounded-lg text-sm font-medium transition-colors flex items-center justify-center gap-2`}
|
||
>
|
||
<Zap className="w-4 h-4" />
|
||
一键生成配置
|
||
</button>
|
||
{showGeneratedConfig && (
|
||
<div className={`p-3 ${inputBg} ${isDark ? 'border-purple-500/30' : 'border-purple-300'} rounded-lg space-y-2`}>
|
||
<p className={`${isDark ? 'text-purple-400' : 'text-purple-600'} text-xs font-medium`}>生成建议:</p>
|
||
<div className={`space-y-1 text-xs ${isDark ? 'text-slate-300' : 'text-gray-700'}`}>
|
||
<p>• 推荐职责:受众识别与画像输出</p>
|
||
<p>• 推荐技能:分层识别、特征抽取</p>
|
||
<p>• 推荐数据源:Y系统、宣传知识库</p>
|
||
<p>• 推荐思考路径:4步法</p>
|
||
</div>
|
||
<div className={`flex items-center gap-2 pt-2 border-t ${isDark ? 'border-purple-500/30' : 'border-purple-300'}`}>
|
||
<button className={`flex-1 px-3 py-1.5 ${isDark ? 'bg-green-600 hover:bg-green-500' : 'bg-green-500 hover:bg-green-400'} text-white rounded text-xs transition-colors`}>
|
||
采纳全部
|
||
</button>
|
||
<button className={`flex-1 px-3 py-1.5 ${btnSecondary} rounded text-xs transition-colors`}>
|
||
逐项插入
|
||
</button>
|
||
<button className={`px-3 py-1.5 ${btnSecondary} rounded text-xs transition-colors`}>
|
||
忽略
|
||
</button>
|
||
</div>
|
||
</div>
|
||
)}
|
||
</div>
|
||
</div>
|
||
|
||
{/* 卡片2:AI优化建议 */}
|
||
<div className={`${cardBg} backdrop-blur-xl ${cardBorder} rounded-xl p-4`}>
|
||
<h3 className={`${textPrimary} font-semibold mb-3 flex items-center gap-2`}>
|
||
<Lightbulb className={`w-4 h-4 ${isDark ? 'text-yellow-400' : 'text-yellow-500'}`} />
|
||
AI优化建议
|
||
</h3>
|
||
<div className="space-y-3">
|
||
{aiOptimizations.map((opt, index) => (
|
||
<div key={index} className={`p-2 ${isDark ? 'bg-amber-500/10 border border-amber-500/30' : 'bg-amber-50 border border-amber-200'} rounded-lg`}>
|
||
<p className={`${isDark ? 'text-slate-300' : 'text-gray-700'} text-xs mb-2`}>{opt.issue}</p>
|
||
<div className="flex items-center gap-2">
|
||
{opt.canFix && (
|
||
<button className={`px-2 py-1 ${btnPrimary} text-white rounded text-xs transition-colors`}>
|
||
一键修复
|
||
</button>
|
||
)}
|
||
<button className={`px-2 py-1 ${btnSecondary} rounded text-xs transition-colors`}>
|
||
忽略
|
||
</button>
|
||
</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
|
||
{/* 卡片3:对话试用 */}
|
||
<div className={`${cardBg} backdrop-blur-xl ${cardBorder} rounded-xl p-4 flex flex-col`}>
|
||
<h3 className={`${textPrimary} font-semibold mb-3 flex items-center gap-2`}>
|
||
<MessageSquare className={`w-4 h-4 ${isDark ? 'text-cyan-400' : 'text-cyan-600'}`} />
|
||
对话试用
|
||
</h3>
|
||
<div className="flex items-center gap-3 mb-3">
|
||
<div className="flex-1">
|
||
<label className={`${textMuted} text-xs mb-1`}>模式</label>
|
||
<select className={`w-full px-2 py-1.5 ${inputBg} ${inputBorder} rounded ${textPrimary} text-xs`}>
|
||
<option>问答</option>
|
||
<option>任务</option>
|
||
</select>
|
||
</div>
|
||
<div className="flex items-center gap-1">
|
||
<span className={`${textSecondary} text-xs`}>数据源</span>
|
||
<label className="relative inline-flex items-center cursor-pointer mx-1">
|
||
<input type="checkbox" className="sr-only peer" defaultChecked />
|
||
<div className={`w-9 h-5 ${isDark ? 'bg-slate-700' : 'bg-gray-300'} peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all ${isDark ? 'peer-checked:bg-green-600' : 'peer-checked:bg-green-500'}`}></div>
|
||
</label>
|
||
</div>
|
||
<div className="flex items-center gap-1">
|
||
<span className={`${textSecondary} text-xs`}>功能</span>
|
||
<label className="relative inline-flex items-center cursor-pointer mx-1">
|
||
<input type="checkbox" className="sr-only peer" defaultChecked />
|
||
<div className={`w-9 h-5 ${isDark ? 'bg-slate-700' : 'bg-gray-300'} peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all ${isDark ? 'peer-checked:bg-green-600' : 'peer-checked:bg-green-500'}`}></div>
|
||
</label>
|
||
</div>
|
||
</div>
|
||
<div className={`flex-1 min-h-[180px] max-h-[180px] overflow-y-auto p-3 ${inputBg} ${inputBorder} rounded-lg mb-3 space-y-3`}>
|
||
{chatMessages.map((msg, index) => (
|
||
<div key={index} className={`flex ${msg.role === 'user' ? 'justify-end' : 'justify-start'}`}>
|
||
<div className={`max-w-[85%] p-2.5 rounded-lg text-xs ${
|
||
msg.role === 'user'
|
||
? isDark ? 'bg-blue-600 text-white' : 'bg-red-500 text-white'
|
||
: isDark ? 'bg-slate-800 text-slate-300' : 'bg-gray-200 text-gray-800'
|
||
}`}>
|
||
{msg.content}
|
||
</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
<div className="flex gap-2">
|
||
<input
|
||
type="text"
|
||
value={chatInput}
|
||
onChange={(e) => setChatInput(e.target.value)}
|
||
onKeyDown={(e) => e.key === 'Enter' && handleSendMessage()}
|
||
placeholder="请输入问题或任务要求..."
|
||
className={`flex-1 px-3 py-2 ${inputBg} ${inputBorder} rounded-lg ${textPrimary} text-xs focus:outline-none ${isDark ? 'focus:border-blue-500/50' : 'focus:border-red-400'}`}
|
||
/>
|
||
<button
|
||
onClick={handleSendMessage}
|
||
className={`px-3 py-2 ${btnPrimary} text-white rounded-lg transition-colors`}
|
||
>
|
||
<Send className="w-4 h-4" />
|
||
</button>
|
||
</div>
|
||
<button className={`mt-2 w-full px-3 py-1.5 ${btnSecondary} rounded text-xs transition-colors`}>
|
||
插入示例任务
|
||
</button>
|
||
</div>
|
||
|
||
{/* 卡片4:本轮执行详情 */}
|
||
<div className={`${cardBg} backdrop-blur-xl ${cardBorder} rounded-xl p-4`}>
|
||
<h3 className={`${textPrimary} font-semibold mb-3 flex items-center gap-2`}>
|
||
<Clock className={`w-4 h-4 ${isDark ? 'text-green-400' : 'text-green-600'}`} />
|
||
本轮执行详情
|
||
</h3>
|
||
<div className="space-y-3 text-xs">
|
||
<div>
|
||
<p className={`${textMuted} mb-1.5`}>调用数据源</p>
|
||
<div className="flex flex-wrap gap-1">
|
||
{executionDetails.dataSources.map((ds) => (
|
||
<span key={ds} className={`px-2 py-0.5 ${isDark ? 'bg-green-500/20 text-green-400' : 'bg-green-100 text-green-600'} rounded`}>{ds}</span>
|
||
))}
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<p className={`${textMuted} mb-1.5`}>启用技能</p>
|
||
<div className="flex flex-wrap gap-1">
|
||
{executionDetails.skills.map((skill) => (
|
||
<span key={skill} className={`px-2 py-0.5 ${isDark ? 'bg-purple-500/20 text-purple-400' : 'bg-purple-100 text-purple-600'} rounded`}>{skill}</span>
|
||
))}
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<p className={`${textMuted} mb-1.5`}>调用功能</p>
|
||
<div className="flex flex-wrap gap-1">
|
||
{executionDetails.functions.map((func) => (
|
||
<span key={func} className={`px-2 py-0.5 ${isDark ? 'bg-cyan-500/20 text-cyan-400' : 'bg-cyan-100 text-cyan-600'} rounded`}>{func}</span>
|
||
))}
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<p className={`${textMuted} mb-1.5`}>输出字段</p>
|
||
<div className="flex flex-wrap gap-1">
|
||
{executionDetails.outputs.map((out) => (
|
||
<span key={out} className={`px-2 py-0.5 ${isDark ? 'bg-blue-500/20 text-blue-400' : 'bg-blue-100 text-blue-600'} rounded font-mono`}>{out}</span>
|
||
))}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default AgentDetail;
|