@echo off REM TSP智能助手快速更新脚本 (Windows) REM 支持热更新和完整更新 setlocal enabledelayedexpansion REM 颜色定义 set "GREEN=[32m" set "YELLOW=[33m" set "RED=[31m" set "NC=[0m" REM 配置变量 set "APP_NAME=tsp_assistant" set "DEPLOY_PATH=." set "BACKUP_PATH=.\backups" set "HEALTH_URL=http://localhost:5000/api/health" REM 解析参数 set "ACTION=%1" set "SOURCE_PATH=%2" set "ENVIRONMENT=%3" if "%ACTION%"=="" ( echo 用法: %0 {check^|hot-update^|full-update^|auto-update^|rollback} [源路径] [环境] echo. echo 命令说明: echo check - 检查更新可用性 echo hot-update - 热更新(不重启服务) echo full-update - 完整更新(重启服务) echo auto-update - 自动更新(智能选择) echo rollback - 回滚到指定备份 echo. echo 环境: development, staging, production exit /b 1 ) if "%ENVIRONMENT%"=="" set "ENVIRONMENT=production" if "%SOURCE_PATH%"=="" set "SOURCE_PATH=." REM 日志函数 :log_info echo %GREEN%[INFO]%NC% %~1 goto :eof :log_warn echo %YELLOW%[WARN]%NC% %~1 goto :eof :log_error echo %RED%[ERROR]%NC% %~1 goto :eof REM 检查更新可用性 :check_update call :log_info "检查更新可用性..." if not exist "%SOURCE_PATH%\version.json" ( call :log_error "源路径中未找到版本文件" exit /b 1 ) REM 比较版本 for /f "tokens=2 delims=:" %%a in ('findstr "version" "%SOURCE_PATH%\version.json"') do ( set "NEW_VERSION=%%a" set "NEW_VERSION=!NEW_VERSION: =!" set "NEW_VERSION=!NEW_VERSION:"=!" set "NEW_VERSION=!NEW_VERSION:,=!" ) if exist "version.json" ( for /f "tokens=2 delims=:" %%a in ('findstr "version" "version.json"') do ( set "CURRENT_VERSION=%%a" set "CURRENT_VERSION=!CURRENT_VERSION: =!" set "CURRENT_VERSION=!CURRENT_VERSION:"=!" set "CURRENT_VERSION=!CURRENT_VERSION:,=!" ) ) else ( set "CURRENT_VERSION=unknown" ) if "!NEW_VERSION!"=="!CURRENT_VERSION!" ( call :log_info "没有更新可用 (当前版本: !CURRENT_VERSION!)" ) else ( call :log_info "发现更新: !CURRENT_VERSION! -> !NEW_VERSION!" ) goto :eof REM 创建备份 :create_backup set "TIMESTAMP=%date:~0,4%%date:~5,2%%date:~8,2%_%time:~0,2%%time:~3,2%%time:~6,2%" set "TIMESTAMP=!TIMESTAMP: =0!" set "BACKUP_NAME=%APP_NAME%_backup_!TIMESTAMP!" call :log_info "创建备份: !BACKUP_NAME!" if not exist "%BACKUP_PATH%" mkdir "%BACKUP_PATH%" mkdir "%BACKUP_PATH%\!BACKUP_NAME!" REM 备份应用文件 if exist "%DEPLOY_PATH%" ( call :log_info "备份应用文件..." xcopy "%DEPLOY_PATH%\*" "%BACKUP_PATH%\!BACKUP_NAME!\" /E /I /Y ) REM 备份数据库 if exist "%DEPLOY_PATH%\tsp_assistant.db" ( call :log_info "备份数据库..." mkdir "%BACKUP_PATH%\!BACKUP_NAME!\database" copy "%DEPLOY_PATH%\tsp_assistant.db" "%BACKUP_PATH%\!BACKUP_NAME!\database\" ) call :log_info "备份完成: !BACKUP_NAME!" echo !BACKUP_NAME! goto :eof REM 热更新 :hot_update call :log_info "开始热更新..." REM 支持热更新的文件列表 set "HOT_UPDATE_FILES=src\web\static\js\dashboard.js src\web\static\css\style.css src\web\templates\dashboard.html src\web\app.py" set "UPDATED_COUNT=0" for %%f in (%HOT_UPDATE_FILES%) do ( if exist "%SOURCE_PATH%\%%f" ( call :log_info "更新文件: %%f" if not exist "%DEPLOY_PATH%\%%f" mkdir "%DEPLOY_PATH%\%%f" 2>nul copy "%SOURCE_PATH%\%%f" "%DEPLOY_PATH%\%%f" /Y >nul set /a UPDATED_COUNT+=1 ) ) if !UPDATED_COUNT! gtr 0 ( call :log_info "热更新完成,更新了 !UPDATED_COUNT! 个文件" ) else ( call :log_info "没有文件需要热更新" ) goto :eof REM 完整更新 :full_update call :log_info "开始完整更新..." REM 创建备份 call :create_backup set "BACKUP_NAME=!BACKUP_NAME!" REM 停止服务(如果运行中) call :log_info "停止服务..." taskkill /f /im python.exe 2>nul || echo 服务未运行 REM 更新文件 call :log_info "更新应用文件..." if exist "%DEPLOY_PATH%" rmdir /s /q "%DEPLOY_PATH%" mkdir "%DEPLOY_PATH%" xcopy "%SOURCE_PATH%\*" "%DEPLOY_PATH%\" /E /I /Y REM 安装依赖 call :log_info "安装依赖..." cd "%DEPLOY_PATH%" if exist "requirements.txt" ( pip install -r requirements.txt ) REM 运行数据库迁移 call :log_info "运行数据库迁移..." if exist "init_database.py" ( python init_database.py ) REM 启动服务 call :log_info "启动服务..." start /b python start_dashboard.py REM 等待服务启动 call :log_info "等待服务启动..." timeout /t 15 /nobreak >nul REM 健康检查 call :log_info "执行健康检查..." set "RETRY_COUNT=0" set "MAX_RETRIES=10" :health_check_loop if !RETRY_COUNT! geq !MAX_RETRIES! ( call :log_error "健康检查失败,开始回滚..." call :rollback !BACKUP_NAME! exit /b 1 ) curl -f "%HEALTH_URL%" >nul 2>&1 if !errorlevel! equ 0 ( call :log_info "健康检查通过!" call :log_info "更新成功!" call :log_info "备份名称: !BACKUP_NAME!" exit /b 0 ) else ( call :log_warn "健康检查失败,重试中... (!RETRY_COUNT!/!MAX_RETRIES!)" set /a RETRY_COUNT+=1 timeout /t 5 /nobreak >nul goto :health_check_loop ) REM 回滚 :rollback set "BACKUP_NAME=%1" if "%BACKUP_NAME%"=="" ( call :log_error "请指定备份名称" exit /b 1 ) call :log_info "开始回滚到备份: !BACKUP_NAME!" if not exist "%BACKUP_PATH%\!BACKUP_NAME!" ( call :log_error "备份不存在: !BACKUP_NAME!" exit /b 1 ) REM 停止服务 call :log_info "停止服务..." taskkill /f /im python.exe 2>nul || echo 服务未运行 REM 恢复文件 call :log_info "恢复文件..." if exist "%DEPLOY_PATH%" rmdir /s /q "%DEPLOY_PATH%" mkdir "%DEPLOY_PATH%" xcopy "%BACKUP_PATH%\!BACKUP_NAME!\*" "%DEPLOY_PATH%\" /E /I /Y REM 恢复数据库 if exist "%BACKUP_PATH%\!BACKUP_NAME!\database\tsp_assistant.db" ( call :log_info "恢复数据库..." copy "%BACKUP_PATH%\!BACKUP_NAME!\database\tsp_assistant.db" "%DEPLOY_PATH%\" ) REM 启动服务 call :log_info "启动服务..." cd "%DEPLOY_PATH%" start /b python start_dashboard.py REM 等待服务启动 timeout /t 15 /nobreak >nul REM 健康检查 curl -f "%HEALTH_URL%" >nul 2>&1 if !errorlevel! equ 0 ( call :log_info "回滚成功!" ) else ( call :log_error "回滚后健康检查失败" exit /b 1 ) goto :eof REM 自动更新 :auto_update call :log_info "开始自动更新..." REM 尝试热更新 call :hot_update if !errorlevel! equ 0 ( call :log_info "热更新成功" exit /b 0 ) REM 热更新失败,进行完整更新 call :log_info "热更新失败,进行完整更新..." call :full_update goto :eof REM 主逻辑 if "%ACTION%"=="check" ( call :check_update ) else if "%ACTION%"=="hot-update" ( call :hot_update ) else if "%ACTION%"=="full-update" ( call :full_update ) else if "%ACTION%"=="auto-update" ( call :auto_update ) else if "%ACTION%"=="rollback" ( call :rollback "%SOURCE_PATH%" ) else ( call :log_error "未知操作: %ACTION%" exit /b 1 ) endlocal