zhwl-miniapp/pages/eatery/index.vue
2025-06-26 12:38:35 +08:00

220 lines
12 KiB
Vue

<template>
<view class="waper">
<mescroll-body @init="mescrollInit" @down="downCallback" @up="upCallback" :down="downOption" :up="upOption" v-if="detail">
<u-navbar :autoBack="true" :bgColor="scrollTop > 20 ? '#fff' : 'transparent'" :left-icon-color="scrollTop > 20 ? '#303133' : '#FFF'">
<view slot='center' class="navbar_title">{{scrollTop > 20 ? '餐饮美食' : ''}}</view>
</u-navbar>
<view class="banner">
<image :src="$utils.setImgUrl(detail.image)" mode="" />
</view>
<view class="content">
<view class="menu">
<scroll-view scroll-x="true">
<view class="menu_waper">
<view v-for="(i, index) in detail.children" :key="index" :class="{ active: menuActive == index }" @click="tabMenu(index)">{{i.name}}</view>
</view>
</scroll-view>
</view>
<view class="content_waper" v-if="detail.children[menuActive].type == 'list'">
<view class="list" v-for="(item, itemIndex) in list" :key="itemIndex">
<navigator hover-class="none" class="info" :url="'/pages/eatery/detail?id=' + item.id">
<view class="img">
<image :src="$utils.setImgUrl(item.image)" mode=""></image>
</view>
<view class="text">
<view class="title">{{item.title}}</view>
<view class="tag" v-if="item.keywords">
<view v-for="(i, index) in item.keywords.split(',')" :key="index">{{i}}</view>
</view>
<view class="msg">{{item.description}}</view>
</view>
</navigator>
<view class="store" v-if="item.eateryShopList && item.eateryShopList.length > 0">
<scroll-view scroll-x="true" class="scroll-view">
<navigator hover-class="none" v-for="(i, index) in item.eateryShopList" :key="index" class="shop_list" :url="'/pages/eatery/shopDetail?id=' + i.id">
<image :src="$utils.setImgUrl(i.doorImage)" mode=""></image>
<view>{{i.shopName}}</view>
</navigator>
</scroll-view>
</view>
</view>
</view>
<view class="content_waper" v-else>
<navigator hover-class="none" class="store_list" v-for="(i, index) in list" :key="index" :url="'/pages/eatery/shopDetail?id=' + i.id">
<view class="left">
<image :src="$utils.setImgUrl(i.doorImage)" mode=""></image>
</view>
<view class="right">
<view class="title">{{i.shopName}}</view>
<view class="infos">
<view class="infos_left">
<view class="tag">{{i.shopCuisine}}</view>
<view class="money">¥{{i.averageConsumption || 0}}/人</view>
</view>
<view class="site" v-if="location">{{getDistance(i)}}</view>
</view>
<view class="msg" v-if="i.beginTime">
<view class="icon">
<u-icon size="28rpx" name="clock" color="rgba(0, 0, 0, 0.65)"></u-icon>
</view>
<view class="text">{{i.beginTime ? (i.beginTime.split(':')[0] <= 12 ? '上午' : '下午') : ''}}{{ i.beginTime }}-{{i.endTime ? (i.endTime.split(':')[0] <= 12 ? '上午' : '下午') : ''}}{{ i.endTime }}</view>
</view>
<view class="msg" :style="i.beginTime ? 'margin-top: 8rpx;' : ''">
<view class="icon">
<u-icon size="30rpx" name="map" color="rgba(0, 0, 0, 0.65)"></u-icon>
</view>
<view class="text">{{i.shopAddress}}</view>
</view>
</view>
</navigator>
</view>
</view>
</mescroll-body>
</view>
</template>
<script>
import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
export default {
mixins: [MescrollMixin],
data () {
return {
downOption: { use: false },
scrollTop: 0,
detail: null,
menuActive: 0,
list: [],
location: null
}
},
onPageScroll (e) {
this.scrollTop = e.scrollTop;
},
async onLoad () {
uni.getLocation({
type: 'gcj02',
isHighAccuracy: true,
success: (res) => {
console.log(res)
let latitude = res.latitude;
let longitude = res.longitude;
this.location = { lat:latitude, lng:longitude };
}
})
let info = await this.$http.getChannelInfo({ id: 17 });
info.data.children.push({ type: 'store', name: '门店推荐' })
this.detail = info.data;
},
methods: {
getDistance(item){
let lat1 = item.lat, lng1 = item.lng, lat2 = this.location.lat, lng2 = this.location.lng;
return this.$utils.getDistance(lat1, lng1, lat2, lng2)
},
async upCallback (page) {
let obj = { pageNum: page.num, pageSize: page.size };
let info = null;
if (this.detail.children[this.menuActive].type == 'list') {
obj.channel = this.detail.children[this.menuActive].id;
obj.modelId = 3;
info = await this.$http.archivesCustomList(obj);
} else {
info = await this.$eatery.getShopList(obj);
}
if (page.num == 1) this.list = [];
this.list = this.list.concat(info.rows)
this.mescroll.endBySize(info.rows.length, info.total);
},
tabMenu (index) {
this.menuActive = index;
this.mescroll.resetUpScroll();
}
}
}
</script>
<style lang="scss">
.banner{ width: 100%; height: 520rpx; }
.content{
width: 100%; position: relative; margin-top: -54rpx; background: #F6F6F6; border-radius: 30rpx 30rpx 0 0; box-sizing: border-box; padding: 32rpx 24rpx;
.menu{
width: 100%;
.menu_waper{
width: 100%; padding-bottom: 17rpx; font-size: 0; white-space: nowrap;
view{
color: rgba(0,0,0,0.45); font-size: 28rpx; display: inline-block; vertical-align: top; line-height: 46rpx; position: relative; margin-right: 68rpx;
&:last-child{ margin-right: 0; }
&.active{
color: rgba(0,0,0,0.85); font-size: 32rpx; font-weight: 600;
&::after{ content: ""; width: 42rpx; height: 6rpx; background: #4C90FF; border-radius: 13rpx; position: absolute; bottom: -16rpx; left: 50%; transform: translateX(-50%); }
}
}
}
}
.content_waper{
width: 100%; margin-top: 22rpx;
.list{
width: 100%; background: #fff; border-radius: 10rpx; box-sizing: border-box; padding: 24rpx; margin-bottom: 22rpx;
&:last-child{ margin-bottom: 0; }
.info{
width: 100%; height: 208rpx; box-sizing: border-box; padding-left: 228rpx; position: relative;
.img{
width: 208rpx; height: 208rpx; position: absolute; left: 0; top: 0;
image{ border-radius: 10rpx; }
}
.text{
width: 100%; padding-top: 6rpx;
.title{ line-height: 46rpx; color: rgba(0, 0, 0, 0.85); font-size: 32rpx; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tag{
margin-top: 10rpx; font-size: 0;
view{
display: inline-block; margin-right: 16rpx; height: 36rpx; padding: 0 14rpx; font-size: 20rpx; vertical-align: top; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; line-height: 36rpx;
&:nth-child(1n){ color: #4C90FF; background: rgba(71, 175, 195, 0.1); }
&:nth-child(2n){ color: #FFB457; background: rgba(255, 180, 87, 0.1); }
&:last-child{ margin-right: 0; }
}
}
.msg{ width: 100%; margin-top: 16rpx; line-height: 36rpx; color: rgba(0, 0, 0, 0.45); font-size: 28rpx; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
}
}
.store{
width: 100%; margin-top: 24rpx; padding-top: 24rpx; border-top: 2rpx solid rgba(0, 0, 0, 0.06);
.scroll-view{
width: 100%; height: 130rpx; white-space: nowrap;
.shop_list{
display: inline-block; vertical-align: top; width: 218rpx; height: 130rpx; margin-right: 22rpx; position: relative;
image{ border-radius: 10rpx; }
&:last-child{ margin-right: 0; }
view{ height: 36rpx; line-height: 36rpx; color: #fff; font-size: 26rpx; box-sizing: border-box; padding: 0 20rpx; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; position: absolute; left: 0; bottom: 12rpx; }
}
}
}
}
.store_list{
width: 100%; background: #fff; border-radius: 10rpx; box-sizing: border-box; padding: 24rpx; margin-bottom: 22rpx; padding-left: 252rpx; position: relative;
&:last-child{ margin-bottom: 0; }
.left{
width: 208rpx; height: 208rpx; position: absolute; left: 24rpx; top: 24rpx;
image{ border-radius: 10rpx; }
}
.right{
width: 100%; height: 208rpx; box-sizing: border-box; padding-top: 6rpx;
.title{ line-height: 46rpx; color: rgba(0, 0, 0, 0.85); font-size: 32rpx; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.infos{
width: 100%; margin-top: 10rpx; display: flex; justify-content: space-between; align-items: center;
.infos_left{
height: 36rpx; display: flex; align-items: center;
.tag{ background: rgba(71, 175, 195, 0.1); color: #4C90FF; height: 100%; padding: 0 14rpx; line-height: 36rpx; font-size: 20rpx; }
.money{ margin-left: 20rpx; color: rgba(0, 0, 0, 0.45); font-size: 26rpx; }
}
.site{ margin-left: 20rpx; color: rgba(0, 0, 0, 0.45); font-size: 26rpx; }
}
.msg{
margin-top: 16rpx; width: 100%; box-sizing: border-box; padding-left: 36rpx; height: 42rpx; position: relative;
.icon{ width: 28rpx; height: 28rpx; display: flex; align-items: center; position: absolute; left: 0; top: 50%; transform: translateY(-50%); }
.text{ line-height: 42rpx; color: rgba(0, 0, 0, 0.65); font-size: 28rpx; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
}
}
}
}
}
</style>