保安服务企业管理项目备份
guoshilong
2023-12-20 c0e471bfb5c3edfb862809908e2c47474c1a17cf
电子围栏
1 files modified
3 files added
432 ■■■■■ changed files
public/img/map/location.png patch | view | raw | blame | history
src/views/check/components/OlMapBox.vue 411 ●●●●● patch | view | raw | blame | history
src/views/check/leave.vue 2 ●●● patch | view | raw | blame | history
src/views/check/livePersonLocation.vue 19 ●●●●● patch | view | raw | blame | history
public/img/map/location.png
src/views/check/components/OlMapBox.vue
New file
@@ -0,0 +1,411 @@
<!--
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2023-10-11 16:01:58
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2023-11-29 14:17:09
 * @FilePath: \web\business\src\components\OlMapBox\index.vue
 * @Description:
 *
 * Copyright (c) 2023 by shuishen, All Rights Reserved.
-->
<template>
  <div class="w100 h100">
    <div id="OlMapBoxElement" class="w100 h100">
    </div>
  </div>
</template>
<script>
// import OLCesium from "ol-cesium"
import "ol/ol.css"
import OlView from "ol/View.js"
import {
  // eslint-disable-next-line no-unused-vars
  defaults as OlControlDefaults,
  defaults,
  // 全屏控件
  FullScreen,
  // 比例尺控件
  ScaleLine,
  // 缩放滚动条控件
  // eslint-disable-next-line no-unused-vars
  ZoomSlider,
  // 鼠标位置控件
  // eslint-disable-next-line no-unused-vars
  MousePosition,
  // -地图属性控件
  Attribution,
  // 鹰眼控件
  // eslint-disable-next-line no-unused-vars
  OverviewMap,
  // 缩放到范围控件
  // eslint-disable-next-line no-unused-vars
  ZoomToExtent,
  Rotate,
} from "ol/control.js"
import OlSourceOSM from "ol/source/OSM.js"
import OlLayerTile from "ol/layer/Tile.js"
import { Image as ImageLayer } from 'ol/layer'
import ImageStatic from 'ol/source/ImageStatic.js'
import OlLayerVectorTile from "ol/layer/VectorTile.js"
import OlMap from "ol/Map.js"
import OlProjection from "ol/proj/Projection.js"
import OlMVT from "ol/format/MVT.js"
import OlUnits from "ol/proj/Units.js"
import OlFeature from "ol/Feature"
import { get as projGet } from "ol/proj.js"
// c
import XYZ from "ol/source/XYZ"
import Cluster from "ol/source/Cluster"
import VectorLayer from "ol/layer/Vector"
import VectorSource from "ol/source/Vector"
import TileArcGISRest from "ol/source/TileArcGISRest"
import TilegridTileGrid from "ol/tilegrid/TileGrid"
import GeoJSON from "ol/format/GeoJSON"
import Feature from 'ol/Feature.js'
import Point from 'ol/geom/Point.js'
import { Icon, Style, Fill, Text, Stroke, Circle } from 'ol/style.js'
let mapView = null
let layersObjcect = {}
let baseMapLayer = {
  yx: [],
  sl: []
}
let options,
  epsgcode,
  isMvt = false
let isMapResource = true
export default {
  name: 'OlMapBox',
  props: {
    mapType: {
      type: String,
      default: 'sl'
    },
    mapContrast: {
      type: String,
      default: 'custom'
    }
  },
  data () {
    return {
      publicPath: process.env.BASE_URL,
    }
  },
  mounted () {
    const that = this
    this.$nextTick(() => {
      mapView = new OlMap({
        target: 'OlMapBoxElement',
        layers: [],
        view: new OlView({
          // 初始化中心点坐标,经纬度一会自己换一下
          center: [113, 24],
          zoom: 18,
          projection: "EPSG:4326"
        }),
      })
      mapView.on("singleclick", function (event) {
        mapView.forEachFeatureAtPixel(
          event.pixel,
          (feature) => {
            feature.dispatchEvent && feature.dispatchEvent({ type: 'click', event: event })
          }
        )
      })
      that.baseInitLayer(that.mapType)
      this.mapAddClusterLayer(
        'livePersonLocationLayer',
        '/public/img/map/location',
        [{lng: 113, lat: 24}, {lng: 115, lat:24 }],
        (e) => { },
      )
    })
  },
  methods: {
    /**
     * @description: 底图加载
     * @param {*} type
     * @return {*}
     */
    baseInitLayer (type) {
      if (baseMapLayer.yx.length) {
        baseMapLayer.yx.forEach(item => {
          mapView.removeLayer(item)
        })
        baseMapLayer.yx = []
      }
      if (baseMapLayer.sl.length) {
        baseMapLayer.sl.forEach(item => {
          mapView.removeLayer(item)
        })
        baseMapLayer.sl = []
      }
      if (type == 'yx') {
        let yxImgW = new OlLayerTile({
          zIndex: 1,
          title: '影像',
          source: new XYZ({
            url: 'https://t0.tianditu.gov.cn/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=e45274b0235bb913eceb393aabbf9c9c',
          })
        })
        mapView.addLayer(yxImgW)
        baseMapLayer.yx.push(yxImgW)
        let yxCvaW = new OlLayerTile({
          zIndex: 2,
          title: '影像标注',
          source: new XYZ({
            url: 'https://t0.tianditu.gov.cn/DataServer?T=cva_w&x={x}&y={y}&l={z}&tk=e45274b0235bb913eceb393aabbf9c9c',
          })
        })
        mapView.addLayer(yxCvaW)
        baseMapLayer.yx.push(yxCvaW)
      } else if (type == 'sl') {
        let slVecW = new OlLayerTile({
          zIndex: 2,
          title: '矢量',
          source: new XYZ({
            url: 'https://t0.tianditu.gov.cn/DataServer?T=vec_w&x={x}&y={y}&l={z}&tk=e45274b0235bb913eceb393aabbf9c9c',
          })
        })
        mapView.addLayer(slVecW)
        baseMapLayer.sl.push(slVecW)
        let slCvaW = new OlLayerTile({
          zIndex: 2,
          title: '矢量标注',
          source: new XYZ({
            url: 'https://t0.tianditu.gov.cn/DataServer?T=cva_w&x={x}&y={y}&l={z}&tk=e45274b0235bb913eceb393aabbf9c9c',
          })
        })
        mapView.addLayer(slCvaW)
        baseMapLayer.sl.push(slVecW)
      }
    },
    // javascript 转换
    lonLat2Mercator (lonlat) {
      var mercator = {
        x: 0,
        y: 0
      }
      var earthRad = 6378137.0
      mercator.x = lonlat.lng * Math.PI / 180 * earthRad
      var a = lonlat.lat * Math.PI / 180
      mercator.y = earthRad / 2 * Math.log((1.0 + Math.sin(a)) / (1.0 - Math.sin(a)))
      return mercator
    },
    getCurItemFeature (params) {
      const iconFeature = new Feature({
        geometry: new Point([Number(params.lng), Number(params.lat)]),
        attributes: params.item
      })
      let styleOptions = {
        cursor: 'pointer',
      }
      if (params.url) {
        styleOptions.image = new Icon({
          scale: params.scale || 1,
          imgSize: params.imgSize || [160, 221],
          src: params.url,
        })
      }
      if (params.text) {
        let textElement = document.createElement('span')
        textElement.innerHTML = params.text
        let color = '#0000FF'
        styleOptions.text = new Text({
          // 对齐方式
          textAlign: 'center',
          // 文本基线
          textBaseline: 'middle',
          text: textElement.innerHTML,
          font: '14px Arial',
          fill: new Fill({
            color: 'white'
          }),
          // 填充背景
          backgroundFill: new Fill({
            color: color
          }),
          padding: [2, 5, 2, 5],
          stroke: new Stroke({ color: '#00000000', width: 1 })
        })
      }
      iconFeature.setStyle(new Style(styleOptions))
      iconFeature.on('click', (e) => {
        if (params.event) {
          params.event(e.target.values_.attributes.attr)
        }
      })
      return iconFeature
    },
    /**
     * 删除图层
     * @param {*} layerName 图层名称
     */
    mapRemoveLayer (layerNames) {
      layerNames.forEach(item => {
        if (layersObjcect[item] && layersObjcect[item] != null) {
          mapView.removeLayer(layersObjcect[item])
          delete layersObjcect[item]
        }
        if (layersObjcect[item + 'ONE'] && layersObjcect[item + 'ONE'] != null) {
          mapView.removeLayer(layersObjcect[item + 'ONE'])
          delete layersObjcect[item + 'ONE']
        }
        if (layersObjcect[item + 'TWO'] && layersObjcect[item + 'TWO'] != null) {
          mapView.removeLayer(layersObjcect[item + 'TWO'])
          delete layersObjcect[item + 'TWO']
        }
      })
    },
    // 添加聚合图层的新模式,水库点分布
    mapAddClusterLayer (layerName, imgUrl, positionData, incident = (e) => { }, type = '') {
      const that = this
      if (!layersObjcect[layerName]) {
        if (type == 'cluster') {
          let source = new VectorSource()
          positionData.forEach(item => {
            source.addFeature(that.getCurItemFeature({
              item,
              lng: item.lng,
              lat: item.lat,
              url: imgUrl,
              event: incident
            }))
          })
          let layer = new Cluster({
            source: source,
            distance: 100
          })
          layersObjcect[layerName] = new VectorLayer({
            source: layer,
            zIndex: 24,
            style: (feature, resolution) => {
              let size = feature.get('features').length
              let radius = 10
              if (size > 900) {
                radius = 19
              } else if (size > 600) {
                radius = 16
              } else if (size > 400) {
                radius = 13
              }
              let style = new Style({
                image: new Circle({
                  radius: radius,
                  stroke: new Stroke({
                    color: 'blue',
                    width: 1
                  }),
                  fill: new Fill({
                    color: 'blue'
                  })
                }),
                text: new Text({
                  text: size.toString(),
                  fill: new Fill({
                    color: 'white'
                  })
                })
              })
              return style
            }
          })
          mapView.addLayer(layersObjcect[layerName])
          return
        } else {
          layersObjcect[layerName] = new VectorLayer({
            // 图标图层
            zIndex: 24,
            minZoom: 12,
            source: new VectorSource(),
          })
        }
        mapView.addLayer(layersObjcect[layerName])
      }
      positionData.forEach(item => {
        layersObjcect[layerName].getSource().addFeature(that.getCurItemFeature({
          item,
          lng: item.lng,
          lat: item.lat,
          url: imgUrl,
          event: incident
        }))
      })
    },
  },
}
</script>
<style lang='scss' scope>
.w100 {
  width: 100%;
}
.h100 {
  height: 100%;
}
</style>
src/views/check/leave.vue
@@ -258,7 +258,7 @@
        id: row.id,
        auditStatus: row.auditStatus,
        auditDetail: row.auditDetail,
        auditUser: this.userInfo.Id
        auditUser: this.userInfo.user_id
      };
      audit(data).then(
        () => {
src/views/check/livePersonLocation.vue
New file
@@ -0,0 +1,19 @@
<template>
  <div style="width: 100%; height: 100%;">
    <OlMapBox></OlMapBox>
  </div>
</template>
<script>
import  OlMapBox  from "./components/OlMapBox.vue";
export default {
  name: "livePersonLocation",
  components: {OlMapBox}
}
</script>
<style scoped>
</style>