2 files added
	
		
		11 files modified
	
	
 
	
	
	
	
	
	
	
	
|  |  |  | 
|---|
|  |  |  | YEAR= 'YEAR', MONTH= 'MONTH', DAY= 'DAY', HOUR= 'HOUR', MINUTE= 'MINUTE' | 
|---|
|  |  |  | } | 
|---|
|  |  |  | export enum AreaRange { | 
|---|
|  |  |  | PROVINCE= 'PROVINCE', | 
|---|
|  |  |  | CITY= 'CITY', | 
|---|
|  |  |  | AREA= 'AREA', | 
|---|
|  |  |  | MONITORPOINT= 'MONITORPOINT', | 
|---|
|  |  |  | DEVICE= 'DEVICE' | 
|---|
|  |  |  | PROVINCE= 1, | 
|---|
|  |  |  | CITY= 2, | 
|---|
|  |  |  | AREA= 3, | 
|---|
|  |  |  | TOWN= 4, | 
|---|
|  |  |  | VILLAGE= 5, | 
|---|
|  |  |  | MONITORPOINT= 6, | 
|---|
|  |  |  | DEVICE= 7 | 
|---|
|  |  |  | } | 
|---|
|  |  |  | export enum ResultCode { | 
|---|
|  |  |  | SUCCESS= 1, FAIL= 0 | 
|---|
|  |  |  | } | 
|---|
|  |  |  | export enum DeviceDimension{ | 
|---|
|  |  |  | export enum DeviceDimension { | 
|---|
|  |  |  | MONITORPOINT= 'MONITORPOINT',  // 监控点维度 比较特殊,自带行政区属性 | 
|---|
|  |  |  | PROFESSION='PROFESSION', | 
|---|
|  |  |  | NONE='NONE' | 
|---|
|  |  |  | } | 
|---|
|  |  |  | PROFESSION= 'PROFESSION', | 
|---|
|  |  |  | NONE= 'NONE' | 
|---|
|  |  |  | } | 
|---|
|  |  |  | 
|---|
|  |  |  | list: environment.SERVER_BASH_URL + 'device/page-list', | 
|---|
|  |  |  | save: environment.SERVER_BASH_URL + 'device/add-or-modify', | 
|---|
|  |  |  | delete: environment.SERVER_BASH_URL + 'device/delete-by-ids', | 
|---|
|  |  |  | count: environment.SERVER_BASH_URL +'device/count-by-example' | 
|---|
|  |  |  | count: environment.SERVER_BASH_URL + 'device/count-by-example' | 
|---|
|  |  |  | }; | 
|---|
|  |  |  | public getListUrl () { | 
|---|
|  |  |  | return this.urls.list; | 
|---|
|  |  |  | 
|---|
|  |  |  | } | 
|---|
|  |  |  | public countByExample(example: ExampleService): Observable<ResultBean<number>> { | 
|---|
|  |  |  | return this.http.get(this.urls.count, { queryParams: example.getSqlParam()}); | 
|---|
|  |  |  | }; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | public getPageByExample(page: PageBean, example: ExampleService): Observable<PageBean> { | 
|---|
|  |  |  | let orderByClause = ''; | 
|---|
|  |  |  | const _queryParams = !!example ? example.getSqlParam() : ''; | 
|---|
|  |  |  | 
|---|
|  |  |  | } | 
|---|
|  |  |  | ); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | public static toThousands(num: string): string { | 
|---|
|  |  |  | var num = (num || 0).toString(), result = ''; | 
|---|
|  |  |  | public static toThousands(number: string): string { | 
|---|
|  |  |  | let num = (number || 0).toString(), result = ''; | 
|---|
|  |  |  | while (num.length > 3) { | 
|---|
|  |  |  | result = ',' + num.slice(-3) + result; | 
|---|
|  |  |  | num = num.slice(0, num.length - 3); | 
|---|
|  |  |  | 
|---|
|  |  |  | avgDeviceCount = ''; | 
|---|
|  |  |  | deviceCountLoading = true; | 
|---|
|  |  |  | // 报警统计 | 
|---|
|  |  |  | alarmCountList:{x: string,y: number}[] = null; | 
|---|
|  |  |  | alarmCountList: {x: string, y: number}[] = null; | 
|---|
|  |  |  | alarmCountCurrMonth = ''; | 
|---|
|  |  |  | alarmCountCurrDay = '';// 单月报警次数 | 
|---|
|  |  |  | alarmCountCurrDay = ''; // 单月报警次数 | 
|---|
|  |  |  | alarmCountLoading = true; | 
|---|
|  |  |  | operationLoading = true; | 
|---|
|  |  |  | operNormalPercent = 0; | 
|---|
|  |  |  | 
|---|
|  |  |  | //     }); | 
|---|
|  |  |  | //     this.totalDeviceCount += fakeDC[i]; | 
|---|
|  |  |  | // } | 
|---|
|  |  |  | let example1 = new ExampleService(); | 
|---|
|  |  |  | let mo = moment(); | 
|---|
|  |  |  | example1.or().andGreaterThanOrEqualTo({ name: "createTime", value: mo.format('YYYY-MM-01 00:00:00') }); | 
|---|
|  |  |  | let example2 = new ExampleService(); | 
|---|
|  |  |  | let example3 = new ExampleService(); | 
|---|
|  |  |  | example3.or().andNotEqualTo({name:'state',value:4}); | 
|---|
|  |  |  | const example1 = new ExampleService(); | 
|---|
|  |  |  | const mo = moment(); | 
|---|
|  |  |  | example1.or().andGreaterThanOrEqualTo({ name: 'createTime', value: mo.format('YYYY-MM-01 00:00:00') }); | 
|---|
|  |  |  | const example2 = new ExampleService(); | 
|---|
|  |  |  | const example3 = new ExampleService(); | 
|---|
|  |  |  | example3.or().andNotEqualTo({name: 'state', value: 4}); | 
|---|
|  |  |  | zip(this.deviceService.countByExample(example1), | 
|---|
|  |  |  | this.deviceService.countByExample(example2), | 
|---|
|  |  |  | this.http.get<ResultBean<{time: string,count: number}[]>>('device/count-by-times',{start:mo.format('YYYY-01-01 00:00:00'),end:mo.format('YYYY-12-31 23:59:59')}), | 
|---|
|  |  |  | this.http.get<ResultBean<{time: string, count: number}[]>>('device/count-by-times', {start: mo.format('YYYY-01-01 00:00:00'), end: mo.format('YYYY-12-31 23:59:59')}), | 
|---|
|  |  |  | this.deviceService.countByExample(example3)).subscribe( | 
|---|
|  |  |  | ([rWtihAvg, rWithToltal,rWithList,rWithNormal]) => { | 
|---|
|  |  |  | if (!!rWtihAvg.code && !!rWithToltal&&!!rWithList.code) { | 
|---|
|  |  |  | ([rWtihAvg, rWithToltal, rWithList, rWithNormal]) => { | 
|---|
|  |  |  | if (!!rWtihAvg.code && !!rWithToltal && !!rWithList.code) { | 
|---|
|  |  |  | this.avgDeviceCount = ToolsService.toThousands(rWtihAvg.data.toString()); | 
|---|
|  |  |  | this.totalDeviceCount = ToolsService.toThousands(rWithToltal.data.toString()); | 
|---|
|  |  |  | this.totalDeviceCountList = rWithList.data.map(item => { | 
|---|
|  |  |  | return {x:item.time,y:item.count}; | 
|---|
|  |  |  | }) | 
|---|
|  |  |  | this.operNormalPercent = Math.round(rWithNormal.data/rWithToltal.data*100); | 
|---|
|  |  |  | return {x: item.time, y: item.count}; | 
|---|
|  |  |  | }); | 
|---|
|  |  |  | this.operNormalPercent = Math.round(rWithNormal.data / rWithToltal.data * 100); | 
|---|
|  |  |  | this.deviceCountLoading = false; | 
|---|
|  |  |  | this.operationLoading = false; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | ); | 
|---|
|  |  |  | zip( | 
|---|
|  |  |  | this.http.get<ResultBean<{time: string,count: number}[]>>("alarm/count-by-times",{start: mo.format('YYYY-MM-01 00:00:00'),end: null,timeUnits: TimeUnits.DAY}), | 
|---|
|  |  |  | this.http.get<ResultBean<{time: string,count: number}[]>>("alarm/count-by-times",{start: mo.format('YYYY-MM-01 00:00:00'),end: null}), | 
|---|
|  |  |  | this.http.get<ResultBean<{time: string,count: number}[]>>("alarm/count-by-times",{start: mo.format('YYYY-MM-DD 00:00:00'),end: null}) | 
|---|
|  |  |  | this.http.get<ResultBean<{time: string, count: number}[]>>('alarm/count-by-times', {start: mo.format('YYYY-MM-01 00:00:00'), end: null, timeUnits: TimeUnits.DAY}), | 
|---|
|  |  |  | this.http.get<ResultBean<{time: string, count: number}[]>>('alarm/count-by-times', {start: mo.format('YYYY-MM-01 00:00:00'), end: null}), | 
|---|
|  |  |  | this.http.get<ResultBean<{time: string, count: number}[]>>('alarm/count-by-times', {start: mo.format('YYYY-MM-DD 00:00:00'), end: null}) | 
|---|
|  |  |  | ).subscribe( | 
|---|
|  |  |  | ([rWithList,rWithMonth,rWithDay]) => { | 
|---|
|  |  |  | if(!!rWithList.code&&!!rWithMonth.code&&!!rWithDay.code){ | 
|---|
|  |  |  | ([rWithList, rWithMonth, rWithDay]) => { | 
|---|
|  |  |  | if (!!rWithList.code && !!rWithMonth.code && !!rWithDay.code) { | 
|---|
|  |  |  | this.alarmCountList = rWithList.data.map( | 
|---|
|  |  |  | item => { | 
|---|
|  |  |  | return {x:item.time,y:item.count}; | 
|---|
|  |  |  | return {x: item.time, y: item.count}; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | ); | 
|---|
|  |  |  | if(!!rWithMonth.data&&rWithMonth.data.length>0){ | 
|---|
|  |  |  | if (!!rWithMonth.data && rWithMonth.data.length > 0) { | 
|---|
|  |  |  | this.alarmCountCurrMonth = ToolsService.toThousands(rWithMonth.data[0].count.toString()); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | if(!!rWithDay.data&&rWithDay.data.length>0) { | 
|---|
|  |  |  | if (!!rWithDay.data && rWithDay.data.length > 0) { | 
|---|
|  |  |  | this.alarmCountCurrDay =  ToolsService.toThousands(rWithDay.data[0].count.toString()); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | this.alarmCountLoading = false; | 
|---|
|  |  |  | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | ); | 
|---|
|  |  |  | }else { | 
|---|
|  |  |  | } else { | 
|---|
|  |  |  | this.openMap(record); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | 
|---|
|  |  |  | private monitorPointService: MonitorPointService, | 
|---|
|  |  |  | private versionService: VersionService, | 
|---|
|  |  |  | private operateUserService: OperateUserService, | 
|---|
|  |  |  | private deviceService:DeviceService, | 
|---|
|  |  |  | private  http:_HttpClient | 
|---|
|  |  |  | private deviceService: DeviceService, | 
|---|
|  |  |  | private  http: _HttpClient | 
|---|
|  |  |  | ) { } | 
|---|
|  |  |  | data: Device; | 
|---|
|  |  |  | //原始数据记录 | 
|---|
|  |  |  | 
|---|
|  |  |  | validateForm: FormGroup; | 
|---|
|  |  |  | ngOnInit() { | 
|---|
|  |  |  | debugger; | 
|---|
|  |  |  | if(!!this.data){ | 
|---|
|  |  |  | Object.assign(this.originalData,this.data); | 
|---|
|  |  |  | if (!!this.data) { | 
|---|
|  |  |  | Object.assign(this.originalData, this.data); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | const data = this.data; | 
|---|
|  |  |  | this.monitorPointChange(null); | 
|---|
|  |  |  | 
|---|
|  |  |  | } | 
|---|
|  |  |  | const validates: Device = { | 
|---|
|  |  |  | name: [data.name, [Validators.required]], | 
|---|
|  |  |  | mac: [data.mac, [Validators.required],[this.macAsyncValidator]], | 
|---|
|  |  |  | mac: [data.mac, [Validators.required], [this.macAsyncValidator]], | 
|---|
|  |  |  | deviceVersionId: [data.deviceVersionId], | 
|---|
|  |  |  | monitorPointId: [data.monitorPointId], | 
|---|
|  |  |  | professionId: [data.professionId], | 
|---|
|  |  |  | 
|---|
|  |  |  | ); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | macAsyncValidator = (control: FormControl): any => { | 
|---|
|  |  |  | return Observable.create(observer =>{ | 
|---|
|  |  |  | return Observable.create(observer => { | 
|---|
|  |  |  | // 编辑状态,mac未改变 | 
|---|
|  |  |  | if(!!this.originalData&&this.originalData.mac === control.value){ | 
|---|
|  |  |  | if (!!this.originalData && this.originalData.mac === control.value) { | 
|---|
|  |  |  | observer.next(null); | 
|---|
|  |  |  | observer.complete(); | 
|---|
|  |  |  | }else { | 
|---|
|  |  |  | } else { | 
|---|
|  |  |  | const exampleService = new ExampleService(); | 
|---|
|  |  |  | exampleService.or().andEqualTo({name:'mac',value:control.value}); | 
|---|
|  |  |  | exampleService.or().andEqualTo({name: 'mac', value: control.value}); | 
|---|
|  |  |  | this.deviceService.countByExample(exampleService).subscribe( | 
|---|
|  |  |  | res => { | 
|---|
|  |  |  | debugger; | 
|---|
|  |  |  | if(!!res.code&&!!res.data){ | 
|---|
|  |  |  | if (!!res.code && !!res.data) { | 
|---|
|  |  |  | observer.next({ error: true, duplicated: true }); | 
|---|
|  |  |  | }else{ | 
|---|
|  |  |  | } else { | 
|---|
|  |  |  | observer.next(null); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | observer.complete(); | 
|---|
|  |  |  | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | }); | 
|---|
|  |  |  | }; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | close() { | 
|---|
|  |  |  | this.subject.destroy(); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | 
|---|
|  |  |  | ToolsService.markAsDirty(this.validateForm); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | professionChange(){ | 
|---|
|  |  |  | this.http.get<ResultBean<any[]>>(environment.SERVER_BASH_URL+"profession/getall").subscribe( | 
|---|
|  |  |  | professionChange() { | 
|---|
|  |  |  | this.http.get<ResultBean<any[]>>(environment.SERVER_BASH_URL + 'profession/getall').subscribe( | 
|---|
|  |  |  | result => { | 
|---|
|  |  |  | if(!!result.code){ | 
|---|
|  |  |  | if (!!result.code) { | 
|---|
|  |  |  | this.professions = result.data; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | 
|---|
|  |  |  | const areaNames = record.areaNames; | 
|---|
|  |  |  | let adress = ''; | 
|---|
|  |  |  | if (areaNames != null) { | 
|---|
|  |  |  | adress += !!areaNames.provinceName?areaNames.provinceName:''; | 
|---|
|  |  |  | adress += !!areaNames.provinceName ? areaNames.provinceName : ''; | 
|---|
|  |  |  | adress += ' '; | 
|---|
|  |  |  | adress += !!areaNames.cityName?areaNames.cityName:''; | 
|---|
|  |  |  | adress += !!areaNames.cityName ? areaNames.cityName : ''; | 
|---|
|  |  |  | adress += ' '; | 
|---|
|  |  |  | adress += !!areaNames.areaName?areaNames.areaName:''; | 
|---|
|  |  |  | adress += !!areaNames.areaName ? areaNames.areaName : ''; | 
|---|
|  |  |  | adress += ' '; | 
|---|
|  |  |  | adress += !!record.address?record.address:''; | 
|---|
|  |  |  | adress += !!record.address ? record.address : ''; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | this.coorPickerService.data.address = adress; | 
|---|
|  |  |  | this.coorPickerService.data['describe'] = '监控站点名称'; | 
|---|
|  |  |  | 
|---|
|  |  |  | </span> | 
|---|
|  |  |  | </td> | 
|---|
|  |  |  | <td nz-td> | 
|---|
|  |  |  | <a (click)="addOrModify(row)">编辑</a> | 
|---|
|  |  |  | <a (click)="addOrModify(row)">编辑</a> | 
|---|
|  |  |  | <span nz-table-divider></span> | 
|---|
|  |  |  | <nz-popconfirm [nzTitle]="'确定要删除该'+grid.title+'吗?'" [nzOkText]="'Yes'" [nzCancelText]="'No'" (nzOnConfirm)="delete(row.id)" > | 
|---|
|  |  |  | <a nz-popconfirm>删除</a> | 
|---|
|  |  |  | </nz-popconfirm> | 
|---|
|  |  |  | <nz-popconfirm [nzTitle]="'确定要删除该'+grid.title+'吗?'" [nzOkText]="'Yes'" [nzCancelText]="'No'" (nzOnConfirm)="delete(row.id)" > | 
|---|
|  |  |  | <a nz-popconfirm>删除</a> | 
|---|
|  |  |  | </nz-popconfirm> | 
|---|
|  |  |  | <span nz-table-divider></span> | 
|---|
|  |  |  | <a (click)="configSensorUnit(row)">配置单位</a> | 
|---|
|  |  |  | </td> | 
|---|
|  |  |  | </tr> | 
|---|
|  |  |  | </tbody> | 
|---|
|  |  |  | 
|---|
|  |  |  | import { Component, OnInit } from '@angular/core'; | 
|---|
|  |  |  | import { Subject } from 'rxjs/Subject'; | 
|---|
|  |  |  | import { SensorEditComponent } from './sensor-edit/sensor-edit.component'; | 
|---|
|  |  |  | import { SensorUnitComponent } from './sensor-unit/sensor-unit.component'; | 
|---|
|  |  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  | 
|---|
|  |  |  | } | 
|---|
|  |  |  | this.load(); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | configSensorUnit(d) { | 
|---|
|  |  |  | const data = {}; | 
|---|
|  |  |  | if ( d != null) { | 
|---|
|  |  |  | Object.assign(data, d); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | this.modalHelper.static(SensorUnitComponent, { data }).subscribe( | 
|---|
|  |  |  | res => { | 
|---|
|  |  |  |  | 
|---|
|  |  |  | } | 
|---|
|  |  |  | ); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
| New file | 
|  |  |  | 
|---|
|  |  |  | <div class="modal-header"> | 
|---|
|  |  |  | <div class="modal-title">配置-传感器单位</div> | 
|---|
|  |  |  | </div> | 
|---|
|  |  |  | <form [formGroup]="validateForm" (ngSubmit)="save($event,validateForm.value,validateForm.valid)" nz-form [nzType]="'horizontal'"> | 
|---|
|  |  |  |  | 
|---|
|  |  |  | </form> | 
|---|
| New file | 
|  |  |  | 
|---|
|  |  |  | import { Component, OnInit } from '@angular/core'; | 
|---|
|  |  |  | import { _HttpClient } from '@delon/theme'; | 
|---|
|  |  |  | import { NzModalSubject } from 'ng-zorro-antd'; | 
|---|
|  |  |  | import { FormGroup } from '@angular/forms'; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | @Component({ | 
|---|
|  |  |  | selector: 'app-sensor-unit', | 
|---|
|  |  |  | templateUrl: './sensor-unit.component.html', | 
|---|
|  |  |  | }) | 
|---|
|  |  |  | export class SensorUnitComponent implements OnInit { | 
|---|
|  |  |  | public isSaving = false; | 
|---|
|  |  |  | public validateForm: FormGroup; | 
|---|
|  |  |  | public data: any; | 
|---|
|  |  |  | constructor( | 
|---|
|  |  |  | private subject: NzModalSubject, | 
|---|
|  |  |  | private http: _HttpClient | 
|---|
|  |  |  | ) { } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | ngOnInit() { | 
|---|
|  |  |  | } | 
|---|
|  |  |  | save($event, value, valid) { | 
|---|
|  |  |  | $event.preventDefault(); | 
|---|
|  |  |  | if (valid) { | 
|---|
|  |  |  | for (const i in this.validateForm.controls) { | 
|---|
|  |  |  | this.validateForm.controls[ i ].disable(); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | this.isSaving = true; | 
|---|
|  |  |  | Object.keys(value).forEach( (key: string) => { | 
|---|
|  |  |  | // '_'为前缀的为自定义属性 | 
|---|
|  |  |  | if (!key.startsWith('_') && value[key] != null) { | 
|---|
|  |  |  | this.data[key] = value[key]; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } ); | 
|---|
|  |  |  | } else { | 
|---|
|  |  |  | this.validate(); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | validate() { | 
|---|
|  |  |  | for (const i in this.validateForm.controls) { | 
|---|
|  |  |  | this.validateForm.controls[ i ].markAsDirty(); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | 
|---|
|  |  |  | import { _HttpClient } from '@delon/theme/services/http/http.client'; | 
|---|
|  |  |  | import { FormBuilder } from '@angular/forms'; | 
|---|
|  |  |  | import { SensorEditComponent } from './basic-info/sensor-edit/sensor-edit.component'; | 
|---|
|  |  |  | import { SensorUnitComponent } from './basic-info/sensor-unit/sensor-unit.component'; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | const routes: Routes = [ | 
|---|
|  |  |  | { | 
|---|
|  |  |  | 
|---|
|  |  |  | ] | 
|---|
|  |  |  | } | 
|---|
|  |  |  | ]; | 
|---|
|  |  |  | const COMPONENTS_NOROUNT = [SensorEditComponent]; | 
|---|
|  |  |  | const COMPONENTS_NOROUNT = [SensorEditComponent, SensorUnitComponent]; | 
|---|
|  |  |  | @NgModule({ | 
|---|
|  |  |  | imports: [ | 
|---|
|  |  |  | // 管道模块必须当前模块导入 | 
|---|
|  |  |  | 
|---|
|  |  |  | ], | 
|---|
|  |  |  | declarations: [ | 
|---|
|  |  |  | BasicInfoComponent, | 
|---|
|  |  |  | SensorUnitComponent, | 
|---|
|  |  |  | SensorEditComponent | 
|---|
|  |  |  | ], | 
|---|
|  |  |  | providers: [SensorsService, _HttpClient, FormBuilder], | 
|---|
|  |  |  | 
|---|
|  |  |  | </tr> | 
|---|
|  |  |  | </thead> | 
|---|
|  |  |  | <tbody formGroupName="alarmLevels" nz-tbody> | 
|---|
|  |  |  | <tr nz-tbody-tr *ngFor="let row of nzTable.data" formGroupName="{{row.sensorKey}}"> | 
|---|
|  |  |  | <tr nz-tbody-tr style="height:50px;" *ngFor="let row of nzTable.data" formGroupName="{{row.sensorKey}}"> | 
|---|
|  |  |  |  | 
|---|
|  |  |  | <td nz-td [nzCheckbox]="true"> | 
|---|
|  |  |  | <label nz-checkbox formControlName="enable"></label> | 
|---|