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>
325 lines
8.0 KiB
Batchfile
325 lines
8.0 KiB
Batchfile
@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
|