带有子节点的树状表的父节点拖动排序#Vue3#Sortable插件
使用Sortable插件这里要保证获取到的是父节点的下标,属性newDraggableIndex获取到的就是只有父节点的下标。设置子节点不能被拖动,最后在逐个调用接口进行数据库中顺序的更新。
bash
<template>
<div class="app-container" v-loading="sortLoading">
<el-table v-if="refreshTable"
class="draggable"
v-loading="loading"
border
:data="menuList"
:row-key="getRowKey"
:default-expand-all="isExpandAll"
:tree-props="{ children: 'child', hasChildren: 'hasChildren' }">
<el-table-column prop="date" label="Date" width="180" />
<el-table-column prop="name" label="Name" width="180" />
<el-table-column prop="address" label="Address" />
</el-table>
</div>
</template>
<script lang="ts" setup>
import Sortable from "sortablejs";
function getRowKey(row: any) {
return row.id + row.type + row.key;
}
// 行拖拽
const rowDrag = function () {
// 要拖拽元素的父容器
const tbody = document.querySelector(
".draggable .el-table__body-wrapper tbody"
);
if (!tbody) return;
Sortable.create(tbody as HTMLElement, {
// 可被拖拽的子元素,设置只有父节点才能被拖动
draggable: ".draggable .el-table__row.el-table__row--level-0",
//设置只有子节点才能拖动,如果要设置父节点下的孩子节点它们兄弟之间拖动,拿到孩子节点的旧新坐标,然后根据旧新坐标判断是否属于同一个父节点,如果不属于就不执行拖动操作
//draggable: ".draggable .el-table__row.el-table__row--level-1",
onEnd(event) {
console.log("event", event);
//如果要实现子节点兄弟之间拖动,在这里获职旧坐标和新坐标,根据是否属于同一父结点决定是否执行一下换作
if (
event.oldDraggableIndex !== undefined &&
event.newDraggableIndex !== undefined
) {
const temp = [...menuList.value];
const currRow = temp.splice(event.oldDraggableIndex, 1)[0];
temp.splice(event.newDraggableIndex, 0, currRow);
console.log("temp", temp);
menuList.value = temp.map((item, i: number) => {
console.log("item", item);
const parentKey = `parent_${item.id}_${item.type}_${Date.now()}_${i}`;
const child = item.child.map((child: any, index: number) => {
const childrenKey = `children_${item.id}_${
item.type
}_${Date.now()}_${i}`;
return {
...child,
key: childrenKey,
};
});
return { ...item, child, key: parentKey };
});
console.log("menuList", menuList.value);
asyncSort();
}
},
});
};
const sortLoading = ref(false);
// 更新菜单排序
function asyncSort() {
sortLoading.value = true;
const list = [...menuList.value];
const apiList = list.map((item, i) => {
return updateMenu({ ...item, sort: i + 1, pid: "" });
});
Promise.all(apiList)
.then((res) => {
handleQuery();
console.log("更新排序成功");
})
.catch(() => {
console.log("部分更新错误");
})
.finally(() => (sortLoading.value = false));
}
const tableData = [
{ "id": "1711314432585502720",
"iD_Module": "1685955461712580611",
"code": "fixture",
"name": "治具管理",
"component": "/",
"path": "/fixture",
"type": 1,
"isOutSide": false,
"redirect": "/",
"alwaysShow": "Y",
"sort": 1,
"icon": "fixture",
"enable": "Y",
"showEnable": "Y",
"pid": null,
"createTime": "2023-10-09 17:35:30",
"updateTime": "2024-07-09 16:37:30",
"child": [
{
"id": "1711314714514034688",
"iD_Module": "1685955461712580611",
"code": "fixture_profile",
"name": "治具台账",
"component": "/",
"path": "profile",
"type": 2,
"isOutSide": false,
"redirect": "/",
"alwaysShow": "Y",
"sort": 1,
"icon": "minus",
"enable": "Y",
"showEnable": "Y",
"pid": "1711314432585502720",
"createTime": "2023-10-09 17:36:37",
"updateTime": "2023-10-10 19:20:18",
"child": null
},
{
"id": "1711314829744148480",
"iD_Module": "1685955461712580611",
"code": "fixture_inspect",
"name": "治具点检",
"component": "/",
"path": "inspect",
"type": 2,
"isOutSide": false,
"redirect": "/",
"alwaysShow": "Y",
"sort": 2,
"icon": "minus",
"enable": "Y",
"showEnable": "Y",
"pid": "1711314432585502720",
"createTime": "2023-10-09 17:37:04",
"updateTime": "2023-10-10 19:20:27",
"child": null
}
]
},
{
"id": "1724976315569934336",
"iD_Module": "1724975614743678976",
"code": "proposal",
"name": "提案改善",
"component": "/",
"path": "/proposal",
"type": 1,
"isOutSide": false,
"redirect": "/",
"alwaysShow": "Y",
"sort": 2,
"icon": "proposal",
"enable": "Y",
"showEnable": "Y",
"pid": null,
"createTime": "2023-11-16 10:22:56",
"updateTime": "2024-07-09 16:37:30",
"child": null,
},
]
</script>
原来我对sortable插件一无所知!!!总想着怎么把拖动的新旧下标算出来,真是没那金刚钻硬揽那瓷器活~