订单结算修改,增加限时折扣
This commit is contained in:
18
common/api/market/exchange.js
Normal file
18
common/api/market/exchange.js
Normal file
@@ -0,0 +1,18 @@
|
||||
// 引入 request 文件
|
||||
import request from '@/common/api/request.js'
|
||||
import {prveUrl} from './config.js'
|
||||
|
||||
export const exchange = (data) => {
|
||||
return request({
|
||||
url: prveUrl + '/user/redemption/exchange',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
export const redemption = (data) => {
|
||||
return request({
|
||||
url: prveUrl + '/user/redemption',
|
||||
method: 'get',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
11
common/api/market/limitTimeDiscount.js
Normal file
11
common/api/market/limitTimeDiscount.js
Normal file
@@ -0,0 +1,11 @@
|
||||
// 引入 request 文件
|
||||
import request from '@/common/api/request.js'
|
||||
import {prveUrl} from './config.js'
|
||||
|
||||
export const getConfig = (data) => {
|
||||
return request({
|
||||
url: prveUrl + '/user/limitTimeDiscount',
|
||||
method: 'get',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
11
common/api/market/suggest.js
Normal file
11
common/api/market/suggest.js
Normal file
@@ -0,0 +1,11 @@
|
||||
// 引入 request 文件
|
||||
import request from '@/common/api/request.js'
|
||||
import {prveUrl} from './config.js'
|
||||
|
||||
export const getGoods = (data) => {
|
||||
return request({
|
||||
url: prveUrl + '/user/suggest',
|
||||
method: 'get',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
@@ -260,7 +260,7 @@ const getCouponPopupAjax = async () => {
|
||||
try {
|
||||
const shopId = uni.cache.get("shopId");
|
||||
const res = await birthdayGiftApi.config({ shopId });
|
||||
if (res.length) {
|
||||
if (res&&res.length) {
|
||||
// 处理有效期格式(固定有效期规则)
|
||||
allCoupons.value = res.map((item) => {
|
||||
if (item.validType === "fixed") {
|
||||
|
||||
56
components/goods-price.vue
Normal file
56
components/goods-price.vue
Normal file
@@ -0,0 +1,56 @@
|
||||
<template>
|
||||
<text v-if="limitDiscount && limitDiscount.id" class="limit-price">
|
||||
{{ returnPrice() }}
|
||||
</text>
|
||||
<text v-else>
|
||||
<text v-if="shopInfo.isMemberPrice == 1 && shopUserInfo.isVip == 1" class="memberPrice">
|
||||
{{ cart.memberPrice || cart.salePrice }}
|
||||
</text>
|
||||
<text v-else class="salePrice">{{ cart.salePrice }}</text>
|
||||
</text>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import BigNumber from "bignumber.js";
|
||||
import * as orderUtils from "@/utils/order-utils.js";
|
||||
|
||||
|
||||
function returnPrice(){
|
||||
return orderUtils.returnPrice({
|
||||
goods:props.cart,
|
||||
shopInfo:props.shopInfo,
|
||||
limitTimeDiscountRes:props.limitDiscount,
|
||||
shopUserInfo:props.shopUserInfo,
|
||||
idKey:props.idKey
|
||||
})
|
||||
}
|
||||
|
||||
const props = defineProps({
|
||||
//购物车
|
||||
cart: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
idKey:{
|
||||
type: String,
|
||||
default: 'id',
|
||||
},
|
||||
//限时折扣
|
||||
limitDiscount: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
//店铺用户信息
|
||||
shopUserInfo: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
//店铺信息
|
||||
shopInfo: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@@ -51,7 +51,6 @@ const wechatAcQrcode = ref("");
|
||||
const userinfo = uni.cache.get("userInfo") || {};
|
||||
const codeVal = ref(userinfo.wechatAcQrcode || "");
|
||||
function qrcodeResult(e) {
|
||||
console.log("qrcodeResult", e);
|
||||
wechatAcQrcode.value = e;
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<template>
|
||||
<view>
|
||||
|
||||
<up-popup :show="show" bgColor="transparent" mode="center" @close="close">
|
||||
<view class="container">
|
||||
<view class="content">
|
||||
@@ -32,7 +31,7 @@
|
||||
<script setup>
|
||||
import _ from "lodash";
|
||||
import dayjs from "dayjs";
|
||||
import { onMounted, ref } from "vue";
|
||||
import { onMounted, ref, watch } from "vue";
|
||||
import { string } from "../uni_modules/uview-plus/libs/function/test";
|
||||
|
||||
const bgUrl = ref(
|
||||
@@ -65,7 +64,7 @@ function init() {
|
||||
show.value = true;
|
||||
}
|
||||
}
|
||||
|
||||
watch(() => props.wechatAcQrcode, init);
|
||||
onMounted(() => {
|
||||
init();
|
||||
});
|
||||
|
||||
@@ -37,14 +37,7 @@ const userinfo = uni.cache.get("userInfo") || {};
|
||||
const codeVal = ref(userinfo.wechatAcQrcode || "");
|
||||
console.log("codeVal", codeVal.value);
|
||||
function qrcodeResult(e) {
|
||||
console.log("qrcodeResult", e);
|
||||
wechatAcQrcode.value = e;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.qrcode {
|
||||
position: fixed;
|
||||
transform: translateX(200vw, 200vh);
|
||||
}
|
||||
</style>
|
||||
@@ -162,12 +162,10 @@ const radiovalue = defineModel({
|
||||
watch(
|
||||
() => props.disablePayType,
|
||||
(newval) => {
|
||||
console.log('禁止支付方式', newval);
|
||||
|
||||
const canUsePayType = paymentMethodList.value.filter((item) => {
|
||||
return !newval.includes(item.name);
|
||||
});
|
||||
console.log('可用支付方式', canUsePayType);
|
||||
if (canUsePayType.find((v) => v.type == radiovalue.value.type)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ onMounted(() => {
|
||||
});
|
||||
const emit = defineEmits(["generate"]);
|
||||
function qrcodeResult(e) {
|
||||
console.log(e);
|
||||
emit("generate", e.img.tempFilePath);
|
||||
}
|
||||
</script>
|
||||
@@ -37,8 +36,10 @@ function qrcodeResult(e) {
|
||||
.qrcode-box {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
left: -400px;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
opacity: 0;
|
||||
z-index: -1;
|
||||
}
|
||||
</style>
|
||||
39
distribution/index.vue
Normal file
39
distribution/index.vue
Normal file
@@ -0,0 +1,39 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class="top">
|
||||
<up-navbar
|
||||
bg-color="transparent"
|
||||
title="分销中心"
|
||||
@leftClick="back"
|
||||
:fixed="false"
|
||||
></up-navbar>
|
||||
<image class="top_bg" src="/distribution/static/top_bg.png"></image>
|
||||
<view class="top_content"></view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
function back() {
|
||||
uni.navigateBack({
|
||||
delta: 1,
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.top{
|
||||
position: relative;
|
||||
.top_content{
|
||||
position: absolute;
|
||||
left: 28rpx;
|
||||
right: 28rpx;
|
||||
bottom: 0;
|
||||
padding: 32rpx 28rpx;
|
||||
}
|
||||
}
|
||||
.top_bg {
|
||||
width: 100%;
|
||||
height: 530rpx;
|
||||
}
|
||||
</style>
|
||||
BIN
distribution/static/top_bg.png
Normal file
BIN
distribution/static/top_bg.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 78 KiB |
76
pages.json
76
pages.json
@@ -203,45 +203,55 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/user/member/czzx-shop-list",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "适用门店"
|
||||
"path": "pages/user/member/czzx-shop-list",
|
||||
"style": {
|
||||
"navigationBarTitleText": "适用门店"
|
||||
}
|
||||
}
|
||||
],
|
||||
"subPackages": [{
|
||||
"root": "user",
|
||||
"pages": [{
|
||||
"path": "vip/vip",
|
||||
"style": {
|
||||
"navigationBarTitleText": "",
|
||||
"navigationStyle": "custom"
|
||||
"root": "user",
|
||||
"pages": [{
|
||||
"path": "vip/vip",
|
||||
"style": {
|
||||
"navigationBarTitleText": "",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "vip/buy-vip",
|
||||
"style": {
|
||||
"navigationBarTitleText": "",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "score/list",
|
||||
"style": {
|
||||
"navigationBarTitleText": "积分门店"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "exchange/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "vip/buy-vip",
|
||||
"style": {
|
||||
"navigationBarTitleText": "",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "score/list",
|
||||
"style": {
|
||||
"navigationBarTitleText": "积分门店"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "exchange/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
}
|
||||
|
||||
]
|
||||
}],
|
||||
]
|
||||
},
|
||||
{
|
||||
"root": "distribution",
|
||||
"pages": [{
|
||||
"path": "index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "分销中心",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
}, ]
|
||||
}
|
||||
],
|
||||
"uniIdRouter": {},
|
||||
"globalStyle": {
|
||||
"navigationBarTextStyle": "black",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -45,62 +45,66 @@
|
||||
</view>
|
||||
|
||||
<view class="card">
|
||||
<orderItemVue
|
||||
<!-- <orderItemVue
|
||||
:useVipPrice="useVipPrice"
|
||||
v-if="nowCarts.length"
|
||||
:nowCarts="nowCarts"
|
||||
:limitDiscount="cartStore.limitTimeDiscount"
|
||||
></orderItemVue> -->
|
||||
<orderItemVue
|
||||
:useVipPrice="useVipPrice"
|
||||
v-if="cartStore.allGoods.length"
|
||||
:nowCarts="cartStore.allGoods"
|
||||
:limitDiscount="cartStore.limitTimeDiscount"
|
||||
></orderItemVue>
|
||||
<!-- 订单头部 -->
|
||||
<view
|
||||
class="card_item"
|
||||
v-for="(value, key) in listinfo.detailMap"
|
||||
:key="key"
|
||||
>
|
||||
<!-- <view class="head">
|
||||
<view class="head_left">
|
||||
<text class="placeNum" v-if="key!=0">第{{key}}次下单</text>
|
||||
</view>
|
||||
</view> -->
|
||||
<!-- 订单详情 -->
|
||||
<view class="shop-info">
|
||||
<view class="item" v-for="item in value" :key="item.id">
|
||||
<view class="cover">
|
||||
<up-image
|
||||
width="76"
|
||||
height="76"
|
||||
radius="16"
|
||||
:src="item.productImg"
|
||||
v-if="item.productId != -999"
|
||||
></up-image>
|
||||
<up-image
|
||||
width="76"
|
||||
height="76"
|
||||
radius="16"
|
||||
:src="'https://czg-qr-order.oss-cn-beijing.aliyuncs.com/confirmOrder/table.png'"
|
||||
mode="heightFix"
|
||||
v-else
|
||||
></up-image>
|
||||
</view>
|
||||
<view class="info">
|
||||
<text class="productName">{{ item.productName }}</text>
|
||||
<text class="productSkuName" v-if="item.skuName">{{
|
||||
item.skuName
|
||||
}}</text>
|
||||
</view>
|
||||
<view class="price">
|
||||
<view class="priceAmount">
|
||||
<text v-if="isBwc">{{ item.price }}</text>
|
||||
<text v-else>
|
||||
¥{{
|
||||
useVipPrice ? item.memberPrice || item.price : item.price
|
||||
}}
|
||||
</text>
|
||||
<template v-if="false">
|
||||
<view
|
||||
class="card_item"
|
||||
v-for="(value, key) in listinfo.detailMap"
|
||||
:key="key"
|
||||
>
|
||||
<view class="shop-info">
|
||||
<view class="item" v-for="item in value" :key="item.id">
|
||||
<view class="cover">
|
||||
<up-image
|
||||
width="76"
|
||||
height="76"
|
||||
radius="6"
|
||||
:src="item.productImg"
|
||||
v-if="item.productId != -999"
|
||||
></up-image>
|
||||
<up-image
|
||||
width="76"
|
||||
height="76"
|
||||
radius="6"
|
||||
:src="'https://czg-qr-order.oss-cn-beijing.aliyuncs.com/confirmOrder/table.png'"
|
||||
mode="heightFix"
|
||||
v-else
|
||||
></up-image>
|
||||
</view>
|
||||
<view class="info">
|
||||
<text class="productName">{{ item.productName }}</text>
|
||||
<text class="productSkuName" v-if="item.skuName">{{
|
||||
item.skuName
|
||||
}}</text>
|
||||
</view>
|
||||
<view class="price">
|
||||
<view class="priceAmount">
|
||||
<text v-if="isBwc">{{ item.price }}</text>
|
||||
<text v-else>
|
||||
¥{{
|
||||
useVipPrice
|
||||
? item.memberPrice || item.price
|
||||
: item.price
|
||||
}}
|
||||
</text>
|
||||
</view>
|
||||
<view class="num">x{{ item.num }}</view>
|
||||
</view>
|
||||
<view class="num">x{{ item.num }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<view
|
||||
class="total-wrap u-m-t-30"
|
||||
@@ -154,7 +158,7 @@
|
||||
"
|
||||
>
|
||||
<view class="u-m-t-40 u-p-l-20 u-p-r-20">
|
||||
<view class="youhui-item" v-if="discountActivity">
|
||||
<view class="youhui-item" v-if="cartStore.orderCostSummary.fullReduction.actualAmount">
|
||||
<view class="u-flex align-center">
|
||||
<image
|
||||
src="/static/icon/coup.png"
|
||||
@@ -165,13 +169,13 @@
|
||||
</view>
|
||||
|
||||
<view class="red font-12 u-flex align-center"
|
||||
>-¥{{ discountActivity.discountAmount }}</view
|
||||
>-¥{{ cartStore.orderCostSummary.fullReduction.actualAmount }}</view
|
||||
>
|
||||
</view>
|
||||
<view class="youhui-item" v-if="newUserDiscount">
|
||||
<view class="u-flex align-center">
|
||||
<image
|
||||
src="/static/icon/coup.png"
|
||||
src="/static/icon/newUserDiscount.png"
|
||||
bgColor="#fff"
|
||||
style="width: 40rpx; height: 34rpx"
|
||||
></image>
|
||||
@@ -304,7 +308,10 @@
|
||||
</view>
|
||||
</block>
|
||||
<block v-else>
|
||||
<view class="cell-item column" v-if="listinfo.discountInfo">
|
||||
<view
|
||||
class="cell-item column"
|
||||
v-if="listinfo.discountInfo && listinfo.discountInfo != '{}'"
|
||||
>
|
||||
<view class="label">优惠折扣</view>
|
||||
<view class="val column">
|
||||
<view
|
||||
@@ -387,6 +394,7 @@ import {
|
||||
defineExpose,
|
||||
toRaw,
|
||||
onMounted,
|
||||
provide,
|
||||
nextTick,
|
||||
} from "vue";
|
||||
import { returnHasCouponCanUse } from "@/utils/coupon.js";
|
||||
@@ -588,8 +596,6 @@ const tabClick = (item, index) => {
|
||||
};
|
||||
cartStore.setDinnerType(tebtypeList[is_type.value].val);
|
||||
|
||||
|
||||
|
||||
// 清空
|
||||
const bwcclear = () => {
|
||||
IntegralInputclose();
|
||||
@@ -833,16 +839,13 @@ function calcDiscountActivity() {
|
||||
const res = discountActivityRes.value;
|
||||
const user = uni.cache.get("shopUserInfo");
|
||||
|
||||
//不与会员同享
|
||||
if (!res.vipPriceShare && user.isVip) {
|
||||
return;
|
||||
}
|
||||
console.log("calcDiscountActivity:originalPrice", originalPrice.value);
|
||||
const usedFullReductionActivityFullAmount=cartStore.orderCostSummary.fullReduction.usedFullReductionActivityFullAmount;
|
||||
console.log("usedFullReductionActivityFullAmount", usedFullReductionActivityFullAmount);
|
||||
|
||||
if (res && res.thresholds && res.thresholds.length > 0) {
|
||||
const canUseThresholds = res.thresholds
|
||||
.filter((v) => {
|
||||
return originalPrice.value >= v.fullAmount;
|
||||
return usedFullReductionActivityFullAmount >= v.fullAmount;
|
||||
})
|
||||
.sort((a, b) => {
|
||||
return b.discountAmount - a.discountAmount;
|
||||
@@ -859,9 +862,7 @@ function calcDiscountActivity() {
|
||||
}
|
||||
console.log("当前满减门槛", discountActivity.value);
|
||||
|
||||
if (discountActivity.value) {
|
||||
cartStore.fullReductionActivities = [discountActivityRes.value];
|
||||
}
|
||||
|
||||
}
|
||||
async function getDiscountActivity() {
|
||||
const res = await discountActivityApi.config({
|
||||
@@ -871,6 +872,8 @@ async function getDiscountActivity() {
|
||||
return;
|
||||
}
|
||||
discountActivityRes.value = res;
|
||||
cartStore.fullReductionActivities = [res];
|
||||
|
||||
calcDiscountActivity();
|
||||
}
|
||||
onMounted(async () => {
|
||||
@@ -1174,6 +1177,7 @@ onMounted(async () => {
|
||||
display: flex;
|
||||
|
||||
.cover {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.info {
|
||||
@@ -1561,4 +1565,19 @@ onMounted(async () => {
|
||||
.align-center {
|
||||
align-items: center;
|
||||
}
|
||||
.limitDiscount {
|
||||
background-color: #cc5617;
|
||||
padding: 2rpx 10rpx;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
color: #ffffff;
|
||||
border-radius: 20rpx 0rpx 20rpx 0rpx;
|
||||
z-index: 9;
|
||||
color: #fff;
|
||||
}
|
||||
</style>
|
||||
@@ -223,7 +223,7 @@
|
||||
@close="ispws = false"
|
||||
/>
|
||||
<!-- 私域引流配置 -->
|
||||
<OrderFinshModal v-model="showDrainage" ></OrderFinshModal>
|
||||
<OrderFinshModal v-model="showDrainage"></OrderFinshModal>
|
||||
</view>
|
||||
</template>
|
||||
<script setup>
|
||||
@@ -243,8 +243,10 @@ import {
|
||||
watch,
|
||||
onBeforeMount,
|
||||
onBeforeUnmount,
|
||||
provide,
|
||||
} from "vue";
|
||||
|
||||
provide("shopUserInfo", ref(uni.cache.get("shopUserInfo")));
|
||||
provide("shopInfo", ref(uni.cache.get("shopInfo")));
|
||||
import { getTableInfo } from "@/common/api/shop/index.js";
|
||||
import {
|
||||
APIgetOrderById,
|
||||
@@ -278,8 +280,8 @@ const cartStore = useCartsStore();
|
||||
|
||||
//充值相关start
|
||||
//充值和余额支付是否可用
|
||||
const isCanUseCharge = ref(false);
|
||||
function updateIsShow(e){
|
||||
const isCanUseCharge = ref(true);
|
||||
function updateIsShow(e) {
|
||||
isCanUseCharge.value = e;
|
||||
}
|
||||
const rechargeItem = ref({
|
||||
@@ -437,20 +439,22 @@ let historyTotalPrices = 0;
|
||||
// * 获取订单详情接口
|
||||
const orderorderInfo = async () => {
|
||||
console.log("listinfo.id", listinfo.id);
|
||||
if (!listinfo.id && !options.tableCode) {
|
||||
return;
|
||||
}
|
||||
let res = listinfo.id
|
||||
? await APIgetOrderById({
|
||||
orderId: listinfo.id,
|
||||
})
|
||||
: await APIhistoryOrder({
|
||||
tableCode: options.tableCode||"",
|
||||
tableCode: options.tableCode || "",
|
||||
});
|
||||
orderRemarker.value = res.remark;
|
||||
Object.assign(listinfo, res);
|
||||
if (res && res.tableCode) {
|
||||
socketInitPar.table_code = res.tableCode;
|
||||
let tableRes = await getTableInfo({
|
||||
tableCode: options.tableCode||"",
|
||||
|
||||
tableCode: options.tableCode || "",
|
||||
});
|
||||
console.log(tableRes);
|
||||
listinfo.tableName = tableRes.name;
|
||||
@@ -458,7 +462,7 @@ const orderorderInfo = async () => {
|
||||
if (options.tableCode) {
|
||||
socketInitPar.table_code = options.tableCode;
|
||||
let tableRes = await getTableInfo({
|
||||
tableCode: options.tableCode||"",
|
||||
tableCode: options.tableCode || "",
|
||||
});
|
||||
console.log(tableRes);
|
||||
listinfo.tableName = tableRes.name;
|
||||
@@ -634,8 +638,17 @@ const createOrder = async () => {
|
||||
placeNum: listinfo.id ? listinfo.placeNum * 1 + 1 : 1, //当前订单下单次数
|
||||
waitCall: "", //是否等叫 0 否 1 等叫
|
||||
orderId: listinfo.id || "",
|
||||
tableCode: options.tableCode||'',
|
||||
tableCode: options.tableCode || "",
|
||||
userId: uni.cache.get("userInfo").id || "", //
|
||||
limitRate: (cartStore.limitTimeDiscount&&cartStore.limitTimeDiscount.id)
|
||||
? {
|
||||
id: cartStore.limitTimeDiscount.id,
|
||||
discountRate: cartStore.limitTimeDiscount.discountRate,
|
||||
discountPriority: cartStore.limitTimeDiscount.discountPriority,
|
||||
foodType: cartStore.limitTimeDiscount.foodType,
|
||||
foods: cartStore.limitTimeDiscount.foods,
|
||||
}
|
||||
: null,
|
||||
});
|
||||
// 清空购物车
|
||||
if (res) {
|
||||
@@ -716,7 +729,18 @@ function returnPayParams() {
|
||||
: "",
|
||||
remark: orderRemarker.value, //用户备注
|
||||
discountActAmount: cartStore.orderCostSummary.fullReduction.actualAmount, //满减抵扣金额
|
||||
discountActId:cartStore.orderCostSummary.fullReduction.usedActivity?cartStore.orderCostSummary.fullReduction.usedActivity.id:null,
|
||||
userId: uni.cache.get("userInfo").id || "", //
|
||||
limitRate: (cartStore.limitTimeDiscount&&cartStore.limitTimeDiscount.id)
|
||||
? {
|
||||
id: cartStore.limitTimeDiscount.id,
|
||||
discountRate: cartStore.limitTimeDiscount.discountRate,
|
||||
discountPriority: cartStore.limitTimeDiscount.discountPriority,
|
||||
foodType: cartStore.limitTimeDiscount.foodType,
|
||||
foods: cartStore.limitTimeDiscount.foods,
|
||||
}
|
||||
: null,
|
||||
vipDiscountAmount: cartStore.orderCostSummary.vipDiscountAmount, //会员折扣减免金额
|
||||
};
|
||||
return {
|
||||
isBwc: isBwc.value,
|
||||
@@ -919,7 +943,6 @@ const goToPay = async (payParams) => {
|
||||
orderorderInfo();
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
const clickPointsamount = (Pointsamount) => {
|
||||
listinfo.pointsDiscountAmount = Pointsamount.pointsDiscountAmount;
|
||||
@@ -1063,9 +1086,13 @@ async function init(opt) {
|
||||
if (res) {
|
||||
uni.cache.set("tableCode", res.tableCode);
|
||||
uni.cache.set("tableCode", res.seatNum);
|
||||
options.tableCode = res.tableCode||'';
|
||||
options.tableCode = res.tableCode || "";
|
||||
cartStore.setSeatFeeConfig("personCount", res.seatNum);
|
||||
cartStore.setDinnerType(res.dineMode || "dine-in");
|
||||
cartStore.setOldOrder(res);
|
||||
if(res.limitRate){
|
||||
cartStore.limitTimeDiscount=res.limitRate
|
||||
}
|
||||
orderRemarker.value = res.remark;
|
||||
Object.assign(listinfo, res);
|
||||
}
|
||||
@@ -1162,7 +1189,7 @@ const disablePayType = computed(() => {
|
||||
// if (cartStore.orderCostSummary.orderOriginFinalPayAmount <= 0) {
|
||||
// arr.add("微信支付");
|
||||
// }
|
||||
if(!isCanUseCharge.value){
|
||||
if (!isCanUseCharge.value) {
|
||||
arr.add("余额支付");
|
||||
}
|
||||
|
||||
|
||||
@@ -328,7 +328,8 @@ function formatCoupon(){
|
||||
goodsOrderPrice,
|
||||
user,
|
||||
selCoupon:selCoupon,
|
||||
shopInfo
|
||||
shopInfo,
|
||||
limitTimeDiscount:cartStore.limitTimeDiscount
|
||||
});
|
||||
const { canUse, reason } = canuseResult;
|
||||
if (coupon.type == 2) {
|
||||
@@ -353,7 +354,7 @@ function formatCoupon(){
|
||||
}
|
||||
//商品券
|
||||
canUseGoodsCoupon = canUseGoodsCoupon.map((v) => {
|
||||
const discount = UTILS.returnCouponDiscount(canDikouGoodsArr, v, user, goodsOrderPrice, quansSelArr.value, shopInfo);
|
||||
const discount = UTILS.returnCouponDiscount(canDikouGoodsArr, v, user, goodsOrderPrice, quansSelArr.value, shopInfo,cartStore.limitTimeDiscount);
|
||||
return {
|
||||
...v,
|
||||
discount,
|
||||
@@ -362,7 +363,7 @@ function formatCoupon(){
|
||||
});
|
||||
//非商品券
|
||||
canUseDiscountCoupon = canUseDiscountCoupon.map((v) => {
|
||||
const discount = UTILS.returnCouponDiscount(canDikouGoodsArr, v, user, goodsOrderPrice, quansSelArr.value, shopInfo);
|
||||
const discount = UTILS.returnCouponDiscount(canDikouGoodsArr, v, user, goodsOrderPrice, quansSelArr.value, shopInfo,cartStore.limitTimeDiscount);
|
||||
return {
|
||||
...v,
|
||||
discount,
|
||||
@@ -518,7 +519,7 @@ watch(
|
||||
let goodsCoupon = newval.filter((v) => v.type == 2);
|
||||
let otherCoupon = newval.filter((v) => v.type != 2);
|
||||
goodsCoupon = goodsCoupon.map((v) => {
|
||||
const discount = UTILS.returnCouponDiscount(canDikouGoodsArr, v, user, goodsOrderPrice, [], shopInfo);
|
||||
const discount = UTILS.returnCouponDiscount(canDikouGoodsArr, v, user, goodsOrderPrice, [], shopInfo,cartStore.limitTimeDiscount);
|
||||
return {
|
||||
...v,
|
||||
discount,
|
||||
@@ -526,7 +527,7 @@ watch(
|
||||
};
|
||||
});
|
||||
otherCoupon = otherCoupon.map((v) => {
|
||||
const discount = UTILS.returnCouponDiscount(canDikouGoodsArr, v, user, goodsOrderPrice, goodsCoupon, shopInfo);
|
||||
const discount = UTILS.returnCouponDiscount(canDikouGoodsArr, v, user, goodsOrderPrice, goodsCoupon, shopInfo,cartStore.limitTimeDiscount);
|
||||
return {
|
||||
...v,
|
||||
discount,
|
||||
|
||||
196
pages/product/components/recommend-goods-modal.vue
Normal file
196
pages/product/components/recommend-goods-modal.vue
Normal file
@@ -0,0 +1,196 @@
|
||||
<template>
|
||||
<up-overlay :show="show">
|
||||
<view class="box" v-if="SelData">
|
||||
<view class="bg-fff u-p-30 item">
|
||||
<view class="u-flex coverImg">
|
||||
<up-image
|
||||
width="204rpx"
|
||||
height="228rpx"
|
||||
radius="6"
|
||||
:src="SelData.goods.coverImg"
|
||||
></up-image>
|
||||
<view class="limitDiscount" v-if="showLimitDiscount(SelData.goods)"
|
||||
>限时折扣</view
|
||||
>
|
||||
</view>
|
||||
|
||||
<view class="u-flex-1 u-p-l-36">
|
||||
<view class="u-flex u-col-center justify-between u-m-t-10">
|
||||
<view class="u-line-1 font-16 color-333 font-bold u-p-r-16">{{
|
||||
SelData.title
|
||||
}}</view>
|
||||
<up-icon
|
||||
size="20"
|
||||
name="close-circle"
|
||||
color="#666"
|
||||
@click="close"
|
||||
></up-icon>
|
||||
</view>
|
||||
<view class="color-333 font-14 u-m-t-32 u-line-1">{{
|
||||
SelData.guideDetail
|
||||
}}</view>
|
||||
<view class="u-flex justify-between u-m-t-30">
|
||||
<view class="price"
|
||||
>¥
|
||||
<GoodsPrice
|
||||
:limitDiscount="cartStore.limitTimeDiscount"
|
||||
:cart="SelData.goods"
|
||||
:shopUserInfo="shopUserInfo"
|
||||
:shopInfo="shopInfo"
|
||||
></GoodsPrice
|
||||
></view>
|
||||
<view class="buy" @click="buy">立即下单</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</up-overlay>
|
||||
</template>
|
||||
<script setup>
|
||||
import * as orderUtils from "@/utils/order-utils.js";
|
||||
import GoodsPrice from "@/components/goods-price.vue";
|
||||
import * as suggestApi from "@/common/api/market/suggest.js";
|
||||
import { ref, onMounted, inject, watch } from "vue";
|
||||
const cartStore = inject("cartStore");
|
||||
const shopUserInfo = inject("shopUserInfo");
|
||||
const shopInfo = inject("shopInfo");
|
||||
|
||||
function showLimitDiscount(item) {
|
||||
if (!cartStore.limitTimeDiscount) {
|
||||
return false;
|
||||
}
|
||||
return orderUtils.canUseLimitTimeDiscount(
|
||||
item,
|
||||
cartStore.limitTimeDiscount,
|
||||
shopInfo,
|
||||
shopUserInfo.value,
|
||||
"id"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
const show = ref(false);
|
||||
|
||||
let timer = null;
|
||||
|
||||
function taskEnd() {
|
||||
clearInterval(timer);
|
||||
show.value = false;
|
||||
}
|
||||
function statTime() {
|
||||
clearInterval(timer);
|
||||
timer = setTimeout(() => {
|
||||
const item = list.value[nowIndex.value];
|
||||
if (item) {
|
||||
SelData.value = item;
|
||||
show.value = true;
|
||||
} else {
|
||||
taskEnd();
|
||||
}
|
||||
}, suggestTime.value * 1000);
|
||||
}
|
||||
|
||||
const list = ref([]);
|
||||
const SelData = ref(null);
|
||||
const nowIndex = ref(0);
|
||||
function close() {
|
||||
suggestTime.value = 30;
|
||||
taskEnd();
|
||||
nowIndex.value += 1;
|
||||
if (nowIndex.value == list.value.length) {
|
||||
return;
|
||||
}
|
||||
statTime();
|
||||
}
|
||||
const suggestTime = ref(100);
|
||||
|
||||
const emits = defineEmits(["onBuyClick"]);
|
||||
function buy() {
|
||||
emits("onBuyClick", SelData.value.goods);
|
||||
}
|
||||
onMounted(() => {
|
||||
suggestApi
|
||||
.getGoods({
|
||||
shopId: uni.cache.get("shopId"),
|
||||
})
|
||||
.then((res) => {
|
||||
if (res) {
|
||||
suggestTime.value = res.suggestTime;
|
||||
list.value = (res.list || [])
|
||||
.map((v) => {
|
||||
return {
|
||||
...v,
|
||||
goods: cartStore.returnGoods(v.foods),
|
||||
};
|
||||
})
|
||||
.filter((v) => v.goods);
|
||||
console.log('list.value ', list.value )
|
||||
startWatch();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function startWatch() {
|
||||
watch(
|
||||
() => cartStore.isEmpty,
|
||||
(newval) => {
|
||||
if (newval && list.value.length) {
|
||||
statTime();
|
||||
} else {
|
||||
clearInterval(timer);
|
||||
nowIndex.value = 0;
|
||||
show.value = false;
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.box {
|
||||
position: fixed;
|
||||
z-index: 100;
|
||||
left: 30rpx;
|
||||
right: 30rpx;
|
||||
bottom: calc(var(--safe-area-inset-bottom) + 0px);
|
||||
.item {
|
||||
padding: 32rpx 28rpx;
|
||||
border-radius: 16rpx;
|
||||
background: #fff;
|
||||
box-shadow: 0 0 20rpx rgba(0, 0, 0, 0.05);
|
||||
display: flex;
|
||||
}
|
||||
.price {
|
||||
font-size: 40rpx;
|
||||
color: #333;
|
||||
}
|
||||
.buy {
|
||||
padding: 4rpx 28rpx;
|
||||
border-radius: 36rpx;
|
||||
background: #e8ad7b;
|
||||
color: #ffffff;
|
||||
font-size: 28rpx;
|
||||
line-height: 48rpx;
|
||||
}
|
||||
}
|
||||
.coverImg{
|
||||
position: relative;
|
||||
}
|
||||
.limitDiscount {
|
||||
background-color: #cc5617;
|
||||
padding: 2rpx 10rpx;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
color: #ffffff;
|
||||
border-radius: 20rpx 0rpx 20rpx 0rpx;
|
||||
z-index: 9;
|
||||
color: #fff;
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -58,6 +58,9 @@
|
||||
v-for="(item, index) in shopProductList.hots"
|
||||
:key="index"
|
||||
>
|
||||
<view class="limitDiscount" v-if="showLimitDiscount(item)"
|
||||
>限时折扣</view
|
||||
>
|
||||
<image
|
||||
class="panelfiveitemimage"
|
||||
:src="item.coverImg"
|
||||
@@ -151,6 +154,10 @@
|
||||
<text class="unit" v-if="item.unitName"
|
||||
>/{{ item.unitName }}</text
|
||||
>
|
||||
|
||||
<text class="old-price"
|
||||
>¥{{ item.salePrice }}</text
|
||||
>
|
||||
</view>
|
||||
</view>
|
||||
<view class="panelfiveitemNum">
|
||||
@@ -189,16 +196,21 @@
|
||||
>¥</text
|
||||
>
|
||||
<!-- 会员价与价格 -->
|
||||
<text class="price">
|
||||
{{
|
||||
shopInfo.isVip == 1 && shopInfo.isMemberPrice == 1
|
||||
? item.memberPrice || item.salePrice
|
||||
: item.salePrice
|
||||
}}
|
||||
</text>
|
||||
<view class="price">
|
||||
<GoodsPrice
|
||||
:limitDiscount="limitTimeDiscountRes"
|
||||
:cart="item"
|
||||
:shopUserInfo="shopUserInfo"
|
||||
:shopInfo="shopInfo"
|
||||
></GoodsPrice>
|
||||
</view>
|
||||
|
||||
<text class="unit" v-if="item.unitName"
|
||||
>/{{ item.unitName }}</text
|
||||
>
|
||||
<text class="old-price"
|
||||
>¥{{ item.salePrice }}</text
|
||||
>
|
||||
<!-- <text v-if="item.suitNum>1 && item.type!= 'sku'"
|
||||
style="font-size: 16rpx;">「{{item.suitNum}}{{item.unitName}}起点」</text> -->
|
||||
</view>
|
||||
@@ -357,12 +369,16 @@
|
||||
mode=""
|
||||
></image>
|
||||
</view>
|
||||
|
||||
<view
|
||||
v-if="index == '0'"
|
||||
class="topSort"
|
||||
:class="'c' + (index1 + 1)"
|
||||
>TOP{{ index1 + 1 }}</view
|
||||
>
|
||||
<view class="limitDiscount" v-else-if="showLimitDiscount(item1)"
|
||||
>限时折扣</view
|
||||
>
|
||||
<view class="goods_right" style="overflow: hidden">
|
||||
<view class="name">{{ item1.name }}</view>
|
||||
<!-- <view class="lookBack" v-if="index=='0'">本店销量第{{index1+1}}名</view>-->
|
||||
@@ -417,16 +433,21 @@
|
||||
<view v-else class="flex-between" style="flex-wrap: inherit">
|
||||
<view class="money">
|
||||
<view>¥</view>
|
||||
<text class="money_num">
|
||||
{{
|
||||
shopInfo.isVip == 1 && shopInfo.isMemberPrice == 1
|
||||
? item1.memberPrice || item1.salePrice
|
||||
: item1.salePrice
|
||||
}}
|
||||
</text>
|
||||
<view class="money_num">
|
||||
<GoodsPrice
|
||||
:limitDiscount="limitTimeDiscountRes"
|
||||
:cart="item1"
|
||||
:shopUserInfo="shopUserInfo"
|
||||
:shopInfo="shopInfo"
|
||||
></GoodsPrice>
|
||||
</view>
|
||||
<text class="money_num" v-if="item1.unitName"
|
||||
>/{{ item1.unitName }}</text
|
||||
>
|
||||
<text class="old-price"
|
||||
>¥{{ item1.salePrice }}</text
|
||||
>
|
||||
|
||||
<!-- <text v-if="item1.suitNum>1 && item1.type!= 'sku'"
|
||||
style="font-size: 14rpx;">
|
||||
「{{item1.suitNum}}{{item1.unitName}}起点」
|
||||
@@ -513,6 +534,7 @@
|
||||
:cartLists_count="cartLists_count"
|
||||
:cartList="matchedProducts"
|
||||
:showCart="showCart"
|
||||
:limitDiscount="limitTimeDiscountRes"
|
||||
@customevent="websocketsendMessage"
|
||||
@close="showCart = !showCart"
|
||||
:orderinfo="orderinfo"
|
||||
@@ -772,11 +794,23 @@
|
||||
</view>
|
||||
<Loading :isLoading="!useSocket.isConnected" />
|
||||
<ModalList></ModalList>
|
||||
<recommendGoodsModal
|
||||
v-if="isDataLoaded"
|
||||
@onBuyClick="onBuyClick"
|
||||
></recommendGoodsModal>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
//价格计算辅助函数
|
||||
import * as orderUtils from "@/utils/order-utils.js";
|
||||
import BigNumber from "bignumber.js";
|
||||
|
||||
import GoodsPrice from "@/components/goods-price.vue";
|
||||
|
||||
import * as limitTimeDiscountapi from "@/common/api/market/limitTimeDiscount.js";
|
||||
import ModalList from "@/components/modal-list.vue";
|
||||
import recommendGoodsModal from "./components/recommend-goods-modal.vue";
|
||||
import {
|
||||
ref,
|
||||
reactive,
|
||||
@@ -784,6 +818,7 @@ import {
|
||||
watchEffect,
|
||||
getCurrentInstance,
|
||||
computed,
|
||||
provide,
|
||||
watch,
|
||||
} from "vue";
|
||||
|
||||
@@ -805,6 +840,49 @@ import dayjs from "dayjs";
|
||||
import isBetween from "dayjs/plugin/isBetween";
|
||||
dayjs.extend(isBetween);
|
||||
|
||||
//点单智能推荐
|
||||
function onBuyClick(item) {
|
||||
console.log("onBuyClick", item);
|
||||
console.log("shopProductList", shopProductList);
|
||||
let index = -1;
|
||||
let index1 = -1;
|
||||
if (!item.isHot) {
|
||||
if (
|
||||
item.type == "sku" ||
|
||||
(item.type == "package" && item.groupType == "1")
|
||||
) {
|
||||
for (let i in shopProductList.productInfo) {
|
||||
const cate = shopProductList.productInfo[i];
|
||||
const goodsList = cate.productList;
|
||||
const index1 = goodsList.findIndex((goods) => goods.id == item.id);
|
||||
if (index1 > -1) {
|
||||
index = i;
|
||||
clickspecifications(item, index, index1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
uni.$u.throttle(() => singleclick(item, "+"), 500);
|
||||
}
|
||||
} else {
|
||||
if (
|
||||
item.type == "sku" ||
|
||||
(item.type == "package" && item.groupType == "1")
|
||||
) {
|
||||
for (let i in shopProductList.hots) {
|
||||
const goods = shopProductList.hots[i];
|
||||
if (goods.id==item.id) {
|
||||
index = i;
|
||||
clickspecifications(item, index, index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
uni.$u.throttle(() => singleclick(item, "+"), 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 获取全局属性
|
||||
const { proxy } = getCurrentInstance();
|
||||
|
||||
@@ -852,8 +930,8 @@ store.updateNavbarConfig({
|
||||
isTransparent: false,
|
||||
hasPlaceholder: false, //是否要占位符
|
||||
});
|
||||
|
||||
const shopInfo = uni.cache.get("shopInfo");
|
||||
const shopInfo = reactive({});
|
||||
Object.assign(shopInfo, uni.cache.get("shopInfo"));
|
||||
const shopTable = uni.cache.get("shopTable");
|
||||
const distance = uni.cache.get("distance"); //距离
|
||||
|
||||
@@ -1082,6 +1160,8 @@ const selectSpec = async (specType, option) => {
|
||||
}
|
||||
};
|
||||
|
||||
const shopUserInfo = ref(uni.cache.get("shopUserInfo"));
|
||||
|
||||
// 监听 specifications 的变化
|
||||
watch(
|
||||
() => specifications.item.groupSnap,
|
||||
@@ -1567,8 +1647,21 @@ const updateProductQuantities = () => {
|
||||
|
||||
//websocket产值
|
||||
const websocketsendMessage = (data) => {
|
||||
console.log(data);
|
||||
uni.$u.debounce(useSocket.sendMessage(data), 500);
|
||||
const sendData = { ...data, is_time_discount: 0 };
|
||||
if (cartStore.limitTimeDiscount && cartStore.limitTimeDiscount.id && data.discount_sale_amount*1<=0) {
|
||||
if (
|
||||
orderUtils.canUseLimitTimeDiscount(
|
||||
data,
|
||||
cartStore.limitTimeDiscount,
|
||||
shopInfo,
|
||||
shopUserInfo.value,
|
||||
"product_id"
|
||||
)
|
||||
) {
|
||||
sendData.is_time_discount = 1;
|
||||
}
|
||||
}
|
||||
uni.$u.debounce(useSocket.sendMessage(sendData), 500);
|
||||
};
|
||||
|
||||
// 用于记录已经处理过的消息的 msg_id
|
||||
@@ -1627,6 +1720,7 @@ async function onMessage(Message) {
|
||||
// 初始化
|
||||
if (Message.operate_type == "init") {
|
||||
cartStore.carts = Message.data;
|
||||
cartStore.limitTimeDiscount = Message.time_dis_info;
|
||||
uni.hideLoading();
|
||||
isLoading.value = false;
|
||||
// 初始化商品数量
|
||||
@@ -1697,6 +1791,10 @@ async function onMessage(Message) {
|
||||
},
|
||||
});
|
||||
}
|
||||
if (Message.operate_type == "time_discount_save") {
|
||||
console.log("time_discount_save", Message.data);
|
||||
cartStore.limitTimeDiscount = Message.data;
|
||||
}
|
||||
|
||||
//除去p 每次返回都回执消息
|
||||
await websocketsendMessage({
|
||||
@@ -1835,35 +1933,6 @@ function combineOrderInfoDetailMap(orderinfo) {
|
||||
|
||||
// 计算购物车商品费用
|
||||
const totalPrices = computed(() => {
|
||||
// 待支付订单
|
||||
let cartone = 0;
|
||||
if (orderinfo.value) {
|
||||
let combinedArray = [];
|
||||
for (const key in orderinfo.value.detailMap) {
|
||||
if (orderinfo.value.detailMap.hasOwnProperty(key)) {
|
||||
let subArray = orderinfo.value.detailMap[key];
|
||||
combinedArray = [...combinedArray, ...subArray];
|
||||
}
|
||||
}
|
||||
// 购物车总数价格
|
||||
cartone = combinedArray.reduce((total, item) => {
|
||||
// 是否启用会员价 0否1是
|
||||
if (shopInfo.isVip == 1 && shopInfo.isMemberPrice == 1) {
|
||||
// memberPrice会员价
|
||||
return (
|
||||
total +
|
||||
parseFloat(item.memberPrice || item.price) *
|
||||
parseFloat(item.num - item.returnNum)
|
||||
);
|
||||
} else {
|
||||
// salePrice销售价
|
||||
return (
|
||||
total +
|
||||
parseFloat(item.price || 0) * parseFloat(item.num - item.returnNum)
|
||||
);
|
||||
}
|
||||
}, 0);
|
||||
}
|
||||
// 购物车总数价格
|
||||
let cart = 0;
|
||||
if (matchedProducts.value.length > 0) {
|
||||
@@ -1877,6 +1946,18 @@ const totalPrices = computed(() => {
|
||||
}
|
||||
});
|
||||
}
|
||||
if (limitTimeDiscountRes.value && limitTimeDiscountRes.value.id) {
|
||||
//限时折扣
|
||||
const price = orderUtils.returnPrice({
|
||||
goods: item,
|
||||
shopInfo,
|
||||
limitTimeDiscountRes: limitTimeDiscountRes.value,
|
||||
shopUserInfo: shopUserInfo.value,
|
||||
idKey: "id",
|
||||
});
|
||||
console.log("限时折扣", item, price);
|
||||
return total + parseFloat(price) * parseFloat(item.cartNumber);
|
||||
}
|
||||
// 是否启用会员价 0否1是
|
||||
if (shopInfo.isVip == 1 && shopInfo.isMemberPrice == 1) {
|
||||
// memberPrice会员价
|
||||
@@ -2059,6 +2140,7 @@ const productqueryProduct = async () => {
|
||||
);
|
||||
cartStore.setGoodsMap(i.id, i);
|
||||
});
|
||||
|
||||
cartStore.goodsIsloading = true;
|
||||
scrollTopSize.value = 0;
|
||||
topArr.value = [];
|
||||
@@ -2081,11 +2163,49 @@ const productqueryProduct = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
provide("cartStore", cartStore);
|
||||
provide("shopUserInfo", shopUserInfo);
|
||||
provide("shopInfo", shopInfo);
|
||||
|
||||
onLoad(async (e) => {
|
||||
await proxy.$onLaunched;
|
||||
});
|
||||
|
||||
const limitTimeDiscountRes = ref(null);
|
||||
|
||||
function showLimitDiscount(item) {
|
||||
if (!limitTimeDiscountRes.value) {
|
||||
return false;
|
||||
}
|
||||
return orderUtils.canUseLimitTimeDiscount(
|
||||
item,
|
||||
limitTimeDiscountRes.value,
|
||||
shopInfo,
|
||||
shopUserInfo.value,
|
||||
"id"
|
||||
);
|
||||
}
|
||||
|
||||
onShow(async () => {
|
||||
limitTimeDiscountapi
|
||||
.getConfig({
|
||||
shopId: uni.cache.get("shopId"),
|
||||
})
|
||||
.then((res) => {
|
||||
console.log("limitTimeDiscountapi", res);
|
||||
if (res && typeof res == "object") {
|
||||
limitTimeDiscountRes.value = res;
|
||||
cartStore.limitTimeDiscount = res;
|
||||
websocketsendMessage({
|
||||
type: "shopping",
|
||||
operate_type: "time_discount_save",
|
||||
table_code: uni.cache.get("tableCode"),
|
||||
shop_id: uni.cache.get("shopId"),
|
||||
operate_type: "time_discount_save",
|
||||
data: res,
|
||||
});
|
||||
}
|
||||
});
|
||||
// 监听页面显示和隐藏
|
||||
useSocket.setOnMessage(onMessage);
|
||||
useSocket.onShowconnect();
|
||||
@@ -2304,6 +2424,8 @@ function toHistory() {
|
||||
|
||||
.panelfiveitemsex {
|
||||
.panelfiveitemsex_oen {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
.tips {
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
@@ -2412,7 +2534,8 @@ function toHistory() {
|
||||
position: relative;
|
||||
|
||||
.left {
|
||||
width: 200rpx;
|
||||
// width: 200rpx;
|
||||
width: 156rpx;
|
||||
background-color: #f6f6f6;
|
||||
line-height: normal;
|
||||
box-sizing: border-box;
|
||||
@@ -2554,6 +2677,7 @@ function toHistory() {
|
||||
width: 200rpx;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
border-radius: 18rpx;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 9;
|
||||
@@ -2578,6 +2702,7 @@ function toHistory() {
|
||||
font-size: 24rpx;
|
||||
color: #ffffff;
|
||||
border-radius: 20rpx 0rpx 20rpx 0rpx;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.topSort.c1 {
|
||||
@@ -2632,10 +2757,11 @@ function toHistory() {
|
||||
|
||||
.money {
|
||||
font-weight: bold;
|
||||
font-size: 24rpx;
|
||||
font-size: 20rpx;
|
||||
color: #333;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
align-items: baseline;
|
||||
white-space: nowrap;
|
||||
|
||||
.money_num {
|
||||
font-size: 28rpx;
|
||||
@@ -3073,4 +3199,25 @@ function toHistory() {
|
||||
height: 36rpx;
|
||||
}
|
||||
}
|
||||
.old-price {
|
||||
color: #999;
|
||||
font-size: 24rpx;
|
||||
text-decoration: line-through;
|
||||
margin-left: 8rpx;
|
||||
}
|
||||
.limitDiscount {
|
||||
background-color: #cc5617;
|
||||
padding: 2rpx 10rpx;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
color: #ffffff;
|
||||
border-radius: 20rpx 0rpx 20rpx 0rpx;
|
||||
z-index: 9;
|
||||
color: #fff;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<view class="header-wrap">
|
||||
<view class="u-flex" style="justify-content: flex-end;">
|
||||
<view @click="toExchangeCode" class="color-333 font-12 u-m-b-26 font-700">优惠券兑换码</view>
|
||||
</view>
|
||||
<view class="search-wrap">
|
||||
<view class="input-wrap">
|
||||
<view class="icon left">
|
||||
@@ -137,7 +140,11 @@ onReachBottom(() => {
|
||||
getCouponList();
|
||||
}
|
||||
});
|
||||
|
||||
function toExchangeCode(){
|
||||
uni.navigateTo({
|
||||
url: '/user/exchange/index'
|
||||
})
|
||||
}
|
||||
const showDetail = ref(false);
|
||||
const selectListItem = ref('');
|
||||
const selectListItemDetails = ref([]);
|
||||
|
||||
@@ -63,7 +63,9 @@
|
||||
<text v-if="item.bizCode == 'freeIn'">
|
||||
霸王餐充值
|
||||
</text>
|
||||
|
||||
<text v-if="item.bizCode == 'rechargeRedemption'">
|
||||
兑换券充值
|
||||
</text>
|
||||
</view>
|
||||
<view v-else>
|
||||
{{item.content}}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
<text class="n t">{{ shopUserInfo.amount || 0 }}</text>
|
||||
</view>
|
||||
<view class="right">
|
||||
<text class="t" @click="toduihuan">兑换码</text>
|
||||
<text class="t" @click="toDetail">明细</text>
|
||||
<text class="t" @click="toPwd">密码设置</text>
|
||||
</view>
|
||||
@@ -161,7 +162,7 @@ import * as rechargeApi from "@/common/api/market/recharge.js";
|
||||
import { recharge } from "@/common/api/order/index.js";
|
||||
import { joinMember } from "@/common/api/order/index.js";
|
||||
import { ref, onMounted, computed, reactive, watch } from "vue";
|
||||
import { onLoad } from "@dcloudio/uni-app";
|
||||
import { onLoad, onShow } from "@dcloudio/uni-app";
|
||||
import { pay } from "@/utils/pay.js";
|
||||
|
||||
function toShopList() {
|
||||
@@ -170,6 +171,12 @@ function toShopList() {
|
||||
});
|
||||
}
|
||||
|
||||
function toduihuan() {
|
||||
uni.navigateTo({
|
||||
url: "/user/exchange/index",
|
||||
});
|
||||
}
|
||||
|
||||
function couponNum(list) {
|
||||
return list.reduce((prve, cur) => {
|
||||
return prve + cur.num;
|
||||
@@ -285,7 +292,7 @@ const charge_money = computed(() => {
|
||||
});
|
||||
onLoad((opt) => {
|
||||
Object.assign(option, opt);
|
||||
init();
|
||||
// init();
|
||||
});
|
||||
|
||||
watch(
|
||||
@@ -296,6 +303,9 @@ watch(
|
||||
}
|
||||
}
|
||||
);
|
||||
onShow(() => {
|
||||
init();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@@ -367,7 +377,7 @@ watch(
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
position: relative;
|
||||
padding-top: 40upx;
|
||||
padding-top: 20rpx;
|
||||
|
||||
.left {
|
||||
display: flex;
|
||||
|
||||
@@ -224,7 +224,7 @@
|
||||
<!-- <l-qrcode :value="wechatAcQrcode" @complete="e=>qrcodeResult(e)"/> -->
|
||||
<view
|
||||
class="qrcode u-flex u-col-center justify-between"
|
||||
v-if="qrcode"
|
||||
v-if="showQrcode"
|
||||
>
|
||||
<view>
|
||||
<view class="color-000 font-14 font-bold">扫码关注公众号</view>
|
||||
@@ -259,10 +259,8 @@ import * as rechargeApi from "@/common/api/market/recharge.js";
|
||||
import { pointsShopList } from "@/common/api/account/points.js";
|
||||
|
||||
|
||||
const qrcode = ref("");
|
||||
|
||||
function qrcodeResult(res) {
|
||||
console.log("qrcodeResult", res);
|
||||
qrcode.value = res
|
||||
}
|
||||
|
||||
@@ -470,7 +468,14 @@ onShow(() => {
|
||||
getData();
|
||||
});
|
||||
|
||||
const qrcode = ref("");
|
||||
const showQrcode = computed(() => {
|
||||
|
||||
const followIndex = uni.cache.get("followIndex");
|
||||
if ( followIndex == "mine" && qrcode.value) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
BIN
static/icon/newUserDiscount.png
Normal file
BIN
static/icon/newUserDiscount.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 502 B |
@@ -157,6 +157,8 @@ export const useCartsStore = defineStore("cart", () => {
|
||||
const isFreeDine = ref(false);
|
||||
// 商家霸王餐配置
|
||||
const freeDineConfig = ref(null);
|
||||
//限时折扣
|
||||
const limitTimeDiscount = ref(null);
|
||||
// 订单额外配置
|
||||
const orderExtraConfig = computed(() => ({
|
||||
// 引用扩展后的商家减免配置
|
||||
@@ -173,6 +175,7 @@ export const useCartsStore = defineStore("cart", () => {
|
||||
currentDinnerType: dinnerType.value,
|
||||
isFreeDine: isFreeDine.value,
|
||||
freeDineConfig: freeDineConfig.value,
|
||||
limitTimeDiscount: limitTimeDiscount.value,
|
||||
}));
|
||||
|
||||
// 营销活动列表
|
||||
@@ -191,6 +194,7 @@ export const useCartsStore = defineStore("cart", () => {
|
||||
// 订单费用汇总
|
||||
const orderCostSummary = computed(() => {
|
||||
allGoods.value = getAllGoodsList();
|
||||
console.log("allGoods.value", allGoods.value);
|
||||
console.log("orderExtraConfig.value", orderExtraConfig.value);
|
||||
const costSummary = OrderPriceCalculator.calculateOrderCostSummary(
|
||||
allGoods.value,
|
||||
@@ -209,6 +213,11 @@ export const useCartsStore = defineStore("cart", () => {
|
||||
|
||||
//商品数据Map
|
||||
const goodsMap = reactive({});
|
||||
|
||||
function returnGoods(product_id){
|
||||
return goodsMap[product_id*1]
|
||||
}
|
||||
|
||||
//获取商品数据
|
||||
async function goodsInit() {
|
||||
goodsIsloading.value = true;
|
||||
@@ -232,10 +241,6 @@ export const useCartsStore = defineStore("cart", () => {
|
||||
goodsMap[product_id] = data;
|
||||
}
|
||||
|
||||
//websocket回执
|
||||
const websocketsendMessage = (data) => {
|
||||
uni.$u.debounce(sendMessage(data), 500);
|
||||
};
|
||||
|
||||
const isLoading = ref(true);
|
||||
|
||||
@@ -348,6 +353,11 @@ export const useCartsStore = defineStore("cart", () => {
|
||||
icon: "none",
|
||||
});
|
||||
}
|
||||
//获取限时折扣
|
||||
// if(Message.operate_type == "time_discount_get"){
|
||||
// console.log("time_discount_get", Message.data);
|
||||
// limitTimeDiscount.value = Message.data;
|
||||
// }
|
||||
|
||||
if (Message.type == "no_suit_num") {
|
||||
uni.showModal({
|
||||
@@ -394,6 +404,9 @@ export const useCartsStore = defineStore("cart", () => {
|
||||
|
||||
//是否使用会员价
|
||||
const useVipPrice = computed(() => {
|
||||
if (!orderVIP.value) {
|
||||
return false;
|
||||
}
|
||||
const isUse =
|
||||
orderVIP.value.isVip && shopInfo.value.isMemberPrice ? true : false;
|
||||
return isUse;
|
||||
@@ -606,6 +619,10 @@ export const useCartsStore = defineStore("cart", () => {
|
||||
userPoints.value = 0;
|
||||
fullReductionActivities.value = [];
|
||||
isFreeDine.value = false;
|
||||
oldOrder.value = {
|
||||
detailMap: {},
|
||||
originAmount: 0,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -616,7 +633,7 @@ export const useCartsStore = defineStore("cart", () => {
|
||||
carts,
|
||||
isEmpty,
|
||||
setGoodsMap,
|
||||
goodsMap,
|
||||
goodsMap:goodsMap,
|
||||
goodsIsloading,
|
||||
goodsInit,
|
||||
onMessage,
|
||||
@@ -631,6 +648,8 @@ export const useCartsStore = defineStore("cart", () => {
|
||||
setUserPoints,
|
||||
setPointDeductionRule,
|
||||
setOldOrder,
|
||||
//返回商品信息
|
||||
returnGoods,
|
||||
//优惠券列表
|
||||
backendCoupons,
|
||||
allGoods,
|
||||
@@ -652,5 +671,7 @@ export const useCartsStore = defineStore("cart", () => {
|
||||
isFreeDine, //是否使用霸王餐
|
||||
// 商家霸王餐配置
|
||||
freeDineConfig,
|
||||
//限时折扣
|
||||
limitTimeDiscount,
|
||||
};
|
||||
});
|
||||
|
||||
@@ -228,8 +228,10 @@ export const Memberpay = defineStore('memberpay', {
|
||||
|
||||
// 生成订单
|
||||
actionscreateOrder(data) {
|
||||
console.log('actionscreateOrder:生成订单',data);
|
||||
return new Promise(async (resolve, reject) => {
|
||||
let res = await APIcreateOrder({
|
||||
...data,
|
||||
orderId: data.orderId, //多次下单时使用
|
||||
shopId: uni.cache.get('shopId'), //店铺Id
|
||||
userId: uni.cache.get('userInfo').id || '', //
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<template>
|
||||
<view @longtap.stop="longtap">
|
||||
<canvas
|
||||
class="canvas"
|
||||
:width="info.destWidth"
|
||||
:height="info.destHeight"
|
||||
:canvas-id="item.id"
|
||||
@@ -173,4 +174,9 @@
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<!-- #endif -->
|
||||
<!-- #endif -->
|
||||
<style scoped>
|
||||
.canvas{
|
||||
opacity: 0;
|
||||
}
|
||||
</style>
|
||||
@@ -11,21 +11,21 @@
|
||||
<view class="box">
|
||||
<view class="u-flex top justify-between u-p-32">
|
||||
<text class="title">确认信息</text>
|
||||
<up-icon name="close"></up-icon>
|
||||
<up-icon name="close" @click="close"></up-icon>
|
||||
</view>
|
||||
<view class="info">
|
||||
<view class="color-333">兑换码包含内容如下:</view>
|
||||
<view class="u-m-t-32 u-flex u-col-center">
|
||||
<view class="color-333 font-bold small-title">店铺</view>
|
||||
<text class="color-666 u-m-l-38">店铺名称</text>
|
||||
<text class="color-666 u-m-l-38">{{data.shopName}}</text>
|
||||
</view>
|
||||
<view class="u-m-t-32 u-flex u-col-center">
|
||||
<view class="color-333 font-bold small-title">名称</view>
|
||||
<text class="color-666 u-m-l-38">10张券兑换码</text>
|
||||
<text class="color-666 u-m-l-38">{{data.name}}</text>
|
||||
</view>
|
||||
<view class="u-m-t-32 u-flex u-col-center">
|
||||
<view class="u-m-t-32 u-flex u-col-center" v-if="data.couponInfoList&&data.couponInfoList.length">
|
||||
<view class="color-333 font-bold small-title">优惠券</view>
|
||||
<text class="color-666 u-m-l-38">优惠券名称*2、优惠券名称*1</text>
|
||||
<text class="color-666 u-m-l-38">{{data.couponInfoList.map(item=>item.title+'*'+item.num).join('、')}}</text>
|
||||
</view>
|
||||
<view class="u-m-t-32 u-flex u-col-center" style="gap: 54rpx">
|
||||
<view class="cancel" @click="close">取消</view>
|
||||
@@ -39,6 +39,13 @@
|
||||
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
const props=defineProps({
|
||||
//兑换码信息
|
||||
data:{
|
||||
type:Object,
|
||||
default:()=>({}),
|
||||
},
|
||||
})
|
||||
const show = defineModel({
|
||||
type: Boolean,
|
||||
default: false,
|
||||
|
||||
@@ -14,46 +14,92 @@
|
||||
<view class="input-box u-flex">
|
||||
<image class="icon" src="/user/static/duihuan.png"></image>
|
||||
<view class="u-flex-1">
|
||||
<input placeholder="请输入兑换码" />
|
||||
<input placeholder="请输入兑换码" v-model="code" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="u-flex justify-center u-m-t-24">
|
||||
<button class="duihuan">确认兑换</button>
|
||||
<button class="duihuan" @click="confirmExchange">确认兑换</button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="desc">
|
||||
<view>兑换说明:</view>
|
||||
<view>
|
||||
兑换说明: 1、请直接输入您获得的兑换码,点击立即兑换即可
|
||||
1、请直接输入您获得的兑换码,点击立即兑换即可
|
||||
<br />
|
||||
2、兑换码为一次性,兑换完成之后即失效
|
||||
<br />
|
||||
3、兑换获得的奖励,将直接发送至您的账号,可直接前往余额或优惠券查看
|
||||
<br />
|
||||
4、兑换码为赠品,不可转赠、不退不换
|
||||
<br />
|
||||
5、兑换码需在有效期内完成兑换,过期即作废
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<confirmModal v-model="modal.confirm.show"></confirmModal>
|
||||
<resultModal v-model="modal.result.show" :title="modal.result.title"></resultModal>
|
||||
<confirmModal v-model="modal.confirm.show" :data="modal.confirm.data" @confirm="exchange"></confirmModal>
|
||||
<resultModal
|
||||
v-model="modal.result.show"
|
||||
:title="modal.result.title"
|
||||
></resultModal>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { result } from "lodash";
|
||||
import confirmModal from "./components/confirm.vue";
|
||||
import resultModal from "./components/result.vue";
|
||||
import { reactive } from "vue";
|
||||
import * as exchangeApi from "@/common/api/market/exchange.js";
|
||||
import { reactive, ref } from "vue";
|
||||
const modal = reactive({
|
||||
confirm: {
|
||||
show: false,
|
||||
},
|
||||
result:{
|
||||
show:true,
|
||||
title:'该兑换码无效,请输入有效兑换码'
|
||||
}
|
||||
result: {
|
||||
show: false,
|
||||
title: "该兑换码无效,请输入有效兑换码",
|
||||
},
|
||||
});
|
||||
|
||||
const code = ref("");
|
||||
function confirmExchange() {
|
||||
if (code.value == "") {
|
||||
uni.showToast({
|
||||
title: "请输入兑换码",
|
||||
icon: "none",
|
||||
});
|
||||
return;
|
||||
}
|
||||
exchangeApi.redemption({
|
||||
code: code.value,
|
||||
}).then((res) => {
|
||||
if (res) {
|
||||
modal.confirm.show = true;
|
||||
modal.confirm.data = res;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function exchange() {
|
||||
exchangeApi
|
||||
.exchange({
|
||||
code: code.value,
|
||||
})
|
||||
.then((res) => {
|
||||
if (res) {
|
||||
modal.result.title = "兑换成功!奖励已发放至您的账户";
|
||||
modal.result.show = true;
|
||||
code.value = "";
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log("err,", err);
|
||||
modal.result.title = err.message || "该兑换码无效,请输入有效兑换码";
|
||||
modal.result.show = true;
|
||||
});
|
||||
}
|
||||
|
||||
function back() {
|
||||
uni.navigateBack();
|
||||
}
|
||||
@@ -115,7 +161,6 @@ function back() {
|
||||
font-weight: 700;
|
||||
}
|
||||
.desc {
|
||||
width: 662rpx;
|
||||
color: #666666;
|
||||
font-size: 24rpx;
|
||||
font-weight: 400;
|
||||
|
||||
@@ -270,10 +270,10 @@
|
||||
return v;
|
||||
});
|
||||
tiaojian_menus = tiaojian_menus.filter(v => {
|
||||
if (!state.isCostRewardPoints && v.name == '消费送积分') {
|
||||
if (!res.memberLevel.isCostRewardPoints && v.name == '消费送积分') {
|
||||
return false
|
||||
}
|
||||
if (!state.isCycleReward && v.name == '周期福利') {
|
||||
if (!res.memberLevel.isCycleReward && v.name == '周期福利') {
|
||||
return false
|
||||
}
|
||||
if (!res.memberLevel.cycleRewardCouponList || res.memberLevel.cycleRewardCouponList.length <=
|
||||
|
||||
1507
utils/goods copy.ts
Normal file
1507
utils/goods copy.ts
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,27 +1,55 @@
|
||||
import {
|
||||
BigNumber
|
||||
} from "bignumber.js";
|
||||
import { BigNumber } from "bignumber.js";
|
||||
import _ from "lodash";
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 返回商品单价
|
||||
* @param goods 商品
|
||||
* @param user 用户信息
|
||||
* @param {Object} shopInfo
|
||||
* @param {Object} shopInfo 店铺信息
|
||||
* @param {boolean} limitTimeDiscount - 限时折扣
|
||||
*/
|
||||
export function returnGoodsPrice(goods, user, shopInfo) {
|
||||
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) {
|
||||
return goods.memberPrice;
|
||||
}
|
||||
return goods.salePrice;
|
||||
export function returnGoodsPrice(goods, user, shopInfo, limitTimeDiscount) {
|
||||
if (!goods) {
|
||||
return 0;
|
||||
}
|
||||
// 商家改价
|
||||
if (goods.discount_sale_amount * 1 > 0) {
|
||||
return goods.discount_sale_amount;
|
||||
}
|
||||
// 限时折扣
|
||||
if (limitTimeDiscount && limitTimeDiscount.id) {
|
||||
if (
|
||||
limitTimeDiscount.foodType == 1 &&
|
||||
limitTimeDiscount.discountPriority == "limit-time"
|
||||
) {
|
||||
return new BigNumber(goods.salePrice)
|
||||
.times(limitTimeDiscount.discountRate / 100)
|
||||
.decimalPlaces(2, BigNumber.ROUND_UP)
|
||||
.toNumber();
|
||||
}
|
||||
const canUseFoods = limitTimeDiscount.foods.split(",");
|
||||
if (
|
||||
limitTimeDiscount.foodType == 2 &&
|
||||
limitTimeDiscount.discountPriority == "limit-time" &&
|
||||
canUseFoods.includes(`${goods.productId}`)
|
||||
) {
|
||||
return new BigNumber(goods.salePrice)
|
||||
.times(limitTimeDiscount.discountRate / 100)
|
||||
.decimalPlaces(2, BigNumber.ROUND_UP)
|
||||
.toNumber();
|
||||
}
|
||||
}
|
||||
if (shopInfo && !shopInfo.isMemberPrice) {
|
||||
return goods.salePrice;
|
||||
}
|
||||
if (
|
||||
user.isVip &&
|
||||
goods.memberPrice * 1 <= goods.salePrice * 1 &&
|
||||
goods.memberPrice * 1 > 0
|
||||
) {
|
||||
return goods.memberPrice;
|
||||
}
|
||||
return goods.salePrice;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -29,15 +57,15 @@ export function returnGoodsPrice(goods, user, shopInfo) {
|
||||
* @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;
|
||||
let map = {};
|
||||
arr.forEach((v) => {
|
||||
const key = v.productId + "_" + v.skuId;
|
||||
if (!map[key]) {
|
||||
map[key] = [];
|
||||
}
|
||||
map[key].push(v);
|
||||
});
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -45,17 +73,17 @@ export function returnGoodsGroupMap(arr) {
|
||||
* @param coupon
|
||||
*/
|
||||
export function returnCoupType(coupon) {
|
||||
const couponTypes = {
|
||||
1: "满减券",
|
||||
2: "商品券",
|
||||
3: "折扣券",
|
||||
4: "第二件半价券",
|
||||
5: "消费送券",
|
||||
6: "买一送一券",
|
||||
7: "固定价格券",
|
||||
8: "免配送费券",
|
||||
};
|
||||
return couponTypes[coupon.type] || "未知类型";
|
||||
const couponTypes = {
|
||||
1: "满减券",
|
||||
2: "商品券",
|
||||
3: "折扣券",
|
||||
4: "第二件半价券",
|
||||
5: "消费送券",
|
||||
6: "买一送一券",
|
||||
7: "固定价格券",
|
||||
8: "免配送费券",
|
||||
};
|
||||
return couponTypes[coupon.type] || "未知类型";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,22 +93,37 @@ export function returnCoupType(coupon) {
|
||||
* @param user 用户信息
|
||||
*/
|
||||
export function returnCanDikouGoodsArr(canDikouGoodsArr, selCoupon, user) {
|
||||
const goodsCouponGoods = selCoupon
|
||||
.filter((v) => v.type == 2)
|
||||
.reduce((prve, cur) => {
|
||||
prve.push(...cur.discount.hasDiscountGoodsArr);
|
||||
return prve;
|
||||
}, []);
|
||||
const arr = _.cloneDeep(canDikouGoodsArr)
|
||||
.map((v) => {
|
||||
const findCart = goodsCouponGoods.find((carts) => carts.id == v.id);
|
||||
if (findCart) {
|
||||
v.num -= findCart.num;
|
||||
}
|
||||
return v;
|
||||
})
|
||||
.filter((v) => v.num > 0);
|
||||
return arr;
|
||||
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) => v.num > 0); // 过滤掉数量<=0的商品
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,139 +140,208 @@ 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 {
|
||||
canUse: false,
|
||||
reason: coupon.noUseRestrictions || "不在可用时间段内",
|
||||
};
|
||||
}
|
||||
if(limitTimeDiscount&&limitTimeDiscount.id&&!coupon.discountShare){
|
||||
return {
|
||||
canUse: false,
|
||||
reason: coupon.noUseRestrictions || "不可与限时折扣同享",
|
||||
};
|
||||
}
|
||||
|
||||
// 优惠券未启用
|
||||
if (!coupon.use) {
|
||||
return {
|
||||
canUse: false,
|
||||
reason: "优惠券未启用"
|
||||
};
|
||||
}
|
||||
// 计算门槛金额
|
||||
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);
|
||||
});
|
||||
fullAmount = canCalcGoodsArr.reduce((pre, cur) => {
|
||||
return (
|
||||
pre + returnGoodsPrice(cur, user, shopInfo, limitTimeDiscount) * cur.num
|
||||
);
|
||||
}, 0);
|
||||
}
|
||||
|
||||
canDikouGoodsArr = returnCanDikouGoodsArr(canDikouGoodsArr, selCoupon, user,shopInfo);
|
||||
// 计算门槛金额
|
||||
let fullAmount = goodsOrderPrice;
|
||||
// 是否抵扣全部商品
|
||||
const isDikouAll = coupon.useFoods.length === 0;
|
||||
let canCalcGoodsArr = [];
|
||||
// 订单里参与门槛计算的商品
|
||||
if (!isDikouAll) {
|
||||
canCalcGoodsArr = canDikouGoodsArr.filter((v) => {
|
||||
return coupon.useFoods.find((food) => food.id == v.productId);
|
||||
});
|
||||
fullAmount = canCalcGoodsArr.reduce((pre, cur) => {
|
||||
return pre + returnGoodsPrice(cur, user,shopInfo) * 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 (coupon.type == 2 && fullAmount < coupon.fullAmount) {
|
||||
return {
|
||||
canUse: false,
|
||||
reason: `满${coupon.fullAmount}元可用,当前可参与金额${fullAmount}元`,
|
||||
};
|
||||
}
|
||||
|
||||
// 没有符合条件的商品
|
||||
if (!isDikouAll && canCalcGoodsArr.length === 0) {
|
||||
return {
|
||||
canUse: false,
|
||||
reason: "没有符合条件的商品"
|
||||
};
|
||||
}
|
||||
// 没有符合条件的商品
|
||||
if (isDikouAll && canDikouGoodsArr.length === 0) {
|
||||
return {
|
||||
canUse: false,
|
||||
reason: "没有符合条件的商品",
|
||||
};
|
||||
}
|
||||
if (!isDikouAll && canUseGoodsArr.length === 0) {
|
||||
return {
|
||||
canUse: false,
|
||||
reason: "没有符合条件的商品",
|
||||
};
|
||||
}
|
||||
}
|
||||
//商品兑换券是否达到门槛金额
|
||||
if (coupon.type == 2 && goodsOrderPrice < coupon.fullAmount) {
|
||||
return {
|
||||
canUse: false,
|
||||
reason: `满${coupon.fullAmount}元可用,当前可参与金额${fullAmount}元`,
|
||||
};
|
||||
}
|
||||
|
||||
// 不满足门槛金额
|
||||
if (fullAmount < 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 (coupon.type === 2) {
|
||||
if (!(isDikouAll || canCalcGoodsArr.length > 0)) {
|
||||
return {
|
||||
canUse: false,
|
||||
reason: "没有符合条件的商品可抵扣"
|
||||
};
|
||||
}
|
||||
}
|
||||
if (!canUse) {
|
||||
return {
|
||||
canUse: false,
|
||||
reason: "需要购买至少2件相同的商品才能使用",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// 买一送一券特殊验证
|
||||
if (coupon.type === 6) {
|
||||
let canUse = false;
|
||||
if (isDikouAll) {
|
||||
canUse = canDikouGoodsArr.some((v) => v.num >= 2);
|
||||
} else if (canCalcGoodsArr.length > 0) {
|
||||
canUse = canCalcGoodsArr.some((v) => v.num >= 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件相同的商品才能使用",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
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 (canCalcGoodsArr.length > 0) {
|
||||
canUse = canCalcGoodsArr.some((v) => v.num >= 2);
|
||||
}
|
||||
|
||||
if (!canUse) {
|
||||
return {
|
||||
canUse: false,
|
||||
reason: "需要购买至少2件相同的商品才能使用"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// 所有条件都满足
|
||||
return {
|
||||
canUse: true,
|
||||
reason: ""
|
||||
};
|
||||
// 所有条件都满足
|
||||
return {
|
||||
canUse: true,
|
||||
reason: "",
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 计算抵扣商品金额
|
||||
* @param discountGoodsArr 可抵扣商品列表
|
||||
* @param discountNum 抵扣数量
|
||||
* @param user 用户信息
|
||||
* @param {Object} shopInfo 店铺信息
|
||||
* @param {Object} shopInfo 店铺信息
|
||||
* @param limitTimeDiscount 限时折扣
|
||||
*/
|
||||
export function calcDiscountGoodsArrPrice(discountGoodsArr, discountNum, user,shopInfo) {
|
||||
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);
|
||||
discountPrice += returnGoodsPrice(goods, user,shopInfo) * num;
|
||||
hasCountNum += num;
|
||||
hasDiscountGoodsArr.push({
|
||||
...goods,
|
||||
num
|
||||
});
|
||||
}
|
||||
return {
|
||||
discountPrice,
|
||||
hasDiscountGoodsArr
|
||||
};
|
||||
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);
|
||||
discountPrice += returnGoodsPrice(goods, user, shopInfo,limitTimeDiscount) * num;
|
||||
|
||||
hasCountNum += num;
|
||||
hasDiscountGoodsArr.push({
|
||||
...goods,
|
||||
num,
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
discountPrice,
|
||||
hasDiscountGoodsArr,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -239,23 +351,51 @@ export function calcDiscountGoodsArrPrice(discountGoodsArr, discountNum, user,sh
|
||||
* @param user 用户信息
|
||||
* @param goodsOrderPrice 商品订单金额
|
||||
* @param selCoupon 已选择的优惠券列表
|
||||
* @param shopInfo 店铺信息
|
||||
* @param limitTimeDiscount 限时折扣
|
||||
*/
|
||||
export function returnCouponDiscount(arr, coupon, user, goodsOrderPrice, selCoupon) {
|
||||
console.log('arr', arr);
|
||||
const canDikouGoodsArr = returnCanDikouGoodsArr(arr, selCoupon, user);
|
||||
console.log('canDikouGoodsArr', canDikouGoodsArr);
|
||||
if (coupon.type == 2) {
|
||||
return returnCouponProductDiscount(canDikouGoodsArr, coupon, user, goodsOrderPrice);
|
||||
}
|
||||
if (coupon.type == 6) {
|
||||
return returnCouponBuyOneGiveOneDiscount(canDikouGoodsArr, coupon, user, goodsOrderPrice);
|
||||
}
|
||||
if (coupon.type == 4) {
|
||||
return returnSecoendDiscount(canDikouGoodsArr, coupon, user, goodsOrderPrice);
|
||||
}
|
||||
if (coupon.type == 3) {
|
||||
return returnCouponZhekouDiscount(canDikouGoodsArr, coupon, user, goodsOrderPrice, selCoupon);
|
||||
}
|
||||
export function returnCouponDiscount(
|
||||
arr,
|
||||
coupon,
|
||||
user,
|
||||
goodsOrderPrice,
|
||||
selCoupon,
|
||||
shopInfo,limitTimeDiscount
|
||||
) {
|
||||
arr = returnCanDikouGoods(arr, user, shopInfo);
|
||||
const canDikouGoodsArr = returnCanDikouGoodsArr(arr, selCoupon, user);
|
||||
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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -265,41 +405,53 @@ export function returnCouponDiscount(arr, coupon, user, goodsOrderPrice, selCoup
|
||||
* @param user 用户信息
|
||||
* @param goodsOrderPrice 商品订单金额
|
||||
* @param selCoupon 已选择的优惠券列表
|
||||
* @param limitTimeDiscount 限时折扣
|
||||
*
|
||||
*/
|
||||
export function returnCouponZhekouDiscount(
|
||||
canDikouGoodsArr,
|
||||
coupon,
|
||||
user,
|
||||
goodsOrderPrice,
|
||||
selCoupon
|
||||
canDikouGoodsArr,
|
||||
coupon,
|
||||
user,
|
||||
goodsOrderPrice,
|
||||
selCoupon,limitTimeDiscount
|
||||
) {
|
||||
const {
|
||||
discountRate,
|
||||
maxDiscountAmount
|
||||
} = coupon;
|
||||
const { discountRate, maxDiscountAmount } = coupon;
|
||||
|
||||
const goodsCouponDiscount = selCoupon
|
||||
.filter((v) => v.type == 2)
|
||||
.reduce((prve, cur) => {
|
||||
return prve + cur.discount.discountPrice;
|
||||
}, 0);
|
||||
goodsOrderPrice -= goodsCouponDiscount;
|
||||
// 使用bignumber处理高精度计算
|
||||
// 1. 计算折扣率(百分比转小数):discountRate / 100
|
||||
const discountRatio = new BigNumber(discountRate).dividedBy(100);
|
||||
// 2. 计算优惠比例:1 - 折扣率(例如:8折的优惠比例是 1 - 0.8 = 0.2)
|
||||
const discountAmountRatio = new BigNumber(1).minus(discountRatio);
|
||||
// 3. 计算折扣金额:商品订单金额 × 优惠比例
|
||||
let discountPrice = new BigNumber(goodsOrderPrice).times(discountAmountRatio).toNumber();
|
||||
if (maxDiscountAmount != 0) {
|
||||
discountPrice = discountPrice >= maxDiscountAmount ? maxDiscountAmount : discountPrice;
|
||||
}
|
||||
// 计算商品优惠券折扣总和,使用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));
|
||||
|
||||
return {
|
||||
discountPrice, // 折扣抵扣金额(即优惠的金额)
|
||||
hasDiscountGoodsArr: [],
|
||||
};
|
||||
// 将商品订单价格转换为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: [],
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -307,39 +459,45 @@ export function returnCouponZhekouDiscount(
|
||||
* @param canDikouGoodsArr 可抵扣商品列表
|
||||
* @param coupon 优惠券
|
||||
* @param user 用户信息
|
||||
* @param shopInfo 店铺信息
|
||||
* @param limitTimeDiscount 限时折扣
|
||||
*/
|
||||
export function returnCouponProductDiscount(canDikouGoodsArr, coupon, user) {
|
||||
const {
|
||||
useFoods,
|
||||
discountNum,
|
||||
useRule
|
||||
} = coupon;
|
||||
//抵扣商品数组
|
||||
let discountGoodsArr = [];
|
||||
//抵扣全部商品
|
||||
if (useFoods.length === 0) {
|
||||
if (useRule == "price_asc") {
|
||||
discountGoodsArr = canDikouGoodsArr
|
||||
.slice(canDikouGoodsArr.length - discountNum, canDikouGoodsArr.length)
|
||||
.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(discountSelGoodsArr.length - discountNum, discountSelGoodsArr.length)
|
||||
.reverse();
|
||||
} else {
|
||||
discountGoodsArr = discountSelGoodsArr.slice(0, discountNum);
|
||||
}
|
||||
}
|
||||
const result = calcDiscountGoodsArrPrice(discountGoodsArr, discountNum, user);
|
||||
return result;
|
||||
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;
|
||||
}
|
||||
|
||||
// 返回买一送一券抵扣详情
|
||||
@@ -348,38 +506,47 @@ export function returnCouponProductDiscount(canDikouGoodsArr, coupon, user) {
|
||||
* @param coupon 优惠券
|
||||
* @param user 用户信息
|
||||
* @param shopInfo 店铺信息
|
||||
* @param limitTimeDiscount 限时折扣
|
||||
*/
|
||||
function returnCouponBuyOneGiveOneDiscount(canDikouGoodsArr, coupon, user,shopInfo) {
|
||||
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.slice(0, 1);
|
||||
}
|
||||
} 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.slice(0, 1);
|
||||
}
|
||||
}
|
||||
const discountPrice = returnGoodsPrice(discountGoods, user,shopInfo);
|
||||
const hasDiscountGoodsArr = [discountGoods];
|
||||
return {
|
||||
discountPrice,
|
||||
hasDiscountGoodsArr
|
||||
};
|
||||
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,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -388,39 +555,46 @@ function returnCouponBuyOneGiveOneDiscount(canDikouGoodsArr, coupon, user,shopIn
|
||||
* @param coupon 优惠券
|
||||
* @param user 用户信息
|
||||
* @param shopInfo 店铺信息
|
||||
* @param limitTimeDiscount 限时折扣
|
||||
*/
|
||||
function returnSecoendDiscount(canDikouGoodsArr, coupon, user,shopInfo) {
|
||||
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.slice(0, 1);
|
||||
}
|
||||
} 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.slice(0, 1);
|
||||
}
|
||||
}
|
||||
const discountPrice = returnGoodsPrice(discountGoods, user,shopInfo);
|
||||
const hasDiscountGoodsArr = [discountGoods];
|
||||
//返回半价价格
|
||||
return {
|
||||
discountPrice: new BigNumber(discountPrice).dividedBy(2).toNumber(),
|
||||
hasDiscountGoodsArr,
|
||||
};
|
||||
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,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -428,17 +602,21 @@ function returnSecoendDiscount(canDikouGoodsArr, coupon, user,shopInfo) {
|
||||
* @param arr 商品列表
|
||||
* @param user 用户信息
|
||||
* @param shopInfo 店铺信息
|
||||
* @param limitTimeDiscount 限时折扣
|
||||
*/
|
||||
export function returnCanDikouGoods(arr, user, shopInfo) {
|
||||
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, use, shopInfo) - returnGoodsPrice(a, user, shopInfo);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -5,19 +5,48 @@ 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;
|
||||
}
|
||||
// 商家改价
|
||||
if (goods.discount_sale_amount * 1 > 0) {
|
||||
return goods.discount_sale_amount;
|
||||
return goods.salePrice;
|
||||
}
|
||||
// 限时折扣
|
||||
if (limitTimeDiscount && limitTimeDiscount.id) {
|
||||
if (
|
||||
limitTimeDiscount.foodType == 1 &&
|
||||
limitTimeDiscount.discountPriority == "limit-time"
|
||||
) {
|
||||
return new BigNumber(goods.salePrice)
|
||||
.times(limitTimeDiscount.discountRate / 100)
|
||||
.decimalPlaces(2, BigNumber.ROUND_UP)
|
||||
.toNumber();
|
||||
}
|
||||
const canUseFoods = limitTimeDiscount.foods.split(",");
|
||||
if (
|
||||
limitTimeDiscount.foodType == 2 &&
|
||||
limitTimeDiscount.discountPriority == "limit-time" &&
|
||||
canUseFoods.includes(`${goods.productId}`)
|
||||
) {
|
||||
return new BigNumber(goods.salePrice)
|
||||
.times(limitTimeDiscount.discountRate / 100)
|
||||
.decimalPlaces(2, BigNumber.ROUND_UP)
|
||||
.toNumber();
|
||||
}
|
||||
}
|
||||
if (shopInfo && !shopInfo.isMemberPrice) {
|
||||
return goods.salePrice;
|
||||
}
|
||||
if (user.isVip && goods.memberPrice * 1 <= goods.salePrice * 1 && goods.memberPrice * 1 > 0) {
|
||||
if (
|
||||
user.isVip &&
|
||||
goods.memberPrice * 1 <= goods.salePrice * 1 &&
|
||||
goods.memberPrice * 1 > 0
|
||||
) {
|
||||
return goods.memberPrice;
|
||||
}
|
||||
return goods.salePrice;
|
||||
@@ -63,7 +92,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 +123,53 @@ 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) => {
|
||||
if (!coupon.discountShare && goods.is_time_discount) {
|
||||
return false;
|
||||
}
|
||||
if(!coupon.vipPriceShare&& returnGoodsIsUseVipPrice(shopInfo,user,goods)){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断优惠券是否可使用,并返回不可用原因
|
||||
*
|
||||
@@ -111,10 +184,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 +205,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 +233,18 @@ 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
|
||||
);
|
||||
fullAmount = canCalcGoodsArr.reduce((pre, cur) => {
|
||||
return (
|
||||
pre + returnGoodsPrice(cur, user, shopInfo, limitTimeDiscount) * cur.num
|
||||
);
|
||||
}, 0);
|
||||
|
||||
// 是否全部商品可用
|
||||
const isDikouAll = coupon.useFoods.length === 0;
|
||||
@@ -147,12 +255,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,15 +291,8 @@ 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) {
|
||||
// 没有符合条件的商品
|
||||
if (isDikouAll && canDikouGoodsArr.length === 0) {
|
||||
return {
|
||||
canUse: false,
|
||||
reason: "没有符合条件的商品",
|
||||
@@ -203,6 +304,23 @@ 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,8 +376,15 @@ 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 = [];
|
||||
@@ -270,7 +395,8 @@ 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;
|
||||
discountPrice +=
|
||||
returnGoodsPrice(goods, user, shopInfo, limitTimeDiscount) * num;
|
||||
|
||||
hasCountNum += num;
|
||||
hasDiscountGoodsArr.push({
|
||||
@@ -293,22 +419,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) {
|
||||
export function returnCouponDiscount(
|
||||
arr,
|
||||
coupon,
|
||||
user,
|
||||
goodsOrderPrice,
|
||||
selCoupon,
|
||||
shopInfo,
|
||||
limitTimeDiscount
|
||||
) {
|
||||
arr = returnCanDikouGoods(arr, user, shopInfo);
|
||||
const canDikouGoodsArr = returnCanDikouGoodsArr(arr, selCoupon, user);
|
||||
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 +485,7 @@ export function returnCouponDiscount(arr, coupon, user, goodsOrderPrice, selCoup
|
||||
* @param user 用户信息
|
||||
* @param goodsOrderPrice 商品订单金额
|
||||
* @param selCoupon 已选择的优惠券列表
|
||||
* @param limitTimeDiscount 限时折扣
|
||||
*
|
||||
*/
|
||||
export function returnCouponZhekouDiscount(
|
||||
@@ -326,7 +493,8 @@ export function returnCouponZhekouDiscount(
|
||||
coupon,
|
||||
user,
|
||||
goodsOrderPrice,
|
||||
selCoupon
|
||||
selCoupon,
|
||||
limitTimeDiscount
|
||||
) {
|
||||
const { discountRate, maxDiscountAmount } = coupon;
|
||||
|
||||
@@ -334,14 +502,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 +525,8 @@ export function returnCouponZhekouDiscount(
|
||||
|
||||
// 应用最大折扣金额限制
|
||||
if (maxDiscountAmount !== 0) {
|
||||
discountPrice = discountPrice >= maxDiscountAmount ? maxDiscountAmount : discountPrice;
|
||||
discountPrice =
|
||||
discountPrice >= maxDiscountAmount ? maxDiscountAmount : discountPrice;
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -366,8 +541,15 @@ 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 = [];
|
||||
@@ -389,7 +571,13 @@ 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 +587,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 +610,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 {
|
||||
@@ -425,7 +622,12 @@ function returnCouponBuyOneGiveOneDiscount(canDikouGoodsArr, coupon, user, shopI
|
||||
let discountPrice = 0;
|
||||
let hasDiscountGoodsArr = [];
|
||||
if (discountGoods) {
|
||||
discountPrice = returnGoodsPrice(discountGoods, user, shopInfo);
|
||||
discountPrice = returnGoodsPrice(
|
||||
discountGoods,
|
||||
user,
|
||||
shopInfo,
|
||||
limitTimeDiscount
|
||||
);
|
||||
hasDiscountGoodsArr = [discountGoods];
|
||||
}
|
||||
return {
|
||||
@@ -440,8 +642,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;
|
||||
@@ -456,7 +665,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 {
|
||||
@@ -466,12 +677,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,
|
||||
};
|
||||
}
|
||||
@@ -481,8 +700,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;
|
||||
@@ -491,7 +711,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;
|
||||
}
|
||||
|
||||
330
utils/goods.ts
330
utils/goods.ts
@@ -234,6 +234,40 @@ 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;
|
||||
}
|
||||
|
||||
/** 订单额外费用配置 */
|
||||
export interface OrderExtraConfig {
|
||||
// merchantReduction: number; // 商家减免金额(元,默认0)
|
||||
@@ -251,6 +285,7 @@ export interface OrderExtraConfig {
|
||||
currentDinnerType: "dine-in" | "take-out" | "take-away" | "post"; // 当前就餐类型(匹配useType)
|
||||
isFreeDine?: boolean; //是否霸王餐
|
||||
freeDineConfig?: FreeDineConfig;
|
||||
limitTimeDiscount?: TimeLimitDiscountConfig; //限时折扣
|
||||
}
|
||||
|
||||
/** 订单费用汇总(修改:补充商家减免类型和明细) */
|
||||
@@ -283,10 +318,12 @@ export interface OrderCostSummary {
|
||||
config: OrderExtraConfig; // 订单额外费用配置
|
||||
//满减活动
|
||||
fullReduction: {
|
||||
usedFullReductionActivityFullAmount: number; // 计算出的满减活动的门槛金额
|
||||
usedActivity?: FullReductionActivity; // 实际使用的满减活动
|
||||
usedThreshold?: FullReductionThreshold; // 实际使用的满减阈值(多门槛中选最优)
|
||||
actualAmount: number; // 满减实际减免金额(元)
|
||||
};
|
||||
vipDiscountAmount: number; //会员折扣减免金额
|
||||
// 订单原支付金额
|
||||
orderOriginFinalPayAmount: number; //订单原金额(包含打包费+餐位费)
|
||||
}
|
||||
@@ -399,6 +436,188 @@ 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(",");
|
||||
if (limitTimeDiscount.discountPriority == "limit-time") {
|
||||
if (
|
||||
limitTimeDiscount.foodType == 1 ||
|
||||
canUseFoods.includes("" + goods[idKey])
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (limitTimeDiscount.discountPriority == "vip-price") {
|
||||
if (!useVipPrice) {
|
||||
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
|
||||
) {
|
||||
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) {
|
||||
//使用会员价
|
||||
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
|
||||
): 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;
|
||||
console.log("amount", amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* 筛选最优满减活动(对齐后端逻辑:状态→时间→周期→时段→就餐类型→排序→修改时间)
|
||||
* @param activities 后端返回的满减活动列表
|
||||
@@ -424,11 +643,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);
|
||||
@@ -665,11 +889,12 @@ 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;
|
||||
|
||||
//如果是增菜价格为0
|
||||
if (goods.is_gift) {
|
||||
@@ -680,6 +905,7 @@ export function calcSingleGoodsRealPrice(
|
||||
if (goods.discountSaleAmount && goods.discountSaleAmount > 0) {
|
||||
return truncateToTwoDecimals(goods.discountSaleAmount);
|
||||
}
|
||||
console.log("calcSingleGoodsRealPrice:goods", goods);
|
||||
|
||||
// 2. 优先级2:会员价(含会员折扣率,SKU会员价优先)
|
||||
const memberPrice = new BigNumber(
|
||||
@@ -687,12 +913,35 @@ 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();
|
||||
}
|
||||
//限时折扣优先或者会员价优先但是不是会员或者未开启会员价格时限时折扣优先
|
||||
if (
|
||||
activity.discountPriority == "limit-time" ||
|
||||
(activity.discountPriority == "vip-price" && !isMember)
|
||||
) {
|
||||
//限时折扣优先
|
||||
return truncateToTwoDecimals(
|
||||
new BigNumber(goods.salePrice)
|
||||
.multipliedBy(activity.discountRate / 100)
|
||||
.toNumber()
|
||||
);
|
||||
}
|
||||
if (activity.discountPriority == "vip-price" && isMember) {
|
||||
return memberPrice.toNumber();
|
||||
}
|
||||
|
||||
// 处理活动与会员的同享/不同享逻辑
|
||||
if (activity.vipPriceShare) {
|
||||
@@ -751,26 +1000,17 @@ 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 })
|
||||
);
|
||||
const realPrice = new BigNumber(calcSingleGoodsRealPrice(goods, config));
|
||||
total = total.plus(realPrice.multipliedBy(availableNum));
|
||||
}
|
||||
|
||||
@@ -967,14 +1207,13 @@ export function calcTotalPackFee(
|
||||
for (const goods of goodsList) {
|
||||
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
|
||||
if (dinnerType === "take-out") {
|
||||
packNum = availableNum;
|
||||
}
|
||||
if (goods.product_type === GoodsType.WEIGHT) {
|
||||
packNum = Math.min(packNum, 1);
|
||||
@@ -1066,7 +1305,12 @@ export function calculateOrderCostSummary(
|
||||
currentTime: Date = new Date()
|
||||
): OrderCostSummary {
|
||||
//是否使用霸王餐,霸王餐配置
|
||||
const { isFreeDine, freeDineConfig } = config;
|
||||
const {
|
||||
isFreeDine,
|
||||
freeDineConfig,
|
||||
limitTimeDiscount,
|
||||
fullReductionActivities,
|
||||
} = config;
|
||||
|
||||
// ------------------------------ 1. 基础费用计算 ------------------------------
|
||||
const goodsOriginalAmount = calcGoodsOriginalAmount(goodsList); // 商品原价总和
|
||||
@@ -1076,13 +1320,17 @@ export function calculateOrderCostSummary(
|
||||
{
|
||||
isMember: config.isMember,
|
||||
memberDiscountRate: config.memberDiscountRate,
|
||||
},
|
||||
activities
|
||||
limitTimeDiscount: config.limitTimeDiscount,
|
||||
}
|
||||
);
|
||||
const goodsDiscountAmount = calcGoodsDiscountAmount(
|
||||
goodsOriginalAmount,
|
||||
goodsRealAmount
|
||||
); // 商品折扣金额
|
||||
|
||||
//会员折扣
|
||||
let vipDiscountAmount = 0;
|
||||
|
||||
const newUserDiscount = config.newUserDiscount || 0; // 新客立减
|
||||
|
||||
// ------------------------------ 2. 满减活动计算(核心步骤) ------------------------------
|
||||
@@ -1104,7 +1352,14 @@ export function calculateOrderCostSummary(
|
||||
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)
|
||||
@@ -1114,10 +1369,19 @@ export function calculateOrderCostSummary(
|
||||
baseAfterNewUserDiscount > 0 ? baseAfterNewUserDiscount : 0;
|
||||
|
||||
// 2.3 选择最优满减阈值(多门槛场景)
|
||||
let usedFullReductionActivityFullAmount = 0;
|
||||
if (usedFullReductionActivity) {
|
||||
//计算当前满减活动的门槛金额
|
||||
usedFullReductionActivityFullAmount = calcFullReductionActivityFullAmount(
|
||||
goodsList,
|
||||
usedFullReductionActivity,
|
||||
config.limitTimeDiscount,
|
||||
config.isMember
|
||||
);
|
||||
|
||||
usedFullReductionThreshold = selectOptimalThreshold(
|
||||
usedFullReductionActivity.thresholds,
|
||||
baseAfterNewUserDiscount,
|
||||
usedFullReductionActivityFullAmount,
|
||||
goodsOriginalAmount,
|
||||
goodsRealAmount,
|
||||
usedFullReductionActivity.discountShare || 0 // 与限时折扣同享规则
|
||||
@@ -1182,27 +1446,23 @@ 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");
|
||||
pointDeductionAmount = 0;
|
||||
usedPoints = 0;
|
||||
}
|
||||
|
||||
//使用霸王餐
|
||||
if (isFreeDine && freeDineConfig && freeDineConfig.enable) {
|
||||
console.log("使用霸王餐");
|
||||
fullReductionAmount=0;
|
||||
fullReductionAmount = 0;
|
||||
//不与优惠券同享
|
||||
if (!freeDineConfig.withCoupon) {
|
||||
couponDeductionAmount = 0;
|
||||
@@ -1319,10 +1579,12 @@ export function calculateOrderCostSummary(
|
||||
scoreMaxMoney,
|
||||
// 满减活动明细(后端字段)
|
||||
fullReduction: {
|
||||
usedFullReductionActivityFullAmount: usedFullReductionActivityFullAmount,
|
||||
usedActivity: usedFullReductionActivity,
|
||||
usedThreshold: usedFullReductionThreshold,
|
||||
actualAmount: truncateToTwoDecimals(fullReductionAmount),
|
||||
},
|
||||
vipDiscountAmount: vipDiscountAmount, //会员折扣减免金额
|
||||
merchantReduction: {
|
||||
type: merchantReductionConfig.type,
|
||||
originalConfig: merchantReductionConfig,
|
||||
|
||||
152
utils/order-utils.js
Normal file
152
utils/order-utils.js
Normal file
@@ -0,0 +1,152 @@
|
||||
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(",");
|
||||
if (limitTimeDiscountRes.discountPriority == "limit-time") {
|
||||
if (
|
||||
limitTimeDiscountRes.foodType == 1 ||
|
||||
canUseFoods.includes("" + goods[idKey])
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (
|
||||
limitTimeDiscountRes.discountPriority == "vip-price"
|
||||
|
||||
) {
|
||||
|
||||
if(shopUserInfo.isVip != 1 || shopInfo.isMemberPrice != 1){
|
||||
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;
|
||||
const canUseFoods = (limitTimeDiscountRes.foods || "").split(",");
|
||||
shopInfo=shopInfo||{}
|
||||
shopUserInfo=shopUserInfo||{}
|
||||
if (shopInfo.isMemberPrice == 1 && shopUserInfo.isVip == 1) {
|
||||
const memberPrice = goods.memberPrice || goods.salePrice;
|
||||
|
||||
//是会员而且启用会员价
|
||||
if (limitTimeDiscountRes) {
|
||||
//使用限时折扣
|
||||
//限时折扣优先
|
||||
if (limitTimeDiscountRes.discountPriority == "limit-time") {
|
||||
if (
|
||||
limitTimeDiscountRes.foodType == 1 ||
|
||||
canUseFoods.includes("" + goods[idKey])
|
||||
) {
|
||||
return returnLimitPrice({
|
||||
price: goods.salePrice,
|
||||
limitTimeDiscountRes,
|
||||
});
|
||||
} else {
|
||||
return memberPrice;
|
||||
}
|
||||
}
|
||||
if (limitTimeDiscountRes.discountPriority == "vip-price") {
|
||||
//会员优先
|
||||
return memberPrice;
|
||||
}
|
||||
} else {
|
||||
//是会员没有限时折扣
|
||||
return memberPrice;
|
||||
}
|
||||
} else {
|
||||
// console.log('不是会员或者没有启用会员价',goods,limitTimeDiscountRes);
|
||||
//不是会员或者没有启用会员价
|
||||
if (
|
||||
limitTimeDiscountRes &&
|
||||
limitTimeDiscountRes.id &&
|
||||
(limitTimeDiscountRes.foodType == 1 ||
|
||||
canUseFoods.includes("" + goods[idKey]))
|
||||
) {
|
||||
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) {
|
||||
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 (shopInfo.isMemberPrice == 1 && shopUserInfo.isVip == 1) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回会员价格
|
||||
* @param {*} goods
|
||||
* @returns
|
||||
*/
|
||||
export function returnMemberPrice(goods) {
|
||||
return goods.memberPrice || goods.salePrice;
|
||||
}
|
||||
Reference in New Issue
Block a user