Files
Meeting_Assistant/scripts/setup-backend.sh
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

394 lines
10 KiB
Bash
Executable File
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.

#!/bin/bash
#
# Meeting Assistant Backend - 一鍵設置與啟動腳本
# 自動安裝依賴、設置環境並啟動後端服務
#
set -e
# 顏色定義
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
# 專案路徑
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
BACKEND_DIR="$PROJECT_DIR/backend"
SIDECAR_DIR="$PROJECT_DIR/sidecar"
# 預設配置
DEFAULT_PORT=8000
DEFAULT_HOST="0.0.0.0"
# 函數:印出訊息
log_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
log_success() {
echo -e "${GREEN}[OK]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
log_step() {
echo -e "${CYAN}[STEP]${NC} $1"
}
# 函數:顯示標題
show_banner() {
echo ""
echo -e "${CYAN}=========================================="
echo " Meeting Assistant Backend Setup"
echo " 一鍵設置與啟動腳本"
echo -e "==========================================${NC}"
echo ""
}
# 函數:檢查 Python 版本
check_python() {
log_step "檢查 Python 環境..."
# 嘗試不同的 Python 命令
local python_cmd=""
for cmd in python3 python; do
if command -v $cmd &> /dev/null; then
local version=$($cmd -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')
local major=$($cmd -c 'import sys; print(sys.version_info.major)')
local minor=$($cmd -c 'import sys; print(sys.version_info.minor)')
if [ "$major" -ge 3 ] && [ "$minor" -ge 10 ]; then
python_cmd=$cmd
log_success "Python $version ($cmd)"
break
fi
fi
done
if [ -z "$python_cmd" ]; then
log_error "需要 Python 3.10 或更高版本"
log_info "請安裝 Python: https://www.python.org/downloads/"
exit 1
fi
echo "$python_cmd"
}
# 函數:設置後端虛擬環境
setup_backend_venv() {
local python_cmd=$1
log_step "設置後端虛擬環境..."
cd "$BACKEND_DIR"
if [ ! -d "venv" ]; then
log_info "創建虛擬環境..."
$python_cmd -m venv venv
log_success "虛擬環境已創建"
else
log_info "虛擬環境已存在"
fi
# 啟動虛擬環境並安裝依賴
log_info "安裝後端依賴..."
if [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "win32" ]] || [[ "$OSTYPE" == "cygwin" ]]; then
# Windows
source venv/Scripts/activate
else
# Linux/Mac
source venv/bin/activate
fi
pip install --upgrade pip -q
pip install -r requirements.txt -q
log_success "後端依賴安裝完成"
}
# 函數:設置 Sidecar 虛擬環境
setup_sidecar_venv() {
local python_cmd=$1
log_step "設置 Sidecar 虛擬環境..."
cd "$SIDECAR_DIR"
if [ ! -d "venv" ]; then
log_info "創建 Sidecar 虛擬環境..."
$python_cmd -m venv venv
log_success "Sidecar 虛擬環境已創建"
else
log_info "Sidecar 虛擬環境已存在"
fi
# 啟動虛擬環境並安裝依賴
log_info "安裝 Sidecar 依賴 (這可能需要幾分鐘)..."
if [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "win32" ]] || [[ "$OSTYPE" == "cygwin" ]]; then
source venv/Scripts/activate
else
source venv/bin/activate
fi
pip install --upgrade pip -q
pip install -r requirements.txt -q
log_success "Sidecar 依賴安裝完成"
}
# 函數:設置環境變數檔案
setup_env_file() {
log_step "檢查環境變數配置..."
cd "$BACKEND_DIR"
if [ ! -f ".env" ]; then
if [ -f ".env.example" ]; then
cp .env.example .env
log_warn "已從 .env.example 創建 .env 檔案"
log_warn "請編輯 $BACKEND_DIR/.env 設置資料庫和 API 密鑰"
else
log_error "找不到 .env.example 檔案"
exit 1
fi
else
log_success "環境變數檔案已存在"
fi
}
# 函數:檢查 port 是否被佔用
check_port() {
local port=$1
if command -v lsof &> /dev/null; then
if lsof -i :$port > /dev/null 2>&1; then
return 0 # port 被佔用
fi
elif command -v netstat &> /dev/null; then
if netstat -tuln | grep -q ":$port "; then
return 0
fi
fi
return 1 # port 可用
}
# 函數:釋放 port
release_port() {
local port=$1
if check_port $port; then
log_warn "Port $port 被佔用,嘗試釋放..."
if command -v lsof &> /dev/null; then
local pid=$(lsof -t -i :$port 2>/dev/null)
if [ -n "$pid" ]; then
kill -9 $pid 2>/dev/null || true
sleep 1
log_success "Port $port 已釋放"
fi
else
log_error "無法釋放 port請手動關閉佔用 $port 的程序"
exit 1
fi
fi
}
# 函數:啟動後端服務
start_backend() {
local host=${1:-$DEFAULT_HOST}
local port=${2:-$DEFAULT_PORT}
local mode=${3:-"foreground"} # foreground 或 background
log_step "啟動後端服務..."
cd "$BACKEND_DIR"
# 載入環境變數
if [ -f ".env" ]; then
export $(grep -v '^#' .env | grep -v '^$' | xargs)
fi
# 使用 .env 中的配置或預設值
host=${BACKEND_HOST:-$host}
port=${BACKEND_PORT:-$port}
# 釋放 port
release_port $port
# 啟動虛擬環境
if [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "win32" ]] || [[ "$OSTYPE" == "cygwin" ]]; then
source venv/Scripts/activate
else
source venv/bin/activate
fi
echo ""
log_success "後端服務準備就緒!"
echo ""
echo -e "${CYAN}=========================================="
echo " 服務資訊"
echo -e "==========================================${NC}"
echo ""
echo " API 地址: http://localhost:$port"
echo " API 文件: http://localhost:$port/docs"
echo " 健康檢查: http://localhost:$port/api/health"
echo ""
echo " 按 Ctrl+C 停止服務"
echo ""
if [ "$mode" = "background" ]; then
nohup uvicorn app.main:app --host $host --port $port --reload > "$PROJECT_DIR/backend.log" 2>&1 &
local pid=$!
echo $pid > "$PROJECT_DIR/.backend_pid"
log_success "後端服務已在背景啟動 (PID: $pid)"
log_info "查看日誌: tail -f $PROJECT_DIR/backend.log"
else
# 前景執行
uvicorn app.main:app --host $host --port $port --reload
fi
}
# 函數:顯示幫助
show_help() {
echo ""
echo "Meeting Assistant Backend - 一鍵設置與啟動腳本"
echo ""
echo "用法: $0 [命令] [選項]"
echo ""
echo "命令:"
echo " setup 僅設置環境 (安裝依賴)"
echo " start 設置並啟動後端服務 (前景執行)"
echo " start-bg 設置並啟動後端服務 (背景執行)"
echo " stop 停止背景執行的後端服務"
echo " help 顯示此幫助訊息"
echo ""
echo "選項:"
echo " --port PORT 服務端口 (預設: $DEFAULT_PORT)"
echo " --host HOST 綁定地址 (預設: $DEFAULT_HOST)"
echo " --no-sidecar 不安裝 Sidecar 依賴"
echo ""
echo "範例:"
echo " $0 start # 設置並啟動服務"
echo " $0 start --port 8080 # 使用自訂端口"
echo " $0 setup # 僅安裝依賴"
echo " $0 start-bg # 背景執行"
echo ""
}
# 函數:停止背景服務
stop_backend() {
log_step "停止後端服務..."
if [ -f "$PROJECT_DIR/.backend_pid" ]; then
local pid=$(cat "$PROJECT_DIR/.backend_pid")
if kill -0 $pid 2>/dev/null; then
kill $pid
rm -f "$PROJECT_DIR/.backend_pid"
log_success "後端服務已停止 (PID: $pid)"
else
rm -f "$PROJECT_DIR/.backend_pid"
log_warn "服務已經停止"
fi
else
# 嘗試通過 port 查找
if command -v lsof &> /dev/null; then
local port=${BACKEND_PORT:-$DEFAULT_PORT}
local pid=$(lsof -t -i :$port 2>/dev/null)
if [ -n "$pid" ]; then
kill $pid 2>/dev/null || true
log_success "已停止 port $port 上的服務"
else
log_warn "沒有找到運行中的後端服務"
fi
fi
fi
}
# 主程式
main() {
local command=${1:-"start"}
local port=$DEFAULT_PORT
local host=$DEFAULT_HOST
local setup_sidecar=true
# 解析參數
shift || true
while [[ $# -gt 0 ]]; do
case $1 in
--port)
port="$2"
shift 2
;;
--host)
host="$2"
shift 2
;;
--no-sidecar)
setup_sidecar=false
shift
;;
*)
log_error "未知參數: $1"
show_help
exit 1
;;
esac
done
case $command in
setup)
show_banner
local python_cmd=$(check_python)
setup_backend_venv "$python_cmd"
if [ "$setup_sidecar" = true ]; then
setup_sidecar_venv "$python_cmd"
fi
setup_env_file
echo ""
log_success "環境設置完成!"
echo ""
log_info "啟動服務: $0 start"
;;
start)
show_banner
local python_cmd=$(check_python)
setup_backend_venv "$python_cmd"
setup_env_file
start_backend "$host" "$port" "foreground"
;;
start-bg)
show_banner
local python_cmd=$(check_python)
setup_backend_venv "$python_cmd"
setup_env_file
start_backend "$host" "$port" "background"
;;
stop)
stop_backend
;;
help|--help|-h)
show_help
;;
*)
log_error "未知命令: $command"
show_help
exit 1
;;
esac
}
# 捕捉中斷信號
trap 'echo ""; log_info "收到中斷信號"; exit 0' INT TERM
# 執行主程式
main "$@"