This commit is contained in:
guochunsi
2026-01-06 19:23:18 +08:00
parent 8af3aaa9b6
commit e1cb334fbf
33 changed files with 685 additions and 329 deletions

View File

@@ -1,6 +1,8 @@
<template>
<el-table-column
v-if="shouldShow"
:prop="prop"
:label="label"
v-bind="$attrs"
>
<template v-for="(_, name) in $slots" :key="name" #[name]="slotProps">

View File

@@ -41,7 +41,7 @@
>
<el-checkbox
:label="column.prop || column.label"
:disabled="column.fixed !== undefined || column.alwaysShow"
:disabled="!!column.fixed || column.alwaysShow"
>
{{ column.label }}
</el-checkbox>
@@ -113,9 +113,99 @@ const emit = defineEmits<{
const visible = ref(false)
const checkedColumns = ref<string[]>([])
// 如果提供了 tableRef使用自动提取否则使用手动配置的 columns
const tableColumnsResult = props.tableRef
? useTableColumns(props.tableRef, props.storageKey, props.autoExtractOptions)
: {
columns: computed(() => []),
visibleColumns: computed(() => []),
updateVisibleColumns: () => {},
refreshColumns: () => {},
isColumnVisible: () => true
}
const {
columns: autoColumns,
visibleColumns: autoVisibleColumns,
updateVisibleColumns: updateAutoVisibleColumns,
refreshColumns: refreshAutoColumns,
isColumnVisible: autoIsColumnVisible
} = tableColumnsResult
// 实际使用的列配置
const actualColumns = computed(() => {
const result = props.tableRef && autoColumns.value.length > 0
? autoColumns.value
: props.columns || []
return result
})
// 获取所有列(包括固定列和 alwaysShow 列)
const getAllColumns = (): string[] => {
return actualColumns.value.map(col => col.prop || col.label)
}
// 初始化选中的列
const initCheckedColumns = () => {
if (props.modelValue && props.modelValue.length > 0) {
checkedColumns.value = [...props.modelValue]
} else if (props.tableRef && autoVisibleColumns.value.length > 0) {
// 使用自动提取的可见列,但需要确保包含所有列(包括固定列)
// 合并已保存的可见列和固定列/alwaysShow列
const fixedAndAlwaysShow = actualColumns.value
.filter(col => col.alwaysShow || !!col.fixed)
.map(col => col.prop || col.label)
checkedColumns.value = [...new Set([...autoVisibleColumns.value, ...fixedAndAlwaysShow])]
} else if (props.storageKey) {
// 从 localStorage 读取
const saved = localStorage.getItem(props.storageKey)
if (saved) {
try {
const savedColumns = JSON.parse(saved)
// 确保固定列和 alwaysShow 列始终在选中列表中
const fixedAndAlwaysShow = actualColumns.value
.filter(col => col.alwaysShow || !!col.fixed)
.map(col => col.prop || col.label)
checkedColumns.value = [...new Set([...savedColumns, ...fixedAndAlwaysShow])]
} catch (e) {
// 如果解析失败,使用默认值(所有列)
checkedColumns.value = getAllColumns()
}
} else {
checkedColumns.value = getAllColumns()
}
} else {
checkedColumns.value = getAllColumns()
}
}
// 监听 actualColumns 变化,更新选中状态
watch(actualColumns, (newColumns) => {
if (newColumns.length > 0 && checkedColumns.value.length === 0) {
// 如果列数据已加载但选中列表为空,初始化选中所有列
initCheckedColumns()
} else if (newColumns.length > 0) {
// 确保固定列和 alwaysShow 列始终在选中列表中
const fixedAndAlwaysShow = newColumns
.filter(col => col.alwaysShow || !!col.fixed)
.map(col => col.prop || col.label)
const currentChecked = checkedColumns.value
const missingFixed = fixedAndAlwaysShow.filter(col => !currentChecked.includes(col))
if (missingFixed.length > 0) {
checkedColumns.value = [...currentChecked, ...missingFixed]
}
}
}, { deep: true })
// 监听弹窗打开,触发列配置重新提取
watch(visible, (newVal) => {
console.log('[TableColumnControl] 弹窗状态变化:', newVal)
if (newVal) {
// 弹窗打开时,确保选中状态正确初始化
if (actualColumns.value.length > 0) {
initCheckedColumns()
}
}
if (newVal && props.tableRef) {
console.log('[TableColumnControl] 弹窗打开tableRef 存在:', props.tableRef)
console.log('[TableColumnControl] tableRef.value:', props.tableRef.value)
@@ -225,25 +315,6 @@ watch(visible, (newVal) => {
}
})
// 如果提供了 tableRef使用自动提取否则使用手动配置的 columns
const tableColumnsResult = props.tableRef
? useTableColumns(props.tableRef, props.storageKey, props.autoExtractOptions)
: {
columns: computed(() => []),
visibleColumns: computed(() => []),
updateVisibleColumns: () => {},
refreshColumns: () => {},
isColumnVisible: () => true
}
const {
columns: autoColumns,
visibleColumns: autoVisibleColumns,
updateVisibleColumns: updateAutoVisibleColumns,
refreshColumns: refreshAutoColumns,
isColumnVisible: autoIsColumnVisible
} = tableColumnsResult
// 监听 tableRef.value 的变化,当它被赋值时触发列配置提取
if (props.tableRef) {
// 尝试多种方式监听 tableRef.value 的变化
@@ -270,10 +341,6 @@ if (props.tableRef) {
}, { immediate: true }) // 立即检查一次,如果 tableRef.value 已经有值,立即触发
}
// 调试:检查 tableRef 传递
console.log('[TableColumnControl] props.tableRef:', props.tableRef)
console.log('[TableColumnControl] props.tableRef?.value:', props.tableRef?.value)
// 暴露给父组件使用
defineExpose({
isColumnVisible: autoIsColumnVisible,
@@ -281,56 +348,17 @@ defineExpose({
refreshColumns: refreshAutoColumns
})
// 实际使用的列配置
const actualColumns = computed(() => {
const result = props.tableRef && autoColumns.value.length > 0
? autoColumns.value
: props.columns || []
console.log('[TableColumnControl] actualColumns 计算:', {
hasTableRef: !!props.tableRef,
autoColumnsLength: autoColumns.value.length,
propsColumnsLength: props.columns?.length || 0,
resultLength: result.length
})
return result
})
// 初始化选中的列
const initCheckedColumns = () => {
if (props.modelValue && props.modelValue.length > 0) {
checkedColumns.value = [...props.modelValue]
} else if (props.tableRef && autoVisibleColumns.value.length > 0) {
// 使用自动提取的可见列
checkedColumns.value = [...autoVisibleColumns.value]
} else if (props.storageKey) {
// 从 localStorage 读取
const saved = localStorage.getItem(props.storageKey)
if (saved) {
try {
checkedColumns.value = JSON.parse(saved)
} catch (e) {
// 如果解析失败,使用默认值(所有列)
checkedColumns.value = getDefaultColumns()
}
} else {
checkedColumns.value = getDefaultColumns()
}
} else {
checkedColumns.value = getDefaultColumns()
}
}
// 获取默认显示的列(所有可隐藏的列)
// 获取默认显示的列(所有可隐藏的列)- 用于重置功能
const getDefaultColumns = (): string[] => {
return actualColumns.value
.filter(col => !col.alwaysShow && col.fixed === undefined)
.filter(col => !col.alwaysShow && !col.fixed)
.map(col => col.prop || col.label)
}
// 获取所有可选择的列
const selectableColumns = computed(() => {
return actualColumns.value
.filter(col => !col.alwaysShow && col.fixed === undefined)
.filter(col => !col.alwaysShow && !col.fixed)
.map(col => col.prop || col.label)
})
@@ -344,11 +372,14 @@ const isAllSelected = computed(() => {
// 切换全选/全不选
const handleToggleSelectAll = () => {
if (isAllSelected.value) {
// 当前全选,执行全不选
checkedColumns.value = []
// 当前全选,执行全不选(但保留固定列和 alwaysShow 列)
const fixedAndAlwaysShow = actualColumns.value
.filter(col => col.alwaysShow || !!col.fixed)
.map(col => col.prop || col.label)
checkedColumns.value = [...fixedAndAlwaysShow]
} else {
// 当前未全选,执行全选
checkedColumns.value = [...selectableColumns.value]
// 当前未全选,执行全选(所有列)
checkedColumns.value = getAllColumns()
}
}
@@ -366,16 +397,30 @@ const handleConfirm = () => {
// 列变化处理
const handleColumnChange = (value: string[]) => {
emit('update:modelValue', value)
emit('change', value)
// 确保固定列和 alwaysShow 列始终在选中列表中
const fixedAndAlwaysShow = actualColumns.value
.filter(col => col.alwaysShow || !!col.fixed)
.map(col => col.prop || col.label)
const finalValue = [...new Set([...value, ...fixedAndAlwaysShow])]
// 如果使用自动提取,同步更新
emit('update:modelValue', finalValue)
emit('change', finalValue)
// 如果使用自动提取,同步更新(只更新可选择的列)
if (props.tableRef) {
updateAutoVisibleColumns(value)
const selectableValue = finalValue.filter(col => {
const column = actualColumns.value.find(c => (c.prop || c.label) === col)
return column && !column.alwaysShow && !column.fixed
})
updateAutoVisibleColumns(selectableValue)
} else {
// 保存到 localStorage
// 保存到 localStorage(只保存可选择的列)
if (props.storageKey) {
localStorage.setItem(props.storageKey, JSON.stringify(value))
const selectableValue = finalValue.filter(col => {
const column = actualColumns.value.find(c => (c.prop || c.label) === col)
return column && !column.alwaysShow && !column.fixed
})
localStorage.setItem(props.storageKey, JSON.stringify(selectableValue))
}
}
}
@@ -459,3 +504,4 @@ onMounted(() => {
</style>