优化优惠积分使用逻辑
This commit is contained in:
@@ -206,7 +206,7 @@
|
||||
<el-form-item label="积分抵扣">
|
||||
<div class="flex">
|
||||
<el-input v-model="couponForm.pointsNum"
|
||||
:disabled="!couponFormUser.id || !pointOptions.usable || goodsStore.cartInfo.costSummary.finalPayAmount < pointOptions.minPaymentAmount || (couponFormUser.accountPoints || 0) < (pointOptions.minPoints || 0)"
|
||||
:disabled="!couponFormUser.id || !pointOptions.usable || goodsStore.cartInfo.costSummary.finalPayAmount < pointOptions.minPaymentAmount"
|
||||
:placeholder="pointOptions.usable ? '请输入需要抵扣的积分' : pointOptions.unusableReason"
|
||||
v-loading="pointOptions.loading" @input="pointInput">
|
||||
<template #prepend>现有积分:{{ couponFormUser.accountPoints || 0 }}</template>
|
||||
@@ -214,10 +214,11 @@
|
||||
</el-input>
|
||||
<el-button type="danger" @click="clearPoint">清除</el-button>
|
||||
</div>
|
||||
<div class="point_tips err"
|
||||
v-if="couponFormUser.id && goodsStore.cartInfo.costSummary.finalPayAmount < pointOptions.minPaymentAmount">
|
||||
注意:订单金额不足¥{{
|
||||
formatDecimal(+pointOptions.minPaymentAmount) }},无法使用积分抵扣
|
||||
<div class="point_tips err" v-if="couponFormUser.id && !pointOptions.usable">
|
||||
注意:{{ pointOptions.unusableReason || (`订单金额不足¥${formatDecimal(+pointOptions.minPaymentAmount)},无法使用积分抵扣`) }}
|
||||
</div>
|
||||
<div class="point_tips" v-if="couponFormUser.id && pointOptions.usable">
|
||||
说明:订单已满足使用门槛,当前积分可抵扣最多¥{{ pointOptions.potentialAmount }}(当前积分 {{ couponFormUser.accountPoints || 0 }})
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
@@ -666,6 +667,7 @@ const pointOptions = ref({
|
||||
usable: true,
|
||||
unusableReason: '',
|
||||
amount: 0, // 抵扣金额(元)
|
||||
potentialAmount: 0, // 用户当前积分可抵扣的最大金额(元,供展示)
|
||||
loading: false
|
||||
})
|
||||
|
||||
@@ -775,7 +777,8 @@ const pointInput = _.debounce(function (e) {
|
||||
|
||||
// 未登录用户或无可用积分时直接归0并返回
|
||||
const userAvailablePoints = Number(couponFormUser.value && couponFormUser.value.accountPoints ? couponFormUser.value.accountPoints : 0)
|
||||
if (!couponFormUser.value || !couponFormUser.value.id || userAvailablePoints <= 0) {
|
||||
// 如果未登录、无可用积分或积分抵扣不可用(不满足门槛或商家未开启),直接归0并返回
|
||||
if (!couponFormUser.value || !couponFormUser.value.id || userAvailablePoints <= 0 || !pointOptions.value.usable) {
|
||||
couponForm.value.pointsNum = 0
|
||||
pointOptions.value.amount = 0
|
||||
updateCartCalc()
|
||||
@@ -788,12 +791,11 @@ const pointInput = _.debounce(function (e) {
|
||||
}
|
||||
|
||||
// 边界限制:不得超过最大/小于最小
|
||||
if (couponForm.value.pointsNum > pointOptions.value.maxPoints) {
|
||||
if (pointOptions.value.maxPoints && couponForm.value.pointsNum > pointOptions.value.maxPoints) {
|
||||
couponForm.value.pointsNum = pointOptions.value.maxPoints
|
||||
}
|
||||
if (couponForm.value.pointsNum < pointOptions.value.minPoints) {
|
||||
couponForm.value.pointsNum = pointOptions.value.minPoints
|
||||
}
|
||||
// 允许输入少于 minPoints 的积分(前端做友好展示),实际抵扣金额由 calcPointMoney 和后端规则决定
|
||||
// 如果希望严格按照 minPoints 阈值生效,可在此恢复置0逻辑
|
||||
|
||||
if (!e) {
|
||||
couponForm.value.pointsNum = 0
|
||||
@@ -806,7 +808,7 @@ const pointInput = _.debounce(function (e) {
|
||||
|
||||
|
||||
// 满足条件式开始计算抵扣金额,由后端返回
|
||||
if (couponForm.value.pointsNum >= pointOptions.value.minPoints && couponForm.value.pointsNum <= pointOptions.value.maxPoints) {
|
||||
if (couponForm.value.pointsNum > 0 && (!pointOptions.value.maxPoints || couponForm.value.pointsNum <= pointOptions.value.maxPoints)) {
|
||||
pointOptions.value.loading = true
|
||||
calcPointMoney()
|
||||
}
|
||||
@@ -822,25 +824,30 @@ const calcPointMoney = async () => {
|
||||
const points = Number(couponForm.value.pointsNum || 0)
|
||||
const orderAmount = Number(goodsStore.cartInfo.costSummary.finalPayAmount || 0)
|
||||
|
||||
if (!pointsPerYuan || points <= 0) {
|
||||
// 若不满足计算条件,则直接退出并复位
|
||||
if (!pointOptions.value.usable || !pointsPerYuan || points <= 0) {
|
||||
pointOptions.value.amount = 0
|
||||
// 若未初始化 couponForm.value.amount,则用订单原价
|
||||
couponForm.value.amount = couponForm.value.amount || originOrderAmount.value || orderAmount
|
||||
updateCartCalc()
|
||||
pointOptions.value.loading = false
|
||||
return
|
||||
}
|
||||
|
||||
// 积分可抵扣的金额(元) => 积分 / (积分数/元)
|
||||
let deductionFromPoints = points / pointsPerYuan
|
||||
const deductionFromPoints = points / pointsPerYuan
|
||||
|
||||
// 最大可抵扣金额基于订单金额和最大抵扣比例
|
||||
// 最大可抵扣金额基于订单金额和最大抵扣比例(后端规则)
|
||||
const maxDeductionAmount = orderAmount * (pointOptions.value.maxDeductionRatio || 0)
|
||||
|
||||
// 最终抵扣为积分抵扣金额与最大比例的较小者,且不超过订单可支付金额
|
||||
const baseAmount = Number(couponForm.value.amount || originOrderAmount.value || orderAmount)
|
||||
// 基数为当前可用于抵扣的订单金额(可能已经包含其他优惠),不能小于0
|
||||
const baseAmount = Math.max(0, Number(couponForm.value.amount || originOrderAmount.value || orderAmount))
|
||||
|
||||
// 最终抵扣为:积分折算金额、最大可抵扣金额、当前可抵扣金额三者的最小值
|
||||
let deduction = Math.min(deductionFromPoints, maxDeductionAmount, baseAmount)
|
||||
|
||||
pointOptions.value.amount = formatDecimal(deduction)
|
||||
deduction = Number(formatDecimal(deduction))
|
||||
|
||||
pointOptions.value.amount = deduction
|
||||
couponForm.value.amount = formatDecimal(baseAmount - deduction)
|
||||
|
||||
updateCartCalc()
|
||||
@@ -977,19 +984,46 @@ async function pointOptionsAjax() {
|
||||
// 后端的 equivalentPoints 表示 积分数/元(例如 20 表示 20 积分 = 1 元)
|
||||
pointOptions.value.pointsPerYuan = pointOptions.value.equivalentPoints
|
||||
|
||||
// 规范化 maxDeductionRatio:后端可能以百分比(如50)返回,若大于1则认为是百分比并除以100
|
||||
if (pointOptions.value.maxDeductionRatio > 1) {
|
||||
pointOptions.value.maxDeductionRatio = pointOptions.value.maxDeductionRatio / 100
|
||||
}
|
||||
|
||||
// 计算页面需要的最小/最大可用积分(按接口返回的金额阈值与比例换算为积分)
|
||||
const pointsPerYuan = pointOptions.value.pointsPerYuan || 0
|
||||
const orderAmount = Number(goodsStore.cartInfo.costSummary.finalPayAmount || 0)
|
||||
|
||||
// 最少使用积分:基于最小抵扣金额换算(若无则为0),minPaymentAmount 单位为元
|
||||
pointOptions.value.minPoints = pointOptions.value.minPaymentAmount && pointsPerYuan ? Math.ceil(pointOptions.value.minPaymentAmount * pointsPerYuan) : 0
|
||||
pointOptions.value.minPoints = (pointOptions.value.minPaymentAmount && pointsPerYuan) ? Math.ceil(pointOptions.value.minPaymentAmount * pointsPerYuan) : 0
|
||||
|
||||
// 最大可用积分:基于订单金额与最大抵扣比例换算
|
||||
pointOptions.value.maxPoints = (pointOptions.value.maxDeductionRatio && pointsPerYuan) ? Math.floor(orderAmount * pointOptions.value.maxDeductionRatio * pointsPerYuan) : 0
|
||||
// 最大可用积分:基于订单金额与最大抵扣比例换算。后端返回的 maxDeductionRatio 表示可抵扣的最大金额占比,需换算为积分
|
||||
const maxDeductionAmount = orderAmount * (pointOptions.value.maxDeductionRatio || 0)
|
||||
pointOptions.value.maxPoints = (pointOptions.value.maxDeductionRatio && pointsPerYuan) ? Math.floor(maxDeductionAmount * pointsPerYuan) : 0
|
||||
|
||||
// 可用性
|
||||
pointOptions.value.usable = pointOptions.value.enableRewards === 1 && pointOptions.value.maxPoints > 0
|
||||
pointOptions.value.unusableReason = pointOptions.value.usable ? '' : (pointOptions.value.enableRewards !== 1 ? '商家未开启积分抵扣' : '订单不可抵扣积分')
|
||||
// 可用性:必须开启、订单满足最小支付金额门槛且最大可用积分>0
|
||||
pointOptions.value.usable = (pointOptions.value.enableRewards === 1) && (orderAmount >= (pointOptions.value.minPaymentAmount || 0)) && pointOptions.value.maxPoints > 0
|
||||
|
||||
if (!pointOptions.value.usable) {
|
||||
if (pointOptions.value.enableRewards !== 1) {
|
||||
pointOptions.value.unusableReason = '商家未开启积分抵扣'
|
||||
} else if (orderAmount < (pointOptions.value.minPaymentAmount || 0)) {
|
||||
pointOptions.value.unusableReason = `订单金额不足¥${formatDecimal(+pointOptions.value.minPaymentAmount)},无法使用积分抵扣`
|
||||
} else {
|
||||
pointOptions.value.unusableReason = '订单不可抵扣积分'
|
||||
}
|
||||
} else {
|
||||
pointOptions.value.unusableReason = ''
|
||||
}
|
||||
|
||||
// 计算当前用户积分在当前订单下的潜在最大抵扣金额(仅供展示)
|
||||
let potential = 0
|
||||
const userPoints = Number(couponFormUser.value && couponFormUser.value.accountPoints ? couponFormUser.value.accountPoints : 0)
|
||||
if (pointsPerYuan && userPoints > 0) {
|
||||
potential = Math.min(userPoints / pointsPerYuan, maxDeductionAmount, orderAmount)
|
||||
}
|
||||
pointOptions.value.potentialAmount = formatDecimal(potential)
|
||||
|
||||
console.log('pointOptions after calc:', JSON.parse(JSON.stringify(pointOptions.value)), 'couponFormUser:', JSON.parse(JSON.stringify(couponFormUser.value)), 'orderAmount:', orderAmount)
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user