feat: Add build scripts and runtime config support

Backend:
- Add setup-backend.sh/bat for one-click backend setup
- Fix test_auth.py mock settings (JWT_EXPIRE_HOURS)
- Fix test_excel_export.py TEMPLATE_DIR reference

Frontend:
- Add config.json for runtime API URL configuration
- Add init.js and settings.js for config loading
- Update main.js to load config from external file
- Update api.js to use dynamic API_BASE_URL
- Update all pages to initialize config before API calls
- Update package.json with extraResources for config

Build:
- Add build-client.sh/bat for packaging Electron + Sidecar
- Add build-all.ps1 PowerShell script with -ApiUrl parameter
- Add GitHub Actions workflow for Windows builds
- Add scripts/README.md documentation

This allows IT to configure backend URL without rebuilding.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
egg
2025-12-16 20:03:16 +08:00
parent 01aee1fd0d
commit 7d4fc69071
20 changed files with 2454 additions and 32 deletions

324
scripts/build-client.bat Normal file
View File

@@ -0,0 +1,324 @@
@echo off
REM Meeting Assistant Client - Windows 打包腳本
REM 將 Electron 應用與 Python Sidecar 打包成免安裝 exe
setlocal enabledelayedexpansion
REM 顏色設定 (Windows 10+)
set "GREEN=[92m"
set "YELLOW=[93m"
set "RED=[91m"
set "BLUE=[94m"
set "CYAN=[96m"
set "NC=[0m"
REM 專案路徑
set "SCRIPT_DIR=%~dp0"
set "PROJECT_DIR=%SCRIPT_DIR%.."
set "CLIENT_DIR=%PROJECT_DIR%\client"
set "SIDECAR_DIR=%PROJECT_DIR%\sidecar"
set "BUILD_DIR=%PROJECT_DIR%\build"
REM 預設配置
set "SKIP_SIDECAR=false"
set "CLEAN_BUILD=false"
REM 解析參數
set "COMMAND=help"
:parse_args
if "%~1"=="" goto :main
if /i "%~1"=="build" (set "COMMAND=build" & shift & goto :parse_args)
if /i "%~1"=="sidecar" (set "COMMAND=sidecar" & shift & goto :parse_args)
if /i "%~1"=="electron" (set "COMMAND=electron" & shift & goto :parse_args)
if /i "%~1"=="clean" (set "COMMAND=clean" & shift & goto :parse_args)
if /i "%~1"=="help" (set "COMMAND=help" & shift & goto :parse_args)
if /i "%~1"=="--skip-sidecar" (set "SKIP_SIDECAR=true" & shift & goto :parse_args)
if /i "%~1"=="--clean" (set "CLEAN_BUILD=true" & shift & goto :parse_args)
echo %RED%[ERROR]%NC% 未知參數: %~1
goto :show_help
:main
if "%COMMAND%"=="help" goto :show_help
if "%COMMAND%"=="build" goto :do_build
if "%COMMAND%"=="sidecar" goto :do_sidecar
if "%COMMAND%"=="electron" goto :do_electron
if "%COMMAND%"=="clean" goto :do_clean
goto :show_help
:show_banner
echo.
echo %CYAN%==========================================
echo Meeting Assistant Client Builder
echo 打包 Electron + Sidecar 為免安裝執行檔
echo ==========================================%NC%
echo.
goto :eof
:check_environment
echo %BLUE%[STEP]%NC% 檢查建置環境...
REM 檢查 Node.js
where node >nul 2>&1
if %errorlevel% equ 0 (
for /f "tokens=*" %%i in ('node --version') do echo %GREEN%[OK]%NC% Node.js: %%i
) else (
echo %RED%[ERROR]%NC% Node.js 未安裝
exit /b 1
)
REM 檢查 npm
where npm >nul 2>&1
if %errorlevel% equ 0 (
for /f "tokens=*" %%i in ('npm --version') do echo %GREEN%[OK]%NC% npm: %%i
) else (
echo %RED%[ERROR]%NC% npm 未安裝
exit /b 1
)
REM 檢查 Python
where python >nul 2>&1
if %errorlevel% equ 0 (
for /f "tokens=*" %%i in ('python -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"') do set "PY_VERSION=%%i"
for /f "tokens=*" %%i in ('python -c "import sys; print(sys.version_info.major)"') do set "PY_MAJOR=%%i"
for /f "tokens=*" %%i in ('python -c "import sys; print(sys.version_info.minor)"') do set "PY_MINOR=%%i"
if !PY_MAJOR! geq 3 if !PY_MINOR! geq 10 (
set "PYTHON_CMD=python"
echo %GREEN%[OK]%NC% Python !PY_VERSION!
goto :eof
)
)
echo %RED%[ERROR]%NC% 需要 Python 3.10 或更高版本
exit /b 1
:do_clean
echo %BLUE%[STEP]%NC% 清理建置目錄...
if exist "%BUILD_DIR%" rmdir /s /q "%BUILD_DIR%"
if exist "%CLIENT_DIR%\dist" rmdir /s /q "%CLIENT_DIR%\dist"
if exist "%SIDECAR_DIR%\dist" rmdir /s /q "%SIDECAR_DIR%\dist"
if exist "%SIDECAR_DIR%\build" rmdir /s /q "%SIDECAR_DIR%\build"
if exist "%SIDECAR_DIR%\*.spec" del /q "%SIDECAR_DIR%\*.spec"
echo %GREEN%[OK]%NC% 建置目錄已清理
goto :eof
:setup_sidecar_venv
echo %BLUE%[STEP]%NC% 設置 Sidecar 建置環境...
cd /d "%SIDECAR_DIR%"
if not exist "venv" (
echo %BLUE%[INFO]%NC% 創建虛擬環境...
%PYTHON_CMD% -m venv venv
)
echo %BLUE%[INFO]%NC% 安裝 Sidecar 依賴...
call venv\Scripts\activate.bat
pip install --upgrade pip -q
pip install -r requirements.txt -q
echo %BLUE%[INFO]%NC% 安裝 PyInstaller...
pip install pyinstaller -q
echo %GREEN%[OK]%NC% Sidecar 建置環境就緒
goto :eof
:build_sidecar
echo %BLUE%[STEP]%NC% 打包 Sidecar (Python → 獨立執行檔)...
cd /d "%SIDECAR_DIR%"
call venv\Scripts\activate.bat
if not exist "dist" mkdir dist
echo %BLUE%[INFO]%NC% 執行 PyInstaller...
echo %BLUE%[INFO]%NC% 這可能需要幾分鐘...
pyinstaller ^
--onedir ^
--name transcriber ^
--distpath dist ^
--workpath build ^
--specpath . ^
--noconfirm ^
--clean ^
--log-level WARN ^
--console ^
--hidden-import=faster_whisper ^
--hidden-import=ctranslate2 ^
--hidden-import=huggingface_hub ^
--hidden-import=tokenizers ^
--hidden-import=onnxruntime ^
--hidden-import=opencc ^
--hidden-import=pydub ^
--hidden-import=numpy ^
--hidden-import=av ^
--collect-data=onnxruntime ^
--collect-data=faster_whisper ^
transcriber.py
if exist "dist\transcriber" (
echo %GREEN%[OK]%NC% Sidecar 打包完成: %SIDECAR_DIR%\dist\transcriber
) else (
echo %RED%[ERROR]%NC% Sidecar 打包失敗
exit /b 1
)
goto :eof
:setup_client
echo %BLUE%[STEP]%NC% 設置前端建置環境...
cd /d "%CLIENT_DIR%"
if not exist "node_modules" (
echo %BLUE%[INFO]%NC% 安裝前端依賴...
call npm install
) else (
echo %BLUE%[INFO]%NC% 前端依賴已安裝
)
if not exist ".env" (
if exist ".env.example" (
copy .env.example .env >nul
echo %YELLOW%[WARN]%NC% 已創建 .env 檔案,請確認設定
)
)
echo %GREEN%[OK]%NC% 前端建置環境就緒
goto :eof
:build_electron
echo %BLUE%[STEP]%NC% 打包 Electron 應用...
cd /d "%CLIENT_DIR%"
echo %BLUE%[INFO]%NC% 目標平台: Windows (Portable)
echo %BLUE%[INFO]%NC% 執行 electron-builder...
call npm run build -- --win
if exist "dist" (
echo %GREEN%[OK]%NC% Electron 打包完成
echo %BLUE%[INFO]%NC% 輸出目錄: %CLIENT_DIR%\dist
) else (
echo %RED%[ERROR]%NC% Electron 打包失敗
exit /b 1
)
goto :eof
:finalize_build
echo %BLUE%[STEP]%NC% 整合建置輸出...
if not exist "%BUILD_DIR%" mkdir "%BUILD_DIR%"
REM 複製 Electron 輸出
if exist "%CLIENT_DIR%\dist" (
xcopy /s /e /y "%CLIENT_DIR%\dist\*" "%BUILD_DIR%\" >nul 2>&1
)
echo.
echo %CYAN%==========================================
echo 建置完成
echo ==========================================%NC%
echo.
echo 輸出目錄: %BUILD_DIR%
echo.
dir /b "%BUILD_DIR%"
echo.
echo %GREEN%[OK]%NC% 打包完成!
echo.
echo Windows 使用說明:
echo 1. 找到 build\ 中的 .exe 檔案
echo 2. 直接執行即可,無需安裝
echo.
goto :eof
:do_build
call :show_banner
call :check_environment
if errorlevel 1 exit /b 1
if "%CLEAN_BUILD%"=="true" call :do_clean
if "%SKIP_SIDECAR%"=="false" (
call :setup_sidecar_venv
call :build_sidecar
)
call :setup_client
call :build_electron
call :finalize_build
goto :eof
:do_sidecar
call :show_banner
call :check_environment
if errorlevel 1 exit /b 1
if "%CLEAN_BUILD%"=="true" (
if exist "%SIDECAR_DIR%\dist" rmdir /s /q "%SIDECAR_DIR%\dist"
if exist "%SIDECAR_DIR%\build" rmdir /s /q "%SIDECAR_DIR%\build"
)
call :setup_sidecar_venv
call :build_sidecar
goto :eof
:do_electron
call :show_banner
call :check_environment
if errorlevel 1 exit /b 1
if not exist "%SIDECAR_DIR%\dist\transcriber" (
if "%SKIP_SIDECAR%"=="false" (
echo %YELLOW%[WARN]%NC% Sidecar 尚未打包
echo %BLUE%[INFO]%NC% 請先執行: %~nx0 sidecar
echo %BLUE%[INFO]%NC% 或使用 --skip-sidecar 跳過
exit /b 1
)
)
if "%CLEAN_BUILD%"=="true" (
if exist "%CLIENT_DIR%\dist" rmdir /s /q "%CLIENT_DIR%\dist"
)
call :setup_client
call :build_electron
call :finalize_build
goto :eof
:show_help
echo.
echo Meeting Assistant Client - Windows 打包腳本
echo.
echo 用法: %~nx0 [命令] [選項]
echo.
echo 命令:
echo build 完整建置 (Sidecar + Electron)
echo sidecar 僅打包 Sidecar
echo electron 僅打包 Electron (需先打包 Sidecar)
echo clean 清理建置目錄
echo help 顯示此幫助訊息
echo.
echo 選項:
echo --skip-sidecar 跳過 Sidecar 打包
echo --clean 建置前先清理
echo.
echo 範例:
echo %~nx0 build 完整建置
echo %~nx0 sidecar 僅打包 Sidecar
echo %~nx0 electron --skip-sidecar 僅打包 Electron
echo.
echo 注意:
echo - 首次打包 Sidecar 需下載 Whisper 模型,可能需要較長時間
echo - 確保有足夠的磁碟空間 (建議 5GB+)
echo.
goto :eof
:end
endlocal