2025-03-31 15:26:29 +00:00
|
|
|
|
<template>
|
|
|
|
|
|
<div class="left-sidebar" :class="{ contracted: isContracted }">
|
2025-06-25 14:27:05 +00:00
|
|
|
|
<div class="alarm-border warningAnimatBox" v-if="iswarning"></div>
|
2025-03-31 15:26:29 +00:00
|
|
|
|
<div class="stats">
|
|
|
|
|
|
<div class="stat-item" v-for="(item, index) in warningDay" :key="index">
|
|
|
|
|
|
<div class="stat-name">{{ item.name }}</div>
|
2025-06-18 15:08:37 +00:00
|
|
|
|
<div class="stat-name">
|
|
|
|
|
|
<span>{{ item.value }}</span> 次
|
|
|
|
|
|
</div>
|
2025-03-31 15:26:29 +00:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="drone-list">
|
|
|
|
|
|
<ul>
|
2025-04-01 16:12:21 +00:00
|
|
|
|
<li
|
|
|
|
|
|
v-for="(drone, index) in drones"
|
|
|
|
|
|
:key="index"
|
2025-06-18 15:08:37 +00:00
|
|
|
|
:style="{
|
2025-06-21 12:00:17 +00:00
|
|
|
|
height: droneStates[drone.BatchId] ? '60px' : '372px',
|
2025-06-18 15:08:37 +00:00
|
|
|
|
padding: 0
|
|
|
|
|
|
}"
|
2025-04-01 16:12:21 +00:00
|
|
|
|
>
|
2025-06-21 12:00:17 +00:00
|
|
|
|
<div
|
|
|
|
|
|
class="details-one"
|
|
|
|
|
|
v-if="droneStates[drone.BatchId]"
|
|
|
|
|
|
@click="handleDroneClick(drone)"
|
2025-06-25 17:43:53 +00:00
|
|
|
|
:style="{
|
|
|
|
|
|
backgroundImage: !drone.IsWhitelist
|
|
|
|
|
|
? `url(${require('@/assets/img/uavBackred.png')})`
|
|
|
|
|
|
: `url(${require('@/assets/img/uavBackfff.png')})`
|
|
|
|
|
|
}"
|
2025-06-21 12:00:17 +00:00
|
|
|
|
>
|
2025-06-18 15:08:37 +00:00
|
|
|
|
<div class="top">
|
|
|
|
|
|
<div class="left">
|
|
|
|
|
|
{{ index < 9 ? "0" + (index + 1) : index + 1 }}
|
|
|
|
|
|
</div>
|
2025-06-26 14:31:31 +00:00
|
|
|
|
<div class="text" style="font-size: 14px">
|
|
|
|
|
|
{{ drone.serial_number }}
|
|
|
|
|
|
</div>
|
2025-06-18 15:08:37 +00:00
|
|
|
|
<div class="img-vector">
|
|
|
|
|
|
<img src="@/assets/img/Vector.png" alt="" />
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="main">
|
|
|
|
|
|
<div class="top_main">
|
|
|
|
|
|
<div class="text">
|
|
|
|
|
|
<span class="color-ef">距离:</span>
|
2025-06-21 12:00:17 +00:00
|
|
|
|
<span class="text-fff">{{ drone.distance || 0 }}米</span>
|
2025-06-18 15:08:37 +00:00
|
|
|
|
</div>
|
|
|
|
|
|
<div class="text">
|
|
|
|
|
|
<span class="color-ef">高度:</span>
|
|
|
|
|
|
<span class="text-fff">{{ drone.height }}米</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2025-03-31 15:26:29 +00:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2025-06-25 17:43:53 +00:00
|
|
|
|
<div
|
|
|
|
|
|
class="details-all"
|
|
|
|
|
|
v-else
|
|
|
|
|
|
@click="handleDroneClick(drone)"
|
|
|
|
|
|
:style="{
|
|
|
|
|
|
backgroundImage: !drone.IsWhitelist
|
|
|
|
|
|
? `url(${require('@/assets/img/uavBackred-big.png')})`
|
|
|
|
|
|
: `url(${require('@/assets/img/uavBackfff-big.png')})`
|
|
|
|
|
|
}"
|
|
|
|
|
|
>
|
2025-06-18 15:08:37 +00:00
|
|
|
|
<div class="top">
|
|
|
|
|
|
<div class="left">
|
|
|
|
|
|
{{ index < 9 ? "0" + (index + 1) : index + 1 }}
|
|
|
|
|
|
</div>
|
2025-06-26 14:31:31 +00:00
|
|
|
|
<div class="text" style="font-size: 14px">
|
|
|
|
|
|
{{ drone.serial_number }}
|
|
|
|
|
|
</div>
|
2025-06-18 15:08:37 +00:00
|
|
|
|
<div class="img-vector">
|
|
|
|
|
|
<img src="@/assets/img/Vector.png" alt="" />
|
|
|
|
|
|
</div>
|
2025-03-31 15:26:29 +00:00
|
|
|
|
</div>
|
2025-06-18 15:08:37 +00:00
|
|
|
|
<div class="content-main">
|
|
|
|
|
|
<div class="content-top">
|
|
|
|
|
|
<div class="top-left">
|
|
|
|
|
|
<span class="color-ef"> 距离:</span>
|
2025-06-21 12:00:17 +00:00
|
|
|
|
<span class="text-fff">{{ drone.distance || 0 }}米</span>
|
2025-06-18 15:08:37 +00:00
|
|
|
|
</div>
|
|
|
|
|
|
<div class="top-right">
|
|
|
|
|
|
<span class="color-ef"> 高度:</span>
|
|
|
|
|
|
<span class="text-fff">{{ drone.height || 0 }}米</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2025-06-21 12:00:17 +00:00
|
|
|
|
<!-- <div class="content-serial">
|
2025-06-18 15:08:37 +00:00
|
|
|
|
<span class="color-ef"> 序列号:</span>
|
2025-06-21 12:00:17 +00:00
|
|
|
|
<span class="text-fff">{{ drone.serial_number }}</span>
|
|
|
|
|
|
</div> -->
|
2025-06-18 15:08:37 +00:00
|
|
|
|
<div class="content-serial">
|
|
|
|
|
|
<span class="color-ef"> 型号:</span>
|
2025-06-21 12:00:17 +00:00
|
|
|
|
<span class="text-fff">{{ drone.device_type }}</span>
|
2025-06-18 15:08:37 +00:00
|
|
|
|
</div>
|
|
|
|
|
|
<div class="content-serial">
|
|
|
|
|
|
<span class="color-ef"> 更新时间:</span>
|
2025-06-21 12:00:17 +00:00
|
|
|
|
<span class="text-fff-time">{{ drone.times }}</span>
|
2025-06-18 15:08:37 +00:00
|
|
|
|
</div>
|
|
|
|
|
|
<div class="content-serial">
|
|
|
|
|
|
<span class="color-ef-fw">无人机方位</span>
|
|
|
|
|
|
</div>
|
2025-06-21 12:00:17 +00:00
|
|
|
|
<div class="content-serial" style="height: 35%">
|
2025-06-18 15:08:37 +00:00
|
|
|
|
<div class="content-potions">
|
|
|
|
|
|
<div class="content-potions-lon">
|
|
|
|
|
|
<p class="text">经纬度:</p>
|
|
|
|
|
|
<p class="characters">
|
|
|
|
|
|
{{ drone.drone_lon }}, {{ drone.drone_lat }}
|
|
|
|
|
|
</p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="content-potions-bottom">
|
|
|
|
|
|
<div class="content-text content-potions-lat">
|
2025-06-29 12:02:30 +00:00
|
|
|
|
<p class="text">距离:</p>
|
|
|
|
|
|
<p class="characters">{{ drone.distanceMeters }}M</p>
|
2025-06-18 15:08:37 +00:00
|
|
|
|
</div>
|
2025-06-21 12:00:17 +00:00
|
|
|
|
</div>
|
|
|
|
|
|
<div class="content-potions-lon">
|
|
|
|
|
|
<p class="text">速度:</p>
|
|
|
|
|
|
<p class="characters">
|
|
|
|
|
|
E:{{ drone.speed_E }} N:{{ drone.speed_N }} U:{{
|
|
|
|
|
|
drone.speed_U
|
|
|
|
|
|
}}
|
|
|
|
|
|
</p>
|
2025-06-18 15:08:37 +00:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="content-serial">
|
2025-06-21 12:00:17 +00:00
|
|
|
|
<span class="color-ef-fw">飞手位置</span>
|
2025-06-18 15:08:37 +00:00
|
|
|
|
</div>
|
2025-06-21 12:00:17 +00:00
|
|
|
|
<div class="content-serial" style="height: 15%">
|
2025-06-18 15:52:42 +00:00
|
|
|
|
<div class="content-fs">
|
|
|
|
|
|
<div class="content-fs-lon">
|
2025-06-18 15:08:37 +00:00
|
|
|
|
<p class="text">经纬度</p>
|
|
|
|
|
|
<p class="characters">
|
2025-06-21 12:00:17 +00:00
|
|
|
|
{{ drone.app_lon }}, {{ drone.app_lat }}
|
2025-06-18 15:08:37 +00:00
|
|
|
|
</p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2025-06-18 15:52:42 +00:00
|
|
|
|
<div class="content-serial" style="height: 10%">
|
2025-06-18 15:08:37 +00:00
|
|
|
|
<div class="btns">
|
2025-06-18 15:52:42 +00:00
|
|
|
|
<div class="btn-trust">
|
2025-06-21 12:00:17 +00:00
|
|
|
|
<el-button
|
|
|
|
|
|
type="primary"
|
|
|
|
|
|
@click.stop="handlewhiteList(drone)"
|
|
|
|
|
|
>
|
2025-06-25 15:29:21 +00:00
|
|
|
|
{{ !drone.IsWhitelist ? "信任" : "不信任" }}
|
2025-06-21 12:00:17 +00:00
|
|
|
|
</el-button>
|
2025-06-18 15:52:42 +00:00
|
|
|
|
</div>
|
|
|
|
|
|
<div class="btn-navigation">
|
2025-06-21 12:00:17 +00:00
|
|
|
|
<el-button
|
|
|
|
|
|
type="primary"
|
|
|
|
|
|
@click.stop="handleNavigation(drone)"
|
|
|
|
|
|
>
|
|
|
|
|
|
导航
|
|
|
|
|
|
</el-button>
|
2025-06-18 15:52:42 +00:00
|
|
|
|
</div>
|
2025-06-18 15:08:37 +00:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2025-03-31 15:26:29 +00:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2025-06-21 12:00:17 +00:00
|
|
|
|
<div
|
|
|
|
|
|
class="navigation-content"
|
|
|
|
|
|
v-if="navigationStates[drone.BatchId]"
|
|
|
|
|
|
>
|
|
|
|
|
|
<!-- <div class="navigation-content-text">
|
2025-06-19 15:41:07 +00:00
|
|
|
|
<span class="color-ef">距飞手:</span>
|
|
|
|
|
|
<span class="text-fff">{{ drone.height || 0 }}米</span>
|
2025-06-21 12:00:17 +00:00
|
|
|
|
</div> -->
|
|
|
|
|
|
<div class="navigation-content-text" style="text-align: center">
|
|
|
|
|
|
<span class="color-ef" style="font-weight: 800">
|
|
|
|
|
|
导航高德地图
|
|
|
|
|
|
</span>
|
2025-06-19 15:41:07 +00:00
|
|
|
|
</div>
|
2025-06-21 12:00:17 +00:00
|
|
|
|
<div class="navigation-content-qrcode">
|
|
|
|
|
|
<img
|
|
|
|
|
|
v-if="qrCodes[drone.BatchId]"
|
|
|
|
|
|
:src="qrCodes[drone.BatchId]"
|
|
|
|
|
|
alt="导航二维码"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<span v-else>二维码生成中...</span>
|
2025-06-19 15:41:07 +00:00
|
|
|
|
</div>
|
|
|
|
|
|
<div class="navigation-content-text">
|
|
|
|
|
|
<span class="text-fff">跳转到导航系统</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="navigation-content-btn">
|
|
|
|
|
|
<div class="btns">
|
|
|
|
|
|
<div class="btn-trust">
|
2025-06-21 12:00:17 +00:00
|
|
|
|
<el-button
|
|
|
|
|
|
type="primary"
|
|
|
|
|
|
@click.stop="closeNavigation(drone)"
|
|
|
|
|
|
>
|
|
|
|
|
|
是
|
|
|
|
|
|
</el-button>
|
2025-06-19 15:41:07 +00:00
|
|
|
|
</div>
|
|
|
|
|
|
<div class="btn-navigation">
|
2025-06-21 12:00:17 +00:00
|
|
|
|
<el-button type="primary" @click.stop="noNavigation(drone)">
|
|
|
|
|
|
否
|
|
|
|
|
|
</el-button>
|
2025-06-19 15:41:07 +00:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2025-03-31 15:26:29 +00:00
|
|
|
|
</li>
|
|
|
|
|
|
</ul>
|
|
|
|
|
|
</div>
|
2025-04-03 14:28:51 +00:00
|
|
|
|
<audio
|
|
|
|
|
|
controls
|
|
|
|
|
|
loop
|
|
|
|
|
|
ref="uavAudio"
|
2025-04-02 14:38:27 +00:00
|
|
|
|
v-show="iswarning"
|
2025-06-22 09:42:09 +00:00
|
|
|
|
style="display: none; pointer-events: auto"
|
2025-06-21 12:00:17 +00:00
|
|
|
|
id="uavAudio"
|
2025-04-03 14:28:51 +00:00
|
|
|
|
>
|
|
|
|
|
|
<source src="@/assets/img/wargin.mp3" type="audio/mpeg" />
|
|
|
|
|
|
</audio>
|
|
|
|
|
|
<div class="audio-prompt" v-if="showAudioPrompt" @click="enableAudio">
|
|
|
|
|
|
<div class="prompt-content">
|
|
|
|
|
|
<p>因浏览器限制,点击打开声音</p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2025-03-31 15:26:29 +00:00
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script>
|
2025-06-21 12:00:17 +00:00
|
|
|
|
import { mapGetters } from "vuex";
|
2025-04-01 16:12:21 +00:00
|
|
|
|
import moment from "moment";
|
|
|
|
|
|
import { mapUavFiex } from "../index.js";
|
2025-06-21 12:00:17 +00:00
|
|
|
|
import Style from "ol/style/Style";
|
|
|
|
|
|
import Stroke from "ol/style/Stroke";
|
|
|
|
|
|
import { fromLonLat, toLonLat } from "ol/proj";
|
2025-06-25 14:27:05 +00:00
|
|
|
|
import { whitListAdd, whitListDelete } from "@/api/whitList.js";
|
2025-06-21 12:00:17 +00:00
|
|
|
|
import QRCode from "qrcode";
|
|
|
|
|
|
|
2025-03-31 15:26:29 +00:00
|
|
|
|
export default {
|
|
|
|
|
|
name: "LeftSidebar",
|
|
|
|
|
|
props: {
|
|
|
|
|
|
homeData: {
|
|
|
|
|
|
type: Object,
|
|
|
|
|
|
default: () => ({})
|
2025-04-01 16:12:21 +00:00
|
|
|
|
},
|
|
|
|
|
|
signaData: {
|
|
|
|
|
|
type: Array,
|
|
|
|
|
|
default: () => []
|
2025-03-31 15:26:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
data() {
|
|
|
|
|
|
return {
|
|
|
|
|
|
leftContract: require("@/assets/img/left-contract.png"),
|
|
|
|
|
|
rightContract: require("@/assets/img/right-contract.png"),
|
|
|
|
|
|
warningDay: [
|
|
|
|
|
|
{
|
|
|
|
|
|
id: "1",
|
|
|
|
|
|
name: "今日预警",
|
2025-06-21 12:00:17 +00:00
|
|
|
|
value: 0
|
2025-03-31 15:26:29 +00:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
id: "2",
|
|
|
|
|
|
name: "累计预警",
|
2025-06-21 12:00:17 +00:00
|
|
|
|
value: 0
|
2025-03-31 15:26:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
],
|
2025-06-21 12:00:17 +00:00
|
|
|
|
drones: [],
|
|
|
|
|
|
droneStates: {}, // 存储 detailsShow 状态
|
|
|
|
|
|
navigationStates: {}, // 控制 navigation-content 显示
|
|
|
|
|
|
qrCodes: {}, // 存储每个无人机的二维码 URL
|
2025-03-31 15:26:29 +00:00
|
|
|
|
isContracted: false,
|
2025-04-01 16:12:21 +00:00
|
|
|
|
homeView: {},
|
2025-04-02 14:29:18 +00:00
|
|
|
|
droneTimers: new Map(),
|
2025-04-04 11:57:33 +00:00
|
|
|
|
iswarning: false,
|
2025-06-21 12:00:17 +00:00
|
|
|
|
showAudioPrompt: false,
|
|
|
|
|
|
startTime: "", // 初始化时间范围
|
|
|
|
|
|
endTime: "",
|
2025-06-25 14:27:05 +00:00
|
|
|
|
qrCodeUrl: "",
|
|
|
|
|
|
isAudioPlaying: false // 跟踪音频播放状态
|
2025-03-31 15:26:29 +00:00
|
|
|
|
};
|
|
|
|
|
|
},
|
2025-06-21 12:00:17 +00:00
|
|
|
|
computed: {
|
2025-06-29 12:02:30 +00:00
|
|
|
|
...mapGetters(["isZoomedIn", "SliderValue", "lonAndLat"])
|
2025-06-21 12:00:17 +00:00
|
|
|
|
},
|
2025-06-19 15:41:07 +00:00
|
|
|
|
mounted() {
|
2025-06-21 12:00:17 +00:00
|
|
|
|
this.endTime = moment.utc().format("YYYY-MM-DD HH:mm:ss");
|
|
|
|
|
|
this.startTime = moment
|
|
|
|
|
|
.utc()
|
|
|
|
|
|
.subtract(1, "month")
|
|
|
|
|
|
.format("YYYY-MM-DD HH:mm:ss");
|
2025-06-26 14:31:31 +00:00
|
|
|
|
this.enableTouchScroll();
|
2025-06-19 15:41:07 +00:00
|
|
|
|
},
|
2025-03-31 15:26:29 +00:00
|
|
|
|
watch: {
|
|
|
|
|
|
homeData: {
|
|
|
|
|
|
handler(newVal) {
|
|
|
|
|
|
this.homeView = newVal;
|
|
|
|
|
|
this.warningDay[0].value = newVal.alarmCount.todaywaring;
|
|
|
|
|
|
this.warningDay[1].value = newVal.alarmCount.totalcount;
|
|
|
|
|
|
},
|
|
|
|
|
|
deep: true
|
2025-04-01 16:12:21 +00:00
|
|
|
|
},
|
2025-06-22 09:42:09 +00:00
|
|
|
|
SliderValue: {
|
|
|
|
|
|
handler(newVal) {
|
|
|
|
|
|
if (newVal) {
|
|
|
|
|
|
console.log("SliderValue:", newVal);
|
|
|
|
|
|
const media = this.$refs.uavAudio;
|
|
|
|
|
|
if (media) {
|
|
|
|
|
|
media.volume = newVal / 100;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
deep: true
|
|
|
|
|
|
},
|
2025-04-01 16:12:21 +00:00
|
|
|
|
signaData: {
|
|
|
|
|
|
handler(newVal) {
|
|
|
|
|
|
if (newVal) {
|
2025-06-21 12:00:17 +00:00
|
|
|
|
// newVal = [
|
|
|
|
|
|
// {
|
|
|
|
|
|
// BatchId: "1936279216064696320",
|
|
|
|
|
|
// serial_number: "1581F6CDC23B6003DTL2",
|
|
|
|
|
|
// device_type: "8",
|
|
|
|
|
|
// device_type_8: 91088,
|
|
|
|
|
|
// app_lat: 39.055,
|
|
|
|
|
|
// app_lon: 117.303466,
|
|
|
|
|
|
// drone_lat: 39.040924,
|
|
|
|
|
|
// drone_lon: 117.337103,
|
|
|
|
|
|
// height: 0.0,
|
|
|
|
|
|
// altitude: 0.0,
|
|
|
|
|
|
// home_lat: 0.0,
|
|
|
|
|
|
// home_lon: 0.0,
|
|
|
|
|
|
// distance: 3299.608332218683,
|
|
|
|
|
|
// centerdistance: 5023.652200054709,
|
|
|
|
|
|
// IsWhitelist: false,
|
|
|
|
|
|
// speed_E: 12210.0,
|
|
|
|
|
|
// speed_N: 3120.0,
|
|
|
|
|
|
// speed_U: 130.0,
|
|
|
|
|
|
// RSSI: 0.0,
|
|
|
|
|
|
// positionId: "1924768527160578048",
|
|
|
|
|
|
// PostionName: "louding",
|
|
|
|
|
|
// DeviceId: "1924798246178394112",
|
|
|
|
|
|
// DeviceName: "0007",
|
|
|
|
|
|
// freq: 0.0,
|
|
|
|
|
|
// alarmLevel: 0,
|
|
|
|
|
|
// Time: 1744872277,
|
|
|
|
|
|
// CreateTime: "2025-06-21T12:25:14.0948095+08:00",
|
|
|
|
|
|
// Id: "1936279217155215360"
|
|
|
|
|
|
// }
|
|
|
|
|
|
// ];
|
2025-06-27 03:17:41 +00:00
|
|
|
|
let positionID = JSON.parse(localStorage.getItem("PositionIds"));
|
|
|
|
|
|
if (positionID !== null || positionID !== undefined) {
|
|
|
|
|
|
const match = newVal.some((item) =>
|
|
|
|
|
|
positionID.includes(item.positionId)
|
|
|
|
|
|
);
|
|
|
|
|
|
console.log(match, "match");
|
2025-06-26 14:31:31 +00:00
|
|
|
|
if (match) {
|
|
|
|
|
|
newVal.forEach((newItem) => {
|
2025-06-26 15:37:03 +00:00
|
|
|
|
if (
|
|
|
|
|
|
newItem.drone_lon !== 0 &&
|
|
|
|
|
|
newItem.drone_lat !== 0 &&
|
|
|
|
|
|
newItem.app_lon !== 0 &&
|
|
|
|
|
|
newItem.app_lat !== 0
|
|
|
|
|
|
) {
|
2025-06-29 12:02:30 +00:00
|
|
|
|
if (this.lonAndLat && this.lonAndLat.length === 2) {
|
|
|
|
|
|
const [userLon, userLat] = this.lonAndLat;
|
|
|
|
|
|
newItem.distanceMeters = this.calculateDistance(
|
|
|
|
|
|
userLon,
|
|
|
|
|
|
userLat,
|
|
|
|
|
|
newItem.drone_lon,
|
|
|
|
|
|
newItem.drone_lat
|
|
|
|
|
|
).toFixed(0);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
newItem.distanceMeters = newItem.distanceMeters || 0;
|
|
|
|
|
|
}
|
2025-06-26 15:25:40 +00:00
|
|
|
|
// 如果已经存在相同BatchId的数据,重置计时器
|
|
|
|
|
|
if (newItem.BatchId) {
|
|
|
|
|
|
const existingTimer = this.droneTimers.get(newItem.BatchId);
|
|
|
|
|
|
if (existingTimer) {
|
|
|
|
|
|
clearInterval(existingTimer); // 清除旧计时器
|
|
|
|
|
|
}
|
|
|
|
|
|
// 设置15秒初始时间
|
|
|
|
|
|
newItem.currTime = window.mapConfig.currTime;
|
|
|
|
|
|
// 创建新计时器
|
|
|
|
|
|
const timer = this.startTimer(newItem);
|
|
|
|
|
|
this.droneTimers.set(newItem.BatchId, timer);
|
2025-04-01 16:12:21 +00:00
|
|
|
|
|
2025-06-26 15:25:40 +00:00
|
|
|
|
// 初始化 detailsShow(仅首次)
|
|
|
|
|
|
if (!(newItem.BatchId in this.droneStates)) {
|
|
|
|
|
|
this.$set(this.droneStates, newItem.BatchId, true);
|
|
|
|
|
|
}
|
|
|
|
|
|
// 默认隐藏 navigation-content
|
|
|
|
|
|
if (!(newItem.BatchId in this.navigationStates)) {
|
|
|
|
|
|
this.$set(this.navigationStates, newItem.BatchId, false);
|
|
|
|
|
|
}
|
2025-06-21 12:00:17 +00:00
|
|
|
|
|
2025-06-26 15:25:40 +00:00
|
|
|
|
// 更新无人机列表
|
|
|
|
|
|
const existingIndex = this.drones.findIndex(
|
|
|
|
|
|
(d) => d.BatchId === newItem.BatchId
|
|
|
|
|
|
);
|
|
|
|
|
|
newItem.times = moment(newItem.CreateTime).format(
|
|
|
|
|
|
"HH:mm:ss"
|
|
|
|
|
|
);
|
|
|
|
|
|
newItem.distance = parseInt(newItem.distance.toFixed(0));
|
2025-06-21 12:00:17 +00:00
|
|
|
|
|
2025-06-26 15:25:40 +00:00
|
|
|
|
if (existingIndex !== -1) {
|
|
|
|
|
|
this.$set(this.drones, existingIndex, { ...newItem });
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.$set(this.drones, this.drones.length, {
|
|
|
|
|
|
...newItem
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2025-06-26 14:31:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
if (newVal.length === 0) {
|
|
|
|
|
|
this.iswarning = false;
|
|
|
|
|
|
this.showAudioPrompt = false; // 没有数据 不显示提示框
|
2025-04-01 16:12:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-26 14:31:31 +00:00
|
|
|
|
if (this.drones) {
|
|
|
|
|
|
mapUavFiex(this.drones, window.olMap);
|
|
|
|
|
|
}
|
|
|
|
|
|
const media = this.$refs.uavAudio;
|
|
|
|
|
|
let alarm = this.drones.find((d) => d.alarmLevel === 1);
|
|
|
|
|
|
if (alarm) {
|
|
|
|
|
|
this.iswarning = true;
|
|
|
|
|
|
this.$nextTick(() => {
|
|
|
|
|
|
if (media) {
|
|
|
|
|
|
media.muted = true; // 初始静音
|
|
|
|
|
|
const savedVolume = localStorage.getItem("soundValue");
|
|
|
|
|
|
media.volume = savedVolume !== null ? savedVolume / 100 : 1;
|
|
|
|
|
|
media.muted = this.isZoomedIn ? false : true;
|
2025-06-25 14:27:05 +00:00
|
|
|
|
|
2025-06-26 14:31:31 +00:00
|
|
|
|
// 如果音频未在播放,则开始播放
|
|
|
|
|
|
if (!this.isAudioPlaying) {
|
|
|
|
|
|
media
|
|
|
|
|
|
.play()
|
|
|
|
|
|
.then(() => {
|
|
|
|
|
|
console.log("播放音频");
|
|
|
|
|
|
this.isAudioPlaying = true;
|
|
|
|
|
|
// 监听音频结束事件,循环播放
|
|
|
|
|
|
media.onended = () => {
|
|
|
|
|
|
if (this.iswarning) {
|
|
|
|
|
|
media.play().catch((error) => {
|
|
|
|
|
|
console.log("循环播放失败:", error);
|
|
|
|
|
|
this.showAudioPrompt = true;
|
|
|
|
|
|
});
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.isAudioPlaying = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
})
|
|
|
|
|
|
.catch((error) => {
|
|
|
|
|
|
console.log("播放失败:", error);
|
|
|
|
|
|
this.showAudioPrompt = true;
|
2025-06-25 14:27:05 +00:00
|
|
|
|
this.isAudioPlaying = false;
|
2025-06-26 14:31:31 +00:00
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
} else if (!alarm && this.iswarning) {
|
|
|
|
|
|
// 告警消失,停止音频
|
|
|
|
|
|
this.iswarning = false;
|
|
|
|
|
|
if (media) {
|
|
|
|
|
|
media.pause();
|
|
|
|
|
|
media.currentTime = 0;
|
|
|
|
|
|
this.isAudioPlaying = false;
|
|
|
|
|
|
media.onended = null; // 移除结束事件监听
|
|
|
|
|
|
this.showAudioPrompt = false;
|
2025-06-25 14:27:05 +00:00
|
|
|
|
}
|
2025-04-03 14:28:51 +00:00
|
|
|
|
}
|
2025-06-26 14:31:31 +00:00
|
|
|
|
// 无数据时重置
|
|
|
|
|
|
if (newVal.length === 0) {
|
|
|
|
|
|
this.iswarning = false;
|
|
|
|
|
|
this.showAudioPrompt = false;
|
|
|
|
|
|
this.isAudioPlaying = false;
|
|
|
|
|
|
if (media) {
|
|
|
|
|
|
media.pause();
|
|
|
|
|
|
media.currentTime = 0;
|
|
|
|
|
|
media.onended = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
vectorSource.clear();
|
|
|
|
|
|
}
|
2025-04-03 14:28:51 +00:00
|
|
|
|
}
|
2025-04-02 14:29:18 +00:00
|
|
|
|
}
|
2025-04-01 16:12:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
deep: true
|
2025-06-21 12:00:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
isZoomedIn: {
|
|
|
|
|
|
handler(newVal) {
|
|
|
|
|
|
if (this.iswarning) {
|
|
|
|
|
|
const media = this.$refs.uavAudio;
|
|
|
|
|
|
if (newVal) {
|
|
|
|
|
|
media.muted = false; // 取消静音
|
|
|
|
|
|
} else {
|
|
|
|
|
|
media.muted = true; // 静音
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
deep: true
|
2025-03-31 15:26:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
methods: {
|
2025-06-29 12:02:30 +00:00
|
|
|
|
calculateDistance(lon1, lat1, lon2, lat2) {
|
|
|
|
|
|
const R = 6371e3; // 地球半径(米)
|
|
|
|
|
|
const a1 = (lat1 * Math.PI) / 180; // 将纬度转换为弧度
|
|
|
|
|
|
const a2 = (lat2 * Math.PI) / 180;
|
|
|
|
|
|
const ab = ((lat2 - lat1) * Math.PI) / 180;
|
|
|
|
|
|
const ac = ((lon2 - lon1) * Math.PI) / 180;
|
|
|
|
|
|
|
|
|
|
|
|
const a =
|
|
|
|
|
|
Math.sin(ab / 2) * Math.sin(ab / 2) +
|
|
|
|
|
|
Math.cos(a1) * Math.cos(a2) * Math.sin(ac / 2) * Math.sin(ac / 2);
|
|
|
|
|
|
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
|
|
|
|
|
|
|
|
|
|
|
return R * c; // 距离(米)
|
|
|
|
|
|
},
|
2025-06-26 14:31:31 +00:00
|
|
|
|
enableTouchScroll() {
|
|
|
|
|
|
const ulElement = this.$el.querySelector(".drone-list ul");
|
|
|
|
|
|
if (ulElement) {
|
|
|
|
|
|
let startY, startScrollTop;
|
|
|
|
|
|
|
|
|
|
|
|
ulElement.addEventListener("touchstart", (e) => {
|
|
|
|
|
|
startY = e.touches[0].clientY;
|
|
|
|
|
|
startScrollTop = ulElement.scrollTop;
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
ulElement.addEventListener("touchmove", (e) => {
|
|
|
|
|
|
const deltaY = e.touches[0].clientY - startY;
|
|
|
|
|
|
ulElement.scrollTop = startScrollTop - deltaY;
|
|
|
|
|
|
// 阻止默认滚动行为(视情况调整)
|
|
|
|
|
|
// e.preventDefault();
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
2025-06-21 12:00:17 +00:00
|
|
|
|
closeNavigation(drone) {
|
2025-06-24 15:33:44 +00:00
|
|
|
|
// 确保 drone.app_lon 和 drone.app_lat 存在
|
|
|
|
|
|
if (!drone || !drone.app_lon || !drone.app_lat) {
|
|
|
|
|
|
this.$message.error("无人机的经纬度信息无效");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
window.location.href =
|
|
|
|
|
|
"amapuri://route/plan/?dlat=" +
|
|
|
|
|
|
drone.app_lat +
|
|
|
|
|
|
"&dlon=" +
|
|
|
|
|
|
drone.app_lon +
|
|
|
|
|
|
"&dname=飞手位置&dev=0&t=0";
|
|
|
|
|
|
|
|
|
|
|
|
// 可选:提供后备方案(如果 App 未安装,跳转到网页版)
|
2025-06-25 14:27:05 +00:00
|
|
|
|
// setTimeout(() => {
|
|
|
|
|
|
// const isAppOpened = document.hidden || document.webkitHidden;
|
|
|
|
|
|
// if (!isAppOpened) {
|
|
|
|
|
|
// this.$message.warning("未安装高德地图 App,将打开网页版导航");
|
|
|
|
|
|
// window.open(
|
|
|
|
|
|
// `https://uri.amap.com/navigation?to=${drone.app_lon},${drone.app_lat},飞手位置&callnative=1`,
|
|
|
|
|
|
// "_blank"
|
|
|
|
|
|
// );
|
|
|
|
|
|
// }
|
|
|
|
|
|
// }, 1000);
|
2025-06-21 12:00:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
noNavigation(drone) {
|
|
|
|
|
|
this.$set(this.navigationStates, drone.BatchId, false);
|
|
|
|
|
|
},
|
|
|
|
|
|
async handleNavigation(drone) {
|
|
|
|
|
|
console.log("导航", drone);
|
|
|
|
|
|
this.$set(
|
|
|
|
|
|
this.navigationStates,
|
|
|
|
|
|
drone.BatchId,
|
|
|
|
|
|
!this.navigationStates[drone.BatchId]
|
2025-06-19 15:41:07 +00:00
|
|
|
|
);
|
2025-06-21 12:00:17 +00:00
|
|
|
|
if (!this.navigationStates[drone.BatchId]) {
|
|
|
|
|
|
return; // 如果关闭导航面板,直接返回
|
|
|
|
|
|
}
|
|
|
|
|
|
// 使用 amapuri 协议,优先打开高德地图 App
|
|
|
|
|
|
const naviUrl = `https://uri.amap.com/navigation?to=${
|
|
|
|
|
|
drone.app_lon + "," + drone.app_lat
|
|
|
|
|
|
},飞手位置&callnative=1`;
|
|
|
|
|
|
try {
|
|
|
|
|
|
// 异步生成二维码并存储到 qrCodes 对象
|
|
|
|
|
|
const qrCodeDataUrl = await QRCode.toDataURL(naviUrl, {
|
|
|
|
|
|
width: 200,
|
|
|
|
|
|
margin: 2
|
|
|
|
|
|
});
|
|
|
|
|
|
this.$set(this.qrCodes, drone.BatchId, qrCodeDataUrl);
|
|
|
|
|
|
} catch (err) {
|
|
|
|
|
|
console.error("二维码生成失败:", err);
|
|
|
|
|
|
this.$message.error("二维码生成失败,请重试!");
|
|
|
|
|
|
}
|
2025-06-19 15:41:07 +00:00
|
|
|
|
},
|
2025-06-21 12:00:17 +00:00
|
|
|
|
handlewhiteList(drone) {
|
|
|
|
|
|
let params = {
|
|
|
|
|
|
model: " ",
|
|
|
|
|
|
sn: drone.serial_number,
|
|
|
|
|
|
allDay: true,
|
|
|
|
|
|
startTime: this.startTime,
|
|
|
|
|
|
endTime: this.endTime,
|
2025-06-25 16:05:02 +00:00
|
|
|
|
positionId: [drone.positionId],
|
2025-06-21 12:00:17 +00:00
|
|
|
|
company: " ",
|
|
|
|
|
|
mark: " "
|
|
|
|
|
|
};
|
2025-06-25 15:29:21 +00:00
|
|
|
|
if (!drone.IsWhitelist) {
|
2025-06-25 14:27:05 +00:00
|
|
|
|
whitListAdd(params)
|
|
|
|
|
|
.then((res) => {
|
|
|
|
|
|
if (res.code === 0) {
|
|
|
|
|
|
console.log(res, "添加成功");
|
|
|
|
|
|
this.$message.success("添加成功");
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.$message.error(res.msg);
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
.catch((err) => {
|
|
|
|
|
|
this.$message.error(err);
|
|
|
|
|
|
});
|
|
|
|
|
|
} else {
|
2025-06-25 16:13:03 +00:00
|
|
|
|
whitListDelete({ id: drone.WhiteListId })
|
2025-06-25 14:27:05 +00:00
|
|
|
|
.then((res) => {
|
|
|
|
|
|
if (res.code === 0) {
|
|
|
|
|
|
this.$message.success("移除成功");
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.$message.error(res.msg);
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
.catch((err) => {
|
|
|
|
|
|
this.$message.error(err);
|
|
|
|
|
|
console.log(err, "移除失败");
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2025-06-19 15:41:07 +00:00
|
|
|
|
},
|
2025-04-03 14:28:51 +00:00
|
|
|
|
enableAudio() {
|
|
|
|
|
|
this.iswarning = true;
|
|
|
|
|
|
const media = this.$refs.uavAudio;
|
2025-06-22 09:42:09 +00:00
|
|
|
|
const savedVolume = localStorage.getItem("soundValue");
|
2025-04-03 14:28:51 +00:00
|
|
|
|
let time = setInterval(() => {
|
|
|
|
|
|
console.log("用户手动启用音频", media);
|
|
|
|
|
|
if (media !== undefined) {
|
|
|
|
|
|
clearInterval(time);
|
2025-06-21 12:00:17 +00:00
|
|
|
|
if (this.isZoomedIn) {
|
|
|
|
|
|
media.muted = false; // 播放成功后取消静音
|
|
|
|
|
|
} else {
|
|
|
|
|
|
media.muted = true; // 初始静音
|
|
|
|
|
|
}
|
2025-06-22 09:42:09 +00:00
|
|
|
|
if (savedVolume !== null) {
|
|
|
|
|
|
media.volume = savedVolume / 100;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
media.volume = 1;
|
|
|
|
|
|
}
|
2025-04-03 14:28:51 +00:00
|
|
|
|
media
|
|
|
|
|
|
.play()
|
|
|
|
|
|
.then(() => {
|
|
|
|
|
|
console.log("用户手动启用音频成功");
|
|
|
|
|
|
this.showAudioPrompt = false; // 关闭提示框
|
|
|
|
|
|
})
|
|
|
|
|
|
.catch((error) => {
|
|
|
|
|
|
console.error("手动播放失败:", error);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}, 500);
|
|
|
|
|
|
},
|
2025-04-01 16:12:21 +00:00
|
|
|
|
startTimer(item) {
|
|
|
|
|
|
return setInterval(() => {
|
|
|
|
|
|
if (item.currTime > 0) {
|
|
|
|
|
|
item.currTime--;
|
2025-06-29 12:24:33 +00:00
|
|
|
|
console.log(item.currTime, "item.currTime");
|
2025-04-01 16:12:21 +00:00
|
|
|
|
// 更新显示时间(可选)
|
|
|
|
|
|
const index = this.drones.findIndex(
|
|
|
|
|
|
(d) => d.BatchId === item.BatchId
|
|
|
|
|
|
);
|
|
|
|
|
|
if (index !== -1) {
|
|
|
|
|
|
this.$set(this.drones, index, { ...item });
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
2025-06-21 12:00:17 +00:00
|
|
|
|
this.droneStates = {};
|
|
|
|
|
|
this.navigationStates = {};
|
|
|
|
|
|
this.qrCodes = {}; // 清理二维码
|
2025-04-01 16:12:21 +00:00
|
|
|
|
clearInterval(this.droneTimers.get(item.BatchId));
|
|
|
|
|
|
this.droneTimers.delete(item.BatchId);
|
|
|
|
|
|
this.handleTimerExpiration(item);
|
2025-04-04 11:58:34 +00:00
|
|
|
|
this.showAudioPrompt = false; // 关闭提示框
|
2025-04-04 11:57:33 +00:00
|
|
|
|
this.iswarning = false;
|
|
|
|
|
|
const media = this.$refs.uavAudio;
|
|
|
|
|
|
media.muted = true; // 静音
|
2025-04-01 16:12:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
}, 1000);
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
handleTimerExpiration(item) {
|
|
|
|
|
|
// 如果drones也需要同步更新
|
|
|
|
|
|
if (this.drones.length === 1) {
|
|
|
|
|
|
this.drones = [];
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.drones = this.drones.filter((d) => d.BatchId !== item.BatchId);
|
|
|
|
|
|
}
|
2025-06-21 12:00:17 +00:00
|
|
|
|
this.$delete(this.droneStates, item.BatchId); // 清理状态
|
|
|
|
|
|
this.$delete(this.navigationStates, item.BatchId); // 清理状态
|
|
|
|
|
|
this.$delete(this.qrCodes, item.BatchId);
|
2025-04-01 16:12:21 +00:00
|
|
|
|
|
2025-06-21 12:00:17 +00:00
|
|
|
|
// 获取 OpenLayers 图层
|
|
|
|
|
|
const graphicLayer = window.olMap
|
|
|
|
|
|
.getLayers()
|
|
|
|
|
|
.getArray()
|
|
|
|
|
|
.find((layer) => layer.get("id") === "uavFiex");
|
|
|
|
|
|
const graphicLayerGJ = window.olMap
|
|
|
|
|
|
.getLayers()
|
|
|
|
|
|
.getArray()
|
|
|
|
|
|
.find((layer) => layer.get("id") === "guiji");
|
|
|
|
|
|
const graphicLayerFSGJX = window.olMap
|
|
|
|
|
|
.getLayers()
|
|
|
|
|
|
.getArray()
|
|
|
|
|
|
.find((layer) => layer.get("id") === "fsguiji");
|
2025-04-01 16:12:21 +00:00
|
|
|
|
|
2025-06-21 12:00:17 +00:00
|
|
|
|
// 清理无人机相关 Feature
|
|
|
|
|
|
if (graphicLayer) {
|
|
|
|
|
|
const graphic = graphicLayer.getSource().getFeatureById(item.BatchId); // 无人机
|
|
|
|
|
|
const appGraphic = graphicLayer
|
|
|
|
|
|
.getSource()
|
|
|
|
|
|
.getFeatureById(item.BatchId + "_app"); // 飞手
|
2025-04-01 16:12:21 +00:00
|
|
|
|
if (graphic) {
|
2025-06-21 12:00:17 +00:00
|
|
|
|
graphicLayer.getSource().removeFeature(graphic);
|
2025-04-01 16:12:21 +00:00
|
|
|
|
}
|
2025-06-21 12:00:17 +00:00
|
|
|
|
if (appGraphic) {
|
|
|
|
|
|
graphicLayer.getSource().removeFeature(appGraphic);
|
2025-04-01 16:12:21 +00:00
|
|
|
|
}
|
2025-06-21 12:00:17 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 清理无人机轨迹
|
|
|
|
|
|
if (graphicLayerGJ) {
|
|
|
|
|
|
const track = graphicLayerGJ
|
|
|
|
|
|
.getSource()
|
|
|
|
|
|
.getFeatureById(item.BatchId + "_track");
|
|
|
|
|
|
if (track) {
|
|
|
|
|
|
graphicLayerGJ.getSource().removeFeature(track);
|
2025-04-01 16:12:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-06-21 12:00:17 +00:00
|
|
|
|
|
|
|
|
|
|
// 清理飞手轨迹
|
|
|
|
|
|
if (graphicLayerFSGJX) {
|
|
|
|
|
|
const appTrack = graphicLayerFSGJX
|
|
|
|
|
|
.getSource()
|
|
|
|
|
|
.getFeatureById(item.BatchId + "_app_track");
|
|
|
|
|
|
if (appTrack) {
|
|
|
|
|
|
graphicLayerFSGJX.getSource().removeFeature(appTrack);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 如果 drones 为空,移除所有相关图层
|
|
|
|
|
|
if (this.drones.length === 0) {
|
|
|
|
|
|
if (graphicLayer) {
|
|
|
|
|
|
window.olMap.removeLayer(graphicLayer);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (graphicLayerGJ) {
|
|
|
|
|
|
window.olMap.removeLayer(graphicLayerGJ);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (graphicLayerFSGJX) {
|
|
|
|
|
|
window.olMap.removeLayer(graphicLayerFSGJX);
|
2025-04-16 14:58:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-04-01 16:12:21 +00:00
|
|
|
|
},
|
2025-03-31 15:26:29 +00:00
|
|
|
|
handleContractClick() {
|
|
|
|
|
|
this.isContracted = !this.isContracted; // 切换状态
|
2025-04-01 16:12:21 +00:00
|
|
|
|
},
|
2025-06-21 12:00:17 +00:00
|
|
|
|
handleDroneClick(drone) {
|
|
|
|
|
|
console.log(drone, "isVisible");
|
|
|
|
|
|
this.$set(
|
|
|
|
|
|
this.droneStates,
|
|
|
|
|
|
drone.BatchId,
|
|
|
|
|
|
!this.droneStates[drone.BatchId]
|
|
|
|
|
|
);
|
|
|
|
|
|
const isVisible = this.droneStates[drone.BatchId];
|
|
|
|
|
|
|
|
|
|
|
|
// 无人机轨迹线
|
2025-06-29 12:02:30 +00:00
|
|
|
|
// let graphicLayerGJ = window.olMap
|
|
|
|
|
|
// .getLayers()
|
|
|
|
|
|
// .getArray()
|
|
|
|
|
|
// .find((layer) => layer.get("id") === "guiji");
|
|
|
|
|
|
// let graphic = graphicLayerGJ
|
|
|
|
|
|
// .getSource()
|
|
|
|
|
|
// .getFeatureById(drone.BatchId + "_track");
|
|
|
|
|
|
// const trackStyle = new Style({
|
|
|
|
|
|
// stroke: new Stroke({
|
|
|
|
|
|
// color: this.getRandomColor(),
|
|
|
|
|
|
// width: 0,
|
|
|
|
|
|
// zIndex: 1
|
|
|
|
|
|
// })
|
|
|
|
|
|
// });
|
|
|
|
|
|
// if (!isVisible) {
|
|
|
|
|
|
// graphic.setStyle(trackStyle);
|
|
|
|
|
|
// } else {
|
|
|
|
|
|
// graphic.setStyle(null);
|
|
|
|
|
|
// }
|
2025-06-21 12:00:17 +00:00
|
|
|
|
|
|
|
|
|
|
// 飞手无人机连接线
|
|
|
|
|
|
let graphicLayerFSGJX = window.olMap
|
|
|
|
|
|
.getLayers()
|
|
|
|
|
|
.getArray()
|
|
|
|
|
|
.find((layer) => layer.get("id") === "fsguiji");
|
|
|
|
|
|
if (!graphicLayerFSGJX) {
|
|
|
|
|
|
graphicLayerFSGJX = new VectorLayer({
|
|
|
|
|
|
source: new VectorSource(),
|
|
|
|
|
|
zIndex: 10
|
2025-04-06 14:39:09 +00:00
|
|
|
|
});
|
2025-06-21 12:00:17 +00:00
|
|
|
|
graphicLayerFSGJX.set("id", "fsguiji");
|
|
|
|
|
|
map.addLayer(graphicLayerFSGJX);
|
|
|
|
|
|
}
|
|
|
|
|
|
let graphiclianjiexian = graphicLayerFSGJX
|
|
|
|
|
|
.getSource()
|
|
|
|
|
|
.getFeatureById(drone.BatchId + "_app_track");
|
|
|
|
|
|
const trackStyleljx = new Style({
|
|
|
|
|
|
stroke: new Stroke({
|
|
|
|
|
|
color: this.getRandomColor(),
|
2025-06-29 12:24:33 +00:00
|
|
|
|
width: 5,
|
2025-06-21 12:00:17 +00:00
|
|
|
|
lineDash: [4, 4],
|
|
|
|
|
|
zIndex: 1
|
|
|
|
|
|
})
|
|
|
|
|
|
});
|
|
|
|
|
|
if (!isVisible) {
|
|
|
|
|
|
graphiclianjiexian.setStyle(trackStyleljx);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
graphiclianjiexian.setStyle(null);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (drone.drone_lon !== 0 && drone.drone_lat !== 0) {
|
|
|
|
|
|
window.olMap.getView().animate({
|
|
|
|
|
|
center: fromLonLat([drone.drone_lon, drone.drone_lat]),
|
2025-06-25 14:27:05 +00:00
|
|
|
|
zoom: window.olMap.getView().getZoom()
|
2025-06-21 12:00:17 +00:00
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
// 随机颜色生成函数
|
|
|
|
|
|
getRandomColor() {
|
|
|
|
|
|
const letters = "0123456789ABCDEF";
|
|
|
|
|
|
let color = "#";
|
2025-06-29 12:24:33 +00:00
|
|
|
|
color += "0";
|
|
|
|
|
|
color += letters[Math.floor(Math.random() * 4)];
|
|
|
|
|
|
color += letters[Math.floor(Math.random() * 16)];
|
|
|
|
|
|
color += letters[Math.floor(Math.random() * 16)];
|
|
|
|
|
|
color += letters[Math.floor(Math.random() * 16)];
|
|
|
|
|
|
color += letters[Math.floor(Math.random() * 16)];
|
2025-06-21 12:00:17 +00:00
|
|
|
|
return color;
|
2025-03-31 15:26:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
|
|
.left-sidebar {
|
|
|
|
|
|
transition: transform 0.5s;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.left-sidebar.contracted {
|
|
|
|
|
|
transform: translateX(-90%);
|
|
|
|
|
|
}
|
2025-06-24 15:33:44 +00:00
|
|
|
|
#uavAudio {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
bottom: -100%;
|
|
|
|
|
|
}
|
2025-06-25 14:27:05 +00:00
|
|
|
|
.alarm-border {
|
2025-04-03 14:28:51 +00:00
|
|
|
|
position: fixed;
|
2025-06-25 14:27:05 +00:00
|
|
|
|
top: 0;
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
right: 0;
|
|
|
|
|
|
bottom: 0;
|
|
|
|
|
|
border: 1px solid transparent;
|
|
|
|
|
|
pointer-events: none; /* Prevent interaction with the border */
|
|
|
|
|
|
z-index: 9999; /* Ensure it appears above other elements */
|
|
|
|
|
|
&.warningAnimatBox {
|
|
|
|
|
|
animation: greenanimated-shadow 2s infinite;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
@keyframes greenanimated-shadow {
|
|
|
|
|
|
0% {
|
2025-06-25 15:29:21 +00:00
|
|
|
|
box-shadow: 0 0 0 0 #ff0000 inset;
|
2025-06-25 14:27:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
85% {
|
2025-06-25 15:29:21 +00:00
|
|
|
|
box-shadow: 0px 0px 100px 0px #ff0000 inset;
|
2025-06-25 14:27:05 +00:00
|
|
|
|
}
|
2025-04-03 14:28:51 +00:00
|
|
|
|
}
|
2025-03-31 15:26:29 +00:00
|
|
|
|
</style>
|