Forráskód Böngészése

feature: 简易版菜单宽度拖拽功能

zouawen 3 hónapja
szülő
commit
57cf6cbc9e

+ 34 - 2
packages/@core/ui-kit/layout-ui/src/components/layout-sidebar.vue

@@ -1,7 +1,7 @@
 <script setup lang="ts">
 import type { CSSProperties } from 'vue';
 
-import { computed, shallowRef, useSlots, watchEffect } from 'vue';
+import { computed, ref, shallowRef, useSlots, watchEffect } from 'vue';
 
 import { VbenScrollbar } from '@vben-core/shadcn-ui';
 
@@ -107,7 +107,7 @@ const props = withDefaults(defineProps<Props>(), {
   zIndex: 0,
 });
 
-const emit = defineEmits<{ leave: [] }>();
+const emit = defineEmits<{ leave: []; 'update:width': [value: number] }>();
 const collapse = defineModel<boolean>('collapse');
 const extraCollapse = defineModel<boolean>('extraCollapse');
 const expandOnHovering = defineModel<boolean>('expandOnHovering');
@@ -254,6 +254,32 @@ function handleMouseleave() {
   collapse.value = true;
   extraVisible.value = false;
 }
+
+const isDragging = ref(false);
+
+function handleDragSidebar(e: MouseEvent) {
+  e.preventDefault();
+
+  isDragging.value = true;
+
+  const startX = e.clientX;
+  const startWidth = props.width;
+
+  function onMouseMove(moveEvent: MouseEvent) {
+    const deltaX = moveEvent.clientX - startX;
+    const newWidth = Math.min(320, Math.max(160, startWidth + deltaX));
+    emit('update:width', newWidth);
+  }
+
+  function onMouseUp() {
+    isDragging.value = false;
+    document.removeEventListener('mousemove', onMouseMove);
+    document.removeEventListener('mouseup', onMouseUp);
+  }
+
+  document.addEventListener('mousemove', onMouseMove);
+  document.addEventListener('mouseup', onMouseUp);
+}
 </script>
 
 <template>
@@ -266,6 +292,7 @@ function handleMouseleave() {
   <aside
     :style="style"
     class="fixed left-0 top-0 h-full transition-all duration-150"
+    :class="{ 'transition-none': isDragging }"
     @mouseenter="handleMouseenter"
     @mouseleave="handleMouseleave"
   >
@@ -296,6 +323,10 @@ function handleMouseleave() {
         v-if="showCollapseButton && !isSidebarMixed"
         v-model:collapsed="collapse"
       />
+      <div
+        class="absolute inset-y-0 -right-0.5 z-1000 w-1 cursor-col-resize"
+        @mousedown="handleDragSidebar"
+      ></div>
     </div>
     <div
       v-if="isSidebarMixed"
@@ -304,6 +335,7 @@ function handleMouseleave() {
         themeSub,
         {
           'border-l': extraVisible,
+          'transition-none': isDragging,
         },
       ]"
       :style="extraStyle"

+ 10 - 1
packages/@core/ui-kit/layout-ui/src/vben-layout.vue

@@ -64,7 +64,11 @@ const props = withDefaults(defineProps<Props>(), {
   zIndex: 200,
 });
 
-const emit = defineEmits<{ sideMouseLeave: []; toggleSidebar: [] }>();
+const emit = defineEmits<{
+  sideMouseLeave: [];
+  toggleSidebar: [];
+  'update:sidebar-width': [value: number];
+}>();
 const sidebarCollapse = defineModel<boolean>('sidebarCollapse', {
   default: false,
 });
@@ -480,6 +484,10 @@ function handleHeaderToggle() {
 }
 
 const idMainContent = ELEMENT_ID_MAIN_CONTENT;
+
+function handleUpdateSidebarWidth(val: number) {
+  emit('update:sidebar-width', val);
+}
 </script>
 
 <template>
@@ -507,6 +515,7 @@ const idMainContent = ELEMENT_ID_MAIN_CONTENT;
       :width="getSidebarWidth"
       :z-index="sidebarZIndex"
       @leave="() => emit('sideMouseLeave')"
+      @update:width="handleUpdateSidebarWidth"
     >
       <template v-if="isSideMode && !isMixedNav" #logo>
         <slot name="logo"></slot>

+ 9 - 0
packages/effects/layouts/src/basic/layout.vue

@@ -211,6 +211,14 @@ const slots: SetupContext['slots'] = useSlots();
 const headerSlots = computed(() => {
   return Object.keys(slots).filter((key) => key.startsWith('header-'));
 });
+
+function handleUpdateSidebarWidth(newWidth: number) {
+  updatePreferences({
+    sidebar: {
+      width: newWidth,
+    },
+  });
+}
 </script>
 
 <template>
@@ -267,6 +275,7 @@ const headerSlots = computed(() => {
       (value: boolean) =>
         updatePreferences({ sidebar: { extraCollapse: value } })
     "
+    @update:sidebar-width="handleUpdateSidebarWidth"
   >
     <!-- logo -->
     <template #logo>