fix: NUXT_PUBLIC_APP_ID 改为数字主键,接口基址切正式域名

1. appId 语义修正
   NUXT_PUBLIC_APP_ID 之前填的是 productCode('website'),但下游拿它去请求
   /api/app/product/detail/{productId},后端按 Integer 解析主键,于是转换失败。
   改为 app_product.product_id 数字主键(种子数据为 42);nuxt.config.ts 的
   缺省值同步去掉 'website' 回退——留空时下游按空值降级,绝不回退到编码值。

2. 接口基址切 hjc-api.sitelnk.cn
   .env.example / .env.production / nuxt.config.ts 的缺省值与 preconnect、
   dns-prefetch 一并从 hjc-api.websoft.top 改为正式域名;scripts/ 与
   outputs/ 文档里的旧地址同步更新。

注:本提交含若干文件的 CRLF/LF 行尾归一,实际内容改动见 git diff --ignore-cr-at-eol。
This commit is contained in:
2026-09-25 05:22:58 +08:00
parent 3d3a377221
commit 4a5a8f306a
12 changed files with 582 additions and 564 deletions
+4 -1
View File
@@ -8,7 +8,10 @@
# ---------- 租户 / 模板 ----------
# 本地开发用固定租户,生产环境通过域名自动识别租户
NUXT_PUBLIC_TENANT_ID=10626
NUXT_PUBLIC_APP_ID=website
# 应用产品 ID(app_product.product_id 数字主键,种子数据为 42)。
# 注意:不是 productCode('website'),按编码查询会打到
# /api/app/product/detail/{productId} 导致 Integer 转换失败。
NUXT_PUBLIC_APP_ID=42
NUXT_PUBLIC_TEMPLATE_ID=template-07
# 本地调试用:强制指定模板,优先级高于应用/站点绑定。留空表示不覆盖
+6 -3
View File
@@ -16,16 +16,19 @@
# ---------- 租户 / 应用 / 模板 ----------
# 固定租户 ID。生产环境留空,改由域名自动识别
NUXT_PUBLIC_TENANT_ID=
NUXT_PUBLIC_APP_ID=website
# 应用产品 ID(app_product.product_id 数字主键,如 42)。
# 注意:不是 productCode('website'),按编码查询会打到
# /api/app/product/detail/{productId} 导致 Integer 转换失败。
NUXT_PUBLIC_APP_ID=
# 默认模板 ID
NUXT_PUBLIC_TEMPLATE_ID=
# 强制模板 ID:设置后优先级最高,覆盖应用/站点绑定(仅本地调试用)
NUXT_PUBLIC_FORCE_TEMPLATE_ID=
# ---------- 后端接口地址 ----------
# 内容/CMS 接口。生产为 https://hjc-api.websoft.top/api
# 内容/CMS 接口。生产为 https://hjc-api.sitelnk.cn/api
NUXT_PUBLIC_MODULES_API_BASE=
# 租户/模板解析接口。生产为 https://hjc-api.websoft.top(无 /api 后缀)
# 租户/模板解析接口。生产为 https://hjc-api.sitelnk.cn(无 /api 后缀)
NUXT_PUBLIC_APP_API_BASE=
# 图片/文件服务器。留空则从 APP_API_BASE 自动推导
NUXT_PUBLIC_FILE_SERVER_BASE=
+3 -3
View File
@@ -7,10 +7,10 @@
# ---------- 接口(生产必须指向线上) ----------
# 单一后端:内容/CMS、租户解析、模板解析全部走 hjc-api
NUXT_PUBLIC_MODULES_API_BASE=https://hjc-api.websoft.top/api
NUXT_PUBLIC_APP_API_BASE=https://hjc-api.websoft.top
NUXT_PUBLIC_MODULES_API_BASE=https://hjc-api.sitelnk.cn/api
NUXT_PUBLIC_APP_API_BASE=https://hjc-api.sitelnk.cn
# 图片/文件服务器。留空则由 nuxt.config.ts 从 APP_API_BASE 推导出
# https://hjc-api.websoft.top,无需手写
# https://hjc-api.sitelnk.cn,无需手写
NUXT_PUBLIC_FILE_SERVER_BASE=
# ---------- 站点 / 多租户域名 ----------
+1 -1
View File
@@ -1,7 +1,7 @@
# 2026-09-08
## 本地开发接口切换(cms-api → 127.0.0.1:9500)
- 需求:把 CMS/内容接口从 `https://hjc-api.websoft.top/api` 切到本地 `http://127.0.0.1:9500/api`。
- 需求:把 CMS/内容接口从 `https://hjc-api.sitelnk.cn/api` 切到本地 `http://127.0.0.1:9500/api`。
- 改法:只动 `.env`,未改 `nuxt.config.ts` 默认值(保持生产配置不变)。新增 `NUXT_PUBLIC_MODULES_API_BASE=http://127.0.0.1:9500/api`;NUXT_ 前缀环境变量会覆盖 `runtimeConfig.public.modulesApiBase`。
- 关联:`modulesApiBase` 被 server/api 下 site/info、page/*、article/*、product/*、case/*、banner、form/submit、sitemap、domain/resolve 共用;文件/图片走另一个变量 `fileServerBase`(默认 origin(serverApiBase)=server.websoft.top),已在 .env 留注释开关。
- 顺带修复:原 `.env` 中 `NUXT_PUBLIC_TENANT_ID` / `NUXT_PUBLIC_TEMPLATE_ID` 两行有前导空格,dotenv 无法解析 → 配置一直没生效。已去除空格(tenant 10626 / template-07 将真正生效,若之前靠默认 template-01 调试需注意行为变化)。
+5 -4
View File
@@ -98,18 +98,19 @@ grep -rl "127.0.0.1" .output/ || echo "产物干净,无本地地址"
```bash
# 租户 / 模板(生产留空,由域名自动识别)
NUXT_PUBLIC_TENANT_ID=
NUXT_PUBLIC_APP_ID=website
# 应用产品 ID(app_product.product_id 数字主键,如 42;不是 productCode 'website')
NUXT_PUBLIC_APP_ID=42
NUXT_PUBLIC_TEMPLATE_ID=
# 接口地址(单一后端:内容/CMS、租户解析、模板解析全部走 hjc-api)
NUXT_PUBLIC_MODULES_API_BASE=https://hjc-api.websoft.top/api
NUXT_PUBLIC_APP_API_BASE=https://hjc-api.websoft.top
NUXT_PUBLIC_MODULES_API_BASE=https://hjc-api.sitelnk.cn/api
NUXT_PUBLIC_APP_API_BASE=https://hjc-api.sitelnk.cn
# 多租户域名
NUXT_PUBLIC_BASE_DOMAINS=shoplnk.cn,sitelink.cn,wsdns.cn
```
> ℹ️ `nuxt.config.ts` 内置的接口默认值已统一为 `https://hjc-api.websoft.top`(单后端)。
> ℹ️ `nuxt.config.ts` 内置的接口默认值已统一为 `https://hjc-api.sitelnk.cn`(单后端)。
> `.env.production` 中也显式指定同一地址。
> 若将来再次更换域名,请同步修改 `nuxt.config.ts`、`.env.production` 与 `.env.example`。
+1 -1
View File
@@ -8,7 +8,7 @@
后台 website-admin `_websopy` 代理 → `websopy-api.websoft.top` = **websopy-java**。
`CmsTemplateController.use()` 按 `loginUser.getTenantId()` 写 `cms_website.template_id`。
- **读路径** `GET /cms/cms-website/getSiteInfo`:
公开站 `modulesApiBase` 与 后台 `_cms` 代理 → `hjc-api.websoft.top` = **mp-java**。
公开站 `modulesApiBase` 与 后台 `_cms` 代理 → `hjc-api.sitelnk.cn` = **mp-java**。
返回 `ShopVo`(站点信息),被 Redis 缓存 1 天(key `SiteInfo:{tenantId}`)。
- 两后端**共享同一 Redis**(prod `1Panel-redis-Q1LE`;dev `47.119.165.234`,同密码),
故 websopy-java 的 `use()` 清缓存能清掉 mp-java 读的 `SiteInfo:{tenantId}`。
+9 -6
View File
@@ -16,7 +16,10 @@ function toBool(v?: string): boolean | null {
}
const tenantId = process.env.NUXT_PUBLIC_TENANT_ID || ''
const appId = process.env.NUXT_PUBLIC_APP_ID || 'website'
// appId 是 app_product.product_id 数字主键(如 42),不是 productCode('website')。
// 留空时下游 getSubscriptionStatus 等按空值降级,绝不回退到编码值,
// 否则 /api/app/product/detail/{productId} 会因 Integer 转换失败报错。
const appId = process.env.NUXT_PUBLIC_APP_ID || ''
const templateId = process.env.NUXT_PUBLIC_TEMPLATE_ID || 'template-01'
// 强制模板 ID:一旦设置则拥有最高优先级,覆盖应用/站点绑定(主要用于本地调试)
const forceTemplateId = process.env.NUXT_PUBLIC_FORCE_TEMPLATE_ID || ''
@@ -25,14 +28,14 @@ const siteName = process.env.NUXT_PUBLIC_SITE_NAME || ''
const modulesApiBase =
process.env.NUXT_PUBLIC_MODULES_API_BASE ||
'https://hjc-api.websoft.top/api'
'https://hjc-api.sitelnk.cn/api'
const appApiBase =
process.env.NUXT_PUBLIC_APP_API_BASE ||
'https://hjc-api.websoft.top'
'https://hjc-api.sitelnk.cn'
const fileServerBase =
process.env.NUXT_PUBLIC_FILE_SERVER_BASE ||
getOrigin(appApiBase) ||
'https://hjc-api.websoft.top'
'https://hjc-api.sitelnk.cn'
const baseDomain =
process.env.NUXT_PUBLIC_BASE_DOMAIN || 'shoplnk.cn'
// 多主域清单:子域名租户解析支持的主域(逗号分隔)。
@@ -77,8 +80,8 @@ export default defineNuxtConfig({
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' },
// 提前与接口/图片源站建立连接,降低首字节与图片加载延迟
{ rel: 'preconnect', href: 'https://hjc-api.websoft.top', crossorigin: '' },
{ rel: 'dns-prefetch', href: 'https://hjc-api.websoft.top' },
{ rel: 'preconnect', href: 'https://hjc-api.sitelnk.cn', crossorigin: '' },
{ rel: 'dns-prefetch', href: 'https://hjc-api.sitelnk.cn' },
{ rel: 'preconnect', href: 'https://file.wsdns.cn', crossorigin: '' },
{ rel: 'dns-prefetch', href: 'https://file.wsdns.cn' },
// 思源黑体(Noto Sans SC,SIL 开源许可,版权无忧)网页字体,全站统一字体
File diff suppressed because one or more lines are too long
@@ -43,7 +43,7 @@
| `server/api/payment/query.get.ts` | `tenderApiBase/payment/query` | 支付状态查询(复用现有支付查询) |
| `server/api/supplier/login.post.ts` 等 | `tenderApiBase/...` | 仅当采用账号密码注册登录时新增 |
> **双后端兼容**:所有 `tenderApiBase` 走统一 runtimeConfig(`NUXT_TENDER_API_BASE`),默认 `https://hjc-api.websoft.top/api`;若确认交易走 guilixu-java,改 env 即可,前端代码不变。租户头 `TenantId`、JWT 透传沿用现有中间件。
> **双后端兼容**:所有 `tenderApiBase` 走统一 runtimeConfig(`NUXT_TENDER_API_BASE`),默认 `https://hjc-api.sitelnk.cn/api`;若确认交易走 guilixu-java,改 env 即可,前端代码不变。租户头 `TenantId`、JWT 透传沿用现有中间件。
---
+1 -1
View File
@@ -7,7 +7,7 @@ import os, json, sys, subprocess, time, urllib.request, urllib.error
TOKEN = os.environ.get("TOKEN", "")
UPLOAD = "https://server.websoft.top/api/file/upload"
CMS = "https://hjc-api.websoft.top/api"
CMS = "https://hjc-api.sitelnk.cn/api"
FILE_BASE = "https://file.websoft.top/api/file/"
HDR = {"TenantId": "10626", "Authorization": "Bearer " + TOKEN}
+1 -1
View File
@@ -25,7 +25,7 @@
* ============================================================================
*/
const API_BASE = process.env.CMS_API_BASE || 'https://hjc-api.websoft.top/api'
const API_BASE = process.env.CMS_API_BASE || 'https://hjc-api.sitelnk.cn/api'
const TOKEN_RAW = process.env.ADMIN_TOKEN || ''
const TENANT_ID = process.env.TENANT_ID || '10546'
const APPLY = process.env.APPLY === '1'
+8
View File
@@ -55,6 +55,14 @@ export async function getAppProductById(
const appApiBase = config.public.appApiBase as string
if (!productId) return null
// 防御:productId 是 app_product.product_id 数字主键。
// 传入 productCode(如 'website')会打到 /api/app/product/detail/{productId}
// 导致后端 Integer 转换失败,且每个请求都会重复报错。直接短路返回 null。
if (!/^\d+$/.test(String(productId))) {
console.warn('[app] getAppProductById 收到非数字 productId=%s,跳过查询', productId)
return null
}
try {
const res = await $fetch<ApiEnvelope<AppProduct> | AppProduct>(
`/api/app/product/detail/${productId}`,