使用高德定位、区分防区无人机
This commit is contained in:
parent
27698dbf0b
commit
68aacde426
|
|
@ -171,7 +171,7 @@ body {
|
|||
width: 100%;
|
||||
height: calc(100% - 140px);
|
||||
margin-top: 25px;
|
||||
pointer-events: none;
|
||||
overflow: hidden;
|
||||
.title {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
|
|
@ -181,7 +181,9 @@ body {
|
|||
height: 100%;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
overflow: auto;
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
touch-action: pan-y; /* 允许垂直方向的触摸滑动 */
|
||||
margin-top: 10px;
|
||||
|
||||
li {
|
||||
|
|
@ -192,6 +194,7 @@ body {
|
|||
margin-top: 3%;
|
||||
position: relative;
|
||||
display: flex;
|
||||
pointer-events: auto;
|
||||
.details-one {
|
||||
width: 60%;
|
||||
height: 100%;
|
||||
|
|
|
|||
|
|
@ -33,7 +33,9 @@
|
|||
<div class="left">
|
||||
{{ index < 9 ? "0" + (index + 1) : index + 1 }}
|
||||
</div>
|
||||
<div class="text">{{ drone.serial_number }}</div>
|
||||
<div class="text" style="font-size: 14px">
|
||||
{{ drone.serial_number }}
|
||||
</div>
|
||||
<div class="img-vector">
|
||||
<img src="@/assets/img/Vector.png" alt="" />
|
||||
</div>
|
||||
|
|
@ -65,7 +67,9 @@
|
|||
<div class="left">
|
||||
{{ index < 9 ? "0" + (index + 1) : index + 1 }}
|
||||
</div>
|
||||
<div class="text">{{ drone.serial_number }}</div>
|
||||
<div class="text" style="font-size: 14px">
|
||||
{{ drone.serial_number }}
|
||||
</div>
|
||||
<div class="img-vector">
|
||||
<img src="@/assets/img/Vector.png" alt="" />
|
||||
</div>
|
||||
|
|
@ -280,7 +284,7 @@ export default {
|
|||
.utc()
|
||||
.subtract(1, "month")
|
||||
.format("YYYY-MM-DD HH:mm:ss");
|
||||
console.log("Initialized time range:", this.startTime, "to", this.endTime);
|
||||
this.enableTouchScroll();
|
||||
},
|
||||
watch: {
|
||||
homeData: {
|
||||
|
|
@ -338,114 +342,118 @@ export default {
|
|||
// Id: "1936279217155215360"
|
||||
// }
|
||||
// ];
|
||||
newVal.forEach((newItem) => {
|
||||
// 如果已经存在相同BatchId的数据,重置计时器
|
||||
if (newItem.BatchId) {
|
||||
const existingTimer = this.droneTimers.get(newItem.BatchId);
|
||||
if (existingTimer) {
|
||||
clearInterval(existingTimer); // 清除旧计时器
|
||||
let positionID = localStorage.getItem("PositionIds");
|
||||
if (positionID === null || positionID === undefined) {
|
||||
const match = newVal.some((item) => positionID.includes(item.id));
|
||||
if (match) {
|
||||
newVal.forEach((newItem) => {
|
||||
// 如果已经存在相同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);
|
||||
|
||||
// 初始化 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);
|
||||
}
|
||||
|
||||
// 更新无人机列表
|
||||
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));
|
||||
|
||||
if (existingIndex !== -1) {
|
||||
this.$set(this.drones, existingIndex, { ...newItem });
|
||||
} else {
|
||||
this.$set(this.drones, this.drones.length, { ...newItem });
|
||||
}
|
||||
}
|
||||
});
|
||||
if (newVal.length === 0) {
|
||||
this.iswarning = false;
|
||||
this.showAudioPrompt = false; // 没有数据 不显示提示框
|
||||
}
|
||||
|
||||
// 设置15秒初始时间
|
||||
newItem.currTime = window.mapConfig.currTime;
|
||||
// 创建新计时器
|
||||
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);
|
||||
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;
|
||||
|
||||
// 更新无人机列表
|
||||
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);
|
||||
|
||||
if (existingIndex !== -1) {
|
||||
this.$set(this.drones, existingIndex, { ...newItem });
|
||||
} else {
|
||||
this.$set(this.drones, this.drones.length, { ...newItem });
|
||||
}
|
||||
}
|
||||
});
|
||||
if (newVal.length === 0) {
|
||||
this.iswarning = false;
|
||||
this.showAudioPrompt = false; // 没有数据 不显示提示框
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
// 如果音频未在播放,则开始播放
|
||||
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 {
|
||||
// 如果音频未在播放,则开始播放
|
||||
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;
|
||||
}
|
||||
};
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log("播放失败:", error);
|
||||
this.showAudioPrompt = true;
|
||||
this.isAudioPlaying = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
} else if (!alarm && this.iswarning) {
|
||||
// 告警消失,停止音频
|
||||
this.iswarning = false;
|
||||
if (media) {
|
||||
media.pause();
|
||||
media.currentTime = 0;
|
||||
this.isAudioPlaying = false;
|
||||
media.onended = null; // 移除结束事件监听
|
||||
this.showAudioPrompt = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
} 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) {
|
||||
this.iswarning = false;
|
||||
this.showAudioPrompt = false;
|
||||
this.isAudioPlaying = false;
|
||||
if (media) {
|
||||
media.pause();
|
||||
media.currentTime = 0;
|
||||
media.onended = null;
|
||||
}
|
||||
vectorSource.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
// 无数据时重置
|
||||
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();
|
||||
}
|
||||
}
|
||||
},
|
||||
deep: true
|
||||
|
|
@ -465,6 +473,24 @@ export default {
|
|||
}
|
||||
},
|
||||
methods: {
|
||||
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();
|
||||
});
|
||||
}
|
||||
},
|
||||
closeNavigation(drone) {
|
||||
console.log(drone.app_lat, drone.app_lon, "导航");
|
||||
// 确保 drone.app_lon 和 drone.app_lat 存在
|
||||
|
|
|
|||
|
|
@ -24,13 +24,13 @@
|
|||
<script>
|
||||
import { mapGetters } from "vuex";
|
||||
import { HomeSyncLocation } from "@/api/home";
|
||||
import Geolocation from "ol/Geolocation";
|
||||
import { fromLonLat, transform } from "ol/proj";
|
||||
import { fromLonLat } from "ol/proj";
|
||||
import { Vector as VectorLayer } from "ol/layer";
|
||||
import VectorSource from "ol/source/Vector";
|
||||
import Point from "ol/geom/Point";
|
||||
import { Style, Icon, Stroke } from "ol/style";
|
||||
import { Style, Icon } from "ol/style";
|
||||
import Feature from "ol/Feature";
|
||||
|
||||
export default {
|
||||
name: "header-top",
|
||||
props: {
|
||||
|
|
@ -51,7 +51,6 @@ export default {
|
|||
lastUpdated: "",
|
||||
timer: null,
|
||||
locationTimer: null,
|
||||
geolocation: null,
|
||||
showPermissionPrompt: false,
|
||||
retryCount: 0,
|
||||
positionLayer: null
|
||||
|
|
@ -61,10 +60,8 @@ export default {
|
|||
...mapGetters(["positionPoint"])
|
||||
},
|
||||
mounted() {
|
||||
console.log("组件挂载,启动定位");
|
||||
this.isAdmins = JSON.parse(localStorage.getItem("isAdmin"));
|
||||
this.updateTime();
|
||||
|
||||
this.timer = setInterval(() => {
|
||||
this.updateTime();
|
||||
}, 1000);
|
||||
|
|
@ -73,24 +70,17 @@ export default {
|
|||
watch: {
|
||||
positionPoint: {
|
||||
handler(newVal) {
|
||||
if (newVal) {
|
||||
// this.$message.success(this.latitude + ", " + this.longitude);
|
||||
console.log("位置更新", newVal, this.latitude, this.longitude);
|
||||
if (newVal && this.latitude && this.longitude && window.olMap) {
|
||||
const newLocation = fromLonLat(
|
||||
[this.longitude, this.latitude],
|
||||
"EPSG:3857"
|
||||
);
|
||||
this.$message.success("定位成功");
|
||||
this.updateMapPosition(this.longitude, this.latitude);
|
||||
const zoomLevel = 13;
|
||||
window.olMap.getView().animate({
|
||||
center: newLocation,
|
||||
zoom: zoomLevel
|
||||
});
|
||||
} else {
|
||||
this.$message.error("定位失败,请稍后重试");
|
||||
}
|
||||
if (newVal && this.latitude && this.longitude && window.olMap) {
|
||||
const newLocation = fromLonLat(
|
||||
[this.longitude, this.latitude],
|
||||
"EPSG:3857"
|
||||
);
|
||||
this.$message.success("定位成功");
|
||||
this.updateMapPosition(this.longitude, this.latitude);
|
||||
window.olMap.getView().animate({
|
||||
center: newLocation,
|
||||
zoom: 13
|
||||
});
|
||||
this.$store.commit("SET_POSITIONPOINT", false);
|
||||
}
|
||||
},
|
||||
|
|
@ -99,19 +89,19 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
updateMapPosition(lng, lat) {
|
||||
// 移除旧的 positionLayer(如果存在)
|
||||
// Remove existing position layer
|
||||
if (this.positionLayer) {
|
||||
window.olMap.removeLayer(this.positionLayer);
|
||||
this.positionLayer = null;
|
||||
}
|
||||
let center = fromLonLat([lng, lat]);
|
||||
var iconFeature = new Feature({
|
||||
|
||||
const center = fromLonLat([lng, lat], "EPSG:3857");
|
||||
const iconFeature = new Feature({
|
||||
geometry: new Point(center),
|
||||
name: "当前位置",
|
||||
population: 4000,
|
||||
rainfall: 500
|
||||
name: "当前位置"
|
||||
});
|
||||
var iconStyle = new Style({
|
||||
|
||||
const iconStyle = new Style({
|
||||
image: new Icon({
|
||||
anchor: [0.5, 46],
|
||||
scale: 0.4,
|
||||
|
|
@ -120,10 +110,12 @@ export default {
|
|||
src: require("@/assets/img/icon_dev.png")
|
||||
})
|
||||
});
|
||||
|
||||
iconFeature.setStyle(iconStyle);
|
||||
var vectorSource = new VectorSource({
|
||||
const vectorSource = new VectorSource({
|
||||
features: [iconFeature]
|
||||
});
|
||||
|
||||
this.positionLayer = new VectorLayer({
|
||||
source: vectorSource
|
||||
});
|
||||
|
|
@ -136,94 +128,88 @@ export default {
|
|||
this.currentDate = now.toLocaleDateString();
|
||||
},
|
||||
startTracking() {
|
||||
if (!window.olMap) {
|
||||
console.error("OpenLayers 地图未传入,延迟重试");
|
||||
if (!window.AMap) {
|
||||
console.error("高德地图 SDK 未加载,延迟重试");
|
||||
this.$message.error("高德地图 SDK 加载失败");
|
||||
setTimeout(() => this.startTracking(), 1000);
|
||||
return;
|
||||
}
|
||||
|
||||
// 清除旧的 locationTimer
|
||||
// Clear existing location timer
|
||||
if (this.locationTimer) {
|
||||
clearInterval(this.locationTimer);
|
||||
}
|
||||
|
||||
// 初始化 Geolocation
|
||||
this.geolocation = new Geolocation({
|
||||
trackingOptions: {
|
||||
// Initialize AMap Geolocation
|
||||
AMap.plugin("AMap.Geolocation", () => {
|
||||
const geolocation = new AMap.Geolocation({
|
||||
enableHighAccuracy: true,
|
||||
timeout: 30000,
|
||||
maximumAge: 10000
|
||||
},
|
||||
projection: window.olMap.getView().getProjection()
|
||||
});
|
||||
maximumAge: 10000,
|
||||
zoomToAccuracy: true
|
||||
});
|
||||
|
||||
// 监听定位错误
|
||||
this.geolocation.on("error", (error) => {
|
||||
let message = "";
|
||||
this.retryCount = this.retryCount || 0;
|
||||
switch (error.code) {
|
||||
case error.PERMISSION_DENIED:
|
||||
message = "请允许地理位置权限";
|
||||
this.showPermissionPrompt = true;
|
||||
this.$message.error("请在浏览器设置中启用地理位置权限");
|
||||
break;
|
||||
case error.POSITION_UNAVAILABLE:
|
||||
message = "无法获取位置信息";
|
||||
if (this.retryCount < 3) {
|
||||
this.retryCount++;
|
||||
setTimeout(() => this.startTracking(), 5000);
|
||||
} else {
|
||||
this.$message.error("多次尝试后仍无法定位,请检查设备设置");
|
||||
// Handle geolocation errors
|
||||
geolocation.on("error", (error) => {
|
||||
let message = "";
|
||||
this.retryCount = this.retryCount || 0;
|
||||
|
||||
switch (error.info) {
|
||||
case "PERMISSION_DENIED":
|
||||
message = "请允许地理位置权限";
|
||||
this.showPermissionPrompt = true;
|
||||
this.$message.error("请在浏览器设置中启用地理位置权限");
|
||||
break;
|
||||
case "POSITION_UNAVAILABLE":
|
||||
message = "无法获取位置信息";
|
||||
if (this.retryCount < 3) {
|
||||
this.retryCount++;
|
||||
setTimeout(() => this.startTracking(), 5000);
|
||||
} else {
|
||||
this.$message.error("多次尝试后仍无法定位,请检查设备设置");
|
||||
}
|
||||
break;
|
||||
case "TIMEOUT":
|
||||
message = "获取位置超时";
|
||||
if (this.retryCount < 3) {
|
||||
this.retryCount++;
|
||||
setTimeout(() => this.startTracking(), 5000);
|
||||
} else {
|
||||
this.$message.error("定位超时,请检查网络或 GPS 信号");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
message = "未知错误";
|
||||
}
|
||||
this.leftText = message;
|
||||
this.rightText = "定位异常";
|
||||
});
|
||||
|
||||
// Start continuous tracking
|
||||
this.locationTimer = setInterval(() => {
|
||||
geolocation.getCurrentPosition((status, result) => {
|
||||
if (status === "complete") {
|
||||
this.handleSuccess(result.position);
|
||||
}
|
||||
break;
|
||||
case error.TIMEOUT:
|
||||
message = "获取位置超时";
|
||||
if (this.retryCount < 3) {
|
||||
this.retryCount++;
|
||||
setTimeout(() => this.startTracking(), 5000);
|
||||
} else {
|
||||
this.$message.error("定位超时,请检查网络或 GPS 信号");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
message = "未知错误";
|
||||
}
|
||||
this.leftText = message;
|
||||
this.rightText = "定位异常";
|
||||
});
|
||||
}, 2000);
|
||||
});
|
||||
|
||||
// 开启定位
|
||||
this.geolocation.setTracking(true);
|
||||
|
||||
// 每 2 秒传递一次经纬度
|
||||
this.locationTimer = setInterval(() => {
|
||||
const coordinates = this.geolocation.getPosition();
|
||||
if (coordinates) {
|
||||
this.handleSuccess(coordinates);
|
||||
}
|
||||
}, 2000);
|
||||
},
|
||||
handleSuccess(coordinates) {
|
||||
// 转换为 WGS84 坐标
|
||||
const wgs84 = transform(coordinates, "EPSG:3857", "EPSG:4326");
|
||||
this.longitude = wgs84[0];
|
||||
this.latitude = wgs84[1];
|
||||
this.lastUpdated = new Date().toLocaleString(); //EPSG:3857 转 EPSG:4326
|
||||
handleSuccess(position) {
|
||||
this.longitude = position.lng;
|
||||
this.latitude = position.lat;
|
||||
this.lastUpdated = new Date().toLocaleString();
|
||||
this.showPermissionPrompt = false;
|
||||
this.retryCount = 0;
|
||||
|
||||
// 传递经纬度到 API
|
||||
let params = {
|
||||
this.updateMapPosition(this.longitude, this.latitude);
|
||||
|
||||
const params = {
|
||||
lat: this.latitude,
|
||||
lon: this.longitude,
|
||||
userId: localStorage.getItem("userId")
|
||||
};
|
||||
this.updateMapPosition(this.longitude, this.latitude);
|
||||
// console.log("触发上报:", {
|
||||
// latitude: this.latitude,
|
||||
// longitude: this.longitude,
|
||||
// time: this.lastUpdated
|
||||
// });
|
||||
|
||||
HomeSyncLocation(params)
|
||||
.then((res) => {
|
||||
if (res.code === 0) {
|
||||
|
|
@ -246,9 +232,6 @@ export default {
|
|||
}
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.geolocation) {
|
||||
this.geolocation.setTracking(false);
|
||||
}
|
||||
if (this.timer) {
|
||||
clearInterval(this.timer);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -342,9 +342,9 @@ export default {
|
|||
});
|
||||
},
|
||||
onMapLoad(map) {
|
||||
setTimeout(() => {
|
||||
this.initPositon();
|
||||
}, 2000);
|
||||
// setTimeout(() => {
|
||||
// this.initPositon();
|
||||
// }, 2000);
|
||||
// 地图加载完成后的处理
|
||||
const camera = window.mapConfig || {};
|
||||
if (camera.isCamera) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue