From 909d08a9d9ac07fc467ed49bd53bac9302490b9f Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: 星期五, 22 四月 2022 16:22:34 +0800 Subject: [PATCH] Merge pull request #446 from 648540858/map --- web_src/src/components/devicePosition.vue | 680 +++++++++++++++++++++++++++----------------------------- 1 files changed, 325 insertions(+), 355 deletions(-) diff --git a/web_src/src/components/devicePosition.vue b/web_src/src/components/devicePosition.vue index 0ffd5fa..cc74dc1 100644 --- a/web_src/src/components/devicePosition.vue +++ b/web_src/src/components/devicePosition.vue @@ -1,383 +1,353 @@ <template> - <div id="devicePosition" style="height: 100%"> - <div style="background-color: #ffffff; position: relative; padding: 1rem 0.5rem 0.5rem 0.5rem; text-align: center;"> - <span style="font-size: 1rem; font-weight: 500">璁惧瀹氫綅 ({{ parentChannelId == 0 ? deviceId : parentChannelId }})</span> + <div id="devicePosition" style="width: 100vw; height: 91vh;"> + <el-container style="height: 91vh;" v-loading="isLoging"> + <el-aside width="auto" style="background-color: #ffffff"> + <DeviceTree ref="deviceTree" :clickEvent="clickEvent" :contextMenuEvent="contextmenuEventHandler" ></DeviceTree> + </el-aside> + <el-main style="height: 91vh; padding: 0"> + <MapComponent ref="map"></MapComponent> + </el-main> + </el-container> + <div ref="infobox" v-if="channel != null " > + <div v-if="channel != null" class="infobox-content"> + <el-descriptions class="margin-top" :title="channel.name" :column="1" :colon="true" size="mini" :labelStyle="labelStyle" > + <el-descriptions-item label="鐢熶骇鍘傚晢">{{channel.manufacture}}</el-descriptions-item> + <el-descriptions-item label="鍨嬪彿">{{channel.model}}</el-descriptions-item> + <el-descriptions-item label="璁惧褰掑睘" >{{channel.owner}}</el-descriptions-item> + <el-descriptions-item label="琛屾斂鍖哄煙" >{{channel.civilCode}}</el-descriptions-item> + <el-descriptions-item label="瀹夎鍦板潃" >{{channel.address == null?'鏈煡': channel.address}}</el-descriptions-item> + <el-descriptions-item label="浜戝彴绫诲瀷" >{{channel.ptztypeText}}</el-descriptions-item> + <el-descriptions-item label="缁忕含搴�" >{{channel.longitude}},{{channel.latitude}}</el-descriptions-item> + <el-descriptions-item label="鐘舵��"> + <el-tag size="small" v-if="channel.status === 1">鍦ㄧ嚎</el-tag> + <el-tag size="small" type="info" v-if="channel.status === 0">绂荤嚎</el-tag> + </el-descriptions-item> + </el-descriptions> + <div style="padding-top: 10px"> + <el-button type="primary" size="small" title="鎾斁" icon="el-icon-video-play" @click="play(channel)"></el-button> + <el-button type="primary" size="small" title="缂栬緫浣嶇疆" icon="el-icon-edit" @click="edit(channel)"></el-button> + <el-button type="primary" size="small" title="杞ㄨ抗鏌ヨ" icon="el-icon-map-location" @click="getTrace(channel)"></el-button> + </div> + <span class="infobox-close el-icon-close" @click="closeInfoBox()"></span> + </div> </div> - <div style="background-color: #ffffff; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left; font-size: 14px;"> - <el-button icon="el-icon-arrow-left" size="mini" style="margin-right: 1rem" type="primary" @click="showDevice">杩斿洖</el-button> - <!-- <span class="demonstration">浠�</span> --> - <el-date-picker v-model="searchFrom" type="datetime" placeholder="閫夋嫨寮�濮嬫棩鏈熸椂闂�" default-time="00:00:00" size="mini" style="width: 11rem;" align="right" :picker-options="pickerOptions"></el-date-picker> - <el-date-picker v-model="searchTo" type="datetime" placeholder="閫夋嫨缁撴潫鏃ユ湡鏃堕棿" default-time="00:00:00" size="mini" style="width: 11rem;" align="right" :picker-options="pickerOptions"></el-date-picker> - <el-button-group> - <el-button icon="el-icon-search" size="mini" type="primary" @click="showHistoryPath">鍘嗗彶杞ㄨ抗</el-button> - <el-button icon="el-icon-search" size="mini" style="margin-right: 1rem" type="primary" @click="showLatestPosition">鏈�鏂颁綅缃�</el-button> - </el-button-group> - <el-tag style="width: 5rem; text-align: center" size="medium">杩囨湡鏃堕棿</el-tag> - <el-input-number size="mini" v-model="expired" :min="300" :controls="false" style="width: 4rem;"></el-input-number> - <el-tag style="width: 5rem; text-align: center" size="medium">涓婃姤鍛ㄦ湡</el-tag> - <el-input-number size="mini" v-model="interval" :min="1" :controls="false" style="width: 4rem;"></el-input-number> - <el-button-group> - <el-button icon="el-icon-search" size="mini" type="primary" @click="subscribeMobilePosition">浣嶇疆璁㈤槄</el-button> - <el-button icon="el-icon-search" size="mini" type="primary" @click="unSubscribeMobilePosition">鍙栨秷璁㈤槄</el-button> - </el-button-group> - <el-checkbox size="mini" style="margin-right: 1rem; float: right" v-model="autoList" @change="autoListChange" >鑷姩鍒锋柊</el-checkbox> - </div> - <div class="mapContainer" style="background-color: #ffffff; position: relative; padding: 1rem 0.5rem 0.5rem 0.5rem; text-align: center; height: calc(100% - 10rem);"> - <div class="baidumap" id="allmap"></div> - </div> + <devicePlayer ref="devicePlayer" ></devicePlayer> + <queryTrace ref="queryTrace" ></queryTrace> </div> </template> <script> -import uiHeader from "../layout/UiHeader.vue"; -import geoTools from "./GeoConvertTools.js"; +import MapComponent from "./common/MapComponent.vue"; +import DeviceService from "./service/DeviceService"; +import DeviceTree from "./common/DeviceTree"; +import channelMapInfobox from "./dialog/channelMapInfobox"; +import devicePlayer from './dialog/devicePlayer.vue' +import queryTrace from './dialog/queryTrace.vue' + export default { - name: "devicePosition", - components: { - uiHeader, - }, - data() { - return { - pickerOptions: { - shortcuts: [{ - text: '浠婂ぉ', - onClick(picker) { - picker.$emit('pick', new Date()); - } - }, { - text: '鏄ㄥぉ', - onClick(picker) { - const date = new Date(); - date.setTime(date.getTime() - 3600 * 1000 * 24); - picker.$emit('pick', date); - } - }, { - text: '涓�鍛ㄥ墠', - onClick(picker) { - const date = new Date(); - date.setTime(date.getTime() - 3600 * 1000 * 24 * 7); - picker.$emit('pick', date); - } - }] + name: "devicePosition", + components: { + MapComponent, + DeviceTree, + channelMapInfobox, + devicePlayer, + queryTrace, + }, + data() { + return { + deviceService: new DeviceService(), + layer: null, + lineLayer: null, + channel: null, + infoBoxId: null, + labelStyle: { + width: "56px" + }, + isLoging: false, + }; + }, + created() { + if (this.$route.query.deviceId) { + console.log(this.$route.query.deviceId) + // this.$refs.deviceTree.openByDeivceId(this.$route.query.deivceId) + setTimeout(()=>{ // 寤惰繜浠ョ瓑寰呭湴鍥惧姞杞藉畬鎴� TODO 鍚庣画淇敼涓洪�氳繃鏄疄闄呰繖锛涚姸鎬佸姞鍥炶皟瀹屾垚 + this.deviceService.getAllChannel(false, this.$route.query.deviceId, this.channelsHandler) + }, 1000) + + } + }, + destroyed() { + + }, + methods: { + clickEvent: function (data) { + if (data.channelId && data.subCount == 0) { + // 鐐瑰嚮閫氶亾 + if (data.longitude * data.latitude === 0) { + this.$message.error('鏈幏鍙栧埌浣嶇疆淇℃伅'); + } else { + if (this.layer != null) { + this.$refs.map.removeLayer(this.layer); + } + this.closeInfoBox() + this.layer = this.$refs.map.addLayer([{ + position: [data.longitude, data.latitude], + image: { + src: this.getImageByChannel(data), + anchor: [0.5, 1] }, - deviceId: this.$route.params.deviceId, - showHistoryPosition: false, //鏄剧ず鍘嗗彶杞ㄨ抗 - startTime: null, - endTime: null, - searchFrom: null, - searchTo: null, - expired: 600, - interval: 5, - mobilePositionList: [], - mapPointList: [], - parentChannelId: this.$route.params.parentChannelId, - updateLooper: 0, //鏁版嵁鍒锋柊杞鏍囧織 - total: 0, - beforeUrl: "/deviceList", - isLoging: false, - autoList: false, - }; - }, - mounted() { - this.initData(); - this.initBaiduMap(); - if (this.autoList) { - this.updateLooper = setInterval(this.initData, 5000); + data: data + }], this.featureClickEvent) + this.$refs.map.panTo([data.longitude, data.latitude], mapParam.maxZoom) } + } }, - destroyed() { - // this.$destroy("videojs"); - clearTimeout(this.updateLooper); + contextmenuEventHandler: function (event, data) { + if (data.channelId && data.subCount == 0) { + // 鐐瑰嚮閫氶亾 + this.$contextmenu({ + items: [ + { + label: "鎾斁", + icon: "el-icon-video-play", + disabled: false, + onClick: () => { + this.play(data); + } + }, + { + label: "缂栬緫浣嶇疆", + icon: "el-icon-edit", + disabled: false, + onClick: () => { + this.edit(data) + } + }, + { + label: "杞ㄨ抗鏌ヨ", + icon: "el-icon-map-location", + disabled: false, + onClick: () => { + this.getTrace(data) + } + } + ], + event, // 榧犳爣浜嬩欢淇℃伅 + customClass: "custom-class", // 鑷畾涔夎彍鍗� class + zIndex: 3000, // 鑿滃崟鏍峰紡 z-index + }); + } else { + this.deviceOrSubChannelMenu(event, data) + } + }, - methods: { - initData: function () { - // if (this.parentChannelId == "" || this.parentChannelId == 0) { - // this.getDeviceChannelList(); - // } else { - // this.showSubchannels(); - // } - }, - initParam: function () { - // this.deviceId = this.$route.params.deviceId; - // this.parentChannelId = this.$route.params.parentChannelId; - // this.currentPage = parseInt(this.$route.params.page); - // this.count = parseInt(this.$route.params.count); - // if (this.parentChannelId == "" || this.parentChannelId == 0) { - // this.beforeUrl = "/deviceList"; - // } - }, - initBaiduMap() { - this.map = new BMap.Map("allmap"); // 鍒涘缓鍦板浘瀹炰緥 - let points = []; - let point = new BMap.Point(116.231398, 39.567445); // 鍒涘缓鐐瑰潗鏍� - this.map.centerAndZoom(point, 5); // 鍒濆鍖栧湴鍥撅紝璁剧疆涓績鐐瑰潗鏍囧拰鍦板浘绾у埆 - this.map.enableScrollWheelZoom(true); //寮�鍚紶鏍囨粴杞缉鏀� - this.map.addControl(new BMap.NavigationControl()); - this.map.addControl(new BMap.ScaleControl()); - this.map.addControl(new BMap.OverviewMapControl()); - this.map.addControl(new BMap.MapTypeControl()); - //map.setMapStyle({ style: 'midnight' }) //鍦板浘椋庢牸 - }, - currentChange: function (val) { - // var url = `/${this.$router.currentRoute.name}/${this.deviceId}/${this.parentChannelId}/${this.count}/${val}`; - // console.log(url); - // this.$router.push(url).then(() => { - // this.initParam(); - // this.initData(); - // }); - }, - handleSizeChange: function (val) { - // var url = `/${this.$router.currentRoute.name}/${this.$router.params.deviceId}/${this.$router.params.parentChannelId}/${val}/1`; - // this.$router.push(url).then(() => { - // this.initParam(); - // this.initData(); - // }); - }, - showDevice: function () { - this.$router.push(this.beforeUrl).then(() => { - this.initParam(); - this.initData(); - }); - }, - autoListChange: function () { - if (this.autoList) { - this.updateLooper = setInterval(this.initData, 1500); - } else { - window.clearInterval(this.updateLooper); + deviceOrSubChannelMenu: function (event, data) { + // 鐐瑰嚮璁惧 + this.$contextmenu({ + items: [ + { + label: "瀹氫綅", + icon: "el-icon-s-promotion", + disabled: false, + onClick: () => { + if (!data.channelId) { + this.deviceService.getAllChannel(false, data.deviceId, this.channelsHandler) + } + if (data.channelId && data.subCount > 0) { + // 鐐瑰嚮瀛愮洰褰� + this.deviceService.getAllSubChannel(false, data.deviceId, data.channelId, this.channelsHandler) + } } - }, - showHistoryPath: function () { - this.map.clearOverlays(); - this.mapPointList = []; - this.mobilePositionList = []; - if (!!this.searchFrom) { - this.startTime = this.toGBString(this.searchFrom); - console.log(this.startTime); - } else{ - this.startTime = null; - } - if (!!this.searchTo) { - this.endTime = this.toGBString(this.searchTo); - console.log(this.endTime); - } else { - this.endTime = null; - } - let self = this; - this.$axios({ - method: 'get', - url:`/api/position/history/${this.deviceId}`, - params: { - start: self.startTime, - end: self.endTime, - }, - }).then(function (res) { - self.total = res.data.length; - self.mobilePositionList = res.data; - console.log(self.mobilePositionList); - if (self.total == 0) { - self.$message({ - showClose: true, - message: '鏈壘鍒扮鍚堟潯浠剁殑绉诲姩浣嶇疆淇℃伅', - type: 'error' - }); - } else { - self.$nextTick(() => { - self.showMarkPoints(self); - }); - } - }).catch(function (error) { - console.log(error); - }); - }, - showLatestPosition: function() { - this.map.clearOverlays(); - this.mapPointList = []; - this.mobilePositionList = []; - let self = this; - this.$axios({ - method: 'get', - url:`/api/position/latest/${this.deviceId}` - }).then(function (res) { - console.log(res.data); - self.total = res.data.length; - self.mobilePositionList.push(res.data); - console.log(self.mobilePositionList); - if (self.total == 0) { - self.$message({ - showClose: true, - message: '鏈壘鍒扮鍚堟潯浠剁殑绉诲姩浣嶇疆淇℃伅', - type: 'error' - }); - } else { - self.$nextTick(() => { - self.showMarkPoints(self); - }); - } - }).catch(function (error) { - console.log(error); - }); - }, - subscribeMobilePosition: function() { - let self = this; - this.$axios({ - method: 'get', - url:`/api/position/subscribe/${this.deviceId}`, - params: { - expires: self.expired, - interval: self.interval, - }, - }).then(function (res) { - console.log(res.data); - }) - .catch(function (error) { - console.log(error); - }); - }, - unSubscribeMobilePosition: function() { - let self = this; - this.$axios({ - method: 'get', - url:`/api/position/subscribe/${this.deviceId}`, - params: { - expires: 0, - interval: self.interval, - }, - }) - .then(function (res) { - console.log(res.data); - }).catch(function (error) { - console.log(error); - }); - }, - toGBString: function (dateTime) { - return ( - dateTime.getFullYear() + - "-" + this.twoDigits(dateTime.getMonth() + 1) + - "-" + this.twoDigits(dateTime.getDate()) + - "T" + this.twoDigits(dateTime.getHours()) + - ":" + this.twoDigits(dateTime.getMinutes()) + - ":" + this.twoDigits(dateTime.getSeconds()) - ); - }, - twoDigits: function (num) { - if (num < 10) { - return "0" + num; - } else { - return "" + num; - } - }, - showMarkPoints: function(self) { - let that = self; - let npointJ = null; - let npointW = null; - let point = null; - for (let i = 0; i < self.mobilePositionList.length; i++) { - if (self.mobilePositionList[i].geodeticSystem == "BD-09") { - npointJ = self.mobilePositionList[i].cnLng; - npointW = self.mobilePositionList[i].cnLat; - point = new BMap.Point(npointJ, npointW); - } else { - npointJ = self.mobilePositionList[i].longitude; - npointW = self.mobilePositionList[i].latitude; - let bd2 = geoTools.GPSToBaidu(npointJ, npointW); - point = new BMap.Point(bd2.lat, bd2.lng); - } - self.mapPointList.push(point); - let marker = new BMap.Marker(point); // 鍒涘缓鏍囨敞 - self.map.addOverlay(marker); // 灏嗘爣娉ㄦ坊鍔犲埌鍦板浘涓� - //鎻愮ず淇℃伅 鍙互瑙f瀽 HTML鏍囩浠ュ強CSS - let infoWindow = new BMap.InfoWindow(`<p style='text-align:left;font-weight:800'>璁惧: ${self.mobilePositionList[i].deviceId}</p> - <p style='text-align:left;font-weight:0'>鏃堕棿: ${self.mobilePositionList[i].time}</p>`); - // 榧犳爣绉讳笂鏍囨敞鐐硅鍙戠敓鐨勪簨 - marker.addEventListener("mouseover", function () { - this.openInfoWindow(infoWindow); - }); - // 榧犳爣绉诲紑鏍囨敞鐐硅鍙戠敓鐨勪簨 - marker.addEventListener("mouseout", function () { - this.closeInfoWindow(infoWindow); - }); - // 榧犳爣鐐瑰嚮鏍囨敞鐐硅鍙戠敓鐨勪簨鎯� - marker.addEventListener("click", function () { - alert("鐐瑰嚮"); - }); - } - let view = that.map.getViewport(eval(self.mapPointList)); - that.map.centerAndZoom(view.center, view.zoom); - }, + } + ], + event, // 榧犳爣浜嬩欢淇℃伅 + customClass: "custom-class", // 鑷畾涔夎彍鍗� class + zIndex: 3000, // 鑿滃崟鏍峰紡 z-index + }); + }, + channelsHandler: function (channels) { + console.log(2) + if (channels.length > 0) { + this.clean() + this.closeInfoBox() + let params = []; + for (let i = 0; i < channels.length; i++) { + if (channels[i].longitude * channels[i].latitude === 0) { + continue; + } + let item = { + position: [channels[i].longitude, channels[i].latitude], + image: { + src: this.getImageByChannel(channels[i]), + anchor: [0.5, 1] + }, + data: channels[i] + } + params.push(item); + } + console.log(3) + + this.layer = this.$refs.map.addLayer(params, this.featureClickEvent) + console.log(4) + if (params.length === 1) { + this.$refs.map.panTo([channels[0].longitude, channels[0].latitude], mapParam.maxZoom) + } else if (params.length > 1) { + this.$refs.map.fit(this.layer) + } else { + this.$message.error('鏈幏鍙栧埌浣嶇疆淇℃伅'); + } + } else { + this.$message.error('鏈幏鍙栧埌浣嶇疆淇℃伅'); + } + }, + getImageByChannel: function (channel) { + let src = "static/images/gis/camera.png" + switch (channel.ptztype) { + case 1: + if (channel.status === 1) { + src = "static/images/gis/camera1.png" + } else { + src = "static/images/gis/camera1-offline.png" + } + break; + case 2: + if (channel.status === 1) { + src = "static/images/gis/camera2.png" + } else { + src = "static/images/gis/camera2-offline.png" + } + break; + case 3: + if (channel.status === 1) { + src = "static/images/gis/camera3.png" + } else { + src = "static/images/gis/camera3-offline.png" + } + break; + default: + if (channel.status === 1) { + src = "static/images/gis/camera.png" + } else { + src = "static/images/gis/camera-offline.png" + } + } + return src; + }, + featureClickEvent: function (channels) { + this.closeInfoBox() + if (channels.length > 0) { + this.channel = channels[0] + } + this.$nextTick(() => { + this.infoBoxId = this.$refs.map.openInfoBox([this.channel.longitude, this.channel.latitude], this.$refs.infobox, [0, -50]) + }) + }, + closeInfoBox: function () { + if (this.infoBoxId != null) { + this.$refs.map.closeInfoBox(this.infoBoxId) + } + }, + play: function (channel) { + + let deviceId = channel.deviceId; + this.isLoging = true; + let channelId = channel.channelId; + console.log("閫氱煡璁惧鎺ㄦ祦1锛�" + deviceId + " : " + channelId); + let that = this; + this.$axios({ + method: 'get', + url: '/api/play/start/' + deviceId + '/' + channelId + }).then(function (res) { + that.isLoging = false; + if (res.data.code === 0) { + + that.$refs.devicePlayer.openDialog("media", deviceId, channelId, { + streamInfo: res.data.data, + hasAudio: channel.hasAudio + }); + + } else { + that.$message.error(res.data.msg); + } + }).catch(function (e) { + }); + }, + edit: function (data) { + this.$message.warning('鏆備笉鏀寔'); + }, + getTrace: function (data) { + // this.$message.warning('鏆備笉鏀寔'); + this.clean() + this.$refs.queryTrace.openDialog(data, (channelPositions) => { + console.log("getTrace") + console.log(channelPositions) + if (channelPositions.length === 0) { + this.$message.success('鏈煡璇㈠埌杞ㄨ抗淇℃伅'); + } else { + let positions = []; + for (let i = 0; i < channelPositions.length; i++) { + if (channelPositions[i].cnLng * channelPositions[i].cnLat > 0) { + positions.push([channelPositions[i].cnLng, channelPositions[i].cnLat]) + } + + } + if (positions.length === 0) { + this.$message.success('鏈煡璇㈠埌杞ㄨ抗淇℃伅'); + return; + } + this.lineLayer = this.$refs.map.addLineLayer(positions) + this.$refs.map.fit(this.lineLayer) + } + }) + }, + clean: function (){ + if (this.lineLayer != null) { + this.$refs.map.removeLayer(this.lineLayer) + } + if (this.infoBoxId != null) { + this.$refs.map.closeInfoBox(this.infoBoxId) + } + if (this.layer != null) { + this.$refs.map.removeLayer(this.layer) + } + } + }, + }; </script> <style> -.videoList { - display: flex; - flex-wrap: wrap; - align-content: flex-start; +.infobox-content{ + width: 260px; + background-color: #FFFFFF; + padding: 10px; + border-radius: 10px; + border: 1px solid #e2e2e2; } -.video-item { - position: relative; - width: 15rem; - height: 10rem; - margin-right: 1rem; - background-color: #000000; -} - -.video-item-img { +.infobox-content::after { position: absolute; - top: 0; - bottom: 0; - left: 0; - right: 0; - margin: auto; - width: 100%; - height: 100%; -} - -.video-item-img:after { + bottom: -11px; + left: 130px; + display: block; content: ""; - display: inline-block; - position: absolute; - z-index: 2; - top: 0; - bottom: 0; - left: 0; - right: 0; - margin: auto; - width: 3rem; - height: 3rem; - background-image: url("../assets/loading.png"); - background-size: cover; - background-color: #000000; + width: 16px; + height: 16px; + background: url('~@static/images/arrow.png') no-repeat center; } - -.video-item-title { +.infobox-close { position: absolute; - bottom: 0; + right: 1rem; + top: 1rem; color: #000000; - background-color: #ffffff; - line-height: 1.5rem; - padding: 0.3rem; - width: 14.4rem; + cursor:pointer } - -.baidumap { +.el-descriptions__title { + font-size: 1rem; + font-weight: 700; + padding: 20px 20px 0px 23px; + text-align: center; width: 100%; - height: 100%; - border: none; - position: absolute; - left: 0; - top: 0; - right: 0; - bottom: 0; - margin: auto; -} - -/* 鍘婚櫎鐧惧害鍦板浘鐗堟潈閭h瀛� 鍜� 鐧惧害logo */ -.baidumap > .BMap_cpyCtrl { - display: none !important; -} -.baidumap > .anchorBL { - display: none !important; } </style> -- Gitblit v1.8.0