Bläddra i källkod

实现物联功能

jiawuxian 1 år sedan
förälder
incheckning
62146c9daa

+ 32 - 0
src/api/iot/alarmCenter.js

@@ -0,0 +1,32 @@
+import request from '@/utils/request'
+
+// 查询【请填写功能名称】列表
+export function list(query) {
+  return request({
+    url: '/iot/iot_alarm_data/app/list',
+    method: 'post',
+    data: query
+  })
+}
+
+// 查询详情
+export function detail(id) {
+  return request({
+    url: `/iot/iot_alarm_data/app/detail/${id}`,
+    method: "get",
+  });
+}
+
+/**
+ * 获取角标
+ * @param {} orgId 
+ * @returns 
+ */
+export function getBadge(orgId){
+  return request({
+    url: `/iot/iot_alarm_data/app/badge/${orgId}`,
+    method: 'get',
+    hideLoading:true
+  });
+}
+

+ 0 - 8
src/api/iot/donghuan.js

@@ -39,11 +39,3 @@ export function getDonghuanBadge(orgId){
     hideLoading:true
   });
 }
-// // 获取某天的录像完整性
-// export function integrity(hostCode, channelCode,date) {
-//   return request({
-//     url: `/iot/VideoDiagnosis/web/integrity/${hostCode}/${channelCode}/${date}`,
-//     method: "get",
-//   });
-// }
-

+ 24 - 0
src/router/router.config.js

@@ -184,6 +184,30 @@ export let routers = [
         meta: { title: '动环设备详情', keepAlive: false,  deep: 2 }
       },
       {
+        path: '/iot/alarmCenter',
+        name: 'iot_alarmCenter',
+        component: () => import('@/views/menu/iot/alarmCenter/index'),
+        meta: { title: '告警中心', keepAlive: true , deep: 1}
+      },
+      {
+        path: '/iot/alarmCenter/detail',
+        name: 'iot_alarmCenter_detail',
+        component: () => import('@/views/menu/iot/alarmCenter/detail'),
+        meta: { title: '告警详情', keepAlive: false,  deep: 2 }
+      },
+      {
+        path: '/iot/ups',
+        name: 'iot_ups',
+        component: () => import('@/views/menu/iot/ups/index'),
+        meta: { title: 'UPS诊断', keepAlive: true , deep: 1}
+      },
+      {
+        path: '/iot/ups/detail',
+        name: 'iot_ups_detail',
+        component: () => import('@/views/menu/iot/ups/detail'),
+        meta: { title: 'UPS诊断详情', keepAlive: false,  deep: 2 }
+      },
+      {
         path: '/iot/board',
         name: 'iot_board',
         component: () => import('@/views/menu/iot/board'),

+ 20 - 0
src/utils/date.js

@@ -67,3 +67,23 @@ export function timeCheck(arr) {
 function timeToNumber(src) {
   return src.replace(':', '') * 1
 }
+
+export function durationText (minutes){
+  let day = Math.floor(minutes / 60 / 24)
+  minutes = minutes % (60 * 24)
+  let hour = Math.floor(minutes / 60)
+  minutes = minutes % 60
+  let text = ''
+  if (day) {
+    text += day + '天'
+  }
+  if (hour) {
+    text += hour + '小时'
+  }
+
+  if (minutes) {
+    text += minutes + '分钟'
+  }
+
+  return text
+}

+ 4 - 1
src/views/home/menu.vue

@@ -41,6 +41,8 @@ import { getMenu, getTheAreaWeather } from '@/api/public'
 import { getDonghuanBadge } from '@/api/iot/donghuan.js'
 import { getDvrRecorderBadge } from '@/api/iot/dvrRecorder.js'
 import { getVideoDiagnosisBadge } from '@/api/iot/videoDiagnosis.js'
+import { getBadge as getAlarmCenterBadge } from '@/api/iot/alarmCenter.js'
+
 export default {
   name: 'menus',
   components: { TopBar, Scroll, Card },
@@ -65,7 +67,8 @@ export default {
         this.$refs.Scroll.refresh()
         this.getBadge('/iot/donghuan', getDonghuanBadge)
         this.getBadge('/iot/dvrDisk', getDvrRecorderBadge)
-        this.getBadge('/iot/videoDiagnosis', getVideoDiagnosisBadge)
+        this.getBadge('/iot/videoDiagnosis', getVideoDiagnosisBadge)        
+        this.getBadge('/iot/alarmCenter', getAlarmCenterBadge)
       })
     },
     getBadge(url, method) {

+ 94 - 0
src/views/menu/iot/alarmCenter/components/item.vue

@@ -0,0 +1,94 @@
+<template>
+  <div class="flex flex-col justify-center k-app-list__item van-clearfix">
+    <van-cell-group clickable @click="itemClick">
+      <van-cell :title="data.orgName" value-class="cell-org-value">
+        <template #right-icon>
+          <van-tag v-if="data.endTime">告警结束</van-tag>
+          <van-tag v-else type="danger">正在告警</van-tag>
+        </template>
+      </van-cell>
+      <van-cell title="设备名称" :value="data.deviceName" title-style="max-width:40%;min-width:100px"> </van-cell>
+      <van-cell title="报警类型" :value="data.sourceTypeDes"> </van-cell>
+      <van-cell title="告警开始时间" :value="renderTime(data.startTime)"></van-cell>
+      <van-cell title="告警结束时间" :value="renderTime(data.endTime)" v-if="data.endTime"></van-cell>
+    </van-cell-group>
+  </div>
+</template>
+<script>
+import dayjs from 'dayjs'
+export default {
+  components: {},
+  data() {
+    return {}
+  },
+  computed: {
+   
+  },
+  watch: {},
+  props: {
+    data: {},
+    statusOptions: {}
+  },
+  methods: {
+    itemClick() {
+      this.$router.push('/iot/alarmCenter/detail?id=' + this.data.id)
+    },
+    renderTime(dateTime) {
+      if (!dateTime) {
+        return ''
+      }
+
+      return dayjs(dateTime).format('YYYY年M月D日H时m分')
+    }
+  },
+  async created() {},
+  async mounted() {}
+}
+</script>
+<style lang="scss" scoped>
+.cell-org-value {
+  display: none;
+}
+.k-app-list__item {
+  //   height: 11.85rem;
+  background: #ffffff;
+  margin: 0.3rem 0.325rem 0;
+  font-size: 3.733333vw;
+  .top {
+    // min-height: 3rem;
+    padding: 0.05rem 0.05rem;
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+    border-bottom: 1px solid #f3f4f5;
+    > label {
+      //   height: 1.38rem;
+      // font-size: 1rem;
+      //   line-height: 1.25rem;
+      color: #323233;
+      opacity: 1;
+    }
+  }
+  .bottom {
+    min-height: 7.75rem;
+    padding: 0 1rem;
+    span {
+      height: 1.25rem;
+      font-size: 0.88rem;
+      line-height: 1.25rem;
+      color: #000000;
+      opacity: 0.61;
+    }
+  }
+}
+.wrapper {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  height: 100%;
+}
+
+.time-cell-default {
+  min-width: 60vw;
+}
+</style>

+ 106 - 0
src/views/menu/iot/alarmCenter/detail.vue

@@ -0,0 +1,106 @@
+<template>
+  <div class="detail">
+    <nav-bar></nav-bar>
+    <van-cell-group>
+      <van-cell :title="info.deviceName" value-class="cell-title-value" title-style="width:100%;">
+        <template #right-icon v-if="info.time">
+          <van-tag v-if="info.endTime">告警结束</van-tag>
+          <van-tag v-else type="danger">正在告警</van-tag>
+        </template>
+      </van-cell>
+      <van-cell title="所属机构" :value="info.orgName" />
+      <van-cell title="告警分类" :value="dataTypeText"></van-cell>
+      <van-cell title="告警类型" :value="info.sourceTypeDes"></van-cell>
+      <van-cell title="告警开始时间" :value="renderTime(info.time)"></van-cell>
+      <van-cell title="告警结束时间" :value="renderTime(info.endTime)"></van-cell>
+      <van-cell title="持续时长" :value="durationText" />
+      <van-cell title="告警值" :value="valueText" />
+      <van-cell title="告警内容" :value="info.content" />
+    </van-cell-group>
+  </div>
+</template>
+<script>
+import { detail } from '@/api/iot/alarmCenter.js'
+import NavBar from '@/components/NavBar'
+import dayjs from 'dayjs'
+import { durationText } from '@/utils/date.js'
+export default {
+  data() {
+    return {
+      info: {},
+      search: {
+        sensorId: this.$route.query.id
+      }
+    }
+  },
+  components: { NavBar },
+  computed: {
+    stateUpdateTimeText() {
+      if (this.info.stateUpdateTime == null) {
+        return '未上报'
+      }
+
+      return dayjs(this.info.stateUpdateTime).format('YYYY年M月D日H时m分')
+    },
+    dataTypeText() {
+      if (!this.info || this.info.dataType == null) {
+        return ''
+      }
+
+      if (this.info.dataType == '0') {
+        return '动环类告警'
+      } else if (this.info.dataType == '1') {
+        return '视频类告警'
+      } else {
+        return '未知'
+      }
+    },
+    durationText() {
+      let endTime = this.info.endTime ? this.info.endTime : new Date()
+
+      let minutes = dayjs(endTime).diff(this.info.time, 'minute')
+      if (minutes < 1) {
+        return dayjs(endTime).diff(this.info.time, 'second') + '秒'
+      } else {
+        return durationText(minutes)
+      }
+    },
+    
+    valueText() {
+      if (!this.info || this.info.valueText == null) {
+        return ''
+      }
+
+      return `${this.info.valueText}${this.info.alarmValue ? this.info.alarmValue : ''}`
+    }
+  },
+  mounted() {
+    this.getInfo()
+  },
+  methods: {
+    getInfo() {
+      detail(this.search.sensorId).then(r => {
+        this.info = r.data
+      })
+    },
+    renderTime(dateTime) {
+      if (!dateTime) {
+        return ''
+      }
+
+      return dayjs(dateTime).format('YYYY年M月D日H时m分')
+    },
+  }
+}
+</script>
+<style lang="scss" scoped>
+.cell-title-value {
+  display: none;
+}
+.detail {
+  margin: 15px;
+}
+.cell-gather-alarm-value {
+  color: #ee0a24;
+}
+</style>

+ 235 - 0
src/views/menu/iot/alarmCenter/index.vue

@@ -0,0 +1,235 @@
+<template>
+  <div class="page_list">
+    <nav-bar></nav-bar>
+    <van-row>
+      <van-col span="24">
+        <org-tree
+          v-model="search.orgId"
+          @changeItem="changeTree"
+          @checked="orgCheckChanged"
+          showChecked
+          defaultChecked
+        ></org-tree>
+      </van-col>
+    </van-row>
+    <van-row>
+      <van-col span="24">
+        <van-search v-model="search.deviceName" @clear="search.deviceName=null" maxlength="50" placeholder="请输入搜索关键词" />        
+      </van-col>
+    </van-row>
+    <van-row>
+      <van-col span="13">
+        <van-cell
+          title="报警类型"
+          @click="showAlarmType = true"
+          is-link
+          arrow-direction="down"
+          :value="defaultAlarmType"
+          value-class="cell-alarmtype-value"
+        />
+        <van-popup v-model="showAlarmType" round position="bottom">
+          <van-picker
+            title="报警类型"
+            show-toolbar
+            :columns="alarmTypes"
+            @confirm="onAlarmTypeConfirm"
+            @cancel="onCancel"
+            default-index="0"
+            :close-on-click-overlay="false"
+          />
+        </van-popup>
+      </van-col>
+      <van-col span="11">
+        <van-cell title="报警状态" @click="showState = true" is-link arrow-direction="down" :value="defaultState" value-class="cell-state-value"/>
+        <van-popup v-model="showState" round position="bottom">
+          <van-picker
+            title="报警状态"
+            show-toolbar
+            :columns="statusOptions"
+            @confirm="onStateConfirm"
+            @cancel="onCancel"
+            default-index="0"
+            :close-on-click-overlay="false"
+          />
+        </van-popup>
+      </van-col>
+    </van-row>
+    <div class="container">
+      <k-list :list="list" :params="search" :auto="false" ref="list">
+        <template slot-scope="{ data }">
+          <item :data="data" :statusOptions="alarmTypes"></item>
+        </template>
+      </k-list>
+    </div>
+  </div>
+</template>
+
+<script>
+import NavBar from '@/components/NavBar'
+import { mapGetters } from 'vuex'
+import { list } from '@/api/iot/alarmCenter.js'
+import KList from '@/components/list/index.vue'
+import Item from './components/item.vue'
+import OrgTree from '@/components/orgTree'
+export default {
+  components: { NavBar, KList, Item, OrgTree },
+  name: 'iot_alarmCenter',
+  data() {
+    return {
+      search: {        
+        orgId: this.orgId,
+        checkSub: true,
+        alarmType: null,
+        deviceName:null,
+        state: null,
+        pageNum: 1,
+        pageSize: 10
+      },
+      showAlarmType: false,
+      defaultAlarmType: '全部',
+      showState: false,
+      defaultState: '全部',
+      dicts: [],
+      alarmTypes: [
+        {
+          value: null,
+          text: '全部'
+        },
+        {
+          value: '4184',
+          text: '水浸告警'
+        },
+        {
+          value: '4183',
+          text: '温湿度告警'
+        },
+        {
+          value: '4182',
+          text: '烟感告警'
+        },
+        {
+          value: '4181',
+          text: '红外告警'
+        },
+        {
+          value: '41885',
+          text: '燃气告警'
+        },
+        {
+          value: '4188',
+          text: '门磁告警'
+        },
+        {
+          value: '1001',
+          text: '信号丢失'
+        },
+        {
+          value: '1002',
+          text: '遮挡告警'
+        },
+        {
+          value: '1003',
+          text: '亮度告警'
+        },
+        {
+          value: '1004',
+          text: '偏色告警'
+        },
+        {
+          value: '1005',
+          text: '雪花告警'
+        },
+        {
+          value: '1006',
+          text: '条纹告警'
+        },
+        {
+          value: '1007',
+          text: '对比度告警'
+        },
+        {
+          value: '1008',
+          text: '模糊告警'
+        },
+        {
+          value: '1009',
+          text: '硬盘告警'
+        }
+      ],
+      statusOptions: [
+        {
+          value: null,
+          text: '全部'
+        },
+        {
+          value: 0,
+          text: '告警结束'
+        },
+        {
+          value: 1,
+          text: '正在告警'
+        }
+      ]
+    }
+  },
+  watch: {},
+  created() {},
+  mounted() {
+    this.search.orgId = this.orgId
+  },
+  computed: {
+    ...mapGetters(['orgName', 'orgId', 'dictionary'])
+  },
+  methods: {
+    list,
+    onAlarmTypeConfirm(opt) {
+      this.defaultAlarmType = opt.text
+      this.search.alarmType = opt.value
+      this.showAlarmType = false
+    },
+    onStateConfirm(opt) {
+      this.defaultState = opt.text
+      this.search.state = opt.value
+      this.showState = false;
+    },
+    onCancel() {
+      this.showAlarmType = false
+      this.showState = false
+    },
+    //改变机构后将重新发起请求
+    changeTree(node) {
+      // console.log(selectedOptions,'aaaaaa')
+      // this.search.orgId = selectedOptions[selectedOptions.length-1].id;
+      // let option = selectedOptions[selectedOptions.length - 1]
+      this.search.orgId = node.id
+    },
+    orgCheckChanged(v) {
+      this.search.checkSub = v
+    },
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.page_list {
+  background-color: transparent;
+  display: block;
+
+  .container {
+    // overflow: auto;
+    // height: calc(100vh - 11rem);
+    .k-content-repair {
+      display: flex;
+      flex-direction: column;
+      justify-content: space-between;
+      flex: 1;
+    }
+  }
+}
+.cell-alarmtype-value{
+  min-width: 120px;
+}
+.cell-state-value{
+  min-width: 90px;
+}
+</style>

+ 2 - 18
src/views/menu/iot/donghuan/detail.vue

@@ -19,6 +19,7 @@
 import { detail } from '@/api/iot/donghuan.js'
 import NavBar from '@/components/NavBar'
 import dayjs from 'dayjs'
+import {durationText} from "@/utils/date.js"
 export default {
   data() {
     return {
@@ -88,25 +89,8 @@ export default {
         return '未上报'
       }
 
-
       let minutes =dayjs().diff(this.info.stateStartTime,'minute') 
-      let day=Math.floor(minutes / 60/24)
-      minutes=minutes%(60*24);
-      let hour = Math.floor(minutes / 60)
-      minutes = minutes % 60
-      let text = ''
-      if (day) {
-        text += day + '天'
-      }
-      if (hour) {
-        text += hour + '小时'
-      }
-
-      if (minutes) {
-        text += minutes + '分钟'
-      }
-
-      return text
+      return durationText(minutes);
     }
   },
   mounted() {

+ 8 - 42
src/views/menu/iot/donghuan/index.vue

@@ -3,7 +3,7 @@
     <nav-bar></nav-bar>
     <van-row>
       <van-col span="24">
-        <org-tree v-model="search.orgId" @changeItem="changeTree" @checked="orgCheckChanged" showChecked></org-tree>
+        <org-tree v-model="search.orgId" @changeItem="changeTree" @checked="orgCheckChanged" showChecked defaultChecked></org-tree>
       </van-col>
       <!-- 
       <van-col span="24">
@@ -91,7 +91,7 @@ export default {
       // normalButtonText: '正常设备',
       search: {
         orgId: this.orgId,
-        checkSub: false,
+        checkSub: true,
         deviceType: null,
         state: null,
         pageNum: 1,
@@ -108,9 +108,7 @@ export default {
   watch: {},
   created() {},
   mounted() {
-    this.getTreeList()
     this.search.orgId = this.orgId
-    this.selectedOrgName = this.orgName
     this.statisticState()
   },
   computed: {
@@ -149,66 +147,34 @@ export default {
   },
   methods: {
     list,
-    //获取机构树
-    getTreeList() {
-      deptTreeList(this.orgId).then(res => {
-        this.options = res.data
-        // this.orgInfo.orgId = this.orgId;
-        // this.orgInfo.orgName = this.orgName;
-        // console.log(res,'3333')
-      })
-    },
     statisticState() {
       stateStatistic(this.search).then(r => {
         this.statusStatistic = r.data
       })
     },
     onDeviceTypeConfirm(opt) {
-      this.defaultDeviceType = opt.text
-      this.search.deviceType = opt.value
-      this.showDeviceType = false
+      this.defaultAlarmType = opt.text
+      this.search.alarmType = opt.value
+      this.showAlarmType = false
     },
     onStatusConfirm(opt) {
-      this.defaultStatus = opt.text
+      this.defaultState = opt.text
       this.search.state = opt.value
       this.showStatus = false
     },
     onCancel() {
-      this.showDeviceType = false
-      this.defaultStatus = false
+      this.showAlarmType = false
+      this.showStatus = false
     },
-    // onStateChanged(state) {
-    //   if (this.search.state === state) {
-    //     this.search.state = null
-    //   } else {
-    //     this.search.state = state
-    //   }
-    // },
-    // onDeviceTypeClick(deviceType) {
-    //   if (this.search.deviceType === deviceType) {
-    //     this.search.deviceType = null
-    //   } else {
-    //     this.search.deviceType = deviceType
-    //   }
-    // },
     //改变机构后将重新发起请求
     changeTree(node) {
-      // console.log(selectedOptions,'aaaaaa')
-      // this.search.orgId = selectedOptions[selectedOptions.length-1].id;
-      // let option = selectedOptions[selectedOptions.length - 1]
       this.search.orgId = node.id
-      this.selectedOrgName = node.shortName
-
-      this.statisticState()
     },
 
     orgCheckChanged(v) {
       this.search.checkSub = v
       this.statisticState()
     },
-    onFinish({ selectedOptions }) {
-      this.showOrg = false
-    }
   }
 }
 </script>

+ 97 - 0
src/views/menu/iot/ups/components/item.vue

@@ -0,0 +1,97 @@
+<template>
+  <div class="flex flex-col justify-center k-app-list__item van-clearfix">
+    <van-cell-group clickable @click="itemClick">
+      <van-cell :title="data.deviceName" value-class="cell-title-value" title-style="width:100% ;margin-left:10px;">
+        <template #icon>
+          <van-tag type="primary">{{ data.deviceType }}</van-tag>
+        </template>
+        <template #right-icon>
+          <van-tag type="danger" v-if="data.state === 1">{{ data.stateText }}</van-tag>
+          <van-tag color="gray" text-color="black" v-else-if="data.state == null">未上报</van-tag>
+          <van-tag type="primary" v-else>{{ data.stateText }}</van-tag>
+        </template>
+      </van-cell>
+      <van-cell title="所属机构" :value="data.orgName"></van-cell>
+      <van-cell title="诊断时间" v-if="data.state != null" :value="stateUpdateTimeText"></van-cell>
+    </van-cell-group>
+  </div>
+</template>
+<script>
+import { mapGetters } from 'vuex'
+import dayjs from 'dayjs'
+export default {
+  components: {},
+  data() {
+    return {}
+  },
+  computed: {
+    ...mapGetters(['orgName', 'orgId', 'dictionary']),
+    stateUpdateTimeText() {
+      if (this.data.stateUpdateTime == null) {
+        return '未上报'
+      }
+
+      return dayjs(this.data.stateUpdateTime).format('YYYY年M月D日H时m分');
+    },    
+  },
+  watch: {},
+  props: {
+    data: {},
+    statusOptions: {}
+  },
+  methods: {
+    itemClick() {
+      this.$router.push('/iot/ups/detail?id=' + this.data.id)
+    }
+  },
+  async created() {},
+  async mounted() {}
+}
+</script>
+<style lang="scss" scoped>
+.cell-title-value {
+  display: none;
+}
+.k-app-list__item {
+  //   height: 11.85rem;
+  background: #ffffff;
+  margin: 0.3rem 0.325rem 0;
+  font-size: 3.733333vw;
+  .top {
+    // min-height: 3rem;
+    padding: 0.05rem 0.05rem;
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+    border-bottom: 1px solid #f3f4f5;
+    > label {
+      //   height: 1.38rem;
+      // font-size: 1rem;
+      //   line-height: 1.25rem;
+      color: #323233;
+      opacity: 1;
+    }
+  }
+  .bottom {
+    min-height: 7.75rem;
+    padding: 0 1rem;
+    span {
+      height: 1.25rem;
+      font-size: 0.88rem;
+      line-height: 1.25rem;
+      color: #000000;
+      opacity: 0.61;
+    }
+  }
+}
+.wrapper {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  height: 100%;
+}
+
+.time-cell-default {
+  min-width: 60vw;
+}
+</style>

+ 129 - 0
src/views/menu/iot/ups/detail.vue

@@ -0,0 +1,129 @@
+<template>
+  <div class="detail">
+    <nav-bar></nav-bar>
+    <card title="ups信息">
+      <van-cell-group>
+        <van-cell :title="info.deviceName" value-class="cell-title-value" title-style="width:100%;">
+          <template #icon>
+            <van-tag type="danger" v-if="info.state === 1">{{ info.stateText }}</van-tag>
+            <van-tag color="gray" text-color="black" v-else-if="info.state == null">未上报</van-tag>
+            <van-tag type="primary" v-else>{{ info.stateText }}</van-tag>
+          </template>
+        </van-cell>
+        <van-cell title="UPS主机编号" :value="info.deviceCode" />
+        <van-cell title="诊断时间" :value="stateUpdateTimeText" title-style="max-width:30%;min-width:100px"/>
+        <van-cell title="所属机构" :value="info.orgName" />
+      </van-cell-group>
+    </card>
+    <card title="设备状态信息">
+      <van-cell-group>
+        <van-cell v-for="iv in info.infos" :key="iv.name" :title="iv.name" :value="iv.val" />
+      </van-cell-group>
+    </card>
+  </div>
+</template>
+<script>
+import NavBar from '@/components/NavBar'
+import dayjs from 'dayjs'
+import { durationText } from '@/utils/date.js'
+import Card from '@/components/card'
+export default {
+  data() {
+    return {
+      info: {},
+      search: {
+        sensorId: this.$route.query.id
+      }
+    }
+  },
+  components: { NavBar, Card },
+  computed: {
+    stateUpdateTimeText() {
+      if (this.info.stateUpdateTime == null) {
+        return '未上报'
+      }
+
+      return dayjs(this.info.stateUpdateTime).format('YYYY年M月D日H时m分')
+    }
+  },
+  mounted() {
+    this.getInfo()
+  },
+  methods: {
+    getInfo() {
+      this.info = {
+        deviceName: '监控主机Ups',
+        state: 0,
+        stateText: '正常',
+        deviceCode: '000342423',
+        stateUpdateTime: dayjs().add(-20 , 'second'),
+        orgName: '六一分理处',
+        infos: [
+          {
+            name: 'UPS市电状态',
+            val: '正常'
+          },
+          {
+            name: 'UPS电池电压低告警',
+            val: '正常'
+          },
+          {
+            name: 'UPS关机状态',
+            val: '正常'
+          },
+          {
+            name: 'UPS故障',
+            val: '正常'
+          },
+          {
+            name: 'UPS报警启动',
+            val: '正常'
+          },
+          {
+            name: 'UPS旁路状态',
+            val: '正常'
+          },
+          {
+            name: 'UPS通信中断告警',
+            val: '正常'
+          },
+          {
+            name: 'UPS输入相电压Ua',
+            val: '正常'
+          },
+          {
+            name: 'UPS输入相电压Ua',
+            val: '正常'
+          },
+          {
+            name: 'UPS输入相电压Ub',
+            val: '正常'
+          },
+          {
+            name: 'UPS温度',
+            val: '30°C'
+          }
+        ]
+      }
+      // detail(this.search.sensorId).then(r => {
+      //   this.info = r.data
+      // })
+    }
+  }
+}
+</script>
+<style lang="scss" scoped>
+.cell-title-value {
+  display: none;
+}
+.detail {
+  margin: 15px;
+
+  ::v-deep .title{
+    font-weight: 700;
+  }
+}
+.cell-gather-alarm-value {
+  color: #ee0a24;
+}
+</style>

+ 189 - 0
src/views/menu/iot/ups/index.vue

@@ -0,0 +1,189 @@
+<template>
+  <div class="page_list">
+    <nav-bar></nav-bar>
+    <van-row>
+      <van-col span="24">
+        <org-tree
+          v-model="search.orgId"
+          @changeItem="changeTree"
+          @checked="orgCheckChanged"
+          showChecked
+          defaultChecked
+        ></org-tree>
+      </van-col>
+    </van-row>
+    <van-row>
+      <van-col span="24">
+        <van-cell title="UPS状态" @click="showStatus = true" is-link arrow-direction="down" :value="defaultStatus" />
+        <van-popup v-model="showStatus" round position="bottom">
+          <van-picker
+            title="UPS状态"
+            show-toolbar
+            :columns="statusOptions"
+            @confirm="onStatusConfirm"
+            @cancel="onCancel"
+            default-index="0"
+            :close-on-click-overlay="false"
+          />
+        </van-popup>
+      </van-col>
+    </van-row>
+    <div class="container">
+      <k-list :list="list" :params="search" :auto="false" ref="list">
+        <template slot-scope="{ data }">
+          <item :data="data" :statusOptions="deviceTypeOptions"></item>
+        </template>
+      </k-list>
+    </div>
+  </div>
+</template>
+
+<script>
+import NavBar from '@/components/NavBar'
+// import Calendar from '@/components/Calendar';
+import { mapGetters } from 'vuex'
+import { deptTreeList } from '@/api/public'
+// import { list, stateStatistic } from '@/api/iot/donghuan.js'
+import KList from '@/components/list/index.vue'
+import Item from './components/item.vue'
+import OrgTree from '@/components/orgTree'
+export default {
+  components: { NavBar, KList, Item, OrgTree },
+  name: 'iot_ups',
+  data() {
+    return {
+      search: {
+        orgId: this.orgId,
+        checkSub: true,
+        deviceType: null,
+        state: null,
+        pageNum: 1,
+        pageSize: 10
+      },
+      statusStatistic: null,
+      showDeviceType: false,
+      defaultDeviceType: '全部',
+      showStatus: false,
+      defaultStatus: '全部',
+      dicts: ['sensor_alarm_status']
+    }
+  },
+  watch: {},
+  created() {},
+  mounted() {
+    this.search.orgId = this.orgId
+  },
+  computed: {
+    ...mapGetters(['orgName', 'orgId', 'dictionary']),
+    statusOptions() {
+      let r = [{ value: null, text: '全部' }]
+
+      let dict = this.getDictItem('sensor_alarm_status')
+      if (dict) {
+        dict.forEach(element => {
+          let label = element.dictLabel
+
+          if (element.dictValue == 0 && this.statusStatistic) {
+            label += `(${this.statusStatistic.normal})`
+          } else if (element.dictValue == 1 && this.statusStatistic) {
+            label += `(${this.statusStatistic.alarm})`
+          }
+          r.push({ value: element.dictValue, text: label })
+        })
+      }
+
+      return r
+    }
+  },
+  methods: {
+    list() {
+      return {
+        total: 3,
+        rows: [
+          {
+            orgName: '六一分理处',
+            deviceName: '监控主机Ups',
+            state: 0,
+            stateText: '正常'
+          },
+          {
+            orgName: '六一分理处',
+            deviceName: '现金区Ups',
+            state: 0,
+            stateText: '正常'
+          },
+          {
+            orgName: '六一分理处',
+            deviceName: '大厅Ups',
+            state: 0,
+            stateText: '正常'
+          }
+        ]
+      }
+    },
+    onStatusConfirm(opt) {
+      this.defaultState = opt.text
+      this.search.state = opt.value
+      this.showStatus = false
+    },
+    onCancel() {
+      this.showAlarmType = false
+      this.showStatus = false
+    },
+    //改变机构后将重新发起请求
+    changeTree(node) {
+      this.search.orgId = node.id
+    },
+
+    orgCheckChanged(v) {
+      this.search.checkSub = v
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.page_list {
+  background-color: transparent;
+  display: block;
+
+  .container {
+    // overflow: auto;
+    // height: calc(100vh - 11rem);
+    .k-content-repair {
+      display: flex;
+      flex-direction: column;
+      justify-content: space-between;
+      flex: 1;
+    }
+  }
+}
+
+.search-devicetype {
+  width: 25%;
+  display: inline-block;
+  text-align: center;
+  margin-top: 10px;
+}
+.search-state {
+  width: 100%;
+  margin-top: 10px;
+  padding-left: 10px;
+  padding-right: 10px;
+  > span {
+    width: 50%;
+    border: solid 1px rgb(196, 196, 196);
+    display: inline-block;
+    text-align: center;
+    padding-top: 1.2vw;
+    padding-bottom: 1.2vw;
+  }
+}
+
+.alarm_state_selected {
+  background-color: #409eff;
+  border-color: #409eff;
+  color: white;
+  font-weight: 700;
+}
+</style>