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.
543 lines
14 KiB
543 lines
14 KiB
<template>
|
|
<view class="centent">
|
|
<lf-nav :title="['分类','品牌'][current]" bgColor="#fff" :search="current == 0" @changeHeight="e => nav_height = e"></lf-nav>
|
|
<view class="tabs">
|
|
<view class="lf-tab"
|
|
:style="{width: 100 / tabs.length +'%'}"
|
|
:class="{'tab-active': current == index}"
|
|
v-for="(item, index) in tabs" :key="index"
|
|
@click="current = index">{{ item.name }}
|
|
</view>
|
|
</view>
|
|
<!-- 分类 -->
|
|
<view class="page" v-if="current == 0 && dataArr.length">
|
|
<scroll-view class="left_view p_r" scroll-y :style="{ height: autoHeight }">
|
|
<block v-for="(item, index) in dataArr" :key="index">
|
|
<view :class="[left_selectIndex == index ? 'left_item_s' : '', 'left_item']" :id="'left_' + index" @click="leftTap({ item, index })">{{ item.name }}</view>
|
|
</block>
|
|
<view class="seletItem" :style="{ top: left_selectIndex * 60 - 19 + 'px' }"></view>
|
|
</scroll-view>
|
|
|
|
<scroll-view @scroll="rightScroll" class="right_view" scroll-y :style="{ height: autoHeight }" :scroll-into-view="'left_' + right_selectIndex" scroll-with-animation>
|
|
<block v-for="(item, index) in dataArr" :key="index">
|
|
<view :ref="'left_' + index" class="right_item " :id="'left_' + index">
|
|
<text class="right_item_title ">{{ item.name }}</text>
|
|
<view class="right_item_view">
|
|
<view class="item" v-for="(c_item, c_index) in item.sub_category" :key="c_index" @click="rightTap(c_item)">
|
|
<image :src="c_item.image" :style="{ width: '100%', height: subItemW + 'px', background: '#999999' }"></image>
|
|
<text class="lf-font-24">{{ c_item.name }}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</block>
|
|
<view class="" :style="{ height: autoScrollHeight }"><!-- 站位 --></view>
|
|
</scroll-view>
|
|
</view>
|
|
<!-- 品牌 -->
|
|
<view class="brand" v-else-if="current == 1" :style="{height: autoHeight}">
|
|
<!-- 筛选 -->
|
|
<view class="lf-filter-box" :style="{'z-index': filter_active == '' ? 1 : 99}">
|
|
<view class="lf-filter" :class="{'lf-filter-after': filter_active == ''}">
|
|
<view v-for="(value, key) in filter_list" :key="key"
|
|
:class="{'filter-active': filter_active == key}"
|
|
@click="filter_active = key">{{ value.name }}
|
|
</view>
|
|
</view>
|
|
<view class="filter-modal-mask" :style="{height: otherHeight}" v-if="filter_active != ''" @click="filter_active = ''">
|
|
<view class="filter-modal" @click.stop>
|
|
<view class="filter-item"
|
|
:class="{'filter-item-active': filter_list[filter_active].current == index}"
|
|
@click="selectFilter(item, index)"
|
|
v-for="(item, index) in filter_list[filter_active].list"
|
|
:key="index">{{ item.name || item }}
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<!-- 内容 -->
|
|
<scroll-view class="brand-scroll" :scroll-into-view="scrollAnchorId" :scroll-y="true" :style="{height: otherHeight}">
|
|
<view class="lf-flex brand-item"
|
|
:id="'anchor-'+ item.initial"
|
|
@click="$url('/pages/shop/shopdetail?id='+ item.id)"
|
|
v-for="(item, index) in brand_list" :key="index">
|
|
<image class="img" :src="item.logo"></image>
|
|
<view class="info">
|
|
<view class="lf-font-36 lf-font-bold lf-color-black">{{ item.name }}</view>
|
|
<view class="lf-font-24 lf-color-gray">{{ item.category }}|{{ item.goods_count || 0 }}件在售</view>
|
|
<view class="lf-font-24">
|
|
<text class="lf-iconfont icon-dizhi lf-font-24 lf-color-primary"></text>
|
|
<text class="lf-color-gray lf-m-l-10">{{ item.floor }}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</scroll-view>
|
|
<!-- 锚点定位 -->
|
|
<view class="fixed-point" v-if="point_list.length">
|
|
<view class="fixed-content" @touchmove="pointTouchmove">
|
|
<view class="point-item"
|
|
@click="pointClick"
|
|
:id="'point-'+ item"
|
|
:style="{height: 100 / 26 +'%'}"
|
|
v-for="(item, index) in point_list"
|
|
:key="index">{{ item }}
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<lf-tabbar></lf-tabbar>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import lfNav from '@/components/lf-nav/lf-nav.vue';
|
|
import lfTabbar from '@/components/lf-tabbar/lf-tabbar.vue';
|
|
import testdata from './testdata.js';
|
|
let app = getApp();
|
|
|
|
export default {
|
|
data() {
|
|
return {
|
|
scrollH: 0,
|
|
subItemW: 0,
|
|
left_selectIndex: 0,
|
|
right_selectIndex: 0,
|
|
ttscrollH: 0, //总高度
|
|
placeholderH: 0, //占位高度
|
|
heighArr: [],
|
|
dataArr: [],
|
|
current: 1,
|
|
nav_height: 0,
|
|
tabs: [{
|
|
name: '分类'
|
|
},{
|
|
name: '品牌'
|
|
}],
|
|
filter_list: {
|
|
'floor': {
|
|
name: '楼层',
|
|
list: [],
|
|
current: null
|
|
},
|
|
'class': {
|
|
name: '分类',
|
|
list: [],
|
|
current: null
|
|
}
|
|
},
|
|
filter_active: '',
|
|
brand_list: [],
|
|
point_list: [],
|
|
scrollAnchorId: ''
|
|
};
|
|
},
|
|
computed: {
|
|
autoHeight(){
|
|
return `calc(${this.scrollH}px - ${this.nav_height}px - 90rpx - 120rpx)`;
|
|
},
|
|
otherHeight(){
|
|
// 屏幕可用总高度 - 导航条高度 - tabs高度 - tabbar高度 - 筛选高度
|
|
return `calc(${this.scrollH}px - ${this.nav_height}px - 90rpx - 120rpx - 105rpx)`;
|
|
},
|
|
autoScrollHeight(){
|
|
return `calc(${this.scrollH}px - ${this.nav_height}px - 90rpx - 120rpx - 300rpx)`;
|
|
}
|
|
},
|
|
components: {
|
|
lfNav,
|
|
lfTabbar
|
|
},
|
|
onLoad(options) {
|
|
// https://ext.dcloud.net.cn/plugin?id=5031
|
|
this.getBrandList();
|
|
if(this.$isRight(options)){
|
|
this.current = options.current || 1;
|
|
this.left_selectIndex = options.type || 0;
|
|
this.right_selectIndex = options.type || 0;
|
|
}
|
|
let info = uni.getSystemInfoSync();
|
|
let self = this;
|
|
self.scrollH = info.screenHeight;
|
|
self.subItemW = parseInt((info.screenWidth * (2 / 3) - 15 * 2 - 24) / 3);
|
|
this.getCategoryList().then(() => {
|
|
self.computerH();
|
|
});
|
|
// setTimeout(function() {
|
|
// self.computerH();
|
|
// }, 100);
|
|
// this.createAtoZ();
|
|
},
|
|
methods: {
|
|
getBrandList(){
|
|
this.$http.get({
|
|
api: '/api/brand'
|
|
}).then(res => {
|
|
console.log("getBrandList", res);
|
|
let category = res.data.data.category;
|
|
let floor = res.data.data.floor;
|
|
this.filter_list['floor'].list = floor;
|
|
this.filter_list['class'].list = category;
|
|
this.brand_list = res.data.data.list;
|
|
this.autoCreateAtoZ(res.data.data.list);
|
|
});
|
|
},
|
|
getCategoryList(){
|
|
return new Promise((resolve, reject) => {
|
|
this.$http.get({
|
|
api: '/api/category/list'
|
|
}).then(res => {
|
|
console.log("getCategoryList", res);
|
|
this.dataArr = res.data.data;
|
|
resolve(res);
|
|
}).catch(err => reject(err));
|
|
})
|
|
},
|
|
// 选择筛选项
|
|
selectFilter(item, index){
|
|
console.log(item, index);
|
|
this.filter_list[this.filter_active].current = index;
|
|
this.filter_active = '';
|
|
},
|
|
// 生成A-Z的大写字母 自己生成的
|
|
createAtoZ(){
|
|
let point_list = [];
|
|
for(var i=0; i<26; i++){
|
|
point_list.push(String.fromCharCode(65+i));
|
|
}
|
|
this.point_list = point_list;
|
|
},
|
|
// 生成A-Z的大写字母 根据店铺类别动态生成
|
|
autoCreateAtoZ(list){
|
|
let letters = Array.from(new Set(list.map(item => item.initial)));
|
|
letters.sort(function(a1, b1){
|
|
let a = a1.toLowerCase();
|
|
let b = b1.toLowerCase();
|
|
if (a < b) return -1;
|
|
if (a > b) return 1;
|
|
return 0;
|
|
})
|
|
this.point_list = letters;
|
|
},
|
|
pointTouchmove(event){
|
|
console.log(event);
|
|
},
|
|
pointClick(event){
|
|
// let index = (event.target.id).replace('point-', '');
|
|
// let letter = this.point_list[index];
|
|
let letter = (event.target.id).replace('point-', '');
|
|
this.scrollAnchorId = '';
|
|
this.$msg(letter);
|
|
this.$nextTick(() => {
|
|
this.scrollAnchorId = 'anchor-'+ letter;
|
|
})
|
|
},
|
|
leftTap: function(e) {
|
|
this.left_selectIndex = e.index;
|
|
this.right_selectIndex = e.index;
|
|
},
|
|
// 右边点击
|
|
rightTap: function(item) {
|
|
this.$url(item.path);
|
|
},
|
|
rightScroll: function(e) {
|
|
let scrollH = e.detail.scrollTop + 30;
|
|
let cc = this.ttscrollH - this.scrollH;
|
|
|
|
let a = 0;
|
|
let findInx = this.heighArr.findIndex(function(itemH, i) {
|
|
a = a + itemH;
|
|
return a > scrollH;
|
|
});
|
|
// if (scrollH >= cc) {
|
|
// return;
|
|
// }
|
|
this.left_selectIndex = findInx;
|
|
},
|
|
// 计算高度
|
|
computerH: function() {
|
|
this.ttscrollH = 0;
|
|
for (let item of this.dataArr) {
|
|
let title_lineH = 49; //rpx
|
|
let subNum = item.sub_category.length;
|
|
let subImgH = this.subItemW; //rpx
|
|
let subTitleH = 40; //rpx
|
|
let rowSpecH = 8; //rpx
|
|
let rowN = subNum % 3;
|
|
let rowSpecNum = parseInt(subNum / 3) + parseInt(rowN > 0 ? 1 : 0);
|
|
let totalRpx = title_lineH + (subImgH + subTitleH) * rowSpecNum + rowSpecH * (rowSpecNum - 1);
|
|
this.heighArr.push(totalRpx);
|
|
this.ttscrollH = this.ttscrollH + totalRpx;
|
|
}
|
|
|
|
// this.placeholderH = this.scrollH - this.heighArr[this.heighArr.length - 1];
|
|
|
|
//以下方法也可以
|
|
// let self=this
|
|
// var selectorQuery = uni.createSelectorQuery()
|
|
// selectorQuery.selectAll('.right_item').boundingClientRect(data => {
|
|
// self.heighArr = data.map(item => {
|
|
// return {
|
|
// top: Math.round(item.top),
|
|
// height: Math.round(item.height)
|
|
// }
|
|
// })
|
|
// }).exec()
|
|
// console.log('ttscrollH',this.$refs.left_0)
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.page {
|
|
display: grid;
|
|
grid-template-columns: 1fr 2fr;
|
|
grid-template-rows: auto;
|
|
position: absolute;
|
|
left: 0rpx;
|
|
right: 0rpx;
|
|
overflow: hidden;
|
|
box-sizing: border-box;
|
|
}
|
|
.left_view {
|
|
background-color: #f4f8f8;
|
|
position: relative;
|
|
box-sizing: border-box;
|
|
// 蒙版
|
|
.seletItem {
|
|
height: 98px;
|
|
position: absolute;
|
|
top: 0rpx;
|
|
left: 0rpx;
|
|
z-index: 10;
|
|
right: 0rpx;
|
|
// background-color: rgba(255, 255, 255, 0.3);
|
|
transition: top 0.2s linear;
|
|
display: flex;
|
|
align-items: center;
|
|
box-sizing: border-box;
|
|
&::before {
|
|
content: '';
|
|
width: 6rpx;
|
|
height: 60%;
|
|
background-color: #15716E;
|
|
left: 0rpx;
|
|
}
|
|
}
|
|
.left_item {
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
height: 60px;
|
|
margin-bottom: 0rpx;
|
|
position: relative;
|
|
font-size: 28rpx;
|
|
box-sizing: border-box;
|
|
color: #555555;
|
|
}
|
|
.left_item_s {
|
|
background-color: #ffffff;
|
|
color: #15716E;
|
|
font-weight: bold;
|
|
position: relative;
|
|
box-sizing: border-box;
|
|
}
|
|
}
|
|
|
|
.right_view {
|
|
background-color: #ffffff;
|
|
padding: 0rpx 12px;
|
|
box-sizing: border-box;
|
|
.right_item {
|
|
.right_item_title {
|
|
display: block;
|
|
box-sizing: border-box;
|
|
line-height: 49px;
|
|
font-size: 28rpx;
|
|
font-weight: bold;
|
|
color: #15716E;
|
|
}
|
|
.right_item_view {
|
|
display: grid;
|
|
grid-template-columns: repeat(3, 1fr);
|
|
grid-template-rows: auto;
|
|
grid-gap: 8px 15px;
|
|
box-sizing: border-box;
|
|
.item {
|
|
display: flex;
|
|
flex-flow: column nowrap;
|
|
align-items: center;
|
|
box-sizing: border-box;
|
|
text {
|
|
color: #333;
|
|
line-height: 40px;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.tabs{
|
|
width: 750rpx;
|
|
height: 90rpx;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
border-bottom: 1rpx solid #e5e5e5;
|
|
background-color: #FFFFFF;
|
|
.lf-tab{
|
|
// width: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 28rpx;
|
|
color: #777777;
|
|
position: relative;
|
|
&.tab-active{
|
|
color: #15716E;
|
|
}
|
|
&.tab-active::after{
|
|
content: '';
|
|
position: absolute;
|
|
bottom: 0;
|
|
left: 50%;
|
|
width: 80rpx;
|
|
height: 10rpx;
|
|
background-color: #15716E;
|
|
border-radius: 10rpx 10rpx 0 0;
|
|
margin-left: -40rpx;
|
|
}
|
|
}
|
|
}
|
|
.lf-filter-box{
|
|
height: 105rpx;
|
|
width: 750rpx;
|
|
background-color: #F4F8F8;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
position: relative;
|
|
.lf-filter{
|
|
width: 300rpx;
|
|
height: 65rpx;
|
|
border-radius: 33rpx;
|
|
border: 1rpx solid #15716E;
|
|
color: #15716E;
|
|
font-size: 24rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
position: relative;
|
|
overflow: hidden;
|
|
&.lf-filter-after::after{
|
|
content: '';
|
|
position: absolute;
|
|
top: 12rpx;
|
|
left: calc(50% - 1rpx);
|
|
width: 2rpx;
|
|
height: 40rpx;
|
|
background-color: #15716E;
|
|
}
|
|
&>view{
|
|
height: 100%;
|
|
width: 50%;
|
|
display: flex;
|
|
justify-content: space-around;
|
|
align-items: center;
|
|
}
|
|
.filter-active{
|
|
background-color: #15716E;
|
|
color: #FFFFFF;
|
|
}
|
|
}
|
|
.filter-modal-mask{
|
|
position: absolute;
|
|
top: 105rpx;
|
|
left: 0;
|
|
width: 100%;
|
|
background-color: rgba(0,0,0,0.5);
|
|
z-index: 99;
|
|
.filter-modal{
|
|
width: 750rpx;
|
|
height: max-content;
|
|
padding: 60rpx 32rpx;
|
|
box-sizing: border-box;
|
|
background-color: #FFFFFF;
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
position: relative;
|
|
z-index: 102;
|
|
.filter-item{
|
|
width: 215rpx;
|
|
height: 65rpx;
|
|
border-radius: 10rpx;
|
|
border: 1rpx solid #555555;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
font-size: 28rpx;
|
|
color: #555555;
|
|
margin-right: 21rpx;
|
|
&:nth-child(3n){
|
|
margin-right: 0rpx;
|
|
}
|
|
&:nth-child(n+4){
|
|
margin-top: 21rpx;
|
|
}
|
|
}
|
|
.filter-item-active{
|
|
background-color: #15716E;
|
|
color: #FFFFFF;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
.brand-scroll{
|
|
padding: 0rpx 32rpx;
|
|
box-sizing: border-box;
|
|
width: 750rpx;
|
|
.brand-item{
|
|
margin-bottom: 60rpx;
|
|
&:nth-child(1n){
|
|
margin-top: 30rpx;
|
|
}
|
|
}
|
|
.img{
|
|
width: 150rpx;
|
|
height: 150rpx;
|
|
border-radius: 4rpx;
|
|
margin-right: 20rpx;
|
|
}
|
|
.info{
|
|
width: 514rpx;
|
|
height: 150rpx;
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: space-between;
|
|
}
|
|
}
|
|
.brand{
|
|
position: relative;
|
|
}
|
|
.fixed-point{
|
|
position: fixed;
|
|
right: 0;
|
|
top: 0;
|
|
// top: 18vh;
|
|
// height: 70vh;
|
|
height: 100vh;
|
|
width: 57rpx;
|
|
z-index: 2;
|
|
display: flex;
|
|
align-items: center;
|
|
.fixed-content{
|
|
width: 100%;
|
|
height: max-content;
|
|
padding: 14rpx 0rpx;
|
|
background-color: rgba(0,0,0,0.3);
|
|
border-radius: 30rpx 0rpx 0rpx 30rpx;
|
|
.point-item{
|
|
font-size: 24rpx;
|
|
color: #FFFFFF;
|
|
text-align: center;
|
|
}
|
|
}
|
|
}
</style>
|