Files
cashier_wx/pages/order/coupon1.vue
2025-09-26 19:56:47 +08:00

634 lines
15 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="container">
<view class="containertop">
<view class="containertopbox">
<view class="containertopboxitem flex-start" v-for="(item,index) in fromInfo.list" :key="index">
<view class="containertopboxitemleft flex-colum"
:class="{'containertopboxitemleft_vip': item.type == 2,'containertopboxitemlefts': fromInfo.status != 1,}">
<view class="containertopboxitemleft_one" v-if="Orderinfo.typeOrder == 1"
:class="Orderinfo.typeOrder == 1 ?'':'containertopboxitemleft_ones'">
<block v-if="item.type == 2">
<text>1</text>
<text style="font-size: 28rpx;margin-left: 6rpx;"></text>
</block>
<block v-else>
<text style="font-size: 28rpx;margin-right: 6rpx;"></text>
<text>{{item.discountAmount || 0}}</text>
</block>
</view>
<view class="containertopboxitemleft_tow"
:class="{'containertopboxitemleft_nameVip': item.type == 2}">
{{ item.type == 2 ? item.name : '优惠券(元)'}}
</view>
</view>
<view class="containertopboxitemright">
<view class="containertopboxitemright_one">
<view class="flex-start">
<image class="icon"
src="https://czg-qr-order.oss-cn-beijing.aliyuncs.com/user/coupon_icon.png"
mode="aspectFill"></image>
<text class="title">{{ item.shopName }}</text>
</view>
<!-- 商品卷显示 -->
<text v-if="Orderinfo.typeOrder == 2">无门槛使用</text>
</view>
<view class="containertopboxitemright_tow">
<view> {{ item.type == 2 ? '会员商品券' : item.name}}</view>
<!-- 优惠卷 -->
<view @click="navigatorGo(item)" v-if="Orderinfo.typeOrder == 1"
class="containertopboxitemright_four containertopboxitemright_btn"
style="padding: 10rpx 15rpx;">
去使用
</view>
<!-- 商品卷 -->
<view @click="clickupicon(item,index)" v-if="Orderinfo.typeOrder == 2 && item.show"
class="containertopboxitemright_btn">
<up-icon v-if="item.Selected" name="checkmark-circle-fill" color="#2979ff"
size="28"></up-icon>
<view v-else class="upicon"></view>
</view>
<view v-if="Orderinfo.typeOrder == 2 && !item.show" class="containertopboxitemright_fours">
不可使用
</view>
</view>
<view class="containertopboxitemright_there">
有效期至{{item.endTime}}
</view>
</view>
</view>
<view v-if="fromInfo.list.length <= 0" style="text-align: center;">
<image style="width: 402rpx;height: 442rpx;margin:240rpx auto 32rpx;"
src="https://czg-qr-order.oss-cn-beijing.aliyuncs.com/nomore.png" mode="aspectFill"></image>
</view>
</view>
</view>
<view style="height:120rpx;"></view>
<view class="btnBox" v-if="Orderinfo.typeOrder == 2">
<view class="btn" @click="cancelCoupon">确定</view>
</view>
<view class="btnBox" v-else>
<button style="margin-top: 20rpx;" @click="IntegralInputclose">取消</button>
</view>
</view>
</template>
<script setup>
import {
ref,
reactive,
onMounted,
computed
} from 'vue';
import {
onLoad,
onReady,
onShow,
} from '@dcloudio/uni-app'
import {
APIcouponfindByUserId,
APIfindCoupon
} from '@/common/api/member.js'
const fromInfo = reactive({
tabIndex: 0,
list: [],
status: 1,
shopId: null,
orderId: null,
couopnInfo: null,
shoppingCart: [],
productList: [],
})
// 判断是选择优惠卷
const Orderinfo = reactive({
typeOrder: '',
shopUserId: "",
payAmount: "",
shoppingCart: [],
show: false
})
// 去使用优惠券
const navigatorGo = (item) => {
// console.log(Orderinfo.payAmount, item)
if (Orderinfo.payAmount < item.fullAmount) {
uni.showToast({
title: "当前订单金额不足使用金额",
icon: "none",
})
return;
}
if (Orderinfo.payAmount < item.discountAmount) {
uni.showToast({
title: "当前订单金额不足抵扣金额",
icon: "none",
})
return;
}
uni.$emit('returnData', {
typeOrder: Orderinfo.typeOrder,
item,
});
uni.navigateBack({
delta: 1
});
}
// 计算合并后的数组 num相加
const mergedArray = computed(() => {
const map = new Map();
Orderinfo.shoppingCart.forEach(item => {
if (map.has(item.productId)) {
const existingItem = map.get(item.productId);
existingItem.num += item.num;
} else {
map.set(item.productId, {
...item
});
}
});
return Array.from(map.values());
});
const Selectedlist = ref([])
// 商品卷
const clickupicon = async (item, index) => {
lowestPrices.value = []
if (!item.show) {
return false;
}
if (item.Selected) {
Selectedlist.value = Selectedlist.value.filter(i => i.id !== item.id)
fromInfo.list[index].Selected = false
return
}
const canSelMaxNum = Orderinfo.shoppingCart.filter((v) => v.productId == item.proId).reduce((prve,
cur) => {
return prve + cur.num * 1
}, 0)
if (canSelMaxNum <= 0) {
uni.showToast({
title: '不可多余商品!',
icon: 'none'
})
return
}
// 查找选中的数组里面 统计指定 id 的重复次数
const count = Selectedlist.value.filter(v => v.couponId == item.couponId).length;
if (count >= canSelMaxNum) {
uni.showToast({
title: '不可多余商品!',
icon: 'none'
})
return false;
}
// 查找选中的数组里面 统计指定 id 的重复次数
// console.log(mergedArray.value)
// console.log(item)
// console.log(Selectedlist.value)
// console.log(Orderinfo.shoppingCart)
// if (Orderinfo.shoppingCart.length <= Selectedlist.value.length) {
// uni.showToast({
// title: '不可多余下单数!',
// icon:'none'
// })
// return false;
// }
// 筛查出最低价格
await productmethod()
const matchedItem = lowestPrices.value.find(cartItem => cartItem.productId == item.proId);
Selectedlist.value.push({
...item,
price: matchedItem.price,
memberPrice: matchedItem.memberPrice
})
fromInfo.list[index].Selected = !item.Selected
}
// 这是判断是否符合选中规格
const groupByPropertyAndCount = (arr, property) => {
// 创建一个空对象来存储每个属性值对应的数量
const propertyMap = {};
// 遍历原始数组
arr.forEach(item => {
const key = item[property];
const num = item.number || 1;
if (!propertyMap[key]) {
// 如果该属性值还没有在 propertyMap 中,初始化一个对象
propertyMap[key] = {
value: item[property],
count: num
};
} else {
// 如果该属性值已经存在,增加数量
propertyMap[key].count += num;
}
});
// 将 propertyMap 中的结果转换为数组
return Object.values(propertyMap);
}
// 存储每个 productId 对应的最低价格
const lowestPrices = ref([]);
// 筛选出携带的商品是否有相同的商品 productId
const productmethod = () => {
const groupedProducts = {};
// 第一步:将相同 productId 的商品分组
Orderinfo.shoppingCart.forEach(product => {
const {
productId
} = product;
if (!groupedProducts[productId]) {
groupedProducts[productId] = [];
}
groupedProducts[productId].push(product);
});
// 第二步:遍历每个分组,找出最低价格
for (const productId in groupedProducts) {
let minPrice = Infinity;
let minMemberPrice = Infinity;
groupedProducts[productId].forEach(product => {
if (product.price < minPrice) {
minPrice = product.price;
minMemberPrice = product.memberPrice;
}
});
// 将每个 productId 的最低价格信息添加到 lowestPrices 数组中
lowestPrices.value.push({
productId: Number(productId),
price: minPrice,
memberPrice: minMemberPrice
});
}
}
const getCouponList = async () => {
let res = await APIfindCoupon({
type: Orderinfo.typeOrder,
shopUserId: Orderinfo.shopUserId,
})
if (Orderinfo.typeOrder == 2 && res.length > 0) {
res.forEach((item) => {
item.Selected = false
})
res = res.map(item => {
const matchedItem = Orderinfo.shoppingCart.find(cartItem => {
return cartItem.productId == item.proId
});
const hasMatch = Boolean(matchedItem);
return {
...item,
show: hasMatch,
price: hasMatch ? matchedItem.price : undefined,
memberPrice: hasMatch ? matchedItem.memberPrice : undefined
};
});
}
if (res.length > 0) {
fromInfo.list = res
} else {
fromInfo.list = []
return false
}
}
// 商品取消
const cancelCoupon = () => {
uni.$emit('returnData', Selectedlist.value);
uni.navigateBack({
delta: 1
});
}
// 优惠卷取消
const IntegralInputclose = () => {
uni.$emit('returnData', {
typeOrder: Orderinfo.typeOrder,
});
uni.navigateBack({
delta: 1
});
}
onMounted(async () => {
// 获取当前页面栈
const pages = getCurrentPages();
// 获取当前页面实例
const currentPage = pages[pages.length - 1];
// 获取页面参数
const options = currentPage.options;
if (options.shopId) {
fromInfo.shopId = options.shopId
}
if (options.type) {
Orderinfo.typeOrder = options.type == 'confirm_order_product' ? 2 : 1
uni.setNavigationBarTitle({
title: Orderinfo.typeOrder == 2 ? '商品卷' : '优惠卷',
success: () => {},
fail: (err) => {}
});
Orderinfo.shopUserId = options.shopUserId
Orderinfo.payAmount = options.payAmount
console.log('coupon mounted');
console.log(Orderinfo.payAmount)
console.log(options);
console.log(JSON.parse(decodeURIComponent(options.shoppingCart)));
Orderinfo.shoppingCart = JSON.parse(decodeURIComponent(options.shoppingCart))
}
getCouponList()
})
</script>
<style lang="scss">
page {
background: #fff;
}
.container {
.towcontent {
padding: 0 28rpx;
border-top: 16rpx solid #f7f7f7;
.towcontentlistxitem {
width: 100%;
margin-top: 32rpx;
.towcontentlistxitembox {
width: 33.33%;
font-family: PingFang SC, PingFang SC;
font-weight: 500;
font-size: 28rpx;
color: #333333;
justify-content: flex-start;
height: 50rpx;
image {
margin-top: 6rpx;
width: 38.83rpx;
height: 8.62rpx;
}
}
.towcontentlistxitemboxopacity {
font-weight: bold;
text {
color: #E3AD7F;
}
image {
margin-top: 6rpx;
width: 38.83rpx;
height: 8.62rpx;
}
}
}
}
.containertop {
padding: 40rpx 32rpx;
.containertopbox {
margin-top: 8rpx;
.containertopboxitem::after {
position: absolute;
bottom: 14rpx;
left: 14rpx;
content: '';
display: inline-block;
background: url(https://czg-qr-order.oss-cn-beijing.aliyuncs.com/coupontop.png) no-repeat;
width: 72.83rpx;
height: 77.14rpx;
background-size: cover;
}
.containertopboxitem {
margin-bottom: 32rpx;
width: 100%;
position: relative;
border-radius: 18rpx;
box-shadow: 0rpx 6rpx 12rpx 2rpx rgba(0, 0, 0, 0.16);
overflow: hidden;
.containertopboxitemleft {
position: relative;
width: 182rpx;
height: 192rpx;
background: #E3AD7F;
border-radius: 18rpx 0rpx 0rpx 18rpx;
padding: 0 20rpx;
// ::before {
// content: '';
// position: absolute;
// bottom: 0rpx;
// left: 166rpx;
// background: #fff;
// display: inline-block;
// width: 32rpx;
// height: 16rpx;
// line-height: 32rpx;
// border-radius: 32rpx 32rpx 0 0;
// box-shadow: 0rpx 6rpx 12rpx 2rpx rgba(255, 255, 255, 0.16);
// z-index: 999;
// }
.containertopboxitemleft_one {
text {
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 500;
font-size: 60rpx;
color: #FFFFFF;
}
}
.containertopboxitemleft_ones {
text {
color: #999999;
}
}
.containertopboxitemleft_tow {
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 500;
font-size: 24rpx;
color: #FFFFFF;
}
.containertopboxitemleft_nameVip {
color: #967152;
}
.containertopboxitemleft_tows {
color: #999999;
}
}
.containertopboxitemleft::after {
content: '';
position: absolute;
top: -20rpx;
left: 166rpx;
background: #fff;
display: inline-block;
width: 40rpx;
height: 40rpx;
border-radius: 50%;
box-shadow: inset 0rpx 1rpx 9rpx 21rpx rgba(0, 0, 0, 0.04);
z-index: 999;
}
.containertopboxitemleft::before {
content: '';
position: absolute;
bottom: -20rpx;
left: 166rpx;
background: #fff;
display: inline-block;
width: 40rpx;
height: 40rpx;
border-radius: 50%;
box-shadow: inset 0rpx 0rpx 15rpx 1rpx rgba(0, 0, 0, 0.1);
z-index: 999;
}
.containertopboxitemleft_vip {
background-color: #E1D4B2;
}
.containertopboxitemlefts {
background: #F7F7F7;
}
.containertopboxitemright {
position: relative;
padding: 0 32rpx;
flex: auto;
height: 192rpx;
background: #FFFFFF;
border-radius: 0rpx 18rpx 18rpx 0rpx;
.containertopboxitemright_one {
font-family: Source Han Sans CN, Source Han Sans CN;
padding: 16rpx 0 20rpx 0;
border-bottom: 1rpx dashed #707070;
display: flex;
justify-content: space-between;
align-items: center;
.icon {
width: 26rpx;
height: 26rpx;
margin-right: 14rpx;
}
text {
font-weight: bold;
font-size: 24rpx;
color: #666666;
}
.title {
color: #333;
}
}
.containertopboxitemright_tow {
margin-top: 24rpx;
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: bold;
font-size: 32rpx;
color: #333333;
display: flex;
justify-content: space-between;
align-items: center;
}
.containertopboxitemright_there {
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 500;
font-size: 24rpx;
color: #999999;
}
.containertopboxitemright_btn {
font-family: Source Han Sans CN, Source Han Sans CN;
font-weight: 500;
font-size: 24rpx;
border-radius: 24rpx 24rpx 24rpx 24rpx;
.upicon {
width: 40rpx;
height: 40rpx;
border-radius: 50%;
border: 1rpx solid #000;
}
}
.containertopboxitemright_four {
color: #FFFFFF;
background: #967152;
}
.containertopboxitemright_fours {
color: #999999;
background: #F7F7F7;
}
}
}
}
}
.select {
padding-bottom: 180rpx;
}
.btnBox {
width: 100%;
position: fixed;
bottom: 0;
left: 0;
z-index: 999;
background-color: #fff;
padding: 30rpx 30rpx 50rpx 30rpx;
.btn {
width: 100%;
height: 90rpx;
line-height: 90rpx;
text-align: center;
font-weight: bold;
font-size: 36rpx;
color: #FFFFFF;
border-radius: 12rpx;
background: #E3AD7F;
}
}
}
</style>