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