创建小部件(教程)

这是一个分步教程,展示了如何创建一个简单的仪表板小部件。 您可以将此小部件的所有文件下载为 ZIP 存档:lesson_gauge_chart.zip

您将构建的内容

在本教程中,您将首先构建一个 基本“Hello, world!”小部件,然后将其转换为一个 更高级 小部件,该小部件将项目值显示为仪表图。 完成的小部件将如下所示:

第一部分 - “Hello, world!”

在本部分中,您将学习如何创建所需的最小小部件元素并向 Zabbix 前端添加新小部件。

向 Zabbix 前端添加空白小部件

  1. 在 Zabbix 前端安装的 modules 目录中创建目录 lesson_gauge_chart(例如,zabbix/ui/modules)。

所有自定义小部件都被视为外部模块,必须添加到 Zabbix 前端安装的 modules 目录中(例如,zabbix/ui/modules)。 目录 zabbix/ui/widgets 为 Zabbix 内置小部件保留,并与 Zabbix UI 一起更新。

  1. 创建一个包含基本小部件元数据的 manifest.json 文件(请参阅支持的 参数 的描述)。

ui/modules/lesson_gauge_chart/manifest.json

{
       "manifest_version": 2.0,
       "id": "lesson_gauge_chart",
       "type": "widget",
       "name": "Gauge chart",
       "namespace": "LessonGaugeChart",
       "version": "1.1",
       "author": "Zabbix"
       }
  1. 在 Zabbix 前端,转到 管理 → 常规 → 模块 部分,然后单击 扫描目录 按钮。

  1. 在列表中找到新模块 Gauge chart,然后单击“已禁用”超链接以将模块的状态从“已禁用”更改为“已启用”。

  1. 打开仪表板,将其切换到编辑模式并添加新小部件。在“类型”字段中,选择“仪表图”。

  1. 此时,“仪表图”小部件配置仅包含常用小部件字段“名称”和“刷新间隔”。

单击“添加”将小部件添加到仪表板。

  1. 仪表板上应出现一个空白小部件。单击右上角的“保存更改”以保存仪表板。

添加小部件视图

小部件的 view 文件应位于 views 目录中(本教程中为 ui/modules/lesson_gauge_chart/views/)。 如果文件具有默认名称 widget.view.php,则无需在 manifest.json 文件中注册它。 如果文件具有不同的名称,请在 manifest.json 文件的 actions/widget.lesson_gauge_chart.view 部分中指定它。

  1. lesson_gauge_chart 目录中创建目录 views

  2. views 目录中创建 widget.view.php 文件。

ui/modules/lesson_gauge_chart/views/widget.view.php

<?php
       
       /**
       * 仪表盘小部件视图。
       *
       * @var CView $this
       * @var array $data
       */
       
       (new CWidgetView($data))
       ->addItem(
       new CTag('h1', true, 'Hello, world!')
       )
       ->show();
  1. 刷新仪表板。仪表盘小部件现在显示“Hello, world!”。

第二部分 - 仪表图

将设置添加到配置视图并在小部件视图中使用它们

在本节中,您将了解如何添加小部件配置字段,并在小部件视图中将输入的值显示为文本。

小部件配置由表单 (Zabbix\Widgets\CWidgetForm) 和小部件表单视图 (widget.edit.php) 组成。

要添加字段 (Zabbix\Widgets\CWidgetField),您需要创建一个 WidgetForm 类,它将扩展 Zabbix\Widgets\CWidgetForm

表单包含各种类型的字段集 (Zabbix\Widgets\CWidgetField),用于验证用户输入的值。

每个输入元素类型的表单字段 (Zabbix\Widgets\CWidgetField) 将值转换为单一格式以将其存储在数据库中。

小部件的 form 文件应位于 includes 目录中(本教程中为 ui/modules/lesson_gauge_chart/includes/)。 如果文件具有默认名称 WidgetForm.php,则无需在 manifest.json 文件中注册它。 如果文件具有不同的名称,请在 manifest.json 文件的 widget/form_class 部分中指定它。

  1. lesson_gauge_chart 目录中创建一个新目录 includes

  2. includes 目录中创建一个 WidgetForm.php 文件。

ui/modules/lesson_gauge_chart/includes/WidgetForm.php

<?php
       
       namespace Modules\LessonGaugeChart\Includes;
       
       use Zabbix\Widgets\CWidgetForm;
       
       class WidgetForm extends CWidgetForm {
       }
  1. 向小部件配置表单添加一个 Description 字段。 这是一个常规文本字段,用户可以在其中输入任何字符集。 您可以使用 CWidgetFieldTextBox 类来实现它。

ui/modules/lesson_gauge_chart/includes/WidgetForm.php

<?php
       
       namespace Modules\LessonGaugeChart\Includes;
       
       use Zabbix\Widgets\CWidgetForm;
       
       use Zabbix\Widgets\Fields\CWidgetFieldTextBox;
       
       class WidgetForm extends CWidgetForm {
       
       public function addFields(): self {
       return $this
       ->addField(
       new CWidgetFieldTextBox('description', _('Description'))
       );
       }
       }
  1. views 目录中,创建一个小部件配置视图文件 widget.edit.php,并为新的 Description 字段添加一个视图。 对于 CWidgetFieldTextBox 字段类,视图为 CWidgetFieldTextBoxView。

ui/modules/lesson_gauge_chart/views/widget.edit.php

<?php
       
       /**
       * 仪表图小部件表单视图。
       *
       * @var CView $this
       * @var array $data
       */
       
       (new CWidgetFormView($data))
       ->addField(
       new CWidgetFieldTextBoxView($data['fields']['description'])
       )
       ->show();
  1. 转到仪表板并单击小部件中的齿轮图标以打开小部件配置表单。

  2. 小部件配置表单现在包含一个新的 Description 文本字段。 输入任何值,例如 Gauge chart description

  1. 单击小部件配置表单中的 Apply。然后单击右上角的 Save changes 以保存仪表板。 请注意,新描述在任何地方都看不到,小部件仍显示“Hello, world!”。

要使新描述显示在小部件中,需要从数据库中检索 Description 字段值并将其传递给小部件视图。

为此,您需要创建一个操作类。

  1. lesson_gauge_chart 目录中创建一个新目录 actions

  2. actions 目录中创建一个 WidgetView.php 文件。

WidgetView 操作类将扩展 CControllerDashboardWidgetView 类。

小部件配置字段的值存储在操作类的 $fields_values 属性中。

ui/modules/lesson_gauge_chart/actions/WidgetView.php

<?php
       
       命名空间 Modules\LessonGaugeChart\Actions;
       
       使用 CControllerDashboardWidgetView,
       CControllerResponseData;
       
       class WidgetView extends CControllerDashboardWidgetView {
       
       protected function doAction(): void {
       $this->setResponse(new CControllerResponseData([
       'name' => $this->getInput('name', $this->widget->getName()),
       'description' => $this->fields_values['description'],
       'user' => [
       'debug_mode' => $this->getDebugMode()
       ]
       ]));
       }
       }
  1. 打开 manifest.json 并在 actions/widget.lesson_gauge_chart.view 部分中将 WidgetView 注册为操作类。

ui/modules/lesson_gauge_chart/manifest.json

{
       "manifest_version": 2.0,
       "id": "lesson_gauge_chart",
       "type": "widget",
       "name": "Gauge chart",
       "namespace": "LessonGaugeChart",
       "version": "1.0",
       "author": "Zabbix",
       "actions": {
       "widget.lesson_gauge_chart.view": {
       "class": "WidgetView"
       }
       }
       }
  1. 现在,您可以在小部件视图中使用包含在 $data['description'] 中的描述字段的值。

打开 views/widget.view.php 并将静态文本“Hello, world!”替换为 $data['description']

ui/modules/lesson_gauge_chart/views/widget.view.php

<?php
       
       /**
       * 仪表盘小部件视图。
       *
       * @var CView $this
       * @var array $data
       */
       
       (new CWidgetView($data))
       ->addItem(
       new CTag('h1', true, $data['description'])
       )
       ->show();
  1. 刷新仪表板页面。您现在应该看到小部件描述文本,而不是“Hello, world!”。

通过 API 获取项目值

小部件应显示用户选择的项目的最后一个值。 为此,您需要在小部件配置中添加选择项目的功能。

在本节中,您将了解如何向小部件表单添加项目选择字段以及如何将此字段的可视部分添加到配置视图。 然后,小部件控制器将能够通过 API 请求检索项目数据及其值。 收到后,该值可显示在小部件视图中。

  1. 打开 includes/WidgetForm.php 并添加 CWidgetFieldMultiSelectItem 字段。 这将允许在配置表单中选择一个项目。

ui/modules/lesson_gauge_chart/includes/WidgetForm.php

<?php
       
       命名空间 Modules\LessonGaugeChart\Includes;
       
       使用 Zabbix\Widgets\{
       CWidgetField,
       CWidgetForm
       };
       
       使用 Zabbix\Widgets\Fields\{
       CWidgetFieldMultiSelectItem,
       CWidgetFieldTextBox
       };
       
       /**
       * 仪表图表小部件表单。
       */
       class WidgetForm 扩展 CWidgetForm {
       
       public function addFields(): self {
       return $this
       ->addField(
       (new CWidgetFieldMultiSelectItem('itemid', _('Item')))
       ->setFlags(CWidgetField::FLAG_NOT_EMPTY | CWidgetField::FLAG_LABEL_ASTERISK)
       ->setMultiple(false)
       )
       ->addField(
       new CWidgetFieldTextBox('description', _('Description'))
       );
       }
       }
  1. 打开 views/widget.edit.php 并将字段可视化组件添加到配置视图。

ui/modules/lesson_gauge_chart/views/widget.edit.php

<?php
       
       /**
       * 仪表盘小部件表单视图。
       *
       * @var CView $this
       * @var array $data
       */
       
       (new CWidgetFormView($data))
       ->addField(
       new CWidgetFieldMultiSelectItemView($data['fields']['itemid'])
       )
       ->addField(
       new CWidgetFieldTextBoxView($data['fields']['description'])
       )
       ->show();
  1. 返回仪表板并单击小部件中的齿轮图标以打开小部件配置表单。

  2. 小部件配置表单现在包含一个新的输入字段 Item。 选择主机“Zabbix 服务器”和项目“平均负载(1 分钟平均值)”。

  1. 在小部件配置表单中单击 应用。然后单击右上角的 保存更改 以保存仪表板。

  2. 打开并修改 actions/WidgetView.php

从现在开始,项目 ID 将在小部件控制器中的 $this->fields_values['itemid'] 中可用。 doAction() 控制器方法使用 API 方法 item.get 收集项目数据(名称、值类型、单位),并使用 API 方法 history.get 收集项目的最后一个值。

ui/modules/lesson_gauge_chart/actions/WidgetView.php

<?php
       
       命名空间 Modules\LessonGaugeChart\Actions;
       
       使用 API,
       CControllerDashboardWidgetView,
       CControllerResponseData;
       
       类 WidgetView 扩展了 CControllerDashboardWidgetView {
       
       受保护的函数 doAction():void {
       $db_items = API::Item()->get([
       'output' => ['itemid', 'value_type', 'name', 'units'],
       'itemids' => $this->fields_values['itemid'],
       'webitems' => true,
       'filter' => [
       'value_type' => [ITEM_VALUE_TYPE_UINT64, ITEM_VALUE_TYPE_FLOAT]
       ]
       ]);
       
       $value = null;
       
       if ($db_items) {
       $item = $db_items[0];
       
       $history = API::History()->get([
       'output' => API_OUTPUT_EXTEND,
       'itemids' => $item['itemid'],
       'history' => $item['value_type'],
       'sortfield' => 'clock',
       'sortorder' => ZBX_SORT_DOWN,
       'limit' => 1
       ]);
       
       if ($history) {
       $value = convertUnitsRaw([
       'value' => $history[0]['value'],
       'units' => $item['units']
       ]);
       }
       }
       
       $this->setResponse(new CControllerResponseData([
       'name' => $this->getInput('name', $this->widget->getName()),
       'value' => $value,
       'description' => $this->fields_values['description'],
       'user' => [
       'debug_mode' => $this->getDebugMode()
       ]
       ]));
       }
       }
  1. 打开 views/widget.view.php 并将项目值添加到小部件视图。

ui/modules/lesson_gauge_chart/views/widget.view.php

<?php
       
       /**
       * 仪表图小部件视图。
       *
       * @var CView $this
       * @var array $data
       */
       
       (new CWidgetView($data))
       ->addItem([
       new CTag('h1', true, $data['description']),
       new CDiv($data['value'] !== null ? $data['value']['value'] : _('No data'))
       ])
       ->show();
  1. 刷新仪表板页面。小部件将显示最新的项目值。

将高级配置设置添加到配置视图

在本节中,您将了解如何添加可扩展/可折叠的 高级配置 部分,其中包含可选参数,例如颜色、最小值和最大值、单位以及之前创建的 描述 字段。

  1. 在主窗口小部件目录 lesson_gauge_chart 中创建一个 Widget.php 文件,以创建一个新的类 Widget

Widget 类将扩展 CWidget 基类以添加/覆盖默认窗口小部件设置(在本例中为翻译)。

如果缺少数据,下面提供的 JavaScript 将显示字符串“无数据”。

“无数据”字符串存在于 Zabbix UI 翻译文件中。

如果有任何窗口小部件常量,建议也在 Widget 类中指定它们。

ui/modules/lesson_gauge_chart/Widget.php

<?php
       
       namespace Modules\LessonGaugeChart;
       
       use Zabbix\Core\CWidget;
       
       class Widget extends CWidget {
       
       public const UNIT_AUTO = 0;
       
       public const UNIT_STATIC = 1;
       
       public function getTranslationStrings(): array {
       return [
       'class.widget.js' => [
       'No data' => _('No data')
       ]
       ];
       }
       }
  1. 打开 includes/WidgetForm.php 并添加新字段 Color(颜色选择器)、Min(数字字段)、Max(数字字段)和 Units(选择),并定义颜色选择器的默认调色板,以便可以在后续步骤中使用。

ui/modules/lesson_gauge_chart/includes/WidgetForm.php

<?php
       
       命名空间 Modules\LessonGaugeChart\Includes;
       
       使用 Modules\LessonGaugeChart\Widget;
       
       使用 Zabbix\Widgets\{
       CWidgetField,
       CWidgetForm
       };
       
       使用 Zabbix\Widgets\Fields\{
       CWidgetFieldColor,
       CWidgetFieldMultiSelectItem,
       CWidgetFieldNumericBox,
       CWidgetFieldSelect,
       CWidgetFieldTextBox
       };
       
       /**
       * 仪表图表小部件表单。
       */
       类 WidgetForm 扩展了 CWidgetForm {
       
       public const DEFAULT_COLOR_PALETTE = [
       'FF465C', 'B0AF07', '0EC9AC', '524BBC', 'ED1248', 'D1E754', '2AB5FF', '385CC7', 'EC1594', 'BAE37D',
       '6AC8FF', 'EE2B29', '3CA20D', '6F4BBC', '00A1FF', 'F3601B', '1CAE59', '45CFDB', '894BBC', '6D6D6D'
       ];
       
       公共函数 addFields(): self {
       返回 $this
       ->addField(
       (new CWidgetFieldMultiSelectItem('itemid', _('Item')))
       ->setFlags(CWidgetField::FLAG_NOT_EMPTY | CWidgetField::FLAG_LABEL_ASTERISK)
       ->setMultiple(false)
       )
       ->addField(
       (new CWidgetFieldColor('chart_color', _('Color')))->setDefault('FF0000')
       )
       ->addField(
       (new CWidgetFieldNumericBox('value_min', _('Min')))
       ->setDefault(0)
       ->setFlags(CWidgetField::FLAG_NOT_EMPTY | CWidgetField::FLAG_LABEL_ASTERISK)
       )
       ->addField(
       (new CWidgetFieldNumericBox('value_max', _('Max')))
       ->setDefault(100)
       ->setFlags(CWidgetField::FLAG_NOT_EMPTY | CWidgetField::FLAG_LABEL_ASTERISK)
       )
       ->addField(
       (new CWidgetFieldSelect('value_units', _('Units'), [
       Widget::UNIT_AUTO => _x('Auto', '历史源选择方法'),
       Widget::UNIT_STATIC => _x('Static', '历史源选择方法')
       ]))->setDefault(Widget::UNIT_AUTO)
       )
       ->addField(
       (new CWidgetFieldTextBox('value_static_units'))
       )
       ->addField(
       new CWidgetFieldTextBox('description', _('Description'))
       );
       }
       }
  1. 打开 views/widget.edit.php 并将字段可视化组件添加到配置视图。

ui/modules/lesson_gauge_chart/views/widget.edit.php

<?php
       
       /**
       * 仪表图小部件表单视图。
       *
       * @var CView $this
       * @var array $data
       */
       
       $lefty_units = new CWidgetFieldSelectView($data['fields']['value_units']);
       $lefty_static_units = (new CWidgetFieldTextBoxView($data['fields']['value_static_units']))
       ->setPlaceholder(_('value'))
       ->setWidth(ZBX_TEXTAREA_TINY_WIDTH);
       
       (新 CWidgetFormView($data))
       ->addField(
       (新 CWidgetFieldMultiSelectItemView($data['fields']['itemid']))
       ->setPopupParameter('numeric', true)
       )
       ->addFieldset(
       (新 CWidgetFormFieldsetCollapsibleView(_('高级配置')))
       ->addField(
       新 CWidgetFieldColorView($data['fields']['chart_color'])
       )
       ->addField(
       新 CWidgetFieldNumericBoxView($data['fields']['value_min'])
       )
       ->addField(
       新 CWidgetFieldNumericBoxView($data['fields']['value_max'])
       )
       ->addItem([
       $lefty_units->getLabel(),
       (新 CFormField([
       $lefty_units->getView()->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
       $lefty_static_units->getView()
       ]))
       ])
       ->addField(
       new CWidgetFieldTextBoxView($data['fields']['description'])
       )
       )
       ->show();

CWidgetFormView 类的 addField() 方法将 CSS 类字符串作为第二个参数。

  1. 返回仪表板,切换到编辑模式,然后单击小部件中的齿轮图标以打开小部件配置表单。 小部件配置表单现在包含一个新的可展开/可折叠部分 高级配置

  1. 展开 高级配置 部分以查看其他小部件配置字段。 请注意,字段 颜色 尚未有颜色选择器。 这是因为必须使用 JavaScript 初始化颜色选择器,这将在下一部分中添加 - 将 JavaScript 添加到小部件

添加在小组建中添加JavaScript

向小部件添加 CSS 样式

在本节中,您将学习如何添加自定义 CSS 样式以使小部件看起来更具吸引力。

  1. 对于小部件样式,请在 assets 目录中创建一个新目录 css

  2. assets/css 目录中创建一个 widget.css 文件。 要设置小部件元素的样式,请使用选择器 div.dashboard-widget-{widget id}。 要为整个小部件配置 CSS,请使用选择器 form.dashboard-widget-{widget id}

ui/modules/lesson_gauge_chart/assets/css/widget.css

div.dashboard-widget-lesson_gauge_chart {
       display: grid;
       grid-template-rows: 1fr;
       padding: 0;
       }
       
       div.dashboard-widget-lesson_gauge_chart .chart {
       display: grid;
       align-items: center;
       justify-items: center;
       }
       
       div.dashboard-widget-lesson_gauge_chart .chart canvas {
       background: white;
       }
       
       div.dashboard-widget-lesson_gauge_chart .description {
       padding-bottom: 8px;
       font-size: 1.750em;
       line-height: 1.2;
       text-align: center;
       }
       
       .dashboard-grid-widget-hidden-header div.dashboard-widget-lesson_gauge_chart .chart {
       margin-top: 8px;
       }
  1. 打开 manifest.json 并将 CSS 文件名 (widget.css) 添加到 assets/css 部分中的数组。 这将允许 widget.css 中定义的 CSS 样式随仪表板页面一起加载。

ui/modules/lesson_gauge_chart/manifest.json

{
       "manifest_version": 2.0,
       "id": "lesson_gauge_chart",
       "type": "widget",
       "name": "Gauge chart",
       "namespace": "LessonGaugeChart",
       "version": "1.0",
       "author": "Zabbix",
       "actions": {
       "widget.lesson_gauge_chart.view": {
       "class": "WidgetView"
       }
       },
       "widget": {
       "js_class": "WidgetLessonGaugeChart"
       },
       "assets": {
       "css": ["widget.css"],
       "js": ["class.widget.js"]
       }
       }
  1. 刷新仪表板页面以查看小部件的完成版本。