This commit is contained in:
2026-08-31 10:17:06 +08:00
parent 0e828cd44a
commit b4d5fb1170
7 changed files with 11 additions and 9 deletions
Vendored
+1 -1
View File
@@ -70,7 +70,7 @@ pipeline {
docker build \ docker build \
--build-arg NODE_IMAGE="$NODE_BASE_IMAGE" \ --build-arg NODE_IMAGE="$NODE_BASE_IMAGE" \
--build-arg NGINX_IMAGE="$NGINX_BASE_IMAGE" \ --build-arg NGINX_IMAGE="$NGINX_BASE_IMAGE" \
--build-arg VITE_CLIENT_WEB_URL=http://8.163.49.32:9002 \ --build-arg VITE_CLIENT_WEB_URL="${CLIENT_WEB_URL:-https://dev-app.buggoglobal.com/}" \
-t "$image" . -t "$image" .
export IMAGE_TAG="$SOURCE_TAG" export IMAGE_TAG="$SOURCE_TAG"
docker compose -p "$DEVELOPMENT_COMPOSE_PROJECT" -f "$DEVELOPMENT_COMPOSE_FILE" up -d --remove-orphans --pull never docker compose -p "$DEVELOPMENT_COMPOSE_PROJECT" -f "$DEVELOPMENT_COMPOSE_FILE" up -d --remove-orphans --pull never
+1 -1
View File
@@ -55,7 +55,7 @@ VITE_CLIENT_WEB_URL=http://localhost:5174
切换开发或测试环境时,只修改未提交的 `.env.local` 中 `API_PROXY_TARGET`、`OVERSEAS_API_PROXY_TARGET` 和 `VITE_CLIENT_WEB_URL`,然后重启 `pnpm dev`;无需修改业务代码。真实环境地址不写入受版本控制的配置模板或说明。 切换开发或测试环境时,只修改未提交的 `.env.local` 中 `API_PROXY_TARGET`、`OVERSEAS_API_PROXY_TARGET` 和 `VITE_CLIENT_WEB_URL`,然后重启 `pnpm dev`;无需修改业务代码。真实环境地址不写入受版本控制的配置模板或说明。
客户代登录打开的工作台地址是运行时配置,不需要为每个环境重新构建镜像。Docker 部署时设置容器环境变量 `CLIENT_WEB_URL`;容器启动时会生成 `/runtime-config.js`。本地 Vite 开发使用 `VITE_CLIENT_WEB_URL` 作为兜底。 客户代登录打开的工作台地址是运行时配置,不需要为每个环境重新构建镜像。Docker 部署时为 Admin 容器设置当前环境的 `CLIENT_WEB_URL`;容器启动时会生成 `/runtime-config.js`。开发、测试和生产分别在各自部署任务中注入自己的 Client 根地址,禁止复用其他环境的域名。本地 Vite 开发使用 `VITE_CLIENT_WEB_URL` 作为兜底。部署后可读取 `/runtime-config.js` 核对最终生效值。
认证请求使用 `/api/auth/**`,平台 IAM 请求使用 `/api/platform/v1/iam/**`。登录后只从 JWT 读取平台身份,菜单和操作权限通过当前用户授权接口实时加载,不从 JWT 携带或解析角色权限。企业审核调用 `/reviews`,打开审核详情后按租户调用 `/tenants/{tenantId}/qualifications`;营业执照通过 `/api/platform/v1/files/qualifications/{tenantId}/{fileName}` 携带平台 Token 临时读取,关闭预览后释放本地对象地址。客户端自主注册企业审核通过后继续使用注册账号作为管理员,不展示新凭据;Admin 代建企业并由后端创建管理员时,页面必须展示不可通过遮罩、Esc 或关闭按钮跳过的一次性凭据弹窗,运营人员确认保存后才清除账号密码。平台角色查询、新增、编辑、启停、删除和权限全量保存均已按 `RbacController` 接入真实 `/roles` 契约,角色返回的 `permissionIds` 用于授权回显;系统内置角色及仍被成员使用的角色继续由服务端保护。权限资源查询和新增调用 `/permissions`,尚未提供的权限编辑、删除和启停不会模拟成功。一期真实权限资源只创建 `MENU` 与 `BUTTON`,不创建 `PAGE` 或 `API` 类型。其余业务页面需在对应服务契约确认后逐项替换,生产逻辑不得静默回退到模拟数据。 认证请求使用 `/api/auth/**`,平台 IAM 请求使用 `/api/platform/v1/iam/**`。登录后只从 JWT 读取平台身份,菜单和操作权限通过当前用户授权接口实时加载,不从 JWT 携带或解析角色权限。企业审核调用 `/reviews`,打开审核详情后按租户调用 `/tenants/{tenantId}/qualifications`;营业执照通过 `/api/platform/v1/files/qualifications/{tenantId}/{fileName}` 携带平台 Token 临时读取,关闭预览后释放本地对象地址。客户端自主注册企业审核通过后继续使用注册账号作为管理员,不展示新凭据;Admin 代建企业并由后端创建管理员时,页面必须展示不可通过遮罩、Esc 或关闭按钮跳过的一次性凭据弹窗,运营人员确认保存后才清除账号密码。平台角色查询、新增、编辑、启停、删除和权限全量保存均已按 `RbacController` 接入真实 `/roles` 契约,角色返回的 `permissionIds` 用于授权回显;系统内置角色及仍被成员使用的角色继续由服务端保护。权限资源查询和新增调用 `/permissions`,尚未提供的权限编辑、删除和启停不会模拟成功。一期真实权限资源只创建 `MENU` 与 `BUTTON`,不创建 `PAGE` 或 `API` 类型。其余业务页面需在对应服务契约确认后逐项替换,生产逻辑不得静默回退到模拟数据。
+1 -1
View File
@@ -6,7 +6,7 @@ services:
ports: ports:
- "127.0.0.1:9001:80" - "127.0.0.1:9001:80"
environment: environment:
CLIENT_WEB_URL: "http://8.163.49.32:9002" CLIENT_WEB_URL: "${CLIENT_WEB_URL:-https://dev-app.buggoglobal.com/}"
API_UPSTREAM: "http://firstleg-development-gateway:9000" API_UPSTREAM: "http://firstleg-development-gateway:9000"
OVERSEAS_API_UPSTREAM: "http://firstleg-development-gateway-overseas:9300" OVERSEAS_API_UPSTREAM: "http://firstleg-development-gateway-overseas:9300"
networks: networks:
+3 -3
View File
@@ -12,8 +12,8 @@ services:
ports: ports:
- "${HOST_PORT:-9001}:80" - "${HOST_PORT:-9001}:80"
environment: environment:
# The test client is exposed on the same host through port 9002. Allow # Runtime URL used by the secure customer-workbench handoff. Each
# deployments to override this, but never fall back to the server IP. # environment may override it without rebuilding the Admin image.
CLIENT_WEB_URL: "${CLIENT_WEB_URL:-http://test-admin.buggoglobal.com:9002}" CLIENT_WEB_URL: "${CLIENT_WEB_URL:-https://test-app.buggoglobal.com/}"
API_UPSTREAM: "http://test-api-cn.buggoglobal.com" API_UPSTREAM: "http://test-api-cn.buggoglobal.com"
OVERSEAS_API_UPSTREAM: "http://test-api-global.buggoglobal.com" OVERSEAS_API_UPSTREAM: "http://test-api-global.buggoglobal.com"
+3 -1
View File
@@ -40,8 +40,9 @@ describe('admin nginx deployment config', () => {
it('declares an explicit overseas gateway upstream in container deployments', () => { it('declares an explicit overseas gateway upstream in container deployments', () => {
expect(testCompose).toContain('API_UPSTREAM: "http://test-api-cn.buggoglobal.com"') expect(testCompose).toContain('API_UPSTREAM: "http://test-api-cn.buggoglobal.com"')
expect(testCompose).toContain('OVERSEAS_API_UPSTREAM: "http://test-api-global.buggoglobal.com"') expect(testCompose).toContain('OVERSEAS_API_UPSTREAM: "http://test-api-global.buggoglobal.com"')
expect(testCompose).toContain('CLIENT_WEB_URL: "${CLIENT_WEB_URL:-http://test-admin.buggoglobal.com:9002}"') expect(testCompose).toContain('CLIENT_WEB_URL: "${CLIENT_WEB_URL:-https://test-app.buggoglobal.com/}"')
expect(testCompose).not.toContain('CLIENT_WEB_URL: "http://8.163.') expect(testCompose).not.toContain('CLIENT_WEB_URL: "http://8.163.')
expect(developmentCompose).toContain('CLIENT_WEB_URL: "${CLIENT_WEB_URL:-https://dev-app.buggoglobal.com/}"')
expect(developmentCompose).toContain('OVERSEAS_API_UPSTREAM: "http://firstleg-development-gateway-overseas:9300"') expect(developmentCompose).toContain('OVERSEAS_API_UPSTREAM: "http://firstleg-development-gateway-overseas:9300"')
expect(config).toContain('proxy_set_header Host $proxy_host;') expect(config).toContain('proxy_set_header Host $proxy_host;')
}) })
@@ -64,5 +65,6 @@ describe('admin nginx deployment config', () => {
expect(jenkinsfile).toContain("NGINX_BASE_IMAGE = '172.31.198.7:10082/java-project/nginx:1.27-alpine'") expect(jenkinsfile).toContain("NGINX_BASE_IMAGE = '172.31.198.7:10082/java-project/nginx:1.27-alpine'")
expect(jenkinsfile).toContain('withCredentials([usernamePassword(') expect(jenkinsfile).toContain('withCredentials([usernamePassword(')
expect(jenkinsfile).toContain('export DOCKER_CONFIG="${WORKSPACE}@tmp/docker-auth"') expect(jenkinsfile).toContain('export DOCKER_CONFIG="${WORKSPACE}@tmp/docker-auth"')
expect(jenkinsfile).toContain('--build-arg VITE_CLIENT_WEB_URL="${CLIENT_WEB_URL:-https://dev-app.buggoglobal.com/}"')
}) })
}) })
@@ -252,7 +252,7 @@ describe('GlobalSmartLoadingView', () => {
const groupedPlan = { ...plan, items } const groupedPlan = { ...plan, items }
const group = { const group = {
groupId: '2093539779795795969', groupNo: 'CLG-2093539779795795969', status: 'LOCKED' as const, warehouseId: '8', channelCode: 'ZBYHK', lockedPlanId: '99', version: 1, groupId: '2093539779795795969', groupNo: 'CLG-2093539779795795969', status: 'LOCKED' as const, warehouseId: '8', channelCode: 'ZBYHK', lockedPlanId: '99', version: 1,
members: items.map((item) => ({ tenantId: item.accountId, orderId: item.orderId, inboundId: item.inboundId, fullPackageCount: item.packageCount })), fullPackageCount: 13, createdAt: '2026-08-29T10:00:00', updatedAt: '2026-08-29T10:30:00', members: items.map((item) => ({ tenantId: item.accountId, orderId: item.orderId, inboundId: item.inboundId, inboundCode: item.inboundCode, fullPackageCount: item.packageCount })), fullPackageCount: 13, createdAt: '2026-08-29T10:00:00', updatedAt: '2026-08-29T10:30:00',
} }
vi.mocked(getSmartLoadingPlanByBooking).mockResolvedValueOnce(groupedPlan).mockResolvedValue({ ...groupedPlan, version: 3, items: [] }) vi.mocked(getSmartLoadingPlanByBooking).mockResolvedValueOnce(groupedPlan).mockResolvedValue({ ...groupedPlan, version: 3, items: [] })
vi.mocked(batchQueryPlatformCoLoadGroups).mockResolvedValue([...new Set(items.map((item) => item.orderId))].map((orderId) => ({ orderId, group }))) vi.mocked(batchQueryPlatformCoLoadGroups).mockResolvedValue([...new Set(items.map((item) => item.orderId))].map((orderId) => ({ orderId, group })))
@@ -189,7 +189,7 @@ describe('SmartLoadingWorkbenchView', () => {
vi.mocked(getSmartLoadingPlanByBooking).mockResolvedValue({ ...planResponse, items }) vi.mocked(getSmartLoadingPlanByBooking).mockResolvedValue({ ...planResponse, items })
vi.mocked(batchQueryPlatformCoLoadGroups).mockResolvedValue([...new Set(items.map((item) => item.orderId))].map((orderId) => ({ orderId, group: { vi.mocked(batchQueryPlatformCoLoadGroups).mockResolvedValue([...new Set(items.map((item) => item.orderId))].map((orderId) => ({ orderId, group: {
groupId: '9900', groupNo: 'CLG-9900', status: 'LOCKED', warehouseId: '8', channelCode: 'ZBYHK', lockedPlanId: '99', version: 1, groupId: '9900', groupNo: 'CLG-9900', status: 'LOCKED', warehouseId: '8', channelCode: 'ZBYHK', lockedPlanId: '99', version: 1,
members: items.map((member) => ({ tenantId: member.accountId, orderId: member.orderId, inboundId: member.inboundId, fullPackageCount: member.packageCount })), fullPackageCount: 13, createdAt: '2026-08-29T10:00:00', updatedAt: '2026-08-29T10:30:00', members: items.map((member) => ({ tenantId: member.accountId, orderId: member.orderId, inboundId: member.inboundId, inboundCode: member.inboundCode, fullPackageCount: member.packageCount })), fullPackageCount: 13, createdAt: '2026-08-29T10:00:00', updatedAt: '2026-08-29T10:30:00',
} }))) } })))
vi.mocked(removeSmartLoadingGroup).mockResolvedValue({ ...planResponse, version: 3, items: [] }) vi.mocked(removeSmartLoadingGroup).mockResolvedValue({ ...planResponse, version: 3, items: [] })
vi.spyOn(ElMessageBox, 'confirm').mockResolvedValue('confirm' as never) vi.spyOn(ElMessageBox, 'confirm').mockResolvedValue('confirm' as never)