🦄 refactor: 封装统一表格组件,便于批量扩展表格能力

This commit is contained in:
砂糖
2025-08-27 16:47:33 +08:00
parent 278b0c8258
commit 7ea0de6a67
133 changed files with 465 additions and 432 deletions

View File

@@ -1,148 +1,132 @@
<template>
<div class="base-table">
<!-- 给内部表格添加ref方便暴露 -->
<div class="my-table-container">
<!-- 扩展层可后续统一添加如加载动画导出按钮等 -->
<div v-if="loading" class="table-loading">
<el-loading-spinner></el-loading-spinner>
<p class="loading-text">{{ loadingText || "加载中..." }}</p>
</div>
<!-- 原生 Table 核心透传 props/事件/插槽 -->
<el-table
ref="internalTable"
:ref="tableRef"
v-bind="$attrs"
v-on="$listeners"
:data="data"
:loading="loading"
:class="['my-table', customClass]"
>
<!-- 通过配置数组渲染列 -->
<template v-for="(column, index) in columns">
<el-table-column
v-if="column.visible !== false"
v-bind="column"
>
<!-- 列的自定义内容插槽 -->
<template v-if="column.slot" #default="scope">
<slot :name="column.slot" :scope="scope"></slot>
</template>
<!-- 表头自定义内容 -->
<template v-if="column.headerSlot" #header>
<slot :name="column.headerSlot"></slot>
</template>
</el-table-column>
</template>
<!-- 操作列 -->
<el-table-column
v-if="showActionColumn"
:label="actionColumnLabel"
:width="actionColumnWidth"
:fixed="actionColumnFixed"
:align="actionColumnAlign"
<!-- 1. 透传列定义插槽原生 columns 中通过 slot 自定义的表头/单元格 -->
<template
v-for="(column, index) in $attrs.columns || []"
v-slot:[`header-${column.prop}`]="scope"
>
<template #default="scope">
<slot name="action" :scope="scope"></slot>
</template>
</el-table-column>
<!-- 原生插槽支持直接写el-table-column -->
<slot></slot>
<!-- 调用业务层定义的表头插槽 -->
<slot :name="`header-${column.prop}`" v-bind="scope"></slot>
</template>
<template
v-for="(column, index) in $attrs.columns || []"
v-slot:[column.prop]="scope"
>
<!-- 调用业务层定义的单元格插槽 -->
<slot :name="column.prop" v-bind="scope"></slot>
</template>
<!-- 2. 透传原生内置插槽 empty 空数据插槽append 底部插槽等 -->
<template v-slot:empty="scope">
<slot name="empty" v-bind="scope"></slot>
</template>
<template v-slot:append="scope">
<slot name="append" v-bind="scope"></slot>
</template>
<!-- 3. 透传自定义列插槽业务层直接用 <el-table-column> 嵌套的情况 -->
<slot v-bind:tableRef="tableRef"></slot>
</el-table>
<!-- 扩展层可后续统一添加分页如与 MyPagination 组件联动 -->
<slot name="pagination"></slot>
</div>
</template>
<script>
export default {
name: 'BaseTable',
name: "KLPTable", // 组件名,便于调试和文档生成
props: {
// 表格数据
data: {
type: Array,
default: () => []
},
// 列配置数组
columns: {
type: Array,
default: () => []
},
// 是否显示加载状态
// 1. 扩展 props新增原生 Table 没有的属性(如加载状态)
loading: {
type: Boolean,
default: false
},
// 是否显示操作列
showActionColumn: {
type: Boolean,
default: false
},
// 操作列标题
actionColumnLabel: {
loadingText: {
type: String,
default: '操作'
default: "加载中..."
},
// 操作列宽度
actionColumnWidth: {
type: Number,
default: 150
},
// 操作列固定方式
actionColumnFixed: {
// 2. 兼容原生 class 用法(原生 el-table 支持 class 属性,此处显式接收避免 $attrs 冲突)
customClass: {
type: String,
default: 'right'
},
// 操作列内容对齐方式
actionColumnAlign: {
type: String,
default: 'center'
default: ""
}
},
// 暴露内部表格的方法和属性
data() {
return {
tableRef: "myTableRef" // 表格 ref便于后续通过 ref 调用原生方法
};
},
methods: {
/**
* 获取内部el-table实例
*/
// 3. 透传原生 Table 实例方法(如 clearSelection、doLayout 等)
// 业务层可通过 this.$refs.myTable.xxx() 调用原生方法
getTableInstance() {
return this.$refs.internalTable
return this.$refs[this.tableRef];
},
/**
* 代理el-table的常用方法方便直接调用
*/
// 示例:透传原生 clearSelection 方法
clearSelection() {
if (this.$refs.internalTable) {
this.$refs.internalTable.clearSelection()
const table = this.getTableInstance();
if (table && table.clearSelection) {
table.clearSelection();
}
},
// 可根据需要扩展更多原生方法(如 toggleRowSelection、sort 等)
toggleRowSelection(row, selected) {
if (this.$refs.internalTable) {
this.$refs.internalTable.toggleRowSelection(row, selected)
}
},
toggleAllSelection() {
if (this.$refs.internalTable) {
this.$refs.internalTable.toggleAllSelection()
}
},
doLayout() {
if (this.$refs.internalTable) {
this.$refs.internalTable.doLayout()
}
},
sort(prop, order) {
if (this.$refs.internalTable) {
this.$refs.internalTable.sort(prop, order)
const table = this.getTableInstance();
if (table && table.toggleRowSelection) {
table.toggleRowSelection(row, selected);
}
}
},
// 提供一个$refs的代理方便访问内部表格
mounted() {
// 可以在这里添加一些初始化逻辑
// 扩展点:后续可统一添加初始化逻辑(如权限控制、默认排序等)
console.log("MyTable 初始化完成,原生实例:", this.getTableInstance());
}
}
};
</script>
<style scoped>
.base-table {
.my-table-container {
width: 100%;
box-sizing: border-box;
position: relative;
}
</style>
/* 扩展样式:加载状态遮罩(后续可统一调整) */
.table-loading {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(255, 255, 255, 0.8);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 10;
}
.loading-text {
margin-top: 12px;
color: #666;
font-size: 14px;
}
/* 原生 Table 样式兼容:避免封装层影响原生样式 */
.my-table {
width: 100%;
}
</style>