效果图:
在父组件使用表格组件
<table-listref="table":stripe="true":loading="loading":set-table-h="slotProps.setMainCardBodyH":table-data="tableData":columns="columns.tableList || []":radio="topicTypeListMapItem.radio"show-opearshow-selection:fix-width="240":page-data="pageData":disabled-select-key="topicTypeListMapItem.disabledSelectKey"@changeSize="changeSize"@changePage="changePage"><!--预警灯--><template #warningLight="{ row }"><div class="lightCireBlock"><div><div v-for="(item,index) in row.warningLight" :key="'warningLight'+index"><svg-icon v-if="Object.keys(columns.warningLight).includes(item)" :icon-class="columns.warningLight[item].icon" class="task-icon" /><spanv-if="columns.warningLight[item] && columns.warningLight[item].hasNum && row[`warningLight${item}`] * 1 > 0"class="fontBoxAll fontBox">{{ row[`warningLight${item}`] }}</span></div></div></div></template><!--标题--><template #taskTitle="{ row }"><span class="td-cell lineCell" @click="editMainEvent(row)"> {{ row.taskTitle }}</span></template><!--状态--><template #status="{ row }"><el-tag :disable-transitions="true" :class="columns.statusLists[row.status].className">{{ columns.statusLists[row.status].label }}</el-tag></template><!--操作--><template slot-scope="{ row }"><div class="table-buttonList"><template v-for="(item,index) in columns.btnList"><el-buttonv-if="item.isShow?item.isShow(row):true":key="index"type="text"@click="btnFn[item.clickFn.fn](row,...(item.clickFn.params?item.clickFn.params:[]))">{{ item.name }}</el-button></template></div></template></table-list>
然后用一个js文件来存储动态的参数
import { selectOverseerMeetingLeaType } from '@/api/common.js'export const topicTypeListMap = new Map([['keyWork',{name: '重点工作',radio: false, // 表格数据是否单选showImportBtn: true, // 是否显示批量导入按钮showApprovalBtn: false, // 是否显示送立项按钮showImportApprovalBtn: false, // 导入时是否显示送立项按钮showItemTypeBtn: false, // 导入时是否显示选择事项类型按钮showWorkRequireBtn: false, // 导入时是否显示批量填写工作要求按钮showFoliCureBtn: false, // 是否显示送办理按钮hasSubtasks: true, // 专题是否有子任务isMeetingTopicType: false, // 是否是会议类专题disabledSelectKey: [{ label: 'status', value: '0' }, { label: 'status', value: '1' }] // 表格哪些状态的数据禁选}],['feasibleInstructions',{name: '督办件',radio: false,showImportBtn: true,showApprovalBtn: true,showImportApprovalBtn: true, // 导入时是否显示送立项按钮showItemTypeBtn: true, // 导入时是否显示选择事项类型按钮showWorkRequireBtn: false, // 导入时是否显示批量填写工作要求按钮showFoliCureBtn: true,hasSubtasks: false,isMeetingTopicType: false,disabledSelectKey: []}]])
在组件中
props传的参数
props: {// 表格数据tableData: {type: Array,default: () => {return []}},// 表格字段columns: {type: Array,default: () => {return []}},// 表格字段的宽度fixWidth: {type: Number,default: 150},// 单选radio: {type: Boolean,default: false},// 显示序号showIndex: {type: Boolean,default: false},// 是否自定义高度setTableH: {type: Boolean,default: true},// 显示勾选showSelection: {type: Boolean,default: false},// 显示操作showOpear: {type: Boolean,default: false},spanMethod: {type: Function,default() {return () => {}}},// 斑马线stripe: {type: Boolean,default: false},// 分页showPagination: {type: Boolean,default: true},setCheckbox: {type: Boolean,default: false},loading: { // 判断是否正在加载表格数据type: Boolean,default: false},align: {type: String,default: 'left'},recordCheck: { // 是否在翻页的时候记录之前选择的表格数据type: Boolean,default: true},// 分页数据pageData: {type: Object,default: () => {return {page: 1,rows: 15,pageSize: [15, 25, 35],total: 0}}},isImportData: { // 判断是否导入的数据type: Boolean,default: false},disabledSelectKey: { // 需要禁用的选择框的数据type: Array,default: () => {return []}}},
完整代码
<template><div ref="wrap" class="wrap"><el-tableref="table":key="'tableData'+tableData.length"v-loading="loading"element-loading-text="正在处理,请稍候!":data="tableData":stripe="stripe":span-method="spanMethod":header-row-class-name="headerRowClassName(radio)":height="setTableH?setTableHeight:'100%'"class="table-list"border@sort-change="sortChange"@selection-change="handleSelectionChange"><template slot="empty"><img src="@/assets/images/empty.png"><p>暂无数据</p></template><!--选择框--><el-table-column v-if="showSelection" type="selection" width="42" :selectable="checkSelectable" /><!--序号--><el-table-column v-if="showIndex" type="index" label="序号" width="55" align="center" /><el-table-columnv-for="item in columns":key="item.lable":label="item.title":prop="item.slot || item.lable":min-width="item.minWidth || 140":width="item.width":sortable="item.sortable":show-overflow-tooltip="item.overflow":align="item.align"><!-- 二级表头 --><el-table-columnv-for="subItem in item.columns":key="subItem.label":label="subItem.title":prop="subItem.slot || subItem.lable":min-width="subItem.minWidth || 140":width="subItem.width":sortable="subItem.sortable":show-overflow-tooltip="subItem.overflow":align="subItem.align"><template slot="header"><!-- <span v-if="item.isRequest" style="color:red">*</span> --><span> {{ subItem.title }}</span></template><template slot-scope="{ row }"><slot :name="subItem.slot" :row="row"><span class="td-cell"> {{ isImportData ? row[subItem.label].value : row[subItem.label] }}</span><template v-if="isImportData"><el-popoverv-if="typeof(row[subItem.label].success) === 'boolean' && !row[subItem.label].success"placement="top"title=""trigger="hover":content="row[subItem.label].message"><i slot="reference" class="el-icon-warning" style="color:#F44336" /></el-popover></template></slot></template></el-table-column><template slot="header"><!-- <span v-if="item.isRequest" style="color:red">*</span> --><span> {{ item.title }}</span></template><template slot-scope="{ row }"><slot :name="item.slot" :row="row"><span class="td-cell">{{ isImportData ? row[item.label].value : row[item.label] }}</span><template v-if="isImportData"><el-popoverv-if="typeof(row[item.label].success) === 'boolean' && !row[item.label].success"placement="top"title=""trigger="hover":content="row[item.label].message"><i slot="reference" class="el-icon-warning" style="color:#F44336" /></el-popover></template></slot></template></el-table-column><!--操作按钮--><el-table-column v-if="showOpear" label="操作" prop="operation" :width="fixWidth" fixed="right"><template #default="{ row, $index }"><slot :row="row" :$index="$index" /></template></el-table-column></el-table><el-paginationv-if="showPagination && tableData.length>0"background:current-page="pageData.page":page-size="pageData.rows":page-sizes="pageData.pageSize"layout="sizes, prev, pager, next, slot, jumper":total="pageData.total"class="pagination"@current-change="handleCurrentChange"@size-change="handleSizeChange"><span class="pagination-total">共{{ pageData.total }}条,</span></el-pagination></div>
</template><script>
import { clone } from 'lodash'
export default {name: 'TableList',props: {// 表格数据tableData: {type: Array,default: () => {return []}},// 表格字段columns: {type: Array,default: () => {return []}},// 表格字段的宽度fixWidth: {type: Number,default: 150},// 单选radio: {type: Boolean,default: false},// 显示序号showIndex: {type: Boolean,default: false},// 是否自定义高度setTableH: {type: Boolean,default: true},// 显示勾选showSelection: {type: Boolean,default: false},// 显示操作showOpear: {type: Boolean,default: false},spanMethod: {type: Function,default() {return () => {}}},// 斑马线stripe: {type: Boolean,default: false},// 分页showPagination: {type: Boolean,default: true},setCheckbox: {type: Boolean,default: false},loading: { // 判断是否正在加载表格数据type: Boolean,default: false},align: {type: String,default: 'left'},recordCheck: { // 是否在翻页的时候记录之前选择的表格数据type: Boolean,default: true},// 分页数据pageData: {type: Object,default: () => {return {page: 1,rows: 15,pageSize: [15, 25, 35],total: 0}}},isImportData: { // 判断是否导入的数据type: Boolean,default: false},disabledSelectKey: { // 需要禁用的选择框的数据type: Array,default: () => {return []}}},data() {return {saveMultipleSelection: {}, // 用来保存每个分页勾选的数据multipleSelection: [],setTableHeight: 300}},computed: {headerRowClassName() {return (radio) => {if (radio) {return 'tableHead isRadio'} else {return 'tableHead'}}}},watch: {tableData: {handler(newVal) {this.$nextTick(() => {if (this.multipleSelection && this.recordCheck) {const idList = this.multipleSelection.map(item => { return item.businessKey })newVal.forEach(item => {if (idList.indexOf(item.businessKey) > -1) {this.$refs.table.toggleRowSelection(item, true)}})}})},deep: true},saveMultipleSelection: {handler(newVal) {this.multipleSelection = Object.keys(newVal).reduce((prev, next) => {prev = prev.concat(newVal[next])return [...new Set(prev)]}, [])this.$EventBus.$emit('selection-change', this.multipleSelection)},deep: true}},updated() {this.$nextTick(() => {this.setTableHeight = this.$refs.wrap.offsetHeight - document.querySelector('.el-table__header-wrapper').offsetHeight - 48 - 10// 10是给分页腾一点空间})},methods: {handleSizeChange(e) {this.$emit('changeSize', e)},handleCurrentChange(e) {this.$emit('changePage', e)},clearSort() {this.$refs.table.clearSort()},getSelection() {return clone(this.$refs.table.selection)},sortChange(e) {this.$emit('sortChange', e)},checkSelectable(row) {let check = trueif (this.disabledSelectKey.length > 0) {this.disabledSelectKey.forEach(item => {if (row[item.label] === item.value) {check = false}})}return check},handleSelectionChange(val) {if (this.radio) { // 单选// var newRows = val.filter((it, index) => {// if (index === val.length - 1) {// this.$refs.table.toggleRowSelection(it, true)// return true// } else {// this.$refs.table.toggleRowSelection(it, false)// return false// }// })// this.saveMultipleSelection = newRowsthis.$nextTick(() => {var newRows = val.filter((it, index) => {if (index === val.length - 1) {this.$refs.table.toggleRowSelection(it, true)return true} else {this.$refs.table.toggleRowSelection(it, false)return false}})if (val.length > 0) {this.saveMultipleSelection = {}this.$set(this.saveMultipleSelection, this.pageData.page, newRows)}// this.saveMultipleSelection = newRows})} else {this.$nextTick(() => {this.$set(this.saveMultipleSelection, this.pageData.page, val)})}},toggleRowSelection(row, bool) {this.$refs.table.toggleRowSelection(row, bool)}}}
</script>
<style scoped lang="scss">.wrap{height: 100%;::v-deep .isRadio {.el-checkbox{display: none;}}}::v-deep .el-table ::-webkit-scrollbar{height: 8px;}
</style>