仪表盘系统使开发者能够创建自定义可配置的小部件,提供超越内置小部件功能的能力。这些自定义小部件可以设计成任何外观和功能,包括通过 AJAX 请求获取数据和处理事件的能力。
仪表盘小部件使用 October CMS Vue 框架。该框架简化了服务端和客户端两部分的开发。
在本文档中,我们将创建一个简单的组件,用于显示当前时间并包含一个按钮。该按钮的点击操作将在服务器上使用 AJAX 进行处理。

仪表盘小部件应放置在插件根目录下的 vuecomponents 目录中,例如 author/plugin/vuecomponents。每个组件必须包含一个用于服务器端实现的 PHP 文件、一个用于 Vue 组件的 JavaScript 文件,以及一个用于 Vue 模板的 PHP 文件。下面是一个小部件的文件结构示例。请注意,CSS、JavaScript 和局部文件的名称是根据小部件的类文件名派生而来的:
├── vuecomponents
| ├── mycustomwidget
| | └── assets
| | └── css
| | └── mycustomwidget.css ← 样式表文件
| | └── js
| | └── mycustomwidget.js ← JavaScript 文件
| | └── partials
| | └── _mycustomwidget.php ← 局部文件
| └── MyCustomWidget.php ← Vue 部件类
仪表盘小部件的服务器代码必须定义一个类,该类继承自 Backend\Classes\VueReportWidgetBase。小部件类唯一需要实现的方法是 getData。下面是该类的初始实现 (MyCustomWidget.php):
namespace Acme\MyPlugin\VueComponents;
use Dashboard\Classes\VueReportWidgetBase;
use Dashboard\Classes\ReportFetchData;
use Carbon\Carbon;
class MyCustomWidget extends VueReportWidgetBase
{
public function getData(ReportFetchData $data): mixed
{
return [
'current_time' => Carbon::now()->format('Y-m-d H:i:s')
];
}
}小部件的 Vue 组件必须定义在 assets/js 目录下的文件中,如前所述。组件代码示例 (assets/js/mycustomwidget.js):
oc.Modules.register('plugin.author.vuecomponents.mycustomwidget', function () {
Vue.component('plugin-author-vuecomponents-mycustomwidget', {
extends: Vue.options.components['dashboard-component-dashboard-widget-base'],
data: function () {
return {
}
},
methods: {
useCustomData: function () {
return true;
},
makeDefaultConfigAndData: function () {
Vue.set(this.widget.configuration, 'title', 'My Custom Widget');
},
getSettingsConfiguration: function () {
const result = [{
property: "title",
title: "Title",
type: "string",
}];
return result;
}
},
template: '#plugin_author_vuecomponents_mycustomwidget'
});
});在定义组件时,请确保在 register 和 component 调用中以及在模板标识符中使用正确的命名空间。这些应从您的插件的 PHP 命名空间和插件 PHP 类名中推断出来。
Widget Vue 组件必须包含示例代码中列出的所有方法。 具体来说:
useCustomData - 此方法必须返回 true 以告知仪表板系统该组件管理其自身的数据生命周期。makeDefaultConfigAndData - 设置默认小部件配置。在我们的示例中,我们设置了小部件标题。配置对象的键是任意的,旨在供小部件内部使用。我们稍后将演示如何在组件模板中访问小部件配置。在服务器端代码中,小部件配置可以在 getData 方法中通过 widgetConfig 参数访问。getSettingsConfiguration - 提供小部件设置表单的配置。该配置使用 JavaScript 对象定义,并与 检查器字段配置 保持一致。组件 Vue 模板必须在一个局部文件中定义,该文件位于 partials 目录中,如上所述。下面是组件模板的基本实现 (partials/_mycustomwidget.php):
<div class="widget-body">
<h3 class="widget-title" v-text="widget.configuration.title"></h3>
<div v-if="!loading">
<p>Current server time: <span v-if="fullWidgetData" v-text="fullWidgetData.data.current_time"></span></p>
</div>
<p v-else>Loading...</p>
</div>模板展示了如何从部件配置中检索 title 属性,该属性是之前在 makeDefaultConfigAndData 方法中设置的。
它还演示了如何访问由仪表盘系统提供的loading 属性。此属性在数据加载AJAX请求期间切换为true,这些请求由仪表盘处理。这些请求可以通过组件配置的更改或用户在仪表盘上选择日期范围时触发。您可以利用loading 属性来指示小部件的加载状态。
最后,该模板指导您使用 fullWidgetData.data 结构访问服务器提供的数据。
仪表盘小部件必须在插件注册文件 (Plugin.php) 中,在 registerReportWidgets 方法内注册。该方法应返回一个数组,其键中包含小部件类,值中包含小部件配置(标签、分组和所需权限)。vue 属性应设置为 true,以表明它是一个 Vue 组件。
public function registerReportWidgets()
{
return [
\October\Test\VueComponents\MyCustomWidget::class => [
'label' => 'Custom Widget',
'group' => 'Acme Author'
]
];
}label 和 group 属性的 registerReportWidgets 返回数组是微件的名称和作者的名称。它们将显示在仪表板用户界面中,特别是在“创建微件”菜单中。一旦微件注册完成,你就可以将其添加到仪表板:

当你添加一个部件时,其设置表单将自动打开:

仪表盘小部件可以使用内置的 AJAX 框架触发和处理事件。我们的演示小部件包含一个按钮。我们将创建一个处理程序,这样当按钮被点击时,服务器代码会返回一个随机数,以显示在小部件主体中。
首先,按钮必须在组件模板中定义。下面的代码定义了一个按钮和一个元素,用于显示服务器返回的值:
<button
class="btn btn-primary"
:disabled="loadingButtonData"
@click.stop.prevent="onButtonClick"
>Click me</button>
<span v-text="buttonClickResult"></span>loadingButtonData 和 buttonClickResult 值尚不可用,需要在小部件的 Vue 组件中定义:
data: function () {
return {
buttonClickResult: null,
loadingButtonData: false
}
},还需要创建 onButtonClick 方法。此方法利用了基础部件 Vue 组件的 request 方法。它将 loadingButtonData 设置为 true,表示加载开始。收到服务器响应后,此方法会用响应中的 result 属性更新 buttonClickResult。有关创建服务器端处理程序的详细信息稍后提供。此方法在请求数据中包含 some_var,这在当前的服务器实现中没有使用,但在其他场景中可能会有用。在服务器端,some_var 的值可以通过 extraData 处理程序参数访问。
onButtonClick: async function () {
this.loadingButtonData = true;
this.buttonClickResult = null;
try {
const response = await this.request('onGetSomeData', {
some_var: "some value"
});
this.buttonClickResult = response.result;
}
catch (err) {
$.oc.alert(err.message);
}
finally {
this.loadingButtonData = false;
}
}最后,服务器端处理程序必须添加到小部件的PHP类中。确保处理程序函数名与客户端 request 调用中指定的名称对应。此外,它应该是一个受保护的方法,接受小部件配置数组和额外数据数组。
protected function onGetSomeData(array $widgetConfig, array $extraData)
{
return [
'result' => rand(1, 100)
];
}下方是显示从服务器接收到的随机值的小部件截图:
