You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
zhishifufei_uniapp/pages/store/index.vue

485 lines
11 KiB

<template>
<BaseContainer class="store" :fixedNav="false">
<view>
<view class="swiper-box" :style="{ background: `linear-gradient(180deg, rgb(${color_one}) 0%,#F7F8F9 100%)` }">
<swiper class="custom-banner" indicator-dots autoplay
@click="handleBannerClick" @change="getChangeImage">
<swiper-item v-for="(item, index) in banner" :key="index" :data-url="item.url" class="swiper-item">
<image :data-url="item.url" mode="aspectFill" :src="item.pic" :alt="item.title" />
</swiper-item>
</swiper>
</view>
<view class="tab-bar-placeholder">
<scroll-view scroll-x class="tab-box" :class="{ fixed: tabBarFixed }" id="tabbox">
<view class="flex tab-content" @click="handleCateClick">
<view :data-idx="index" class="tab-item" v-for="(item, index) in categoryList" :key="item.id"
:class="{ on: clickedIndex === index }">{{ item.cate_name }}</view>
</view>
</scroll-view>
</view>
<view class="goods-section">
<view class="list">
<navigator hover-class="none" v-for="item in goodsList" :key="item.id" class="item"
:url="'/pages/store/detail?id=' + item.id">
<view class="image">
<image mode="aspectFit" class="img" :src="item.image" alt="" />
</view>
<view class="text">
<view class="title">{{ item.store_name }}</view>
<view class="group">
<view class="price">
¥<span class="num">{{ item.price }}</span>
</view>
<view class="sale">已售{{ item.sales }}件</view>
</view>
</view>
</navigator>
</view>
<view v-if="goodsList.length && !loading" class="finished">{{ loadTitle }}</view>
<view v-if="finished && !goodsList.length" class="empty">
<image mode="aspectFill" :src="getImgPath('/wap/first/zsff/images/empty.png')" alt="暂无商品" />
<view>暂无商品</view>
</view>
<!-- <view style="height: var(--tab-bar-height)"></view> -->
</view>
</view>
</BaseContainer>
</template>
<script>
import { getCateList, getGoodsList, getIndexData } from "@/api/store";
export default {
data() {
const systemInfo = this.$util.getSystemInfo();
const { statusBarHeight } = systemInfo;
return {
statusBarHeight,
banner: [],
categoryList: [],
goodsList: [],
clickedIndex: 0,
activeId: 0,
loadTitle: "",
page: 1,
limit: 16,
loading: false,
finished: false,
isFixed: false,
offsetTop: 0,
offsetHeight: 0,
tabBarFixed: false,
tabBarTopSize: 0,
color_one: '',
color_two: '',
};
},
onLoad() {
this.handlePageScroll = this.$util.debounce(this.handlePageScroll, 30);
this.getCateList();
this.getGoodsList();
this.getIndexData();
},
onReachBottom() {
this.getGoodsList();
},
onPageScroll({ scrollTop }) {
this.handlePageScroll(scrollTop);
},
onShareAppMessage() {
return {};
},
onShareTimeline() {
return {};
},
mounted() {
const selectQuery = uni.createSelectorQuery().in(this);
selectQuery
.select("#tabbox")
.boundingClientRect(({ top }) => {
this.tabBarTopSize = top;
})
.exec();
},
methods: {
handlePageScroll(scrollTop) {
this.tabBarFixed = scrollTop + this.statusBarHeight >= this.tabBarTopSize;
},
async getIndexData() {
try {
const { data } = await getIndexData();
this.banner = data;
if(!this.color_one && !this.color_two){
this.color_one = this.banner[0].color_one;
this.color_two = this.banner[0].color_two;
}
} catch (err) { }
},
// 点击轮播图
handleBannerClick(e) {
if (e.target.dataset.url === undefined) return;
uni.navigateTo({
url: e.target.dataset.url,
});
},
getChangeImage(e) {
this.banner.forEach((item, index) => {
if (index == e.detail.current) {
this.color_one = item.color_one;
this.color_two = item.color_two;
}
});
},
// 获取分类
async getCateList() {
try {
const { data } = await getCateList();
this.categoryList = [
{
cate_name: "全部",
id: 0,
},
].concat(data);
} catch (err) { }
},
// 获取商品列表
async getGoodsList() {
if (this.loading || this.finished) {
return;
}
this.loadTitle = "";
this.loading = true;
try {
const { data } = await getGoodsList({
cId: this.activeId,
page: this.page++,
limit: this.limit,
});
this.goodsList = this.goodsList.concat(data);
this.finished = data.length < this.limit;
this.loadTitle = this.finished ? "已全部加载完" : "上拉加载更多";
} catch (err) { }
this.loading = false;
},
// 点击商品分类
handleCateClick(e) {
if (e.target.dataset.idx === undefined || this.loading) return;
this.clickedIndex = e.target.dataset.idx;
this.goodsList = [];
this.page = 1;
this.finished = false;
this.activeId = this.categoryList[this.clickedIndex].id;
this.getGoodsList();
},
},
};
</script>
<style>
page{
background: #F7F8F9;
}
</style>
<style lang="scss" scoped>
.goods-section{
width: 686rpx;
background: #FFFFFF;
border-radius: 24rpx;
margin: auto;
}
swiper {
/deep/ {
.wx-swiper-dots-horizontal,
.uni-swiper-dots-horizontal {
left: 70%;
}
.wx-swiper-dot,
.uni-swiper-dot {
width: 12rpx;
height: 8rpx;
background: #8ab1ff;
border-radius: 4rpx;
float: left;
}
.wx-swiper-dot-active,
.uni-swiper-dot-active {
width: 24rpx;
height: 8rpx;
background: #FFFFFF !important;
border-radius: 4rpx;
}
}
}
.nothing {
position: absolute;
top: 50%;
left: 50%;
width: 400rpx;
height: 400rpx;
transform: translate(-50%, -50%);
}
.swiper-box {
/* #ifndef MP-TOUTIAO */
padding-top: var(--safe-top);
height: 306rpx;
/* #endif */
}
.custom-banner {
width: 710rpx;
height: 370rpx;
border-radius: 20rpx;
margin: 0 auto;
overflow: hidden;
}
.swiper-item {
padding: 30rpx 0;
}
.swiper-item image {
width: 100%;
height: 100%;
border-radius: 32rpx;
}
swiper {
/deep/ {
.wx-swiper-dots-horizontal,
.uni-swiper-dots-horizontal {
bottom: 60rpx;
}
.wx-swiper-dot,
.uni-swiper-dot {
width: 10rpx;
height: 10rpx;
border-radius: 5rpx;
margin-right: 5rpx;
margin-left: 5rpx;
}
.wx-swiper-dot-active,
.uni-swiper-dot-active {
width: 20rpx;
}
}
}
.tab-box {
z-index: 1;
// background: #ffffff;
&.fixed {
top: 0;
padding-top: var(--safe-top);
box-shadow: 0 6rpx 20rpx rgba(0, 0, 0, 0.03);
background-color: #FFFFFF;
}
}
.tab-content {
white-space: nowrap;
padding: 0 16rpx;
// background-color: #ffffff;
}
/deep/ ::-webkit-scrollbar {
display: none;
width: 0 !important;
height: 0 !important;
-webkit-appearance: none;
background: transparent;
}
.tab-item {
width: auto;
height: 92rpx;
padding: 0 25rpx;
font-size: 32rpx;
font-weight: 400;
color: #7A808A;
line-height: 92rpx;
&.on {
font-weight: bold;
font-size: 32rpx;
color: #23272E;
position: relative;
&::after {
content: "";
position: absolute;
bottom: 20rpx;
left: 50%;
width: 32rpx;
height: 8rpx;
background: #1D8DFF;
border-radius: 4rpx;
transform: translateX(-50%);
}
}
}
.tab-bar-placeholder {
height: 92rpx;
/* #ifndef MP-TOUTIAO */
margin-top: calc(60rpx + var(--safe-top));
/* #endif */
}
/* #ifdef MP-KUAISHOU */
.swiper-item{
padding: 0 !important;
}
/* #endif */
.store{
padding-bottom: calc(var(--tab-bar-height) + 60rpx)
}
/* 商品列表 */
.store .finished,
.store .loading {
font-size: 28rpx;
line-height: 100rpx;
text-align: center;
color: #bbb;
}
.store .fa-spin {
animation: fa-spin 1s infinite linear;
}
.store .empty {
margin-top: 100rpx;
font-size: 28rpx;
text-align: center;
color: #bbb;
}
.store .empty image {
display: block;
width: 414rpx;
height: 305rpx;
margin: 0 auto;
pointer-events: none;
}
.store .banner {
position: relative;
padding-top: 30rpx;
padding-bottom: 30rpx;
}
.store .banner .swiper-container {
width: 710rpx;
height: 310rpx;
border-radius: 20rpx;
}
.store .banner image {
display: block;
width: 100%;
height: 100%;
border-radius: 20rpx;
object-fit: cover;
pointer-events: none;
}
.store .nothing {
display: block;
width: 414rpx;
margin: 30rpx auto;
pointer-events: none;
-webkit-touch-callout: none;
}
.store .list {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
padding-top: 30rpx;
padding-right: 20rpx;
padding-left: 20rpx;
}
.store .list .item {
width: 320rpx;
margin-bottom: 30rpx;
padding: 0 8rpx;
}
.store .list .image {
height: 300rpx;
border-radius: 30rpx;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
}
.store .list .image .img {
width: 75%;
height: 75%;
border-radius: 12rpx;
object-fit: scale-down;
pointer-events: none;
-webkit-touch-callout: none;
}
.store .list .text {
display: flex;
flex-direction: column;
justify-content: space-between;
height: 148rpx;
padding-top: 13rpx;
}
.store .list .title {
overflow: hidden;
font-size: 28rpx;
line-height: 40rpx;
font-weight: 600;
color: #23272E;
-webkit-line-clamp: 2;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
}
.store .list .group {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 6rpx;
}
.store .list .price {
font-size: 32rpx;
color: #23272E;
font-weight: 600;
}
.store .list .price .num {
font-size: 32rpx;
}
.store .list .sale {
font-size: 22rpx;
color: #aaa;
}
</style>