electripper-v2-ui/src/components/BaseRemoteSelect/index.vue
2025-04-08 08:48:03 +08:00

150 lines
3.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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>