20261008-ide1.0发布 #1
@ -1,8 +1,9 @@
|
||||
# VITE_API_BASE_URL='http://localhost:5173/'
|
||||
|
||||
# 本地开发统一走线上 Admin API(与 /rbac、/order 等 Vite 代理一致)
|
||||
VITE_OMS_ADMIN_URL=http://api.nanafa.com/admin
|
||||
VITE_API_ADMIN_URL=http://api.nanafa.com/admin
|
||||
# 本地开发统一走测试环境 API(与 /rbac、/order、/api 等 Vite 代理一致)
|
||||
VITE_API_ORIGIN=https://api.test.ideship.com
|
||||
VITE_OMS_ADMIN_URL=https://api.test.ideship.com/admin
|
||||
VITE_API_ADMIN_URL=https://api.test.ideship.com/admin
|
||||
|
||||
# 智谱 AI(接口映射脚本生成)
|
||||
# 在 https://open.bigmodel.cn 申请 API Key
|
||||
|
||||
@ -1,12 +1,11 @@
|
||||
# 复制到 itfx-front 仓库 .gitea/workflows/deploy.yml
|
||||
# 前置: kaniko-git + kaniko-docker-config;act_runner(k3s-host) 只负责 kubectl
|
||||
# 构建在集群 Kaniko Job(role=build),不跑宿主机 Docker
|
||||
# push master → prod;push test → test
|
||||
# 构建始终用 prod kubeconfig(Kaniko);仅 deploy 切集群
|
||||
name: Build and Deploy Front
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master, main]
|
||||
workflow_dispatch:
|
||||
branches: [master, test]
|
||||
|
||||
env:
|
||||
IMAGE_NAME: itfx-front
|
||||
@ -20,13 +19,45 @@ jobs:
|
||||
- name: Build and deploy
|
||||
run: |
|
||||
set -euxo pipefail
|
||||
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
|
||||
TAG="${{ gitea.sha }}"
|
||||
IMG="${{ env.TCR_REGISTRY }}/${{ env.TCR_NAMESPACE }}/${{ env.IMAGE_NAME }}:${TAG}"
|
||||
REF="${{ gitea.ref_name }}"
|
||||
case "$REF" in
|
||||
test) TARGET=test ;;
|
||||
master) TARGET=prod ;;
|
||||
*) echo "unsupported branch: $REF"; exit 1 ;;
|
||||
esac
|
||||
|
||||
SHA="${{ gitea.sha }}"
|
||||
REPO="${{ gitea.repository }}"
|
||||
REPO="${REPO:-${{ github.repository }}}"
|
||||
test -n "$REPO" && [[ "$REPO" == */* ]]
|
||||
echo "REPO=$REPO TAG=$TAG host=$(hostname)"
|
||||
|
||||
case "$TARGET" in
|
||||
test) TAG="test-${SHA}" ;;
|
||||
*) TAG="${SHA}" ;;
|
||||
esac
|
||||
|
||||
IMG="${{ env.TCR_REGISTRY }}/${{ env.TCR_NAMESPACE }}/${{ env.IMAGE_NAME }}:${TAG}"
|
||||
echo "TARGET=$TARGET REF=$REF REPO=$REPO TAG=$TAG host=$(hostname)"
|
||||
|
||||
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
|
||||
unset NAMESPACE
|
||||
cd /data/k3s
|
||||
./scripts/ci-publish-front.sh "$REPO" "${{ env.IMAGE_NAME }}" "$TAG" "$TAG"
|
||||
./scripts/ci-publish-front.sh "$REPO" "${{ env.IMAGE_NAME }}" "$TAG" "$SHA"
|
||||
|
||||
case "$TARGET" in
|
||||
test)
|
||||
export KUBECONFIG=/etc/rancher/k3s/k3s-test.yaml
|
||||
export NAMESPACE=test
|
||||
export MANIFEST_ROOT=/data/k3s-test
|
||||
;;
|
||||
*)
|
||||
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
|
||||
export NAMESPACE=prod
|
||||
export MANIFEST_ROOT=/data/k3s
|
||||
;;
|
||||
esac
|
||||
if [[ ! -f "$KUBECONFIG" ]]; then
|
||||
echo "FAIL: missing KUBECONFIG=$KUBECONFIG host=$(hostname) uid=$(id -u)"
|
||||
ls -la /etc/rancher/k3s/ /root/.kube/ 2>/dev/null || true
|
||||
exit 1
|
||||
fi
|
||||
./scripts/ci-deploy-front.sh "$IMG"
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
# k3s / Kaniko:静态 SPA(方案 A)。API 直连 api.ideship.com,镜像内 nginx 不做反代
|
||||
# 基础镜像走 DaoCloud,避免 Kaniko 直连 docker.io 超时
|
||||
# k3s / Kaniko:静态 SPA(方案 A)。API 由浏览器按站点域名直连
|
||||
# app.test.ideship.com → api.test.ideship.com;其余 → api.ideship.com
|
||||
# 镜像内 nginx 不做反代;也可用构建期 VITE_API_ORIGIN / VITE_API_ADMIN_URL 覆盖
|
||||
FROM docker.m.daocloud.io/library/node:20-alpine AS build
|
||||
WORKDIR /app
|
||||
RUN npm config set registry https://registry.npmmirror.com \
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# k3s 方案 A:仅静态 SPA。API 由浏览器直连 api.ideship.com(本文件不做反代)。
|
||||
# k3s 方案 A:仅静态 SPA。API 由浏览器按域名直连(prod: api.ideship.com / test: api.test.ideship.com)。
|
||||
server {
|
||||
listen 80;
|
||||
server_name _;
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
import { getMethodText } from '@/views/api/upstreamInterface/utils';
|
||||
import { useTabRowCounts } from '@/utils/useTabRowCounts';
|
||||
import RequestLog from '@/views/api/requestLog/index.vue';
|
||||
import { prodApiOrigin } from '@/utils/rewriteBrowserApiPath';
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
@ -1336,21 +1337,29 @@
|
||||
|
||||
/**
|
||||
* 开发态:把已知外域 URL 改写到 Vite 代理,避免浏览器 CORS。
|
||||
* - api.nanafa.com → /nanafa/...
|
||||
* - api.nanafa.com / api(.test).ideship.com → /nanafa/...
|
||||
* - 旧 itfx IP → /api/...
|
||||
* - lsp.globex.cn → /external/...
|
||||
* 生产:nanafa 旧址改写到 api.ideship.com(方案 A)
|
||||
* 生产/测试构建:nanafa 旧址改写到当前环境 API 根(方案 A)
|
||||
*/
|
||||
function rewriteDebuggerUrlForProxy(rawUrl: string): string {
|
||||
const url = String(rawUrl || '').trim();
|
||||
if (!url) return url;
|
||||
const apiOrigin = prodApiOrigin();
|
||||
|
||||
// http(s)://api.nanafa.com/...
|
||||
if (/^https?:\/\/api\.nanafa\.com(?::\d+)?(\/|$)/i.test(url)) {
|
||||
// http(s)://api.nanafa.com/... 或 api(.test).ideship.com/...
|
||||
if (/^https?:\/\/api\.(?:nanafa|ideship)\.com(?::\d+)?(\/|$)/i.test(url)
|
||||
|| /^https?:\/\/api\.test\.ideship\.com(?::\d+)?(\/|$)/i.test(url)) {
|
||||
if (import.meta.env.DEV) {
|
||||
return url.replace(/^https?:\/\/api\.nanafa\.com(?::\d+)?/i, '/nanafa');
|
||||
return url
|
||||
.replace(/^https?:\/\/api\.nanafa\.com(?::\d+)?/i, '/nanafa')
|
||||
.replace(/^https?:\/\/api\.test\.ideship\.com(?::\d+)?/i, '/nanafa')
|
||||
.replace(/^https?:\/\/api\.ideship\.com(?::\d+)?/i, '/nanafa');
|
||||
}
|
||||
return url.replace(/^https?:\/\/api\.nanafa\.com(?::\d+)?/i, 'https://api.ideship.com');
|
||||
return url
|
||||
.replace(/^https?:\/\/api\.nanafa\.com(?::\d+)?/i, apiOrigin)
|
||||
.replace(/^https?:\/\/api\.test\.ideship\.com(?::\d+)?/i, apiOrigin)
|
||||
.replace(/^https?:\/\/api\.ideship\.com(?::\d+)?/i, apiOrigin);
|
||||
}
|
||||
|
||||
// 旧 itfx 直连 IP
|
||||
@ -1358,7 +1367,7 @@
|
||||
if (import.meta.env.DEV) {
|
||||
return url.replace('http://43.139.210.35:8888', '/api');
|
||||
}
|
||||
return url.replace('http://43.139.210.35:8888', 'https://api.ideship.com/itfx');
|
||||
return url.replace('http://43.139.210.35:8888', `${apiOrigin}/itfx`);
|
||||
}
|
||||
|
||||
// 示例外部服务商
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
/**
|
||||
* Admin API 地址(方案 A)
|
||||
* - 开发:相对路径,Vite 代理到 Admin
|
||||
* - 生产:直连 https://api.ideship.com/admin(可用 VITE_API_ADMIN_URL 覆盖)
|
||||
* - 生产/测试:{apiOrigin}/admin(可用 VITE_API_ADMIN_URL 覆盖)
|
||||
*/
|
||||
|
||||
import { prodApiOrigin } from './rewriteBrowserApiPath'
|
||||
|
||||
function normalizeBase(base: string): string {
|
||||
return base.trim().replace(/\/$/, '')
|
||||
}
|
||||
@ -12,12 +14,10 @@ function ensureLeadingSlash(path: string): string {
|
||||
return path.startsWith('/') ? path : `/${path}`
|
||||
}
|
||||
|
||||
const DEFAULT_PROD_ADMIN = 'https://api.ideship.com/admin'
|
||||
|
||||
function prodAdminBase(): string {
|
||||
const override = import.meta.env.VITE_API_ADMIN_URL as string | undefined
|
||||
if (override?.trim()) return normalizeBase(override)
|
||||
return DEFAULT_PROD_ADMIN
|
||||
return `${prodApiOrigin()}/admin`
|
||||
}
|
||||
|
||||
/** 浏览器请求 Admin API(OpenAPI.BASE 或 omsUrl/orderUrl 等) */
|
||||
@ -43,13 +43,13 @@ export function resolveDirectAdminApiUrl(): string {
|
||||
return normalizeBase(override)
|
||||
}
|
||||
if (import.meta.env.DEV) {
|
||||
return 'http://api.nanafa.com/admin'
|
||||
return 'https://api.test.ideship.com/admin'
|
||||
}
|
||||
return DEFAULT_PROD_ADMIN
|
||||
return prodAdminBase()
|
||||
}
|
||||
|
||||
/** 静态资源(uploads)在 Admin wwwroot,须带 `/admin`。
|
||||
* 生产默认 api 域名;开发空串走 Vite `/uploads` 代理。
|
||||
* 生产/测试默认 api 域名;开发空串走 Vite `/uploads` 代理。
|
||||
*/
|
||||
export function resolveAdminAssetOrigin(): string {
|
||||
const override = import.meta.env.VITE_API_ASSET_ORIGIN as string | undefined
|
||||
@ -57,7 +57,7 @@ export function resolveAdminAssetOrigin(): string {
|
||||
return normalizeBase(override)
|
||||
}
|
||||
if (!import.meta.env.DEV) {
|
||||
return DEFAULT_PROD_ADMIN
|
||||
return prodAdminBase()
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
/**
|
||||
* 方案 A:生产直连 api.ideship.com PATHBASE;开发仍走 Vite 代理旧路径。
|
||||
* 方案 A:浏览器直连 API 网关 PATHBASE;开发仍走 Vite 代理旧路径。
|
||||
* - prod:https://api.ideship.com
|
||||
* - test(app.test.ideship.com):https://api.test.ideship.com
|
||||
* - 可用 VITE_API_ORIGIN 覆盖
|
||||
*/
|
||||
|
||||
const SPA_API_PREFIXES = [
|
||||
@ -16,10 +19,19 @@ const SPA_API_PREFIXES = [
|
||||
] as const
|
||||
|
||||
const DEFAULT_PROD_API = 'https://api.ideship.com'
|
||||
const DEFAULT_TEST_API = 'https://api.test.ideship.com'
|
||||
|
||||
function prodApiOrigin(): string {
|
||||
/** 生产/测试 API 根(无尾斜杠) */
|
||||
export function prodApiOrigin(): string {
|
||||
const override = (import.meta.env.VITE_API_ORIGIN as string | undefined)?.trim()
|
||||
return (override || DEFAULT_PROD_API).replace(/\/$/, '')
|
||||
if (override) return override.replace(/\/$/, '')
|
||||
if (typeof window !== 'undefined') {
|
||||
const h = window.location.hostname
|
||||
if (h === 'app.test.ideship.com' || h.endsWith('.test.ideship.com')) {
|
||||
return DEFAULT_TEST_API
|
||||
}
|
||||
}
|
||||
return DEFAULT_PROD_API
|
||||
}
|
||||
|
||||
function isItfxSpaPath(afterApi: string): boolean {
|
||||
|
||||
@ -14,9 +14,12 @@ import configCompressPlugin from './config/plugin/compress';
|
||||
|
||||
export default defineConfig(({ mode }) => {
|
||||
const env = loadEnv(mode, process.cwd(), '');
|
||||
// Admin API 目标:由 VITE_OMS_ADMIN_URL 决定(开发默认线上)
|
||||
// 开发默认打测试环境;可用 VITE_API_ORIGIN / VITE_OMS_ADMIN_URL 覆盖
|
||||
const apiOrigin = (
|
||||
env.VITE_API_ORIGIN || 'https://api.test.ideship.com'
|
||||
).replace(/\/$/, '');
|
||||
const omsAdminTarget = (
|
||||
env.VITE_OMS_ADMIN_URL || 'http://api.nanafa.com/admin'
|
||||
env.VITE_OMS_ADMIN_URL || `${apiOrigin}/admin`
|
||||
).replace(/\/$/, '');
|
||||
|
||||
return {
|
||||
@ -34,16 +37,17 @@ export default defineConfig(({ mode }) => {
|
||||
changeOrigin: true,
|
||||
secure: false,
|
||||
},
|
||||
// 上传静态资源:/api/upload/xxx -> http://api.nanafa.com/upload/xxx
|
||||
// 上传静态资源:/api/upload/xxx -> {api}/upload/xxx
|
||||
// 必须放在通用 /api 规则前,避免被转发到 /itfx/upload 导致 404
|
||||
'/api/upload': {
|
||||
target: 'http://api.nanafa.com',
|
||||
target: apiOrigin,
|
||||
changeOrigin: true,
|
||||
secure: false,
|
||||
rewrite: (path) => path.replace(/^\/api/, ''),
|
||||
timeout: 30000,
|
||||
proxyTimeout: 30000,
|
||||
},
|
||||
// Admin API:目标由 VITE_OMS_ADMIN_URL 决定(默认 http://api.nanafa.com/admin)
|
||||
// Admin API:目标由 VITE_OMS_ADMIN_URL 决定(默认 https://api.test.ideship.com/admin)
|
||||
'/rbac': {
|
||||
target: omsAdminTarget,
|
||||
changeOrigin: true,
|
||||
@ -281,10 +285,11 @@ export default defineConfig(({ mode }) => {
|
||||
secure: false,
|
||||
rewrite: (path) => path.replace(/^\/api/, ''),
|
||||
},
|
||||
// 轨迹(track)43.139.210.35:8889 -> http://api.nanafa.com/track,路径与 rbac、api 一致:/Track/xxx
|
||||
// 轨迹(track):/Track/xxx → {api}/track/Track/xxx
|
||||
'/Track': {
|
||||
target: 'http://api.nanafa.com',
|
||||
target: apiOrigin,
|
||||
changeOrigin: true,
|
||||
secure: false,
|
||||
rewrite: (path) => '/track' + path,
|
||||
configure: (proxy) => {
|
||||
proxy.on('error', (err, req, res) => {
|
||||
@ -292,11 +297,12 @@ export default defineConfig(({ mode }) => {
|
||||
});
|
||||
},
|
||||
},
|
||||
// API(itfx)43.139.210.35:8888 -> http://api.nanafa.com/itfx
|
||||
// API(itfx):/api/... → {api}/itfx/...
|
||||
// 使用正则表达式匹配,排除前端路由路径
|
||||
'^/api/(?!upstreamInterface|upstreamInterfaceConfig|upstreamInterfaceConfigEdit|downstreamInterface|downstreamInterface/newPort|appList|appList/createApplication|requestLog|callStatistics|apiDebugger|trackApi)': {
|
||||
target: 'http://api.nanafa.com/itfx',
|
||||
target: `${apiOrigin}/itfx`,
|
||||
changeOrigin: true,
|
||||
secure: false,
|
||||
rewrite: (path) => path.replace(/^\/api/, ''),
|
||||
timeout: 30000,
|
||||
proxyTimeout: 30000,
|
||||
@ -321,9 +327,9 @@ export default defineConfig(({ mode }) => {
|
||||
timeout: 30000,
|
||||
proxyTimeout: 30000,
|
||||
},
|
||||
// api.nanafa.com 整站代理(ApiTest 调试):/nanafa/itfx/xxx → http://api.nanafa.com/itfx/xxx
|
||||
// API 网关整站代理(ApiTest 调试,路径名历史遗留):/nanafa/itfx/xxx → {api}/itfx/xxx
|
||||
'/nanafa': {
|
||||
target: 'http://api.nanafa.com',
|
||||
target: apiOrigin,
|
||||
changeOrigin: true,
|
||||
secure: false,
|
||||
rewrite: (path) => path.replace(/^\/nanafa/, ''),
|
||||
|
||||
@ -9,7 +9,7 @@ from pathlib import Path
|
||||
|
||||
@dataclass
|
||||
class AgentSettings:
|
||||
oms_url: str = "http://api.nanafa.com/admin"
|
||||
oms_url: str = "https://api.test.ideship.com/admin"
|
||||
token: str = ""
|
||||
device_name: str = ""
|
||||
bridge_port: int = 9333
|
||||
|
||||
@ -110,7 +110,7 @@ class LicenseConfig:
|
||||
class OmsConfig:
|
||||
"""OMS 物流查价 API(POST /order/price-check)。"""
|
||||
|
||||
api_base_url: str = "http://api.nanafa.com/admin"
|
||||
api_base_url: str = "https://api.test.ideship.com/admin"
|
||||
timeout_sec: int = 30
|
||||
auth_token: str = ""
|
||||
contact_name: str = ""
|
||||
|
||||
Loading…
Reference in New Issue
Block a user