2025-06-04 11:18:40 +08:00

303 lines
5.9 KiB
Vue

<template>
<view class="popup" v-show="show">
<view class="bg" @tap="cancelMultiple"></view>
<view class="selectMultiple" :animation="animationData">
<view class="multipleBody">
<view class="title">
<view class="close" @tap="cancelMultiple">
取消
</view>
<view class="name">
{{title}}
</view>
<view class="confirm" @tap="confirmMultiple">
确认
</view>
</view>
<view class="list">
<view class="mask mask-top"></view>
<view class="mask mask-bottom"></view>
<scroll-view class="diet-list" scroll-y="true">
<view v-for="(item, index) in list" :class="['item', item.selected ? 'checked' : '']"
@tap="onChange(index, item)">
<span>{{item.label}}</span>
<view class="icon" v-show="item.selected">
<icon type="success_no_circle" size="16" color="#2D8DFF" />
</view>
</view>
</scroll-view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
name: "multiple-picker",
data() {
return {
// 选中数量
selectNum: 0,
// 选中值
value: [],
// 选中列表
selected: [],
// 列表数据
list: [],
// 出场动画
animationData: {},
};
},
props: {
// 最大选中
selectMax: {
type: Number,
default: 100
},
// 是否显示
show: {
type: Boolean,
default: false
},
// 标题
title: {
type: String,
default: ''
},
//数据列表
columns: {
type: Array,
default: [{
label: '测试1',
value: '1',
}]
},
// 默认选中
defaultIndex: {
type: Array,
default: [],
}
},
watch: {
// 监听是否显示
show(val) {
if (val) {
this.openMultiple();
}
}
},
methods: {
// 列点击事件
onChange(index, item) {
// console.log("多选选中", this.selectMax,this.list.length)
// 是否已选中
if (this.value.indexOf(item.value.toString()) >= 0) {
this.list[index].selected = false;
this.selectNum --
} else {
if (this.selectNum == this.selectMax) {
uni.showToast({
title: '最多选中' + this.selectMax +'个',
icon: 'error',
});
return
}
this.list[index].selected = true;
this.selectNum ++
}
// this.value.push(item.value.toString())
// this.selected.push({
// label: item.label,
// value: item.value,
// });
// // 筛选已勾选数据
this.value = [];
this.selected = [];
this.list.forEach((col_item, col_index) => {
if(col_item.selected) {
this.value.push(col_item.value.toString());
this.selected.push({
label: col_item.label,
value: col_item.value,
});
}
});
this.$emit("change", {
selected: this.selected,
value: this.value
});
},
// 弹出框开启触发事件
openMultiple() {
// 初始化列表数据,默认勾选数据
this.selectNum = 0
this.value = this.defaultIndex;
this.columns.forEach((item, index) => {
this.$set(item, "selected", false);
if (this.value.indexOf(item.value.toString()) >= 0) {
this.selectNum ++
item.selected = true;
}
});
this.list = Object.assign([], this.columns);
// 弹出动画
this.openAnimation();
},
// 确认
confirmMultiple() {
this.$emit("confirm", {
selected: this.selected,
value: this.value
});
},
// 关闭/取消
cancelMultiple() {
this.selectNum = 0
this.$emit("cancel");
},
// 展开动画
openAnimation() {
var animation = uni.createAnimation()
animation.translate(0, 300).step({
duration: 0
});
this.animationData = animation.export();
this.$nextTick(() => {
animation.translate(0, 0).step({
duration: 300,
timingFunction: 'ease'
});
this.animationData = animation.export()
})
},
}
}
</script>
<style scoped lang="scss">
.popup {
width: 100%;
height: 100vh;
position: fixed;
z-index: 10075;
left: 0;
bottom: 0;
.bg {
width: 100%;
height: 100%;
background-color: rgba(black, .5);
}
}
.selectMultiple {
width: 100%;
position: absolute;
left: 0;
bottom: 0;
background-color: white;
.multipleBody {
width: 100%;
padding: 30rpx;
box-sizing: border-box;
padding-bottom: 80rpx;
.title {
font-size: 28rpx;
display: flex;
flex-direction: row;
.close {
width: 80rpx;
opacity: .5;
}
.name {
width: 530rpx;
text-align: center;
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
}
.confirm {
width: 80rpx;
text-align: right;
color: #2D8DFF;
}
}
.list {
width: 100%;
padding-top: 30rpx;
position: relative;
.mask {
width: 100%;
height: 120rpx;
position: absolute;
left: 0;
z-index: 2;
pointer-events: none;
&.mask-top {
top: 30rpx;
background-image: linear-gradient(to bottom, #fff, rgba(#fff, 0));
}
&.mask-bottom {
bottom: 0;
background-image: linear-gradient(to bottom, rgba(#fff, 0), #fff);
}
}
.diet-list {
max-height: 400rpx;
}
.item {
position: relative;
width: 100%;
line-height: 40rpx;
border-bottom: 1px solid rgba($color: #000000, $alpha: .05);
padding: 20rpx 0;
font-size: 30rpx;
box-sizing: border-box;
text-align: center;
span {
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
padding: 0 40rpx;
}
.icon {
position: absolute;
right: 10rpx;
top: 50%;
transform: translateY(-50%);
height: 30rpx;
}
&.checked {
color: #2D8DFF;
}
&:last-child {
border-bottom: none;
margin-bottom: 60rpx;
}
&:first-child {
margin-top: 60rpx;
}
}
}
}
}
</style>