From 1706494087a9f8fd22f691d279e9ef7756cd316d Mon Sep 17 00:00:00 2001 From: ZZJ <zzjdsg2300@163.com> Date: 星期五, 03 十二月 2021 18:15:21 +0800 Subject: [PATCH] 地图 --- src/pages/internetEquipment/module/mapIndex.vue | 626 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 596 insertions(+), 30 deletions(-) diff --git a/src/pages/internetEquipment/module/mapIndex.vue b/src/pages/internetEquipment/module/mapIndex.vue index e295056..7bfe1f1 100644 --- a/src/pages/internetEquipment/module/mapIndex.vue +++ b/src/pages/internetEquipment/module/mapIndex.vue @@ -1,19 +1,102 @@ <template> <div id="map-index"> <div class="control"> - <div class="location icon iconfont" @click="location"></div> - <div class="zoom-in icon iconfont" @click="zoomIn"></div> - <div class="zoom-out icon iconfont" @click="zoomOut"></div> + <a href="#" title="瀹氫綅" @click="aClick()"> + <div class="location icon iconfont" @click="location"></div> + </a> + <a href="#" title="鏀惧ぇ" @click="aClick()"> + <div class="zoom-in icon iconfont" @click="zoomIn"></div> + </a> + + <a href="#" title="缂╁皬" @click="aClick()"> + <div class="zoom-out icon iconfont" @click="zoomOut"></div> + </a> </div> - <div class="range icon iconfont" @click="drawPolygon"></div> + <a href="#" title="鏂板/缂栬緫" @click="aClick()"> + <div class="range icon iconfont" @click="drawPolygon"></div> + </a> <el-input v-model="nodeId" placeholder="璇疯緭鍏ュ唴瀹�"></el-input> <div class="save" v-if="showBtn" @click="savePoly">淇濆瓨</div> + <div class="del" v-if="polygonInfo" @click="delPoly">鍒犻櫎</div> <div class="cancel" v-if="showBtn" @click="resetMap">鍙栨秷</div> + + <span id="polygonInfo" v-show="polygonInfo">{{ polygonInfo }}</span> + + <img + v-if="myNode && !isHidden" + src="/images/map/Group 594.png" + alt="" + class="video_icon" + @click="hiddenVideo()" + /> + <a v-else href="#" title="瀹炴椂鐩戞帶" @click="aClick()"> + <img + src="/images/map/鐩戞帶.png" + alt="" + class="video_icon" + @click="showVideo()" + /> + </a> + + <div class="video_box" v-if="myNode" :class="{ hidden: isHidden }"> + <div class="title"> + <div class="left"> + <span class="ball"></span> + <span class="left_info">瀹炴椂鐩戞帶</span> + </div> + + <div class="right">璁惧缂栫爜: {{ myNode.values_.id }}</div> + </div> + + <video controls="controls" loop="loop"> + <source src="/images/map/video_20210924_101628.mp4" type="video/mp4" /> + </video> + </div> + + <div class="helmet_box" v-show="myNode"> + <div class="icon_close iconfont" @click="close"></div> + <div class="sn" v-if="myNode">{{ myNode.values_.lat.id }}</div> + <div class="location" v-if="myNode">缁忓害: {{ myNode.values_.lat }}</div> + <div class="location" v-if="myNode">绾害: {{ myNode.values_.lng }}</div> + <div class="info" v-if="myNode">鐢甸噺: {{ myNode.values_.battery }}</div> + <div class="button"> + <img + src="/images/InternetData/瑙嗛.png" + alt="" + v-if="!isSending" + @click="sendVoice()" + /> + <img src="/images/InternetData/瑙嗛_鐐瑰嚮.png" alt="" v-if="isSending" /> + <img + src="/images/InternetData/璇煶.png" + alt="" + v-if="isTele == false" + @click="isTele = true" + /> + <img + src="/images/InternetData/璇煶_鐐瑰嚮.png" + alt="" + v-if="isTele == true" + @click="isTele = false" + /> + </div> + </div> + + <telephoneBox :tele="myNode" v-if="isTele" @close="isTele = false" /> + + <div class="mask" v-if="isTele"></div> </div> </template> <script> -import { getHelemtData, getZones, createZones } from "@/api/helemt"; +import { + getHelemtData, + getZones, + createZones, + delZones, + sendAudio, +} from "@/api/helemt"; +import telephoneBox from "../components/telephoneBox.vue"; import "ol/ol.css"; import Feature from "ol/Feature"; @@ -28,6 +111,9 @@ import Draw from "ol/interaction/Draw"; import { Modify, Snap } from "ol/interaction"; import Polygon from "ol/geom/Polygon"; +import Select from "ol/interaction/Select"; +import Overlay from "ol/Overlay"; +import { pointerMove } from "ol/events/condition"; let myMap = {}; let myVectorSource = {}; @@ -41,24 +127,20 @@ }); let myDraw = {}; let myModify = {}; +let myPolygon = {}; +let mySelect = {}; +let overlay = {}; +let overlay2 = {}; +let voiceText = ""; export default { - created() { - this.getNodeData(); - }, data() { return { + isSending: false, + isTele: false, + isHidden: false, showBtn: false, - nodeArr: [ - { data: [116.06157, 39.66157], id: 1, color: "缁�" }, - { data: [116.06247, 39.66247], id: 2, color: "缁�" }, - { data: [116.06337, 39.66337], id: 3, color: "缁�" }, - { data: [116.06467, 39.66437], id: 4, color: "缁�" }, - { data: [116.06517, 39.66517], id: 5, color: "绾�" }, - { data: [116.06627, 39.66627], id: 6, color: "绾�" }, - { data: [116.06787, 39.66787], id: 7, color: "绾�" }, - { data: [116.06897, 39.66897], id: 8, color: "绾�" }, - ], + nodeArr: [], nodeId: "", iconArr: [], rangeArr: [], @@ -68,14 +150,21 @@ polyFeature: [], drawStore: [], modifyStore: [], + polygonInfo: "", + nodeFeature: [], + myNode: null, + commentContent: "", }; }, mounted() { this.initMap(); }, + components: { + telephoneBox, + }, methods: { - async getNodeData() {}, async initMap() { + const that = this; // 鑾峰彇鑺傜偣 const res = await getHelemtData(); this.nodeArr = []; @@ -84,6 +173,7 @@ data: [item.lng, item.lat], id: item.device_sn, color: item.is_out_bound == 0 ? "缁�" : "绾�", + battery: item.battery, }); }); @@ -97,7 +187,6 @@ return obj; }); } - console.log(this.polygonArr); // 璁剧疆鍦板浘涓績 this.center = this.nodeArr[0].data; @@ -131,6 +220,114 @@ console.log(item); }) }) */ + + window.addEventListener("resize", function () { + map.updateSize(); + }); + + const select = new Select({ + filter: (feature, layer) => { + if (feature.values_ && feature.values_.type == "node") { + this.myNode = feature; + return true; + } else if (feature.type && feature.type == "polygon") { + myPolygon = feature; + this.myNode = null; + + return true; + } else { + this.myNode = null; + return false; + } + }, + style: (feature) => { + if (feature.values_ && feature.values_.type == "node") { + return new Style({ + image: new Icon({ + size: [32, 32], + src: `/images/map/瀹夊叏甯�-${feature.values_.color}.png`, + }), + zIndex: 1, + }); + } else if (feature.type && feature.type == "polygon") { + return new Style({ + fill: new Fill({ + color: "rgba(0, 0, 255, 0.1)", + }), + stroke: new Stroke({ + color: "skyblue", + width: 3, + }), + }); + } + }, + }); + + const select2 = new Select({ + condition: pointerMove, + filter: (feature, layer) => { + if (feature.values_ && feature.values_.type == "node") { + return true; + } else { + return false; + } + }, + style: (feature) => { + if (feature.values_ && feature.values_.type == "node") { + return new Style({ + image: new Icon({ + size: [32, 32], + src: `/images/map/瀹夊叏甯�-${feature.values_.color}.png`, + }), + zIndex: 1, + }); + } + }, + }); + + const info = document.querySelector("#polygonInfo"); + + map.addInteraction(select); + map.addInteraction(select2); + mySelect = select; + select.on("select", function (e) { + e.stopPropagation(); + overlay2.setPosition(undefined); + + if (e.selected.length == 0) { + that.polygonInfo = ""; + that.nodeId = ""; + that.myNode = null; + return false; + } + + if (e.selected[0].values_.type == "node") { + that.isHidden = false; + that.polygonInfo = ""; + that.nodeId = e.selected[0].values_.id; + return false; + } + + if (myPolygon.polygonName) { + that.polygonInfo = myPolygon.polygonName; + } else { + that.polygonInfo = "鏂板尯鍩�"; + } + overlay.setPosition(e.mapBrowserEvent.coordinate); + return false; + }); + + select2.on("select", function (e) { + if ( + e.selected.length && + e.selected[0].values_.type == "node" && + that.myNode && + that.myNode.values_.id == e.selected[0].values_.id + ) { + overlay2.setPosition(e.mapBrowserEvent.coordinate); + } else { + } + }); }, initNode([x, y], color) { const iconFeature = new Feature({ @@ -147,12 +344,19 @@ iconFeature.setStyle(iconStyle); this.iconArr.push(iconFeature); + iconFeature.set("color", `${color}`); + iconFeature.set("lat", `${x}`); + iconFeature.set("lng", `${y}`); + return iconFeature; }, initAllNode() { this.nodeArr.forEach((item) => { const node = this.initNode(item.data, item.color); node.set("id", item.id); + node.set("type", "node"); + node.set("battery", item.battery); + this.nodeFeature.push(node); myVectorSource.addFeature(node); }); }, @@ -161,6 +365,8 @@ this.polygonArr.forEach((item) => { const feature = new Feature({ geometry: new Polygon([item.data]) }); feature.id = item.id; + feature.type = "polygon"; + feature.polygonName = item.name; this.polyFeature.push(feature); }); }, @@ -179,6 +385,19 @@ }); }, initBottomMap(vectorLayer) { + const info = document.querySelector("#polygonInfo"); + const helmet_box = document.querySelector(".helmet_box"); + overlay2 = new Overlay({ + element: helmet_box, + autoPan: true, + autoPanAnimation: { + duration: 250, + }, + }); + + overlay = new Overlay({ + element: info, + }); return new Map({ target: "map-index", layers: [baseLayer, vectorLayer], @@ -186,6 +405,7 @@ center: transform(this.center, "EPSG:4326", "EPSG:3857"), zoom: this.zoom, }), + overlays: [overlay, overlay2], }); }, zoomIn() { @@ -204,6 +424,8 @@ view.setCenter(transform(this.center, "EPSG:4326", "EPSG:3857")); }, drawPolygon() { + this.resetMap(); + mySelect.setActive(false); this.showBtn = true; const draw = new Draw({ source: myVectorSource, @@ -232,6 +454,7 @@ } event.feature.id = id; + event.feature.type = "polygon"; this.drawStore.push({ id, data: event.feature.getGeometry().getCoordinates()[0], @@ -240,7 +463,6 @@ const modify = new Modify({ source: myVectorSource }); modify.addEventListener("modifyend", (event) => { - console.log(event.features); const id = event.features.array_[0].id; const data = event.features.array_[0].getGeometry().getCoordinates()[0]; this.modifyStore.push({ id, data }); @@ -250,14 +472,14 @@ myMap.addInteraction(draw); }, resetMap() { + this.polygonInfo = ""; + mySelect.setActive(true); this.initPolygonArr(); - console.log(this.polyFeature); const vectorSource = new VectorSource({ features: this.polyFeature, }); /* if(this.polygonArr.length>0){ this.initPolygonArr() - console.log(this.polyFeature); vectorSource.addFeature(this.polyFeature[0]) } */ myVectorSource = vectorSource; @@ -272,6 +494,7 @@ this.modifyStore = []; }, async savePoly() { + mySelect.setActive(true); myMap.removeInteraction(myDraw); myMap.removeInteraction(myModify); this.showBtn = false; @@ -291,7 +514,6 @@ } const arrData = this.polygonArr.map((item) => { let name = item.name ? item.name : ""; - console.log(item); let data = item.data.map((arr) => { arr = transform([arr[0], arr[1]], "EPSG:3857", "EPSG:4326"); return arr.join(","); @@ -303,8 +525,181 @@ id: +item.id, }; }); - const res = await createZones({ dots_arr: arrData }); - console.log(res); + await createZones({ dots_arr: arrData }); + const res = await getHelemtData(); + this.nodeArr = []; + res.data.items.forEach((item) => { + this.nodeArr.push({ + data: [item.lng, item.lat], + id: item.device_sn, + color: item.is_out_bound == 0 ? "缁�" : "绾�", + }); + }); + this.nodeFeature.forEach((item) => { + myVectorSource.removeFeature(item); + }); + this.initNode(); + this.initAllNode(); + }, + delPoly() { + this.$confirm("姝ゆ搷浣滃皢鍒犻櫎璇ュ尯鍩�, 鏄惁缁х画?", "鎻愮ず", { + confirmButtonText: "纭畾", + cancelButtonText: "鍙栨秷", + type: "warning", + }) + .then(async () => { + myVectorSource.removeFeature(myPolygon); + const res = await delZones({ id: myPolygon.id }); + if (res.status == 200) { + this.$message({ + type: "success", + message: "鍒犻櫎鎴愬姛!", + }); + this.polygonInfo = ""; + const res2 = await getZones(); + if (res2.data && res2.data.items && res2.data.items.length > 0) { + this.polygonArr = res2.data.items.map((obj) => { + obj.data = obj.dots.map((item) => { + return transform( + [item[0], item[1]], + "EPSG:4326", + "EPSG:3857" + ); + }); + return obj; + }); + } + } else { + this.$message({ + type: "info", + message: "鍒犻櫎澶辫触", + }); + } + }) + .catch(() => { + this.$message({ + type: "info", + message: "宸插彇娑堝垹闄�", + }); + }); + }, + showVideo() { + if (!this.myNode) { + return false; + } + + this.isHidden = false; + }, + hiddenVideo() { + document.querySelector("video").pause(); + this.isHidden = true; + }, + close() { + overlay2.setPosition(undefined); + }, + onCommentInputChange() { + let value = document.querySelector("#commentContent").value; + voiceText = value; + let cont = 20 - value.length; + document.querySelector( + "#comment_info" + ).innerHTML = `杩樺彲杈撳叆${cont}涓瓧绗; + }, + sendVoice() { + const _this = this; + this.isSending = true; + + const h = this.$createElement; + this.$msgbox({ + message: h( + "div", + { + attrs: { + class: "el-textarea", + }, + }, + [ + h( + "div", + { + attrs: { + class: "el-title", + }, + }, + [ + h( + "span", + { + attrs: { + class: "icon iconfont", + }, + }, + "\ue7cc" + ), + h("span", null, "鍙戦�佽闊�"), + ] + ), + h("textarea", { + attrs: { + placeholder: "璇疯緭鍏ヨ闊冲懡浠�", + maxlength: "20", + class: "el-textarea__inner", + autocomplete: "off", + rows: 3, + id: "commentContent", + }, + value: this.commentContent, + on: { input: this.onCommentInputChange }, + }), + h( + "div", + { attrs: { class: "info", id: "comment_info" } }, + "杩樺彲杈撳叆20涓瓧绗�" + ), + ] + ), + showCancelButton: true, + confirmButtonText: "纭畾", + confirmButtonClass: "hele_btn_save", + cancelButtonClass: "hele_btn_cancel", + cancelButtonText: "鍙栨秷", + beforeClose: (action, instance, done) => { + document.querySelector("#commentContent").value = ""; + document.querySelector( + "#comment_info" + ).innerHTML = `杩樺彲杈撳叆20涓瓧绗; + _this.isSending = false; + done(); + }, + }) + .then((action) => { + if (action == "confirm") { + if (!voiceText) { + this.$message({ + message: "鎸囦护涓嶈兘涓虹┖", + type: "warning", + }); + _this.isSending = false; + return; + } + sendAudio(_this.myNode.values_.id, voiceText).then((res) => { + this.$message({ + message: "鎸囦护鍙戦�佹垚鍔�", + type: "success", + }); + _this.isSending = false; + }); + _this.isSending = false; + } else { + _this.isSending = false; + } + }) + .catch(() => { + _this.isSending = false; + }); + }, + aClick() { + return false; }, }, watch: { @@ -326,14 +721,12 @@ if (res.data.items && res.data.items.length > 0) { res.data.items.forEach((obj) => { this.nodeArr.forEach((item) => { - if ((item.id = obj.device_sn)) { + if (item.id == obj.device_sn) { arr.push(item); } }); }); } - - console.log(this.rangeArr); if (this.rangeArr.length > 0) { this.rangeArr.forEach((item) => { @@ -362,6 +755,7 @@ rangeFeature.setStyle(iconStyle); myVectorSource.addFeature(rangeFeature); + rangeFeature.set("type", "range"); this.rangeArr.push(rangeFeature); }); } @@ -372,12 +766,106 @@ </script> <style scoped lang="scss"> +a { + background-color: transparent; + color: #337ab7; + text-decoration: none; +} +a:active a:hover { + outline: 0; +} + #map-index { position: relative; margin: 20px 0; - width: 1170px; + width: 100%; height: 396px; border-radius: 15px; + + .helmet_box { + width: 205px; + height: 172px; + padding: 10px 10px 20px 15px; + font-size: 12px; + background: rgba(255, 255, 255, 0.7); + backdrop-filter: blur(4px); + border-radius: 15px; + text-align: left; + + .icon_close { + text-align: right; + cursor: pointer; + } + + .sn { + color: #f54336; + } + .location { + margin: 10px 0; + } + .button { + margin-top: 10px; + text-align: center; + img { + cursor: pointer; + width: 22px; + &:first-child { + margin-right: 48px; + } + } + } + } + + .video_box { + box-sizing: border-box; + overflow: hidden; + position: absolute; + z-index: 2; + top: 45px; + right: 25px; + width: 483px; + height: 306px; + background: rgba(241, 250, 246, 0.6); + backdrop-filter: blur(4px); + /* Note: backdrop-filter has minimal browser support */ + border-radius: 15px; + border: 1px solid rgb(17, 170, 102); + transition: all linear 0.5s; + + &.hidden { + width: 0; + border: none; + } + + .title { + margin: 15px 40px 0 20px; + width: 420px; + display: flex; + justify-content: space-between; + align-items: center; + color: #4f4f4f; + font-size: 12px; + + .left { + .ball { + display: inline-block; + width: 0; + height: 0; + border: 4px solid #f54336; + border-radius: 2px; + margin-right: 10px; + } + } + } + + video { + margin: 8px 40px 0 20px; + width: 424px; + height: 246px; + object-fit: fill; + } + } + .control { position: absolute; display: flex; @@ -464,6 +952,84 @@ line-height: 36px; cursor: pointer; } + + .del { + position: absolute; + z-index: 3; + top: 15px; + right: 113px; + width: 87px; + height: 35px; + background: rgb(245, 108, 108); + border: 1px solid rgb(245, 108, 108); + border-radius: 8px; + color: #fff; + font-size: 12px; + line-height: 36px; + cursor: pointer; + } + + .video_icon { + position: absolute; + z-index: 3; + top: 179px; + right: 10px; + width: 37px; + } + + #polygonInfo { + padding: 10px; + border: 1px solid; + color: black; + background-color: #fff; + z-index: 3; + width: 100px; + } + + .mask { + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; + text-align: center; + z-index: 4; + background-color: black; + opacity: 0.5; + } +} + +.el-textarea { + height: 150px; + padding: 0 15px; + + .el-title { + margin-top: 20px; + margin-bottom: 15px; + color: #4f4f4f; + font-size: 16px; + font-weight: 700; + + .icon { + font-weight: normal; + font-size: 19px; + } + } + + .el-textarea__inner { + width: 357px; + + &:focus { + border: 1px solid #11aa66; + } + } + + .info { + font-size: 12px; + color: #828282; + text-align: right; + padding-right: 38px; + } } </style> -- Gitblit v1.8.0