hl-api-changelog/changelogs/2026-04/24_admin-ui_hotel-assignment-upgrade-price-not-sent.md

4.3 KiB

配房差价弹窗用户输入的差价未传给后端(前端 BUG,后端零改动)

日期: 2026-04-24 类型: 前端缺字段 BUG 指引 受众: hl-ui 管理后台 对应界面: 订单详情 → 行程安排 → 编辑房间 → 弹出「配房差价确认」


现场

订单 HL20260423175303-5448:

  1. 第一次配房(4 天都是便宜房型),系统算 totalDiff=-280 → 生成「房间优惠 ¥280」
  2. 用户把第 3 天改为大床房,弹窗「配房差价确认」显示 差价 +200 / 合计 +200 元
  3. 点「确认提交」后,财务页仍显示「房间优惠 ¥280」,没有 +200 升级房型

后端自检结论:无问题

实测 DB 当前 hotel_assignment 数据

day=1 普通标间   upgradePrice=null
day=2 俄式标准房  upgradePrice=null
day=3 大床房     upgradePrice=null   ← 用户在弹窗输入 +200
day=4 俄式标准房  upgradePrice=null

4 条 assignment 的 upgradePrice 全部为 null — 用户在弹窗里输入的 +200 根本没传到后端

实测服务端日志(每次提交都命中)

配房升级差价记录已创建: orderId=2047252402389598209, count=1, totalDiff=-280.00, isCustomizer=true
系统写入分配副作用优惠: amount=280.00

后端 calcDayUpgrade 逻辑:assignment.upgradePrice != null ? upgradePrice : systemDiff。上游没传,必然走 systemDiff,其它 3 天按产品默认对比算出 -480 左右,第 3 天大床房 +200,合计 -280。

契约:后端已经预留字段(OrderAssignmentService 早就支持)

HotelAssignmentRequest.HotelAssignmentItem 字段(hl-order-service-v2/src/main/java/com/hulalv/order/assignment/dto/HotelAssignmentRequest.java):

@ApiModelProperty(value = "手动覆盖升级差价(null=使用系统计算)")
private BigDecimal upgradePrice;

这个字段在 PUT /admin/order/{orderId}/hotel-assignment(保存配房) POST /admin/order/{orderId}/hotel-assignment/preview(预览)两个接口都接收

前端修复方案

方案(必做)

「配房差价确认」弹窗里,每一行用户可编辑的差价输入框,应该:

  1. 保存时:把用户输入值赋给对应 assignment.upgradePrice,通过 PUT /hotel-assignment 传给后端
  2. 预览时:同样赋值后调 POST /hotel-assignment/preview,保证 preview 和 execute 看到的是同一份 payload

伪代码:

function submitHotelAssignment(dayEditedItems) {
  const payload = {
    assignments: dayEditedItems.map(d => ({
      familyIndex: d.familyIndex,
      hotelId: d.hotelId,
      hotelName: d.hotelName,
      roomTypeId: d.roomTypeId,
      roomType: d.roomType,
      dayNumber: d.dayNumber,
      remark: d.remark,
      upgradePrice: d.dayDiffEdited,   // ← 本次要补的字段,null 也要显式传
    })),
  };
  await http.put(`/admin/order/${orderId}/hotel-assignment`, payload);
}

关键点

  • 全量替换语义:PUT /hotel-assignment 是全量替换(内部 deleteByOrderId + insertBatch)。前端必须全量把所有天的 assignment 都传过来,不能只传改动的那一天。
  • 未编辑的天:upgradePrice=null(或省略字段,Jackson 会当 null),后端按系统价计算该天差价。
  • 用户编辑过的天:把用户输入的数字放到 upgradePrice。哪怕只编辑 1 天,其它 3 天也要按原值回填并带上 upgradePrice 处理策略(保持 null 让后端算,或显式传 0 意味"本天按产品默认不算差价")。

验证步骤

  1. 用户编辑第 3 天差价 +200 → 提交
  2. 检查请求 body,assignments[day=3].upgradePrice == 200
  3. 后端日志应出现 totalDiff=+200(或其它符合预期的合计)
  4. 财务页优惠记录消失,出现「升级房型 ¥200」

为什么不建 Gitea 工单

后端契约早就就绪(字段 upgradePrice 在 VO 里,calcDayUpgrade 里的 override 逻辑也在),纯前端保存时漏传。按约定不占 Gitea 待办通道,直接给前端指引。

同类预防

「前后端字段对齐问题」在本仓库历次踩坑里很常见:

  • PR #691 GET 分页字段别名双通道
  • PR #819 MyBatis-Plus NOT_NULL 策略 setXxx(null) 写不进 DB
  • 本次 upgradePrice 契约早就在,但前端漏用

建议前端新字段发布到后端 changelog 后,第一时间在关键提交路径加上该字段,不要等到用户报错才发现。