ZZJ
2022-01-26 1e09a7a01a6c1888e1a2a832eb007fb8c2b653a0
src/pages/internetEquipment/module/mapIndex.vue
@@ -1,21 +1,1129 @@
<template>
  <div class="map-index">
  <div id="map-index">
    <div class="control">
      <a href="#" title="定位" @click="aClick()">
        <div class="location icon iconfont" @click="location">&#xe74e;</div>
      </a>
      <a href="#" title="放大" @click="aClick()">
        <div class="zoom-in icon iconfont" @click="zoomIn">&#xeb89;</div>
      </a>
      <a href="#" title="缩小" @click="aClick()">
        <div class="zoom-out icon iconfont" @click="zoomOut">&#xe758;</div>
      </a>
    </div>
    <a href="#" title="新增/编辑" @click="aClick()">
      <div class="range icon iconfont" @click="drawPolygon">&#xe773;</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-if="myNode && isHidden" href="#" title="实时监控" @click="aClick()">
      <img
        src="/images/map/监控.png"
        alt=""
        class="video_icon"
        @click="showVideo()"
      />
    </a>
    <div class="video_box" v-show="myNode" :class="{ hidden: isHidden }">
      <div class="title">
        <div class="left">
          <span class="ball"></span>
          <span class="left_info">实时监控</span>
        </div>
        <div class="right">
          设备编码: {{ myNode && myNode.values && 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="myNodeHover">
      <div class="icon_close iconfont" @click="close">&#xe729;</div>
      <div class="sn" v-if="myNodeHover">{{ myNodeHover.values_.lat.id }}</div>
      <div class="location" v-if="myNodeHover">
        经度: {{ myNodeHover.values_.lat }}
      </div>
      <div class="location" v-if="myNodeHover">
        纬度: {{ myNodeHover.values_.lng }}
      </div>
      <div class="info" v-if="myNodeHover">
        电量: {{ myNodeHover.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>
export default {
import {
  getHelemtData,
  getZones,
  createZones,
  delZones,
  sendAudio,
} from "@/api/helemt";
import telephoneBox from "../components/telephoneBox.vue";
}
import "ol/ol.css";
import Feature from "ol/Feature";
import Point from "ol/geom/Point";
import VectorSource from "ol/source/Vector";
import { Icon, Style, Fill, Stroke } from "ol/style";
import { transform } from "ol/proj";
import { Map, View } from "ol";
import TileLayer from "ol/layer/Tile";
import { Vector as VectorLayer } from "ol/layer";
import OSM from "ol/source/OSM";
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 = {};
let baseLayer = new TileLayer({
  source: new OSM({
    // url:'http://wprd0{1-4}.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scl=1&style=8',
    url: "http://wprd0{1-4}.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scl=1&style=7",
    crossOrigin: "anonymous",
    // url: 'http://wprd0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}'
  }),
});
let myDraw = {};
let myModify = {};
let myPolygon = {};
let mySelect = {};
let mySelect2 = {};
let overlay = {};
let overlay2 = {};
let voiceText = "";
let drawFeature = [];
export default {
  data() {
    return {
      isSending: false,
      isTele: false,
      isHidden: false,
      showBtn: false,
      nodeArr: [],
      nodeId: "",
      iconArr: [],
      rangeArr: [],
      zoom: 15,
      center: [116.06667, 39.66667],
      polygonArr: [],
      polyFeature: [],
      drawStore: [],
      modifyStore: [],
      polygonInfo: "",
      nodeFeature: [],
      myNode: null,
      myNodeHover: null,
      commentContent: "",
    };
  },
  mounted() {
    this.initMap();
  },
  components: {
    telephoneBox,
  },
  methods: {
    async initMap() {
      const that = this;
      // 获取节点
      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 ? "绿" : "红",
          battery: item.battery,
        });
      });
      // 获取区域
      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;
        });
      }
      // 设置地图中心
      this.center = this.nodeArr[0].data;
      if (this.polygonArr.length > 0) {
        this.initPolygonArr();
      }
      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;
      this.initAllNode();
      const vectorLayer = this.initLayer(vectorSource);
      const map = this.initBottomMap(vectorLayer);
      myMap = map;
      /* map.getView().on('change:resolution', ()=> {
      this.iconArr.forEach(item=>{
        let style = item.getStyle()
        console.log(this.zoom);
        style.getImage().setScale(this.zoom/15)
        item.setStyle(style)
        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;
            this.nodeId = "";
            return true;
          }
        },
        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") {
            this.myNodeHover = feature;
            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;
      mySelect2 = select2;
      select.on("select", function (e) {
        //   e.stopPropagation();
        console.log("--------------");
        overlay.setPosition(undefined);
        if (e.selected.length == 0) {
          console.log("999999");
          that.polygonInfo = "";
          that.nodeId = "";
          that.myNode = null;
          return false;
        }
        if (e.selected[0].values_.type == "node") {
          that.isHidden = false;
          that.nodeId = e.selected[0].values_.id;
          return false;
        }
        if (myPolygon.polygonName) {
          that.polygonInfo = myPolygon.polygonName;
        } else {
          that.polygonInfo = "新区域";
        }
        if (e.mapBrowserEvent) {
          console.log(e.mapBrowserEvent.coordinate);
          overlay.setPosition(e.mapBrowserEvent.coordinate);
        }
        return false;
      });
      select2.on("select", function (e) {
        if (
          e.selected.length &&
          e.selected[0].values_.type == "node" &&
          that.myNodeHover &&
          that.myNodeHover.values_.id == e.selected[0].values_.id
        ) {
          overlay2.setPosition(e.mapBrowserEvent.coordinate);
        } else {
        }
      });
    },
    initNode([x, y], color) {
      const iconFeature = new Feature({
        geometry: new Point(transform([x, y], "EPSG:4326", "EPSG:3857")),
      });
      const iconStyle = new Style({
        image: new Icon({
          size: [32, 32],
          src: `/images/map/安全帽-${color}.png`,
        }),
        zIndex: 1,
      });
      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);
      });
    },
    initPolygonArr() {
      this.polyFeature = [];
      this.polygonArr.forEach((item) => {
        const feature = new Feature({ geometry: new Polygon([item.data]) });
        feature.id = item.id;
        feature.type = "polygon";
        feature.polygonName = item.name;
        feature.data1 = item.data[1];
        this.polyFeature.push(feature);
      });
    },
    initLayer(source) {
      return new VectorLayer({
        source: source,
        style: new Style({
          fill: new Fill({
            color: "rgba(255, 255, 255, 0.4)",
          }),
          stroke: new Stroke({
            color: "#F54336",
            width: 2,
          }),
        }),
      });
    },
    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],
        view: new View({
          center: transform(this.center, "EPSG:4326", "EPSG:3857"),
          zoom: this.zoom,
        }),
        overlays: [overlay, overlay2],
      });
    },
    zoomIn() {
      const view = myMap.getView();
      this.zoom++;
      view.setZoom(this.zoom);
    },
    zoomOut() {
      const view = myMap.getView();
      this.zoom--;
      view.setZoom(this.zoom);
    },
    location() {
      const view = myMap.getView();
      view.setZoom(this.zoom);
      view.setCenter(transform(this.center, "EPSG:4326", "EPSG:3857"));
    },
    drawPolygon() {
      this.rangeArr = [];
      this.myNodeHover = null;
      //   this.myNode = null;
      //   this.nodeId = "";
      mySelect2.getFeatures().clear();
      mySelect.dispatchEvent({
        type: "select",
        selected: [],
      });
      this.resetMap();
      mySelect.setActive(false);
      mySelect2.setActive(false);
      this.showBtn = true;
      const draw = new Draw({
        source: myVectorSource,
        type: "Polygon",
      });
      myDraw = draw;
      draw.on("drawend", (event) => {
        let id;
        /* if (this.polygonArr.length > 0) {
          id =
            this.drawStore.length > 0
              ? +this.drawStore[this.drawStore.length - 1].id + 1
              : +this.polygonArr[this.polygonArr.length - 1].id + 1;
        } else {
          id = 1;
        } */
        if (this.drawStore.length > 0) {
          id = +this.drawStore[this.drawStore.length - 1].id + 1;
        } else {
          id =
            this.polygonArr.length > 0
              ? +this.polygonArr[this.polygonArr.length - 1].id + 1
              : "1";
        }
        event.feature.id = id;
        event.feature.type = "polygon";
        this.drawStore.push({
          id,
          data: event.feature.getGeometry().getCoordinates()[0],
        });
        drawFeature.push(event.feature);
      });
      const modify = new Modify({ source: myVectorSource });
      modify.addEventListener("modifyend", (event) => {
        const id = event.features.array_[0].id;
        const data = event.features.array_[0].getGeometry().getCoordinates()[0];
        this.modifyStore.push({ id, data });
      });
      myModify = modify;
      myMap.addInteraction(modify);
      myMap.addInteraction(draw);
    },
    resetMap() {
      drawFeature = [];
      this.polygonInfo = "";
      mySelect.setActive(true);
      mySelect2.setActive(true);
      this.initPolygonArr();
      const vectorSource = new VectorSource({
        features: this.polyFeature,
      });
      /* if(this.polygonArr.length>0){
      this.initPolygonArr()
      vectorSource.addFeature(this.polyFeature[0])
      } */
      myVectorSource = vectorSource;
      this.initAllNode();
      const vectorLayer = this.initLayer(vectorSource);
      myMap.setLayers([baseLayer, vectorLayer]);
      myMap.removeInteraction(myDraw);
      myMap.removeInteraction(myModify);
      this.showBtn = false;
      this.drawStore = [];
      this.modifyStore = [];
    },
    async savePoly() {
      mySelect.setActive(true);
      mySelect2.setActive(true);
      myMap.removeInteraction(myDraw);
      myMap.removeInteraction(myModify);
      this.showBtn = false;
      if (this.drawStore.length) {
        this.polygonArr = [...this.polygonArr, ...this.drawStore];
        this.drawStore = [];
      }
      if (this.modifyStore.length) {
        this.modifyStore.forEach((item) => {
          this.polygonArr.forEach((item2) => {
            if (item.id == item2.id) {
              item2.data = item.data;
            }
          });
        });
        this.modifyStore = [];
      }
      const arrData = this.polygonArr.map((item) => {
        let name = item.name ? item.name : "";
        let data = item.data.map((arr) => {
          arr = transform([arr[0], arr[1]], "EPSG:3857", "EPSG:4326");
          return arr.join(",");
        });
        data = data.join("&");
        return {
          name,
          dots: data,
          id: +item.id,
        };
      });
      const res = await createZones({ dots_arr: arrData });
      if (res.status == 200) {
        this.$message({
          type: "success",
          message: "保存成功!",
        });
      } else {
        this.$message({
          type: "info",
          message: "保存失败",
        });
      }
      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;
        });
      }
      if (drawFeature.length > 0) {
        this.polyFeature.forEach((item) => {
          myVectorSource.removeFeature(item);
        });
        this.initPolygonArr();
        this.polyFeature.forEach((item) => {
          myVectorSource.addFeature(item);
        });
      }
      //   ;
      /*  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: {
    nodeId: {
      async handler(val) {
        if (!val) {
          if (this.rangeArr.length > 0) {
            this.rangeArr.forEach((item) => {
              myVectorSource.removeFeature(item);
            });
            this.rangeArr = [];
          }
          return false;
        }
        const res = await getHelemtData({ sn: val });
        if (res.msg == "zone") {
          mySelect.getFeatures().clear();
          const polyArr = this.polyFeature.filter((item) => {
            return item.id == res.data.ID;
          });
          myPolygon = polyArr[0];
          mySelect.getFeatures().push(polyArr[0]);
          mySelect.dispatchEvent({
            type: "select",
            selected: [polyArr[0]],
            mapBrowserEvent: {
              coordinate: polyArr[0].data1,
            },
          });
          return;
        }
        const arr = [];
        if (res.data.items && res.data.items.length > 0) {
          res.data.items.forEach((obj) => {
            this.nodeArr.forEach((item) => {
              if (item.id == obj.device_sn) {
                arr.push(item);
              }
            });
          });
        }
        if (this.rangeArr.length > 0) {
          this.rangeArr.forEach((item) => {
            myVectorSource.removeFeature(item);
          });
          this.rangeArr = [];
        }
        if (arr.length > 0) {
          arr.forEach((item) => {
            const rangeFeature = new Feature({
              geometry: new Point(
                transform(item.data, "EPSG:4326", "EPSG:3857")
              ),
              name: "Null Island",
              population: 4000,
              rainfall: 500,
            });
            const iconStyle = new Style({
              image: new Icon({
                size: [64, 64],
                src: `/images/map/范围-${item.color}.png`,
              }),
            });
            rangeFeature.setStyle(iconStyle);
            myVectorSource.addFeature(rangeFeature);
            rangeFeature.set("type", "range");
            this.rangeArr.push(rangeFeature);
          });
        }
      },
    },
  },
};
</script>
<style scoped lang="scss">
.map-index  {
    width: 1170px;
    height: 396px;
    border-radius: 15px;
    background-color: skyblue
a {
  background-color: transparent;
  color: #337ab7;
  text-decoration: none;
}
a:active a:hover {
  outline: 0;
}
#map-index {
  position: relative;
  margin: 20px 0;
  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;
    flex-direction: column;
    z-index: 1;
    left: 25px;
    bottom: 25px;
    width: 30px;
    height: 91px;
    background: #ffffff;
    box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.25);
    border-radius: 8px;
    .location,
    .zoom-in,
    .zoom-out {
      line-height: 30px;
      font-size: 18px;
      flex: 1;
      cursor: pointer;
    }
    .location {
      background: #11aa66;
      border-radius: 8px 8px 0 0;
      color: #fff;
    }
  }
  .el-input {
    position: absolute;
    z-index: 1;
    top: 15px;
    left: 15px;
    width: 205px;
    height: 35px;
    ::v-deep input {
      width: 100%;
      height: 100%;
      &:focus {
        border-color: #11aa66 !important;
      }
    }
  }
  .range {
    position: absolute;
    left: 25px;
    bottom: 126px;
    width: 30px;
    height: 30px;
    background: #11aa66;
    color: #fff;
    border-radius: 8px;
    cursor: pointer;
    z-index: 1;
    line-height: 30px;
  }
  .save {
    position: absolute;
    z-index: 3;
    top: 15px;
    right: 113px;
    width: 87px;
    height: 35px;
    background: #11aa66;
    border: 1px solid #11aa66;
    border-radius: 8px;
    color: #fff;
    font-size: 12px;
    line-height: 36px;
    cursor: pointer;
  }
  .cancel {
    position: absolute;
    z-index: 3;
    top: 15px;
    right: 20px;
    width: 87px;
    height: 35px;
    background: #fff;
    border: 1px solid #11aa66;
    border-radius: 8px;
    color: #4f4f4f;
    font-size: 12px;
    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 {
    position: absolute;
    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>
<style>
.ol-zoom {
  display: none !important;
}
</style>