上饶市警务平台后台管理前端
guoshilong
2023-02-14 f6ca44fd34e71b9d5ae9a52ac6b7781a13b8ed7b
安保管理地图选点
4 files modified
2 files added
2224 ■■■■■ changed files
src/api/security/security.js 42 ●●●●● patch | view | raw | blame | history
src/components/map/mapBox.vue 847 ●●●● patch | view | raw | blame | history
src/components/map/searchMap.vue 89 ●●●●● patch | view | raw | blame | history
src/components/map/searchMapBox.vue 350 ●●●●● patch | view | raw | blame | history
src/views/security/security.vue 882 ●●●● patch | view | raw | blame | history
vue.config.js 14 ●●●● patch | view | raw | blame | history
src/api/security/security.js
@@ -67,3 +67,45 @@
  })
}
//http://192.168.0.112:18080/sf3d/area/getAoiByPt?lng=117.9471794&lat=28.4474852&height=0&tolerance=10&adcode=361102
export const getAoiByPt = (row) =>{
  return request({
    url:'http://192.168.0.112:18080/sf3d/area/getAoiByPt',
    method:'get',
    data:row
  })
}
//192.168.0.112:9091/zhs/bs/search?ak=ebf48ecaa1fd436fa3d40c4600aa051f&region=361100&query=公安局&ids=61743e28bbf11700e9fc4ef03dd8bea9
export const searchByQuery  = (ak, region, query, ids) => {
  return request({
    url: '/bsapi/zhs/bs/search',
    method: 'get',
    params: {
      ak,
      region,
      query,
      ids
    }
  })
}
//http://{IP}:{PORT}/zhs/bs/search?ak=***&query= 万 达 商 场
// &region=440300&region_type=circle&page_size=3&page_num=1&infos=1&radius=500&location=113.841901,22.628249
export const searchByLonLat  = (ak, query,region,region_type,page_size,page_num,infos,radius,location) => {
  return request({
    url: '/bsapi/zhs/bs/search',
    method: 'get',
    params: {
      ak,
      query,
      region,
      region_type,
      page_size,
      page_num,
      infos,
      radius,
      location
    }
  })
}
src/components/map/mapBox.vue
@@ -1,448 +1,449 @@
<template>
    <div>
        <div id='map' :style="{ height: isDetail ? '90vh' : '40vh', width: '100%' }" ref="MapContent">
            <div style="position: absolute;right:40%;top:-1%;z-index: 999999">
                <p style="margin-top: 10px" v-if="!isDetail">
                    <el-button type="primary" size="small" @click="point()">绘制区域</el-button>
                    <el-button size="small" @click="clearDraw()">重置</el-button>
                </p>
            </div>
            <!--画线后的提示-->
            <div class="mapTip" v-if="showTip" :style="{ top: tipPosition.h + 'px', left: tipPosition.w + 'px' }">
                {{ tipTitle }}
            </div>
        </div>
  <div>
    <div id='map' :style="{ height: isDetail ? '90vh' : '40vh', width: '100%' }" ref="MapContent">
      <div style="position: absolute;right:40%;top:-1%;z-index: 999999">
        <p style="margin-top: 10px" v-if="!isDetail">
          <el-button type="primary" size="small" @click="point()">绘制区域</el-button>
          <el-button size="small" @click="clearDraw()">重置</el-button>
        </p>
      </div>
      <!--画线后的提示-->
      <div class="mapTip" v-if="showTip" :style="{ top: tipPosition.h + 'px', left: tipPosition.w + 'px' }">
        {{ tipTitle }}
      </div>
    </div>
  </div>
</template>
<script>
import 'ol/ol.css'
import { Map, View, Feature } from 'ol'
import {Map, View, Feature} from 'ol'
import VectorSource from 'ol/source/Vector'
import Cluster from 'ol/source/Cluster'
import { Vector as VectorLayer, Tile as TileLayer } from 'ol/layer'
import {Vector as VectorLayer, Tile as TileLayer} from 'ol/layer'
import LineString from "ol/geom/LineString"
import Point from 'ol/geom/Point'
import Icon from 'ol/style/Icon'
import { Style, Fill as StyleFill, Stroke as StyleStroke, Text as StyleText, Circle as StyleCircle } from 'ol/style'
import { Circle as GeomCircle, Point as GeomPoint, LineString as GeomLineString, Polygon as GeomPolygon } from 'ol/geom'
import {Style, Fill as StyleFill, Stroke as StyleStroke, Text as StyleText, Circle as StyleCircle} from 'ol/style'
import {Circle as GeomCircle, Point as GeomPoint, LineString as GeomLineString, Polygon as GeomPolygon} from 'ol/geom'
import Draw from 'ol/interaction/Draw'
import XYZ from "ol/source/XYZ"
import 'ol/ol.css'
export default {
    name: 'mapBox',
    props: ['routeRange', 'isDetail'],
    data () {
        return {
            map: null,
            points: [],
            // 线条点数组
            linePoints: [],
            // 多边形数组
            polygonPoints: [],
            draw: null,
            drawLayer: null,
            lineVector: null,
            pointVector: null,
            polygonVector:null,
            coordinates: [],// 保存绘画坐标地址   [[115.90490549080435, 28.746101718722358],[115.93151300423209, 28.741123538790717]]
            toData: null,// 保存数据库格式坐标地址
            showTip: false,
            tipPosition: {//提示的位置
                w: 200,
                h: 10,
            },
            tipTitle: null
        }
    },
    methods: {
        createMap () {
            let _this = this
            _this.map = new Map({
                target: 'map',
                layers: [
                    new TileLayer({
                        source: new XYZ({
                            url: "https://webmap-tile.sf-express.com/MapTileService/rt?fetchtype=static&x={x}&y={y}&z={z}&project=sfmap&pic_size=256&pic_type=png8&data_name=361100&data_format=merged-dat&data_type=normal", // 行政区划
                        })
                    }),
                ],
                view: new View({
                    // 设置中心点,默认南昌,用于规划南昌市的路线
                    center: [115.9032747077233, 28.67433116990186],
                    projection: 'EPSG:4326',
                    // 设置缩放倍数
                    zoom: 13,
                    minZoom: 8,
                    maxZoom: 19
                })
            })
            _this.lineVector = new VectorLayer({
                //layer所对应的source
                source: new VectorSource({
                    wrapX: false // 禁止横向无限重复(底图渲染的时候会横向无限重复),设置了这个属性,可以让绘制的图形不跟随底图横向无限重复
                }),
            })
            _this.pointVector = new VectorLayer({
                //layer所对应的source
                source: new VectorSource({
                    wrapX: false // 禁止横向无限重复(底图渲染的时候会横向无限重复),设置了这个属性,可以让绘制的图形不跟随底图横向无限重复
                }),
            })
            _this.polygonVector = new VectorLayer({
              //layer所对应的source
              source: new VectorSource({
                wrapX: false // 禁止横向无限重复(底图渲染的时候会横向无限重复),设置了这个属性,可以让绘制的图形不跟随底图横向无限重复
              }),
            })
            _this.map.addLayer(_this.lineVector)
            _this.map.addLayer(_this.pointVector)
            _this.map.addLayer(_this.polygonVector)
            //在地图上回显线或点
            _this.startAdd(_this.routeRange)
        },
        // 绘画之后的样式
        styleFunction () {
            // 绘画之后的样式
            let styles = [
                new Style({
                    fill: new StyleFill({ color: "rgba(255, 255, 255, 0.2)" }),
                    stroke: new StyleStroke({
                        color: 'rgb(252, 94, 32)',
                        width: 5
                    })
                })
            ]
            return styles
        },
        // 添加线路
        addLineDraw (toData) {
            // toData = 'LINESTRING(115.90505364627936 28.740342332731327,115.9119724729309 28.74040302419318,115.90766337913915 28.73566909016844)'
            if (toData) {
                // 将数据库点坐标数据转换
                let entityData = ""
                let entityArr = []
                entityData = toData.match(/\(([^)]*)\)/)
                if (entityData && entityData != "") {
                    entityData = entityData[1].split(",")
                    for (let j = 0; j < entityData.length; j++) {
                        entityArr.push([
                            Number(entityData[j].split(" ")[0]),
                            Number(entityData[j].split(" ")[1]),
                        ])
                    }
                }
                // let lineCoords = [[115.90490549080435, 28.746101718722358],[115.93151300423209, 28.741123538790717],[115.90696542732779, 28.73408542233564],[115.90696542732779, 28.73408542233564]]
                let lineCoords = entityArr
                let view = this.map.getView()
                view.setCenter([
                    lineCoords[Math.ceil(lineCoords.length / 2)][0],
                    lineCoords[Math.ceil(lineCoords.length / 2)][1],
                ])
                view.setZoom(14.5)
                let feature_LineString = new Feature({
                    geometry: new LineString(lineCoords),
                })
                feature_LineString.setStyle(this.styleFunction())// 设置样式
                this.lineVector.getSource().addFeature(feature_LineString)
            }
        },
        // 添加点
        addPoint (pointLonLat) {
            // pointLonLat = POINT(115.87531914674 28.8603307485585)
            if (pointLonLat) {
                let pointData = ""
                let pointArray = []
                pointData = pointLonLat.match(/\(([^)]*)\)/)
                pointArray = pointData[1].split(" ")
                //设置点
                let feature_Point = new Feature({
                    geometry: new Point([Number(pointArray[0]), Number(pointArray[1])])
                })
                //点样式
                let style = new Style({
                    image: new Icon({
                        src: "/img/dwicon.jpeg",
                        anchor: [0.48, 0.52],
                        // imgSize: [250,320],
                        scale: 0.2
                    }),
                })
                feature_Point.setStyle(style)
                this.pointVector.getSource().addFeature(feature_Point)
                let center = [Number(pointArray[0]), Number(pointArray[1])]
                let view = this.map.getView()
                view.setZoom(16)
                view.animate({
                    center: center,
                    duration: 5,
                })
            }
        },
        //回显多边形区域
        addPolygon(area){
        },
        // 将点坐标集合转换为数据库数据
        doData (val) {
            let str = "LINESTRING("
            for (let k = 0; k < val.length; k++) {
                str += `${val[k][0]} ${val[k][1]}`
                if (k != val.length - 1) {
                    str += ","
                }
            }
            str =str +","+ `${val[0][0]} ${val[0][1]}`
            str += ")"
            // console.log(str)
            return '\'' + str + '\''
        },
        // 开始绘制
        point () {
            let _this = this
            _this.coordinates = []
            _this.map.removeInteraction(_this.draw)
            _this.polygonVector.getSource().clear()
            //提示
            if (!_this.showTip) {
                _this.showTip = true
            }
            _this.tipTitle = "单击左键或者右键开始绘画"
            //提示器
            function mapMousemove (e) {
                _this.setTipPosition(e.offsetX, e.offsetY, 5, 5)
            }
            this.$refs.MapContent.addEventListener('mousemove', mapMousemove)
          // this.$refs.MapContent.removeEventListener('mousemove', mapMousemove)
            function mapMousedown () {
                _this.tipTitle = "可继续,或选择最终位置双击结束绘画"
            }
            this.$refs.MapContent.addEventListener('mousedown', mapMousedown)
            // this.$refs.MapContent.removeEventListener('mousedown', mapMousedown)
            _this.draw = new Draw({
                source: _this.polygonVector.getSource(),
                type: 'Polygon',
                style: new Style({
                    stroke: new StyleStroke({
                        color: "red",
                        width: 3,
                    })
                }),
            })
            _this.map.addInteraction(_this.draw)
            // 点击事件
            _this.map.on('click', function (e) {
                // 将点坐标保存集合
                _this.coordinates.push(e.coordinate)
            })
            // 结束事件
            _this.draw.on('drawend', function () {
                _this.map.removeInteraction(_this.draw)
                _this.polygonVector.setStyle(_this.styleFunction())// 路线画好之后的样式
                // 将点坐标集合转换为数据库数据
                let toData = _this.doData(_this.coordinates)
                // 传值给父组件
                _this.$emit('toData', toData)
                //隐藏提示
                _this.tipTitle = null
                _this.showTip = false
            })
        },
        // 设置统一控制点击事件,需要画图方式在此处切换
        handleClick (point) {
            // 绘制连线
            this.drawLineString(point)
            // 绘制点
            // this.drawPoint(point)
            // 绘制圆形
            // this.drawCircle(point)
            // 绘制多边形
            // this.drawPolygon(point)
        },
        // 绘制点位
        drawPoint (center) {
            let vectorLayer = this.getLayer()
            let point = new GeomPoint(center)
            let feature = new Feature(point)
            vectorLayer.getSource().addFeature(feature)
            this.map.addLayer(vectorLayer)
        },
        // 绘制连线
        drawLineString (point) {
            this.linePoints.push(point)
            let featureLine = new Feature({
                geometry: new GeomLineString(this.linePoints),
            })
            // 添加线的样式
            let lineStyle = new Style({
                fill: new StyleFill({
                    color: 'rgba(1, 210, 241, 0.1)'
                }),
                stroke: new StyleStroke({
                    color: 'rgba(255, 0, 0)',
                    width: 4,
                }),
            })
            featureLine.setStyle(lineStyle)
            let source = new VectorSource()
            source.addFeature(featureLine)
            let layer = new VectorLayer()
            layer.setSource(source)
            this.map.addLayer(layer)
        },
        // 绘制区域圆形
        drawCircle (center) {
            let vectorLayer = this.getLayer()
            // 设置半径
            let circle = new GeomCircle(center, 0.003)// 新建圆对象
            let feature = new Feature(circle)// 新建Feature对象 并将circle传入
            vectorLayer.getSource().addFeature(feature)// 将Feature对象填入图层源
            this.map.addLayer(vectorLayer) // 将图层添至地图对象
        },
        // 画多边形
        drawPolygon (point) {
            this.polygonPoints.push(point)
            let feature = new Feature({
                geometry: new GeomPolygon([this.polygonPoints]),
                attributes: null
            })
            // 添加线的样式
            let lineStyle = new Style({
                fill: new StyleFill({
                    color: 'rgba(1, 210, 241, 0.1)'
                }),
                stroke: new StyleStroke({
                    color: 'rgba(255, 0, 0)',
                    width: 4,
                }),
            })
            feature.setStyle(lineStyle)
            let source = new VectorSource()
            source.addFeature(feature)
            let vectorLayer = new VectorLayer({
                source: source
            })
            this.map.addLayer(vectorLayer)
        },
        // 设置聚合点
        addMarker () {
            let source = new VectorSource()
            // 随机创建200个要素,后台点位取出后按此格式处理
            for (let i = 1; i <= 200; i++) {
                let coordinates = [115.90 + Math.random() * 0.05, 28.64 + Math.random() * 0.05]
                let feature = new Feature(new GeomPoint(coordinates))
                source.addFeature(feature)
            }
            // 聚合
            let clusterSource = new Cluster({
                source: source,
                distance: 50
            })
            let clusters = new VectorLayer({
                source: clusterSource,
                style: function (feature) {
                    let size = feature.get('features').length
                    let style = new Style({
                        image: new StyleCircle({
                            radius: 20,
                            stroke: new StyleStroke({
                                color: 'white'
                            }),
                            fill: new StyleFill({
                                color: '#AAD3DF'
                            })
                        }),
                        text: new StyleText({
                            text: size.toString(),
                            fill: new StyleFill({
                                color: 'black'
                            })
                        })
                    })
                    return style
                }
            })
            this.map.addLayer(clusters)
        },
        // 重置图层
        clearDraw () {
            let _this = this
            _this.coordinates = []
            _this.map.removeInteraction(_this.draw)
            _this.lineVector.getSource().clear()
            _this.showTip = false
            _this.tipTitle = null
            // 传值给父组件
            _this.$emit('toData', "")
        },
        // 获取新的 layer 图层对象
        getLayer () {
            return new VectorLayer({
                source: new VectorSource({
                    features: ''
                }),
                // 设置样式,但不完全兼容
                // style: function (feature) {
                //   let style = new Style({
                //     stroke: new StyleStroke({
                //       color: '#E80000',
                //       width: 2
                //     }),
                //     fill: new StyleFill({
                //       color: 'rgba(0,0,0,0)'
                //     })
                //   })
                //   return style
                // }
            })
        },
        // 设置提示位置
        setTipPosition (x, y, n, m) {
            let _this = this
            _this.tipPosition.w = x + n
            _this.tipPosition.h = y + m
        },
        startAdd (routeRange) {
            if (routeRange.startsWith("LINESTRING")) {
                this.addLineDraw(routeRange)
            } else if (routeRange.startsWith("POINT")) {
                this.addPoint(routeRange)
            } else if (routeRange.startsWith("POLYGON")){
              this.addPolygon(routeRange)
            }
        }
    },
    mounted () {
        this.createMap()
  name: 'mapBox',
  props: ['routeRange', 'isDetail', "searchMap"],
  data() {
    return {
      map: null,
      points: [],
      // 线条点数组
      linePoints: [],
      // 多边形数组
      polygonPoints: [],
      draw: null,
      drawLayer: null,
      lineVector: null,
      pointVector: null,
      polygonVector: null,
      coordinates: [],// 保存绘画坐标地址   [[115.90490549080435, 28.746101718722358],[115.93151300423209, 28.741123538790717]]
      toData: null,// 保存数据库格式坐标地址
      showTip: false,
      tipPosition: {//提示的位置
        w: 200,
        h: 10,
      },
      tipTitle: null
    }
  },
  methods: {
    createMap() {
      let _this = this
      _this.map = new Map({
        target: 'map',
        layers: [
          new TileLayer({
            source: new XYZ({
              url: "https://webmap-tile.sf-express.com/MapTileService/rt?fetchtype=static&x={x}&y={y}&z={z}&project=sfmap&pic_size=256&pic_type=png8&data_name=361100&data_format=merged-dat&data_type=normal", // 行政区划
            })
          }),
        ],
        view: new View({
          // 设置中心点,默认南昌,用于规划南昌市的路线
          center: [117.951478782, 28.447896798],
          projection: 'EPSG:4326',
          // 设置缩放倍数
          zoom: 13,
          minZoom: 8,
          maxZoom: 19
        })
      })
      _this.lineVector = new VectorLayer({
        //layer所对应的source
        source: new VectorSource({
          wrapX: false // 禁止横向无限重复(底图渲染的时候会横向无限重复),设置了这个属性,可以让绘制的图形不跟随底图横向无限重复
        }),
      })
      _this.pointVector = new VectorLayer({
        //layer所对应的source
        source: new VectorSource({
          wrapX: false // 禁止横向无限重复(底图渲染的时候会横向无限重复),设置了这个属性,可以让绘制的图形不跟随底图横向无限重复
        }),
      })
      _this.polygonVector = new VectorLayer({
        //layer所对应的source
        source: new VectorSource({
          wrapX: false // 禁止横向无限重复(底图渲染的时候会横向无限重复),设置了这个属性,可以让绘制的图形不跟随底图横向无限重复
        }),
      })
      _this.map.addLayer(_this.lineVector)
      _this.map.addLayer(_this.pointVector)
      _this.map.addLayer(_this.polygonVector)
      //在地图上回显线或点
      _this.startAdd(_this.routeRange)
    },
    // 绘画之后的样式
    styleFunction() {
      // 绘画之后的样式
      let styles = [
        new Style({
          fill: new StyleFill({color: "rgba(255, 255, 255, 0.2)"}),
          stroke: new StyleStroke({
            color: 'rgb(252, 94, 32)',
            width: 5
          })
        })
      ]
      return styles
    },
    // 添加线路
    addLineDraw(toData) {
      // toData = 'LINESTRING(115.90505364627936 28.740342332731327,115.9119724729309 28.74040302419318,115.90766337913915 28.73566909016844)'
      if (toData) {
        // 将数据库点坐标数据转换
        let entityData = ""
        let entityArr = []
        entityData = toData.match(/\(([^)]*)\)/)
        if (entityData && entityData != "") {
          entityData = entityData[1].split(",")
          for (let j = 0; j < entityData.length; j++) {
            entityArr.push([
              Number(entityData[j].split(" ")[0]),
              Number(entityData[j].split(" ")[1]),
            ])
          }
        }
        // let lineCoords = [[115.90490549080435, 28.746101718722358],[115.93151300423209, 28.741123538790717],[115.90696542732779, 28.73408542233564],[115.90696542732779, 28.73408542233564]]
        let lineCoords = entityArr
        let view = this.map.getView()
        view.setCenter([
          lineCoords[Math.ceil(lineCoords.length / 2)][0],
          lineCoords[Math.ceil(lineCoords.length / 2)][1],
        ])
        view.setZoom(14.5)
        let feature_LineString = new Feature({
          geometry: new LineString(lineCoords),
        })
        feature_LineString.setStyle(this.styleFunction())// 设置样式
        this.lineVector.getSource().addFeature(feature_LineString)
      }
    },
    // 添加点
    addPoint(pointLonLat) {
      // pointLonLat = POINT(115.87531914674 28.8603307485585)
      if (pointLonLat) {
        let pointData = ""
        let pointArray = []
        pointData = pointLonLat.match(/\(([^)]*)\)/)
        pointArray = pointData[1].split(" ")
        //设置点
        let feature_Point = new Feature({
          geometry: new Point([Number(pointArray[0]), Number(pointArray[1])])
        })
        //点样式
        let style = new Style({
          image: new Icon({
            src: "/img/dwicon.jpeg",
            anchor: [0.48, 0.52],
            // imgSize: [250,320],
            scale: 0.2
          }),
        })
        feature_Point.setStyle(style)
        this.pointVector.getSource().addFeature(feature_Point)
        let center = [Number(pointArray[0]), Number(pointArray[1])]
        let view = this.map.getView()
        view.setZoom(16)
        view.animate({
          center: center,
          duration: 5,
        })
      }
    },
    // 将点坐标集合转换为数据库数据
    doData(val) {
      let str = "LINESTRING("
      for (let k = 0; k < val.length; k++) {
        str += `${val[k][0]} ${val[k][1]}`
        if (k != val.length - 1) {
          str += ","
        }
      }
      str = str + "," + `${val[0][0]} ${val[0][1]}`
      str += ")"
      // console.log(str)
      return '\'' + str + '\''
    },
    // 开始绘制
    point() {
      let _this = this
      _this.coordinates = []
      _this.map.removeInteraction(_this.draw)
      _this.polygonVector.getSource().clear()
      //提示
      if (!_this.showTip) {
        _this.showTip = true
      }
      _this.tipTitle = "单击左键或者右键开始绘画"
      //提示器
      function mapMousemove(e) {
        _this.setTipPosition(e.offsetX, e.offsetY, 5, 5)
      }
      this.$refs.MapContent.addEventListener('mousemove', mapMousemove)
      // this.$refs.MapContent.removeEventListener('mousemove', mapMousemove)
      function mapMousedown() {
        _this.tipTitle = "可继续,或选择最终位置双击结束绘画"
      }
      this.$refs.MapContent.addEventListener('mousedown', mapMousedown)
      // this.$refs.MapContent.removeEventListener('mousedown', mapMousedown)
      _this.draw = new Draw({
        source: _this.polygonVector.getSource(),
        type: 'Polygon',
        style: new Style({
          stroke: new StyleStroke({
            color: "red",
            width: 3,
          })
        }),
      })
      _this.map.addInteraction(_this.draw)
      // 点击事件
      _this.map.on('click', function (e) {
        // 将点坐标保存集合
        _this.coordinates.push(e.coordinate)
      })
      // 结束事件
      _this.draw.on('drawend', function () {
        _this.map.removeInteraction(_this.draw)
        _this.polygonVector.setStyle(_this.styleFunction())// 路线画好之后的样式
        // 将点坐标集合转换为数据库数据
        let toData = _this.doData(_this.coordinates)
        // 传值给父组件
        _this.$emit('toData', toData)
        //隐藏提示
        _this.tipTitle = null
        _this.showTip = false
      })
    },
    // 设置统一控制点击事件,需要画图方式在此处切换
    handleClick(point) {
      // 绘制连线
      this.drawLineString(point)
      // 绘制点
      // this.drawPoint(point)
      // 绘制圆形
      // this.drawCircle(point)
      // 绘制多边形
      // this.drawPolygon(point)
    },
    // 绘制点位
    drawPoint(center) {
      let vectorLayer = this.getLayer()
      let point = new GeomPoint(center)
      let feature = new Feature(point)
      vectorLayer.getSource().addFeature(feature)
      this.map.addLayer(vectorLayer)
    },
    // 绘制连线
    drawLineString(point) {
      this.linePoints.push(point)
      let featureLine = new Feature({
        geometry: new GeomLineString(this.linePoints),
      })
      // 添加线的样式
      let lineStyle = new Style({
        fill: new StyleFill({
          color: 'rgba(1, 210, 241, 0.1)'
        }),
        stroke: new StyleStroke({
          color: 'rgba(255, 0, 0)',
          width: 4,
        }),
      })
      featureLine.setStyle(lineStyle)
      let source = new VectorSource()
      source.addFeature(featureLine)
      let layer = new VectorLayer()
      layer.setSource(source)
      this.map.addLayer(layer)
    },
    // 绘制区域圆形
    drawCircle(center) {
      let vectorLayer = this.getLayer()
      // 设置半径
      let circle = new GeomCircle(center, 0.003)// 新建圆对象
      let feature = new Feature(circle)// 新建Feature对象 并将circle传入
      vectorLayer.getSource().addFeature(feature)// 将Feature对象填入图层源
      this.map.addLayer(vectorLayer) // 将图层添至地图对象
    },
    // 画多边形
    drawPolygon(point) {
      this.polygonPoints.push(point)
      let feature = new Feature({
        geometry: new GeomPolygon([this.polygonPoints]),
        attributes: null
      })
      // 添加线的样式
      let lineStyle = new Style({
        fill: new StyleFill({
          color: 'rgba(1, 210, 241, 0.1)'
        }),
        stroke: new StyleStroke({
          color: 'rgba(255, 0, 0)',
          width: 4,
        }),
      })
      feature.setStyle(lineStyle)
      let source = new VectorSource()
      source.addFeature(feature)
      let vectorLayer = new VectorLayer({
        source: source
      })
      this.map.addLayer(vectorLayer)
    },
    // 设置聚合点
    addMarker() {
      let source = new VectorSource()
      // 随机创建200个要素,后台点位取出后按此格式处理
      for (let i = 1; i <= 200; i++) {
        let coordinates = [115.90 + Math.random() * 0.05, 28.64 + Math.random() * 0.05]
        let feature = new Feature(new GeomPoint(coordinates))
        source.addFeature(feature)
      }
      // 聚合
      let clusterSource = new Cluster({
        source: source,
        distance: 50
      })
      let clusters = new VectorLayer({
        source: clusterSource,
        style: function (feature) {
          let size = feature.get('features').length
          let style = new Style({
            image: new StyleCircle({
              radius: 20,
              stroke: new StyleStroke({
                color: 'white'
              }),
              fill: new StyleFill({
                color: '#AAD3DF'
              })
            }),
            text: new StyleText({
              text: size.toString(),
              fill: new StyleFill({
                color: 'black'
              })
            })
          })
          return style
        }
      })
      this.map.addLayer(clusters)
    },
    // 重置图层
    clearDraw() {
      let _this = this
      _this.coordinates = []
      _this.map.removeInteraction(_this.draw)
      _this.lineVector.getSource().clear()
      _this.showTip = false
      _this.tipTitle = null
      // 传值给父组件
      _this.$emit('toData', "")
    },
    // 获取新的 layer 图层对象
    getLayer() {
      return new VectorLayer({
        source: new VectorSource({
          features: ''
        }),
        // 设置样式,但不完全兼容
        // style: function (feature) {
        //   let style = new Style({
        //     stroke: new StyleStroke({
        //       color: '#E80000',
        //       width: 2
        //     }),
        //     fill: new StyleFill({
        //       color: 'rgba(0,0,0,0)'
        //     })
        //   })
        //   return style
        // }
      })
    },
    // 设置提示位置
    setTipPosition(x, y, n, m) {
      let _this = this
      _this.tipPosition.w = x + n
      _this.tipPosition.h = y + m
    },
    startAdd(routeRange) {
      if (routeRange) {
        if (routeRange.startsWith("LINESTRING")) {
          this.addLineDraw(routeRange)
        } else if (routeRange.startsWith("POINT")) {
          this.addPoint(routeRange)
        }
      }
    }
  },
  mounted() {
    this.createMap()
  }
}
</script>
<style>
.mapTip {
    background-color: rgb(168, 168, 168);
    padding: 5px;
    border: 1px solid #000;
    position: absolute;
    z-index: 10 !important;
    border-radius: 5px;
  background-color: rgb(168, 168, 168);
  padding: 5px;
  border: 1px solid #000;
  position: absolute;
  z-index: 10 !important;
  border-radius: 5px;
}
</style>
src/components/map/searchMap.vue
New file
@@ -0,0 +1,89 @@
<template>
  <div class="basic-container">
    <div class="search-line">
      <el-input class="search-input" v-model="queryString" placeholder="请输入内容"></el-input>
      <el-button class="search-button" @click="getAddressByQuery">查询</el-button>
    </div>
    <search-map-box ref="OpenLayersMap" @getMapData="getMapData" :route-range="point"
                    :is-detail="true"></search-map-box>
  </div>
</template>
<script>
import SearchMapBox from "@/components/map/searchMapBox";
import {getAoiByPt, search, searchByLonLat, searchByQuery} from "@/api/security/security";
export default {
  name: "searchMap",
  components: {SearchMapBox},
  props: ['pointLonLat'],
  data() {
    return {
      ak:"ebf48ecaa1fd436fa3d40c4600aa051f",
      region:"361100",
      longitude: "",
      latitude: "",
      queryString: "",
      point: "",
    }
  },
  watch:{
    longitude:{
      handler(newVal){
        if (newVal){
          this.getAddressByLonLat()
        }
      }
    }
  },
  created() {
    this.point = this.pointLonLat
  },
  methods: {
    getMapData(data) {
      this.longitude = data[0][0]
      this.latitude = data[0][1]
      this.$emit("getLonLat", data[0])
    },
    getAddressByQuery() {
      let ak = this.ak
      let region = this.region
      let query = this.queryString
      let ids = "61743e28bbf11700e9fc4ef03dd8bea9"
      searchByQuery(ak,region,query,ids).then(res => {
        console.log(res)
      })
    },
    getAddressByLonLat(){
      let ak = this.ak
      let query = ""
      let region = this.region
      let region_type = "circle"
      let page_size = "3"
      let page_num = "1"
      let infos = 1
      let radius = 10
      let location = this.longitude+" "+this.latitude
      searchByLonLat(ak,query,region,region_type,page_size,page_num,infos,radius,location).then(res=>{
        console.log(res)
      })
    }
  }
}
</script>
<style scoped>
.search-line {
  display: flex;
}
.search-input {
  margin-bottom: 2%;
}
.search-button {
  height: 10%;
}
</style>
src/components/map/searchMapBox.vue
New file
@@ -0,0 +1,350 @@
<template>
  <div>
    <div id='searchMap' style="height: 50vh; width: 100%" ref="MapContent">
    </div>
  </div>
</template>
<script>
import {Feature, Map, View} from "ol";
import {Tile as TileLayer, Vector as VectorLayer} from "ol/layer";
import XYZ from "ol/source/XYZ";
import VectorSource from "ol/source/Vector";
import {Circle as StyleCircle, Fill as StyleFill, Stroke as StyleStroke, Style, Text as StyleText} from "ol/style";
import Point from "ol/geom/Point";
import Icon from "ol/style/Icon";
import Draw from "ol/interaction/Draw";
import {Circle as GeomCircle, LineString as GeomLineString, Point as GeomPoint, Polygon as GeomPolygon} from "ol/geom";
import Cluster from "ol/source/Cluster";
export default {
  name: "searchMapBox",
  props: ['routeRange'],
  data() {
    return {
      map: null,
      points: [],
      featurePoint:null,
      // 线条点数组
      linePoints: [],
      // 多边形数组
      polygonPoints: [],
      draw: null,
      drawLayer: null,
      pointVector: null,
      coordinates: [],// 保存绘画坐标地址   [[115.90490549080435, 28.746101718722358],[115.93151300423209, 28.741123538790717]]
      toData: null,// 保存数据库格式坐标地址
      showTip: false,
      tipTitle: null
    }
  },
  methods: {
    createMap() {
      let _this = this
      //初始化地图
      _this.map = new Map({
        target: 'searchMap',
        layers: [
          new TileLayer({
            source: new XYZ({
              url: "https://webmap-tile.sf-express.com/MapTileService/rt?fetchtype=static&x={x}&y={y}&z={z}&project=sfmap&pic_size=256&pic_type=png8&data_name=361100&data_format=merged-dat&data_type=normal", // 行政区划
            })
          }),
        ],
        view: new View({
          // 设置中心点
          //117.951478782, 28.447896798, 5000
          center: [117.951478782, 28.447896798],
          projection: 'EPSG:4326',
          // 设置缩放倍数
          zoom: 13,
          minZoom: 8,
          maxZoom: 19
        })
      })
      _this.pointVector = new VectorLayer({
        //layer所对应的source
        source: new VectorSource({
          wrapX: false // 禁止横向无限重复(底图渲染的时候会横向无限重复),设置了这个属性,可以让绘制的图形不跟随底图横向无限重复
        }),
        style: new Style({
          image: new Icon({
            src: "/img/dwicon.jpeg",
            anchor: [0.48, 1],
            // imgSize: [250,320],
            scale: 0.13
          }),
        })
      })
      _this.map.addLayer(_this.pointVector)
      // 在地图上回显线或点
      if (this.routeRange) {
        _this.startAdd(_this.routeRange)
      }
      this.point()
    },
    // 绘画之后的样式
    styleFunction() {
      // 绘画之后的样式
      let styles = [
        new Style({
          fill: new StyleFill({color: "rgba(255, 255, 255, 0.2)"}),
          stroke: new StyleStroke({
            color: 'rgb(252, 94, 32)',
            width: 5
          })
        })
      ]
      return styles
    },
    // 添加点
    addPoint(pointLonLat) {
      // pointLonLat = POINT(115.87531914674 28.8603307485585)
      if (pointLonLat) {
        let pointData = ""
        let pointArray = []
        pointData = pointLonLat.match(/\(([^)]*)\)/)
        pointArray = pointData[1].split(" ")
        //设置点
        let feature_Point = new Feature({
          geometry: new Point([Number(pointArray[0]), Number(pointArray[1])])
        })
        //点样式
        let style = new Style({
          image: new Icon({
            src: "/img/dwicon.jpeg",
            anchor: [0.48, 1],
            // imgSize: [250,320],
            scale: 0.13
          }),
        })
        this.featurePoint = feature_Point
        feature_Point.setStyle(style)
        this.pointVector.getSource().addFeature(feature_Point)
        let center = [Number(pointArray[0]), Number(pointArray[1])]
        let view = this.map.getView()
        view.setZoom(16)
        view.animate({
          center: center,
          duration: 5,
        })
      }
    },
    // 将点坐标集合转换为数据库数据
    doData(val) {
      let str = "LINESTRING("
      for (let k = 0; k < val.length; k++) {
        str += `${val[k][0]} ${val[k][1]}`
        if (k != val.length - 1) {
          str += ","
        }
      }
      str = str + "," + `${val[0][0]} ${val[0][1]}`
      str += ")"
      // console.log(str)
      return '\'' + str + '\''
    },
    // 开始绘制
    point() {
      let _this = this
      _this.coordinates = []
      _this.map.removeInteraction(_this.draw)
      // _this.pointVector.getSource().clear()
      _this.draw = new Draw({
        source: _this.pointVector.getSource(),
        type: 'Point',
      })
      _this.map.addInteraction(_this.draw)
      // 点击事件
      _this.map.on('click', function (e) {
        if (_this.featurePoint != null){
          _this.pointVector.getSource().removeFeature(_this.featurePoint)
        }
        if (_this.coordinates.length > 0) {
          let featureArray = _this.pointVector.getSource().getFeatures()
          for (let i = 0; i < featureArray.length -1; i++) {
            _this.pointVector.getSource().removeFeature(featureArray[i])
          }
          _this.coordinates = []
        }
        // 将点坐标保存集合
        _this.coordinates.push(e.coordinate)
        _this.$emit("getMapData", _this.coordinates)
      })
    },
    // 设置统一控制点击事件,需要画图方式在此处切换
    handleClick(point) {
      // 绘制连线
      this.drawLineString(point)
      // 绘制点
      // this.drawPoint(point)
      // 绘制圆形
      // this.drawCircle(point)
      // 绘制多边形
      // this.drawPolygon(point)
    },
    // 绘制点位
    drawPoint(center) {
      let vectorLayer = this.getLayer()
      let point = new GeomPoint(center)
      let feature = new Feature(point)
      vectorLayer.getSource().addFeature(feature)
      this.map.addLayer(vectorLayer)
    },
    // 绘制连线
    drawLineString(point) {
      this.linePoints.push(point)
      let featureLine = new Feature({
        geometry: new GeomLineString(this.linePoints),
      })
      // 添加线的样式
      let lineStyle = new Style({
        fill: new StyleFill({
          color: 'rgba(1, 210, 241, 0.1)'
        }),
        stroke: new StyleStroke({
          color: 'rgba(255, 0, 0)',
          width: 4,
        }),
      })
      featureLine.setStyle(lineStyle)
      let source = new VectorSource()
      source.addFeature(featureLine)
      let layer = new VectorLayer()
      layer.setSource(source)
      this.map.addLayer(layer)
    },
    // 绘制区域圆形
    drawCircle(center) {
      let vectorLayer = this.getLayer()
      // 设置半径
      let circle = new GeomCircle(center, 0.003)// 新建圆对象
      let feature = new Feature(circle)// 新建Feature对象 并将circle传入
      vectorLayer.getSource().addFeature(feature)// 将Feature对象填入图层源
      this.map.addLayer(vectorLayer) // 将图层添至地图对象
    },
    // 画多边形
    drawPolygon(point) {
      this.polygonPoints.push(point)
      let feature = new Feature({
        geometry: new GeomPolygon([this.polygonPoints]),
        attributes: null
      })
      // 添加线的样式
      let lineStyle = new Style({
        fill: new StyleFill({
          color: 'rgba(1, 210, 241, 0.1)'
        }),
        stroke: new StyleStroke({
          color: 'rgba(255, 0, 0)',
          width: 4,
        }),
      })
      feature.setStyle(lineStyle)
      let source = new VectorSource()
      source.addFeature(feature)
      let vectorLayer = new VectorLayer({
        source: source
      })
      this.map.addLayer(vectorLayer)
    },
    // 设置聚合点
    addMarker() {
      let source = new VectorSource()
      // 随机创建200个要素,后台点位取出后按此格式处理
      for (let i = 1; i <= 200; i++) {
        let coordinates = [115.90 + Math.random() * 0.05, 28.64 + Math.random() * 0.05]
        let feature = new Feature(new GeomPoint(coordinates))
        source.addFeature(feature)
      }
      // 聚合
      let clusterSource = new Cluster({
        source: source,
        distance: 50
      })
      let clusters = new VectorLayer({
        source: clusterSource,
        style: function (feature) {
          let size = feature.get('features').length
          let style = new Style({
            image: new StyleCircle({
              radius: 20,
              stroke: new StyleStroke({
                color: 'white'
              }),
              fill: new StyleFill({
                color: '#AAD3DF'
              })
            }),
            text: new StyleText({
              text: size.toString(),
              fill: new StyleFill({
                color: 'black'
              })
            })
          })
          return style
        }
      })
      this.map.addLayer(clusters)
    },
    // 重置图层
    clearDraw() {
      let _this = this
      _this.coordinates = []
      _this.map.removeInteraction(_this.draw)
      _this.pointVector.getSource().clear()
      // 传值给父组件
      _this.$emit('toData', "")
    },
    // 获取新的 layer 图层对象
    getLayer() {
      return new VectorLayer({
        source: new VectorSource({
          features: ''
        }),
        // 设置样式,但不完全兼容
        // style: function (feature) {
        //   let style = new Style({
        //     stroke: new StyleStroke({
        //       color: '#E80000',
        //       width: 2
        //     }),
        //     fill: new StyleFill({
        //       color: 'rgba(0,0,0,0)'
        //     })
        //   })
        //   return style
        // }
      })
    },
    startAdd(routeRange) {
      if (routeRange.startsWith("POINT")) {
        this.addPoint(routeRange)
      }
    }
  },
  mounted() {
    this.createMap()
  }
}
</script>
<style scoped>
</style>
src/views/security/security.vue
@@ -1,440 +1,480 @@
<template>
    <basic-container>
        <avue-crud :option="option" :table-loading="loading" :data="data" :page.sync="page" :permission="permissionList"
            :before-open="beforeOpen" v-model="form" ref="crud" @row-update="rowUpdate" @row-save="rowSave"
            @row-del="rowDel" @search-change="searchChange" @search-reset="searchReset"
            @selection-change="selectionChange" @current-change="currentChange" @size-change="sizeChange"
            @refresh-change="refreshChange" @on-load="onLoad">
            <template slot="menuLeft">
                <el-button size="small" icon="el-icon-delete" plain v-if="permission.security_delete"
                    @click="handleDelete">删 除
                </el-button>
            </template>
            <template slot-scope="{type,size,row,index}" slot="menu">
                <el-button icon="el-icon-coordinate" :size="size" :type="type"
                    @click="handlePersonList(row)">活动人员</el-button>
                <el-button icon="el-icon-data-line" :size="size" :type="type"
                    @click="handleCarList(row)">活动车辆</el-button>
            </template>
            <template slot="activityAreaForm">
              <map-box ref="OpenLayersMap" @toData="toData" :routeRange="form.activityArea"></map-box>
            </template>
  <basic-container>
    <avue-crud :option="option" :table-loading="loading" :data="data" :page.sync="page" :permission="permissionList"
               :before-open="beforeOpen" v-model="form" ref="crud" @row-update="rowUpdate" @row-save="rowSave"
               @row-del="rowDel" @search-change="searchChange" @search-reset="searchReset"
               @selection-change="selectionChange" @current-change="currentChange" @size-change="sizeChange"
               @refresh-change="refreshChange" @on-load="onLoad">
      <template slot="menuLeft">
        <el-button size="small" icon="el-icon-delete" plain v-if="permission.security_delete"
                   @click="handleDelete">删 除
        </el-button>
      </template>
      <template slot-scope="{type,size,row,index}" slot="menu">
        <el-button icon="el-icon-coordinate" :size="size" :type="type"
                   @click="handlePersonList(row)">活动人员
        </el-button>
        <el-button icon="el-icon-data-line" :size="size" :type="type"
                   @click="handleCarList(row)">活动车辆
        </el-button>
      </template>
      <template slot="activityAreaForm">
        <map-box ref="OpenLayersMap" @toData="toData" :routeRange="form.activityArea"></map-box>
      </template>
        </avue-crud>
    </avue-crud>
        <el-drawer title="活动人员区域" :visible.sync="personBox" :append-to-body="true" size="50%" :destroy-on-close="true">
            <securityManage ref="securityManage" :securityId="securityId" />
        </el-drawer>
    <el-drawer title="活动人员区域" :visible.sync="personBox" :append-to-body="true" size="50%" :destroy-on-close="true">
      <securityManage ref="securityManage" :securityId="securityId"/>
    </el-drawer>
        <el-drawer title="活动车辆区域" :visible.sync="carBox" :append-to-body="true" size="50%" :destroy-on-close="true">
            <securityManageCar ref="car" :securityId="securityId" />
        </el-drawer>
    </basic-container>
    <el-drawer title="活动车辆区域" :visible.sync="carBox" :append-to-body="true" size="50%" :destroy-on-close="true">
      <securityManageCar ref="car" :securityId="securityId"/>
    </el-drawer>
    <el-dialog
      title="提示"
      :visible.sync="placeBox"
      append-to-body
      destroy-on-close
      width="70%">
      <search-map @getLonLat="getLonLat" :point-lon-lat="point"></search-map>
      <span slot="footer" class="dialog-footer">
            <el-button type="primary" @click="confirmLonLat">确 定</el-button>
          </span>
    </el-dialog>
  </basic-container>
</template>
<script>
import { getPage, getDetail, add, update, remove } from "@/api/security/security"
import { getUserInfos } from "@/api/system/user"
import {getPage, getDetail, add, update, remove} from "@/api/security/security"
import {getUserInfos} from "@/api/system/user"
// import AvueMap from 'avue-plugin-map';
import { mapGetters } from "vuex"
import {mapGetters} from "vuex"
import securityManage from "@/views/securityManage/securityManage"
import securityManageCar from "@/views/securityManageCar/securityManageCar"
import MapBox from "@/components/map/mapBox";
import SearchMap from "@/components/map/searchMap";
export default {
    components: {
      MapBox,
        securityManage,
        securityManageCar
    },
    data () {
        return {
            securityId: "",
            carBox: false,
            personBox: false,
            form: {},
            query: {},
            loading: true,
            page: {
                pageSize: 10,
                currentPage: 1,
                total: 0
  components: {
    SearchMap,
    MapBox,
    securityManage,
    securityManageCar
  },
  data() {
    return {
      securityId: "",
      carBox: false,
      personBox: false,
      placeBox: false,
      point:"",
      chosePoint:{},
      form: {},
      query: {},
      loading: true,
      page: {
        pageSize: 10,
        currentPage: 1,
        total: 0
      },
      selectionList: [],
      option: {
        height: 'auto',
        calcHeight: 30,
        labelWidth: "100",
        dialogWidth: 950,
        tip: false,
        searchShow: true,
        searchMenuSpan: 6,
        border: true,
        index: true,
        viewBtn: true,
        selection: true,
        excelBtn: true,
        dialogClickModal: false,
        menuWidth: 370,
        column: [
          {
            label: "活动名称",
            prop: "name",
            search: true,
            searchSpan: 4,
            rules: [{
              required: true,
              message: "请输入活动名称",
              trigger: "blur"
            }],
          },
          {
            label: "负责单位",
            prop: "company",
          },
          {
            label: "负责人",
            prop: "person",
            width: 80,
            rules: [{
              required: true,
              message: "请输入负责人",
              trigger: "blur"
            }],
          },
          {
            label: "联系方式",
            prop: "contact",
            width: 100,
            rules: [{
              required: true,
              message: "请输入联系方式",
              trigger: "blur"
            }],
          },
          {
            label: "活动地点",
            prop: "place",
            span: 24,
            click: () => {
              this.placeBox = !this.placeBox
            },
            selectionList: [],
            option: {
                height: 'auto',
                calcHeight: 30,
                labelWidth: "100",
                dialogWidth: 950,
                tip: false,
                searchShow: true,
                searchMenuSpan: 6,
                border: true,
                index: true,
                viewBtn: true,
                selection: true,
                excelBtn: true,
                dialogClickModal: false,
                menuWidth: 370,
                column: [
                    {
                        label: "活动名称",
                        prop: "name",
                        search: true,
                        searchSpan: 4,
                        rules: [{
                            required: true,
                            message: "请输入活动名称",
                            trigger: "blur"
                        }],
                    },
                    {
                        label: "负责单位",
                        prop: "company",
                    },
                    {
                        label: "负责人",
                        prop: "person",
                        width: 80,
                        rules: [{
                            required: true,
                            message: "请输入负责人",
                            trigger: "blur"
                        }],
                    },
                    {
                        label: "联系方式",
                        prop: "contact",
                        width: 100,
                        rules: [{
                            required: true,
                            message: "请输入联系方式",
                            trigger: "blur"
                        }],
                    },
                    {
                        label: "活动地点",
                        prop: "place",
                        span: 24
                        // addDisplay: false,
                        // editDisplay: false,
                        // viewDisplay: false,
                    },
                    {
                      label: "经度",
                      prop: "longitude",
                      span: 12,
                      hide: true,
                      rules: [{
                        required: true,
                        message: "请输入纬度",
                        trigger: "blur"
                      }],
                    },
                    {
                      label: "纬度",
                      prop: "latitude",
                      span: 12,
                      hide: true,
                      rules: [{
                        required: true,
                        message: "请输入纬度",
                        trigger: "blur"
                      }],
                    },
                    {
                      label: "活动区域",
                      prop: "activityArea",
                      type: "input",
                      hide: true,
                      span: 24,
                      display: true,
                      addDisplay: true
                    },
                    {
                        label: "所属辖区",
                        prop: "deptId",
                        type: "tree",
                        dicUrl: "api/blade-system/dept/lazy-list",
                        props: {
                            label: 'deptName',
                            value: 'id',
                            children: 'children'
                        },
                        search: true,
                        searchSpan: 4,
                        span: 24,
                        width: 110,
                        rules: [{
                            required: true,
                            message: "请选择所属辖区",
                            trigger: "blur"
                        }]
                    },
                    // {
                    //   label: "地址",
                    //   prop: "avueMap",
                    //   type: "map",
                    // },
                    {
                        label: "开始时间",
                        prop: "startTime",
                        type: "datetime",
                        defaultTime: '00:00:00',
                        format: "yyyy-MM-dd HH:mm",
                        valueFormat: "yyyy-MM-dd HH:mm:ss",
                        rules: [{
                            required: true,
                            message: "请输入开始时间",
                            trigger: "blur"
                        }],
                        width: 120,
                    },
                    {
                        label: "结束时间",
                        prop: "endTime",
                        type: "datetime",
                        defaultTime: '23:59:59',
                        format: "yyyy-MM-dd HH:mm",
                        valueFormat: "yyyy-MM-dd HH:mm",
                        rules: [{
                            required: true,
                            message: "请输入结束时间",
                            trigger: "blur"
                        }],
                        width: 120,
                    },
                    // {
                    //   label: "",
                    //   prop: "map",
                    //   labelWidth: 10,
                    //   searchSpan: 0,
                    //   // maxlength: 5,
                    //   hide: true,
                    //   span: 3,
                    //   // display:false,
                    //   component: "AvueMap",
                    // },
                    {
                        label: "活动类型",
                        prop: "type",
                        type: "select",
                        dicUrl: "/api/blade-system/dict-biz/dictionary?code=securityType",
                        props: {
                            label: "dictValue",
                            value: "dictKey"
                        },
                        rules: [{
                            required: true,
                            message: "请选择活动类型",
                            trigger: "blur"
                        }],
                        width: 90,
                    },
                    {
                        label: "人数",
                        prop: "number",
                        width: 60,
                    },
                    {
                        label: "活动内容",
                        prop: "content",
                        type: "textarea",
                        span: 24
                    },
                ]
            // addDisplay: false,
            // editDisplay: false,
            // viewDisplay: false,
          },
          {
            label: "经度",
            prop: "longitude",
            span: 12,
            hide: true,
            disabled:true,
            rules: [{
              required: true,
              message: "请输入纬度",
              trigger: "blur"
            }],
          },
          {
            label: "纬度",
            prop: "latitude",
            span: 12,
            hide: true,
            disabled: true,
            rules: [{
              required: true,
              message: "请输入纬度",
              trigger: "blur"
            }],
          },
          {
            label: "活动区域",
            prop: "activityArea",
            type: "input",
            hide: true,
            span: 24,
            display: true,
            addDisplay: true
          },
          {
            label: "所属辖区",
            prop: "deptId",
            type: "tree",
            dicUrl: "api/blade-system/dept/lazy-list",
            props: {
              label: 'deptName',
              value: 'id',
              children: 'children'
            },
            data: []
        }
    },
    // watch: {
    //   //latitude   longitude   formattedAddress
    //   "form.avueMap":{
    //     handler (newObj) {
    //       if (newObj.length>0) {
    //         this.form.place = newObj[2]
    //         this.form.position = newObj[0]+","+newObj[1]
    //       }
    //     }
    //   }
    // },
    computed: {
        ...mapGetters(["userInfo", "permission"]),
        permissionList () {
            return {
                addBtn: this.vaildData(this.permission.security_add, false),
                viewBtn: this.vaildData(this.permission.security_view, false),
                delBtn: this.vaildData(this.permission.security_delete, false),
                editBtn: this.vaildData(this.permission.security_edit, false)
            }
        },
        ids () {
            let ids = []
            this.selectionList.forEach(ele => {
                ids.push(ele.id)
            })
            return ids.join(",")
        }
    },
    created () {
        const tokenLength = window.location.href.indexOf('=')
        if (tokenLength > 0) {
            //取“=”之后的token
            this.getUserInfo()
        }
    },
    methods: {
        getUserInfo () {
            getUserInfos().then(res => {
                const data = res.data
                this.$store.commit('SET_TOKEN', data.access_token)
                this.$store.commit('SET_REFRESH_TOKEN', data.refresh_token)
                this.$store.commit('SET_TENANT_ID', data.tenant_id)
                this.$store.commit('SET_USER_INFO', data)
                this.$store.commit('DEL_ALL_TAG')
                this.$store.commit('CLEAR_LOCK')
            })
        },
        rowSave (row, done, loading) {
            row.position = row.longitude + " " + row.latitude
            add(row).then(() => {
                this.onLoad(this.page)
                this.$message({
                    type: "success",
                    message: "操作成功!"
                })
                done()
            }, error => {
                loading()
                window.console.log(error)
            })
        },
        rowUpdate (row, index, done, loading) {
            if (!row.activityArea){
              this.$message.warning("请绘制活动区域")
              loading()
              return
            }
            row.position = row.longitude + " " + row.latitude
            update(row).then(() => {
                this.onLoad(this.page)
                this.$message({
                    type: "success",
                    message: "操作成功!"
                })
                done()
            }, error => {
                loading()
                console.log(error)
            })
        },
        rowDel (row) {
            this.$confirm("确定将选择数据删除?", {
                confirmButtonText: "确定",
                cancelButtonText: "取消",
                type: "warning"
            })
                .then(() => {
                    return remove(row.id)
                })
                .then(() => {
                    this.onLoad(this.page)
                    this.$message({
                        type: "success",
                        message: "操作成功!"
                    })
                })
        },
        handleDelete () {
            if (this.selectionList.length === 0) {
                this.$message.warning("请选择至少一条数据")
                return
            }
            this.$confirm("确定将选择数据删除?", {
                confirmButtonText: "确定",
                cancelButtonText: "取消",
                type: "warning"
            })
                .then(() => {
                    return remove(this.ids)
                })
                .then(() => {
                    this.onLoad(this.page)
                    this.$message({
                        type: "success",
                        message: "操作成功!"
                    })
                    this.$refs.crud.toggleSelection()
                })
        },
        beforeOpen (done, type) {
            if (["edit", "view"].includes(type)) {
                getDetail(this.form.id).then(res => {
                    var data = res.data.data
                    this.form = data
                    this.form['longitude'] = data.position.split(" ")[0]
                    this.form['latitude'] = data.position.split(" ")[1]
                })
            }
            done()
        },
        searchReset () {
            this.query = {}
            this.onLoad(this.page)
        },
        searchChange (params, done) {
            this.query = params
            this.page.currentPage = 1
            this.onLoad(this.page, params)
            done()
        },
        selectionChange (list) {
            this.selectionList = list
        },
        selectionClear () {
            this.selectionList = []
            this.$refs.crud.toggleSelection()
        },
        currentChange (currentPage) {
            this.page.currentPage = currentPage
        },
        sizeChange (pageSize) {
            this.page.pageSize = pageSize
        },
        refreshChange () {
            this.onLoad(this.page, this.query)
        },
        onLoad (page, params = {}) {
            this.loading = true
            if (this.userInfo.role_name != "admin" && this.userInfo.role_name != "administrator") {
                params["jurisdiction"] = this.userInfo.dept_id
            }
            getPage(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
                const data = res.data.data
                this.page.total = data.total
                this.data = data.records
                this.loading = false
                this.selectionClear()
            })
        },
        //活动人员区域点击按钮事件
        handlePersonList (row) {
            this.personBox = true
            this.securityId = row.id
        },
        //活动车辆区域点击按钮事件
        handleCarList (row) {
            this.carBox = true
            this.securityId = row.id
        },
        //地图传回的polygon坐标
        toData(data){
          this.form.activityArea = data
        }
            search: true,
            searchSpan: 4,
            span: 24,
            width: 110,
            rules: [{
              required: true,
              message: "请选择所属辖区",
              trigger: "blur"
            }]
          },
          // {
          //   label: "地址",
          //   prop: "avueMap",
          //   type: "map",
          // },
          {
            label: "开始时间",
            prop: "startTime",
            type: "datetime",
            defaultTime: '00:00:00',
            format: "yyyy-MM-dd HH:mm",
            valueFormat: "yyyy-MM-dd HH:mm:ss",
            rules: [{
              required: true,
              message: "请输入开始时间",
              trigger: "blur"
            }],
            width: 120,
          },
          {
            label: "结束时间",
            prop: "endTime",
            type: "datetime",
            defaultTime: '23:59:59',
            format: "yyyy-MM-dd HH:mm",
            valueFormat: "yyyy-MM-dd HH:mm",
            rules: [{
              required: true,
              message: "请输入结束时间",
              trigger: "blur"
            }],
            width: 120,
          },
          // {
          //   label: "",
          //   prop: "map",
          //   labelWidth: 10,
          //   searchSpan: 0,
          //   // maxlength: 5,
          //   hide: true,
          //   span: 3,
          //   // display:false,
          //   component: "AvueMap",
          // },
          {
            label: "活动类型",
            prop: "type",
            type: "select",
            dicUrl: "/api/blade-system/dict-biz/dictionary?code=securityType",
            props: {
              label: "dictValue",
              value: "dictKey"
            },
            rules: [{
              required: true,
              message: "请选择活动类型",
              trigger: "blur"
            }],
            width: 90,
          },
          {
            label: "人数",
            prop: "number",
            width: 60,
          },
          {
            label: "活动内容",
            prop: "content",
            type: "textarea",
            span: 24
          },
        ]
      },
      data: []
    }
  },
  // watch: {
  //   //latitude   longitude   formattedAddress
  //   "form.avueMap":{
  //     handler (newObj) {
  //       if (newObj.length>0) {
  //         this.form.place = newObj[2]
  //         this.form.position = newObj[0]+","+newObj[1]
  //       }
  //     }
  //   }
  // },
  computed: {
    ...mapGetters(["userInfo", "permission"]),
    permissionList() {
      return {
        addBtn: this.vaildData(this.permission.security_add, false),
        viewBtn: this.vaildData(this.permission.security_view, false),
        delBtn: this.vaildData(this.permission.security_delete, false),
        editBtn: this.vaildData(this.permission.security_edit, false)
      }
    },
    ids() {
      let ids = []
      this.selectionList.forEach(ele => {
        ids.push(ele.id)
      })
      return ids.join(",")
    }
  },
  created() {
    const tokenLength = window.location.href.indexOf('=')
    if (tokenLength > 0) {
      //取“=”之后的token
      this.getUserInfo()
    }
  },
  methods: {
    getUserInfo() {
      getUserInfos().then(res => {
        const data = res.data
        this.$store.commit('SET_TOKEN', data.access_token)
        this.$store.commit('SET_REFRESH_TOKEN', data.refresh_token)
        this.$store.commit('SET_TENANT_ID', data.tenant_id)
        this.$store.commit('SET_USER_INFO', data)
        this.$store.commit('DEL_ALL_TAG')
        this.$store.commit('CLEAR_LOCK')
      })
    },
    rowSave(row, done, loading) {
      row.position = row.longitude + " " + row.latitude
      add(row).then(() => {
        this.onLoad(this.page)
        this.$message({
          type: "success",
          message: "操作成功!"
        })
        done()
      }, error => {
        loading()
        window.console.log(error)
      })
    },
    rowUpdate(row, index, done, loading) {
      if (!row.activityArea) {
        this.$message.warning("请绘制活动区域")
        loading()
        return
      }
      if (row.activityArea.startsWith("LINESTRING")){
      }else {
        row.activityArea = "'LINESTRING("+row.activityArea+")'"
      }
      row.position = row.longitude + " " + row.latitude
      update(row).then(() => {
        this.onLoad(this.page)
        this.$message({
          type: "success",
          message: "操作成功!"
        })
        done()
      }, error => {
        loading()
        console.log(error)
      })
    },
    rowDel(row) {
      this.$confirm("确定将选择数据删除?", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      })
        .then(() => {
          return remove(row.id)
        })
        .then(() => {
          this.onLoad(this.page)
          this.$message({
            type: "success",
            message: "操作成功!"
          })
        })
    },
    handleDelete() {
      if (this.selectionList.length === 0) {
        this.$message.warning("请选择至少一条数据")
        return
      }
      this.$confirm("确定将选择数据删除?", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      })
        .then(() => {
          return remove(this.ids)
        })
        .then(() => {
          this.onLoad(this.page)
          this.$message({
            type: "success",
            message: "操作成功!"
          })
          this.$refs.crud.toggleSelection()
        })
    },
    beforeOpen(done, type) {
      if (["edit", "view"].includes(type)) {
        getDetail(this.form.id).then(res => {
          var data = res.data.data
          this.form = data
          this.form['longitude'] = data.position.split(" ")[0]
          this.form['latitude'] = data.position.split(" ")[1]
          this.point = "POINT("+this.form.longitude +" "+this.form.latitude+")"
        })
      }
      done()
    },
    searchReset() {
      this.query = {}
      this.onLoad(this.page)
    },
    searchChange(params, done) {
      this.query = params
      this.page.currentPage = 1
      this.onLoad(this.page, params)
      done()
    },
    selectionChange(list) {
      this.selectionList = list
    },
    selectionClear() {
      this.selectionList = []
      this.$refs.crud.toggleSelection()
    },
    currentChange(currentPage) {
      this.page.currentPage = currentPage
    },
    sizeChange(pageSize) {
      this.page.pageSize = pageSize
    },
    refreshChange() {
      this.onLoad(this.page, this.query)
    },
    onLoad(page, params = {}) {
      this.loading = true
      if (this.userInfo.role_name != "admin" && this.userInfo.role_name != "administrator") {
        params["jurisdiction"] = this.userInfo.dept_id
      }
      getPage(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
        const data = res.data.data
        this.page.total = data.total
        this.data = data.records
        this.loading = false
        this.selectionClear()
      })
    },
    //活动人员区域点击按钮事件
    handlePersonList(row) {
      this.personBox = true
      this.securityId = row.id
    },
    //活动车辆区域点击按钮事件
    handleCarList(row) {
      this.carBox = true
      this.securityId = row.id
    },
    //地图传回的polygon坐标
    toData(data) {
      this.form.activityArea = data
    },
    getLonLat(data){
      this.chosePoint.longitude = data[0]
      this.chosePoint.latitude = data[1]
    },
    confirmLonLat(){
      this.form.longitude =  this.chosePoint.longitude
      this.form.latitude =  this.chosePoint.latitude
      this.point = "POINT("+this.form.longitude +" "+this.form.latitude+")"
      this.placeBox = false
    }
  }
}
</script>
vue.config.js
@@ -4,9 +4,9 @@
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2023-02-09 15:16:33
 * @FilePath: \srs-police-web\vue.config.js
 * @Description:
 *
 * Copyright (c) 2023 by ${git_name_email}, All Rights Reserved.
 * @Description:
 *
 * Copyright (c) 2023 by ${git_name_email}, All Rights Reserved.
 */
module.exports = {
    //路径前缀
@@ -43,7 +43,13 @@
                pathRewrite: {
                    '^/api': '/'
                }
            }
            },
          'bsapi': {
              target: 'http://192.168.0.112:9091',
              pathRewrite: {
                '^/bsapi': '/'
              }
          }
        }
    }
}