余额:{{ carts.vipUser.amount }} - 积分:{{ carts.vipUser.accountPoints }} + 积分:{{ carts.vipUser.pointBalance }}
* @@ -398,8 +399,16 @@ watch( ); //002-获取订单可用积分及抵扣金额(支付页面使用) -const pointsRes = ref({ usable: true, maxUsablePoints: 0, minDeductionPoints: 0 }); -const usePointsNumber = ref(0); +const pointsRes = ref({ + usable: false, + equivalentPoints: 0, // 积分换算比例 eg: 20 积分 = 1 元 + maxDeductionRatio: 0, // 下单最高抵扣比例(小数) + minPaymentAmount: 0, // 下单实付抵扣门槛(元) + maxUsablePoints: 0, + minDeductionPoints: 0, + unusableReason: "", +}); +const usePointsNumber = ref(0); // 输入的积分数量(用户填写) //积分可抵扣最大金额 const scoreMaxMoney = computed(() => { return ( @@ -421,22 +430,129 @@ async function pointsInit() { if (!carts.vipUser.id) { return; } - const res = await PointsApi.calcOrderUsablePoints({ + const { pointsConfig, pointsUser } = await PointsApi.calcOrderUsablePoints({ shopUserId: carts.vipUser.id, - orderAmount: scoreMaxMoney.value, }); + + // 不修改 accountPoints(为余额),将积分保存到 pointBalance 字段 + carts.vipUser.pointBalance = pointsUser && pointsUser.id ? pointsUser.pointBalance : 0; + + // 保险取值 + const eq = pointsConfig?.equivalentPoints || 0; + const maxRatio = pointsConfig?.maxDeductionRatio || 0; + const minPay = pointsConfig?.minPaymentAmount || 0; + + // 计算当前订单可抵扣金额上限(元) + let finalPay = Number(carts.orderCostSummary.finalPayAmount) || 0; + + const res = { + usable: true, + equivalentPoints: eq, + maxDeductionRatio: maxRatio, + minPaymentAmount: minPay, + maxUsablePoints: 0, + minDeductionPoints: pointsConfig?.minDeductionPoints || eq, + unusableReason: "", + }; + + // 如果订单实付低于最小使用门槛,则不可用 + if (finalPay <= 0 || (minPay > 0 && finalPay < minPay)) { + res.usable = false; + res.unusableReason = `订单实付金额低于 ${minPay} 元,无法使用积分抵扣`; + } else if (eq <= 0) { + res.usable = false; + res.unusableReason = `积分换算比例配置错误,无法使用积分抵扣`; + } else { + // 计算基于比例限制的最大抵扣金额(元) + let maxByRatio = finalPay * maxRatio; + // 保证抵扣后剩余金额 >= minPaymentAmount + if (minPay > 0) { + const allowed = finalPay - minPay; + if (allowed <= 0) { + res.usable = false; + res.unusableReason = `抵扣后实付金额必须大于等于 ${minPay} 元,当前不可使用积分`; + } else { + maxByRatio = Math.min(maxByRatio, allowed); + } + } + + if (res.usable) { + // 可用积分上限(向下取整为 eq 的倍数) + const maxByMoney = Math.floor(maxByRatio * eq); + const userPoints = carts.vipUser.pointBalance || 0; + res.maxUsablePoints = Math.min(userPoints, maxByMoney); + // 最小抵扣积分为配置值或等于换算比 + res.minDeductionPoints = pointsConfig?.minDeductionPoints || eq; + if (res.maxUsablePoints < res.minDeductionPoints) { + res.usable = false; + res.unusableReason = `可用积分不足,至少需要 ${res.minDeductionPoints} 积分才可抵扣`; + } + } + } + pointsRes.value = res; carts.pointDeductionRule.pointsPerYuan = res.equivalentPoints; + if (score.sel == -1) { + // 未选择使用积分 + return res; + } + + // 如果可用则默认填充可用最大值,否则清零 + usePointsNumber.value = res.usable ? res.maxUsablePoints : 0; + if (!res.usable) score.sel = -1; + + return res; +} + +// 将输入的积分数转换为抵扣金额并写回 carts.orderCostSummary +function pointsToMoney(val) { + const cfg = pointsRes.value; + if (!cfg.usable || cfg.equivalentPoints <= 0) { + usePointsNumber.value = 0; + carts.orderCostSummary.pointUsed = 0; + carts.orderCostSummary.pointDeductionAmount = 0; return; } - usePointsNumber.value = res.usable ? res.maxUsablePoints : 0; - if (res.usable) { - } else { - score.sel = -1; + // 确保为整数积分 + let pts = parseInt(usePointsNumber.value || 0, 10); + if (isNaN(pts) || pts <= 0) { + pts = 0; } - return res; + + // 限制最大值 + if (cfg.maxUsablePoints && pts > cfg.maxUsablePoints) { + pts = cfg.maxUsablePoints; + } + + // 计算抵扣金额(元),向下保留两位 + const money = new BigNumber(pts).div(cfg.equivalentPoints).decimalPlaces(2, BigNumber.ROUND_DOWN).toNumber(); + + // 再次校验不超过允许的最大抵扣金额(基于比例或门槛) + let finalPay = Number(carts.orderCostSummary.finalPayAmount) || 0; + let maxByRatio = finalPay * cfg.maxDeductionRatio; + if (cfg.minPaymentAmount > 0) { + const allowed = finalPay - cfg.minPaymentAmount; + if (allowed <= 0) { + usePointsNumber.value = 0; + carts.orderCostSummary.pointUsed = 0; + carts.orderCostSummary.pointDeductionAmount = 0; + return; + } + maxByRatio = Math.min(maxByRatio, allowed); + } + const maxAllowedMoney = new BigNumber(maxByRatio).decimalPlaces(2, BigNumber.ROUND_DOWN).toNumber(); + if (money > maxAllowedMoney) { + // 调整积分到允许的最大金额对应的积分 + const allowedPts = Math.floor(maxAllowedMoney * cfg.equivalentPoints); + pts = Math.min(allowedPts, cfg.maxUsablePoints); + } + + usePointsNumber.value = pts; + const finalMoney = new BigNumber(pts).div(cfg.equivalentPoints).decimalPlaces(2, BigNumber.ROUND_DOWN).toNumber(); + carts.orderCostSummary.pointUsed = pts; + carts.orderCostSummary.pointDeductionAmount = finalMoney; } const emits = defineEmits(["chooseUser", "paysuccess"]); @@ -693,6 +809,10 @@ watch( onMounted(() => { carts.payParamsInit(); getPaytype(); + + if (carts.vipUser.id) { + pointsInit(); + } }); defineExpose({ nowPayClick,