el-table 多级表头拖拽


场景

业务需求做多级表头拖拽,具体要求如下:
没有子表头的父表头不可拖拽,第一个序号不可拖拽,父表头拖拽换位,同一个父表头下的子表头拖拽时 子表头换位,不同父表头下子表头拖拽时子表头不变两个父表头换位。

一、代码

1.页面部分

我这里是多级表头的数据表格。使用了Element UI库来构建表格组件,并结合了sortable.js插件来实现表格列的拖拽排序功能。
在模板部分,使用了<el-table>组件来展示表格数据,通过v-for指令循环渲染表头列和子列。每一列都设置了相应的属性,如label、align、sortable等,在表格中显示对应的数据页面代码如下:

<template>
	<el-table :data="tableData" tooltip-effect="dark" class="financeTotalTwo financeTotal_spfcjhz"
		style="width: 100%" height="100%" :size="GLOBAL.tableSize" ref="multipleTable">
		<el-table-column type="index" width="80" label="序号" align="center"></el-table-column>
		<el-table-column
			v-for="(item, index) in titleList"
			v-if="item.show"
			:label="item.label"
			:align="item.align"
			:sortable="item.sortable"
			:prop="item.prop"
			:min-width="item.width"
			:class-name="(item.prop == 'cityName' ||item.prop == 'tjDate' || item.prop == 'whHouseUseName' ||item.prop == 'blockName' || item.prop =='districtName' ) ? 'disableDrag':'allowDrag'"
			:key="item.prop + index"
			class="allowDrag"
			>
			<template slot-scope="scope">
				<div>{{ scope.row[item.prop] }}</div>
			</template>
			<el-table-column
				v-for="(zitem, zindex) in item.children"
				v-if="zitem.show && item.children.length >0"
				:label="zitem.label"
				:align="zitem.align"
				:sortable="zitem.sortable"
				:prop="zitem.prop"
				:min-width="zitem.width"
				class-name="zallowDrag"
				:class="'draggable'"
				:key="zitem.prop + zindex"
				>
				<template slot-scope="scope">
					<div class="finance_table_alignRight">{{ scope.row[zitem.prop] }}</div>
				</template>
			</el-table-column>
		</el-table-column>
	</el-table>
</template>

2.表格数据及拖拽处理部分

在脚本部分,定义了组件的数据对象,包括tableHeaderList、titleList和tableData。tableHeaderList用来存储表头的配置信息,titleList根据tableHeaderList筛选出有效的表头信息,tableData则是实际要展示的表格数据。
在组件的生命周期钩子函数中,调用了loadTitleList方法来初始化有效的表头列表,并通过setTimeout延迟执行columnDrop方法来初始化表格列的拖拽功能。
loadTitleList方法遍历tableHeaderList,根据show属性判断表头是否有效,若有效则将其添加到titleList中。
columnDrop方法初始化了表格列的拖拽功能,分别对父表头列和子表头列进行了绑定。在拖拽结束时,根据拖拽的起始索引和结束索引,对titleList进行相应的操作,包括表头交换和子表头交换:

<script>
	import Sortable from 'sortablejs';
	import { moveArr, strMapToObj} from './utils/utils'
	export default {
		name: "landSj",
		components: {
		},
		data() {
			return {
				tableHeaderList: [
					// 多级表头数据
					{
						"id":4,
						"show":true,
						"prop":"tjDate",
						"label":"时间",
						"width":130,
						"sortable":false,
						"children":[
									
						],
						"align":"center",
						"width":130,
						"template":true
					},
					{
						"id":5,
						"show":true,
						"label":"供应信息",
						"prop":'gy',
						"sortable":false,
						"children":[
							{
								"id":6,
								"show":true,
								"prop":"gyts",
								"label":"供应套数",
								"sortable":"gyts",
								"align":"center",
								"width":130,
								"template":true
							},
							{
								"id":7,
								"show":true,
								"prop":"gymj",
								"label":"供应面积(㎡)",
								"sortable":"gymj",
								"align":"center",
								"width":130,
								"template":true
							}
						],
						"align":"center",
						"width":130,
						"template":true
					},
					{
						"id":11,
						"show":true,
						"label":"预测成交信息",
						"sortable":false,
						"prop":'yccj',
						"children":[
							{
								"id":12,
								"show":true,
								"prop":"ysts",
								"label":"预测成交套数",
								"sortable":"ysts",
								"align":"center",
								"width":130,
								"template":true
							},
							{
								"id":13,
								"show":true,
								"prop":"ysmj",
								"label":"预测面积(㎡)",
								"sortable":"ysmj",
								"align":"center",
								"width":130,
								"template":true
							},
							{
								"id":14,
								"show":true,
								"prop":"yszj",
								"label":"预测成交金额(万元)",
								"sortable":"yszj",
								"align":"center",
								"width":130,
								"template":true
							},
							{
								"id":15,
								"show":true,
								"prop":"ysjj",
								"label":"预测成交均价",
								"sortable":"ysjj",
								"align":"center",
								"width":130,
								"template":true
							}
						],
						"align":"center",
						"width":130,
						"template":true
					},
					{
						"id":21,
						"show":true,
						"label":"存量信息",
						"sortable":false,
						"prop":'cl',
						"children":[
							{
								"id":22,
								"show":true,
								"prop":"clts",
								"label":"存量套数",
								"sortable":"clts",
								"align":"center",
								"width":130,
								"template":true
							},
							{
								"id":23,
								"show":true,
								"prop":"clmj",
								"label":"存量面积(㎡)",
								"sortable":"clmj",
								"align":"center",
								"width":130,
								"template":true
							},
							{
								"id":24,
								"show":true,
								"prop":"xzxclts",
								"label":"限制性套数",
								"sortable":"xzxclts",
								"align":"center",
								"width":130,
								"template":true
							},
							{
								"id":25,
								"show":true,
								"prop":"xzxclmj",
								"label":"限制性面积(㎡)",
								"sortable":"xzxclmj",
								"align":"center",
								"width":130,
								"template":true
							}
						],
						"align":"center",
						"width":130,
						"template":true
					}
				  ],
				  titleList:[],
				  tableData:[
						{
							"cityId": null,
							"cityName": null,
							"districtId": null,
							"districtName": null,
							"blockId": null,
							"blockName": null,
							"tjDate": "2023-01-01-2023-10-26",
							"gyts": "30119",
							"gymj": "4027187.55",
							"qngyts": null,
							"qngymj": null,
							"ysts": "60022",
							"ysmj": "7741787.72",
							"yszj": "25548525",
							"ysjj": "33001",
							"qnysts": null,
							"qnysmj": null,
							"qnyszj": null,
							"qnysjj": null,
							"clts": "0",
							"clmj": "0.00",
							"xzxclts": "0",
							"xzxclmj": "0.00"
						}
					]
			};
		},
		created() {
		},
		mounted() {
			this.loadTitleList();
			setTimeout(() => {
				this.columnDrop();
			}, 100);
		},
		beforeUpdate(){
		  this.$nextTick(() => { //在数据加载完,重新渲染表格
			if(this.$refs['multipleTable']){
			  this.$refs['multipleTable'].doLayout();
			}
		  })
		},
		methods: {
			/**
			 * 获取有效的表格
			 */
			loadTitleList(){
				  this.titleList = []
				  // 制造数据
				  for(var i = 0;i < this.tableHeaderList.length;i++){
					if(this.tableHeaderList[i].show){
						this.titleList.push(this.tableHeaderList[i]);
					}
				  };
			},
			//表格列拖拽
			columnDrop() {
				//父表头列拖拽
				const wrapperTr = document.querySelector('.el-table__header-wrapper tr')
				this.sortable = Sortable.create(wrapperTr, {
					handle:".allowDrag",
					animation: 180,
					delay: 0,
					 filter: function (evt) {
					    const element = evt.target;
					    // 判断元素是否具有 allowDrag 类名,如果有则可拖拽
					    return element.classList.contains('allowDrag');
					  },
					onEnd: evt => {
						if (evt.oldIndex === evt.newIndex) return;
						//表头排序,第一列为序号,第二列是时间 ,因为 需求要求序号跟时间咧不参与拖拽 因此减1
						moveArr(this.titleList, evt.newIndex -1, evt.oldIndex -1)
					},
					onMove(e) {
						return e.related.className.indexOf('allowDrag') > 1;
					}
				})
				//子表头列拖拽
				const wrapperTrx = document.querySelector('.el-table__header-wrapper tr+tr')
				this.sortablex = Sortable.create(wrapperTrx, {
					handle:".zallowDrag",
				    animation: 180,
				    delay: 0,
				    onEnd: evt => {
						 if (evt.oldIndex === evt.newIndex) return;
							// 计算子表头的起始索引和结束索引
							let startIndex = 0;
							for (let i = 1; i < this.titleList.length; i++) {
							  const childrenLength = this.titleList[i].children.length;
							  if (startIndex <= evt.oldIndex && evt.oldIndex < startIndex + childrenLength) {
								const adjustedOldIndex = evt.oldIndex - startIndex;
								const adjustedNewIndex = evt.newIndex - startIndex;
								if (adjustedNewIndex >= childrenLength) {
								  // 超出当前拖拽父表头长度,不进行子表头操作 直接操作父表头交换操作
								  moveArr(this.titleList, i, i+1)
								  break; 
								}
								  // 判断是否在同一个子表头的children下切换
								if (adjustedOldIndex >= 0 && adjustedOldIndex < childrenLength && adjustedNewIndex >= 0 && adjustedNewIndex < childrenLength) {
									//'同一个父表头 子表头交换操作
								   moveArr(this.titleList[i].children, adjustedNewIndex, adjustedOldIndex);
								   break;
								}else{
								  //非同一个父表头 只进行父表头操作
								  moveArr(this.titleList, i, i-1)
								   break;
								}
							  }
							  startIndex += childrenLength;
							}
							
					},
						onMove(e) {
							return e.related.className.indexOf('allowDrag') > 1;
						}
					})
			},
		}
	};
</script>
 moveArr(arr, newIndex, oldIndex) {
    arr.splice(newIndex, 0, arr.splice(oldIndex, 1)[0])
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值