fengxiang
2018-01-25 8570af7c6051c3d9a516f39d597ff49e1e1e2840
设备模块 坐标 校准值 配置 等功能
13 files added
23 files modified
1167 ■■■■■ changed files
package.json 14 ●●●● patch | view | raw | blame | history
src/app/business/entity/data.ts 35 ●●●●● patch | view | raw | blame | history
src/app/business/services/http/alarm-config.service.ts 6 ●●●● patch | view | raw | blame | history
src/app/business/services/http/device-adjust-value.service.ts 25 ●●●●● patch | view | raw | blame | history
src/app/business/services/http/device.service.ts 34 ●●●●● patch | view | raw | blame | history
src/app/business/services/http/monitor-point.service.ts 20 ●●●● patch | view | raw | blame | history
src/app/business/services/http/operate-user.service.ts 32 ●●●●● patch | view | raw | blame | history
src/app/business/services/http/organization.service.ts 4 ●●●● patch | view | raw | blame | history
src/app/business/services/http/version.service.ts 10 ●●●● patch | view | raw | blame | history
src/app/business/services/util/tools.service.ts 14 ●●●●● patch | view | raw | blame | history
src/app/routes/dashboard/monitor/monitor.component.ts 4 ●●●● patch | view | raw | blame | history
src/app/routes/dashboard/workplace/workplace.component.ts 6 ●●●● patch | view | raw | blame | history
src/app/routes/devices/basic-info/adjust-config/adjust-config.component.html 45 ●●●●● patch | view | raw | blame | history
src/app/routes/devices/basic-info/adjust-config/adjust-config.component.ts 120 ●●●●● patch | view | raw | blame | history
src/app/routes/devices/basic-info/basic-info.component.html 30 ●●●●● patch | view | raw | blame | history
src/app/routes/devices/basic-info/basic-info.component.ts 186 ●●●●● patch | view | raw | blame | history
src/app/routes/devices/basic-info/device-edit/device-edit.component.html 105 ●●●●● patch | view | raw | blame | history
src/app/routes/devices/basic-info/device-edit/device-edit.component.ts 133 ●●●●● patch | view | raw | blame | history
src/app/routes/devices/devices.module.ts 19 ●●●● patch | view | raw | blame | history
src/app/routes/devices/monitor-point/monitor-point-edit/monitor-point-edit.component.html 3 ●●●● patch | view | raw | blame | history
src/app/routes/devices/monitor-point/monitor-point.component.html 2 ●●●●● patch | view | raw | blame | history
src/app/routes/devices/monitor-point/monitor-point.component.ts 32 ●●●●● patch | view | raw | blame | history
src/app/routes/devices/version/version-sensor-config/version-sensor-config.component.ts 2 ●●● patch | view | raw | blame | history
src/app/routes/map/coordinates-picker/coordinates-picker.component.css 19 ●●●●● patch | view | raw | blame | history
src/app/routes/map/coordinates-picker/coordinates-picker.component.html 44 ●●●●● patch | view | raw | blame | history
src/app/routes/map/coordinates-picker/coordinates-picker.component.ts 120 ●●●●● patch | view | raw | blame | history
src/app/routes/map/coordinates-picker/coordinates-picker.service.ts 15 ●●●●● patch | view | raw | blame | history
src/app/routes/map/map.module.ts 21 ●●●●● patch | view | raw | blame | history
src/app/routes/sensors/basic-info/basic-info.component.ts 2 ●●● patch | view | raw | blame | history
src/app/routes/sensors/basic-info/sensor-edit/sensor-edit.component.html 2 ●●● patch | view | raw | blame | history
src/app/routes/sensors/basic-info/sensor-edit/sensor-edit.component.ts 2 ●●● patch | view | raw | blame | history
src/app/routes/systems/account/account.component.ts 1 ●●●● patch | view | raw | blame | history
src/app/routes/systems/organization/organization-config/organization-config.component.html 10 ●●●● patch | view | raw | blame | history
src/app/routes/systems/organization/organization-config/organization-config.component.ts 6 ●●●●● patch | view | raw | blame | history
src/assets/img/map_coordinates.png patch | view | raw | blame | history
yarn.lock 44 ●●●● patch | view | raw | blame | history
package.json
@@ -40,15 +40,15 @@
    "@antv/data-set": "^0.8.3",
    "@antv/g2": "^3.0.1",
    "@antv/g2-plugin-slider": "^2.0.0",
    "@delon/abc": "^0.6.0-rc.2",
    "@delon/acl": "^0.6.0-rc.2",
    "@delon/auth": "^0.6.0-rc.2",
    "@delon/theme": "^0.6.0-rc.2",
    "@delon/mock": "^0.6.0-rc.2",
    "@delon/cache": "^0.6.0-rc.2",
    "@delon/abc": "0.6.1",
    "@delon/acl": "0.6.1",
    "@delon/auth": "0.6.1",
    "@delon/theme": "0.6.1",
    "@delon/mock": "0.6.1",
    "@delon/cache": "0.6.1",
    "@ngx-translate/core": "^9.0.0",
    "@ngx-translate/http-loader": "^2.0.0",
    "angular-baidu-maps": "^1.0.1",
    "angular2-baidu-map": "^4.1.0",
    "angular-qq-maps": "^1.0.1",
    "angular-split": "^1.0.0-rc.0",
    "angular-tree-component": "^7.0.1",
src/app/business/entity/data.ts
@@ -11,7 +11,7 @@
export interface Sensor {
    description?: any|Column;
    id?: any|Column;
    key?: any|Column;
    sensorKey?: any|Column;
    lower?: any|Column;
    name?: any|Column;
    unit?: any|Column;
@@ -85,6 +85,24 @@
  increment: number []|any[];
  degression: number []|any [];
}
export interface Device {
  address?: any|Column;
  createTime?: any|Column;
  deviceVersion?: any|Column;
  deviceVersionId?: any|Column;
  id?: any|Column;
  installTime?: any|Column;
  isDelete?: any|Column;
  latitude?: any|Column;
  longitude?: any|Column;
  mac?: any|Column;
  monitorPoint?: any|Column;
  monitorPointId?: any|Column;
  name?: any|Column;
  operateUser?: any|Column;
  operateUserId?: any|Column;
  state?: any|Column;
}
export interface AlarmMode {
  enable: boolean|any[];
@@ -92,3 +110,18 @@
  level2: AlarmStyle[]|any[];
  level3: AlarmStyle[]|any[];
}
export interface DeviceAdjustValue {
  createTime?: number|any[];
  deviceId?: number|any[];
  id?: number|any[];
  updateTime?: number|any[];
  value?:{[s:string] : number}|any[];
}
export interface CoorPicker{
  longitude:number;//  经度
  latitude:number;// 纬度
  address:string;
  describe:string;
  name:string;
}
src/app/business/services/http/alarm-config.service.ts
@@ -9,12 +9,12 @@
export class AlarmConfigService {
  private urls = {
    getByOid: environment.SERVER_BASH_URL + 'alarm-config/get-by-oid',
    save: environment.SERVER_BASH_URL + '/alarm-config/add-or-modify',
    save: environment.SERVER_BASH_URL + 'alarm-config/add-or-modify',
  };
  constructor( private http: _HttpClient) {
     
  }
  public generateAlarmConfig(sensors: {key:string} [],alarmConfig?: AlarmConfig): AlarmConfig{
  public generateAlarmConfig(sensors: {sensorKey:string} [],alarmConfig?: AlarmConfig): AlarmConfig{
        const _alarmConfig : AlarmConfig = alarmConfig==null || alarmConfig.value == null ? {value:{
            alarmLevels:null,
            alarmMode:null
@@ -23,7 +23,7 @@
        alarmLevels = alarmLevels ==null ?{} :alarmLevels;
        sensors.forEach(
          sensor => {
                const key = sensor.key;
                const key = sensor.sensorKey;
                alarmLevels[key]  = 
                alarmLevels[key] == null ?
                {
src/app/business/services/http/device-adjust-value.service.ts
New file
@@ -0,0 +1,25 @@
import { environment } from 'environments/environment';
import { _HttpClient } from '@delon/theme';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { ResultBean } from '@business/entity/grid';
import { AlarmConfig, DeviceAdjustValue } from '@business/entity/data';
@Injectable()
export class DeviceAdjustValueService {
  private urls = {
    getByDid: environment.SERVER_BASH_URL + 'device-adjust/get-by-did',
    save: environment.SERVER_BASH_URL + 'device-adjust/add-or-modify',
  };
  constructor(private http:_HttpClient) { }
  /**
   *
   * @param did 设备ID
   */
  public getByDid(did:number):Observable<ResultBean<DeviceAdjustValue>>{
    return this.http.get(this.urls.getByDid,{deviceId:did});
  }
  public save(data:DeviceAdjustValue): Observable<any> {
    return this.http.post(this.urls.save, data);
  }
}
src/app/business/services/http/device.service.ts
New file
@@ -0,0 +1,34 @@
import { _HttpClient } from '@delon/theme';
import { environment } from 'environments/environment';
import { Injectable } from '@angular/core';
import { ResultBean } from '@business/entity/grid';
import { Observable } from 'rxjs/Observable';
import { ExampleService } from '@business/services/util/example.service';
import { Device } from '@business/entity/data';
@Injectable()
export class DeviceService {
  private urls = {
    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'
  };
  public getListUrl (){
    return this.urls.list;
  }
  public getSqlParams(queryText:string){
    const example = new ExampleService();
    if (queryText != null && queryText !== '') {
      example.or().andLike({name: 'name', value: '%' + queryText + '%'});
      example.or().andLike({name: 'mac', value: '%' + queryText + '%'});
    }
    return example.getSqlParam();
  }
  constructor(private http: _HttpClient) { }
  delete(...ids: number[]): Observable< ResultBean<any> > {
      return this.http.post(this.urls.delete, ids);
  }
  public save(data:Device): Observable<any> {
    return this.http.post(this.urls.save, data);
  }
}
src/app/business/services/http/monitor-point.service.ts
@@ -1,4 +1,4 @@
import { PageBean } from '@business/entity/grid';
import { PageBean, ResultBean } from '@business/entity/grid';
import { ExampleService } from '@business/services/util/example.service';
import { _HttpClient } from '@delon/theme';
import { environment } from 'environments/environment';
@@ -6,14 +6,16 @@
import { Injectable } from '@angular/core';
import { equal } from 'assert';
import { Observable } from 'rxjs/Observable';
import { MonitorPoint } from '@business/entity/data';
@Injectable()
export class MonitorPointService {
  private urls = {
    edit: environment.SERVER_BASH_URL + '/monitor-point/page-list',
    list: environment.SERVER_BASH_URL + '/monitor-point/page-list',
    save: environment.SERVER_BASH_URL + '/monitor-point/add-or-modify',
    delete: environment.SERVER_BASH_URL + '/monitor-point/delete-by-ids'
    delete: environment.SERVER_BASH_URL + '/monitor-point/delete-by-ids',
    getOne:environment.SERVER_BASH_URL + '/monitor-point/get-by-id'
};
constructor(private http: _HttpClient) { }
 public getPagingList(page: PageBean, queryText: string): Observable<PageBean> {
@@ -21,9 +23,13 @@
  if (queryText != null && queryText !== '') {
    example.or().andLike({name: 'name', value: '%' + queryText + '%'});
  }
  let orderByClause = '';
  if ( page.getOrderByClause != null && page.getOrderByClause instanceof Function) {
    orderByClause = page.getOrderByClause();
  }
  const param: PageBean = {pageSize: page.pageSize, pageIndex: page.pageIndex, 
      queryParams: example.getSqlParam(), orderByClause: page.getOrderByClause()};
      return this.http.get(this.urls.edit, param);
      queryParams: example.getSqlParam(), orderByClause: orderByClause};
      return this.http.get(this.urls.list, param);
}
public save(data: any): Observable<any> {
      return this.http.post(this.urls.save, data);
@@ -31,5 +37,7 @@
public delete(...ids: number[]): Observable<any> {             
      return this.http.post(this.urls.delete, ids);
}
public getEntity(id:number):Observable<ResultBean<MonitorPoint>>{
      return this.http.get(this.urls.getOne,{id:id});
}
}
src/app/business/services/http/operate-user.service.ts
New file
@@ -0,0 +1,32 @@
import { PageBean } from '@business/entity/grid';
import { ExampleService } from '@business/services/util/example.service';
import { _HttpClient } from '@delon/theme';
import { environment } from 'environments/environment';
import { RouteConfigLoadStart } from '@angular/router';
import { Injectable } from '@angular/core';
import { equal } from 'assert';
import { Observable } from 'rxjs/Observable';
@Injectable()
export class OperateUserService {
  private urls = {
    list: environment.SERVER_BASH_URL + 'operateUser/page-list'
};
constructor(private http: _HttpClient) { }
 public getPagingList(page: PageBean, queryText: string): Observable<PageBean> {
  const example = new ExampleService();
  if (queryText != null && queryText !== '') {
    example.or().andLike({name: 'name', value: '%' + queryText + '%'});
    example.or().andLike({name: 'jobNumber', value: '%' + queryText + '%'});
  }
  let orderByClause = '';
  if ( page.getOrderByClause != null && page.getOrderByClause instanceof Function) {
    orderByClause = page.getOrderByClause();
  }
  const param: PageBean = {pageSize: page.pageSize, pageIndex: page.pageIndex,
      queryParams: example.getSqlParam(), orderByClause: orderByClause};
      return this.http.get(this.urls.list, param);
}
}
src/app/business/services/http/organization.service.ts
@@ -16,7 +16,7 @@
  data: Organization;
  title: '组织列表'|'组织配置' = '组织列表';
  private urls = {
      edit: environment.SERVER_BASH_URL + '/organization/page-list',
      list: environment.SERVER_BASH_URL + '/organization/page-list',
      save: environment.SERVER_BASH_URL + '/organization/add-or-modify',
      delete: environment.SERVER_BASH_URL + '/organization/delete-by-ids'
  };
@@ -32,7 +32,7 @@
    }
    const param: PageBean = {pageSize: page.pageSize, pageIndex: page.pageIndex, 
        queryParams: example.getSqlParam(), orderByClause: orderByClause};
        return this.http.get(this.urls.edit, param);
        return this.http.get(this.urls.list, param);
  }
  public save(data: any): Observable<any> {
        return this.http.post(this.urls.save, data);
src/app/business/services/http/version.service.ts
@@ -11,7 +11,7 @@
@Injectable()
export class VersionService {
  private urls = {
      edit: environment.SERVER_BASH_URL + '/device-version/page-list',
      list: environment.SERVER_BASH_URL + '/device-version/page-list',
      save: environment.SERVER_BASH_URL + '/device-version/add-or-modify',
      delete: environment.SERVER_BASH_URL + '/device-version/delete-by-ids',
      getSensorIds: environment.SERVER_BASH_URL + '/device-version/get-sensor-ids',
@@ -24,9 +24,13 @@
      example.or().andLike({name: 'name', value: '%' + queryText + '%'});
      example.or().andEqualTo({name: 'version', value: queryText});
    }
    let orderByClause = '';
    if ( page.getOrderByClause != null && page.getOrderByClause instanceof Function) {
      orderByClause = page.getOrderByClause();
    }
    const param: PageBean = {pageSize: page.pageSize, pageIndex: page.pageIndex, 
      queryParams: example.getSqlParam(), orderByClause: page.getOrderByClause()};
    return this.http.get(this.urls.edit, param);
      queryParams: example.getSqlParam(), orderByClause:orderByClause};
    return this.http.get(this.urls.list, param);
  }
  public save(data: any): Observable<any> {
        return this.http.post(this.urls.save, data);
src/app/business/services/util/tools.service.ts
@@ -1,6 +1,18 @@
import { FormGroup, FormArray, AbstractControl } from '@angular/forms';
import { Injectable } from '@angular/core';
@Injectable()
export class ToolsService {
      public static markAsDirty(controlSet:FormGroup|FormArray){
         const controls = controlSet.controls;
         Object.values(controls).forEach(
             (control:AbstractControl) => {
                    if(control instanceof FormGroup || control instanceof FormArray){
                        ToolsService.markAsDirty(control);
                    }else{
                          control.markAsDirty();
                    }
             }
         )
      }
}
src/app/routes/dashboard/monitor/monitor.component.ts
@@ -26,8 +26,8 @@
            this.http.get('/chart/tags')
        ).subscribe(([ res, tags ]) => {
            this.data = res;
            tags.list[Math.floor(Math.random() * tags.list.length) + 1].value = 1000;
            this.tags = tags.list;
            tags['list'][Math.floor(Math.random() *  tags['list'].length) + 1].value = 1000;
            this.tags =  tags['list'];
            this.loading = false;
        });
src/app/routes/dashboard/workplace/workplace.component.ts
@@ -84,9 +84,9 @@
            this.http.get('/api/notice'),
            this.http.get('/api/activities')
        ).subscribe(([ chart, notice, activities ]) => {
            this.radarData = chart.radarData;
            this.notice = notice;
            this.activities = activities.map((item: any) => {
            this.radarData = chart['radarData'];
            this.notice = <any []>notice;
            this.activities = (<any []>activities).map((item: any) => {
                item.template = item.template.split(/@\{([^{}]*)\}/gi).map((key: string) => {
                    if (item[key]) return `<a>${item[key].name}</a>`;
                    return key;
src/app/routes/devices/basic-info/adjust-config/adjust-config.component.html
New file
@@ -0,0 +1,45 @@
<div class="modal-header">
    <div class="modal-title">配置传感器</div>
  </div>
  <nz-table #nzTable [nzDataSource]="grid.data"  [nzPageSize]="8"
    [nzLoading]="grid.loading" [nzShowTotal]="true">
    <thead nz-thead>
      <tr>
        <th nz-th style="width:45px;">
            <label>序号</label>
        </th>
        <th nz-th *ngFor="let col of grid.columns" [ngStyle]="{'width':col.width,'text-align':col['align'] === undefined?'left':col.align}">
          <span>{{ col.text }}</span>
          <nz-table-sort *ngIf="col.isSort" [(nzValue)]="col.sort" (nzValueChange)="sort(col.name,$event)"></nz-table-sort>
        </th>
        <th nz-th>
             <span>校准值</span>
        </th>
      </tr>
    </thead>
    <tbody nz-tbody>
      <tr nz-tbody-tr *ngFor="let row of nzTable.data,index as i">
        <td nz-td  [ngClass]="{'bg-grey-1':true}" style="text-align:center">
            {{ i }}
        </td>
        <td nz-td *ngFor="let col of grid.columns" [ngStyle]="{'width':col.width,'text-align':col['align'] === undefined?'left':col.align}">
          <span [ngSwitch]="col.type">
            <!-- 要使用管道,无法自动生成 -->
            <span *ngSwitchDefault> {{ row[col.name]|tyepHandle:col:row }} </span>
            <!-- 要使用管道,无法自动生成 -->
          </span>
        </td>
         <td>
             <nz-input-number [(ngModel)]="data.value[row.sensorKey]" [nzStep]="0.1"></nz-input-number>
         </td>
      </tr>
    </tbody>
  </nz-table>
  <div class="modal-footer">
    <button nz-button type="button" (click)="close()">关闭</button>
    <button nz-button [nzType]="'primary'" (click)="save($event)" [nzLoading]="isSaving">
           <span >
              保存<span *ngIf="isSaving" >中</span>
           </span>
    </button>
  </div>
src/app/routes/devices/basic-info/adjust-config/adjust-config.component.ts
New file
@@ -0,0 +1,120 @@
import { zip } from 'rxjs/observable/zip';
import { DeviceAdjustValueService } from '@business/services/http/device-adjust-value.service';
import { NzModalSubject, NzMessageService } from 'ng-zorro-antd';
import { SensorsService } from '@business/services/http/sensors.service';
import { Component, OnInit } from '@angular/core';
import { DeviceAdjustValue, Sensor, Device } from '@business/entity/data';
import { Grid, PageBean, ResultBean } from '@business/entity/grid';
@Component({
  selector: 'app-adjust-config',
  templateUrl: './adjust-config.component.html',
  styles: []
})
export class AdjustConfigComponent implements OnInit {
  record:Device;
  _dataValue:{[s:string]:number} = {};
  data:DeviceAdjustValue;
  deviceVersionId: number;
  isSaving = false;
  grid: Grid<Sensor> = new Grid(null);
  private initPage() {
    const sensor: Sensor = {
      name: {
        text: '名称',
        width: '200px'
      },
      sensorKey: {
        text: '键值',
        width: '60px'
      },
      lower: {
        text: '下限值',
        width: '90px'
      },
      upper: {
        text: '上限值',
        width: '90px'
      },
      unit: {
        text: '单位',
        width: '100px'
      },
      description: {
        text: '描述'
      }
    };
    this.grid.title = '传感器';
    this.grid.setColumns(sensor);
    this.grid.pageSize = 0;
  }
  constructor(
    private subject: NzModalSubject,
    private sensorsService: SensorsService,
    private adjustValueService:DeviceAdjustValueService,
    public msgSrv: NzMessageService,
  ) { }
  ngOnInit() {
    this.initPage();
    this.load();
  }
  load() {
    // 延时加载避免ExpressionChangedAfterItHasBeenCheckedError
    setTimeout(() => {
      this.grid.loading = true;
    }, 1);
    zip(
      this.adjustValueService.getByDid(this.record.id),
      this.sensorsService.getPagingList(this.grid, null)
    ).subscribe(
        ([adjustRes,sensorsRes]) => {
            if(adjustRes!=null && adjustRes.code==1 && sensorsRes != null && sensorsRes.data != null){
               this.data = adjustRes.data;
               if(this.data == null||this.data.deviceId== null){
                  this.data = {};
                  this.data.value = {};
                  this.data['deviceId'] = this.record.id;
               }
              // 存储修改前到值
              Object.assign(this._dataValue,this.data.value);
               this.grid.initData(sensorsRes);
               sensorsRes.data.forEach(
                (item:Sensor) => {
                  this.data.value[item.sensorKey] = this.data.value[item.sensorKey] == null?0:this.data.value[item.sensorKey];
                  }
              );
              this.grid.refreshStatus();
              setTimeout(() => {
                this.grid.loading = false;
              }, 1);
            }
        }
    );
  }
  close() {
    this.subject.destroy();
  }
  save($event) {
    // $event.preventDefault();
    let isModify = Object.keys(this.data.value).some(
        key => {
            return this.data.value[key] !== this._dataValue[key];
        }
    );
    debugger;
    if(isModify){
      this.adjustValueService.save(this.data).subscribe(
        (res:ResultBean<any>) =>{
               if(res!=null&&res.code==1){
                   this.subject.destroy();
                   this.msgSrv.success('校准值配置成功');
               }
        }
    );
    }else{
        this.subject.destroy();
        this.msgSrv.success('校准值配置未改变');
    }
  }
}
src/app/routes/devices/basic-info/basic-info.component.html
@@ -1,3 +1,27 @@
<p>
  device basic-info works!
</p>
<div class="content__title">
    <h1>
        设备列表
        <small>包含设备的查询、编辑、删除、配置等功能</small>
    </h1>
</div>
<nz-card [nzBordered]="false">
        <div class="mb-md">
                <button nz-button (click)="addOrModify()" [nzType]="'primary'" [nzSize]="'large'">
                    <i class="anticon anticon-plus"></i><span>新建</span>
                </button>
                <ng-container *ngIf="selectedRows.length > 0"> &nbsp;
                <button nz-button [nzSize]="'large'" (click)="deleteSelected()">批量删除</button>
                </ng-container>
                <nz-input [ngStyle]="{'width': '280px','float':'right'}" [(ngModel)]="queryText" name=""  [nzPlaceHolder]="'请输入名称或mac'"
                (keyup)="queryTextChanged($event)" (change)="queryTextChanged($event)" ></nz-input>
        </div>
        <div class="mb-md">
                <nz-alert *ngIf="selectedRows.length > 0" [nzType]="'info'" [nzShowIcon]="true">
                    <span alert-body>
                         已选择<strong class="text-primary">{{selectedRows.length}}</strong>项
                    </span>
                </nz-alert>
         </div>
<simple-table #simpleTable  [data]="listUrl" [extraParams]="extraParams"  [columns]="columns" [showTotal]="true"
[reqReName]="{pi: 'pageIndex',ps: 'pageSize'}"  (checkboxChange)="checkboxChange($event)" [ps]="10" [resReName]="{list: 'data',total: 'total'}"></simple-table>
</nz-card>
src/app/routes/devices/basic-info/basic-info.component.ts
@@ -1,4 +1,16 @@
import { Component, OnInit } from '@angular/core';
import { MonitorPointService } from '@business/services/http/monitor-point.service';
import { CoorPicker, Device } from '@business/entity/data';
import { AdjustConfigComponent } from './adjust-config/adjust-config.component';
import { DeviceEditComponent } from './device-edit/device-edit.component';
import { ModalHelper } from '@delon/theme';
import { NzModalService, NzMessageService } from 'ng-zorro-antd';
import { PageBean, ResultBean } from '@business/entity/grid';
import { DeviceService } from '@business/services/http/device.service';
import { Component, OnInit, ElementRef, ViewChild } from '@angular/core';
import { SimpleTableColumn } from '@delon/abc';
import { Subject } from 'rxjs/Subject';
import { CoordinatesPickerComponent } from 'app/routes/map/coordinates-picker/coordinates-picker.component';
import { CoorPickerService } from 'app/routes/map/coordinates-picker/coordinates-picker.service';
@Component({
  selector: 'app-basic-info',
@@ -6,10 +18,178 @@
  styles: []
})
export class BasicInfoComponent implements OnInit {
  constructor() { }
  columns: SimpleTableColumn[] = [
    { title: '编号', index: 'id', type: 'checkbox' },
    { title: '名称', index: 'name' },
    { title: 'mac', index: 'mac' },
    { title: '型号', index: 'deviceVersion.name' },
    { title: '监控点', index: 'monitorPoint.name' },
    { title: '维护人', index: 'operateUser.name' },
    { title: '生产时间',width: '100px', type: 'date', index: 'createTime' },
    { title: '安装时间', width: '100px',type: 'date', index: 'installTime' },
    {
      title: '操作区',
      buttons: [
        {
          text: '编辑',
          type: 'none',
          click: (record: any) => this.addOrModify(record)
        },
        {
          text: '删除',
          type: 'del',
          click: (record: any) => this.delete(record.id)
        },
        {
            text: '更多',
            children: [
                {
                    text: `配置校准值`,
                    type: 'static',
                    component:AdjustConfigComponent,
                    format: (record: any) => `<i class="anticon anticon-setting"></i>配置校准值`
                },
                {
                  text: `配置坐标`,
                  type: 'none',
                  click: (record: any) => this.configCoord(record),
                  format: (record: any) => `<i class="anticon anticon-environment-o"></i>配置坐标`
              }
            ]
        }
      ]
    }
  ];
  queryTextStream: Subject<string> = new Subject<string>();
  constructor(
    private monitorPointService:MonitorPointService,
    private deviceService: DeviceService,
    private confirmServ: NzModalService,
    public msgSrv: NzMessageService,
    private modalHelper: ModalHelper,
    private coorPickerService:CoorPickerService
  ) { }
  ngOnInit() {
    this.queryTextStream
      .debounceTime(900)
      .distinctUntilChanged()
      .subscribe(value => {
        this.extraParams.queryParams = this.deviceService.getSqlParams(value);
        this.load();
      });
  }
  get listUrl() {
    return this.deviceService.getListUrl();;
  }
  extraParams = { queryParams: null };
  queryText: string;
  selectedRows: any[] = [];
  checkboxChange(list: any[]) {
    this.selectedRows = list;
  }
  deleteSelected() {
    this.confirmServ.confirm({
      title: '批量删除',
      content: '注意:数据一旦删除,将不可恢复!',
      okText: '确定',
      cancelText: '取消'
    }).on('onOk', () => {
      if (this.selectedRows != null && this.selectedRows.length > 0) {
        const ids = this.selectedRows.map(
          (row: any) => {
            return Number.parseInt(row.id);
          }
        );
        this.delete(...ids);
      }
    });
  }
  load() {
    this.selectedRows = [];
    this.simpleTable.load();
  }
  delete(...id: number[]) {
    this.deviceService.delete(...id).subscribe(
      (res: any) => {
        if (res.code === 1) {
          this.load();
          this.msgSrv.success('删除成功!');
        }
      }
    );
  }
  @ViewChild('simpleTable') simpleTable: { load: Function };
  queryTextChanged(event) {
    this.queryTextStream.next(this.queryText);
  }
  addOrModify(d) {
    const data = {};
    if (d != null) {
      Object.assign(data, d);
    }
    this.modalHelper.static(DeviceEditComponent, { data }).subscribe(
      (ret: { data: any, close: Function }) => {
        // 修改状态
        if (ret.data['id'] != null) {
          const origData = d;
          const isModified = Object.keys(ret.data).some(
            (key: string) => {
              return ret.data[key] !== origData[key];
            }
          );
          // 未作修改
          if (!isModified) {
            ret.close();
            this.msgSrv.success('数据未作任何修改!');
            return;
          }
        }
        this.deviceService.save(ret.data).subscribe(
          (res: any) => {
            if (res.code === 1) {
              this.load();
              ret.close();
              this.msgSrv.success('数据保存成功!');
            }
          }
        );
      });
  }
  configCoord(record:Device):void {
    Object.assign(this.coorPickerService.data,record);
    let _data = this.coorPickerService.data;
    this.monitorPointService.getEntity(record.monitorPointId).subscribe(
         res => {
            if(res!=null && res.code==1 && res.data!=null){
                const areaNames = res.data.areaNames;
                let adress = null;
                if(areaNames != null){
                  adress = areaNames.provinceName+areaNames.cityName+areaNames.areaName+res.data.address;
                }
                this.coorPickerService.data.address = adress;
                this.coorPickerService.data['describe'] = '设备名称';
            }
            this.modalHelper.static(CoordinatesPickerComponent).subscribe(
              (staticComp) => {
                     const data:Device = {
                        id:record.id,
                        longitude:_data.longitude,
                        latitude:_data.latitude,
                     }
                     this.deviceService.save(data).subscribe(
                      (res: any) => {
                        if (res.code === 1) {
                          this.load();
                          this.msgSrv.success('坐标配置成功!');
                        }
                      }
                     );
              }
           );
         }
    )
  }
}
src/app/routes/devices/basic-info/device-edit/device-edit.component.html
New file
@@ -0,0 +1,105 @@
  <div class="modal-header">
    <div class="modal-title">{{ data.id != null ? '编辑' : '添加'}} - 设备</div>
  </div>
  <form [formGroup]="validateForm" (ngSubmit)="save($event,validateForm.value,validateForm.valid)" nz-form [nzType]="'horizontal'">
      <div nz-form-item nz-row class="mb-sm">
          <div nz-form-label nz-col [nzSm]="4" [nzXs]="24">
            <label nz-form-item-required>名称</label>
          </div>
          <div nz-form-control nz-col [nzSpan]="7" nzHasFeedback>
            <nz-input formControlName="name" maxlength="20" [nzPlaceHolder]="'设备名称'">
            </nz-input>
          </div>
          <div nz-form-label nz-col [nzSm]="4" [nzXs]="24">
            <label>mac</label>
          </div>
          <div nz-form-control nz-col [nzSpan]="7" nzHasFeedback>
                <nz-input formControlName="mac" maxlength="20" [nzPlaceHolder]="'mac地址'">
                </nz-input>
          </div>
        </div>
        <div nz-form-item nz-row class="mb-sm">
            <div nz-form-label nz-col [nzSm]="4" [nzXs]="24">
              <label>经度</label>
            </div>
            <div nz-form-control nz-col [nzSpan]="7" nzHasFeedback>
              <nz-input-number [ngStyle]="{'width': '100%' }" formControlName="longitude"  [nzMin]="-180" [nzMax]="180" [nzStep]="0.000001"
              [nzPlaceHolder]="'-180~180之间'">
              </nz-input-number>
            </div>
            <div nz-form-label nz-col [nzSm]="4" [nzXs]="24">
              <label>纬度</label>
            </div>
            <div nz-form-control nz-col [nzSpan]="6" nzHasFeedback>
              <nz-input-number [ngStyle]="{'width': '100%' }" formControlName="latitude" [nzMin]="-90" [nzMax]="90" [nzStep]="0.000001"
              [nzPlaceHolder]="'-90~90之间'">
              </nz-input-number>
            </div>
          </div>
          <div nz-form-item  nz-row class="mb-sm">
              <div nz-form-label nz-col [nzSm]="4" [nzXs]="24">
                <label>设备型号</label>
              </div>
              <div nz-form-control nz-col [nzSpan]="7" nzHasFeedback>
                  <nz-select formControlName="deviceVersionId" [nzPlaceHolder]="'选择 设备(输入名称搜索)'"
                  nzAllowClear [nzFilter]="false" nzShowSearch (nzSearchChange)="deviceVersionChange($event)" [nzNotFoundContent]="'无法找到'" >
                    <nz-option *ngFor="let option of deviceVersions" [nzLabel]="option.name" [nzValue]="option.id" [nzDisabled]="option.disabled">
                    </nz-option>
                  </nz-select>
              </div>
              <div nz-form-label nz-col [nzSm]="4" [nzXs]="24">
                <label>维护人</label>
              </div>
              <div nz-form-control nz-col [nzSpan]="7" nzHasFeedback>
                  <nz-select formControlName="operateUserId" [nzPlaceHolder]="'选择 维护人(输入名称搜索)'"
                  nzAllowClear [nzFilter]="false" nzShowSearch (nzSearchChange)="operateUserChange($event)" [nzNotFoundContent]="'无法找到'" >
                    <nz-option *ngFor="let option of operateUsers" [nzLabel]="option.name" [nzValue]="option.id" [nzDisabled]="option.disabled">
                    </nz-option>
                  </nz-select>
              </div>
          </div>
          <div nz-form-item  nz-row class="mb-sm">
            <div nz-form-label nz-col [nzSm]="4" [nzXs]="24">
              <label>监控点</label>
            </div>
            <div nz-form-control nz-col [nzSpan]="7" nzHasFeedback>
                <nz-select formControlName="monitorPointId" [nzPlaceHolder]="'选择 监控点(输入名称搜索)'"
                nzAllowClear [nzFilter]="false" nzShowSearch (nzSearchChange)="monitorPointChange($event)" [nzNotFoundContent]="'无法找到'" >
                  <nz-option *ngFor="let option of monitorPoints" [nzLabel]="option.name" [nzValue]="option.id" [nzDisabled]="option.disabled">
                  </nz-option>
                </nz-select>
            </div>
            <div nz-form-label nz-col [nzSm]="4" [nzXs]="24">
              <label>具体地址</label>
            </div>
            <div nz-form-control nz-col [nzSpan]="7" nzHasFeedback>
                <nz-input formControlName="address" maxlength="20" [nzPlaceHolder]="'设备安装的具体地址'">
                </nz-input>
            </div>
          </div>
          <div nz-form-item  nz-row class="mb-sm">
              <div nz-form-label nz-col [nzSm]="4" [nzXs]="24">
                <label>生产时间</label>
              </div>
              <div nz-form-control nz-col [nzSpan]="7" nzHasFeedback>
                  <nz-datepicker nzSize="large"  style="width: 100%;" formControlName="createTime" nzShowTime  [nzPlaceHolder]="'选择时间'"
                  [nzFormat]="'YYYY-MM-DD HH:mm:ss'" ></nz-datepicker>
              </div>
              <div nz-form-label nz-col [nzSm]="4" [nzXs]="24">
                <label>安装时间</label>
              </div>
              <div nz-form-control nz-col [nzSpan]="7" nzHasFeedback>
                  <nz-datepicker nzSize="large"  style="width: 100%;" formControlName="installTime" nzShowTime  [nzPlaceHolder]="'选择时间'"
                  [nzFormat]="'YYYY-MM-DD HH:mm:ss'" ></nz-datepicker>
              </div>
            </div>
    <div class="modal-footer">
        <button nz-button type="button" (click)="close()">关闭</button>
        <button nz-button [nzType]="'primary'" [nzLoading]="isSaving">
          <span>
            保存
            <span *ngIf="isSaving">中</span>
          </span>
        </button>
    </div>
  </form>
src/app/routes/devices/basic-info/device-edit/device-edit.component.ts
New file
@@ -0,0 +1,133 @@
import { ToolsService } from '@business/services/util/tools.service';
import { OperateUserService } from '@business/services/http/operate-user.service';
import { VersionService } from '@business/services/http/version.service';
import { MonitorPointService } from '@business/services/http/monitor-point.service';
import { NzModalSubject } from 'ng-zorro-antd';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { DeviceService } from '@business/services/http/device.service';
import { Component, OnInit } from '@angular/core';
import { Device} from '@business/entity/data';
import { _Validators } from '@delon/abc';
import { PageBean } from '@business/entity/grid';
@Component({
  selector: 'app-device-edit',
  templateUrl: './device-edit.component.html',
  styles: []
})
export class DeviceEditComponent implements OnInit {
  private monitorPoints:any [] = [];
  private deviceVersions:any [] = [];
  private operateUsers:any [] = [];
  private isSaving = false;
  constructor(
    private subject: NzModalSubject,
    private formBuilder: FormBuilder,
    private monitorPointService:MonitorPointService,
    private versionService:VersionService,
    private operateUserService:OperateUserService
  ) { }
  data:Device;
  validateForm:FormGroup;
  ngOnInit() {
    const data = this.data;
    this.monitorPointChange(null);
    this.deviceVersionChange(null);
    this.operateUserChange(null);
    if (this.data.createTime == null) {
        this.data.createTime = new Date().getTime();
    }
    const validates:Device = {
         name:[data.name,[Validators.required]],
         mac:[data.mac],
         deviceVersionId:[data.deviceVersionId],
         monitorPointId:[data.monitorPointId],
         operateUserId:[data.operateUserId],
         address:[data.address],
         id:[data.id],
         longitude:[data.longitude],
         latitude:[data.latitude],
         createTime:[data.createTime],
         installTime:[data.installTime]
    };
    this.validateForm = this.formBuilder.group(
      validates
    );
  }
  close(){
     this.subject.destroy();
   }
   save($event, value, valid){
    $event.preventDefault();
    if(valid){
      this.isSaving = true;
      this.data = value;
      this.subject.next( this );
    }else{
        ToolsService.markAsDirty(this.validateForm);
    }
   }
   monitorPointChange(text){
    const pageBean: PageBean = {pageIndex: 0, pageSize: 20};
    this.monitorPointService.getPagingList(pageBean, text).subscribe(
      (res: PageBean) => {
           if (res != null && res.data != null) {
               this.monitorPoints = res.data;
           }
           const monitorPoint = this.data.monitorPoint;
           if (monitorPoint != null && text == null) {
               const hasSelectedValue = this.monitorPoints.some(
                   (item: any) => {
                      return item.id === monitorPoint.id;
                   }
               );
               if ( hasSelectedValue ) {
                  this.monitorPoints.push(monitorPoint);
               }
           }
      }
   );
   }
   deviceVersionChange(text){
    const pageBean: PageBean = {pageIndex: 0, pageSize: 20};
    this.versionService.getPagingList(pageBean, text).subscribe(
      (res: PageBean) => {
           if (res != null && res.data != null) {
               this.deviceVersions = res.data;
           }
           const deviceVersion = this.data.deviceVersion;
           if (deviceVersion != null && text == null) {
               const hasSelectedValue = this.deviceVersions.some(
                   (item: any) => {
                      return item.id === deviceVersion.id;
                   }
               );
               if ( hasSelectedValue ) {
                  this.monitorPoints.push(deviceVersion);
               }
           }
      }
   );
   }
   operateUserChange(text){
    const pageBean: PageBean = {pageIndex: 0, pageSize: 20};
    this.operateUserService.getPagingList(pageBean, text).subscribe(
      (res: PageBean) => {
           if (res != null && res.data != null) {
               this.operateUsers = res.data;
           }
           const operateUser = this.data.operateUser;
           if (operateUser != null && text == null) {
               const hasSelectedValue = this.operateUsers.some(
                   (item: any) => {
                      return item.id === operateUser.id;
                   }
               );
               if ( hasSelectedValue ) {
                  this.monitorPoints.push(operateUser);
               }
           }
      }
   );
   }
}
src/app/routes/devices/devices.module.ts
@@ -1,3 +1,5 @@
import { DeviceAdjustValueService } from '@business/services/http/device-adjust-value.service';
import { ToolsService } from '@business/services/util/tools.service';
import { SensorsService } from '@business/services/http/sensors.service';
import { OrganizationService } from '@business/services/http/organization.service';
import { MonitorPointService } from '@business/services/http/monitor-point.service';
@@ -17,8 +19,14 @@
import { VersionEditComponent } from './version/version-edit/version-edit.component';
import { MonitorPointEditComponent } from './monitor-point/monitor-point-edit/monitor-point-edit.component';
import { VersionSensorConfigComponent } from './version/version-sensor-config/version-sensor-config.component';
const COMPONENTS_NOROUNT = [  VersionEditComponent, MonitorPointEditComponent, VersionSensorConfigComponent  ];
import { DeviceService } from '@business/services/http/device.service';
import { DeviceEditComponent } from './basic-info/device-edit/device-edit.component';
import { OperateUserService } from '@business/services/http/operate-user.service';
import { AdjustConfigComponent } from './basic-info/adjust-config/adjust-config.component';
import { CoordinatesPickerComponent } from 'app/routes/map/coordinates-picker/coordinates-picker.component';
import { MapModule } from 'app/routes/map/map.module';
import { CoorPickerService } from 'app/routes/map/coordinates-picker/coordinates-picker.service';
const COMPONENTS_NOROUNT = [AdjustConfigComponent,DeviceEditComponent,VersionEditComponent, MonitorPointEditComponent, VersionSensorConfigComponent  ];
const routes: Routes = [
  {
@@ -37,6 +45,7 @@
    PipeModule,
    CommonModule,
    SharedModule,
    MapModule,
    RouterModule.forChild(routes)
  ],
  declarations: [
@@ -45,9 +54,9 @@
    MonitorPointComponent,
    ...COMPONENTS_NOROUNT     
  ],
  providers: [OrganizationService, VersionService,
  providers: [CoorPickerService,DeviceAdjustValueService,OrganizationService, VersionService,
    SensorsService, AreacodeService, MonitorPointService,
    _HttpClient, FormBuilder],
  entryComponents: COMPONENTS_NOROUNT
    _HttpClient, FormBuilder,DeviceService,OperateUserService,ToolsService],
  entryComponents: [CoordinatesPickerComponent,...COMPONENTS_NOROUNT]
})
export class DevicesModule { }
src/app/routes/devices/monitor-point/monitor-point-edit/monitor-point-edit.component.html
@@ -15,8 +15,7 @@
    </div>
    <div nz-form-control nz-col [nzSpan]="6" nzHasFeedback>
      <nz-select formControlName="organizationId" [nzPlaceHolder]="'选择 组织(输入名称搜索)'"
        nzAllowClear [nzFilter]="false" nzShowSearch
              formControlName="organizationId" (nzSearchChange)="OrgSelectChange($event)" [nzNotFoundContent]="'无法找到'" >
        nzAllowClear [nzFilter]="false" nzShowSearch  (nzSearchChange)="OrgSelectChange($event)" [nzNotFoundContent]="'无法找到'" >
        <nz-option *ngFor="let option of orgOptions" [nzLabel]="option.name" [nzValue]="option.id" [nzDisabled]="option.disabled">
        </nz-option>
      </nz-select>
src/app/routes/devices/monitor-point/monitor-point.component.html
@@ -57,6 +57,8 @@
                              <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)="configCoord(row)">配置坐标</a>
                     </td>
                </tr>
              </tbody>
src/app/routes/devices/monitor-point/monitor-point.component.ts
@@ -1,3 +1,4 @@
import { CoorPickerService } from 'app/routes/map/coordinates-picker/coordinates-picker.service';
import {  AreaNames, MonitorPoint } from '@business/entity/data';
import { Version, ValueTransformer } from '@angular/compiler/src/util';
import { Subject } from 'rxjs/Subject';
@@ -12,6 +13,7 @@
import { filter } from 'rxjs/operators/filter';
import { MonitorPointEditComponent } from 'app/routes/devices/monitor-point/monitor-point-edit/monitor-point-edit.component';
import { MonitorPointService } from '@business/services/http/monitor-point.service';
import { CoordinatesPickerComponent } from 'app/routes/map/coordinates-picker/coordinates-picker.component';
@Component({
@@ -55,6 +57,7 @@
    this.grid.pageSize = 10;
  }
  constructor(
    private coorPickerService:CoorPickerService,
    private monitorPointService: MonitorPointService,
    
    private confirmServ: NzModalService,
@@ -174,4 +177,33 @@
     }
     this.load();
  }
  configCoord(record: MonitorPoint): void {
    Object.assign(this.coorPickerService.data, record);
    let _data = this.coorPickerService.data;
    const areaNames = record.areaNames;
    let adress = null;
    if (areaNames != null) {
      adress = areaNames.provinceName + areaNames.cityName + areaNames.areaName + record.address;
    }
    this.coorPickerService.data.address = adress;
    this.coorPickerService.data['describe'] = '监控点名称';
    this.modalHelper.static(CoordinatesPickerComponent).subscribe(
      (staticComp) => {
        const data: MonitorPoint = {
          id: record.id,
          longitude: _data.longitude,
          latitude: _data.latitude,
        }
        this.monitorPointService.save(data).subscribe(
          (res: any) => {
            if (res.code === 1) {
              this.load();
              this.msgSrv.success('坐标配置成功!');
            }
          }
        );
      }
    );
  }
}
src/app/routes/devices/version/version-sensor-config/version-sensor-config.component.ts
@@ -21,7 +21,7 @@
        text: '名称',
        width: '200px'
      },
      key: {
      sensorKey: {
        text: '键值',
        width: '60px'
      },
src/app/routes/map/coordinates-picker/coordinates-picker.component.css
New file
@@ -0,0 +1,19 @@
.anchorBL {
    display: none;
}
.top_transparent {
    width: 98%;
    height: 40px;
    background: #fff;
    position: absolute;
    margin-top: 0;
    opacity: 0.6;
    z-index: 1;
}
.coordinate_title {
    width: 90%;
    position: absolute;
    top: 4%;
    z-index: 2;
}
src/app/routes/map/coordinates-picker/coordinates-picker.component.html
New file
@@ -0,0 +1,44 @@
          <div class="top_transparent">
          </div>
          <div class="coordinate_title">
              <div nz-row class="mb-sm">
                    <div nz-col [nzSm]="1">
                      <span></span>
                    </div>
                    <div  nz-col [nzSpan]="7">
                        <nz-input maxlength="20" [(ngModel)]="queryTest" [nzPlaceHolder]="'请输入地址(省 市 区 路 多少号)'">
                        </nz-input>
                    </div>
                    <div nz-col [nzSpan]="1">
                        <button nz-button [nzType]="'primary'" [disabled]="disabled"  (click)="mapSearch($event)" class="mr-sm">
                            <i class="anticon anticon-search"></i><span>搜索</span>
                        </button>
                    </div>
                    <div nz-col [nzSpan]="4">
                         <span></span>
                    </div>
                    <div nz-col [nzSpan]="11">
                            <label>
                                坐标:
                            </label>
                            <span>
                               ( {{markerOption.point.lng}} <strong>,</strong> {{markerOption.point.lat}} )
                            </span>
                    </div>
              </div>
          </div>
          <baidu-map #map [options]="options"  (loaded)="loadMap($event)" (clicked)="clickMap($event)"  style="display: block;height:400px;">
              <control type="navigation" [options]="navigationOpts"></control>
              <marker #marker  [point]="markerOption.point" [options]="markerOption.options" (loaded)="loadMarker($event)"></marker>
          </baidu-map>
<div class="modal-footer">
        <label>{{data.describe}}:</label>
  <span [ngStyle]="{'font-size': '16px','font-weight': 'bold','margin-right':'30px'}">{{data.name}}</span>
  <button nz-button type="button" (click)="close()">关闭</button>
  <button nz-button [nzType]="'primary'" (click)="save()" [nzLoading]="isSaving">
    <span>
      保存
      <span *ngIf="isSaving">中</span>
    </span>
  </button>
</div>
src/app/routes/map/coordinates-picker/coordinates-picker.component.ts
New file
@@ -0,0 +1,120 @@
import { NzModalSubject } from 'ng-zorro-antd';
import { ReactiveFormsModule } from '@angular/forms';
import { ViewEncapsulation,Component,  ViewChild, ElementRef, NgZone } from '@angular/core';
import { MapOptions,Point,MarkerOptions,ControlAnchor,NavigationControlOptions,NavigationControlType,BMapInstance } from 'angular2-baidu-map';
import { CoorPicker } from '@business/entity/data';
import { CoorPickerService } from 'app/routes/map/coordinates-picker/coordinates-picker.service';
@Component({
  encapsulation: ViewEncapsulation.None,
  selector: 'app-coordinates-picker',
  templateUrl: './coordinates-picker.component.html',
  styleUrls: [ './coordinates-picker.component.css' ],
})
export class CoordinatesPickerComponent{
    Default_LNG = 121;
    Default_LAT = 31.4;
    markerOption:{
      point:Point,
      options:MarkerOptions
    }= {
      point:null,
      options:null
    };
    data:CoorPicker;
    navigationOpts:NavigationControlOptions;
    options: MapOptions;
    _BMap:any = null;
  constructor(private subject:NzModalSubject,private coorPickerService:CoorPickerService) {
    this.data = this.coorPickerService.data;
    let lng = this.data.longitude;
    lng = lng ==0 || lng == null ? this.Default_LNG:lng;
    this.data.longitude = lng;
    let lat = this.data.latitude;
    lat = lat == 0||lat == null ? this.Default_LAT:lat;
    this.data.latitude = lat;
    this.options = {
        minZoom:3,
        maxZoom:19,
        cursor:'default',
        centerAndZoom: {
          lng:lng,
          lat:lat,
          zoom: 19
        },
        enableKeyboard: true
      };
      this.navigationOpts = {
        anchor: ControlAnchor.BMAP_ANCHOR_BOTTOM_RIGHT,
        type: NavigationControlType.BMAP_NAVIGATION_CONTROL_LARGE
      }
      this.markerOption.point = {
        lng:lng,
        lat:lat
      };
      this.markerOption.options = {
        icon: {
          imageUrl: './assets/img/map_coordinates.png',
          size: {
            height: 30,
            width: 30
          }
        },
        offset:{
           height:-30,
           width:-15
        }
       };
  }
  private _marker:any = null;
  loadMarker(marker){
    if(this._marker==null){
      this._marker = marker;
    }
  }
  private _map: any;
  private _localSearch;
  loadMap(map: any) {
      this._map = map;
      this._BMap = window.BMap;
      this._map.addEventListener(
        'tilesloaded',
        (type, fn) => {
           this._map.clearOverlays();
           this._map.addOverlay(this._marker);
        }
      );
      this._localSearch= new  this._BMap.LocalSearch(map, {
        renderOptions:{map: map}
      });
      if(this.data.latitude==this.Default_LAT&&this.data.longitude==this.Default_LNG
      &&this.data.address!=null){
          this._localSearch.search(this.data.address);
      }
  }
  queryTest:string;
   mapSearch(param:any){
      let text = this.queryTest;
      text = text == null || text.trim() ==''?'昆山市':text;
      this._localSearch.search(text);
  }
  clickMap(e: any) {
       this.markerOption.point = {
         lng: e.point.lng,
         lat: e.point.lat
       };
       this.coorPickerService.data.longitude = e.point.lng;
       this.coorPickerService.data.latitude = e.point.lat;
  }
  close() {
      this.subject.destroy();
  }
  save() {
      this.subject.next();
      this.subject.destroy();
  }
}
src/app/routes/map/coordinates-picker/coordinates-picker.service.ts
New file
@@ -0,0 +1,15 @@
import { CoorPicker } from '@business/entity/data';
import { Injectable } from '@angular/core';
@Injectable()
export class CoorPickerService {
  public data:CoorPicker = {
    longitude:0,
    latitude:0,
    name:'',
    describe:'',
    address:''
  };
  constructor() { }
}
src/app/routes/map/map.module.ts
New file
@@ -0,0 +1,21 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { CoordinatesPickerComponent } from './coordinates-picker/coordinates-picker.component';
import { Routes, RouterModule } from '@angular/router';
import { BaiduMapModule  } from 'angular2-baidu-map';
import { AqmModule } from 'angular-qq-maps';
import { SharedModule } from '@shared/shared.module';
@NgModule({
    imports: [
      CommonModule,
      SharedModule,
        BaiduMapModule.forRoot({
          ak:'rER1sgBIcQxkfNSlm2wmBGZGgEERrooM'
        })
    ],
  declarations: [CoordinatesPickerComponent],
  exports:[CoordinatesPickerComponent]
})
export class MapModule { }
src/app/routes/sensors/basic-info/basic-info.component.ts
@@ -27,7 +27,7 @@
        text: '名称',
        width: '200px'  
      },
      key: {
      sensorKey: {
        text: '键值',
        width: '60px'  
      },
src/app/routes/sensors/basic-info/sensor-edit/sensor-edit.component.html
@@ -16,7 +16,7 @@
      <label nz-form-item-required>键值</label>
    </div>
    <div nz-form-control nz-col [nzSpan]="5" nzHasFeedback>
      <nz-input formControlName="key" maxlength="20" [nzPlaceHolder]="'键值'">
      <nz-input formControlName="sensorKey" maxlength="20" [nzPlaceHolder]="'键值'">
      </nz-input>
    </div>
    <div nz-form-label nz-col [nzSm]="4" [nzXs]="24">
src/app/routes/sensors/basic-info/sensor-edit/sensor-edit.component.ts
@@ -23,7 +23,7 @@
     const data = this.data;
     const validates: Sensor  = {
          name: [data.name, [Validators.required] ],
          key: [data.key, [Validators.required] ],
          sensorKey: [data.sensorKey, [Validators.required] ],
          lower: [data.lower ],
          upper: [data.upper ],
          unit: [data.unit ],
src/app/routes/systems/account/account.component.ts
@@ -141,5 +141,4 @@
      return this.dateSrv.date_format(date, 'YYYY-MM-DD');
    }
  }
}
src/app/routes/systems/organization/organization-config/organization-config.component.html
@@ -31,7 +31,7 @@
                </tr>
            </thead>
            <tbody formGroupName="alarmLevels" nz-tbody>
                <tr nz-tbody-tr *ngFor="let row of nzTable.data" formGroupName="{{row.key}}">
                <tr nz-tbody-tr *ngFor="let row of nzTable.data" formGroupName="{{row.sensorKey}}">
                    <td nz-td [nzCheckbox]="true">
                        <label nz-checkbox formControlName="enable"></label>
@@ -41,17 +41,17 @@
                            {{ row.name }}({{ row.unit }})
                        </span>
                    </td>
                    <td formArrayName="increment" *ngFor="let in of validateForm.get('alarmLevels.'+row.key+'.increment').controls; index as i">
                    <td formArrayName="increment" *ngFor="let in of validateForm.get('alarmLevels.'+row.sensorKey+'.increment').controls; index as i">
                            <div nz-form-item>
                                <div nz-form-control nzHasFeedback>
                                    <nz-input [formControlName]="i" maxlength="20" nzDisabled="{{ !f.value['alarmLevels'][row.key]['enable'] }}"></nz-input>
                                    <nz-input [formControlName]="i" maxlength="20" nzDisabled="{{ !f.value['alarmLevels'][row.sensorKey]['enable'] }}"></nz-input>
                                </div>
                            </div>
                    </td>
                    <td formArrayName="degression" *ngFor="let in of validateForm.get('alarmLevels.'+row.key+'.degression').controls; index as i">
                    <td formArrayName="degression" *ngFor="let in of validateForm.get('alarmLevels.'+row.sensorKey+'.degression').controls; index as i">
                        <div nz-form-item>
                            <div nz-form-control nzHasFeedback>
                                <nz-input [formControlName]="i" maxlength="20" nzDisabled="{{ !f.value['alarmLevels'][row.key]['enable'] }}"></nz-input>
                                <nz-input [formControlName]="i" maxlength="20" nzDisabled="{{ !f.value['alarmLevels'][row.sensorKey]['enable'] }}"></nz-input>
                            </div>
                        </div>
                   </td>   
src/app/routes/systems/organization/organization-config/organization-config.component.ts
@@ -140,7 +140,7 @@
  checkAll(param) {
    const keys = this.grid.data.map(
      item => {
        return item['key'];
        return item['sensorKey'];
      }
    );
    this._allCheckTriggers = 0;
@@ -156,16 +156,18 @@
  refreshIndeterminate() {
    const keys = this.grid.data.map(
      item => {
        return item['key'];
        return item['sensorKey'];
      }
    );
    const allChecked = keys.every(key => this.validateForm.get('alarmLevels.' + key + '.enable').value);
    const allUnChecked = keys.every(key => !this.validateForm.get('alarmLevels.' + key + '.enable').value);
    this.indeterminate = (!allChecked) && (!allUnChecked);
  }
  isSaving:boolean = false;
  save($event, value, valid) {
    $event.preventDefault();
    if (valid) {
       this.isSaving = true;
       const data:AlarmConfig = {
         id:value._id,
         organizationId:this.organization.id,
src/assets/img/map_coordinates.png
yarn.lock
@@ -219,29 +219,29 @@
    lodash "^4.17.4"
    wolfy87-eventemitter "^5.1.0"
"@delon/abc@^0.6.0-rc.2":
  version "0.6.0-rc.2"
  resolved "http://registry.npm.taobao.org/@delon/abc/download/@delon/abc-0.6.0-rc.2.tgz#29042b329147492d2900eff5266dce2f760118c9"
"@delon/abc@0.6.1":
  version "0.6.1"
  resolved "http://registry.npm.taobao.org/@delon/abc/download/@delon/abc-0.6.1.tgz#161ab09848715700fd00d073c55ac0a51268195d"
"@delon/acl@^0.6.0-rc.2":
  version "0.6.0-rc.2"
  resolved "http://registry.npm.taobao.org/@delon/acl/download/@delon/acl-0.6.0-rc.2.tgz#3e62d7ea2b7b5faa03644354e9bc9c0e496baa8e"
"@delon/acl@0.6.1":
  version "0.6.1"
  resolved "http://registry.npm.taobao.org/@delon/acl/download/@delon/acl-0.6.1.tgz#2728f2c24684640caff36db98c0777589b59f747"
"@delon/auth@^0.6.0-rc.2":
  version "0.6.0-rc.2"
  resolved "http://registry.npm.taobao.org/@delon/auth/download/@delon/auth-0.6.0-rc.2.tgz#2aab1245f114845b29f3d127846efa19d617ce5c"
"@delon/auth@0.6.1":
  version "0.6.1"
  resolved "http://registry.npm.taobao.org/@delon/auth/download/@delon/auth-0.6.1.tgz#26b0945008663b7126ea30aca6372a6bc5d6a9cb"
"@delon/cache@^0.6.0-rc.2":
  version "0.6.0-rc.2"
  resolved "http://registry.npm.taobao.org/@delon/cache/download/@delon/cache-0.6.0-rc.2.tgz#d65789d375c7939d398395e97adf66b9f87a2fa4"
"@delon/cache@0.6.1":
  version "0.6.1"
  resolved "http://registry.npm.taobao.org/@delon/cache/download/@delon/cache-0.6.1.tgz#13b412897743dc2ad612c4c4fca280c3dc044825"
"@delon/mock@^0.6.0-rc.2":
  version "0.6.0-rc.2"
  resolved "http://registry.npm.taobao.org/@delon/mock/download/@delon/mock-0.6.0-rc.2.tgz#9e7b677c692241845425e82116755f3c0dfed439"
"@delon/mock@0.6.1":
  version "0.6.1"
  resolved "http://registry.npm.taobao.org/@delon/mock/download/@delon/mock-0.6.1.tgz#e52bbdd708ff83680c985d0aa4ace282168de873"
"@delon/theme@^0.6.0-rc.2":
  version "0.6.0-rc.2"
  resolved "http://registry.npm.taobao.org/@delon/theme/download/@delon/theme-0.6.0-rc.2.tgz#906f81ba8fe292aa86dea2cb97f7dffff37ffef3"
"@delon/theme@0.6.1":
  version "0.6.1"
  resolved "http://registry.npm.taobao.org/@delon/theme/download/@delon/theme-0.6.1.tgz#4e98b1dc565c2f0684717c44ed73509cd866f120"
"@ngtools/json-schema@1.1.0", "@ngtools/json-schema@^1.1.0":
  version "1.1.0"
@@ -420,10 +420,6 @@
  version "1.0.1"
  resolved "http://registry.npm.taobao.org/amdefine/download/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5"
angular-baidu-maps@^1.0.1:
  version "1.0.1"
  resolved "http://registry.npm.taobao.org/angular-baidu-maps/download/angular-baidu-maps-1.0.1.tgz#000f206b1992336baca42cc7a4ae8575726a96b9"
angular-qq-maps@^1.0.1:
  version "1.0.1"
  resolved "http://registry.npm.taobao.org/angular-qq-maps/download/angular-qq-maps-1.0.1.tgz#ba4f312f501bb208837081ed9dd7e595ba53c810"
@@ -442,6 +438,10 @@
    mobx ">=3"
    mobx-angular ">=1"
angular2-baidu-map@^4.1.0:
  version "4.1.0"
  resolved "https://registry.yarnpkg.com/angular2-baidu-map/-/angular2-baidu-map-4.1.0.tgz#9992840349a78e3d3c3eaf3b3857fd85e59ccb32"
ansi-escapes@^1.0.0:
  version "1.4.0"
  resolved "http://registry.npm.taobao.org/ansi-escapes/download/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e"