1313 :treeData =" filterTreeData"
1414 :selectedKeys =" treeKey ? [treeKey] : []"
1515 :defaultExpandedKeys =" treeKey ? [treeKey] : []"
16+ :draggable =" !searchValue"
17+ :allowDrop =" allowDrop"
18+ @dragstart =" handleDragStart"
19+ @drop =" handleDrop"
1620 >
1721 <template #title =" treeNodeData " >
1822 <div
19- class =" ipam-tree-node"
23+ :class =" [
24+ 'ipam-tree-node',
25+ treeNodeData.isSubnet && !searchValue ? 'ipam-tree-node-draggable' : ''
26+ ]"
2027 @click =" clickTreeNode(treeNodeData)"
2128 >
29+ <OpsMoveIcon
30+ v-if =" treeNodeData .isSubnet && ! searchValue "
31+ class="ipam-tree-node-drag-icon"
32+ />
2233 <ops-icon
2334 :type =" treeNodeData.icon"
2435 class =" ipam-tree-node-icon"
102113
103114<script >
104115import _ from ' lodash'
105- import { deleteIPAMSubnet , deleteIPAMScope } from ' @/modules/cmdb/api/ipam.js'
116+ import { deleteIPAMSubnet , deleteIPAMScope , moveIPAMSubnet } from ' @/modules/cmdb/api/ipam.js'
117+ import { ops_move_icon as OpsMoveIcon } from ' @/core/icons'
106118
107119import SubnetForm from ' ./subnetForm.vue'
108120import CatalogForm from ' ./catalogForm.vue'
109121
110122export default {
111123 name: ' IPAMTree' ,
112124 components: {
125+ OpsMoveIcon,
113126 SubnetForm,
114127 CatalogForm
115128 },
@@ -146,6 +159,21 @@ export default {
146159 }
147160 },
148161 methods: {
162+ findNodeByKey (nodes , key ) {
163+ for (const node of nodes) {
164+ if (String (node .key ) === String (key)) {
165+ return node
166+ }
167+ if (node .children ) {
168+ const foundNode = this .findNodeByKey (node .children , key)
169+ if (foundNode) {
170+ return foundNode
171+ }
172+ }
173+ }
174+ return null
175+ },
176+
149177 handleTreeDataBySearch (data ) {
150178 const isMatch = data? .title ? .indexOf ? .(this .searchValue ) !== - 1
151179 if (! data? .children ? .length ) {
@@ -203,6 +231,50 @@ export default {
203231
204232 clickTreeNode (node ) {
205233 this .$emit (' updateTreeKey' , node .key )
234+ },
235+
236+ allowDrop ({ dropNode, dropPosition }) {
237+ if (this .searchValue || dropPosition !== 0 ) {
238+ return false
239+ }
240+
241+ const targetNode = this .findNodeByKey (this .treeData , dropNode? .eventKey )
242+ return targetNode? .key === ' all' || ! targetNode? .isSubnet
243+ },
244+
245+ handleDragStart (info ) {
246+ const dragNode = this .findNodeByKey (this .treeData , info? .node ? .eventKey )
247+ if (! dragNode? .isSubnet ) {
248+ const event = info && info .event
249+ if (event && event .preventDefault ) {
250+ event .preventDefault ()
251+ }
252+ if (event && event .stopPropagation ) {
253+ event .stopPropagation ()
254+ }
255+ return false
256+ }
257+ },
258+
259+ async handleDrop (info ) {
260+ const dragNode = this .findNodeByKey (this .treeData , info? .dragNode ? .eventKey )
261+ const targetNode = this .findNodeByKey (this .treeData , info? .node ? .eventKey )
262+
263+ if (! dragNode? .isSubnet || ! targetNode) {
264+ return
265+ }
266+
267+ const targetParentId = targetNode .key === ' all' ? null : targetNode .key
268+ if (` ${ dragNode .parentId || ' ' } ` === ` ${ targetParentId || ' ' } ` ) {
269+ return
270+ }
271+
272+ await moveIPAMSubnet (dragNode .key , {
273+ target_parent_id: targetParentId
274+ })
275+
276+ this .$message .success (this .$t (' editSuccess' ))
277+ this .refreshData ()
206278 }
207279 }
208280}
@@ -223,16 +295,25 @@ export default {
223295 height: 100 % ;
224296
225297 / deep/ .ant - tree {
298+ .ant - tree- switcher {
299+ display: inline- flex;
300+ align- items: center;
301+ justify- content: center;
302+ width: 18px ;
303+ height: 32px ;
304+ line- height: 32px ;
305+ }
306+
226307 .ant - tree- node- content- wrapper {
227- width: calc (100 % - 24px );
308+ width: calc (100 % - 18px );
228309 padding: 0px ;
229310 display: inline- block;
230311 height: fit- content;
231312
232313 .ant - tree- title {
233314 display: inline- block;
234315 width: 100 % ;
235- padding: 0 6px ;
316+ padding: 0 4px 0 2px ;
236317 }
237318 }
238319
@@ -263,6 +344,16 @@ export default {
263344 flex- shrink: 0 ;
264345 }
265346
347+ & - drag- icon {
348+ width: 12px ;
349+ height: 12px ;
350+ margin- right: 1px ;
351+ flex- shrink: 0 ;
352+ color: #A5A9BC ;
353+ opacity: 0 ;
354+ transition: opacity 0 .2s ease;
355+ }
356+
266357 & - title {
267358 margin- left: 6px ;
268359 font- size: 14px ;
@@ -306,10 +397,22 @@ export default {
306397 }
307398
308399 & : hover {
400+ .ipam - tree- node- drag- icon {
401+ opacity: 1 ;
402+ }
403+
309404 .ipam - tree- node- action {
310405 display: inline- block;
311406 }
312407 }
408+
409+ & - draggable {
410+ cursor: grab;
411+
412+ & : active {
413+ cursor: grabbing;
414+ }
415+ }
313416 }
314417}
315418< / style>
0 commit comments