配置二级菜单
{ 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); }); }}