<template>
|
<el-select
|
v-model="innerValue"
|
:multiple="true"
|
:collapse-tags="false"
|
:filterable="filterable"
|
:placeholder="placeholder"
|
:clearable="clearable"
|
@change="handleChange"
|
@clear="handleClear"
|
@remove-tag="handleTagRemove"
|
size="medium"
|
style="width: 97%; max-height: 55px; overflow-y: auto;"
|
>
|
<div class="select-all-container">
|
<el-option
|
:value="SELECT_ALL"
|
:label="selectAllLabel"
|
class="select-all-option"
|
@click.native="handleSelectAll"
|
>
|
<div class="select-all-inner">
|
<span>{{ selectAllLabel }}</span>
|
<span class="count">({{ innerValue.filter(v => v !== SELECT_ALL).length }} 已选)</span>
|
</div>
|
</el-option>
|
</div>
|
|
<el-option
|
v-for="item in options"
|
:key="item.value"
|
:label="item.label"
|
:value="item.value"
|
/>
|
</el-select>
|
</template>
|
|
<script>
|
const SELECT_ALL = 'SELECT_ALL';
|
|
export default {
|
name: 'SelectAllDropdown',
|
props: {
|
value: {
|
type: Array,
|
default: () => ([])
|
},
|
options: {
|
type: Array,
|
required: true,
|
validator: value => value.every(opt => opt.value && opt.label)
|
},
|
selectAllLabel: {
|
type: String,
|
default: '全选'
|
},
|
placeholder: {
|
type: String,
|
default: '请选择'
|
},
|
filterable: {
|
type: Boolean,
|
default: true
|
},
|
clearable: {
|
type: Boolean,
|
default: true
|
}
|
},
|
data() {
|
return {
|
SELECT_ALL,
|
innerValue: []
|
};
|
},
|
watch: {
|
value: {
|
immediate: true,
|
handler(newVal) {
|
if (newVal.includes(SELECT_ALL)) {
|
// 如果包含全选标识,过滤掉它
|
this.innerValue = newVal.filter(v => v !== SELECT_ALL);
|
this.$emit('input', this.innerValue);
|
} else {
|
this.innerValue = [...newVal];
|
}
|
}
|
}
|
},
|
computed: {
|
allSelected() {
|
return this.innerValue.length === this.options.length;
|
},
|
someSelected() {
|
return this.innerValue.length > 0 && !this.allSelected;
|
}
|
},
|
mounted() {
|
this.handleSelectAll()
|
},
|
methods: {
|
handleSelectAll() {
|
if (this.allSelected) {
|
// 如果已经全选,则清空所有
|
this.innerValue = [];
|
} else {
|
// 否则选择所有选项
|
this.innerValue = this.options.map(opt => opt.value);
|
}
|
this.$emit('input', this.innerValue);
|
this.$emit('change', this.innerValue);
|
},
|
|
handleChange(value) {
|
// 确保过滤掉全选标识
|
const cleanValue = value.filter(v => v !== SELECT_ALL);
|
this.innerValue = cleanValue;
|
|
this.$emit('input', cleanValue);
|
this.$emit('change', cleanValue);
|
},
|
|
handleClear() {
|
this.innerValue = [];
|
this.$emit('input', []);
|
this.$emit('change', []);
|
},
|
|
handleTagRemove(tag) {
|
const index = this.innerValue.indexOf(tag);
|
if (index !== -1) {
|
this.innerValue.splice(index, 1);
|
this.$emit('input', this.innerValue);
|
this.$emit('change', this.innerValue);
|
}
|
}
|
}
|
};
|
</script>
|
|
<style lang="scss" scoped>
|
.select-all-container {
|
border-bottom: 1px solid #eee;
|
margin-bottom: 5px;
|
padding-bottom: 5px;
|
}
|
|
.select-all-option {
|
height: auto;
|
padding: 5px 10px;
|
|
.select-all-inner {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
width: 100%;
|
}
|
|
.count {
|
font-size: 12px;
|
color: #888;
|
}
|
}
|
|
.el-select-dropdown__list {
|
padding-top: 0;
|
}
|
|
// 选中状态的特殊样式
|
.el-option.is-selected.select-all-option {
|
background-color: #f5f7fa;
|
color: #333;
|
font-weight: bold;
|
}
|
</style>
|