金诚优选前端代码
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.
 
 
 
 
 

577 lines
16 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-into-view="left_tabview" 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" :id="'tab_'+ left_selectIndex" :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" :style="{color: left_selectIndex == index ? '#15716E' : '#555555'}">{{ 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="clickFilterTab(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>
<lf-nocontent src="/static/images/empty.png" v-if="brand_list.length <= 0"></lf-nocontent>
</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';
let app = getApp();
export default {
data() {
return {
scrollH: 0,
subItemW: 0,
left_selectIndex: 0,
right_selectIndex: 0,
left_tabview: 'tab_0', // 默认和left_selectIndex对应,scroll-view定位到的左侧tab元素
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({load: true});
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(options = {}){
let par = {};
if(options.filter){
let _floor = this.filter_list['floor'];
let _class = this.filter_list['class'];
if(_floor.current != null){
par.floor = _floor.list[_floor.current].name;
}
if(_class.current != null){
par.category_id = _class.current;
}
}
this.$http.get({
api: '/api/brand',
data: par
}).then(res => {
console.log("getBrandList", res);
if(options.load){
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);
if(this.filter_list[this.filter_active].current == index){
this.filter_list[this.filter_active].current = null;
}else{
this.filter_list[this.filter_active].current = index;
}
this.filter_active = '';
this.getBrandList({filter: true});
},
// 生成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) {
console.log(item);
this.$url('/pages/index/onlineMall/onlineMall?id='+ item.id);
},
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;
this.left_tabview = '';
setTimeout(() => {
this.left_tabview = 'tab_'+ findInx; // TODO 待验证是否跟随滚动
}, 0);
},
// 计算高度
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)
},
// 品牌筛选tab被点击
clickFilterTab(key){
if(this.filter_active == key){
this.filter_active = '';
}else{
this.filter_active = key;
}
}
}
}
</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: #555555;
// 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: 5rpx;
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>