Files
deerflow-code/web-code/components/taskManagement/TaskWorkspace.tsx
T
2026-05-28 18:29:37 +08:00

936 lines
46 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import React, { useState } from 'react';
import {
Target,
Clock,
User,
ChevronRight,
Play,
RotateCcw,
Download,
MessageSquare,
AlertTriangle,
CheckCircle,
Bot,
FileText,
Lightbulb,
ArrowRight,
RefreshCw,
Pause,
Eye,
Zap,
Shield,
AlertCircle,
UserCheck,
CheckCircle2,
XCircle,
Send,
Plus,
AtSign,
FileInput,
} from 'lucide-react';
import { useTheme } from '@/contexts/ThemeContext';
import { PageType } from '@/components/Sidebar';
interface TaskWorkspaceProps {
onNavigate: (page: PageType) => void;
}
const TaskWorkspace: React.FC<TaskWorkspaceProps> = ({ onNavigate }) => {
const { theme } = useTheme();
const isDark = theme === 'dark';
const [currentPhase, setCurrentPhase] = useState(3);
const [showHumanIntervention, setShowHumanIntervention] = useState(false);
const [inputType, setInputType] = useState('question');
const [sendTarget, setSendTarget] = useState('current');
const [inputMessage, setInputMessage] = useState('');
// 逻辑链一致性检查数据
const logicChainChecks = [
{ id: 'goal-behavior', label: '目标-行为', status: 'passed', detail: '行为与目标高度一致' },
{ id: 'behavior-driver', label: '行为-驱动', status: 'passed', detail: '驱动有效支撑行为' },
{ id: 'driver-narrative', label: '驱动-叙事', status: 'passed', detail: '叙事与驱动匹配' },
{ id: 'narrative-audience', label: '叙事-受众', status: 'warning', detail: '叙事需进一步收窄以匹配核心受众' },
];
// 待确认问题列表
const pendingQuestions = [
{ id: 1, type: 'field', title: '受众范围收窄', description: '是否聚焦基层青年而非全体青年?', priority: 'high' },
{ id: 2, type: 'conflict', title: '叙事方向待定', description: '真实性与话题性如何平衡?', priority: 'medium' },
];
const phases = [
{ id: 1, name: '目标分析', agent: 'GoalAgent', status: 'completed' },
{ id: 2, name: '受众分析', agent: 'AudienceAgent', status: 'completed' },
{ id: 3, name: '行为分析', agent: 'BehaviorAgent', status: 'active' },
{ id: 4, name: '驱动分析', agent: 'DriverAgent', status: 'pending' },
{ id: 5, name: '叙事分析', agent: 'NarrativeAgent', status: 'pending' },
{ id: 6, name: '逻辑链收敛', agent: 'LogicChainAgent', status: 'pending' },
{ id: 7, name: '风险评估', agent: 'RiskAgent', status: 'pending' },
{ id: 8, name: '方案生成', agent: 'DraftAgent', status: 'pending' },
];
const discussionCards = [
{
id: 1,
agent: 'GoalAgent',
phase: '目标分析',
time: '10:32',
type: 'judgment',
coreJudgment: '核心目标是提升品牌在年轻群体中的认知度和好感度',
outputFields: {
primary_goal: '提升品牌在Z世代用户中的认知度',
secondary_goal: '建立品牌年轻化形象',
},
releaseStatus: 'passed',
riskWarnings: [],
},
{
id: 2,
agent: 'AudienceAgent',
phase: '受众分析',
time: '11:15',
type: 'judgment',
coreJudgment: '核心受众应聚焦18-25岁基层青年群体,次级受众为25-30岁职场新人',
outputFields: {
core_audience: '18-25岁基层青年',
secondary_audience: '25-30岁职场新人',
audience_insights: ['社交媒体重度用户', '注重性价比', '偏好真实、有态度的品牌'],
},
releaseStatus: 'passed',
riskWarnings: ['受众范围可能过宽,建议进一步细化'],
},
{
id: 3,
agent: 'BehaviorAgent',
phase: '行为分析',
time: '14:20',
type: 'response',
coreJudgment: '目标行为是促使受众主动参与互动并生成UGC内容',
outputFields: {
target_behavior: '主动参与话题讨论、生成UGC内容',
key_conversion: '浏览 → 点赞 → 评论 → 转发 → 创作',
},
releaseStatus: 'pending',
riskWarnings: [],
},
];
const confirmedFields = {
goal: '提升品牌在Z世代用户中的认知度',
audience: '18-25岁基层青年',
behavior: '主动参与互动并生成UGC内容',
driver: '待分析',
narrative: '待分析',
};
const currentPhaseName = phases.find(p => p.status === 'active')?.name || '未知';
return (
<div className="h-[calc(100vh-140px)] flex flex-col">
{/* 顶部:运行状态栏(精简版 - 无流程图) */}
<div className={`rounded-xl p-4 flex-shrink-0 border ${
isDark ? 'bg-slate-800/30 backdrop-blur-xl border-blue-800/30' : 'bg-white border-red-100 shadow-sm'
}`}>
<div className="flex items-center justify-between">
{/* 左侧:当前阶段和运行状态 */}
<div className="flex items-center gap-6">
<div className="flex items-center gap-3">
<div className={`w-10 h-10 rounded-lg flex items-center justify-center ${
isDark ? 'bg-blue-500/20' : 'bg-red-100'
}`}>
<Target className={`w-5 h-5 ${isDark ? 'text-blue-400' : 'text-red-500'}`} />
</div>
<div>
<p className={`text-xs ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>当前阶段</p>
<p className={`font-semibold ${isDark ? 'text-white' : 'text-gray-900'}`}>{currentPhaseName}</p>
</div>
</div>
<div className={`h-8 w-px ${isDark ? 'bg-blue-800/30' : 'bg-red-200'}`} />
<span className={`px-3 py-1.5 rounded-full text-sm font-medium flex items-center gap-1.5 ${
isDark
? 'bg-blue-500/20 text-blue-400'
: 'bg-red-100 text-red-600'
}`}>
<span className={`w-2 h-2 rounded-full animate-pulse ${
isDark ? 'bg-blue-400' : 'bg-red-500'
}`} />
运行中
</span>
</div>
{/* 右侧:全局操作按钮 */}
<div className="flex items-center gap-2">
<button className={`flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-sm transition-colors border ${
isDark
? 'bg-yellow-500/20 hover:bg-yellow-500/30 border-yellow-500/30 text-yellow-400'
: 'bg-yellow-100 hover:bg-yellow-200 border-yellow-200 text-yellow-600'
}`}>
<Pause className="w-4 h-4" />
暂停
</button>
<button className={`flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-sm transition-colors ${
isDark
? 'bg-green-600 hover:bg-green-500 text-white'
: 'bg-green-600 hover:bg-green-500 text-white shadow-md'
}`}>
<Play className="w-4 h-4" />
开始
</button>
<button
onClick={() => onNavigate('strategy-result')}
className={`flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-sm transition-colors border ${
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-200 text-gray-700'
}`}
>
<Eye className="w-4 h-4" />
查看结果
</button>
<button className={`flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-sm transition-colors border ${
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-200 text-gray-700'
}`}>
<Download className="w-4 h-4" />
导出
</button>
<button className={`p-2 rounded-lg transition-colors border ${
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-200 text-gray-700'
}`}>
<ChevronRight className="w-4 h-4" />
</button>
</div>
</div>
</div>
{/* 三栏式主工作区 */}
<div className="flex-1 grid grid-cols-12 gap-4 mt-4 min-h-0 overflow-hidden">
{/* 左栏 - 任务与流程区 (22%) */}
<div className="col-span-3 flex flex-col gap-4 min-h-0 overflow-y-auto">
{/* 任务信息卡 */}
<div className={`rounded-xl p-4 flex-shrink-0 border ${
isDark ? 'bg-slate-800/30 backdrop-blur-xl border-blue-800/30' : 'bg-white border-red-100 shadow-sm'
}`}>
<h3 className={`font-semibold text-sm mb-3 flex items-center gap-2 ${isDark ? 'text-white' : 'text-gray-900'}`}>
<FileText className={`w-4 h-4 ${isDark ? 'text-blue-400' : 'text-red-500'}`} />
任务信息
</h3>
<div className="space-y-2 text-sm">
<div className="flex items-center justify-between">
<span className={isDark ? 'text-slate-500' : 'text-gray-500'}>任务标题</span>
<span className={`text-right truncate max-w-[140px] ${isDark ? 'text-slate-300' : 'text-gray-700'}`}>五四青年节宣传活动策略</span>
</div>
<div className="flex items-center justify-between">
<span className={isDark ? 'text-slate-500' : 'text-gray-500'}>任务编号</span>
<span className={`text-xs ${isDark ? 'text-slate-400' : 'text-gray-400'}`}>TASK-0319-001</span>
</div>
<div className="flex items-center justify-between">
<span className={isDark ? 'text-slate-500' : 'text-gray-500'}>所属场景</span>
<span className={`text-xs ${isDark ? 'text-blue-400' : 'text-red-600'}`}>宣传策略生成</span>
</div>
<div className={`pt-2 border-t ${isDark ? 'border-blue-800/30' : 'border-red-100'}`}>
<div className="flex items-center justify-between text-xs">
<span className={`flex items-center gap-1 ${isDark ? 'text-slate-500' : 'text-gray-500'}`}>
<User className="w-3 h-3" /> 张策略
</span>
<span className={`flex items-center gap-1 ${isDark ? 'text-slate-500' : 'text-gray-500'}`}>
<Clock className="w-3 h-3" /> 2026-03-19
</span>
</div>
</div>
</div>
</div>
{/* 流程节点区 */}
<div className={`rounded-xl p-4 flex-shrink-0 border ${
isDark ? 'bg-slate-800/30 backdrop-blur-xl border-blue-800/30' : 'bg-white border-red-100 shadow-sm'
}`}>
<h3 className={`font-semibold text-sm mb-3 flex items-center gap-2 ${isDark ? 'text-white' : 'text-gray-900'}`}>
<Bot className={`w-4 h-4 ${isDark ? 'text-cyan-400' : 'text-red-500'}`} />
流程节点
</h3>
<div className="space-y-1.5">
{phases.map((phase) => (
<button
key={phase.id}
onClick={() => setCurrentPhase(phase.id)}
className={`w-full flex items-center gap-2 p-2 rounded-lg transition-all text-left border ${
phase.status === 'active'
? isDark
? 'bg-blue-500/20 border-blue-500/30'
: 'bg-red-50 border-red-200'
: phase.status === 'completed'
? isDark
? 'bg-slate-900/50 hover:bg-slate-800/50'
: 'bg-gray-50 hover:bg-gray-100'
: isDark
? 'bg-slate-900/30 opacity-50'
: 'bg-gray-50 opacity-50'
}`}
>
<div className={`w-5 h-5 rounded-full flex items-center justify-center text-xs font-bold flex-shrink-0 ${
phase.status === 'completed'
? isDark ? 'bg-green-500 text-white' : 'bg-green-500 text-white'
: phase.status === 'active'
? isDark ? 'bg-blue-500 text-white' : 'bg-blue-500 text-white'
: isDark ? 'bg-slate-700 text-slate-400' : 'bg-gray-200 text-gray-500'
}`}>
{phase.id}
</div>
<div className="flex-1 min-w-0">
<p className={`text-xs font-medium truncate ${
phase.status === 'active' ? (isDark ? 'text-white' : 'text-gray-900') : (isDark ? 'text-slate-400' : 'text-gray-500')
}`}>
{phase.name}
</p>
<p className={`text-[10px] truncate ${isDark ? 'text-slate-500' : 'text-gray-400'}`}>{phase.agent}</p>
</div>
<span className={`w-1.5 h-1.5 rounded-full flex-shrink-0 ${
phase.status === 'completed' ? (isDark ? 'bg-green-400' : 'bg-green-500') :
phase.status === 'active' ? (isDark ? 'bg-blue-400' : 'bg-blue-500') :
(isDark ? 'bg-slate-600' : 'bg-gray-300')
}`} />
</button>
))}
</div>
</div>
{/* 快捷操作卡 */}
<div className={`rounded-xl p-4 flex-shrink-0 border ${
isDark ? 'bg-slate-800/30 backdrop-blur-xl border-blue-800/30' : 'bg-white border-red-100 shadow-sm'
}`}>
<h3 className={`font-semibold text-sm mb-3 flex items-center gap-2 ${isDark ? 'text-white' : 'text-gray-900'}`}>
<Zap className={`w-4 h-4 ${isDark ? 'text-yellow-400' : 'text-red-500'}`} />
快捷操作
</h3>
<div className="space-y-2">
<button className={`w-full flex items-center justify-center gap-2 px-3 py-2 rounded-lg text-sm transition-colors border ${
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-200 text-gray-700'
}`}>
<RefreshCw className="w-4 h-4" />
重新运行当前节点
</button>
<button className={`w-full flex items-center justify-center gap-2 px-3 py-2 rounded-lg text-sm transition-colors border ${
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-200 text-gray-700'
}`}>
<RotateCcw className="w-4 h-4" />
发起回退
</button>
<button className={`w-full flex items-center justify-center gap-2 px-3 py-2 rounded-lg text-sm transition-colors border ${
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-200 text-gray-700'
}`}>
<FileInput className="w-4 h-4" />
查看日志
</button>
<button
onClick={() => setShowHumanIntervention(true)}
className={`w-full flex items-center justify-center gap-2 px-3 py-2 rounded-lg text-sm transition-colors border ${
isDark
? 'bg-purple-500/20 hover:bg-purple-500/30 border-purple-500/30 text-purple-400'
: 'bg-purple-100 hover:bg-purple-200 border-purple-200 text-purple-600'
}`}
>
<UserCheck className="w-4 h-4" />
人工介入
</button>
</div>
</div>
</div>
{/* 中栏 - 讨论区 (47%) */}
<div className="col-span-6 flex flex-col gap-4 min-h-0">
{/* 当前议题卡 */}
<div className={`rounded-xl p-4 flex-shrink-0 border ${
isDark ? 'bg-slate-800/30 backdrop-blur-xl border-blue-800/30' : 'bg-white border-red-100 shadow-sm'
}`}>
<div className="flex items-center justify-between">
<div className="flex items-center gap-3">
<div className={`w-8 h-8 rounded-lg flex items-center justify-center ${
isDark ? 'bg-cyan-500/20' : 'bg-red-100'
}`}>
<MessageSquare className={`w-4 h-4 ${isDark ? 'text-cyan-400' : 'text-red-500'}`} />
</div>
<div>
<p className={`text-xs ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>当前议题</p>
<p className={`text-sm font-medium ${isDark ? 'text-white' : 'text-gray-900'}`}>明确目标受众的行为模式和转化路径</p>
</div>
</div>
<div className="flex items-center gap-2">
<span className={`px-2.5 py-1 rounded-full text-xs font-medium ${
isDark ? 'bg-cyan-500/20 text-cyan-400' : 'bg-red-100 text-red-600'
}`}>
BehaviorAgent
</span>
<button className={`px-2 py-1 rounded text-xs transition-colors border ${
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-200 text-gray-700'
}`}>
指定发言
</button>
<button className={`px-2 py-1 rounded text-xs transition-colors border ${
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-200 text-gray-700'
}`}>
结束本轮
</button>
</div>
</div>
<div className={`mt-3 p-2 rounded-lg text-xs ${isDark ? 'bg-slate-900/50' : 'bg-gray-50'}`}>
<span className={isDark ? 'text-slate-500' : 'text-gray-400'}>上游输入:</span>
<span className={isDark ? 'text-cyan-400' : 'text-red-600'}>AudienceAgent 已确认输出</span>
<span className={`mx-2 ${isDark ? 'text-slate-400' : 'text-gray-400'}`}>→</span>
<span className={isDark ? 'text-slate-300' : 'text-gray-700'}>核心受众已明确:18-25岁基层青年群体</span>
</div>
</div>
{/* 讨论消息流 */}
<div className={`flex-1 rounded-xl p-4 overflow-y-auto min-h-0 border ${
isDark ? 'bg-slate-800/30 backdrop-blur-xl border-blue-800/30' : 'bg-white border-red-100 shadow-sm'
}`}>
<h3 className={`font-semibold text-sm mb-4 flex items-center gap-2 ${isDark ? 'text-white' : 'text-gray-900'}`}>
<Bot className={`w-4 h-4 ${isDark ? 'text-purple-400' : 'text-red-500'}`} />
讨论消息流
</h3>
<div className="space-y-4">
{discussionCards.map((card) => (
<div
key={card.id}
className={`p-4 rounded-xl border ${
card.releaseStatus === 'passed'
? isDark
? 'bg-slate-900/50 border-green-500/30'
: 'bg-green-50 border-green-200'
: card.releaseStatus === 'pending'
? isDark
? 'bg-blue-500/10 border-blue-500/30'
: 'bg-blue-50 border-blue-200'
: isDark
? 'bg-red-500/10 border-red-500/30'
: 'bg-red-50 border-red-200'
}`}
>
<div className="flex items-start justify-between mb-3">
<div className="flex items-center gap-2">
<div className={`w-8 h-8 rounded-lg flex items-center justify-center ${
isDark ? 'bg-purple-500/20' : 'bg-red-100'
}`}>
<Bot className={`w-4 h-4 ${isDark ? 'text-purple-400' : 'text-red-500'}`} />
</div>
<div>
<div className="flex items-center gap-2">
<p className={`text-sm font-medium ${isDark ? 'text-white' : 'text-gray-900'}`}>{card.agent}</p>
<span className={`px-1.5 py-0.5 rounded text-[10px] ${isDark ? 'bg-slate-700 text-slate-400' : 'bg-gray-100 text-gray-500'}`}>
{card.type === 'judgment' ? '独立判断' : '回应'}
</span>
</div>
<p className={`text-xs ${isDark ? 'text-slate-500' : 'text-gray-400'}`}>{card.phase} · {card.time}</p>
</div>
</div>
<span className={`px-2 py-1 rounded-full text-xs font-medium flex items-center gap-1 ${
card.releaseStatus === 'passed'
? isDark
? 'bg-green-500/20 text-green-400'
: 'bg-green-100 text-green-600'
: card.releaseStatus === 'pending'
? isDark
? 'bg-yellow-500/20 text-yellow-400'
: 'bg-yellow-100 text-yellow-600'
: isDark
? 'bg-red-500/20 text-red-400'
: 'bg-red-100 text-red-600'
}`}>
{card.releaseStatus === 'passed' ? (
<><CheckCircle className="w-3 h-3" /> 已放行</>
) : card.releaseStatus === 'pending' ? (
<><Clock className="w-3 h-3" /> 待放行</>
) : (
<><AlertTriangle className="w-3 h-3" /> 未通过</>
)}
</span>
</div>
<div className="mb-3">
<p className={`text-xs mb-1 ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>核心观点</p>
<p className={`text-sm ${isDark ? 'text-white' : 'text-gray-900'}`}>{card.coreJudgment}</p>
</div>
<div className={`mb-3 p-3 rounded-lg ${isDark ? 'bg-slate-800/50' : 'bg-gray-50'}`}>
<p className={`text-xs mb-2 ${isDark ? 'text-slate-500' : 'text-gray-400'}`}>输出字段摘要</p>
<div className="space-y-1 text-xs">
{Object.entries(card.outputFields).map(([key, value]) => (
<div key={key} className="flex items-start gap-2">
<span className={`font-mono ${isDark ? 'text-cyan-400' : 'text-red-600'}`}>{key}:</span>
<span className={isDark ? 'text-slate-300' : 'text-gray-700'}>
{Array.isArray(value) ? value.join(', ') : value}
</span>
</div>
))}
</div>
</div>
{card.riskWarnings.length > 0 && (
<div className={`mb-3 p-2 rounded-lg border ${
isDark ? 'bg-amber-500/10 border-amber-500/30' : 'bg-yellow-50 border-yellow-200'
}`}>
<p className={`text-xs font-medium flex items-center gap-1 ${
isDark ? 'text-amber-400' : 'text-yellow-600'
}`}>
<AlertTriangle className="w-3 h-3" /> 风险提示
</p>
<p className={`text-xs mt-1 ${isDark ? 'text-slate-300' : 'text-gray-700'}`}>{card.riskWarnings[0]}</p>
</div>
)}
<div className={`flex items-center gap-2 pt-2 border-t ${isDark ? 'border-blue-800/30' : 'border-gray-200'}`}>
<button className={`px-2.5 py-1.5 rounded text-xs transition-colors ${
isDark
? 'bg-green-600/50 hover:bg-green-600 text-white'
: 'bg-green-600 hover:bg-green-500 text-white'
}`}>
采纳
</button>
<button className={`px-2.5 py-1.5 rounded text-xs transition-colors border ${
isDark
? 'bg-yellow-500/20 hover:bg-yellow-500/30 border-yellow-500/30 text-yellow-400'
: 'bg-yellow-100 hover:bg-yellow-200 border-yellow-200 text-yellow-600'
}`}>
待确认
</button>
<button className={`px-2.5 py-1.5 rounded text-xs transition-colors border ${
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-200 text-gray-700'
}`}>
引用追问
</button>
<button className={`px-2.5 py-1.5 rounded text-xs transition-colors border ${
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-200 text-gray-700'
}`}>
写入策略链
</button>
</div>
</div>
))}
{/* 系统摘要卡 */}
<div className={`p-4 rounded-xl border ${
isDark ? 'bg-blue-500/10 border-blue-500/30' : 'bg-blue-50 border-blue-200'
}`}>
<div className="flex items-center gap-2 mb-3">
<div className={`w-6 h-6 rounded flex items-center justify-center ${
isDark ? 'bg-blue-500/20' : 'bg-blue-100'
}`}>
<Lightbulb className={`w-3 h-3 ${isDark ? 'text-blue-400' : 'text-blue-500'}`} />
</div>
<p className={`text-sm font-medium ${isDark ? 'text-blue-400' : 'text-blue-600'}`}>系统摘要</p>
</div>
<div className="space-y-2 text-sm">
<div>
<p className={`text-xs mb-1 ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>已形成结论:</p>
<ul className={`text-xs space-y-0.5 list-disc list-inside ${isDark ? 'text-slate-300' : 'text-gray-700'}`}>
<li>核心受众明确为18-25岁基层青年</li>
<li>目标行为建议拆分为参与和传播两层</li>
</ul>
</div>
<div>
<p className={`text-xs mb-1 ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>待确认:</p>
<ul className={`text-xs space-y-0.5 list-disc list-inside ${isDark ? 'text-yellow-400' : 'text-yellow-600'}`}>
<li>UGC创作是否纳入核心行为?</li>
</ul>
</div>
<div className={`pt-2 border-t ${isDark ? 'border-blue-800/30' : 'border-blue-200'}`}>
<p className={`text-xs ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>建议下一步:</p>
<p className={`text-xs ${isDark ? 'text-cyan-400' : 'text-red-600'}`}>邀请 DriverAgent 分析驱动因素</p>
</div>
</div>
<div className="flex items-center gap-2 mt-3">
<button className={`px-3 py-1.5 rounded text-xs transition-colors ${
isDark
? 'bg-blue-600 hover:bg-blue-500 text-white'
: 'bg-blue-600 hover:bg-blue-500 text-white shadow-md'
}`}>
推进下一步
</button>
<button className={`px-3 py-1.5 rounded text-xs transition-colors border ${
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-200 text-gray-700'
}`}>
写入待确认
</button>
</div>
</div>
</div>
</div>
</div>
{/* 右栏 - 策略收敛区 (28%) */}
<div className="col-span-3 flex flex-col gap-4 min-h-0 overflow-y-auto">
{/* 策略链卡 */}
<div className={`rounded-xl p-4 flex-shrink-0 border ${
isDark
? 'bg-gradient-to-br from-blue-600/20 to-cyan-600/20 backdrop-blur-xl border-blue-500/30'
: 'bg-gradient-to-br from-red-50 to-red-100 border-red-200'
}`}>
<div className="flex items-center justify-between mb-3">
<h3 className={`font-semibold text-sm flex items-center gap-2 ${isDark ? 'text-white' : 'text-gray-900'}`}>
<Lightbulb className={`w-4 h-4 ${isDark ? 'text-yellow-400' : 'text-red-500'}`} />
策略链
</h3>
<div className="flex items-center gap-1">
<button className={`p-1 rounded transition-colors ${isDark ? 'hover:bg-slate-700/50' : 'hover:bg-red-50'}`} title="复制">
<FileText className={`w-3.5 h-3.5 ${isDark ? 'text-slate-400' : 'text-gray-400'}`} />
</button>
<button className={`p-1 rounded transition-colors ${isDark ? 'hover:bg-slate-700/50' : 'hover:bg-red-50'}`} title="编辑">
<RefreshCw className={`w-3.5 h-3.5 ${isDark ? 'text-slate-400' : 'text-gray-400'}`} />
</button>
</div>
</div>
<div className={`p-3 rounded-lg border ${
isDark ? 'bg-slate-900/50 border-blue-500/20' : 'bg-white border-red-100'
}`}>
<p className={`text-xs leading-relaxed ${isDark ? 'text-slate-300' : 'text-gray-700'}`}>
面向<span className={`font-medium ${isDark ? 'text-cyan-400' : 'text-red-600'}`}>【18-25岁基层青年】</span>,
围绕其<span className={`font-medium ${isDark ? 'text-yellow-400' : 'text-red-600'}`}>【社交认同与自我表达】</span>驱动,
传播<span className={`font-medium ${isDark ? 'text-purple-400' : 'text-red-600'}`}>【真实、有态度的青年故事】</span>叙事,
促使其产生<span className={`font-medium ${isDark ? 'text-green-400' : 'text-red-600'}`}>【主动参与互动并生成UGC内容】</span>行为,
从而实现<span className={`font-medium ${isDark ? 'text-blue-400' : 'text-red-600'}`}>【提升品牌在Z世代用户中的认知度】</span>目标。
</p>
</div>
</div>
{/* 逻辑链一致性校验 */}
<div className={`rounded-xl p-4 flex-shrink-0 border ${
isDark ? 'bg-slate-800/30 backdrop-blur-xl border-blue-800/30' : 'bg-white border-red-100 shadow-sm'
}`}>
<div className="flex items-center justify-between mb-3">
<h3 className={`font-semibold text-sm flex items-center gap-2 ${isDark ? 'text-white' : 'text-gray-900'}`}>
<Shield className={`w-4 h-4 ${isDark ? 'text-green-400' : 'text-red-500'}`} />
逻辑链一致性
</h3>
<span className={`px-2 py-0.5 rounded text-xs ${
isDark ? 'bg-green-500/20 text-green-400' : 'bg-green-100 text-green-600'
}`}>
3/4 通过
</span>
</div>
<div className="space-y-1.5">
{logicChainChecks.map((check) => (
<div
key={check.id}
className={`p-2 rounded-lg border text-xs ${
check.status === 'passed'
? isDark
? 'bg-green-500/10 border-green-500/30'
: 'bg-green-50 border-green-200'
: check.status === 'warning'
? isDark
? 'bg-yellow-500/10 border-yellow-500/30'
: 'bg-yellow-50 border-yellow-200'
: isDark
? 'bg-red-500/10 border-red-500/30'
: 'bg-red-50 border-red-200'
}`}
>
<div className="flex items-center justify-between">
<span className={`font-medium ${
check.status === 'passed'
? isDark ? 'text-green-400' : 'text-green-600'
: check.status === 'warning'
? isDark ? 'text-yellow-400' : 'text-yellow-600'
: isDark ? 'text-red-400' : 'text-red-600'
}`}>
{check.label}
</span>
{check.status === 'passed' ? (
<CheckCircle2 className={`w-3.5 h-3.5 ${isDark ? 'text-green-400' : 'text-green-500'}`} />
) : check.status === 'warning' ? (
<AlertCircle className={`w-3.5 h-3.5 ${isDark ? 'text-yellow-400' : 'text-yellow-500'}`} />
) : (
<XCircle className={`w-3.5 h-3.5 ${isDark ? 'text-red-400' : 'text-red-500'}`} />
)}
</div>
</div>
))}
</div>
</div>
{/* 已采纳观点 */}
<div className={`rounded-xl p-4 flex-shrink-0 border ${
isDark ? 'bg-slate-800/30 backdrop-blur-xl border-blue-800/30' : 'bg-white border-red-100 shadow-sm'
}`}>
<h3 className={`font-semibold text-sm mb-3 flex items-center gap-2 ${isDark ? 'text-white' : 'text-gray-900'}`}>
<CheckCircle className={`w-4 h-4 ${isDark ? 'text-green-400' : 'text-red-500'}`} />
已采纳观点
</h3>
<div className="space-y-2">
{[
{ agent: 'GoalAgent', opinion: '主目标是提升认知度与好感度' },
{ agent: 'AudienceAgent', opinion: '核心受众为18-25岁基层青年' },
{ agent: 'BehaviorAgent', opinion: '目标行为应拆为参与和传播' },
].map((item, index) => (
<div key={index} className={`p-2 rounded-lg border ${
isDark ? 'bg-slate-900/50 border-green-500/20' : 'bg-green-50 border-green-200'
}`}>
<p className={`text-xs font-medium mb-0.5 ${isDark ? 'text-green-400' : 'text-green-600'}`}>{item.agent}</p>
<p className={`text-xs ${isDark ? 'text-slate-300' : 'text-gray-700'}`}>{item.opinion}</p>
</div>
))}
</div>
</div>
{/* 待确认与分歧 */}
<div className={`rounded-xl p-4 flex-shrink-0 border ${
isDark ? 'bg-slate-800/30 backdrop-blur-xl border-blue-800/30' : 'bg-white border-red-100 shadow-sm'
}`}>
<div className="flex items-center justify-between mb-3">
<h3 className={`font-semibold text-sm flex items-center gap-2 ${isDark ? 'text-white' : 'text-gray-900'}`}>
<AlertTriangle className={`w-4 h-4 ${isDark ? 'text-amber-400' : 'text-red-500'}`} />
待确认与分歧
</h3>
<span className={`px-2 py-0.5 rounded text-xs ${
isDark ? 'bg-amber-500/20 text-amber-400' : 'bg-yellow-100 text-yellow-600'
}`}>
{pendingQuestions.length} 项
</span>
</div>
<div className="space-y-2">
{pendingQuestions.map((question) => (
<div
key={question.id}
className={`p-2 rounded-lg border ${
question.priority === 'high'
? isDark
? 'bg-red-500/10 border-red-500/30'
: 'bg-red-50 border-red-200'
: isDark
? 'bg-amber-500/10 border-amber-500/30'
: 'bg-yellow-50 border-yellow-200'
}`}
>
<p className={`text-xs font-medium ${
question.priority === 'high' ? (isDark ? 'text-red-400' : 'text-red-600') : (isDark ? 'text-amber-400' : 'text-yellow-600')
}`}>
{question.title}
</p>
<p className={`text-xs mt-0.5 ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>{question.description}</p>
<button className={`mt-1 text-xs flex items-center gap-1 ${
isDark ? 'text-blue-400 hover:text-blue-300' : 'text-blue-500 hover:text-blue-600'
}`}>
<UserCheck className="w-3 h-3" />
点名分析
</button>
</div>
))}
</div>
</div>
</div>
</div>
{/* 底部:固定输入区 */}
<div className={`mt-4 rounded-xl p-4 flex-shrink-0 border ${
isDark ? 'bg-slate-800/30 backdrop-blur-xl border-blue-800/30' : 'bg-white border-red-100 shadow-sm'
}`}>
<div className="flex items-center gap-3">
{/* 发送对象选择 */}
<select
value={sendTarget}
onChange={(e) => setSendTarget(e.target.value)}
className={`px-3 py-2 rounded-lg text-sm focus:outline-none ${
isDark
? 'bg-slate-900/50 border border-blue-800/30 text-white'
: 'bg-white border border-gray-200 text-gray-700'
}`}
>
<option value="current">当前智能体</option>
<option value="all">全部智能体</option>
<option value="host">主持人</option>
</select>
{/* 输入类型选择 */}
<select
value={inputType}
onChange={(e) => setInputType(e.target.value)}
className={`px-3 py-2 rounded-lg text-sm focus:outline-none ${
isDark
? 'bg-slate-900/50 border border-blue-800/30 text-white'
: 'bg-white border border-gray-200 text-gray-700'
}`}
>
<option value="question">提问</option>
<option value="instruction">指令</option>
<option value="judgment">人工判断</option>
<option value="note">批注</option>
</select>
{/* 主输入框 */}
<input
type="text"
value={inputMessage}
onChange={(e) => setInputMessage(e.target.value)}
placeholder="输入问题、指令、人工判断或批注..."
className={`flex-1 px-4 py-2 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-red-500/20 ${
isDark
? 'bg-slate-900/50 border border-blue-800/30 text-white placeholder-slate-500'
: 'bg-white border border-gray-200 text-gray-900 placeholder-gray-400'
}`}
/>
{/* 发送按钮 */}
<button className={`flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-medium transition-colors ${
isDark
? 'bg-blue-600 hover:bg-blue-500 text-white'
: 'bg-red-600 hover:bg-red-500 text-white shadow-md'
}`}>
<Send className="w-4 h-4" />
发送
</button>
</div>
{/* 第二行快捷操作 */}
<div className="flex items-center gap-4 mt-3">
<button className={`flex items-center gap-1.5 px-2 py-1 rounded text-xs transition-colors border ${
isDark
? 'bg-slate-700/50 hover:bg-slate-600/50 border-blue-800/30 text-slate-400'
: 'bg-gray-100 hover:bg-gray-200 border-gray-200 text-gray-500'
}`}>
<AtSign className="w-3 h-3" />
@智能体
</button>
<button className={`flex items-center gap-1.5 px-2 py-1 rounded text-xs transition-colors border ${
isDark
? 'bg-slate-700/50 hover:bg-slate-600/50 border-blue-800/30 text-slate-400'
: 'bg-gray-100 hover:bg-gray-200 border-gray-200 text-gray-500'
}`}>
<FileInput className="w-3 h-3" />
引用消息
</button>
<button className={`flex items-center gap-1.5 px-2 py-1 rounded text-xs transition-colors border ${
isDark
? 'bg-slate-700/50 hover:bg-slate-600/50 border-blue-800/30 text-slate-400'
: 'bg-gray-100 hover:bg-gray-200 border-gray-200 text-gray-500'
}`}>
<Lightbulb className="w-3 h-3" />
生成摘要
</button>
<button className={`flex items-center gap-1.5 px-2 py-1 rounded text-xs transition-colors border ${
isDark
? 'bg-slate-700/50 hover:bg-slate-600/50 border-blue-800/30 text-slate-400'
: 'bg-gray-100 hover:bg-gray-200 border-gray-200 text-gray-500'
}`}>
<Plus className="w-3 h-3" />
写入整合区
</button>
</div>
</div>
{/* 人工干预弹窗 */}
{showHumanIntervention && (
<div className="fixed inset-0 bg-black/60 backdrop-blur-sm flex items-center justify-center z-50">
<div className={`rounded-2xl p-6 w-full max-w-lg border ${
isDark ? 'bg-slate-800 border-blue-800/50' : 'bg-white border-red-200'
}`}>
<div className="flex items-center justify-between mb-6">
<h3 className={`font-semibold text-lg flex items-center gap-2 ${isDark ? 'text-white' : 'text-gray-900'}`}>
<UserCheck className={`w-5 h-5 ${isDark ? 'text-purple-400' : 'text-red-500'}`} />
人工干预
</h3>
<button
onClick={() => setShowHumanIntervention(false)}
className={`p-2 rounded-lg transition-colors ${isDark ? 'hover:bg-slate-700' : 'hover:bg-gray-100'}`}
>
<XCircle className={`w-5 h-5 ${isDark ? 'text-slate-400' : 'text-gray-400'}`} />
</button>
</div>
<div className="space-y-4">
<div>
<label className={`block text-sm mb-2 ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>干预类型</label>
<div className="grid grid-cols-2 gap-3">
{[
{ value: 'correct', label: '人工修正', icon: RefreshCw },
{ value: 'approve', label: '提前放行', icon: CheckCircle2 },
{ value: 'override', label: '强制覆盖', icon: Zap },
{ value: 'reject', label: '终止本轮', icon: XCircle },
].map((type) => (
<button
key={type.value}
className={`flex items-center gap-2 p-3 rounded-lg transition-colors border ${
isDark
? 'bg-slate-900/50 hover:bg-slate-700/50 border-blue-800/30 text-slate-300'
: 'bg-gray-50 hover:bg-gray-100 border-gray-200 text-gray-700'
}`}
>
<type.icon className={`w-4 h-4 ${isDark ? 'text-blue-400' : 'text-red-500'}`} />
<span className="text-sm">{type.label}</span>
</button>
))}
</div>
</div>
<div>
<label className={`block text-sm mb-2 ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>目标字段</label>
<select className={`w-full px-4 py-2.5 rounded-lg text-sm ${
isDark
? 'bg-slate-900/50 border border-blue-800/30 text-white'
: 'bg-white border border-gray-200 text-gray-700'
}`}>
<option value="">请选择要干预的字段</option>
<option value="audience">受众细分</option>
<option value="behavior">目标行为</option>
<option value="driver">核心驱动</option>
<option value="narrative">叙事策略</option>
</select>
</div>
<div>
<label className={`block text-sm mb-2 ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>干预内容</label>
<textarea
rows={4}
className={`w-full px-4 py-2.5 rounded-lg text-sm resize-none ${
isDark
? 'bg-slate-900/50 border border-blue-800/30 text-white placeholder-slate-500'
: 'bg-white border border-gray-200 text-gray-900 placeholder-gray-400'
}`}
placeholder="请输入人工干预的具体内容或修正意见..."
/>
</div>
<div className="flex gap-3 pt-2">
<button
onClick={() => setShowHumanIntervention(false)}
className={`flex-1 px-4 py-2.5 rounded-lg text-sm transition-colors border ${
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-200 text-gray-700'
}`}
>
取消
</button>
<button className={`flex-1 px-4 py-2.5 rounded-lg text-sm transition-colors ${
isDark
? 'bg-purple-600 hover:bg-purple-500 text-white'
: 'bg-red-600 hover:bg-red-500 text-white shadow-md'
}`}>
确认干预
</button>
</div>
</div>
</div>
</div>
)}
</div>
);
};
export default TaskWorkspace;