From 8acd3a0310985fd37d8ebfcc096906eb2f7b47d4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=B0=8F=E6=96=AF=EF=BC=88xiaosi=EF=BC=89?=
<1531733886@qq.com>
Date: Wed, 25 Oct 2023 20:45:32 +0800
Subject: [PATCH] =?UTF-8?q?feat(layouts):=20=E2=9C=A8=20sidebar?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- Sidebar text overflows to display abbreviations and displays tootips
- Adjust the style to optimize the expansion and contraction animation
---
.env | 0
package.json | 2 +-
pnpm-lock.yaml | 10 +-
src/components/SvgIcon/index.vue | 19 +-
.../page-layouts/components/Sidebar/Item.vue | 55 +++-
.../components/Sidebar/MinSidebar.vue | 1 +
.../components/Sidebar/SidebarItem.vue | 95 ++++--
.../page-layouts/components/Sidebar/index.vue | 9 +-
src/styles/sidebar.scss | 301 +++++-------------
src/styles/var/site-bar.scss | 2 +-
src/utils/plugin/element.ts | 5 +
11 files changed, 214 insertions(+), 285 deletions(-)
create mode 100644 .env
diff --git a/.env b/.env
new file mode 100644
index 00000000..e69de29b
diff --git a/package.json b/package.json
index 6509ae46..caf2b4fc 100644
--- a/package.json
+++ b/package.json
@@ -48,7 +48,7 @@
"dayjs": "^1.11.9",
"docx-preview": "^0.1.18",
"echarts": "^5.4.3",
- "element-plus": "^2.3.12",
+ "element-plus": "^2.4.1",
"es6-promise": "^4.2.8",
"i18next": "^23.5.0",
"intro.js": "^7.2.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index ce16b40b..8cad1e2c 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1,4 +1,4 @@
-lockfileVersion: '6.1'
+lockfileVersion: '6.0'
settings:
autoInstallPeers: true
@@ -39,8 +39,8 @@ dependencies:
specifier: ^5.4.3
version: 5.4.3
element-plus:
- specifier: ^2.3.12
- version: 2.3.12(vue@3.3.4)
+ specifier: ^2.4.1
+ version: 2.4.1(vue@3.3.4)
es6-promise:
specifier: ^4.2.8
version: 4.2.8
@@ -7597,10 +7597,10 @@ packages:
integrity: sha512-shUVy6Eawp33dFBFIoYbIwLHrX0IZ857AlH9ug2o4rvbWmpaCUdBpQ5Zw39HRrfzAFm4APJE9V+E2A/WB0YqJw==,
}
- /element-plus@2.3.12(vue@3.3.4):
+ /element-plus@2.4.1(vue@3.3.4):
resolution:
{
- integrity: sha512-fAWpbKCyt+l1dsqSNPOs/F/dBN4Wp5CGAyxbiS5zqDwI4q3QPM+LxLU2h3GUHMIBtMGCvmsG98j5HPMkTKkvcA==,
+ integrity: sha512-t7nl+vQlkBKVk1Ag6AufSDyFV8YIXxTFsaya4Nz/0tiRlcz65WPN4WMFeNURuFJleu1HLNtP4YyQKMuS7El8uA==,
}
peerDependencies:
vue: ^3.2.0
diff --git a/src/components/SvgIcon/index.vue b/src/components/SvgIcon/index.vue
index bdddac62..68a3c81f 100644
--- a/src/components/SvgIcon/index.vue
+++ b/src/components/SvgIcon/index.vue
@@ -26,7 +26,7 @@
-
+
@@ -37,24 +37,21 @@
diff --git a/src/layouts/page-layouts/components/Sidebar/MinSidebar.vue b/src/layouts/page-layouts/components/Sidebar/MinSidebar.vue
index eeae3ebf..706fdb18 100644
--- a/src/layouts/page-layouts/components/Sidebar/MinSidebar.vue
+++ b/src/layouts/page-layouts/components/Sidebar/MinSidebar.vue
@@ -51,6 +51,7 @@
class-name="menu-item-svg"
:icon="menusRoute.meta && menusRoute.meta.icon"
:title="menusRoute.meta?.title"
+ mode="horizontal"
/>
diff --git a/src/layouts/page-layouts/components/Sidebar/SidebarItem.vue b/src/layouts/page-layouts/components/Sidebar/SidebarItem.vue
index ba388a20..787cc07d 100644
--- a/src/layouts/page-layouts/components/Sidebar/SidebarItem.vue
+++ b/src/layouts/page-layouts/components/Sidebar/SidebarItem.vue
@@ -6,6 +6,7 @@
import Item from './Item.vue';
import AppLink from './Link.vue';
import type { AppRouteRecordRaw } from '@/router/type';
+ import { translateI18n } from '@/hooks/web/useI18n';
const props = defineProps({
// route object
@@ -21,21 +22,32 @@
type: String,
default: '',
},
+ level: {
+ type: Number,
+ default: 0,
+ },
+ collapse: {
+ type: Boolean,
+ default: false,
+ },
+ mode: {
+ type: String as PropType<'vertical' | 'horizontal'>,
+ default: 'vertical',
+ },
});
- const onlyOneChild = ref({});
- const hasOneShowingChild = (
- children: Array = [],
- parent: AppRouteRecordRaw,
- ) => {
- const showingChildren = children.filter((item: AppRouteRecordRaw) => {
- if (item.meta?.hideSidebar) {
- return false;
- } else {
- // Temp set(will be used if only has one showing child)
- onlyOneChild.value = item;
- return true;
- }
- });
+
+ const onlyOneChild = ref>({});
+ const hasOneShowingChild = (parent: AppRouteRecordRaw) => {
+ const showingChildren =
+ parent.children?.filter((item: AppRouteRecordRaw) => {
+ if (item.meta?.hideSidebar) {
+ return false;
+ } else {
+ // Temp set(will be used if only has one showing child)
+ onlyOneChild.value = item;
+ return true;
+ }
+ }) ?? [];
// When there is only one child router, the child router is displayed by default
if (showingChildren.length === 1) {
@@ -65,44 +77,63 @@
-
-
-
-
-
+
+
+
+
+
+
+
-
+
-
-
diff --git a/src/layouts/page-layouts/components/Sidebar/index.vue b/src/layouts/page-layouts/components/Sidebar/index.vue
index 89f76b20..12f48dcb 100644
--- a/src/layouts/page-layouts/components/Sidebar/index.vue
+++ b/src/layouts/page-layouts/components/Sidebar/index.vue
@@ -56,6 +56,10 @@
}
return path;
});
+
+ const collapse = computed(() =>
+ appConfig.value.sidebarMode === 'horizontal' ? false : appConfig.value.collapseMenu,
+ );
@@ -63,8 +67,9 @@
diff --git a/src/styles/sidebar.scss b/src/styles/sidebar.scss
index 0f6e17a3..eabb43fd 100644
--- a/src/styles/sidebar.scss
+++ b/src/styles/sidebar.scss
@@ -14,7 +14,6 @@
flex: 1;
width: calc(100vw - #{$sideBarWidth});
min-height: 100%;
- transition: margin-left 0.28s;
display: flex;
flex-direction: column;
@@ -26,39 +25,72 @@
}
.sidebar-container {
- width: $sideBarWidth !important;
- // padding: 26px 0;
- // margin-top: #{$navBarHeight};
+ max-width: $sideBarWidth;
+ width: 100%;
display: flex;
flex-direction: column;
overflow: hidden;
font-size: 0;
background-color: $menuBg;
box-shadow: 1px 0 2px rgb(28 29 30 / 8%);
- transition: width 0.28s;
+ transition: all 0.3s;
border-right: 1px solid var(--border-color-light);
- .el-menu-item::before {
- position: absolute;
- top: 0;
- left: 0;
- width: 3px;
+ --el-menu-base-level-padding: 18px;
+ --el-menu-level-padding: 18px;
+ --el-menu-icon-width: 20px;
+
+ a {
+ display: inline-block;
+ width: 100%;
+ overflow: hidden;
+ }
+
+ .el-menu {
+ width: $sideBarWidth;
height: 100%;
- clear: both;
- content: '';
- transition: all 0.2s ease-in-out;
- transform: translateY(0);
+ border: none;
+ }
+
+ .scrollbar-wrapper {
+ overflow-x: hidden !important;
+ }
+
+ .el-scrollbar {
+ height: 100%;
+ flex: 1;
}
.el-menu-item {
color: $menuItemText;
- // border-left: #{$menuItemBorderLeft} solid 3px;
.menu-item-svg {
- margin-right: 16px;
font-size: var(--font-size-large);
line-height: 0;
color: $menuItemText;
+ transition: all 0.3s ease-in-out;
+ }
+ }
+
+ .one-level-menu-item {
+ padding-left: 0;
+ .menu-item-svg {
+ width: $sideHideBarWidth;
+ }
+ > .menu-item-text-only {
+ padding-left: var(--el-menu-base-level-padding);
+ }
+ }
+
+ .one-level-sub-menu {
+ > .el-sub-menu__title {
+ padding-left: 0;
+ .sub-menu-svg {
+ width: $sideHideBarWidth;
+ }
+ }
+ > .menu-item-text-only {
+ padding-left: var(--el-menu-base-level-padding);
}
}
@@ -69,57 +101,15 @@
.el-menu-item.is-active {
color: $menuItemActiveText !important;
background-color: $menuItemActiveBg !important;
- // border-left: #{$menuItemActiveBorderLeft} solid 3px !important;
.menu-item-svg {
color: $menuItemActiveText !important;
}
}
- // reset element-ui css
- .horizontal-collapse-transition {
- transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out;
- }
-
- .scrollbar-wrapper {
- overflow-x: hidden !important;
- }
-
- .el-scrollbar__bar.is-vertical {
- right: 0;
- }
-
- .el-scrollbar {
- height: 100%;
- flex: 1;
- }
-
- &.has-logo {
- .el-scrollbar {
- height: calc(100% - 50px);
- }
- }
-
- .is-horizontal {
- display: none;
- }
-
- a {
- display: inline-block;
- width: 100%;
- overflow: hidden;
- }
-
- .el-menu {
- width: 100% !important;
- height: 100%;
- border: none;
- }
-
// menu hover
.submenu-title-noDropdown,
.el-sub-menu__title {
- padding-right: 20px;
color: $menuText;
-webkit-user-select: none;
-moz-user-select: none;
@@ -127,11 +117,16 @@
user-select: none;
background-color: $menuBg;
+ .el-sub-menu__icon-arrow {
+ opacity: 1;
+ transition: all 0.3s ease-in-out;
+ }
+
.sub-menu-svg {
- margin-right: 16px;
font-size: var(--font-size-large);
line-height: 0;
color: $menuText;
+ transition: all 0.3s ease-in-out;
}
&:hover {
@@ -170,72 +165,36 @@
}
.hideSidebar {
- width: $sideHideBarWidth !important;
- // .sidebar-container {
- // width: 54px !important;
- // }
-
- // .el-menu--inline{
- // display: none;
- // }
-
- .submenu-title-noDropdown {
- position: relative;
- padding: 0 !important;
-
- .el-tooltip {
- padding: 0 !important;
- }
+ max-width: $sideHideBarWidth;
+ .el-menu--collapse {
+ width: $sideHideBarWidth;
}
.el-sub-menu {
- background-color: $menuBg;
- overflow: hidden;
-
- .sub-menu-svg {
- margin-left: 20px;
- }
-
& > .el-sub-menu__title {
- padding: 0 !important;
-
.el-sub-menu__icon-arrow {
- display: none;
+ opacity: 0;
}
}
}
- .el-menu-item {
- .menu-item-svg {
- margin-left: 20px;
- }
-
- .el-sub-menu__icon-arrow {
- display: none;
+ .one-level-menu-item {
+ padding: 0;
+ > .menu-item-text-only {
+ width: $sideHideBarWidth;
+ padding: 0 calc(var(--el-menu-base-level-padding) - 10px);
+ text-align: center;
}
}
- .el-menu--collapse {
- .el-sub-menu {
- & > .el-sub-menu__title {
- & > span {
- display: inline-block;
- width: 0;
- height: 0;
- overflow: hidden;
- visibility: hidden;
- }
- }
+ .one-level-sub-menu {
+ > .el-sub-menu__title {
+ padding: 0;
}
-
- .el-menu-item {
- & > span {
- display: inline-block;
- width: 0;
- height: 0;
- overflow: hidden;
- visibility: hidden;
- }
+ > .menu-item-text-only {
+ width: $sideHideBarWidth;
+ padding: 0 calc(var(--el-menu-base-level-padding) - 10px);
+ text-align: center;
}
}
}
@@ -247,98 +206,22 @@
height: 100%;
.el-sub-menu__title {
- color: $menuText;
- -webkit-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none;
-
- .el-sub-menu__icon-arrow {
- position: relative !important;
- top: 0;
- right: 0;
- margin-top: 0;
- margin-left: 8px;
- }
-
.sub-menu-svg {
margin-right: 10px;
font-size: var(--font-size-large);
line-height: 0;
- // color: $menuText;
- }
-
- &:hover {
- color: $menuHoverText !important;
- background-color: $menuHover;
-
- .sub-menu-svg,
- .menu-item-svg {
- color: $menuHoverText !important;
- }
- }
- }
-
- .is-active > .el-sub-menu__title {
- color: $menuActiveText !important;
-
- .sub-menu-svg {
- color: $menuActiveText !important;
}
}
.el-menu-item {
- color: $menuItemText;
background-color: $menuItemBg;
.menu-item-svg {
- margin-right: 16px;
+ margin-right: 10px;
font-size: var(--font-size-large);
- line-height: 0;
- color: $menuItemText;
- }
-
- &:hover {
- color: $menuItemHoverText !important;
- background-color: $menuItemHover;
-
- .menu-item-svg {
- color: $menuItemHoverText !important;
- }
}
}
}
-
- // .el-menu--collapse .el-menu .el-sub-menu {
- // min-width: $sideBarWidth !important;
- // }
-
- // // mobile responsive
- // .mobile {
- // .main-container {
- // margin-left: 0;
- // }
-
- // .sidebar-container {
- // width: $sideBarWidth !important;
- // transition: transform 0.28s;
- // }
-
- // &.hideSidebar {
- // .sidebar-container {
- // pointer-events: none;
- // transition-duration: 0.3s;
- // transform: translate3d(-$sideBarWidth, 0, 0);
- // }
- // }
- // }
-
- // .withoutAnimation {
- // .main-container,
- // .sidebar-container {
- // transition: none;
- // }
- // }
}
// when menu collapsed
@@ -367,18 +250,6 @@
}
}
- .el-menu--popup .el-menu-item::before {
- position: absolute;
- top: 0;
- left: 0;
- width: 3px;
- height: 100%;
- clear: both;
- content: '';
- transition: all 0.2s ease-in-out;
- transform: translateY(0);
- }
-
.el-menu-item,
> .el-menu--popup .el-menu-item {
background-color: $menuItemBg;
@@ -392,12 +263,6 @@
}
}
}
-
- .nest-menu .is-active.el-menu-item::before {
- background-color: #{$menuItemActiveBorderLeft};
- }
-
- .nest-menu .is-active.el-menu-item,
.el-menu-item.is-active {
color: $menuItemActiveText !important;
background-color: $menuItemActiveBg !important;
@@ -406,7 +271,6 @@
color: $menuItemActiveText !important;
}
}
-
// the scroll bar appears when the subMenu is too long
> .el-menu--popup {
max-height: 100vh;
@@ -414,38 +278,21 @@
overflow-y: auto;
.el-sub-menu__title {
- line-height: 0;
color: $menuText;
.sub-menu-svg {
- margin-right: 16px;
- line-height: 0;
+ margin-right: 10px;
color: $menuText;
}
}
.el-menu-item {
- line-height: 0;
color: $menuItemText;
.menu-item-svg {
- margin-right: 16px;
- line-height: 0;
+ margin-right: 10px;
color: $menuItemText;
}
}
-
- &::-webkit-scrollbar-track-piece {
- background: #d3dce6;
- }
-
- &::-webkit-scrollbar {
- width: 6px;
- }
-
- &::-webkit-scrollbar-thumb {
- background: #99a9bf;
- border-radius: 20px;
- }
}
}
diff --git a/src/styles/var/site-bar.scss b/src/styles/var/site-bar.scss
index 986dde4c..08395f9a 100644
--- a/src/styles/var/site-bar.scss
+++ b/src/styles/var/site-bar.scss
@@ -1,6 +1,6 @@
// 左侧导航栏(此地方颜色全部改成自定义)
$sideBarWidth: 210px;
-$sideHideBarWidth: 55px;
+$sideHideBarWidth: 54px;
$navBarHeight: 50px;
$tabsPageHeight: 38px; //面包屑高度 38px
diff --git a/src/utils/plugin/element.ts b/src/utils/plugin/element.ts
index 8f592209..289b840c 100644
--- a/src/utils/plugin/element.ts
+++ b/src/utils/plugin/element.ts
@@ -40,6 +40,9 @@ import {
ElSwitch,
ElProgress,
ElColorPicker,
+ ElText,
+ ElCollapseTransition,
+
// 指令
ElLoading,
ElInfiniteScroll,
@@ -109,6 +112,8 @@ const components = [
ElSwitch,
ElProgress,
ElColorPicker,
+ ElText,
+ ElCollapseTransition,
];
// Icon