Files

789 lines
19 KiB
Vue
Raw Permalink 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="u-p-l-30 u-p-r-30 u-p-t-30 u-font-28">
<up-sticky offset-top="0">
<my-tabs v-model="myQuan.types.sel" :list="myQuan.types.list"></my-tabs>
</up-sticky>
<view class="u-m-t-32">
<view
class=""
@click="changeSelCoupon(item)"
v-for="(item, index) in list.canUseCoupons"
:class="{ filtergray: !item.use }"
:key="index"
>
<view
class="quan u-row-between u-flex u-col-center u-m-b-32 border-r-10"
>
<view class="no-use" v-if="!item.use">
<image
class="img"
src="/pagesOrder/static/image/no-use.svg"
mode=""
></image>
</view>
<view class="sel u-abso" v-if="isActive(item)">
<up-icon name="checkbox-mark" color="#fff"></up-icon>
</view>
<view class="u-p-t-32 u-p-b-32 u-p-l-24 u-p-r-24 left">
<view class="u-flex" v-if="item.type != 2">
<view class="hui"></view>
<view class="u-m-l-18">{{ item.name }}</view>
</view>
<view v-else>{{ item.name }}</view>
<view class="u-m-t-20 u-flex">
<view>有效期:</view>
<view class="u-font-24 u-m-l-6">
{{ dayjs(item.effectStartTime).format("YYYY-MM-DD HH:mm:ss") }}
-
{{ dayjs(item.effectEndTime).format("YYYY-MM-DD HH:mm:ss") }}
</view>
</view>
<view class="u-m-t-10 color-999 u-font-24">
{{ formatStr(item.useRestrictions) }}
</view>
</view>
<view class="right u-flex u-flex-col u-row-between">
<view class="u-flex u-row-center u-font-36" v-if="item.type != 2">
{{ item.discountAmount }}
</view>
<view class="u-flex u-font-24"> {{ item.fullAmount }}可用 </view>
<view class="u-flex">
<!-- <view class="use-btn" @click.stop="toEmitChooseQuan(item)"
>去使用</view
> -->
</view>
</view>
</view>
</view>
<template v-if="list.canUseCoupons.length <= 0 && myQuan.hasAjax">
<my-img-empty tips="暂无可用优惠券"></my-img-empty>
</template>
<view style="height: 40rpx"></view>
<view
v-for="(item, index) in list.noCanUseCoupons"
class="filtergray"
:key="index"
>
<view
class="quan u-row-between u-flex u-col-center u-m-b-32 border-r-10"
>
<view class="no-use">
<image
class="img"
src="/pagesOrder/static/image/no-use.svg"
mode=""
></image>
</view>
<view class="sel u-abso" v-if="isActive(item)">
<up-icon name="checkbox-mark" color="#fff"></up-icon>
</view>
<view class="u-p-t-32 u-p-b-32 u-p-l-24 u-p-r-24 left">
<view class="u-flex" v-if="item.type != 2">
<view class="hui"></view>
<view class="u-m-l-18">{{ item.name }}</view>
</view>
<template v-else>
<view class="u-flex">
{{ item.foods }}
</view>
<view class="u-flex">
{{ item.name }}
</view>
</template>
<view class="u-m-t-20 u-flex">
<view>有效期:</view>
<view class="u-font-24 u-m-l-6">
{{ dayjs(item.effectStartTime).format("YYYY-MM-DD HH:mm:ss") }}
-
{{ dayjs(item.effectEndTime).format("YYYY-MM-DD HH:mm:ss") }}
</view>
</view>
<view class="u-m-t-10 color-999 u-font-24">
{{ formatStr(item.useRestrictions) }}
</view>
<view class="u-m-t-10 color-999 u-font-24">
{{ returnNoUseRestrictions(item) }}
</view>
</view>
<view class="right u-flex u-flex-col u-row-between">
<view class="u-flex u-row-center u-font-36" v-if="item.type != 2">
{{ item.discountAmount }}
</view>
<view class="u-flex u-font-24"> {{ item.fullAmount }}可用 </view>
<view class="u-flex">
<!-- <view class="use-btn" @click.stop="toEmitChooseQuan(item)"
>去使用</view
> -->
</view>
</view>
</view>
</view>
</view>
<view :style="{ height: safebottomHeight + 'px' }"></view>
<view class="fixed-b bottom safe-bottom border-top">
<view class="u-m-b-32 u-flex u-row-between u-p-t-10">
<view class="u-flex">
<text>抵扣金额</text>
<text class="color-red"></text>
<text class="color-red">{{ discountAmount }}</text>
</view>
<view class="u-flex u-relative">
<text>支付金额</text>
<text class="color-red"></text>
<text class="color-red">{{ payPrice }}</text>
<view
class="u-absolute u-flex u-row-between"
style="bottom: 100%; right: 0"
v-if="payPrice * 1 != option.orderPrice * 1"
>
<view class="u-flex line-th color-999">
<text class=""></text>
<text class="">{{ option.orderPrice }}</text>
</view>
</view>
</view>
</view>
<view class="u-flex gap-20">
<up-button shape="circle" plain @click="back">
<view class="font-bold">取消</view>
</up-button>
<up-button shape="circle" type="primary" @click="toEmitChooseQuan()">
<view class="font-bold">确定</view>
</up-button>
</view>
</view>
<up-modal
:title="modal.title"
:content="modal.content"
:show="modal.clear"
:confirmText="modal.confirmText"
:cancelText="modal.cancelText"
showCancelButton
closeOnClickOverlay
@confirm="confirmModelConfirm"
@cancel="confirmModelCancel"
@close="setModalShow('clear', false)"
width="300px"
/>
</view>
</template>
<script setup>
import { ref, reactive, watch, computed, onMounted, toRaw } from "vue";
import color from "@/commons/color.js";
import dayjs from "dayjs";
import { getSafeBottomHeight } from "@/commons/utils/safe-bottom.js";
import go from "@/commons/utils/go.js";
import { onLoad, onReady } from "@dcloudio/uni-app";
import * as orderApi from "@/http/yskApi/order.js";
import { $findCoupon } from "@/http/yskApi/Instead.js";
import infoBox from "@/commons/utils/infoBox.js";
import { queryAllShopUser, shopUserDetail } from "@/http/yskApi/shop-user.js";
// import {
// returnNewGoodsList,
// returnCoupCanUse,
// returnCouponAllPrice,
// returnProductCoupon,
// returnCanUseFullReductionCoupon,
// } from "../quan_util.js";
// const yskUtils = {
// couponUtils,
// };
// import yskUtils from "ysk-utils";
import {couponUtils} from "@/lib/index";
const yskUtils={
couponUtils
}
const modal = reactive({
title: "提示",
cancelText: "取消",
confirmText: "确定",
content: "",
key: "",
clear: false,
data: "",
});
function confirmModelCancel() {
setModalShow("clear", false, "");
}
async function confirmModelConfirm() {
if (modal.key == "clear") {
myQuan.fullReductionCouponSel = {
id: "",
};
const item = modal.data;
item.checked = !item.checked;
const CheckedArr = myQuan.res.productCoupon.filter((v) => v.checked);
const noCheckedArr = myQuan.res.productCoupon.filter((v) => !v.checked);
noCheckedArr.map((v) => {
console.log(returnCoupCanUse(canDikouGoodsArr, v, CheckedArr));
v.use = returnCoupCanUse(canDikouGoodsArr, v, CheckedArr);
});
setModalShow("clear", false, "");
}
}
function setModalShow(key = "show", show = true, data) {
modal.key = key;
modal[key] = show;
modal.data = data;
}
function back() {
uni.navigateBack();
}
let order = ref({});
let canDikouGoodsArr = [];
const myQuan = reactive({
fullReductionCouponSel: {
id: "",
},
res: {
fullReductionCoupon: [],
productCoupon: [],
},
types: {
list: ["优惠券(单选)", "商品券(单选)"],
sel: 0,
},
list: [],
sel: -1,
hasAjax: false,
});
function changeSelCoupon(item) {
if (myQuan.types.sel == 0) {
if (couponSel.value.id == item.id) {
couponSel.value = {
id: "",
};
} else {
couponSel.value = item;
}
} else {
if (goodsCouponSel.value.id == item.id) {
goodsCouponSel.value = {
id: "",
};
} else {
goodsCouponSel.value = item;
}
}
}
function formatStr(str) {
console.log(str);
if (!str) {
return "";
}
const reg = /^[,]+|[,]+$/g;
return `${str}`.replace(reg, "");
}
function isActive(item) {
if (myQuan.types.sel == 0) {
return couponSel.value.id == item.id;
} else {
return goodsCouponSel.value.id == item.id;
}
}
const shopUserInfo = ref(null);
// 将订单商品转换为一维数组返回全部商品
function returnAllGoodsList() {
let goodsArr = [];
for (let key in order.value.detailMap) {
console.log(order.value.detailMap[key]);
for (let goods of order.value.detailMap[key]) {
goods.salePrice = goods.salePrice || goods.price;
goods.number = goods.num || 0;
goodsArr.push(toRaw(goods));
}
}
return goodsArr;
}
//返回不可用原因
function returnNoUseRestrictions(item) {
if (item.noUseRestrictions) {
return item.noUseRestrictions;
}
if (item.canuseResult) {
return item.canuseResult.reason;
}
return "";
}
//优惠券列表
const couponList = ref([]);
//已选商品抵扣券
const goodsCouponSel = ref({
id: "",
});
//已选优惠券
const couponSel = ref({
id: "",
});
//限时折扣
const limitTimeDiscount = reactive({ id: "" });
//已选优惠券列表
const quansSelArr = computed(() => {
return [couponSel.value, goodsCouponSel.value].filter((v) => v.id);
});
const list = reactive({
page: 1,
size: 10,
status: "nomore",
data: [],
noCanUseCoupons: [],
canUseCoupons: [],
});
//返回优惠券可用与不可用的,计算优惠券抵扣金额
function formatCoupon() {
let canUseGoodsCoupon = [];
let canUseDiscountCoupon = [];
let noUseGoodsCoupon = [];
let noUseDiscountCoupon = [];
const user = shopUserInfo.value;
let shopInfo = uni.getStorageSync("shopInfo") || {};
const goodsOrderPrice = option.orderPrice || 0;
const dinnerType = option.dinnerType || "dine-in";
let goodsArr = returnAllGoodsList();
const canDikouGoodsArr = yskUtils.couponUtils.returnCanDikouGoods(
goodsArr,
user,
shopInfo
);
for (let i = 0; i < couponList.value.length; i++) {
const coupon = couponList.value[i];
console.log('quansSelArr',quansSelArr.value)
const selCoupon =
myQuan.types.sel ==1
? quansSelArr.value.filter((v) => v.type != 2)
: quansSelArr.value.filter((v) => v.type == 2);
const canuseResult = yskUtils.couponUtils.returnCouponCanUse({
canDikouGoodsArr,
coupon,
goodsOrderPrice,
user,
selCoupon: selCoupon,
shopInfo,
limitTimeDiscount: limitTimeDiscount,
});
const { canUse, reason } = canuseResult;
if (coupon.type == 2) {
if (canUse || goodsCouponSel.value.id == coupon.id) {
canUseGoodsCoupon.push(coupon);
} else {
noUseGoodsCoupon.push({
...coupon,
canuseResult,
});
}
} else {
if (canUse || couponSel.value.id == coupon.id) {
canUseDiscountCoupon.push(coupon);
} else {
noUseDiscountCoupon.push({
...coupon,
canuseResult,
});
}
}
}
//商品券
canUseGoodsCoupon = canUseGoodsCoupon.map((v) => {
const discount = yskUtils.couponUtils.returnCouponDiscount(
canDikouGoodsArr,
v,
user,
goodsOrderPrice,
quansSelArr.value.filter((v) => v.type != 2),
shopInfo,
limitTimeDiscount
);
return {
...v,
discount,
discountAmount: discount ? discount.discountPrice : v.discountAmount,
};
});
//非商品券
canUseDiscountCoupon = canUseDiscountCoupon.map((v) => {
const discount = yskUtils.couponUtils.returnCouponDiscount(
canDikouGoodsArr,
v,
user,
goodsOrderPrice,
quansSelArr.value.filter((v) => v.type == 2),
shopInfo,
limitTimeDiscount
);
return {
...v,
discount,
discountAmount: discount ? discount.discountPrice : v.discountAmount,
};
});
if (myQuan.types.sel == 1) {
list.noCanUseCoupons = noUseGoodsCoupon;
list.canUseCoupons = canUseGoodsCoupon;
} else {
list.noCanUseCoupons = noUseDiscountCoupon;
list.canUseCoupons = canUseDiscountCoupon;
}
console.log("list", list);
console.log("canUseGoodsCoupon", canUseGoodsCoupon);
console.log("noUseGoodsCoupon", noUseGoodsCoupon);
console.log("canUseDiscountCoupon", canUseDiscountCoupon);
console.log("noUseDiscountCoupon", noUseDiscountCoupon);
}
async function getQuan() {
const orderRes = await orderApi.tbOrderInfoDetail(option.orderId);
if (orderRes) {
order.value = orderRes
Object.assign(limitTimeDiscount,orderRes.limitRate)
}
console.log(order.value);
const res = await $findCoupon({
shopUserId: option.shopUserId,
});
couponList.value = res || [];
formatCoupon();
myQuan.hasAjax = true;
}
const option = reactive({
orderId: "",
shopUserId: "",
orderPrice: 0,
});
function toEmitChooseQuan(item) {
let arr = [];
if (item) {
arr = [item];
} else {
if (myQuan.fullReductionCouponSel.id) {
arr.push(myQuan.fullReductionCouponSel);
}
const goodsQuan = myQuan.res.productCoupon.filter((v) => v.checked);
arr.push(...goodsQuan);
}
uni.$emit("choose-quan", arr);
back();
}
const discountAmount = computed(() => {
return quansSelArr.value.reduce((pre, cur) => pre + cur.discountAmount, 0);
});
const payPrice = computed(() => {
const pay = option.orderPrice - discountAmount.value;
return (pay < 0 ? 0 : pay).toFixed(2);
});
watch(
() => myQuan.types.sel,
(newval) => {
formatCoupon();
}
);
watch(
() => couponSel.value.id,
(newval) => {
formatCoupon();
}
);
watch(
() => goodsCouponSel.value.id,
(newval) => {
formatCoupon();
}
);
watch(
() => quansSelArr.value,
(newval) => {
const user = shopUserInfo.value;
let shopInfo = uni.getStorageSync("shopInfo") || {};
const goodsOrderPrice = option.orderPrice || 0;
const dinnerType = option.dinnerType || "dine-in";
let goodsArr = returnAllGoodsList();
const canDikouGoodsArr = yskUtils.couponUtils.returnCanDikouGoods(
goodsArr,
user,
shopInfo
);
console.log('canDikouGoodsArr');
console.log(canDikouGoodsArr);
let goodsCoupon = newval.filter((v) => v.type == 2);
let otherCoupon = newval.filter((v) => v.type != 2);
goodsCoupon = goodsCoupon.map((v) => {
const discount = yskUtils.couponUtils.returnCouponDiscount(
canDikouGoodsArr,
v,
user,
goodsOrderPrice,
[],
shopInfo,
limitTimeDiscount
);
return {
...v,
discount,
discountAmount: discount ? discount.discountPrice : v.discountAmount,
};
});
otherCoupon = otherCoupon.map((v) => {
const discount = yskUtils.couponUtils.returnCouponDiscount(
canDikouGoodsArr,
v,
user,
goodsOrderPrice,
goodsCoupon,
shopInfo,
limitTimeDiscount
);
return {
...v,
discount,
discountAmount: discount ? discount.discountPrice : v.discountAmount,
};
});
uni.$emit("selCoupon", [...goodsCoupon, ...otherCoupon]);
},
{
deep: true,
}
);
async function getShopUser() {
const res = await shopUserDetail({
id: option.shopUserId,
});
if (res) {
shopUserInfo.value = res;
}
}
onLoad(async (opt) => {
Object.assign(option, opt);
const selCoupon=uni.getStorageSync("selCoupon")||[];
for(let i=0;i<selCoupon.length;i++){
if(selCoupon[i].type==2){
goodsCouponSel.value=selCoupon[i];
}else{
couponSel.value=selCoupon[i];
}
}
await getShopUser();
getQuan();
});
let safebottomHeight = ref(0);
onReady(() => {
getSafeBottomHeight("bottom", 0).then((height) => {
console.log(height);
safebottomHeight.value = height;
});
});
</script>
<style lang="scss" scoped>
// $quan-color:rgb(233, 77, 60);
$quan-color: #318afe;
.no-use {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
display: flex;
justify-content: center;
align-items: center;
.img {
width: 200rpx;
height: 200rpx;
z-index: 10;
}
}
.fixed-b {
position: fixed;
bottom: 0;
background-color: #fff;
right: 0;
left: 0;
}
.bg-gray {
border-radius: 18rpx;
overflow: hidden;
}
.price1 {
color: rgb(255, 107, 0);
}
.payType {
.radio {
display: flex;
justify-content: center;
align-items: center;
background-color: rgb(255, 212, 0);
width: 40rpx;
height: 40rpx;
border-radius: 40rpx;
opacity: 0;
}
.active {
.radio {
opacity: 1;
}
}
}
.left-block {
position: relative;
&::after {
content: "";
position: absolute;
left: -30rpx;
display: block;
width: 12rpx;
top: 0;
background-color: rgb(255, 212, 0);
bottom: 0;
}
}
.filtergray {
filter: grayscale(1);
}
.radio {
display: flex;
justify-content: center;
align-items: center;
background-color: rgb(255, 255, 255);
width: 40rpx;
height: 40rpx;
border-radius: 40rpx;
&.active {
}
}
.use-btn {
background-color: #fff;
border-radius: 100rpx;
padding: 4rpx 20rpx;
color: $quan-color;
}
.u-font-40 {
font-size: 40rpx;
}
.yilingqu {
position: absolute;
bottom: 20rpx;
right: 20rpx;
}
.lingqu {
position: absolute;
bottom: 20rpx;
right: 20rpx;
background-color: rgb(255, 207, 0);
padding: 10rpx 30rpx;
border-radius: 100rpx;
}
.btn {
background-color: $my-main-color;
color: #fff;
border: none;
padding: 10rpx 20rpx;
border-radius: 10rpx;
}
.hui {
// background-color: $quan-color;
background-image: linear-gradient(
to right bottom,
rgb(254, 103, 4),
rgb(241, 50, 42)
);
padding: 4rpx 10rpx;
border-radius: 10rpx;
font-size: 24rpx;
color: #fff;
}
.quan {
border: 1px solid rgb(238, 238, 238);
position: relative;
border-radius: 10rpx;
box-shadow: 0 0 5px #eee;
overflow: hidden;
.left {
max-width: 70%;
}
.sel {
padding: 2rpx 4rpx;
position: absolute;
background-color: $quan-color;
left: 0;
top: 0;
border-radius: 0 0 24rpx 0;
}
.right {
position: absolute;
top: 0;
right: 0;
bottom: 0;
padding: 20rpx 24rpx;
color: #fff;
display: flex;
flex-direction: column;
background-color: $quan-color;
height: 100%;
min-width: 180rpx;
}
&.goods {
.right {
background-color: #fff;
position: initial;
.use-btn {
padding: 10rpx 40rpx;
color: #fff;
background-color: $quan-color;
}
}
}
}
.bottom {
padding: 30rpx 30rpx 80rpx 30rpx;
}
</style>