Files
cashier-web/src/views/tool/Instead/components/order.vue

902 lines
30 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="order-box">
<div class="left">
<div class="user bg-fff u-p-20">
<div class="userinfo" v-if="carts.vipUser.id" @click="chooseUser">
<el-avatar :src="carts.vipUser.headImg" class="avatar" :size="50" />
<div class="u-m-l-12">
<p>
<span class="name u-font-16">{{ carts.vipUser.nickName }}</span>
<span class="vip" v-if="carts.vipUser.isVip">
VIP{{ carts.vipUser.memberLevelName }}
</span>
</p>
<p class="u-font-14 color-666 u-m-t-10">
<span class="money">余额{{ carts.vipUser.amount }}</span>
<span class="score u-m-l-10">积分{{ carts.vipUser.pointBalance }}</span>
</p>
</div>
</div>
<div class="userinfo" v-else @click="chooseUser">
<el-avatar class="avatar" :size="50" />
<div class="u-m-l-12 no-wrap">
<p>
<span class="name u-font-16">服务员下单</span>
</p>
<p class="u-font-14 color-666 u-m-t-10">
<span class="money">余额</span>
<span class="score u-m-l-10">积分</span>
</p>
</div>
</div>
<template v-if="carts.vipUser.id">
<div class="score">
<div class="u-flex u-col-center u-m-t-10">
<span class="u-font-14 font-bold u-m-r-20">积分抵扣</span>
<el-radio-group v-model="score.sel" size="small" class="">
<el-radio :value="-1">
<span class="u-font-14">不使用</span>
</el-radio>
<el-radio :value="0" :disabled="!pointsRes.usable">
<span class="u-font-14">使用</span>
</el-radio>
<!-- <el-radio :value="1" :disabled="!pointsRes.usable">
<span class="u-font-14">部分抵扣</span>
</el-radio> -->
</el-radio-group>
<el-input-number class="u-m-l-10" v-if="score.sel != -1" v-model="usePointsNumber" step-strictly
:step="pointsRes.equivalentPoints" placeholder="请输入积分抵扣数量" :min="pointsRes.minDeductionPoints"
:max="pointsRes.maxUsablePoints" :disabled="!pointsRes.usable"
@change="pointsToMoney"></el-input-number>
</div>
<p class="u-font-14 color-666 u-m-t-10" v-if="pointsRes.unusableReason && !pointsRes.usable">
<span class="color-red">*</span>
<span>{{ pointsRes.unusableReason }}</span>
</p>
<p class="u-font-14 color-666 u-m-t-10" v-else>
<span class="color-red">*</span>
<span>{{ pointsRes.equivalentPoints }}积分等于1元</span>
</p>
</div>
<div class="u-flex u-col-center u-m-t-20 no-wrap">
<span class="u-font-14 font-bold u-m-r-20">团购代金券</span>
<div class="u-flex my-select">
<span class="u-m-r-10">代金券名称</span>
<el-icon>
<ArrowDown />
</el-icon>
</div>
<svg-icon iconClass="scan" size="30" class="u-m-l-10 cur-pointer"></svg-icon>
</div>
<div class="u-flex u-col-center u-m-t-20 no-wrap">
<span class="u-font-14 font-bold u-m-r-20">优惠券</span>
<div v-if="
carts.orderCostSummary.fullReduction !== undefined &&
carts.orderCostSummary.fullReduction.actualAmount > 0
" style="font-size: 14px; color: #555">
参与满减活动不可用优惠券!
</div>
<div class="u-flex my-select" @click="openCoupon" v-else>
<span class="u-m-r-10">选择优惠券</span>
<el-icon>
<ArrowDown />
</el-icon>
</div>
</div>
<div class="u-m-t-20" v-if="quansSelArr.length > 0">
<div class="font-bold u-m-b-10">已选优惠券</div>
<el-table empty-text="未选择优惠券" :data="quansSelArr">
<el-table-column type="index" width="50" label="#"></el-table-column>
<el-table-column prop="name" label="券名称"></el-table-column>
<el-table-column label="券类型" width="80">
<template v-slot="scope">
{{ UTILS.returnCoupType(scope.row) }}
</template>
</el-table-column>
<el-table-column label="商品信息">
<template v-slot="scope">
<div>
{{ scope.row.foods }}
</div>
</template>
</el-table-column>
<el-table-column prop="discountAmount" label="抵扣">
<template v-slot="scope">
<span class="color-red">¥{{ scope.row.discountAmount }}</span>
</template>
</el-table-column>
<el-table-column prop="useRestrictions" label="操作">
<template v-slot="scope">
<el-button type="danger" size="small" @click="delQuan(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
</template>
</div>
<div class="u-m-t-30">
<el-button size="large" @click="discountShow">
{{ checkOrderPay.discount ? checkOrderPay.discount / 10 + "折" : "整单打折/减免" }}
</el-button>
</div>
<div class="u-m-t-30">
<p class="u-font-16 font-bold u-m-r-20 font-bold u-flex">选择支付方式</p>
<div class="u-m-t-20">
<div>
<el-button v-for="(item, index) in payTypes.list" :key="index" size="large"
:type="index == payTypes.sel ? 'primary' : ''" :disabled="canUsePayType(item)"
@click="changePayType(index)">
{{ item.payName }}
</el-button>
</div>
</div>
<div class="u-m-t-20">
<el-button type="primary" size="large" @click="nowPayClick()">立即支付</el-button>
</div>
</div>
</div>
<div class="right">
<h3>账单明细</h3>
<!-- <p class="u-font-12 u-m-b-20">
<span class="color-red">*</span>
<span class="color-red">餐位费和打包费不参与折扣和满减</span>
</p> -->
<div class="order-info">
<div class="u-flex u-m-b-10 u-row-between">
<span class="title">订单号:</span>
<span class="u-m-l-10 value">{{ orderInfo.orderNo }}</span>
</div>
<div class="u-flex u-m-b-10 u-row-between">
<span class="title">餐位费</span>
<span class="u-m-l-10 value">¥{{ carts.orderCostSummary.seatFee }}</span>
</div>
<div class="u-flex u-m-b-10 u-row-between">
<span class="title">打包费</span>
<span class="u-m-l-10 value">¥{{ carts.orderCostSummary.packFee }}</span>
</div>
<div class="u-flex u-m-b-10 u-row-between">
<span class="title">商品订单金额</span>
<span class="u-m-l-10 value">
¥{{
carts.orderCostSummary.goodsOriginalAmount -
carts.orderCostSummary.goodsDiscountAmount
}}
</span>
</div>
<div class="u-flex u-m-b-10 u-row-between">
<span class="title">满减活动</span>
<span class="u-m-l-10 value">
-¥{{ carts.orderCostSummary.fullReduction.actualAmount }}
</span>
</div>
<div class="u-flex u-m-b-10 u-row-between">
<span class="title">新客立减</span>
<span class="u-m-l-10 value">-¥{{ carts.orderCostSummary.newUserDiscount }}</span>
</div>
<div class="u-flex u-m-b-10 u-row-between">
<span class="title">商品优惠券</span>
<span class="u-m-l-10 value">-¥{{ productCouponDiscountAmount }}</span>
</div>
<div class="u-flex u-m-b-10 u-row-between">
<span class="title">会员折扣</span>
<span class="u-m-l-10 value">-¥{{ carts.orderCostSummary.vipDiscountAmount }}</span>
</div>
<div class="u-flex u-m-b-10 u-row-between">
<span class="title">其他优惠券</span>
<span class="u-m-l-10 value">-¥{{ fullCouponDiscountAmount }}</span>
</div>
<div class="u-flex u-m-b-10 u-row-between">
<span class="title">整单改价</span>
<span class="u-m-l-10 value color-red">
-¥{{ carts.orderCostSummary.merchantReduction.actualAmount }}
</span>
</div>
<div class="u-flex u-m-b-10 u-row-between">
<span class="title">积分抵扣</span>
<span class="u-m-l-10 value">-¥{{ carts.orderCostSummary.pointDeductionAmount }}</span>
</div>
<div class="u-flex u-m-b-10 u-row-between">
<span class="title">抹零</span>
<span class="u-m-l-10 value">-¥{{ 0 }}</span>
</div>
<div class="u-flex u-m-b-10 u-row-between">
<span class="title">总价(商品订单金额-商品优惠券-满减券-整单改价-积分抵扣)</span>
<span class="u-m-l-10 value color-red">¥{{ totalPrice }}</span>
</div>
<div class="u-flex u-m-b-10 u-row-between">
<span class="title">应付金额(总价+客座费+打包费)</span>
<span class="u-m-l-10 value price">¥{{ carts.orderCostSummary.finalPayAmount }}</span>
</div>
</div>
</div>
<!-- 扫码 -->
<scanPay ref="refScanPay" :order="orderInfo" @confirm="refScanPayConfirm" @paysuccess="paysuccess"></scanPay>
<!-- 打折 -->
<discount ref="refDiscount" @confirm="discountConfirm"></discount>
<!-- 优惠券 -->
<popup-coupon ref="refCoupon" :user="carts.vipUser" @confirm="refCouponConfirm"></popup-coupon>
<!-- 挂账 -->
<chooseGuaZahng ref="refGuaZhang" :payMoney="currentpayMoney" @confirm="refGuaZhangConfirm"></chooseGuaZahng>
</div>
</template>
<script setup>
import * as UTILS from "@/utils/coupon-utils.js";
import * as quanUtil from "../quan_util.js";
import { OrderPriceCalculator } from "@/utils/goods";
import { useCartsStore } from "@/store/modules/carts";
import { useUserStore } from "@/store/modules/user";
import chooseGuaZahng from "./popup-choose-guazhang.vue";
const shopUser = useUserStore();
const carts = useCartsStore();
import popupCoupon from "./popup-coupon.vue";
import PointsApi from "@/api/account/points";
import limitTimeDiscountApi from "@/api/market/limitTimeDiscount.js";
import payTypeApi from "@/api/account/payType";
import payApi from "@/api/order/pay";
import scanPay from "./scan-pay.vue";
import discount from "./discount.vue";
import { ElLoading } from "element-plus";
import { ElMessage, ElMessageBox } from "element-plus";
import { BigNumber } from "bignumber.js";
// 配置BigNumber精度
BigNumber.set({
DECIMAL_PLACES: 2,
ROUNDING_MODE: BigNumber.ROUND_DOWN, // 向下取整,符合业务需求
});
//挂账
const refGuaZhang = ref();
function refGuaZhangConfirm(guazhangRen) {
payOrder("arrears", true, guazhangRen);
}
function refGuaZhangShow() {
refGuaZhang.value.open();
}
const refCoupon = ref();
let quansSelArr = ref([]);
function openCoupon() {
//商品订单金额
const price = carts.orderCostSummary.goodsRealAmount;
refCoupon.value.open(price, props.orderInfo);
}
function refCouponConfirm(e, goodsList) {
e = e.map((v) => {
return {
...v,
couponType: v.type,
title: v.name,
};
});
console.log("refCouponConfirm", e);
carts.setCoupons(e);
quansSelArr.value = e;
checkOrderPay.discountAmount = 0;
checkOrderPay.discount = 0;
}
function delQuan(row) {
const index = quansSelArr.value.findIndex((v) => v.id == row.id);
if (index != -1) {
quansSelArr.value.splice(index, 1);
}
carts.setCoupons(quansSelArr.value);
}
//打折
const refDiscount = ref();
const checkOrderPay = reactive({
discountAmount: 0, //手动优惠金额
discount: 0,
});
function discountConfirm(e) {
console.log(e);
Object.assign(checkOrderPay, e);
if (e.discount) {
carts.setMerchantDiscountReduction(e.discount);
} else {
carts.setMerchantFixedReduction(e.discountAmount);
checkOrderPay.discount = 0;
}
score.sel = -1;
usePointsNumber.value = 0;
}
// 计算商家减免前金额使用bignumber.js确保精度
function returnMerchantReductionDiscount() {
const {
fullReduction, //满减活动
goodsOriginalAmount, // 商品原价总和
goodsDiscountAmount, // 商品折扣
couponDeductionAmount, // 优惠券抵扣
pointDeductionAmount, // 积分抵扣
seatFee, // 餐位费(不参与减免)
packFee, // 打包费(不参与减免)
additionalFee,
} = carts.orderCostSummary;
// 将所有金额转换为BigNumber实例
const originalAmount = new BigNumber(goodsOriginalAmount);
const discountAmount = new BigNumber(goodsDiscountAmount);
const couponAmount = new BigNumber(couponDeductionAmount);
const pointAmount = new BigNumber(pointDeductionAmount);
const seat = new BigNumber(seatFee);
const pack = new BigNumber(packFee);
const additional = new BigNumber(additionalFee);
const vipDiscountAmount = new BigNumber(carts.orderCostSummary.vipDiscountAmount);
// 按照原逻辑进行精确计算
const total = originalAmount
.minus(fullReduction.actualAmount) // 减去满减活动抵扣金额
.minus(discountAmount) // 减去商品折扣
.minus(couponAmount) // 减去优惠券抵扣
.minus(pointAmount) // 减去积分抵扣
.minus(vipDiscountAmount) // 减去会员折扣
.plus(seat) // 加上餐位费
.plus(pack) // 加上打包费
.plus(additional); // 加上附加费
// 确保结果不小于0返回数字类型
return total.lte(0) ? 0 : total.toNumber();
}
function discountShow(e) {
refDiscount.value.open({
// amount: carts.goodsTotal - productCouponDiscountAmount.value,
amount: returnMerchantReductionDiscount(),
});
}
const props = defineProps({
table: {
type: Object,
default: () => { },
},
user: {
type: Object,
default: () => {
return { id: "" };
},
},
perpole: {
type: [Number, String],
default: 0,
},
orderInfo: {
type: Object,
default: () => { },
},
});
watch(
() => props.user.id,
(newval) => {
quansSelArr.value = [];
checkOrderPay.discountAmount = 0;
checkOrderPay.discount = 0;
score.sel = -1;
usePointsNumber.value = 0;
if (newval !== "") {
pointsInit();
}
}
);
watch(
() => props.orderInfo.id,
(newval) => {
if (newval !== "") {
pointsInit();
}
}
);
//002-获取订单可用积分及抵扣金额(支付页面使用)
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 (
carts.orderCostSummary.finalPayAmount +
carts.orderCostSummary.pointDeductionAmount -
carts.orderCostSummary.merchantReduction.actualAmount
);
});
watch(
() => scoreMaxMoney.value,
(newval, oldval) => {
if (newval != oldval) {
pointsInit();
}
}
);
async function pointsInit() {
if (!carts.vipUser.id) {
return;
}
const { pointsConfig, pointsUser } = await PointsApi.calcOrderUsablePoints({
shopUserId: carts.vipUser.id,
});
// 不修改 accountPoints为余额将积分保存到 pointBalance 字段
carts.vipUser.pointBalance = pointsUser && pointsUser.id ? pointsUser.pointBalance : 0;
// 保险取值
const eq = pointsConfig?.equivalentPoints || 0;
const rawMaxRatio = pointsConfig?.maxDeductionRatio || 0;
// 兼容后端返回的百分比或小数两种形式如果大于1则视为百分比如100表示100%需除以100
const maxRatio = rawMaxRatio > 1 ? rawMaxRatio / 100 : rawMaxRatio;
const minPay = pointsConfig?.minPaymentAmount || 0;
// 计算当前订单可抵扣金额上限(元)
// 使用“抵扣前实付金额”作为门槛判断(即把当前已应用的积分抵扣金额加回),
// 避免在已经抵扣导致 finalPay 变小后错误地判定为不可用。
let finalPay = Number(carts.orderCostSummary.finalPayAmount) || 0;
const currentPointDeduction = Number(carts.orderCostSummary.pointDeductionAmount) || 0;
const basePay = finalPay + currentPointDeduction;
const res = {
usable: true,
equivalentPoints: eq,
maxDeductionRatio: maxRatio,
minPaymentAmount: minPay,
maxUsablePoints: 0,
minDeductionPoints: pointsConfig?.minDeductionPoints || eq,
unusableReason: "",
};
// 如果订单实付低于最小使用门槛,则不可用(门槛仅作为启用条件)
// 这里使用 basePay抵扣前实付进行判断确保已填写积分后不会回退为不可用
if (basePay <= 0 || (minPay > 0 && basePay < minPay)) {
res.usable = false;
res.unusableReason = `订单实付金额低于 ${minPay} 元,无法使用积分抵扣`;
} else if (eq <= 0) {
res.usable = false;
res.unusableReason = `积分换算比例配置错误,无法使用积分抵扣`;
} else {
// 计算基于比例限制的最大抵扣金额(元)
// 注意:此处不再减少 minPaymentAmountminPaymentAmount 仅用作是否可用的门槛;
// 真正的最大抵扣由 maxRatio抵扣比例与用户积分数量共同决定。
// 计算基于比例限制的最大抵扣金额(元),基于抵扣前实付金额
let maxByRatio = basePay * maxRatio;
if (res.usable) {
// 可用积分上限(按等价积分步长对齐到 eq 的倍数)
const maxByMoney = Math.floor(maxByRatio * eq);
const userPoints = carts.vipUser.pointBalance || 0;
let computedMax = Math.min(userPoints, maxByMoney);
// 对齐到等价积分步长,保证输入步长生效
if (eq > 0) {
computedMax = Math.floor(computedMax / eq) * eq;
}
res.maxUsablePoints = computedMax;
console.debug("pointsInit debug:", { finalPay: finalPay, basePay: basePay, eq, rawMaxRatio, maxRatio, maxByMoney, userPoints, computedMax });
// 最小抵扣积分为配置值或等于换算比
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;
}
// 如果可用则默认填充可用最大值(对齐步长),否则清零
if (res.usable) {
// 计算默认填充值:基于抵扣前实付的比例上限与等价比计算需要的积分数
const defaultMaxByMoney = Math.floor(basePay * res.maxDeductionRatio * res.equivalentPoints);
let defaultPts = Math.min(res.maxUsablePoints || 0, defaultMaxByMoney || 0);
if (res.equivalentPoints > 0) {
defaultPts = Math.floor(defaultPts / res.equivalentPoints) * res.equivalentPoints;
}
// 最终确保不超过用户积分
const userPts = carts.vipUser.pointBalance || 0;
usePointsNumber.value = Math.min(defaultPts, userPts);
} else {
usePointsNumber.value = 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;
}
// 确保为整数积分
let pts = parseInt(usePointsNumber.value || 0, 10);
if (isNaN(pts) || pts <= 0) {
pts = 0;
}
// 限制最大值
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 && finalPay < cfg.minPaymentAmount) {
usePointsNumber.value = 0;
carts.orderCostSummary.pointUsed = 0;
carts.orderCostSummary.pointDeductionAmount = 0;
return;
}
const maxAllowedMoney = new BigNumber(maxByRatio).decimalPlaces(2, BigNumber.ROUND_DOWN).toNumber();
console.debug("pointsToMoney debug:", { finalPay, cfg, pts, money, maxByRatio, maxAllowedMoney });
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"]);
function chooseUser() {
emits("chooseUser");
}
const score = reactive({
list: [],
sel: -1,
});
const payTypes = reactive({
list: [],
sel: 0,
});
watch(
() => score.sel,
(newval) => {
console.log(newval);
usePointsNumber.value = 0;
pointsInit();
}
);
watch(
() => usePointsNumber.value,
(newval) => {
carts.userPoints = newval;
}
);
function canUsePayType(item) {
if (currentpayMoney.value * 1 == 0) {
return item.payType == "cash" ? false : true;
}
// if (item.payType == "virtual" && item.payName == "会员支付") {
// return props.user.id ? false : true;
// }
return false;
}
const refScanPay = ref();
function changePayType(i) {
const payType = payTypes.list[i].payType;
payTypes.sel = i;
if (payType == "member-account") {
return chooseUser();
}
refScanPayOpen(payType);
}
function returnPayParams() {
console.log("carts.orderCostSummary", carts.orderCostSummary);
return {
money: currentpayMoney.value * 1,
shopId: localStorage.getItem("shopId"),
authCode: authCode,
checkOrderPay: {
vipPrice: shopUser.userInfo.isMemberPrice && carts.vipUser.id && carts.vipUser.isVip ? 1 : 0,
orderId: props.orderInfo.id,
// discountRatio: (checkOrderPay.discount / 100).toFixed(2),
discountRatio: 0,
seatNum: carts.dinnerType == "dine-in" ? props.perpole * 1 : 0,
originAmount: carts.orderCostSummary.goodsRealAmount,
discountAmount: discountAmount.value,
productCouponDiscountAmount: carts.orderCostSummary.productCouponDeduction,
otherCouponDiscountAmount: carts.orderCostSummary.fullCouponDeduction,
orderAmount: carts.orderCostSummary.finalPayAmount, // 最终订单金额
roundAmount: props.orderInfo.roundAmount,
pointsDiscountAmount: carts.orderCostSummary.pointDeductionAmount, //积分抵扣金额
pointsNum: carts.orderCostSummary.pointUsed,
discountActAmount: carts.orderCostSummary.fullReduction.actualAmount, // 满减活动金额
discountActId:
carts.orderCostSummary.fullReduction.usedThreshold !== undefined
? carts.orderCostSummary.fullReduction.usedThreshold.activityId
: "", // 满减活动id
couponList: carts.coupons.map((v) => v.id),
userId: carts.vipUser.userId || "",
allPack: carts.dinnerType == "take-out" ? 1 : 0,
limitRate: carts.limitDiscountRes,
newCustomerDiscountId: carts.newUserDiscount !== null ? carts.newUserDiscount.id : "", // 新客立减Id
newCustomerDiscountAmount:
carts.newUserDiscount !== null ? carts.newUserDiscount.amount : 0, // 新客立减金额
vipDiscountAmount: carts.orderCostSummary.vipDiscountAmount, // 超级会员折扣
},
};
}
function refScanPayOpen(payType) {
if (payType == "member-account") {
chooseUser();
return;
}
if (payType == "deposit") {
return refScanPay.value.open(returnPayParams(), "deposit");
}
if (payType == "scanCode") {
return refScanPay.value.open(returnPayParams(), "scanCode");
}
if (payType == "arrears") {
refGuaZhangShow();
return;
}
}
async function getPaytype() {
const res = await payTypeApi.getList();
payTypes.list = res.filter((v) => v.isDisplay);
if (currentpayMoney.value * 1 <= 0) {
payTypes.sel = payTypes.list.findIndex((v) => v.payType == "cash");
}
}
function nowPayClick(payType) {
payType = payType || payTypes.list[payTypes.sel].payType;
if (payType === "cash") {
ElMessageBox.confirm("是否确认已现金收款:" + currentpayMoney.value + "元", "快捷支付", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(() => {
payOrder("cash");
})
.catch(() => { });
return;
}
if (payType == "member-account") {
if (!carts.vipUser.id) {
return ElMessage.error("请先选择会员");
}
payOrder(payType);
return;
}
refScanPayOpen(payType);
}
let authCode = "";
function refScanPayConfirm($authCode, isScan) {
const payType = payTypes.list[payTypes.sel].payType;
authCode = $authCode;
payOrder(payType, isScan);
}
let payTimer = null;
//是否是正扫
async function payOrder(payType, isScan, guazhangren) {
clearTimeout(payTimer);
const loading = ElLoading.service({
lock: true,
text: "支付中,请稍等……",
background: "rgba(0, 0, 0, 0.7)",
});
payTimer = setTimeout(() => {
ElMessage.error("支付超时");
loading.close();
}, 1000 * 20);
let res = undefined;
console.log(payType);
try {
if (payType == "scanCode") {
res = isScan
? await payApi.scanPay(returnPayParams())
: await payApi.microPay(returnPayParams());
}
if (payType == "cash") {
res = await payApi.cashPay(returnPayParams());
}
if (payType == "deposit") {
res = await payApi.vipPay({ ...returnPayParams(), payType: "scanCode" });
}
if (payType == "member-account") {
res = await payApi.vipPay({
...returnPayParams(),
payType: "userPay",
shopUserId: carts.vipUser.id,
});
}
if (payType == "arrears") {
res = await payApi.creditPay({ ...returnPayParams(), creditBuyerId: guazhangren.id });
}
carts.clear();
} catch (error) {
console.log(error);
clearTimeout(payTimer);
loading.close();
}
if (res) {
loading.close();
paysuccess();
}
}
function paysuccess() {
clearTimeout(payTimer);
ElMessage.success("支付成功");
emits("paysuccess");
}
//整单改价
const discountAmount = computed(() => {
const money = carts.goodsTotal - productCouponDiscountAmount.value;
if (checkOrderPay.discount) {
return ((money * (100 - checkOrderPay.discount)) / 100).toFixed(2);
}
return checkOrderPay.discountAmount;
});
//满减优惠券
const fullCouponDiscountAmount = computed(() => {
return (
carts.orderCostSummary.fullCouponDeduction || props.orderInfo.fullCouponDiscountAmount || 0
);
});
//商品券抵扣金额
const productCouponDiscountAmount = computed(() => {
// 优先从 Store 扩展字段取,若无则用 props 数据(过渡方案)
return carts.orderCostSummary.productCouponDeduction;
});
const totalPrice = computed(() => {
// 使用bignumber.js处理高精度计算
const originalAmount = new BigNumber(carts.orderCostSummary.goodsOriginalAmount);
const discountAmount = new BigNumber(carts.orderCostSummary.goodsDiscountAmount);
const couponDeduction = new BigNumber(carts.orderCostSummary.couponDeductionAmount);
const merchantReduction = new BigNumber(carts.orderCostSummary.merchantReduction.actualAmount);
const pointDeduction = new BigNumber(carts.orderCostSummary.pointDeductionAmount);
// 逐步计算:原价 - 商品折扣 - 优惠券 - 商家减免 - 积分抵扣
const total = originalAmount
.minus(discountAmount)
.minus(couponDeduction)
.minus(merchantReduction)
.minus(pointDeduction)
.decimalPlaces(2, BigNumber.ROUND_DOWN); // 保持与工具库一致的舍入策略
const n = total.toNumber();
if (n <= 0) {
return 0;
}
return total.toNumber();
});
//应付金额
const currentpayMoney = computed(() => {
return carts.orderCostSummary.finalPayAmount;
});
watch(
() => currentpayMoney.value,
(newval) => {
if (newval * 1 <= 0) {
payTypes.sel = payTypes.list.findIndex((v) => v.payType == "cash");
}
}
);
onMounted(() => {
carts.payParamsInit();
getPaytype();
if (carts.vipUser.id) {
pointsInit();
}
});
defineExpose({
nowPayClick,
});
</script>
<style lang="scss" scoped>
.userinfo {
display: flex;
align-items: center;
line-height: 1;
cursor: pointer;
}
.vip {
padding: 2px 5px;
background: #f7793d;
color: #fff;
border-radius: 4px;
margin-left: 10px;
font-size: 10px;
}
.order-box {
display: flex;
padding: 20px 20px;
background-color: #f7f7fa;
min-height: 100%;
.left,
.right {
flex: 1;
}
.left {
padding-right: 20px;
}
.right {
border-left: 1px solid #ebebeb;
padding-left: 20px;
.order-info {
font-size: 14px;
.title {
display: inline-block;
}
.value {
display: inline-block;
}
.price {
color: #fa5555;
font-size: 20px;
}
}
}
}
.my-select {
border: 1px solid #d9d9d9;
border-radius: 4px;
margin-left: 12px;
cursor: pointer;
font-size: 14px;
color: #666;
padding: 8px 10px 8px 20px;
}
</style>