创建一致的管理员界面

这些指南旨在创建一个协调一致的管理员界面,重点关注可用性、可访问性和结构化布局。请参阅目录以了解包含的内容并轻松导航到每个部分。

注意:此处使用的术语在管理员界面术语表中有定义。

0. 前言 - 配置页面结构和侧边栏链接

在管理员界面中添加新的配置页面时,每个页面都需要一个侧边栏链接,并且每个页面都需要一个标题和头部描述。这是为了确保我们保持一致,并且未来对管理员搜索的增强可以显示管理员界面的整个布局。

通常,管理员界面的结构如下所示:

  • 管理员界面
    • 配置页面(显示在侧边栏中)
      • 设置选项卡
      • 其他可选的第三级选项卡
        • 资源的编辑/新建第三级页面

最终,将在根界面和配置页面之间插入一个“部分概览”。

侧边栏链接

所有管理员页面都应添加到 discourse/frontend/discourse/app/lib/sidebar/admin-nav-map.js at main · discourse/discourse · GitHub 中的 ADMIN_NAV_MAP。每个项至少应包含以下键:

  • name - 链接的唯一标识符,应为 snake_case
  • routehref - route 是 Ember 路由标识符,例如 adminUsers。对于管理员,这些在管理员路由映射中定义。也可以使用 href,但推荐使用 route
  • labeltext - Label 是 I18n 键,通常应为 admin.config.page_name.title(见下文翻译部分)。如果使用 text,则将是已翻译的文本。

还可以提供以下可选键:

  • description - 建议你也提供这个。它是一个 I18n 键,通常应为 admin.config.page_name.header_description
  • icon - 也建议,显示在侧边栏链接旁边。
  • routeModels - 用于路由参数的 URL 数据数组。例如 adminCustomizeThemes 有一个 :type 路由参数,因此你可以传递 routeModels: ["components"]。数组项按路由参数出现的顺序使用。
  • moderator:如果版主应在侧边栏中看到此页面,请将其设置为 true
  • keywords:一个 I18n 键,包含用 | 分隔的侧边栏链接关键词列表,用于在过滤/搜索页面时提供额外的“搜索权重”。
  • links:位于侧边栏页面下方的第三级路由列表。这些不会直接显示在侧边栏中。这将用于未来的管理员搜索功能。
  • settings_areasettings_category:如果页面仅显示过滤后的站点设置列表,则应填写其中之一。如果站点设置定义了 area(在 AdminAreaSettings 中使用),则应使用 settings_area。如果页面上显示整个设置类别,并且在 AdminAreaSettings 中也使用,则应使用 settings_category
  • multi_tabbed:如果页面有设置选项卡其他选项卡,则应将其设置为 true。它有助于为管理员搜索系统生成链接。

翻译

每个配置页面的标题和头部描述应位于:

  • admin
    • config
      • page_name
        • title: “页面标题”
        • header_description: “此页面用于 xyz”

你可以在这里看到示例:

1. 面包屑导航

面包屑导航作为一种导航工具,帮助用户了解他们在管理员界面中的当前位置、内容结构和层级关系。

管理员 > 面包屑 > 路径
页面标题

:art: 设计

结构

  1. 管理员:固定前缀,出现在每个面包屑路径的开头,链接到 /admin
  2. 链接:在同一窗口中打开页面
  3. 分隔符angle-right 图标分隔每个链接

用法

何时使用:

  • 出现在每个管理员页面上
  • 位于内容(标题、描述、选项卡)上方
  • 显示当前选中的页面

何时不使用:

  • 访问新建或编辑路由时

内容

  • 每个项包含指向其相关页面的链接
  • 显示当前选中的页面

可访问性

  • 带有 aria-label="Breadcrumb"nav 元素包裹有序列表,以提供导航地标
  • 在最后一个链接上应用 aria-current="page" 以指示它是当前页面
  • 更多详情,请参阅 WAI-ARIA 作者实践面包屑示例

:hammer_and_wrench: 实现

DBreadcrumbsContainer 组件必须放置在页面的某个位置:

<DBreadcrumbsContainer />

然后,添加到路由或子路由上任何组件的每个 DBreadcrumbsItem 元素都将渲染到这个容器中。每个 DBreadcrumbsItem 必须提供 @label@path

<DBreadcrumbsItem @path="/admin" @label={{i18n "admin_title"}} />
<DBreadcrumbsItem
  @path="/admin/plugins"
  @label={{i18n "admin.plugins.title"}}
/>
<DBreadcrumbsItem
  @path="/admin/plugins/{{@plugin.name}}"
  @label={{@plugin.nameTitleized}}
/>
```\n
使用 Discourse AI 插件的视觉示例如下所示:

![面包屑示例|690x302, 75%](upload://2jbYauteEJY2b6OimlKlW1TDJyq.jpeg)

# 2. 页面头部和标题

管理员页面的顶部部分,包含页面标题以及可选的操作和描述。

![页面标题示例|690x114](upload://iBs3rxNAlF6s0xrUj2XFIVvMsBC.png)

## :art: 设计

**结构**

* **页面标题:** 页面的标题

* **页面描述:** 内容涵盖内容的简介或描述 *(可选)*

* **主要操作:** 页面标题主要操作 *(可选)*

* **次要操作:** 页面标题次要操作按钮设置 *(可选)*

**用法和内容**

* **页面标题:** 使用一级标题以句子大小写解释页面的主要主题。通常 I18n 翻译应位于 `admin.config.your_page.title` 下。

* **页面描述:** 支持基本 markdown 节点,如 `_斜体_`、`**粗体**` 和 `[链接名称](url)`

* **主要操作:** 使用 `btn-primary`。不要包含图标。通常 I18n 翻译应位于 `admin.config.your_page.header_description` 下。

* **次要操作:** 使用 `btn-default` 按钮设置,仅当存在主要操作时才可见。不要包含图标。

  > :point_right: 操作按钮要清晰。例如,使用描述性标签如“添加表情符号”而不是简单的“添加”以减少歧义。

## :hammer_and_wrench: 实现

这里使用 `DPageHeader` 组件。它接受 `@titleLabel`、`@descriptionLabel`、`@learnMoreUrl` 和 `@shouldDisplay` 参数。这使用 Ember 中的命名 `yields` 为内容提供 5 个命名块:

1. `breadcrumbs` - 页面的任何额外 `DBreadcrumbsItem` 组件应放置在此处。
2. `actions` - 用于定义标题右侧的按钮。这会产生一个名为 `actions` 的对象,可用于渲染 `Default`、`Primary`、`Danger` 和 `Wrapped` 按钮。
3. `title` - `@titleLabel` 的替代方案,允许在标题中使用自定义标记。
4. `drawer` - 一个可选的可折叠抽屉部分,当 `@showDrawer` 为 true 时显示。
5. `tabs` - 使用 `NavItem` 组件定义页面的选项卡。`@hideTabs` 可用于在不需要的情况下删除头部的这部分。

完整示例如下:

```gjs
<DPageHeader
  @titleLabel={{i18n "admin.config.backups.title"}}
  @descriptionLabel={{i18n "admin.config.backups.header_description"}}
  @learnMoreUrl="https://meta.discourse.org/t/create-download-and-restore-a-backup-of-your-discourse-database/122710"
>
  <:breadcrumbs>
    <DBreadcrumbsItem
      @path="/admin/backups"
      @label={{i18n "admin.backups.title"}}
    />
  </:breadcrumbs>
  <:actions as |actions|>
    <actions.Primary
      @action={{routeAction "showStartBackupModal"}}
      @title="admin.backups.operations.backup.title"
      @label="admin.backups.operations.backup.label"
      class="admin-backups__start"
    />
  </:actions>
  <:tabs>
    <NavItem
      @route="admin.backups.settings"
      @label="settings"
      class="admin-backups-tabs__settings"
    />
    <NavItem
      @route="admin.backups.index"
      @label="admin.backups.menu.backup_files"
      class="admin-backups-tabs__files"
    />
    <NavItem
      @route="admin.backups.logs"
      @label="admin.backups.menu.logs"
      class="admin-backups-tabs__logs"
    />
    <PluginOutlet @name="downloader" @connectorTagName="div" />
  </:tabs>
</DPageHeader>

浏览器选项卡的页面标题在 Ember 路由中使用 titleToken 功能处理。每次在路由中使用它时,它都会将令牌添加到浏览器选项卡标题的末尾。请注意,你必须使用 DiscourseRoute 类来扩展你的路由,而不是 Ember 中的普通 Route,才能使其工作:

titleToken() {
  return i18n("admin.config.backups.title");
}

:point_right: 页面头部对于 /new/edit 路径自动隐藏,以支持第三级路由。可以通过使用 @shouldDisplay 参数来覆盖。

3. 选项卡

一个可选的导航,提供对更深层设置或功能的访问。我们也将其称为“第三级”页面或导航。

:art: 设计

我们使用选项卡在相同上下文中的不同但相关的视图之间切换。

用法

  • 不用于主要导航
  • 一次只有一个处于活动状态

:hammer_and_wrench: 实现

参见页面头部详细信息,选项卡在 DPageHeader 组件中定义。

:white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square: :white_small_square:

4. 概览/部分着陆页

允许用户查看部分的内容,特别是在侧边栏折叠或在移动设备上时。

:art: 设计

结构
使用网格系统使用三个相等的列布局。在小屏幕上,这些列将垂直堆叠。

设计和用法

  • 可以通过面包屑访问(管理员 > 社区 > 概览)
  • 每个部分应该有一个,除了插件(显示已安装的)和报告(只有一页)
  • 项具有:
    • 名称 - 与部分链接相同
    • 描述 - 关于页面内容的简短描述
    • 图标 - 与侧边栏使用的相同图标

:hammer_and_wrench: 实现

代码片段或链接到主题/GitHub

5. 页面内容

管理员页面的主要区域,在此显示和交互设置、配置和其他内容。

:art: 设计

结构
使用网格系统使用 2/3 + 1/3 布局。主要部分占据三分之二,次要部分占据三分之一的空间。在小屏幕上,这些列将垂直堆叠。

  • 配置区域: 页面内容中专门用于设置和配置的部分。
  • 帮助/参考/插入: 页面内容中提供指南、文档或额外上下文信息的区域。(可选)

设计和用法

  • 将类似的设置和操作分组在卡片中
  • 构建主要/次要布局,以便主要(2/3)部分用于主要设置,次要(1/3)部分用于额外信息或有帮助的上下文
  • 如果次要部分不可用,保持主要部分的宽度相同

内容

:hammer_and_wrench: 实现

代码片段或 GitHub 链接

5.a. 副标题

副标题是用于分割部分下内容的次要标题,通常在选项卡下方。

结构

  • 副标题: 内容涵盖的副标题 (可选)
  • 主要操作: 副标题主要操作 (可选)
  • 次要操作: 副标题次要操作按钮设置 (可选)

用法和内容

  • 副标题: 使用二级标题解释相关内容的主要主题。仅当:

    • 主要操作按钮,或
    • 描述解释该部分。
  • 主要操作: 使用 btn-primary。不要包含图标。

  • 次要操作: 使用 btn-default 按钮设置,仅当存在主要操作时才可见。不要包含图标。

    :point_right: 操作按钮要清晰。例如,使用描述性标签如“添加表情符号”而不是简单的“添加”以减少歧义。

:hammer_and_wrench: 实现

这与 DPageHeader 类似,有一个 DPageSubheader 组件。主要区别是只有一个用于 actions 的命名 yield。

  1. actions - 用于定义标题右侧的按钮。这会产生一个名为 actions 的对象,可用于渲染 DefaultPrimaryDangerWrapped 按钮。
<DPageSubheader @titleLabel="admin.config.backups.subheader.title">
  <:actions>
    <actions.Primary
      @action={{routeAction "showStartBackupModal"}}
      @title="admin.backups.operations.backup.title"
      @label="admin.backups.operations.backup.label"
      class="admin-backups__start"
    />
  </:actions>
</DPageSubheader>

5.b. 配置区域

配置区域由卡片或部分构成。卡片非常适合分组相关信息和任务,帮助用户更轻松地扫描和优先处理内容。

:art: 设计

卡片

卡片设置为 2px 边框半径,并使用 --secondary 背景。它还有一个 1px 实线边框,带有 --primary-low 和内容周围 20px 的内边距。

默认变体

手风琴变体

设计和用法

  • 分组相关信息
  • 显示信息,以便管理员和版主首先看到最重要的内容
  • 使用清晰解释卡片用途的标题
  • 如有必要,将复杂的卡片分成多个部分

默认变体

  • 每张卡片坚持一个主要号召性用语
  • 将主要号召性用语放在卡片底部以进行下一步

手风琴变体

  • 使用卡片的右上角进行可选操作,如“查看全部”

内容

  • 所有表单应使用核心中描述的 FormKit ember 组件,详见文档

  • 卡片标题应为句子大小写

    :white_check_mark: :cross_mark: 不做
    常规设置 常规设置
    联系信息 联系信息

:hammer_and_wrench: 实现

我们有一个 AdminConfigAreaCard 组件,应用于所有这些卡片。目前这只有 @translatedHeading@heading 参数,未来我们可以添加操作并使它们可折叠等:

<AdminConfigAreaCard
  @heading="admin.config_areas.about.general_settings"
  class="admin-config-area-about__general-settings-section"
>
  <AdminConfigAreasAboutGeneralSettings
    @generalSettings={{this.generalSettings}}
    @setGlobalSavingStatus={{this.setSavingStatus}}
    @globalSavingStatus={{this.saving}}
  />
</AdminConfigAreaCard>

嵌入式站点设置

此部分仍在进行中。

5.c. 帮助插入

此部分在页面内容中提供额外的指导、文档或上下文。

v1

:art: 设计

设计和用法

  • 显示与页面内容相关的文档或指南,以提供有用信息
  • 在标题中包含图标,使其易于识别
  • 将此部分放置在次要(1/3)布局区域

内容

  • 标题应为句子大小写

:hammer_and_wrench: 实现

代码片段或链接到主题/GitHub

5.d. 表格

表格以单元格、列和行的网格形式显示信息,使管理员能够快速扫描项目并采取行动。

:art: 设计

用法

  • 使用表格显示结构化内容,其中每个条目共享相同的属性。
  • 允许管理员查看、启用/禁用、编辑和删除数据集。
  • 适用于随时间继续增长的数据集。

设计

  • 在行之间使用水平线以视觉上分隔内容,包括最后一行。避免在表格周围使用边框或框架,以防止其看起来像网。
  • 不要在列之间应用垂直线。没有垂直线的表格通常更容易扫描和阅读。

额外操作

  • 行操作: 在每个表格行的最右列中包含额外操作。
    • 如果有两个或更多交互元素,主要操作(例如,“编辑”)应为文本按钮,所有其他行操作包括“删除”应分组在 [...] 下拉菜单中。鼓励在下拉菜单中使用图标以在视觉上打破内容。
    • 如果只有“删除”操作且没有主要操作,请使用内联“删除”文本按钮,样式为 btn-default
    • 你应该将主列的文本(通常是 d-table__cell --overview)包装在链接中,将管理员直接带到对应行的显示/编辑页面,以便快速访问。
  • 删除确认:所有“删除”按钮应在执行操作前显示确认。

内容

  • 标题: 表格标题是识别下方列的顶行。它提供清晰度,特别是如果数据不具描述性或模糊。标题应简短、描述性和相关,使用标题大小写。避免标题对于下方行中的内容来说太长。
  • 列: 按优先级或以一种讲述连贯数据故事的方式排序列。根据内容调整列大小,小内容使用窄列,段落使用宽列。
  • 行: 行应支持文本、按钮、链接和图标,以增强数据呈现。
  • 无数据: 空列表应使用 AdminConfigAreaEmptyList 组件,带有 CTA 按钮和标签,引导用户创建新记录

:hammer_and_wrench: 实现

有一小集合 CSS 类必须与表格一起使用,以使其在移动设备和桌面上正常工作。

<table> 元素应应用 d-table 类。

<thead> 元素应应用 d-table__header 类。

<tr> 元素应应用 d-table__row 类。

<td> 元素包含大量描述性文本(通常是最左边的列)应使用 d-table__cell --overview 类。所有其他单元格应使用 d-table__cell --detail

带有 d-table__cell --overview 类的 <td> 元素可以将内部行内容包装在链接中,将管理员直接带到行的编辑/显示页面。此链接应遵循此结构并应用 d-table__overview-link CSS 类。理想情况下应使用 LinkTo 组件,但 <a> 也可以,只要使用 getURL 即可。

d-table__overview-name 类应应用于此处的名称部分,但不应用于描述。

<td class="d-table__cell --overview">
  <LinkTo
    class="d-table__overview-link"
    @route="adminPlugins.show.explorer.details"
    @model={{query.id}}
  >
    <strong class="query-name d-table__overview-name">{{query.name}}</strong>
    {{#if query.is_default}}
      <span class="query-badge">{{i18n
          "explorer.default_query"
        }}</span>
    {{/if}}
    <div class="query-desc">{{query.description}}</div>
  </LinkTo>
</td>
<td class="d-table__cell --overview">
  <a class="d-table__overview-name admin-flag-item__name d-table__overview-link" href={{this.editUrl}}>
    {{@flag.name}}
  </a>
</td>

包装每行按钮的 <td> 元素应应用 d-table-cell --controls CSS 类。这确保按钮对齐。每个按钮也应应用 btn-small 类。

对于移动设备,每个 <td> 元素除了 d-table-cell --overview 还应包含一个带有类 d-table__mobile-label<div>,其中包含与 <th> 中相同的 I18n 标签:

<td class="d-table__cell --detail">
  <div class="d-table__mobile-label">
    {{i18n "chat.incoming_webhooks.emoji"}}
  </div>
  {{replaceEmoji webhook.emoji}}
</td>

这在移动设备上以更易读的卡片格式显示表格行:

对于 [...] 下拉菜单,应使用 DMenuDropdownMenu,这里是一个示例:

<DMenu
  @identifier="backup-item-menu"
  @title={{i18n "more_options"}}
  @icon="ellipsis-vertical"
  class="btn-small"
>
  <:content>
    <DropdownMenu as |dropdown|>
      <dropdown.item>
        <DButton ...[button args here] />
      </dropdown.item>
      <dropdown.item>
        <DButton ...[button args here] />
      </dropdown.item>
    </DropdownMenu>
  </:content>
</DMenu>

表格行中的切换使用 DToggleSwitch 组件处理:

<DToggleSwitch
  @state={{this.enabled}}
  class="admin-flag-item__toggle {{@flag.name_key}}"
  {{on "click" (fn this.toggleFlagEnabled @flag)}}
/>

将所有内容放在一起,这里是一个管理员表格的最小示例:

 <table class="d-table">
    <thead class="d-table__header">
      <tr>
        <th>Name</th>
        <th>Description</th>
        <th></th>
      </tr>
    </thead>
    <tbody>
      <tr class="d-table__row">
        <td class="d-table__cell --overview">
          <LinkTo @route="admin.exampleRoute" class="d-table__overview-link">
            <span class="d-table__overview-name">Example Item</span>
            <span class="d-table__overview-about">A short description</span>
          </LinkTo>
        </td>
        <td class="d-table__cell --detail">
          <span class="d-table__mobile-label">Description</span>
          Some detail content here
        </td>
        <td class="d-table__cell --controls">
          <div class="d-table__cell-actions">
            <button class="btn btn-default btn-small">Edit</button>
          </div>
        </td>
      </tr>
    </tbody>
  </table>

5.e 第三级路由

第三级路由是只能从配置区域到达的路由。这些通常以编辑/新建路由的形式出现,如下面的标志示例:

在大多数情况下,使用 FormKit 的表单将放置在这里。

使用标准的 RESTful 路由:

操作 路径
新建 <resource>/new
编辑 <resource>/:id/edit

并确保路由也在后端路由。(重新加载新建或编辑页面不应导致错误。)

:art: 设计

用法

  • 优先使用这些第三级路由,而不是在主路由或表格中使用内联表单。独立的编辑和新建路由最好,因为它们可以轻松链接。
  • 不要显示页面 UI 的顶部部分(面包屑、页面头部和副标题)
  • 相反,显示一个单一的“返回 X”链接,允许管理员返回主配置区域
  • 页面内容应至少包裹在一个 AdminConfigAreaCard
  • 页面上的任何副标题应使用配置区域卡片完成

:hammer_and_wrench: 实现

有一个简单的 BackButton 组件,可用于页面顶部返回:

<BackButton
  @route="adminConfig.flags"
  @label="admin.config_areas.flags.back"
/>

6. 过滤设置配置页面

我们的许多管理员界面配置页面都是简单的过滤站点设置列表。这允许管理员找到相关的设置组,而不会被完整的“所有站点设置”列表所淹没,直到我们创建更多专门的配置页面,如 /admin/config/about/

:hammer_and_wrench: 实现

添加这些路由之一需要几件事。首先,你可以显示整个 category 的站点设置,这些是 site_settings.yml 中的顶级键(例如 branding:),或者你可以使用设置 area

站点设置可以存在于多个 areas 中,你可以在同一页面上显示一个或多个。

  1. adminConfig 下方的管理员路由映射中添加路由,例如:
this.route("trustLevels", { path: "/trust-levels" }, function () {
  this.route("settings", {
    path: "/",
  });
});
  1. 添加一个新的路由 .js 文件,文件将匹配类似 frontend/discourse/admin/routes/admin-config/localization.js 的路径,具体取决于你的新路由名称。这应继承自 AdminConfigWithSettingsRoute 并包含 titleToken()
import { i18n } from "discourse-i18n";
import AdminConfigWithSettingsRoute from "../admin-config-with-settings-route";

export default class AdminConfigLocalizationRoute extends AdminConfigWithSettingsRoute {
  titleToken() {
    return i18n("admin.config.localization.title");
  }
}
  1. 添加一个控制器,这主要是为了启用设置搜索和过滤。它必须继承自 AdminAreaSettingsBaseController
import AdminAreaSettingsBaseController from "discourse/admin/controllers/admin-area-settings-base";

export default class AdminConfigLocalizationSettingsController extends AdminAreaSettingsBaseController {}
  1. 最后,添加一个 .gjs 格式的路由模板文件,路径类似 frontend/discourse/admin/templates/admin-config/localization/settings.gjs。这应包含正常的 DPageHeader 和面包屑,但要显示设置,你需要 AdminAreaSettings
<div class="admin-config-page__main-area">
  <AdminAreaSettings
    @showBreadcrumb={{false}}
    @area="localization"
    @path="/admin/config/localization"
    @filter={{@controller.filter}}
    @adminSettingsFilterChangedCallback={{@controller.adminSettingsFilterChangedCallback}}
  />
</div>

这里需要更改的重要事项是 @path@area(或者使用 @categories)。如前所述,填写你想要显示的站点设置区域或类别。

7. 一般指导

  • URL slugs 必须使用连字符 (-) 来表示单词中的空格,而不是下划线 (_)。

  • 管理员界面中的所有文本应遵循此处概述的文本格式指南:

8. 插件

一些插件需要为其插件进行深入的配置 UI(例如 AI、自动化、游戏化),而不仅仅是拥有一系列站点设置。例如,这里是 Discourse AI:

一些使用此的插件示例:

:art: 设计

用法

  • 制作独立插件 UI 时应遵循一般管理员 UI 指南。

:hammer_and_wrench: 实现

Ember 路由

  • 所有路由模板将位于
    admin/assets/javascripts/discourse/templates/admin-plugins/show/
  • 所有路由 js 文件将位于 admin/assets/javascripts/discourse/routes/
    admin-plugins-show- 为前缀
  • 管理员路由映射应在类似 admin-PLUGIN-NAME-plugin-route-map.js 的文件中
  • 路由映射应具有如下结构。重要的是我们使用 admin.adminPlugins.show 作为 resource
export default {
  resource: "admin.adminPlugins.show",

  path: "/plugins",

  map() {
    this.route("discourse-ai-personas", { path: "ai-personas" }, function () {
      this.route("new");
      this.route("show", { path: "/:id" });
    });
  },
};
  • 当前所有工作的示例可以在 Discourse AI 插件中看到,如果你转到 /admin/plugins/discourse-ai/ai-personas
  • 如果你只有一个“顶级”路由,例如不定义子路由的路由,那么模板路径将是类似 admin/assets/javascripts/discourse/templates/admin-plugins/show/your-route-name.gjs。如果有子路由,那么你就进入了需要 index.gjsshow.gjsnew.gjs 模板等的领域。

导航

插件可以在内部侧边栏或顶部选项卡导航栏中显示其导航。后者高度推荐,未来可能会放弃内部侧边栏支持。

服务器端

  • add_admin_route 仍用于在管理员侧边栏和带有顶部选项卡的 /plugins 索引中显示自定义管理员路由。基本上,这定义了你的插件 UI 的根页面。
    • 应传递 use_new_show_route: true 作为额外参数,以便使用新的插件显示页面。

UI 约定

  • 插件的每个索引路由应显示 DPageSubheader 组件,以描述该路由的意图并添加任何相关的操作按钮。
  • 需要渲染到主插件页面头部的操作按钮必须使用 admin-plugin-config-page-actions 出口和专用组件。最佳位置是在使用 addAdminPluginConfigurationNav 的同一初始化程序中。
    • pluginactions 作为 outletArgs 传递。plugin 是当前插件的模型表示,因此可以访问插件名称和其他内容,actions 是来自 DPageHeader 的 yielded 操作按钮组件。
api.renderInOutlet(
  "admin-plugin-config-page-actions",
  ChatAdminPluginActions
);

相关主题:

10 个赞

还有

仍然不起作用。我认为第二个是 -23 而不是 -24

5 个赞

很高兴终于在 meta 上看到这个。数月的工作投入其中,我们将用它来统一管理界面中每个页面的 UI 和导航。

我们是不是应该直接移除目录,而依赖 discotoc 呢?我认为这样会更稳定,尽管我确实喜欢在帖子顶部看到目录。

7 个赞

感谢 @Moin - 都修好了!

我已经做了这个更改,否则它只是一个重复的目录。

4 个赞

帖子已拆分为新主题:在用户管理页面在浏览器选项卡中显示用户名