2022-04-21 18:20:39 +08:00
|
|
|
<script lang="ts" setup>
|
2024-11-18 19:40:44 +08:00
|
|
|
import { useDevice } from "@/hooks/useDevice"
|
|
|
|
import { useLayoutMode } from "@/hooks/useLayoutMode"
|
2022-04-22 01:16:02 +08:00
|
|
|
import { useAppStore } from "@/store/modules/app"
|
|
|
|
import { usePermissionStore } from "@/store/modules/permission"
|
|
|
|
import { useSettingsStore } from "@/store/modules/settings"
|
2024-11-12 13:06:33 +08:00
|
|
|
import { getCssVar } from "@/utils/css"
|
2024-11-18 19:40:44 +08:00
|
|
|
import { computed } from "vue"
|
|
|
|
import { useRoute } from "vue-router"
|
|
|
|
import Logo from "../Logo/index.vue"
|
|
|
|
import SidebarItem from "./SidebarItem.vue"
|
2022-05-25 21:53:38 +08:00
|
|
|
|
2024-11-12 13:06:33 +08:00
|
|
|
const v3SidebarMenuBgColor = getCssVar("--v3-sidebar-menu-bg-color")
|
|
|
|
const v3SidebarMenuTextColor = getCssVar("--v3-sidebar-menu-text-color")
|
|
|
|
const v3SidebarMenuActiveTextColor = getCssVar("--v3-sidebar-menu-active-text-color")
|
2022-04-21 18:20:39 +08:00
|
|
|
|
2024-02-06 13:39:56 +08:00
|
|
|
const { isMobile } = useDevice()
|
2024-02-06 15:25:16 +08:00
|
|
|
const { isLeft, isTop } = useLayoutMode()
|
2022-04-21 18:20:39 +08:00
|
|
|
const route = useRoute()
|
2022-08-24 16:52:01 +08:00
|
|
|
const appStore = useAppStore()
|
|
|
|
const permissionStore = usePermissionStore()
|
|
|
|
const settingsStore = useSettingsStore()
|
2022-08-25 16:26:28 +08:00
|
|
|
|
2022-04-21 18:20:39 +08:00
|
|
|
const activeMenu = computed(() => {
|
2023-06-15 13:42:58 +08:00
|
|
|
const {
|
|
|
|
meta: { activeMenu },
|
|
|
|
path
|
|
|
|
} = route
|
2024-11-18 19:40:44 +08:00
|
|
|
return activeMenu || path
|
2022-04-21 18:20:39 +08:00
|
|
|
})
|
2024-11-18 19:40:44 +08:00
|
|
|
const noHiddenRoutes = computed(() => permissionStore.routes.filter(item => !item.meta?.hidden))
|
2024-02-06 13:39:56 +08:00
|
|
|
const isCollapse = computed(() => !appStore.sidebar.opened)
|
2024-02-06 15:25:16 +08:00
|
|
|
const isLogo = computed(() => isLeft.value && settingsStore.showLogo)
|
2023-07-07 12:21:28 +08:00
|
|
|
const backgroundColor = computed(() => (isLeft.value ? v3SidebarMenuBgColor : undefined))
|
|
|
|
const textColor = computed(() => (isLeft.value ? v3SidebarMenuTextColor : undefined))
|
|
|
|
const activeTextColor = computed(() => (isLeft.value ? v3SidebarMenuActiveTextColor : undefined))
|
2023-07-18 11:14:07 +08:00
|
|
|
const sidebarMenuItemHeight = computed(() => {
|
2024-02-06 15:25:16 +08:00
|
|
|
return !isTop.value ? "var(--v3-sidebar-menu-item-height)" : "var(--v3-navigationbar-height)"
|
2023-07-18 11:14:07 +08:00
|
|
|
})
|
|
|
|
const sidebarMenuHoverBgColor = computed(() => {
|
2024-02-06 15:25:16 +08:00
|
|
|
return !isTop.value ? "var(--v3-sidebar-menu-hover-bg-color)" : "transparent"
|
2023-07-18 11:14:07 +08:00
|
|
|
})
|
|
|
|
const tipLineWidth = computed(() => {
|
2024-02-06 15:25:16 +08:00
|
|
|
return !isTop.value ? "2px" : "0px"
|
2023-07-18 11:14:07 +08:00
|
|
|
})
|
2024-11-19 20:14:23 +08:00
|
|
|
/** 当为顶部模式时隐藏垂直滚动条 */
|
|
|
|
const hiddenScrollbarVerticalBar = computed(() => isTop.value ? "none" : "block")
|
2022-04-21 18:20:39 +08:00
|
|
|
</script>
|
|
|
|
|
2022-04-22 12:47:04 +08:00
|
|
|
<template>
|
2023-07-06 13:02:52 +08:00
|
|
|
<div :class="{ 'has-logo': isLogo }">
|
|
|
|
<Logo v-if="isLogo" :collapse="isCollapse" />
|
2022-04-22 12:47:04 +08:00
|
|
|
<el-scrollbar wrap-class="scrollbar-wrapper">
|
|
|
|
<el-menu
|
|
|
|
:default-active="activeMenu"
|
2023-07-18 11:14:07 +08:00
|
|
|
:collapse="isCollapse && !isTop"
|
2023-07-07 12:21:28 +08:00
|
|
|
:background-color="backgroundColor"
|
|
|
|
:text-color="textColor"
|
|
|
|
:active-text-color="activeTextColor"
|
2022-08-25 16:26:28 +08:00
|
|
|
:unique-opened="true"
|
|
|
|
:collapse-transition="false"
|
2023-07-18 11:14:07 +08:00
|
|
|
:mode="isTop && !isMobile ? 'horizontal' : 'vertical'"
|
2022-04-22 12:47:04 +08:00
|
|
|
>
|
2024-11-18 19:40:44 +08:00
|
|
|
<SidebarItem
|
|
|
|
v-for="noHiddenRoute in noHiddenRoutes"
|
|
|
|
:key="noHiddenRoute.path"
|
|
|
|
:item="noHiddenRoute"
|
|
|
|
:base-path="noHiddenRoute.path"
|
|
|
|
/>
|
2022-04-22 12:47:04 +08:00
|
|
|
</el-menu>
|
|
|
|
</el-scrollbar>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
2022-04-21 18:20:39 +08:00
|
|
|
<style lang="scss" scoped>
|
2023-09-07 13:43:23 +08:00
|
|
|
%tip-line {
|
2022-04-21 18:20:39 +08:00
|
|
|
&::before {
|
2022-04-22 01:16:02 +08:00
|
|
|
content: "";
|
2022-04-21 18:20:39 +08:00
|
|
|
position: absolute;
|
|
|
|
top: 0;
|
|
|
|
left: 0;
|
2023-07-18 11:14:07 +08:00
|
|
|
width: v-bind(tipLineWidth);
|
2022-04-21 18:20:39 +08:00
|
|
|
height: 100%;
|
2022-05-25 21:53:38 +08:00
|
|
|
background-color: var(--v3-sidebar-menu-tip-line-bg-color);
|
2022-04-21 18:20:39 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.has-logo {
|
|
|
|
.el-scrollbar {
|
2023-07-19 09:05:55 +08:00
|
|
|
// 多 1% 是为了在左侧模式时侧边栏最底部不显示 1px 左右的白色线条
|
|
|
|
height: calc(101% - var(--v3-header-height));
|
2022-04-21 18:20:39 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-25 16:26:28 +08:00
|
|
|
.el-scrollbar {
|
2023-10-07 16:29:43 +08:00
|
|
|
// 多 1% 是为了在顶部模式时防止垂直滚动
|
|
|
|
height: 101%;
|
2022-09-28 17:17:24 +08:00
|
|
|
:deep(.scrollbar-wrapper) {
|
2022-08-25 16:26:28 +08:00
|
|
|
// 限制水平宽度
|
|
|
|
overflow-x: hidden !important;
|
|
|
|
.el-scrollbar__view {
|
|
|
|
height: 100%;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// 滚动条
|
2022-09-28 17:17:24 +08:00
|
|
|
:deep(.el-scrollbar__bar) {
|
2022-08-25 16:26:28 +08:00
|
|
|
&.is-horizontal {
|
|
|
|
// 隐藏水平滚动条
|
|
|
|
display: none;
|
|
|
|
}
|
2023-10-07 16:29:43 +08:00
|
|
|
&.is-vertical {
|
|
|
|
// 当为顶部模式时隐藏垂直滚动条
|
|
|
|
display: v-bind(hiddenScrollbarVerticalBar);
|
|
|
|
}
|
2022-08-25 16:26:28 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-21 18:20:39 +08:00
|
|
|
.el-menu {
|
|
|
|
border: none;
|
2023-03-16 17:42:32 +08:00
|
|
|
min-height: 100%;
|
2022-04-21 18:20:39 +08:00
|
|
|
width: 100% !important;
|
|
|
|
}
|
|
|
|
|
2023-10-18 15:48:54 +08:00
|
|
|
.el-menu--horizontal {
|
|
|
|
height: v-bind(sidebarMenuItemHeight);
|
|
|
|
}
|
|
|
|
|
2022-09-28 17:17:24 +08:00
|
|
|
:deep(.el-menu-item),
|
|
|
|
:deep(.el-sub-menu__title),
|
2023-07-18 11:14:07 +08:00
|
|
|
:deep(.el-sub-menu .el-menu-item),
|
|
|
|
:deep(.el-menu--horizontal .el-menu-item) {
|
|
|
|
height: v-bind(sidebarMenuItemHeight);
|
|
|
|
line-height: v-bind(sidebarMenuItemHeight);
|
2022-09-30 16:58:37 +08:00
|
|
|
&.is-active,
|
2022-04-21 18:20:39 +08:00
|
|
|
&:hover {
|
2023-07-18 11:14:07 +08:00
|
|
|
background-color: v-bind(sidebarMenuHoverBgColor);
|
2022-04-21 18:20:39 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-18 11:14:07 +08:00
|
|
|
:deep(.el-sub-menu) {
|
|
|
|
&.is-active {
|
2023-08-16 14:48:50 +08:00
|
|
|
> .el-sub-menu__title {
|
2023-07-18 11:14:07 +08:00
|
|
|
color: v-bind(activeTextColor) !important;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-07 17:12:31 +08:00
|
|
|
:deep(.el-menu-item.is-active) {
|
|
|
|
@extend %tip-line;
|
2022-04-21 18:20:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
.el-menu--collapse {
|
2023-09-07 17:12:31 +08:00
|
|
|
:deep(.el-sub-menu.is-active) {
|
|
|
|
.el-sub-menu__title {
|
|
|
|
@extend %tip-line;
|
2022-04-21 18:20:39 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</style>
|