这是原厂英文文档的翻译页面. 欢迎帮助我们 完善文档.

创建一个 widget (tutorial)

这是一个分步教程,演示如何create一个简单的仪表板小部件。 您可以将此widget的所有文件下载为ZIP压缩包:lesson_gauge_chart.zip

你将构建的内容

在本教程中,您将首先构建一个基础的“Hello, world!” widget,然后将其转换为一个更高级的 widget,以仪表图的形式显示一个 监控项 值。 以下是最终完成的 widget 的外观:

Part I - "Hello, world!"

在本节中,您将学习如何create最低要求的widget元素,并向Zabbix前端添加一个新的widget。

向 Zabbix 前端添加空白小部件

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

所有自定义小部件均被视为外部模块,且必须添加到 Zabbix 前端安装目录的 modules 目录中(例如,zabbix/ui/modules)。 目录 zabbix/ui/widgets 专用于 Zabbix 内置小部件,并会随着 Zabbix UI 一同更新。

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

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"
       }

3。在 Zabbix 前端中,进入 Administration → General → Modules 页面,然后点击 Scan directory 按钮。

4。在列表中找到新模块 Gauge chart,点击 "Disabled" 超链接,将模块状态从 "Disabled" 更改为 "Enabled"(如果模块未列出,请参阅 安装 章节)。

5。打开一个仪表板,切换到编辑模式并添加一个新的小部件。在 Type 字段中,选择 "Gauge chart"。

6。此时,Gauge chart 小部件 get 的配置仅包含通用小部件 get 字段 NameRefresh interval。点击 Add 将该小部件 get 添加到仪表板。

7。一个空白的小部件 get 应该会出现在仪表板上。点击右上角的 Top 的 Save changes 按钮以保存仪表板更改。

添加小部件视图

该小部件的视图file应位于views目录中(本教程中为ui/modules/lesson_gauge_chart/views/)。 如果file使用默认名称widget.view.php,则无需在manifest.json file中注册。 如果file使用其他名称,请在manifest.json file的actions/widget.lesson_gauge_chart.view部分指定。

  1. lesson_gauge_chart目录中创建views目录。

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

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

<?php
       
       /**
        * Gauge chart widget view.
        *
        * @var CView $this
        * @var array $data
        */
       
       (new CWidgetView($data))
           ->addItem(
               new CTag('h1', true, 'Hello, world!')
           )
           ->show();
  1. 刷新仪表板。此时Gauge chart小部件将显示"Hello, world!"。

第二部分 - 仪表图

向配置视图添加设置,并在小部件视图中使用这些设置

在本节中,您将学习如何添加一个 widget 配置字段,并将输入的值以文本形式显示在 widget 视图中。

widget 配置由一个表单(Zabbix\Widgets\CWidgetForm)和一个 widget 表单视图(widget.edit.php)组成。
要添加字段(Zabbix\Widgets\CWidgetField),您需要 create 一个 WidgetForm 类,该类将继承 Zabbix\Widgets\CWidgetForm

表单包含一组各种类型的字段(Zabbix\Widgets\CWidgetField),用于验证用户输入的值。
每种输入元素类型的表单字段(Zabbix\Widgets\CWidgetField)会将值转换为统一格式,以便存储在数据库中。

小部件的 表单 file 应位于 includes 目录中(对于本教程,即 ui/modules/lesson_gauge_chart/includes/)。
如果 file 使用默认名称 WidgetForm.php,则无需在 manifest.json 文件中注册它。
如果 file 使用了其他名称,请在 manifest.json 文件的 widget/form_class 部分指定该名称。

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

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

ui/modules/lesson_gauge_chart/includes/WidgetForm.php

<?php
       
       namespace Modules\LessonGaugeChart\Includes;
       
       use Zabbix\Widgets\CWidgetForm;
       
       class WidgetForm extends CWidgetForm {
       }
  1. 在 widget 配置表单中添加一个 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 目录中,create 一个 widget 配置视图 file widget.edit.php,并为新的 Description 字段添加视图。
    对于 CWidgetFieldTextBox 字段类,对应的视图是 CWidgetFieldTextBoxView

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

<?php
       
       /**
        * Gauge chart widget form view.
        *
        * @var CView $this
        * @var array $data
        */
       
       (new CWidgetFormView($data))
           ->addField(
               new CWidgetFieldTextBoxView($data['fields']['description'])
           )
           ->show();
  1. 转到仪表板,点击 widget 上的齿轮图标以打开 widget 配置表单。

  2. 此时 widget 配置表单中包含了一个新的 Description 文本字段。
    输入任意值,例如 Gauge chart description

  1. 在 widget 配置表单中点击 Apply。然后在右上角的 Top 区域点击 Save changes 以保存仪表板。
    请注意,新的描述目前在任何地方都不可见,widget 仍然显示 "Hello, world!"。

为了让新描述显示在小部件中,需要从数据库中检索 Description 字段的值,并将其传递给 widget 视图。
为此,您需要 create 一个动作类。

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

  2. actions 目录中创建一个 WidgetView.php file。
    WidgetView 动作类将继承 CControllerDashboardWidgetView 类。

widget 配置字段的值存储在动作类的 $fields_values 属性中。

ui/modules/lesson_gauge_chart/actions/WidgetView.php

<?php
       
       namespace Modules\LessonGaugeChart\Actions;
       
       use 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. 现在您可以在 widget 视图中使用描述字段的值,该值包含在 $data['描述'] 中。
    打开 views/widget.view.php,将静态文本 "Hello, world!" 替换为 $data['描述']

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

<?php
       
       /**
        * Gauge chart widget view.
        *
        * @var CView $this
        * @var array $data
        */
       
       (new CWidgetView($data))
           ->addItem(
               new CTag('h1', true, $data['description'])
           )
           ->show();
  1. 刷新仪表板页面。此时您应该看到 widget 的描述文本,而不是 "Hello, world!"。

通过API检索监控项值

该widget应显示用户选择的监控项的最新值。为此,你需要在widget配置中添加选择监控项的功能。

在本节中,你将学习如何向widget表单中添加监控项选择字段,以及如何将该字段的可视化部分添加到配置视图中。然后,widget控制器将能够通过API请求检索监控项数据及其值。接收到该值后,可以在widget视图中显示。

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

ui/modules/lesson_gauge_chart/includes/WidgetForm.php

<?php
       
       namespace Modules\LessonGaugeChart\Includes;
       
       use Zabbix\Widgets\{
           CWidgetField,
           CWidgetForm
       };
       
       use Zabbix\Widgets\Fields\{
           CWidgetFieldMultiSelectItem,
           CWidgetFieldTextBox
       };
       
       /**
        * Gauge chart widget form.
        */
       class WidgetForm extends 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
       
       /**
        * Gauge chart widget form view.
        *
        * @var CView $this
        * @var array $data
        */
       
       (new CWidgetFormView($data))
           ->addField(
               new CWidgetFieldMultiSelectItemView($data['fields']['itemid'])
           )
           ->addField(
               new CWidgetFieldTextBoxView($data['fields']['description'])
           )
           ->show();
  1. 返回仪表板并点击widget中的齿轮图标以打开widget配置表单。

  2. widget配置表单现在包含一个新的输入字段监控项。选择主机 "Zabbix server" 以及监控项 "Load average (1m avg)"。

  1. 在widget配置表单中点击 Apply。然后点击Top右上角的 Save changes 以保存仪表板。

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

从现在开始,监控项的ID将在widget控制器中通过 $this->fields_values['itemid'] 获取。doAction() 控制器方法将使用API方法 item.get 收集监控项数据(名称、值类型、单位),并使用API方法 history.get 收集监控项的最新值。

ui/modules/lesson_gauge_chart/actions/WidgetView.php

<?php
       
       namespace Modules\LessonGaugeChart\Actions;
       
       use API,
           CControllerDashboardWidgetView,
           CControllerResponseData;
       
       class WidgetView extends CControllerDashboardWidgetView {
       
           protected function 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 并将监控项的值添加到widget视图中。

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

<?php
       
       /**
        * Gauge chart widget view.
        *
        * @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. 刷新仪表板页面。widget将显示最新的监控项值。

向配置视图添加高级配置设置

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

  1. 在主部件目录lesson_gauge_chart中创建Widget.php file,以create一个新的Widget类。

Widget类将扩展CWidget基类,以添加/覆盖默认部件设置(在本例中为翻译)。 下面提供的JavaScript会在数据缺失时显示string“无数据”。 “无数据”string存在于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并添加新字段颜色(颜色选择器)、最小值(数字字段)、最大值(数字字段)和单位(选择框),并为颜色选择器定义默认调色板,以便在后续步骤中使用。

ui/modules/lesson_gauge_chart/includes/WidgetForm.php

<?php
       
       namespace Modules\LessonGaugeChart\Includes;
       
       use Modules\LessonGaugeChart\Widget;
       
       use Zabbix\Widgets\{
           CWidgetField,
           CWidgetForm
       };
       
       use Zabbix\Widgets\Fields\{
           CWidgetFieldColor,
           CWidgetFieldMultiSelectItem,
           CWidgetFieldNumericBox,
           CWidgetFieldSelect,
           CWidgetFieldTextBox
       };
       
       /**
        * Gauge chart widget form.
        */
       class WidgetForm extends 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'
           ];
       
           public function addFields(): self {
               return $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', 'history source selection method'),
                           Widget::UNIT_STATIC => _x('Static', 'history source selection method')
                       ]))->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
       
       /**
        * Gauge chart widget form view.
        *
        * @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);
       
       (new CWidgetFormView($data))
           ->addField(
               (new CWidgetFieldMultiSelectItemView($data['fields']['itemid']))
                   ->setPopupParameter('numeric', true)
           )
           ->addFieldset(
               (new CWidgetFormFieldsetCollapsibleView(_('Advanced configuration')))
                   ->addField(
                       new CWidgetFieldColorView($data['fields']['chart_color'])
                   )
                   ->addField(
                       new CWidgetFieldNumericBoxView($data['fields']['value_min'])
                   )
                   ->addField(
                       new CWidgetFieldNumericBoxView($data['fields']['value_max'])
                   )
                   ->addItem([
                       $lefty_units->getLabel(),
                       (new CFormField([
                           $lefty_units->getView()->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
                           $lefty_static_units->getView()
                       ]))
                   ])
                   ->addField(
                       new CWidgetFieldTextBoxView($data['fields']['description'])
                   )
           )
           ->show();

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

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

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

向小部件添加 JavaScript

在本节中,您将学习如何添加一个使用JavaScript制作的仪表盘图表,用于显示最新值是正常、过高还是过低。

  1. views目录中创建widget.edit.js.phpfile。

JavaScript将负责在配置视图中初始化颜色选择器。

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

<?php
       
       use Modules\LessonGaugeChart\Widget;
       
       ?>
       
       window.widget_lesson_gauge_chart_form = new class {
       
           init({color_palette}) {
               this._unit_select = document.getElementById('value_units');
               this._unit_value = document.getElementById('value_static_units');
       
               this._unit_select.addEventListener('change', () => this.updateForm());
       
               colorPalette.setThemeColors(color_palette);
       
               for (const colorpicker of jQuery('.<?= ZBX_STYLE_COLOR_PICKER ?> input')) {
                   jQuery(colorpicker).colorpicker();
               }
       
               const overlay = overlays_stack.getById('widget_properties');
       
               for (const event of ['overlay.reload', 'overlay.close']) {
                   overlay.$dialogue[0].addEventListener(event, () => { jQuery.colorpicker('hide'); });
               }
       
               this.updateForm();
           }
       
           updateForm() {
               this._unit_value.disabled = this._unit_select.value == <?= Widget::UNIT_AUTO ?>;
           }
       };
  1. 打开views/widget.edit.php并将包含JavaScript的widget.edit.js.phpfile添加到配置视图。 为此,请使用includeJsFile()方法。要添加内联JavaScript,请使用addJavaScript()方法。

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

<?php
       
       /**
        * Gauge chart widget form view.
        *
        * @var CView $this
        * @var array $data
        */
       
       use Modules\LessonGaugeChart\Includes\WidgetForm;
       
       $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);
       
       (new CWidgetFormView($data))
           ->addField(
               (new CWidgetFieldMultiSelectItemView($data['fields']['itemid']))
                   ->setPopupParameter('numeric', true)
           )
           ->addFieldset(
               (new CWidgetFormFieldsetCollapsibleView(_('Advanced configuration')))
                   ->addField(
                       new CWidgetFieldColorView($data['fields']['chart_color'])
                   )
                   ->addField(
                       new CWidgetFieldNumericBoxView($data['fields']['value_min'])
                   )
                   ->addField(
                       new CWidgetFieldNumericBoxView($data['fields']['value_max'])
                   )
                   ->addItem([
                       $lefty_units->getLabel(),
                       (new CFormField([
                           $lefty_units->getView()->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
                           $lefty_static_units->getView()
                       ]))
                   ])
                   ->addField(
                       new CWidgetFieldTextBoxView($data['fields']['description'])
                   )
           )
           ->includeJsFile('widget.edit.js.php')
           ->addJavaScript('widget_lesson_gauge_chart_form.init('.json_encode([
               'color_palette' => WidgetForm::DEFAULT_COLOR_PALETTE
           ], JSON_THROW_ON_ERROR).');')
           ->show();
  1. 返回仪表盘,点击部件中的齿轮图标打开部件配置表单。 现在展开高级配置部分即可看到已初始化的颜色选择器。 填写各字段值并为仪表盘图表选择颜色。

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

  2. 打开actions/WidgetView.php并update控制器。

$this->fields_values属性现在包含所有高级配置字段的值。 完善控制器以实现将配置和选定的监控项值传递给部件视图。

ui/modules/lesson_gauge_chart/actions/WidgetView.php

<?php
       
       namespace Modules\LessonGaugeChart\Actions;
       
       use API,
           CControllerDashboardWidgetView,
           CControllerResponseData;
       
       class WidgetView extends CControllerDashboardWidgetView {
       
           protected function 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]
                   ]
               ]);
       
               $history_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) {
                       $history_value = convertUnitsRaw([
                           'value' => $history[0]['value'],
                           'units' => $item['units']
                       ]);
                   }
               }
       
               $this->setResponse(new CControllerResponseData([
                   'name' => $this->getInput('name', $this->widget->getName()),
                   'history' => $history_value,
                   'fields_values' => $this->fields_values,
                   'user' => [
                       'debug_mode' => $this->getDebugMode()
                   ]
               ]));
           }
       }
  1. 打开并修改views/widget.view.php

您需要create一个用于仪表盘图表的容器(将在后续步骤中绘制)以及一个描述文本容器。

要使用setVar()方法将值作为JSONobject传递给JavaScript。

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

<?php
       
       /**
        * Gauge chart widget view.
        *
        * @var CView $this
        * @var array $data
        */
       
       (new CWidgetView($data))
           ->addItem([
               (new CDiv())->addClass('chart'),
               $data['fields_values']['description']
                   ? (new CDiv($data['fields_values']['description']))->addClass('description')
                   : null
           ])
           ->setVar('history', $data['history'])
           ->setVar('fields_values', $data['fields_values'])
           ->show();
  1. lesson_gauge_chart目录中新建assets目录。 该目录将用于存储JavaScript、CSS以及可能需要的其他资源(如字体或图像)。

  2. 为部件视图JavaScript,在assets目录下createjs子目录。

  3. assets/js目录中创建class.widget.jsfile。

此JavaScript部件类将扩展所有仪表盘部件的基类——CWidget

仪表盘依赖于部件的正确实现,并通过调用相应的JavaScript方法与部件通信相关信息。 仪表盘还期望部件在发生交互时generate事件。 因此,CWidget类包含一组具有默认部件行为实现的方法,可通过扩展该类进行自定义。

本例中需要对以下部件行为实现自定义逻辑:

  • 负责定义部件初始状态的部件初始化(参见onInitialize()方法);
  • 当部件update过程成功且无错误时显示部件内容(即绘制仪表盘图表)(参见processUpdateResponse(response)方法及相关的*_resizeChart()_updatedChart()*方法)
  • 调整部件尺寸(参见onResize()方法及相关的*_resizeChart()*方法)

对于仪表盘图表部件的其他方面,将使用部件行为的默认实现。 要了解CWidget类的JavaScript方法详情,请参阅:JavaScript

由于此JavaScript是部件视图所必需的,应随仪表盘页面加载。 要实现JavaScript加载,您需要在manifest.jsonfile中updateassets/jsjs_class参数,如步骤10.所示

ui/modules/lesson_gauge_chart/assets/js/class.widget.js

class WidgetLessonGaugeChart extends CWidget {
       
           static UNIT_AUTO = 0;
           static UNIT_STATIC = 1;
       
           onInitialize() {
               super.onInitialize();
       
               this._refresh_frame = null;
               this._chart_container = null;
               this._canvas = null;
               this._chart_color = null;
               this._min = null;
               this._max = null;
               this._value = null;
               this._last_value = null;
               this._units = '';
           }
       
           processUpdateResponse(response) {
               if (response.history === null) {
                   this._value = null;
                   this._units = '';
               }
               else {
                   this._value = Number(response.history.value);
                   this._units = response.fields_values.value_units == WidgetLessonGaugeChart.UNIT_AUTO
                       ? response.history.units
                       : response.fields_values.value_static_units;
               }
       
               this._chart_color = response.fields_values.chart_color;
               this._min = Number(response.fields_values.value_min);
               this._max = Number(response.fields_values.value_max);
       
               super.processUpdateResponse(response);
           }
       
           setContents(response) {
               if (this._canvas === null) {
                   super.setContents(response);
       
                   this._chart_container = this._body.querySelector('.chart');
                   this._chart_container.style.height =
                       `${this._getContentsSize().height - this._body.querySelector('.description').clientHeight}px`;
                   this._canvas = document.createElement('canvas');
       
                   this._chart_container.appendChild(this._canvas);
       
                   this._resizeChart();
               }
       
               this._updatedChart();
           }
       
           onResize() {
               super.onResize();
       
               if (this._state === WIDGET_STATE_ACTIVE) {
                   this._resizeChart();
               }
           }
       
           _resizeChart() {
               const ctx = this._canvas.getContext('2d');
               const dpr = window.devicePixelRatio;
       
               this._canvas.style.display = 'none';
               const size = Math.min(this._chart_container.offsetWidth, this._chart_container.offsetHeight);
               this._canvas.style.display = '';
       
               this._canvas.width = size * dpr;
               this._canvas.height = size * dpr;
       
               ctx.scale(dpr, dpr);
       
               this._canvas.style.width = `${size}px`;
               this._canvas.style.height = `${size}px`;
       
               this._refresh_frame = null;
       
               this._updatedChart();
           }
       
           _updatedChart() {
               if (this._last_value === null) {
                   this._last_value = this._min;
               }
       
               const start_time = Date.now();
               const end_time = start_time + 400;
       
               const animate = () => {
                   const time = Date.now();
       
                   if (time <= end_time) {
                       const progress = (time - start_time) / (end_time - start_time);
                       const smooth_progress = 0.5 + Math.sin(Math.PI * (progress - 0.5)) / 2;
                       let value = this._value !== null ? this._value : this._min;
                       value = (this._last_value + (value - this._last_value) * smooth_progress - this._min) / (this._max - this._min);
       
                       const ctx = this._canvas.getContext('2d');
                       const size = this._canvas.width;
                       const char_weight = size / 12;
                       const char_shadow = 3;
                       const char_x = size / 2;
                       const char_y = size / 2;
                       const char_radius = (size - char_weight) / 2 - char_shadow;
       
                       const font_ratio = 32 / 100;
       
                       ctx.clearRect(0, 0, size, size);
       
                       ctx.beginPath();
                       ctx.shadowBlur = char_shadow;
                       ctx.shadowColor = '#bbb';
                       ctx.strokeStyle = '#eee';
                       ctx.lineWidth = char_weight;
                       ctx.lineCap = 'round';
                       ctx.arc(char_x, char_y, char_radius, Math.PI * 0.749, Math.PI * 2.251, false);
                       ctx.stroke();
       
                       ctx.beginPath();
                       ctx.strokeStyle = `#${this._chart_color}`;
                       ctx.lineWidth = char_weight - 2;
                       ctx.lineCap = 'round';
                       ctx.arc(char_x, char_y, char_radius, Math.PI * 0.75,
                           Math.PI * (0.75 + (1.5 * Math.min(1, Math.max(0, value)))), false
                           );
                       ctx.stroke();
       
                       ctx.shadowBlur = 2;
                       ctx.fillStyle = '#1f2c33';
                       ctx.font = `${(char_radius * font_ratio)|0}px Arial`;
                       ctx.textAlign = 'center';
                       ctx.textBaseline = 'middle';
                       ctx.fillText(`${this._value !== null ? this._value : t('No data')}${this._units}`,
                           char_x, char_y, size - char_shadow * 4 - char_weight * 2
                       );
       
                       ctx.fillStyle = '#768d99';
                       ctx.font = `${(char_radius * font_ratio * .5)|0}px Arial`;
                       ctx.textBaseline = 'top';
       
                       ctx.textAlign = 'left';
                       ctx.fillText(`${this._min}${this._min != '' ? this._units : ''}`,
                           char_weight * .75, size - char_weight * 1.25, size / 2 - char_weight
                       );
       
                       ctx.textAlign = 'right';
                       ctx.fillText(`${this._max}${this._max != '' ? this._units : ''}`,
                           size - char_weight * .75, size - char_weight * 1.25, size / 2 - char_weight
                       );
       
                       requestAnimationFrame(animate);
                   }
                   else {
                       this._last_value = this._value;
                   }
               };
       
               requestAnimationFrame(animate);
           }
       }
  1. 打开manifest.json并添加:
  • 将file名称(class.widget.js)添加到assets/js部分的array中;
  • 将类名(WidgetLessonGaugeChart)添加到widget部分的js_class参数。

WidgetLessonGaugeChart类现在将随仪表盘自动加载。

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": {
               "js": ["class.widget.js"]
           }
       }

向小部件添加 CSS 样式

在本节中,您将学习如何添加自定义 CSS 样式,以使 widget 看起来更加美观。

1。针对 widget 样式,在 assets 目录中 create 一个名为 css 的新目录。

2。在 assets/css 目录中创建一个 widget.css file 文件。
为 widget 元素设置样式,请使用选择器 div.dashboard-widget-{widget id}
为整个 widget 配置 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;
       }

3。打开 manifest.json 并将 CSS file 名称(widget.css)添加到 assets/css 部分的 array 中。
这样就可以在仪表板页面加载时同时加载 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"]
           }
       }

4。刷新仪表板页面,以查看 widget 的最终 version 效果。