<template>
|
<el-popover ref="input-select" v-model="showPopover" :title="'请选择'+label" :disabled="disabled" :trigger="trigger" popper-class="input-popover" placement="bottom" width="300" @show="()=>{treeSuffixIcon='el-icon-yrt-xiangxiajiantou1 dropdown'}" @hide="()=>{treeSuffixIcon='el-icon-yrt-xiangxiajiantou1'}">
|
<el-input slot="reference" ref="input" v-model="currentValue" :style="{width: inputWidth}" :placeholder="placeholder" :disabled="disabled" :suffix-icon="treeSuffixIcon" class="input no-bg" @focus="(event)=>{onFocus($refs['input'], currentValue, event);}" @change="(val)=>{onInputChange($refs['input-select'], val);}" @keyup.native="(e)=>{onInputKeyup($refs['input'], e);}" @keydown.native="(event)=>{onInputKeydown($refs['input'], event);}" @blur="(event)=>{onBlur($refs['input'], currentValue, event);}">
|
</el-input>
|
<el-scrollbar :noresize="false" :native="false" wrap-class="popover-options scrollbar-wrap">
|
<slot>
|
<div v-for="(item, index) in currentOptions" :key="index" :class="['select-item', {'selected': currentValue === item[props.label], 'hover': currentValue === getItemLabel(item)}]" @click="onItemClick(getItemLabel(item), item)">
|
{{ getItemLabel(item) }}
|
</div>
|
<div v-if="!options.length" class="no-data">
|
没有数据
|
</div>
|
</slot>
|
</el-scrollbar>
|
</el-popover>
|
</template>
|
|
<script>
|
export default {
|
name: "input-select",
|
props: {
|
// 下拉框绑定值
|
value: {
|
type: String,
|
default: null
|
},
|
// 字段中文名
|
label: {
|
type: String,
|
default: null
|
},
|
// 候选项列表
|
options: {
|
type: Array,
|
required: true,
|
default: () => {
|
return [];
|
}
|
},
|
// 是否禁用
|
disabled: {
|
type: Boolean,
|
default: false
|
},
|
// 输入框宽度
|
inputWidth: {
|
type: String,
|
default: "100%"
|
},
|
// 提示内容
|
placeholder: {
|
type: String,
|
default: null
|
},
|
// 配置选项
|
props: {
|
type: Object,
|
default: () => {
|
return {
|
label: "label",
|
value: "value"
|
};
|
}
|
},
|
// 弹出框触发事件方式
|
trigger: {
|
type: String,
|
default: "click"
|
},
|
// 选中后隐藏下拉框
|
clickHidden: {
|
type: Boolean,
|
default: false
|
}
|
},
|
data() {
|
return {
|
// TREE选择器右侧下拉框
|
treeSuffixIcon: "el-icon-yrt-xiangxiajiantou1",
|
// 是否显示下拉框
|
isShowPopover: false
|
};
|
},
|
computed: {
|
// 当前筛选完数据
|
currentValue: {
|
get: function() {
|
return this.value;
|
},
|
set: function(val) {
|
this.$emit("input", val);
|
}
|
},
|
// 当前候选项
|
currentOptions: {
|
get: function() {
|
if (!this.value) {
|
return this.options;
|
} else {
|
const filterItems = this.options.filter(item => item.label && item.label.indexOf(this.value) >= 0);
|
return filterItems;
|
}
|
}
|
},
|
// 当前值
|
showPopover: {
|
get: function() {
|
return this.isShowPopover;
|
},
|
set: function(val) {
|
this.isShowPopover = val;
|
}
|
}
|
},
|
methods: {
|
// item单击事件
|
onItemClick(label, itemData) {
|
var ref = this.$refs["input-select"];
|
this.currentValue = label;
|
this.$emit("on-item-click", ref, label, itemData);
|
if (this.clickHidden) {
|
ref.doClose();
|
}
|
},
|
// 关闭下拉框
|
close() {
|
var ref = this.$refs["input-select"];
|
ref.doClose();
|
},
|
// input change事件
|
onInputChange(ref, val) {
|
this.$emit("on-change", ref, val);
|
},
|
// input change事件
|
onInputKeyup(ref, e) {
|
// Up key
|
if (e.keyCode === 38) {
|
let existIndex = this.options.findIndex(item => {
|
return item[this.props.label] === this.currentValue;
|
});
|
existIndex -= 1;
|
if (existIndex < 0) {
|
existIndex = this.options.length - 1;
|
}
|
const itemData = this.options.find((item, index) => {
|
return index === existIndex;
|
});
|
this.currentValue = itemData[this.props.label];
|
this.$emit("on-row-change", ref, this.currentValue, itemData);
|
return;
|
}
|
// Down key
|
if (e.keyCode === 40) {
|
let existIndex = this.options.findIndex(item => {
|
return item[this.props.label] === this.currentValue;
|
});
|
existIndex += 1;
|
if (existIndex >= this.options.length) {
|
existIndex = 0;
|
}
|
const itemData = this.options.find((item, index) => {
|
return index === existIndex;
|
});
|
this.currentValue = itemData[this.props.label];
|
this.$nextTick(() => {
|
this.$emit("on-row-change", ref, this.currentValue, itemData);
|
});
|
return;
|
}
|
// Enter key
|
if (e.keyCode === 13) {
|
this.showPopover = !this.showPopover;
|
this.$refs.input.select();
|
this.$refs.input.focus();
|
return;
|
}
|
this.$emit("on-key-up", ref, this.currentValue, e);
|
},
|
// input keydown事件
|
onInputKeydown(ref, event) {
|
this.$emit("on-key-down", ref, this.currentValue, event);
|
},
|
// 当值当前行
|
setCurrentIndex(existIndex) {
|
var ref = this.$refs["input"];
|
const itemData = this.options.find((item, index) => {
|
return index === existIndex;
|
});
|
if (itemData) {
|
this.currentValue = itemData[this.props.label];
|
this.$nextTick(() => {
|
this.$emit("on-row-change", ref, this.currentValue, itemData);
|
});
|
// this.$refs["input-select"].doClose();
|
}
|
},
|
// 判断是否有选中项
|
getCurrrentIndex() {
|
const existIndex = this.options.findIndex(item => {
|
return item[this.props.label] === this.currentValue;
|
});
|
return existIndex;
|
},
|
// 获得焦点
|
onFocus(ref, val, event) {
|
var disabled = ref.$attrs.disabled;
|
if (disabled) return;
|
|
this.$emit("on-focus", ref, val, event);
|
},
|
// 失去焦点
|
onBlur(ref, val, event) {
|
var disabled = ref.$attrs.disabled;
|
if (disabled) return;
|
|
this.$emit("on-blur", ref, val, event);
|
},
|
focus() {
|
this.$refs.input.focus();
|
},
|
// 下拉框数据项-label值
|
getItemLabel(item) {
|
if (typeof item === "string") {
|
return item;
|
} else {
|
return item[this.props.label] || item[this.props.value];
|
}
|
},
|
// 下拉框数据项-label值
|
getItemValue(item) {
|
if (typeof item === "string") {
|
return item;
|
} else {
|
return item.value !== null ? item[this.props.value] : item[this.props.label];
|
}
|
}
|
}
|
};
|
</script>
|
|
<style lang="scss" scoped>
|
.input {
|
/deep/ .el-input__icon.el-icon-yrt-xiangxiajiantou1 {
|
transition: all 0.6s;
|
-moz-transition: all 0.6s; /* Firefox 4 */
|
-webkit-transition: all 0.6s; /* Safari and Chrome */
|
-o-transition: all 0.6s; /* Opera */
|
height: 36px;
|
&.dropdown {
|
transform: rotateZ(-180deg) translateY(3px);
|
-ms-transform: rotateZ(-180deg) translateY(3px); /* Internet Explorer */
|
-moz-transform: rotateZ(-180deg) translateY(3px); /* Firefox */
|
-webkit-transform: rotateZ(-180deg) translateY(3px); /* Safari 和 Chrome */
|
-o-transform: rotateZ(-180deg) translateY(3px); /* Opera */
|
}
|
}
|
}
|
.select-item {
|
font-size: 14px;
|
padding: 0 20px;
|
position: relative;
|
white-space: nowrap;
|
overflow: hidden;
|
text-overflow: ellipsis;
|
color: #606266;
|
height: 34px;
|
line-height: 34px;
|
-webkit-box-sizing: border-box;
|
box-sizing: border-box;
|
cursor: pointer;
|
&.hover,
|
&:hover {
|
background-color: #f5f7fa;
|
}
|
&:last-child {
|
margin-bottom: 20px;
|
}
|
&.selected {
|
color: #409eff;
|
font-weight: 700;
|
}
|
}
|
.no-data {
|
font-size: 14px;
|
padding: 0 20px;
|
position: relative;
|
white-space: nowrap;
|
overflow: hidden;
|
text-overflow: ellipsis;
|
color: #606266;
|
height: 34px;
|
line-height: 34px;
|
-webkit-box-sizing: border-box;
|
box-sizing: border-box;
|
&:last-child {
|
margin-bottom: 20px;
|
}
|
}
|
.el-scrollbar {
|
/deep/ .popover-options.scrollbar-wrap {
|
max-height: 200px;
|
overflow-x: hidden;
|
padding: 0px;
|
}
|
}
|
</style>
|