- M3 认证/权限/审计/限流 + 全部 REST 接口 - M4 管理面板(MIUIx + 成绩录入/积分榜下钻/大屏控制) - M5a 大屏页面(六页 + 明细覆盖层 + 缩放适配) - M6 WebSocket 实时同步中心 - M7 xlsx 导出 + 赛事包 zip + 备份 - 规则包 YAML 导入导出(差异预览) - 字体 vendor 子集化(4 套 x2 字重) - 集成:realtime/export/rules 接入 main+httpapi;backup 子命令 - 修复:中间件包装 ResponseWriter 丢失 Hijacker,导致 WS 握手 501
125 lines
3.5 KiB
Batchfile
125 lines
3.5 KiB
Batchfile
@echo off
|
||
REM ============================================================================
|
||
REM Scoreboard 一键备份(Windows)
|
||
REM
|
||
REM 用 sqlite3.exe 的 VACUUM INTO 生成一致性快照,服务运行中也能安全执行,
|
||
REM 不需要停服务、不需要重启。产物落在 data\backups\,滚动保留最近 20 份。
|
||
REM
|
||
REM 依赖:sqlite3.exe(放到本脚本同目录、项目根目录,或加入 PATH 均可)。
|
||
REM 下载地址 https://www.sqlite.org/download.html 的 sqlite-tools-win-x64。
|
||
REM
|
||
REM 用法:deploy\backup.bat 手动备份(原因记 manual)
|
||
REM deploy\backup.bat publish 发布前备份(原因记 publish)
|
||
REM ============================================================================
|
||
setlocal enabledelayedexpansion
|
||
chcp 65001 >nul 2>&1
|
||
|
||
cd /d "%~dp0.."
|
||
set "ROOT=%CD%"
|
||
set "DATA=%ROOT%\data"
|
||
set "OUT=%DATA%\backups"
|
||
set "KEEP=20"
|
||
set "REASON=manual"
|
||
|
||
if not "%~1"=="" set "REASON=%~1"
|
||
set "REASON=%REASON: =_%"
|
||
set "REASON=%REASON:/=-%"
|
||
set "REASON=%REASON:\=-%"
|
||
set "REASON=%REASON:"=%"
|
||
|
||
if not exist "%DATA%" (
|
||
echo [错误] 找不到数据目录:%DATA%
|
||
echo 请在项目根目录执行本脚本。
|
||
exit /b 1
|
||
)
|
||
|
||
REM ---- 定位 sqlite3.exe -------------------------------------------------------
|
||
set "SQLITE="
|
||
if exist "%~dp0sqlite3.exe" set "SQLITE=%~dp0sqlite3.exe"
|
||
if not defined SQLITE if exist "%ROOT%\sqlite3.exe" set "SQLITE=%ROOT%\sqlite3.exe"
|
||
if not defined SQLITE for %%I in (sqlite3.exe) do if exist "%%~$PATH:I" set "SQLITE=%%~$PATH:I"
|
||
if not defined SQLITE (
|
||
echo [错误] 找不到 sqlite3.exe。
|
||
echo 请把它放到 deploy\ 目录或加入 PATH 后重试。
|
||
exit /b 1
|
||
)
|
||
|
||
REM ---- 时间戳:优先 PowerShell,避免受区域设置影响 -----------------------------
|
||
set "TS="
|
||
for /f "usebackq delims=" %%I in (`powershell -NoProfile -Command "Get-Date -Format yyyyMMdd-HHmmss" 2^>nul`) do set "TS=%%I"
|
||
if not defined TS call :fallback_ts
|
||
if not defined TS (
|
||
echo [错误] 无法生成时间戳。
|
||
exit /b 1
|
||
)
|
||
|
||
if not exist "%OUT%" mkdir "%OUT%"
|
||
|
||
echo === Scoreboard 备份 ===
|
||
echo 数据目录:%DATA%
|
||
echo 备份目录:%OUT%
|
||
echo 时间戳 :%TS%
|
||
echo.
|
||
|
||
set /a OK=0
|
||
set /a FAIL=0
|
||
|
||
if exist "%DATA%\system.db" call :backup "system" "%DATA%\system.db"
|
||
|
||
for /d %%D in ("%DATA%\event_projs\*") do (
|
||
if exist "%%~fD\event.db" call :backup "%%~nxD" "%%~fD\event.db"
|
||
)
|
||
|
||
echo.
|
||
echo === 滚动清理(保留最近 %KEEP% 份)===
|
||
set /a N=0
|
||
for /f "delims=" %%F in ('dir /b /o-d /a-d "%OUT%\*.db" 2^>nul') do (
|
||
set /a N+=1
|
||
if !N! GTR %KEEP% (
|
||
echo 删除 %%F
|
||
del /f /q "%OUT%\%%F" >nul 2>&1
|
||
)
|
||
)
|
||
|
||
echo.
|
||
echo === 备份完成:成功 !OK! 个,失败 !FAIL! 个 ===
|
||
dir /b "%OUT%\*.db" 2>nul
|
||
|
||
if !FAIL! GTR 0 (
|
||
endlocal
|
||
exit /b 1
|
||
)
|
||
endlocal
|
||
exit /b 0
|
||
|
||
REM ---- 备份单个库:%1 文件名前缀,%2 数据库路径 -------------------------------
|
||
:backup
|
||
set "PREFIX=%~1"
|
||
set "DBFILE=%~2"
|
||
set "TARGET=%OUT%\%PREFIX%-%REASON%-%TS%.db"
|
||
if exist "%TARGET%" set "TARGET=%OUT%\%PREFIX%-%REASON%-%TS%-%RANDOM%.db"
|
||
|
||
echo 备份 %DBFILE%
|
||
echo -^> %TARGET%
|
||
"%SQLITE%" "%DBFILE%" "VACUUM INTO '%TARGET%'"
|
||
if errorlevel 1 (
|
||
echo [失败] sqlite3 返回错误
|
||
set /a FAIL+=1
|
||
) else (
|
||
set /a OK+=1
|
||
)
|
||
exit /b 0
|
||
|
||
REM ---- %DATE%/%TIME% 兜底:只保证名字不重复 -----------------------------------
|
||
:fallback_ts
|
||
set "D=%DATE%"
|
||
set "T=%TIME%"
|
||
set "D=%D:/=%"
|
||
set "D=%D:-=%"
|
||
set "D=%D:.=%"
|
||
set "T=%T::=%"
|
||
set "T=%T:.=%"
|
||
set "T=%T: =0%"
|
||
set "TS=%D%-%T%"
|
||
exit /b 0
|