最近遇到一个需求,vue项目中的表现需要拖拽排序,并且表格中标为电子凭证的行是默认排在最底部,其他数据可以拖拽排序。
表格html
<cm-table
ref="scanned-table"
class="table-header-sty scanned-table"
:data="tableList"
border
highlight-current-row
current-row-key="id"
:row-class-name="tableRowClassName"
v-loading.lock="loading">
<cm-table-column label="序号" align="center" width="80">
<template slot-scope="scope">
<span>{{scope.row[isElectronicProp] === 'Y' ? '' : scope.row['serialNum']}}</span>
</template>
</cm-table-column>
<template v-for="(item, index) in tableHeader">
<template v-if="item.label === '是否为电子凭证'">
<cm-table-column :label="item.label" align="center" :key="index">
<template slot-scope="scope">
<span>{{scope.row[isElectronicProp] | formatIsElectric}}</span>
</template>
</cm-table-column>
</template>
<template v-else>
<cm-table-column :label="item.label" :prop="item.prop" align="center" :key="index"></cm-table-column>
</template>
</template>
<cm-table-column label="操作人" prop="updatedUser" align="center"></cm-table-column>
<cm-table-column label="操作" align="center">
<template slot-scope="scope">
<cm-button type="link" @click="handlePreview(scope.row)">一键预览</cm-button>
<cm-button type="link" @click="handleDelete(scope.row)">删除</cm-button>
</template>
</cm-table-column>
</cm-table>
设置拖拽
// 设置表格row的class
tableRowClassName({ row }) {
if (row[this.isElectronicProp] === 'Y') {
return "disabled"; // 返回不可拖拽的类名
}
return "can-move";
}
mounted中调用该函数
initSortable() {
const tbody = this.$refs['scanned-table'].$el.querySelector('.cm-table__body > tbody')
const _this = this
// 创建拖拽实例
let dragTable = Sortable.create(tbody, {
animation: 150, //动画
// handle: ".move", //指定拖拽目标,点击此目标才可拖拽元素
filter: ".disabled", //指定不可拖动的类名(el-table中可通过row-class-name设置行的class)
// 开始拖动事件
onStart: (e) => {
// console.log(e, "开始拖动");
},
// 结束拖动事件
onEnd: async (e) => {
console.log("结束拖动", `拖动前索引${e.oldIndex}---拖动后索引${e.newIndex}`);
const oldIndex = e.oldIndex // 拖拽前索引
const newIndex = e.newIndex // 拖拽后索引
const minIndex = oldIndex < newIndex ? oldIndex : newIndex // 最小索引
const maxIndex = oldIndex > newIndex ? oldIndex : newIndex // 最大索引
const oldSerialNum = _this.tableList[oldIndex].serialNum // 拖拽前数据的序号
const newSerialNum = _this.tableList[newIndex].serialNum // 拖拽后数据的序号
let minSerialNum = oldSerialNum < newSerialNum ? oldSerialNum : newSerialNum // 最小序号
let maxSerialNum = oldSerialNum > newSerialNum ? oldSerialNum : newSerialNum // 最大序号
//拖拽排序
const copyList = cloneDeep(_this.tableList)
copyList.splice(newIndex, 0, copyList.splice(oldIndex, 1)[0])
const updateList = []
//遍历出新老索引区间的数据
map(copyList, (item, index) => {
if(minIndex <= index && index <= maxIndex) {
let obj = {}
let currentSerialNum = maxSerialNum--
const row = find(_this.tableList, i => {
return i.archivesStringId === item.archivesStringId
})
row.serialNum = currentSerialNum
obj.archivesId = item.archivesStringId
obj.fileCode = item.fileCode
obj.serialNum = currentSerialNum
updateList.push(obj)
}
})
const { success, data, message } = await battchUpdateSerialNum(updateList)
if(success) {
console.log('排序成功')
// _this.getList()
} else {
_this.$message.error(message)
}
},
// 拖拽移动的时候
onMove(evt, originalEvent) {
console.log(evt)
const dragged = evt.dragged // 被拖拽的对象
const related = evt.related // 被替换的对象
// DOMTokenList 接口表示一组空格分隔的符号, 如由 Element.classList
if(dragged.classList.contains('disabled') || related.classList.contains('disabled')) return false
return true
},
// 列表内元素顺序更新的时候触发
onUpdate: function (/**Event*/evt) {
// console.log(_this.tableList, 'update')
},
});
}