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

263 lines
6.4 KiB
Vue

<template>
<view class="uni-container detail-content">
<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>
<mescroll-body @init="mescrollInit" @down="downCallback" @up="upCallback" :down="downOption" :up="upOption">
<view class="goodes_detail_swiper-box" v-if="goodsInfo">
<!-- 详情轮播 -->
<swiper class="carousel" circular @change="swiperChange" :autoplay="true">
<swiper-item @tap="tools.previewImage(goodsInfo.images, swiperCurrent)" v-for="(img, index) in goodsInfo.images" :key="index" class="carousel-item">
<image class="swiper-image shopro-selector-rect" :src="$utils.setImgUrl(img)" mode="aspectFill" lazy-load></image>
</swiper-item>
</swiper>
<view v-if="goodsInfo.images" class="swiper-dots">{{ swiperCurrent + 1 }} / {{ goodsInfo.images.length }}</view>
</view>
<view class="card-box">
<view class="title-box">
<view class="name">{{goodsInfo.name}}</view>
<view class="address">地址:{{goodsInfo.address}}</view>
</view>
<view class="tel_waper" @click="callTel">
<u-icon name="phone-fill" size="38rpx" color="#fff"></u-icon>
</view>
</view>
<view class="tabs-box">
<scroll-view scroll-x="true">
<view class="menu">
<view class="tabs" :class="{active: activeTabs == item.id}" v-for="(item,index) in tabsList" :key="index" @click="changeTabs(item)">
{{item.name}}
</view>
</view>
</scroll-view>
</view>
<view v-if="list.length" class="list-box">
<navigator hover-class="none" class="list-item" v-for="(item, index) in list" :key="index" :url="'/pages/shop/detail?id=' + item.id">
<image class="img" :src="$utils.setImgUrl(item.image)" mode=""></image>
<view class="item-con">
<view class="title">{{item.title}}</view>
<view class="num">
<view class="price"><text class="unit">¥</text>{{item.price.toFixed(2)}}</view>
<view class="sell">已售{{(item.showSales ? item.showSales : 0) + item.sales}}</view>
</view>
</view>
</navigator>
</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 {
scrollTop: 0,
id: '',
swiperCurrent: 0, //轮播下标
goodsInfo: null,
tabsList: [],
activeTabs: null,
list: []
};
},
onPageScroll (e) {
this.scrollTop = e.scrollTop;
},
onLoad(options) {
this.id = options.id;
},
methods: {
async upCallback (page) {
if (!this.goodsInfo) {
let info = await this.$shop.getStoreDetail(this.id)
info.data.images = info.data.images.split(',');
this.goodsInfo = info.data;
let info1 = await this.$shop.getCategoryList({storeId: this.id})
this.tabsList = info1.data;
this.activeTabs = this.tabsList[0].id;
}
let obj = { pageNum: page.num, pageSize: page.size, storeId: this.id, categoryIds: this.activeTabs };
let info = await this.$shop.getGoodsList(obj);
if(page.num == 1) this.list = [];
this.list = this.list.concat(info.rows);
this.mescroll.endBySize(info.rows.length, info.total);
},
// 轮播图切换
swiperChange(e) {
const index = e.detail.current;
this.swiperCurrent = index;
},
callTel () {
uni.makePhoneCall({
phoneNumber: this.goodsInfo.phone
});
},
changeTabs(item) {
this.activeTabs = item.id;
this.init();
}
}
};
</script>
<style lang="scss" scoped>
.uni-container {
width: 100%;
min-height: 100vh;
box-sizing: border-box;
background-color: #FBFBFB;
}
.detail-content {
&::-webkit-scrollbar {
width: 0;
height: 0;
color: transparent;
}
}
// 商品图片轮播
.goodes_detail_swiper-box {
width: 750rpx;
height: 588rpx;
position: relative;
.carousel {
width: 750rpx;
height: 100%;
}
.carousel-item {
width: 750rpx;
height: 100%;
}
.swiper-image {
width: 750rpx;
height: 100%;
background: #ccc;
}
.swiper-dots {
display: flex;
position: absolute;
right: 20rpx;
bottom: 100rpx;
line-height: 44rpx;
border-radius: 22rpx;
padding: 0 15rpx;
background: rgba(#333, 0.3);
font-size: 28rpx;
color: rgba(#fff, 0.9);
}
}
.card-box {
display: flex;
align-items: center;
flex-direction: row;
justify-content: space-between;
margin: 0 24rpx;
background: #FFFFFF;
border-radius: 10rpx;
padding: 32rpx 24rpx;
position: relative;
top: -88rpx;
.title-box {
flex: 1; margin-right: 24rpx;
.name {
font-weight: 500;
font-size: 40rpx;
color: rgba(0,0,0,0.85);
}
.address {
margin-top: 16rpx;
font-size: 26rpx;
color: rgba(0,0,0,0.45);
}
}
.tel_waper{
width: 60rpx; height: 60rpx; background: #03AE80; border-radius: 50rpx; display: flex; justify-content: center; align-items: center;
}
}
.tabs-box {
margin: -44rpx 32rpx 0;
.menu{
width: 100%; display: flex; align-items: flex-end; flex-wrap: nowrap;
.tabs{
vertical-align: top; margin-right: 36rpx; height: 42rpx; line-height: 33rpx; color: rgba(0,0,0,0.45); font-size: 28rpx; white-space: nowrap;
&.active{
font-weight: 500;
font-size: 36rpx;
color: rgba(0,0,0,0.85);
line-height: 42rpx;
height: 53rpx;
}
}
}
}
.list-box {
margin: 20rpx 24rpx 0;
display: flex;
align-items: center;
flex-direction: row;
flex-wrap: wrap;
.list-item {
width: 341rpx;
margin-bottom: 22rpx;
margin-right: 20rpx;
background: #FFFFFF;
border-radius: 10rpx;
&:nth-child(2n) {
margin-right: 0;
}
.img {
width: 341rpx;
height: 342rpx;
}
.item-con {
padding: 20rpx 24rpx 24rpx;
.title {
font-weight: 500;
font-size: 28rpx;
color: rgba(0,0,0,0.85);
line-height: 38rpx;
height: 78rpx;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.num {
display: flex;
align-items: baseline;
flex-direction: row;
justify-content: space-between;
margin-top: 24rpx;
.price {
font-weight: bold;
font-size: 40rpx;
color: #FF3333;
.unit {
font-weight: 400;
font-size: 24rpx;
color: #FF3333;
}
}
.sell {
font-weight: 400;
font-size: 28rpx;
color: rgba(0,0,0,0.45);
}
}
}
}
}
</style>