Vben admin - 表格组件合并单元格
需求
最近在项目中有需求需要表格合并单元格,不但内容有合并的,操作列也需要合并,找遍vben官方例子,没有实现操作列合并的,只能硬着头皮实现,还好实现了,下面具体就是实现思路;
原型设计图
分析需求
整体思路就是当数据中一级分类值相同则进行合并分数、一级分类以及编辑分数(操作列),由于操作列合并vben框架目前不支持,只能在数据上下功夫,假设表格数据中每组数据返回字段operatorName:‘操作’;这样我们就像渲染普通数据一样渲染出来,然后再给器操作加上事件即可
合并核心思路
let newArr = data.reduce((result, item) => {
// 首先将字段作为新数组result取出
if (result.indexOf(item['name']) < 0) {
result.push(item['name']);
}
return result;
}, []).reduce((res, name) => {
// 将name相同的数据作为新数组取出,并在其内部添加新字段**rowSpan**
const children = data.filter((item) => item['name'] === name);
// eslint-disable-next-line no-param-reassign
res = res.concat(
children.map((item, index) => ({
...item,
['rowspan']: index === 0 ? children.length : 0, // 将第一行数据添加rowSpan字段
})),
);
return res;
}, []);
整体代码
const [registerTable] = useTable({
title: '合并单元格',
bordered: true,
// 假数据
dataSource: [
{
key: '1',
fenshu: 5,
name: '政治',
age: '政治交流',
num: 4545,
address: 'New York No. 1 Lake Park',
rowspan:2
},
{
key: '2',
fenshu: 5,
name: '政治',
age: '总统选举',
num: 4545,
address: 'London No. 1 Lake Park',
rowspan:0
},
{
key: '3',
fenshu: 5,
name: '经济',
age: '黄金大涨',
num: 4545,
address: 'Sidney No. 1 Lake Park',
rowspan:1
},
{
key: '4',
fenshu: 5,
name: '军事',
age: '核弹引爆',
num: 4545,
address: 'London No. 2 Lake Park',
rowspan:1
},
{
key: '5',
fenshu: 5,
name: '安全',
age: '食品安全',
num: 4545,
address: 'Dublin No. 2 Lake Park',
rowspan:1
},
],
afterFetch: (data) => {
let newArr = data
.reduce((result, item) => {
// 首先将字段作为新数组result取出
if (result.indexOf(item['name']) < 0) {
result.push(item['name']);
}
return result;
}, [])
.reduce((res, name) => {
// 将name相同的数据作为新数组取出,并在其内部添加新字段**rowSpan**
const children = data.filter((item) => item['name'] === name);
// eslint-disable-next-line no-param-reassign
res = res.concat(
children.map((item, index) => ({
...item,
['rowspan']: index === 0 ? children.length : 0, // 将第一行数据添加rowSpan字段
})),
);
return res;
}, []);
return newArr;
},
columns: [
{
title: '分数',
dataIndex: 'fenshu',
width: 200,
customRender: ({ text, record }) => {
const obj = {
children: text,
props: {} as any,
};
obj.props.rowSpan = record.rowspan;
return obj;
},
},
{
title: '一级分类',
dataIndex: 'name',
customRender: ({ text, record }) => {
const obj = {
children: text,
props: {} as any,
};
obj.props.rowSpan = record.rowspan;
return obj;
},
},
{
title: '二级分类',
dataIndex: 'age',
width: 180,
},
{
title: '内容',
dataIndex: 'address',
width: 380,
},
{
title: '数据来源数量',
dataIndex: 'num',
width: 180,
},
{
title: '操作',
dataIndex: 'operatorName',
width: 180,
customRender: ({ text, record }) => {
return {
children: h('a', { onClick: () => handelEdit(record) }, text),
props: {
rowSpan: record.rowspan,
},
};
},
className: 'caozuo', // 单独加上样式类名,在css中将字体颜色改为蓝色 以便和普通数据进行区分
},
],
pagination: false,
showIndexColumn: false,
})
// 编辑操作
const handelEdit = (record: Recordable) => {
console.log(record)
};