优化更新
This commit is contained in:
@@ -69,7 +69,7 @@
|
||||
"vue-clipboard3": "^2.0.0",
|
||||
"vue-i18n": "^11.1.0",
|
||||
"vue-router": "^4.5.0",
|
||||
"ysk-utils": "^1.0.35"
|
||||
"ysk-utils": "^1.0.50"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "^19.7.1",
|
||||
|
||||
@@ -54,6 +54,21 @@ const API = {
|
||||
data
|
||||
});
|
||||
},
|
||||
// 批量台桌配置
|
||||
shopTabBatch(data: any) {
|
||||
return request({
|
||||
url: `${baseURL}/batch`,
|
||||
method: "PUT",
|
||||
data
|
||||
});
|
||||
},
|
||||
// 获取清台配置信息
|
||||
tableCurrentState() {
|
||||
return request({
|
||||
url: `${baseURL}/currentState`,
|
||||
method: "GET"
|
||||
});
|
||||
},
|
||||
}
|
||||
export default API;
|
||||
/**
|
||||
|
||||
30
src/api/market/limitTimeDiscount.js
Normal file
30
src/api/market/limitTimeDiscount.js
Normal file
@@ -0,0 +1,30 @@
|
||||
import request from "@/utils/request";
|
||||
import { Market_BaseUrl } from "@/api/config";
|
||||
const API = {
|
||||
// 获取当前可用限时折扣
|
||||
getLimitTimeDiscount(params) {
|
||||
return request({
|
||||
url: `${Market_BaseUrl}/admin/limitTimeDiscount`,
|
||||
method: "get",
|
||||
params
|
||||
});
|
||||
},
|
||||
// 满减活动配置
|
||||
getDiscountActivity(params) {
|
||||
return request({
|
||||
url: `${Market_BaseUrl}/admin/discountActivity`,
|
||||
method: "get",
|
||||
params
|
||||
});
|
||||
},
|
||||
// 根据用户id获取新客立减金额,返回null代表不可用
|
||||
getConsumeDiscount(params) {
|
||||
return request({
|
||||
url: `${Market_BaseUrl}/admin/consumeDiscount/getDiscountByUserId`,
|
||||
method: "get",
|
||||
params
|
||||
});
|
||||
},
|
||||
}
|
||||
export default API;
|
||||
|
||||
3
src/assets/icons/分销中心.svg
Normal file
3
src/assets/icons/分销中心.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M17.54 18.8H13.74C13.4 18.84 13.06 18.7 12.8 18.46C12.56 18.22 12.44 17.88 12.46 17.52V13.7C12.42 13.36 12.56 13.02 12.8 12.76C13.04 12.52 13.38 12.4 13.74 12.42H15V11.8C15 11.26 14.9 10.52 14.36 10.52H5.46003C4.92003 10.52 4.82003 11.26 4.82003 11.8V12.44H6.10003C6.44003 12.4 6.78003 12.54 7.04003 12.78C7.28003 13.02 7.40003 13.36 7.38003 13.72V17.54C7.42003 17.88 7.28003 18.22 7.04003 18.48C6.80003 18.72 6.46003 18.84 6.10003 18.82H2.30003C1.96003 18.86 1.62003 18.72 1.36003 18.48C1.12003 18.24 1.00003 17.9 1.02003 17.54V13.7C0.980025 13.36 1.12003 13.02 1.36003 12.76C1.60003 12.52 1.94003 12.4 2.30003 12.42H3.58003V10.52C3.58003 9.46 4.42003 9.24 5.48003 9.24H9.30003V7.34H10.58V9.24H14.4C15.48 9.24 16.3 9.44 16.3 10.52V12.42H17.58C17.92 12.38 18.26 12.52 18.52 12.76C18.76 13 18.88 13.34 18.86 13.7V17.52C18.9 17.86 18.76 18.2 18.52 18.46C18.24 18.7 17.9 18.82 17.54 18.8ZM11.82 7.36H8.02003C7.32003 7.36 6.74003 6.8 6.74003 6.08V2.28C6.74003 1.58 7.30003 1 8.02003 1H11.84C12.54 1 13.12 1.56 13.12 2.28V6.1C13.1 6.78 12.52 7.36 11.82 7.36ZM11.82 2.9C11.82 2.54 11.54 2.26 11.18 2.26H8.64003C8.28003 2.26 8.00003 2.54 8.00003 2.9V5.44C8.00003 5.8 8.28003 6.08 8.64003 6.08H11.18C11.54 6.08 11.82 5.8 11.82 5.44V2.9Z" fill="#999999"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
12
src/assets/icons/通知.svg
Normal file
12
src/assets/icons/通知.svg
Normal file
@@ -0,0 +1,12 @@
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_334_1283)">
|
||||
<path d="M10.3939 0.870157C10.147 0.740821 9.85303 0.776095 9.64139 0.964219C9.62963 0.964219 8.58319 1.82254 7.44268 2.70437C5.44386 4.23288 4.85597 4.49156 4.73839 4.53859H1.90476C1.893 4.53859 1.88125 4.53859 1.85773 4.53859H0.587889C0.270429 4.53859 0 4.80902 0 5.14999V14.8502C0 15.1794 0.258671 15.4616 0.587889 15.4616H5.2087C5.32628 15.5086 5.87889 15.7673 7.64256 17.2723C8.67725 18.1541 9.60611 19.0007 9.60611 19.0124C9.73545 19.13 9.91182 19.2006 10.0764 19.2006C10.1705 19.2006 10.2763 19.177 10.3704 19.1418C10.629 19.0242 10.7937 18.7538 10.7937 18.4716V1.54035C10.7937 1.24641 10.6408 0.999493 10.3939 0.870157ZM16.6138 9.9942C16.6138 8.11296 15.6379 6.46686 14.1681 5.58503C14.0976 5.54976 13.9447 5.47921 13.8389 5.47921C13.5215 5.47921 13.251 5.74964 13.251 6.09062C13.251 6.31401 13.3686 6.5139 13.545 6.61972C14.6737 7.28991 15.438 8.54799 15.438 9.9942C15.438 11.4639 14.6502 12.7455 13.4862 13.404C13.3216 13.5098 13.204 13.7097 13.204 13.9331C13.204 14.274 13.4627 14.5445 13.7919 14.5445C13.933 14.5445 14.0858 14.4622 14.0858 14.4622C15.5908 13.5803 16.6138 11.9107 16.6138 9.9942ZM15.8613 2.49273C15.7554 2.42219 15.6496 2.3634 15.5085 2.3634C15.1911 2.3634 14.9206 2.63383 14.9206 2.9748C14.9206 3.20996 15.0617 3.40984 15.2499 3.52742C17.3898 4.83253 18.836 7.24288 18.836 10.0177C18.836 11.4522 18.448 12.7808 17.7778 13.9213C17.6367 14.1565 17.672 14.4504 17.8601 14.6385C17.8601 14.6385 17.8601 14.6385 17.8718 14.6503C18.1423 14.909 18.5891 14.8619 18.7772 14.5327C19.5532 13.2158 20 11.6756 20 10.0177C20 6.80784 18.3304 4.00949 15.8613 2.49273ZM17.4721 15.4851C17.2604 15.2147 16.8489 15.1911 16.6138 15.4381C16.2022 15.8496 15.7554 16.2023 15.2616 16.4963C15.0735 16.6021 14.9089 16.802 14.9089 17.0489C14.9089 17.3899 15.1675 17.6603 15.4968 17.6603C15.6261 17.6603 15.7319 17.6132 15.8377 17.5427C16.4139 17.19 16.9547 16.7667 17.425 16.2846C17.6484 16.073 17.672 15.732 17.4721 15.4851C17.4838 15.4968 17.4721 15.4968 17.4721 15.4851Z" fill="#999999"/>
|
||||
<path d="M4.83245 5.64366C4.17401 5.76124 2.92768 6.12573 2.10464 7.19569C1.96355 7.37206 1.99882 7.63073 2.17519 7.77182C2.17519 7.77182 2.17519 7.77182 2.18694 7.77182C2.36331 7.91292 2.61022 7.87764 2.75132 7.71303C3.20987 7.14866 3.76249 6.6078 4.93827 6.45495C5.13815 6.43143 5.27924 6.26682 5.27924 6.0787V6.01991C5.27924 5.78476 5.0676 5.60839 4.83245 5.64366Z" fill="#999999"/>
|
||||
<path d="M2.01059 8.3011C1.77543 8.19528 1.505 8.31285 1.43446 8.54801C1.38743 8.73613 1.3404 8.92426 1.31688 9.1359C1.28161 9.37106 1.45797 9.5827 1.69313 9.5827H1.76368C1.96356 9.5827 2.12817 9.42984 2.13993 9.24172C2.15168 9.08887 2.1752 8.98305 2.22223 8.77141C2.28102 8.58328 2.18696 8.39516 2.01059 8.3011Z" fill="#999999"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_334_1283">
|
||||
<rect width="20" height="20" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
@@ -63,6 +63,16 @@ export const constantRoutes: RouteRecordRaw[] = [
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "work",
|
||||
name: "workStatistics",
|
||||
component: () => import("@/views/data/work.vue"),
|
||||
meta: {
|
||||
title: "交班记录",
|
||||
affix: false,
|
||||
keepAlive: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "401",
|
||||
component: () => import("@/views/error/401.vue"),
|
||||
|
||||
@@ -3,6 +3,7 @@ import WebSocketManager, { type ApifoxModel, msgType } from "@/utils/websocket";
|
||||
import orderApi from "@/api/order/order";
|
||||
import { useUserStoreHook } from "@/store/modules/user";
|
||||
import productApi from "@/api/product/index";
|
||||
import limitTimeDiscountApi from '@/api/market/limitTimeDiscount.js'
|
||||
import * as UTILS from "@/utils/coupon-utils.js";
|
||||
import { BigNumber } from "bignumber.js";
|
||||
import _ from "lodash";
|
||||
@@ -15,6 +16,11 @@ import {
|
||||
OrderExtraConfig, MerchantReductionConfig, MerchantReductionType,
|
||||
GoodsType, FullReductionActivity
|
||||
} from "@/utils/goods";
|
||||
// import yskUtils from 'ysk-utils';
|
||||
// const OrderPriceCalculator = yskUtils.OrderPriceCalculator
|
||||
|
||||
import { useUserStore } from "@/store/modules/user";
|
||||
import { canUseLimitTimeDiscount, returnPrice } from '@/utils/order-utils'
|
||||
|
||||
const shopUser = useUserStoreHook();
|
||||
export interface CartsState {
|
||||
@@ -72,7 +78,9 @@ export const useCartsStore = defineStore("carts", () => {
|
||||
vipPriceShare: !!item.activityInfo.vipPriceShare
|
||||
}
|
||||
: undefined,
|
||||
skuData
|
||||
skuData,
|
||||
is_time_discount: item.isTimeDiscount,
|
||||
isTimeDiscount: item.isTimeDiscount
|
||||
};
|
||||
};
|
||||
|
||||
@@ -85,10 +93,16 @@ export const useCartsStore = defineStore("carts", () => {
|
||||
const oldOrderGoods = Object.values(oldOrder.value.detailMap || {})
|
||||
.flat()
|
||||
.map(convertToBaseCartItem);
|
||||
// console.log('list=====================================', list.value);
|
||||
// console.log('giftList=====================================', giftList.value);
|
||||
// console.log('oldOrder.value.detailMap=====================================', oldOrder.value.detailMap);
|
||||
|
||||
console.log('getAllGoodsList.[]===================', [...currentGoods, ...giftGoods, ...oldOrderGoods])
|
||||
return [...currentGoods, ...giftGoods, ...oldOrderGoods];
|
||||
};
|
||||
|
||||
const limitDiscountRes = ref(null)
|
||||
|
||||
// ------------------------------ 2. Store 内部原有响应式变量 ------------------------------
|
||||
// 选择用户
|
||||
const vipUser = ref<{ id?: string | number, isVip?: boolean }>({});
|
||||
@@ -119,16 +133,78 @@ export const useCartsStore = defineStore("carts", () => {
|
||||
originAmount: 0
|
||||
});
|
||||
|
||||
/**
|
||||
* 异步查询链接/任务是否完成,完成后设置 isLinkFinshed.value = true
|
||||
* @param {number} [interval=1000] - 查询间隔时间(毫秒),默认 1 秒
|
||||
* @returns {Promise<void>} - 完成后 resolve,可通过 await 等待后续操作
|
||||
*/
|
||||
async function checkLinkFinished(interval = 100) {
|
||||
return new Promise((resolve) => {
|
||||
let elapsedTime = 0; // 已消耗时间
|
||||
const checkTimer = setInterval(async () => {
|
||||
// 2. 实际查询逻辑(这里替换为你的真实查询逻辑,比如调用接口)
|
||||
try {
|
||||
if (isLinkFinshed.value == true) {
|
||||
clearInterval(checkTimer);
|
||||
resolve();
|
||||
} else {
|
||||
console.log('链接未完成,继续查询...');
|
||||
elapsedTime += interval;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('查询出错,继续重试:', error);
|
||||
elapsedTime += interval;
|
||||
}
|
||||
}, interval);
|
||||
});
|
||||
}
|
||||
|
||||
// 代客下单页面商品缓存
|
||||
const goods = useStorage<any[]>("Instead_goods", []);
|
||||
async function getGoods(query: any) {
|
||||
// 获取当前店铺可用的限时折扣
|
||||
limitDiscountRes.value = await limitTimeDiscountApi.getLimitTimeDiscount({
|
||||
shopId: localStorage.getItem("shopId")
|
||||
})
|
||||
|
||||
// 获取满减活动
|
||||
fullReductionActivities.value = await limitTimeDiscountApi.getDiscountActivity({
|
||||
shopId: localStorage.getItem("shopId")
|
||||
})
|
||||
|
||||
if (limitDiscountRes.value !== null) {
|
||||
checkLinkFinished().then(() => {
|
||||
console.log('给ws发送限时折扣信息');
|
||||
WebSocketManager.sendMessage({
|
||||
type: "shopping",
|
||||
operate_type: "time_discount_save",
|
||||
table_code: table_code.value,
|
||||
shop_id: localStorage.getItem("shopId"),
|
||||
data: limitDiscountRes.value,
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
console.log('代客下单页面商品缓存.获取当前店铺可用的限时折扣', limitDiscountRes.value);
|
||||
|
||||
const res = await productApi.getPage({
|
||||
page: 1,
|
||||
size: 999,
|
||||
status: "on_sale",
|
||||
...query,
|
||||
});
|
||||
goods.value = res.records;
|
||||
|
||||
const shopInfo = JSON.parse(localStorage.getItem('userInfo'))
|
||||
goods.value = res.records.map(item => {
|
||||
return {
|
||||
...item,
|
||||
isLimitDiscount: limitDiscountRes.value !== null && canUseLimitTimeDiscount(item, limitDiscountRes.value, shopInfo, shopUser.userInfo),
|
||||
limitDiscountPrice: limitDiscountRes.value !== null && returnPrice({ goods: { ...item, memberPrice: item.lowMemberPrice, salePrice: item.lowPrice }, shopInfo: shopInfo, limitTimeDiscountRes: limitDiscountRes.value, shopUserInfo: shopUser.userInfo, idKey: 'id' })
|
||||
}
|
||||
});
|
||||
|
||||
console.log('代客下单页面商品缓存.goods.value', goods.value);
|
||||
|
||||
setGoodsMap(goods.value);
|
||||
}
|
||||
|
||||
@@ -215,35 +291,15 @@ export const useCartsStore = defineStore("carts", () => {
|
||||
pointsPerYuan: 100,
|
||||
maxDeductionAmount: Infinity
|
||||
})
|
||||
|
||||
const fullReductionActivities = ref([])
|
||||
|
||||
//使用积分数量
|
||||
const userPoints = ref(0);
|
||||
const testFullReductionActivity: FullReductionActivity = {
|
||||
"id": 231,
|
||||
"shopId": 26,
|
||||
"status": 2, // 2=进行中
|
||||
"sort": 10,
|
||||
"createTime": "2025-10-14 13:56:07",
|
||||
"updateTime": "2025-10-14 14:41:02", // 最新修改
|
||||
"validStartTime": "2025-10-14",
|
||||
"validEndTime": "2025-12-14",
|
||||
"useType": "dine,pickup,deliv,express", // 支持所有就餐类型
|
||||
"useDays": "周一,周二,周三,周四,周五,周六,周日", // 全周期
|
||||
"useTimeType": "all", // 全时段
|
||||
"useStartTime": '',
|
||||
"useEndTime": '',
|
||||
"couponShare": 0, // 与优惠券不同享
|
||||
"discountShare": 0, // 与限时折扣不同享
|
||||
"vipPriceShare": 0, // 与会员价不同享
|
||||
"pointsShare": 0, // 与积分不同享
|
||||
"thresholds": [ // 多门槛(此处1个)
|
||||
{
|
||||
"activityId": 231,
|
||||
"fullAmount": 1, // 满1元
|
||||
"discountAmount": 10 // 减10元
|
||||
}
|
||||
],
|
||||
"isDel": false,
|
||||
};
|
||||
|
||||
// 新客立减金额
|
||||
const newUserDiscount = ref(0)
|
||||
|
||||
// 订单额外配置(现在依赖响应式的 merchantReduction)
|
||||
const orderExtraConfig = computed<OrderExtraConfig>(() => ({
|
||||
// 引用扩展后的商家减免配置
|
||||
@@ -255,9 +311,11 @@ export const useCartsStore = defineStore("carts", () => {
|
||||
userPoints: userPoints.value,
|
||||
isMember: useVipPrice.value,
|
||||
memberDiscountRate: shopUser.userInfo.memberDiscountRate || 1,
|
||||
fullReductionActivities: [testFullReductionActivity],
|
||||
currentDinnerType: dinnerType.value
|
||||
|
||||
fullReductionActivities: fullReductionActivities.value,
|
||||
currentDinnerType: dinnerType.value,
|
||||
limitTimeDiscount: limitDiscountRes.value,
|
||||
shopUserInfo: shopUser.userInfo,
|
||||
newUserDiscount: newUserDiscount.value
|
||||
}));
|
||||
|
||||
// 营销活动列表
|
||||
@@ -305,7 +363,7 @@ export const useCartsStore = defineStore("carts", () => {
|
||||
// 订单费用汇总(调用内部的 getAllGoodsList)
|
||||
const orderCostSummary = computed(() => {
|
||||
allGoods.value = getAllGoodsList();
|
||||
console.log(' allGoods.value', allGoods.value);
|
||||
console.log(' allGoods.value+++++++++++++++++++++++++', allGoods.value);
|
||||
console.log(' orderExtraConfig.value', orderExtraConfig.value);
|
||||
const costSummary = OrderPriceCalculator.calculateOrderCostSummary(
|
||||
allGoods.value,
|
||||
@@ -316,7 +374,7 @@ export const useCartsStore = defineStore("carts", () => {
|
||||
cartOrder.value,
|
||||
new Date()
|
||||
);
|
||||
console.log('costSummary', costSummary);
|
||||
console.log('costSummary----------------------------', costSummary);
|
||||
|
||||
return costSummary;
|
||||
});
|
||||
@@ -464,10 +522,19 @@ export const useCartsStore = defineStore("carts", () => {
|
||||
}
|
||||
|
||||
function add(data: any) {
|
||||
goods.value.map(item => {
|
||||
if (item.id == data.product_id) {
|
||||
data.is_time_discount = item.isLimitDiscount ? 1 : 0
|
||||
}
|
||||
})
|
||||
|
||||
const msg = { ...basic_msg, ...data };
|
||||
const hasCart = list.value.find((cartItem) => {
|
||||
return cartItem.product_id == msg.product_id && cartItem.sku_id == msg.sku_id;
|
||||
});
|
||||
|
||||
console.log('carts.add===', data);
|
||||
|
||||
if (hasCart) {
|
||||
update({ ...hasCart, ...msg, number: hasCart.number * 1 + msg.number * 1 });
|
||||
} else {
|
||||
@@ -566,6 +633,7 @@ export const useCartsStore = defineStore("carts", () => {
|
||||
if (res) setOldOrder(res);
|
||||
}
|
||||
|
||||
// 购物车信息补全
|
||||
function getProductDetails(v: { product_id: string, sku_id: string }) {
|
||||
const goods = goodsMap[v.product_id];
|
||||
console.log('getProductDetails', goods)
|
||||
@@ -579,6 +647,7 @@ export const useCartsStore = defineStore("carts", () => {
|
||||
|
||||
if (skuData) {
|
||||
return {
|
||||
limitDiscountPrice: goods.limitDiscountPrice,
|
||||
salePrice: skuData.salePrice || 0,
|
||||
memberPrice: skuData.memberPrice || 0,
|
||||
coverImg: goods.coverImg,
|
||||
@@ -613,10 +682,13 @@ export const useCartsStore = defineStore("carts", () => {
|
||||
product_name: v.productName,
|
||||
sku_name: v.skuName,
|
||||
sku_id: v.skuId,
|
||||
product_type: v.productType
|
||||
product_type: v.productType,
|
||||
is_time_discount: v.isTimeDiscount
|
||||
};
|
||||
});
|
||||
}
|
||||
console.log('returnDetailMap.newData================', newData);
|
||||
|
||||
return newData;
|
||||
}
|
||||
|
||||
@@ -645,8 +717,10 @@ export const useCartsStore = defineStore("carts", () => {
|
||||
function concocatSocket(initParams = $initParams) {
|
||||
WebSocketManager.subscribeToTopic(initParams, (msg) => {
|
||||
console.log("收到消息:", msg);
|
||||
if (msg.hasOwnProperty('status') && msg.status !== 1) {
|
||||
return ElMessage.error(msg.message || '操作失败');
|
||||
if (!msg.status) {
|
||||
if (msg.hasOwnProperty('status') && msg.status !== 1) {
|
||||
return ElMessage.error(msg.message || '操作失败');
|
||||
}
|
||||
}
|
||||
if (msg?.data) {
|
||||
if (Array.isArray(msg.data) && msg.data.length && msg.data[0].table_code) {
|
||||
@@ -834,11 +908,14 @@ export const useCartsStore = defineStore("carts", () => {
|
||||
clearMerchantReduction,
|
||||
seatFeeConfig,
|
||||
pointDeductionRule,
|
||||
// 新客立减金额
|
||||
newUserDiscount,
|
||||
//使用积分数量
|
||||
userPoints,
|
||||
coupons,
|
||||
setCoupons,
|
||||
payParamsInit
|
||||
payParamsInit,
|
||||
limitDiscountRes
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
@@ -5,19 +5,45 @@ import _ from "lodash";
|
||||
* 返回商品单价
|
||||
* @param goods 商品
|
||||
* @param user 用户信息
|
||||
* @param {Object} shopInfo
|
||||
* @param {Object} shopInfo 店铺信息
|
||||
* @param {boolean} limitTimeDiscount - 限时折扣
|
||||
*/
|
||||
export function returnGoodsPrice(goods, user, shopInfo) {
|
||||
export function returnGoodsPrice(goods, user, shopInfo, limitTimeDiscount) {
|
||||
if (!goods) {
|
||||
return 0;
|
||||
}
|
||||
//是否可以使用会员价
|
||||
const canUseVipPrice =
|
||||
user && user.isVip && user.isMemberPrice && goods.memberPrice * 1 > 0;
|
||||
// 商家改价
|
||||
if (goods.discount_sale_amount * 1 > 0) {
|
||||
return goods.discount_sale_amount;
|
||||
}
|
||||
if (shopInfo && !shopInfo.isMemberPrice) {
|
||||
return goods.salePrice;
|
||||
}
|
||||
if (user.isVip && goods.memberPrice * 1 <= goods.salePrice * 1 && goods.memberPrice * 1 > 0) {
|
||||
// 限时折扣
|
||||
if (limitTimeDiscount && limitTimeDiscount.id) {
|
||||
const canUseFoods = limitTimeDiscount.foods.split(",");
|
||||
const canUseLimit =
|
||||
limitTimeDiscount.foodType == 1 ||
|
||||
canUseFoods.includes(`${goods.productId}`);
|
||||
if (canUseLimit && limitTimeDiscount.discountPriority == "limit-time") {
|
||||
return new BigNumber(goods.salePrice)
|
||||
.times(limitTimeDiscount.discountRate / 100)
|
||||
.decimalPlaces(2, BigNumber.ROUND_UP)
|
||||
.toNumber();
|
||||
}
|
||||
|
||||
if (canUseLimit && limitTimeDiscount.discountPriority == "vip-price") {
|
||||
if (canUseVipPrice) {
|
||||
return goods.memberPrice;
|
||||
} else {
|
||||
return new BigNumber(goods.salePrice)
|
||||
.times(limitTimeDiscount.discountRate / 100)
|
||||
.decimalPlaces(2, BigNumber.ROUND_UP)
|
||||
.toNumber();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (canUseVipPrice) {
|
||||
return goods.memberPrice;
|
||||
}
|
||||
return goods.salePrice;
|
||||
@@ -63,7 +89,9 @@ export function returnCoupType(coupon) {
|
||||
* @param selCoupon 已选择的优惠券列表
|
||||
* @param user 用户信息
|
||||
*/
|
||||
export function returnCanDikouGoodsArr(canDikouGoodsArr, selCoupon, user) {
|
||||
export function returnCanDikouGoodsArr(args) {
|
||||
const { canDikouGoodsArr, selCoupon, user, shopInfo, limitTimeDiscount } =
|
||||
args;
|
||||
const types = [2, 4, 6];
|
||||
// 收集已抵扣商品并关联对应的优惠券类型
|
||||
const goodsCouponGoods = selCoupon
|
||||
@@ -92,11 +120,60 @@ export function returnCanDikouGoodsArr(canDikouGoodsArr, selCoupon, user) {
|
||||
}
|
||||
return v;
|
||||
})
|
||||
.filter((v) => v.num > 0); // 过滤掉数量<=0的商品
|
||||
.filter((v) => {
|
||||
const canUseNum = v.num - (v.returnNum || 0);
|
||||
if (canUseNum <= 0 || v.is_temporary == 1 || v.is_gift == 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}); // 过滤掉数量<=0的商品,赠菜,临时菜
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回商品是否享用了会员价/会员折扣
|
||||
* @param {*} goods
|
||||
*/
|
||||
function returnGoodsIsUseVipPrice(shopInfo, user, goods) {
|
||||
if (goods.is_time_discount) {
|
||||
return false;
|
||||
}
|
||||
if (shopInfo.isMemberPrice != 1 || user.isVip != 1) {
|
||||
return false;
|
||||
}
|
||||
if (shopInfo.isMemberPrice == 1 && user.isVip == 1) {
|
||||
if (goods.memberPrice <= 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回可以计算抵扣金额的商品列表
|
||||
*/
|
||||
function returnCanCalcGoodsList(canCalcGoodsArr, coupon, shopInfo, user) {
|
||||
return canCalcGoodsArr.filter((goods) => {
|
||||
console.log("goods");
|
||||
console.log(goods);
|
||||
if (
|
||||
!coupon.discountShare &&
|
||||
(goods.is_time_discount || goods.isTimeDiscount)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
!coupon.vipPriceShare &&
|
||||
returnGoodsIsUseVipPrice(shopInfo, user, goods)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断优惠券是否可使用,并返回不可用原因
|
||||
*
|
||||
@@ -111,10 +188,20 @@ export function returnCanDikouGoodsArr(canDikouGoodsArr, selCoupon, user) {
|
||||
* @param {Object} args.user - 用户信息对象
|
||||
* @param {Object} args.selCoupon - 已经选择的优惠券信息对象
|
||||
* @param {Object} args.shopInfo
|
||||
* @param {boolean} args.limitTimeDiscount - 限时折扣
|
||||
* @returns {Object} - { canUse: boolean, reason: string } 可用状态及不可用原因
|
||||
*/
|
||||
export function returnCouponCanUse(args) {
|
||||
let { canDikouGoodsArr, coupon, goodsOrderPrice, user, selCoupon, shopInfo } = args;
|
||||
let {
|
||||
canDikouGoodsArr,
|
||||
coupon,
|
||||
goodsOrderPrice,
|
||||
user,
|
||||
selCoupon,
|
||||
shopInfo,
|
||||
isMemberPrice,
|
||||
limitTimeDiscount,
|
||||
} = args;
|
||||
// 优惠券未启用
|
||||
if (!coupon.use) {
|
||||
return {
|
||||
@@ -122,10 +209,27 @@ export function returnCouponCanUse(args) {
|
||||
reason: coupon.noUseRestrictions || "不在可用时间段内",
|
||||
};
|
||||
}
|
||||
if (
|
||||
limitTimeDiscount &&
|
||||
limitTimeDiscount.id &&
|
||||
limitTimeDiscount.foodType == 1 &&
|
||||
!coupon.discountShare
|
||||
) {
|
||||
return {
|
||||
canUse: false,
|
||||
reason: coupon.noUseRestrictions || "不可与限时折扣同享",
|
||||
};
|
||||
}
|
||||
|
||||
// 计算门槛金额
|
||||
let fullAmount = goodsOrderPrice;
|
||||
canDikouGoodsArr = returnCanDikouGoodsArr(canDikouGoodsArr, selCoupon, user, shopInfo);
|
||||
canDikouGoodsArr = returnCanDikouGoodsArr({
|
||||
canDikouGoodsArr,
|
||||
selCoupon,
|
||||
user,
|
||||
shopInfo,
|
||||
limitTimeDiscount,
|
||||
});
|
||||
//优惠券指定门槛商品列表
|
||||
let canCalcGoodsArr = [...canDikouGoodsArr];
|
||||
//部分商品参与门槛计算
|
||||
@@ -133,10 +237,20 @@ export function returnCouponCanUse(args) {
|
||||
canCalcGoodsArr = canDikouGoodsArr.filter((v) => {
|
||||
return coupon.thresholdFoods.find((food) => food.id == v.productId);
|
||||
});
|
||||
fullAmount = canCalcGoodsArr.reduce((pre, cur) => {
|
||||
return pre + returnGoodsPrice(cur, user, shopInfo) * cur.num;
|
||||
}, 0);
|
||||
}
|
||||
canCalcGoodsArr = returnCanCalcGoodsList(
|
||||
canCalcGoodsArr,
|
||||
coupon,
|
||||
shopInfo,
|
||||
user
|
||||
);
|
||||
console.log("canCalcGoodsArr");
|
||||
console.log(canCalcGoodsArr);
|
||||
fullAmount = canCalcGoodsArr.reduce((pre, cur) => {
|
||||
return (
|
||||
pre + returnGoodsPrice(cur, user, shopInfo, limitTimeDiscount) * cur.num
|
||||
);
|
||||
}, 0);
|
||||
|
||||
// 是否全部商品可用
|
||||
const isDikouAll = coupon.useFoods.length === 0;
|
||||
@@ -147,12 +261,12 @@ export function returnCouponCanUse(args) {
|
||||
return coupon.useFoods.find((food) => food.id == v.productId);
|
||||
});
|
||||
}
|
||||
if (user.isVip && !coupon.vipPriceShare) {
|
||||
return {
|
||||
canUse: false,
|
||||
reason: "非会员可用",
|
||||
};
|
||||
}
|
||||
// if (user.isVip && !coupon.vipPriceShare) {
|
||||
// return {
|
||||
// canUse: false,
|
||||
// reason: "非会员可用",
|
||||
// };
|
||||
// }
|
||||
if (selCoupon.length > 0 && !selCoupon[0].otherCouponShare) {
|
||||
return {
|
||||
canUse: false,
|
||||
@@ -183,13 +297,6 @@ export function returnCouponCanUse(args) {
|
||||
}
|
||||
// 商品兑换券,第二件半价和买一送一判断是否有可用商品
|
||||
if ([2, 4, 5].includes(coupon.type)) {
|
||||
if (coupon.type == 2 && fullAmount < coupon.fullAmount) {
|
||||
return {
|
||||
canUse: false,
|
||||
reason: `满${coupon.fullAmount}元可用,当前可参与金额${fullAmount}元`,
|
||||
};
|
||||
}
|
||||
|
||||
// 没有符合条件的商品
|
||||
if (isDikouAll && canDikouGoodsArr.length === 0) {
|
||||
return {
|
||||
@@ -203,6 +310,20 @@ export function returnCouponCanUse(args) {
|
||||
reason: "没有符合条件的商品",
|
||||
};
|
||||
}
|
||||
if (coupon.type == 2) {
|
||||
if (canCalcGoodsArr.length <= 0) {
|
||||
return {
|
||||
canUse: false,
|
||||
reason: "没有符合计算门槛条件的商品",
|
||||
};
|
||||
}
|
||||
if (fullAmount < coupon.fullAmount) {
|
||||
return {
|
||||
canUse: false,
|
||||
reason: `满${coupon.fullAmount}元可用,当前可参与金额${fullAmount}元`,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
//商品兑换券是否达到门槛金额
|
||||
if (coupon.type == 2 && goodsOrderPrice < coupon.fullAmount) {
|
||||
@@ -258,11 +379,19 @@ export function returnCouponCanUse(args) {
|
||||
* @param discountNum 抵扣数量
|
||||
* @param user 用户信息
|
||||
* @param {Object} shopInfo 店铺信息
|
||||
* @param limitTimeDiscount 限时折扣
|
||||
*/
|
||||
export function calcDiscountGoodsArrPrice(discountGoodsArr, discountNum, user, shopInfo) {
|
||||
export function calcDiscountGoodsArrPrice(
|
||||
discountGoodsArr,
|
||||
discountNum,
|
||||
user,
|
||||
shopInfo,
|
||||
limitTimeDiscount
|
||||
) {
|
||||
let hasCountNum = 0;
|
||||
let discountPrice = 0;
|
||||
let hasDiscountGoodsArr = [];
|
||||
|
||||
for (let i = 0; i < discountGoodsArr.length; i++) {
|
||||
if (hasCountNum >= discountNum) {
|
||||
break;
|
||||
@@ -270,7 +399,14 @@ export function calcDiscountGoodsArrPrice(discountGoodsArr, discountNum, user, s
|
||||
const goods = discountGoodsArr[i];
|
||||
const shengyuNum = discountNum - hasCountNum;
|
||||
const num = Math.min(goods.num, shengyuNum);
|
||||
discountPrice += returnGoodsPrice(goods, user, shopInfo) * num;
|
||||
const realPrice = returnGoodsPrice(
|
||||
goods,
|
||||
user,
|
||||
shopInfo,
|
||||
limitTimeDiscount
|
||||
);
|
||||
|
||||
discountPrice += realPrice * num;
|
||||
|
||||
hasCountNum += num;
|
||||
hasDiscountGoodsArr.push({
|
||||
@@ -293,22 +429,62 @@ export function calcDiscountGoodsArrPrice(discountGoodsArr, discountNum, user, s
|
||||
* @param goodsOrderPrice 商品订单金额
|
||||
* @param selCoupon 已选择的优惠券列表
|
||||
* @param shopInfo 店铺信息
|
||||
* @param limitTimeDiscount 限时折扣
|
||||
*/
|
||||
export function returnCouponDiscount(arr, coupon, user, goodsOrderPrice, selCoupon, shopInfo) {
|
||||
arr = returnCanDikouGoods(arr, user, shopInfo);
|
||||
const canDikouGoodsArr = returnCanDikouGoodsArr(arr, selCoupon, user);
|
||||
export function returnCouponDiscount(
|
||||
arr,
|
||||
coupon,
|
||||
user,
|
||||
goodsOrderPrice,
|
||||
selCoupon,
|
||||
shopInfo,
|
||||
limitTimeDiscount
|
||||
) {
|
||||
arr = returnCanDikouGoods(arr, user, shopInfo,limitTimeDiscount);
|
||||
const canDikouGoodsArr = returnCanDikouGoodsArr({
|
||||
canDikouGoodsArr: arr,
|
||||
selCoupon,
|
||||
user,
|
||||
shopInfo,
|
||||
limitTimeDiscount,
|
||||
});
|
||||
if (coupon.type == 2) {
|
||||
return returnCouponProductDiscount(canDikouGoodsArr, coupon, user, shopInfo);
|
||||
return returnCouponProductDiscount(
|
||||
canDikouGoodsArr,
|
||||
coupon,
|
||||
user,
|
||||
shopInfo,
|
||||
limitTimeDiscount
|
||||
);
|
||||
}
|
||||
if (coupon.type == 6) {
|
||||
const result = returnCouponBuyOneGiveOneDiscount(canDikouGoodsArr, coupon, user, shopInfo);
|
||||
const result = returnCouponBuyOneGiveOneDiscount(
|
||||
canDikouGoodsArr,
|
||||
coupon,
|
||||
user,
|
||||
shopInfo,
|
||||
limitTimeDiscount
|
||||
);
|
||||
return result;
|
||||
}
|
||||
if (coupon.type == 4) {
|
||||
return returnSecoendDiscount(canDikouGoodsArr, coupon, user, shopInfo);
|
||||
return returnSecoendDiscount(
|
||||
canDikouGoodsArr,
|
||||
coupon,
|
||||
user,
|
||||
shopInfo,
|
||||
limitTimeDiscount
|
||||
);
|
||||
}
|
||||
if (coupon.type == 3) {
|
||||
return returnCouponZhekouDiscount(canDikouGoodsArr, coupon, user, goodsOrderPrice, selCoupon);
|
||||
return returnCouponZhekouDiscount(
|
||||
canDikouGoodsArr,
|
||||
coupon,
|
||||
user,
|
||||
goodsOrderPrice,
|
||||
selCoupon,
|
||||
limitTimeDiscount
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -319,6 +495,7 @@ export function returnCouponDiscount(arr, coupon, user, goodsOrderPrice, selCoup
|
||||
* @param user 用户信息
|
||||
* @param goodsOrderPrice 商品订单金额
|
||||
* @param selCoupon 已选择的优惠券列表
|
||||
* @param limitTimeDiscount 限时折扣
|
||||
*
|
||||
*/
|
||||
export function returnCouponZhekouDiscount(
|
||||
@@ -326,7 +503,8 @@ export function returnCouponZhekouDiscount(
|
||||
coupon,
|
||||
user,
|
||||
goodsOrderPrice,
|
||||
selCoupon
|
||||
selCoupon,
|
||||
limitTimeDiscount
|
||||
) {
|
||||
const { discountRate, maxDiscountAmount } = coupon;
|
||||
|
||||
@@ -334,14 +512,20 @@ export function returnCouponZhekouDiscount(
|
||||
const goodsCouponDiscount = selCoupon
|
||||
.filter((v) => v.type == 2)
|
||||
.reduce((prve, cur) => {
|
||||
return new BigNumber(prve).plus(new BigNumber(cur.discount.discountPrice));
|
||||
return new BigNumber(prve).plus(
|
||||
new BigNumber(cur.discount.discountPrice)
|
||||
);
|
||||
}, new BigNumber(0));
|
||||
|
||||
// 将商品订单价格转换为BigNumber并减去优惠券折扣
|
||||
const adjustedGoodsOrderPrice = new BigNumber(goodsOrderPrice).minus(goodsCouponDiscount);
|
||||
const adjustedGoodsOrderPrice = new BigNumber(goodsOrderPrice).minus(
|
||||
goodsCouponDiscount
|
||||
);
|
||||
|
||||
// 计算优惠比例:(100 - 折扣率) / 100
|
||||
const discountAmountRatio = new BigNumber(100).minus(discountRate).dividedBy(100);
|
||||
const discountAmountRatio = new BigNumber(100)
|
||||
.minus(discountRate)
|
||||
.dividedBy(100);
|
||||
|
||||
// 计算折扣金额:调整后的商品订单金额 × 优惠比例
|
||||
let discountPrice = adjustedGoodsOrderPrice
|
||||
@@ -351,7 +535,8 @@ export function returnCouponZhekouDiscount(
|
||||
|
||||
// 应用最大折扣金额限制
|
||||
if (maxDiscountAmount !== 0) {
|
||||
discountPrice = discountPrice >= maxDiscountAmount ? maxDiscountAmount : discountPrice;
|
||||
discountPrice =
|
||||
discountPrice >= maxDiscountAmount ? maxDiscountAmount : discountPrice;
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -366,11 +551,20 @@ export function returnCouponZhekouDiscount(
|
||||
* @param coupon 优惠券
|
||||
* @param user 用户信息
|
||||
* @param shopInfo 店铺信息
|
||||
* @param limitTimeDiscount 限时折扣
|
||||
*/
|
||||
export function returnCouponProductDiscount(canDikouGoodsArr, coupon, user, shopInfo) {
|
||||
export function returnCouponProductDiscount(
|
||||
canDikouGoodsArr,
|
||||
coupon,
|
||||
user,
|
||||
shopInfo,
|
||||
limitTimeDiscount
|
||||
) {
|
||||
const { useFoods, discountNum, useRule } = coupon;
|
||||
|
||||
//抵扣商品数组
|
||||
let discountGoodsArr = [];
|
||||
|
||||
//抵扣全部商品
|
||||
if (useFoods.length === 0) {
|
||||
if (useRule == "price_asc") {
|
||||
@@ -389,7 +583,15 @@ export function returnCouponProductDiscount(canDikouGoodsArr, coupon, user, shop
|
||||
discountGoodsArr = discountSelGoodsArr.slice(0, discountNum);
|
||||
}
|
||||
}
|
||||
const result = calcDiscountGoodsArrPrice(discountGoodsArr, discountNum, user, shopInfo);
|
||||
|
||||
|
||||
const result = calcDiscountGoodsArrPrice(
|
||||
discountGoodsArr,
|
||||
discountNum,
|
||||
user,
|
||||
shopInfo,
|
||||
limitTimeDiscount
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -399,8 +601,15 @@ export function returnCouponProductDiscount(canDikouGoodsArr, coupon, user, shop
|
||||
* @param coupon 优惠券
|
||||
* @param user 用户信息
|
||||
* @param shopInfo 店铺信息
|
||||
* @param limitTimeDiscount 限时折扣
|
||||
*/
|
||||
function returnCouponBuyOneGiveOneDiscount(canDikouGoodsArr, coupon, user, shopInfo) {
|
||||
function returnCouponBuyOneGiveOneDiscount(
|
||||
canDikouGoodsArr,
|
||||
coupon,
|
||||
user,
|
||||
shopInfo,
|
||||
limitTimeDiscount
|
||||
) {
|
||||
const { useFoods, useRule } = coupon;
|
||||
//抵扣商品
|
||||
let discountGoods = undefined;
|
||||
@@ -415,7 +624,9 @@ function returnCouponBuyOneGiveOneDiscount(canDikouGoodsArr, coupon, user, shopI
|
||||
}
|
||||
} else {
|
||||
//符合抵扣条件的商品
|
||||
const canUseGoods1 = canUseGoods.filter((v) => useFoods.find((food) => food.id == v.productId));
|
||||
const canUseGoods1 = canUseGoods.filter((v) =>
|
||||
useFoods.find((food) => food.id == v.productId)
|
||||
);
|
||||
if (useRule == "price_asc") {
|
||||
discountGoods = canUseGoods1[canUseGoods1.length - 1];
|
||||
} else {
|
||||
@@ -424,9 +635,13 @@ function returnCouponBuyOneGiveOneDiscount(canDikouGoodsArr, coupon, user, shopI
|
||||
}
|
||||
let discountPrice = 0;
|
||||
let hasDiscountGoodsArr = [];
|
||||
console.log("returnCouponBuyOneGiveOneDiscount:discountGoods", discountGoods);
|
||||
if (discountGoods) {
|
||||
discountPrice = returnGoodsPrice(discountGoods, user, shopInfo);
|
||||
discountPrice = returnGoodsPrice(
|
||||
discountGoods,
|
||||
user,
|
||||
shopInfo,
|
||||
limitTimeDiscount
|
||||
);
|
||||
hasDiscountGoodsArr = [discountGoods];
|
||||
}
|
||||
return {
|
||||
@@ -441,8 +656,15 @@ function returnCouponBuyOneGiveOneDiscount(canDikouGoodsArr, coupon, user, shopI
|
||||
* @param coupon 优惠券
|
||||
* @param user 用户信息
|
||||
* @param shopInfo 店铺信息
|
||||
* @param limitTimeDiscount 限时折扣
|
||||
*/
|
||||
function returnSecoendDiscount(canDikouGoodsArr, coupon, user, shopInfo) {
|
||||
function returnSecoendDiscount(
|
||||
canDikouGoodsArr,
|
||||
coupon,
|
||||
user,
|
||||
shopInfo,
|
||||
limitTimeDiscount
|
||||
) {
|
||||
const { useFoods, useRule } = coupon;
|
||||
//抵扣商品
|
||||
let discountGoods = undefined;
|
||||
@@ -457,7 +679,9 @@ function returnSecoendDiscount(canDikouGoodsArr, coupon, user, shopInfo) {
|
||||
}
|
||||
} else {
|
||||
//符合抵扣条件的商品
|
||||
const canUseGoods1 = canUseGoods.filter((v) => useFoods.find((food) => food.id == v.productId));
|
||||
const canUseGoods1 = canUseGoods.filter((v) =>
|
||||
useFoods.find((food) => food.id == v.productId)
|
||||
);
|
||||
if (useRule == "price_asc") {
|
||||
discountGoods = canUseGoods1[canUseGoods1.length - 1];
|
||||
} else {
|
||||
@@ -467,12 +691,20 @@ function returnSecoendDiscount(canDikouGoodsArr, coupon, user, shopInfo) {
|
||||
let discountPrice = 0;
|
||||
let hasDiscountGoodsArr = [];
|
||||
if (discountGoods) {
|
||||
discountPrice = returnGoodsPrice(discountGoods, user, shopInfo);
|
||||
discountPrice = returnGoodsPrice(
|
||||
discountGoods,
|
||||
user,
|
||||
shopInfo,
|
||||
limitTimeDiscount
|
||||
);
|
||||
hasDiscountGoodsArr = [discountGoods];
|
||||
}
|
||||
//返回半价价格
|
||||
return {
|
||||
discountPrice: discountPrice <= 0 ? 0 : new BigNumber(discountPrice).dividedBy(2).toNumber(),
|
||||
discountPrice:
|
||||
discountPrice <= 0
|
||||
? 0
|
||||
: new BigNumber(discountPrice).dividedBy(2).toNumber(),
|
||||
hasDiscountGoodsArr,
|
||||
};
|
||||
}
|
||||
@@ -482,8 +714,9 @@ function returnSecoendDiscount(canDikouGoodsArr, coupon, user, shopInfo) {
|
||||
* @param arr 商品列表
|
||||
* @param user 用户信息
|
||||
* @param shopInfo 店铺信息
|
||||
* @param limitTimeDiscount 限时折扣
|
||||
*/
|
||||
export function returnCanDikouGoods(arr, user, shopInfo) {
|
||||
export function returnCanDikouGoods(arr, user, shopInfo, limitTimeDiscount) {
|
||||
const result = arr
|
||||
.filter((v) => {
|
||||
return v.is_temporary != 1 && v.is_gift != 1;
|
||||
@@ -492,7 +725,10 @@ export function returnCanDikouGoods(arr, user, shopInfo) {
|
||||
return v.num > 0;
|
||||
})
|
||||
.sort((a, b) => {
|
||||
return returnGoodsPrice(b, user, shopInfo) - returnGoodsPrice(a, user, shopInfo);
|
||||
return (
|
||||
returnGoodsPrice(b, user, shopInfo, limitTimeDiscount) -
|
||||
returnGoodsPrice(a, user, shopInfo, limitTimeDiscount)
|
||||
);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
734
src/utils/goods-utils.js
Normal file
734
src/utils/goods-utils.js
Normal file
@@ -0,0 +1,734 @@
|
||||
import { BigNumber } from "bignumber.js";
|
||||
import _ from "lodash";
|
||||
|
||||
/**
|
||||
* 返回商品单价
|
||||
* @param goods 商品
|
||||
* @param user 用户信息
|
||||
* @param {Object} shopInfo 店铺信息
|
||||
* @param {boolean} limitTimeDiscount - 限时折扣
|
||||
*/
|
||||
export function returnGoodsPrice(goods, user, shopInfo, limitTimeDiscount) {
|
||||
if (!goods) {
|
||||
return 0;
|
||||
}
|
||||
//是否可以使用会员价
|
||||
const canUseVipPrice =
|
||||
user && user.isVip && user.isMemberPrice && goods.memberPrice * 1 > 0;
|
||||
// 商家改价
|
||||
if (goods.discount_sale_amount * 1 > 0) {
|
||||
return goods.salePrice;
|
||||
}
|
||||
// 限时折扣
|
||||
if (limitTimeDiscount && limitTimeDiscount.id) {
|
||||
const canUseFoods = limitTimeDiscount.foods.split(",");
|
||||
const canUseLimit =
|
||||
limitTimeDiscount.foodType == 1 ||
|
||||
canUseFoods.includes(`${goods.productId}`);
|
||||
if (canUseLimit && limitTimeDiscount.discountPriority == "limit-time") {
|
||||
return new BigNumber(goods.salePrice)
|
||||
.times(limitTimeDiscount.discountRate / 100)
|
||||
.decimalPlaces(2, BigNumber.ROUND_UP)
|
||||
.toNumber();
|
||||
}
|
||||
|
||||
if (canUseLimit && limitTimeDiscount.discountPriority == "vip-price") {
|
||||
if (canUseVipPrice) {
|
||||
return goods.memberPrice;
|
||||
} else {
|
||||
return new BigNumber(goods.salePrice)
|
||||
.times(limitTimeDiscount.discountRate / 100)
|
||||
.decimalPlaces(2, BigNumber.ROUND_UP)
|
||||
.toNumber();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (canUseVipPrice) {
|
||||
return goods.memberPrice;
|
||||
}
|
||||
return goods.salePrice;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回商品分组
|
||||
* @param arr 商品列表
|
||||
*/
|
||||
export function returnGoodsGroupMap(arr) {
|
||||
let map = {};
|
||||
arr.forEach((v) => {
|
||||
const key = v.productId + "_" + v.skuId;
|
||||
if (!map[key]) {
|
||||
map[key] = [];
|
||||
}
|
||||
map[key].push(v);
|
||||
});
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* 优惠券类型:1-满减券,2-商品兑换券,3-折扣券,4-第二件半价券,5-消费送券,6-买一送一券,7-固定价格券,8-免配送费券
|
||||
* @param coupon
|
||||
*/
|
||||
export function returnCoupType(coupon) {
|
||||
const couponTypes = {
|
||||
1: "满减券",
|
||||
2: "商品券",
|
||||
3: "折扣券",
|
||||
4: "第二件半价券",
|
||||
5: "消费送券",
|
||||
6: "买一送一券",
|
||||
7: "固定价格券",
|
||||
8: "免配送费券",
|
||||
};
|
||||
return couponTypes[coupon.type] || "未知类型";
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回商品券抵扣后的商品列表
|
||||
* @param canDikouGoodsArr 可抵扣商品列表
|
||||
* @param selCoupon 已选择的优惠券列表
|
||||
* @param user 用户信息
|
||||
*/
|
||||
export function returnCanDikouGoodsArr(args) {
|
||||
const { canDikouGoodsArr, selCoupon, user, shopInfo, limitTimeDiscount } =
|
||||
args;
|
||||
const types = [2, 4, 6];
|
||||
// 收集已抵扣商品并关联对应的优惠券类型
|
||||
const goodsCouponGoods = selCoupon
|
||||
.filter((v) => types.includes(v.type))
|
||||
.reduce((prev, cur) => {
|
||||
// 给每个抵扣商品添加所属优惠券类型
|
||||
const goodsWithType = cur.discount.hasDiscountGoodsArr.map((goods) => ({
|
||||
...goods,
|
||||
couponType: cur.type, // 记录该商品是被哪种类型的优惠券抵扣的
|
||||
}));
|
||||
prev.push(...goodsWithType);
|
||||
return prev;
|
||||
}, []);
|
||||
const arr = _.cloneDeep(canDikouGoodsArr)
|
||||
.map((v) => {
|
||||
const findCart = goodsCouponGoods.find((carts) => carts.id == v.id);
|
||||
if (findCart) {
|
||||
// 根据优惠券类型判断扣减数量
|
||||
if ([4, 6].includes(findCart.couponType)) {
|
||||
// 类型4(第二件半价)或6(买一送一),数量减2
|
||||
v.num -= 2;
|
||||
} else {
|
||||
// 其他类型(如类型2商品券),按原逻辑扣减对应数量
|
||||
v.num -= findCart.num;
|
||||
}
|
||||
}
|
||||
return v;
|
||||
})
|
||||
.filter((v) => {
|
||||
const canUseNum = v.num - (v.returnNum || 0);
|
||||
if (canUseNum <= 0 || v.is_temporary == 1 || v.is_gift == 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}); // 过滤掉数量<=0的商品,赠菜,临时菜
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回商品是否享用了会员价/会员折扣
|
||||
* @param {*} goods
|
||||
*/
|
||||
function returnGoodsIsUseVipPrice(shopInfo, user, goods) {
|
||||
if (goods.is_time_discount) {
|
||||
return false;
|
||||
}
|
||||
if (shopInfo.isMemberPrice != 1 || user.isVip != 1) {
|
||||
return false;
|
||||
}
|
||||
if (shopInfo.isMemberPrice == 1 && user.isVip == 1) {
|
||||
if (goods.memberPrice <= 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回可以计算抵扣金额的商品列表
|
||||
*/
|
||||
function returnCanCalcGoodsList(canCalcGoodsArr, coupon, shopInfo, user) {
|
||||
return canCalcGoodsArr.filter((goods) => {
|
||||
console.log("goods");
|
||||
console.log(goods);
|
||||
if (
|
||||
!coupon.discountShare &&
|
||||
(goods.is_time_discount || goods.isTimeDiscount)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
!coupon.vipPriceShare &&
|
||||
returnGoodsIsUseVipPrice(shopInfo, user, goods)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断优惠券是否可使用,并返回不可用原因
|
||||
*
|
||||
* @param {Object} args - 函数参数集合
|
||||
* @param {Array} args.canDikouGoodsArr - 可参与抵扣的商品列表
|
||||
* @param {Object} args.coupon - 优惠券信息对象
|
||||
* @param {boolean} args.coupon.use - 优惠券是否启用
|
||||
* @param {Array} args.coupon.useFoods - 优惠券适用的商品ID列表
|
||||
* @param {number} args.coupon.fullAmount - 优惠券使用门槛金额
|
||||
* @param {number} args.coupon.type - 优惠券类型
|
||||
* @param {number} args.goodsOrderPrice - 订单中所有商品的总金额
|
||||
* @param {Object} args.user - 用户信息对象
|
||||
* @param {Object} args.selCoupon - 已经选择的优惠券信息对象
|
||||
* @param {Object} args.shopInfo
|
||||
* @param {boolean} args.limitTimeDiscount - 限时折扣
|
||||
* @returns {Object} - { canUse: boolean, reason: string } 可用状态及不可用原因
|
||||
*/
|
||||
export function returnCouponCanUse(args) {
|
||||
let {
|
||||
canDikouGoodsArr,
|
||||
coupon,
|
||||
goodsOrderPrice,
|
||||
user,
|
||||
selCoupon,
|
||||
shopInfo,
|
||||
isMemberPrice,
|
||||
limitTimeDiscount,
|
||||
} = args;
|
||||
// 优惠券未启用
|
||||
if (!coupon.use) {
|
||||
return {
|
||||
canUse: false,
|
||||
reason: coupon.noUseRestrictions || "不在可用时间段内",
|
||||
};
|
||||
}
|
||||
if (
|
||||
limitTimeDiscount &&
|
||||
limitTimeDiscount.id &&
|
||||
limitTimeDiscount.foodType == 1 &&
|
||||
!coupon.discountShare
|
||||
) {
|
||||
return {
|
||||
canUse: false,
|
||||
reason: coupon.noUseRestrictions || "不可与限时折扣同享",
|
||||
};
|
||||
}
|
||||
|
||||
// 计算门槛金额
|
||||
let fullAmount = goodsOrderPrice;
|
||||
canDikouGoodsArr = returnCanDikouGoodsArr({
|
||||
canDikouGoodsArr,
|
||||
selCoupon,
|
||||
user,
|
||||
shopInfo,
|
||||
limitTimeDiscount,
|
||||
});
|
||||
//优惠券指定门槛商品列表
|
||||
let canCalcGoodsArr = [...canDikouGoodsArr];
|
||||
//部分商品参与门槛计算
|
||||
if (coupon.thresholdFoods.length) {
|
||||
canCalcGoodsArr = canDikouGoodsArr.filter((v) => {
|
||||
return coupon.thresholdFoods.find((food) => food.id == v.productId);
|
||||
});
|
||||
}
|
||||
canCalcGoodsArr = returnCanCalcGoodsList(
|
||||
canCalcGoodsArr,
|
||||
coupon,
|
||||
shopInfo,
|
||||
user
|
||||
);
|
||||
console.log("canCalcGoodsArr");
|
||||
console.log(canCalcGoodsArr);
|
||||
fullAmount = canCalcGoodsArr.reduce((pre, cur) => {
|
||||
return (
|
||||
pre + returnGoodsPrice(cur, user, shopInfo, limitTimeDiscount) * cur.num
|
||||
);
|
||||
}, 0);
|
||||
|
||||
// 是否全部商品可用
|
||||
const isDikouAll = coupon.useFoods.length === 0;
|
||||
// 订单可用商品列表
|
||||
let canUseGoodsArr = [];
|
||||
if (!isDikouAll) {
|
||||
canUseGoodsArr = canDikouGoodsArr.filter((v) => {
|
||||
return coupon.useFoods.find((food) => food.id == v.productId);
|
||||
});
|
||||
}
|
||||
// if (user.isVip && !coupon.vipPriceShare) {
|
||||
// return {
|
||||
// canUse: false,
|
||||
// reason: "非会员可用",
|
||||
// };
|
||||
// }
|
||||
if (selCoupon.length > 0 && !selCoupon[0].otherCouponShare) {
|
||||
return {
|
||||
canUse: false,
|
||||
reason: "当前选中的券不可与其他券同享",
|
||||
};
|
||||
}
|
||||
if (selCoupon.length > 0 && !coupon.otherCouponShare) {
|
||||
return {
|
||||
canUse: false,
|
||||
reason: "当前选中的券不可与其他券同享",
|
||||
};
|
||||
}
|
||||
// 满减券和折扣券计算门槛金额是否满足
|
||||
if ([1, 3].includes(coupon.type)) {
|
||||
if (canCalcGoodsArr.length <= 0) {
|
||||
return {
|
||||
canUse: false,
|
||||
reason: "没有可参与计算门槛的商品",
|
||||
};
|
||||
}
|
||||
// 不满足门槛金额
|
||||
if (fullAmount < coupon.fullAmount) {
|
||||
return {
|
||||
canUse: false,
|
||||
reason: `满${coupon.fullAmount}元可用,当前可参与金额${fullAmount}元`,
|
||||
};
|
||||
}
|
||||
}
|
||||
// 商品兑换券,第二件半价和买一送一判断是否有可用商品
|
||||
if ([2, 4, 5].includes(coupon.type)) {
|
||||
// 没有符合条件的商品
|
||||
if (isDikouAll && canDikouGoodsArr.length === 0) {
|
||||
return {
|
||||
canUse: false,
|
||||
reason: "没有符合条件的商品",
|
||||
};
|
||||
}
|
||||
if (!isDikouAll && canUseGoodsArr.length === 0) {
|
||||
return {
|
||||
canUse: false,
|
||||
reason: "没有符合条件的商品",
|
||||
};
|
||||
}
|
||||
if (coupon.type == 2) {
|
||||
if (canCalcGoodsArr.length <= 0) {
|
||||
return {
|
||||
canUse: false,
|
||||
reason: "没有符合计算门槛条件的商品",
|
||||
};
|
||||
}
|
||||
if (fullAmount < coupon.fullAmount) {
|
||||
return {
|
||||
canUse: false,
|
||||
reason: `满${coupon.fullAmount}元可用,当前可参与金额${fullAmount}元`,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
//商品兑换券是否达到门槛金额
|
||||
if (coupon.type == 2 && goodsOrderPrice < coupon.fullAmount) {
|
||||
return {
|
||||
canUse: false,
|
||||
reason: `满${coupon.fullAmount}元可用,当前可参与金额${fullAmount}元`,
|
||||
};
|
||||
}
|
||||
|
||||
// 买一送一券特殊验证
|
||||
if (coupon.type === 6) {
|
||||
let canUse = false;
|
||||
if (isDikouAll) {
|
||||
canUse = canDikouGoodsArr.some((v) => v.num >= 2);
|
||||
} else if (canUseGoodsArr.length > 0) {
|
||||
canUse = canUseGoodsArr.some((v) => v.num >= 2);
|
||||
}
|
||||
|
||||
if (!canUse) {
|
||||
return {
|
||||
canUse: false,
|
||||
reason: "需要购买至少2件相同的商品才能使用",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// 第二件半价券特殊验证
|
||||
if (coupon.type === 4) {
|
||||
let canUse = false;
|
||||
if (isDikouAll) {
|
||||
canUse = canDikouGoodsArr.some((v) => v.num >= 2);
|
||||
} else if (canUseGoodsArr.length > 0) {
|
||||
canUse = canUseGoodsArr.some((v) => v.num >= 2);
|
||||
}
|
||||
if (!canUse) {
|
||||
return {
|
||||
canUse: false,
|
||||
reason: "需要购买至少2件相同的商品才能使用",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// 所有条件都满足
|
||||
return {
|
||||
canUse: true,
|
||||
reason: "",
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算抵扣商品金额
|
||||
* @param discountGoodsArr 可抵扣商品列表
|
||||
* @param discountNum 抵扣数量
|
||||
* @param user 用户信息
|
||||
* @param {Object} shopInfo 店铺信息
|
||||
* @param limitTimeDiscount 限时折扣
|
||||
*/
|
||||
export function calcDiscountGoodsArrPrice(
|
||||
discountGoodsArr,
|
||||
discountNum,
|
||||
user,
|
||||
shopInfo,
|
||||
limitTimeDiscount
|
||||
) {
|
||||
let hasCountNum = 0;
|
||||
let discountPrice = 0;
|
||||
let hasDiscountGoodsArr = [];
|
||||
|
||||
for (let i = 0; i < discountGoodsArr.length; i++) {
|
||||
if (hasCountNum >= discountNum) {
|
||||
break;
|
||||
}
|
||||
const goods = discountGoodsArr[i];
|
||||
const shengyuNum = discountNum - hasCountNum;
|
||||
const num = Math.min(goods.num, shengyuNum);
|
||||
const realPrice = returnGoodsPrice(
|
||||
goods,
|
||||
user,
|
||||
shopInfo,
|
||||
limitTimeDiscount
|
||||
);
|
||||
|
||||
discountPrice += realPrice * num;
|
||||
|
||||
hasCountNum += num;
|
||||
hasDiscountGoodsArr.push({
|
||||
...goods,
|
||||
num,
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
discountPrice,
|
||||
hasDiscountGoodsArr,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算优惠券抵扣金额
|
||||
* @param arr 可抵扣商品列表
|
||||
* @param coupon 优惠券
|
||||
* @param user 用户信息
|
||||
* @param goodsOrderPrice 商品订单金额
|
||||
* @param selCoupon 已选择的优惠券列表
|
||||
* @param shopInfo 店铺信息
|
||||
* @param limitTimeDiscount 限时折扣
|
||||
*/
|
||||
export function returnCouponDiscount(
|
||||
arr,
|
||||
coupon,
|
||||
user,
|
||||
goodsOrderPrice,
|
||||
selCoupon,
|
||||
shopInfo,
|
||||
limitTimeDiscount
|
||||
) {
|
||||
arr = returnCanDikouGoods(arr, user, shopInfo,limitTimeDiscount);
|
||||
const canDikouGoodsArr = returnCanDikouGoodsArr({
|
||||
canDikouGoodsArr: arr,
|
||||
selCoupon,
|
||||
user,
|
||||
shopInfo,
|
||||
limitTimeDiscount,
|
||||
});
|
||||
if (coupon.type == 2) {
|
||||
return returnCouponProductDiscount(
|
||||
canDikouGoodsArr,
|
||||
coupon,
|
||||
user,
|
||||
shopInfo,
|
||||
limitTimeDiscount
|
||||
);
|
||||
}
|
||||
if (coupon.type == 6) {
|
||||
const result = returnCouponBuyOneGiveOneDiscount(
|
||||
canDikouGoodsArr,
|
||||
coupon,
|
||||
user,
|
||||
shopInfo,
|
||||
limitTimeDiscount
|
||||
);
|
||||
return result;
|
||||
}
|
||||
if (coupon.type == 4) {
|
||||
return returnSecoendDiscount(
|
||||
canDikouGoodsArr,
|
||||
coupon,
|
||||
user,
|
||||
shopInfo,
|
||||
limitTimeDiscount
|
||||
);
|
||||
}
|
||||
if (coupon.type == 3) {
|
||||
return returnCouponZhekouDiscount(
|
||||
canDikouGoodsArr,
|
||||
coupon,
|
||||
user,
|
||||
goodsOrderPrice,
|
||||
selCoupon,
|
||||
limitTimeDiscount
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 折扣券抵扣金额
|
||||
* @param canDikouGoodsArr 可抵扣商品列表
|
||||
* @param coupon 优惠券
|
||||
* @param user 用户信息
|
||||
* @param goodsOrderPrice 商品订单金额
|
||||
* @param selCoupon 已选择的优惠券列表
|
||||
* @param limitTimeDiscount 限时折扣
|
||||
*
|
||||
*/
|
||||
export function returnCouponZhekouDiscount(
|
||||
canDikouGoodsArr,
|
||||
coupon,
|
||||
user,
|
||||
goodsOrderPrice,
|
||||
selCoupon,
|
||||
limitTimeDiscount
|
||||
) {
|
||||
const { discountRate, maxDiscountAmount } = coupon;
|
||||
|
||||
// 计算商品优惠券折扣总和,使用BigNumber避免精度问题
|
||||
const goodsCouponDiscount = selCoupon
|
||||
.filter((v) => v.type == 2)
|
||||
.reduce((prve, cur) => {
|
||||
return new BigNumber(prve).plus(
|
||||
new BigNumber(cur.discount.discountPrice)
|
||||
);
|
||||
}, new BigNumber(0));
|
||||
|
||||
// 将商品订单价格转换为BigNumber并减去优惠券折扣
|
||||
const adjustedGoodsOrderPrice = new BigNumber(goodsOrderPrice).minus(
|
||||
goodsCouponDiscount
|
||||
);
|
||||
|
||||
// 计算优惠比例:(100 - 折扣率) / 100
|
||||
const discountAmountRatio = new BigNumber(100)
|
||||
.minus(discountRate)
|
||||
.dividedBy(100);
|
||||
|
||||
// 计算折扣金额:调整后的商品订单金额 × 优惠比例
|
||||
let discountPrice = adjustedGoodsOrderPrice
|
||||
.times(discountAmountRatio)
|
||||
.decimalPlaces(2, BigNumber.ROUND_FLOOR)
|
||||
.toNumber();
|
||||
|
||||
// 应用最大折扣金额限制
|
||||
if (maxDiscountAmount !== 0) {
|
||||
discountPrice =
|
||||
discountPrice >= maxDiscountAmount ? maxDiscountAmount : discountPrice;
|
||||
}
|
||||
|
||||
return {
|
||||
discountPrice, // 折扣抵扣金额(即优惠的金额)
|
||||
hasDiscountGoodsArr: [],
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 商品券抵扣金额
|
||||
* @param canDikouGoodsArr 可抵扣商品列表
|
||||
* @param coupon 优惠券
|
||||
* @param user 用户信息
|
||||
* @param shopInfo 店铺信息
|
||||
* @param limitTimeDiscount 限时折扣
|
||||
*/
|
||||
export function returnCouponProductDiscount(
|
||||
canDikouGoodsArr,
|
||||
coupon,
|
||||
user,
|
||||
shopInfo,
|
||||
limitTimeDiscount
|
||||
) {
|
||||
const { useFoods, discountNum, useRule } = coupon;
|
||||
|
||||
//抵扣商品数组
|
||||
let discountGoodsArr = [];
|
||||
|
||||
//抵扣全部商品
|
||||
if (useFoods.length === 0) {
|
||||
if (useRule == "price_asc") {
|
||||
discountGoodsArr = canDikouGoodsArr.slice(discountNum * -1).reverse();
|
||||
} else {
|
||||
discountGoodsArr = canDikouGoodsArr.slice(0, discountNum);
|
||||
}
|
||||
} else {
|
||||
//抵扣选中商品
|
||||
const discountSelGoodsArr = canDikouGoodsArr.filter((v) =>
|
||||
useFoods.find((food) => food.id == v.productId)
|
||||
);
|
||||
if (useRule == "price_asc") {
|
||||
discountGoodsArr = discountSelGoodsArr.slice(discountNum * -1).reverse();
|
||||
} else {
|
||||
discountGoodsArr = discountSelGoodsArr.slice(0, discountNum);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const result = calcDiscountGoodsArrPrice(
|
||||
discountGoodsArr,
|
||||
discountNum,
|
||||
user,
|
||||
shopInfo,
|
||||
limitTimeDiscount
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
// 返回买一送一券抵扣详情
|
||||
/**
|
||||
* @param canDikouGoodsArr 可抵扣商品列表
|
||||
* @param coupon 优惠券
|
||||
* @param user 用户信息
|
||||
* @param shopInfo 店铺信息
|
||||
* @param limitTimeDiscount 限时折扣
|
||||
*/
|
||||
function returnCouponBuyOneGiveOneDiscount(
|
||||
canDikouGoodsArr,
|
||||
coupon,
|
||||
user,
|
||||
shopInfo,
|
||||
limitTimeDiscount
|
||||
) {
|
||||
const { useFoods, useRule } = coupon;
|
||||
//抵扣商品
|
||||
let discountGoods = undefined;
|
||||
//符合买一送一条件的商品
|
||||
const canUseGoods = canDikouGoodsArr.filter((v) => v.num >= 2);
|
||||
//抵扣全部商品
|
||||
if (useFoods.length === 0) {
|
||||
if (useRule == "price_asc") {
|
||||
discountGoods = canUseGoods[canUseGoods.length - 1];
|
||||
} else {
|
||||
discountGoods = canUseGoods[0];
|
||||
}
|
||||
} else {
|
||||
//符合抵扣条件的商品
|
||||
const canUseGoods1 = canUseGoods.filter((v) =>
|
||||
useFoods.find((food) => food.id == v.productId)
|
||||
);
|
||||
if (useRule == "price_asc") {
|
||||
discountGoods = canUseGoods1[canUseGoods1.length - 1];
|
||||
} else {
|
||||
discountGoods = canUseGoods1[0];
|
||||
}
|
||||
}
|
||||
let discountPrice = 0;
|
||||
let hasDiscountGoodsArr = [];
|
||||
if (discountGoods) {
|
||||
discountPrice = returnGoodsPrice(
|
||||
discountGoods,
|
||||
user,
|
||||
shopInfo,
|
||||
limitTimeDiscount
|
||||
);
|
||||
hasDiscountGoodsArr = [discountGoods];
|
||||
}
|
||||
return {
|
||||
discountPrice: discountPrice <= 0 ? 0 : discountPrice,
|
||||
hasDiscountGoodsArr,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回第二件半价券抵扣详情
|
||||
* @param canDikouGoodsArr 可抵扣商品列表
|
||||
* @param coupon 优惠券
|
||||
* @param user 用户信息
|
||||
* @param shopInfo 店铺信息
|
||||
* @param limitTimeDiscount 限时折扣
|
||||
*/
|
||||
function returnSecoendDiscount(
|
||||
canDikouGoodsArr,
|
||||
coupon,
|
||||
user,
|
||||
shopInfo,
|
||||
limitTimeDiscount
|
||||
) {
|
||||
const { useFoods, useRule } = coupon;
|
||||
//抵扣商品
|
||||
let discountGoods = undefined;
|
||||
//符合条件的商品
|
||||
const canUseGoods = canDikouGoodsArr.filter((v) => v.num >= 2);
|
||||
//抵扣全部商品
|
||||
if (useFoods.length === 0) {
|
||||
if (useRule == "price_asc") {
|
||||
discountGoods = canUseGoods[canUseGoods.length - 1];
|
||||
} else {
|
||||
discountGoods = canUseGoods[0];
|
||||
}
|
||||
} else {
|
||||
//符合抵扣条件的商品
|
||||
const canUseGoods1 = canUseGoods.filter((v) =>
|
||||
useFoods.find((food) => food.id == v.productId)
|
||||
);
|
||||
if (useRule == "price_asc") {
|
||||
discountGoods = canUseGoods1[canUseGoods1.length - 1];
|
||||
} else {
|
||||
discountGoods = canUseGoods1[0];
|
||||
}
|
||||
}
|
||||
let discountPrice = 0;
|
||||
let hasDiscountGoodsArr = [];
|
||||
if (discountGoods) {
|
||||
discountPrice = returnGoodsPrice(
|
||||
discountGoods,
|
||||
user,
|
||||
shopInfo,
|
||||
limitTimeDiscount
|
||||
);
|
||||
hasDiscountGoodsArr = [discountGoods];
|
||||
}
|
||||
//返回半价价格
|
||||
return {
|
||||
discountPrice:
|
||||
discountPrice <= 0
|
||||
? 0
|
||||
: new BigNumber(discountPrice).dividedBy(2).toNumber(),
|
||||
hasDiscountGoodsArr,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回可以抵扣优惠券的商品列表,过滤掉赠品、临时商品,价格从高到低排序
|
||||
* @param arr 商品列表
|
||||
* @param user 用户信息
|
||||
* @param shopInfo 店铺信息
|
||||
* @param limitTimeDiscount 限时折扣
|
||||
*/
|
||||
export function returnCanDikouGoods(arr, user, shopInfo, limitTimeDiscount) {
|
||||
const result = arr
|
||||
.filter((v) => {
|
||||
return v.is_temporary != 1 && v.is_gift != 1;
|
||||
})
|
||||
.filter((v) => {
|
||||
return v.num > 0;
|
||||
})
|
||||
.sort((a, b) => {
|
||||
return (
|
||||
returnGoodsPrice(b, user, shopInfo, limitTimeDiscount) -
|
||||
returnGoodsPrice(a, user, shopInfo, limitTimeDiscount)
|
||||
);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
@@ -234,6 +234,46 @@ export interface FreeDineConfig {
|
||||
useShopType?: string; //all 全部 part部分
|
||||
shopIdList?: number[]; //可用门店id
|
||||
}
|
||||
|
||||
//限时折扣配置
|
||||
export interface TimeLimitDiscountConfig {
|
||||
/**
|
||||
* 折扣优先级 limit-time/vip-price
|
||||
*/
|
||||
discountPriority: string;
|
||||
/**
|
||||
* 折扣% 范围1-99
|
||||
*/
|
||||
discountRate: number;
|
||||
/**
|
||||
* 参与商品
|
||||
*/
|
||||
foods: string;
|
||||
/**
|
||||
* 参与商品 1全部 2部分
|
||||
*/
|
||||
foodType: number;
|
||||
/**
|
||||
* 自增主键
|
||||
*/
|
||||
id: number;
|
||||
/**
|
||||
* 店铺ID
|
||||
*/
|
||||
shopId: number;
|
||||
/**
|
||||
* 可使用类型:堂食 dine-in 外带 take-out 外卖 take-away 配送 post
|
||||
*/
|
||||
useType: string;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
//用户信息
|
||||
interface ShopUserInfo {
|
||||
isVip: number | null; //是否会员
|
||||
discount: number | null; //用户折扣
|
||||
isMemberPrice: number | null; //会员折扣与会员价是否同时使用
|
||||
}
|
||||
/** 订单额外费用配置 */
|
||||
export interface OrderExtraConfig {
|
||||
// merchantReduction: number; // 商家减免金额(元,默认0)
|
||||
@@ -251,6 +291,8 @@ export interface OrderExtraConfig {
|
||||
currentDinnerType: "dine-in" | "take-out" | "take-away" | "post"; // 当前就餐类型(匹配useType)
|
||||
isFreeDine?: boolean; //是否霸王餐
|
||||
freeDineConfig?: FreeDineConfig;
|
||||
limitTimeDiscount?: TimeLimitDiscountConfig; //限时折扣
|
||||
shopUserInfo: ShopUserInfo; // 用户信息
|
||||
}
|
||||
|
||||
/** 订单费用汇总(修改:补充商家减免类型和明细) */
|
||||
@@ -283,10 +325,12 @@ export interface OrderCostSummary {
|
||||
config: OrderExtraConfig; // 订单额外费用配置
|
||||
//满减活动
|
||||
fullReduction: {
|
||||
usedFullReductionActivityFullAmount: number; // 计算出的满减活动的门槛金额
|
||||
usedActivity?: FullReductionActivity; // 实际使用的满减活动
|
||||
usedThreshold?: FullReductionThreshold; // 实际使用的满减阈值(多门槛中选最优)
|
||||
actualAmount: number; // 满减实际减免金额(元)
|
||||
};
|
||||
vipDiscountAmount: number; //会员折扣减免金额
|
||||
// 订单原支付金额
|
||||
orderOriginFinalPayAmount: number; //订单原金额(包含打包费+餐位费)
|
||||
}
|
||||
@@ -399,6 +443,195 @@ function isDinnerTypeMatch(
|
||||
//满减活动的就餐类型和当前券类型字段值不一样,暂时返回true
|
||||
return true;
|
||||
}
|
||||
|
||||
//判断商品是否可以使用限时折扣
|
||||
export function returnCanUseLimitTimeDiscount(
|
||||
goods: BaseCartItem,
|
||||
limitTimeDiscount: TimeLimitDiscountConfig | null | undefined,
|
||||
useVipPrice: boolean,
|
||||
idKey = "product_id"
|
||||
) {
|
||||
if (!limitTimeDiscount || !limitTimeDiscount.id) {
|
||||
return false;
|
||||
}
|
||||
const canUseFoods = (limitTimeDiscount.foods || "").split(",");
|
||||
const goodsCanUse =
|
||||
limitTimeDiscount.foodType == 1 || canUseFoods.includes("" + goods[idKey as keyof BaseCartItem]);
|
||||
if (!goodsCanUse) {
|
||||
return false;
|
||||
}
|
||||
if (limitTimeDiscount.discountPriority == "limit-time") {
|
||||
return true;
|
||||
}
|
||||
if (limitTimeDiscount.discountPriority == "vip-price") {
|
||||
if (!useVipPrice) {
|
||||
return true;
|
||||
}
|
||||
if (useVipPrice && goods.hasOwnProperty("memberPrice")) {
|
||||
if (goods.memberPrice && goods.memberPrice * 1 <= 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function returnMemberPrice(useVipPrice: boolean, goods: BaseCartItem) {
|
||||
if (useVipPrice) {
|
||||
return goods.memberPrice || goods.salePrice;
|
||||
} else {
|
||||
return goods.salePrice;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回商品限时折扣价格
|
||||
*/
|
||||
function returnLimitPrice(
|
||||
goods: BaseCartItem,
|
||||
limitTimeDiscount: TimeLimitDiscountConfig | null | undefined,
|
||||
useVipPrice: boolean
|
||||
) {
|
||||
if (!limitTimeDiscount) {
|
||||
return 0;
|
||||
}
|
||||
const discountRate = new BigNumber(limitTimeDiscount.discountRate).dividedBy(
|
||||
100
|
||||
);
|
||||
|
||||
const canuseLimit = returnCanUseLimitTimeDiscount(
|
||||
goods,
|
||||
limitTimeDiscount,
|
||||
useVipPrice
|
||||
);
|
||||
if (canuseLimit) {
|
||||
//可以使用限时折扣
|
||||
if (limitTimeDiscount.discountPriority == "limit-time") {
|
||||
//限时价优先
|
||||
const result = BigNumber(goods.salePrice)
|
||||
.times(discountRate)
|
||||
.decimalPlaces(2, BigNumber.ROUND_UP)
|
||||
.toNumber();
|
||||
return result;
|
||||
}
|
||||
if (limitTimeDiscount.discountPriority == "vip-price") {
|
||||
//会员价优先
|
||||
if (useVipPrice && goods.memberPrice && goods.memberPrice * 1 > 0) {
|
||||
//使用会员价
|
||||
return returnMemberPrice(useVipPrice, goods);
|
||||
} else {
|
||||
//不使用会员价
|
||||
const result = BigNumber(goods.salePrice)
|
||||
.times(discountRate)
|
||||
.decimalPlaces(2, BigNumber.ROUND_UP)
|
||||
.toNumber();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//不可以使用限时折扣
|
||||
//会员价优先
|
||||
if (useVipPrice) {
|
||||
//使用会员价
|
||||
return returnMemberPrice(useVipPrice, goods);
|
||||
} else {
|
||||
return goods.salePrice;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算商品计算门槛时的金额
|
||||
*/
|
||||
|
||||
export function returnCalcPrice(
|
||||
goods: BaseCartItem,
|
||||
fullReductionActivitie: FullReductionActivity | undefined,
|
||||
limitTimeDiscount: TimeLimitDiscountConfig | null | undefined,
|
||||
useVipPrice: boolean,
|
||||
idKey = "product_id"
|
||||
) {
|
||||
if (goods.discountSaleAmount && goods.discountSaleAmount * 1 > 0) {
|
||||
return goods.salePrice;
|
||||
}
|
||||
//限时折扣和满减活动都有
|
||||
if (fullReductionActivitie && limitTimeDiscount) {
|
||||
if (
|
||||
fullReductionActivitie.discountShare == 1 &&
|
||||
fullReductionActivitie.vipPriceShare == 1
|
||||
) {
|
||||
//与限时折扣同享,与会员价不同享
|
||||
return returnLimitPrice(goods, limitTimeDiscount, useVipPrice);
|
||||
}
|
||||
if (
|
||||
fullReductionActivitie.discountShare != 1 &&
|
||||
fullReductionActivitie.vipPriceShare == 1
|
||||
) {
|
||||
//与限时折扣不同享,与会员价同享
|
||||
return returnMemberPrice(useVipPrice, goods);
|
||||
}
|
||||
if (fullReductionActivitie.vipPriceShare != 1) {
|
||||
//与会员价不同享
|
||||
return goods.salePrice;
|
||||
}
|
||||
return goods.salePrice;
|
||||
}
|
||||
//只有满减活动
|
||||
if (fullReductionActivitie) {
|
||||
if (fullReductionActivitie.vipPriceShare == 1) {
|
||||
return returnMemberPrice(useVipPrice, goods);
|
||||
} else {
|
||||
return goods.salePrice;
|
||||
}
|
||||
}
|
||||
//只有限时折扣
|
||||
if (limitTimeDiscount) {
|
||||
return returnLimitPrice(goods, limitTimeDiscount, useVipPrice);
|
||||
}
|
||||
|
||||
if (useVipPrice) {
|
||||
return returnMemberPrice(useVipPrice, goods);
|
||||
}
|
||||
return goods.salePrice;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算满减活动门槛
|
||||
*/
|
||||
export function calcFullReductionActivityFullAmount(
|
||||
goodsList: BaseCartItem[],
|
||||
fullReductionActivitie: FullReductionActivity | undefined,
|
||||
limitTimeDiscount: TimeLimitDiscountConfig | null | undefined,
|
||||
useVipPrice: boolean,
|
||||
seatFee: number,
|
||||
packFee: number
|
||||
): number {
|
||||
if (!fullReductionActivitie) {
|
||||
return 0;
|
||||
}
|
||||
let amount = 0;
|
||||
for (let goods of goodsList) {
|
||||
const availableNum = Math.max(0, goods.number - (goods.returnNum || 0));
|
||||
if (goods.is_temporary || goods.is_gift || availableNum <= 0) {
|
||||
//临时菜,赠菜,数量<=0的商品不计算
|
||||
continue;
|
||||
}
|
||||
const calcPrice = returnCalcPrice(
|
||||
goods,
|
||||
fullReductionActivitie,
|
||||
limitTimeDiscount,
|
||||
useVipPrice,
|
||||
"product_id"
|
||||
);
|
||||
if (calcPrice !== undefined) {
|
||||
amount += calcPrice * availableNum;
|
||||
}
|
||||
}
|
||||
return amount + seatFee + packFee;
|
||||
console.log("amount", amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* 筛选最优满减活动(对齐后端逻辑:状态→时间→周期→时段→就餐类型→排序→修改时间)
|
||||
* @param activities 后端返回的满减活动列表
|
||||
@@ -424,11 +657,16 @@ export function filterOptimalFullReductionActivity(
|
||||
activity.thresholds?.length // 至少有一个满减阈值
|
||||
);
|
||||
});
|
||||
console.log("baseEligible", baseEligible);
|
||||
|
||||
if (!baseEligible.length) return undefined;
|
||||
|
||||
// 第二步:时间筛选(有效期内+周期内+时段内)
|
||||
const timeEligible = baseEligible.filter((activity) => {
|
||||
// 1. 校验有效期(validStartTime ~ validEndTime)
|
||||
if (activity.useTimeType == "all") {
|
||||
return true;
|
||||
}
|
||||
if (!activity.validStartTime || !activity.validEndTime) return false;
|
||||
const startDate = new Date(activity.validStartTime);
|
||||
const endDate = new Date(activity.validEndTime);
|
||||
@@ -520,9 +758,7 @@ export function calcMemberPrice(
|
||||
if (!isMember) return truncateToTwoDecimals(goods.salePrice);
|
||||
|
||||
// 优先级:SKU会员价 > 商品会员价 > 商品原价(无会员价时用会员折扣)
|
||||
const basePrice =
|
||||
goods.skuData?.memberPrice ?? goods.memberPrice ?? goods.salePrice;
|
||||
|
||||
const basePrice = goods.memberPrice || goods.salePrice;
|
||||
// 仅当无SKU会员价、无商品会员价时,才应用会员折扣率
|
||||
if (memberDiscountRate && !goods.skuData?.memberPrice && !goods.memberPrice) {
|
||||
return truncateToTwoDecimals(
|
||||
@@ -565,8 +801,8 @@ export function filterThresholdGoods(
|
||||
return applicableProductIds.length === 0
|
||||
? baseEligibleGoods
|
||||
: baseEligibleGoods.filter((goods) =>
|
||||
applicableProductIds.includes(String(goods.product_id))
|
||||
); // 核心修正:用商品ID匹配
|
||||
applicableProductIds.includes(String(goods.product_id))
|
||||
); // 核心修正:用商品ID匹配
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -665,11 +901,13 @@ export function calcCouponThresholdAmount(
|
||||
*/
|
||||
export function calcSingleGoodsRealPrice(
|
||||
goods: BaseCartItem,
|
||||
config: Pick<OrderExtraConfig, "isMember" | "memberDiscountRate"> & {
|
||||
activity?: ActivityConfig; // 商品参与的营销活动(如限时折扣,按商品ID匹配)
|
||||
}
|
||||
config: Pick<
|
||||
OrderExtraConfig,
|
||||
"isMember" | "memberDiscountRate" | "limitTimeDiscount"
|
||||
>
|
||||
): number {
|
||||
const { isMember, memberDiscountRate, activity } = config;
|
||||
const { isMember, memberDiscountRate, limitTimeDiscount: activity } = config;
|
||||
console.log("activity", activity);
|
||||
|
||||
//如果是增菜价格为0
|
||||
if (goods.is_gift) {
|
||||
@@ -687,12 +925,38 @@ export function calcSingleGoodsRealPrice(
|
||||
);
|
||||
|
||||
// 3. 优先级3:营销活动折扣(如限时折扣,需按商品ID匹配活动)
|
||||
const isActivityApplicable = activity
|
||||
? (activity.applicableProductIds || []).includes(String(goods.product_id)) // 核心修正:用商品ID匹配活动
|
||||
: false;
|
||||
let isActivityApplicable = false;
|
||||
if (activity) {
|
||||
if (activity.foodType == 1) {
|
||||
isActivityApplicable = true;
|
||||
} else {
|
||||
const canUseGoods = activity.foods?.split(",") || [];
|
||||
if (canUseGoods.find((v) => v == String(goods.product_id))) {
|
||||
isActivityApplicable = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!activity || !isActivityApplicable) {
|
||||
return memberPrice.toNumber();
|
||||
}
|
||||
console.log("isMember", isMember);
|
||||
//限时折扣优先或者会员价优先但是不是会员或者未开启会员价格时限时折扣优先
|
||||
if (
|
||||
activity.discountPriority == "limit-time" ||
|
||||
(activity.discountPriority == "vip-price" && !isMember) ||
|
||||
(activity.discountPriority == "vip-price" && isMember && !goods.memberPrice)
|
||||
) {
|
||||
//限时折扣优先
|
||||
return truncateToTwoDecimals(
|
||||
new BigNumber(goods.salePrice)
|
||||
.times(activity.discountRate / 100)
|
||||
.decimalPlaces(2, BigNumber.ROUND_UP)
|
||||
.toNumber()
|
||||
);
|
||||
}
|
||||
if (activity.discountPriority == "vip-price" && isMember) {
|
||||
return memberPrice.toNumber();
|
||||
}
|
||||
|
||||
// 处理活动与会员的同享/不同享逻辑
|
||||
if (activity.vipPriceShare) {
|
||||
@@ -751,26 +1015,18 @@ export function calcGoodsOriginalAmount(goodsList: BaseCartItem[]): number {
|
||||
*/
|
||||
export function calcGoodsRealAmount(
|
||||
goodsList: BaseCartItem[],
|
||||
config: Pick<OrderExtraConfig, "isMember" | "memberDiscountRate">,
|
||||
activities: ActivityConfig[] = []
|
||||
config: Pick<
|
||||
OrderExtraConfig,
|
||||
"isMember" | "memberDiscountRate" | "limitTimeDiscount"
|
||||
>
|
||||
): number {
|
||||
let total = new BigNumber(0);
|
||||
|
||||
for (const goods of goodsList) {
|
||||
const availableNum = Math.max(0, goods.number - (goods.returnNum || 0));
|
||||
if (availableNum <= 0) continue;
|
||||
|
||||
// 匹配商品参与的营销活动(按商品ID匹配,优先商品自身配置)
|
||||
const activity =
|
||||
goods.activityInfo ??
|
||||
activities.find(
|
||||
(act) =>
|
||||
(act.applicableProductIds || []).includes(String(goods.product_id)) // 核心修正:用商品ID匹配活动
|
||||
);
|
||||
|
||||
const realPrice = new BigNumber(
|
||||
calcSingleGoodsRealPrice(goods, { ...config, activity })
|
||||
);
|
||||
console.log("goods", goods);
|
||||
const realPrice = new BigNumber(calcSingleGoodsRealPrice(goods, config));
|
||||
total = total.plus(realPrice.multipliedBy(availableNum));
|
||||
}
|
||||
|
||||
@@ -818,27 +1074,18 @@ export function selectOptimalThreshold(
|
||||
const validThresholds = thresholds.filter((threshold) => {
|
||||
const fullAmount = new BigNumber(threshold.fullAmount || 0);
|
||||
const discountAmount = new BigNumber(threshold.discountAmount || 0);
|
||||
console.log("fullAmount", fullAmount);
|
||||
console.log("discountAmount", discountAmount);
|
||||
|
||||
return (
|
||||
fullAmount.isLessThanOrEqualTo(thresholdBase) &&
|
||||
discountAmount.isGreaterThan(0)
|
||||
);
|
||||
});
|
||||
console.log("validThresholds", validThresholds);
|
||||
|
||||
if (!validThresholds.length) return undefined;
|
||||
// 第三步:选择最优阈值(优先级:1.满金额最小 → 2.减免金额最大)
|
||||
// const sortValidThresholds = validThresholds.sort((a, b) => {
|
||||
// const aFull = new BigNumber(a.fullAmount || 0);
|
||||
// const bFull = new BigNumber(b.fullAmount || 0);
|
||||
// const aDiscount = new BigNumber(a.discountAmount || 0);
|
||||
// const bDiscount = new BigNumber(b.discountAmount || 0);
|
||||
|
||||
// // 先比满金额:越小越优先(满1减10 比 满100减20 更优)
|
||||
// if (!aFull.isEqualTo(bFull)) {
|
||||
// return aFull.comparedTo(bFull) || 0; // Ensure a number is always returned
|
||||
// }
|
||||
// // 再比减免金额:越大越优先
|
||||
// return bDiscount.comparedTo(aDiscount) || 0; // Ensure a number is always returned
|
||||
// })
|
||||
// 找到抵扣金额最大的门槛项
|
||||
const maxDiscountThreshold = validThresholds.reduce(
|
||||
(maxItem, currentItem) => {
|
||||
@@ -981,13 +1228,12 @@ export function calcTotalPackFee(
|
||||
const packNumber = goods.packNumber ? goods.packNumber * 1 : 0;
|
||||
let availableNum = Math.max(0, goods.number - (goods.returnNum || 0));
|
||||
|
||||
|
||||
if (availableNum === 0) continue;
|
||||
|
||||
// 计算单个商品打包数量(外卖全打包,堂食按配置,称重商品≤1)
|
||||
let packNum = Math.min(availableNum, packNumber);
|
||||
if (dinnerType === "take-out") {
|
||||
packNum = availableNum
|
||||
packNum = availableNum;
|
||||
}
|
||||
if (goods.product_type === GoodsType.WEIGHT) {
|
||||
packNum = Math.min(packNum, 1);
|
||||
@@ -1043,8 +1289,8 @@ export function calcPointDeduction(
|
||||
)
|
||||
? maxDeductByPoints
|
||||
: new BigNumber(rule.maxDeductionAmount || Infinity).isLessThan(maxLimitBn)
|
||||
? maxDeductByPoints
|
||||
: maxLimitBn;
|
||||
? maxDeductByPoints
|
||||
: maxLimitBn;
|
||||
|
||||
// 实际使用积分 = 抵扣金额 * 积分兑换比例
|
||||
const usedPoints = maxDeductAmount.multipliedBy(pointsPerYuanBn);
|
||||
@@ -1057,6 +1303,24 @@ export function calcPointDeduction(
|
||||
};
|
||||
}
|
||||
|
||||
function calcVipDiscountAmount(
|
||||
goodsRealAmount: number,
|
||||
shopUserInfo: ShopUserInfo
|
||||
): number {
|
||||
if (!shopUserInfo.isVip || shopUserInfo.discount === 0) return 0;
|
||||
if (shopUserInfo.isVip == 1 && shopUserInfo.isMemberPrice != 1) {
|
||||
return 0;
|
||||
}
|
||||
console.log("goodsRealAmount", goodsRealAmount);
|
||||
console.log("discount", (100 - (shopUserInfo.discount || 0)) / 100);
|
||||
return truncateToTwoDecimals(
|
||||
new BigNumber(goodsRealAmount)
|
||||
.times((100 - (shopUserInfo.discount || 0)) / 100)
|
||||
.decimalPlaces(2, BigNumber.ROUND_DOWN)
|
||||
.toNumber()
|
||||
);
|
||||
}
|
||||
|
||||
// ============================ 6. 订单总费用汇总与实付金额计算(核心入口,补充细分字段) ============================
|
||||
/**
|
||||
* 计算订单所有费用子项并汇总(核心入口函数)
|
||||
@@ -1079,7 +1343,14 @@ export function calculateOrderCostSummary(
|
||||
currentTime: Date = new Date()
|
||||
): OrderCostSummary {
|
||||
//是否使用霸王餐,霸王餐配置
|
||||
const { isFreeDine, freeDineConfig } = config;
|
||||
const {
|
||||
isFreeDine,
|
||||
freeDineConfig,
|
||||
limitTimeDiscount,
|
||||
fullReductionActivities,
|
||||
shopUserInfo,
|
||||
} = config;
|
||||
console.log("shopUserInfo", shopUserInfo);
|
||||
|
||||
// ------------------------------ 1. 基础费用计算 ------------------------------
|
||||
const goodsOriginalAmount = calcGoodsOriginalAmount(goodsList); // 商品原价总和
|
||||
@@ -1089,19 +1360,35 @@ export function calculateOrderCostSummary(
|
||||
{
|
||||
isMember: config.isMember,
|
||||
memberDiscountRate: config.memberDiscountRate,
|
||||
},
|
||||
activities
|
||||
limitTimeDiscount: config.limitTimeDiscount,
|
||||
}
|
||||
);
|
||||
const goodsDiscountAmount = calcGoodsDiscountAmount(
|
||||
goodsOriginalAmount,
|
||||
goodsRealAmount
|
||||
); // 商品折扣金额
|
||||
|
||||
const newUserDiscount = config.newUserDiscount || 0; // 新客立减
|
||||
|
||||
// 其他费用计算(原有逻辑不变) ------------------------------
|
||||
const packFee = calcTotalPackFee(goodsList, dinnerType); // 打包费
|
||||
let seatFee = calcSeatFee(config.seatFeeConfig); // 餐位费
|
||||
seatFee = dinnerType === "dine-in" ? seatFee : 0; // 外卖不收餐位费
|
||||
const additionalFee = Math.max(0, config.additionalFee); // 附加费
|
||||
|
||||
// ------------------------------ 2. 满减活动计算(核心步骤) ------------------------------
|
||||
let usedFullReductionActivity: FullReductionActivity | undefined;
|
||||
let usedFullReductionThreshold: FullReductionThreshold | undefined;
|
||||
let fullReductionAmount = 0;
|
||||
let usedFullReductionActivityFullAmount = calcFullReductionActivityFullAmount(
|
||||
goodsList,
|
||||
usedFullReductionActivity,
|
||||
config.limitTimeDiscount,
|
||||
config.isMember,
|
||||
seatFee,
|
||||
packFee
|
||||
);
|
||||
|
||||
// 2.1 筛选最优满减活动(后端活动列表、当前店铺、就餐类型、时间)
|
||||
usedFullReductionActivity = filterOptimalFullReductionActivity(
|
||||
config.fullReductionActivities,
|
||||
@@ -1110,14 +1397,15 @@ export function calculateOrderCostSummary(
|
||||
currentTime
|
||||
);
|
||||
|
||||
// 其他费用计算(原有逻辑不变) ------------------------------
|
||||
const packFee = calcTotalPackFee(goodsList, dinnerType); // 打包费
|
||||
let seatFee = calcSeatFee(config.seatFeeConfig); // 餐位费
|
||||
seatFee = dinnerType === "dine-in" ? seatFee : 0; // 外卖不收餐位费
|
||||
const additionalFee = Math.max(0, config.additionalFee); // 附加费
|
||||
|
||||
// 2.2 计算满减基数(先扣新客立减)
|
||||
let baseAfterNewUserDiscount = new BigNumber(goodsRealAmount)
|
||||
let baseAfterNewUserDiscount = new BigNumber(
|
||||
limitTimeDiscount &&
|
||||
limitTimeDiscount.id &&
|
||||
usedFullReductionActivity &&
|
||||
!usedFullReductionActivity.discountShare
|
||||
? goodsRealAmount
|
||||
: goodsRealAmount
|
||||
)
|
||||
.minus(newUserDiscount)
|
||||
.plus(packFee)
|
||||
.plus(seatFee)
|
||||
@@ -1128,9 +1416,19 @@ export function calculateOrderCostSummary(
|
||||
|
||||
// 2.3 选择最优满减阈值(多门槛场景)
|
||||
if (usedFullReductionActivity) {
|
||||
//计算当前满减活动的门槛金额
|
||||
usedFullReductionActivityFullAmount = calcFullReductionActivityFullAmount(
|
||||
goodsList,
|
||||
usedFullReductionActivity,
|
||||
config.limitTimeDiscount,
|
||||
config.isMember,
|
||||
seatFee,
|
||||
packFee
|
||||
);
|
||||
|
||||
usedFullReductionThreshold = selectOptimalThreshold(
|
||||
usedFullReductionActivity.thresholds,
|
||||
baseAfterNewUserDiscount,
|
||||
usedFullReductionActivityFullAmount,
|
||||
goodsOriginalAmount,
|
||||
goodsRealAmount,
|
||||
usedFullReductionActivity.discountShare || 0 // 与限时折扣同享规则
|
||||
@@ -1143,6 +1441,7 @@ export function calculateOrderCostSummary(
|
||||
usedFullReductionThreshold
|
||||
);
|
||||
}
|
||||
|
||||
// ------------------------------ 3. 优惠券抵扣(适配满减同享规则) ------------------------------
|
||||
let couponDeductionAmount = 0;
|
||||
let productCouponDeduction = 0;
|
||||
@@ -1164,6 +1463,7 @@ export function calculateOrderCostSummary(
|
||||
currentTime,
|
||||
}
|
||||
);
|
||||
console.log("couponResult", couponResult);
|
||||
couponDeductionAmount = couponResult.deductionAmount;
|
||||
productCouponDeduction = couponResult.productCouponDeduction;
|
||||
fullCouponDeduction = couponResult.fullCouponDeduction;
|
||||
@@ -1171,7 +1471,10 @@ export function calculateOrderCostSummary(
|
||||
excludedProductIds = couponResult.excludedProductIds;
|
||||
|
||||
// 若满减与优惠券同享(couponShare=1),才计算优惠券;否则优惠券抵扣为0
|
||||
if (usedFullReductionActivity && !usedFullReductionActivity.couponShare) {
|
||||
if (
|
||||
usedFullReductionThreshold &&
|
||||
(!usedFullReductionActivity || !usedFullReductionActivity.couponShare)
|
||||
) {
|
||||
couponDeductionAmount = 0;
|
||||
productCouponDeduction = 0;
|
||||
fullCouponDeduction = 0;
|
||||
@@ -1195,26 +1498,26 @@ export function calculateOrderCostSummary(
|
||||
maxPointDeductionLimit =
|
||||
maxPointDeductionLimit > 0 ? maxPointDeductionLimit : 0;
|
||||
|
||||
|
||||
const pointResult = calcPointDeduction(
|
||||
config.userPoints,
|
||||
config.pointDeductionRule,
|
||||
maxPointDeductionLimit
|
||||
);
|
||||
console.log("积分抵扣结果:", pointResult);
|
||||
|
||||
pointDeductionAmount = pointResult.deductionAmount;
|
||||
usedPoints = pointResult.usedPoints;
|
||||
// 若满减与积分不同享(pointsShare=1)积分抵扣为0
|
||||
if (usedFullReductionActivity && !usedFullReductionActivity.pointsShare) {
|
||||
console.log("满减与积分不同享:积分抵扣为0");
|
||||
if (
|
||||
usedFullReductionThreshold &&
|
||||
(!usedFullReductionActivity || !usedFullReductionActivity.pointsShare)
|
||||
) {
|
||||
pointDeductionAmount = 0;
|
||||
usedPoints = 0;
|
||||
}
|
||||
|
||||
//使用霸王餐
|
||||
if (isFreeDine && freeDineConfig && freeDineConfig.enable) {
|
||||
console.log("使用霸王餐");
|
||||
fullReductionAmount = 0;
|
||||
//不与优惠券同享
|
||||
if (!freeDineConfig.withCoupon) {
|
||||
couponDeductionAmount = 0;
|
||||
@@ -1242,13 +1545,13 @@ export function calculateOrderCostSummary(
|
||||
.plus(packFee)
|
||||
.isGreaterThan(0)
|
||||
? new BigNumber(goodsRealAmount)
|
||||
.minus(newUserDiscount)
|
||||
.minus(fullReductionAmount)
|
||||
.minus(couponDeductionAmount)
|
||||
.minus(pointDeductionAmount)
|
||||
.plus(seatFee)
|
||||
.plus(packFee)
|
||||
.toNumber()
|
||||
.minus(newUserDiscount)
|
||||
.minus(fullReductionAmount)
|
||||
.minus(couponDeductionAmount)
|
||||
.minus(pointDeductionAmount)
|
||||
.plus(seatFee)
|
||||
.plus(packFee)
|
||||
.toNumber()
|
||||
: 0;
|
||||
|
||||
switch (merchantReductionConfig.type) {
|
||||
@@ -1271,9 +1574,22 @@ export function calculateOrderCostSummary(
|
||||
truncateToTwoDecimals(merchantReductionActualAmount)
|
||||
);
|
||||
|
||||
// 会员折扣减免
|
||||
const vipDiscountAmount = calcVipDiscountAmount(
|
||||
new BigNumber(goodsRealAmount)
|
||||
.minus(couponDeductionAmount)
|
||||
.plus(packFee)
|
||||
.plus(seatFee)
|
||||
.minus(newUserDiscount)
|
||||
.minus(fullReductionAmount)
|
||||
.toNumber(),
|
||||
shopUserInfo
|
||||
);
|
||||
console.log("vipDiscountAmount", vipDiscountAmount);
|
||||
// ------------------------------ 6. 最终实付金额计算 ------------------------------
|
||||
const finalPayAmountBn = new BigNumber(goodsRealAmount)
|
||||
.minus(newUserDiscount)
|
||||
.minus(vipDiscountAmount)
|
||||
.minus(fullReductionAmount)
|
||||
.minus(couponDeductionAmount)
|
||||
.minus(pointDeductionAmount)
|
||||
@@ -1301,6 +1617,7 @@ export function calculateOrderCostSummary(
|
||||
.plus(couponDeductionAmount)
|
||||
.plus(pointDeductionAmount)
|
||||
.plus(merchantReductionActualAmount)
|
||||
.plus(vipDiscountAmount)
|
||||
.toNumber()
|
||||
);
|
||||
//积分可抵扣最大金额 最终支付金额+积分抵扣-商家减免
|
||||
@@ -1331,10 +1648,12 @@ export function calculateOrderCostSummary(
|
||||
scoreMaxMoney,
|
||||
// 满减活动明细(后端字段)
|
||||
fullReduction: {
|
||||
usedFullReductionActivityFullAmount: usedFullReductionActivityFullAmount,
|
||||
usedActivity: usedFullReductionActivity,
|
||||
usedThreshold: usedFullReductionThreshold,
|
||||
actualAmount: truncateToTwoDecimals(fullReductionAmount),
|
||||
},
|
||||
vipDiscountAmount: vipDiscountAmount, //会员折扣减免金额
|
||||
merchantReduction: {
|
||||
type: merchantReductionConfig.type,
|
||||
originalConfig: merchantReductionConfig,
|
||||
|
||||
183
src/utils/order-utils.js
Normal file
183
src/utils/order-utils.js
Normal file
@@ -0,0 +1,183 @@
|
||||
import BigNumber from "bignumber.js";
|
||||
|
||||
//判断商品是否可以使用限时折扣
|
||||
export function canUseLimitTimeDiscount(
|
||||
goods,
|
||||
limitTimeDiscountRes,
|
||||
shopInfo,
|
||||
shopUserInfo,
|
||||
idKey = "id"
|
||||
) {
|
||||
shopInfo = shopInfo || {};
|
||||
shopUserInfo = shopUserInfo || {};
|
||||
if (!limitTimeDiscountRes || !limitTimeDiscountRes.id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const canUseFoods = (limitTimeDiscountRes.foods || "").split(",");
|
||||
|
||||
const goodsCanUse =
|
||||
limitTimeDiscountRes.foodType == 1 ||
|
||||
canUseFoods.includes(`${goods[idKey]}`);
|
||||
if (!goodsCanUse) {
|
||||
return false;
|
||||
}
|
||||
if (limitTimeDiscountRes.discountPriority == "limit-time") {
|
||||
return true;
|
||||
}
|
||||
if (limitTimeDiscountRes.discountPriority == "vip-price") {
|
||||
if (shopUserInfo.isVip != 1 || shopUserInfo.isMemberPrice != 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (
|
||||
shopUserInfo.isVip == 1 &&
|
||||
shopUserInfo.isMemberPrice == 1 &&
|
||||
goods.memberPrice * 1 <= 0
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回商品显示价格
|
||||
* @params {*} args 参数对象
|
||||
* @params {*} args.goods 商品对象
|
||||
* @params {*} args.shopInfo 店铺信息
|
||||
* @params {*} args.limitTimeDiscountRes 限时折扣信息
|
||||
* @params {*} args.shopUserInfo 店铺用户信息
|
||||
* @returns
|
||||
*/
|
||||
export function returnPrice(args) {
|
||||
let {
|
||||
goods,
|
||||
shopInfo,
|
||||
limitTimeDiscountRes,
|
||||
shopUserInfo,
|
||||
idKey = "product_id",
|
||||
} = args;
|
||||
|
||||
console.log('返回商品显示价格.args===', args);
|
||||
|
||||
|
||||
limitTimeDiscountRes = limitTimeDiscountRes || { foods: '', foodType: 2 }
|
||||
const canUseFoods = (limitTimeDiscountRes.foods || "").split(",");
|
||||
|
||||
// console.log('返回商品显示价格.goods===', goods);
|
||||
|
||||
const includesGoods =
|
||||
limitTimeDiscountRes.foodType == 1 ||
|
||||
canUseFoods.includes("" + goods[idKey]);
|
||||
|
||||
|
||||
console.log('includesGoods===', includesGoods);
|
||||
|
||||
shopInfo = shopInfo || {};
|
||||
shopUserInfo = shopUserInfo || {};
|
||||
if (shopUserInfo.isMemberPrice == 1 && shopUserInfo.isVip == 1 && shopInfo.isMemberPrice == 1) {
|
||||
const memberPrice = goods.memberPrice || goods.salePrice;
|
||||
|
||||
//是会员而且启用会员价
|
||||
if (limitTimeDiscountRes) {
|
||||
//使用限时折扣
|
||||
//限时折扣优先
|
||||
if (limitTimeDiscountRes.discountPriority == "limit-time") {
|
||||
if (includesGoods) {
|
||||
return returnLimitPrice({
|
||||
price: goods.salePrice,
|
||||
limitTimeDiscountRes,
|
||||
});
|
||||
} else {
|
||||
return memberPrice;
|
||||
}
|
||||
}
|
||||
if (
|
||||
limitTimeDiscountRes.discountPriority == "vip-price" &&
|
||||
includesGoods
|
||||
) {
|
||||
if (goods.memberPrice * 1 > 0) {
|
||||
//会员优先
|
||||
return memberPrice;
|
||||
} else {
|
||||
const price = returnLimitPrice({
|
||||
price: goods.salePrice,
|
||||
limitTimeDiscountRes,
|
||||
goods: goods,
|
||||
});
|
||||
|
||||
return price;
|
||||
}
|
||||
} else {
|
||||
return memberPrice;
|
||||
}
|
||||
} else {
|
||||
//是会员没有限时折扣
|
||||
return memberPrice;
|
||||
}
|
||||
} else {
|
||||
// console.log('不是会员或者没有启用会员价',goods,limitTimeDiscountRes);
|
||||
//不是会员或者没有启用会员价
|
||||
if (limitTimeDiscountRes && limitTimeDiscountRes.id && includesGoods) {
|
||||
const price = returnLimitPrice({
|
||||
price: goods.salePrice,
|
||||
limitTimeDiscountRes,
|
||||
goods: goods,
|
||||
});
|
||||
|
||||
return price;
|
||||
} else {
|
||||
return goods.salePrice;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回限时折扣价格
|
||||
* @params {*} args 参数对象
|
||||
* @params {*} args.limitTimeDiscountRes 限时折扣信息
|
||||
* @params {*} args.price 商品价格
|
||||
* @param {*} args.goods 商品对象
|
||||
* @returns
|
||||
*/
|
||||
export function returnLimitPrice(args) {
|
||||
console.log('返回限时折扣价格===', args);
|
||||
|
||||
const { limitTimeDiscountRes, price, goods } = args;
|
||||
const discountRate = new BigNumber(
|
||||
limitTimeDiscountRes.discountRate
|
||||
).dividedBy(100);
|
||||
|
||||
const result = BigNumber(price)
|
||||
.times(discountRate)
|
||||
.decimalPlaces(2, BigNumber.ROUND_UP)
|
||||
.toNumber();
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否返回会员价
|
||||
* @param {*} args 参数对象
|
||||
* @param {*} args.shopInfo 店铺信息
|
||||
* @param {*} args.shopUserInfo 店铺用户信息
|
||||
* @returns
|
||||
*/
|
||||
export function canReturnMemberPrice(args) {
|
||||
const { shopInfo, shopUserInfo } = args;
|
||||
if (shopUserInfo.isMemberPrice == 1 && shopUserInfo.isVip == 1) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回会员价格
|
||||
* @param {*} goods
|
||||
* @returns
|
||||
*/
|
||||
export function returnMemberPrice(goods) {
|
||||
return goods.memberPrice || goods.salePrice;
|
||||
}
|
||||
@@ -387,10 +387,10 @@ export default {
|
||||
conName: v.conName,
|
||||
purchasePrice: v.price,
|
||||
unitName: v.conUnit,
|
||||
inOutNumber,
|
||||
inOutNumber: v.number,
|
||||
subTotal: this.xiaoji(v),
|
||||
imgUrls: v.imgUrls,
|
||||
number: v.number,
|
||||
number: inOutNumber,
|
||||
};
|
||||
});
|
||||
if (this.type == "in") {
|
||||
|
||||
@@ -37,7 +37,11 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="会员" prop="memberLevelName">
|
||||
<template #default="scope">
|
||||
{{ scope.row.memberLevelName.length > 0 ? scope.row.memberLevelName : '否' }}
|
||||
<span v-if="scope.row.isVip == 1">
|
||||
<template v-if="scope.row.memberLevelName.length > 0"> {{ scope.row.memberLevelName }}</template>
|
||||
<template v-else>是</template>
|
||||
</span>
|
||||
<span v-else>否</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="分销员" prop="distributionShops">
|
||||
|
||||
@@ -217,6 +217,7 @@ async function getTableData() {
|
||||
if (tabIndex.value == 0) {
|
||||
res = await distributionUserInviteUser({
|
||||
id: rowInfo.value.id,
|
||||
shopId: rowInfo.value.shopId,
|
||||
page: tableData.page,
|
||||
size: tableData.size,
|
||||
shopUserId: querForm.value.userId,
|
||||
@@ -225,6 +226,7 @@ async function getTableData() {
|
||||
} else {
|
||||
res = await distributionFlowGet({
|
||||
id: rowInfo.value.id,
|
||||
shopId: rowInfo.value.shopId,
|
||||
parentId: rowInfo.value.id,
|
||||
shopUserId: querForm.value.userId,
|
||||
distributionLevelId: querForm.value.distributionLevelId,
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="关联订单号" prop="orderNo" min-width="200"></el-table-column>
|
||||
<el-table-column label="总收益(元)" prop="rewardAmount" min-width="120">
|
||||
<el-table-column label="收益(元)" prop="rewardAmount" min-width="120">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.status == 'refund'">-</span>
|
||||
{{ multiplyAndFormat(scope.row.rewardAmount || 0) }}
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="分销员等级" prop="distributionLevelName" width="100"></el-table-column>
|
||||
<el-table-column label="总收益(元)" prop="totalIncome" width="100">
|
||||
<template #default="scope">
|
||||
{{ multiplyAndFormat(scope.row.totalIncome || 0) }}
|
||||
|
||||
@@ -69,6 +69,7 @@ async function submitHandle() {
|
||||
confirmLoading.value = true
|
||||
let data = {}
|
||||
data.id = rowInfo.value.id
|
||||
data.shopId = rowInfo.value.shopId
|
||||
if (type.value == 1) {
|
||||
data.isAssignLevel = 1
|
||||
data.distributionLevelId = form.value.distributionLevelId
|
||||
|
||||
@@ -48,7 +48,15 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="变动金额(元)" prop="changeAmount"></el-table-column>
|
||||
<el-table-column label="变动后金额(元)" prop="amount"></el-table-column>
|
||||
<el-table-column label="变动原因" prop="remark"></el-table-column>
|
||||
<el-table-column label="变动原因" prop="remark">
|
||||
<template #default="scope">
|
||||
<div class="column" v-if="scope.row.type == 'manual_recharge' || scope.row.type == 'manual_sub'">
|
||||
<span>{{ scope.row.remark }}</span>
|
||||
<span class="info">操作员:{{ scope.row.opAccount }}</span>
|
||||
</div>
|
||||
<span v-else>{{ scope.row.remark }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="关联订单" prop="orderNo"></el-table-column>
|
||||
<el-table-column label="创建时间" prop="createTime"></el-table-column>
|
||||
</el-table>
|
||||
@@ -77,7 +85,7 @@ const info = ref({
|
||||
const statusList = ref([
|
||||
{
|
||||
value: 'manual_recharge',
|
||||
label: '充值'
|
||||
label: '手动充值'
|
||||
},
|
||||
{
|
||||
value: 'self_recharge',
|
||||
@@ -194,4 +202,14 @@ defineExpose({
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.info {
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -63,7 +63,7 @@
|
||||
<div class="title_row">
|
||||
分销员等级
|
||||
</div>
|
||||
<el-form-item label="条件升级" style="margin-top: 14px;" prop="upgradeType">
|
||||
<el-form-item label="升级条件" style="margin-top: 14px;" prop="upgradeType">
|
||||
<el-radio-group v-model="form.upgradeType" @change="upgradeTypeChange">
|
||||
<el-radio label="不自动升级" value="not_upgrade"></el-radio>
|
||||
<el-radio label="邀请有效人数" value="invite"></el-radio>
|
||||
@@ -163,7 +163,7 @@
|
||||
<el-form-item style="margin-top: 24px;">
|
||||
<el-button type="primary" @click="addLevelHandle">添加等级</el-button>
|
||||
</el-form-item>
|
||||
<div class="title_row mt14">未开通页面营销</div>
|
||||
<div class="title_row mt14">未开通页面</div>
|
||||
<el-form-item :label-width="0" style="margin-top: 14px;">
|
||||
<WangEditor v-model="form.notActivatedPage" />
|
||||
</el-form-item>
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
<div class="gyq_content">
|
||||
<HeaderCard name="分销" intro="用户成为业务员,可促进消费" icon="xffx" showSwitch v-model:isOpen="form.isEnable">
|
||||
</HeaderCard>
|
||||
<div class="tips">
|
||||
<el-alert title="请记得前往《分销明细》充值余额,余额不足时用户收益将无法正常入账" type="primary" show-icon :closable="false" />
|
||||
</div>
|
||||
<div class="row mt14">
|
||||
<tabHeader v-model="tabActiveIndex" :list="tabList" />
|
||||
</div>
|
||||
@@ -111,4 +114,8 @@ onMounted(() => {
|
||||
margin-top: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.tips {
|
||||
margin-top: 14px;
|
||||
}
|
||||
</style>
|
||||
@@ -8,10 +8,10 @@
|
||||
<div class="preview">
|
||||
<div class="info">
|
||||
<div class="top">
|
||||
<div class="title">{{ form.title || '请输入模块标题' }}</div>
|
||||
<div class="title">{{ form.title || defaultTitle }}</div>
|
||||
<div class="content">{{ form.content || '请输入模块内容' }}</div>
|
||||
</div>
|
||||
<div class="btm">{{ form.note || '请输入模块提示语' }}</div>
|
||||
<div class="btm">{{ form.note || defaultNote }}</div>
|
||||
</div>
|
||||
<div class="img_wrap">
|
||||
<el-image :src="form.qrCode" style="width: 100%;height: 100%;"></el-image>
|
||||
@@ -32,7 +32,7 @@
|
||||
<single-image-upload style="width: 120px; height: 120px" v-model="form.qrCode"></single-image-upload>
|
||||
</el-form-item>
|
||||
<el-form-item label="模块标题" prop="title">
|
||||
<el-input placeholder="请输入模块标题" :maxlength="20" v-model.trim="form.title"></el-input>
|
||||
<el-input :placeholder="defaultTitle" :maxlength="20" v-model.trim="form.title"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="模块内容">
|
||||
<div class="textarea">
|
||||
@@ -42,7 +42,7 @@
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="模块提示语">
|
||||
<el-input placeholder="请输模块提示语" :maxlength="20" v-model.trim="form.note"></el-input>
|
||||
<el-input :placeholder="defaultNote" :maxlength="20" v-model.trim="form.note"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" :loading="loading" @click="submitHandle">保存</el-button>
|
||||
@@ -59,13 +59,14 @@ import { ref, reactive, onMounted } from 'vue'
|
||||
import { ElNotification } from 'element-plus'
|
||||
import { drainageConfigGet, drainageConfigPost } from '@/api/coupon/index'
|
||||
|
||||
const defaultTitle = ref('扫码进群,优惠多多')
|
||||
const defaultNote = ref('长按识别,微信内扫一扫加好友')
|
||||
|
||||
const form = ref({
|
||||
id: '',
|
||||
useType: ['dine-in'],
|
||||
qrCode: '',
|
||||
title: '',
|
||||
title: defaultTitle.value,
|
||||
content: '',
|
||||
note: '长按识别,微信内扫一扫加好友',
|
||||
isEnable: '',
|
||||
@@ -129,6 +130,14 @@ function submitHandle() {
|
||||
|
||||
let data = { ...form.value }
|
||||
|
||||
if (data.title == '') {
|
||||
data.title = defaultTitle.value
|
||||
}
|
||||
|
||||
if (data.note == '') {
|
||||
data.note = defaultNote.value
|
||||
}
|
||||
|
||||
await drainageConfigPost(data);
|
||||
ElNotification({
|
||||
title: '注意',
|
||||
@@ -151,6 +160,13 @@ async function drainageConfigGetAjax() {
|
||||
res.useType = []
|
||||
}
|
||||
form.value = res
|
||||
|
||||
if (form.value.title == '') {
|
||||
form.value.title = defaultTitle.value
|
||||
}
|
||||
if (form.value.note == '') {
|
||||
form.value.note = defaultNote.value
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ const statusList = ref([
|
||||
},
|
||||
{
|
||||
value: 2,
|
||||
label: '发送成功',
|
||||
label: '发送完成',
|
||||
type: 'success'
|
||||
},
|
||||
{
|
||||
|
||||
@@ -28,8 +28,8 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="变动原因" prop="reason"></el-table-column>
|
||||
<el-table-column label="变动前余额" prop="balance"></el-table-column>
|
||||
<el-table-column label="变动金额" prop="expense"></el-table-column>
|
||||
<el-table-column label="变动后余额" prop="balance"></el-table-column>
|
||||
<el-table-column label="创建时间" prop="createTime"></el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
<el-radio-button :label="1">可选套餐</el-radio-button>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div v-if="ruleForm.groupType == '0'">
|
||||
<div v-if="ruleForm.groupType == 0">
|
||||
<el-table border :data="item.goods" v-for="(item, index) in ruleForm.proGroupVo" :key="index">
|
||||
<el-table-column label="名称" prop="proName"></el-table-column>
|
||||
<el-table-column label="规格" prop="skuName"></el-table-column>
|
||||
@@ -95,7 +95,7 @@
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<div v-if="ruleForm.groupType == '1'">
|
||||
<div v-if="ruleForm.groupType == 1">
|
||||
<div class="group_wrap" v-for="(item, index) in ruleForm.proGroupVo" :key="index">
|
||||
<el-form inline :model="item">
|
||||
<el-form-item label="规格组名">
|
||||
@@ -382,7 +382,7 @@ const ruleForm = reactive<RuleForm>({
|
||||
// 规格id
|
||||
specId: "",
|
||||
// 套餐类型
|
||||
groupType: "0",
|
||||
groupType: 0,
|
||||
// 套餐入参
|
||||
proGroupVo: [
|
||||
{
|
||||
@@ -569,7 +569,7 @@ function selectShopRes(res: Array<any>) {
|
||||
return item;
|
||||
});
|
||||
|
||||
if (ruleForm.groupType == "0") {
|
||||
if (ruleForm.groupType == 0) {
|
||||
let obj = {
|
||||
title: "",
|
||||
count: newres.length,
|
||||
@@ -726,7 +726,7 @@ function cartesian(arr) {
|
||||
// 套餐类型切换
|
||||
function typeChange() {
|
||||
// ruleForm.typeEnum = 'normal'
|
||||
if (ruleForm.groupType == "0") {
|
||||
if (ruleForm.groupType == 0) {
|
||||
ruleForm.proGroupVo = [];
|
||||
ruleForm.proGroupVo[0] = {
|
||||
title: "",
|
||||
@@ -783,7 +783,7 @@ const submitForm = async (formEl: FormInstance | undefined) => {
|
||||
|
||||
// 标题和几选几是否填写
|
||||
if (ruleForm.type == "package") {
|
||||
if (ruleForm.groupType == "1") {
|
||||
if (ruleForm.groupType == 1) {
|
||||
let selectTitle = false;
|
||||
ruleForm.proGroupVo.forEach((item: any) => {
|
||||
if (item.number == "" || item.title == "") {
|
||||
|
||||
@@ -3,25 +3,14 @@
|
||||
<div>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="160px" label-position="left">
|
||||
<el-form-item label="门店名称" prop="shopName">
|
||||
<el-input
|
||||
v-model.trim="form.shopName"
|
||||
placeholder="请输入门店名称"
|
||||
style="width: 500px"
|
||||
></el-input>
|
||||
<el-input v-model.trim="form.shopName" placeholder="请输入门店名称" style="width: 500px"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="连锁店扩展店名">
|
||||
<el-input
|
||||
v-model.trim="form.chainName"
|
||||
placeholder="请输入连锁店扩展店名"
|
||||
style="width: 500px"
|
||||
></el-input>
|
||||
<el-input v-model.trim="form.chainName" placeholder="请输入连锁店扩展店名" style="width: 500px"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="门店logo">
|
||||
<div class="img_box">
|
||||
<single-image-upload
|
||||
style="width: 80px; height: 80px"
|
||||
v-model="form.logo"
|
||||
></single-image-upload>
|
||||
<single-image-upload style="width: 80px; height: 80px" v-model="form.logo"></single-image-upload>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="门店照片">
|
||||
@@ -38,37 +27,21 @@
|
||||
<el-form-item label="门店收款码">
|
||||
<div class="img_box">
|
||||
<canvas ref="canvas" id="QRCode_header" style="width: 80px; height: 80px"></canvas>
|
||||
<el-button
|
||||
size="small"
|
||||
plain
|
||||
v-if="form.paymentQrcode"
|
||||
@click="downloadCanvas(form.paymentQrcode)"
|
||||
>
|
||||
<el-button size="small" plain v-if="form.paymentQrcode" @click="downloadCanvas(form.paymentQrcode)">
|
||||
下载
|
||||
</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="微信二维码">
|
||||
<div class="img_box">
|
||||
<single-image-upload
|
||||
style="width: 80px; height: 80px"
|
||||
v-model="form.shopQrcode"
|
||||
></single-image-upload>
|
||||
<single-image-upload style="width: 80px; height: 80px" v-model="form.shopQrcode"></single-image-upload>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="店铺小程序码">
|
||||
<div class="img_box">
|
||||
<el-image
|
||||
:src="form.smallQrcode || img_download_error"
|
||||
fit="contain"
|
||||
style="width: 80px; height: 80px"
|
||||
></el-image>
|
||||
<el-button
|
||||
size="small"
|
||||
plain
|
||||
v-if="form.shopQrcode"
|
||||
@click="downloadImgHandle(form.smallQrcode)"
|
||||
>
|
||||
<el-image :src="form.smallQrcode || img_download_error" fit="contain"
|
||||
style="width: 80px; height: 80px"></el-image>
|
||||
<el-button size="small" plain v-if="form.shopQrcode" @click="downloadImgHandle(form.smallQrcode)">
|
||||
下载
|
||||
</el-button>
|
||||
</div>
|
||||
@@ -92,11 +65,7 @@
|
||||
</el-radio-group>
|
||||
</el-form-item> -->
|
||||
<el-form-item label="联系电话" prop="phone">
|
||||
<el-input
|
||||
v-model.trim="form.phone"
|
||||
placeholder="请输入联系电话"
|
||||
style="width: 500px"
|
||||
></el-input>
|
||||
<el-input v-model.trim="form.phone" placeholder="请输入联系电话" style="width: 500px"></el-input>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="外卖起送金额">
|
||||
<el-input-number v-model="form.takeaway_money" placeholder="0.00" controls-position="right"
|
||||
@@ -122,83 +91,43 @@
|
||||
<div style="color: #999">注:准确的定位便于用户导航到店铺</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="门店详细地址">
|
||||
<el-input
|
||||
type="textarea"
|
||||
v-model.trim="form.address"
|
||||
placeholder="请输入门店详细地址"
|
||||
style="width: 500px"
|
||||
></el-input>
|
||||
<el-input type="textarea" v-model.trim="form.address" placeholder="请输入门店详细地址" style="width: 500px"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="营业时间">
|
||||
<div class="u-flex gap-2" style="width: 50%">
|
||||
<el-select v-model="form.businessStartDay" placeholder="周几开始">
|
||||
<el-option
|
||||
:value="item.label"
|
||||
:label="item.label"
|
||||
v-for="item in weeks"
|
||||
:key="item.value"
|
||||
></el-option>
|
||||
<el-option :value="item.label" :label="item.label" v-for="item in weeks" :key="item.value"></el-option>
|
||||
</el-select>
|
||||
<el-select v-model="form.businessEndDay" placeholder="周几结束">
|
||||
<el-option
|
||||
:value="item.label"
|
||||
:label="item.label"
|
||||
v-for="item in weeks"
|
||||
:key="item.value"
|
||||
></el-option>
|
||||
<el-option :value="item.label" :label="item.label" v-for="item in weeks" :key="item.value"></el-option>
|
||||
</el-select>
|
||||
<el-time-picker
|
||||
placeholder="起始时间"
|
||||
v-model="startTime"
|
||||
:picker-options="{
|
||||
selectableRange: '00:00:00 - 23:59:59',
|
||||
format: 'HH:mm',
|
||||
}"
|
||||
format="HH:mm"
|
||||
value-format="HH:mm"
|
||||
></el-time-picker>
|
||||
<el-time-picker
|
||||
placeholder="结束时间"
|
||||
v-model="endTime"
|
||||
:picker-options="{
|
||||
selectableRange: '00:00:00 - 23:59:59',
|
||||
}"
|
||||
format="HH:mm"
|
||||
value-format="HH:mm"
|
||||
></el-time-picker>
|
||||
<el-time-picker placeholder="起始时间" v-model="startTime" :picker-options="{
|
||||
selectableRange: '00:00:00 - 23:59:59',
|
||||
format: 'HH:mm',
|
||||
}" format="HH:mm" value-format="HH:mm"></el-time-picker>
|
||||
<el-time-picker placeholder="结束时间" v-model="endTime" :picker-options="{
|
||||
selectableRange: '00:00:00 - 23:59:59',
|
||||
}" format="HH:mm" value-format="HH:mm"></el-time-picker>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="桌位费/位/元">
|
||||
<el-input-number :disabled="!!form.isTableFee" v-model="form.tableFee" :min="0" />
|
||||
<!-- <el-checkbox v-model="form.isTableFee" :label="1">免餐位费</el-checkbox> -->
|
||||
<el-switch
|
||||
class="u-m-l-10"
|
||||
v-model.trim="form.isTableFee"
|
||||
:active-value="1"
|
||||
:inactive-value="0"
|
||||
active-text="免餐位费"
|
||||
></el-switch>
|
||||
<el-switch class="u-m-l-10" v-model.trim="form.isTableFee" :active-value="1" :inactive-value="0"
|
||||
active-text="免餐位费"></el-switch>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="是否开启8折活动">
|
||||
<el-switch v-model.trim="form.isOpenYhq" active-value="true" inactive-value="false"></el-switch>
|
||||
<div style="color: #999;">是否允许用户在小程序端支付订单</div>
|
||||
</el-form-item> -->
|
||||
<el-form-item label="是否启用商品会员价">
|
||||
<el-switch
|
||||
v-model.trim="form.isMemberPrice"
|
||||
:active-value="1"
|
||||
::inactive-value="0"
|
||||
></el-switch>
|
||||
<!-- <div style="color: #999;">是否允许用户在小程序端支付订单</div> -->
|
||||
<!-- <el-form-item label="是否启用商品会员价">
|
||||
<el-switch v-model.trim="form.isMemberPrice" :active-value="1" ::inactive-value="0"></el-switch>
|
||||
<div style="color: #999;">是否允许用户在小程序端支付订单</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否开启会员余额支付">
|
||||
<el-switch
|
||||
v-model.trim="form.isAccountPay"
|
||||
:active-value="1"
|
||||
:inactive-value="0"
|
||||
></el-switch>
|
||||
<!-- <div style="color: #999;">是否允许用户在小程序端支付订单</div> -->
|
||||
</el-form-item>
|
||||
<el-switch v-model.trim="form.isAccountPay" :active-value="1" :inactive-value="0"></el-switch>
|
||||
<div style="color: #999;">是否允许用户在小程序端支付订单</div>
|
||||
</el-form-item> -->
|
||||
<!-- <el-form-item label="结算类型">
|
||||
<el-radio-group v-model="form.settleType">
|
||||
<el-radio :label="0">今日</el-radio>
|
||||
@@ -219,20 +148,11 @@
|
||||
</el-time-picker>
|
||||
</el-form-item> -->
|
||||
<el-form-item label="店铺简介">
|
||||
<el-input
|
||||
type="textarea"
|
||||
v-model.trim="form.detail"
|
||||
placeholder="请输入店铺简介"
|
||||
style="width: 500px"
|
||||
></el-input>
|
||||
<el-input type="textarea" v-model.trim="form.detail" placeholder="请输入店铺简介" style="width: 500px"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="台桌预订短信">
|
||||
<el-input
|
||||
type="textarea"
|
||||
v-model.trim="form.bookingSms"
|
||||
placeholder="请输入台桌预订短信"
|
||||
style="width: 500px"
|
||||
></el-input>
|
||||
<el-input type="textarea" v-model.trim="form.bookingSms" placeholder="请输入台桌预订短信"
|
||||
style="width: 500px"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态">
|
||||
<el-radio-group v-model="form.status">
|
||||
@@ -249,24 +169,11 @@
|
||||
</el-form>
|
||||
</div>
|
||||
<ChooseAddress ref="refChooseAddress" @choose="chooseAddressConfirm"></ChooseAddress>
|
||||
<el-dialog
|
||||
v-model="showUpload"
|
||||
:close-on-click-modal="false"
|
||||
append-to-body
|
||||
width="500px"
|
||||
@close="showUpload = false"
|
||||
>
|
||||
<el-upload
|
||||
:before-remove="handleBeforeRemove"
|
||||
:on-success="handleSuccess"
|
||||
:on-error="handleError"
|
||||
:file-list="fileList"
|
||||
:headers="headers"
|
||||
:action="qiNiuUploadApi"
|
||||
:limit="1"
|
||||
list-type="picture"
|
||||
class="upload-demo"
|
||||
>
|
||||
<el-dialog v-model="showUpload" :close-on-click-modal="false" append-to-body width="500px"
|
||||
@close="showUpload = false">
|
||||
<el-upload :before-remove="handleBeforeRemove" :on-success="handleSuccess" :on-error="handleError"
|
||||
:file-list="fileList" :headers="headers" :action="qiNiuUploadApi" :limit="1" list-type="picture"
|
||||
class="upload-demo">
|
||||
<el-button size="small" type="primary">点击上传</el-button>
|
||||
<template #tip>
|
||||
<div style="display: block" class="el-upload__tip">请勿上传违法文件,且文件不超过15M</div>
|
||||
@@ -465,7 +372,6 @@ export default {
|
||||
...this.form,
|
||||
eatModel: this.form.eatModel.join(","),
|
||||
});
|
||||
this.formLoading = false;
|
||||
ElMessage.success({
|
||||
title: "成功",
|
||||
message: "提交成功",
|
||||
@@ -473,7 +379,8 @@ export default {
|
||||
setTimeout(() => {
|
||||
// location.reload();
|
||||
}, 1000);
|
||||
} catch (error) {}
|
||||
} catch (error) { }
|
||||
this.formLoading = false;
|
||||
}
|
||||
});
|
||||
},
|
||||
@@ -487,7 +394,7 @@ export default {
|
||||
handleBeforeRemove(file, fileList) {
|
||||
for (let i = 0; i < this.files.length; i++) {
|
||||
if (this.files[i].uid === file.uid) {
|
||||
crudQiNiu.del([this.files[i].id]).then((res) => {});
|
||||
crudQiNiu.del([this.files[i].id]).then((res) => { });
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,10 +30,7 @@
|
||||
<div class="isSeatFee img u-line-1 u-flex u-col-center u-row-center" v-if="isSeatFee">
|
||||
<span>{{ item.name }}</span>
|
||||
</div>
|
||||
<div
|
||||
class="isSeatFee img u-line-1 u-flex u-col-center u-row-center"
|
||||
v-else-if="item.is_temporary"
|
||||
>
|
||||
<div class="isSeatFee img u-line-1 u-flex u-col-center u-row-center" v-else-if="item.is_temporary">
|
||||
<span>临时菜</span>
|
||||
</div>
|
||||
<img v-else :src="item.coverImg" class="" alt="" />
|
||||
@@ -62,7 +59,9 @@
|
||||
<div class="note" v-if="item.remark">备注:{{ item.remark }}</div>
|
||||
<div class="note flex" v-else>
|
||||
<span>备注:</span>
|
||||
<el-icon v-if="!isOld" @click="editNote" color="#999"><EditPen /></el-icon>
|
||||
<el-icon v-if="!isOld" @click="editNote" color="#999">
|
||||
<EditPen />
|
||||
</el-icon>
|
||||
</div>
|
||||
</div>
|
||||
<div class="note" v-if="placeNum != 0 && item.note">备注:{{ item.remark || "" }}</div>
|
||||
@@ -75,17 +74,13 @@
|
||||
<div class="" v-else>X{{ item.number }}</div>
|
||||
<div class="absolute" v-if="canChangeNumber">
|
||||
<div class="order-input-number">
|
||||
<el-icon color="#d8d8d8" size="22" @click="changeOrderNumber(-1)"><Remove /></el-icon>
|
||||
<el-icon color="#d8d8d8" size="22" @click="changeOrderNumber(-1)">
|
||||
<Remove />
|
||||
</el-icon>
|
||||
|
||||
<div style="width: 60px; margin: 0 4px" class="number-box">
|
||||
<el-input
|
||||
:min="0"
|
||||
type="number"
|
||||
@input="cartGoodsNumberInput"
|
||||
@change="cartGoodsNumberChange"
|
||||
v-model="number"
|
||||
placeholder="0"
|
||||
></el-input>
|
||||
<el-input :min="0" type="number" @input="cartGoodsNumberInput" @change="cartGoodsNumberChange"
|
||||
v-model="number" placeholder="0"></el-input>
|
||||
</div>
|
||||
<el-icon color="#22bf64" size="22" @click="changeOrderNumber(1)">
|
||||
<CirclePlusFilled />
|
||||
@@ -93,7 +88,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="color-333 total-price">
|
||||
<template v-if="item.is_gift || item.status == 'return'">
|
||||
<div>¥0</div>
|
||||
@@ -103,28 +97,32 @@
|
||||
</div>
|
||||
</template>
|
||||
<!-- 单品改价 -->
|
||||
<template
|
||||
v-else-if="
|
||||
item.discount_sale_amount * 1 > 0 &&
|
||||
discount_before_price != allPrice &&
|
||||
!item.is_temporary
|
||||
"
|
||||
>
|
||||
<template v-else-if="
|
||||
item.discount_sale_amount * 1 > 0 &&
|
||||
discount_before_price != allPrice &&
|
||||
!item.is_temporary
|
||||
">
|
||||
<div>¥{{ to2(allPrice) }}</div>
|
||||
<div class="free-price">
|
||||
<span>¥{{ to2(discount_before_price) }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div>
|
||||
<div v-if="item.isLimitDiscount || item.is_time_discount">
|
||||
<div>
|
||||
¥{{ to2(item.limitDiscountPrice) }}
|
||||
</div>
|
||||
<div class="free-price">
|
||||
<span>¥{{ to2(item.salePrice) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div v-if="useVipPrice && vipAllPrice * 1 != allPrice * 1">
|
||||
¥{{ to2(vipAllPrice) }}
|
||||
</div>
|
||||
<div
|
||||
:class="{
|
||||
'free-price': useVipPrice && vipAllPrice != allPrice,
|
||||
}"
|
||||
>
|
||||
<div :class="{
|
||||
'free-price': useVipPrice && vipAllPrice != allPrice,
|
||||
}">
|
||||
<span>¥{{ to2(allPrice) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -349,7 +347,7 @@ onMounted(() => {
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
|
||||
> span {
|
||||
>span {
|
||||
display: block;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
@@ -367,6 +365,7 @@ onMounted(() => {
|
||||
|
||||
.pack {
|
||||
background: #35ac6a;
|
||||
|
||||
.number {
|
||||
background: #f56c6c;
|
||||
color: #fff;
|
||||
@@ -379,8 +378,10 @@ onMounted(() => {
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.tui {
|
||||
position: relative;
|
||||
|
||||
.number {
|
||||
background: #f56c6c;
|
||||
color: #fff;
|
||||
@@ -393,6 +394,7 @@ onMounted(() => {
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.da {
|
||||
background: #35ac6a;
|
||||
}
|
||||
|
||||
@@ -1,58 +1,34 @@
|
||||
<template>
|
||||
<div class="goods-item">
|
||||
<el-image
|
||||
v-if="item.coverImg"
|
||||
class="goods-image"
|
||||
:src="item.coverImg + '?x-oss-process=image/resize,m_lfit,w_100,h_100'"
|
||||
fit="cover"
|
||||
></el-image>
|
||||
<el-image v-if="item.coverImg" class="goods-image"
|
||||
:src="item.coverImg + '?x-oss-process=image/resize,m_lfit,w_100,h_100'" fit="cover"></el-image>
|
||||
<div class="info" @click="itemClick">
|
||||
<div class="name u-flex u-flex-wrap">
|
||||
<span class="weight" v-if="item.type == 'weight'">称重</span>
|
||||
<span class="u-line-3">{{ item.name }}</span>
|
||||
</div>
|
||||
<div class="">¥{{ item.lowPrice }}</div>
|
||||
<div class="" v-if="item.isLimitDiscount">
|
||||
<span class="o_price">¥{{ item.lowPrice }}</span>
|
||||
<span>¥{{ item.limitDiscountPrice }}</span>
|
||||
</div>
|
||||
<div v-else>¥{{ item.lowPrice }}</div>
|
||||
</div>
|
||||
<div
|
||||
class="status"
|
||||
v-if="
|
||||
item.isSoldStock ||
|
||||
!item.isSale ||
|
||||
!item.isSaleTime ||
|
||||
(item.isStock && item.stockNumber * 1 <= 0)
|
||||
"
|
||||
>
|
||||
<svg-icon
|
||||
@click="ElMessage.error('该商品已下架')"
|
||||
v-if="!item.isSale"
|
||||
iconClass="yi-xiajia"
|
||||
color="#fff"
|
||||
size="60"
|
||||
></svg-icon>
|
||||
<svg-icon
|
||||
@click="
|
||||
ElMessage.error('该商品不在可售时间内') ||
|
||||
isProductAvailable(item.days, item.startTime, item.endTime)
|
||||
"
|
||||
v-else-if="!item.isSaleTime"
|
||||
iconClass="no-sale"
|
||||
color="#fff"
|
||||
size="60"
|
||||
></svg-icon>
|
||||
<svg-icon
|
||||
@click="ElMessage.error('该商品已售罄')"
|
||||
v-else-if="item.isSoldStock"
|
||||
iconClass="shouqing"
|
||||
color="#fff"
|
||||
size="60"
|
||||
></svg-icon>
|
||||
<svg-icon
|
||||
@click="ElMessage.error('库存不足')"
|
||||
v-else-if="item.isStock && item.stockNumber * 1 <= 0"
|
||||
iconClass="stock_null"
|
||||
color="#fff"
|
||||
size="60"
|
||||
></svg-icon>
|
||||
<div class="status" v-if="
|
||||
item.isSoldStock ||
|
||||
!item.isSale ||
|
||||
!item.isSaleTime ||
|
||||
(item.isStock && item.stockNumber * 1 <= 0)
|
||||
">
|
||||
<svg-icon @click="ElMessage.error('该商品已下架')" v-if="!item.isSale" iconClass="yi-xiajia" color="#fff"
|
||||
size="60"></svg-icon>
|
||||
<svg-icon @click="
|
||||
ElMessage.error('该商品不在可售时间内') ||
|
||||
isProductAvailable(item.days, item.startTime, item.endTime)
|
||||
" v-else-if="!item.isSaleTime" iconClass="no-sale" color="#fff" size="60"></svg-icon>
|
||||
<svg-icon @click="ElMessage.error('该商品已售罄')" v-else-if="item.isSoldStock" iconClass="shouqing" color="#fff"
|
||||
size="60"></svg-icon>
|
||||
<svg-icon @click="ElMessage.error('库存不足')" v-else-if="item.isStock && item.stockNumber * 1 <= 0"
|
||||
iconClass="stock_null" color="#fff" size="60"></svg-icon>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -105,10 +81,12 @@ function isProductAvailable(sellDaysStr, startTimeStr, endTimeStr) {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
|
||||
.goods-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.info {
|
||||
position: absolute;
|
||||
box-sizing: border-box;
|
||||
@@ -122,6 +100,7 @@ function isProductAvailable(sellDaysStr, startTimeStr, endTimeStr) {
|
||||
background-color: rgba(46, 46, 46, 0.38);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.status {
|
||||
position: absolute;
|
||||
box-sizing: border-box;
|
||||
@@ -134,9 +113,11 @@ function isProductAvailable(sellDaysStr, startTimeStr, endTimeStr) {
|
||||
background-color: rgba($color: #000000, $alpha: 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.svg-icon) {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.weight {
|
||||
height: 15px;
|
||||
background: linear-gradient(124deg, rgb(115, 201, 105) 6%, rgb(39, 146, 27) 93%);
|
||||
@@ -147,4 +128,10 @@ function isProductAvailable(sellDaysStr, startTimeStr, endTimeStr) {
|
||||
padding: 0px 2px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
.o_price {
|
||||
font-size: 10px;
|
||||
text-decoration: line-through;
|
||||
opacity: .8;
|
||||
}
|
||||
</style>
|
||||
@@ -42,22 +42,11 @@
|
||||
<span class="u-font-14">部分抵扣</span>
|
||||
</el-radio> -->
|
||||
</el-radio-group>
|
||||
<el-input-number
|
||||
class="u-m-l-10"
|
||||
v-if="score.sel != -1"
|
||||
v-model="usePointsNumber"
|
||||
step-strictly
|
||||
:step="pointsRes.equivalentPoints"
|
||||
placeholder="请输入积分抵扣数量"
|
||||
:min="pointsRes.minDeductionPoints"
|
||||
:max="pointsRes.maxUsablePoints"
|
||||
@change="pointsToMoney"
|
||||
></el-input-number>
|
||||
<el-input-number class="u-m-l-10" v-if="score.sel != -1" v-model="usePointsNumber" step-strictly
|
||||
:step="pointsRes.equivalentPoints" placeholder="请输入积分抵扣数量" :min="pointsRes.minDeductionPoints"
|
||||
:max="pointsRes.maxUsablePoints" @change="pointsToMoney"></el-input-number>
|
||||
</div>
|
||||
<p
|
||||
class="u-font-14 color-666 u-m-t-10"
|
||||
v-if="pointsRes.unusableReason && !pointsRes.usable"
|
||||
>
|
||||
<p class="u-font-14 color-666 u-m-t-10" v-if="pointsRes.unusableReason && !pointsRes.usable">
|
||||
<span class="color-red">*</span>
|
||||
<span>{{ pointsRes.unusableReason }}</span>
|
||||
</p>
|
||||
@@ -70,7 +59,9 @@
|
||||
<span class="u-font-14 font-bold u-m-r-20">团购代金券</span>
|
||||
<div class="u-flex my-select">
|
||||
<span class="u-m-r-10">代金券名称</span>
|
||||
<el-icon><ArrowDown /></el-icon>
|
||||
<el-icon>
|
||||
<ArrowDown />
|
||||
</el-icon>
|
||||
</div>
|
||||
<svg-icon iconClass="scan" size="30" class="u-m-l-10 cur-pointer"></svg-icon>
|
||||
</div>
|
||||
@@ -78,7 +69,9 @@
|
||||
<span class="u-font-14 font-bold u-m-r-20">优惠券</span>
|
||||
<div class="u-flex my-select" @click="openCoupon">
|
||||
<span class="u-m-r-10">选择优惠券</span>
|
||||
<el-icon><ArrowDown /></el-icon>
|
||||
<el-icon>
|
||||
<ArrowDown />
|
||||
</el-icon>
|
||||
</div>
|
||||
</div>
|
||||
<div class="u-m-t-20" v-if="quansSelArr.length > 0">
|
||||
@@ -121,16 +114,13 @@
|
||||
<div class="u-m-t-30">
|
||||
<p class="u-font-16 font-bold u-m-r-20 font-bold u-flex">选择支付方式</p>
|
||||
<div class="u-m-t-20">
|
||||
<el-button
|
||||
v-for="(item, index) in payTypes.list"
|
||||
:key="index"
|
||||
size="large"
|
||||
:type="index == payTypes.sel ? 'primary' : ''"
|
||||
:disabled="canUsePayType(item)"
|
||||
@click="changePayType(index)"
|
||||
>
|
||||
{{ item.payName }}
|
||||
</el-button>
|
||||
<div>
|
||||
<el-button v-for="(item, index) in payTypes.list" :key="index" size="large"
|
||||
:type="index == payTypes.sel ? 'primary' : ''" :disabled="canUsePayType(item)"
|
||||
@click="changePayType(index)">
|
||||
{{ item.payName }}
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="u-m-t-20">
|
||||
<el-button type="primary" size="large" @click="nowPayClick()">立即支付</el-button>
|
||||
@@ -206,26 +196,17 @@
|
||||
</div>
|
||||
</div>
|
||||
<!-- 扫码 -->
|
||||
<scanPay
|
||||
ref="refScanPay"
|
||||
:order="orderInfo"
|
||||
@confirm="refScanPayConfirm"
|
||||
@paysuccess="paysuccess"
|
||||
></scanPay>
|
||||
<scanPay ref="refScanPay" :order="orderInfo" @confirm="refScanPayConfirm" @paysuccess="paysuccess"></scanPay>
|
||||
<!-- 打折 -->
|
||||
<discount ref="refDiscount" @confirm="discountConfirm"></discount>
|
||||
<!-- 优惠券 -->
|
||||
<popup-coupon ref="refCoupon" :user="user" @confirm="refCouponConfirm"></popup-coupon>
|
||||
<!-- 挂账 -->
|
||||
<chooseGuaZahng
|
||||
ref="refGuaZhang"
|
||||
:payMoney="currentpayMoney"
|
||||
@confirm="refGuaZhangConfirm"
|
||||
></chooseGuaZahng>
|
||||
<chooseGuaZahng ref="refGuaZhang" :payMoney="currentpayMoney" @confirm="refGuaZhangConfirm"></chooseGuaZahng>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
<script setup>
|
||||
import * as UTILS from "@/utils/coupon-utils.js";
|
||||
|
||||
import * as quanUtil from "../quan_util.js";
|
||||
@@ -237,7 +218,7 @@ const shopUser = useUserStore();
|
||||
const carts = useCartsStore();
|
||||
import popupCoupon from "./popup-coupon.vue";
|
||||
import PointsApi from "@/api/account/points";
|
||||
|
||||
import limitTimeDiscountApi from '@/api/market/limitTimeDiscount.js'
|
||||
import payTypeApi from "@/api/account/payType";
|
||||
import payApi from "@/api/order/pay";
|
||||
import scanPay from "./scan-pay.vue";
|
||||
@@ -357,7 +338,7 @@ function discountShow(e) {
|
||||
const props = defineProps({
|
||||
table: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
default: () => { },
|
||||
},
|
||||
user: {
|
||||
type: Object,
|
||||
@@ -371,7 +352,7 @@ const props = defineProps({
|
||||
},
|
||||
orderInfo: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
default: () => { },
|
||||
},
|
||||
});
|
||||
|
||||
@@ -488,6 +469,26 @@ function changePayType(i) {
|
||||
refScanPayOpen(payType);
|
||||
}
|
||||
|
||||
// 根据用户id获取新客立减金额,返回null代表不可用
|
||||
const newCustomerDiscount = ref(null)
|
||||
async function getConsumeDiscountAjax() {
|
||||
try {
|
||||
if (props.user.id) {
|
||||
newCustomerDiscount.value = await limitTimeDiscountApi.getConsumeDiscount({
|
||||
shopId: localStorage.getItem("shopId"),
|
||||
shopUserId: props.user.id,
|
||||
orderId: props.orderInfo.id
|
||||
})
|
||||
console.log('根据用户id获取新客立减金额,返回null代表不可用', newCustomerDiscount.value);
|
||||
if (newCustomerDiscount.value !== null) {
|
||||
carts.newUserDiscount = newCustomerDiscount.value.amount
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
function returnPayParams() {
|
||||
console.log("carts.orderCostSummary", carts.orderCostSummary);
|
||||
return {
|
||||
@@ -511,6 +512,9 @@ function returnPayParams() {
|
||||
couponList: carts.coupons.map((v) => v.id),
|
||||
userId: props.user.userId || "",
|
||||
allPack: carts.dinnerType == "take-out" ? 1 : 0,
|
||||
limitRate: carts.limitDiscountRes,
|
||||
newCustomerDiscountId: newCustomerDiscount.value !== null ? newCustomerDiscount.value.id : '', // 新客立减Id
|
||||
newCustomerDiscountAmount: newCustomerDiscount.value !== null ? newCustomerDiscount.value.amount : 0, // 新客立减金额
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -550,7 +554,7 @@ function nowPayClick(payType) {
|
||||
.then(() => {
|
||||
payOrder("cash");
|
||||
})
|
||||
.catch(() => {});
|
||||
.catch(() => { });
|
||||
return;
|
||||
}
|
||||
if (payType == "member-account") {
|
||||
@@ -680,9 +684,25 @@ watch(
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// 获取当前店铺可用的限时折扣
|
||||
async function getlimitTimeDiscount() {
|
||||
try {
|
||||
const res = await limitTimeDiscountApi.getLimitTimeDiscount({
|
||||
shopId: localStorage.getItem("shopId")
|
||||
})
|
||||
|
||||
console.log('获取当前店铺可用的限时折扣===', res);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
carts.payParamsInit();
|
||||
getPaytype();
|
||||
getlimitTimeDiscount()
|
||||
getConsumeDiscountAjax()
|
||||
});
|
||||
defineExpose({
|
||||
nowPayClick,
|
||||
@@ -696,6 +716,7 @@ defineExpose({
|
||||
line-height: 1;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.vip {
|
||||
padding: 2px 5px;
|
||||
background: #f7793d;
|
||||
@@ -704,27 +725,33 @@ defineExpose({
|
||||
margin-left: 10px;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.order-box {
|
||||
display: flex;
|
||||
padding: 20px 20px;
|
||||
background-color: #f7f7fa;
|
||||
min-height: 100%;
|
||||
|
||||
.left,
|
||||
.right {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.left {
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
.right {
|
||||
border-left: 1px solid #ebebeb;
|
||||
padding-left: 20px;
|
||||
|
||||
.order-info {
|
||||
font-size: 14px;
|
||||
.title {
|
||||
}
|
||||
.value {
|
||||
}
|
||||
|
||||
.title {}
|
||||
|
||||
.value {}
|
||||
|
||||
.price {
|
||||
color: #fa5555;
|
||||
font-size: 20px;
|
||||
@@ -732,6 +759,7 @@ defineExpose({
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.my-select {
|
||||
border: 1px solid #d9d9d9;
|
||||
border-radius: 4px;
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
<template>
|
||||
<div
|
||||
class="box"
|
||||
v-loading="!carts.isLinkFinshed"
|
||||
element-loading-text="购物车连接初始化中,请稍等……"
|
||||
>
|
||||
<div class="box" v-loading="!carts.isLinkFinshed" element-loading-text="购物车连接初始化中,请稍等……">
|
||||
<div class="content">
|
||||
<div class="top">
|
||||
<div class="left u-flex u-col-center">
|
||||
@@ -13,12 +9,7 @@
|
||||
<el-button type="primary" v-if="!user.id">选择用户</el-button>
|
||||
|
||||
<div v-else class="flex cur-pointer">
|
||||
<img
|
||||
v-if="user.headImg && user.headImg != 'null'"
|
||||
class="headimg"
|
||||
:src="user.headImg"
|
||||
alt=""
|
||||
/>
|
||||
<img v-if="user.headImg && user.headImg != 'null'" class="headimg" :src="user.headImg" alt="" />
|
||||
<div v-else class="headimg flex flex-x-y-center">
|
||||
<i class="el-icon-user"></i>
|
||||
</div>
|
||||
@@ -34,19 +25,11 @@
|
||||
</div>
|
||||
</div>
|
||||
<el-popover placement="right" width="333" trigger="click" ref="refTable">
|
||||
<el-input
|
||||
placeholder="请输入内容"
|
||||
prefix-icon="search"
|
||||
v-model="tableSearchText"
|
||||
@input="tablesearchInput"
|
||||
></el-input>
|
||||
<el-input placeholder="请输入内容" prefix-icon="search" v-model="tableSearchText"
|
||||
@input="tablesearchInput"></el-input>
|
||||
<div style="max-height: 398px; overflow-y: scroll" class="u-m-t-12">
|
||||
<div
|
||||
class="u-flex u-row-between u-p-t-8 table-item u-p-b-8 u-p-r-30"
|
||||
v-for="(item, index) in tableList"
|
||||
:key="index"
|
||||
@click="tableClick(item, index)"
|
||||
>
|
||||
<div class="u-flex u-row-between u-p-t-8 table-item u-p-b-8 u-p-r-30" v-for="(item, index) in tableList"
|
||||
:key="index" @click="tableClick(item, index)">
|
||||
<span>{{ item.name }}</span>
|
||||
<span :style="{ color: returnTableColor(item.status) }">
|
||||
{{ returnTableLabel(item.status) }}
|
||||
@@ -64,14 +47,11 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
<el-input
|
||||
placeholder="请输入商品名称"
|
||||
v-model="goods.query.name"
|
||||
clearable
|
||||
@change="getGoods"
|
||||
>
|
||||
<el-input placeholder="请输入商品名称" v-model="goods.query.name" clearable @change="getGoods">
|
||||
<template #suffix>
|
||||
<el-icon class="el-input__icon"><search /></el-icon>
|
||||
<el-icon class="el-input__icon">
|
||||
<search />
|
||||
</el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
</div>
|
||||
@@ -81,83 +61,51 @@
|
||||
<div class="diners">
|
||||
<!-- 就餐类型 -->
|
||||
<el-button-group v-model="diners.sel" style="width: 100%; display: flex">
|
||||
<el-button
|
||||
:class="{ active: index == diners.sel }"
|
||||
v-for="(item, index) in diners.list"
|
||||
:disabled="dinerDisabled(item, index)"
|
||||
@click="changeDinersSel(index)"
|
||||
:key="index"
|
||||
>
|
||||
<el-button :class="{ active: index == diners.sel }" v-for="(item, index) in diners.list"
|
||||
:disabled="dinerDisabled(item, index)" @click="changeDinersSel(index)" :key="index">
|
||||
{{ item.label }}
|
||||
</el-button>
|
||||
</el-button-group>
|
||||
</div>
|
||||
|
||||
<div class="u-flex u-font-14 clear u-m-t-10 perpoles">
|
||||
<div
|
||||
@click="showDinerNumber"
|
||||
class="u-flex u-p-r-14 u-m-r-14"
|
||||
style="border-right: 1px solid #ebebeb; line-height: 1"
|
||||
>
|
||||
<div @click="showDinerNumber" class="u-flex u-p-r-14 u-m-r-14"
|
||||
style="border-right: 1px solid #ebebeb; line-height: 1">
|
||||
<span>就餐人数:{{ perpole || "-" }} 位</span>
|
||||
<el-icon><ArrowRight /></el-icon>
|
||||
<el-icon>
|
||||
<ArrowRight />
|
||||
</el-icon>
|
||||
</div>
|
||||
<el-button link type="primary" :disabled="carts.isEmpty" @click="clearCarts">
|
||||
清空
|
||||
</el-button>
|
||||
</div>
|
||||
<!-- 购物车 -->
|
||||
<cartsList
|
||||
@editNote="showNote(true)"
|
||||
@createOrder="createOrder"
|
||||
@hideOrder="hideOrder"
|
||||
@clearOldOrder="clearOldOrder"
|
||||
:showOrder="showOrder"
|
||||
:goodsList="carts.goods"
|
||||
:dinerType="diners.sel"
|
||||
:perpole="perpole"
|
||||
:remark="remark"
|
||||
:table="table"
|
||||
ref="refCart"
|
||||
></cartsList>
|
||||
<cartsList @editNote="showNote(true)" @createOrder="createOrder" @hideOrder="hideOrder"
|
||||
@clearOldOrder="clearOldOrder" :showOrder="showOrder" :goodsList="carts.goods" :dinerType="diners.sel"
|
||||
:perpole="perpole" :remark="remark" :table="table" ref="refCart"></cartsList>
|
||||
</div>
|
||||
<div class="center">
|
||||
<!-- 购物车控制操作按钮 -->
|
||||
<Controls
|
||||
@noteClick="showNote"
|
||||
@packClick="showPack"
|
||||
@changePriceClick="showChangePrice"
|
||||
@return="refReturnCartShow"
|
||||
@rottable="rottableShow"
|
||||
@changeCartNumberShow="refChangeNumberShow"
|
||||
/>
|
||||
<Controls @noteClick="showNote" @packClick="showPack" @changePriceClick="showChangePrice"
|
||||
@return="refReturnCartShow" @rottable="rottableShow" @changeCartNumberShow="refChangeNumberShow" />
|
||||
</div>
|
||||
<div class="right">
|
||||
<template v-if="!showOrder">
|
||||
<div class="flex categoty u-col-center">
|
||||
<div
|
||||
class="show_more_btn"
|
||||
:class="{ showAll: category.showAll }"
|
||||
@click="toggleShowAll"
|
||||
>
|
||||
<div class="show_more_btn" :class="{ showAll: category.showAll }" @click="toggleShowAll">
|
||||
<div class="flex">
|
||||
<div class="flex showmore">
|
||||
<el-icon color="#fff"><ArrowDown /></el-icon>
|
||||
<el-icon color="#fff">
|
||||
<ArrowDown />
|
||||
</el-icon>
|
||||
</div>
|
||||
<span>{{ category.showAll ? "收起" : "展开" }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex categorys" :class="{ 'flex-wrap': category.showAll }">
|
||||
<div
|
||||
v-for="(item, index) in category.list"
|
||||
:key="index"
|
||||
@click="changeCategoryId(item)"
|
||||
>
|
||||
<el-tag
|
||||
size="large"
|
||||
:type="goods.query.categoryId === item.id ? 'primary' : 'info'"
|
||||
effect="dark"
|
||||
>
|
||||
<div v-for="(item, index) in category.list" :key="index" @click="changeCategoryId(item)">
|
||||
<el-tag size="large" :type="goods.query.categoryId === item.id ? 'primary' : 'info'" effect="dark">
|
||||
{{ item.name }}
|
||||
</el-tag>
|
||||
</div>
|
||||
@@ -166,29 +114,19 @@
|
||||
<div v-if="carts.goods.length <= 0" class="no-goods">未找到相关商品</div>
|
||||
<div class="goods-list">
|
||||
<div class="lingshicai" @click="showaddLingShiCai">
|
||||
<el-icon size="26"><Plus /></el-icon>
|
||||
<el-icon size="26">
|
||||
<Plus />
|
||||
</el-icon>
|
||||
<div class="u-m-t-10">临时菜</div>
|
||||
</div>
|
||||
<GoodsItem
|
||||
:item="item"
|
||||
@itemClick="goodsClick(item)"
|
||||
v-for="item in carts.goods"
|
||||
:key="item.id"
|
||||
></GoodsItem>
|
||||
<GoodsItem :item="item" @itemClick="goodsClick(item)" v-for="item in carts.goods" :key="item.id">
|
||||
</GoodsItem>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 订单信息展示 -->
|
||||
<Order
|
||||
ref="refOrder"
|
||||
:orderInfo="carts.oldOrder"
|
||||
@chooseUser="showChooseUser"
|
||||
@paysuccess="refresh"
|
||||
:table="table"
|
||||
:perpole="perpole"
|
||||
v-else
|
||||
:user="user"
|
||||
></Order>
|
||||
<Order ref="refOrder" :orderInfo="carts.oldOrder" @chooseUser="showChooseUser" @paysuccess="refresh"
|
||||
:table="table" :perpole="perpole" v-else :user="user"></Order>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -203,11 +141,7 @@
|
||||
<!-- 临时菜 -->
|
||||
<addLingShiCai ref="refAddLingShiCai" @confirm="addLingShiCaiConfirm"></addLingShiCai>
|
||||
<!-- 改价 -->
|
||||
<changePrice
|
||||
ref="refChangePrice"
|
||||
:useVipPrice="carts.useVipPrice"
|
||||
@confirm="changePriceConfirm"
|
||||
></changePrice>
|
||||
<changePrice ref="refChangePrice" :useVipPrice="carts.useVipPrice" @confirm="changePriceConfirm"></changePrice>
|
||||
<!-- 称重商品 -->
|
||||
<change-weight ref="refChangeWeight" @confirm="changeWeightConfirm"></change-weight>
|
||||
<!-- 可选套餐 -->
|
||||
@@ -421,6 +355,7 @@ async function createOrder(key) {
|
||||
placeNum: carts.oldOrder.placeNum * 1 + 1,
|
||||
waitCall: false,
|
||||
vipPrice: user.value.id && user.value.isVip,
|
||||
limitRate: carts.limitDiscountRes
|
||||
});
|
||||
clearTimeout(loadingTimer);
|
||||
loading.close();
|
||||
@@ -553,7 +488,7 @@ async function getTableDetail(params) {
|
||||
const res = await tableApi.get(params);
|
||||
return res;
|
||||
}
|
||||
function tablesearchInput() {}
|
||||
function tablesearchInput() { }
|
||||
//返回桌台状态颜色
|
||||
function returnTableColor(key) {
|
||||
const item = $status[key];
|
||||
@@ -773,11 +708,15 @@ function clearCarts() {
|
||||
});
|
||||
}
|
||||
function addCarts(item, isWeight = false) {
|
||||
console.log('index.addCarts===', item);
|
||||
|
||||
|
||||
|
||||
if (isWeight) {
|
||||
carts.add({ pack_number: diners.sel ? 1 : 0, ...item });
|
||||
carts.add({ pack_number: diners.sel ? 1 : 0, ...item, is_time_discount: item.isLimitDiscount ? 1 : 0 });
|
||||
return;
|
||||
}
|
||||
carts.add({ pack_number: diners.sel ? item.number : 0, ...item });
|
||||
carts.add({ pack_number: diners.sel ? item.number : 0, ...item, is_time_discount: item.isLimitDiscount ? 1 : 0 });
|
||||
}
|
||||
|
||||
watch(
|
||||
@@ -804,11 +743,11 @@ onMounted(async () => {
|
||||
// 获取历史订单数据
|
||||
const res = id
|
||||
? await orderApi.getHistoryList({
|
||||
orderId: id,
|
||||
})
|
||||
orderId: id,
|
||||
})
|
||||
: await orderApi.getHistoryList({
|
||||
tableCode,
|
||||
});
|
||||
tableCode,
|
||||
});
|
||||
const noPayStatus = {
|
||||
cancelled: "订单已取消",
|
||||
done: "订单已关闭",
|
||||
@@ -893,20 +832,24 @@ watch(
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$pl: 30px;
|
||||
|
||||
.box {
|
||||
padding: 20px 20px 10px 20px;
|
||||
height: 100%;
|
||||
|
||||
.content {
|
||||
background-color: #fff;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 20px 20px 20px 0;
|
||||
|
||||
.top {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding-bottom: 20px;
|
||||
border-bottom: 1px solid #ebebeb;
|
||||
margin-left: $pl;
|
||||
|
||||
.left {
|
||||
flex: 1;
|
||||
|
||||
@@ -917,39 +860,48 @@ $pl: 30px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
.right {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.diancan {
|
||||
padding-top: 10px;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
max-height: calc(100vh - 256px);
|
||||
|
||||
.left {
|
||||
width: 350px;
|
||||
padding-right: 14px;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.diners {
|
||||
padding-left: $pl;
|
||||
}
|
||||
|
||||
.perpoles {
|
||||
padding-left: $pl;
|
||||
}
|
||||
}
|
||||
|
||||
.right {
|
||||
flex: 1;
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.center {
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
@@ -964,18 +916,22 @@ $pl: 30px;
|
||||
background: rgba(24, 144, 255, 0.1) !important;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
:deep(.diners .el-button-group) {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
:deep(.diners .el-button-group .el-button) {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
:deep(.categorys .el-tag--plain.el-tag--info) {
|
||||
border: 1px solid #dcdfe6;
|
||||
color: #000;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
:deep(.categorys .el-tag) {
|
||||
min-width: 80px;
|
||||
height: 38px;
|
||||
@@ -991,6 +947,7 @@ $pl: 30px;
|
||||
margin: 0 10px 10px 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.categoty {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
@@ -1036,20 +993,24 @@ $pl: 30px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.goods-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 15px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
:deep(.carts) {
|
||||
padding-left: $pl;
|
||||
}
|
||||
|
||||
:deep(.left) {
|
||||
.bottom {
|
||||
padding-left: $pl;
|
||||
}
|
||||
}
|
||||
|
||||
.lingshicai {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
@@ -1064,11 +1025,13 @@ $pl: 30px;
|
||||
border: 1px solid #dddfe6;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
:deep(.el-tag--dark.el-tag--info) {
|
||||
background-color: #fff;
|
||||
color: #000;
|
||||
border: 1px solid #dcdfe6;
|
||||
}
|
||||
|
||||
.table-item {
|
||||
cursor: pointer;
|
||||
transition: 0.2s ease-in-out;
|
||||
@@ -1077,12 +1040,15 @@ $pl: 30px;
|
||||
background: #f4f9ff;
|
||||
}
|
||||
}
|
||||
|
||||
.no-goods {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.choose-user {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.headimg {
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
@@ -1090,6 +1056,7 @@ $pl: 30px;
|
||||
border-radius: 2px;
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
.vip {
|
||||
padding: 2px 5px;
|
||||
background: #f7793d;
|
||||
|
||||
@@ -1,35 +1,14 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:title="form.id ? '编辑台桌' : '添加台桌'"
|
||||
v-model="dialogVisible"
|
||||
@open="tbShopAreaGet"
|
||||
@close="reset"
|
||||
>
|
||||
<el-form
|
||||
ref="refForm"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
label-width="120px"
|
||||
label-position="left"
|
||||
>
|
||||
<el-dialog :title="form.id ? '编辑台桌' : '添加台桌'" v-model="dialogVisible" @open="tbShopAreaGet" @close="reset">
|
||||
<el-form ref="refForm" :model="form" :rules="rules" label-width="120px" label-position="left">
|
||||
<el-form-item label="选择区域" prop="areaId">
|
||||
<el-select v-model="form.areaId" placeholder="请选择区域">
|
||||
<el-option
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
v-for="item in areaList"
|
||||
:key="item.id"
|
||||
></el-option>
|
||||
<el-option :label="item.name" :value="item.id" v-for="item in areaList" :key="item.id"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="台桌状态" prop="status" v-if="form.id">
|
||||
<el-select v-model="form.status" placeholder="请选择台桌状态">
|
||||
<el-option
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
v-for="item in statusList"
|
||||
:key="item.value"
|
||||
></el-option>
|
||||
<el-option :label="item.label" :value="item.value" v-for="item in statusList" :key="item.value"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="台桌标识" prop="sign" v-if="!form.id">
|
||||
@@ -41,29 +20,18 @@
|
||||
<div class="u-flex u-m-l-30">
|
||||
<div class="u-flex">
|
||||
<div class="u-m-r-4">起始</div>
|
||||
<el-input
|
||||
v-model="form.start"
|
||||
style="width: 57px"
|
||||
placeholder="请输入起始值"
|
||||
></el-input>
|
||||
<el-input v-model="form.start" style="width: 57px" placeholder="请输入起始值"></el-input>
|
||||
</div>
|
||||
|
||||
<div
|
||||
style="
|
||||
<div style="
|
||||
background-color: #d9d9d9;
|
||||
height: 1px;
|
||||
width: 32px;
|
||||
border-radius: 1px;
|
||||
"
|
||||
class="u-m-l-16 u-m-r-16"
|
||||
></div>
|
||||
" class="u-m-l-16 u-m-r-16"></div>
|
||||
<div class="u-flex">
|
||||
<span class="u-m-r-4">结束</span>
|
||||
<el-input
|
||||
v-model="form.end"
|
||||
style="width: 57px"
|
||||
placeholder="请输入结束值"
|
||||
></el-input>
|
||||
<el-input v-model="form.end" style="width: 57px" placeholder="请输入结束值"></el-input>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -72,31 +40,19 @@
|
||||
<el-input v-model="form.name" placeholder="请输入台桌名称"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="客座数">
|
||||
<el-input-number
|
||||
v-model="form.maxCapacity"
|
||||
:min="0"
|
||||
controls-position="right"
|
||||
></el-input-number>
|
||||
<el-input-number v-model="form.maxCapacity" :min="0" controls-position="right"></el-input-number>
|
||||
</el-form-item>
|
||||
<el-form-item label="清台管理">
|
||||
<!-- <el-form-item label="清台管理">
|
||||
<el-radio-group v-model="form.autoClear">
|
||||
<el-radio-button :value="0">手动清台</el-radio-button>
|
||||
<el-radio-button :value="1">自动清台</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-form-item> -->
|
||||
<el-form-item v-if="form.id" label="网络预定开关">
|
||||
<el-switch
|
||||
v-model="form.isPredate"
|
||||
:active-value="1"
|
||||
:inactive-value="2"
|
||||
></el-switch>
|
||||
<el-switch v-model="form.isPredate" :active-value="1" :inactive-value="2"></el-switch>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.id" label="网络预定台桌支付金额">
|
||||
<el-input-number
|
||||
v-model="form.predateAmount"
|
||||
:min="0"
|
||||
controls-position="right"
|
||||
></el-input-number>
|
||||
<el-input-number v-model="form.predateAmount" :min="0" controls-position="right"></el-input-number>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
|
||||
113
src/views/tool/table/components/clearTabDialog.vue
Normal file
113
src/views/tool/table/components/clearTabDialog.vue
Normal file
@@ -0,0 +1,113 @@
|
||||
<!-- 统一清台设置 -->
|
||||
<template>
|
||||
<el-dialog title="清台设置" width="600px" v-model="visible">
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-position="right" label-width="120">
|
||||
<el-form-item label="清台方式">
|
||||
<el-radio-group v-model="form.autoClear">
|
||||
<el-radio label="手动清台" :value="0"></el-radio>
|
||||
<el-radio label="自动清台" :value="1"></el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="自动清台时间" prop="autoClearTime" v-if="form.autoClear === 1">
|
||||
<div class="column">
|
||||
<div>
|
||||
<el-input v-model="form.autoClearTime" style="width: 220px;" placeholder="请输入"
|
||||
@input="e => form.autoClearTime = filterNumberInput(e, 0)">
|
||||
<template #append>分钟后自动清台</template>
|
||||
</el-input>
|
||||
</div>
|
||||
<div class="tips">输入0时,默认支付后既自动清台</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="visible = false">取 消</el-button>
|
||||
<el-button type="primary" @click="submitHandle" :loading="confirmLoading">确 定</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import tableApi from "@/api/account/table";
|
||||
import { filterNumberInput } from '@/utils'
|
||||
|
||||
const visible = ref(false)
|
||||
const formRef = ref(null)
|
||||
const form = ref({
|
||||
autoClear: 1, // 自动清台 0手动 1自动
|
||||
autoClearTime: 0, // 自动清台时间 单位分钟 默认10
|
||||
})
|
||||
|
||||
const rules = ref({
|
||||
autoClearTime: [
|
||||
{
|
||||
validator: (rule, value, callback) => {
|
||||
if (form.value.autoClearTime === '') {
|
||||
callback(new Error('请输入自动清台时间'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
},
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
// 提交配置
|
||||
const confirmLoading = ref(false)
|
||||
function submitHandle() {
|
||||
formRef.value.validate(async vaild => {
|
||||
try {
|
||||
if (vaild) {
|
||||
confirmLoading.value = true
|
||||
await tableApi.shopTabBatch(form.value)
|
||||
visible.value = false
|
||||
ElNotification({
|
||||
title: '注意',
|
||||
message: '设置成功',
|
||||
type: 'success'
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
setTimeout(() => {
|
||||
confirmLoading.value = false
|
||||
}, 500);
|
||||
})
|
||||
}
|
||||
|
||||
// 获取清台配置信息
|
||||
async function tableCurrentStateAjax() {
|
||||
try {
|
||||
const res = await tableApi.tableCurrentState()
|
||||
form.value.autoClear = res.autoClear
|
||||
form.value.autoClearTime = res.autoClearTime || 0
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
function show() {
|
||||
visible.value = true
|
||||
tableCurrentStateAjax()
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
show
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.tips {
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -2,12 +2,7 @@
|
||||
<div class="app-container">
|
||||
<el-tabs v-model="tableArea.tabsSel" type="card" @tab-click="tabClick">
|
||||
<el-tab-pane label="全部" name="" />
|
||||
<el-tab-pane
|
||||
v-for="item in tableArea.tabs"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:name="`${item.id}`"
|
||||
>
|
||||
<el-tab-pane v-for="item in tableArea.tabs" :key="item.id" :label="item.name" :name="`${item.id}`">
|
||||
<template #label>
|
||||
<div class="">
|
||||
<span>
|
||||
@@ -31,6 +26,7 @@
|
||||
<div class="">
|
||||
<el-button icon="plus" @click="addEaraShow()">添加区域</el-button>
|
||||
<el-button type="primary" icon="plus" @click="addTableShow()">添加台桌</el-button>
|
||||
<el-button type="danger" icon="Setting" @click="clearTabDialogRef.show()">清台设置</el-button>
|
||||
<el-button type="primary" icon="download" @click="showDownloadTableCode">
|
||||
下载桌台码
|
||||
</el-button>
|
||||
@@ -41,12 +37,9 @@
|
||||
|
||||
<div class="u-flex u-p-b-15 u-font-14 u-m-t-16">
|
||||
<div v-for="(item, key) in status" :key="key" class="state u-m-r-24">
|
||||
<span
|
||||
class="dot"
|
||||
:style="{
|
||||
backgroundColor: status[key] ? status[key].type : '',
|
||||
}"
|
||||
/>
|
||||
<span class="dot" :style="{
|
||||
backgroundColor: status[key] ? status[key].type : '',
|
||||
}" />
|
||||
{{ item.label }}
|
||||
</div>
|
||||
</div>
|
||||
@@ -54,14 +47,9 @@
|
||||
<!-- 列表 -->
|
||||
<div class="head-container">
|
||||
<div v-loading="loading" class="table_list">
|
||||
<div
|
||||
v-for="item in tableList"
|
||||
:key="item.id"
|
||||
class="item"
|
||||
:style="{
|
||||
'background-color': status[item.status] ? status[item.status].type : '',
|
||||
}"
|
||||
>
|
||||
<div v-for="item in tableList" :key="item.id" class="item" :style="{
|
||||
'background-color': status[item.status] ? status[item.status].type : '',
|
||||
}">
|
||||
<div class="new-top flex u-row-between">
|
||||
<div class="u-flex u-flex-1 u-p-r-10">
|
||||
<span class="name u-line-1" style="max-width: 50px">
|
||||
@@ -80,10 +68,7 @@
|
||||
<el-dropdown-item command="edit">
|
||||
<span>编辑</span>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
command="bindTableCode"
|
||||
v-if="envName !== 'production'"
|
||||
>
|
||||
<el-dropdown-item command="bindTableCode" v-if="envName !== 'production'">
|
||||
<span>绑定桌码</span>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item command="del">
|
||||
@@ -102,20 +87,14 @@
|
||||
item.bookingInfo.bookingPerson
|
||||
}}「{{ item.bookingInfo.gender == 1 ? "先生" : "女士" }}」
|
||||
</span>
|
||||
<div
|
||||
class="state"
|
||||
style="
|
||||
<div class="state" style="
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
"
|
||||
>
|
||||
<img
|
||||
style="width: 16px; height: 16px; filter: contrast(0.5)"
|
||||
src="@/assets/images/perpole.png"
|
||||
alt=""
|
||||
/>
|
||||
">
|
||||
<img style="width: 16px; height: 16px; filter: contrast(0.5)" src="@/assets/images/perpole.png"
|
||||
alt="" />
|
||||
|
||||
{{ item.bookingInfo.bookingTime.substring(11, 19) }}
|
||||
</div>
|
||||
@@ -128,71 +107,47 @@
|
||||
</div>
|
||||
|
||||
<div v-else class="u-font-18 font-600 total-price">
|
||||
<span
|
||||
v-if="item.status == 'using'"
|
||||
class="cur-pointer"
|
||||
@click="diancanShow(item, 'isAddGoods')"
|
||||
>
|
||||
<span v-if="item.status == 'using'" class="cur-pointer" @click="diancanShow(item, 'isAddGoods')">
|
||||
¥{{ item.totalAmount || 0 }}「{{ item.productNum }}件」
|
||||
</span>
|
||||
<!-- <span v-else class="color-fff">|</span> -->
|
||||
</div>
|
||||
<div class="row btn-group" style="margin-top: 10px">
|
||||
<template v-if="item.status == 'subscribe'">
|
||||
<el-button
|
||||
type="success"
|
||||
:disabled="!item.tableId || item.status === 'closed'"
|
||||
@click="markStatus(item, -1)"
|
||||
>
|
||||
<el-button type="success" :disabled="!item.tableId || item.status === 'closed'"
|
||||
@click="markStatus(item, -1)">
|
||||
取消预约
|
||||
</el-button>
|
||||
</template>
|
||||
<template
|
||||
v-if="
|
||||
item.status == 'subscribe' &&
|
||||
item.bookingInfo &&
|
||||
item.bookingInfo.status == 20
|
||||
"
|
||||
>
|
||||
<el-button
|
||||
type="success"
|
||||
:disabled="!item.tableId || item.status === 'closed'"
|
||||
@click="markStatus(item, 10)"
|
||||
>
|
||||
<template v-if="
|
||||
item.status == 'subscribe' &&
|
||||
item.bookingInfo &&
|
||||
item.bookingInfo.status == 20
|
||||
">
|
||||
<el-button type="success" :disabled="!item.tableId || item.status === 'closed'"
|
||||
@click="markStatus(item, 10)">
|
||||
到店
|
||||
</el-button>
|
||||
</template>
|
||||
<template
|
||||
v-if="
|
||||
item.status == 'idle' ||
|
||||
(item.status == 'subscribe' &&
|
||||
item.bookingInfo &&
|
||||
item.bookingInfo.status == 10)
|
||||
"
|
||||
>
|
||||
<el-button
|
||||
type="primary"
|
||||
:disabled="!item.tableCode || item.status === 'closed'"
|
||||
@click="diancanShow(item)"
|
||||
>
|
||||
<template v-if="
|
||||
item.status == 'idle' ||
|
||||
(item.status == 'subscribe' &&
|
||||
item.bookingInfo &&
|
||||
item.bookingInfo.status == 10)
|
||||
">
|
||||
<el-button type="primary" :disabled="!item.tableCode || item.status === 'closed'"
|
||||
@click="diancanShow(item)">
|
||||
点餐
|
||||
</el-button>
|
||||
</template>
|
||||
<template
|
||||
v-else-if="item.status != 'idle' && item.status != 'subscribe'"
|
||||
>
|
||||
<template v-else-if="item.status != 'idle' && item.status != 'subscribe'">
|
||||
<template v-if="item.status == 'using'">
|
||||
<el-button
|
||||
:disabled="!item.tableId || item.status === 'closed'"
|
||||
@click="diancanShow(item, 'isAddGoods')"
|
||||
>
|
||||
<el-button :disabled="!item.tableId || item.status === 'closed'"
|
||||
@click="diancanShow(item, 'isAddGoods')">
|
||||
加菜
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
:disabled="!item.tableId || item.status === 'closed'"
|
||||
@click="diancanShow(item, 'isPayOrder')"
|
||||
>
|
||||
<el-button type="danger" :disabled="!item.tableId || item.status === 'closed'"
|
||||
@click="diancanShow(item, 'isPayOrder')">
|
||||
结账
|
||||
</el-button>
|
||||
</template>
|
||||
@@ -200,13 +155,10 @@
|
||||
<el-button type="info" disabled>已关台</el-button>
|
||||
</template>
|
||||
<template v-else-if="item.status == 'cleaning'">
|
||||
<el-button
|
||||
type="info"
|
||||
:style="{
|
||||
backgroundColor: status[item.status].type,
|
||||
borderColor: status[item.status].type,
|
||||
}"
|
||||
>
|
||||
<el-button type="info" :style="{
|
||||
backgroundColor: status[item.status].type,
|
||||
borderColor: status[item.status].type,
|
||||
}">
|
||||
清理中
|
||||
</el-button>
|
||||
</template>
|
||||
@@ -216,26 +168,17 @@
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="u-flex u-col-bottom bottom u-row-between color-666"
|
||||
:class="{ 'opacity-0': item.status == 'closed' }"
|
||||
>
|
||||
<div class="u-flex u-col-bottom bottom u-row-between color-666"
|
||||
:class="{ 'opacity-0': item.status == 'closed' }">
|
||||
<div class="u-flex u-col-center">
|
||||
<img
|
||||
style="width: 16px; height: 16px; filter: contrast(0.5)"
|
||||
src="@/assets/images/perpole.png"
|
||||
alt=""
|
||||
/>
|
||||
<img style="width: 16px; height: 16px; filter: contrast(0.5)" src="@/assets/images/perpole.png"
|
||||
alt="" />
|
||||
<span class="u-m-t-4 u-font-12 u-m-l-2">
|
||||
{{ item.useNum || 0 }}/{{ item.maxCapacity }}
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="item.status == 'using'" class="u-flex">
|
||||
<img
|
||||
style="width: 16px; height: 16px; filter: contrast(0.5)"
|
||||
src="@/assets/images/shalou.png"
|
||||
alt=""
|
||||
/>
|
||||
<img style="width: 16px; height: 16px; filter: contrast(0.5)" src="@/assets/images/shalou.png" alt="" />
|
||||
<span class="u-m-t-4 u-font-12">
|
||||
{{ formatTime(item.durationTime) }}
|
||||
</span>
|
||||
@@ -256,6 +199,8 @@
|
||||
<downloadTableCode ref="refDownloadTableCode" />
|
||||
<!-- 绑定桌码 -->
|
||||
<bindCode ref="refBindCode" @refresh="tableInit" />
|
||||
<!-- 清台设置 -->
|
||||
<clearTabDialog ref="clearTabDialogRef" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -270,6 +215,9 @@ import addEara from "./components/addEara.vue";
|
||||
import addTable from "./components/addTable.vue";
|
||||
import bindCode from "./components/bind-table-code.vue";
|
||||
import downloadTableCode from "./components/downloadTableCode.vue";
|
||||
import clearTabDialog from "./components/clearTabDialog.vue";
|
||||
|
||||
const clearTabDialogRef = ref(null)
|
||||
|
||||
const envName = import.meta.env.VITE_APP_NAME;
|
||||
|
||||
@@ -298,7 +246,7 @@ function formatTime(milliseconds) {
|
||||
return `${days ? days + "天" : ""} ${hours ? hours + "时" : ""} ${minutes + "分"}`;
|
||||
}
|
||||
|
||||
function downloadTableCpde() {}
|
||||
function downloadTableCpde() { }
|
||||
function downloadShopCpde() {
|
||||
try {
|
||||
const link = document.createElement("a");
|
||||
@@ -341,7 +289,7 @@ function tableComman(command, item) {
|
||||
ElMessage.success("删除成功");
|
||||
tableInit();
|
||||
})
|
||||
.catch(() => {});
|
||||
.catch(() => { });
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -417,7 +365,7 @@ function init() {
|
||||
areainit();
|
||||
tableInit();
|
||||
}
|
||||
onMounted(() => {});
|
||||
onMounted(() => { });
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
Reference in New Issue
Block a user