|
|
<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> <view style="height: 40rpx;" v-if="brand_list.length > 0"></view> <lf-nocontent src="/static/images/empty.png" v-else></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> <!-- 悬浮购物车入口 --> <view class="fixed-right"> <view class="fixed-cart" hover-class="lf-opacity" @click="$url('/pages/store/cart/cart')"> <text class="lf-iconfont icon-gouwulan icon-text"></text> <text class="tips">购物车</text> <block v-if="$isRight(car_num)"> <view class="angle-mark" v-if="car_num<99">{{car_num || 0}}</view> <view class="angle-mark" v-else>99+</view> </block> </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: '', car_num: 0 }; }, 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(); }); this.getcarNum(); // setTimeout(function() {
// self.computerH();
// }, 100);
// this.createAtoZ();
}, methods: { getcarNum() { this.$http .get({ api: 'api/shopping/cart/count', header: { Authorization: this.$cookieStorage.get('user_token') }, }) .then(res => { if (res.data.code == 200) { if(res.data.data == null) { this.car_num = 0; }else { this.car_num = res.data.data; } } else { wx.showModal({ content: '请下拉页面刷新重试', showCancel: false }); } }) .catch(() => { wx.stopPullDownRefresh(); wx.hideLoading(); wx.showModal({ content: '请求失败', showCancel: false }); }); }, 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> .fixed-right{ position: fixed; right: 62rpx; bottom: 400rpx; width: max-content; height: max-content; z-index: 9; .fixed-cart{ width: 110rpx; height: 110rpx; border-radius: 50%; background-color: #FFFFFF; border: 1rpx solid #DEDEDE; display: flex; justify-content: center; align-items: center; flex-direction: column; color: #333333; position: relative; margin-top: 30rpx; .icon-text{ font-size: 50rpx; line-height: 1; } .tips{ font-size: 20rpx; color: #333333; } .angle-mark{ position: absolute; right: 4rpx; top: 4rpx; width: 40rpx; height: 40rpx; background-color: #15716E; border-radius: 50%; font-size: 20rpx; display: flex; justify-content: center; align-items: center; color: #FFFFFF; } } .fixed-live{ background: #15716E; border-radius: 100rpx 5rpx 100rpx 100rpx; border: none; color: #FFFFFF; // animation: bounceIn 1s .2s ease both;
backface-visibility:visible; transform-origin:center center; animation: demo 2s 0s infinite ease normal none ; // &>text:nth-child(1){
// animation: fadeInRightBig 1s .1s ease both;
// }
.tips{ color: #FFFFFF; } } } .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; } } .brand-item:last-child{ margin-bottom: 0rpx; } .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>
|