Files
hfb_sys/scripts/dev.sh
T
ymlandClaude Opus 4.7 6fb5de204c 用户消息系统:消息列表、订单群聊、联系对方入口
- 新增消息列表页和聊天详情页,支持 SSE 实时推送
- 订单详情页新增"联系对方"按钮,一键进入订单群聊
- 导航栏新增"消息"入口
- 修复 mobileHost 路径匹配 bug,避免 /m 前缀误匹配
- 优化 dev.sh:提取 mysql 辅助函数、修复空 PID 处理、条件检查依赖

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-27 09:46:34 +08:00

287 lines
6.4 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.
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
COMPOSE_FILE="${ROOT_DIR}/deploy/docker-compose.dev.yml"
BACKEND_ENV="${ROOT_DIR}/backend/.env"
BACKEND_ENV_EXAMPLE="${ROOT_DIR}/backend/.env.example"
BACKEND_PID=""
FRONTEND_PID=""
CLEANED_UP=0
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[1;34m'
NC='\033[0m'
log() {
printf "${BLUE}[dev]${NC} %s\n" "$*"
}
log_success() {
printf "${GREEN}[dev]${NC} %s\n" "$*"
}
log_warn() {
printf "${YELLOW}[dev]${NC} %s\n" "$*"
}
log_error() {
printf "${RED}[dev]${NC} %s\n" "$*" >&2
}
need_cmd() {
if ! command -v "$1" >/dev/null 2>&1; then
log_error "缺少命令:$1"
exit 1
fi
}
show_help() {
cat << EOF
用法: ./scripts/dev.sh [选项]
选项:
--reset-db 重置数据库(删除并重建)
--seed-only 仅重新加载种子数据
--no-frontend 不启动前端
--no-backend 不启动后端
-h, --help 显示帮助信息
环境变量:
DEV_RESET_DB=1 等同于 --reset-db
示例:
./scripts/dev.sh # 正常启动
./scripts/dev.sh --reset-db # 重置数据库后启动
./scripts/dev.sh --seed-only # 重新加载种子数据
EOF
exit 0
}
# 参数解析
RESET_DB="${DEV_RESET_DB:-0}"
SEED_ONLY=0
NO_FRONTEND=0
NO_BACKEND=0
while [[ $# -gt 0 ]]; do
case "$1" in
--reset-db)
RESET_DB=1
shift
;;
--seed-only)
SEED_ONLY=1
shift
;;
--no-frontend)
NO_FRONTEND=1
shift
;;
--no-backend)
NO_BACKEND=1
shift
;;
-h|--help)
show_help
;;
*)
log_error "未知选项: $1"
show_help
;;
esac
done
cleanup() {
if [[ "${CLEANED_UP}" == "1" ]]; then
return
fi
CLEANED_UP=1
if [[ -z "${FRONTEND_PID}" && -z "${BACKEND_PID}" ]]; then
return
fi
log "正在停止前后端开发进程..."
if [[ -n "${FRONTEND_PID}" ]] && kill -0 "${FRONTEND_PID}" >/dev/null 2>&1; then
kill "${FRONTEND_PID}" >/dev/null 2>&1 || true
fi
if [[ -n "${BACKEND_PID}" ]] && kill -0 "${BACKEND_PID}" >/dev/null 2>&1; then
kill "${BACKEND_PID}" >/dev/null 2>&1 || true
fi
}
wait_container_healthy() {
local container_name="$1"
local label="$2"
local attempt
log "等待 ${label} 就绪..."
for attempt in {1..60}; do
local status
status="$(docker inspect -f '{{if .State.Health}}{{.State.Health.Status}}{{else}}{{.State.Status}}{{end}}' "${container_name}" 2>/dev/null || true)"
if [[ "${status}" == "healthy" || "${status}" == "running" ]]; then
log "${label} 已就绪"
return 0
fi
sleep 2
done
printf "%s 启动超时,请检查:docker logs %s\n" "${label}" "${container_name}" >&2
exit 1
}
mysql_root() {
docker exec -i -e MYSQL_PWD=rootsecret hfb-mysql mysql -uroot "$@"
}
mysql_hfb() {
docker exec -i -e MYSQL_PWD=secret hfb-mysql mysql -uhfb "$@"
}
init_database() {
if [[ "${RESET_DB}" == "1" ]]; then
log_warn "重置数据库..."
mysql_root -e \
"DROP DATABASE IF EXISTS hfb_sys; CREATE DATABASE hfb_sys CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
fi
local table_count
table_count="$(
mysql_hfb -N -s -e \
"SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'hfb_sys' AND table_name = 'users';" 2>/dev/null
)"
if [[ "${table_count}" == "0" ]]; then
log "首次启动,初始化数据库..."
local migration
for migration in "${ROOT_DIR}"/backend/migrations/*.sql; do
log "执行迁移:$(basename "${migration}")"
mysql_hfb --default-character-set=utf8mb4 hfb_sys < "${migration}"
done
log_success "数据库初始化完成"
elif [[ "${SEED_ONLY}" == "1" ]]; then
log "重新加载种子数据..."
mysql_hfb --default-character-set=utf8mb4 hfb_sys < "${ROOT_DIR}/backend/migrations/000002_seed.sql"
log_success "种子数据加载完成"
else
log "数据库已存在,跳过迁移(使用 --reset-db 重建)"
fi
}
load_env_file() {
local env_file="$1"
local line
while IFS= read -r line || [[ -n "${line}" ]]; do
[[ -z "${line}" || "${line}" =~ ^[[:space:]]*# ]] && continue
line="${line#export }"
export "${line}"
done < "${env_file}"
}
start_backend() {
if [[ ! -f "${BACKEND_ENV}" ]]; then
log "创建 backend/.env"
cp "${BACKEND_ENV_EXAMPLE}" "${BACKEND_ENV}"
fi
log "启动后端:http://localhost:8080"
(
cd "${ROOT_DIR}/backend"
load_env_file "${BACKEND_ENV}"
go run ./cmd/api
) &
BACKEND_PID="$!"
}
start_frontend() {
if [[ ! -d "${ROOT_DIR}/frontend/node_modules" ]]; then
log "安装前端依赖..."
(
cd "${ROOT_DIR}/frontend"
npm ci
)
fi
log "启动前端:http://localhost:5173"
(
cd "${ROOT_DIR}/frontend"
npm run dev
) &
FRONTEND_PID="$!"
}
watch_processes() {
while true; do
if [[ -n "${BACKEND_PID}" ]] && ! kill -0 "${BACKEND_PID}" >/dev/null 2>&1; then
wait "${BACKEND_PID}" || true
printf "后端进程已退出\n" >&2
exit 1
fi
if [[ -n "${FRONTEND_PID}" ]] && ! kill -0 "${FRONTEND_PID}" >/dev/null 2>&1; then
wait "${FRONTEND_PID}" || true
printf "前端进程已退出\n" >&2
exit 1
fi
sleep 2
done
}
main() {
need_cmd docker
if [[ "${SEED_ONLY}" != "1" && "${NO_BACKEND}" == "0" ]]; then
need_cmd go
fi
if [[ "${SEED_ONLY}" != "1" && "${NO_FRONTEND}" == "0" ]]; then
need_cmd npm
fi
trap cleanup EXIT
trap 'cleanup; exit 130' INT TERM
log "启动开发依赖:MySQL、Redis、MinIO"
docker compose -f "${COMPOSE_FILE}" up -d
wait_container_healthy hfb-mysql "MySQL"
wait_container_healthy hfb-redis "Redis"
wait_container_healthy hfb-minio "MinIO"
init_database
# 仅加载种子数据模式
if [[ "${SEED_ONLY}" == "1" ]]; then
log_success "种子数据加载完成,退出"
exit 0
fi
if [[ "${NO_BACKEND}" == "0" ]]; then
start_backend
fi
if [[ "${NO_FRONTEND}" == "0" ]]; then
start_frontend
fi
log_success "开发环境已启动"
if [[ "${NO_FRONTEND}" == "0" ]]; then
log "前台:http://localhost:5173"
log "后台:http://localhost:5173/admin/loginadmin / admin123456"
fi
if [[ -z "${BACKEND_PID}" && -z "${FRONTEND_PID}" ]]; then
log "仅启动 Docker 开发依赖,前后端未启动"
return 0
fi
log "按 Ctrl+C 停止前后端;Docker 依赖会保留运行"
watch_processes
}
main "$@"