yanglzh 10 hónapja
szülő
commit
791dc968fd
3 módosított fájl, 338 hozzáadás és 48 törlés
  1. 9 1
      src/api/alarm/index.ts
  2. 75 2
      src/utils/dataUiOptions.ts
  3. 254 45
      src/views/iot/alarm/dashboard/index.vue

+ 9 - 1
src/api/alarm/index.ts

@@ -25,12 +25,20 @@ export default {
   dashboard: {
     getDeviceAlarmTop10: () => get("/alarm/log/getDeviceAlarmTop10"),
     // 部门告警统计
-    getDeptAlarm: () => get("/alarm/log/getDeptAlarm"),
+    getDeptAlarm: (params: object) => get("/alarm/log/getDeptAlarm", params),
     // 今日告警信息
     getCurrentDayInfo: () => get("/alarm/log/getCurrentDayInfo"),
     // 最新告警
     getAlarmNewList: () => get("/alarm/log/getAlarmNewList"),
     // 告警统计
     getAlarmStatistics: (params: object) => get("/alarm/log/getAlarmStatistics", params),
+    // 告警趋势统计
+    getAnalyzeTrend: (params: object) => get("/alarm/log/getAnalyzeTrend", params),
+    // 告警状态统计
+    getAlarmStatus: (params: object) => get("/alarm/log/getAlarmStatus", params),
+    // 告警类型统计
+    getAlarmType: (params: object) => get("/alarm/log/getAlarmType", params),
+    // 告警等级统计
+    getAlarmLevel: (params: object) => get("/alarm/log/getAlarmLevel", params),
   },
 };

+ 75 - 2
src/utils/dataUiOptions.ts

@@ -298,12 +298,13 @@ export function getLine2Data({ xAxis = [] as any[], datas = [] as number[][], le
   return { config, dataset }
 }
 
-export function getPieData({ datas = [] as number[][], legend = [] as string[], types = [] as number[], width = 500, height = 1300 }) {
+export function getPieData({ datas = [] as number[][], legend = [] as string[], types = [] as number[], width = 500, height = 1300, responsive = false }) {
 
   const colorList = ['#4285F4', '#2ecc71', '#FBBB04', '#e67e22', '#FF0000'].reverse()
 
   const config = {
     theme: getTheme(),
+    "responsive": responsive,
     "backgroundColor": "transparent",
     style: {
       "backgroundColor": "transparent",
@@ -336,7 +337,7 @@ export function getPieData({ datas = [] as number[][], legend = [] as string[],
             value: { rounding: 0, show: true, formatter: null },
             percentage: {
               bold: true,
-              fontSize: 18,
+              fontSize: 14,
               rounding: 0,
               formatter: null,
             },
@@ -371,6 +372,78 @@ export function getPieData({ datas = [] as number[][], legend = [] as string[],
   return { config, dataset }
 }
 
+export function getPieSmallData({ datas = [] as number[][], legend = [] as string[], colorList = ['#4285F4', '#2ecc71', '#FBBB04', '#e67e22', '#FF0000'].reverse() as string[], width = 500, height = 1300, responsive = false }) {
+
+  const config = {
+    theme: getTheme(),
+    "responsive": responsive,
+    "backgroundColor": "transparent",
+    style: {
+      "backgroundColor": "transparent",
+      chart: {
+        "fontFamily": "inherit",
+        "paddingTop": 0,
+        "backgroundColor": "transparent",
+        height,
+        width,
+        "padding": {
+          "top": 0,
+          "right": 0,
+          "bottom": 0,
+          "left": 0
+        },
+        "title": {
+          "text": " ",
+          "show": false,
+        },
+        "legend": {
+          "show": true,
+          "bold": false,
+          "backgroundColor": "transparent",
+          "fontSize": 14,
+          "roundingValue": 0,
+          "roundingPercentage": 0
+        },
+        "layout": {
+          "labels": {
+            value: { rounding: 0, show: true, formatter: null },
+            percentage: {
+              bold: true,
+              fontSize: 14,
+              rounding: 0,
+              formatter: null,
+            },
+            name: { bold: false, fontSize: 14 },
+            "hollow": {
+              "total": {
+                "fontSize": 18,
+                "text": "总计",
+                "value": {
+                  "fontSize": 18,
+                }
+              },
+              "average": {
+                "show": false,
+              },
+            },
+          },
+        },
+      },
+    },
+    "userOptions": {
+      "show": false
+    },
+  }
+
+  // const dataset = [{ "name": "Series 1", "values": [100] }, { "name": "Series 2", "values": [50] }, { "name": "Series 3", "values": [25] }, { "name": "Series 4", "values": [12.5] }]
+
+  const dataset = datas.map((data, i) => {
+    return { "name": legend[i], "values": data, color: colorList[i] }
+  })
+
+  return { config, dataset }
+}
+
 export function getGaugeData({ value = 50 }) {
 
   const config = {

+ 254 - 45
src/views/iot/alarm/dashboard/index.vue

@@ -53,36 +53,103 @@
             range-separator="至"
             start-placeholder="开始日期"
             end-placeholder="结束日期"
-            :default-value="[defaultStartDate, defaultEndDate]"
-            @change="handleDateChange"
+            @change="getAlarmStatistics"
             size="small"
-            style="margin-left: 10px; width: 240px"
+            style="max-width: 200px"
+            :clearable="false"
           />
         </div>
         <VueUiXy v-if="dataset4?.length" :config="config4" :dataset="dataset4" />
         <VueUiSkeleton v-else :config="{ type: 'bar' }" />
       </el-card>
       <el-card shadow="nover">
-        <div class="title">告警增长趋势</div>
-        <VueUiSkeleton :config="{ type: 'bar' }" />
+        <div class="title">
+          告警增长趋势
+          <el-date-picker
+            v-model="analyzeTrendDate"
+            type="month"
+            @change="getAnalyzeTrend"
+            size="small"
+            style="max-width: 100px"
+            :clearable="false"
+          />
+        </div>
+        <VueUiDonut v-if="dataset5?.length" :config="config5" :dataset="dataset5" />
+        <VueUiSkeleton v-else :config="{ type: 'donut' }" />
       </el-card>
       <el-card shadow="nover">
-        <div class="title">部门告警分析</div>
-        <VueUiSkeleton :config="{ type: 'bar' }" />
+        <div class="title">
+          部门告警分析
+          <el-date-picker
+            v-model="deptAlarmDate"
+            type="daterange"
+            range-separator="至"
+            start-placeholder="开始日期"
+            end-placeholder="结束日期"
+            @change="getDeptAlarm"
+            size="small"
+            style="max-width: 200px"
+            :clearable="false"
+          />
+        </div>
+        <VueUiXy v-if="dataset6?.length" :config="config6" :dataset="dataset6" />
+        <VueUiSkeleton v-else :config="{ type: 'bar' }" />
       </el-card>
     </div>
     <div class="flex-row" style="gap: 12px">
       <el-card shadow="nover">
-        <div class="title">告警状态</div>
-        <VueUiSkeleton :config="{ type: 'bar' }" />
+        <div class="title">
+          告警状态
+          <el-date-picker
+            v-model="alarmStatusDate"
+            type="daterange"
+            range-separator="至"
+            start-placeholder="开始日期"
+            end-placeholder="结束日期"
+            @change="getAlarmStatus"
+            size="small"
+            style="max-width: 200px"
+            :clearable="false"
+          />
+        </div>
+        <VueUiXy v-if="dataset7?.length" :config="config7" :dataset="dataset7" />
+        <VueUiSkeleton v-else :config="{ type: 'bar' }" />
       </el-card>
       <el-card shadow="nover">
-        <div class="title">告警等级</div>
-        <VueUiSkeleton :config="{ type: 'bar' }" />
+        <div class="title">
+          告警等级
+          <el-date-picker
+            v-model="alarmLevelDate"
+            type="daterange"
+            range-separator="至"
+            start-placeholder="开始日期"
+            end-placeholder="结束日期"
+            @change="getAlarmLevel"
+            size="small"
+            style="max-width: 200px"
+            :clearable="false"
+          />
+        </div>
+        <VueUiXy v-if="dataset9?.length" :config="config9" :dataset="dataset9" />
+        <VueUiSkeleton v-else :config="{ type: 'bar' }" />
       </el-card>
       <el-card shadow="nover">
-        <div class="title">告警类型</div>
-        <VueUiSkeleton :config="{ type: 'bar' }" />
+        <div class="title">
+          告警类型
+          <el-date-picker
+            v-model="alarmTypeDate"
+            type="daterange"
+            range-separator="至"
+            start-placeholder="开始日期"
+            end-placeholder="结束日期"
+            @change="getAlarmType"
+            size="small"
+            style="max-width: 200px"
+            :clearable="false"
+          />
+        </div>
+        <VueUiXy v-if="dataset8?.length" :config="config8" :dataset="dataset8" />
+        <VueUiSkeleton v-else :config="{ type: 'bar' }" />
       </el-card>
     </div>
   </div>
@@ -92,7 +159,12 @@
 import { unref, reactive, getCurrentInstance, ref } from "vue";
 import { VueUiXy, VueUiDonut, VueUiSkeleton } from "vue-data-ui";
 import "vue-data-ui/style.css";
-import { getBarData, getLineData, getPieData } from "/@/utils/dataUiOptions";
+import {
+  getBarData,
+  getLineData,
+  getPieData,
+  getPieSmallData,
+} from "/@/utils/dataUiOptions";
 import api from "/@/api/alarm";
 import { useThemeChange } from "/@/hooks/useCommon";
 import dayjs from "dayjs";
@@ -104,38 +176,24 @@ function typeFormat(type: string) {
   return proxy.selectDictLabel(unref(alarm_type), type);
 }
 
-//#region 线图
-
-// 获取默认图形配置数据
-const chartData = getLineData({
-  xAxis: [],
-  legend: [" "],
-  datas: [[]],
-  responsive: true,
-});
-
 const config = ref<any>({});
 const config2 = ref<any>({});
 const config4 = ref<any>({});
-const dataset = ref<any[]>([]);
+const config5 = ref<any>({});
+const config6 = ref<any>({});
+const config7 = ref<any>({});
+const config8 = ref<any>({});
+const config9 = ref<any>({});
 const dataset2 = ref<any[]>([]);
 const dataset4 = ref<any[]>([]);
-
-//#endregion
-
-//#region 饼图
-
-// 获取默认图形配置数据
-const pieData = getPieData({
-  legend: [" "],
-  datas: [[]],
-});
-
-const pieConfig = ref<any>(pieData.config);
-const pieDataset = ref<any[]>(pieData.dataset);
+const dataset5 = ref<any[]>([]);
+const dataset6 = ref<any[]>([]);
+const dataset7 = ref<any[]>([]);
+const dataset8 = ref<any[]>([]);
+const dataset9 = ref<any[]>([]);
 
 // 监听暗黑模式变化,将 vue-data-ui 的 config 传进来,就能自动更新主题
-useThemeChange([config, pieConfig]);
+useThemeChange([config, config2, config4, config5, config6, config7, config8, config9]);
 
 const todayCount = reactive({
   currentDayCount: "-",
@@ -147,10 +205,23 @@ const alarmNewList = ref<any[]>([]);
 const defaultStartDate = dayjs().subtract(7, "day").toDate();
 const defaultEndDate = dayjs().toDate();
 const dateRange = ref([defaultStartDate, defaultEndDate]);
-
-const handleDateChange = () => {
-  getAlarmStatistics();
-};
+const analyzeTrendDate = ref(dayjs().format("YYYY-MM"));
+const deptAlarmDate = ref([
+  dayjs().subtract(7, "day").format("YYYY-MM-DD"),
+  dayjs().format("YYYY-MM-DD"),
+]);
+const alarmStatusDate = ref([
+  dayjs().subtract(7, "day").format("YYYY-MM-DD"),
+  dayjs().format("YYYY-MM-DD"),
+]);
+const alarmTypeDate = ref([
+  dayjs().subtract(7, "day").format("YYYY-MM-DD"),
+  dayjs().format("YYYY-MM-DD"),
+]);
+const alarmLevelDate = ref([
+  dayjs().subtract(7, "day").format("YYYY-MM-DD"),
+  dayjs().format("YYYY-MM-DD"),
+]);
 
 getData();
 
@@ -171,6 +242,16 @@ function getData() {
   });
   // 告警统计
   getAlarmStatistics();
+  // 告警趋势统计
+  getAnalyzeTrend();
+  // 部门告警统计
+  getDeptAlarm();
+  // 告警状态统计
+  getAlarmStatus();
+  // 告警类型统计
+  getAlarmType();
+  // 告警等级统计
+  getAlarmLevel();
   // 告警设备top10
   api.dashboard.getDeviceAlarmTop10().then((res: any) => {
     const list = res || [];
@@ -194,7 +275,6 @@ function getAlarmStatistics() {
       endDate: dayjs(dateRange.value[1]).format("YYYY-MM-DD"),
     })
     .then((res: any) => {
-      console.log(res);
       const list = res || [];
       const chartData = getBarData({
         xAxis: list.map((item: any) => item.alarmDate),
@@ -205,11 +285,136 @@ function getAlarmStatistics() {
         modulo: 3,
         responsive: true,
       });
-      console.log(chartData);
       config4.value = chartData.config;
       dataset4.value = chartData.dataset;
     });
 }
+
+function getAnalyzeTrend() {
+  api.dashboard
+    .getAnalyzeTrend({
+      searchMonth: analyzeTrendDate.value,
+    })
+    .then((res: any) => {
+      const list = res || [];
+      console.log({
+        legend: list.map((item: any) => item.month),
+        datas: list.map((item: any) => [item.alarmCount]),
+        width: 300,
+        height: 300,
+        responsive: false,
+      });
+      const chartData = getPieSmallData({
+        legend: list.map((item: any) => item.month),
+        datas: list.map((item: any) => [item.alarmCount]),
+        width: 300,
+        height: 300,
+        responsive: false,
+      });
+      config5.value = chartData.config;
+      dataset5.value = chartData.dataset;
+    });
+}
+
+function getDeptAlarm() {
+  api.dashboard
+    .getDeptAlarm({
+      startDate: deptAlarmDate.value[0],
+      endDate: deptAlarmDate.value[1],
+    })
+    .then((res: any) => {
+      console.log(res);
+      const list = res || [];
+      const chartData = getBarData({
+        xAxis: list.map((item: any) => item.deptName),
+        legend: ["部门告警"],
+        datas: [list.map((item: any) => item.alarmCount)],
+        width: 300,
+        height: 300,
+        modulo: 3,
+        responsive: true,
+      });
+      config6.value = chartData.config;
+      dataset6.value = chartData.dataset;
+    });
+}
+
+function getAlarmStatus() {
+  api.dashboard
+    .getAlarmStatus({
+      startDate: alarmStatusDate.value[0],
+      endDate: alarmStatusDate.value[1],
+    })
+    .then((res: any) => {
+      console.log(res);
+      const list = res || [];
+      const chartData = getBarData({
+        xAxis: list.map((item: any) => (item.status ? "已处理" : "未处理")),
+        legend: ["告警状态"],
+        datas: [list.map((item: any) => item.alarmCount)],
+        width: 300,
+        height: 300,
+        modulo: 3,
+        responsive: true,
+      });
+      config7.value = chartData.config;
+      dataset7.value = chartData.dataset;
+    });
+}
+
+function getAlarmType() {
+  api.dashboard
+    .getAlarmType({
+      startDate: alarmTypeDate.value[0],
+      endDate: alarmTypeDate.value[1],
+    })
+    .then((res: any) => {
+      console.log(res);
+      const list = res || [];
+      console.log({
+        legend: list.map((item: any) =>
+          item.alarmType === "1" ? "规则告警" : "自助上报告警"
+        ),
+        datas: list.map((item: any) => [item.alarmCount]),
+        width: 300,
+        height: 300,
+        responsive: true,
+      });
+      const chartData = getPieSmallData({
+        legend: list.map((item: any) =>
+          item.alarmType === "1" ? "规则告警" : "自助上报告警"
+        ),
+        datas: list.map((item: any) => [item.alarmCount]),
+        width: 300,
+        height: 300,
+        responsive: true,
+      });
+      config8.value = chartData.config;
+      dataset8.value = chartData.dataset;
+    });
+}
+
+function getAlarmLevel() {
+  api.dashboard
+    .getAlarmLevel({
+      startDate: alarmLevelDate.value[0],
+      endDate: alarmLevelDate.value[1],
+    })
+    .then((res: any) => {
+      const list = res || [];
+      const chartData = getBarData({
+        xAxis: list.map((item: any) => item.levelName),
+        legend: ["告警等级"],
+        datas: [list.map((item: any) => item.alarmCount)],
+        width: 300,
+        height: 300,
+        modulo: 3,
+        responsive: true,
+      });
+      config9.value = chartData.config;
+      dataset9.value = chartData.dataset;
+    });
+}
 </script>
 
 <style scoped lang="scss">
@@ -232,6 +437,9 @@ function getAlarmStatistics() {
     color: #333;
     font-weight: 500;
     line-height: 1;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
   }
 
   .flex-row {
@@ -250,6 +458,7 @@ function getAlarmStatistics() {
         justify-content: space-between;
 
         .vue-ui-xy,
+        .vue-ui-donut,
         .vue-ui-skeleton {
           flex: 1;
           height: 100%;