Files
cashier_desktop/src/components/payCard/payCard.vue
2025-11-18 14:32:25 +08:00

1354 lines
46 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="card">
<div class="header">
<div class="left">
<div class="t1">
<span class="title">应收:</span>
<span class="num">{{ formatDecimal(goodsStore.cartInfo.costSummary.finalPayAmount || 0) }}</span>
<!-- <div class="clear" v-if="money != props.amount" @click="emit('reset')">
<span style="margin-left: 10px;">清除优惠</span>
<el-icon style="margin-left: 6px">
<CircleClose />
</el-icon>
</div> -->
</div>
<div class="t2">
<span>商品原价:{{ goodsStore.cartInfo.costSummary.goodsRealAmount || 0 }}</span>
<span>餐位费:{{ formatDecimal(goodsStore.cartInfo.costSummary.seatFee || 0)
}}</span>
<span>打包费:{{ formatDecimal(goodsStore.cartInfo.costSummary.packFee || 0)
}}</span>
<span>优惠:{{ formatDecimal(goodsStore.cartInfo.costSummary.totalDiscountAmount || 0) }}</span>
<!-- <span v-if="goodsStore.cartInfo.costSummary.goodsDiscountAmount">
<span>折扣:{{ goodsStore.cartInfo.costSummary.goodsDiscountAmount }}</span>
</span> -->
</div>
</div>
</div>
<div class="number_wrap">
<div class="menus">
<div class="item" :class="{ active: payActive == index, disabled: item.disabled }"
v-for="(item, index) in payList" :key="item.id" @click="payTypeChange(index, item)">
<div class="icon">
<el-image :src="item.icon" class="img"></el-image>
</div>
<span class="title">{{ item.payName }}</span>
</div>
<!-- <div class="item" :class="{ active: payActive == 'buyer' }"
@click="payTypeChange('buyer', { payType: 'buyer' })">
<div class="icon">
<div class="img"
style="display: flex;align-items: center;justify-content: center;background-color: var(--el-color-danger);color: #fff;font-size: 24px;border-radius: 11px;">
</div>
</div>
<span class="title">挂账</span>
</div> -->
</div>
<div class="input_wrap">
<div class="input" style="flex: 1">付款{{ formatDecimal(goodsStore.cartInfo.costSummary.finalPayAmount
|| 0) }}</div>
<el-button type="primary" style="width: 120px;border-radius: 6px; height: 60px;"
@click="showCouponHandle">添加优惠</el-button>
</div>
<div class="blance">
<!-- 可用余额0.00 -->
</div>
<div class="keybord_wrap">
<div class="left">
<div class="item" v-for="item in 9" :key="item" @click="amountInput(`${item}`)">
{{ item }}
</div>
<div class="item" @click="amountInput('.')">.</div>
<div class="item" @click="amountInput('0')">0</div>
<div class="item" @click="delHandle">
<el-icon>
<Back />
</el-icon>
</div>
</div>
<div class="pay_btn" v-loading="payLoading" @click="confirmOrder">
<span></span>
<span></span>
</div>
</div>
</div>
</div>
<scanModal ref="scanModalRef" :amount="props.amount" :money="money" :orderId="props.orderId"
:selecttype="props.selecttype" :payType="payType" :payData="payData" @success="scanCodeSuccess"
@orderExpired="emit('orderExpired')" />
<!-- 选择挂账人员 -->
<el-dialog title="挂账" top="1vh" v-model="showBuyer" width="90%" @closed="resetBuyerTable">
<el-form inline>
<el-form-item>
<el-input placeholder="请输入挂账人或手机号搜索" v-model="buyerTable.keywords" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="getBuyerList">搜索</el-button>
<el-button @click="resetBuyerTable">重置</el-button>
</el-form-item>
</el-form>
<el-table :data="buyerTable.list" height="440px" border stripe v-loading="buyerTable.loading">
<el-table-column prop="debtor" label="挂账人" width="100px" />
<el-table-column prop="mobile" label="手机" width="150px" />
<el-table-column prop="position" label="职位" width="120px" />
<el-table-column prop="repaymentMethod" label="还款方式" width="160px">
<template v-slot="scope">
<template v-if="scope.row.repaymentMethod == 'total'">按总金额还款</template>
<template v-if="scope.row.repaymentMethod == 'order'">按订单还款</template>
</template>
</el-table-column>
<el-table-column prop="creditAmount" label="挂账额度" width="160px">
<template v-slot="scope">
{{ formatDecimal(scope.row.creditAmount) }}
</template>
</el-table-column>
<el-table-column prop="remainingAmount" label="剩余挂账额度" width="160px">
<template v-slot="scope">
{{ formatDecimal(scope.row.remainingAmount) }}
</template>
</el-table-column>
<el-table-column prop="accumulateAmount" label="累计挂账金额" width="160px">
<template v-slot="scope">
{{ formatDecimal(scope.row.accumulateAmount) }}
</template>
</el-table-column>
<el-table-column label="操作" width="120px" fixed="right">
<template v-slot="scope">
<el-button type="primary" @click="payCreditPayHandle(scope.row)">选择</el-button>
</template>
</el-table-column>
</el-table>
<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="`添加优惠(商品原价:¥${formatDecimal(goodsStore.cartInfo.costSummary.goodsRealAmount || 0)}`" top="5vh" width="80%"
@open="couponDialogOpen">
<div class="coupom_dialog">
<el-form ref="couponFormRef" :model="couponForm" label-width="100" label-position="left">
<el-form-item label="选择用户">
<div class="flex">
<div class="select_wrap">
<el-select placeholder="请选择用户" readonly v-model="couponFormUser.userId"
@click="SelectVipUserRef.show()" style="width: 100%;">
<el-option :label="item.nickName" :value="item.id" v-for="item in couponFormUserList"
:key="item.id"></el-option>
</el-select>
</div>
<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"
v-if="(goodsStore.cartInfo.costSummary
.fullReduction !== undefined && goodsStore.cartInfo.costSummary.fullReduction.actualAmount > 0)"
disabled>参与满减活动不可用优惠券</el-button>
<el-button type="primary"
:disabled="(!couponFormUser.id && (!couponResList1.length && !couponResList2.length))"
@click="showCounponModalHandle" v-else>选择优惠券</el-button>
<div style="padding-top: 20px;">
<el-table :data="couponResList1" border stripe>
<el-table-column label="名称" prop="name"></el-table-column>
<el-table-column label="抵扣" prop="discountAmount"></el-table-column>
<el-table-column label="限制" prop="fullAmount">
<template v-slot="scope">
满{{ scope.row.fullAmount }}减{{ scope.row.discountAmount }}
</template>
</el-table-column>
<el-table-column label="描述" prop="useRestrictions">
<template v-slot="scope">
<div v-html="scope.row.useRestrictions"></div>
</template>
</el-table-column>
<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>
</div>
<!-- <div>
<div class="title">商品券</div>
<el-table :data="couponResList2" border stripe>
<el-table-column label="名称" prop="name"></el-table-column>
<el-table-column label="商品信息">
<template v-slot="scope">
{{ 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">
<template v-slot="scope">
<div v-html="scope.row.useRestrictions"></div>
</template>
</el-table-column>
<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>
</div> -->
</div>
</el-form-item>
<el-form-item label="积分抵扣">
<div class="flex">
<el-input v-model="couponForm.pointsNum"
: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>
<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 && goodsStore.cartInfo.costSummary.finalPayAmount < pointOptions.minPaymentAmount">
注意:订单金额不足¥{{
formatDecimal(+pointOptions.minPaymentAmount) }},无法使用积分抵扣
</div>
</el-form-item>
</el-form>
</div>
<div class="dialog_footer">
<div class="result">
优惠完:
<span class="i">¥</span> <span class="n">{{
formatDecimal(goodsStore.cartInfo.costSummary.finalPayAmount) }}</span>
</div>
<div class="btn">
<el-button @click="cancelAllDiscount">取消</el-button>
<el-button type="primary" @click="discountConfirm">确定</el-button>
</div>
</div>
</el-dialog>
<!-- 选择会员 -->
<SelectVipUser ref="SelectVipUserRef" @success="selectUserHandle" />
<!-- 选择优惠券 -->
<CouponModal ref="CouponModalRef" :orderList="props.orderList" @success="CouponModalSuccess" />
</template>
<script setup>
import _ from 'lodash'
import { onMounted, ref, reactive, watch } from "vue";
import { useUser } from "@/store/user.js";
import { clearNoNum, formatDecimal, inputFilterInt, inputFilterFloat } from "@/utils";
import { getPayType } from "@/api/account.js";
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 { 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 store = useUser();
const props = defineProps({
amount: {
type: Number,
default: 0,
},
selecttype: {
type: Number,
default: 0,
},
orderId: {
type: [Number, String],
default: 0,
},
orderList: {
type: Array,
default: []
},
isPrint: {
type: [Number, String],
default: 1,
}
});
const discountAmount = ref(null)
watch(props, () => {
if (goodsStore.cartInfo.costSummary) {
money.value = formatDecimal(goodsStore.cartInfo.costSummary.finalPayAmount)
}
// originOrderAmount.value = formatDecimal(props.amount - (goodsStore.tableInfo.tableFee || 0) -
// (goodsStore.cartInfo.packFee || 0))
})
const originOrderAmount = ref(0)
const money = ref("0");
const discountRateVlaue = ref(0)
const scanModalRef = ref(null);
const payActive = ref(0);
const payType = ref("");
const payList = ref([]);
const payLoading = ref(false);
const payData = ref({});
const roundAmount = ref(0) // 抹零金额
// 挂账人 start
const showBuyer = ref(false);
const buyerTable = reactive({
keywords: "",
loading: false,
page: 1,
size: 10,
total: 0,
list: [],
});
// 显示挂账人
function showBuyerHandle() {
showBuyer.value = true;
getBuyerList();
}
// 重置
function resetBuyerTable() {
buyerTable.keywords = "";
buyerTable.page = 1;
getBuyerList();
}
// 获取挂账人列表
async function getBuyerList() {
try {
buyerTable.loading = true;
const res = await buyerPage({
page: buyerTable.page,
size: buyerTable.size,
keywords: buyerTable.keywords,
status: 1,
responsiblePerson: "",
repaymentStatus: "",
});
buyerTable.list = res.records;
buyerTable.total = res.totalRow;
} catch (error) {
console.log(error);
}
buyerTable.loading = false;
}
// 选择挂账人支付
async function payCreditPayHandle(row) {
try {
payLoading.value = true;
buyerTable.loading = true;
payData.value.creditBuyerId = row.id
await creditPay(payData.value);
showBuyer.value = false;
payLoading.value = false;
buyerTable.loading = false;
emit("paySuccess");
} catch (error) {
console.log(error);
}
buyerTable.loading = false;
payLoading.value = false;
}
// 显示选择挂账人 end
// 获得扫码值
function scanCodeSuccess() {
emit("paySuccess");
}
// 会员支付
async function vipPayAjax(row) {
try {
// if (row.amount < money.value) {
// ElMessage.error('余额不足')
// return
// }
payData.value.payType = 'userPay'
payData.value.shopUserId = row.id
payData.value.checkOrderPay.userId = row.userId
payLoading.value = true;
await vipPay(payData.value)
goodsStore.showVipPrice = 0
goodsStore.vipUserInfo = ''
emit("paySuccess");
} catch (error) {
console.log(error);
if (error.code == 701) {
// 订单已过期需刷新购物车和订单
emit('orderExpired')
}
}
payLoading.value = false;
}
// 切换支付类型
async function payTypeChange(index, item) {
try {
console.log(item);
// await staffPermission('yun_xu_shou_kuan')
// if (item.disabled) return
payActive.value = index;
payType.value = item.payType;
upadatePayData()
if (item.payType == "scanCode") {
scanModalRef.value.show();
}
if (item.payType == "member-account") {
if (goodsStore.vipUserInfo.id) {
// await vipPayAjax(goodsStore.vipUserInfo)
} else {
SelectVipUserRef.value.show()
}
}
if (item.payType == "arrears") {
// 挂账支付
showBuyerHandle();
}
if (item.payType == 'deposit') {
scanModalRef.value.show();
}
} catch (error) {
console.log(error);
}
}
// 更新支付参数
function upadatePayData() {
// console.log(goodsStore.cartInfo);
payData.value.checkOrderPay = {
vipPrice: store.shopInfo.isMemberPrice ? goodsStore.showVipPrice : 0,
orderId: goodsStore.orderListInfo.id,
// discountRatio: (checkOrderPay.discount / 100).toFixed(2),
discountRatio: 0,
seatNum: goodsStore.allSelected ? 0 : goodsStore.tableInfo.num,
originAmount: goodsStore.cartInfo.costSummary.goodsRealAmount,
discountAmount: discountRateNumber.value,
productCouponDiscountAmount: goodsStore.cartInfo.costSummary.productCouponDeduction,
otherCouponDiscountAmount: goodsStore.cartInfo.costSummary.fullCouponDeduction,
orderAmount: goodsStore.cartInfo.costSummary.finalPayAmount, // 最终订单金额
roundAmount: 0,
pointsDiscountAmount: goodsStore.cartInfo.costSummary.pointDeductionAmount, //积分抵扣金额
pointsNum: goodsStore.cartInfo.costSummary.pointUsed,
discountActAmount: goodsStore.cartInfo.costSummary.fullReduction.actualAmount, // 满减活动金额
discountActId: goodsStore.cartInfo.costSummary.fullReduction.usedThreshold !== undefined ? goodsStore.cartInfo.costSummary.fullReduction.usedThreshold.activityId : '', // 满减活动id
couponList: couponResList1.value.map(item => item.id),
userId: goodsStore.vipUserInfo.userId || '',
allPack: goodsStore.allSelected,
limitRate: goodsStore.limitDiscountRes,
newCustomerDiscountId: goodsStore.newCustomerDiscount !== null ? goodsStore.newCustomerDiscount.id : '', // 新客立减Id
newCustomerDiscountAmount: goodsStore.newCustomerDiscount !== null ? goodsStore.newCustomerDiscount.amount : 0, // 新客立减金额
vipDiscountAmount: goodsStore.cartInfo.costSummary.vipDiscountAmount, // 超级会员折扣
}
}
// 结算支付
async function confirmOrder() {
try {
// 判断订单是否锁定
await goodsStore.isOrderLock({
table_code: goodsStore.orderListInfo.tableCode
})
if (payLoading.value) return
// await staffPermission("yun_xu_shou_kuan");
upadatePayData()
payType.value = payList.value[payActive.value].payType
if (payList.value[payActive.value].payType == "arrears") {
showBuyerHandle();
return
} else if (payList.value[payActive.value].payType == "scanCode") {
scanModalRef.value.show();
return
} else {
// if (money.value < props.amount) return
payLoading.value = true;
switch (payList.value[payActive.value].payType) {
case "deposit":
// 会员码支付
payLoading.value = false;
scanModalRef.value.show();
return;
case "cash":
//现金
if (props.selecttype == 0) {
payLoading.loading = true
await cashPay(payData.value);
}
break
case "member-account":
// 会员支付
payLoading.value = false;
if (goodsStore.vipUserInfo.id) {
await vipPayAjax(goodsStore.vipUserInfo)
} else {
SelectVipUserRef.value.show()
}
return;
default:
break;
}
payLoading.value = false;
emit("paySuccess");
}
} catch (error) {
console.log(error);
payLoading.value = false;
// if (error.code == 1003) {
// ElMessage.error(error.msg)
// return
// }
if (error.code == 701) {
// 订单已过期需刷新购物车和订单
emit('orderExpired')
}
scanModalRef.value.loading = false;
}
}
// 输入
function amountInput(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 {
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)
}
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) {
money.value = "0";
}
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;
}
/**
* 检查goodsStore.cartInfo.costSummary是否为真值的Promise
* @param {number} [interval=100] 轮询检查间隔(ms)
* @param {number} [timeout=5000] 超时时间(ms)超过则reject
* @returns {Promise} 当costSummary为真时resolve超时则reject
*/
function checkCostSummaryIsTruthy(interval = 100, timeout = 5000) {
return new Promise((resolve, reject) => {
// 记录开始时间,用于超时判断
const startTime = Date.now();
// 轮询检查函数
const check = () => {
const targetValue = goodsStore.cartInfo.costSummary;
// 检查是否为真值非null、undefined、0、''、false、NaN
if (targetValue) {
resolve(targetValue); // 成功时返回该值
return;
}
// 检查是否超时
if (Date.now() - startTime >= timeout) {
reject(new Error('检查超时costSummary始终为假值'));
return;
}
// 未满足条件且未超时,继续轮询
setTimeout(check, interval);
};
// 立即开始第一次检查
check();
});
}
// 获取支付方式
function queryPayTypeAjax() {
checkCostSummaryIsTruthy().then(async () => {
try {
const res = await getPayType();
res.map((item) => {
if (goodsStore.cartInfo.costSummary.finalPayAmount <= 0 && item.payType == "scanCode") {
item.disabled = true;
} else {
item.disabled = false;
}
});
payList.value = res.filter(item => item.isDisplay);
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);
}
})
}
/** 添加优惠 start */
const showCoupon = ref(false)
const couponFormRef = ref(null)
const couponFormUser = ref('')
const couponFormUserList = ref([])
const couponFormDiscountRate = ref(10)
const couponResType = ref('')
const couponResList1 = ref([])
const couponResList2 = ref([])
const pointOptions = ref({
min: 0,
max: 0,
minPaymentAmount: 0,
usable: true,
unusableReason: '',
amount: 0,
equivalentPoints: '',
loading: false
})
const couponForm = ref({
originAmount: 0,
discountRatio: "",
pointsNum: '',
amount: '',
coupon: '',
productCouponDiscountAmount: 0,
fullCouponDiscountAmount: 0,
couponList: []
})
const resetCouponForm = ref('')
// 清除已选择的用户
function clearCouponUser() {
couponFormUser.value = ''
couponFormUserList.value = []
goodsStore.clearVipUserInfo()
couponForm.value.pointsNum = ''
couponForm.value.discountRatio = ''
discountRateNumber.value = 0
couponResList1.value = []
updateCartCalc()
// resetCouponFormHandle()
}
// 折扣格式化
const discountRateNumber = ref(0)
const discountInput = _.debounce(function (e) {
// 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) {
discountRateNumber.value = formatDecimal(goodsStore.cartInfo.costSummary.finalPayAmount - goodsStore.cartInfo.costSummary.finalPayAmount * (couponForm.value.discountRatio / couponFormDiscountRate.value))
} else {
discountRateNumber.value = formatDecimal(goodsStore.cartInfo.costSummary.finalPayAmount - goodsStore.cartInfo.costSummary.finalPayAmount)
}
updateCartCalc()
// // 将优惠券/积分所有设置初始化
// couponResList1.value = []
// couponResList2.value = []
// couponForm.value.pointsNum = ''
// pointOptions.value.amount = 0
}, 500)
// 取消所有优惠
function cancelAllDiscount() {
showCoupon.value = false
couponForm.value.pointsNum = ''
couponResList1.value = []
couponForm.value.discountRatio = ''
discountRateNumber.value = ''
updateCartCalc()
}
// 同意更新商品计算
function updateCartCalc() {
goodsStore.calcCartInfo({
pointsPerYuan: pointOptions.value.equivalentPoints,
maxDeductionAmount: pointOptions.value.max,
userPoints: couponForm.value.pointsNum,
backendCoupons: couponResList1.value,
fixedAmount: discountRateNumber.value
})
}
// 清除积分
function clearPoint() {
if (couponForm.value.pointsNum > 0) {
couponForm.value.pointsNum = ''
couponForm.value.amount = +couponForm.value.amount + +pointOptions.value.amount
pointOptions.value.amount = 0
}
updateCartCalc()
}
// 积分输入格式化
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()
}
updateCartCalc()
}, 500)
// 根据积分计算可抵扣金额
const calcPointMoney = async () => {
try {
const res = await calcDeductionAmount({
shopUserId: goodsStore.vipUserInfo.id,
orderAmount: goodsStore.cartInfo.costSummary.finalPayAmount,
points: couponForm.value.pointsNum
})
pointOptions.value.amount = formatDecimal(+res)
couponForm.value.amount = couponForm.value.amount - res
updateCartCalc()
} catch (error) {
console.log(error);
}
pointOptions.value.loading = false
}
// 当dialog打开时
function couponDialogOpen() {
// couponResList2Amount.value = 0
// couponForm.value.discountRatio = ''
// // 需减去抹零金额
// couponForm.value.amount = formatDecimal(originOrderAmount.value - roundAmount.value)
// couponForm.value.originAmount = couponForm.value.amount
// resetCouponForm.value = { ...couponForm.value }
// couponResList1.value = []
// couponResList2.value = []
// 当购物车已存在用户时
if (goodsStore.vipUserInfo.id) {
couponFormUserList.value = [
{
id: goodsStore.vipUserInfo.userId,
nickName: goodsStore.vipUserInfo.nickName,
}
]
couponFormUser.value = goodsStore.vipUserInfo
pointOptionsAjax()
} else {
couponFormUserList.value = []
couponFormUser.value = ''
}
}
// 关闭后初始化dialog
function resetCouponFormHandle() {
couponForm.value = { ...resetCouponForm.value }
couponForm.value.pointsNum = ''
couponForm.value.discountRatio = ''
discountRateNumber.value = 0
// clearCouponUser()
cancelAllDiscount()
}
// 选择会员完成后
async function selectUserHandle(row) {
try {
console.log('selectUserHandle===', row);
goodsStore.selectUser(row)
// 选择会员后重新计算会员价
if (store.shopInfo.isMemberPrice && row.isVip) {
console.log('选择会员后重新计算会员价===', row);
goodsStore.showVipPrice = 1
} else {
goodsStore.showVipPrice = 0
}
couponResList1.value = []
goodsStore.calcCartInfo()
// emit('reset')
// couponForm.value.discountRatio = ''
// discountInput('')
if (showCoupon.value) {
setTimeout(() => {
couponDialogOpen()
}, 100)
couponFormUserList.value = [
{
id: row.userId,
nickName: row.nickName,
}
]
couponFormUser.value = row
pointOptionsAjax()
// 已存在选择的用户,并且切换了不通用户
if (couponFormUser.id && row.userId != couponFormUser.value.userId) {
resetCoupon()
}
} else {
if (payList.value[payActive.value].payType == 'member-account') {
setTimeout(() => {
vipPayAjax(row)
}, 500)
}
}
} catch (error) {
console.log(error);
}
}
// 重选用户后重置优惠券和积分,并重新计算价格
function resetCoupon() {
couponResList1.value = []
couponResList2.value = []
couponForm.value.amount = originOrderAmount.value
}
// 选择完用户后开始获取积分使用配置
async function pointOptionsAjax() {
try {
const res = await calcUsablePoints({
shopUserId: goodsStore.vipUserInfo.id,
orderAmount: goodsStore.cartInfo.costSummary.finalPayAmount
})
pointOptions.value.min = res.minDeductionPoints // 最少使用积分
pointOptions.value.max = res.maxUsablePoints // 最大使用积分
pointOptions.value.usable = res.usable // 是否可用
pointOptions.value.unusableReason = res.unusableReason // 不可用的原因
pointOptions.value.minPaymentAmount = res.minPaymentAmount // 最少使用的金额
pointOptions.value.equivalentPoints = res.equivalentPoints
} catch (error) {
console.log(error);
}
}
// 显示添加优惠
function showCouponHandle() {
showCoupon.value = true
}
// 显示选择优惠券
function showCounponModalHandle() {
CouponModalRef.value.show(couponFormUser.value.id)
}
const couponResList2Amount = ref(0)
// 选择完优惠券的回调事件
function CouponModalSuccess(res) {
couponResList1.value = res
updateCartCalc()
// 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
// }
// couponResList1.value = res.couponList
// couponForm.value.fullCouponDiscountAmount = res.couponList[0].discountAmount
// }
// 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
// }
}
// 多个优惠券抵扣多个商品,优先已价格最低的抵扣
const applyCoupons = (orders, coupons) => {
// 遍历每张优惠券
coupons.forEach(coupon => {
// 筛选出订单列表中与当前优惠券 product_id 相同的商品
const eligibleProducts = orders.filter(order => order.product_id == coupon.proId);
// 对筛选出的商品按价格从小到大排序
eligibleProducts.sort((a, b) => a.price - b.price);
let couponUsed = false; // 用于标记优惠券是否已使用
// 依次使用优惠券抵扣价格最低的商品
eligibleProducts.forEach(product => {
if (!couponUsed && !product.isCoupon) {
product.isCoupon = true;
product.discount = coupon.discount
couponUsed = true; // 标记优惠券已使用
}
});
});
return orders;
};
// 删除优惠券
function delCoupon(index, t) {
if (t == 1) {
couponForm.value.amount = +couponForm.value.amount + +couponResList1.value[index].discountAmount
couponResList1.value.splice(index, 1)
} else {
// 恢复这个券的价格
const price = props.orderList.find(item => item.product_id == couponResList2.value[index].proId).price
couponForm.value.amount = +couponForm.value.amount + +price
couponResList2.value.splice(index, 1)
}
updateCartCalc()
console.log(couponForm.value.amount);
}
// 确认优惠
function discountConfirm() {
// 确认折扣
discountRateVlaue.value = couponForm.value.discountRatio || ''
// 计算折扣金额
if (couponForm.value.discountRatio) {
let rate = couponForm.value.discountRatio / couponFormDiscountRate.value
let discount = formatDecimal(couponForm.value.originAmount * rate)
payData.value.checkOrderPay.discountAmount = formatDecimal(couponForm.value.originAmount - discount)
} else {
payData.value.checkOrderPay.discountAmount = 0
}
if (couponFormUser.value.id) {
payData.value.checkOrderPay.userId = couponFormUser.value.userId
// 确认积分
payData.value.checkOrderPay.pointsNum = couponForm.value.pointsNum
payData.value.checkOrderPay.pointsDiscountAmount = pointOptions.value.amount
payData.value.checkOrderPay.productCouponDiscountAmount = couponForm.value.productCouponDiscountAmount
}
payData.value.checkOrderPay.orderAmount = couponForm.value.amount
// 优惠完之后加上餐位费
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 */
// 初始化
async function payCardInit() {
console.log('payCardInit111111==============================', goodsStore.orderListInfo);
// const maxRetries = 10;
// let retries = 0;
// const waitForOrderId = async () => {
// while (retries < maxRetries && !goodsStore.orderListInfo.id) {
// await new Promise(resolve => setTimeout(resolve, 200));
// retries++;
// }
// return goodsStore.orderListInfo.id;
// };
// const orderId = await waitForOrderId();
// if (!orderId) {
// console.error('无法获取订单 ID');
// return;
// }
discountAmount.value = null
roundAmount.value = 0
discountRateVlaue.value = 0
money.value = `${formatDecimal(goodsStore.cartInfo.costSummary.finalPayAmount)}`;
originOrderAmount.value = formatDecimal(props.amount - (goodsStore.tableInfo.tableFee || 0) -
(goodsStore.cartInfo.packFee || 0))
payData.value = {
shopId: store.shopInfo.id,
buyerRemark: "", // 订单备注
checkOrderPay: {
// orderId: goodsStore.orderListInfo.id,
// vipPrice: store.shopInfo.isMemberPrice ? goodsStore.showVipPrice : 0, // 是否使用会员价
// allPack: goodsStore.allSelected, // 是否整单打包
// userId: goodsStore.vipUserInfo.userId || '',
// seatNum: goodsStore.tableInfo.num, // 用餐人数
// originAmount: formatDecimal(+goodsStore.cartInfo.totalAmount), // 订单原金额(包含打包费+餐位费) 不含折扣价格
// discountRatio: '', // 折扣比例(计算时 向上取整保留 两位小数)
// discountAmount: 0, // 手动优惠金额
// productCouponDiscountAmount: 0, // 商品优惠券抵扣金额
// fullCouponDiscountAmount: 0, // 满减优惠券抵扣金额
// couponList: [], // 用户使用的卡券
// orderAmount: formatDecimal(+goodsStore.cartInfo.totalAmount), // 订单金额
// roundAmount: 0, // 抹零金额 减免多少钱
// pointsDiscountAmount: 0, // 积分抵扣金额(tb_points_basic_setting表)
// pointsNum: 0, // 使用的积分数量 (扣除各类折扣 enable_deduction后使用)
// isPrint: 1
},
};
console.log('payData================================', payData.value);
if (!payList.value.length) {
queryPayTypeAjax()
}
}
defineExpose({
payCardInit,
resetCouponFormHandle
})
</script>
<style scoped lang="scss">
.point_tips {
&.err {
color: var(--el-color-danger);
}
}
.card {
padding: var(--el-font-size-base);
height: 100%;
}
.header {
padding-bottom: var(--el-font-size-base);
border-bottom: 1px solid #ececec;
display: flex;
.left {
flex: 1;
.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;
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 {
display: flex;
align-items: center;
}
}
}
}
.number_wrap {
padding: var(--el-font-size-base) 0;
.menus {
display: flex;
gap: var(--el-font-size-base);
.item {
height: 130px;
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background-color: #efefef;
padding: 10px 0;
border-radius: 10px;
position: relative;
$lineHeight: 4px;
&.disabled {
filter: grayscale(1);
}
&.active {
&::after {
content: "";
width: 50%;
height: $lineHeight;
background-color: var(--primary-color);
position: absolute;
bottom: 0;
left: 25%;
border-radius: $lineHeight;
}
}
.img {
$size: 40px;
width: $size;
height: $size;
}
.title {
padding-top: 10px;
}
}
}
.input_wrap {
display: flex;
gap: var(--el-font-size-base);
padding: var(--el-font-size-base) 0;
.input {
display: flex;
align-items: center;
height: 60px;
border-radius: 6px;
border: 1px solid var(--primary-color);
font-size: calc(var(--el-font-size-base) + 6px);
padding: 0 var(--el-font-size-base);
}
}
.blance {
color: var(--el-color-danger);
font-size: calc(var(--el-font-size-base) + 10px);
}
}
.keybord_wrap {
display: flex;
.left {
--item-height: calc((100vh - 440px) / 4);
flex: 1;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: var(--item-height) var(--item-height) var(--item-height) var(--item-height);
gap: var(--el-font-size-base);
.item {
background-color: #efefef;
display: flex;
align-items: center;
justify-content: center;
border-radius: 6px;
font-size: calc(var(--el-font-size-base) + 10px);
&:active {
background-color: #dbdbdb;
}
}
}
.pay_btn {
flex: 0.3;
border-radius: 6px;
color: #fff;
background-color: var(--el-color-warning);
margin-left: var(--el-font-size-base);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(var(--el-font-size-base) + 10px);
}
}
.coupom_dialog {
height: 60vh;
overflow-y: auto;
.title {
font-size: 16px;
}
.flex {
display: flex;
align-items: center;
width: 100%;
gap: 10px;
.select_wrap {
flex: 1;
display: flex;
align-items: center;
}
}
.res {
display: flex;
align-items: center;
.i {
font-size: 14px;
position: relative;
top: 4px;
}
.n {
font-size: 24px;
font-weight: bold;
}
}
}
.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>