/** * 购物车套餐offer展示辅助(纯函数) * * 权威计算在后端:POST /api/cart/combo-offer 按勾选子集检测 offer, * 前端仅消费后端下发的 comboOffer 做提示与「一键替换为套餐」,不做任何金额扣减。 */ /** * 安全读取套餐offer:未命中/未激活/非法值一律返回 null。 * @param {Object|null} offer 后端下发的 comboOffer * @returns {Object|null} */ export function comboOfferOf(offer) { if (!offer || offer.active !== true) return null return offer } /** * 套餐offer提示文案:这N件组成套餐「XX」,套餐价 ¥Y(省 ¥Z) * @param {Object|null} offer 后端下发的 comboOffer * @param {number} [checkedCount] 勾选子集件数(后端响应未含,由前端传入) * @returns {string} */ export function formatComboOfferText(offer, checkedCount) { const o = comboOfferOf(offer) if (!o) return '' const n = (typeof checkedCount === 'number' && checkedCount > 0) ? checkedCount : ((typeof o.groups === 'number' && o.groups > 0) ? o.groups : 0) const name = o.comboName || '' const price = (typeof o.comboPrice === 'number' && o.comboPrice >= 0) ? o.comboPrice : 0 const saving = (typeof o.saving === 'number' && o.saving > 0) ? o.saving : 0 let txt = '' if (n) txt += n + ' 件' if (name) txt += '组成套餐「' + name + '」' txt += ',套餐价 ¥' + (price / 100).toFixed(2) if (saving) txt += '(省 ¥' + (saving / 100).toFixed(2) + ')' return txt }