thingsboard 通过Entities hierarchy部件实现左边菜单点击,右边的表格按左边的分类型进行过滤筛选数据源

在 ThingsBoard 中,要让“Entities hierarchy”部件(左侧树形导航)与右侧的数据表格实现联动——即点击左侧某个节点后,右侧表格立刻按该节点对应的实体类型/层级进行过滤——需要把“数据源别名(Alias)+ 仪表板状态(State)+ 部件动作(Action)”三件事串起来做。下面给出可直接落地的完整步骤(PE/CE 通用)。


一、准备数据模型

  1. 给所有需要被分类的实体(设备/资产)打上统一的属性关系
    例如:

    • 属性 region: “华北”、“华南”

    • 关系 Contains:Asset → Device

  2. 在“资产”里建一个树形结构,如
    根 Asset → 区域 Asset → 子区域 Asset → 设备 Device。


二、做左侧“Entities hierarchy”部件

  1. 进入仪表板编辑模式 → 添加部件 → Cards → Entities hierarchy

  2. 数据源选“实体列表”或“资产查询”别名(见下一步),让它把整个资产树一次性展开。

  3. 在部件设置 → Actions(动作) → 添加动作

    • 触发源:On node selected

    • 动作类型:Update current dashboard state

    • 状态参数:

      entityId: ${entityId}
      entityType: ${entityType}
      entityName: ${entityName}

    保存。


三、做右侧“Entity table”部件

  1. 添加部件 → Cards → Entities table

  2. 关键在数据源别名

    • 打开“Entity aliases” → 新建别名

    • 类型选 Relations query(关系查询)

    • 起点:Dashboard state entity(即左侧点击的节点)

    • 方向:From

    • 关系类型:Contains

    • 最大层级:按需要(一般 1 层即可)

    • 目标实体过滤:可再按类型(Device/Asset)或属性过滤
      保存别名后回到表格部件,数据源选择刚创建的别名。

  3. 表格列配置完后保存。


四、测试

  1. 退出编辑,刷新仪表板。

  2. 在左侧树形列表点任意节点 → 右侧表格立即只显示该节点“包含”的设备或子资产。

  3. 若要多级联动(点区域 → 子区域 → 设备),把层级设成 2 或 3 即可。

ngOnInit(): void {this.ctx.$scope.entitiesTableWidget = this;this.settings = this.ctx.settings;this.widgetConfig = this.ctx.widgetConfig;this.subscription = this.ctx.defaultSubscription;this.initializeConfig();this.updateDatasources();this.ctx.updateWidgetParams();if (this.displayPagination) {this.widgetResize$ = new ResizeObserver(() => {this.ngZone.run(() => {const showHidePageSize = this.elementRef.nativeElement.offsetWidth < hidePageSizePixelValue;if (showHidePageSize !== this.hidePageSize) {this.hidePageSize = showHidePageSize;this.cd.markForCheck();}});});this.widgetResize$.observe(this.elementRef.nativeElement);}function decodeState(raw: string | null): any {if (!raw) return null;try {// 1️⃣ URL 解码const urlDecoded = decodeURIComponent(raw);// 2️⃣ BASE64 解码 → Latin-1 字符串const latin1 = atob(urlDecoded);// 3️⃣ Latin-1 → UTF-8const utf8 = new TextDecoder('utf-8').decode(Uint8Array.from(latin1, c => c.charCodeAt(0)));// 4️⃣ JSON 解析return JSON.parse(utf8);} catch (e) {console.error('state 解码失败', e);return null;}}var collectParamObj=null;// 监听路由参数变化(不刷新页面)this.route.queryParams.pipe(takeUntil(this.destroy$)).subscribe(params => {const state = decodeState(params['state']);//console.log('监听路由state=', JSON.stringify(state));if (!state) return ;if (state.length > 0 && state[0]?.params) {//const stateId = state[0].id;collectParamObj = state?.[0]?.params?.collect_param;if (collectParamObj) {// 把整个 collect_param 对象传进去this.handleUrlParamsChange(collectParamObj);}}});}private handleUrlParamsChange(collectParam:any) {// 根据参数重新加载数据或更新过滤条件// 示例:更新 pageLink 的过滤条件//this.pageLink.textSearch = params.entityId || null;//console.log('filter entityId=', params);if (collectParam){const entityId = collectParam?.entityId?.id;const entityType = collectParam?.entityId?.entityType;const entityName = collectParam?.entityName;const entityLabel = collectParam?.entityLabel;const param={entityType,entityId,entityName,entityLabel};// 延后一帧再执行setTimeout(() => this.updateData(param));}}private buildKeyFiltersFromQueryParams(params: Params): KeyFilter[] {const filters: KeyFilter[] = [];if (!params) {return filters;   // 返回空数组而不是 null,避免下游遍历出错}const entityType = params['entityType'];const entityId = params['entityId'];const entityName = params['entityName'];const entityLabel = params['entityLabel'];if (entityType =="ENTITY_VIEW"){if (entityLabel) {filters.push({key: {type: EntityKeyType.ENTITY_FIELD,key: 'label'},valueType: EntityKeyValueType.STRING,predicate: {type: FilterPredicateType.STRING,operation: StringOperation.EQUAL,value: {defaultValue: entityLabel,dynamicValue: null},ignoreCase: false // ✅ 添加这一行}});}}else if (entityType =="DEVICE"){if (entityName) {filters.push({key: {type: EntityKeyType.ENTITY_FIELD,key: 'name'},valueType: EntityKeyValueType.STRING,predicate: {type: FilterPredicateType.STRING,operation: StringOperation.EQUAL,value: {defaultValue: entityName,dynamicValue: null},ignoreCase: false // ✅ 添加这一行}});}}//console.log("filters",filters);return filters;}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/93869.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/93869.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Ansible】核心概念解析:架构、清单管理与配置入门

本专栏文章持续更新&#xff0c;新增内容使用蓝色表示。对于系统管理员而言&#xff0c;手动管理每一台服务器不仅维护难度极大&#xff0c;而且即使经验丰富&#xff0c;也难免出现疏忽和错误。自动化技术能有效避免因手动管理系统和基础架构而产生的各类问题。其优点包括&…

rs-fMRI_两篇文章中分析方法的梳理(近乎翻译)

文章一文章信息APOE ε4 influences within and between network functional connectivity in posterior cortical atrophy and logopenic progressive aphasia2024美国梅奥诊所发表在Alzheimers Dement. 的文章。“APOE ε4等位基因对后皮质萎缩与进行性语言障碍型失语症的网络…

在互联网大厂的Java面试:谢飞机的搞笑历险记

在互联网大厂的Java面试&#xff1a;谢飞机的搞笑历险记 在一个阳光明媚的早上&#xff0c;我们的主角&#xff0c;程序员谢飞机&#xff0c;走进了一家著名的互联网大厂&#xff0c;准备迎接他人生中最严峻的挑战——Java面试。 第一轮&#xff1a;基础技术面试 面试官&#x…

微软AD国产化替换倒计时——不是选择题,而是生存题

一直以来&#xff0c;微软Active Directory&#xff08;AD&#xff09;作为企业身份管理和访问控制的核心组件&#xff0c;承担着用户认证、权限分配、资源目录管理等基础职能。然而&#xff0c;随着政策、合规与网络安全压力不断加剧&#xff0c;AD面临着前所未有的挑战&#…

MyBatis-Plus MetaObjectHandler的几个坑(主要是id字段)

1.背景 主要是要实现一个id字段的自增长&#xff0c;不依赖数据库的能力&#xff08;已避免后续换库的问题&#xff09;。姑且使用redis作为表的id分配器&#xff0c;因此使用MyBatis-Plus MetaObjectHandler对每个insert的id进行分配。 2.实施过程 以下是实现过程 1.实现MetaO…

Springboot 项目配置多数据源

Springboot 项目配置多数据源 基础环境 java8、springboot2.2.13、mybatis、mysql5.x、oracle 项目配置 1.application.yml spring:datasource:mysql1:username: abcpassword: 123456url: jdbc:mysql://127.0.0.1:3306/panda?useUnicodetrue&characterEncodingUTF-8&z…

STM32_0001 KEILMDK V5.36 编译一个STM32F103C8T6说core_cm3.h文件找不到以及编译器版本不匹配的解决办法

KEILMDK V5.36 编译一个STM32F103C8T6说core_cm3.h文件找不到的解决办法利用KEILMDK V5.36 编译一个STM32F103C8T6说core_cm3.h文件找不到。主要错误信息如下D:/stm32studio/Armmdk/Packs/Keil/STM32F1xx_DFP/2.4.1/Device/Include\stm32f10x.h(486): error: core_cm3.h file n…

基于Transformer的机器翻译——训练篇

前言 还在为机器翻译模型从理论到落地卡壳&#xff1f;系列博客第三弹——模型训练篇强势登场&#xff0c;手把手带你走完Transformer中日翻译项目的最后关键一步&#xff01; 前两期我们搞定了数据预处理&#xff08;分词、词表构建全流程&#xff09;和模型搭建&#xff08…

智能编程中的智能体与 AI 应用:概念、架构与实践场景

一、智能体&#xff08;Intelligent Agent&#xff09;在编程中的定义与架构1. 智能体的核心概念 智能体是指在特定环境中能够自主感知、决策并执行动作的软件实体&#xff0c;具备以下特征&#xff1a;自主性&#xff1a;无需人工干预即可根据环境变化调整行为。交互性&#x…

数组实现各类数据结构

目录 一、数组实现单链表 二、数组实现双链表 三、数组实现栈 四、数组模拟队列 五、数组模拟单调栈 六、数组模拟单调队列&#xff08;滑动窗口&#xff09; 七、数组模拟堆 一、数组实现单链表 #include<iostream> #include<algorithm> #include<cstr…

数据处理与统计分析 —— apply自定义函数

目录 一、向量化与伪向量化 1、向量化 2、np.vectorize 伪向量化&#xff08;特定场景&#xff09; 3、apply&#xff08;自定义函数&#xff09; 二、apply函数 1、对series中使用apply 2、对dataframe中使用apply 3、apply函数案例-泰坦尼克号数据集] 数据集下载链接&#xf…

如何有效利用大语言模型来智能加速产业联盟的产业链转化路径?

观点作者&#xff1a;科易网AI技术转移研究院在科技创新浪潮席卷全球的今天&#xff0c;科技成果转化已成为衡量一个国家创新能力的重要标志。然而&#xff0c;一项权威调查显示&#xff0c;我国科技成果转化率不足30%&#xff0c;大量有价值的创新成果仍停留在实验室阶段&…

视频加水印 视频加水印软件 视频加动态水印

如果你有一个视频&#xff0c;你想给他加一个水印&#xff0c;那么你可以使用这个工具&#xff0c;准备好你的视频和水印。水印一般采用PNG&#xff0c;打开这个工具&#xff0c;把你的视频和水印拖进这个方框当中。视频限制是MP4&#xff0c;水印限制是PNG&#xff0c;它可以把…

面向DeepSeek chat coding实录(二)

向DeepSeek的提问 帮我设计以下两个python class Span 属性&#xff1a; hash值&#xff08;在init函数中通过时间初始化&#xff09; 创建时间&#xff1a;时间&#xff08;在init函数中通过时间初始化&#xff09; 结束时间&#xff1a;时间&#xff08;可选&#xff0c;默认…

Hi3516CV610-00S 海思SOC芯片 可申请开发资料

1.1 概述Hi3516CV610 是一颗应用在安防市场的 IPC SoC。在开放操作系统、新一代视频编解码标准、网络安全和隐私保护、人工智能方面引领行业发展&#xff0c;主要面向室内外场景下的枪机、球机、半球机、海螺机、枪球一体机、双目长短焦机等产品形态&#xff0c;打造极具竞争力…

算法题Day4

目录 13. 练习13 : 整数十位 14. 练习14 : 时间转换 15. 练习15 : 小雨的游泳时间 13. 练习13 : 整数十位 解题方法: #include <iostream> using namespace std; int a; int main() {cin >> a;cout << a % 100 / 10 << endl;return 0; } 14. 练习…

加速你的故障排查:使用 Elasticsearch 构建家电手册的 RAG 应用

作者&#xff1a;来自 Elastic Alessandro Brofferio 学习如何使用 Elasticsearch 构建 RAG 应用&#xff0c;轻松排查你的家电问题。 想要获得 Elastic 认证吗&#xff1f;来看看下一次 Elasticsearch 工程师培训什么时候开始吧&#xff01; Elasticsearch 拥有大量新功能&am…

6.Shell脚本修炼手册---grep命令使用指南

grep 命令&#xff1a;从文本中精准筛选信息的实用指南 文章目录grep 命令&#xff1a;从文本中精准筛选信息的实用指南一、什么是 grep&#xff1f;为什么要用它&#xff1f;二、grep 基本语法三、常用选项详解&#xff08;附实例&#xff09;&#xff08;一&#xff09;模式选…

Python day51

浙大疏锦行 Python day51 复习日&#xff0c;DDPM class DenoiseDiffusion():def __init__(self, eps_model: nn.Module, n_steps: int, device: torch.device):super().__init__()self.eps_model eps_modelself.n_steps n_stepsself.device deviceself.beta torch.linsp…

数据结构:生成 (Generating) 一棵 AVL 树

目录 搭建“创世”的舞台 注入序列&#xff0c;观察演化 注入 10 注入 20 注入 30 注入 40 注入 50 注入 25 再次审视 上一讲&#xff0c;我们已经从最根本的逻辑出发&#xff0c;推导出了 AVL 树失衡时所必需的修复操作——旋转 (Rotation)。 现在&#xff0c;我们将…