【需求】
三级嵌套的json数据 :班级嵌套学生,学生中嵌套全部时间的考试成绩, 自动生成表格并合并单元格,如图
【原理】
将三级嵌套的数据扁平化成为一级,再根据主合并的字段,判断相同即记录合并的行数,
【json数据】
[{
className: '高一三班',
studentList:[
{
name: '张三',
age: 18,
achievement:[
{
time:'7年级-期中',
yu:'80',
shu:'90',
ying:'100'
},
...
]
}
...
],
jigelv:'80%',
gaofenlv:'30%'
}
...
]
【代码】
<template>
<div style="padding: 20px;">
<el-table :data="buildData" style="width: 100%;" :span-method="objectSpanMethod" border>
<!--遍历表-->
<el-table-column
:prop="item.prop"
:label="item.label"
v-for="(item, index) in tableHeader"
:key="index"
></el-table-column>
<!-- <el-table-column label="班级" align="center" prop="className" />
<el-table-column label="姓名" align="center" prop="name" />
<el-table-column label="年龄" align="center" prop="age" /> -->
</el-table>
</div>
</template>
<script>
const datas = [{
className: '高一三班',
studentList:[
{
name: '张三',
age: 18,
achievement:[
{
time:'7年级-期中',
yu:'80',
shu:'90',
ying:'100'
},
{
time:'7年级-期末',
yu:'82',
shu:'91',
ying:'103'
},
]
},
{
name: '李四',
age: 19,
achievement:[
{
time:'7年级-期中',
yu:'80',
shu:'90',
ying:'100'
},
{
time:'7年级-期末',
yu:'82',
shu:'91',
ying:'103'
},
]
},
],
jigelv:'80%',
gaofenlv:'30%'
},
{
className: '高一五班',
studentList:[
{
name: '张其',
age: 18,
achievement:[
{
time:'7年级-期中',
yu:'80',
shu:'90',
ying:'100'
},
{
time:'7年级-期末',
yu:'82',
shu:'91',
ying:'103'
},
]
},
{
name: '王芳',
age: 19,
achievement:[
{
time:'7年级-期中',
yu:'80',
shu:'90',
ying:'100'
},
{
time:'7年级-期末',
yu:'82',
shu:'91',
ying:'103'
},
]
},
],
jigelv:'70%',
gaofenlv:'20%'
},
{
className: '高一六班',
studentList:[
{
name: '张其',
age: 18,
achievement:[
{
time:'7年级-期中',
yu:'80',
shu:'90',
ying:'100'
},
{
time:'7年级-期末',
yu:'82',
shu:'91',
ying:'103'
},
]
},
{
name: '王芳',
age: 19,
achievement:[
{
time:'7年级-期中',
yu:'80',
shu:'90',
ying:'100'
},
{
time:'7年级-期末',
yu:'82',
shu:'91',
ying:'103'
},
{
time:'8年级-期中',
yu:'80',
shu:'90',
ying:'100'
},
{
time:'8年级-期末',
yu:'82',
shu:'91',
ying:'103'
},
]
},
],
jigelv:'50%',
gaofenlv:'10%'
},
]
export default {
name: "MultiRowMergeTable",
data() {
this.spanMap = {};
this.mergedColumns = ["className","name","age"]
this.mergedMainColumns = ["jigelv","gaofenlv"]
return {
tableHeader: [{
prop: "className",
label: "班级",
},
{
prop: "name",
label: "姓名",
},
{
prop: "age",
label: "年龄",
},
{
prop: "time",
label: "考试时间",
},
{
prop: "yu",
label: "语文",
},
{
prop: "shu",
label: "数学",
},
{
prop: "ying",
label: "英语",
},
{
prop: "jigelv",
label: "及格率"
},
{
prop: "gaofenlv",
label: "高分率"
},
],
tableData: [],
}
},
created() {
this.getList(); //进入页面时调用getList()获取tableData[]数据
},
computed:{
buildData(){
let data=this.tableData
if(!data) return
let datas = this.flattenArray(data)
console.log(datas)
this.getSpanArr(datas, this.mergedColumns)
return datas
}
},
methods: {
//具体获取数据方法因需求而异
getList() {
// listExamineTableData(this.queryParams).then(response => {
// this.tableData = response.data;
// this.getSpanArr(this.tableData);
// });
this.tableData = datas;
// console.log(this.tableData)
},
flattenArray(arr) {
let result=[]
let id=''
arr.forEach((obj,xh)=>{
let one=xh.toString()
const { studentList: child, ...otherProps } = obj;
if(child && child.length>0){
child.forEach((item,index)=>{
let two=index.toString()
const {achievement: childTwo, ...otherItem} = item
if(childTwo && childTwo.length>0){
childTwo.forEach((third,thirdIndex)=>{
let three=thirdIndex.toString()
id=one+'-'+two+'-'+three
result.push({id, ...otherProps, ...third, ...otherItem});
})
}else{
id=one+'-'+two
result.push({id, ...otherProps, ...otherItem});
}
})
}else{
id=one
result.push({id,...otherProps})
}
})
// console.log(result)
return result;
},
getSpanArr(data) {
for (var i = 0; i < data.length; i++) {
if (i === 0) {
this.mergedColumns.forEach(column => {
this.spanMap[column] = {
spanArr: [1],
pos: 0,
// index:i
}
})
} else {
this.mergedColumns.forEach(column => {
if (data[i][column] === data[i - 1][column]) {
this.spanMap[column].spanArr[this.spanMap[column].pos] += 1;
this.spanMap[column].spanArr.push(0)
} else {
this.spanMap[column].spanArr.push(1);
this.spanMap[column].pos = i;
}
// this.spanMap[column].index=i
})
}
// console.log(this.spanMap)
}
this.mergedMainColumns.forEach(column => {
this.spanMap[column] = this.spanMap["className"]
})
},
objectSpanMethod({
column,
rowIndex
}) {
if (this.spanMap[column.property]) {
const _row = this.spanMap[column.property].spanArr[rowIndex];
const _col = _row > 0 ? 1 : 0;
return {
rowspan: _row,
colspan: _col
}
}
}
}
}
</script>
<style>
</style>