最近在整理thingsboard课程,基于最新thingsboard版本3.9.1/4.0,欢迎大家点赞,收藏、关注我,提问,在评论区留言,我争取把最新、最准、最好的课程,呈现在各位亦师亦友的csdn广大读者面前。
目录
自定义部件静态部件点击事件
两种方式可以实现静态部件的点击事件触发动作。
静态部件不从设备、实体或其他数据源获取实时数据。这意味着它不会订阅任何遥测数据、属性更新或报警信息,这种设计使得静态部件加载速度快、资源消耗低。
静态部件在 ThingsBoard 中的典型工作流程:
1. 初始化阶段:onInit 函数
当小部件加载时,会调用self.onInit 方法,负责渲染HTML 内容并绑定事件。
HTML 渲染 :将用户提供的HTML 字符串插入到容器中。
CSS 注入 :动态生成 <style> 标签,防止样式冲突。
事件绑定 :为HTML 元素添加点击事件,触发预定义动作(如跳转、弹窗等)。
2. 生命周期管理
ThingsBoard 提供了多个生命周期钩子函数,静态部件也可以使用这些钩子来执行特定操作:
self.onInit():初始化内容。
self.onDestroy():清理资源(如移除全局变量、解绑事件监听器)。
self.onDataUpdated():虽然静态部件不使用数据更新,但该方法仍然存在,可留空或用于调试。
3. 交互支持
尽管是静态部件,但仍可通过JavaScript 实现基本的交互行为,比如点击事件、弹窗提示等。这通常通过在HTML中添加onclick属性,并绑定到window上的函数实现 。
1-自定义函数方式
新增加一个部件,名称htmlcode0609,如下:
选择"静态部件",如下:
静态部件的默认js代码如下:
// 初始化函数,当部件被创建或初始化时调用
self.onInit = function() {
// 获取 AngularJS 的依赖注入器
var $injector = self.ctx.$scope.$injector;
// 通过服务映射获取 utils 服务
var utils = $injector.get(self.ctx.servicesMap.get('utils'));
// 创建 CSS 解析器实例
var cssParser = new cssjs();
cssParser.testMode = false;
// 为部件生成唯一的命名空间,基于卡片 CSS 内容的哈希值
var namespace = 'html-card-' + hashCode(self.ctx.settings.cardCss);
cssParser.cssPreviewNamespace = namespace;
// 创建样式元素并应用到部件
cssParser.createStyleElement(namespace, self.ctx.settings.cardCss);
self.ctx.$container.addClass(namespace);
// 生成事件函数前缀,基于卡片 CSS、HTML 和部件 ID 的哈希值
var evtFnPrefix = 'htmlCard_' + Math.abs(hashCode(self.ctx.settings.cardCss + self.ctx.settings.cardHtml + self.ctx.widget.id));
// 构建卡片 HTML,添加点击事件处理
cardHtml = '<div style="height:100%" onclick="' + evtFnPrefix + '_onClickFn(event)">' +
self.ctx.settings.cardHtml +
'</div>';
// 替换 HTML 中的自定义翻译标记
cardHtml = replaceCustomTranslations(cardHtml);
// 将生成的 HTML 设置到部件容器中
self.ctx.$container.html(cardHtml);
// 定义全局点击处理函数
window[evtFnPrefix + '_onClickFn'] = function (event) {
// 调用 ThingsBoard 的点击动作 API
self.ctx.actionsApi.elementClick(event);
}
// 哈希生成函数
function hashCode(str) {
var hash = 0;
var i, char;
if (str.length === 0) return hash;
for (i = 0; i < str.length; i++) {
char = str.charCodeAt(i);
hash = ((hash << 5) - hash) + char;
hash = hash & hash; // 转换为 32 位整数
}
return hash;
}
// 替换自定义翻译标记的函数
function replaceCustomTranslations (pattern) {
// 匹配 {i18n:...} 格式的翻译标记
var customTranslationRegex = new RegExp('{i18n:[^{}]+}', 'g');
pattern = pattern.replace(customTranslationRegex, getTranslationText);
return pattern;
}
// 获取翻译文本的函数
function getTranslationText (variable) {
// 使用 ThingsBoard 的 utils 服务进行翻译
return utils.customTranslation(variable, variable);
}
}
// 定义部件的动作源
self.actionSources = function() {
return {
'elementClick': { // 元素点击动作
name: 'widget-action.element-click', // 动作名称
multiple: true // 是否允许多个动作
}
};
}
// 部件销毁时的清理函数
self.onDestroy = function() {
// 当前为空,可以在这里添加清理逻辑
// 例如移除全局事件处理函数等
}
代码解析说明:
访问部件设置:
通过self.ctx.settings访问部件配置,例如:self.ctx.settings.cardHtml获取HTML内容
DOM操作:
使用self.ctx.$container访问部件容器,例如:self.ctx.$container.html(content)设置HTML内容
样式处理:
推荐使用唯一命名空间避免样式冲突,可以使用类似示例中的cssjs库或直接创建style元素
事件处理:
定义动作源(actionSources)使部件可交互,通过self.ctx.actionsApi触发动作
点击“保存”按钮,
在widget_type表中,存储了这个部件的信息。
编辑部件,修改html部分和js部分,改为自定义部件,
在html和js代码中,实现点击事件处理,如下:
点击保存。
点击事件完成。点击clickme,触发alert告警对话框,点击HtmlButton,触发alert告警对话框。
如上增加的静态部件,可以在部件列表中可查询到,如下:
2-静态部件动作触发方式
再新增一个静态部件,名称html0601,如下:
配置静态部件的动作和行为,如下:
触发alert告警对话框,如下:
代码如下:
自定义部件背景颜色
在self.onInit = function() {}方法中,加入如下代码:
self.ctx.$container[0].style.backgroundColor = "#ff4500";
根据数据值变换部件背景颜色:
self.onDataUpdated = function() {
function isNumber(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
if (self.ctx.valueCell && self.ctx.data.length > 0) {
var cellData = self.ctx.data[0];
if (cellData.data.length > 0) {
var tvPair = cellData.data[cellData.data.length -
1];
var value = tvPair[1];
var txtValue;
if (isNumber(value)) {
var decimals = self.ctx.decimals;
var units = self.ctx.units;
if (self.ctx.datasources.length > 0 && self.ctx.datasources[0].dataKeys.length > 0) {
dataKey = self.ctx.datasources[0].dataKeys[0];
if (dataKey.decimals || dataKey.decimals === 0) {
decimals = dataKey.decimals;
}
if (dataKey.units) {
units = dataKey.units;
}
}
// Change background color to red (v<0) or green (v>=0)
self.ctx.$container[0].style.backgroundColor = value > 0 ? "#00ff00" : "#ff0000";
txtValue = self.ctx.utils.formatValue(value, decimals, units, true);
} else {
txtValue = value;
}
self.ctx.valueCell.html(txtValue);
var targetWidth;
var minDelta;
if (self.ctx.labelPosition === 'left') {
targetWidth = self.ctx.datasourceContainer.width() - self.ctx.labelCell.width();
minDelta = self.ctx.width/16 + self.ctx.padding;
} else {
targetWidth = self.ctx.datasourceContainer.width();
minDelta = self.ctx.padding;
}
var delta = targetWidth - self.ctx.valueCell.textWidth();
var fontSize = self.ctx.valueFontSize;
if (targetWidth > minDelta) {
while (delta < minDelta && fontSize > 6) {
fontSize--;
self.ctx.valueCell.css('font-size', fontSize+'px');
delta = targetWidth - self.ctx.valueCell.textWidth();
}
}
}
}
};
结束。