mirror of
https://gitee.com/dapppp/ruoyi-plus-vben5.git
synced 2026-04-10 20:33:15 +08:00
fix: 侧边栏菜单拖拽功能在设置内增加开关
This commit is contained in:
@@ -109,6 +109,7 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
});
|
||||
|
||||
const emit = defineEmits<{ leave: []; 'update:width': [value: number] }>();
|
||||
const draggable = defineModel<boolean>('draggable');
|
||||
const collapse = defineModel<boolean>('collapse');
|
||||
const extraCollapse = defineModel<boolean>('extraCollapse');
|
||||
const expandOnHovering = defineModel<boolean>('expandOnHovering');
|
||||
@@ -262,14 +263,19 @@ const handleDragSidebar = (e: MouseEvent) => {
|
||||
const { isSidebarMixed, collapseWidth, extraWidth, width } = props;
|
||||
const minLimit = collapseWidth;
|
||||
const maxLimit = 320;
|
||||
const currentWidth = isSidebarMixed ? extraWidth : width;
|
||||
const startWidth = isSidebarMixed ? extraWidth : width;
|
||||
|
||||
startDrag(
|
||||
e,
|
||||
minLimit,
|
||||
maxLimit,
|
||||
currentWidth,
|
||||
asideRef.value,
|
||||
dragBarRef.value,
|
||||
{
|
||||
min: minLimit,
|
||||
max: maxLimit,
|
||||
startWidth,
|
||||
},
|
||||
{
|
||||
target: asideRef.value,
|
||||
dragBar: dragBarRef.value,
|
||||
},
|
||||
(newWidth) => {
|
||||
emit('update:width', newWidth);
|
||||
if (isSidebarMixed) {
|
||||
@@ -357,6 +363,7 @@ const handleDragSidebar = (e: MouseEvent) => {
|
||||
</VbenScrollbar>
|
||||
</div>
|
||||
<div
|
||||
v-if="draggable"
|
||||
ref="dragBarRef"
|
||||
class="absolute inset-y-0 -right-[1px] z-1000 w-[2px] cursor-col-resize hover:bg-primary"
|
||||
@mousedown="handleDragSidebar"
|
||||
|
||||
@@ -1,106 +1,157 @@
|
||||
import { onUnmounted } from 'vue';
|
||||
|
||||
interface DragOptions {
|
||||
max: number;
|
||||
min: number;
|
||||
startWidth: number;
|
||||
}
|
||||
|
||||
interface DragElements {
|
||||
dragBar: HTMLElement | null;
|
||||
target: HTMLElement | null;
|
||||
}
|
||||
|
||||
type DragCallback = (newWidth: number) => void;
|
||||
|
||||
export function useSidebarDrag() {
|
||||
let startX = 0;
|
||||
let startWidth = 0;
|
||||
let targetTransition = '';
|
||||
let dragBarTransition = '';
|
||||
let dragBarOffsetLeft = 0;
|
||||
let dragBarLeft = '';
|
||||
let dragBarRight = '';
|
||||
let userSelect = '';
|
||||
let cursor = '';
|
||||
let cleanup: (() => void) | null = null;
|
||||
const state: {
|
||||
cleanup: (() => void) | null;
|
||||
isDragging: boolean;
|
||||
originalStyles: {
|
||||
bodyCursor: string;
|
||||
bodyUserSelect: string;
|
||||
dragBarLeft: string;
|
||||
dragBarRight: string;
|
||||
dragBarTransition: string;
|
||||
targetTransition: string;
|
||||
};
|
||||
startLeft: number;
|
||||
startWidth: number;
|
||||
startX: number;
|
||||
} = {
|
||||
cleanup: null,
|
||||
isDragging: false,
|
||||
startLeft: 0,
|
||||
startWidth: 0,
|
||||
startX: 0,
|
||||
originalStyles: {
|
||||
bodyCursor: '',
|
||||
bodyUserSelect: '',
|
||||
dragBarLeft: '',
|
||||
dragBarRight: '',
|
||||
dragBarTransition: '',
|
||||
targetTransition: '',
|
||||
},
|
||||
};
|
||||
|
||||
const startDrag = (
|
||||
e: MouseEvent,
|
||||
min: number,
|
||||
max: number,
|
||||
currentWidth: number,
|
||||
targetElement: HTMLElement | null,
|
||||
dragBarElement: HTMLElement | null,
|
||||
onDrag: (newWidth: number) => void,
|
||||
options: DragOptions,
|
||||
elements: DragElements,
|
||||
onDrag: DragCallback,
|
||||
) => {
|
||||
cleanup?.();
|
||||
const { min, max, startWidth } = options;
|
||||
const { dragBar, target } = elements;
|
||||
|
||||
if (state.isDragging || !dragBar || !target) return;
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
if (!dragBarElement || !targetElement) return;
|
||||
state.isDragging = true;
|
||||
|
||||
startX = e.clientX;
|
||||
startWidth = currentWidth;
|
||||
state.startX = e.clientX;
|
||||
state.startWidth = startWidth;
|
||||
state.startLeft = dragBar.offsetLeft;
|
||||
|
||||
targetTransition = targetElement.style.transition;
|
||||
dragBarTransition = dragBarElement.style.transition;
|
||||
state.originalStyles = {
|
||||
bodyCursor: document.body.style.cursor,
|
||||
bodyUserSelect: document.body.style.userSelect,
|
||||
dragBarLeft: dragBar.style.left,
|
||||
dragBarRight: dragBar.style.right,
|
||||
dragBarTransition: dragBar.style.transition,
|
||||
targetTransition: target.style.transition,
|
||||
};
|
||||
|
||||
dragBarOffsetLeft = dragBarElement.offsetLeft;
|
||||
dragBarLeft = dragBarElement.style.left;
|
||||
dragBarRight = dragBarElement.style.right;
|
||||
|
||||
userSelect = document.body.style.userSelect;
|
||||
cursor = document.body.style.cursor;
|
||||
|
||||
targetElement.style.transition = 'none';
|
||||
dragBarElement.style.transition = 'none';
|
||||
|
||||
dragBarElement.style.left = `${dragBarOffsetLeft}px`;
|
||||
dragBarElement.style.right = 'auto';
|
||||
|
||||
document.body.style.userSelect = 'none';
|
||||
document.body.style.cursor = 'col-resize';
|
||||
document.body.style.userSelect = 'none';
|
||||
|
||||
dragBar.style.left = `${state.startLeft}px`;
|
||||
dragBar.style.right = 'auto';
|
||||
dragBar.style.transition = 'none';
|
||||
target.style.transition = 'none';
|
||||
|
||||
const onMouseMove = (moveEvent: MouseEvent) => {
|
||||
const deltaX = moveEvent.clientX - startX;
|
||||
let newLeft = dragBarOffsetLeft + deltaX;
|
||||
if (!state.isDragging || !dragBar) return;
|
||||
|
||||
const deltaX = moveEvent.clientX - state.startX;
|
||||
let newLeft = state.startLeft + deltaX;
|
||||
|
||||
if (newLeft < min) newLeft = min;
|
||||
if (newLeft > max) newLeft = max;
|
||||
dragBarElement.style.left = `${newLeft}px`;
|
||||
|
||||
dragBar.style.left = `${newLeft}px`;
|
||||
dragBar.classList.add('bg-primary');
|
||||
};
|
||||
|
||||
const onMouseUp = (upEvent: MouseEvent) => {
|
||||
const deltaX = upEvent.clientX - startX;
|
||||
let newWidth = startWidth + deltaX;
|
||||
if (!state.isDragging || !dragBar || !target) return;
|
||||
|
||||
const deltaX = upEvent.clientX - state.startX;
|
||||
let newWidth = state.startWidth + deltaX;
|
||||
|
||||
newWidth = Math.min(max, Math.max(min, newWidth));
|
||||
|
||||
if (dragBarElement) {
|
||||
dragBarElement.style.left = dragBarLeft;
|
||||
dragBarElement.style.right = dragBarRight;
|
||||
}
|
||||
dragBar.classList.remove('bg-primary');
|
||||
|
||||
onDrag?.(newWidth);
|
||||
|
||||
cleanup?.();
|
||||
endDrag();
|
||||
};
|
||||
|
||||
document.addEventListener('mousemove', onMouseMove, { passive: true });
|
||||
document.addEventListener('mousemove', onMouseMove);
|
||||
document.addEventListener('mouseup', onMouseUp);
|
||||
|
||||
cleanup = () => {
|
||||
const cleanup = () => {
|
||||
if (!state.cleanup) return;
|
||||
|
||||
document.removeEventListener('mousemove', onMouseMove);
|
||||
document.removeEventListener('mouseup', onMouseUp);
|
||||
|
||||
if (targetElement) {
|
||||
targetElement.style.transition = targetTransition;
|
||||
}
|
||||
if (dragBarElement) {
|
||||
dragBarElement.style.transition = dragBarTransition;
|
||||
dragBarElement.style.left = dragBarLeft;
|
||||
dragBarElement.style.right = dragBarRight;
|
||||
document.body.style.cursor = state.originalStyles.bodyCursor;
|
||||
document.body.style.userSelect = state.originalStyles.bodyUserSelect;
|
||||
|
||||
if (dragBar) {
|
||||
dragBar.style.left = state.originalStyles.dragBarLeft;
|
||||
dragBar.style.right = state.originalStyles.dragBarRight;
|
||||
dragBar.style.transition = state.originalStyles.dragBarTransition;
|
||||
dragBar.classList.remove('bg-primary');
|
||||
}
|
||||
|
||||
document.body.style.userSelect = userSelect;
|
||||
document.body.style.cursor = cursor;
|
||||
if (target) {
|
||||
target.style.transition = state.originalStyles.targetTransition;
|
||||
}
|
||||
|
||||
cleanup = null;
|
||||
state.isDragging = false;
|
||||
state.cleanup = null;
|
||||
};
|
||||
|
||||
state.cleanup = cleanup;
|
||||
};
|
||||
|
||||
const endDrag = () => {
|
||||
state.cleanup?.();
|
||||
};
|
||||
|
||||
onUnmounted(() => {
|
||||
cleanup?.();
|
||||
endDrag();
|
||||
});
|
||||
|
||||
return {
|
||||
startDrag,
|
||||
endDrag,
|
||||
get isDragging() {
|
||||
return state.isDragging;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -69,6 +69,9 @@ const emit = defineEmits<{
|
||||
toggleSidebar: [];
|
||||
'update:sidebar-width': [value: number];
|
||||
}>();
|
||||
const sidebarDraggable = defineModel<boolean>('sidebarDraggable', {
|
||||
default: true,
|
||||
});
|
||||
const sidebarCollapse = defineModel<boolean>('sidebarCollapse', {
|
||||
default: false,
|
||||
});
|
||||
@@ -493,6 +496,7 @@ const idMainContent = ELEMENT_ID_MAIN_CONTENT;
|
||||
<div class="relative flex min-h-full w-full">
|
||||
<LayoutSidebar
|
||||
v-if="sidebarEnableState"
|
||||
v-model:draggable="sidebarDraggable"
|
||||
v-model:collapse="sidebarCollapse"
|
||||
v-model:expand-on-hover="sidebarExpandOnHover"
|
||||
v-model:expand-on-hovering="sidebarExpandOnHovering"
|
||||
|
||||
Reference in New Issue
Block a user