You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1697 lines
55 KiB
1697 lines
55 KiB
<!--
|
|
电子地图
|
|
-编辑页面
|
|
-->
|
|
<template>
|
|
<div>
|
|
<div id="earthContainer" ref="earthContainer" style="width: 100%; height: 100%; top: 300px"></div>
|
|
<div class="earthUI_header" v-if="PropsEarthHeaderShow">
|
|
<header>
|
|
<p>{{ earthTitle }}</p>
|
|
<p>{{ realTime }}</p>
|
|
</header>
|
|
</div>
|
|
<div>
|
|
<a-radio-group default-value="satellite" button-style="solid" size="small" @change="radioChange" class="radioBtn" v-show="radioBtnShow">
|
|
<a-radio-button value="satellite"> 卫星影像</a-radio-button>
|
|
<a-radio-button value="vector"> 矢量地图</a-radio-button>
|
|
</a-radio-group>
|
|
<a-spin size="large" tip="地图切换中,请稍候..." :spinning="earthChangeSpin" class="earthChangeSpin"></a-spin>
|
|
</div>
|
|
|
|
<!-- 预警列表 -->
|
|
<!-- <WarnInfoList /> -->
|
|
|
|
<!-- 电线杆弹窗 -->
|
|
<div id="cameraModal" class="cameraModal" v-show="cameraModalShow" ref="cameraModal">
|
|
<a-spin size="large" :spinning="spinning" class="spinning"></a-spin>
|
|
<a-button @click="roamPathSet()">视频融合</a-button>
|
|
</div>
|
|
<!-- 视频融合 -->
|
|
<VideoFusionWin
|
|
v-if="VideoFusionWinShow"
|
|
:cameraList="cameraList"
|
|
:monitorPosition="monitorPosition"
|
|
:updateModel="toItemObj.updateModel"
|
|
:isUpdate="toItemObj.isUpdate"
|
|
:userSave="toItemObj.userSave"
|
|
></VideoFusionWin>
|
|
<!-- 地标弹窗 -->
|
|
<!-- <div id="poiModal" class="poiModal" v-show="poiModalShow" ref="poiModal">
|
|
<div class="poiModal-content">
|
|
<div class="poiModal-header"></div>
|
|
<div class="poiModal-body"></div>
|
|
</div>
|
|
</div>-->
|
|
|
|
<!-- 警示弹窗 -->
|
|
<video-split-screen />
|
|
|
|
<!-- 警示音频 -->
|
|
<audio ref="audio" loop>
|
|
<source src="@/assets/earthMap/audio/notify.mp3" />
|
|
</audio>
|
|
|
|
<!-- 云台控制弹窗 -->
|
|
<video-window
|
|
:id="videoWindowProps.id"
|
|
:visible.sync="videoWindowProps.visible"
|
|
:title="videoWindowProps.title"
|
|
:videoUrl="videoWindowProps.videoUrl"
|
|
:cameraIp="videoWindowProps.cameraIp"
|
|
:cameraUser="videoWindowProps.cameraUser"
|
|
:cameraPwd="videoWindowProps.cameraPwd"
|
|
:isAlarm="videoWindowProps.isAlarm"
|
|
:playRecord="videoWindowProps.playRecord"
|
|
:warnTime="videoWindowProps.warnTime"
|
|
:warnEvent="videoWindowProps.warnEvent"
|
|
/>
|
|
|
|
<!-- 左侧操作栏 -->
|
|
<Toolbar v-if="toolbarShow" :setLabelStatus="setLabelStatus" :all="this.all"></Toolbar>
|
|
<!-- 左下角显隐控件 -->
|
|
<ShowHideControl v-if="toolbarShow"></ShowHideControl>
|
|
<AddModelWin
|
|
v-if="addModelWinShow"
|
|
:setLabelStatus="setLabelStatus"
|
|
:czmObject="czmObject"
|
|
:node="node"
|
|
:type="type"
|
|
:lineId="lineId"
|
|
:areaCode="areaCode"
|
|
:areaByNodeId="areaByNodeIdModel"
|
|
:setIconByRef="setIconByRef"
|
|
:el="el"
|
|
:eidtId="eidtId"
|
|
></AddModelWin>
|
|
<AddRoamVideo v-if="addRoamVideoShow"></AddRoamVideo>
|
|
<!-- AIS信息显示窗口 -->
|
|
<AISInfoWindow v-if="AISInfoWindowShow" :ship_guid="ship_guid" :ship_aisData="ship_aisData"></AISInfoWindow>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import { Options, Vue } from 'vue-class-component';
|
|
import sceneTree from '@/assets/earthMap/resjson/sc.json';
|
|
import { defHttp } from '/@/utils/http/axios';
|
|
import earthUtils from '@/utils/earthMap/earth';
|
|
import _ from 'lodash';
|
|
import $ from 'jquery';
|
|
import { useUserStore } from '/@/store/modules/user';
|
|
import { useEarthMapStore } from '/@/store/modules/earthMap';
|
|
import Toolbar from '@/components/earthMap/Toolbar.vue';
|
|
import ShowHideControl from '/@/components/earthMap/ShowHideControl.vue';
|
|
import AddModelWin from '@/components/earthMap/toolbar/AddModelWin.vue';
|
|
import AddRoamVideo from '@/components/earthMap/toolbar/AddRoamVideo.vue';
|
|
import VideoSplitScreen from '@/components/earthMap/VideoSplitScreen.vue';
|
|
import VideoWindow from '@/components/earthMap/VideoWindow.vue';
|
|
import WarnInfoList from '@/components/earthMap/WarnInfoList.vue';
|
|
import AISInfoDetail from '@/components/earthMap/AISInfoDetail.vue';
|
|
import AISInfoWindow from '@/components/earthMap/AISInfoWindow.vue';
|
|
import { getRealTime } from '@/utils/date';
|
|
import $mitt from '@/utils/earthMap/mitt';
|
|
import guid from '@/utils/earthMap/guid';
|
|
import HandleNodeType from '@/utils/earthMap/handleNodeType';
|
|
import { handleNodeType } from '@/utils/earthMap/handleNodeType';
|
|
import { getRandomArr, getHeigthByLonLat } from '@/utils/earthMap/earth';
|
|
import redFlag from '@/assets/earthMap/redFlag.png';
|
|
import { addModel, addPin, addViewShedRadar, addShipGroundImg, addShipTrack } from '@/utils/earthMap/earthObj';
|
|
import { drawAllShips } from '@/utils/earthMap/shipDraw';
|
|
import hidePng from '@/assets/earthMap/hide.png';
|
|
import alarmImg from '@/assets/earthMap/alarm.gif';
|
|
import VideoFusionWin from './components/VideoFusionWin.vue';
|
|
import { useMessage } from '/@/hooks/web/useMessage';
|
|
import { CircleScan } from '@/utils/earthMap/radarEntity';
|
|
import { radianToDegreeInLngLatHeight } from '@/utils/earthMap/earth';
|
|
import listenMouseHandlerSence from '@/utils/earthMap/listenMouseHandlerSence';
|
|
import listenMouseHandler from '@/utils/earthMap/listenMouseHandler';
|
|
import getLineInfo from '@/utils/earthMap/getLineInfo';
|
|
import getCameraInfo from '@/utils/earthMap/getCameraInfo';
|
|
import getLabelInfo from '@/utils/earthMap/getLabelInfo';
|
|
import { setLabelStatus, setAllLabelStatus } from '@/utils/earthMap/setLabelStatus';
|
|
import keyControlInit from '@/utils/earthMap/keyControlInit';
|
|
import createRealTimeObj from '@/utils/earthMap/createRealTimeObj';
|
|
import sceneTreePopContextMenu from '@/utils/earthMap/sceneTreePopContextMenu';
|
|
import { drawInit } from '@/utils/earthMap/earthDraw';
|
|
import { cloneModel, cloneShamNode } from '@/utils/earthMap/clone';
|
|
import {
|
|
initWebSocket,
|
|
websocketonopen,
|
|
websocketonerror,
|
|
loreadAlarmInfo,
|
|
websocketclose,
|
|
websocketonmessage,
|
|
websocketdosend,
|
|
websock,
|
|
} from '@/utils/earthMap/websocket';
|
|
import setIconByRef from '@/utils/earthMap/setIconByRef';
|
|
|
|
import dwPng from '@/assets/images/rotationXYZ.png';
|
|
import rotationXYZ from '@/assets/images/rotationXYZ.png';
|
|
import circleDot2 from '@/assets/earthMap/circleDot2.png';
|
|
import circleDot1 from '@/assets/earthMap/circleDot1.png';
|
|
import circleDot3 from '@/assets/earthMap/circleDot3.png';
|
|
import { nextTick } from 'vue';
|
|
|
|
const { createMessage } = useMessage();
|
|
function setClassEl(setClassEl1, setClassEl2, checked) {
|
|
if (checked) {
|
|
setClassChecked(setClassEl1, setClassEl2);
|
|
} else {
|
|
setClassNoChecked(setClassEl1, setClassEl2);
|
|
}
|
|
}
|
|
|
|
function setClassChecked(setClassEl1, setClassEl2) {
|
|
// node.checkStatus = 'checked'
|
|
// node.disabled = ''
|
|
//***设置样式为选中 */
|
|
setClassEl1.className = 'xbsj-checkbox-wrapper xbsj-checkbox-wrapper-checked xbsj-checkbox-default';
|
|
setClassEl2.className = 'xbsj-checkbox xbsj-checkbox-checked';
|
|
}
|
|
|
|
function setClassNoChecked(setClassEl1, setClassEl2) {
|
|
// node.checkStatus = ''
|
|
// node.disabled = 'disabled'
|
|
// 设置为非选中
|
|
setClassEl1.className = 'xbsj-checkbox-wrapper xbsj-checkbox-wrapper-disabled xbsj-checkbox-default';
|
|
setClassEl2.className = 'xbsj-checkbox xbsj-checkbox-disabled';
|
|
}
|
|
|
|
function classMutationObserver(el, el1, checkedStauts, id) {
|
|
// 观察器的配置(需要观察什么变动) 属性,子节点or后代节点
|
|
const config = { attributes: true, childList: false, subtree: false };
|
|
const callback1 = function (mutationsList, observer) {
|
|
const checked = checkedStauts.get(id);
|
|
const oldClassName = el.className;
|
|
const trueClassName = 'xbsj-checkbox-wrapper xbsj-checkbox-wrapper-checked xbsj-checkbox-default';
|
|
const noClassName = 'xbsj-checkbox-wrapper xbsj-checkbox-wrapper-disabled xbsj-checkbox-default';
|
|
if (checked) {
|
|
if (oldClassName == trueClassName) {
|
|
return;
|
|
} else {
|
|
setClassChecked(el, el1);
|
|
}
|
|
} else {
|
|
if (oldClassName == noClassName) {
|
|
return;
|
|
} else {
|
|
setClassNoChecked(el, el1);
|
|
}
|
|
}
|
|
};
|
|
// 创建一个观察器实例并传入回调函数
|
|
const observer1 = new MutationObserver(callback1);
|
|
// 以上述配置开始观察目标节点
|
|
observer1.observe(el, config);
|
|
}
|
|
|
|
function disabledMutationObserver(el) {
|
|
const config = { attributes: true, childList: false, subtree: false };
|
|
const callback1 = function (mutationsList, observer) {
|
|
const el1 = mutationsList[0];
|
|
if (el1.attributeName == 'disabled') {
|
|
el.removeAttribute('disabled');
|
|
}
|
|
};
|
|
const observe1 = new MutationObserver(callback1);
|
|
// 以上述配置开始观察目标节点
|
|
observe1.observe(el, config);
|
|
}
|
|
|
|
@Options({
|
|
components: {
|
|
Toolbar,
|
|
ShowHideControl,
|
|
VideoSplitScreen,
|
|
VideoWindow,
|
|
WarnInfoList,
|
|
AddModelWin,
|
|
AddRoamVideo,
|
|
VideoFusionWin,
|
|
AISInfoDetail,
|
|
AISInfoWindow,
|
|
},
|
|
props: {
|
|
//全部显示
|
|
all: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
//头部显示
|
|
earthHeaderShow: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
//图层显示
|
|
sceneTreeShow: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
//状态栏
|
|
statusBarShow: {
|
|
type: Boolean,
|
|
default: true,
|
|
},
|
|
//主工具栏
|
|
mainBar: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
//监听事件
|
|
listenMouseHandlerOpen: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
//监听mitt
|
|
listenMittHandlerOpen: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
//地图路线资源
|
|
createBBHLineOpen: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
//加载区域
|
|
getLineInfoShow: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
//加载站点
|
|
getCameraInfoShow: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
//加载微波和雷达
|
|
getLabelInfoShow: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
//加载绘图
|
|
drawInitShow: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
//加载重点监控区域
|
|
keyControlInitShow: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
//后台场景管理点击
|
|
enablePointer: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
//后台场景管理点击事件监听
|
|
listenMouseHandlerSenceOpen: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
//后台区域管理事件
|
|
msMapLineHandler: {
|
|
type: Object,
|
|
default: null,
|
|
},
|
|
//后台监控点位管理事件
|
|
msCameraSiteHandle: {
|
|
type: Object,
|
|
default: null,
|
|
},
|
|
},
|
|
})
|
|
export default class EarthComp extends Vue {
|
|
/**
|
|
* 资源创建
|
|
*/
|
|
userStore = useUserStore();
|
|
store = useEarthMapStore();
|
|
setLabelStatus: any = setLabelStatus;
|
|
setIconByRef: any = setIconByRef;
|
|
earthTitle = '态势监控一张图';
|
|
realTime = '……';
|
|
// 注意:Earth和Cesium的相关变量放在vue中,必须使用下划线作为前缀!
|
|
// _earth = undefined;
|
|
// _viewer = undefined;
|
|
_pin = undefined;
|
|
_handler = undefined;
|
|
// sceneTree= require('@/assets/earthMap/resjson/sc.json'),
|
|
// sceneTree= new URL(`@/assets/earthMap/resjson/sc.json`, import.meta.url).href,
|
|
sceneTree: any = sceneTree;
|
|
// areaB= require('@/assets/earthMap/resjson/area_b.json'),
|
|
url: any = {
|
|
queryLabelList: 'military/msMapLabel/queryLabelAndDeviceList',
|
|
queryLineList: 'military/msMapLine/list',
|
|
queryCameraInfo: 'military/camera/site/getCameraInfoForEarth',
|
|
queryAllModelInfo: 'military/msModelPosition/queryAllModelInfo',
|
|
queryPatrolRouteInfo: 'military/msPatrolLine/getLineDetail',
|
|
queryBayoneByParam: 'military/msBayonetStatistics/getBayoneByParam',
|
|
queryAisInfo: 'military/checkpoint/msAisInfo/list',
|
|
keepAlive: 'military/mapInfo/keepAlive',
|
|
//雷达扫描列表
|
|
radarList: '/military/RadarConfig/list',
|
|
// 删除模型
|
|
// 传感器
|
|
deleteSensor: '/military/msModelPosition/deleteByEventSerialNum',
|
|
// 站点
|
|
deleteSite: '/military/camera/site/delete',
|
|
// 标志点
|
|
deleteMapLabel: '/military/msMapLabel/delete',
|
|
updateMapLine: '/military/msMapLine/edit',
|
|
deleteMapLine: '/military/msMapLine/delete',
|
|
saveMapLine: '/military/msMapLine/add',
|
|
// 编辑 模型
|
|
// 传感器
|
|
updateSensor: '/military/msModelPosition/editByEventSerialNum',
|
|
// 站点
|
|
updateSite: '/military/camera/site/edit',
|
|
|
|
// 标志点
|
|
updateMapLabel: '/military/msMapLabel/edit',
|
|
|
|
// 模型 保存
|
|
// 传感器
|
|
SaveSensorModel: '/military/msModelPosition/add',
|
|
// 站点
|
|
saveCameraSiteModel: '/military/camera/site/add',
|
|
// 标志点
|
|
saveMapLabel: '/military/msMapLabel/addMapLabel',
|
|
|
|
// 通过 线路名称 查询 线路
|
|
queryMapLine: '/military/msMapLine/queryByName',
|
|
querySiteById: '/military/camera/site/queryById',
|
|
// 查询设备列表
|
|
queryDeviceInfoList: '/military/msDeviceInfo/list',
|
|
setDefenseArea: '/military/netty/microwaveDetector/defenceArea',
|
|
perimeterRegionList: '/third/api/perimeterRegionList',
|
|
perimeterControl: '/third/api/perimeterControl',
|
|
// 雷达重新发送报警信息
|
|
sendRadarAlarmByWebSocket: '/military/warn/sendRadarAlarmByWebSocket',
|
|
};
|
|
// cameraData: any = {};
|
|
cameraModalShow = false;
|
|
poiModalShow = false;
|
|
radioBtnShow = true;
|
|
glmId: any = [];
|
|
spinning = false;
|
|
earthChangeSpin = false;
|
|
// websock: any = [];
|
|
timer: any = null; // 保活定时器
|
|
timer2: any = null; // 时间定时器
|
|
// 报警清除-定时器
|
|
alarmTrackClearTimer: any = null;
|
|
videoWindowProps: any = {
|
|
visible: false,
|
|
isAlarm: false,
|
|
id: '',
|
|
title: '',
|
|
videoUrl: '',
|
|
cameraIp: '',
|
|
cameraUser: '',
|
|
cameraPwd: '',
|
|
playRecord: false,
|
|
warnTime: null,
|
|
warnEvent: {
|
|
happenTime: '',
|
|
happenLoc: '',
|
|
warnNum: 0,
|
|
warnLevel: 0,
|
|
warnType: 0,
|
|
warnContent: '',
|
|
},
|
|
};
|
|
// 图层管理- 模型 ref 旧值
|
|
sceneTreeOldRefValue = '';
|
|
sceneInfo: any = null;
|
|
// 区域节点By Ref划分
|
|
// nodeConfigByRef = new Map();
|
|
// nodeCheckedByRef = new Map();
|
|
// areaByNodeId = new Map();
|
|
// statusByNodeId = new Map();
|
|
// imgByRef = new Map();
|
|
// radarAlarmDataMap = new Map();
|
|
wbUnifiedResponse = false;
|
|
// hostDeviceMapById = new Map();
|
|
// alarmInfoMap = new Map();
|
|
toolbarShow = false;
|
|
|
|
//addModelWin
|
|
addModelWinShow = false;
|
|
czmObject: any = null;
|
|
node: any = null;
|
|
type = '';
|
|
lineId = '';
|
|
areaCode = '';
|
|
areaByNodeIdModel = '';
|
|
el: any = null;
|
|
eidtId: any = null;
|
|
//addroamVideo
|
|
addRoamVideoShow = false;
|
|
|
|
// 控制窗口显示
|
|
VideoFusionWinShow = false;
|
|
//传到子组件的值
|
|
toItemObj: any = {
|
|
updateModel: {},
|
|
isUpdate: true,
|
|
userSave: {},
|
|
};
|
|
// 节点值
|
|
domKey: any = '';
|
|
// 监控相机列表
|
|
cameraList: any = [];
|
|
// 监控相机位置
|
|
monitorPosition: any = [];
|
|
|
|
//处理props 由于从父组件传来props,为作区分其他变量,则采用首字母大写命名
|
|
PropsEarthHeaderShow = this.earthHeaderShow;
|
|
PropsSceneTreeShow = this.sceneTreeShow;
|
|
PropsListenMouseHandlerOpen = this.listenMouseHandlerOpen;
|
|
PropsListenMittHandlerOpen = this.listenMittHandlerOpen;
|
|
PropsCreateBBHLineOpen = this.createBBHLineOpen;
|
|
PropsGetLineInfoShow = this.getLineInfoShow;
|
|
PropsGetCameraInfoShow = this.getCameraInfoShow;
|
|
PropsGetLabelInfoShow = this.getLabelInfoShow;
|
|
PropsDrawInitShow = this.drawInitShow;
|
|
PropsKeyControlInitShow = this.keyControlInitShow;
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//AIS信息窗口显示
|
|
AISInfoWindowShow = false;
|
|
// 船只guid
|
|
ship_guid = '123456';
|
|
// 船只ais信息
|
|
ship_aisData = {};
|
|
|
|
// 添加地图上的鼠标监听事件
|
|
// pin: any = undefined;
|
|
// viewer: any = undefined;
|
|
// // 鼠标样式
|
|
// cursorCss = "grab";
|
|
// position: any = null;
|
|
// rotation: any = null;
|
|
// fov: any = null;
|
|
mounted() {
|
|
let that = this;
|
|
//随机数
|
|
window.guid = guid;
|
|
//创建地球资源
|
|
this.createEarth();
|
|
//获取实时日期时间
|
|
this.getRealTime();
|
|
//初始化websocket
|
|
// this.initWebSocket('domianURL')
|
|
//阻止浏览器右键事件
|
|
document.oncontextmenu = function (e) {
|
|
return false;
|
|
};
|
|
|
|
{
|
|
//将回调延迟到下次 DOM 更新循环之后执行(针对由jq动态增加的元素绑定事件)
|
|
this.$nextTick(() => {
|
|
{
|
|
//监控点击事件
|
|
$('.cameraModal').on('click', '.openIframe', function (e: any) {
|
|
// web插件播放视频流
|
|
let videoWindowProps = that.videoWindowProps;
|
|
videoWindowProps.id = $(this).attr('id');
|
|
videoWindowProps.title = $(this).text();
|
|
videoWindowProps.videoUrl = $(this).attr('videoUrl');
|
|
videoWindowProps.cameraIp = $(this).attr('cameraIP');
|
|
videoWindowProps.cameraUser = $(this).attr('cameraUser');
|
|
videoWindowProps.cameraPwd = $(this).attr('cameraPsd');
|
|
videoWindowProps.isAlarm = false;
|
|
videoWindowProps.visible = true;
|
|
videoWindowProps.playRecord = false;
|
|
});
|
|
}
|
|
// 轮询
|
|
{
|
|
//一个小时调用一次空接口,保持系统session不过期
|
|
this.timer = setInterval(() => {
|
|
this.keepAlive();
|
|
}, 60 * 60 * 1000);
|
|
|
|
this.alarmTrackClearTimer = setInterval(() => {
|
|
this.radarAlarmTimeOutCheck();
|
|
}, 6 * 1000);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
// 打开视频融合
|
|
roamPathSet() {
|
|
// 打开视频融合
|
|
this.VideoFusionWinShow = true;
|
|
// 关闭相机列表
|
|
this.cameraModalShow = false;
|
|
}
|
|
|
|
// 后台区域管理事件
|
|
areaHandler(){
|
|
// 取消双击旋转事件
|
|
window.$viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(
|
|
window.Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK
|
|
);
|
|
this.$nextTick(() => {
|
|
$mitt.emit('msMapLineHandler', this.msMapLineHandler);
|
|
})
|
|
}
|
|
|
|
// 后台监控点位管理事件
|
|
cameraSiteHandler(){
|
|
// 取消双击旋转事件
|
|
window.$viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(
|
|
window.Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK
|
|
);
|
|
this.$nextTick(() => {
|
|
$mitt.emit('msCameraSiteHandle', this.msCameraSiteHandle);
|
|
})
|
|
}
|
|
|
|
// 控制子元素的显示或者隐藏
|
|
showOrHideChild(clickNode, earthUI, parentChecked) {
|
|
const childs = clickNode.children;
|
|
if (childs && childs.length > 0) {
|
|
for (const child of childs) {
|
|
const ref = child.ref;
|
|
const inputEl: any = document.getElementById(ref);
|
|
if (inputEl) {
|
|
inputEl.checked = parentChecked;
|
|
const event = new Event('change');
|
|
inputEl.dispatchEvent(event);
|
|
} else {
|
|
if (ref.startsWith('node_')) {
|
|
const readyNode = earthUI.earth.sceneTree.$refs[ref.split('_')[1]];
|
|
if (readyNode && readyNode.czmObject) {
|
|
readyNode.czmObject.show = parentChecked;
|
|
}
|
|
} else if (ref.startsWith('nodeSecondary_')) {
|
|
const readyNode = earthUI.earth.sceneTree.$refs[ref.split('_')[1]];
|
|
if (readyNode && readyNode.czmObject) {
|
|
readyNode.czmObject.show = parentChecked;
|
|
let guid = readyNode.czmObject.pinXbsjGuid;
|
|
let pin = window.$earth.getObject(guid);
|
|
pin.show = !pin.show;
|
|
}
|
|
} else {
|
|
if (child && child.czmObject) {
|
|
child.czmObject.show = parentChecked;
|
|
}
|
|
}
|
|
this.store.nodeCheckedByRef.set(ref, parentChecked);
|
|
this.showOrHideChild(child, earthUI, parentChecked);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 告警模型显示/隐藏
|
|
showAlarmPin(show) {
|
|
this.store.alarmInfoMap.forEach((item, _index) => {
|
|
item.pin.show = show;
|
|
item.pin._div.hidden = !show;
|
|
item.scanline.show = !show;
|
|
});
|
|
}
|
|
|
|
cameraPositionChange = _.debounce(
|
|
(that) => {
|
|
let height = window.$earth.camera.position[2];
|
|
if (height < 100) {
|
|
// 相机高度小于1000米,告警显示扫描线
|
|
that.showAlarmPin(false);
|
|
} else if (height >= 100) {
|
|
// 相机高度大于1000米,告警显示图标
|
|
that.showAlarmPin(true);
|
|
}
|
|
},
|
|
500,
|
|
{ maxWait: 1000 }
|
|
);
|
|
|
|
createEarth() {
|
|
let that = this;
|
|
//使用store存储XbsjEarthUI
|
|
this.store.xbsjEarthUI = XbsjEarthUI;
|
|
//处理props
|
|
if (this.all) {
|
|
this.PropsEarthHeaderShow = true;
|
|
this.PropsSceneTreeShow = true;
|
|
this.PropsListenMouseHandlerOpen = true;
|
|
this.PropsListenMittHandlerOpen = true;
|
|
this.PropsCreateBBHLineOpen = true;
|
|
this.PropsGetLineInfoShow = true;
|
|
this.PropsGetCameraInfoShow = true;
|
|
this.PropsGetLabelInfoShow = true;
|
|
this.PropsDrawInitShow = true;
|
|
this.PropsKeyControlInitShow = true;
|
|
}
|
|
//创建地球
|
|
XbsjEarthUI.create('earthContainer').then(async (earthUI: any) => {
|
|
// 设置全局变量,可调试
|
|
window.$uia = earthUI;
|
|
window.$earth = earthUI.earth;
|
|
window.$viewer = earthUI.earth.czm.viewer;
|
|
earthUI.controls.mainBar.show = false; //隐藏主工具栏
|
|
earthUI.controls.statusBar.show = true; //状态栏
|
|
//图层管理
|
|
let sceneTree = earthUI.tools.sceneTree;
|
|
// 显示图层管理
|
|
sceneTree.show = this.PropsSceneTreeShow;
|
|
// 设置图层管理 ref 输入框的 回车 事件
|
|
// ref 输入框的
|
|
let sceneTreeInput = sceneTree._comp.$el.getElementsByClassName('xbsj-model-content-box')[0].children[1];
|
|
// 地图右键菜单和ref输入框控制
|
|
this.$nextTick(() => {
|
|
// 删除ref 的 输入框
|
|
sceneTreeInput.remove();
|
|
// ----右键菜单样式控制--start
|
|
// 选择需要观察变动的节点
|
|
const targetNode = document.getElementsByClassName('menu-box')[0];
|
|
// 观察器的配置(需要观察什么变动) 属性,子节点or后代节点
|
|
const config = { attributes: true, childList: false, subtree: false };
|
|
// 当观察到变动时执行的回调函数
|
|
const callback = function (mutationsList, observer) {
|
|
// 右键会弹出菜单的样式 此时可以活的菜单这个元素
|
|
const el = mutationsList[0].target;
|
|
// 菜单的展示属性
|
|
const elDisplay = el.style.display;
|
|
// 如果菜单的展示属性本来就是none 则什么也不做
|
|
if (elDisplay == 'none') {
|
|
return;
|
|
}
|
|
// 获取到菜单项的集合
|
|
const childList = el.children[0].children;
|
|
// 菜单长度
|
|
const liSize = childList.length;
|
|
// 当菜单为none时 不显示
|
|
if (liSize == 0) {
|
|
el.style.display = 'none';
|
|
} else {
|
|
// 长度大于零 但第一个元素是 添加文件夹时也不显示
|
|
const text = childList[0].textContent;
|
|
if ('添加文件夹 ' == text) {
|
|
el.style.display = 'none';
|
|
}
|
|
}
|
|
};
|
|
// 创建一个观察器实例并传入回调函数
|
|
const observer = new MutationObserver(callback);
|
|
// 以上述配置开始观察目标节点
|
|
observer.observe(targetNode, config);
|
|
// -----右键菜单控制----end
|
|
});
|
|
let XE = window.XE;
|
|
// ref 的 输入框
|
|
// 设置 回车 事件
|
|
sceneTreeInput.onkeydown = function (e) {
|
|
if (e.code === 'Enter') {
|
|
// 回车事件
|
|
that.changeRef(earthUI.earth.sceneTree.currentSelectedNode, sceneTree._comp.$data.refvalue, that.sceneTreeOldRefValue);
|
|
}
|
|
};
|
|
// 设置失去焦点事件
|
|
sceneTreeInput.onblur = function () {
|
|
that.changeRef(earthUI.earth.sceneTree.currentSelectedNode, sceneTree._comp.$data.refvalue, that.sceneTreeOldRefValue);
|
|
};
|
|
// 修改图层管理中,右键菜单的显示
|
|
sceneTree._comp.popContextMenu = ({ item, vueObject }) => {
|
|
sceneTreePopContextMenu({ item, vueObject }, earthUI, this);
|
|
};
|
|
earthUI.tools.featureProperty.disabled = true; //禁用对象属性面板
|
|
|
|
window.$earth = earthUI.earth;
|
|
window.$earth.interaction.picking.enabled = true; // 全局打开点击事件权限
|
|
window.$earth.czm.viewer.scene.globe.depthTestAgainstTerrain = true; //开启深度检测
|
|
window.$earth.terrainEffect.subSurfaceEnabled = false; //开启地表透明模式
|
|
|
|
// this._viewer = earthUI.earth.czm.viewer;
|
|
window.$viewer.scene.fxaa = true; //图像改善
|
|
window.$viewer.scene.globe.baseColor = window.Cesium.Color.BLACK;
|
|
|
|
//加载场景资源
|
|
// console.log("this.sceneTree",this.sceneTree);
|
|
// console.log("window._CONFIG['earthMapURL']",window._CONFIG['earthMapURL']);
|
|
// console.log("window._CONFIG['satellite']",window._CONFIG['satellite']);
|
|
|
|
this.sceneTree.children[0].czmObject.xbsjImageryProvider.TileMapServiceImageryProvider.url =
|
|
window._CONFIG['earthMapURL'] + window._CONFIG['satellite'];
|
|
this.sceneTree.children[1].czmObject.xbsjImageryProvider.TileMapServiceImageryProvider.url =
|
|
window._CONFIG['earthMapURL'] + window._CONFIG['vector'];
|
|
this.sceneTree.children[2].czmObject.xbsjTerrainProvider.XbsjCesiumTerrainProvider.url =
|
|
window._CONFIG['earthMapURL'] + window._CONFIG['terrain'];
|
|
|
|
window.$earth.sceneTree.root = {
|
|
expand: true,
|
|
title: '场景树',
|
|
children: [this.sceneTree],
|
|
};
|
|
// 监控相机数据
|
|
XE.MVVM.watch(window.$earth.camera, 'position', () => {
|
|
this.cameraPositionChange(this);
|
|
});
|
|
|
|
// 飞入方法
|
|
await this.fly();
|
|
//创建工具栏
|
|
this.toolbarShow = true;
|
|
|
|
//加载地图实时资源(无人机、车辆、人员、巡逻路线等)
|
|
// createRealTimeObj(earthUI)
|
|
|
|
//监听鼠标事件
|
|
if (this.PropsListenMouseHandlerOpen) listenMouseHandler(that);
|
|
//监听鼠标事件(场景管理)
|
|
if (this.listenMouseHandlerSenceOpen) listenMouseHandlerSence(this.enablePointer, this);
|
|
|
|
//监听mitt
|
|
if (this.PropsListenMittHandlerOpen) this.listenMittHandler();
|
|
//加载地图线路资源
|
|
if (this.PropsCreateBBHLineOpen) await this.createBBHLine();
|
|
|
|
//使用后台区域管理事件 绘制区域等操作
|
|
if (this.msMapLineHandler) this.areaHandler()
|
|
|
|
//使用后台监控点位管理事件 设置监控杆等操作
|
|
if (this.msCameraSiteHandle) this.cameraSiteHandler()
|
|
|
|
});
|
|
}
|
|
|
|
//飞入方法
|
|
async fly() {
|
|
if (this.$attrs.onCustomFly) {
|
|
// 如果外部传入了customFly方法则调用外部的
|
|
this.$emit('customFly');
|
|
return;
|
|
}
|
|
let position, rotation, viewDistance, duration;
|
|
const sceneId = this.userStore.userInfo?.sceneId;
|
|
await defHttp
|
|
.get(
|
|
{
|
|
url: '/military/msMapScene/list',
|
|
params: {
|
|
pageNo: 1,
|
|
pageSize: 999,
|
|
sceneId: sceneId + '*',
|
|
column: 'sceneId',
|
|
order: 'asc',
|
|
},
|
|
},
|
|
{ isTransformResponse: false }
|
|
)
|
|
.then((response) => {
|
|
console.log('fly', response);
|
|
// 设置岛屿信息为数组
|
|
this.sceneInfo = response.result.records;
|
|
return response.result.records;
|
|
})
|
|
.then((res) => {
|
|
//飞入 所属场景下的位置
|
|
position = [res[0].cameraLon, res[0].cameraLat, res[0].cameraAltitude];
|
|
rotation = [res[0].rotationX, res[0].rotationY, res[0].rotationZ];
|
|
viewDistance = res[0].viewDistance;
|
|
duration = res[0].duration;
|
|
window.$earth.camera.flyTo(position, viewDistance, rotation, duration);
|
|
// 地图复原事件
|
|
window.$flyTo = this.flyTo = () => {
|
|
window.$earth.camera.flyTo(position, viewDistance, rotation, duration);
|
|
};
|
|
});
|
|
}
|
|
|
|
setLoginPoint(data) {
|
|
let position = [data.lon, data.lat, 0];
|
|
let rotation = [data.rotationX, data.rotationY, data.rotationZ];
|
|
let viewDistance = data.viewDistance;
|
|
let duration = data.duration ? data.duration : 1;
|
|
const leafConfig = {
|
|
name: '岛屿',
|
|
xbsjType: 'Pin',
|
|
// far: 2500000,
|
|
near: 3000000,
|
|
position: position,
|
|
// imageUrl: require('@/assets/redFlag.png'),
|
|
imageUrl: redFlag,
|
|
pinBuilder: {
|
|
extText: data.sceneName,
|
|
extTextFont: '30px 楷体',
|
|
extTextPixelOffset: [30, -40],
|
|
fillColor: [1, 1, 1, 0.9],
|
|
outlineColor: [0, 0, 0, 0.9],
|
|
},
|
|
};
|
|
|
|
const pin = new window.XE.Obj.Pin(window.$earth);
|
|
pin.xbsjFromJSON(leafConfig);
|
|
position[2] = data.altitude;
|
|
//鼠标事件
|
|
pin.onmouseover = () => {
|
|
window.$viewer._container.style.cursor = 'pointer';
|
|
};
|
|
pin.onmouseout = () => {
|
|
window.$viewer._container.style.cursor = 'default';
|
|
};
|
|
pin.onclick = function () {
|
|
window.$earth.camera.flyTo(position, viewDistance, rotation, duration);
|
|
};
|
|
}
|
|
|
|
/* 使用async/await 处理异步方法顺序执行。成功的操作放到try里,失败的放在catch里 */
|
|
async createBBHLine() {
|
|
// console.log('MyScene', this.userStore.userInfo?.sceneId);
|
|
let labelItems: any = undefined;
|
|
let type = 1; //**
|
|
|
|
let models: any = {
|
|
ref: this.sceneInfo[0].sceneId,
|
|
expand: true,
|
|
title: this.sceneInfo[0].sceneName,
|
|
children: [],
|
|
};
|
|
for (let record of this.sceneInfo) {
|
|
if (record.sceneId == this.userStore.userInfo?.sceneId) {
|
|
continue;
|
|
}
|
|
models.children.push({
|
|
ref: record.sceneId,
|
|
expand: false,
|
|
title: record.sceneName,
|
|
children: [],
|
|
});
|
|
}
|
|
|
|
// console.log('models',models);
|
|
|
|
// 加载防区
|
|
// console.log("加载防区");
|
|
if (this.PropsGetLineInfoShow) await getLineInfo(models, type);
|
|
|
|
// 加载站点
|
|
// console.log("加载站点");
|
|
if (this.PropsGetCameraInfoShow) await getCameraInfo(models, type);
|
|
|
|
// 加载雷达和微波
|
|
// console.log("加载雷达和微波");
|
|
if (this.PropsGetLabelInfoShow) labelItems = await getLabelInfo(models, type);
|
|
|
|
//加载绘画资源
|
|
if (this.PropsDrawInitShow) await drawInit();
|
|
|
|
//加载重点监控区域
|
|
if (this.PropsKeyControlInitShow) await keyControlInit();
|
|
|
|
// 监听树的dom节点变化
|
|
// console.log("监听树的dom节点变化");
|
|
this.$nextTick(() => {
|
|
// ----树节点复选框控制--start
|
|
// 容器元素
|
|
const target1 = document.getElementById('earthContainer')?.children[0].children[0].children[4].children[2].children[0].children[0];
|
|
// 配置子元素变动时触发
|
|
const config1 = { attributes: false, childList: true, subtree: false };
|
|
// this的别称
|
|
const that = this;
|
|
// 回调事件
|
|
const callback1 = function (mutationsList, observer) {
|
|
for (const mutation of mutationsList) {
|
|
// 新增元素
|
|
const el = mutation.addedNodes[0];
|
|
// 删除元素时不触发
|
|
if (!el) {
|
|
continue;
|
|
}
|
|
// 样式设置1
|
|
const setClassEl1 = el.children[0].children[1];
|
|
// 样式设置2
|
|
const setClassEl2 = setClassEl1.children[0];
|
|
|
|
// 查找input元素
|
|
const inputEl = setClassEl2.querySelector('input');
|
|
// 移除input元素的禁用属性
|
|
inputEl.removeAttribute('disabled');
|
|
const item = el.__vue__.item;
|
|
// item.checkStatus = 'ignored'
|
|
// 从元素中拿到这个元素节点对象
|
|
const nodeObject = item._inner.sn;
|
|
// console.log("nodeObject",nodeObject);
|
|
|
|
// 记录ref
|
|
const ref = nodeObject.ref;
|
|
if (ref.startsWith('wbList') || ref.startsWith('ldList')) {
|
|
// 展开菜单图标元素
|
|
const iel = el.children[0].children[0];
|
|
iel.addEventListener('click', function (e) {
|
|
if (iel.className == 'xbsj-icon xbsj-icon-ios-arrow-forward XbsjVritualTreeItemExpandIcon') {
|
|
console.log('收起菜单');
|
|
return;
|
|
}
|
|
// 获取展开菜单下的元素并设置图标
|
|
let eventTarget;
|
|
// console.log(nodeObject.children);
|
|
for (let index in nodeObject.children) {
|
|
if (index === '0') {
|
|
eventTarget = el.nextElementSibling;
|
|
} else {
|
|
eventTarget = eventTarget.nextElementSibling;
|
|
}
|
|
const child = nodeObject.children[index];
|
|
let customProp = JSON.parse(child.czmObject.customProp);
|
|
if (that.store.hostDeviceMapById.has(customProp.deviceId)) {
|
|
let device = that.store.hostDeviceMapById.get(customProp.deviceId);
|
|
// 设置状态
|
|
setLabelStatus(device, customProp.labelCode, child.ref, 2);
|
|
}
|
|
|
|
// 设置图标
|
|
setIconByRef(child.ref, eventTarget);
|
|
}
|
|
});
|
|
}
|
|
if (nodeObject.czmObject && nodeObject.czmObject.xbsjType == 'Pin') {
|
|
setIconByRef(ref, el);
|
|
}
|
|
// ref不为空并且大于0时 设置为input的id属性
|
|
if (ref && ref.length > 0) {
|
|
inputEl.id = ref;
|
|
}
|
|
// 首次展开添加元素默认为true,显示展示的对象
|
|
if (that.store.nodeCheckedByRef.size <= 0) {
|
|
// item.checkStatus = 'checked'
|
|
inputEl.checked = true;
|
|
//***设置样式为选中 */
|
|
setClassChecked(setClassEl1, setClassEl2, item);
|
|
that.store.nodeCheckedByRef.set(ref, true);
|
|
} else {
|
|
// 之后的展开根据ref获取应该显示的状态是选中还是非选中
|
|
let checked = that.store.nodeCheckedByRef.get(ref);
|
|
if (checked == undefined) {
|
|
checked = true;
|
|
if (ref && ref.length > 0 && ref.startsWith('node_')) {
|
|
// 分割ref
|
|
const refSplit = ref.split('_');
|
|
// 取出真实对象
|
|
const readyNode = window.$uia.earth.sceneTree.$refs[refSplit[1]];
|
|
if (readyNode && readyNode.czmObject) {
|
|
checked = readyNode.czmObject.show;
|
|
}
|
|
} else {
|
|
if (nodeObject && nodeObject.czmObject) {
|
|
checked = nodeObject.czmObject.show;
|
|
}
|
|
}
|
|
inputEl.checked = checked;
|
|
that.store.nodeCheckedByRef.set(ref, checked);
|
|
setClassEl(setClassEl, setClassEl2, checked, item);
|
|
} else {
|
|
setClassEl(setClassEl, setClassEl2, checked, item);
|
|
}
|
|
}
|
|
// 显示隐藏样式监听
|
|
classMutationObserver(setClassEl1, setClassEl2, that.store.nodeCheckedByRef, ref);
|
|
// input disabled属性监听
|
|
disabledMutationObserver(inputEl);
|
|
/**调整触发顺序,阻止默认的input change事件,并绑定自己的change事件 */
|
|
inputEl.addEventListener(
|
|
'change',
|
|
function (e) {
|
|
// 阻止其他同类型事件调用
|
|
e.stopImmediatePropagation();
|
|
// input元素获取
|
|
const el = e.target;
|
|
// 获取ref
|
|
const ref = el.id;
|
|
// 点击元素的earthSdk对象
|
|
const clickNode = window.$uia.earth.sceneTree.$refs[ref];
|
|
// 真实的earthSdk对象
|
|
let readyNode: any = null;
|
|
// 当ref大于0,并且以node_开头时,此为虚假的对象
|
|
if (ref && ref.length > 0 && ref.startsWith('node_')) {
|
|
// 分割ref
|
|
const refSplit = ref.split('_');
|
|
// 取出真实对象
|
|
readyNode = window.$uia.earth.sceneTree.$refs[refSplit[1]];
|
|
} else if (ref && ref.length > 0 && ref.startsWith('nodeSecondary_')) {
|
|
// 分割ref
|
|
const refSplit = ref.split('_');
|
|
// 取出真实对象
|
|
readyNode = window.$uia.earth.sceneTree.$refs[refSplit[1]];
|
|
let guid = readyNode.czmObject.pinXbsjGuid;
|
|
let pin = window.$earth.getObject(guid);
|
|
pin.show = !pin.show;
|
|
} else if (ref && ref.length > 0) {
|
|
// 真实对象就是本身
|
|
readyNode = clickNode;
|
|
}
|
|
// 控制子节点的状态同步
|
|
that.showOrHideChild(clickNode, window.$uia, el.checked);
|
|
if (readyNode != null) {
|
|
// 隐藏对象
|
|
if (!el.checked) {
|
|
if (readyNode && readyNode.czmObject) {
|
|
readyNode.czmObject.show = false;
|
|
}
|
|
// 设置属性
|
|
setClassNoChecked(setClassEl1, setClassEl2, item);
|
|
} else {
|
|
// 显示对象
|
|
if (readyNode && readyNode.czmObject) {
|
|
readyNode.czmObject.show = true;
|
|
}
|
|
// 设置属性
|
|
setClassChecked(setClassEl1, setClassEl2, item);
|
|
}
|
|
// 设置属性
|
|
setClassNoChecked(setClassEl1, setClassEl2, item);
|
|
} else {
|
|
// 显示对象
|
|
if (readyNode && readyNode.czmObject) {
|
|
readyNode.czmObject.show = true;
|
|
}
|
|
// 设置属性
|
|
setClassChecked(setClassEl1, setClassEl2, item);
|
|
}
|
|
// 记录当前节点状态
|
|
that.store.nodeCheckedByRef.set(ref, el.checked);
|
|
},
|
|
true
|
|
);
|
|
}
|
|
};
|
|
// 创建一个观察器实例并传入回调函数
|
|
const observer1 = new MutationObserver(callback1);
|
|
// 以上述配置开始观察目标节点
|
|
observer1.observe(target1, config1);
|
|
// 设置label的鼠标事件
|
|
labelItems.forEach((itemId) => {
|
|
if (window.$earth.sceneTree.$refs[itemId]) {
|
|
window.$earth.sceneTree.$refs[itemId].czmObject.onmouseover = () => {
|
|
window.$viewer._container.style.cursor = 'pointer';
|
|
};
|
|
window.$earth.sceneTree.$refs[itemId].czmObject.onmouseout = () => {
|
|
window.$viewer._container.style.cursor = 'default';
|
|
};
|
|
}
|
|
});
|
|
});
|
|
// 隐藏图层管理 "地图场景" 一栏
|
|
// document.getElementsByClassName('XbsjVritualTreeItem').item(0).style.display = 'none'
|
|
window.$earth.sceneTree.root.children.splice(1, 0, models);
|
|
}
|
|
|
|
listenMittHandler() {
|
|
let that = this;
|
|
{
|
|
$mitt.on('winShow', function (e: any) {
|
|
that.VideoFusionWinShow = e;
|
|
});
|
|
//其他页面调用本页面的methods方法
|
|
$mitt.on('listenMouseHandler', function () {
|
|
listenMouseHandler(that);
|
|
});
|
|
$mitt.on('removeHandler', function () {
|
|
that.removeHandler();
|
|
});
|
|
$mitt.on('createBBHLine', function () {
|
|
that.createBBHLine();
|
|
});
|
|
$mitt.on('createRealTimeObj', function () {
|
|
createRealTimeObj();
|
|
});
|
|
$mitt.on('radioChangeBtnShow', function (callback) {
|
|
that.radioChangeBtnShow(callback);
|
|
});
|
|
$mitt.on('loadingStatus', function () {
|
|
that.loadingStatus();
|
|
});
|
|
$mitt.on('clearAlarmModel', (mittData: any) => {
|
|
let { isWarnEvent, eventSerialNum } = mittData;
|
|
// 清除告警模型
|
|
if (isWarnEvent) {
|
|
// 是告警事件 先去后台查询预警事件获取事件编号
|
|
let url = 'military/msWarnEvent/queryWarnEventDetailList';
|
|
let params = {
|
|
eventSerialNum: eventSerialNum,
|
|
};
|
|
defHttp.get({ url, params }, { isTransformResponse: false }).then((res) => {
|
|
if (res.success) {
|
|
// 成功
|
|
let data = res.result;
|
|
for (const warnEventInfo of data) {
|
|
this.clearAlarmModel(warnEventInfo.eventSerialNum);
|
|
}
|
|
} else {
|
|
// 失败
|
|
console.log('失败');
|
|
createMessage.error(res.message);
|
|
}
|
|
});
|
|
} else {
|
|
// 不是告警事件,直接清除
|
|
this.clearAlarmModel(eventSerialNum);
|
|
}
|
|
});
|
|
// 监听mqtt消息
|
|
$mitt.on('deviceCmd', (message: any) => {
|
|
drawAllShips(message);
|
|
});
|
|
}
|
|
}
|
|
|
|
removeHandler() {
|
|
this._handler.removeInputAction(window.Cesium.ScreenSpaceEventType.MOUSE_MOVE); //移除鼠标事件
|
|
this._handler.removeInputAction(window.Cesium.ScreenSpaceEventType.LEFT_CLICK); //移除鼠标事件
|
|
}
|
|
|
|
radioChange(e) {
|
|
this.loadingStatus();
|
|
if (`${e.target.value}` == 'satellite') {
|
|
window.$earth.sceneTree.$refs.satellite.czmObject.show = true;
|
|
window.$earth.sceneTree.$refs.vector.czmObject.show = false;
|
|
} else if (`${e.target.value}` == 'vector') {
|
|
window.$earth.sceneTree.$refs.vector.czmObject.show = true;
|
|
window.$earth.sceneTree.$refs.satellite.czmObject.show = false;
|
|
}
|
|
}
|
|
|
|
radioChangeBtnShow(callback) {
|
|
this.radioBtnShow = !this.radioBtnShow;
|
|
callback(this.radioBtnShow); //回调返回当前状态
|
|
}
|
|
|
|
loadingStatus() {
|
|
this.earthChangeSpin = !this.earthChangeSpin; //加载状态
|
|
setTimeout(() => {
|
|
this.earthChangeSpin = !this.earthChangeSpin; //3秒后去除加载状态
|
|
}, 3000);
|
|
}
|
|
|
|
keepAlive() {
|
|
defHttp.get({ url: this.url.keepAlive }, { isTransformResponse: false }).then((res) => {});
|
|
}
|
|
|
|
closeClient() {
|
|
chrome.call('close');
|
|
}
|
|
|
|
/**
|
|
* 保存更改的ref到模型和后台数据中;
|
|
* @param {Object} model 当前模型
|
|
* @param {string} newRef 新的ref
|
|
* @param {string} oldRef 旧的ref
|
|
*/
|
|
changeRef = _.debounce(function (model, newRef, oldRef) {
|
|
// 当数值改变时且旧值不等于空时,更新模型的ref
|
|
if (newRef !== oldRef && oldRef !== '') {
|
|
// 修改后台的数据
|
|
handleNodeType(model)
|
|
.sensor(() => {
|
|
defHttp
|
|
.put(
|
|
{
|
|
url: this.url.updateSensor + `?eventSerialNum=${oldRef}`,
|
|
params: { eventSerialNum: newRef },
|
|
},
|
|
{ isTransformResponse: false }
|
|
)
|
|
// putAction(this.url.updateSensor + `?eventSerialNum=${oldRef}`, {eventSerialNum: newRef})
|
|
.then((res) => {
|
|
if (res.success) {
|
|
// 设置保存的 ref
|
|
this.sceneTreeOldRefValue = '';
|
|
// 更新模型的名称
|
|
model.title = newRef;
|
|
createMessage.success('修改成功');
|
|
} else {
|
|
createMessage.error('修改失败: ' + res.message);
|
|
}
|
|
})
|
|
.catch((err) => {
|
|
createMessage.error('修改失败: ' + err);
|
|
});
|
|
})
|
|
.modelCallback(() => {
|
|
// 传感器标志线不能修改ref,因为 ref 是后台数据库的ID;
|
|
createMessage.warning('无法修改传感器标志线的ref');
|
|
})
|
|
.run();
|
|
}
|
|
}, 150);
|
|
|
|
radarAlarmTimeOutCheck() {
|
|
const now = Date.now();
|
|
const timeout = 5 * 60 * 1000;
|
|
// 遍历报警数据
|
|
this.store.alarmInfoMap.forEach((value, key) => {
|
|
// 获取当前时间与报警时间的时间差
|
|
const timeDiff = now - value.timestamp;
|
|
// 如果时间差大于5分钟,则清除报警
|
|
if (timeDiff > timeout) {
|
|
// 清除报警,有雷达告警则清除雷达告警和雷达轨迹
|
|
this.clearAlarmModel(key);
|
|
}
|
|
});
|
|
}
|
|
clearRadarAlarmModel(radarAlarmDataMap, eventNum) {
|
|
if (radarAlarmDataMap.has(eventNum)) {
|
|
let alarmData = radarAlarmDataMap.get(eventNum);
|
|
for (let target of alarmData.target) {
|
|
let pathModel = target.path;
|
|
let groundImageModel = target.groundImage;
|
|
// 销毁模型
|
|
pathModel && pathModel.destroy();
|
|
groundImageModel && groundImageModel.destroy();
|
|
}
|
|
this.store.radarAlarmDataMap.delete(eventNum);
|
|
}
|
|
}
|
|
clearAlarmModel(eventNum) {
|
|
// let alarmInfoMap = this.store.alarmInfoMap;
|
|
// let radarAlarmDataMap = this.store.radarAlarmDataMap;
|
|
if (this.store.alarmInfoMap.has(eventNum)) {
|
|
let alarmData = this.store.alarmInfoMap.get(eventNum);
|
|
// 清除报警
|
|
alarmData.pin && alarmData.pin._div.remove();
|
|
alarmData.pin && alarmData.pin.destroy();
|
|
alarmData.scanline && alarmData.scanline.destroy();
|
|
this.store.alarmInfoMap.delete(eventNum);
|
|
}
|
|
this.clearRadarAlarmModel(this.store.radarAlarmDataMap, eventNum);
|
|
}
|
|
|
|
// 获取当前实时时间
|
|
getRealTime() {
|
|
this.timer2 = setInterval(() => {
|
|
this.realTime = getRealTime();
|
|
}, 1000);
|
|
}
|
|
// 资源销毁
|
|
beforeDestroy() {
|
|
// vue程序销毁时,需要清理相关资源
|
|
console.log('vue程序销毁');
|
|
|
|
window.$earth = window.$earth && window.$earth.destroy();
|
|
websocketclose(null);
|
|
//清除定时器
|
|
clearInterval(this.timer);
|
|
clearInterval(this.timer2);
|
|
clearInterval(this.alarmTrackClearTimer);
|
|
}
|
|
// 资源销毁
|
|
destroy() {
|
|
// vue程序销毁时,需要清理相关资源
|
|
console.log('vue程序销毁', window.$earth);
|
|
|
|
// websocketclose();
|
|
//清除定时器
|
|
clearInterval(this.timer);
|
|
clearInterval(this.timer2);
|
|
clearInterval(this.alarmTrackClearTimer);
|
|
// window.$uia.tools.sceneTree.destroy()
|
|
// window.$earth = window.$earth && window.$earth.destroy();
|
|
//利用store.xbsjEarthUI 重新赋值 window.XbsjEarthUI
|
|
window.XbsjEarthUI = this.store.xbsjEarthUI;
|
|
window.$earth = undefined;
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style>
|
|
.xbsj-model-box,
|
|
.detail-model,
|
|
.xbsj-modal-box {
|
|
background: linear-gradient(360deg, rgba(9, 39, 76, 0.9), rgba(9, 39, 76, 0.6)) !important;
|
|
/* border: 1px solid #2c58a6; */
|
|
box-shadow: 0 0 10px #2c58a6;
|
|
}
|
|
|
|
.xbsjSceneTreeBox {
|
|
left: initial !important;
|
|
width: 280px !important;
|
|
height: 600px !important;
|
|
right: 0 !important;
|
|
top: 0 !important;
|
|
background: -webkit-linear-gradient(270deg, RGBA(9, 39, 76, 0.9), RGBA(9, 39, 76, 0.1)) !important;
|
|
background: -o-linear-gradient(270deg, RGBA(9, 39, 76, 0.9), RGBA(9, 39, 76, 0.1)) !important;
|
|
background: -moz-linear-gradient(270deg, RGBA(9, 39, 76, 0.9), RGBA(9, 39, 76, 0.1)) !important;
|
|
background: linear-gradient(270deg, RGBA(9, 39, 76, 0.9), RGBA(9, 39, 76, 0.1)) !important;
|
|
box-shadow: none !important;
|
|
}
|
|
|
|
.xbsjSceneTreeBox .xbsj-model-close {
|
|
display: none;
|
|
}
|
|
|
|
.xbsjcesium + div {
|
|
background: -webkit-linear-gradient(360deg, RGBA(9, 39, 76, 0.9), RGBA(9, 39, 76, 0.1)) !important;
|
|
background: -o-linear-gradient(360deg, RGBA(9, 39, 76, 0.9), RGBA(9, 39, 76, 0.1)) !important;
|
|
background: -moz-linear-gradient(360deg, RGBA(9, 39, 76, 0.9), RGBA(9, 39, 76, 0.1)) !important;
|
|
background: linear-gradient(360deg, RGBA(9, 39, 76, 0.9), RGBA(9, 39, 76, 0.1)) !important;
|
|
}
|
|
|
|
.distance-legend {
|
|
background: RGBA(9, 39, 76, 0.8);
|
|
}
|
|
|
|
/* 标题 */
|
|
.earthUI_header header {
|
|
position: relative;
|
|
top: -3px;
|
|
height: 4rem;
|
|
background: url(../../../assets/earthMap/head_bg.png) no-repeat top center;
|
|
background-size: 100% 90%;
|
|
}
|
|
|
|
.earthUI_header p {
|
|
font-family: 'Arial', 'Microsoft YaHei', '黑体', '宋体', sans-serif;
|
|
color: #00ffe4;
|
|
text-align: center;
|
|
margin: 0;
|
|
padding: 0;
|
|
}
|
|
|
|
.earthUI_header header > p:first-child {
|
|
font-size: 1.1rem;
|
|
line-height: 28px;
|
|
padding-top: 0.5vh;
|
|
/* 文字间隔 */
|
|
letter-spacing: 5px;
|
|
}
|
|
|
|
.earthUI_header header > p:last-child {
|
|
font-family: Microsoft YaHei;
|
|
font-size: 0.8rem;
|
|
font-weight: 400;
|
|
/* 文字间隔 */
|
|
letter-spacing: 0.5px;
|
|
}
|
|
|
|
.quitBtn {
|
|
position: relative;
|
|
text-align: center;
|
|
font-size: 12px;
|
|
min-width: 100px;
|
|
width: 120px;
|
|
height: 30px;
|
|
padding: 0 7px;
|
|
margin-left: 100px;
|
|
line-height: 30px;
|
|
border-radius: 100px;
|
|
border: 1px solid #c9c9c9;
|
|
background-color: #fff;
|
|
color: #555;
|
|
cursor: pointer;
|
|
display: none;
|
|
}
|
|
|
|
/* 视频窗口 */
|
|
.videos {
|
|
display: none;
|
|
border: 1px solid #080808;
|
|
/*position: fixed;
|
|
right: 0;
|
|
bottom: 2px; */
|
|
position: absolute;
|
|
left: 0;
|
|
top: 0;
|
|
z-index: 100;
|
|
width: 420px;
|
|
height: 380px;
|
|
-webkit-box-shadow: 0px 3px 3px #c8c8c8;
|
|
-moz-box-shadow: 0px 3px 3px #c8c8c8;
|
|
box-shadow: 0px 3px 3px #c8c8c8;
|
|
}
|
|
|
|
.vclose {
|
|
position: absolute;
|
|
right: 1%;
|
|
top: 1%;
|
|
border-radius: 100%;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.videosSpan1 {
|
|
position: absolute;
|
|
left: 1%;
|
|
top: 1%;
|
|
color: #000;
|
|
font-size: 15px;
|
|
font-weight: bold;
|
|
font-family: 黑体;
|
|
border-radius: 100%;
|
|
}
|
|
|
|
.videosSpan2 {
|
|
position: absolute;
|
|
right: 1%;
|
|
bottom: 1%;
|
|
color: #000;
|
|
font-size: 16px;
|
|
font-weight: bold;
|
|
font-family: 黑体;
|
|
border-radius: 100%;
|
|
}
|
|
|
|
/* 相机状态点 */
|
|
.successStatus,
|
|
.offlineStatus,
|
|
.errorStatus {
|
|
position: relative;
|
|
}
|
|
|
|
.successStatus::before {
|
|
content: ' ';
|
|
position: absolute;
|
|
height: 7px;
|
|
width: 7px;
|
|
top: -60px;
|
|
left: 0;
|
|
/*transform: translateY(-50%);*/
|
|
border-radius: 50%;
|
|
background: rgb(0, 255, 0);
|
|
}
|
|
|
|
.offlineStatus::before {
|
|
content: ' ';
|
|
position: absolute;
|
|
height: 7px;
|
|
width: 7px;
|
|
top: -60px;
|
|
left: 0;
|
|
/*transform: translateY(-50%);*/
|
|
border-radius: 50%;
|
|
background: rgb(170, 170, 170);
|
|
}
|
|
|
|
.errorStatus::before {
|
|
content: ' ';
|
|
position: absolute;
|
|
height: 7px;
|
|
width: 7px;
|
|
top: -60px;
|
|
left: 0;
|
|
/*transform: translateY(-50%);*/
|
|
border-radius: 50%;
|
|
background: rgb(255, 0, 0);
|
|
}
|
|
|
|
/* 相机状态点 */
|
|
|
|
/* 电线杆气泡窗 */
|
|
.cameraModal {
|
|
margin: 20px auto;
|
|
position: absolute;
|
|
left: 0;
|
|
top: 0;
|
|
width: auto;
|
|
line-height: 25px;
|
|
color: white;
|
|
text-align: center;
|
|
font-size: 14px;
|
|
border: 1px solid rgb(255, 255, 255);
|
|
opacity: 0.9;
|
|
border-radius: 5px;
|
|
background: rgb(255, 255, 255);
|
|
}
|
|
|
|
.cameraModal::after {
|
|
/* 箭头靠下边 */
|
|
content: '';
|
|
position: absolute;
|
|
width: 0;
|
|
height: 0;
|
|
left: 35px;
|
|
bottom: -15px;
|
|
border-left: 10px solid transparent;
|
|
border-right: 10px solid transparent;
|
|
border-top: 15px solid rgb(255, 255, 255);
|
|
}
|
|
|
|
.cameraModal ul {
|
|
margin: 20px;
|
|
padding: 0px;
|
|
list-style: none;
|
|
}
|
|
|
|
.cameraModal li {
|
|
float: left;
|
|
list-style-type: none;
|
|
display: inline;
|
|
margin: 5px;
|
|
width: 120px;
|
|
border: 2px solid #fff;
|
|
}
|
|
|
|
.cameraModal li:hover {
|
|
border-bottom-color: #00ffe4;
|
|
}
|
|
|
|
.cameraModal li > a {
|
|
color: rgb(19, 15, 15);
|
|
text-decoration: none;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.cameraModal img {
|
|
width: 80px;
|
|
height: 60px;
|
|
display: block;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
.spinning {
|
|
position: absolute;
|
|
left: 50%;
|
|
top: 35%;
|
|
z-index: 999;
|
|
}
|
|
|
|
/* 电线杆气泡窗 */
|
|
|
|
/* 地标气泡窗 */
|
|
/*.poiModal {
|
|
margin: 20px auto;
|
|
padding: 5px;
|
|
position: absolute;
|
|
left: 0;
|
|
top: 0;
|
|
height: 160px;
|
|
width: 300px;
|
|
color: white;
|
|
text-align: center;
|
|
font-size: 14px;
|
|
border: 1px solid RGBA(12, 177, 177, 0.8);
|
|
border-radius: 5px;
|
|
filter: alpha(opacity=50);
|
|
background: RGBA(12, 177, 177, 0.9);
|
|
}
|
|
|
|
.poiModal::after {
|
|
!* 箭头靠下边 *!
|
|
content: '';
|
|
position: absolute;
|
|
width: 0;
|
|
height: 0;
|
|
left: 140px;
|
|
bottom: -15px;
|
|
border-left: 10px solid transparent;
|
|
border-right: 10px solid transparent;
|
|
border-top: 15px solid RGBA(12, 177, 177, 0.8);
|
|
}
|
|
|
|
.poiModal-content {
|
|
width: 100%;
|
|
height: 100%;
|
|
box-shadow: 0 5px 8px 0 rgba(0, 0, 0, 0.2), 0 7px 20px 0 rgba(0, 0, 0, 0.2);
|
|
animation-name: modalopen;
|
|
animation-duration: 1s;
|
|
}
|
|
|
|
.poiModal-header h2 {
|
|
margin: 0;
|
|
color: white;
|
|
}
|
|
|
|
.poiModal-header {
|
|
line-height: 40px;
|
|
}
|
|
|
|
.poiModal-body {
|
|
text-align: left;
|
|
font-size: 16px;
|
|
padding-left: 5px;
|
|
}
|
|
|
|
.poiModal-body span {
|
|
color: #ffeb3b;
|
|
}*/
|
|
|
|
/* 地标气泡窗 */
|
|
/* 地图切换按钮 */
|
|
.radioBtn {
|
|
position: absolute;
|
|
bottom: 40px;
|
|
right: 15px;
|
|
}
|
|
|
|
.radioBtn span {
|
|
transition: color 0.3s linear;
|
|
}
|
|
|
|
.radioBtn span:hover {
|
|
color: #00ffe4bb !important;
|
|
transition: color 0.3s linear;
|
|
}
|
|
|
|
.ant-radio-button-wrapper-checked {
|
|
background: #00ffe4bb !important;
|
|
border-color: #00ffe4 !important;
|
|
}
|
|
|
|
.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled)::before {
|
|
background-color: #00ffe4 !important;
|
|
}
|
|
|
|
.earthChangeSpin {
|
|
position: absolute;
|
|
left: 45%;
|
|
top: 35%;
|
|
}
|
|
|
|
.ant-spin {
|
|
color: #00ffe4;
|
|
}
|
|
|
|
.ant-spin-dot-item {
|
|
background-color: #00ffe4;
|
|
}
|
|
|
|
/* 地图切换按钮 */
|
|
/* 比例尺和指南针属性 */
|
|
#distanceLegendDiv .distance-legend {
|
|
bottom: 80px !important;
|
|
background-color: rgba(9, 39, 76, 0.7) !important;
|
|
}
|
|
|
|
#navigationDiv > div {
|
|
top: unset !important;
|
|
/*去掉已有的top值使bottom生效 */
|
|
bottom: 120px !important;
|
|
right: 40px !important;
|
|
}
|
|
|
|
.compass-outer-ring-background {
|
|
border: 12px solid rgba(9, 39, 76, 0.7) !important;
|
|
}
|
|
|
|
.compass-gyro-background {
|
|
background-color: rgba(9, 39, 76, 0.7) !important;
|
|
}
|
|
|
|
/* 比例尺和指南针属性 */
|
|
|
|
body {
|
|
user-select: none;
|
|
}
|
|
</style>
|
|
|