|
@@ -1,7 +1,7 @@
|
|
|
<template>
|
|
<template>
|
|
|
<div class="dashboard-container">
|
|
<div class="dashboard-container">
|
|
|
- <Spin class="w-full h-full" v-if="!isDataLoaded"></Spin>
|
|
|
|
|
- <div class="content-area" v-if="isDataLoaded">
|
|
|
|
|
|
|
+ <Skeleton v-if="loading" active class="p-20px"></Skeleton>
|
|
|
|
|
+ <div class="content-area" v-if="!loading">
|
|
|
<!-- 顶部信息卡片 -->
|
|
<!-- 顶部信息卡片 -->
|
|
|
<div class="top-info">
|
|
<div class="top-info">
|
|
|
<!-- {{ mineStore.getRoot }} -->
|
|
<!-- {{ mineStore.getRoot }} -->
|
|
@@ -51,7 +51,7 @@
|
|
|
<div class="icon-bottom"></div>
|
|
<div class="icon-bottom"></div>
|
|
|
</div>
|
|
</div>
|
|
|
<div class="text">超限异常报警</div>
|
|
<div class="text">超限异常报警</div>
|
|
|
- <div class="count">{{ realtimeWarning.overLimitCount }}</div>
|
|
|
|
|
|
|
+ <div class="count">{{ get(realtimeWarning, 'overLimitCount', '-') }}</div>
|
|
|
</div>
|
|
</div>
|
|
|
<div class="stat-item medium-risk">
|
|
<div class="stat-item medium-risk">
|
|
|
<div class="icon">
|
|
<div class="icon">
|
|
@@ -59,7 +59,7 @@
|
|
|
<div class="icon-bottom"></div>
|
|
<div class="icon-bottom"></div>
|
|
|
</div>
|
|
</div>
|
|
|
<div class="text">预测预警</div>
|
|
<div class="text">预测预警</div>
|
|
|
- <div class="count">{{ realtimeWarning.alarmInfoCount }}</div>
|
|
|
|
|
|
|
+ <div class="count">{{ get(realtimeWarning, 'alarmInfoCount', '-') }}</div>
|
|
|
</div>
|
|
</div>
|
|
|
<div class="stat-item normal-risk">
|
|
<div class="stat-item normal-risk">
|
|
|
<div class="icon">
|
|
<div class="icon">
|
|
@@ -67,7 +67,7 @@
|
|
|
<div class="icon-bottom"></div>
|
|
<div class="icon-bottom"></div>
|
|
|
</div>
|
|
</div>
|
|
|
<div class="text">数据中断</div>
|
|
<div class="text">数据中断</div>
|
|
|
- <div class="count">{{ realtimeWarning.dataBreakCount }}</div>
|
|
|
|
|
|
|
+ <div class="count">{{ get(realtimeWarning, 'dataBreakCount', '-') }}</div>
|
|
|
</div>
|
|
</div>
|
|
|
<div class="stat-item low-risk">
|
|
<div class="stat-item low-risk">
|
|
|
<div class="icon">
|
|
<div class="icon">
|
|
@@ -75,7 +75,7 @@
|
|
|
<div class="icon-bottom"></div>
|
|
<div class="icon-bottom"></div>
|
|
|
</div>
|
|
</div>
|
|
|
<div class="text">数据质量</div>
|
|
<div class="text">数据质量</div>
|
|
|
- <div class="count">{{ realtimeWarning.dataQualityCount }}</div>
|
|
|
|
|
|
|
+ <div class="count">{{ get(realtimeWarning, 'dataQualityCount', '-') }}</div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
@@ -175,7 +175,7 @@
|
|
|
</template>
|
|
</template>
|
|
|
<script setup lang="ts">
|
|
<script setup lang="ts">
|
|
|
import { useRouter } from 'vue-router';
|
|
import { useRouter } from 'vue-router';
|
|
|
- import { onMounted, ref } from 'vue';
|
|
|
|
|
|
|
+ import { ref, watch } from 'vue';
|
|
|
import { getAlarmType, getGoafAccessCount, getHistoryAlarmNum, getMineData, getRealAlarmNum, getGoafData } from '../overhaul.api';
|
|
import { getAlarmType, getGoafAccessCount, getHistoryAlarmNum, getMineData, getRealAlarmNum, getGoafData } from '../overhaul.api';
|
|
|
import { columns } from '../overhaul.data';
|
|
import { columns } from '../overhaul.data';
|
|
|
import { useMineDepartmentStore } from '/@/store/modules/mine';
|
|
import { useMineDepartmentStore } from '/@/store/modules/mine';
|
|
@@ -186,10 +186,11 @@
|
|
|
import { StatusColorEnum } from '/@/enums/jeecgEnum';
|
|
import { StatusColorEnum } from '/@/enums/jeecgEnum';
|
|
|
import { BasicTable } from '/@/components/Table';
|
|
import { BasicTable } from '/@/components/Table';
|
|
|
import { BasicModal } from '/@/components/Modal';
|
|
import { BasicModal } from '/@/components/Modal';
|
|
|
- import { Spin } from 'ant-design-vue';
|
|
|
|
|
|
|
+ import { Skeleton } from 'ant-design-vue';
|
|
|
import { EChartsOption, graphic } from 'echarts';
|
|
import { EChartsOption, graphic } from 'echarts';
|
|
|
import IMG1 from '/@/assets/images/overHaul/rootPage/pie-chart-center.png';
|
|
import IMG1 from '/@/assets/images/overHaul/rootPage/pie-chart-center.png';
|
|
|
import IMG2 from '/@/assets/images/overHaul/rootPage/alarm-icon-9.svg';
|
|
import IMG2 from '/@/assets/images/overHaul/rootPage/alarm-icon-9.svg';
|
|
|
|
|
+ import { get } from 'lodash-es';
|
|
|
|
|
|
|
|
// 处理矿名选择器相关的逻辑
|
|
// 处理矿名选择器相关的逻辑
|
|
|
const isDetailModalVisible = ref(false);
|
|
const isDetailModalVisible = ref(false);
|
|
@@ -249,7 +250,7 @@
|
|
|
const router = useRouter();
|
|
const router = useRouter();
|
|
|
const mineStore = useMineDepartmentStore();
|
|
const mineStore = useMineDepartmentStore();
|
|
|
// 数据加载状态
|
|
// 数据加载状态
|
|
|
- const isDataLoaded = ref(false);
|
|
|
|
|
|
|
+ const loading = ref(false);
|
|
|
const accessStatics = ref<any[]>([]);
|
|
const accessStatics = ref<any[]>([]);
|
|
|
// 控制图表显示/隐藏的状态
|
|
// 控制图表显示/隐藏的状态
|
|
|
const isChartVisible = ref(true);
|
|
const isChartVisible = ref(true);
|
|
@@ -278,48 +279,53 @@
|
|
|
// // {key: 'leakageAlarm', label: '漏风'},
|
|
// // {key: 'leakageAlarm', label: '漏风'},
|
|
|
// // {key: 'unsealAlarm', label: '密闭启封'},
|
|
// // {key: 'unsealAlarm', label: '密闭启封'},
|
|
|
// ];
|
|
// ];
|
|
|
- async function fetchAccessStatics() {
|
|
|
|
|
- accessStatics.value = await getGoafAccessCount({ deptId: mineStore.getRootId });
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 单一刷新方法:并行获取所有接口数据,统一处理空数组/undefined 兜底
|
|
|
|
|
+ */
|
|
|
const realtimeWarning = ref<any>({});
|
|
const realtimeWarning = ref<any>({});
|
|
|
- async function fetchRealtimeWarning() {
|
|
|
|
|
- realtimeWarning.value = await getRealAlarmNum({ deptId: mineStore.getRootId });
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
const alarmType = ref<any[]>([]);
|
|
const alarmType = ref<any[]>([]);
|
|
|
- async function fetchAlarmType() {
|
|
|
|
|
- const result = await getAlarmType({
|
|
|
|
|
- deptId: mineStore.getRootId,
|
|
|
|
|
- startTime: dayjs().add(-6, 'months').format('YYYY-MM-DD HH:mm:ss'),
|
|
|
|
|
- endTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
|
|
|
|
- });
|
|
|
|
|
- alarmType.value = result.map((e) => ({
|
|
|
|
|
|
|
+ const historyAlarmNum = ref<any[]>([]);
|
|
|
|
|
+ const mineData = ref<any>([]);
|
|
|
|
|
+
|
|
|
|
|
+ async function fetchAllData() {
|
|
|
|
|
+ const deptId = mineStore.getDepartId;
|
|
|
|
|
+ if (!deptId) return;
|
|
|
|
|
+
|
|
|
|
|
+ const [accessResult, realtimeResult, alarmTypeResult, historyResult, mineResult] = await Promise.all([
|
|
|
|
|
+ getGoafAccessCount({ deptId }),
|
|
|
|
|
+ getRealAlarmNum({ deptId }),
|
|
|
|
|
+ getAlarmType({
|
|
|
|
|
+ deptId,
|
|
|
|
|
+ startTime: dayjs().add(-6, 'months').format('YYYY-MM-DD HH:mm:ss'),
|
|
|
|
|
+ endTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
|
|
|
|
+ }),
|
|
|
|
|
+ getHistoryAlarmNum({
|
|
|
|
|
+ deptId,
|
|
|
|
|
+ startTime: dayjs().add(-6, 'months').format('YYYY-MM-DD HH:mm:ss'),
|
|
|
|
|
+ endTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
|
|
|
|
+ }),
|
|
|
|
|
+ getMineData({ deptId }),
|
|
|
|
|
+ ]);
|
|
|
|
|
+
|
|
|
|
|
+ // —— 兜底处理:接口返回空数组/undefined 时使用安全的默认值 ——
|
|
|
|
|
+ accessStatics.value = Array.isArray(accessResult) ? accessResult : [];
|
|
|
|
|
+ realtimeWarning.value = realtimeResult ?? {};
|
|
|
|
|
+
|
|
|
|
|
+ const alarmTypeList = Array.isArray(alarmTypeResult) ? alarmTypeResult : [];
|
|
|
|
|
+ alarmType.value = alarmTypeList.map((e) => ({
|
|
|
key: e.alarm_type,
|
|
key: e.alarm_type,
|
|
|
name: e.name,
|
|
name: e.name,
|
|
|
value: e.num,
|
|
value: e.num,
|
|
|
}));
|
|
}));
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
- const historyAlarmNum = ref<any[]>([]);
|
|
|
|
|
- async function fetchHistoryAlarmNum() {
|
|
|
|
|
- const result = await getHistoryAlarmNum({
|
|
|
|
|
- deptId: mineStore.getRootId,
|
|
|
|
|
- startTime: dayjs().add(-6, 'months').format('YYYY-MM-DD HH:mm:ss'),
|
|
|
|
|
- endTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
|
|
|
|
- });
|
|
|
|
|
- historyAlarmNum.value = result.map((e) => ({
|
|
|
|
|
|
|
+ const historyList = Array.isArray(historyResult) ? historyResult : [];
|
|
|
|
|
+ historyAlarmNum.value = historyList.map((e) => ({
|
|
|
name: e.mine_name,
|
|
name: e.mine_name,
|
|
|
value: e.num,
|
|
value: e.num,
|
|
|
}));
|
|
}));
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
- const mineData = ref<any>([]);
|
|
|
|
|
- async function fetchMineData() {
|
|
|
|
|
- const { records } = await getMineData({
|
|
|
|
|
- deptId: mineStore.getRootId,
|
|
|
|
|
- });
|
|
|
|
|
- mineData.value = records;
|
|
|
|
|
|
|
+ const mineRecords = Array.isArray(mineResult?.records) ? mineResult.records : [];
|
|
|
|
|
+ mineData.value = mineRecords;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -635,10 +641,18 @@
|
|
|
],
|
|
],
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- onMounted(async () => {
|
|
|
|
|
- await Promise.all([fetchAccessStatics(), fetchRealtimeWarning(), fetchAlarmType(), fetchHistoryAlarmNum(), fetchMineData()]);
|
|
|
|
|
- isDataLoaded.value = true;
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ watch(
|
|
|
|
|
+ () => mineStore.getDepartId,
|
|
|
|
|
+ async (newId) => {
|
|
|
|
|
+ if (!newId) return;
|
|
|
|
|
+ loading.value = true;
|
|
|
|
|
+ await fetchAllData();
|
|
|
|
|
+ loading.value = false;
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ immediate: true,
|
|
|
|
|
+ }
|
|
|
|
|
+ );
|
|
|
</script>
|
|
</script>
|
|
|
<style lang="less" scoped>
|
|
<style lang="less" scoped>
|
|
|
.dashboard-container {
|
|
.dashboard-container {
|
|
@@ -741,7 +755,7 @@
|
|
|
height: 100%;
|
|
height: 100%;
|
|
|
display: flex;
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
flex-direction: column;
|
|
|
- overflow-y: scroll;
|
|
|
|
|
|
|
+ overflow-y: auto;
|
|
|
gap: 15px;
|
|
gap: 15px;
|
|
|
}
|
|
}
|
|
|
.card-item {
|
|
.card-item {
|
|
@@ -951,8 +965,8 @@
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
.details-content {
|
|
.details-content {
|
|
|
- height: 450px;
|
|
|
|
|
- overflow-y: scroll;
|
|
|
|
|
|
|
+ max-height: 450px;
|
|
|
|
|
+ overflow-y: auto;
|
|
|
scroll-snap-type: y mandatory;
|
|
scroll-snap-type: y mandatory;
|
|
|
}
|
|
}
|
|
|
|
|
|