Files
im-system/hd-glasses-app/src/pages/hd_map_patrol_line.vue
2023-11-24 17:39:04 +08:00

770 lines
21 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div id="content">
<div id="map" ref="map" style="width: 100vw; height: 100vh"/>
<div id="overlay-box"/>
<div class="addAlarmPoint" v-if="page=='addAlarmPoint'">
<div class="addAlarmPointNext" @click="addAlarmPointNextAction">下一步</div>
</div>
<div class="mobileHomePageExpandBtn" v-if="page=='mobileHomePage'">
<van-icon name="expand-o" color="white" @click="switchFullScreen"/>
</div>
<div class="iconColorList" v-if="page=='mobileHomePage'&&pageType=='large'">
<div class="iconColorListItem"><span style="background-color: #FF0000"></span>报警点位</div>
<div class="iconColorListItem"><span style="background-color: #369FFF"></span>在线</div>
<div class="iconColorListItem"><span style="background-color: #9B9B9B"></span>离线</div>
<div class="iconColorListItem"><span style="background-color: #16CE81"></span>接收报警</div>
</div>
<van-overlay :show="alarmDetailsOverlay" @click="alarmDetailsOverlay = false" z-index="20">
<div class="alarmDetailsOverlayWrapper" @click.stop>
<div class="alarmDetailsBox">
<div class="title">{{ alarmDetailsData.title }}</div>
<div class="alarmDetailsBoxItem"><span>报警类型:</span><span>{{
alarmDetailsData.alarmCategory_dictText
}}</span>
</div>
<div class="alarmDetailsBoxItem"><span>报警时间:</span><span>{{ alarmDetailsData.createTime }}</span></div>
<div class="alarmDetailsBoxItem"><span>警情内容:</span><span>{{ alarmDetailsData.msgContent }}</span></div>
<div class="alarmDetailsBoxItem"><span>发布人:</span><span>{{ alarmDetailsData.sender }}</span></div>
<div class="alarmDetailsBoxItem"><span>关联设备:</span><span>内容</span></div>
</div>
<div class="btnList">
<div class="btnItem" @click="alarmClickAction(1)">确认</div>
<div class="btnItem" @click="alarmClickAction(2)">导航</div>
</div>
</div>
</van-overlay>
<!--
<div class="pcPlanningPath" v-if="page=='pcPlanningPath'">
<div class="pcPlanningPathNext" @click="clearPcPlanningPath">清空重新绘制</div>
</div>
-->
</div>
</template>
<script>
import "ol/ol.css";
import TileLayer from "ol/layer/Tile";
import VectorLayer from "ol/layer/Vector";
import VectorSource from "ol/source/Vector";
import XYZ from "ol/source/XYZ";
import {Map, View, Feature} from "ol";
import {Icon, Fill, Stroke, Style, Circle, Text} from "ol/style";
import Overlay from "ol/Overlay";
import {Point, LineString, Polygon} from "ol/geom.js";
import {getVectorContext} from "ol/render";
import axios from "axios";
import TileWMS from "ol/source/TileWMS"
import WMTS from "ol/source/WMTS"
import TileGrid from "ol/tilegrid/TileGrid"
import {Notify, Dialog} from 'vant';
import * as interaction from 'ol/interaction'; // 交互
import {OL as ol} from "plot-ol/plottingol";
import GeoJSON from 'ol/format/GeoJSON'
import service from "@/utils/service";
import {appInit, getStatisFileUrl, getUrlParam} from "../utils/publicFun";
import WMTSTileGrid from 'ol/tilegrid/WMTS.js';
import {get as getProjection} from 'ol/proj.js';
import {getTopLeft, getWidth} from 'ol/extent.js';
export default {
data() {
return {
map: {},
pointLayer: {},
canAddPoints: false,
coordinate: [],
route: new LineString([[12496610.1929, 2476571.7426], [12496623.829, 2476586.2505]]),
route1: new LineString([[113.95113841271974, 22.568523240293505], [113.94452944970705, 22.563351941312792], [113.95188943124391, 22.559317898954394], [113.94467965341188, 22.555326771940233]]),
geometryMove: {},
featureMove: {},
styles: {
route: new Style({
stroke: new Stroke({
width: 6,
color: [237, 212, 0, 0.8],
}),
}),
icon: new Style({
image: new Icon({
anchor: [0.5, 1],
src: "https://openlayers.org/en/v4.6.5/examples/data/icon.png",
scale: 1, //设置大小
}),
}),
featureMove: new Style({
image: new Circle({
radius: 7,
fill: new Fill({color: "black"}),
stroke: new Stroke({
color: "white",
width: 2,
}),
}),
}),
},
vectorLayer: {},
distance: 0,
lastTime: 0,
speed: 0.1,
page: null,
selectPoint: [],
drawPlanningPathLayer: null,
draw: null,
snap: null,
pcDrawType: "",
equipmentLayer: {},
alarmLayer: {},
alarmAnimation: null,
planningTargetPoint: [],
alarmDetailsOverlay: false,
alarmDetailsData: {
alarmCategory_dictText: ""
},
navigationStartPoint: [],
navigationEndPoint: [],
hd_gps_location: [],
pageType: "",
planningVectorLayer: {},
parentPostMessageData: [],
isCanDraw: true,
from: ""
};
},
mounted() {
console.log(location.href)
this.page = getUrlParam("page");
this.pageType = getUrlParam("type");
this.from = getUrlParam("from");
this.token = getUrlParam("token")
if (this.token != null) {
localStorage.setItem("hd_token", this.token)
}
setInterval(() => {
let hd_gps_location = localStorage.getItem("hd_gps_location")
if (hd_gps_location) {
hd_gps_location = hd_gps_location.split(",")
this.hd_gps_location = hd_gps_location
this.navigationStartPoint = this.hd_gps_location
}
}, 2000)
this.initMap();
switch (this.page) {
case "addAlarmPoint":
console.log("新增报警点");
//处理ok
this.PageAddAlarmPoint()
break
case "pcPlanningPath":
this.pcDrawType = "LineString";
window.addEventListener('message', (event) => {
this.isCanDraw = false
console.log(event.data)
if (this.parentPostMessageData.length == 0) {
if (event.data instanceof Array) {
this.drawPatrolRoute(event.data)
} else {
// this.isCanDraw = true;
}
}
});
if(this.pageType=="edit"){
this.PageAddAlarmPoint()
}
break
case "pcDrawArea":
this.pcDrawType = "Polygon"
window.addEventListener('message', (event) => {
this.isCanDraw = false
if (this.parentPostMessageData.length == 0) {
if (event.data instanceof Array) {
this.map.removeLayer(this.drawPlanningPathLayer);
this.parentPostMessageData = event.data;
this.drawPcPostMessageDataLayer()
} else {
this.isCanDraw = true;
}
}
});
//处理ok
this.pcPlanningPath();
break
case "planningPath":
// http://localhost:8080/hd-glasses-app/#/hd_map?page=planningPath&alarmId=1714938284919808002
if (this.$route.query.alarmId == null) {
console.error("告警id不可为空")
}
this.getAlarmDetails(this.$route.query.alarmId)
// this.planningPath()
break
case "mobileHomePage":
// http://localhost:8080/hd-glasses-app/#/hd_map?page=mobileHomePage
appInit(500).then((e) => {
console.log("获取到token开始执行后续")
console.log(e)
this.queryAlarmList();
this.queryAllEquipment();
this.getAreaList()
setInterval(() => {
this.queryAlarmList();
}, 3500)
setInterval(() => {
this.queryAllEquipment();
}, 5000)
}).then((e) => {
console.error(e)
})
break
default:
console.log("未匹配到page参数")
// this.planningPath()
// this.queryAlarmList()
// this.queryAllEquipment()
}
},
methods: {
PageAddAlarmPoint() {
this.canAddPoints = true;
this.clickMap();
},
showHistory() {
var _list = [[113.94755498147583, 22.565597285534384], [113.9468468782959, 22.563151110912802], [113.9487566111145, 22.56018995216036], [113.95017281747437, 22.55748628547335]]
},
clearPointsLayers() {
this.coordinate = []
this.map.removeLayer(this.pointLayer);
this.pointLayer = {};
if (Object.keys(this.pointLayer).length == 0) {
// 创建图层
this.pointLayer = new VectorLayer({
source: new VectorSource(),
});
// 图层添加到地图上
this.map.addLayer(this.pointLayer);
}
},
initMap() {
const wmsLayer_0 = new TileLayer({
source: new TileWMS({
// 设置 Geoserver 服务的 URL
url: process.env.VUE_APP_MAP_URL + "/wms",
params: {
LAYERS: "china:yangjianghedian",
TILED: true
}
})
});
const wmsLayer_1 = new TileLayer({
source: new TileWMS({
// 设置 Geoserver 服务的 URL
url: process.env.VUE_APP_MAP_URL + "/wms",
params: {
LAYERS: "china:yangjianghedian_dt",
TILED: true
}
})
});
// 切片方案0-18级
const projection = getProjection('EPSG:3857');
const projectionExtent = projection.getExtent();
const size = getWidth(projectionExtent) / 256;
const resolutions = new Array(19);
const matrixIds = new Array(19);
for (let z = 0; z < 19; ++z) {
resolutions[z] = size / Math.pow(2, z);
matrixIds[z] = "EPSG:3857:" + z;
}
var style = '';
var format = 'image/png';
var layerName = 'china:yangjianghedian_dt';
let baseParams = ['VERSION', 'LAYER', 'STYLE', 'TILEMATRIX', 'TILEMATRIXSET', 'SERVICE', 'FORMAT'];
let params = {
'VERSION': '1.0.0',
'LAYER': layerName,
'STYLE': style,
'TILEMATRIX': matrixIds,
'TILEMATRIXSET': projection,
'SERVICE': 'WMTS',
'FORMAT': format
};
var url = process.env.VUE_APP_MAP_URL + "/gwc/service/wmts?authkey=" + process.env.VUE_APP_MAP_AUTHKEY + "&"
for (var param in params) {
if (baseParams.indexOf(param.toUpperCase()) < 0) {
url = url + param + '=' + params[param] + '&';
}
}
url = url.slice(0, -1);
const wmtsLayer_1 = new TileLayer({
opacity: 1, //图层透明度
source: new WMTS({
url: url,
layer: "china:yangjianghedian_dt",
matrixSet: 'EPSG:3857',
format: 'image/png', // 默认:'image/jpeg'
projection: projection,
tileGrid: new WMTSTileGrid({
origin: getTopLeft(projectionExtent),
resolutions: resolutions,
matrixIds: matrixIds,
}),
style: '',
wrapX: true
})
});
this.map = new Map({
target: "map",
layers: [
// new TileLayer({
// source: new XYZ({
// url: "http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetPurplishBlue/MapServer/tile/{z}/{y}/{x}",
// }),
// }),
wmtsLayer_1,
wmsLayer_0,
],
view: new View({
resolutions: resolutions,
projection: projection,
center: [12497018.585823221, 2476783.2447665134],
zoom: 16,
}),
});
this.map.on('singleclick', e => {
this.map.forEachFeatureAtPixel(
e.pixel,
(feature) => {
console.log("Feature被点击了")
console.log(feature)
if (feature.values_.type == 'alarm') {
this.alarmDetailsData = feature.values_.data;
this.alarmDetailsOverlay = true;
}
},
{
hitTolerance: 30
}
);
});
},
/**
* 点击地图添加摄像头要素
*/
clickMap() {
this.map.on("click", (e) => {
if (this.canAddPoints) {
this.addPoints(e.coordinate);
}
});
},
planningPath() {
const startPoint = ol.proj.transform(this.navigationStartPoint, 'EPSG:4326', 'EPSG:3857');
const endPoint = ol.proj.transform(this.navigationEndPoint, 'EPSG:4326', 'EPSG:3857');
console.log(startPoint)
console.log(endPoint)
const _points = `${startPoint[0]}#${startPoint[1]}@${endPoint[0]}#${endPoint[1]}`
axios({
method: "post",
url: process.env.VUE_APP_MAP_URL + "/wfs?authkey=" + process.env.VUE_APP_MAP_AUTHKEY,
headers: {
'Content-Type': 'text/xml'
},
data: `<GetFeature xmlns="http://www.opengis.net/wfs" service="WFS" version="1.1.0"
outputFormat="application/json"
viewParams="points:${_points}"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/wfs.xsd">
<Query typeName="china:planning-path" xmlns:china="www.shgis.com"/>
</GetFeature>`,
}).then(res => {
// console.log("================================获取到了导航结果")
let pathList = [];
res.data.features.map((item, index) => {
pathList.push(item.geometry.coordinates[0])
pathList.push(item.geometry.coordinates[1])
// console.log(item.geometry.coordinates[0])
// console.log(item.geometry.coordinates[0])
})
const route = new LineString(pathList)
const geometryMove = new Point(route.getFirstCoordinate());
const featureMove = new Feature({
type: "featureMove",
geometry: geometryMove,
});
// this.planningVectorLayer.set('id', 'planningVectorLayer');
//先清空 再清除
this.map.removeLayer(this.planningVectorLayer)
this.planningVectorLayer = new VectorLayer({
source: new VectorSource({
features: [
new Feature({
type: "route",
geometry: route,
}),
featureMove,
new Feature({
type: "icon",
geometry: new Point(route.getFirstCoordinate()),
}),
new Feature({
type: "icon",
geometry: new Point(route.getLastCoordinate()),
}),
],
}),
style: (feature) => {
return this.styles[feature.get("type")];
},
});
this.map.addLayer(this.planningVectorLayer)
})
},
/**
* 根据经纬度坐标添加摄像头要素
*/
addPoints(coordinate) {
console.log("点击触发addPoints")
if (this.selectPoint.length > 0) {
this.coordinate = []
this.map.removeLayer(this.pointLayer);
this.pointLayer = {};
if (Object.keys(this.pointLayer).length == 0) {
// 创建图层
this.pointLayer = new VectorLayer({
source: new VectorSource(),
});
// 图层添加到地图上
this.map.addLayer(this.pointLayer);
}
} else {
// 创建图层
this.pointLayer = new VectorLayer({
source: new VectorSource(),
});
// 图层添加到地图上
this.map.addLayer(this.pointLayer);
}
this.selectPoint = coordinate;
this.coordinate = coordinate;
this.addAlarmPointNextAction()
/*
// 创建feature要素一个feature就是一个点坐标信息
const feature = new Feature({
geometry: new Point(coordinate),
});
// 设置要素的图标
feature.setStyle(
new Style({
// 设置图片效果
image: new Icon({
src: getStatisFileUrl("/map/icon_paishuibeng_h_2.png"),
// anchor: [0.5, 0.5],
scale: 0.4,
}),
})
);
// 要素添加到地图图层上
this.pointLayer.getSource().addFeature(feature);
*/
// 设置文字信息
// this.addText(coordinate);
},
addText(coordinate) {
const overlayBox = document.getElementById("overlay-box"); //获取一个div
const oSpan = document.createElement("span"); //创建一个span
oSpan.contentEditable = true; //设置文字是否可编辑
oSpan.id = coordinate[0]; //创建一个id
let pText = document.createTextNode("摄像头" + coordinate[0].toFixed(2)); //创建span的文本信息
oSpan.appendChild(pText); //将文本信息添加到span
overlayBox.appendChild(oSpan); //将span添加到div中
let textInfo = new Overlay({
position: coordinate, //设置位置
element: document.getElementById(coordinate[0]),
offset: [-25, 30], //设置偏移
});
this.map.addOverlay(textInfo);
},
addAlarmPointNextAction() {
if (this.selectPoint.length == 0) {
Dialog({message: '请先选择点位'});
}
// 上传之前将3857转4326
const result = ol.proj.transform(this.selectPoint, 'EPSG:3857', 'EPSG:4326');
window.parent.postMessage(result, "*");
},
drawPatrolRoute(routeList) {
this.map.removeLayer(this.pointLayer);
this.pointLayer = {};
this.pointLayer = new VectorLayer({
source: new VectorSource(),
});
// 图层添加到地图上
this.map.addLayer(this.pointLayer);
let pathList = []
routeList.map((item, index) => {
let fontColor = "black"
let circleColor="black"
if (index == 0 || routeList.length == index + 1) {
fontColor = "#F61115"
circleColor = "#F61115"
}
//打点
const coordinate = ol.proj.transform(item.point, 'EPSG:4326', 'EPSG:3857');
console.log(coordinate)
const feature = new Feature({
geometry: new Point(coordinate),
});
pathList.push(coordinate)
// 设置要素的图标
feature.setStyle(
new Style({
// 设置图片效果
image: new Circle({
radius: 7,
fill: new Fill({color: circleColor}),
stroke: new Stroke({
color: "white",
width: 2,
}),
}),
text: new Text({
testAlign: 'center',
text: item.title,
font: '16px 微软雅黑',
fill: new Fill({
color: fontColor,
}),
offsetY: 20
})
})
);
this.pointLayer.getSource().addFeature(feature);
})
// 要素添加到地图图层上
const route = new LineString(pathList)
let routeFeature = new Feature({
type: "route12",
geometry: route,
})
routeFeature.setStyle(new Style({
stroke: new Stroke({
width: 3,
color: "#FF8910",
}),
}))
this.pointLayer.getSource().addFeature(routeFeature);
}
},
};
</script>
<style lang="less">
// 非核心已删除
#content {
width: 100%;
height: 100%;
#map {
width: 100%;
height: 100%;
}
}
.ol-touch .ol-control button {
font-size: 26px;
}
.actionList {
position: fixed;
bottom: 0px;
left: 0px;
height: 200px;
width: 100%;
display: flex;
flex-direction: row;
justify-content: space-around;
flex-wrap: wrap;
}
.addAlarmPoint {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 100px;
display: flex;
flex-direction: row;
justify-content: center;
z-index: 100;
.addAlarmPointNext {
width: 80%;
height: 80px;
line-height: 80px;
background-color: #369FFF;
border-radius: 20px;
font-size: 26px;
color: white;
}
}
.pcPlanningPath {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 30px;
display: flex;
flex-direction: row;
justify-content: center;
z-index: 100;
.pcPlanningPathNext {
width: 80%;
height: 30px;
line-height: 30px;
background-color: #369FFF;
border-radius: 20px;
font-size: 16px;
color: white;
}
}
.mobileHomePageExpandBtn {
position: fixed;
top: 20px;
right: 30px;
z-index: 100;
}
.iconColorList {
position: fixed;
bottom: 20px;
left: 30px;
z-index: 2;
text-align: left;
font-size: 16px;
color: #333333;
.iconColorListItem {
display: flex;
flex-direction: row;
justify-content: start;
margin-top: 10px;
}
span {
width: 20px;
height: 20px;
border-radius: 20px;
margin-right: 20px;
display: block;
}
}
.alarmDetailsOverlayWrapper {
background-color: white;
position: fixed;
bottom: 0px;
left: 0px;
width: 100%;
z-index: 999;
display: flex;
flex-direction: column;
justify-content: flex-end;
font-size: 18px !important;
padding-top: 50px;
.alarmDetailsBox {
margin-left: 20px;
.title {
width: 100%;
font-weight: 900;
font-size: 10px;
text-align: left;
}
.alarmDetailsBoxItem {
font-weight: 700;
width: 100%;
text-align: left;
margin-top: 20px;
}
}
.btnList {
margin-top: 20px;
margin-bottom: 20px;
display: flex;
width: 100%;
flex-direction: row;
justify-content: space-around;
.btnItem {
background-color: #369FFF;
border-radius: 10px;
width: 40%;
height: 80px;
line-height: 80px;
color: white;
font-weight: bold;
}
}
}
</style>