feat: 代客下单优惠券更新,挂账更新

This commit is contained in:
2025-03-06 11:27:01 +08:00
parent ed9a3335c8
commit dda4db24e0
22 changed files with 1219 additions and 300 deletions

View File

@@ -55,11 +55,11 @@ const CommonApi = {
/** /**
* 发送验证码 * 发送验证码
*/ */
sms(data: smsRequest) { sms(params: smsRequest) {
return request<any, smsResponse>({ return request<any, smsResponse>({
url: `${baseURL}/sms`, url: `${baseURL}/sms`,
method: "post", method: "get",
data: data, params
}); });
}, },
}; };

View File

@@ -32,9 +32,24 @@ const API = {
data: data, data: data,
}); });
}, },
// 查找优惠券 生成订单后使用
findCoupon(params: findCouponRequest) {
return request<any>({
url: `${baseURL}/findCoupon`,
method: "get",
params
});
},
} }
export default API; export default API;
export interface findCouponRequest {
/**
* 店铺用户Id
*/
shopUserId: number;
type?: number;
[property: string]: any;
}
export interface queryReceive { export interface queryReceive {
/** /**
* 优惠券id * 优惠券id

52
src/api/order/credit.ts Normal file
View File

@@ -0,0 +1,52 @@
import request from "@/utils/request";
import { Order_BaseUrl } from "@/api/config";
const baseURL = Order_BaseUrl + "/admin/order/credit/buyer";
const Api = {
getList(params: any) {
return request<any, any>({
url: `${baseURL}/page`,
method: "get",
params
});
},
get(params: any) {
return request<any, any>({
url: `${baseURL}`,
method: "get",
params
});
},
add(data: any) {
return request<any, any>({
url: `${baseURL}`,
method: "post",
data
});
},
edit(data: any) {
return request<any, any>({
url: `${baseURL}`,
method: "put",
data
});
},
delete(id: string | number) {
return request<any, any>({
url: `${baseURL}/` + id,
method: "delete",
});
},
// 还款
repayment(data: any) {
return request<any, any>({
url: `${baseURL}/repayment`,
method: "post",
data
});
},
};
export default Api;

View File

@@ -66,7 +66,7 @@ export const constantRoutes: RouteRecordRaw[] = [
{ {
path: "credit", path: "credit",
name: "creditStatistics", name: "creditStatistics",
component: () => import("@/views/data/credit.vue"), component: () => import("@/views/data/credit/index.vue"),
meta: { meta: {
title: "挂账管理", title: "挂账管理",
affix: false, affix: false,

View File

@@ -18,7 +18,7 @@ export const useCartsStore = defineStore("carts", () => {
//是否启用会员价 //是否启用会员价
const useVipPrice = computed(() => { const useVipPrice = computed(() => {
return shopUser.userInfo.isMemberPrice && vipUser.value.id && vipUser.value.isVip return (shopUser.userInfo.isMemberPrice && vipUser.value.id && vipUser.value.isVip) ? true : false
}) })
//台桌id //台桌id
@@ -380,7 +380,6 @@ export const useCartsStore = defineStore("carts", () => {
for (let i in data) { for (let i in data) {
newData[i] = data[i].map((v: any) => { newData[i] = data[i].map((v: any) => {
const skuData = getProductDetails({ product_id: v.productId, sku_id: v.skuId }) const skuData = getProductDetails({ product_id: v.productId, sku_id: v.skuId })
console.log(v)
return { return {
...skuData, ...skuData,
placeNum: v.placeNum, placeNum: v.placeNum,

View File

@@ -38,7 +38,7 @@ class WebSocketManager {
private reconnectAttempts = 0; private reconnectAttempts = 0;
private maxReconnectAttempts = 3; // 自定义最大重试次数 private maxReconnectAttempts = 3; // 自定义最大重试次数
private reconnectDelay = 5000; // 重试延迟(单位:毫秒) private reconnectDelay = 5000; // 重试延迟(单位:毫秒)
private timer: any | null = null;
// 初始化 WebSocket 客户端 // 初始化 WebSocket 客户端
setupWebSocket() { setupWebSocket() {
const endpoint = import.meta.env.VITE_APP_WS_ENDPOINT; const endpoint = import.meta.env.VITE_APP_WS_ENDPOINT;
@@ -60,8 +60,13 @@ class WebSocketManager {
console.log("WebSocket 连接已建立"); console.log("WebSocket 连接已建立");
// ElNotification.success('WebSocket 连接已建立') // ElNotification.success('WebSocket 连接已建立')
this.sendMessage(this.initParams) this.sendMessage(this.initParams)
clearTimeout(this.timer)
this.timer = setInterval(() => {
this.sendMessage({ "type": "ping_interval" })
}, 1000 * 10);
}; };
this.client.onclose = () => { this.client.onclose = () => {
clearTimeout(this.timer)
if (!this.connected) { if (!this.connected) {
// ElMessageBox.alert('WebSocket 连接已断开', 'Title', { // ElMessageBox.alert('WebSocket 连接已断开', 'Title', {
// confirmButtonText: '立即重连', // confirmButtonText: '立即重连',
@@ -74,6 +79,7 @@ class WebSocketManager {
console.log("WebSocket 连接已断开"); console.log("WebSocket 连接已断开");
}; };
this.client.onerror = (error) => { this.client.onerror = (error) => {
clearTimeout(this.timer)
console.error("WebSocket 发生错误:", error); console.error("WebSocket 发生错误:", error);
// ElNotification({ // ElNotification({
// title: "提示", // title: "提示",

View File

@@ -295,7 +295,25 @@ export default {
methods: { methods: {
reset() { reset() {
this.$refs.form.resetFields(); this.$refs.form.resetFields();
this.form = this.resetForm; this.form = {
id: "",
shopId: "",
type: "1",
title: "",
fullAmount: null,
discountAmount: null,
validityType: "fixed",
validStartTime: "",
validEndTime: "",
userDays: [],
validDays: "",
useTimeType: "all",
useStartTime: "",
useEndTime: "",
proId: "",
proName: "",
number: "",
};
this.form.type = 1; this.form.type = 1;
}, },
async open(data) { async open(data) {

View File

@@ -1,3 +0,0 @@
<template>
<div></div>
</template>

View File

@@ -0,0 +1,80 @@
import creditApi from "@/api/order/credit";
import { returnOptions } from "./config";
import type { IModalConfig } from "@/components/CURD/types";
const modalConfig: IModalConfig = {
pageName: "sys:user",
dialog: {
title: "创建挂账人",
width: 800,
draggable: true,
},
form: {
labelWidth: 140,
},
formAction: function (data) {
return creditApi.add({ ...data });
},
beforeSubmit(data) {
console.log("提交之前处理", data);
},
formItems: [
{
label: "状态",
prop: "status",
type: 'switch',
attrs: {
activeText: '开启',
inactiveText: '关闭',
activeValue: 1,
inactiveValue: 0
},
initialValue: 1
},
{
label: "挂账人",
prop: "debtor",
rules: [{ required: true, message: "请输入挂账人", trigger: "blur" }],
attrs: {
placeholder: "请输入挂账人",
},
},
{
label: "手机号",
prop: "mobile",
rules: [{ required: true, message: "请输入挂账人手机号", trigger: "blur" }],
attrs: {
placeholder: "请输入挂账人手机号",
},
},
{
label: "职务",
prop: "position",
rules: [{ required: false, message: "请输入挂账人职务", trigger: "blur" }],
attrs: {
placeholder: "请输入挂账人职务",
},
},
{
label: "挂账额度",
prop: "creditAmount",
type: "input-number",
rules: [{ required: true, message: "请输入挂账额度", trigger: "blur" }],
attrs: {
placeholder: "请输入挂账额度",
},
initialValue: 0
},
{
label: "还款方式",
prop: "repaymentMethod",
type: "radio-button",
options: returnOptions('repaymentMethod'),
initialValue: returnOptions('repaymentMethod')[0].value
},
],
};
// 如果有异步数据会修改配置的推荐用reactive包裹而纯静态配置的可以直接导出
export default reactive(modalConfig);

View File

@@ -0,0 +1,26 @@
const options: Record<string, { label: string; value: string; }[]> = {
repaymentMethod: [
{ label: '按总金额还款', value: "total" },
{ label: '按订单还款', value: "order" },
]
};
export function returnOptions(type: keyof typeof options) {
return options[type];
}
export function returnOptionsLabel(optionsType: optionsType, value: string | number) {
const options = returnOptions(optionsType);
if (!options) {
return "";
}
const option = options.find((item) => item.value === value);
return option ? option.label : "";
}
export interface options {
label: string;
value: string | number;
[property: string]: any;
}

View File

@@ -0,0 +1,102 @@
import creditApi from "@/api/order/credit";
import type { IContentConfig } from "@/components/CURD/types";
const contentConfig: IContentConfig = {
pageName: "sys:user",
table: {
border: true,
highlightCurrentRow: true,
},
pagination: {
background: true,
layout: "prev,pager,next,jumper,total,sizes",
pageSize: 20,
pageSizes: [10, 20, 30, 50],
},
indexAction: function (params) {
return creditApi.getList(params);
},
deleteAction: creditApi.delete,
// modifyAction: function (data) {
// // return creditApi.edit(data);
// },
pk: "id",
toolbar: ["add"],
defaultToolbar: ["refresh", "filter", "search"],
cols: [
{
label: "挂账编码",
align: "center",
prop: "id",
},
{
label: "状态",
align: "center",
prop: "status",
templet: 'custom',
slotName: 'status',
width: 120,
},
{
label: "挂账人",
align: "center",
prop: "debtor",
},
{
label: "手机号",
align: "center",
prop: "mobile",
},
{
label: "挂账额度(元)",
align: "center",
prop: "creditAmount",
},
{
label: "已挂账金额(元)",
align: "center",
prop: "owedAmount",
},
{
label: "剩余挂账额度(元)",
align: "center",
prop: "owedAmount",
},
{
label: "账户余额",
align: "center",
prop: "accountBalance",
},
{
label: "操作",
align: "center",
fixed: "right",
width: 300,
templet: "tool",
operat: [
{
text: "查看明细",
name: 'detail'
},
{
text: "编辑",
name: 'edit'
},
{
text: "还款",
name: 'huankuan'
},
{
text: "还款记录",
name: 'huankuan_detail'
},
{
text: "删除",
name: 'delete'
},
],
},
],
};
export default contentConfig;

View File

@@ -0,0 +1,80 @@
import creditApi from "@/api/order/credit";
import { returnOptions } from "./config";
import type { IModalConfig } from "@/components/CURD/types";
const modalConfig: IModalConfig = {
pageName: "sys:user",
dialog: {
title: "编辑挂账人",
width: 800,
draggable: true,
},
form: {
labelWidth: 140,
},
formAction: function (data) {
return creditApi.edit({ ...data });
},
beforeSubmit(data) {
console.log("提交之前处理", data);
},
formItems: [
{
label: "状态",
prop: "status",
type: 'switch',
attrs: {
activeText: '开启',
inactiveText: '关闭',
activeValue: 1,
inactiveValue: 0
},
initialValue: 1
},
{
label: "挂账人",
prop: "debtor",
rules: [{ required: true, message: "请输入挂账人", trigger: "blur" }],
attrs: {
placeholder: "请输入挂账人",
},
},
{
label: "手机号",
prop: "mobile",
rules: [{ required: true, message: "请输入挂账人手机号", trigger: "blur" }],
attrs: {
placeholder: "请输入挂账人手机号",
},
},
{
label: "职务",
prop: "position",
rules: [{ required: false, message: "请输入挂账人职务", trigger: "blur" }],
attrs: {
placeholder: "请输入挂账人职务",
},
},
{
label: "挂账额度",
prop: "creditAmount",
type: "input-number",
rules: [{ required: true, message: "请输入挂账额度", trigger: "blur" }],
attrs: {
placeholder: "请输入挂账额度",
},
initialValue: 0
},
{
label: "还款方式",
prop: "repaymentMethod",
type: "radio-button",
options: returnOptions('repaymentMethod'),
initialValue: returnOptions('repaymentMethod')[0].value
},
],
};
// 如果有异步数据会修改配置的推荐用reactive包裹而纯静态配置的可以直接导出
export default reactive(modalConfig);

View File

@@ -0,0 +1,39 @@
import type { ISearchConfig } from "@/components/CURD/types";
const searchConfig: ISearchConfig = {
pageName: "sys:user",
formItems: [
{
type: "input",
label: "挂账人",
prop: "keywords",
attrs: {
placeholder: "请输入挂账人或手机号",
clearable: true,
style: {
width: "200px",
},
},
},
{
type: "select",
label: "还款状态",
prop: "repaymentStatus",
attrs: {
placeholder: "请选择还款状态",
clearable: true,
style: {
width: "200px",
},
},
initialValue: '',
options: [
{ label: "未还款", value: 'unpaid' },
{ label: "部分还款", value: 'partial' },
{ label: "已还清", value: 'paid' },
],
},
],
};
export default searchConfig;

View File

@@ -0,0 +1,131 @@
<template>
<div class="app-container">
<!-- 列表 -->
<!-- 搜索 -->
<page-search
ref="searchRef"
:search-config="searchConfig"
@query-click="handleQueryClick"
@reset-click="handleResetClick"
/>
<!-- 列表 -->
<page-content
ref="contentRef"
:content-config="contentConfig"
@add-click="handleAddClick"
@edit-click="handleEditClick"
@export-click="handleExportClick"
@search-click="handleSearchClick"
@toolbar-click="handleToolbarClick"
@operat-click="handleOperatClick"
@filter-change="handleFilterChange"
>
<template #status="scope">
<el-tag :type="scope.row[scope.prop] == 1 ? 'success' : 'info'">
{{ scope.row[scope.prop] == 1 ? "启用" : "禁用" }}
</el-tag>
</template>
<template #options="scope">
{{ returnOptionsLabel(scope.prop, scope.row[scope.prop]) }}
</template>
<template #gender="scope">
<DictLabel v-model="scope.row[scope.prop]" code="gender" />
</template>
<template #mobile="scope">
<el-text>{{ scope.row[scope.prop] }}</el-text>
<copy-button
v-if="scope.row[scope.prop]"
:text="scope.row[scope.prop]"
style="margin-left: 2px"
/>
</template>
</page-content>
<!-- 新增 -->
<page-modal
ref="addModalRef"
@form-data-change="handleFormDataChange"
:modal-config="addModalConfig"
@submit-click="handleSubmitClick"
>
<template #formFooter>
<el-form-item label="" label-width="140">
<p>一经创建无法更改还款方式</p>
</el-form-item>
</template>
</page-modal>
<!-- 编辑 -->
<page-modal
ref="editModalRef"
:modal-config="editModalConfig"
@submit-click="handleSubmitClick"
></page-modal>
</div>
</template>
<script setup lang="ts">
import creditApi from "@/api/order/credit";
import type { IObject, IOperatData } from "@/components/CURD/types";
import usePage from "@/components/CURD/usePage";
import addModalConfig from "./config/add";
import contentConfig from "./config/content";
import editModalConfig from "./config/edit";
import searchConfig from "./config/search";
import { returnOptionsLabel } from "./config/config";
let version = ref<string | number>("");
function handleFormDataChange(type: string, value: string | number) {
version.value = value;
if (type === "version" && value !== "") {
addModalConfig.formItems[5].hidden = false;
return;
}
if (type === "version" && value == "") {
addModalConfig.formItems[5].hidden = true;
}
}
const refVersionFile = ref<any>();
const {
searchRef,
contentRef,
addModalRef,
editModalRef,
handleQueryClick,
handleResetClick,
// handleAddClick,
// handleEditClick,
handleSubmitClick,
handleExportClick,
handleSearchClick,
handleFilterChange,
} = usePage();
// 新增
async function handleAddClick() {
addModalRef.value?.setModalVisible();
// addModalConfig.formItems[2]!.attrs!.data =
}
// 编辑
async function handleEditClick(row: IObject) {
editModalRef.value?.handleDisabled(false);
editModalRef.value?.setModalVisible();
// 根据id获取数据进行填充
// const data = await creditApi.getFormData(row.id);
console.log({ ...row });
editModalRef.value?.setFormData({ ...row, url: [row.url] });
}
1;
// 其他工具栏
function handleToolbarClick(name: string) {
console.log(name);
if (name === "custom1") {
ElMessage.success("点击了自定义1按钮");
}
}
// 其他操作列
async function handleOperatClick(data: IOperatData) {
console.log(data);
}
</script>

View File

@@ -14,7 +14,7 @@
<div class="form"> <div class="form">
<div class="preview_wrap"> <div class="preview_wrap">
<div class="phone_wrap"> <div class="phone_wrap">
<div class="index_bg" v-if="tableActive == 'home'"> <div class="index_bg" v-if="tableActive == 'index_bg'">
<img class="bg" :src="selectItem.value" /> <img class="bg" :src="selectItem.value" />
<div class="menu_wrap"> <div class="menu_wrap">
<div class="menu_wrap_div"> <div class="menu_wrap_div">
@@ -232,7 +232,7 @@ import shopExtendApi from "@/api/account/shopExtend";
export default { export default {
data() { data() {
return { return {
tableActive: "home", tableActive: "",
tableData: [], tableData: [],
selectItem: {}, selectItem: {},
imageUrl: "", imageUrl: "",
@@ -269,7 +269,7 @@ export default {
try { try {
let res = await shopExtendApi.get({}); let res = await shopExtendApi.get({});
this.tableData = res; this.tableData = res;
console.log(this.tableData[0]); this.tableActive = res[0].autoKey;
this.selectItemChange(this.tableActive); this.selectItemChange(this.tableActive);
} catch (error) { } catch (error) {
console.log(error); console.log(error);

View File

@@ -77,6 +77,7 @@
<div>打包费{{ detail.packFee || "-" }}</div> <div>打包费{{ detail.packFee || "-" }}</div>
<div>订单原价{{ detail.originAmount }}</div> <div>订单原价{{ detail.originAmount }}</div>
<div>优惠金额{{ detail.discountAmount }}</div> <div>优惠金额{{ detail.discountAmount }}</div>
<div>积分抵扣{{ detail.pointsDiscountAmount }}</div>
<div> <div>
实收金额 实收金额
<span style="color: red">{{ detail.payAmount }}</span> <span style="color: red">{{ detail.payAmount }}</span>

View File

@@ -30,9 +30,9 @@
<hr /> <hr />
<el-form ref="form" :model="form" label-width="120px" label-position="left"> <el-form ref="form" :model="form" label-width="120px" label-position="left">
<el-form-item label="校验安全密码"> <el-form-item label="校验安全密码">
<el-checkbox v-model="form.isReturn">退款</el-checkbox> <el-checkbox v-model="form.isReturnPwd">退款</el-checkbox>
<el-checkbox v-model="form.isMemberIn">会员充值</el-checkbox> <el-checkbox v-model="form.isMemberInPwd">会员充值</el-checkbox>
<el-checkbox v-model="form.isMemberReturn">会员退款</el-checkbox> <el-checkbox v-model="form.isMemberReturnPwd">会员退款</el-checkbox>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="submitHandles">保存</el-button> <el-button type="primary" @click="submitHandles">保存</el-button>
@@ -43,6 +43,8 @@
<script> <script>
import ShopApi from "@/api/account/shop"; import ShopApi from "@/api/account/shop";
import commonApi from "@/api/account/common";
import { ElMessage } from "element-plus";
export default { export default {
data() { data() {
return { return {
@@ -61,48 +63,48 @@ export default {
async getinfo() { async getinfo() {
const res = await ShopApi.get(); const res = await ShopApi.get();
this.form = res; this.form = res;
this.form.isReturn = this.form.isReturn == 1 ? true : false; this.form.isReturnPwd = this.form.isReturnPwd == 1 ? true : false;
this.form.isMemberIn = this.form.isMemberIn == 1 ? true : false; this.form.isMemberInPwd = this.form.isMemberInPwd == 1 ? true : false;
this.form.isMemberReturn = this.form.isMemberReturn == 1 ? true : false; this.form.isMemberReturnPwd = this.form.isMemberReturnPwd == 1 ? true : false;
}, },
async submitHandle() { async submitHandle() {
if (!this.form.prepareAmount) { if (!this.form.prepareAmount) {
this.$message({ ElMessage({
message: "请输入验证码", message: "请输入验证码",
}); });
return; return;
} }
if (!this.form.password) { if (!this.form.password) {
this.$message({ ElMessage({
message: "请输入密码", message: "请输入密码",
}); });
return; return;
} }
const res = await modfiyUserInfo({ const res = await ShopApi.edit({
id: this.form.id,
code: this.form.prepareAmount, code: this.form.prepareAmount,
pwd: md5(this.form.password), operationPwd: this.form.password,
}); });
console.log(222);
this.form.prepareAmount = ""; this.form.prepareAmount = "";
this.form.password = "******"; this.form.password = "******";
this.disabled = true; this.disabled = true;
this.$message({ ElMessage({
message: "修改成功", message: "修改成功",
type: "success", type: "success",
}); });
}, },
async submitHandles() { async submitHandles() {
const res = await tbShopInfoPUT({ const res = await ShopApi.edit({
// code: this.form.prepareAmount, // code: this.form.prepareAmount,
// id: this.form.id, // id: this.form.id,
// status:this.form.status, // status:this.form.status,
...this.form, ...this.form,
isReturn: this.form.isReturn == true ? 1 : 0, isReturnPwd: this.form.isReturnPwd == true ? 1 : 0,
isMemberIn: this.form.isMemberIn == true ? 1 : 0, isMemberInPwd: this.form.isMemberInPwd == true ? 1 : 0,
isMemberReturn: this.form.isMemberReturn == true ? 1 : 0, isMemberReturnPwd: this.form.isMemberReturnPwd == true ? 1 : 0,
}); });
this.$message({ ElMessage({
message: "修改成功", message: "修改成功",
type: "success", type: "success",
}); });
@@ -112,8 +114,8 @@ export default {
this.disabled = false; this.disabled = false;
}, },
async onSubmit() { async onSubmit() {
const res = await sendMsg(); const res = await commonApi.sms({ type: "editShopInfoOpePwd" });
this.$message({ ElMessage({
message: "发送成功", message: "发送成功",
type: "success", type: "success",
}); });

View File

@@ -9,8 +9,8 @@
<el-form-item> <el-form-item>
<div class="flex gap-20"> <div class="flex gap-20">
<el-button type="primary" @click="getTableData" size="medium">搜索</el-button> <el-button type="primary" @click="getTableData">搜索</el-button>
<el-button @click="noChooseUser" size="medium">不选择用户</el-button> <el-button @click="noChooseUser">不选择用户</el-button>
</div> </div>
</el-form-item> </el-form-item>
</el-form> </el-form>
@@ -49,7 +49,7 @@
<el-table-column label="操作" width="90" fixed="right"> <el-table-column label="操作" width="90" fixed="right">
<template v-slot="scope"> <template v-slot="scope">
<el-button type="primary" size="mini" @click="choose(scope.row)">选择</el-button> <el-button type="primary" size="small" @click="choose(scope.row)">选择</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>

View File

@@ -31,7 +31,15 @@
<div class="score"> <div class="score">
<div class="u-flex u-col-center u-m-t-10"> <div class="u-flex u-col-center u-m-t-10">
<span class="u-font-14 font-bold u-m-r-20">积分抵扣</span> <span class="u-font-14 font-bold u-m-r-20">积分抵扣</span>
<el-radio-group v-model="score.sel" size="small" class=""> <el-radio-group
:disabled="!pointsRes.usable"
v-model="score.sel"
size="small"
class=""
>
<el-radio :value="-1">
<span class="u-font-14">不使用</span>
</el-radio>
<el-radio :value="0"> <el-radio :value="0">
<span class="u-font-14">全部抵扣</span> <span class="u-font-14">全部抵扣</span>
</el-radio> </el-radio>
@@ -39,10 +47,27 @@
<span class="u-font-14">部分抵扣</span> <span class="u-font-14">部分抵扣</span>
</el-radio> </el-radio>
</el-radio-group> </el-radio-group>
<el-input-number
class="u-m-l-10"
v-if="score.sel == 1"
v-model="usePointsNumber"
step-strictly
placeholder="请输入积分抵扣数量"
:min="pointsRes.minDeductionPoints"
:max="pointsRes.maxUsablePoints"
@change="pointsToMoney"
></el-input-number>
</div> </div>
<p class="u-font-14 color-666 u-m-t-10"> <p
class="u-font-14 color-666 u-m-t-10"
v-if="pointsRes.unusableReason && !pointsRes.usable"
>
<span class="color-red">*</span> <span class="color-red">*</span>
<span>积分不足或小于最低使用门槛1</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> </p>
</div> </div>
<div class="u-flex u-col-center u-m-t-20 no-wrap"> <div class="u-flex u-col-center u-m-t-20 no-wrap">
@@ -60,6 +85,51 @@
<el-icon><ArrowDown /></el-icon> <el-icon><ArrowDown /></el-icon>
</div> </div>
</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">
{{ scope.row.type == 1 ? "优惠券" : "商品券" }}
</template>
</el-table-column>
<el-table-column label="商品信息" width="120">
<template v-slot="scope">
<div class="u-flex" v-if="scope.row.type == 2">
<div class="u-flex">
<el-image
:src="scope.row.productImg"
fit="cover"
style="width: 40px; height: 40px"
:preview-src-list="[scope.row.productImg]"
></el-image>
</div>
<div class="u-p-l-10">
<div class="">{{ scope.row.productName }}</div>
<div class="">x{{ scope.row.num || "" }}</div>
</div>
</div>
</template>
</el-table-column>
<el-table-column prop="discountAmount" label="抵扣">
<template v-slot="scope">
<span class="color-red" v-if="scope.row.type == 1">
{{ scope.row.discountAmount }}
</span>
<span class="color-red" v-if="scope.row.type == 2">
{{ returnProDiscount(scope.row, scope.row.index) }}
</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> </template>
</div> </div>
@@ -105,12 +175,16 @@
<span class="u-m-l-10 value">{{ carts.payMoney }}</span> <span class="u-m-l-10 value">{{ carts.payMoney }}</span>
</div> </div>
<div class="u-flex u-m-b-10 u-row-between"> <div class="u-flex u-m-b-10 u-row-between">
<span class="title">优惠券</span> <span class="title">商品优惠券</span>
<span class="u-m-l-10 value">{{ coupDiscount }}</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">{{ fullCouponDiscountAmount }}</span>
</div> </div>
<div class="u-flex u-m-b-10 u-row-between"> <div class="u-flex u-m-b-10 u-row-between">
<span class="title">积分抵扣</span> <span class="title">积分抵扣</span>
<span class="u-m-l-10 value">-{{ orderInfo.pointsDiscountAmount || 0 }}</span> <span class="u-m-l-10 value">-{{ pointsDiscountAmount }}</span>
</div> </div>
<div class="u-flex u-m-b-10 u-row-between"> <div class="u-flex u-m-b-10 u-row-between">
<span class="title">整单改价</span> <span class="title">整单改价</span>
@@ -118,7 +192,7 @@
</div> </div>
<div class="u-flex u-m-b-10 u-row-between"> <div class="u-flex u-m-b-10 u-row-between">
<span class="title">抹零</span> <span class="title">抹零</span>
<span class="u-m-l-10 value">-{{ orderInfo.pointsDiscountAmount || 0 }}</span> <span class="u-m-l-10 value">-{{ 0 }}</span>
</div> </div>
<div class="u-flex u-m-b-10 u-row-between"> <div class="u-flex u-m-b-10 u-row-between">
<span class="title">应付金额</span> <span class="title">应付金额</span>
@@ -127,20 +201,17 @@
</div> </div>
</div> </div>
<!-- 扫码 --> <!-- 扫码 -->
<scanPay <scanPay ref="refScanPay" :order="orderInfo" @confirm="refScanPayConfirm"></scanPay>
ref="refScanPay"
:order="orderInfo"
@paySuccess="paySuccess"
@confirm="refScanPayConfirm"
></scanPay>
<!-- 打折 --> <!-- 打折 -->
<discount ref="refDiscount" @confirm="discountConfirm"></discount> <discount ref="refDiscount" @confirm="discountConfirm"></discount>
<!-- 优惠券 --> <!-- 优惠券 -->
<popup-coupon ref="refCoupon" @confirm="refCouponConfirm"></popup-coupon> <popup-coupon ref="refCoupon" :user="user" @confirm="refCouponConfirm"></popup-coupon>
</div> </div>
</template> </template>
<script setup> <script setup>
import * as quanUtil from "../quan_util.js";
import { useCartsStore } from "@/store/modules/carts"; import { useCartsStore } from "@/store/modules/carts";
const carts = useCartsStore(); const carts = useCartsStore();
@@ -154,10 +225,48 @@ import discount from "./discount.vue";
import { ElLoading } from "element-plus"; import { ElLoading } from "element-plus";
import { ElMessage, ElMessageBox } from "element-plus"; import { ElMessage, ElMessageBox } from "element-plus";
//商品列表
let goodsArr = [];
//优惠券 //优惠券
let $goodsPayPriceMap = {};
const refCoupon = ref(); const refCoupon = ref();
let quansSelArr = ref([]);
function openCoupon() { function openCoupon() {
refCoupon.value.open(); refCoupon.value.open(carts.payMoney, props.orderInfo);
}
//返回商品券抵扣金额
function returnProDiscount(row) {
//相同商品抵扣券数组
const arr = quansSelArr.value.filter((v) => v.type == 2 && v.proId == row.proId);
console.log(arr);
const index = arr.findIndex((v) => v.id == row.id);
const item = goodsArr.find((v) => v.productId == row.proId);
if (index != -1) {
const n = quanUtil.returnProductCoupAllPrice(
$goodsPayPriceMap[row.proId],
index,
row.num,
props.user.id && props.user.isVip
);
return n.toFixed(2);
} else {
return 0;
}
}
function refCouponConfirm(e, goodsPayPriceMap, goodsList) {
goodsArr = goodsList;
usePointsNumber.value = 0;
pointsDiscountAmount.value = 0;
score.sel = -1;
quansSelArr.value = e;
$goodsPayPriceMap = goodsPayPriceMap;
}
function delQuan(row) {
const index = quansSelArr.value.findIndex((v) => v.id == row.id);
if (index != -1) {
quansSelArr.value.splice(index, 1);
}
} }
function couponChange(data) {} function couponChange(data) {}
@@ -172,7 +281,7 @@ function discountConfirm(e) {
Object.assign(checkOrderPay, e); Object.assign(checkOrderPay, e);
if (e.discount) { if (e.discount) {
checkOrderPay.discountAmount = checkOrderPay.discountAmount =
carts.payMoney - (carts.payMoney * (e.discount / 100).toFixed(2)).toFixed(2); carts.payMoney - ((carts.payMoney * (100 - e.discount)) / 100).toFixed(2);
} else { } else {
checkOrderPay.discount = 0; checkOrderPay.discount = 0;
} }
@@ -218,16 +327,43 @@ watch(
); );
//002-获取订单可用积分及抵扣金额(支付页面使用) //002-获取订单可用积分及抵扣金额(支付页面使用)
function pointsInit() { const pointsRes = ref({ usable: false, maxUsablePoints: 0, minDeductionPoints: 0 });
if (!props.user.id) { const usePointsNumber = ref(0);
const orderAmountOrderAmount = computed(() => {
return (carts.payMoney - checkOrderPay.discountAmount).toFixed(2);
});
const pointsDiscountAmount = ref(0);
watch(
() => orderAmountOrderAmount.value,
(newval) => {
pointsInit();
}
);
async function pointsInit() {
if (!props.user.id || score.sel == -1) {
return; return;
} }
PointsApi.calcOrderUsablePoints({ const res = await PointsApi.calcOrderUsablePoints({
userId: props.user.id, userId: props.user.id,
orderAmount: (carts.payMoney - checkOrderPay.discountAmount).toFixed(2), orderAmount: currentpayMoney.value - pointsDiscountAmount.value,
}); });
pointsRes.value = res;
usePointsNumber.value = res.usable ? res.maxUsablePoints : 0;
if (res.usable) {
pointsToMoney();
}
return res;
}
// 根据积分计算可抵扣金额
async function pointsToMoney() {
const res = await PointsApi.calcPointsToMoney({
userId: props.user.id,
orderAmount: currentpayMoney.value - pointsDiscountAmount.value,
points: usePointsNumber.value,
});
pointsDiscountAmount.value = res;
} }
const emits = defineEmits(["chooseUser", "paysuccess"]); const emits = defineEmits(["chooseUser", "paysuccess"]);
function chooseUser() { function chooseUser() {
emits("chooseUser"); emits("chooseUser");
@@ -240,7 +376,7 @@ const coupDiscount = computed(() => {
} }
return total.toFixed(2); return total.toFixed(2);
}); });
const score = ref({ const score = reactive({
list: [], list: [],
sel: 0, sel: 0,
}); });
@@ -249,6 +385,18 @@ const payTypes = reactive({
list: [], list: [],
sel: 0, sel: 0,
}); });
watch(
() => score.sel,
(newval) => {
console.log(newval);
if (newval == -1) {
usePointsNumber.value = 0;
pointsDiscountAmount.value = 0;
} else {
pointsInit();
}
}
);
function canUsePayType(item) { function canUsePayType(item) {
if (currentpayMoney.value * 1 == 0) { if (currentpayMoney.value * 1 == 0) {
return item.payType == "cash" ? false : true; return item.payType == "cash" ? false : true;
@@ -278,16 +426,16 @@ function returnPayParams() {
vipPrice: props.user.id && props.user.isVip ? 1 : 0, vipPrice: props.user.id && props.user.isVip ? 1 : 0,
orderId: props.orderInfo.id, orderId: props.orderInfo.id,
// discountRatio: (checkOrderPay.discount / 100).toFixed(2), // discountRatio: (checkOrderPay.discount / 100).toFixed(2),
discountRatio: 0, discountRatio: checkOrderPay.discount ? checkOrderPay.discount : 0,
seatNum: props.orderInfo.seatNum, seatNum: props.orderInfo.seatNum,
originAmount: carts.payMoney * 1, originAmount: carts.payMoney * 1,
discountAmount: checkOrderPay.discountAmount * 1, discountAmount: !checkOrderPay.discount ? checkOrderPay.discountAmount * 1 : 0,
productCouponDiscountAmount: props.orderInfo.productCouponDiscountAmount || 0, productCouponDiscountAmount: 0,
orderAmount: currentpayMoney.value * 1, orderAmount: currentpayMoney.value * 1,
roundAmount: props.orderInfo.roundAmount, roundAmount: props.orderInfo.roundAmount,
pointsDiscountAmount: props.orderInfo.pointsDiscountAmount || 0, pointsDiscountAmount: pointsDiscountAmount.value * 1,
pointsNum: props.orderInfo.pointsNum, pointsNum: usePointsNumber.value * 1,
fullCouponDiscountAmount: props.orderInfo.fullCouponDiscountAmount || 0, fullCouponDiscountAmount: 0,
}, },
}; };
} }
@@ -387,13 +535,34 @@ async function payOrder(payType, isScan) {
loading.close(); loading.close();
} }
} }
//满减优惠券
const fullCouponDiscountAmount = computed(() => {
return quansSelArr.value
.reduce((pre, cur) => {
return pre + cur.discountAmount;
}, 0)
.toFixed(2);
});
//商品券抵扣金额
const productCouponDiscountAmount = computed(() => {
let index = -1;
return quansSelArr.value.reduce((pre, cur) => {
index++;
return pre + returnProDiscount(cur, index) * 1;
}, 0);
});
//应付金额 //应付金额
const currentpayMoney = computed(() => { const currentpayMoney = computed(() => {
if (checkOrderPay.discount) { if (checkOrderPay.discount) {
return (carts.payMoney * (checkOrderPay.discount / 100)).toFixed(2); return (carts.payMoney * (checkOrderPay.discount / 100)).toFixed(2);
} }
return (carts.payMoney - checkOrderPay.discountAmount).toFixed(2); return (
carts.payMoney -
productCouponDiscountAmount.value -
fullCouponDiscountAmount.value -
checkOrderPay.discountAmount -
pointsDiscountAmount.value
).toFixed(2);
}); });
watch( watch(
() => currentpayMoney.value, () => currentpayMoney.value,
@@ -405,7 +574,6 @@ watch(
); );
onMounted(() => { onMounted(() => {
getPaytype(); getPaytype();
pointsInit();
}); });
defineExpose({ defineExpose({
nowPayClick, nowPayClick,

View File

@@ -14,23 +14,23 @@
<template v-slot="scope"> <template v-slot="scope">
<el-checkbox <el-checkbox
@change="fullReductionCouponClick(scope.row)" @change="fullReductionCouponClick(scope.row)"
:value="scope.row.id == fullReductionCouponSel.id" :model-value="scope.row.id == fullReductionCouponSel.id"
></el-checkbox> ></el-checkbox>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column type="index" label="#"></el-table-column> <el-table-column type="index" label="#"></el-table-column>
<el-table-column prop="name" label="券名称"></el-table-column> <el-table-column prop="name" label="券名称"></el-table-column>
<el-table-column label="券类型" width="80"> <!-- <el-table-column label="券类型" width="80">
<template v-slot="scope"> <template v-slot="scope">
{{ scope.row.type == 1 ? "优惠券" : "商品券" }} {{ scope.row.type == 1 ? "优惠券" : "商品券" }}
</template> </template>
</el-table-column> </el-table-column> -->
<el-table-column prop="discountAmount" label="抵扣"> <el-table-column prop="discountAmount" label="抵扣">
<template v-slot="scope"> <template v-slot="scope">
<span class="color-red">{{ scope.row.discountAmount }}</span> <span class="color-red">{{ scope.row.discountAmount }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="discountAmount" label="限制" width="120"> <el-table-column prop="discountAmount" label="限制" width="180">
<template v-slot="scope"> <template v-slot="scope">
<div class="u-flex"> <div class="u-flex">
<span>支付满</span> <span>支付满</span>
@@ -52,31 +52,31 @@
:data="quans.productCoupon" :data="quans.productCoupon"
style="width: 100%" style="width: 100%"
> >
<el-table-column> <el-table-column width="80">
<template v-slot="scope"> <template v-slot="scope">
<el-checkbox <el-checkbox
@change="productCouponClick(scope.row)" @change="productCouponClick(scope.row)"
:value="scope.row.checked" :model-value="scope.row.checked"
></el-checkbox> ></el-checkbox>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column type="index" width="50" label="#"></el-table-column> <el-table-column type="index" width="50" label="#"></el-table-column>
<el-table-column prop="name" label="券名称"></el-table-column> <el-table-column prop="name" label="券名称"></el-table-column>
<el-table-column label="商品信息" width="120"> <el-table-column label="商品信息" width="220">
<template v-slot="scope"> <template v-slot="scope">
<div class="u-flex"> <div class="u-flex">
<div class="u-flex"> <div class="u-flex">
<el-image <el-image
:src="scope.row.productCover" :src="scope.row.productImg"
fit="cover" fit="cover"
style="width: 40px; height: 40px" style="width: 40px; height: 40px"
:preview-src-list="[scope.row.productCover]" :preview-src-list="[scope.row.productImg]"
></el-image> ></el-image>
</div> </div>
<div class="u-p-l-10"> <div class="u-p-l-10">
<div class="">{{ scope.row.productName }}</div> <div class="">{{ scope.row.productName }}</div>
<div class="">x{{ scope.row.num || "" }}</div> <div class="">x{{ scope.row.num || 1 }}</div>
</div> </div>
</div> </div>
</template> </template>
@@ -88,11 +88,11 @@
</span> </span>
</template> </template>
</el-table-column> --> </el-table-column> -->
<el-table-column label="券类型"> <!-- <el-table-column label="券类型">
<template v-slot="scope"> <template v-slot="scope">
{{ scope.row.type == 1 ? "优惠券" : "商品券" }} {{ scope.row.type == 1 ? "优惠券" : "商品券" }}
</template> </template>
</el-table-column> </el-table-column> -->
<el-table-column prop="useRestrictions" label="描述"></el-table-column> <el-table-column prop="useRestrictions" label="描述"></el-table-column>
<!-- <el-table-column prop="useRestrictions" label="是否可用"> <!-- <el-table-column prop="useRestrictions" label="是否可用">
<template v-slot="scope"> <template v-slot="scope">
@@ -117,15 +117,15 @@
<div class="u-flex" v-if="scope.row.type == 2"> <div class="u-flex" v-if="scope.row.type == 2">
<div class="u-flex"> <div class="u-flex">
<el-image <el-image
:src="scope.row.productCover" :src="scope.row.productImg"
fit="cover" fit="cover"
style="width: 40px; height: 40px" style="width: 40px; height: 40px"
:preview-src-list="[scope.row.productCover]" :preview-src-list="[scope.row.productImg]"
></el-image> ></el-image>
</div> </div>
<div class="u-p-l-10"> <div class="u-p-l-10">
<div class="">{{ scope.row.productName }}</div> <div class="">{{ scope.row.productName }}</div>
<div class="">x{{ scope.row.num || "" }}</div> <div class="">x{{ scope.row.num || 1 }}</div>
</div> </div>
</div> </div>
</template> </template>
@@ -143,7 +143,7 @@
<el-table-column prop="useRestrictions" label="描述"></el-table-column> <el-table-column prop="useRestrictions" label="描述"></el-table-column>
<el-table-column prop="useRestrictions" label=""> <el-table-column prop="useRestrictions" label="">
<template v-slot="scope"> <template v-slot="scope">
<el-button type="danger" size="mini" @click="delQuan(scope.row)">删除</el-button> <el-button type="danger" size="small" @click="delQuan(scope.row)">删除</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@@ -166,14 +166,17 @@
</div> </div>
</div> </div>
<div class="u-flex u-row-center u-m-t-50"> <div class="u-flex u-row-center u-m-t-50">
<el-button size="medium" @click="close">取消</el-button> <el-button size="large" @click="close">取消</el-button>
<el-button size="medium" type="primary" @click="confirm">确定</el-button> <el-button size="large" type="primary" @click="confirm">确定</el-button>
</div> </div>
</div> </div>
</div> </div>
</el-dialog> </el-dialog>
</template> </template>
<script setup> <script setup>
import couponApi from "@/api/account/coupon";
import { ElMessageBox } from "element-plus";
import * as quanUtil from "../quan_util.js";
const props = defineProps({ const props = defineProps({
title: { title: {
type: String, type: String,
@@ -183,7 +186,7 @@ const props = defineProps({
type: Array, type: Array,
default: [], default: [],
}, },
vipUser: { user: {
type: Object, type: Object,
default: () => { default: () => {
return { return {
@@ -196,7 +199,6 @@ function tabClick() {}
const state = reactive({ const state = reactive({
discount: 1, discount: 1,
orderPrice: 0,
fullReductionCouponSel: { fullReductionCouponSel: {
id: "", id: "",
}, },
@@ -216,36 +218,210 @@ const state = reactive({
const { const {
discount, discount,
orderPrice,
fullReductionCouponSel, fullReductionCouponSel,
quansSelArr, quansSelArr,
quans, quans,
currentRow, currentRow,
multipleSelection, multipleSelection,
fullReductionCouponSelId,
activeName, activeName,
form, form,
show, show,
isSetProductCoup, isSetProductCoup,
} = toRefs(state); } = toRefs(state);
const AllCouponPrice = computed(() => {
return 0; let orderPrice = ref(0);
}); let $originFullReductionCoupon = [];
const payPrice = computed(() => { //可以抵扣的商品列表
return 0; let canDikouGoodsArr = [];
}); //商品数量从0到n每一个对应的价格
function open() { let $goodsPayPriceMap = {};
let goodsArr = [];
function open(money, orderInfo) {
let arr = [];
for (let i in orderInfo.detailMap) {
arr.push(...orderInfo.detailMap[i]);
}
goodsArr = arr;
$goodsPayPriceMap = quanUtil.returnGoodsPayPriceMap(goodsArr || []);
canDikouGoodsArr = quanUtil.returnNewGoodsList(goodsArr);
console.log(canDikouGoodsArr);
getcoup();
orderPrice.value = money;
show.value = true; show.value = true;
} }
async function getcoup() {
const res = await couponApi.findCoupon({ shopUserId: props.user.id });
quans.value.fullReductionCoupon = res.filter(
(v) => v.type == 1 && orderPrice.value * 1 >= v.fullAmount * 1
);
quans.value.productCoupon = res
.filter((v) => v.type == 2 && canDikouGoodsArr.find((goods) => v.proId == goods.productId))
.map((v) => {
const findGoods = goodsArr.find((goods) => goods.productId == v.proId);
return {
...v,
productImg: findGoods ? findGoods.productImg : "",
productName: findGoods ? findGoods.productName : "",
};
});
}
function fullReductionCouponClick(row) {
if (row.id == fullReductionCouponSel.value.id) {
fullReductionCouponSel.value = { id: "" };
quansSelArr.value.splice(0, 1);
return;
}
const dikouQuan = quansSelArr.value[0];
fullReductionCouponSel.value = row;
if (dikouQuan && dikouQuan.type == 1) {
quansSelArr.value[0] = row;
} else {
quansSelArr.value.unshift(row);
}
if (!fullReductionCouponSel.value.id) {
return;
}
}
const AllCouponPrice = computed(() => {
return quanUtil.returnCouponAllPrice(quansSelArr.value, canDikouGoodsArr, props.user);
});
const payPrice = computed(() => {
return (orderPrice.value - AllCouponPrice.value).toFixed(2);
});
function productCouponClick(item) {
if (!item.use) {
return;
}
const hasSelNum = quansSelArr.value
.filter((v) => v.type == 2 && v.proId == item.proId)
.reduce((a, b) => {
return a + (b.num || 1);
}, 0);
console.log($goodsPayPriceMap[item.proId]);
const maxSelNum = $goodsPayPriceMap[item.proId].length;
const coupMaxUseNum = Math.min(item.num || 1, maxSelNum - hasSelNum);
const canUseNum = Math.min(maxSelNum, coupMaxUseNum);
console.log("maxSelNum", maxSelNum);
console.log("coupMaxUseNum", coupMaxUseNum);
console.log("canUseNum", canUseNum);
if (!item.checked && canUseNum <= 0) {
return ElMessage.error("购物车该商品券可使用最大数量为" + maxSelNum);
}
if (fullReductionCouponSel.value.id && !item.checked) {
const goodsQuan = quans.value.productCoupon.filter((v) => v.checked);
const fullReductionCoupon = fullReductionCouponSel.value.id
? [fullReductionCouponSel.value]
: [];
let coupArr = [...goodsQuan, { ...item, num: canUseNum }];
const payPrice =
orderPrice.value - quanUtil.returnCouponAllPrice(coupArr, canDikouGoodsArr, props.user);
console.log(payPrice);
if (payPrice <= 0) {
return ElMessageBox.confirm(
"选择该商品券后支付金额将为0继续选择将取消选择的满减券",
"提示",
{
confirmButtonText: "继续选择",
cancelButtonText: "取消",
type: "warning",
}
)
.then(() => {
fullReductionCouponSel.value = {
id: "",
};
quansSelArr.value.splice(0, 1);
})
.catch(() => {});
}
if (fullReductionCouponSel.value.fullAmount > payPrice) {
ElMessageBox.confirm(
"选择该商品券后将不满足选择抵扣券的最低满减需求,继续选择将取消选择的满减券",
"提示",
{
confirmButtonText: "继续选择",
cancelButtonText: "取消",
type: "warning",
}
)
.then(() => {
fullReductionCouponSel.value = {
id: "",
};
})
.catch(() => {
item.checked = false;
const index = quansSelArr.value.findIndex((v) => v.id == item.id);
quansSelArr.value.splice(index, 1);
});
}
}
item.checked = !item.checked;
if (!item.checked) {
const index = quansSelArr.value.findIndex((v) => v.id == item.id);
quansSelArr.value.splice(index, 1);
} else {
quansSelArr.value.push({ ...item, num: canUseNum });
}
const CheckedArr = quans.value.productCoupon.filter((v) => v.checked);
if (CheckedArr.length <= 0) {
return quans.value.productCoupon.map((v) => {
v.use = true;
});
}
const noCheckedArr = quans.value.productCoupon.filter((v) => !v.checked);
noCheckedArr.map((v) => {
v.use = quanUtil.returnCoupCanUse(canDikouGoodsArr, v, CheckedArr);
});
}
//返回商品券抵扣金额
function returnProDiscount(row) {
//相同商品抵扣券数组
const arr = quansSelArr.value.filter((v) => v.type == 2 && v.proId == row.proId);
const index = arr.findIndex((v) => v.id == row.id);
const item = goodsArr.find((v) => v.productId == row.proId);
if (index != -1) {
const n = quanUtil.returnProductCoupAllPrice(
$goodsPayPriceMap[row.proId],
index,
row.num,
props.user.id && props.user.isVip
);
return n.toFixed(2);
} else {
return 0;
}
}
//删除选中的优惠券
function delQuan(row) {
const index = quansSelArr.value.findIndex((item) => item.id == row.id);
if (row.type == 2 && index != -1) {
quansSelArr.value.splice(index, 1);
const proIndex = quans.value.productCoupon.findIndex((v) => v.id == row.id);
quans.value.productCoupon[proIndex].checked = false;
}
if (row.type == 1 && index != -1) {
fullReductionCouponSel.value = { id: "" };
quansSelArr.value.splice(0, 1);
}
}
function close() { function close() {
show.value = false; show.value = false;
} }
const emits = defineEmits(["confirm"]); const emits = defineEmits(["confirm"]);
function confirm() { function reset() {
emits("confirm"); quansSelArr.value = [];
fullReductionCouponSel.value = { id: "" };
}
function confirm() {
emits("confirm", [...quansSelArr.value], $goodsPayPriceMap, goodsArr);
close();
} }
function reset() {}
defineExpose({ defineExpose({
close, close,
open, open,

View File

@@ -1,250 +1,247 @@
export function isTui(item) { export function isTui(item) {
return item.status == 'return' || item.status == 'refund' || item.status == 'refunding' return item.status == "return" || item.status == "refund" || item.status == "refunding";
} }
//是否使用会员价 //是否使用会员价
export function isUseVipPrice(vipUser,goods){ export function isUseVipPrice(vipUser, goods) {
return vipUser.id&&vipUser.isVip&&goods.isMember return vipUser.id && vipUser.isVip;
} }
//计算商品券优惠价格 //计算商品券优惠价格
export function returnProductCouponPrice(coup, goodsArr, vipUser) { export function returnProductCouponPrice(coup, goodsArr, vipUser) {
const item = goodsArr.find(v => v.productId == coup.proId); const item = goodsArr.find((v) => v.productId == coup.proId);
if (!item) { if (!item) {
return 0 return 0;
} }
const memberPrice = item.memberPrice ? item.memberPrice : item.price; const memberPrice = item.memberPrice ? item.memberPrice : item.price;
const price = item ? (isUseVipPrice(vipUser,item) ? memberPrice : item.price) : 0; const price = item ? (isUseVipPrice(vipUser, item) ? memberPrice : item.price) : 0;
return price * coup.num return price * coup.num;
} }
//返回新的商品列表,过滤掉退菜的,退单的商品 //返回新的商品列表,过滤掉退菜的,退单的商品
export function returnNewGoodsList(arr) { export function returnNewGoodsList(arr) {
let goodsMap = {} let goodsMap = {};
return arr.filter(v => !isTui(v)) return arr.filter((v) => !isTui(v));
} }
//根据当前购物车商品以及数量,已选券对应商品数量,判断该商品券是否可用 //根据当前购物车商品以及数量,已选券对应商品数量,判断该商品券是否可用
export function returnCoupCanUse(goodsArr = [], coup, selCoupArr = []) { export function returnCoupCanUse(goodsArr = [], coup, selCoupArr = []) {
// if(!coup.use){ // if(!coup.use){
// return false // return false
// } // }
const findGoods = goodsArr.filter(v => v.productId == coup.proId) const findGoods = goodsArr.filter((v) => v.productId == coup.proId);
if (!findGoods.length) { if (!findGoods.length) {
return false return false;
} }
const findGoodsTotalNumber = findGoods.reduce((prve, cur) => { const findGoodsTotalNumber = findGoods.reduce((prve, cur) => {
return prve + cur.num * 1 return prve + cur.num * 1;
}, 0) }, 0);
const selCoupNumber = selCoupArr.filter(v => v.proId == coup.proId).reduce((prve, cur) => { const selCoupNumber = selCoupArr
return prve + cur.num * 1 .filter((v) => v.proId == coup.proId)
}, 0) .reduce((prve, cur) => {
if (selCoupNumber >= findGoodsTotalNumber) { return prve + cur.num * 1;
return false }, 0);
} if (selCoupNumber >= findGoodsTotalNumber) {
console.log(selCoupNumber,findGoodsTotalNumber); return false;
return findGoodsTotalNumber < selCoupNumber ? false : true }
return findGoodsTotalNumber < selCoupNumber ? false : true;
} }
//查找购物车商品根据购物车商品数据返回商品券信息(抵扣价格以及是否满足可用需求) //查找购物车商品根据购物车商品数据返回商品券信息(抵扣价格以及是否满足可用需求)
export function returnProductCoupon(coup, goodsArr, vipUser, selCoupArr = []) { export function returnProductCoupon(coup, goodsArr, vipUser, selCoupArr = []) {
const newGoodsArr = returnNewGoodsList(goodsArr) const newGoodsArr = returnNewGoodsList(goodsArr);
const item = newGoodsArr.find(v => v.productId == coup.proId); const item = newGoodsArr.find((v) => v.productId == coup.proId);
if (!item) { if (!item) {
return { return {
...coup, ...coup,
discountAmount: 0, discountAmount: 0,
use: false use: false,
} };
} }
const memberPrice = item.memberPrice ? item.memberPrice : item.price; const memberPrice = item.memberPrice ? item.memberPrice : item.price;
const price = item ? (isUseVipPrice(vipUser,item) ? memberPrice : item.price) : 0; const price = item ? (isUseVipPrice(vipUser, item) ? memberPrice : item.price) : 0;
const discountAmount = (price * coup.num).toFixed(2) const discountAmount = (price * coup.num).toFixed(2);
console.log(discountAmount); // const canUse = !coup.use ? false : (discountAmount > 0 && returnCoupCanUse(goodsArr, coup, selCoupArr))
// const canUse=discountAmount>0
// const canUse = !coup.use ? false : (discountAmount > 0 && returnCoupCanUse(goodsArr, coup, selCoupArr)) const canUse = coup.use;
// const canUse=discountAmount>0 return {
const canUse=coup.use ...coup,
return { discountAmount: discountAmount,
...coup, use: canUse,
discountAmount: discountAmount, };
use: canUse
}
} }
/** /**
* 根据购物车商品计算商品券抵扣价格以及是否满足可用需求 * 根据购物车商品计算商品券抵扣价格以及是否满足可用需求
* 1.商品券对应商品数量大于购物车对应商品数量不可用 * 1.商品券对应商品数量大于购物车对应商品数量不可用
* 2.未在购物车找到相关商品不可用 * 2.未在购物车找到相关商品不可用
* @param {*} coupArr * @param {*} coupArr
* @param {*} goodsArr * @param {*} goodsArr
* @param {*} vipUser * @param {*} vipUser
* @returns * @returns
*/ */
export function returnProductAllCoup(coupArr, goodsArr, vipUser) { export function returnProductAllCoup(coupArr, goodsArr, vipUser) {
return coupArr.map((v) => { return coupArr.map((v) => {
return returnProductCoupon(v, goodsArr, vipUser) return returnProductCoupon(v, goodsArr, vipUser);
}) });
} }
//返回商品实际支付价格 //返回商品实际支付价格
export function returnProductPayPrice(goods,vipUser){ export function returnProductPayPrice(goods, vipUser) {
const memberPrice = goods.memberPrice ? goods.memberPrice : goods.price; const memberPrice = goods.memberPrice ? goods.memberPrice : goods.price;
const price = isUseVipPrice(vipUser,goods) ? memberPrice : goods.price; const price = isUseVipPrice(vipUser, goods) ? memberPrice : goods.price;
return price return price;
} }
//返回商品券抵扣的商品价格 //返回商品券抵扣的商品价格
export function returnProductCoupAllPrice(productPriceArr,startIndex,num,isMember=true){ export function returnProductCoupAllPrice(productPriceArr, startIndex, num = 1, isVip = true) {
console.log(productPriceArr); num = num || 1;
return productPriceArr.slice(startIndex,startIndex+num).reduce((prve,cur)=>{ return productPriceArr.slice(startIndex, startIndex + num).reduce((prve, cur) => {
let curPrice=0 let curPrice = 0;
if(typeof cur==='object'){ if (typeof cur === "object") {
curPrice=isMember?cur.memberPrice*1:cur.price curPrice = isVip ? cur.memberPrice * 1 : cur.price;
}else{ } else {
curPrice=cur*1 curPrice = cur * 1;
} }
return prve+curPrice
},0) return prve + curPrice;
}, 0);
} }
//返回商品券可抵扣的商品数量 //返回商品券可抵扣的商品数量
export function returnProductCanUseNum(productPriceArr,startIndex,num){ export function returnProductCanUseNum(productPriceArr, startIndex, num) {
console.log(productPriceArr); let n = 0;
console.log(num); for (let i = 0; i < num; i++) {
let n=0; if (productPriceArr[startIndex * 1 + i]) {
for(let i=0;i<num;i++){ n += 1;
if(productPriceArr[startIndex*1+i]){ } else {
n+=1 break;
console.log(n); }
}else{ }
break return n;
}
}
return n
} }
//返回同类商品券在同类商品价格数组里的开始位置 //返回同类商品券在同类商品价格数组里的开始位置
export function returnProCoupStartIndex(coupArr,index){ export function returnProCoupStartIndex(coupArr, index) {
return coupArr.slice(0,index).reduce((prve,cur)=>{ return coupArr.slice(0, index).reduce((prve, cur) => {
return prve+cur.num*1 return prve + cur.num * 1;
},0) }, 0);
} }
//返回商品数量从0到n每一个对应的价格对照表 //返回商品数量从0到n每一个对应的价格对照表
export function returnGoodsPayPriceMap(goodsArr){ export function returnGoodsPayPriceMap(goodsArr) {
return goodsArr.reduce((prve,cur)=>{ return goodsArr.reduce((prve, cur) => {
if(!prve.hasOwnProperty(cur.productId)){ if (!prve.hasOwnProperty(cur.productId)) {
prve[cur.productId]=[] prve[cur.productId] = [];
} }
const arr=new Array(cur.num).fill(cur).map(v=>{ const arr = new Array(cur.num).fill(cur).map((v) => {
return { return {
memberPrice:v.memberPrice?v.memberPrice:v.price, memberPrice: v.memberPrice ? v.memberPrice : v.price,
price:v.price price: v.price,
} };
}) });
prve[cur.productId].push(...arr) prve[cur.productId].push(...arr);
return prve return prve;
},{}) }, {});
} }
//计算商品券总优惠价格 //计算商品券总优惠价格
export function returnProductCouponAllPrice(coupArr, goodsArr, vipUser) { export function returnProductCouponAllPrice(coupArr, goodsArr, vipUser) {
if (coupArr.length == 0) { if (coupArr.length == 0) {
return 0; return 0;
} }
//商品分组 //商品分组
const goodsMap={} const goodsMap = {};
//商品数量从0到n每一个对应的价格 //商品数量从0到n每一个对应的价格
const goodsPayPriceMap={} const goodsPayPriceMap = {};
//商品券分组 //商品券分组
let coupMap={} let coupMap = {};
for(let i in coupArr){ for (let i in coupArr) {
const coup=coupArr[i] const coup = coupArr[i];
if(coupMap.hasOwnProperty(coup.proId)){ if (coupMap.hasOwnProperty(coup.proId)) {
coupMap[coup.proId].push(coup) coupMap[coup.proId].push(coup);
}else{ } else {
coupMap[coup.proId]=[coup] coupMap[coup.proId] = [coup];
} }
} }
let total=0 let total = 0;
for(let key in coupMap){ for (let key in coupMap) {
const arr=coupMap[key] const arr = coupMap[key];
for(let i in arr){ for (let i in arr) {
const coup=arr[i] const coup = arr[i];
if(!goodsMap.hasOwnProperty(coup.proId)){ if (!goodsMap.hasOwnProperty(coup.proId)) {
goodsMap[coup.proId]=goodsArr.filter(v=>v.productId==coup.proId).map(v=>{ goodsMap[coup.proId] = goodsArr
return { .filter((v) => v.productId == coup.proId)
...v, .map((v) => {
payPrice:returnProductPayPrice(v,vipUser) return {
} ...v,
}).sort((a,b)=>{ payPrice: returnProductPayPrice(v, vipUser),
const aPrice=a.payPrice };
const bPrice=b.payPrice })
return aPrice-bPrice .sort((a, b) => {
}) const aPrice = a.payPrice;
goodsPayPriceMap[coup.proId]=goodsMap[coup.proId].reduce((prve,cur)=>{ const bPrice = b.payPrice;
const arr=new Array(cur.num).fill(cur.payPrice) return aPrice - bPrice;
console.log(arr); });
prve.push(...arr) goodsPayPriceMap[coup.proId] = goodsMap[coup.proId].reduce((prve, cur) => {
return prve const arr = new Array(cur.num).fill(cur.payPrice);
},[]) prve.push(...arr);
} return prve;
const proCoupStartIndex=returnProCoupStartIndex(arr,i) }, []);
console.log(proCoupStartIndex); }
const coupNum=Math.min(goodsPayPriceMap[coup.proId].length,coup.num) const proCoupStartIndex = returnProCoupStartIndex(arr, i);
console.log(coupNum); const coupNum = Math.min(goodsPayPriceMap[coup.proId].length, coup.num);
total+=returnProductCoupAllPrice(goodsPayPriceMap[coup.proId],proCoupStartIndex,coupNum) total += returnProductCoupAllPrice(goodsPayPriceMap[coup.proId], proCoupStartIndex, coupNum);
} }
} }
return total.toFixed(2);
return total.toFixed(2);
} }
//计算满减券总优惠价格 //计算满减券总优惠价格
export function returnFullReductionCouponAllPrice(coupArr) { export function returnFullReductionCouponAllPrice(coupArr) {
if (coupArr.length == 0) { if (coupArr.length == 0) {
return 0; return 0;
} }
return coupArr.filter(v => v.type == 1).reduce((a, b) => { return coupArr
const price = b.discountAmount .filter((v) => v.type == 1)
return a + price; .reduce((a, b) => {
}, 0).toFixed(2); const price = b.discountAmount;
return a + price;
}, 0)
.toFixed(2);
} }
//计算优惠券总价格 //计算优惠券总价格
export function returnCouponAllPrice(coupArr, goodsArr, vipUser) { export function returnCouponAllPrice(coupArr, goodsArr, vipUser) {
const poductAllprice = returnProductCouponAllPrice(coupArr, goodsArr, vipUser) const poductAllprice = returnProductCouponAllPrice(coupArr, goodsArr, vipUser);
const pointAllPrice = returnFullReductionCouponAllPrice(coupArr) const pointAllPrice = returnFullReductionCouponAllPrice(coupArr);
return (poductAllprice * 1 + pointAllPrice * 1).toFixed(2); return (poductAllprice * 1 + pointAllPrice * 1).toFixed(2);
} }
//返回当前满减券列表可用状态 //返回当前满减券列表可用状态
export function returnCanUseFullReductionCoupon(coupArr, payPrice, selCoup) { export function returnCanUseFullReductionCoupon(coupArr, payPrice, selCoup) {
return coupArr.map(v => { return coupArr
if (v.id == selCoup.id) { .map((v) => {
return {...v,use:true} if (v.id == selCoup.id) {
} return { ...v, use: true };
const isfullAmount = payPrice*1 >= v.fullAmount * 1 }
if(payPrice<=0){ const isfullAmount = payPrice * 1 >= v.fullAmount * 1;
return { if (payPrice <= 0) {
...v, return {
use: false ...v,
} use: false,
} };
return { }
...v, return {
use: v.use && isfullAmount ...v,
} use: v.use && isfullAmount,
}).filter(v => v.use) };
})
.filter((v) => v.use);
} }
//根据商品数量还有商品券数量返回优惠券可以使用的数量数组 //根据商品数量还有商品券数量返回优惠券可以使用的数量数组
export function returnCanUseNumProductCoup(coupArr,){ export function returnCanUseNumProductCoup(coupArr) {
let productCoup = coupArr.filter(v => v.type == 2) let productCoup = coupArr.filter((v) => v.type == 2);
//商品券分组 //商品券分组
let coupMap={} let coupMap = {};
for(let i in productCoup){ for (let i in productCoup) {
const coup=productCoup[i] const coup = productCoup[i];
if(coupMap.hasOwnProperty(coup.proId)){ if (coupMap.hasOwnProperty(coup.proId)) {
coupMap[coup.proId].push(coup) coupMap[coup.proId].push(coup);
}else{ } else {
coupMap[coup.proId]=[coup] coupMap[coup.proId] = [coup];
} }
} }
return arr return arr;
} }

View File

@@ -143,7 +143,7 @@
> >
<el-button <el-button
type="primary" type="primary"
:disabled="!item.tableId || item.status === 'closed'" :disabled="!item.tableCode || item.status === 'closed'"
@click="diancanShow(item)" @click="diancanShow(item)"
> >
点餐 点餐
@@ -334,7 +334,37 @@ async function areainit() {
return prve; return prve;
}, {}); }, {});
} }
async function diancanShow(item, key) {
// if (key === "isPayOrder") {
// const canShoukuan = await hasPermission("允许收款");
// if (!canShoukuan) {
// return;
// }
// }
// const canXiadan = await hasPermission("允许下单");
// if (!canXiadan) {
// return;
// }
// if (key === "subscribe") {
// this.$refs.subscribe.show();
// return;
// }
// key isAddGoods 加菜
// key isPayOrder 结账
this.selTable = item;
if (this.shopInfo.isTableFee) {
// 免餐位费
this.toInstead({ num: 0, key });
// this.$refs.diancan.open(item, key, '');
return;
}
const num = item.useNum || 0;
if (item.useNum <= 0) {
return this.$refs.refChooseDinersNumber.open();
}
this.toInstead({ num: num, key });
// this.$refs.diancan.open(item, key, num);
}
const tabClick = (tab) => { const tabClick = (tab) => {
console.log(tab); console.log(tab);
}; };