Files
deerflow-code/web-code/components/taskManagement/TaskSingle.tsx
T
2026-05-27 19:43:15 +08:00

716 lines
32 KiB
TypeScript

import React, { useState } from 'react';
import {
ArrowLeft,
Bot,
CheckCircle,
Clock,
User,
Download,
FileText,
Send,
Zap,
Sparkles,
Lightbulb,
Copy,
Edit3,
ChevronDown,
ChevronRight,
Database,
Brain,
MessageSquare,
ExternalLink,
BookOpen,
Info,
Eye,
} from 'lucide-react';
import { useTheme } from '@/contexts/ThemeContext';
import { PageType } from '@/components/Sidebar';
interface TaskSingleProps {
onNavigate: (page: PageType) => void;
}
interface ChatMessage {
id: string;
role: 'user' | 'agent';
content: string;
timestamp: string;
citations?: { title: string; source: string; page?: number }[];
}
const TaskSingle: React.FC<TaskSingleProps> = ({ onNavigate }) => {
const { theme } = useTheme();
const isDark = theme === 'dark';
const [taskStatus, setTaskStatus] = useState<'pending' | 'running' | 'completed'>('completed');
const [input, setInput] = useState('请分析五四青年节宣传活动的目标受众');
const [isRunning, setIsRunning] = useState(false);
const [showCitations, setShowCitations] = useState<string | null>(null);
const [isEditing, setIsEditing] = useState(false);
const [editedContent, setEditedContent] = useState('');
const [messages, setMessages] = useState<ChatMessage[]>([
{
id: '1',
role: 'user',
content: '请分析五四青年节宣传活动的目标受众',
timestamp: '14:00',
},
{
id: '2',
role: 'agent',
content: `根据您的任务要求,我对五四青年节宣传活动的目标受众进行了全面分析,以下是详细报告:
## 一、核心受众画像
**基本信息**
- 年龄段:18-25岁
- 身份定位:基层青年(学生、职场新人)
- 地域分布:一二线城市为主
**用户特征**
- 社交媒体重度用户,日均使用时长超过3小时
- 短视频内容消费主力,偏好竖屏内容
- 注重"真实感"和"态度感",反感过度营销
- 追求个性化表达和群体认同
## 二、行为洞察
**媒体习惯**
- 主要平台:抖音、小红书、微博、B站
- 内容偏好:真实故事、情感共鸣、实用价值
- 互动方式:点赞、评论、转发、UGC创作
**决策因素**
- 社交认同 > 品牌声誉 > 产品功能
- 性价比 > 品牌溢价
- 真实体验 > 官方宣传
## 三、核心需求
1. **归属感需求** - 希望被看见、被认可,参与活动获得身份认同
2. **表达欲驱动** - 有态度的内容激发创作冲动
3. **社交认同激励** - 优质内容获得曝光和认可
## 结论
核心受众应聚焦18-25岁基层青年群体,这部分用户与品牌年轻化战略高度契合。`,
timestamp: '14:03',
citations: [
{ title: 'Z世代消费行为研究报告', source: '市场研究数据库', page: 23 },
{ title: '短视频平台用户画像', source: 'Y系统-用户标签', page: 5 },
{ title: '品牌年轻化营销案例集', source: '宣传知识库', page: 45 },
],
},
]);
const agentConfig = {
name: 'AudienceAgent',
role: '受众分析专家',
description: '分析目标受众画像、行为特征和核心需求,为策略制定提供数据支持',
skills: [
{ name: '受众分层', type: '分析类', status: 'enabled' },
{ name: '核心受众识别', type: '推断类', status: 'enabled' },
{ name: '受众画像抽取', type: '抽取类', status: 'enabled' },
{ name: '阻力因素提炼', type: '分析类', status: 'enabled' },
],
databases: [
{ name: '宣传知识库', type: '知识库', access: '品牌案例、活动方法论', status: 'connected' },
{ name: 'Y系统', type: '业务系统', access: '用户标签、传播数据', status: 'connected' },
{ name: '市场数据库', type: '外部数据源', access: '市场报告、用户研究', status: 'connected' },
],
outputFields: ['core_audience', 'key_traits', 'concerns', 'barriers'],
};
const analysisResult = {
title: '五四青年节宣传活动目标受众分析报告',
agent: 'AudienceAgent',
completionTime: '2026-03-19 14:03',
status: '已完成',
summary: '核心受众聚焦18-25岁基层青年群体,需用"真实、有态度"的内容打动',
};
const handleSend = () => {
if (!input.trim()) return;
const userMessage: ChatMessage = {
id: Date.now().toString(),
role: 'user',
content: input,
timestamp: new Date().toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' }),
};
setMessages([...messages, userMessage]);
setInput('');
setIsRunning(true);
setTimeout(() => {
const agentMessage: ChatMessage = {
id: (Date.now() + 1).toString(),
role: 'agent',
content: '分析结果已生成,请查看上方报告详情。',
timestamp: new Date().toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' }),
citations: [
{ title: '青年消费趋势报告', source: '市场数据库', page: 12 },
],
};
setMessages(prev => [...prev, agentMessage]);
setIsRunning(false);
setTaskStatus('completed');
}, 2000);
};
const handleCopyResult = () => {
const content = messages.filter(m => m.role === 'agent').map(m => m.content).join('\n\n');
navigator.clipboard.writeText(content);
};
const handleEditResult = () => {
if (isEditing) {
setIsEditing(false);
} else {
setEditedContent(messages.filter(m => m.role === 'agent').map(m => m.content).join('\n\n'));
setIsEditing(true);
}
};
const handleExport = () => {
const content = `# ${analysisResult.title}\n\n智能体:${analysisResult.agent}\n完成时间:${analysisResult.completionTime}\n状态:${analysisResult.status}\n\n---\n\n${messages.filter(m => m.role === 'agent').map(m => m.content).join('\n\n')}`;
const blob = new Blob([content], { type: 'text/markdown' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'audience_analysis_report.md';
a.click();
URL.revokeObjectURL(url);
};
return (
<div className="h-[calc(100vh-140px)] flex flex-col">
{/* 顶部工具栏 */}
<div className={`rounded-xl p-4 flex-shrink-0 theme-card 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-4">
<button
onClick={() => onNavigate('task-list')}
className={`flex items-center gap-2 px-3 py-2 rounded-lg text-sm transition-colors ${
isDark
? 'bg-slate-700/50 hover:bg-slate-600/50 border border-blue-800/30 text-slate-300'
: 'bg-red-50 hover:bg-red-100 border border-red-200 text-red-600'
}`}
>
<ArrowLeft className="w-4 h-4" />
返回
</button>
<div className={`h-8 w-px ${isDark ? 'bg-blue-800/30' : 'bg-red-200'}`} />
<div>
<h1 className={`font-bold ${isDark ? 'text-white' : 'text-gray-900'}`}>五四青年节受众分析</h1>
<p className={`text-xs ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>单智能体任务 · AudienceAgent</p>
</div>
</div>
<div className="flex items-center gap-2">
<span className={`px-3 py-1.5 rounded-full text-xs font-medium flex items-center gap-1.5 ${
taskStatus === 'completed'
? isDark
? 'bg-green-500/20 text-green-400'
: 'bg-green-100 text-green-600'
: taskStatus === 'running'
? isDark
? 'bg-blue-500/20 text-blue-400'
: 'bg-red-100 text-red-600'
: isDark
? 'bg-slate-500/20 text-slate-400'
: 'bg-gray-100 text-gray-600'
}`}>
{taskStatus === 'completed' ? (
<><CheckCircle className="w-3 h-3" /> 已完成</>
) : taskStatus === 'running' ? (
<><Clock className="w-3 h-3" /> 运行中</>
) : (
<><Clock className="w-3 h-3" /> 待运行</>
)}
</span>
</div>
</div>
</div>
{/* 主内容区:三栏布局 - 中间栏加宽,右侧栏变窄 */}
<div className="flex-1 grid grid-cols-12 gap-4 mt-4 min-h-0">
{/* 左侧栏 (15%) - 任务信息 + 智能体配置 */}
<div className={`col-span-2 flex flex-col gap-4 min-h-0 overflow-y-auto ${
isDark ? '' : 'pr-2'
}`}>
{/* 任务信息卡片 */}
<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'}`}>
<span className={isDark ? 'text-blue-400' : 'text-red-500'}>
<FileText className="w-4 h-4" />
</span>
任务信息
</h3>
<div className="space-y-3 text-sm">
<div className="flex items-center justify-between">
<span className={isDark ? 'text-slate-500' : 'text-gray-500'}>任务类型</span>
<span className={`px-2 py-0.5 rounded text-xs ${
isDark
? 'bg-blue-500/20 text-blue-400'
: 'bg-red-100 text-red-600'
}`}>单智能体</span>
</div>
<div className="flex items-center justify-between">
<span className={isDark ? 'text-slate-500' : 'text-gray-500'}>执行智能体</span>
<span className={isDark ? 'text-cyan-400' : 'text-red-600'}>AudienceAgent</span>
</div>
<div className="flex items-center justify-between">
<span className={isDark ? 'text-slate-500' : 'text-gray-500'}>创建时间</span>
<span className={isDark ? 'text-slate-400' : 'text-gray-600'}>14:00</span>
</div>
<div className="flex items-center justify-between">
<span className={isDark ? 'text-slate-500' : 'text-gray-500'}>完成时间</span>
<span className={isDark ? 'text-slate-400' : 'text-gray-600'}>14:03</span>
</div>
</div>
</div>
{/* 智能体配置卡片 */}
<div className={`rounded-xl p-4 flex-1 overflow-y-auto border theme-card scrollbar-thin ${
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'}`}>
<span className={isDark ? 'text-cyan-400' : 'text-red-500'}>
<Bot className="w-4 h-4" />
</span>
智能体配置
</h3>
{/* 智能体简介 */}
<div className={`mb-4 p-3 rounded-lg ${
isDark ? 'bg-slate-900/50' : 'bg-red-50'
}`}>
<p className={`text-sm font-medium mb-1 ${isDark ? 'text-cyan-400' : 'text-red-600'}`}>{agentConfig.name}</p>
<p className={`text-xs mb-2 ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>{agentConfig.role}</p>
<p className={`text-xs ${isDark ? 'text-slate-500' : 'text-gray-400'}`}>{agentConfig.description}</p>
</div>
{/* 技能列表 */}
<div className="mb-4">
<div className="flex items-center gap-2 mb-2">
<Brain className={`w-4 h-4 ${isDark ? 'text-purple-400' : 'text-red-500'}`} />
<span className={`text-xs ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>启用技能</span>
</div>
<div className="space-y-1.5">
{agentConfig.skills.map((skill, index) => (
<div key={index} className={`flex items-center justify-between p-2 rounded ${
isDark ? 'bg-slate-900/50' : 'bg-red-50'
}`}>
<span className={`text-xs ${isDark ? 'text-slate-300' : 'text-gray-700'}`}>{skill.name}</span>
<span className={`px-1.5 py-0.5 rounded text-[10px] ${
isDark
? 'bg-purple-500/20 text-purple-400'
: 'bg-red-100 text-red-600'
}`}>{skill.type}</span>
</div>
))}
</div>
</div>
{/* 数据源列表 */}
<div>
<div className="flex items-center gap-2 mb-2">
<Database className={`w-4 h-4 ${isDark ? 'text-green-400' : 'text-red-500'}`} />
<span className={`text-xs ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>可调用数据源</span>
</div>
<div className="space-y-1.5">
{agentConfig.databases.map((db, index) => (
<div key={index} className={`p-2 rounded ${
isDark ? 'bg-slate-900/50' : 'bg-red-50'
}`}>
<div className="flex items-center justify-between mb-1">
<span className={`text-xs ${isDark ? 'text-slate-300' : 'text-gray-700'}`}>{db.name}</span>
<span className={`w-1.5 h-1.5 rounded-full ${
db.status === 'connected'
? isDark ? 'bg-green-400' : 'bg-red-500'
: 'bg-slate-500'
}`} />
</div>
<p className={`text-[10px] ${isDark ? 'text-slate-500' : 'text-gray-400'}`}>{db.access}</p>
</div>
))}
</div>
</div>
</div>
</div>
{/* 中间栏 (65%) - 对话式问答 - 加宽 */}
<div className="col-span-7 flex flex-col min-h-0">
<div className={`rounded-xl flex-1 flex flex-col min-h-0 border theme-card ${
isDark
? 'bg-slate-800/30 backdrop-blur-xl border-blue-800/30'
: 'bg-white border-red-100 shadow-sm'
}`}>
{/* 对话区域头部 */}
<div className={`p-4 border-b flex-shrink-0 ${
isDark ? 'border-blue-800/30' : 'border-red-100'
}`}>
<h3 className={`font-semibold flex items-center gap-2 ${isDark ? 'text-white' : 'text-gray-900'}`}>
<span className={isDark ? 'text-blue-400' : 'text-red-500'}>
<MessageSquare className="w-4 h-4" />
</span>
对话分析
</h3>
</div>
{/* 消息列表 */}
<div className="flex-1 overflow-y-auto p-4 space-y-4 scrollbar-thin">
{messages.map((msg) => (
<div key={msg.id} className={`flex ${msg.role === 'user' ? 'justify-end' : 'justify-start'}`}>
<div className={`max-w-[85%] rounded-xl p-4 border ${
msg.role === 'user'
? isDark
? 'bg-blue-600/30 border-blue-500/30'
: 'bg-red-50 border-red-200'
: isDark
? 'bg-slate-900/50 border-blue-800/30'
: 'bg-gray-50 border-gray-200'
}`}>
<div className="flex items-center gap-2 mb-2">
{msg.role === 'agent' ? (
<Bot className={`w-4 h-4 ${isDark ? 'text-cyan-400' : 'text-red-500'}`} />
) : (
<User className={`w-4 h-4 ${isDark ? 'text-blue-400' : 'text-red-500'}`} />
)}
<span className={`text-xs font-medium ${
msg.role === 'user'
? isDark ? 'text-blue-400' : 'text-red-600'
: isDark ? 'text-cyan-400' : 'text-red-600'
}`}>
{msg.role === 'user' ? '你' : 'AudienceAgent'}
</span>
<span className={`text-[10px] ${isDark ? 'text-slate-500' : 'text-gray-400'}`}>{msg.timestamp}</span>
</div>
<p className={`text-sm whitespace-pre-wrap ${
isDark ? 'text-slate-300' : 'text-gray-700'
}`}>{msg.content}</p>
{/* 引用信息 */}
{msg.citations && msg.citations.length > 0 && (
<div className={`mt-3 pt-3 border-t ${
isDark ? 'border-blue-800/30' : 'border-red-200'
}`}>
<button
onClick={() => setShowCitations(showCitations === msg.id ? null : msg.id)}
className={`flex items-center gap-2 text-xs transition-colors ${
isDark ? 'text-slate-400 hover:text-blue-400' : 'text-gray-500 hover:text-red-500'
}`}
>
<BookOpen className="w-3 h-3" />
查看引用 ({msg.citations.length})
{showCitations === msg.id ? <ChevronDown className="w-3 h-3" /> : <ChevronRight className="w-3 h-3" />}
</button>
{showCitations === msg.id && (
<div className="mt-2 space-y-2">
{msg.citations.map((citation, index) => (
<div className={`p-2 rounded flex items-start gap-2 ${
isDark ? 'bg-slate-800/50' : 'bg-white border border-gray-200'
}`}>
<ExternalLink className={`w-3 h-3 mt-0.5 ${isDark ? 'text-slate-500' : 'text-gray-400'}`} />
<div>
<p className={`text-xs ${isDark ? 'text-slate-300' : 'text-gray-700'}`}>{citation.title}</p>
<p className={`text-[10px] ${isDark ? 'text-slate-500' : 'text-gray-400'}`}>{citation.source} {citation.page && `· 第${citation.page}页`}</p>
</div>
</div>
))}
</div>
)}
</div>
)}
</div>
</div>
))}
{isRunning && (
<div className="flex justify-start">
<div className={`rounded-xl p-4 border ${
isDark ? 'bg-slate-900/50 border-blue-800/30' : 'bg-gray-50 border-gray-200'
}`}>
<div className="flex items-center gap-2">
<Bot className={`w-4 h-4 ${isDark ? 'text-cyan-400' : 'text-red-500'}`} />
<span className={`text-sm ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>分析中...</span>
<div className="flex gap-1">
<span className={`w-1.5 h-1.5 rounded-full animate-pulse ${
isDark ? 'bg-cyan-400' : 'bg-red-500'
}`} />
<span className={`w-1.5 h-1.5 rounded-full animate-pulse ${
isDark ? 'bg-cyan-400' : 'bg-red-500'
}`} style={{ animationDelay: '100ms' }} />
<span className={`w-1.5 h-1.5 rounded-full animate-pulse ${
isDark ? 'bg-cyan-400' : 'bg-red-500'
}`} style={{ animationDelay: '200ms' }} />
</div>
</div>
</div>
</div>
)}
</div>
{/* 输入区域 */}
<div className={`p-4 border-t flex-shrink-0 ${
isDark ? 'border-blue-800/30' : 'border-red-100'
}`}>
<div className="flex gap-2">
<input
type="text"
value={input}
onChange={(e) => setInput(e.target.value)}
onKeyDown={(e) => e.key === 'Enter' && handleSend()}
placeholder="输入问题或任务要求..."
className={`flex-1 px-4 py-2.5 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-red-500/20 transition-colors ${
isDark
? 'bg-slate-900/50 border border-blue-800/30 text-white placeholder-slate-500'
: 'bg-white border border-red-200 text-gray-900 placeholder-gray-400'
}`}
/>
<button
onClick={handleSend}
disabled={isRunning}
className={`px-4 py-2.5 rounded-lg text-sm transition-colors flex items-center gap-2 ${
isDark
? 'bg-blue-600 hover:bg-blue-500 disabled:bg-slate-700 text-white'
: 'bg-red-600 hover:bg-red-500 disabled:bg-gray-400 text-white shadow-md'
}`}
>
<Send className="w-4 h-4" />
发送
</button>
</div>
</div>
</div>
</div>
{/* 右侧栏 (20%) - 分析结果 - 变窄 */}
<div className="col-span-3 flex flex-col min-h-0">
<div className={`rounded-xl flex-1 flex flex-col min-h-0 border theme-card ${
isDark
? 'bg-slate-800/30 backdrop-blur-xl border-blue-800/30'
: 'bg-white border-red-100 shadow-sm'
}`}>
{/* 结果区域头部 */}
<div className={`p-4 border-b flex-shrink-0 ${
isDark ? 'border-blue-800/30' : 'border-red-100'
}`}>
<div className="flex items-center justify-between">
<h3 className={`font-semibold flex items-center gap-2 ${isDark ? 'text-white' : 'text-gray-900'}`}>
<span className={isDark ? 'text-purple-400' : 'text-red-500'}>
<Sparkles className="w-4 h-4" />
</span>
分析结果
</h3>
<div className="flex items-center gap-1">
<button
onClick={handleCopyResult}
className={`p-2 rounded-lg transition-colors ${
isDark ? 'hover:bg-slate-700/50' : 'hover:bg-red-50'
}`}
title="复制结果"
>
<Copy className={`w-4 h-4 ${isDark ? 'text-slate-400' : 'text-red-400'}`} />
</button>
<button
onClick={handleEditResult}
className={`p-2 rounded-lg transition-colors ${
isDark ? 'hover:bg-slate-700/50' : 'hover:bg-red-50'
}`}
title="编辑结果"
>
<Edit3 className={`w-4 h-4 ${isEditing ? (isDark ? 'text-blue-400' : 'text-red-500') : (isDark ? 'text-slate-400' : 'text-red-400')}`} />
</button>
<button
onClick={handleExport}
className={`p-2 rounded-lg transition-colors ${
isDark ? 'hover:bg-slate-700/50' : 'hover:bg-red-50'
}`}
title="导出结果"
>
<Download className={`w-4 h-4 ${isDark ? 'text-slate-400' : 'text-red-400'}`} />
</button>
</div>
</div>
</div>
{/* 结果内容 */}
<div className="flex-1 overflow-y-auto p-4 scrollbar-thin">
{/* 结果概览 */}
<div className={`mb-4 p-4 rounded-xl border ${
isDark
? 'bg-gradient-to-br from-purple-600/20 to-blue-600/20 border-purple-500/30'
: 'bg-gradient-to-br from-red-50 to-red-100 border-red-200'
}`}>
<h4 className={`font-medium text-sm mb-2 ${isDark ? 'text-white' : 'text-gray-900'}`}>{analysisResult.title}</h4>
<div className={`flex items-center gap-4 text-xs ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>
<span className="flex items-center gap-1">
<Bot className="w-3 h-3" />
{analysisResult.agent}
</span>
<span className="flex items-center gap-1">
<Clock className="w-3 h-3" />
{analysisResult.completionTime}
</span>
</div>
</div>
{/* 结论摘要 */}
<div className="mb-4">
<h4 className={`text-xs mb-2 flex items-center gap-2 ${
isDark ? 'text-slate-400' : 'text-gray-500'
}`}>
<Lightbulb className={`w-3 h-3 ${isDark ? 'text-yellow-400' : 'text-yellow-500'}`} />
核心结论
</h4>
<div className={`p-3 rounded-lg border ${
isDark
? 'bg-blue-500/10 border-blue-500/30'
: 'bg-red-50 border-red-200'
}`}>
<p className={`text-sm ${isDark ? 'text-blue-300' : 'text-red-600'}`}>{analysisResult.summary}</p>
</div>
</div>
{/* 关键洞察 */}
<div className="mb-4">
<h4 className={`text-xs mb-2 flex items-center gap-2 ${
isDark ? 'text-slate-400' : 'text-gray-500'
}`}>
<Eye className={`w-3 h-3 ${isDark ? 'text-green-400' : 'text-green-500'}`} />
关键洞察
</h4>
<div className="space-y-2">
<div className={`p-3 rounded-lg border ${
isDark ? 'bg-slate-900/50 border-blue-800/30' : 'bg-gray-50 border-gray-200'
}`}>
<p className={`text-sm font-medium mb-1 ${isDark ? 'text-white' : 'text-gray-900'}`}>核心受众</p>
<p className={`text-xs ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>18-25岁基层青年群体</p>
</div>
<div className={`p-3 rounded-lg border ${
isDark ? 'bg-slate-900/50 border-blue-800/30' : 'bg-gray-50 border-gray-200'
}`}>
<p className={`text-sm font-medium mb-1 ${isDark ? 'text-white' : 'text-gray-900'}`}>核心驱动</p>
<p className={`text-xs ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>社交认同与真实态度</p>
</div>
<div className={`p-3 rounded-lg border ${
isDark ? 'bg-slate-900/50 border-blue-800/30' : 'bg-gray-50 border-gray-200'
}`}>
<p className={`text-sm font-medium mb-1 ${isDark ? 'text-white' : 'text-gray-900'}`}>内容策略</p>
<p className={`text-xs ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>真实故事 + 情感共鸣 + 实用价值</p>
</div>
</div>
</div>
{/* 详细信息预览 */}
<div>
<h4 className={`text-xs mb-2 flex items-center gap-2 ${
isDark ? 'text-slate-400' : 'text-gray-500'
}`}>
<Info className={`w-3 h-3 ${isDark ? 'text-slate-500' : 'text-gray-400'}`} />
详细报告
</h4>
{isEditing ? (
<textarea
value={editedContent}
onChange={(e) => setEditedContent(e.target.value)}
className={`w-full h-48 p-3 rounded-lg text-xs resize-none focus:outline-none focus:ring-2 focus:ring-red-500/20 ${
isDark
? 'bg-slate-900/50 border border-blue-800/30 text-slate-300'
: 'bg-white border border-gray-200 text-gray-700'
}`}
/>
) : (
<div className={`p-3 rounded-lg max-h-48 overflow-y-auto ${
isDark ? 'bg-slate-900/50 border border-blue-800/30' : 'bg-gray-50 border border-gray-200'
}`}>
<div className={`space-y-3 text-xs ${isDark ? 'text-slate-400' : 'text-gray-500'}`}>
<p>## 核心受众画像</p>
<p className="pl-2">• 年龄段:18-25岁</p>
<p className="pl-2">• 身份定位:基层青年(学生、职场新人)</p>
<p className="pl-2">• 地域分布:一二线城市为主</p>
<p className="pt-2">## 用户特征</p>
<p className="pl-2">• 社交媒体重度用户</p>
<p className="pl-2">• 注重"真实感"和"态度感"</p>
<p className="pl-2">• 追求个性化表达</p>
<p className={`pt-2 ${isDark ? 'text-blue-400' : 'text-red-500'}`}>点击编辑按钮可修改报告内容</p>
</div>
</div>
)}
</div>
{/* 引用来源 */}
<div className="mt-4">
<h4 className={`text-xs mb-2 flex items-center gap-2 ${
isDark ? 'text-slate-400' : 'text-gray-500'
}`}>
<BookOpen className={`w-3 h-3 ${isDark ? 'text-slate-500' : 'text-gray-400'}`} />
引用来源
</h4>
<div className="space-y-1.5">
{[
{ title: 'Z世代消费行为研究报告', source: '市场研究数据库' },
{ title: '短视频平台用户画像', source: 'Y系统-用户标签' },
{ title: '品牌年轻化营销案例集', source: '宣传知识库' },
].map((item, index) => (
<div key={index} className={`flex items-center gap-2 p-2 rounded ${
isDark ? 'bg-slate-900/30' : 'bg-white border border-gray-100'
}`}>
<ExternalLink className={`w-3 h-3 ${isDark ? 'text-slate-500' : 'text-gray-400'}`} />
<div>
<p className={`text-xs ${isDark ? 'text-slate-300' : 'text-gray-700'}`}>{item.title}</p>
<p className={`text-[10px] ${isDark ? 'text-slate-500' : 'text-gray-400'}`}>{item.source}</p>
</div>
</div>
))}
</div>
</div>
</div>
{/* 底部操作 */}
<div className={`p-4 border-t flex-shrink-0 ${
isDark ? 'border-blue-800/30' : 'border-red-100'
}`}>
<div className="flex gap-2">
<button
onClick={handleExport}
className={`flex-1 flex items-center justify-center gap-2 px-4 py-2.5 rounded-lg text-sm transition-colors ${
isDark
? 'bg-blue-600 hover:bg-blue-500 text-white'
: 'bg-red-600 hover:bg-red-500 text-white shadow-md'
}`}
>
<Download className="w-4 h-4" />
导出报告
</button>
<button className={`flex-1 flex items-center justify-center gap-2 px-4 py-2.5 rounded-lg text-sm transition-colors ${
isDark
? 'bg-slate-700/50 hover:bg-slate-600/50 border border-blue-800/30 text-slate-300'
: 'bg-gray-100 hover:bg-gray-200 border border-gray-200 text-gray-700'
}`}>
<Zap className="w-4 h-4" />
存入知识库
</button>
</div>
</div>
</div>
</div>
</div>
</div>
);
};
export default TaskSingle;