chore: 新增 refer 参考表格组件

- gr-table.vue: 通用 el-table 封装 (展开详情 + 事件透传)
- gr-table-simple.vue: 简化版表格
- gr-table-plus.vue: 增强版 (筛选框 + 展开详情)
This commit is contained in:
郭庆泰
2026-08-26 19:14:34 +08:00
parent 8a08c8378f
commit a837e43b53
3 changed files with 372 additions and 0 deletions
+161
View File
@@ -0,0 +1,161 @@
<template>
<div class="gr-table-container">
<div class="gr-table-filter">
<div class="gr-query-wrap">
<div>筛选</div>
<van-field class="gr-query" v-model="queryVal"></van-field>
<van-icon name="search" size="18"></van-icon>
</div>
</div>
<el-table class="gr-table" ref="mesSysTable" :data="data2Show" :border="border" :height="height"
:max-height="maxHeight" :stripe="stripe" :size="size" :fit="fit" :show-header="showHeader"
:highlight-current-row="highlightCurrentRow" :highlight-selection-row="highlightSelectionRow"
:current-row-key="currentRowKey" :row-class-name="rowClassName" :row-style="rowStyle" :cell-class-name="cellClassName"
:cell-style="cellStyle" :header-row-class-name="headerRowClassName" :header-row-style="headerRowStyle"
:header-cell-class-name="headerCellClassName" :header-cell-style="headerCellStyle" :row-key="rowKey"
:empty-text="emptyText" :default-expand-all="defaultExpandAll" :expand-row-keys="expandRowKeys"
:default-sort="defaultSort" :tooltip-effect="tooltipEffect" :show-summary="showSummary" :summary-method="summaryMethod"
:sum-text="sumText" :span-method="spanMethod" :select-on-indeterminate="selectOnIndeterminate" :indent="indent"
:lazy="lazy" :load="load" :tree-props="treeProps"
@select="(evt) => $emit('select',evt)" @select-all="(evt) => $emit('select-all',evt)"
@selection-change="(evt) => $emit('selection-change',evt)" @cell-mouse-enter="(evt) => $emit('cell-mouse-enter',evt)"
@cell-mouse-leave="(evt) => $emit('cell-mouse-leave',evt)" @cell-click="(evt) => $emit('cell-click',evt)"
@cell-dblclick="(evt) => $emit('cell-dblclick',evt)" @row-click="(evt) => $emit('row-click',evt)"
@row-contextmenu="(evt) => $emit('row-contextmenu',evt)" @row-dblclick="(evt) => $emit('row-dblclick',evt)"
@header-click="(evt) => $emit('header-click',evt)" @header-contextmenu="(evt) => $emit('header-contextmenu',evt)"
@sort-change="(evt) => $emit('sort-change',evt)" @filter-change="(evt) => $emit('filter-change',evt)"
@current-change="(evt) => $emit('current-change',evt)" @header-dragend="(evt) => $emit('header-dragend',evt)"
@expand-change="(evt) => $emit('expand-change',evt)" >
<el-table-column width="30" type="expand" v-if="meta">
<template slot-scope="scope">
<el-descriptions :column="1" style="margin: 0 20px;">
<el-descriptions-item v-for="(item, index) in meta" :label="item.label" :key="index">{{scope.row[item.prop]}}</el-descriptions-item>
</el-descriptions>
</template>
</el-table-column>
<slot>
</slot>
</el-table>
</div>
</template>
<script>
import Vue from 'vue';
import { Field } from 'vant';
Vue.use(Field);
import {Icon} from "vant";
Vue.use(Icon);
export default {
props: ["data","meta" ,"major","border","height","maxHeight","stripe","size","fit","showHeader",
"highlightCurrentRow","highlightSelectionRow","currentRowKey","rowClassName","rowStyle","cellClassName",
"cellStyle","headerRowClassName", "headerRowStyle","headerCellClassName","headerCellStyle",
"rowKey", "emptyText","defaultExpandAll", "expandRowKeys","defaultSort","tooltipEffect","sumText","showSummary",
"summaryMethod", "spanMethod","selectOnIndeterminate","indent","lazy","load","treeProps",
],
data() {
return {
data2Show: [],
slight: null,
mainCol: this.major,
rows: null,
queryVal: null,
};
},
watch: {
data() {
this.refreshData();
},
queryVal(val) {
// console.log("queryval ", val);
this.refreshData();
}
},
methods: {
getDataList(row) {
return Object.keys(row)
.filter((key) => this.slight.some((s) => s.prop == key)).map((key) => {
return {
label: this.slight.find((s) => s.prop == key).label,
value: row[this.slight.find((s) => s.prop == key).prop],
};
});
},
clearSelection(...args) { this.$refs['mesSysTable'].clearSelection(...args)},
toggleRowSelection (...args) {this.$refs['mesSysTable'].toggleRowSelection(...args)},
toggleAllSelection (...args) { this.$refs['mesSysTable'].toggleAllSelection(...args)},
toggleRowExpansion (...args) { this.$refs['mesSysTable'].toggleRowExpansion(...args)},
setCurrentRow (...args) { this.$refs['mesSysTable'].setCurrentRow(...args)},
clearSort (...args) { this.$refs['mesSysTable'].clearSort(...args)},
clearFilter (...args){ this.$refs['mesSysTable'].clearFilter(...args)},
doLayout (...args){ this.$refs['mesSysTable'].doLayout(...args)},
sort (...args){ this.$refs['mesSysTable'].sort(...args)},
refreshData() {
if (this.queryVal) {
// this.$showLoading();
// console.log("queryval is",this.queryVal);
this.data2Show = this.data.filter(item => {
return JSON.stringify(item).indexOf(this.queryVal) != -1;
})
// this.$hideLoading();
} else {
this.data2Show = this.data;
}
}
},
// created() {
// this.data2Show = JSON.parse(JSON.stringify(this.data));
// },
};
</script>
<style scoped lang="scss">
@import "@/assets/styles/vant.scss";
::v-deep .van-cell {
padding: 0px !important
}
::v-deep .el-table .cell {
padding-left: 0 !important;
padding-right: 0 !important;
font-size: 12px;
line-height: 18px;
}
.gr-table-container {
padding: 0 8px;
.gr-table-filter {
width: 100%;
display: flex;
justify-content: center;
align-items: center;
border-radius: 16px;
height: 32px;
border: 1px solid $gr-border;
margin-bottom: 10px;
.gr-query-wrap {
width: calc(100% - 32px);
display: flex;
justify-content: space-between;
align-items: center;
}
.gr-query {
width: calc(100% - 60px);
}
}
}
::v-deep th.el-table__cell {
background: #0ECD4916 !important;
font-family: PingFangSC-Medium;
color: #323233;
line-height: 22px;
font-weight: 700;
}
::v-deep .el-table__cell {
padding: 8px !important;
}
::v-deep .el-descriptions__body {
font-size: 12px !important;
line-height: 18px;
}
</style>
+94
View File
@@ -0,0 +1,94 @@
<template>
<div>
<el-table v-if="showTable" ref="mesSysTable" :data="data" :border="border" :height="height"
@select="(evt) => $emit('select',evt)" @select-all="(evt) => $emit('select-all',evt)"
@selection-change="(evt) => $emit('selection-change',evt)" @cell-mouse-enter="(evt) => $emit('cell-mouse-enter',evt)"
>
<el-table-column type="expand" v-if="slight && slight[0]">
<template slot-scope="scope">
<el-descriptions :column="1" style="margin: 0 20px;">
<el-descriptions-item v-for="(item, index) in getDataList(scope.row)" :label="item.label" :key="index">{{item.value}}</el-descriptions-item>
</el-descriptions>
</template>
</el-table-column>
<slot name="default">
</slot>
</el-table>
</div>
</template>
<script>
export default {
props: ["data", "major","border","height"],
data() {
return {
mainCol: this.major,
rows: null,
showTable: true,
refreshing: false,
};
},
methods: {
getDataList(row) {
return Object.keys(row)
.filter((key) => this.slight.some((s) => s.prop == key)).map((key) => {
return {
label: this.slight.find((s) => s.prop == key).label,
value: row[this.slight.find((s) => s.prop == key).prop],
};
});
},
initData() {
let length = this.$slots.default.length, rows = this.$slots.default;
// if (window.innerWidth < 768) { //判断PDA
if (!this.major || !this.major[0]) { //如果没有指定重要的列,默认第一列(一般是名称)和最后一列(一般是操作)
this.mainCol = [rows[0].componentOptions.propsData.prop,rows[length-1].componentOptions.propsData.prop]
}
this.slight = rows.filter((item) => { //筛选不重要的列,展示到expand中
return !(this.mainCol.some((main) => {
return main == item.componentOptions.propsData.prop;
}));
}).map((item) => {
return item.componentOptions.propsData;
});
this.rows = rows.filter((item) => { //去掉不重要的列
return this.mainCol.some((main) => {
return main == item.componentOptions.propsData.prop;
}) || !item.componentOptions.propsData.prop;
});
this.$slots.default = this.rows;
// }
}
},
created() {
this.initData();
},
updated() {
if (!this.refreshing) {
this.refreshing = true;
this.showTable = false;
} else{
setTimeout(()=> {
this.showTable = true;
this.initData();
},0)
}
}
};
</script>
<style scoped lang="scss">
::v-deep th.el-table__cell {
background: #0ECD4916 !important;
font-family: PingFangSC-Medium;
// font-size: 16px;
color: #323233;
line-height: 22px;
font-weight: 700;
}
::v-deep .el-table__cell {
padding: 8px !important;
}
</style>
+117
View File
@@ -0,0 +1,117 @@
<template>
<div>
<el-table ref="mesSysTable" :data="data" :border="border" :height="height"
:max-height="maxHeight" :stripe="stripe" :size="size" :fit="fit" :show-header="showHeader"
:highlight-current-row="highlightCurrentRow" :highlight-selection-row="highlightSelectionRow"
:current-row-key="currentRowKey" :row-class-name="rowClassName" :row-style="rowStyle" :cell-class-name="cellClassName"
:cell-style="cellStyle" :header-row-class-name="headerRowClassName" :header-row-style="headerRowStyle"
:header-cell-class-name="headerCellClassName" :header-cell-style="headerCellStyle" :row-key="rowKey"
:empty-text="emptyText" :default-expand-all="defaultExpandAll" :expand-row-keys="expandRowKeys"
:default-sort="defaultSort" :tooltip-effect="tooltipEffect" :show-summary="showSummary" :summary-method="summaryMethod"
:sum-text="sumText" :span-method="spanMethod" :select-on-indeterminate="selectOnIndeterminate" :indent="indent"
:lazy="lazy" :load="load" :tree-props="treeProps"
@select="(evt) => $emit('select',evt)" @select-all="(evt) => $emit('select-all',evt)"
@selection-change="(evt) => $emit('selection-change',evt)" @cell-mouse-enter="(evt) => $emit('cell-mouse-enter',evt)"
@cell-mouse-leave="(evt) => $emit('cell-mouse-leave',evt)" @cell-click="(evt) => $emit('cell-click',evt)"
@cell-dblclick="(evt) => $emit('cell-dblclick',evt)" @row-click="(evt) => $emit('row-click',evt)"
@row-contextmenu="(evt) => $emit('row-contextmenu',evt)" @row-dblclick="(evt) => $emit('row-dblclick',evt)"
@header-click="(evt) => $emit('header-click',evt)" @header-contextmenu="(evt) => $emit('header-contextmenu',evt)"
@sort-change="(evt) => $emit('sort-change',evt)" @filter-change="(evt) => $emit('filter-change',evt)"
@current-change="(evt) => $emit('current-change',evt)" @header-dragend="(evt) => $emit('header-dragend',evt)"
@expand-change="(evt) => $emit('expand-change',evt)" >
<el-table-column type="expand" v-if="slight && slight[0]">
<template slot-scope="scope">
<el-descriptions :column="1" style="margin: 0 20px;">
<el-descriptions-item v-for="(item, index) in getDataList(scope.row)" :label="item.label" :key="index">{{item.value}}</el-descriptions-item>
</el-descriptions>
</template>
</el-table-column>
<slot>
</slot>
</el-table>
</div>
</template>
<script>
export default {
props: ["data", "major","border","height","maxHeight","stripe","size","fit","showHeader",
"highlightCurrentRow","highlightSelectionRow","currentRowKey","rowClassName","rowStyle","cellClassName",
"cellStyle","headerRowClassName", "headerRowStyle","headerCellClassName","headerCellStyle",
"rowKey", "emptyText","defaultExpandAll", "expandRowKeys","defaultSort","tooltipEffect","sumText","showSummary",
"summaryMethod", "spanMethod","selectOnIndeterminate","indent","lazy","load","treeProps",
],
data() {
return {
slight: null,
mainCol: this.major,
rows: null,
};
},
methods: {
getDataList(row) {
return Object.keys(row)
.filter((key) => this.slight.some((s) => s.prop == key)).map((key) => {
return {
label: this.slight.find((s) => s.prop == key).label,
value: row[this.slight.find((s) => s.prop == key).prop],
};
});
},
clearSelection(...args) { this.$refs['mesSysTable'].clearSelection(...args)},
toggleRowSelection (...args) {this.$refs['mesSysTable'].toggleRowSelection(...args)},
toggleAllSelection (...args) { this.$refs['mesSysTable'].toggleAllSelection(...args)},
toggleRowExpansion (...args) { this.$refs['mesSysTable'].toggleRowExpansion(...args)},
setCurrentRow (...args) { this.$refs['mesSysTable'].setCurrentRow(...args)},
clearSort (...args) { this.$refs['mesSysTable'].clearSort(...args)},
clearFilter (...args){ this.$refs['mesSysTable'].clearFilter(...args)},
doLayout (...args){ this.$refs['mesSysTable'].doLayout(...args)},
sort (...args){ this.$refs['mesSysTable'].sort(...args)},
initData() {
let length = this.$slots.default.length, rows = this.$slots.default;
// if (window.innerWidth < 768) { //判断PDA
if (!this.major || !this.major[0]) { //如果没有指定重要的列,默认第一列(一般是名称)和最后一列(一般是操作)
this.mainCol = [rows[0].componentOptions.propsData.prop,rows[length-1].componentOptions.propsData.prop]
}
this.slight = rows.filter((item) => { //筛选不重要的列,展示到expand中
return !(this.mainCol.some((main) => {
return main == item.componentOptions.propsData.prop;
}));
}).map((item) => {
return item.componentOptions.propsData;
});
this.rows = rows.filter((item) => { //去掉不重要的列
return this.mainCol.some((main) => {
return main == item.componentOptions.propsData.prop;
}) || !item.componentOptions.propsData.prop;
});
this.$slots.default = this.rows;
// }
}
},
created() {
this.initData();
},
updated() {
console.log("updated!!!!");
// this.initData();
// this.$slots.default = this.rows;
}
};
</script>
<style scoped lang="scss">
::v-deep th.el-table__cell {
background: #0ECD4916 !important;
font-family: PingFangSC-Medium;
// font-size: 16px;
color: #323233;
line-height: 22px;
font-weight: 700;
}
::v-deep .el-table__cell {
padding: 8px !important;
}
</style>