diff --git a/.cursor/rules/frontend-design-spec.mdc b/.cursor/rules/frontend-design-spec.mdc index bbe5f88..e2614eb 100644 --- a/.cursor/rules/frontend-design-spec.mdc +++ b/.cursor/rules/frontend-design-spec.mdc @@ -33,7 +33,7 @@ alwaysApply: true - HandsontablePro 固定列序:操作(可选,内容自适应宽)→ 序号(50px)→ 复选框(可选,60px)→ 数据;`stretch-columns` 只拉宽数据列,勿再传 `action-column-position` / `action-column-width` - 列表页高度:`flex: 1; min-height: 0`,`.list-wrap` 勿写死 min-height - 分页 10/30/50/100,默认 50 -- 新页面 path 与 API 前缀冲突时须配置 nginx SPA 回退(见规范 §十五) +- 生产前后端分域名 + Traefik TLS;前端容器仅静态 SPA(见规范 §十五) ### 权限 - `hasPermission('Module.Resource.Action')` 控制按钮/路由 diff --git a/.dockerignore b/.dockerignore index 4caeb06..5674289 100644 --- a/.dockerignore +++ b/.dockerignore @@ -26,7 +26,5 @@ xhs-agent-desktop .env* !.env.production -# 本地/旧部署用的 nginx,k3s 用 nginx-k3s.conf -nginx-default.conf -nginx-docker.conf +# 本地简易镜像另用 Dockerfile;k3s 构建用 Dockerfile.k3s Dockerfile diff --git a/Dockerfile b/Dockerfile index f7f517b..0112129 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,9 +1,9 @@ -FROM nginx:1.27-alpine - -# 静态资源 -COPY dist/ /usr/share/nginx/html/ - -# Docker 内只用 HTTP:80,SSL 在宿主机 nginx 或网关层处理 -COPY nginx-docker.conf /etc/nginx/conf.d/default.conf - +# 本地/简易 Docker:仅静态 SPA。HTTPS 由外层网关(如 Traefik)终结。 +# 构建前先执行:pnpm build +FROM docker.m.daocloud.io/library/node:20-alpine +WORKDIR /app +RUN npm config set registry https://registry.npmmirror.com \ + && npm install -g serve@14.2.4 +COPY dist/ ./dist/ EXPOSE 80 +CMD ["serve", "-s", "dist", "-l", "80"] diff --git a/Dockerfile.k3s b/Dockerfile.k3s index baaa055..88fa85e 100644 --- a/Dockerfile.k3s +++ b/Dockerfile.k3s @@ -1,4 +1,5 @@ -# k3s / Kaniko:静态 SPA(方案 A)。API 由浏览器按站点域名直连 +# k3s / Kaniko:静态 SPA(方案 A)。TLS 由 Traefik(websecure) + cert-manager 终结。 +# API 由浏览器按站点域名直连: # test.ideship.com → api.test.ideship.com;其余 → api.ideship.com # FRONT_BUILD_SCRIPT: # prod 默认 build(.env.production → api.ideship.com) @@ -16,7 +17,11 @@ RUN pnpm config set registry https://registry.npmmirror.com \ COPY . . 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/ -COPY nginx-k3s.conf /etc/nginx/conf.d/default.conf +# 仅静态托管 + SPA fallback;不再内置 nginx(网关层 Traefik 负责 HTTPS) +FROM docker.m.daocloud.io/library/node:20-alpine +WORKDIR /app +RUN npm config set registry https://registry.npmmirror.com \ + && npm install -g serve@14.2.4 +COPY --from=build /app/dist ./dist EXPOSE 80 +CMD ["serve", "-s", "dist", "-l", "80"] diff --git a/README.md b/README.md index ee7b479..5a4a972 100644 --- a/README.md +++ b/README.md @@ -98,17 +98,18 @@ npm run lint 1. 安装依赖 `pnpm i` 2. 构建 `pnpm build`(生成 `dist/`) -3. **宿主机 nginx(推荐)**:将 `dist/` 放到 `/usr/share/nginx/html`,使用 `nginx-default.conf`(含 SSL,证书在 `/etc/nginx/ssl/`) -4. **Docker 方式(7962 端口)**:使用 `nginx-docker.conf`(仅 HTTP,不含 SSL) +3. **k3s(推荐)**:`Dockerfile.k3s` 多阶段构建,容器内用 `serve` 提供静态 SPA(`:80`);**HTTPS 由 Traefik `websecure` + cert-manager(Let's Encrypt)终结**,经 Ingress(tls) → Service,不在前端容器内挂证书。 +4. **本地简易 Docker**:先 `pnpm build`,再 `docker build -t web1 .`(`Dockerfile` 拷贝已有 `dist/`) ```bash +# 本地试跑静态容器(HTTP:7962 → 容器 80) docker build -t web1 . docker rm -f web docker run -d -p 7962:80 --name web web1 -docker ps | grep web # 确认 Up 状态 +docker ps | grep web ``` -> 勿把 `nginx-default.conf`(含 SSL)直接打进 Docker,容器内没有 `/etc/nginx/ssl/` 会导致启动失败。 +> 生产勿在前端镜像内配置 SSL;证书由集群 cert-manager 写入 Secret,Traefik Ingress 引用即可。 ## 贡献指南 diff --git a/docs/H5客户中心设计方案.md b/docs/H5客户中心设计方案.md index 26c8762..b804afd 100644 --- a/docs/H5客户中心设计方案.md +++ b/docs/H5客户中心设计方案.md @@ -547,7 +547,7 @@ src/views/h5/customer-center/ - [x] 独立 H5 账号密码登录(`/h5/login`,不跳 PC 登录页) - [x] H5 微信扫码登录:`GET /wechat/mp/login-qrcode` + 长按识别 + 轮询登录 - [x] 独立 H5 充值(`/h5/recharge`,不跳 PC 充值页) -- [x] 中英文与 nginx `/h5` SPA 回退 +- [x] 中英文与 `/h5` SPA 回退(`serve -s` / Traefik) - [ ] 键盘适配与运单上下文在顾问页的完整预填联调 - [x] 手机完整下单(二期):`/h5/place-order` 三步精简下单 + 查价「去下单」草稿深链 diff --git a/docs/前端页面设计规范.md b/docs/前端页面设计规范.md index 0d4108c..9852214 100644 --- a/docs/前端页面设计规范.md +++ b/docs/前端页面设计规范.md @@ -27,19 +27,31 @@ ``` a-layout (垂直) -├── TopNav(顶部导航,fixed) +├── TopNav(仅运营端,fixed) ├── a-layout-content -│ ├── paddingTop: 顶部导航高度 + Tab 栏高度(可选) -│ └── PageLayout(router-view + keep-alive) +│ ├── 运营端:paddingTop = 顶栏 + Tab;PageLayout +│ └── 客户门户:CustomerSideRail(全高)+ PageLayout(无顶栏、无多页签) └── Footer(可选) ``` +运营端布局 DOM/样式与改前一致;客户门户不挂载 TopNav / TabBar。 + **约定:** - 主内容背景色:`#f0f3f4` - 页面容器使用 `[class$='-container']`,统一 `padding: 16px` - 内容区域使用 `overflow: hidden`、`height: 100%` 保证高度正确 +**客户门户 vs 运营端导航(差异约定):** + +| | 运营端 | 客户门户 | +|---|---|---| +| 顶栏 | 一级模块 + hover 二级 + 右侧余额/打印/用户 | **无顶栏** | +| 页签 | TabBar 多页签 | **无多页签**(当前页仅由侧栏高亮表达) | +| 侧栏 | 无全局侧栏 | **全高可折叠左栏**(默认展开):顶 Logo;中按「常用 / 仓储 / 更多」浅分组;**资产与账户收进用户下拉**;底沉余额/打印(含下载)/消息/仓库;**语言收进用户菜单** | +| 高亮 | 路由最长路径匹配 | 侧栏最长路径匹配;账户类路由高亮底栏用户区 | +| 数据 | RBAC 菜单树原样 | 仍用同一菜单树,`flatMap` 二级即可,不改表结构 | + ### 2.2 页面内容结构 单页内容推荐结构: @@ -555,33 +567,25 @@ const { t } = useI18n(); - [ ] 分页组件置于**列表上方工具栏右侧**(列表右上角),**§7.3**;分页 10/30/50/100,默认 50 - [ ] 操作按钮按权限使用 `hasPermission` - [ ] 路由 meta 配置 `permission` -- [ ] **新增前端页面路径**若落在 `/order/`、`/channel/`、`/system/` 等与 Admin API 同源前缀下,须在 **`nginx-default.conf` / `nginx-docker.conf`** 增加 `^~` 的 `try_files /index.html =200` 规则(**§十五**),避免刷新/直链 404 +- [ ] **部署**:前端与 Admin API **分域名**(如 `ideship.com` / `api.ideship.com`);TLS 走 Traefik + cert-manager(**§十五**) - [ ] 文案通过 i18n,不写死中文 - [ ] 命名符合本规范(文件、路由、变量、i18n key) --- -## 十五、部署与 nginx(SPA 路由) +## 十五、部署与网关(Traefik / SPA) -生产环境 nginx 将 `/order/`、`/channel/`、`/system/` 等前缀**同时**用于 Admin API 反代。浏览器刷新或直接打开前端 URL(如 `/order/batchJobs`)时,若未单独配置 SPA 回退,请求会被转发到后端 API 并返回 **404**。 +生产已弃用站内 nginx。静态资源由前端容器(`serve -s`)提供,**HTTPS** 由 k3s Traefik `websecure` + cert-manager(Let's Encrypt)签发;流量路径: + +`浏览器 → :443 Traefik(websecure) → Ingress(tls) → Service → 前端 Pod(:80)` **约定:** -1. 官网 **`/`** 为 Vue 路由(`src/views/site`);静态资源在 **`/site/`**;**`/9610.html`** 为 `public/9610.html`。客户登录为 **`/login`**,管理端为 **`/admin`**。勿再把 `/login` 重定向到 `/`。 -2. 每新增一个**前端页面路由**,若其 path 与 API 前缀冲突,必须在 `nginx-default.conf` 与 `nginx-docker.conf` 中、**API 正则代理块之前**增加更高优先级的 `^~` 规则,例如: - -```nginx -# 订单前端路由(^~ 须比下方 /order/ API 正则代理更优先) -location ^~ /order/batchJobs { - try_files /index.html =200; -} -``` - -3. 修改后执行 `nginx -t && nginx -s reload`(或重建前端 Docker 镜像使 `nginx-docker.conf` 生效)。 - -4. 本地 Vite 开发不受此限制;**仅在部署环境**需遵守本节前缀规则。`pnpm dev` 时 `/` 即为官网。 - -当前订单模块已配置的前端路径示例:`/order/priceCheck`、`/order/placeOrder`、`/order/myOrders`、`/order/batchJobs`。 +1. **前后端分域名**(方案 A):站点如 `ideship.com` / `test.ideship.com`,API 如 `api.ideship.com` / `api.test.ideship.com`。浏览器直连 API,前端容器不做 Admin 反代,也无 `/__cos__` 反代。 +2. SPA 回退由 `serve -s`(或等价静态服务器)处理;刷新 `/order/batchJobs` 等路径应回 `index.html`,不依赖 nginx `try_files`。 +3. 官网 **`/`** 为 Vue 路由(`src/views/site`);静态资源在 **`/site/`**;**`/9610.html`** 为 `public/9610.html`。客户登录 **`/login`**,管理端 **`/admin`**。 +4. 面单/附件预览:开发可用 Vite `/__cos__`;生产优先 `file-storage/access-url` 新鲜签名直开,失败再 `stream` → blob(勿依赖过期库内签名 URL)。 +5. 本地 `pnpm dev` 不受 Ingress 限制;`/` 即为官网。 --- diff --git a/docs/在线客服模块设计方案.md b/docs/在线客服模块设计方案.md index d0e2bc9..163f162 100644 --- a/docs/在线客服模块设计方案.md +++ b/docs/在线客服模块设计方案.md @@ -181,7 +181,7 @@ | `OmsFileUploadHelper` | 聊天图片上传(新 folder:`cs`) | | `NoticeService` | 可选:新消息站内信 | | 数据权限 | 坐席列表/认领范围按客服数据权限过滤 | -| nginx | P1 必须补 WebSocket Upgrade | +| Traefik Ingress | P1 须允许 WebSocket Upgrade(SignalR) | ### 4.3 技术选型 @@ -197,16 +197,8 @@ ### 4.4 服务端部署注意 1. `AddSignalR().AddStackExchangeRedis(...)` 或与现有 FreeRedis 兼容的 backplane 方案(实现阶段选定一种,避免双 Redis 客户端混乱)。 -2. nginx 为 Hub 增加独立 location(建议 `/hubs/`),配置: - -```nginx -proxy_http_version 1.1; -proxy_set_header Upgrade $http_upgrade; -proxy_set_header Connection "upgrade"; -proxy_read_timeout 3600s; -``` - -3. 前端 Docker / `nginx-docker.conf`、`nginx-default.conf` 同步修改;新坐席路由若与 API 前缀冲突,按规范 §十五做 SPA `try_files`。 +2. Traefik / Ingress 对 Hub 路径(建议 `/hubs/` 或 SignalR 约定路径)开启 WebSocket;超时按长连接调大。前后端分域名时,浏览器直连 **api.***,前端静态容器无需反代 Hub。 +3. SPA 回退由前端容器 `serve -s` 处理;见规范 §十五。 --- @@ -610,7 +602,7 @@ src/composables/useCsHub.ts - [ ] 坐席右侧能看到客户与最近订单摘要 - [ ] 结束会话后客户再进线为新会话 - [ ] 双实例部署下消息不丢(Redis backplane) -- [ ] nginx WebSocket 升级验证通过 +- [ ] Traefik / Ingress WebSocket 升级验证通过 - [ ] 权限码控制认领 / 回复 / 结束;客户无法调坐席接口 ### 12.3 非功能 @@ -630,7 +622,7 @@ src/composables/useCsHub.ts | 2 | DDL:`t_cs_conversation` / `t_cs_message` + 仓储 | P1 | | 3 | HTTP 会话/消息/上传 API + 权限码种子 | P1 | | 4 | 坐席 Inbox 静态联调(可先轮询) | P1 | -| 5 | SignalR Hub + 前端 `useCsHub` + nginx | P1 | +| 5 | SignalR Hub + 前端 `useCsHub` + Traefik WS | P1 | | 6 | 分配逻辑 + 在线心跳 + 微信降级 | P1 | | 7 | AI 转人工 + 上下文侧栏 | P1 | | 8 | 未读角标 +(可选)站内信 | P1 | @@ -646,7 +638,7 @@ src/composables/useCsHub.ts | 风险 | 对策 | | --- | --- | | 坐席不用系统、仍只回微信 | P0 微信永远保留;P1 强调「转人工带单号」提升系统内处理价值 | -| SignalR 经 nginx 失败 | 独立 `/hubs/` location + 验收清单;可临时 `SignalREnabled=false` HTTP 轮询 | +| SignalR 经网关失败 | Ingress 允许 Upgrade + 验收清单;可临时 `SignalREnabled=false` HTTP 轮询 | | 多实例串消息 | 强制 Redis backplane,禁止单机假设 | | 客户把客服当即时 IM 闲聊 | 入口文案强调「物流咨询」;系统消息提示工作时间(可配置) | | AI 灌入消息过长 | 限制条数与单条长度;仅转人工时写入 | diff --git a/docs/小红书模块联调与验收.md b/docs/小红书模块联调与验收.md index 5da89af..3883fdb 100644 --- a/docs/小红书模块联调与验收.md +++ b/docs/小红书模块联调与验收.md @@ -46,7 +46,7 @@ pnpm install # 首次 pnpm dev ``` -生产构建:`pnpm build`,Nginx 配置见 `nginx-default.conf`(**仅** SPA 页面路径走 `index.html`,`/xhs/agent/list` 等 API 走 admin 后端,勿整段 `/xhs` 当 SPA)。 +生产构建:`pnpm build`;前后端分域名后,`/xhs/*` 页面由前端 `serve -s` SPA 回退,`/xhs/agent/*` 等 API 走 **api.*** Admin,勿把 API 打到前端域名。 ### 1.4 LIKE AI Agent @@ -158,12 +158,12 @@ Content-Type: application/json - [ ] **F2** 编辑提供商:BaseUrl、Model、ApiSecret 保存成功 - [ ] **F3** 对话发送消息 → 流式/完整回复正常 -### 阶段 G — 生产/nginx(上线前) +### 阶段 G — 生产 / Traefik(上线前) -- [ ] **G1** `nginx -t && nginx -s reload` 已执行 -- [ ] **G2** 刷新 `/xhs/analysis` 等页面返回 SPA,**不** 404 -- [ ] **G3** `POST https://api.nanafa.com/admin/xhs/agent/list`(带 Token)正常 -- [ ] **G4** Agent 使用生产 `--oms-url https://api.nanafa.com/admin` +- [ ] **G1** Ingress(tls) + cert-manager 证书就绪;前端 Service 健康 +- [ ] **G2** 刷新站点域名下 `/xhs/analysis` 等返回 SPA,**不** 404 +- [ ] **G3** `POST https://api.ideship.com/admin/xhs/agent/list`(带 Token)正常 +- [ ] **G4** Agent 使用生产 `--oms-url https://api.ideship.com/admin` --- @@ -232,8 +232,8 @@ curl.exe -s "http://localhost:5281/admin/rbac/auth/login" ... ### 5.5 前端 dev 正常、生产 404 -- Nginx 仅对 **页面路径** 回退 `index.html`(见 `nginx-default.conf` 第 63–66 行) -- API 请求应走 `VITE_API_ADMIN_URL`(如 `https://api.nanafa.com/admin`),不要打到 oms 静态站点的 `/xhs/agent/list` +- 站点域名下页面由 `serve -s` 回退 `index.html` +- API 请求应走 `VITE_API_ADMIN_URL`(如 `https://api.ideship.com/admin`),不要打到前端静态域名的 `/xhs/agent/list` ### 5.6 AI 生成 / 分析失败 diff --git a/docs/小红书模块设计-063001.md b/docs/小红书模块设计-063001.md index f139d17..485c47f 100644 --- a/docs/小红书模块设计-063001.md +++ b/docs/小红书模块设计-063001.md @@ -126,18 +126,12 @@ export default XHS; 'menu.system.xhsAiAssistant': 'AI 助手', ``` -### 2.3 Vite / Nginx SPA 规则 +### 2.3 Vite / SPA 规则 -`/xhs/*` 为纯前端路由,须加入: +`/xhs/*` 为纯前端路由: -- `vite.config.ts` → `frontendRoutes` 增加 `'/xhs'` -- `nginx-default.conf` → 在 API 反代规则之前增加: - -```nginx -location ~ ^/xhs { - try_files $uri /index.html; -} -``` +- `vite.config.ts` → `frontendRoutes` 增加 `'/xhs'`(开发 history fallback) +- 生产由前端容器 `serve -s` 回退 `index.html`;API 走分域名 `api.*`,无需站内 nginx --- diff --git a/docs/微信登录整合方案.md b/docs/微信登录整合方案.md index f30afbf..20c3229 100644 --- a/docs/微信登录整合方案.md +++ b/docs/微信登录整合方案.md @@ -422,17 +422,10 @@ src/SimpleAdmin.Api/ | Token | 与数据库/AppSettings 一致 | | 消息加解密 | **明文**(当前实现) | -### 7.3 Nginx +### 7.3 网关 / 回调 -`nginx-default.conf` 关键规则: - -```nginx -# 微信回调 -location ^~ /api/apiwechat/ { - rewrite ^/api/apiwechat/(.*)$ /admin/apiwechat/$1 break; - proxy_pass https://api.nanafa.com; -} -``` +生产已弃用站内 nginx。微信服务器回调应直连 **API 域名**(如 `https://api.ideship.com/admin/apiwechat/verification`),由 Traefik Ingress 转发到后端 Service;前端静态容器不做 `/api/apiwechat` 反代。 +本地开发仍可由 Vite 代理 `/api/apiwechat` → Admin。 --- diff --git a/nginx-default.conf b/nginx-default.conf deleted file mode 100644 index 6e9d274..0000000 --- a/nginx-default.conf +++ /dev/null @@ -1,489 +0,0 @@ -# ============ 生产环境部署必读(避免「本地可以、线上不行」)============ -# 1. 本文件必须真正生效:确认 oms.nanafa.com 的请求由「本 server 块」处理 -# - 若用 include:确保 include 的是含本 server 的 conf,且无其它 server 抢先匹配 -# - 更新后必须执行:nginx -t && nginx -s reload -# 2. /api、/Track、/rbac、/order 等 Admin 接口均由 nginx 代理到 api.nanafa.com,浏览器只访问 oms 同源 -# 3. HTTPS:证书部署到服务器(勿提交 .key 到 git) -# /etc/nginx/ssl/oms.nanafa.com.pem -# /etc/nginx/ssl/oms.nanafa.com.key -# 4. 官网 `/` 走 Vue SPA;静态资源在 /site/;客户登录 /login;管理端 /admin -# 5. 静态资源使用 /login-assets/,勿使用 /login/ 目录名 -# 6. 微信公众号服务器 URL 请使用 https://api.ideship.com/admin/apiwechat/verification -# (生产三套:admin / itfx / track,均挂在 https://api.ideship.com/{pathbase}) -# ============================================================================ - -# HTTP → HTTPS -server { - listen 80; - server_name oms.nanafa.com; - - return 301 https://$host$request_uri; -} - -server { - listen 443 ssl; - http2 on; - server_name oms.nanafa.com; - - ssl_certificate /etc/nginx/ssl/oms.nanafa.com.pem; - ssl_certificate_key /etc/nginx/ssl/oms.nanafa.com.key; - - ssl_session_timeout 1d; - ssl_session_cache shared:OMS_SSL:10m; - ssl_protocols TLSv1.2 TLSv1.3; - ssl_prefer_server_ciphers off; - - # 启用gzip压缩 - gzip on; - gzip_vary on; - gzip_min_length 1024; - gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json application/xml image/svg+xml; - gzip_comp_level 6; - gzip_disable "msie6"; - - root /usr/share/nginx/html; - - # ============ 官网首页(Vue SPA)============ - location = / { - try_files /index.html =200; - add_header Cache-Control "no-cache, no-store, must-revalidate"; - add_header Pragma "no-cache"; - add_header Expires "0"; - } - - location = /9610.html { - try_files /9610.html =404; - add_header Cache-Control "no-cache, no-store, must-revalidate"; - } - - # 官网仅静态资源在 /site/;首页保持在 / - location = /site { - return 301 /; - } - location = /site/ { - return 301 /; - } - location = /site/index.html { - return 301 /; - } - - location ^~ /site/ { - try_files $uri =404; - expires 7d; - add_header Cache-Control "public"; - access_log off; - } - - location = /favicon.ico { - try_files /favicon.png =404; - expires 7d; - add_header Cache-Control "public"; - access_log off; - } - - location = /favicon.png { - try_files /favicon.png =404; - expires 7d; - add_header Cache-Control "public"; - access_log off; - } - - # ============ 客户 / 管理端登录入口 ============ - location = /login { - try_files /index.html =200; - } - location = /login/ { - try_files /index.html =200; - } - - rewrite ^/admin/?$ /index.html last; - - location = /admin { - try_files /index.html =200; - } - location = /admin/ { - try_files /index.html =200; - } - - # ============ API 前端路由(必须先于 /api/ 代理)============ - location ~ ^/api/(upstreamInterface|upstreamInterfaceConfig|upstreamInterfaceConfigEdit|downstreamInterface(|/newPort)|appList(|/createApplication)|requestLog|callStatistics|apiDebugger|apiTest|openApi)(/|$) { - try_files /index.html =200; - } - - # ============ 小红书前端路由(^~ 须比下方 /xhs/ API 更具体)============ - location ^~ /xhs/startService { - try_files /index.html =200; - } - location ^~ /xhs/creation { - try_files /index.html =200; - } - location ^~ /xhs/publishHistory { - try_files /index.html =200; - } - location ^~ /xhs/skills { - try_files /index.html =200; - } - location ^~ /xhs/humanSettings { - try_files /index.html =200; - } - location ^~ /xhs/agentPair { - try_files /index.html =200; - } - location = /xhs/analysis { - try_files /index.html =200; - } - location = /xhs/analysis/ { - try_files /index.html =200; - } - - # ============ 微信 H5 / 操作页(^~ 须比下方 API 前缀更长或更具体)============ - location ^~ /wechat/register { - try_files /index.html =200; - } - location ^~ /wechat/bind { - try_files /index.html =200; - } - location ^~ /h5 { - try_files /index.html =200; - } - location ^~ /operation/inboundScan { - try_files /index.html =200; - } - location ^~ /operation/outboundScan { - try_files /index.html =200; - } - location ^~ /operation/printLabel { - try_files /index.html =200; - } - location ^~ /operation/parcelArrival { - try_files /index.html =200; - } - location ^~ /operation/fulfillPack { - try_files /index.html =200; - } - - # ============ 订单前端路由(^~ 须比下方 /order/ API 正则代理更优先)============ - location ^~ /order/priceCheck { - try_files /index.html =200; - } - location ^~ /order/placeOrder { - try_files /index.html =200; - } - location ^~ /order/myOrders { - try_files /index.html =200; - } - location ^~ /order/fulfillOrders { - try_files /index.html =200; - } - location ^~ /order/waybillManage { - try_files /index.html =200; - } - location ^~ /order/pickupOrder { - try_files /index.html =200; - } - location ^~ /order/customs9610Order { - try_files /index.html =200; - } - location ^~ /order/batchJobs { - try_files /index.html =200; - } - location ^~ /order/templateMapping { - try_files /index.html =200; - } - location ^~ /order/platformStore { - try_files /index.html =200; - } - location ^~ /order/platformStoreOrder { - try_files /index.html =200; - } - - # ============ 知识库前端路由(^~ 须比下方 /kb/ API 代理更优先)============ - location ^~ /kb/category { - try_files /index.html =200; - } - location ^~ /kb/article { - try_files /index.html =200; - } - - # ============ 仓储前端路由(^~ 须比下方 /warehouse/ API 正则代理更优先)============ - # 页面路径与 API 前缀相同者用精确匹配,避免 /warehouse/sku/list 等接口被误判为 SPA - location = /warehouse/parcel { - try_files /index.html =200; - } - location = /warehouse/inventory { - try_files /index.html =200; - } - location = /warehouse/sku { - try_files /index.html =200; - } - location = /warehouse/binLocation { - try_files /index.html =200; - } - location ^~ /warehouse/inboundNotice { - try_files /index.html =200; - } - - # 采集插件确认页(/Plugin/AddPackage);API 走 /plugin/browser/* - location ^~ /Plugin/ { - try_files /index.html =200; - } - - # ============ 渠道前端路由(^~ 须比下方 /channel/ API 正则代理更优先)============ - location ^~ /channel/salesProducts { try_files /index.html =200; } - location ^~ /channel/serviceChannels { try_files /index.html =200; } - location ^~ /channel/priceArea { try_files /index.html =200; } - location ^~ /channel/blacklist { try_files /index.html =200; } - location ^~ /channel/remoteZones { try_files /index.html =200; } - location ^~ /channel/weightRules { try_files /index.html =200; } - location ^~ /channel/weightRounding { try_files /index.html =200; } - location ^~ /channel/autoTrigger { try_files /index.html =200; } - location ^~ /channel/issueTemplate { try_files /index.html =200; } - location ^~ /channel/labelDesign { try_files /index.html =200; } - location ^~ /channel/guide { try_files /index.html =200; } - - # ============ 系统管理前端路由(^~ 须比下方 /system/ API 正则代理更优先)============ - # 页面路径为 camelCase;API 为 kebab(如 /system/dict/list、/system/batch-email/…),勿用宽泛前缀匹配 dict - location = /system/dict { - try_files /index.html =200; - } - location = /system/warehouseAddress { - try_files /index.html =200; - } - location = /system/announcement { - try_files /index.html =200; - } - location = /system/country { - try_files /index.html =200; - } - location ^~ /system/users { - try_files /index.html =200; - } - location ^~ /system/roles { - try_files /index.html =200; - } - location ^~ /system/menus { - try_files /index.html =200; - } - location ^~ /system/organizations { - try_files /index.html =200; - } - location ^~ /system/batchEmail { - try_files /index.html =200; - } - location ^~ /system/otherConfig { - try_files /index.html =200; - } - location ^~ /system/aiAssistant { - try_files /index.html =200; - } - location ^~ /system/aiSkills { - try_files /index.html =200; - } - location ^~ /system/mcpTools { - try_files /index.html =200; - } - location ^~ /system/dataPerm/ { - try_files /index.html =200; - } - - # ============ 营销前端路由(^~ 须比下方 /marketing/ API 正则代理更优先)============ - location ^~ /marketing/memberLevel { try_files /index.html =200; } - location ^~ /marketing/pointsRule { try_files /index.html =200; } - location ^~ /marketing/pointsFlow { try_files /index.html =200; } - location ^~ /marketing/couponTemplate { try_files /index.html =200; } - location ^~ /marketing/couponGrant { try_files /index.html =200; } - location ^~ /marketing/commissionRule { try_files /index.html =200; } - location ^~ /marketing/commissionDetail { try_files /index.html =200; } - location ^~ /marketing/commissionWithdraw { try_files /index.html =200; } - location ^~ /marketing/referralTree { try_files /index.html =200; } - - # ============ 微信公众号服务器回调(admin API,非 itfx)============ - location ^~ /api/apiwechat/ { - rewrite ^/api/apiwechat/(.*)$ /admin/apiwechat/$1 break; - proxy_pass http://api.nanafa.com; - proxy_http_version 1.1; - proxy_set_header Host api.nanafa.com; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_connect_timeout 30s; - proxy_send_timeout 30s; - proxy_read_timeout 30s; - } - - # ============ API 代理(仅真实后端接口,同源请求避免跨域 405)============ - location ~ ^/api/ { - rewrite ^/api/(.*)$ /itfx/$1 break; - proxy_pass http://api.nanafa.com; - proxy_http_version 1.1; - proxy_set_header Host api.nanafa.com; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_connect_timeout 30s; - proxy_send_timeout 30s; - proxy_read_timeout 30s; - } - - location ^~ /Track { - rewrite ^/Track(.*)$ /track/Track$1 break; - proxy_pass http://api.nanafa.com; - proxy_http_version 1.1; - proxy_set_header Host api.nanafa.com; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_connect_timeout 30s; - proxy_send_timeout 30s; - proxy_read_timeout 30s; - } - - # ============ Admin API 同源反代(/rbac /order /xhs … → api.nanafa.com/admin)============ - location ~ ^/(rbac|order|monitor|customer|recharge|channel|system|warehouse|plugin|marketing|kb)/ { - rewrite ^/(.*)$ /admin/$1 break; - proxy_pass http://api.nanafa.com; - proxy_http_version 1.1; - proxy_set_header Host api.nanafa.com; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_connect_timeout 30s; - proxy_send_timeout 30s; - proxy_read_timeout 120s; - } - - location ^~ /wechat/ { - rewrite ^/(.*)$ /admin/$1 break; - proxy_pass http://api.nanafa.com; - proxy_http_version 1.1; - proxy_set_header Host api.nanafa.com; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_connect_timeout 30s; - proxy_send_timeout 30s; - proxy_read_timeout 120s; - } - - location ^~ /operation/ { - rewrite ^/(.*)$ /admin/$1 break; - proxy_pass http://api.nanafa.com; - proxy_http_version 1.1; - proxy_set_header Host api.nanafa.com; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_connect_timeout 30s; - proxy_send_timeout 30s; - proxy_read_timeout 120s; - } - - location ^~ /xhs/ { - rewrite ^/(.*)$ /admin/$1 break; - proxy_pass http://api.nanafa.com; - proxy_http_version 1.1; - proxy_set_header Host api.nanafa.com; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_connect_timeout 30s; - proxy_send_timeout 30s; - proxy_read_timeout 300s; - } - - location ^~ /uploads/ { - rewrite ^/(.*)$ /admin/$1 break; - proxy_pass http://api.nanafa.com; - proxy_http_version 1.1; - proxy_set_header Host api.nanafa.com; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_connect_timeout 30s; - proxy_send_timeout 30s; - proxy_read_timeout 120s; - } - - location ^~ /mcp/ { - rewrite ^/(.*)$ /admin/$1 break; - proxy_pass http://api.nanafa.com; - proxy_http_version 1.1; - proxy_set_header Host api.nanafa.com; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_connect_timeout 30s; - proxy_send_timeout 30s; - proxy_read_timeout 300s; - } - - location ^~ /ai/ { - rewrite ^/(.*)$ /admin/$1 break; - proxy_pass http://api.nanafa.com; - proxy_http_version 1.1; - proxy_set_header Host api.nanafa.com; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_connect_timeout 30s; - proxy_send_timeout 30s; - proxy_read_timeout 300s; - } - - # HTML 不缓存 - location = /index.html { - add_header Cache-Control "no-cache, no-store, must-revalidate"; - add_header Pragma "no-cache"; - add_header Expires "0"; - } - - # 微信 JS 安全域名校验:原样返回 txt,禁止 SPA 回落 index.html - location ~* ^/MP_verify_[A-Za-z0-9]+\.txt$ { - default_type text/plain; - charset off; - add_header Cache-Control "no-store"; - try_files $uri =404; - } - - # ============ 静态资源缓存 ============ - - location ~* \.(?:js|css)$ { - try_files $uri =404; - expires 1y; - add_header Cache-Control "public, immutable"; - access_log off; - } - - location ~* \.(?:jpg|jpeg|png|gif|ico|svg|webp|avif)$ { - try_files $uri =404; - expires 1y; - add_header Cache-Control "public, immutable"; - access_log off; - } - - location ~* \.(?:woff2?|ttf|eot|otf)$ { - try_files $uri =404; - expires 1y; - add_header Cache-Control "public, immutable"; - access_log off; - } - - location ~* \.(?:pdf|zip|tar|gz|br)$ { - try_files $uri =404; - expires 1M; - add_header Cache-Control "public"; - access_log off; - } - - # ============ SPA 前端路由(放在最后)============ - # 不用 try_files $uri $uri/ —— 若磁盘存在同名目录且无 index,会 403 且不会回落 index.html - location / { - index index.html; - try_files $uri /index.html; - } - - error_page 500 502 503 504 /50x.html; - location = /50x.html { - root html; - } -} diff --git a/nginx-docker.conf b/nginx-docker.conf deleted file mode 100644 index 9cf8ed8..0000000 --- a/nginx-docker.conf +++ /dev/null @@ -1,279 +0,0 @@ -# Docker 容器专用:只监听 80,不配置 SSL(7962:80,由外层网关/宿主机 nginx 终结 HTTPS) -server { - listen 80; - server_name _; - - gzip on; - gzip_vary on; - gzip_min_length 1024; - gzip_types text/plain text/css text/xml text/javascript application/javascript application/json application/xml image/svg+xml; - - root /usr/share/nginx/html; - - location = / { - try_files /index.html =200; - add_header Cache-Control "no-cache, no-store, must-revalidate"; - add_header Pragma "no-cache"; - add_header Expires "0"; - } - - location = /9610.html { - try_files /9610.html =404; - add_header Cache-Control "no-cache, no-store, must-revalidate"; - } - - location = /site { - return 301 /; - } - location = /site/ { - return 301 /; - } - location = /site/index.html { - return 301 /; - } - - location ^~ /site/ { - try_files $uri =404; - expires 7d; - add_header Cache-Control "public"; - access_log off; - } - - location = /favicon.ico { - try_files /favicon.png =404; - expires 7d; - add_header Cache-Control "public"; - access_log off; - } - - location = /favicon.png { - try_files /favicon.png =404; - expires 7d; - add_header Cache-Control "public"; - access_log off; - } - - location = /login { - try_files /index.html =200; - } - location = /login/ { - try_files /index.html =200; - } - - rewrite ^/admin/?$ /index.html last; - - location = /admin { - try_files /index.html =200; - } - location = /admin/ { - try_files /index.html =200; - } - - location ~ ^/api/(upstreamInterface|upstreamInterfaceConfig|upstreamInterfaceConfigEdit|downstreamInterface(|/newPort)|appList(|/createApplication)|requestLog|callStatistics|apiDebugger|apiTest|openApi)(/|$) { - try_files /index.html =200; - } - - location ^~ /xhs/startService { try_files /index.html =200; } - location ^~ /xhs/creation { try_files /index.html =200; } - location ^~ /xhs/publishHistory { try_files /index.html =200; } - location ^~ /xhs/skills { try_files /index.html =200; } - location ^~ /xhs/humanSettings { try_files /index.html =200; } - location ^~ /xhs/agentPair { try_files /index.html =200; } - location = /xhs/analysis { try_files /index.html =200; } - location = /xhs/analysis/ { try_files /index.html =200; } - - location ^~ /wechat/register { try_files /index.html =200; } - location ^~ /wechat/bind { try_files /index.html =200; } - location ^~ /h5 { try_files /index.html =200; } - location ^~ /track/query { try_files /index.html =200; } - location ^~ /operation/inboundScan { try_files /index.html =200; } - location ^~ /operation/outboundScan { try_files /index.html =200; } - location ^~ /operation/printLabel { try_files /index.html =200; } - location ^~ /operation/parcelArrival { try_files /index.html =200; } - location ^~ /operation/fulfillPack { try_files /index.html =200; } - - # 订单前端路由(^~ 须比下方 /order/ API 正则代理更优先) - location ^~ /order/priceCheck { try_files /index.html =200; } - location ^~ /order/placeOrder { try_files /index.html =200; } - location ^~ /order/myOrders { try_files /index.html =200; } - location ^~ /order/fulfillOrders { try_files /index.html =200; } - location ^~ /order/waybillManage { try_files /index.html =200; } - location ^~ /order/pickupOrder { try_files /index.html =200; } - location ^~ /order/customs9610Order { try_files /index.html =200; } - location ^~ /order/batchJobs { try_files /index.html =200; } - location ^~ /order/templateMapping { try_files /index.html =200; } - location ^~ /order/platformStore { try_files /index.html =200; } - location ^~ /order/platformStoreOrder { try_files /index.html =200; } - - # 知识库前端路由(^~ 须比下方 /kb/ API 代理更优先) - location ^~ /kb/category { try_files /index.html =200; } - location ^~ /kb/article { try_files /index.html =200; } - - location = /warehouse/parcel { try_files /index.html =200; } - location = /warehouse/inventory { try_files /index.html =200; } - location = /warehouse/sku { try_files /index.html =200; } - location = /warehouse/binLocation { try_files /index.html =200; } - location ^~ /warehouse/inboundNotice { try_files /index.html =200; } - location ^~ /Plugin/ { try_files /index.html =200; } - - location ^~ /channel/salesProducts { try_files /index.html =200; } - location ^~ /channel/serviceChannels { try_files /index.html =200; } - location ^~ /channel/priceArea { try_files /index.html =200; } - location ^~ /channel/blacklist { try_files /index.html =200; } - location ^~ /channel/remoteZones { try_files /index.html =200; } - location ^~ /channel/weightRules { try_files /index.html =200; } - location ^~ /channel/weightRounding { try_files /index.html =200; } - location ^~ /channel/autoTrigger { try_files /index.html =200; } - location ^~ /channel/issueTemplate { try_files /index.html =200; } - location ^~ /channel/labelDesign { try_files /index.html =200; } - - # 营销前端路由(^~ 须比下方 /marketing/ API 正则代理更优先) - location ^~ /marketing/memberLevel { try_files /index.html =200; } - location ^~ /marketing/pointsRule { try_files /index.html =200; } - location ^~ /marketing/pointsFlow { try_files /index.html =200; } - location ^~ /marketing/couponTemplate { try_files /index.html =200; } - location ^~ /marketing/couponGrant { try_files /index.html =200; } - location ^~ /marketing/commissionRule { try_files /index.html =200; } - location ^~ /marketing/commissionDetail { try_files /index.html =200; } - location ^~ /marketing/commissionWithdraw { try_files /index.html =200; } - location ^~ /marketing/referralTree { try_files /index.html =200; } - - # 系统管理前端路由(^~ 须比下方 /system/ API 正则代理更优先) - location = /system/dict { try_files /index.html =200; } - location = /system/warehouseAddress { try_files /index.html =200; } - location = /system/announcement { try_files /index.html =200; } - location = /system/country { try_files /index.html =200; } - location ^~ /system/users { try_files /index.html =200; } - location ^~ /system/roles { try_files /index.html =200; } - location ^~ /system/menus { try_files /index.html =200; } - location ^~ /system/organizations { try_files /index.html =200; } - location ^~ /system/batchEmail { try_files /index.html =200; } - location ^~ /system/otherConfig { try_files /index.html =200; } - location ^~ /system/aiAssistant { try_files /index.html =200; } - location ^~ /system/aiSkills { try_files /index.html =200; } - location ^~ /system/mcpTools { try_files /index.html =200; } - location ^~ /system/dataPerm/ { try_files /index.html =200; } - - location ^~ /api/apiwechat/ { - rewrite ^/api/apiwechat/(.*)$ /admin/apiwechat/$1 break; - proxy_pass http://api.nanafa.com; - proxy_http_version 1.1; - proxy_set_header Host api.nanafa.com; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - } - - location ~ ^/api/ { - rewrite ^/api/(.*)$ /itfx/$1 break; - proxy_pass http://api.nanafa.com; - proxy_http_version 1.1; - proxy_set_header Host api.nanafa.com; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - } - - location ^~ /Track { - rewrite ^/Track(.*)$ /track/Track$1 break; - proxy_pass http://api.nanafa.com; - proxy_http_version 1.1; - proxy_set_header Host api.nanafa.com; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - } - - location ~ ^/(rbac|order|monitor|customer|recharge|channel|system|warehouse|plugin|marketing|kb)/ { - rewrite ^/(.*)$ /admin/$1 break; - proxy_pass http://api.nanafa.com; - proxy_http_version 1.1; - proxy_set_header Host api.nanafa.com; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_read_timeout 120s; - } - - location ^~ /wechat/ { - rewrite ^/(.*)$ /admin/$1 break; - proxy_pass http://api.nanafa.com; - proxy_http_version 1.1; - proxy_set_header Host api.nanafa.com; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - } - - location ^~ /operation/ { - rewrite ^/(.*)$ /admin/$1 break; - proxy_pass http://api.nanafa.com; - proxy_http_version 1.1; - proxy_set_header Host api.nanafa.com; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - } - - location ^~ /xhs/ { - rewrite ^/(.*)$ /admin/$1 break; - proxy_pass http://api.nanafa.com; - proxy_http_version 1.1; - proxy_set_header Host api.nanafa.com; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_read_timeout 300s; - } - - location ^~ /uploads/ { - rewrite ^/(.*)$ /admin/$1 break; - proxy_pass http://api.nanafa.com; - proxy_http_version 1.1; - proxy_set_header Host api.nanafa.com; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_read_timeout 120s; - } - - location ^~ /mcp/ { - rewrite ^/(.*)$ /admin/$1 break; - proxy_pass http://api.nanafa.com; - proxy_http_version 1.1; - proxy_set_header Host api.nanafa.com; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_read_timeout 300s; - } - - location ^~ /ai/ { - rewrite ^/(.*)$ /admin/$1 break; - proxy_pass http://api.nanafa.com; - proxy_http_version 1.1; - proxy_set_header Host api.nanafa.com; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_read_timeout 300s; - } - - location = /index.html { - add_header Cache-Control "no-cache, no-store, must-revalidate"; - add_header Pragma "no-cache"; - add_header Expires "0"; - } - - location ~* \.(?:js|css)$ { - try_files $uri =404; - expires 1y; - add_header Cache-Control "public, immutable"; - access_log off; - } - - location / { - index index.html; - try_files $uri /index.html; - } -} diff --git a/nginx-k3s.conf b/nginx-k3s.conf deleted file mode 100644 index 6b3f6ab..0000000 --- a/nginx-k3s.conf +++ /dev/null @@ -1,225 +0,0 @@ -# k3s 方案 A:仅静态 SPA。API 由浏览器按域名直连(prod: api.ideship.com / test: api.test.ideship.com)。 -server { - listen 80; - server_name _; - - gzip on; - gzip_vary on; - gzip_min_length 1024; - gzip_types text/plain text/css text/xml text/javascript application/javascript application/json application/xml image/svg+xml; - - root /usr/share/nginx/html; - - location = / { - try_files $uri @spa; - } - - location = /9610.html { - try_files /9610.html =404; - add_header Cache-Control "no-cache, no-store, must-revalidate"; - } - - location = /site { - return 301 /; - } - location = /site/ { - return 301 /; - } - location = /site/index.html { - return 301 /; - } - - location ^~ /site/ { - try_files $uri =404; - expires 7d; - add_header Cache-Control "public"; - access_log off; - } - - location = /favicon.ico { - try_files /favicon.png =404; - expires 7d; - add_header Cache-Control "public"; - access_log off; - } - - location = /favicon.png { - try_files /favicon.png =404; - expires 7d; - add_header Cache-Control "public"; - access_log off; - } - - location = /login { - try_files $uri @spa; - } - location = /login/ { - try_files $uri @spa; - } - - rewrite ^/admin/?$ /index.html last; - - location = /admin { - try_files $uri @spa; - } - location = /admin/ { - try_files $uri @spa; - } - - location ~ ^/api/(upstreamInterface|upstreamInterfaceConfig|upstreamInterfaceConfigEdit|downstreamInterface(|/newPort)|appList(|/createApplication)|requestLog|callStatistics|apiDebugger|apiTest|openApi)(/|$) { - try_files $uri @spa; - } - - location ^~ /xhs/startService { try_files $uri @spa; } - location ^~ /xhs/creation { try_files $uri @spa; } - location ^~ /xhs/publishHistory { try_files $uri @spa; } - location ^~ /xhs/skills { try_files $uri @spa; } - location ^~ /xhs/humanSettings { try_files $uri @spa; } - location ^~ /xhs/agentPair { try_files $uri @spa; } - location = /xhs/analysis { try_files $uri @spa; } - location = /xhs/analysis/ { try_files $uri @spa; } - - location ^~ /wechat/register { try_files $uri @spa; } - location ^~ /wechat/bind { try_files $uri @spa; } - location ^~ /h5 { try_files $uri @spa; } - location ^~ /track/query { try_files $uri @spa; } - location ^~ /operation/inboundScan { try_files $uri @spa; } - location ^~ /operation/outboundScan { try_files $uri @spa; } - location ^~ /operation/printLabel { try_files $uri @spa; } - location ^~ /operation/parcelArrival { try_files $uri @spa; } - location ^~ /operation/fulfillPack { try_files $uri @spa; } - - # 订单前端路由(^~ 须比下方 /order/ API 正则代理更优先) - location ^~ /order/priceCheck { try_files $uri @spa; } - location ^~ /order/placeOrder { try_files $uri @spa; } - location ^~ /order/myOrders { try_files $uri @spa; } - location ^~ /order/fulfillOrders { try_files $uri @spa; } - location ^~ /order/waybillManage { try_files $uri @spa; } - location ^~ /order/pickupOrder { try_files $uri @spa; } - location ^~ /order/customs9610Order { try_files $uri @spa; } - location ^~ /order/batchJobs { try_files $uri @spa; } - location ^~ /order/templateMapping { try_files $uri @spa; } - location ^~ /order/platformStore { try_files $uri @spa; } - location ^~ /order/platformStoreOrder { try_files $uri @spa; } - - # 知识库前端路由(^~ 须比下方 /kb/ API 代理更优先) - location ^~ /kb/category { try_files $uri @spa; } - location ^~ /kb/article { try_files $uri @spa; } - - location = /warehouse/parcel { try_files $uri @spa; } - location = /warehouse/inventory { try_files $uri @spa; } - location = /warehouse/sku { try_files $uri @spa; } - location = /warehouse/binLocation { try_files $uri @spa; } - location ^~ /warehouse/inboundNotice { try_files $uri @spa; } - location ^~ /Plugin/ { try_files $uri @spa; } - - location ^~ /channel/salesProducts { try_files $uri @spa; } - location ^~ /channel/serviceChannels { try_files $uri @spa; } - location ^~ /channel/priceArea { try_files $uri @spa; } - location ^~ /channel/blacklist { try_files $uri @spa; } - location ^~ /channel/remoteZones { try_files $uri @spa; } - location ^~ /channel/weightRules { try_files $uri @spa; } - location ^~ /channel/weightRounding { try_files $uri @spa; } - location ^~ /channel/autoTrigger { try_files $uri @spa; } - location ^~ /channel/issueTemplate { try_files $uri @spa; } - location ^~ /channel/labelDesign { try_files $uri @spa; } - - # 官网线路目录。这条不是前端路由;落到下方 SPA 会返回 index.html,浏览器看不到 JSON。 - # 仅这一条转到对应环境的 Admin API(test → api.test.ideship.com,其余 → api.ideship.com)。 - location = /channel/sales-product/portal/catalog { - set $oms_api_upstream api.ideship.com; - if ($host ~* "(^test\.ideship\.com$|\.test\.ideship\.com$)") { - set $oms_api_upstream api.test.ideship.com; - } - resolver 1.1.1.1 8.8.8.8 ipv6=off valid=300s; - resolver_timeout 5s; - proxy_http_version 1.1; - proxy_ssl_server_name on; - proxy_set_header Host $oms_api_upstream; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_pass https://$oms_api_upstream/admin/channel/sales-product/portal/catalog$is_args$args; - proxy_connect_timeout 10s; - proxy_read_timeout 30s; - } - - # 营销前端路由(^~ 须比下方 /marketing/ API 正则代理更优先) - location ^~ /marketing/memberLevel { try_files $uri @spa; } - location ^~ /marketing/pointsRule { try_files $uri @spa; } - location ^~ /marketing/pointsFlow { try_files $uri @spa; } - location ^~ /marketing/couponTemplate { try_files $uri @spa; } - location ^~ /marketing/couponGrant { try_files $uri @spa; } - location ^~ /marketing/commissionRule { try_files $uri @spa; } - location ^~ /marketing/commissionDetail { try_files $uri @spa; } - location ^~ /marketing/commissionWithdraw { try_files $uri @spa; } - location ^~ /marketing/referralTree { try_files $uri @spa; } - - # 面单/截图同源代理:/__cos__// → http:/// - # cos.ideship.com 自定义域名 https 证书不可用,上游走 http;避免浏览器直打 CORS / 混合内容 - location ~ ^/__cos__/([^/]+)(/.*)$ { - set $cos_host $1; - set $cos_uri $2; - resolver 1.1.1.1 8.8.8.8 ipv6=off valid=300s; - resolver_timeout 5s; - proxy_http_version 1.1; - proxy_set_header Host $cos_host; - proxy_set_header Authorization ""; - proxy_set_header Cookie ""; - proxy_set_header X-Real-IP ""; - proxy_pass http://$cos_host$cos_uri$is_args$args; - proxy_connect_timeout 10s; - proxy_read_timeout 120s; - proxy_buffering off; - } - - # 系统管理前端路由(^~ 须比下方 /system/ API 正则代理更优先) - location = /system/dict { try_files $uri @spa; } - location = /system/warehouseAddress { try_files $uri @spa; } - location = /system/announcement { try_files $uri @spa; } - location = /system/country { try_files $uri @spa; } - location ^~ /system/users { try_files $uri @spa; } - location ^~ /system/roles { try_files $uri @spa; } - location ^~ /system/menus { try_files $uri @spa; } - location ^~ /system/organizations { try_files $uri @spa; } - location ^~ /system/batchEmail { try_files $uri @spa; } - location ^~ /system/otherConfig { try_files $uri @spa; } - location ^~ /system/aiAssistant { try_files $uri @spa; } - location ^~ /system/aiSkills { try_files $uri @spa; } - location ^~ /system/mcpTools { try_files $uri @spa; } - location ^~ /system/dataPerm/ { try_files $uri @spa; } - - # SPA 回退:try_files $uri @spa 统一带 no-cache,避免部署后浏览器缓存旧 index.html - location @spa { - add_header Cache-Control "no-cache, no-store, must-revalidate" always; - add_header Pragma "no-cache" always; - add_header Expires "0" always; - try_files /index.html =404; - } - - location = /index.html { - add_header Cache-Control "no-cache, no-store, must-revalidate" always; - add_header Pragma "no-cache" always; - add_header Expires "0" always; - try_files /index.html =404; - } - - # 微信 JS 安全域名校验:原样返回 txt,禁止 SPA 回落 index.html - location ~* ^/MP_verify_[A-Za-z0-9]+\.txt$ { - default_type text/plain; - charset off; - add_header Cache-Control "no-store"; - try_files $uri =404; - } - - location ~* \.(?:js|css)$ { - try_files $uri =404; - expires 1y; - add_header Cache-Control "public, immutable"; - access_log off; - } - - location / { - try_files $uri @spa; - } -} diff --git a/src/App.vue b/src/App.vue index 9d2fb68..2d6db0f 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,21 +1,216 @@