对接支付优惠

This commit is contained in:
gyq
2025-03-11 09:10:49 +08:00
parent 5cf2355d28
commit 3df0cce9ec
31 changed files with 1527 additions and 846 deletions

View File

@@ -5,8 +5,8 @@
<div class="list_title">{{ item.name }}</div>
<div class="item_wrap">
<el-button :type="item.active ? 'primary' : ''" @click="selectHandle(item)">全部</el-button>
<el-button :type="val.active ? 'primary' : ''" v-for="val in item.childrenList" :key="val.id"
@click="selectHandle(val, index)">{{ val.name }}</el-button>
<!-- <el-button :type="val.active ? 'primary' : ''" v-for="val in item.childrenList" :key="val.id"
@click="selectHandle(val, index)">{{ val.name }}</el-button> -->
</div>
</div>
</div>
@@ -18,9 +18,11 @@
</template>
<script setup>
import { tbShopCategoryGet } from "@/api/device";
import { onMounted, ref } from "vue";
import { useUser } from "@/store/user.js";
import { useGoods } from '@/store/goods.js'
const goodsStore = useGoods()
const store = useUser();
const emit = defineEmits(["success"]);
@@ -29,6 +31,7 @@ const dialogVisible = ref(false);
const loading = ref(false);
const categorys = ref([]);
// 确定
function onSubmitHandle() {
let categorysArr = [];
for (let item of categorys.value) {
@@ -38,16 +41,16 @@ function onSubmitHandle() {
id: item.id,
});
}
if (item.childrenList.length) {
for (let val of item.childrenList) {
if (val.active) {
categorysArr.push({
name: `${val.name}`,
id: val.id,
});
}
}
}
// if (item.childrenList.length) {
// for (let val of item.childrenList) {
// if (val.active) {
// categorysArr.push({
// name: `${val.name}`,
// id: val.id,
// });
// }
// }
// }
}
emit("success", categorysArr);
dialogVisible.value = false;
@@ -55,38 +58,34 @@ function onSubmitHandle() {
// 选择分类
function selectHandle(item, index = -1) {
if (index != -1) {
categorys.value[index].active = false;
} else {
item.childrenList.map((item) => {
item.active = false;
});
}
// if (index != -1) {
// categorys.value[index].active = false;
// } else {
// item.childrenList.map((item) => {
// item.active = false;
// });
// }
item.active = !item.active;
}
// 获取分类
async function tbShopCategoryGetAjax() {
try {
loading.value = true;
const res = await tbShopCategoryGet({
shopId: store.userInfo.shopId,
sort: "sort,desc",
page: 0,
pageSize: 200,
// loading.value = true;
// const res = await categoryList();
// res.list.map((item) => {
// item.active = false;
// item.childrenList.map((item) => {
// item.active = false;
// });
// });
categorys.value = goodsStore.originCategoryList.map(item => {
item.active = false
return item
});
// console.log(res);
res.list.map((item) => {
item.active = false;
item.childrenList.map((item) => {
item.active = false;
});
});
categorys.value = res.list;
setTimeout(() => {
loading.value = false;
}, 300);
// setTimeout(() => {
// loading.value = false;
// }, 300);
} catch (error) {
console.log(error);
loading.value = false;

View File

@@ -38,7 +38,7 @@
<!-- 更多 -->
<more ref="moreref" @openCall="openCall"></more>
<!-- 叫号 -->
<callNumber ref="callNumberRef" />
<!-- <callNumber ref="callNumberRef" /> -->
</template>
<script setup>

View File

@@ -13,52 +13,67 @@ export default (data) => {
// 文字内容
let html = `
<div style="font-size: 30px;display:flex;justify-content:center;">
${data.merchantName}
${data.shopName}
</div>
<div style="font-size: 16px;display: flex; justify-content:center;margin-top:6px;">
交班小票
</div>
<div style="font-size: 12px;margin-top:50px;">
当班时间:${data.startTime}
当班时间:${data.loginTime}
</div>
<div style="font-size: 12px;">
交班时间:${data.endTime}
交班时间:${data.handoverTime}
</div>
<div style="font-size: 12px;">
收银员:${data.staff}
收银员:${data.staffName}
</div>
<div style="font-size: 12px;margin-top: 4px;">
当班收入:${data.totalAmount}
当班收入:${data.handAmount}
</div>
<div style="font-size: 12px;margin-top: 4px;">
现金收入:${data.cashAmount}
</div>
<div style="font-size: 12px;margin-top: 4px;">
微信收入:${data.wechatAmount}
</div>
<div style="font-size: 12px;margin-top: 4px;">
支付宝收入:${data.alipayAmount}
</div>
<div style="font-size: 12px;margin-top: 4px;">
会员支付:${data.vipPay}
</div>
<div style="font-size: 12px;margin-top: 4px;">
会员充值:${data.vipRecharge}
</div>
`;
let payInfos = "";
if (data.payInfos && data.payInfos.length) {
for (let item of data.payInfos) {
payInfos += `
<div style="font-size: 12px;padding-left:20px;">
${item.payType}${item.amount}
</div>
`;
}
}
// let payInfos = "";
// if (data.payInfos && data.payInfos.length) {
// for (let item of data.payInfos) {
// payInfos += `
// <div style="font-size: 12px;padding-left:20px;">
// ${item.payType}${item.amount}
// </div>
// `;
// }
// }
let memberTitle = `
<div style="font-size: 12px;margin-top: 4px;">
会员数据
</div>
`;
// let memberTitle = `
// <div style="font-size: 12px;margin-top: 4px;">
// 会员数据
// </div>
// `;
let memberData = "";
if (data.memberData && data.memberData.length) {
for (let item of data.memberData) {
memberData += `
<div style="font-size: 12px;padding-left:20px;">
${item.deposit}${item.amount}
</div>
`;
}
}
// let memberData = "";
// if (data.memberData && data.memberData.length) {
// for (let item of data.memberData) {
// memberData += `
// <div style="font-size: 12px;padding-left:20px;">
// ${item.deposit}${item.amount}
// </div>
// `;
// }
// }
let productCategoriesTabHead = `
<div style="font-size: 12px;margin-top: 4px;">分类数据</div>
@@ -71,8 +86,8 @@ export default (data) => {
`;
let productCategoriesTableBody = "";
if (data.productCategories && data.productCategories.length) {
for (let item of data.productCategories) {
if (data.categoryDataList && data.categoryDataList.length) {
for (let item of data.categoryDataList) {
productCategoriesTableBody += `
<tr>
<td style="font-size: 12px;width:50%;">
@@ -98,8 +113,8 @@ export default (data) => {
`;
let tableBody = "";
if (data.productInfos && data.productInfos.length) {
for (let item of data.productInfos) {
if (data.productDatalist && data.productDatalist.length) {
for (let item of data.productDatalist) {
tableBody += `
<tr>
<td style="font-size: 12px;width:75%;">
@@ -120,27 +135,23 @@ export default (data) => {
</table>
<div style="font-size: 12px;margin-top: 4px;">
<span>快捷收款金额:</span>
<span>${data.quickAmount}</span>
<span>${data.quickInAmount}</span>
</div>
<div style="font-size: 12px;">
<span>退款金额:</span>
<span>${data.returnAmount}</span>
<span>${data.refundAmount}</span>
</div>
<div style="font-size: 12px;">
<span>总收入:</span>
<span>${data.totalAmount}</span>
<span>${data.handAmount}</span>
</div>
<div style="font-size: 12px;">
<span>备用金</span>
<span>${data.imprest}</span>
</div>
<div style="font-size: 12px;">
<span>应交金额:</span>
<span>${data.payable}</span>
<span>挂账金额</span>
<span>${data.creditAmount}</span>
</div>
<div style="margin-top: 20px; font-size: 12px;">
<span>总订单数:</span>
<span>${data.orderNum}</span>
<span>${data.orderCount}</span>
</div>
<div style="font-size: 12px;">
打印时间:${data.printTime}
@@ -151,7 +162,9 @@ export default (data) => {
<div>.</div>
`;
let lastHtml = `${html}${payInfos}${memberTitle}${memberData}${productCategoriesTabHead}${productCategoriesTableBody}${tabHead}${tableBody}${str}`;
// let lastHtml = `${html}${payInfos}${memberTitle}${memberData}${productCategoriesTabHead}${productCategoriesTableBody}${tabHead}${tableBody}${str}`;
let lastHtml = `${html}${productCategoriesTabHead}${productCategoriesTableBody}${tabHead}${tableBody}${str}`;
setTimeout(() => {
LODOP.ADD_PRINT_HTM("9mm", "0mm", "RightMargin:0mm", 20, lastHtml);

View File

@@ -5,12 +5,12 @@
<div class="drawerbox_bo_top">
<div class="drawerbox_bo_top_left" @click="computeExpired">
<div class="drawerbox_bo_top_left_one" style="font-size: 24px;">
{{ store.userInfo.shopName }}
{{ store.shopInfo.shopName }}
</div>
<div class="tips" style="margin-top: 4px; color: var(--el-color-warning);" v-if="!showTips">注意您的账号将于{{
store.userInfo.expireDate }}后过期请尽快续期</div>
store.shopInfo.expireTime }}后过期请尽快续期</div>
<div class="drawerbox_bo_top_left_tow" style="margin-top: 10px">
收银员{{ store.userInfo.loginAccount }}
收银员{{ store.userInfo.name }}
</div>
<div>
<span style="color: #666">{{ dayjs(store.userInfo.loginTime).format('YYYY-MM-DD HH:mm:ss') }}</span>
@@ -50,14 +50,14 @@
</div>
<div class="drawerbox_bo_box_icontext">设备管理</div>
</div>
<div class="drawerbox_bo_box_itembox" @click="openCallHandle">
<!-- <div class="drawerbox_bo_box_itembox" @click="openCallHandle">
<div class="drawerbox_bo_box_icon">
<el-icon size="40">
<Bell />
</el-icon>
</div>
<div class="drawerbox_bo_box_icontext">叫号</div>
</div>
</div> -->
<div class="drawerbox_bo_box_itembox" @click="screenref.shows()">
<div class="drawerbox_bo_box_icon">
<el-icon size="40">
@@ -123,7 +123,7 @@ function computeExpired() {
// 当前日期
let now = dayjs()
// 到期时间
let expired = dayjs(store.userInfo.expireDate).subtract(30, 'day')
let expired = dayjs(store.userInfo.expireTime).subtract(30, 'day')
// 判断当前时间是否大于到期时间30天
showTips.value = now.isBefore(expired)
}

View File

@@ -0,0 +1,216 @@
<template>
<el-dialog v-model="showDialog" title="选择优惠券" top="12vh" width="80%" @closed="resetHandle">
<el-radio-group v-model="query.type" @change="typeChange">
<el-radio-button label="优惠券" :value="1"></el-radio-button>
<el-radio-button label="商品券" :value="2"></el-radio-button>
</el-radio-group>
<div class="table">
<el-table ref="tableRef1" :data="tableData.list" border stripe v-loading="tableData.loading"
v-show="query.type == 1" height="300px">
<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="操作" align="center">
<template v-slot="scope">
<el-button type="primary" @click="selectCoupon(scope.row)">选择</el-button>
</template>
</el-table-column>
</el-table>
<el-table ref="tableRef2" :data="tableData.list" border stripe row-key="id" v-loading="tableData.loading"
v-show="query.type == 2" height="300px">
<el-table-column type="selection" width="55"></el-table-column>
<el-table-column label="名称" prop="name"></el-table-column>
<el-table-column label="商品信息">
<template v-slot="scope">
{{ scope.row.productName }} {{ scope.row.lowPrice }}
</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>
</div>
<div class="dialog_footer" v-if="query.type == 2">
<el-button @click="showDialog = false">取消</el-button>
<el-button type="primary" @click="selectCoupon()">确认</el-button>
</div>
</el-dialog>
</template>
<script setup>
import { ref, reactive } from 'vue'
import { useGoods } from '@/store/goods.js'
import { findCoupon } from '@/api/account.js'
import { ElMessage } from 'element-plus'
const props = defineProps({
orderList: {
type: Array,
default: []
}
})
const emits = defineEmits(['success'])
const goodsStore = useGoods()
const tableRef1 = ref(null)
const tableRef2 = ref(null)
const showDialog = ref(false)
const query = ref({
type: 1,
userId: ''
})
const tableData = reactive({
loading: false,
list: []
})
// 关闭初始化
function resetHandle() {
query.value.type = 1
tableData.loading = false
tableData.list = []
}
function typeChange() {
tableData.loading = false
tableData.list = []
findCouponAjax()
if (query.type == 2) {
tableRef2.value.clearSelection()
}
}
function groupByPropertyAndCount(arr, property) {
// 创建一个空对象来存储每个属性值对应的数量
const propertyMap = {};
// 遍历原始数组
arr.forEach(item => {
const key = item[property];
const num = item.number || 1;
if (!propertyMap[key]) {
// 如果该属性值还没有在 propertyMap 中,初始化一个对象
propertyMap[key] = {
value: item[property],
count: num
};
} else {
// 如果该属性值已经存在,增加数量
propertyMap[key].count += num;
}
});
// 将 propertyMap 中的结果转换为数组
return Object.values(propertyMap);
}
// 选择优惠券
function selectCoupon(row) {
if (query.value.type == 1) {
emits('success', { type: query.value.type, couponList: [{ ...row }] })
} else {
let goods = [
...goodsStore.cartList,
...goodsStore.orderList.map(item => item.goods).flat()
]
let arr = tableRef2.value.getSelectionRows()
if (!arr.length) {
ElMessage.error('请选择优惠券')
return
}
let obj = groupByPropertyAndCount(arr, 'proId')
let goodsObj = groupByPropertyAndCount(goods, 'product_id')
console.log(obj);
console.log(goodsObj);
for (let val of goodsObj) {
for (let item of obj) {
if (val.value == item.value) {
if (item.count > val.count) {
ElMessage.error('超出订单数量,请重新选择')
return
}
}
}
}
emits('success', { type: query.value.type, couponList: arr })
}
showDialog.value = false
}
// 获取用户可用de优惠券
async function findCouponAjax() {
try {
tableData.loading = true
const res = await findCoupon({
shopUserId: query.value.userId,
type: query.value.type
})
if (query.value.type == 1) {
tableData.list = res
} else {
let arr = []
let ids = props.orderList.map(item => item.productId)
res.map(item => {
if (ids.includes(item.proId)) {
let pro = props.orderList.find(val => val.productId == item.proId)
arr.push({
...item,
productName: pro.productName,
lowPrice: pro.lowPrice
})
}
})
tableData.list = arr
}
} catch (error) {
console.log(error);
}
tableData.loading = false
}
function show(userId) {
showDialog.value = true
query.value.userId = userId
findCouponAjax()
console.log('couponModal.orderList===', props.orderList);
}
defineExpose({
show
})
</script>
<style scoped lang="scss">
.table {
padding-top: var(--el-font-size-base);
}
.dialog_footer {
display: flex;
justify-content: flex-end;
padding-top: var(--el-font-size-base);
}
</style>

View File

@@ -7,10 +7,11 @@
<span class="num">{{ money }}</span>
</div>
<div class="t2">
<span>原价{{ formatDecimal(props.amount) }}</span>
<span>原价{{ formatDecimal(props.amount - goodsStore.tableInfo.tableFee) }}</span>
<span style="margin-left: 20px">餐位费{{ formatDecimal(goodsStore.tableInfo.tableFee) }}</span>
<span style="margin-left: 20px">优惠{{ formatDecimal(props.amount - money) }}</span>
<span style="margin-left: 20px" v-if="props.discount" @click="cancelDiscount">折扣{{
formatDecimal(props.discount * 10, 1, true) }}
<span style="margin-left: 20px" v-if="discountRateVlaue" @click="cancelDiscount">
折扣{{ discountRateVlaue }}
<el-icon style="margin-left: 6px">
<CircleClose />
</el-icon>
@@ -27,7 +28,7 @@
</div>
<span class="title">{{ item.payName }}</span>
</div>
<!-- <div class="item" :class="{ active: payActive == 'buyer' }"
<div class="item" :class="{ active: payActive == 'buyer' }"
@click="payTypeChange('buyer', { payType: 'buyer' })">
<div class="icon">
<div class="img"
@@ -36,10 +37,10 @@
</div>
</div>
<span class="title">挂账</span>
</div> -->
</div>
</div>
<div class="input_wrap">
<div class="input" style="flex: 1">储值{{ money }}</div>
<div class="input" style="flex: 1">付款{{ money }}</div>
<el-button type="primary" style="width: 120px;border-radius: 6px; height: 60px;"
@click="showCouponHandle">添加优惠</el-button>
</div>
@@ -99,7 +100,7 @@
:total="Number(tableData.total)" v-model:current-page="tableData.page" @current-change="getMemberList" />
</el-dialog>
<!-- 选择挂账人员 -->
<el-dialog title="挂账" top="3vh" v-model="showBuyer" width="90%" @closed="resetBuyerTable">
<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" />
@@ -110,7 +111,7 @@
</el-form-item>
</el-form>
<el-table :data="buyerTable.list" height="440px" border stripe v-loading="buyerTable.loading">
<el-table-column prop="debtor" label="挂账人" />
<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">
@@ -143,49 +144,128 @@
<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="添加优惠">
<el-form ref="couponFormRef" :model="couponForm">
<el-form-item label="会员">
<el-select>
<el-option label="会员1" value="1"></el-option>
</el-select>
</el-form-item>
</el-form>
<el-dialog v-model="showCoupon" title="添加优惠" @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">
<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="优惠券">
<div style="width: 100%;">
<el-button type="primary" :disabled="!couponFormUser.id"
@click="showCounponModalHandle">选择优惠券</el-button>
<div>
<div class="title">优惠券</div>
<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 }} {{ scope.row.lowPrice }}
</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="积分抵扣">
<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="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>
</el-dialog>
<!-- 选择会员 -->
<SelectVipUser ref="SelectVipUserRef" @success="selectUserHandle" />
<!-- 选择优惠券 -->
<CouponModal ref="CouponModalRef" :orderList="props.orderList" @success="CouponModalSuccess" />
</template>
<script setup>
import { onMounted, ref, computed, watch, reactive } from "vue";
import {
queryPayType,
accountPay,
vipPay,
buyerPage,
payCreditPay,
} from "@/api/pay";
import {
queryMembermember,
createMembermember,
membermemberScanPay,
accountPaymember,
} from "@/api/member/index.js";
import _ from 'lodash'
import { onMounted, ref, reactive, watch } from "vue";
import { useUser } from "@/store/user.js";
import { clearNoNum, formatDecimal } from "@/utils";
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 { useGlobal } from "@/store/global.js";
import { staffPermission } from "@/api/user.js";
import { cashPay } from "@/api/order.js";
import { cashPay, buyerPage, creditPay, vipPay } from "@/api/order.js";
import { calcUsablePoints, calcDeductionAmount } from '@/api/account.js'
import { useGoods } from "@/store/goods.js";
const SelectVipUserRef = ref(null)
const CouponModalRef = ref(null)
const goodsStore = useGoods();
const global = useGlobal();
const store = useUser();
const props = defineProps({
@@ -198,32 +278,24 @@ const props = defineProps({
default: 0,
},
orderId: {
type: [String, Number],
default: "",
},
discount: {
type: [String, Number],
type: [Number, String],
default: 0,
},
});
const emit = defineEmits(["paySuccess", "cancelDiscount"]);
const money = ref("0");
const scanModalRef = ref(null);
watch(props, (value) => {
money.value = `${formatDecimal(props.amount)}`;
if (props.discount > 0) {
money.value = `${formatDecimal(props.amount * props.discount)}`;
orderList: {
type: Array,
default: []
}
});
// const waitPayMoney = computed(() => {
// let num = JSON.stringify(props.amount - money.value)
// num = Math.floor(num * 100) / 100
// return num
// })
watch(props, () => {
money.value = formatDecimal(props.amount)
})
const emit = defineEmits(["paySuccess"]);
const money = ref("0");
const discountRateVlaue = ref(0)
const scanModalRef = ref(null);
const payActive = ref(0);
const payType = ref("");
@@ -231,6 +303,8 @@ const payList = ref([]);
const payLoading = ref(false);
const payData = ref({});
const roundAmount = ref(0) // 抹零金额
// 挂账人 start
const showBuyer = ref(false);
const buyerTable = reactive({
@@ -248,7 +322,7 @@ function showBuyerHandle() {
getBuyerList();
}
//
// 重置
function resetBuyerTable() {
buyerTable.keywords = "";
buyerTable.page = 1;
@@ -262,19 +336,17 @@ async function getBuyerList() {
const res = await buyerPage({
page: buyerTable.page,
size: buyerTable.size,
shopId: store.userInfo.shopId,
keywords: buyerTable.keywords,
status: 1,
responsiblePerson: "",
repaymentStatus: "",
});
buyerTable.loading = false;
buyerTable.list = res.list;
buyerTable.total = res.total;
buyerTable.list = res.records;
buyerTable.total = res.totalRow;
} catch (error) {
buyerTable.loading = false;
console.log(error);
}
buyerTable.loading = false;
}
// 选择挂账人支付
@@ -282,17 +354,12 @@ async function payCreditPayHandle(row) {
try {
payLoading.value = true;
buyerTable.loading = true;
const res = await payCreditPay({
creditBuyerId: row.id,
orderId: props.orderId,
payAmount: props.discount > 0 ? money.value : "",
discountAmount:
props.discount > 0 ? formatDecimal(props.amount - money.value) : "",
});
payData.value.creditBuyerId = row.id
await creditPay(payData.value);
showBuyer.value = false;
payLoading.value = false;
buyerTable.loading = false;
ElMessage.success("支付成功");
emit("paySuccess");
} catch (error) {
buyerTable.loading = false;
@@ -338,17 +405,13 @@ async function payTypeChange(index, item) {
async function confirmOrder() {
try {
payLoading.value = true;
// 暂时使用现金支付
payData.value.checkOrderPay.orderAmount = formatDecimal(+money.value);
payData.value.checkOrderPay.roundAmount = formatDecimal(props.amount - money.value);
payData.value.checkOrderPay.userId = goodsStore.vipUserInfo.userId ? goodsStore.vipUserInfo.userId : "";
payData.value.checkOrderPay.roundAmount = roundAmount.value;
payData.value.checkOrderPay.vipPrice = goodsStore.vipUserInfo.userId ? 1 : 0;
await cashPay(payData.value);
payLoading.value = false;
emit("paySuccess");
return;
await staffPermission("yun_xu_shou_kuan");
if (payLoading.value) return;
payData.value.checkOrderPay.couponList = [...couponResList1.value.map(item => item.id), ...couponResList2.value.map(item => item.id)];
// await staffPermission("yun_xu_shou_kuan");
if (payActive.value == "buyer") {
showBuyerHandle();
} else if (payList.value[payActive.value].payType == "scanCode") {
@@ -357,40 +420,16 @@ async function confirmOrder() {
// if (money.value < props.amount) return
payLoading.value = true;
switch (payList.value[payActive.value].payType) {
case "deposit": //储值卡
// if (props.selecttype == 1) {
// } else {
// }
if (global.orderMemberInfo.id) {
await accountPay({
orderId: props.orderId,
memberId: global.orderMemberInfo.id,
memberAccount: "",
});
} else {
payLoading.value = false;
scanModalRef.value.show();
return;
}
case "deposit":
// 会员码支付
payLoading.value = false;
scanModalRef.value.show();
break;
case "cash": //现金
if (props.selecttype == 1) {
await accountPaymember({
shopId: store.userInfo.shopId,
memberId: props.orderId,
amount: props.amount,
});
case "cash":
//现金
if (props.selecttype == 0) {
await cashPay(payData.value);
} else {
await cashPay({
orderId: props.orderId,
payAmount: props.discount > 0 ? money.value : "",
discountAmount:
props.discount > 0
? formatDecimal(props.amount - money.value)
: "",
});
}
break;
case "vipPay":
@@ -404,7 +443,6 @@ async function confirmOrder() {
break;
}
payLoading.value = false;
ElMessage.success("支付成功");
emit("paySuccess");
}
} catch (error) {
@@ -417,10 +455,13 @@ async function confirmOrder() {
// 输入
function amountInput(num) {
if (money.value + num <= props.amount) {
money.value = clearNoNum({ value: (money.value += num) });
money.value = clearNoNum({ value: (money.value += num) })
} else {
money.value = clearNoNum({ value: `${props.amount}` });
money.value = formatDecimal(+props.amount);
}
roundAmount.value = formatDecimal(props.amount - money.value)
console.log('roundAmount.value', roundAmount.value);
}
// 删除
@@ -430,6 +471,9 @@ function delHandle() {
if (!money.value) {
money.value = "0";
}
roundAmount.value = formatDecimal(props.amount - money.value)
console.log('roundAmount.value', roundAmount.value);
}
// 获取支付方式
@@ -445,10 +489,10 @@ async function queryPayTypeAjax() {
}
});
payList.value = res;
if (res[0].payType == "scanCode" && !res[0].disabled) {
payList.value = res.filter(item => item.isDisplay);
if (payList.value[0].payType == "scanCode" && !payList.value[0].disabled) {
scanModalRef.value.show();
payType.value = res[0].payType;
payType.value = payList.value[0].payType;
}
} catch (error) {
console.log(error);
@@ -517,56 +561,337 @@ async function toHomeMember(row) {
// 取消折扣
function cancelDiscount() {
emit("cancelDiscount");
discountRateVlaue.value = 0
money.value = formatDecimal(props.amount)
}
/** 添加优惠 start */
const showCoupon = ref(false)
const couponFormRef = ref(null)
const couponForm = ref({
userId: '',
discountRatio: '',
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,
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 = []
resetCouponFormHandle()
}
// 折扣格式化
function discountInput(e) {
couponForm.value.amount = couponForm.value.originAmount
setTimeout(() => {
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)
}
// 003-根据积分计算可抵扣金额
const calcPointMoney = _.debounce(async function () {
try {
const res = await calcDeductionAmount({
userId: couponFormUser.value.id,
orderAmount: couponForm.value.amount,
points: couponForm.value.pointsNum
})
pointOptions.value.amount = formatDecimal(+res)
couponForm.value.amount = couponForm.value.amount - res
} catch (error) {
console.log(error);
}
pointOptions.value.loading = false
}, 500)
// 当dialog打开时
function couponDialogOpen() {
couponForm.value.amount = formatDecimal(money.value - goodsStore.tableInfo.tableFee)
couponForm.value.originAmount = couponForm.value.amount
resetCouponForm.value = { ...couponForm.value }
couponResList1.value = []
couponResList2.value = []
// 当购物车已存在用户时
if (goodsStore.vipUserInfo.id && goodsStore.showVipPrice) {
couponFormUserList.value = [
{
id: goodsStore.vipUserInfo.userId,
nickName: goodsStore.vipUserInfo.nickName,
}
]
couponFormUser.value = goodsStore.vipUserInfo
pointOptions()
}
}
// 关闭后初始化dialog
function resetCouponFormHandle() {
couponForm.value = { ...resetCouponForm.value }
}
// 选择会员完成后
function selectUserHandle(row) {
couponFormUserList.value = [
{
id: row.userId,
nickName: row.nickName,
}
]
couponFormUser.value = row
pointOptionsAjax()
// 已存在选择的用户,并且切换了不通用户
if (couponFormUser.id && row.userId != couponFormUser.value.userId) {
resetCoupon()
}
}
// 重选用户后重置优惠券和积分,并重新计算价格
function resetCoupon() {
couponResList1.value = []
couponResList2.value = []
couponForm.value.amount = formatDecimal(couponForm.value.amount * (couponForm.value.discountRatio / couponFormDiscountRate.value))
}
// 选择完用户后开始获取积分使用配置
async function pointOptionsAjax() {
try {
const res = await calcUsablePoints({
userId: couponFormUser.value.id,
orderAmount: couponForm.value.amount
})
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 // 最少使用的金额
} catch (error) {
console.log(error);
}
}
// 显示添加优惠
function showCouponHandle() {
showCoupon.value = true
}
// 显示选择优惠券
function showCounponModalHandle() {
CouponModalRef.value.show(couponFormUser.value.id)
}
// 选择完优惠券的回调事件
function CouponModalSuccess(res) {
console.log(res);
couponResType.value = res.type
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);
// 计算所有的优惠金额
let amount = 0
discountOrders.forEach(item => {
if (item.isCoupon) {
amount += item.price
}
})
couponForm.value.productCouponDiscountAmount = amount
couponForm.value.amount = formatDecimal(couponForm.value.amount - amount)
}
}
// 多个优惠券抵扣多个商品,优先已价格最低的抵扣
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;
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)
}
console.log(couponForm.value.amount);
}
// 确认优惠
function discountConfirm() {
// 确认折扣
discountRateVlaue.value = couponForm.value.discountRatio || ''
payData.value.checkOrderPay.discountAmount = couponForm.value.discountRatio ? formatDecimal(couponForm.value.originAmount - (couponForm.value.originAmount * (couponForm.value.discountRatio / couponFormDiscountRate.value))) : 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)
payData.value.checkOrderPay.fullCouponDiscountAmount = couponForm.value.fullCouponDiscountAmount
showCoupon.value = false
}
/** 添加优惠 end */
onMounted(() => {
// 初始化
function reset() {
roundAmount.value = 0
discountRateVlaue.value = 0
money.value = `${formatDecimal(props.amount)}`;
payData.value = {
shopId: store.shopInfo.id,
buyerRemark: "", // 订单备注
checkOrderPay: {
orderId: goodsStore.orderListInfo.id,
vipPrice: 0, // 是否使用会员价
allPack: 0, // 是否整单打包
vipPrice: store.shopInfo.isMemberPrice || goodsStore.showVipPrice, // 是否使用会员价
allPack: goodsStore.allSelected, // 是否整单打包
userId: goodsStore.vipUserInfo.id,
seatNum: goodsStore.tableInfo.num, // 用餐人数
originAmount: formatDecimal(+goodsStore.cartInfo.totalAmount), // 订单原金额(包含打包费+餐位费) 不含折扣价格
discountRatio: 1, // 折扣比例(计算时 向上取整保留 两位小数)
discountRatio: '', // 折扣比例(计算时 向上取整保留 两位小数)
discountAmount: 0, // 手动优惠金额
productCouponDiscountAmount: 0, // 商品优惠券抵扣金额
fullCouponDiscountAmount: 0, // 满减优惠券抵扣金额
couponList: [], // 用户使用的卡券
orderAmount: formatDecimal(
+goodsStore.cartInfo.totalAmount - goodsStore.cartInfo.packFee
), // 订单金额
orderAmount: formatDecimal(+goodsStore.cartInfo.totalAmount), // 订单金额
roundAmount: 0, // 抹零金额 减免多少钱
pointsDiscountAmount: 0, // 积分抵扣金额(tb_points_basic_setting表)
pointsNum: 0, // 使用的积分数量 (扣除各类折扣 enable_deduction后使用)
},
};
}
onMounted(() => {
queryPayTypeAjax();
});
defineExpose({
reset
})
</script>
<style scoped lang="scss">
.point_tips {
&.err {
color: var(--el-color-danger);
}
}
.card {
padding: var(--el-font-size-base);
height: 100%;
@@ -718,4 +1043,39 @@ onMounted(() => {
font-size: calc(var(--el-font-size-base) + 10px);
}
}
.coupom_dialog {
.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;
}
}
}
</style>

View File

@@ -58,7 +58,7 @@ import { scanpay, queryOrder, quickPay, queryQuickPayStatus, accountPay, querySc
import { useUser } from "@/store/user.js";
import { useGlobal } from '@/store/global.js'
import { formatDecimal } from '@/utils'
import { microPay, queryOrderStatus, microPayVip } from '@/api/order.js'
import { microPay, queryOrderStatus, microPayVip, vipPay } from '@/api/order.js'
const store = useUser();
const global = useGlobal()
@@ -89,6 +89,7 @@ const props = defineProps({
type: Boolean,
default: false,
},
// 支付类型
payType: {
type: [Number, String],
default: "",
@@ -119,11 +120,20 @@ async function submitHandle() {
if (!scanCode.value) return;
loading.value = true;
if (props.selecttype == 0) {
// 正常下单扫码支付
await microPay({
...props.payData,
authCode: scanCode.value
});
// 下单扫码支付
if (props.payType == 'payType') {
await microPay({
...props.payData,
authCode: scanCode.value
});
} else if (props.payType == 'deposit') {
await vipPay({
...props.payData,
payType: 'scanCode',
authCode: scanCode.value
});
}
} else if (props.selecttype == 1) {
// 会员扫码充值
await microPayVip({
@@ -133,6 +143,7 @@ async function submitHandle() {
authCode: scanCode.value
})
} else {
// 快捷收银
if (props.fast) {
await quickPay({
amount: props.amount,

View File

@@ -1,9 +1,16 @@
<template>
<el-dialog :title="`选择会员`" top="3vh" v-model="showDialog" width="80%">
<el-dialog :title="`选择会员`" top="2vh" v-model="showDialog" width="80%">
<el-form inline>
<el-form-item>
<el-input placeholder="请输入手机号搜索会员" v-model="tableData.phone" />
</el-form-item>
<el-form-item>
<el-select v-model="tableData.isVips" placeholder="是否为会员" style="width: 150px;" @change="resetTable">
<el-option label="全部" value=""></el-option>
<el-option label="是" :value="1"></el-option>
<el-option label="否" :value="0"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="getMemberList">搜索</el-button>
<el-button @click="resetTable">重置</el-button>
@@ -15,7 +22,7 @@
<el-table-column prop="code" label="编号" width="120px" />
<el-table-column prop="level" label="等级" />
<el-table-column prop="accountPoints" label="积分" />
<el-table-column prop="amount" label="余额" width="100px">
<el-table-column prop="amount" label="余额" width="120px">
<template v-slot="scope">
{{ formatDecimal(scope.row.amount) }}
</template>
@@ -35,14 +42,12 @@
import { ref, reactive } from 'vue'
import { shopUserList } from "@/api/account.js";
import { formatDecimal } from '@/utils/index.js'
import { useGoods } from '@/store/goods.js'
import { useUser } from '@/store/user.js'
const useStore = useUser()
const goodsStore = useGoods()
const emits = defineEmits(['success'])
const showDialog = ref(false)
const tableData = reactive({
phone: '',
isVips: "",
loading: false,
list: [],
page: 1,
@@ -50,15 +55,10 @@ const tableData = reactive({
total: 0
})
// 选择会员去下单
async function toHomeMember(row) {
try {
goodsStore.vipUserInfo = { ...row }
if (useStore.shopInfo.isMemberPrice) {
goodsStore.showVipPrice = true
goodsStore.calcCartInfo()
}
emits('success', { ...row })
} catch (error) {
console.log(error);
}
@@ -78,7 +78,7 @@ async function getMemberList() {
tableData.loading = true
const res = await shopUserList({
key: tableData.phone,
isVips: 1,
isVips: tableData.isVips,
page: tableData.page,
size: tableData.size
})