feat(KLPTable): 添加表格浮层功能以显示详细信息
实现表格行悬浮显示详细信息的浮层功能,支持自定义浮层列配置 重构KLPTable组件结构,将浮层逻辑独立为子组件 在用户管理和钢卷管理页面应用新浮层功能
This commit is contained in:
@@ -6,88 +6,45 @@
|
||||
<p class="loading-text">{{ loadingText || "加载中..." }}</p>
|
||||
</div>
|
||||
|
||||
<!-- 原生 Table 核心:透传 props/事件/插槽 -->
|
||||
<el-table
|
||||
:ref="tableRef"
|
||||
v-bind="$attrs"
|
||||
v-on="$listeners"
|
||||
:class="['my-table', customClass]"
|
||||
>
|
||||
<!-- 1. 透传“列定义插槽”(原生 columns 中通过 slot 自定义的表头/单元格) -->
|
||||
<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>
|
||||
|
||||
<!-- 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-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 customColumns"
|
||||
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>
|
||||
<div class="el-table-container" ref="elTableWrapper" @mouseleave="handleTableLeave">
|
||||
<!-- 原生 Table 核心:透传 props/事件/插槽 -->
|
||||
<el-table :ref="tableRef" v-bind="$attrs" v-on="$listeners" :class="['my-table', customClass]"
|
||||
@cell-mouse-enter="handleCellEnter" @row-mouseleave="handleRowLeave">
|
||||
<!-- 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>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 3. 透传“自定义列”插槽(直接接收<el-table-column> 嵌套的情况) -->
|
||||
<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>
|
||||
<!-- 浮层组件 -->
|
||||
<KLPTableFloatLayer v-if="floatLayer" :columns="floatLayerColumns" :data="hoveredRow" :tooltipVisible="tooltipVisible"
|
||||
:tooltipStyle="tooltipStyle" />
|
||||
</div>
|
||||
<!-- 扩展层:可后续统一添加分页(如与 MyPagination 组件联动) -->
|
||||
<slot name="pagination"></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ColumnRender from './ColumnRender.vue';
|
||||
import ColumnRender from './ColumnRender.vue';
|
||||
import Eclipse from './renderer/eclipse.vue';
|
||||
import KLPTableFloatLayer from './FloatLayer/index.vue';
|
||||
|
||||
export default {
|
||||
name: "KLPTable", // 组件名,便于调试和文档生成
|
||||
components: {
|
||||
ColumnRender,
|
||||
Eclipse
|
||||
Eclipse,
|
||||
KLPTableFloatLayer
|
||||
},
|
||||
props: {
|
||||
// 1. 扩展 props:新增原生 Table 没有的属性(如加载状态)
|
||||
@@ -104,10 +61,6 @@ export default {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
customColumns: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
selectionColumn: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
@@ -115,13 +68,42 @@ export default {
|
||||
indexColumn: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// floatLayer:是否显示浮层
|
||||
floatLayer: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
floatLayerConfig: {
|
||||
type: Object,
|
||||
default: () => ({
|
||||
columns: [],
|
||||
title: '详细信息'
|
||||
})
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
tableRef: "myTableRef" // 表格 ref,便于后续通过 ref 调用原生方法
|
||||
tableRef: "myTableRef", // 表格 ref,便于后续通过 ref 调用原生方法
|
||||
// 浮层相关
|
||||
tooltipVisible: false,
|
||||
tooltipStyle: {
|
||||
top: '0px',
|
||||
left: '0px'
|
||||
},
|
||||
hoveredRow: null,
|
||||
columns: []
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
floatLayerColumns() {
|
||||
console.log(this.floatLayerConfig?.columns?.length > 1)
|
||||
if (this.floatLayerConfig?.columns?.length > 1) {
|
||||
return this.floatLayerConfig.columns
|
||||
}
|
||||
return this.columns;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 核心方法:净化scope,移除可能导致循环引用的属性
|
||||
sanitizeScope(scope) {
|
||||
@@ -136,7 +118,7 @@ export default {
|
||||
if (obj === null || typeof obj !== "object") return obj;
|
||||
if (obj instanceof Date) return new Date(obj);
|
||||
if (obj instanceof RegExp) return new RegExp(obj);
|
||||
|
||||
|
||||
// 避免处理Vue实例(通常带有循环引用)
|
||||
if (obj._isVue) return { _isVue: true };
|
||||
|
||||
@@ -166,11 +148,48 @@ export default {
|
||||
if (table && table.toggleRowSelection) {
|
||||
table.toggleRowSelection(row, selected);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// 浮层相关
|
||||
handleCellEnter(row, column, cell, event) {
|
||||
if (!row || !event) return
|
||||
this.hoveredRow = row
|
||||
this.tooltipVisible = true
|
||||
this.updateTooltipPosition(event)
|
||||
},
|
||||
handleRowLeave() {
|
||||
this.tooltipVisible = false
|
||||
this.hoveredRow = null
|
||||
},
|
||||
handleTableLeave() {
|
||||
this.tooltipVisible = false
|
||||
this.hoveredRow = null
|
||||
},
|
||||
updateTooltipPosition(event) {
|
||||
this.$nextTick(() => {
|
||||
const wrapper = this.$refs.elTableWrapper
|
||||
if (!wrapper) return
|
||||
|
||||
const wrapperRect = wrapper.getBoundingClientRect()
|
||||
let left = event.clientX - wrapperRect.left + 16
|
||||
let top = event.clientY - wrapperRect.top + 12
|
||||
|
||||
this.tooltipStyle = {
|
||||
top: `${top}px`,
|
||||
left: `${left}px`
|
||||
}
|
||||
})
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
// 扩展点:后续可统一添加初始化逻辑(如权限控制、默认排序等)
|
||||
console.log("MyTable 初始化完成,原生实例:", this.getTableInstance());
|
||||
// console.log("MyTable 初始化完成,原生实例:", this.getTableInstance());
|
||||
// 几个特殊的列,需要特殊处理 index, selection, action
|
||||
const columns = this.$slots.default.filter(item => item.tag?.includes('ElTableColumn') && item.componentInstance && item.componentInstance.columnConfig && item.componentOptions && item.componentOptions.propsData).map(item => ({
|
||||
...item.componentInstance.columnConfig,
|
||||
...item.componentOptions.propsData
|
||||
}))
|
||||
this.columns = columns
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user