代客下单逻辑修改

This commit is contained in:
2025-11-14 18:06:04 +08:00
parent d0cee95145
commit 67ec915181
26 changed files with 5314 additions and 870 deletions

View File

@@ -17,7 +17,7 @@
<view class="u-m-t-10 u-flex u-row-center color-main">
<view @click="discountShow">修改</view>
</view>
<view class="u-m-t-10 u-flex u-row-center color-main">
<view class="u-m-t-10 u-flex u-row-center color-main u-m-t-24">
<view @click="chooseUser()">选择用户</view>
</view>
</view>
@@ -58,13 +58,16 @@
</view>
<view
class="border-bottom-dashed u-p-b-30 u-p-t-30"
v-if="discountSaleAmount * 1 > 0"
v-if="orderCostSummary.fullReduction.actualAmount&&orderCostSummary.fullReduction.usedThreshold"
>
<view class="u-flex u-p-l-24 u-p-r-24 u-row-between">
<view>单品打折优惠</view>
<view class="color-red"> -{{ discountSaleAmount }} </view>
<view>满减活动</view>
<view class="color-red">
-{{ orderCostSummary.fullReduction.actualAmount }}
</view>
</view>
</view>
<view class="border-bottom-dashed u-p-b-30 u-p-t-30">
<view class="u-flex u-p-l-24 u-p-r-24 u-row-between" @click="toQuan">
@@ -312,6 +315,7 @@
import {
reactive,
onMounted,
nextTick,
watch,
ref,
onBeforeUnmount,
@@ -338,6 +342,8 @@ import { getDiscountByUserId } from "@/http/yskApi/market/consumeDiscount.js";
import { getHistoryOrder } from "@/http/api/order.js";
import { getPayTypeList } from "@/http/api/payType.js";
import { shopUserDetail } from "@/http/api/shopUser.js";
import { discountActivity } from "@/http/yskApi/market/discountActivity.js";
import {
scanPay,
microPay,
@@ -353,6 +359,7 @@ import {
payedDeductPoints,
consumeAwardPoints,
} from "@/http/api/points.js";
import yskUtils from "ysk-utils";
const websocketUtil = inject("websocketUtil"); // 注入 WebSocket 工具类实例
@@ -380,8 +387,7 @@ const pageData = reactive({
const order = reactive({
orderAmount: 0,
});
//商品数量从0到n每一个对应的价格
let $goodsPayPriceMap = {};
const pays = reactive({
list: ["扫码收款", "二维码收款"],
selIndex: 0,
@@ -420,10 +426,20 @@ onShow(() => {
watchChooseQuan();
});
const options = reactive({});
async function getDiscountActivity() {
let res = await discountActivity({
shopId: uni.getStorageSync("shopId"),
});
if (res.code == 200) {
fullReductionActivities.value = res.data?[res.data]:[];
}
}
onLoad(async (opt) => {
Object.assign(order, opt);
Object.assign(options, opt);
getPayType();
await getPayType();
await getDiscountActivity()
console.log("pays.payTypes.list");
init();
});
onBeforeUnmount(() => {
@@ -445,6 +461,9 @@ function toDiancai() {
* 初始化
*/
async function init() {
nextTick(() => {
onMessage();
});
// 获取订单详情
const { data: orderRes } = await getHistoryOrder({ orderId: order.orderId });
if (orderRes.status == "cancelled") {
@@ -466,11 +485,10 @@ async function init() {
Object.assign(order, orderRes);
pageData.goodsList = objToArrary(orderRes.detailMap);
$goodsPayPriceMap = returnGoodsPayPriceMap(pageData.goodsList);
// console.log("order===",order)
// console.log("pageData.user===",pageData.user)
// 获取用户信息
if (order.userId || pageData.user.userId) {
shopUserDetail({
userId: order.userId || pageData.user.userId,
@@ -549,42 +567,7 @@ const originPrice = computed(() => {
}
});
const newOriginPrice = computed(() => {
if (pageData.goodsList) {
let goodsPrice = pageData.goodsList
.filter((v) => v.price != 0 && v.status !== "return")
.reduce((a, b) => {
let memberPrice = b.memberPrice ? b.memberPrice : b.price;
let tPrice = isVip.value ? memberPrice : b.price;
tPrice = b.discountSaleAmount ? b.discountSaleAmount : tPrice;
return (
a +
parseFloat(
mathFloorPrice(b.num * tPrice, b) * 1 -
mathFloorPrice(b.returnNum * tPrice, b) * 1 -
mathFloorPrice(b.refundNum * tPrice, b) * 1
)
);
}, 0);
// console.log("减去退款退费的菜品金额===",goodsPrice)
return (goodsPrice + tableFee.value + packAmount.value).toFixed(2);
}
});
/**
* 菜品折扣金额
*/
const discountSaleAmount = computed(() => {
if (pageData.goodsList) {
let price = pageData.goodsList
.filter((v) => v.discountSaleAmount > 0 && v.status !== "return")
.reduce((a, b) => {
return a + (b.num * b.price - b.num * b.discountSaleAmount);
}, 0);
// console.log("单品折扣金额====",price)
return price.toFixed(2);
}
});
@@ -756,6 +739,9 @@ watch(
v.disabled = false;
});
}
},
{
immediate: true,
}
);
@@ -797,14 +783,14 @@ function getPayParam() {
newCustomerDiscountAmount: orderCostSummary.value.newUserDiscount, //新客立减
newCustomerDiscountId:
orderCostSummary.value.newUserDiscount > 0
? cartStore.consumeDiscount.id
? newUserDiscountRes.value.id
: "",
discountActAmount: orderCostSummary.value.fullReduction.actualAmount, //满减抵扣金额
discountActId: orderCostSummary.value.fullReduction.usedActivity
discountActId: (orderCostSummary.value.fullReduction.usedActivity&&orderCostSummary.value.fullReduction.usedThreshold)
? orderCostSummary.value.fullReduction.usedActivity.id
: null,
vipPrice: orderCostSummary.value.vipDiscountAmount != 0 ? 1 : 0, // 是否使用会员价
vipPrice:isVip.value? 1 : 0, // 是否使用会员价
limitRate:
order.limitRate && order.limitRate.id
? {
@@ -840,7 +826,6 @@ function getPayUrl() {
if (order.userId || pageData.user.userId) {
params.userId = order.userId || pageData.user.userId;
}
delete params.limitRate;
getOrderPayUrl(params).then((res) => {
console.log(res, "tishi");
payCodeUrl.value = res.data;
@@ -854,11 +839,20 @@ function getPayUrl() {
async function getPayType() {
const payTypeList = await getPayTypeList();
pays.payTypes.list = [];
const arr = ["cash", "member-account"];
payTypeList.data.map((v) => {
if (v.payType != "bank") {
let disabled = false;
if (orderCostSummary.value.finalPayAmount <= 0) {
if (arr.includes(v.payType)) {
disabled = false;
} else {
disabled = true;
}
}
pays.payTypes.list.push({
...v,
disabled: false,
disabled
});
}
});
@@ -927,6 +921,9 @@ function changeAccountPoints() {
function toQuan() {
console.log("toQuan", order);
console.log("pageData.user", pageData.user);
if(orderCostSummary.value.usedActivity){
return infoBox.showToast("满减活动不可与优惠券同享")
}
if (!order.userId && !pageData.user.id) {
return infoBox.showToast("请先选择会员", 0.5).then(() => {
chooseUser();
@@ -993,19 +990,80 @@ function chooseUser() {
function watchChooseuser() {
uni.$off("choose-user");
uni.$on("choose-user", (data) => {
if (pageData.user.id != data.id) {
selCoupon.value = [];
accountPoints.sel = false;
}
pageData.user = data;
if (data.id) {
getNewUserDiscount();
}
init();
});
}
watch(
() => pageData.user.id,
(newval) => {
selCoupon.value = [];
accountPoints.sel = false;
// 更新购物车和历史订单数据
uodateCartAndHistory();
if (newval) {
getNewUserDiscount();
// getShopUserDetail();
}
}
);
/**
* 更新购物车和历史订单数据
*/
function uodateCartAndHistory() {
let newData = {
history: [],
cart: [],
};
console.log("uodateCartAndHistory", pageData.user);
for (let cart of pageData.goodsList) {
const canUseLimitTimeDiscount = yskUtils.limitUtils.canUseLimitTimeDiscount(
cart,
order.limitRate,
pageData.shopInfo,
pageData.user,
"productId"
)
? 1
: 0;
console.log("uodateCartAndHistory", pageData.user);
if (canUseLimitTimeDiscount != cart.is_time_discount) {
newData.cart.push({
id: cart.id,
is_time_discount: canUseLimitTimeDiscount,
});
}
}
if (newData.history.length <= 0 && newData.cart.length <= 0) {
return;
}
websocketUtil.send(
JSON.stringify({
type: "pad",
account: uni.getStorageSync("shopInfo").id,
shop_id: uni.getStorageSync("shopInfo").id,
operate_type: "bulk_edit",
table_code: order.takeCode,
data: newData,
})
);
}
function getShopUserDetail() {
shopUserDetail({
// shopId: uni.getStorageSync("shopInfo").id,
id: pageData.user.id,
}).then((res) => {
if (res.data) {
pageData.user = res.data;
}
});
}
const newUserDiscountRes=ref(null)
//获取用户新客立减
function getNewUserDiscount() {
getDiscountByUserId({
@@ -1013,6 +1071,7 @@ function getNewUserDiscount() {
}).then((res) => {
if (res.data) {
newUserDiscount.value = res.data.amount || 0;
newUserDiscountRes.value = res.data;
}
});
}
@@ -1298,6 +1357,64 @@ function cashConfirmShow() {
modal.key = "cash";
modal.show = true;
}
/**
* 获取历史订单并更新商品列表
*/
async function getHistoryAndUpdateGoodsList() {
// 获取订单详情
const { data: orderRes } = await getHistoryOrder({ orderId: order.orderId });
if (orderRes.status == "cancelled") {
uni.showToast({
title: "订单已取消",
icon: "none",
});
toDiancai();
return;
}
if (orderRes.status == "done") {
uni.showToast({
title: "订单已完成",
icon: "none",
});
toDiancai();
return;
}
Object.assign(order, orderRes);
pageData.goodsList = objToArrary(orderRes.detailMap);
pageData.seatNum = order.seatNum;
}
/**
* socket消息监听
*/
function onMessage() {
websocketUtil.offMessage();
websocketUtil.onMessage((res) => {
let msg = JSON.parse(res);
switch (msg.operate_type) {
case "pad_init":
getHistoryAndUpdateGoodsList();
break;
case "pad_add":
case "add":
break;
case "pad_edit":
case "edit":
break;
case "pad_del":
case "del":
break;
case "pad_cleanup":
case "cleanup":
break;
case "product_update":
break;
case "pad_batch":
break;
}
});
}
</script>
<style lang="scss" scoped>

View File

@@ -1,888 +0,0 @@
import { BigNumber } from "bignumber.js";
import _ from "lodash";
export interface Goods {
productId: string | number; // 商品ID唯一标识商品用于优惠券/活动匹配,必选)
skuId: string | number; // 商品规格ID唯一标识商品规格如颜色/尺寸)
id: string | number; // 购物车ID唯一标识购物车中的条目如购物车项主键
product_id: string | number; // 商品ID唯一标识商品用于优惠券/活动匹配,必选)
salePrice: number; // 商品原价(元)
number: number; // 商品数量
product_type: string; // 商品类型
is_temporary?: number; // 是否临时菜默认false
is_gift?: number; // 是否赠菜默认false
returnNum?: number; // 退货数量历史订单用默认0
memberPrice: number; // 商品会员价(元,优先级:商品会员价 > 会员折扣)
discountSaleAmount?: number; // 商家改价后单价(元,优先级最高)
packFee?: number; // 单份打包费默认0
packNumber?: number; // 堂食打包数量默认0
skuData?: {
// SKU扩展数据可选
id: string | number; // SKU ID唯一标识商品规格如颜色/尺寸)
memberPrice?: number; // SKU会员价
salePrice?: number; // SKU原价
};
discount_sale_amount: number; // 商家改价后单价(元,优先级最高)
[property: string]: any;
}
export interface User {
isVip: number; // 是否会员 1是会员
[property: string]: any;
}
export interface ShopInfo {
isMemberPrice: number; // 是否开启会员价 1是开启
[property: string]: any;
}
export interface ThresholdFood {
id: string | number; // 商品ID
[property: string]: any;
}
export interface UseFood {
id: string | number;
[property: string]: any;
}
export interface Coupon {
id: string | number;
use: boolean;
type: number;
thresholdFoods: ThresholdFood[];
useFoods: UseFood[];
noUseRestrictions?: string;
discountShare: number; // 是否与折扣优惠同享 1是同享
vipPriceShare: number; // 是否与会员优惠同享 1是同享
otherCouponShare: number; // 是否与其他优惠券同享 1是同享
fullAmount: number; // 使用门槛金额
discountRate: number; // 折扣率(满减券:折扣金额/门槛金额,折扣券:折扣率)
maxDiscountAmount: number; // 最大折扣金额(满减券:折扣金额,折扣券:折扣金额)
discountNum: number; // 抵扣商品数量商品券抵扣商品数量折扣券0
useRule: string; // 使用规则price_asc按商品单价升序price_desc按商品单价降序
}
export interface couponDiscount {
discountPrice: number;
hasDiscountGoodsArr: Goods[];
}
export interface selCoupon extends Coupon {
discount?: couponDiscount;
}
export interface couponCalcParams {
canDikouGoodsArr: Goods[];
coupon: Coupon;
user: User;
shopInfo: ShopInfo;
selCoupon: selCoupon[];
goodsOrderPrice: number; //商品订单总价
isMemberPrice: number; // 是否开启会员价 1是开启
limitTimeDiscount?: TimeLimitDiscountConfig | null | undefined;
}
//限时折扣配置
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;
}
export interface CanDikouGoodsArrArgs {
canDikouGoodsArr: Goods[];
selCoupon: selCoupon[];
user: User;
shopInfo: ShopInfo;
limitTimeDiscount?: TimeLimitDiscountConfig | null | undefined;
}
/**
* 返回商品单价
* @param goods 商品
* @param user 用户信息
* @param {Object} shopInfo
*/
export function returnGoodsPrice(
goods: Goods,
user: User,
shopInfo: ShopInfo,
limitTimeDiscount: TimeLimitDiscountConfig | null | undefined
) {
if (!goods) {
return 0;
}
//是否可以使用会员价
const canUseVipPrice =
user &&
user.isVip &&
user.isMemberPrice &&
goods.memberPrice * 1 > 0 &&
shopInfo &&
shopInfo.isMemberPrice;
// 商家改价
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: Goods[]) {
let map: { [key: string]: Goods[] } = {};
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: Coupon) {
const couponTypes = {
1: "满减券",
2: "商品券",
3: "折扣券",
4: "第二件半价券",
5: "消费送券",
6: "买一送一券",
7: "固定价格券",
8: "免配送费券",
};
return couponTypes[coupon.type as keyof typeof couponTypes] || "未知类型";
}
/**
* 返回商品券抵扣后的商品列表
* @param canDikouGoodsArr 可抵扣商品列表
* @param selCoupon 已选择的优惠券列表
* @param user 用户信息
*/
export function returnCanDikouGoodsArr(args: CanDikouGoodsArrArgs) {
const { canDikouGoodsArr, selCoupon, user, shopInfo, limitTimeDiscount } =
args;
const types = [2, 4, 6];
// 收集已抵扣商品并关联对应的优惠券类型
const goodsCouponGoods = selCoupon
.filter((v) => types.includes(v.type))
.reduce((prev: Goods[], cur) => {
// 给每个抵扣商品添加所属优惠券类型
if (cur && cur.discount) {
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: ShopInfo, user: User, goods: Goods) {
if (goods.is_time_discount) {
return false;
}
if (shopInfo.isMemberPrice != 1 || user.isVip != 1) {
return false;
}
if (shopInfo.isMemberPrice == 1 && user.isVip == 1) {
console.log('goods', goods);
if (goods.memberPrice <= 0) {
return false;
}else{
return true;
}
}
return false
}
/**
* 返回可以计算抵扣金额的商品列表
*/
function returnCanCalcGoodsList(canCalcGoodsArr: Goods[], coupon: Coupon, shopInfo: ShopInfo, user: User) {
return canCalcGoodsArr.filter((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: couponCalcParams) {
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(args);
//优惠券指定门槛商品列表
let canCalcGoodsArr = [...canDikouGoodsArr];
//部分商品参与门槛计算
if (coupon.thresholdFoods.length) {
canCalcGoodsArr = canDikouGoodsArr.filter((v) => {
return coupon.thresholdFoods.find((food) => food.id == v.productId);
});
}
console.log("canCalcGoodsArr",canCalcGoodsArr);
canCalcGoodsArr = returnCanCalcGoodsList(
canCalcGoodsArr,
coupon,
shopInfo,
user
);
fullAmount = canCalcGoodsArr.reduce((pre, cur) => {
return (
pre + returnGoodsPrice(cur, user, shopInfo, limitTimeDiscount) * cur.num
);
}, 0);
// 是否全部商品可用
const isDikouAll = coupon.useFoods.length === 0;
// 订单可用商品列表
let canUseGoodsArr: Goods[] = [];
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(coupon.type==2){
console.log("isDikouAll",isDikouAll);
console.log("canCalcGoodsArr",canCalcGoodsArr);
}
// 没有符合条件的商品
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 店铺信息
*/
export function calcDiscountGoodsArrPrice(
discountGoodsArr: Goods[],
discountNum: number,
user: User,
shopInfo: ShopInfo,
limitTimeDiscount?: TimeLimitDiscountConfig | null | undefined
) {
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: Goods[],
coupon: Coupon,
user: User,
goodsOrderPrice: number,
selCoupon: selCoupon[],
shopInfo: ShopInfo,
limitTimeDiscount?: TimeLimitDiscountConfig | null | undefined
) {
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: Goods[],
coupon: Coupon,
user: User,
goodsOrderPrice: number,
selCoupon: selCoupon[],
limitTimeDiscount?: TimeLimitDiscountConfig | null | undefined
) {
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 || 0)
);
}, 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 店铺信息
*/
export function returnCouponProductDiscount(
canDikouGoodsArr: Goods[],
coupon: Coupon,
user: User,
shopInfo: ShopInfo,
limitTimeDiscount?: TimeLimitDiscountConfig | null | undefined
) {
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 店铺信息
*/
function returnCouponBuyOneGiveOneDiscount(
canDikouGoodsArr: Goods[],
coupon: Coupon,
user: User,
shopInfo: ShopInfo,
limitTimeDiscount?: TimeLimitDiscountConfig | null | undefined
) {
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: Goods[] = [];
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 店铺信息
*/
function returnSecoendDiscount(
canDikouGoodsArr: Goods[],
coupon: Coupon,
user: User,
shopInfo: ShopInfo,
limitTimeDiscount?: TimeLimitDiscountConfig | null | undefined
) {
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: Goods[] = [];
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: Goods[],
user: User,
shopInfo: ShopInfo,
limitTimeDiscount?: TimeLimitDiscountConfig | null | undefined
) {
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;
}
export const utils = {
returnGoodsPrice,
returnGoodsGroupMap,
returnCoupType,
returnCanDikouGoods,
returnCanDikouGoodsArr,
returnCouponCanUse,
calcDiscountGoodsArrPrice,
returnCouponDiscount,
returnCouponProductDiscount,
returnCouponZhekouDiscount,
};
export default utils;

View File

@@ -48,9 +48,9 @@
</view>
<view class="u-flex u-font-24"> {{ item.fullAmount }}可用 </view>
<view class="u-flex">
<view class="use-btn" @click.stop="toEmitChooseQuan(item)"
<!-- <view class="use-btn" @click.stop="toEmitChooseQuan(item)"
>去使用</view
>
> -->
</view>
</view>
</view>
@@ -112,9 +112,9 @@
</view>
<view class="u-flex u-font-24"> {{ item.fullAmount }}可用 </view>
<view class="u-flex">
<view class="use-btn" @click.stop="toEmitChooseQuan(item)"
<!-- <view class="use-btn" @click.stop="toEmitChooseQuan(item)"
>去使用</view
>
> -->
</view>
</view>
</view>
@@ -173,7 +173,6 @@
<script setup>
import { ref, reactive, watch, computed, onMounted, toRaw } from "vue";
import couponUtils from "./coupon";
import color from "@/commons/color.js";
import dayjs from "dayjs";
import { getSafeBottomHeight } from "@/commons/utils/safe-bottom.js";
@@ -193,8 +192,12 @@ import { queryAllShopUser, shopUserDetail } from "@/http/yskApi/shop-user.js";
// const yskUtils = {
// couponUtils,
// };
import yskUtils from "ysk-utils";
// import yskUtils from "ysk-utils";
import {couponUtils} from "@/lib/index";
const yskUtils={
couponUtils
}
const modal = reactive({
title: "提示",
@@ -458,6 +461,7 @@ async function getQuan() {
const orderRes = await orderApi.tbOrderInfoDetail(option.orderId);
if (orderRes.code == 200) {
order.value = orderRes.data;
Object.assign(limitTimeDiscount,orderRes.data.limitRate)
}
console.log(order.value);
@@ -528,6 +532,7 @@ watch(
user,
shopInfo
);
console.log('canDikouGoodsArr');
console.log(canDikouGoodsArr);
let goodsCoupon = newval.filter((v) => v.type == 2);
@@ -757,6 +762,7 @@ $quan-color: #318afe;
flex-direction: column;
background-color: $quan-color;
height: 100%;
min-width: 180rpx;
}
&.goods {