You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

680 lines
20 KiB
Vue

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<view>
<view style="display: flex;flex-direction: column;height: 100vh;background: #F6D13A;" :style="{
background: mch && mch.main_color ? mch.main_color : (mch ? '#F6D13A' : '#F0F0F0')
}">
<view class="hearder-box" style="" v-if="mch">
<view style="display: flex;align-items: center;">
<view style="flex: 1;">
<u-search placeholder="请输入搜索商品名称" v-model="keyword" @search="getData"
@custom="getData"></u-search>
</view>
<view v-if="table" style="font-size: 32rpx;font-weight: bold;margin-left: 20rpx;">
桌号:{{ table.number }}
</view>
</view>
<view style="display: flex;align-items: center;justify-content: space-between;margin-top: 20rpx;">
<view style="display: flex;align-items: center;">
<view style="margin-right: 20rpx;">
<image style="width: 60rpx;height: 60rpx;border-radius: 20rpx;" :src="mch.logo_url"></image>
</view>
<view style="color: #000;font-weight: 600;">
{{ mch.name }}
</view>
<view>
<u-icon name="arrow-right" color="#262626" size="15"></u-icon>
</view>
</view>
<view style="font-size: 28rpx;font-weight: 600;"
v-if="mch.business_hours && mch.business_hours.length > 0">
<!-- <text style="color: #000;">10:30-22:40</text> -->
<view style="margin-left: 20rpx;color: #000;" v-for="(items, i) of mch.business_hours" :key="i">
{{ items.join('-') }}
</view>
</view>
</view>
<view style="margin-top: 14rpx;">
<u-icon @click="openLocation(mch)" name="map" :label="mch.detail || mch.name" labelColor="#a8a8a8"
color="#a8a8a8" size="12" label-size="12"></u-icon>
</view>
</view>
<view class="content-box" style="overflow: hidden;">
<!-- 左侧菜单 -->
<view class="left-tab" style="overflow-y: scroll;background: #F0F0F0;">
<template v-if="cat_list && cat_list.length > 0">
<view v-for="(item, index) in cat_list" class="cat-item" @click="updateCatIndex(item.id, index)"
:class="cat_index == index ? 'cat-item-active' : ''">
<template v-if="item.id">
<view v-if="item.pic_url">
<image style="width: 60rpx;height: 60rpx;" :src="item.pic_url" mode=""></image>
</view>
<view :style="{
lineHeight: item.pic_url ? '40rpx' : '60rpx'
}">
{{ item.name }}
</view>
</template>
<template v-else>
<view>
<image style="width: 60rpx;height: 60rpx;" src="@/static/image/bixuan.png" mode="">
</image>
</view>
<view :style="{
lineHeight: '40rpx'
}">
{{ item.name }}
</view>
</template>
</view>
</template>
<template v-else>
<view style="padding: 80rpx 0;">
<u-empty iconSize="80rpx" mode="list"></u-empty>
</view>
</template>
<view style="height: 180rpx;width: 100%;"></view>
</view>
<!-- 右侧菜单 -->
<view class="right-tab" style="display: flex;flex-direction: column;position: relative;">
<view style="flex: 1;position: relative;">
<scroll-view :scroll-into-view="'cat_id_' + cat_id" @scroll="scrollRight"
style="position: absolute;top: 0;right: 0;bottom: 0;left: 0;padding: 20rpx;" :scroll-y="true">
<view v-for="cat_item in cat_list" :id="'cat_id_' + cat_item.id">
<view style="margin-bottom: 20rpx;" >
{{ cat_item.name }}
</view>
<view v-for="(item, index) in cat_item.goods_list" @click="show_goods_id = item.goods_id"
style="display: flex;width: 100%;background: #FFF;border-radius: 14rpx;box-shadow: 0px 0px 8rpx 0px rgba(0, 0, 0, 0.1);margin-bottom: 20rpx;overflow: hidden;">
<view style="background: #F0F0F0;">
<image style="display: block;width: 200rpx;height: 200rpx;"
:src="item.goods_info.pic_url" mode="aspectFill"></image>
</view>
<view
style="flex: 1;padding: 10rpx 14rpx;display: flex;flex-direction: column;justify-content: space-between;">
<view>
<view class="goods_name">{{ item.goods_info.name }}</view>
<view style="color: #A16222;font-weight: bold;margin-top: 16rpx;">
¥{{ item.goods_info.price_min }}
</view>
</view>
<view style="display: flex;justify-content: flex-end;">
<view @click.stop="chooseSpecifications(item, $event)" :data-index="index">
<u-icon name="plus-circle-fill"
:color="mch && mch.main_color ? mch.main_color : '#A16222'"
size="50rpx"></u-icon>
</view>
</view>
</view>
</view>
</view>
<view style="height: 180rpx;width: 100%;"></view>
</scroll-view>
</view>
</view>
</view>
</view>
<view class="bttom-box" style="padding: 0 30rpx;" v-show="1 || goodsArr.reduce((sum, item) => sum + (item.num - 0), 0) > 0">
<view
style="padding: 10rpx 20rpx;display: flex;align-items: center;justify-content: space-between;position: relative;z-index: 1;background: #FFF;width: 100%;border-radius: 70rpx;border: 2rpx solid #F0F0F0;">
<view style="display: flex;align-items: center;">
<view @click="show_card = !show_card"
style="width: 100rpx;height: 100rpx;background: #FFF;border-radius: 50%;display: flex;align-items: center;justify-content: center;position: relative;">
<u-icon size="90rpx" name="shopping-cart"
:color="mch && mch.main_color ? mch.main_color : '#A16222'"></u-icon>
<view
style="position: absolute;background: #BD3124;color: #FFF;font-size: 20rpx;line-height: 30rpx;padding: 0 10rpx;border-radius: 15rpx;right: 0;top: 0;">
{{ goodsArr.reduce((sum, item) => sum + (item.num - 0), 0) }}
</view>
</view>
<view style="margin-left: 40rpx;color: #000;font-weight: bold;font-size: 40rpx;">
¥{{ totalPrice }}
</view>
</view>
<view @click="toSubmit" :style="{
background: mch && mch.main_color ? mch.main_color : '#A16222'
}" style="color: #FFF;padding: 0 40rpx;line-height: 80rpx;border-radius: 40rpx;font-size: 32rpx;">
去下单
</view>
</view>
<view style="position: fixed;bottom: 0;top: 0;left: 0;right: 0;background: rgba(0, 0, 0, .2);"
@click="show_card = !show_card" v-if="show_card">
<view :style="{
maxHeight: show_card ? '60vh' : '0'
}" style="position: absolute;left: 0;right: 0;bottom: 0;background: #FFF;border-radius: 20rpx 20rpx 0 0;z-index: 0;transition: max-height 0.5s;overflow-y: scroll;">
<view
style="padding: 20rpx 30rpx;border-bottom: 1rpx solid #F0F0F0;position: sticky;top: 0;z-index: 3;background: #FFF;">
购物车({{ goodsArr.reduce((sum, item) => sum + (item.num - 0), 0) }})
</view>
<view style="padding: 20rpx;flex: 1;overflow-y: scroll;">
<view v-for="(item, index) in goodsArr" v-if="item.num > 0"
style="display: flex;width: 100%;background: #f7f7f7;border-radius: 14rpx;margin-bottom: 20rpx;overflow: hidden;padding: 16rpx;">
<view style="overflow: hidden;">
<image style="display: block;width: 140rpx;height: 140rpx;border-radius: 18rpx;"
:src="item.goods.pic_url" mode="aspectFill"></image>
</view>
<view
style="flex: 1;padding: 10rpx 14rpx;display: flex;flex-direction: column;justify-content: space-between;">
<view>
<view class="goods_name" style="-webkit-line-clamp: 1;font-size: 20rpx;">
{{ item.goods.name }}
</view>
</view>
<view class="item-desc" style="margin: 10rpx 0;">
<view class="goods_sky" style="color: #999;font-size: 24rpx;">
<text v-for="(sku, _index) of item.activeGoodsInfo.attr_list" :key="_index">
{{ sku.group_name }}{{ sku.name }}
</text>
</view>
</view>
<view style="display: flex;">
<view v-for="(small, index) of item.small_goods" :key="index"
v-show="small.group_item.length != 0">
<view
style="display: flex;background: #FFF;margin: 0 10rpx 10rpx 0;font-size: 22rpx;padding: 10rpx 20rpx;flex-wrap: nowrap;align-items: center;border-radius: 10rpx;justify-content: center;"
v-for="sitem of small.group_item">
<view>
{{ sitem.name }}
</view>
<view v-if="sitem.price" style="color:#BD3124;">
{{ sitem.price }} 元
</view>
</view>
</view>
</view>
<view style="display: flex;justify-content: space-between;align-items: center;">
<view style="color: #A16222;font-weight: bold;">
¥{{ item.activeGoodsInfo.price }}
</view>
<u-number-box :min="0" v-model="item.num"></u-number-box>
</view>
</view>
</view>
</view>
<view style="height: 180rpx;"></view>
</view>
</view>
</view>
<logins v-if="wcCode != -1" :wcCode="wcCode"
:type="$utils.isInAliBrowser() || $utils.isInWeChatBrowser() ? 0 : 2" @isLogin="getCatList"></logins>
<pageSku v-if="goods.id" ref="pagesku" :goods="goods" @skuPopData="skuPopData"></pageSku>
<view v-if="show_donghua == 1" :animation="animationData"
style="position: fixed;right: 32rpx;top: 600rpx;z-index: 10;" :style="{
top: top + 'px'
}">
<!-- <image style="width: 50rpx;height: 50rpx;" src="../my/images/av.png" mode=""></image> -->
<u-icon size="50rpx" name="plus-circle-fill" :color="mch && mch.main_color ? mch.main_color : '#A16222'"
style="background: #fff;border-radius: 50%;"></u-icon>
</view>
<goods v-if="show_goods_id > 0" :goods_id="show_goods_id" @close="show_goods_id = 0"></goods>
<u-popup mode="bottom" :show="show_ren" round="20rpx">
<view v-if="ren_setting" style="padding-bottom: 50rpx;font-size: 40rpx;">
<view style="text-align: center;line-height: 80rpx;font-size: 34rpx;">
请选择人数
</view>
<view style="display: flex;flex-wrap: wrap;">
<view v-for="(item, index) in (ren_setting.max_num - ren_setting.min_num + 1)">
<view @click="table_num = index + (ren_setting.min_num - 0);show_ren = false"
style="padding: 30rpx 40rpx;margin: 20rpx;background: #F0F0F0;border-radius: 10rpx;">
{{ index + (ren_setting.min_num - 0) }}
</view>
</view>
</view>
</view>
</u-popup>
</view>
</template>
<script>
import logins from '@/components/login/logins.vue'
import pageSku from "./compontents/page-sku.vue";
import goods from "./compontents/goods.vue";
export default {
components: {
logins,
pageSku,
goods
},
data() {
return {
wcCode: -1,
mch_id: 0,
store_id: 0,
n_id: 0,
cat_id: 0,
cat_index: 0,
goods_loading: 0,
cat_list: [],
mch: null,
table: null,
goods: {},
goodsArr: [],
show_card: false,
top: 0,
show_donghua: 0,
animationData: {},
animation: null,
cartData: null,
is_cont: 0,
show_goods_id: 0,
keyword: '',
start_i: 0,
end_i: 0,
required_list: [], // 必选订单
show_ren: false,
ren_setting: null,
table_num: 0,
distanceArr: []
}
},
watch: {},
async onLoad(query) {
let that = this
if (query.wxcode) {
uni.getStorage({
key: 'take_query',
success(res) {
if (!res.data.mch_id) {
uni.showModal({
title: '提示',
showCancel: false,
content: JSON.stringify(res)
})
} else {
that.mch_id = res.data.mch_id
that.store_id = res.data.store_id
that.n_id = res.data.n_id
that.is_cont = res.data.is_cont ? 1 : 0
that.$nextTick(() => {
that.wcCode = query.wxcode
})
}
},
fail(res) {
uni.showModal({
title: '提示',
showCancel: false,
content: JSON.stringify(res)
})
}
})
} else {
this.mch_id = query.mch_id
this.store_id = query.store_id
this.n_id = query.n_id
if (query.mch_id) {
uni.setStorage({
data: {
mch_id: query.mch_id,
store_id: query.store_id,
n_id: query.n_id,
is_cont: query.is_cont,
},
key: 'take_query',
success() {
that.is_cont = query.is_cont ? 1 : 0
that.wcCode = ''
if (!that.$utils.isInAliBrowser() && !that.$utils.isInWeChatBrowser()) {
that.getCatList()
}
},
fail(res) {
uni.showModal({
title: '提示',
showCancel: false,
content: JSON.stringify(res)
})
}
})
} else {}
}
},
//发送给朋友
onShareAppMessage(res) {},
onPullDownRefresh() {},
onShow() {
},
onReady() {
setTimeout(() => {
let view = uni.createSelectorQuery().select(".bttom-box");
if (view) {
view.boundingClientRect(data => {
this.cartData = data
}).exec();
}
}, 200)
},
onHide() {},
computed: {
totalPrice() {
return this.goodsArr.reduce((pre, cur) => {
let price = cur.activeGoodsInfo.price * cur.num
// 计算小料
let smallMaterialPrice = 0
if (cur.small_goods) {
smallMaterialPrice = cur.small_goods.reduce((price, item) => {
return price + item.group_item.reduce((price, item) =>
price + item.price, 0)
}, 0)
}
smallMaterialPrice = cur.num * (Number(smallMaterialPrice))
return pre + Number(price) + smallMaterialPrice;
}, 0).toFixed(2);
},
},
methods: {
getData() {
this.cat_list = []
this.$nextTick(() => {
this.getCatList({
store_id: this.store_id,
mch_id: this.mch_id,
n_id: this.n_id,
})
})
},
async getCatList() {
uni.showLoading({
title: '加载中'
})
let res = await this.$api.common.getFootCatAll({
store_id: this.store_id,
mch_id: this.mch_id,
n_id: this.n_id,
keyword: this.keyword
})
uni.hideLoading()
if (res.code > 0) {
uni.showModal({
title: '提示',
content: res.msg,
showCancel: false,
success() {}
})
} else {
if (res.data.is_more && res.data.is_more > 0 && this.is_cont == 0) {
uni.reLaunch({
url: '/pages/takeaway/orderAndSettlement/edit?n_id=' + this.n_id + '&mch_id=' +
this.mch_id + '&store_id=' + this.store_id
})
}
if (res.data.cat_list && res.data.cat_list.length > 0) {
this.cat_id = res.data.cat_list[0].id
}
this.cat_list = res.data.cat_list
this.mch = res.data.mch
this.table = res.data.table
setTimeout(() => {
this.getDistanceArr()
}, 1500)
}
this.showRen()
},
getDistanceArr () {
const _this = this
let topHeard = 0
_this.distanceArr = []
_this.cat_list.map(el => {
uni.createSelectorQuery().select('#cat_id_' + el.id).boundingClientRect(data => {
// console.log(data, 'data')
if (_this.distanceArr.length == 0) {
topHeard = data.top
_this.distanceArr.push(0)
} else {
_this.distanceArr.push(data.top - topHeard)
}
}).exec()
})
},
// 选择规格
async chooseSpecifications(params, e) {
uni.showLoading({
title: "请稍等",
mask: true,
});
this.goods = {};
await this.$nextTick()
const res = await this.$api.common.goodsInfo({
id: params.goods_id
});
this.goods = res.data
await this.$nextTick()
await this.setStart(e)
setTimeout(async () => {
uni.hideLoading();
this.$refs.pagesku.skuPopData.type = 2;
this.$refs.pagesku.$refs?.popup?.open();
}, 0)
},
async skuPopData(e) {
const goods = this.goodsArr.find(item => item.goods_sku_id === e.goods_sku_id && item
.small_goods_json ===
e.small_goods_json)
if (goods) {
let goodsArr = this.goodsArr
this.goodsArr.forEach((item, index) => {
if (item.goods_sku_id === e.goods_sku_id && item.small_goods_json === e
.small_goods_json) {
this.goodsArr[index].num = (this.goodsArr[index].num - 0) + 1
}
})
this.goodsArr = []
this.goodsArr = goodsArr
} else {
e.key = Math.random()
this.goodsArr.push(JSON.parse(JSON.stringify(e)))
}
console.log(this.goodsArr)
await this.$nextTick()
this.setA()
},
setStart(e) {
this.top = e.detail.y
var animation = uni.createAnimation({
duration: 600,
timingFunction: 'ease',
})
this.animation = animation
this.animationData = animation.export()
},
setA() {
this.show_donghua = 1
// 先旋转后放大
this.animation.translate('-600rpx', (this.cartData.top - this.top)).step()
this.animationData = this.animation.export()
setTimeout(() => {
this.show_donghua = 0
this.$nextTick(() => {
this.animation.translate('600rpx', -(this.cartData.top - this.top)).step()
this.animationData = this.animation.export()
})
}, 600)
},
updateCatIndex(id, index) {
if (this.cat_id == 0 && id != 0) {
if (!this.verRequired()) {
uni.showToast({
icon: 'none',
title: '请选择必选商品'
})
} else {
this.cat_id = id
}
} else {
this.cat_id = id
}
this.cat_index = index
},
// 验证必点商品是否已点
verRequired() {
let that = this
let goodsArr = this.goodsArr.filter(item => item.num > 0)
let required_list = that.required_list.filter((item) => {
return goodsArr.filter((item1) => {
return item.goods_info.id == item1.goods.id
}).length > 0 ? true : false
})
return that.required_list.length <= required_list.length
},
toSubmit() {
let goodsArr = this.goodsArr.filter(item => item.num > 0)
if (!goodsArr.length) {
uni.$u.toast("请选择点餐商品")
return
}
if (this.required_list && this.required_list.length > 0) {
if (!this.verRequired()) {
uni.$u.toast("请选择必选商品")
return
}
}
let that = this
uni.setStorage({
key: 'take_n_id_' + this.n_id,
data: goodsArr,
success() {
uni.navigateTo({
url: "/pages/takeaway/orderAndSettlement/index?" + "n_id=" + that.n_id +
"&mch_id=" + that.mch_id + "&store_id=" + that.store_id + "&table_num=" +
that.table_num,
});
}
})
},
async showRen() {
this.goods = {};
await this.$nextTick()
const res = await this.$api.common.getRen({
store_id: this.store_id,
mch_id: this.mch_id,
n_id: this.n_id,
});
if (res.code == 0) {
this.show_ren = true
this.ren_setting = res.data
}
},
async scrollRight(event) {
let scrollTop = event.detail.scrollTop
let cat_index = this.cat_index
await this.distanceArr.forEach((item, index) => {
if ((scrollTop + 5) > item) {
cat_index = index
}
})
this.cat_index = cat_index
return;
}
}
}
</script>
<style lang="scss" scoped>
.hearder-box {
// background: linear-gradient(to bottom, #D6BDA3, #F3EEE8);
// background: #FFF;
padding: 20rpx;
}
.content-box {
display: flex;
flex: 1;
background: blue;
border-radius: 20rpx 20rpx 0 0;
overflow: hidden;
.left-tab {
width: 160rpx;
height: 100%;
background: #E3DAD0;
}
.right-tab {
flex: 1;
height: 100%;
background: #FFF;
}
}
.bttom-box {
// padding-bottom: constant(safe-area-inset-bottom);
// padding-bottom: env(safe-area-inset-bottom);
height: 180rpx;
background: rgba(0, 0, 0, 0);
display: flex;
align-items: flex-start;
width: calc(100% - 0rpx);
position: fixed;
left: 0;
right: 0;
bottom: 0rpx;
padding: 0 10rpx;
}
.cat-item {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-size: 30rpx;
padding: 20rpx;
color: #666666;
}
.cat-item-active {
background: #FFF;
color: #000;
font-weight: bold;
}
.goods_name {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
/* 定义文本的行数 */
overflow: hidden;
text-overflow: ellipsis;
font-size: 28rpx;
}
.minus {
border: 1px solid #e5e5e5;
border-right: none;
border-radius: 20px 0 0 20px;
padding: 6px;
}
.plus {
border: 1px solid #e5e5e5;
border-left: none;
border-radius: 0 20px 20px 0;
padding: 6px;
}
.numInput {
width: 35px;
text-align: center;
border: 1px solid #e5e5e5;
padding: 3px 0;
height: 20px;
line-height: 20px;
font-size: 12px;
color: #000;
}
</style>