|
@@ -1,74 +1,112 @@
|
|
<template>
|
|
<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>
|
|
|
|
|
|
+ <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>
|
|
|
|
+ <el-table
|
|
|
|
+ class="flex1"
|
|
|
|
+ :data="alarmNewList"
|
|
|
|
+ border
|
|
|
|
+ style="width: 100%"
|
|
|
|
+ size="small"
|
|
|
|
+ >
|
|
|
|
+ <el-table-column prop="createdAt" label="告警日期" width="140" align="center" />
|
|
|
|
+ <el-table-column
|
|
|
|
+ prop="status"
|
|
|
|
+ :formatter="(row:any) => (row.status ? '已处理' : '未处理')"
|
|
|
|
+ label="告警状态"
|
|
|
|
+ width="70"
|
|
|
|
+ align="center"
|
|
|
|
+ />
|
|
|
|
+ <el-table-column
|
|
|
|
+ prop="level"
|
|
|
|
+ label="告警等级"
|
|
|
|
+ :formatter="(row:any) => typeFormat(row.level)"
|
|
|
|
+ width="100"
|
|
|
|
+ align="center"
|
|
|
|
+ />
|
|
|
|
+ <el-table-column
|
|
|
|
+ prop="ruleName"
|
|
|
|
+ label="告警说明"
|
|
|
|
+ show-overflow-tooltip
|
|
|
|
+ aign="center"
|
|
|
|
+ />
|
|
|
|
+ </el-table>
|
|
|
|
+ </el-card>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="flex-row" style="gap: 12px">
|
|
|
|
+ <el-card shadow="nover">
|
|
|
|
+ <div class="title">告警统计</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' }" />
|
|
|
|
+ </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>
|
|
</template>
|
|
|
|
|
|
<script lang="ts" setup>
|
|
<script lang="ts" setup>
|
|
-import { toRefs, reactive, onMounted, ref } from "vue";
|
|
|
|
|
|
+import { unref, reactive, getCurrentInstance, ref } from "vue";
|
|
import { VueUiXy, VueUiDonut, VueUiSkeleton } from "vue-data-ui";
|
|
import { VueUiXy, VueUiDonut, VueUiSkeleton } from "vue-data-ui";
|
|
import "vue-data-ui/style.css";
|
|
import "vue-data-ui/style.css";
|
|
import { getBarData, getLineData, getPieData } from "/@/utils/dataUiOptions";
|
|
import { getBarData, getLineData, getPieData } from "/@/utils/dataUiOptions";
|
|
import api from "/@/api/alarm";
|
|
import api from "/@/api/alarm";
|
|
-import dayjs from "dayjs";
|
|
|
|
import { useThemeChange } from "/@/hooks/useCommon";
|
|
import { useThemeChange } from "/@/hooks/useCommon";
|
|
|
|
+import dayjs from "dayjs";
|
|
|
|
+
|
|
|
|
+const { proxy } = getCurrentInstance() as any;
|
|
|
|
+const { alarm_type } = proxy.useDict("alarm_type");
|
|
|
|
+
|
|
|
|
+function typeFormat(type: string) {
|
|
|
|
+ return proxy.selectDictLabel(unref(alarm_type), type);
|
|
|
|
+}
|
|
|
|
|
|
//#region 线图
|
|
//#region 线图
|
|
|
|
|
|
// 获取默认图形配置数据
|
|
// 获取默认图形配置数据
|
|
const chartData = getLineData({
|
|
const chartData = getLineData({
|
|
- xAxis: [],
|
|
|
|
- legend: [" "],
|
|
|
|
- datas: [[]],
|
|
|
|
- responsive: true,
|
|
|
|
|
|
+ xAxis: [],
|
|
|
|
+ legend: [" "],
|
|
|
|
+ datas: [[]],
|
|
|
|
+ responsive: true,
|
|
});
|
|
});
|
|
|
|
|
|
const config = ref<any>({});
|
|
const config = ref<any>({});
|
|
const config2 = ref<any>({});
|
|
const config2 = ref<any>({});
|
|
|
|
+const config4 = ref<any>({});
|
|
const dataset = ref<any[]>([]);
|
|
const dataset = ref<any[]>([]);
|
|
const dataset2 = ref<any[]>([]);
|
|
const dataset2 = ref<any[]>([]);
|
|
|
|
+const dataset4 = ref<any[]>([]);
|
|
|
|
|
|
//#endregion
|
|
//#endregion
|
|
|
|
|
|
@@ -76,8 +114,8 @@ const dataset2 = ref<any[]>([]);
|
|
|
|
|
|
// 获取默认图形配置数据
|
|
// 获取默认图形配置数据
|
|
const pieData = getPieData({
|
|
const pieData = getPieData({
|
|
- legend: [" "],
|
|
|
|
- datas: [[]],
|
|
|
|
|
|
+ legend: [" "],
|
|
|
|
+ datas: [[]],
|
|
});
|
|
});
|
|
|
|
|
|
const pieConfig = ref<any>(pieData.config);
|
|
const pieConfig = ref<any>(pieData.config);
|
|
@@ -86,74 +124,117 @@ const pieDataset = ref<any[]>(pieData.dataset);
|
|
// 监听暗黑模式变化,将 vue-data-ui 的 config 传进来,就能自动更新主题
|
|
// 监听暗黑模式变化,将 vue-data-ui 的 config 传进来,就能自动更新主题
|
|
useThemeChange([config, pieConfig]);
|
|
useThemeChange([config, pieConfig]);
|
|
|
|
|
|
-getData()
|
|
|
|
|
|
+const todayCount = reactive({
|
|
|
|
+ currentDayCount: "-",
|
|
|
|
+ currentMonthCount: "-",
|
|
|
|
+});
|
|
|
|
+
|
|
|
|
+const alarmNewList = ref<any[]>([]);
|
|
|
|
+
|
|
|
|
+getData();
|
|
|
|
|
|
function 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
|
|
|
|
- })
|
|
|
|
|
|
+ // 今日告警信息
|
|
|
|
+ api.dashboard.getCurrentDayInfo().then((res: any) => {
|
|
|
|
+ const list = res.alarmList || [];
|
|
|
|
+ todayCount.currentDayCount = res.currentDayCount;
|
|
|
|
+ todayCount.currentMonthCount = res.currentMonthCount;
|
|
|
|
+
|
|
|
|
+ console.log(res);
|
|
|
|
+ console.log(list);
|
|
|
|
+ });
|
|
|
|
+ // 最新告警
|
|
|
|
+ api.dashboard.getAlarmNewList().then((res: any) => {
|
|
|
|
+ console.log(res);
|
|
|
|
+ alarmNewList.value = res || [];
|
|
|
|
+ });
|
|
|
|
+ // 告警统计
|
|
|
|
+ api.dashboard
|
|
|
|
+ .getAlarmStatistics({
|
|
|
|
+ startDate: dayjs().subtract(7, "day").format("YYYY-MM-DD"),
|
|
|
|
+ endDate: dayjs().format("YYYY-MM-DD"),
|
|
|
|
+ })
|
|
|
|
+ .then((res: any) => {
|
|
|
|
+ console.log(res);
|
|
|
|
+ const list = res || [];
|
|
|
|
+ const chartData = getBarData({
|
|
|
|
+ xAxis: list.map((item: any) => item.alarmDate),
|
|
|
|
+ legend: ["告警统计"],
|
|
|
|
+ datas: [list.map((item: any) => item.alarmCount)],
|
|
|
|
+ width: 300,
|
|
|
|
+ height: 300,
|
|
|
|
+ modulo: 3,
|
|
|
|
+ responsive: true,
|
|
|
|
+ });
|
|
|
|
+ console.log(chartData);
|
|
|
|
+ config4.value = chartData.config;
|
|
|
|
+ dataset4.value = chartData.dataset;
|
|
|
|
+ });
|
|
|
|
+ // 告警设备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>
|
|
</script>
|
|
|
|
|
|
<style scoped lang="scss">
|
|
<style scoped lang="scss">
|
|
.page {
|
|
.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;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ 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>
|
|
</style>
|