<template>
<view class="uni-stat__select">
<span v-if="label" class="uni-label-text hide-on-phone">{{label + ':'}}</span>
<view class="uni-select">
<view class="uni-select__input-box" id="uni-select__input-box" @click="toggleSelector1($event)">
<!-- 显示插槽内容 -->
<slot></slot>
</view>
<view class="uni-select--mask" v-if="showSelector" @touchend="toggleSelector" @click="toggleSelector" />
<view class="uni-select__selector" :style="uniselectselectorstyle" v-if="showSelector">
<view class="uni-popper__arrow" :style="unipopperarrowstyle"></view>
<scroll-view scroll-y="true" class="uni-select__selector-scroll">
<view class="uni-select__selector-empty" v-if="mixinDatacomResData.length === 0">
<text>{{emptyTips}}</text>
</view>
<view v-else class="uni-select__selector-item" v-for="(item,index) in mixinDatacomResData"
:key="index" @click="change(item)">
<text :class="{'uni-select__selector__disabled': item.disable}">{{formatItemName(item)}}</text>
</view>
</scroll-view>
</view>
</view>
</view>
</template>
<script>
/**
* DataChecklist 数据选择器
* @description 通过数据渲染的下拉框组件
* @property {String} value 默认值
* @property {Array} localdata 本地数据 ,格式 [{text:'',value:''}]
* @property {Boolean} clear 是否可以清空已选项
* @property {Boolean} emptyText 没有数据时显示的文字 ,本地数据无效
* @property {String} label 左侧标题
* @property {String} placeholder 输入框的提示文字
* @event {Function} change 选中发生变化触发
*/
export default {
name: "uni-stat-select",
mixins: [uniCloud.mixinDatacom || {}],
data() {
return {
showSelector: false,
current: '',
mixinDatacomResData: [],
apps: [],
channels: [],
uniselectselectorstyle: "top: calc(100% + 4px);",
unipopperarrowstyle: "top: -6px;border-top-width: 0;border-bottom-color: #fff;"
};
},
props: {
localdata: {
type: Array,
default () {
return []
}
},
value: {
type: [String, Number],
default: ''
},
modelValue: {
type: [String, Number],
default: ''
},
label: {
type: String,
default: ''
},
placeholder: {
type: String,
default: '...'
},
emptyTips: {
type: String,
default: ''
},
clear: {
type: Boolean,
default: true
},
defItem: {
type: Number,
default: 0
},
},
created() {
this.last = `${this.collection}_last_selected_option_value`
if (this.collection && !this.localdata.length) {
this.mixinDatacomEasyGet()
}
},
watch: {
localdata: {
immediate: true,
handler(val, old) {
if (Array.isArray(val)) {
this.mixinDatacomResData = val
}
}
},
// #ifndef VUE3
value() {
this.initDefVal()
},
// #endif
// #ifdef VUE3
modelValue() {
this.initDefVal()
},
// #endif
mixinDatacomResData: {
immediate: true,
handler(val) {
if (val.length) {
this.initDefVal()
}
}
},
},
methods: {
initDefVal() {
let defValue = ''
if ((this.value || this.value === 0) && !this.isDisabled(this.value)) {
defValue = this.value
} else if ((this.modelValue || this.modelValue === 0) && !this.isDisabled(this.modelValue)) {
defValue = this.modelValue
} else {
let strogeValue
if (this.collection) {
strogeValue = uni.getStorageSync(this.last)
}
if (strogeValue || strogeValue === 0) {
defValue = strogeValue
} else {
let defItem = ''
if (this.defItem > 0 && this.defItem < this.mixinDatacomResData.length) {
defItem = this.mixinDatacomResData[this.defItem - 1].value
}
defValue = defItem
}
this.emit(defValue)
}
const def = this.mixinDatacomResData.find(item => item.value === defValue)
this.current = def ? this.formatItemName(def) : ''
},
/**
* @param {[String, Number]} value
* 判断用户给的 value 是否同时为禁用状态
*/
isDisabled(value) {
let isDisabled = false;
this.mixinDatacomResData.forEach(item => {
if (item.value === value) {
isDisabled = item.disable
}
})
return isDisabled;
},
clearVal() {
this.emit('')
if (this.collection) {
uni.removeStorageSync(this.last)
}
},
change(item) {
if (!item.disable) {
this.showSelector = false
this.current = this.formatItemName(item)
this.emit(item.value)
}
},
emit(val) {
this.$emit('change', val)
this.$emit('input', val)
this.$emit('update:modelValue', val)
if (this.collection) {
uni.setStorageSync(this.last, val)
}
},
toggleSelector() {
this.showSelector = !this.showSelector;
},
toggleSelector1(e) {
// 判断距离屏幕底部的距离
const res = uni.getSystemInfoSync();
const query = uni.createSelectorQuery().in(this);
query.select('#uni-select__input-box').boundingClientRect(data => {
if ((res.safeArea.height - data.bottom) < 80) {
this.uniselectselectorstyle = "bottom: calc(100% - 4px);;";
this.unipopperarrowstyle = "bottom: -6px;border-bottom-width: 0;border-top-color: #fff;";
} else {
this.uniselectselectorstyle = "top: calc(100% + 4px);";
this.unipopperarrowstyle = "top: -6px;border-top-width: 0;border-bottom-color: #fff;";
}
this.showSelector = !this.showSelector;
}).exec();
},
formatItemName(item) {
let {
text,
value,
channel_code
} = item
channel_code = channel_code ? `(${channel_code})` : ''
return this.collection.indexOf('app-list') > 0 ?
`${text}(${value})` :
(
text ?
text :
`未命名${channel_code}`
)
}
}
}
</script>
<style lang="scss">
$uni-base-color: #6a6a6a !default;
$uni-main-color: #3a3a3a !default;
$uni-secondary-color: #909399 !default;
$uni-border-3: #DCDCDC;
/* #ifndef APP-NVUE */
@media screen and (max-width: 100%) {
.hide-on-phone {
display: none;
}
}
/* #endif */
.uni-stat__select {
display: flex;
align-items: center;
cursor: pointer;
}
.uni-label-text {
font-size: 14px;
font-weight: bold;
color: $uni-base-color;
margin: auto 0;
margin-right: 5px;
}
.uni-select {
font-size: 14px;
// border: 1px solid $uni-border-3;
box-sizing: border-box;
border-radius: 1px;
padding: 0 5px;
position: relative;
/* #ifndef APP-NVUE */
display: flex;
user-select: none;
/* #endif */
flex-direction: row;
align-items: center;
// border-bottom: solid 1px $uni-border-3;
}
.uni-select__label {
font-size: 16px;
line-height: 22px;
padding-right: 10px;
color: $uni-secondary-color;
}
.uni-select__input-box {
min-height: 20px;
position: relative;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex: 1;
flex-direction: row;
align-items: center;
z-index: 1;
}
.uni-select__input {
flex: 1;
font-size: 14px;
height: 22px;
line-height: 22px;
}
.uni-select__input-plac {
font-size: 14px;
color: $uni-secondary-color;
}
.uni-select__selector {
/* #ifndef APP-NVUE */
box-sizing: border-box;
/* #endif */
position: absolute;
right: 2px;
width: auto;
background-color: #FFFFFF;
border: 1px solid #EBEEF5;
border-radius: 6px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
z-index: 1002;
padding: 5px 0;
}
.uni-select__selector-scroll {
/* #ifndef APP-NVUE */
max-height: 200px;
box-sizing: border-box;
/* #endif */
}
.uni-select__selector-empty,
.uni-select__selector-item {
/* #ifndef APP-NVUE */
display: flex;
cursor: pointer;
/* #endif */
line-height: 20px;
font-size: 14px;
text-align: center;
/* border-bottom: solid 1px $uni-border-3; */
padding: 5px 15px;
width: auto;
white-space: nowrap;
flex-wrap: nowrap;
}
.uni-select__selector-item:hover {
background-color: #f9f9f9;
}
.uni-select__selector-empty:last-child,
.uni-select__selector-item:last-child {
/* #ifndef APP-NVUE */
border-bottom: none;
/* #endif */
}
.uni-select__selector__disabled {
opacity: 0.4;
cursor: default;
}
/* picker 弹出层通用的指示小三角 */
.uni-popper__arrow {
position: absolute;
display: block;
width: 0;
height: 0;
border-color: transparent;
border-style: solid;
border-width: 6px;
filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03));
right: 10%;
margin-right: 3px;
}
.uni-popper__arrow::after {
content: " ";
top: 1px;
margin-left: -6px;
border-top-width: 0;
border-bottom-color: #fff;
}
.uni-select__input-text {
color: $uni-main-color;
white-space: nowrap;
text-overflow: ellipsis;
-o-text-overflow: ellipsis;
overflow: hidden;
width: auto;
}
.uni-select__input-placeholder {
color: $uni-base-color;
}
.uni-select--mask {
position: fixed;
top: 0;
bottom: 0;
right: 0;
left: 0;
z-index: 1000;
}
</style>
使用
<rudon-rowMenuDotDotDot :localdata="options" @change="menuAction($event, '10086')" class="item-top">
...
</rudon-rowMenuDotDotDot>
data() {
return {
options: [{
value: 'connect',
text: "连接"
},
{
value: 'detail',
text: "详情"
},
{
value: 'close',
text: "断开"
}
],
},
},
menuAction(action, rowId) {
// 忽略初始化时的传入的空操作
if (action === '') {
return
}
// 打印看参数
console.log(JSON.stringify(action))
console.log(JSON.stringify(rowId))
},
效果