<script lang="ts" setup>
import { ref, computed } from 'vue'
import FixedSizeList from 'element-plus-secondary/es/components/virtual-list/src/components/fixed-size-list.mjs'
import VanPopup from 'vant/es/popup'
import 'vant/es/popup/style'
const props = defineProps({
options: {
type: Array,
default: () => []
},
selectValue: {
type: Array,
default: () => []
},
multiple: {
type: Boolean,
default: false
}
})
const showSelect = ref(false)
let oldCheckList = []
const checkAll = ref(false)
const isIndeterminate = ref(false)
const checkTableList = ref([])
const checkList = ref([])
const keywords = ref('')
const tableListWithSearch = computed(() => {
if (!keywords.value) return props.options
return props.options.filter((ele: any) =>
ele.label.toLowerCase().includes(keywords.value.toLowerCase())
)
})
const emits = defineEmits(['onClear', 'onConfirm'])
const reset = () => {
oldCheckList = []
showSelect.value = false
checkAll.value = false
isIndeterminate.value = false
keywords.value = ''
}
const showPopup = () => {
reset()
if (props.multiple) {
checkList.value = [...props.selectValue]
} else {
checkList.value = Array.isArray(props.selectValue)
? [...props.selectValue]
: [props.selectValue]
oldCheckList = [...checkList.value]
}
showSelect.value = true
}
const onClear = () => {
reset()
emits('onClear')
}
const onConfirm = () => {
showSelect.value = false
checkAll.value = false
isIndeterminate.value = false
keywords.value = ''
emits('onConfirm', checkList.value)
}
const handleCheckedTablesChange = (value: any[]) => {
if (!props.multiple) {
if (!oldCheckList.length) {
oldCheckList = [...value]
} else {
checkList.value = value.filter(ele => !oldCheckList.includes(ele))
oldCheckList = [...checkList.value]
}
return
}
const checkedCount = value.length
checkAll.value = checkedCount === tableListWithSearch.value.length
isIndeterminate.value = checkedCount > 0 && checkedCount < tableListWithSearch.value.length
const tableNameArr = tableListWithSearch.value.map((ele: any) => ele.label)
checkTableList.value = [
...new Set([...checkTableList.value.filter(ele => !tableNameArr.includes(ele)), ...value])
]
}
const handleCheckAllChange = (val: any) => {
checkList.value = val
? [...new Set([...tableListWithSearch.value.map((ele: any) => ele.label), ...checkList.value])]
: []
isIndeterminate.value = false
const tableNameArr = tableListWithSearch.value.map((ele: any) => ele.label)
checkTableList.value = val
? [...new Set([...tableNameArr, ...checkTableList.value])]
: checkTableList.value.filter(ele => !tableNameArr.includes(ele))
}
</script>
<template>
<div class="vant-mobile_select" @click="showPopup" />
<van-popup teleport="body" position="bottom" v-model:show="showSelect">
<div class="container-vant_mobile">
<div class="select-all">
<el-checkbox
v-model="checkAll"
v-if="multiple"
:indeterminate="isIndeterminate"
@change="handleCheckAllChange"
>
{{ $t('component.allSelect') }}
</el-checkbox>
<el-input
style="position: absolute; top: 3px; right: 115px; width: 150px"
v-model="keywords"
clearable
></el-input>
<button
style="position: absolute; top: 0; right: 60px"
@click="onClear"
class="van-picker__confirm van-haptics-feedback"
>
{{ $t('commons.clear') }}
</button>
<button
style="position: absolute; top: 0; right: 10px"
@click="onConfirm"
class="van-picker__confirm van-haptics-feedback"
>
{{ $t('commons.confirm') }}
</button>
</div>
<el-checkbox-group
v-model="checkList"
style="position: relative"
@change="handleCheckedTablesChange"
>
<FixedSizeList
:item-size="32"
:data="tableListWithSearch"
:total="tableListWithSearch.length"
:height="460"
:scrollbar-always-on="true"
class-name="ed-select-dropdown__list"
layout="vertical"
>
<template #default="{ index, style }">
<div class="list-item_primary" :style="style">
<el-checkbox :label="tableListWithSearch[index].value">
{{ tableListWithSearch[index].label }}</el-checkbox
>
</div>
</template>
</FixedSizeList>
</el-checkbox-group>
</div>
</van-popup>
</template>
<style lang="less">
.vant-mobile_select {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.container-vant_mobile {
overflow: hidden;
padding: 0 10px;
.select-all {
height: 40px;
padding-left: 12px;
display: flex;
align-items: center;
border-bottom: 1px solid #dee0e3;
position: relative;
.ed-input__wrapper {
background-color: var(--ed-input-bg-color, var(--ed-fill-color-blank)) !important;
box-shadow: 0 0 0 1px var(--ed-color-primary) inset !important;
}
}
.ed-checkbox__label {
display: inline-flex;
align-items: center;
color: #1f2329 !important;
}
.ed-vl__window {
scrollbar-width: none;
}
}
</style>