vben
authored
5 years ago
1
<template>
vben
authored
5 years ago
2
<div :class="`${prefixCls}-dom`" :style="getDomStyle"></div>
vben
authored
5 years ago
3
4
<div
v-click-outside="handleClickOutside"
vben
authored
5 years ago
5
:style="getWrapStyle"
vben
authored
5 years ago
6
7
8
9
10
:class="[
prefixCls,
getMenuTheme,
{
open: openMenu,
vben
authored
5 years ago
11
mini: getCollapsed,
vben
authored
5 years ago
12
13
},
]"
vben
authored
5 years ago
14
v-bind="getMenuEvents"
vben
authored
5 years ago
15
16
>
<AppLogo :showTitle="false" :class="`${prefixCls}-logo`" />
vben
authored
5 years ago
17
18
19
<Trigger :class="`${prefixCls}-trigger`" />
vben
authored
5 years ago
20
21
22
23
24
25
26
27
28
<ScrollContainer>
<ul :class="`${prefixCls}-module`">
<li
:class="[
`${prefixCls}-module__item `,
{
[`${prefixCls}-module__item--active`]: item.path === activePath,
},
]"
Vben
authored
4 years ago
29
v-bind="getItemEvents(item)"
vben
authored
5 years ago
30
31
32
v-for="item in menuModules"
:key="item.path"
>
Vben
authored
4 years ago
33
<SimpleMenuTag :item="item" collapseParent dot />
vben
authored
5 years ago
34
<Icon
vben
authored
5 years ago
35
:class="`${prefixCls}-module__icon`"
vben
authored
5 years ago
36
:size="getCollapsed ? 16 : 20"
Vben
authored
4 years ago
37
:icon="item.icon || (item.meta && item.meta.icon)"
vben
authored
5 years ago
38
/>
vben
authored
5 years ago
39
40
41
<p :class="`${prefixCls}-module__name`">
{{ t(item.name) }}
</p>
vben
authored
5 years ago
42
43
44
45
46
47
</li>
</ul>
</ScrollContainer>
<div :class="`${prefixCls}-menu-list`" ref="sideRef" :style="getMenuStyle">
<div
vben
authored
5 years ago
48
v-show="openMenu"
vben
authored
5 years ago
49
50
51
52
53
54
55
56
:class="[
`${prefixCls}-menu-list__title`,
{
show: openMenu,
},
]"
>
<span class="text"> {{ title }}</span>
vben
authored
5 years ago
57
58
<Icon
:size="16"
vben
authored
5 years ago
59
:icon="getMixSideFixed ? 'ri:pushpin-2-fill' : 'ri:pushpin-2-line'"
vben
authored
5 years ago
60
61
62
class="pushpin"
@click="handleFixedMenu"
/>
vben
authored
5 years ago
63
64
</div>
<ScrollContainer :class="`${prefixCls}-menu-list__content`">
vben
authored
5 years ago
65
<SimpleMenu
vben
authored
5 years ago
66
67
:items="chilrenMenus"
:theme="getMenuTheme"
vben
authored
5 years ago
68
mixSider
vben
authored
5 years ago
69
70
71
72
73
74
75
76
77
78
79
80
81
@menuClick="handleMenuClick"
/>
</ScrollContainer>
<div
v-show="getShowDragBar && openMenu"
:class="`${prefixCls}-drag-bar`"
ref="dragBarRef"
></div>
</div>
</div>
</template>
<script lang="ts">
import type { Menu } from '/@/router/types';
vben
authored
5 years ago
82
83
84
85
86
import type { CSSProperties } from 'vue';
import type { RouteLocationNormalized } from 'vue-router';
import { defineComponent, onMounted, ref, computed, unref } from 'vue';
vben
authored
5 years ago
87
import { ScrollContainer } from '/@/components/Container';
Vben
authored
4 years ago
88
import { SimpleMenuTag } from '/@/components/SimpleMenu';
Vben
authored
4 years ago
89
import { Icon } from '/@/components/Icon';
vben
authored
5 years ago
90
import { AppLogo } from '/@/components/Application';
vben
authored
5 years ago
91
92
import Trigger from '../trigger/HeaderTrigger.vue';
vben
authored
5 years ago
93
94
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
import { useDragLine } from './useLayoutSider';
vben
authored
5 years ago
95
import { useGlobSetting } from '/@/hooks/setting';
vben
authored
5 years ago
96
97
98
import { useDesign } from '/@/hooks/web/useDesign';
import { useI18n } from '/@/hooks/web/useI18n';
import { useGo } from '/@/hooks/web/usePage';
vben
authored
5 years ago
99
vben
authored
5 years ago
100
import { SIDE_BAR_SHOW_TIT_MINI_WIDTH, SIDE_BAR_MINI_WIDTH } from '/@/enums/appEnum';
vben
authored
5 years ago
101
102
import clickOutside from '/@/directives/clickOutside';
vben
authored
5 years ago
103
import { getShallowMenus, getChildrenMenus, getCurrentParentPath } from '/@/router/menus';
Vben
authored
4 years ago
104
import { listenerRouteChange } from '/@/logics/mitt/routeChange';
vben
authored
5 years ago
105
import { SimpleMenu } from '/@/components/SimpleMenu';
vben
authored
5 years ago
106
107
108
109
110
111
export default defineComponent({
name: 'LayoutMixSider',
components: {
ScrollContainer,
AppLogo,
vben
authored
5 years ago
112
SimpleMenu,
vben
authored
5 years ago
113
Icon,
vben
authored
5 years ago
114
Trigger,
Vben
authored
4 years ago
115
SimpleMenuTag,
vben
authored
5 years ago
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
},
directives: {
clickOutside,
},
setup() {
let menuModules = ref<Menu[]>([]);
const activePath = ref('');
const chilrenMenus = ref<Menu[]>([]);
const openMenu = ref(false);
const dragBarRef = ref<ElRef>(null);
const sideRef = ref<ElRef>(null);
const currentRoute = ref<Nullable<RouteLocationNormalized>>(null);
const { prefixCls } = useDesign('layout-mix-sider');
const go = useGo();
const { t } = useI18n();
const {
getMenuWidth,
getCanDrag,
getCloseMixSidebarOnChange,
getMenuTheme,
vben
authored
5 years ago
137
getMixSideTrigger,
vben
authored
5 years ago
138
139
140
141
getRealWidth,
getMixSideFixed,
mixSideHasChildren,
setMenuSetting,
vben
authored
5 years ago
142
143
getIsMixSidebar,
getCollapsed,
vben
authored
5 years ago
144
} = useMenuSetting();
vben
authored
5 years ago
145
vben
authored
5 years ago
146
147
148
149
150
151
152
153
const { title } = useGlobSetting();
useDragLine(sideRef, dragBarRef, true);
const getMenuStyle = computed(
(): CSSProperties => {
return {
width: unref(openMenu) ? `${unref(getMenuWidth)}px` : 0,
vben
authored
5 years ago
154
left: `${unref(getMixSideWidth)}px`,
vben
authored
5 years ago
155
156
157
158
};
}
);
vben
authored
5 years ago
159
const getIsFixed = computed(() => {
vben
authored
5 years ago
160
/* eslint-disable-next-line */
vben
authored
5 years ago
161
162
163
mixSideHasChildren.value = unref(chilrenMenus).length > 0;
const isFixed = unref(getMixSideFixed) && unref(mixSideHasChildren);
if (isFixed) {
vben
authored
5 years ago
164
/* eslint-disable-next-line */
vben
authored
5 years ago
165
166
167
168
169
openMenu.value = true;
}
return isFixed;
});
vben
authored
5 years ago
170
171
172
173
const getMixSideWidth = computed(() => {
return unref(getCollapsed) ? SIDE_BAR_MINI_WIDTH : SIDE_BAR_SHOW_TIT_MINI_WIDTH;
});
vben
authored
5 years ago
174
175
176
const getDomStyle = computed(
(): CSSProperties => {
const fixedWidth = unref(getIsFixed) ? unref(getRealWidth) : 0;
vben
authored
5 years ago
177
178
179
180
181
182
183
184
185
const width = `${unref(getMixSideWidth) + fixedWidth}px`;
return getWrapCommonStyle(width);
}
);
const getWrapStyle = computed(
(): CSSProperties => {
const width = `${unref(getMixSideWidth)}px`;
return getWrapCommonStyle(width);
vben
authored
5 years ago
186
187
188
}
);
vben
authored
5 years ago
189
const getMenuEvents = computed(() => {
vben
authored
5 years ago
190
191
192
193
194
195
196
return !unref(getMixSideFixed)
? {
onMouseleave: () => {
closeMenu();
},
}
: {};
vben
authored
5 years ago
197
198
});
vben
authored
5 years ago
199
200
201
202
203
204
const getShowDragBar = computed(() => unref(getCanDrag));
onMounted(async () => {
menuModules.value = await getShallowMenus();
});
Vben
authored
4 years ago
205
listenerRouteChange((route) => {
vben
authored
5 years ago
206
currentRoute.value = route;
vben
authored
5 years ago
207
setActive(true);
vben
authored
5 years ago
208
if (unref(getCloseMixSidebarOnChange)) {
vben
authored
5 years ago
209
closeMenu();
vben
authored
5 years ago
210
211
212
}
});
vben
authored
5 years ago
213
214
215
216
217
218
219
220
221
222
function getWrapCommonStyle(width: string): CSSProperties {
return {
width,
maxWidth: width,
minWidth: width,
flex: `0 0 ${width}`,
};
}
// Process module menu click
vben
authored
5 years ago
223
async function hanldeModuleClick(path: string, hover = false) {
vben
authored
5 years ago
224
225
226
const children = await getChildrenMenus(path);
if (unref(activePath) === path) {
vben
authored
5 years ago
227
if (!hover) {
vben
authored
5 years ago
228
229
230
231
232
if (!unref(openMenu)) {
openMenu.value = true;
} else {
closeMenu();
}
vben
authored
5 years ago
233
}
vben
authored
5 years ago
234
235
236
237
238
239
240
241
242
243
244
if (!unref(openMenu)) {
setActive();
}
} else {
openMenu.value = true;
activePath.value = path;
}
if (!children || children.length === 0) {
go(path);
chilrenMenus.value = [];
vben
authored
5 years ago
245
closeMenu();
vben
authored
5 years ago
246
247
248
249
250
return;
}
chilrenMenus.value = children;
}
vben
authored
5 years ago
251
// Set the currently active menu and submenu
vben
authored
5 years ago
252
async function setActive(setChildren = false) {
vben
authored
5 years ago
253
254
255
256
257
const path = currentRoute.value?.path;
if (!path) return;
const parentPath = await getCurrentParentPath(path);
activePath.value = parentPath;
// hanldeModuleClick(parentPath);
vben
authored
5 years ago
258
if (unref(getIsMixSidebar)) {
vben
authored
5 years ago
259
260
261
262
263
264
const activeMenu = unref(menuModules).find((item) => item.path === unref(activePath));
const p = activeMenu?.path;
if (p) {
const children = await getChildrenMenus(p);
if (setChildren) {
chilrenMenus.value = children;
vben
authored
5 years ago
265
266
267
268
if (unref(getMixSideFixed)) {
openMenu.value = children.length > 0;
}
vben
authored
5 years ago
269
270
271
272
273
274
}
if (children.length === 0) {
chilrenMenus.value = [];
}
}
}
vben
authored
5 years ago
275
276
277
278
279
280
281
}
function handleMenuClick(path: string) {
go(path);
}
function handleClickOutside() {
vben
authored
5 years ago
282
setActive(true);
vben
authored
5 years ago
283
closeMenu();
vben
authored
5 years ago
284
285
}
vben
authored
5 years ago
286
287
288
289
290
291
292
293
294
295
296
function getItemEvents(item: Menu) {
if (unref(getMixSideTrigger) === 'hover') {
return {
onMouseenter: () => hanldeModuleClick(item.path, true),
};
}
return {
onClick: () => hanldeModuleClick(item.path),
};
}
vben
authored
5 years ago
297
298
299
300
301
302
function handleFixedMenu() {
setMenuSetting({
mixSideFixed: !unref(getIsFixed),
});
}
vben
authored
5 years ago
303
// Close menu
vben
authored
5 years ago
304
305
306
307
308
309
function closeMenu() {
if (!unref(getIsFixed)) {
openMenu.value = false;
}
}
vben
authored
5 years ago
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
return {
t,
prefixCls,
menuModules,
hanldeModuleClick,
activePath,
chilrenMenus,
getShowDragBar,
handleMenuClick,
getMenuStyle,
handleClickOutside,
sideRef,
dragBarRef,
title,
openMenu,
getMenuTheme,
vben
authored
5 years ago
326
327
getItemEvents,
getMenuEvents,
vben
authored
5 years ago
328
329
330
getDomStyle,
handleFixedMenu,
getMixSideFixed,
vben
authored
5 years ago
331
332
getWrapStyle,
getCollapsed,
vben
authored
5 years ago
333
334
335
336
337
338
339
340
341
342
343
344
345
346
};
},
});
</script>
<style lang="less">
@prefix-cls: ~'@{namespace}-layout-mix-sider';
@width: 80px;
.@{prefix-cls} {
position: fixed;
top: 0;
left: 0;
z-index: @layout-mix-sider-fixed-z-index;
height: 100%;
overflow: hidden;
Vben
authored
4 years ago
347
background-color: @sider-dark-bg-color;
vben
authored
5 years ago
348
transition: all 0.2s ease 0s;
vben
authored
5 years ago
349
vben
authored
5 years ago
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
&-dom {
height: 100%;
overflow: hidden;
transition: all 0.2s ease 0s;
}
&-logo {
display: flex;
height: @header-height;
padding-left: 0 !important;
justify-content: center;
img {
width: @logo-width;
height: @logo-width;
}
}
&.light {
.@{prefix-cls}-logo {
border-bottom: 1px solid rgb(238, 238, 238);
}
&.open {
vben
authored
5 years ago
374
> .scrollbar {
vben
authored
5 years ago
375
376
377
378
379
380
381
382
383
384
385
border-right: 1px solid rgb(238, 238, 238);
}
}
.@{prefix-cls}-module {
&__item {
font-weight: normal;
color: rgba(0, 0, 0, 0.65);
&--active {
color: @primary-color;
Vben
authored
4 years ago
386
background-color: unset;
vben
authored
5 years ago
387
388
389
}
}
}
vben
authored
5 years ago
390
.@{prefix-cls}-menu-list {
vben
authored
5 years ago
391
392
393
394
&__content {
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.1);
}
vben
authored
5 years ago
395
396
397
398
399
400
401
402
403
404
&__title {
.pushpin {
color: rgba(0, 0, 0, 0.35);
&:hover {
color: rgba(0, 0, 0, 0.85);
}
}
}
}
vben
authored
5 years ago
405
}
Vben
authored
4 years ago
406
@border-color: @sider-dark-lighten-bg-color;
vben
authored
5 years ago
407
408
409
410
&.dark {
&.open {
.@{prefix-cls}-logo {
Vben
authored
4 years ago
411
// border-bottom: 1px solid @border-color;
vben
authored
5 years ago
412
413
}
vben
authored
5 years ago
414
> .scrollbar {
vben
authored
5 years ago
415
border-right: 1px solid @border-color;
vben
authored
5 years ago
416
417
418
}
}
.@{prefix-cls}-menu-list {
Vben
authored
4 years ago
419
background-color: @sider-dark-bg-color;
vben
authored
5 years ago
420
421
422
423
&__title {
color: @white;
border-bottom: none;
vben
authored
5 years ago
424
border-bottom: 1px solid @border-color;
vben
authored
5 years ago
425
426
427
428
}
}
}
vben
authored
5 years ago
429
> .scrollbar {
vben
authored
5 years ago
430
height: calc(100% - @header-height - 38px);
vben
authored
5 years ago
431
432
}
vben
authored
5 years ago
433
434
435
436
437
438
439
440
441
442
&.mini &-module {
&__name {
display: none;
}
&__icon {
margin-bottom: 0;
}
}
vben
authored
5 years ago
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
&-module {
position: relative;
padding-top: 1px;
&__item {
position: relative;
padding: 12px 0;
color: rgba(255, 255, 255, 0.65);
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
&:hover {
color: @white;
}
// &:hover,
&--active {
font-weight: 700;
color: @white;
Vben
authored
4 years ago
462
background-color: @sider-dark-darken-bg-color;
vben
authored
5 years ago
463
464
465
466
467
468
469
&::before {
position: absolute;
top: 0;
left: 0;
width: 3px;
height: 100%;
Vben
authored
4 years ago
470
background-color: @primary-color;
vben
authored
5 years ago
471
472
473
474
475
476
477
478
content: '';
}
}
}
&__icon {
margin-bottom: 8px;
font-size: 24px;
vben
authored
5 years ago
479
transition: all 0.2s;
vben
authored
5 years ago
480
481
482
483
484
}
&__name {
margin-bottom: 0;
font-size: 12px;
vben
authored
5 years ago
485
transition: all 0.2s;
vben
authored
5 years ago
486
487
488
}
}
vben
authored
5 years ago
489
490
491
492
493
494
495
496
497
498
&-trigger {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
padding: 6px;
padding-left: 12px;
font-size: 18px;
color: rgba(255, 255, 255, 0.65);
cursor: pointer;
Vben
authored
4 years ago
499
background-color: @sider-dark-bg-color;
vben
authored
5 years ago
500
501
502
503
}
&.light &-trigger {
color: rgba(0, 0, 0, 0.65);
Vben
authored
4 years ago
504
background-color: #fff;
vben
authored
5 years ago
505
506
}
vben
authored
5 years ago
507
508
509
510
511
512
&-menu-list {
position: fixed;
top: 0;
width: 0;
width: 200px;
height: calc(100%);
Vben
authored
4 years ago
513
background-color: #fff;
vben
authored
5 years ago
514
transition: all 0.2s;
vben
authored
5 years ago
515
516
517
518
&__title {
display: flex;
height: @header-height;
vben
authored
5 years ago
519
// margin-left: -6px;
vben
authored
5 years ago
520
521
522
523
524
525
font-size: 18px;
color: @primary-color;
border-bottom: 1px solid rgb(238, 238, 238);
opacity: 0;
transition: unset;
align-items: center;
vben
authored
5 years ago
526
justify-content: space-between;
vben
authored
5 years ago
527
528
&.show {
vben
authored
5 years ago
529
min-width: 130px;
vben
authored
5 years ago
530
531
532
opacity: 1;
transition: all 0.5s ease;
}
vben
authored
5 years ago
533
534
535
536
537
538
539
540
541
542
.pushpin {
margin-right: 6px;
color: rgba(255, 255, 255, 0.65);
cursor: pointer;
&:hover {
color: #fff;
}
}
vben
authored
5 years ago
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
}
&__content {
height: calc(100% - @header-height) !important;
.scrollbar__wrap {
height: 100%;
overflow-x: hidden;
}
.scrollbar__bar.is-horizontal {
display: none;
}
.ant-menu {
height: 100%;
}
.ant-menu-inline,
.ant-menu-vertical,
.ant-menu-vertical-left {
border-right: 1px solid transparent;
}
}
}
&-drag-bar {
position: absolute;
vben
authored
5 years ago
571
572
573
574
top: 50px;
right: -1px;
width: 1px;
height: calc(100% - 50px);
vben
authored
5 years ago
575
cursor: ew-resize;
Vben
authored
4 years ago
576
background-color: #f8f8f9;
vben
authored
5 years ago
577
578
579
580
581
582
border-top: none;
border-bottom: none;
box-shadow: 0 0 4px 0 rgba(28, 36, 56, 0.15);
}
}
</style>