Files
guilixu-admin/docs/运费模板-不发货地区-接口方案.md
T
gxwebsoft 3bc856fc95 feat(shopGoods): 优化商品列表加载及封面图性能
- image.ts 中 getCompressedImageUrl 增加缓存,避免列表重渲染时重复计算压缩 URL
- shopGoods 页面用原生 img 标签替换 antdv a-image,支持浏览器懒加载减少首屏网络压力
- shopGoods 页面数据加载流程优化,取消表格自动首屏加载,改为手动触发,合并请求避免重复调用
- 首屏分类数据延迟加载,不阻塞首屏渲染,提升页面响应速度
- search.vue 中用 onMounted 替代 watch immediate,防止首次入场重复触发请求
- 新增商品封面图样式,保证图片大小固定且样式统一
2026-08-06 17:19:15 +08:00

7.3 KiB
Raw Blame History

运费模板「不发货地区(排除地区)」接口方案

目标:支持商家配置"除部分偏远地区外,全国均可配送"的场景,避免逐个添加可配送省份。 前端代码库:guilixu-adminshop 模块接口走 MODULES_API_URL,即 mp-java 的 shop 模块)


一、现状(改造前)

  • 一条 shop_express_template_detail = 一种配送区域 + 一套运费规则。
  • 当前只能选 1 个省市组合,字段为 province_id + city_id(单值)。
  • 不选 = 默认全国。
  • 无任何排除/不发货逻辑

二、需求(改造后)

配送区域支持两种模式:

模式 含义 典型场景
白名单(指定配送) 只发列表中的地区 仅发江浙沪
黑名单(指定不发货) 发列表外的所有地区 除新疆/西藏/港澳台外全国发

新增「不发货地区」配置:商家框选不发货的省/市,保存后这些地区下单时报"暂不配送"。

三、数据库变更

shop_express_template_detail 表新增两个字段(存储方案选型见下方说明):

存储方案选型:推荐逗号分隔单字段,不新建关联表。 理由:① 本业务查询模式是「模板→明细」,非「地区→模板」,无需按地区反查;② 排除地区通常仅几个省,VARCHAR(2000) 足够;③ 改动最小、前端直接透传编码字符串、可快速上线满足客户急迫配置需求。若未来需「按地区统计运费模板」等报表,再迁关联表。

ALTER TABLE shop_express_template_detail
  ADD COLUMN region_mode TINYINT NOT NULL DEFAULT 0 COMMENT '配送区域模式: 0=全国, 1=指定配送(白名单), 2=指定不发货(黑名单)',
  ADD COLUMN region_ids VARCHAR(2000) DEFAULT NULL COMMENT '地区编码列表(与regions-data.json一致),逗号分隔,如 110000,120000。region_mode=1或2时有效';
  • region_mode=0(全国):region_ids 为空,兼容旧"不选=全国"行为。
  • region_mode=1/2region_ids 存选中的地区编码(省/市/区 6 位编码,与前端 regions-data.jsonvalue 一致)。

旧数据兼容

历史数据 province_id / city_id 保留不删。迁移建议:

  • 旧数据 region_mode 默认置 1region_ids = province_id[,city_id](有 city 才拼)。
  • 前端编辑时若检测到旧字段(无 region_mode),按 province_id/city_id 回显到白名单模式。

四、region_ids 存储与匹配规则

  • 最小选中粒度编码:用户选到省只存省码,选到市存市码(省码可推导,不必冗余存)。
  • 编码前缀关系:区码 110101 ⊃ 市码 110100 ⊃ 省码 110000
  • 匹配算法(下单时使用):
    • 收货地址解析出 省码 / 市码 / 区码。
    • 命中判断:region_ids 中包含收货地的 省码 市码 区码 即视为命中该条明细。
  • 推荐:前端提交时统一存省+市两级(不存区),简化逻辑;如需区县级排除再加。

五、下单配送校验逻辑(后端 + 小程序端双重校验)

收货地址 → 解析 {provinceCode, cityCode, districtCode}

1. 查该商品运费模板下所有 detail 明细
2. 遍历所有 region_mode=2(黑名单) 明细:
     若 收货地省/市/区码 任一 ∈ 该明细.region_ids
       → 直接判定【不配送】,返回 "该地区暂不配送"
3. 若无黑名单命中,按现有逻辑选运费明细:
     - region_mode=0(全国) 明细 → 匹配
     - region_mode=1(白名单) 明细 → 收货地码 ∈ region_ids 才匹配
4. 无任何明细匹配 → 不配送(或走默认模板,按业务定)

优先级:黑名单排除 > 白名单/全国匹配。即一旦落入不发货列表,直接不可下单。

六、接口变更

涉及接口(mp-java ShopExpressTemplateDetailController):

接口 METHOD & PATH 变更
新增明细 POST /shop/shop-express-template-detail 入参加 regionModeregionIds
修改明细 PUT /shop/shop-express-template-detail 入参加 regionModeregionIds
明细详情 GET /shop/shop-express-template-detail/{id} 出参加 regionModeregionIds
明细列表 GET /shop/shop-express-template-detail/page 出参加 regionModeregionIds

入参示例(新增):

{
  "templateId": 12,
  "type": true,
  "regionMode": 2,
  "regionIds": "650000,540000,810000,820000,710000",
  "firstNum": "1",
  "firstAmount": "0",
  "extraNum": "1",
  "extraAmount": "0",
  "status": 0,
  "sortNumber": 100
}

七、需后端确认的问题 —— 已确认(2026-08-06 后端已实现)

落地仓库:guilixu-java(不是 mp-java;两边 shop 模块原本字节一致,本次只改 guilixu-java)。

# 问题 结论
1 编码 vs 名称 存编码。6 位行政区划码,与 regions-data.jsonvalue 一致。
2 粒度 省/市/区三级都支持。前端建议只提交省+市两级;后端匹配时省/市/区任一命中即算命中。
3 黑白名单优先级 确认:黑名单命中即不可下单,优先级高于白名单/全国。允许同一模板下多种模式共存。
4 旧数据迁移 由后端 SQL 一次性迁移,见 sql/shop_express_template_detail_region.sql。经核查现网 province_id/city_id 存的就是 6 位区划码(如 150000/150200),可直接拼接,无需映射表。
5 下单校验落点 后端统一做,已接入 OrderBusinessService.createOrder() 第 3.2 步,防绕过。小程序端可另做前置提示。
6 多模板 按租户维度跨模板取并集。因 shop_goods 目前未与运费模板建立关联字段,按"本店除偏远地区外全国发货"的语义处理;后续商品绑定模板后可加 templateId 过滤。

后端实现要点(前端需知)

  • 新增字段regionMode(Integer) + regionIds(String),已贯通 page / list / get / save / update 全部接口,直接传即可。
  • regionIds 格式:逗号分隔的 6 位编码字符串,如 "650000,540000,810000,820000,710000"
  • regionMode 取值0=全国、1=指定配送(白名单)、2=指定不发货(黑名单)。默认 0
  • 列表筛选regionMode 支持精确筛选;regionIds 支持模糊包含筛选。
  • 旧数据回显:迁移 SQL 已把历史行刷成 regionMode=1 + regionIds,前端无需再兼容 province_id/city_id 回显逻辑。
  • 地址名称→编码:后端 RegionCodeResolver 负责把 shop_user_address 里的省/市/区名称翻译成编码(该表只存名称不存编码)。已处理 新疆维吾尔自治区新疆北京市北京 等后缀归一化。
  • 拦截文案:命中时后端抛 BusinessException,接口返回形如 "新疆维吾尔自治区暂不配送,请更换收货地址",前端直接展示 message 即可。
  • 放行兜底:地址解析不出行政区划编码时(境外地址等)放行不拦截,避免误伤。

⚠️ 上线顺序:必须先执行 sql/shop_express_template_detail_region.sql,再发布后端,否则查询会报未知列。


前端侧对应改造:新建 RegionsTransfer 双栏选择组件 + 改造 shopExpressTemplateDetailEdit.vue 增加模式切换 + 列表回显。