# 二期 v3:新建订单向导「选主题/选产品」接通真实接口(替换 mockProducts.js) > **服务**: hl-product-service-v2(+ hl-order-service-v3 内部统计) > **PR**: #3155 > **Issue**: #3142 > **日期**: 2026-05-28 > **影响**: 🟡 新建订单页 `order-v2/new` 第 1 步「选主题」可改用真接口;第 2 步「选产品」用已有接口;地区筛选删除 --- ## ⚠️ 关键变化(前端 mmg 必读) `order-v2/new` 第 1、2 步当前用 `src/views/order-v2/new/_shared/mockProducts.js` 写死假数据。现可替换为真实接口。 ### 1. 第 1 步「选主题」— 新增接口 ``` GET /admin/product/line/order-picker ``` - 无 query 参数,**不分页**,按排序号升序返回 - 仅返回「**启用(ACTIVE) + 在售(该产品线下挂≥1个已上架产品)**」的主题 - **数据权限**:和产品管理一致——超管看全部、核心(CORE)/小蒙马(GROUP)主题全员可见、私人定制(CUSTOM)仅创建人本人可见。**地区(region)筛选不需要,产品线无此字段,请删掉那排 chips。** 返回结构: ```jsonc { "code": 200, "data": [ { "lineId": 2056937785918369794, // 主题ID(雪花,前端按字符串透传) "name": "测试核心产品", // 主题名 "description": "...", // 描述(原 mock 的 desc/tagline 都用它) "coverImageUrl": "https://...", // 真实封面图(替代 mock 的 emoji cover + coverColor) "productType": "CORE", // CORE=核心 / GROUP=小蒙马 "skuCount": 6, // 该主题下已上架产品的档位总数(原 mock 的 skuCount) "fromPrice": 3105.00, // 起价/人(已上架产品最低成人起价;未设价为 null,请显示 ¥-- 或灰) "hot": true // 热门标识 = 该主题近90天下单量较多(前30%且>0) } ] } ``` 字段映射建议(mock → 真接口): - `id` → `lineId`(字符串透传,勿 Number()) - `cover`/`coverColor`(emoji 装饰)→ 改用 `coverImageUrl` 真实图;如仍要色块可前端按 lineId 取色 - `region`/`regionKey` → **删除**(无后端字段,地区 chips 去掉) - `tagline` → 并入 `description` 或省略 - `skuCount` / `fromPrice` / `hot` → 同名直取 - 顶部统计「在售主题数」= 列表长度;「SKU总数」= Σ`skuCount`;「最低人均」= min(`fromPrice`) ### 2. 第 2 步「选产品」— 用已有接口(无新增),已在测试服实测返回结构 ``` GET /admin/product/item/list?lineId={lineId}&status=PUBLISHED ``` - 选定主题后传其 `lineId`,只取已上架产品;返回 `PageResult`(`data.records[]` + `data.total`) - 数据权限同上(带 @DataScope,超管全部 / CORE·GROUP 全员 / CUSTOM 仅本人) - 下单提交需要的 `productId + tierSeq` 都从这里取(雪花 `productId` 按字符串透传,勿 Number()) 返回 `records[]` 实测字段(与 Step2 SKU 卡片显示元素的映射): ```jsonc { "productId": 2043595351268519937, // 产品ID(字符串透传) "name": "6天5晚旷野版", // 卡片大标题 "subtitle": "装甲车穿越·帐篷营地…", // 副标题 "tags": ["亲子","露营"], // 标签行(· tag · tag) "tripDays": 6, "tripNights": 5, // "6天5晚 起" "coverImageUrl": "https://...", "startPrice": 10.00, // 产品级最低起价(可能 null) "tierCount": 2, "tierPrices": [ // 档位数组(档次过滤 chips = 去重 tierName) {"tierSeq":1, "tierName":"舒适", "tierDescription":"…", "startPrice":10.00}, {"tierSeq":2, "tierName":"豪华", "tierDescription":"…", "startPrice":null} // 该档未设价 ] } ``` **SKU 卡渲染**:mock 里每张卡=一个产品的一个档位;真实是一个产品(`productId`)含多档位(`tierPrices[]`)。 建议按「产品 × 档位」平铺成卡(每个 `tierPrices[i]` 一张卡),卡上: - 档位标签 ← `tierPrices[i].tierName`("尊享档/挑战档") - 价格 ← `tierPrices[i].startPrice`(**为 null 时显示 ¥-- / 灰**,别显示 0) - 提交带 `productId` + `tierPrices[i].tierSeq` **⚠️ 两个 mock 元素后端暂无对应字段(同「地区」性质,需前端确认怎么处理):** - **「热销」徽标(每个 SKU)**:`/item/list` 无产品/档位级热门字段(热门目前只做到了主题级,在选主题接口的 `hot`)。→ 选产品卡片**先不显示热销徽标**;若确实要按"该产品下单较多"标热,需后端再加一个产品级下单量字段(同主题 hot 的做法,可另开工单)。 - **「发团日期」(如 5-10 月)**:`/item/list` 无此字段,它是班期/价格日历的可售日期,不是单一文案。→ **先省略**;若要展示,需后端补"可售日期范围"或前端另调班期/价格日历接口。 ### 3. 提交(不变) `POST /v3/admin/order`,入参 `productId` + `tierSeq` 等,已就绪。 --- ## 验证 测试服 `web.test.1814.love:9443` 真 admin token 实测:order-picker 返 9 个在售主题(库内 ACTIVE 29 → 在售 9 精确吻合),字段齐全,hot 跨服务统计生效。