diff --git a/changelogs/2026-03/2026-03-18_group_quote_and_operation_log.md b/changelogs/2026-03/2026-03-18_group_quote_and_operation_log.md new file mode 100644 index 0000000..3304323 --- /dev/null +++ b/changelogs/2026-03/2026-03-18_group_quote_and_operation_log.md @@ -0,0 +1,322 @@ +# 小蒙马报价增强 + 产品操作日志 - 前端对接指南 + +> **日期**: 2026-03-18 +> **后端状态**: ✅ 已完成,可直接对接 +> **涉及模块**: 产品管理(管理端)、C端产品(小程序端) + +--- + +## 一、功能说明 + +### 1. 产品操作日志(管理端) + +产品服务全部管理接口已补全 `@OperationLog` 注解,管理端产品列表页右侧的"操作日志"面板现在能正常显示操作记录。 + +**覆盖的模块**(共 73 个写操作接口): +- 产品管理:保存/创建/更新/删除/复制/移动/分享/路径图/状态变更 +- 拼团批次管理:创建主批次/子批次/更新/删除/开启报名/关闭报名/解散/服务人员/复制人员 +- 定价公式管理:公式组CRUD/激活 + 步骤CRUD/启停/回滚 + 测试 + 变量CRUD +- 定价与费用管理:定价规则/价格日历/费用项/额外成本/自定义费用 +- 行程管理:行程天/节点/住宿/餐饮/物资/人员配置 +- 产品线管理/文件夹管理/家庭分组管理/报价计算 + +**前端无需改动**,操作日志面板已接入 `/admin/monitor/operation-logs` 接口,后端开始写入日志后自动显示。 + +### 2. 小蒙马(GROUP)产品报价增强 + +GROUP 产品报价接口新增空床补差计算和房间数参数,算价公式更精确。 + +### 3. 团期批次新增 `adultsPerRoom` 字段 + +创建/更新批次时可配置每间房入住成人数(默认2),影响单房差和空床补差计算。 + +--- + +## 二、接口清单 + +| # | 接口 | 方法 | 路径 | 变更类型 | 说明 | +|---|------|------|------|----------|------| +| 1 | GROUP产品报价 | GET | `/admin/product/item/{productId}/group-quote` | 参数+响应新增 | 新增 childCount、roomCount 参数和多个响应字段 | +| 2 | 创建主批次 | POST | `/admin/product/item/{productId}/batch` | 请求新增 | 新增 adultsPerRoom 字段 | +| 3 | 更新批次 | PUT | `/admin/product/item/{productId}/batch/{batchId}` | 请求新增 | 新增 adultsPerRoom 字段 | +| 4 | 批次列表/详情 | GET | 批次相关接口 | 响应新增 | 返回中新增 adultsPerRoom 字段 | + +--- + +## 三、接口详细定义 + +### 接口 1:GROUP产品报价(管理端) + +**使用场景**:管理端产品详情页 → 报价计算面板,输入人数和房间数查看GROUP产品的完整报价。 + +``` +GET /admin/product/item/{productId}/group-quote?batchId=xxx&adultCount=2&childCount=1&roomCount=1 +``` + +### 请求参数 + +| 参数 | 类型 | 必填 | 默认值 | 说明 | +|------|------|------|--------|------| +| productId | Long | 是 | - | 产品ID(路径参数) | +| batchId | Long | 是 | - | 团期批次ID | +| adultCount | Integer | 否 | 2 | 成人人数 | +| childCount | Integer | 否 | 0 | 儿童人数(🆕 新增) | +| roomCount | Integer | 否 | 1 | 房间数(🆕 新增) | + +### 响应示例 + +```json +{ + "code": 200, + "message": "操作成功", + "data": { + "code": 0, + "message": null, + "singleRoomSupplement": 200.00, + "perPersonCost": 800.00, + "adultCostPrice": 1000.00, + "childCostPrice": 800.00, + "adultSellPrice": 1500.00, + "childSellPrice": 1300.00, + "hotelCostTotal": 600.00, + "adultsPerRoom": 2, + "roomCount": 1, + "adultCount": 2, + "childCount": 1, + "emptyBedSupplement": 0.00, + "totalSellPrice": 4300.00, + "extraCostTotal": 200.00, + "extraCostPerPerson": 66.67, + "extraCostItems": [ + { + "costItemId": "2026...", + "costItemName": "保险费", + "unitPrice": 50.00, + "quantity": 1, + "totalPrice": 50.00 + } + ], + "dayCosts": [...], + "profitMode": "PERCENT", + "warnings": [] + } +} +``` + +### 响应字段说明 + +| 字段 | 类型 | 说明 | +|------|------|------| +| code | Integer | 返回码: 0=成功, 1=非GROUP产品, 2=错误 | +| message | String | 错误信息(code!=0时) | +| singleRoomSupplement | BigDecimal | 单房差 = 成人售价 - 儿童售价(🆕 含义变更) | +| perPersonCost | BigDecimal | 每人成本(不含酒店) | +| adultCostPrice | BigDecimal | 成人成本价 = 单房差 + 每人费用 | +| childCostPrice | BigDecimal | 儿童成本价 = 每人费用(不含酒店) | +| adultSellPrice | BigDecimal | 成人售价 | +| childSellPrice | BigDecimal | 儿童售价 | +| hotelCostTotal | BigDecimal | 酒店总成本 | +| adultsPerRoom | Integer | 🆕 每间房入住成人数 | +| roomCount | Integer | 🆕 选择的房间数 | +| adultCount | Integer | 🆕 成人数 | +| childCount | Integer | 🆕 儿童数 | +| emptyBedSupplement | BigDecimal | 🆕 空床补差 = (房间数×每房成人数 - 成人数) × 单房差 | +| totalSellPrice | BigDecimal | 🆕 总售价 = 成人价×成人数 + 儿童价×儿童数 + 空床补差 | +| extraCostTotal | BigDecimal | 额外成本总额(团队) | +| extraCostPerPerson | BigDecimal | 额外成本(人均) | +| extraCostItems | Array | 额外成本明细列表 | +| dayCosts | Array | 每日成本明细 | +| profitMode | String | 利润模式 | +| warnings | Array[String] | 警告信息 | + +### 算价公式 + +``` +单房差 = 酒店总成本 ÷ 每房成人数 +成人成本价 = 单房差 + 人均成本(不含酒店) +儿童成本价 = 人均成本(不含酒店) +成人售价 = 成人成本价 × (1 + 利润率) +儿童售价 = 儿童成本价 × (1 + 利润率) +空床补差 = (房间数 × 每房成人数 - 成人数) × 单房差 +总售价 = 成人售价 × 成人数 + 儿童售价 × 儿童数 + 空床补差 +``` + +--- + +### 接口 2/3:创建/更新团期批次 + +**变更**:新增 `adultsPerRoom` 字段。 + +#### 创建批次请求(新增字段) + +``` +POST /admin/product/item/{productId}/batch +``` + +```json +{ + "batchLabel": "五一团", + "batchName": "2026年五一黄金周第一批", + "departureDate": "2026-05-01", + "endDate": "2026-05-05", + "enrollmentDeadline": "2026-04-25", + "minParticipants": 10, + "maxParticipants": 30, + "adultsPerRoom": 2, + "remark": "备注" +} +``` + +#### 更新批次请求(新增字段) + +``` +PUT /admin/product/item/{productId}/batch/{batchId} +``` + +```json +{ + "batchLabel": "五一团(更新)", + "adultsPerRoom": 3, + "maxParticipants": 35 +} +``` + +### 新增字段说明 + +| 字段 | 类型 | 必填 | 默认值 | 说明 | +|------|------|------|--------|------| +| adultsPerRoom | Integer | 否 | 2 | 每间房入住成人数(影响单房差和空床补差计算) | + +### 批次列表/详情响应(新增字段) + +批次列表和详情接口返回的 `GroupTourBatchVO` 新增 `adultsPerRoom` 字段: + +```json +{ + "batchId": "2026280000000000001", + "productId": "2026270000000000001", + "batchLabel": "五一团", + "departureDate": "2026-05-01", + "enrolledCount": 15, + "adultsPerRoom": 2, + "batchStatus": "ENROLLING", + "remainingSlots": 15, + "subBatches": [] +} +``` + +--- + +## 四、关联字典 + +### batch_status(批次状态) + +| 值 | 中文 | 说明 | +|----|------|------| +| PENDING | 待开放 | 创建后默认状态 | +| ENROLLING | 报名中 | 用户可报名 | +| CONFIRMED | 已成团 | 达到最低人数 | +| FULL | 已满员 | 达到最大人数 | +| CLOSED | 已关闭 | 不再接受报名 | +| IN_PROGRESS | 进行中 | 已出发 | +| FINISHED | 已结束 | 行程结束 | +| DISBANDED | 已解散 | 批次取消 | + +### product_type(产品类型) + +| 值 | 中文 | 说明 | +|----|------|------| +| CORE | 核心产品 | 标准产品,按人头计价 | +| GROUP | 小蒙马 | 拼团产品,按人头+房间计价 | +| CUSTOM | 定制产品 | 按单计价 | +| ROUTE | 线路产品 | 预设线路,按单计价 | + +--- + +## 五、前端实现建议 + +### 1. GROUP报价面板 + +在团期详情或报价页面,增加"房间数"输入框: + +``` +┌────────────────────────────────────────┐ +│ GROUP产品报价 │ +├────────────────────────────────────────┤ +│ 团期: [五一团 ▼] │ +│ 成人: [2] 儿童: [1] 房间: [1] │ +│ │ +│ ┌──────────────────────────────┐ │ +│ │ 成人售价: ¥1,500/人 │ │ +│ │ 儿童售价: ¥1,300/人 │ │ +│ │ 空床补差: ¥0.00 │ │ +│ │ ───────────────────── │ │ +│ │ 总售价: ¥4,300.00 │ │ +│ └──────────────────────────────┘ │ +└────────────────────────────────────────┘ +``` + +**参数变更**:调用 `group-quote` 接口时需传 `childCount` 和 `roomCount`。 + +### 2. 批次创建/编辑表单 + +新增"每间房入住成人数"字段(默认2,下拉或数字输入框): + +``` +┌────────────────────────────────────────┐ +│ 创建团期 │ +├────────────────────────────────────────┤ +│ 批次标签: [五一团 ] │ +│ 出发日期: [2026-05-01 ] │ +│ 结束日期: [2026-05-05 ] │ +│ 最少成团: [10] 最大人数: [30] │ +│ 每房成人数: [2 ▼] │ +│ 报名截止: [2026-04-25 ] │ +└────────────────────────────────────────┘ +``` + +### 3. 操作日志面板 + +无需前端改动。后端已为产品服务所有 POST/PUT/DELETE 接口添加操作日志,查看产品操作日志的面板将自动展示数据。 + +--- + +## 六、调用示例(JavaScript) + +### GROUP产品报价 + +```javascript +// 查询GROUP产品报价(含房间数和儿童) +const res = await request.get(`/admin/product/item/${productId}/group-quote`, { + params: { + batchId: selectedBatchId, + adultCount: 2, + childCount: 1, // 新增 + roomCount: 1 // 新增 + } +}) + +if (res.data.code === 0) { + const quote = res.data + console.log('成人售价:', quote.adultSellPrice) + console.log('儿童售价:', quote.childSellPrice) + console.log('空床补差:', quote.emptyBedSupplement) // 新增 + console.log('总售价:', quote.totalSellPrice) // 新增 +} +``` + +### 创建团期批次(含每房成人数) + +```javascript +const res = await request.post(`/admin/product/item/${productId}/batch`, { + batchLabel: '五一团', + batchName: '2026年五一黄金周第一批', + departureDate: '2026-05-01', + endDate: '2026-05-05', + enrollmentDeadline: '2026-04-25', + minParticipants: 10, + maxParticipants: 30, + adultsPerRoom: 2, // 新增:每间房入住成人数 + remark: '' +}) +```