|
@@ -0,0 +1,1513 @@
|
|
|
+<template>
|
|
|
+ <div>
|
|
|
+ <div id="map" class="map-container"></div>
|
|
|
+ <!-- <countarea-panel
|
|
|
+ :buildid="tbuildId"
|
|
|
+ :countdic="countDic"
|
|
|
+ :show="buildData ? buildData.CountareaPanelOpen : false"
|
|
|
+ v-if="buildData ? buildData.CountareaPanelDisplay : false"
|
|
|
+ ></countarea-panel> -->
|
|
|
+ <!-- <image-video :cameraData.sync="cameraData" :visible.sync="cameraVisible"></image-video> -->
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import 'maptalks/dist/maptalks.css'
|
|
|
+import * as maptalks from 'maptalks'
|
|
|
+import * as mqtt from 'mqtt'
|
|
|
+import { getMQTTCilentId } from '@/utils/mqtt'
|
|
|
+import {
|
|
|
+ getRailListJson,
|
|
|
+ getAreaListJson,
|
|
|
+ getCameraListJson,
|
|
|
+ getPerimeterListJson,
|
|
|
+} from '@/api/positioning/map'
|
|
|
+import CountareaPanel from '@/components/CountareaPanel'
|
|
|
+import ImageVideo from '@/components/ImageVideo'
|
|
|
+
|
|
|
+import {
|
|
|
+ getRobotList,
|
|
|
+ getRecognizeList,
|
|
|
+ getAreaTree,
|
|
|
+ getNaviList,
|
|
|
+ getPositionList,
|
|
|
+ getSenceList,
|
|
|
+ getTaskList,
|
|
|
+ getRobotToken,
|
|
|
+ getPatrolRecordList,
|
|
|
+ getAlarmList,
|
|
|
+ getRealtimeList,
|
|
|
+} from '@/api/robotSLG/public'
|
|
|
+
|
|
|
+export default {
|
|
|
+ name: 'Map',
|
|
|
+ components: { CountareaPanel, ImageVideo },
|
|
|
+ props: {
|
|
|
+ runningTask: {
|
|
|
+ type: String,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ locationData: null,
|
|
|
+ baseRelativeCoordinate0: null,
|
|
|
+ baseRelativeCoordinate1: null,
|
|
|
+ baseRelativeExtent: null,
|
|
|
+ baseGPSCoordinate0: null,
|
|
|
+ baseGPSCoordinate1: null,
|
|
|
+ baseGPSExtent: null,
|
|
|
+ baseExtent: null,
|
|
|
+ //
|
|
|
+ buildNo: 0, //默认建筑编号,和建筑数据内容在数组中的下标一致
|
|
|
+ buildPanelPos: 0,
|
|
|
+ floorNo: 0, //默认楼层编号,和楼层数据在FloorList数组的下标一致
|
|
|
+ floorPanelPos: 0,
|
|
|
+ floorNoArray: [], //楼层数据,需为数组格式(接口参数规定)
|
|
|
+ postExtent: null,
|
|
|
+ //
|
|
|
+ buildData: null,
|
|
|
+ //
|
|
|
+ map: null,
|
|
|
+ mapLayer: null,
|
|
|
+ personLayer: null,
|
|
|
+ railLayer: null,
|
|
|
+ railAlarmLayer: null,
|
|
|
+ cameraLayer: null,
|
|
|
+ perimeterLayer: null,
|
|
|
+ perimeterAlarmLayer: null,
|
|
|
+ historyLayer: null,
|
|
|
+ //巡检机器人增加
|
|
|
+ robotNavLayer: null,
|
|
|
+ robotLayer: null,
|
|
|
+ //
|
|
|
+ debugPanel: null,
|
|
|
+ floorPanel: null,
|
|
|
+ buildPanel: null,
|
|
|
+
|
|
|
+ mqttClient: null,
|
|
|
+ topicArray: [],
|
|
|
+ topicCount: null,
|
|
|
+
|
|
|
+ areaList: [],
|
|
|
+ perimeterList: [],
|
|
|
+
|
|
|
+ personAlarm: {},
|
|
|
+ railAlarm: {},
|
|
|
+ areaAlarm: {},
|
|
|
+ arearailAlarm: {},
|
|
|
+ alarmingPerson: [],
|
|
|
+ alarmingRail: [],
|
|
|
+ countDic: {},
|
|
|
+
|
|
|
+ cameraData: {},
|
|
|
+ cameraVisible: false,
|
|
|
+
|
|
|
+ //机器人修改
|
|
|
+ robotToken: '',
|
|
|
+ patrolRecord: [],
|
|
|
+ realltimeData: [],
|
|
|
+ naviList: [],
|
|
|
+ }
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ VUE_APP_BASE_API() {
|
|
|
+ return process.env.VUE_APP_BASE_API
|
|
|
+ },
|
|
|
+ VUE_APP_BASE_WS() {
|
|
|
+ return 'ws://' + window.location.host + process.env.VUE_APP_BASE_API
|
|
|
+ },
|
|
|
+ tbuildId() {
|
|
|
+ return this.buildData ? this.buildData.BuildId || '' : ''
|
|
|
+ },
|
|
|
+ },
|
|
|
+ created() {
|
|
|
+ window.moveBuildPanel = this.moveBuildPanel
|
|
|
+ window.changeBuild = this.changeBuild
|
|
|
+ window.moveFloorPanel = this.moveFloorPanel
|
|
|
+ window.changeFloor = this.changeFloor
|
|
|
+ //机器人相关
|
|
|
+ this.initRobotInfo().then(() => {
|
|
|
+ this.getNaviListOption()
|
|
|
+ setTimeout(() => {
|
|
|
+ this.showTaskPoint()
|
|
|
+ console.log(this.runningTask)
|
|
|
+ }, 200)
|
|
|
+ })
|
|
|
+ },
|
|
|
+ mounted() {
|
|
|
+ this.$nextTick(async (_) => {
|
|
|
+ await this.getLocationData()
|
|
|
+ })
|
|
|
+ this.$nextTick(() => {
|
|
|
+ if (this.$route.query.type) {
|
|
|
+ this.railLayer.show()
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ // beforeDestroy() {
|
|
|
+ // this.mqttClient?.end()
|
|
|
+ // },
|
|
|
+ methods: {
|
|
|
+ // 机器人登录获取token
|
|
|
+ async initRobotInfo() {
|
|
|
+ try {
|
|
|
+ let res = await getRobotToken(ROBOT)
|
|
|
+ if (res.code === 1) {
|
|
|
+ this.robotToken = res.data
|
|
|
+ }
|
|
|
+ } catch (error) {}
|
|
|
+ },
|
|
|
+
|
|
|
+ //机器人导航点数据
|
|
|
+ async getNaviListOption() {
|
|
|
+ try {
|
|
|
+ let res = await getNaviList({ token: this.robotToken, pageIndex: 1, pageSize: 100 })
|
|
|
+ if (res.code === 1) {
|
|
|
+ this.naviList = res.data.list
|
|
|
+ //设置添加所有导航点并隐藏
|
|
|
+ this.setNavPointList()
|
|
|
+ } else {
|
|
|
+ this.initRobotInfo()
|
|
|
+ }
|
|
|
+ } catch (error) {}
|
|
|
+ },
|
|
|
+
|
|
|
+ //导航图层执行导航点
|
|
|
+ setNavPointList() {
|
|
|
+ this.robotNavLayer.clear()
|
|
|
+ if (this.naviList) {
|
|
|
+ this.naviList.forEach((check) => {
|
|
|
+ var m = new maptalks.Marker(
|
|
|
+ this.getNewCoordinate(+check.coordinateY * 100, +check.coordinateX * 100),
|
|
|
+ {
|
|
|
+ id: check.id,
|
|
|
+ visible: false,
|
|
|
+ symbol: {
|
|
|
+ markerFile: this.VUE_APP_BASE_API + '/../static/images/finishP.svg',
|
|
|
+ markerWidth: 40,
|
|
|
+ markerHeight: 40,
|
|
|
+ markerDx: 0,
|
|
|
+ markerDy: 20,
|
|
|
+ },
|
|
|
+ properties: {
|
|
|
+ id: check.id,
|
|
|
+ name: check.alias,
|
|
|
+ data: check,
|
|
|
+ },
|
|
|
+ }
|
|
|
+ ).addTo(this.robotNavLayer)
|
|
|
+ m.on('click', '')
|
|
|
+ })
|
|
|
+ }
|
|
|
+ return m
|
|
|
+ },
|
|
|
+ //显示任务点
|
|
|
+ showTaskPoint() {
|
|
|
+ if (this.runningTask) {
|
|
|
+ let p = this.robotNavLayer.getGeometryById(this.runningTask)
|
|
|
+ // console.log(p)
|
|
|
+ p.options.visible = true
|
|
|
+ }
|
|
|
+ },
|
|
|
+ //地图初始化数据
|
|
|
+ async getLocationData() {
|
|
|
+ this.locationData = this.$setting
|
|
|
+
|
|
|
+ if (this.locationData) {
|
|
|
+ this.buildNo = this.locationData.DefaultBuild // 默认建筑(在BuildList数组的位置)
|
|
|
+ this.buildData = this.locationData.BuildList[this.buildNo] //默认建筑数据
|
|
|
+ this.mapBaseLayer = this.locationData.MapBaseLayer //地图底图
|
|
|
+
|
|
|
+ this.floorNo = this.buildData.DefaultFloor //默认楼层(在FloorList数组的位置)
|
|
|
+
|
|
|
+ if (this.buildData.FloorList[this.floorNo].No instanceof Array) {
|
|
|
+ // 楼层数据,数组格式
|
|
|
+ this.floorNoArray = this.buildData.FloorList[this.floorNo].No
|
|
|
+ } else {
|
|
|
+ this.floorNoArray = [this.buildData.FloorList[this.floorNo].No]
|
|
|
+ }
|
|
|
+
|
|
|
+ this.baseRelativeCoordinate0 = new maptalks.Coordinate(this.buildData.RelativeCoordinate0) //左上角相对坐标,单位:毫米
|
|
|
+ this.baseRelativeCoordinate1 = new maptalks.Coordinate(this.buildData.RelativeCoordinate1) //右下角相对坐标,单位:毫米
|
|
|
+ //Extent 表示地图上的边界框,一个具有最小和最大坐标的矩形经纬度
|
|
|
+ // baseRelativeExtent 生成了一个相对坐标的边界矩形
|
|
|
+ this.baseRelativeExtent = new maptalks.Extent(
|
|
|
+ this.baseRelativeCoordinate0,
|
|
|
+ this.baseRelativeCoordinate1
|
|
|
+ )
|
|
|
+
|
|
|
+ if (this.buildData.MultiMap) {
|
|
|
+ //同一个服务器上是否有同一个BuildId的多个地图
|
|
|
+ this.postExtent = [
|
|
|
+ this.baseRelativeCoordinate0.x,
|
|
|
+ this.baseRelativeCoordinate0.y,
|
|
|
+ this.baseRelativeCoordinate1.x,
|
|
|
+ this.baseRelativeCoordinate1.y,
|
|
|
+ ]
|
|
|
+ } else {
|
|
|
+ this.postExtent = null
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.buildData.Projection == 'identity') {
|
|
|
+ // Projection 地图投影 值为EPSG:3857
|
|
|
+ // baseExtent 生成一个GPS坐标的矩形
|
|
|
+ this.baseExtent = new maptalks.Extent(
|
|
|
+ new maptalks.Coordinate(0, 0),
|
|
|
+ new maptalks.Coordinate(
|
|
|
+ this.baseRelativeCoordinate1.x - this.baseRelativeCoordinate0.x,
|
|
|
+ this.baseRelativeCoordinate0.y - this.baseRelativeCoordinate1.y
|
|
|
+ )
|
|
|
+ )
|
|
|
+ } else {
|
|
|
+ // GPSCoordinate0 左上角GPS坐标(WGS84) x:经度 y:纬度
|
|
|
+ // GPSCoordinate1 右下角GPS坐标(WGS84) x:经度 y:纬度
|
|
|
+ this.baseGPSCoordinate0 = new maptalks.Coordinate(this.buildData.GPSCoordinate0)
|
|
|
+ this.baseGPSCoordinate1 = new maptalks.Coordinate(this.buildData.GPSCoordinate1)
|
|
|
+ this.baseGPSExtent = new maptalks.Extent(this.baseGPSCoordinate0, this.baseGPSCoordinate1)
|
|
|
+ this.baseExtent = this.baseGPSExtent
|
|
|
+ }
|
|
|
+ await this.createMap()
|
|
|
+ } else {
|
|
|
+ console.log('获取定位配置文件失败')
|
|
|
+ }
|
|
|
+ },
|
|
|
+ async createMap() {
|
|
|
+ let zoom, maxZoom, minZoom, baseLayer, resolution0, resolutionMax
|
|
|
+
|
|
|
+ if (this.buildData.Projection == 'identity') {
|
|
|
+ zoom = this.buildData.RelativeMapZoom // 相对坐标地图缩放
|
|
|
+ maxZoom = this.buildData.RelativeMapMaxZoom //相对坐标地图最大缩放
|
|
|
+ minZoom = this.buildData.RelativeMapMinZoom //相对坐标地图最小缩放
|
|
|
+ resolution0 = this.buildData.RelativeResolution0 //相对坐标地图最大分辨率
|
|
|
+ resolutionMax = this.buildData.RelativeResolutionMax //相对坐标地图最大分辨率倍数
|
|
|
+ baseLayer = null
|
|
|
+ } else {
|
|
|
+ zoom = this.buildData.GPSMapZoom //GPS地图缩放
|
|
|
+ maxZoom = this.buildData.GPSMapMaxZoom //GPS地图最大缩放
|
|
|
+ minZoom = this.buildData.GPSMapMinZoom //GPS地图最小缩放
|
|
|
+ resolution0 = this.buildData.GPSResolution0 //GPS地图最大分辨率
|
|
|
+ resolutionMax = this.buildData.GPSResolutionMax //GPS地图最大分辨率倍数
|
|
|
+ baseLayer = new maptalks.TileLayer('base', this.mapBaseLayer) //地图来源
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.map) this.map.remove()
|
|
|
+ this.map = new maptalks.Map('map', {
|
|
|
+ center: this.baseExtent.getCenter(), //地图中点
|
|
|
+ //centerCross: true,
|
|
|
+ zoom: zoom,
|
|
|
+ maxZoom: maxZoom,
|
|
|
+ minZoom: minZoom,
|
|
|
+ bearing: this.buildData.MapBearing, //地图旋转角度
|
|
|
+ pitch: this.buildData.MapPitch, //地图倾斜角度
|
|
|
+ maxExtent: this.baseExtent, //地图最大范围,平移超出范围会反弹回来
|
|
|
+ zoomControl: {
|
|
|
+ // 缩放控件
|
|
|
+ position: 'top-left',
|
|
|
+ slider: false,
|
|
|
+ zoomLevel: false,
|
|
|
+ },
|
|
|
+ scaleControl: true, //比例尺控件
|
|
|
+ spatialReference: {
|
|
|
+ // Map 的空间引用,默认使用的是google的地图投影 EPSG: 3857
|
|
|
+ projection: this.buildData.Projection,
|
|
|
+ resolutions: (function () {
|
|
|
+ const resolutions = []
|
|
|
+ for (let i = 0; i <= resolutionMax; i++) {
|
|
|
+ resolutions[i] = resolution0 / Math.pow(2, i)
|
|
|
+ }
|
|
|
+ return resolutions
|
|
|
+ })(),
|
|
|
+ },
|
|
|
+ baseLayer: baseLayer, //基础图层
|
|
|
+ })
|
|
|
+ //将地图设置为适合给定范围的最大缩放级别
|
|
|
+ this.map.fitExtent(this.baseExtent, 0)
|
|
|
+ // 图片图层
|
|
|
+ this.mapLayer = new maptalks.ImageLayer(
|
|
|
+ 'map',
|
|
|
+ [
|
|
|
+ {
|
|
|
+ url: this.buildData.FloorList[this.floorNo].MapPath,
|
|
|
+ extent: this.baseExtent,
|
|
|
+ opacity: 1,
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ {
|
|
|
+ forceRenderOnMoving: true,
|
|
|
+ forceRenderOnZooming: true,
|
|
|
+ forceRenderOnRotating: true,
|
|
|
+ }
|
|
|
+ ).addTo(this.map)
|
|
|
+ // 矢量图层
|
|
|
+ this.robotNavLayer = new maptalks.VectorLayer('robotNav', {
|
|
|
+ zIndex: 2,
|
|
|
+ forceRenderOnMoving: true,
|
|
|
+ forceRenderOnZooming: true,
|
|
|
+ forceRenderOnRotating: true,
|
|
|
+ }).addTo(this.map)
|
|
|
+
|
|
|
+ this.robotLayer = new maptalks.VectorLayer('robot', {
|
|
|
+ zIndex: 1,
|
|
|
+ forceRenderOnMoving: true,
|
|
|
+ forceRenderOnZooming: true,
|
|
|
+ forceRenderOnRotating: true,
|
|
|
+ }).addTo(this.map)
|
|
|
+
|
|
|
+ this.personLayer = new maptalks.VectorLayer('person', {
|
|
|
+ zIndex: 100,
|
|
|
+ forceRenderOnMoving: true,
|
|
|
+ forceRenderOnZooming: true,
|
|
|
+ forceRenderOnRotating: true,
|
|
|
+ }).addTo(this.map)
|
|
|
+
|
|
|
+ this.cameraLayer = new maptalks.VectorLayer('camera', {
|
|
|
+ zIndex: 10,
|
|
|
+ visible: this.buildData.CameraLayerDisplay,
|
|
|
+ forceRenderOnMoving: true,
|
|
|
+ forceRenderOnZooming: true,
|
|
|
+ forceRenderOnRotating: true,
|
|
|
+ }).addTo(this.map)
|
|
|
+
|
|
|
+ this.railLayer = new maptalks.VectorLayer('rail', {
|
|
|
+ zIndex: 1,
|
|
|
+ visible: false,
|
|
|
+ forceRenderOnMoving: true,
|
|
|
+ forceRenderOnZooming: true,
|
|
|
+ forceRenderOnRotating: true,
|
|
|
+ }).addTo(this.map)
|
|
|
+
|
|
|
+ this.railAlarmLayer = new maptalks.VectorLayer('railAlarm', {
|
|
|
+ zIndex: 2,
|
|
|
+ visible: true,
|
|
|
+ forceRenderOnMoving: true,
|
|
|
+ forceRenderOnZooming: true,
|
|
|
+ forceRenderOnRotating: true,
|
|
|
+ }).addTo(this.map)
|
|
|
+
|
|
|
+ this.perimeterLayer = new maptalks.VectorLayer('perimeter', {
|
|
|
+ zIndex: 3,
|
|
|
+ visible: true,
|
|
|
+ forceRenderOnMoving: true,
|
|
|
+ forceRenderOnZooming: true,
|
|
|
+ forceRenderOnRotating: true,
|
|
|
+ }).addTo(this.map)
|
|
|
+
|
|
|
+ this.perimeterAlarmLayer = new maptalks.VectorLayer('perimeterAlarm', {
|
|
|
+ zIndex: 40,
|
|
|
+ visible: true,
|
|
|
+ forceRenderOnMoving: true,
|
|
|
+ forceRenderOnZooming: true,
|
|
|
+ forceRenderOnRotating: true,
|
|
|
+ }).addTo(this.map)
|
|
|
+
|
|
|
+ this.historyLayer = new maptalks.VectorLayer('history', {
|
|
|
+ zIndex: 20,
|
|
|
+ forceRenderOnMoving: true,
|
|
|
+ forceRenderOnZooming: true,
|
|
|
+ forceRenderOnRotating: true,
|
|
|
+ }).addTo(this.map)
|
|
|
+ // 右上角工具栏
|
|
|
+ let _this = this
|
|
|
+ new maptalks.control.Toolbar({
|
|
|
+ items: [
|
|
|
+ {
|
|
|
+ item: '复位地图',
|
|
|
+ click: function () {
|
|
|
+ _this.map.animateTo(
|
|
|
+ {
|
|
|
+ //center: baseExtent.getCenter(),
|
|
|
+ //zoom: 13,
|
|
|
+ bearing: _this.buildData.MapBearing,
|
|
|
+ pitch: _this.buildData.MapPitch,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ duration: 1000,
|
|
|
+ },
|
|
|
+ (frame) => {
|
|
|
+ if (frame.state.playState === 'finished') {
|
|
|
+ _this.map.fitExtent(_this.baseExtent, 0, {
|
|
|
+ duration: 1000,
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+ )
|
|
|
+ },
|
|
|
+ },
|
|
|
+ // {
|
|
|
+ // item: '围栏',
|
|
|
+ // children: [
|
|
|
+ // {
|
|
|
+ // item: '显示',
|
|
|
+ // click: function () {
|
|
|
+ // _this.railLayer.show()
|
|
|
+ // },
|
|
|
+ // },
|
|
|
+ // {
|
|
|
+ // item: '隐藏',
|
|
|
+ // click: function () {
|
|
|
+ // _this.railLayer.hide()
|
|
|
+ // },
|
|
|
+ // },
|
|
|
+ // ],
|
|
|
+ // },
|
|
|
+ // {
|
|
|
+ // item: '摄像头',
|
|
|
+ // children: [
|
|
|
+ // {
|
|
|
+ // item: '显示',
|
|
|
+ // click: function () {
|
|
|
+ // _this.cameraLayer.show()
|
|
|
+ // },
|
|
|
+ // },
|
|
|
+ // {
|
|
|
+ // item: '隐藏',
|
|
|
+ // click: function () {
|
|
|
+ // _this.cameraLayer.hide()
|
|
|
+ // },
|
|
|
+ // },
|
|
|
+ // ],
|
|
|
+ // },
|
|
|
+ ],
|
|
|
+ }).addTo(this.map)
|
|
|
+ // 右下角信息栏
|
|
|
+ if (this.buildData.DebugPanelDisplay) {
|
|
|
+ this.debugPanel = new maptalks.control.Panel({
|
|
|
+ position: 'bottom-right',
|
|
|
+ draggable: false,
|
|
|
+ custom: true,
|
|
|
+ content: '<div class="map-debugpanel">hello </div>',
|
|
|
+ closeButton: false,
|
|
|
+ }).addTo(this.map)
|
|
|
+
|
|
|
+ this.map.on('click', (e) => this.update(e))
|
|
|
+ }
|
|
|
+ // 楼层控制器
|
|
|
+ if (this.buildData.FloorPanelDisplay) {
|
|
|
+ this.createFloorPanel()
|
|
|
+ }
|
|
|
+ // 地图选择器
|
|
|
+ // if (this.locationData.BuildPanelDisplay) {
|
|
|
+ // this.createBuildPanel()
|
|
|
+ // }
|
|
|
+
|
|
|
+ // await this.getRail()
|
|
|
+ // await this.getArea()
|
|
|
+ // await this.getCamera()
|
|
|
+ // await this.getPerimeter()
|
|
|
+ // this.getLocation()
|
|
|
+
|
|
|
+ this.startMQTT()
|
|
|
+
|
|
|
+ // if (!this.interval1)
|
|
|
+ // this.interval1 = setInterval(() => {
|
|
|
+ // //this.getLocation()
|
|
|
+ // this.getRailAlarm()
|
|
|
+ // }, 1000)
|
|
|
+ // 点选重叠图形
|
|
|
+ this.map.on('contextmenu', (e) => this.identifyAndSelect(e))
|
|
|
+ },
|
|
|
+ //开始MQTT接收
|
|
|
+ startMQTT() {
|
|
|
+ this.personAlarm = {}
|
|
|
+ this.railAlarm = {}
|
|
|
+ this.areaAlarm = {}
|
|
|
+ this.arearailAlarm = {}
|
|
|
+ this.alarmingPerson = []
|
|
|
+ this.alarmingRail = []
|
|
|
+
|
|
|
+ this.topicArray.splice(0)
|
|
|
+ this.floorNoArray.forEach((f) => {
|
|
|
+ this.topicArray.push('Positioning/Positioning/' + this.buildData.BuildId + '/' + f + '/#')
|
|
|
+ this.topicArray.push('Positioning/Alarm/Person/' + this.buildData.BuildId + '/' + f + '/#')
|
|
|
+ this.topicArray.push('Positioning/Alarm/Rail/' + this.buildData.BuildId + '/' + f + '/#')
|
|
|
+ })
|
|
|
+ this.topicArray.push('Positioning/Alarm/Rail/' + this.buildData.BuildId + '/0/#')
|
|
|
+ this.topicArray.push('Positioning/Alarm/Area/' + this.buildData.BuildId + '/#')
|
|
|
+ this.topicArray.push('Perimeter/' + this.buildData.BuildId + '/0/#')
|
|
|
+ this.topicArray.push('Perimeter/#')
|
|
|
+ this.topicCount = 'CountArea/CountDic/' + this.buildData.BuildId
|
|
|
+
|
|
|
+ if (this.mqttClient && this.mqttClient.connected) {
|
|
|
+ this.mqttClient.subscribe(this.topicArray)
|
|
|
+ this.mqttClient.subscribe(this.topicCount)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 连接选项
|
|
|
+ const options = {
|
|
|
+ clean: true, // true: 清除会话, false: 保留会话
|
|
|
+ keepalive: 60,
|
|
|
+ connectTimeout: 4000, // 超时时间
|
|
|
+ // 认证信息
|
|
|
+ clientId: getMQTTCilentId('map'),
|
|
|
+ username: 'client',
|
|
|
+ password: '19c9547ad2029be96774fce5f1b9f099',
|
|
|
+ }
|
|
|
+ const connectUrl = this.VUE_APP_BASE_WS + '/MQTTOverWebSocket'
|
|
|
+ //console.log(connectUrl)
|
|
|
+ this.mqttClient = mqtt.connect(connectUrl, options)
|
|
|
+
|
|
|
+ let _this = this
|
|
|
+ this.mqttClient.on('connect', function () {
|
|
|
+ //订阅主题
|
|
|
+ console.log('定位MQTT正在连接')
|
|
|
+ _this.mqttClient.subscribe(_this.topicArray)
|
|
|
+ _this.mqttClient.subscribe(_this.topicCount)
|
|
|
+ })
|
|
|
+ this.mqttClient.on('message', (topic, message) => {
|
|
|
+ if (topic == 'Online') {
|
|
|
+ console.log('定位MQTT收到消息:', topic, message.toString())
|
|
|
+ } else if (topic.startsWith('Positioning/Positioning/')) {
|
|
|
+ this.chengePerson(JSON.parse(message.toString()))
|
|
|
+ //console.log(JSON.parse(message.toString()))
|
|
|
+ } else if (topic.startsWith('Positioning/Alarm/')) {
|
|
|
+ let alarm = JSON.parse(message.toString())
|
|
|
+ switch (alarm.AlarmSource) {
|
|
|
+ case 1:
|
|
|
+ this.personAlarm[alarm.Id] = alarm.AlarmList
|
|
|
+ this.personAlarming(alarm.Id)
|
|
|
+ break
|
|
|
+ case 2:
|
|
|
+ this.railAlarm[alarm.Id] = alarm.AlarmList
|
|
|
+ this.railAlarming(alarm.Id)
|
|
|
+ break
|
|
|
+ case 3:
|
|
|
+ this.areaAlarm[alarm.Id] = alarm.AlarmList
|
|
|
+ let area = this.areaList.find((v) => v.id == alarm.Id)
|
|
|
+ if (area && area.railIds && area.railIds.length > 0) {
|
|
|
+ area.railIds.forEach((a) => {
|
|
|
+ if (this.arearailAlarm[a]) {
|
|
|
+ if (alarm.AlarmList.length > 0) {
|
|
|
+ if (this.arearailAlarm[a].indexOf(area.id) == -1)
|
|
|
+ this.arearailAlarm[a].push(area.id)
|
|
|
+ } else {
|
|
|
+ let i = this.arearailAlarm[a].indexOf(area.id)
|
|
|
+ if (i >= 0) this.arearailAlarm[a].splice(i, 1)
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ this.arearailAlarm[a] = []
|
|
|
+ if (alarm.AlarmList.length > 0) this.arearailAlarm[a].push(area.id)
|
|
|
+ }
|
|
|
+ this.railAlarming(a)
|
|
|
+ })
|
|
|
+ }
|
|
|
+ break
|
|
|
+ default:
|
|
|
+ break
|
|
|
+ }
|
|
|
+ } else if (topic.startsWith('CountArea/CountDic/')) {
|
|
|
+ let count = JSON.parse(message.toString())
|
|
|
+ this.countDic = count
|
|
|
+ } else if (topic.startsWith('Perimeter/')) {
|
|
|
+ let perimeter = JSON.parse(message.toString())
|
|
|
+ if (
|
|
|
+ perimeter.buildId == this.buildData.BuildId &&
|
|
|
+ (this.floorNoArray.indexOf(perimeter.floorNo) > -1 || perimeter.FloorNo == 0)
|
|
|
+ ) {
|
|
|
+ //console.log(perimeter)
|
|
|
+ this.chengePerimeter(perimeter)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ chengePerson(person) {
|
|
|
+ if (person.Display == 1) {
|
|
|
+ let p = this.personLayer.getGeometryById(person.Id)
|
|
|
+ if (p) {
|
|
|
+ this.personMove(p, person)
|
|
|
+ } else {
|
|
|
+ this.addPerson(person)
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ let p = this.personLayer.getGeometryById(person.Id)
|
|
|
+ if (p) {
|
|
|
+ p.remove()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ chengePerimeter(perimeter) {
|
|
|
+ let s = this.perimeterLayer.getGeometryById(perimeter.segmentId)
|
|
|
+ if (!s) s = this.addPerimeter(perimeter.segmentId)
|
|
|
+ if (s) {
|
|
|
+ switch (perimeter.alarmType) {
|
|
|
+ case 0: //无报警
|
|
|
+ s.setSymbol({
|
|
|
+ lineColor: '#00ff00',
|
|
|
+ lineWidth: 4,
|
|
|
+ lineOpacity: 1,
|
|
|
+ })
|
|
|
+ break
|
|
|
+ case 1: //离线
|
|
|
+ s.setSymbol({
|
|
|
+ lineColor: '#ababab',
|
|
|
+ lineWidth: 4,
|
|
|
+ lineOpacity: 1,
|
|
|
+ })
|
|
|
+ break
|
|
|
+ case 2: //警告
|
|
|
+ s.setSymbol({
|
|
|
+ lineColor: '#00ff00',
|
|
|
+ lineWidth: 4,
|
|
|
+ lineOpacity: 1,
|
|
|
+ })
|
|
|
+ s.openInfoWindow()
|
|
|
+ break
|
|
|
+ case 3: //报警
|
|
|
+ s.setSymbol({
|
|
|
+ lineColor: '#00ff00',
|
|
|
+ lineWidth: 4,
|
|
|
+ lineOpacity: 1,
|
|
|
+ })
|
|
|
+ s.openInfoWindow()
|
|
|
+ break
|
|
|
+ default:
|
|
|
+ break
|
|
|
+ }
|
|
|
+ this.changPerimeterAlarm(perimeter.segmentId, perimeter.alarmType, perimeter.camera)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ addPerimeter(id) {
|
|
|
+ let perimeter
|
|
|
+ let segment
|
|
|
+ for (let p in this.perimeterList) {
|
|
|
+ perimeter = this.perimeterList[p]
|
|
|
+ segment = perimeter.segments.find((b) => b.id == id)
|
|
|
+ if (segment) break
|
|
|
+ }
|
|
|
+ let s
|
|
|
+ if (perimeter && segment) {
|
|
|
+ s = new maptalks.LineString(
|
|
|
+ segment.points.map((p) => this.getNewCoordinate(p.x, p.y)),
|
|
|
+ {
|
|
|
+ id: segment.id,
|
|
|
+ symbol: {
|
|
|
+ lineColor: '#00ff00',
|
|
|
+ lineWidth: 4,
|
|
|
+ lineOpacity: 1,
|
|
|
+ },
|
|
|
+ properties: {
|
|
|
+ id: segment.id,
|
|
|
+ name: perimeter.name + '分段' + segment.code,
|
|
|
+ },
|
|
|
+ }
|
|
|
+ )
|
|
|
+ .addTo(this.perimeterLayer)
|
|
|
+ .setInfoWindow({
|
|
|
+ width: 150,
|
|
|
+ content: perimeter.name + '分段' + segment.code,
|
|
|
+ })
|
|
|
+ }
|
|
|
+ return s
|
|
|
+ },
|
|
|
+ changPerimeterAlarm(id, alarmType, camera) {
|
|
|
+ let color
|
|
|
+ switch (alarmType) {
|
|
|
+ case 0: //无报警
|
|
|
+ return
|
|
|
+ case 1: //离线
|
|
|
+ return
|
|
|
+ case 2: //警告
|
|
|
+ color = '#ffff00'
|
|
|
+ break
|
|
|
+ case 3: //报警
|
|
|
+ color = '#ff0000'
|
|
|
+ break
|
|
|
+ default:
|
|
|
+ break
|
|
|
+ }
|
|
|
+ let g = this.perimeterAlarmLayer.getGeometryById(id)
|
|
|
+ if (g) {
|
|
|
+ if (g.getSymbol().lineColor == '#ff0000') color = '#ff0000'
|
|
|
+ g.setSymbol({
|
|
|
+ lineColor: color,
|
|
|
+ lineWidth: 6,
|
|
|
+ lineOpacity: 1,
|
|
|
+ })
|
|
|
+ return
|
|
|
+ }
|
|
|
+ let perimeter
|
|
|
+ let segment
|
|
|
+ for (let p in this.perimeterList) {
|
|
|
+ perimeter = this.perimeterList[p]
|
|
|
+ segment = perimeter.segments.find((b) => b.id == id)
|
|
|
+ if (segment) break
|
|
|
+ }
|
|
|
+ if (perimeter && segment) {
|
|
|
+ let s = new maptalks.LineString(
|
|
|
+ segment.points.map((p) => this.getNewCoordinate(p.x, p.y)),
|
|
|
+ {
|
|
|
+ id: segment.id,
|
|
|
+ symbol: {
|
|
|
+ lineColor: color,
|
|
|
+ lineWidth: 6,
|
|
|
+ lineOpacity: 1,
|
|
|
+ },
|
|
|
+ }
|
|
|
+ ).addTo(this.perimeterAlarmLayer)
|
|
|
+ s.on('click', (param) => this.perimeterAlarmLayer.removeGeometry(param.target))
|
|
|
+ setTimeout(() => this.flashPerimeterAlarm(id), 500)
|
|
|
+
|
|
|
+ if (alarmType == 2 || alarmType == 3) {
|
|
|
+ this.cameraVisible = true
|
|
|
+ this.cameraData = camera
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ flashPerimeterAlarm(id) {
|
|
|
+ let g = this.perimeterAlarmLayer.getGeometryById(id)
|
|
|
+ if (g) {
|
|
|
+ let s = g.getSymbol()
|
|
|
+ s.lineOpacity = s.lineOpacity == 1 ? 0 : 1
|
|
|
+ if (g) {
|
|
|
+ g.setSymbol(s)
|
|
|
+ setTimeout(() => this.flashPerimeterAlarm(id), 500)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 获取围栏
|
|
|
+ async getRail() {
|
|
|
+ this.railLayer.clear()
|
|
|
+ this.railAlarmLayer.clear()
|
|
|
+ let params = {
|
|
|
+ BuildId: this.buildData.BuildId,
|
|
|
+ FloorNoArray: this.floorNoArray,
|
|
|
+ Extent: this.postExtent,
|
|
|
+ // riskLevelArray: [1, 2, 3, 4] //四色图参数
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ let res = await getRailListJson(params)
|
|
|
+ let data = res.data.content
|
|
|
+ if (data.length > 0) {
|
|
|
+ data.forEach((r) => {
|
|
|
+ let inExtent = true
|
|
|
+ let points = []
|
|
|
+ r.points.forEach((p) => {
|
|
|
+ if (!this.baseRelativeExtent.contains(new maptalks.Coordinate(p.x, p.y)))
|
|
|
+ inExtent = false
|
|
|
+ points.push(this.getNewCoordinate(p.x, p.y))
|
|
|
+ })
|
|
|
+ if (inExtent) {
|
|
|
+ this.railLayer.addGeometry(
|
|
|
+ new maptalks.Polygon(points, {
|
|
|
+ symbol: {
|
|
|
+ lineColor: 'rgb(0,196,240)',
|
|
|
+ lineWidth: 2,
|
|
|
+ lineOpacity: 1,
|
|
|
+ polygonFill: 'rgb(135,196,240)',
|
|
|
+ polygonOpacity: 0.6,
|
|
|
+ },
|
|
|
+ })
|
|
|
+ )
|
|
|
+ this.railAlarmLayer.addGeometry(
|
|
|
+ new maptalks.Polygon(points, {
|
|
|
+ id: r.id,
|
|
|
+ visible: false,
|
|
|
+ symbol: {
|
|
|
+ lineColor: '#C06173',
|
|
|
+ lineWidth: 2,
|
|
|
+ lineOpacity: 1,
|
|
|
+ polygonFill: '#E08193',
|
|
|
+ polygonOpacity: 0.6,
|
|
|
+ },
|
|
|
+ })
|
|
|
+ )
|
|
|
+ this.railAlarming(r.id)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.log(error)
|
|
|
+ this.$message.error(error)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 获取摄像头
|
|
|
+ async getCamera() {
|
|
|
+ this.cameraLayer.clear()
|
|
|
+ let params = {
|
|
|
+ buildId: this.buildData.BuildId,
|
|
|
+ floorNoArray: this.floorNoArray,
|
|
|
+ extent: this.postExtent,
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ let res = await getCameraListJson(params)
|
|
|
+ let data = res.data.content
|
|
|
+ if (data.length > 0) {
|
|
|
+ data.forEach((c) => {
|
|
|
+ var m = new maptalks.Marker(this.getNewCoordinate(c.location.x, c.location.y), {
|
|
|
+ id: c.id,
|
|
|
+ visible: true,
|
|
|
+ symbol: {
|
|
|
+ markerFile: this.VUE_APP_BASE_API + c.iconPath,
|
|
|
+ markerWidth: 40,
|
|
|
+ markerHeight: 40,
|
|
|
+ markerDx: 0,
|
|
|
+ markerDy: 20,
|
|
|
+ },
|
|
|
+ properties: {
|
|
|
+ id: c.id,
|
|
|
+ name: c.name,
|
|
|
+ data: c,
|
|
|
+ },
|
|
|
+ }).addTo(this.cameraLayer)
|
|
|
+ m.on('click', this.cameraClickHandler)
|
|
|
+ })
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.log(error)
|
|
|
+ this.$message.error(error)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ cameraClickHandler(param) {
|
|
|
+ let c = param.target.getProperties()
|
|
|
+ this.cameraVisible = true
|
|
|
+ this.cameraData = c.data
|
|
|
+ },
|
|
|
+ // 获取区域
|
|
|
+ async getArea() {
|
|
|
+ let params = {
|
|
|
+ BuildId: this.buildData.BuildId,
|
|
|
+ // riskLevelArray: [1, 2, 3, 4] //四色图参数
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ let res = await getAreaListJson(params)
|
|
|
+ let data = res.data.content
|
|
|
+ this.areaList = data
|
|
|
+ } catch (error) {
|
|
|
+ console.log(error)
|
|
|
+ this.$message.error(error)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 获取周界
|
|
|
+ async getPerimeter() {
|
|
|
+ this.perimeterLayer.clear()
|
|
|
+ this.perimeterAlarmLayer.clear()
|
|
|
+ this.perimeterList = []
|
|
|
+ let params = {
|
|
|
+ BuildId: this.buildData.BuildId,
|
|
|
+ FloorNoArray: this.floorNoArray,
|
|
|
+ Extent: this.postExtent,
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ let res = await getPerimeterListJson(params)
|
|
|
+ let data = res.data.content
|
|
|
+ if (data.length > 0) {
|
|
|
+ this.perimeterList = data
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.log(error)
|
|
|
+ this.$message.error(error)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 创建地图选择按钮模块
|
|
|
+ createBuildPanel() {
|
|
|
+ if (this.buildNo <= 1) {
|
|
|
+ this.buildPanelPos = 0
|
|
|
+ } else if (this.buildNo >= this.locationData.BuildList.length - 3) {
|
|
|
+ this.buildPanelPos = this.locationData.BuildList.length - 3
|
|
|
+ } else {
|
|
|
+ this.buildPanelPos = this.buildNo - 1
|
|
|
+ }
|
|
|
+
|
|
|
+ let mapdiv = document.getElementById('map')
|
|
|
+ let mapdivh = mapdiv.clientHeight || mapdiv.offsetHeight
|
|
|
+
|
|
|
+ this.buildPanel = new maptalks.control.Panel({
|
|
|
+ position: { top: mapdivh / 2 - 60, left: '20' },
|
|
|
+ draggable: false,
|
|
|
+ custom: true,
|
|
|
+ content: this.makeBuildPanelContent(),
|
|
|
+ closeButton: false,
|
|
|
+ }).addTo(this.map)
|
|
|
+ },
|
|
|
+ // 左下按钮页面内容生成
|
|
|
+ makeBuildPanelContent() {
|
|
|
+ let content
|
|
|
+ content = '<table class="map-buildpanel" cellpadding="0" frame=void rules=none>'
|
|
|
+ content +=
|
|
|
+ '<tr><td><button onclick="moveBuildPanel(0)"><div class="up-arrows"></div></button></td></tr>'
|
|
|
+ for (let i = this.buildPanelPos; i <= this.buildPanelPos + 2; i++) {
|
|
|
+ if (i == this.buildNo) {
|
|
|
+ content +=
|
|
|
+ '<tr><td><button style="background: rgb(28,188,156);">' +
|
|
|
+ this.locationData.BuildList[i].BuildAbbName +
|
|
|
+ '</button></td></tr>'
|
|
|
+ } else {
|
|
|
+ if (this.locationData.BuildList[i]) {
|
|
|
+ content +=
|
|
|
+ '<tr><td><button onclick="changeBuild(' +
|
|
|
+ i +
|
|
|
+ ')">' +
|
|
|
+ this.locationData.BuildList[i].BuildAbbName +
|
|
|
+ '</button></td></tr>'
|
|
|
+ } else {
|
|
|
+ content += '<tr><td><button></button></td></tr>'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ content +=
|
|
|
+ '<tr><td><button onclick="moveBuildPanel(1)"><div class="down-arrows"></div></button></td></tr>'
|
|
|
+ content += '</table>'
|
|
|
+ return content
|
|
|
+ },
|
|
|
+ // 点击地图按钮上下箭头
|
|
|
+ moveBuildPanel(s) {
|
|
|
+ let b = this.buildPanelPos
|
|
|
+ if (s == 0) {
|
|
|
+ if (b > 0) b--
|
|
|
+ } else if (s == 1) {
|
|
|
+ if (b < this.buildData.FloorList.length - 3) b++
|
|
|
+ }
|
|
|
+ if (b != this.buildPanelPos) {
|
|
|
+ this.buildPanelPos = b
|
|
|
+ this.buildPanel.setContent(this.makeBuildPanelContent())
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 切换地图按钮操作
|
|
|
+ changeBuild(b) {
|
|
|
+ this.buildNo = b
|
|
|
+ this.buildPanel.setContent(this.makeBuildPanelContent())
|
|
|
+
|
|
|
+ this.buildData = this.locationData.BuildList[this.buildNo]
|
|
|
+
|
|
|
+ this.floorNo = this.buildData.DefaultFloor
|
|
|
+ if (this.buildData.FloorList[this.floorNo].No instanceof Array) {
|
|
|
+ this.floorNoArray = this.buildData.FloorList[this.floorNo].No
|
|
|
+ } else {
|
|
|
+ this.floorNoArray = [this.buildData.FloorList[this.floorNo].No]
|
|
|
+ }
|
|
|
+
|
|
|
+ this.baseRelativeCoordinate0 = new maptalks.Coordinate(this.buildData.RelativeCoordinate0)
|
|
|
+ this.baseRelativeCoordinate1 = new maptalks.Coordinate(this.buildData.RelativeCoordinate1)
|
|
|
+ this.baseRelativeExtent = new maptalks.Extent(
|
|
|
+ this.baseRelativeCoordinate0,
|
|
|
+ this.baseRelativeCoordinate1
|
|
|
+ )
|
|
|
+
|
|
|
+ if (this.buildData.MultiMap) {
|
|
|
+ this.postExtent = [
|
|
|
+ this.baseRelativeCoordinate0.x,
|
|
|
+ this.baseRelativeCoordinate0.y,
|
|
|
+ this.baseRelativeCoordinate1.x,
|
|
|
+ this.baseRelativeCoordinate1.y,
|
|
|
+ ]
|
|
|
+ } else {
|
|
|
+ this.postExtent = null
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.buildData.Projection == 'identity') {
|
|
|
+ this.baseExtent = new maptalks.Extent(
|
|
|
+ new maptalks.Coordinate(0, 0),
|
|
|
+ new maptalks.Coordinate(
|
|
|
+ this.baseRelativeCoordinate1.x - this.baseRelativeCoordinate0.x,
|
|
|
+ this.baseRelativeCoordinate0.y - this.baseRelativeCoordinate1.y
|
|
|
+ )
|
|
|
+ )
|
|
|
+ } else {
|
|
|
+ this.baseGPSCoordinate0 = new maptalks.Coordinate(this.buildData.GPSCoordinate0)
|
|
|
+ this.baseGPSCoordinate1 = new maptalks.Coordinate(this.buildData.GPSCoordinate1)
|
|
|
+ this.baseGPSExtent = new maptalks.Extent(this.baseGPSCoordinate0, this.baseGPSCoordinate1)
|
|
|
+ this.baseExtent = this.baseGPSExtent
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.mqttClient && this.mqttClient.connected) {
|
|
|
+ if (this.topicArray && this.topicArray.length > 0) {
|
|
|
+ this.topicArray.push(this.topicCount)
|
|
|
+ this.mqttClient.unsubscribe(this.topicArray, () => {
|
|
|
+ if (this.personLayer) this.personLayer.clear()
|
|
|
+ this.createMap()
|
|
|
+ })
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ this.createMap()
|
|
|
+ },
|
|
|
+ // 创建右下楼层切换按钮模块
|
|
|
+ createFloorPanel() {
|
|
|
+ if (this.floorNo <= 1) {
|
|
|
+ this.floorPanelPos = 0
|
|
|
+ } else if (this.floorNo >= this.buildData.FloorList.length - 3) {
|
|
|
+ this.floorPanelPos = this.buildData.FloorList.length - 3
|
|
|
+ } else {
|
|
|
+ this.floorPanelPos = this.floorNo - 1
|
|
|
+ }
|
|
|
+
|
|
|
+ let mapdiv = document.getElementById('map')
|
|
|
+ let mapdivh = mapdiv.clientHeight || mapdiv.offsetHeight
|
|
|
+
|
|
|
+ if (this.floorPanel) this.floorPanel.remove()
|
|
|
+
|
|
|
+ this.floorPanel = new maptalks.control.Panel({
|
|
|
+ position: { top: mapdivh / 2 - 60, right: '20' },
|
|
|
+ draggable: false,
|
|
|
+ custom: true,
|
|
|
+ content: this.makeFloorPanelContent(),
|
|
|
+ closeButton: false,
|
|
|
+ }).addTo(this.map)
|
|
|
+ },
|
|
|
+ // 楼层选择按钮模块页面内容生成
|
|
|
+ makeFloorPanelContent() {
|
|
|
+ let content
|
|
|
+ content = '<table class="map-floorpanel" cellpadding="0" frame=void rules=none>'
|
|
|
+ content +=
|
|
|
+ '<tr><td><button onclick="moveFloorPanel(0)"><div class="up-arrows"></div></button></td></tr>'
|
|
|
+ for (let i = this.floorPanelPos; i <= this.floorPanelPos + 2; i++) {
|
|
|
+ if (i == this.floorNo) {
|
|
|
+ content +=
|
|
|
+ '<tr><td><button style="background: rgb(28,188,156)">' +
|
|
|
+ this.buildData.FloorList[i].Name +
|
|
|
+ '</button></td></tr>'
|
|
|
+ } else {
|
|
|
+ if (this.buildData.FloorList[i]) {
|
|
|
+ content +=
|
|
|
+ '<tr><td><button onclick="changeFloor(' +
|
|
|
+ i +
|
|
|
+ ')">' +
|
|
|
+ this.buildData.FloorList[i].Name +
|
|
|
+ '</button></td></tr>'
|
|
|
+ } else {
|
|
|
+ content += '<tr><td><button></button></td></tr>'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ content +=
|
|
|
+ '<tr><td><button onclick="moveFloorPanel(1)"><div class="down-arrows"></div></button></td></tr>'
|
|
|
+ content += '</table>'
|
|
|
+ return content
|
|
|
+ },
|
|
|
+ // 点击切换楼层按钮上下箭头
|
|
|
+ moveFloorPanel(s) {
|
|
|
+ let f = this.floorPanelPos
|
|
|
+ if (s == 0) {
|
|
|
+ if (f > 0) f--
|
|
|
+ } else if (s == 1) {
|
|
|
+ if (f < this.buildData.FloorList.length - 3) f++
|
|
|
+ }
|
|
|
+ if (f != this.floorPanelPos) {
|
|
|
+ this.floorPanelPos = f
|
|
|
+ this.floorPanel.setContent(this.makeFloorPanelContent())
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 点击切换楼层
|
|
|
+ changeFloor(f) {
|
|
|
+ this.floorNo = f
|
|
|
+ this.floorPanel.setContent(this.makeFloorPanelContent())
|
|
|
+
|
|
|
+ if (this.buildData.FloorList[this.floorNo].No instanceof Array) {
|
|
|
+ this.floorNoArray = this.buildData.FloorList[this.floorNo].No
|
|
|
+ } else {
|
|
|
+ this.floorNoArray = [this.buildData.FloorList[this.floorNo].No]
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.mqttClient && this.mqttClient.connected) {
|
|
|
+ if (this.topicArray && this.topicArray.length > 0)
|
|
|
+ this.mqttClient.unsubscribe(this.topicArray, () => {
|
|
|
+ if (this.personLayer) this.personLayer.clear()
|
|
|
+ this.startMQTT()
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ this.mapLayer.setImages([
|
|
|
+ {
|
|
|
+ url: this.buildData.FloorList[this.floorNo].MapPath,
|
|
|
+ extent: this.baseExtent,
|
|
|
+ opacity: 1,
|
|
|
+ },
|
|
|
+ ])
|
|
|
+ this.getRail()
|
|
|
+ this.getCamera()
|
|
|
+ },
|
|
|
+ // 右下角信息栏显示内容生成
|
|
|
+ update(e) {
|
|
|
+ let projection = this.map.getProjection()
|
|
|
+ let coordinate = e.coordinate,
|
|
|
+ prj = projection.project(coordinate)
|
|
|
+
|
|
|
+ this.debugPanel.setContent(
|
|
|
+ '<div class="map-debugpanel">' +
|
|
|
+ [
|
|
|
+ 'Coordinate : [' + coordinate.x.toFixed(5) + ', ' + coordinate.y.toFixed(5) + ']',
|
|
|
+ 'Projected Coordinate : [' + prj.x.toFixed(5) + ', ' + prj.y.toFixed(5) + ']',
|
|
|
+ 'Zoom : ' + this.map.getZoom(),
|
|
|
+ ].join('<br>') +
|
|
|
+ '</div>'
|
|
|
+ )
|
|
|
+ },
|
|
|
+
|
|
|
+ addPerson(person) {
|
|
|
+ let marker = new maptalks.Marker(
|
|
|
+ this.getNewCoordinate(person.Positioning.X, person.Positioning.Y),
|
|
|
+ {
|
|
|
+ id: person.Id,
|
|
|
+ visible: true,
|
|
|
+ symbol: [
|
|
|
+ {
|
|
|
+ markerFile: this.VUE_APP_BASE_API + person.IconPath,
|
|
|
+ markerWidth: 40,
|
|
|
+ markerHeight: 40,
|
|
|
+ markerDx: 0,
|
|
|
+ markerDy: 20,
|
|
|
+ textName: person.Name,
|
|
|
+ textDx: 0,
|
|
|
+ textDy: 20,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ textName: '',
|
|
|
+ textWeight: 'bold',
|
|
|
+ textStyle: 'normal',
|
|
|
+ textSize: 0,
|
|
|
+ textFill: '#FF0000',
|
|
|
+ textOpacity: 1,
|
|
|
+ textDx: 0,
|
|
|
+ textDy: -20,
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ properties: {
|
|
|
+ id: person.Id,
|
|
|
+ name: person.Name,
|
|
|
+ },
|
|
|
+ }
|
|
|
+ ).addTo(this.personLayer)
|
|
|
+ marker.setInfoWindow({
|
|
|
+ title: person.Name,
|
|
|
+ width: 300,
|
|
|
+ autoCloseOn: 'click contextmenu',
|
|
|
+ content:
|
|
|
+ '<table width = "100%" style="border-bottom: 0px solid rgb(231, 234, 236) !important">\
|
|
|
+ <tr>\
|
|
|
+ <td width = "40%" rowspan="5" align="center">\
|
|
|
+ <img src="' +
|
|
|
+ (person.PhotoPath
|
|
|
+ ? this.VUE_APP_BASE_API + person.PhotoPath
|
|
|
+ : 'static/images/default.png') +
|
|
|
+ '" style="width: 85px; height: 140px; object-fit: contain"/>\
|
|
|
+ </td>\
|
|
|
+ <td class="tdname">类型:</td>\
|
|
|
+ <td class="tddata">' +
|
|
|
+ person.TypeName +
|
|
|
+ '</td>\
|
|
|
+ <tr>\
|
|
|
+ <td class="tdname">部门:</td>\
|
|
|
+ <td class="tddata">' +
|
|
|
+ person.DepartmentName +
|
|
|
+ '</td>\
|
|
|
+ </tr>\
|
|
|
+ <tr>\
|
|
|
+ <td class="tdname">职位:</td>\
|
|
|
+ <td class="tddata">' +
|
|
|
+ person.PositionName +
|
|
|
+ '</td>\
|
|
|
+ </tr>\
|
|
|
+ <tr>\
|
|
|
+ <td class="tdname">电话:</td>\
|
|
|
+ <td class="tddata">' +
|
|
|
+ person.Telephone +
|
|
|
+ '</td>\
|
|
|
+ </tr>\
|
|
|
+ <tr>\
|
|
|
+ <td class="tdname">SN:</td>\
|
|
|
+ <td class="tddata">' +
|
|
|
+ person.LabelMAC +
|
|
|
+ '</td>\
|
|
|
+ </tr>\
|
|
|
+ <tr style="height:10px"/>\
|
|
|
+ </table>',
|
|
|
+ })
|
|
|
+
|
|
|
+ this.personAlarming(person.Id)
|
|
|
+
|
|
|
+ return marker
|
|
|
+ },
|
|
|
+ personMove(geometry, person) {
|
|
|
+ geometry.animate(
|
|
|
+ {
|
|
|
+ translate: this.getOffset(geometry, person),
|
|
|
+ },
|
|
|
+ {
|
|
|
+ duration: 1000,
|
|
|
+ }
|
|
|
+ )
|
|
|
+ },
|
|
|
+ personAlarming(personId, repeat = false) {
|
|
|
+ let p = this.personLayer.getGeometryById(personId)
|
|
|
+ let pa = this.personAlarm[personId]
|
|
|
+
|
|
|
+ if (p) {
|
|
|
+ if (pa && pa.length > 0) {
|
|
|
+ if (!repeat) {
|
|
|
+ if (this.alarmingPerson.indexOf(personId) >= 0) return
|
|
|
+ else this.alarmingPerson.push(personId)
|
|
|
+ }
|
|
|
+
|
|
|
+ let str = ''
|
|
|
+ pa.forEach((v) => {
|
|
|
+ switch (v.AlarmType) {
|
|
|
+ case 11:
|
|
|
+ str += '越界(进入),'
|
|
|
+ break
|
|
|
+ case 12:
|
|
|
+ str += '越界(离开),'
|
|
|
+ break
|
|
|
+ case 20:
|
|
|
+ str += '滞留,'
|
|
|
+ break
|
|
|
+ case 50:
|
|
|
+ str += '静止,'
|
|
|
+ break
|
|
|
+ case 60:
|
|
|
+ str += 'SOS,'
|
|
|
+ break
|
|
|
+ default:
|
|
|
+ break
|
|
|
+ }
|
|
|
+ })
|
|
|
+ str = str.substr(0, str.length - 1)
|
|
|
+ if (p.getSymbol()[1].textName != str) {
|
|
|
+ p.updateSymbol([{}, { textName: str }])
|
|
|
+ }
|
|
|
+
|
|
|
+ if (p.getSymbol()[1].textSize == 0) {
|
|
|
+ p.updateSymbol([{}, { textSize: 16 }])
|
|
|
+ } else {
|
|
|
+ p.updateSymbol([{}, { textSize: 0 }])
|
|
|
+ }
|
|
|
+
|
|
|
+ setTimeout(() => {
|
|
|
+ this.personAlarming(personId, true)
|
|
|
+ }, 500)
|
|
|
+ } else {
|
|
|
+ let index = this.alarmingPerson.indexOf(personId)
|
|
|
+ if (index >= 0) this.alarmingPerson.splice(index, 1)
|
|
|
+ p.updateSymbol([{}, { textSize: 0 }])
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ railAlarming(railId, repeat = false) {
|
|
|
+ let r = this.railAlarmLayer.getGeometryById(railId)
|
|
|
+ let ra = this.railAlarm[railId]
|
|
|
+ let aa = this.arearailAlarm[railId]
|
|
|
+
|
|
|
+ if (r) {
|
|
|
+ if ((ra && ra.length > 0) || (aa && aa.length > 0)) {
|
|
|
+ if (!repeat) {
|
|
|
+ if (this.alarmingRail.indexOf(railId) >= 0) return
|
|
|
+ else this.alarmingRail.push(railId)
|
|
|
+ }
|
|
|
+
|
|
|
+ if (r.isVisible()) r.hide()
|
|
|
+ else r.show()
|
|
|
+ setTimeout(() => {
|
|
|
+ this.railAlarming(railId, true)
|
|
|
+ }, 500)
|
|
|
+ } else {
|
|
|
+ let index = this.alarmingRail.indexOf(railId)
|
|
|
+ if (index >= 0) this.alarmingRail.splice(index, 1)
|
|
|
+ r.hide()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ getOffset(geometry, person) {
|
|
|
+ let start = geometry.getCoordinates()
|
|
|
+ let end = this.getNewCoordinate(person.Positioning.X, person.Positioning.Y)
|
|
|
+ return end.sub(start)
|
|
|
+ },
|
|
|
+ getNewCoordinate(x, y) {
|
|
|
+ if (this.buildData.Projection == 'identity') {
|
|
|
+ return new maptalks.Coordinate(
|
|
|
+ x - this.baseRelativeCoordinate0.x,
|
|
|
+ this.baseRelativeCoordinate0.y - y
|
|
|
+ )
|
|
|
+ } else {
|
|
|
+ return this.map.locate(
|
|
|
+ this.baseGPSCoordinate0,
|
|
|
+ (x - this.baseRelativeCoordinate0.x) / 1000,
|
|
|
+ -(y - this.baseRelativeCoordinate0.y) / 1000
|
|
|
+ )
|
|
|
+ }
|
|
|
+ },
|
|
|
+ identifyAndSelect(e) {
|
|
|
+ let _this = this
|
|
|
+ //identify
|
|
|
+ this.map.identify(
|
|
|
+ {
|
|
|
+ coordinate: e.coordinate,
|
|
|
+ layers: [this.personLayer, this.cameraLayer, this.perimeterLayer],
|
|
|
+ },
|
|
|
+ function (geos) {
|
|
|
+ if (geos.length === 0) {
|
|
|
+ _this.map.removeMenu()
|
|
|
+ return
|
|
|
+ }
|
|
|
+ var options = { items: [] }
|
|
|
+ geos.forEach(function (g) {
|
|
|
+ var personN = g.getProperties().name
|
|
|
+ options.items.push({
|
|
|
+ item: personN,
|
|
|
+ click: function () {
|
|
|
+ // console.log(g.toJSON());
|
|
|
+ //g.openInfoWindow()
|
|
|
+ g.fire('click')
|
|
|
+ },
|
|
|
+ })
|
|
|
+ })
|
|
|
+ _this.map.setMenu(options).openMenu(e.coordinate)
|
|
|
+ }
|
|
|
+ )
|
|
|
+ },
|
|
|
+ },
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.map-container {
|
|
|
+ width: 90%;
|
|
|
+ height: calc(40vh - 98px);
|
|
|
+}
|
|
|
+::v-deep #title {
|
|
|
+ width: 100%;
|
|
|
+ height: 50px;
|
|
|
+ display: table;
|
|
|
+ text-align: center;
|
|
|
+ background-color: #3c8dbc;
|
|
|
+ p {
|
|
|
+ margin: auto;
|
|
|
+ display: table-cell;
|
|
|
+ vertical-align: middle;
|
|
|
+ text-align: center;
|
|
|
+ color: white;
|
|
|
+ font-family: SimHei, STHeiti;
|
|
|
+ font-size: 25px;
|
|
|
+ font-weight: bold;
|
|
|
+ letter-spacing: 5px;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+::v-deep .page-main {
|
|
|
+ position: absolute;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ top: 0;
|
|
|
+ bottom: 0;
|
|
|
+ overflow-y: auto;
|
|
|
+}
|
|
|
+
|
|
|
+::v-deep .left {
|
|
|
+ width: 20%;
|
|
|
+ height: 100%;
|
|
|
+ float: left;
|
|
|
+ background-color: #101c45;
|
|
|
+}
|
|
|
+
|
|
|
+::v-deep .right {
|
|
|
+ width: 20%;
|
|
|
+ height: 100%;
|
|
|
+ float: left;
|
|
|
+ background-color: #101c45;
|
|
|
+}
|
|
|
+
|
|
|
+::v-deep .map {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ height: calc(100vh - 84px);
|
|
|
+ float: left;
|
|
|
+}
|
|
|
+
|
|
|
+::v-deep .map-debugpanel {
|
|
|
+ background: rgba(135, 196, 240, 0.8);
|
|
|
+ width: 450px;
|
|
|
+ height: 120px;
|
|
|
+ border: 2px #fff solid;
|
|
|
+ padding: 10px;
|
|
|
+ color: #fff;
|
|
|
+}
|
|
|
+
|
|
|
+::v-deep .map-debugpanel input {
|
|
|
+ color: #bbb;
|
|
|
+}
|
|
|
+
|
|
|
+::v-deep .map-debugpanel a {
|
|
|
+ color: #fff;
|
|
|
+ float: right;
|
|
|
+ margin-right: 15px;
|
|
|
+}
|
|
|
+
|
|
|
+::v-deep .map-floorpanel {
|
|
|
+ background: rgb(52, 73, 94);
|
|
|
+ width: 40px;
|
|
|
+ height: 120px;
|
|
|
+ padding: 0px;
|
|
|
+ color: #fff;
|
|
|
+ border: 0px solid rgb(231, 234, 236) !important;
|
|
|
+}
|
|
|
+
|
|
|
+::v-deep .map-floorpanel tr {
|
|
|
+ text-align: center;
|
|
|
+ height: 30px;
|
|
|
+}
|
|
|
+
|
|
|
+::v-deep .map-floorpanel td {
|
|
|
+ text-align: center;
|
|
|
+ height: 30px;
|
|
|
+}
|
|
|
+
|
|
|
+::v-deep .map-floorpanel button {
|
|
|
+ width: 40px;
|
|
|
+ height: 30px;
|
|
|
+ border: none;
|
|
|
+ background: rgb(52, 73, 94);
|
|
|
+ color: #fff;
|
|
|
+}
|
|
|
+
|
|
|
+::v-deep .map-buildpanel {
|
|
|
+ background: rgb(52, 73, 94);
|
|
|
+ width: 40px;
|
|
|
+ height: 120px;
|
|
|
+ padding: 0px;
|
|
|
+ color: #fff;
|
|
|
+ border: 0px solid rgb(231, 234, 236) !important;
|
|
|
+}
|
|
|
+
|
|
|
+::v-deep .map-buildpanel tr {
|
|
|
+ text-align: center;
|
|
|
+ height: 30px;
|
|
|
+}
|
|
|
+
|
|
|
+::v-deep .map-buildpanel td {
|
|
|
+ text-align: center;
|
|
|
+ height: 30px;
|
|
|
+}
|
|
|
+
|
|
|
+::v-deep .map-buildpanel button {
|
|
|
+ width: 40px;
|
|
|
+ height: 30px;
|
|
|
+ border: none;
|
|
|
+ background: rgb(52, 73, 94);
|
|
|
+ color: #fff;
|
|
|
+ font-size: 14px;
|
|
|
+ cursor: pointer;
|
|
|
+}
|
|
|
+
|
|
|
+::v-deep .up-arrows {
|
|
|
+ width: 0;
|
|
|
+ height: 0;
|
|
|
+ border-bottom: 20px solid white;
|
|
|
+ border-left: 10px solid transparent;
|
|
|
+ border-right: 10px solid transparent;
|
|
|
+ position: absolute;
|
|
|
+ left: 50%;
|
|
|
+ transform: translate(-50%, -50%);
|
|
|
+}
|
|
|
+
|
|
|
+::v-deep .down-arrows {
|
|
|
+ width: 0;
|
|
|
+ height: 0;
|
|
|
+ border-top: 20px solid white;
|
|
|
+ border-left: 10px solid transparent;
|
|
|
+ border-right: 10px solid transparent;
|
|
|
+ position: absolute;
|
|
|
+ left: 50%;
|
|
|
+ transform: translate(-50%, -50%);
|
|
|
+}
|
|
|
+</style>
|