new-storepc-view/src/layout/components/Sidebar/index.vue

479 lines
14 KiB
Vue

<template>
<div :key="sideBar1 && isCollapse" :class="{ 'has-logo': showLogo }">
<logo v-if="showLogo" :collapse="isCollapse" :sideBar1="sideBar1" />
<el-scrollbar>
<el-menu
v-if="!sideBar1"
:default-active="activeMenu"
:collapse="isCollapse"
:background-color="variables.menuBg"
:text-color="variables.menuText"
:unique-opened="true"
:active-text-color="variables.menuActiveText"
:collapse-transition="false"
mode="vertical"
class="subMenu1"
>
<template>
<sidebar-item
v-for="route in menuList"
:key="route.route"
:item="route"
:base-path="route.route"
/>
</template>
</el-menu>
<template v-else>
<template v-if="!isCollapse">
<ul v-for="item in menuList" :key="item.route" style="padding: 0;"><li><div class="menu menu-one"><div class="menu-item" :class="{ active: pathCompute(item) }" @click="goPath(item)"><i :class="'menu-icon el-icon-' + item.icon"></i><span>{{ item.menu_name }}</span></div></div></li></ul>
</template>
<!--一级菜单点击后二级菜单展开样式-->
<el-menu
v-if="subMenuList && subMenuList.length > 0 && !isCollapse"
class="menuOpen"
:default-active="activeMenu"
background-color="#ffffff"
text-color="#303133"
:unique-opened="false"
active-text-color="#303133"
mode="vertical"
>
<div style="height: 100%;">
<div class="sub-title">{{ menu_name }}</div>
<el-scrollbar wrap-class="scrollbar-wrapper">
<div v-for="(itm, idx) in subMenuList" :key="idx">
<template
v-if="
hasOneShowingChild(itm.children, itm) &&
(!onlyOneChild.children ||
onlyOneChild.noShowingChildren) &&
!itm.alwaysShow
"
>
<app-link
v-if="onlyOneChild"
:to="resolvePath(onlyOneChild.route)"
>
<el-menu-item :index="resolvePath(onlyOneChild.route)">
<item :icon="onlyOneChild.icon || (itm && itm.icon)":title="onlyOneChild.menu_name"/>
</el-menu-item>
</app-link>
</template>
<el-submenu
v-else
ref="subMenu"
:index="resolvePath(itm.route)"
popper-append-to-body
>
<template slot="title">
<item
v-if="itm"
:icon="itm && itm.icon"
:title="itm.menu_name"
/>
</template>
<sidebar-item
v-for="(child, index) in itm.children"
:key="index"
:is-nest="true"
:item="child"
:base-path="resolvePath(child.route)"
:isCollapse="isCollapse"
class="nest-menu"
/>
</el-submenu>
</div>
</el-scrollbar>
</div>
</el-menu>
<template v-if="isCollapse">
<el-menu
:default-active="activeMenu"
:collapse="isCollapse"
:background-color="variables.menuBg"
:text-color="variables.menuText"
:unique-opened="true"
active-text-color="#ffffff"
:collapse-transition="false"
mode="vertical"
class="menuStyle2"
popper-class="styleTwo"
>
<template>
<sidebar-item
v-for="route in menuList"
:key="route.route"
:item="route"
:base-path="route.route"
class="style2"
/>
</template>
</el-menu>
</template>
</template>
</el-scrollbar>
</div>
</template>
<script>
import path from "path";
import { mapGetters, mapMutations, mapState } from "vuex";
import Logo from "./Logo";
import AppLink from "./Link";
import SidebarItem from "./SidebarItem";
import Item from "./Item";
import { isExternal } from "@/utils/validate";
import FixiOSBug from "./FixiOSBug";
import variables from "@/styles/variables.scss";
export default {
components: { SidebarItem, Logo, AppLink, Item },
mixins: [FixiOSBug],
data() {
this.onlyOneChild = null;
return {
sideBar1:
window.localStorage.getItem("sidebarStyle") == "a" ? false : true,
menu_name: "",
list: this.$store.state.user.menuList,
subMenuList: [],
activePath: "",
isShow: false,
};
},
computed: {
...mapGetters(["permission_routes", "sidebar", "menuList"]),
...mapState({
sidebar: state => state.app.sidebar,
sidebarRouters: state => state.user.sidebarRouters,
sidebarStyle: state => state.user.sidebarStyle,
// 所有的路由信息
routers() {
let routers = this.$store.state.user.menuList
? this.$store.state.user.menuList
: [];
return routers;
}
}),
activeMenu() {
const route = this.$route;
const { meta, path } = route;
// if set path, the sidebar will highlight the path you set
if (meta.activeMenu) {
return meta.activeMenu;
}
return path;
},
showLogo() {
return this.$store.state.settings.sidebarLogo;
},
variables() {
return variables;
},
isCollapse() {
return !this.sidebar.opened;
}
},
watch: {
sidebarStyle(newValue, oldValue) {
this.sideBar1 = newValue == "a" && oldValue != "a" ? false : true;
this.setMenuWidth();
},
sidebar: {
handler(newVal, oldVal) {
if(this.sideBar1){
this.getSubMenu();
}
},
deep: true // 对象内部属性的监听,关键。
},
$route:{
handler(newVal, oldVal) {
if(this.sideBar1){
this.getSubMenu();
}
},
deep: true // 对象内部属性的监听,关键。
},
},
mounted() {
this.getMenus();
if(this.sideBar1){
this.getSubMenu();
}else{
this.setMenuWidth();
}
},
methods: {
// 菜单选中后左侧宽度数值存储
setMenuWidth() {
if (this.sideBar1) {
if (this.subMenuList && this.subMenuList.length > 0 && !this.isCollapse) {
this.$store.commit("user/SET_SIDEBAR_WIDTH", 270);
} else {
this.$store.commit("user/SET_SIDEBAR_WIDTH", 130);
}
} else {
this.$store.commit("user/SET_SIDEBAR_WIDTH", 180);
}
},
ishttp(url) {
return url.indexOf("http://") !== -1 || url.indexOf("https://") !== -1;
},
getMenus() {
this.$store.dispatch("user/getMenus", {
that: this
});
},
hasOneShowingChild(children = [], parent) {
const showingChildren = children.filter(item => {
if (item.hidden) {
return false;
} else {
// Temp set(will be used if only has one showing child)
this.onlyOneChild = item;
return true;
}
});
// When there is only one child router, the child router is displayed by default
if (showingChildren.length === 1) {
return true;
}
// Show parent if there are no child router to display
if (showingChildren.length === 0) {
this.onlyOneChild = { ...parent, path: "", noShowingChildren: true };
return true;
}
return false;
},
resolvePath(routePath) {
if (isExternal(routePath)) {
return routePath;
}
if (isExternal(this.basePath)) {
return routePath;
}
return path.resolve(routePath, routePath);
},
goPath(item) {
this.menu_name = item.menu_name;
if (item.children) {
this.$store.commit("user/SET_SIDEBAR_WIDTH", 270);
// console.log(this.pathCompute(item.children)+ 'sdxsds');
this.subMenuList = item.children;
window.localStorage.setItem("subMenuList",this.subMenuList);
let goUrl = this.resolvePath(this.getChild(item.children)[0].route);
item.route = goUrl;
this.$router.push({
path: goUrl
});
} else {
this.$store.commit("user/SET_SIDEBAR_WIDTH", 130);
this.subMenuList = [];
window.localStorage.setItem("subMenuList",[]);
let goUrl = this.resolvePath(item.route);
this.$router.push({
path: goUrl
});
}
},
getChild(data) {
const result = [];
data.forEach(item => {
// 遍历树
const loop = data => {
let child = data.children;
if (child) {
// 是否有子节点,有则继续遍历下一级,无则是叶子节点
for (let i = 0; i < child.length; i++) {
loop(child[i]);
}
} else {
result.push(data);
}
};
loop(item);
});
return result;
},
//判断当前页面父级菜单
pathCompute(data) {
// console.log(this.$route)
const loop = child => {
// 是否有子节点,有则继续遍历下一级,无则是叶子节点
for (let i = 0; i < child.length; i++) {
if(this.$route.path == child[i]['route'] || this.$route.meta.activeMenu == child[i]['route']){
return true;
}
if(loop(child[i].children || [])){
return true;
};
}
return false;
};
if(!loop(data.children || [])){
return this.$route.path == data.route;
}
return true;
},
// 获取当前一级菜单的二级菜单
getSubMenu(){
for (let i = 0; i < this.menuList.length; i++) {
if(this.pathCompute(this.menuList[i])){
this.subMenuList = this.menuList[i].children;
this.menu_name = this.menuList[i].menu_name;
window.localStorage.setItem("subMenuList",this.menuList[i].children);
this.setMenuWidth();
return;
}
}
},
...mapMutations("user", ["SET_MENU_LIST"])
}
};
</script>
<style lang="scss" scoped>
.menu-one {
position: relative;
.menu-item {
padding: 0 20px;
// height: 50px;
line-height: 50px;
font-size: 14px;
transition: border-color 0.3s, background-color 0.3s, color 0.3s;
box-sizing: border-box;
white-space: nowrap;
display: flex;
align-items: center;
cursor: pointer;
width: 130px;
.menu-icon {
font-size: 18px;
margin-right: 5px;
vertical-align: middle;
text-align: center;
color: #909399;
width: 24px;
}
span{
display: inline-block;
color: #bfcbd9;
}
&.active {
background: rgba(67, 127, 253, 0.5);
}
&:hover {
background: rgba(67, 127, 253, 0.2);
}
}
.menu-two {
position: absolute;
left: 130px;
top: 0;
box-shadow: 2px 0px 4px 0px rgba(0, 0, 0, 0.06);
width: 140px;
background: #000000;
.two-list {
font-size: 13px;
color: #ffffff;
line-height: 46px;
padding: 0 20px;
}
}
}
.el-scrollbar {
height: calc(100vh - 50px);
}
.menuOpen {
width: 140px !important;
height: 100%;
background: #ffffff;
position: fixed;
top: 0;
left: 130px;
box-shadow: 2px 0px 4px 0px rgba(0, 0, 0, 0.06);
.subMenu2{
background: #ffffff!important;
}
.sub-title {
font-weight: 600;
color: #303133;
font-size: 18px;
padding: 20px;
}
/deep/.el-menu-item,/deep/.el-submenu__title {
height: 46px;
line-height: 46px;
// background: #ffffff !important;
color: #303133 !important;
font-size: 13px;
&:hover {
background: #ECF2FE !important;
color: #303133 !important;
.el-submenu__title{
background: #ECF2FE !important;
color: #303133 !important;
}
}
}
/deep/.subMenu2 .el-submenu__title{
padding-left: 15px!important;
}
/deep/.router-link-active .el-menu-item, /deep/.el-menu-item.is-active,/deep/ .router-link-active .el-submenu__title{
background: #ECF2FE !important;
}
}
/deep/.menus-new .el-icon-arrow-down {
display: none;
}
/deep/.el-submenu .el-menu-item {
min-width: 140px !important;
font-size: 13px;
}
/deep/.menuOpen .el-menu-item,/deep/.menuOpen .el-menu-item,/deep/.menuOpen .el-submenu__title{
padding-left: 15px!important;
}
/deep/.menuOpen .subMenu2 .el-submenu__title{
padding-left: 30px!important;
}
/deep/.style2 .is-active,/deep/.style2>.el-submenu:hover{
background: #182848!important;
}
/deep/.style2.menuTwo .el-submenu__title{
display: flex;
align-items: center;
}
/deep/.subMenu1 .menuTwo .el-submenu__title:hover,/deep/.subMenu1 .menuTwo .el-menu-item:hover{
background: #182848!important;
}
.menu-link{
display: flex!important;
align-items: center;
width: 100%;
}
/deep/.menuStyle2 .el-submenu>.el-submenu__title>span{
display: inline-block!important;
visibility: visible!important;
width: auto!important;
height: auto!important;
}
/deep/.menuStyle2 .el-submenu{
padding: 0 20px;
}
/deep/.menuStyle2 .el-submenu .el-submenu__title{
background: transparent!important;
}
/deep/.subMenu1 .menuTwo .el-menu{
background: #030C17!important;
}
/deep/.subMenu1 .menuTwo .nest-menu .el-submenu>.el-submenu__title,/deep/.subMenu1 .menuTwo .el-submenu .el-menu-item{
background: #030c17!important;
}
</style>