274 lines
7.9 KiB
Vue
274 lines
7.9 KiB
Vue
<template>
|
||
<a-card :bordered="false">
|
||
<a-layout id="components-layout-demo-custom-trigger" style="height: 100%">
|
||
<a-layout-sider theme="light" v-model="collapsed" :trigger="null" collapsible width="320px">
|
||
<div>
|
||
<a-menu
|
||
id="dddddd"
|
||
:defaultSelectedKeys="defaultSelectedKeys"
|
||
:defaultOpenKeys="defaultOpenKeys"
|
||
mode="inline"
|
||
:inline-collapsed="collapsed"
|
||
@openChange="onOpenChange"
|
||
@click="menuClick"
|
||
:inlineIndent="13"
|
||
>
|
||
<!-- 菜单遍历的开始 -->
|
||
<template v-for="(item, index) in menus">
|
||
<!-- 如果当前遍历项没有children,视为子菜单项,注意所有的key都是path用于路由跳转,以及当前选中记录 -->
|
||
<a-menu-item v-if="!item.children" :key="item.path">
|
||
<span>{{ item.meta.title }}</span>
|
||
<div class="line"></div>
|
||
</a-menu-item>
|
||
<!-- 否则视为子菜单,传入菜单信息并且运用下面定义的函数式组件 -->
|
||
<sub-menu v-else :key="item.path" :menu-info="item" :menu-index="index" />
|
||
</template>
|
||
</a-menu>
|
||
</div>
|
||
</a-layout-sider>
|
||
<a-layout style="background-color: aliceblue">
|
||
<keep-alive>
|
||
<router-view v-if="keepAlive" />
|
||
</keep-alive>
|
||
<router-view v-if="!keepAlive" />
|
||
</a-layout>
|
||
</a-layout>
|
||
</a-card>
|
||
</template>
|
||
<script>
|
||
import { Menu } from 'ant-design-vue'
|
||
const SubMenu = {
|
||
template: `
|
||
<a-sub-menu :key="menuInfo.path" :id="menuIndex" v-bind="$props" v-on="$listeners">
|
||
<span slot="title" >
|
||
<span>{{ menuInfo.meta.title }}</span>
|
||
<div class="line"></div>
|
||
</span>
|
||
<template v-for="item in menuInfo.children">
|
||
<a-menu-item v-if="!item.children" :key="item.path" class="sub-menu-children">
|
||
<i :class="item.icon" />
|
||
<span>{{ item.meta.title }}</span>
|
||
</a-menu-item>
|
||
<sub-menu v-else :key="item.path" :menu-info="item" />
|
||
</template>
|
||
</a-sub-menu>
|
||
`,
|
||
name: 'SubMenu',
|
||
// must add isSubMenu: true 此项必须被定义
|
||
isSubMenu: true,
|
||
props: {
|
||
// 解构a-sub-menu的属性,也就是文章开头提到的为什么使用函数式组件
|
||
...Menu.SubMenu.props,
|
||
// 接收父级传递过来的菜单信息
|
||
menuInfo: {
|
||
type: Object,
|
||
default: () => ({}),
|
||
},
|
||
menuIndex: {
|
||
type: Number,
|
||
},
|
||
},
|
||
}
|
||
export default {
|
||
name: 'menuTree',
|
||
components: { 'sub-menu': SubMenu },
|
||
computed: {
|
||
keepAlive() {
|
||
return this.$route.meta.keepAlive
|
||
},
|
||
},
|
||
data() {
|
||
const collapsed = false
|
||
return {
|
||
collapsed,
|
||
selectedKeys: '',
|
||
openKeys: '',
|
||
handleClick: '',
|
||
titleClick: '',
|
||
menu: [],
|
||
// 展开的父菜单项
|
||
openKeys: [],
|
||
// 选中的子菜单项
|
||
defaultSelectedKeys: [],
|
||
defaultOpenKeys: [],
|
||
rootSubmenuKeys: ['/istatistics/imsData', '/istatistics'],
|
||
}
|
||
},
|
||
created() {
|
||
var permissionList = this.$store.getters.permissionList
|
||
permissionList.forEach((f) => {
|
||
if (f.name === 'istatistics') {
|
||
this.menus = f.children
|
||
}
|
||
})
|
||
this.initDefaultKeys(this.menus[0])
|
||
// 将从缓存中取出openKeys
|
||
const openKeys = window.sessionStorage.getItem('openKeys')
|
||
if (openKeys) {
|
||
// 存在即赋值
|
||
this.openKeys = JSON.parse(openKeys)
|
||
}
|
||
},
|
||
methods: {
|
||
// 点击菜单,路由跳转,注意的是当点击MenuItem才会触发此函数
|
||
menuClick({ item, key, keyPath }) {
|
||
// var parentPath = item._props.parentMenu._props.eventKey;
|
||
// var parentTitle = parentPath.substring(parentPath.lastIndexOf("/") + 1, parentPath.length)
|
||
// var par = {"type": "q"}
|
||
// 获取到当前的key,并且跳转
|
||
this.$router.push({
|
||
path: key,
|
||
})
|
||
},
|
||
initDefaultKeys(data) {
|
||
this.defaultOpenKeys.push(data.path)
|
||
data.children.some((f) => {
|
||
if (f.children) {
|
||
// 第一个节点展开
|
||
this.defaultOpenKeys.push(f.path)
|
||
this.initDefaultKeys(f.children[0])
|
||
} else {
|
||
// 选中
|
||
this.defaultSelectedKeys.push(f.path)
|
||
return true
|
||
}
|
||
})
|
||
},
|
||
onOpenChange(openKeys) {
|
||
// 将当前打开的父级菜单存入缓存中
|
||
window.sessionStorage.setItem('openKeys', JSON.stringify(openKeys))
|
||
// 控制只打开一个
|
||
const latestOpenKey = openKeys.find((key) => this.openKeys.indexOf(key) === -1)
|
||
if (this.rootSubmenuKeys.indexOf(latestOpenKey) === -1) {
|
||
this.openKeys = openKeys
|
||
} else {
|
||
this.openKeys = latestOpenKey ? [latestOpenKey] : []
|
||
}
|
||
},
|
||
},
|
||
}
|
||
</script>
|
||
<style lang="less" scoped>
|
||
.ant-layout {
|
||
height: 100%;
|
||
.ant-layout-sider-light {
|
||
background: none;
|
||
}
|
||
}
|
||
.ant-menu {
|
||
width: 320px;
|
||
height: 939px;
|
||
background-color: #022024;
|
||
border: solid 1px #0c6a66;
|
||
opacity: 0.9;
|
||
|
||
font-family: MicrogrammaD-MediExte;
|
||
font-size: 20px;
|
||
font-weight: bold;
|
||
font-stretch: normal;
|
||
line-height: 16px;
|
||
letter-spacing: 1px;
|
||
color: #ffffff;
|
||
|
||
::v-deep {
|
||
.ant-menu-inline.ant-menu-sub {
|
||
color: #60b3a6;
|
||
background-color: #032d31 !important;
|
||
}
|
||
.ant-menu-submenu-selected {
|
||
color: #ade6ee;
|
||
}
|
||
.ant-menu-submenu > .ant-menu-submenu-title,
|
||
.ant-menu-item {
|
||
font-size: 20px;
|
||
}
|
||
.ant-menu-sub.ant-menu-inline > .ant-menu-submenu > .ant-menu-submenu-title {
|
||
font-size: 18px;
|
||
font-weight: bold;
|
||
}
|
||
.sub-menu-children {
|
||
font-size: 16px;
|
||
}
|
||
.ant-menu-inline .ant-menu-item::after {
|
||
border-right: none;
|
||
}
|
||
}
|
||
.ant-menu-submenu-open {
|
||
font-family: MicrogrammaD-MediExte;
|
||
font-weight: bold;
|
||
font-stretch: normal;
|
||
line-height: 43px;
|
||
// letter-spacing: 2px;
|
||
color: #ade6ee;
|
||
}
|
||
.line {
|
||
width: 70px;
|
||
height: 5px;
|
||
background-color: #0cebc9;
|
||
margin-top: 10px;
|
||
position: absolute;
|
||
bottom: -1px;
|
||
}
|
||
}
|
||
::v-deep .ant-menu-inline > .ant-menu-submenu[menuindex] > .ant-menu-submenu-title {
|
||
border-bottom: 1px solid #0cecca66;
|
||
color: #ffffff !important;
|
||
height: 47px;
|
||
.line {
|
||
width: 96%;
|
||
height: 5px;
|
||
background-image: linear-gradient(
|
||
to right,
|
||
#0cebc9 70px,
|
||
transparent 10px,
|
||
transparent calc(100% - 10px),
|
||
transparent calc(100% - 10px)
|
||
);
|
||
margin-top: 10px;
|
||
position: absolute;
|
||
bottom: -1px;
|
||
}
|
||
.line:after {
|
||
content: '';
|
||
display: block;
|
||
height: 100%;
|
||
width: 5px;
|
||
position: absolute;
|
||
top: 2px;
|
||
right: 0;
|
||
background-color: #0cebc9;
|
||
}
|
||
}
|
||
::v-deep {
|
||
//菜单打开状态/\箭头左\
|
||
.ant-menu-submenu-open.ant-menu-submenu[menuindex] > .ant-menu-submenu-title > .ant-menu-submenu-arrow::before {
|
||
width: 0px;
|
||
transform: rotate(45deg) translateX(4.5px);
|
||
}
|
||
//菜单打开状态/\箭头右\
|
||
.ant-menu-submenu-open.ant-menu-submenu[menuindex] > .ant-menu-submenu-title > .ant-menu-submenu-arrow::after {
|
||
content: url(~@/assets/images/station-operation/toggle.png);
|
||
width: 0px;
|
||
transform: rotate(-90deg) translateX(-6.5px) translateY(-8.5px);;
|
||
}
|
||
//菜单收起状态\/箭头左\
|
||
.ant-menu-inline-collapsed .ant-menu-submenu-arrow::before,
|
||
.ant-menu-submenu[menuindex] > .ant-menu-submenu-title .ant-menu-submenu-arrow::before {
|
||
width: 0px;
|
||
transform: rotate(-45deg) translateX(4.5px);
|
||
}
|
||
//菜单收起状态\/箭头右/
|
||
.ant-menu-inline-collapsed .ant-menu-submenu-arrow::after,
|
||
.ant-menu-submenu[menuindex] > .ant-menu-submenu-title .ant-menu-submenu-arrow::after {
|
||
content: url(~@/assets/images/station-operation/toggle.png);
|
||
width: 0px;
|
||
transform: rotate(90deg) translateX(-5.5px) translateY(-19.5px);
|
||
}
|
||
|
||
.ant-menu:not(.ant-menu-horizontal) .ant-menu-item-selected {
|
||
background-color: #075259 !important;
|
||
color: #0cecca;
|
||
}
|
||
}
|
||
</style>
|
||
|