11<template >
22 <div class =" layout-container flex h-full" >
3- <div :class =" `layout-container__left border-r ${isCollapse ? 'hidden' : ''}`" >
3+ <div
4+ :class =" `layout-container__left border-r ${isCollapse ? 'hidden' : ''}`"
5+ :style =" { width: isCollapse ? 0 : `${leftWidth}px` }"
6+ >
47 <div class =" layout-container__left_content" >
58 <slot name =" left" ></slot >
69 </div >
1720 :icon =" isCollapse ? 'ArrowRightBold' : 'ArrowLeftBold'"
1821 />
1922 </el-tooltip >
23+ <div
24+ v-if =" props.resizable"
25+ class =" splitter-bar-line"
26+ :class =" isResizing ? 'hover' : ''"
27+ @mousedown =" onSplitterMouseDown"
28+ ></div >
2029 </div >
2130 <div class =" layout-container__right" >
2231 <slot ></slot >
2534</template >
2635
2736<script setup lang="ts">
28- import { computed , useSlots , ref } from ' vue'
37+ import { onUnmounted , ref } from ' vue'
2938defineOptions ({ name: ' LayoutContainer' })
30- const slots = useSlots ()
39+
3140const props = defineProps ({
32- header: String || null ,
33- backTo: String ,
3441 showCollapse: Boolean ,
42+ resizable: Boolean ,
43+ minLeftWidth: {
44+ type: Number ,
45+ default: 240 ,
46+ },
47+ maxLeftWidth: {
48+ type: Number ,
49+ default: 400 ,
50+ },
3551})
3652
3753const isCollapse = ref (false )
54+ const leftWidth = ref (props .minLeftWidth )
55+ const isResizing = ref (false )
56+
57+ const onSplitterMouseDown = (e : MouseEvent ) => {
58+ if (! props .resizable ) return
59+ e .preventDefault ()
60+ isResizing .value = true
61+ document .body .style .userSelect = ' none'
62+ const startX = e .clientX
63+ const startWidth = leftWidth .value
64+ const onMouseMove = (moveEvent : MouseEvent ) => {
65+ if (! isResizing .value ) return
66+ const deltaX = moveEvent .clientX - startX
67+ let newWidth = startWidth + deltaX
68+
69+ // 限制宽度在最小和最大值之间
70+ newWidth = Math .max (props .minLeftWidth , Math .min (props .maxLeftWidth , newWidth ))
71+ leftWidth .value = newWidth
72+ }
73+
74+ const onMouseUp = () => {
75+ isResizing .value = false
76+ document .body .style .userSelect = ' '
77+ document .removeEventListener (' mousemove' , onMouseMove )
78+ document .removeEventListener (' mouseup' , onMouseUp )
79+ }
80+ document .addEventListener (' mousemove' , onMouseMove )
81+ document .addEventListener (' mouseup' , onMouseUp )
82+ }
3883
39- const showBack = computed (() => {
40- const { backTo } = props
41- return backTo
84+ onUnmounted (() => {
85+ document . removeEventListener ( ' mousemove ' , () => {})
86+ document . removeEventListener ( ' mouseup ' , () => {})
4287})
4388 </script >
4489
@@ -47,17 +92,34 @@ const showBack = computed(() => {
4792 & __left {
4893 position : relative ;
4994 box-sizing : border-box ;
50- transition : width 0.28s ;
95+ // transition: width 0.28s;
5196 width : var (--sidebar-width );
52- min-width : var (--sidebar-width );
53- box-sizing : border-box ;
97+ .splitter-bar-line {
98+ z-index : 1 ;
99+ position : absolute ;
100+ top : 0 ;
101+ right : 0 ;
102+ cursor : col-resize ;
103+ width : 4px ;
104+ height : 100% ;
105+ & .hover :after {
106+ width : 1px ;
107+ height : 100% ;
108+ content : ' ' ;
109+ z-index : 2 ;
110+ position : absolute ;
111+ right : -1px ;
112+ top : 0 ;
113+ background : var (--el-color-primary );
114+ }
115+ }
54116
55117 .collapse {
56118 position : absolute ;
57119 top : 36px ;
58120 right : -12px ;
59121 box-shadow : 0px 5px 10px 0px var (--app-text-color-light-1 );
60- z-index : 1 ;
122+ z-index : 2 ;
61123 }
62124
63125 .layout-container__left_content {
0 commit comments