246 lines
5.5 KiB
Vue
246 lines
5.5 KiB
Vue
<template>
|
||
<div class="dashboard-container">
|
||
<!-- 顶部固定区域 -->
|
||
<div class="top-bar">
|
||
<div class="header-info">
|
||
<div>{{ currentTime }}</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 全屏地图区域(背景) -->
|
||
<div class="fullscreen-map">
|
||
<MapComponent></MapComponent>
|
||
</div>
|
||
|
||
<!-- 悬浮模块容器 -->
|
||
<div class="floating-modules">
|
||
<!-- 左侧模块组 -->
|
||
<div class="left-modules">
|
||
<div class="module-card overview-card">
|
||
<div class="module-header">设备总览</div>
|
||
<div class="module-content">
|
||
<DeviceOverview />
|
||
</div>
|
||
</div>
|
||
|
||
<div class="module-card">
|
||
<div class="module-header">设备类别</div>
|
||
<div class="module-content">
|
||
<DeviceCategory />
|
||
</div>
|
||
</div>
|
||
|
||
<div class="module-card">
|
||
<div class="module-header">设备使用频次</div>
|
||
<div class="module-content">
|
||
<DeviceUsage />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 右侧模块组 -->
|
||
<div class="right-modules">
|
||
<div class="module-card alarm-card">
|
||
<div class="module-header">报警数据</div>
|
||
<div class="module-content">
|
||
<AlarmOverview :alarmOverview="alarmOverview" />
|
||
</div>
|
||
</div>
|
||
|
||
<div class="module-card">
|
||
<div class="module-header">报警事件</div>
|
||
<div class="module-content">
|
||
<AlarmEvent :alarmOverview="alarmOverview" />
|
||
</div>
|
||
</div>
|
||
|
||
<div class="module-card">
|
||
<div class="module-header">报警次数</div>
|
||
<div class="module-content">
|
||
<AlarmCount />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 底部中间模块 -->
|
||
<div class="bottom-middle-module">
|
||
<div class="module-card realtime-card">
|
||
<div class="module-header realtime-header">实时报警信息</div>
|
||
<div class="module-content">
|
||
<RealTimeAlarm />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { getAlarmStatistics } from '@/api/homeIndex'
|
||
import DeviceOverview from './components/DeviceOverview.vue';
|
||
import AlarmOverview from './components/AlarmOverview.vue';
|
||
import DeviceCategory from './components/DeviceCategory.vue';
|
||
import DeviceUsage from './components/DeviceUsage.vue';
|
||
import AlarmEvent from './components/AlarmEvent.vue';
|
||
import AlarmCount from './components/AlarmCount.vue';
|
||
import RealTimeAlarm from './components/RealTimeAlarm.vue';
|
||
import MapComponent from './components/MapComponent.vue';
|
||
const alarmOverview = ref<any>({})
|
||
// 实时时间实现
|
||
const currentDate = ref(new Date());
|
||
// 每秒更新时间
|
||
const timer = setInterval(() => {
|
||
currentDate.value = new Date();
|
||
}, 1000);
|
||
// 组件卸载时清除定时器
|
||
onUnmounted(() => {
|
||
clearInterval(timer);
|
||
});
|
||
|
||
// 格式化时间
|
||
const currentTime = computed(() => {
|
||
const now = currentDate.value;
|
||
return `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')} ${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}:${String(now.getSeconds()).padStart(2, '0')}`;
|
||
});
|
||
// 报警事件是同一个接口,在这里调用,两个子组件直接引入
|
||
const getData = async () => {
|
||
const res = await getAlarmStatistics({})
|
||
if (res.code == 200) {
|
||
alarmOverview.value = res.data
|
||
}
|
||
}
|
||
getData()
|
||
onMounted(() => {
|
||
|
||
})
|
||
|
||
|
||
</script>
|
||
|
||
<style scoped>
|
||
.dashboard-container {
|
||
width: 100vw;
|
||
height: 100vh;
|
||
position: relative;
|
||
overflow: hidden;
|
||
}
|
||
|
||
/* 顶部栏 */
|
||
.top-bar {
|
||
position: relative;
|
||
z-index: 10;
|
||
height: 13vh;
|
||
background: url(@/assets/homeIndex/nav.png) no-repeat;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
background-size: 100% 100%;
|
||
|
||
}
|
||
|
||
.header-info {
|
||
position: absolute;
|
||
right: 6vh;
|
||
top: 3.8vh;
|
||
color: #fff;
|
||
font-size: 1.8vh;
|
||
}
|
||
|
||
/* 全屏地图 */
|
||
.fullscreen-map {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
background: radial-gradient(0% 0% at 0% 0%, #091B2D 0%, #0C2644 100%);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
/* 悬浮模块容器 */
|
||
.floating-modules {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100vw;
|
||
height: 100vh;
|
||
z-index: 5;
|
||
padding: 1.5vw;
|
||
box-sizing: border-box;
|
||
pointer-events: none;
|
||
}
|
||
|
||
/* 左侧模块组 */
|
||
.left-modules {
|
||
position: absolute;
|
||
top: 8vh;
|
||
left: 0.5vw;
|
||
display: flex;
|
||
flex-direction: column;
|
||
width: 27vw;
|
||
height: calc(100vh - 9vh);
|
||
pointer-events: auto;
|
||
}
|
||
|
||
/* 右侧模块组 */
|
||
.right-modules {
|
||
position: absolute;
|
||
top: 8vh;
|
||
right: 0.5vw;
|
||
display: flex;
|
||
flex-direction: column;
|
||
width: 27vw;
|
||
height: calc(100vh - 9vh);
|
||
pointer-events: auto;
|
||
}
|
||
|
||
/* 底部中间模块 */
|
||
.bottom-middle-module {
|
||
position: absolute;
|
||
bottom: 0.4vw;
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
width: 44vw;
|
||
height: calc(39vh - 9vh);
|
||
pointer-events: auto;
|
||
}
|
||
|
||
/* 模块卡片样式 */
|
||
.module-card {
|
||
background: url(@/assets/homeIndex/card.png) no-repeat;
|
||
position: relative;
|
||
background-size: 100% 100%;
|
||
width: 100%;
|
||
height: 100%;
|
||
box-sizing: border-box;
|
||
overflow: hidden;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
/* 模块标题 */
|
||
.module-header {
|
||
position: absolute;
|
||
font-size: 1.6vh;
|
||
color: #fff;
|
||
display: flex;
|
||
align-items: center;
|
||
flex-shrink: 0;
|
||
left: 5vh;
|
||
top: 3.2vh;
|
||
|
||
}
|
||
|
||
.realtime-header {
|
||
left: 8vh;
|
||
top: 3.4vh;
|
||
}
|
||
|
||
/* 模块内容 */
|
||
.module-content {
|
||
position: relative;
|
||
}
|
||
</style>
|