车间能级提升-智能设备管理系统
朱桂飞
2025-01-09 3e8f7f239bedae0b4f04a1ac6bd443ba6298f73c
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
124
125
126
127
import type { EmitType } from '@vben-core/typings';
 
import type { TabsProps } from './types';
 
import { nextTick, onMounted, onUnmounted, ref, watch } from 'vue';
 
import {
  type Sortable,
  useIsMobile,
  useSortable,
} from '@vben-core/composables';
 
// 可能会找到拖拽的子元素,这里需要确保拖拽的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();
  });
}