<!--
|
* @Author : yuan
|
* @Date : 2026-01-06 16:35:50
|
* @LastEditors : yuan
|
* @LastEditTime : 2026-02-09 15:40:07
|
* @FilePath : \applications\drone-command\src\views\dataCockpit\index.vue
|
* @Description :
|
* Copyright 2026 OBKoro1, All Rights Reserved.
|
* 2026-01-06 16:35:50
|
-->
|
<template>
|
<div class="page-container">
|
<DeviceMapContainer ref="deviceMapRef" :all-devices="allDevices" :alarm-drones="realWarningData"
|
:right-collapsed="rightCollapsed" container-id="data-cockpit-map"
|
@drone-signal="handleAlarmAction('signal', $event)" @drone-counter="handleAlarmAction('counter', $event)"
|
@drone-favorite="handleAlarmFavorite" />
|
<LeftContainer class="left-container" v-model:activeId="leftActiveId" v-model:collapsed="leftCollapsed"
|
:real-warning-data="realWarningData" :real-warning-loading="realWarningLoading"
|
@real-warning-signal="handleAlarmAction('signal', $event)"
|
@real-warning-counter="handleAlarmAction('counter', $event)" @real-warning-favorite="handleAlarmFavorite" />
|
<RightContainer class="right-container" v-model:collapsed="rightCollapsed" v-model:allDevices="allDevices"
|
@scene-click="handleSceneClick" />
|
<CenterContainer @select-warning="onSelectWarning" @select-equipment="onSelectEquipment" />
|
<LegendBar class="legend-container" />
|
</div>
|
</template>
|
|
<script setup>
|
import DeviceMapContainer from '@/components/map-container/device-map-container.vue'
|
import LeftContainer from './components/LeftContainer.vue'
|
import RightContainer from './components/RightContainer.vue'
|
import CenterContainer from './components/CenterContainer.vue'
|
import LegendBar from './components/LegendBar.vue'
|
import {
|
alarmLogApi,
|
alarmFavoriteRemoveApi,
|
alarmFavoriteSaveApi,
|
interferenceAndExpulsionApi
|
} from '@/api/dataCockpit'
|
import { ElMessage } from 'element-plus'
|
import { onMounted, ref } from 'vue'
|
|
const leftActiveId = ref(1)
|
const leftCollapsed = ref(false)
|
|
const rightCollapsed = ref(false)
|
const allDevices = ref([])
|
const realWarningData = ref([])
|
const realWarningLoading = ref(false)
|
const loadingTimer = ref(null)
|
const deviceMapRef = ref(null)
|
|
const onSelectWarning = (type) => {
|
leftActiveId.value = type
|
leftCollapsed.value = false
|
}
|
|
const onSelectEquipment = () => {
|
rightCollapsed.value = false
|
}
|
|
const handleSceneClick = (item) => {
|
if (item?.longitude && item?.latitude) {
|
deviceMapRef.value?.flyTo({
|
position: {
|
longitude: Number(item.longitude),
|
latitude: Number(item.latitude),
|
height: 18000
|
},
|
})
|
}
|
}
|
|
const actionTextMap = {
|
signal: '信号干扰',
|
counter: '诱导驱离'
|
}
|
|
const getAlarmRecordId = (item) => item?.alarmRecordId ?? item?.id
|
const getFavoriteId = (item) =>
|
item?.favoriteId ??
|
item?.alarmFavoriteId ??
|
item?.fwAlarmFavoriteId ??
|
item?.favoriteRecordId ??
|
getAlarmRecordId(item)
|
|
const isFavorited = (item) => {
|
const value = item?.favorited ?? item?.isFavorite
|
return value === 1 || value === '1' || value === true
|
}
|
|
const buildPayload = (type, item) => ({
|
counterWay: type === 'signal' ? 1 : type === 'counter' ? 2 : '',
|
alarmRecordId: getAlarmRecordId(item)
|
})
|
|
const handleAlarmAction = async (type, item) => {
|
const actionText = actionTextMap[type] || '操作'
|
try {
|
const res = await interferenceAndExpulsionApi(buildPayload(type, item))
|
if (res?.data?.success) {
|
ElMessage({ type: 'success', message: actionText + '成功' })
|
await fetchRealWarning()
|
} else {
|
ElMessage({ type: 'error', message: res?.data?.msg || actionText + '失败' })
|
}
|
} catch (error) {
|
ElMessage({ type: 'error', message: actionText + '失败' })
|
}
|
}
|
|
const handleAlarmFavorite = async (item) => {
|
const alarmRecordId = getAlarmRecordId(item)
|
if (!alarmRecordId) {
|
ElMessage({ type: 'warning', message: '缺少告警记录ID' })
|
return
|
}
|
const favorite = isFavorited(item)
|
const actionText = favorite ? '取消关注' : '关注'
|
try {
|
const res = favorite
|
? await alarmFavoriteRemoveApi(getFavoriteId(item))
|
: await alarmFavoriteSaveApi({ alarmRecordId })
|
if (res?.data?.success) {
|
ElMessage({ type: 'success', message: actionText + '成功' })
|
await fetchRealWarning()
|
} else {
|
ElMessage({ type: 'error', message: res?.data?.msg || actionText + '失败' })
|
}
|
} catch (error) {
|
ElMessage({ type: 'error', message: actionText + '失败' })
|
}
|
}
|
|
const fetchRealWarning = async () => {
|
// 只有超过200ms才显示loading,避免闪烁
|
loadingTimer.value = setTimeout(() => {
|
realWarningLoading.value = true
|
}, 200)
|
|
try {
|
const params = { current: 1, size: 9999, alarmType: '1' }
|
const res = await alarmLogApi(params)
|
const records = res?.data?.data?.records ?? []
|
realWarningData.value = records.map((record) => ({
|
...record,
|
isFavorite:
|
record?.isFavorite ??
|
(record?.favorited === 1 || record?.favorited === '1')
|
}))
|
} finally {
|
if (loadingTimer.value) clearTimeout(loadingTimer.value)
|
realWarningLoading.value = false
|
}
|
}
|
|
onMounted(() => {
|
fetchRealWarning()
|
})
|
</script>
|
|
<style scoped lang="scss">
|
.page-container {
|
position: relative;
|
width: 100%;
|
height: 100%;
|
}
|
|
.left-container,
|
.right-container {
|
position: absolute;
|
bottom: 20px;
|
width: 300px;
|
z-index: 9;
|
backdrop-filter: blur(2px);
|
border-radius: 10px 10px 10px 10px;
|
|
::v-deep(.wrapper) {
|
display: flex;
|
flex-direction: column;
|
position: absolute;
|
top: 0;
|
bottom: 0;
|
padding: 20px;
|
width: 300px;
|
background: rgba(0, 0, 0, 0.3);
|
backdrop-filter: blur(16px);
|
border-radius: 10px 10px 10px 10px;
|
box-sizing: border-box;
|
}
|
}
|
|
.left-container {
|
top: 113px;
|
left: 17px;
|
background: linear-gradient(270deg, rgba(17, 23, 34, 0) 0%, rgba(17, 23, 34, 0.56) 50%, rgba(17, 23, 34, 0.96) 100%);
|
}
|
|
.right-container {
|
top: 75px;
|
right: 17px;
|
background: linear-gradient(270deg, rgba(17, 23, 34, 0.96) 0.16%, rgba(17, 23, 34, 0.56) 57.57%, rgba(4, 30, 37, 0) 100%);
|
}
|
|
.legend-container {
|
position: absolute;
|
left: 50%;
|
bottom: 22px;
|
transform: translateX(-50%);
|
z-index: 9;
|
}
|
</style>
|