Files
GEAR-OA/gear-ui3/src/components/GearTable/index.vue

237 lines
5.3 KiB
Vue
Raw Normal View History

2025-09-02 15:03:34 +08:00
<template>
<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 核心 -->
<el-table
:ref="tableRef"
v-bind="$attrs"
v-on="$listeners"
:class="['my-table', customClass]"
:data="tableData"
>
<!-- 透传列定义插槽 -->
<template
v-for="(column, index) in $attrs.columns || []"
v-slot:[`header-${column.prop}`]="scope"
>
<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>
<!-- 透传原生内置插槽 -->
<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>
<!-- 透传自定义列插槽 -->
<slot v-bind:tableRef="tableRef"></slot>
<el-table-column
v-if="selectionColumn"
type="selection"
width="55"
align="center"
></el-table-column>
<el-table-column
v-if="indexColumn"
type="index"
width="55"
align="center"
></el-table-column>
<el-table-column
v-for="(column, index) in _columns"
v-bind="column"
:width="column.width"
:prop="column.prop"
:align="column.align"
:label="column.label"
:min-width="column.minWidth"
:fixed="column.fixed"
:show-overflow-tooltip="column.showOverflowTooltip"
:sortable="column.sortable"
>
<template v-slot="scope">
<ColumnRender v-if="column.render" :column="column" :data="scope.row" :render="column.render"/>
<Eclipse v-else-if="column.eclipse" :text="scope.row[column.prop]"></Eclipse>
<span v-else>{{ scope.row[column.prop] }}</span>
</template>
</el-table-column>
</el-table>
<!-- 分页插槽 -->
<slot name="pagination"></slot>
</div>
</template>
<script>
import ColumnRender from './ColumnRender.vue';
import Eclipse from './renderer/eclipse.vue';
export default {
name: "KLPTable",
components: {
ColumnRender,
Eclipse,
},
props: {
// 基础扩展属性
loading: {
type: Boolean,
default: false
},
loadingText: {
type: String,
default: "加载中..."
},
customClass: {
type: String,
default: ""
},
// 表格数据
tableData: {
type: Array,
default: () => []
},
// 列定义
customColumns: {
type: Array,
default: () => []
},
// 选择列
selectionColumn: {
type: Boolean,
default: false
},
// 索引列
indexColumn: {
type: Boolean,
default: false
},
// 操作工具
actionTool: {
type: Array,
default: () => ['fullScreen', 'export', 'setting']
},
// 导出文件名
exportFileName: {
type: String,
default: '表格数据'
}
},
data() {
return {
tableRef: "myTableRef",
columns: []
};
},
computed: {
_columns() {
return this.columns.filter(col => col.show);
},
},
watch: {
customColumns: {
handler(newVal) {
console.log(newVal, this.customColumns, '自定义列');
this.columns = newVal.map(col => ({...col, show: true}));
},
deep: true,
immediate: true
}
},
methods: {
// 获取表格实例
getTableInstance() {
return this.$refs[this.tableRef];
},
// 透传原生方法
clearSelection() {
const table = this.getTableInstance();
if (table && table.clearSelection) {
table.clearSelection();
}
},
toggleRowSelection(row, selected) {
const table = this.getTableInstance();
if (table && table.toggleRowSelection) {
table.toggleRowSelection(row, selected);
}
},
// 操作处理方法(可被覆盖或扩展)
handleFullScreen() {
this.$emit('fullScreen');
},
handleRefresh() {
this.$emit('refresh');
},
handleExport() {
this.$emit('export');
},
handlePrint() {
this.$emit('print');
},
// handleSetting() {
// this.$emit('setting');
// },
updateColumnsVisibility(changes) {
// 更新列的hidden属性
changes.forEach(change => {
const column = this.columns.find(col => col.prop === change.prop);
if (column) {
column.show = !column.show;
}
});
}
},
mounted() {
console.log("KLPTable 初始化完成,原生实例:", this.getTableInstance());
}
};
</script>
<style scoped>
.my-table-container {
width: 100%;
position: relative;
}
.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;
}
.my-table {
width: 100%;
}
</style>