Blame view

Yi.Vben5.Vue3/packages/@core/ui-kit/tabs-ui/src/use-tabs-drag.ts 3.27 KB
515fceeb   “wangming”   框架初始化
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
  import type { Sortable } from '@vben-core/composables';
  import type { EmitType } from '@vben-core/typings';
  
  import type { TabsProps } from './types';
  
  import { useIsMobile, useSortable } from '@vben-core/composables';
  import { nextTick, onMounted, onUnmounted, ref, watch } from 'vue';
  
  // 可能会找到拖拽的子元素,这里需要确保拖拽的dom时tab元素
  function findParentElement(element: HTMLElement) {
    const parentCls = 'group';
    return element.classList.contains(parentCls)
      ? element
      : element.closest(`.${parentCls}`);
  }
  
  export function useTabsDrag(props: TabsProps, emit: EmitType) {
    const sortableInstance = ref<null | Sortable>(null);
  
    async function initTabsSortable() {
      await nextTick();
  
      const el = document.querySelectorAll(
        `.${props.contentClass}`,
      )?.[0] as HTMLElement;
  
      if (!el) {
        console.warn('Element not found for sortable initialization');
        return;
      }
  
      const resetElState = async () => {
        el.style.cursor = 'default';
        // el.classList.remove('dragging');
        el.querySelector('.draggable')?.classList.remove('dragging');
      };
  
      const { initializeSortable } = useSortable(el, {
        filter: (_evt, target: HTMLElement) => {
          const parent = findParentElement(target);
          const draggable = parent?.classList.contains('draggable');
          return !draggable || !props.draggable;
        },
        onEnd(evt) {
          const { newIndex, oldIndex } = evt;
          // const fromElement = evt.item;
          const { srcElement } = (evt as any).originalEvent;
  
          if (!srcElement) {
            resetElState();
            return;
          }
  
          const srcParent = findParentElement(srcElement);
  
          if (!srcParent) {
            resetElState();
            return;
          }
  
          if (!srcParent.classList.contains('draggable')) {
            resetElState();
  
            return;
          }
  
          if (
            oldIndex !== undefined &&
            newIndex !== undefined &&
            !Number.isNaN(oldIndex) &&
            !Number.isNaN(newIndex) &&
            oldIndex !== newIndex
          ) {
            emit('sortTabs', oldIndex, newIndex);
          }
          resetElState();
        },
        onMove(evt) {
          const parent = findParentElement(evt.related);
          if (parent?.classList.contains('draggable') && props.draggable) {
            const isCurrentAffix = evt.dragged.classList.contains('affix-tab');
            const isRelatedAffix = evt.related.classList.contains('affix-tab');
            // 不允许在固定的tab和非固定的tab之间互相拖拽
            return isCurrentAffix === isRelatedAffix;
          } else {
            return false;
          }
        },
        onStart: () => {
          el.style.cursor = 'grabbing';
          el.querySelector('.draggable')?.classList.add('dragging');
          // el.classList.add('dragging');
        },
      });
  
      sortableInstance.value = await initializeSortable();
    }
  
    async function init() {
      const { isMobile } = useIsMobile();
  
      // 移动端下tab不需要拖拽
      if (isMobile.value) {
        return;
      }
      await nextTick();
      initTabsSortable();
    }
  
    onMounted(init);
  
    watch(
      () => props.styleType,
      () => {
        sortableInstance.value?.destroy();
        init();
      },
    );
  
    onUnmounted(() => {
      sortableInstance.value?.destroy();
    });
  }