实现效果如下: 横向为不同的班级,纵向为不同的科目,行数和列数内容都是不确定的,需要动态生成。
1.数据格式
行数据对应tableData里每项的grade,列数据对应的是tableData里每项options的label。具体渲染几行和几列要看后台返回的数据,以下数据结构是参考示例。
// 用来渲染每列的表头
this.headerList = this.tableData?.[0]?.options?.map(item => ({ label: item.label }))
// table的数据格式
this.tableData = [
{
id: 1,
grade: "高一(1)",
options: [
{ label: "语文", num: 200 },
{ label: "数学", num: 200 },
{ label: "英语", num: 200 },
{ label: "物理", num: 150 },
{ label: "历史", num: 80 },
],
},
{
id: 2,
grade: "高一(2)",
options: [
{ label: "语文", num: 150 },
{ label: "数学", num: 150 },
{ label: "英语", num: 150 },
{ label: "物理", num: 70 },
{ label: "历史", num: 50 },
],
},
]
2.html结构
列循环,匹配每个科目得到对应的num人数
<el-table
:data="tableData"
border
:summary-method="getSummaries"
show-summary
>
<el-table-column label="班级/科目" align="center" prop="grade" width="150"/>
<el-table-column
v-for="(item, index) in headerList"
:key="index"
:label="item.label"
align="center"
width="120"
>
<template slot-scope="scope">
<span>{{ scope.row.options[index].num }}</span>
</template>
</el-table-column>
<el-table-column label="班级人数汇总" align="center" prop="sum" width="180" />
</el-table>
3.求和
横向求和:对班级人数进行汇总,加工数据结构,将每项options的num进行求和,定义一个sum元素来接收,用prop进行绑定渲染。
this.tableData = this.tableData.map((item) => {
const sum = item.options.reduce((prev, curr) => {
return prev + Number(curr.num);
}, 0);
return {
...item,
sum
};
});
纵向求和:使用summary-method并传入一个方法,返回一个数组,这个数组中的各项就会显示在合计行的各列中
getSummaries(param) {
const { columns, data } = param;
const sums = [];
columns.forEach((column, index) => {
if (index === 0) {
sums[index] = "科目人数汇总";
return;
}
const values = data.map((item) => {
const sameObj = item.options.find(
(val) => val.label === columns[index].label
);
return sameObj ? Number(sameObj.num) : 0;
});
if (
!values.every((value) => isNaN(value)) &&
column.property !== "sum"
) {
sums[index] = values.reduce((prev, curr) => {
const value = Number(curr);
if (!isNaN(value)) {
return prev + curr;
} else {
return prev;
}
}, 0);
} else {
sums[index] = "";
}
});
// 如果需要对末项进行求和,需要单独处理,否则可忽略这段。
let init = 0
for (let i = 0; i < sums.length; i++) {
if (typeof sums[i] === 'number') {
init += sums[i]
}
}
sums[sums.length - 1] = init
return sums;
}
大概就是这样,这些数据格式可以根据需要自行调整啦~