feat(dev): 增加独立分销前台端口5191、标签页会话隔离与免hosts二级域名支持
This commit is contained in:
@@ -16,13 +16,12 @@
|
||||
./scripts/dev.sh
|
||||
```
|
||||
|
||||
脚本会自动启动 MySQL、Redis、MinIO,首次初始化数据库结构,并同时启动后端和前端。
|
||||
脚本会自动启动 MySQL、Redis、MinIO,首次初始化数据库结构,并同时启动后端、主站前后台、分销独立后台与分销专属前台。
|
||||
|
||||
前端地址:`http://localhost:5189`
|
||||
|
||||
后台地址默认:`http://localhost:5189/admin/login`。可通过 `VITE_ADMIN_BASE_PATH` 调整后台页面入口。
|
||||
|
||||
分销后台地址默认:`http://localhost:5190`
|
||||
- 主站前台地址:`http://localhost:5189`
|
||||
- 主站后台地址:`http://localhost:5189/admin/login`(超级管理员默认 `admin` / `admin123456`)
|
||||
- 分销管理后台:`http://localhost:5190`(分销操作员 `test_fx1`)
|
||||
- 分销专属前台:`http://localhost:5191`(独立端口隔离,默认直连 `test_1` 分销站)
|
||||
|
||||
|
||||
如需拆分调试,可手动执行:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { apiClient } from '@/shared/api/client'
|
||||
|
||||
import type { ApiResponse, PaginatedResult } from '@/shared/types/types'
|
||||
import { getEffectiveSiteCode } from '@/stores/distributionSite'
|
||||
|
||||
export interface NotificationItem {
|
||||
id: number
|
||||
@@ -16,10 +16,7 @@ export interface NotificationItem {
|
||||
}
|
||||
|
||||
export async function fetchNotifications(page = 1, pageSize = 20, distributionSiteCode?: string) {
|
||||
const siteCode =
|
||||
distributionSiteCode ||
|
||||
(typeof window !== 'undefined' ? localStorage.getItem('hfb_site_code') : '') ||
|
||||
undefined
|
||||
const siteCode = distributionSiteCode || getEffectiveSiteCode() || undefined
|
||||
const params: Record<string, unknown> = { page, page_size: pageSize }
|
||||
if (siteCode) {
|
||||
params.distribution_site_code = siteCode
|
||||
@@ -34,10 +31,7 @@ export async function fetchNotifications(page = 1, pageSize = 20, distributionSi
|
||||
}
|
||||
|
||||
export async function markNotificationRead(id: number, distributionSiteCode?: string) {
|
||||
const siteCode =
|
||||
distributionSiteCode ||
|
||||
(typeof window !== 'undefined' ? localStorage.getItem('hfb_site_code') : '') ||
|
||||
undefined
|
||||
const siteCode = distributionSiteCode || getEffectiveSiteCode() || undefined
|
||||
const params: Record<string, unknown> = {}
|
||||
if (siteCode) {
|
||||
params.distribution_site_code = siteCode
|
||||
@@ -51,10 +45,7 @@ export async function markNotificationRead(id: number, distributionSiteCode?: st
|
||||
}
|
||||
|
||||
export async function fetchUnreadNotificationCount(distributionSiteCode?: string) {
|
||||
const siteCode =
|
||||
distributionSiteCode ||
|
||||
(typeof window !== 'undefined' ? localStorage.getItem('hfb_site_code') : '') ||
|
||||
undefined
|
||||
const siteCode = distributionSiteCode || getEffectiveSiteCode() || undefined
|
||||
const params: Record<string, unknown> = {}
|
||||
if (siteCode) {
|
||||
params.distribution_site_code = siteCode
|
||||
@@ -70,10 +61,7 @@ export async function fetchUnreadNotificationCount(distributionSiteCode?: string
|
||||
}
|
||||
|
||||
export async function markAllNotificationsRead(distributionSiteCode?: string) {
|
||||
const siteCode =
|
||||
distributionSiteCode ||
|
||||
(typeof window !== 'undefined' ? localStorage.getItem('hfb_site_code') : '') ||
|
||||
undefined
|
||||
const siteCode = distributionSiteCode || getEffectiveSiteCode() || undefined
|
||||
const params: Record<string, unknown> = {}
|
||||
if (siteCode) {
|
||||
params.distribution_site_code = siteCode
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { apiClient } from '@/shared/api/client'
|
||||
import type { ApiResponse, PaginatedResult } from '@/shared/types/types'
|
||||
import { getEffectiveSiteCode } from '@/stores/distributionSite'
|
||||
|
||||
export interface ChatParticipant {
|
||||
id: number
|
||||
@@ -94,10 +95,7 @@ export interface ChatMessage {
|
||||
}
|
||||
|
||||
export async function fetchChats(page = 1, pageSize = 20, distributionSiteCode?: string) {
|
||||
const siteCode =
|
||||
distributionSiteCode ||
|
||||
(typeof window !== 'undefined' ? localStorage.getItem('hfb_site_code') : '') ||
|
||||
undefined
|
||||
const siteCode = distributionSiteCode || getEffectiveSiteCode() || undefined
|
||||
const params: Record<string, unknown> = { page, page_size: pageSize }
|
||||
if (siteCode) {
|
||||
params.distribution_site_code = siteCode
|
||||
@@ -109,10 +107,7 @@ export async function fetchChats(page = 1, pageSize = 20, distributionSiteCode?:
|
||||
}
|
||||
|
||||
export async function fetchUnreadChatCount(distributionSiteCode?: string) {
|
||||
const siteCode =
|
||||
distributionSiteCode ||
|
||||
(typeof window !== 'undefined' ? localStorage.getItem('hfb_site_code') : '') ||
|
||||
undefined
|
||||
const siteCode = distributionSiteCode || getEffectiveSiteCode() || undefined
|
||||
const params: Record<string, unknown> = {}
|
||||
if (siteCode) {
|
||||
params.distribution_site_code = siteCode
|
||||
@@ -141,10 +136,7 @@ export async function ensureSupportChat(
|
||||
scene: SupportScene | string = 'general',
|
||||
distributionSiteCode?: string
|
||||
) {
|
||||
const siteCode =
|
||||
distributionSiteCode ||
|
||||
(typeof window !== 'undefined' ? localStorage.getItem('hfb_site_code') : '') ||
|
||||
undefined
|
||||
const siteCode = distributionSiteCode || getEffectiveSiteCode() || undefined
|
||||
const payload: { scene: string; distribution_site_code?: string } = {
|
||||
scene: scene || 'general',
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { apiClient } from '@/shared/api/client'
|
||||
import type { ApiResponse } from '@/shared/types/types'
|
||||
import { getEffectiveSiteCode } from '@/stores/distributionSite'
|
||||
import type { ListingReviewStatus, ListingStatus } from '@/shared/types/status'
|
||||
|
||||
export interface Listing {
|
||||
@@ -102,10 +103,7 @@ export async function fetchListings(query: PublicListingQuery = {}) {
|
||||
}
|
||||
|
||||
export async function fetchListingsPage(query: PublicListingQuery = {}) {
|
||||
const siteCode =
|
||||
query.distribution_site_code ||
|
||||
(typeof window !== 'undefined' ? localStorage.getItem('hfb_site_code') : '') ||
|
||||
undefined
|
||||
const siteCode = query.distribution_site_code || getEffectiveSiteCode() || undefined
|
||||
const effectiveQuery = siteCode ? { distribution_site_code: siteCode, ...query } : query
|
||||
const params = Object.fromEntries(
|
||||
Object.entries(effectiveQuery).filter(
|
||||
|
||||
@@ -2,6 +2,7 @@ import { apiClient } from '@/shared/api/client'
|
||||
import type { ApiResponse, PaginatedResult } from '@/shared/types/types'
|
||||
import type { HandoffStatus, OrderStatus, SettlementStatus } from '@/shared/types/status'
|
||||
import { yuanToCent } from '@/shared/utils/money'
|
||||
import { getEffectiveSiteCode } from '@/stores/distributionSite'
|
||||
|
||||
export interface Order {
|
||||
id: number
|
||||
@@ -320,10 +321,7 @@ export async function fetchPostRentalNotice() {
|
||||
}
|
||||
|
||||
export async function fetchOrders(page = 1, pageSize = 20, distributionSiteCode?: string) {
|
||||
const siteCode =
|
||||
distributionSiteCode ||
|
||||
(typeof window !== 'undefined' ? localStorage.getItem('hfb_site_code') : '') ||
|
||||
undefined
|
||||
const siteCode = distributionSiteCode || getEffectiveSiteCode() || undefined
|
||||
const params: Record<string, unknown> = { page, page_size: pageSize }
|
||||
if (siteCode) {
|
||||
params.distribution_site_code = siteCode
|
||||
@@ -352,10 +350,7 @@ export async function fetchSellerHandoffs(
|
||||
}
|
||||
|
||||
export async function fetchOrder(id: string | number, distributionSiteCode?: string) {
|
||||
const siteCode =
|
||||
distributionSiteCode ||
|
||||
(typeof window !== 'undefined' ? localStorage.getItem('hfb_site_code') : '') ||
|
||||
undefined
|
||||
const siteCode = distributionSiteCode || getEffectiveSiteCode() || undefined
|
||||
const params: Record<string, unknown> = {}
|
||||
if (siteCode) {
|
||||
params.distribution_site_code = siteCode
|
||||
@@ -365,10 +360,7 @@ export async function fetchOrder(id: string | number, distributionSiteCode?: str
|
||||
}
|
||||
|
||||
export async function createOrder(listingId: number, distributionSiteCode?: string) {
|
||||
const siteCode =
|
||||
distributionSiteCode ||
|
||||
(typeof window !== 'undefined' ? localStorage.getItem('hfb_site_code') : '') ||
|
||||
undefined
|
||||
const siteCode = distributionSiteCode || getEffectiveSiteCode() || undefined
|
||||
const payload: { listing_id: number; distribution_site_code?: string } = { listing_id: listingId }
|
||||
if (siteCode) {
|
||||
payload.distribution_site_code = siteCode
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { apiClient } from '@/shared/api/client'
|
||||
|
||||
import type { ApiResponse, PaginatedResult } from '@/shared/types/types'
|
||||
import { getEffectiveSiteCode } from '@/stores/distributionSite'
|
||||
import type { BalanceType, LedgerDirection, WalletStatus } from '@/shared/types/status'
|
||||
|
||||
export interface WalletAccount {
|
||||
@@ -28,10 +28,7 @@ export interface WalletLedger {
|
||||
}
|
||||
|
||||
export async function fetchWalletBalance(distributionSiteCode?: string) {
|
||||
const siteCode =
|
||||
distributionSiteCode ||
|
||||
(typeof window !== 'undefined' ? localStorage.getItem('hfb_site_code') : '') ||
|
||||
undefined
|
||||
const siteCode = distributionSiteCode || getEffectiveSiteCode() || undefined
|
||||
const params: Record<string, unknown> = {}
|
||||
if (siteCode) {
|
||||
params.distribution_site_code = siteCode
|
||||
@@ -41,10 +38,7 @@ export async function fetchWalletBalance(distributionSiteCode?: string) {
|
||||
}
|
||||
|
||||
export async function fetchWalletLedger(page = 1, pageSize = 20, distributionSiteCode?: string) {
|
||||
const siteCode =
|
||||
distributionSiteCode ||
|
||||
(typeof window !== 'undefined' ? localStorage.getItem('hfb_site_code') : '') ||
|
||||
undefined
|
||||
const siteCode = distributionSiteCode || getEffectiveSiteCode() || undefined
|
||||
const params: Record<string, unknown> = { page, page_size: pageSize }
|
||||
if (siteCode) {
|
||||
params.distribution_site_code = siteCode
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { apiClient } from '@/shared/api/client'
|
||||
|
||||
import type { ApiResponse, PaginatedResult } from '@/shared/types/types'
|
||||
import { getEffectiveSiteCode } from '@/stores/distributionSite'
|
||||
|
||||
// 收款账号类型
|
||||
export type AccountType = 'alipay' | 'wechat' | 'bank'
|
||||
@@ -116,11 +116,7 @@ export async function createWithdrawal(
|
||||
req: CreateWithdrawalRequest,
|
||||
distributionSiteCode?: string
|
||||
) {
|
||||
const siteCode =
|
||||
distributionSiteCode ||
|
||||
req.distribution_site_code ||
|
||||
(typeof window !== 'undefined' ? localStorage.getItem('hfb_site_code') : '') ||
|
||||
undefined
|
||||
const siteCode = distributionSiteCode || req.distribution_site_code || getEffectiveSiteCode() || undefined
|
||||
const payload: CreateWithdrawalRequest = { ...req }
|
||||
if (siteCode) {
|
||||
payload.distribution_site_code = siteCode
|
||||
@@ -130,10 +126,7 @@ export async function createWithdrawal(
|
||||
}
|
||||
|
||||
export async function fetchWithdrawals(page = 1, pageSize = 20, distributionSiteCode?: string) {
|
||||
const siteCode =
|
||||
distributionSiteCode ||
|
||||
(typeof window !== 'undefined' ? localStorage.getItem('hfb_site_code') : '') ||
|
||||
undefined
|
||||
const siteCode = distributionSiteCode || getEffectiveSiteCode() || undefined
|
||||
const params: Record<string, unknown> = { page, page_size: pageSize }
|
||||
if (siteCode) {
|
||||
params.distribution_site_code = siteCode
|
||||
|
||||
@@ -3,6 +3,7 @@ import { ElMessage } from 'element-plus'
|
||||
import { showToast } from 'vant'
|
||||
import { apiMonitor } from './monitor'
|
||||
import { debugError, debugLog } from '@/shared/utils/debug'
|
||||
import { getEffectiveSiteCode } from '@/stores/distributionSite'
|
||||
|
||||
function showError(message: string) {
|
||||
const isMobile = window.location.pathname.startsWith('/m')
|
||||
@@ -201,11 +202,9 @@ apiClient.interceptors.request.use(
|
||||
config.headers.Authorization = `Bearer ${token}`
|
||||
}
|
||||
|
||||
if (typeof window !== 'undefined') {
|
||||
const siteCode = localStorage.getItem('hfb_site_code')
|
||||
if (siteCode && !config.headers['X-Distribution-Site-Code']) {
|
||||
config.headers['X-Distribution-Site-Code'] = siteCode
|
||||
}
|
||||
const siteCode = getEffectiveSiteCode()
|
||||
if (siteCode && !config.headers['X-Distribution-Site-Code']) {
|
||||
config.headers['X-Distribution-Site-Code'] = siteCode
|
||||
}
|
||||
|
||||
// 记录请求日志
|
||||
|
||||
@@ -11,20 +11,52 @@ export interface DistributionSiteInfo {
|
||||
default_support_group_id?: number | null
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前上下文生效的分销站点编码
|
||||
* 优先级:
|
||||
* 1. 环境变量 VITE_DISTRIBUTION_SITE_CODE(针对独立分销前台开发端口,如 5191)
|
||||
* 2. 当前标签页 sessionStorage 中的 hfb_site_code(避免跨 Tab 污染主站)
|
||||
* 3. 本地二级域名(如 test_1.localhost:5189)
|
||||
* 4. 生产环境或独立域名绑定的 localStorage 缓存
|
||||
*/
|
||||
export function getEffectiveSiteCode(): string {
|
||||
if (typeof window === 'undefined') return ''
|
||||
const envCode = ((import.meta.env.VITE_DISTRIBUTION_SITE_CODE as string) || '').trim()
|
||||
if (envCode) return envCode
|
||||
|
||||
const sessionCode = sessionStorage.getItem('hfb_site_code') || ''
|
||||
if (sessionCode) return sessionCode
|
||||
|
||||
const hostname = window.location.hostname
|
||||
if (hostname && hostname.endsWith('.localhost')) {
|
||||
return hostname.replace(/\.localhost$/, '')
|
||||
}
|
||||
|
||||
if (hostname !== 'localhost' && hostname !== '127.0.0.1') {
|
||||
return localStorage.getItem('hfb_site_code') || ''
|
||||
}
|
||||
|
||||
return ''
|
||||
}
|
||||
|
||||
export const useDistributionSiteStore = defineStore('distributionSite', {
|
||||
state: () => ({
|
||||
siteCode: localStorage.getItem('hfb_site_code') || '',
|
||||
siteName: localStorage.getItem('hfb_site_name') || '大锤商行',
|
||||
domain: '',
|
||||
isDistribution: Boolean(localStorage.getItem('hfb_site_code')),
|
||||
displayAccountEnabled: true,
|
||||
defaultSupportGroupId: null as number | null,
|
||||
initialized: false,
|
||||
}),
|
||||
state: () => {
|
||||
const code = getEffectiveSiteCode()
|
||||
return {
|
||||
siteCode: code,
|
||||
siteName: sessionStorage.getItem('hfb_site_name') || '大锤商行',
|
||||
domain: '',
|
||||
isDistribution: Boolean(code),
|
||||
displayAccountEnabled: true,
|
||||
defaultSupportGroupId: null as number | null,
|
||||
initialized: false,
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
async initSite() {
|
||||
// 1. Check URL query params: ?site=xxx or ?site_code=xxx
|
||||
const envCode = ((import.meta.env.VITE_DISTRIBUTION_SITE_CODE as string) || '').trim()
|
||||
const hostname = window.location.hostname
|
||||
const urlParams = new URLSearchParams(window.location.search)
|
||||
const querySite = (
|
||||
urlParams.get('site') ||
|
||||
@@ -33,24 +65,37 @@ export const useDistributionSiteStore = defineStore('distributionSite', {
|
||||
''
|
||||
).trim()
|
||||
|
||||
// 1. 显式清除或重置为主站
|
||||
if (querySite === 'main' || querySite === 'clear' || querySite === '0') {
|
||||
this.resetToMainSite()
|
||||
this.initialized = true
|
||||
return
|
||||
}
|
||||
|
||||
// 2. 识别目标分销站点编码
|
||||
let targetCode = ''
|
||||
if (querySite) {
|
||||
if (querySite === 'main' || querySite === 'clear' || querySite === '0') {
|
||||
targetCode = querySite
|
||||
sessionStorage.setItem('hfb_site_code', querySite)
|
||||
} else if (envCode) {
|
||||
targetCode = envCode
|
||||
sessionStorage.setItem('hfb_site_code', envCode)
|
||||
} else if (hostname && hostname.endsWith('.localhost')) {
|
||||
targetCode = hostname.replace(/\.localhost$/, '')
|
||||
sessionStorage.setItem('hfb_site_code', targetCode)
|
||||
} else {
|
||||
targetCode = sessionStorage.getItem('hfb_site_code') || ''
|
||||
// 若在普通 localhost 且无 envCode、无 query、无 sessionStorage,则视为纯主站,清理旧的 localStorage 串扰
|
||||
if (!targetCode && (hostname === 'localhost' || hostname === '127.0.0.1')) {
|
||||
this.resetToMainSite()
|
||||
this.initialized = true
|
||||
return
|
||||
}
|
||||
this.siteCode = querySite
|
||||
localStorage.setItem('hfb_site_code', querySite)
|
||||
}
|
||||
|
||||
const effectiveCode = this.siteCode || localStorage.getItem('hfb_site_code') || ''
|
||||
const hostname = window.location.hostname
|
||||
|
||||
// If we have a site code, query by code.
|
||||
// Otherwise query by domain (for independent domain access in production).
|
||||
let queryUrl = ''
|
||||
if (effectiveCode) {
|
||||
queryUrl = `/distribution/site-info?code=${encodeURIComponent(effectiveCode)}`
|
||||
if (targetCode) {
|
||||
queryUrl = `/distribution/site-info?code=${encodeURIComponent(targetCode)}`
|
||||
} else if (hostname && hostname !== 'localhost' && hostname !== '127.0.0.1') {
|
||||
queryUrl = `/distribution/site-info?domain=${encodeURIComponent(hostname)}`
|
||||
}
|
||||
@@ -75,16 +120,16 @@ export const useDistributionSiteStore = defineStore('distributionSite', {
|
||||
this.displayAccountEnabled = info.display_account_enabled ?? true
|
||||
this.defaultSupportGroupId = info.default_support_group_id ?? null
|
||||
|
||||
localStorage.setItem('hfb_site_code', this.siteCode)
|
||||
localStorage.setItem('hfb_site_name', this.siteName)
|
||||
sessionStorage.setItem('hfb_site_code', this.siteCode)
|
||||
sessionStorage.setItem('hfb_site_name', this.siteName)
|
||||
|
||||
// Update page title
|
||||
// 更新页面标题
|
||||
document.title = `【${this.siteName}】租号商城 - 精选游戏账号平台`
|
||||
} else {
|
||||
this.resetToMainSite()
|
||||
}
|
||||
} catch {
|
||||
// If site code was invalid or not found, fall back to main site
|
||||
// 若站点编码无效或未找到,自动回退为主站
|
||||
this.resetToMainSite()
|
||||
} finally {
|
||||
this.initialized = true
|
||||
@@ -98,6 +143,8 @@ export const useDistributionSiteStore = defineStore('distributionSite', {
|
||||
this.isDistribution = false
|
||||
this.displayAccountEnabled = true
|
||||
this.defaultSupportGroupId = null
|
||||
sessionStorage.removeItem('hfb_site_code')
|
||||
sessionStorage.removeItem('hfb_site_name')
|
||||
localStorage.removeItem('hfb_site_code')
|
||||
localStorage.removeItem('hfb_site_name')
|
||||
document.title = '大锤商行 - 官方租号平台'
|
||||
|
||||
+47
-4
@@ -20,6 +20,8 @@ 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}"
|
||||
DISTRIBUTION_STOREFRONT_PORT="${DEV_DISTRIBUTION_STOREFRONT_PORT:-5191}"
|
||||
DISTRIBUTION_STOREFRONT_SITE_CODE="${DEV_DISTRIBUTION_STOREFRONT_SITE_CODE:-test_1}"
|
||||
MYSQL_PORT="${DEV_MYSQL_PORT:-13306}"
|
||||
REDIS_PORT="${DEV_REDIS_PORT:-16379}"
|
||||
MINIO_API_PORT="${DEV_MINIO_API_PORT:-19090}"
|
||||
@@ -27,6 +29,7 @@ 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}/}"
|
||||
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}"
|
||||
AUTO_KILL_PORTS="${DEV_AUTO_KILL_PORTS:-1}"
|
||||
FORCE_NPM_CI="${DEV_FORCE_NPM_CI:-0}"
|
||||
@@ -36,6 +39,7 @@ GOOSE_BIN="${GOOSE_BIN:-}"
|
||||
BACKEND_PID=""
|
||||
FRONTEND_PID=""
|
||||
DISTRIBUTION_PID=""
|
||||
DISTRIBUTION_STOREFRONT_PID=""
|
||||
CLEANED_UP=0
|
||||
|
||||
# 颜色定义
|
||||
@@ -78,6 +82,8 @@ show_help() {
|
||||
--no-frontend 不启动主站前端
|
||||
--no-backend 不启动后端
|
||||
--no-distribution 不启动分销后台
|
||||
--no-distribution-storefront
|
||||
不启动分销前台商城
|
||||
-h, --help 显示帮助信息
|
||||
|
||||
环境变量:
|
||||
@@ -124,6 +130,7 @@ NO_MIGRATE=0
|
||||
NO_FRONTEND=0
|
||||
NO_BACKEND=0
|
||||
NO_DISTRIBUTION=0
|
||||
NO_DISTRIBUTION_STOREFRONT=0
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
@@ -147,6 +154,10 @@ while [[ $# -gt 0 ]]; do
|
||||
NO_DISTRIBUTION=1
|
||||
shift
|
||||
;;
|
||||
--no-distribution-storefront)
|
||||
NO_DISTRIBUTION_STOREFRONT=1
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
show_help
|
||||
;;
|
||||
@@ -163,11 +174,14 @@ cleanup() {
|
||||
fi
|
||||
CLEANED_UP=1
|
||||
|
||||
if [[ -z "${FRONTEND_PID}" && -z "${BACKEND_PID}" && -z "${DISTRIBUTION_PID}" ]]; then
|
||||
if [[ -z "${FRONTEND_PID}" && -z "${BACKEND_PID}" && -z "${DISTRIBUTION_PID}" && -z "${DISTRIBUTION_STOREFRONT_PID}" ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
log "正在停止前后端开发进程..."
|
||||
if [[ -n "${DISTRIBUTION_STOREFRONT_PID}" ]] && kill -0 "${DISTRIBUTION_STOREFRONT_PID}" >/dev/null 2>&1; then
|
||||
kill "${DISTRIBUTION_STOREFRONT_PID}" >/dev/null 2>&1 || true
|
||||
fi
|
||||
if [[ -n "${DISTRIBUTION_PID}" ]] && kill -0 "${DISTRIBUTION_PID}" >/dev/null 2>&1; then
|
||||
kill "${DISTRIBUTION_PID}" >/dev/null 2>&1 || true
|
||||
fi
|
||||
@@ -619,6 +633,21 @@ start_distribution() {
|
||||
DISTRIBUTION_PID="$!"
|
||||
}
|
||||
|
||||
start_distribution_storefront() {
|
||||
ensure_frontend_dependencies
|
||||
|
||||
log "启动分销前台:http://localhost:${DISTRIBUTION_STOREFRONT_PORT} (分销站: ${DISTRIBUTION_STOREFRONT_SITE_CODE})"
|
||||
(
|
||||
cd "${FRONTEND_DIR}"
|
||||
export DEV_FRONTEND_PORT="${DISTRIBUTION_STOREFRONT_PORT}"
|
||||
export DEV_BACKEND_PORT="${BACKEND_PORT}"
|
||||
export VITE_API_PROXY_TARGET="${VITE_API_PROXY_TARGET:-http://127.0.0.1:${BACKEND_PORT}}"
|
||||
export VITE_DISTRIBUTION_SITE_CODE="${DISTRIBUTION_STOREFRONT_SITE_CODE}"
|
||||
npm run dev
|
||||
) &
|
||||
DISTRIBUTION_STOREFRONT_PID="$!"
|
||||
}
|
||||
|
||||
watch_processes() {
|
||||
while true; do
|
||||
if [[ -n "${BACKEND_PID}" ]] && ! kill -0 "${BACKEND_PID}" >/dev/null 2>&1; then
|
||||
@@ -636,6 +665,11 @@ watch_processes() {
|
||||
printf "分销后台进程已退出\n" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ -n "${DISTRIBUTION_STOREFRONT_PID}" ]] && ! kill -0 "${DISTRIBUTION_STOREFRONT_PID}" >/dev/null 2>&1; then
|
||||
wait "${DISTRIBUTION_STOREFRONT_PID}" || true
|
||||
printf "分销前台商城进程已退出\n" >&2
|
||||
exit 1
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
}
|
||||
@@ -698,7 +732,13 @@ main() {
|
||||
wait_http_ready "${DISTRIBUTION_HEALTH_URL}" "分销后台" "${DISTRIBUTION_PID}"
|
||||
fi
|
||||
|
||||
if [[ -z "${BACKEND_PID}" && -z "${FRONTEND_PID}" && -z "${DISTRIBUTION_PID}" ]]; then
|
||||
if [[ "${NO_DISTRIBUTION_STOREFRONT}" == "0" && "${NO_FRONTEND}" == "0" ]]; then
|
||||
ensure_port_free "${DISTRIBUTION_STOREFRONT_PORT}" "分销前台"
|
||||
start_distribution_storefront
|
||||
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 开发依赖,前后端与分销端未启动"
|
||||
return 0
|
||||
fi
|
||||
@@ -706,12 +746,15 @@ main() {
|
||||
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
|
||||
if [[ "${NO_DISTRIBUTION_STOREFRONT}" == "0" && "${NO_FRONTEND}" == "0" ]]; then
|
||||
log "分销前台:http://localhost:${DISTRIBUTION_STOREFRONT_PORT} (直连分销站: ${DISTRIBUTION_STOREFRONT_SITE_CODE})"
|
||||
fi
|
||||
|
||||
log "按 Ctrl+C 停止所有服务;Docker 依赖会保留运行"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user