表格多列合并
要实现的效果 :
实现步骤解析:
- 通过第一列型别等级判断, 将序号列和第一列内容一致的分别合并
- 过滤数据, 将每一个型别等级的数据存放到一个数组, 使各个型别等级之间合并时不互相影响
- 通过第二列注册分公司判断, 将此列内容一致的合并
- 再次过滤, 在同一个型别等级的基础上将每一个注册分公司的数据存放到一个数组, 使各个注册分公司之间合并时不互相影响
- 同一个型别等级, 同一个注册分公司下, 通过第三列运行分公司判断, 将此列内容一致的合并(正常不会出现一致的, 若三者都一样则是一条数据, 此处只为展示过程)
- 到此图片上合并结束
具体实现过程:
1、template 此处 sino-table 为封装 element-ui table 后的版本,具体属性可参照 element-ui
<template>
<div>
<sino-table
:data="statisticData"
:span-method="cellMerge"
border
:height="500"
:cell-style="columnStyle"
:header-cell-style="{backgroundColor:'#FAFCFF'}"
@cell-click='goDetil'
style="width: 100%; margin-top: 20px">
<sino-table-column width="60" prop="indexSpan" label="序号" align="center"></sino-table-column>
<sino-table-column width="120" prop="typeGrade" label="现飞型别等级" align="center"></sino-table-column>
<sino-table-column width="150" prop="corpName" label="注册分公司" align="center"></sino-table-column>
<sino-table-column width="150" prop="flyCorpName" label="运行分公司" align="center"></sino-table-column>
<sino-table-column width="120" align="center" prop="SUM" label="带飞总人数" show-overflow-tooltip>
<template scope="scope">
<span class="count-num">{ { scope.row.SUM}}</span>
</template>
</sino-table-column>
<sino-table-column width="80" align="center" prop="F1" label="F1" show-overflow-tooltip>
<template scope="scope">
<span class="count-num">{ { scope.row['F1']}}</span>
</template>
</sino-table-column>
<sino-table-column width="80" align="center" prop="F2" label="F2" show-overflow-tooltip>
<template scope="scope">
<span class="count-num">{ { scope.row['F2']}}</span>
</template>
</sino-table-column>
</sino-table>
</div>
</template>
2、script
<script>
export default {
data () {
return {
// 以假数据为例, 也可请求接口获取
statisticData: [
{
typeGrade: "A-320",
typeGradeName: "A-320",
corpId: 74,
corpName: "飞行总队",
countMap: { F1: "2", F2: "0", SUM: "3"},
flyCorpId: 4,
flyCorpName: "西南分公司"
},
{
typeGrade: "A-320",
typeGradeName: "A-320",
corpId: 74,
corpName: "飞行总队",
countMap: { F1: "0", F2: "0", SUM: "1"},
flyCorpId: 5,
flyCorpName: "浙江分公司"
},
{
typeGrade: "A-320",
typeGradeName: "A-320",
corpId: 4,
corpName: "上海分公司",
countMap: { F1: "0", F2: "0", SUM: "1"},
flyCorpId: 5,
flyCorpName: "浙江分公司"
},
{
typeGrade: "A-320",
typeGradeName: "A-320",
corpId: 4,
corpName: "上海分公司",
countMap: { F1: "0", F2: "0", SUM: "1"},
flyCorpId: 5,
flyCorpName: "浙江分公司"
},
{
typeGrade: "A-330",
typeGradeName: "A-330",
corpId: 5,
corpName: "浙江分公司",
flyCorpId: 4,
flyCorpName: "西南分公司",
countMap: { F1: "0", F2: "0", SUM: "1"}
},
{
typeGrade: "A-330",
typeGradeName: "A-330",
corpId: 74,
corpName: "飞行总队",
countMap: { F1: "1", F2: "0", SUM: "2"},
flyCorpId: 4,
flyCorpName: "西南分公司"
}
]
}
},
mounted () {
this.init();
},
methods: {
init () {
let data = [];
this.statisticData.map((item, index) => {
// 处理数据,使countMap(SUM F1 F2)内容渲染到列表
data.push({
index,
...item,
...item.countMap
});
});
// 合并typeGrade(第一列型别等级)内容一致的
this.statisticData = this.mergeTableRow(data, ['index', 'typeGrade']);
let typeArr = [];
let corpArr = [];
// 将第一列内容存放数组且去重
this.statisticData.map(item => {
typeArr.push(item.typeGrade);
});
typeArr = Array.from(new Set(typeArr));
// 循环表格数据
this.statisticData.map(item => {
// 循环第一列内容存放数组
typeArr.map(it => {
// 过滤出每一大行的数据,使每行之后的数据不会互相影响
let a = this.statisticData.filter(item => {
return item.typeGrade == it;
});
// 合并每大行corpName(第二列)内容一致的
this.mergeTableRow(a, ['index', 'corpName']);
// 继续之前的操作,基于a数组(每一大行的数据)对第三列进行判断合并,若有多列需要合并可一直执行下去,不建议过多以防性能不好
// 将第二列内容存放数组且去重
a.map(item => {
corpArr.push(item.corpId);
});
corpArr = Array.from(new Set(corpArr));
// 循环表格每一大行数据
a.map(item => {
// 循环第二列内容存放数组
corpArr.map(it => {
// 过滤出每一小行的数据
let b = a.filter(item => {
return item.corpId == it;
});
// 合并每小行flyCorpName(第三列)内容一致的
this.mergeTableRow(b, ['index', 'flyCorpName']);
});
});
});
});
},
// 合并内容相等的某一列(传入的merge)
mergeTableRow (data, merge) {
if (!merge || merge.length === 0) {
return data;
}
merge.forEach((m) => {
const mList = { };
data = data.map((v, index) => {
const rowVal = v[m];
if (mList[rowVal]) {
mList[rowVal]++;
data[index - (mList[rowVal] - 1)][m + '-span'].rowspan++;
v[m + '-span'] = {
rowspan: 0,
colspan: 0
};
} else {
mList[rowVal] = 1;
v[m + '-span'] = {
rowspan: 1,
colspan: 1
};
}
return v;
});
});
return data;
},
// 点击单元格
goDetil (row, col, cell) {
if (row[col['property']]) {
let query = {
'column': col['property']
};
this.$emit('transmit', query); // 传递给父组件参数
};
},
// 合并行或列
cellMerge ({ row, column, rowIndex, columnIndex }) {
if (columnIndex == 0) {
let _row = this.indexFilter(this.statisticData, 'typeGrade')[rowIndex];
let _col = _row > 0 ? 1 : 0;
const arr = this.indexFilter(this.statisticData, 'typeGrade');
var Nosort = 0;
for (let i in arr) {
if (arr[i] > 0) {
Nosort += 1;
};
for (let j in this.statisticData) {
if (i == j) {
// indexSpan 为表格序号列
this.statisticData[i].indexSpan= Nosort;
this.statisticData[i].indexSpan == 0 ? this.statisticData[i].indexSpan= null : this.statisticData[i].indexSpan= Nosort; // 去掉序号0
}
};
};
return [_row, _col];
};
const span = column['property'] + '-span';
if (row[span]) {
return row[span];
}
},
// 通过传入的type(除序号第一列)使序号列进行合并
indexFilter (arr, type) {
var spanOneArr = [];
var concatone = 0;
arr.forEach((item, index) => {
if (index == 0) {
spanOneArr.push(1);
} else {
if (item[type] == arr[index - 1][type]) {
spanOneArr[concatone] += 1;
spanOneArr.push(0);
} else {
spanOneArr.push(1);
concatone = index;
}
}
});
return spanOneArr;
},
columnStyle ({ row, column, rowIndex, columnIndex }) {
if (columnIndex === 0) { // 第1列的背景色就改变了
return 'background:rgb(250, 252, 255);';
}
}
}
};
</script>
还没有评论,来说两句吧...