2025-03-31 15:26:29 +00:00
|
|
|
|
<template>
|
|
|
|
|
|
<div class="left-sidebar" :class="{ contracted: isContracted }">
|
|
|
|
|
|
<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-18 15:08:37 +00:00
|
|
|
|
<div class="top">
|
|
|
|
|
|
<div class="left">
|
|
|
|
|
|
{{ index < 9 ? "0" + (index + 1) : index + 1 }}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="text">{{ drone.serial_number }}</div>
|
|
|
|
|
|
<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-21 12:00:17 +00:00
|
|
|
|
<div class="details-all" v-else @click="handleDroneClick(drone)">
|
2025-06-18 15:08:37 +00:00
|
|
|
|
<div class="top">
|
|
|
|
|
|
<div class="left">
|
|
|
|
|
|
{{ index < 9 ? "0" + (index + 1) : index + 1 }}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="text">{{ drone.serial_number }}</div>
|
|
|
|
|
|
<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">
|
|
|
|
|
|
<p class="text">高度:</p>
|
|
|
|
|
|
<p class="characters">{{ drone.height || 0 }}M</p>
|
|
|
|
|
|
</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)"
|
|
|
|
|
|
>
|
|
|
|
|
|
信任
|
|
|
|
|
|
</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-04-03 14:28:51 +00:00
|
|
|
|
style="display: none"
|
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";
|
|
|
|
|
|
import { whitListAdd } from "@/api/whitList.js";
|
|
|
|
|
|
import AMapLoader from "@amap/amap-jsapi-loader";
|
|
|
|
|
|
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: "",
|
|
|
|
|
|
qrCodeUrl: ""
|
2025-03-31 15:26:29 +00:00
|
|
|
|
};
|
|
|
|
|
|
},
|
2025-06-21 12:00:17 +00:00
|
|
|
|
computed: {
|
|
|
|
|
|
...mapGetters(["isZoomedIn"])
|
|
|
|
|
|
},
|
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");
|
|
|
|
|
|
console.log("Initialized time range:", this.startTime, "to", this.endTime);
|
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
|
|
|
|
},
|
|
|
|
|
|
signaData: {
|
|
|
|
|
|
handler(newVal) {
|
|
|
|
|
|
if (newVal) {
|
2025-06-21 12:00:17 +00:00
|
|
|
|
console.log(newVal, "newVal");
|
|
|
|
|
|
// 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-04-01 16:12:21 +00:00
|
|
|
|
newVal.forEach((newItem) => {
|
|
|
|
|
|
// 如果已经存在相同BatchId的数据,重置计时器
|
|
|
|
|
|
if (newItem.BatchId) {
|
|
|
|
|
|
const existingTimer = this.droneTimers.get(newItem.BatchId);
|
|
|
|
|
|
if (existingTimer) {
|
|
|
|
|
|
clearInterval(existingTimer); // 清除旧计时器
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 设置15秒初始时间
|
2025-04-26 08:37:01 +00:00
|
|
|
|
newItem.currTime = window.mapConfig.currTime;
|
2025-04-01 16:12:21 +00:00
|
|
|
|
// 创建新计时器
|
|
|
|
|
|
const timer = this.startTimer(newItem);
|
|
|
|
|
|
this.droneTimers.set(newItem.BatchId, timer);
|
|
|
|
|
|
|
2025-06-21 12:00:17 +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-04-01 16:12:21 +00:00
|
|
|
|
// 更新无人机列表
|
|
|
|
|
|
const existingIndex = this.drones.findIndex(
|
|
|
|
|
|
(d) => d.BatchId === newItem.BatchId
|
|
|
|
|
|
);
|
|
|
|
|
|
newItem.times = moment(newItem.CreateTime).format("HH:mm:ss");
|
2025-06-21 12:00:17 +00:00
|
|
|
|
newItem.distance = parseInt(newItem.distance.toFixed(0));
|
|
|
|
|
|
// newItem.drone_lon = newItem.drone_lon.toFixed(6);
|
|
|
|
|
|
// newItem.drone_lat = newItem.drone_lat.toFixed(6);
|
|
|
|
|
|
|
2025-04-01 16:12:21 +00:00
|
|
|
|
if (existingIndex !== -1) {
|
|
|
|
|
|
this.$set(this.drones, existingIndex, { ...newItem });
|
|
|
|
|
|
} else {
|
2025-06-21 12:00:17 +00:00
|
|
|
|
this.$set(this.drones, this.drones.length, { ...newItem });
|
2025-04-01 16:12:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2025-04-04 11:57:33 +00:00
|
|
|
|
if (newVal.length === 0) {
|
|
|
|
|
|
this.iswarning = false;
|
2025-04-04 12:00:59 +00:00
|
|
|
|
this.showAudioPrompt = false; // 没有数据 不显示提示框
|
2025-04-04 11:57:33 +00:00
|
|
|
|
}
|
2025-04-01 16:12:21 +00:00
|
|
|
|
|
|
|
|
|
|
if (this.drones) {
|
2025-06-21 12:00:17 +00:00
|
|
|
|
mapUavFiex(this.drones, window.olMap);
|
2025-04-01 16:12:21 +00:00
|
|
|
|
}
|
2025-04-02 14:29:18 +00:00
|
|
|
|
let alarm = this.drones.find((d) => d.alarmLevel === 1);
|
2025-06-21 12:00:17 +00:00
|
|
|
|
const media = this.$refs.uavAudio;
|
2025-04-02 14:29:18 +00:00
|
|
|
|
if (alarm) {
|
|
|
|
|
|
this.iswarning = true;
|
2025-04-03 14:28:51 +00:00
|
|
|
|
this.$nextTick(() => {
|
|
|
|
|
|
if (media) {
|
|
|
|
|
|
media.muted = true; // 初始静音
|
|
|
|
|
|
media
|
|
|
|
|
|
.play()
|
|
|
|
|
|
.then(() => {
|
|
|
|
|
|
console.log("播放成功,取消静音");
|
2025-06-21 12:00:17 +00:00
|
|
|
|
if (this.isZoomedIn) {
|
|
|
|
|
|
media.muted = false; // 播放成功后取消静音
|
|
|
|
|
|
} else {
|
|
|
|
|
|
media.muted = true; // 初始静音
|
|
|
|
|
|
}
|
2025-04-03 14:28:51 +00:00
|
|
|
|
})
|
|
|
|
|
|
.catch((error) => {
|
|
|
|
|
|
console.log("播放失败:", error);
|
|
|
|
|
|
this.showAudioPrompt = true; // 播放失败时显示提示框
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2025-04-02 14:29:18 +00:00
|
|
|
|
} else {
|
|
|
|
|
|
this.iswarning = false;
|
2025-04-03 14:28:51 +00:00
|
|
|
|
if (media) {
|
|
|
|
|
|
media.pause(); // 无告警时停止播放
|
|
|
|
|
|
media.currentTime = 0; // 重置到开始
|
|
|
|
|
|
}
|
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-21 12:00:17 +00:00
|
|
|
|
closeNavigation(drone) {
|
|
|
|
|
|
const naviUrl = `https://uri.amap.com/navigation?to=${
|
|
|
|
|
|
drone.app_lon + "," + drone.app_lat
|
|
|
|
|
|
},飞手位置&callnative=1`;
|
|
|
|
|
|
window.open(naviUrl, "_blank"); // '_blank' 表示在新标签页中打开
|
|
|
|
|
|
},
|
|
|
|
|
|
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`;
|
|
|
|
|
|
console.log(naviUrl, "naviUrl");
|
|
|
|
|
|
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,
|
|
|
|
|
|
positionId: [],
|
|
|
|
|
|
company: " ",
|
|
|
|
|
|
mark: " "
|
|
|
|
|
|
};
|
|
|
|
|
|
whitListAdd(params)
|
|
|
|
|
|
.then((res) => {
|
|
|
|
|
|
if (res.code === 0) {
|
|
|
|
|
|
console.log(res, "添加成功");
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
.catch((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;
|
|
|
|
|
|
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-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--;
|
|
|
|
|
|
// 更新显示时间(可选)
|
|
|
|
|
|
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];
|
|
|
|
|
|
|
|
|
|
|
|
// 无人机轨迹线
|
|
|
|
|
|
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);
|
2025-04-01 16:12:21 +00:00
|
|
|
|
} else {
|
2025-06-21 12:00:17 +00:00
|
|
|
|
graphic.setStyle(null);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 飞手无人机连接线
|
|
|
|
|
|
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(),
|
|
|
|
|
|
width: 2,
|
|
|
|
|
|
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]),
|
|
|
|
|
|
zoom: 13
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
// 随机颜色生成函数
|
|
|
|
|
|
getRandomColor() {
|
|
|
|
|
|
const letters = "0123456789ABCDEF";
|
|
|
|
|
|
let color = "#";
|
|
|
|
|
|
for (let i = 0; i < 6; i++) {
|
|
|
|
|
|
color += letters[Math.floor(Math.random() * 16)];
|
2025-04-01 16:12:21 +00:00
|
|
|
|
}
|
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-04-03 14:28:51 +00:00
|
|
|
|
.audio-prompt {
|
|
|
|
|
|
position: fixed;
|
2025-06-21 12:00:17 +00:00
|
|
|
|
top: 0%;
|
2025-04-03 14:28:51 +00:00
|
|
|
|
left: 50%;
|
2025-06-21 12:00:17 +00:00
|
|
|
|
width: 20%;
|
2025-04-03 14:28:51 +00:00
|
|
|
|
height: 10%;
|
|
|
|
|
|
background: rgba(0, 0, 0, 0.5);
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
z-index: 1000;
|
|
|
|
|
|
color: #fff;
|
|
|
|
|
|
border-radius: 5px;
|
|
|
|
|
|
transform: translateX(-50%);
|
2025-06-21 12:00:17 +00:00
|
|
|
|
pointer-events: auto;
|
2025-04-03 14:28:51 +00:00
|
|
|
|
}
|
2025-03-31 15:26:29 +00:00
|
|
|
|
</style>
|