更改底图颜色

This commit is contained in:
zengmingjie 2025-06-22 17:42:09 +08:00
parent d8f87fdf88
commit 0e36765929
13 changed files with 634 additions and 143 deletions

6
package-lock.json generated
View File

@ -14,6 +14,7 @@
"@vue-office/excel": "^1.7.11", "@vue-office/excel": "^1.7.11",
"@vue-office/pdf": "^2.0.10", "@vue-office/pdf": "^2.0.10",
"axios": "^1.1.3", "axios": "^1.1.3",
"be-full": "^0.1.4",
"core-js": "^3.8.3", "core-js": "^3.8.3",
"echarts": "^5.5.1", "echarts": "^5.5.1",
"echarts-gl": "^2.0.9", "echarts-gl": "^2.0.9",
@ -5289,6 +5290,11 @@
"integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==",
"dev": true "dev": true
}, },
"node_modules/be-full": {
"version": "0.1.4",
"resolved": "https://registry.npmmirror.com/be-full/-/be-full-0.1.4.tgz",
"integrity": "sha512-Nj3yBvk8rxhBhDv6YROxP9ynTA5H0l9lMjU+XqEAY4rTLJ68l2+n0geWCoeTqAxhOFedtbmYCpxFzMxMA8CnUg=="
},
"node_modules/big.js": { "node_modules/big.js": {
"version": "5.2.2", "version": "5.2.2",
"resolved": "https://registry.npmmirror.com/big.js/-/big.js-5.2.2.tgz", "resolved": "https://registry.npmmirror.com/big.js/-/big.js-5.2.2.tgz",

View File

@ -19,6 +19,7 @@
"@vue-office/excel": "^1.7.11", "@vue-office/excel": "^1.7.11",
"@vue-office/pdf": "^2.0.10", "@vue-office/pdf": "^2.0.10",
"axios": "^1.1.3", "axios": "^1.1.3",
"be-full": "^0.1.4",
"core-js": "^3.8.3", "core-js": "^3.8.3",
"echarts": "^5.5.1", "echarts": "^5.5.1",
"echarts-gl": "^2.0.9", "echarts-gl": "^2.0.9",

View File

@ -83,7 +83,7 @@
height: 100%; height: 100%;
display: flex; display: flex;
align-items: center; align-items: center;
flex-wrap: wrap; flex-wrap: nowrap;
.el-form-item { .el-form-item {
margin-right: 3%; margin-right: 3%;
margin-bottom: 13px; margin-bottom: 13px;
@ -596,3 +596,60 @@
.el-picker-panel__icon-btn { .el-picker-panel__icon-btn {
color: #fff; color: #fff;
} }
.custom-class {
.el-dialog {
height: 50% !important;
.el-dialog__header {
.el-dialog__headerbtn {
top: 30px;
right: 40px;
}
}
.el-dialog__body {
height: calc(100% - 140px);
.block {
width: 80%;
margin: 0 auto;
display: flex;
align-items: center;
.demonstration {
width: 100px;
color: #fff;
}
.el-slider {
width: calc(100% - 120px);
}
}
}
.el-dialog__footer {
}
}
}
.custom-table {
.el-dialog {
height: 80% !important;
.el-dialog__header {
.el-dialog__headerbtn {
top: 30px;
right: 40px;
}
}
.el-dialog__body {
height: calc(100% - 110px);
.table-container {
height: calc(100% - 50px);
margin-top: 0;
padding-top: 0;
.table-box {
height: 90%;
.el-table__body-wrapper {
overflow: auto;
}
}
}
}
.el-dialog__footer {
}
}
}

View File

@ -32,7 +32,8 @@ import {
Upload, Upload,
Dropdown, Dropdown,
DropdownMenu, DropdownMenu,
DropdownItem DropdownItem,
Slider
} from "element-ui"; } from "element-ui";
import "element-ui/lib/theme-chalk/index.css"; import "element-ui/lib/theme-chalk/index.css";
@ -67,6 +68,7 @@ Vue.use(Switch);
Vue.use(Timeline); Vue.use(Timeline);
Vue.use(TimelineItem); Vue.use(TimelineItem);
Vue.use(Upload); Vue.use(Upload);
Vue.use(Slider);
Vue.prototype.$message = Message; Vue.prototype.$message = Message;
Vue.prototype.$confirm = MessageBox.confirm; Vue.prototype.$confirm = MessageBox.confirm;

View File

@ -8,6 +8,9 @@ const getters = {
targetCode: (state) => state.chart.targetCode, //防护目标单一点击更改两侧数据 targetCode: (state) => state.chart.targetCode, //防护目标单一点击更改两侧数据
airspaceCode: (state) => state.chart.airspaceCode, //低空空域单一点击更改两侧数据 airspaceCode: (state) => state.chart.airspaceCode, //低空空域单一点击更改两侧数据
positionPoint: (state) => state.chart.positionPoint, //实时位置更新 positionPoint: (state) => state.chart.positionPoint, //实时位置更新
isZoomedIn: (state) => state.chart.isZoomedIn //音频是否打开 isZoomedIn: (state) => state.chart.isZoomedIn, //音频是否打开
SliderValue: (state) => state.chart.SliderValue, //音量值
checkFlag: (state) => state.chart.checkFlag, //轨迹查看按钮
clearTrajectory: (state) => state.chart.clearTrajectory //清空轨迹
}; };
export default getters; export default getters;

View File

@ -11,7 +11,10 @@ const user = {
airspaceCode: {}, airspaceCode: {},
positionPoint: false, // 位置上报 positionPoint: false, // 位置上报
isZoomedIn: true // 音频是否打开 isZoomedIn: true, // 音频是否打开
SliderValue: 0, // 音频滑动条值
checkFlag: false, // 轨迹查看按钮
clearTrajectory: false // 清除过往轨迹
}, },
mutations: { mutations: {
@ -38,6 +41,15 @@ const user = {
}, },
SET_ISZOOMEDIN: (state, value) => { SET_ISZOOMEDIN: (state, value) => {
state.isZoomedIn = value; state.isZoomedIn = value;
},
SET_SILDERVALUE: (state, value) => {
state.SliderValue = value;
},
SET_CHECKFLAG: (state, value) => {
state.checkFlag = value;
},
SET_CLEARTRAJECTORY: (state, value) => {
state.clearTrajectory = value;
} }
}, },

View File

@ -190,7 +190,7 @@
loop loop
ref="uavAudio" ref="uavAudio"
v-show="iswarning" v-show="iswarning"
style="display: none" style="display: none; pointer-events: auto"
id="uavAudio" id="uavAudio"
> >
<source src="@/assets/img/wargin.mp3" type="audio/mpeg" /> <source src="@/assets/img/wargin.mp3" type="audio/mpeg" />
@ -211,7 +211,6 @@ import Style from "ol/style/Style";
import Stroke from "ol/style/Stroke"; import Stroke from "ol/style/Stroke";
import { fromLonLat, toLonLat } from "ol/proj"; import { fromLonLat, toLonLat } from "ol/proj";
import { whitListAdd } from "@/api/whitList.js"; import { whitListAdd } from "@/api/whitList.js";
import AMapLoader from "@amap/amap-jsapi-loader";
import QRCode from "qrcode"; import QRCode from "qrcode";
export default { export default {
@ -257,7 +256,7 @@ export default {
}; };
}, },
computed: { computed: {
...mapGetters(["isZoomedIn"]) ...mapGetters(["isZoomedIn", "SliderValue"])
}, },
mounted() { mounted() {
this.endTime = moment.utc().format("YYYY-MM-DD HH:mm:ss"); this.endTime = moment.utc().format("YYYY-MM-DD HH:mm:ss");
@ -276,6 +275,18 @@ export default {
}, },
deep: true deep: true
}, },
SliderValue: {
handler(newVal) {
if (newVal) {
console.log("SliderValue:", newVal);
const media = this.$refs.uavAudio;
if (media) {
media.volume = newVal / 100;
}
}
},
deep: true
},
signaData: { signaData: {
handler(newVal) { handler(newVal) {
if (newVal) { if (newVal) {
@ -359,8 +370,9 @@ export default {
if (this.drones) { if (this.drones) {
mapUavFiex(this.drones, window.olMap); mapUavFiex(this.drones, window.olMap);
} }
let alarm = this.drones.find((d) => d.alarmLevel === 1); let alarm = this.drones.find((d) => d.alarmLevel === 0);
const media = this.$refs.uavAudio; const media = this.$refs.uavAudio;
const savedVolume = localStorage.getItem("soundValue");
if (alarm) { if (alarm) {
this.iswarning = true; this.iswarning = true;
this.$nextTick(() => { this.$nextTick(() => {
@ -370,6 +382,11 @@ export default {
.play() .play()
.then(() => { .then(() => {
console.log("播放成功,取消静音"); console.log("播放成功,取消静音");
if (savedVolume !== null) {
media.volume = savedVolume / 100;
} else {
media.volume = 1;
}
if (this.isZoomedIn) { if (this.isZoomedIn) {
media.muted = false; // media.muted = false; //
} else { } else {
@ -468,6 +485,7 @@ export default {
enableAudio() { enableAudio() {
this.iswarning = true; this.iswarning = true;
const media = this.$refs.uavAudio; const media = this.$refs.uavAudio;
const savedVolume = localStorage.getItem("soundValue");
let time = setInterval(() => { let time = setInterval(() => {
console.log("用户手动启用音频", media); console.log("用户手动启用音频", media);
if (media !== undefined) { if (media !== undefined) {
@ -477,6 +495,11 @@ export default {
} else { } else {
media.muted = true; // media.muted = true; //
} }
if (savedVolume !== null) {
media.volume = savedVolume / 100;
} else {
media.volume = 1;
}
media media
.play() .play()
.then(() => { .then(() => {

View File

@ -25,6 +25,7 @@
import { mapGetters } from "vuex"; import { mapGetters } from "vuex";
import { HomeSyncLocation } from "@/api/home"; import { HomeSyncLocation } from "@/api/home";
import _ from "lodash"; import _ from "lodash";
import { fromLonLat } from "ol/proj";
export default { export default {
name: "header-top", name: "header-top",
@ -41,12 +42,13 @@ export default {
isAdmins: false, isAdmins: false,
leftText: "平台已连接", leftText: "平台已连接",
rightText: "定位正常", rightText: "定位正常",
latitude: null, latitude: "",
longitude: null, longitude: "",
lastUpdated: "", lastUpdated: "",
watchId: null, watchId: null,
timer: null, timer: null,
showPermissionPrompt: false showPermissionPrompt: false,
retryCount: 0
}; };
}, },
computed: { computed: {
@ -60,14 +62,15 @@ export default {
this.timer = setInterval(() => { this.timer = setInterval(() => {
this.updateTime(); this.updateTime();
}, 1000); }, 1000);
this.$on("retry-tracking", this.startTracking);
}, },
watch: { watch: {
positionPoint: { positionPoint: {
handler(newVal, oldVal) { handler(newVal) {
if (newVal) { if (newVal && this.latitude && this.longitude) {
console.log("定位更新:", this.latitude, this.longitude); const newLocation = fromLonLat([this.longitude, this.latitude]);
const newLocation = [this.longitude, this.latitude]; // this.$message.success(this.longitude + "," + this.latitude);
const zoomLevel = 13; // const zoomLevel = 13;
window.olMap.getView().animate({ window.olMap.getView().animate({
center: newLocation, center: newLocation,
zoom: zoomLevel zoom: zoomLevel
@ -75,9 +78,9 @@ export default {
this.startTracking(); this.startTracking();
} }
this.$store.commit("SET_POSITIONPOINT", false); this.$store.commit("SET_POSITIONPOINT", false);
} },
}, deep: true
deep: true }
}, },
methods: { methods: {
updateTime() { updateTime() {
@ -97,9 +100,9 @@ export default {
(position) => this.handleSuccess(position), (position) => this.handleSuccess(position),
(error) => this.handleError(error), (error) => this.handleError(error),
{ {
enableHighAccuracy: false, enableHighAccuracy: true,
timeout: 15000, timeout: 30000,
maximumAge: 0 maximumAge: 10000
} }
); );
}, },
@ -119,13 +122,17 @@ export default {
if (res.code === 0) { if (res.code === 0) {
this.leftText = "平台已连接"; this.leftText = "平台已连接";
this.rightText = "定位正常"; this.rightText = "定位正常";
if (!latitude && res.data.fallbackLocation) {
this.handleSuccess({
coords: { latitude: this.latitude, longitude: this.longitude }
});
}
} else { } else {
this.leftText = "平台连接失败"; this.leftText = "平台连接失败";
this.rightText = "定位异常"; this.rightText = "定位异常";
} }
}) })
.catch((err) => { .catch((err) => {
console.error("上报失败:", err);
this.leftText = "平台连接失败"; this.leftText = "平台连接失败";
this.rightText = "定位异常"; this.rightText = "定位异常";
}); });
@ -135,10 +142,12 @@ export default {
this.longitude = position.coords.longitude; this.longitude = position.coords.longitude;
this.lastUpdated = new Date().toLocaleString(); this.lastUpdated = new Date().toLocaleString();
this.showPermissionPrompt = false; this.showPermissionPrompt = false;
this.retryCount = 0;
this.syncLocation(this.latitude, this.longitude); this.syncLocation(this.latitude, this.longitude);
}, },
handleError(error) { handleError(error) {
let message = ""; let message = "";
this.retryCount = this.retryCount || 0;
switch (error.code) { switch (error.code) {
case error.PERMISSION_DENIED: case error.PERMISSION_DENIED:
message = "请允许地理位置权限"; message = "请允许地理位置权限";
@ -147,21 +156,31 @@ export default {
break; break;
case error.POSITION_UNAVAILABLE: case error.POSITION_UNAVAILABLE:
message = "无法获取位置信息"; message = "无法获取位置信息";
setTimeout(() => this.startTracking(), 5000); if (this.retryCount < 3) {
this.retryCount++;
setTimeout(() => this.startTracking(), 5000);
} else {
this.$message.error("多次尝试后仍无法定位,请检查设备设置");
}
break; break;
case error.TIMEOUT: case error.TIMEOUT:
message = "获取位置超时"; message = "获取位置超时";
setTimeout(() => this.startTracking(), 5000); if (this.retryCount < 3) {
this.retryCount++;
setTimeout(() => this.startTracking(), 5000);
} else {
this.$message.error("定位超时,请检查网络或 GPS 信号");
}
break; break;
default: default:
message = "未知错误"; message = "未知错误";
} }
this.leftText = message; this.leftText = message;
this.rightText = "定位异常"; this.rightText = "定位异常";
console.error("定位错误:", error);
}, },
retryTracking() { retryTracking() {
this.showPermissionPrompt = false; this.showPermissionPrompt = false;
this.retryCount = 0;
this.startTracking(); this.startTracking();
} }
}, },
@ -181,11 +200,9 @@ export default {
font-size: 20px; font-size: 20px;
font-weight: bold; font-weight: bold;
} }
.time { .time {
font-size: 14px; font-size: 14px;
} }
.actions span { .actions span {
margin-left: 10px; margin-left: 10px;
cursor: pointer; cursor: pointer;
@ -198,7 +215,8 @@ export default {
padding: 15px; padding: 15px;
border: 1px solid #ddd; border: 1px solid #ddd;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
z-index: 1000; z-index: 10000;
pointer-events: auto;
} }
.permission-prompt p { .permission-prompt p {
margin: 0 0 10px; margin: 0 0 10px;

View File

@ -1,18 +1,10 @@
<template> <template>
<fit-screen :width="1280" :height="800" mode="fit"> <!-- <fit-screen :width="1280" :height="800" mode="fit"> -->
<div id="home"> <div id="home">
<contentData <contentData id="contentData" :signaData="signaData" :homeData="homeData" />
id="contentData" <map-control id="mapControl" :signaData="signaData" :homeData="homeData" />
:signaData="signaData" </div>
:homeData="homeData" <!-- </fit-screen> -->
/>
<map-control
id="mapControl"
:signaData="signaData"
:homeData="homeData"
/>
</div>
</fit-screen>
</template> </template>
<script> <script>
@ -21,6 +13,7 @@ import mapControl from "./mapControl/index.vue";
import contentData from "./contentData/index.vue"; import contentData from "./contentData/index.vue";
import { Homeview } from "@/api/home.js"; import { Homeview } from "@/api/home.js";
import * as signalR from "@microsoft/signalr"; import * as signalR from "@microsoft/signalr";
import { beFull } from "be-full";
export default { export default {
name: "HomeIndex", name: "HomeIndex",
data() { data() {
@ -44,6 +37,21 @@ export default {
this.timeInterval = setInterval(() => { this.timeInterval = setInterval(() => {
this.initHomeData(); this.initHomeData();
}, 2000); }, 2000);
//
this.$confirm("是否全屏?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
beFull();
})
.catch(() => {
this.$message({
type: "info",
message: "已取消"
});
});
}, },
methods: { methods: {
initHomeData() { initHomeData() {

View File

@ -37,7 +37,6 @@
<script> <script>
import { login, loginPosition } from "@/api/login.js"; import { login, loginPosition } from "@/api/login.js";
export default { export default {
name: "my-Login", // name: "my-Login", //
data() { data() {
@ -48,7 +47,8 @@ export default {
}, },
errors: {}, errors: {},
value: "", value: "",
tipShow: false tipShow: false,
positionList: []
}; };
}, },
mounted() { mounted() {
@ -91,6 +91,7 @@ export default {
loginPosition(arrParams).then((positionRes) => { loginPosition(arrParams).then((positionRes) => {
if (positionRes.code === 0) { if (positionRes.code === 0) {
localStorage.setItem("PositionIds", positionRes.data); // localStorage.setItem("PositionIds", positionRes.data); //
this.$message.success("登录成功");
} else { } else {
this.$message.error(positionRes.msg); this.$message.error(positionRes.msg);
} }

View File

@ -3,11 +3,14 @@
<div class="zoom-level" @click="soundAndMenu"> <div class="zoom-level" @click="soundAndMenu">
<img :src="zoomLevelImage" alt="" /> <img :src="zoomLevelImage" alt="" />
</div> </div>
<div class="btn-container" v-if="closeBtnVisible">
<el-button @click="handleClickClose()">返回</el-button>
</div>
<div id="map" ref="olMap" class="map-container"></div> <div id="map" ref="olMap" class="map-container"></div>
<div class="pointingNorth" @click="mapNorth"> <div class="pointingNorth">
<img src="@/assets/img/user.png" alt="" /> <img src="@/assets/img/user.png" alt="" @click="userOpen" />
<img src="@/assets/img/setup.png" alt="" /> <img src="@/assets/img/setup.png" alt="" @click="setupOpen" />
<img src="@/assets/img/query.png" alt="" /> <img src="@/assets/img/query.png" alt="" @click="queryOpen" />
</div> </div>
<div class="configuration"> <div class="configuration">
<div class="refresh" @click="refreshClick"> <div class="refresh" @click="refreshClick">
@ -20,6 +23,33 @@
<img src="@/assets/img/icon_model.png" alt="" /> <img src="@/assets/img/icon_model.png" alt="" />
</div> </div>
</div> </div>
<el-dialog
title="设置"
:visible.sync="dialogVisible"
width="50%"
:before-close="handleClose"
append-to-body
class="custom-class"
>
<div class="block">
<span class="demonstration">预警声音设置</span>
<el-slider v-model="value2"></el-slider>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="determine"> </el-button>
</span>
</el-dialog>
<el-dialog
title="查询"
:visible.sync="dialogQueryVisible"
width="90%"
:before-close="handleClose"
append-to-body
class="custom-table"
>
<AlertDialog />
</el-dialog>
</div> </div>
</template> </template>
@ -30,31 +60,32 @@ import View from "ol/View";
import TileLayer from "ol/layer/Tile"; import TileLayer from "ol/layer/Tile";
import { fromLonLat } from "ol/proj"; import { fromLonLat } from "ol/proj";
import XYZ from "ol/source/XYZ"; import XYZ from "ol/source/XYZ";
import { Feature, Overlay } from "ol";
import VectorLayer from "ol/layer/Vector"; import { Point, MultiPolygon } from "ol/geom";
import VectorSource from "ol/source/Vector"; import { Vector as VectorLayer } from "ol/layer";
import Feature from "ol/Feature"; import { Vector as VectorSource } from "ol/source";
import Point from "ol/geom/Point"; import { Style, Fill, Stroke, Circle } from "ol/style";
import LineString from "ol/geom/LineString"; import GeoJSON from "ol/format/GeoJSON";
import Style from "ol/style/Style"; import AlertDialog from "../menuData/AlertDialog.vue";
import Icon from "ol/style/Icon"; import { devPositionList } from "@/api/position.js";
import Stroke from "ol/style/Stroke";
import Fill from "ol/style/Fill";
import Text from "ol/style/Text";
import CircleStyle from "ol/style/Circle";
import Static from "ol/source/ImageStatic.js";
import uaImg from "@/assets/img/icon_uav.png";
export default { export default {
name: "HomeMap", name: "HomeMap",
components: {
AlertDialog
},
data() { data() {
return { return {
map: null, map: null,
zoomLevel: null, zoomLevel: null,
isZoomedIn: true, isZoomedIn: true,
isZoomedOut: false, isZoomedOut: false,
showPermissionPrompt: false showPermissionPrompt: false,
dialogVisible: false,
value2: 0,
currentBaseMap: "gaode",
dialogQueryVisible: false,
closeBtnVisible: false
}; };
}, },
created() { created() {
@ -65,14 +96,127 @@ export default {
this.initMap(); this.initMap();
}, },
computed: { computed: {
...mapGetters(["statePage", "cityCode"]), ...mapGetters(["statePage", "cityCode", "checkFlag"]),
zoomLevelImage() { zoomLevelImage() {
return this.isZoomedIn return this.isZoomedIn
? require("@/assets/img/sound.png") ? require("@/assets/img/sound.png")
: require("@/assets/img/mute.png"); : require("@/assets/img/mute.png");
} }
}, },
watch: {
checkFlag: {
handler(newVal) {
this.closeBtnVisible = newVal;
this.dialogQueryVisible = false;
},
deep: true
}
},
methods: { methods: {
handleClickClose() {
this.$store.commit("SET_CHECKFLAG", false);
this.$store.commit("SET_CLEARTRAJECTORY", true);
},
initPositon() {
let positionIds = {
pageNum: 1,
pageSize: 10000
};
devPositionList(positionIds).then((devRes) => {
if (devRes.code === 0) {
let positionRes = localStorage.getItem("PositionIds");
this.positionList = devRes.data.items;
const matchedList = this.positionList.filter((item) =>
positionRes.includes(item.id)
);
this.loadGeoJson(matchedList);
}
});
},
// GeoJSON
loadGeoJson(value) {
//
this.clearLayer();
//
const source = new VectorSource();
// GeoJSON
const geojsonFormat = new GeoJSON();
value.forEach((item) => {
// regionJson OpenLayers
const feature = geojsonFormat.readFeature(JSON.parse(item.regionJson), {
dataProjection: "EPSG:4326", // WGS84
featureProjection: "EPSG:3857" //
});
//
feature.setStyle(
new Style({
fill: new Fill({
color: "rgba(0, 0, 255, 0.3)" //
}),
stroke: new Stroke({
color: "#0000FF", //
width: 2
})
})
);
//
source.addFeature(feature);
//
const centerFeature = new Feature({
geometry: new Point(fromLonLat([item.lon, item.lat]))
});
//
centerFeature.setStyle(
new Style({
image: new Circle({
radius: 6,
fill: new Fill({
color: "#FF0000" //
}),
stroke: new Stroke({
color: "#FFFFFF", //
width: 1
})
})
})
);
//
source.addFeature(centerFeature);
});
//
this.vectorLayer = new VectorLayer({
source: source,
zIndex: 10 //
});
//
window.olMap.addLayer(this.vectorLayer);
// GeoJSON
if (source.getFeatures().length > 0) {
const extent = source.getExtent(); //
window.olMap.getView().fit(extent, {
padding: [50, 50, 50, 50], //
maxZoom: 15, //
duration: 500 //
});
}
},
//
clearLayer() {
if (this.vectorLayer) {
window.olMap.removeLayer(this.vectorLayer);
this.vectorLayer = null;
}
},
refreshClick() { refreshClick() {
// //
window.location.reload(); window.location.reload();
@ -95,16 +239,6 @@ export default {
soundAndMenu() { soundAndMenu() {
this.isZoomedIn = !this.isZoomedIn; this.isZoomedIn = !this.isZoomedIn;
this.$store.commit("SET_ISZOOMEDIN", this.isZoomedIn); this.$store.commit("SET_ISZOOMEDIN", this.isZoomedIn);
// const media = document.getElementById("uavAudio");
// if (media) {
// media.muted = !this.isZoomedIn; // isZoomedIntrue
// if (!this.isZoomedIn) {
// //
// media.play().catch((error) => {
// console.log(":", error);
// });
// }
// }
}, },
initMap() { initMap() {
// OpenLayers // OpenLayers
@ -120,11 +254,36 @@ export default {
}) })
}), }),
new TileLayer({ new TileLayer({
name: "tianditu", name: "tianditu", //
visible: false,
source: new XYZ({ source: new XYZ({
url: "https://{a-d}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png" url: "http://webrd01.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=7",
layer: "img",
style: "default",
matrixSet: "c",
format: "tiles",
tileLoadFunction: function (imageTile, src) {
// 使
const img = new Image();
// img.crossOrigin = ''
//
img.setAttribute("crossOrigin", "anonymous");
img.onload = function () {
const canvas = document.createElement("canvas");
const w = img.width;
const h = img.height;
canvas.width = w;
canvas.height = h;
const context = canvas.getContext("2d");
context.filter =
"grayscale(98%) invert(100%) sepia(20%) hue-rotate(180deg) saturate(1600%) brightness(80%) contrast(90%)";
context.drawImage(img, 0, 0, w, h, 0, 0, w, h);
imageTile.getImage().src = canvas.toDataURL("image/png");
};
img.src = src;
}
}), }),
visible: false format: new GeoJSON()
}) })
], ],
view: new View({ view: new View({
@ -159,6 +318,7 @@ export default {
this.zoomLevel = Math.round(this.map.getView().getZoom()); this.zoomLevel = Math.round(this.map.getView().getZoom());
}, },
onMapLoad(map) { onMapLoad(map) {
this.initPositon();
// //
const camera = window.mapConfig || {}; const camera = window.mapConfig || {};
if (camera.isCamera) { if (camera.isCamera) {
@ -172,17 +332,87 @@ export default {
map.getView().setMaxZoom(18); // map.getView().setMaxZoom(18); //
} }
}, },
mapNorth() { handleClose() {
// 0 this.dialogVisible = false;
const view = this.map.getView(); this.dialogQueryVisible = false;
const currentCenter = view.getCenter(); },
const currentZoom = view.getZoom(); userOpen() {
view.animate({ this.$confirm("是否退出登录?", "提示", {
center: currentCenter, confirmButtonText: "确定",
zoom: currentZoom < 3 ? 10 : currentZoom, // cancelButtonText: "取消",
rotation: 0, // type: "warning"
duration: 500 // })
}); .then(() => {
this.$router.push({ name: "login" });
localStorage.removeItem("setToken");
localStorage.removeItem("expires");
localStorage.removeItem("userId");
localStorage.removeItem("isAdmin");
localStorage.removeItem("PositionIds");
})
.catch(() => {
this.$message({
type: "info",
message: "已取消退出登录"
});
});
},
setupOpen() {
this.dialogVisible = true;
const media = this.$refs.uavAudio;
const savedVolume = localStorage.getItem("soundValue");
if (savedVolume !== null) {
this.value2 = Number(savedVolume);
} else {
this.value2 = media.volume * 100;
}
localStorage.setItem("soundValue", this.value2);
},
determine() {
// localStorage
localStorage.setItem("soundValue", this.value2);
this.$store.commit("SET_SILDERVALUE", this.value2);
this.dialogVisible = false; //
},
queryOpen() {
this.dialogQueryVisible = true;
},
headdenForm(value, type) {
let params = {};
if (type === "search") {
params = JSON.parse(JSON.stringify(this.$refs.myForm.ruleForm));
if (params.dateRange && params.dateRange.length === 2) {
params.strartDate = moment(params.dateRange[0]).format("YYYY-MM-DD");
params.endDate = moment(params.dateRange[1]).format("YYYY-MM-DD");
}
this.$delete(params, "dateRange");
params.pageNum = this.paginationParam.currentPage;
params.pageSize = this.paginationParam.size;
alarmList(params).then((res) => {
if (res.code === 0) {
this.tableData = res.data.items.map((item) => {
const { isWhitelist, duration, frequency, ...rest } = item;
return {
...rest,
isattacked: item.isattacked ? "是" : "否",
duration: String(item.duration),
frequency: String(item.frequency)
};
});
this.paginationParam.total = res.data.total;
}
});
}
},
handleSizeChange(value) {
console.log(value);
this.paginationParam.size = value;
this.headdenForm({}, "search");
},
handlePageChange(value) {
console.log(value);
this.paginationParam.currentPage = value;
this.headdenForm({}, "search");
} }
} }
}; };
@ -205,6 +435,13 @@ export default {
height: 48px; height: 48px;
} }
} }
.btn-container {
position: absolute;
top: 70px;
right: 100px;
z-index: 1000;
color: #fff;
}
.configuration { .configuration {
position: absolute; position: absolute;
bottom: 32px; bottom: 32px;

View File

@ -35,7 +35,7 @@
:underline="false" :underline="false"
@click="handleClick(data, 'playback')" @click="handleClick(data, 'playback')"
> >
轨迹回放 查看
</el-link> </el-link>
</template> </template>
</my-table> </my-table>
@ -57,8 +57,15 @@
<script> <script>
"use script"; "use script";
import { mapGetters } from "vuex";
import { alarmList, alarmDetail } from "@/api/alarm.js"; import { alarmList, alarmDetail } from "@/api/alarm.js";
import moment from "moment"; import moment from "moment";
import { Map, View, Feature, Overlay } from "ol";
import { LineString, Point } from "ol/geom";
import { Vector as VectorLayer } from "ol/layer";
import { Vector as VectorSource } from "ol/source";
import { Style, Stroke } from "ol/style";
import { fromLonLat } from "ol/proj";
export default { export default {
name: "webDevice", name: "webDevice",
data() { data() {
@ -150,7 +157,7 @@ export default {
align: "center" align: "center"
}, },
{ {
label: "持续时间(秒)", label: "持续时间",
prop: "duration", prop: "duration",
align: "center" align: "center"
}, },
@ -186,9 +193,7 @@ export default {
// }, // },
{ {
slot: "operate", slot: "operate",
label: "操作", label: "操作"
width: 250,
fixed: "right"
} }
], ],
paginationParam: { paginationParam: {
@ -204,6 +209,18 @@ export default {
historyList: [] historyList: []
}; };
}, },
computed: {
...mapGetters(["clearTrajectory"])
},
watch: {
clearTrajectory(newVal) {
if (newVal) {
this.clearTrack();
this.$store.commit("SET_CLEARTRAJECTORY", false);
}
},
deep: true
},
mounted() { mounted() {
this.headdenForm({}, "search"); this.headdenForm({}, "search");
}, },
@ -245,11 +262,97 @@ export default {
}; };
}); });
this.paginationParam.total = res.data.total; this.paginationParam.total = res.data.total;
// this.tableData = [
// {
// batchId: "1936635182949994496",
// startTime: "2025-06-22 11:59:43",
// endTime: "2025-06-22 12:02:10",
// duration: 147,
// model: "8",
// sn: "1581F6CDC23B6003DTL2",
// frequency: 0,
// isWhitelist: false,
// whitelist: null,
// positionId: "1924768527160578048",
// positionName: "louding"
// }
// ];
} }
}); });
} }
console.log(value); console.log(value);
}, },
// 线
drawTrack() {
//
this.clearTrack();
// OpenLayers (EPSG:3857)
const coordinates = this.historyList.map((item) =>
fromLonLat([item.lon, item.lat])
);
console.log(coordinates, "coordinates");
// 线
const lineFeature = new Feature({
geometry: new LineString(coordinates)
});
// 线10
lineFeature.setStyle(
new Style({
stroke: new Stroke({
color: "#ff0000",
width: 7
})
})
);
//
const source = new VectorSource({
features: [lineFeature]
});
this.trackLayer = new VectorLayer({
source: source,
zIndex: 10 //
});
//
window.olMap.addLayer(this.trackLayer);
window.olMap.getView().animate({
center: [coordinates[0][0], coordinates[0][1]],
zoom: 15
});
//
// this.addClickToRemove();
},
//
addClickToRemove() {
window.olMap.on("singleclick", (event) => {
const feature = window.olMap.forEachFeatureAtPixel(
event.pixel,
(feat) => feat
);
if (
feature &&
this.trackLayer.getSource().getFeatures().includes(feature)
) {
// 线
if (confirm("是否关闭该轨迹?")) {
this.clearTrack();
}
}
});
},
handleClickClose() {
this.clearTrack();
},
//
clearTrack() {
if (this.trackLayer) {
window.olMap.removeLayer(this.trackLayer);
this.trackLayer = null;
}
},
// //
handleClick(value, type) { handleClick(value, type) {
let params = { batchid: value.batchId }; let params = { batchid: value.batchId };
@ -258,55 +361,75 @@ export default {
alarmDetail(params).then((res) => { alarmDetail(params).then((res) => {
if (res.code === 0) { if (res.code === 0) {
console.log(res.data, "res.data"); console.log(res.data, "res.data");
this.historyList = res.data; this.historyList = [
// this.historyList = [ {
// { lon: 118.71041006571824,
// lon: 109.056198, lat: 32.031231916027345,
// lat: 38.674443, alt: 41.3,
// alt: 0, app_lat: 32.03116889069689,
// createTime: "2025-03-30 03:44:21", app_lon: 118.71035276996328,
// alarmLevel: 0 createTime: "2025-06-14 15:31:28",
// }, alarmLevel: 0
// { },
// lon: 109.081454, {
// lat: 38.664766, lon: 118.7104387135957,
// alt: 0, lat: 32.03126056390482,
// createTime: "2025-03-30 03:44:22", alt: 41.3,
// alarmLevel: 0 app_lat: 32.03116889069689,
// }, app_lon: 118.71035276996328,
// { createTime: "2025-06-14 15:31:30",
// lon: 109.101687, alarmLevel: 0
// lat: 38.632524, },
// alt: 0, {
// createTime: "2025-03-30 03:44:25", lon: 118.71056476425662,
// alarmLevel: 0 lat: 32.03135796668825,
// }, alt: 45.7,
// { app_lat: 32.03116889069689,
// lon: 109.063063, app_lon: 118.71034704038777,
// lat: 38.622878, createTime: "2025-06-14 15:32:04",
// alt: 0, alarmLevel: 0
// createTime: "2025-03-30 03:44:30", },
// alarmLevel: 0 {
// }, lon: 118.71056476425662,
// { lat: 32.03135796668825,
// lon: 109.016034, alt: 45.7,
// lat: 38.635138, app_lat: 32.03116316112139,
// alt: 0, app_lon: 118.71034704038777,
// createTime: "2025-03-30 03:44:35", createTime: "2025-06-14 15:32:06",
// alarmLevel: 0 alarmLevel: 0
// }, },
// { {
// lon: 108.991419, lon: 118.71034704038777,
// lat: 38.659515, lat: 32.031077217488956,
// alt: 0, alt: 24.4,
// createTime: "2025-03-30 03:44:38", app_lat: 32.03117462027238,
// alarmLevel: 0 app_lon: 118.71036422911426,
// } createTime: "2025-06-14 15:32:49",
// ]; alarmLevel: 0
},
{
lon: 118.71038141784075,
lat: 32.03106575833797,
alt: 22.3,
app_lat: 32.03116889069689,
app_lon: 118.71035276996328,
createTime: "2025-06-14 15:32:55",
alarmLevel: 0
},
{
lon: 118.71036995868977,
lat: 32.03092824852607,
alt: 34.6,
app_lat: 32.03118034984788,
app_lon: 118.71035849953877,
createTime: "2025-06-14 15:33:54",
alarmLevel: 0
}
];
this.drawTrack();
this.$store.commit("SET_CHECKFLAG", true);
} }
}); });
this.title = "轨迹回放";
this.drawer = true;
} }
}, },
handleSizeChange(value) { handleSizeChange(value) {

View File

@ -18,7 +18,7 @@ module.exports = defineConfig({
productionSourceMap: false, productionSourceMap: false,
transpileDependencies: true, transpileDependencies: true,
devServer: { devServer: {
host: "127.0.0.1", host: "192.168.1.9",
port: 9997, port: 9997,
open: true, open: true,
proxy: {} proxy: {}