带有子节点的树状表的父节点拖动排序#Vue3#Sortable插件
使用Sortable插件这里要保证获取到的是父节点的下标,属性newDraggableIndex获取到的就是只有父节点的下标。设置子节点不能被拖动,最后在逐个调用接口进行数据库中顺序的更新。
<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",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>