太坑了,百度了所有都找不到的答案,elementui的table的多级表头固定前n列的问题

2,241 阅读3分钟

废话不多说,先看效果如下,我固定的是前三列,复杂表头渲染,是我前一章节说的 复杂表头固定前n列

Snipaste_2021-08-17_11-01-35.png

1、elementui的table的多级表头固定前n列(注意:n列是根据width来固定的)的问题所在

1.1 发现给了el-column固定宽度,和fixed属性后,其他没有这两个属性的el-column部分被加上了is-hidden的类名(这个要浏览器控制台查看html结构代码才知道),导致页面渲染的数据被隐藏了,所以要想办法去掉这个类名
1.2 经过查看html结构后,使用jquery去掉is-hidden类名(没有想到更好的办法,有其他办法的大神希望能点拔我一下)

2、解决的办法:

2.1 核心代码:
this.$nextTick(() => {
					// 如果不是固定列用这个
					let myTrList = $('.kingChangeHead .el-table__header .has-gutter tr');
					// 第一行表头(表头的样式)
					let colorTr = myTrList.eq(0);
					let colorTh = colorTr.find('th').eq(0);
					$(colorTh).removeClass('is-hidden');
					$(colorTh)
						.find('.cell')
						.css({ color: '#000', 'font-size': '18px', 'font-weight': 'bold' });
					/**
					 * @Date: 2021-08-17
					 * @author @拿菜刀砍电线
					 * @Description:为了解决elementui的复杂表头,固定前三列的问题
					 * 问题分析1、发现给了固定宽度,和fixed属性后,没有固定的部分被加上了is-hidden的类名,导致页面数据被隐藏了,所以要想办法去掉这个类名
					 * 2、经过查看html结构后,使用jquery去掉is-hidden类名
					 */
					let kingBody = $('.kingChangeHead .el-table__body-wrapper .el-table__body tr');
					kingBody.each(function(index, domEle) {
						$(domEle)
							.find('td')
							.each(function(index1, domEle1) {
								$(domEle1).removeClass('is-hidden');
							});
					});
					if (this.$refs.mutipleTable !== undefined) {
						this.$refs.mutipleTable.doLayout();
					}
				});
2.2 全部代码:
<template>
	<div class="barCodeManageIndex">
		<div>
			<div class="collapseContent">
				<div id="searchForm" class="collapseCon">
					<el-form label-position="right">
						<div class="l-f">
							<el-form-item label="年份:" label-width="50px">
								<el-date-picker :clearable="false" format="yyyy" value-format="yyyy" v-model="searchForm.year" type="year" placeholder="请选择"></el-date-picker>
							</el-form-item>
							<el-form-item label="月份:" label-width="50px">
								<el-select :clearable="false" v-model.trim="searchForm.month" placeholder="请选择">
									<el-option v-for="(item, index) in monthList" :key="index" :label="item.label" :value="item.value"></el-option>
								</el-select>
							</el-form-item>
						</div>
					</el-form>
				</div>
			</div>
		</div>
		<div class="collapseContent">
			<div @click.self="show = !show" class="l-f l-flex-c collapseCon pointer">
				<i @click.self="show = !show" class="el-icon-arrow-up o-mr-40" :class="{ isRotate: !show }"></i>
				<el-button class="o-ml-12" icon="el-icon-zoom-in" v-preventReClick type="goon" size="mini" @click="searchAll">查询</el-button>
				<el-button class="o-ml-12" icon="el-icon-my-export" v-preventReClick type="success" size="mini" @click="exportFile">导出</el-button>
				<el-button class="o-ml-12 kingButton" icon="el-icon-full-screen" v-preventReClick type="success" size="mini" @click="clickFullscreen('kingFullScreen')">
					全屏显示
				</el-button>
			</div>
			<div>
				<el-collapse-transition>
					<div v-show="show">
						<div class="showToolTip changeElBoCoSt kingChangeHead">
							<el-table
								id="kingFullScreen"
								v-loading="loading"
								:cell-style="sca_CellStyle"
								border
								highlight-current-row
								:height="clientHeight"
								resizable
								:data="tableData"
								ref="mutipleTable"
								:span-method="objectSpanMethod"
								:header-cell-style="headerCellStyleNameKing"
								:row-style="selectedHighlight_custom"
							>
								<el-table-column fixed width="300" :label="subCompanyMonth + '月-五大战区各项质量汇总'" align="center">
									<el-table-column fixed :index="kingIndex" type="index" label="序号" width="60" align="center"></el-table-column>
									<el-table-column fixed prop="type" 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-if="scope.$index == 1" style="font-weight: bold;">
												各区排名
												<span style="color: red;">最后</span>
												项目个数
											</span>
											<span v-else>{{ scope.row.type }}</span>
										</template>
									</el-table-column>
									<el-table-column fixed prop="project" label="项目" width="120" align="center"></el-table-column>
									<el-table-column
										v-if="tableData && tableData.length > 0"
										v-for="(value1, key, index) in tableDataDetail"
										: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]['color'],
															fontWeight: scope.row.daySale[key][key2][index1]['fontBold']
														}"
													>
														{{ scope.row.daySale[key][key2][index1]['value'] }}
													</span>
												</template>
											</el-table-column>
										</el-table-column>
									</el-table-column>
								</el-table-column>
							</el-table>
						</div>
					</div>
				</el-collapse-transition>
			</div>
		</div>
	</div>
</template>

<script>
export default {
	name: 'brCoInAn_daRe_ovSuOfThZone',
	data() {
		return {
			// 代表的月份
			subCompanyMonth: '',
			formLabelWidth: '120px',
			searchFormLableWidth: '100px',
			// 查询参数
			searchForm: {
				month: '',
				year: null
			},
			show: true,
			tableData: [],
			// 表格高度
			clientHeight: null,
			// 统计合并多少行
			needMergeArr: ['type'], // 有合并项的列
			rowMergeArrs: {} // 包含需要一个或多个合并项信息的对象
		};
	},
	computed: {
		monthList() {
			let monthList = [];
			for (var i = 1; i < 13; i++) {
				monthList.push({
					label: `${i}月`,
					value: i
				});
			}
			return monthList;
		},
		loading() {
			return this.GetStore('globalNotice', 'kingLoading');
		},
		tableDataDetail() {
			let tableData = [];
			if (this.tableData && this.tableData.length > 0) {
				tableData = this.tableData[0]['daySale'];
			}
			return tableData;
		}
	},
	mounted() {
		this.searchForm.year = this.GetCurrentTime().orderYear;
		this.searchForm.month = Number(this.GetCurrentTime().yearMonth.substring(5, 7));
		// 自定义table的宽度,为了固定表头
		this.clientHeight = document.body.clientHeight - 230;
		const that = this;
		window.onresize = () => {
			return (() => {
				window.clientHeight = document.body.clientHeight;
				that.clientHeight = window.clientHeight - 230;
			})();
		};
	},
	updated() {
		this.$nextTick(() => {
			if (this.$refs.mutipleTable !== undefined) {
				this.$refs.mutipleTable.doLayout();
			}
		});
	},
	methods: {
		// 第一第二行背景色
		selectedHighlight_custom({ row, rowIndex }) {
			// if (rowIndex == 0 || rowIndex == 1) {
			// 	return {
			// 		'background-color': '#ddd'
			// 	};
			// }
		},
		// 点击导出按钮
		exportFile() {
			this.exportFile_king(this.$api.reBrGuAnalyAreaexportReport, this.searchForm);
		},
		/**
		 * @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 || rowIndex === 1) {
				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', 'font-size': '20px' });
							$('.' + column.id).attr('rowspan', 2);
							// var _c = document.getElementsByClassName(column.id);
							// document.getElementsByClassName(column.id)[0].setAttribute('rowSpan', 2);
						}
					});
					return column;
				} else {
					return {
						textAlign: 'center',
						color: '#111111',
						fontSize: '16px',
						fontWeight: 400
					};
				}
			} else if (rowIndex === 3) {
				if (column.label == '整体') {
					return { display: 'none' };
				} else {
					return {
						textAlign: 'center',
						color: '#111111',
						fontSize: '16px',
						fontWeight: 400
					};
				}
			} else {
				return {
					textAlign: 'center',
					color: '#111111',
					fontSize: '16px',
					fontWeight: 400
				};
			}
		},
		// 解决下标从第二行开始,(数字要从1开始)
		kingIndex(index) {
			if (index != 0 || index != 1) {
				return index - 1;
			}
		},
		searchAll() {
			this.tableData = [];
			this.getList();
		},
		getList() {
			// 因为时间是一定要的,如果用户没有选择时间,要强制
			if (!this.searchForm.year) {
				this.searchForm.year = this.GetCurrentTime().orderYear;
			}
			if (!this.searchForm.month) {
				this.searchForm.month = Number(this.GetCurrentTime().yearMonth.substring(5, 7));
			}
			// 表头数据
			this.subCompanyMonth = this.searchForm.month || '';
			this.$store.commit('Edit_loading', true);
			let param = this.searchForm;
			this.$method(this.$api.reBrGuAnalygetAreaSumReport, 'post', param).then(res => {
				if (res.data && res.data.length > 0) {
					res.data.forEach((item, index) => {
						for (let key in item.daySale) {
							for (let key1 in item.daySale[key]) {
								item.daySale[key][key1].forEach((item1, index1) => {
									// 颜色和加粗
									item1.color = null;
									item1.fontBold = null;
									// 如果有值
									if (item1.value != null) {
										// 有没有变色
										if (item1.isRanking == 1) {
											item1.color = 'blue';
											item1.fontBold = 'bold';
										} else if (item1.isRanking == 2) {
											item1.color = 'red';
											item1.fontBold = 'bold';
										}
										// 看是不是整数类型
										// 2代表为整数
										if (item1.algorithm != 2 && item1.algorithm != 4 && item1.algorithm != null) {
											item1.value = this.Big(item1.value).mul(100) + '%';
										}
									} else {
										item1.value = '-';
									}
								});
							}
						}
					});
				}
				this.tableData = res.data;
				// 处理数据
				this.rowMergeArrs = this.rowMergeHandle(this.needMergeArr, this.tableData);
				this.$nextTick(() => {
					// 如果不是固定列用这个
					let myTrList = $('.kingChangeHead .el-table__header .has-gutter tr');
					// 第一行表头(表头的样式)
					let colorTr = myTrList.eq(0);
					let colorTh = colorTr.find('th').eq(0);
					$(colorTh).removeClass('is-hidden');
					$(colorTh)
						.find('.cell')
						.css({ color: '#000', 'font-size': '18px', 'font-weight': 'bold' });
					/**
					 * @Date: 2021-08-17
					 * @author @拿菜刀砍电线
					 * @Description:为了解决elementui的复杂表头,固定前三列的问题
					 * 问题分析1、发现给了固定宽度,和fixed属性后,没有固定的部分被加上了is-hidden的类名,导致页面数据被隐藏了,所以要想办法去掉这个类名
					 * 2、经过查看html结构后,使用jquery去掉is-hidden类名
					 */
					let kingBody = $('.kingChangeHead .el-table__body-wrapper .el-table__body tr');
					kingBody.each(function(index, domEle) {
						$(domEle)
							.find('td')
							.each(function(index1, domEle1) {
								$(domEle1).removeClass('is-hidden');
							});
					});
					if (this.$refs.mutipleTable !== undefined) {
						this.$refs.mutipleTable.doLayout();
					}
				});
			});
		}
	}
};
</script>

<style lang="scss">
.changeElBoCoSt {
	.el-table .cell {
		color: #333;
	}
	.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>