<template>
<div :class="['container',{fixed:isFixedNav}]" v-if="isLoading">
<div :class="['sort-nav']" ref="scrollbox" v-show="isShowNav">
<div class="sort-list">
<div :class="['sort-item',`nav${i}`,{active:current===i}]" v-for="(item,i) in groupInfo" :key="i" @click="changeNav(i)">
<img :src="item.groupIcon" alt="">
<h4>{{item.groupName}}</h4>
</div>
</div>
</div>
<div class="sort-content">
<div :class="['sort-module',,`module${i}`]" v-for="(item,i) in groupInfo" :key="i">
<div class="module-title" v-if="isShowNav">
<p>{{item.groupName}}</p>
</div>
<div class="module-product">
<div class="product-item" v-for="(it,j) in item.dataList" :key="j" @click="toMallProduct(it)">
<div class="l-icon">
<img :src="it.mainPic" alt="">
</div>
<div class="r-info">
<div class="name">
<i v-for="(x,y) in it.titleTag&&it.titleTag.split(',')" :key="y" :class="[{yx:x==='优选'},{xp:x==='新品'},{th:x==='特惠'},]">{{x}}</i><span>{{it.brand}}{{it.name}}</span>
</div>
<div class="desc">
<p>{{it.description}}</p>
</div>
<div class="price">
<i>¥</i><b>{{it.priceAfterCoupon||it.salePrice}}</b> <em v-if="it.priceAfterCoupon">券后价</em> <span class="old">¥{{it.originPrice}} </span>
<span v-if="it.monthSaleNum>0">月售{{it.monthSaleNum}}</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import BScroll from 'better-scroll'
import { queryKdfMallProductListV2 } from 'service'
export default {
data() {
return {
isLoading: false,
groupId: '',
upGroupId: '',
groupInfo: {},
current: 0,
scrollTop: 0,
scrollHeight: 0,
clientHeight: 0,
windowRatio: 0,
isFixedNav: false,
timer: null
}
},
computed: {
isShowNav() {
return this.groupInfo.length > 1
},
navOffsetHeight() {
return document.documentElement.querySelector(`.sort-nav`).offsetHeight || 0
},
currentOffsetTop() {
return document.documentElement.querySelector(`.module${this.current}`).offsetTop - this.navOffsetHeight || 0
},
nextOffsetTop() {
if (this.current === this.groupInfo.length - 1) {
return this.scrollHeight - this.clientHeight
} else {
return document.documentElement.querySelector(`.module${this.current + 1}`).offsetTop - this.navOffsetHeight || 0
}
}
},
filters: {
computeSales(number) {
let day = new Date().getDate()
return parseInt(Number(number) * (day * 3 + 5) / 3)
}
},
methods: {
changeNav(i) {
this.backToId(i)
},
toMallProduct(data) {
sessionStorage.setItem('mallSortProductList', this.scrollTop)
this.routerPush({
path: '/member/mallProduct',
query: {
mallProductId: data.id
}
})
},
getSortProductList() {
this.isLoading = false
const { uid, token } = this.$store.state.user.userInfo
queryKdfMallProductListV2({
uid,
token,
groupId: this.groupId,
upGroupId: this.upGroupId,
showStyle: 'groupList',
productIds: '',
pageNo: 0,
pageSize: 200
}).then(res => {
this.isLoading = true
this.ToastWithLoading().hide()
const {data, message, code} = res.data
if (code === 200) {
this.groupInfo = data.data.productInfo
if (this.isShowNav) {
this.initScrollNav()
}
this.$nextTick(() => {
this.setScrollTop(Number(sessionStorage.getItem('mallSortProductList')) || 0)
sessionStorage.setItem('mallSortProductList', 0)
})
} else {
}
}).catch(e => {
this.isLoading = true
this.ToastWithLoading().hide()
this.ToastWithText('获取数据失败')
})
},
initScrollNav() {
this.$nextTick(() => {
this.scrollmethod = new BScroll(this.$refs.scrollbox, {
bounce: true,
eventPassthrough: 'vertical',
scrollX: true,
scrollY: false,
preventDefault: false
})
})
},
backToId(id) {
clearTimeout(this.timer)
this.timer = null
let elOffsetTop = document.documentElement.querySelector(`.module${id}`).offsetTop - this.navOffsetHeight + 3
let distance = document.documentElement.scrollTop || document.body.scrollTop
let step = 50
let smoothDown = () => {
if (distance < elOffsetTop && distance + 2 * step < elOffsetTop) {
distance += step
this.setScrollTop(distance)
this.timer = setTimeout(smoothDown, 10)
} else {
this.setScrollTop(elOffsetTop)
}
}
let smoothUp = () => {
if (distance > elOffsetTop && distance - 2 * step > elOffsetTop) {
distance -= step
this.setScrollTop(distance)
this.timer = setTimeout(smoothUp, 10)
} else {
this.setScrollTop(elOffsetTop)
}
}
if (elOffsetTop > distance) {
smoothDown()
} else {
smoothUp()
}
},
setScrollTop(scrollTop) {
document.body.scrollTop = scrollTop
document.documentElement.scrollTop = scrollTop
},
scrollInit() {
this.clientHeight = document.documentElement.clientHeight || document.body.clientHeight
this.windowRatio = document.documentElement.clientWidth / 375 || 1
window.addEventListener('scroll', () => {
this.scrollTop = window.pageYOffset || document.scrollTop || document.body.scrollTop
this.scrollHeight = document.documentElement.scrollHeight || document.body.scrollHeight
})
}
},
created() {
this.groupId = this.$route.query.groupId || ''
this.upGroupId = this.$route.query.upGroupId || ''
document.title = this.$route.query.title || ''
this.getSortProductList()
},
mounted() {
this.scrollInit()
},
destroyed() {
clearTimeout(this.timer)
},
watch: {
current: {
deep: true,
handler(newStatus, oldStatus) {
let dom = document.querySelector(`.nav${newStatus}`)
this.$nextTick(() => {
this.scrollmethod.scrollToElement(dom, null, true, true)
})
}
},
scrollTop: {
deep: true,
handler(newStatus, oldStatus) {
if (this.scrollTop >= this.nextOffsetTop && this.current < this.groupInfo.length - 1) {
this.current = this.current + 1
} else if (this.scrollTop < this.currentOffsetTop && this.current > 0) {
this.current = this.current - 1
}
if (this.isShowNav) {
let navScrollTop = document.documentElement.querySelector(`.module0`).offsetTop - this.navOffsetHeight - 3
if (this.scrollTop >= navScrollTop) {
this.isFixedNav = true
} else {
this.isFixedNav = false
}
}
}
}
}
}
</script>
<style lang="less" scoped>
.container{
max-width: 10rem;
padding-bottom: 2.666667rem;
.sort-nav{
width: 10rem;
height: 2.666667rem;
background-color: #EDEEEF;
padding: .266667rem 0;
position: relative;
overflow: hidden;
z-index: 1;
.sort-list{
display: inline-flex;
flex-wrap: nowrap;
padding: 0 .4rem;
.sort-item{
width: 1.866667rem;
height: 2.133333rem;
background-color: #fff;
border-radius: .08rem;
margin-right: .266667rem;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
img{
display: block;
width: 1.226667rem;
height: 1.226667rem;
}
h4{
font-size: .32rem;
font-weight: 400;
color: #000;
line-height: .533333rem;
margin-top: .106667rem;
}
&.active h4{
font-weight: 600;
}
}
}
}
.sort-content{
background-color: #fff;
.sort-module{
padding: .266667rem .4rem;
.module-title{
padding: .266667rem 0;
p{
font-size: .32rem;
font-weight: 400;
color: #888;
line-height: .48rem;
}
}
.module-product{
.product-item{
display: flex;
margin-bottom: .266667rem;
&:last-child{
margin-bottom: 0;
}
.l-icon{
width: 2.666667rem;
height: 2.666667rem;
border-radius: .16rem;
img{
display: block;
width: 100%;
height: 100%;
}
}
.r-info{
flex: 1;
padding: .053333rem 0 .053333rem .4rem;
.name{
height: .8rem;
text-overflow: -o-ellipsis-lastline;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
line-clamp: 2;
-webkit-box-orient: vertical;
word-break:break-all;
i{
display: inline-block;
font-size: .32rem;
font-weight: 600;
padding:.053333rem ;
border-radius: .053333rem;
font-family: PangMenZhengDao;
transform: scale(0.8);
transform-origin: left top;
&.yx{
color: #8E5800;
background: linear-gradient(180deg, #FAD961 0%, #F7B91C 100%);
}
&.xp{
color: #fff;
background: linear-gradient(180deg, #016DFE 0%, #3A87F1 100%);
}
&.th{
color: #fff;
background: linear-gradient(180deg, #B4EC51 0%, #429321 100%);
}
}
span{
vertical-align: middle;
font-size: .346667rem;
font-weight: 600;
color: #000;
line-height: .426667rem;
height: .853333rem;
}
}
.desc{
padding-top: .133333rem ;
min-height: 1.2rem;
p{
color: #FE9C1E;
font-size: .266667rem;
font-weight: 400;
line-height: .533333rem;
}
}
.price{
height: .533333rem;
line-height: .533333rem;
display: flex;
margin-top: .08rem;
i{
font-size: .32rem;
font-weight: 600;
color: #F93A52;
transform: scale(0.8);
transform-origin: left bottom;
}
b{
font-size: .426667rem;
font-weight: 600;
color: #F93A52;
margin-right: .106667rem;
}
em{
font-size: .32rem;
font-weight: 400;
color: #F93A52;
margin-right: .106667rem;
}
span{
font-size: .293333rem;
font-weight: 400;
color: #888;
margin-right:.106667rem;
&.old{
text-decoration: line-through;
}
}
}
}
}
}
}
}
&.fixed{
padding-top: 2.666667rem;// 等于nav高度
.sort-nav{
position: fixed;
left: 0;
top: 0;
}
}
}
</style>