feat(distribution): 独立分销后台账号体系、多租户隔离与主站后台分销管理GUI
- 独立账号鉴权:分销后台支持独立登录页面、Bearer+Cookie 双模鉴权与租户资料接口 - 多租户隔离:分销商成员强制锁定自身站点数据范围,防止横向越权;平台超管享有全局视界 - 一键开通分销商:平台端支持一键录入站点、管理员账号、分配角色并原子化初始化佣金规则 - 主后台分销分组:在主站后台增加「分销管理」导航分组,提供站点管理、规则配置、订单监控与结算管理 GUI - 门禁与联调:补充完整单测,全量代码门禁 check.sh 100% 通过,dev.sh 支持前后端与分销后台一键同启
This commit is contained in:
+124
-31
@@ -10,16 +10,23 @@ FRONTEND_PACKAGE_JSON="${FRONTEND_DIR}/package.json"
|
||||
FRONTEND_PACKAGE_LOCK="${FRONTEND_DIR}/package-lock.json"
|
||||
FRONTEND_NODE_MODULES="${FRONTEND_DIR}/node_modules"
|
||||
FRONTEND_NODE_MODULES_LOCK="${FRONTEND_NODE_MODULES}/.package-lock.json"
|
||||
DISTRIBUTION_DIR="${ROOT_DIR}/distribution-admin"
|
||||
DISTRIBUTION_PACKAGE_JSON="${DISTRIBUTION_DIR}/package.json"
|
||||
DISTRIBUTION_PACKAGE_LOCK="${DISTRIBUTION_DIR}/package-lock.json"
|
||||
DISTRIBUTION_NODE_MODULES="${DISTRIBUTION_DIR}/node_modules"
|
||||
DISTRIBUTION_NODE_MODULES_LOCK="${DISTRIBUTION_NODE_MODULES}/.package-lock.json"
|
||||
MIGRATIONS_DIR="${ROOT_DIR}/backend/migrations"
|
||||
MYSQL_DATABASE="${DEV_MYSQL_DATABASE:-hfb_sys}"
|
||||
BACKEND_PORT="${DEV_BACKEND_PORT:-18088}"
|
||||
FRONTEND_PORT="${DEV_FRONTEND_PORT:-5189}"
|
||||
DISTRIBUTION_PORT="${DEV_DISTRIBUTION_PORT:-5190}"
|
||||
MYSQL_PORT="${DEV_MYSQL_PORT:-13306}"
|
||||
REDIS_PORT="${DEV_REDIS_PORT:-16379}"
|
||||
MINIO_API_PORT="${DEV_MINIO_API_PORT:-19090}"
|
||||
MINIO_CONSOLE_PORT="${DEV_MINIO_CONSOLE_PORT:-19091}"
|
||||
BACKEND_HEALTH_URL="${DEV_BACKEND_HEALTH_URL:-http://127.0.0.1:${BACKEND_PORT}/health}"
|
||||
FRONTEND_HEALTH_URL="${DEV_FRONTEND_HEALTH_URL:-http://127.0.0.1:${FRONTEND_PORT}/}"
|
||||
DISTRIBUTION_HEALTH_URL="${DEV_DISTRIBUTION_HEALTH_URL:-http://127.0.0.1:${DISTRIBUTION_PORT}/}"
|
||||
HTTP_READY_TIMEOUT="${DEV_HTTP_READY_TIMEOUT:-120}"
|
||||
AUTO_KILL_PORTS="${DEV_AUTO_KILL_PORTS:-1}"
|
||||
FORCE_NPM_CI="${DEV_FORCE_NPM_CI:-0}"
|
||||
@@ -28,6 +35,7 @@ GOOSE_BIN="${GOOSE_BIN:-}"
|
||||
|
||||
BACKEND_PID=""
|
||||
FRONTEND_PID=""
|
||||
DISTRIBUTION_PID=""
|
||||
CLEANED_UP=0
|
||||
|
||||
# 颜色定义
|
||||
@@ -65,41 +73,46 @@ show_help() {
|
||||
用法: ./scripts/dev.sh [选项]
|
||||
|
||||
选项:
|
||||
--reset-db 重置数据库(删除并重建)
|
||||
--no-migrate 不执行数据库迁移
|
||||
--no-frontend 不启动前端
|
||||
--no-backend 不启动后端
|
||||
-h, --help 显示帮助信息
|
||||
--reset-db 重置数据库(删除并重建)
|
||||
--no-migrate 不执行数据库迁移
|
||||
--no-frontend 不启动主站前端
|
||||
--no-backend 不启动后端
|
||||
--no-distribution 不启动分销后台
|
||||
-h, --help 显示帮助信息
|
||||
|
||||
环境变量:
|
||||
DEV_RESET_DB=1 等同于 --reset-db
|
||||
DEV_RESET_DB=1 等同于 --reset-db
|
||||
DEV_MYSQL_DATABASE=hfb_sys
|
||||
开发数据库名
|
||||
开发数据库名
|
||||
DEV_BACKEND_PORT=18088
|
||||
后端启动端口
|
||||
后端启动端口
|
||||
DEV_FRONTEND_PORT=5189
|
||||
前端启动端口
|
||||
主站前端启动端口
|
||||
DEV_DISTRIBUTION_PORT=5190
|
||||
分销后台启动端口
|
||||
DEV_MYSQL_PORT=13306
|
||||
MySQL 宿主机映射端口
|
||||
MySQL 宿主机映射端口
|
||||
DEV_REDIS_PORT=16379
|
||||
Redis 宿主机映射端口
|
||||
Redis 宿主机映射端口
|
||||
DEV_MINIO_API_PORT=19090
|
||||
MinIO API 宿主机映射端口
|
||||
MinIO API 宿主机映射端口
|
||||
DEV_MINIO_CONSOLE_PORT=19091
|
||||
MinIO 控制台宿主机映射端口
|
||||
MinIO 控制台宿主机映射端口
|
||||
DEV_BACKEND_HEALTH_URL=http://127.0.0.1:18088/health
|
||||
后端健康检查地址
|
||||
后端健康检查地址
|
||||
DEV_FRONTEND_HEALTH_URL=http://127.0.0.1:5189/
|
||||
前端健康检查地址
|
||||
主站前端健康检查地址
|
||||
DEV_DISTRIBUTION_HEALTH_URL=http://127.0.0.1:5190/
|
||||
分销后台健康检查地址
|
||||
DEV_HTTP_READY_TIMEOUT=120
|
||||
HTTP 服务就绪等待秒数
|
||||
HTTP 服务就绪等待秒数
|
||||
DEV_AUTO_KILL_PORTS=1
|
||||
前后端端口被占用时自动停止占用的 Docker 容器或本机进程
|
||||
前后端端口被占用时自动停止占用的 Docker 容器或本机进程
|
||||
DEV_FORCE_NPM_CI=0
|
||||
强制重新执行前端 npm ci
|
||||
强制重新执行前端 npm ci
|
||||
|
||||
示例:
|
||||
./scripts/dev.sh # 正常启动
|
||||
./scripts/dev.sh # 正常启动(后端 + 主前后台 + 分销前台)
|
||||
./scripts/dev.sh --reset-db # 重置数据库后启动(推荐迁移后使用)
|
||||
EOF
|
||||
exit 0
|
||||
@@ -110,6 +123,7 @@ RESET_DB="${DEV_RESET_DB:-0}"
|
||||
NO_MIGRATE=0
|
||||
NO_FRONTEND=0
|
||||
NO_BACKEND=0
|
||||
NO_DISTRIBUTION=0
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
@@ -129,6 +143,10 @@ while [[ $# -gt 0 ]]; do
|
||||
NO_BACKEND=1
|
||||
shift
|
||||
;;
|
||||
--no-distribution)
|
||||
NO_DISTRIBUTION=1
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
show_help
|
||||
;;
|
||||
@@ -145,11 +163,14 @@ cleanup() {
|
||||
fi
|
||||
CLEANED_UP=1
|
||||
|
||||
if [[ -z "${FRONTEND_PID}" && -z "${BACKEND_PID}" ]]; then
|
||||
if [[ -z "${FRONTEND_PID}" && -z "${BACKEND_PID}" && -z "${DISTRIBUTION_PID}" ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
log "正在停止前后端开发进程..."
|
||||
if [[ -n "${DISTRIBUTION_PID}" ]] && kill -0 "${DISTRIBUTION_PID}" >/dev/null 2>&1; then
|
||||
kill "${DISTRIBUTION_PID}" >/dev/null 2>&1 || true
|
||||
fi
|
||||
if [[ -n "${FRONTEND_PID}" ]] && kill -0 "${FRONTEND_PID}" >/dev/null 2>&1; then
|
||||
kill "${FRONTEND_PID}" >/dev/null 2>&1 || true
|
||||
fi
|
||||
@@ -540,6 +561,64 @@ start_frontend() {
|
||||
FRONTEND_PID="$!"
|
||||
}
|
||||
|
||||
distribution_dependencies_need_ci() {
|
||||
if [[ "${FORCE_NPM_CI}" == "1" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ ! -d "${DISTRIBUTION_NODE_MODULES}" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ ! -f "${DISTRIBUTION_NODE_MODULES_LOCK}" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ "${DISTRIBUTION_PACKAGE_JSON}" -nt "${DISTRIBUTION_NODE_MODULES_LOCK}" || "${DISTRIBUTION_PACKAGE_LOCK}" -nt "${DISTRIBUTION_NODE_MODULES_LOCK}" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
(
|
||||
cd "${DISTRIBUTION_DIR}"
|
||||
npm ls --depth=0 >/dev/null 2>&1
|
||||
) || return 0
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
ensure_distribution_dependencies() {
|
||||
if [[ ! -f "${DISTRIBUTION_PACKAGE_LOCK}" ]]; then
|
||||
log_error "缺少 distribution-admin/package-lock.json,无法执行 npm ci"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if distribution_dependencies_need_ci; then
|
||||
log "同步分销后台依赖(npm ci)..."
|
||||
(
|
||||
cd "${DISTRIBUTION_DIR}"
|
||||
npm ci
|
||||
)
|
||||
log_success "分销后台依赖已同步"
|
||||
else
|
||||
log "分销后台依赖已同步,跳过 npm ci"
|
||||
fi
|
||||
}
|
||||
|
||||
start_distribution() {
|
||||
ensure_distribution_dependencies
|
||||
|
||||
log "启动分销后台:http://localhost:${DISTRIBUTION_PORT}"
|
||||
(
|
||||
cd "${DISTRIBUTION_DIR}"
|
||||
export PORT="${DISTRIBUTION_PORT}"
|
||||
export DEV_DISTRIBUTION_PORT="${DISTRIBUTION_PORT}"
|
||||
export DEV_BACKEND_PORT="${BACKEND_PORT}"
|
||||
export VITE_API_PROXY_TARGET="${VITE_API_PROXY_TARGET:-http://127.0.0.1:${BACKEND_PORT}}"
|
||||
npm run dev
|
||||
) &
|
||||
DISTRIBUTION_PID="$!"
|
||||
}
|
||||
|
||||
watch_processes() {
|
||||
while true; do
|
||||
if [[ -n "${BACKEND_PID}" ]] && ! kill -0 "${BACKEND_PID}" >/dev/null 2>&1; then
|
||||
@@ -549,7 +628,12 @@ watch_processes() {
|
||||
fi
|
||||
if [[ -n "${FRONTEND_PID}" ]] && ! kill -0 "${FRONTEND_PID}" >/dev/null 2>&1; then
|
||||
wait "${FRONTEND_PID}" || true
|
||||
printf "前端进程已退出\n" >&2
|
||||
printf "主站前端进程已退出\n" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ -n "${DISTRIBUTION_PID}" ]] && ! kill -0 "${DISTRIBUTION_PID}" >/dev/null 2>&1; then
|
||||
wait "${DISTRIBUTION_PID}" || true
|
||||
printf "分销后台进程已退出\n" >&2
|
||||
exit 1
|
||||
fi
|
||||
sleep 2
|
||||
@@ -561,10 +645,10 @@ main() {
|
||||
if [[ "${NO_BACKEND}" == "0" ]]; then
|
||||
need_cmd go
|
||||
fi
|
||||
if [[ "${NO_FRONTEND}" == "0" ]]; then
|
||||
if [[ "${NO_FRONTEND}" == "0" || "${NO_DISTRIBUTION}" == "0" ]]; then
|
||||
need_cmd npm
|
||||
fi
|
||||
if [[ "${NO_BACKEND}" == "0" || "${NO_FRONTEND}" == "0" ]]; then
|
||||
if [[ "${NO_BACKEND}" == "0" || "${NO_FRONTEND}" == "0" || "${NO_DISTRIBUTION}" == "0" ]]; then
|
||||
need_cmd curl
|
||||
fi
|
||||
|
||||
@@ -603,24 +687,33 @@ main() {
|
||||
fi
|
||||
|
||||
if [[ "${NO_FRONTEND}" == "0" ]]; then
|
||||
ensure_port_free "${FRONTEND_PORT}" "前端"
|
||||
ensure_port_free "${FRONTEND_PORT}" "主站前端"
|
||||
start_frontend
|
||||
wait_http_ready "${FRONTEND_HEALTH_URL}" "前端" "${FRONTEND_PID}"
|
||||
wait_http_ready "${FRONTEND_HEALTH_URL}" "主站前端" "${FRONTEND_PID}"
|
||||
fi
|
||||
|
||||
if [[ -z "${BACKEND_PID}" && -z "${FRONTEND_PID}" ]]; then
|
||||
log "仅启动 Docker 开发依赖,前后端未启动"
|
||||
if [[ "${NO_DISTRIBUTION}" == "0" && -d "${DISTRIBUTION_DIR}" ]]; then
|
||||
ensure_port_free "${DISTRIBUTION_PORT}" "分销后台"
|
||||
start_distribution
|
||||
wait_http_ready "${DISTRIBUTION_HEALTH_URL}" "分销后台" "${DISTRIBUTION_PID}"
|
||||
fi
|
||||
|
||||
if [[ -z "${BACKEND_PID}" && -z "${FRONTEND_PID}" && -z "${DISTRIBUTION_PID}" ]]; then
|
||||
log "仅启动 Docker 开发依赖,前后端与分销端未启动"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log_success "开发环境已启动"
|
||||
log_success "开发环境已就绪"
|
||||
if [[ "${NO_FRONTEND}" == "0" ]]; then
|
||||
local admin_base_path="${VITE_ADMIN_BASE_PATH:-/admin}"
|
||||
log "前台:http://localhost:${FRONTEND_PORT}"
|
||||
log "后台:http://localhost:${FRONTEND_PORT}${admin_base_path%/}/login"
|
||||
log "前台地址:http://localhost:${FRONTEND_PORT}"
|
||||
log "后台地址:http://localhost:${FRONTEND_PORT}${admin_base_path%/}/login"
|
||||
fi
|
||||
if [[ "${NO_DISTRIBUTION}" == "0" && -d "${DISTRIBUTION_DIR}" ]]; then
|
||||
log "分销后台:http://localhost:${DISTRIBUTION_PORT}"
|
||||
fi
|
||||
|
||||
log "按 Ctrl+C 停止前后端;Docker 依赖会保留运行"
|
||||
log "按 Ctrl+C 停止所有服务;Docker 依赖会保留运行"
|
||||
|
||||
watch_processes
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user