/** * 将 getUserCouponList 等接口返回的单条优惠券规范为前端统一结构(与券包页一致) * @param {object} raw 接口原始项 * @param {number} [tabStatus=0] 列表 Tab 状态(券包页传入 currentTab) */ export function normalizeUserCouponListItem(raw, tabStatus = 0) { if (!raw || typeof raw !== 'object') return null; const couponType = Number(raw.couponType) ?? 1; const nominalValue = Number(raw.nominalValue ?? raw.amount ?? 0) || 0; const discountRate = ((Number(raw.discountRate ?? 0) || 0) / 10) || 0; const minAmount = Number(raw.minimumSpendingAmount ?? raw.minAmount ?? 0) || 0; let amount = nominalValue; let amountUnit = '元'; let conditionText = minAmount > 0 ? `满${minAmount}可用` : '无门槛'; if (couponType === 2 && discountRate > 0) { amount = discountRate; amountUnit = '折'; conditionText = minAmount > 0 ? `满${minAmount}可用` : '无门槛'; } const expirationTime = raw.expirationTime ?? raw.endGetDate ?? raw.expireDate ?? ''; const longTermValid = Number(raw.longTermValid) === 1 ? 1 : 0; // id 用于列表选中态与 :key,必须为「用户持有实例」唯一键;勿把模板 couponId 放首位,否则多张相同活动券会 id 重复、出现多选假象 const listId = raw.userCouponId ?? raw.user_coupon_id ?? raw.memberCouponId ?? raw.receiveRecordId ?? raw.receiveId ?? raw.id ?? raw.couponId ?? ''; return { id: listId, /** 券模板/业务侧 couponId,与 id(用户券实例)区分,支付等场景按需选用 */ couponId: raw.couponId ?? raw.coupon_id ?? '', amount, amountUnit, minAmount, name: raw.name ?? raw.title ?? raw.couponName ?? '', expirationTime, expireDate: expirationTime, longTermValid, status: tabStatus, couponType, nominalValue, discountRate, conditionText, specifiedDay: raw.specifiedDay ?? raw.validDays ?? '', supplementaryInstruction: raw.supplementaryInstruction ?? raw.description ?? '', qrCodeUrl: raw.qrCodeUrl ?? raw.qrcodeUrl ?? raw.qrUrl ?? '', verificationCode: raw.verificationCode ?? raw.verifyCode ?? raw.couponCode ?? raw.pickUpCode ?? '' }; } /** 解析 getUserCouponList 分页响应(数组或 { records/list, total }) */ export function parseCouponListPage(res) { if (res == null) return { list: [], total: 0 }; if (Array.isArray(res)) return { list: res, total: 0 }; const data = res.data !== undefined && res.data !== null && !Array.isArray(res) ? res.data : res; if (Array.isArray(data)) return { list: data, total: 0 }; if (data && typeof data === 'object') { const list = data.records ?? data.list ?? data.rows ?? data.items ?? (Array.isArray(data.data) ? data.data : []); const total = Number(data.total ?? data.totalCount ?? data.totalElements ?? data.count ?? res.total ?? res.totalCount ?? 0) || 0; return { list: Array.isArray(list) ? list : [], total }; } return { list: [], total: 0 }; } /** 分页追加时按 id 去重 */ export function mergeCouponListById(existing, incoming) { const seen = new Set((existing ?? []).map((c) => String(c?.id ?? ''))); const out = [...(existing ?? [])]; for (const item of incoming ?? []) { const id = String(item?.id ?? ''); if (id && !seen.has(id)) { seen.add(id); out.push(item); } else if (!id) { out.push(item); } } return out; }