如何利用穿梭框完成自定义表格表头

目录

前言:

一、封装穿梭框

二、引入穿梭框

三、自定义表头 

四、效果图


前言:

最近在项目中遇到新的需求,客户需要能够自己配置对应的表头并打印。第一想法就是利用穿梭框去完成对表头的自定义配置。但是因为element-plus中的穿梭框满足不了我想要的功能,只能去单独封装一个穿梭框。

一、封装穿梭框

穿梭框主要是为了获取到选择字段的数组,通过这个数组在表头中渲染完成自定义表头配置。勾选后将所勾选的字段放入选择字段数组中,再通过sort对数组进行排序

源码:

<template>
  <div class="shuttle">
    <!-- 左边列表 -->
    <div class="shuttle-box">
      <div class="shuttle-box-title">
        <div> <span>未选择字段</span></div>
        <div class="index-num">{{itemLeft.length}}</div>
      </div>
      <div class="shuttle-box-list">
        <el-checkbox-group v-model="checkLeft">
          <el-checkbox style="display: block;" v-for="(vo,inx) in itemLeft" :label="inx" :key="inx">{{vo.name}}</el-checkbox>
        </el-checkbox-group>
      </div>
    </div>
    <!-- 左右操作按钮 -->
    <div class="shuttle-click" v-if="isEdit">
      <span @click="goLeft">←</span>
      <span @click="goRight">→</span>
    </div>
    <!-- 右边列表 -->
    <div class="shuttle-box">
      <div class="shuttle-box-title">
        <div>已选择字段</div>
        <div class="index-num">{{itemRight.length}}</div>
      </div>
      <div class="shuttle-box-list">
        <el-checkbox-group v-model="checkRight">
          <el-checkbox style="display: block;position: relative;" v-for="(vo,inx) in itemRight" :label="inx" :key="inx">
            <span v-if="isEdit" style=" width: 40px;margin-right: 5px;
    display: inline-block;"> <el-button size="medium" type="text" style="margin-left: 5px; " icon="el-icon-top" v-if="inx>0" @click="moveUp(inx)"> </el-button>
              <el-button size="medium" type="text" style="margin-left:5px; " icon="el-icon-bottom" v-if="inx<itemRight.length-1" @click="moveDown(inx)"></el-button>
            </span>
            {{vo.name}}
            <el-popover placement="right" :width="400" trigger="click" v-if="vo.field=='Supporting'">
              <template #reference>
                <el-button size="medium" type="text" style="margin-left: 8px;color: #ff9800;">设置比例</el-button>
              </template>
              <table class="mytable">
                <tr>
                  <th>配套比例</th>
                  <th v-if="isEdit">
                    <el-button type="text" @click="addData(vo)">添加</el-button>
                  </th>
                </tr>
                <tr v-for="(item, index) in vo.subfield" :key="index">
                  <td>
                    <el-input v-model="item.Name" clearable></el-input>
                  </td>
                  <td v-if="isEdit">
                    <el-button type="text" @click="addData(vo,index)">添加</el-button>
                    <el-button type="text" @click="removeData(vo,index)">删除</el-button>
                  </td>
                </tr>
              </table>
            </el-popover>
          </el-checkbox>
        </el-checkbox-group>
      </div>
    </div>
  </div>

</template>
 <script lang="ts">
import { reactive, toRefs, getCurrentInstance, watch } from 'vue';
import { ElMessageBox, ElMessage } from 'element-plus';
export default {
	props: {
		itemLeft: {
			type: Array,
			default: () => {
				return [];
			},
		},
		itemRight: {
			type: Array,
			default: () => {
				return [];
			},
		},
		isEdit: {
			type: Boolean,
			default: () => {
				return true;
			},
		},
	},
	setup(props, context) {
		const state = reactive({
			checkLeft: [],
			checkRight: [],
			sortIndex: 0,
		});

		const addData = (item: any) => {
			if (item.subfield.length > 3) {
				ElMessage.error('最多只能添加4条数据!');
				return;
			}
			item.subfield.push({ ID: 'Supporting' + item.subfield.length, Name: '' });
		};
		const removeData = (item: any, index: any) => {
			item.subfield.splice(index, 1);
		};

		const goLeft = () => {
			//数组排序
			state.checkRight.forEach((item) => {
				//将itemRight对应索引的数据移动到左边去
				props.itemLeft.push(props.itemRight[item]);
				//移除
				props.itemRight.splice(item, 1);
			});
			//清空
			state.checkLeft = [];
			state.checkRight = [];
			sortIndex();
		};
		const goRight = () => {
			//数组排序
			state.checkLeft.forEach((item) => {
				//将itemLeft对应索引的数据移动到右边去
				props.itemRight.push(props.itemLeft[item]);
				//移除
				props.itemLeft.splice(item, 1);
			});
			//清空
			state.checkLeft = [];
			state.checkRight = [];
		};

		const sortIndex = () => {
			props.itemLeft.sort(function (a, b) {
				return a.id - b.id;
			});
		};

		//上移
		const moveUp = (index: any) => {
			var item = JSON.parse(JSON.stringify(props.itemRight[index]));
			var itemPre = JSON.parse(JSON.stringify(props.itemRight[index - 1]));
			props.itemRight.splice(index, 1, itemPre);
			props.itemRight.splice(index - 1, 1, item);
		};

		//下移
		const moveDown = (index: any) => {
			var item = JSON.parse(JSON.stringify(props.itemRight[index]));
			var itemNext = JSON.parse(JSON.stringify(props.itemRight[index + 1]));
			props.itemRight.splice(index, 1, itemNext);
			props.itemRight.splice(index + 1, 1, item);
		};

		return {
			moveDown,
			moveUp,
			addData,
			removeData,
			sortIndex,
			goLeft,
			goRight,
			...toRefs(state),
		};
	},
};
</script>


<style scoped  lang="scss">
.mytable th {
	padding: 0px 10px;
}
.shuttle {
	width: 800px;
	padding: 50px 0;
	display: flex;
	justify-content: space-between;
	//整个穿梭框
	.shuttle-box {
		width: 260px;
		height: 420px;
		border: 1px solid #ddd;
		//标题
		.shuttle-box-title {
			background: #f5f7fa;
			padding: 0 20px;
			height: 40px;
			line-height: 40px;
			display: flex;
			justify-content: space-between;
			.index-num {
				color: #909399;
				font-size: 12px;
				font-weight: 400;
			}
		}
		//列表
		.shuttle-box-list {
			padding: 20px;
			height: 380px;
			overflow: auto;
			//一个列表item
			.shuttle-box-item {
				line-height: 2;
			}
		}
	}
	//左右穿梭按钮
	.shuttle-click {
		padding-top: 60px;
		cursor: pointer;
		display: flex;
		align-content: space-around;
		flex-direction: column;
		flex-wrap: wrap;
		justify-content: flex-start;
		span {
			padding: 10px;
			display: inline-block;
			background: #409eff;
			color: #ffffff;
			margin: 10px;
			text-align: center;
		}
	}
}
</style>

二、引入穿梭框

 引入后在页面中使用,注意使用时需要传入可选字段和已选字段

三、自定义表头 

将穿梭框的已选字段数组对表头进行遍历渲染,即可完成对表头的自定义配置。我这里用的是原生表格,如果用element的表格需要数据绑定的话可以通过props属性进行绑定。

<table class="mytable">
				<tr>
					<th v-if="selectfield.length !== 0">序号</th>
					<th v-for="element in selectfield" :key="element.id">{{ element.name }}</th>
				</tr>
				<tr v-for="(item, index) in data" :key="index">
					<td v-if="selectfield.length !== 0">{{ index + 1 }}</td>
					<td v-for="eitem in selectfield" :key="eitem.id">{{ item[eitem.field] }}</td>
				</tr>
			</table>

四、效果图

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值