20261008-ide1.0发布 #1

Merged
zzh merged 24 commits from test into master 2026-10-08 09:19:21 +08:00
4 changed files with 42 additions and 9 deletions
Showing only changes of commit 1bc2838def - Show all commits

View File

@ -1,6 +1,7 @@
# 复制到 itfx-front 仓库 .gitea/workflows/deploy.yml
# push master → prod;push test → test
# 构建始终用 prod kubeconfig(Kaniko);仅 deploy 切集群
# 前端镜像:test 分支须传 FRONT_BUILD_SCRIPT=build:test,否则会打进正式 API 域名
name: Build and Deploy Front
on:
@ -38,6 +39,12 @@ jobs:
IMG="${{ env.TCR_REGISTRY }}/${{ env.TCR_NAMESPACE }}/${{ env.IMAGE_NAME }}:${TAG}"
echo "TARGET=$TARGET REF=$REF REPO=$REPO TAG=$TAG host=$(hostname)"
case "$TARGET" in
test) export FRONT_BUILD_SCRIPT=build:test ;;
*) export FRONT_BUILD_SCRIPT=build ;;
esac
echo "FRONT_BUILD_SCRIPT=$FRONT_BUILD_SCRIPT"
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
unset NAMESPACE
cd /data/k3s

View File

@ -1,8 +1,12 @@
# k3s / Kaniko:静态 SPA(方案 A)。API 由浏览器按站点域名直连
# test.ideship.com → api.test.ideship.com;其余 → api.ideship.com
# 镜像内 nginx 不做反代;也可用构建期 VITE_API_ORIGIN / VITE_API_ADMIN_URL 覆盖
# FRONT_BUILD_SCRIPT:
# prod 默认 build(.env.production → api.ideship.com)
# test 传 build:test(.env.ideship-test → api.test.ideship.com)
# 即使误用 production 构建,运行时也会按 hostname 纠正到测试 API。
FROM docker.m.daocloud.io/library/node:20-alpine AS build
WORKDIR /app
ARG FRONT_BUILD_SCRIPT=build
RUN npm config set registry https://registry.npmmirror.com \
&& npm install -g pnpm@9.15.9
COPY package.json pnpm-lock.yaml ./
@ -10,7 +14,7 @@ COPY package.json pnpm-lock.yaml ./
RUN pnpm config set registry https://registry.npmmirror.com \
&& pnpm install --frozen-lockfile --ignore-scripts
COPY . .
RUN pnpm run build
RUN pnpm run ${FRONT_BUILD_SCRIPT}
FROM docker.m.daocloud.io/library/nginx:1.27-alpine
COPY --from=build /app/dist /usr/share/nginx/html/

View File

@ -2,9 +2,12 @@
* Admin API 地址(方案 A)
* - 开发:相对路径,Vite 代理到 Admin
* - 生产/测试:{apiOrigin}/admin(可用 VITE_API_ADMIN_URL 覆盖)
* - 浏览器在 test.ideship.com 时强制 api.test.ideship.com/admin
*/
import { prodApiOrigin } from './rewriteBrowserApiPath'
import { isTestFrontHost, prodApiOrigin } from './rewriteBrowserApiPath'
const DEFAULT_TEST_ADMIN = 'https://api.test.ideship.com/admin'
function normalizeBase(base: string): string {
return base.trim().replace(/\/$/, '')
@ -14,7 +17,14 @@ function ensureLeadingSlash(path: string): string {
return path.startsWith('/') ? path : `/${path}`
}
function isBrowserOnTestFront(): boolean {
return typeof window !== 'undefined' && isTestFrontHost(window.location.hostname)
}
function prodAdminBase(): string {
if (isBrowserOnTestFront()) {
return DEFAULT_TEST_ADMIN
}
const override = import.meta.env.VITE_API_ADMIN_URL as string | undefined
if (override?.trim()) return normalizeBase(override)
return `${prodApiOrigin()}/admin`
@ -38,12 +48,15 @@ export function resolveOpenApiBase(): string {
/** 桌面 Agent 等直连 Admin 网关 */
export function resolveDirectAdminApiUrl(): string {
if (isBrowserOnTestFront()) {
return DEFAULT_TEST_ADMIN
}
const override = import.meta.env.VITE_API_ADMIN_URL as string | undefined
if (override?.trim()) {
return normalizeBase(override)
}
if (import.meta.env.DEV) {
return 'https://api.test.ideship.com/admin'
return DEFAULT_TEST_ADMIN
}
return prodAdminBase()
}
@ -52,6 +65,9 @@ export function resolveDirectAdminApiUrl(): string {
* 生产/测试默认 api 域名;开发空串走 Vite `/uploads` 代理。
*/
export function resolveAdminAssetOrigin(): string {
if (isBrowserOnTestFront()) {
return DEFAULT_TEST_ADMIN
}
const override = import.meta.env.VITE_API_ASSET_ORIGIN as string | undefined
if (override?.trim()) {
return normalizeBase(override)

View File

@ -2,7 +2,8 @@
* 方案 A:浏览器直连 API 网关 PATHBASE;开发仍走 Vite 代理旧路径。
* - prod:https://api.ideship.com
* - test(test.ideship.com):https://api.test.ideship.com
* - 可用 VITE_API_ORIGIN 覆盖
* - 浏览器在测试站点时优先按域名判定(避免 test 镜像误用 production 环境变量打成正式 API)
* - 非测试站点可用 VITE_API_ORIGIN 覆盖
*/
const SPA_API_PREFIXES = [
@ -21,7 +22,7 @@ const SPA_API_PREFIXES = [
const DEFAULT_PROD_API = 'https://api.ideship.com'
const DEFAULT_TEST_API = 'https://api.test.ideship.com'
function isTestFrontHost(hostname: string): boolean {
export function isTestFrontHost(hostname: string): boolean {
return (
hostname === 'test.ideship.com' ||
hostname === 'app.test.ideship.com' || // 旧域名兼容
@ -29,13 +30,18 @@ function isTestFrontHost(hostname: string): boolean {
)
}
function isBrowserOnTestFront(): boolean {
return typeof window !== 'undefined' && isTestFrontHost(window.location.hostname)
}
/** 生产/测试 API 根(无尾斜杠) */
export function prodApiOrigin(): string {
const override = (import.meta.env.VITE_API_ORIGIN as string | undefined)?.trim()
if (override) return override.replace(/\/$/, '')
if (typeof window !== 'undefined' && isTestFrontHost(window.location.hostname)) {
// 测试站点强制走测试 API,不被错误打进包的 VITE_API_ORIGIN 覆盖
if (isBrowserOnTestFront()) {
return DEFAULT_TEST_API
}
const override = (import.meta.env.VITE_API_ORIGIN as string | undefined)?.trim()
if (override) return override.replace(/\/$/, '')
return DEFAULT_PROD_API
}