#!/bin/bash # 暖记开发环境启动脚本 — 自动清理旧进程 + 启动后端和前端 # # 用法: # ./scripts/dev.sh # 启动全部 (后端+管理端+学生端) # ./scripts/dev.sh backend # 只启动后端 # ./scripts/dev.sh admin # 只启动管理端前端 (React, port 5174) # ./scripts/dev.sh app # 只启动学生端 Flutter (port 8080) # ./scripts/dev.sh stop # 停止所有服务 set -e # ===== 配置 ===== BACKEND_PORT=3000 ADMIN_PORT=5174 # 管理端前端 (React + Ant Design) APP_PORT=8080 # 学生端前端 (Flutter Web) PG_HOST="localhost" PG_PORT=5432 PG_USER="postgres" PG_PASS="123123" PG_DB="nuanji" # ===== 颜色 ===== RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' log_info() { echo -e "${BLUE}[INFO]${NC} $1"; } log_ok() { echo -e "${GREEN}[OK]${NC} $1"; } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } log_err() { echo -e "${RED}[ERROR]${NC} $1"; } # ===== 清理端口占用的进程 ===== kill_port() { local port=$1 local name=$2 local pids=$(netstat -ano 2>/dev/null | grep ":${port}.*LISTENING" | awk '{print $5}' | sort -u) if [ -n "$pids" ]; then for pid in $pids; do if [ "$pid" != "0" ]; then taskkill //F //PID "$pid" 2>/dev/null && \ log_ok "已停止 ${name} (PID: ${pid}, 端口: ${port})" || \ log_warn "无法停止 ${name} (PID: ${pid})" fi done else log_info "${name} 端口 ${port} 空闲" fi } stop_all() { log_info "停止所有暖记服务..." kill_port $BACKEND_PORT "后端" kill_port $ADMIN_PORT "管理端前端" kill_port $APP_PORT "学生端前端" taskkill //F //IM erp-server.exe 2>/dev/null && log_ok "已停止 erp-server.exe" || true log_ok "所有服务已停止" } # ===== 检查依赖 ===== check_deps() { log_info "检查依赖..." # PostgreSQL if PGPASSWORD=$PG_PASS /d/postgreSQL/bin/psql.exe -U $PG_USER -h $PG_HOST -p $PG_PORT \ -d $PG_DB -c "SELECT 1" > /dev/null 2>&1; then log_ok "PostgreSQL 已连接 (${PG_DB}@${PG_HOST}:${PG_PORT})" else log_err "无法连接 PostgreSQL (${PG_DB}@${PG_HOST}:${PG_PORT})" log_err "请确保 PostgreSQL 已启动且数据库 ${PG_DB} 存在" exit 1 fi # Redis if redis-cli ping > /dev/null 2>&1; then log_ok "Redis 已连接" else log_err "无法连接 Redis (localhost:6379)" exit 1 fi # Flutter if D:/flutter/bin/flutter.bat --version > /dev/null 2>&1; then log_ok "Flutter SDK 可用" else log_err "Flutter SDK 不可用" exit 1 fi } # ===== 启动后端 ===== start_backend() { log_info "清理旧后端进程..." kill_port $BACKEND_PORT "后端" taskkill //F //IM erp-server.exe 2>/dev/null || true sleep 1 log_info "编译并启动后端 (diary feature)..." cd /g/nj ERP__DATABASE__URL="postgres://${PG_USER}:${PG_PASS}@${PG_HOST}:${PG_PORT}/${PG_DB}" \ ERP__REDIS__URL="redis://localhost:6379" \ ERP__JWT__SECRET="nuanji-dev-jwt-secret-2024-warm-notes-hmac-key-32b" \ ERP__AUTH__SUPER_ADMIN_PASSWORD="admin123" \ ERP__WECHAT__APPID="wx_dev_placeholder" \ ERP__WECHAT__SECRET="wx_dev_secret_placeholder" \ ERP__WECHAT__DEV_MODE="true" \ ERP__CRYPTO__KEK="0000000000000000000000000000000000000000000000000000000000000000" \ cargo run -p erp-server --features diary & # 等待后端就绪 log_info "等待后端就绪..." for i in $(seq 1 30); do if curl -s "http://localhost:${BACKEND_PORT}/api/v1/health" > /dev/null 2>&1; then log_ok "后端已就绪 → http://localhost:${BACKEND_PORT}" return 0 fi sleep 2 done log_err "后端启动超时" return 1 } # ===== 启动管理端前端 (React + Ant Design) ===== start_admin() { log_info "清理旧管理端进程..." kill_port $ADMIN_PORT "管理端前端" sleep 1 log_info "启动管理端前端 (React + Vite)..." cd /g/nj/apps/web pnpm dev & log_info "等待管理端就绪..." for i in $(seq 1 20); do if curl -s -o /dev/null "http://localhost:${ADMIN_PORT}" 2>/dev/null; then log_ok "管理端已就绪 → http://localhost:${ADMIN_PORT}" return 0 fi sleep 2 done log_err "管理端启动超时" return 1 } # ===== 启动学生端 Flutter Web ===== start_app() { log_info "清理旧学生端进程..." kill_port $APP_PORT "学生端前端" sleep 1 log_info "编译并启动 Flutter Web..." cd /g/nj/app D:/flutter/bin/flutter.bat run -d chrome --web-port=$APP_PORT & log_info "等待学生端就绪..." for i in $(seq 1 30); do if curl -s -o /dev/null "http://localhost:${APP_PORT}" 2>/dev/null; then log_ok "学生端已就绪 → http://localhost:${APP_PORT}" return 0 fi sleep 3 done log_err "学生端启动超时" return 1 } # ===== 主流程 ===== case "${1:-all}" in stop) stop_all ;; backend) check_deps start_backend ;; admin) check_deps start_admin ;; app) check_deps start_app ;; all) check_deps start_backend start_admin start_app log_ok "=== 暖记开发环境已启动 ===" log_ok "后端 API: http://localhost:${BACKEND_PORT}" log_ok "管理端: http://localhost:${ADMIN_PORT} (admin/admin123)" log_ok "学生端: http://localhost:${APP_PORT}" ;; *) echo "用法: $0 [all|backend|admin|app|stop]" exit 1 ;; esac