import React, { useState, useEffect } from 'react'; import { useTheme } from '../contexts/ThemeContext'; import { ArrowLeft, Save, Download, Send, RotateCcw, PlayCircle, CheckCircle2, Circle, Loader2, ChevronDown, ChevronRight, FileText, Link2, Upload, Clock, AlertTriangle, Sparkles, Users, Copy, CheckCheck, RefreshCw, Database, BarChart3, PieChart, LineChart, Table, User, MessageSquare, Network, Target, BookOpen, Calendar, Search, } from 'lucide-react'; import { LightAppType } from './LightAppSquare'; // 应用配置接口 interface AppConfig { id: LightAppType; name: string; description: string; icon: React.ElementType; iconColor: string; bgColor: string; inputs: { name: string; label: string; placeholder: string; type: 'text' | 'textarea' | 'link' | 'upload'; required: boolean; }[]; params: { name: string; label: string; options: { value: string; label: string }[]; default: string; }[]; dimensions: { name: string; label: string; default: boolean; }[]; steps: string[]; previewFields: { key: string; label: string }[]; } interface LightAppRunProps { onNavigate: (page: string, appId?: string) => void; appId?: LightAppType; } // 应用配置数据 const appConfigs: Record = { 'info-ty': { id: 'info-ty', name: '信息TY', description: '围绕单条或多条信息进行TY向分析', icon: FileText, iconColor: 'text-blue-500', bgColor: 'bg-blue-500/10', inputs: [ { name: 'mainInput', label: '信息文本', placeholder: '请输入信息内容...', type: 'textarea', required: true }, { name: 'link', label: '信息链接', placeholder: '可选,粘贴信息链接', type: 'link', required: false }, { name: 'materials', label: '上传材料', placeholder: '支持 txt, pdf, docx', type: 'upload', required: false }, ], params: [ { name: 'timeRange', label: '时间范围', options: [ { value: '7d', label: '近7天' }, { value: '30d', label: '近30天' }, { value: '90d', label: '近90天' }, { value: 'all', label: '全部' }, ], default: '30d' }, { name: 'dataRange', label: '数据范围', options: [ { value: 'all', label: '全部' }, { value: '国内', label: '国内' }, { value: '境外', label: '境外' }, ], default: 'all' }, { name: 'depth', label: '输出深度', options: [ { value: 'brief', label: '简略' }, { value: 'standard', label: '标准' }, { value: 'detailed', label: '详细' }, ], default: 'standard' }, ], dimensions: [ { name: 'basic', label: '基础分析', default: true }, { name: 'risk', label: '风险提示', default: true }, { name: 'summary', label: '摘要结论', default: true }, ], steps: ['已识别输入对象', '已获取数据', '已完成核心分析', '已生成结果'], previewFields: [ { key: 'title', label: '信息标题' }, { key: 'time', label: '发布时间' }, { key: 'source', label: '信息来源' }, ], }, 'info-pg': { id: 'info-pg', name: '信息PG', description: '围绕单条或多条信息进行PG向分析', icon: User, iconColor: 'text-cyan-500', bgColor: 'bg-cyan-500/10', inputs: [ { name: 'mainInput', label: '信息文本', placeholder: '请输入信息内容...', type: 'textarea', required: true }, { name: 'materials', label: '上传材料', placeholder: '支持 txt, pdf, docx', type: 'upload', required: false }, ], params: [ { name: 'timeRange', label: '时间范围', options: [ { value: '30d', label: '近30天' }, { value: '90d', label: '近90天' }, { value: '180d', label: '近半年' }, { value: 'all', label: '全部' }, ], default: '30d' }, { name: 'count', label: '抓取条数', options: [ { value: '50', label: '50条' }, { value: '100', label: '100条' }, { value: '200', label: '200条' }, { value: '500', label: '500条' }, ], default: '100' }, ], dimensions: [ { name: 'profile', label: '画像分析', default: true }, { name: 'tendency', label: '内容倾向', default: true }, { name: 'behavior', label: '行为特征', default: true }, ], steps: ['已识别输入对象', '已获取数据', '已完成画像分析', '已生成结果'], previewFields: [ { key: 'title', label: '信息标题' }, { key: 'author', label: '发布者' }, { key: 'type', label: '内容类型' }, ], }, 'info-spread': { id: 'info-spread', name: '信息传播分析', description: '分析信息传播路径、传播范围与传播表现', icon: Network, iconColor: 'text-teal-500', bgColor: 'bg-teal-500/10', inputs: [ { name: 'link', label: '信息链接', placeholder: '请粘贴信息链接', type: 'link', required: true }, { name: 'text', label: '信息文本', placeholder: '可选,补充信息文本', type: 'textarea', required: false }, ], params: [ { name: 'scope', label: '传播范围', options: [ { value: 'all', label: '全部' }, { value: 'domestic', label: '国内' }, { value: 'overseas', label: '境外' }, ], default: 'all' }, { name: 'timeRange', label: '时间范围', options: [ { value: '7d', label: '近7天' }, { value: '30d', label: '近30天' }, { value: '90d', label: '近90天' }, ], default: '7d' }, ], dimensions: [ { name: 'path', label: '传播路径', default: true }, { name: 'nodes', label: '传播节点', default: true }, { name: 'performance', label: '传播表现', default: true }, { name: 'impact', label: '影响摘要', default: true }, ], steps: ['已识别信息', '已获取传播数据', '已完成传播路径分析', '已生成结果'], previewFields: [ { key: 'title', label: '信息标题' }, { key: 'originalPlatform', label: '原始平台' }, { key: 'totalSpread', label: '总传播量' }, ], }, 'account-pg': { id: 'account-pg', name: '账号PG', description: '围绕账号内容与行为特征进行PG分析', icon: Users, iconColor: 'text-purple-500', bgColor: 'bg-purple-500/10', inputs: [ { name: 'accountId', label: '账号ID/链接', placeholder: '请输入账号ID或粘贴账号链接', type: 'text', required: true }, { name: 'materials', label: '上传内容包', placeholder: '支持 json, csv, zip', type: 'upload', required: false }, ], params: [ { name: 'timeRange', label: '时间范围', options: [ { value: '30d', label: '近30天' }, { value: '90d', label: '近90天' }, { value: '180d', label: '近半年' }, { value: 'all', label: '全部' }, ], default: '30d' }, { name: 'count', label: '抓取条数', options: [ { value: '50', label: '50条' }, { value: '100', label: '100条' }, { value: '200', label: '200条' }, { value: '500', label: '500条' }, ], default: '100' }, ], dimensions: [ { name: 'profile', label: '账号画像', default: true }, { name: 'tendency', label: '内容倾向', default: true }, { name: 'behavior', label: '行为特征', default: true }, { name: 'impact', label: '影响判断', default: true }, ], steps: ['已定位账号', '已抓取内容', '已完成内容倾向分析', '已完成账号画像分析', '已生成结果'], previewFields: [ { key: 'accountName', label: '账号名称' }, { key: 'accountType', label: '账号类型' }, { key: 'followers', label: '粉丝数' }, ], }, 'sentiment': { id: 'sentiment', name: '三情分析', description: '对事件进行舆情、社情、民情综合分析', icon: MessageSquare, iconColor: 'text-orange-500', bgColor: 'bg-orange-500/10', inputs: [ { name: 'eventName', label: '事件名称', placeholder: '请输入事件名称', type: 'text', required: true }, { name: 'eventLink', label: '事件链接', placeholder: '可选,粘贴事件相关链接', type: 'link', required: false }, { name: 'materials', label: '上传材料', placeholder: '支持上传相关素材', type: 'upload', required: false }, ], params: [ { name: 'timeRange', label: '时间范围', options: [ { value: '7d', label: '近7天' }, { value: '30d', label: '近30天' }, { value: '90d', label: '近90天' }, ], default: '7d' }, { name: 'dataRange', label: '数据范围', options: [ { value: 'all', label: '全部' }, { value: '国内', label: '国内' }, { value: '境外', label: '境外' }, ], default: 'all' }, ], dimensions: [ { name: 'publicSentiment', label: '舆情分析', default: true }, { name: 'socialSentiment', label: '社情分析', default: true }, { name: 'publicOpinion', label: '民情分析', default: true }, { name: 'riskAlert', label: '风险提示', default: true }, ], steps: ['已识别事件', '已聚合相关内容', '已完成舆情分析', '已完成社情分析', '已完成民情分析', '已生成结果'], previewFields: [ { key: 'eventName', label: '事件名称' }, { key: 'eventTime', label: '事件时间' }, { key: 'relatedCount', label: '相关内容数' }, ], }, 'event': { id: 'event', name: '事件分析', description: '围绕某个事件进行整体分析', icon: Target, iconColor: 'text-red-500', bgColor: 'bg-red-500/10', inputs: [ { name: 'eventName', label: '事件名称', placeholder: '请输入事件名称', type: 'text', required: true }, { name: 'eventDesc', label: '事件说明', placeholder: '请补充事件相关说明', type: 'textarea', required: false }, { name: 'materials', label: '上传材料', placeholder: '支持上传事件相关材料', type: 'upload', required: false }, ], params: [ { name: 'timeRange', label: '时间范围', options: [ { value: '30d', label: '近30天' }, { value: '90d', label: '近90天' }, { value: '180d', label: '近半年' }, { value: 'all', label: '全部' }, ], default: '30d' }, { name: 'depth', label: '输出深度', options: [ { value: 'brief', label: '简略' }, { value: 'standard', label: '标准' }, { value: 'detailed', label: '详细' }, ], default: 'standard' }, ], dimensions: [ { name: 'context', label: '事件脉络', default: true }, { name: 'keyPoints', label: '关键节点', default: true }, { name: 'risk', label: '风险判断', default: true }, { name: 'suggestions', label: '初步建议', default: true }, ], steps: ['已识别事件', '已整理事件材料', '已完成脉络分析', '已完成风险判断', '已生成结果'], previewFields: [ { key: 'eventName', label: '事件名称' }, { key: 'eventStage', label: '所处阶段' }, { key: 'keyPlayers', label: '关键参与者' }, ], }, 'topic': { id: 'topic', name: '专题分析', description: '对某专题做集中分析', icon: BookOpen, iconColor: 'text-green-500', bgColor: 'bg-green-500/10', inputs: [ { name: 'topicName', label: '专题名称', placeholder: '请输入专题名称', type: 'text', required: true }, { name: 'materials', label: '上传材料', placeholder: '支持上传专题相关文本集合', type: 'upload', required: false }, ], params: [ { name: 'depth', label: '分析深度', options: [ { value: 'surface', label: '表面' }, { value: 'standard', label: '标准' }, { value: 'deep', label: '深度' }, ], default: 'standard' }, { name: 'sourceRange', label: '来源范围', options: [ { value: 'all', label: '全部' }, { value: '国内', label: '国内' }, { value: '境外', label: '境外' }, ], default: 'all' }, ], dimensions: [ { name: 'structure', label: '专题结构', default: true }, { name: 'coreIssues', label: '核心问题', default: true }, { name: 'viewpoints', label: '观点聚合', default: true }, { name: 'conclusions', label: '结论建议', default: true }, ], steps: ['已识别专题', '已获取相关材料', '已完成结构分析', '已聚合核心观点', '已生成结果'], previewFields: [ { key: 'topicName', label: '专题名称' }, { key: 'relatedDocs', label: '相关文档' }, { key: 'coverage', label: '覆盖范围' }, ], }, }; type ResultTab = 'overview' | 'details' | 'raw'; const LightAppRun: React.FC = ({ onNavigate, appId }) => { const { theme } = useTheme(); const isDark = theme === 'dark'; const [currentAppId, setCurrentAppId] = useState(appId || 'sentiment'); const [resultTab, setResultTab] = useState('overview'); const [isRunning, setIsRunning] = useState(false); const [currentStep, setCurrentStep] = useState(0); const [copied, setCopied] = useState(false); const [formData, setFormData] = useState>({}); const [params, setParams] = useState>({}); const [dimensions, setDimensions] = useState>({}); const [hasResult, setHasResult] = useState(false); const [result, setResult] = useState(null); const config = appConfigs[currentAppId]; const Icon = config.icon; // 初始化表单数据 useEffect(() => { console.log('当前应用:', currentAppId); if (config) { const initialForm: Record = {}; config.inputs.forEach(input => { initialForm[input.name] = ''; }); setFormData(initialForm); const initialParams: Record = {}; config.params.forEach(param => { initialParams[param.name] = param.default; }); setParams(initialParams); const initialDims: Record = {}; config.dimensions.forEach(dim => { initialDims[dim.name] = dim.default; }); setDimensions(initialDims); } }, [currentAppId]); // 执行分析 const handleRun = async () => { setIsRunning(true); setCurrentStep(0); setHasResult(false); // 模拟执行步骤 for (let i = 0; i < config.steps.length; i++) { await new Promise(resolve => setTimeout(resolve, 800)); setCurrentStep(i + 1); } // 生成结果 await new Promise(resolve => setTimeout(resolve, 500)); setResult(generateMockResult()); setHasResult(true); setIsRunning(false); }; // 生成模拟结果 const generateMockResult = () => { switch (currentAppId) { case 'sentiment': return { overview: { overallSentiment: '中偏负', mainConcerns: ['活动形式', '品牌调性', '执行成本'], riskAlert: '讨论热度上升,负向占比增加', sentimentTrend: '下行', }, details: { publicSentiment: '舆情方面,主要关注点是活动本身的创新性和参与体验。部分用户对活动细节提出质疑,整体讨论呈现多元化特征。', socialSentiment: '社情方面,该事件引发了关于活动公平性的讨论,社交媒体上相关话题讨论量显著上升。', publicOpinion: '民情方面,公众对该活动的看法分化明显,支持和反对声音并存,需关注后续舆情走向。', riskAssessment: '当前风险等级:中。建议持续关注舆情变化,准备应对预案。', }, raw: [ { type: '正面评论', content: '活动创意很好,期待参与', count: 234 }, { type: '中性评论', content: '等待活动正式开始', count: 567 }, { type: '负面评论', content: '对活动细节表示质疑', count: 189 }, ], }; case 'event': return { overview: { eventStage: '发酵期', keyNodes: '活动公布期,关注度持续上升', riskLevel: '中', suggestion: '建议加强信息透明度,及时回应公众关切', }, details: { context: '该事件起因于...,经过...,目前处于...阶段。', keyPoints: ['关键节点一:...', '关键节点二:...', '关键节点三:...'], riskJudgment: '风险可控,但需关注...', suggestions: '1. ... 2. ... 3. ...', }, raw: [ { time: '2026-03-18', title: '事件起因', content: '...' }, { time: '2026-03-19', title: '初步发酵', content: '...' }, { time: '2026-03-20', title: '关注度上升', content: '...' }, ], }; case 'account-pg': return { overview: { accountProfile: '该账号为...类型账号', contentTendency: '内容倾向明显偏...', influenceJudgment: '具有一定影响力,需关注...', }, details: { profileAnalysis: '账号画像分析...', contentAnalysis: '内容倾向分析...', behaviorAnalysis: '行为特征分析...', influenceAnalysis: '影响判断分析...', }, raw: [ { date: '2026-03-15', content: '...' }, { date: '2026-03-16', content: '...' }, { date: '2026-03-17', content: '...' }, ], }; default: return { overview: { summary: '分析结果摘要...' }, details: { analysis: '详细分析内容...' }, raw: [], }; } }; // 重置 const handleReset = () => { const initialForm: Record = {}; config.inputs.forEach(input => { initialForm[input.name] = ''; }); setFormData(initialForm); const initialParams: Record = {}; config.params.forEach(param => { initialParams[param.name] = param.default; }); setParams(initialParams); const initialDims: Record = {}; config.dimensions.forEach(dim => { initialDims[dim.name] = dim.default; }); setDimensions(initialDims); setHasResult(false); setResult(null); setCurrentStep(0); }; // 复制结果 const handleCopy = () => { navigator.clipboard.writeText(JSON.stringify(result, null, 2)); setCopied(true); setTimeout(() => setCopied(false), 2000); }; // 保存快照 const handleSaveSnapshot = () => { // 模拟保存 alert('快照已保存到运行记录'); onNavigate('light-app-records'); }; // 导出 const handleExport = () => { const blob = new Blob([JSON.stringify(result, null, 2)], { type: 'application/json' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `${config.name}_结果_${new Date().toISOString().split('T')[0]}.json`; a.click(); }; return (
{/* 顶部操作栏 */}

{config.name}

{config.description}

{/* 主体内容区 - 三栏布局 */}
{/* 左侧:输入与配置 */}
{/* 输入对象 */}

输入对象

{config.inputs.map(input => (
{input.type === 'textarea' ? (