Files
Meeting_Assistant/scripts/build-all.ps1
egg 7d4fc69071 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>
2025-12-16 20:03:16 +08:00

305 lines
8.3 KiB
PowerShell
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.

#Requires -Version 5.1
<#
.SYNOPSIS
Meeting Assistant - Windows 一鍵打包腳本
.DESCRIPTION
在 Windows 環境下一鍵打包 Sidecar + Electron 成免安裝 exe
.EXAMPLE
.\scripts\build-all.ps1
.\scripts\build-all.ps1 -ApiUrl "http://192.168.1.100:8000/api"
.\scripts\build-all.ps1 -SkipSidecar
.\scripts\build-all.ps1 -Clean
#>
param(
[string]$ApiUrl,
[switch]$SkipSidecar,
[switch]$Clean,
[switch]$Help
)
$ErrorActionPreference = "Stop"
# 顏色輸出函數
function Write-Step { param($msg) Write-Host "[STEP] $msg" -ForegroundColor Cyan }
function Write-OK { param($msg) Write-Host "[OK] $msg" -ForegroundColor Green }
function Write-Warn { param($msg) Write-Host "[WARN] $msg" -ForegroundColor Yellow }
function Write-Err { param($msg) Write-Host "[ERROR] $msg" -ForegroundColor Red }
# 路徑設定
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$ProjectDir = Split-Path -Parent $ScriptDir
$SidecarDir = Join-Path $ProjectDir "sidecar"
$ClientDir = Join-Path $ProjectDir "client"
$BuildDir = Join-Path $ProjectDir "build"
function Show-Banner {
Write-Host ""
Write-Host "==========================================" -ForegroundColor Cyan
Write-Host " Meeting Assistant - Windows Builder" -ForegroundColor Cyan
Write-Host " 一鍵打包 Electron + Sidecar" -ForegroundColor Cyan
Write-Host "==========================================" -ForegroundColor Cyan
Write-Host ""
}
function Show-Help {
Write-Host @"
Meeting Assistant - Windows
: .\build-all.ps1 []
:
-ApiUrl URL API URL (: http://localhost:8000/api)
-SkipSidecar Sidecar
-Clean
-Help
:
.\build-all.ps1 # (使 localhost)
.\build-all.ps1 -ApiUrl "http://192.168.1.100:8000/api" # URL
.\build-all.ps1 -ApiUrl "https://api.example.com/api" # 使
.\build-all.ps1 -Clean #
.\build-all.ps1 -SkipSidecar # Electron
"@
}
function Update-Config {
param([string]$NewApiUrl)
Write-Step "更新設定檔..."
$configPath = Join-Path $ClientDir "config.json"
if (Test-Path $configPath) {
$config = Get-Content $configPath -Raw | ConvertFrom-Json
if ($NewApiUrl) {
$config.apiBaseUrl = $NewApiUrl
Write-Host " API URL: $NewApiUrl" -ForegroundColor Gray
}
$config | ConvertTo-Json -Depth 10 | Set-Content $configPath -Encoding UTF8
Write-OK "設定檔已更新"
} else {
Write-Warn "找不到 config.json使用預設設定"
}
}
function Test-Prerequisites {
Write-Step "檢查建置環境..."
# 檢查 Python
try {
$pyVersion = python --version 2>&1
Write-OK "Python: $pyVersion"
} catch {
Write-Err "Python 未安裝,請安裝 Python 3.10+"
exit 1
}
# 檢查 Node.js
try {
$nodeVersion = node --version 2>&1
Write-OK "Node.js: $nodeVersion"
} catch {
Write-Err "Node.js 未安裝,請安裝 Node.js 18+"
exit 1
}
# 檢查 npm
try {
$npmVersion = npm --version 2>&1
Write-OK "npm: $npmVersion"
} catch {
Write-Err "npm 未安裝"
exit 1
}
}
function Clear-BuildDirs {
Write-Step "清理建置目錄..."
$dirsToClean = @(
$BuildDir,
(Join-Path $ClientDir "dist"),
(Join-Path $SidecarDir "dist"),
(Join-Path $SidecarDir "build")
)
foreach ($dir in $dirsToClean) {
if (Test-Path $dir) {
Remove-Item -Recurse -Force $dir
Write-Host " 已刪除: $dir" -ForegroundColor Gray
}
}
# 刪除 spec 檔案
Get-ChildItem -Path $SidecarDir -Filter "*.spec" | Remove-Item -Force
Write-OK "清理完成"
}
function Build-Sidecar {
Write-Step "打包 Sidecar (Python → exe)..."
Write-Host " 這可能需要 5-10 分鐘..." -ForegroundColor Gray
Push-Location $SidecarDir
try {
# 建立/啟動虛擬環境
if (-not (Test-Path "venv")) {
Write-Host " 建立虛擬環境..." -ForegroundColor Gray
python -m venv venv
}
# 啟動虛擬環境並安裝依賴
& ".\venv\Scripts\Activate.ps1"
Write-Host " 安裝依賴..." -ForegroundColor Gray
pip install --upgrade pip -q
pip install -r requirements.txt -q
pip install pyinstaller -q
# 建立 dist 目錄
if (-not (Test-Path "dist")) {
New-Item -ItemType Directory -Path "dist" | Out-Null
}
Write-Host " 執行 PyInstaller..." -ForegroundColor Gray
# PyInstaller 打包
pyinstaller `
--onedir `
--name transcriber `
--distpath dist `
--workpath build `
--noconfirm `
--clean `
--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 (Test-Path "dist\transcriber\transcriber.exe") {
Write-OK "Sidecar 打包完成"
} else {
Write-Err "Sidecar 打包失敗"
exit 1
}
}
finally {
Pop-Location
}
}
function Build-Electron {
Write-Step "打包 Electron 應用..."
Push-Location $ClientDir
try {
# 檢查 Sidecar 是否存在
$sidecarExe = Join-Path $SidecarDir "dist\transcriber\transcriber.exe"
if (-not (Test-Path $sidecarExe)) {
Write-Err "找不到 Sidecar: $sidecarExe"
Write-Warn "請先執行完整打包或移除 -SkipSidecar 參數"
exit 1
}
# 安裝依賴
if (-not (Test-Path "node_modules")) {
Write-Host " 安裝 npm 依賴..." -ForegroundColor Gray
npm install
}
# 建立 .env 如果不存在
if (-not (Test-Path ".env") -and (Test-Path ".env.example")) {
Copy-Item ".env.example" ".env"
Write-Warn "已建立 .env請確認設定"
}
Write-Host " 執行 electron-builder..." -ForegroundColor Gray
npm run build -- --win
if (Test-Path "dist\*.exe") {
Write-OK "Electron 打包完成"
} else {
Write-Err "Electron 打包失敗"
exit 1
}
}
finally {
Pop-Location
}
}
function Copy-Output {
Write-Step "整合輸出..."
if (-not (Test-Path $BuildDir)) {
New-Item -ItemType Directory -Path $BuildDir | Out-Null
}
# 複製 exe 檔案
$exeFiles = Get-ChildItem -Path (Join-Path $ClientDir "dist") -Filter "*.exe"
foreach ($file in $exeFiles) {
Copy-Item $file.FullName -Destination $BuildDir
Write-Host " 複製: $($file.Name)" -ForegroundColor Gray
}
Write-Host ""
Write-Host "==========================================" -ForegroundColor Cyan
Write-Host " 打包完成!" -ForegroundColor Green
Write-Host "==========================================" -ForegroundColor Cyan
Write-Host ""
Write-Host " 輸出目錄: $BuildDir" -ForegroundColor White
Write-Host ""
# 列出輸出檔案
Get-ChildItem -Path $BuildDir | ForEach-Object {
$size = [math]::Round($_.Length / 1MB, 2)
Write-Host " $($_.Name) ($size MB)" -ForegroundColor Gray
}
Write-Host ""
Write-Host " 使用說明:" -ForegroundColor Yellow
Write-Host " 直接執行 .exe 檔案即可,無需安裝" -ForegroundColor Gray
Write-Host ""
}
# 主程式
if ($Help) {
Show-Help
exit 0
}
Show-Banner
Test-Prerequisites
if ($Clean) {
Clear-BuildDirs
}
# Update config.json if API URL is specified
if ($ApiUrl) {
Update-Config -NewApiUrl $ApiUrl
}
if (-not $SkipSidecar) {
Build-Sidecar
}
Build-Electron
Copy-Output