161 lines
4.9 KiB
TypeScript
161 lines
4.9 KiB
TypeScript
import { ref, computed, onMounted, nextTick, type Ref } from 'vue'
|
||
import { useRoute } from 'vue-router'
|
||
import type { TableInstance } from 'element-plus'
|
||
|
||
export interface ColumnConfig {
|
||
prop?: string
|
||
label: string
|
||
fixed?: boolean | 'left' | 'right'
|
||
alwaysShow?: boolean
|
||
[key: string]: any
|
||
}
|
||
|
||
/**
|
||
* 表格列控制通用 Composable
|
||
* 简化 TableColumnControl 组件的使用
|
||
*
|
||
* @param options 配置选项
|
||
* @returns 返回列控制相关的响应式数据和方法
|
||
*/
|
||
export function useTableColumnControl(options?: {
|
||
/** 表格 ref(用于自动提取列配置) */
|
||
tableRef?: Ref<TableInstance | undefined>
|
||
/** 手动配置的列(如果提供了 tableRef 则忽略) */
|
||
columns?: ColumnConfig[]
|
||
/** localStorage 存储的 key(可选,默认根据路由自动生成) */
|
||
storageKey?: string
|
||
/** 默认显示的列(prop 或 label 数组) */
|
||
defaultVisible?: string[]
|
||
/** 始终显示的列(prop 或 label 数组) */
|
||
alwaysShow?: string[]
|
||
}) {
|
||
const route = useRoute()
|
||
|
||
// 根据路由自动生成 storageKey
|
||
const getStorageKey = (suffix: string = ''): string => {
|
||
if (options?.storageKey) {
|
||
return options.storageKey + (suffix ? `-${suffix}` : '')
|
||
}
|
||
const routePath = route.path.replace(/^\//, '').replace(/\//g, '-')
|
||
return `table-columns-${routePath}${suffix ? `-${suffix}` : ''}`
|
||
}
|
||
|
||
// 可见列
|
||
const visibleColumns = ref<string[]>([])
|
||
|
||
// 列排序
|
||
const columnOrder = ref<string[]>([])
|
||
|
||
// 列配置(手动配置或从表格提取)
|
||
const tableColumns = computed(() => {
|
||
return options?.columns || []
|
||
})
|
||
|
||
// 加载保存的配置
|
||
const loadSavedConfig = () => {
|
||
const storageKey = getStorageKey()
|
||
const saved = localStorage.getItem(storageKey)
|
||
|
||
if (saved) {
|
||
try {
|
||
const savedColumns = JSON.parse(saved)
|
||
const validColumns = tableColumns.value
|
||
.filter(col => !col.alwaysShow && !col.fixed)
|
||
.map(col => col.prop || col.label)
|
||
const filteredSaved = savedColumns.filter((col: string) => validColumns.includes(col))
|
||
|
||
if (filteredSaved.length > 0) {
|
||
visibleColumns.value = filteredSaved
|
||
} else if (options?.defaultVisible && options.defaultVisible.length > 0) {
|
||
visibleColumns.value = options.defaultVisible
|
||
} else {
|
||
visibleColumns.value = validColumns
|
||
}
|
||
} catch (e) {
|
||
console.error('解析列配置失败:', e)
|
||
visibleColumns.value = options?.defaultVisible || tableColumns.value
|
||
.filter(col => !col.alwaysShow && !col.fixed)
|
||
.map(col => col.prop || col.label)
|
||
}
|
||
} else {
|
||
visibleColumns.value = options?.defaultVisible || tableColumns.value
|
||
.filter(col => !col.alwaysShow && !col.fixed)
|
||
.map(col => col.prop || col.label)
|
||
}
|
||
|
||
// 加载列排序配置
|
||
const orderKey = getStorageKey('order')
|
||
const savedOrder = localStorage.getItem(orderKey)
|
||
if (savedOrder) {
|
||
try {
|
||
const parsedOrder = JSON.parse(savedOrder)
|
||
const validColumns = tableColumns.value
|
||
.filter(col => !col.alwaysShow && !col.fixed)
|
||
.map(col => col.prop || col.label)
|
||
columnOrder.value = parsedOrder.filter((key: string) => validColumns.includes(key))
|
||
|
||
// 添加新列到排序列表末尾
|
||
validColumns.forEach(key => {
|
||
if (!columnOrder.value.includes(key)) {
|
||
columnOrder.value.push(key)
|
||
}
|
||
})
|
||
} catch (e) {
|
||
console.error('解析列排序失败:', e)
|
||
columnOrder.value = tableColumns.value
|
||
.filter(col => !col.alwaysShow && !col.fixed)
|
||
.map(col => col.prop || col.label)
|
||
}
|
||
} else {
|
||
columnOrder.value = tableColumns.value
|
||
.filter(col => !col.alwaysShow && !col.fixed)
|
||
.map(col => col.prop || col.label)
|
||
}
|
||
}
|
||
|
||
// 保存列配置
|
||
const saveColumnConfig = (columns: string[]) => {
|
||
visibleColumns.value = columns
|
||
const storageKey = getStorageKey()
|
||
const selectableColumns = columns.filter(col => {
|
||
const column = tableColumns.value.find(c => (c.prop || c.label) === col)
|
||
return column && !column.alwaysShow && !column.fixed
|
||
})
|
||
localStorage.setItem(storageKey, JSON.stringify(selectableColumns))
|
||
}
|
||
|
||
// 保存列排序
|
||
const saveColumnOrder = (order: string[]) => {
|
||
columnOrder.value = order
|
||
const orderKey = getStorageKey('order')
|
||
localStorage.setItem(orderKey, JSON.stringify(order))
|
||
}
|
||
|
||
// 检查列是否可见
|
||
const checkColumnVisible = (prop: string): boolean => {
|
||
if (visibleColumns.value.length === 0) {
|
||
return true
|
||
}
|
||
return visibleColumns.value.includes(prop)
|
||
}
|
||
|
||
// 初始化
|
||
onMounted(() => {
|
||
nextTick(() => {
|
||
loadSavedConfig()
|
||
})
|
||
})
|
||
|
||
return {
|
||
visibleColumns,
|
||
columnOrder,
|
||
tableColumns,
|
||
checkColumnVisible,
|
||
saveColumnConfig,
|
||
saveColumnOrder,
|
||
loadSavedConfig,
|
||
getStorageKey
|
||
}
|
||
}
|
||
|