<template>
|
<view class="dropdown-container" :style="{ '--theme-color': themeColor }">
|
<!-- 触发按钮 -->
|
<view class="dropdown-trigger" @click="toggleDropdown">
|
<uni-icons type="more-filled" size="20" color="#666"></uni-icons>
|
<view class="dropdown-icon" :class="{ 'rotate': isOpen }">
|
<uni-icons type="arrowdown" size="16" color="#666"></uni-icons>
|
</view>
|
</view>
|
|
<!-- 下拉菜单 -->
|
<view
|
class="dropdown-menu"
|
:class="[placementClass]"
|
v-if="isOpen"
|
@click.stop
|
>
|
<scroll-view scroll-y class="dropdown-scroll" :style="{ maxHeight: maxHeight + 'px' }">
|
<view
|
v-for="(item, index) in options"
|
:key="index"
|
class="dropdown-item"
|
@click="selectItem(item)"
|
>
|
<text>{{ item[labelKey] }}</text>
|
</view>
|
</scroll-view>
|
</view>
|
|
<!-- 遮罩层 -->
|
<view
|
class="dropdown-mask"
|
v-if="isOpen"
|
@click="closeDropdown"
|
></view>
|
</view>
|
</template>
|
|
<script>
|
export default {
|
name: 'DropdownMenu',
|
props: {
|
// 选项列表
|
options: {
|
type: Array,
|
default: () => []
|
},
|
// 选项对象中显示文本的key
|
labelKey: {
|
type: String,
|
default: 'label'
|
},
|
// 选项对象中值的key
|
valueKey: {
|
type: String,
|
default: 'command'
|
},
|
// 主题颜色
|
themeColor: {
|
type: String,
|
default: '#409EFF'
|
},
|
// 下拉菜单最大高度
|
maxHeight: {
|
type: Number,
|
default: 300
|
},
|
// 菜单弹出位置(top/bottom)
|
placement: {
|
type: String,
|
default: 'bottom',
|
validator: (value) => ['top', 'bottom'].includes(value)
|
}
|
},
|
data() {
|
return {
|
isOpen: false,
|
selectedItem: null
|
}
|
},
|
computed: {
|
placementClass() {
|
return `placement-${this.placement}`;
|
}
|
},
|
methods: {
|
toggleDropdown() {
|
this.isOpen = !this.isOpen
|
if (this.isOpen) {
|
this.$emit('open')
|
} else {
|
this.$emit('close')
|
}
|
},
|
closeDropdown() {
|
this.isOpen = false
|
this.$emit('close')
|
},
|
selectItem(item) {
|
this.selectedItem = item
|
this.closeDropdown()
|
|
// 根据配置返回整个对象或value值
|
const emitValue = typeof item === 'object' ? item[this.valueKey] : item
|
this.$emit('input', emitValue)
|
this.$emit('change', emitValue)
|
}
|
}
|
}
|
</script>
|
|
<style lang="scss" scoped>
|
.dropdown-container {
|
position: relative;
|
display: inline-block;
|
z-index: 10;
|
}
|
|
.dropdown-trigger {
|
height: 70rpx;
|
line-height: 70rpx;
|
border-radius: 8rpx;
|
background-color: #fff;
|
box-sizing: border-box;
|
cursor: pointer;
|
|
&:active {
|
opacity: 0.8;
|
}
|
}
|
|
.dropdown-text {
|
flex: 1;
|
font-size: 28rpx;
|
color: #333;
|
overflow: hidden;
|
text-overflow: ellipsis;
|
white-space: nowrap;
|
}
|
|
.dropdown-icon {
|
transition: transform 0.3s;
|
margin-left: 10rpx;
|
|
&.rotate {
|
transform: rotate(180deg);
|
}
|
}
|
|
.dropdown-menu {
|
position: absolute;
|
left: -50rpx;
|
display: inline-block;
|
white-space: nowrap;
|
background-color: #fff;
|
border: 1rpx solid #EBEEF5;
|
border-radius: 8rpx;
|
// box-shadow: 0 2rpx 12rpx 0 rgba(0, 0, 0, 0.1);
|
z-index: 100;
|
overflow: hidden;
|
|
&.placement-bottom {
|
top: 80rpx;
|
}
|
|
&.placement-top {
|
bottom: 80rpx;
|
}
|
}
|
|
.dropdown-scroll {
|
width: 100%;
|
}
|
|
.dropdown-item {
|
display: flex;
|
align-items: center;
|
justify-content: space-between;
|
padding: 0 20rpx;
|
height: 80rpx;
|
line-height: 80rpx;
|
font-size: 28rpx;
|
color: #606266;
|
|
&:active {
|
background-color: #f5f7fa;
|
}
|
|
&.active {
|
color: var(--theme-color);
|
font-weight: bold;
|
}
|
}
|
|
.dropdown-mask {
|
position: fixed;
|
top: 0;
|
left: 0;
|
right: 0;
|
bottom: 0;
|
background-color: transparent;
|
z-index: 99;
|
}
|
</style>
|