ren
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
:label="label"
|
||||
v-bind="$attrs"
|
||||
>
|
||||
<template v-for="(_, name) in $slots" :key="name" #[name]="slotProps">
|
||||
<template v-for="(_, name) in $slots" #[name]="slotProps">
|
||||
<slot :name="name" v-bind="slotProps" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -31,35 +31,13 @@ const isColumnVisible = inject<(propOrLabel: string) => boolean>('isColumnVisibl
|
||||
// 计算是否应该显示该列
|
||||
const shouldShow = computed(() => {
|
||||
// 优先使用 prop,如果没有 prop 则使用 label
|
||||
let key = props.prop || props.label || ''
|
||||
const key = props.prop || props.label || ''
|
||||
if (!key) {
|
||||
// 如果没有 prop 和 label,默认显示(可能是序号列等特殊列)
|
||||
return true
|
||||
}
|
||||
|
||||
// 如果 key 是 label,尝试通过 labelToPropMap 映射到 prop
|
||||
// 这样可以确保与 useTableColumns 的提取逻辑一致
|
||||
if (!props.prop && props.label) {
|
||||
const labelToPropMap: Record<string, string> = {
|
||||
'是否退休': 'tied',
|
||||
'姓名/工号': 'nameNo',
|
||||
'性别': 'sex',
|
||||
'部门': 'deptName',
|
||||
'学历学位': 'dgreeName',
|
||||
'职称等级': 'professionalTitle',
|
||||
'岗位级别': 'stationLevelName',
|
||||
'职业资格等级': 'levelName',
|
||||
'职业资格工种': 'workName',
|
||||
'用工性质': 'employmentNatureName',
|
||||
'手机': 'telPhone',
|
||||
'家庭住址': 'homeAddress',
|
||||
'授课类型': 'teacherCate',
|
||||
'操作': 'action',
|
||||
}
|
||||
// 如果 label 在映射表中,使用映射后的 prop;否则使用 label
|
||||
key = labelToPropMap[props.label] || props.label
|
||||
}
|
||||
|
||||
// isColumnVisible 函数会同时匹配 prop 和 label,所以直接传递即可
|
||||
return isColumnVisible(key)
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -2,36 +2,24 @@
|
||||
<div class="table-column-control">
|
||||
<el-button
|
||||
:type="triggerType"
|
||||
:icon="Setting"
|
||||
:icon="slots.trigger ? undefined : Menu"
|
||||
:size="triggerSize"
|
||||
:circle="triggerCircle"
|
||||
:link="triggerLink"
|
||||
@click="visible = true"
|
||||
>
|
||||
<slot name="trigger">
|
||||
{{ triggerText || '列设置' }}
|
||||
{{ triggerText || '列显隐' }}
|
||||
</slot>
|
||||
</el-button>
|
||||
|
||||
<el-dialog
|
||||
v-model="visible"
|
||||
title="列显示设置"
|
||||
title="列显隐设置"
|
||||
:width="dialogWidth"
|
||||
append-to-body
|
||||
>
|
||||
<div class="column-control-content">
|
||||
<div class="column-control-header">
|
||||
<div class="header-actions">
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
@click="handleToggleSelectAll"
|
||||
>
|
||||
{{ isAllSelected ? '取消全选' : '全选' }}
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="column-control-body">
|
||||
<el-checkbox-group v-model="checkedColumns" @change="handleColumnChange" class="column-checkbox-group">
|
||||
<div
|
||||
@@ -45,30 +33,25 @@
|
||||
>
|
||||
{{ column.label }}
|
||||
</el-checkbox>
|
||||
<el-tag v-if="column.fixed !== undefined" size="small" type="info">
|
||||
<!-- <el-tag v-if="column.fixed !== undefined" size="small" type="info">
|
||||
{{ column.fixed === 'left' ? '固定左侧' : column.fixed === 'right' ? '固定右侧' : '固定' }}
|
||||
</el-tag>
|
||||
</el-tag> -->
|
||||
</div>
|
||||
</el-checkbox-group>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<div class="column-control-footer">
|
||||
<el-button @click="handleReset">重置</el-button>
|
||||
<el-button type="primary" @click="handleConfirm">确定</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch, onMounted, nextTick, type Ref } from 'vue'
|
||||
import { Setting } from '@element-plus/icons-vue'
|
||||
import { ref, computed, watch, onMounted, nextTick, useSlots, type Ref } from 'vue'
|
||||
import { Menu } from '@element-plus/icons-vue'
|
||||
import type { TableInstance } from 'element-plus'
|
||||
import { useTableColumns, type ColumnConfig } from '/@/composables/useTableColumns'
|
||||
|
||||
const slots = useSlots()
|
||||
|
||||
interface Column {
|
||||
prop?: string
|
||||
label: string
|
||||
@@ -102,7 +85,7 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
triggerCircle: false,
|
||||
triggerText: '',
|
||||
triggerLink: false,
|
||||
dialogWidth: '600px'
|
||||
dialogWidth: '800px'
|
||||
})
|
||||
|
||||
const emit = defineEmits<{
|
||||
@@ -225,7 +208,6 @@ watch(actualColumns, (newColumns) => {
|
||||
|
||||
// 监听弹窗打开,触发列配置重新提取
|
||||
watch(visible, (newVal) => {
|
||||
console.log('[TableColumnControl] 弹窗状态变化:', newVal)
|
||||
if (newVal) {
|
||||
// 弹窗打开时,确保选中状态正确初始化(但不重置用户已保存的设置)
|
||||
if (actualColumns.value.length > 0) {
|
||||
@@ -246,27 +228,20 @@ watch(visible, (newVal) => {
|
||||
}
|
||||
}
|
||||
if (newVal && props.tableRef) {
|
||||
console.log('[TableColumnControl] 弹窗打开,tableRef 存在:', props.tableRef)
|
||||
console.log('[TableColumnControl] tableRef.value:', props.tableRef.value)
|
||||
console.log('[TableColumnControl] tableRef.value 类型:', typeof props.tableRef.value)
|
||||
|
||||
// 尝试多种方式获取表格实例
|
||||
const getTableInstance = (): TableInstance | null => {
|
||||
// 方法1: 直接从 props.tableRef.value 获取
|
||||
if (props.tableRef?.value) {
|
||||
console.log('[TableColumnControl] 从 props.tableRef.value 获取表格实例')
|
||||
return props.tableRef.value
|
||||
}
|
||||
|
||||
// 方法2: 尝试从 props.tableRef 本身获取(可能是直接的 ref 对象)
|
||||
if ((props.tableRef as any).value) {
|
||||
console.log('[TableColumnControl] 从 props.tableRef 的 value 属性获取表格实例')
|
||||
return (props.tableRef as any).value
|
||||
}
|
||||
|
||||
// 方法3: 如果 props.tableRef 本身就是表格实例(不应该发生,但作为备用)
|
||||
if ((props.tableRef as any).$el) {
|
||||
console.log('[TableColumnControl] props.tableRef 本身就是表格实例')
|
||||
return props.tableRef as any
|
||||
}
|
||||
|
||||
@@ -278,10 +253,8 @@ watch(visible, (newVal) => {
|
||||
if (tableInstance) {
|
||||
const tableEl = (tableInstance as any).$el
|
||||
if (tableEl) {
|
||||
console.log('[TableColumnControl] 表格实例已就绪,立即提取列配置')
|
||||
nextTick(() => {
|
||||
refreshAutoColumns()
|
||||
console.log('[TableColumnControl] 刷新后列数:', actualColumns.value.length)
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -298,21 +271,16 @@ watch(visible, (newVal) => {
|
||||
if (tableInstance) {
|
||||
const tableEl = (tableInstance as any).$el
|
||||
if (tableEl) {
|
||||
console.log('[TableColumnControl] 表格实例已就绪,开始提取列配置')
|
||||
nextTick(() => {
|
||||
refreshAutoColumns()
|
||||
console.log('[TableColumnControl] 刷新后列数:', actualColumns.value.length)
|
||||
|
||||
// 如果还是没有数据,多次重试
|
||||
let retryCount = 0
|
||||
const maxRetries = 10
|
||||
const retryInterval = setInterval(() => {
|
||||
retryCount++
|
||||
console.log(`[TableColumnControl] 第 ${retryCount} 次重试刷新列配置`)
|
||||
refreshAutoColumns()
|
||||
console.log(`[TableColumnControl] 重试后列数:`, actualColumns.value.length)
|
||||
if (actualColumns.value.length > 0 || retryCount >= maxRetries) {
|
||||
console.log('[TableColumnControl] 停止重试,最终列数:', actualColumns.value.length)
|
||||
clearInterval(retryInterval)
|
||||
}
|
||||
}, 200)
|
||||
@@ -324,16 +292,10 @@ watch(visible, (newVal) => {
|
||||
// 继续等待
|
||||
waitCount++
|
||||
if (waitCount < maxWaitCount) {
|
||||
console.log(`[TableColumnControl] tableRef.value 还未就绪,等待中... (${waitCount}/${maxWaitCount})`)
|
||||
waitTimer = setTimeout(waitForTableRef, 100)
|
||||
} else {
|
||||
console.warn('[TableColumnControl] 等待超时,tableRef.value 仍未就绪')
|
||||
console.warn('[TableColumnControl] props.tableRef:', props.tableRef)
|
||||
console.warn('[TableColumnControl] props.tableRef?.value:', props.tableRef?.value)
|
||||
// 即使超时,也尝试提取一次(可能表格已经渲染了,只是 ref 没有正确绑定)
|
||||
console.log('[TableColumnControl] 尝试强制提取列配置')
|
||||
refreshAutoColumns()
|
||||
console.log('[TableColumnControl] 强制提取后列数:', actualColumns.value.length)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -349,8 +311,6 @@ watch(visible, (newVal) => {
|
||||
waitTimer = null
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.warn('[TableColumnControl] 弹窗打开但 tableRef 不存在或为空')
|
||||
}
|
||||
})
|
||||
|
||||
@@ -368,16 +328,14 @@ if (props.tableRef) {
|
||||
return null
|
||||
}, (newVal, oldVal) => {
|
||||
if (newVal && newVal !== oldVal) {
|
||||
console.log('[TableColumnControl] tableRef.value 已赋值,触发列配置提取')
|
||||
// 延迟一下,确保表格完全渲染
|
||||
setTimeout(() => {
|
||||
nextTick(() => {
|
||||
refreshAutoColumns()
|
||||
console.log('[TableColumnControl] 列配置提取完成,列数:', actualColumns.value.length)
|
||||
})
|
||||
}, 200)
|
||||
}
|
||||
}, { immediate: true }) // 立即检查一次,如果 tableRef.value 已经有值,立即触发
|
||||
}, { immediate: true })
|
||||
}
|
||||
|
||||
// 暴露给父组件使用
|
||||
@@ -387,54 +345,7 @@ defineExpose({
|
||||
refreshColumns: refreshAutoColumns
|
||||
})
|
||||
|
||||
// 获取默认显示的列(所有可隐藏的列)- 用于重置功能
|
||||
const getDefaultColumns = (): string[] => {
|
||||
return actualColumns.value
|
||||
.filter(col => !col.alwaysShow && !col.fixed)
|
||||
.map(col => col.prop || col.label)
|
||||
}
|
||||
|
||||
// 获取所有可选择的列
|
||||
const selectableColumns = computed(() => {
|
||||
return actualColumns.value
|
||||
.filter(col => !col.alwaysShow && !col.fixed)
|
||||
.map(col => col.prop || col.label)
|
||||
})
|
||||
|
||||
// 判断是否全选
|
||||
const isAllSelected = computed(() => {
|
||||
const selectable = selectableColumns.value
|
||||
if (selectable.length === 0) return false
|
||||
return selectable.every(col => checkedColumns.value.includes(col))
|
||||
})
|
||||
|
||||
// 切换全选/全不选
|
||||
const handleToggleSelectAll = () => {
|
||||
if (isAllSelected.value) {
|
||||
// 当前全选,执行全不选(但保留固定列和 alwaysShow 列)
|
||||
const fixedAndAlwaysShow = actualColumns.value
|
||||
.filter(col => col.alwaysShow || !!col.fixed)
|
||||
.map(col => col.prop || col.label)
|
||||
checkedColumns.value = [...fixedAndAlwaysShow]
|
||||
} else {
|
||||
// 当前未全选,执行全选(所有列)
|
||||
checkedColumns.value = getAllColumns()
|
||||
}
|
||||
}
|
||||
|
||||
// 重置为默认值
|
||||
const handleReset = () => {
|
||||
checkedColumns.value = getDefaultColumns()
|
||||
handleColumnChange(checkedColumns.value)
|
||||
}
|
||||
|
||||
// 确认
|
||||
const handleConfirm = () => {
|
||||
handleColumnChange(checkedColumns.value)
|
||||
visible.value = false
|
||||
}
|
||||
|
||||
// 列变化处理
|
||||
// 列变化处理(实时生效)
|
||||
const handleColumnChange = (value: string[]) => {
|
||||
// 确保固定列和 alwaysShow 列始终在选中列表中
|
||||
const fixedAndAlwaysShow = actualColumns.value
|
||||
@@ -442,6 +353,7 @@ const handleColumnChange = (value: string[]) => {
|
||||
.map(col => col.prop || col.label)
|
||||
const finalValue = [...new Set([...value, ...fixedAndAlwaysShow])]
|
||||
|
||||
// 立即应用更改
|
||||
emit('update:modelValue', finalValue)
|
||||
emit('change', finalValue)
|
||||
|
||||
@@ -483,26 +395,6 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
.column-control-content {
|
||||
.column-control-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding-bottom: 12px;
|
||||
margin-bottom: 12px;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
|
||||
.header-title {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.header-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.column-control-body {
|
||||
max-height: 400px;
|
||||
overflow-y: auto;
|
||||
|
||||
Reference in New Issue
Block a user