1,组件代码
<template>
<div ref="vtable" class="relative">
<slot name="content"> </slot>
<a-popover
v-model:visible="popoverVisible"
trigger="click"
placement="bottomRight"
class="popover"
:overlay-inner-style="{
maxHeight: `${elementBottomHeight}vw`,
overflowY: 'auto',
}"
>
<template #content>
<div
v-for="(col, index) in allColumns"
:key="index"
class="checkbox-wrapper table-format"
>
<span v-show="col.show"> {{ col.title }}</span>
<a-switch
v-show="col.show"
v-model:checked="col.open"
size="small"
@change="toggleColumnVisibility"
/>
</div>
</template>
<template #title>
<h1>表头设置</h1>
<hr />
<br />
<a-input placeholder="搜索添加更多字段" @input="search">
<template #prefix>
<SearchOutlined />
</template>
</a-input>
</template>
<FunnelPlotOutlined ref="funnelIconRef" class="icon" />
</a-popover>
</div>
<div ref="stickyElementRef" class="sticky"></div>
</template>
<script lang="ts" setup>
import { FunnelPlotOutlined, SearchOutlined } from '@ant-design/icons-vue'
import { inject } from 'vue'
const elementBottomHeight = ref(0)
const popoverVisible = ref(false)
const vtable = ref(null)
const stickyElementRef = ref(null)
let columns = inject('columns') as any[]
let code = columns[0].code
let allColumns: any
// 开关控制表头显示隐藏,为open为true的返回给columns
const toggleColumnVisibility = () => {
const filteredColumns = Object.values(allColumns).filter(col => col.open)
columns.splice(0, columns.length, ...filteredColumns)
localStorage.setItem(code, JSON.stringify(allColumns))
}
const searchShow = () => {
allColumns.forEach((ele: any) => {
ele.show = true
})
}
// 查询表头方法
const search = (event: Event) => {
const inputValue = (event.target as HTMLInputElement).value
const keyword = inputValue.trim().toLowerCase()
if (keyword) {
allColumns.forEach((ele: any) => {
ele.show = ele.title.toLowerCase().includes(keyword) ? true : false
})
} else {
allColumns.forEach((ele: any) => {
ele.show = ele.title.toLowerCase().includes(keyword) ? true : false
})
}
}
onMounted(() => {
// 优先加载本地数据要不然会影响列表的显示
loadInitialVisibleColumns()
// 加载了本地的数据之后,调用一次开关控制隐藏的方法,对表头为true的返回给表头
toggleColumnVisibility()
// 进来的时候对查询的数据进行赋值,让开关的v-show属性全部设为true
searchShow()
// a-popover的动态高度
nextTick(() => {
calculateStickyPosition()
})
})
// 计算并设置 sticky 元素的顶部位置的函数
const calculateStickyPosition = () => {
const funnelIconRect = vtable.value.getBoundingClientRect()
const stickyRect = stickyElementRef.value.getBoundingClientRect()
// 计算 FunnelPlotOutlined 图标和 sticky 元素之间的距离
const distance = Math.abs(funnelIconRect.top - stickyRect.top)
console.log(distance)
elementBottomHeight.value = (distance / 1920) * 100
console.log(elementBottomHeight.value)
}
window.addEventListener('resize', calculateStickyPosition)
// 本地获取表头
const loadInitialVisibleColumns = () => {
let storedColumns = localStorage.getItem(code)
if (storedColumns) {
let parsedColumns = JSON.parse(storedColumns)
if (Array.isArray(parsedColumns)) {
allColumns = reactive(parsedColumns)
} else {
allColumns = reactive(Object.values(parsedColumns))
}
} else {
allColumns = reactive([...unref(inject('columns') as any[])])
}
}
</script>
<style lang="scss">
.table-format {
display: flex;
justify-content: space-between;
margin-bottom: 10px;
}
.sticky {
position: fixed;
bottom: 0px;
border: 1px solid #000;
width: 100%;
opacity: 0;
}
.icon {
position: absolute;
right: 15px;
top: 3px;
}
</style>
2,使用方式
在需要的地方
只需要套起来
在表头的地方多添加两个字段
和子组件数据共享