前言
PE版本有CSV/XLS数据导出功能,具体视频演示查看官方文档地址。
对此功能的描述如下:
ThingsBoard允许您将数据从小部件导出到CSV或XLS。几乎任何小部件都支持此功能。
导出数据集中的列列表与您在数据集配置中配置的参数列表相对应。
CE版本实现演示
注意:
调试前端代码 在ui-ngx目录下 打开命令行 执行yarn start
进行调试,更改后自动重新编译前端,不需要重复启动项目。
thingsboard版本 3.2.0
组件设置页面修改
添加「启用数据导出选项」
源码实现
主要修改下列文件(添加注释部分代码。官方源码部分有省略,减少篇幅)ui-ngx/src/app/modules/home/components/widget/
widget-config.component.html
377行
<div fxLayout="column" fxLayoutAlign="center" fxLayoutGap="8px" fxFlex.sm="40%" fxFlex.gt-sm="30%">
<mat-checkbox formControlName="enableFullscreen">
{{ 'widget-config.enable-fullscreen' | translate }}
</mat-checkbox>
<!--添加数据导出按钮↓↓↓-->
<mat-checkbox formControlName="enableDataExport">
{{ 'widget-config.enable-data-export' | translate }}
</mat-checkbox>
</div>
widget-config.component.ts
208行
this.widgetSettings = this.fb.group({
dropShadow: [null, []],
enableFullscreen: [null, []],
//添加是否允许数据导出变量
enableDataExport: [null, []],
backgroundColor: [null, []],
...
});
379行
this.widgetSettings.patchValue({
dropShadow: isDefined(config.dropShadow) ? config.dropShadow : true,
enableFullscreen: isDefined(config.enableFullscreen) ? config.enableFullscreen : true,
//是否允许数据导出 设置默认值
enableDataExport: isDefined(config.enableDataExport) ? config.enableDataExport : true,
backgroundColor: config.backgroundColor,
...
},
ui-ngx/src/app/shared/models/widget.models.ts
369行
export interface WidgetConfig {
dropShadow?: boolean;
enableFullscreen?: boolean;
//添加是否允许数据导出变量
enableDataExport?: boolean;
useDashboardTimewindow?: boolean;
...
}
组件右上角导出数据按钮实现
源码实现
ui-ngx/src/app/modules/home/components/dashboard/dashboard.component.html
123行 添加俩个注释中间部分
注意:
<mat-icon>{{'archive'}}</mat-icon>
中的archive
代表图标样式,其他mat-icon
标签同理可替换图标 可以在https://www.materialpalette.com/icons中找到喜欢的进行替换。
<button mat-button mat-icon-button *ngFor="let action of widget.widgetActions"
[fxShow]="!isEdit && action.show"
(click)="action.onAction($event)"
matTooltip="{{ action.name | translate }}"
matTooltipPosition="above">
<mat-icon>{{ action.icon }}</mat-icon>
</button>
<!--数据导出按钮实现 开始↓-->
<button mat-button mat-icon-button
[matMenuTriggerFor]="menu"
#menuTrigger="matMenuTrigger"
[fxShow]="!isEdit && widget.enableDataExport"
matTooltip="{{ 'widget.data-export' | translate }}"
matTooltipPosition="above">
<mat-icon>{{'archive'}}</mat-icon>
</button>
<mat-menu #menu="matMenu">
<button mat-menu-item (click)="exportData($event, widgetComponent.widgetContext,'csv');menuTrigger.toggleMenu();">
<mat-icon>insert_drive_file</mat-icon>
<span>{{ 'widget.data-export-csv' | translate }}</span>
</button>
<button mat-menu-item (click)="exportData($event, widgetComponent.widgetContext,'xls');menuTrigger.toggleMenu();">
<mat-icon>insert_drive_file</mat-icon>
<span>{{ 'widget.data-export-xls' | translate }}</span>
</button>
<button mat-menu-item (click)="exportData($event, widgetComponent.widgetContext,'xlsx');menuTrigger.toggleMenu();">
<mat-icon>insert_drive_file</mat-icon>
<span>{{ 'widget.data-export-xlsx' | translate }}</span>
</button>
</mat-menu>
<!--数据导出按钮实现 结束↑-->
<button mat-button mat-icon-button
[fxShow]="!isEdit && widget.enableFullscreen"
(click)="$event.stopPropagation(); widget.isFullscreen = !widget.isFullscreen"
matTooltip="{{(widget.isFullscreen ? 'fullscreen.exit' : 'fullscreen.expand') | translate}}"
matTooltipPosition="above">
<mat-icon>{{ widget.isFullscreen ? 'fullscreen_exit' : 'fullscreen' }}</mat-icon>
</button>
ui-ngx/src/app/modules/home/models/dashboard-component.models.ts
添加注释部分代码
export class DashboardWidget implements GridsterItem, IDashboardWidget {
dropShadow: boolean;
enableFullscreen: boolean;
//308行后 添加变量
enableDataExport: boolean;
hasTimewindow: boolean;
}
//379行后 添加默认值
this.enableDataExport = isDefined(this.widget.config.enableDataExport) ? this.widget.config.enableDataExport : true;
ui-ngx/src/app/shared/models/ace/widget-completion.models.ts
217行
enableDataExport: {
description: 'Whether to enable data export button on widget.',
meta: 'property',
type: 'boolean'
},
ui-ngx/src/app/modules/home/components/dashboard/dashboard.component.ts
添加方法
//文件开头导入依赖
import { WidgetContext } from '@home/models/widget-component.models';
exportData($event: Event, ctx: WidgetContext, fileType) {
if ($event) {
$event.stopPropagation();
}
const export_data = this.data_format(ctx.datasources, ctx.data);
this.export(export_data, fileType, ctx.widgetConfig.title);
}
console.log(fileType);
可以看出点击的哪个文件类型的导出按钮console.log(ctx.datasources);
可以看出实体enityName,实体类型enityType及数据点dataKeysconsole.log(ctx.data);
可以看到具体数据,格式是二维数据[[时间戳,值],[时间戳,值],[时间戳,值]],还有每条数据对应的数据键this.data_format(datasource, data);
是对数据做格式转换
转化后执行console.log(export_data);
结果如下
最后执行this.export(export_data, fileType, ctx.widgetConfig.title);
导出数据到浏览器下载。
文件名格式小部件标题-时间戳.文件后缀
translate相关
ui-ngx/src/assets/locale/locale.constant-zh_CN.json
添加widget
中的内容
"widget": {
"data-export": "导出数据",
"data-export-csv": "数据导出为CSV格式",
"data-export-xls": "数据导出为XLS格式",
"data-export-xlsx": "数据导出为XLSX格式",
}
添加widget-config
中的内容
"widget-config": {
"enable-data-export": "启用数据导出",
}
时间段选择
如果勾选了「使用仪表板的时间窗口」
则导出数据的时间段就是仪表板上的时间段内的数据
可以根据自己需求得时间段进行修改
如果没有勾选「使用仪表板的时间窗口」
那么组件上会有时间选择器
可以根据自己需求得时间段进行修改
优化
按照前面步骤做完,所有部件类型都加上了数据导出功能。实际上rpc,alarm,static是不需要的。
小部件有五种类型:timeseries,latest-values,rpc,alarm,static
但并不是每一种部件类型都需要数据导出功能。下面演示如何让rpc,static,alarm三类部件去掉数据导出功能。
rpc,static,alarm去掉图例中的启用数据导出选项
ui-ngx/src/app/modules/home/components/widget/widget-config.component.ts
- 添加变量控制是否渲染启用数据导出选项
- writeValue方法给isEnableDataExport赋值 ```typescript //添加变量控制是否渲染启用数据导出选项 isEnableDataExport: boolean;
writeValue(value: WidgetConfigComponentData): void { this.modelValue = value; this.removeChangeSubscriptions(); if (this.modelValue) { if (this.widgetType !== this.modelValue.widgetType) { this.widgetType = this.modelValue.widgetType; this.buildForms(); //给isEnableDataExport赋值 this.isEnableDataExport = (!(this.widgetType === widgetType.static || this.widgetType === widgetType.rpc || this.widgetType === widgetType.alarm)); } …. } }
//384行 this.widgetSettings.patchValue中之前定义的默认值改为false //是否允许数据导出 设置默认值 enableDataExport: isDefined(config.enableDataExport) ? config.enableDataExport : false,
ui-ngx/src/app/modules/home/components/widget/widget-config.component.html
1. 前面图例页面中添加的`启用数据导出`按钮上添加`*ngIf='isEnableDataExport'`
```html
<!--添加数据导出按钮↓↓↓-->
<mat-checkbox *ngIf='isEnableDataExport' formControlName="enableDataExport">
{{ 'widget-config.enable-data-export' | translate }}
</mat-checkbox>
效果
导出功能手动打开,添加后默认 启用数据导出
选项是不勾选状态。rpc,alram,static类型部件不显示启用数据导出
选项
alarm类型部件左上角没有了
rpc类型部件左上角没有了吧
而且部件设置中也没有了选项启用数据导出
测试
新建俩种实体
实体Timer A
Timer B
有数据点 bili
ali
实体Bus A
Bus B
有数据点 long
lat
规则链生成测试数据,红框内的节点复制后共8份。
每一个节点:1条数据/s,四个节点8份 = 32条数据/s。
测试导出10分钟数据:10分钟60秒32条 = 1.92w条
注意:测试节点生成数据无数量限制message-count = 0,但是根规则链的保存时序节点TTL设置600s(10分钟)有效期,防止测试数据无限多。
1.92w条近10分钟的数据瞬间导出,数据结构视频演示,包含不同实体的不同字段。
[![数据演示.mp4 (1.79MB)](https://gw.alipayobjects.com/mdn/prod_resou/afts/img/ANNs6TKOR3isAAAAAAAAAAABkARQnAQ)](https://www.yuque.com/thingsboard/book/yoe8ys?_lake_card=%7B%22status%22%3A%22done%22%2C%22name%22%3A%22%E6%95%B0%E6%8D%AE%E6%BC%94%E7%A4%BA.mp4%22%2C%22size%22%3A1881041%2C%22taskId%22%3A%22Bzrdghg9ZnWb%22%2C%22taskType%22%3A%22%22%2C%22url%22%3Anull%2C%22cover%22%3Anull%2C%22videoId%22%3A%22inputs%2Fprod%2Fyuque%2F2021%2F1453676%2Fmp4%2F1619587751391-ff983a97-57b9-45a1-9c98-5ffc5c9a43e5.mp4%22%2C%22download%22%3Afalse%2C%22percent%22%3A100%2C%22__spacing%22%3A%22both%22%2C%22id%22%3A%228BmAu%22%2C%22margin%22%3A%7B%22top%22%3Atrue%2C%22bottom%22%3Atrue%7D%2C%22card%22%3A%22video%22%7D#8BmAu)到这里,毫无保留的数据及功能已经全部拿到,基本可以自己实现了,就差数据格式转换和导出浏览器下载,有动手能力的自己实现一下也是不错的。
不想掉头发的可以继续看下面的内容:
- 下面俩个方法的具体实现
const export_data = this.data_format(ctx.datasources, ctx.data);
this.export(export_data, fileType, ctx.widgetConfig.title);