You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

274 lines
6.6 KiB

2 weeks ago
<template>
<OpenLayerMap
class="w-full map-container"
v-if="inited"
:showDrawFences="false"
:showTrajectories="false"
:markers="markers"
:fences="fences"
/>
<div class="top-panel" v-show="!appStore.mobile">
<div class="top-panel__left">
<div class="search-group">
<el-input v-model="search" class="search-input" placeholder="请输入关键词" />
</div>
<!-- <div>
<el-checkbox-group v-model="openFences">
<el-checkbox label="显示电子围栏" value="1" />
</el-checkbox-group>
</div> -->
</div>
<div class="top-panel__center">
<div class="data_item">
<span class="data_item__title">手持设备</span>
<span class="data_item__value">{{ handDetectorCount }}</span>
<span class="data_item__unit"></span>
</div>
<div class="data_item">
<span class="data_item__title">在线数量</span>
<span class="data_item__value">{{ onlineCount }}</span>
<span class="data_item__unit"></span>
</div>
</div>
<div class="top-panel__right">
<span class="legend-title">报警图例</span>
<div class="normal-legend">正常状态</div>
<div class="alarm1-legend">围栏报警</div>
<div class="alarm2-legend">气体报警</div>
</div>
</div>
2 weeks ago
</template>
<script lang="ts" setup>
import OpenLayerMap from './components/OpenLayerMap.vue'
import { getLastestDetectorData } from '@/api/gas'
1 week ago
import { HandDetectorData } from '@/api/gas/handdetector'
import { MarkerData, FenceData } from './components/types/map.types'
import { useAppStore } from '@/store/modules/app'
import { useHandDetectorStore } from '@/store/modules/handDetector'
import dayjs from 'dayjs'
const appStore = useAppStore()
const handDetectorStore = useHandDetectorStore() // 手持探测器 store
2 weeks ago
const getDataTimer = ref<NodeJS.Timeout | null>(null)
const markers = ref<MarkerData[]>([])
1 week ago
const fences = ref<FenceData[]>([])
2 weeks ago
const inited = ref(false)
const search = ref('')
// 手持设备数量
const handDetectorCount = computed(() => markers.value.length)
const onlineCount = computed(() => markers.value.filter((item) => item.onlineStatus === 1).length)
2 weeks ago
const getMarkers = async () => {
console.log('getMarkers')
1 week ago
return await getLastestDetectorData().then((res: HandDetectorData[]) => {
2 weeks ago
res = res.filter((i) => i.enableStatus === 1)
var res2 = res.map((i) => {
2 weeks ago
return {
...i,
coordinates: [i.longitude, i.latitude],
data: [],
time: i.time ? dayjs(i.time).format('YYYY-MM-DD HH:mm:ss') : '',
value: i.value,
1 week ago
unit: i.unit,
gasStatus: i.gasStatus, //气体报警状态
batteryStatus: i.batteryStatus, //电池报警状态
fenceStatus: i.fenceStatus, //电子围栏报警状态
onlineStatus: i.onlineStatus, //在线状态
enableStatus: i.enableStatus //启用状态
2 weeks ago
}
})
markers.value = res2 as unknown as any[]
2 weeks ago
inited.value = true
})
}
2 weeks ago
const getFences = async () => {
return await handDetectorStore.getAllFences().then((res) => {
2 weeks ago
console.log('getFences', res)
let fencesData = res.map((i) => {
return {
...i,
fenceRange: JSON.parse(i.fenceRange)
}
})
1 week ago
fences.value = fencesData as unknown as FenceData[]
2 weeks ago
})
}
2 weeks ago
onMounted(() => {
getMarkers()
2 weeks ago
getFences()
1 week ago
console.log('定时器,暂时关掉,太烦了')
// getDataTimer.value = setInterval(() => {
// getMarkers()
// getFences()
// }, 5000)
2 weeks ago
})
onUnmounted(() => {
clearInterval(getDataTimer.value as NodeJS.Timeout)
})
</script>
<style scoped lang="scss">
2 weeks ago
.map-container {
width: 100%;
height: calc(100vh - 140px);
}
/* 顶部面板样式 */
.top-panel {
position: absolute;
top: 12px;
left: 50px;
right: 10px;
z-index: 1000;
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
padding: 10px 12px;
flex-wrap: wrap;
box-sizing: border-box;
.top-panel__left {
// flex: 0 0 260px;
background: rgba(255, 255, 255, 0.7);
border: 1px solid rgba(0, 0, 0, 0.06);
border-radius: 10px;
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.12);
height: 100%;
display: flex;
align-items: center;
gap: 8px;
padding: 10px;
.search-group {
display: flex;
align-items: center;
gap: 8px;
// .search-type {
// flex: 0 0 120px;
// }
.search-input {
width: 220px;
}
}
}
.top-panel__center {
flex: 1 1 auto;
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 12px;
align-items: center;
.data_item {
background: rgba(255, 255, 255, 0.9);
border: 1px solid rgba(0, 0, 0, 0.06);
border-radius: 8px;
padding: 12px 12px;
// min-height: 56px;
// display: flex;
// flex-direction: column;
// justify-content: center;
.data_item__title {
font-size: 14px;
color: #909399;
vertical-align: middle;
}
.data_item__value {
display: inline-block;
padding: 0 10px;
font-size: 18px;
font-weight: 600;
color: #3399ff;
vertical-align: middle;
}
.data_item__unit {
font-size: 14px;
color: #909399;
vertical-align: middle;
}
}
}
.top-panel__right {
display: flex;
align-items: center;
gap: 8px;
flex: 0 0 auto;
background: rgba(255, 255, 255, 0.85);
border: 1px solid rgba(0, 0, 0, 0.06);
padding: 12px 12px;
border-radius: 8px;
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.12);
white-space: nowrap;
height: 100%;
.legend-title {
color: #606266;
font-size: 14px;
}
.normal-legend {
padding: 4px 8px;
border-radius: 999px;
color: #fff;
font-size: 12px;
line-height: 1;
background: #67c23a;
}
.alarm1-legend {
padding: 4px 8px;
border-radius: 999px;
color: #fff;
font-size: 12px;
line-height: 1;
background: #e6a23c;
}
.alarm2-legend {
padding: 4px 8px;
border-radius: 999px;
color: #fff;
font-size: 12px;
line-height: 1;
background: #f56c6c;
}
}
}
@media (max-width: 992px) {
.top-panel {
.top-panel__left {
flex: 1 1 100%;
}
.top-panel__center {
flex: 1 1 100%;
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.top-panel__right {
flex: 1 1 100%;
justify-content: flex-start;
}
}
}
@media (max-width: 600px) {
.top-panel {
.top-panel__center {
grid-template-columns: 1fr;
}
}
}
2 weeks ago
</style>