Browse Source

fix: 优化侧边栏拖拽逻辑,支持展开和折叠

zouawen 3 tháng trước cách đây
mục cha
commit
afffc4b3f0

+ 0 - 1
packages/@core/composables/src/index.ts

@@ -2,7 +2,6 @@ export * from './use-is-mobile';
 export * from './use-layout-style';
 export * from './use-namespace';
 export * from './use-priority-value';
-export * from './use-resizable';
 export * from './use-scroll-lock';
 export * from './use-simple-locale';
 export * from './use-sortable';

+ 21 - 10
packages/@core/ui-kit/layout-ui/src/components/layout-sidebar.vue

@@ -3,11 +3,11 @@ import type { CSSProperties } from 'vue';
 
 import { computed, shallowRef, useSlots, watchEffect } from 'vue';
 
-import { useResizable } from '@vben-core/composables';
 import { VbenScrollbar } from '@vben-core/shadcn-ui';
 
 import { useScrollLock } from '@vueuse/core';
 
+import { useSidebarDrag } from '../hooks/use-sidebar-drag';
 import { SidebarCollapseButton, SidebarFixedButton } from './widgets';
 
 interface Props {
@@ -256,18 +256,29 @@ function handleMouseleave() {
   extraVisible.value = false;
 }
 
-const { startDrag } = useResizable({
-  min: 160,
-  max: 320,
-  onChange: (newWidth) => {
-    emit('update:width', newWidth);
-  },
-});
+const { startDrag } = useSidebarDrag();
 
 const handleDragSidebar = (e: MouseEvent) => {
-  const { isSidebarMixed, extraWidth, width } = props;
+  const { isSidebarMixed, collapseWidth, extraWidth, width } = props;
+  const minLimit = isSidebarMixed ? width + collapseWidth : collapseWidth;
+  const maxLimit = isSidebarMixed ? width + 320 : 320;
   const currentWidth = isSidebarMixed ? extraWidth : width;
-  startDrag(e, currentWidth, asideRef.value, dragBarRef.value);
+  startDrag(
+    e,
+    minLimit,
+    maxLimit,
+    currentWidth,
+    asideRef.value,
+    dragBarRef.value,
+    (newWidth) => {
+      emit('update:width', newWidth);
+      if (isSidebarMixed) {
+        extraCollapse.value = newWidth <= collapseWidth;
+      } else {
+        collapse.value = newWidth <= collapseWidth;
+      }
+    },
+  );
 };
 </script>
 

+ 8 - 11
packages/@core/composables/src/use-resizable.ts → packages/@core/ui-kit/layout-ui/src/hooks/use-sidebar-drag.ts

@@ -1,14 +1,6 @@
 import { onUnmounted } from 'vue';
 
-interface ResizableOptions {
-  max?: number;
-  min?: number;
-  onChange?: (newWidth: number) => void;
-}
-
-export function useResizable(options: ResizableOptions = {}) {
-  const { min = 0, max = 999, onChange } = options;
-
+export function useSidebarDrag() {
   let startX = 0;
   let startWidth = 0;
   let targetTransition = '';
@@ -22,9 +14,12 @@ export function useResizable(options: ResizableOptions = {}) {
 
   const startDrag = (
     e: MouseEvent,
+    min: number,
+    max: number,
     currentWidth: number,
     targetElement: HTMLElement | null,
     dragBarElement: HTMLElement | null,
+    onDrag: (newWidth: number) => void,
   ) => {
     cleanup?.();
 
@@ -57,7 +52,9 @@ export function useResizable(options: ResizableOptions = {}) {
 
     const onMouseMove = (moveEvent: MouseEvent) => {
       const deltaX = moveEvent.clientX - startX;
-      const newLeft = dragBarOffsetLeft + deltaX;
+      let newLeft = dragBarOffsetLeft + deltaX;
+      if (newLeft < min) newLeft = min;
+      if (newLeft > max) newLeft = max;
       dragBarElement.style.left = `${newLeft}px`;
     };
 
@@ -71,7 +68,7 @@ export function useResizable(options: ResizableOptions = {}) {
         dragBarElement.style.right = dragBarRight;
       }
 
-      onChange?.(newWidth);
+      onDrag?.(newWidth);
 
       cleanup?.();
     };

+ 6 - 3
packages/@core/ui-kit/layout-ui/src/vben-layout.vue

@@ -124,13 +124,16 @@ const headerWrapperHeight = computed(() => {
 });
 
 const getSideCollapseWidth = computed(() => {
-  const { sidebarCollapseShowTitle, sidebarMixedWidth, sideCollapseWidth } =
-    props;
+  const {
+    sidebarCollapseShowTitle,
+    sidebarExtraCollapsedWidth,
+    sideCollapseWidth,
+  } = props;
 
   return sidebarCollapseShowTitle ||
     isSidebarMixedNav.value ||
     isHeaderMixedNav.value
-    ? sidebarMixedWidth
+    ? sidebarExtraCollapsedWidth
     : sideCollapseWidth;
 });