优惠卷选择显示
parent
35cc05448f
commit
801f4953ff
|
|
@ -102,8 +102,8 @@
|
||||||
<!-- 底部结算栏(固定) -->
|
<!-- 底部结算栏(固定) -->
|
||||||
<view class="checkout-footer">
|
<view class="checkout-footer">
|
||||||
<view class="total-info">
|
<view class="total-info">
|
||||||
<text class="total-label">总金额¥</text>
|
<text class="total-label">应付¥</text>
|
||||||
<text class="total-amount">{{ totalAmount.toFixed(2) }}</text>
|
<text class="total-amount">{{ payableAmountYuan.toFixed(2) }}</text>
|
||||||
<view class="member-benefit">
|
<view class="member-benefit">
|
||||||
<image
|
<image
|
||||||
class="crown-icon"
|
class="crown-icon"
|
||||||
|
|
@ -113,6 +113,12 @@
|
||||||
<text class="benefit-text">{{ memberLevelName }}优惠</text>
|
<text class="benefit-text">{{ memberLevelName }}优惠</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
<view class="coupon-brief" @click="openCouponSelect">
|
||||||
|
<image class="coupon-icon" src="/static/service/coupon-icon.png" mode="aspectFill"></image>
|
||||||
|
<text class="coupon-text">{{ selectedCoupon ? selectedCoupon.name : '选择优惠卷' }}</text>
|
||||||
|
<text class="coupon-deduction" v-if="selectedCoupon && couponDiscountFen > 0">-¥{{ (couponDiscountFen / 100).toFixed(2) }}</text>
|
||||||
|
<text class="coupon-arrow">›</text>
|
||||||
|
</view>
|
||||||
<button
|
<button
|
||||||
class="checkout-btn"
|
class="checkout-btn"
|
||||||
:class="{ disabled: totalAmount <= 0 }"
|
:class="{ disabled: totalAmount <= 0 }"
|
||||||
|
|
@ -131,7 +137,8 @@ import {
|
||||||
getGuildStoreDetail,
|
getGuildStoreDetail,
|
||||||
getGuildVoucher,
|
getGuildVoucher,
|
||||||
getPaySign,
|
getPaySign,
|
||||||
appBuy
|
appBuy,
|
||||||
|
getLuCouponPage
|
||||||
} from "@/api/service";
|
} from "@/api/service";
|
||||||
import NavHeader from "@/components/NavHeader/NavHeader.vue";
|
import NavHeader from "@/components/NavHeader/NavHeader.vue";
|
||||||
|
|
||||||
|
|
@ -149,6 +156,10 @@ export default {
|
||||||
userInfo: {},
|
userInfo: {},
|
||||||
distance: null,
|
distance: null,
|
||||||
paying: false,
|
paying: false,
|
||||||
|
coupons: [],
|
||||||
|
selectedCoupon: null,
|
||||||
|
selectedCouponId: null,
|
||||||
|
couponLoading: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
@ -166,6 +177,36 @@ export default {
|
||||||
return total;
|
return total;
|
||||||
}, 0);
|
}, 0);
|
||||||
},
|
},
|
||||||
|
totalAmountFen() {
|
||||||
|
return Math.round(this.totalAmount * 100);
|
||||||
|
},
|
||||||
|
couponDiscountFen() {
|
||||||
|
if (!this.selectedCoupon) return 0;
|
||||||
|
const now = Date.now();
|
||||||
|
if ((this.selectedCoupon.validStartTime && now < this.selectedCoupon.validStartTime) ||
|
||||||
|
(this.selectedCoupon.validEndTime && now > this.selectedCoupon.validEndTime)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!this.isCouponApplicable(this.selectedCoupon)) return 0;
|
||||||
|
const totalFen = this.totalAmountFen;
|
||||||
|
if (this.selectedCoupon.type === 2) {
|
||||||
|
const percent = this.selectedCoupon.discountPercent || 0;
|
||||||
|
const raw = Math.round(totalFen * (1 - percent / 100));
|
||||||
|
const limit = this.selectedCoupon.discountLimit || 0;
|
||||||
|
const val = limit > 0 ? Math.min(raw, limit) : raw;
|
||||||
|
return Math.max(0, val);
|
||||||
|
}
|
||||||
|
const amt = this.selectedCoupon.discountAmount || this.selectedCoupon.discountPrice || this.selectedCoupon.price || 0;
|
||||||
|
return Math.max(0, Math.min(amt, totalFen));
|
||||||
|
},
|
||||||
|
payableAmountFen() {
|
||||||
|
const val = this.totalAmountFen - this.couponDiscountFen;
|
||||||
|
if (val <= 0 && this.totalAmountFen > 0) return 1;
|
||||||
|
return Math.max(0, val);
|
||||||
|
},
|
||||||
|
payableAmountYuan() {
|
||||||
|
return this.payableAmountFen / 100;
|
||||||
|
},
|
||||||
// 是否有会员优惠
|
// 是否有会员优惠
|
||||||
hasMemberDiscount() {
|
hasMemberDiscount() {
|
||||||
return this.menuList.some((item) => item.selected && item.discount);
|
return this.menuList.some((item) => item.selected && item.discount);
|
||||||
|
|
@ -295,6 +336,7 @@ export default {
|
||||||
// 选中时,如果当前数量为 0 或未设置,则默认数量为 1
|
// 选中时,如果当前数量为 0 或未设置,则默认数量为 1
|
||||||
item.quantity = 1;
|
item.quantity = 1;
|
||||||
}
|
}
|
||||||
|
this.autoSelectBestCoupon();
|
||||||
},
|
},
|
||||||
|
|
||||||
// 增加数量
|
// 增加数量
|
||||||
|
|
@ -310,6 +352,7 @@ export default {
|
||||||
}
|
}
|
||||||
// 增加数量
|
// 增加数量
|
||||||
item.quantity = (item.quantity || 0) + 1;
|
item.quantity = (item.quantity || 0) + 1;
|
||||||
|
this.autoSelectBestCoupon();
|
||||||
},
|
},
|
||||||
|
|
||||||
// 减少数量
|
// 减少数量
|
||||||
|
|
@ -328,6 +371,7 @@ export default {
|
||||||
item.selected = false;
|
item.selected = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.autoSelectBestCoupon();
|
||||||
},
|
},
|
||||||
|
|
||||||
// 格式化价格:将分转换为元(除以100,保留两位小数)
|
// 格式化价格:将分转换为元(除以100,保留两位小数)
|
||||||
|
|
@ -341,6 +385,94 @@ export default {
|
||||||
return yuan.toFixed(2);
|
return yuan.toFixed(2);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async openCouponSelect() {
|
||||||
|
if (this.totalAmountFen <= 0) {
|
||||||
|
uni.showToast({ title: "请先选择商品", icon: "none" });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await this.loadUserCoupons();
|
||||||
|
const eventChannelData = {
|
||||||
|
coupons: this.coupons,
|
||||||
|
selectedCouponId: this.selectedCouponId,
|
||||||
|
};
|
||||||
|
uni.navigateTo({
|
||||||
|
url: "/pages/detail/selectCoupon",
|
||||||
|
success: (res) => {
|
||||||
|
res.eventChannel.emit("acceptDataFromOpenerPage", eventChannelData);
|
||||||
|
res.eventChannel.on("acceptDataFromOpenedPage", ({ coupon }) => {
|
||||||
|
this.selectedCoupon = coupon;
|
||||||
|
this.selectedCouponId = coupon ? coupon.id : null;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
async loadUserCoupons() {
|
||||||
|
if (this.couponLoading) return;
|
||||||
|
this.couponLoading = true;
|
||||||
|
try {
|
||||||
|
const res = await getLuCouponPage({ pageNo: 1, pageSize: 100, status: 0 });
|
||||||
|
const list = (res && res.list) || [];
|
||||||
|
const enhanced = list.map((c) => {
|
||||||
|
const copy = { ...c };
|
||||||
|
copy.isApplicable = this.isCouponApplicable(copy);
|
||||||
|
return copy;
|
||||||
|
});
|
||||||
|
this.coupons = enhanced;
|
||||||
|
if (!this.selectedCoupon && enhanced.length > 0) {
|
||||||
|
this.autoSelectBestCoupon();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
this.couponLoading = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isCouponApplicable(coupon) {
|
||||||
|
const now = Date.now();
|
||||||
|
if (coupon.status !== 0) return false;
|
||||||
|
if (coupon.validStartTime && now < coupon.validStartTime) return false;
|
||||||
|
if (coupon.validEndTime && now > coupon.validEndTime) return false;
|
||||||
|
const totalFen = this.totalAmountFen;
|
||||||
|
if (coupon.usePrice && totalFen < coupon.usePrice) return false;
|
||||||
|
const selectedIds = this.menuList.filter(i => i.selected && i.quantity > 0).map(i => i.id);
|
||||||
|
if (selectedIds.length === 0) return false;
|
||||||
|
if (coupon.productScope === 1) return true;
|
||||||
|
if (coupon.productScope === 2) {
|
||||||
|
const ids = Array.isArray(coupon.voucherIds)
|
||||||
|
? coupon.voucherIds
|
||||||
|
: (typeof coupon.voucherIds === "string" ? coupon.voucherIds.split(",").map(s => Number(s.trim())).filter(Boolean) : []);
|
||||||
|
return selectedIds.some(id => ids.includes(id));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
autoSelectBestCoupon() {
|
||||||
|
if (!this.coupons || this.coupons.length === 0) return;
|
||||||
|
const applicable = this.coupons.filter(c => this.isCouponApplicable(c));
|
||||||
|
if (applicable.length === 0) {
|
||||||
|
this.selectedCoupon = null;
|
||||||
|
this.selectedCouponId = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let best = null;
|
||||||
|
let maxDeduct = -1;
|
||||||
|
applicable.forEach(c => {
|
||||||
|
const deduct = (() => {
|
||||||
|
if (c.type === 2) {
|
||||||
|
const percent = c.discountPercent || 0;
|
||||||
|
const raw = Math.round(this.totalAmountFen * (1 - percent / 100));
|
||||||
|
const limit = c.discountLimit || 0;
|
||||||
|
return Math.max(0, limit > 0 ? Math.min(raw, limit) : raw);
|
||||||
|
}
|
||||||
|
return Math.max(0, Math.min(c.discountAmount || c.discountPrice || c.price || 0, this.totalAmountFen));
|
||||||
|
})();
|
||||||
|
if (deduct > maxDeduct) {
|
||||||
|
maxDeduct = deduct;
|
||||||
|
best = c;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.selectedCoupon = best || null;
|
||||||
|
this.selectedCouponId = best ? best.id : null;
|
||||||
|
this.coupons = this.coupons.map(c => ({ ...c, isApplicable: this.isCouponApplicable(c) }));
|
||||||
|
},
|
||||||
|
|
||||||
// 去结算
|
// 去结算
|
||||||
async handleCheckout() {
|
async handleCheckout() {
|
||||||
if (this.totalAmount <= 0) {
|
if (this.totalAmount <= 0) {
|
||||||
|
|
@ -365,8 +497,8 @@ export default {
|
||||||
.map((item) => `${item.id}:${item.quantity}`)
|
.map((item) => `${item.id}:${item.quantity}`)
|
||||||
.join(";");
|
.join(";");
|
||||||
|
|
||||||
// this.totalAmount 是元, 要转换成分
|
const trxamtFen = this.payableAmountFen;
|
||||||
const trxamt = (this.totalAmount * 100).toFixed(0);
|
const trxamt = String(trxamtFen);
|
||||||
|
|
||||||
console.log("购买信息: " + voucherStr);
|
console.log("购买信息: " + voucherStr);
|
||||||
console.log("金额:" + trxamt);
|
console.log("金额:" + trxamt);
|
||||||
|
|
@ -374,6 +506,7 @@ export default {
|
||||||
shopId: this.shopId,
|
shopId: this.shopId,
|
||||||
voucherData: voucherStr,
|
voucherData: voucherStr,
|
||||||
payableAmount: trxamt,
|
payableAmount: trxamt,
|
||||||
|
couponId: this.selectedCouponId || undefined,
|
||||||
});
|
});
|
||||||
console.log(res);
|
console.log(res);
|
||||||
if (!res) {
|
if (!res) {
|
||||||
|
|
@ -810,6 +943,41 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.coupon-brief {
|
||||||
|
position: absolute;
|
||||||
|
left: 20rpx;
|
||||||
|
top: -68rpx;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 8rpx 12rpx;
|
||||||
|
background: #fff7f8;
|
||||||
|
border: 1rpx dashed #ffd4d8;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
color: #d51c3c;
|
||||||
|
}
|
||||||
|
.coupon-icon {
|
||||||
|
width: 24rpx;
|
||||||
|
height: 24rpx;
|
||||||
|
margin-right: 8rpx;
|
||||||
|
}
|
||||||
|
.coupon-text {
|
||||||
|
font-size: 24rpx;
|
||||||
|
margin-right: 8rpx;
|
||||||
|
max-width: 280rpx;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
.coupon-deduction {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #d51c3c;
|
||||||
|
margin-right: 8rpx;
|
||||||
|
}
|
||||||
|
.coupon-arrow {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #d51c3c;
|
||||||
|
}
|
||||||
|
|
||||||
.checkout-btn {
|
.checkout-btn {
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
font-family: PingFang-SC, PingFang-SC;
|
font-family: PingFang-SC, PingFang-SC;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue