Skip to content

页面工具栏扩展 ​

工具栏贡献者在模块表格上方添加操作。本例提示当前页的用户数量。

定义贡献者 ​

ts
import { ToolbarAction } from '@lsw-abpvue/components';
import { LocalizationService } from '@lsw-abpvue/core';
import { IdentityComponents, type IdentityConfigOptions } from '@lsw-abpvue/identity';
import type { IdentityUserDto } from '@lsw-abpvue/identity/proxy';
import { ToasterService } from '@lsw-abpvue/theme-shared';

export const userToolbar = {
  toolbarActionContributors: {
    [IdentityComponents.Users]: [
      actions =>
        actions.addTail(
          ToolbarAction.create<readonly IdentityUserDto[]>({
            text: 'BookStore::CurrentPageCount',
            icon: 'bi bi-list-ol',
            permission: 'AbpIdentity.Users',
            action: data =>
              data.getInjected(ToasterService).info(
                data.getInjected(LocalizationService).t(
                  {
                    key: 'BookStore::CurrentPageCountMessage',
                    defaultValue: '{0} users on this page',
                  },
                  String(data.record.length),
                ),
              ),
          }),
        ),
    ],
  },
} satisfies IdentityConfigOptions;

注册到模块路由 ​

将示例保存为 src/identity-options.ts,在 src/routes.ts 使用导出的选项:

ts
import { lazyRoutes } from '@lsw-abpvue/core/router';
import { userToolbar } from './identity-options';

const identityRoute = lazyRoutes('/identity', () =>
  import('@lsw-abpvue/identity').then(module => module.createIdentityRoutes(userToolbar)),
);

将 identityRoute 放入应用路由数组,并保留启动时的 provideIdentityConfig()。替换已有 identity 路由,不要为同一前缀注册两份路由。模块配置改变后重启开发服务,再打开 /identity/users。

当前页与勾选记录 ​

Identity 用户工具栏的类型为 ToolbarAction<readonly IdentityUserDto[]>,data.record 包含当前页记录,不是勾选记录,也不是跨页的全部查询结果。

按勾选 id 执行批量操作,需要页面拥有的选择状态。自定义组件可以读取页面提供的命令/状态 token,或通过替换、包装页面提供该状态。不能用当前页数组代替勾选 id。

打开模态框或执行页面命令 ​

在操作回调中通过 data.getInjected 获取页面命令 token。命令负责 visible、dirty、busy 等状态,工具栏操作负责触发。复杂控件可以由自定义页面中的工具栏插槽渲染。

文字、图标与回调操作使用 ToolbarAction。需要自定义渲染的控件放入 Vue 工具栏插槽或页面组件。

权限与异步状态 ​

permission 设置所需策略,visible 添加响应式业务条件。操作可以返回 Promise,但防止重复修改、完成后刷新查询,需要页面命令显式管理。

示例计数使用带默认值的本地化 key。将 BookStore::CurrentPageCount 与 BookStore::CurrentPageCountMessage 添加到后端资源或前端本地化。

检查效果 ​

切换每页条数与页码后点击操作,数量应跟随当前页;没有策略权限的用户不应看到该操作。自己的批量操作还应分别检查零勾选和翻页后的选择状态。

另见扩展行为与组件替换。

调用业务服务 ​

安装后端示例中的 ReportAppService。GET /api/app/report?year=2026 返回 { total: number },本教程使用 AbpIdentity.Users 权限。复制两个文件,在已有 Identity 路由选项传入 reportToolbar,增加 BookStore::Report/ReportTotal 资源。服务负责防重复请求,贡献器通过 getInjected 触发。它统计当前租户指定年份的教学目录记录,不使用 Users 的勾选行。

ts
import { defineService, inject, RestService, type ServiceOf } from '@lsw-abpvue/core';

export const ReportService = defineService('ReportService', () => {
  const rest = inject(RestService);

  return {
    get: (year: number) =>
      rest.request<never, { total: number }>({
        method: 'GET',
        url: '/api/app/report',
        params: { year },
      }),
  };
});

export type ReportService = ServiceOf<typeof ReportService>;
ts
import { ref } from 'vue';
import { defineService, inject } from '@lsw-abpvue/core';
import { ToolbarAction } from '@lsw-abpvue/components';
import { IdentityComponents, type IdentityConfigOptions } from '@lsw-abpvue/identity';
import type { IdentityUserDto } from '@lsw-abpvue/identity/proxy';
import { ToasterService } from '@lsw-abpvue/theme-shared';
import { ReportService } from './report-service';

const ReportCommand = defineService('ReportCommand', () => {
  const reports = inject(ReportService);
  const toaster = inject(ToasterService);
  const busy = ref(false);
  return {
    async run(): Promise<void> {
      if (busy.value) return;
      busy.value = true;
      try {
        const report = await reports.get(new Date().getFullYear());
        toaster.info(
          { key: 'BookStore::ReportTotal', defaultValue: 'Report total: {0}' },
          undefined,
          { messageLocalizationParams: [String(report.total)] },
        );
      } catch {
        /* The request error handlers report the failure. */
      } finally {
        busy.value = false;
      }
    },
  };
});
export const reportToolbar = {
  toolbarActionContributors: {
    [IdentityComponents.Users]: [
      actions =>
        actions.addTail(
          ToolbarAction.create<readonly IdentityUserDto[]>({
            text: 'BookStore::Report',
            permission: 'AbpIdentity.Users',
            icon: 'bi bi-bar-chart',
            action: data => data.getInjected(ReportCommand).run(),
          }),
        ),
    ],
  },
} satisfies IdentityConfigOptions;

非官方社区项目,采用 MIT 许可证,与 Volosoft 无关。