electripper-v2-ui/src/components/BaseRemoteSelect/index.vue

147 lines
3.5 KiB
Vue
Raw Normal View History

2025-04-04 18:13:14 +08:00
<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>