LIDEXI il y a 5 ans
Parent
commit
a1aee83a86
51 fichiers modifiés avec 8074 ajouts et 222 suppressions
  1. 193 0
      public/cdn/elevator/main.js
  2. 0 0
      public/cdn/elevator/zlplayer.min.js
  3. BIN
      public/img/grid/back.png
  4. BIN
      public/img/grid/bg.png
  5. BIN
      public/img/grid/bg2.png
  6. BIN
      public/img/grid/car.png
  7. BIN
      public/img/grid/device.png
  8. BIN
      public/img/grid/home.png
  9. BIN
      public/img/grid/humidity.png
  10. BIN
      public/img/grid/location.png
  11. BIN
      public/img/grid/menuHome.png
  12. BIN
      public/img/grid/people.png
  13. BIN
      public/img/grid/pm25.png
  14. BIN
      public/img/grid/room.png
  15. BIN
      public/img/grid/tem.png
  16. BIN
      public/img/grid/video.png
  17. BIN
      public/img/grid/xiaoqu.png
  18. 2 0
      public/index.html
  19. 124 0
      src/api/dataview/dataviewoption.js
  20. 50 0
      src/api/device/doordevice.js
  21. 195 0
      src/api/device/elevatorUtil.js
  22. 50 0
      src/api/device/elevatoralarm.js
  23. 50 0
      src/api/device/elevatoralarmdirector.js
  24. 50 0
      src/api/device/elevatoralarmsetting.js
  25. 117 0
      src/api/device/elevatordevice.js
  26. 50 0
      src/api/device/iotalarm.js
  27. 50 0
      src/api/device/iotalarmgroup.js
  28. 50 0
      src/api/device/iotalarmgroupuser.js
  29. 61 0
      src/api/device/iotdevice.js
  30. 50 0
      src/api/device/iotdevicedetail.js
  31. 50 0
      src/api/device/videoclouddevice.js
  32. 0 116
      src/api/smartapplication/smartdevice.js
  33. 0 102
      src/api/smartapplication/videoclouddevice.js
  34. 359 0
      src/components/device/alarmhistory.vue
  35. 197 0
      src/components/residential/customAvueMap.vue
  36. 2 2
      src/main.js
  37. 433 0
      src/views/device/doordevice.vue
  38. 371 0
      src/views/device/elevatoralarm.vue
  39. 236 0
      src/views/device/elevatoralarmdirector.vue
  40. 462 0
      src/views/device/elevatoralarmsetting.vue
  41. 407 0
      src/views/device/elevatordevice.vue
  42. 583 0
      src/views/device/elevatorvideo.vue
  43. 384 0
      src/views/device/iotalarm.vue
  44. 507 0
      src/views/device/iotalarmgroup.vue
  45. 240 0
      src/views/device/iotalarmgroupuser.vue
  46. 1463 0
      src/views/device/iotdevice.vue
  47. 245 0
      src/views/device/iotdevicedetail.vue
  48. 178 0
      src/views/device/videoSurveillance.vue
  49. 863 0
      src/views/device/videoclouddevice.vue
  50. 1 1
      src/views/smartapplication/buildingvideo.vue
  51. 1 1
      src/views/smartapplication/devicebuilding.vue

+ 193 - 0
public/cdn/elevator/main.js

@@ -0,0 +1,193 @@
+import zlplayer from '';
+
+let webServer = {
+    host: 'localhost',
+    port: 7890
+}
+
+let isLive = true;          //是否为实时视频
+
+zlplayer.resPath = '';
+
+//去后端获取预览视频地址
+function getRealUrlByToken() {
+    isLive = true;
+    let elevatorSn = document.getElementById('elevatorSn').value;
+    let xhr = new XMLHttpRequest();
+    let reqUrl = `http://${webServer.host}:${webServer.port}/getElevatorMonitolUrlByToken?elevatorSn=${elevatorSn}`;
+    xhr.open('GET', reqUrl, false);
+    xhr.send();
+    if (xhr.status == 200) {
+        let res = JSON.parse(xhr.responseText);
+        if (res && res.monitorUrl) {
+            document.getElementById('url').value = res.monitorUrl;
+        }
+        return;
+    }
+    console.error(`getElevatorMonitolUrl error ${xhr.status}`);
+}
+
+
+//去后端获取报警录像地址
+function getAlarmRecordUrlByToken() {
+    isLive = false;
+    let elevatorSn = document.getElementById('elevatorSn').value;
+    let alarmId = document.getElementById('alarmId').value;
+    let xhr = new XMLHttpRequest();
+    let reqUrl = `http://${webServer.host}:${webServer.port}/getAlarmRecordUrlByToken?elevatorSn=${elevatorSn}&alarmId=${alarmId}`;
+    xhr.open('GET', reqUrl, false);
+    xhr.send();
+    if (xhr.status == 200) {
+        let res = JSON.parse(xhr.responseText);
+        if (res && res.recordUrl) {
+            document.getElementById('url').value = res.recordUrl;
+        }
+        return;
+    }
+    console.error(`getAlarmRecordUrlByToken error ${xhr.status}`);
+}
+
+//去后端获取视频地址
+function getTimeRecordUrlByToken() {
+    isLive = false;
+    let elevatorSn = document.getElementById('elevatorSn').value;
+    let beginTime = parseInt(document.getElementById('beginTime').value);
+    let endTime = parseInt(document.getElementById('endTime').value);
+    let xhr = new XMLHttpRequest();
+    let reqUrl = `http://${webServer.host}:${webServer.port}/getElevatorRecordUrlByToken?elevatorSn=${elevatorSn}&beginTime=${beginTime}&endTime=${endTime}`;
+    xhr.open('GET', reqUrl, false);
+    xhr.send();
+    if (xhr.status == 200) {
+        let res = JSON.parse(xhr.responseText);
+        if (res && res.recordUrl) {
+            document.getElementById('url').value = res.recordUrl;
+        }
+        return;
+    }
+    console.error(`getTimeRecordUrlByToken error ${xhr.status}`);
+}
+
+let player = null;
+
+//开始播放
+function startPlay() {
+    stopPlay();
+
+    let videoElement = document.getElementById('myvideo');
+    let urlElement = document.getElementById("url");
+
+    let config = {
+        url: urlElement.value,                   //资源地址
+        isLive: isLive,                          //实时预览:true , 回放:false
+        enableFullScreen: true,                  //是否双击全屏
+        enableFillWindow: true                   //是否视频铺满窗口
+    };
+
+    player = zlplayer.createPlayer(videoElement, config);
+    player.on('error', onPlayerError);
+    player.play();
+}
+
+//停止播放
+function stopPlay() {
+    if ( player ) {
+        player.stop();
+        player = null;
+    }
+}
+
+//抓图
+function capture() {
+    if (player) {
+
+        let img = player.capture();            //抓图,返回image
+
+        if (img) {
+            let now = new Date();
+            let filename = `capture_${now.toLocaleDateString()}_${now.toLocaleTimeString()}.png`;
+
+            let save_link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');
+            save_link.href = img;
+            save_link.download = filename;
+
+            let event = document.createEvent('MouseEvents');
+            event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
+            save_link.dispatchEvent(event);
+        }
+    }
+}
+
+//开始录像
+function startRecord() {
+    if (player) {
+        player.startRecord();
+    }
+}
+
+//停止录像
+function stopRecord() {
+    if (player) {
+        let blob = player.stopRecord();              //停止录像返回 blob
+        if ( blob ) {
+            let url = window.URL.createObjectURL(blob);
+            let now = new Date();
+
+            let filename = `record_${now.toLocaleDateString()}_${now.toLocaleTimeString()}.webm`;
+
+            let a = document.createElement('a');
+            a.style.display = 'none';
+            a.href = url;
+            a.download = filename;
+            document.body.appendChild(a);
+            a.click();
+            setTimeout(function() {
+                document.body.removeChild(a);
+                window.URL.revokeObjectURL(url);
+            }, 100);
+        }
+    }
+}
+
+//旋转视频
+function rotate(deg) {
+    if (player) {
+        player.rotate(deg);
+    }
+}
+
+//清理创建过的播放器
+function clearPlayer() {
+    zlplayer.clearPlayer();
+}
+
+//播放器错误event
+function onPlayerError(type, reason, desc) {
+    switch(type){
+        case 'NetworkError':
+            if ( desc.code == -1 ) {
+                alert("网络错误");
+            }
+            else if ( desc.code == -999 ) {
+                alert("网络错误, 流中断");
+
+                let urlElement = document.getElementById("url");
+                player.flvSrc.url = urlElement.value;    //这里应该是重新去获取新的url
+                player.resume();
+            }else if ( desc.code == 401 ) {
+                console.log(`${desc.msg} : 鉴权失败`);
+            }
+            else if ( desc.code == 404 ) {
+                alert("资源不存在, 设备不在线");
+            };
+            break;
+        case 'MediaError':
+            if ( reason == 'NeedReplay' ) {
+                console.log("媒体异常,自动重新播放");
+
+                let urlElement = document.getElementById("url");
+                player.flvSrc.url = urlElement.value;    //这里应该是重新去获取新的url
+                player.resume();
+            };
+            break;
+    }
+}

Fichier diff supprimé car celui-ci est trop grand
+ 0 - 0
public/cdn/elevator/zlplayer.min.js


BIN
public/img/grid/back.png


BIN
public/img/grid/bg.png


BIN
public/img/grid/bg2.png


BIN
public/img/grid/car.png


BIN
public/img/grid/device.png


BIN
public/img/grid/home.png


BIN
public/img/grid/humidity.png


BIN
public/img/grid/location.png


BIN
public/img/grid/menuHome.png


BIN
public/img/grid/people.png


BIN
public/img/grid/pm25.png


BIN
public/img/grid/room.png


BIN
public/img/grid/tem.png


BIN
public/img/grid/video.png


BIN
public/img/grid/xiaoqu.png


+ 2 - 0
public/index.html

@@ -20,6 +20,8 @@
   <script src="<%= BASE_URL %>cdn/xlsx/xlsx.full.min.js"></script>
   <link rel="icon" href="<%= BASE_URL %>favicon.png">
 
+  <script src="<%= BASE_URL %>cdn/elevator/zlplayer.min.js"></script>
+
 
   <script type="text/javascript" src="https://webapi.amap.com/maps?v=2.0&key=cbb265e2a60bbbc04a52eec4eecdeb12&plugin=AMap.PolygonEditor,AMap.Driving"></script>
   <script src="https://webapi.amap.com/ui/1.1/main.js?v=1.0.11"></script>

+ 124 - 0
src/api/dataview/dataviewoption.js

@@ -0,0 +1,124 @@
+
+
+export const iconsOption = (obj) =>{
+  return {
+    span:2,
+    data: [
+      {
+        click: function (item) {obj.select(100004)},
+        title: '智能烟感',
+        count: 0,
+        // icon: 'el-icon-smoking',
+        icon: 'yc-grid-zhinengyangan',
+      },
+      {
+        click: function (item) {obj.select(100020)},
+        title: '燃气监控',
+        count: 0,
+        // icon: 'el-icon-help',
+        icon: 'yc-grid-ranqijianceqi',
+      },
+      {
+        click: function (item) {obj.select(3)},
+        title: '井盖监控',
+        count: 0,
+        // icon: 'el-icon-circle-plus-outline',
+        icon: 'yc-grid-manhole-cover',
+      },
+      {
+        click: function (item) {obj.select(4)},
+        title: '一键告警',
+        count: 0,
+        // icon: 'el-icon-thumb',
+        icon: 'yc-grid-peizhitubiaosvg-1',
+      },
+      {
+        click: function (item) {obj.select(5)},
+        title: '智慧路灯',
+        count: 0,
+        // icon: 'el-icon-wind-power',
+        icon: 'yc-grid-ludeng',
+      },
+      {
+        click: function (item) {obj.select(960417)},
+        title: '智慧消防',
+        count: 0,
+        // icon: 'el-icon-loading',
+        icon: 'yc-grid-xiaofanghuopao',
+      },
+      {
+        click: function (item) {obj.select(7)},
+        title: '智能垃圾桶',
+        count: 0,
+        // icon: 'el-icon-delete',
+        icon: 'iconfont iconicon_delete',
+      },
+      {
+        click: function (item) {obj.select(8)},
+        title: '智能地磁',
+        count: 0,
+        // icon: 'el-icon-s-help',
+        icon: 'yc-grid-dici',
+      },
+      {
+        click: function (item) {obj.select(9)},
+        title: '智能门磁',
+        count: 0,
+        // icon: 'el-icon-attract',
+        icon: 'yc-grid-menci',
+      }]
+  }
+}
+
+export const dataDisplay = (obj,parent) =>{
+  return {
+    span: 4,
+    data: [
+      {
+        click: function (item) {
+          parent.select(this.deviceType,this.deviceStatus)
+        },
+        count: obj.normalCount,
+        title: '正常',
+        deviceType: obj.deviceType,
+        deviceStatus: 1,
+      },
+      {
+        click: function (item) {
+          parent.select(this.deviceType,this.deviceStatus)
+        },
+        count: obj.alertCount,
+        title: '告警',
+        deviceType: obj.deviceType,
+        deviceStatus: 2,
+      },
+      {
+        click: function (item) {
+          parent.select(this.deviceType,this.deviceStatus)
+        },
+        count: obj.outlineCount,
+        title: '失联',
+        deviceType: obj.deviceType,
+        deviceStatus: 3,
+      },
+      {
+        click: function (item) {
+          parent.select(this.deviceType,this.deviceStatus)
+        },
+        count: obj.pauseCount,
+        title: '停用',
+        deviceType: obj.deviceType,
+        deviceStatus: 4,
+      },
+      {
+        click: function (item) {
+          parent.select(this.deviceType,this.deviceStatus)
+        },
+        count: obj.armedCount,
+        title: '待布防',
+        deviceType: obj.deviceType,
+        deviceStatus: 5,
+      }
+    ]
+  }
+}

+ 50 - 0
src/api/device/doordevice.js

@@ -0,0 +1,50 @@
+import request from '@/router/axios';
+
+export const getList = (current, size, params) => {
+  return request({
+    url: '/api/cyzh-smart-device/doordevice/list',
+    method: 'get',
+    params: {
+      ...params,
+      current,
+      size,
+    }
+  })
+}
+
+export const getDetail = (id) => {
+  return request({
+    url: '/api/cyzh-smart-device/doordevice/detail',
+    method: 'get',
+    params: {
+      id
+    }
+  })
+}
+
+export const remove = (ids) => {
+  return request({
+    url: '/api/cyzh-smart-device/doordevice/remove',
+    method: 'post',
+    params: {
+      ids,
+    }
+  })
+}
+
+export const add = (row) => {
+  return request({
+    url: '/api/cyzh-smart-device/doordevice/submit',
+    method: 'post',
+    data: row
+  })
+}
+
+export const update = (row) => {
+  return request({
+    url: '/api/cyzh-smart-device/doordevice/submit',
+    method: 'post',
+    data: row
+  })
+}
+

+ 195 - 0
src/api/device/elevatorUtil.js

@@ -0,0 +1,195 @@
+let webServer = {
+  host: 'localhost',
+  port: 7890
+}
+
+let isLive = true;          //是否为实时视频
+
+zlplayer.resPath = '';
+
+//去后端获取预览视频地址
+export const getRealUrlByToken = () => {
+  isLive = true;
+  let elevatorSn = document.getElementById('elevatorSn').value;
+  let xhr = new XMLHttpRequest();
+  let reqUrl = `http://${webServer.host}:${webServer.port}/getElevatorMonitolUrlByToken?elevatorSn=${elevatorSn}`;
+  xhr.open('GET', reqUrl, false);
+  xhr.send();
+  if (xhr.status == 200) {
+    let res = JSON.parse(xhr.responseText);
+    if (res && res.monitorUrl) {
+      document.getElementById('url').value = res.monitorUrl;
+    }
+    return;
+  }
+  console.error(`getElevatorMonitolUrl error ${xhr.status}`);
+}
+
+
+//去后端获取报警录像地址
+export const getAlarmRecordUrlByToken = () => {
+  isLive = false;
+  let elevatorSn = document.getElementById('elevatorSn').value;
+  let alarmId = document.getElementById('alarmId').value;
+  let xhr = new XMLHttpRequest();
+  let reqUrl = `http://${webServer.host}:${webServer.port}/getAlarmRecordUrlByToken?elevatorSn=${elevatorSn}&alarmId=${alarmId}`;
+  xhr.open('GET', reqUrl, false);
+  xhr.send();
+  if (xhr.status == 200) {
+    let res = JSON.parse(xhr.responseText);
+    if (res && res.recordUrl) {
+      document.getElementById('url').value = res.recordUrl;
+    }
+    return;
+  }
+  console.error(`getAlarmRecordUrlByToken error ${xhr.status}`);
+}
+
+//去后端获取视频地址
+export const getTimeRecordUrlByToken = () => {
+  isLive = false;
+  let elevatorSn = document.getElementById('elevatorSn').value;
+  let beginTime = parseInt(document.getElementById('beginTime').value);
+  let endTime = parseInt(document.getElementById('endTime').value);
+  let xhr = new XMLHttpRequest();
+  let reqUrl = `http://${webServer.host}:${webServer.port}/getElevatorRecordUrlByToken?elevatorSn=${elevatorSn}&beginTime=${beginTime}&endTime=${endTime}`;
+  xhr.open('GET', reqUrl, false);
+  xhr.send();
+  if (xhr.status == 200) {
+    let res = JSON.parse(xhr.responseText);
+    if (res && res.recordUrl) {
+      document.getElementById('url').value = res.recordUrl;
+    }
+    return;
+  }
+  console.error(`getTimeRecordUrlByToken error ${xhr.status}`);
+}
+
+
+
+//开始播放
+export const startPlay = (elementId, url, player) => {
+  if (player){
+    stopPlay(player)
+  }
+  let videoElement = document.getElementById(elementId);
+  // let urlElement = document.getElementById("url");
+
+  // let url = 'https://admin:123456@apigateway.yun-ti.com/media/ehome/D76228640?ch=1&streamtype=sub&token=YBv4-TkyYjU4N2JhYzVkMTI2MzhiMmJkMWE1OTg0NzM2NzQzE6YiQJ1lqBuM4VdjbL5u8O2vdBcxiB6S7XBXx4dA11U=';
+
+  let config = {
+    url: url,                   //资源地址
+    isLive: isLive,                          //实时预览:true , 回放:false
+    enableFullScreen: true,                  //是否双击全屏
+    enableFillWindow: true                   //是否视频铺满窗口
+  };
+  player = zlplayer.createPlayer(videoElement, config);
+  player.on('error', onPlayerError);
+  player.play();
+  return player;
+}
+
+//停止播放
+export const stopPlay = (player) => {
+  if ( player ) {
+    player.stop();
+    player = null;
+  }
+}
+
+//抓图
+export const capture = (player) => {
+  if (player) {
+
+    let img = player.capture();            //抓图,返回image
+
+    if (img) {
+      let now = new Date();
+      let filename = `capture_${now.toLocaleDateString()}_${now.toLocaleTimeString()}.png`;
+
+      let save_link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');
+      save_link.href = img;
+      save_link.download = filename;
+
+      let event = document.createEvent('MouseEvents');
+      event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
+      save_link.dispatchEvent(event);
+    }
+  }
+}
+
+//开始录像
+export const startRecord = (player) => {
+  if (player) {
+    player.startRecord();
+  }
+}
+
+//停止录像
+export const stopRecord = (player) => {
+  if (player) {
+    let blob = player.stopRecord();              //停止录像返回 blob
+    if ( blob ) {
+      let url = window.URL.createObjectURL(blob);
+      let now = new Date();
+
+      let filename = `record_${now.toLocaleDateString()}_${now.toLocaleTimeString()}.webm`;
+
+      let a = document.createElement('a');
+      a.style.display = 'none';
+      a.href = url;
+      a.download = filename;
+      document.body.appendChild(a);
+      a.click();
+      setTimeout(function() {
+        document.body.removeChild(a);
+        window.URL.revokeObjectURL(url);
+      }, 100);
+    }
+  }
+}
+
+//旋转视频
+export const rotate = (player, deg) => {
+  if (player) {
+    player.rotate(deg);
+  }
+}
+
+//清理创建过的播放器
+export const clearPlayer = () => {
+  zlplayer.clearPlayer();
+}
+
+//播放器错误event
+export const onPlayerError = (player, type, reason, desc) => {
+  switch(type){
+    case 'NetworkError':
+      if ( desc.code == -1 ) {
+        alert("网络错误");
+      }
+      else if ( desc.code == -999 ) {
+        alert("网络错误, 流中断");
+
+        let urlElement = document.getElementById("url");
+        player.flvSrc.url = urlElement.value;    //这里应该是重新去获取新的url
+        player.resume();
+      }else if ( desc.code == 401 ) {
+        console.log(`${desc.msg} : 鉴权失败`);
+      }
+      else if ( desc.code == 404 ) {
+        alert("资源不存在, 设备不在线");
+      };
+      break;
+    case 'MediaError':
+      if ( reason == 'NeedReplay' ) {
+        console.log("媒体异常,自动重新播放");
+
+        let urlElement = document.getElementById("url");
+        player.flvSrc.url = urlElement.value;    //这里应该是重新去获取新的url
+        player.resume();
+      };
+      break;
+  }
+}
+

+ 50 - 0
src/api/device/elevatoralarm.js

@@ -0,0 +1,50 @@
+import request from '@/router/axios';
+
+export const getList = (current, size, params) => {
+  return request({
+    url: '/api/cyzh-smart-device/elevatoralarm/list',
+    method: 'get',
+    params: {
+      ...params,
+      current,
+      size,
+    }
+  })
+}
+
+export const getDetail = (id) => {
+  return request({
+    url: '/api/cyzh-smart-device/elevatoralarm/detail',
+    method: 'get',
+    params: {
+      id
+    }
+  })
+}
+
+export const remove = (ids) => {
+  return request({
+    url: '/api/cyzh-smart-device/elevatoralarm/remove',
+    method: 'post',
+    params: {
+      ids,
+    }
+  })
+}
+
+export const add = (row) => {
+  return request({
+    url: '/api/cyzh-smart-device/elevatoralarm/submit',
+    method: 'post',
+    data: row
+  })
+}
+
+export const update = (row) => {
+  return request({
+    url: '/api/cyzh-smart-device/elevatoralarm/submit',
+    method: 'post',
+    data: row
+  })
+}
+

+ 50 - 0
src/api/device/elevatoralarmdirector.js

@@ -0,0 +1,50 @@
+import request from '@/router/axios';
+
+export const getList = (current, size, params) => {
+  return request({
+    url: '/api/cyzh-smart-device/elevatoralarmdirector/list',
+    method: 'get',
+    params: {
+      ...params,
+      current,
+      size,
+    }
+  })
+}
+
+export const getDetail = (id) => {
+  return request({
+    url: '/api/cyzh-smart-device/elevatoralarmdirector/detail',
+    method: 'get',
+    params: {
+      id
+    }
+  })
+}
+
+export const remove = (ids) => {
+  return request({
+    url: '/api/cyzh-smart-device/elevatoralarmdirector/remove',
+    method: 'post',
+    params: {
+      ids,
+    }
+  })
+}
+
+export const add = (row) => {
+  return request({
+    url: '/api/cyzh-smart-device/elevatoralarmdirector/submit',
+    method: 'post',
+    data: row
+  })
+}
+
+export const update = (row) => {
+  return request({
+    url: '/api/cyzh-smart-device/elevatoralarmdirector/submit',
+    method: 'post',
+    data: row
+  })
+}
+

+ 50 - 0
src/api/device/elevatoralarmsetting.js

@@ -0,0 +1,50 @@
+import request from '@/router/axios';
+
+export const getList = (current, size, params) => {
+  return request({
+    url: '/api/cyzh-smart-device/elevatoralarmsetting/list',
+    method: 'get',
+    params: {
+      ...params,
+      current,
+      size,
+    }
+  })
+}
+
+export const getDetail = (id) => {
+  return request({
+    url: '/api/cyzh-smart-device/elevatoralarmsetting/detail',
+    method: 'get',
+    params: {
+      id
+    }
+  })
+}
+
+export const remove = (ids) => {
+  return request({
+    url: '/api/cyzh-smart-device/elevatoralarmsetting/remove',
+    method: 'post',
+    params: {
+      ids,
+    }
+  })
+}
+
+export const add = (row) => {
+  return request({
+    url: '/api/cyzh-smart-device/elevatoralarmsetting/submit',
+    method: 'post',
+    data: row
+  })
+}
+
+export const update = (row) => {
+  return request({
+    url: '/api/cyzh-smart-device/elevatoralarmsetting/submit',
+    method: 'post',
+    data: row
+  })
+}
+

+ 117 - 0
src/api/device/elevatordevice.js

@@ -0,0 +1,117 @@
+import request from '@/router/axios';
+
+export const getList = (current, size, params) => {
+  return request({
+    url: '/api/cyzh-smart-device/elevatordevice/list',
+    method: 'get',
+    params: {
+      ...params,
+      current,
+      size,
+    }
+  })
+}
+
+export const getDetail = (id) => {
+  return request({
+    url: '/api/cyzh-smart-device/elevatordevice/detail',
+    method: 'get',
+    params: {
+      id
+    }
+  })
+}
+
+export const remove = (ids) => {
+  return request({
+    url: '/api/cyzh-smart-device/elevatordevice/remove',
+    method: 'post',
+    params: {
+      ids,
+    }
+  })
+}
+
+export const add = (row) => {
+  return request({
+    url: '/api/cyzh-smart-device/elevatordevice/submit',
+    method: 'post',
+    data: row
+  })
+}
+
+export const update = (row) => {
+  return request({
+    url: '/api/cyzh-smart-device/elevatordevice/submit',
+    method: 'post',
+    data: row
+  })
+}
+
+
+export const getLiftResidentialSelect = () => {
+  return request({
+    url: '/api/cyzh-smart-device/elevatordevice/getLiftResidentialSelect',
+    method: 'get',
+  })
+}
+
+export const getLiftList = (params) => {
+  return request({
+    url: '/api/cyzh-smart-device/elevatordevice/getLiftList',
+    method: 'get',
+    params: {
+      ...params,
+    }
+  })
+}
+
+export const getRealvideo = (registerCode) => {
+  return request({
+    url: '/api/cyzh-smart-device/elevatordevice/getRealvideo',
+    method: 'get',
+    params: {
+      registerCode
+    }
+  })
+}
+
+
+
+export const getLiftHisAlarm = (registerCodes) => {
+  return request({
+    url: '/api/cyzh-smart-device/elevatordevice/getLiftHisAlarm',
+    method: 'get',
+    params: {
+      registerCodes
+    }
+  })
+}
+
+export const sync = () => {
+  return request({
+    url: '/api/cyzh-smart-device/elevatordevice/sync',
+    method: 'post',
+  })
+}
+
+export const getLiftStatus = (registerCode) => {
+  return request({
+    url: '/api/cyzh-smart-device/elevatordevice/getLiftStatus',
+    method: 'get',
+    params: {
+      registerCode
+    }
+  })
+}
+
+export const getLiftPointData = (registerCode) => {
+  return request({
+    url: '/api/cyzh-smart-device/elevatordevice/getLiftPointData',
+    method: 'get',
+    params: {
+      registerCode
+    }
+  })
+}
+

+ 50 - 0
src/api/device/iotalarm.js

@@ -0,0 +1,50 @@
+import request from '@/router/axios';
+
+export const getList = (current, size, params) => {
+  return request({
+    url: '/api/cyzh-smart-device/iotalarm/list',
+    method: 'get',
+    params: {
+      ...params,
+      current,
+      size,
+    }
+  })
+}
+
+export const getDetail = (id) => {
+  return request({
+    url: '/api/cyzh-smart-device/iotalarm/detail',
+    method: 'get',
+    params: {
+      id
+    }
+  })
+}
+
+export const remove = (ids) => {
+  return request({
+    url: '/api/cyzh-smart-device/iotalarm/remove',
+    method: 'post',
+    params: {
+      ids,
+    }
+  })
+}
+
+export const add = (row) => {
+  return request({
+    url: '/api/cyzh-smart-device/iotalarm/submit',
+    method: 'post',
+    data: row
+  })
+}
+
+export const update = (row) => {
+  return request({
+    url: '/api/cyzh-smart-device/iotalarm/submit',
+    method: 'post',
+    data: row
+  })
+}
+

+ 50 - 0
src/api/device/iotalarmgroup.js

@@ -0,0 +1,50 @@
+import request from '@/router/axios';
+
+export const getList = (current, size, params) => {
+  return request({
+    url: '/api/cyzh-smart-device/iotalarmgroup/list',
+    method: 'get',
+    params: {
+      ...params,
+      current,
+      size,
+    }
+  })
+}
+
+export const getDetail = (id) => {
+  return request({
+    url: '/api/cyzh-smart-device/iotalarmgroup/detail',
+    method: 'get',
+    params: {
+      id
+    }
+  })
+}
+
+export const remove = (ids) => {
+  return request({
+    url: '/api/cyzh-smart-device/iotalarmgroup/remove',
+    method: 'post',
+    params: {
+      ids,
+    }
+  })
+}
+
+export const add = (row) => {
+  return request({
+    url: '/api/cyzh-smart-device/iotalarmgroup/submit',
+    method: 'post',
+    data: row
+  })
+}
+
+export const update = (row) => {
+  return request({
+    url: '/api/cyzh-smart-device/iotalarmgroup/submit',
+    method: 'post',
+    data: row
+  })
+}
+

+ 50 - 0
src/api/device/iotalarmgroupuser.js

@@ -0,0 +1,50 @@
+import request from '@/router/axios';
+
+export const getList = (current, size, params) => {
+  return request({
+    url: '/api/cyzh-smart-device/iotalarmgroupuser/list',
+    method: 'get',
+    params: {
+      ...params,
+      current,
+      size,
+    }
+  })
+}
+
+export const getDetail = (id) => {
+  return request({
+    url: '/api/cyzh-smart-device/iotalarmgroupuser/detail',
+    method: 'get',
+    params: {
+      id
+    }
+  })
+}
+
+export const remove = (ids) => {
+  return request({
+    url: '/api/cyzh-smart-device/iotalarmgroupuser/remove',
+    method: 'post',
+    params: {
+      ids,
+    }
+  })
+}
+
+export const add = (row) => {
+  return request({
+    url: '/api/cyzh-smart-device/iotalarmgroupuser/submit',
+    method: 'post',
+    data: row
+  })
+}
+
+export const update = (row) => {
+  return request({
+    url: '/api/cyzh-smart-device/iotalarmgroupuser/submit',
+    method: 'post',
+    data: row
+  })
+}
+

+ 61 - 0
src/api/device/iotdevice.js

@@ -0,0 +1,61 @@
+import request from '@/router/axios';
+
+export const getList = (current, size, params) => {
+  return request({
+    url: '/api/cyzh-smart-device/iotdevice/list',
+    method: 'get',
+    params: {
+      ...params,
+      current,
+      size,
+    }
+  })
+}
+
+export const getDetail = (id) => {
+  return request({
+    url: '/api/cyzh-smart-device/iotdevice/detail',
+    method: 'get',
+    params: {
+      id
+    }
+  })
+}
+
+export const remove = (ids) => {
+  return request({
+    url: '/api/cyzh-smart-device/iotdevice/remove',
+    method: 'post',
+    params: {
+      ids,
+    }
+  })
+}
+
+export const add = (row) => {
+  return request({
+    url: '/api/cyzh-smart-device/iotdevice/submit',
+    method: 'post',
+    data: row
+  })
+}
+
+export const update = (row) => {
+  return request({
+    url: '/api/cyzh-smart-device/iotdevice/submit',
+    method: 'post',
+    data: row
+  })
+}
+
+
+export const deviceListCount = (params) => {
+  return request({
+    url: '/api/cyzh-smart-device/iotdevice/deviceListCount',
+    method: 'get',
+    params: {
+      ...params,
+    }
+  })
+}
+

+ 50 - 0
src/api/device/iotdevicedetail.js

@@ -0,0 +1,50 @@
+import request from '@/router/axios';
+
+export const getList = (current, size, params) => {
+  return request({
+    url: '/api/cyzh-smart-device/iotdevicedetail/list',
+    method: 'get',
+    params: {
+      ...params,
+      current,
+      size,
+    }
+  })
+}
+
+export const getDetail = (id) => {
+  return request({
+    url: '/api/cyzh-smart-device/iotdevicedetail/detail',
+    method: 'get',
+    params: {
+      id
+    }
+  })
+}
+
+export const remove = (ids) => {
+  return request({
+    url: '/api/cyzh-smart-device/iotdevicedetail/remove',
+    method: 'post',
+    params: {
+      ids,
+    }
+  })
+}
+
+export const add = (row) => {
+  return request({
+    url: '/api/cyzh-smart-device/iotdevicedetail/submit',
+    method: 'post',
+    data: row
+  })
+}
+
+export const update = (row) => {
+  return request({
+    url: '/api/cyzh-smart-device/iotdevicedetail/submit',
+    method: 'post',
+    data: row
+  })
+}
+

+ 50 - 0
src/api/device/videoclouddevice.js

@@ -0,0 +1,50 @@
+import request from '@/router/axios';
+
+export const getList = (current, size, params) => {
+  return request({
+    url: '/api/cyzh-smart-device/videoclouddevice/list',
+    method: 'get',
+    params: {
+      ...params,
+      current,
+      size,
+    }
+  })
+}
+
+export const getDetail = (id) => {
+  return request({
+    url: '/api/cyzh-smart-device/videoclouddevice/detail',
+    method: 'get',
+    params: {
+      id
+    }
+  })
+}
+
+export const remove = (ids) => {
+  return request({
+    url: '/api/cyzh-smart-device/videoclouddevice/remove',
+    method: 'post',
+    params: {
+      ids,
+    }
+  })
+}
+
+export const add = (row) => {
+  return request({
+    url: '/api/cyzh-smart-device/videoclouddevice/submit',
+    method: 'post',
+    data: row
+  })
+}
+
+export const update = (row) => {
+  return request({
+    url: '/api/cyzh-smart-device/videoclouddevice/submit',
+    method: 'post',
+    data: row
+  })
+}
+

+ 0 - 116
src/api/smartapplication/smartdevice.js

@@ -1,116 +0,0 @@
-import request from '@/router/axios';
-
-export const getList = (current, size, params) => {
-  return request({
-    url: '/api/smartapplication/smartdevice/list',
-    method: 'get',
-    params: {
-      ...params,
-      current,
-      size,
-    }
-  })
-}
-
-export const getEnterpriseList = (params) => {
-  return request({
-    url: '/api/smartapplication/smartdevice/getEnterpriseList',
-    method: 'get',
-    params: {
-      ...params,
-    }
-  })
-}
-
-export const getSmartDeviceStaticVo = (params) => {
-  return request({
-    url: '/api/smartapplication/smartdevice/getSmartDeviceStaticVo',
-    method: 'get',
-    params: {
-      ...params,
-    }
-  })
-}
-
-export const deviceListCount = (params) => {
-  return request({
-    url: '/api/smartapplication/smartdevice/deviceListCount',
-    method: 'get',
-    params: {
-      ...params,
-    }
-  })
-}
-
-export const getGateStatic = () => {
-  return request({
-    url: '/api/smartapplication/smartdevice/getGateStatic',
-    method: 'get',
-
-  })
-}
-export const getDetail = (id) => {
-  return request({
-    url: '/api/smartapplication/smartdevice/detail',
-    method: 'get',
-    params: {
-      id
-    }
-  })
-}
-
-export const getDetailByDeviceId = (imei) => {
-  return request({
-    url: '/api/smartapplication/smartdevice/detail',
-    method: 'get',
-    params: {
-      imei
-    }
-  })
-}
-
-export const remove = (ids) => {
-  return request({
-    url: '/api/smartapplication/smartdevice/remove',
-    method: 'post',
-    params: {
-      ids,
-    }
-  })
-}
-
-export const add = (row) => {
-  return request({
-    url: '/api/smartapplication/smartdevice/submit',
-    method: 'post',
-    data: row
-  })
-}
-
-export const update = (row) => {
-  return request({
-    url: '/api/smartapplication/smartdevice/submit',
-    method: 'post',
-    data: row
-  })
-}
-
-export const batchBindResidential = (row) => {
-  return request({
-    url: '/api/smartapplication/smartdevice/batchBindResidential',
-    method: 'post',
-    data: row
-  })
-}
-
-export const getDeviceList = (current, size, params) => {
-  return request({
-    url: '/grid/iot/device/list',
-    method: 'get',
-    params: {
-      ...params,
-      current,
-      size,
-    }
-  })
-}

+ 0 - 102
src/api/smartapplication/videoclouddevice.js

@@ -1,102 +0,0 @@
-import request from '@/router/axios';
-
-export const getList = (current, size, params) => {
-  return request({
-    url: '/api/yc_video_cloud_device/videoclouddevice/list',
-    method: 'get',
-    params: {
-      ...params,
-      current,
-      size,
-    }
-  })
-}
-
-export const pageByBuilding = (current, size, params) => {
-  return request({
-    url: '/api/yc_video_cloud_device/videoclouddevice/pageByBuilding',
-    method: 'get',
-    params: {
-      ...params,
-      current,
-      size,
-    }
-  })
-}
-
-export const getListByResidential = (residentialName) => {
-  return request({
-    url: '/api/yc_video_cloud_device/videoclouddevice/getByResidential',
-    method: 'get',
-    params: {
-      residentialName,
-    }
-  })
-}
-
-export const getByResidentialAndDeviceName = (residentialId,buildingId,deviceName) => {
-  return request({
-    url: '/api/yc_video_cloud_device/videoclouddevice/getByResidentialAndDeviceName',
-    method: 'get',
-    params: {
-      residentialId,
-      buildingId,
-      deviceName
-    }
-  })
-}
-export const bindResidentialBatch = (deviceIds,residentialId,buildingId) => {
-  return request({
-    url: '/api/yc_video_cloud_device/videoclouddevice/bindResidentialBatch',
-    method: 'post',
-    params: {
-      deviceIds,
-      residentialId,
-      buildingId
-    }
-  })
-}
-export const getDetail = (id) => {
-  return request({
-    url: '/api/yc_video_cloud_device/videoclouddevice/detail',
-    method: 'get',
-    params: {
-      id
-    }
-  })
-}
-
-export const remove = (ids) => {
-  return request({
-    url: '/api/yc_video_cloud_device/videoclouddevice/remove',
-    method: 'post',
-    params: {
-      ids,
-    }
-  })
-}
-
-export const add = (row) => {
-  return request({
-    url: '/api/yc_video_cloud_device/videoclouddevice/submit',
-    method: 'post',
-    data: row
-  })
-}
-
-export const update = (row) => {
-  return request({
-    url: '/api/yc_video_cloud_device/videoclouddevice/submit',
-    method: 'post',
-    data: row
-  })
-}
-
-
-export const updateVideoDevice = (row) => {
-  return request({
-    url: '/api/yc_video_cloud_device/videoclouddevice/update',
-    method: 'post',
-    data: row
-  })
-}

+ 359 - 0
src/components/device/alarmhistory.vue

@@ -0,0 +1,359 @@
+<template>
+  <basic-container>
+    <avue-crud :option="option" :table-loading="loading" :data="data" :page="page" :permission="permissionList"
+               :before-open="beforeOpen" v-model="form" ref="crud" @row-update="rowUpdate" @row-save="rowSave" @row-del="rowDel"
+               @search-change="searchChange" @search-reset="searchReset" @selection-change="selectionChange" @current-change="currentChange"
+               @size-change="sizeChange" @refresh-change="refreshChange" @on-load="onLoad">
+
+    </avue-crud>
+  </basic-container>
+</template>
+
+<script>
+  // import{
+  //   getDetailByDeviceId
+  // } from "../../api/smartapplication/smartdevice.js";
+  // import {
+  //   getList,
+  //   getDetail,
+  //   add,
+  //   update,
+  //   remove
+  // } from "../../api/homecare/alarmlist.js";
+  import {
+    mapGetters
+  } from "vuex";
+
+
+  export default {
+    props:{
+      imei: "",
+    },
+    data() {
+
+      return {
+        deviceDetail:{},
+        alarmDetail: {},
+        alarmDetailVisible: false,
+        form: {},
+        query: {},
+        loading: true,
+        page: {
+          pageSize: 10,
+          currentPage: 1,
+          total: 0
+        },
+        selectionList: [],
+        option: {
+          menuWidth: 200,
+          height: 'auto',
+          calcHeight: 30,
+          tip: false,
+          menu: false,
+          searchShow: true,
+          searchMenuSpan: 6,
+          border: true,
+          index: true,
+          addBtn: true,
+          selection: true,
+          dialogClickModal: false,
+          column: [
+            {
+              label: "设备sn号",
+              prop: "deviceId",
+              // search: true,
+              width: 130,
+              rules: [{
+                required: false,
+                message: "请输入告警设备sn号",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "设备名称",
+              prop: "deviceName",
+              // search: true,
+              width: 200,
+              overHidden: true,
+              rules: [{
+                required: false,
+                message: "请输入设备名称",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "设备类型",
+              prop: "deviceType",
+              type: "select",
+              // search: true,
+              dicUrl: "/api/blade-system/dict-biz/dictionary?code=device_type",
+              props: {
+                label: "dictValue",
+                value: "dictKey"
+              },
+              dataType: "number",
+              rules: [{
+                required: false,
+                message: "请输入设备类型",
+                trigger: "blur"
+              }]
+            },
+
+            // {
+            //   label: "告警次数",
+            //   prop: "alarmTimes",
+            //   rules: [{
+            //     required: false,
+            //     message: "请输入告警次数",
+            //     trigger: "blur"
+            //   }]
+            // },
+            // {
+            //   label: "告警等级",
+            //   prop: "level",
+            //   type: "select",
+            //   dicUrl: "/api/blade-system/dict-biz/dictionary?code=alarm_level",
+            //   props: {
+            //     label: "dictValue",
+            //     value: "dictKey"
+            //   },
+            //   dataType: "nubmer",
+            //   rules: [{
+            //     required: false,
+            //     message: "请输入告警等级 1:严重告警,2:警告告警,3:提示告警",
+            //     trigger: "blur"
+            //   }]
+            // },
+            // {
+            //   label: "数据",
+            //   prop: "name",
+            //   width: 100,
+            //   rules: [{
+            //     required: false,
+            //     message: "请输入告警原因",
+            //     trigger: "blur"
+            //   }]
+            // },
+            {
+              label: "监测值",
+              prop: "monitorValue",
+              width: 100,
+              rules: [{
+                required: false,
+                message: "请输入监测值",
+                trigger: "blur"
+              }]
+            },
+
+            {
+              label: "告警时间",
+              prop: "recordTime",
+              rules: [{
+                required: false,
+                message: "请输入告警时间",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "最新告警时间",
+              prop: "updateTime",
+              hide: true,
+              rules: [{
+                required: false,
+                message: "请输入最新告警时间",
+                trigger: "blur"
+              }]
+            },
+
+
+            // {
+            //   label: "告警状态",
+            //   prop: "status",
+            //   type: "select",
+            //   dicUrl: "/api/blade-system/dict-biz/dictionary?code=alarm_status",
+            //   props: {
+            //     label: "dictValue",
+            //     value: "dictKey"
+            //   },
+            //   dataType: "number",
+            //   rules: [{
+            //     required: false,
+            //     message: "请输入告警状态,0 实时告警,1-历史告警",
+            //     trigger: "blur"
+            //   }]
+            // },
+            {
+              label: "告警类型",
+              prop: "alarmType",
+              type: "select",
+              dicUrl: "/api/blade-system/dict-biz/dictionary?code=alarm_type",
+              props: {
+                label: "dictValue",
+                value: "dictKey"
+              },
+              dataType: "number",
+              rules: [{
+                required: false,
+                message: "请输入告警类型, 0-业务告警;1-设备告警",
+                trigger: "blur"
+              }]
+            },
+
+          ]
+        },
+        data: []
+      };
+    },
+    computed: {
+      ...mapGetters(["permission"]),
+      permissionList() {
+        return {
+          addBtn: this.vaildData(this.permission.alarmlist_add, false),
+          viewBtn: this.vaildData(this.permission.alarmlist_view, false),
+          delBtn: this.vaildData(this.permission.alarmlist_delete, false),
+          editBtn: this.vaildData(this.permission.alarmlist_edit, false)
+        };
+      },
+      ids() {
+        let ids = [];
+        this.selectionList.forEach(ele => {
+          ids.push(ele.id);
+        });
+        return ids.join(",");
+      }
+    },
+
+    methods: {
+      init(){
+        // this.query.deviceId = this.imei;
+        this.page.currentPage =1;
+        this.page.pageSize =10;
+        this.onLoad(this.page)
+      },
+      ViewAlarmDetail(row) {
+        getDetailByDeviceId(row.deviceId).then(res=>{
+          this.deviceDetail = res.data.data;
+          console.log(res)
+        });
+        this.alarmDetail = row;
+        this.alarmDetailVisible = true;
+      },
+
+      rowSave(row, done, loading) {
+        add(row).then(() => {
+          this.onLoad(this.page);
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          done();
+        }, error => {
+          loading();
+          window.console.log(error);
+        });
+      },
+      rowUpdate(row, index, done, loading) {
+        update(row).then(() => {
+          this.onLoad(this.page);
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          done();
+        }, error => {
+          loading();
+          console.log(error);
+        });
+      },
+      rowDel(row) {
+        this.$confirm("确定将选择数据删除?", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        })
+          .then(() => {
+            return remove(row.id);
+          })
+          .then(() => {
+            this.onLoad(this.page);
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+          });
+      },
+      handleDelete() {
+        if (this.selectionList.length === 0) {
+          this.$message.warning("请选择至少一条数据");
+          return;
+        }
+        this.$confirm("确定将选择数据删除?", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        })
+          .then(() => {
+            return remove(this.ids);
+          })
+          .then(() => {
+            this.onLoad(this.page);
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+            this.$refs.crud.toggleSelection();
+          });
+      },
+      beforeOpen(done, type) {
+        if (["edit", "view"].includes(type)) {
+          getDetail(this.form.id).then(res => {
+            this.form = res.data.data;
+          });
+        }
+        done();
+      },
+      searchReset() {
+        this.query = {};
+        this.onLoad(this.page);
+      },
+      searchChange(params, done) {
+        this.query = params;
+        this.page.currentPage = 1;
+        this.onLoad(this.page, params);
+        done();
+      },
+      selectionChange(list) {
+        this.selectionList = list;
+      },
+      selectionClear() {
+        this.selectionList = [];
+        this.$refs.crud.toggleSelection();
+      },
+      currentChange(currentPage) {
+        this.page.currentPage = currentPage;
+      },
+      sizeChange(pageSize) {
+        this.page.pageSize = pageSize;
+      },
+      refreshChange() {
+        this.onLoad(this.page, this.query);
+      },
+      onLoad(page, params = {}) {
+        this.loading = true;
+        this.query.deviceId = this.imei;
+        console.log("imei:"+this.imei)
+        // this.query.deviceName = "阅海万家"
+        getList(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
+          const data = res.data.data;
+          this.page.total = data.total;
+          this.data = data.records;
+          this.loading = false;
+          this.selectionClear();
+        });
+      }
+    }
+  };
+</script>
+
+<style>
+</style>

+ 197 - 0
src/components/residential/customAvueMap.vue

@@ -0,0 +1,197 @@
+<template>
+  <div style="position: relative;">
+    <div style="display: flex;">
+      <input id="tipinput" class="el-input__inner" placeholder="搜索地址" v-model="address" style="margin-right: 100px;">
+      <!-- <button class="el-button" @click="startEdit" style="margin-bottom: 5px">编辑区域</button> -->
+      <!-- <button class="el-button" @click="closeEdit" style="margin-bottom: 5px">编辑完成</button> -->
+      <!-- <button class="el-button" @click="getPath" style="margin-bottom: 5px">保存</button> -->
+    </div>
+    <div id="container"  style="height: 500px;display: block;position: relative;">
+      <div id="panel" style="position: absolute;top: 0;bottom:0;right: 0;width: 300px;overflow: auto;z-index: 9;"></div>
+    </div>
+  </div>
+</template>
+<script>
+  export default {
+    data() {
+      return {
+        location:{
+          latitude: "39.994257",
+          longitude: "116.471354",
+        },
+        map:null,
+        polyEditor:null,
+        marker:null,
+        polygonPath:[],
+        address:'',
+      }
+    },
+    props:['value','polygonMapData'],
+    model:{
+      prop:'vaule',
+      event:'change'
+    },
+    mounted() {
+      let data = this.polygonMapData
+      if(data){
+        if(data.longitude!==""&&data.latitude!==""){
+          this.location.longitude = data.longitude
+          this.location.latitude = data.latitude
+        }
+        if(data.boundaryPath!==""&&data.boundaryPath!==null&&data.boundaryPath!==undefined){
+          this.polygonPath = JSON.parse(data.boundaryPath)
+        }
+      }
+        this.initMap()
+        this.setMark(this.location)
+        this.initPolygon()
+        this.initSearch()
+    },
+    methods:{
+      initMap(){
+        var _this = this
+        this.map = new AMap.Map('container', {
+          resizeEnable: true, //是否监控地图容器尺寸变化
+          center: [this.location.longitude, this.location.latitude],
+          zoom: 16,
+        });
+        this.map.on('click', function(e) {
+          _this.location['longitude'] = e.lnglat.getLng()
+          _this.location['latitude'] = e.lnglat.getLat()
+          _this.setMark(_this.location)
+        });
+      },
+      setMark(data){
+        var _this = this
+        if(this.marker){
+          this.map.remove(this.marker);
+        }
+        AMap.plugin('AMap.Geocoder', function() {
+          var geocoder = new AMap.Geocoder({})
+          var lnglat = [data.longitude, data.latitude]
+          geocoder.getAddress(lnglat, function(status, result) {
+            if (status === 'complete' && result.info === 'OK') {
+                // result为对应的地理位置详细信息
+                let address = result.regeocode.formattedAddress
+                _this.marker = new AMap.Marker({
+                  position: new AMap.LngLat(data.longitude, data.latitude), // 经纬度对象,也可以是经纬度构成的一维数组[116.39, 39.9]
+                });
+                _this.marker.setLabel({
+                    direction:'center top',
+                    offset: new AMap.Pixel(10, 0),  //设置文本标注偏移量
+                    content: address, //设置文本标注内容
+                });
+                _this.address = address
+                _this.map.add(_this.marker);
+                _this.getPath()
+            }
+          })
+        })
+
+      },
+      initSearch(){
+          var _this = this
+          //输入提示
+          var autoOptions = {
+              input: "tipinput"
+          };
+          AMap.plugin(['AMap.PlaceSearch','AMap.AutoComplete'], function(){
+              var auto = new AMap.AutoComplete(autoOptions);
+              var placeSearch = new AMap.PlaceSearch({
+                  pageSize: 5, // 单页显示结果条数
+                  pageIndex: 1, // 页码
+                  map: _this.map, // 展现结果的地图实例
+                  panel: "panel", // 结果列表将在此容器中进行展示。
+                  autoFitView: true // 是否自动调整地图视野使绘制的 Marker点都处于视口的可见范围
+              });  //构造地点查询类
+              auto.on("select", select);//注册监听,当选中某条记录时会触发
+              function select(e) {
+                  placeSearch.setCity(e.poi.adcode);
+                  placeSearch.search(e.poi.name);  //关键字查询查询
+              }
+          });
+      },
+      initPolygon(){
+        var _this = this;
+        this.polyEditor = new AMap.PolygonEditor(this.map);
+        this.setPolygon(this.polygonPath)
+        this.polyEditor.on('add', function (data) {
+          var polygon = data.target;
+          _this.polyEditor.addAdsorbPolygons(polygon);
+          // polygon.on('click', (res) => {
+          //   console.log(res)
+          //   _this.polyEditor.setTarget(polygon);
+          //   _this.polyEditor.open();
+          // })
+        })
+      } ,
+      setPolygon(data){
+        if(data.length<1)return
+        var _this = this
+            let polygon = new AMap.Polygon({
+              path: data,
+              fillColor: '#ccebc5',
+              strokeOpacity: 1,
+              fillOpacity: 0.5,
+              strokeColor: '#2b8cbe',
+              strokeWeight: 1,
+              strokeStyle: 'dashed',
+              strokeDasharray: [5, 5],
+            });
+            polygon.on('mouseover', () => {
+              polygon.setOptions({
+                fillOpacity: 0.7,
+                fillColor: '#7bccc4'
+              })
+            })
+            polygon.on('mouseout', () => {
+              polygon.setOptions({
+                fillOpacity: 0.5,
+                fillColor: '#ccebc5'
+              })
+            })
+            polygon.on('click', () => {
+              this.polyEditor.open();
+            })
+            this.map.add(polygon);
+            this.map.setFitView();
+            _this.polyEditor.setTarget(polygon)
+      },
+      createPolygon() {
+        this.polyEditor.close();
+        this.polyEditor.setTarget();
+        this.polyEditor.open();
+      },
+      startEdit(){
+        this.polyEditor.open();
+      },
+      closeEdit(){
+        this.polyEditor.close();
+      },
+      getPath(){
+        let target = this.polyEditor.getTarget()
+        let path = ""
+        if(target){
+          path = target._opts.path
+        }
+        if(path!==""&&path!==null&&path!==undefined){
+          path = JSON.stringify(path)
+        }
+        let value = {
+          formattedAddress: this.address,
+          longitude:  this.location['longitude'],
+          latitude: this.location['latitude'],
+          boundaryPath:path
+        }
+        this.$emit('change',value)
+        this.$emit('update:visible', false)
+      }
+    }
+  }
+</script>
+
+<style>
+  .amap-sug-result{
+        z-index: 999999999;
+  }
+</style>

+ 2 - 2
src/main.js

@@ -25,8 +25,8 @@ import avueUeditor from 'avue-plugin-ueditor';
 import website from '@/config/website';
 import crudCommon from '@/mixins/crud';
 import {select} from "./api/base/region";
-import $ from 'jquery'
-import layer from "layui-layer";
+// import $ from 'jquery'
+// import layer from "layui-layer";
 
 // 注册全局crud驱动
 window.$crudCommon = crudCommon;

+ 433 - 0
src/views/device/doordevice.vue

@@ -0,0 +1,433 @@
+<template>
+  <basic-container>
+    <avue-crud :option="option"
+               :table-loading="loading"
+               :data="data"
+               :page="page"
+               :permission="permissionList"
+               :before-open="beforeOpen"
+               v-model="form"
+               ref="crud"
+               @row-update="rowUpdate"
+               @row-save="rowSave"
+               @row-del="rowDel"
+               @search-change="searchChange"
+               @search-reset="searchReset"
+               @selection-change="selectionChange"
+               @current-change="currentChange"
+               @size-change="sizeChange"
+               @refresh-change="refreshChange"
+               @on-load="onLoad">
+      <template slot="menuLeft">
+        <el-button type="danger"
+                   size="small"
+                   icon="el-icon-delete"
+                   plain
+                   v-if="permission.facedevice_delete"
+                   @click="handleDelete">删 除
+        </el-button>
+      </template>
+      <template slot="mapSelectForm" slot-scope="scope">
+        <!-- <avue-map v-model="scope.row.mapSelect"></avue-map> -->
+        <div>
+          <input class="el-input--small el-input__inner" placeholder="选择地址" @click="mapVisible = true">
+
+          <el-dialog :append-to-body="true" :close-on-click-modal="false" :modal-append-to-body="false" :visible.sync="mapVisible"
+                     title="编辑地址" width="80%">
+            <customAvueMap v-if="mapVisible" v-model="scope.row.mapSelect"></customAvueMap>
+          </el-dialog>
+        </div>
+      </template>
+    </avue-crud>
+  </basic-container>
+</template>
+
+<script>
+  import {getList, getDetail, add, update, remove} from "../../api/device/doordevice.js";
+  import {mapGetters} from "vuex";
+  import customAvueMap from "../../components/residential/customAvueMap.vue"
+  export default {
+    components:{
+      customAvueMap
+    },
+    data() {
+      return {
+        mapVisible:false,
+        form: {},
+        query: {},
+        loading: true,
+        page: {
+          pageSize: 10,
+          currentPage: 1,
+          total: 0
+        },
+        selectionList: [],
+        option: {
+          height:'auto',
+          calcHeight: 60,
+          tip: false,
+          searchShow: true,
+          searchMenuSpan: 6,
+          border: true,
+          index: true,
+          viewBtn: true,
+          selection: true,
+          dialogClickModal: false,
+          column: [
+            {
+              label: "门禁设备",
+              prop: "id",
+              hide: true,
+              display:false,
+              rules: [{
+                required: true,
+                message: "请输入门禁设备",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "设备编号",
+              prop: "cameraCode",
+              width: 135,
+              rules: [{
+                required: true,
+                message: "请输入设备编号",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "名称",
+              prop: "cameraName",
+              search: true,
+              width: 130,
+              overHidden: true,
+              rules: [{
+                required: true,
+                message: "请输入名称",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "所属省",
+              prop: "provinceCode",
+              hide: true,
+              width: 150,
+              type: "select",
+              dicUrl: "/api/blade-system/region/lazy-tree?parentCode=000000",
+              cascaderItem:["cityCode"],
+              props:{
+                label:"title",
+                value: "id"
+              },
+              rules: [{
+                required: true,
+                message: "请输入省行政编码",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "所属市",
+              prop: "cityCode",
+              hide: true,
+              type: "select",
+              width: 100,
+              cascaderItem: ["areaCode"],
+              ddicUrl: `/api/blade-system/region/lazy-tree?parentCode={{key}}`,
+
+              props:{
+                label: "title",
+                value: "id"
+              },
+              dicFlag: false,
+
+              rules: [{
+                required: true,
+                message: "请输入市行政编码",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "所属区",
+              prop: "areaCode",
+              type: "select",
+              width: 100,
+              dicFlag: false,
+              cascaderItem: ["residentialId"],
+              dicUrl: `/api/blade-system/region/lazy-tree?parentCode={{key}}`,
+
+              props:{
+                label: "title",
+                value: "id"
+              },
+              rules: [{
+                required: true,
+                message: "请输入区行政编码",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "所属小区",
+              prop: "residentialId",
+              type: "select",
+              width: 100,
+              dicUrl: "/api/cyzh-community/residential/list?size=90000&regionArea={{key}}",
+              filterable: true,
+              dicFlag: false,
+              // cascaderItem: ["residentialId"],
+              props: {
+                label: "name",
+                value: "id"
+              },
+              dicFormatter: (res) => {
+                return res.data.records;
+              },
+              rules: [{
+                required: true,
+                message: "请输入所属小区",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "具体地址",
+              prop: "address",
+              width: 180,
+              search: true,
+              overHidden: true,
+              rules: [{
+                required: true,
+                message: "请输入具体地址",
+                trigger: "blur"
+              }]
+            },
+
+            {
+              label: "Mac编码",
+              prop: "macAddress",
+              width: 110,
+              rules: [{
+                required: true,
+                message: "请输入Mac编码",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "创建时间",
+              prop: "createTime",
+              display: false,
+              width: 150,
+              rules: [{
+                required: true,
+                message: "请输入创建时间",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "设备状态",
+              prop: "deviceStatus",
+              type: "select",
+              width: 80,
+              dicUrl:"/api/blade-system/dict-biz/dictionary?code=face_device_status",
+              props: {
+                label: 'dictValue',
+                value: 'dictKey'
+              },
+              dataType: "number",
+              rules: [{
+                required: true,
+                message: "请输入设备状态:0-离线 2-mac异常",
+                trigger: "blur"
+              }]
+            },
+            {
+              label:'',
+              prop:'mapSelect',
+              // row: true,
+              // span: 20,
+              formslot: true,
+              hide: true,
+            },
+            {
+              label: "经度",
+              prop: "longitude",
+              width: 100,
+              overHidden: true,
+              rules: [{
+                required: true,
+                message: "请输入经度",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "纬度",
+              prop: "latitude",
+              width: 100,
+              overHidden: true,
+              rules: [{
+                required: true,
+                message: "请输入纬度",
+                trigger: "blur"
+              }]
+            },
+
+
+
+          ]
+        },
+        data: []
+      };
+    },
+    computed: {
+      ...mapGetters(["permission"]),
+      permissionList() {
+        return {
+          addBtn: this.vaildData(this.permission.doordevice_add, false),
+          viewBtn: this.vaildData(this.permission.doordevice_view, false),
+          delBtn: this.vaildData(this.permission.doordevice_delete, false),
+          editBtn: this.vaildData(this.permission.doordevice_edit, false)
+        };
+      },
+      ids() {
+        let ids = [];
+        this.selectionList.forEach(ele => {
+          ids.push(ele.id);
+        });
+        return ids.join(",");
+      }
+    },
+    watch: {
+      'form.mapSelect': {
+        handler: function(value) {
+          if (!value){
+            return
+          }else{
+            this.form.longitude = this.form.mapSelect.longitude;
+            this.form.latitude = this.form.mapSelect.latitude;
+          }
+        },
+      }
+    },
+    mounted() {
+      let tenantType = localStorage.getItem("tenantType");
+      const residentialColumn = this.findObject(this.option.column, "residentialId");
+      if (tenantType == 1) { //园区
+        residentialColumn.label = "所属区域";
+      } else { //社区
+        residentialColumn.label = "所属小区";
+      }
+    },
+    methods: {
+      rowSave(row, done, loading) {
+        add(row).then(() => {
+          this.onLoad(this.page);
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          done();
+        }, error => {
+          loading();
+          window.console.log(error);
+        });
+      },
+      rowUpdate(row, index, done, loading) {
+        update(row).then(() => {
+          this.onLoad(this.page);
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          done();
+        }, error => {
+          loading();
+          console.log(error);
+        });
+      },
+      rowDel(row) {
+        this.$confirm("确定将选择数据删除?", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        })
+          .then(() => {
+            return remove(row.id);
+          })
+          .then(() => {
+            this.onLoad(this.page);
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+          });
+      },
+      handleDelete() {
+        if (this.selectionList.length === 0) {
+          this.$message.warning("请选择至少一条数据");
+          return;
+        }
+        this.$confirm("确定将选择数据删除?", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        })
+          .then(() => {
+            return remove(this.ids);
+          })
+          .then(() => {
+            this.onLoad(this.page);
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+            this.$refs.crud.toggleSelection();
+          });
+      },
+      beforeOpen(done, type) {
+        if (["edit", "view"].includes(type)) {
+          getDetail(this.form.id).then(res => {
+            this.form = res.data.data;
+          });
+        }
+        done();
+      },
+      searchReset() {
+        this.query = {};
+        this.onLoad(this.page);
+      },
+      searchChange(params, done) {
+        this.query = params;
+        this.page.currentPage = 1;
+        this.onLoad(this.page, params);
+        done();
+      },
+      selectionChange(list) {
+        this.selectionList = list;
+      },
+      selectionClear() {
+        this.selectionList = [];
+        this.$refs.crud.toggleSelection();
+      },
+      currentChange(currentPage){
+        this.page.currentPage = currentPage;
+      },
+      sizeChange(pageSize){
+        this.page.pageSize = pageSize;
+      },
+      refreshChange() {
+        this.onLoad(this.page, this.query);
+      },
+      onLoad(page, params = {}) {
+        this.loading = true;
+        getList(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
+          const data = res.data.data;
+          this.page.total = data.total;
+          this.data = data.records;
+          this.loading = false;
+          this.selectionClear();
+        });
+      }
+    }
+  };
+</script>
+
+<style>
+</style>

+ 371 - 0
src/views/device/elevatoralarm.vue

@@ -0,0 +1,371 @@
+<template>
+  <basic-container>
+    <avue-crud :option="option"
+               :table-loading="loading"
+               :data="data"
+               :page="page"
+               :permission="permissionList"
+               :before-open="beforeOpen"
+               v-model="form"
+               ref="crud"
+               @row-update="rowUpdate"
+               @row-save="rowSave"
+               @row-del="rowDel"
+               @search-change="searchChange"
+               @search-reset="searchReset"
+               @selection-change="selectionChange"
+               @current-change="currentChange"
+               @size-change="sizeChange"
+               @refresh-change="refreshChange"
+               @on-load="onLoad">
+      <template slot="menuLeft">
+        <el-button type="danger"
+                   size="small"
+                   icon="el-icon-delete"
+                   plain
+                   v-if="permission.elevatoralarm_delete"
+                   @click="handleDelete">删 除
+        </el-button>
+      </template>
+      <template slot="menu" slot-scope="{row}">
+        <el-button icon="el-icon-video-camera" v-if="'1000007,1000010,1000018,1000050'.indexOf(row.alarmType) != -1" type="text" @click="getAlarmVideoData(row)">查看告警视频</el-button>
+      </template>
+    </avue-crud>
+
+    <!--  告警视频  -->
+    <el-dialog :append-to-body="true" :close-on-click-modal="false" :modal-append-to-body="false" width="40%" top="1vh"
+               :title="videoAlarmName" :visible.sync="videoAlarmVisible" @close="videoClose">
+      <video id="videoAlarm" autoplay  style="background-color: black; width:100%;height:100%"></video>
+    </el-dialog>
+
+  </basic-container>
+</template>
+
+<script>
+  import {getList, getDetail, add, update, remove} from "@/api/device/elevatoralarm";
+  import {getAlarmVideo} from "@/api/device/elevatoralarm";
+  import {mapGetters} from "vuex";
+  import {startPlay, stopPlay} from "@/api/device/elevatorUtil";
+
+  export default {
+    name: "elevatorAlarm",
+    data() {
+      return {
+        form: {},
+        query: {},
+        videoAlarmName: '',
+        videoAlarmVisible: false,
+        player: null,
+        loading: true,
+        page: {
+          pageSize: 10,
+          currentPage: 1,
+          total: 0
+        },
+        selectionList: [],
+        option: {
+          height:'auto',
+          calcHeight: 30,
+          tip: false,
+          searchShow: true,
+          searchMenuSpan: 6,
+          border: true,
+          index: true,
+          viewBtn: true,
+          selection: true,
+          dialogClickModal: false,
+          column: [
+            /*{
+              label: "告警编号",
+              prop: "alarmCode",
+              rules: [{
+                required: true,
+                message: "请输入告警编号",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "电梯注册编码",
+              prop: "registerCode",
+              rules: [{
+                required: true,
+                message: "请输入电梯注册编码",
+                trigger: "blur"
+              }]
+            },*/
+            {
+              label: "小区名称",
+              prop: "residentialName",
+              // search: true,
+              // searchSpan: 4,
+
+            },
+            {
+              label: "小区",
+              prop: "residentialId",
+              type: "select",
+              hide: true,
+              search: true,
+              searchSpan: 4,
+              searchFilterable: true,
+              // remote: true,
+              //回显的时候有问题,如果所选不在前十条内,下拉框只会显示id
+              dicUrl: "/api/cyzh-community/residential/list?size=1000&name={{key}}",
+              // dicUrl: "/api/community/elevator/elevator/getListWithYtelevatorXq",
+              props:{
+                label: "name",
+                value: "id"
+              },
+            },
+            {
+              label: "告警大类",
+              prop: "standardType",
+              type: "select",
+              search: true,
+              searchSpan: 4,
+              dicUrl: "/api/blade-system/dict-biz/dictionary?code=yt_standard_type",
+              props:{
+                label: "dictValue",
+                value: "dictKey",
+              },
+              rules: [{
+                required: true,
+                message: "请输入告警大类{9000001:报警 ,9000002:故障, 9000004:事件}",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "告警类型",
+              prop: "alarmType",
+              type: "select",
+              search: true,
+              searchSpan: 4,
+              dicUrl: "/api/blade-system/dict-biz/dictionary?code=yt_alarm_type",
+              props:{
+                label: "dictValue",
+                value: "dictKey",
+              },
+              rules: [{
+                required: true,
+                message: "请输入告警类型",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "告警状态",
+              prop: "alarmStatus",
+              type: "select",
+              search: true,
+              searchSpan: 4,
+              dicUrl: "/api/blade-system/dict-biz/dictionary?code=yt_alarm_status",
+              dataType: "number",
+              props:{
+                label: "dictValue",
+                value: "dictKey",
+              },
+              rules: [{
+                required: true,
+                message: "请输入告警状态{1:告警中,6:自动结束,7:超期结束,8:自动处理}",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "告警时间",
+              prop: "alarmTime",
+              rules: [{
+                required: true,
+                message: "请输入告警时间",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "告警结束时间",
+              prop: "alarmEndTime",
+              rules: [{
+                required: true,
+                message: "请输入告警结束时间",
+                trigger: "blur"
+              }]
+            },
+
+            {
+              label: "云梯状态",
+              prop: "ytStatus",
+              type: "select",
+              search: true,
+              searchSpan: 4,
+              dicUrl: "/api/blade-system/dict-biz/dictionary?code=yt_status",
+              props:{
+                label: "dictValue",
+                value: "dictKey",
+              },
+              rules: [{
+                required: true,
+                message: "请输入云梯告警状态{20:正常,40:演示,50:测试}",
+                trigger: "blur"
+              }]
+            },
+          ]
+        },
+        data: []
+      };
+    },
+    computed: {
+      ...mapGetters(["permission"]),
+      permissionList() {
+        return {
+          addBtn: this.vaildData(this.permission.elevatoralarm_add, false),
+          viewBtn: this.vaildData(this.permission.elevatoralarm_view, false),
+          delBtn: this.vaildData(this.permission.elevatoralarm_delete, false),
+          editBtn: this.vaildData(this.permission.elevatoralarm_edit, false)
+        };
+      },
+      ids() {
+        let ids = [];
+        this.selectionList.forEach(ele => {
+          ids.push(ele.id);
+        });
+        return ids.join(",");
+      }
+    },
+    props:["registerCode"],
+    methods: {
+      videoClose(){
+        stopPlay(this.player);
+      },
+      getAlarmVideoData(row){
+        let alarmCode = row.alarmCode;
+        this.videoAlarmName = row.$alarmType;
+        this.videoAlarmVisible = true;
+        alarmCode && getAlarmVideo(alarmCode).then(res => {
+          if (res.data.code == 200 && res.data.data.code == 0){
+            let videoUrl = res.data.data.data.urlSec;
+            this.videoDetail(videoUrl);
+          }
+        });
+
+      },
+      videoDetail(videoUrl){
+
+        let elementId = 'videoAlarm';
+        this.player = startPlay(elementId, videoUrl, this.player);
+      },
+      rowSave(row, done, loading) {
+        add(row).then(() => {
+          this.onLoad(this.page);
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          done();
+        }, error => {
+          loading();
+          window.console.log(error);
+        });
+      },
+      rowUpdate(row, index, done, loading) {
+        update(row).then(() => {
+          this.onLoad(this.page);
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          done();
+        }, error => {
+          loading();
+          console.log(error);
+        });
+      },
+      rowDel(row) {
+        this.$confirm("确定将选择数据删除?", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        })
+          .then(() => {
+            return remove(row.id);
+          })
+          .then(() => {
+            this.onLoad(this.page);
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+          });
+      },
+      handleDelete() {
+        if (this.selectionList.length === 0) {
+          this.$message.warning("请选择至少一条数据");
+          return;
+        }
+        this.$confirm("确定将选择数据删除?", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        })
+          .then(() => {
+            return remove(this.ids);
+          })
+          .then(() => {
+            this.onLoad(this.page);
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+            this.$refs.crud.toggleSelection();
+          });
+      },
+      beforeOpen(done, type) {
+        if (["edit", "view"].includes(type)) {
+          getDetail(this.form.id).then(res => {
+            this.form = res.data.data;
+          });
+        }
+        done();
+      },
+      searchReset() {
+        this.query = {};
+        this.onLoad(this.page);
+      },
+      searchChange(params, done) {
+        this.query = params;
+        this.page.currentPage = 1;
+        this.onLoad(this.page, params);
+        done();
+      },
+      selectionChange(list) {
+        this.selectionList = list;
+      },
+      selectionClear() {
+        this.selectionList = [];
+        this.$refs.crud.toggleSelection();
+      },
+      currentChange(currentPage){
+        this.page.currentPage = currentPage;
+      },
+      sizeChange(pageSize){
+        this.page.pageSize = pageSize;
+      },
+      refreshChange() {
+        this.onLoad(this.page, this.query);
+      },
+      onLoad(page, params = {}) {
+        this.loading = true;
+        params.registerCode = this.registerCode;
+        if (params.registerCode){
+          this.option.column[1].search = false;
+        }
+        getList(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
+          const data = res.data.data;
+          this.page.total = data.total;
+          this.data = data.records;
+          this.loading = false;
+          this.selectionClear();
+        });
+      }
+    }
+  };
+</script>
+
+<style>
+</style>

+ 236 - 0
src/views/device/elevatoralarmdirector.vue

@@ -0,0 +1,236 @@
+<template>
+  <basic-container>
+    <avue-crud :option="option"
+               :table-loading="loading"
+               :data="data"
+               :page="page"
+               :permission="permissionList"
+               :before-open="beforeOpen"
+               v-model="form"
+               ref="crud"
+               @row-update="rowUpdate"
+               @row-save="rowSave"
+               @row-del="rowDel"
+               @search-change="searchChange"
+               @search-reset="searchReset"
+               @selection-change="selectionChange"
+               @current-change="currentChange"
+               @size-change="sizeChange"
+               @refresh-change="refreshChange"
+               @on-load="onLoad">
+      <template slot="menuLeft">
+        <el-button type="danger"
+                   size="small"
+                   icon="el-icon-delete"
+                   plain
+                   v-if="permission.alarmdirector_delete"
+                   @click="handleDelete">删 除
+        </el-button>
+      </template>
+    </avue-crud>
+  </basic-container>
+</template>
+
+<script>
+  import {getList, getDetail, add, update, remove} from "@/api/device/elevatoralarmdirector";
+  import {mapGetters} from "vuex";
+
+  export default {
+    name: 'alarmDirector',
+    data() {
+      return {
+        form: {},
+        query: {},
+        loading: true,
+        page: {
+          pageSize: 10,
+          currentPage: 1,
+          total: 0
+        },
+        selectionList: [],
+        option: {
+          height:'auto',
+          calcHeight: 130,
+          tip: false,
+          searchShow: true,
+          searchMenuSpan: 6,
+          border: true,
+          index: true,
+          viewBtn: true,
+          selection: true,
+          dialogClickModal: false,
+          column: [
+            {
+              label: "小区名称",
+              prop: "residentialName",
+              addDisplay: false,
+              editDisplay: false,
+              rules: [{
+                required: true,
+                message: "请输入小区名称",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "负责人姓名",
+              prop: "personName",
+              rules: [{
+                required: true,
+                message: "请输入负责人姓名",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "负责人电话",
+              prop: "personTel",
+              rules: [{
+                required: true,
+                message: "请输入负责人电话",
+                trigger: "blur"
+              }]
+            },
+          ]
+        },
+        data: []
+      };
+    },
+    computed: {
+      ...mapGetters(["permission"]),
+      permissionList() {
+        return {
+          addBtn: this.vaildData(this.permission.alarmdirector_add, false),
+          viewBtn: this.vaildData(this.permission.alarmdirector_view, false),
+          delBtn: this.vaildData(this.permission.alarmdirector_delete, false),
+          editBtn: this.vaildData(this.permission.alarmdirector_edit, false)
+        };
+      },
+      ids() {
+        let ids = [];
+        this.selectionList.forEach(ele => {
+          ids.push(ele.id);
+        });
+        return ids.join(",");
+      }
+    },
+    props: ["residentialId"],
+    mounted() {
+      this.residentialId;
+    },
+    methods: {
+      rowSave(row, done, loading) {
+        row.residentialId = this.residentialId;
+        add(row).then(() => {
+          this.onLoad(this.page);
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          done();
+        }, error => {
+          loading();
+          window.console.log(error);
+        });
+      },
+      rowUpdate(row, index, done, loading) {
+        update(row).then(() => {
+          this.onLoad(this.page);
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          done();
+        }, error => {
+          loading();
+          console.log(error);
+        });
+      },
+      rowDel(row) {
+        this.$confirm("确定将选择数据删除?", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        })
+          .then(() => {
+            return remove(row.id);
+          })
+          .then(() => {
+            this.onLoad(this.page);
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+          });
+      },
+      handleDelete() {
+        if (this.selectionList.length === 0) {
+          this.$message.warning("请选择至少一条数据");
+          return;
+        }
+        this.$confirm("确定将选择数据删除?", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        })
+          .then(() => {
+            return remove(this.ids);
+          })
+          .then(() => {
+            this.onLoad(this.page);
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+            this.$refs.crud.toggleSelection();
+          });
+      },
+      beforeOpen(done, type) {
+        if (["edit", "view"].includes(type)) {
+          getDetail(this.form.id).then(res => {
+            this.form = res.data.data;
+          });
+        }
+        done();
+      },
+      searchReset() {
+        this.query = {};
+        this.onLoad(this.page);
+      },
+      searchChange(params, done) {
+        this.query = params;
+        this.page.currentPage = 1;
+        this.onLoad(this.page, params);
+        done();
+      },
+      selectionChange(list) {
+        this.selectionList = list;
+      },
+      selectionClear() {
+        this.selectionList = [];
+        this.$refs.crud.toggleSelection();
+      },
+      currentChange(currentPage){
+        this.page.currentPage = currentPage;
+      },
+      sizeChange(pageSize){
+        this.page.pageSize = pageSize;
+      },
+      refreshChange() {
+        this.onLoad(this.page, this.query);
+      },
+      onLoad(page, params = {}) {
+        this.loading = true;
+        params.residentialId = this.residentialId;
+        getList(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
+          const data = res.data.data;
+          this.page.total = data.total;
+          this.data = data.records;
+          this.loading = false;
+          this.selectionClear();
+        });
+      }
+    }
+  };
+</script>
+
+<style>
+</style>

+ 462 - 0
src/views/device/elevatoralarmsetting.vue

@@ -0,0 +1,462 @@
+<template>
+  <basic-container>
+
+    <el-tabs :value="level" @tab-click="handleClickType">
+      <el-tab-pane></el-tab-pane>
+      <el-tab-pane label="全局设置" name="1">
+        <div v-if="activeTab == '1'">
+          <avue-crud :option="option"
+                     :table-loading="loading"
+                     :data="data"
+                     :page="page"
+                     :permission="permissionList"
+                     ref="crud"
+                     @search-change="searchChange"
+                     @search-reset="searchReset"
+                     @selection-change="selectionChange"
+                     @current-change="currentChange"
+                     @size-change="sizeChange"
+                     @refresh-change="refreshChange"
+                     @on-load="onLoad">
+            <template slot="menuLeft">
+              <el-button type="danger" v-if="permission.alarmsetting_add" plain size="small" @click="init(row, true)">初始化数据</el-button>
+            </template>
+            <template slot="isNotice" slot-scope="{row}">
+              <el-switch v-model="row.isNotice" :disabled="!permission.alarmsetting_edit" @change="changeNotice(row)">
+              </el-switch>
+            </template>
+          </avue-crud>
+        </div>
+      </el-tab-pane>
+      <el-tab-pane label="小区设置" name="2">
+        <div v-if="activeTab == '2'">
+          <avue-crud :data="xqSettingData" :option="xqOption"
+                     :page="xqpage"
+                     v-model="form"
+                     :before-open="beforeOpen"
+                     @row-update="rowUpdate"
+                     @row-save="rowSave"
+                     @row-del="rowDel"
+                     @current-change="currentChangeXq"
+                     @size-change="sizeChangeXq"
+                     @refresh-change="refreshChangeXq"
+                     @on-load="loadXqSetting"
+          >
+            <template slot="menuLeft">
+              <div style="display: flex;">
+                <el-select filterable v-model="selectXqId" size="small" placeholder="请选择" @change="selectResidential">
+                  <el-option
+                    v-for="(item, idx) in ytXqList"
+                    :key="idx"
+                    :label="item.name"
+                    :value="item.id">
+                  </el-option>
+                </el-select>
+                <el-button type="danger" style="margin-left: 20px;" v-if="permission.alarmdirector_add && ytXqList.length > 0" plain size="small" @click="initXqSetting">初始化告警设置</el-button>
+                <el-button type="primary" style="margin-left: 20px;" v-if="permission.alarmdirector_add && ytXqList.length > 0" plain size="small" @click="settingDirector">告警负责人</el-button>
+              </div>
+
+            </template>
+
+            <template slot="isNotice" slot-scope="{row}">
+              <el-switch v-model="row.isNotice" :disabled="!permission.alarmsetting_edit" @change="changeNotice(row)">
+              </el-switch>
+            </template>
+            <template slot="isGenerateJob" slot-scope="{row}">
+              <el-switch v-model="row.isGenerateJob" :disabled="!permission.alarmsetting_edit" @change="changeGenerateJob(row)">
+              </el-switch>
+            </template>
+          </avue-crud>
+        </div>
+      </el-tab-pane>
+    </el-tabs>
+
+    <el-dialog :modal-append-to-body="false" append-to-body :visible.sync="directorVisible" title="告警负责人" top="2vh" center width="70%" height="80%">
+      <alarm-director v-if="directorVisible" :residential-id="selectXqId"></alarm-director>
+    </el-dialog>
+
+  </basic-container>
+</template>
+
+<script>
+  import {getList, getDetail, add, update, remove, initData, initDataWithResidential, getAlarmTypeSelect} from "@/api/device/elevatoralarmsetting";
+  import {mapGetters} from "vuex";
+  import {getListWithYtelevatorXq} from "@/api/device/elevatordevice";
+  import AlarmDirector from "./elevatoralarmdirector";
+
+  export default {
+    components: {AlarmDirector},
+    data() {
+      return {
+        ytXqList: [],
+        selectXqId: '',
+        activeTab: '1',
+        directorVisible: false,
+
+        form: {},
+        query: {},
+        loading: true,
+        level: "1",
+        page: {
+          pageSize: 10,
+          currentPage: 1,
+          total: 0
+        },
+        selectionList: [],
+        option: {
+          height:'auto',
+          calcHeight: 220,
+          tip: false,
+          searchShow: true,
+          searchMenuSpan: 6,
+          border: true,
+          index: true,
+          viewBtn: false,
+          addBtn: false,
+          editBtn: false,
+          delBtn: false,
+          menu: false,
+          selection: true,
+          dialogClickModal: false,
+          column: [
+            {
+              label: "电梯告警类型",
+              prop: "alarmType",
+            },
+            {
+              label: "电梯告警名称",
+              prop: "alarmName",
+            },
+            {
+              label: "是否开启告警通知",
+              prop: "isNotice",
+              type:'switch',
+              slot: true,
+              // cell: true
+            },
+          ]
+        },
+        data: [],
+        xqquery: {},
+        xqform: {},
+        xqpage: {
+          pageSize: 10,
+          currentPage: 1,
+          total: 0
+        },
+        xqselectionList: [],
+        xqSettingData: [],
+        xqOption: {
+          height:'auto',
+          calcHeight: 220,
+          tip: false,
+          searchShow: true,
+          searchMenuSpan: 6,
+          border: true,
+          index: true,
+          viewBtn: false,
+          addBtn: true,
+          menu: true,
+          editBtn: false,
+          delBtn: true,
+          selection: true,
+          dialogClickModal: false,
+          column: [
+            {
+              label: "小区名称",
+              prop: "residentialName",
+              addDisplay: false,
+            },
+            {
+              label: "告警类型",
+              prop: "alarmType",
+              type: "select",
+              dicData: [],
+              props: {
+                label: "dictValue",
+                value: "dictKey"
+              },
+            },
+            {
+              label: "告警名称",
+              prop: "alarmName",
+              addDisplay: false
+            },
+            {
+              label: "开启告警通知",
+              prop: "isNotice",
+              type:'switch',
+              slot: true,
+              labelWidth: "200",
+              addDisplay: false,
+            },
+            {
+              label: "开启告警生成工单",
+              prop: "isGenerateJob",
+              hide: true,
+              type:'switch',
+              addDisplay: false,
+              slot: true,
+              // cell: true
+            },
+          ]
+        }
+      };
+    },
+    computed: {
+      ...mapGetters(["permission"]),
+      permissionList() {
+        return {
+          addBtn: this.vaildData(this.permission.alarmsetting_add, false),
+          viewBtn: this.vaildData(this.permission.alarmsetting_view, false),
+          delBtn: this.vaildData(this.permission.alarmsetting_delete, false),
+          editBtn: this.vaildData(this.permission.alarmsetting_edit, false)
+        };
+      },
+      ids() {
+        let ids = [];
+        this.selectionList.forEach(ele => {
+          ids.push(ele.id);
+        });
+        return ids.join(",");
+      }
+    },
+    methods: {
+      settingDirector(){
+        this.directorVisible = true;
+      },
+      selectResidential(){
+        // 加载列表
+        this.loadXqSetting(this.xqpage);
+        this.initAlarmTypeSelect();
+      },
+      initAlarmTypeSelect(){
+        this.selectXqId && getAlarmTypeSelect(this.selectXqId).then(res => {
+          let alarmSelect = res.data.data;
+          this.xqOption.column[1].dicData = alarmSelect;
+        });
+      },
+      initXqSetting(){
+        this.selectXqId &&
+        initDataWithResidential(this.selectXqId).then(() => {
+          this.$message({
+            type: "success",
+            message: "数据初始化成功!"
+          });
+          // 加载列表
+          this.loadXqSetting(this.xqpage);
+        });
+      },
+      loadXqSetting(page, params = {}){
+        params = {};
+        this.loading = true;
+        params.level = 2;
+        params.residentialId = this.selectXqId;
+        this.selectXqId && getList(page.currentPage, page.pageSize, Object.assign(params, this.xqquery)).then(res => {
+          const data = res.data.data;
+          this.xqpage.total = data.total;
+          data.records.forEach(item => {
+            // item.$cellEdit = false;
+            item.isNotice = item.isNotice == 1;
+            item.isGenerateJob = item.isGenerateJob == 1;
+          })
+          this.xqSettingData = data.records;
+          this.loading = false;
+          // this.selectionClear();
+        });
+      },
+      handleClickType(tab){
+        this.activeTab = tab.name;
+        if (tab.name == '1'){
+          //全局配置
+        }else {
+          //小区局部配置
+          if (this.ytXqList.length <= 0){
+            getListWithYtelevatorXq().then(res => {
+              this.ytXqList = res.data.data;
+              if (this.ytXqList && this.ytXqList.length > 0){
+                this.selectXqId = this.ytXqList[0].id;
+                this.loadXqSetting(this.xqpage);
+              }
+            });
+          }else{
+            if (this.ytXqList && this.ytXqList.length > 0){
+              this.selectXqId = this.ytXqList[0].id;
+              this.loadXqSetting(this.xqpage);
+            }
+          }
+
+        }
+      },
+      init(){
+        initData().then(() => {
+          this.$message({
+            type: "success",
+            message: "数据初始化成功!"
+          });
+          this.onLoad(this.page)
+        });
+      },
+      changeNotice(row) {
+        row.isNotice = row.isNotice ? 1 : 0;
+        if (row.level == 2){
+          row.isGenerateJob = row.isGenerateJob ? 1 : 0;
+        }
+        update(row).then(() => {
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          row.level == 1 ? this.onLoad(this.page) : this.loadXqSetting(this.xqpage);
+        }, error => {
+          console.log(error);
+        });
+      },
+      changeGenerateJob(row) {
+        row.isNotice = row.isNotice ? 1 : 0;
+        row.isGenerateJob = row.isGenerateJob ? 1 : 0;
+        update(row).then(() => {
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          this.loadXqSetting(this.xqpage);
+        }, error => {
+          console.log(error);
+        });
+      },
+      rowSave(row, done, loading) {
+        row.alarmName = row.$alarmType;
+        row.residentialId = this.selectXqId;
+        row.level = 2;
+        add(row).then(() => {
+          this.loadXqSetting(this.xqpage);
+          this.xqOption.column[1].dicData = [];
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          done();
+        }, error => {
+          loading();
+          window.console.log(error);
+        });
+      },
+      rowUpdate(row, index, done, loading) {
+        update(row).then(() => {
+          this.onLoad(this.page);
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          done();
+        }, error => {
+          loading();
+          console.log(error);
+        });
+      },
+      rowDel(row) {
+        this.$confirm("确定将选择数据删除?", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        })
+          .then(() => {
+            return remove(row.id);
+          })
+          .then(() => {
+            this.loadXqSetting(this.xqpage);
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+          });
+      },
+      handleDelete() {
+        if (this.selectionList.length === 0) {
+          this.$message.warning("请选择至少一条数据");
+          return;
+        }
+        this.$confirm("确定将选择数据删除?", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        })
+          .then(() => {
+            return remove(this.ids);
+          })
+          .then(() => {
+            this.onLoad(this.page);
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+            this.$refs.crud.toggleSelection();
+          });
+      },
+      beforeOpen(done, type) {
+        // 初始化告警类型select(未有配置的类型)
+        this.initAlarmTypeSelect();
+        if (["edit", "view"].includes(type)) {
+          getDetail(this.form.id).then(res => {
+            this.form = res.data.data;
+          });
+        }
+        done();
+      },
+      searchReset() {
+        this.query = {};
+        this.onLoad(this.page);
+      },
+      searchChange(params, done) {
+        this.query = params;
+        this.page.currentPage = 1;
+        this.onLoad(this.page, params);
+        done();
+      },
+      selectionChange(list) {
+        this.selectionList = list;
+      },
+      selectionClear() {
+        this.selectionList = [];
+        this.$refs.crud.toggleSelection();
+      },
+      currentChange(currentPage){
+        this.page.currentPage = currentPage;
+      },
+      sizeChange(pageSize){
+        this.page.pageSize = pageSize;
+      },
+      refreshChange() {
+        this.onLoad(this.xqpage, this.xqquery);
+      },
+      currentChangeXq(currentPage){
+        this.xqpage.currentPage = currentPage;
+      },
+      sizeChangeXq(pageSize){
+        this.xqpage.pageSize = pageSize;
+      },
+      refreshChangeXq() {
+        this.loadXqSetting(this.xqpage, this.xqquery);
+      },
+      onLoad(page, params = {}) {
+        this.loading = true;
+        params.level = 1;
+        getList(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
+          const data = res.data.data;
+          this.page.total = data.total;
+          data.records.forEach(item => {
+            // item.$cellEdit = false;
+            item.isNotice = item.isNotice == 1;
+          })
+          this.data = data.records;
+          this.loading = false;
+          this.selectionClear();
+        });
+      }
+    }
+  };
+</script>
+
+<style>
+</style>

+ 407 - 0
src/views/device/elevatordevice.vue

@@ -0,0 +1,407 @@
+<template>
+  <basic-container>
+    <avue-crud :option="option"
+               :table-loading="loading"
+               :data="data"
+               :page="page"
+               :permission="permissionList"
+               :before-open="beforeOpen"
+               v-model="form"
+               ref="crud"
+               @row-update="rowUpdate"
+               @row-save="rowSave"
+               @row-del="rowDel"
+               @search-change="searchChange"
+               @search-reset="searchReset"
+               @selection-change="selectionChange"
+               @current-change="currentChange"
+               @size-change="sizeChange"
+               @refresh-change="refreshChange"
+               @on-load="onLoad">
+
+      <template slot="menuLeft">
+        <el-button type="success" size="small" icon="el-icon-refresh" plain
+                   v-if="permission.elevator_sync"
+                   @click="handleSync">同 步
+        </el-button>
+      </template>
+
+      <template slot="menu" slot-scope="scope">
+        <el-button v-if="permission.elevator_bind" icon="el-icon-paperclip" :class="{changeBind: !!scope.row.residentialId}" type="text" @click="showDeviceBind(scope.row)">{{!scope.row.residentialId ? '小区绑定' : '小区改绑'}}</el-button>
+      </template>
+
+    </avue-crud>
+
+    <!--    小区列表-->
+    <el-dialog :modal-append-to-body="false" append-to-body :visible.sync="bindVisible" title="小区绑定" center width="20%">
+      <div style="text-align: center;">
+        <el-select v-model="selectValue" filterable placeholder="请选择">
+          <el-option v-for="item in residentialList" :key="item.id" :label="item.name" :value="item.id">
+          </el-option>
+        </el-select>
+        <p style="margin-top: 20px;">
+          <el-button type="primary" icon="el-icon-paperclip" @click="bindResidential">绑定</el-button>
+        </p>
+      </div>
+    </el-dialog>
+
+  </basic-container>
+</template>
+
+<script>
+  import {getList, getDetail, add, update, remove, sync} from "@/api/device/elevatordevice";
+  import {mapGetters} from "vuex";
+  import {getAllList} from "@/api/community/residential";
+
+  export default {
+    data() {
+      return {
+        form: {},
+        residentialList: [],
+        loading: true,
+        bindVisible: false,
+        settingVisible: false,
+        selectValue: '',
+        query: {},
+        page: {
+          pageSize: 10,
+          currentPage: 1,
+          total: 0
+        },
+        selectionList: [],
+        option: {
+          height:'auto',
+          calcHeight: 60,
+          tip: false,
+          searchShow: true,
+          searchMenuSpan: 6,
+          border: true,
+          index: true,
+          viewBtn: true,
+          editBtn: false,
+          delBtn: false,
+          addBtn: false,
+          selection: true,
+          dialogClickModal: false,
+          column: [
+            {
+              label: "注册编码",
+              prop: "registerCode",
+              search: true,
+              searchSpan: 4,
+              rules: [{
+                required: true,
+                message: "请输入电梯注册编码",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "电梯名称",
+              prop: "liftName",
+              search: true,
+              searchSpan: 4,
+              rules: [{
+                required: true,
+                message: "请输入电梯名称",
+                trigger: "blur"
+              }]
+            },
+            /*{
+              label: "省编码",
+              prop: "provinceCode",
+              rules: [{
+                required: true,
+                message: "请输入省编码",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "市编码",
+              prop: "cityCode",
+              rules: [{
+                required: true,
+                message: "请输入市编码",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "区编码",
+              prop: "townCode",
+              rules: [{
+                required: true,
+                message: "请输入区编码",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "街道编码",
+              prop: "streetCode",
+              rules: [{
+                required: true,
+                message: "请输入街道编码",
+                trigger: "blur"
+              }]
+            },*/
+            {
+              label: "小区名称",
+              prop: "nbhdName",
+              search: true,
+              searchSpan: 4,
+              rules: [{
+                required: true,
+                message: "请输入小区名称",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "梯号",
+              prop: "elevatorNo",
+              rules: [{
+                required: true,
+                message: "请输入梯号",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "楼层数",
+              prop: "floorNum",
+              rules: [{
+                required: true,
+                message: "请输入楼层数",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "楼号",
+              prop: "floorNo",
+              hide: true,
+              rules: [{
+                required: true,
+                message: "请输入楼号",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "单元号",
+              prop: "partNo",
+              hide: true,
+              rules: [{
+                required: true,
+                message: "请输入单元号",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "云梯状态",
+              prop: "ytStatus",
+              type: "select",
+              search: true,
+              searchSpan: 4,
+              dicUrl: "/api/blade-system/dict-biz/dictionary?code=yt_status",
+              props:{
+                label: "dictValue",
+                value: "dictKey",
+              },
+              rules: [{
+                required: true,
+                message: "请输入云梯状态{10:云梯处于未上线,安装调试状态,20:云梯处于已上线,正常状态,30:云梯处于故障,维护状态}",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "在线状态",
+              prop: "onlineStatus",
+              type: "select",
+              search: true,
+              searchSpan: 4,
+              dicUrl: "/api/blade-system/dict-biz/dictionary?code=yt_online_status",
+              props:{
+                label: "dictValue",
+                value: "dictKey",
+              },
+              rules: [{
+                required: true,
+                message: "请输入在离线状态{0:离线,1:在线}",
+                trigger: "blur"
+              }]
+            },
+          ]
+        },
+        data: []
+      };
+    },
+    computed: {
+      ...mapGetters(["permission"]),
+      permissionList() {
+        return {
+          addBtn: this.vaildData(this.permission.elevatordevice_add, false),
+          viewBtn: this.vaildData(this.permission.elevatordevice_view, false),
+          delBtn: this.vaildData(this.permission.elevatordevice_delete, false),
+          editBtn: this.vaildData(this.permission.elevatordevice_edit, false)
+        };
+      },
+      ids() {
+        let ids = [];
+        this.selectionList.forEach(ele => {
+          ids.push(ele.id);
+        });
+        return ids.join(",");
+      }
+    },
+    methods: {
+      handleSync(){
+        this.loading = true;
+        sync().then(() => {
+          this.loading = false;
+          this.$message({
+            type: "success",
+            message: "同步成功!"
+          });
+          this.onLoad(this.page);
+        });
+      },
+      showDeviceBind(row){
+        this.selectValue = row.residentialId;
+        if (this.residentialList.length == 0){
+          //  请求获取小区列表
+          getAllList().then(res => {
+            this.residentialList = res.data.data;
+            this.bindVisible = true;
+          })
+        }else{
+          this.bindVisible = true;
+        }
+        this.form = row;
+      },
+      bindResidential(){
+        this.form.residentialId = this.selectValue;
+        //保存
+        update(this.form).then(() => {
+          this.onLoad(this.page);
+          this.bindVisible = false;
+          this.$message({
+            type: "success",
+            message: "绑定成功!"
+          });
+        }, error => {
+          console.log(error);
+        });
+      },
+      rowSave(row, done, loading) {
+        add(row).then(() => {
+          this.onLoad(this.page);
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          done();
+        }, error => {
+          loading();
+          window.console.log(error);
+        });
+      },
+      rowUpdate(row, index, done, loading) {
+        update(row).then(() => {
+          this.onLoad(this.page);
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          done();
+        }, error => {
+          loading();
+          console.log(error);
+        });
+      },
+      rowDel(row) {
+        this.$confirm("确定将选择数据删除?", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        })
+          .then(() => {
+            return remove(row.id);
+          })
+          .then(() => {
+            this.onLoad(this.page);
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+          });
+      },
+      handleDelete() {
+        if (this.selectionList.length === 0) {
+          this.$message.warning("请选择至少一条数据");
+          return;
+        }
+        this.$confirm("确定将选择数据删除?", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        })
+          .then(() => {
+            return remove(this.ids);
+          })
+          .then(() => {
+            this.onLoad(this.page);
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+            this.$refs.crud.toggleSelection();
+          });
+      },
+      beforeOpen(done, type) {
+        if (["edit", "view"].includes(type)) {
+          getDetail(this.form.id).then(res => {
+            this.form = res.data.data;
+          });
+        }
+        done();
+      },
+      searchReset() {
+        this.query = {};
+        this.onLoad(this.page);
+      },
+      searchChange(params, done) {
+        this.query = params;
+        this.page.currentPage = 1;
+        this.onLoad(this.page, params);
+        done();
+      },
+      selectionChange(list) {
+        this.selectionList = list;
+      },
+      selectionClear() {
+        this.selectionList = [];
+        this.$refs.crud.toggleSelection();
+      },
+      currentChange(currentPage){
+        this.page.currentPage = currentPage;
+      },
+      sizeChange(pageSize){
+        this.page.pageSize = pageSize;
+      },
+      refreshChange() {
+        this.onLoad(this.page, this.query);
+      },
+      onLoad(page, params = {}) {
+        this.loading = true;
+        getList(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
+          const data = res.data.data;
+          this.page.total = data.total;
+          this.data = data.records;
+          this.loading = false;
+          this.selectionClear();
+        });
+      }
+    }
+  };
+</script>
+
+<style scoped>
+  >>> .changeBind {
+    color: orange;
+  }
+</style>

+ 583 - 0
src/views/device/elevatorvideo.vue

@@ -0,0 +1,583 @@
+<template>
+  <basic-container>
+    <el-row>
+      <el-col>
+        <el-select v-model="value" filterable placeholder="请选择" @change="selectResidential">
+          <el-option
+            v-for="(item, idx) in residentialList"
+            :key="idx"
+            :label="item"
+            :value="item">
+          </el-option>
+        </el-select>
+        <el-button type="warning" size="small" icon="el-icon-remove" style="margin-left: 20px"
+                   v-if="permission.elevator_sync"
+                   @click="stopAll">停 止
+        </el-button>
+        <el-button type="success" size="small" icon="el-icon-remove" style="margin-left: 20px"
+                   v-if="permission.elevator_sync"
+                   @click="alarmName = '告警列表',alarmVisible = true">告警列表
+        </el-button>
+      </el-col>
+    </el-row>
+
+    <el-row>
+      <el-col v-for="(item, index) in data" :key="index" :span="8"><div class="grid-content bg-purple" :style="styleObject">
+        <el-card class="box-card" :body-style="{background: 'lightgrey'}">
+          <el-button class="play-btn" type="success" size="mini" icon="el-icon-video-play" @click="playOne(index)">播 放</el-button>
+          <label style="padding: 15px"><span>{{item.nbhdName}} - {{item.liftName}} - {{item.elevatorNo}}</span></label>
+          <el-dropdown class="card-btn" size="mini" split-button type="primary" @click="videoDetail(index)">
+            放 大
+            <el-dropdown-menu slot="dropdown">
+              <el-dropdown-item><el-button size="mini" type="primary" plain @click="getLiftStatusInfo(item)">实时梯况</el-button></el-dropdown-item>
+              <el-dropdown-item><el-button size="mini" type="warning" plain @click="getLiftPointInfo(item)">梯内环境</el-button></el-dropdown-item>
+              <el-dropdown-item><el-button size="mini" type="success" plain @click="getHisAlarm(item)">历史告警</el-button></el-dropdown-item>
+<!--              <el-dropdown-item><el-button size="mini" type="warning" plain>警告按钮</el-button></el-dropdown-item>-->
+<!--              <el-dropdown-item><el-button size="mini" type="danger" plain>危险按钮</el-button></el-dropdown-item>-->
+            </el-dropdown-menu>
+          </el-dropdown>
+          <video :id="'myvideo' + index" autoplay  style="background-color: black; width:100%;height:100%"></video>
+        </el-card>
+      </div></el-col>
+    </el-row>
+
+    <el-dialog :append-to-body="true" :close-on-click-modal="false" :modal-append-to-body="false" width="40%" top="1vh"
+                :title="bigVideoName" :visible.sync="bigVideoVisible" @close="videoClose">
+      <video id="bigVideo" autoplay  style="background-color: black; width:100%;height:100%"></video>
+    </el-dialog>
+
+    <el-dialog :append-to-body="true" :close-on-click-modal="false" :modal-append-to-body="false" width="80%" top="2vh"
+                :title="alarmName" :visible.sync="alarmVisible" center @close="registerCode = ''">
+      <elevator-alarm v-if="alarmVisible" :register-code="registerCode"></elevator-alarm>
+    </el-dialog>
+
+    <el-dialog :append-to-body="true" :close-on-click-modal="false" :modal-append-to-body="false" width="40%"
+                title="实时梯况" :visible.sync="liftStatusVisible" center>
+      <el-row>
+        <el-form ref="liftStatusForm" :inline="true" label-width="auto">
+          <div>
+            <el-col :span="12" :push="1">
+              <el-form-item label="运行速度:">
+                <span>{{ liftStatus.speed + 'mm/s'}}</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12" :push="1">
+              <el-form-item label="运行方向:">
+                <span v-if="liftStatus.direction == 1">向下</span>
+                <span v-if="liftStatus.direction == 2">向上</span>
+                <span v-if="liftStatus.direction == 3">静止</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12" :push="1">
+              <el-form-item label="梯门状态:">
+                <span v-if="liftStatus.doorStatus == 1">开门</span>
+                <span v-if="liftStatus.doorStatus == 2">关门</span>
+                <span v-if="liftStatus.doorStatus == 3">正在开</span>
+                <span v-if="liftStatus.doorStatus == 4">正在关</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12" :push="1">
+              <el-form-item label="平层状态:">
+                <span v-if="liftStatus.flatStatus == 1">平层</span>
+                <span v-if="liftStatus.flatStatus == 2">非平层</span>
+                <span v-if="liftStatus.flatStatus == 3">运动</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12" :push="1">
+              <el-form-item label="当前楼层:">
+                <span>{{ liftStatus.currentFloor + '层'}}</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12" :push="1">
+              <el-form-item label="运行状态:">
+                <span v-if="liftStatus.runModel == 0">停止</span>
+                <span v-if="liftStatus.runModel == 1">运行</span>
+              </el-form-item>
+            </el-col>
+          </div>
+        </el-form>
+      </el-row>
+    </el-dialog>
+
+    <el-dialog :append-to-body="true" :close-on-click-modal="false" :modal-append-to-body="false" width="40%"
+                title="梯内环境" :visible.sync="liftPointVisible" center>
+      <el-row>
+        <el-form ref="liftStatusForm" :inline="true" label-width="auto">
+          <div>
+            <el-col :span="12" :push="1">
+              <el-form-item label="轿厢烟感状态:">
+                <span v-if="liftPoint.smokeDetector == false">OFF</span>
+                <span v-if="liftPoint.smokeDetector == true">ON</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12" :push="1">
+              <el-form-item label="轿厢顶温度:">
+                <span>{{ liftPoint.carTopTemperature + '℃'}}</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12" :push="1">
+              <el-form-item label="机房温度:">
+                <span>{{ liftPoint.roomTemperature + '℃'}}</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12" :push="1">
+              <el-form-item label="适配器电压:">
+                <span>{{ liftPoint.dcValue}}</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12" :push="1">
+              <el-form-item label="轿厢顶人感:">
+                <span v-if="liftPoint.carTopHuman == 0">无人</span>
+                <span v-if="liftPoint.carTopHuman == 1">有人</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12" :push="1">
+              <el-form-item label="轿厢内人感:">
+                <span v-if="liftPoint.carHuman == 0">无人</span>
+                <span v-if="liftPoint.carHuman == 1">有人</span>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12" :push="1">
+              <el-form-item label="机房人感:">
+                <span v-if="liftPoint.roomHuman == 0">无人</span>
+                <span v-if="liftPoint.roomHuman == 1">有人</span>
+              </el-form-item>
+            </el-col>
+          </div>
+        </el-form>
+      </el-row>
+    </el-dialog>
+
+  </basic-container>
+</template>
+
+<script>
+  import {getLiftList, getDetail, add, update, remove, getLiftResidentialSelect,getLiftStatus, getLiftPointData, getRealvideo} from "@/api/device/elevatordevice";
+
+  import {mapGetters} from "vuex";
+  import {startPlay, stopPlay} from "@/api/device/elevatorUtil";
+  import ElevatorAlarm from "./elevatoralarm";
+
+  export default {
+    components: {ElevatorAlarm},
+    data() {
+      return {
+        registerCode: '',
+        value: '',
+        residentialList: [],
+        plays: {},
+        styleObject: {
+          width: "300px",
+          height: "450px",
+        },
+        bigVideoVisible: false,
+        alarmVisible: false,
+        liftStatusVisible: false,
+        liftStatus: {},
+        liftPointVisible: false,
+        liftPoint: {},
+        bigVideoName: '',
+        alarmName: '',
+        form: {},
+        query: {},
+        loading: true,
+        page: {
+          pageSize: 10,
+          currentPage: 1,
+          total: 0
+        },
+        selectionList: [],
+        option: {
+          height:'auto',
+          calcHeight: 30,
+          tip: false,
+          searchShow: true,
+          searchMenuSpan: 6,
+          border: true,
+          index: true,
+          viewBtn: true,
+          addBtn: false,
+          editBtn: false,
+          delBtn: false,
+          selection: true,
+          dialogClickModal: false,
+          column: [
+            {
+              label: "电梯注册编码",
+              prop: "registerCode",
+              rules: [{
+                required: true,
+                message: "请输入电梯注册编码",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "电梯名称",
+              prop: "liftName",
+              rules: [{
+                required: true,
+                message: "请输入电梯名称",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "小区名称",
+              prop: "nbhdName",
+              rules: [{
+                required: true,
+                message: "请输入小区名称",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "梯号",
+              prop: "elevatorNo",
+              rules: [{
+                required: true,
+                message: "请输入梯号",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "楼层数",
+              prop: "floorNum",
+              rules: [{
+                required: true,
+                message: "请输入楼层数",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "楼号",
+              prop: "floorNo",
+              hide: true,
+              rules: [{
+                required: true,
+                message: "请输入楼号",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "单元号",
+              prop: "partNo",
+              hide: true,
+              rules: [{
+                required: true,
+                message: "请输入单元号",
+                trigger: "blur"
+              }]
+            },
+
+            {
+              label: "云梯状态",
+              prop: "ytStatus",
+              dicUrl: "/api/blade-system/dict-biz/dictionary?code=yt_status",
+              props:{
+                label: "dictValue",
+                value: "dictKey",
+              },
+              rules: [{
+                required: true,
+                message: "请输入云梯状态{10:云梯处于未上线,安装调试状态,20:云梯处于已上线,正常状态,30:云梯处于故障,维护状态}",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "在线状态",
+              prop: "onlineStatus",
+              dicUrl: "/api/blade-system/dict-biz/dictionary?code=yt_online_status",
+              props:{
+                label: "dictValue",
+                value: "dictKey",
+              },
+              rules: [{
+                required: true,
+                message: "请输入在离线状态{0:离线,1:在线}",
+                trigger: "blur"
+              }]
+            },
+          ]
+        },
+        data: [],
+        alarmData: [],
+        alarmOption: {
+          title:'历史告警',
+          page:false,
+          // viewBtn: true,
+          addBtn: false,
+          editBtn: false,
+          delBtn: false,
+          align:'center',
+          menuAlign:'center',
+          column:[
+            {
+              label:'小区名称',
+              prop:'nbhdName'
+            },
+            {
+              label:'电梯名称',
+              prop:'liftName'
+            },
+            {
+              label:'告警类型',
+              prop:'alarmName'
+            },
+            {
+              label: "告警时间",
+              prop: "alarmTime",
+              type: "date",
+              format: "yyyy-MM-dd hh:mm:ss",
+              valueFormat: "yyyy-MM-dd hh:mm:ss",
+            }
+          ]
+        },
+      };
+    },
+    computed: {
+      ...mapGetters(["permission"]),
+      permissionList() {
+        return {
+          addBtn: this.vaildData(this.permission.elevator_add, false),
+          viewBtn: this.vaildData(this.permission.elevator_view, false),
+          delBtn: this.vaildData(this.permission.elevator_delete, false),
+          editBtn: this.vaildData(this.permission.elevator_edit, false)
+        };
+      },
+      ids() {
+        let ids = [];
+        this.selectionList.forEach(ele => {
+          ids.push(ele.id);
+        });
+        return ids.join(",");
+      }
+    },
+    mounted() {
+
+      this.initVideoWidth();
+
+      getLiftResidentialSelect().then(res => {
+        this.residentialList = res.data.data;
+        if (this.residentialList.length > 0){
+          // let nbhdName = this.residentialList[0].nbhdName;
+          let nbhdName = this.residentialList[0];
+          this.value = nbhdName;
+          this.onLoad({nbhdName: nbhdName});
+        /*}else{
+          this.onLoad();*/
+        }
+      });
+    },
+    methods: {
+      initVideoWidth(){
+        let $main = document.querySelector('.avue-main');
+        let mainWidth = $main.clientWidth;
+        let width = mainWidth * 0.30;
+        let height = width / 0.76;
+        this.styleObject.width = width + 'px';
+        this.styleObject.height = height + 'px';
+      },
+      getHisAlarm(item){
+        // let item = this.data[index];
+        this.registerCode = item.registerCode;
+        this.alarmVisible = true;
+        this.alarmName = '【' + item.nbhdName+ ' - ' + item.liftName + ' - ' + item.elevatorNo + '】历史告警';
+      },
+      getLiftStatusInfo(item){
+        item.registerCode && getLiftStatus(item.registerCode).then(res => {
+          if (res.data.code == 200 && res.data.data.code == 0){
+            this.liftStatusVisible = true;
+            this.liftStatus = res.data.data.data;
+          }
+        });
+
+      },
+      getLiftPointInfo(item){
+        item.registerCode && getLiftPointData(item.registerCode).then(res => {
+          if (res.data.code == 200 && res.data.data.code == 0){
+            this.liftPointVisible = true;
+            this.liftPoint = res.data.data.data;
+          }
+        });
+
+      },
+      videoClose(){
+        stopPlay(this.plays['bigVideo']);
+      },
+      videoDetail(index){
+        this.bigVideoVisible = true;
+        let item = this.data[index];
+        this.bigVideoName = item.nbhdName;
+        let elementId = 'bigVideo';
+        let code = item.registerCode;
+
+        getRealvideo(code).then(res => {
+          // let obj = JSON.parse(res.data.data);
+          let videoUrl = res.data.data.data.urls[0].httpsUrl;
+          let player = startPlay(elementId, videoUrl, this.plays[elementId]);
+          this.plays[elementId] = player;
+
+        });
+      },
+      stopAll(){
+        let _this = this;
+        Object.keys(this.plays).forEach(item => {
+          stopPlay(_this.plays[item]);
+        })
+      },
+      selectResidential(value){
+        this.stopAll();
+        this.onLoad({nbhdName: value});
+      },
+      playOne(index){
+        let code = this.data[index].registerCode;
+        let elementId = 'myvideo' + index;
+        getRealvideo(code).then(res => {
+          // let obj = JSON.parse(res.data.data);
+          let videoUrl = res.data.data.data.urls[0].httpsUrl;
+          let player = startPlay(elementId, videoUrl, this.plays[elementId]);
+          this.plays[elementId] = player;
+          console.log("url=" + videoUrl)
+        });
+      },
+      playAll(){
+        this.data.forEach((item, index) => {
+          this.playOne(index);
+        })
+      },
+      /*handleSync(){
+        this.loading = true;
+        sync().then(() => {
+          this.loading = false;
+          let nbhdName = this.residentialList[0].nbhdName;
+          this.onLoad({nbhdName: nbhdName});
+        });
+      },*/
+      rowSave(row, done, loading) {
+        add(row).then(() => {
+          this.onLoad(this.page);
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          done();
+        }, error => {
+          loading();
+          window.console.log(error);
+        });
+      },
+      rowUpdate(row, index, done, loading) {
+        update(row).then(() => {
+          this.onLoad(this.page);
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          done();
+        }, error => {
+          loading();
+          console.log(error);
+        });
+      },
+      rowDel(row) {
+        this.$confirm("确定将选择数据删除?", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        })
+          .then(() => {
+            return remove(row.id);
+          })
+          .then(() => {
+            this.onLoad(this.page);
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+          });
+      },
+      handleDelete() {
+        if (this.selectionList.length === 0) {
+          this.$message.warning("请选择至少一条数据");
+          return;
+        }
+        this.$confirm("确定将选择数据删除?", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        })
+          .then(() => {
+            return remove(this.ids);
+          })
+          .then(() => {
+            this.onLoad(this.page);
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+            this.$refs.crud.toggleSelection();
+          });
+      },
+      beforeOpen(done, type) {
+        if (["edit", "view"].includes(type)) {
+          getDetail(this.form.id).then(res => {
+            this.form = res.data.data;
+          });
+        }
+        done();
+      },
+      searchReset() {
+        this.query = {};
+        this.onLoad(this.page);
+      },
+      searchChange(params, done) {
+        this.query = params;
+        this.page.currentPage = 1;
+        this.onLoad(this.page, params);
+        done();
+      },
+      selectionChange(list) {
+        this.selectionList = list;
+      },
+      selectionClear() {
+        this.selectionList = [];
+        this.$refs.crud.toggleSelection();
+      },
+      currentChange(currentPage){
+        this.page.currentPage = currentPage;
+      },
+      sizeChange(pageSize){
+        this.page.pageSize = pageSize;
+      },
+      refreshChange() {
+        this.onLoad(this.query);
+      },
+      onLoad(params = {}) {
+        this.loading = true;
+        getLiftList(Object.assign(params, this.query)).then(res => {
+          const data = res.data.data;
+          this.data = data;
+          this.loading = false;
+          this.playAll();
+        });
+      }
+    }
+  };
+</script>
+
+<style scoped>
+  >>> .play-btn{
+    margin-bottom: 5px;
+    margin-top: -5px;
+  }
+  >>> .card-btn{
+    float: right !important;
+    margin-top: -5px;
+  }
+  >>> .grid-content{
+    width: 380px;
+    height: 500px;
+  }
+  >>> .el-form-item__label{
+    font-weight: bold;
+  }
+</style>

+ 384 - 0
src/views/device/iotalarm.vue

@@ -0,0 +1,384 @@
+<template>
+  <basic-container>
+    <el-dialog :append-to-body="true" :close-on-click-modal="false" :modal-append-to-body="false" :visible.sync="alarmDetailVisible"
+               title="告警详情" width="40%">
+      <avue-form v-model="alarmDetail" :option="option" disabled="false">
+
+      </avue-form>
+    </el-dialog>
+
+    <avue-crud :option="option" :table-loading="loading" :data="data" :page="page" :permission="permissionList"
+               :before-open="beforeOpen" v-model="form" ref="crud" @row-update="rowUpdate" @row-save="rowSave" @row-del="rowDel"
+               @search-change="searchChange" @search-reset="searchReset" @selection-change="selectionChange" @current-change="currentChange"
+               @size-change="sizeChange" @refresh-change="refreshChange" @on-load="onLoad">
+      <template slot="menu" slot-scope="scope">
+        <el-button type="text" divided @click.native="ViewAlarmDetail(scope.row)" icon="el-icon-view">告警详情</el-button>
+        <el-button type="text" divided @click.native="createAlarmJob(scope.row)" icon="el-icon-finished" v-if="scope.row.orderId == null||scope.row.orderId ==''">生成工单</el-button>
+      </template>
+      <template slot="monitorValue" slot-scope="scope">
+
+        {{scope.row.monitorValue == null||scope.row.monitorValue == ''?"无":scope.row.monitorValue}}
+      </template>
+    </avue-crud>
+  </basic-container>
+</template>
+
+<script>
+  import{
+    getDetailByDeviceId
+  } from "../../api/device/iotdevice.js";
+  import {
+    getList,
+    getDetail,
+    add,
+    update,
+    remove
+  } from "../../api/device/iotalarm.js";
+  import {
+    mapGetters
+  } from "vuex";
+  // import {add as addDeviceJob} from "@/api/jobs/devicejob";
+  // import center from "@/components/grid/components/center";
+
+  export default {
+    data() {
+      return {
+        deviceDetail:{},
+        alarmDetail: {},
+        alarmDetailVisible: false,
+        form: {},
+        query: {},
+        loading: true,
+        page: {
+          pageSize: 10,
+          currentPage: 1,
+          total: 0
+        },
+        selectionList: [],
+        option: {
+          submitBtn:false,
+          emptyBtn:false,
+          // menuWidth: 200,
+          menuAlign:'center',
+          height: 'auto',
+          calcHeight: 30,
+          tip: false,
+          searchShow: true,
+          searchMenuSpan: 6,
+          border: true,
+          index: true,
+          addBtn: true,
+          selection: true,
+          dialogClickModal: false,
+          column: [
+            {
+              label: "告警原因",
+              prop: "name",
+              width: 100,
+              hide:true,
+              rules: [{
+                required: false,
+                message: "请输入告警原因",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "设备sn号",
+              prop: "deviceId",
+              search: true,
+              width: 150,
+              rules: [{
+                required: false,
+                message: "请输入告警设备sn号",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "设备名称",
+              prop: "deviceName",
+              search: true,
+              width: 270,
+              overHidden: true,
+              rules: [{
+                required: false,
+                message: "请输入设备名称",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "设备类型",
+              prop: "deviceType",
+              type: "select",
+              search: true,
+              width: 100,
+              dicUrl: "/api/blade-system/dict-biz/dictionary?code=device_type",
+              props: {
+                label: "dictValue",
+                value: "dictKey"
+              },
+              dataType: "number",
+              rules: [{
+                required: false,
+                message: "请输入设备类型",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "告警次数",
+              prop: "alarmTimes",
+              width:80,
+              align:'center',
+              rules: [{
+                required: false,
+                message: "请输入告警次数",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "告警等级",
+              prop: "level",
+              width:100,
+              align: 'center',
+              type: "select",
+              // dataType: "number",
+              dicUrl: "/api/blade-system/dict-biz/dictionary?code=alarm_level",
+              props: {
+                label: "dictValue",
+                value: "dictKey"
+              },
+              rules: [{
+                required: false,
+                message: "请输入告警等级 1:严重告警,2:警告告警,3:提示告警",
+                trigger: "blur"
+              }]
+            },
+            // {
+            //   label: "监测值",
+            //   prop: "monitorValue",
+            //   slot: true,
+            //   width: 100,
+            //   rules: [{
+            //     required: false,
+            //     message: "请输入监测值",
+            //     trigger: "blur"
+            //   }]
+            // },
+
+            {
+              label: "告警时间",
+              prop: "recordTime",
+              width: 170,
+              align:"center",
+              rules: [{
+                required: false,
+                message: "请输入告警时间",
+                trigger: "blur"
+              }]
+            },
+            // {
+            //   label: "告警状态",
+            //   prop: "status",
+            //   type: "select",
+            //   dicUrl: "/api/blade-system/dict-biz/dictionary?code=alarm_status",
+            //   props: {
+            //     label: "dictValue",
+            //     value: "dictKey"
+            //   },
+            //   dataType: "number",
+            //   rules: [{
+            //     required: false,
+            //     message: "请输入告警状态,0 实时告警,1-历史告警",
+            //     trigger: "blur"
+            //   }]
+            // },
+            {
+              label: "告警类型",
+              prop: "alarmType",
+              type: "select",
+              // width: 100,
+              // align:'center',
+              dicUrl: "/api/blade-system/dict-biz/dictionary?code=alarm_type",
+              props: {
+                label: "dictValue",
+                value: "dictKey"
+              },
+              dataType: "number",
+              rules: [{
+                required: false,
+                message: "请输入告警类型, 0-业务告警;1-设备告警",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "最新告警时间",
+              prop: "lastNoticeDate",
+              width:170,
+              align:"center",
+              hide: true,
+              rules: [{
+                required: false,
+                message: "请输入最新告警时间",
+                trigger: "blur"
+              }]
+            },
+          ]
+        },
+        data: []
+      };
+    },
+    computed: {
+      ...mapGetters(["permission"]),
+      permissionList() {
+        return {
+          addBtn: this.vaildData(this.permission.alarmlist_add, false),
+          viewBtn: this.vaildData(this.permission.alarmlist_view, false),
+          delBtn: this.vaildData(this.permission.alarmlist_delete, false),
+          editBtn: this.vaildData(this.permission.alarmlist_edit, false)
+        };
+      },
+      ids() {
+        let ids = [];
+        this.selectionList.forEach(ele => {
+          ids.push(ele.id);
+        });
+        return ids.join(",");
+      }
+    },
+    methods: {
+      ViewAlarmDetail(row) {
+        getDetailByDeviceId(row.deviceId).then(res=>{
+          this.deviceDetail = res.data.data;
+          console.log(res)
+        });
+        this.alarmDetail = row;
+        this.alarmDetailVisible = true;
+      },
+      createAlarmJob(row){
+        // addDeviceJob(row).then(() => {
+        //   this.onLoad(this.page);
+        //   this.$message({
+        //     type: "success",
+        //     message: "操作成功!"
+        //   });
+        //   done();
+        // }, error => {
+        //   loading();
+        //   window.console.log(error);
+        // });
+      },
+      rowSave(row, done, loading) {
+        add(row).then(() => {
+          this.onLoad(this.page);
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          done();
+        }, error => {
+          loading();
+          window.console.log(error);
+        });
+      },
+      rowUpdate(row, index, done, loading) {
+        update(row).then(() => {
+          this.onLoad(this.page);
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          done();
+        }, error => {
+          loading();
+          console.log(error);
+        });
+      },
+      rowDel(row) {
+        this.$confirm("确定将选择数据删除?", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        })
+          .then(() => {
+            return remove(row.id);
+          })
+          .then(() => {
+            this.onLoad(this.page);
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+          });
+      },
+      handleDelete() {
+        if (this.selectionList.length === 0) {
+          this.$message.warning("请选择至少一条数据");
+          return;
+        }
+        this.$confirm("确定将选择数据删除?", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        })
+          .then(() => {
+            return remove(this.ids);
+          })
+          .then(() => {
+            this.onLoad(this.page);
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+            this.$refs.crud.toggleSelection();
+          });
+      },
+      beforeOpen(done, type) {
+        if (["edit", "view"].includes(type)) {
+          getDetail(this.form.id).then(res => {
+            this.form = res.data.data;
+          });
+        }
+        done();
+      },
+      searchReset() {
+        this.query = {};
+        this.onLoad(this.page);
+      },
+      searchChange(params, done) {
+        this.query = params;
+        this.page.currentPage = 1;
+        this.onLoad(this.page, params);
+        done();
+      },
+      selectionChange(list) {
+        this.selectionList = list;
+      },
+      selectionClear() {
+        this.selectionList = [];
+        this.$refs.crud.toggleSelection();
+      },
+      currentChange(currentPage) {
+        this.page.currentPage = currentPage;
+      },
+      sizeChange(pageSize) {
+        this.page.pageSize = pageSize;
+      },
+      refreshChange() {
+        this.onLoad(this.page, this.query);
+      },
+      onLoad(page, params = {}) {
+        this.loading = true;
+        // this.query.deviceName = "阅海万家"
+        getList(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
+          const data = res.data.data;
+          this.page.total = data.total;
+          this.data = data.records;
+          this.loading = false;
+          this.selectionClear();
+        });
+      }
+    }
+  };
+</script>
+
+<style>
+</style>

+ 507 - 0
src/views/device/iotalarmgroup.vue

@@ -0,0 +1,507 @@
+<template>
+  <el-row>
+    <el-col :span="12">
+      <basic-container>
+        <avue-crud :option="optionParent" :table-loading="loading" :data="dataParent" :page="pageParent" :permission="permissionList"
+                   :before-open="beforeOpen" v-model="formParent" ref="crud" @row-click="handleRowClick" @row-update="rowUpdate"
+                   @row-save="rowSave" @row-del="rowDel" @search-change="searchChange" @search-reset="searchReset"
+                   @selection-change="selectionChange" @current-change="currentChange" @size-change="sizeChange" @refresh-change="refreshChange"
+                   @on-load="onLoadParent">
+          <template slot="menuLeft">
+            <el-button type="danger" size="small" icon="el-icon-delete" plain v-if="permission.alarmgroup_delete"
+                       @click="handleDelete">删 除
+            </el-button>
+          </template>
+          <template slot="residentialId" slot-scope="scope">
+            <div>{{scope.row.residentialName}}</div>
+          </template>
+        </avue-crud>
+      </basic-container>
+    </el-col>
+
+    <el-col :span="12">
+      <basic-container>
+        <avue-crud :option="optionChild" :table-loading="loadingChild" :data="dataChild" :page="pageChild" :permission="permissionListChild"
+                   :before-open="beforeOpenChild" v-model="formChild" ref="crudChild" @row-update="rowUpdateChild" @row-save="rowSaveChild"
+                   @row-del="rowDelChild" @search-change="searchChangeChild" @search-reset="searchResetChild" @selection-change="selectionChangeChild"
+                   @current-change="currentChangeChild" @size-change="sizeChangeChild" @refresh-change="refreshChangeChild"
+                   @on-load="onLoadChild">
+          <template slot="menuLeft">
+            <el-button type="danger" size="small" icon="el-icon-delete" plain v-if="permission.alarmgroupuser_delete"
+                       @click="handleDeleteChild">删 除
+            </el-button>
+          </template>
+
+        </avue-crud>
+      </basic-container>
+    </el-col>
+
+  </el-row>
+
+</template>
+
+<script>
+  import {
+    getList,
+    getDetail,
+    add,
+    update,
+    remove
+  } from "@/api/device/iotalarmgroup";
+  import {
+    getList as getUserList,
+    getDetail as getUserDetail,
+    add as addUser,
+    updata as updateUser,
+    remove as removeUser
+  } from "@/api/device/iotalarmgroupuser";
+  import {
+    mapGetters
+  } from "vuex";
+
+  var DIC = {
+    yes_no: [{
+      label: '否',
+      value: 0
+    }, {
+      label: '是',
+      value: 1
+    }]
+  }
+
+  export default {
+    data() {
+      return {
+        formParent: {},
+        query: {},
+        loading: true,
+        pageParent: {
+          pageSize: 10,
+          currentPage: 1,
+          total: 0
+        },
+        selectionList: [],
+        optionParent: {
+          height: 'auto',
+          calcHeight: 30,
+          tip: false,
+          searchShow: true,
+          searchMenuSpan: 8,
+          border: true,
+          index: true,
+          viewBtn: true,
+          dialogWidth: 600,
+          selection: true,
+          dialogClickModal: false,
+          menuPosition: "center",
+          column: [{
+            label: "组名",
+            prop: "name",
+            row: true,
+            span: 20,
+            rules: [{
+              required: true,
+              message: "请输入组名",
+              trigger: "blur"
+            }]
+
+          },
+            {
+              label: "归属",
+              prop: "residentialId",
+              span: 20,
+              row: true,
+              type: "select",
+              searchSpan: 12,
+              remote: true,
+              //回显的时候有问题,如果所选不在前十条内,下拉框只会显示id
+              dicUrl: "/api/cyzh-community/residential/list?size=10000&name={{key}}",
+              props: {
+                label: "name",
+                value: "id"
+              },
+              searchFilterable: true,
+              search: true,
+              slot: true,
+              rules: [{
+                required: true,
+                message: "请输入",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "设备类型",
+              prop: "tag",
+              type: "select",
+              row: true,
+              span: 20,
+              dicUrl: "/api/blade-system/dict-biz/dictionary?code=iot_device_type",
+              props: {
+                label: "dictValue",
+                value: "dictKey",
+              },
+              dataType: "number",
+              rules: [{
+                required: true,
+                message: "请输入标识",
+                trigger: "blur"
+              }]
+            },
+          ]
+        },
+        dataParent: [],
+        //-----------------------------------------------------------------------------------------
+        formChild: {},
+        loadingChild: true,
+        pageChild: {
+          pageSize: 10,
+          currentPage: 1,
+          total: 0
+        },
+        optionChild: {
+          height: 'auto',
+          calcHeight: 30,
+          tip: false,
+          searchShow: true,
+          searchMenuSpan: 6,
+          menuPosition: "center",
+          dialogWidth: 600,
+          border: true,
+          index: true,
+          viewBtn: true,
+          selection: true,
+          dialogClickModal: false,
+          column: [{
+            label: "责任人",
+            prop: "person",
+            row: true,
+            span: 20,
+            labelWidth: 120,
+            rules: [{
+              required: true,
+              message: "请输入责任人",
+              trigger: "blur"
+            }]
+          },
+            {
+              label: "责任人电话",
+              prop: "phone",
+              row: true,
+              labelWidth: 120,
+              span: 20,
+              rules: [{
+                required: true,
+                message: "请输入责任人电话",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "是否为处理人",
+              prop: "isHandler",
+              type: "switch",
+              row: true,
+              span: 20,
+              labelWidth: 120,
+              dicData: DIC.yes_no,
+              mock: {
+                type: 'dic'
+              },
+              displayAs: 'switch',
+              rules: [{
+                required: false,
+                message: "请输入是否为处理人",
+                trigger: "blur"
+              }]
+            },
+          ]
+        },
+        dataChild: []
+      };
+    },
+    computed: {
+      ...mapGetters(["permission"]),
+      permissionList() {
+        return {
+          addBtn: this.vaildData(this.permission.alarmgroup_add, false),
+          viewBtn: this.vaildData(this.permission.alarmgroup_view, false),
+          delBtn: this.vaildData(this.permission.alarmgroup_delete, false),
+          editBtn: this.vaildData(this.permission.alarmgroup_edit, false)
+        };
+      },
+      permissionListChild() {
+        return {
+          addBtn: this.vaildData(this.permission.alarmgroupuser_add, false),
+          viewBtn: this.vaildData(this.permission.alarmgroupuser_view, false),
+          delBtn: this.vaildData(this.permission.alarmgroupuser_delete, false),
+          editBtn: this.vaildData(this.permission.alarmgroupuser_edit, false)
+        };
+      },
+      ids() {
+        let ids = [];
+        this.selectionList.forEach(ele => {
+          ids.push(ele.id);
+        });
+        return ids.join(",");
+      }
+    },
+    mounted() {
+      let tenantType = localStorage.getItem("tenantType");
+      const residentialIdColumn = this.findObject(this.optionParent.column, "residentialId");
+      if (tenantType == 1) { //园区
+        residentialIdColumn.label = "所属区域"
+      } else { //社区
+        residentialIdColumn.label = "所属小区"
+      }
+    },
+    methods: {
+      rowSave(row, done, loading) {
+        add(row).then(() => {
+          this.onLoadParent(this.pageParent);
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          done();
+        }, error => {
+          loading();
+          window.console.log(error);
+        });
+      },
+      rowUpdate(row, index, done, loading) {
+        update(row).then(() => {
+          this.onLoadParent(this.pageParent);
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          done();
+        }, error => {
+          loading();
+          console.log(error);
+        });
+      },
+      rowDel(row) {
+        this.$confirm("确定将选择数据删除?", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        })
+          .then(() => {
+            return remove(row.id);
+          })
+          .then(() => {
+            this.onLoadParent(this.pageParent);
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+          });
+      },
+      handleDelete() {
+        if (this.selectionList.length === 0) {
+          this.$message.warning("请选择至少一条数据");
+          return;
+        }
+        this.$confirm("确定将选择数据删除?", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        })
+          .then(() => {
+            return remove(this.ids);
+          })
+          .then(() => {
+            this.onLoadParent(this.pageParent);
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+            this.$refs.crud.toggleSelection();
+          });
+      },
+      beforeOpen(done, type) {
+        if (["edit", "view"].includes(type)) {
+          getDetail(this.formParent.id).then(res => {
+            this.formParent = res.data.data;
+          });
+        }
+        done();
+      },
+      handleRowClick(row) {
+        this.query = {};
+        this.parentId = row.id;
+        debugger
+        this.dictValue = row.dictValue;
+        this.$refs.crudChild.value.code = row.code;
+        this.$refs.crudChild.value.parentId = row.id;
+        // this.$refs.crudChild.option.column.filter(item => {
+        //   if (item.prop === "code") {
+        //     item.value = row.code;
+        //   }
+        //   if (item.prop === "parentId") {
+        //     item.value = row.id;
+        //   }
+        // });
+        this.onLoadChild(this.pageChild);
+      },
+      searchReset() {
+        this.query = {};
+        this.onLoadParent(this.pageParent);
+      },
+      searchChange(params, done) {
+        this.query = params;
+        this.pageParent.currentPage = 1;
+        this.onLoadParent(this.pageParent, params);
+        done();
+      },
+      selectionChange(list) {
+        this.selectionList = list;
+      },
+      selectionClear() {
+        this.selectionList = [];
+        this.$refs.crud.toggleSelection();
+      },
+      currentChange(currentPage) {
+        this.pageParent.currentPage = currentPage;
+      },
+      sizeChange(pageSize) {
+        this.pageParent.pageSize = pageSize;
+      },
+      refreshChange() {
+        this.onLoadParent(this.pageParent, this.query);
+      },
+      onLoadParent(page, params = {}) {
+        this.loading = true;
+        getList(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
+          const data = res.data.data;
+          this.pageParent.total = data.total;
+          this.dataParent = data.records;
+          if (this.dataParent.length > 0) {
+            this.parentId = this.dataParent[0].id;
+            this.onLoadChild(this.pageChild);
+          }
+          this.loading = false;
+          this.selectionClear();
+        });
+      },
+      rowSaveChild(row, done, loading) {
+        row.groupId = this.parentId;
+        addUser(row).then(() => {
+          this.onLoadChild(this.pageChild);
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          done();
+        }, error => {
+          loading();
+          window.console.log(error);
+        });
+      },
+      rowUpdateChild(row, index, done, loading) {
+        // row.groupId = this.parentId;
+        updateUser(row).then(() => {
+          this.onLoadChild(this.pageChild);
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          done();
+        }, error => {
+          loading();
+          console.log(error);
+        });
+      },
+      rowDelChild(row) {
+        this.$confirm("确定将选择数据删除?", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        })
+          .then(() => {
+            return removeUser(row.id);
+          })
+          .then(() => {
+            this.onLoadChild(this.pageChild);
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+          });
+      },
+      handleDeleteChild() {
+        if (this.selectionList.length === 0) {
+          this.$message.warning("请选择至少一条数据");
+          return;
+        }
+        this.$confirm("确定将选择数据删除?", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        })
+          .then(() => {
+            return remove(this.ids);
+          })
+          .then(() => {
+            this.onLoadChild(this.pageChild);
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+            this.$refs.crud.toggleSelection();
+          });
+      },
+      beforeOpenChild(done, type) {
+        if (["edit", "view"].includes(type)) {
+          getUserDetail(this.formChild.id).then(res => {
+            this.formChild = res.data.data;
+          });
+        }
+        done();
+      },
+      searchResetChild() {
+        this.query = {};
+        this.onLoadChild(this.pageChild);
+      },
+      searchChangeChild(params, done) {
+        this.query = params;
+        this.pageChild.currentPage = 1;
+        this.onLoadChild(this.pageChild, params);
+        done();
+      },
+      selectionChangeChild(list) {
+        this.selectionList = list;
+      },
+      selectionClearChild() {
+        this.selectionList = [];
+        this.$refs.crud.toggleSelection();
+      },
+      currentChangeChild(currentPage) {
+        this.pageChild.currentPage = currentPage;
+      },
+      sizeChangeChild(pageSize) {
+        this.pageChild.pageSize = pageSize;
+      },
+      refreshChangeChild() {
+        this.onLoadChild(this.pageChild, this.query);
+      },
+      onLoadChild(page, params = {}) {
+        this.loadingChild = true;
+        params.groupId = this.parentId;
+        getUserList(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
+          const data = res.data.data;
+          this.pageChild.total = data.total;
+          this.dataChild = data.records;
+          this.dataChild.forEach(item => {
+            item.isHandler = item.isHandler == 1;
+          })
+          this.loadingChild = false;
+          this.selectionClearChild();
+        });
+      }
+    }
+  };
+</script>
+
+<style>
+</style>

+ 240 - 0
src/views/device/iotalarmgroupuser.vue

@@ -0,0 +1,240 @@
+<template>
+  <basic-container>
+    <avue-crud :option="optionChild"
+               :table-loading="loadingChild"
+               :data="dataChild"
+               :page="pageChild"
+               :permission="permissionListChild"
+               :before-open="beforeOpenChild"
+               v-model="formChild"
+               ref="crud"
+               @row-update="rowUpdateChild"
+               @row-save="rowSaveChild"
+               @row-del="rowDelChild"
+               @search-change="searchChangeChild"
+               @search-reset="searchResetChild"
+               @selection-change="selectionChangeChild"
+               @current-change="currentChangeChild"
+               @size-change="sizeChangeChild"
+               @refresh-change="refreshChangeChild"
+               @on-load="onLoadChild">
+      <template slot="menuLeft">
+        <el-button type="danger"
+                   size="small"
+                   icon="el-icon-delete"
+                   plain
+                   v-if="permission.alarmgroupuser_delete"
+                   @click="handleDelete">删 除
+        </el-button>
+      </template>
+    </avue-crud>
+  </basic-container>
+</template>
+
+<script>
+  import {getList, getDetail, add, update, remove} from "@/api/device/iotalarmgroupuser";
+  import {mapGetters} from "vuex";
+
+  export default {
+    data() {
+      return {
+        formChild: {},
+        query: {},
+        loadingChild: true,
+        pageChild: {
+          pageSize: 10,
+          currentPage: 1,
+          total: 0
+        },
+        selectionList: [],
+        optionChild: {
+          height:'auto',
+          calcHeight: 30,
+          tip: false,
+          searchShow: true,
+          searchMenuSpan: 6,
+          border: true,
+          index: true,
+          viewBtn: true,
+          selection: true,
+          dialogClickModal: false,
+          column: [
+            {
+              label: "组id",
+              prop: "groupId",
+              rules: [{
+                required: true,
+                message: "请输入组id",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "责任人",
+              prop: "person",
+              rules: [{
+                required: true,
+                message: "请输入责任人",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "责任人电话",
+              prop: "phone",
+              rules: [{
+                required: true,
+                message: "请输入责任人电话",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "是否为处理人",
+              prop: "phone",
+              type: "switch",
+              mock:{
+                type:'dic'
+              },
+              rules: [{
+                required: true,
+                message: "请输入是否为处理人",
+                trigger: "blur"
+              }]
+            },
+          ]
+        },
+        dataChild: []
+      };
+    },
+    computed: {
+      ...mapGetters(["permission"]),
+      permissionListChild() {
+        return {
+          addBtn: this.vaildData(this.permission.alarmgroupuser_add, false),
+          viewBtn: this.vaildData(this.permission.alarmgroupuser_view, false),
+          delBtn: this.vaildData(this.permission.alarmgroupuser_delete, false),
+          editBtn: this.vaildData(this.permission.alarmgroupuser_edit, false)
+        };
+      },
+      ids() {
+        let ids = [];
+        this.selectionList.forEach(ele => {
+          ids.push(ele.id);
+        });
+        return ids.join(",");
+      }
+    },
+    methods: {
+      rowSaveChild(row, done, loading) {
+        add(row).then(() => {
+          this.onLoadChild(this.pageChild);
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          done();
+        }, error => {
+          loading();
+          window.console.log(error);
+        });
+      },
+      rowUpdateChild(row, index, done, loading) {
+        update(row).then(() => {
+          this.onLoadChild(this.pageChild);
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          done();
+        }, error => {
+          loading();
+          console.log(error);
+        });
+      },
+      rowDelChild(row) {
+        this.$confirm("确定将选择数据删除?", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        })
+          .then(() => {
+            return remove(row.id);
+          })
+          .then(() => {
+            this.onLoadChild(this.pageChild);
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+          });
+      },
+      handleDeleteChild() {
+        if (this.selectionList.length === 0) {
+          this.$message.warning("请选择至少一条数据");
+          return;
+        }
+        this.$confirm("确定将选择数据删除?", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        })
+          .then(() => {
+            return remove(this.ids);
+          })
+          .then(() => {
+            this.onLoadChild(this.pageChild);
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+            this.$refs.crud.toggleSelection();
+          });
+      },
+      beforeOpenChild(done, type) {
+        if (["edit", "view"].includes(type)) {
+          getDetail(this.formChild.id).then(res => {
+            this.formChild = res.data.data;
+          });
+        }
+        done();
+      },
+      searchResetChild() {
+        this.query = {};
+        this.onLoadChild(this.pageChild);
+      },
+      searchChangeChild(params, done) {
+        this.query = params;
+        this.pageChild.currentPage = 1;
+        this.onLoadChild(this.pageChild, params);
+        done();
+      },
+      selectionChangeChild(list) {
+        this.selectionList = list;
+      },
+      selectionClearChild() {
+        this.selectionList = [];
+        this.$refs.crud.toggleSelection();
+      },
+      currentChangeChild(currentPage){
+        this.pageChild.currentPage = currentPage;
+      },
+      sizeChangeChild(pageSize){
+        this.pageChild.pageSize = pageSize;
+      },
+      refreshChangeChild() {
+        this.onLoadChild(this.pageChild, this.query);
+      },
+      onLoadChild(page, params = {}) {
+        this.loading = true;
+        getList(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
+          const data = res.data.data;
+          this.pageChild.total = data.total;
+          this.dataChild = data.records;
+          this.loadingChild = false;
+          this.selectionClearChild();
+        });
+      }
+    }
+  };
+</script>
+
+<style>
+</style>

+ 1463 - 0
src/views/device/iotdevice.vue

@@ -0,0 +1,1463 @@
+<template>
+  <basic-container>
+    <el-dialog  :append-to-body="true" :close-on-click-modal="false" :modal-append-to-body="false" :visible.sync="alarmRecordVisible" title="历史告警记录"
+                width="80%" height="50%">
+      <alarmhistory :imei="imei" ref="alarmRecordRef"></alarmhistory>
+    </el-dialog>
+    <el-dialog  :append-to-body="true" :close-on-click-modal="false" :modal-append-to-body="false" :visible.sync="editVisible" title="编辑"
+                width="80%">
+      <avue-form v-model="editForm" :option="option" @submit="submitSmartDevice">
+        <template slot="mapSelect">
+
+          <input class="el-input--small el-input__inner" placeholder="选择地址" @click="mapVisible2 = true">
+          <!-- <avue-map v-model="editForm.mapSelect"></avue-map> -->
+        </template>
+      </avue-form>
+    </el-dialog>
+    <el-dialog :append-to-body="true" :close-on-click-modal="false" :modal-append-to-body="false" :visible.sync="mapVisible2"
+               title="编辑地址" width="80%">
+      <customAvueMap v-if="mapVisible2" v-model="editForm.mapSelect"></customAvueMap>
+    </el-dialog>
+    <el-dialog  :append-to-body="true" :close-on-click-modal="false" :modal-append-to-body="false" :visible.sync="viewVisible" title="详情"
+                width="80%">
+      <avue-form v-model="detailForm" :option="detailoption" disabled="false">
+
+      </avue-form>
+    </el-dialog>
+
+    <el-dialog :modal-append-to-body="false" :visible.sync="detailVisible" :title="titleText" width="80%">
+      <el-tabs @tab-click="handleClick" v-model="activeName">
+        <el-tab-pane label="设备详情" name="first">
+          <device-detail pic="/img/device/smoke.png" :device="deviceDetail" v-if="deviceDetail.deviceType == 100004 || deviceDetail.deviceType == 10000002"></device-detail>
+          <device-detail pic="/img/device/gas.png" :device="deviceDetail" v-if="deviceDetail.deviceType == 100020 || deviceDetail.deviceType == 10000017 || deviceDetail.deviceType == 100055"></device-detail>
+          <device-detail pic="/img/device/cover.png" :device="deviceDetail" v-if="deviceDetail.deviceType == 3"></device-detail>
+          <device-detail pic="/img/device/alarm.png" :device="deviceDetail" v-if="deviceDetail.deviceType == 950414"></device-detail>
+          <device-detail pic="/img/device/lamp.png" :device="deviceDetail" v-if="deviceDetail.deviceType == 100011"></device-detail>
+          <device-detail pic="/img/device/fire_hydrant.png" :device="deviceDetail" v-if="deviceDetail.deviceType == 960417"></device-detail>
+          <device-detail pic="/img/device/trashbin.png" :device="deviceDetail" v-if="deviceDetail.deviceType == 100022"></device-detail>
+          <device-detail pic="/img/device/parkingmonitor.png" :device="deviceDetail" v-if="deviceDetail.deviceType == 100007"></device-detail>
+          <device-detail pic="/img/device/gate.png" :device="deviceDetail" v-if="deviceDetail.deviceType == 9"></device-detail>
+        </el-tab-pane>
+        <!--<el-tab-pane label="告警设置" name="second">-->
+        <!--  <alarm :alarmData="alarmData" :alarmSetData="alarmSetData" :residential-id="residentialId"></alarm>-->
+        <!--</el-tab-pane>-->
+      </el-tabs>
+    </el-dialog>
+    <el-container>
+      <el-main>
+        <template>
+          <el-carousel :interval="5000" type="card" height="200px">
+            <el-carousel-item v-for="item in deviceCount" :key="item">
+              <el-container>
+                <el-header style="background-color: rgb(83,168,255);height: 65px">
+                  <div class="titleLabel">
+                    <el-row :gutter="40">
+                      <div @click="deviceClick(item.deviceType)">
+                        <el-col :span="20"><div class="titleText">{{item.deviceTypeName}}</div></el-col>
+                        <el-col :span="4"><div class="titleCount">{{item.deviceCount}}</div></el-col>
+                      </div>
+                    </el-row>
+                  </div>
+                </el-header>
+                <el-main>
+                  <div style="margin-left: 100px">
+                    <avue-data-display :option="dataShow(item)"></avue-data-display>
+                  </div>
+                </el-main>
+              </el-container>
+            </el-carousel-item>
+          </el-carousel>
+        </template>
+
+      </el-main>
+
+    </el-container>
+
+    <el-divider class="divider-bottom"></el-divider>
+
+    <avue-crud :option="option"
+               :table-loading="loading"
+               :data="data"
+               :page="page"
+               :permission="permissionList"
+               :before-open="beforeOpen"
+               v-model="form"
+               ref="crud"
+               @row-update="rowUpdate"
+               @row-save="rowSave"
+               @row-del="rowDel"
+               @search-change="searchChange"
+               @search-reset="searchReset"
+               @selection-change="selectionChange"
+               @current-change="currentChange"
+               @size-change="sizeChange"
+               @refresh-change="refreshChange"
+               @on-load="onLoad">
+
+      <template slot="mapSelectForm" slot-scope="scope">
+        <div>
+          <input class="el-input--small el-input__inner" placeholder="选择地址" @click="mapVisible = true">
+          <el-dialog :append-to-body="true" :close-on-click-modal="false" :modal-append-to-body="false" :visible.sync="mapVisible"
+                     title="编辑地址" width="80%">
+            <customAvueMap v-if="mapVisible" v-model="scope.row.mapSelect"></customAvueMap>
+          </el-dialog>
+        </div>
+        <!-- <avue-map v-model="scope.row.mapSelect"></avue-map> -->
+      </template>
+      <template slot="menu" slot-scope="scope">
+        <!--         <el-button icon="el-icon-view" type="text" @click="viewDetail(scope.row)">查看</el-button>-->
+        <el-button v-if="permission.bind_residential" icon="el-icon-paperclip" :class="{changeBind: !!scope.row.residentialId}" type="text" @click="showDeviceBind(scope.row)">{{!scope.row.residentialId ? '设备绑定' : '设备改绑'}}</el-button>
+        <el-button type="text" size="small" icon="el-icon-setting">
+          <el-dropdown @command="tip">
+            <span class="el-dropdown-link">
+              操作<i class="el-icon-arrow-down el-icon--right"> </i>
+            </span>
+            <el-dropdown-menu slot="dropdown">
+              <el-dropdown-item v-if="permission.smartdevice_view" icon="el-icon-view" type="text" @click.native="viewDetail(scope.row)">查看</el-dropdown-item>
+              <el-dropdown-item v-if="permission.smartdevice_edit" divided @click.native="edit(scope.row)" icon="el-icon-edit">编辑</el-dropdown-item>
+              <el-dropdown-item v-if="permission.bind_residential" icon="el-icon-paperclip" :class="{changeBind: !!scope.row.residentialId}" type="text" @click.native="showDeviceBind(scope.row)">{{!scope.row.residentialId ? '设备绑定' : '设备改绑'}}</el-dropdown-item>
+              <el-dropdown-item v-if="permission.bind_enterprises" icon="el-icon-office-building" type="text" @click.native="showEnterpriseSelect(scope.row)">绑定企业</el-dropdown-item>
+              <el-dropdown-item divided v-if="permission.alarm_view && scope.row.imei!=''" @click.native="viewAlarmRecord(scope.row)" icon="el-icon-bell">历史告警</el-dropdown-item>
+            </el-dropdown-menu>
+          </el-dropdown>
+        </el-button>
+
+      </template>
+
+      <template slot="battery" slot-scope="scope">
+        <!-- <battery style=" width: 90px;height: 30px;" :proIsCharge="proIsCharge" :proQuantity="scope.row.battery"></battery> -->
+        <el-progress v-if="scope.row.battery>20" color="green" :text-inside="true" :stroke-width="18" :percentage="scope.row.battery"></el-progress>
+        <el-progress v-if="scope.row.battery<20 ||scope.row.battery == 20" color="red" :text-inside="true"
+                     :stroke-width="18" :percentage="scope.row.battery"></el-progress>
+      </template>
+
+      <template slot="signalIntensity" slot-scope="scope">
+        <img src="../../../public/img/device/signal0.png" :alt="scope.row.signalIntensity" :title="scope.row.signalIntensity"
+             style="width: 30px;height: 30px;text-align: center;" v-if="scope.row.signalIntensity<-100 || scope.row.signalIntensity==-100">
+        <img src="../../../public/img/device/signal1.png" :alt="scope.row.signalIntensity" :title="scope.row.signalIntensity"
+             style="width: 30px;height: 30px;text-align: center;" v-if="scope.row.signalIntensity>-100 && (scope.row.signalIntensity<-88 || scope.row.signalIntensity == -88)">
+        <img src="../../../public/img/device/signal2.png" :alt="scope.row.signalIntensity" :title="scope.row.signalIntensity"
+             style="width: 30px;height: 30px;text-align: center;" v-if="scope.row.signalIntensity>-88 && (scope.row.signalIntensity<-77 || scope.row.signalIntensity == -77)">
+        <img src="../../../public/img/device/signal3.png" :alt="scope.row.signalIntensity" :title="scope.row.signalIntensity"
+             style="width: 30px;height: 30px;text-align: center;" v-if="scope.row.signalIntensity>-66 && (scope.row.signalIntensity<-55 || scope.row.signalIntensity == -55)">
+        <img src="../../../public/img/device/signal4.png" :alt="scope.row.signalIntensity" :title="scope.row.signalIntensity"
+             style="width: 30px;height: 30px;text-align: center;" v-if="scope.row.signalIntensity>-55 || scope.row.signalIntensity==-55">
+      </template>
+    </avue-crud>
+
+    <!--    小区列表-->
+    <el-dialog :modal-append-to-body="false" append-to-body :visible.sync="bindVisible" title="设备绑定" center width="20%">
+      <div style="text-align: center;">
+        <el-select v-model="selectValue" filterable placeholder="请选择">
+          <el-option v-for="item in residentialList" :key="item.id" :label="item.name" :value="item.id">
+          </el-option>
+        </el-select>
+        <p style="margin-top: 20px;">
+          <el-button type="primary" icon="el-icon-paperclip" @click="bindDevice">绑定</el-button>
+        </p>
+      </div>
+    </el-dialog>
+
+    <!--    企业列表-->
+    <el-dialog :modal-append-to-body="true" append-to-body :visible.sync="enterpriseVisible" title="企业绑定" center width="20%">
+      <div style="text-align: center;">
+        <el-select v-model="enterpriseSelect" multiple filterable placeholder="请选择企业">
+          <el-option v-for="item in enterpriseList" :key="item.id" :label="item.enterpriseName" :value="item.id">
+          </el-option>
+        </el-select>
+        <p style="margin-top: 20px;">
+          <el-button type="primary" icon="el-icon-office-building" @click="enterpriseBindDevice">绑定</el-button>
+        </p>
+      </div>
+    </el-dialog>
+
+  </basic-container>
+</template>
+
+
+
+<script>
+  import {
+    getList,
+    getDetail,
+    add,
+    update,
+    remove,
+    deviceListCount
+  } from "@/api/device/iotdevice";
+  // import { getList as getUserList} from "@/api/system/user";
+  import {
+    mapGetters
+  } from "vuex";
+  // import {getAllList} from "@/api/community/residential";
+  import alarmhistory from "../../components/device/alarmhistory.vue";
+  import {dataDisplay} from "@/api/dataview/dataviewoption";
+  import customAvueMap from "../../components/residential/customAvueMap.vue"
+  export default {
+    components:{
+      alarmhistory,customAvueMap
+    },
+    data() {
+      return {
+        mapVisible:false,
+        mapVisible2:false,
+        // alarmRecordForm:{},
+        // treeDateList:[],
+        enterpriseVisible:false,
+        enterpriseList:[],
+        enterpriseSelect:[],
+
+        imei:"",
+        alarmRecordVisible: false,
+        editForm: {},
+        editVisible: false,
+        residentialId : '',
+        SmartDeviceStaticVo: {},
+        deviceCount: {},
+        allVisible: true,
+        activeName: "first",
+        detailVisible: false,
+        bindVisible: false,
+        residentialList: [],
+        selectValue: '',
+        form: {},
+        detailForm:{
+        },
+        viewVisible:false,
+        titleText: '',
+        deviceDetail: {},
+
+        alarmData: [],
+        alarmSetData: [],
+
+        homeUserData: [],
+        bindedHomeUserData: [],
+        query: {},
+        loading: true,
+
+        page: {
+          pageSize: 10,
+          currentPage: 1,
+          total: 0
+        },
+
+        selectionList: [],
+        dataShowOption: {},
+        transhbinRecordOption: {
+          height: 'auto',
+          menuWidth: 200,
+          calcHeight: 30,
+          tip: false,
+          searchShow: true,
+          searchMenuSpan: 6,
+          border: true,
+          index: true,
+
+          addBtn: false,
+
+          menu: false,
+
+          selection: true,
+          dialogClickModal: false,
+          column: [
+            // {
+            //   label:"企业绑定",
+            //   prop:"enterpriseBind",
+            //   type: 'tree',
+            //   filterText:'搜索关键字制自定义',
+            //   multiple:true,
+            //   dicData:DIC
+            // },
+            {
+              label: "时间",
+              prop: "time",
+              rules: [{
+                required: true,
+                message: "请输入设备唯一标识",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "设备号",
+              prop: "deviceNumber",
+              rules: [{
+                required: true,
+                message: "请输入设备唯一标识",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "设备名称",
+              prop: "deviceName",
+              search: true,
+              rules: [{
+                required: true,
+                message: "请输入设备名称",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "描述",
+              prop: "introduce",
+              rules: [{
+                required: true,
+                message: "请输入设备注册平台标识,1:aep,2:华为,3:厂商",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "卡号",
+              prop: "cardNo",
+              rules: [{
+                required: true,
+                message: "请输入产品,对应 aep 产品的 apikey",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "重量",
+              prop: "heavy",
+              rules: [{
+                required: true,
+                message: "请输入操作者",
+                trigger: "blur"
+              }]
+            }
+          ]
+        },
+
+        option: {
+          height: 'auto',
+          menuWidth: 300,
+          calcHeight: 30,
+          tip: false,
+          searchShow: true,
+          searchMenuSpan: 20,
+          border: true,
+          index: true,
+          viewBtn:false,
+          // addBtn: false,
+          delBtn: false,
+          editBtn: false,
+          selection: true,
+          dialogClickModal: false,
+          column: [{
+            label: "设备编码",
+            prop: "deviceId",
+            width: 100,
+            hide: true,
+            // search:true,
+            // display: false,
+            rules: [{
+              required: true,
+              message: "请输入设备唯一标识",
+              trigger: "blur"
+            }]
+          },
+            {
+              label: "IMEI号",
+              prop: "imei",
+              width: 130,
+              hide: true,
+              rules: [{
+                required: true,
+                message: "请输入IMEI号",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "设备名称",
+              prop: "deviceName",
+              searchSpan: 4,
+              search: true,
+              // width:200,
+              overHidden:true,
+              rules: [{
+                required: true,
+                message: "请输入设备名称",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "所属小区",
+              prop: "residentialId",
+              type:"select",
+              searchSpan: 4,
+              remote: true,
+              dicUrl: "/api/cyzh-community/residential/list?size=10000&name={{key}}",
+              props:{
+                label: "name",
+                value: "id"
+              },
+              dicFormatter:(res)=>{
+                return res.data.records;
+              },
+              searchFilterable: true,
+              search: true,
+              rules: [{
+                required: true,
+                message: "请输入",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "企业",
+              prop: "enterpriseIds",
+              type: "select",
+              searchSpan: 4,
+              display: false,
+              hide: true,
+              remote: true,
+              dicUrl: "/api/cyzh-enterprise/enterprise/list?enterpriseName={{key}}",
+              props:{
+                label: "enterpriseName",
+                value: "id"
+              },
+              searchFilterable: true,
+              search: false,
+              rules: [{
+                required: true,
+                message: "请输入",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "设备注册平台标识",
+              prop: "isAep",
+              type: "select",
+              width: 80,
+              dicUrl: "/api/blade-system/dict-biz/dictionary?code=device_registry_label",
+              props: {
+                label: 'dictValue',
+                value: 'dictKey'
+              },
+              dataType: "number",
+              // search: true,
+              searchLabelWidth: 140,
+              searchSpan: 8,
+
+              rules: [{
+                required: true,
+                message: "请输入设备注册平台标识,1:aep,2:华为,3:厂商",
+                trigger: "blur"
+              }]
+            },
+            {
+              label:'',
+              prop:'mapSelect',
+              // row: true,
+              // span: 20,
+              formslot: true,
+              hide: true,
+            },
+            {
+              label: "经纬度",
+              prop: "latitudeLongitude",
+              hide: true,
+              rules: [{
+                required: true,
+                message: "请输入经纬度",
+                trigger: "blur"
+              }]
+            },
+
+            {
+              label: "apikey",
+              prop: "masterKey",
+              hide: true,
+              viewDisplay:false,
+              rules: [{
+                required: false,
+                message: "请输入产品,对应 aep 产品的 apikey",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "操作者",
+              prop: "operator",
+              hide: true,
+              addDisplay: false,
+              display: false,
+              rules: [{
+                required: false,
+                message: "请输入操作者",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "产品ID",
+              prop: "productId",
+              hide: true,
+              addDisplay: false,
+              display: false,
+              rules: [{
+                required: false,
+                message: "请输入产品ID",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "订阅事件",
+              prop: "autoObserver",
+              type: "select",
+              hide: true,
+              addDisplay: false,
+              display: false,
+              dicUrl: "/api/blade-system/dict-biz/dictionary?code=auto_subscribe",
+              props: {
+                label: "dictValue",
+                value: "dictKey"
+              },
+              dataType: "number",
+              rules: [{
+                required: false,
+                message: "请输入0 自动订阅(默认),1 取消自动订阅 (LWM2M 协议选填,其他协议不填)",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "设备类型",
+              prop: "deviceType",
+              type: "select",
+              width: 70,
+              searchSpan: 4,
+              search: true,
+              dicUrl: "/api/blade-system/dict-biz/dictionary?code=iot_device_type",
+              props: {
+                label: "dictValue",
+                value: "dictKey"
+              },
+              dataType: "string",
+              // display: false,
+              rules: [{
+                required: true,
+                message: "请输入设备类型",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "安装位置",
+              prop: "deviceInstallAddress",
+              search: true,
+              viewDisplay:false,
+              rules: [{
+                required: false,
+                message: "请输入安装位置",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "设备状态",
+              prop: "deviceStatus",
+              type: "select",
+              search: true,
+              searchSpan: 4,
+              width: 70,
+              display: false,
+              addDisplay: false,
+              dicUrl: "/api/blade-system/dict-biz/dictionary?code=device_status",
+              props: {
+                label: "dictValue",
+                value: "dictKey"
+              },
+              dataType: "number",
+              rules: [{
+                required: true,
+                message: "请输入设备状态",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "电池电量",
+              prop: "battery",
+              slot: true,
+              width: 100,
+              display: false,
+              addDisplay: false,
+              rules: [{
+                required: true,
+                message: "请输入电池电量",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "信号强度",
+              prop: "signalIntensity",
+              slot: true,
+              display: false,
+              width: 80,
+              addDisplay: false,
+              rules: [{
+                required: true,
+                message: "请输入信号强度",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "厂家名称",
+              prop: "manufacturers",
+              hide: true,
+              rules: [{
+                required: false,
+                message: "请输入厂家名称",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "厂商编号(附录)",
+              prop: "manufacturersNo",
+              hide: true,
+              display: false,
+              addDisplay: false,
+              rules: [{
+                required: false,
+                message: "请输入厂商编号(附录)",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "设备型号",
+              prop: "deviceSpecld",
+              hide: true,
+              rules: [{
+                required: false,
+                message: "请输入设备型号",
+                trigger: "blur"
+              }]
+            },
+
+            {
+              label: "iccid",
+              prop: "iccid",
+              display: false,
+              addDisplay: false,
+              hide: true,
+              rules: [{
+                required: false,
+                message: "请输入iccid",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "Mcu软件版本",
+              prop: "mcuEdition",
+              hide: true,
+              viewDisplay:false,
+              rules: [{
+                required: false,
+                message: "请输入Mcu软件版本",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "NB模组型号",
+              prop: "nbModuleModel",
+              hide: true,
+              viewDisplay:false,
+              rules: [{
+                required: false,
+                message: "请输入NB模组型号",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "NB模组版本信息",
+              prop: "nbModuleEdition",
+              hide: true,
+              viewDisplay:false,
+              rules: [{
+                required: false,
+                message: "请输入NB模组版本信息",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "最后更新时间",
+              prop: "lastUpdateTime",
+              hide: true,
+              display: false,
+              addDisplay: false,
+              type: "datetime",
+              valueFormat: "yyyy-MM-dd HH:mm:ss",
+              rules: [{
+                required: false,
+                message: "请输入最后更新时间",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "心跳保护时间",
+              prop: "heartbeatTime",
+              type: "datetime",
+              addDisplay: false,
+              display: false,
+              hide: true,
+              valueFormat: "yyyy-MM-dd HH:mm:ss",
+              rules: [{
+                required: false,
+                message: "请输入心跳保护时间",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "无线信号覆盖等级",
+              prop: "wirelessLevel",
+              hide: true,
+              display: false,
+              addDisplay: false,
+              rules: [{
+                required: false,
+                message: "请输入无线信号覆盖等级",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "当前磁场值",
+              prop: "magneticField",
+              hide: true,
+              display: false,
+              addDisplay: false,
+              rules: [{
+                required: false,
+                message: "请输入当前磁场值",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "终端发射功率",
+              prop: "transmittingPower",
+              hide: true,
+              display: false,
+              addDisplay: false,
+              rules: [{
+                required: false,
+                message: "请输入终端发射功率",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "终端接收功率",
+              prop: "receivingPower",
+              hide: true,
+              display: false,
+              addDisplay: false,
+              rules: [{
+                required: false,
+                message: "请输入终端接收功率",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "信噪比",
+              prop: "signalNoiseRatio",
+              hide: true,
+              addDisplay: false,
+              display: false,
+              rules: [{
+                required: false,
+                message: "请输入信噪比",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "IMSI",
+              prop: "imsi",
+              hide: true,
+              viewDisplay:false,
+              rules: [{
+                required: false,
+                message: "请输入IMSI",
+                trigger: "blur"
+              }]
+            },
+
+          ]
+        },
+        //详情字段
+        detailoption: {
+          submitBtn:false,
+          emptyBtn:false,
+          column: [{
+            label: "设备编码",
+            prop: "deviceId",
+            width: 100,
+            hide: true,
+            // search:true,
+            // display: false,
+            rules: [{
+              required: true,
+              message: "请输入设备唯一标识",
+              trigger: "blur"
+            }]
+          },
+            {
+              label: "IMEI号",
+              prop: "imei",
+              width: 130,
+              hide: true,
+              rules: [{
+                required: true,
+                message: "请输入IMEI号",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "设备名称",
+              prop: "deviceName",
+              searchSpan: 4,
+              search: true,
+              // width:200,
+              overHidden:true,
+              rules: [{
+                required: true,
+                message: "请输入设备名称",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "归属",
+              prop: "residentialId",
+              type:"select",
+              searchSpan: 4,
+              remote: true,
+              dicUrl: "/api/cyzh-community/residential/list?name={{key}}",
+              props:{
+                label: "name",
+                value: "id"
+              },
+              searchFilterable: true,
+              search: true,
+              rules: [{
+                required: true,
+                message: "请输入",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "企业",
+              prop: "enterpriseIds",
+              type: "select",
+              searchSpan: 4,
+              display: false,
+              hide: true,
+              remote: true,
+              dicUrl: "/api/cyzh-enterprise/enterprise/list?enterpriseName={{key}}",
+              props:{
+                label: "enterpriseName",
+                value: "id"
+              },
+              searchFilterable: true,
+              search: false,
+              rules: [{
+                required: true,
+                message: "请输入",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "设备注册平台标识",
+              prop: "isAep",
+              type: "select",
+              width: 80,
+              dicUrl: "/api/blade-system/dict-biz/dictionary?code=device_registry_label",
+              props: {
+                label: 'dictValue',
+                value: 'dictKey'
+              },
+              dataType: "number",
+              // search: true,
+              searchLabelWidth: 140,
+              searchSpan: 8,
+
+              rules: [{
+                required: true,
+                message: "请输入设备注册平台标识,1:aep,2:华为,3:厂商",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "经纬度",
+              prop: "latitudeLongitude",
+              hide: true,
+              rules: [{
+                required: true,
+                message: "请输入经纬度",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "操作者",
+              prop: "operator",
+              hide: true,
+              addDisplay: false,
+              display: false,
+              rules: [{
+                required: false,
+                message: "请输入操作者",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "产品ID",
+              prop: "productId",
+              hide: true,
+              addDisplay: false,
+              display: false,
+              rules: [{
+                required: false,
+                message: "请输入产品ID",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "订阅事件",
+              prop: "autoObserver",
+              type: "select",
+              hide: true,
+              addDisplay: false,
+              display: false,
+              dicUrl: "/api/blade-system/dict-biz/dictionary?code=auto_subscribe",
+              props: {
+                label: "dictValue",
+                value: "dictKey"
+              },
+              dataType: "number",
+              rules: [{
+                required: false,
+                message: "请输入0 自动订阅(默认),1 取消自动订阅 (LWM2M 协议选填,其他协议不填)",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "设备类型",
+              prop: "deviceType",
+              type: "select",
+              width: 70,
+              searchSpan: 4,
+              search: true,
+              dicUrl: "/api/blade-system/dict-biz/dictionary?code=iot_device_type",
+              props: {
+                label: "dictValue",
+                value: "dictKey"
+              },
+              dataType: "string",
+              // display: false,
+              rules: [{
+                required: true,
+                message: "请输入设备类型",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "设备状态",
+              prop: "deviceStatus",
+              type: "select",
+              search: true,
+              searchSpan: 4,
+              width: 70,
+              display: false,
+              addDisplay: false,
+              dicUrl: "/api/blade-system/dict-biz/dictionary?code=device_status",
+              props: {
+                label: "dictValue",
+                value: "dictKey"
+              },
+              dataType: "number",
+              rules: [{
+                required: true,
+                message: "请输入设备状态",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "电池电量",
+              prop: "battery",
+              slot: true,
+              width: 100,
+              display: false,
+              addDisplay: false,
+              rules: [{
+                required: true,
+                message: "请输入电池电量",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "信号强度",
+              prop: "signalIntensity",
+              slot: true,
+              display: false,
+              width: 80,
+              addDisplay: false,
+              rules: [{
+                required: true,
+                message: "请输入信号强度",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "厂家名称",
+              prop: "manufacturers",
+              hide: true,
+              rules: [{
+                required: false,
+                message: "请输入厂家名称",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "厂商编号(附录)",
+              prop: "manufacturersNo",
+              hide: true,
+              display: false,
+              addDisplay: false,
+              rules: [{
+                required: false,
+                message: "请输入厂商编号(附录)",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "设备型号",
+              prop: "deviceSpecld",
+              hide: true,
+              rules: [{
+                required: false,
+                message: "请输入设备型号",
+                trigger: "blur"
+              }]
+            },
+
+          ]
+        },
+        data: []
+      };
+    },
+
+    computed: {
+      ...mapGetters(["permission"]),
+      permissionList() {
+        return {
+          addBtn: this.vaildData(this.permission.smartdevice_add, false),
+          viewBtn: this.vaildData(this.permission.smartdevice_view, false),
+          delBtn: this.vaildData(this.permission.smartdevice_delete, false),
+          editBtn: this.vaildData(this.permission.smartdevice_edit, false)
+        };
+      },
+      ids() {
+        let ids = [];
+        this.selectionList.forEach(ele => {
+          ids.push(ele.id);
+        });
+        return ids.join(",");
+      }
+    },
+    watch: {
+      'form.mapSelect': {
+        handler: function (value) {
+          if (!value) {
+            return
+          } else {
+            this.form.longitude = this.form.mapSelect.longitude;
+            this.form.latitude = this.form.mapSelect.latitude;
+            this.form.latitudeLongitude = this.form.mapSelect.longitude + ',' + this.form.mapSelect.latitude;
+            this.form.deviceInstallAddress = this.form.mapSelect.formattedAddress;
+          }
+        },
+      },
+      'editForm.mapSelect': {
+        handler: function (value) {
+          if (!value) {
+            return
+          } else {
+            this.editForm.longitude = this.editForm.mapSelect.longitude;
+            this.editForm.latitude = this.editForm.mapSelect.latitude;
+            this.editForm.latitudeLongitude = this.editForm.mapSelect.longitude + ',' + this.editForm.mapSelect.latitude;
+            // this.editForm.deviceInstallAddress = this.editForm.mapSelect.formattedAddress;
+          }
+        },
+      },
+    },
+    created() {
+      deviceListCount({deviceUsage : 20}).then(res =>{
+        this.deviceCount = res.data.data;
+      })
+    },
+    mounted() {
+      this.option.column[4].search = this.permission.bind_enterprises;
+
+      let tenantType = localStorage.getItem("tenantType");
+      const residentialColumn = this.findObject(this.option.column, "residentialId");
+      if (tenantType == 1) { //园区
+        residentialColumn.label = "所属区域";
+      } else { //社区
+        residentialColumn.label = "所属小区";
+      }
+
+    },
+    methods: {
+      dataShow(obj){
+        return dataDisplay(obj,this)
+      },
+      select(deviceType,deviceStatus,params={}) {
+        this.$refs.crud.searchForm.deviceType = deviceType;
+        this.query.deviceType = deviceType;
+        this.$refs.crud.searchForm.deviceStatus = deviceStatus;
+        this.query.deviceStatus = deviceStatus;
+        this.onLoad(this.page,this.query);
+      },
+      enterpriseBindDevice(){
+        let enterpriseSelectStr = '';
+
+        for (let i = 0; i < this.enterpriseSelect.length; i++){
+          enterpriseSelectStr += this.enterpriseSelect[i]+',';
+        }
+        this.form.enterpriseIds = enterpriseSelectStr;
+        console.log(this.form.enterpriseIds);
+        //保存
+        update(this.form).then(() => {
+          this.onLoad(this.page);
+          this.enterpriseVisible = false;
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+        }, error => {
+          console.log(error);
+        });
+      },
+      showEnterpriseSelect(row){
+        if (this.enterpriseList.length == 0){
+          //  请求获取企业列表
+          getEnterpriseList().then(res => {
+            this.enterpriseList = res.data.data;
+            this.enterpriseVisible = true;
+            console.log(res);
+          })
+        }else{
+          this.enterpriseVisible = true;
+        }
+        this.form = row;
+      },
+      viewAlarmRecord(row,params={}){
+        this.imei = row.imei;
+        this.alarmRecordVisible = true;
+        this.$nextTick(()=>{
+          this.$refs.alarmRecordRef.init();
+        })
+      },
+      submitSmartDevice(row,done,loading){
+        update(this.editForm).then(() => {
+          this.onLoad(this.page);
+          this.editVisible = false;
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          done();
+        }, error => {
+          loading();
+          console.log(error);
+        });
+      },
+      edit(row){
+        this.editForm = row;
+        this.editVisible = true;
+      },
+      deviceClick(type){
+        this.$refs.crud.searchForm.deviceType = type;
+        this.query.deviceType = type;
+        this.onLoad(this.page);
+      },
+      handleClick(tab, event) {
+        console.log(tab + " " + event)
+      },
+      showDeviceBind(row){
+        this.selectValue = row.residentialId;
+        if (this.residentialList.length == 0){
+          //  请求获取小区列表
+          getAllList().then(res => {
+            this.residentialList = res.data.data;
+            this.bindVisible = true;
+          })
+        }else{
+          this.bindVisible = true;
+        }
+        this.form = row;
+      },
+      bindDevice(){
+        this.form.residentialId = this.selectValue;
+        //保存
+        update(this.form).then(() => {
+          this.onLoad(this.page);
+          this.bindVisible = false;
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+        }, error => {
+          console.log(error);
+        });
+      },
+      rowView(row){
+
+      },
+      viewDetail(row) {
+        this.detailForm = row;
+        this.viewVisible = true;
+        // console.log("row" + JSON.stringify(row))
+        // this.titleText = row.$deviceType
+        // this.deviceDetail = row;
+        // /*getUserList(this.page.currentPage, this.page.pageSize, {residential: row.residentialId}).then(res =>{
+        //   this.alarmData = res.data.data.records;
+        // })*/
+        // this.residentialId = row.residentialId
+        // /*this.alarmData = [
+        //   {
+        //   name: "李德",
+        //   tel: "15089107336",
+        //   area: "阅海万家D区"
+        // }, {
+        //   name: "黄俊豪",
+        //   tel: "15145867336",
+        //   area: "阅海万家D区"
+        // }, {
+        //   name: "林旭光",
+        //   tel: "17899572954",
+        //   area: "阅海万家D区"
+        // }, {
+        //   name: "蔡志彬",
+        //   tel: "17899584512",
+        //   area: "阅海万家D区"
+        // }, {
+        //   name: "黄坚伟",
+        //   tel: "17899571256",
+        //   area: "阅海万家D区"
+        // } ];*/
+        // this.alarmSetData = [
+        //   {
+        //     name: "蔡志彬",
+        //     tel: "17899584512",
+        //     area: "阅海万家D区"
+        //   }, {
+        //     name: "黄坚伟",
+        //     tel: "17899571256",
+        //     area: "阅海万家D区"
+        //   }];
+        // this.homeUserData = [
+        //   {
+        //     name: "李德",
+        //     tel: "15089107336",
+        //     area: "阅海万家D区"
+        //   }, {
+        //     name: "黄俊豪",
+        //     tel: "15145867336",
+        //     area: "阅海万家D区"
+        //   }, {
+        //     name: "林旭光",
+        //     tel: "17899572954",
+        //     area: "阅海万家D区"
+        //   }, {
+        //     name: "蔡志彬",
+        //     tel: "17899584512",
+        //     area: "阅海万家D区"
+        //   }, {
+        //     name: "黄坚伟",
+        //     tel: "17899571256",
+        //     area: "阅海万家D区"
+        //   }];
+        // this.bindedHomeUserData = [];
+        // this.detailVisible = true;
+      },
+      rowSave(row, done, loading) {
+        add(row).then(() => {
+          this.onLoad(this.page);
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          done();
+        }, error => {
+          loading();
+          window.console.log(error);
+        });
+      },
+      rowUpdate(row, index, done, loading) {
+        update(row).then(() => {
+          this.onLoad(this.page);
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          done();
+        }, error => {
+          loading();
+          console.log(error);
+        });
+      },
+      rowDel(row) {
+        this.$confirm("确定将选择数据删除?", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        })
+          .then(() => {
+            return remove(row.id);
+          })
+          .then(() => {
+            this.onLoad(this.page);
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+          });
+      },
+      handleDelete() {
+        if (this.selectionList.length === 0) {
+          this.$message.warning("请选择至少一条数据");
+          return;
+        }
+        this.$confirm("确定将选择数据删除?", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        })
+          .then(() => {
+            return remove(this.ids);
+          })
+          .then(() => {
+            this.onLoad(this.page);
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+            this.$refs.crud.toggleSelection();
+          });
+      },
+      beforeOpen(done, type) {
+        if (["edit", "view"].includes(type)) {
+          getDetail(this.form.id).then(res => {
+            this.form = res.data.data;
+          });
+        }
+        done();
+      },
+      searchReset() {
+        this.query = {};
+        this.onLoad(this.page);
+      },
+
+      searchChange(params, done) {
+        this.query = params;
+        this.page.currentPage = 1;
+        this.onLoad(this.page, params);
+        done();
+      },
+      selectionChange(list) {
+        this.selectionList = list;
+      },
+      selectionClear() {
+        this.selectionList = [];
+        this.$refs.crud.toggleSelection();
+      },
+      currentChange(currentPage) {
+        this.page.currentPage = currentPage;
+      },
+      sizeChange(pageSize) {
+        this.page.pageSize = pageSize;
+      },
+      refreshChange() {
+        this.onLoad(this.page, this.query);
+      },
+
+
+      onLoad(page, params = {}) {
+        this.loading = true;
+        params.deviceUsage = 20; //公共区域
+        /*getSmartDeviceStaticVo(Object.assign(params, this.query)).then(res =>{
+          this.SmartDeviceStaticVo = res.data.data;
+        })*/
+        getList(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
+          const data = res.data.data;
+          this.page.total = data.total;
+          this.data = data.records;
+          this.loading = false;
+          this.selectionClear();
+        });
+
+
+      }
+    }
+  };
+</script>
+
+<style scoped>
+  .avue-crud{
+    padding-bottom: 20px;
+    /* height: 800px; */
+  }
+  >>> .el-pagination{
+    position: absolute;
+    top: 0px;
+    bottom: 0px;
+    /* height: 100px; */
+  }
+  .shadow{
+    box-shadow: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04)
+  }
+  .titleLabel{
+    color: white;
+    height: 65px;
+    line-height: 65px;
+  }
+  .titleText{
+    font-size: 25px;
+    font-weight: bolder;
+    padding-left: 10px;
+  }
+  .titleCount{
+    font-size: 25px;
+    font-weight: bolder;
+  }
+  .colMarginBottom{
+    margin-bottom: 0px;
+  }
+  .statusText{
+    font-size: 14px;
+    font-weight: bolder;
+    color: green;
+  }
+  .statusCount{
+    font-size: 14px;
+    font-weight: 700;
+    color: red;
+  }
+  .el-divider--vertical {
+    /* height: 100%; */
+  }
+  >>> .el-divider--horizontal{
+    margin: 0px !important;
+    margin-bottom: 5px !important;
+  }
+  >>> .el-main{
+    overflow: hidden;
+  }
+  >>> .divider-bottom{
+    margin: 0 !important;
+    margin-bottom: 10px !important;
+  }
+  >>> aside font {
+    cursor: pointer;
+  }
+  >>> .changeBind {
+    color: orange;
+  }
+
+  .el-carousel__item:nth-child(2n) {
+    background-color: rgb(217,236,255);
+  }
+
+  .el-carousel__item:nth-child(2n+1) {
+    background-color: rgb(236,245,255);
+  }
+</style>

+ 245 - 0
src/views/device/iotdevicedetail.vue

@@ -0,0 +1,245 @@
+<template>
+  <basic-container>
+    <avue-crud :option="option"
+               :table-loading="loading"
+               :data="data"
+               :page.sync="page"
+               :permission="permissionList"
+               :before-open="beforeOpen"
+               v-model="form"
+               ref="crud"
+               @row-update="rowUpdate"
+               @row-save="rowSave"
+               @row-del="rowDel"
+               @search-change="searchChange"
+               @search-reset="searchReset"
+               @selection-change="selectionChange"
+               @current-change="currentChange"
+               @size-change="sizeChange"
+               @refresh-change="refreshChange"
+               @on-load="onLoad">
+      <template slot="menuLeft">
+        <el-button type="danger"
+                   size="small"
+                   icon="el-icon-delete"
+                   plain
+                   v-if="permission.iotdevicedetail_delete"
+                   @click="handleDelete">删 除
+        </el-button>
+      </template>
+    </avue-crud>
+  </basic-container>
+</template>
+
+<script>
+  import {getList, getDetail, add, update, remove} from "@/api/device/iotdevicedetail";
+  import {mapGetters} from "vuex";
+
+  export default {
+    data() {
+      return {
+        form: {},
+        query: {},
+        loading: true,
+        page: {
+          pageSize: 10,
+          currentPage: 1,
+          total: 0
+        },
+        selectionList: [],
+        option: {
+          height:'auto',
+          calcHeight: 30,
+          tip: false,
+          searchShow: true,
+          searchMenuSpan: 6,
+          border: true,
+          index: true,
+          viewBtn: true,
+          selection: true,
+          dialogClickModal: false,
+          column: [
+            {
+              label: "iot设备的主键",
+              prop: "deviceId",
+              rules: [{
+                required: true,
+                message: "请输入iot设备的主键",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "个性化字段名称",
+              prop: "attributeName",
+              rules: [{
+                required: true,
+                message: "请输入个性化字段名称",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "个性化字段值",
+              prop: "attributeValue",
+              rules: [{
+                required: true,
+                message: "请输入个性化字段值",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "个性化字段的类型",
+              prop: "attributeType",
+              rules: [{
+                required: true,
+                message: "请输入个性化字段的类型",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "个性化字段的长度",
+              prop: "attributeLength",
+              rules: [{
+                required: true,
+                message: "请输入个性化字段的长度",
+                trigger: "blur"
+              }]
+            },
+          ]
+        },
+        data: []
+      };
+    },
+    computed: {
+      ...mapGetters(["permission"]),
+      permissionList() {
+        return {
+          addBtn: this.vaildData(this.permission.iotdevicedetail_add, false),
+          viewBtn: this.vaildData(this.permission.iotdevicedetail_view, false),
+          delBtn: this.vaildData(this.permission.iotdevicedetail_delete, false),
+          editBtn: this.vaildData(this.permission.iotdevicedetail_edit, false)
+        };
+      },
+      ids() {
+        let ids = [];
+        this.selectionList.forEach(ele => {
+          ids.push(ele.id);
+        });
+        return ids.join(",");
+      }
+    },
+    methods: {
+      rowSave(row, done, loading) {
+        add(row).then(() => {
+          this.onLoad(this.page);
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          done();
+        }, error => {
+          loading();
+          window.console.log(error);
+        });
+      },
+      rowUpdate(row, index, done, loading) {
+        update(row).then(() => {
+          this.onLoad(this.page);
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          done();
+        }, error => {
+          loading();
+          console.log(error);
+        });
+      },
+      rowDel(row) {
+        this.$confirm("确定将选择数据删除?", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        })
+          .then(() => {
+            return remove(row.id);
+          })
+          .then(() => {
+            this.onLoad(this.page);
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+          });
+      },
+      handleDelete() {
+        if (this.selectionList.length === 0) {
+          this.$message.warning("请选择至少一条数据");
+          return;
+        }
+        this.$confirm("确定将选择数据删除?", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        })
+          .then(() => {
+            return remove(this.ids);
+          })
+          .then(() => {
+            this.onLoad(this.page);
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+            this.$refs.crud.toggleSelection();
+          });
+      },
+      beforeOpen(done, type) {
+        if (["edit", "view"].includes(type)) {
+          getDetail(this.form.id).then(res => {
+            this.form = res.data.data;
+          });
+        }
+        done();
+      },
+      searchReset() {
+        this.query = {};
+        this.onLoad(this.page);
+      },
+      searchChange(params, done) {
+        this.query = params;
+        this.page.currentPage = 1;
+        this.onLoad(this.page, params);
+        done();
+      },
+      selectionChange(list) {
+        this.selectionList = list;
+      },
+      selectionClear() {
+        this.selectionList = [];
+        this.$refs.crud.toggleSelection();
+      },
+      currentChange(currentPage){
+        this.page.currentPage = currentPage;
+      },
+      sizeChange(pageSize){
+        this.page.pageSize = pageSize;
+      },
+      refreshChange() {
+        this.onLoad(this.page, this.query);
+      },
+      onLoad(page, params = {}) {
+        this.loading = true;
+        getList(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
+          const data = res.data.data;
+          this.page.total = data.total;
+          this.data = data.records;
+          this.loading = false;
+          this.selectionClear();
+        });
+      }
+    }
+  };
+</script>
+
+<style>
+</style>

+ 178 - 0
src/views/device/videoSurveillance.vue

@@ -0,0 +1,178 @@
+<template>
+  <basic-container>
+    <el-row>
+      <el-col span="2" align="right" style="font-size: large;" v-if="tenantType!=1">所属小区:</el-col>
+      <el-col span="2" align="right" style="font-size: large;" v-if="tenantType==1">所属区域:</el-col>
+      <el-col span="4" align="left">
+        <el-select size="small" v-model="selectResidential" filterable  clearable @change="residentialIdChange()">
+          <el-option v-for="item in residentialList" :key="item.id" :label="item.name" :value="item.id">
+          </el-option>
+        </el-select>
+
+      </el-col>
+
+      <el-col span="2" align="right" style="font-size: large;">所属楼栋:</el-col>
+      <el-col span="4" align="left">
+        <el-select size="small" v-model="selectBuilding" filterable placeholder="所属楼栋"  clearable>
+          <el-option v-for="item in buildingList" :key="item.id" :label="item.name" :value="item.id">
+          </el-option>
+        </el-select>
+
+      </el-col>
+      <el-col span="4" align="right" style="font-size: large;">设备名称:</el-col>
+      <el-col span="6" align="left">
+        <el-input v-model="deviceName" size="mini" clearable></el-input>
+
+      </el-col>
+    </el-row>
+
+
+    <div id="videoSurveillance" style="margin-top: 20px;">
+      <div class="item" v-for="(item,index) in data" :key="index">
+        <div align="center">{{item.name}}</div>
+        <video :id="'videoId'+index" controls="true" width="100%" height="100%">
+        </video>
+      </div>
+    </div>
+  </basic-container>
+</template>
+
+
+<script>
+  import {
+    getList
+  } from "@/api/community/building"
+  import {
+    getByResidentialAndDeviceName
+  } from "@/api/device/videoclouddevice";
+  import {
+    getAllList
+  } from "@/api/community/residential";
+  import {
+    getTenantTypeDetailByTenantId
+  } from "../../api/system/tenant.js";
+  import {
+    mapGetters
+  } from "vuex";
+  export default {
+    data() {
+      // http://139.9.103.171/live?port=1935&app=myapp&stream=mystream
+      // http://139.9.103.171/live?port=1935&app=myapp&stream=mystream1
+      // http://139.9.103.171/live?port=1935&app=myapp&stream=mystream3
+      return {
+        selectBuilding: "",
+        buildingList:[],
+        tenantType: "",
+        deviceName: "",
+        selectResidential: "",
+        loading: false,
+        residentialList: [],
+        value: [],
+        // baseUrlVedio: "http://139.9.103.171/live?port=1935&app=myapp&stream=",
+        baseUrlVedio: "ws://36.103.228.148:8888/live/",
+        data: []
+      }
+    },
+    computed:{
+      ...mapGetters(["userInfo"])
+    },
+    mounted() {
+      getTenantTypeDetailByTenantId(this.userInfo.tenant_id).then(res => {
+
+        if (res.data.data.tenantType == 1) {
+          this.tenantType = 1;
+        }
+      })
+      //  请求获取小区列表
+      getAllList().then(res => {
+        this.residentialList = res.data.data;
+
+      })
+      this.onLoad()
+    },
+    watch:{
+      "selectResidential":function(){
+        this.onLoad()
+      },
+      "selectBuilding":function(){
+        this.onLoad()
+      },
+      "deviceName":function(){
+        this.onLoad()
+      }
+    },
+    methods: {
+      play() {
+        this.data.map((item, index) => {
+          try {
+            let videoElement = document.getElementById('videoId' + index);
+            let flvPlayer = flvjs.createPlayer({
+              type: 'flv',
+              url: item.src
+            });
+            flvPlayer.on(flvjs.Events.ERROR, (errType, errDetail) => {
+              // errType是 NetworkError时,对应errDetail有:Exception、HttpStatusCodeInvalid、ConnectingTimeout、EarlyEof、UnrecoverableEarlyEof
+              // errType是 MediaError时,对应errDetail是MediaMSEError
+            });
+            flvPlayer.on(flvjs.Events.MEDIA_SOURCE_CLOSE || flvjs.Events.MEDIA_SOURCE_ENDED, () => {})
+            flvPlayer.attachMediaElement(videoElement);
+            flvPlayer.load();
+            flvPlayer.play();
+          } catch (e) {
+            console.log(e);
+          }
+
+        })
+      },
+      residentialIdChange(params={}){
+        params.residentialId = this.selectResidential;
+        getList(1,500,params).then((res)=>{
+          this.selectBuilding = "",
+          this.buildingList = res.data.data.records;
+        })
+      },
+      onLoad() {
+        let _this = this;
+        if (this.value&&(this.selectResidential != ""||this.selectBuilding != "" || this.deviceName !="")) {
+          getByResidentialAndDeviceName(this.selectResidential,this.selectBuilding,this.deviceName).then(res => {
+            if (res.data.code == 200) {
+              this.data = [];
+              const data = res.data.data;
+              data.forEach(item => {
+                let obj = {};
+                obj.src = this.baseUrlVedio + item.deviceNum + ".flv";
+                obj.name = item.deviceName;
+                this.data.push(obj);
+              })
+              // _this.play();
+              setTimeout(function() {
+                _this.play();
+              }, 1000)
+            }
+
+          });
+        }else{
+          this.data = [];
+        }
+      }
+    }
+  }
+</script>
+
+
+<style lang="less">
+  #videoSurveillance {
+    width: 100%;
+    height: 100%;
+    display: flex;
+    flex-wrap: wrap;
+    box-sizing: border-box;
+
+    .item {
+      width: calc(~"25% - 10px");
+      overflow: hidden;
+      border-radius: 5px;
+      margin: 5px;
+    }
+  }
+</style>

+ 863 - 0
src/views/device/videoclouddevice.vue

@@ -0,0 +1,863 @@
+<template>
+  <basic-container>
+    <avue-crud :option="option" :table-loading="loading" :data="data" :page="page" :permission="permissionList"
+               :before-open="beforeOpen" v-model="form" ref="crud" @row-update="rowUpdate" @row-save="rowSave" @row-del="rowDel"
+               @search-change="searchChange" @search-reset="searchReset" @selection-change="selectionChange" @current-change="currentChange"
+               @size-change="sizeChange" @refresh-change="refreshChange" @on-load="onLoad">
+      <template slot="menuLeft">
+        <el-button type="danger" size="small" icon="el-icon-delete" plain v-if="permission.videoclouddevice_delete"
+                   @click="handleDelete">删 除
+        </el-button>
+        <el-button type="success" icon="el-icon-paperclip" size="small" @click="showDeviceBindBatch()">批量绑定</el-button>
+      </template>
+
+      <template slot="menu" slot-scope="scope">
+        <el-button size="small" type="text" icon="el-icon-setting">
+          <el-dropdown>
+            <span class="el-dropdown-link">
+              操作<i class="el-icon-arrow-down el-icon--right"></i>
+            </span>
+            <el-dropdown-menu slot="dropdown">
+              <el-dropdown-item icon="el-icon-view" type="text" @click.native="view(scope.row)">查看</el-dropdown-item>
+              <el-dropdown-item icon="el-icon-edit" type="text" @click.native="edit(scope.row)">编辑</el-dropdown-item>
+              <el-dropdown-item icon="el-icon-video-camera" type="text" @click.native="showVideo(scope.row)">查看监控</el-dropdown-item>
+              <el-dropdown-item icon="el-icon-paperclip" type="text" @click.native="showDeviceBind(scope.row)">{{!scope.row.residentialId ? '设备绑定' : '设备改绑'}}</el-dropdown-item>
+            </el-dropdown-menu>
+
+          </el-dropdown>
+        </el-button>
+        <!--<el-button icon="el-icon-paperclip" type="text" @click="showDeviceBind(scope.row)">{{!scope.row.residentialId ? '设备绑定' : '设备改绑'}}</el-button>-->
+        <!--<el-button icon="el-icon-video-camera" type="text" @click="showVideo(scope.row)">查看监控</el-button>-->
+      </template>
+
+    </avue-crud>
+
+    <!--    小区列表-->
+    <el-dialog :modal-append-to-body="false" append-to-body :visible.sync="bindVisible" title="设备绑定" center width="20%">
+      <div style="text-align: center;">
+        <!-- <el-select v-model="selectValue" filterable placeholder="请选择">
+          <el-option v-for="item in residentialList" :key="item.id" :label="item.name" :value="item.id">
+          </el-option>
+        </el-select>
+        <p style="margin-top: 20px;">
+          <el-button type="primary" icon="el-icon-paperclip" @click="bindDevice">绑定</el-button>
+        </p> -->
+        <avue-form v-model="bindForm" :option="bindOption" @submit="bindDevice">
+
+        </avue-form>
+      </div>
+    </el-dialog>
+
+    <el-dialog :modal-append-to-body="false" append-to-body :visible.sync="bindBatchVisible" title="设备批量绑定" center
+               width="50%">
+      <div style="text-align: center;">
+        <avue-form v-model="bindBatchForm" :option="bindOption" @submit="bindBatchDevice">
+
+        </avue-form>
+        <!-- <el-select v-model="selectValue" filterable placeholder="请选择">
+          <el-option v-for="item in residentialList" :key="item.id" :label="item.name" :value="item.id">
+          </el-option>
+        </el-select>
+        <p style="margin-top: 20px;">
+          <el-button type="primary" icon="el-icon-paperclip" @click="bindBatchDevice">绑定</el-button>
+        </p> -->
+      </div>
+    </el-dialog>
+
+    <el-dialog :modal-append-to-body="false" append-to-body :visible.sync="videoVisible" title="视频监控" center width="50%">
+      <div>
+        <div align="center">{{video.name}}</div>
+        <video :id="videoId" controls="true" width="100%" height="100%">
+        </video>
+      </div>
+    </el-dialog>
+    <el-dialog :modal-append-tobody="false" append-to-body :visible.sync="editVisiable" title="编辑" width="60%">
+      <avue-form :option="option" v-model="editForm" @submit="submitVideoclouddevice"></avue-form>
+    </el-dialog>
+    <el-dialog :modal-append-tobody="false" append-to-body :visible.sync="detailVisible" title="查看" width="60%">
+      <avue-detail :option="option" v-model="detailForm"></avue-detail>
+    </el-dialog>
+
+  </basic-container>
+</template>
+
+<script>
+  import {
+    getList,
+    getDetail,
+    add,
+    update,
+    remove,
+    updateVideoDevice,
+    bindResidentialBatch
+  } from "../../api/device/videoclouddevice.js";
+  import {
+    mapGetters
+  } from "vuex";
+  import {
+    getAllList
+  } from "@/api/community/residential";
+
+  export default {
+    data() {
+      return {
+        bindBatchForm:{},
+        bindForm: {},
+        videoVisible: false,
+        video: {},
+        editVisiable: false,
+        editForm: {},
+        detailVisible: false,
+        detailForm: {},
+        selectValue: "",
+        form: {},
+        query: {},
+        loading: true,
+        bindVisible: false,
+        bindBatchVisible: false,
+        residentialList: [],
+        page: {
+          pageSize: 10,
+          currentPage: 1,
+          total: 0
+        },
+        selectionList: [],
+
+        option: {
+          menu: true,
+          height: 'auto',
+          calcHeight: 30,
+          tip: false,
+          searchShow: true,
+          searchMenuSpan: 6,
+          labelWidth: 150,
+          border: true,
+          index: true,
+          viewBtn: false,
+          editBtn: false,
+          delBtn: true,
+          selection: true,
+          dialogClickModal: false,
+          column: [{
+            label: "设备编号",
+            prop: "deviceId",
+            hide: true,
+            span: 12,
+            rules: [{
+              required: true,
+              message: "请输入设备编号",
+              trigger: "blur"
+            }]
+          },
+            {
+              label: "设备名称",
+              prop: "deviceName",
+              search: true,
+              span: 12,
+              rules: [{
+                required: true,
+                message: "请输入设备名称",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "设备号",
+              prop: "deviceNum",
+              span: 12,
+              rules: [{
+                required: true,
+                message: "请输入设备号",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "设备密码",
+              prop: "devicePassword",
+              span: 12,
+              hide: true,
+              rules: [{
+                required: true,
+                message: "请输入设备密码",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "设备类型",
+              prop: "deviceType",
+              span: 12,
+              search: true,
+              dataType: "number",
+              type: "select",
+              dicUrl: "/api/blade-system/dict-biz/dictionary?code=video_device_type",
+              props: {
+                label: 'dictValue',
+                value: 'dictKey'
+              },
+              rules: [{
+                required: true,
+                message: "请输入设备类型(132:IPC;111:DVR;118:NVR,114:解码器)",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "型号",
+              prop: "modelSequence",
+              span: 12,
+              hide: true,
+              rules: [{
+                required: true,
+                message: "请输入型号",
+                trigger: "blur"
+              }]
+            },
+            {
+              // label: "协议类型(1:GB28181,2:ONVIF)",
+              label: "协议类型",
+              prop: "protocolType",
+              span: 12,
+              hide: true,
+              rules: [{
+                required: true,
+                message: "请输入协议类型(1:GB28181,2:ONVIF)",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "是否在线",
+              prop: "isOnline",
+              span: 12,
+              dataType: "number",
+              type: "select",
+              search: true,
+              dicUrl: "/api/blade-system/dict-biz/dictionary?code=online_or_offline",
+              props: {
+                label: 'dictValue',
+                value: 'dictKey'
+              },
+              rules: [{
+                required: true,
+                message: "请输入是否在线(0:不在线,1:在线)",
+                trigger: "blur"
+              }]
+            },
+            {
+              // label: "是否支持云存储(0:不支持,1:支持)",
+              label: "是否支持云存储",
+              prop: "isSupportCloudStorage",
+              span: 12,
+              hide: true,
+              rules: [{
+                required: true,
+                message: "请输入是否支持云存储(0:不支持,1:支持)",
+                trigger: "blur"
+              }]
+            },
+            {
+              // label: "是否支持本地存储(0:不支持,1:支持)",
+              label: "是否支持本地存储",
+              prop: "isSupportLocalStorage",
+              span: 12,
+              hide: true,
+              rules: [{
+                required: true,
+                message: "请输入是否支持本地存储(0:不支持,1:支持)",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "是否支持云台",
+              prop: "isSupportPtz",
+              span: 12,
+              dataType: "number",
+              type: "select",
+              dicUrl: "/api/blade-system/dict-biz/dictionary?code=is_support",
+              props: {
+                label: 'dictValue',
+                value: 'dictKey'
+              },
+              rules: [{
+                required: true,
+                message: "请输入是否支持云台(0:不支持,1:支持)",
+                trigger: "blur"
+              }]
+            },
+            {
+              // label: "是否支持移动侦测(0:不支持,1:支持)",
+              label: "是否支持移动侦测",
+              prop: "isSupportMotionDetection",
+              span: 12,
+              hide: true,
+              rules: [{
+                required: true,
+                message: "请输入是否支持移动侦测(0:不支持,1:支持)",
+                trigger: "blur"
+              }]
+            },
+            {
+              // label: "是否支持手动报警(0:不支持,1:支持)",
+              label: "是否支持手动报警",
+              prop: "isSupportManualAlarm",
+              span: 12,
+              hide: true,
+              rules: [{
+                required: true,
+                message: "请输入是否支持手动报警(0:不支持,1:支持)",
+                trigger: "blur"
+              }]
+            },
+            {
+              // label: "是否支持外部开关报警(0:不支持,1:支持)",
+              label: "是否支持外部开关报警",
+              prop: "isSupportExternalAlarmSwitch",
+              span: 12,
+              hide: true,
+              rules: [{
+                required: true,
+                message: "请输入是否支持外部开关报警(0:不支持,1:支持)",
+                trigger: "blur"
+              }]
+            },
+            {
+              // label: "设备是否有反转倒置能力(0:否,1:是)",
+              label: "设备是否有反转倒置能力",
+              prop: "isHaveInversion",
+              span: 12,
+              hide: true,
+              rules: [{
+                required: true,
+                message: "请输入设备是否有反转倒置能力(0:否,1:是)",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "云存储类别",
+              prop: "cloudStorageType",
+              span: 12,
+              type: "select",
+              dataType: "number",
+              dicUrl: "/api/blade-system/dict-biz/dictionary?code=cloud_storage_type",
+              props: {
+                label: 'dictValue',
+                value: 'dictKey'
+              },
+              rules: [{
+                required: true,
+                message: "请输入云存储类别(0:无云存储,1:电信分布式存储,2:21cn存储)",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "云存储配置id",
+              prop: "cloudStorageConfId",
+              span: 12,
+              hide: true,
+              rules: [{
+                required: true,
+                message: "请输入云存储配置id",
+                trigger: "blur"
+              }]
+            },
+            {
+              // label: "视频流获取方式(0:主动推流,1:主动拉取流)",
+              label: "视频流获取方式",
+              prop: "streamType",
+              span: 12,
+              hide: true,
+              rules: [{
+                required: true,
+                message: "请输入视频流获取方式(0:主动推流,1:主动拉取流)",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "设备地址",
+              prop: "address",
+              span: 12,
+              hide: true,
+              rules: [{
+                required: true,
+                message: "请输入设备地址",
+                trigger: "blur"
+              }]
+            },
+            {
+              // label: "是否拥有者(0:否,1:是)",
+              label: "是否拥有者",
+              prop: "isOwner",
+              span: 12,
+              hide: true,
+              rules: [{
+                required: true,
+                message: "请输入是否拥有者(0:否,1:是)",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "所属NVR的编号",
+              prop: "parentNvrNum",
+              span: 12,
+              hide: true,
+              rules: [{
+                required: true,
+                message: "请输入所属NVR的编号",
+                trigger: "blur"
+              }]
+            },
+            {
+              // label: "告警状态(0:正常;1:告警)",
+              label: "告警状态",
+              prop: "alarmStatus",
+              span: 12,
+              hide: true,
+              rules: [{
+                required: true,
+                message: "请输入告警状态(0:正常;1:告警)",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "经度",
+              prop: "longitude",
+              span: 12,
+              rules: [{
+                required: true,
+                message: "请输入经度",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "纬度",
+              prop: "latitude",
+              span: 12,
+              rules: [{
+                required: true,
+                message: "请输入纬度",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "维护人员信息",
+              prop: "maintainer",
+              span: 12,
+              hide: true,
+              rules: [{
+                required: true,
+                message: "请输入维护人员信息",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "是否封存,true封存",
+              prop: "block",
+              span: 12,
+              hide: true,
+              rules: [{
+                required: true,
+                message: "请输入是否封存,true封存",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "封存时间",
+              prop: "blockTime",
+              span: 12,
+              hide: true,
+              rules: [{
+                required: true,
+                message: "请输入封存时间",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "路由器id",
+              prop: "routeId",
+              span: 12,
+              hide: true,
+              rules: [{
+                required: true,
+                message: "请输入路由器id",
+                trigger: "blur"
+              }]
+            },
+            {
+              // label: "摄像头类型 G:枪机 D:球机",
+              label: "摄像头类型",
+              prop: "equipType",
+              span: 12,
+              hide: true,
+              rules: [{
+                required: true,
+                message: "请输入摄像头类型 G:枪机 D:球机",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "设备最后状态更新时间",
+              prop: "updateStateTimeString",
+              span: 12,
+              hide: true,
+              rules: [{
+                required: true,
+                message: "请输入设备最后状态更新时间",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "设备监控位id",
+              prop: "districtId",
+              span: 12,
+              hide: true,
+              rules: [{
+                required: true,
+                message: "请输入设备监控位id",
+                trigger: "blur"
+              }]
+            },
+            {
+              // label: "存储位置(通过该字段快速查询,所有的子节点)机构树位置",
+              label: "存储位置",
+              prop: "orgPosition",
+              span: 12,
+              hide: true,
+              rules: [{
+                required: true,
+                message: "请输入存储位置(通过该字段快速查询,所有的子节点)机构树位置",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "rtsp视频播放地址",
+              prop: "rtspUrl",
+              span: 12,
+              hide: true,
+              rules: [{
+                required: true,
+                message: "请输入rtsp视频播放地址",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "http-flv视频播放地址",
+              prop: "httpFlvUrl",
+              span: 12,
+              hide: true,
+              rules: [{
+                required: true,
+                message: "请输入http-flv视频播放地址",
+                trigger: "blur"
+              }]
+            },
+            {
+              label: "所属账户",
+              prop: "accountName",
+              span: 12,
+              hide: true,
+              rules: [{
+                required: true,
+                message: "请输入所属账户",
+                trigger: "blur"
+              }]
+            },
+          ]
+        },
+        bindOption: {
+          column: [{
+            label: "所属小区",
+            prop: "residentialId",
+            search: true,
+            span:24,
+            cascaderItem: ['buildingId'],
+            type: "select",
+            remote: true,
+
+            dicUrl: "/api/community/residential/select?name={{key}}",
+            props: {
+              label: "name",
+              value: "id"
+            },
+            rules: [{
+              required: true,
+              message: "请选择所属小区",
+              trigger: "blur"
+            }]
+          },
+            {
+              label: "所属楼栋",
+              prop: "buildingId",
+              search: true,
+              type: "select",
+              span:24,
+              cascaderIndex: 0,
+              dicFlag: true,
+              dicUrl: "/api/building/building/select?residentialId={{key}}",
+              filterable: true,
+              dicFlag: false,
+              props: {
+                label: "name",
+                value: "id"
+              },
+
+            }]
+
+        },
+        data: []
+      };
+    },
+    computed: {
+      ...mapGetters(["permission"]),
+      permissionList() {
+        return {
+          addBtn: this.vaildData(this.permission.videoclouddevice_add, false),
+          viewBtn: this.vaildData(this.permission.videoclouddevice_view, false),
+          delBtn: this.vaildData(this.permission.videoclouddevice_delete, false),
+          editBtn: this.vaildData(this.permission.videoclouddevice_edit, false)
+        };
+      },
+      ids() {
+        let ids = [];
+        this.selectionList.forEach(ele => {
+          ids.push(ele.id);
+        });
+        return ids.join(",");
+      }
+    },
+    methods: {
+      showVideo(row) {
+        // this.video.url = "http://139.9.103.171/live?port=1935&app=myapp&stream=" + row.id;
+        this.video.url = "ws://36.103.228.148:8888/live/" + row.id + ".flv";
+        this.video.name = row.deviceName;
+        this.videoVisible = true;
+        this.$nextTick(() => {
+          try {
+            let videoElement = document.getElementById('videoId');
+            let flvPlayer = flvjs.createPlayer({
+              type: 'flv',
+              url: this.video.url
+            });
+            flvPlayer.on(flvjs.Events.ERROR, (errType, errDetail) => {
+              // errType是 NetworkError时,对应errDetail有:Exception、HttpStatusCodeInvalid、ConnectingTimeout、EarlyEof、UnrecoverableEarlyEof
+              // errType是 MediaError时,对应errDetail是MediaMSEError
+            });
+            flvPlayer.on(flvjs.Events.MEDIA_SOURCE_CLOSE || flvjs.Events.MEDIA_SOURCE_ENDED, () => {})
+            flvPlayer.attachMediaElement(videoElement);
+            flvPlayer.load();
+            flvPlayer.play();
+          } catch (e) {
+            console.log(e);
+          }
+        })
+      },
+      showDeviceBindBatch() {
+        if (this.selectionList.length === 0) {
+          this.$message.warning("请选择至少一条数据");
+          return;
+        }
+        if (this.residentialList.length == 0) {
+          //  请求获取小区列表
+          getAllList().then(res => {
+            this.residentialList = res.data.data;
+            this.selectValue = "";
+            this.bindBatchVisible = true;
+          })
+        } else {
+          this.selectValue = ""
+          this.bindBatchVisible = true;
+        }
+        // this.form = row;
+      },
+      showDeviceBind(row) {
+
+        if (this.residentialList.length == 0) {
+          //  请求获取小区列表
+          getAllList().then(res => {
+            this.residentialList = res.data.data;
+            this.selectValue = ""
+            this.bindVisible = true;
+          })
+        } else {
+          this.selectValue = ""
+          this.bindVisible = true;
+        }
+        this.bindForm = row;
+      },
+      bindBatchDevice(loading,done) {
+        // if (this.selectValue == "") {
+        //   this.$message.warning("请选择所属小区");
+        //   return;
+        // }
+        //保存
+        debugger
+        bindResidentialBatch(this.ids, this.bindBatchForm.residentialId,this.bindBatchForm.buildingId).then(() => {
+          // debugger
+          this.bindBatchVisible = false;
+          this.bindBatchForm = {};
+          this.onLoad(this.page);
+
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          done();
+        }, error => {
+          loading();
+          console.log(error);
+        });
+      },
+      bindDevice(loading,done) {
+        // this.form.residentialId = this.selectValue;
+        //保存
+        updateVideoDevice(this.bindForm).then(() => {
+          this.onLoad(this.page);
+          this.bindVisible = false;
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          done();
+        }, error => {
+          loading();
+          console.log(error);
+        });
+      },
+      rowSave(row, done, loading) {
+        add(row).then(() => {
+          this.onLoad(this.page);
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          done();
+        }, error => {
+          loading();
+          window.console.log(error);
+        });
+      },
+      rowUpdate(row, index, done, loading) {
+        update(row).then(() => {
+          this.onLoad(this.page);
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          done();
+        }, error => {
+          loading();
+          console.log(error);
+        });
+      },
+      rowDel(row) {
+        this.$confirm("确定将选择数据删除?", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        })
+          .then(() => {
+            return remove(row.id);
+          })
+          .then(() => {
+            this.onLoad(this.page);
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+          });
+      },
+      handleDelete() {
+        if (this.selectionList.length === 0) {
+          this.$message.warning("请选择至少一条数据");
+          return;
+        }
+        this.$confirm("确定将选择数据删除?", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        })
+          .then(() => {
+            return remove(this.ids);
+          })
+          .then(() => {
+            this.onLoad(this.page);
+            this.$message({
+              type: "success",
+              message: "操作成功!"
+            });
+            this.$refs.crud.toggleSelection();
+          });
+      },
+      beforeOpen(done, type) {
+        if (["edit", "view"].includes(type)) {
+          getDetail(this.form.id).then(res => {
+            this.form = res.data.data;
+          });
+        }
+        done();
+      },
+      searchReset() {
+        this.query = {};
+        this.onLoad(this.page);
+      },
+      searchChange(params, done) {
+        this.query = params;
+        this.page.currentPage = 1;
+        this.onLoad(this.page, params);
+        done();
+      },
+      selectionChange(list) {
+        this.selectionList = list;
+      },
+      selectionClear() {
+        this.selectionList = [];
+        this.$refs.crud.toggleSelection();
+      },
+      currentChange(currentPage) {
+        this.page.currentPage = currentPage;
+      },
+      sizeChange(pageSize) {
+        this.page.pageSize = pageSize;
+      },
+      refreshChange() {
+        this.onLoad(this.page, this.query);
+      },
+      edit(row) {
+        this.editForm = row;
+        this.editVisiable = true;
+      },
+      view(row) {
+        this.detailForm = row;
+        this.detailVisible = true;
+      },
+      submitVideoclouddevice(row,done,loading) {
+        update(row).then(() => {
+          this.onLoad(this.page);
+          this.$message({
+            type: "success",
+            message: "操作成功!"
+          });
+          done();
+        }, error => {
+          loading();
+          console.log(error);
+        });
+      },
+      onLoad(page, params = {}) {
+        this.loading = true;
+        getList(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
+          const data = res.data.data;
+          this.page.total = data.total;
+          this.data = data.records;
+          this.loading = false;
+          this.selectionClear();
+        });
+      }
+    }
+  };
+</script>
+
+<style>
+  .el-dropdown-link {
+    cursor: pointer;
+    color: #409eff;
+    font-size: small;
+    margin-left: 10px;
+  }
+</style>

+ 1 - 1
src/views/smartapplication/buildingvideo.vue

@@ -32,7 +32,7 @@
 </template>
 
 <script>
-  import {getList, getDetail, add, update, remove,pageByBuilding} from "../../api/smartapplication/videoclouddevice.js";
+  import {getList, getDetail, add, update, remove,pageByBuilding} from "../../api/device/iotdevice.js";
   import {mapGetters} from "vuex";
 
   export default {

+ 1 - 1
src/views/smartapplication/devicebuilding.vue

@@ -144,7 +144,7 @@
     update,
     remove,
     getSmartDeviceStaticVo
-  } from "@/api/smartapplication/smartdevice";
+  } from "@/api/device/iotdevice";
   import {
     mapGetters
   } from "vuex";

Certains fichiers n'ont pas été affichés car il y a eu trop de fichiers modifiés dans ce diff