cashier-web/src/views/tool/Instead/components/carts/item.vue

546 lines
13 KiB
Vue

<template>
<div class="flex order-item u-m-b-14 relative" :class="[isActive]" @click="itemClick">
<div class="absolute status-box">
<template v-if="isOld">
<span class="pack" v-if="dinerType == 1">
<span class="number">{{ item.product_type == "weight" ? 1 : item.num * 1 }}</span>
</span>
<span class="pack" v-if="dinerType == 0 && item.pack_number * 1 > 0">
<span class="number">{{ item.product_type == "weight" ? 1 : item.num * 1 }}</span>
</span>
</template>
<template v-else>
<span class="pack" v-if="item.pack_number * 1 > 0">
<span class="number">{{ item.pack_number * 1 }}</span>
</span>
</template>
<span class="da" v-if="item.is_print || item.is_print === null">打</span>
<span class="isWaitCall" v-if="item.is_wait_call">等</span>
<span class="tui" v-if="item.returnNum">
退
<span class="number">{{ item.returnNum * 1 }}</span>
</span>
</div>
<div class="flex u-col-top">
<div class="img">
<div class="xszk" v-if="item.isLimitDiscount || item.is_time_discount">限时折扣</div>
<div class="isSeatFee img u-line-1 u-flex u-col-center u-row-center" v-if="isSeatFee">
<span>{{ item.name }}</span>
</div>
<div class="isSeatFee img u-line-1 u-flex u-col-center u-row-center" v-else-if="item.is_temporary">
<span>临时菜</span>
</div>
<img v-else :src="item.coverImg" class="" alt="" />
</div>
<div class="good-info u-p-t-6">
<div class="flex lh-16">
<div class="name" :class="{ 'free-price': item.status === 'return' }">
{{ item.name || item.product_name }}
</div>
<span class="good_info_discount" v-if="item.is_gift">赠</span>
</div>
<div v-if="item.typeEnum == 'weight'" class="specSnap">
¥{{ currentPrice }}/{{ item.unit }}
</div>
<div v-if="item.specInfo" class="specSnap">
{{ item.specInfo }}
</div>
<div v-if="item.proGroupInfo" class="specSnapss">
<span>{{ item.groupType == 0 ? "固定套餐" : "可选套餐" }}:</span>
<span v-for="(a, b) in proGroupInfo" :key="a.proId">
{{ b == 0 ? "" : "," }}{{ a.proName }}
</span>
</div>
<div class="" v-if="placeNum == 0">
<div class="note" v-if="item.remark">备注:{{ item.remark }}</div>
<div class="note flex" v-else>
<span>备注:</span>
<el-icon v-if="!isOld" @click="editNote" color="#999">
<EditPen />
</el-icon>
</div>
</div>
<div class="note" v-if="placeNum != 0 && item.note">备注:{{ item.remark || "" }}</div>
</div>
</div>
<div style="width: 10px"></div>
<div class="flex">
<div class="order-number-box u-font-12">
<div class="" v-if="isSeatFee">X{{ item.totalNumber }}</div>
<div class="" v-else>X{{ item.number }}</div>
<div class="absolute" v-if="canChangeNumber">
<div class="order-input-number">
<el-icon color="#d8d8d8" size="22" @click="changeOrderNumber(-1)">
<Remove />
</el-icon>
<div style="width: 60px; margin: 0 4px" class="number-box">
<el-input :min="0" type="number" @input="cartGoodsNumberInput" @change="cartGoodsNumberChange"
v-model="number" placeholder="0"></el-input>
</div>
<el-icon color="#22bf64" size="22" @click="changeOrderNumber(1)">
<CirclePlusFilled />
</el-icon>
</div>
</div>
</div>
<div class="color-333 total-price">
<template v-if="item.is_gift || item.status == 'return'">
<div>¥0</div>
<div class="free-price">
<span v-if="isSeatFee">¥{{ to2(item.totalAmount) }}</span>
<span v-else>¥{{ to2(useVipPrice ? vipAllPrice : allPrice) }}</span>
</div>
</template>
<!-- 单品改价 -->
<template v-else-if="
item.discount_sale_amount * 1 > 0 &&
discount_before_price != allPrice &&
!item.is_temporary
">
<div>¥{{ to2(allPrice) }}</div>
<div class="free-price">
<span>¥{{ to2(discount_before_price) }}</span>
</div>
</template>
<template v-else>
<div v-if="item.isLimitDiscount || item.is_time_discount">
<div>
¥{{ to2(item.limitDiscountPrice) }}
</div>
<div class="free-price">
<span>¥{{ to2(item.salePrice) }}</span>
</div>
</div>
<div v-else>
<div v-if="useVipPrice && vipAllPrice * 1 != allPrice * 1">
¥{{ to2(vipAllPrice) }}
</div>
<div :class="{
'free-price': useVipPrice && vipAllPrice != allPrice,
}">
<span>{{ to2(allPrice) }}</span>
</div>
</div>
</template>
</div>
</div>
</div>
</template>
<script setup>
import { customTruncateToTwoDecimals } from "@/views/tool/Instead/util";
const props = defineProps({
dinerType: {
type: [Number, String],
default: 0, //0 堂食 1 自取
},
useVipPrice: {
type: Boolean,
default: false,
},
//是否是餐位费
isSeatFee: {
type: Boolean,
default: false,
},
//是否是历史订单商品
isOld: {
type: Boolean,
default: false,
},
//第几次下单 1以及以上为历史订单 0为当前购物车
placeNum: {
type: [String, Number],
default: 0,
},
selPlaceNum: {
type: [String, Number],
default: -1,
},
//是否允许改变数量
canChangeNumber: {
type: Boolean,
default: true,
},
item: {
type: Object,
default: () => {
return {
number: 0,
};
},
},
selCart: {
type: Object,
default: () => {
return {
id: "",
};
},
},
index: {
type: Number,
default: 0,
},
});
function to2(n) {
return customTruncateToTwoDecimals(n);
}
let number = ref(0);
const currentPrice = computed(() => {
return 0;
});
const proGroupInfo = computed(() => {
try {
return JSON.parse(props.item.proGroupInfo);
} catch (e) {
return [];
}
});
const vipAllPrice = computed(() => {
const n = (props.item.memberPrice || props.item.salePrice) * props.item.number;
return n;
});
const allPrice = computed(() => {
console.log("allPrice", props.item);
if (props.item.discount_sale_amount * 1 > 0) {
return props.item.discount_sale_amount * props.item.number;
}
if (props.useVipPrice) {
const memberPrice = props.item.memberPrice || props.item.salePrice;
return memberPrice * props.item.number;
}
if (
props.item.hasOwnProperty("discount_sale_amount") &&
props.item.discount_sale_amount * 1 != 0
) {
return props.item.number * props.item.discount_sale_amount;
}
return props.item.number * props.item.salePrice;
});
const discount_before_price = computed(() => {
if (props.useVipPrice) {
return props.item.number * (props.item.memberPrice || props.item.salePrice);
}
return props.item.number * props.item.salePrice;
});
const isActive = computed(() => {
return props.item.id == props.selCart.id ? "active" : "";
});
watch(
() => props.item.number,
(newval) => {
console.log(newval);
number.value = newval;
}
);
const emits = defineEmits([
"editNote",
"cartGoodsNumberChange",
"cartGoodsNumberInput",
"changeNumber",
"itemClick",
]);
function editNote() {
emits("editNote");
}
//购物车商品输入框数量改变
function cartGoodsNumberChange(newval) {
if (newval <= 0) {
item.number = 1;
}
newval = `${newval}`.split(".")[0] * 1;
number.value = newval;
changeOrderNumber(newval - props.item.number);
}
//购物车商品输入框数量输入
function cartGoodsNumberInput(newval) {
if (newval <= 0) {
return (number.value = 1);
}
newval = `${newval}`.split(".")[0] * 1;
number.value = newval;
}
function changeOrderNumber(step) {
emits("changeNumber", step, props.item);
}
function itemClick() {
emits("itemClick");
}
onMounted(() => {
number.value = props.item.number;
});
</script>
<style lang="scss" scoped>
:deep(.number-box .el-input__inner) {
border: none;
}
:deep(.el-button--text) {
color: #000;
}
:deep(.number-box .el-input__inner) {
border: none;
padding: 0 4px;
text-align: center;
}
.isSeatFee {
background: #3f9eff;
color: #fff;
font-size: 12px;
}
.icon-remove {
border: 1px solid #d8d8d8;
width: 22px;
height: 22px;
display: flex;
justify-content: center;
align-items: center;
border-radius: 50%;
box-sizing: border-box;
cursor: pointer;
&::after {
content: "";
display: block;
width: 10px;
height: 1px;
background: #999;
}
}
.icon-add {
color: rgb(34, 191, 100);
font-size: 22px;
cursor: pointer;
}
.flex.order-item {
padding: 4px;
border-radius: 2px;
display: flex;
overflow: visible;
cursor: pointer;
align-items: flex-start;
justify-content: space-between;
background-color: rgba(0, 0, 0, 0);
transition: all 0.3s;
.status-box {
width: 18px;
position: absolute;
top: 4px;
right: 100%;
display: flex;
flex-direction: column;
gap: 2px;
>span {
display: block;
width: 18px;
height: 18px;
border-radius: 4px 0 4px 0;
font-size: 12px;
line-height: 17px;
text-align: center;
color: #fff;
}
}
.isWaitCall {
background: #d3adf7;
}
.pack {
background: #35ac6a;
.number {
background: #f56c6c;
color: #fff;
position: absolute;
left: -7px;
top: -7px;
width: 14px;
height: 14px;
text-align: center;
border-radius: 50%;
}
}
.tui {
position: relative;
.number {
background: #f56c6c;
color: #fff;
position: absolute;
left: -7px;
top: -7px;
width: 14px;
height: 14px;
text-align: center;
border-radius: 50%;
}
}
.da {
background: #35ac6a;
}
.tui {
background: #ac4735;
}
&.active {
background-color: rgba(0, 0, 0, 0.04);
}
.total-price {
width: 94px;
font-size: 16px;
text-align: right;
}
.good-info {
display: flex;
flex-direction: column;
justify-content: center;
min-width: 70px;
.specSnap {
color: #999;
font-size: 12px;
margin-top: 3px;
}
.specSnapss {
display: flex;
justify-content: flex-start;
align-items: center;
flex-wrap: wrap;
color: #999;
font-size: 12px;
margin-top: 3px;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
.specSnap {
color: #999;
font-size: 12px;
margin-top: 3px;
}
}
}
.name {
font-size: 13px;
text-align: left;
color: #212121;
overflow: hidden;
line-height: 1;
}
.img {
width: 59px;
height: 59px;
position: relative;
margin-right: 10px;
.xszk {
padding: 2px 4px 2px 6px;
background-color: var(--el-color-danger);
position: absolute;
top: 0;
right: 0;
z-index: 10;
color: #fff;
font-size: 8px;
}
img {
width: 59px;
height: 59px;
}
}
}
.note {
max-width: 70%;
font-size: 12px;
font-weight: 400;
text-align: left;
color: #999;
margin-top: 5px;
word-break: break-all;
}
.order-number-box {
position: relative;
.absolute {
width: 60px;
height: 40px;
right: -38px;
top: -14px;
position: absolute;
.order-input-number {
position: absolute;
right: -6px;
top: 0;
justify-content: center;
align-items: center;
display: none;
background-color: #fff;
border: 1px solid #e4e7ed;
border-radius: 4px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.06);
padding: 9px 6px;
background-color: #fff;
height: 40px;
}
&:hover .order-input-number {
display: flex;
}
}
}
.good_info_discount {
height: 16px;
padding: 0 3px;
color: #ff3f3f;
background-color: rgba(255, 63, 63, 0.1);
border-radius: 2px;
margin-left: 6px;
font-size: 12px;
line-height: 1;
white-space: nowrap;
}
:deep(.order-input-number .el-input__inner::-webkit-inner-spin-button) {
-webkit-appearance: none;
margin: 0;
}
:deep(.order-input-number .el-input__inner::-webkit-outer-spin-button) {
-webkit-appearance: none;
margin: 0;
}
</style>