浏览代码

物联看板

jiawuxian 1 年之前
父节点
当前提交
893759abee

+ 20 - 8
src/api/iot/board.js

@@ -6,7 +6,7 @@ import request from "@/utils/request";
  */
 export function deviceCount(orgId) {
   return request({
-    url: "/iot/board/deviceCount/" + orgId,
+    url: "/iot/web/board/statistic/deviceCount/" + orgId,
     method: "get",
   });
 }
@@ -18,7 +18,7 @@ export function deviceCount(orgId) {
  */
 export function protectionInfo(orgId) {
   return request({
-    url: "/iot/board/protection/" + orgId,
+    url: "/iot/web/board/statistic/protection/" + orgId,
     method: "get",
   });
 }
@@ -30,7 +30,7 @@ export function protectionInfo(orgId) {
  */
 export function deviceOnline(orgId) {
   return request({
-    url: "/iot/board/deviceOnline/" + orgId,
+    url: "/iot/web/board/statistic/deviceOnline/" + orgId,
     method: "get",
   });
 }
@@ -42,7 +42,7 @@ export function deviceOnline(orgId) {
  */
 export function deviceHealth(orgId) {
   return request({
-    url: "/iot/board/deviceHealth/" + orgId,
+    url: "/iot/web/board/statistic/deviceHealth/" + orgId,
     method: "get",
   });
 }
@@ -52,9 +52,9 @@ export function deviceHealth(orgId) {
  * @param {*} orgId
  * @returns
  */
-export function alarmTrend(orgId) {
+export function alarmTrend(orgId,period) {
   return request({
-    url: "/iot/board/alarmTrend/" + orgId,
+    url: `/iot/web/board/statistic/alarmTrend/${orgId}/${period}`,
     method: "get",
   });
 }
@@ -66,7 +66,7 @@ export function alarmTrend(orgId) {
  */
 export function alarmRate(orgId) {
   return request({
-    url: "/iot/board/alarmRate/" + orgId,
+    url: "/iot/web/board/statistic/alarmRate/" + orgId,
     method: "get",
   });
 }
@@ -78,7 +78,19 @@ export function alarmRate(orgId) {
  */
 export function alarmList(orgId) {
   return request({
-    url: "/iot/board/alarmList/" + orgId,
+    url: "/iot/web/board/statistic/alarmList/" + orgId,
     method: "get",
   });
 }
+
+/**
+ * 下级的设备数量
+ * @param {*} orgId
+ * @returns
+ */
+ export function deviceCountOfChildren(orgId) {
+  return request({
+    url: "/iot/web/board/statistic/deviceCountOfChildren/" + orgId,
+    method: "get",
+  });
+}

+ 152 - 78
src/views/iot/board/components/alarmList.vue

@@ -1,105 +1,179 @@
 <template>
-    <div class="component_box" @mouseenter="handleMouseEnter" @mouseleave="handleMouseLeave">
-        <h1 class="t_title">实时告警列表</h1>
-        <el-table :data="data" width="100%">
-            <el-table-column label="所在机构" prop="orgName" align="center"></el-table-column>
-            <el-table-column label="告警设备" prop="deviceName" align="center"></el-table-column>
-            <el-table-column label="告警时间" prop="alarmTime" align="center"></el-table-column>
-            <el-table-column label="告警信息" prop="alarmInfo" align="center"></el-table-column>
-        </el-table>       
-    </div>
+  <div
+    class="component_box"
+    @mouseenter="handleMouseEnter"
+    @mouseleave="handleMouseLeave"
+  >
+    <h1 class="t_title">实时告警列表</h1>
+    <el-table :data="data" height="calc(95% - 50px)" class="alarm-table">
+      <el-table-column
+        label="所在机构"
+        prop="orgName"
+        align="center"
+      ></el-table-column>
+      <el-table-column
+        label="告警设备"
+        prop="deviceName"
+        align="center"
+      ></el-table-column>
+      <el-table-column label="告警时间" prop="alarmTime" align="center">
+        <template slot-scope="r">
+          {{ renderTime(r.row) }}
+        </template>
+      </el-table-column>
+      <el-table-column
+        label="告警信息"
+        prop="alarmInfo"
+        align="center"
+        width="100px"
+      ></el-table-column>
+    </el-table>
+  </div>
 </template>
 <script>
 import { alarmList } from "@/api/iot/board";
+import dayjs from 'dayjs';
 export default {
-    props: {
-        orgId: {
-            type: String,
-            isRequired: true,
-        },
-    },
-    data() {
-        return {
-            data: [],
-        };
+  props: {
+    orgId: {
+      type: String,
+      isRequired: true,
     },
+  },
+  data() {
+    return {
+      data: [],
+    };
+  },
 
-    components: {},
+  components: {},
 
-    computed: {},
+  computed: {},
 
-    watch: {
-        orgId: {
-            deep: true,
-            handler(val) {
-                this.resetTimer();
-                this.getData();
-            },
-        },
+  watch: {
+    orgId: {
+      deep: true,
+      handler(val) {
+        this.resetTimer();
+        this.getData();
+      },
+    },
+  },
+  created() {
+    this.refreshTime = 1 * 30 * 1000;
+    this.isMouseOver = false;
+  },
+  mounted() {},
+  methods: {
+    async getData() {
+      let r = (await alarmList(this.orgId)).data;
+      this.data = r;
     },
-    created() {
-        this.refreshTime = 1 * 10 * 1000;
-        this.isMouseOver = false;
+    handleMouseEnter() {
+      this.isMouseOver = true;
     },
-    mounted() {
+    handleMouseLeave() {
+      this.isMouseOver = false;
+    },
+    resetTimer() {
+      this.timer && clearInterval(this.timer);
+      this.timer = setInterval(() => {
+        if (this.isMouseOver) {
+          return;
+        }
 
+        this.getData();
+      }, this.refreshTime);
     },
-    methods: {
-        async getData() {
-            let r = (await alarmList(this.orgId))
-                .data;
-            this.data = r;
-        },
-        resetTimer() {
-            this.timer && clearInterval(this.timer);
-            this.timer = setInterval(() => {
-                if (this.isMouseOver) {
-                    return;
-                }
+    renderTime(row) {
+      let st = dayjs(row.alarmStartTime);
+      let str = st.format("M月DD日H时m分");
+      if (!row.alarmEndTime) {
+        str += "-至今";
+        return str;
+      }
 
-                this.getData();
-            }, this.refreshTime);
-        },
-    }
-}
+      let et = dayjs(row.alarmEndTime);
+      if (st.isSame(et,'day')) {
+        str += "-" + et.format("H时m分");
+      } else {
+        str += "-" + et.format("M月DD日H时m分");
+      }
+
+      return str;
+    },
+  },
+};
 </script>
 <style scoped src="./../css/index.css"></style>
 <style lang="scss" scoped>
-.t_table {
-    font-size: 14px;
-    color: #fff;
-    width: 94%;
-    margin: 0 auto;
-    border-spacing: 0;
-    text-align: center;
-    box-sizing: border-box;
-    margin-top: 10%;
+.alarm-table {
+  width: calc(100% - 20px);
 }
 
-.t_table tr {
-    margin: 0;
-    padding: 0;
-    height: 40px;
+.component_box ::v-deep .el-table {
+  box-shadow: none !important;
 }
 
-.t_table thead tr {
-    background: #053a98;
+.component_box ::v-deep .el-table__body tr:hover > td {
+  background-color: #053a9888 !important;
 }
-
-.t_table tbody tr td:first-child {
-    border-left: 1px solid #053a98;
+.component_box ::v-deep .el-table::before {
+  background-color: transparent !important;
 }
-
-.t_table td {
-    border-bottom: 1px solid #053a98;
-    border-right: 1px solid #053a98;
+.component_box ::v-deep .el-table__body-wrapper {
+  scrollbar-width: none;
 }
+.component_box ::v-deep .el-table,
+.component_box ::v-deep .el-table__expanded-cell,
+.component_box ::v-deep .el-table th,
+.component_box ::v-deep .el-table tr,
+.component_box ::v-deep .el-table tr {
+  background-color: transparent !important;
+  border-bottom-color: #ebeef555;
+  color: #fff;
+}
+.component_box ::v-deep .el-table__header-wrapper th {
+  background-color: #053a98 !important;
+  border-bottom-color: none;
+}
+
+// .t_table {
+//     font-size: 14px;
+//     color: #fff;
+//     width: 94%;
+//     margin: 0 auto;
+//     border-spacing: 0;
+//     text-align: center;
+//     box-sizing: border-box;
+//     margin-top: 10%;
+// }
+
+// .t_table tr {
+//     margin: 0;
+//     padding: 0;
+//     height: 40px;
+// }
+
+// .t_table thead tr {
+//     background: #053a98;
+// }
+
+// .t_table tbody tr td:first-child {
+//     border-left: 1px solid #053a98;
+// }
+
+// .t_table td {
+//     border-bottom: 1px solid #053a98;
+//     border-right: 1px solid #053a98;
+// }
 
 .t_title {
-    position: absolute;
-    font-size: 20px;
-    color: #fff;
-    left: 5%;
-    top: 10%;
+  // position: absolute;
+  font-size: 16px;
+  font-weight: 700;
+  color: #fff;
+  margin-left: 5%;
+  margin-top: 5%;
 }
-</style>
+</style>

+ 156 - 134
src/views/iot/board/components/alarmRate.vue

@@ -1,157 +1,179 @@
 <template>
-    <div class="component_box">
-        <div ref="chart" style="width: 100%; height: 100%;" @mouseenter="handleMouseEnter"
-            @mouseleave="handleMouseLeave"></div>
-    </div>
+  <div class="component_box">
+    <div
+      ref="chart"
+      style="width: 100%; height: 100%"
+      @mouseenter="handleMouseEnter"
+      @mouseleave="handleMouseLeave"
+    ></div>
+  </div>
 </template>
 <script>
-import { alarmRate } from '@/api/iot/board'
+import { alarmRate } from "@/api/iot/board";
+import * as echarts from "echarts";
 export default {
-    props: {
-        orgId: {
-            type: String,
-            isRequired: true,
-        },
-    },
-    data() {
-        return {
-            data: {
-                normalCount: 0,
-                alarmCount: 0
-            },
-            // activeName: types[0].value,
-        };
+  props: {
+    orgId: {
+      type: String,
+      isRequired: true,
     },
+  },
+  data() {
+    return {
+      data: {
+        normalCount: 0,
+        alarmCount: 0,
+      },
+    };
+  },
 
-    components: {},
+  components: {},
 
-    computed: {},
+  computed: {},
 
-    watch: {
-        orgId: {
-            deep: true,
-            handler(val) {
-                this.resetTimer();
-                this.getData();
-            },
-        },
-        data: {
-            deep: true,
-            handler() {
-                this.initMap();
-            },
-        },
+  watch: {
+    orgId: {
+      deep: true,
+      handler(val) {
+        this.resetTimer();
+        this.getData();
+      },
     },
-
-    created() {
-        this.refreshTime = 1 * 10 * 1000;
-        this.isMouseOver = false;
+    data: {
+      deep: true,
+      handler() {
+        this.initMap();
+      },
     },
+  },
+
+  created() {
+    this.refreshTime = 1 * 60 * 1000;
+    this.isMouseOver = false;
+  },
 
-    async mounted() {
-        window.addEventListener("resize", this.windowResize);
+  async mounted() {
+    window.addEventListener("resize", this.windowResize);
+  },
+  beforeDestroy() {
+    this.timer && clearInterval(this.timer);
+    this.timer = null;
+
+    window.removeEventListener("resize", this.windowResize);
+  },
+
+  methods: {
+    handleClick() {
+      this.resetTimer();
+      this.getData();
+    },
+    handleMouseEnter() {
+      this.isMouseOver = true;
+    },
+    handleMouseLeave() {
+      this.isMouseOver = false;
+    },
+    async getData() {
+      let r = (await alarmRate(this.orgId)).data;
+      this.data = r;
     },
-    beforeDestroy() {
-        this.timer && clearInterval(this.timer);
-        this.timer = null;
 
-        window.removeEventListener("resize", this.windowResize);
+    windowResize() {
+      this.myChart && this.myChart.resize();
     },
+    initMap() {
+      this.myChart && this.myChart.dispose();
+      let c = this.$refs["chart"];
 
-    methods: {
-        handleClick() {
-            this.resetTimer();
-            this.getData();
-        },
-        handleMouseEnter() {
-            this.isMouseOver = true;
+      // 基于准备好的dom,初始化echarts实例
+      this.myChart = echarts.init(c);
+      let option = {
+        title: {
+          text: "设备告警状态",
+          top: 35,
+          left: 20,
+          textStyle: {
+            fontSize: 18,
+            color: "#fff",
+          },
         },
-        handleMouseLeave() {
-            this.isMouseOver = false;
+        tooltip: {
+          trigger: "item",
+          formatter: "{a} <br/>{b}: {c} ({d}%)",
         },
-        async getData() {
-            let r = (await alarmRate(this.orgId))
-                .data;
-            this.data = r;
+        legend: {
+          right: 20,
+          top: 35,
+          data: ["告警", "正常"],
+          textStyle: {
+            color: "#fff",
+          },
         },
-
-        windowResize() {
-            this.myChart && this.myChart.resize();
-        },
-        initMap() {
-            this.myChart && this.myChart.dispose();
-            let c = this.$refs["chart"];
-
-            // 基于准备好的dom,初始化echarts实例
-            this.myChart = echarts.init(
-                c
-            );
-            option = {
-                title: {
-                    text: "设备告警状态",
-                    top: 35,
-                    left: 20,
-                    textStyle: {
-                        fontSize: 18,
-                        color: "#fff",
-                    },
+        series: [
+          {
+            name: "设备告警状态",
+            type: "pie",
+            radius: ["0", "55%"],
+            center: ["50%", "60%"],
+            // color: ['#e72325', '#98e002', '#2ca3fd'],
+            color: ["#F6A645", "#13D0B2"],
+            selectedMode: true,
+            selectedOffset: 4,
+            // avoidLabelOverlap:false,
+            // padAngle: 5,
+            // emphasis:{
+            //     label:{
+            //         show:true
+            //     }
+            // },
+            // itemStyle: {
+            //   borderWidth: 2,
+            //   borderColor: 'rgba(12,30,50,1)'
+            //   emphasis: {
+            //     shadowBlur: 10,
+            //     shadowOffsetX: 0,
+            //     shadowColor: "rgba(0,0,0,0,5)",
+            //   },
+            // },
+            label: {
+              normal: {
+                color: "inherit",
+                formatter: (param) => {
+                  return `${param.name}\n${param.percent == null ? 0 : param.percent}%`;
                 },
-                tooltip: {
-                    trigger: "item",
-                    formatter: "{a} <br/>{b}: {c} ({d}%)",
-                },
-                legend: {
-                    right: 20,
-                    top: 35,
-                    data: ["告警", "正常"],
-                    textStyle: {
-                        color: "#fff",
-                    },
-                },
-                series: [
-                    {
-                        name: "设备告警状态",
-                        type: "pie",
-                        radius: ["0", "60%"],
-                        center: ["50%", "60%"],
-                        // color: ['#e72325', '#98e002', '#2ca3fd'],
-                        color: ["#F6A645", "#13D0B2", "#2ca3fd"],
-                        label: {
-                            normal: {
-                                formatter: "{b}\n{d}%",
-                            },
-                        },
-                        data: [
-                            {
-                                value: this.data.alarmCount,
-                                name: "告警",
-                            },
-                            {
-                                value: this.data.normalCount,
-                                name: "正常",
-                                selected: true,
-                            },
-                        ],
-                    },
-                ],
-            };
-            // 使用刚指定的配置项和数据显示图表。
-            if (option && typeof option === "object") {
-                this.myChart.setOption(option);
-            }
-        },
+              },
+            },
+            data: [
+              {
+                value: this.data.alarmCount,
+                name: "告警",
+                selected: true,
+              },
+              {
+                value: this.data.normalCount,
+                name: "正常",
+              },
+            ],
+          },
+        ],
+      };
+      // 使用刚指定的配置项和数据显示图表。
+      if (option && typeof option === "object") {
+        this.myChart.setOption(option);
+      }
+    },
 
-        resetTimer() {
-            this.timer && clearInterval(this.timer);
-            this.timer = setInterval(() => {
-                if (this.isMouseOver) {
-                    return;
-                }
-                // this.activeName = getNextPeriod(this.types, this.activeName);
-                this.getData();
-            }, this.refreshTime);
-        },
+    resetTimer() {
+      this.timer && clearInterval(this.timer);
+      this.timer = setInterval(() => {
+        if (this.isMouseOver) {
+          return;
+        }
+        // this.activeName = getNextPeriod(this.types, this.activeName);
+        this.getData();
+      }, this.refreshTime);
     },
+  },
 };
 </script>
-<style scoped src="./../css/index.css"></style>
+<style scoped src="./../css/index.css"></style>

+ 388 - 341
src/views/iot/board/components/alarmTrend.vue

@@ -1,377 +1,424 @@
 <template>
-    <div class="component_box">
-        <div ref="chart" style="width: 100%; height: 100%;" @mouseenter="handleMouseEnter"
-            @mouseleave="handleMouseLeave"></div>
+  <div class="component_box" style="padding-top: 10px">
+    <div class="header">{{ title }}</div>
+    <div>
+      <el-tabs v-model="activeName" @tab-click="handleClick">
+        <el-tab-pane
+          v-for="t in types"
+          :key="t.value"
+          :label="t.text"
+          :name="t.value"
+        ></el-tab-pane>
+      </el-tabs>
     </div>
+    <div
+      ref="chart"
+      style="width: 100%; height: calc(100% - 40px)"
+      @mouseenter="handleMouseEnter"
+      @mouseleave="handleMouseLeave"
+    ></div>
+  </div>
 </template>
 <script>
-import { alarmTrend } from '@/api/iot/board'
+const types = [
+  {
+    text: "近七天",
+    value: "0",
+  },
+  {
+    text: "近7周",
+    value: "1",
+  },
+  {
+    text: "近半年",
+    value: "2",
+  },
+];
+import { alarmTrend } from "@/api/iot/board";
+import * as echarts from "echarts";
+import { getNextPeriod } from "@/views/board/utils.js";
 export default {
-    props: {
-        orgId: {
-            type: String,
-            isRequired: true,
-        },
-    },
-    data() {
-        return {
-            data: {
-                date: [], //x轴的日期
-                total: [], //报警总数
-                countByType: [],//按分类统计的报警总数
-            },
-            isMouseOver: false,
-            // activeName: types[0].value,
-        };
+  props: {
+    orgId: {
+      type: String,
+      isRequired: true,
     },
+  },
+  data() {
+    return {
+      types,
+      data: {
+        date: [], //x轴的日期
+        total: [], //报警总数
+        countByType: [], //按分类统计的报警总数
+      },
+      title: "近七天告警趋势",
+      isMouseOver: false,
+      activeName: types[0].value,
+    };
+  },
 
-    components: {},
+  components: {},
 
-    computed: {},
+  computed: {},
 
-    watch: {
-        orgId: {
-            deep: true,
-            handler(val) {
-                this.resetTimer();
-                this.getData();
-            },
-        },
-        data: {
-            deep: true,
-            handler() {
-                this.initMap();
-            },
-        },
+  watch: {
+    orgId: {
+      deep: true,
+      handler(val) {
+        this.resetTimer();
+        this.getData();
+      },
     },
-
-    created() {
-        this.types = types;
-        this.maxDisplay = 16;
-        this.refreshTime = 1 * 10 * 1000;
-        this.isMouseOver = false;
+    data: {
+      deep: true,
+      handler() {
+        this.initMap();
+      },
     },
+  },
 
-    async mounted() {
-        window.addEventListener("resize", this.windowResize);
-    },
-    beforeDestroy() {
-        this.timer && clearInterval(this.timer);
-        this.timer = null;
+  created() {
+    this.maxDisplay = 16;
+    this.refreshTime = 1 * 60 * 1000;
+    this.isMouseOver = false;
+  },
 
-        window.removeEventListener("resize", this.windowResize);
-    },
+  async mounted() {
+    window.addEventListener("resize", this.windowResize);
+  },
+  beforeDestroy() {
+    this.timer && clearInterval(this.timer);
+    this.timer = null;
 
-    methods: {
-        // handleClick() {
-        //     this.resetTimer();
-        //     this.getData();
-        // },
-        handleMouseEnter() {
-            this.isMouseOver = true;
-        },
-        handleMouseLeave() {
-            this.isMouseOver = false;
-        },
-        async getData() {
-            let r = (await alarmTrend(this.orgId))
-                .data;
-            let data = {
-                date: [], //x轴的日期
-                total: [], //报警总数
-                countByType: [],//按分类统计的报警总数
-            };
+    window.removeEventListener("resize", this.windowResize);
+  },
 
-            let monitorCount = [];
-            let fireCount = [];
-            let environmentCount = [];
-            for (let item of r) {
-                data.total.push(item.total);
-                monitorCount.push(item.monitorCount);
-                fireCount.push(item.fireCount);
-                environmentCount.push(item.environmentCount);
+  methods: {
+    handleClick() {
+      this.title = types[this.activeName].text + "告警趋势";
+      this.resetTimer();
+      this.getData();
+    },
+    handleMouseEnter() {
+      this.isMouseOver = true;
+    },
+    handleMouseLeave() {
+      this.isMouseOver = false;
+    },
+    async getData() {
+      let r = (await alarmTrend(this.orgId, this.activeName)).data;
+      let data = {
+        date: [], //x轴的日期
+        total: [], //报警总数
+        countByType: [], //按分类统计的报警总数
+      };
 
-                data.date.push(item.orgName);
-            }
+      let monitorCount = [];
+      let fireCount = [];
+      let environmentCount = [];
+      for (let item of r) {
+        data.total.push(item.total);
+        monitorCount.push(item.monitorCount);
+        fireCount.push(item.fireCount);
+        environmentCount.push(item.environmentCount);
 
-            data.countByType.push(monitorCount)
-            data.countByType.push(fireCount)
-            data.countByType.push(environmentCount);
-            this.data = data;
-        },
+        data.date.push(item.date);
+      }
 
-        windowResize() {
-            this.myChart && this.myChart.resize();
-        },
-        initMap() {
-            this.myChart && this.myChart.dispose();
-            let c = this.$refs["chart"];
+      data.countByType.push(monitorCount);
+      data.countByType.push(fireCount);
+      data.countByType.push(environmentCount);
 
-            // 基于准备好的dom,初始化echarts实例
-            this.myChart = echarts.init(
-                c
-            );
-            var data = {
-                id: "multipleBarsLines",
-                title: "近7天告警趋势",
-                legendBar: ["报警总数"],
-                symbol: "", //数值是否带百分号        --默认为空 ''
-                legendLine: ["监控设备", "消防设备", "环境监测"],
-                // xAxis: ["9月19", "9月20", "9月21", "9月22", "9月23", "9月24", "9月25"],
-                // yAxis: [[8, 10, 10, 11, 4, 13, 8]],
-                // lines: [
-                //     [4, 3, 2, 4, 2, 1, 1],
-                //     [2, 1, 4, 2, 3, 2, 4],
-                //     [1, 0, 2, 1, 1, 2, 1],
-                // ],
-                barColor: ["#3FA7DC", "#7091C4", "#5170A2"], //柱子颜色 必填参数
-                lineColor: ["#D9523F"], // 折线颜色
-            };
-            /////////////end/////////
+      this.data = data;
+    },
 
-            var myData = (function test() {
-                var yAxis = this.data.total || [];
-                var lines = this.data.countByType || [];
-                var legendBar = data.legendBar || [];
-                var legendLine = data.legendLine || [];
-                var symbol = data.symbol || " ";
-                var seriesArr = [];
-                var legendArr = [];
-                yAxis &&
-                    yAxis.forEach((item, index) => {
-                        legendArr.push({
-                            name: legendBar && legendBar.length > 0 && legendBar[index],
-                        });
-                        seriesArr.push({
-                            name: legendBar && legendBar.length > 0 && legendBar[index],
-                            type: "bar",
-                            barGap: "0.5px",
-                            data: item,
-                            barWidth: data.barWidth || 12,
-                            label: {
-                                normal: {
-                                    show: true,
-                                    formatter: "{c}" + symbol,
-                                    position: "top",
-                                    textStyle: {
-                                        color: "#fff",
-                                        fontStyle: "normal",
-                                        fontFamily: "微软雅黑",
-                                        textAlign: "left",
-                                        fontSize: 11,
-                                    },
-                                },
-                            },
-                            itemStyle: {
-                                //图形样式
-                                normal: {
-                                    barBorderRadius: 4,
-                                    color: data.barColor[index],
-                                },
-                            },
-                        });
-                    });
+    windowResize() {
+      this.myChart && this.myChart.resize();
+    },
+    initMap() {
+      this.myChart && this.myChart.dispose();
+      let c = this.$refs["chart"];
 
-                lines &&
-                    lines.forEach((item, index) => {
-                        legendArr.push({
-                            name: legendLine && legendLine.length > 0 && legendLine[index],
-                        });
-                        seriesArr.push({
-                            name: legendLine && legendLine.length > 0 && legendLine[index],
-                            type: "line",
-                            data: item,
-                            itemStyle: {
-                                normal: {
-                                    color: data.lineColor[index],
-                                    lineStyle: {
-                                        width: 3,
-                                        type: "solid",
-                                    },
-                                },
-                            },
-                            label: {
-                                normal: {
-                                    show: false, //折线上方label控制显示隐藏
-                                    position: "top",
-                                },
-                            },
-                            symbol: "circle",
-                            symbolSize: 10,
-                        });
-                    });
+      // 基于准备好的dom,初始化echarts实例
+      this.myChart = echarts.init(c);
 
-                return {
-                    seriesArr,
-                    legendArr,
-                };
-            })();
+      var data = {
+        id: "multipleBarsLines",
+        title: types[this.activeName].text + "告警趋势",
+        legendBar: ["报警总数"],
+        symbol: "", //数值是否带百分号        --默认为空 ''
+        legendLine: ["监控设备", "消防设备", "环境监测"],
+        // xAxis: ["9月19", "9月20", "9月21", "9月22", "9月23", "9月24", "9月25"],
+        // yAxis: [[8, 10, 10, 11, 4, 13, 8]],
+        // lines: [
+        //     [4, 3, 2, 4, 2, 1, 1],
+        //     [2, 1, 4, 2, 3, 2, 4],
+        //     [1, 0, 2, 1, 1, 2, 1],
+        // ],
+        barColor: ["#3FA7DC", "#7091C4", "#5170A2"], //柱子颜色 必填参数
+        lineColor: ["#D9523F"], // 折线颜色
+      };
+      /////////////end/////////
 
-            option = {
-                title: {
-                    show: true,
-                    top: "10%",
-                    left: "3%",
-                    text: data.title,
-                    textStyle: {
-                        fontSize: 18,
-                        color: "#fff",
-                    },
-                    subtext: data.subTitle,
-                    link: "",
-                },
-                tooltip: {
-                    trigger: "axis",
-                    formatter: function (params) {
-                        var time = "";
-                        var str = "";
-                        for (var i of params) {
-                            time = i.name.replace(/\n/g, "") + "<br/>";
-                            if (i.data == "null" || i.data == null) {
-                                str += i.seriesName + ":无数据" + "<br/>";
-                            } else {
-                                str += i.seriesName + ":" + i.data + symbol + "%<br/>";
-                            }
-                        }
-                        return time + str;
-                    },
-                    axisPointer: {
-                        type: "none",
-                    },
-                },
-                legend: {
-                    right: data.legendRight || "30%",
-                    top: "12%",
-                    right: "5%",
-                    itemGap: 16,
-                    itemWidth: 10,
-                    itemHeight: 10,
-                    data: myData.legendArr,
-                    textStyle: {
-                        color: "#fff",
-                        fontStyle: "normal",
-                        fontFamily: "微软雅黑",
-                        fontSize: 12,
-                    },
+      var myData = (() => {
+        var yAxis = [this.data.total] || [];
+        var lines = this.data.countByType || [];
+        var legendBar = data.legendBar || [];
+        var legendLine = data.legendLine || [];
+        var symbol = data.symbol || " ";
+        var seriesArr = [];
+        var legendArr = [];
+
+        yAxis &&
+          yAxis.forEach((item, index) => {
+            legendArr.push({
+              name: legendBar && legendBar.length > 0 && legendBar[index],
+            });
+            seriesArr.push({
+              name: legendBar && legendBar.length > 0 && legendBar[index],
+              type: "bar",
+              barGap: "0.5px",
+              data: item,
+              barWidth: data.barWidth || 12,
+              label: {
+                normal: {
+                  show: true,
+                  formatter: "{c}" + symbol,
+                  position: "top",
+                  textStyle: {
+                    color: "#fff",
+                    fontStyle: "normal",
+                    fontFamily: "微软雅黑",
+                    textAlign: "left",
+                    fontSize: 11,
+                  },
                 },
-                grid: {
-                    x: 30,
-                    y: 80,
-                    x2: 30,
-                    y2: 60,
+              },
+              itemStyle: {
+                //图形样式
+                normal: {
+                  barBorderRadius: 4,
+                  color: data.barColor[index],
                 },
-                xAxis: {
-                    type: "category",
-                    data: this.data.date,
-                    axisTick: {
-                        show: false,
-                    },
-
-                    axisLine: {
-                        show: true,
-                        lineStyle: {
-                            color: "#1AA1FD",
-                        },
-                        symbol: ["none", "arrow"],
-                    },
-                    axisLabel: {
-                        show: true,
-                        interval: "0",
-                        textStyle: {
-                            lineHeight: 16,
-                            padding: [2, 2, 0, 2],
-                            height: 50,
-                            fontSize: 12,
-                        },
-                        rich: {
-                            Sunny: {
-                                height: 50,
-                                // width: 60,
-                                padding: [0, 5, 0, 5],
-                                align: "center",
-                            },
-                        },
-                        formatter: function (params, index) {
-                            var newParamsName = "";
-                            var splitNumber = 5;
-                            var paramsNameNumber = params && params.length;
-                            if (paramsNameNumber && paramsNameNumber <= 4) {
-                                splitNumber = 4;
-                            } else if (paramsNameNumber >= 5 && paramsNameNumber <= 7) {
-                                splitNumber = 4;
-                            } else if (paramsNameNumber >= 8 && paramsNameNumber <= 9) {
-                                splitNumber = 5;
-                            } else if (paramsNameNumber >= 10 && paramsNameNumber <= 14) {
-                                splitNumber = 5;
-                            } else {
-                                params = params && params.slice(0, 15);
-                            }
+              },
+            });
+          });
 
-                            var provideNumber = splitNumber; //一行显示几个字
-                            var rowNumber = Math.ceil(paramsNameNumber / provideNumber) || 0;
-                            if (paramsNameNumber > provideNumber) {
-                                for (var p = 0; p < rowNumber; p++) {
-                                    var tempStr = "";
-                                    var start = p * provideNumber;
-                                    var end = start + provideNumber;
-                                    if (p == rowNumber - 1) {
-                                        tempStr = params.substring(start, paramsNameNumber);
-                                    } else {
-                                        tempStr = params.substring(start, end) + "\n";
-                                    }
-                                    newParamsName += tempStr;
-                                }
-                            } else {
-                                newParamsName = params;
-                            }
-                            params = newParamsName;
-                            return "{Sunny|" + params + "}";
-                        },
-                        color: "#1AA1FD",
-                    },
+        lines &&
+          lines.forEach((item, index) => {
+            legendArr.push({
+              name: legendLine && legendLine.length > 0 && legendLine[index],
+            });
+            seriesArr.push({
+              name: legendLine && legendLine.length > 0 && legendLine[index],
+              type: "line",
+              data: item,
+              itemStyle: {
+                normal: {
+                  color: data.lineColor[index],
+                  lineStyle: {
+                    width: 3,
+                    type: "solid",
+                  },
                 },
-                yAxis: {
-                    axisLine: {
-                        show: true,
-                        lineStyle: {
-                            color: "#1AA1FD",
-                        },
-                        symbol: ["none", "arrow"],
-                    },
-                    type: "value",
-                    axisTick: {
-                        show: false,
-                    },
-                    axisLabel: {
-                        show: false,
-                    },
-                    splitLine: {
-                        show: false,
-                        lineStyle: {
-                            color: "#1AA1FD",
-                            type: "solid",
-                        },
-                    },
+              },
+              label: {
+                normal: {
+                  show: false, //折线上方label控制显示隐藏
+                  position: "top",
                 },
-                series: myData.seriesArr,
-            };
-            // 使用刚指定的配置项和数据显示图表。
-            if (option && typeof option === "object") {
-                this.myChart.setOption(option);
+              },
+              symbol: "circle",
+              symbolSize: 10,
+            });
+          });
+
+        return {
+          seriesArr,
+          legendArr,
+        };
+      })();
+      //   console.info(myData);
+      let option = {
+        // title: {
+        //   show: false,
+        //   top: "5%",
+        //   left: "3%",
+        //   text: data.title,
+        //   textStyle: {
+        //     fontSize: 18,
+        //     color: "#fff",
+        //   },
+        //   subtext: data.subTitle,
+        //   link: "",
+        // },
+        tooltip: {
+          trigger: "axis",
+          formatter: function (params) {
+            var time = "";
+            var str = "";
+            for (var i of params) {
+              time = i.name.replace(/\n/g, "") + "<br/>";
+              if (i.data == "null" || i.data == null) {
+                str += i.seriesName + ":无数据" + "<br/>";
+              } else {
+                str += i.seriesName + ":" + i.data + data.symbol + "<br/>";
+              }
             }
+            return time + str;
+          },
+          axisPointer: {
+            type: "none",
+          },
+        },
+        legend: {
+          right: data.legendRight || "30%",
+          top: "3%",
+          right: "5%",
+          itemGap: 16,
+          itemWidth: 10,
+          itemHeight: 10,
+          data: myData.legendArr,
+          textStyle: {
+            color: "#fff",
+            fontStyle: "normal",
+            fontFamily: "微软雅黑",
+            fontSize: 12,
+          },
+        },
+        grid: {
+          x: 30,
+          y: 60,
+          x2: 30,
+          y2: 60,
         },
+        xAxis: {
+          type: "category",
+          data: this.data.date,
+          axisTick: {
+            show: false,
+          },
 
-        resetTimer() {
-            this.timer && clearInterval(this.timer);
-            this.timer = setInterval(() => {
-                if (this.isMouseOver) {
-                    return;
+          axisLine: {
+            show: true,
+            lineStyle: {
+              color: "#1AA1FD",
+            },
+            symbol: ["none", "arrow"],
+          },
+          axisLabel: {
+            show: true,
+            interval: "0",
+            textStyle: {
+              lineHeight: 16,
+              padding: [2, 2, 0, 2],
+              height: 50,
+              fontSize: 12,
+            },
+            rich: {
+              Sunny: {
+                height: 50,
+                // width: 60,
+                padding: [0, 5, 0, 5],
+                align: "center",
+              },
+            },
+            formatter: function (params, index) {
+              var newParamsName = "";
+              var splitNumber = 6;
+              var paramsNameNumber = params && params.length;
+              //   if (paramsNameNumber && paramsNameNumber <= 4) {
+              //     splitNumber = 4;
+              //   } else if (paramsNameNumber >= 5 && paramsNameNumber <= 7) {
+              //     splitNumber = 5;
+              //   } else if (paramsNameNumber >= 8 && paramsNameNumber <= 9) {
+              //     splitNumber = 5;
+              //   } else if (paramsNameNumber >= 10 && paramsNameNumber <= 14) {
+              //     splitNumber = 5;
+              //   } else {
+              //     params = params && params.slice(0, 15);
+              //   }
+
+              var provideNumber = splitNumber; //一行显示几个字
+              var rowNumber = Math.ceil(paramsNameNumber / provideNumber) || 0;
+              if (paramsNameNumber > provideNumber) {
+                for (var p = 0; p < rowNumber; p++) {
+                  var tempStr = "";
+                  var start = p * provideNumber;
+                  var end = start + provideNumber;
+                  if (p == rowNumber - 1) {
+                    tempStr = params.substring(start, paramsNameNumber);
+                  } else {
+                    tempStr = params.substring(start, end) + "\n";
+                  }
+                  newParamsName += tempStr;
                 }
-                this.activeName = getNextPeriod(this.types, this.activeName);
-                this.getData();
-            }, this.refreshTime);
+              } else {
+                newParamsName = params;
+              }
+              params = newParamsName;
+              return "{Sunny|" + params + "}";
+            },
+            color: "#1AA1FD",
+          },
         },
+        yAxis: {
+          axisLine: {
+            show: true,
+            lineStyle: {
+              color: "#1AA1FD",
+            },
+            symbol: ["none", "arrow"],
+          },
+          type: "value",
+          axisTick: {
+            show: false,
+          },
+          axisLabel: {
+            show: false,
+          },
+          splitLine: {
+            show: false,
+            lineStyle: {
+              color: "#1AA1FD",
+              type: "solid",
+            },
+          },
+        },
+        series: myData.seriesArr,
+      };
+      // 使用刚指定的配置项和数据显示图表。
+      if (option && typeof option === "object") {
+        this.myChart.setOption(option);
+      }
+    },
+
+    resetTimer() {
+      this.timer && clearInterval(this.timer);
+      this.timer = setInterval(() => {
+        if (this.isMouseOver) {
+          return;
+        }
+        this.activeName = getNextPeriod(this.types, this.activeName);
+        this.getData();
+      }, this.refreshTime);
     },
+  },
 };
 </script>
-<style scoped src="./../css/index.css"></style>
+<style scoped src="./../css/index.css"></style>
+<style lang="scss" scoped>
+.header {
+  position: absolute;
+  top: calc(18px + 20px);
+  left: calc(18px + 3%);
+  font-size: 16px;
+  font-weight: 700;
+}
+.component_box {
+  ::v-deep .el-tabs__nav-scroll {
+    justify-content: right !important;
+  }
+}
+</style>

+ 120 - 126
src/views/iot/board/components/deviceCount.vue

@@ -1,132 +1,127 @@
 <template>
-    <div class="component_box">
-        <div class="t_mbox t_rbox">
-            <div>
-                <i></i>
-            </div>
-            <div>
-                <div>
-                    <span>视频监控设备</span>
-                    <span>{{ info.monitorCount }}</span>
-                </div>
-            </div>
+  <div class="component_box">
+    <div class="t_mbox t_rbox">
+      <div>
+        <i></i>
+      </div>
+      <div>
+        <div>
+          <span>视频监控设备</span>
+          <span>{{ info.monitorCount }}</span>
         </div>
-        <div class="t_mbox t_gbox">
-            <div>
-                <i></i>
-            </div>
-            <div>
-                <div>
-                    <span>消防预警设备</span>
-                    <span>{{ info.fireCount }}</span>
-                </div>
-            </div>
+      </div>
+    </div>
+    <div class="t_mbox t_gbox">
+      <div>
+        <i></i>
+      </div>
+      <div>
+        <div>
+          <span>消防预警设备</span>
+          <span>{{ info.fireCount }}</span>
         </div>
-        <div class="t_mbox t_ybox">
-            <div>
-                <i></i>
-            </div>
-            <div>
-                <div>
-                    <span>环境监测设备</span>
-                    <span>{{ info.environmentCount }}</span>
-                </div>
-            </div>
+      </div>
+    </div>
+    <div class="t_mbox t_ybox">
+      <div>
+        <i></i>
+      </div>
+      <div>
+        <div>
+          <span>环境监测设备</span>
+          <span>{{ info.environmentCount }}</span>
         </div>
+      </div>
     </div>
+  </div>
 </template>
 <script>
 import { deviceCount } from "@/api/iot/board";
 export default {
-    data() {
-        return {
-            info: {
-                monitorCount: 0,
-                fireCount: 0,
-                environmentCount: 0
-            },
-        }
+  data() {
+    return {
+      info: {
+        monitorCount: 0,
+        fireCount: 0,
+        environmentCount: 0,
+      },
+    };
+  },
+  props: {
+    orgId: {
+      type: String,
+      isRequired: true,
     },
-    props: {
-        orgId: {
-            type: String,
-            isRequired: true,
-        }
+  },
+  watch: {
+    orgId: {
+      deep: true,
+      handler(val) {
+        this.resetTimer();
+        this.getData();
+      },
     },
-    watch: {
-        orgId: {
-            deep: true,
-            handler(val) {
-                this.resetTimer();
-                this.getData();
-            },
-        }
+  },
+  created() {
+    this.refreshTime = 10 * 60 * 1000;
+    this.isMouseOver = false;
+  },
+  methods: {
+    getData() {
+      deviceCount(this.orgId).then((r) => {
+        this.info = r.data;
+      });
     },
-    created() {
-        this.refreshTime = 1 * 10 * 1000;
-        this.isMouseOver = false;
+    beforeDestroy() {
+      this.timer && clearInterval(this.timer);
+      this.timer = null;
     },
-    methods: {
-        getData() {
-            deviceCount(this.orgId).then(r => {
-                this.info = r.data;
-            })
-        },
-        beforeDestroy() {
-            this.timer && clearInterval(this.timer);
-            this.timer = null;
-        },
-        resetTimer() {
-            this.timer && clearInterval(this.timer);
-            this.timer = setInterval(() => {
-                // if (this.isMouseOver) {
-                //     return;
-                // }
-                // this.activeName = getNextPeriod(this.types, this.activeName);
-                this.getData();
-            }, this.refreshTime);
-        },
-    }
-}
+    resetTimer() {
+      this.timer && clearInterval(this.timer);
+      this.timer = setInterval(() => {
+        this.getData();
+      }, this.refreshTime);
+    },
+  },
+};
 </script>
 <style scoped src="./../css/index.css"></style>
 <style lang="scss" scoped>
 .t_mbox {
-    width: 90%;
-    height: 28.33%;
-    /* position: relative; */
-    margin: 0 auto;
-    margin-top: 5%;
-    display: flex;
+  width: 90%;
+  height: 28.33%;
+  /* position: relative; */
+  margin: 0 auto;
+  margin-top: 5%;
+  display: flex;
 }
 
-.t_mbox>div {
-    height: 100%;
-    display: flex;
-    align-items: center;
+.t_mbox > div {
+  height: 100%;
+  display: flex;
+  align-items: center;
 }
 
-.t_mbox>div:first-child {
-    width: 40%;
-    text-align: right;
-    padding-left: calc(40% - 50px - 10px);
+.t_mbox > div:first-child {
+  width: 40%;
+  text-align: right;
+  padding-left: calc(40% - 50px - 10px);
 }
 
-.t_mbox>div:first-child>i {
-    display: block;
-    width: 50px;
-    height: 50px;
-    /* top: 0;
+.t_mbox > div:first-child > i {
+  display: block;
+  width: 50px;
+  height: 50px;
+  /* top: 0;
     bottom: 0; */
 }
 
-.t_mbox>div:nth-child(2) {
-    width: 60%;
-    display: flex;
-    justify-content: center;
+.t_mbox > div:nth-child(2) {
+  width: 60%;
+  display: flex;
+  justify-content: center;
 }
 
-
 // .t_mbox>div:nth-child(2) h2 {
 //     font-size: 20px;
 //     color: #fff;
@@ -134,52 +129,51 @@ export default {
 //     // top: 50%;
 //     // left: 50%;
 // }
-.t_mbox>div:nth-child(2)>div {
-    display: flex;
-    flex-direction: column;
-    align-items: center;
+.t_mbox > div:nth-child(2) > div {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
 }
 
-.t_mbox>div:nth-child(2)>div span {
-    font-size: 20px;
-    color: #fff;
+.t_mbox > div:nth-child(2) > div span {
+  font-size: 20px;
+  color: #fff;
 
-    // position: relative;
-    // top: 24%;
-    // left: 48%;
+  // position: relative;
+  // top: 24%;
+  // left: 48%;
 }
 
-.t_mbox>div:nth-child(2)>div span:last-child {
-    margin-top: 10px;
+.t_mbox > div:nth-child(2) > div span:last-child {
+  margin-top: 10px;
 }
 
 .t_rbox {
-    background: #d9523f;
-    /* #44AFF0 */
+  background: #d9523f;
+  /* #44AFF0 */
 }
 
 .t_gbox {
-    background: #13d0b2;
+  background: #13d0b2;
 }
 
 .t_ybox {
-    background: #f6a645;
-    /* #4777F5 */
+  background: #f6a645;
+  /* #4777F5 */
 }
 
-
 .t_rbox i {
-    background: url(../img/monitor.png) no-repeat;
-    background-size: 100% 100%;
+  background: url(../img/monitor.png) no-repeat;
+  background-size: 100% 100%;
 }
 
 .t_gbox i {
-    background: url(../img/fire.png) no-repeat;
-    background-size: 100% 100%;
+  background: url(../img/fire.png) no-repeat;
+  background-size: 100% 100%;
 }
 
 .t_ybox i {
-    background: url(../img/environment.png) no-repeat;
-    background-size: 100% 100%;
+  background: url(../img/environment.png) no-repeat;
+  background-size: 100% 100%;
 }
-</style>
+</style>

+ 260 - 236
src/views/iot/board/components/deviceMap.vue

@@ -1,258 +1,282 @@
+<!--  -->
+<template>
+  <div class="component_box">
+    <div id="iot_map_Chart" style="height: 100%"></div>
+  </div>
+</template>
 
+<script>
+import * as echarts from "echarts";
+import { getMap, mapInfo } from "@/api/board/cockpit.js";
+import { deviceCountOfChildren } from "@/api/iot/board";
+export default {
+  props: ["orgId", "orgName"],
+  data() {
+    return {
+      map: {},
+      deviceCount: {},
+      coordinates: [],
+      icon: "image://data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAAUCAYAAABvVQZ0AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAF3SURBVDhPvZTBK4RBGIe/z56UklDay+6JkhM3RYo/wVlOrg4uTtyc3JSrg6Lc2CQHp5U7RyVylBBJXD7PO/PO7M43Y3OQp57mfd/fzOz6dlf2LxRFMYLr2hro63io7e/gQI53uKwjA303Cr06CujStcwV1rCHg3Kpgf4E1/CBtsraGTbN4wv24Q0K2/hsy2IFN/FJj6Rhw4zshg2ctGVxodkcfmET+/EVd8zBFISXKH+O1HtSQ92EQD2Bo1rfSggLJmyHoQvNZYK27nKXm3fDGu030I/ZsecDh/DIdCHy9Ti1peceK+6yFGeaLaE8q1UcxllMYR8HxYHtI4IHTO8+oDJvOOA2VfFTpgm2zCagfrejiIZuaaFBhGb+gZfYNYfLEKQeuFDBny7zX50IwvIn1emdTZlDSuq3ua+r41rX8jzL87ypZQyvVLMvGDCoseTuV+EI/kUFEB7bPZ5FjTw6b2dcoxYMGzbznGsUwHzaxp5Hjf6SLPsG2jnZyz2k38wAAAAASUVORK5CYII=",
+    };
+  },
 
+  components: {},
 
-<!--  -->
-<template>
-    <div class="component_box">
-      <div id="iot_map_Chart" style="height: 100%"></div>
-    </div>
-  </template>
-  
-  <script>
+  computed: {},
 
-  import * as echarts from "echarts";
-  import { getMap,mapInfo } from "@/api/board/cockpit.js";
-  
-  export default {
-    props: ["orgId", "orgName"],
-    data() {
-      return {
-        map: {},
-        coordinates: [],
-        icon: "image://data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAAUCAYAAABvVQZ0AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAF3SURBVDhPvZTBK4RBGIe/z56UklDay+6JkhM3RYo/wVlOrg4uTtyc3JSrg6Lc2CQHp5U7RyVylBBJXD7PO/PO7M43Y3OQp57mfd/fzOz6dlf2LxRFMYLr2hro63io7e/gQI53uKwjA303Cr06CujStcwV1rCHg3Kpgf4E1/CBtsraGTbN4wv24Q0K2/hsy2IFN/FJj6Rhw4zshg2ctGVxodkcfmET+/EVd8zBFISXKH+O1HtSQ92EQD2Bo1rfSggLJmyHoQvNZYK27nKXm3fDGu030I/ZsecDh/DIdCHy9Ti1peceK+6yFGeaLaE8q1UcxllMYR8HxYHtI4IHTO8+oDJvOOA2VfFTpgm2zCagfrejiIZuaaFBhGb+gZfYNYfLEKQeuFDBny7zX50IwvIn1emdTZlDSuq3ua+r41rX8jzL87ypZQyvVLMvGDCoseTuV+EI/kUFEB7bPZ5FjTw6b2dcoxYMGzbznGsUwHzaxp5Hjf6SLPsG2jnZyz2k38wAAAAASUVORK5CYII=",
-      };
-    },
-  
-    components: {},
-  
-    computed: {},
-  
-    watch: {
-      orgId: {
-        deep: true,
-        handler(val) {
-          //   this.resetTimer();
-          this.getData();
-        },
+  watch: {
+    orgId: {
+      deep: true,
+      handler(val) {
+        //   this.resetTimer();
+        this.getData();
       },
-      // map: {
-      //   deep: true,
-      //   handler() {
-      //     this.$nextTick(() => {
-      //       this.initMap();
-      //     });
-      //   },
-      // },
     },
-  
-    created() {
-      //   this.types = types;
-      //   this.maxDisplay = 16;
-      //   this.refreshTime = 1 * 10 * 1000;
-      this.isMouseOver = false;
+    // map: {
+    //   deep: true,
+    //   handler() {
+    //     this.$nextTick(() => {
+    //       this.initMap();
+    //     });
+    //   },
+    // },
+  },
+
+  created() {
+    //   this.types = types;
+    //   this.maxDisplay = 16;
+    //   this.refreshTime = 1 * 10 * 1000;
+    this.isMouseOver = false;
+  },
+
+  async mounted() {
+    // console.info(this.fjMap)
+
+    window.addEventListener("resize", this.windowResize);
+  },
+  beforeDestroy() {
+    this.timer && clearInterval(this.timer);
+    this.timer = null;
+
+    window.removeEventListener("resize", this.windowResize);
+  },
+
+  methods: {
+    // handleClick() {
+    //   this.resetTimer();
+    //   this.getData();
+    // },
+    handleMouseEnter() {
+      this.isMouseOver = true;
     },
-  
-    async mounted() {
-      // console.info(this.fjMap)
-  
-      window.addEventListener("resize", this.windowResize);
+    handleMouseLeave() {
+      this.isMouseOver = false;
     },
-    beforeDestroy() {
-      this.timer && clearInterval(this.timer);
-      this.timer = null;
-  
-      window.removeEventListener("resize", this.windowResize);
+    async getData() {
+      let mapinfo = await mapInfo(this.orgId);
+      let deviceCount = (await deviceCountOfChildren(this.orgId)).data;
+      let orgIdsHasDevice = deviceCount.map((d) => d.orgId);
+
+      let map = mapinfo.data.map;
+      let coordinates = mapinfo.data.sites
+        .filter((s) => orgIdsHasDevice.includes(s.orgId))
+        .map((s) => ({
+          name: s.orgName,
+          id: s.orgId,
+          value: [s.longitude, s.latitude, 10],
+        }));
+
+      this.map = map;
+      this.coordinates = coordinates;
+      this.deviceCount = deviceCount;
+      this.$nextTick(() => {
+        this.initMap();
+      });
     },
-  
-    methods: {
-      // handleClick() {
-      //   this.resetTimer();
-      //   this.getData();
-      // },
-      handleMouseEnter() {
-        this.isMouseOver = true;
-      },
-      handleMouseLeave() {
-        this.isMouseOver = false;
-      },
-      async getData() {
-        let mapinfo= await mapInfo(this.orgId);
-  
-        let map = mapinfo.data.map;
-        let coordinates =mapinfo.data.sites.map(s=>({ name: s.orgName, value: [s.longitude,s.latitude, 10] })); 
-        this.map = map;
-        this.coordinates = coordinates;
-        this.$nextTick(() => {
-          this.initMap();
-        });
-      },
-      initMap() {
-        this.myChart && this.myChart.dispose();
-  
-        // 基于准备好的dom,初始化echarts实例
-        this.myChart = echarts.init(document.getElementById("iot_map_Chart"));
-        let t = this;
-  
-        getMap(this.map).then((data) => {
-          echarts.registerMap("map", data);
-  
-          let option = {
-            tooltip: {
-              trigger: "item",
+    initMap() {
+      this.myChart && this.myChart.dispose();
+
+      // 基于准备好的dom,初始化echarts实例
+      this.myChart = echarts.init(document.getElementById("iot_map_Chart"));
+      let t = this;
+
+      getMap(this.map).then((data) => {
+        echarts.registerMap("map", data);
+
+        let option = {
+          tooltip: {
+            trigger: "item",
+          },
+          geo: {
+            show: true,
+            map: "map",
+            zoom: 1.25,
+
+            showLegendSymbol: false, // 存在legend时显示
+
+            label: {
+              normal: {
+                show: false,
+                color: "#c1b496", //控制地图省市文字颜色
+                fontSize: 14,
+              },
+              emphasis: {
+                show: false,
+                color: "#fff", //悬浮字体颜色
+              },
+            },
+
+            roam: true,
+            selectedMode: "single", //选择模式,单选,只能选中一个地市
+            select: {
+              //这个就是鼠标点击后,地图想要展示的配置
+              disabled: false, //可以被选中
+              itemStyle: {
+                //相关配置项很多,可以参考echarts官网
+                borderWidth: 1, //区域边框宽度
+                borderColor: "#2B91B7ff", //区域边框颜色
+                areaColor: "#2B91B730", //选中
+              },
+              label: {
+                show: false,
+                color: "#fff", //悬浮字体颜色
+              },
+            },
+            itemStyle: {
+              normal: {
+                borderWidth: 1, //区域边框宽度
+                borderColor: "#3fdaffff", //区域边框颜色
+                areaColor: "#3fdaff55", //区域颜色"rgba(23,107,221,0.7)",//
+              },
+              emphasis: {
+                borderWidth: 1,
+                borderColor: "#fff",
+                areaColor: "#2B91B7",
+              },
             },
-            geo: {
-              show: true,
+          },
+          legend: [
+            {
+              selectedMode: true, //取消图例上的点击事件
+            },
+          ],
+          series: [
+            {
               map: "map",
-              zoom: 1.25,
-  
-              showLegendSymbol: false, // 存在legend时显示
-  
+              type: "effectScatter",
+              // silent: true,
+              coordinateSystem: "geo",
+              // datasetIndex: 0,
+              // geoIndex: 0,
+              // selectedMode: false,
+              // focusNodeAdjacency: false,
+              // label: {
+              // 	show: true,
+              // 	width: 13,
+              // 	height: 15,
+              // 	fontSize: 0,
+              // 	color: "#1DF9FC",
+              // 	backgroundColor: {
+              // 		image: iconRQ
+              // 	},
+              // },
               label: {
-                normal: {
-                  show: false,
-                  color: "#c1b496", //控制地图省市文字颜色
-                  fontSize: 14,
-                },
-                emphasis: {
-                  show: false,
-                  color: "#fff", //悬浮字体颜色
+                formatter: (param) => {
+                  return param.name;
                 },
+                position: "top",
+                fontSize: "10",
+                color: "#fff",
+                show: true,
               },
-  
-              roam: true,
-              selectedMode: "single", //选择模式,单选,只能选中一个地市
-              select: {
-                //这个就是鼠标点击后,地图想要展示的配置
-                disabled: false, //可以被选中
-                itemStyle: {
-                  //相关配置项很多,可以参考echarts官网
-                  borderWidth: 1, //区域边框宽度
-                  borderColor: "#2B91B7ff", //区域边框颜色
-                  areaColor: "#2B91B730", //选中
-                },
-                label: {
-                  show: false,
-                  color: "#fff", //悬浮字体颜色
-                },
+              tooltip: {
+                show: false,
               },
-              itemStyle: {
-                normal: {
-                  borderWidth: 1, //区域边框宽度
-                  borderColor: "#3fdaffff", //区域边框颜色
-                  areaColor: "#3fdaff55", //区域颜色"rgba(23,107,221,0.7)",//
+              tooltip: {
+                position: "right",
+                textStyle: {
+                  // color:'#fff',
                 },
-                emphasis: {
-                  borderWidth: 1,
-                  borderColor: "#fff",
-                  areaColor: "#2B91B7",
+                // backgroundColor:'rgba(184,189,192,1)',
+                formatter: function (param) {
+                  // debugger
+                  let deviceCount = t.deviceCount.find(
+                    (d) => d.orgId == param.data.id
+                  );
+                  // console.info(deviceCount)
+                  if (deviceCount) {
+                    return `<div >
+                  <div> ${param.data.name} </div>
+                  <div>视频监控设备:${
+                    deviceCount.monitorCount ? deviceCount.monitorCount : 0
+                  } </div>
+                  <div>消防预警设备:${
+                    deviceCount.fireCount ? deviceCount.fireCount : 0
+                  } </div>
+                  <div>环境监测设备:${
+                    deviceCount.environmentCount
+                      ? deviceCount.environmentCount
+                      : 0
+                  } </div>
+                  </div>`;
+                  } else {
+                    return param.data.name;
+                  }
                 },
               },
-            },
-            legend: [
-              {
-                selectedMode: true, //取消图例上的点击事件
+              itemStyle: {
+                color: "#ddb926",
               },
-            ],
-            series: [
-              {
-                map: "map",
-                type: "effectScatter",
-                // silent: true,
-                coordinateSystem: "geo",
-                // datasetIndex: 0,
-                // geoIndex: 0,
-                // selectedMode: false,
-                // focusNodeAdjacency: false,
-                // label: {
-                // 	show: true,
-                // 	width: 13,
-                // 	height: 15,
-                // 	fontSize: 0,
-                // 	color: "#1DF9FC",
-                // 	backgroundColor: {
-                // 		image: iconRQ
-                // 	},
-                // },
-                label: {
-                  formatter: (param) => {
-                    return param.name;
-                  },
-                  position: "top",
-                  fontSize: "10",
-                  color: "#fff",
-                  show: true,
-                },
-                tooltip: {
-                  show: false,
-                },
-                //  tooltip:{
-                //   position: "right",
-                //   textStyle:{
-                //     // color:'#fff',
-                //   },
-                //   // backgroundColor:'rgba(184,189,192,1)',
-                //   formatter:function(param){
-                //     return `<div >
-                //     <div> ${param.data.name} </div>
-                //     <div>履职总数:85 </div>
-                //     <div> 已完成:67 </div>
-                //     </div>`
-                //   }
-                // },
-                itemStyle: {
-                  color: "#ddb926",
-                },
-                symbol: this.icon, //自定义图标
-                symbolSize: [10, 10],
-                // encode: {
-                //   value: 2,
-                // },
-                // showEffectOn: "emphasis", //关闭涟漪
-                // hoverEffectOn: true,
-                rippleEffect: {
-                  brushType: "fill",
-                  period: 0,
-                  number: 0,
-                },
-                data: this.coordinates,
+              symbol: this.icon, //自定义图标
+              symbolSize: [10, 10],
+              // encode: {
+              //   value: 2,
+              // },
+              // showEffectOn: "emphasis", //关闭涟漪
+              // hoverEffectOn: true,
+              rippleEffect: {
+                brushType: "fill",
+                period: 0,
+                number: 0,
               },
-            ],
-          };
-          if (option && typeof option === "object") {
-            this.myChart.setOption(option);
-          }
-        });
-      },
-      windowResize() {
-        this.myChart && this.myChart.resize();
-      },
+              data: this.coordinates,
+            },
+          ],
+        };
+        if (option && typeof option === "object") {
+          this.myChart.setOption(option);
+        }
+      });
+    },
+    windowResize() {
+      this.myChart && this.myChart.resize();
     },
-  };
-  </script>
-  <style scoped src="./../css/index.css"></style>
-  <style lang="scss" scoped>
-  .content {
-    display: flex;
-  
-    margin-bottom: 20px;
-    margin-left: 5px;
-    margin-right: 5px;
-    border: solid 1px #b8bdc088;
-  
-    & > span {
-      margin-right: 10px;
-      padding-top: 5px;
-      padding-bottom: 5px;
-      height: 30px;
-      color: rgb(245, 245, 245);
-      font-size: 14px;
-    }
-  
-    & > span:first-child {
-      width: 100px;
-      background-color: #b8bdc088;
-      text-align: center;
-    }
+  },
+};
+</script>
+<style scoped src="./../css/index.css"></style>
+<style lang="scss" scoped>
+.content {
+  display: flex;
+
+  margin-bottom: 20px;
+  margin-left: 5px;
+  margin-right: 5px;
+  border: solid 1px #b8bdc088;
+
+  & > span {
+    margin-right: 10px;
+    padding-top: 5px;
+    padding-bottom: 5px;
+    height: 30px;
+    color: rgb(245, 245, 245);
+    font-size: 14px;
+  }
+
+  & > span:first-child {
+    width: 100px;
+    background-color: #b8bdc088;
+    text-align: center;
   }
-  </style>
-  
+}
+</style>

+ 481 - 478
src/views/iot/board/components/onlineAndHealth.vue

@@ -1,528 +1,531 @@
 <template>
-    <div class="component_box" style="display: flex;" @mouseenter="handleMouseEnter" @mouseleave="handleMouseLeave">
-        <div ref="chart" style="width: 50%; height: 100%; "></div>
-        <div class="health">
-            <header class="header">
-                <span>网点设备健康度检查</span>
-                <!-- <h3><span>网点数:100</span></h3> -->
-                <!-- <img src="img/end.png"></img> -->
-                <!-- <span>已检查:90</span> -->
-            </header>
-            <main class="banklet_main">
-                <!-- <img src="img/map.png" alt=""> -->
-                <div class="item_box">
-                    <span>网点数</span>
-                    <div>
-                        <i></i>
-                        <h2>{{ healthSummary.total }}</h2>
-                    </div>
-                </div>
-                <div class="item_box">
-                    <span>已检</span>
-
-                    <div>
-                        <i></i>
-                        <h2>{{ healthSummary.checkedCount }}</h2>
-                    </div>
-                </div>
-                <div class="item_box">
-                    <span>90分以上</span>
-                    <div>
-                        <i></i>
-                        <h2>{{ healthSummary.over90Count }}</h2>
-                    </div>
-                </div>
-                <div class="item_box">
-                    <span>90及以下</span>
-                    <div>
-                        <i></i>
-                        <h2>{{ healthSummary.notover90Count }}</h2>
-                    </div>
-                </div>
-            </main>
-
-            <header class="t_b_h_1">
-                <span>网点健康度检查TOP3</span>
-            </header>
-            <main class="t_b_m_1" style="top:70%">
-                <div v-for="(item, index) in healthRanking" :key="index">
-                    <i>
-                        <t>{{ index + 1 }}</t>
-                    </i> {{ item.orgName }} {{ parseFloat(item.score).toFixed(2) }}分
-                </div>
-            </main>
+  <div
+    class="component_box"
+    style="display: flex"
+    @mouseenter="handleMouseEnter"
+    @mouseleave="handleMouseLeave"
+  >
+    <div ref="chart" style="width: 50%; height: 100%"></div>
+    <div class="health">
+      <header class="header">
+        <span>网点设备健康度检查</span>
+        <!-- <h3><span>网点数:100</span></h3> -->
+        <!-- <img src="img/end.png"></img> -->
+        <!-- <span>已检查:90</span> -->
+      </header>
+      <main class="banklet_main">
+        <!-- <img src="img/map.png" alt=""> -->
+        <div class="item_box">
+          <span>网点数</span>
+          <div>
+            <i></i>
+            <h2>{{ healthSummary.total }}</h2>
+          </div>
         </div>
+        <div class="item_box">
+          <span>已检</span>
+          <div>
+            <i></i>
+            <h2>{{ healthSummary.checkedCount }}</h2>
+          </div>
+        </div>
+        <div class="item_box">
+          <span>90分以上</span>
+          <div>
+            <i></i>
+            <h2>{{ healthSummary.over90Count }}</h2>
+          </div>
+        </div>
+        <div class="item_box">
+          <span>90及以下</span>
+          <div>
+            <i></i>
+            <h2>{{ healthSummary.notover90Count }}</h2>
+          </div>
+        </div>
+      </main>
+
+      <header class="t_b_h_1">
+        <span>网点健康度检查TOP3</span>
+      </header>
+      <main class="t_b_m_1" style="top: 65%">
+        <div v-for="(item, index) in healthRanking" :key="index">
+          <i>
+            <span>{{ index + 1 }}</span>
+          </i>
+          {{ item.orgName }} {{ parseFloat(item.score).toFixed(2) }}分
+        </div>
+      </main>
     </div>
+  </div>
 </template>
 <script>
 import { deviceOnline, deviceHealth } from "@/api/iot/board";
-
+import * as echarts from "echarts";
 export default {
-    props: {
-        orgId: {
-            type: String,
-            isRequired: true,
-        },
+  props: {
+    orgId: {
+      type: String,
+      isRequired: true,
     },
-    data() {
-        return {
-            chartData: {
-                total: [],
-                onLineCount: [],
-                name: [],
-            },
-            healthSummary: {
-                total: 0,
-                checkedCount: 0,
-                over90Count: 0,
-                notover90Count: 0,
-            },
-            healthRanking: [],
-            isMouseOver: false
-        };
+  },
+  data() {
+    return {
+      chartData: {
+        total: [],
+        onLineCount: [],
+        onLineRate: [],
+        name: [],
+      },
+      healthSummary: {
+        total: 0,
+        checkedCount: 0,
+        over90Count: 0,
+        notover90Count: 0,
+      },
+      healthRanking: [],
+      isMouseOver: false,
+    };
+  },
+
+  components: {},
+
+  computed: {},
+
+  watch: {
+    orgId: {
+      deep: true,
+      handler(val) {
+        this.resetTimer();
+        this.getData();
+      },
     },
-
-    components: {},
-
-    computed: {},
-
-    watch: {
-        orgId: {
-            deep: true,
-            handler(val) {
-                this.resetTimer();
-                this.getData();
-            },
-        },
-        chartData: {
-            deep: true,
-            handler() {
-                this.initMap();
-            },
-        },
+    chartData: {
+      deep: true,
+      handler() {
+        this.initMap();
+      },
     },
-
-    created() {
-        this.refreshTime = 1 * 10 * 1000;
-        this.isMouseOver = false;
+  },
+
+  created() {
+    this.refreshTime = 1 * 60 * 1000;
+    this.isMouseOver = false;
+  },
+
+  async mounted() {
+    window.addEventListener("resize", this.windowResize);
+  },
+  beforeDestroy() {
+    this.timer && clearInterval(this.timer);
+    this.timer = null;
+
+    window.removeEventListener("resize", this.windowResize);
+  },
+
+  methods: {
+    handleMouseEnter() {
+      this.isMouseOver = true;
     },
-
-    async mounted() {
-        window.addEventListener("resize", this.windowResize);
+    handleMouseLeave() {
+      this.isMouseOver = false;
     },
-    beforeDestroy() {
-        this.timer && clearInterval(this.timer);
-        this.timer = null;
+    async getData() {
+      deviceOnline(this.orgId).then((r) => {
+        let data = r.data;
+        let chartData = {
+          total: [],
+          onLineCount: [],
+          onLineRate:[],
+          name: [],
+        };
 
-        window.removeEventListener("resize", this.windowResize);
+        for (let item of data) {
+          chartData.total.push(item.deviceCount);
+          chartData.onLineCount.push(item.onLineCount);
+          chartData.onLineRate.push((item.onLineRate * 100).toFixed(2));
+          chartData.name.push(item.deviceTypeName);
+        }
+        this.chartData = chartData;
+      });
+
+      deviceHealth(this.orgId).then((r) => {
+        this.healthSummary = r.data.healthSummary;
+        this.healthRanking = r.data.healthRanking;
+      });
     },
 
-    methods: {
-        handleMouseEnter() {
-            this.isMouseOver = true;
-        },
-        handleMouseLeave() {
-            this.isMouseOver = false;
+    windowResize() {
+      this.myChart && this.myChart.resize();
+    },
+    initMap() {
+      this.myChart && this.myChart.dispose();
+      
+      let c = this.$refs["chart"];
+      // console.info("online", this.chartData);
+      // 基于准备好的dom,初始化echarts实例
+      this.myChart = echarts.init(
+        c
+      );
+      
+      var myColor = ["#1089E7", "#F57474", "#56D0E3", "#F8B448"];
+      let option = {
+        title: {
+          text: "设备在线率",
+          x: "center",
+          textStyle: {
+            color: "#FFF",
+          },
+          left: "6%",
+          top: "10%",
         },
-        async getData() {
-            deviceOnline(this.orgId).then(r => {
-                let data = r.data;
-                let chartData = {
-                    total: [],
-                    onLineCount: [],
-                    name: [],
-                };
-
-                for (let item of data) {
-                    chartData.total.push(item.deviceCount);
-                    chartData.onLineCount.push(item.completedCount);
-                    // chartData.rate.push((item.completedRate * 100).toFixed(2));
-                    chartData.name.push(item.orgName);
-                }
-                this.chartData = chartData;
-            });
-
-            deviceHealth(this.orgId).then(r => {
-                this.healthSummary = r.data.healthSummary;
-                this.healthRanking = r.data.healthRanking
-            })
+        //图标位置
+        grid: {
+          top: "20%",
+          left: "25%",
+          bottom:'5%',
+          right:'15%'
         },
-
-        windowResize() {
-            this.myChart && this.myChart.resize();
+        xAxis: {
+          show: false,
         },
-        initMap() {
-            let c = this.$refs["chart"];
-
-            // 基于准备好的dom,初始化echarts实例
-            this.myChart = echarts.init(
-                c
-                // document.getElementById("commAlarmEvent_Chart")
-            );
-            // var data = [70, 34, 60, 78, 69];
-            // var titlename = [
-            //     "监控主机",
-            //     "报警主机",
-            //     "动环主机",
-            //     "对讲主机",
-            //     "门禁主机",
-            // ];
-            // var valdata = [702, 406, 664, 793, 505];
-            var myColor = ["#1089E7", "#F57474", "#56D0E3", "#F8B448"];
-            option = {
-                title: {
-                    text: "设备在线率",
-                    x: "center",
-                    textStyle: {
-                        color: "#FFF",
-                    },
-                    left: "6%",
-                    top: "10%",
-                },
-                //图标位置
-                grid: {
-                    top: "20%",
-                    left: "32%",
+        yAxis: [
+          {
+            show: true,
+            data: this.chartData.name,
+            inverse: true,
+            axisLine: {
+              show: false,
+            },
+            splitLine: {
+              show: false,
+            },
+            axisTick: {
+              show: false,
+            },
+            axisLabel: {
+              color: "#fff",
+              formatter: (value, index) => {
+                return [`{lg|${index + 1}}  ` + "{title|" + value + "} "].join(
+                  "\n"
+                );
+              },
+              rich: {
+                lg: {
+                  backgroundColor: "#339911",
+                  color: "#fff",
+                  borderRadius: 15,
+                  // padding: 5,
+                  align: "center",
+                  width: 15,
+                  height: 15,
                 },
-                xAxis: {
-                    show: false,
+              },
+            },
+          },
+          {
+            show: true,
+            inverse: true,
+            data: this.chartData.total,
+            axisLabel: {
+              textStyle: {
+                fontSize: 12,
+                color: "#fff",
+              },
+            },
+            axisLine: {
+              show: false,
+            },
+            splitLine: {
+              show: false,
+            },
+            axisTick: {
+              show: false,
+            },
+          },
+        ],
+        series: [
+          {
+            name: "条",
+            type: "bar",
+            yAxisIndex: 0,
+            data: this.chartData.onLineRate,
+            barWidth: 10,
+            itemStyle: {
+              normal: {
+                barBorderRadius: 20,
+                color: function (params) {
+                  var num = myColor.length;
+                  return myColor[params.dataIndex % num];
                 },
-                yAxis: [
-                    {
-                        show: true,
-                        data: this.chartData.name,
-                        inverse: true,
-                        axisLine: {
-                            show: false,
-                        },
-                        splitLine: {
-                            show: false,
-                        },
-                        axisTick: {
-                            show: false,
-                        },
-                        axisLabel: {
-                            color: "#fff",
-                            formatter: (value, index) => {
-                                return [`{lg|${index + 1}}  ` + "{title|" + value + "} "].join(
-                                    "\n"
-                                );
-                            },
-                            rich: {
-                                lg: {
-                                    backgroundColor: "#339911",
-                                    color: "#fff",
-                                    borderRadius: 15,
-                                    // padding: 5,
-                                    align: "center",
-                                    width: 15,
-                                    height: 15,
-                                },
-                            },
-                        },
-                    },
-                    {
-                        show: true,
-                        inverse: true,
-                        data: this.chartData.total,
-                        axisLabel: {
-                            textStyle: {
-                                fontSize: 12,
-                                color: "#fff",
-                            },
-                        },
-                        axisLine: {
-                            show: false,
-                        },
-                        splitLine: {
-                            show: false,
-                        },
-                        axisTick: {
-                            show: false,
-                        },
-                    },
-                ],
-                series: [
-                    {
-                        name: "条",
-                        type: "bar",
-                        yAxisIndex: 0,
-                        data: this.chartData.onLineCount,
-                        barWidth: 10,
-                        itemStyle: {
-                            normal: {
-                                barBorderRadius: 20,
-                                color: function (params) {
-                                    var num = myColor.length;
-                                    return myColor[params.dataIndex % num];
-                                },
-                            },
-                        },
-                        label: {
-                            normal: {
-                                show: true,
-                                position: "inside",
-                                formatter: "{c}%",
-                            },
-                        },
-                    },
-                    {
-                        name: "框",
-                        type: "bar",
-                        yAxisIndex: 1,
-                        barGap: "-100%",
-                        data: [100, 100, 100, 100, 100],
-                        barWidth: 15,
-                        itemStyle: {
-                            normal: {
-                                color: "none",
-                                borderColor: "#00c1de",
-                                borderWidth: 3,
-                                barBorderRadius: 15,
-                            },
-                        },
-                    },
-                ],
-            };
-            // 使用刚指定的配置项和数据显示图表。
-            this.myChart.setOption(option);
-        },
+              },
+            },
+            label: {
+              normal: {
+                color: "#fff",
+                show: true,
+                position: ['40%','0%'],
+                formatter: "{c}%",
+              },
+            },
+          },
+          {
+            name: "框",
+            type: "bar",
+            yAxisIndex: 1,
+            barGap: "-100%",
+            data: [100, 100, 100, 100, 100],
+            barWidth: 15,
+            itemStyle: {
+              normal: {
+                color: "none",
+                borderColor: "#00c1de",
+                borderWidth: 3,
+                barBorderRadius: 15,
+              },
+            },
+          },
+        ],
+      };
+      // 使用刚指定的配置项和数据显示图表。
+      this.myChart.setOption(option);
+    },
 
-        resetTimer() {
-            this.timer && clearInterval(this.timer);
-            this.timer = setInterval(() => {
-                if (this.isMouseOver) {
-                    return;
-                }
-                this.getData();
-            }, this.refreshTime);
-        },
+    resetTimer() {
+      this.timer && clearInterval(this.timer);
+      this.timer = setInterval(() => {
+        if (this.isMouseOver) {
+          return;
+        }
+        this.getData();
+      }, this.refreshTime);
     },
+  },
 };
 </script>
 <style scoped src="./../css/index.css"></style>
 <style lang="scss" scoped>
 .health {
-    width: 50%;
-    height: 100%;
-    display: flex;
-    flex-direction: column;
-    padding: 0 3%;
-
-    ::v-deep .header {
-        color: #fff;
-        width: 100%;
-        height: 12%;
-        font-size: 20px;
-    }
-
-    ::v-deep .banklet_main {
-        height: 40%;
-        width: 100%;
-    }
-
-    ::v-deep .item_box {
-        border: 1px dotted #f0ff00;
-        border-radius: 5px;
-        margin-top: 5%;
-        height: 45%;
-        width: 45%;
-        float: left;
-        display: flex;
-        flex-direction: column;
-        font-size: 14px;
-    }
-
-
-    ::v-deep .item_box:nth-child(even) {
-        margin-left: 10%;
-    }
-
-    ::v-deep .item_box>span:first-child {
-        line-height: 20px;
-    }
-
-    ::v-deep .item_box>div:last-child {
-        // display: block;
-        width: 100%;
-        height: calc(100% - 20px);
-        display: flex;
-        align-items: center;
-        justify-content: center;
-        position: relative;
-    }
-
-    ::v-deep .item_box>div:last-child>i {
-        width: 16px;
-        height: 16px;
-        display: inline-block;
-        position: absolute;
-        left: 20%;
-    }
-
-    ::v-deep .item_box:first-child>div:last-child>i {
-        background: url("../img/t.png") no-repeat;
-        background-size: 100% 100%;
-    }
-
-    ::v-deep .item_box:nth-child(2)>div:last-child>i {
-        background: url("../img/s.png") no-repeat;
-        background-size: 100% 100%;
-    }
-
-    ::v-deep .item_box:nth-child(3)>div:last-child>i {
-        background: url("../img/j.png") no-repeat;
-        background-size: 100% 100%;
-    }
-
-    ::v-deep .item_box:nth-child(4)>div:last-child>i {
-        background: url("../img/g.png") no-repeat;
-        background-size: 100% 100%;
-    }
-}
+  width: 50%;
+  height: 100%;
+  display: flex;
+  flex-direction: column;
+  padding: 0 3%;
 
-.t_b_m img {
-    position: absolute;
-    left: 52%;
-    top: 22%;
-    border-top: 1px dotted #f0ff00;
-    padding: 0 0.18rem;
-    padding-top: 20px;
-    width: 3.19rem;
-    height: 1.67rem;
-}
-
-.t_b_h_1 {
-    position: absolute;
-    font-size: 0.16rem;
-    left: 54%;
-    width: 50%;
-    height: 2.1rem;
-    top: 60%;
-}
-
-.t_b_h_1 span {
-    position: absolute;
+  ::v-deep .header {
     color: #fff;
-    top: 10%;
-    font-size: 20px;
-}
-
-.t_b_h_1 img {
-    position: absolute;
-    width: 0.53rem;
-    height: 0.53rem;
-    top: 6%;
-    left: 24%;
-}
-
-.t_b_h_1 h3 {
-    font-size: 0.36rem;
-    color: #f0ff00;
-    position: absolute;
-    left: 55%;
-    top: 8%;
-    width: 1rem;
-}
-
-.t_b_h_1 h3 span {
-    font-size: 0.2rem;
-    position: absolute;
-    left: 50%;
-    top: 28%;
-    color: #0072ff;
-}
-
-.t_b_m_1 {
-    position: absolute;
-    font-size: 0.16rem;
-    left: 54%;
-    width: 50%;
-    height: 2.1rem;
-    top: 70%;
-}
-
-.t_b_m_1 div {
-    margin-top: 15px;
-    height: 20px;
-    color: white;
+    width: 100%;
+    height: 12%;
+    font-size: 16px;
+    font-weight: 700;
+  }
+
+  ::v-deep .banklet_main {
+    height: 40%;
+    width: 100%;
+  }
+
+  ::v-deep .item_box {
+    border: 1px dotted #f0ff00;
+    border-radius: 5px;
+    margin-top: 5%;
+    height: 45%;
+    width: 45%;
+    float: left;
+    display: flex;
+    flex-direction: column;
     font-size: 14px;
-}
+  }
 
-.t_b_m_1 div>i {
-    background-color: #339911;
-    font-family: 仿宋体;
-    width: 19px;
-    display: inline-block;
-    border-radius: 9.5px;
-}
+  ::v-deep .item_box:nth-child(even) {
+    margin-left: 10%;
+  }
 
-.t_b_m_1 div>i>t {
-    left: 3px;
-    position: relative;
-}
+  ::v-deep .item_box > span:first-child {
+    line-height: 20px;
+    margin-left: 8%;
+  }
 
-.t_b_box,
-.t_b_box1,
-.t_b_box2,
-.t_b_box3 {
-    width: 35%;
-    height: 10%;
+  ::v-deep .item_box > div:last-child {
+    // display: block;
+    width: 100%;
+    height: calc(100% - 20px);
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    position: relative;
+  }
 
+  ::v-deep .item_box > div:last-child > i {
+    width: 16px;
+    height: 16px;
+    display: inline-block;
     position: absolute;
+    left: 20%;
+  }
+
+  ::v-deep .item_box:first-child > div:last-child > i {
+    background: url("../img/t.png") no-repeat;
+    background-size: 100% 100%;
+  }
+
+  ::v-deep .item_box:nth-child(2) > div:last-child > i {
+    background: url("../img/s.png") no-repeat;
+    background-size: 100% 100%;
+  }
+
+  ::v-deep .item_box:nth-child(3) > div:last-child > i {
+    background: url("../img/j.png") no-repeat;
+    background-size: 100% 100%;
+  }
+
+  ::v-deep .item_box:nth-child(4) > div:last-child > i {
+    background: url("../img/g.png") no-repeat;
+    background-size: 100% 100%;
+  }
 }
 
-.t_b_box {
-    top: 25%;
-    left: 56%;
-}
+// .t_b_m img {
+//   position: absolute;
+//   left: 52%;
+//   top: 22%;
+//   border-top: 1px dotted #f0ff00;
+//   padding: 0 0.18rem;
+//   padding-top: 20px;
+//   width: 3.19rem;
+//   height: 1.67rem;
+// }
 
-.t_b_box span,
-.t_b_box1 span,
-.t_b_box2 span,
-.t_b_box3 span {
-    font-size: 0.14rem;
-    color: #fff;
-    position: absolute;
-    left: 10%;
+.t_b_h_1 {
+  position: absolute;
+  font-size: 0.16rem;
+  left: 54%;
+  width: 50%;
+  height: 2.1rem;
+  top: 60%;
 }
 
-.t_b_box i,
-.t_b_box1 i,
-.t_b_box2 i,
-.t_b_box3 i {
-    width: 20px;
-    height: 20px;
-    position: absolute;
-    top: 50%;
-    left: 15%;
+.t_b_h_1 span {
+  position: absolute;
+  color: #fff;
+  top: 10%;
+  font-size: 20px;
 }
 
+// .t_b_h_1 img {
+//   position: absolute;
+//   width: 0.53rem;
+//   height: 0.53rem;
+//   top: 6%;
+//   left: 24%;
+// }
+
+// .t_b_h_1 h3 {
+//   font-size: 0.36rem;
+//   color: #f0ff00;
+//   position: absolute;
+//   left: 55%;
+//   top: 8%;
+//   width: 1rem;
+// }
+
+// .t_b_h_1 h3 span {
+//   font-size: 0.2rem;
+//   position: absolute;
+//   left: 50%;
+//   top: 28%;
+//   color: #0072ff;
+// }
 
-
-.t_b_box h2,
-.t_b_box1 h2,
-.t_b_box2 h2,
-.t_b_box3 h2 {
-    font-size: 0.18rem;
-    color: #fff;
-    position: absolute;
-    top: 30%;
-    left: 40%;
+.t_b_m_1 {
+  position: absolute;
+  font-size: 0.16rem;
+  left: 54%;
+  width: 50%;
+  height: 2.1rem;
+  top: 70%;
 }
 
-.t_b_box1 {
-    top: 25%;
-    left: 78%;
+.t_b_m_1 div {
+  margin-top: 15px;
+  height: 20px;
+  color: white;
+  font-size: 14px;
 }
 
-.t_b_box2 {
-    top: 45%;
-    left: 56%;
+.t_b_m_1 div > i {
+  background-color: #339911;
+  //   font-family: 仿宋体;
+  width: 19px;
+  display: inline-block;
+  border-radius: 9.5px;
 }
 
-.t_b_box3 {
-    top: 45%;
-    left: 78%;
+.t_b_m_1 div > i > span {
+  //   left: 3px;
+  margin-left: calc(50% - 5px);
+  //   position: relative;
 }
-</style>
+
+// .t_b_box,
+// .t_b_box1,
+// .t_b_box2,
+// .t_b_box3 {
+//   width: 35%;
+//   height: 10%;
+
+//   position: absolute;
+// }
+
+// .t_b_box {
+//   top: 25%;
+//   left: 56%;
+// }
+
+// .t_b_box span,
+// .t_b_box1 span,
+// .t_b_box2 span,
+// .t_b_box3 span {
+//   font-size: 0.14rem;
+//   color: #fff;
+//   position: absolute;
+//   left: 10%;
+// }
+
+// .t_b_box i,
+// .t_b_box1 i,
+// .t_b_box2 i,
+// .t_b_box3 i {
+//   width: 20px;
+//   height: 20px;
+//   position: absolute;
+//   top: 50%;
+//   left: 15%;
+// }
+
+// .t_b_box h2,
+// .t_b_box1 h2,
+// .t_b_box2 h2,
+// .t_b_box3 h2 {
+//   font-size: 0.18rem;
+//   color: #fff;
+//   position: absolute;
+//   top: 30%;
+//   left: 40%;
+// }
+
+// .t_b_box1 {
+//   top: 25%;
+//   left: 78%;
+// }
+
+// .t_b_box2 {
+//   top: 45%;
+//   left: 56%;
+// }
+
+// .t_b_box3 {
+//   top: 45%;
+//   left: 78%;
+// }
+</style>

+ 3 - 3
src/views/iot/board/components/protection.vue

@@ -19,7 +19,7 @@
     </div>
 </template>
 <script>
-import { protectionCount } from '@/api/iot/board'
+import { protectionInfo } from '@/api/iot/board'
 export default {
     data() {
         return {
@@ -46,12 +46,12 @@ export default {
         }
     },
     created() {
-        this.refreshTime = 1 * 10 * 1000;
+        this.refreshTime = 10 * 60 * 1000;
         this.isMouseOver = false;
     },
     methods: {
         getData() {
-            protectionCount(this.orgId).then(r => {
+            protectionInfo(this.orgId).then(r => {
                 this.info = r.data;
             })
         },

+ 6 - 1
src/views/iot/board/css/index.css

@@ -15,6 +15,7 @@
     height: 80px;
     background: url("../img/linx.png") no-repeat;
     background-size: 100% 100%;
+    position: relative;
 }
 
 .t_header_title{
@@ -24,6 +25,7 @@
     display: flex;
     align-items: center;
     justify-content: center;
+    
 
 }
 
@@ -42,7 +44,6 @@
     width: 100%;
     height: 50%;
     display: flex;
-    border:solid 1px #fff;
 }
 
 .t_left_box {
@@ -51,6 +52,10 @@
     /* display: inline-block; */
     /* text-align: center; */
 }
+
+.t_left_box>div{
+    height: 100%;
+}
 .t_l_line {
     position: relative;
     top: 0;

+ 215 - 52
src/views/iot/board/index.vue

@@ -1,63 +1,226 @@
 <template>
-    <div class="body">
-        <header class="t_header">
-            <div class="t_header_title">
-                <span>物联监测看板</span>
+  <div class="body" ref="board">
+    <header class="t_header">
+      <div class="t_header_title">
+        <span>物联监测看板</span>
+      </div>
+      <span style="position:absolute;right:10px;top:10px;">
+          <i v-if="!fullScreen" class="el-icon-full-screen" @click="onChangeFullScreen(true)"></i>
+          <i v-else class="el-icon-copy-document" @click="onChangeFullScreen(false)"></i>
+        </span>
+    </header>
+    <main class="t_main">
+      <div>
+        <layout :className="'t_left_box'">
+          <div>
+            <el-cascader
+              :options="orgOptions"
+              v-model="orgCascaderSelectedIds"
+              :props="{ checkStrictly: true, value: 'id', label: 'shortName' }"
+              :show-all-levels="false"
+              class="org-cascader"
+              popper-class="board-org-popper"
+              @change="handOrgChange"
+              ref="orgCascader"
+            ></el-cascader>
+            <div style="height: calc(100% - 50px)">
+              <deviceCount :orgId="selectedOrg.id"></deviceCount>
             </div>
-        </header>
-        <main class="t_main">
-            <div>
-                <layout :className="'t_left_box'">
-                    <deviceCount :orgId="orgId"></deviceCount>
-                </layout>
-                <div class="t_center_box">
-                    <layout :className="'t_top_box'" style="padding-bottom: 0px;">
-                        <protection />
-                    </layout>
-                    <layout :className="'t_bottom_box'" style="padding-top:0px">
-                        <device-map />
-                    </layout>
-                </div>
-                <layout :className="'t_right_box'">
-                    <online-and-health></online-and-health>
-                </layout>
-            </div>
-            <div>
-                <layout :className="'b_left_box'">
-                    <alarm-trend />
-                </layout>
-                <layout :className="'b_center_box'">
-                    <alarm-rate></alarm-rate>
-                </layout>
-                <layout :className="'b_right_box'">
-                    <alarm-list></alarm-list>
-                </layout>
-            </div>
-        </main>
-    </div>
+          </div>
+        </layout>
+        <div class="t_center_box">
+          <layout :className="'t_top_box'" style="padding-bottom: 0px">
+            <protection :orgId="selectedOrg.id" />
+          </layout>
+          <layout :className="'t_bottom_box'" style="padding-top: 0px">
+            <device-map :orgId="selectedOrg.id" />
+          </layout>
+        </div>
+        <layout :className="'t_right_box'">
+          <online-and-health :orgId="selectedOrg.id"></online-and-health>
+        </layout>
+      </div>
+      <div>
+        <layout :className="'b_left_box'">
+          <alarm-trend :orgId="selectedOrg.id" />
+        </layout>
+        <layout :className="'b_center_box'">
+          <alarm-rate :orgId="selectedOrg.id"></alarm-rate>
+        </layout>
+        <layout :className="'b_right_box'">
+          <alarm-list :orgId="selectedOrg.id"></alarm-list>
+        </layout>
+      </div>
+    </main>
+  </div>
 </template>
 <script>
 import { mapGetters } from "vuex";
-import layout from './components/layout.vue';
-import deviceCount from './components/deviceCount.vue';
-import protection from './components/protection.vue';
-import deviceMap from './components/deviceMap.vue';
-import onlineAndHealth from './components/onlineAndHealth.vue';
-import alarmTrend from './components/alarmTrend.vue';
-import alarmRate from './components/alarmRate.vue';
-import alarmList from './components/alarmList.vue';
+import layout from "./components/layout.vue";
+import deviceCount from "./components/deviceCount.vue";
+import protection from "./components/protection.vue";
+import deviceMap from "./components/deviceMap.vue";
+import onlineAndHealth from "./components/onlineAndHealth.vue";
+import alarmTrend from "./components/alarmTrend.vue";
+import alarmRate from "./components/alarmRate.vue";
+import alarmList from "./components/alarmList.vue";
 
 export default {
-    name: "iot_board",
-    components: { layout, deviceCount, protection, deviceMap, onlineAndHealth, alarmTrend, alarmRate, alarmList },
-    computed: {
-        ...mapGetters(["orgId", "depTree", "orgName",]),
+  name: "iot_board",
+  components: {
+    layout,
+    deviceCount,
+    protection,
+    deviceMap,
+    onlineAndHealth,
+    alarmTrend,
+    alarmRate,
+    alarmList,
+  },
+  computed: {
+    ...mapGetters(["orgId", "depTree", "orgName"]),
+    orgOptions() {
+      let deps = this.depTree;
+      let recursion = (deps) => {
+        for (let index in deps) {
+          let dep = deps[index];
+          if (!dep.children) {
+            continue;
+          }
+          if (dep.children.length === 0) {
+            delete dep.children;
+            continue;
+          }
+
+          recursion(dep.children);
+        }
+      };
+      recursion(deps);
+      this.$nextTick(() => {
+        if (deps.length > 0) {
+          this.selectedOrg = {
+            id: deps[0].id,
+            name: deps[0].shortName,
+          };
+          this.orgCascaderSelectedIds = [deps[0].id];
+        }
+      });
+      // console.info(deps);
+      return deps;
+    },
+  },
+  data() {
+    return {
+      orgTree: [], //分行下拉列表
+      selectedOrg: {
+        id: null,
+        name: null,
+      },
+      orgCascaderSelectedIds: [],
+      fullScreen: false,
+    };
+  },
+  mounted() {
+    this.selectedOrg = {
+      id: this.orgId,
+      name: this.orgName,
+    };
+  },
+  methods: {
+    handOrgChange(id, m, n) {
+      let checked = this.$refs["orgCascader"].getCheckedNodes(true);
+      if (!checked || checked.length === 0) {
+        return;
+      }
+
+      this.selectedOrg = {
+        id: checked[0].data.id,
+        name: checked[0].data.shortName,
+      };
     },
-    data() {
-        return {
-            orgId: this.orgId,
+    onChangeFullScreen(fullScreen) {
+      let dom = this.$refs["board"];
+      if (fullScreen) {
+        if (document.fullscreenEnabled) {
+          if (dom.requestFullscreen) {
+            dom.requestFullscreen();
+          } else if (dom.mozRequestFullScreen) {
+            dom.mozRequestFullScreen();
+          } else if (dom.webkitRequestFullScreen) {
+            dom.webkitRequestFullScreen();
+          } else if (dom.msRequestFullScreen) {
+            dom.msRequestFullScreen();
+          }
+        }
+      } else {
+        // if (!document.fullscreenEnabled) {
+        if (document.exitFullscreen) {
+          document.exitFullscreen();
+        } else if (document.mozCancelFullScreen) {
+          document.mozCancelFullScreen();
+        } else if (document.webkitCancelFullScreen) {
+          document.webkitCancelFullScreen();
+        } else if (document.msExitFullScreen) {
+          document.msExitFullScreen();
         }
+        // }
+      }
+      this.fullScreen = fullScreen;
+    },
+  },
+};
+</script>
+<style scoped src="./css/index.css"></style>
+<style lang="scss" scoped>
+.body {
+  ::v-deep .el-tabs__nav-wrap::after {
+    height: 1 !important;
+    background-color: #424040;
+  }
+
+  ::v-deep .el-tabs__item {
+    color: #8e949c;
+    padding: 0 5px;
+    font-size: 12px;
+    background-color: transparent;
+    display: inline-block;
+    &:hover {
+      color: #ffffff;
     }
+  }
+
+  ::v-deep .el-tabs {
+    .is-active {
+      color: #ffffff;
+    }
+
+    .el-tabs__header {
+      margin: 0 0 8px;
+    }
+
+    .el-tabs__active-bar {
+      background-color: #2754dd;
+    }
+
+    .el-tabs__nav-scroll {
+      display: flex;
+      justify-content: center;
+    }
+  }
 }
-</script>
-<style scoped src="./css/index.css"></style>
+
+.org-cascader {
+  margin-top: 0px;
+  width: 100%;
+  line-height: 50px;
+
+  ::v-deep .el-input__inner {
+    background-color: transparent !important;
+    border: none !important;
+    color: #ffffff;
+    font-size: 16px;
+    font-weight: 700;
+    text-align: center;
+  }
+}
+</style>