1.ScreenPopup筛选组件
<template>
<view class="screen-wrap">
<view class="screen-select">
<view class="s-item" v-for="(item,index) in menuList" :key="index" @tap="tapCurrentItem(item,index)">
<text class="s-title">{{cTitle[index]|| item.title}}</text>
<u-icon name="arrow-down-fill" size="10" />
</view>
</view>
<u-popup :show="show" :round="26">
<view class="screen-popup">
<view class="close-icon" @tap="show=false">
<u-icon name="close" color="#3D3D3D" size="22"></u-icon>
</view>
<view class="p-title">{{currentSelect.title }}</view>
<view class="p-content border-top">
<!-- 年份 -->
<template v-if="currentSelect.type=='year'">
<view class="tab-title">
<u-icon name="play-left-fill" size="10" @click="updateIndex('minus')"
:color="yearIndex == 0 ? '#9D9D9D' : ''" />
<text>{{years[yearIndex][0]}}-{{years[yearIndex][years.length-1]}}</text>
<u-icon name="play-right-fill" size="10" @click="updateIndex('plus')"
:color="yearIndex == years.length-1 ? '#9D9D9D' : ''" />
</view>
<view class="year-grid">
<view class="tab-item" v-for="y in years[yearIndex]" :key="y"
:class="{ active: query[currentSelect.key] == y }" @tap="tabItem(currentSelect,y)">
{{y}}
</view>
</view>
</template>
<!-- 输入框 -->
<input v-model="query[currentSelect.key]" v-if="currentSelect.type=='input'"
:placeholder="`请输入${currentSelect.title}`" class="mt-30" />
<!-- 单选列表 -->
<text v-if="child.label" v-for="(child,index) in currentSelect.tab" :key="index" class="tab-item"
:class="{ active: query[currentSelect.key] === child.value }" @tap="tabItem(currentSelect,child)">
{{ child.label}}
</text>
</view>
</view>
<view class="footer-btn space-between">
<button class="btn mr-30" @tap="reset">重置</button>
<button class="btn btn-primary" @tap="confirmBtn">确认</button>
</view>
</u-popup>
</view>
</template>
<script>
export default {
name: "ScreenPopup",
props: {
// 循环筛选项
menuList: {
type: Array,
default: () => []
},
// 筛选默认值
defaultValue: {
type: Object,
default: () => {}
}
},
data() {
const date = new Date()
let years = []
const year = date.getFullYear()
for (let i = 2020; i <= year + 19; i++) {
years.push(i)
}
function spArr(arr, num) { //arr是你要分割的数组,num是以几个为一组
let newArr = [] //首先创建一个新的空数组。用来存放分割好的数组
for (let i = 0; i < arr.length;) { //注意:这里与for循环不太一样的是,没有i++
newArr.push(arr.slice(i, i += num));
}
return newArr
}
years = spArr(years, 12)
const yearIndex = years.findIndex(yy => yy.includes(year))
return {
// 筛选弹窗显示
show: false,
// 年份二维数组,一次显示12个
years,
// 当前年份
year,
// 当前年份所在的数组索引
yearIndex,
// 当前点击的select保存对应的item数据
currentSelect: {},
// 点击后显示的标题
cTitle: [],
// 点击select存储当前index
cIndex: 0,
// 选择的参数
query: {},
};
},
created() {
this.copyQuery = JSON.parse(JSON.stringify(this.$props.defaultValue))
this.query = this.$props.defaultValue
},
methods: {
updateIndex(type) {
if (type == 'plus') {
this.years.length - 1 > this.yearIndex && this.yearIndex++
} else {
this.yearIndex != 0 && this.yearIndex--
}
},
tapCurrentItem(item, index) {
this.currentSelect = item
this.cIndex = index
this.show = true
},
isTabActive(item, child) {
return this.query[item.key] === child.value;
},
// 点击小项事件
tabItem(item, child) {
if (this.isTabActive(item, child)) {
// 如果已经选中,则取消选中
this.$set(this.query, item.key, '')
// 清空标题
this.$set(this.cTitle, this.cIndex, '')
} else {
// 更新提交数据
this.$set(this.query, item.key, typeof child == 'number' ? child : child.value)
// 选择后改变标题
this.$set(this.cTitle, this.cIndex, typeof child == 'number' ? child : child.label)
}
},
// 筛选确认按钮
confirmBtn() {
this.$emit('confirm', this.query)
this.show = false
},
// 重置
reset() {
// 重置所有选项
// this.query = this.copyQuery
// 重置打开项对应
this.$set(this.query, this.currentSelect.key, this.copyQuery[this.currentSelect.key])
if (this.currentSelect.type == 'year') {
this.yearIndex = 0
}
this.$set(this.cTitle, this.cIndex, '')
// 搜索
this.confirmBtn()
}
}
}
</script>
<style scoped lang="scss">
.screen-wrap {
.screen-select {
display: flex;
width: 100vw;
padding: 30rpx 0;
.s-item {
width: 150rpx;
display: flex;
margin-left: 30rpx;
.s-title {
margin-right: 8rpx;
}
}
}
// 弹窗
.screen-popup {
position: relative;
padding: 40rpx 30rpx 60rpx;
.close-icon {
position: absolute;
right: 40rpx;
}
// 标题
.p-title {
font-size: 34rpx;
text-align: center;
padding-bottom: 40rpx;
}
// 小项内容区
.p-content {
padding-bottom: 200rpx;
max-height: 50vh;
overflow: auto;
.tab-title {
display: flex;
justify-content: center;
margin: 30rpx 0;
text {
margin: 0 16rpx;
}
}
// 年份
.year-grid {
display: grid;
grid-template-columns: repeat(3, 3fr);
gap: 18rpx;
}
// 小项
.tab-item {
width: 100%;
display: inline-block;
box-sizing: border-box;
text-align: center;
padding: 20rpx;
margin: 20rpx 18rpx 0 0;
font-size: 26rpx;
background-color: #F6F6F6;
border: 1rpx solid #F6F6F6;
border-radius: 43rpx;
// 选中样式
&.active {
color: #DB4B40;
background: rgba(219, 75, 64, 0.1);
}
}
}
}
.footer-btn button {
border-radius: 60rpx;
}
}
</style>
2.页面中使用
<template>
<!-- 筛选组件 -->
<ScreenPopup ref="screen" :defaultValue="query" @confirm="screenConfirm" :menuList="menuList" />
</template>
<script>
data() {
return {
query: {
year:2024,
storeQry: ''
},
menuList: [
{ key: 'year', title: '工作年份', type: 'year' },
{
key: 'storeQry',
title: '接收状态',
tab: [{ label: '全部', value: '' }, { label: '采煤一区', value: 1 },{ label: '采煤2区', value: 2 }]
}]
}
},
methods: {
// 筛选确认
screenConfirm(data) {
this.query = data
this.init('query')
}
}
</script>