修改菜单
菜单位于 @abp/ng.theme.basic 包的 ApplicationLayoutComponent 中。有几种方法可以修改菜单元素。本文档将介绍这些方法。如果您想完全替换菜单,请参考组件替换文档,了解如何替换布局。
如何添加徽标
环境变量中的 logoUrl 属性是徽标的URL。
您可以将徽标添加到 src/assets 文件夹,并按如下所示设置 logoUrl:
export const environment = {
// 其他配置
application: {
name: 'MyProjectName',
logoUrl: 'assets/logo.png',
},
// 其他配置
};
然后,在应用程序启动时使用 Theme Shared 提供者提供徽标。这使得徽标(和应用程序名称)可以通过注入令牌供所有 ABP/Theme 组件(包括 LeptonX 品牌组件)使用。
// app.config.ts
import { provideLogo, withEnvironmentOptions } from '@abp/ng.theme.shared';
import { environment } from './environments/environment';
export const appConfig: ApplicationConfig = {
providers: [
// ... 其他提供者
provideLogo(withEnvironmentOptions(environment)),
],
};
注意事项
- 此方法适用于所有主题。如果您使用 LeptonX,品牌徽标组件会自动读取这些值;您不需要任何特定于主题的代码。
- 如果需要,您仍然可以使用 CSS 变量覆盖视觉效果。有关 CSS 覆盖,请参阅 LeptonX 部分。
如何添加导航元素
通过 RoutesService
您可以通过调用 RoutesService 的 add 方法向菜单添加路由。它是一个单例服务,即在根目录提供,因此您可以立即注入并使用它。
import { RoutesService, eLayoutType } from '@abp/ng.core';
import { Component, inject } from '@angular/core';
@Component(/* 组件元数据 */)
export class AppComponent {
private routes = inject(RoutesService);
constructor() {
this.routes.add([
{
path: '/your-path',
name: '您的导航',
order: 101,
iconClass: 'fas fa-question-circle',
requiredPolicy: '此处填写权限密钥',
layout: eLayoutType.application,
},
{
path: '/your-path/child',
name: '您的子导航',
parentName: '您的导航',
order: 1,
requiredPolicy: '此处填写权限密钥',
},
]);
}
}
另一种可能更简洁的方法是使用路由提供者。首先创建一个提供者:
// route.provider.ts
import { RoutesService, eLayoutType } from '@abp/ng.core';
import { provideAppInitializer } from '@angular/core';
export const APP_ROUTE_PROVIDER = [
provideAppInitializer(() => {
configureRoutes();
}),
];
function configureRoutes() {
const routesService = inject(RoutesService);
routes.add([
{
path: '/your-path',
name: '您的导航',
requiredPolicy: '此处填写权限密钥',
order: 101,
iconClass: 'fas fa-question-circle',
layout: eLayoutType.application,
},
{
path: '/your-path/child',
name: '您的子导航',
parentName: '您的导航',
requiredPolicy: '此处填写权限密钥',
order: 1,
},
]);
}
我们还可以为导航元素定义一个组。这是一个可选属性。
- 注意: 它还将包含在模块中定义的组。
// route.provider.ts
import { RoutesService } from '@abp/ng.core';
function configureRoutes() {
const routesService = inject(RoutesService);
routes.add([
{
//等等..
group: '模块名::组名'
},
{
path: '/your-path/child',
name: '您的子导航',
parentName: '您的导航',
requiredPolicy: '此处填写权限密钥',
order: 1,
},
]);
}
要获取分组的路由项,我们可以使用 groupedVisible(或可观察版本 groupedVisible$) getter 方法。
- 如果路由树中存在任何组,则返回
RouteGroup<T>[],否则返回undefined。
import { ABP, RoutesService, RouteGroup } from "@abp/ng.core";
import { Component, inject } from "@angular/core";
import { Observable } from "rxjs";
@Component(/* 组件元数据 */)
export class AppComponent {
private routes = inject(RoutesService);
visible: RouteGroup<ABP.Route>[] | undefined = this.routes.groupedVisible;
// 或者
visible$: Observable<RouteGroup<ABP.Route>[] | undefined> = this.routes.groupedVisible$;
}
...然后在 app.config.ts 中...
groupedVisible方法将为未分组的项返回Others组,默认键是AbpUi::OthersGroup,我们可以通过OTHERS_GROUP注入令牌更改此key。
import { OTHERS_GROUP } from '@abp/ng.core';
import { APP_ROUTE_PROVIDER } from './route.provider';
export const appConfig: ApplicationConfig = {
providers: [
// ...
APP_ROUTE_PROVIDER,
{
provide: OTHERS_GROUP,
useValue: '模块名::MyOthersGroupKey',
},
],
};
路由项单一化
name属性必须是唯一的键。如果存在多个具有相同名称的项,菜单中将显示最后一个。- 如果您想在不同父级下显示多个同名的项,可以调用
RoutesService的 setSingularizeStatus(false) 方法来禁用单一化。- 此方法应在添加路由之前调用。
- 要启用名称的单一化,可以调用
RoutesService的 setSingularizeStatus(true)(默认值: true)方法。
import { RoutesService } from '@abp/ng.core';
import { Component, inject } from '@angular/core';
@Component(/* 组件元数据 */)
export class AppComponent {
private routes = inject(RoutesService);
constructor() {
this.routes.setSingularizeStatus(false);
}
}
以下是每个属性的作用:
path是导航元素的绝对路径。name是导航元素的标签。可以传递本地化键或本地化对象。parentName是对菜单中父路由name的引用,用于创建多级菜单项。requiredPolicy是访问页面所需的权限密钥。请参阅权限管理文档order是导航元素的顺序。"Administration" 的 order 为100,因此在排序顶级菜单项时请记住这一点。iconClass是i标签的类,该标签放置在导航标签的左侧。layout定义路由在哪个布局中加载。(默认:eLayoutType.empty)invisible使项在菜单中不可见。(默认:false)group是一个可选属性,用于在应用程序中对相关路由进行分组。(类型:string, 默认:AbpUi::OthersGroup)
通过 APP_ROUTES 中的 routes 属性
您可以通过在 app.routes.ts 中的路由配置的 data 属性下添加 routes 作为子属性来定义您的路由。@abp/ng.core 包会组织您的路由并将其存储在 RoutesService 中。
您可以像下面这样添加 routes 属性:
{
path: 'your-path',
data: {
routes: {
name: '您的导航',
order: 101,
iconClass: 'fas fa-question-circle',
requiredPolicy: '此处填写权限密钥',
children: [
{
path: 'child',
name: '您的子导航',
order: 1,
requiredPolicy: '此处填写权限密钥',
},
],
},
},
}
或者,您可以这样做:
{
path: 'your-path',
data: {
routes: [
{
path: '/your-path',
name: '您的导航',
order: 101,
iconClass: 'fas fa-question-circle',
requiredPolicy: '此处填写权限密钥',
},
{
path: '/your-path/child',
name: '您的子导航',
parentName: '您的导航',
order: 1,
requiredPolicy: '此处填写权限密钥',
},
] as ABP.Route[], // 可以从 @abp/ng.core 导入
},
}
第二种方法的优点是您不受父/子结构的约束,可以使用任何您喜欢的路径。
按照上述方式添加 routes 属性后,导航菜单将如下所示:
如何修补或移除导航元素
RoutesService 的 patch 方法通过名称查找路由,并使用作为第二个参数传递的新配置替换其配置。类似地,remove 方法查找路由并将其及其子项一起移除。您还可以使用 removeByParam 方法删除具有给定属性的路由。
// this.routes 是 RoutesService 的实例
// eThemeSharedRouteNames 枚举可以从 @abp/ng.theme.shared 导入
const dashboardRouteConfig: ABP.Route = {
path: '/dashboard',
name: '::Menu:Dashboard',
parentName: '::Menu:Home',
order: 1,
layout: eLayoutType.application,
};
const newHomeRouteConfig: Partial<ABP.Route> = {
iconClass: 'fas fa-home',
parentName: eThemeSharedRouteNames.Administration,
order: 0,
};
this.routes.add([dashboardRouteConfig]);
this.routes.patch('::Menu:Home', newHomeRouteConfig);
this.routes.remove(['您的导航']);
// 或
this.routes.removeByParam({ name: '您的导航' });
方法参数:
remove(routeNames: string[]): 接受要移除的路由名称数组。removeByParam(routeProperty: Partial<ABP.Route>): 接受任何路由属性(name、path、parentName 等)来匹配和移除路由。
上述操作的结果:
- 根据给定的
parentName,将 Home 导航移至 Administration 下拉菜单下。 - 为 Home 添加了一个图标。
- 指定了顺序,使 Home 成为列表中的第一项。
- 添加了一个名为 Dashboard 的路由作为 Home 的子项。
- 移除了 您的导航 及其子路由。
上述操作后,新菜单如下所示:
如何在菜单右侧添加元素
您可以通过调用 NavItemsService 的 addItems 方法向菜单右侧添加元素。它是一个单例服务,即在根目录提供,因此您可以立即注入并使用它。
import { NavItemsService } from '@abp/ng.theme.shared';
import { Component, inject } from '@angular/core';
@Component({
template: `
<input type="search" placeholder="搜索" class="bg-transparent border-0 color-white" />
`,
})
export class MySearchInputComponent {}
@Component(/* 组件元数据 */)
export class AppComponent {
private navItems = inject(NavItemsService);
constructor() {
this.navItems.addItems([
{
id: 'MySearchInput',
order: 1,
component: MySearchInputComponent,
},
{
id: 'SignOutIcon',
html: '<i class="fas fa-sign-out-alt fa-lg text-white m-2"><i>',
action: () => console.log('点击了退出图标'),
order: 101, // 作为最后一个元素放置
},
]);
}
}
这将在菜单中插入一个搜索输入框和一个退出图标。最终UI如下所示:
默认元素的顺序为
100。如果要在默认元素之前放置自定义元素,请分配一个最多为99的顺序号。如果要在默认元素之后放置自定义元素,请分配从101开始的顺序号。最后,如果必须在默认元素之间放置一个项,请按照下面的描述修补默认元素的顺序。但请注意:我们将来可能会添加另一个默认元素,其顺序号也为100。
如何修补或移除右侧元素
NavItemsService 的 patchItem 方法通过其 id 属性查找元素,并使用作为第二个参数传递的新配置替换其配置。类似地,removeItem 方法查找元素并将其移除。
export class AppComponent {
private navItems = inject(NavItemsService);
constructor() {
this.navItems.patchItem(eThemeBasicComponents.Languages, {
requiredPolicy: '新的权限策略',
order: 1,
});
this.navItems.removeItem(eThemeBasicComponents.CurrentUser);
}
}
- 使用新的
requiredPolicy和新的order修补了语言下拉元素。 - 移除了当前用户下拉元素。
分组菜单 (专业版)
此功能仅适用于 LeptonX 主题
抠丁客







