大屏优化
This commit is contained in:
@@ -34,7 +34,10 @@
|
|||||||
</div>
|
</div>
|
||||||
<span>总计</span>
|
<span>总计</span>
|
||||||
<div class="number-wrapper">
|
<div class="number-wrapper">
|
||||||
<span class="total-number" v-for="(digit, index) in totalCountDigits" :key="index">
|
<div v-if="isFirstLoading" class="skeleton-number-wrapper">
|
||||||
|
<div v-for="i in 4" :key="i" class="skeleton-number skeleton-pulse"></div>
|
||||||
|
</div>
|
||||||
|
<span v-else class="total-number" v-for="(digit, index) in totalCountDigits" :key="index">
|
||||||
{{ digit }}
|
{{ digit }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -47,9 +50,14 @@
|
|||||||
<span>正式员工</span>
|
<span>正式员工</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="type-number-wrapper" :style="{ width: `${maxNumberWidth}px` }">
|
<div class="type-number-wrapper" :style="{ width: `${maxNumberWidth}px` }">
|
||||||
<span class="type-number" v-for="(digit, index) in formalEmployeeDigits" :key="index">
|
<div v-if="isFirstLoading" class="skeleton-type-number-wrapper">
|
||||||
{{ digit }}
|
<div v-for="i in formalEmployeeDigits.length" :key="i" class="skeleton-type-number skeleton-pulse"></div>
|
||||||
</span>
|
</div>
|
||||||
|
<div v-else class="type-number-wrapper">
|
||||||
|
<span class="type-number" v-for="(digit, index) in formalEmployeeDigits" :key="index">
|
||||||
|
{{ digit }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<span>人</span>
|
<span>人</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -59,9 +67,14 @@
|
|||||||
<span>外协人员</span>
|
<span>外协人员</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="type-number-wrapper" :style="{ width: `${maxNumberWidth}px` }">
|
<div class="type-number-wrapper" :style="{ width: `${maxNumberWidth}px` }">
|
||||||
<span class="type-number" v-for="(digit, index) in externalStaffDigits" :key="index">
|
<div v-if="isFirstLoading" class="skeleton-type-number-wrapper">
|
||||||
{{ digit }}
|
<div v-for="i in externalStaffDigits.length" :key="i" class="skeleton-type-number skeleton-pulse"></div>
|
||||||
</span>
|
</div>
|
||||||
|
<div v-else class="type-number-wrapper">
|
||||||
|
<span class="type-number" v-for="(digit, index) in externalStaffDigits" :key="index">
|
||||||
|
{{ digit }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<span>人</span>
|
<span>人</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -71,9 +84,14 @@
|
|||||||
<span>访客</span>
|
<span>访客</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="type-number-wrapper" :style="{ width: `${maxNumberWidth}px` }">
|
<div class="type-number-wrapper" :style="{ width: `${maxNumberWidth}px` }">
|
||||||
<span class="type-number" v-for="(digit, index) in visitorDigits" :key="index">
|
<div v-if="isFirstLoading" class="skeleton-type-number-wrapper">
|
||||||
{{ digit }}
|
<div v-for="i in visitorDigits.length" :key="i" class="skeleton-type-number skeleton-pulse"></div>
|
||||||
</span>
|
</div>
|
||||||
|
<div v-else class="type-number-wrapper">
|
||||||
|
<span class="type-number" v-for="(digit, index) in visitorDigits" :key="index">
|
||||||
|
{{ digit }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<span>人</span>
|
<span>人</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -88,12 +106,14 @@
|
|||||||
<div class="type-wrapper">
|
<div class="type-wrapper">
|
||||||
<div class="type-item">
|
<div class="type-item">
|
||||||
<span class="type-btn yellow">重大</span>
|
<span class="type-btn yellow">重大</span>
|
||||||
<span class="type-num cursor-pointer" @click="handleSeverityCountClick">{{
|
<div v-if="isFirstLoading" class="type-num skeleton-pulse"></div>
|
||||||
|
<span v-else class="type-num cursor-pointer" @click="handleSeverityCountClick">{{
|
||||||
mockData.hiddenDangerData.severityCount }}</span>
|
mockData.hiddenDangerData.severityCount }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="type-item">
|
<div class="type-item">
|
||||||
<span class="type-btn green">一般</span>
|
<span class="type-btn green">一般</span>
|
||||||
<span class="type-num cursor-pointer" @click="handleGeneralCountClick">{{
|
<div v-if="isFirstLoading" class="type-num skeleton-pulse"></div>
|
||||||
|
<span v-else class="type-num cursor-pointer" @click="handleGeneralCountClick">{{
|
||||||
mockData.hiddenDangerData.generalCount }}</span>
|
mockData.hiddenDangerData.generalCount }}</span>
|
||||||
</div>
|
</div>
|
||||||
<!-- <div class="type-item">
|
<!-- <div class="type-item">
|
||||||
@@ -103,6 +123,7 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="hazard-wrapper">
|
<div class="hazard-wrapper">
|
||||||
|
<!-- <div v-if="isFirstLoading" class="skeleton-chart skeleton-pulse"></div> -->
|
||||||
<div ref="progressChartRef" class="progress-chart"></div>
|
<div ref="progressChartRef" class="progress-chart"></div>
|
||||||
<div class="progress-legend">
|
<div class="progress-legend">
|
||||||
<div class="legend-item"><span class="dot red"></span>已逾期</div>
|
<div class="legend-item"><span class="dot red"></span>已逾期</div>
|
||||||
@@ -165,7 +186,12 @@
|
|||||||
<img width="50%" style="margin: 8px 0" src="@/assets/images/line_1.png" />
|
<img width="50%" style="margin: 8px 0" src="@/assets/images/line_1.png" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<AlertList maxHeight="40vh" style="margin-left: 1vw;" :table-title="tableTitle" :list-data="examList" />
|
<AlertList
|
||||||
|
maxHeight="40vh"
|
||||||
|
style="margin-left: 1vw;"
|
||||||
|
:table-title="tableTitle"
|
||||||
|
:list-data="examList"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template v-if="activeTab === '应急预案及演练'">
|
<template v-if="activeTab === '应急预案及演练'">
|
||||||
<div class="bottom-card">
|
<div class="bottom-card">
|
||||||
@@ -178,7 +204,7 @@
|
|||||||
:list-data="drillList" />
|
:list-data="drillList" />
|
||||||
</template>
|
</template>
|
||||||
</div> -->
|
</div> -->
|
||||||
<RiskStatisticsPanel :riskStatistics="riskStatistics" :dangerDetail="dangerDetail" :park="parkValue"
|
<RiskStatisticsPanel :loading="isFirstLoading" :riskStatistics="riskStatistics" :dangerDetail="dangerDetail" :park="parkValue"
|
||||||
@tab-change="handleRiskTabChange" :campus_id="query.campus_id" />
|
@tab-change="handleRiskTabChange" :campus_id="query.campus_id" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -192,34 +218,39 @@
|
|||||||
<div class="tip-container">
|
<div class="tip-container">
|
||||||
<div class="tip-image">
|
<div class="tip-image">
|
||||||
<img src="@/assets/images/screen/circle_image.png" width="80" height="80" />
|
<img src="@/assets/images/screen/circle_image.png" width="80" height="80" />
|
||||||
<span class="number">{{ mockData.alertData.total }}</span>
|
<div v-if="isFirstLoading" style="width: 20px; height: 20px" class="number skeleton-pulse"></div>
|
||||||
|
<span v-else class="number">{{ mockData.alertData.total }}</span>
|
||||||
</div>
|
</div>
|
||||||
<img src="@/assets/images/screen/tip_bg_image.png" width="100%" height="70" />
|
<img src="@/assets/images/screen/tip_bg_image.png" width="100%" height="70" />
|
||||||
<div class="tip-content">
|
<div class="tip-content">
|
||||||
<div class="col-item">
|
<div class="col-item">
|
||||||
<img src="@/assets/images/screen/warning_img.png" width="23" />
|
<img src="@/assets/images/screen/warning_img.png" width="23" />
|
||||||
<span>告警总数</span>
|
<span>告警总数</span>
|
||||||
<span style="font-size: 1.2rem; marker-start: 2vw; color: yellow;">{{ mockData.alertData.total }}</span>
|
<div v-if="isFirstLoading" style="width: 20px; height: 20px;" class="skeleton-pulse"></div>
|
||||||
|
<span v-else style="font-size: 1.2rem; marker-start: 2vw; color: yellow;">{{ mockData.alertData.total }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-item">
|
<div class="col-item">
|
||||||
<span>已处理</span>
|
<span>已处理</span>
|
||||||
<span style="font-size: 1.2rem; marker-start: 2vw; color: greenyellow;">{{ mockData.alertData.processed
|
<div v-if="isFirstLoading" style="width: 20px; height: 20px;" class="skeleton-pulse"></div>
|
||||||
|
<span v-else style="font-size: 1.2rem; marker-start: 2vw; color: greenyellow;">{{ mockData.alertData.processed
|
||||||
}}</span>
|
}}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-item" style=" display: flex;margin-left: 2vw; align-items: center;">
|
<div class="col-item" style=" display: flex;margin-left: 2vw; align-items: center;">
|
||||||
<span>待处理</span>
|
<span>待处理</span>
|
||||||
<span style="font-size: 1.2rem; marker-start: 2vw; color: yellow;">{{ mockData.alertData.pending
|
<div v-if="isFirstLoading" style="width: 20px; height: 20px;" class="skeleton-pulse"></div>
|
||||||
|
<span v-else style="font-size: 1.2rem; marker-start: 2vw; color: yellow;">{{ mockData.alertData.pending
|
||||||
}}</span>
|
}}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-item" style=" display: flex;margin-left: 2vw; align-items: center;">
|
<div class="col-item" style=" display: flex;margin-left: 2vw; align-items: center;">
|
||||||
<span>处理中</span>
|
<span>处理中</span>
|
||||||
<span style="font-size: 1.2rem; marker-start: 2vw; color: yellow;">{{ mockData.alertData.processing
|
<div v-if="isFirstLoading" style="width: 20px; height: 20px;" class="skeleton-pulse"></div>
|
||||||
|
<span v-else style="font-size: 1.2rem; marker-start: 2vw; color: yellow;">{{ mockData.alertData.processing
|
||||||
}}</span>
|
}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style=" display: flex; width: 100%;margin-top: 1vw; flex: 1; justify-content: flex-end;">
|
<div style=" display: flex; width: 100%;margin-top: 1vw; flex: 1; justify-content: flex-end;">
|
||||||
<AlertList linkUrl="http://10.0.64.20/security/console/command-center?p=tabl" style="margin-right: 1vw;" title="告警详情" :list-data="mockData.alertData.details" />
|
<AlertList :loading="isFirstLoading" linkUrl="http://10.0.64.20/security/console/command-center?p=tabl" style="margin-right: 1vw;" title="告警详情" :list-data="mockData.alertData.details" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- 右下区域 -->
|
<!-- 右下区域 -->
|
||||||
@@ -229,20 +260,30 @@
|
|||||||
<div class="tip-container">
|
<div class="tip-container">
|
||||||
<div class="tip-image">
|
<div class="tip-image">
|
||||||
<img src="@/assets/images/screen/circle_image.png" width="80" height="80" />
|
<img src="@/assets/images/screen/circle_image.png" width="80" height="80" />
|
||||||
<span class="number">{{ mockData.timeoutWorkOrders.total }}</span>
|
<div v-if="isFirstLoading" style="width: 20px; height: 20px" class="number skeleton-pulse"></div>
|
||||||
|
<span v-else class="number">{{ mockData.timeoutWorkOrders.total }}</span>
|
||||||
</div>
|
</div>
|
||||||
<img src="@/assets/images/screen/tip_bg_image.png" width="100%" height="70" />
|
<img src="@/assets/images/screen/tip_bg_image.png" width="100%" height="70" />
|
||||||
<div class="tip-content">
|
<div class="tip-content">
|
||||||
<div class="col-item">
|
<div class="col-item">
|
||||||
<img src="@/assets/images/screen/warning_img.png" width="23" />
|
<img src="@/assets/images/screen/warning_img.png" width="23" />
|
||||||
<span>超时工单数</span>
|
<span>超时工单数</span>
|
||||||
<span style="font-size: 1.2rem; marker-start: 2vw; color: red;">{{ mockData.timeoutWorkOrders.total
|
<div v-if="isFirstLoading" style="width: 20px; height: 20px;" class="skeleton-pulse"></div>
|
||||||
}}</span>
|
<span
|
||||||
|
v-else
|
||||||
|
style="font-size: 1.2rem; marker-start: 2vw; color: red;"
|
||||||
|
>{{ mockData.timeoutWorkOrders.total }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style=" display: flex; width: 100%;margin-top: 1vw; flex: 1; justify-content: flex-end;">
|
<div style=" display: flex; width: 100%;margin-top: 1vw; flex: 1; justify-content: flex-end;">
|
||||||
<AlertList linkUrl="http://10.0.64.20/pms/workorder-list" style="margin-right: 1vw;" title="工单详情" :list-data="mockData.timeoutWorkOrders.details" />
|
<AlertList
|
||||||
|
:loading="isFirstLoading"
|
||||||
|
linkUrl="http://10.0.64.20/pms/workorder-list"
|
||||||
|
style="margin-right: 1vw;"
|
||||||
|
title="工单详情"
|
||||||
|
:list-data="mockData.timeoutWorkOrders.details"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -261,6 +302,9 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, onMounted, onUnmounted, computed } from 'vue'
|
import { ref, onMounted, onUnmounted, computed } from 'vue'
|
||||||
import { useRoute, useRouter } from 'vue-router'
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
|
|
||||||
|
// 创建 AbortController 用于取消请求
|
||||||
|
const abortController = new AbortController()
|
||||||
import * as echarts from 'echarts'
|
import * as echarts from 'echarts'
|
||||||
import ParkCenter from './components/ParkCenter.vue'
|
import ParkCenter from './components/ParkCenter.vue'
|
||||||
import PointInfoPopup from './components/PointInfoPopup.vue'
|
import PointInfoPopup from './components/PointInfoPopup.vue'
|
||||||
@@ -304,6 +348,9 @@ const currentTime = ref<string>('')
|
|||||||
const activeTab = ref<string>('高危作业')
|
const activeTab = ref<string>('高危作业')
|
||||||
const showPointPopup = ref(false)
|
const showPointPopup = ref(false)
|
||||||
const currentPoint = ref<PointPosition | null>(null)
|
const currentPoint = ref<PointPosition | null>(null)
|
||||||
|
|
||||||
|
// 首次加载状态
|
||||||
|
const isFirstLoading = ref<boolean>(true)
|
||||||
const progressChart = ref<echarts.ECharts | null>(null)
|
const progressChart = ref<echarts.ECharts | null>(null)
|
||||||
const progressChartRef = ref<HTMLElement | null>(null)
|
const progressChartRef = ref<HTMLElement | null>(null)
|
||||||
const timeUpdateTimerId = ref<ReturnType<typeof setInterval> | null>(null)
|
const timeUpdateTimerId = ref<ReturnType<typeof setInterval> | null>(null)
|
||||||
@@ -351,11 +398,11 @@ const handleRiskTabChange = async (tab: TabType) => {
|
|||||||
|
|
||||||
// 同时获取维保任务和巡检任务的数据
|
// 同时获取维保任务和巡检任务的数据
|
||||||
const [maintenanceResponse, inspectionResponse] = await Promise.all([
|
const [maintenanceResponse, inspectionResponse] = await Promise.all([
|
||||||
getWorkOrderStatistics({ workOrderType, taskType: '维保任务', campus_id: query.campus_id }).catch(error => {
|
getWorkOrderStatistics({ workOrderType, taskType: '维保任务', campus_id: query.campus_id }, { signal: abortController.signal }).catch(error => {
|
||||||
console.error('获取维保任务数据失败:', error)
|
console.error('获取维保任务数据失败:', error)
|
||||||
return { records: [] }
|
return { records: [] }
|
||||||
}),
|
}),
|
||||||
getWorkOrderStatistics({ workOrderType, taskType: '巡检任务', campus_id: query.campus_id }).catch(error => {
|
getWorkOrderStatistics({ workOrderType, taskType: '巡检任务', campus_id: query.campus_id }, { signal: abortController.signal }).catch(error => {
|
||||||
console.error('获取巡检任务数据失败:', error)
|
console.error('获取巡检任务数据失败:', error)
|
||||||
return { records: [] }
|
return { records: [] }
|
||||||
})
|
})
|
||||||
@@ -752,55 +799,70 @@ onMounted(async () => {
|
|||||||
updateTime()
|
updateTime()
|
||||||
timeUpdateTimerId.value = setInterval(updateTime, 1000)
|
timeUpdateTimerId.value = setInterval(updateTime, 1000)
|
||||||
|
|
||||||
if (typeof route.query.parkName === 'string') {
|
try {
|
||||||
selectedPark.value = route.query.parkName
|
if (typeof route.query.parkName === 'string') {
|
||||||
query.campus_id = route.query.parkCode as string
|
selectedPark.value = route.query.parkName
|
||||||
}
|
query.campus_id = route.query.parkCode as string
|
||||||
|
|
||||||
handleRiskTabChange('安全类事项')
|
|
||||||
|
|
||||||
// 先检查缓存
|
|
||||||
const cachedRecords = getCachedRegionOption()
|
|
||||||
let records = cachedRecords
|
|
||||||
|
|
||||||
if (!records || records.length === 0) {
|
|
||||||
// 缓存不存在或已过期,调用接口
|
|
||||||
try {
|
|
||||||
let result = await getTableList('park_info_list')
|
|
||||||
records = result.records || []
|
|
||||||
|
|
||||||
if (records && records.length > 0) {
|
|
||||||
// 保存到缓存
|
|
||||||
setCachedRegionOption(records)
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('初始化园区数据失败:', error)
|
|
||||||
records = []
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (records && records.length > 0) {
|
|
||||||
// 更新为新的数据格式
|
|
||||||
regionOption.value = records.map(el => ({
|
|
||||||
name: el.park_name,
|
|
||||||
code: el.park_code,
|
|
||||||
pic_url: el.pic_url
|
|
||||||
}))
|
|
||||||
|
|
||||||
for (let i = 0; i < regionOption.value.length; i++) {
|
handleRiskTabChange('安全类事项')
|
||||||
const el = regionOption.value[i];
|
|
||||||
if (el.code == query.campus_id && el.pic_url) {
|
// 先检查缓存
|
||||||
backgroundImage.value = el.pic_url
|
const cachedRecords = getCachedRegionOption()
|
||||||
|
let records = cachedRecords
|
||||||
|
|
||||||
|
if (!records || records.length === 0) {
|
||||||
|
// 缓存不存在或已过期,调用接口
|
||||||
|
try {
|
||||||
|
let result = await getTableList('park_info_list', {}, false, { signal: abortController.signal })
|
||||||
|
records = result.records || []
|
||||||
|
|
||||||
|
if (records && records.length > 0) {
|
||||||
|
// 保存到缓存
|
||||||
|
setCachedRegionOption(records)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('初始化园区数据失败:', error)
|
||||||
|
records = []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// 初始化数据
|
if (records && records.length > 0) {
|
||||||
await loadDashboardData()
|
// 更新为新的数据格式
|
||||||
|
regionOption.value = records.map(el => ({
|
||||||
|
name: el.park_name,
|
||||||
|
code: el.park_code,
|
||||||
|
pic_url: el.pic_url
|
||||||
|
}))
|
||||||
|
|
||||||
|
for (let i = 0; i < regionOption.value.length; i++) {
|
||||||
|
const el = regionOption.value[i];
|
||||||
|
if (el.code == query.campus_id && el.pic_url) {
|
||||||
|
backgroundImage.value = el.pic_url
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 初始化数据
|
||||||
|
await loadDashboardData()
|
||||||
|
|
||||||
// 添加周期性动画演示
|
// 添加周期性动画演示
|
||||||
dashboardTimerId.value = setInterval(async () => {
|
dashboardTimerId.value = setInterval(async () => {
|
||||||
await loadDashboardData()
|
try {
|
||||||
|
await loadDashboardData()
|
||||||
|
} catch (error) {
|
||||||
|
console.error('定时数据更新失败:', error)
|
||||||
|
}
|
||||||
}, 2 * 60 * 1000) // 每2分钟更新一次
|
}, 2 * 60 * 1000) // 每2分钟更新一次
|
||||||
|
} catch (error) {
|
||||||
|
console.error('页面初始化失败:', error)
|
||||||
|
// 即使出错也要隐藏骨架屏,避免界面一直处于加载状态
|
||||||
|
setTimeout(() => {
|
||||||
|
if (isFirstLoading.value) {
|
||||||
|
isFirstLoading.value = false
|
||||||
|
console.log('因错误隐藏骨架屏')
|
||||||
|
}
|
||||||
|
}, 1000)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const loadDashboardData = () => {
|
const loadDashboardData = () => {
|
||||||
@@ -808,7 +870,7 @@ const loadDashboardData = () => {
|
|||||||
isFirstLoad.value = false
|
isFirstLoad.value = false
|
||||||
}
|
}
|
||||||
// 获取总体概览数据
|
// 获取总体概览数据
|
||||||
getTableList('generalTotal', query).then(generalTotal => {
|
getTableList('generalTotal', query, false, { signal: abortController.signal }).then(generalTotal => {
|
||||||
if (generalTotal.records && generalTotal.records.length > 0) {
|
if (generalTotal.records && generalTotal.records.length > 0) {
|
||||||
mockData.totalCount = Number(generalTotal.records[0].totalCount)
|
mockData.totalCount = Number(generalTotal.records[0].totalCount)
|
||||||
mockData.formalEmployeeCount = Number(generalTotal.records[0].formalEmployeeCount)
|
mockData.formalEmployeeCount = Number(generalTotal.records[0].formalEmployeeCount)
|
||||||
@@ -916,7 +978,7 @@ const loadDashboardData = () => {
|
|||||||
handleTabClick("高危作业")
|
handleTabClick("高危作业")
|
||||||
|
|
||||||
// 获取风险预警数据
|
// 获取风险预警数据
|
||||||
getTableList('risk_alert_data', query).then(risk_alert_data => {
|
getTableList('risk_alert_data', query, false, { signal: abortController.signal }).then(risk_alert_data => {
|
||||||
if (risk_alert_data.records && risk_alert_data.records.length > 0) {
|
if (risk_alert_data.records && risk_alert_data.records.length > 0) {
|
||||||
mockData.alertData.total = risk_alert_data.records[0].total
|
mockData.alertData.total = risk_alert_data.records[0].total
|
||||||
mockData.alertData.processed = risk_alert_data.records[0].processed
|
mockData.alertData.processed = risk_alert_data.records[0].processed
|
||||||
@@ -927,7 +989,7 @@ const loadDashboardData = () => {
|
|||||||
console.error('获取风险预警数据失败:', error)
|
console.error('获取风险预警数据失败:', error)
|
||||||
})
|
})
|
||||||
// 获取风险预警详情数据
|
// 获取风险预警详情数据
|
||||||
getTableList('risk_alert_detail', query).then(risk_alert_detail => {
|
getTableList('risk_alert_detail', query, false, { signal: abortController.signal }).then(risk_alert_detail => {
|
||||||
if (risk_alert_detail.records && risk_alert_detail.records.length > 0) {
|
if (risk_alert_detail.records && risk_alert_detail.records.length > 0) {
|
||||||
mockData.alertData.details = risk_alert_detail.records
|
mockData.alertData.details = risk_alert_detail.records
|
||||||
}
|
}
|
||||||
@@ -936,7 +998,7 @@ const loadDashboardData = () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// 获取超期工单数据
|
// 获取超期工单数据
|
||||||
getTableList('timeout_work_order', query).then(timeout_work_order => {
|
getTableList('timeout_work_order', query, false, { signal: abortController.signal }).then(timeout_work_order => {
|
||||||
if (timeout_work_order.records && timeout_work_order.records.length >= 0) {
|
if (timeout_work_order.records && timeout_work_order.records.length >= 0) {
|
||||||
mockData.timeoutWorkOrders.total = timeout_work_order.records.length
|
mockData.timeoutWorkOrders.total = timeout_work_order.records.length
|
||||||
mockData.timeoutWorkOrders.details = timeout_work_order.records
|
mockData.timeoutWorkOrders.details = timeout_work_order.records
|
||||||
@@ -946,7 +1008,7 @@ const loadDashboardData = () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// 获取超期工单数据
|
// 获取超期工单数据
|
||||||
getTableList('park_build_info', query).then(res => {
|
getTableList('park_build_info', query, false, { signal: abortController.signal }).then(res => {
|
||||||
if (res.records && res.records.length > 0) {
|
if (res.records && res.records.length > 0) {
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -954,11 +1016,22 @@ const loadDashboardData = () => {
|
|||||||
console.error('获取超期工单数据失败:', error)
|
console.error('获取超期工单数据失败:', error)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 调用数据处理函数
|
||||||
handleHiddenDangerPannelData(query)
|
handleHiddenDangerPannelData(query)
|
||||||
|
|
||||||
|
// 延迟一段时间等待异步操作完成,然后隐藏骨架屏
|
||||||
|
setTimeout(() => {
|
||||||
|
if (isFirstLoading.value) {
|
||||||
|
isFirstLoading.value = false
|
||||||
|
console.log('隐藏骨架屏')
|
||||||
|
}
|
||||||
|
}, 2000) // 2秒后隐藏骨架屏
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const handleHiddenDangerPannelData = (query) => {
|
const handleHiddenDangerPannelData = async (query) => {
|
||||||
|
const promises = []
|
||||||
|
|
||||||
let _data = {
|
let _data = {
|
||||||
flag: false,
|
flag: false,
|
||||||
general: 0,
|
general: 0,
|
||||||
@@ -978,6 +1051,8 @@ const handleHiddenDangerPannelData = (query) => {
|
|||||||
processing: 0,
|
processing: 0,
|
||||||
pending: 0
|
pending: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 初始化图表
|
||||||
progressChart.value = echarts.init(progressChartRef.value)
|
progressChart.value = echarts.init(progressChartRef.value)
|
||||||
const width = progressChart.value.getWidth()
|
const width = progressChart.value.getWidth()
|
||||||
const progressOption = {
|
const progressOption = {
|
||||||
@@ -1030,12 +1105,12 @@ const handleHiddenDangerPannelData = (query) => {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
// 获取隐患排查治理数据
|
// 获取隐患排查治理数据
|
||||||
getTableList('risk_level_count', query).then(res => {
|
getTableList('risk_level_count', query, false, { signal: abortController.signal }).then(res => {
|
||||||
if (res.records && res.records.length > 0) {
|
if (res.records && res.records.length > 0) {
|
||||||
_data.general = _data.general + Number(res.records[0].general_count)
|
_data.general = _data.general + Number(res.records[0].general_count)
|
||||||
_data.major = _data.major + Number(res.records[0].major_count)
|
_data.major = _data.major + Number(res.records[0].major_count)
|
||||||
// 获取隐患排查治理数据
|
// 获取隐患排查治理数据
|
||||||
getTableList('risk_status_count', query).then(res => {
|
getTableList('risk_status_count', query, false, { signal: abortController.signal }).then(res => {
|
||||||
if (res.records && res.records.length > 0) {
|
if (res.records && res.records.length > 0) {
|
||||||
// 接口返回的已经是百分比,直接使用
|
// 接口返回的已经是百分比,直接使用
|
||||||
const record = res.records[0]
|
const record = res.records[0]
|
||||||
@@ -1109,13 +1184,13 @@ const handleHiddenDangerPannelData = (query) => {
|
|||||||
|
|
||||||
|
|
||||||
// 获取隐患排查治理数据
|
// 获取隐患排查治理数据
|
||||||
getTableList('hidden_danger_investigation', query).then(res => {
|
getTableList('hidden_danger_investigation', query, false, { signal: abortController.signal }).then(res => {
|
||||||
if (res.records && res.records.length > 0) {
|
if (res.records && res.records.length > 0) {
|
||||||
_data2.general = Number(res.records[0].general)
|
_data2.general = Number(res.records[0].general)
|
||||||
_data2.major = Number(res.records[0].major)
|
_data2.major = Number(res.records[0].major)
|
||||||
|
|
||||||
// 获取隐患排查治理处理进度数据
|
// 获取隐患排查治理处理进度数据
|
||||||
getTableList('hidden_danger_process_progress', query).then(res => {
|
getTableList('hidden_danger_process_progress', query, false, { signal: abortController.signal }).then(res => {
|
||||||
// if (res.records && res.records.length > 0) {
|
// if (res.records && res.records.length > 0) {
|
||||||
// _data2.flag = true
|
// _data2.flag = true
|
||||||
// _data2.overdue = Number(res.records[0].overdue) / 100 * (_data2.general + _data2.major)
|
// _data2.overdue = Number(res.records[0].overdue) / 100 * (_data2.general + _data2.major)
|
||||||
@@ -1190,12 +1265,12 @@ const handleTabClick = async (tab: string) => {
|
|||||||
code = "fire_drill"
|
code = "fire_drill"
|
||||||
code1 = "fire_drill_detail"
|
code1 = "fire_drill_detail"
|
||||||
|
|
||||||
getDangerDetail(query.campus_id).then(res => {
|
getDangerDetail(query.campus_id, { signal: abortController.signal }).then(res => {
|
||||||
const list = res.records.map((item: any) => ({ description: item.contenttext }))
|
const list = res.records.map((item: any) => ({ description: item.contenttext }))
|
||||||
dangerList.value = list
|
dangerList.value = list
|
||||||
})
|
})
|
||||||
|
|
||||||
getDangerCount(query.campus_id).then(res => {
|
getDangerCount(query.campus_id, { signal: abortController.signal }).then(res => {
|
||||||
unfinishedCount.value = res.records[0].wks
|
unfinishedCount.value = res.records[0].wks
|
||||||
inProgressCount.value = res.records[0].jxz
|
inProgressCount.value = res.records[0].jxz
|
||||||
finishedCount.value = res.records[0].ywc
|
finishedCount.value = res.records[0].ywc
|
||||||
@@ -1206,7 +1281,7 @@ const handleTabClick = async (tab: string) => {
|
|||||||
code = 'security_training_count'
|
code = 'security_training_count'
|
||||||
code1 = 'security_training_detail'
|
code1 = 'security_training_detail'
|
||||||
|
|
||||||
const res = await getExamDetail(query.campus_id)
|
const res = await getExamDetail(query.campus_id, { signal: abortController.signal })
|
||||||
|
|
||||||
examList.value = res.records
|
examList.value = res.records
|
||||||
|
|
||||||
@@ -1215,7 +1290,7 @@ const handleTabClick = async (tab: string) => {
|
|||||||
code = 'security_training_count'
|
code = 'security_training_count'
|
||||||
code1 = 'security_training_detail'
|
code1 = 'security_training_detail'
|
||||||
|
|
||||||
const res1 = await getDrillDetail(query.campus_id)
|
const res1 = await getDrillDetail(query.campus_id, { signal: abortController.signal })
|
||||||
|
|
||||||
drillList.value = res1.records
|
drillList.value = res1.records
|
||||||
|
|
||||||
@@ -1363,6 +1438,9 @@ const updateTime = (): void => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
|
// 取消所有正在进行的请求
|
||||||
|
abortController.abort()
|
||||||
|
|
||||||
if (dashboardTimerId.value) {
|
if (dashboardTimerId.value) {
|
||||||
clearInterval(dashboardTimerId.value)
|
clearInterval(dashboardTimerId.value)
|
||||||
dashboardTimerId.value = null
|
dashboardTimerId.value = null
|
||||||
@@ -2075,4 +2153,44 @@ onUnmounted(() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 骨架屏样式
|
||||||
|
.skeleton-pulse {
|
||||||
|
animation: skeleton-loading-company 1.5s ease-in-out infinite;
|
||||||
|
background-color: #444;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-number-wrapper {
|
||||||
|
display: flex;
|
||||||
|
gap: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-number {
|
||||||
|
width: 14px;
|
||||||
|
height: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-type-number {
|
||||||
|
width: 14px;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-chart {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
min-height: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes skeleton-loading-company {
|
||||||
|
0% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
opacity: 0.4;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -55,6 +55,9 @@
|
|||||||
import {getTableList, getTableData, getWorkOrderStatistics} from './report'
|
import {getTableList, getTableData, getWorkOrderStatistics} from './report'
|
||||||
import {ref, reactive, onMounted, watch, onUnmounted} from 'vue'
|
import {ref, reactive, onMounted, watch, onUnmounted} from 'vue'
|
||||||
import {useRouter} from 'vue-router'
|
import {useRouter} from 'vue-router'
|
||||||
|
|
||||||
|
// 创建 AbortController 用于取消请求
|
||||||
|
const abortController = new AbortController()
|
||||||
import HeaderSelector from './components/HeaderSelector.vue'
|
import HeaderSelector from './components/HeaderSelector.vue'
|
||||||
import WeatherWarning from './components/WeatherWarning.vue'
|
import WeatherWarning from './components/WeatherWarning.vue'
|
||||||
import {getDashboardData, getAlertDetails, type DashboardData} from '@/api/dashboard'
|
import {getDashboardData, getAlertDetails, type DashboardData} from '@/api/dashboard'
|
||||||
@@ -270,7 +273,7 @@ onMounted(async () => {
|
|||||||
if (!records || records.length === 0) {
|
if (!records || records.length === 0) {
|
||||||
// 缓存不存在或已过期,调用接口
|
// 缓存不存在或已过期,调用接口
|
||||||
try {
|
try {
|
||||||
let result = await getTableList('park_info_list')
|
let result = await getTableList('park_info_list', {}, false, { signal: abortController.signal })
|
||||||
records = result.records || []
|
records = result.records || []
|
||||||
|
|
||||||
if (records && records.length > 0) {
|
if (records && records.length > 0) {
|
||||||
@@ -320,8 +323,11 @@ onMounted(async () => {
|
|||||||
}, 2 * 60 * 1000) // 每2分钟更新一次
|
}, 2 * 60 * 1000) // 每2分钟更新一次
|
||||||
})
|
})
|
||||||
|
|
||||||
// 组件卸载时清理定时器
|
// 组件卸载时清理定时器并取消所有请求
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
|
// 取消所有正在进行的请求
|
||||||
|
abortController.abort()
|
||||||
|
|
||||||
if (dashboardTimerId.value) {
|
if (dashboardTimerId.value) {
|
||||||
clearInterval(dashboardTimerId.value)
|
clearInterval(dashboardTimerId.value)
|
||||||
dashboardTimerId.value = null
|
dashboardTimerId.value = null
|
||||||
@@ -356,7 +362,7 @@ const loadDashboardData = async (): Promise<void> => {
|
|||||||
|
|
||||||
// 获取总体概览数据
|
// 获取总体概览数据
|
||||||
promises.push(
|
promises.push(
|
||||||
getTableList('generalTotal', query).then(generalTotal => {
|
getTableList('generalTotal', query, false, { signal: abortController.signal }).then(generalTotal => {
|
||||||
if (generalTotal.records && generalTotal.records.length > 0) {
|
if (generalTotal.records && generalTotal.records.length > 0) {
|
||||||
dashboardData.value.totalCount = Number(generalTotal.records[0].totalCount)
|
dashboardData.value.totalCount = Number(generalTotal.records[0].totalCount)
|
||||||
dashboardData.value.formalEmployeeCount = Number(generalTotal.records[0].formalEmployeeCount)
|
dashboardData.value.formalEmployeeCount = Number(generalTotal.records[0].formalEmployeeCount)
|
||||||
@@ -376,7 +382,7 @@ const loadDashboardData = async (): Promise<void> => {
|
|||||||
|
|
||||||
// 获取各园区统计数据
|
// 获取各园区统计数据
|
||||||
promises.push(
|
promises.push(
|
||||||
getTableList('parkscreen_user_info', query).then(parkscreen_user_info => {
|
getTableList('parkscreen_user_info', query, false, { signal: abortController.signal }).then(parkscreen_user_info => {
|
||||||
if (parkscreen_user_info.records && parkscreen_user_info.records.length > 0) {
|
if (parkscreen_user_info.records && parkscreen_user_info.records.length > 0) {
|
||||||
dashboardData.value.parkStatistics = parkscreen_user_info.records.map(el => {
|
dashboardData.value.parkStatistics = parkscreen_user_info.records.map(el => {
|
||||||
return {
|
return {
|
||||||
@@ -394,7 +400,7 @@ const loadDashboardData = async (): Promise<void> => {
|
|||||||
|
|
||||||
// 获取风险预警数据
|
// 获取风险预警数据
|
||||||
promises.push(
|
promises.push(
|
||||||
getTableList('risk_alert_data', query).then(risk_alert_data => {
|
getTableList('risk_alert_data', query, false, { signal: abortController.signal }).then(risk_alert_data => {
|
||||||
if (risk_alert_data.records && risk_alert_data.records.length > 0) {
|
if (risk_alert_data.records && risk_alert_data.records.length > 0) {
|
||||||
dashboardData.value.alertData.total = risk_alert_data.records[0].total
|
dashboardData.value.alertData.total = risk_alert_data.records[0].total
|
||||||
dashboardData.value.alertData.processed = risk_alert_data.records[0].processed
|
dashboardData.value.alertData.processed = risk_alert_data.records[0].processed
|
||||||
@@ -408,7 +414,7 @@ const loadDashboardData = async (): Promise<void> => {
|
|||||||
|
|
||||||
// 获取风险预警详情数据
|
// 获取风险预警详情数据
|
||||||
promises.push(
|
promises.push(
|
||||||
getTableList('risk_alert_detail', query).then(risk_alert_detail => {
|
getTableList('risk_alert_detail', query, false, { signal: abortController.signal }).then(risk_alert_detail => {
|
||||||
if (risk_alert_detail.records && risk_alert_detail.records.length > 0) {
|
if (risk_alert_detail.records && risk_alert_detail.records.length > 0) {
|
||||||
dashboardData.value.alertData.details = risk_alert_detail.records
|
dashboardData.value.alertData.details = risk_alert_detail.records
|
||||||
}
|
}
|
||||||
@@ -419,7 +425,7 @@ const loadDashboardData = async (): Promise<void> => {
|
|||||||
|
|
||||||
// 获取超期工单数据
|
// 获取超期工单数据
|
||||||
promises.push(
|
promises.push(
|
||||||
getTableList('timeout_work_order', query).then(timeout_work_order => {
|
getTableList('timeout_work_order', query, false, { signal: abortController.signal }).then(timeout_work_order => {
|
||||||
if (timeout_work_order.records && timeout_work_order.records.length >= 0) {
|
if (timeout_work_order.records && timeout_work_order.records.length >= 0) {
|
||||||
dashboardData.value.timeoutWorkOrders.total = timeout_work_order.records.length
|
dashboardData.value.timeoutWorkOrders.total = timeout_work_order.records.length
|
||||||
dashboardData.value.timeoutWorkOrders.details = timeout_work_order.records
|
dashboardData.value.timeoutWorkOrders.details = timeout_work_order.records
|
||||||
@@ -463,12 +469,12 @@ const handleHiddenDangerPannelData = async (query) => {
|
|||||||
|
|
||||||
// 获取隐患排查治理数据 - 系统数据
|
// 获取隐患排查治理数据 - 系统数据
|
||||||
promises.push(
|
promises.push(
|
||||||
getTableList('risk_level_count', query).then(res => {
|
getTableList('risk_level_count', query, false, { signal: abortController.signal }).then(res => {
|
||||||
if (res.records && res.records.length > 0) {
|
if (res.records && res.records.length > 0) {
|
||||||
dashboardData.value.hiddenDangerData.general = Number(res.records[0].general_count)
|
dashboardData.value.hiddenDangerData.general = Number(res.records[0].general_count)
|
||||||
dashboardData.value.hiddenDangerData.major = Number(res.records[0].major_count)
|
dashboardData.value.hiddenDangerData.major = Number(res.records[0].major_count)
|
||||||
}
|
}
|
||||||
return getTableList('risk_status_count', query)
|
return getTableList('risk_status_count', query, false, { signal: abortController.signal })
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
if (res.records && res.records.length > 0) {
|
if (res.records && res.records.length > 0) {
|
||||||
const record = res.records[0]
|
const record = res.records[0]
|
||||||
@@ -486,10 +492,10 @@ const handleHiddenDangerPannelData = async (query) => {
|
|||||||
|
|
||||||
// 获取第三方隐患排查治理数据
|
// 获取第三方隐患排查治理数据
|
||||||
promises.push(
|
promises.push(
|
||||||
getTableList('hidden_danger_investigation', query).then(res => {
|
getTableList('hidden_danger_investigation', query, false, { signal: abortController.signal }).then(res => {
|
||||||
if (res.records && res.records.length > 0) {
|
if (res.records && res.records.length > 0) {
|
||||||
// 获取安全指数
|
// 获取安全指数
|
||||||
return getTableList('hidden_danger_safety_index', query)
|
return getTableList('hidden_danger_safety_index', query, false, { signal: abortController.signal })
|
||||||
}
|
}
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
if (res.records && res.records.length > 0) {
|
if (res.records && res.records.length > 0) {
|
||||||
@@ -502,7 +508,7 @@ const handleHiddenDangerPannelData = async (query) => {
|
|||||||
|
|
||||||
// 获取隐患排查治理TOP3类型数据
|
// 获取隐患排查治理TOP3类型数据
|
||||||
promises.push(
|
promises.push(
|
||||||
getTableList('hidden_danger_top', query).then(hidden_danger_top => {
|
getTableList('hidden_danger_top', query, false, { signal: abortController.signal }).then(hidden_danger_top => {
|
||||||
if (hidden_danger_top.records && hidden_danger_top.records.length > 0) {
|
if (hidden_danger_top.records && hidden_danger_top.records.length > 0) {
|
||||||
dashboardData.value.hiddenDangerData.top3Types = hidden_danger_top.records
|
dashboardData.value.hiddenDangerData.top3Types = hidden_danger_top.records
|
||||||
}
|
}
|
||||||
@@ -544,7 +550,7 @@ const handleRiskTabChange = async (tab: TabType | '安全类事项' | '工程类
|
|||||||
workOrderType,
|
workOrderType,
|
||||||
taskType: '维保任务',
|
taskType: '维保任务',
|
||||||
campus_id: query.campus_id
|
campus_id: query.campus_id
|
||||||
}).catch(error => {
|
}, { signal: abortController.signal }).catch(error => {
|
||||||
console.error('获取维保任务数据失败:', error)
|
console.error('获取维保任务数据失败:', error)
|
||||||
return {records: []}
|
return {records: []}
|
||||||
}),
|
}),
|
||||||
@@ -552,7 +558,7 @@ const handleRiskTabChange = async (tab: TabType | '安全类事项' | '工程类
|
|||||||
workOrderType,
|
workOrderType,
|
||||||
taskType: '巡检任务',
|
taskType: '巡检任务',
|
||||||
campus_id: query.campus_id
|
campus_id: query.campus_id
|
||||||
}).catch(error => {
|
}, { signal: abortController.signal }).catch(error => {
|
||||||
console.error('获取巡检任务数据失败:', error)
|
console.error('获取巡检任务数据失败:', error)
|
||||||
return {records: []}
|
return {records: []}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -26,26 +26,29 @@
|
|||||||
<!-- 主内容区 -->
|
<!-- 主内容区 -->
|
||||||
<div class="content-container">
|
<div class="content-container">
|
||||||
<div class="left-wrapper">
|
<div class="left-wrapper">
|
||||||
<OverviewPanel :totalCount="dashboardData?.totalCount || 0"
|
<OverviewPanel :loading="isFirstLoading"
|
||||||
|
:totalCount="dashboardData?.totalCount || 0"
|
||||||
:formalEmployeeCount="dashboardData?.formalEmployeeCount || 0"
|
:formalEmployeeCount="dashboardData?.formalEmployeeCount || 0"
|
||||||
:externalStaffCount="dashboardData?.externalStaffCount || 0"
|
:externalStaffCount="dashboardData?.externalStaffCount || 0"
|
||||||
:visitorCount="dashboardData?.visitorCount || 0"
|
:visitorCount="dashboardData?.visitorCount || 0"
|
||||||
:parkStatistics="dashboardData?.parkStatistics"/>
|
:parkStatistics="dashboardData?.parkStatistics"/>
|
||||||
<RiskStatisticsPanel :riskStatistics="riskStatistics" :dangerDetail="dangerDetail"
|
<RiskStatisticsPanel :loading="isFirstLoading" :riskStatistics="riskStatistics" :dangerDetail="dangerDetail"
|
||||||
:park="parkValue"
|
:park="parkValue"
|
||||||
@tab-change="handleRiskTabChange" :campus_id="query.campus_id"/>
|
@tab-change="handleRiskTabChange" :campus_id="query.campus_id"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="right-wrapper">
|
<div class="right-wrapper">
|
||||||
<HighRiskAlertPanel :alertData="dashboardData?.alertData"
|
<HighRiskAlertPanel :loading="isFirstLoading"
|
||||||
|
:alertData="dashboardData?.alertData"
|
||||||
:alertDetails="dashboardData?.alertData.details"
|
:alertDetails="dashboardData?.alertData.details"
|
||||||
linkUrl="http://10.0.64.20/security/console/command-center?p=tabl"
|
linkUrl="http://10.0.64.20/security/console/command-center?p=tabl"
|
||||||
:sourceIndex="sourceIndex"/>
|
:sourceIndex="sourceIndex"/>
|
||||||
<TimeoutWorkOrderPanel :timeoutWorkOrders="dashboardData?.timeoutWorkOrders"
|
<TimeoutWorkOrderPanel :loading="isFirstLoading"
|
||||||
|
:timeoutWorkOrders="dashboardData?.timeoutWorkOrders"
|
||||||
:alertDetails="dashboardData?.timeoutWorkOrders.details"
|
:alertDetails="dashboardData?.timeoutWorkOrders.details"
|
||||||
linkUrl="http://10.0.64.20/pms/workorder-list"
|
linkUrl="http://10.0.64.20/pms/workorder-list"
|
||||||
:sourceIndex="sourceIndex"/>
|
:sourceIndex="sourceIndex"/>
|
||||||
</div>
|
</div>
|
||||||
<HiddenDangerPanel :hiddenDangerData="dashboardData?.hiddenDangerData"/>
|
<HiddenDangerPanel :loading="isFirstLoading" :hiddenDangerData="dashboardData?.hiddenDangerData"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -55,6 +58,9 @@
|
|||||||
import {getTableList, getTableData, getWorkOrderStatistics} from './report'
|
import {getTableList, getTableData, getWorkOrderStatistics} from './report'
|
||||||
import {ref, onMounted, watch, onUnmounted} from 'vue'
|
import {ref, onMounted, watch, onUnmounted} from 'vue'
|
||||||
import {useRoute, useRouter} from 'vue-router'
|
import {useRoute, useRouter} from 'vue-router'
|
||||||
|
|
||||||
|
// 创建 AbortController 用于取消请求
|
||||||
|
const abortController = new AbortController()
|
||||||
import HeaderSelector from './components/HeaderSelector.vue'
|
import HeaderSelector from './components/HeaderSelector.vue'
|
||||||
import WeatherWarning from './components/WeatherWarning.vue'
|
import WeatherWarning from './components/WeatherWarning.vue'
|
||||||
import {getDashboardData, getAlertDetails, type DashboardData} from '@/api/dashboard'
|
import {getDashboardData, getAlertDetails, type DashboardData} from '@/api/dashboard'
|
||||||
@@ -106,6 +112,9 @@ const dangerDetail = ref<any>()
|
|||||||
const isAnimating = ref<boolean>(false)
|
const isAnimating = ref<boolean>(false)
|
||||||
const animationDuration = 2000 // 动画持续时间(毫秒)
|
const animationDuration = 2000 // 动画持续时间(毫秒)
|
||||||
|
|
||||||
|
// 首次加载状态
|
||||||
|
const isFirstLoading = ref<boolean>(true)
|
||||||
|
|
||||||
// 数字变化时的闪烁效果
|
// 数字变化时的闪烁效果
|
||||||
const flashNumbers = () => {
|
const flashNumbers = () => {
|
||||||
const numberElements = document.querySelectorAll('.total-number, .type-number')
|
const numberElements = document.querySelectorAll('.total-number, .type-number')
|
||||||
@@ -278,7 +287,7 @@ onMounted(async () => {
|
|||||||
if (!records || records.length === 0) {
|
if (!records || records.length === 0) {
|
||||||
// 缓存不存在或已过期,调用接口
|
// 缓存不存在或已过期,调用接口
|
||||||
try {
|
try {
|
||||||
let result = await getTableList('park_info_list')
|
let result = await getTableList('park_info_list', {}, false, { signal: abortController.signal })
|
||||||
records = result.records || []
|
records = result.records || []
|
||||||
|
|
||||||
if (records && records.length > 0) {
|
if (records && records.length > 0) {
|
||||||
@@ -327,8 +336,11 @@ onMounted(async () => {
|
|||||||
}, 2 * 60 * 1000) // 每2分钟更新一次
|
}, 2 * 60 * 1000) // 每2分钟更新一次
|
||||||
})
|
})
|
||||||
|
|
||||||
// 组件卸载时清理定时器
|
// 组件卸载时清理定时器并取消所有请求
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
|
// 取消所有正在进行的请求
|
||||||
|
abortController.abort()
|
||||||
|
|
||||||
if (dashboardTimerId.value) {
|
if (dashboardTimerId.value) {
|
||||||
clearInterval(dashboardTimerId.value)
|
clearInterval(dashboardTimerId.value)
|
||||||
dashboardTimerId.value = null
|
dashboardTimerId.value = null
|
||||||
@@ -355,7 +367,7 @@ const loadDashboardData = async (): Promise<void> => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// 获取总体概览数据
|
// 获取总体概览数据
|
||||||
getTableList('generalTotal', query).then(generalTotal => {
|
getTableList('generalTotal', query, false, { signal: abortController.signal }).then(generalTotal => {
|
||||||
if (generalTotal.records && generalTotal.records.length > 0) {
|
if (generalTotal.records && generalTotal.records.length > 0) {
|
||||||
dashboardData.value.totalCount = generalTotal.records.reduce((sum, item) => sum + Number(item.totalCount || 0), 0)
|
dashboardData.value.totalCount = generalTotal.records.reduce((sum, item) => sum + Number(item.totalCount || 0), 0)
|
||||||
dashboardData.value.formalEmployeeCount = generalTotal.records.reduce((sum, item) => sum + Number(item.formalEmployeeCount || 0), 0)
|
dashboardData.value.formalEmployeeCount = generalTotal.records.reduce((sum, item) => sum + Number(item.formalEmployeeCount || 0), 0)
|
||||||
@@ -375,7 +387,7 @@ const loadDashboardData = async (): Promise<void> => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// 获取各园区统计数据
|
// 获取各园区统计数据
|
||||||
getTableList('parkscreen_user_info', query).then(parkscreen_user_info => {
|
getTableList('parkscreen_user_info', query, false, { signal: abortController.signal }).then(parkscreen_user_info => {
|
||||||
if (parkscreen_user_info.records && parkscreen_user_info.records.length > 0) {
|
if (parkscreen_user_info.records && parkscreen_user_info.records.length > 0) {
|
||||||
dashboardData.value.parkStatistics = parkscreen_user_info.records.map(el => {
|
dashboardData.value.parkStatistics = parkscreen_user_info.records.map(el => {
|
||||||
return {
|
return {
|
||||||
@@ -393,7 +405,7 @@ const loadDashboardData = async (): Promise<void> => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// 获取风险预警数据
|
// 获取风险预警数据
|
||||||
getTableList('risk_alert_data', query).then(risk_alert_data => {
|
getTableList('risk_alert_data', query, false, { signal: abortController.signal }).then(risk_alert_data => {
|
||||||
if (risk_alert_data.records && risk_alert_data.records.length > 0) {
|
if (risk_alert_data.records && risk_alert_data.records.length > 0) {
|
||||||
dashboardData.value.alertData.total = risk_alert_data.records.reduce((sum, item) => sum + Number(item.total || 0), 0)
|
dashboardData.value.alertData.total = risk_alert_data.records.reduce((sum, item) => sum + Number(item.total || 0), 0)
|
||||||
dashboardData.value.alertData.processed = risk_alert_data.records.reduce((sum, item) => sum + Number(item.processed || 0), 0)
|
dashboardData.value.alertData.processed = risk_alert_data.records.reduce((sum, item) => sum + Number(item.processed || 0), 0)
|
||||||
@@ -409,7 +421,7 @@ const loadDashboardData = async (): Promise<void> => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// 获取风险预警详情数据
|
// 获取风险预警详情数据
|
||||||
getTableList('risk_alert_detail', query).then(risk_alert_detail => {
|
getTableList('risk_alert_detail', query, false, { signal: abortController.signal }).then(risk_alert_detail => {
|
||||||
// if (risk_alert_detail.records && risk_alert_detail.records.length > 0) {
|
// if (risk_alert_detail.records && risk_alert_detail.records.length > 0) {
|
||||||
dashboardData.value.alertData.details = risk_alert_detail.records || []
|
dashboardData.value.alertData.details = risk_alert_detail.records || []
|
||||||
// }
|
// }
|
||||||
@@ -422,7 +434,7 @@ const loadDashboardData = async (): Promise<void> => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// 获取超期工单数据
|
// 获取超期工单数据
|
||||||
getTableList('timeout_work_order', query).then(timeout_work_order => {
|
getTableList('timeout_work_order', query, false, { signal: abortController.signal }).then(timeout_work_order => {
|
||||||
if (timeout_work_order.records && timeout_work_order.records.length >= 0) {
|
if (timeout_work_order.records && timeout_work_order.records.length >= 0) {
|
||||||
dashboardData.value.timeoutWorkOrders.total = timeout_work_order.records.length
|
dashboardData.value.timeoutWorkOrders.total = timeout_work_order.records.length
|
||||||
dashboardData.value.timeoutWorkOrders.details = timeout_work_order.records
|
dashboardData.value.timeoutWorkOrders.details = timeout_work_order.records
|
||||||
@@ -461,12 +473,12 @@ const handleHiddenDangerPannelData = (query) => {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
// 获取隐患排查治理数据
|
// 获取隐患排查治理数据
|
||||||
getTableList('risk_level_count', query).then(res => {
|
getTableList('risk_level_count', query, false, { signal: abortController.signal }).then(res => {
|
||||||
if (res.records && res.records.length > 0) {
|
if (res.records && res.records.length > 0) {
|
||||||
_data.general = _data.general + Number(res.records[0].general_count)
|
_data.general = _data.general + Number(res.records[0].general_count)
|
||||||
_data.major = _data.major + Number(res.records[0].major_count)
|
_data.major = _data.major + Number(res.records[0].major_count)
|
||||||
// 获取隐患排查治理数据
|
// 获取隐患排查治理数据
|
||||||
getTableList('risk_status_count', query).then(res => {
|
getTableList('risk_status_count', query, false, { signal: abortController.signal }).then(res => {
|
||||||
if (res.records && res.records.length > 0) {
|
if (res.records && res.records.length > 0) {
|
||||||
// 接口返回的已经是百分比,直接使用
|
// 接口返回的已经是百分比,直接使用
|
||||||
const record = res.records[0]
|
const record = res.records[0]
|
||||||
@@ -533,7 +545,7 @@ const handleHiddenDangerPannelData = (query) => {
|
|||||||
|
|
||||||
|
|
||||||
// 获取隐患排查治理数据
|
// 获取隐患排查治理数据
|
||||||
getTableList('hidden_danger_investigation', query).then(res => {
|
getTableList('hidden_danger_investigation', query, false, { signal: abortController.signal }).then(res => {
|
||||||
if (res.records && res.records.length > 0) {
|
if (res.records && res.records.length > 0) {
|
||||||
_data2.general = Number(res.records[0].general)
|
_data2.general = Number(res.records[0].general)
|
||||||
_data2.major = Number(res.records[0].major)
|
_data2.major = Number(res.records[0].major)
|
||||||
@@ -541,7 +553,7 @@ const handleHiddenDangerPannelData = (query) => {
|
|||||||
// 安全指数另算,再起一个报表
|
// 安全指数另算,再起一个报表
|
||||||
// dashboardData.value.hiddenDangerData.safetyIndex = res.records[0].safetyIndex
|
// dashboardData.value.hiddenDangerData.safetyIndex = res.records[0].safetyIndex
|
||||||
// 在这里添加获取安全指数的逻辑
|
// 在这里添加获取安全指数的逻辑
|
||||||
getTableList('hidden_danger_safety_index', query).then(res => {
|
getTableList('hidden_danger_safety_index', query, false, { signal: abortController.signal }).then(res => {
|
||||||
if (res.records && res.records.length > 0) {
|
if (res.records && res.records.length > 0) {
|
||||||
dashboardData.value.hiddenDangerData.safetyIndex = res.records[0].safetyIndex
|
dashboardData.value.hiddenDangerData.safetyIndex = res.records[0].safetyIndex
|
||||||
}
|
}
|
||||||
@@ -550,7 +562,7 @@ const handleHiddenDangerPannelData = (query) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// 获取隐患排查治理处理进度数据
|
// 获取隐患排查治理处理进度数据
|
||||||
getTableList('hidden_danger_process_progress', query).then(res => {
|
getTableList('hidden_danger_process_progress', query, false, { signal: abortController.signal }).then(res => {
|
||||||
// if (res.records && res.records.length > 0) {
|
// if (res.records && res.records.length > 0) {
|
||||||
// _data2.flag = true
|
// _data2.flag = true
|
||||||
// _data2.overdue = Number(res.records[0].overdue) / 100 * (_data2.general + _data2.major)
|
// _data2.overdue = Number(res.records[0].overdue) / 100 * (_data2.general + _data2.major)
|
||||||
@@ -604,7 +616,7 @@ const handleHiddenDangerPannelData = (query) => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// 获取隐患排查治理TOP3类型数据
|
// 获取隐患排查治理TOP3类型数据
|
||||||
getTableList('hidden_danger_top', query).then(res => {
|
getTableList('hidden_danger_top', query, false, { signal: abortController.signal }).then(res => {
|
||||||
if (res.records && res.records.length > 0) {
|
if (res.records && res.records.length > 0) {
|
||||||
dashboardData.value.hiddenDangerData.top3Types = res.records
|
dashboardData.value.hiddenDangerData.top3Types = res.records
|
||||||
}
|
}
|
||||||
@@ -639,7 +651,7 @@ const handleRiskTabChange = async (tab: TabType) => {
|
|||||||
workOrderType,
|
workOrderType,
|
||||||
taskType: '维保任务',
|
taskType: '维保任务',
|
||||||
campus_id: query.campus_id
|
campus_id: query.campus_id
|
||||||
}).catch(error => {
|
}, { signal: abortController.signal }).catch(error => {
|
||||||
console.error('获取维保任务数据失败:', error)
|
console.error('获取维保任务数据失败:', error)
|
||||||
return {records: []}
|
return {records: []}
|
||||||
}),
|
}),
|
||||||
@@ -647,7 +659,7 @@ const handleRiskTabChange = async (tab: TabType) => {
|
|||||||
workOrderType,
|
workOrderType,
|
||||||
taskType: '巡检任务',
|
taskType: '巡检任务',
|
||||||
campus_id: query.campus_id
|
campus_id: query.campus_id
|
||||||
}).catch(error => {
|
}, { signal: abortController.signal }).catch(error => {
|
||||||
console.error('获取巡检任务数据失败:', error)
|
console.error('获取巡检任务数据失败:', error)
|
||||||
return {records: []}
|
return {records: []}
|
||||||
})
|
})
|
||||||
@@ -727,6 +739,12 @@ const handleRiskTabChange = async (tab: TabType) => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取风险统计数据失败:', error)
|
console.error('获取风险统计数据失败:', error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 第一次加载完成后,隐藏骨架屏
|
||||||
|
if (isFirstLoading.value) {
|
||||||
|
isFirstLoading.value = false
|
||||||
|
console.log('隐藏骨架屏')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 方法定义
|
// 方法定义
|
||||||
|
|||||||
@@ -73,24 +73,24 @@ export const exportExcelData = (reportCode, data?) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//获取报表数据
|
//获取报表数据
|
||||||
export const getTableList = (reportCode, data?, isOpen?) => {
|
export const getTableList = (reportCode, data?, isOpen?, options = {}) => {
|
||||||
return request.post({ url: `/jeelowcode/${isOpen ? 'open/report' : 'report-data'}/list/${reportCode}`, data })
|
return request.post({ url: `/jeelowcode/${isOpen ? 'open/report' : 'report-data'}/list/${reportCode}`, data, ...options })
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getDangerDetail = (campus_id: string) => {
|
export const getDangerDetail = (campus_id: string, options = {}) => {
|
||||||
return request.post({ url: '/jeelowcode/report-data/list/dp_yq_danger_detail', data: {campus_id} })
|
return request.post({ url: '/jeelowcode/report-data/list/dp_yq_danger_detail', data: {campus_id}, ...options })
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getZBDangerSum = (campus_id: string) => {
|
export const getZBDangerSum = (campus_id: string) => {
|
||||||
return request.post({ url: '/jeelowcode/report-data/list/dp_zb_danger_sum', data: {campus_id} })
|
return request.post({ url: '/jeelowcode/report-data/list/dp_zb_danger_sum', data: {campus_id} })
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getDangerCount = (campus_id: string) => {
|
export const getDangerCount = (campus_id: string, options = {}) => {
|
||||||
return request.post({ url: '/jeelowcode/report-data/list/dp_yq_danger_sum', data: {campus_id} })
|
return request.post({ url: '/jeelowcode/report-data/list/dp_yq_danger_sum', data: {campus_id}, ...options })
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getExamDetail = (campus_id: string) => {
|
export const getExamDetail = (campus_id: string, options = {}) => {
|
||||||
return request.post({ url: '/jeelowcode/report-data/list/dp_yq_exam_detail', data: {campus_id} })
|
return request.post({ url: '/jeelowcode/report-data/list/dp_yq_exam_detail', data: {campus_id}, ...options })
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getExamSum = (campus_id: string) => {
|
export const getExamSum = (campus_id: string) => {
|
||||||
@@ -101,13 +101,13 @@ export const getDrillSum = (campus_id: string) => {
|
|||||||
return request.post({ url: '/jeelowcode/report-data/list/dp_zb_drill_sum', data: {campus_id} })
|
return request.post({ url: '/jeelowcode/report-data/list/dp_zb_drill_sum', data: {campus_id} })
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getDrillDetail = (campus_id: string) => {
|
export const getDrillDetail = (campus_id: string, options = {}) => {
|
||||||
return request.post({ url: '/jeelowcode/report-data/list/dp_yq_drill_detail', data: {campus_id} })
|
return request.post({ url: '/jeelowcode/report-data/list/dp_yq_drill_detail', data: {campus_id}, ...options })
|
||||||
}
|
}
|
||||||
|
|
||||||
//获取报表数据
|
//获取报表数据
|
||||||
export const getTableData = (tableId, data?) => {
|
export const getTableData = (tableId, data?, options = {}) => {
|
||||||
return request.post({ url: `/jeelowcode/dbform-data/list/${tableId}`, data })
|
return request.post({ url: `/jeelowcode/dbform-data/list/${tableId}`, data, ...options })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -135,8 +135,8 @@ export const batchGetTableList = (reportCodes: string, data?) => {
|
|||||||
// 参数:workOrderType:'物业服务-工程',taskType:'巡检任务'
|
// 参数:workOrderType:'物业服务-工程',taskType:'巡检任务'
|
||||||
// 统计周期 cycle: day,month,year 对应月日年
|
// 统计周期 cycle: day,month,year 对应月日年
|
||||||
|
|
||||||
export const getWorkOrderStatistics = (data: {workOrderType: string, taskType: string, campus_id?: string}) => {
|
export const getWorkOrderStatistics = (data: {workOrderType: string, taskType: string, campus_id?: string}, options = {}) => {
|
||||||
return request.post({ url: '/jeelowcode/report-data/list/report_work_order_statistics', data: {...data, pageNo: 1, pageSize: 10} })
|
return request.post({ url: '/jeelowcode/report-data/list/report_work_order_statistics', data: {...data, pageNo: 1, pageSize: 10}, ...options })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user