ly-front/src/views/contentData/LeftSidebar/index.vue

796 lines
26 KiB
Vue
Raw Normal View History

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="{
height: droneStates[drone.BatchId] ? '60px' : '372px',
2025-06-18 15:08:37 +00:00
padding: 0
}"
2025-04-01 16:12:21 +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>
<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>
<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>
<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>
<!-- <div class="content-serial">
2025-06-18 15:08:37 +00:00
<span class="color-ef"> 序列号</span>
<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>
<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>
<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>
<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>
</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">
<span class="color-ef-fw">飞手位置</span>
2025-06-18 15:08:37 +00:00
</div>
<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">
{{ 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">
<el-button
type="primary"
@click.stop="handlewhiteList(drone)"
>
2025-06-25 15:29:21 +00:00
{{ !drone.IsWhitelist ? "信任" : "不信任" }}
</el-button>
2025-06-18 15:52:42 +00:00
</div>
<div class="btn-navigation">
<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>
<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>
</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>
<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">
<el-button
type="primary"
@click.stop="closeNavigation(drone)"
>
</el-button>
2025-06-19 15:41:07 +00:00
</div>
<div class="btn-navigation">
<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"
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>
import { mapGetters } from "vuex";
2025-04-01 16:12:21 +00:00
import moment from "moment";
import { mapUavFiex } from "../index.js";
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";
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: "今日预警",
value: 0
2025-03-31 15:26:29 +00:00
},
{
id: "2",
name: "累计预警",
value: 0
2025-03-31 15:26:29 +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,
showAudioPrompt: false,
startTime: "", // 初始化时间范围
endTime: "",
2025-06-25 14:27:05 +00:00
qrCodeUrl: "",
isAudioPlaying: false // 跟踪音频播放状态
2025-03-31 15:26:29 +00:00
};
},
computed: {
2025-06-22 09:42:09 +00:00
...mapGetters(["isZoomedIn", "SliderValue"])
},
2025-06-19 15:41:07 +00:00
mounted() {
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
},
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) {
// 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);
// 初始化 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");
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 {
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) {
mapUavFiex(this.drones, window.olMap);
2025-04-01 16:12:21 +00:00
}
const media = this.$refs.uavAudio;
2025-06-25 14:27:05 +00:00
let alarm = this.drones.find((d) => d.alarmLevel === 1);
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; // 初始静音
2025-06-25 14:27:05 +00:00
const savedVolume = localStorage.getItem("soundValue");
media.volume = savedVolume !== null ? savedVolume / 100 : 1;
media.muted = this.isZoomedIn ? false : true;
// 如果音频未在播放,则开始播放
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;
this.isAudioPlaying = false;
});
}
2025-04-03 14:28:51 +00:00
}
});
2025-06-25 14:27:05 +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;
}
}
// 无数据时重置
if (newVal.length === 0) {
2025-04-02 14:29:18 +00:00
this.iswarning = false;
2025-06-25 14:27:05 +00:00
this.showAudioPrompt = false;
this.isAudioPlaying = false;
2025-04-03 14:28:51 +00:00
if (media) {
2025-06-25 14:27:05 +00:00
media.pause();
media.currentTime = 0;
media.onended = null;
2025-04-03 14:28:51 +00:00
}
2025-06-25 14:27:05 +00:00
vectorSource.clear();
2025-04-02 14:29:18 +00:00
}
2025-04-01 16:12:21 +00:00
}
},
deep: true
},
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: {
closeNavigation(drone) {
2025-06-24 15:33:44 +00:00
console.log(drone.app_lat, drone.app_lon, "导航");
// 确保 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);
},
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
);
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
},
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],
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);
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--;
// 更新显示时间(可选)
const index = this.drones.findIndex(
(d) => d.BatchId === item.BatchId
);
if (index !== -1) {
this.$set(this.drones, index, { ...item });
}
} else {
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);
}
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
// 获取 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
// 清理无人机相关 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) {
graphicLayer.getSource().removeFeature(graphic);
2025-04-01 16:12:21 +00:00
}
if (appGraphic) {
graphicLayer.getSource().removeFeature(appGraphic);
2025-04-01 16:12:21 +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
}
}
// 清理飞手轨迹
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
},
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 {
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
});
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]),
2025-06-25 14:27:05 +00:00
zoom: window.olMap.getView().getZoom()
});
}
},
// 随机颜色生成函数
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
}
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>