el-Transfer 穿梭框重写左右拖拽排序及点击复选框组件

  1. 适用组件:

    导入,注册组件,然后使用

    <DragTransfer
              :checkedSearchList="checkedSearchList"
              leftTitle="未展示筛选项"
              rightTitle="常用筛选区"
              :data="checkedSearchLists"
              :props="transferProps"
              @chageRightData="updateSelectedItems"
            ></DragTransfer>

    参数解释:

    :checkedSearchList="checkedSearchList"  右边已选择的数据
     :data="data" 所有数据,左边和右边一起的数据
    leftTitle="未选择字段"  左边标题
     rightTitle="已选择字段" 右边标题
    :props="transferProps" 字段映射
    @chageRightData="updateSelectedItems" 接受子组件传递的值

    vue  data中定义:

    transferProps: {
            value: "rfidSetId",
            label: "rfidSetName",
          },
  2. 左右拖拽加复选组件:

    src/components/DragTransfer.vue

<template>
  <div class="drag-transfer">
    <div class="drag-transfer-content">
      <div class="drag-transfer-left">
        <span class="tipSapn1"></span>
        <div class="drag-transfer-title">
          {{ leftTitle }}
          <span class="dragSpan">可拖拽字段进行配置</span>
        </div>
        <div
          id="left"
          class="drag-transfer-item"
          @drop="drop"
          @dragover="allowDrop"
        >
          <template v-for="(item, index) in leftData">
            <div
              :key="index"
              draggable="true"
              @dragstart="dragstart"
              :id="item.key"
              @click="checkLeftElement(item)"
              :class="[
                'drag-transfer-item-name',
                item.checked ? 'dragActive' : '',
              ]"
            >
              <input
                class="checkInput"
                type="checkbox"
                v-model="item.checked"
                @change="checkboxLeftChanged(item)"
              />
              <span class="checkSpan">{{ item.label }}</span>
            </div>
          </template>
        </div>
      </div>
      <div class="drag-transfer-center">
        <div class="twoImage">
          <img
            src="@/assets/img/toLeft.png"
            alt=""
            v-if="checkRight.length === 0"
          />
          <img
            src="@/assets/img/toLeftBG.png"
            alt=""
            v-if="checkRight.length !== 0"
            @click="turnLeft"
          />
          <img
            src="@/assets/img/toRight.png"
            alt=""
            v-if="checkLeft.length === 0"
          />
          <img
            src="@/assets/img/toRightBG.png"
            alt=""
            v-if="checkLeft.length !== 0"
            @click="turnRight"
          />
        </div>
      </div>

      <div class="drag-transfer-right">
        <span class="tipSapn1"></span>
        <div class="drag-transfer-title">{{ rightTitle }}</div>
        <div
          id="right"
          class="drag-transfer-item"
          @drop="drop"
          @dragover="allowDrop"
        >
          <template v-for="(item, index) in rightData">
            <div
              :key="index"
              draggable="true"
              @dragstart="dragstart"
              :id="item.key"
              :class="[
                'drag-transfer-item-name',
                item.checked ? 'dragActive' : '',
              ]"
            >
              <input
                class="checkInput"
                type="checkbox"
                v-model="item.checked"
                @change="checkboxRightChanged(item)"
              />
              <span class="checkSpan">{{ item.label }}</span>
            </div>
          </template>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  name: "drag-transfer",
  model: {
    prop: "rightData",
    event: "chageRightData",
  },
  props: {
    rightData: {
      type: Array,
      default: () => [],
    },
    checkedSearchList: {
      type: Array,
      default: () => [],
    },
    leftTitle: {
      type: String,
      default: "未选择",
    },
    rightTitle: {
      type: String,
      default: "已选择",
    },
    props: {
      type: Object,
      default: () => ({
        value: "value",
        label: "label",
      }),
    },
    data: {
      type: Array,
      default: () => [],
    },
  },
  data() {
    return {
      leftData: [],
      rightData: [],
      tableData: [],
      leftKey: "",
      checkLeft: [],
      checkRight: [],
    };
  },
  mounted() {
    this.rightData = this.checkedSearchList;
  },
  watch: {
    data: {
      handler(val) {
        const self = this;
        this.leftData = [];
        this.data.forEach(function (element) {
          const index = self.rightData.findIndex(
            (x) => x["key"] == element["key"]
          );
          if (index == -1) {
            self.leftData.push(element);
          }
        });
      },
      deep: true,
    },
  },
  methods: {
    // 选中左侧元素
    checkLeftElement(val) {
      this.leftKey = val.key;
    },
    // 左侧选中的元素
    checkboxLeftChanged(value) {
      if (value.checked) {
        this.checkLeft.push(value);
      } else {
        const index = this.checkLeft.findIndex((obj) => obj.key === value.key);
        if (index !== -1) {
          this.checkLeft.splice(index, 1);
        }
      }
    },
    // 右侧选中的元素
    checkboxRightChanged(value) {
      if (value.checked) {
        this.checkRight.push(value);
      } else {
        const index = this.checkRight.findIndex((obj) => obj.key === value.key);
        if (index !== -1) {
          this.checkRight.splice(index, 1);
        }
      }
    },
    // 向右
    turnRight() {
      let pushRight = this.checkLeft.map((item) => {
        return { ...item, status: true };
      });
      pushRight.forEach((item) => {
        item.checked = false;
        if (!this.rightData.some((obj) => obj.key === item.key)) {
          this.rightData.push(item);
        }
      });
      this.checkLeft = [];
      this.leftData = this.leftData.filter((x) => x["checked"] !== true);
      this.$emit("chageRightData", this.rightData);
    },
    // 向左
    turnLeft() {
      let modifiedArray = this.checkRight.map((item) => {
        const { status, ...rest } = item;
        return { ...rest, checked: false };
      });
      modifiedArray.forEach((item) => {
        if (!this.leftData.some((obj) => obj.key === item.key)) {
          this.leftData.push(item);
        }
      });
      this.checkRight = [];
      this.rightData = this.rightData.filter((x) => x["checked"] !== true);
      this.$emit("chageRightData", this.rightData);
    },
    switchLeftNumber(sourceObj, targetObj) {
      const self = this;
      const sourceIndex = this.getLeftIndex(sourceObj["key"]);
      const targetIndex = this.getLeftIndex(targetObj["key"]);

      let arr = JSON.parse(JSON.stringify(this.leftData));
      arr[sourceIndex] = targetObj;
      arr[targetIndex] = sourceObj;
      this.leftData = arr;
    },
    switchRightNumber(sourceObj, targetObj) {
      const self = this;
      const sourceIndex = this.getRightIndex(sourceObj["key"]);
      const targetIndex = this.getRightIndex(targetObj["key"]);
      let arr = JSON.parse(JSON.stringify(this.rightData));
      arr[sourceIndex] = targetObj;
      arr[targetIndex] = sourceObj;
      this.rightData = arr;

      // for (const element of this.rightData) {
      //   if (element["key"] == sourceObj["key"]) {
      //     console.log("targetObj", element, targetObj);
      //     // element = targetObj;
      //   }
      //   if (element["key"] == targetObj["key"]) {
      //     console.log("sourceObj", element, sourceObj);
      //     // element = sourceObj;
      //   }
      // }
    },
    dragRightToLeft(sourceData, tagetId) {
      sourceData.status = false;
      if (tagetId & (tagetId != "left")) {
        //放到元素上,在此处插入
        const targetIndex = this.leftData.findIndex((x) => x["key"] == tagetId);
        this.leftData.splice(targetIndex, 0, sourceData);
      } else {
        //未放到元素上,追加尾部
        this.leftData.push(sourceData);
      }
      this.rightData = this.rightData.filter(
        (x) => x["key"] != sourceData["key"]
      );
    },
    dragLeftToRight(sourceData, tagetId) {
      sourceData.status = true;
      if (tagetId && tagetId != "right") {
        //放到元素上,在此处插入
        const targetIndex = this.rightData.findIndex(
          (x) => x["key"] == tagetId
        );
        this.rightData.splice(targetIndex, 0, sourceData);
      } else {
        //未放到元素上,追加尾部
        this.rightData.push(sourceData);
      }
      this.leftData = this.leftData.filter(
        (x) => x["key"] != sourceData["key"]
      );
    },
    getDataById(id) {
      const dataList = this.data.filter((x) => x["key"] == id);
      return dataList ? dataList[0] : {};
    },
    getRightDataById(id) {
      const dataList = this.rightData.filter((x) => x["key"] == id);
      return dataList ? dataList[0] : {};
    },
    getLeftIndex(id) {
      return this.leftData.findIndex((x) => x["key"] == id);
    },
    getRightIndex(id) {
      return this.rightData.findIndex((x) => x["key"] == id);
    },
    getLeftDataById(id) {
      const dataList = this.leftData.filter((x) => x["key"] == id);
      return dataList ? dataList[0] : {};
    },
    allowDrop(ev) {
      ev.preventDefault();
    },
    dragstart(ev) {
      ev.dataTransfer.setData("id", ev.target.id);
    },
    drop(ev) {
      ev.preventDefault();
      debugger;
      const source_id = ev.dataTransfer.getData("id");
      const targetElement = ev.target.closest("[id]");
      const target_id = targetElement ? targetElement.id : "";
      if (source_id && target_id) {
        const left_source_obj = this.getLeftDataById(source_id);
        const left_target_obj = this.getLeftDataById(target_id);
        const right_source_obj = this.getRightDataById(source_id);
        const right_target_obj = this.getRightDataById(target_id);
        if (left_source_obj && (right_target_obj || target_id == "right")) {
          //左边-右边
          this.dragLeftToRight(left_source_obj, target_id);
        } else if (
          right_source_obj &&
          (left_target_obj || target_id == "left")
        ) {
          //右边-左边
          this.dragRightToLeft(right_source_obj, target_id);
        } else if (
          left_source_obj &&
          (left_target_obj || target_id == "left")
        ) {
          //左边调换顺序
          this.switchLeftNumber(left_source_obj, left_target_obj);
        } else if (
          right_source_obj &&
          (right_target_obj || target_id == "right")
        ) {
          if (target_id == "right") {
            this.rightData = this.rightData.filter(
              (x) => x["key"] != right_source_obj["key"]
            );
            this.rightData.push(right_source_obj);
          } else {
            //右边调换顺序
            this.switchRightNumber(right_source_obj, right_target_obj);
          }
        }
      }
      this.$emit("chageRightData", this.rightData);
    },
  },
};
</script>
<style scoped lang="scss">
.drag-transfer {
  margin: 0;
  padding: 0;
  height: 450px;
}
.tipSapn1 {
  display: inline-block;
  width: 4px;
  height: 14px;
  background: #4353e2;
  float: left;
  margin-right: 6px;
  margin-top: 3px;
}
.drag-transfer-title {
  font-family: PingFangSC, PingFang SC;
  margin-bottom: 18px;
  font-weight: 500;
  font-size: 14px;
  color: rgba(0, 0, 0, 0.85);
  font-style: normal;
}
.dragSpan {
  font-family: PingFangSC, PingFang SC;
  font-weight: 400;
  font-size: 12px;
  color: #a6acbd;
  line-height: 14px;
  text-align: left;
  font-style: normal;
}
.drag-transfer-content {
}
.drag-transfer-item {
  width: 280px;
  height: 368px;
  /* width: 260px; */
  /* height: 100%; */
  background: #fafbfc;
  border-radius: 4px;
  border: 1px solid #d7e3ff;
  overflow-y: auto;
  overflow-x: hidden;
}
.drag-transfer-left {
  float: left;
  height: 400px;
}
.drag-transfer-center {
  float: left;
  height: 400px;
  width: 52px;
}
.drag-transfer-right {
  float: left;
  height: 400px;
}
.drag-transfer-item-name {
  width: 112px;
  height: 30px;
  background: #ffffff;
  border-radius: 2px;
  border: 1px solid #dce4f6;
  margin-left: 19px;
  margin-top: 19px;
  float: left;
}
input[type="checkbox"] {
  background: #ffffff;
  border-radius: 2px;
  margin-top: 6px;
  float: left;
  margin-left: 11px;
  margin-right: 7px;
  width: 16px;
  height: 16px;
}
.checkSpan {
  display: inline-block;
  font-family: PingFangSC, PingFang SC;
  font-weight: 400;
  font-size: 14px;
  color: #333333;
  line-height: 30px;
  text-align: center;
  font-style: normal;
}

input[type="checkbox"]::after {
  color: #000;
  width: 16px;
  height: 16px;
  display: inline-block;
  visibility: visible;
  padding-left: 0px;
  text-align: center;
  content: " ";
  border-radius: 2px;
}
input[type="checkbox"]:checked::after {
  content: "✓";
  color: #fff;
  font-size: 14px;
  line-height: 17px;
  background-color: #4a5de8;
  border-radius: 3px;
}
.dragActive {
  border-radius: 2px;
  border: 1px solid #4353e2;
}
.twoImage {
  height: 84px;
  margin-top: 168px;
  img {
    margin-bottom: 28px;
    margin-left: 12px;
    cursor: pointer;
  }
}
</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值