feat: hot reload

This commit is contained in:
2025-12-17 09:32:05 +08:00
parent e8b2699104
commit f2b53967eb
7 changed files with 95 additions and 32 deletions

View File

@@ -7,6 +7,11 @@ FRONTEND_SUPERADMIN_DIR := frontend/superadmin
ATOMCTL ?= atomctl
ADMIN_DEV_PORT ?= 5173
USER_DEV_PORT ?= 5174
SUPER_DEV_PORT ?= 5175
BACKEND_DEV_PORT ?= 8080
TENANT_CODE ?= demo
TENANT_NAME ?= Demo Tenant
TENANT_UUID ?= $(shell python3 -c 'import uuid; print(uuid.uuid4())' 2>/dev/null || uuidgen 2>/dev/null || echo "00000000-0000-0000-0000-000000000000")
@@ -20,10 +25,16 @@ help:
@printf "%s\n" " make build-frontend Build admin+user frontends (requires npm)"
@printf "%s\n" " make serve Run backend server (serves built dist)"
@printf "%s\n" " make preview build + serve"
@printf "%s\n" " make dev Run air + 3 vite dev servers"
@printf "%s\n" ""
@printf "%s\n" "Preview URLs (after make preview):"
@printf "%s\n" " User : http://localhost:8080/t/$(TENANT_CODE)/"
@printf "%s\n" " Admin: http://localhost:8080/t/$(TENANT_CODE)/admin/"
@printf "%s\n" ""
@printf "%s\n" "Dev URLs (after make dev):"
@printf "%s\n" " Super: http://localhost:$(SUPER_DEV_PORT)/super/"
@printf "%s\n" " Admin: http://localhost:$(ADMIN_DEV_PORT)/t/$(TENANT_CODE)/admin/"
@printf "%s\n" " User : http://localhost:$(USER_DEV_PORT)/t/$(TENANT_CODE)/"
.PHONY: migrate
migrate:
@@ -66,3 +77,30 @@ serve:
.PHONY: preview
preview: build-frontend serve
.PHONY: dev-backend
dev-backend:
@cd $(BACKEND_DIR) && command -v air >/dev/null 2>&1 || (echo "air not found: go install github.com/air-verse/air@latest" && exit 1)
@cd $(BACKEND_DIR) && air -c .air.toml
.PHONY: dev-admin
dev-admin:
@cd $(FRONTEND_ADMIN_DIR) && npm run dev -- --host 0.0.0.0 --port $(ADMIN_DEV_PORT) --strictPort
.PHONY: dev-user
dev-user:
@cd $(FRONTEND_USER_DIR) && npm run dev -- --host 0.0.0.0 --port $(USER_DEV_PORT) --strictPort
.PHONY: dev-superadmin
dev-superadmin:
@cd $(FRONTEND_SUPERADMIN_DIR) && npm run dev -- --host 0.0.0.0 --port $(SUPER_DEV_PORT) --strictPort
.PHONY: dev
dev:
@set -e; \
trap 'kill 0' INT TERM EXIT; \
$(MAKE) dev-backend & \
$(MAKE) dev-admin & \
$(MAKE) dev-user & \
$(MAKE) dev-superadmin & \
wait

View File

@@ -1,40 +1,39 @@
# .air.toml - Air 热重载配置文件
root = "."
testdata_dir = "testdata"
tmp_dir = "tmp"
[build]
args_bin = []
bin = "./tmp/main"
cmd = "go build -o ./tmp/main ."
delay = 1000
exclude_dir = ["assets", "tmp", "vendor", "testdata", "frontend"]
exclude_file = []
exclude_regex = ["_test.go"]
exclude_unchanged = false
follow_symlink = false
full_bin = ""
include_dir = []
include_ext = ["go", "tpl", "tmpl", "html", "yaml", "yml", "toml"]
kill_delay = "0s"
log = "build-errors.log"
send_interrupt = false
stop_on_root = false
args_bin = ["serve"]
bin = "./tmp/main"
cmd = "go build -o ./tmp/main ."
delay = 1000
exclude_dir = ["assets", "tmp", "vendor", "testdata", "frontend"]
exclude_file = []
exclude_regex = ["_test.go"]
exclude_unchanged = false
follow_symlink = false
full_bin = ""
include_dir = []
include_ext = ["go", "tpl", "tmpl", "html", "yaml", "yml", "toml"]
kill_delay = "0s"
log = "build-errors.log"
send_interrupt = false
stop_on_root = false
[color]
app = ""
build = "yellow"
main = "magenta"
runner = "green"
watcher = "cyan"
app = ""
build = "yellow"
main = "magenta"
runner = "green"
watcher = "cyan"
[log]
time = false
time = false
[misc]
clean_on_exit = false
clean_on_exit = false
[screen]
clear_on_rebuild = false
keep_scroll = true
clear_on_rebuild = false
keep_scroll = true

View File

@@ -22,6 +22,31 @@ Port = 8080
# Host = "0.0.0.0"
# 全局路由前缀(可选)
# BaseURI = "/api/v1"
[Http.Cors]
# dev CORS for Vite dev servers
Mode = "dev"
[[Http.Cors.Whitelist]]
AllowOrigin = "http://localhost:5173"
AllowHeaders = "Content-Type,Authorization"
AllowMethods = "GET,POST,PUT,PATCH,DELETE,OPTIONS"
ExposeHeaders = "*"
AllowCredentials = true
[[Http.Cors.Whitelist]]
AllowOrigin = "http://localhost:5174"
AllowHeaders = "Content-Type,Authorization"
AllowMethods = "GET,POST,PUT,PATCH,DELETE,OPTIONS"
ExposeHeaders = "*"
AllowCredentials = true
[[Http.Cors.Whitelist]]
AllowOrigin = "http://localhost:5175"
AllowHeaders = "Content-Type,Authorization"
AllowMethods = "GET,POST,PUT,PATCH,DELETE,OPTIONS"
ExposeHeaders = "*"
AllowCredentials = true
# =========================
# 数据库配置
# =========================

View File

@@ -11,6 +11,6 @@ export function getAdminRouterBase(pathname = window.location.pathname): string
export function getApiBaseURL(pathname = window.location.pathname): string {
const tenantCode = getTenantCodeFromPath(pathname)
return `/t/${tenantCode}/v1`
const origin = import.meta.env.DEV ? 'http://localhost:8080' : ''
return `${origin}/t/${tenantCode}/v1`
}

View File

@@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>QuyUn Super Admin</title>
<script type="module" crossorigin src="./assets/index-CHzhCW76.js"></script>
<script type="module" crossorigin src="./assets/index-BJ_2zMy4.js"></script>
<link rel="stylesheet" crossorigin href="./assets/index-B1dbpKz4.css">
</head>
<body>

View File

@@ -1,7 +1,8 @@
import axios from 'axios'
import { getToken, setToken } from './auth'
export const api = axios.create({ baseURL: '/super/v1' })
const baseURL = import.meta.env.DEV ? 'http://localhost:8080/super/v1' : '/super/v1'
export const api = axios.create({ baseURL })
api.interceptors.request.use((config) => {
const token = getToken()

View File

@@ -11,6 +11,6 @@ export function getUserRouterBase(pathname = window.location.pathname): string {
export function getApiBaseURL(pathname = window.location.pathname): string {
const tenantCode = getTenantCodeFromPath(pathname)
return `/t/${tenantCode}/v1`
const origin = import.meta.env.DEV ? 'http://localhost:8080' : ''
return `${origin}/t/${tenantCode}/v1`
}