<template> <div> <div class="flex"> <el-table :data="tableObject.tableList" border style="flex: 1"> <slot></slot> </el-table> <el-button ref="ColumnSetting" plain style="writing-mode: vertical-lr; height: 100px; letter-spacing: 2px" @click="clickSetting" >表格列控制</el-button > <el-popover ref="TableColumnPop" :virtual-ref="ColumnSetting" placement="left" width="120px" trigger="click" virtual-triggering > <el-checkbox-group v-model="checkedColumns" @change="confirm"> <draggable v-model="allColumns" item-key="field" ghost-class="draggable-ghost" :animation="400" @end="onDragEnd" > <template #item="{ element: item }"> <el-checkbox :key="item.field" :label="item.field"> {{ item.label }} </el-checkbox> </template> </draggable> </el-checkbox-group> </el-popover> </div> <!-- 分页 --> <Pagination v-model:limit="pageSize" v-model:page="currentPage" :total="tableObject.total" @pagination="getList" /> </div> </template> <script setup> import draggable from 'vuedraggable' import { useUserStore } from '@/store/modules/user' import { useRoute } from 'vue-router' import cache from '@/plugins/cache' const props = defineProps({ tableObject: { type: Object, default: () => ({ tableList: [] }) }, tableColumns: { type: Array, default: () => [] } }) const emit = defineEmits(['update:tableObject', 'getList', 'getCheckedColumns']) const route = useRoute() const { id: userId } = useUserStore().user //取用户ID const currentPage = ref(props.tableObject?.currentPage || 1) const pageSize = ref(props.tableObject?.pageSize || 20) const ColumnSetting = ref() const TableColumnPop = ref() // 展示在设置里的所有表格列,由于会排序,所以使用新属性,不直接修改原值 const allColumns = ref({}) // 已勾选的选项 const checkedColumns = ref([]) // 调用获取数据的接口,分页时需要使用 function getList({ page, limit }) { emit('update:tableObject', { ...props.tableObject, currentPage: page, pageSize: limit }) nextTick(() => { emit('getList') }) } // 点击"表格列控制"按钮,出现设置页面 const clickSetting = () => { unref(TableColumnPop).TableColumnPop?.delayHide?.() } // 获取所有的表格列,注意如果本地有缓存使用缓存数据,因为用户可能已对表格列排序,并且不依赖网络请求,可更快渲染表头 function getAllColumns() { // 1. 先获取缓存表头 const localData = getColumn('TableColumnAll')[route.name] || [] // 2. 如果有缓存的表头,直接使用,并将新增的标题加入,如果没有缓存,那就得用获取到的表头 if (localData && localData) { const newColumns = props.tableColumns.filter( (item) => !localData.some((it) => it.field == item.field) ) allColumns.value = [...localData, ...newColumns] } else { allColumns.value = [...props.tableColumns] } } // 获取缓存的表头 function getColumn(name = 'shitTable') { return cache.local.get(`${name}-${userId}`) || {} } // 设置表头缓存 function setColumn(val, name = 'shitTable') { cache.local.set(`${name}-${userId}`, val) } // 获取用户已勾选的表头 function getUserCheckedColumns() { // 1. 先获取缓存 const localData = getColumn('shitTable')[route.name] // 2. 如果有缓存,使用缓存表头,否则使用默认的所有表头 if (localData && localData.length) { checkedColumns.value = localData } else { checkedColumns.value = allColumns.value.map((it) => it.field) } // 3. 回显到表格中 emitColumns() } // 表格列排序 function onDragEnd() { const obj = getColumn('TableColumnAll') obj[route.name] = allColumns.value // 1. 设置缓存 setColumn(obj, 'TableColumnAll') // 2. 表格回显 emitColumns() } // 勾选确认 function confirm() { const obj = getColumn() obj[route.name] = checkedColumns.value setColumn(obj, 'shitTable') emitColumns() } // 将表头数据返回至父组件 function emitColumns() { const arr = allColumns.value.filter((item) => checkedColumns.value.includes(item.field)) emit('getCheckedColumns', arr) } getAllColumns() getUserCheckedColumns() defineExpose({ getUserCheckedColumns }) </script> <style lang="scss" scoped></style>