hl-api-changelog/changelogs/2026-03/2026-03-19_custom_product_query.md
API Changelog Bot 7c3531e98a docs: 小程序已完成定制产品查询接口前端对接指南
新增2个C端接口:
- GET /mp/custom/product/{productId} 查询单个定制产品详情
- GET /mp/custom/products 我的已完成定制产品列表

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 11:13:02 +08:00

15 KiB

小程序已完成定制产品查询 - 前端对接指南

日期: 2026-03-19 后端状态: 已完成,测试服务器已部署 涉及模块: hl-mp-serviceBFF层、hl-product-service产品详情、hl-order-service定制需求关联 页面路由: 定制需求详情页 → 查看定制产品


功能说明

用户提交定制需求后,定制师会设计一个定制产品CUSTOM类型。产品设计完成后状态变为 COMPLETED,用户下单后变为 ORDERED

本次新增两个小程序端接口:

  1. 产品详情 — 根据产品ID查询单个已完成的定制产品定制需求详情页展示产品方案
  2. 产品列表 — 查询当前登录用户所有已完成的定制产品("我的定制"页展示列表)

业务流程

用户提交定制需求 → 定制师接单 → 设计产品(DRAFT)
  → 完成设计(COMPLETED) → 用户查看产品方案 → 下单(ORDERED)
                                ↑
                          本次新增接口覆盖此环节

聚合调用链

小程序 → /mp/custom/products (BFF)
  ├─ Feign → order-service: 获取用户定制需求关联的 productId 列表
  └─ Feign → product-service: 批量查询 CUSTOM + COMPLETED/ORDERED 产品

接口清单

# 接口 方法 路径 认证 说明
1 已完成定制产品详情 GET /mp/custom/product/{productId} 需登录 根据产品ID查询定制产品详情
2 我的已完成定制产品列表 GET /mp/custom/products 需登录 当前用户的所有已完成定制产品

接口 1已完成定制产品详情

使用场景:定制需求详情页中,当定制师完成产品设计后(状态 QUOTED/COMPLETED,前端通过定制需求中的 productId 调用此接口展示完整产品方案。

GET /mp/custom/product/{productId}

请求参数

参数 类型 位置 必填 说明
productId Long 路径 定制产品ID来自定制需求详情中的 productId 字段)

请求头

Header 说明
Authorization Bearer {token}JWT令牌

响应示例

{
  "code": 200,
  "message": "成功",
  "data": {
    "productId": "2026279738275856385",
    "productNo": "P20260319001",
    "productType": "CUSTOM",
    "name": "呼伦贝尔7日定制游-张三家庭",
    "subtitle": "专属家庭定制方案",
    "status": "COMPLETED",
    "tripDays": 7,
    "tripNights": 6,
    "departureCity": "北京",
    "destinationCity": "呼伦贝尔",
    "coverImageUrl": "https://oss.example.com/cover.jpg",
    "bannerImageUrls": ["https://oss.example.com/banner1.jpg"],
    "tags": ["草原", "亲子", "定制"],
    "seasons": ["SUMMER"],
    "seasonLabels": ["夏季"],
    "highlights": "...",
    "description": "...",
    "inclusions": "费用包含说明",
    "exclusions": "费用不含说明",
    "notes": "注意事项",
    "routeMapUrl": "https://oss.example.com/route-map.jpg",
    "itinerary": [
      {
        "dayIndex": 1,
        "title": "北京 → 海拉尔",
        "description": "...",
        "nodes": [...]
      }
    ],
    "staffConfigs": [
      {
        "staffType": "GUIDE",
        "staffName": "李导",
        "staffCount": 1,
        "dailyCost": 500.00
      }
    ],
    "families": [
      {
        "familyIndex": 1,
        "familyName": "张三家庭",
        "adultCount": 2,
        "childCount": 1
      }
    ],
    "creatorAvatarUrl": "https://oss.example.com/designer-avatar.jpg",
    "customizerId": "2026279738275856300",
    "createTime": "2026-03-19T10:30:00",
    "updateTime": "2026-03-19T15:00:00"
  }
}

响应字段

字段 类型 说明
productId String 产品ID雪花ID,用String接收
productNo String 产品编号P开头
productType String 产品类型,固定 CUSTOM
name String 产品名称
subtitle String 副标题
status String 产品状态:COMPLETED=已完成可下单、ORDERED=已有订单
tripDays Integer 行程天数
tripNights Integer 住宿晚数
departureCity String 出发城市
destinationCity String 目的地城市
coverImageUrl String 封面图URL
bannerImageUrls Array<String> 轮播图URL列表
tags Array<String> 产品标签
seasons Array<String> 适用季节编码
seasonLabels Array<String> 季节中文标签
highlights String 产品亮点
description String 详细描述
inclusions String 费用包含
exclusions String 费用不含
notes String 注意事项
routeMapUrl String 路线图URL
itinerary Array 行程安排(按天组织)
itinerary[].dayIndex Integer 第几天
itinerary[].title String 当天标题
itinerary[].description String 当天描述
itinerary[].nodes Array 行程节点列表
staffConfigs Array 人员配置(定制产品特有)
staffConfigs[].staffType String 人员类型GUIDE=导游等)
staffConfigs[].staffName String 人员姓名
staffConfigs[].staffCount Integer 人数
staffConfigs[].dailyCost BigDecimal 日费用
families Array 家庭分组(定制产品特有)
families[].familyIndex Integer 家庭序号
families[].familyName String 家庭名称
families[].adultCount Integer 成人数
families[].childCount Integer 儿童数
customizerId String 定制师ID
creatorAvatarUrl String 定制师头像URL
createTime String 创建时间
updateTime String 更新时间

错误响应

code message 说明
404 产品不存在 productId 无效
404 产品不存在(非定制产品) 不是 CUSTOM 类型
404 定制产品尚未完成 状态不是 COMPLETED/ORDERED

前端实现建议

  • 定制需求详情页中,当 statusQUOTEDCOMPLETEDproductId 不为空时,展示"查看定制方案"按钮
  • 点击按钮调用此接口,跳转到产品详情页展示完整方案
  • staffConfigsfamilies 是定制产品特有字段,需单独展示区域

接口 2我的已完成定制产品列表

使用场景"我的定制"页面展示用户所有已完成的定制产品列表。

GET /mp/custom/products

请求参数

无(自动取当前登录用户)

请求头

Header 说明
Authorization Bearer {token}JWT令牌

响应示例

{
  "code": 200,
  "message": "成功",
  "data": [
    {
      "productId": "2026279738275856385",
      "productType": "CUSTOM",
      "name": "呼伦贝尔7日定制游-张三家庭",
      "subtitle": "专属家庭定制方案",
      "tripDays": 7,
      "tripNights": 6,
      "departureCity": "北京",
      "destinationCity": "呼伦贝尔",
      "coverImageUrl": "https://oss.example.com/cover.jpg",
      "tags": ["草原", "亲子", "定制"],
      "seasons": ["SUMMER"],
      "seasonLabels": ["夏季"],
      "routeMapUrl": "https://oss.example.com/route-map.jpg",
      "creatorAvatarUrl": "https://oss.example.com/designer-avatar.jpg",
      "startPrice": 29800.00,
      "paymentMode": "DEPOSIT",
      "lineName": null
    }
  ]
}

响应字段

字段 类型 说明
productId String 产品ID
productType String 产品类型,固定 CUSTOM
name String 产品名称
subtitle String 副标题
tripDays Integer 行程天数
tripNights Integer 住宿晚数
departureCity String 出发城市
destinationCity String 目的地城市
coverImageUrl String 封面图URL
tags Array<String> 产品标签
seasons Array<String> 适用季节编码
seasonLabels Array<String> 季节中文标签
routeMapUrl String 路线图URL
creatorAvatarUrl String 定制师头像
startPrice BigDecimal 起步价整单售价,可能为null未设置价格日历
paymentMode String 支付方式:FULL-全额、DEPOSIT-定金
lineName String 产品线名称,可能为null

前端实现建议

  • uni-list 或自定义卡片列表展示
  • 每张卡片展示:封面图 + 名称 + 目的地 + 天数 + 起步价
  • 点击卡片跳转到接口1查看完整详情
  • 列表为空时展示空状态:"暂无定制产品,去提交定制需求吧"
  • 定制产品为整单计价perOrderStockstartPrice 是整单价格,不是每人价格

关联字典

字典类型 字典值 中文标签 说明
product_type CUSTOM 私人定制 定制产品类型
product_status COMPLETED 已完成 定制师设计完成,可下单
ORDERED 已下单 已有活跃订单
customize_request_status QUOTED 已报价 定制需求中产品已关联
COMPLETED 已完成 定制需求流程完结
season SPRING 春季
SUMMER 夏季
AUTUMN 秋季
WINTER 冬季
ALL_SEASON 全年

校验规则

  • 接口1productId 必须为 CUSTOM 类型且状态为 COMPLETED 或 ORDERED,否则返回404
  • 接口2自动关联当前用户的定制需求status=QUOTED/COMPLETED 且 productId 不为空),无需传参
  • 定制产品一单一产品:同一个定制产品同时只能有一个有效订单
  • 定制产品为整单计价:价格日历中的 adultSellPrice 即整单售价,不按人头乘以

页面布局建议

"我的定制"列表页

┌─────────────────────────────────────────┐
│  我的定制产品                              │
├─────────────────────────────────────────┤
│  ┌───────────────────────────────────┐  │
│  │ [封面图]  呼伦贝尔7日定制游-张三家庭  │  │
│  │           北京 → 呼伦贝尔 · 7天6晚   │  │
│  │           ¥29,800/整单              │  │
│  │           定制师: [头像] 李设计师      │  │
│  └───────────────────────────────────┘  │
│  ┌───────────────────────────────────┐  │
│  │ [封面图]  三亚5日定制游-王先生       │  │
│  │           上海 → 三亚 · 5天4晚       │  │
│  │           ¥18,600/整单              │  │
│  └───────────────────────────────────┘  │
│                                         │
│  ── 没有更多了 ──                         │
└─────────────────────────────────────────┘

定制产品详情页接口1展示

┌─────────────────────────────────────────┐
│  [轮播图 bannerImageUrls]                │
├─────────────────────────────────────────┤
│  呼伦贝尔7日定制游-张三家庭                │
│  专属家庭定制方案                          │
│  北京 → 呼伦贝尔 · 7天6晚                 │
│  标签: [草原] [亲子] [定制]                │
├─────────────────────────────────────────┤
│  👨‍👩‍👧 家庭分组                              │
│  家庭1: 张三家庭2大1小                  │
├─────────────────────────────────────────┤
│  👤 人员配置                               │
│  导游: 李导 × 1人                          │
├─────────────────────────────────────────┤
│  📅 行程安排                               │
│  Day 1: 北京 → 海拉尔                      │
│  Day 2: 莫日格勒河 → 额尔古纳              │
│  ...                                     │
├─────────────────────────────────────────┤
│  [路线图 routeMapUrl]                     │
├─────────────────────────────────────────┤
│  费用包含 / 费用不含 / 注意事项             │
├─────────────────────────────────────────┤
│        [立即预订 ¥29,800]                 │
└─────────────────────────────────────────┘

完整调用示例

示例1从定制需求跳转查看产品

// 1. 获取定制需求详情(已有接口)
const detail = await request.get('/mp/custom/detail', { params: { id: requestId } })
const { productId, status } = detail.data

// 2. 如果定制师已完成产品设计,跳转查看
if (productId && ['QUOTED', 'COMPLETED'].includes(status)) {
  uni.navigateTo({
    url: `/pages/custom/product-detail?productId=${productId}`
  })
}

// 3. 在产品详情页加载数据
const product = await request.get(`/mp/custom/product/${productId}`)
// product.data 包含完整产品信息

示例2展示"我的定制产品"列表

// 1. 获取列表
const res = await request.get('/mp/custom/products')
const products = res.data  // Array

// 2. 列表为空时展示空状态
if (!products || products.length === 0) {
  // 展示 "暂无定制产品"
  return
}

// 3. 渲染列表
products.forEach(item => {
  // item.name, item.coverImageUrl, item.tripDays, item.startPrice
  // 注意: startPrice 是整单价格
})

// 4. 点击跳转详情
function onItemClick(productId) {
  uni.navigateTo({
    url: `/pages/custom/product-detail?productId=${productId}`
  })
}

🤖 Generated with Claude Code