From 707b3914498d16975e2bc140e8caf265e976f35f Mon Sep 17 00:00:00 2001 From: zouawen <846027729@qq.com> Date: Thu, 26 Feb 2026 10:09:29 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BE=A7=E8=BE=B9=E6=A0=8F=E5=AE=BD?= =?UTF-8?q?=E5=BA=A6=E6=8B=96=E6=8B=BD=E6=94=B9=E4=B8=BAcomposable?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=EF=BC=8C=E5=90=8C=E6=97=B6=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?tabbar.ts=E6=96=87=E4=BB=B6lint=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/@core/composables/src/index.ts | 1 + .../@core/composables/src/use-resizable.ts | 72 +++++++++++++++++++ .../src/components/layout-sidebar.vue | 36 ++++------ .../ui-kit/layout-ui/src/vben-layout.vue | 6 +- packages/stores/src/modules/tabbar.ts | 58 +++++++++++---- 5 files changed, 129 insertions(+), 44 deletions(-) create mode 100644 packages/@core/composables/src/use-resizable.ts diff --git a/packages/@core/composables/src/index.ts b/packages/@core/composables/src/index.ts index 2dbd4b80..2f6826f2 100644 --- a/packages/@core/composables/src/index.ts +++ b/packages/@core/composables/src/index.ts @@ -2,6 +2,7 @@ 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'; diff --git a/packages/@core/composables/src/use-resizable.ts b/packages/@core/composables/src/use-resizable.ts new file mode 100644 index 00000000..eeda2df9 --- /dev/null +++ b/packages/@core/composables/src/use-resizable.ts @@ -0,0 +1,72 @@ +import { onUnmounted, ref } from 'vue'; + +interface ResizableOptions { + max?: number; + min?: number; + onChange?: (newWidth: number) => void; +} + +export function useResizable(options: ResizableOptions = {}) { + const { min = 0, max = 999, onChange } = options; + + const isDragging = ref(false); + + let cleanup: (() => void) | null = null; + + let userSelect = ''; + let cursor = ''; + + const startDrag = (e: MouseEvent, width: number) => { + e.preventDefault(); + e.stopPropagation(); + + isDragging.value = true; + const startX = e.clientX; + const startWidth = width; + + userSelect = document.body.style.userSelect; + cursor = document.body.style.cursor; + + document.body.style.userSelect = 'none'; + document.body.style.cursor = 'col-resize'; + + const onMouseMove = (moveEvent: MouseEvent) => { + if (!isDragging.value) return; + + const deltaX = moveEvent.clientX - startX; + let newWidth = startWidth + deltaX; + + newWidth = Math.min(max, Math.max(min, newWidth)); + + onChange?.(newWidth); + }; + + const onMouseUp = () => { + if (!isDragging.value) return; + cleanup?.(); + }; + + document.addEventListener('mousemove', onMouseMove, { passive: true }); + document.addEventListener('mouseup', onMouseUp); + + cleanup = () => { + document.removeEventListener('mousemove', onMouseMove); + document.removeEventListener('mouseup', onMouseUp); + + document.body.style.userSelect = userSelect; + document.body.style.cursor = cursor; + + isDragging.value = false; + cleanup = null; + }; + }; + + onUnmounted(() => { + cleanup?.(); + }); + + return { + isDragging, + startDrag, + }; +} diff --git a/packages/@core/ui-kit/layout-ui/src/components/layout-sidebar.vue b/packages/@core/ui-kit/layout-ui/src/components/layout-sidebar.vue index dddb282b..c3930ac9 100644 --- a/packages/@core/ui-kit/layout-ui/src/components/layout-sidebar.vue +++ b/packages/@core/ui-kit/layout-ui/src/components/layout-sidebar.vue @@ -1,8 +1,9 @@