浪迹天涯king教你用elementui做复杂的表格,去处理报表数据(合并表头,合并表体行和列)

815 阅读3分钟

1、不用多说了,先上图片

1.png

2、功能特性

1.表头的背景色,标题的虚线边框
2.表头的个别单元格样式
3. 表头合并行功能
4. 复杂的动态表头功能
5. 表体渲染下标从第n行开始
6. 表体第一行,第二行的1,2,3列合并
7. 表体第一行,第二行的,“达成”,“环比”,“排名”合并
8. 表体的个别单元格样式

3、代码(直接复制粘贴看效果)

<template>
	<div class="changeElBoCoSt kingChangeHead">
		<el-table
			:data="tableData"
			style="width: 100%"
			:span-method="objectSpanMethod"
			:row-class-name="rowClassName"
			:cell-class-name="cellClassNameKing"
			:header-cell-class-name="headerCellClassNameKing"
			:header-cell-style="headerCellStyleNameKing"
		>
			<el-table-column label="7月-罗湖东子公司各项质量达成汇总" align="center">
				<el-table-column :index="kingIndex" type="index" label="序号" align="center"></el-table-column>
				<el-table-column label="类型" width="120" align="center">
					<template slot-scope="scope">
						<span v-if="scope.$index == 0" style="font-weight: bold;">
							各区排名
							<span style="color: blue;">第一</span>
							项目个数
						</span>
						<span v-else>{{ scope.row.type }}</span>
					</template>
				</el-table-column>
				<el-table-column prop="project" label="项目" width="120" align="center"></el-table-column>
				<el-table-column v-for="(value1, key, index) in tableData[0]['daySale']" :key="index + 'day'" :label="key" align="center">
					<el-table-column v-for="(value2, key2, index2) in value1" :key="index2" :label="key2" align="center">
						<el-table-column v-for="(item1, index1) in value2" :key="index1" :label="item1.name" align="center">
							<template slot-scope="scope">
								<span :style="{
															color:
																scope.row.daySale[key][key2][index1]['isColor'] == 1
																	? 'blue'
																	: scope.row.daySale[key][key2][index1]['isColor'] == 2
																	? 'red'
																	: '',
															fontWeight:
																scope.row.daySale[key][key2][index1]['isColor'] == 1 || scope.row.daySale[key][key2][index1]['isColor'] == 2 ? 'bold' : ''
														}">{{ scope.row.daySale[key][key2][index1]['value'] }}</span>
							</template>
						</el-table-column>
					</el-table-column>
				</el-table-column>
			</el-table-column>
		</el-table>
	</div>
</template>

<script>
export default {
	data() {
		return {
			tableData: [
				{
					type: '各区排名第一项目个数',
					project: '各区排名第一项目个数',
					daySale: {
						'7月': {
							整体: [
								{
									name: '整体',
									value: 0.32,
									isColor:null,
								}
							],
							宝安: [
								{
									name: '达成',
									value: 0.33,
									isColor:null,
								},
								{
									name: '环比',
									value: 0.33,
									isColor:null,
								},
								{
									name: '排名',
									value: 0.33,
									isColor:null,
								}
							],
							龙岗: [
								{
									name: '达成',
									value: 0.331,
									isColor:null,
								},
								{
									name: '环比',
									value: 0.341,
									isColor:null,
								},
								{
									name: '排名',
									value: 0.351,
									isColor:null,
								}
							]
						},
						'第一周(7月1日-6日)': {
							整体: [
								{
									name: '整体',
									value: 0.322,
									isColor:null,
								}
							],
							宝安: [
								{
									name: '达成',
									value: 0.332,
									isColor:null,
								},
								{
									name: '环比',
									value: 0.342,
									isColor:null,
								},
								{
									name: '排名',
									value: 0.352,
									isColor:null,
								}
							],
							龙岗: [
								{
									name: '达成',
									value: 0.332,
									isColor:null,
								},
								{
									name: '环比',
									value: 0.342,
									isColor:null,
								},
								{
									name: '排名',
									value: 0.352,
									isColor:null,
								}
							]
						}
					}
				},
				{
					type: '各区排名最后项目个数',
					project: '各区排名最后项目个数',
					daySale: {
						'7月': {
							整体: [
								{
									name: '整体',
									value: 0.32,
									isColor:1,
								}
							],
							宝安: [
								{
									name: '达成',
									value: 0.33,
									isColor:null,
								},
								{
									name: '环比',
									value: 0.34,
									isColor:2,
								},
								{
									name: '排名',
									value: 0.35,
									isColor:null,
								}
							],
							龙岗: [
								{
									name: '达成',
									value: 0.331,
									isColor:null,
								},
								{
									name: '环比',
									value: 0.341,
									isColor:null,
								},
								{
									name: '排名',
									value: 0.351,
									isColor:null,
								}
							]
						},
						'第一周(7月1日-6日)': {
							整体: [
								{
									name: '整体',
									value: 0.322,
									isColor:null,
								}
							],
							宝安: [
								{
									name: '达成',
									value: 0.332,
									isColor:null,
								},
								{
									name: '环比',
									value: 0.342,
									isColor:null,
								},
								{
									name: '排名',
									value: 0.352,
									isColor:null,
								}
							],
							龙岗: [
								{
									name: '达成',
									value: 0.332,
									isColor:null,
								},
								{
									name: '环比',
									value: 0.342,
									isColor:null,
								},
								{
									name: '排名',
									value: 0.352,
									isColor:null,
								}
							]
						}
					}
				},
				{
					type: '收件1',
					project: '收件滞留率1',
					daySale: {
						'7月': {
							整体: [
								{
									name: '整体',
									value: 0.328,
									isColor:null,
								}
							],
							宝安: [
								{
									name: '达成',
									value: 0.338,
									isColor:null,
								},
								{
									name: '环比',
									value: 0.348,
									isColor:null,
								},
								{
									name: '排名',
									value: 0.358,
									isColor:null,
								}
							],
							龙岗: [
								{
									name: '达成',
									value: 0.3318,
									isColor:null,
								},
								{
									name: '环比',
									value: 0.3418,
									isColor:null,
								},
								{
									name: '排名',
									value: 0.3518,
									isColor:null,
								}
							]
						},
						'第一周(7月1日-6日)': {
							整体: [
								{
									name: '整体',
									value: 0.3229,
									isColor:null,
								}
							],
							宝安: [
								{
									name: '达成',
									value: 0.3329,
									isColor:null,
								},
								{
									name: '环比',
									value: 0.3429,
									isColor:null,
								},
								{
									name: '排名',
									value: 0.3529,
									isColor:null,
								}
							],
							龙岗: [
								{
									name: '达成',
									value: 0.3329,
									isColor:null,
								},
								{
									name: '环比',
									value: 0.3429,
									isColor:null,
								},
								{
									name: '排名',
									value: 0.3529,
									isColor:null,
								}
							]
						}
					}
				}
			],
			selectData: [],

			// 统计合并多少行
			needMergeArr: ['type'], // 有合并项的列
			rowMergeArrs: {} // 包含需要一个或多个合并项信息的对象
		};
	},
	mounted() {
		this.getList();
	},

	updated() {
		this.$nextTick(() => {
			if (this.$refs.mutipleTable !== undefined) {
				this.$refs.mutipleTable.doLayout();
			}
		});
	},
	methods: {
		/**
		 * @description 实现合并行或列
		 * @param row:Object 需要合并的列name 如:'name' 'id'
		 * @param column:Object 当前行的行数,由合并函数传入
		 * @param rowIndex:Number 当前列的数据,由合并函数传入
		 * @param columnIndex:Number 当前列的数据,由合并函数传入
		 *
		 * @return 函数可以返回一个包含两个元素的数组,第一个元素代表rowspan,
		 * 第二个元素代表colspan。 也可以返回一个键名为rowspan和colspan的对象
		 */
		objectSpanMethod({ row, column, rowIndex, columnIndex }) {
			// 第一行的达成,环比,排名,列合并
			if (rowIndex === 0) {
				if (column.label == '达成') {
					return [1, 3];
				} else if (column.label == '环比') {
					return [0, 0];
				} else if (column.label == '排名') {
					return [0, 0];
				}
			}
			// 第一,第二行的1,2,3列合并
			if (rowIndex === 0 || rowIndex === 1) {
				if (columnIndex === 0) {
					return [0, 0];
				} else if (columnIndex === 1) {
					return [1, 3];
				} else if (columnIndex === 2) {
					return [0, 0];
				}
			}
			// 方法二:(合并行)
			for (let key in this.rowMergeArrs) {
				if (column.property == key) {
					let _row = this.rowMergeArrs[key].rowArr[rowIndex];
					let _col = _row > 0 ? 1 : 0;
					return [_row, _col];
				}
			}
		},
		// 用来合并表头的(label为“整体”的上下两行合并)
		headerCellStyleNameKing({ row, column, rowIndex, columnIndex }) {
			if(rowIndex === 0){
				this.$nextTick(() => {
					if ($('.'+column.id).length !== 0) {
						$('.'+column.id+' .cell').css({'color':'#111','font-weight': 'bold'}); 
					}
				});
				return column;
			}
			else if (rowIndex === 2) {
				if (column.label == '整体') {
					this.$nextTick(() => {
						if ($('.'+column.id).length !== 0) {
							$('.'+column.id+' .cell').css({'color':'#111','font-weight': 'bold'});
							$('.'+column.id).attr('rowspan', 2);
							// var _c = document.getElementsByClassName(column.id);
							// document.getElementsByClassName(column.id)[0].setAttribute('rowSpan', 2);
						}
					});
					return column;
				}
			} else if (rowIndex === 3) {
				if (column.label == '整体') {
					return { display: 'none' };
				}
			}
		},
		// 解决下标从第二行开始,(数字要从1开始)
		kingIndex(index) {
			if (index != 0 || index != 1) {
				return index - 1;
			}
		},
		// 解决表头的双下划线
		headerCellClassNameKing({ row, column, rowIndex, columnIndex }) {
			if (columnIndex == 6) {
				return 'kingRowIndex1';
			}
		},
		cellClassNameKing({ row, column, rowIndex, columnIndex }) {
			if (columnIndex == 6) {
				return 'kingRowIndex1';
			}
		},
		// 给行添加类名(用于单元格的下划线问题)
		rowClassName({ row, rowIndex }) {
			if (rowIndex == this.kingRowIndex - 1) {
				return 'kingRowIndex';
			}
		},/*
		date: 2021-05-10
		author: @拿菜刀砍电线
		* @description 根据数组将指定对象转化为相应的数组
		* @param arr:Array[String] 必填 必须是字符串形式的数组
		* @param data:Array 必填 需要转化的对象
		*/
                 rowMergeHandle(arr, data) {
                    if (!Array.isArray(arr) && !arr.length) return false
                    if (!Array.isArray(data) && !data.length) return false
                    const needMerge = {}
                    arr.forEach(i => {
                        needMerge[i] = {
                            rowArr: [],
                            rowMergeNum: 0
                        }
                        data.forEach((item, index) => {
                            if (index === 0) {
                                needMerge[i].rowArr.push(1)
                                needMerge[i].rowMergeNum = 0
                            } else {
                                if (item[i] === data[index - 1][i]) {
                                    needMerge[i].rowArr[needMerge[i].rowMergeNum] += 1
                                    needMerge[i].rowArr.push(0)
                                } else {
                                    needMerge[i].rowArr.push(1)
                                    needMerge[i].rowMergeNum = index
                                }
                            }
                        })
                    })
                    // console.log(needMerge);
                    return needMerge
                },
		getList() {
			// 实线加粗
			this.kingRowIndex = 1;
			// 处理数据
			this.rowMergeArrs = this.rowMergeHandle(this.needMergeArr, this.tableData);
		}
	}
};
</script>
<style lang="scss">
.changeElBoCoSt {
	.el-table__header {
		// border-right: 1px solid #000;
		border-top: 1px solid #000;
		border-left: 1px solid #000;
	}
	.el-table__body {
		// border-right: 1px solid #000;
		// border-bottom: 1px solid #000;
		border-left: 1px dashed #000;
	}

	.el-table--border td {
		border-right: 1px dashed #000;
	}
	.el-table--border th {
		border-right: 1px solid #000;
	}
	.el-table__body-wrapper .el-table--border.is-scrolling-left ~ .el-table__fixed {
		border-right: 1px dashed #000;
	}

	.el-table--border th {
		border-bottom: 1px solid #000;
	}

	.el-table__fixed-right-patch {
		border-bottom: 1px dashed #000;
	}

	.el-table td {
		border-bottom: 1px dashed #000;
	}
	.el-table th.is-leaf {
		border-bottom: 1px solid #000;
	}

	.el-table__header tr,
	.el-table__header th {
		background-color: #ffc000 !important;
	}
	// // body的每一行的最后一个单元格
	// .el-table__body tr td:last-child {
	// 	border-right: 1px solid #000;
	// }
	// // body的最后一行
	// .el-table__body tr:last-child td {
	// 	border-bottom: 1px solid #000;
	// }
	// //(刚好最后两行的第一列有合并才要这个)
	// .el-table__body tr:first-child td:first-child {
	// 	border-bottom: 1px solid #000;
	// }

	// 双下划线(表体)
	// .kingRowIndex td {
	//     border-bottom: 2px solid #000000 !important;
	// }
	// 表头
	// .kingRowIndex1 {
	// 	 border-right: 2px solid #000000 !important;
	// }
}
</style>