效果图:
后端返回数据:
实现步骤:
- 将数据平铺处理成效果图展示的格式
handleData(data) {
return data.flatMap(item => {
if (item.tpList.length > 0) {
return item.tpList.map(tp => {
return {
...item,
updateTime: this.$moment(item.updateTime).format('YYYY-MM-DD'),
postLevelList: tp.postLevelList,
tpList: [tp]
};
});
}
return {...item}
});
},
- 处理好的数据格式
- 开始合并单元格(在不需要额外的样式需求及事件时,可以在配置列时直接调用此函数。有其他需求可参考下方配置的操作列对比修改)
//传入的name表示要根据哪个字段进行合并,tableData是处理好的表格数据
mergeCell(value, row, index, name, tableData) {
// 满足要求需要合并的行中的第一行
const temp_Index = tableData.findIndex(record => record[name] === row[name] && row[name] !== null && row[name] !== '');
// 需要合并的行数
const rowSpan = tableData.filter(record => record[name] === row[name] && row[name] !== null && row[name] !== '').length;
if (rowSpan > 1) {
// 要合并的行中的第一个(从这一行合并)
if (temp_Index === index) {
return {
children: value,
attrs: { rowSpan }
};
}
// 其他要合并的行都设rowSpan=0
return {
children: value,
attrs: { rowSpan: 0 }
};
}
return value;
}
- 这里根据name进行合并,columns配置如下:
columns: [
{
title: '岗位系列',
dataIndex: 'name',
key: 'name',
width: 300,
align: 'left',
customRender: (value, row, index) => {
return mergeCell(value, row, index, 'name', this.tableData);
}
},
{
title: '岗位类别',
dataIndex: 'postTypeList',
key: 'postTypeList',
width: 300,
align: 'left',
scopedSlots: {customRender: 'postTypeList'},
customRender: (value, row, index) => {
// 满足要求需要合并的行中的第一行
const temp_Index = this.tableData.findIndex(record => record.name === row.name && row.name !== null);
// 需要合并的行数
const rowSpan = this.tableData.filter(record => record.name === row.name && row.name !== null).length;
let tag = this.$createElement('tb-table-tags', {
props: {
list: value
}
});
if (rowSpan > 1) {
// 要合并的行中的第一个(从这一行合并)
if (temp_Index === index) {
return {
children: value ? tag : '',
attrs: {rowSpan}
};
}
// 其他要合并的行都设rowSpan=0
return {
children: value ? tag : '',
attrs: {rowSpan: 0}
};
}
return value ? tag : '';
}
},
{
title: '专业技术职务',
dataIndex: 'tpList',
key: 'tpList',
width: 300,
align: 'left',
scopedSlots: {customRender: 'tpList'},
},
{
title: '字典值',
dataIndex: 'postLevelList',
key: 'postLevelList',
width: 300,
align: 'left',
scopedSlots: {customRender: 'postLevelList'},
},
{
title: '最新修改日期',
dataIndex: 'updateTime',
key: 'updateTime',
width: 300,
align: 'left',
customRender: (value, row, index) => {
return mergeCell(value, row, index, 'name', this.tableData);
}
},
{
title: '状态',
dataIndex: 'state',
key: 'state',
width: 200,
align: 'center',
customRender: (value, row, index) => {
// 满足要求需要合并的行中的第一行
const temp_Index = this.tableData.findIndex(record => record.name === row.name && row.name !== null);
// 需要合并的行数
const rowSpan = this.tableData.filter(record => record.name === row.name && row.name !== null).length;
let tag = this.$createElement('string-table-tag', {
props: {
type: value ? 'primary' : 'danger'
}
}, value ? '启用' : '禁用');
if (rowSpan > 1) {
// 要合并的行中的第一个(从这一行合并)
if (temp_Index === index) {
return {
children: tag,
attrs: {rowSpan}
};
}
// 其他要合并的行都设rowSpan=0
return {
children: tag,
attrs: {rowSpan: 0}
};
}
return tag;
}
},
{
title: '操作',
dataIndex: 'operation',
key: 'operation',
width: 200,
customRender: (value, row, index) => {
const temp_Index = this.tableData.findIndex(record => record.name === row.name && row.name !== null);
const rowSpan = this.tableData.filter(record => record.name === row.name && row.name !== null).length;
let div = this.$createElement(
'div',
[
this.$createElement('string-text-button', {
on: {click: () => this.updateState(row)},
props: {
type: row.state === 0 ? 'primary' : 'delete'
}
}, row.state ? '禁用' : '启用'),
this.$createElement('a-divider', {props: {type: 'vertical'}}),
this.$createElement('string-text-button', {
on: {click: () => this.onEdit(row)},
props: {
type: 'edit'
}
}, '编辑'),
this.$createElement('a-divider', {props: {type: 'vertical'}}),
this.$createElement('string-text-button', {
on: {click: () => this.onDelete(row)},
props: {
type: 'delete',
content: `确认删除【${row.name}】,是否继续?`
}
}, '删除')
]
);
if (rowSpan > 1) {
if (temp_Index === index) {
return {
children: div,
attrs: {rowSpan}
};
}
return {
children: div,
attrs: {rowSpan: 0}
};
}
return div;
}
}
],
- 这样我们的表格就合并好了,可以按照我们想要的样子渲染啦。html部分如下:
<a-table
id="myTable"
:columns="columns"
:data-source="tableData"
:loading="loading"
:pagination="false"
:rowKey="record => record.id"
bordered
>
<template slot="tpList" slot-scope="text, record">
<tb-table-tags :list="record.tpList"></tb-table-tags>
</template>
<template slot="postLevelList" slot-scope="text, record">
<tb-table-tags :list="record.postLevelList"></tb-table-tags>
</template>
</a-table>