20 KiB
schema, ticket, title, consumer, author, change_type, backend_status, gateway_status, frontend_status, frontend_owner, frontend_ref, target_release, verified_at, status_note, updated_at, base
| schema | ticket | title | consumer | author | change_type | backend_status | gateway_status | frontend_status | frontend_owner | frontend_ref | target_release | verified_at | status_note | updated_at | base |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| hl-changelog/v2 | 7143 | 团期看板分页项/详情/看板 VO 补 productId(供新增子订单深链预填产品) | admin | wx(GIT) | 修改接口 | deployed | verified | verified | mmg | 5d0344ad | 2026-09-06 | 2026-09-06 | dev-v3 |
团期模块:看板 VO 补 productId
三个团期看板读接口响应新增 productId 字段,供前端「新增子订单」深链到订单创建向导时预填产品和班期 ID,锁定出发日期。前端逻辑:仅 GROUP 产品创单时才在 payload 中带 productBatchId;非 GROUP 产品忽略 productBatchId。
⚠️ 关键变化
- 新增
productId是产品主键,用于深链向导/order-v2/new?productId={productId}&productBatchId={productBatchId}&departureDate={date}的预填参数。 - 向导跳转后,仅 GROUP 产品应将 productBatchId 放入订单创建 POST payload;其他产品类型忽略该参数。
- 前端缺陷单已发,说明旧建单向导漏传 productBatchId,新版本补全(见关联链接)。
二、变更接口清单
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|---|---|---|---|---|
| 1 | 团期分页列表 | GET | /v3/admin/order/group-batch |
响应新增字段 | data.list[] 各项新增 productId |
| 2 | 团期详情 | GET | /v3/admin/order/group-batch/{groupBatchId} |
响应新增字段 | data 新增 productId |
| 3 | 团期看板列表 | GET | /v3/admin/order/group-batch/board?productId= |
响应新增字段 | data[] 各项新增 productId |
三、接口详情
1. 团期分页列表 GET /v3/admin/order/group-batch
VO: GroupBatchPageItemRespVO(响应位置:data.list[])
使用场景
加载团期分页列表时,每一行包含产品 ID,前端点击「新增子订单」时取该行的 productId / productBatchId / departureDate 拼接深链,跳转到订单创建向导。
入参
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
productId |
Query | String | 否 | 正整数 ID | 按产品筛选 |
batchStatus |
Query | String | 否 | 枚举值 | 按团期状态码筛选(RECRUITING/RESOURCE_PREPARING/...) |
deadlineFrom |
Query | String | 否 | yyyy-MM-dd | 报名截止日起 |
deadlineTo |
Query | String | 否 | yyyy-MM-dd | 报名截止日止 |
opsStage |
Query | String | 否 | 枚举值 | 按运营阶段筛选(RECRUIT/FORMED/PENDING_TRIP/TRAVELLING/AUDITING/CHECKED/DISBANDED) |
month |
Query | String | 否 | yyyy-MM | 按出发月份筛选 |
keyword |
Query | String | 否 | - | 班期编号/班期名称模糊关键词 |
pageNo |
Query | Integer | 是 | ≥1 | 页码,从 1 开始 |
pageSize |
Query | Integer | 是 | ≤100 | 每页条数,默认 20 |
出参 Result<Page<GroupBatchPageItemRespVO>>
| 字段 | 类型 | 说明 |
|---|---|---|
data.list[].groupBatchId |
String | 团期聚合主键 |
data.list[].productBatchId |
String | product 侧班期 ID |
data.list[].productId |
String | 【新增】 产品 ID,供深链预填 |
data.list[].productName |
String | 产品名称 |
data.list[].batchNo |
String | 班期编号 |
data.list[].batchName |
String | 班期名称 |
data.list[].batchStatus |
String | 团期状态码 |
data.list[].batchStatusName |
String | 状态中文名 |
data.list[].minGroupPeople |
Integer | 最低成团人数 |
data.list[].maxRooms |
Integer | 房间容量 |
data.list[].maxParticipants |
Integer | 人数容量 |
data.list[].enrolledPeople |
Integer | 已报名人数 |
data.list[].enrolledRooms |
Integer | 已用房间数 |
data.list[].remainRooms |
Integer | 剩余房间数 |
data.list[].remainParticipants |
Integer | 剩余人数 |
data.list[].orderCount |
Integer | 子订单数 |
data.list[].enrollDeadline |
String | 报名截止日 |
data.list[].departDate |
String | 出发日期 |
data.list[].endDate |
String | 结束日期 |
data.list[].receivableAmount |
String | 整团应收合计 |
data.list[].receivedAmount |
String | 整团已收合计 |
data.list[].chips |
Object | 六芯片整团聚合态(hotel/vehicle/guide/photo/contract/insurance,各为字符串状态:全部完成为 DONE,存在未完成项为待办态;完整取值见六芯片文档 GB-ADM-090~095) |
请求示例
GET /v3/admin/order/group-batch?pageNo=1&pageSize=20
Authorization: Bearer <token>
无请求体。
响应示例
{
"code": 200,
"message": "成功",
"success": true,
"data": {
"total": 5,
"list": [
{
"groupBatchId": "2096412454643802114",
"productBatchId": "2052935476557328386",
"productId": "2044306857534636034",
"productName": "冻干粉发短信给",
"batchNo": "Q202610012052935476548939777",
"batchName": "10月1日长白山亲子团",
"batchStatus": "RECRUITING",
"batchStatusName": "招募中",
"minGroupPeople": 6,
"maxRooms": 4,
"maxParticipants": 10,
"enrolledPeople": 4,
"enrolledRooms": 2,
"remainRooms": 2,
"remainParticipants": 6,
"orderCount": 2,
"enrollDeadline": "2026-09-25",
"departDate": "2026-10-01",
"endDate": "2026-10-03",
"receivableAmount": "48000.00",
"receivedAmount": "36000.00",
"chips": {
"hotel": "DONE",
"vehicle": "DONE",
"guide": "DONE",
"photo": "DONE",
"contract": "DONE",
"insurance": "DONE"
}
}
]
}
}
空数据 / 降级响应
{
"code": 200,
"message": "成功",
"success": true,
"data": {
"total": 0,
"list": []
}
}
错误响应
{
"code": 589507,
"message": "无操作权限",
"success": false,
"data": null
}
业务边界
- 沿用团期列表权限校验(团期管理员/运营/定制师等);无权返回 589507。
productId与其他字段同时生效,始终非空(命中行/未命中行/孤儿行均返回)。- 分页参数超界时返回空列表。
- 业务失败仍为 HTTP 200,需检查 code。
2. 团期详情 GET /v3/admin/order/group-batch/{groupBatchId}
VO: GroupBatchDetailRespVO(响应位置:data)
使用场景
打开团期详情页时,读取产品 ID,供「新增子订单」按钮拼接深链,跳转订单创建向导并预填产品及班期。
入参
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
groupBatchId |
Path | String | 是 | 正整数 ID | 团期主键 |
出参 Result<GroupBatchDetailRespVO>
| 字段 | 类型 | 说明 |
|---|---|---|
data.groupBatchId |
String | 团期聚合主键 |
data.productBatchId |
String | product 侧班期 ID |
data.productId |
String | 【新增】 产品 ID,供深链预填 |
data.productName |
String | 产品名称 |
data.batchNo |
String | 班期编号 |
data.batchName |
String | 班期名称 |
data.batchLabel |
String/null | 班期标签快照 |
data.batchStatus |
String | 团期状态码 |
data.batchStatusName |
String | 状态中文名 |
data.minGroupPeople |
Integer | 最低成团人数 |
data.maxRooms |
Integer | 房间容量 |
data.maxParticipants |
Integer | 人数容量 |
data.enrolledPeople |
Integer | 已报名人数 |
data.enrolledRooms |
Integer | 已用房间数 |
data.remainRooms |
Integer | 剩余房间数 |
data.remainParticipants |
Integer | 剩余人数 |
data.hotelReady |
Boolean | 配房完成标志 |
data.vehicleReady |
Boolean | 配车完成标志 |
data.guideReady |
Boolean | 导游完成标志 |
data.photographerReady |
Boolean | 摄影完成标志 |
data.materialConfirmed |
Boolean | 物资确认标志 |
data.requirementConfirmed |
Boolean | 需求整体确认标志 |
data.departDate |
String | 出发日期 |
data.endDate |
String | 结束日期 |
data.enrollDeadline |
String | 报名截止日 |
data.totalReceivable |
String | 整团应收合计 |
data.totalReceived |
String | 整团已收合计 |
data.remark |
String/null | 备注 |
请求示例
GET /v3/admin/order/group-batch/2096412454643802114
Authorization: Bearer <token>
无请求体。
响应示例
{
"code": 200,
"message": "成功",
"success": true,
"data": {
"groupBatchId": "2096412454643802114",
"productBatchId": "2052935476557328386",
"productId": "2044306857534636034",
"productName": "冻干粉发短信给",
"batchNo": "Q202610012052935476548939777",
"batchName": "10月1日长白山亲子团",
"batchLabel": null,
"batchStatus": "RESOURCE_PREPARING",
"batchStatusName": "资源准备中",
"minGroupPeople": 6,
"maxRooms": 4,
"maxParticipants": 10,
"enrolledPeople": 10,
"enrolledRooms": 4,
"remainRooms": 0,
"remainParticipants": 0,
"hotelReady": false,
"vehicleReady": false,
"guideReady": false,
"photographerReady": false,
"materialConfirmed": false,
"requirementConfirmed": false,
"departDate": "2026-10-01",
"endDate": "2026-10-03",
"enrollDeadline": "2026-09-25",
"totalReceivable": "48000.00",
"totalReceived": "36000.00",
"remark": null
}
}
空数据 / 降级响应
详情接口不存在空数据响应。
错误响应
{
"code": 589501,
"message": "团期不存在",
"success": false,
"data": null
}
业务失败错误码沿用 GroupBatchErrorCode(权限/不存在等)。
业务边界
- 沿用团期详情权限校验;无权返回 589507。
productId与其他字段同时返回,始终非空。- 团期不存在返回业务码 589501(HTTP 200)。
3. 团期看板列表 GET /v3/admin/order/group-batch/board?productId=
VO: GroupBatchBoardItemRespVO(响应位置:data[])
使用场景
打开团期看板时,按产品维度加载该产品下的所有班期(产品侧班期为基底,左连运营侧团期数据),每一行携带 productId,供「新增子订单」深链按行数据拼接预填参数。
入参
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
productId |
Query | String | 是 | 正整数 ID | 按产品筛选(必填;缺参返回 400) |
出参 Result<List<GroupBatchBoardItemRespVO>>
| 字段 | 类型 | 说明 |
|---|---|---|
data[].productBatchId |
String | product 侧班期 ID |
data[].productId |
String | 【新增】 产品 ID(= 请求入参;命中/未命中/孤儿行均非空) |
data[].batchNo |
String | 班期编号 |
data[].batchName |
String | 班期名称 |
data[].departureDate |
String | 出发日期 |
data[].endDate |
String | 结束日期 |
data[].enrollmentDeadline |
String | 报名截止日 |
data[].maxRooms |
Integer | 房间容量 |
data[].maxParticipants |
Integer | 人数容量 |
data[].enrolledRooms |
Integer | 已报名房数 |
data[].enrolledPeople |
Integer | 已报名人数 |
data[].remainRooms |
Integer | 剩余房间数 |
data[].remainParticipants |
Integer | 剩余人数 |
data[].batchStatus |
String | 团期状态码 |
data[].batchStatusLabel |
String | 状态中文名 |
data[].hotelReady |
Boolean | 配房完成标志 |
data[].vehicleReady |
Boolean | 配车完成标志 |
data[].guideReady |
Boolean | 导游完成标志 |
data[].photographerReady |
Boolean | 摄影完成标志 |
data[].needsGuide |
Boolean | 是否需领队 |
data[].needsPhotographer |
Boolean | 是否需摄影 |
data[].orderCount |
Integer | 活跃子订单数 |
data[].groupBatchId |
String/null | 团期聚合主键(未成团时为 null) |
data[].productBatchRemoved |
Boolean | 是否孤儿行(product 侧已删除该班期) |
data[].contractSignedCount |
Integer | 合同已签子订单数 |
data[].insuranceInsuredCount |
Integer | 保险已出子订单数 |
请求示例
GET /v3/admin/order/group-batch/board?productId=2044306857534636034
Authorization: Bearer <token>
无请求体。
响应示例
{
"code": 200,
"message": "成功",
"success": true,
"data": [
{
"productBatchId": "2052935476557328386",
"productId": "2044306857534636034",
"batchNo": "Q202610012052935476548939777",
"batchName": "10月1日长白山亲子团",
"departureDate": "2026-10-01",
"endDate": "2026-10-03",
"enrollmentDeadline": "2026-09-25",
"maxRooms": 4,
"maxParticipants": 10,
"enrolledRooms": 2,
"enrolledPeople": 4,
"remainRooms": 2,
"remainParticipants": 6,
"batchStatus": "RECRUITING",
"batchStatusLabel": "招募中",
"hotelReady": false,
"vehicleReady": false,
"guideReady": false,
"photographerReady": false,
"needsGuide": true,
"needsPhotographer": false,
"orderCount": 2,
"groupBatchId": "2096412454643802114",
"productBatchRemoved": false,
"contractSignedCount": 1,
"insuranceInsuredCount": 1
},
{
"productBatchId": "2052935476557328387",
"productId": "2044306857534636034",
"batchNo": "Q202610022052935476548939778",
"batchName": "10月2日长白山亲子团",
"departureDate": "2026-10-02",
"endDate": "2026-10-04",
"enrollmentDeadline": "2026-09-26",
"maxRooms": 4,
"maxParticipants": 10,
"enrolledRooms": 0,
"enrolledPeople": 0,
"remainRooms": 4,
"remainParticipants": 10,
"batchStatus": "RECRUITING",
"batchStatusLabel": "招募中",
"hotelReady": false,
"vehicleReady": false,
"guideReady": false,
"photographerReady": false,
"needsGuide": true,
"needsPhotographer": false,
"orderCount": 0,
"groupBatchId": null,
"productBatchRemoved": false,
"contractSignedCount": 0,
"insuranceInsuredCount": 0
}
]
}
空数据 / 降级响应
{
"code": 200,
"message": "成功",
"success": true,
"data": []
}
错误响应
缺参 productId:
{
"code": 400,
"message": "productId 参数缺失",
"success": false,
"data": null
}
业务边界
productId必填,缺参返回 HTTP 200 + code 400;不要用 GET 参数默认值。- 返回结构按产品侧班期为基底(左连团期数据):
- 命中行(班期有对应团期):团期状态/容量/ready 取订单侧值;batchStatus ≠ RECRUITING
- 未命中行(班期无团期):batchStatus 固定 RECRUITING;groupBatchId = null;容量取产品侧 maxRooms/maxParticipants
- 孤儿行(团期但班期已删):productBatchRemoved = true;仅 orderCount > 0 时出现
productId在命中行、未命中行、孤儿行中均等于请求入参,始终非空。- 表合并按 productBatchId 左连 order_group_batch;无团期记录时新增一行(未命中)。
四、契约约束与正确调用方式
| 场景 | 正确做法 |
|---|---|
| 新增子订单深链 | 按行数据拼接 /order-v2/new?productId={productId}&productBatchId={productBatchId}&departureDate={departureDate} |
| 向导内 GROUP 产品创单 | 检查产品类型,仅 GROUP 类型在 POST payload 中带 productBatchId;其他类型忽略 |
| 非 GROUP 产品创单 | 忽略 productBatchId 参数,后端根据 productId 与 departureDate 自行逻辑 |
| 孤儿行处理 | 若 productBatchRemoved = true,需向用户提示"班期已下架,不可创建子订单"或禁用按钮 |
| 未成团行处理 | groupBatchId = null 时无团期记录;前端可选择隐藏"团期信息"列或显示"待成团" |
五、数据库行为
| 班期状态 | productBatchId | groupBatchId | batchStatus | 数据来源 |
|---|---|---|---|---|
| 命中(有团期) | 产品侧 | 订单侧 | 订单侧 | order_group_batch 存在 |
| 未命中(无团期) | 产品侧 | null | RECRUITING | 无 order_group_batch 行 |
| 孤儿(班期删) | 产品侧 | 订单侧 | 订单侧 | order_group_batch 存在但班期无 |
新增 productId 字段在 productBatchId 后(响应顺序一致)。
六、边界行为
- 业务失败可能仍为 HTTP 200,必须同时检查
code、success和message。 - 看板接口
productId缺参返回 400(HTTP 200);不要依赖前端参数校验。 - 分页/列表接口分页参数超界时返回空列表(无 5XX)。
productId在所有三个接口的所有行中均非空,无特殊情况返回 null。- Long 型 ID 在 JSON 字符串化后,前端若需数值运算应保持字符串存储。
六.6、修改前后对比
字段级对比
| 字段 | 改前 | 改后 |
|---|---|---|
productId(分页项) |
无此字段 | 新增;产品 ID |
productId(详情) |
无此字段 | 新增;产品 ID |
productId(看板项) |
无此字段 | 新增;产品 ID |
行为级对比
| 行为 | 改前 | 改后 |
|---|---|---|
| 新增子订单跳转 | 无法从响应直接拼深链参数 | 新增 productId,与 productBatchId/departureDate 配合直接拼链 |
| 向导内产品预填 | 依赖约定俗成或外部 context | 直接从深链 query string 传入 |
| GROUP 产品识别 | 向导内自行判别 | 向导根据产品类型自动识别是否需 productBatchId |
六.7、影响评估
- 是否破坏向后兼容: 否。新增字段对旧客户端透明。
- 前端是否必须同步上线: 否(从旧口径讲);但为完整支持团期看板「新增子订单」功能,前端应同步接入新增 productId 于深链拼接(仅一处改动)。
- 前端 workaround 清理点:
- 新增子订单按钮处,改用响应中的 productId 拼深链,而非硬编码产品 ID
- 向导内创建 GROUP 订单时,检查产品类型再决定是否传 productBatchId(无需前端重构,只需补一个类型判断)
七、不影响范围
- 仅影响: 管理后台团期看板的「新增子订单」功能入口
- 零影响:
- 团期创建、编辑、审批、资源配置等写接口
- 团期与订单间的关联关系和业务流程
- 产品侧班期相关接口和定义
八、测试环境已验证
- 单测: 79 条测试用例绿✓(新增 productId 相关的 UT 已覆盖命中/未命中/孤儿行三路径)
- ArchTest: 45 条架构测试绿✓
- 测试服网关实测: 单测 + CR 通过;测试服网关实测见管理者补充
实测产品: productId=2044306857534636034(冻干粉发短信给),班期 2026-10-01(productBatchId=2052935476557328386),团期主键 groupBatchId=2096412454643802114,团期名 batchName=10月1日长白山亲子团。
九、相关历史 PR(功能演进)
| PR | Issue | 说明 | 是否仍有效 |
|---|---|---|---|
| #7135 | - | GROUP 产品创单校验与重整(定义 productBatchId 入参) | ✅ 有效 |
| #7142 | - | 订单详情/列表/创单响应透出判团字段(groupBatchId/productBatchId/groupOrder) | ✅ 有效 |
| 本 PR #7157 | #7143 | 团期看板 VO 补 productId(配合深链预填) | ✅ 最新 |
十、相关文档
- 关联 Issue: wx/HL#7143
- 关联 PR: wx/HL#7157
- 相关工单: #7142(订单判团字段)、#7135(GROUP 产品规范)
- 前端缺陷: 新建订单向导漏传 productBatchId(另发前端 changelog)
关联 / 联系人
链接
联系人
- 后端负责人: @wx