更改底图颜色
This commit is contained in:
parent
d8f87fdf88
commit
0e36765929
|
|
@ -14,6 +14,7 @@
|
|||
"@vue-office/excel": "^1.7.11",
|
||||
"@vue-office/pdf": "^2.0.10",
|
||||
"axios": "^1.1.3",
|
||||
"be-full": "^0.1.4",
|
||||
"core-js": "^3.8.3",
|
||||
"echarts": "^5.5.1",
|
||||
"echarts-gl": "^2.0.9",
|
||||
|
|
@ -5289,6 +5290,11 @@
|
|||
"integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==",
|
||||
"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": {
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmmirror.com/big.js/-/big.js-5.2.2.tgz",
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
"@vue-office/excel": "^1.7.11",
|
||||
"@vue-office/pdf": "^2.0.10",
|
||||
"axios": "^1.1.3",
|
||||
"be-full": "^0.1.4",
|
||||
"core-js": "^3.8.3",
|
||||
"echarts": "^5.5.1",
|
||||
"echarts-gl": "^2.0.9",
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@
|
|||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
flex-wrap: nowrap;
|
||||
.el-form-item {
|
||||
margin-right: 3%;
|
||||
margin-bottom: 13px;
|
||||
|
|
@ -596,3 +596,60 @@
|
|||
.el-picker-panel__icon-btn {
|
||||
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 {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,8 @@ import {
|
|||
Upload,
|
||||
Dropdown,
|
||||
DropdownMenu,
|
||||
DropdownItem
|
||||
DropdownItem,
|
||||
Slider
|
||||
} from "element-ui";
|
||||
import "element-ui/lib/theme-chalk/index.css";
|
||||
|
||||
|
|
@ -67,6 +68,7 @@ Vue.use(Switch);
|
|||
Vue.use(Timeline);
|
||||
Vue.use(TimelineItem);
|
||||
Vue.use(Upload);
|
||||
Vue.use(Slider);
|
||||
|
||||
Vue.prototype.$message = Message;
|
||||
Vue.prototype.$confirm = MessageBox.confirm;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@ const getters = {
|
|||
targetCode: (state) => state.chart.targetCode, //防护目标单一点击更改两侧数据
|
||||
airspaceCode: (state) => state.chart.airspaceCode, //低空空域单一点击更改两侧数据
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,10 @@ const user = {
|
|||
airspaceCode: {},
|
||||
|
||||
positionPoint: false, // 位置上报
|
||||
isZoomedIn: true // 音频是否打开
|
||||
isZoomedIn: true, // 音频是否打开
|
||||
SliderValue: 0, // 音频滑动条值
|
||||
checkFlag: false, // 轨迹查看按钮
|
||||
clearTrajectory: false // 清除过往轨迹
|
||||
},
|
||||
|
||||
mutations: {
|
||||
|
|
@ -38,6 +41,15 @@ const user = {
|
|||
},
|
||||
SET_ISZOOMEDIN: (state, 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;
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -190,7 +190,7 @@
|
|||
loop
|
||||
ref="uavAudio"
|
||||
v-show="iswarning"
|
||||
style="display: none"
|
||||
style="display: none; pointer-events: auto"
|
||||
id="uavAudio"
|
||||
>
|
||||
<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 { fromLonLat, toLonLat } from "ol/proj";
|
||||
import { whitListAdd } from "@/api/whitList.js";
|
||||
import AMapLoader from "@amap/amap-jsapi-loader";
|
||||
import QRCode from "qrcode";
|
||||
|
||||
export default {
|
||||
|
|
@ -257,7 +256,7 @@ export default {
|
|||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(["isZoomedIn"])
|
||||
...mapGetters(["isZoomedIn", "SliderValue"])
|
||||
},
|
||||
mounted() {
|
||||
this.endTime = moment.utc().format("YYYY-MM-DD HH:mm:ss");
|
||||
|
|
@ -276,6 +275,18 @@ export default {
|
|||
},
|
||||
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: {
|
||||
handler(newVal) {
|
||||
if (newVal) {
|
||||
|
|
@ -359,8 +370,9 @@ export default {
|
|||
if (this.drones) {
|
||||
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 savedVolume = localStorage.getItem("soundValue");
|
||||
if (alarm) {
|
||||
this.iswarning = true;
|
||||
this.$nextTick(() => {
|
||||
|
|
@ -370,6 +382,11 @@ export default {
|
|||
.play()
|
||||
.then(() => {
|
||||
console.log("播放成功,取消静音");
|
||||
if (savedVolume !== null) {
|
||||
media.volume = savedVolume / 100;
|
||||
} else {
|
||||
media.volume = 1;
|
||||
}
|
||||
if (this.isZoomedIn) {
|
||||
media.muted = false; // 播放成功后取消静音
|
||||
} else {
|
||||
|
|
@ -468,6 +485,7 @@ export default {
|
|||
enableAudio() {
|
||||
this.iswarning = true;
|
||||
const media = this.$refs.uavAudio;
|
||||
const savedVolume = localStorage.getItem("soundValue");
|
||||
let time = setInterval(() => {
|
||||
console.log("用户手动启用音频", media);
|
||||
if (media !== undefined) {
|
||||
|
|
@ -477,6 +495,11 @@ export default {
|
|||
} else {
|
||||
media.muted = true; // 初始静音
|
||||
}
|
||||
if (savedVolume !== null) {
|
||||
media.volume = savedVolume / 100;
|
||||
} else {
|
||||
media.volume = 1;
|
||||
}
|
||||
media
|
||||
.play()
|
||||
.then(() => {
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
import { mapGetters } from "vuex";
|
||||
import { HomeSyncLocation } from "@/api/home";
|
||||
import _ from "lodash";
|
||||
import { fromLonLat } from "ol/proj";
|
||||
|
||||
export default {
|
||||
name: "header-top",
|
||||
|
|
@ -41,12 +42,13 @@ export default {
|
|||
isAdmins: false,
|
||||
leftText: "平台已连接",
|
||||
rightText: "定位正常",
|
||||
latitude: null,
|
||||
longitude: null,
|
||||
latitude: "",
|
||||
longitude: "",
|
||||
lastUpdated: "",
|
||||
watchId: null,
|
||||
timer: null,
|
||||
showPermissionPrompt: false
|
||||
showPermissionPrompt: false,
|
||||
retryCount: 0
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -60,14 +62,15 @@ export default {
|
|||
this.timer = setInterval(() => {
|
||||
this.updateTime();
|
||||
}, 1000);
|
||||
this.$on("retry-tracking", this.startTracking);
|
||||
},
|
||||
watch: {
|
||||
positionPoint: {
|
||||
handler(newVal, oldVal) {
|
||||
if (newVal) {
|
||||
console.log("定位更新:", this.latitude, this.longitude);
|
||||
const newLocation = [this.longitude, this.latitude]; // 新的位置坐标
|
||||
const zoomLevel = 13; // 目标缩放级别
|
||||
handler(newVal) {
|
||||
if (newVal && this.latitude && this.longitude) {
|
||||
const newLocation = fromLonLat([this.longitude, this.latitude]);
|
||||
this.$message.success(this.longitude + "," + this.latitude);
|
||||
const zoomLevel = 13;
|
||||
window.olMap.getView().animate({
|
||||
center: newLocation,
|
||||
zoom: zoomLevel
|
||||
|
|
@ -75,9 +78,9 @@ export default {
|
|||
this.startTracking();
|
||||
}
|
||||
this.$store.commit("SET_POSITIONPOINT", false);
|
||||
}
|
||||
},
|
||||
deep: true
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
updateTime() {
|
||||
|
|
@ -97,9 +100,9 @@ export default {
|
|||
(position) => this.handleSuccess(position),
|
||||
(error) => this.handleError(error),
|
||||
{
|
||||
enableHighAccuracy: false,
|
||||
timeout: 15000,
|
||||
maximumAge: 0
|
||||
enableHighAccuracy: true,
|
||||
timeout: 30000,
|
||||
maximumAge: 10000
|
||||
}
|
||||
);
|
||||
},
|
||||
|
|
@ -119,13 +122,17 @@ export default {
|
|||
if (res.code === 0) {
|
||||
this.leftText = "平台已连接";
|
||||
this.rightText = "定位正常";
|
||||
if (!latitude && res.data.fallbackLocation) {
|
||||
this.handleSuccess({
|
||||
coords: { latitude: this.latitude, longitude: this.longitude }
|
||||
});
|
||||
}
|
||||
} else {
|
||||
this.leftText = "平台连接失败";
|
||||
this.rightText = "定位异常";
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error("上报失败:", err);
|
||||
this.leftText = "平台连接失败";
|
||||
this.rightText = "定位异常";
|
||||
});
|
||||
|
|
@ -135,10 +142,12 @@ export default {
|
|||
this.longitude = position.coords.longitude;
|
||||
this.lastUpdated = new Date().toLocaleString();
|
||||
this.showPermissionPrompt = false;
|
||||
this.retryCount = 0;
|
||||
this.syncLocation(this.latitude, this.longitude);
|
||||
},
|
||||
handleError(error) {
|
||||
let message = "";
|
||||
this.retryCount = this.retryCount || 0;
|
||||
switch (error.code) {
|
||||
case error.PERMISSION_DENIED:
|
||||
message = "请允许地理位置权限";
|
||||
|
|
@ -147,21 +156,31 @@ export default {
|
|||
break;
|
||||
case error.POSITION_UNAVAILABLE:
|
||||
message = "无法获取位置信息";
|
||||
setTimeout(() => this.startTracking(), 5000);
|
||||
if (this.retryCount < 3) {
|
||||
this.retryCount++;
|
||||
setTimeout(() => this.startTracking(), 5000);
|
||||
} else {
|
||||
this.$message.error("多次尝试后仍无法定位,请检查设备设置");
|
||||
}
|
||||
break;
|
||||
case error.TIMEOUT:
|
||||
message = "获取位置超时";
|
||||
setTimeout(() => this.startTracking(), 5000);
|
||||
if (this.retryCount < 3) {
|
||||
this.retryCount++;
|
||||
setTimeout(() => this.startTracking(), 5000);
|
||||
} else {
|
||||
this.$message.error("定位超时,请检查网络或 GPS 信号");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
message = "未知错误";
|
||||
}
|
||||
this.leftText = message;
|
||||
this.rightText = "定位异常";
|
||||
console.error("定位错误:", error);
|
||||
},
|
||||
retryTracking() {
|
||||
this.showPermissionPrompt = false;
|
||||
this.retryCount = 0;
|
||||
this.startTracking();
|
||||
}
|
||||
},
|
||||
|
|
@ -181,11 +200,9 @@ export default {
|
|||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.time {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.actions span {
|
||||
margin-left: 10px;
|
||||
cursor: pointer;
|
||||
|
|
@ -198,7 +215,8 @@ export default {
|
|||
padding: 15px;
|
||||
border: 1px solid #ddd;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
z-index: 1000;
|
||||
z-index: 10000;
|
||||
pointer-events: auto;
|
||||
}
|
||||
.permission-prompt p {
|
||||
margin: 0 0 10px;
|
||||
|
|
|
|||
|
|
@ -1,18 +1,10 @@
|
|||
<template>
|
||||
<fit-screen :width="1280" :height="800" mode="fit">
|
||||
<div id="home">
|
||||
<contentData
|
||||
id="contentData"
|
||||
:signaData="signaData"
|
||||
:homeData="homeData"
|
||||
/>
|
||||
<map-control
|
||||
id="mapControl"
|
||||
:signaData="signaData"
|
||||
:homeData="homeData"
|
||||
/>
|
||||
</div>
|
||||
</fit-screen>
|
||||
<!-- <fit-screen :width="1280" :height="800" mode="fit"> -->
|
||||
<div id="home">
|
||||
<contentData id="contentData" :signaData="signaData" :homeData="homeData" />
|
||||
<map-control id="mapControl" :signaData="signaData" :homeData="homeData" />
|
||||
</div>
|
||||
<!-- </fit-screen> -->
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
|
@ -21,6 +13,7 @@ import mapControl from "./mapControl/index.vue";
|
|||
import contentData from "./contentData/index.vue";
|
||||
import { Homeview } from "@/api/home.js";
|
||||
import * as signalR from "@microsoft/signalr";
|
||||
import { beFull } from "be-full";
|
||||
export default {
|
||||
name: "HomeIndex",
|
||||
data() {
|
||||
|
|
@ -44,6 +37,21 @@ export default {
|
|||
this.timeInterval = setInterval(() => {
|
||||
this.initHomeData();
|
||||
}, 2000);
|
||||
// 全屏
|
||||
this.$confirm("是否全屏?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
})
|
||||
.then(() => {
|
||||
beFull();
|
||||
})
|
||||
.catch(() => {
|
||||
this.$message({
|
||||
type: "info",
|
||||
message: "已取消"
|
||||
});
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
initHomeData() {
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@
|
|||
|
||||
<script>
|
||||
import { login, loginPosition } from "@/api/login.js";
|
||||
|
||||
export default {
|
||||
name: "my-Login", // 组件名称
|
||||
data() {
|
||||
|
|
@ -48,7 +47,8 @@ export default {
|
|||
},
|
||||
errors: {},
|
||||
value: "",
|
||||
tipShow: false
|
||||
tipShow: false,
|
||||
positionList: []
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
|
|
@ -91,6 +91,7 @@ export default {
|
|||
loginPosition(arrParams).then((positionRes) => {
|
||||
if (positionRes.code === 0) {
|
||||
localStorage.setItem("PositionIds", positionRes.data); // 阵地权限
|
||||
this.$message.success("登录成功");
|
||||
} else {
|
||||
this.$message.error(positionRes.msg);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,11 +3,14 @@
|
|||
<div class="zoom-level" @click="soundAndMenu">
|
||||
<img :src="zoomLevelImage" alt="" />
|
||||
</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 class="pointingNorth" @click="mapNorth">
|
||||
<img src="@/assets/img/user.png" alt="" />
|
||||
<img src="@/assets/img/setup.png" alt="" />
|
||||
<img src="@/assets/img/query.png" alt="" />
|
||||
<div class="pointingNorth">
|
||||
<img src="@/assets/img/user.png" alt="" @click="userOpen" />
|
||||
<img src="@/assets/img/setup.png" alt="" @click="setupOpen" />
|
||||
<img src="@/assets/img/query.png" alt="" @click="queryOpen" />
|
||||
</div>
|
||||
<div class="configuration">
|
||||
<div class="refresh" @click="refreshClick">
|
||||
|
|
@ -20,6 +23,33 @@
|
|||
<img src="@/assets/img/icon_model.png" alt="" />
|
||||
</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>
|
||||
</template>
|
||||
|
||||
|
|
@ -30,31 +60,32 @@ import View from "ol/View";
|
|||
import TileLayer from "ol/layer/Tile";
|
||||
import { fromLonLat } from "ol/proj";
|
||||
import XYZ from "ol/source/XYZ";
|
||||
|
||||
import VectorLayer from "ol/layer/Vector";
|
||||
import VectorSource from "ol/source/Vector";
|
||||
import Feature from "ol/Feature";
|
||||
import Point from "ol/geom/Point";
|
||||
import LineString from "ol/geom/LineString";
|
||||
import Style from "ol/style/Style";
|
||||
import Icon from "ol/style/Icon";
|
||||
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";
|
||||
import { Feature, Overlay } from "ol";
|
||||
import { Point, MultiPolygon } from "ol/geom";
|
||||
import { Vector as VectorLayer } from "ol/layer";
|
||||
import { Vector as VectorSource } from "ol/source";
|
||||
import { Style, Fill, Stroke, Circle } from "ol/style";
|
||||
import GeoJSON from "ol/format/GeoJSON";
|
||||
import AlertDialog from "../menuData/AlertDialog.vue";
|
||||
import { devPositionList } from "@/api/position.js";
|
||||
|
||||
export default {
|
||||
name: "HomeMap",
|
||||
components: {
|
||||
AlertDialog
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
map: null,
|
||||
zoomLevel: null,
|
||||
isZoomedIn: true,
|
||||
isZoomedOut: false,
|
||||
showPermissionPrompt: false
|
||||
showPermissionPrompt: false,
|
||||
dialogVisible: false,
|
||||
value2: 0,
|
||||
currentBaseMap: "gaode",
|
||||
dialogQueryVisible: false,
|
||||
closeBtnVisible: false
|
||||
};
|
||||
},
|
||||
created() {
|
||||
|
|
@ -65,14 +96,127 @@ export default {
|
|||
this.initMap();
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(["statePage", "cityCode"]),
|
||||
...mapGetters(["statePage", "cityCode", "checkFlag"]),
|
||||
zoomLevelImage() {
|
||||
return this.isZoomedIn
|
||||
? require("@/assets/img/sound.png")
|
||||
: require("@/assets/img/mute.png");
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
checkFlag: {
|
||||
handler(newVal) {
|
||||
this.closeBtnVisible = newVal;
|
||||
this.dialogQueryVisible = false;
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
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() {
|
||||
// 刷新页面
|
||||
window.location.reload();
|
||||
|
|
@ -95,16 +239,6 @@ export default {
|
|||
soundAndMenu() {
|
||||
this.isZoomedIn = !this.isZoomedIn;
|
||||
this.$store.commit("SET_ISZOOMEDIN", this.isZoomedIn);
|
||||
// const media = document.getElementById("uavAudio");
|
||||
// if (media) {
|
||||
// media.muted = !this.isZoomedIn; // isZoomedIn为true时静音
|
||||
// if (!this.isZoomedIn) {
|
||||
// // 取消静音时尝试播放
|
||||
// media.play().catch((error) => {
|
||||
// console.log("播放失败,可能需要用户交互:", error);
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
},
|
||||
initMap() {
|
||||
// 初始化 OpenLayers 地图
|
||||
|
|
@ -120,11 +254,36 @@ export default {
|
|||
})
|
||||
}),
|
||||
new TileLayer({
|
||||
name: "tianditu",
|
||||
name: "tianditu", // 图层名称
|
||||
visible: false,
|
||||
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({
|
||||
|
|
@ -159,6 +318,7 @@ export default {
|
|||
this.zoomLevel = Math.round(this.map.getView().getZoom());
|
||||
},
|
||||
onMapLoad(map) {
|
||||
this.initPositon();
|
||||
// 地图加载完成后的处理
|
||||
const camera = window.mapConfig || {};
|
||||
if (camera.isCamera) {
|
||||
|
|
@ -172,17 +332,87 @@ export default {
|
|||
map.getView().setMaxZoom(18); // 最大缩放等级
|
||||
}
|
||||
},
|
||||
mapNorth() {
|
||||
// 指北:将地图旋转角度重置为 0
|
||||
const view = this.map.getView();
|
||||
const currentCenter = view.getCenter();
|
||||
const currentZoom = view.getZoom();
|
||||
view.animate({
|
||||
center: currentCenter,
|
||||
zoom: currentZoom < 3 ? 10 : currentZoom, // 确保最小缩放等级
|
||||
rotation: 0, // 指北
|
||||
duration: 500 // 动画持续时间
|
||||
});
|
||||
handleClose() {
|
||||
this.dialogVisible = false;
|
||||
this.dialogQueryVisible = false;
|
||||
},
|
||||
userOpen() {
|
||||
this.$confirm("是否退出登录?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
})
|
||||
.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;
|
||||
}
|
||||
}
|
||||
.btn-container {
|
||||
position: absolute;
|
||||
top: 70px;
|
||||
right: 100px;
|
||||
z-index: 1000;
|
||||
color: #fff;
|
||||
}
|
||||
.configuration {
|
||||
position: absolute;
|
||||
bottom: 32px;
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
:underline="false"
|
||||
@click="handleClick(data, 'playback')"
|
||||
>
|
||||
轨迹回放
|
||||
查看
|
||||
</el-link>
|
||||
</template>
|
||||
</my-table>
|
||||
|
|
@ -57,8 +57,15 @@
|
|||
|
||||
<script>
|
||||
"use script";
|
||||
import { mapGetters } from "vuex";
|
||||
import { alarmList, alarmDetail } from "@/api/alarm.js";
|
||||
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 {
|
||||
name: "webDevice",
|
||||
data() {
|
||||
|
|
@ -150,7 +157,7 @@ export default {
|
|||
align: "center"
|
||||
},
|
||||
{
|
||||
label: "持续时间(秒)",
|
||||
label: "持续时间",
|
||||
prop: "duration",
|
||||
align: "center"
|
||||
},
|
||||
|
|
@ -186,9 +193,7 @@ export default {
|
|||
// },
|
||||
{
|
||||
slot: "operate",
|
||||
label: "操作",
|
||||
width: 250,
|
||||
fixed: "right"
|
||||
label: "操作"
|
||||
}
|
||||
],
|
||||
paginationParam: {
|
||||
|
|
@ -204,6 +209,18 @@ export default {
|
|||
historyList: []
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(["clearTrajectory"])
|
||||
},
|
||||
watch: {
|
||||
clearTrajectory(newVal) {
|
||||
if (newVal) {
|
||||
this.clearTrack();
|
||||
this.$store.commit("SET_CLEARTRAJECTORY", false);
|
||||
}
|
||||
},
|
||||
deep: true
|
||||
},
|
||||
mounted() {
|
||||
this.headdenForm({}, "search");
|
||||
},
|
||||
|
|
@ -245,11 +262,97 @@ export default {
|
|||
};
|
||||
});
|
||||
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);
|
||||
},
|
||||
// 绘制轨迹线
|
||||
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) {
|
||||
let params = { batchid: value.batchId };
|
||||
|
|
@ -258,55 +361,75 @@ export default {
|
|||
alarmDetail(params).then((res) => {
|
||||
if (res.code === 0) {
|
||||
console.log(res.data, "res.data");
|
||||
this.historyList = res.data;
|
||||
// this.historyList = [
|
||||
// {
|
||||
// lon: 109.056198,
|
||||
// lat: 38.674443,
|
||||
// alt: 0,
|
||||
// createTime: "2025-03-30 03:44:21",
|
||||
// alarmLevel: 0
|
||||
// },
|
||||
// {
|
||||
// lon: 109.081454,
|
||||
// lat: 38.664766,
|
||||
// alt: 0,
|
||||
// createTime: "2025-03-30 03:44:22",
|
||||
// alarmLevel: 0
|
||||
// },
|
||||
// {
|
||||
// lon: 109.101687,
|
||||
// lat: 38.632524,
|
||||
// alt: 0,
|
||||
// createTime: "2025-03-30 03:44:25",
|
||||
// alarmLevel: 0
|
||||
// },
|
||||
// {
|
||||
// lon: 109.063063,
|
||||
// lat: 38.622878,
|
||||
// alt: 0,
|
||||
// createTime: "2025-03-30 03:44:30",
|
||||
// alarmLevel: 0
|
||||
// },
|
||||
// {
|
||||
// lon: 109.016034,
|
||||
// lat: 38.635138,
|
||||
// alt: 0,
|
||||
// createTime: "2025-03-30 03:44:35",
|
||||
// alarmLevel: 0
|
||||
// },
|
||||
// {
|
||||
// lon: 108.991419,
|
||||
// lat: 38.659515,
|
||||
// alt: 0,
|
||||
// createTime: "2025-03-30 03:44:38",
|
||||
// alarmLevel: 0
|
||||
// }
|
||||
// ];
|
||||
this.historyList = [
|
||||
{
|
||||
lon: 118.71041006571824,
|
||||
lat: 32.031231916027345,
|
||||
alt: 41.3,
|
||||
app_lat: 32.03116889069689,
|
||||
app_lon: 118.71035276996328,
|
||||
createTime: "2025-06-14 15:31:28",
|
||||
alarmLevel: 0
|
||||
},
|
||||
{
|
||||
lon: 118.7104387135957,
|
||||
lat: 32.03126056390482,
|
||||
alt: 41.3,
|
||||
app_lat: 32.03116889069689,
|
||||
app_lon: 118.71035276996328,
|
||||
createTime: "2025-06-14 15:31:30",
|
||||
alarmLevel: 0
|
||||
},
|
||||
{
|
||||
lon: 118.71056476425662,
|
||||
lat: 32.03135796668825,
|
||||
alt: 45.7,
|
||||
app_lat: 32.03116889069689,
|
||||
app_lon: 118.71034704038777,
|
||||
createTime: "2025-06-14 15:32:04",
|
||||
alarmLevel: 0
|
||||
},
|
||||
{
|
||||
lon: 118.71056476425662,
|
||||
lat: 32.03135796668825,
|
||||
alt: 45.7,
|
||||
app_lat: 32.03116316112139,
|
||||
app_lon: 118.71034704038777,
|
||||
createTime: "2025-06-14 15:32:06",
|
||||
alarmLevel: 0
|
||||
},
|
||||
{
|
||||
lon: 118.71034704038777,
|
||||
lat: 32.031077217488956,
|
||||
alt: 24.4,
|
||||
app_lat: 32.03117462027238,
|
||||
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) {
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ module.exports = defineConfig({
|
|||
productionSourceMap: false,
|
||||
transpileDependencies: true,
|
||||
devServer: {
|
||||
host: "127.0.0.1",
|
||||
host: "192.168.1.9",
|
||||
port: 9997,
|
||||
open: true,
|
||||
proxy: {}
|
||||
|
|
|
|||
Loading…
Reference in New Issue