73 lines
2.3 KiB
Vue
73 lines
2.3 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" />
|
|
</div>
|
|
</template>
|