如何在 ThingsBoard 前端增加手写签名，并且体现在报告中？
目录 关注我们 关注 ThingsBoard 微信公众号 访问 ThingsBoard 中文社区网站 准备工作 增加签名用的 signature pad 包 新增用于签名的组建 新增配套 service 处理 后端图片处理 代码示例 TS 文件 HTML 文件 结果展示 关注我们 关注 ThingsBoard 微信公众号 手动增加微信公众号：thingsboard_cn 访问 ThingsBoard 中文社区网站 访问网址：http://www.thingsboard.club 准备工作 当然，首先必须要有 ThingsBoard 二次开发基础，可以在本博客中搜索“二次开发”，你会得到很多提升。 如果你有 ThingsBoard 服务需求或二次开发需求，请与我们联系： 18616669123 增加签名用的 signature pad 包 https://www.npmjs.com/package/angular2-signaturepad，根据提示，加入到 package.json 中，确保模块运行正常。 新增用于签名的组建 手工创建或通过命令行创建，sign.component.ts, sign.component.html, sign.component.scss，并且加入到 module.ts 新增配套 service 处理 页面点击触发签名框弹出，保存签名图片到数据库的请求。 后端图片处理 后端需要将前端提交的数据保存到数据库，还需要将数据展现在前端页面。 代码示例 TS 文件 import { Component, Inject, OnInit, SkipSelf, ViewChild } from '@angular/core'; import { ErrorStateMatcher } from '@angular/material/core'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; import { FormBuilder, FormControl, FormGroup, FormGroupDirective, NgForm, Validators } from '@angular/forms'; import { ReportService } from '@core/http/report.service'; import { Report, ReportFill } from '@shared/models/report.models'; import { DialogComponent } from '@shared/components/dialog.component'; import { Router } from '@angular/router'; import { SignaturePad } from 'angular2-signaturepad'; export interface ReportSignObservationDialogData { report: Report; } @Component({ selector: 'tb-report-sign-observation-dialog', templateUrl: './sign-report-observation-dialog.component.html', styleUrls: ['./sign-report-observation-dialog.component.scss'], providers: [{provide: ErrorStateMatcher, useExisting: ReportSignObservationDialogComponent}] }) export class ReportSignObservationDialogComponent extends DialogComponent<ReportSignObservationDialogComponent, Report> implements OnInit, ErrorStateMatcher { @ViewChild(SignaturePad) signaturePad: SignaturePad; private signaturePadOptions: Object = { // passed through to szimek/signature_pad constructor 'minWidth': 2, 'canvasWidth': 400, // 弹出的窗口宽度 'canvasHeight': 200, // 弹出的窗口高度 'backgroundColor': 'rgb(240,240,240)' // 背景颜色 }; reportSignFormGroup: FormGroup; isReadOnly: boolean; reportSign: String; report: Report; submitted = false; constructor(protected store: Store<AppState>, protected router: Router, @Inject(MAT_DIALOG_DATA) public data: ReportSignObservationDialogData, private reportService: ReportService, @SkipSelf() private errorStateMatcher: ErrorStateMatcher, public dialogRef: MatDialogRef<ReportSignObservationDialogComponent, Report>, public fb: FormBuilder) { super(store, router, dialogRef); } ngAfterViewInit() { // this.signaturePad is now available this.signaturePad.set('minWidth', 2); // set szimek/signature_pad options at runtime this.signaturePad.clear(); // invoke functions from szimek/signature_pad API } signatureImage; drawComplete() { // will be notified of szimek/signature_pad's onEnd event // console.log(this.signaturePad.toDataURL()); this.reportSign = this.signaturePad.toDataURL(); this.signatureImage=this.signaturePad.toDataURL(); // 将图片转换成 base64 码 } drawStart() { // will be notified of szimek/signature_pad's onBegin event // console.log('begin drawing'); } ngOnInit(): void { this.buildReportSign(); this.loadReportSign(); } isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean { const originalErrorState = this.errorStateMatcher.isErrorState(control, form); const customErrorState = !!(control && control.invalid && this.submitted); return originalErrorState || customErrorState; } buildReportSign() { this.reportSignFormGroup = this.fb.group({ file: '' }); } loadReportSign() { this.reportSignFormGroup = this.fb.group({ file: '' }); } cancel(): void { this.dialogRef.close(null); } save(): void { this.submitted = true; // console.log(this.data.report.id, this.reportSign); this.report = this.data.report; this.reportService.signReport(this.report, encodeURIComponent(this.reportSign.toString())).subscribe( // 调用保存签名的 service (report) => { this.dialogRef.close(this.report); } ); } } HTML 文件 report.sign-report close {{ 'action.save' | translate }} {{ (isReadOnly ? 'action.close' : 'action.cancel') | translate }} 结果展示 签名提示： 报告结果：