安装vant^2.12.38和better-scroll^2.5.1
javascript
<template>
<div>
<div class="dept-filter" @click="showFilter">
<div class="name">{{ params.name }}</div>
<img class="img" src="@/assets/images/index/filter.png" />
</div>
<van-popup v-model="show" position="bottom" :style="{ height: '70vh' }">
<div class="title-box">
<div class="title">店铺列表</div>
<img class="close" src="@/assets/images/index/close.png" @click="show = false" />
</div>
<div class="content-box">
<div class="left">
<div
@click="setDept(item, index)"
class="item"
:class="currentDeptIndex === index ? 'active' : ''"
v-for="(item, index) in list"
:key="item.deptId"
>
<div class="line"></div>
<div class="dept">{{ item.deptName }}</div>
</div>
</div>
<div class="right" @mousewheel="dataScroll" @touchmove="dataScroll">
<div
class="item right-item"
v-for="(item, index) in list"
:key="item.deptId"
:ref="'id' + item.deptId"
>
<div class="dept weight">{{ item.deptName }}</div>
<div class="store" :ref="'dept' + item.deptId" @click="setAllStore(item, index)">
<div
class="name"
:class="params.deptId === item.deptId && params.storeId === null ? 'active' : ''"
>
所有店铺
</div>
<img
v-if="params.deptId === item.deptId && params.storeId === null"
class="checked"
src="@/assets/images/index/checked.png"
/>
<!-- 占位 -->
<div v-else class="checked"></div>
</div>
<div class="dept" v-if="item.storeList.length !== 0">
部门下店铺({{ item.storeList.length }})
</div>
<div
class="store"
@click="setStore(item, child, index)"
v-for="child in item.storeList"
:key="child.storeId"
:ref="'dept' + item.deptId + child.storeId"
>
<div class="name" :class="params.storeId === child.storeId ? 'active' : ''">
{{ child.storeName }}
</div>
<img
v-if="params.storeId === child.storeId"
class="checked"
src="@/assets/images/index/checked.png"
/>
<div v-else class="checked"></div>
</div>
</div>
</div>
</div>
</van-popup>
</div>
</template>
<script>
export default {
name: 'DeptFilter1',
data() {
return {
show: false,
params: {
deptId: 1,
storeId: null,
name: '所有部门'
},
currentDeptIndex: 0,
list: [
{
deptId: 1,
deptName: '所有部门',
storeList: []
},
{
deptId: 2,
deptName: '软件研发部',
storeList: []
},
{
deptId: 3,
deptName: '事业部',
storeList: [
{ storeId: 1, storeName: '大药房官方旗舰店' },
{ storeId: 2, storeName: '拼多多事业店-拼多多事业店' },
{ storeId: 3, storeName: '拼多多事业店-拼多多事业店' }
]
},
{
deptId: 4,
deptName: '技术部',
storeList: [
{ storeId: 13, storeName: '大药房官方旗舰店' },
{ storeId: 4, storeName: '拼多多事业店-拼多多事业店' },
{
storeId: 5,
storeName:
'拼多多事业部拼多多拼多多事业部拼多多拼多多事业部拼多多拼多多事业部拼多多拼多多事业部拼多多'
},
{ storeId: 6, storeName: '拼多多事业店-拼多多事业店' },
{ storeId: 7, storeName: '拼多多事业店-拼多多事业店' },
{ storeId: 8, storeName: '拼多多事业店-拼多多事业店' },
{ storeId: 9, storeName: '拼多多事业店-拼多多事业店' },
{ storeId: 10, storeName: '拼多多事业店-拼多多事业店' }
]
},
{
deptId: 5,
deptName: '人事部',
storeList: [
{ storeId: 11, storeName: '大药房官方旗舰店' },
{ storeId: 12, storeName: '拼多多事业店-拼多多事业店' }
]
}
],
initTop: 0
}
},
methods: {
setDept(item, index) {
this.currentDeptIndex = index
this.$refs['id' + item.deptId][0].scrollIntoView({ behavior: 'smooth' })
},
setAllStore(item, index) {
this.params.deptId = item.deptId
this.params.storeId = null
this.params.name = item.deptName
this.currentDeptIndex = index
this.show = false
console.log(this.params)
this.$emit('getParams', this.params)
},
setStore(item, child, index) {
this.params.storeId = child.storeId
this.params.deptId = item.deptId
this.params.name = child.storeName
this.currentDeptIndex = index
this.show = false
console.log(this.params)
this.$emit('getParams', this.params)
},
showFilter() {
this.show = true
this.setInitTop()
this.topTop()
},
//设置选中元素置顶
topTop() {
this.$nextTick(() => {
let ref = 'dept' + this.params.deptId
if (this.params.storeId !== null) {
ref = 'dept' + this.params.deptId + this.params.storeId
}
this.$refs[ref][0].scrollIntoView({ behavior: 'smooth' })
})
},
//获取初始高度
setInitTop() {
this.$nextTick(() => {
setTimeout(() => {
const element = document.getElementsByClassName('title-box')[0]
this.initTop = element.getBoundingClientRect().top + element.clientHeight
}, 400)
})
},
dataScroll() {
const element = document.getElementsByClassName('right-item')
this.currentDeptIndex = 0
for (let i = 0; i < element.length; i++) {
if (element[i].getBoundingClientRect().top <= this.initTop) {
this.currentDeptIndex = i
}
}
}
}
}
</script>
<style scoped lang="scss">
.dept-filter {
display: flex;
align-items: center;
background: #191e28;
color: #fff;
height: 30px;
.name {
font-weight: 500;
font-size: 13px;
line-height: 13px;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
margin: 0 5px 0 10px;
max-width: 92px;
}
.img {
width: 12px;
height: 12px;
}
}
::v-deep .van-popup {
border-radius: 10px 10px 0 0;
background: linear-gradient(
179.71deg,
rgba(23, 28, 37, 1) 0.75%,
rgba(49, 55, 65, 1) 49.55%,
rgba(23, 28, 37, 1) 98.76%
);
overflow-y: hidden;
color: #ffffff;
}
.title-box {
font-weight: 600;
font-size: 15px;
padding: 16px 20px;
position: relative;
.title {
text-align: center;
}
.close {
width: 30px;
height: 30px;
position: absolute;
right: 20px;
top: 12px;
}
}
.content-box {
display: flex;
.left {
width: 108px;
height: calc(70vh - 52px);
overflow-y: scroll;
.item {
height: 48px;
display: flex;
align-items: center;
.line {
width: 4px;
height: 16px;
}
.dept {
padding: 0 12px 0 8px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-size: 14px;
}
}
.active {
.dept {
background: linear-gradient(
136.52deg,
rgba(4, 189, 248, 0.88) 4.9%,
rgba(8, 252, 223, 0.88) 132.73%
);
-webkit-background-clip: text !important;
-webkit-text-fill-color: transparent;
}
.line {
background: linear-gradient(
136.52deg,
rgba(4, 189, 248, 0.88) 4.9%,
rgba(8, 252, 223, 0.88) 132.73%
);
}
}
}
.right {
width: calc(100vw - 108px);
height: calc(70vh - 52px);
overflow-y: scroll;
.item {
border-top: 2px solid rgba(255, 255, 255, 0.5);
padding: 0 16px 0 16px;
&:first-child {
border: none;
}
.dept {
color: #bfbfbf;
font-size: 12px;
height: 25px;
display: flex;
align-items: flex-end;
}
.weight {
font-weight: 500;
}
.store {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12px 0;
font-size: 14px;
.name {
width: calc(100vw - 170px);
}
.active {
background: linear-gradient(
136.52deg,
rgba(4, 189, 248, 0.88) 4.9%,
rgba(8, 252, 223, 0.88) 132.73%
);
-webkit-background-clip: text !important;
-webkit-text-fill-color: transparent;
}
.checked {
width: 20px;
height: 20px;
margin-left: 10px;
}
}
}
}
}
</style>
展示效果