<template>
<div class="MySider">
<div class="logo" @click="handleCollapsed" :class="{ collapsed: collapsed }">
<img :src="collapsed ? logo_c : logo" />
</div>
<a-menu theme="light" v-model:openKeys="openKeys" v-model:selectedKeys="selectedKeys" mode="inline"
:inlineCollapsed="collapsed">
<template v-for="item of showList" :key="item.path">
<a-menu-item :key="item.path" v-if="item.meta.is_leaf" @click="routerChange(item.path)">
<i class="icon" :class="item.meta.icon" />
<span :class="{ 'collapsed-title': collapsed }">{{
item.meta.title_zh
}}</span>
</a-menu-item>
<a-sub-menu :key="'sub-menu' + item.path" v-else>
<template #title>
<i class="icon" :class="item.meta.icon" />
<span v-show="!collapsed">{{ item.meta.title_zh }}</span>
</template>
<template v-for="i of item.children">
<a-sub-menu :key="'sub-menu' + i.path" v-if="i.children && i.children.length > 0">
<template #title>
<span>{{ i.meta.title_zh }}</span>
</template>
<!-- 循环显示三级菜单项 -->
<template v-for="j of i.children">
<a-menu-item :key="'sub-menu' + i.path + '/' + j.path" @click="routerChange(i.path + '/' + j.path)"
v-if="showMenuItem(j)">
<span>{{ j.meta.title_zh }}</span>
</a-menu-item>
</template>
</a-sub-menu>
<!-- 如果没有三级菜单,则显示二级菜单项 -->
<a-menu-item :key="'sub-menu' + item.path + '/' + i.path" @click="routerChange(item.path + '/' + i.path)"
v-else-if="showMenuItem(i)">
<span>{{ i.meta.title_zh }}</span>
</a-menu-item>
</template>
</a-sub-menu>
</template>
</a-menu>
</div>
</template>
<!-- item.children.length === 1 || -->
<script setup>
import { storeToRefs } from "pinia";
import { ref, watch, computed, getCurrentInstance } from "vue";
import { useRoute, useRouter } from "vue-router";
import logo from "@/assets/images/logo.png";
import logo_c from "@/assets/images/logo-c.png";
import Core from "@/core";
import routes from "@/router/routes";
import useStore from "@/core/store/index.js";
const route = useRoute();
const router = useRouter();
const { permission } = useStore();
const { permissionObj, showList } = storeToRefs(permission);
const { getRouterArray } = permission;
const emits = defineEmits(["collapsed"]);
const userType = Core.Data.getUserType();
// 获取展示用列表
getShowList();
function getShowList() {
getRouterArray();
}
const openKeys = ref([]);
const selectedKeys = ref([route.path]);
// 获取当前展开
for (const item of routes) {
if (item.hidden || item.children.length === 1) {
continue;
}
for (const i of item.children) {
if (item.path + "/" + i.path === route.path) {
openKeys.value = [item.path];
break;
}
}
}
// 获取当前高亮
watch(
() => route,
(n) => {
console.log("watch route n:", n);
if (n.matched && n.matched.length >= 2) {
let firstItem = n.matched[0];
let lastItem = n.matched[n.matched.length - 1];
if (firstItem?.meta?.is_leaf) {
selectedKeys.value = [firstItem.path];
} else {
selectedKeys.value = [lastItem.path];
}
} else {
selectedKeys.value = [n.path];
}
// console.log('selectedKeys.value:', selectedKeys.value)
},
{ deep: true, immediate: true }
);
// 路由跳转
function routerChange(path) {
console.log("routerChange path:", path);
router.push(path);
}
// 二级菜单的展示控制
function showMenuItem(i) {
const auth = i.meta ? i.meta.auth || [] : [];
const roles = i.meta ? i.meta.roles : "";
return (
Core.Util.auth(...auth) && !i.hidden && (!roles || roles.includes(userType))
);
}
// 展开收缩
const collapsed = ref(false);
function handleCollapsed() {
collapsed.value = !collapsed.value;
emits("collapsed", collapsed.value);
if (collapsed.value) {
window.document.getElementById("showLayoutSider").style.left = "80px";
} else {
window.document.getElementById("showLayoutSider").style.left = "180px";
}
}
</script>
<style lang='scss' scoped>
.MySider {
height: 100vh;
.logo {
width: 100%;
height: 50px;
display: flex;
align-items: center;
overflow: hidden;
// border-bottom: 1px solid #e6eaee;
img {
max-width: calc(100% - 40px);
margin-left: 20px;
}
&.collapsed {
justify-content: center;
img {
max-width: calc(80%);
max-height: 70%;
margin-left: 0;
}
}
}
i.icon {
margin-right: 14px;
font-size: 14px;
transition: color 0.3s;
}
.collapsed-title {
padding-left: 50px;
}
.ant-menu.ant-menu-inline {
height: calc(100% - 50px);
overflow-y: auto;
overflow-x: hidden;
border-right: 0;
.ant-menu-item {
height: 40px;
line-height: 40px;
margin: 0;
}
.ant-menu-submenu-title {
height: 40px;
line-height: 40px;
margin: 0;
}
.ant-menu-submenu {
.ant-menu-item {
margin-bottom: 0;
}
}
@include scrollbar(2px);
}
.ant-menu-inline .ant-menu-item,
.ant-menu-inline .ant-menu-submenu-title {
width: 100%;
font-size: 13px !important;
color: #334d6e;
.icon {
color: #c2cfe0;
}
}
.ant-menu-inline-collapsed {
border: 0;
}
li.ant-menu-item {
background-color: transparent !important;
}
ul.ant-menu-sub {
background-color: transparent;
}
.ant-menu-item-selected::after {
display: none;
}
.ant-menu-item-selected .ant-menu-title-content,
.ant-menu-item:hover .ant-menu-title-content {
color: $primary;
.icon {
color: $primary;
}
}
.ant-menu-submenu.ant-menu-submenu-selected .ant-menu-submenu-title,
.ant-menu-submenu .ant-menu-submenu-title:hover {
color: $primary;
.icon {
color: $primary;
}
.ant-menu-submenu-arrow {
color: $primary;
}
}
.ant-menu-submenu .ant-menu-item .ant-menu-title-content {
padding-left: 4px;
}
}
.ant-menu-inline-collapsed-tooltip {
font-size: 13px;
i.icon {
display: none;
}
}
.ant-menu-vertical.ant-menu-sub>.ant-menu-item {
width: 100%;
font-size: 13px !important;
margin: 4px 0 !important;
height: 32px;
line-height: 32px;
}
</style>
ant-design-vue三级菜单
最新推荐文章于 2024-06-11 10:30:00 发布