147 lines
3.5 KiB
Vue
147 lines
3.5 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>
|
|||
|
<el-option
|
|||
|
v-for="item in options"
|
|||
|
:key="item[prop]"
|
|||
|
:value="item[prop]"
|
|||
|
:label="item[showProp]"
|
|||
|
/>
|
|||
|
<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() {
|
|||
|
console.log("getOptions", this.beforeGetOptions());
|
|||
|
if (!this.beforeGetOptions()) {
|
|||
|
return;
|
|||
|
}
|
|||
|
this.loading = true;
|
|||
|
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>
|