<template>
<div class="selected" :style="{width:(width?width+'px':'100%')}">
<div class="select-container" @click="openCtrl=!openCtrl" @mouseenter="mouseenter" @mouseleave="closeIconCtrl=false;">
<p v-show="(selectArr.length==0&&type==='multiple')||(!selectedObj[keyName]&&type==='single')" class="select-placeholder">{{ placeholder }}</p>
<Icon v-show="!closeIconCtrl" type="ios-arrow-down" :class="arrowDownClass" size="16" />
<Icon v-if="closeIconCtrl" type="ios-close-circle" class="clear-selected" @click.stop="clearSelected" />
<!-- 多选样式 -->
<template v-if="type=='multiple'">
<div v-for="(item,index) in selectArr" :key="index" class="select-tag">
<span class="tag-text">{{ item[keyName] }}</span><Icon type="ios-close" class="ios-close" size="16" @click.stop="deleteItem(item[keyId])" />
</div>
</template>
<!-- 单选样式 -->
<p v-if="type=='single'" class="selected-text textover">{{ selectedObj[keyName] }}</p>
</div>
<!-- 搜索框 -->
<Input v-show="openCtrl" v-model="keyword" type="text" class="select-search" :placeholder="placeholderInput" @on-keyup="searchKeyword" />
<!-- scroll列表 -->
<div :class="selectListClass" :style="{bottom:data.length==0&&openCtrl?'-84px':-(height+32)+'px'}">
<Scroll v-if="data.length!=0" v-show="openCtrl" :on-reach-bottom="handleReachBottom"
:height="height" :distance-to-edge="10"
>
<div v-for="(item, index) in data"
:key="index" :class="[(tempIdArr.indexOf(item[keyId])>-1||selectedObj[keyId]==item[keyId])?'list-item-active':'',
(tempDisabledIdArr&&tempDisabledIdArr.indexOf(item[keyId])>-1||tempDisabledIdArr[0]==item[keyId])?'list-item-disabled':'',
'list-item']"
@click="(tempDisabledIdArr&&tempDisabledIdArr.indexOf(item[keyId])>-1||tempDisabledIdArr[0]==item[keyId])?'':chooseItem(item)"
>
<div>
<p style="line-height:18px;">{{ item[keyName] }}<br />
<slot name="moreText" :item="item"></slot>
</p>
</div>
<Icon type="md-checkmark" class="checked-icon" />
</div>
</Scroll>
<Row v-if="data.length==0&&openCtrl" class="no-data">暂无数据</Row>
</div>
</div>
</template>
<script>
export default {
components: {},
props: {
path: {
type: String,
required: true
},
keyName: {
type: String,
required: true
},
keyId: {
type: String,
default: 'id'
},
keyCode: {
type: String
},
placeholder: {
type: String,
default: '请选择成员组'
},
placeholderInput: {
type: String,
default: '请输入关键字搜索'
},
type: {
type: String,
default: 'single'
},
height: {
type: [Number, String],
default: 200
},
width: {
type: Number
},
params: {
type: Object
},
pagingMode: {
type: Boolean,
default: true
},
defaultObj: {
type: [Object, Array]
},
inputKey: {
type: String,
default: 'keyword'
},
method: {
type: String,
default: 'GET'
},
disabledList: {
type: Array
}
},
data () {
return {
openCtrl: false,
selectArr: [],
tempIdArr: [],
tempDisabledIdArr: [],
selectedObj: {},
keyword: '',
closeIconCtrl: false,
inputScroll: {
pageNum: 1,
pageSize: this.config.pageSize,
total: 0
},
data: [],
timer: 0
}
},
computed: {
arrowDownClass() {
return [
'arrow-down',
{
'arrow-down-visible': this.openCtrl
}
]
},
selectListClass() {
return [
'select-list',
{
'select-list-open': this.openCtrl
}
]
}
},
watch: {
path(newVal, oldVal) {
this.getMemberGroupList('', true)
},
params: {
deep: true,
handler(newVal, oldVal) {
if (JSON.stringify(newVal) !== JSON.stringify(oldVal)) {
this.getMemberGroupList('', true)
}
}
}
},
created() {},
beforeMount() {
this.getMemberGroupList('', true)
},
mounted() {
document.addEventListener('click', e => {
if (!this.$el.contains(e.target)) {
this.openCtrl = false
}
})
},
updated() {},
methods: {
getMemberGroupList(keyword, flag) {
if (flag) {
this.inputScroll.pageNum = 1
}
const url = this.path
const ajaxData = {
current: this.inputScroll.pageNum,
size: this.inputScroll.pageSize,
[this.inputKey]: keyword || ''
}
if (this.params) {
for (const key in this.params) {
ajaxData[key] = this.params[key]
}
}
if ((this.inputScroll.pageNum - 1) * this.inputScroll.pageSize > this.inputScroll.total) {
return
}
if (this.method === 'GET') {
this.$get(url, ajaxData).then(res => {
if (res.code === 0) {
if (flag) {
if (res.data.records) {
this.data = res.data.records
} else {
this.data = res.data
}
} else {
if (res.data.records) {
this.data = this.data.concat(res.data.records)
} else {
this.data = res.data
}
}
this.inputScroll.pageNum = res.data.current + 1
this.inputScroll.total = res.data.total
}
})
} else {
this.$post(url, ajaxData).then(res => {
if (res.code === 0) {
if (flag) {
if (res.data.records) {
this.data = res.data.records
} else {
this.data = res.data
}
} else {
if (res.data.records) {
this.data = this.data.concat(res.data.records)
} else {
this.data = res.data
}
}
this.inputScroll.pageNum = res.data.current + 1
this.inputScroll.total = res.data.total
}
})
}
},
handleReachBottom () {
return new Promise(resolve => {
this.getMemberGroupList(this.keyword, false)
resolve()
})
},
chooseItem(item) {
const keyId = this.keyId
if (this.type === 'multiple') {
const index = this.tempIdArr.indexOf(item[keyId])
if (index > -1) {
this.selectArr.splice(index, 1)
this.tempIdArr.splice(index, 1)
} else {
this.selectArr.push(item)
this.tempIdArr.push(item[keyId])
}
this.$emit('getValue', this.selectArr)
} else {
this.selectedObj = item
this.openCtrl = false
this.$emit('getValue', this.selectedObj)
}
if (this.keyword) {
this.keyword = ''
this.getMemberGroupList(this.keyword, true)
}
},
deleteItem(id) {
const index = this.tempIdArr.indexOf(id)
this.selectArr.splice(index, 1)
this.tempIdArr.splice(index, 1)
this.$emit('getValue', this.selectArr)
},
clearSelected() {
if (this.type === 'multiple') {
this.tempIdArr.splice(0)
this.selectArr.splice(0)
this.$emit('getValue', this.selectArr)
} else {
this.selectedObj = {}
this.$emit('getValue', this.selectedObj)
}
},
searchKeyword() {
this.timer = new Date().getTime()
setTimeout(() => {
if (new Date().getTime() - this.timer >= 1000) {
this.getMemberGroupList(this.keyword, true)
}
}, 1000)
},
mouseenter() {
if (this.selectArr.length > 0 || this.selectedObj.name || this.selectedObj.team) {
this.closeIconCtrl = true
} else {
this.closeIconCtrl = false
}
},
voluation() {
if (this.type === 'single' && this.defaultObj) {
this.selectedObj[this.keyName] = this.defaultObj.name
this.selectedObj[this.keyId] = this.defaultObj.id
} else if (this.type !== 'single' && this.defaultObj) {
const key = this.keyName
this.tempIdArr = []
this.selectArr = this.defaultObj.map(item => {
this.tempIdArr.push(item[this.keyId])
if (this.keyCode) {
return { [key]: item.name, id: item[this.keyId], [this.keyCode]: item[this.keyCode] }
} else {
return { [key]: item.name, id: item[this.keyId] }
}
})
}
if (this.disabledList && this.disabledList.length > 0) {
this.tempDisabledIdArr = this.disabledList.map(item => {
return item
})
}
}
}
}
</script>
<style scoped lang="sass">
@import './mySelect.scss'
</style>
@import '@/assets/globalStyle.scss';
.selected{
width:300px;
background: #fff;
position: relative;
.select-container{
position: relative;
overflow: auto;
max-height: 60px;
line-height: 1;
padding: 0 30px 0 4px;
border:1px solid $borderColor;
border-radius: 2px;
cursor: pointer;
&:hover{
border-color:$globalMainColor;
}
.select-tag{
position: relative;
height: 22px;
line-height: 22px;
// max-width: 99%;
display: inline-block;
margin: 4px 4px 2px 0;
padding: 0 8px;
border: 1px solid $borderColor;
border-radius: 3px;
background: #f7f7f7;
font-size: 12px;
vertical-align: middle;
opacity: 1;
overflow: hidden;
.tag-text{
display: block;
margin-right: 14px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.ios-close{
position: absolute;
display: block;
right: 4px;
top: 3px;
}
}
.selected-text{
line-height: 30px;
padding-left:3px;
}
.arrow-down{
position: absolute;
top: 50%;
transform: translateY(-50%);
right: 8px;
line-height: 1;
transition: all .2s ease-in-out;
}
.arrow-down-visible{
transform: translateY(-50%) rotate(180deg);
}
.clear-selected{
position: absolute;
top: 50%;
transform: translateY(-50%);
right: 8px;
line-height: 1;
color:#808695;
}
.select-placeholder{
line-height: 30px;
padding-left:3px;
color:#9E9E9E;
}
}
.select-search{
position: absolute;
bottom: -32px;
z-index: 2;
width:100%;
height: 30px;
box-sizing: border-box;
// padding-left:5px;
// border:1px solid $globalMainColor;
}
.select-list{
position: absolute;
// bottom: -235px;
width:100%;
background: #fff;
will-change: top, left;
transform-origin: center top;
box-shadow: 0 4px 6px rgba(0,0,0,.2);
transform: all 0.2s ease-in-out;
z-index: 999;
.list-item{
padding:7px 16px;
cursor: pointer;
position: relative;
&:hover{
background: #f3f3f3;
color:$globalMainColor;
}
&.list-item-active{
background: #f3f3f3;
color:$globalMainColor;
}
&.list-item-disabled{
cursor:not-allowed;
color: $disabledColor;
}
&.list-item-active .checked-icon{
display: block;
}
.checked-icon{
position: absolute;
top:50%;
transform: translateY(-50%);
right:20px;
line-height: 1;
color:$globalMainColor;
display: none;
}
}
}
.no-data{
height: 52px;
}
}
<Col span="18">
<mySelect ref="projectSelect"
:path="'/report/projects'"
:placeholder="'请选择项目'"
:placeholder-input="'请输入项目'"
:key-name="'name'"
@getValue="getProjectId"
/>
</Col>
````