74 lines
2.4 KiB
Vue
74 lines
2.4 KiB
Vue
<script setup lang="ts">
|
||
// draggable:拖到行的上/下 25% 是「前/后插入」,中间是「放入内部」
|
||
// drop 事件里自己重排数据(组件不直接改 treeData)
|
||
import { ref } from 'vue'
|
||
import { G3Message, G3Tree, type TreeNodeData } from '@g3soft/ui'
|
||
|
||
const treeData = ref<TreeNodeData[]>([
|
||
{ key: '1', title: '第一项' },
|
||
{ key: '2', title: '第二项' },
|
||
{
|
||
key: '3',
|
||
title: '第三项(可拖入)',
|
||
children: [{ key: '3-1', title: '子项' }],
|
||
},
|
||
])
|
||
|
||
function findNode(nodes: TreeNodeData[], key: string): TreeNodeData | null {
|
||
for (const node of nodes) {
|
||
if (String(node.key) === key) return node
|
||
const found = node.children ? findNode(node.children, key) : null
|
||
if (found) return found
|
||
}
|
||
return null
|
||
}
|
||
|
||
function removeNode(nodes: TreeNodeData[], key: string): TreeNodeData | null {
|
||
const index = nodes.findIndex((node) => String(node.key) === key)
|
||
if (index >= 0) return nodes.splice(index, 1)[0]
|
||
for (const node of nodes) {
|
||
if (node.children) {
|
||
const removed = removeNode(node.children, key)
|
||
if (removed) return removed
|
||
}
|
||
}
|
||
return null
|
||
}
|
||
|
||
function onDrop(info: { dragKey: string | number; dropKey: string | number; dropPosition: string }) {
|
||
const dragKey = String(info.dragKey)
|
||
const dropKey = String(info.dropKey)
|
||
const data = treeData.value
|
||
const moved = removeNode(data, dragKey)
|
||
if (!moved) return
|
||
|
||
if (info.dropPosition === 'inside') {
|
||
const target = findNode(data, dropKey)
|
||
if (target) {
|
||
target.children = [...(target.children ?? []), moved]
|
||
G3Message.success(`已移动到「${target.title}」内部`)
|
||
}
|
||
} else {
|
||
const insert = (nodes: TreeNodeData[]): boolean => {
|
||
const index = nodes.findIndex((node) => String(node.key) === dropKey)
|
||
if (index >= 0) {
|
||
nodes.splice(info.dropPosition === 'before' ? index : index + 1, 0, moved)
|
||
return true
|
||
}
|
||
return nodes.some((node) => (node.children ? insert(node.children) : false))
|
||
}
|
||
insert(data)
|
||
G3Message.success(`已${info.dropPosition === 'before' ? '前移' : '后移'}到「${dropKey}」`)
|
||
}
|
||
|
||
treeData.value = [...data]
|
||
}
|
||
</script>
|
||
|
||
<template>
|
||
<div style="max-width: 320px">
|
||
<G3Tree :tree-data="treeData" draggable default-expand-all block-node @drop="onDrop" />
|
||
<p style="margin: 8px 0 0; font-size: 12px; color: #6b7280">拖拽任意节点试试(子节点不能拖进自己的子树)</p>
|
||
</div>
|
||
</template>
|