vue 基于tree结构的穿梭框



两级分组 的情况
 <div v-if="dialogType == 'add'">
        <el-form ref="ruleForm" :model="form" label-width="100px">
          <el-form-item
            label="设备"
            prop="predicates"
            :rules="[{ required: true, message: '请选择执行方案' }]"
          >
            <div class="add_device">
              <div class="left">
                <div class="num">
                  <span
                    class="checkAll"
                    @click="checkAll"
                    :style="{
                      background: checkedKeysLift.length ? '#059A7A' : '#fff',
                    }"
                  >
                    <i
                      class="el-icon-check"
                      v-if="checkedKeysLift.length == checkAllLeft"
                    ></i>
                    <i
                      class="el-icon-minus"
                      v-if="checkedKeysLift.length < checkAllLeft"
                    ></i>
                  </span>
                  <span>{{ checkedKeysLift.length }}/{{ checkAllLeft }}</span>
                </div>
                <div class="list">
                  <el-tree
                    :props="defaultProps"
                    :data="deviceList"
                    show-checkbox
                    node-key="id"
                    @check-change="handleCheckChange"
                    ref="tree"
                  >
                  </el-tree>
                </div>
              </div>
              <div class="center">
                <div
                  :class="checkedKeysRight.length ? 'checkd' : 'nocheck'"
                  @click="addtoLift"
                >
                  <i class="el-icon-arrow-left"></i>
                </div>
                <div
                  :class="checkedKeysLift.length ? 'checkd' : 'nocheck'"
                  @click="addtoRight"
                >
                  <i class="el-icon-arrow-right"></i>
                </div>
              </div>
              <div class="right">
                <div class="num">
                  <span
                    class="checkAll"
                    @click="checkAllRight"

                    :style="{
                      background: checkedKeysRight.length ? '#059A7A' : '#fff',
                    }"
                  >
                    <i
                      class="el-icon-check"
                      v-if="checkedKeysRight.length == checktoRight.length"
                    ></i>
                    <i
                      class="el-icon-minus"
                      v-if="checkedKeysRight.length < checktoRight.length"
                    ></i>
                  </span>
                  <span
                    >{{ checkedKeysRight.length }}/{{
                      checktoRight.length
                    }}</span
                  >
                </div>

                <div>
                  <el-tree
                    :props="defaultProps"
                    :data="checktoRight"
                    show-checkbox
                    node-key="id"
                    @check-change="handleCheckChangeRight"
                    ref="treeright"
                  >
                  </el-tree>
                </div>
              </div>
            </div>
          </el-form-item>
        </el-form>
      </div>

<script>
import {
  getGroup,
  getDeviceGroup,
  getGroupAll,
} from "@iotManagement/api/index";
export default {
  name: "config",
  props: {
    //详情数据
    info: {
      type: Object,
      default: () => {},
    },
  },

  watch: {
    info: {
      handler(val) {
        console.log(val);
      },
      
    },
    checktoRight:{
      handler(val){
        // console.log(val)
        this.form.predicates=val

        // console.log( this.form.predicates)
        

      },
      deep:true,
          immediate: true,

    }
  },
  filters: {
    changename(val) {
      return val.join("|");
    },
  },
  computed: {},

  data() {
    return {
      firstDeviceList: [], //初始获取的设备分组
    
    
      dialogType: "add",
     
     
      form: {
        predicates: [],
      },
      deviceList: [], //左侧数据列表
       
      checkcolorLeft: "#fff",
      checknumLeft: 0,
      checkAllLeft: 0,
      checkedKeysLift: [],
      defaultProps: {
        children: "children",
        label: "name",
        isLeaf: "leaf",
        disabled: "disabled",
      },
      checktoRight: [], //右侧数据列表
      checkedKeysRight: [],//右侧选中数据
    };
  },
  mounted() {this.addcufa()},
  methods: {
    //  获取设备分组
    getGropList() {
      getGroup().then((res) => {
        console.log(res);
        this.firstDeviceList = res.data.items;

        let data = JSON.parse(JSON.stringify(res.data.items));
        this.chuliListWay(data);
       
      });
    },

    // 处理左侧树结构用的list
    chuliListWay(data) {
      let list = [];
      this.checkAllLeft = 0;

      data.forEach((element) => {
        if (element.parentId == "0") {
          element.children = [];
          list.push(element);
        }
      });
      for (var j = 0; j < data.length; j++) {
        for (var i = 0; i < list.length; i++) {
          if (data[j].parentId == list[i].id) {
            if (data[j].groupDeviceList) {
              data[j].groupDeviceList.forEach((element) => {
                element.name = element.deviceName;
                if (!element.disabled) {
                  //左边的总数
                  this.checkAllLeft++;
                }
              });

              data[j].children = data[j].groupDeviceList;
            }
            list[i].children.push(data[j]);
          }
        }
      }
      this.deviceList = list;
    },

     
    
    addcufa() {
      this.getGropList();

      

      this.dialogVisible = true;

      this.checktoRight = [];
    },
    // 左侧全选or取消全选

    checkAll() {
      
      if (this.checkedKeysLift.length == this.checkAllLeft) {
        this.$refs.tree.setCheckedKeys([]);
      } else {
        this.$refs.tree.setCheckedNodes(this.deviceList);
      }
    },
    // 右侧全选or取消全选
    checkAllRight(){
      if (this.checkedKeysRight.length == this.checktoRight.length) {
        this.$refs.treeright.setCheckedKeys([]);
        
      } else {
        this.$refs.treeright.setCheckedNodes(this.checktoRight);
      }
    },
    //选中设备事件
    handleCheckChange(data, checked, indeterminate) {
      var data1 = this.$refs.tree.getCheckedNodes(true);

      this.checkedKeysLift = [];
      data1.forEach((element) => {
        if (element.groupName) {
          this.checkedKeysLift.push(element);
        }
      });
    },
    //点击添加到右边
    addtoRight() {
      this.checktoRight = this.checktoRight.concat(this.checkedKeysLift);

      this.leftListDisabled();
    },
    // 右侧选中设备事件
    handleCheckChangeRight() {
      var data1 = this.$refs.treeright.getCheckedNodes(true);

      this.checkedKeysRight = data1;
    },
    //添加到左边
    addtoLift() {
      // 去掉选中数据
      let newArr = this.checktoRight.filter((v) =>
        this.checkedKeysRight.every((val) => val.id != v.id)
      );
      // 把去重之后的数组赋值给右边
      this.checktoRight = newArr;
       this.checkedKeysRight=[]
      this.leftListDisabled();
    },
    // 处理左侧数据
    leftListDisabled() {
      console.log(this.checktoRight)
      var firstDeviceList1 = JSON.parse(JSON.stringify(this.firstDeviceList));//获取初始化设备分组列表

      for (let i = 0; i < firstDeviceList1.length; i++) {
        // 只需要获取又设备的分组
        if (firstDeviceList1[i].groupDeviceList) {
          for (let j = 0; j < firstDeviceList1[i].groupDeviceList.length; j++) {
            // 添加到右侧的数据不让再选中
            this.checktoRight.forEach((element) => {
              console.log('zuihouyibu')
              if (element.id == firstDeviceList1[i].groupDeviceList[j].id) {
                firstDeviceList1[i].groupDeviceList[j].disabled = true;
                
              }
            });
          }
        }
      }
      this.chuliListWay(firstDeviceList1);
      
    },
  },
};
</script>

<style lang="less" scoped>
#config {
  padding: 20px;

  .title {
    font-size: 20px;
    font-weight: bold;
    color: #1d2129;
    border-bottom: 1px solid #d9d9d9;
    padding: 10px 0;
    span {
      font-size: 14px;
      font-weight: 400;
      color: #595959;
    }
  }
  .config_content {
    display: flex;
    justify-content: space-between;
    flex-wrap: wrap;
    .new {
      display: flex;
      flex-direction: column;
      align-items: center;
      padding: 20px;
      justify-content: center;
      cursor: pointer;
      i {
        font-size: 18px;
        font-weight: bold;
        margin-bottom: 10px;
      }
      span {
        font-size: 14px;
        color: #595959;
      }
    }
    .box {
      position: relative;
      .bianji {
        background: #f7f7f7;
        position: absolute;
        bottom: 0;
        border-radius: 0px 0px 4px 4px;
        text-align: center;
        border-top: 1px solid #e5e8ef;
        width: 100%;
        font-size: 14px;

        color: #595959;
        padding: 14px 0;
        cursor: pointer;
      }
      .con {
        margin-bottom: 40px;
        padding: 20px;
        .con_title {
          width: 100%;
          font-size: 14px;
          font-weight: bold;
          color: #1c2023;
          overflow: hidden;
          text-overflow: ellipsis;
          width: 100%;
          display: -webkit-box;
          -webkit-box-orient: vertical;
          -webkit-line-clamp: 1;
          word-break: break-all;
        }
        .con_con {
          font-size: 14px;
          color: #2f92f7;
          background: rgba(47, 146, 247, 0.06);
          border-radius: 2px;
          border: 1px solid rgba(47, 146, 247, 0.5);
          margin: 10px 10px 0;
        }
      }
    }
    .new,
    .box {
      width: 24%;
      margin-top: 20px;
      border: 1px solid #e5e8ef;
      border-radius: 4px;
    }
    /* 如果最后一行是4个元素 */
    .box:last-child:nth-child(4n - 1) {
      margin-right: calc(24% + 4% / 3);
    }
    /* 如果最后一行是3个元素 */
    .box:last-child:nth-child(4n - 2) {
      margin-right: calc(48% + 8% / 3);
    }
    /* 如果最后一行是2个元素 */
    .box:last-child:nth-child(4n - 3) {
      margin-right: calc(72% + 12% / 3);
    }
  }
}
.popover {
  max-height: 280px;
  overflow: scroll;

  ul {
    list-style-type: none;
    li {
      color: #1c2023;
      line-height: 28px;
      font-size: 14px;
      margin-right: 20px;
    }
  }
}
.divider {
  margin: 80px 0;

  background-color: #d9d9d9;
  div {
    color: #059a7a;
    cursor: pointer;
  }
}
.add_device {
  display: flex;
  width: 100%;
  .left,
  .right {
    width: 45%;
    border-radius: 2px;
    border: 1px solid #d9d9d9;

    .num {
      width: 100%;
      border-bottom: 1px solid #d9d9d9;
      padding: 8px;

      .checkAll {
        margin-right: 8px;
        cursor: pointer;
        border-radius: 2px;
        border: 1px solid #d9d9d9;
        i {
          color: #fff;
          font-size: 10px;
          padding: 0 2px;
        }
      }
    }
    .list {
      max-height: 400px;
      overflow: scroll;
    }
  }
  .center {
    width: 10%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: space-evenly;
    div {
      width: 30px;
      height: 30px;
      border-radius: 2px;
      display: flex;
      align-items: center;
      justify-content: center;
      cursor: pointer;
    }
    .checkd {
      background: #059a7a;
      border: 1px solid #059a7a;
      color: #fff;
    }
    .nocheck {
      background: #f5f5f5;
      border: 1px solid #d9d9d9;
      color: #bfbfbf;
    }
  }
}
</style>












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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值