Files
klp-oa/klp-ui/src/components/MutiSelect/index.vue

168 lines
3.9 KiB
Vue
Raw Normal View History

<template>
<div class="muti-select">
<!-- 下拉选择模式 -->
<div v-if="type === 'select'" class="select-container">
<el-select
v-model="innerValue"
multiple
:placeholder="placeholder"
:filterable="filterable"
:clearable="clearable"
:allow-create="allowAdd"
:disabled="disabled"
:size="size"
:collapse-tags="collapseTags"
@change="handleChange"
>
<!-- 全选选项 -->
2026-04-16 15:50:54 +08:00
<!-- <el-option
v-if="showSelectAll && options.length > 0"
key="selectAll"
label="全选"
value="selectAll"
@click="toggleSelectAll"
2026-04-16 15:50:54 +08:00
/> -->
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
<!-- 复选框模式 -->
<div v-else-if="type === 'checkbox'" class="checkbox-group">
<el-checkbox-group v-model="innerValue" @change="handleCheckboxChange">
<el-checkbox
v-for="item in options"
:key="item.value"
:label="item.value"
:disabled="disabled"
>
{{ item.label }}
</el-checkbox>
</el-checkbox-group>
<el-button
v-if="showSelectAll && options.length > 0"
type="text"
size="small"
@click="toggleSelectAll"
>
{{ isAllSelected ? '取消全选' : '全选' }}
</el-button>
</div>
</div>
</template>
<!-- v-model 绑定逗号分隔的字符串可以 props 配置是否允许新增 -->
<script>
export default {
name: 'MutiSelect',
props: {
value: {
type: String,
default: ''
},
options: {
type: Array,
default: () => []
},
allowAdd: {
type: Boolean,
default: false
},
type: {
type: String,
default: 'select' // select or checkbox
},
placeholder: {
type: String,
default: '请选择'
},
filterable: {
type: Boolean,
default: true
},
clearable: {
type: Boolean,
default: true
},
disabled: {
type: Boolean,
default: false
},
size: {
type: String,
default: 'default' // large, default, small
},
showSelectAll: {
type: Boolean,
default: true
},
collapseTags: {
type: Boolean,
default: true
}
},
// 计算属性捕获实现双向绑定
computed: {
innerValue: {
get() {
if (!this.value) {
return [];
}
return this.value?.split(',');
},
set(val) {
const newValue = val?.join(',') ?? '';
this.$emit('input', newValue);
this.$emit('change', newValue);
}
},
// 是否全选
isAllSelected() {
return this.options.length > 0 && this.innerValue.length === this.options.length;
}
},
methods: {
// 处理选择变化
handleChange(val) {
// 过滤掉 'selectAll' 选项
const filteredVal = val.filter(item => item !== 'selectAll');
this.$emit('change', filteredVal.join(','));
},
// 处理复选框变化
handleCheckboxChange(val) {
const newValue = val.join(',');
this.$emit('input', newValue);
this.$emit('change', newValue);
},
// 切换全选/取消全选
toggleSelectAll() {
if (this.isAllSelected) {
this.innerValue = [];
} else {
this.innerValue = this.options.map(item => item.value);
}
}
}
}
</script>
<style scoped>
.muti-select {
width: 100%;
}
.checkbox-group {
display: flex;
flex-wrap: wrap;
gap: 10px;
align-items: center;
}
.checkbox-group .el-checkbox {
margin-right: 10px;
}
</style>