拖拽功能(列表拖拽) vue + 移动端 + vuedraggable

发布时间 2023-08-01 16:27:23作者: 风雪中de冲破

拖拽列表效果图:

1. 安装  yarn  add  vuedraggable 或者  npm install  vuedraggable
2.新建文件夹   tagManage.vue
代码如下:

<template>
  <div class="home">
    <div class="drag-wrap">
      <draggable
        v-model="myArray"
        chosenClass="chosen"
        forceFallback="true"
        group="people"
        animation="200"
        @start="onStart"
        @end="onEnd"
        :fallbackTolerance="3"
      >
        <transition-group>
          <div
            class="card"
            v-for="item in myArray"
            :key="item.id"
            @click.stop="checkFun(item)"
          >
            <div class="left">
              <img
                v-if="item.isTrue == false"
                src="@/assets/images/34.png"
                alt=""
              />
              <img v-else src="@/assets/images/35.png" alt="" />
            </div>
            <div class="min">
              <p>{{ item.name }}</p>
              <p>
                <span @click.stop="editor(item)">编辑</span>
                <span @click.stop="deleteTor(item)">删除</span>
              </p>
            </div>
          </div>
        </transition-group>
      </draggable>
    </div>
    <div class="inviteWrap">
      <div class="left" @click.stop="checkAllFun">
        <p>
          <img v-if="isCheckAll == false" src="@/assets/images/34.png" alt="" />
          <img v-else src="@/assets/images/35.png" alt="" />
          <span>全选</span>
        </p>
        <p>
          已选择 <i> {{ checkNum }} </i> 标签
        </p>
      </div>
      <div class="right" @click.stop="signInvitationFun">
        <span>删除</span>
      </div>
    </div>
    <img class="fixedImg" @click="addTag" src="@/assets/images/89.png" alt="" />
    <van-action-sheet
      class="relationshipWrap"
      v-model="showRelationship"
      :title="title"
    >
      <div class="wrap">
        <textarea
          class="textarea"
          placeholder="请输入标签名称"
          v-model="tagName"
        ></textarea>
        <div class="btn">
          <span @click="reset">取消</span>
          <span @click="relationshipSure">确定</span>
        </div>
        <div class="borderBottom"></div>
      </div>
    </van-action-sheet>
  </div>
</template>

<script>
import draggable from "vuedraggable";
import {
  defined_tag_query_list,
  defined_tag_sort,
  defined_tag_add,
  update_tag,
  delete_tag,
} from "@/request/api/http.js";
import { Toast, Dialog } from "vant";
export default {
  components: {
    draggable,
  },
  data() {
    return {
      currentDingtalk: {},
      drag: false,
      //定义要被拖拽对象的数组
      myArray: [],
      isCheckAll: false,
      checkNum: 0,
      showRelationship: false,
      title: "新增标签55",
      tagName: "",
      tagChange: null,
      editorObj: {},
    };
  },
  mounted() {
    this.currentDingtalk = JSON.parse(sessionStorage.getItem("userInfo"));
    this.init();
  },

  methods: {
    init() {
      this.tagQueryListFun();
    },
    tagQueryListFun() {
      let that = this;
      that.myArray = [
        {
          name: "严重精神病障碍",
          id: 7,
          value: 7,
        },
        {
          name: "高血压",
          id: 2,
          value: 2,
        },
        {
          name: "阿尔兹海默症",
          id: 10,
          value: 10,
        },
        {
          name: "心脏病患者",
          id: 22,
          value: 22,
        },
        {
          name: "慢阻肺",
          id: 12,
          value: 12,
        },
        {
          name: "65岁以上重点老人",
          id: 9,
          value: 9,
        },
        {
          name: "二型糖尿病",
          id: 3,
          value: 3,
        },
        {
          name: "其他",
          id: 21,
          value: 21,
        },
      ];
      for (let i = 0; i < this.myArray.length; i++) {
        that.myArray[i].isTrue = false;
      }
    },
    //开始拖拽事件
    onStart() {
      this.drag = true;
    },
    //拖拽结束事件
    onEnd() {
      this.drag = false;
      let param = {
        organization_id: this.currentDingtalk.organization_id,
        doctor_job_number: this.currentDingtalk.doctor_job_number,
        doctor_card_number: this.currentDingtalk.doctor_card_number,
        list: this.myArray,
      };
      defined_tag_sort(param).then((res) => {
        Toast.clear();
        if (res.code == 200) {
          console.log(res.data);
        } else {
          Toast.fail(res.message);
        }
      });
    },
    checkFun(item, num) {
      let that = this;
      item.isTrue = !item.isTrue;
      let dataList = [];
      for (let i = 0; i < this.myArray.length; i++) {
        if (this.myArray[i].isTrue == true) {
          dataList.push(this.myArray[i]);
        }
      }
      this.checkNum = dataList.length;
      if (dataList.length == this.myArray.length && dataList.length != 0) {
        this.isCheckAll = true;
      } else {
        this.isCheckAll = false;
      }
      that.$forceUpdate();
    },
    checkAllFun() {
      if (this.isCheckAll == false) {
        this.checkNum = this.myArray.length;
        this.isCheckAll = true;
        for (let i = 0; i < this.myArray.length; i++) {
          this.myArray[i].isTrue = true;
        }
      } else {
        this.checkNum = 0;
        this.isCheckAll = false;
        for (let i = 0; i < this.myArray.length; i++) {
          this.myArray[i].isTrue = false;
        }
      }
    },
    reset() {
      this.showRelationship = false;
    },
    addTag() {
      this.tagName = "";
      this.showRelationship = true;
      this.title = "新增标签";
      this.tagChange = 1;
    },
    editor(item) {
      this.editorObj = {};
      this.title = "修改标签";
      this.tagName = item.name;
      this.showRelationship = true;
      this.tagChange = 2;
      this.editorObj = item;
    },
    deleteTor(item) {
      let that = this;
      Dialog.alert({
        title: "提示",
        message: "确定要删除此项标签么?",
        cancelButtonText: "取消",
        confirmButtonText: "确定",
        showCancelButton: true,
        confirmButtonColor: "#316FFE",
      }).then(() => {
        let param = {
          organization_id: this.currentDingtalk.organization_id,
          doctor_job_number: this.currentDingtalk.doctor_job_number,
          doctor_card_number: this.currentDingtalk.doctor_card_number,
          tag_id: item.id,
        };
        Toast.loading({
          duration: 0, // 持续展示 toast
          forbidClick: true,
        });
        delete_tag(param).then((res) => {
          Toast.clear();
          if (res.code == 200) {
            Toast.success("删除成功");
            setTimeout(function () {
              that.tagQueryListFun();
            }, 500);
          } else {
            Toast.fail(res.message);
          }
        });
      });
    },
    relationshipSure() {
      let that = this;
      if (
        (this.tagName == "" && this.tagChange == 1) ||
        (this.tagName == "" && this.tagChange == 2)
      ) {
        Toast.fail("请输入标签名称");
        return false;
      } else if (this.tagName != "" && this.editorObj.name == this.tagName) {
        Toast.fail("标签名称重复,请重新输入");
        return false;
      } else {
        if (this.tagChange == 1) {
          let param = {
            organization_id: this.currentDingtalk.organization_id,
            doctor_job_number: this.currentDingtalk.doctor_job_number,
            doctor_card_number: this.currentDingtalk.doctor_card_number,
            name: this.tagName,
          };
          Toast.loading({
            duration: 0, // 持续展示 toast
            forbidClick: true,
          });
          defined_tag_add(param).then((res) => {
            Toast.clear();
            if (res.code == 200) {
              Toast.success("新增标签成功");
              setTimeout(function () {
                that.showRelationship = false;
                that.tagQueryListFun();
              }, 500);
            } else {
              Toast.fail(res.message);
            }
          });
        } else if (this.tagChange == 2) {
          let param = {
            organization_id: this.currentDingtalk.organization_id,
            doctor_job_number: this.currentDingtalk.doctor_job_number,
            doctor_card_number: this.currentDingtalk.doctor_card_number,
            name: this.tagName,
            id: this.editorObj.id,
          };
          Toast.loading({
            duration: 0, // 持续展示 toast
            forbidClick: true,
          });
          update_tag(param).then((res) => {
            Toast.clear();
            if (res.code == 200) {
              Toast.success("编辑标签成功");
              setTimeout(function () {
                that.showRelationship = false;
                that.tagQueryListFun();
              }, 500);
            } else {
              Toast.fail(res.message);
            }
          });
        }
      }
    },
    signInvitationFun() {
      let dataList = [];
      for (let i = 0; i < this.myArray.length; i++) {
        if (this.myArray[i].isTrue == true) {
          dataList.push(this.myArray[i].id);
        }
      }
      if (dataList && dataList.length <= 0) {
        Toast.fail("删除标签不能为空");
        return false;
      }
      Dialog.alert({
        title: "提示",
        message: "确定要删除此" + dataList.length + "项标签么?",
        cancelButtonText: "取消",
        confirmButtonText: "确定",
        showCancelButton: true,
        confirmButtonColor: "#316FFE",
      }).then(() => {
        let param = {
          organization_id: this.currentDingtalk.organization_id,
          doctor_job_number: this.currentDingtalk.doctor_job_number,
          doctor_card_number: this.currentDingtalk.doctor_card_number,
          tag_id: item.id,
        };
        Toast.loading({
          duration: 0, // 持续展示 toast
          forbidClick: true,
        });
        delete_tag(param).then((res) => {
          Toast.clear();
          if (res.code == 200) {
            Toast.success("删除成功");
            setTimeout(function () {
              that.tagQueryListFun();
            }, 500);
          } else {
            Toast.fail(res.message);
          }
        });
      });
    },
  },
};
</script>
<style lang="scss" scoped>
.home {
  padding-bottom: calc(85px + constant(safe-area-inset-bottom));
  padding-bottom: calc(85px + env(safe-area-inset-bottom));
  /*被拖拽对象的样式*/
  // .item {
  //   padding: 6px;
  //  
  //   border: solid 1px #eee;
  //   margin-bottom: 10px;
  //   cursor: move;
  // }
  /*选中样式*/
  .drag-wrap {
    background: #fff;
    display: inline-block;
    margin: 15px 15px 0 15px;
    width: calc(100% - 30px);
    border-radius: 6px;
    overflow: hidden;
    .card {
      border-bottom: 0.5px solid #e5e6eb;
      border-left: 0.5px solid #fff;
      border-right: 0.5px solid #fff;
      border-top: 0.5px solid #fff;
      &:nth-last-child(1) {
        border-bottom: 0;
      }
      .left {
        display: inline-block;
        vertical-align: top;
        padding: 18px 15px;
        img {
          display: block;
          width: 20px;
          height: 20px;
        }
      }
      .min {
        display: inline-block;
        vertical-align: top;
        width: calc(100% - 50px);
        position: relative;
        padding: 18px 0;
        p {
          &:nth-child(1) {
            max-width: calc(100% - 150px);
            font-size: 15px;
            color: #333;
          }
          &:nth-child(2) {
            position: absolute;
            top: 19px;
            right: 15px;
            span {
              font-size: 12px;
              color: #316ffe;
              border: 0.5px solid #316ffe;
              font-weight: 700;
              padding: 4px 16px;
              border-radius: 12px;
              margin-right: 10px;
              &:nth-child(2) {
                color: #ff503d;
                border-color: #ff503d;
                margin-right: 0;
              }
            }
          }
        }
      }
      &.chosen {
        border: 0.5px solid #3089dc !important;
      }
    }
  }
  .inviteWrap {
    position: fixed;
    bottom: 0;
    background: #fff;
    width: 100%;
    left: 0px;
    padding: 12px 0;
    padding-bottom: calc(10px + constant(safe-area-inset-bottom));
    padding-bottom: calc(10px + env(safe-area-inset-bottom));
    .left {
      position: absolute;
      top: calc(50% - 12px);
      transform: translateY(-50%);
      left: 0px;
      padding: 12px 15px;
      p {
        img {
          display: inline-block;
          vertical-align: middle;
          width: 20px;
          height: 20px;
          margin-right: 5px;
        }
        span {
          display: inline-block;
          vertical-align: middle;
          font-size: 15px;
          color: #222;
        }
        &:nth-child(2) {
          margin-top: 5px;
          font-size: 13px;
          color: #999;
          i {
            font-style: normal;
            color: #316ffe;
          }
        }
      }
    }
    .right {
      text-align: right;
      span {
        display: inline-block;
        border: 0.5px solid #ff503d;
        color: #ff503d;
        font-size: 16px;
        font-weight: 700;
        padding: 12px 50px;
        border-radius: 100px;
        margin-right: 15px;
      }
    }
  }
  .fixedImg {
    position: fixed;
    bottom: 100px;
    right: 15px;
    width: 40px;
    height: 40px;
  }
  ::v-deep .van-popup {
    &.relationshipWrap {
      .van-action-sheet__header {
        font-weight: 700;
        font-size: 16px;
        color: #333;
      }
      .wrap {
        margin-top: 6px;
        .textarea {
          border: 0.5px solid #e5e6eb;
          width: calc(100% - 50px);
          margin-left: 15px;
          border-radius: 4px;
          height: 96px;
          padding: 10px;
          font-size: 15px;
          &::placeholder {
            color: #999;
          }
        }
        .btn {
          padding: 20px 15px;
          span {
            display: inline-block;
            width: calc(50% - 7px);
            font-size: 16px;
            color: #999;
            text-align: center;
            padding: 10px 0;
            border-radius: 100px;
            border: 0.5px solid #cfcfcf;
            &:nth-child(2) {
              background: #316ffe;
              color: #fff;
              margin-left: 10px;
              border-color: #316ffe;
            }
          }
        }
      }
    }
  }
}
</style>