Bootstrap

基于iview封装的tree组件、checkbox组件的穿梭框组件

在这里插入图片描述

<template>
  <Modal width="1100" class="transfer-main" v-model="isShowModle" @on-ok="ok" @on-cancel="cancel">
    <div slot="header" class="header">
      <span>部门人员选择</span>
    </div>
    <div class="tr-content">
      <div class="tree-main">
        <div class="title">组织机构</div>
        <div class="tree-con">
          <Tree class="suc-tree" ref='tree' @on-select-change="clickTree" :data="institutions"></Tree>
        </div>
      </div>
      <div class="tr-main">
        <div class="source">
          <div class="title seach">
            <span>用户列表({{ transferData.length }})</span>
            <Input v-model="keyWords" suffix="ios-search" placeholder="请输入" style="width: auto" @on-change="onInputSearch"
              clearable />
          </div>
          <div class="user-list">
            <CheckboxGroup v-for="(item, index) in transferData" :key="index" v-model="checkAllGroup"
              @on-change="checkAllGroupChange">
              <Checkbox :label="item.label"></Checkbox>
            </CheckboxGroup>
          </div>
        </div>
        <div class="mid">
          <Icon v-if="checkAllGroup.length > 0" type="ios-arrow-forward" :size="30" @click="onSelectUser"
            color="#1890ff" />
          <Icon v-else type="ios-arrow-forward" :size="30" color="#d9d9d9" />
        </div>
        <div class="selected">
          <div class="title">已选择({{ selectedData.length }})</div>
          <div class="user-list">
            <ul>
              <li v-for="(item, index) in selectedData" :key="index" @mouseenter="currentIndex = index"
                @mouseleave="currentIndex = -1">
                <span>{{ item.label }}</span>
                <Icon v-if="currentIndex === index" type="ios-close-circle-outline" :size="24" color="#1890ff"
                  @click="onDelte(index)" />
              </li>
            </ul>
          </div>
        </div>
      </div>
    </div>
  </Modal>
</template>

<script>
export default {
  props: {
    isShowModle: {
      type: Boolean
    },
  },
  data () {
    return {
      keyWords: '',
      currentIndex: -1,
      indeterminate: true,
      checkAll: false,
      checkAllGroup: [],
      selectedAllGroup: [],
      institutions: [],
      transferData: [],
      selectedData: [],
      allUserList: []
    }
  },
  mounted () {
    this.getinstitutions()
    this.getUserData()
  },
  methods: {
    onDelte (index) {
      this.selectedData.splice(index, 1)
    },
    handleCheckAll () {
      if (this.indeterminate) {
        this.checkAll = false;
      } else {
        this.checkAll = !this.checkAll;
      }
      this.indeterminate = false;

      if (this.checkAll) {
        let tmp = []
        this.allUserList.forEach(el => {
          tmp.push(el.label)
        })
        this.checkAllGroup = tmp;
      } else {
        this.checkAllGroup = [];
      }
    },
    // 模糊搜索
    onInputSearch () {
      if (this.keyWords) {
        this.transferData = this.allUserList.filter(
          item => item.deptName.indexOf(this.keyWords) != -1 || item.userName.indexOf(this.keyWords) != -1 || item.label.indexOf(this.keyWords) != -1
        );
      } else {
        this.transferData = this.allUserList
      }
    },
    // 从左到右,穿梭
    onSelectUser () {
      // 备份用户列表
      let selectedDataCp = JSON.parse(JSON.stringify(this.selectedData))
      let checkAllGroupCp = JSON.parse(JSON.stringify(this.checkAllGroup))
      // 根据选择的label(iview中checkbox以label作为回显),获取相应的对象,及序号
      let getSelected = []
      let getSelectedIndex = []
      // this.checkAllGroup中是选中的人员的label
      this.checkAllGroup.forEach((el, index) => {
        this.transferData.forEach(ele => {
          if (el === ele.label) {
            getSelected.push(ele)
            getSelectedIndex.push(index)
          }
        })
      })

      // 将选中的项在checkAllGroup中删除
      getSelected.forEach((el) => {
        // 将已选中的项置空
        this.checkAllGroup.forEach((ele, index) => {
          if (el.label === ele) {
            checkAllGroupCp[index] = ''
          }
        })
        //添加到右侧时, 判断是否已经选择
        let isUnique = this.selectedData.some(cur => cur.pkId === el.pkId)
        // 将未选择的加入,已选择的剔除
        if (!isUnique) {
          selectedDataCp.push(el)
        }
      })
      // 将空的项,过滤掉(穿梭后将选中状态取消)
      this.checkAllGroup = checkAllGroupCp.filter(el => el !== '')

      // 给已选择赋值
      this.selectedData = selectedDataCp
      // this.indeterminate = true;
      // this.checkAll = false;
    },
    ok () {
      // 处理人员和部门
      if (this.selectedData.length === 0) {
        this.$Message.warning('请选择人员!')
        return false
      }
      this.$emit('onModelData', this.selectedData)
      this.$emit('update:isShowModle', false)
    },
    cancel () {
      this.$emit('update:isShowModle', false)
    },
    clickTree (selected, current) {
      let selectedNodes = this.$refs.tree.getSelectedNodes()
      if (selectedNodes.length > 0) {
        this.getUserData(current.code)
      } else {
        this.getUserData()
      }
      console.log(this.$refs.tree.getSelectedNodes())
    },
    // 组织机构数据
    getinstitutions () {
      let params = {}
      // 机构接口
      this.$http.get('XXX', params)
        .then((res) => {
          if (res.code == 200) {
            this.institutions = res.data.children
          }
        })
        .catch((error) => { })
    },
    getUserData (deptId) {
      this.datalist = []
      let params = {
        deptId: deptId ? deptId : ''
      }
     //人员接口
      this.$http.get('XXX', params)
        .then((res) => {
          if (res.code == 200) {
            res.data.forEach(el => {
              el.label = el.userName + '(' + el.deptName + ')'
              el.key = el.pkId
            })
            this.transferData = res.data
            if (!deptId) {
              this.allUserList = res.data
            }
          }
        })
        .catch((error) => { })
    },
  }
}
</script>

<style lang="scss" scoped>
.tr-content {
  display: flex;
  padding: 15px 15px 0;

  .tree-main {
    width: 320px;
    height: 500px;
    border: 1px solid #d9d9d9;

    .tree-con {
      height: calc(100% - 50px);
      overflow: auto;
    }

  }

  .suc-tree {
    box-sizing: border-box;
    padding-left: 15px;

    ::v-deep .ivu-checkbox-wrapper {
      margin: 0;
    }

    ::v-deep .ivu-checkbox-wrapper+span {
      width: 220px;
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
    }
  }

  .user-list {
    margin: 10px;
    height: calc(100% - 50px);
    overflow: auto;

    ::v-deep .ivu-checkbox-group {
      margin-bottom: 5px;
    }

    ul>li {
      display: flex;
      padding: 0 10px;
      background-color: #d5e8fc;
      justify-content: space-between;
      height: 26px;
      margin-bottom: 5px;
      align-items: center;
    }
  }

  .title {
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 14px;
    color: #333;
    height: 40px;
    border-bottom: 1px solid #d9d9d9;
  }

  .tr-main {
    flex: 1;
    display: flex;
    margin-left: 15px;
    height: 500px;

    .source {
      flex: 1;
      border: 1px solid #d9d9d9;

      .seach {
        padding: 0 10px;
        display: flex;
        justify-content: space-between;
      }
    }

    .mid {
      width: 20px;
      margin: 0 15px;
      display: flex;
      align-items: center;
      justify-content: center;
      flex-direction: column;

      ::v-deep .ivu-icon {
        cursor: pointer;
      }
    }

    .selected {
      flex: 1;
      border: 1px solid #d9d9d9;
    }
  }

}

.transfer-main {
  ::v-deep .ivu-modal-close .ivu-icon-ios-close {
    top: -5px;
    right: -9px;
    color: #fff;
  }

  .header {
    height: 40px;
    display: flex;
    align-items: center;
    padding-left: 20px;
    background-color: #1890ff;
    border-radius: 5px 5px 0 0;
    color: #fff;

    &::before {
      position: absolute;
      content: '';
      width: 3px;
      height: 15px;
      background-color: #fff;
      left: 12px;
    }
  }

}
</style>

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;