hl-api-changelog/changelogs-v2/2026-06/17_前端接线_新建订单选主题向导接口对照-后端已实现仅需接线-管理后台.md

11 KiB

【前端接线·管理后台】「新建订单」向导第1步「选主题」接口对照——后端核心全已实现,仅需前端接线含联动第2步「选产品」

页面:管理后台 → 订单 → 新建订单(order-v2/new第1步「选主题」、联动第2步「选产品」 | 服务hl-product-service-v2order-picker 端点)+ hl-order-service-v3热门下单量,内部 Feign| 无 PR,后端零改动 | 负责mmg 核验方式2026-06-17 源码全链路审计(热门链路追到 order-v3 Mapper 真查订单表)+ 测试服 admin token 经网关 9443 实测 3 端点全 200

⚠️ 关键判定:核心接口全部已实现且实测可用,没有缺失的必备接口

这个页面用到的后端接口全部已上线,热门标识是真实计算(不是写死/Mock。需要前端处理的只有 2 处「前端本地实现」(搜索、最近选过)、1 处「确认删除」(分类 tab,wx 已批注不需要)、1 处「待 wx 拍板」(卡片地区标签)。

术语对照(必读,否则字段对不上):前端「主题」= 后端「产品线 ProductLine」(lineId);前端「产品/版本」= 后端「产品 Product」(productId);前端「SKU/规格/档位」= 后端「档位 tier」(tierSeq)。

接口对照总表

页面数据块 后端落地 取数方式 前端动作
主题卡片网格 已实现 GET /admin/product/line/order-picker 直接接
「热」角标 + 「热门主题·直接进入」 已实现(真实算) 同上 hot 字段;入口=filter(hot==true) 本地筛,不要新接口
顶部统计头(在售数/SKU总/最低人均) ⚠️ 无接口 从上面列表前端派生 本地算
搜索框(主题/目的地/关键词) ⚠️ 无入参 在已返回列表本地模糊匹配 本地搜
分类筛选 tab西藏/云南/日本…) 确认删除 后端无目的地数据源,无法过滤 直接删
「最近选过」 ⚠️ 无接口 localStorage 本地历史 本地存取
第2步「选择产品」 已实现 GET /admin/product/item/order-picker?lineId= 直接接
选档位/规格 已实现 GET /admin/product/item/{productId}/tiers 直接接
网关路由 全放行 /admin/product/** → product-v2 经网关 9443 调通
卡片「国内·西藏」地区标签 wx 拍 A不显示 第1步主题 VO 不返回,后端零改动 地区标签不显示

1. 第1步「选主题」主接口直接接

GET /admin/product/line/order-picker(经网关 9443,路由已配 /admin/product/**

  • 入参:无(不分页,一次性返回全部在售主题;数据权限由后端按当前管理员自动过滤)
  • 返回Result<List<OrderPickerThemeVO>>
字段 类型 含义
lineId String雪花,序列化为字符串 主题ID,下一步选产品要传它
name String 主题名称(布达拉宫朝圣…)
description String 主题描述
coverImageUrl String 主题封面图 URL
productType String CORE=核心产品 / GROUP=小蒙马 / CUSTOM=私人定制
skuCount Integer 该主题下已上架产品的档位总数(= 页面「X 个 SKU」
fromPrice String(金额,可能为 null 最低成人起价(= 页面「起 ¥XXXX / 人」;全无价返 null,前端兜底)
hot Boolean 是否热门(见第 2 节)
  • 只返「ACTIVE + 下挂 ≥1 个已上架产品」的在售主题,按排序号升序。
  • ⚠️ fromPrice字符串(后端 @JsonSerialize(ToStringSerializer),防大数精度丢失),前端展示前自行 parseFloat

请求示例:

GET https://api.test.1814.love:9443/admin/product/line/order-picker
Authorization: Bearer {adminToken}

响应示例(节选,实测):

{
  "code": 200,
  "data": [
    { "lineId": "2056937785918369794", "name": "呼伦贝尔产品-yst", "productType": "CORE",
      "skuCount": 6, "fromPrice": "3105.00", "hot": true,
      "coverImageUrl": "https://hlgl-test.oss-cn-beijing.aliyuncs.com/...png", "description": "..." },
    { "lineId": "2043694738304880641", "name": "草原深度游", "productType": "CORE",
      "skuCount": 3, "fromPrice": "2980.00", "hot": false, "coverImageUrl": "...", "description": "..." }
  ]
}

2. 热门(「热」角标 + 「热门主题·直接进入」入口)——真实落地,无需新接口

  • hot唯一数据源:近 90 天下单量在当前返回列表内降序排名前 30%(向上取整、至少 1 名)且下单量 > 0true
  • 链路已核到底:product-v2 → 内部 Feign → order-v3 GET /v3/internal/order/stats/product-order-count → 真 selectCountorder_main 表(非 Mock)。实测当前测试库返回 1 个 hot=true 主题,证明实时计算生效。
  • 「热门主题·直接进入」不是独立接口 = 同一份 order-picker 列表里 hot==true 的子集,前端本地 filter 即可,不要再找/要求新接口
  • 降级行为order-v3 不可用时,列表照常返回但所有 hot=false(不报错、不阻断),前端按 hot=false 正常渲染即可(此时无角标、无热门入口属预期降级)。
  • 口径说明(非 bug,设计如此热门按「下单量(含未支付/已取消单)」算,不是「成交量」;在售主题很少时可能出现「几乎都标热」。如要改成「成交热」口径需 wx 另拍,目前保持现状。

3. 统计头 / 搜索框 / 最近选过 —— 前端本地实现,后端无接口(也不需要)

  • 统计头(在售主题数 / SKU 总数 / 最低人均):无独立接口,从第 1 节列表直接派生:
    • 在售主题数 = list.length
    • SKU 总数 = Σ skuCount
    • 最低人均 = min(fromPrice)(后端口径是「最低成人起价」,与「最低人均」基本等价;后端无单独「人均」概念)
  • 搜索框order-picker 零入参、不分页、一次返全量(量级 = 公司在售主题数,很小)。前端在已返回列表上按 name / description 本地模糊匹配即可,后端无需加参
  • 「最近选过」:后端无最近浏览接口(全范围 grep recent/viewed/footprint/history 仅命中小程序 C 端,与后台无关)。前端用 localStorage 自存浏览历史,无需对接后端。

4. 分类筛选 tab全部/西藏/内蒙古/云南…)—— 确认删除

  • wx 批注「不需要」正确,额外实锤product_line根本没有 region / 目的地 / 分类 任何结构化列(只有 name / product_type / description / seasons / tags / cover…,后端本就无法按目的地过滤主题。
  • → 前端直接删这排 tab,不要让后端补地区维度(那是另一个数据建模工程,非本页范畴)。

5. 第2步「选择产品」+ 选档位(直接接)

5.1 选产品列表GET /admin/product/item/order-picker?lineId={第1步选中的lineId}&keyword=&pageNo=1&pageSize=20

  • lineId 必填keyword 可选(按产品名模糊);分页。
  • 返回 PageResult<OrderPickerProductVO>,字段(实测全有):
字段 类型 含义
productId String 产品ID前端「版本」
name / subtitle String 产品名 / 副标题
tripDays / tripNights Integer 行程天数 / 晚数
tags List<String> 产品标签(实测返回 ["国内"] 之类
coverImageUrl String 封面图
startPrice String金额,可 null 起步价(各档位未来可售最低成人价的最小值)
tierPrices List 档位起价列表(档位序号/名称/描述/该档起价)
hot Boolean 是否热销同主题热门口径,order-v3 90 天下单量前 30%
nextSaleDate LocalDate可 null 最近可售日CORE/CUSTOM 取价格日历最早未来可售日,GROUP 取最近未来班期出发日)

5.2 选档位/规格GET /admin/product/item/{productId}/tiers

  • 返回 List,字段 tierSeq规格序号,1 起)/ tierName(如「舒适」)/ tierDescription
  • tierSeq后续算价/下单的入参,选档后带上。

6. 网关路由(无缺口)

  • /admin/product/**lb://hl-product-service-v2同时覆盖 /admin/product/line/**/admin/product/item/**,两个 order-picker 端点经网关 9443 正常调通。
  • order-v3 的 /v3/internal/... 是 product-v2 内部 Feign LB 直连不经网关,admin token 直调会被安全过滤返 403前端不直接调它,不算路由缺口。

已拍板:卡片「国内·西藏」地区标签 —— 不显示wx 2026-06-17 拍 A

页面每张主题卡片左上原有「国内·西藏 / 国内·云南」地区标签。第1步 order-pickerOrderPickerThemeVO不返回任何标签字段(数据虽存在于 product_line.tags、第2步产品 VO 也返 tags,但第1步主题 VO 未透出)。

结论:分类 tab 既已删,卡片地区标签一并不显示,后端零改动。 前端去掉卡片上的地区标签,不需要地区字段。(备查:若日后又要显示,最低成本是后端给 OrderPickerThemeVOtags 字段,1 个字段、低风险,但「国内·」国别前缀无干净来源。)

测试服实测admin token 经网关 9443,2026-06-17

端点 结果
GET /admin/product/line/order-picker code=200,9 个在售主题,SKU 总 33,最低起价 ¥10,热门 1 个(hot=true 实时算出)
GET /admin/product/item/order-picker?lineId=... code=200,返回字段含 productId/name/subtitle/tripDays/tripNights/tags/coverImageUrl/startPrice/tierPrices/hot/nextSaleDate
GET /admin/product/item/{productId}/tiers code=200,返回 tierSeq/tierName/tierDescription

前端 TODO 清单

  1. 第1步卡片网格GET /admin/product/line/order-picker(无参)。
  2. 「热」角标:用返回项 hot 渲染;「热门主题·直接进入」= 本地 filter(hot==true),不要新接口。
  3. 统计头:本地算(length / Σ skuCount / min(fromPrice))。
  4. 搜索框:本地按 name/description 匹配,不传后端。
  5. 删除分类筛选 tab(后端无数据源)。
  6. 「最近选过」:localStorage 本地实现。
  7. 第2步选产品GET /admin/product/item/order-picker?lineId={上一步lineId};选档位 GET /admin/product/item/{productId}/tiers,带 tierSeq 进算价/下单。
  8. 卡片地区标签:不显示wx 已拍 A,后端零改动
  9. 金额字段 fromPrice/startPrice字符串,展示前 parseFloat,注意 null 兜底。