优化添加优惠

This commit is contained in:
gyq
2025-03-25 00:31:50 +08:00
parent a914adc9f8
commit 3e84edbb6c
19 changed files with 402 additions and 238 deletions

View File

@@ -5,16 +5,20 @@
<div class="t1">
<span class="title">应收:</span>
<span class="num">{{ money }}</span>
</div>
<div class="t2">
<span>原价{{ formatDecimal(props.amount - (goodsStore.tableInfo.tableFee || 0)) }}</span>
<span style="margin-left: 20px">餐位费{{ formatDecimal(+goodsStore.tableInfo.tableFee || 0) }}</span>
<span style="margin-left: 20px">优惠{{ formatDecimal(props.amount - money) }}</span>
<span style="margin-left: 20px" v-if="discountRateVlaue" @click="cancelDiscount">
折扣{{ discountRateVlaue }}
<div class="clear" v-if="money != props.amount" @click="reset">
<span style="margin-left: 10px;">清除优惠</span>
<el-icon style="margin-left: 6px">
<CircleClose />
</el-icon>
</div>
</div>
<div class="t2">
<span>原价:{{ originOrderAmount }}</span>
<span>餐位费:{{ formatDecimal(+goodsStore.tableInfo.tableFee || 0) }}</span>
<span>打包费:{{ formatDecimal(+goodsStore.cartInfo.packFee || 0) }}</span>
<span>优惠:{{ formatDecimal(props.amount - money) }}</span>
<span v-if="discountRateVlaue">
<span>折扣:{{ discountRateVlaue }}</span>
</span>
</div>
</div>
@@ -56,7 +60,7 @@
<div class="item" @click="amountInput('0')">0</div>
<div class="item" @click="delHandle">
<el-icon>
<CloseBold />
<Back />
</el-icon>
</div>
</div>
@@ -115,16 +119,10 @@
<el-pagination layout="prev, pager, next, total" background style="margin-top: 20px"
:total="Number(buyerTable.total)" v-model:current-page="buyerTable.page" @current-change="getBuyerList" />
</el-dialog>
<el-dialog v-model="showCoupon" title="添加优惠" @open="couponDialogOpen" @closed="resetCouponFormHandle" top="5vh"
width="80%">
<el-dialog v-model="showCoupon" :title="`添加优惠(¥${originOrderAmount}`" @open="couponDialogOpen"
@closed="resetCouponFormHandle" top="5vh" width="80%">
<div class="coupom_dialog">
<el-form ref="couponFormRef" :model="couponForm" label-width="100" label-position="left">
<el-form-item label="整单折扣">
<el-input v-model="couponForm.discountRatio" placeholder="请输入折扣" style="width: 180px;"
@input="discountInput">
<template #append></template>
</el-input>
</el-form-item>
<el-form-item label="选择会员">
<div class="flex">
<div class="select_wrap">
@@ -137,9 +135,16 @@
<el-button type="danger" @click="clearCouponUser">清除</el-button>
</div>
</el-form-item>
<el-form-item label="整单折扣">
<el-input v-model="couponForm.discountRatio" placeholder="请输入折扣" style="width: 180px;"
@input="discountInput">
<template #append></template>
</el-input>
</el-form-item>
<el-form-item label="优惠券">
<div style="width: 100%;">
<el-button type="primary" :disabled="!couponFormUser.id"
<el-button type="primary"
:disabled="!couponFormUser.id && (!couponResList1.length && !couponResList2.length)"
@click="showCounponModalHandle">选择优惠券</el-button>
<div>
<div class="title">优惠券</div>
@@ -156,11 +161,11 @@
<div v-html="scope.row.useRestrictions"></div>
</template>
</el-table-column>
<el-table-column label="操作" width="110" align="center">
<!-- <el-table-column label="操作" width="110" align="center">
<template v-slot="scope">
<el-button type="danger" @click="delCoupon(scope.$index, 1)">删除</el-button>
</template>
</el-table-column>
</el-table-column> -->
</el-table>
</div>
<div>
@@ -169,7 +174,12 @@
<el-table-column label="名称" prop="name"></el-table-column>
<el-table-column label="商品信息">
<template v-slot="scope">
{{ scope.row.productName }} {{ scope.row.lowPrice }}
{{ scope.row.productName }}
</template>
</el-table-column>
<el-table-column label="抵扣" prop="useRestrictions">
<template v-slot="scope">
<div v-html="scope.row.discount"></div>
</template>
</el-table-column>
<el-table-column label="描述" prop="useRestrictions">
@@ -177,38 +187,42 @@
<div v-html="scope.row.useRestrictions"></div>
</template>
</el-table-column>
<el-table-column label="操作" width="110" align="center">
<!-- <el-table-column label="操作" width="110" align="center">
<template v-slot="scope">
<el-button type="danger" @click="delCoupon(scope.$index, 2)">删除</el-button>
</template>
</el-table-column>
</el-table-column> -->
</el-table>
</div>
</div>
</el-form-item>
<el-form-item label="积分抵扣">
<el-input v-model="couponForm.pointsNum"
:disabled="!couponFormUser.id || !pointOptions.usable || couponForm.amount < pointOptions.minPaymentAmount"
:placeholder="pointOptions.usable ? '请输入需要抵扣的积分' : pointOptions.unusableReason"
v-loading="pointOptions.loading" @input="pointInput">
<template #prepend>现有积分{{ couponFormUser.accountPoints || 0 }}</template>
<template #append>可抵扣金额{{ pointOptions.amount || 0 }}</template>
</el-input>
<div class="flex">
<el-input v-model="couponForm.pointsNum"
:disabled="!couponFormUser.id || !pointOptions.usable || couponForm.amount < pointOptions.minPaymentAmount"
:placeholder="pointOptions.usable ? '请输入需要抵扣的积分' : pointOptions.unusableReason"
v-loading="pointOptions.loading" @input="pointInput">
<template #prepend>现有积分{{ couponFormUser.accountPoints || 0 }}</template>
<template #append>可抵扣金额{{ pointOptions.amount || 0 }}</template>
</el-input>
<el-button type="danger" @click="clearPoint">清除</el-button>
</div>
<div class="point_tips err"
v-if="couponFormUser.id && couponForm.amount < pointOptions.minPaymentAmount">注意订单金额不足{{
formatDecimal(+pointOptions.minPaymentAmount) }}无法使用积分抵扣
</div>
</el-form-item>
<el-form-item label="优惠完">
<div class="res">
<span class="i"></span> <span class="n">{{ formatDecimal(+couponForm.amount) }}</span>
</div>
</el-form-item>
</el-form>
</div>
<div class="dialog_footer" style="display: flex;justify-content: flex-end;">
<el-button @click="showCoupon = false">取消</el-button>
<el-button type="primary" @click="discountConfirm">确定</el-button>
<div class="dialog_footer">
<div class="result">
优惠完
<span class="i"></span> <span class="n">{{ formatDecimal(+couponForm.amount) }}</span>
</div>
<div class="btn">
<el-button @click="showCoupon = false">取消</el-button>
<el-button type="primary" @click="discountConfirm">确定</el-button>
</div>
</div>
</el-dialog>
<!-- 选择会员 -->
@@ -227,16 +241,16 @@ import scanModal from "@/components/payCard/scanModal.vue";
import SelectVipUser from '@/components/selectVipUser.vue'
import CouponModal from '@/components/payCard/couponModal.vue'
import { ElMessage } from "element-plus";
import { useGlobal } from "@/store/global.js";
import { staffPermission } from "@/api/user.js";
import { cashPay, buyerPage, creditPay, vipPay } from "@/api/order.js";
import { calcUsablePoints, calcDeductionAmount } from '@/api/account.js'
import { useGoods } from "@/store/goods.js";
const emit = defineEmits(["paySuccess", 'orderExpired', 'reset']);
const SelectVipUserRef = ref(null)
const CouponModalRef = ref(null)
const goodsStore = useGoods();
const global = useGlobal();
const store = useUser();
const props = defineProps({
@@ -262,13 +276,16 @@ const props = defineProps({
}
});
const discountAmount = ref(null)
watch(props, () => {
money.value = formatDecimal(props.amount)
originOrderAmount.value = formatDecimal(props.amount - (goodsStore.tableInfo.tableFee || 0) -
(goodsStore.cartInfo.packFee || 0))
payData.value.checkOrderPay.isPrint = props.isPrint
})
const emit = defineEmits(["paySuccess", 'orderExpired']);
const originOrderAmount = ref(0)
const money = ref("0");
const discountRateVlaue = ref(0)
const scanModalRef = ref(null);
@@ -353,18 +370,10 @@ function scanCodeSuccess() {
// 会员支付
async function vipPayAjax(row) {
try {
if (row.amount < money.value) {
ElMessage.error('余额不足')
return
}
goodsStore.showVipPrice = 1
goodsStore.vipUserInfo = row
goodsStore.calcCartInfo()
reset()
// if (row.amount < money.value) {
// ElMessage.error('余额不足')
// return
// }
payData.value.payType = 'userPay'
payData.value.shopUserId = row.id
payData.value.checkOrderPay.userId = row.userId
@@ -378,6 +387,10 @@ async function vipPayAjax(row) {
emit("paySuccess");
} catch (error) {
console.log(error);
if (error.code == 701) {
// 订单已过期需刷新购物车和订单
emit('orderExpired')
}
}
payLoading.value = false;
}
@@ -406,11 +419,6 @@ async function payTypeChange(index, item) {
if (item.payType == 'deposit') {
scanModalRef.value.show();
}
// if (payActive.value != "buyer") {
// if (payList.value[payActive.value].payType == "deposit") {
// }
// }
} catch (error) {
console.log(error);
}
@@ -420,11 +428,6 @@ async function payTypeChange(index, item) {
async function confirmOrder() {
try {
if (payLoading.value) return
payData.value.checkOrderPay.orderAmount = formatDecimal(+money.value);
payData.value.checkOrderPay.roundAmount = roundAmount.value;
payData.value.checkOrderPay.vipPrice = goodsStore.vipUserInfo.userId ? 1 : 0;
payData.value.checkOrderPay.couponList = [...couponResList1.value.map(item => item.id), ...couponResList2.value.map(item => item.id)];
// await staffPermission("yun_xu_shou_kuan");
if (payList.value[payActive.value].payType == "arrears") {
showBuyerHandle();
@@ -465,7 +468,7 @@ async function confirmOrder() {
emit("paySuccess");
}
} catch (error) {
if (error.code == 701 || error.code == 603) {
if (error.code == 701) {
// 订单已过期需刷新购物车和订单
emit('orderExpired')
}
@@ -477,26 +480,44 @@ async function confirmOrder() {
// 输入
function amountInput(num) {
if (money.value + num <= props.amount) {
money.value = clearNoNum({ value: (money.value += num) })
if (discountAmount.value !== null) {
if (money.value + num <= discountAmount.value) {
money.value = clearNoNum({ value: (money.value += num) })
} else {
money.value = formatDecimal(+discountAmount.value);
}
roundAmount.value = formatDecimal(discountAmount.value - money.value)
} else {
money.value = formatDecimal(+props.amount);
if (money.value + num <= props.amount) {
money.value = clearNoNum({ value: (money.value += num) })
} else {
money.value = formatDecimal(+props.amount);
}
roundAmount.value = formatDecimal(props.amount - money.value)
}
roundAmount.value = formatDecimal(props.amount - money.value)
console.log('roundAmount.value', roundAmount.value);
payData.value.checkOrderPay.roundAmount = roundAmount.value;
payData.value.checkOrderPay.orderAmount = money.value;
}
// 删除
function delHandle() {
if (!money.value) return;
money.value = money.value.substring(0, money.value.length - 1);
if (!money.value) return; money.value = money.value.substring(0, money.value.length - 1);
if (!money.value) {
money.value = "0";
}
roundAmount.value = formatDecimal(props.amount - money.value)
console.log('roundAmount.value', roundAmount.value);
if (discountAmount.value !== null) {
roundAmount.value = formatDecimal(discountAmount.value - money.value)
} else {
roundAmount.value = formatDecimal(props.amount - money.value)
}
payData.value.checkOrderPay.roundAmount = roundAmount.value;
payData.value.checkOrderPay.orderAmount = money.value;
}
// 获取支付方式
@@ -513,21 +534,17 @@ async function queryPayTypeAjax() {
});
payList.value = res.filter(item => item.isDisplay);
if (payList.value[0].payType == "scanCode" && !payList.value[0].disabled) {
scanModalRef.value.show();
payType.value = payList.value[0].payType;
if (payList.value.length) {
if (payList.value[0].payType == "scanCode" && !payList.value[0].disabled) {
scanModalRef.value.show();
payType.value = payList.value[0].payType;
}
}
} catch (error) {
console.log(error);
}
}
// 取消折扣
function cancelDiscount() {
discountRateVlaue.value = 0
money.value = formatDecimal(props.amount)
}
/** 添加优惠 start */
const showCoupon = ref(false)
const couponFormRef = ref(null)
@@ -593,61 +610,49 @@ const discountInput = _.debounce(function (e) {
pointOptions.value.amount = 0
}, 500)
// const discountInput = (e) => {
// setTimeout(() => {
// couponForm.value.amount = couponForm.value.originAmount
// couponForm.value.discountRatio = inputFilterFloat(e)
// if (couponForm.value.discountRatio > 9.9) {
// couponForm.value.discountRatio = 9.9
// }
// if (couponForm.value.discountRatio < 0.1) {
// couponForm.value.discountRatio = 0.1
// }
// if (couponForm.value.discountRatio) {
// couponForm.value.amount = formatDecimal(couponForm.value.amount * (couponForm.value.discountRatio / couponFormDiscountRate.value))
// } else {
// couponForm.value.amount = formatDecimal(+couponForm.value.originAmount)
// }
// // 将优惠券/积分所有设置初始化
// couponResList1.value = []
// couponResList2.value = []
// couponForm.value.pointsNum = ''
// pointOptions.value.amount = 0
// }, 50)
// }
// 积分输入格式化
function pointInput(e) {
setTimeout(() => {
couponForm.value.pointsNum = inputFilterInt(e)
// 若如果大于最大值
if (couponForm.value.pointsNum > pointOptions.value.max) {
couponForm.value.pointsNum = pointOptions.value.max
}
// 如果小于最大值
if (couponForm.value.pointsNum < pointOptions.value.min) {
couponForm.value.pointsNum = pointOptions.value.min
}
if (!e) {
couponForm.value.pointsNum = 0
couponForm.value.amount = +couponForm.value.amount + +pointOptions.value.amount
pointOptions.value.amount = 0
}
// 满足条件式开始计算抵扣金额,由后端返回
if (couponForm.value.pointsNum >= pointOptions.value.min && couponForm.value.pointsNum <= pointOptions.value.max) {
pointOptions.value.loading = true
calcPointMoney()
}
}, 50)
// 清除积分
function clearPoint() {
if (couponForm.value.pointsNum > 0) {
couponForm.value.pointsNum = ''
couponForm.value.amount = +couponForm.value.amount + +pointOptions.value.amount
pointOptions.value.amount = 0
}
}
// 003-根据积分计算可抵扣金额
const calcPointMoney = _.debounce(async function () {
// 积分输入格式化
const pointInput = _.debounce(function (e) {
couponForm.value.pointsNum = inputFilterInt(e)
console.log('inputFilterInt===', couponForm.value.pointsNum);
// 若如果大于最大值
if (couponForm.value.pointsNum > pointOptions.value.max) {
couponForm.value.pointsNum = pointOptions.value.max
}
// 如果小于最大值
if (couponForm.value.pointsNum < pointOptions.value.min) {
couponForm.value.pointsNum = pointOptions.value.min
}
if (!e) {
couponForm.value.pointsNum = 0
couponForm.value.amount = +couponForm.value.amount + +pointOptions.value.amount
pointOptions.value.amount = 0
}
console.log('pointOptions.value===', pointOptions.value);
console.log('couponForm.value.pointsNum===', couponForm.value.pointsNum);
// 满足条件式开始计算抵扣金额,由后端返回
if (couponForm.value.pointsNum >= pointOptions.value.min && couponForm.value.pointsNum <= pointOptions.value.max) {
pointOptions.value.loading = true
calcPointMoney()
}
}, 500)
// 根据积分计算可抵扣金额
const calcPointMoney = async () => {
try {
const res = await calcDeductionAmount({
shopUserId: couponFormUser.value.id,
@@ -660,11 +665,15 @@ const calcPointMoney = _.debounce(async function () {
console.log(error);
}
pointOptions.value.loading = false
}, 500)
}
// 当dialog打开时
function couponDialogOpen() {
couponForm.value.amount = formatDecimal(money.value - (goodsStore.tableInfo.tableFee || 0))
couponResList2Amount.value = 0
couponForm.value.discountRatio = ''
// 需减去抹零金额
couponForm.value.amount = formatDecimal(originOrderAmount.value - roundAmount.value)
couponForm.value.originAmount = couponForm.value.amount
resetCouponForm.value = { ...couponForm.value }
@@ -672,7 +681,7 @@ function couponDialogOpen() {
couponResList2.value = []
// 当购物车已存在用户时
if (goodsStore.vipUserInfo.id && goodsStore.showVipPrice) {
if (goodsStore.vipUserInfo.id) {
couponFormUserList.value = [
{
id: goodsStore.vipUserInfo.userId,
@@ -680,7 +689,10 @@ function couponDialogOpen() {
}
]
couponFormUser.value = goodsStore.vipUserInfo
pointOptions()
pointOptionsAjax()
} else {
couponFormUserList.value = []
couponFormUser.value = ''
}
}
@@ -692,6 +704,23 @@ function resetCouponFormHandle() {
// 选择会员完成后
async function selectUserHandle(row) {
try {
console.log('selectUserHandle===', row);
goodsStore.vipUserInfo = { ...row }
// 选择会员后重新计算会员价
if (store.shopInfo.isMemberPrice && row.isVip) {
goodsStore.showVipPrice = 1
}
goodsStore.calcCartInfo()
emit('reset')
couponForm.value.discountRatio = ''
discountInput('')
setTimeout(() => {
couponDialogOpen()
}, 100)
if (showCoupon.value) {
couponFormUserList.value = [
{
@@ -706,10 +735,10 @@ async function selectUserHandle(row) {
if (couponFormUser.id && row.userId != couponFormUser.value.userId) {
resetCoupon()
}
}
if (payList.value[payActive.value].payType == 'member-account') {
vipPayAjax(row)
} else {
if (payList.value[payActive.value].payType == 'member-account') {
vipPayAjax(row)
}
}
} catch (error) {
console.log(error);
@@ -720,7 +749,7 @@ async function selectUserHandle(row) {
function resetCoupon() {
couponResList1.value = []
couponResList2.value = []
couponForm.value.amount = formatDecimal(couponForm.value.amount * (couponForm.value.discountRatio / couponFormDiscountRate.value))
couponForm.value.amount = originOrderAmount.value
}
// 选择完用户后开始获取积分使用配置
@@ -751,33 +780,54 @@ function showCounponModalHandle() {
CouponModalRef.value.show(couponFormUser.value.id)
}
const couponResList2Amount = ref(0)
// 选择完优惠券的回调事件
function CouponModalSuccess(res) {
console.log(res);
couponResType.value = res.type
clearPoint()
if (res.type == 2) {
couponResList2Amount.value = 0
couponResList1.value = []
couponForm.value.fullCouponDiscountAmount = 0
couponResList2.value = res.couponList
// 商品券
const discountOrders = applyCoupons([...props.orderList], couponResList2.value)
// 计算所有的优惠金额
discountOrders.forEach(item => {
if (item.isCoupon) {
if (item.discount) {
couponResList2Amount.value += item.discount
}
}
})
couponForm.value.productCouponDiscountAmount = couponResList2Amount.value
}
if (res.type == 1) {
if (couponForm.value.amount < res.couponList[0].fullAmount) {
ElMessage.error(`订单金额不足¥${formatDecimal(res.couponList[0].fullAmount, 2, true)},无法使用优惠券`)
return
} else {
couponResList1.value = res.couponList
couponForm.value.amount = formatDecimal(couponForm.value.amount - res.couponList[0].discountAmount)
couponForm.value.fullCouponDiscountAmount = res.couponList[0].discountAmount
}
} else {
couponResList2.value = res.couponList
const discountOrders = applyCoupons([...props.orderList], couponResList2.value)
console.log('discountOrder===', discountOrders);
couponResList1.value = res.couponList
couponForm.value.fullCouponDiscountAmount = res.couponList[0].discountAmount
}
// 计算所有的优惠金额
let amount = 0
discountOrders.forEach(item => {
if (item.isCoupon) {
amount += item.price
}
})
couponForm.value.productCouponDiscountAmount = amount
couponForm.value.amount = formatDecimal(couponForm.value.amount - amount)
let rate = 1
if (couponForm.value.discountRatio) {
rate = couponForm.value.discountRatio / couponFormDiscountRate.value
}
// 满减券切勿使用discount计算
couponForm.value.amount = formatDecimal((originOrderAmount.value * rate) - (couponResList1.value.length ? couponResList1.value[0].discountAmount : 0) - couponResList2Amount.value)
if (couponForm.value.amount < 0) {
couponForm.value.amount = 0
}
}
@@ -796,6 +846,7 @@ const applyCoupons = (orders, coupons) => {
eligibleProducts.forEach(product => {
if (!couponUsed && !product.isCoupon) {
product.isCoupon = true;
product.discount = coupon.discount
couponUsed = true; // 标记优惠券已使用
}
});
@@ -829,9 +880,6 @@ function discountConfirm() {
let rate = couponForm.value.discountRatio / couponFormDiscountRate.value
let discount = formatDecimal(couponForm.value.originAmount * rate)
payData.value.checkOrderPay.discountAmount = formatDecimal(couponForm.value.originAmount - discount)
// console.log(rate);
// console.log(discount);
// console.log(payData.value.checkOrderPay.discountAmount);
} else {
payData.value.checkOrderPay.discountAmount = 0
}
@@ -848,19 +896,26 @@ function discountConfirm() {
payData.value.checkOrderPay.orderAmount = couponForm.value.amount
// 优惠完之后加上餐位费
money.value = formatDecimal(+couponForm.value.amount + +(goodsStore.tableInfo.tableFee || 0))
money.value = formatDecimal(+couponForm.value.amount + +(goodsStore.tableInfo.tableFee || 0) + +(goodsStore.cartInfo.packFee || 0))
discountAmount.value = money.value
payData.value.checkOrderPay.fullCouponDiscountAmount = couponForm.value.fullCouponDiscountAmount
showCoupon.value = false
payData.value.checkOrderPay.couponList = [...couponResList1.value.map(item => item.id), ...couponResList2.value.map(item => item.id)];
payData.value.checkOrderPay.orderAmount = money.value
}
/** 添加优惠 end */
// 初始化
function reset() {
discountAmount.value = null
roundAmount.value = 0
discountRateVlaue.value = 0
money.value = `${formatDecimal(props.amount)}`;
originOrderAmount.value = formatDecimal(props.amount - (goodsStore.tableInfo.tableFee || 0) -
(goodsStore.cartInfo.packFee || 0))
payData.value = {
shopId: store.shopInfo.id,
buyerRemark: "", // 订单备注
@@ -883,11 +938,11 @@ function reset() {
isPrint: props.isPrint
},
};
}
onMounted(() => {
queryPayTypeAjax();
});
if (!payList.value.length) {
queryPayTypeAjax()
}
}
defineExpose({
reset
@@ -916,23 +971,33 @@ defineExpose({
.t1 {
display: flex;
align-items: flex-end;
color: var(--el-color-danger);
font-weight: bold;
.title {
font-size: var(--el-font-size-base);
position: relative;
top: 14px;
bottom: 6px;
}
.num {
font-size: 30px;
}
.clear {
position: relative;
bottom: 6px;
display: flex;
align-items: center;
margin-left: 20px;
}
}
.t2 {
display: flex;
color: #999;
gap: 10px;
padding-top: 10px;
span {
@@ -1054,6 +1119,9 @@ defineExpose({
}
.coupom_dialog {
height: 60vh;
overflow-y: auto;
.title {
font-size: 16px;
}
@@ -1087,4 +1155,21 @@ defineExpose({
}
}
}
.dialog_footer {
display: flex;
align-items: center;
justify-content: flex-end;
justify-content: space-between;
padding-top: 20px;
.result {
font-size: 22px;
font-weight: bold;
}
.btn {
display: flex;
}
}
</style>