Files
GEAR-OA/gear-ui3/src/components/GearTable/index.vue
2025-09-03 11:55:00 +08:00

237 lines
5.3 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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>