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:
500
n8n-n8n-1.109.2/start_cn.bat
Normal file
500
n8n-n8n-1.109.2/start_cn.bat
Normal file
@@ -0,0 +1,500 @@
|
||||
@echo off
|
||||
REM Save original codepage
|
||||
for /f "tokens=2 delims=:" %%a in ('chcp') do set OLDCP=%%a
|
||||
chcp 65001 >nul 2>&1
|
||||
REM n8n Chinese Version Quick Start Script (Windows)
|
||||
REM Author: xiaoqi
|
||||
REM Last Update: 2025-09-09
|
||||
REM Compatibility: Windows 7/8/10/11
|
||||
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
REM Display banner
|
||||
:show_banner
|
||||
echo ======================================
|
||||
echo n8n Chinese Version Launcher
|
||||
echo Version: n8n-1.109.2 with CN
|
||||
echo Maintainer: xiaoqi
|
||||
echo ======================================
|
||||
echo.
|
||||
|
||||
REM Parse command line arguments
|
||||
set "DEV_MODE="
|
||||
set "FORCE_BUILD="
|
||||
set "CHECK_ONLY="
|
||||
set "SKIP_DEPS="
|
||||
set "USE_NPM="
|
||||
set "CUSTOM_PORT=5678"
|
||||
|
||||
:parse_args
|
||||
if "%~1"=="" goto main_execution
|
||||
if /I "%~1"=="-h" goto show_help
|
||||
if /I "%~1"=="--help" goto show_help
|
||||
if /I "%~1"=="-d" (
|
||||
set "DEV_MODE=true"
|
||||
shift
|
||||
goto parse_args
|
||||
)
|
||||
if /I "%~1"=="--dev" (
|
||||
set "DEV_MODE=true"
|
||||
shift
|
||||
goto parse_args
|
||||
)
|
||||
if /I "%~1"=="-b" (
|
||||
set "FORCE_BUILD=true"
|
||||
shift
|
||||
goto parse_args
|
||||
)
|
||||
if /I "%~1"=="--build" (
|
||||
set "FORCE_BUILD=true"
|
||||
shift
|
||||
goto parse_args
|
||||
)
|
||||
if /I "%~1"=="-c" (
|
||||
set "CHECK_ONLY=true"
|
||||
shift
|
||||
goto parse_args
|
||||
)
|
||||
if /I "%~1"=="--check" (
|
||||
set "CHECK_ONLY=true"
|
||||
shift
|
||||
goto parse_args
|
||||
)
|
||||
if /I "%~1"=="--skip-deps" (
|
||||
set "SKIP_DEPS=true"
|
||||
shift
|
||||
goto parse_args
|
||||
)
|
||||
if /I "%~1"=="--npm" (
|
||||
set "USE_NPM=true"
|
||||
shift
|
||||
goto parse_args
|
||||
)
|
||||
if /I "%~1"=="-p" (
|
||||
set "CUSTOM_PORT=%~2"
|
||||
shift
|
||||
shift
|
||||
goto parse_args
|
||||
)
|
||||
if /I "%~1"=="--port" (
|
||||
set "CUSTOM_PORT=%~2"
|
||||
shift
|
||||
shift
|
||||
goto parse_args
|
||||
)
|
||||
echo [ERROR] Unknown option: %~1
|
||||
goto show_help
|
||||
|
||||
:main_execution
|
||||
REM Check OS version
|
||||
call :check_os_version
|
||||
|
||||
REM Check and change to correct directory
|
||||
call :check_and_change_directory
|
||||
if errorlevel 1 goto error_exit
|
||||
|
||||
REM Check dependencies
|
||||
if not defined SKIP_DEPS (
|
||||
echo [INFO] Checking system dependencies...
|
||||
call :check_dependencies
|
||||
if errorlevel 1 goto error_exit
|
||||
)
|
||||
|
||||
REM Check port
|
||||
call :check_port
|
||||
if errorlevel 1 goto error_exit
|
||||
|
||||
REM Stop existing processes
|
||||
call :stop_existing
|
||||
|
||||
REM Setup environment
|
||||
call :setup_environment
|
||||
|
||||
REM Check only mode
|
||||
if defined CHECK_ONLY (
|
||||
echo [SUCCESS] System check completed
|
||||
goto end
|
||||
)
|
||||
|
||||
REM Install dependencies if needed
|
||||
if not exist "node_modules\" (
|
||||
echo [INFO] Installing dependencies...
|
||||
if defined USE_NPM (
|
||||
call :install_with_npm
|
||||
) else (
|
||||
call :install_with_pnpm
|
||||
)
|
||||
if errorlevel 1 goto error_exit
|
||||
)
|
||||
|
||||
REM Check and install run-script-os
|
||||
if not exist "node_modules\run-script-os" (
|
||||
echo [FIX] Installing run-script-os...
|
||||
call npm install run-script-os
|
||||
)
|
||||
|
||||
REM Build or check build
|
||||
if defined FORCE_BUILD (
|
||||
echo [INFO] Force rebuilding project...
|
||||
call :build_project
|
||||
if errorlevel 1 goto error_exit
|
||||
) else (
|
||||
call :check_build
|
||||
if errorlevel 1 goto error_exit
|
||||
)
|
||||
|
||||
REM Dev mode or normal start
|
||||
if defined DEV_MODE (
|
||||
echo [INFO] Starting n8n in development mode...
|
||||
echo [WARNING] Dev mode takes longer to start...
|
||||
if defined USE_NPM (
|
||||
call npm run dev
|
||||
) else (
|
||||
call pnpm dev
|
||||
)
|
||||
) else (
|
||||
call :start_n8n
|
||||
)
|
||||
goto end
|
||||
|
||||
REM ========== Functions ==========
|
||||
|
||||
:check_os_version
|
||||
ver | findstr /i "5\.1\." >nul
|
||||
if not errorlevel 1 (
|
||||
echo [WARNING] Windows XP detected
|
||||
)
|
||||
ver | findstr /i "6\.0\." >nul
|
||||
if not errorlevel 1 (
|
||||
echo [INFO] Windows Vista detected
|
||||
)
|
||||
ver | findstr /i "6\.1\." >nul
|
||||
if not errorlevel 1 (
|
||||
echo [INFO] Windows 7 detected
|
||||
)
|
||||
ver | findstr /i "6\.2\." >nul
|
||||
if not errorlevel 1 (
|
||||
echo [INFO] Windows 8 detected
|
||||
)
|
||||
ver | findstr /i "6\.3\." >nul
|
||||
if not errorlevel 1 (
|
||||
echo [INFO] Windows 8.1 detected
|
||||
)
|
||||
ver | findstr /i "10\.0\." >nul
|
||||
if not errorlevel 1 (
|
||||
echo [INFO] Windows 10/11 detected
|
||||
)
|
||||
exit /b 0
|
||||
|
||||
:check_and_change_directory
|
||||
if exist "package.json" if exist "packages" (
|
||||
echo [INFO] Already in n8n project directory
|
||||
exit /b 0
|
||||
)
|
||||
|
||||
set "SCRIPT_DIR=%~dp0"
|
||||
if "%SCRIPT_DIR:~-1%"=="\" set "SCRIPT_DIR=%SCRIPT_DIR:~0,-1%"
|
||||
|
||||
echo %SCRIPT_DIR% | findstr /I /C:"n8n-n8n-1.109.2" >nul
|
||||
if not errorlevel 1 (
|
||||
echo [INFO] Switching to n8n project directory
|
||||
cd /d "%SCRIPT_DIR%" 2>nul
|
||||
if errorlevel 1 (
|
||||
cd "%SCRIPT_DIR%" 2>nul
|
||||
if errorlevel 1 (
|
||||
echo [ERROR] Cannot change to directory: %SCRIPT_DIR%
|
||||
exit /b 1
|
||||
)
|
||||
)
|
||||
echo [SUCCESS] Changed to correct n8n project directory
|
||||
exit /b 0
|
||||
)
|
||||
|
||||
if exist "n8n-n8n-1.109.2\" (
|
||||
cd n8n-n8n-1.109.2
|
||||
) else if exist "..\n8n-n8n-1.109.2\" (
|
||||
cd ..\n8n-n8n-1.109.2
|
||||
) else if exist "..\..\n8n-n8n-1.109.2\" (
|
||||
cd ..\..\n8n-n8n-1.109.2
|
||||
) else (
|
||||
echo [ERROR] n8n-n8n-1.109.2 directory not found
|
||||
echo [INFO] Please run this script from the correct project directory
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
if not exist "package.json" (
|
||||
echo [ERROR] Invalid directory structure, missing package.json
|
||||
exit /b 1
|
||||
)
|
||||
if not exist "packages" (
|
||||
echo [ERROR] Invalid directory structure, missing packages directory
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo [SUCCESS] Changed to correct n8n project directory
|
||||
exit /b 0
|
||||
|
||||
:check_dependencies
|
||||
where node >nul 2>&1
|
||||
if errorlevel 1 (
|
||||
if exist "C:\Program Files\nodejs\node.exe" (
|
||||
set "PATH=C:\Program Files\nodejs;%PATH%"
|
||||
) else if exist "C:\Program Files (x86)\nodejs\node.exe" (
|
||||
set "PATH=C:\Program Files (x86)\nodejs;%PATH%"
|
||||
) else (
|
||||
echo [ERROR] Node.js not installed or not in PATH
|
||||
echo [INFO] Please visit https://nodejs.org to download and install
|
||||
exit /b 1
|
||||
)
|
||||
)
|
||||
|
||||
echo [INFO] Node.js version:
|
||||
node --version
|
||||
|
||||
if not defined USE_NPM (
|
||||
where pnpm >nul 2>&1
|
||||
if errorlevel 1 (
|
||||
echo [WARNING] pnpm not installed, trying npm
|
||||
set "USE_NPM=true"
|
||||
) else (
|
||||
echo [INFO] Using pnpm as package manager
|
||||
)
|
||||
) else (
|
||||
echo [INFO] Using npm as package manager
|
||||
)
|
||||
|
||||
echo [SUCCESS] Dependencies check passed
|
||||
exit /b 0
|
||||
|
||||
:install_with_pnpm
|
||||
echo [INFO] Installing dependencies with pnpm...
|
||||
where pnpm >nul 2>&1
|
||||
if errorlevel 1 (
|
||||
echo [INFO] Installing pnpm...
|
||||
call npm install -g pnpm@8
|
||||
if errorlevel 1 (
|
||||
echo [ERROR] pnpm installation failed
|
||||
exit /b 1
|
||||
)
|
||||
)
|
||||
call pnpm install --no-frozen-lockfile
|
||||
exit /b %errorlevel%
|
||||
|
||||
:install_with_npm
|
||||
echo [WARNING] Using npm install
|
||||
echo [INFO] Recommend installing pnpm: npm install -g pnpm
|
||||
call npm install --legacy-peer-deps
|
||||
exit /b %errorlevel%
|
||||
|
||||
:check_port
|
||||
echo [INFO] Checking port %CUSTOM_PORT% availability...
|
||||
netstat -ano 2>nul | findstr ":%CUSTOM_PORT%" >nul 2>&1
|
||||
if not errorlevel 1 (
|
||||
echo [WARNING] Port %CUSTOM_PORT% is already in use
|
||||
echo [INFO] Checking process using the port...
|
||||
netstat -ano | findstr ":%CUSTOM_PORT%"
|
||||
echo.
|
||||
|
||||
set /p "kill_process=Terminate the process? (y/N): "
|
||||
if /I "!kill_process!"=="y" (
|
||||
echo [INFO] Terminating process...
|
||||
for /f "tokens=5" %%a in ('netstat -ano ^| findstr ":%CUSTOM_PORT%"') do (
|
||||
taskkill /PID %%a /F >nul 2>&1
|
||||
if errorlevel 1 (
|
||||
tskill %%a >nul 2>&1
|
||||
)
|
||||
)
|
||||
echo [SUCCESS] Process terminated
|
||||
timeout /t 2 /nobreak >nul 2>&1
|
||||
if errorlevel 1 (
|
||||
ping -n 3 127.0.0.1 >nul
|
||||
)
|
||||
) else (
|
||||
echo [ERROR] Cannot start n8n, port is in use
|
||||
exit /b 1
|
||||
)
|
||||
)
|
||||
exit /b 0
|
||||
|
||||
:stop_existing
|
||||
echo [INFO] Stopping existing n8n processes...
|
||||
|
||||
taskkill /F /IM node.exe /FI "WINDOWTITLE eq *n8n*" >nul 2>&1
|
||||
taskkill /F /IM node.exe /FI "WINDOWTITLE eq *pnpm*" >nul 2>&1
|
||||
taskkill /F /IM node.exe /FI "WINDOWTITLE eq *npm*" >nul 2>&1
|
||||
|
||||
timeout /t 2 /nobreak >nul 2>&1
|
||||
if errorlevel 1 (
|
||||
ping -n 3 127.0.0.1 >nul
|
||||
)
|
||||
|
||||
echo [SUCCESS] Existing processes stopped
|
||||
exit /b 0
|
||||
|
||||
:setup_environment
|
||||
echo [INFO] Setting environment variables...
|
||||
|
||||
set "N8N_PORT=%CUSTOM_PORT%"
|
||||
set "N8N_DEFAULT_LOCALE=zh-CN"
|
||||
set "N8N_SECURE_COOKIE=false"
|
||||
set "DB_SQLITE_POOL_SIZE=5"
|
||||
set "N8N_RUNNERS_ENABLED=true"
|
||||
set "N8N_BLOCK_ENV_ACCESS_IN_NODE=false"
|
||||
set "NODE_OPTIONS=--max-old-space-size=4096"
|
||||
|
||||
echo [SUCCESS] Environment variables set
|
||||
echo - N8N_PORT=%CUSTOM_PORT%
|
||||
echo - N8N_DEFAULT_LOCALE=zh-CN
|
||||
echo - N8N_SECURE_COOKIE=false
|
||||
echo - DB_SQLITE_POOL_SIZE=5
|
||||
echo - NODE_OPTIONS=--max-old-space-size=4096
|
||||
exit /b 0
|
||||
|
||||
:check_build
|
||||
if not exist "packages\cli\dist\" goto need_build
|
||||
if not exist "packages\core\dist\" goto need_build
|
||||
if not exist "packages\workflow\dist\" goto need_build
|
||||
exit /b 0
|
||||
|
||||
:need_build
|
||||
echo [WARNING] Project needs to be built
|
||||
set /p "build_project=Build project now? This may take a few minutes (y/N): "
|
||||
if /I "!build_project!"=="y" (
|
||||
call :build_project
|
||||
)
|
||||
exit /b 0
|
||||
|
||||
:build_project
|
||||
echo [INFO] Building project...
|
||||
if defined USE_NPM (
|
||||
call npm run build > build.log 2>&1
|
||||
) else (
|
||||
call pnpm build > build.log 2>&1
|
||||
)
|
||||
if errorlevel 1 (
|
||||
echo [ERROR] Build failed, check build.log
|
||||
type build.log | more
|
||||
exit /b 1
|
||||
)
|
||||
echo [SUCCESS] Project built successfully
|
||||
exit /b 0
|
||||
|
||||
:start_n8n
|
||||
echo [INFO] Starting n8n Chinese version...
|
||||
|
||||
set "DATETIME=%date:~0,4%%date:~5,2%%date:~8,2%-%time:~0,2%%time:~3,2%"
|
||||
set "DATETIME=%DATETIME: =0%"
|
||||
set "DATETIME=%DATETIME:/=%"
|
||||
set "DATETIME=%DATETIME:\=%"
|
||||
set "LOG_FILE=n8n-%DATETIME%.log"
|
||||
|
||||
echo [INFO] Starting n8n service...
|
||||
echo [INFO] Log file: %LOG_FILE%
|
||||
|
||||
if defined USE_NPM (
|
||||
start "n8n Server" /B cmd /c "npm start > %LOG_FILE% 2>&1"
|
||||
) else (
|
||||
start "n8n Server" /B cmd /c "pnpm start > %LOG_FILE% 2>&1"
|
||||
)
|
||||
|
||||
echo Waiting for n8n to start
|
||||
set "count=0"
|
||||
:wait_loop
|
||||
set /a count+=1
|
||||
if %count% gtr 60 goto start_failed
|
||||
|
||||
netstat -an 2>nul | findstr ":%CUSTOM_PORT%" | findstr "LISTENING" >nul 2>&1
|
||||
if not errorlevel 1 goto start_success
|
||||
|
||||
set /p "=." <nul
|
||||
timeout /t 1 /nobreak >nul 2>&1
|
||||
if errorlevel 1 (
|
||||
ping -n 2 127.0.0.1 >nul
|
||||
)
|
||||
goto wait_loop
|
||||
|
||||
:start_success
|
||||
echo.
|
||||
echo [SUCCESS] n8n started successfully!
|
||||
echo.
|
||||
echo ========== START INFO ==========
|
||||
echo Access URL: http://localhost:%CUSTOM_PORT%
|
||||
echo Interface Language: Chinese (zh-CN)
|
||||
echo Log file: %LOG_FILE%
|
||||
echo =================================
|
||||
echo.
|
||||
echo [INFO] Use Ctrl+C to stop service
|
||||
echo [TIP] First visit requires account setup
|
||||
echo.
|
||||
pause
|
||||
exit /b 0
|
||||
|
||||
:start_failed
|
||||
echo.
|
||||
echo [ERROR] n8n failed to start
|
||||
echo [INFO] Check log file: %LOG_FILE%
|
||||
if exist "%LOG_FILE%" (
|
||||
echo.
|
||||
echo ===== ERROR LOG =====
|
||||
type "%LOG_FILE%" | more
|
||||
)
|
||||
|
||||
echo.
|
||||
echo [INFO] Trying alternative start method...
|
||||
call npx n8n
|
||||
if errorlevel 1 (
|
||||
echo [ERROR] Alternative method also failed
|
||||
echo.
|
||||
echo Please try:
|
||||
echo 1. Run: npm install run-script-os
|
||||
echo 2. Run: node packages/cli/bin/n8n
|
||||
)
|
||||
pause
|
||||
exit /b 1
|
||||
|
||||
:show_help
|
||||
echo Usage: %~nx0 [options]
|
||||
echo.
|
||||
echo Options:
|
||||
echo -h, --help Show this help
|
||||
echo -d, --dev Start in development mode
|
||||
echo -b, --build Force rebuild project
|
||||
echo -c, --check Only check system status
|
||||
echo -p, --port Specify port (default: 5678)
|
||||
echo --skip-deps Skip dependency check
|
||||
echo --npm Use npm instead of pnpm
|
||||
echo.
|
||||
echo Examples:
|
||||
echo %~nx0 # Normal start (port 5678)
|
||||
echo %~nx0 -p 8080 # Use port 8080
|
||||
echo %~nx0 -d # Development mode
|
||||
echo %~nx0 -b # Rebuild and start
|
||||
echo %~nx0 --npm # Use npm
|
||||
echo %~nx0 -p 3000 -d # Dev mode on port 3000
|
||||
echo.
|
||||
echo Troubleshooting:
|
||||
echo 1. If pnpm install fails, use --npm option
|
||||
echo 2. If port is in use, script will prompt to terminate process
|
||||
echo 3. Check build.log when build fails
|
||||
echo.
|
||||
goto end
|
||||
|
||||
:error_exit
|
||||
echo [ERROR] Script execution failed
|
||||
echo.
|
||||
echo Common solutions:
|
||||
echo 1. Ensure Node.js version is 18.x or 20.x
|
||||
echo 2. Try running with administrator privileges
|
||||
echo 3. Use --npm option if pnpm has issues
|
||||
echo 4. Check network connection and proxy settings
|
||||
echo.
|
||||
pause
|
||||
exit /b 1
|
||||
|
||||
:end
|
||||
REM Restore original codepage
|
||||
if defined OLDCP (
|
||||
chcp %OLDCP% >nul 2>&1
|
||||
)
|
||||
endlocal
|
||||
exit /b 0
|
||||
@@ -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" />
|
||||
|
||||
@@ -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">7个专业Agent</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">7个专业Agent</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,000平方米展览面积,350家参展商,预计50,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>
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user