import { ref, computed, onMounted, nextTick } from 'vue' import { useRoute } from 'vue-router' import { getTableConfigFromLocal, saveTableConfigToLocal, updateUserTableConfig } from '/@/api/admin/usertable' /** * 表格列配置类型 */ export interface TableColumn { prop?: string label?: string icon?: any width?: number | string minWidth?: number | string showOverflowTooltip?: boolean align?: 'left' | 'center' | 'right' alwaysShow?: boolean fixed?: boolean | 'left' | 'right' [key: string]: any } /** * useTableColumnControl Hook * * 用于统一管理表格列的显示/隐藏和排序功能 * * @param tableColumns 表格列配置数组 * @param options 可选配置项 * @returns 返回列控制相关的状态和方法 * * @example * ```ts * const tableColumns = [ * { prop: 'name', label: '姓名', icon: User }, * { prop: 'age', label: '年龄', icon: Calendar } * ] * * const { * visibleColumns, * visibleColumnsSorted, * checkColumnVisible, * handleColumnChange, * handleColumnOrderChange * } = useTableColumnControl(tableColumns) * ``` */ export function useTableColumnControl( tableColumns: TableColumn[], options?: { /** 是否在挂载时自动加载配置,默认为 true */ autoLoad?: boolean /** 自定义存储 key,默认使用路由路径 */ storageKey?: string } ) { const route = useRoute() const { autoLoad = true, storageKey: customStorageKey } = options || {} // 生成存储 key const getStorageKey = () => { if (customStorageKey) { return customStorageKey } const routePath = route.path.replace(/^\//, '').replace(/\//g, '-') return `table-columns-${routePath}` } // 当前显示的列 const visibleColumns = ref([]) // 列排序顺序 const columnOrder = ref([]) /** * 从本地统一存储加载配置 */ const loadSavedConfig = () => { const storageKey = getStorageKey() const savedConfig = getTableConfigFromLocal(storageKey) // 获取所有有效的列 key const validColumns = tableColumns .filter(col => !col.alwaysShow && !col.fixed) .map(col => col.prop || col.label || '') .filter(Boolean) // 加载可见列配置 if (savedConfig && savedConfig.visibleColumns) { const filteredSaved = savedConfig.visibleColumns.filter((col: string) => validColumns.includes(col)) visibleColumns.value = filteredSaved.length > 0 ? filteredSaved : validColumns } else { visibleColumns.value = validColumns } // 加载列排序配置 if (savedConfig && savedConfig.columnOrder) { columnOrder.value = savedConfig.columnOrder.filter((key: string) => validColumns.includes(key)) // 补充缺失的列 validColumns.forEach(key => { if (!columnOrder.value.includes(key)) { columnOrder.value.push(key) } }) } else { columnOrder.value = validColumns } } /** * 列显示控制函数 * @param prop 列的 prop 或 label * @returns 是否可见 */ const checkColumnVisible = (prop: string): boolean => { if (visibleColumns.value.length === 0) { return true } return visibleColumns.value.includes(prop) } /** * 列变化处理 * @param value 新的可见列数组 */ const handleColumnChange = (value: string[]) => { visibleColumns.value = value const storageKey = getStorageKey() // 过滤掉 alwaysShow 和 fixed 的列 const selectableColumns = value.filter(col => { const column = tableColumns.find(c => (c.prop || c.label) === col) return column && !column.alwaysShow && !column.fixed }) // 保存到本地统一存储 saveTableConfigToLocal(storageKey, { visibleColumns: selectableColumns }) // 异步保存到后端 updateUserTableConfig(storageKey, { visibleColumns: selectableColumns }).catch(() => {}) } /** * 列排序变化处理 * @param order 新的列排序数组 */ const handleColumnOrderChange = (order: string[]) => { columnOrder.value = order const storageKey = getStorageKey() // 保存到本地统一存储 saveTableConfigToLocal(storageKey, { columnOrder: order }) // 异步保存到后端 updateUserTableConfig(storageKey, { columnOrder: order }).catch(() => {}) } /** * 排序后的表格列 * 根据 visibleColumns 和 columnOrder 计算最终显示的列 */ const visibleColumnsSorted = computed(() => { // 如果 visibleColumns 为空,显示所有列(初始化时) if (visibleColumns.value.length === 0) { return tableColumns.filter(col => !col.alwaysShow && !col.fixed) } // 过滤出可见的列 const columns = tableColumns.filter(col => { const key = col.prop || col.label || '' return visibleColumns.value.includes(key) }) // 如果有排序配置,按排序顺序排列 if (columnOrder.value.length > 0) { const orderedColumns: TableColumn[] = [] const unorderedColumns: TableColumn[] = [] // 先按保存的顺序添加列 columnOrder.value.forEach(key => { const col = columns.find(c => (c.prop || c.label) === key) if (col) { orderedColumns.push(col) } }) // 添加未在排序列表中的列(新增的列) columns.forEach(col => { const key = col.prop || col.label || '' if (!columnOrder.value.includes(key)) { unorderedColumns.push(col) } }) return [...orderedColumns, ...unorderedColumns] } return columns }) // 自动加载配置 if (autoLoad) { loadSavedConfig() onMounted(() => { nextTick(() => { if (visibleColumns.value.length === 0) { loadSavedConfig() } }) }) } return { /** 当前可见的列 key 数组 */ visibleColumns, /** 列排序顺序 */ columnOrder, /** 排序后的可见列配置数组 */ visibleColumnsSorted, /** 检查列是否可见 */ checkColumnVisible, /** 列变化处理函数 */ handleColumnChange, /** 列排序变化处理函数 */ handleColumnOrderChange, /** 手动加载配置 */ loadSavedConfig } }