544 lines
26 KiB
TypeScript
544 lines
26 KiB
TypeScript
import React, { useState } from 'react';
|
|
import {
|
|
FileText,
|
|
ArrowLeft,
|
|
ArrowRight,
|
|
Download,
|
|
Edit3,
|
|
Send,
|
|
CheckCircle,
|
|
Clock,
|
|
Bot,
|
|
Target,
|
|
Users,
|
|
TrendingUp,
|
|
MessageSquare,
|
|
Megaphone,
|
|
Shield,
|
|
ChevronDown,
|
|
ChevronRight,
|
|
RefreshCw,
|
|
MoreHorizontal,
|
|
Share2,
|
|
Printer,
|
|
History,
|
|
AlertCircle,
|
|
Check,
|
|
X,
|
|
} from 'lucide-react';
|
|
import { useTheme } from '../contexts/ThemeContext';
|
|
import { PageType } from '../components/Sidebar';
|
|
|
|
interface ResultDetailProps {
|
|
taskId?: string;
|
|
onNavigate: (page: PageType, taskId?: string) => void;
|
|
onBack?: () => void;
|
|
}
|
|
|
|
// 模拟任务详情数据
|
|
const mockTaskDetail = {
|
|
id: 'task-001',
|
|
title: '五四青年节宣传活动策略',
|
|
category: '规划任务',
|
|
subCategory: '叙事策略',
|
|
status: 'completed',
|
|
createdAt: '2026-03-19 10:30',
|
|
updatedAt: '2026-03-19 15:30',
|
|
completedAt: '2026-03-19 15:30',
|
|
reportType: 'strategy',
|
|
agentCount: 6,
|
|
description: '针对五四青年节的品牌传播策略方案',
|
|
scene: '宣传策略生成',
|
|
duration: '5小时32分',
|
|
conclusion: {
|
|
main: '五四青年节宣传活动应聚焦"真实、有态度的青年故事"这一叙事方向,以18-25岁基层青年为核心受众,优先在短视频平台建立品牌认知。',
|
|
recommended: [
|
|
'以真实人物故事为核心叙事内容',
|
|
'采用平等对话而非说教式的传播语气',
|
|
'优先布局抖音、小红书等短视频平台',
|
|
'建立UGC激励机制促进用户参与',
|
|
],
|
|
notRecommended: [
|
|
'过度包装的精致化内容',
|
|
'单向输出的宣传式传播',
|
|
'纯文字为主的长图文形式',
|
|
],
|
|
pendingIssues: [
|
|
'叙事角度:事件叙事 vs 人物叙事(待进一步验证)',
|
|
'渠道策略:短视频为主 vs 社交媒体为主',
|
|
'预算在内容制作和达人投放的分配比例',
|
|
],
|
|
},
|
|
strategyChain: [
|
|
{ id: 1, name: '目标', icon: Target, color: 'blue', status: 'completed', result: '提升品牌在Z世代用户中的认知度' },
|
|
{ id: 2, name: '受众', icon: Users, color: 'cyan', status: 'completed', result: '18-25岁基层青年' },
|
|
{ id: 3, name: '行为', icon: TrendingUp, color: 'green', status: 'completed', result: '主动参与话题讨论、生成UGC内容' },
|
|
{ id: 4, name: '驱动', icon: MessageSquare, color: 'yellow', status: 'completed', result: '社交认同与自我表达' },
|
|
{ id: 5, name: '叙事', icon: Megaphone, color: 'purple', status: 'completed', result: '真实、有态度的青年故事' },
|
|
{ id: 6, name: '风险', icon: Shield, color: 'red', status: 'completed', result: 'UGC质量不稳定、话题热度维持' },
|
|
],
|
|
versionHistory: [
|
|
{ version: 'V3', time: '2026-03-19 15:30', changes: ['叙事由"事件主导"改为"人物+事件结合"', '风险项已修正'] },
|
|
{ version: 'V2', time: '2026-03-19 14:20', changes: ['受众由"全体青年"收窄为"基层青年"', '目标行为已明确'] },
|
|
{ version: 'V1', time: '2026-03-19 10:30', changes: ['初始版本生成'] },
|
|
],
|
|
agentOpinions: [
|
|
{ agentName: 'GoalAgent', role: '目标分析专家', opinion: '建议聚焦提升品牌认知度这一核心目标,短期内不追求直接转化', adopted: true, color: 'blue' },
|
|
{ agentName: 'AudienceAgent', role: '受众分析专家', opinion: '核心受众应为18-25岁基层青年群体,注重"真实感"和"态度感"', adopted: true, color: 'cyan' },
|
|
{ agentName: 'NarrativeAgent', role: '叙事策略专家', opinion: '应采用"真实、有态度的青年故事"叙事框架', adopted: true, color: 'purple' },
|
|
{ agentName: 'RiskAgent', role: '风险评估专家', opinion: '需注意UGC质量不稳定和话题热度维持的风险', adopted: true, color: 'red' },
|
|
],
|
|
disputes: [
|
|
{
|
|
issue: '叙事角度选择',
|
|
description: '人物叙事 vs 事件叙事',
|
|
viewpoints: [
|
|
{ agent: 'NarrativeAgent', opinion: '人物叙事更有情感穿透力' },
|
|
{ agent: 'GoalAgent', opinion: '事件叙事更聚焦目标达成' },
|
|
],
|
|
status: '待确认',
|
|
},
|
|
],
|
|
};
|
|
|
|
const ResultDetail: React.FC<ResultDetailProps> = ({ taskId, onNavigate, 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-gray-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 btnPrimary = isDark ? 'bg-blue-600 hover:bg-blue-500' : 'bg-red-600 hover:bg-red-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 inputBg = isDark ? 'bg-slate-900/50' : 'bg-gray-50';
|
|
|
|
const [activeTab, setActiveTab] = useState<'conclusion' | 'process' | 'opinions' | 'history'>('conclusion');
|
|
const [expandedSection, setExpandedSection] = useState<string | null>('goal');
|
|
const [showReportMenu, setShowReportMenu] = useState(false);
|
|
|
|
const task = mockTaskDetail;
|
|
|
|
const toggleSection = (section: string) => {
|
|
setExpandedSection(expandedSection === section ? null : section);
|
|
};
|
|
|
|
const getColorClasses = (color: string) => {
|
|
const colors: Record<string, { bg: string; text: string }> = {
|
|
blue: { bg: isDark ? 'bg-blue-500/20' : 'bg-blue-50', text: isDark ? 'text-blue-400' : 'text-blue-600' },
|
|
cyan: { bg: isDark ? 'bg-cyan-500/20' : 'bg-cyan-50', text: isDark ? 'text-cyan-400' : 'text-cyan-600' },
|
|
green: { bg: isDark ? 'bg-green-500/20' : 'bg-green-50', text: isDark ? 'text-green-400' : 'text-green-600' },
|
|
yellow: { bg: isDark ? 'bg-yellow-500/20' : 'bg-yellow-50', text: isDark ? 'text-yellow-400' : 'text-yellow-600' },
|
|
purple: { bg: isDark ? 'bg-purple-500/20' : 'bg-purple-50', text: isDark ? 'text-purple-400' : 'text-purple-600' },
|
|
red: { bg: isDark ? 'bg-red-500/20' : 'bg-red-50', text: isDark ? 'text-red-400' : 'text-red-600' },
|
|
};
|
|
return colors[color] || colors.blue;
|
|
};
|
|
|
|
const handleBack = () => {
|
|
if (onBack) {
|
|
onBack();
|
|
} else {
|
|
onNavigate('result-management');
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
{/* 顶部信息栏 */}
|
|
<div className={`${cardBg} backdrop-blur-xl ${cardBorder} rounded-xl p-5`}>
|
|
<div className="flex items-center justify-between mb-4">
|
|
<div className="flex items-center gap-4">
|
|
<button
|
|
onClick={handleBack}
|
|
className={`flex items-center gap-2 px-3 py-2 ${btnSecondary} rounded-lg text-sm transition-colors`}
|
|
>
|
|
<ArrowLeft className="w-4 h-4" />
|
|
返回
|
|
</button>
|
|
<div className={`h-8 w-px ${isDark ? 'bg-blue-800/30' : 'bg-gray-200'}`} />
|
|
<div className="flex items-center gap-3">
|
|
<div className={`w-10 h-10 rounded-xl bg-blue-500/20 flex items-center justify-center`}>
|
|
<FileText className="w-5 h-5 text-blue-400" />
|
|
</div>
|
|
<div>
|
|
<h1 className={`${textPrimary} font-bold text-lg`}>{task.title}</h1>
|
|
<p className={`${textMuted} text-sm`}>{task.subCategory} · {task.status === 'completed' ? '已完成' : '进行中'}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div className="flex items-center gap-3">
|
|
<button className={`flex items-center gap-2 px-3 py-2 ${btnSecondary} rounded-lg text-sm transition-colors`}>
|
|
<Edit3 className="w-4 h-4" />
|
|
编辑
|
|
</button>
|
|
<button className={`flex items-center gap-2 px-3 py-2 ${btnSecondary} rounded-lg text-sm transition-colors`}>
|
|
<History className="w-4 h-4" />
|
|
历史版本
|
|
</button>
|
|
<button className={`flex items-center gap-2 px-3 py-2 ${btnSecondary} rounded-lg text-sm transition-colors`}>
|
|
<Download className="w-4 h-4" />
|
|
导出报告
|
|
</button>
|
|
<div className="relative">
|
|
<button
|
|
onClick={() => setShowReportMenu(!showReportMenu)}
|
|
className={`flex items-center gap-2 px-4 py-2 ${btnPrimary} text-white rounded-lg text-sm transition-colors`}
|
|
>
|
|
<Send className="w-4 h-4" />
|
|
呈报
|
|
<ChevronDown className="w-4 h-4" />
|
|
</button>
|
|
{showReportMenu && (
|
|
<div className={`absolute right-0 top-full mt-2 w-48 ${cardBg} backdrop-blur-xl ${cardBorder} rounded-xl shadow-xl py-2 z-10`}>
|
|
<button className={`w-full flex items-center gap-3 px-4 py-2.5 text-sm ${textPrimary} hover:${isDark ? 'bg-slate-700/50' : 'bg-gray-50'} transition-colors`}>
|
|
<Share2 className="w-4 h-4" />
|
|
分享链接
|
|
</button>
|
|
<button className={`w-full flex items-center gap-3 px-4 py-2.5 text-sm ${textPrimary} hover:${isDark ? 'bg-slate-700/50' : 'bg-gray-50'} transition-colors`}>
|
|
<Printer className="w-4 h-4" />
|
|
打印
|
|
</button>
|
|
<button className={`w-full flex items-center gap-3 px-4 py-2.5 text-sm ${textPrimary} hover:${isDark ? 'bg-slate-700/50' : 'bg-gray-50'} transition-colors`}>
|
|
<Send className="w-4 h-4" />
|
|
发送至邮箱
|
|
</button>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* 基本信息 */}
|
|
<div className={`grid grid-cols-5 gap-4 p-4 ${inputBg} rounded-lg`}>
|
|
<div className="text-center">
|
|
<p className={`${textMuted} text-xs mb-1`}>使用场景</p>
|
|
<p className={`${textPrimary} font-medium text-sm`}>{task.scene}</p>
|
|
</div>
|
|
<div className="text-center">
|
|
<p className={`${textMuted} text-xs mb-1`}>运行时长</p>
|
|
<p className={`${textPrimary} font-medium text-sm`}>{task.duration}</p>
|
|
</div>
|
|
<div className="text-center">
|
|
<p className={`${textMuted} text-xs mb-1`}>参与智能体</p>
|
|
<p className={`${textPrimary} font-medium text-sm`}>{task.agentCount}个</p>
|
|
</div>
|
|
<div className="text-center">
|
|
<p className={`${textMuted} text-xs mb-1`}>当前版本</p>
|
|
<p className={`${isDark ? 'text-cyan-400' : 'text-cyan-600'} font-medium text-sm`}>V{task.versionHistory.length}</p>
|
|
</div>
|
|
<div className="text-center">
|
|
<p className={`${textMuted} text-xs mb-1`}>完成时间</p>
|
|
<p className={`${textPrimary} font-medium text-sm`}>{task.completedAt}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Tab切换 */}
|
|
<div className={`flex items-center gap-1 ${cardBg} p-1 rounded-lg w-fit`}>
|
|
<button
|
|
onClick={() => setActiveTab('conclusion')}
|
|
className={`px-4 py-2 rounded-lg text-sm font-medium transition-colors ${
|
|
activeTab === 'conclusion'
|
|
? `${btnPrimary} text-white`
|
|
: `${textSecondary} ${isDark ? 'hover:text-white hover:bg-slate-700/50' : 'hover:text-gray-900 hover:bg-gray-100'}`
|
|
}`}
|
|
>
|
|
会商结论
|
|
</button>
|
|
<button
|
|
onClick={() => setActiveTab('process')}
|
|
className={`px-4 py-2 rounded-lg text-sm font-medium transition-colors ${
|
|
activeTab === 'process'
|
|
? `${btnPrimary} text-white`
|
|
: `${textSecondary} ${isDark ? 'hover:text-white hover:bg-slate-700/50' : 'hover:text-gray-900 hover:bg-gray-100'}`
|
|
}`}
|
|
>
|
|
策略链
|
|
</button>
|
|
<button
|
|
onClick={() => setActiveTab('opinions')}
|
|
className={`px-4 py-2 rounded-lg text-sm font-medium transition-colors ${
|
|
activeTab === 'opinions'
|
|
? `${btnPrimary} text-white`
|
|
: `${textSecondary} ${isDark ? 'hover:text-white hover:bg-slate-700/50' : 'hover:text-gray-900 hover:bg-gray-100'}`
|
|
}`}
|
|
>
|
|
观点汇总
|
|
</button>
|
|
<button
|
|
onClick={() => setActiveTab('history')}
|
|
className={`px-4 py-2 rounded-lg text-sm font-medium transition-colors ${
|
|
activeTab === 'history'
|
|
? `${btnPrimary} text-white`
|
|
: `${textSecondary} ${isDark ? 'hover:text-white hover:bg-slate-700/50' : 'hover:text-gray-900 hover:bg-gray-100'}`
|
|
}`}
|
|
>
|
|
版本历史
|
|
</button>
|
|
</div>
|
|
|
|
{/* 内容区 */}
|
|
{activeTab === 'conclusion' && (
|
|
<div className="grid grid-cols-12 gap-6">
|
|
{/* 会商结论 */}
|
|
<div className="col-span-8 space-y-6">
|
|
<div className={`${cardBg} backdrop-blur-xl ${cardBorder} rounded-xl p-5`}>
|
|
<h3 className={`${textPrimary} font-semibold text-sm mb-4 flex items-center gap-2`}>
|
|
<CheckCircle className={`w-4 h-4 ${isDark ? 'text-green-400' : 'text-green-600'}`} />
|
|
本次会商结论
|
|
</h3>
|
|
<div className={`p-4 ${isDark ? 'bg-green-500/10 border-green-500/30' : 'bg-green-50 border-green-200'} rounded-lg`}>
|
|
<p className={`${isDark ? 'text-green-300' : 'text-green-800'} leading-relaxed`}>{task.conclusion.main}</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div className={`${cardBg} backdrop-blur-xl ${cardBorder} rounded-xl p-5`}>
|
|
<h3 className={`${textPrimary} font-semibold text-sm mb-4 flex items-center gap-2`}>
|
|
<Check className={`w-4 h-4 ${isDark ? 'text-green-400' : 'text-green-600'}`} />
|
|
推荐采用方向
|
|
</h3>
|
|
<div className="space-y-2">
|
|
{task.conclusion.recommended.map((item, index) => (
|
|
<div key={index} className={`flex items-center gap-3 p-3 ${isDark ? 'bg-green-500/10 border-green-500/30' : 'bg-green-50 border-green-200'} rounded-lg`}>
|
|
<div className={`w-6 h-6 rounded-full ${isDark ? 'bg-green-500/20' : 'bg-green-100'} flex items-center justify-center`}>
|
|
<Check className={`w-4 h-4 ${isDark ? 'text-green-400' : 'text-green-600'}`} />
|
|
</div>
|
|
<p className={`${isDark ? 'text-green-300' : 'text-green-800'} text-sm`}>{item}</p>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
<div className={`${cardBg} backdrop-blur-xl ${cardBorder} rounded-xl p-5`}>
|
|
<h3 className={`${textPrimary} font-semibold text-sm mb-4 flex items-center gap-2`}>
|
|
<X className={`w-4 h-4 ${isDark ? 'text-red-400' : 'text-red-600'}`} />
|
|
不建议采用方向
|
|
</h3>
|
|
<div className="space-y-2">
|
|
{task.conclusion.notRecommended.map((item, index) => (
|
|
<div key={index} className={`flex items-center gap-3 p-3 ${isDark ? 'bg-red-500/10 border-red-500/30' : 'bg-red-50 border-red-200'} rounded-lg`}>
|
|
<div className={`w-6 h-6 rounded-full ${isDark ? 'bg-red-500/20' : 'bg-red-100'} flex items-center justify-center`}>
|
|
<X className={`w-4 h-4 ${isDark ? 'text-red-400' : 'text-red-600'}`} />
|
|
</div>
|
|
<p className={`${isDark ? 'text-red-300' : 'text-red-800'} text-sm`}>{item}</p>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* 侧边栏 */}
|
|
<div className="col-span-4 space-y-6">
|
|
<div className={`${cardBg} backdrop-blur-xl ${isDark ? 'border-yellow-800/30' : 'border-yellow-200'} rounded-xl p-5`}>
|
|
<h3 className={`${textPrimary} font-semibold text-sm mb-4 flex items-center gap-2`}>
|
|
<AlertCircle className={`w-4 h-4 ${isDark ? 'text-yellow-400' : 'text-yellow-600'}`} />
|
|
待确认问题
|
|
</h3>
|
|
<div className="space-y-2">
|
|
{task.conclusion.pendingIssues.map((item, index) => (
|
|
<div key={index} className={`p-3 ${isDark ? 'bg-yellow-500/10 border-yellow-500/30' : 'bg-yellow-50 border-yellow-200'} rounded-lg`}>
|
|
<p className={`${isDark ? 'text-yellow-300' : 'text-yellow-800'} text-sm`}>{item}</p>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
<div className={`${cardBg} backdrop-blur-xl ${cardBorder} rounded-xl p-5`}>
|
|
<h3 className={`${textPrimary} font-semibold text-sm mb-4`}>操作</h3>
|
|
<div className="space-y-2">
|
|
<button className={`w-full flex items-center gap-3 px-4 py-3 ${btnSecondary} rounded-xl text-sm transition-colors`}>
|
|
<RefreshCw className="w-4 h-4" />
|
|
重新发起会商
|
|
</button>
|
|
<button className={`w-full flex items-center gap-3 px-4 py-3 ${btnPrimary} text-white rounded-xl text-sm transition-colors`}>
|
|
<FileText className="w-4 h-4" />
|
|
生成最终方案
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{activeTab === 'process' && (
|
|
<div className={`${cardBg} backdrop-blur-xl ${cardBorder} rounded-xl p-5`}>
|
|
{/* 策略链可视化 */}
|
|
<h3 className={`${textPrimary} font-semibold text-sm mb-4`}>策略链结果</h3>
|
|
<div className="flex items-center justify-between mb-6">
|
|
{task.strategyChain.map((item, index) => {
|
|
const Icon = item.icon;
|
|
const colors = getColorClasses(item.color);
|
|
return (
|
|
<React.Fragment key={item.id}>
|
|
<div className="flex flex-col items-center">
|
|
<div className={`w-14 h-14 rounded-xl bg-${item.color}-500/20 border-2 border-${item.color}-500/50 flex items-center justify-center mb-2`}>
|
|
<Icon className={`w-7 h-7 text-${item.color}-400`} />
|
|
</div>
|
|
<span className={`text-${item.color}-400 text-sm font-medium`}>{item.name}</span>
|
|
<span className={`${textMuted} text-xs mt-1 flex items-center gap-1`}>
|
|
<CheckCircle className="w-3 h-3 text-green-400" /> 已确认
|
|
</span>
|
|
</div>
|
|
{index < task.strategyChain.length - 1 && (
|
|
<ArrowRight className="w-6 h-6 text-slate-600 mb-6" />
|
|
)}
|
|
</React.Fragment>
|
|
);
|
|
})}
|
|
</div>
|
|
|
|
{/* 详细结果可折叠展开 */}
|
|
<div className={`${inputBg} rounded-xl overflow-hidden border ${cardBorder}`}>
|
|
{task.strategyChain.map((section) => {
|
|
const Icon = section.icon;
|
|
const colors = getColorClasses(section.color);
|
|
const isExpanded = expandedSection === section.name;
|
|
return (
|
|
<div key={section.id} className={`border-b last:border-0 ${cardBorder}`}>
|
|
<button
|
|
onClick={() => toggleSection(section.name)}
|
|
className="w-full flex items-center justify-between p-4 hover:bg-slate-700/20 transition-colors"
|
|
>
|
|
<div className="flex items-center gap-3">
|
|
<div className={`w-10 h-10 rounded-lg bg-${section.color}-500/20 flex items-center justify-center`}>
|
|
<Icon className={`w-5 h-5 text-${section.color}-400`} />
|
|
</div>
|
|
<div className="text-left">
|
|
<p className={`${textPrimary} font-medium`}>{section.name}</p>
|
|
<p className={`text-${section.color}-400 text-sm`}>{section.result}</p>
|
|
</div>
|
|
</div>
|
|
{isExpanded ? (
|
|
<ChevronDown className={`w-5 h-5 ${textSecondary}`} />
|
|
) : (
|
|
<ChevronRight className={`w-5 h-5 ${textSecondary}`} />
|
|
)}
|
|
</button>
|
|
{isExpanded && (
|
|
<div className="px-4 pb-4 pt-0 ml-13">
|
|
<div className={`p-4 ${cardBg} rounded-lg`}>
|
|
<p className={`${textSecondary} text-sm`}>详细分析内容将在此处展示,包含智能体推理过程和依据。</p>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{activeTab === 'opinions' && (
|
|
<div className={`${cardBg} backdrop-blur-xl ${cardBorder} rounded-xl p-5`}>
|
|
<h3 className={`${textPrimary} font-semibold text-sm mb-4 flex items-center gap-2`}>
|
|
<Bot className={`w-4 h-4 ${isDark ? 'text-cyan-400' : 'text-cyan-600'}`} />
|
|
各智能体观点汇总
|
|
</h3>
|
|
<div className="space-y-4">
|
|
{task.agentOpinions.map((agent) => {
|
|
const colors = getColorClasses(agent.color);
|
|
return (
|
|
<div key={agent.agentName} className={`p-4 ${inputBg} ${cardBorder} rounded-xl`}>
|
|
<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}`}>{agent.agentName}</p>
|
|
{agent.adopted ? (
|
|
<span className={`px-1.5 py-0.5 ${isDark ? 'bg-green-500/20 text-green-400' : 'bg-green-100 text-green-700'} rounded text-xs`}>
|
|
已采纳
|
|
</span>
|
|
) : (
|
|
<span className={`px-1.5 py-0.5 ${isDark ? 'bg-slate-500/20 text-slate-400' : 'bg-gray-200 text-gray-600'} rounded text-xs`}>
|
|
未采纳
|
|
</span>
|
|
)}
|
|
</div>
|
|
<p className={`${textMuted} text-xs`}>{agent.role}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div className="pl-13">
|
|
<p className={`${textSecondary} text-sm`}>{agent.opinion}</p>
|
|
</div>
|
|
</div>
|
|
);
|
|
})}
|
|
|
|
{/* 分歧点 */}
|
|
{task.disputes.length > 0 && (
|
|
<div className={`p-4 ${isDark ? 'bg-yellow-500/10 border-yellow-500/30' : 'bg-yellow-50 border-yellow-200'} rounded-xl`}>
|
|
<h4 className={`${textPrimary} font-medium text-sm mb-3 flex items-center gap-2`}>
|
|
<AlertCircle className={`w-4 h-4 ${isDark ? 'text-yellow-400' : 'text-yellow-600'}`} />
|
|
争议点
|
|
</h4>
|
|
{task.disputes.map((dispute, idx) => (
|
|
<div key={idx} className="space-y-2">
|
|
<p className={`${textPrimary} text-sm font-medium`}>{dispute.issue}</p>
|
|
<p className={`${textMuted} text-xs`}>{dispute.description}</p>
|
|
{dispute.viewpoints.map((vp, i) => (
|
|
<div key={i} className={`p-2 ${isDark ? 'bg-yellow-500/5' : 'bg-yellow-50'} rounded-lg`}>
|
|
<span className={`${textMuted} text-xs mr-2`}>{vp.agent}:</span>
|
|
<span className={`${isDark ? 'text-yellow-300' : 'text-yellow-800'} text-xs`}>{vp.opinion}</span>
|
|
</div>
|
|
))}
|
|
</div>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{activeTab === 'history' && (
|
|
<div className={`${cardBg} backdrop-blur-xl ${cardBorder} rounded-xl p-5`}>
|
|
<div className="flex items-center justify-between mb-4">
|
|
<h3 className={`${textPrimary} font-semibold text-sm`}>版本迭代记录</h3>
|
|
<button className="flex items-center gap-1 text-blue-400 text-sm hover:text-blue-300 transition-colors">
|
|
<RefreshCw className="w-4 h-4" />
|
|
对比
|
|
</button>
|
|
</div>
|
|
<div className="space-y-3">
|
|
{task.versionHistory.map((version, index) => (
|
|
<div
|
|
key={version.version}
|
|
className={`p-4 rounded-xl border ${
|
|
index === 0
|
|
? isDark ? 'bg-cyan-500/10 border-cyan-500/30' : 'bg-cyan-50 border-cyan-200'
|
|
: `${inputBg} border-slate-700/30`
|
|
}`}
|
|
>
|
|
<div className="flex items-center justify-between mb-2">
|
|
<span className={`font-bold ${
|
|
index === 0 ? (isDark ? 'text-cyan-400' : 'text-cyan-600') : textSecondary
|
|
}`}>
|
|
{version.version}
|
|
</span>
|
|
<span className={`${textMuted} text-xs`}>{version.time}</span>
|
|
</div>
|
|
<ul className="space-y-1">
|
|
{version.changes.map((change, i) => (
|
|
<li key={i} className={`${textPrimary} text-sm flex items-start gap-2`}>
|
|
<span className={textSecondary}>•</span>
|
|
{change}
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default ResultDetail;
|