Files
cashier_app/pagesCreateOrder/index/components/list-goods-item.vue

377 lines
8.9 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="u-relative u-flex item">
<up-image :src="data.coverImg" mode="aspectFill" :width="img.width" :height="img.height"></up-image>
<view class="info u-flex u-row-between u-col-top u-flex-col">
<view class="limit-discount" v-if="is_time_discount">限时折扣</view>
<view class="nowStockerNumber" v-if="nowStockerNumber<=10">
剩余库存{{nowStockerNumber}}
</view>
<view>
<view>
<text class="up-line-1">{{ data.name }}</text>
</view>
<view>
<text class="u-font-32 font-bold u-m-t-16" v-if="is_time_discount"> {{ limitPrice }} </text>
<text class="u-font-32 font-bold u-m-t-16" :class="[is_time_discount ? 'line-through' : '']">
{{ data.lowPrice }}
</text>
</view>
<template v-if="data.type == 'weight'">
<view class="btnweigh">称重</view>
</template>
</view>
<view class="u-flex" v-if="!isSellout">
<template v-if="data.type == 'sku' || data.groupType == 1">
<button class="btn" hover-class="btn-hover-class" @tap="emitEvent('chooseGuige')">
选规格
</button>
</template>
<template v-else>
<view class="u-flex icon-btn">
<template v-if="data.chooseNumber">
<view class="u-flex" @tap.stop="emitEvent('reduce')">
<image src="/pagesCreateOrder/static/images/icon-reduce.svg" class="icon" mode="">
</image>
</view>
<view class="u-font-32">
{{ data.chooseNumber.toFixed(2) }}
</view>
</template>
<view class="u-flex" @tap.stop="emitEvent(data.type == 'weight' ? 'tapweigh' : 'add')">
<image src="/pagesCreateOrder/static/images/icon-add.svg" class="icon" mode=""></image>
</view>
</view>
</template>
</view>
<template v-if="isSellout">
<view class="isSellout" v-if="data.isSale == 0">
<image class="isSellout_icon" src="/pagesCreateOrder/static/images/no-toDown.svg" mode=""></image>
</view>
<view class="isSellout" v-else-if="
!isProductAvailable(data.days, data.startTime, data.endTime)
">
<image class="isSellout_icon" src="/pagesCreateOrder/static/images/no-saleTime.svg" mode=""></image>
</view>
<view class="isSellout" v-else-if="data.isSoldStock == 1">
<image class="isSellout_icon" src="/pagesCreateOrder/static/images/no-sold.svg" mode=""></image>
</view>
<view class="isSellout" v-else>
<image class="isSellout_icon" src="/pagesCreateOrder/static/images/no-stock.svg" mode=""></image>
</view>
</template>
</view>
</view>
</template>
<script setup>
import {
computed,
toRef,
inject
} from "vue";
import util from "../util.js";
import dayjs from "dayjs";
import isBetween from "dayjs/plugin/isBetween.js";
const yskUtils = inject("yskUtils");
const shopInfo = inject("shopInfo");
dayjs.extend(isBetween);
const props = defineProps({
img: {
type: Object,
default: {
width: "250rpx",
height: "272rpx",
},
},
index: {
type: [Number, String],
},
isSeatFee: {
//是否为餐位费
type: Boolean,
default: false,
},
data: {
type: Object,
default: () => {
return {
chooseNumber: 0,
};
},
},
limitTimeDiscount: {
type: Object,
default: () => {
return {};
},
},
consStockList: {
type: Array,
default:[]
}
});
//判断是否是时间折扣商品
const is_time_discount = computed(() => {
if (!props.limitTimeDiscount || !props.limitTimeDiscount.id) {
return false;
}
const isCanuse = yskUtils.limitUtils.canUseLimitTimeDiscount(
props.data,
props.limitTimeDiscount,
shopInfo,
null,
"id"
);
return isCanuse;
});
const limitPrice = computed(() => {
if (!is_time_discount.value) {
return 0;
}
console.log("props.data", props.data);
const price = yskUtils.limitUtils.returnPrice({
goods: props.data,
shopInfo: shopInfo,
limitTimeDiscountRes: props.limitTimeDiscount,
shopUserInfo: null,
idKey: "id",
});
return price;
});
/**
* 判断是否是菜品
*/
function isGoods() {
return props.data.hasOwnProperty("id");
}
/**
* 判断商品是否售尽
*/
const isSellout = computed(() => {
const item = props.data;
if (!isGoods()) {
return false;
}
return (
!consStockisFull(item) ||
item.isSoldStock == 1 ||
item.isSale == 0 ||
!isProductAvailable(item.days, item.startTime, item.endTime)
);
});
const stockNumber=computed(()=>{
})
// 1. 筛选匹配的耗材列表
const conslist=computed(()=>{
if(props.consStockList.length<=0){
return []
}
return props.consStockList.filter(v => {
return props.data.consList.find(i =>{
return i.consInfoId == v.consId
});
});
})
// 2. 找到 stockNumber 最小的那一项
const minConsItem=computed(()=>{
if(conslist.value.length<=0){
return null
}
return conslist.value.reduce((prev, current) => {
return prev.stockNumber < current.stockNumber ? prev : current;
});
})
// 3. 找到和 minItem 的 consId 一样的那个消耗配置项
const targetCons=computed(()=>{
if(!minConsItem.value){
return null
}
return props.data.consList.find(i => i.consInfoId == minConsItem.value.consId);
})
const nowStockerNumber=computed(()=>{
if(!targetCons.value||!minConsItem.value){
return 9999
}
return Math.floor(minConsItem.value.stockNumber/targetCons.value.surplusStock)
})
function consStockisFull(item) {
// 无数据直接返回 true或按你需求返回 false
if (!conslist.value.length) return true;
if(!minConsItem.value)return true;
if(!targetCons.value) return true;
// 4. 判断:最小库存 > 每份消耗库存 → 返回 true否则 false
if (nowStockerNumber.value>=1) {
return true;
} else {
return false;
}
}
// 判断商品是否在可售时间内
function isProductAvailable(sellDaysStr, startTimeStr, endTimeStr) {
// 将后端返回的字符串转换为数组
const sellDays = sellDaysStr.split(",");
const now = dayjs();
const days = [
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
];
const currentDay = days[now.day()];
const currentTime = now.format("HH:mm:ss"); // 检查当前周几是否在可售周几列表中
// console.log('当前日期:', currentDay);
// console.log('可售日期列表:', sellDays);
if (!sellDays.includes(currentDay)) {
// console.log('当前日期不在可售日期列表中');
return false;
}
const startTime = dayjs(`${now.format("YYYY-MM-DD")} ${startTimeStr}`);
let endTime = dayjs(`${now.format("YYYY-MM-DD")} ${endTimeStr}`);
// 处理跨天情况
if (endTime.isBefore(startTime)) {
endTime = endTime.add(1, "day");
} // console.log('开始时间:', startTime.format('YYYY-MM-DD HH:mm:ss')); // console.log('结束时间:', endTime.format('YYYY-MM-DD HH:mm:ss'));
// console.log('当前时间:', now.format('YYYY-MM-DD HH:mm:ss'));
const isInRange = now.isBetween(startTime, endTime, null, "[)"); // console.log('当前时间是否在可售时间范围内:', isInRange);
return isInRange;
}
const emits = defineEmits(["add", "reduce", "chooseGuige", "tapweigh"]);
function emitEvent(emitName) {
if (isGoods()) {
emits(emitName, props.index);
}
}
</script>
<style lang="scss" scoped>
.icon {
width: 48rpx;
height: 48rpx;
}
.icon-btn {
gap: 14rpx;
}
.btn {
background: #eb4f4f;
border-radius: 100rpx;
font-size: 28rpx;
height: 56rpx;
line-height: 56rpx;
color: #fff;
}
.btnweigh {
margin: 5rpx 0;
width: 100rpx;
background: linear-gradient(124deg, #73c969 6%, #27921b 93%);
border-radius: 10rpx;
font-size: 24rpx;
padding: 6rpx 0;
text-align: center;
}
.btn-hover-class {
opacity: 0.6;
}
image {
will-change: transform;
}
.item {
// width: 250rpx;
// height: 272rpx;
background: #f9b798;
border-radius: 8rpx 8rpx 8rpx 8rpx;
overflow: hidden;
.img {
width: 250rpx;
height: 272rpx;
}
.info {
position: absolute;
left: 0;
right: 0;
bottom: 0;
color: #fff;
padding: 52rpx 24rpx 24rpx 24rpx;
top: 0;
background: rgba(37, 22, 15, 0.5);
border-radius: 8rpx 8rpx 8rpx 8rpx;
overflow: hidden;
}
}
.isSellout {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
background-color: rgba(0, 0, 0, 0.6);
display: flex;
justify-content: center;
align-items: center;
.isSellout_icon {
height: 60%;
width: 60%;
}
}
.limit-discount {
background-color: #cc5617;
padding: 10rpx 20rpx;
white-space: nowrap;
text-align: center;
position: absolute;
top: 0;
left: 0;
font-weight: 400;
font-size: 24rpx;
color: #ffffff;
border-radius: 0 0rpx 20rpx 0rpx;
color: #fff;
}
.line-through {
font-size: 24rpx;
color: rgba(255, 255, 255, 0.8);
text-decoration: line-through;
}
.nowStockerNumber{
position: absolute;
left: 24rpx;
bottom: 80rpx;
background-color: rgba(255, 255, 255, .8);
color: red;
padding: 4rpx 8rpx;
font-size: 24rpx;
border-radius: 4rpx ;
}
</style>