feat: 优化展会演示前端界面和功能

主要更新:
- 重新设计首页UI,采用现代黑色科技风格
- 修复结果弹窗按钮显示问题,固定在底部
- 添加Duoduo Agent Logo和三击调试功能
- 添加右下角浮动查看结果按钮
- 优化功能卡片布局和对齐
- 简化按钮文字为'开始'
- 移除首页演示案例内容
- 创建Windows启动脚本start_cn.bat

技术改进:
- 使用深色主题配色方案
- 添加网格背景和动态光效
- 优化组件动画效果
- 改进响应式布局

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Yep_Q
2025-09-09 19:18:37 +08:00
parent 7edfb28ddd
commit 3e7d0f39f8
4 changed files with 647 additions and 67 deletions

View File

@@ -47,9 +47,9 @@ const ResultModal: React.FC<ResultModalProps> = ({ isOpen, onClose, onViewDetail
className="fixed inset-0 flex items-center justify-center z-50 p-4"
onClick={(e) => e.stopPropagation()}
>
<div className="bg-white rounded-2xl shadow-2xl max-w-2xl w-full max-h-[90vh] overflow-hidden">
<div className="bg-white rounded-2xl shadow-2xl max-w-2xl w-full max-h-[90vh] overflow-hidden flex flex-col">
{/* 头部 */}
<div className="relative bg-gradient-to-br from-green-500 to-emerald-600 p-8 text-white">
<div className="relative bg-gradient-to-br from-green-500 to-emerald-600 p-8 text-white flex-shrink-0">
<button
onClick={onClose}
className="absolute top-4 right-4 p-2 hover:bg-white/20 rounded-lg transition-colors"
@@ -74,7 +74,7 @@ const ResultModal: React.FC<ResultModalProps> = ({ isOpen, onClose, onViewDetail
</p>
</div>
<div className="p-6">
<div className="p-6 overflow-y-auto flex-1">
{/* 统计信息 */}
<div className="grid grid-cols-3 gap-4 mb-6">
{stats.map((stat, index) => (
@@ -138,11 +138,13 @@ const ResultModal: React.FC<ResultModalProps> = ({ isOpen, onClose, onViewDetail
</div>
</div>
</div>
</div>
{/* 操作按钮 */}
{/* 操作按钮 - 固定在底部 */}
<div className="p-6 bg-gray-50 border-t border-gray-200 flex-shrink-0">
<div className="flex justify-center">
<button
onClick={() => window.open('http://localhost:4155', '_blank')}
onClick={() => window.open('http://localhost:4155/index.html', '_blank')}
className="px-8 py-3 bg-gradient-to-r from-blue-600 to-purple-600 text-white rounded-xl font-medium hover:shadow-lg transform hover:scale-105 transition-all flex items-center justify-center gap-2"
>
<Eye className="w-5 h-5" />

View File

@@ -8,9 +8,27 @@ interface LandingPageProps {
const LandingPage: React.FC<LandingPageProps> = ({ onStart }) => {
return (
<div className="min-h-screen flex items-center justify-center p-8 relative">
{/* 背景图片和蒙版 */}
<div className="min-h-screen flex items-center justify-center p-8 relative overflow-hidden bg-black">
{/* 高级背景效果 */}
<div className="absolute inset-0 z-0">
{/* 渐变背景 */}
<div className="absolute inset-0 bg-gradient-to-br from-slate-950 via-slate-900 to-slate-950" />
{/* 网格背景 */}
<div
className="absolute inset-0 opacity-20"
style={{
backgroundImage: `linear-gradient(to right, #1e293b 1px, transparent 1px),
linear-gradient(to bottom, #1e293b 1px, transparent 1px)`,
backgroundSize: '50px 50px'
}}
/>
{/* 动态光效 */}
<div className="absolute top-1/4 -left-1/4 w-96 h-96 bg-blue-500/30 rounded-full blur-[120px] animate-pulse" />
<div className="absolute bottom-1/4 -right-1/4 w-96 h-96 bg-purple-500/30 rounded-full blur-[120px] animate-pulse" />
{/* 图片叠加 */}
<div
className="absolute inset-0"
style={{
@@ -18,11 +36,9 @@ const LandingPage: React.FC<LandingPageProps> = ({ onStart }) => {
backgroundSize: 'cover',
backgroundPosition: 'center',
backgroundRepeat: 'no-repeat',
opacity: 0.08
opacity: 0.03
}}
/>
<div className="absolute inset-0 bg-gradient-to-br from-gray-900/50 via-purple-900/30 to-blue-900/40" />
<div className="absolute inset-0 backdrop-blur-sm" />
</div>
{/* 主内容 */}
@@ -38,9 +54,12 @@ const LandingPage: React.FC<LandingPageProps> = ({ onStart }) => {
initial={{ scale: 0 }}
animate={{ scale: 1 }}
transition={{ delay: 0.2, type: "spring", stiffness: 200 }}
className="inline-flex items-center justify-center w-24 h-24 rounded-3xl bg-gradient-to-br from-blue-500 to-purple-500 shadow-2xl"
className="inline-flex items-center justify-center w-24 h-24 rounded-2xl bg-gradient-to-br from-slate-800 to-slate-900 shadow-2xl border border-slate-700/50"
style={{
boxShadow: '0 0 40px rgba(59, 130, 246, 0.2), 0 0 80px rgba(147, 51, 234, 0.1)'
}}
>
<Sparkles className="w-12 h-12 text-white" />
<Sparkles className="w-12 h-12 text-blue-400" />
</motion.div>
{/* Title */}
@@ -49,10 +68,10 @@ const LandingPage: React.FC<LandingPageProps> = ({ onStart }) => {
animate={{ opacity: 1 }}
transition={{ delay: 0.4 }}
>
<h1 className="text-6xl font-bold bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent">
<h1 className="text-7xl font-bold text-white tracking-tight">
DuoDuo Agent
</h1>
<p className="mt-4 text-xl text-neutral-600 dark:text-neutral-400">
<p className="mt-4 text-xl text-slate-400 font-light tracking-wide">
Agent协同 · ·
</p>
</motion.div>
@@ -62,54 +81,39 @@ const LandingPage: React.FC<LandingPageProps> = ({ onStart }) => {
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.6 }}
className="grid grid-cols-3 gap-6 mt-12"
className="grid grid-cols-3 gap-8 mt-16 max-w-3xl mx-auto"
>
<div className="glass-morphism rounded-2xl p-6 hover:scale-105 transition-transform">
<Layers className="w-8 h-8 text-blue-500 mb-4" />
<h3 className="font-semibold text-lg mb-2">7Agent</h3>
<p className="text-sm text-neutral-600 dark:text-neutral-400">
</p>
<div className="relative group">
<div className="absolute inset-0 bg-gradient-to-r from-blue-600/20 to-cyan-600/20 rounded-2xl blur-xl group-hover:blur-2xl transition-all opacity-0 group-hover:opacity-100" />
<div className="relative bg-slate-900/50 backdrop-blur-xl rounded-2xl p-8 border border-slate-800 hover:border-slate-700 transition-all h-full flex flex-col items-center text-center">
<Layers className="w-10 h-10 text-blue-400 mb-4" />
<h3 className="font-semibold text-lg mb-2 text-white">7Agent</h3>
<p className="text-sm text-slate-400">
</p>
</div>
</div>
<div className="glass-morphism rounded-2xl p-6 hover:scale-105 transition-transform">
<Zap className="w-8 h-8 text-purple-500 mb-4" />
<h3 className="font-semibold text-lg mb-2"></h3>
<p className="text-sm text-neutral-600 dark:text-neutral-400">
</p>
<div className="relative group">
<div className="absolute inset-0 bg-gradient-to-r from-purple-600/20 to-pink-600/20 rounded-2xl blur-xl group-hover:blur-2xl transition-all opacity-0 group-hover:opacity-100" />
<div className="relative bg-slate-900/50 backdrop-blur-xl rounded-2xl p-8 border border-slate-800 hover:border-slate-700 transition-all h-full flex flex-col items-center text-center">
<Zap className="w-10 h-10 text-purple-400 mb-4" />
<h3 className="font-semibold text-lg mb-2 text-white"></h3>
<p className="text-sm text-slate-400">
</p>
</div>
</div>
<div className="glass-morphism rounded-2xl p-6 hover:scale-105 transition-transform">
<Sparkles className="w-8 h-8 text-green-500 mb-4" />
<h3 className="font-semibold text-lg mb-2"></h3>
<p className="text-sm text-neutral-600 dark:text-neutral-400">
</p>
</div>
</motion.div>
{/* Demo Info */}
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ delay: 0.8 }}
className="glass-morphism rounded-2xl p-8 text-left"
>
<h2 className="text-2xl font-semibold mb-4"></h2>
<div className="space-y-2 text-neutral-600 dark:text-neutral-400">
<p>
<span className="font-medium text-neutral-900 dark:text-neutral-100"></span>
2024
</p>
<p>
<span className="font-medium text-neutral-900 dark:text-neutral-100"></span>
50,00035050,000
</p>
<p>
<span className="font-medium text-neutral-900 dark:text-neutral-100"></span>
3
</p>
<div className="relative group">
<div className="absolute inset-0 bg-gradient-to-r from-emerald-600/20 to-green-600/20 rounded-2xl blur-xl group-hover:blur-2xl transition-all opacity-0 group-hover:opacity-100" />
<div className="relative bg-slate-900/50 backdrop-blur-xl rounded-2xl p-8 border border-slate-800 hover:border-slate-700 transition-all h-full flex flex-col items-center text-center">
<Sparkles className="w-10 h-10 text-emerald-400 mb-4" />
<h3 className="font-semibold text-lg mb-2 text-white"></h3>
<p className="text-sm text-slate-400">
</p>
</div>
</div>
</motion.div>
@@ -117,17 +121,19 @@ const LandingPage: React.FC<LandingPageProps> = ({ onStart }) => {
<motion.button
initial={{ opacity: 0, scale: 0.9 }}
animate={{ opacity: 1, scale: 1 }}
transition={{ delay: 1 }}
transition={{ delay: 0.8 }}
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
onClick={onStart}
className="group relative inline-flex items-center gap-3 px-8 py-4 bg-gradient-to-r from-blue-500 to-purple-500 text-white font-semibold text-lg rounded-2xl shadow-xl hover:shadow-2xl transition-all"
className="relative mt-12 px-16 py-4 bg-white text-black font-semibold text-lg rounded-xl transition-all duration-300 group"
style={{
boxShadow: '0 4px 30px rgba(255, 255, 255, 0.1)'
}}
>
<span></span>
<ArrowRight className="w-5 h-5 group-hover:translate-x-1 transition-transform" />
{/* Glow effect */}
<div className="absolute inset-0 rounded-2xl bg-gradient-to-r from-blue-500 to-purple-500 blur-xl opacity-50 group-hover:opacity-70 transition-opacity" />
<span className="flex items-center gap-3">
<ArrowRight className="w-5 h-5 group-hover:translate-x-1 transition-transform" />
</span>
</motion.button>
{/* Footer */}
@@ -135,7 +141,7 @@ const LandingPage: React.FC<LandingPageProps> = ({ onStart }) => {
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ delay: 1.2 }}
className="text-sm text-neutral-500 dark:text-neutral-500 mt-8"
className="text-xs text-slate-600 mt-8 tracking-wide"
>
Powered by n8n Workflow · DeepSeek · Google Gemini
</motion.p>

View File

@@ -1,7 +1,7 @@
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 { Play, Pause, RotateCcw, Maximize2, Terminal, FileInput, Eye } from 'lucide-react';
import RequirementModal from '@/components/RequirementModal';
import ResultModal from '@/components/ResultModal';
@@ -46,9 +46,12 @@ const WorkflowPageV4 = () => {
const [showResultModal, setShowResultModal] = useState(false);
const [userRequirement, setUserRequirement] = useState('');
const [imageLoadingStates, setImageLoadingStates] = useState<{ [key: string]: boolean }>({});
const [logoClickCount, setLogoClickCount] = useState(0);
const [showFloatingButton, setShowFloatingButton] = useState(false);
const terminalRef = useRef<HTMLDivElement>(null);
const intervalRef = useRef<number | null>(null);
const progressLineIdRef = useRef<string | null>(null);
const logoClickTimerRef = useRef<number | null>(null);
// 启动序列
const startupSequence = [
@@ -639,6 +642,7 @@ const WorkflowPageV4 = () => {
setTimeout(() => {
console.log('Setting showResultModal to true');
setShowResultModal(true);
setShowFloatingButton(true);
}, 2000);
return;
@@ -696,6 +700,7 @@ const WorkflowPageV4 = () => {
}
}, [currentAgentIndex]);
// 计时器
useEffect(() => {
if (status === 'running') {
@@ -739,6 +744,30 @@ const WorkflowPageV4 = () => {
setIsExecuting(false);
setUserRequirement('');
setShowResultModal(false);
setShowFloatingButton(false);
};
// Logo三击处理
const handleLogoClick = () => {
const newCount = logoClickCount + 1;
setLogoClickCount(newCount);
// 清除之前的定时器
if (logoClickTimerRef.current) {
clearTimeout(logoClickTimerRef.current);
}
// 如果点击了3次打开结果弹窗并显示浮动按钮
if (newCount === 3) {
setShowResultModal(true);
setShowFloatingButton(true); // 调试模式也显示浮动按钮
setLogoClickCount(0);
} else {
// 设置500ms后重置计数
logoClickTimerRef.current = window.setTimeout(() => {
setLogoClickCount(0);
}, 500);
}
};
// 格式化时间
@@ -788,7 +817,15 @@ const WorkflowPageV4 = () => {
{/* 顶部控制栏 */}
<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>
{/* Duoduo Logo - 可三击打开结果 */}
<img
src="https://ddcz-1315997005.cos.ap-nanjing.myqcloud.com/static/img/duoduo_logo/LOGO_1097x300.png"
alt="Duoduo Agent"
className="h-7 cursor-pointer select-none"
onClick={handleLogoClick}
style={{ userSelect: 'none' }}
/>
<h1 className="text-lg font-semibold text-gray-900">·</h1>
<div className="flex items-center gap-2">
<button
onClick={status === 'idle' ? () => setShowRequirementModal(true) : pauseDemo}
@@ -1056,6 +1093,41 @@ const WorkflowPageV4 = () => {
onClose={() => setShowResultModal(false)}
onViewDetails={handleViewDetails}
/>
{/* 右下角浮动按钮 - 只在完成后显示 */}
<AnimatePresence>
{showFloatingButton && (
<motion.button
initial={{ opacity: 0, scale: 0.8, y: 20 }}
animate={{ opacity: 1, scale: 1, y: 0 }}
exit={{ opacity: 0, scale: 0.8, y: 20 }}
transition={{ type: 'spring', stiffness: 300, damping: 25 }}
onClick={() => setShowResultModal(true)}
className="fixed bottom-8 right-8 px-6 py-3 bg-gradient-to-r from-blue-600 to-purple-600 text-white rounded-full shadow-lg hover:shadow-xl transform hover:scale-105 transition-all flex items-center gap-2 z-50"
style={{
backdropFilter: 'blur(10px)',
background: 'linear-gradient(135deg, rgba(59, 130, 246, 0.9) 0%, rgba(147, 51, 234, 0.9) 100%)',
}}
>
<Eye className="w-5 h-5" />
<span className="font-medium"></span>
{/* 呼吸灯效果 */}
<motion.div
className="absolute -inset-1 bg-gradient-to-r from-blue-600 to-purple-600 rounded-full opacity-30"
animate={{
scale: [1, 1.2, 1],
opacity: [0.3, 0.1, 0.3],
}}
transition={{
duration: 2,
repeat: Infinity,
ease: "easeInOut"
}}
/>
</motion.button>
)}
</AnimatePresence>
</div>
);
};