配置二级菜单
{
path: '/page/hospital-edit/current',
name: '医院信息',
iconClass: '#icon-yiyuanguanli',
requiredPolicy: 'FutureClinic_HospitalMenu.Menu',
order: 3,
layout: eLayoutType.application,
},
{
// 注意,这里不需要设置 path,因为他不跳转
name: '科室管理',
iconClass: '#icon-keshiguanli',
requiredPolicy: 'FutureClinic_DepartmentMenu.Menu',
order: 4,
layout: eLayoutType.application,
children: [
{
// 将 path 放到二级菜单下即可
path: '/page/department-list',
name: '科室列表',
iconClass: '#icon-keshiguanli',
requiredPolicy: 'FutureClinic_DepartmentMenu.Menu',
order: 4,
// 注意,这里一定要手动添加上去,否则也是下拉展开的效果,不能点击
isLeaf: true,
layout: eLayoutType.application,
// 注意,这个属性也要手动设置,否则会导致循环溢出
children: []
},
{
path: '/page/doctor-list',
name: '医生管理',
requiredPolicy: 'FutureClinic_DoctorMenu.Menu',
iconClass: '#icon-yishengguanli',
order: 5,
isLeaf: true,
layout: eLayoutType.application,
children: []
},
]
},
注意,需要设置 isLeaf/children 属性。
使用改造的 nz-menu
template
<ul nz-menu nzMode="inline" nzTheme="dark">
<ng-container
[ngTemplateOutlet]="commonLink"
[ngTemplateOutletContext]="{ $implicit: routesService.visible }"
>
</ng-container>
<ng-template #commonLink let-routes>
<ng-container *ngFor="let route of routes">
<ng-container *ngIf="!isDropdown(route)">
<li
nz-menu-item
nz-tooltip
*abpPermission="route.requiredPolicy"
[nzPaddingLeft]="route.iconClass ? 0 : 50"
>
<a [routerLink]="[route.path]">
<span title class="menu-title-wrapper">
<svg
*ngIf="route.iconClass && route.iconClass.indexOf('#') > -1; else fontIcon1"
class="icon"
aria-hidden="true"
>
<use [attr.xlink:href]="route.iconClass"></use>
</svg>
<ng-template #fontIcon1>
<i class="icon" *ngIf="route.iconClass" [ngClass]="route.iconClass"></i>
</ng-template>
<span class="name">{{ route.name | abpLocalization }}</span>
</span>
</a>
</li>
</ng-container>
<ng-container *ngIf="isDropdown(route)">
<li nz-submenu nz-tooltip *abpPermission="route.requiredPolicy">
<span title class="menu-title-wrapper">
<svg
*ngIf="route.iconClass.indexOf('#') > -1; else fontIcon"
class="icon"
aria-hidden="true"
>
<use [attr.xlink:href]="route.iconClass"></use>
</svg>
<ng-template #fontIcon>
<i class="icon" *ngIf="route.iconClass" [ngClass]="route.iconClass"></i>
</ng-template>
<span>{{ route.name | abpLocalization }}</span>
</span>
<ul>
<ng-container *ngTemplateOutlet="commonLink; context: { $implicit: route.children }">
</ng-container>
</ul>
</li>
</ng-container>
</ng-container>
</ng-template>
</ul>
scss
.icon {
width: 1em; height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
.ant-menu-root {
padding-bottom: 120px;
}
.ant-menu {
background-color: #082a64 !important;
.ant-menu-item,
.ant-menu-item a {
color: #fff;
height: auto;
padding-top: 4px;
padding-bottom: 4px;
transition: none;
}
.ant-menu-item:hover {
a {
color: #fff;
}
}
.ant-menu-item-selected {
color: #fff;
background-color: #6385ff;
}
.ant-menu-item-selected a {
color: #fff;
background-color: #6385ff;
}
::ng-deep .ant-menu-submenu {
.ant-menu-submenu-title {
color: #fff;
}
}
}
::ng-deep .ant-menu > .ant-menu-submenu > .ant-menu-sub .ant-menu-submenu-title {
color: #fff;
padding-left: 50px !important;
}
::ng-deep .ant-menu > .ant-menu-submenu > .ant-menu-sub .ant-menu-item.ng-star-inserted {
padding-left: 60px !important;
}
.menu-title-wrapper {
// display: flex;
.icon {
margin-right: 10px;
}
.img {
width: 16px;
height: 16px;
background-repeat: no-repeat;
background-size: contain;
margin-right: 12px;
}
}
::ng-deep .ant-menu-sub {
background-color: #082a64 !important;
}
.img {
width: 16px;
height: 16px;
background-repeat: no-repeat;
background-size: contain;
margin-right: 12px;
}
ts
import { ABP, RoutesService, TreeNode } from '@abp/ng.core';
import {
Component,
ElementRef,
Input,
QueryList,
Renderer2,
TrackByFunction,
ViewChildren,
} from '@angular/core';
@Component({
selector: 'abp-routes',
templateUrl: 'routes.component.html',
styleUrls: ['./routes.component.scss'],
})
export class RoutesComponent {
@Input() smallScreen?: boolean;
@ViewChildren('childrenContainer') childrenContainers!: QueryList<ElementRef<HTMLDivElement>>;
rootDropdownExpand = {} as { [key: string]: boolean };
trackByFn: TrackByFunction<TreeNode<ABP.Route>> = (_, item) => item.name;
constructor(public readonly routesService: RoutesService, protected renderer: Renderer2) {
}
isDropdown(node: TreeNode<ABP.Route>) {
console.log('isDropdown', node);
return !node?.isLeaf || this.routesService.hasChildren(node.name);
}
closeDropdown() {
this.childrenContainers.forEach(({ nativeElement }) => {
this.renderer.addClass(nativeElement, 'd-none');
setTimeout(() => this.renderer.removeClass(nativeElement, 'd-none'), 0);
});
}
}