diff --git a/App.vue b/App.vue index 1e2c48f..8f3a6df 100644 --- a/App.vue +++ b/App.vue @@ -160,6 +160,8 @@ App.vue本身不是页面,这里不能编写视图元素,也就是没有 \ No newline at end of file diff --git a/commons/style/common.scss b/commons/style/common.scss index b6b3ec8..bf82359 100644 --- a/commons/style/common.scss +++ b/commons/style/common.scss @@ -403,4 +403,13 @@ text { ::v-deep .u-m-t-16 .u-textarea{ border-width: 1px!important; +} + +/* #ifdef H5 */ +.u-flex, .u-flex-row, .u-flex-x, .up-flex, .up-flex-row, .up-flex-x{ + // flex-direction: row; +} +/* #endif */ +.u-flex-col{ + flex-direction: column!important; } \ No newline at end of file diff --git a/commons/utils/encryptUtil.js b/commons/utils/encryptUtil.js deleted file mode 100644 index 95881ce..0000000 --- a/commons/utils/encryptUtil.js +++ /dev/null @@ -1,72 +0,0 @@ -/** - * 加解密工具包 - * - * @author terrfly - * @site https://www.jeepay.vip - * @date 2021/5/16 17:35 - */ -import { SM4 } from 'gm-crypto' -import appConfig from '@/config/appConfig.js' - -let HEX_KEY = null - -// 字符串转16进制 -function str2hex(str) { - var val = '' - for (var i = 0; i < str.length; i++) { - if (val == '') - val = str.charCodeAt(i).toString(16) - else - val += str.charCodeAt(i).toString(16) - } - val += '' - return val -} - -// 获取hex秘钥 -function getHexKey(){ - - if(!HEX_KEY){ - - HEX_KEY = str2hex(appConfig.encryptKey) - - } - return HEX_KEY -} - - -// 解密 (http响应数据, 做通用处理) -export function sm4DecryptByResData(data){ - - if(!data){ - return data - } - - let res = SM4.decrypt(data, getHexKey(), { - inputEncoding: 'base64', - outputEncoding: 'utf8' - }) - - if(!res){ - return res - } - - return JSON.parse(res)['originData'] -} - -// 加密 (http响应数据, 做通用处理) -export function sm4EncryptByReqData(data){ - - if(!data){ - return data - } - - // 加密处理 - let encryptData = SM4.encrypt(JSON.stringify(data), getHexKey(), { - inputEncoding: 'utf8', - outputEncoding: 'base64' - }) - - return {encryptData : encryptData} -} - diff --git a/components/my-components/my-login.vue b/components/my-components/my-login.vue index d097dc0..d317361 100644 --- a/components/my-components/my-login.vue +++ b/components/my-components/my-login.vue @@ -11,19 +11,19 @@ - + - + - - + + @@ -94,9 +94,6 @@ \ No newline at end of file diff --git a/pagesCreateOrder/index/components/car.vue b/pagesCreateOrder/index/components/car.vue index 15e1ee3..23410da 100644 --- a/pagesCreateOrder/index/components/car.vue +++ b/pagesCreateOrder/index/components/car.vue @@ -1,654 +1,783 @@ \ No newline at end of file diff --git a/pagesCreateOrder/index/components/cart-goods-item.vue b/pagesCreateOrder/index/components/cart-goods-item.vue index 1cba1ed..c7189ca 100644 --- a/pagesCreateOrder/index/components/cart-goods-item.vue +++ b/pagesCreateOrder/index/components/cart-goods-item.vue @@ -1,310 +1,426 @@ \ No newline at end of file diff --git a/pagesCreateOrder/index/components/guige.vue b/pagesCreateOrder/index/components/guige.vue index 6960214..084f6a8 100644 --- a/pagesCreateOrder/index/components/guige.vue +++ b/pagesCreateOrder/index/components/guige.vue @@ -1,249 +1,282 @@ \ No newline at end of file diff --git a/pagesCreateOrder/index/index.vue b/pagesCreateOrder/index/index.vue index e4eb3f5..bd753d4 100644 --- a/pagesCreateOrder/index/index.vue +++ b/pagesCreateOrder/index/index.vue @@ -1,251 +1,355 @@ + + + + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/pagesOrder/detail/detail.vue b/pagesOrder/detail/detail.vue index 7a8689d..c4b0380 100644 --- a/pagesOrder/detail/detail.vue +++ b/pagesOrder/detail/detail.vue @@ -98,8 +98,8 @@ */ function getShopInfoData () { getShopInfo({id:uni.getStorageSync('shopInfo').id}).then(res=>{ - pageData.shopInfo = res; - uni.setStorageSync('shopInfo',res) + pageData.shopInfo = res.data; + uni.setStorageSync('shopInfo',res.data) }) } diff --git a/pagesOrder/pay-order/pay-order.vue b/pagesOrder/pay-order/pay-order.vue index d5539aa..c20998c 100644 --- a/pagesOrder/pay-order/pay-order.vue +++ b/pagesOrder/pay-order/pay-order.vue @@ -1,1197 +1,1432 @@ - - + - - - - - - - - - - - - - - + + \ No newline at end of file diff --git a/pagesOrder/quan/coupon.ts b/pagesOrder/quan/coupon.ts new file mode 100644 index 0000000..f721b57 --- /dev/null +++ b/pagesOrder/quan/coupon.ts @@ -0,0 +1,888 @@ +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; diff --git a/pagesOrder/quan/quan.vue b/pagesOrder/quan/quan.vue index 7b0ad03..4724b6f 100644 --- a/pagesOrder/quan/quan.vue +++ b/pagesOrder/quan/quan.vue @@ -1,580 +1,779 @@ \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7c9ec7f..2d56c8c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,9 @@ importers: .: dependencies: + bignumber.js: + specifier: ^9.3.1 + version: 9.3.1 clipboard: specifier: ^2.0.11 version: 2.0.11 @@ -33,8 +36,8 @@ importers: specifier: ^3.3.32 version: 3.6.10 ysk-utils: - specifier: ^1.0.50 - version: 1.0.50 + specifier: ^1.0.56 + version: 1.0.56 devDependencies: copy-webpack-plugin: specifier: ^12.0.2 @@ -325,8 +328,8 @@ packages: engines: {node: '>=0.10'} hasBin: true - electron-to-chromium@1.5.248: - resolution: {integrity: sha512-zsur2yunphlyAO4gIubdJEXCK6KOVvtpiuDfCIqbM9FjcnMYiyn0ICa3hWfPr0nc41zcLWobgy1iL7VvoOyA2Q==} + electron-to-chromium@1.5.249: + resolution: {integrity: sha512-5vcfL3BBe++qZ5kuFhD/p8WOM1N9m3nwvJPULJx+4xf2usSlZFJ0qoNYO2fOX4hi3ocuDcmDobtA+5SFr4OmBg==} emojis-list@3.0.0: resolution: {integrity: sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==} @@ -685,8 +688,8 @@ packages: webpack-cli: optional: true - ysk-utils@1.0.50: - resolution: {integrity: sha512-lQbm5T5jBqlB4O4E/f39l+mtKepBfNp81vTWsAko+2524VvrRdNZyzeqAeTaNM1IA9XOtcU7wPWOqEp+3Z6PRw==} + ysk-utils@1.0.56: + resolution: {integrity: sha512-TsRQGo1TEIVWZTc/j084eKVhTeI4r73dJRrzJHPUI56861hy40ekwYtozoa8v+LURXgEVIwXlMHM6zkgv8zBZw==} snapshots: @@ -931,7 +934,7 @@ snapshots: dependencies: baseline-browser-mapping: 2.8.25 caniuse-lite: 1.0.30001754 - electron-to-chromium: 1.5.248 + electron-to-chromium: 1.5.249 node-releases: 2.0.27 update-browserslist-db: 1.1.4(browserslist@4.27.0) @@ -975,7 +978,7 @@ snapshots: detect-libc@1.0.3: optional: true - electron-to-chromium@1.5.248: {} + electron-to-chromium@1.5.249: {} emojis-list@3.0.0: {} @@ -1297,7 +1300,7 @@ snapshots: - esbuild - uglify-js - ysk-utils@1.0.50: + ysk-utils@1.0.56: dependencies: bignumber.js: 9.3.1 loadsh: 0.0.4