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.
395 lines
9.5 KiB
395 lines
9.5 KiB
<template>
|
|
<view class="wSelect" :class="show ? 'active' : ''" :style="{
|
|
width: width,
|
|
height: height,
|
|
backgroundColor: bgColor,
|
|
borderRadius: round ? '6rpx' : 'none'
|
|
}">
|
|
<view @click="openSelect" class="pickerSelect">
|
|
<view :style="{ height: height }" v-if="multiple" class="multipleChoice">
|
|
<view class="defaultValue" :style="{ color: color }" v-if="!inputData && multiSelectList.length < 1">
|
|
{{ defaultValue }}
|
|
</view>
|
|
<view class="option" v-if="multiSelectList.length > 0">
|
|
<view class="">{{ multiSelectList[0][valueName] }}</view>
|
|
<image class="img" @click.stop="multiDelete" :src="refreshUrl" mode=""></image>
|
|
</view>
|
|
<view v-if="multiSelectList.length > 1" class="more">{{ multiLength }}</view>
|
|
<input :disabled="!filterable"
|
|
:style="{ height: height, paddingRight: '30rpx', fontSize: '28rpx', color: color }"
|
|
@input="inputChange" type="text" v-model="inputData" />
|
|
</view>
|
|
<input v-else :disabled="!filterable"
|
|
:style="{ height: height, paddingRight: '30rpx', fontSize: '30rpx', color:'#000' }" @input="inputChange"
|
|
:placeholder="defaultValue" :placeholder-style="placeholderColor" type="text" v-model="inputData" />
|
|
<view v-if="!inputData || !showClose" :class="show ? 'arrow-up' : 'arrow'"></view>
|
|
<view class="showClose" v-if="showClose && inputData">
|
|
<image @click.stop="refreshValue" :src="refreshUrl" mode=""></image>
|
|
</view>
|
|
<view v-show="show" :class="isShow ? 'animation-top' : 'animation-bottom'" class="tips"
|
|
:style="{ top: tipsPositon }"></view>
|
|
</view>
|
|
<!-- 单选时的下拉框 -->
|
|
<view v-if="!multiple" :style="{ width: '75%', color: '#737478' }" v-show="show"
|
|
:class="isShow ? 'animation-top' : 'animation-bottom'" class="content">
|
|
<view class="item" :class="value == item[valueName] ? 'choose' : ''" v-for="(item, index) in listData"
|
|
:key="index" @click="clickSelect(item)">
|
|
{{ item[valueName] }}
|
|
</view>
|
|
<view class="item" v-if="listData.length < 1">无匹配项</view>
|
|
</view>
|
|
<!-- 多选的下拉框 -->
|
|
<view v-else :style="{ width: width }" v-show="show" :class="isShow ? 'animation-top' : 'animation-bottom'"
|
|
class="content">
|
|
<view class="item" :class="multiSelectList.find(res => res[valueName] == item[valueName]) ? 'choose' : ''"
|
|
v-for="(item, index) in listData" :key="index" @click="multiSelect(item)">
|
|
{{ item[valueName] }}
|
|
</view>
|
|
<view class="item" v-if="listData.length < 1">无匹配项</view>
|
|
</view>
|
|
<view v-if="show" @click="closeContentSelect" class="contentMask"></view>
|
|
</view>
|
|
</template>
|
|
<script>
|
|
export default {
|
|
name: 'wSelect',
|
|
props: {
|
|
//是否多选
|
|
multiple: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
//是否可搜索
|
|
filterable: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
//是否显示关闭按钮
|
|
showClose: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
width: {
|
|
type: String,
|
|
default: '300rpx'
|
|
},
|
|
color: {
|
|
type: String,
|
|
default: '#606266'
|
|
},
|
|
placeholderColor: {
|
|
type: String,
|
|
default: 'color:#bcbec4'
|
|
},
|
|
bgColor: {
|
|
type: String,
|
|
default: '#fff'
|
|
},
|
|
height: {
|
|
type: String,
|
|
default: '60rpx'
|
|
},
|
|
//默认显示的内容
|
|
defaultValue: {
|
|
type: String,
|
|
default: '请选择'
|
|
},
|
|
//显示的内容
|
|
valueName: {
|
|
type: String,
|
|
required: true
|
|
},
|
|
list: {
|
|
type: Array,
|
|
default: () => [],
|
|
required: true
|
|
},
|
|
//双向绑定的值
|
|
value: {
|
|
type: String,
|
|
default: ''
|
|
},
|
|
round: {
|
|
type: Boolean,
|
|
default: true
|
|
}
|
|
},
|
|
watch: {
|
|
value: {
|
|
immediate: true,
|
|
handler(newValueData) {
|
|
if (!this.inputData) {
|
|
this.inputData = newValueData
|
|
}
|
|
}
|
|
}
|
|
},
|
|
data() {
|
|
return {
|
|
show: false,
|
|
isShow: false,
|
|
multiSelectList: [],
|
|
inputData: '',
|
|
listData: this.list,
|
|
refreshUrl: 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDQ4IDQ4IiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxyZWN0IHdpZHRoPSI0OCIgaGVpZ2h0PSI0OCIgZmlsbD0id2hpdGUiIGZpbGwtb3BhY2l0eT0iMC4wMSIvPjxwYXRoIGQ9Ik0yNCA0NEMzNS4wNDU3IDQ0IDQ0IDM1LjA0NTcgNDQgMjRDNDQgMTIuOTU0MyAzNS4wNDU3IDQgMjQgNEMxMi45NTQzIDQgNCAxMi45NTQzIDQgMjRDNCAzNS4wNDU3IDEyLjk1NDMgNDQgMjQgNDRaIiBmaWxsPSJub25lIiBzdHJva2U9IiM3YzZlNmUiIHN0cm9rZS13aWR0aD0iNCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPjxwYXRoIGQ9Ik0yOS42NTY5IDE4LjM0MzFMMTguMzQzMiAyOS42NTY4IiBzdHJva2U9IiM3YzZlNmUiIHN0cm9rZS13aWR0aD0iNCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+PHBhdGggZD0iTTE4LjM0MzIgMTguMzQzMUwyOS42NTY5IDI5LjY1NjgiIHN0cm9rZT0iIzdjNmU2ZSIgc3Ryb2tlLXdpZHRoPSI0IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz48L3N2Zz4='
|
|
}
|
|
},
|
|
computed: {
|
|
multiLength() {
|
|
const length = this.multiSelectList.length - 1
|
|
return '+' + length
|
|
},
|
|
tipsPositon() {
|
|
let num = this.height.replace('rpx', '')
|
|
let numAdd = Number(num) + Number(10)
|
|
return numAdd + 'rpx'
|
|
}
|
|
},
|
|
methods: {
|
|
openSelect() {
|
|
this.listData = this.list
|
|
console.log("listData>>>", this.listData)
|
|
if (this.show === true) {
|
|
this.isShow = false
|
|
} else {
|
|
this.isShow = true
|
|
}
|
|
setTimeout(() => {
|
|
this.show = !this.show
|
|
}, 200)
|
|
},
|
|
clickSelect(item) {
|
|
this.$emit('input', item[this.valueName])
|
|
this.inputData = item[this.valueName]
|
|
this.$emit('change', item)
|
|
this.show = false
|
|
},
|
|
inputChange(e) {
|
|
console.log(e.detail.value)
|
|
let value = e.detail.value
|
|
this.$emit('input', value)
|
|
if (value) {
|
|
this.listData = this.listData.filter(item => item[this.valueName].includes(value))
|
|
} else {
|
|
this.listData = this.list
|
|
}
|
|
},
|
|
multiSelect(item) {
|
|
let index = this.multiSelectList.findIndex(res => res[this.valueName] == item[this.valueName])
|
|
if (index > -1) {
|
|
this.multiSelectList.splice(index, 1)
|
|
} else {
|
|
this.multiSelectList.push(item)
|
|
}
|
|
this.inputData = ''
|
|
this.listData = this.list
|
|
this.$emit('input', this.multiSelectList)
|
|
this.$emit('change', item)
|
|
},
|
|
refreshValue() {
|
|
this.$emit('input', '')
|
|
this.inputData = ''
|
|
this.listData = this.list
|
|
this.$emit('change', '')
|
|
this.show = false
|
|
},
|
|
multiDelete() {
|
|
this.multiSelectList.splice(0, 1)
|
|
this.$emit('input', this.multiSelectList)
|
|
if (this.multiSelectList.length < 1) {
|
|
this.show = false
|
|
}
|
|
},
|
|
closeContentSelect() {
|
|
this.isShow = false
|
|
setTimeout(() => {
|
|
this.show = false
|
|
}, 200)
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
<style lang="scss" scoped>
|
|
.wSelect {
|
|
// border: 2rpx solid #dcdfe6;
|
|
transition: all 0.5s;
|
|
|
|
.pickerSelect {
|
|
border-radius: 6rpx;
|
|
padding: 0 20rpx;
|
|
position: relative;
|
|
transition: all 0.6s;
|
|
display: flex;
|
|
align-items: center;
|
|
|
|
input {
|
|
flex: 1;
|
|
}
|
|
|
|
.tips {
|
|
position: absolute;
|
|
margin-left: 30rpx;
|
|
width: 0;
|
|
height: 0;
|
|
border-bottom: 12rpx solid #fff;
|
|
border-left: 12rpx solid transparent;
|
|
border-right: 12rpx solid transparent;
|
|
z-index: 1000;
|
|
}
|
|
|
|
.showClose {
|
|
width: 30rpx;
|
|
height: 30rpx;
|
|
position: absolute;
|
|
right: 14rpx;
|
|
top: 50%;
|
|
transform: translateY(-50%);
|
|
|
|
image {
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
}
|
|
|
|
.arrow {
|
|
transition: all 0.3s;
|
|
position: absolute;
|
|
top: 44%;
|
|
right: 20rpx;
|
|
border-left: 2rpx solid #999999;
|
|
border-bottom: 2rpx solid #999999;
|
|
height: 16rpx;
|
|
width: 16rpx;
|
|
transform: translateY(-50%) rotate(-45deg);
|
|
-webkit-transform: translateY(-50%) rotate(-45deg);
|
|
border-right: 2rpx solid transparent;
|
|
border-top: 2rpx solid transparent;
|
|
display: inline-block;
|
|
}
|
|
|
|
.arrow-up {
|
|
@extend .arrow;
|
|
transform: rotate(-235deg);
|
|
}
|
|
|
|
.multipleChoice {
|
|
display: flex;
|
|
align-items: center;
|
|
|
|
input {
|
|
flex: 1;
|
|
}
|
|
|
|
.defaultValue {
|
|
position: absolute;
|
|
left: 20rpx;
|
|
}
|
|
|
|
.option {
|
|
display: flex;
|
|
align-items: center;
|
|
background-color: #f4f4f5;
|
|
border-radius: 10rpx;
|
|
font-size: 24rpx;
|
|
color: #aa93b1;
|
|
padding: 6rpx 12rpx;
|
|
|
|
.img {
|
|
margin-left: 4rpx;
|
|
width: 30rpx;
|
|
height: 30rpx;
|
|
}
|
|
}
|
|
|
|
.more {
|
|
background-color: #f4f4f5;
|
|
border-radius: 10rpx;
|
|
font-size: 24rpx;
|
|
color: #aa93b1;
|
|
margin-left: 10rpx;
|
|
padding: 6rpx 12rpx;
|
|
}
|
|
}
|
|
}
|
|
|
|
.content {
|
|
position: absolute;
|
|
margin-top: 20rpx;
|
|
padding: 20rpx;
|
|
border-radius: 4px;
|
|
background-color: #fff;
|
|
box-shadow: rgba(0, 0, 0, 0.5) 0px 3px 8px;
|
|
z-index: 999;
|
|
max-height: 300rpx;
|
|
overflow-y: auto;
|
|
|
|
.item {
|
|
padding: 10rpx;
|
|
height: 60rpx;
|
|
line-height: 40rpx;
|
|
margin-bottom: 10rpx;
|
|
font-size: 28px;
|
|
color: #000;
|
|
}
|
|
|
|
.choose {
|
|
background-color: #f5f7fa;
|
|
color: #409eff;
|
|
font-weight: 700;
|
|
}
|
|
}
|
|
|
|
.animation-top {
|
|
animation-name: slide-top;
|
|
animation-duration: 0.5s;
|
|
animation-timing-function: ease-out;
|
|
animation-fill-mode: both;
|
|
}
|
|
|
|
.animation-bottom {
|
|
animation-name: slide-bottom;
|
|
animation-duration: 0.2s;
|
|
animation-timing-function: ease-out;
|
|
animation-fill-mode: both;
|
|
}
|
|
|
|
@keyframes slide-top {
|
|
0% {
|
|
opacity: 0;
|
|
transform: translateY(-20%);
|
|
}
|
|
|
|
100% {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
}
|
|
|
|
@keyframes slide-bottom {
|
|
0% {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
|
|
100% {
|
|
opacity: 0;
|
|
transform: translateY(-20%);
|
|
}
|
|
}
|
|
}
|
|
|
|
.active {
|
|
// border: 2rpx solid #409eff;
|
|
}
|
|
|
|
.contentMask {
|
|
position: fixed;
|
|
left: 0;
|
|
top: 0;
|
|
bottom: 0;
|
|
right: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
z-index: 998;
|
|
}
|
|
</style>
|
|
|