Files
guoju0808/ry-vue3/refer/gr-table-simple.vue
T
guoju0808 0644e26120 feat: GrTable 移动端表格组件 + manager/Projects 试点
业务背景
- 项目里 17+ 列的列表页 (manager/Projects, Meetings, AdminUsers 等) 在手机端只能
  横向滚动, 操作体验差.
- refer/gr-table.vue 是 Vue2 + Vant 组件, Vue3 不能直接用 (componentOptions
  私有 API 已被 Vue3 移除).
- 新建 Vue3 + EP 兼容版本 GrTable, 吸收"主列显示 / 次要列折叠到展开行"思想.

组件设计
- props: data, mainCols (默认 = 第一个 prop + 最后一个 prop), mobileBreakpoint
- 通过 slots.default() 取 vnode, 读 vnode.props.prop/label (Vue3 思路, 替代
  Vue2 componentOptions 私有 API)
- v-bind="\$attrs" 全透传 el-table 原生 props/events
- el-table 引用方法 (clearSelection / toggleRowSelection 等) defineExpose
  暴露

manager/Projects 试点
- 引入 GrTable, :main-cols="['projectNo', 'projectName']"
- 手机端: 只显示项目编号 + 项目名称 + 操作列, 其他 13 列折叠到展开行
- 桌面端: 与原 el-table 完全一致 (所有 17 列)
- 操作列 (label=操作, 无 prop) 自动保留 (因为 shouldRenderColumn 跳过无 prop 列)
2026-08-26 11:32:53 +00:00

94 lines
2.8 KiB
Vue

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