【ant-design-vue】实现table的拖拽排序(拖拽行和伸缩列):

1.效果:

拖拽前:
在这里插入图片描述
拖拽后:
在这里插入图片描述

在这里插入图片描述

2.实现:
<template>
  <a-card :bordered="false">
    <a-table bordered :columns="columns" :data-source="data" :customRow="customRow" :pagination="pagination"
      @change="tableChange">
      <template v-slot:action>
        <a href="javascript:;" style="cursor:move">拖拽排序</a>
      </template>
    </a-table>
  </a-card>
</template>

<script>
import Vue from "vue";
import VueDraggableResizable from "vue-draggable-resizable";
// 可拖拽表格
// "vue-draggable-resizable": "2.1.0"  //=>需要的话记得安装
// "ant-design-vue": "^1.5.5"
Vue.component("vue-draggable-resizable", VueDraggableResizable);

import { mapState } from 'vuex';
import { mixinDevice } from '@/utils/mixin'
import '@/assets/less/TableExpand.less'
import { getAction, deleteAction, putAction, putActions, postAction, postActions, httpAction, downFile, uploadAction } from '@/api/manage' //二次封装的接口方法


export default {
  name: "queueInfoList",
  mixins: [mixinDevice],
  data() {
    // this.components = {//实现伸缩列=>不需要的话a-table去除:components="components"
    //   header: {
    //     cell: (h, props, children) => {
    //       const { key, ...restProps } = props;
    //       console.log("ResizeableTitle", key);
    //       const col = this.columns.find(col => {
    //         const k = col.dataIndex || col.key;
    //         return k === key;
    //       });

    //       if (!col || !col.width) {
    //         return h("th", { ...restProps }, [...children]);
    //       }

    //       const dragProps = {
    //         key: col.dataIndex || col.key,
    //         class: "table-draggable-handle",
    //         attrs: {
    //           w: 10,
    //           x: col.width,
    //           z: 1,
    //           axis: "x",
    //           draggable: true,
    //           resizable: false
    //         },
    //         on: {
    //           dragging: (x, y) => {
    //             console.log(x, y);
    //             col.width = Math.max(x, 1);
    //           }
    //         }
    //       };
    //       const drag = h("vue-draggable-resizable", { ...dragProps });
    //       return h("th", { ...restProps, class: "resize-table-th" }, [
    //         ...children,
    //         drag
    //       ]);
    //     }
    //   }
    // };
    return {
      sourceObj: null,
      targetObj: null,
      dragStartIndex: '',

      queryParam: {
        bankPositon: '',//装卸位
        carNumber: '',//车号
        varietyName: '',//货品
        deptId: '',
        stationId: '',
        pageNo: '1',
        pageSize: '10',
        isInQueue: '1',//	是否排队中。1=是,0=},
      url: {
        list: '/kd/queueInfo/list',
        queueInfoSort: "/kd/queueInfo/editSort",// 排队列表-拖拽排序
      },
      columns: [
        {
          title: "序号",
          align: "center",
          dataIndex: "queueNo",
          sorter: true,
        },
        {
          title: "id",
          align: "center",
          dataIndex: "id",
          sorter: true,
        },
        {
          title: "库位",
          align: "center",
          dataIndex: "bankPositon",
          sorter: true,
        },
        {
          title: "货品",
          align: "center",
          dataIndex: "varietyName",
          sorter: true,
        },
        {
          title: "车牌号码",
          align: "center",
          dataIndex: "carNumber",
          sorter: true,
        },
        {
          title: "状态",
          sorter: true,
          align: "center",
          dataIndex: "status",
          // status	状态(1:等待装车,2正在装车,3装车完成)
          customRender: function (text) {
            return !text ? "" : text == 1 ? '等待装车' : text == 2 ? '正在装车' : '装车完成'
          }
        },
        {
          title: "排队号",
          align: "center",
          dataIndex: "sortNo",
          sorter: true,
        },
        {
          title: "操作",
          key: "action",
          align: "center",
          fixed: "right",
          width: 147,
          scopedSlots: { customRender: "action" }
        }
      ],
      data: [],
      tableLoading: false,//防止快速点击时,没获取到新数据
      pagination: {
        current: 1,
        pageSize: 10, // 默认每页显示数量
        total: 0,
        showSizeChanger: true, // 显示可改变每页数量
        pageSizeOptions: ['10', '20', '30', '50', '100'], // 每页数量选项
        showTotal: total => `共 ${total}`, // 显示总数
        showSizeChange: (current, pageSize) => this.pageSize = pageSize, // 改变每页数量时更新显示
      },
    };
  },
  computed: {
    ...mapState(['bdidInfo']),
  },
  watch: {
    // 监听机构和磅点bdidInfo存储信息的变化
    bdidInfo: {
      handler(value) {
        if (value != null) {
          this.queryParam.deptId = value.deptId
          this.queryParam.stationId = value.stationId
          this.searchQuery()
        }
      },
      immediate: true,
    }
  },
  methods: {
    // 搜索列表数据
    searchQuery() {
      const that = this
      this.tableLoading = true
      let param = { ...this.queryParam }
      param.pageNo = this.pagination.current
      param.pageSize = this.pagination.pageSize
      getAction(this.url.list, param).then(res => {
        if (res.success) {
          that.data = res.result.records
          // this.data.forEach((res, index) => {//测试=>这里是重复时,让排队号变成1,2,3,4,...
          //   res.sortNo = index + 1
          // })
          that.pagination.total = res.result.total
        } else {
          this.$message.error(res.message || res.msg)
        }
        setTimeout(() => {
          that.tableLoading = false
        }, 200)
      })
    },
    // 重置
    searchReset() {
      this.pagination.current = 1
      this.pagination.pageSize = 10
      this.queryParam.carNumber = ''
      this.queryParam.bankPositon = ''
      this.queryParam.varietyName = ''
      this.searchQuery()
    },
    // table的change事件
    tableChange(e) {
      const { current, pageSize } = e;
      this.pagination.current = current;
      this.pagination.pageSize = pageSize;
      this.searchQuery();
    },
    // 拖动排序
    customRow(record, index) {
      const that = this
      return {
        // FIXME: draggable: true 不生效还不晓得是什么原因,先使用鼠标移入事件设置目标行的draggable属性
        props: {
          // draggable: 'true'
        },
        style: {
          cursor: "move"
        },
        on: {
          // 鼠标移入
          mouseenter: event => {
            // 兼容IE
            var ev = event || window.event;
            ev.target.draggable = true;
          },
          // 开始拖拽
          dragstart: event => {
            var ev = event || window.event; // 兼容IE
            ev.stopPropagation();// 阻止冒泡
            
            // 得到源目标数据
            that.dragStartIndex = index;
            that.sourceObj = record;
          },
          // 拖动元素经过的元素
          dragover: event => {
            var ev = event || window.event;
            ev.preventDefault();// 阻止默认行为
          },
          // 鼠标松开
          drop: event => {
            var ev = event || window.event;
            ev.stopPropagation(); // 阻止冒泡
            
            // 得到目标数据
            that.targetObj = record;
            // let _data = JSON.parse(JSON.stringify(that.data));
            // _data[that.dragStartIndex] = that.data[index];
            // _data[index] = that.data[that.dragStartIndex];
            // that.data = _data;
            // console.log(that.data)
            // console.log(that.sourceObj, '源数据')
            that.getDragData(that.sourceObj, that.targetObj)
          }
        }
      };
    },
    // 获取拖拽的数据=>拖拽的接口
    getDragData(sourceObj, targetObj) {
      const that = this
      // console.log(sourceObj, targetObj)
		
	 if (that.data && that.data.length > 0) {//防止快速点击时,获取到的数据不是最新的
        that.data.forEach(item => {
          if (item.id == sourceObj.id && item.sortNo != sourceObj.sortNo) {
            // that.sourceObj = item;
            // console.log(item.sortNo, sourceObj.sortNo, '排队号不一致')
            that.searchQuery()
            return
          }
        })
      }

      if (sourceObj.id == targetObj.id || sourceObj.sortNo == targetObj.sortNo) {//防止快速点击时,获取到的数据不是最新的
        this.searchQuery()
        return
      }
      let param = {
        "queueInfo": [
          {
            id: sourceObj.id,
            sortNo: targetObj.sortNo,
          }, {
            id: targetObj.id,
            sortNo: sourceObj.sortNo,
          }
        ]
      }
      // console.log(sourceObj.sortNo + '-' + targetObj.sortNo, that.dragStartIndex)
      
      putAction(this.url.queueInfoSort, param).then(res => {
        if (res.success) {
          that.tableLoading = true //开启动画=>防止快速点击时,获取到的数据不是最新的
          that.searchQuery()
          that.$message.success(res.message || res.msg)
        } else {
          this.$message.error(res.message || res.msg)
        }
      })
    },
  }
};
</script>


<style scoped>
.resize-table-th {
  position: relative;
}

.table-draggable-handle {
  /* width: 10px !important; */
  height: 100% !important;
  left: auto !important;
  right: -5px;
  cursor: col-resize;
  touch-action: none;
  border: none;
}
</style>
3.出现的问题:
1.拖拽过程中,出现排队号重复的问题(后台不重复)=>原因:获取列表数据的方法还没完成,连续两次运行拖拽的接口

2.拖拽过程中,出现排队号数据过时的问题=>没有获取到最新的数据
4.初始拖拽版本:
<template>
  <a-table bordered :columns="columns" :components="components" :data-source="data" :customRow="customRow">
    <template v-slot:action>
      <a href="javascript:;"></a>
    </template>
  </a-table>
</template>

<script>
import Vue from "vue";
import VueDraggableResizable from "vue-draggable-resizable";
// 可拖拽表格
// "vue-draggable-resizable": "2.1.0"
// "ant-design-vue": "^1.5.5"
Vue.component("vue-draggable-resizable", VueDraggableResizable);
var that;
export default {
  name: "App",
  data() {
    this.components = {
      header: {
        cell: (h, props, children) => {
          const { key, ...restProps } = props;
          // console.log("ResizeableTitle", key);
          const col = this.columns.find(col => {
            const k = col.dataIndex || col.key;
            return k === key;
          });

          if (!col || !col.width) {
            return h("th", { ...restProps }, [...children]);
          }

          const dragProps = {
            key: col.dataIndex || col.key,
            class: "table-draggable-handle",
            attrs: {
              w: 10,
              x: col.width,
              z: 1,
              axis: "x",
              draggable: true,
              resizable: false
            },
            on: {
              dragging: (x, y) => {
                console.log(x, y);
                col.width = Math.max(x, 1);
              }
            }
          };
          const drag = h("vue-draggable-resizable", { ...dragProps });
          return h("th", { ...restProps, class: "resize-table-th" }, [
            ...children,
            drag
          ]);
        }
      }
    };
    return {
      data: [
        {
          key: 0,
          date: "2018-02-11",
          amount: 120,
          type: "income",
          note: "transfer"
        },
        {
          key: 1,
          date: "2018-03-11",
          amount: 243,
          type: "income",
          note: "transfer"
        },
        {
          key: 2,
          date: "2018-04-11",
          amount: 98,
          type: "income",
          note: "transfer"
        }
      ],
      columns: [
        {
          title: "Date",
          dataIndex: "date",
          width: 200
        },
        {
          title: "Amount",
          dataIndex: "amount",
          width: 100
        },
        {
          title: "Type",
          dataIndex: "type",
          width: 100
        },
        {
          title: "Note",
          dataIndex: "note",
          width: 100
        },
        {
          title: "Action",
          key: "action",
          scopedSlots: { customRender: "action" }
        }
      ],
      sourceObj: "",
      targetObj: '',
      // 拖动排序
      customRow(record, index) {
        return {
          // FIXME: draggable: true 不生效还不晓得是什么原因,先使用鼠标移入事件设置目标行的draggable属性
          props: {
            // draggable: 'true'
          },
          style: {
            cursor: "pointer"
          },
          on: {
            // 鼠标移入
            mouseenter: event => {
              // 兼容IE
              var ev = event || window.event;
              ev.target.draggable = true;
            },
            // 开始拖拽
            dragstart: event => {
              // 兼容IE
              var ev = event || window.event;
              // 阻止冒泡
              ev.stopPropagation();
              // 得到源目标数据
              // console.log(that);
              that.dragStartIndex = index;
              that.sourceObj = record;
            },
            // 拖动元素经过的元素
            dragover: event => {
              // 兼容 IE
              var ev = event || window.event;
              // 阻止默认行为
              ev.preventDefault();
            },
            // 鼠标松开
            drop: event => {
              // 兼容IE
              var ev = event || window.event;
              // 阻止冒泡
              ev.stopPropagation();
              // 得到目标数据
              that.targetObj = record;
              // 注意=>这里会调换数据,记得注释
              let _data = JSON.parse(JSON.stringify(that.data));
              _data[that.dragStartIndex] = that.data[index];
              _data[index] = that.data[that.dragStartIndex];
              that.data = _data;
              console.log(that.data, '拖拽后的数据')
              console.log(that.sourceObj, '源数据')
              console.log(that.targetObj, '目标数据')
            }
          }
        };
      }
    };
  },
  mounted() {
    that = this;
  },
  methods: {

  }
};
</script>
<style>
.resize-table-th {
  position: relative;
}

.table-draggable-handle {
  /* width: 10px !important; */
  height: 100% !important;
  left: auto !important;
  right: -5px;
  cursor: col-resize;
  touch-action: none;
  border: none;
}
</style>
5.相关知识:

在这里插入图片描述

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
实现两个table相互拖拽排序可以使用ant-design-vue的`<a-transfer>`组件。具体实现步骤如下: 1. 使用`<a-transfer>`组件分别渲染两个table,设置`:data-source`和`:target-keys`属性。 ``` <a-transfer :data-source="leftTableData" :target-keys="leftSelectedKeys" :render="item => item.title" :operations="['>', '<']" :list-style="{'width': '200px'}" ></a-transfer> <a-transfer :data-source="rightTableData" :target-keys="rightSelectedKeys" :render="item => item.title" :operations="['>', '<']" :list-style="{'width': '200px'}" ></a-transfer> ``` 2. 监听`change`事件,实现数据的拖拽操作。 ``` <a-transfer :data-source="leftTableData" :target-keys="leftSelectedKeys" :render="item => item.title" :operations="['>', '<']" :list-style="{'width': '200px'}" @change="handleTransferChange" ></a-transfer> <a-transfer :data-source="rightTableData" :target-keys="rightSelectedKeys" :render="item => item.title" :operations="['>', '<']" :list-style="{'width': '200px'}" @change="handleTransferChange" ></a-transfer> ``` ``` methods: { handleTransferChange (nextTargetKeys, direction, moveKeys) { const { leftTableData, rightTableData } = this if (direction === 'right') { const moveData = leftTableData.filter(item => moveKeys.includes(item.key)) this.rightTableData = rightTableData.concat(moveData) this.leftTableData = leftTableData.filter(item => !moveKeys.includes(item.key)) } else if (direction === 'left') { const moveData = rightTableData.filter(item => moveKeys.includes(item.key)) this.leftTableData = leftTableData.concat(moveData) this.rightTableData = rightTableData.filter(item => !moveKeys.includes(item.key)) } } } ``` 3. 根据需要自定义样式和数据源。 完整代码示例: ``` <template> <div> <a-transfer :data-source="leftTableData" :target-keys="leftSelectedKeys" :render="item => item.title" :operations="['>', '<']" :list-style="{'width': '200px'}" @change="handleTransferChange" ></a-transfer> <a-transfer :data-source="rightTableData" :target-keys="rightSelectedKeys" :render="item => item.title" :operations="['>', '<']" :list-style="{'width': '200px'}" @change="handleTransferChange" ></a-transfer> </div> </template> <script> export default { data () { return { leftTableData: [ { key: '1', title: '项目1' }, { key: '2', title: '项目2' }, { key: '3', title: '项目3' }, { key: '4', title: '项目4' } ], rightTableData: [ { key: '5', title: '项目5' }, { key: '6', title: '项目6' }, { key: '7', title: '项目7' }, { key: '8', title: '项目8' } ], leftSelectedKeys: [], rightSelectedKeys: [] } }, methods: { handleTransferChange (nextTargetKeys, direction, moveKeys) { const { leftTableData, rightTableData } = this if (direction === 'right') { const moveData = leftTableData.filter(item => moveKeys.includes(item.key)) this.rightTableData = rightTableData.concat(moveData) this.leftTableData = leftTableData.filter(item => !moveKeys.includes(item.key)) } else if (direction === 'left') { const moveData = rightTableData.filter(item => moveKeys.includes(item.key)) this.leftTableData = leftTableData.concat(moveData) this.rightTableData = rightTableData.filter(item => !moveKeys.includes(item.key)) } } } } </script> ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sun Peng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值