<template> <el-table
|
v-loading="loading"
|
:data="tableData"
|
:border="border"
|
:show-selection="showSelection"
|
:max-height="maxHeight"
|
:header-cell-style="{ background: '#EBEEF5', color: '#3D3D3D' }"
|
@selection-change="handleSelectionChange"
|
@row-click="handleRowClick"
|
@row-dblclick="handleRowDblClick"
|
@cell-click="handleCellClick"
|
:max-width="maxWidth"
|
@export="handleExport"
|
:default-selection="defaultSelection"
|
:show-overflow-tooltip="showOverflowTooltip"
|
ref="tableRef"
|
:row-key="rowKey"
|
style="width: 100%"
|
>
|
<el-table-column v-if="showSelection" type="selection" width="55" align="center" />
|
<el-table-column v-if="showIndex" label="序号" type="index" width="60" align="center" />
|
<template v-for="col in columns" :key="col.prop">
|
<el-table-column v-bind="col" :show-overflow-tooltip="shouldShowTooltip(col, tableData)"
|
:formatter="col.formatter || defaultFormatter" align="center">
|
<template v-if="col.slot" #default="scope">
|
<slot :name="col.prop" :row="scope.row" :column="scope.column" :index="scope.$index"></slot>
|
</template>
|
</el-table-column>
|
</template>
|
<!-- 操作列 -->
|
<el-table-column v-if="showOperations" :label="operationsLabel" :width="operationsWidth" fixed="right" align="center">
|
<template #default="scope">
|
<slot name="operations" :row="scope.row">
|
<el-button v-if="operations.includes('edit')" link type="primary" size="small"
|
@click="handleEdit(scope.row)">编辑</el-button>
|
<!-- <el-button-->
|
<!-- v-if="operations.includes('delete')"-->
|
<!-- link-->
|
<!-- type="danger"-->
|
<!-- size="small"-->
|
<!-- @click="handleDelete(scope.row)"-->
|
<!-- >删除</el-button>-->
|
</slot>
|
</template>
|
</el-table-column>
|
</el-table>
|
</template>
|
|
<script setup>
|
import { defineEmits, ref , defineProps, onMounted ,defineExpose, watch, nextTick} from 'vue'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
const props = defineProps({
|
// 最大宽度
|
maxWidth: {
|
type: [String, Number],
|
default: 'auto'
|
},
|
handleCellClick: {
|
type: Function,
|
default: () => { }
|
},
|
handleRowClick: {
|
type: Function,
|
default: () => { }
|
},
|
handleExport: {
|
type: Function,
|
default: () => { }
|
},
|
handleRowDblClick: {
|
type: Function,
|
default: () => { }
|
},
|
// 高度
|
maxHeight: {
|
type: [String, Number],
|
default: 'auto'
|
},
|
// 加载状态
|
loading: {
|
type: Boolean,
|
default: false
|
},
|
// border
|
border: {
|
type: Boolean,
|
default: false
|
},
|
// 表格数据
|
tableData: {
|
type: Array,
|
default: () => []
|
},
|
// 是否显示选择列
|
showSelection: {
|
type: Boolean,
|
default: true
|
},
|
// 是否显示序号列
|
showIndex: {
|
type: Boolean,
|
default: true
|
},
|
// 列配置
|
columns: {
|
type: Array,
|
default: () => []
|
},
|
// 是否显示操作列
|
showOperations: {
|
type: Boolean,
|
default: true
|
},
|
// 操作列标签
|
operationsLabel: {
|
type: String,
|
default: '操作'
|
},
|
// 操作列宽度
|
operationsWidth: {
|
type: [String, Number],
|
default: 100
|
},
|
// 显示哪些操作按钮
|
operations: {
|
type: Array,
|
default: () => ['edit', 'delete', 'export']
|
}, // 删除确认信息
|
deleteConfirmText: {
|
type: String,
|
default: '确认删除该记录?'
|
},
|
// 默认选中的行 ID 数组
|
defaultSelectedIds: {
|
type: Array,
|
default: () => []
|
},
|
// 行唯一标识字段名(默认为 id)
|
rowKey: {
|
type: String,
|
default: 'id'
|
},
|
showOverflowTooltip: {
|
type: Boolean,
|
default: true
|
}
|
})
|
const tableRef = ref(null)
|
// 检查列是否需要显示tooltip
|
const shouldShowTooltip = (col, data) => {
|
// 如果列配置中明确设置了showOverflowTooltip,使用该设置
|
if (col.hasOwnProperty('showOverflowTooltip')) {
|
return col.showOverflowTooltip;
|
}
|
// 如果没有prop,直接返回false
|
if (!col.prop) return false;
|
// 检查该列在所有数据中是否有非空值,默认显示tooltip
|
return data.some(row => row[col.prop] != null && row[col.prop] !== '');
|
};
|
|
// 默认的格式化函数
|
const defaultFormatter = (row, column, cellValue) => {
|
return cellValue == null || cellValue === '' || cellValue === 0 ? '--' : cellValue;
|
};
|
|
// 处理选择变化、编辑、删除和导出操作
|
const emit = defineEmits(['selection-change', 'edit', 'delete', 'export'])
|
const handleSelectionChange = (selection) => {
|
emit('selection-change', selection)
|
}
|
const handleEdit = (row) => {
|
emit('edit', row)
|
}
|
const handleDelete = (row) => {
|
ElMessageBox.confirm(
|
props.deleteConfirmText,
|
'警告',
|
{
|
confirmButtonText: '确定',
|
cancelButtonText: '取消',
|
type: 'warning'
|
}
|
).then(() => {
|
emit('delete', row)
|
}).catch(() => { })
|
}
|
|
const handleExport = (row) => {
|
emit('export', row)
|
}
|
|
// 正确的 toggleRowSelection 方法:针对单行
|
const toggleRowSelection = (row, selected) => {
|
if (tableRef.value && row) {
|
tableRef.value.toggleRowSelection(row, selected);
|
}
|
};
|
|
// 批量设置行选中状态的方法
|
const setRowsSelection = (rows, selected = true) => {
|
if (tableRef.value && Array.isArray(rows)) {
|
rows.forEach((row) => {
|
tableRef.value.toggleRowSelection(row, selected);
|
});
|
}
|
};
|
|
// 复选框默认选中状态
|
const defaultSelection = ref([])
|
// 设置默认选中状态
|
const setDefaultSelection = () => {
|
if (!tableRef.value || !props.defaultSelectedIds.length || !props.tableData.length) {
|
return;
|
}
|
|
|
// 延迟执行,确保表格完全渲染
|
nextTick(() => {
|
setTimeout(() => {
|
try {
|
tableRef.value.clearSelection();
|
const rowsToSelect = props.tableData.filter(row => {
|
const rowId = row[props.rowKey];
|
return props.defaultSelectedIds.includes(rowId);
|
});
|
rowsToSelect.forEach(row => {
|
tableRef.value.toggleRowSelection(row, true);
|
});
|
} catch (error) {
|
}
|
}, 100);
|
});
|
};
|
|
// 监听数据变化,自动设置默认选中
|
watch(() => [props.tableData, props.defaultSelectedIds], () => {
|
if (props.tableData.length > 0 && props.defaultSelectedIds.length > 0) {
|
setDefaultSelection();
|
}
|
}, {
|
deep: true,
|
immediate: true
|
});
|
|
// 组件挂载后设置默认选中
|
onMounted(() => {
|
if (props.defaultSelectedIds.length > 0) {
|
setDefaultSelection();
|
}
|
});
|
|
// 暴露 el-table 的实例和常用方法
|
defineExpose({
|
// 单行选中/取消选中
|
toggleRowSelection,
|
// 批量设置行选中状态
|
setRowsSelection,
|
// 根据ID数组选中行
|
setDefaultSelection,
|
// 清除所有选中
|
clearSelection: () => tableRef.value?.clearSelection(),
|
// 获取选中的行
|
getSelectionRows: () => tableRef.value?.getSelectionRows() || [],
|
// 设置当前行
|
setCurrentRow: (row) => tableRef.value?.setCurrentRow(row),
|
// 获取表格实例(如需直接操作)
|
getTableRef: () => tableRef.value
|
});
|
|
</script>
|
|
<style scoped>
|
.el-table {
|
margin: 20px 0 !important;
|
}
|
|
:deep(.el-table th) {
|
background-color: #f5f7fa;
|
}
|
|
/* 响应式样式 */
|
@media screen and (max-width: 768px) {
|
:deep(.el-table) {
|
width: 100%;
|
overflow-x: auto;
|
}
|
}
|
|
/* 支持地址列换行显示 */
|
:deep(.el-table .cell) {
|
white-space: normal !important;
|
word-break: break-all;
|
line-height: 1.4;
|
}
|
|
/* 为地址列设置最小高度以容纳多行文本 */
|
:deep(.el-table td) {
|
padding: 8px 0;
|
}
|
</style>
|