<template>
|
<div class="select-filter">
|
<div v-for="item in data" :key="item.key" class="select-filter-item">
|
<div class="select-filter-item-title">
|
<span>{{ item.title }} :</span>
|
</div>
|
<span v-if="!item.options.length" class="select-filter-notData">暂无数据 ~</span>
|
<el-scrollbar>
|
<ul class="select-filter-list">
|
<li
|
v-for="option in item.options"
|
:key="option.value"
|
:class="{
|
active:
|
option.value === selected[item.key] ||
|
(Array.isArray(selected[item.key]) && selected[item.key].includes(option.value))
|
}"
|
@click="select(item, option)"
|
>
|
<slot :row="option">
|
<el-icon v-if="option.icon">
|
<component :is="option.icon" />
|
</el-icon>
|
<span>{{ option.label }}</span>
|
</slot>
|
</li>
|
</ul>
|
</el-scrollbar>
|
</div>
|
</div>
|
</template>
|
|
<script setup lang="ts" name="selectFilter">
|
import { ref, watch } from "vue";
|
|
interface OptionsProps {
|
value: string | number;
|
label: string;
|
icon?: string;
|
}
|
|
interface SelectDataProps {
|
title: string; // 列表标题
|
key: string; // 当前筛选项 key 值
|
multiple?: boolean; // 是否为多选
|
options: OptionsProps[]; // 筛选数据
|
}
|
|
interface SelectFilterProps {
|
data?: SelectDataProps[]; // 选择的列表数据
|
defaultValues?: { [key: string]: any }; // 默认值
|
}
|
|
const props = withDefaults(defineProps<SelectFilterProps>(), {
|
data: () => [],
|
defaultValues: () => ({})
|
});
|
|
// 重新接收默认值
|
const selected = ref<{ [key: string]: any }>({});
|
watch(
|
() => props.defaultValues,
|
() => {
|
props.data.forEach(item => {
|
if (item.multiple) selected.value[item.key] = props.defaultValues[item.key] ?? [""];
|
else selected.value[item.key] = props.defaultValues[item.key] ?? "";
|
});
|
},
|
{ deep: true, immediate: true }
|
);
|
|
// emit
|
const emit = defineEmits<{
|
change: [value: any];
|
}>();
|
|
/**
|
* @description 选择筛选项
|
* @param {Object} item 选中的哪项列表
|
* @param {Object} option 选中的值
|
* @return void
|
* */
|
const select = (item: SelectDataProps, option: OptionsProps) => {
|
if (!item.multiple) {
|
// * 单选
|
if (selected.value[item.key] !== option.value) selected.value[item.key] = option.value;
|
} else {
|
// * 多选
|
// 如果选中的是第一个值,则直接设置
|
if (item.options[0].value === option.value) selected.value[item.key] = [option.value];
|
// 如果选择的值已经选中了,则删除选中的值
|
if (selected.value[item.key].includes(option.value)) {
|
let currentIndex = selected.value[item.key].findIndex((s: any) => s === option.value);
|
selected.value[item.key].splice(currentIndex, 1);
|
// 当全部删光时,把第第一个值选中
|
if (selected.value[item.key].length == 0) selected.value[item.key] = [item.options[0].value];
|
} else {
|
// 未选中点击值的时候,追加选中值
|
selected.value[item.key].push(option.value);
|
// 单选中全部并且点击到了未选中的值,把第一个值删除掉
|
if (selected.value[item.key].includes(item.options[0].value)) selected.value[item.key].splice(0, 1);
|
}
|
}
|
emit("change", selected.value);
|
};
|
</script>
|
|
<style scoped lang="scss">
|
@import "./index";
|
</style>
|