Files
AIRegulation-DocAnalysis/dev.bat

646 lines
16 KiB
Batchfile
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.

@echo off
setlocal EnableExtensions EnableDelayedExpansion
set "ROOT_DIR=%~dp0"
pushd "%ROOT_DIR%" >nul
set "VENV_DIR=.venv"
set "VENV_PYTHON=%VENV_DIR%\Scripts\python.exe"
set "LOG_DIR=logs"
set "API_PID_FILE=%LOG_DIR%\api.pid"
set "FRONTEND_PID_FILE=%LOG_DIR%\frontend.pid"
set "API_LOG_FILE=%CD%\%LOG_DIR%\api.log"
set "FRONTEND_LOG_FILE=%CD%\%LOG_DIR%\frontend.log"
call :load_env
if not defined API_HOST set "API_HOST=0.0.0.0"
if not defined API_PORT set "API_PORT=8000"
if not defined FRONTEND_PORT set "FRONTEND_PORT=5173"
if not defined FRONTEND_MODE set "FRONTEND_MODE=dev"
if "%~1"=="" goto help
if /I "%~1"=="help" goto help
if /I "%~1"=="-h" goto help
if /I "%~1"=="--help" goto help
if /I "%~1"=="setup" goto setup
if /I "%~1"=="start" goto start
if /I "%~1"=="stop" goto stop
if /I "%~1"=="restart" goto restart
if /I "%~1"=="status" goto status
if /I "%~1"=="logs" goto logs
echo Unknown command: %~1
echo Use dev.bat help to see available commands.
exit /b 1
:help
echo.
echo ========================================
echo AI+合规智能中枢统一脚本Windows
echo ========================================
echo.
echo Usage:
echo dev.bat help
echo dev.bat setup
echo dev.bat start [all^|api^|frontend] [--foreground] [--mode dev^|static]
echo dev.bat stop [all^|api^|frontend]
echo dev.bat restart [all^|api^|frontend] [--mode dev^|static]
echo dev.bat status
echo dev.bat logs ^<api^|frontend^> [--follow]
echo.
echo Command details:
echo help
echo Show the full command list, default ports, log paths and examples.
echo.
echo setup
echo Create .venv if missing, install backend dependencies from backend\requirements.txt,
echo run npm install in frontend, then report Docker base service status.
echo.
echo start
echo Start services. Default target is all.
echo start api --foreground Run uvicorn in the current window with --reload for debugging.
echo start frontend --mode static Build the frontend and serve frontend\dist as static files.
echo.
echo stop
echo Stop services. It first uses logs\*.pid, then falls back to listeners on the configured ports.
echo.
echo restart
echo Stop and then start the selected target.
echo.
echo status
echo Show API, frontend and Docker service status. API status also checks /health.
echo.
echo logs
echo Show the last 50 lines by default. Add --follow to stream updates.
echo.
echo Defaults:
echo API_HOST = %API_HOST%
echo API_PORT = %API_PORT%
echo FRONTEND_PORT = %FRONTEND_PORT%
echo FRONTEND_MODE = %FRONTEND_MODE%
echo Log files = logs\api.log, logs\frontend.log
echo.
echo Examples:
echo dev.bat setup
echo dev.bat start
echo dev.bat start api --foreground
echo dev.bat start frontend --mode static
echo dev.bat restart frontend --mode dev
echo dev.bat status
echo dev.bat logs api --follow
echo.
exit /b 0
:setup
if not exist "%LOG_DIR%" mkdir "%LOG_DIR%"
echo.
echo ========================================
echo AI+合规智能中枢 - 环境初始化
echo ========================================
echo.
call :resolve_python_bootstrap || exit /b 1
call %PYTHON_BOOTSTRAP% -c "import sys; raise SystemExit(0 if sys.version_info ^>= (3, 10) else 1)" || (
echo Python 3.10+ is required.
exit /b 1
)
if not exist "%VENV_PYTHON%" (
call %PYTHON_BOOTSTRAP% -m venv "%VENV_DIR%" || exit /b 1
echo Created virtual environment: %VENV_DIR%
) else (
echo Virtual environment already exists: %VENV_DIR%
)
"%VENV_PYTHON%" -m pip install --upgrade pip || exit /b 1
"%VENV_PYTHON%" -m pip install -r backend\requirements.txt || exit /b 1
echo Backend dependencies installed.
if not exist "frontend\package.json" (
echo Frontend package.json not found.
exit /b 1
)
where npm >nul 2>nul || (
echo npm was not found. Install Node.js 20+ first.
exit /b 1
)
pushd frontend >nul
call npm install || (
popd >nul
exit /b 1
)
popd >nul
echo Frontend dependencies installed.
echo.
echo Docker base services:
for %%C in (milvus minio redis postgres) do call :print_docker_status %%C
echo.
echo Setup complete.
echo dev.bat start
echo dev.bat status
echo dev.bat logs api --follow
exit /b 0
:start
set "TARGET=all"
set "MODE=%FRONTEND_MODE%"
set "FOREGROUND=0"
if /I "%~2"=="all" set "TARGET=all"
if /I "%~2"=="api" set "TARGET=api"
if /I "%~2"=="frontend" set "TARGET=frontend"
call :parse_start_options %* || exit /b 1
if /I "%TARGET%"=="all" (
if "%FOREGROUND%"=="1" (
echo start all does not support --foreground.
exit /b 1
)
call :start_api_background || exit /b 1
call :start_frontend "%MODE%" || exit /b 1
exit /b 0
)
if /I "%TARGET%"=="api" (
if "%FOREGROUND%"=="1" (
call :start_api_foreground
exit /b %errorlevel%
)
call :start_api_background
exit /b %errorlevel%
)
if /I "%TARGET%"=="frontend" (
call :start_frontend "%MODE%"
exit /b %errorlevel%
)
echo Invalid start target.
exit /b 1
:parse_start_options
set "MODE=%FRONTEND_MODE%"
set "FOREGROUND=0"
:parse_start_options_loop
if "%~1"=="" exit /b 0
if /I "%~1"=="start" (
shift
goto parse_start_options_loop
)
if /I "%~1"=="all" (
shift
goto parse_start_options_loop
)
if /I "%~1"=="api" (
shift
goto parse_start_options_loop
)
if /I "%~1"=="frontend" (
shift
goto parse_start_options_loop
)
if /I "%~1"=="--foreground" (
set "FOREGROUND=1"
shift
goto parse_start_options_loop
)
if /I "%~1"=="--mode" (
if "%~2"=="" (
echo --mode requires dev or static.
exit /b 1
)
set "MODE=%~2"
call :validate_mode "%MODE%" || exit /b 1
shift
shift
goto parse_start_options_loop
)
echo Unknown argument: %~1
exit /b 1
:stop
set "TARGET=all"
if /I "%~2"=="api" set "TARGET=api"
if /I "%~2"=="frontend" set "TARGET=frontend"
if /I "%TARGET%"=="all" (
call :stop_frontend
call :stop_api
exit /b 0
)
if /I "%TARGET%"=="api" (
call :stop_api
exit /b 0
)
if /I "%TARGET%"=="frontend" (
call :stop_frontend
exit /b 0
)
echo Invalid stop target.
exit /b 1
:restart
set "TARGET=all"
set "MODE=%FRONTEND_MODE%"
if /I "%~2"=="api" set "TARGET=api"
if /I "%~2"=="frontend" set "TARGET=frontend"
call :parse_restart_options %* || exit /b 1
if /I "%TARGET%"=="all" (
call :stop_frontend
call :stop_api
call :start_api_background || exit /b 1
call :start_frontend "%MODE%" || exit /b 1
exit /b 0
)
if /I "%TARGET%"=="api" (
call :stop_api
call :start_api_background
exit /b %errorlevel%
)
if /I "%TARGET%"=="frontend" (
call :stop_frontend
call :start_frontend "%MODE%"
exit /b %errorlevel%
)
echo Invalid restart target.
exit /b 1
:parse_restart_options
set "MODE=%FRONTEND_MODE%"
:parse_restart_options_loop
if "%~1"=="" exit /b 0
if /I "%~1"=="restart" (
shift
goto parse_restart_options_loop
)
if /I "%~1"=="all" (
shift
goto parse_restart_options_loop
)
if /I "%~1"=="api" (
shift
goto parse_restart_options_loop
)
if /I "%~1"=="frontend" (
shift
goto parse_restart_options_loop
)
if /I "%~1"=="--mode" (
if "%~2"=="" (
echo --mode requires dev or static.
exit /b 1
)
set "MODE=%~2"
call :validate_mode "%MODE%" || exit /b 1
shift
shift
goto parse_restart_options_loop
)
echo Unknown argument: %~1
exit /b 1
:status
if not exist "%LOG_DIR%" mkdir "%LOG_DIR%"
echo.
echo ========================================
echo AI+合规智能中枢 - 服务状态
echo ========================================
echo.
echo API service:
set "API_PID="
set "API_RUNNING=0"
set "API_LISTENER="
set "API_DISPLAY_PID="
if exist "%API_PID_FILE%" set /p API_PID=<"%API_PID_FILE%"
if defined API_PID (
call :pid_exists !API_PID!
if errorlevel 1 (
del /q "%API_PID_FILE%" >nul 2>nul
set "API_PID="
) else (
set "API_RUNNING=1"
set "API_DISPLAY_PID=!API_PID!"
)
)
if "%API_RUNNING%"=="1" goto api_running
call :get_listener_pid %API_PORT% API_LISTENER
if defined API_LISTENER goto api_listener
echo Status: stopped
goto api_done
:api_running
echo Status: running
if defined API_DISPLAY_PID echo PID: !API_DISPLAY_PID!
call :check_api_health
if errorlevel 1 (
echo Health: failed
) else (
echo Health: ok
)
goto api_done
:api_listener
echo Status: running (no PID file)
echo PID: !API_LISTENER!
call :check_api_health
if errorlevel 1 (
echo Health: failed
) else (
echo Health: ok
)
:api_done
echo URL: http://localhost:%API_PORT%
echo Docs: http://localhost:%API_PORT%/docs
echo.
echo Frontend service:
set "FRONTEND_PID="
set "FRONTEND_RUNNING=0"
set "FRONTEND_LISTENER="
set "FRONTEND_DISPLAY_PID="
if exist "%FRONTEND_PID_FILE%" set /p FRONTEND_PID=<"%FRONTEND_PID_FILE%"
if defined FRONTEND_PID (
call :pid_exists !FRONTEND_PID!
if errorlevel 1 (
del /q "%FRONTEND_PID_FILE%" >nul 2>nul
set "FRONTEND_PID="
) else (
set "FRONTEND_RUNNING=1"
set "FRONTEND_DISPLAY_PID=!FRONTEND_PID!"
)
)
if "%FRONTEND_RUNNING%"=="1" goto frontend_running
call :get_listener_pid %FRONTEND_PORT% FRONTEND_LISTENER
if defined FRONTEND_LISTENER goto frontend_listener
echo Status: stopped
goto frontend_done
:frontend_running
echo Status: running
if defined FRONTEND_DISPLAY_PID echo PID: !FRONTEND_DISPLAY_PID!
goto frontend_done
:frontend_listener
echo Status: running (no PID file)
echo PID: !FRONTEND_LISTENER!
:frontend_done
echo Mode: %FRONTEND_MODE%
echo URL: http://localhost:%FRONTEND_PORT%
echo.
echo Docker services:
where docker >nul 2>nul || (
echo Docker not installed.
exit /b 0
)
for %%C in (milvus minio redis postgres) do call :print_docker_status %%C
exit /b 0
:logs
if "%~2"=="" (
echo Specify api or frontend.
exit /b 1
)
if /I "%~2"=="api" (
set "LOG_FILE=%API_LOG_FILE%"
)
if /I "%~2"=="frontend" (
set "LOG_FILE=%FRONTEND_LOG_FILE%"
)
if not defined LOG_FILE (
echo Unknown log target: %~2
exit /b 1
)
if not exist "%LOG_FILE%" (
echo Log file not found: %LOG_FILE%
exit /b 1
)
if /I "%~3"=="--follow" (
pwsh -NoProfile -Command "Get-Content -LiteralPath '%LOG_FILE%' -Wait"
) else (
pwsh -NoProfile -Command "Get-Content -LiteralPath '%LOG_FILE%' -Tail 50"
)
exit /b %errorlevel%
:start_api_background
if not exist "%LOG_DIR%" mkdir "%LOG_DIR%"
if not exist "%VENV_PYTHON%" (
echo Virtual environment not found. Run dev.bat setup first.
exit /b 1
)
set "EXISTING_PID="
if exist "%API_PID_FILE%" set /p EXISTING_PID=<"%API_PID_FILE%"
if defined EXISTING_PID (
call :pid_exists %EXISTING_PID%
if not errorlevel 1 (
echo API is already running. PID: %EXISTING_PID%
exit /b 0
) else del /q "%API_PID_FILE%" >nul 2>nul
)
for /f %%P in ('pwsh -NoProfile -Command "$p = Start-Process -FilePath 'pwsh' -ArgumentList '-NoProfile','-Command',('Set-Location ''%CD%''; $env:PYTHONPATH=''backend''; & ''.\%VENV_PYTHON%'' -m uvicorn app.main:app --host ''%API_HOST%'' --port ''%API_PORT%'' *^> ''%API_LOG_FILE%''') -WindowStyle Hidden -PassThru; $p.Id"') do set "API_PID=%%P"
if not defined API_PID (
echo Failed to start API.
exit /b 1
)
> "%API_PID_FILE%" echo %API_PID%
timeout /t 3 /nobreak >nul
call :pid_exists %API_PID%
if errorlevel 1 (
del /q "%API_PID_FILE%" >nul 2>nul
echo API failed to start. Check logs\api.log
exit /b 1
)
echo API started. PID: %API_PID%
echo URL: http://localhost:%API_PORT%
echo Docs: http://localhost:%API_PORT%/docs
echo Log: logs\api.log
exit /b 0
:start_api_foreground
if not exist "%VENV_PYTHON%" (
echo Virtual environment not found. Run dev.bat setup first.
exit /b 1
)
set "PYTHONPATH=backend;%PYTHONPATH%"
echo API running in foreground with reload enabled.
echo URL: http://localhost:%API_PORT%
echo Docs: http://localhost:%API_PORT%/docs
"%VENV_PYTHON%" -m uvicorn app.main:app --host "%API_HOST%" --port "%API_PORT%" --reload
exit /b %errorlevel%
:start_frontend
set "MODE=%~1"
if "%MODE%"=="" set "MODE=%FRONTEND_MODE%"
if not exist "%LOG_DIR%" mkdir "%LOG_DIR%"
where npm >nul 2>nul || (
echo npm was not found. Install Node.js 20+ first.
exit /b 1
)
if not exist "frontend\node_modules\vite" (
echo Frontend dependencies are missing. Running npm install...
pushd frontend >nul
call npm install || (
popd >nul
exit /b 1
)
popd >nul
)
set "EXISTING_PID="
if exist "%FRONTEND_PID_FILE%" set /p EXISTING_PID=<"%FRONTEND_PID_FILE%"
if defined EXISTING_PID (
call :pid_exists %EXISTING_PID%
if not errorlevel 1 (
echo Frontend is already running. PID: %EXISTING_PID%
exit /b 0
) else del /q "%FRONTEND_PID_FILE%" >nul 2>nul
)
if /I "%MODE%"=="static" (
pushd frontend >nul
call npm run build || (
popd >nul
exit /b 1
)
popd >nul
call :resolve_python_bootstrap || exit /b 1
for /f %%P in ('pwsh -NoProfile -Command "$p = Start-Process -FilePath 'pwsh' -ArgumentList '-NoProfile','-Command',('Set-Location ''%CD%''; & %PYTHON_BOOTSTRAP% -m http.server %FRONTEND_PORT% --bind 0.0.0.0 --directory frontend/dist *^> ''%FRONTEND_LOG_FILE%''') -WindowStyle Hidden -PassThru; $p.Id"') do set "FRONTEND_PID=%%P"
) else (
for /f %%P in ('pwsh -NoProfile -Command "$p = Start-Process -FilePath 'pwsh' -ArgumentList '-NoProfile','-Command',('Set-Location ''%CD%''; & npm --prefix frontend run dev -- --host 0.0.0.0 --port %FRONTEND_PORT% *^> ''%FRONTEND_LOG_FILE%''') -WindowStyle Hidden -PassThru; $p.Id"') do set "FRONTEND_PID=%%P"
)
if not defined FRONTEND_PID (
echo Failed to start frontend.
exit /b 1
)
> "%FRONTEND_PID_FILE%" echo %FRONTEND_PID%
timeout /t 4 /nobreak >nul
call :pid_exists %FRONTEND_PID%
if errorlevel 1 (
del /q "%FRONTEND_PID_FILE%" >nul 2>nul
echo Frontend failed to start. Check logs\frontend.log
exit /b 1
)
echo Frontend started. PID: %FRONTEND_PID%
echo URL: http://localhost:%FRONTEND_PORT%
echo Mode: %MODE%
echo Log: logs\frontend.log
exit /b 0
:stop_api
set "API_PID="
if exist "%API_PID_FILE%" set /p API_PID=<"%API_PID_FILE%"
if defined API_PID (
call :stop_pid %API_PID%
del /q "%API_PID_FILE%" >nul 2>nul
echo API stopped.
exit /b 0
)
call :get_listener_pid %API_PORT% API_PORT_PID
if defined API_PORT_PID (
call :stop_pid %API_PORT_PID%
echo Stopped process listening on API port %API_PORT%.
exit /b 0
)
echo API is not running.
exit /b 0
:stop_frontend
set "FRONTEND_PID="
if exist "%FRONTEND_PID_FILE%" set /p FRONTEND_PID=<"%FRONTEND_PID_FILE%"
if defined FRONTEND_PID (
call :stop_pid %FRONTEND_PID%
del /q "%FRONTEND_PID_FILE%" >nul 2>nul
echo Frontend stopped.
exit /b 0
)
call :get_listener_pid %FRONTEND_PORT% FRONTEND_PORT_PID
if defined FRONTEND_PORT_PID (
call :stop_pid %FRONTEND_PORT_PID%
echo Stopped process listening on frontend port %FRONTEND_PORT%.
exit /b 0
)
echo Frontend is not running.
exit /b 0
:validate_mode
if /I "%~1"=="dev" exit /b 0
if /I "%~1"=="static" exit /b 0
echo Invalid frontend mode: %~1
exit /b 1
:resolve_python_bootstrap
where python >nul 2>nul && (
set "PYTHON_BOOTSTRAP=python"
exit /b 0
)
where py >nul 2>nul && (
set "PYTHON_BOOTSTRAP=py -3"
exit /b 0
)
echo Python was not found.
exit /b 1
:load_env
for %%K in (API_HOST API_PORT FRONTEND_PORT FRONTEND_MODE) do call :read_env %%K .env
for %%K in (API_HOST API_PORT FRONTEND_PORT FRONTEND_MODE) do call :read_env %%K .env.development
exit /b 0
:read_env
if "%~2"=="" exit /b 0
if not exist "%~2" exit /b 0
for /f "usebackq tokens=1,* delims==" %%A in (`findstr /r /b /c:"%~1=" "%~2" 2^>nul`) do set "%~1=%%B"
exit /b 0
:pid_exists
pwsh -NoProfile -Command "exit([int](-not [bool](Get-Process -Id %~1 -ErrorAction SilentlyContinue)))"
exit /b %errorlevel%
:stop_pid
pwsh -NoProfile -Command "$p = Get-Process -Id %~1 -ErrorAction SilentlyContinue; if ($p) { Stop-Process -Id %~1 -Force }"
exit /b 0
:get_listener_pid
set "%~2="
for /f %%P in ('pwsh -NoProfile -Command "(Get-NetTCPConnection -LocalPort %~1 -State Listen -ErrorAction SilentlyContinue ^| Select-Object -ExpandProperty OwningProcess -Unique ^| Select-Object -First 1)"') do set "%~2=%%P"
exit /b 0
:check_api_health
pwsh -NoProfile -Command "try { $r = Invoke-WebRequest -Uri 'http://localhost:%API_PORT%/health' -TimeoutSec 3 -UseBasicParsing; exit([int](-not ($r.Content -match 'healthy'))) } catch { exit 1 }"
exit /b %errorlevel%
:print_docker_status
docker ps --format "{{.Names}}" | findstr /x /c:"%~1" >nul && (
echo %~1: running
exit /b 0
)
docker ps -a --format "{{.Names}}" | findstr /x /c:"%~1" >nul && (
echo %~1: stopped
exit /b 0
)
echo %~1: not created
exit /b 0