150 lines
3.6 KiB
Vue
150 lines
3.6 KiB
Vue
<template>
|
||
<el-select
|
||
v-model="selectedValue"
|
||
placeholder="请选择"
|
||
filterable
|
||
:multiple="multiple"
|
||
:loading="loading"
|
||
@change="handleChange"
|
||
@visible-change="handleVisibleChange"
|
||
remote
|
||
:remote-method="remoteMethod"
|
||
>
|
||
<div class="select-header">
|
||
<div>
|
||
共{{ total }}条数据
|
||
</div>
|
||
<el-button v-if="multiple && !isEmpty(options)" style="margin-left: 10px;" size="mini" type="text" @click.stop="handleSelectAll">
|
||
{{ isAllSelected ? '取消全选' : '全选' }}
|
||
</el-button>
|
||
</div>
|
||
<slot name="option" :options="options">
|
||
<el-option
|
||
v-for="item in options"
|
||
:key="item[prop]"
|
||
:value="item[prop]"
|
||
:label="item[showProp]"
|
||
/>
|
||
</slot>
|
||
<el-option v-if="isEmpty(value) && isEmpty(options)" :label="emptyText" disabled :value="null"></el-option>
|
||
</el-select>
|
||
</template>
|
||
|
||
<script>
|
||
import { isEmpty } from '@/utils';
|
||
import { $remoteSelect } from '@/components/BaseRemoteSelect/mixins';
|
||
|
||
export default {
|
||
name: 'BaseRemoteSelect',
|
||
mixins: [$remoteSelect],
|
||
data() {
|
||
return {
|
||
options: [],
|
||
total: 0,
|
||
loading: false,
|
||
queryParams: {
|
||
pageNum: 1,
|
||
pageSize: 100
|
||
}
|
||
}
|
||
},
|
||
computed: {
|
||
selectedValue: {
|
||
get() {
|
||
return this.value
|
||
},
|
||
set(value) {
|
||
this.$emit('input', value)
|
||
}
|
||
},
|
||
// 是否全选
|
||
isAllSelected() {
|
||
return this.multiple && this.options.length > 0 && Array.isArray(this.value) && this.value.length === this.options.length;
|
||
}
|
||
},
|
||
created() {
|
||
this.queryParams[this.keywordProp] = null;
|
||
// 优先使用API加载数据
|
||
if (this.loadApi) {
|
||
this.loadData();
|
||
}
|
||
// 其次使用初始化选项
|
||
else if (!isEmpty(this.initOptions)) {
|
||
this.options = this.initOptions;
|
||
}
|
||
},
|
||
methods: {
|
||
isEmpty,
|
||
// 加载数据
|
||
loadData() {
|
||
this.loading = true;
|
||
this.loadApi(this.value).then(res => {
|
||
this.options = res.data;
|
||
this.total = this.options?.length;
|
||
}).finally(() => {
|
||
this.loading = false;
|
||
});
|
||
},
|
||
// 远程搜索
|
||
remoteMethod(val) {
|
||
this.queryParams.keyword = val;
|
||
this.getOptions();
|
||
},
|
||
// 下拉框可见性变化
|
||
handleVisibleChange(visible) {
|
||
if (visible) {
|
||
this.getOptions();
|
||
}
|
||
},
|
||
// 全选
|
||
handleSelectAll() {
|
||
if (this.isAllSelected) {
|
||
this.handleChange([]);
|
||
} else {
|
||
const all = this.options.map(item => item[this.prop]);
|
||
this.handleChange(all);
|
||
}
|
||
},
|
||
// 选中值变化,触发change事件
|
||
handleChange(value) {
|
||
if (this.multiple) {
|
||
let list = this.options.filter(item => value.includes(item[this.prop]));
|
||
this.$emit('change', list);
|
||
} else {
|
||
let item = this.options.find(item => value.includes(item[this.prop]));
|
||
this.$emit('change', item);
|
||
}
|
||
},
|
||
// 获取选项
|
||
getOptions() {
|
||
if (!this.beforeGetOptions()) {
|
||
return;
|
||
}
|
||
this.loading = true;
|
||
console.log("getOptions", this.query);
|
||
Object.assign(this.queryParams, this.query);
|
||
this.listApi(this.queryParams).then(res => {
|
||
this.options = res.rows;
|
||
this.total = res.total;
|
||
}).finally(() => {
|
||
this.loading = false;
|
||
});
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.select-header {
|
||
padding: 2px 12px;
|
||
border-bottom: 1px solid #EBEEF5;
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
align-items: center;
|
||
line-height: 1em;
|
||
text-align: center;
|
||
color: #8492a6;
|
||
font-size: 13px;
|
||
}
|
||
</style>
|