546 lines
13 KiB
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> |