【前端】印包客app
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.

226 lines
6.4 KiB

<template>
<view style="width: 100%; height: 100%">
<view class="select-mask" v-show="visible" @click="hideOption"></view>
<view class="select-section" :style="contentStyle" @click="showOption">
<text class="text" :class="label ? '' : 'placeholder'" :style="label ? '' : placeholderStyle">{{ label || placeholder }}</text>
<view class="icon"></view>
<view class="options-area" v-show="visible" :style="location[optionsAlign] || 'left:0'">
<slot>
<view class="option" v-for="item in options" :key="item.value" @click.stop="handleSelect(item)">
<text>{{ item.label }}</text>
<view v-show="isSelected(item.value)" class="icon"></view>
</view>
</slot>
</view>
</view>
</view>
</template>
<script>
const location = {
left: 'left:0',
right: 'right:0'
}
export default {
props: {
value: {
default: ''
},
placeholder: {
type: String,
default: '请选择'
},
/**
* 下拉框选项
* @param {Object} item
* @property {String} label - 选项名称
* @property {String} value - 选项值
*/
options: {
type: Array,
default: () => []
},
placeholderStyle: {
type: String,
default: ''
},
/**
* 指向select-section的样式
*/
contentStyle: {
type: String,
default: ''
},
/**
* 是否多选
*/
multiple: {
type: Boolean,
default: false
},
optionsAlign: {
type: String,
default: 'left'
}
},
data() {
return {
visible: false,
label: '',
location: Object.freeze(location)
}
},
created() {
this.handleChange(this.value, this.options)
},
methods: {
handleSelect(item) {
if (this.multiple) {
let value = []
if (!this.value) {
value = []
} else {
value = [...this.value]
}
const index = value.indexOf(item.value)
if (index > -1) {
value.splice(index, 1)
} else {
value.push(item.value)
}
this.$emit('input', value)
} else {
this.hideOption()
this.$emit('input', item.value)
}
},
showOption() {
this.visible = true
},
hideOption() {
this.visible = false
},
isSelected(value) {
if (!this.value) {
return false
}
if (this.multiple) {
return this.value.indexOf(value) > -1
} else {
return this.value === value
}
},
/**
* 处理外层val或options改变的情况
*/
handleChange(val, options) {
if (this.multiple) {
let labelList = []
for (let value of val) {
const item = options.find((item) => item.value === value)
if (item) {
labelList.push(item.label)
} else {
labelList.push(' ')
}
}
this.label = labelList.join(' , ')
} else {
let target = options.find((o) => o.value === val)
this.label = target?.label || ''
}
}
},
watch: {
value(val) {
this.handleChange(val, this.options)
},
options(val) {
this.handleChange(this.value, val)
}
}
}
</script>
<style lang="scss" scoped>
.select-section {
width: 100%;
height: 100%;
// min-height: 64rpx;
position: relative;
// 将fixed元素锚定到该元素
transform: translateX(0);
// z-index: 300;
z-index: 90;
display: flex;
align-items: center;
justify-content: space-between;
color: rgb(51, 51, 51);
font-size: 28rpx;
line-height: 40rpx;
white-space: nowrap;
padding: 12rpx 24rpx;
background-color: rgb(245, 245, 245);
border-radius: 8rpx;
.text {
flex: 1 1 auto;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.icon {
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADgAAAAgCAYAAABHA7voAAACtklEQVRYhdXYOW8TQRgG4CcxBHIQTA5uCCDRICSoKChB3MefBYmjpYCCDjokEnIQEDRIiPsqPltJjGe8a++G8EpWJPvLeB7P7OzsDGEIZ3AK27GEx/js/8oUzmMWH/EU80M4i3MdxR9wB582s4cDZB+uiwFan7sNXMBIxwc7cRQv8aP27g2WWYHrNEBj2N/qdpq4IbBbNTOij91wMNLAtJi/3TKKQ2Ikf1bevcEyJXA7MjXPG3iD45nCMVsP2cQt+dm1iCcNcY3N45g0chwHBPJXdf3sK7sFbjRTs4yH+NVovfEdC5iTRk5gv3+LnBS48UzNMh5ozbbGug++CWRuJHdhrxjxzUZOCNxEpmYDjo1AiiEnxeo1j999drZsxnFb/MCptKflhnWiE0gx5G6x+m4GckyM3GSmpo37657dDUgxZLP1WlAfclTgmpmaJI40kEC+EreQ1I10j/hlF3r1tI/sxM3Wd6SSxZEHsjaSOeSUuDZe9WirTHYI3HSmZkUPHL2BFENOi4VgsUB7vTIicDOZmhWxWvbcJxcBUgw5I6bVUsE2u2VEbJxnMzWFcRQHsnZNHpNG7hWb9+US7bazHdfEo08qpXCUA8JXvReefa12V0q0uw1XxXYwldI4ygMphtzf+rtasA9XxIY+ldf6wLUb7ydFkAfFruJNj++/jCOZmte4r88H736BFEMeEhv5t10+G8YlcXKQykA4BgMSyEWckD4ZOIwveLfuvWFcFAtWKgPjGBzI2kjmkEfFAdZ7cYp3oVWfSiU4qgFSDDknjvNO42SmrcpwxK9ZZZpiFzLW5/9XiqO6EWzni7gmj0uPZCqrKsZRPZA1ZG66dmYV99RwBlsHkHLI2nDUB6QYspZpuT51Agnkku4b9Pbe8nudHagbSCBfiOfFMfFU8gyPbJ2D5P83fwA+SqvvLFrSmAAAAABJRU5ErkJggg==')
no-repeat center center/cover;
width: 28rpx;
height: 16rpx;
margin-left: 16rpx;
}
}
.select-mask {
width: 750rpx;
height: 100vh;
background-color: transparent;
position: fixed;
z-index: 80;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.options-area {
z-index: 400;
position: fixed;
top: 100%;
max-width: 686rpx;
height: 184rpx;
border-radius: 6rpx;
border: 2rpx solid #f5f5f5;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
background-color: #fff;
overflow-y: auto;
color: rgb(0, 0, 0);
font-size: 28rpx;
.option {
height: 60rpx;
line-height: 60rpx;
// max-width: 500rpx;
// overflow-x: hidden;
// text-overflow: ellipsis;
padding: 0 24rpx;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1rpx solid #f5f5f5;
.icon {
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABa0lEQVRYhe2Tu0oDQRSG/zNYmNmnsDVlouJ7xIAgWIigWCiCZoPiFdyNCgGLgBDwhqCxt/ARMpvHSYLF7rHKhewk7iZxbeavBuYcvm+YcwATE5N/DiUBWSp+z/u+f8wsHhs3s1/9dzNJwAMENQikgWAZwFz/vUgCzsxpACDw02DNn32BBn6pXOskEYFBuCC+qjvWka526gLhl6OkXGkPq5+qQAhOuFWOPBjVExLI2s0zIpFDwBeqJGvjwgGUPVfu/9YX2gIikWPmNBPeFwrttXHgRLiLAtcLMJ93zkz8kj1sb8SBM1BRjtyNAtcK1F35IYB8r4KrmUJzOwocRPcNV+5EhWsFdBJEVMkWW3uj4ASqek5qKw58qIBOAoxyxm4VtHDiB+WmNuPCgQhruGi3VgKguw3EdAqBfG/a+dlzrfVx4JEEdBLdZsKrcmSkTZlIQCtBePMcuToJPJZAR8IHrgF8xp12ExMTk2H5ASlkxc57+JuCAAAAAElFTkSuQmCC')
no-repeat center center/cover;
width: 32rpx;
height: 32rpx;
}
}
}
.placeholder {
color: #ccc;
}
</style>