feat: 接入旧站管理端并完整迁移后台能力
This commit is contained in:
@@ -41,11 +41,11 @@ require_pattern "backend/internal/modules/pickup/repository.go" "if pageSize > 1
|
||||
# 智能意图路由与单表唯一索引直达防线(防止多表跨表 OR/LIKE 导致 MySQL 放弃索引而退化为全表扫描)
|
||||
require_pattern "backend/internal/modules/order/queries.go" "o.order_no = ?" "订单列表订单号唯一索引直达"
|
||||
require_pattern "backend/internal/modules/order/queries.go" "l.listing_no = ?" "订单列表商品号唯一索引直达"
|
||||
require_pattern "backend/internal/modules/order/queries.go" "owner.phone = ? OR renter.phone = ?" "订单列表手机号索引直达"
|
||||
require_pattern "backend/internal/modules/order/queries.go" "o.owner_id = (SELECT id FROM users WHERE phone = ?) OR o.renter_id = (SELECT id FROM users WHERE phone = ?)" "订单列表手机号索引直达"
|
||||
require_pattern "backend/internal/modules/order/queries.go" "page == 1 && len(rows) < pageSize" "订单列表首页面单扫描短路"
|
||||
|
||||
require_pattern "backend/internal/modules/pickup/repository.go" "p.pickup_no = ?" "提号列表提号单号唯一索引直达"
|
||||
require_pattern "backend/internal/modules/pickup/repository.go" "owner.phone = ?" "提号列表号主手机号索引直达"
|
||||
require_pattern "backend/internal/modules/pickup/repository.go" "p.owner_id = (SELECT id FROM users WHERE phone = ?)" "提号列表号主手机号索引直达"
|
||||
require_pattern "backend/internal/modules/pickup/repository.go" "page == 1 && len(rows) < pageSize" "提号列表首页面单扫描短路"
|
||||
|
||||
require_pattern "backend/internal/modules/dispute/query.go" "o.order_no = ?" "纠纷列表订单号唯一索引直达"
|
||||
@@ -58,7 +58,7 @@ require_pattern "backend/internal/modules/listing/query.go" "l.listing_no = ?" "
|
||||
require_pattern "backend/internal/modules/listing/query.go" "page == 1 && len(rows) < pageSize" "商品列表首页面单扫描短路"
|
||||
|
||||
require_pattern "backend/internal/modules/chat/support.go" "l.listing_no = ?" "客服会话商品号唯一索引直达"
|
||||
require_pattern "backend/internal/modules/chat/support.go" "renter.phone = ? OR owner.phone = ?" "客服会话手机号唯一索引直达"
|
||||
require_pattern "backend/internal/modules/chat/support.go" "o2.owner_id = (SELECT id FROM users WHERE phone = ?)" "客服会话手机号唯一索引直达"
|
||||
|
||||
# 禁止核心列表重新引入跨表 6~10 路全扫描反模式
|
||||
forbid_pattern "backend/internal/modules/dispute/query.go" "o.order_no LIKE ? OR l.listing_no LIKE ? OR a.title LIKE ? OR owner.phone LIKE ? OR renter.phone LIKE ? OR d.id = ?" "纠纷列表禁止6表无意图全表扫描"
|
||||
|
||||
@@ -16,6 +16,7 @@ set -euo pipefail
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
BACKEND_DIR="${ROOT_DIR}/backend"
|
||||
FRONTEND_DIR="${ROOT_DIR}/frontend"
|
||||
ADMIN_WEB_DIR="${ROOT_DIR}/admin-web"
|
||||
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
@@ -127,6 +128,21 @@ if [[ "${SKIP_FRONTEND}" == "0" ]]; then
|
||||
log_warn "跳过前端测试 (--skip-tests)"
|
||||
fi
|
||||
run_step "npm run build (vite 生产构建)" npm run build || FAILED=1
|
||||
|
||||
log "管理端检查目录: ${ADMIN_WEB_DIR}"
|
||||
cd "${ADMIN_WEB_DIR}"
|
||||
|
||||
if [[ ! -d node_modules ]]; then
|
||||
run_step "管理端 npm ci (首次安装依赖)" npm ci || FAILED=1
|
||||
fi
|
||||
|
||||
run_step "管理端 npm run check (prettier + eslint + typecheck)" npm run check || FAILED=1
|
||||
if [[ "${SKIP_TESTS}" == "0" ]]; then
|
||||
run_step "管理端 npm run test (vitest)" npm run test || FAILED=1
|
||||
else
|
||||
log_warn "跳过后台管理端测试 (--skip-tests)"
|
||||
fi
|
||||
run_step "管理端 npm run build (vite 生产构建)" npm run build || FAILED=1
|
||||
else
|
||||
log_warn "跳过前端检查 (--skip-frontend)"
|
||||
fi
|
||||
|
||||
+80
-8
@@ -10,6 +10,10 @@ 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"
|
||||
ADMIN_WEB_DIR="${ROOT_DIR}/admin-web"
|
||||
ADMIN_WEB_PACKAGE_LOCK="${ADMIN_WEB_DIR}/package-lock.json"
|
||||
ADMIN_WEB_NODE_MODULES="${ADMIN_WEB_DIR}/node_modules"
|
||||
ADMIN_WEB_NODE_MODULES_LOCK="${ADMIN_WEB_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"
|
||||
@@ -19,6 +23,7 @@ MIGRATIONS_DIR="${ROOT_DIR}/backend/migrations"
|
||||
MYSQL_DATABASE="${DEV_MYSQL_DATABASE:-hfb_jysh}"
|
||||
BACKEND_PORT="${DEV_BACKEND_PORT:-18089}"
|
||||
FRONTEND_PORT="${DEV_FRONTEND_PORT:-5289}"
|
||||
ADMIN_WEB_PORT="${DEV_ADMIN_WEB_PORT:-5292}"
|
||||
DISTRIBUTION_PORT="${DEV_DISTRIBUTION_PORT:-5290}"
|
||||
DISTRIBUTION_STOREFRONT_PORT="${DEV_DISTRIBUTION_STOREFRONT_PORT:-5291}"
|
||||
DISTRIBUTION_STOREFRONT_SITE_CODE="${DEV_DISTRIBUTION_STOREFRONT_SITE_CODE:-test_1}"
|
||||
@@ -28,6 +33,7 @@ MINIO_API_PORT="${DEV_MINIO_API_PORT:-29090}"
|
||||
MINIO_CONSOLE_PORT="${DEV_MINIO_CONSOLE_PORT:-29091}"
|
||||
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}/}"
|
||||
ADMIN_WEB_HEALTH_URL="${DEV_ADMIN_WEB_HEALTH_URL:-http://127.0.0.1:${ADMIN_WEB_PORT}${VITE_ADMIN_BASE_PATH:-/console-jy8k3m}/login}"
|
||||
DISTRIBUTION_HEALTH_URL="${DEV_DISTRIBUTION_HEALTH_URL:-http://127.0.0.1:${DISTRIBUTION_PORT}/}"
|
||||
DISTRIBUTION_STOREFRONT_HEALTH_URL="${DEV_DISTRIBUTION_STOREFRONT_HEALTH_URL:-http://127.0.0.1:${DISTRIBUTION_STOREFRONT_PORT}/}"
|
||||
HTTP_READY_TIMEOUT="${DEV_HTTP_READY_TIMEOUT:-120}"
|
||||
@@ -35,9 +41,11 @@ AUTO_KILL_PORTS="${DEV_AUTO_KILL_PORTS:-1}"
|
||||
FORCE_NPM_CI="${DEV_FORCE_NPM_CI:-0}"
|
||||
GOOSE_VERSION="${GOOSE_VERSION:-v3.27.1}"
|
||||
GOOSE_BIN="${GOOSE_BIN:-}"
|
||||
GOOSE_GOPROXY="${GOOSE_GOPROXY:-https://goproxy.cn,direct}"
|
||||
|
||||
BACKEND_PID=""
|
||||
FRONTEND_PID=""
|
||||
ADMIN_WEB_PID=""
|
||||
DISTRIBUTION_PID=""
|
||||
DISTRIBUTION_STOREFRONT_PID=""
|
||||
CLEANED_UP=0
|
||||
@@ -80,6 +88,7 @@ show_help() {
|
||||
--reset-db 重置数据库(删除并重建)
|
||||
--no-migrate 不执行数据库迁移
|
||||
--no-frontend 不启动主站前端
|
||||
--no-admin 不启动独立管理端
|
||||
--no-backend 不启动后端
|
||||
--no-distribution 不启动分销后台
|
||||
--no-distribution-storefront
|
||||
@@ -94,6 +103,8 @@ show_help() {
|
||||
后端启动端口
|
||||
DEV_FRONTEND_PORT=5289
|
||||
主站前端启动端口
|
||||
DEV_ADMIN_WEB_PORT=5292
|
||||
独立管理端启动端口
|
||||
DEV_DISTRIBUTION_PORT=5290
|
||||
分销后台启动端口
|
||||
DEV_MYSQL_PORT=23306
|
||||
@@ -108,6 +119,8 @@ show_help() {
|
||||
后端健康检查地址
|
||||
DEV_FRONTEND_HEALTH_URL=http://127.0.0.1:5289/
|
||||
主站前端健康检查地址
|
||||
DEV_ADMIN_WEB_HEALTH_URL=http://127.0.0.1:5292/console-jy8k3m/login
|
||||
独立管理端健康检查地址
|
||||
DEV_DISTRIBUTION_HEALTH_URL=http://127.0.0.1:5290/
|
||||
分销后台健康检查地址
|
||||
DEV_HTTP_READY_TIMEOUT=120
|
||||
@@ -116,6 +129,8 @@ show_help() {
|
||||
前后端端口被占用时自动停止占用的 Docker 容器或本机进程
|
||||
DEV_FORCE_NPM_CI=0
|
||||
强制重新执行前端 npm ci
|
||||
GOOSE_GOPROXY=https://goproxy.cn,direct
|
||||
Goose 安装失败时使用的 Go 模块代理
|
||||
|
||||
示例:
|
||||
./scripts/dev.sh # 正常启动(后端 + 主前后台 + 分销前台)
|
||||
@@ -128,6 +143,7 @@ EOF
|
||||
RESET_DB="${DEV_RESET_DB:-0}"
|
||||
NO_MIGRATE=0
|
||||
NO_FRONTEND=0
|
||||
NO_ADMIN_WEB=0
|
||||
NO_BACKEND=0
|
||||
NO_DISTRIBUTION=0
|
||||
NO_DISTRIBUTION_STOREFRONT=0
|
||||
@@ -146,6 +162,10 @@ while [[ $# -gt 0 ]]; do
|
||||
NO_FRONTEND=1
|
||||
shift
|
||||
;;
|
||||
--no-admin)
|
||||
NO_ADMIN_WEB=1
|
||||
shift
|
||||
;;
|
||||
--no-backend)
|
||||
NO_BACKEND=1
|
||||
shift
|
||||
@@ -174,7 +194,7 @@ cleanup() {
|
||||
fi
|
||||
CLEANED_UP=1
|
||||
|
||||
if [[ -z "${FRONTEND_PID}" && -z "${BACKEND_PID}" && -z "${DISTRIBUTION_PID}" && -z "${DISTRIBUTION_STOREFRONT_PID}" ]]; then
|
||||
if [[ -z "${FRONTEND_PID}" && -z "${ADMIN_WEB_PID}" && -z "${BACKEND_PID}" && -z "${DISTRIBUTION_PID}" && -z "${DISTRIBUTION_STOREFRONT_PID}" ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
@@ -185,6 +205,9 @@ cleanup() {
|
||||
if [[ -n "${DISTRIBUTION_PID}" ]] && kill -0 "${DISTRIBUTION_PID}" >/dev/null 2>&1; then
|
||||
kill "${DISTRIBUTION_PID}" >/dev/null 2>&1 || true
|
||||
fi
|
||||
if [[ -n "${ADMIN_WEB_PID}" ]] && kill -0 "${ADMIN_WEB_PID}" >/dev/null 2>&1; then
|
||||
kill "${ADMIN_WEB_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
|
||||
@@ -446,7 +469,10 @@ ensure_goose() {
|
||||
if [[ -z "${GOOSE_BIN}" ]]; then
|
||||
need_cmd go
|
||||
log "未找到 goose,正在安装 ${GOOSE_VERSION}..."
|
||||
(cd "${ROOT_DIR}/backend" && go install "github.com/pressly/goose/v3/cmd/goose@${GOOSE_VERSION}")
|
||||
if ! (cd "${ROOT_DIR}/backend" && go install "github.com/pressly/goose/v3/cmd/goose@${GOOSE_VERSION}"); then
|
||||
log_warn "默认 Go 模块代理不可用,改用 ${GOOSE_GOPROXY} 重试..."
|
||||
(cd "${ROOT_DIR}/backend" && GOPROXY="${GOOSE_GOPROXY}" go install "github.com/pressly/goose/v3/cmd/goose@${GOOSE_VERSION}")
|
||||
fi
|
||||
GOOSE_BIN="$(go env GOPATH)/bin/goose"
|
||||
fi
|
||||
|
||||
@@ -575,6 +601,40 @@ start_frontend() {
|
||||
FRONTEND_PID="$!"
|
||||
}
|
||||
|
||||
ensure_admin_web_dependencies() {
|
||||
if [[ ! -f "${ADMIN_WEB_PACKAGE_LOCK}" ]]; then
|
||||
log_error "缺少 admin-web/package-lock.json,无法执行 npm ci"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "${FORCE_NPM_CI}" == "1" || ! -d "${ADMIN_WEB_NODE_MODULES}" || ! -f "${ADMIN_WEB_NODE_MODULES_LOCK}" ]]; then
|
||||
log "同步管理端依赖(npm ci)..."
|
||||
(
|
||||
cd "${ADMIN_WEB_DIR}"
|
||||
npm ci
|
||||
)
|
||||
log_success "管理端依赖已同步"
|
||||
else
|
||||
log "管理端依赖已同步,跳过 npm ci"
|
||||
fi
|
||||
}
|
||||
|
||||
start_admin_web() {
|
||||
ensure_admin_web_dependencies
|
||||
|
||||
log "启动独立管理端:http://localhost:${ADMIN_WEB_PORT}${VITE_ADMIN_BASE_PATH:-/console-jy8k3m}/login"
|
||||
(
|
||||
cd "${ADMIN_WEB_DIR}"
|
||||
export PORT="${ADMIN_WEB_PORT}"
|
||||
export DEV_FRONTEND_PORT="${ADMIN_WEB_PORT}"
|
||||
export DEV_BACKEND_PORT="${BACKEND_PORT}"
|
||||
export VITE_ADMIN_BASE_PATH="${VITE_ADMIN_BASE_PATH:-/console-jy8k3m}"
|
||||
export VITE_API_PROXY_TARGET="${VITE_API_PROXY_TARGET:-http://127.0.0.1:${BACKEND_PORT}}"
|
||||
npm run dev
|
||||
) &
|
||||
ADMIN_WEB_PID="$!"
|
||||
}
|
||||
|
||||
distribution_dependencies_need_ci() {
|
||||
if [[ "${FORCE_NPM_CI}" == "1" ]]; then
|
||||
return 0
|
||||
@@ -660,6 +720,11 @@ watch_processes() {
|
||||
printf "主站前端进程已退出\n" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ -n "${ADMIN_WEB_PID}" ]] && ! kill -0 "${ADMIN_WEB_PID}" >/dev/null 2>&1; then
|
||||
wait "${ADMIN_WEB_PID}" || true
|
||||
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
|
||||
@@ -679,10 +744,10 @@ main() {
|
||||
if [[ "${NO_BACKEND}" == "0" ]]; then
|
||||
need_cmd go
|
||||
fi
|
||||
if [[ "${NO_FRONTEND}" == "0" || "${NO_DISTRIBUTION}" == "0" ]]; then
|
||||
if [[ "${NO_FRONTEND}" == "0" || "${NO_ADMIN_WEB}" == "0" || "${NO_DISTRIBUTION}" == "0" ]]; then
|
||||
need_cmd npm
|
||||
fi
|
||||
if [[ "${NO_BACKEND}" == "0" || "${NO_FRONTEND}" == "0" || "${NO_DISTRIBUTION}" == "0" ]]; then
|
||||
if [[ "${NO_BACKEND}" == "0" || "${NO_FRONTEND}" == "0" || "${NO_ADMIN_WEB}" == "0" || "${NO_DISTRIBUTION}" == "0" ]]; then
|
||||
need_cmd curl
|
||||
fi
|
||||
|
||||
@@ -726,6 +791,12 @@ main() {
|
||||
wait_http_ready "${FRONTEND_HEALTH_URL}" "主站前端" "${FRONTEND_PID}"
|
||||
fi
|
||||
|
||||
if [[ "${NO_ADMIN_WEB}" == "0" && -d "${ADMIN_WEB_DIR}" ]]; then
|
||||
ensure_port_free "${ADMIN_WEB_PORT}" "管理端"
|
||||
start_admin_web
|
||||
wait_http_ready "${ADMIN_WEB_HEALTH_URL}" "管理端" "${ADMIN_WEB_PID}"
|
||||
fi
|
||||
|
||||
if [[ "${NO_DISTRIBUTION}" == "0" && -d "${DISTRIBUTION_DIR}" ]]; then
|
||||
ensure_port_free "${DISTRIBUTION_PORT}" "分销后台"
|
||||
start_distribution
|
||||
@@ -738,16 +809,17 @@ main() {
|
||||
wait_http_ready "${DISTRIBUTION_STOREFRONT_HEALTH_URL}" "分销前台" "${DISTRIBUTION_STOREFRONT_PID}"
|
||||
fi
|
||||
|
||||
if [[ -z "${BACKEND_PID}" && -z "${FRONTEND_PID}" && -z "${DISTRIBUTION_PID}" && -z "${DISTRIBUTION_STOREFRONT_PID}" ]]; then
|
||||
log "仅启动 Docker 开发依赖,前后端与分销端未启动"
|
||||
if [[ -z "${BACKEND_PID}" && -z "${FRONTEND_PID}" && -z "${ADMIN_WEB_PID}" && -z "${DISTRIBUTION_PID}" && -z "${DISTRIBUTION_STOREFRONT_PID}" ]]; then
|
||||
log "仅启动 Docker 开发依赖,前端、管理端、后端与分销端未启动"
|
||||
return 0
|
||||
fi
|
||||
|
||||
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"
|
||||
fi
|
||||
if [[ "${NO_ADMIN_WEB}" == "0" && -d "${ADMIN_WEB_DIR}" ]]; then
|
||||
log "管理端:http://localhost:${ADMIN_WEB_PORT}${VITE_ADMIN_BASE_PATH:-/console-jy8k3m}/login"
|
||||
fi
|
||||
if [[ "${NO_DISTRIBUTION}" == "0" && -d "${DISTRIBUTION_DIR}" ]]; then
|
||||
log "分销后台:http://localhost:${DISTRIBUTION_PORT}"
|
||||
|
||||
Reference in New Issue
Block a user