205 lines
4.3 KiB
Vue
205 lines
4.3 KiB
Vue
<template>
|
|
<!-- 如果菜单项没有隐藏则显示 -->
|
|
<div v-if="!item.meta || !item.meta.hidden">
|
|
<!-- 显示只有一个子路由或没有子路由的菜单项 -->
|
|
<template
|
|
v-if="
|
|
hasOneShowingChild(item.children, item as RouteRecordRaw) &&
|
|
(!onlyOneChild.children || onlyOneChild.noShowingChildren) &&
|
|
!item.meta?.alwaysShow
|
|
"
|
|
>
|
|
<AppLink
|
|
v-if="onlyOneChild.meta"
|
|
:to="{
|
|
path: resolvePath(onlyOneChild.path),
|
|
query: onlyOneChild.meta.params,
|
|
}"
|
|
>
|
|
<el-menu-item
|
|
:index="resolvePath(onlyOneChild.path)"
|
|
:class="{ 'submenu-title-noDropdown': !isNest }"
|
|
>
|
|
<SidebarMenuItemTitle
|
|
:icon="onlyOneChild.meta.icon || (item.meta && item.meta.icon)"
|
|
:title="onlyOneChild.meta.title"
|
|
/>
|
|
</el-menu-item>
|
|
</AppLink>
|
|
</template>
|
|
|
|
<!-- 显示具有多个子路由的父菜单项 -->
|
|
<el-sub-menu v-else :index="resolvePath(item.path)" teleported>
|
|
<template #title>
|
|
<SidebarMenuItemTitle
|
|
v-if="item.meta"
|
|
:icon="item.meta && item.meta.icon"
|
|
:title="item.meta.title"
|
|
/>
|
|
</template>
|
|
|
|
<SidebarMenuItem
|
|
v-for="child in item.children"
|
|
:key="child.path"
|
|
:is-nest="true"
|
|
:item="child"
|
|
:base-path="resolvePath(child.path)"
|
|
/>
|
|
</el-sub-menu>
|
|
</div>
|
|
</template>
|
|
<script setup lang="ts">
|
|
defineOptions({
|
|
name: "SidebarMenuItem",
|
|
inheritAttrs: false,
|
|
});
|
|
|
|
import path from "path-browserify";
|
|
import { isExternal } from "@themeDefault/utils";
|
|
import { RouteRecordRaw } from "vue-router";
|
|
|
|
import SidebarMenuItemTitle from "./SidebarMenuItemTitle.vue";
|
|
|
|
const props = defineProps({
|
|
/**
|
|
* 当前路由项对象
|
|
*/
|
|
item: {
|
|
type: Object,
|
|
required: true,
|
|
},
|
|
|
|
/**
|
|
* 父层级完整路由路径
|
|
*/
|
|
basePath: {
|
|
type: String,
|
|
required: true,
|
|
},
|
|
/**
|
|
* 是否为嵌套路由
|
|
*/
|
|
isNest: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
});
|
|
|
|
const onlyOneChild = ref();
|
|
|
|
/**
|
|
* 判断当前路由是否只有一个显示的子路由
|
|
*
|
|
* @param children 子路由数组
|
|
* @param parent 父级路由对象
|
|
* @returns 布尔值,表示是否只有一个显示的子路由
|
|
*/
|
|
function hasOneShowingChild(
|
|
children: RouteRecordRaw[] = [],
|
|
parent: RouteRecordRaw
|
|
) {
|
|
// 筛选出需要显示的子路由
|
|
const showingChildren = children.filter((route: RouteRecordRaw) => {
|
|
if (route.meta?.hidden) {
|
|
return false;
|
|
} else {
|
|
route.meta!.hidden = false;
|
|
onlyOneChild.value = route;
|
|
return true;
|
|
}
|
|
});
|
|
|
|
// 如果只有一个或没有显示的子路由
|
|
if (showingChildren.length === 1) {
|
|
return true;
|
|
}
|
|
|
|
// 如果没有子路由,显示父级路由
|
|
if (showingChildren.length === 0) {
|
|
onlyOneChild.value = { ...parent, path: "", noShowingChildren: true };
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* 解析路由路径,将相对路径转换为绝对路径
|
|
*
|
|
* @param routePath 路由路径
|
|
* @returns 绝对路径
|
|
*/
|
|
function resolvePath(routePath: string) {
|
|
if (isExternal(routePath)) {
|
|
return routePath;
|
|
}
|
|
if (isExternal(props.basePath)) {
|
|
return props.basePath;
|
|
}
|
|
|
|
// 完整路径(/system/user) = 父级路径(/system) + 路由路径(user)
|
|
const fullPath = path.resolve(props.basePath, routePath);
|
|
return fullPath;
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
.hideSidebar {
|
|
.submenu-title-noDropdown {
|
|
position: relative;
|
|
padding: 0 !important;
|
|
|
|
.el-tooltip {
|
|
padding: 0 !important;
|
|
|
|
.sub-el-icon {
|
|
margin-left: 19px;
|
|
}
|
|
}
|
|
|
|
& > span {
|
|
display: inline-block;
|
|
width: 0;
|
|
height: 0;
|
|
overflow: hidden;
|
|
visibility: hidden;
|
|
}
|
|
}
|
|
|
|
.el-sub-menu {
|
|
overflow: hidden;
|
|
|
|
& > .el-sub-menu__title {
|
|
padding: 0 !important;
|
|
|
|
.sub-el-icon {
|
|
margin-left: 19px;
|
|
}
|
|
|
|
.el-sub-menu__icon-arrow {
|
|
display: none;
|
|
}
|
|
}
|
|
}
|
|
|
|
.el-menu--collapse {
|
|
width: $sidebar-width-collapsed;
|
|
|
|
.el-sub-menu {
|
|
& > .el-sub-menu__title {
|
|
& > span {
|
|
display: inline-block;
|
|
width: 0;
|
|
height: 0;
|
|
overflow: hidden;
|
|
visibility: hidden;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.el-menu-item:hover {
|
|
background-color: $menu-hover;
|
|
}
|
|
</style>
|