vue.draggable 拖拽

项目需求中,需要支持拖拽,即找到了vue.draggable,下面来说一下基本使用方法
1.首先需要安装它,官网地址 https://www.itxst.com/vue-draggable/tutorial.html
2.安装 npm i -S vuedraggable
3.基本教程请看官网例子
我这边是根据后端接口请求的数据进行布局与官网例子稍有不同
我们首先看一下成果
在这里插入图片描述
下面直接上代码+注释

<template>
  <div class="box">
    <!-- 操作 -->
    <div class="action-box">
      <a-icon type="unordered-list" class="icon-style" @click="$router.push('/business')" />
      <a-form-model layout="inline">
        <a-form-model-item>
          <a-input style="width: 240px" v-model="query.name" allowClear placeholder="商机名称" />
          <a-button type="primary" style="margin:0 0 0 10px;" @click="handleFilter()">查询</a-button>
        </a-form-model-item>
      </a-form-model>
      <a-icon type="funnel-plot" class="icon-style" title="筛选" @click="openTransfer()" />
    </div>

    <!-- 阶段 -->
    <div class="stage">
      <div v-for="(item,index) in boardList" :key="index">
        <div class="triangle">
          <span>{{item.stageName}}</span>
          <span class="triangle-right"></span>
        </div>
      </div>
    </div>

    <!-- 阶段内容 -->
    <div class="stage-content">
      <draggable v-for="(item,index) in boardList" v-model="boardList[index].businessOpportunity" :key="index" group="site" animation="300" dragClass="dragClass" ghostClass="ghostClass" chosenClass="chosenClass" @start="onStart(index)" @end="onEnd()" @add="onAdd(index)" class="context">
        <div v-for="val in item.businessOpportunity" :key="val.id" class="stage-box" @mousedown="handleMousedown(val)" :class="val.id ? '':'transparent'">
          <div>
            <div class="title">{{val.name ? val.name : '--'}}</div>
            <div class="font">{{val.currency ? val.currency : '--'}} {{val.salesAmount ? val.salesAmount : '--'}}</div>
          </div>
          <div style="margin-top:10px;">
            <div class="title">{{val.companyName ? val.companyName : '--'}}</div>
            <div class="font" v-show="val.id">联系人:{{val.contactsName ? val.contactsName : '--'}}</div>
            <div class="font" v-show="val.id">结单日期:{{val.statementDate ? val.statementDate : '--'}}</div>
          </div>
        </div>
      </draggable>
    </div>
    <a-modal v-model="visible" title="确定更新阶段?" @ok="handleOk" @cancel="cancel">
      <p>确定将<span class="state-name">{{stateinfoName}}</span>更新到<span class="state-name">{{stateName}}</span>阶段?</p>
    </a-modal>

    <!-- 筛选 -->
    <a-modal title="商机筛选" :footer="null" :visible="isShow" @cancel="close">
      <a-form-model :label-col="{ span: 5 }" :model="query" :wrapper-col="{ span: 12 }" ref="ruleForm">
        <a-form-model-item label="商机名称" prop="name">
          <a-input style="width:300px;" v-model="query.name" placeholder="请输入内容" />
        </a-form-model-item>

        <a-form-model-item label="公司名称" prop="companyName">
          <a-input style="width:300px;" v-model="query.companyName" placeholder="请输入内容" />
        </a-form-model-item>

        <a-form-model-item label="联系人" prop="contactsName">
          <a-input style="width:300px;" placeholder="请输入内容" v-model="query.contactsName" />
        </a-form-model-item>

      </a-form-model>
      <div class="modal">
        <a-button type="primary" @click="handleFilter()">高级筛选</a-button>
        <a-button @click="clear()">清空条件</a-button>
      </div>
    </a-modal>
  </div>
</template>
<script>
import draggable from 'vuedraggable'  //导入拖拽模块
import { selectBusinessOpportunityBoard, updateOpportunityStage } from '../../api/business'  //查询数据接口与拖拽编辑接口
export default {
  components: {
    draggable,  //导入组件
  },
  data () {
    return {
      boardList: [],  //接口返回的所有数据
      drag: false,  //是否开始拖拽
      query: {
        companyName: '', //公司名称
        contactsName: '', //联系人名称
        name: '', //商机名称
        type: 0, //用来区分是否为企业栏,0不是,1是

      },
      stateId: undefined, //每个阶段的id
      visible: false,  //确定事件弹窗
      stateName: '',  //阶段名称
      stateinfoName: '',  //转移的信息名称
      startIndex: undefined,  //阶段的index,也可以说是 每一列的index
      isShow: false  //筛选弹窗
    };
  },
  methods: {
    // 获取商机阶段信息
    getBoardList () {
      selectBusinessOpportunityBoard(this.query).then(res => {
        this.boardList = res.data //直接将数据赋值 给 boardList 
      })
    },
    	
    /* 鼠标按下事件 */
    handleMousedown (info) {
      if (info.id) {
        this.stateinfoId = info.id  //拿到拖拽信息的id,拖拽编辑请求接口用
        this.stateinfoName = info.name  //拿到拖拽信息的名称,确认弹窗时用
      } else {
        return
      }
    },
    //开始拖拽事件
    onStart (index) {
      this.drag = true; //开启拖拽
      this.startIndex = index  //保存拖拽的index,下面要用
    },
    
    //新增事件,如果有新增 拿到新增的index,
    //获取 this.boardList[index].id 阶段id
    //获取  this.boardList[index].stageName 阶段的名称
    onAdd (index) {
      this.stateId = this.boardList[index].id  //拿到阶段id,拖拽编辑请求接口用
      this.stateName = this.boardList[index].stageName //拿到阶段名称,确认弹窗时用
      this.visible = true  //插入的时候显示弹窗,询问是否确定更改阶段
    },

    //拖拽结束事件
    onEnd () {
      this.drag = false //关闭拖拽
    },

    /* 确定更新 ,弹窗确定按钮*/  
    handleOk () {
    //请求更新编辑
      updateOpportunityStage({ opportunityStageId: this.stateId, id: this.stateinfoId }).then(res => {
        console.log(res)
        if (res.code == 200) {
          this.visible = false  //关闭弹窗
          this.getBoardList()  //编辑后,重新请求查询数据接口
          return this.$message.success(res.message)
        }
      })
    },

    /* 弹窗取消保存 */
    cancel () {
      this.stateName = ''
      this.getBoardList()  //确认弹窗取消按钮,重新查询数据
    },



    /* 关闭弹窗 */
    close () {
      this.isShow = false
    },
    
    /* 打开弹窗 */
    openTransfer () {
      this.isShow = true
    },
    
      /* 筛选 */
    handleFilter () {
      this.getBoardList(this.query)
      console.log('父组件拿到的信息', this.query);
      this.isShow = false
    },
    clear () {
      this.$refs.ruleForm.resetFields();
    }
  },
  mounted () {
    this.getBoardList()
  },
};
css
</script>

//css保留了,为了复制直接看到结果
<style lang="scss" scoped>
.box {
  .action-box {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    padding-bottom: 10px;
    .icon-style {
      margin-right: 15px;
      cursor: pointer;
      :hover {
        color: #1890ff;
      }
    }
  }
}
.stage {
  display: flex;
  justify-content: space-between;
  background-color: #3894ff;
  height: 60px;
  border-radius: 60px;
  align-items: center;
  div {
    flex: 1;
    text-align: center;
    color: #fff;
    font-size: 16px;
  }
}

.stage-content {
  box-sizing: border-box;
  display: flex;
  justify-content: space-around;
  .stage-box {
    min-width: 200px;
    min-height: 150px;
    box-sizing: border-box;
    border: 1px #ccc solid;
    padding: 5px 10px;
    margin-top: 10px;
  }
  .title {
    font-size: 14px;
    font-weight: 600;
    color: #3894ff;
    font-family: SourceHanSansSC-regular;
    padding: 0;
  }
  .font {
    font-size: 14px;
    color: #8e8e93;
    font-family: SourceHanSansSC-regular;
  }
}
.triangle {
  position: relative;
  height: 48px;
  line-height: 48px;
  padding-right: 30px;
  .triangle-right {
    box-sizing: border-box;
    position: absolute;
    width: 48px;
    height: 48px;
    background-color: transparent;
    border-top: 5px #fff solid;
    border-right: 5px #fff solid;
    left: -58px;
    transform: rotate(45deg);
  }
}
.line {
  min-height: 680px;
  width: 1px;
  background-color: #ccc;
  margin: 0 10px;
}
.context {
  margin-right: 10px;
  position: relative;
}
.context::after {
  content: " ";
  display: block;
  min-height: 100%;
  width: 1px;
  background-color: #ccc;
  position: absolute;
  right: -35%;
  top: 10px;
}

.ghostClass {
  background-color: blue !important;
}
.chosenClass {
  background-color: #3895ff52 !important;
  opacity: 1 !important;
}
.dragClass {
  background-color: rgba(0, 0, 0, 0.274) !important;
  opacity: 1 !important;
  box-shadow: none !important;
  outline: none !important;
  background-image: none !important;
}
.itxst {
  margin: 10px;
}
.title {
  padding: 6px 12px;
}
.col {
  width: 40%;
  flex: 1;
  padding: 10px;
  border: solid 1px #eee;
  border-radius: 5px;
  float: left;
}
.col + .col {
  margin-left: 10px;
}

.item {
  padding: 6px 12px;
  margin: 0px 10px 0px 10px;
  border: solid 1px #eee;
  background-color: #f1f1f1;
}
.item:hover {
  background-color: #fdfdfd;
  cursor: move;
}
.item + .item {
  border-top: none;
  margin-top: 6px;
}
.state-name {
  margin: 0 5px;
  color: #3894ff;
  // font-weight: bold;
}
.transparent {
  color: transparent !important;
  border: transparent !important;
}
.modal {
  display: flex;
  margin-left: 30px;
  :nth-child(2) {
    margin-left: 10px;
  }
}
</style>

提供一下假数据,可以自行修改

 boardList: [
        {
          stageName: "进行中一",
          id: 21,
          businessOpportunity: [
            {
              companyName: "公司",
              contactsName: "luo",
              createdBy: "rojie",
              currency: "CNY",
              custumerId: 11,
              exchangeRate: "1",
              id: 17,
              name: "测试商机",
              opportunityStageId: 22,
              salesAmount: 100,
              statementDate: "2022-03-02"
            },
          ]
        },
        {
          stageName: "进行中二",
          id: 22,
          businessOpportunity: [
            {
              companyName: "公司",
              contactsName: "luo",
              createdBy: "rojie",
              currency: "CNY",
              custumerId: 12,
              exchangeRate: "1",
              id: 12,
              name: "测试商机",
              opportunityStageId: 22,
              salesAmount: 100,
              statementDate: "2022-03-02"
            },
          ]
        },
        {
          stageName: "进行中三",
          id: 23,
          businessOpportunity: [
            {
              companyName: "公司",
              contactsName: "luo",
              createdBy: "rojie",
              currency: "CNY",
              custumerId: 13,
              exchangeRate: "1",
              id: 17,
              name: "测试商机",
              opportunityStageId: 22,
              salesAmount: 100,
              statementDate: "2022-03-02"
            },
          ]
        },
        {
          stageName: "赢单一",
          id: 24,
          businessOpportunity: [
            {
              companyName: "公司",
              contactsName: "luo",
              createdBy: "rojie",
              currency: "CNY",
              custumerId: 16,
              exchangeRate: "1",
              id: 13,
              name: "测试商机",
              opportunityStageId: 22,
              salesAmount: 100,
              statementDate: "2022-03-02"
            },
          ]
        },
        {
          stageName: "输单",
          id: 26,
          businessOpportunity: [
            {
              companyName: "公司",
              contactsName: "luo",
              createdBy: "rojie",
              currency: "CNY",
              custumerId: 16,
              exchangeRate: "1",
              id: 14,
              name: "测试商机",
              opportunityStageId: 22,
              salesAmount: 100,
              statementDate: "2022-03-02"
            },
          ]
        },
      ], 
GitHub 加速计划 / vu / Vue.Draggable
19.97 K
2.89 K
下载
SortableJS/Vue.Draggable: Vue.Draggable 是 Sortable.js 的 Vue.js 封装组件,提供了拖放排序功能,可以在 Vue 应用中轻松实现列表元素的可拖拽重排。
最近提交(Master分支:3 个月前 )
431db153 - 2 年前
017ab498 - 3 年前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐