diff --git a/changelogs/2026-06/01_frontend_booking_popup_capacity_enforce.md b/changelogs/2026-06/01_frontend_booking_popup_capacity_enforce.md new file mode 100644 index 0000000..eae9103 --- /dev/null +++ b/changelogs/2026-06/01_frontend_booking_popup_capacity_enforce.md @@ -0,0 +1,56 @@ +# 【前端待办·小程序】下单弹窗满团提示/禁用支付 - 精确落点(后端字段已就绪) + +> **类型**: 前端待办(mmg) - 配合后端 PR #3289 已发的容量字段 +> **仓库**: hl-mini(小程序) +> **日期**: 2026-06-01 +> **关联**: changelog `01_fix_mp_quote_capacity_fields.md`(后端) / 工单 #3288 +> **现状**: 后端 `/mp/product/{id}/quote` 已正确返回 `capacityEnough`/`remainParticipants`/`remainStock`/`maxParticipants`(真机已验:余名额2时选4人 `capacityEnough=false`),但**前端弹窗没消费这些字段**,仍可选超员人数并点「支付订金」。 + +--- + +## 一、问题定位(已查到行级) + +弹窗组件:`packages/product/_shared/components/booking-popup/booking-popup.js` + `.wxml` + +全局 grep 确认:`capacityEnough` 前端**零处使用**;`remainParticipants` 仅在 `mengma/detail/detail.js:1354` 用于展示「剩余名额」,**弹窗内未用于封顶/拦截**。 + +弹窗已有**房间步进器封顶**先例可照抄到人数:`roomAtLimit`(js L165/L441)+ `_getRoomLimit()` + wxml L105 `stepper-btn--capped`。 + +## 二、改动落点(4 处) + +### 1. 接收容量字段 — `setQuoteResult(quote)`(js ~L491,`quoteUpdate` 对象内追加) +```js +const quoteUpdate = { + ..., + capacityEnough: quote.capacityEnough, // null=非GROUP不限, true=够位, false=超员/售罄 + remainParticipants: quote.remainParticipants, // 剩余名额, null=不限 + remainStock: quote.remainStock // 剩余房间, null=不限 +}; +``` + +### 2. 人数步进器封顶 — `onPlus`(js ~L425,加人前判断) +仿 `roomAtLimit`:总人数 `travelerTypes.reduce((s,t)=>s+(t.count||0),0)` 已达 `remainParticipants`(非 null)时,不再 +,`wx.showToast({title:'仅剩 '+remainParticipants+' 个名额', icon:'none'})`。可加 data `peopleAtLimit` 控制 + 号置灰。 + +### 3. 支付按钮拦截 — `onConfirm`(js,合法性校验处,L244 注释已写"合法性由 onConfirm 校验") +进入下单前增加: +```js +if (this.data.capacityEnough === false) { + wx.showToast({ title: '该班期名额不足,请减少人数', icon: 'none' }); + return; +} +``` + +### 4. wxml 提示 + 置灰 +- 支付按钮(wxml L146 `bindtap="onConfirm"`):`capacityEnough===false` 时加禁用样式(如 `booking-bottom__pay-btn--disabled`)。 +- 人数 + 步进器(wxml L80):`peopleAtLimit` 时加 `stepper-btn--capped`(同房间的 L105 写法)。 +- 弹窗内加一行提示:`wx:if="{{capacityEnough===false}}"` → 「该班期仅剩 {{remainParticipants}} 个名额」或「已满」。 + +## 三、口径说明 + +- `capacityEnough` 为 `null`/`undefined`(CORE/CUSTOM 或不限人数班期)时**不拦截**,按现状放行;只在**显式 `false`** 时提示+禁用。 +- `remainParticipants`/`remainStock` 为 `null` 表示该维度不限,不封顶。 +- 后端硬拦截仍在(下单 503109 名额不足 / 503106 房间不足),前端这层是**体验软提示**,避免用户填完资料才在支付时被拒。 + +## 四、自测 + +测试服班期(最大人数26/线下报名24→余名额2):弹窗选成人2+儿童2=4 → 报价 `capacityEnough:false remainParticipants:2` → 期望:+ 号到 2 人即置灰、顶部提示「仅剩2个名额」、支付按钮置灰或点击 toast。