|
|
@@ -8,7 +8,7 @@
|
|
|
</div>
|
|
|
<a-tree :tree-data="classList" :field-names="treeFieldNames" :selected-keys="selectedClassKeys"
|
|
|
:expanded-keys="expandedKeys" :expand-action="false" :autoExpandParent="true" @select="onClassSelect"
|
|
|
- @expand="onTreeExpand" class="custom-tree">
|
|
|
+ @expand="onTreeExpand" class="custom-tree" draggable @dragenter="onDragEnter" @drop="onDrop">
|
|
|
<template #title="node">
|
|
|
<div class="tree-node-content" :style="{ width: 240 - node.level * 21 + 'px' }">
|
|
|
<!-- 每少一级别,宽度减少21px -->
|
|
|
@@ -436,6 +436,18 @@ const getClassList = async () => {
|
|
|
}
|
|
|
}
|
|
|
})
|
|
|
+
|
|
|
+ // 为每个节点添加层级字段
|
|
|
+ const addLevelToNodes = (nodes, level = 1) => {
|
|
|
+ nodes.forEach(node => {
|
|
|
+ node.level = level
|
|
|
+ if (node.children && node.children.length > 0) {
|
|
|
+ addLevelToNodes(node.children, level + 1)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ addLevelToNodes(res.data)
|
|
|
classList.value = res.data
|
|
|
|
|
|
// 获取所有节点的key用于默认展开(只展开一级分类)
|
|
|
@@ -462,6 +474,214 @@ const onTreeExpand = (expandedKeysArray) => {
|
|
|
expandedKeys.value = expandedKeysArray
|
|
|
}
|
|
|
|
|
|
+// 拖动进入事件处理
|
|
|
+const onDragEnter = (info) => {
|
|
|
+ console.log('拖动进入:', info)
|
|
|
+ // 可以在这里处理展开节点等逻辑
|
|
|
+}
|
|
|
+
|
|
|
+// 拖动放置事件处理
|
|
|
+const onDrop = (info) => {
|
|
|
+ console.log('放置:', info)
|
|
|
+ const dropKey = info.node.key
|
|
|
+ const dragKey = info.dragNode.key
|
|
|
+ const dropPos = info.node.pos.split('-')
|
|
|
+ const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1]) // the drop position relative to the drop node, inside 0, top -1, bottom 1
|
|
|
+
|
|
|
+ const loop = (data, key, callback) => {
|
|
|
+ for (let i = 0; i < data.length; i++) {
|
|
|
+ if (data[i].sa_fadclassid === key) {
|
|
|
+ return callback(data[i], i, data)
|
|
|
+ }
|
|
|
+ if (data[i].children) {
|
|
|
+ loop(data[i].children, key, callback)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const data = JSON.parse(JSON.stringify(classList.value))
|
|
|
+
|
|
|
+ // Find dragObject and its original position
|
|
|
+ let dragObj
|
|
|
+ let originalParentArr
|
|
|
+ let originalIndex
|
|
|
+
|
|
|
+ loop(data, dragKey, (item, index, arr) => {
|
|
|
+ originalParentArr = arr
|
|
|
+ originalIndex = index
|
|
|
+ dragObj = item
|
|
|
+ })
|
|
|
+
|
|
|
+ // 层级检查和处理
|
|
|
+ let isValidDrop = true
|
|
|
+ let dropSuccess = false
|
|
|
+
|
|
|
+ // 先从数据中移除拖动的节点
|
|
|
+ if (originalParentArr && originalIndex !== undefined) {
|
|
|
+ originalParentArr.splice(originalIndex, 1)
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!info.dropToGap) {
|
|
|
+ // Drop on the content (as child)
|
|
|
+ loop(data, dropKey, (item) => {
|
|
|
+ // 检查拖动节点的层级是否比目标节点低一级
|
|
|
+ if (dragObj.level !== item.level + 1) {
|
|
|
+ // 特殊处理:一级分类拖到二级分类上
|
|
|
+ if (dragObj.level === 1 && item.level === 2) {
|
|
|
+ // 找到二级分类的父级一级分类
|
|
|
+ let parentNode
|
|
|
+ let parentArr
|
|
|
+ let parentIndex
|
|
|
+
|
|
|
+ // 查找父级一级分类
|
|
|
+ const findParent = (nodes) => {
|
|
|
+ for (let i = 0; i < nodes.length; i++) {
|
|
|
+ if (nodes[i].children) {
|
|
|
+ for (let j = 0; j < nodes[i].children.length; j++) {
|
|
|
+ if (nodes[i].children[j].sa_fadclassid === item.sa_fadclassid) {
|
|
|
+ parentNode = nodes[i]
|
|
|
+ parentArr = nodes
|
|
|
+ parentIndex = i
|
|
|
+ return true
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (findParent(nodes[i].children)) {
|
|
|
+ return true
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false
|
|
|
+ }
|
|
|
+
|
|
|
+ findParent(data)
|
|
|
+
|
|
|
+ if (parentArr && parentIndex !== undefined) {
|
|
|
+ // 将一级分类插入到父级一级分类的后面
|
|
|
+ parentArr.splice(parentIndex + 1, 0, dragObj)
|
|
|
+ dropSuccess = true
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ isValidDrop = false
|
|
|
+ utils.message({ msg: '失败' }, '分类层级不能变更', 'error')
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ item.children = item.children || []
|
|
|
+ // where to insert. New item was inserted to the start of the array in this example, but can be anywhere
|
|
|
+ item.children.unshift(dragObj)
|
|
|
+ dropSuccess = true
|
|
|
+ }
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ let ar = []
|
|
|
+ let i
|
|
|
+ let targetNode
|
|
|
+ loop(data, dropKey, (item, index, arr) => {
|
|
|
+ ar = arr
|
|
|
+ i = index
|
|
|
+ targetNode = item
|
|
|
+ })
|
|
|
+
|
|
|
+ // 检查拖动节点的层级是否与目标节点相同
|
|
|
+ if (dragObj.level !== targetNode.level) {
|
|
|
+ // 特殊处理:一级分类拖到二级分类间隙
|
|
|
+ if (dragObj.level === 1 && targetNode.level === 2) {
|
|
|
+ // 找到二级分类的父级一级分类
|
|
|
+ let parentNode
|
|
|
+ let parentArr
|
|
|
+ let parentIndex
|
|
|
+
|
|
|
+ // 查找父级一级分类
|
|
|
+ const findParent = (nodes) => {
|
|
|
+ for (let i = 0; i < nodes.length; i++) {
|
|
|
+ if (nodes[i].children) {
|
|
|
+ for (let j = 0; j < nodes[i].children.length; j++) {
|
|
|
+ if (nodes[i].children[j].sa_fadclassid === targetNode.sa_fadclassid) {
|
|
|
+ parentNode = nodes[i]
|
|
|
+ parentArr = nodes
|
|
|
+ parentIndex = i
|
|
|
+ return true
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (findParent(nodes[i].children)) {
|
|
|
+ return true
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false
|
|
|
+ }
|
|
|
+
|
|
|
+ findParent(data)
|
|
|
+
|
|
|
+ if (parentArr && parentIndex !== undefined) {
|
|
|
+ // 将一级分类插入到父级一级分类的后面
|
|
|
+ parentArr.splice(parentIndex + 1, 0, dragObj)
|
|
|
+ dropSuccess = true
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ isValidDrop = false
|
|
|
+ utils.message({ msg: '失败' }, '分类层级不能变更', 'error')
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (dropPosition === -1) {
|
|
|
+ // Drop on the top of the drop node
|
|
|
+ ar.splice(i, 0, dragObj)
|
|
|
+ } else {
|
|
|
+ // Drop on the bottom of the drop node
|
|
|
+ ar.splice(i + 1, 0, dragObj)
|
|
|
+ }
|
|
|
+ dropSuccess = true
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果放置失败,将节点放回原来的位置
|
|
|
+ if (!dropSuccess && originalParentArr && originalIndex !== undefined) {
|
|
|
+ originalParentArr.splice(originalIndex, 0, dragObj)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新分类列表
|
|
|
+ classList.value = data
|
|
|
+
|
|
|
+ // 只有放置成功才保存分类结构
|
|
|
+ if (dropSuccess) {
|
|
|
+ // 保存拖动后的分类结构
|
|
|
+ saveClassStructure(data)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 保存分类结构
|
|
|
+const saveClassStructure = async (data) => {
|
|
|
+ // 构建分类结构数据
|
|
|
+ const buildStructure = (nodes, parentid = 0) => {
|
|
|
+ const result = []
|
|
|
+ nodes.forEach((node, index) => {
|
|
|
+ result.push({
|
|
|
+ sa_fadclassid: node.sa_fadclassid,
|
|
|
+ parentid: parentid,
|
|
|
+ sequence: index + 1
|
|
|
+ })
|
|
|
+ if (node.children && node.children.length > 0) {
|
|
|
+ result.push(...buildStructure(node.children, node.sa_fadclassid))
|
|
|
+ }
|
|
|
+ })
|
|
|
+ return result
|
|
|
+ }
|
|
|
+
|
|
|
+ const structureData = buildStructure(data)
|
|
|
+
|
|
|
+ try {
|
|
|
+ const res = await Api.requested({
|
|
|
+ "id": "20240418112102",
|
|
|
+ "content": {
|
|
|
+ "classStructure": structureData
|
|
|
+ }
|
|
|
+ })
|
|
|
+ if (res.msg === '成功') {
|
|
|
+ utils.message(res, '分类排序更新成功')
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('保存分类结构失败:', error)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
onMounted(() => {
|
|
|
getClassList()
|
|
|
})
|