前言:由于项目需要,element ui 里面的穿梭框不满足需求,所以自己封装了一个穿梭框,此穿梭框为三个,可以两两穿梭。

如下图:

穿梭框

代码如下:如有bug ,欢迎指出; 其实数据的传输,最好用vuex 来做;下面用的props ,监听来做的。

其中需要判断的几个点:大家参考下

1):操作按钮什么情况下可以点,什么情况下致灰;利用:disabled 来判断的

2):穿梭框里面的选项,什么情况下可以点,什么情况下不能点;利用:disabled 来判断的

3):每个框里面的数据全部分为展示用的,和选中操作用的,注意他们之间的互相计算

4):每操作完一步,注意清空数据和合并数据

<template>
  <div class="shuttle">
    <div class="shuttle_item">
      <span>区域内学校</span>
      <ul class="school">
        <li v-for="(item,index) in allSchool" :key="index">
          <input type="checkbox" :id="item.userId" :value="item.userId"
                 v-model="schoolsNames"
                 :disabled="teamName.length>0||teamLeader.length>0?true:false"
          >
          <label :for="item.userId">{{item.username}}</label>
        </li>
      </ul>
    </div>
    <div class="shuttle_arrow">
      <el-button icon="el-icon-d-arrow-right" type="primary" plain @click="toRightTeam"
                 :disabled="schoolsNames.length==0?true:false">到右边
      </el-button>
      <el-button icon="el-icon-d-arrow-left" type="primary" plain class="go_left"
                 :disabled="teamName.length==0?true:false" @click="toLeftSchools">到左边
      </el-button>
    </div>
    <div class="shuttle_item">
      <span>小组成员</span>
      <ul class="school">
        <li v-for="(item ,index ) in allTeam" :key="index">
          <input type="checkbox" :id="item.userId" :value="item.userId"
                 v-model="teamName"
                 :disabled="schoolsNames.length>0||teamLeader.length>0?true:false"
          >
          <label for="item.userId">{{item.username}}</label>
        </li>
      </ul>
    </div>
    <div class="shuttle_arrow">
      <el-button icon="el-icon-d-arrow-right" type="primary" plain
                 :disabled="teamName.length==0?true:false"
                 @click="toRightLeader"
      >到右边
      </el-button>
      <el-button icon="el-icon-d-arrow-left" type="primary" plain class="go_left"
                 :disabled="teamLeader.length==0?true:false"
                 @click="toLeftTeam"
      >到左边
      </el-button>
    </div>
    <div class="shuttle_item">
      <span>小组组长</span>
      <ul class="school">
        <li v-for="(item,index) in leader" :key="index">
          <input type="checkbox" :id="item.userId" :value="item.userId"
                 v-model="teamLeader"
                 :disabled="schoolsNames.length>0||teamName.length>0?true:false"
          >
          <label :for="item.userId">{{item.username}}</label>
        </li>
      </ul>
    </div>
  </div>
</template>

<script>
  export default {
    name: "shuttle",
    data() {
      return {
        allSchool: [],//所有学校
        allTeam: [],  //所有小组
        leader:[],// 组长
        schoolsNames: [],   //所有学校 选中的
        teamName: [],   //小组成员  选中的
        teamLeader: [],   //小组组长  选中的
      }
    },
    props: ["schoolInfo","teamInfo","leaderInfo"],
    created() {
    },
    mounted() {
    },
    watch: {
      schoolInfo(val) {   //  编辑时用来回显,添加时的默认数据
        this.schoolInfo = val;
        this.allSchool = val;
      },
      teamInfo(val){   //  编辑时用来回显
        this.teamInfo = val;
        this.allTeam=val;
      },
      leaderInfo(val){   //  编辑时用来回显
        this.leaderInfo=val;
        this.leader=val;
      },
    },
    methods: {
      async toRightTeam() {
        let moveName= await this.matching(this.allSchool,this.schoolsNames);
        let allArr= await this.myFilter(this.allSchool,moveName);
        this.allSchool = allArr;
        for(let i=0;i<moveName.length;i++){
          this.allTeam.push(moveName[i])
        }
        this.schoolsNames=[];
        await this.putParentsTeams();
      },
      async toLeftSchools() {
        let moveName= await this.matching(this.allTeam,this.teamName);
        let allArr =await this.myFilter(this.allTeam,moveName);
        this.allTeam = allArr;
        for(let i=0;i<moveName.length;i++){
          this.allSchool.push(moveName[i])
        }
        this.teamName=[];
        await this.putParentsTeams();
      },
      async toRightLeader() {
        if (this.leader.length >= 1||this.teamName.length>1) {
          this.$message({
            message: "小组组长只能选一个",
            type: "error"
          });
          return false;
        }
        let moveName= await this.matching(this.allTeam,this.teamName);
        let allArr =await this.myFilter(this.allTeam,moveName);
        this.allTeam = allArr;
        for(let i=0;i<moveName.length;i++){
          this.leader.push(moveName[i])
        }
        this.teamName=[];
        await this.putParentsTeams();
      },
      async toLeftTeam() {
        let moveName= await this.matching(this.leader,this.teamLeader);
        let allArr =await this.myFilter(this.leader,moveName);
        this.leader = allArr;
        for(let i=0;i<moveName.length;i++){
          this.allTeam.push(moveName[i])
        }
        this.teamLeader=[];
        await this.putParentsTeams();
      },
      // 过滤 相同选项
      async myFilter(allArr, selArr) {
        let ary03 = [];
        for (let i = 0; i < allArr.length; i++) {
          for (let j = 0; j < selArr.length; j++) {
            if (allArr[i].userId == selArr[j].userId) {
              allArr.splice(i,1);
            }
          }
        }
        return allArr;
      },
      //  匹配 移动的 选项
      async matching(allArr, matchArr) {
        let matArr = [];
        for (let i = 0; i < allArr.length; i++) {
          for (let j = 0; j < matchArr.length; j++) {
            if (allArr[i].userId == matchArr[j]) {
              matArr.push(allArr[i]);
            }
          }
        }
        return matArr;
      },
      //    向父组件传组员名称 和组长id   由于这是单独的一个穿梭框组件,数据会和父组件里面的动态绑定,提交按钮也在父组件,所以需要此步骤,
      async putParentsTeams() {
        this.$emit('teamNames', this.allTeam,this.leader);
      },
    },

  }
</script>

<style lang="scss" scoped>
  ul li {
    list-style: none;
  }

  .shuttle {
    display: flex;
    flex-direction: row;
    justify-content: center;

    .shuttle_item {
      width: 20%;

      span {
        font-size: 16px;
        margin-left: 50px;
      }
    }

    .shuttle_arrow {
      width: 10%;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      margin: 0 30px 0 20px;

      .go_left {
        margin-left: 0;
        margin-top: 15px;
      }
    }

    .school {
      border: 1px solid #c8c9cc;
      padding: 0 10px;
      border-radius: 5px;
      height: 150px;
      overflow: auto;

      li {
        padding-top: 10px;
      }
    }
  }
</style>

 

 

 

 

Logo

前往低代码交流专区

更多推荐