7.7 KiB
7.7 KiB
新建订单预估价改用产品报价接口 - 前端待处理 - 管理后台
日期:2026-07-13 端类型:管理后台(新建订单向导,第 3 步基本信息及第 4 步确认创建) 服务:
hl-product-service-v2(现有接口,无后端代码变更、无 DDL) 责任端:hl-ui关联说明:2026-06/18_新建订单出发日期选择器需限制可售日期-前端待修-管理后台.md
1. 结论
新建订单的预估总价必须在用户选择出发日期后,通过产品服务报价接口计算。禁止继续使用产品起价 startPrice 或 儿童数 * 0.7 在前端估算。总价还必须包含后端按当日配置和成人数奇偶计算出的实际单房差。
两个接口职责不同:
| 接口 | 职责 |
|---|---|
GET /admin/product/item/{productId}/pricing-calendar |
获取可售日期;日期选择器按 sellable 禁用不可售日期,同时保留该日价格/班期信息。 |
POST /admin/product/item/{productId}/quote |
按已选出发日期、档位及四类人数执行权威算价,并处理单房差;预估总价直接展示响应 grandTotal。 |
quote 后端会按产品类型读取正确价格源:CORE/CUSTOM 读取所选日期的 product_price_calendar,GROUP 读取所选日期的 group_tour_batch。前端不要复制价格日历计算规则。
2. 当前缺陷
只读检查当前 hl-ui:
| 位置 | 当前行为 | 问题 |
|---|---|---|
src/views/order-v2/new/components/Step2Info.vue |
startPrice * (adultCount + childCount * 0.7) |
起价不是所选日期价格,儿童价也不是成人价的固定比例,且完全漏算单房差。 |
src/views/order-v2/new/components/Step3Confirm.vue |
再次使用相同本地公式 | 确认页会重复展示错误金额。 |
src/api/product/pricing.js |
已有统一价格日历方法,无管理端报价方法 | 新建订单流程没有调用现有报价接口。 |
截图样本的测试环境实测:
| 条件 | 值 |
|---|---|
| 产品 ID | 2056944461216100353 |
| 出发日期 / 档位 | 2026-07-14 / tierSeq=1 |
| 价格日历 | 成人 4000.00,儿童 3000.00 |
| 人数 | 2 成人、1 儿童 |
| 当前前端本地公式 | 10800.00(错误) |
后端 quote.grandTotal |
11000.00(正确) |
3. 报价接口契约
请求
POST /admin/product/item/{productId}/quote
{
"departureDate": "2026-07-14",
"adultCount": 2,
"childCount": 1,
"toddlerCount": 0,
"infantCount": 0,
"tierSeq": 1,
"batchId": null
}
| 请求字段 | 必填 | 新建订单页面来源 |
|---|---|---|
productId |
是 | URL path,选中的 draft.product.productId,雪花 ID 按字符串透传。 |
departureDate |
是 | draft.departureDate;未选择时禁止发起报价。 |
adultCount |
是 | draft.adultCount,最少 1。 |
childCount |
否 | draft.childCount,默认 0。 |
toddlerCount |
否 | draft.youngChildCount,默认 0。 |
infantCount |
否 | draft.babyCount,默认 0。 |
tierSeq |
否 | draft.product.tierSeq,默认 1。 |
batchId |
GROUP 时建议传 | 从所选日期对应的 pricing-calendar.items[].batchId 取得;CORE/CUSTOM 不传。 |
响应
{
"code": 200,
"data": {
"adultUnitPrice": "4000.00",
"childUnitPrice": "3000.00",
"toddlerUnitPrice": "0",
"infantUnitPrice": "0.00",
"totalAdultPrice": "8000.00",
"totalChildPrice": "3000.00",
"totalToddlerPrice": "0",
"totalInfantPrice": "0.00",
"grandTotal": "11000.00",
"singleRoomDiff": "0",
"singleRoomSurcharge": "0"
}
}
金额字段按字符串处理和展示,禁止先转 JS Number 后再长期保存。预估总价使用 data.grandTotal,不要由各单价在前端重新相加。
单房差口径
| 字段/条件 | 口径 |
|---|---|
singleRoomDiff |
所选出发日期价格日历或 GROUP 班期配置的单房差原值。 |
singleRoomSurcharge |
本次报价实际收取的单房差。成人数为奇数(1、3、5……)且配置了单房差时,收取一份 singleRoomDiff;成人数为偶数时为 0。 |
grandTotal |
已包含 singleRoomSurcharge,前端禁止再把单房差加一次。 |
| 人数范围 | 仅 adultCount 参与奇偶判断;儿童、小童、幼童不参与。 |
测试环境同一产品、同一日期的实测结果:
| 出发日期 | 人数 | 成人单价 | 单房差配置 | 实际单房差 | grandTotal |
|---|---|---|---|---|---|
2026-06-30 |
1 成人 | 4000.00 |
1000.00 |
1000.00 |
5000.00 |
2026-06-30 |
2 成人 | 4000.00 |
1000.00 |
0 |
8000.00 |
前端预估价卡片和确认页都直接展示 grandTotal。当 singleRoomSurcharge > 0 时,增加一行金额明细“单房差 +¥xxx”;为 0 时可隐藏该行。该明细只用于解释总价,不能参与二次计算。
4. 前端处理要求
- 未选择出发日期时,预估总价显示“请选择出发日期”或“待计算”,不得展示基于起价的金额。
- 选择出发日期后调用
quote;产品、档位、出发日期、成人数、儿童数、小童数、幼童数任一变化,都要重新报价。成人数变化时必须重新获取singleRoomSurcharge,不得仅在前端切换奇偶。 - 请求期间展示明确加载态;连续修改人数时做短防抖,并用请求序号或取消旧请求防止旧响应覆盖新结果。
- 报价失败时清空旧报价,不允许退回
startPrice/0.7本地估算;展示后端错误信息并阻止带着过期报价进入确认页。 - 第 4 步确认页复用与当前输入完全匹配的最新报价;若报价依赖项已变化或无有效报价,进入确认页前重新调用一次。
- 删除
Step2Info.vue和Step3Confirm.vue中childCount * 0.7及startPrice预估总价逻辑。 grandTotal已含单房差;前端不得重复相加。singleRoomSurcharge > 0时仅展示单房差明细。pricing-calendar仍用于可售日期限制,不要删除;quote是其后的权威算价步骤。
5. 验收清单
- 未选出发日期时不展示金额,也不调用报价接口。
- 选择
2026-07-14、tierSeq=1、2 成人 1 儿童后,样本产品预估总价显示11000.00,不再显示10800.00。 - 成人/儿童/小童/幼童任一人数变化均重新报价,页面结果与最后一次请求一致。
- 单房差配置为
1000.00时,1 成人返回并显示singleRoomSurcharge=1000.00、grandTotal=5000.00;2 成人返回singleRoomSurcharge=0、grandTotal=8000.00。 - 单房差只按成人数奇偶判断;儿童、小童、幼童数量变化不会被前端错误用于单房差判断。
- 第 3 步和第 4 步在实际单房差大于 0 时显示单房差明细,但不会在
grandTotal上再次累加。 - 切换产品、档位或日期后,旧报价立即失效并重新获取。
- CORE/CUSTOM 按所选日期价格日历算价;GROUP 携带所选班期
batchId后报价正确。 - 报价接口失败时不展示旧金额、不使用本地比例兜底。
- 第 3 步与第 4 步显示同一份有效
grandTotal。
6. 验证证据
- 当前源码已确认
POST /admin/product/item/{id}/quote为管理端正式报价接口。 - Knife4j 测试环境聚合文档已确认该接口存在。
- 2026-07-13 经测试环境网关实调:价格日历与报价接口均返回
code=200;上述样本grandTotal=11000.00。 - 2026-07-13 经测试环境网关补测单房差:
2026-06-30配置单房差1000.00,1 成人报价singleRoomSurcharge=1000.00、grandTotal=5000.00;2 成人报价singleRoomSurcharge=0、grandTotal=8000.00。 - 本通知只修改
hl-api-changelog,未修改hl-ui或后端业务代码。