|
@@ -0,0 +1,159 @@
|
|
|
|
+<template>
|
|
|
|
+ <div class="page">
|
|
|
|
+ <div class="flex-row" style="gap: 12px">
|
|
|
|
+ <el-card shadow="nover">
|
|
|
|
+ <div class="title">今日告警</div>
|
|
|
|
+ <VueUiSkeleton class="flex1" :config="{ type: 'bar' }" />
|
|
|
|
+ </el-card>
|
|
|
|
+ <el-card shadow="nover">
|
|
|
|
+ <div class="title">告警设备top10</div>
|
|
|
|
+ <VueUiXy v-if="dataset2?.length" :config="config2" :dataset="dataset2" />
|
|
|
|
+ <VueUiSkeleton v-else :config="{ type: 'bar' }" />
|
|
|
|
+ </el-card>
|
|
|
|
+ <el-card shadow="nover">
|
|
|
|
+ <div class="title">最新告警</div>
|
|
|
|
+ <VueUiSkeleton :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' }" />
|
|
|
|
+ </el-card>
|
|
|
|
+ <el-card shadow="nover">
|
|
|
|
+ <div class="title">告警增长趋势</div>
|
|
|
|
+ <VueUiSkeleton :config="{ type: 'bar' }" />
|
|
|
|
+ </el-card>
|
|
|
|
+ <el-card shadow="nover">
|
|
|
|
+ <div class="title">部门告警分析</div>
|
|
|
|
+ <VueUiSkeleton :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' }" />
|
|
|
|
+ </el-card>
|
|
|
|
+ <el-card shadow="nover">
|
|
|
|
+ <div class="title">告警等级</div>
|
|
|
|
+ <VueUiSkeleton :config="{ type: 'bar' }" />
|
|
|
|
+ </el-card>
|
|
|
|
+ <el-card shadow="nover">
|
|
|
|
+ <div class="title">告警类型</div>
|
|
|
|
+ <VueUiSkeleton :config="{ type: 'bar' }" />
|
|
|
|
+ </el-card>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+</template>
|
|
|
|
+
|
|
|
|
+<script lang="ts" setup>
|
|
|
|
+import { toRefs, reactive, onMounted, 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 api from "/@/api/alarm";
|
|
|
|
+import dayjs from "dayjs";
|
|
|
|
+import { useThemeChange } from "/@/hooks/useCommon";
|
|
|
|
+
|
|
|
|
+//#region 线图
|
|
|
|
+
|
|
|
|
+// 获取默认图形配置数据
|
|
|
|
+const chartData = getLineData({
|
|
|
|
+ xAxis: [],
|
|
|
|
+ legend: [" "],
|
|
|
|
+ datas: [[]],
|
|
|
|
+ responsive: true,
|
|
|
|
+});
|
|
|
|
+
|
|
|
|
+const config = ref<any>({});
|
|
|
|
+const config2 = ref<any>({});
|
|
|
|
+const dataset = ref<any[]>([]);
|
|
|
|
+const dataset2 = ref<any[]>([]);
|
|
|
|
+
|
|
|
|
+//#endregion
|
|
|
|
+
|
|
|
|
+//#region 饼图
|
|
|
|
+
|
|
|
|
+// 获取默认图形配置数据
|
|
|
|
+const pieData = getPieData({
|
|
|
|
+ legend: [" "],
|
|
|
|
+ datas: [[]],
|
|
|
|
+});
|
|
|
|
+
|
|
|
|
+const pieConfig = ref<any>(pieData.config);
|
|
|
|
+const pieDataset = ref<any[]>(pieData.dataset);
|
|
|
|
+
|
|
|
|
+// 监听暗黑模式变化,将 vue-data-ui 的 config 传进来,就能自动更新主题
|
|
|
|
+useThemeChange([config, pieConfig]);
|
|
|
|
+
|
|
|
|
+getData()
|
|
|
|
+
|
|
|
|
+function getData() {
|
|
|
|
+ // 告警设备top10
|
|
|
|
+ api.dashboard.getDeviceAlarmTop10().then((res: any) => {
|
|
|
|
+ const list = res || []
|
|
|
|
+ const chartData = getBarData({
|
|
|
|
+ xAxis: list.map((item: any) => item.deviceName),
|
|
|
|
+ legend: ['告警设备top10'],
|
|
|
|
+ datas: [list.map((item: any) => item.alarmCount)],
|
|
|
|
+ width: 300,
|
|
|
|
+ height: 300,
|
|
|
|
+ responsive: true
|
|
|
|
+ })
|
|
|
|
+ config2.value = chartData.config
|
|
|
|
+ dataset2.value = chartData.dataset
|
|
|
|
+ })
|
|
|
|
+}
|
|
|
|
+</script>
|
|
|
|
+
|
|
|
|
+<style scoped lang="scss">
|
|
|
|
+.page {
|
|
|
|
+ display: flex;
|
|
|
|
+ flex-direction: column;
|
|
|
|
+ justify-content: space-between;
|
|
|
|
+ gap: 12px;
|
|
|
|
+
|
|
|
|
+ .vue-ui-skeleton {
|
|
|
|
+ height: 100%;
|
|
|
|
+
|
|
|
|
+ & ::v-deep>svg {
|
|
|
|
+ height: 100%;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .title {
|
|
|
|
+ font-size: 14px;
|
|
|
|
+ color: #333;
|
|
|
|
+ font-weight: 500;
|
|
|
|
+ line-height: 1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .flex-row {
|
|
|
|
+ flex: 1;
|
|
|
|
+
|
|
|
|
+ .el-card {
|
|
|
|
+ height: 100%;
|
|
|
|
+ flex: 1;
|
|
|
|
+
|
|
|
|
+ & ::v-deep .el-card__body {
|
|
|
|
+ padding: 1.5vh 1vw;
|
|
|
|
+ height: 100%;
|
|
|
|
+ gap: 10px;
|
|
|
|
+ display: flex;
|
|
|
|
+ flex-direction: column;
|
|
|
|
+ justify-content: space-between;
|
|
|
|
+
|
|
|
|
+ .vue-ui-xy,
|
|
|
|
+ .vue-ui-skeleton {
|
|
|
|
+ flex: 1;
|
|
|
|
+ height: 100%;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .vue-ui-skeleton {
|
|
|
|
+ overflow: hidden;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+</style>
|