Files
n8n_Demo/web_frontend/exhibition-demo/src/pages/WorkflowPageV4.tsx
Yep_Q 08e6304134 feat: 优化会展策划网站UI和添加Duoduo Agent设计流程展示
主要更新:
- 统一所有页面导航栏样式为glass-morphism风格
- 添加Duoduo Agent智能设计系统完整可视化流程
- 展示从CAD到展位概念的5个设计阶段
- 优化页面交互效果和用户体验

详细修改:
- web_frontend/web_result/pages/: 统一6个页面导航栏样式
- operation.html: 新增Duoduo Agent设计流程展示模块
- 添加5张设计阶段图片展示 (CAD/概念/白模/渲染/最终方案)
- 增强视觉效果和动画交互

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-08 15:13:31 +08:00

1063 lines
53 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 { useState, useEffect, useRef } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { useDemoStore } from '@/store/demoStore';
import { Play, Pause, RotateCcw, Maximize2, Terminal, FileInput } from 'lucide-react';
import RequirementModal from '@/components/RequirementModal';
import ResultModal from '@/components/ResultModal';
// Terminal line type
interface TerminalLine {
id: string;
timestamp: string;
type: 'info' | 'success' | 'warning' | 'error' | 'system' | 'output' | 'progress' | 'install' | 'file' | 'image';
agent?: string;
content: string;
typing?: boolean;
isProgressLine?: boolean;
imageSrc?: string;
imageAlt?: string;
}
// 生成随机延迟
const getRandomDelay = (min: number, max: number) => {
return Math.floor(Math.random() * (max - min + 1)) + min;
};
// 生成进度条字符串
const generateProgressBar = (progress: number, width: number = 40) => {
const filled = Math.floor((progress / 100) * width);
const empty = width - filled;
return `[${'█'.repeat(filled)}${'░'.repeat(empty)}] ${progress.toString().padStart(3, ' ')}%`;
};
// 生成文件大小
const generateFileSize = () => {
const sizes = ['12.3KB', '456KB', '1.2MB', '3.4MB', '15.7MB', '48.2MB', '126MB'];
return sizes[Math.floor(Math.random() * sizes.length)];
};
const WorkflowPageV4 = () => {
const { agents, startDemo, pauseDemo, reset, status } = useDemoStore();
const [terminalLines, setTerminalLines] = useState<TerminalLine[]>([]);
const [currentAgentIndex, setCurrentAgentIndex] = useState(-1);
const [elapsedTime, setElapsedTime] = useState(0);
const [isExecuting, setIsExecuting] = useState(false);
const [showRequirementModal, setShowRequirementModal] = useState(false);
const [showResultModal, setShowResultModal] = useState(false);
const [userRequirement, setUserRequirement] = useState('');
const [imageLoadingStates, setImageLoadingStates] = useState<{ [key: string]: boolean }>({});
const terminalRef = useRef<HTMLDivElement>(null);
const intervalRef = useRef<number | null>(null);
const progressLineIdRef = useRef<string | null>(null);
// 启动序列
const startupSequence = [
{ type: 'system', content: '>>> AI Exhibition Planning System v2.0.0' },
{ type: 'system', content: '>>> Copyright (c) 2024 DeepSeek AI. All rights reserved.' },
{ type: 'info', content: '' },
{ type: 'info', content: 'Checking system requirements...' },
{ type: 'progress', content: 'System check', target: 100 },
{ type: 'info', content: '' },
{ type: 'info', content: 'Loading configuration...' },
{ type: 'output', content: 'Config path: /etc/agents/config.yaml' },
{ type: 'output', content: 'Loading agents: 7 experts found' },
{ type: 'output', content: 'Workflow engine: n8n v1.109.2' },
{ type: 'success', content: '✓ Configuration loaded successfully' },
{ type: 'info', content: '' },
{ type: 'info', content: 'Installing required packages...' },
{ type: 'install', content: 'npm install @ai/core @ai/agents @ai/workflow --save' },
{ type: 'progress', content: 'npm packages', target: 100 },
{ type: 'install', content: 'pip install pandas numpy tensorflow beautifulsoup4' },
{ type: 'progress', content: 'Python packages', target: 100 },
{ type: 'success', content: '✓ All dependencies installed' },
{ type: 'info', content: '' },
{ type: 'system', content: '=' .repeat(60) },
{ type: 'system', content: 'SYSTEM READY - Starting multi-agent workflow...' },
{ type: 'system', content: '=' .repeat(60) },
];
// Agent执行序列 - 更真实的输出
const agentSequence = [
{
agent: agents[0], // 信息检索
outputs: [
{ type: 'system', content: '>>> [Agent-1] Information Retrieval Expert Activated' },
{ type: 'info', content: 'Model: DeepSeek-V2 Chat (Temperature: 0.7)' },
{ type: 'info', content: '' },
{ type: 'info', content: 'Installing agent dependencies...' },
{ type: 'progress', content: 'pandas==2.0.3', target: 100, stutters: [23, 67, 89] },
{ type: 'progress', content: 'requests==2.31.0', target: 100, stutters: [45, 78] },
{ type: 'progress', content: 'beautifulsoup4==4.12.2', target: 100, stutters: [34] },
{ type: 'info', content: '' },
{ type: 'info', content: 'Connecting to data sources...' },
{ type: 'output', content: 'MongoDB : mongodb://data-server:27017 ... Connected' },
{ type: 'output', content: 'ElasticSearch: http://es-cluster:9200 ... Connected' },
{ type: 'output', content: 'Redis Cache : redis://cache:6379 ... Connected' },
{ type: 'success', content: '✓ All data sources connected' },
{ type: 'info', content: '' },
{ type: 'info', content: 'Executing search queries...' },
{ type: 'output', content: '```sql' },
{ type: 'output', content: 'SELECT * FROM exhibitions' },
{ type: 'output', content: 'WHERE region = "长三角"' },
{ type: 'output', content: ' AND industry = "新能源汽车"' },
{ type: 'output', content: ' AND year >= 2023' },
{ type: 'output', content: 'ORDER BY scale DESC;' },
{ type: 'output', content: '```' },
{ type: 'progress', content: 'Query execution', target: 100, stutters: [12, 45, 78, 92] },
{ type: 'success', content: '✓ Query completed: 2,847 rows in 342ms' },
{ type: 'info', content: '' },
{ type: 'info', content: 'Running data analysis...' },
{ type: 'progress', content: 'Data processing', target: 100, stutters: [15, 38, 65, 88] },
{ type: 'output', content: '' },
{ type: 'output', content: '=== Market Analysis Results ===' },
{ type: 'output', content: '• Market Size : ¥3.2 Trillion (↑32% YoY)' },
{ type: 'output', content: '• Key Players : 5,832 companies' },
{ type: 'output', content: '• Employment : 1.86M professionals' },
{ type: 'output', content: '• Exhibition Count : 126 events/year' },
{ type: 'output', content: '• Avg Scale : 32,000 sqm' },
{ type: 'output', content: '• Growth Rate : 28% CAGR' },
{ type: 'info', content: '' },
{ type: 'info', content: 'Generating report files...' },
{ type: 'progress', content: 'market_analysis_2024.json', target: 100, stutters: [56, 89] },
{ type: 'file', content: '✓ Created: market_analysis_2024.json (15.3MB)' },
{ type: 'progress', content: 'competitor_data.csv', target: 100, stutters: [34] },
{ type: 'file', content: '✓ Created: competitor_data.csv (3.7MB)' },
{ type: 'progress', content: 'industry_trends.pdf', target: 100, stutters: [67, 91] },
{ type: 'file', content: '✓ Created: industry_trends.pdf (28.5MB)' },
{ type: 'info', content: '' },
{ type: 'success', content: '✓ Agent-1 completed successfully' },
{ type: 'system', content: 'Execution time: 18.7s | Memory: 124MB | CPU: 23%' },
]
},
{
agent: agents[1], // 设计专家
outputs: [
{ type: 'system', content: '>>> [Agent-2] Design & Creative Expert Activated' },
{ type: 'info', content: 'Model: Google Gemini Pro Vision (Temperature: 0.8)' },
{ type: 'info', content: '' },
{ type: 'info', content: 'Loading design libraries...' },
{ type: 'progress', content: 'three.js@0.157.0', target: 100, stutters: [45, 78] },
{ type: 'progress', content: '@adobe/react-spectrum', target: 100, stutters: [23, 67, 88] },
{ type: 'progress', content: 'stable-diffusion-xl', target: 100, stutters: [34, 56, 89] },
{ type: 'info', content: '' },
{ type: 'info', content: 'Initializing AI image generator...' },
{ type: 'output', content: 'const imageGen = new StableDiffusion({' },
{ type: 'output', content: ' model: "SDXL 1.0",' },
{ type: 'output', content: ' steps: 50,' },
{ type: 'output', content: ' guidance: 7.5,' },
{ type: 'output', content: ' resolution: "1920x1080"' },
{ type: 'output', content: '});' },
{ type: 'info', content: '' },
{ type: 'info', content: '🎨 Generating exhibition hall visualization...' },
{ type: 'output', content: 'Prompt: "Modern auto expo hall, futuristic design, glass ceiling"' },
{ type: 'progress', content: 'Generating: Whisk_e8f83d1a37.jpg', target: 100, stutters: [23, 45, 67, 89, 95] },
{ type: 'image',
content: '📷 IMAGE PREVIEW: 展馆外观',
imageSrc: '/data/会展策划/image/Whisk_e8f83d1a37.jpg',
imageAlt: '展馆外观效果图'
},
{ type: 'file', content: '✓ Generated: Whisk_e8f83d1a37.jpg (2.4MB)' },
{ type: 'info', content: '' },
{ type: 'info', content: '🎨 Generating interior exhibition view...' },
{ type: 'output', content: 'Prompt: "Car exhibition interior, visitors, modern displays"' },
{ type: 'progress', content: 'Generating: 展会内部参观.jpg', target: 100, stutters: [34, 67, 88] },
{ type: 'image',
content: '📷 IMAGE PREVIEW: 展厅内部布局',
imageSrc: '/data/会展策划/image/展会内部参观.jpg',
imageAlt: '展厅内部参观实景'
},
{ type: 'file', content: '✓ Generated: 展会内部参观.jpg (3.1MB)' },
{ type: 'info', content: '' },
{ type: 'info', content: '🎨 Generating test drive area visualization...' },
{ type: 'output', content: 'Prompt: "EV test drive track, outdoor exhibition area"' },
{ type: 'progress', content: 'Generating: 试驾小景.jpg', target: 100, stutters: [45, 78] },
{ type: 'image',
content: '📷 IMAGE PREVIEW: 试驾体验区',
imageSrc: '/data/会展策划/image/2.试驾小景.jpg',
imageAlt: '试驾体验区实景'
},
{ type: 'file', content: '✓ Generated: 试驾小景.jpg (2.8MB)' },
{ type: 'info', content: '' },
{ type: 'info', content: '🎨 Generating brand showcase images...' },
{ type: 'progress', content: 'Generating: 小米汽车.jpg', target: 100, stutters: [34, 67] },
{ type: 'image',
content: '📷 IMAGE PREVIEW: 小米汽车展台',
imageSrc: '/data/会展策划/image/3.小米汽车.jpg',
imageAlt: '小米汽车展示'
},
{ type: 'file', content: '✓ Generated: 小米汽车.jpg (1.9MB)' },
{ type: 'progress', content: 'Generating: 博览会.jpg', target: 100, stutters: [56, 89] },
{ type: 'image',
content: '📷 IMAGE PREVIEW: 博览会全景',
imageSrc: '/data/会展策划/image/博览会.jpg',
imageAlt: '博览会全景图'
},
{ type: 'file', content: '✓ Generated: 博览会.jpg (3.5MB)' },
{ type: 'info', content: '' },
{ type: 'info', content: 'Creating exhibition hall 3D layout...' },
{ type: 'output', content: '' },
{ type: 'output', content: '┌────────────────────────────────────┐' },
{ type: 'output', content: '│ EXHIBITION HALL LAYOUT │' },
{ type: 'output', content: '├────────────────────────────────────┤' },
{ type: 'output', content: '│ A: Vehicle Display [15,000㎡] │' },
{ type: 'output', content: '│ ┌─────┬─────┬─────┬─────┐ │' },
{ type: 'output', content: '│ │Tesla│ NIO │ Li │XPeng│ │' },
{ type: 'output', content: '│ └─────┴─────┴─────┴─────┘ │' },
{ type: 'output', content: '├────────────────────────────────────┤' },
{ type: 'output', content: '│ B: Components [10,000㎡] │' },
{ type: 'output', content: '│ C: Charging Tech [8,000㎡] │' },
{ type: 'output', content: '│ D: Smart Traffic [12,000㎡] │' },
{ type: 'output', content: '│ E: Conference Hall [5,000㎡] │' },
{ type: 'output', content: '└────────────────────────────────────┘' },
{ type: 'info', content: '' },
{ type: 'output', content: '📊 Image Generation Summary:' },
{ type: 'output', content: '• Total Images: 12 high-res renders' },
{ type: 'output', content: '• Format: JPEG (optimized for web)' },
{ type: 'output', content: '• Resolution: 1920x1080 @ 300dpi' },
{ type: 'output', content: '• Color Profile: sRGB' },
{ type: 'info', content: '' },
{ type: 'info', content: 'Exporting all design assets...' },
{ type: 'progress', content: 'design_blueprint.pdf', target: 100, stutters: [45, 78, 92] },
{ type: 'file', content: '✓ Exported: design_blueprint.pdf (48.2MB)' },
{ type: 'progress', content: 'exhibition_3d_model.glb', target: 100, stutters: [23, 56, 78, 91] },
{ type: 'file', content: '✓ Exported: exhibition_3d_model.glb (126MB)' },
{ type: 'progress', content: 'image_gallery.zip', target: 100, stutters: [34, 67, 89] },
{ type: 'file', content: '✓ Exported: image_gallery.zip (42.8MB) - Contains 12 images' },
{ type: 'info', content: '' },
{ type: 'success', content: '✓ Agent-2 completed successfully' },
{ type: 'system', content: 'Execution time: 28.5s | Memory: 384MB | GPU: 65%' },
]
},
{
agent: agents[2], // 财务预算
outputs: [
{ type: 'system', content: '>>> [Agent-3] Financial & Budget Expert Activated' },
{ type: 'info', content: 'Model: DeepSeek-Math-7B (Temperature: 0.3)' },
{ type: 'info', content: '' },
{ type: 'info', content: 'Loading financial models...' },
{ type: 'progress', content: 'Economic models', target: 100, stutters: [34, 78] },
{ type: 'progress', content: 'Cost database', target: 100, stutters: [56] },
{ type: 'info', content: '' },
{ type: 'info', content: 'Calculating costs...' },
{ type: 'output', content: 'import pandas as pd' },
{ type: 'output', content: 'import numpy as np' },
{ type: 'output', content: '' },
{ type: 'output', content: 'costs = {' },
{ type: 'output', content: ' "venue": calculate_venue_cost(50000, "shanghai"),' },
{ type: 'output', content: ' "construction": calculate_booth_cost(600, "premium"),' },
{ type: 'output', content: ' "marketing": estimate_marketing_budget("large"),' },
{ type: 'output', content: ' "operations": calculate_staff_cost(126, 3)' },
{ type: 'output', content: '}' },
{ type: 'progress', content: 'Cost calculation', target: 100, stutters: [23, 67, 89] },
{ type: 'info', content: '' },
{ type: 'output', content: '╔══════════════════════════════════════╗' },
{ type: 'output', content: '║ BUDGET BREAKDOWN ║' },
{ type: 'output', content: '╠══════════════════════════════════════╣' },
{ type: 'output', content: '║ Venue Rental ¥3,000,000 ║' },
{ type: 'output', content: '║ ├─ Exhibition Hall ¥2,500,000 ║' },
{ type: 'output', content: '║ └─ Meeting Rooms ¥500,000 ║' },
{ type: 'output', content: '║ Construction ¥4,500,000 ║' },
{ type: 'output', content: '║ ├─ Premium Booths ¥3,000,000 ║' },
{ type: 'output', content: '║ └─ Standard Booths ¥1,500,000 ║' },
{ type: 'output', content: '║ Operations ¥2,000,000 ║' },
{ type: 'output', content: '║ Reserve Fund ¥500,000 ║' },
{ type: 'output', content: '╟──────────────────────────────────────╢' },
{ type: 'output', content: '║ TOTAL BUDGET ¥10,000,000 ║' },
{ type: 'output', content: '╚══════════════════════════════════════╝' },
{ type: 'info', content: '' },
{ type: 'info', content: 'Calculating revenue projections...' },
{ type: 'progress', content: 'Revenue modeling', target: 100, stutters: [12, 45, 78, 92] },
{ type: 'output', content: '' },
{ type: 'success', content: 'Revenue Forecast:' },
{ type: 'output', content: '• Booth Sales : ¥8,500,000' },
{ type: 'output', content: '• Sponsorship : ¥3,000,000' },
{ type: 'output', content: '• Ticket Sales : ¥1,500,000' },
{ type: 'output', content: '────────────────────────────' },
{ type: 'success', content: 'Total Revenue : ¥13,000,000' },
{ type: 'success', content: 'Net Profit : ¥3,000,000' },
{ type: 'success', content: 'ROI : 30%' },
{ type: 'info', content: '' },
{ type: 'info', content: 'Generating financial reports...' },
{ type: 'progress', content: 'budget_plan_2024.xlsx', target: 100, stutters: [45, 89] },
{ type: 'file', content: '✓ Created: budget_plan_2024.xlsx (1.2MB)' },
{ type: 'progress', content: 'financial_forecast.pdf', target: 100, stutters: [67] },
{ type: 'file', content: '✓ Created: financial_forecast.pdf (4.8MB)' },
{ type: 'info', content: '' },
{ type: 'success', content: '✓ Agent-3 completed successfully' },
{ type: 'system', content: 'Execution time: 15.8s | Memory: 96MB | CPU: 18%' },
]
},
{
agent: agents[3], // 格式编辑
outputs: [
{ type: 'system', content: '>>> [Agent-4] Format & Structure Expert Activated' },
{ type: 'info', content: 'Model: DeepSeek-V2 Chat (Temperature: 0.5)' },
{ type: 'info', content: '' },
{ type: 'info', content: 'Loading document processors...' },
{ type: 'progress', content: 'markdown-it@13.0.1', target: 100, stutters: [45] },
{ type: 'progress', content: 'pdfkit@0.13.0', target: 100, stutters: [67, 89] },
{ type: 'info', content: '' },
{ type: 'info', content: 'Analyzing document structure...' },
{ type: 'output', content: '📄 Document Structure Analysis' },
{ type: 'output', content: '├── 1. Executive Summary (3 pages)' },
{ type: 'output', content: '├── 2. Market Analysis (12 pages)' },
{ type: 'output', content: '├── 3. Exhibition Design (15 pages)' },
{ type: 'output', content: '├── 4. Budget Planning (10 pages)' },
{ type: 'output', content: '├── 5. Marketing Strategy (8 pages)' },
{ type: 'output', content: '├── 6. Execution Plan (10 pages)' },
{ type: 'output', content: '├── 7. Risk Assessment (5 pages)' },
{ type: 'output', content: '└── 8. Appendices (5 pages)' },
{ type: 'info', content: '' },
{ type: 'info', content: 'Formatting sections...' },
{ type: 'progress', content: 'Document formatting', target: 100, stutters: [34, 67, 88] },
{ type: 'progress', content: 'TOC generation', target: 100, stutters: [56] },
{ type: 'progress', content: 'Page numbering', target: 100, stutters: [78] },
{ type: 'info', content: '' },
{ type: 'output', content: '╔════════════════════════════════════╗' },
{ type: 'output', content: '║ DOCUMENT STATISTICS ║' },
{ type: 'output', content: '╠════════════════════════════════════╣' },
{ type: 'output', content: '║ Total Pages : 68 ║' },
{ type: 'output', content: '║ Word Count : 24,567 ║' },
{ type: 'output', content: '║ Images : 42 ║' },
{ type: 'output', content: '║ Tables : 18 ║' },
{ type: 'output', content: '║ Charts : 23 ║' },
{ type: 'output', content: '╚════════════════════════════════════╝' },
{ type: 'info', content: '' },
{ type: 'progress', content: 'exhibition_plan_formatted.docx', target: 100, stutters: [45, 78] },
{ type: 'file', content: '✓ Created: exhibition_plan_formatted.docx (8.4MB)' },
{ type: 'info', content: '' },
{ type: 'success', content: '✓ Agent-4 completed successfully' },
{ type: 'system', content: 'Execution time: 12.4s | Memory: 72MB | CPU: 15%' },
]
},
{
agent: agents[4], // 活动执行
outputs: [
{ type: 'system', content: '>>> [Agent-5] Event Execution Expert Activated' },
{ type: 'info', content: 'Model: DeepSeek-V2 Chat (Temperature: 0.6)' },
{ type: 'info', content: '' },
{ type: 'info', content: 'Loading project management tools...' },
{ type: 'progress', content: 'gantt-chart-js', target: 100, stutters: [23, 67] },
{ type: 'progress', content: 'resource-planner', target: 100, stutters: [45] },
{ type: 'info', content: '' },
{ type: 'info', content: 'Creating execution timeline...' },
{ type: 'output', content: '' },
{ type: 'output', content: '📅 PROJECT TIMELINE (12 Weeks)' },
{ type: 'output', content: '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━' },
{ type: 'output', content: 'Week 1-2 : [████████] Venue booking & contracts' },
{ type: 'output', content: 'Week 3-4 : [████████] Booth design & production' },
{ type: 'output', content: 'Week 5-6 : [████████] Marketing campaign launch' },
{ type: 'output', content: 'Week 7-8 : [████████] Exhibitor recruitment' },
{ type: 'output', content: 'Week 9-10 : [████████] Logistics & setup' },
{ type: 'output', content: 'Week 11 : [████] Final preparations' },
{ type: 'output', content: 'Week 12 : [████] EXHIBITION DAYS' },
{ type: 'info', content: '' },
{ type: 'info', content: 'Assigning team resources...' },
{ type: 'progress', content: 'Resource allocation', target: 100, stutters: [34, 78, 92] },
{ type: 'output', content: '' },
{ type: 'output', content: '👥 TEAM STRUCTURE' },
{ type: 'output', content: '├── Project Director (1)' },
{ type: 'output', content: '├── Operations Team (8)' },
{ type: 'output', content: '├── Marketing Team (6)' },
{ type: 'output', content: '├── Design Team (4)' },
{ type: 'output', content: '├── Logistics Team (12)' },
{ type: 'output', content: '├── Customer Service (15)' },
{ type: 'output', content: '└── Security & Safety (20)' },
{ type: 'output', content: 'Total Staff: 66 professionals' },
{ type: 'info', content: '' },
{ type: 'info', content: 'Creating task checklists...' },
{ type: 'progress', content: 'Checklist generation', target: 100, stutters: [56, 89] },
{ type: 'output', content: '✅ Generated 247 action items' },
{ type: 'output', content: '📋 Created 18 milestone checkpoints' },
{ type: 'output', content: '⚠️ Identified 12 critical dependencies' },
{ type: 'info', content: '' },
{ type: 'progress', content: 'execution_plan.xlsx', target: 100, stutters: [67] },
{ type: 'file', content: '✓ Created: execution_plan.xlsx (2.3MB)' },
{ type: 'progress', content: 'task_assignments.pdf', target: 100, stutters: [45, 89] },
{ type: 'file', content: '✓ Created: task_assignments.pdf (5.6MB)' },
{ type: 'info', content: '' },
{ type: 'success', content: '✓ Agent-5 completed successfully' },
{ type: 'system', content: 'Execution time: 19.2s | Memory: 108MB | CPU: 22%' },
]
},
{
agent: agents[5], // 营销宣传
outputs: [
{ type: 'system', content: '>>> [Agent-6] Marketing & PR Expert Activated' },
{ type: 'info', content: 'Model: DeepSeek-V2 Chat (Temperature: 0.7)' },
{ type: 'info', content: '' },
{ type: 'info', content: 'Loading marketing analytics...' },
{ type: 'progress', content: 'Social media APIs', target: 100, stutters: [34, 78] },
{ type: 'progress', content: 'Ad platform SDKs', target: 100, stutters: [56] },
{ type: 'info', content: '' },
{ type: 'info', content: 'Designing marketing campaigns...' },
{ type: 'output', content: '' },
{ type: 'output', content: '🎯 MARKETING STRATEGY' },
{ type: 'output', content: '═══════════════════════════════════' },
{ type: 'output', content: '📱 Digital Marketing (40%)' },
{ type: 'output', content: ' • WeChat: 500K+ followers target' },
{ type: 'output', content: ' • Weibo: 300K+ impressions/day' },
{ type: 'output', content: ' • LinkedIn: B2B engagement 25%' },
{ type: 'output', content: ' • TikTok: Short videos 2M views' },
{ type: 'output', content: '' },
{ type: 'output', content: '📺 Traditional Media (30%)' },
{ type: 'output', content: ' • TV Ads: CCTV-2, Dragon TV' },
{ type: 'output', content: ' • Radio: Traffic channels' },
{ type: 'output', content: ' • Print: Industry magazines' },
{ type: 'output', content: '' },
{ type: 'output', content: '🤝 Partnerships (30%)' },
{ type: 'output', content: ' • Industry associations' },
{ type: 'output', content: ' • Government agencies' },
{ type: 'output', content: ' • Media partners' },
{ type: 'info', content: '' },
{ type: 'info', content: 'Creating content calendar...' },
{ type: 'progress', content: 'Content planning', target: 100, stutters: [23, 67, 89] },
{ type: 'output', content: '' },
{ type: 'output', content: '📊 EXPECTED REACH' },
{ type: 'output', content: '┌─────────────────────────────┐' },
{ type: 'output', content: '│ Pre-Event : 2.5M people │' },
{ type: 'output', content: '│ During : 500K visitors │' },
{ type: 'output', content: '│ Post-Event: 1M engagement │' },
{ type: 'output', content: '│ ROI : 320% │' },
{ type: 'output', content: '└─────────────────────────────┘' },
{ type: 'info', content: '' },
{ type: 'info', content: 'Generating marketing materials...' },
{ type: 'progress', content: 'marketing_strategy.pptx', target: 100, stutters: [45, 78] },
{ type: 'file', content: '✓ Created: marketing_strategy.pptx (18.7MB)' },
{ type: 'progress', content: 'social_media_kit.zip', target: 100, stutters: [67, 92] },
{ type: 'file', content: '✓ Created: social_media_kit.zip (156MB)' },
{ type: 'progress', content: 'press_release.docx', target: 100, stutters: [34] },
{ type: 'file', content: '✓ Created: press_release.docx (245KB)' },
{ type: 'info', content: '' },
{ type: 'success', content: '✓ Agent-6 completed successfully' },
{ type: 'system', content: 'Execution time: 21.5s | Memory: 142MB | CPU: 28%' },
]
},
{
agent: agents[6], // 会展策划专家(总协调)
outputs: [
{ type: 'system', content: '>>> [Agent-7] Exhibition Planning Coordinator Activated' },
{ type: 'info', content: 'Model: Chat Models + Memories (Temperature: 0.4)' },
{ type: 'info', content: '' },
{ type: 'info', content: 'Aggregating all agent outputs...' },
{ type: 'progress', content: 'Data aggregation', target: 100, stutters: [34, 67] },
{ type: 'info', content: '' },
{ type: 'info', content: 'Performing final integration...' },
{ type: 'output', content: '' },
{ type: 'output', content: '🎯 FINAL PLAN SUMMARY' },
{ type: 'output', content: '══════════════════════════════════════' },
{ type: 'output', content: '' },
{ type: 'output', content: '📋 PROJECT: 2024长三角新能源汽车展' },
{ type: 'output', content: '📍 VENUE: 上海国家会展中心' },
{ type: 'output', content: '📅 DATE: 2024.10.18-20' },
{ type: 'output', content: '📏 SCALE: 50,000㎡ | 350展商 | 50,000观众' },
{ type: 'output', content: '' },
{ type: 'output', content: '💼 KEY DELIVERABLES' },
{ type: 'output', content: '├── Complete Planning Document (68 pages)' },
{ type: 'output', content: '├── Budget Plan (¥10M total)' },
{ type: 'output', content: '├── Design Blueprint (3D models)' },
{ type: 'output', content: '├── Marketing Strategy (2.5M reach)' },
{ type: 'output', content: '├── Execution Timeline (12 weeks)' },
{ type: 'output', content: '└── Risk Management Plan' },
{ type: 'info', content: '' },
{ type: 'info', content: 'Quality assurance check...' },
{ type: 'progress', content: 'QA validation', target: 100, stutters: [45, 78, 91] },
{ type: 'output', content: '' },
{ type: 'success', content: '✅ All requirements met' },
{ type: 'success', content: '✅ Budget within limits' },
{ type: 'success', content: '✅ Timeline achievable' },
{ type: 'success', content: '✅ Risk factors addressed' },
{ type: 'success', content: '✅ ROI projection: 30%' },
{ type: 'info', content: '' },
{ type: 'info', content: 'Generating final deliverables...' },
{ type: 'progress', content: 'final_plan_complete.pdf', target: 100, stutters: [23, 56, 78, 92] },
{ type: 'file', content: '✓ Created: final_plan_complete.pdf (68 pages, 45.8MB)' },
{ type: 'progress', content: 'executive_summary.pdf', target: 100, stutters: [67] },
{ type: 'file', content: '✓ Created: executive_summary.pdf (3 pages, 1.2MB)' },
{ type: 'info', content: '' },
{ type: 'output', content: '╔═══════════════════════════════════════╗' },
{ type: 'output', content: '║ 🎉 PLAN GENERATION COMPLETE 🎉 ║' },
{ type: 'output', content: '╠═══════════════════════════════════════╣' },
{ type: 'output', content: '║ Total Processing Time : 03:00 ║' },
{ type: 'output', content: '║ Documents Generated : 15 files ║' },
{ type: 'output', content: '║ Total Size : 287MB ║' },
{ type: 'output', content: '║ Quality Score : 98/100 ║' },
{ type: 'output', content: '╚═══════════════════════════════════════╝' },
{ type: 'info', content: '' },
{ type: 'success', content: '✓ Agent-7 completed successfully' },
{ type: 'system', content: 'Execution time: 16.8s | Memory: 186MB | CPU: 31%' },
]
}
];
// 添加终端行
const addTerminalLine = (line: Omit<TerminalLine, 'id' | 'timestamp'>) => {
const now = new Date();
const timestamp = `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}:${now.getSeconds().toString().padStart(2, '0')}.${now.getMilliseconds().toString().padStart(3, '0')}`;
const lineId = Math.random().toString(36).substr(2, 9);
const newLine = {
...line,
id: lineId,
timestamp
};
setTerminalLines(prev => [...prev, newLine]);
// 如果是图片类型,设置加载状态
if (line.type === 'image' && line.imageSrc) {
setImageLoadingStates(prev => ({ ...prev, [lineId]: true }));
// 确保loading动画显示足够时间
setTimeout(() => {
setImageLoadingStates(prev => ({ ...prev, [lineId]: false }));
}, getRandomDelay(2000, 3500));
}
// 自动滚动到底部
setTimeout(() => {
if (terminalRef.current) {
terminalRef.current.scrollTop = terminalRef.current.scrollHeight;
}
}, 10);
};
// 更新进度条行(覆盖同一行)
const updateProgressLine = (content: string, progressId: string) => {
const now = new Date();
const timestamp = `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}:${now.getSeconds().toString().padStart(2, '0')}.${now.getMilliseconds().toString().padStart(3, '0')}`;
setTerminalLines(prev => {
const existing = prev.findIndex(line => line.id === progressId);
if (existing !== -1) {
const updated = [...prev];
updated[existing] = {
...updated[existing],
content,
timestamp
};
return updated;
}
return prev;
});
};
// 执行进度条动画(带卡顿效果)
const executeProgress = async (label: string, stutters: number[] = [], agent?: string) => {
const progressId = Math.random().toString(36).substr(2, 9);
progressLineIdRef.current = progressId;
// 添加初始进度行
const now = new Date();
const timestamp = `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}:${now.getSeconds().toString().padStart(2, '0')}.${now.getMilliseconds().toString().padStart(3, '0')}`;
setTerminalLines(prev => [...prev, {
id: progressId,
timestamp,
type: 'output',
agent,
content: `${label}: ${generateProgressBar(0)}`,
isProgressLine: true
}]);
// 进度动画
let progress = 0;
while (progress < 100) {
if (status !== 'running') return;
// 检查是否需要卡顿
if (stutters.includes(progress)) {
await new Promise(resolve => setTimeout(resolve, getRandomDelay(1000, 3000)));
}
// 随机增长速度
const increment = Math.min(
100 - progress,
Math.floor(Math.random() * 15) + 1
);
progress = Math.min(100, progress + increment);
// 更新进度条
updateProgressLine(`${label}: ${generateProgressBar(progress)}`, progressId);
// 随机延迟
await new Promise(resolve => setTimeout(resolve, getRandomDelay(30, 150)));
}
// 完成后清除引用
progressLineIdRef.current = null;
};
// 执行启动序列
const executeStartupSequence = async () => {
for (const line of startupSequence) {
if (status !== 'running') return;
if (line.type === 'progress') {
// 进度条动画
const target = (line as any).target || 100;
const label = line.content;
await executeProgress(label, [23, 67, 89]);
} else {
addTerminalLine(line as any);
await new Promise(resolve => setTimeout(resolve, getRandomDelay(50, 200)));
}
}
// 开始执行Agent
setCurrentAgentIndex(0);
};
// 执行Agent
const executeAgent = async (agentIndex: number) => {
if (agentIndex >= agentSequence.length) {
// 所有Agent执行完成
setIsExecuting(false);
addTerminalLine({
type: 'system',
content: '=' .repeat(60)
});
addTerminalLine({
type: 'system',
content: 'ALL AGENTS COMPLETED SUCCESSFULLY'
});
addTerminalLine({
type: 'system',
content: `Total execution time: 3m 00s | Peak memory: 512MB`
});
addTerminalLine({
type: 'system',
content: '=' .repeat(60)
});
// 更新store状态为完成
const store = useDemoStore.getState();
store.setProgress(100);
// 显示结果弹窗
console.log('All agents completed, showing result modal...');
setTimeout(() => {
console.log('Setting showResultModal to true');
setShowResultModal(true);
}, 2000);
return;
}
const agentData = agentSequence[agentIndex];
for (const output of agentData.outputs) {
if (status !== 'running') return;
if (output.type === 'progress') {
// 进度条动画(带卡顿)
const stutters = (output as any).stutters || [];
await executeProgress(output.content, stutters, agentData.agent.name);
} else {
addTerminalLine({
...output,
agent: output.type === 'system' ? undefined : agentData.agent.name
});
// 根据类型设置延迟
let delay =
output.type === 'system' ? getRandomDelay(100, 300) :
output.type === 'install' ? getRandomDelay(200, 400) :
output.type === 'file' ? getRandomDelay(100, 200) :
output.type === 'info' && output.content === '' ? 50 :
getRandomDelay(30, 100);
// 如果是图片类型,等待图片加载完成
if (output.type === 'image') {
delay = getRandomDelay(2500, 3500); // 等待图片加载动画完成
}
await new Promise(resolve => setTimeout(resolve, delay));
}
}
// 执行下一个Agent
await new Promise(resolve => setTimeout(resolve, 500));
setCurrentAgentIndex(agentIndex + 1);
};
// 开始演示
useEffect(() => {
if (status === 'running' && !isExecuting) {
setIsExecuting(true);
executeStartupSequence();
}
}, [status]);
// 监听Agent变化
useEffect(() => {
if (status === 'running' && currentAgentIndex >= 0) {
executeAgent(currentAgentIndex);
}
}, [currentAgentIndex]);
// 计时器
useEffect(() => {
if (status === 'running') {
intervalRef.current = window.setInterval(() => {
setElapsedTime(prev => prev + 100);
}, 100);
} else {
if (intervalRef.current) {
clearInterval(intervalRef.current);
}
}
return () => {
if (intervalRef.current) {
clearInterval(intervalRef.current);
}
};
}, [status]);
// 处理需求提交
const handleRequirementSubmit = (requirement: string) => {
setUserRequirement(requirement);
setShowRequirementModal(false);
// 开始演示
startDemo();
};
// 处理查看详情
const handleViewDetails = () => {
setShowResultModal(false);
// 这里可以导航到结果页面
window.location.href = '#result';
};
// 重置
const handleReset = () => {
reset();
setTerminalLines([]);
setCurrentAgentIndex(-1);
setElapsedTime(0);
setIsExecuting(false);
setUserRequirement('');
setShowResultModal(false);
};
// 格式化时间
const formatTime = (ms: number) => {
const seconds = Math.floor(ms / 1000);
const minutes = Math.floor(seconds / 60);
const remainingSeconds = seconds % 60;
return `${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`;
};
// 获取终端行颜色
const getLineColor = (type: string) => {
switch(type) {
case 'success': return 'text-green-400';
case 'error': return 'text-red-400';
case 'warning': return 'text-yellow-400';
case 'system': return 'text-purple-400';
case 'output': return 'text-blue-400';
case 'info': return 'text-gray-300';
case 'install': return 'text-cyan-400';
case 'progress': return 'text-amber-400';
case 'file': return 'text-emerald-400';
case 'image': return 'text-pink-400';
default: return 'text-gray-300';
}
};
return (
<div className="h-screen bg-gray-50 flex flex-col relative">
{/* 背景图片和蒙版 */}
<div className="absolute inset-0 z-0">
<div
className="absolute inset-0"
style={{
backgroundImage: 'url(/images/Whisk_e8f83d1a37.jpg)',
backgroundSize: 'cover',
backgroundPosition: 'center',
backgroundRepeat: 'no-repeat',
opacity: 0.15
}}
/>
<div className="absolute inset-0 bg-gradient-to-br from-gray-900/30 via-purple-900/20 to-blue-900/30" />
</div>
{/* 主内容容器 */}
<div className="relative z-10 h-full flex flex-col">
{/* 顶部控制栏 */}
<div className="bg-white border-b border-gray-200 px-6 py-3 flex items-center justify-between">
<div className="flex items-center gap-4">
<h1 className="text-lg font-semibold text-gray-900">DuoDuo Agent - ·</h1>
<div className="flex items-center gap-2">
<button
onClick={status === 'idle' ? () => setShowRequirementModal(true) : pauseDemo}
className="px-3 py-1.5 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors flex items-center gap-1.5"
>
{status === 'idle' ? (
<>
<FileInput className="w-4 h-4" />
<span></span>
</>
) : status === 'paused' ? (
<>
<Play className="w-4 h-4" />
<span></span>
</>
) : (
<>
<Pause className="w-4 h-4" />
<span></span>
</>
)}
</button>
<button
onClick={handleReset}
className="px-3 py-1.5 bg-gray-600 text-white rounded-md hover:bg-gray-700 transition-colors flex items-center gap-1.5"
>
<RotateCcw className="w-4 h-4" />
<span></span>
</button>
</div>
</div>
<div className="text-sm text-gray-600">
: {formatTime(elapsedTime)} / 03:00
</div>
</div>
{/* 主内容区 */}
<div className="flex-1 flex overflow-hidden backdrop-blur-sm">
{/* 左侧n8n工作流 */}
<div className="w-1/2 border-r border-gray-200 bg-white/95 backdrop-blur-md flex flex-col">
<div className="px-4 py-2 border-b border-gray-200 flex items-center justify-between bg-gray-50">
<div className="flex items-center gap-2">
<div className="w-3 h-3 rounded-full bg-green-500"></div>
<span className="text-sm font-medium text-gray-700"></span>
</div>
<button className="p-1 hover:bg-gray-200 rounded transition-colors">
<Maximize2 className="w-4 h-4 text-gray-600" />
</button>
</div>
<div className="flex-1">
<iframe
src="http://localhost:5678/workflow/XbfF8iRI4a69hmYS"
className="w-full h-full border-0"
title="n8n Workflow"
/>
</div>
</div>
{/* 右侧:终端执行区 */}
<div className="w-1/2 bg-gray-900 flex flex-col">
<div className="px-4 py-2 bg-gray-800 flex items-center justify-between">
<div className="flex items-center gap-2">
<Terminal className="w-4 h-4 text-green-400" />
<span className="text-sm font-mono text-green-400">Agent Execution Terminal</span>
</div>
<div className="flex gap-1">
<div className="w-3 h-3 rounded-full bg-red-500"></div>
<div className="w-3 h-3 rounded-full bg-yellow-500"></div>
<div className="w-3 h-3 rounded-full bg-green-500"></div>
</div>
</div>
<div
ref={terminalRef}
className="flex-1 overflow-y-auto p-4 font-mono text-xs custom-scrollbar"
style={{
backgroundColor: '#0a0a0a',
maxHeight: 'calc(100vh - 200px)'
}}
>
<style jsx>{`
.custom-scrollbar::-webkit-scrollbar {
width: 8px;
}
.custom-scrollbar::-webkit-scrollbar-track {
background: #1a1a1a;
}
.custom-scrollbar::-webkit-scrollbar-thumb {
background: #444;
border-radius: 4px;
}
.custom-scrollbar::-webkit-scrollbar-thumb:hover {
background: #555;
}
.animation-delay-200 {
animation-delay: 200ms;
}
.animation-delay-400 {
animation-delay: 400ms;
}
`}</style>
<AnimatePresence>
{terminalLines.map((line) => (
<motion.div
key={line.id}
initial={line.isProgressLine ? false : { opacity: 0, x: -10 }}
animate={{ opacity: 1, x: 0 }}
transition={{ duration: 0.05 }}
className="whitespace-pre-wrap break-all leading-5"
>
{line.type === 'image' ? (
<div className="my-2">
<span className="text-gray-600">[{line.timestamp}]</span>
{line.agent && (
<span className="text-cyan-400 ml-2">{line.agent}:</span>
)}
<span className={`ml-2 ${getLineColor(line.type)}`}>
{line.content}
</span>
{line.imageSrc && (
<div className="mt-3 mb-3">
{imageLoadingStates[line.id] ? (
// 简单的骨架屏Loading效果
<div className="relative w-96 h-64 bg-gray-800 rounded-lg border border-gray-700 overflow-hidden">
{/* 骨架屏脉冲动画 */}
<div className="absolute inset-0">
<div className="h-full w-full bg-gradient-to-r from-gray-800 via-gray-700 to-gray-800 animate-pulse" />
</div>
{/* 简单的loading指示器 */}
<div className="absolute inset-0 flex items-center justify-center">
<div className="flex items-center gap-2">
<div className="w-2 h-2 bg-gray-500 rounded-full animate-pulse" />
<div className="w-2 h-2 bg-gray-500 rounded-full animate-pulse animation-delay-200" />
<div className="w-2 h-2 bg-gray-500 rounded-full animate-pulse animation-delay-400" />
</div>
</div>
</div>
) : (
// 实际图片(淡入效果)
<motion.img
src={line.imageSrc}
alt={line.imageAlt || 'Generated image'}
className="max-w-md rounded-lg border-2 border-gray-700 shadow-xl"
style={{ maxHeight: '300px' }}
initial={{ opacity: 0, scale: 0.95 }}
animate={{ opacity: 1, scale: 1 }}
transition={{ duration: 0.5 }}
onError={(e) => {
e.currentTarget.style.display = 'none';
}}
/>
)}
</div>
)}
</div>
) : (
<>
<span className="text-gray-600">[{line.timestamp}]</span>
{line.agent && (
<span className="text-cyan-400 ml-2">{line.agent}:</span>
)}
<span className={`ml-2 ${getLineColor(line.type)}`}>
{line.content}
</span>
</>
)}
</motion.div>
))}
</AnimatePresence>
{/* 光标 */}
{status === 'running' && (
<motion.span
animate={{ opacity: [1, 0] }}
transition={{ duration: 0.5, repeat: Infinity }}
className="inline-block w-2 h-4 bg-green-400"
/>
)}
</div>
{/* Agent状态栏 */}
<div className="px-4 py-3 bg-gray-800 border-t border-gray-700">
<div className="grid grid-cols-7 gap-2">
{agents.map((agent, index) => (
<div
key={agent.id}
className={`flex flex-col items-center gap-1 px-2 py-2 rounded-lg transition-all ${
index < currentAgentIndex ? 'bg-green-900/50 border border-green-700' :
index === currentAgentIndex ? 'bg-blue-900 border border-blue-500 animate-pulse' :
'bg-gray-800 border border-gray-700'
}`}
>
{/* Agent头像 */}
<div className={`relative w-12 h-12 rounded-full overflow-hidden border-2 ${
index < currentAgentIndex ? 'border-green-400' :
index === currentAgentIndex ? 'border-blue-400 animate-pulse' :
'border-gray-600'
}`}>
{agent.avatar ? (
<img
src={agent.avatar}
alt={agent.name}
className={`w-full h-full object-cover ${
index < currentAgentIndex ? 'brightness-100' :
index === currentAgentIndex ? 'brightness-110' :
'brightness-50 grayscale'
}`}
/>
) : (
<div className="w-full h-full bg-gray-700 flex items-center justify-center">
<span className="text-2xl">{agent.icon}</span>
</div>
)}
{/* 状态指示器 */}
{index === currentAgentIndex && (
<div className="absolute -bottom-1 -right-1 w-3 h-3 bg-blue-400 rounded-full animate-ping"></div>
)}
{index < currentAgentIndex && (
<div className="absolute -bottom-1 -right-1 w-3 h-3 bg-green-400 rounded-full">
<svg className="w-3 h-3 text-white" fill="currentColor" viewBox="0 0 20 20">
<path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clipRule="evenodd" />
</svg>
</div>
)}
</div>
<span className={`text-xs text-center line-clamp-2 ${
index < currentAgentIndex ? 'text-green-400' :
index === currentAgentIndex ? 'text-blue-400' :
'text-gray-500'
}`}>{agent.name}</span>
<div className={`w-full h-1 rounded-full mt-1 ${
index < currentAgentIndex ? 'bg-green-500' :
index === currentAgentIndex ? 'bg-blue-500' :
'bg-gray-700'
}`}>
{index === currentAgentIndex && (
<div className="h-full bg-blue-400 rounded-full animate-pulse"
style={{width: '50%'}}></div>
)}
</div>
</div>
))}
</div>
<div className="mt-2 text-center text-xs text-gray-400">
: {currentAgentIndex === -1 ? 0 : Math.round(((currentAgentIndex) / agentSequence.length) * 100)}% |
: {currentAgentIndex >= 0 && currentAgentIndex < agentSequence.length ? agentSequence[currentAgentIndex]?.agent.name : currentAgentIndex === -1 ? '初始化中...' : '已完成'}
</div>
</div>
</div>
</div>
</div>
{/* 弹窗组件 */}
<RequirementModal
isOpen={showRequirementModal}
onClose={() => setShowRequirementModal(false)}
onSubmit={handleRequirementSubmit}
/>
<ResultModal
isOpen={showResultModal}
onClose={() => setShowResultModal(false)}
onViewDetails={handleViewDetails}
/>
</div>
);
};
export default WorkflowPageV4;