zjk
2026-07-17 47f583f707d9177486af3ac5c3c7844513691ca1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import type { NDataTable } from 'naive-ui'
import { useDraggable } from 'vue-draggable-plus'
 
export function useTableDrag<T = unknown>(params: {
  tableRef: Ref<InstanceType<typeof NDataTable> | undefined>
  data: Ref<T[]>
  onRowDrag: (rows: T[]) => void
}) {
  const tableEl = computed(() => params.tableRef?.value?.$el as HTMLElement)
  const tableBodyRef = ref<HTMLElement | undefined>(undefined)
 
  const { start } = useDraggable(tableBodyRef, params.data, {
    immediate: false,
    animation: 150,
    handle: '.drag-handle',
    onEnd: (event) => {
      const { oldIndex, newIndex } = event
      const start = Math.min(oldIndex!, newIndex!)
      const end = Math.max(oldIndex!, newIndex!) - start + 1
      const changedRows = [...params.data.value].splice(start, end)
      params.onRowDrag(unref([...changedRows]))
    },
  })
 
  onMounted(async () => {
    while (!tableBodyRef.value) {
      tableBodyRef.value = tableEl.value?.querySelector('tbody') || undefined
      await new Promise(resolve => setTimeout(resolve, 100))
    }
  })
 
  watchOnce(() => tableBodyRef.value, (el) => {
    el && start()
  })
}