xy 2 years ago
parent a844588f90
commit 57e0e61036

@ -0,0 +1,97 @@
<template>
<div :class="classObj" class="app-wrapper">
<div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside" />
<navbar />
<sidebar class="sidebar-container" />
<div class="main-container">
<app-main />
</div>
</div>
</template>
<script>
import { Sidebar, AppMain } from './components'
import ResizeMixin from './mixin/ResizeHandler'
import Navbar from '@/layout/components/Navbar/index.vue'
export default {
name: 'Layout',
components: {
Navbar,
Sidebar,
AppMain
},
mixins: [ResizeMixin],
computed: {
sidebar() {
return this.$store.state.app.sidebar
},
device() {
return this.$store.state.app.device
},
fixedHeader() {
return this.$store.state.settings.fixedHeader
},
classObj() {
return {
hideSidebar: !this.sidebar.opened,
openSidebar: this.sidebar.opened,
withoutAnimation: this.sidebar.withoutAnimation,
mobile: this.device === 'mobile'
}
}
},
methods: {
handleClickOutside() {
this.$store.dispatch('app/closeSideBar', { withoutAnimation: false })
}
}
}
</script>
<style lang="scss" scoped>
@import "~@/styles/mixin.scss";
@import "~@/styles/variables.scss";
@import '~@/styles/sidebar.scss';
.app-wrapper {
@include clearfix;
position: relative;
height: 100%;
width: 100%;
&.mobile.openSidebar{
z-index: 1000;
top: 0;
}
}
.drawer-bg {
background: #000;
opacity: 0.3;
width: 100%;
top: 0;
height: 100%;
position: absolute;
z-index: 999;
}
.fixed-header {
position: fixed;
top: 0;
right: 0;
z-index: 9;
width: calc(100% - #{$sideBarWidth});
transition: width 0.28s;
}
.hideSidebar .fixed-header {
width: calc(100% - 54px)
}
.mobile .fixed-header {
width: 100%;
}
::v-deep .el-button.is-circle {
padding: 8px;
}
</style>

@ -12,19 +12,25 @@
</template>
<template v-else>
<el-submenu ref="subMenu" :index="/^\/+/.test(resolvePath(item.path)) ? Math.random().toString() : resolvePath(item.path)" popper-append-to-body>
<template slot="title">
<app-link :to="item.children[0].path">
<el-menu-item :index="item.children[0].path">
<icon :icon="item.meta.icon" />
<span>{{ item.meta.title }}</span>
</template>
<navbar-item
v-for="child in item.children"
:key="child.key"
:item="child"
:base-path="resolvePath(child.path)"
class="nest-menu"
/>
</el-submenu>
</el-menu-item>
</app-link>
<!-- <el-submenu ref="subMenu" :index="/^\/+/.test(resolvePath(item.path)) ? Math.random().toString() : resolvePath(item.path)" popper-append-to-body>-->
<!-- <template slot="title">-->
<!-- <icon :icon="item.meta.icon" />-->
<!-- <span>{{ item.meta.title }}</span>-->
<!-- </template>-->
<!-- <navbar-item-->
<!-- v-for="child in item.children"-->
<!-- :key="child.key"-->
<!-- :item="child"-->
<!-- :base-path="resolvePath(child.path)"-->
<!-- class="nest-menu"-->
<!-- />-->
<!-- </el-submenu>-->
</template>
</div>
</template>

@ -10,7 +10,7 @@
<img class="navbar-brand__img" :src="require('@/assets/title.png')" alt="">
</router-link>
</div>
<div v-show="$route.meta.isModule" class="toggle-sidebar" @click="toggleIframeSidebarOpened">
<div v-show="$route.path !== '/dashboard'" class="toggle-sidebar" @click="toggleIframeSidebarOpened">
<i v-show="isIframeSidebarOpened" class="el-icon-s-fold" />
<i v-show="!isIframeSidebarOpened" class="el-icon-s-unfold" />
</div>
@ -182,6 +182,8 @@ export default {
if (iframe) {
iframe.contentWindow.toggleSideBar()
this.isIframeSidebarOpened = Cookies.get('sidebarStatus') ? !!+Cookies.get('sidebarStatus') : true
} else {
this.$store.commit('app/TOGGLE_SIDEBAR')
}
},
handleFullscreen() {

@ -20,7 +20,7 @@ export default {
if (icon.includes('el-icon')) {
vnodes.push(<i class={[icon, 'sub-el-icon']} />)
} else {
vnodes.push(<svg-icon icon-class={icon}/>)
vnodes.push(<svg-icon icon-class={icon} class="sub-el-icon" />)
}
}
@ -35,7 +35,9 @@ export default {
<style scoped>
.sub-el-icon {
color: currentColor;
width: 1em;
height: 1em;
font-size: 16px;
width: 16px;
height: 16px;
margin-right: 5px;
}
</style>

@ -1,6 +1,5 @@
<template>
<div :class="{'has-logo':showLogo}">
<logo v-if="showLogo" :collapse="isCollapse" />
<el-scrollbar wrap-class="scrollbar-wrapper">
<el-menu
:default-active="activeMenu"
@ -20,18 +19,20 @@
<script>
import { mapGetters } from 'vuex'
import Logo from './Logo'
import SidebarItem from './SidebarItem'
import variables from '@/styles/variables.scss'
import variables from '@/styles/sidebar-variables.scss'
export default {
components: { SidebarItem, Logo },
components: { SidebarItem },
computed: {
...mapGetters([
'sidebar'
'sidebar',
'permission_routes'
]),
routes() {
return this.$router.options.routes
const resRoutes = this.permission_routes.find(i => i.name === this.$route.matched[0].name)?.children || []
console.log(resRoutes)
return resRoutes
},
activeMenu() {
const route = this.$route

@ -3,13 +3,16 @@ import { permissions } from '@/api/me'
import Layout from '@/layout'
import Nested from '@/layout/nested.vue'
import Wujie from '@/views/wujie'
import SiderbarLayout from '@/layout/SiderbarLayout.vue'
const loadView = (view) => {
return (resolve) => require([`@/views${view}`], resolve)
}
const componentHandle = (path, route) => {
if (/^#+/.test(path) && route.pid === 0) {
if (/^#+/.test(path) && route.pid === 0 && route.children.length <= 1) {
return Layout
} else if (/^#+/.test(path) && route.pid === 0 && route.children.length > 1) {
return SiderbarLayout
} else if (/^#+/.test(path) && route.pid !== 0) {
return Nested
} else if (/^\/./.test(path)) {
@ -31,6 +34,7 @@ export function filterAsyncRoutes(routes) {
name: route.name,
hidden: !route.visible,
meta: {
id: route.id,
title: route.title,
icon: route.icon,
guard: route.guard_name,
@ -39,7 +43,7 @@ export function filterAsyncRoutes(routes) {
// TODO:修改地址
// moduleUri: /^\/./.test(route.path) ? '' : `https://cz-hjjc.115.langye.net/${route.path}`,
moduleUri: /^\/./.test(route.path) ? '' : `/${route.path}`,
moduleName: /^\/./.test(route.path) ? '' : route.path
moduleName: /^\/./.test(route.path) ? '' : route.path,
}
}

@ -2,7 +2,6 @@
@import './mixin.scss';
@import './transition.scss';
@import './element-ui.scss';
@import './sidebar.scss';
body {
height: 100%;

@ -71,7 +71,7 @@
}
}
.tool-item + .tool-item {
margin-left: 6px;
margin-left: 10px;
}
}
.nav-info {
@ -150,3 +150,61 @@
}
}
}
@import "variables.scss";
#navbar-menu {
.sidebar-item {
display: inline-block;
.el-menu-item:hover ,.el-submenu__title:hover {
color: $menuActiveText !important;
background-color: transparent !important;
}
}
.el-menu-item, .el-submenu__title {
height: 54px;
line-height: 54px;
}
.el-submenu__icon-arrow {
display: none;
}
}
.navbar {
.el-menu--horizontal {
border-bottom: none !important;
overflow: hidden;
white-space: nowrap;
}
}
#navbar-menu-mobile {
position: absolute;
left: 0;
right: 0;
box-shadow: 0 1px 6px rgba(0,0,0,.2);
.el-menu {
border-right: none;
.el-menu-item, .el-submenu__title{
height: auto;
line-height: inherit;
min-height: 2rem;
display: flex;
align-items: center;
}
.el-submenu.is-active .el-submenu__title {
border-bottom: 0;
color: var(--theme-color);
}
}
.el-menu {
background-color: #fff !important;
}
.sidebar-item {
.el-menu-item ,.el-submenu__title {
color: #333 !important;
background-color: #fff !important;
}
}
}

@ -0,0 +1,27 @@
// sidebar
$menuText:#606266;
$menuActiveText:#303133;
$subMenuActiveText:#338de3; //https://github.com/ElemeFE/element/issues/12951
$menuBg:#ffffff;
$menuHover:#e0f2ff;
$menuActiveBg:#dcf3ff;
$subMenuBg:#ffffff;
$subMenuHover:#edf6ff;
$submenuActiveBg:#dcf3ff;
$sideBarWidth: 210px;
// the :export directive is the magic sauce for webpack
// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
:export {
menuText: $menuText;
menuActiveText: $menuActiveText;
subMenuActiveText: $subMenuActiveText;
menuBg: $menuBg;
menuHover: $menuHover;
subMenuBg: $subMenuBg;
subMenuHover: $subMenuHover;
sideBarWidth: $sideBarWidth;
}

@ -1,67 +1,281 @@
@import "variables";
#navbar-menu {
.sidebar-item {
display: inline-block;
#app {
.el-menu-item:hover ,.el-submenu__title:hover {
color: $menuActiveText !important;
background-color: transparent !important;
.main-container {
min-height: calc(100vh - 54px);
transition: margin-left .28s;
margin-left: $sideBarWidth;
position: relative;
}
.sidebar-container {
box-shadow: 2px 0 8px 0 rgba(29,35,41,.05);
transition: width 0.28s;
width: $sideBarWidth !important;
background-color: $menuBg;
position: fixed;
font-size: 0px;
top: 54px;
bottom: 0;
left: 0;
z-index: 1001;
overflow: hidden;
.hamburger-container {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
}
// 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: 0px;
}
.el-scrollbar {
height: 100%;
}
&.has-logo {
.el-scrollbar {
height: calc(100% - 50px);
}
}
.is-horizontal {
display: none;
}
a {
display: inline-block;
width: 100%;
overflow: hidden;
}
.svg-icon {
margin-right: 16px;
}
.sub-el-icon {
margin-right: 12px;
margin-left: -2px;
}
.el-menu {
border: none;
height: 100%;
width: 100% !important;
}
// menu hover
.submenu-title-noDropdown,
.el-submenu__title {
&:hover {
background-color: $menuHover !important;
position: relative;
&::before {
content: '';
position: absolute;
background-color: var(--theme-color);
inset: 0 0 0 0;
opacity: 0.36;
}
}
}
.is-active{
//background-color: $menuActiveBg !important;
position: relative;
&::before {
content: '';
position: absolute;
background-color: var(--theme-color);
inset: 0 0 0 0;
opacity: 0.36;
}
}
.is-active>.el-submenu__title {
color: var(--theme-color) !important;
}
& .nest-menu .el-submenu>.el-submenu__title,
& .el-submenu .el-menu-item {
min-width: $sideBarWidth !important;
background-color: $subMenuBg !important;
&:hover {
//background-color: $subMenuHover !important;
color: var(--theme-color) !important;
position: relative;
&::before {
content: '';
position: absolute;
background-color: var(--theme-color);
inset: 0 0 0 0;
opacity: 0.36;
}
}
&.is-active{
position: relative;
//background-color: $submenuActiveBg !important;
border-right: 5px solid var(--theme-color) !important;
&::before {
content: '';
position: absolute;
background-color: var(--theme-color);
inset: 0 0 0 0;
opacity: 0.36;
}
}
}
}
.hideSidebar {
.sidebar-container {
width: 54px !important;
}
.main-container {
margin-left: 54px;
}
.submenu-title-noDropdown {
padding: 0 !important;
position: relative;
.el-tooltip {
padding: 0 !important;
.svg-icon {
margin-left: 20px;
}
.sub-el-icon {
margin-left: 19px;
}
}
}
.el-submenu {
overflow: hidden;
&>.el-submenu__title {
padding: 0 !important;
.svg-icon {
margin-left: 20px;
}
.sub-el-icon {
margin-left: 19px;
}
.el-submenu__icon-arrow {
display: none;
}
}
}
.el-menu--collapse {
.el-submenu {
&>.el-submenu__title {
&>span {
height: 0;
width: 0;
overflow: hidden;
visibility: hidden;
display: inline-block;
}
}
}
}
}
.el-menu-item, .el-submenu__title {
height: 54px;
line-height: 54px;
.el-menu--collapse .el-menu .el-submenu {
min-width: $sideBarWidth !important;
}
.el-submenu__icon-arrow {
display: none;
// mobile responsive
.mobile {
.main-container {
margin-left: 0px;
}
.sidebar-container {
transition: transform .28s;
width: $sideBarWidth !important;
}
&.hideSidebar {
.sidebar-container {
pointer-events: none;
transition-duration: 0.3s;
transform: translate3d(-$sideBarWidth, 0, 0);
}
}
}
}
.navbar {
.el-menu--horizontal {
border-bottom: none !important;
overflow: hidden;
white-space: nowrap;
.withoutAnimation {
.main-container,
.sidebar-container {
transition: none;
}
}
}
.el-submenu__title,.el-menu-item {
padding: 0 14px!important;
}
.el-menu--collapse .el-menu .el-submenu, .el-menu--popup {
min-width: 124px !important;
background-color: $subMenuBg !important;
}
.el-menu--horizontal .el-menu .el-menu-item, .el-menu--horizontal .el-menu .el-submenu__title {
color: $subMenuText !important;
}
#navbar-menu-mobile {
position: absolute;
left: 0;
right: 0;
box-shadow: 0 1px 6px rgba(0,0,0,.2);
.el-menu {
border-right: none;
.el-menu-item, .el-submenu__title{
height: auto;
line-height: inherit;
min-height: 2rem;
display: flex;
align-items: center;
}
.el-submenu.is-active .el-submenu__title {
border-bottom: 0;
color: var(--theme-color);
// when menu collapsed
.el-menu--vertical {
&>.el-menu {
.svg-icon {
margin-right: 16px;
}
.sub-el-icon {
margin-right: 12px;
margin-left: -2px;
}
}
.el-menu {
background-color: #fff !important;
.nest-menu .el-submenu>.el-submenu__title,
.el-menu-item {
&:hover {
// you can use $subMenuHover
//background-color: $menuHover !important;
position: relative;
&::before {
content: '';
position: absolute;
background-color: var(--theme-color);
inset: 0 0 0 0;
opacity: 0.36;
}
}
}
.sidebar-item {
.el-menu-item ,.el-submenu__title {
color: #333 !important;
background-color: #fff !important;
// the scroll bar appears when the subMenu is too long
>.el-menu--popup {
max-height: 100vh;
overflow-y: auto;
&::-webkit-scrollbar-track-piece {
background: #d3dce6;
}
&::-webkit-scrollbar {
width: 6px;
}
&::-webkit-scrollbar-thumb {
background: #99a9bf;
border-radius: 20px;
}
}
}

@ -5,7 +5,7 @@
$menuText: hsla(0,0%,100%,.7);
$subMenuText: #333;
$menuActiveText: #fff;
$subMenuActiveText:#f4f4f5; //https://github.com/ElemeFE/element/issues/12951
$subMenuActiveText:#f4f4f5;
$menuBg: transparent;
$menuHover: transparent;
@ -15,8 +15,6 @@ $subMenuHover: #001528;
$sideBarWidth: 210px;
$navBarHeight: 200px;
// the :export directive is the magic sauce for webpack
// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
:export {
menuText: $menuText;
menuActiveText: $menuActiveText;

Loading…
Cancel
Save