cashier-ipad/pagesOrder/quan/quan.vue

779 lines
19 KiB
Vue

<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 couponUtils from "./coupon";
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";
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 querForm = ref({
searchValue: "",
shopId: "",
shopName: "",
statusActiveIndex: 0,
});
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];
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.code == 200) {
order.value = orderRes.data;
}
console.log(order.value);
const res = await $findCoupon({
shopUserId: option.shopUserId,
});
couponList.value = res.data || [];
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);
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.code == 200) {
shopUserInfo.value = res.data;
}
}
onLoad(async (opt) => {
Object.assign(option, opt);
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%;
}
&.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>