From 8e3865214943c20e1269a06d6e1cbbc4c8c7890f Mon Sep 17 00:00:00 2001
From: guanqb <18720758508@163.com>
Date: Tue, 16 Jan 2024 16:02:46 +0800
Subject: [PATCH] 派遣服务地图标点
---
public/img/map/unit.png | 0
src/views/dispatch/components/OlMapBox.vue | 428 +++++++++++++++++++++++++++++++++++++++++++++++
src/api/dispatch/dispatch.js | 11 +
src/views/dispatch/dispatchView.vue | 40 ++-
src/views/dispatch/components/dispatchMap.vue | 23 +
5 files changed, 477 insertions(+), 25 deletions(-)
diff --git a/public/img/map/unit.png b/public/img/map/unit.png
new file mode 100644
index 0000000..d5435a6
--- /dev/null
+++ b/public/img/map/unit.png
Binary files differ
diff --git a/src/api/dispatch/dispatch.js b/src/api/dispatch/dispatch.js
index e9283f4..50e57c6 100644
--- a/src/api/dispatch/dispatch.js
+++ b/src/api/dispatch/dispatch.js
@@ -1,4 +1,4 @@
-import request from '@/router/axios';
+import request from '@/router/axios'
export const getdata = (current, size, params) => {
return request({
@@ -12,6 +12,15 @@
})
}
+export const getAlldata = (params) => {//不分页
+ return request({
+ url: '/api/dispatcherUnit/getAll',
+ method: 'get',
+ params: {
+ ...params
+ }
+ })
+}
export const getDispatcherUnitByDeptId = (deptId) => {
return request({
diff --git a/src/views/dispatch/components/OlMapBox.vue b/src/views/dispatch/components/OlMapBox.vue
new file mode 100644
index 0000000..2292e3d
--- /dev/null
+++ b/src/views/dispatch/components/OlMapBox.vue
@@ -0,0 +1,428 @@
+<!--
+ * @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 id="popup" class="ol-popup" v-show="isShowUnitInfoPopover">
+ <a href="#" id="popup-closer" class="ol-popup-closer"></a>
+ <div id="popup-content">
+ <p>负责人:{{ unitData.securityLinkman }}</p>
+ <p>联系方式:{{ unitData.cell }}</p>
+ <p>派遣保安员数:{{ unitData.num }}</p>
+ <p>派遣单位行业:{{ unitData.professionName }}</p>
+ </div>
+ </div>
+ </div>
+</template>
+
+<script>
+import "ol/ol.css"
+import OlView from "ol/View.js"
+import OlLayerTile from "ol/layer/Tile.js"
+import Overlay from "ol/Overlay.js"
+import OlMap from "ol/Map.js"
+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 Feature from 'ol/Feature.js'
+import Point from 'ol/geom/Point.js'
+import { Icon, Style, Fill, Text, Stroke, Circle } from 'ol/style.js'
+import { getAlldata } from "@/api/dispatch/dispatch"
+import { mapGetters } from "vuex"
+import { mapState } from "vuex"
+
+let mapView = null
+let layersObjcect = {}
+
+let baseMapLayer = {
+ yx: [],
+ sl: []
+}
+
+let unitInfoPopover = null
+
+export default {
+ name: 'OlMapBox',
+
+ props: {
+ mapType: {
+ type: String,
+ default: 'sl'
+ },
+
+ mapContrast: {
+ type: String,
+ default: 'custom'
+ }
+ },
+
+ data () {
+ return {
+ publicPath: process.env.BASE_URL,
+ unitData: {},
+ isShowUnitInfoPopover: false
+ }
+ },
+
+ computed: {
+ ...mapGetters(["permission", "userInfo"]),
+
+ ...mapState({
+ userInfo: state => state.user.userInfo
+ })
+ },
+ mounted () {
+ const that = this
+
+ this.$nextTick(() => {
+ mapView = new OlMap({
+ target: 'OlMapBoxElement',
+ layers: [],
+ view: new OlView({
+ // 初始化中心点坐标,经纬度一会自己换一下
+ center: [112.85857823133, 35.496284586473],
+ zoom: 18,
+ projection: "EPSG:4326"
+ }),
+ })
+
+ mapView.on("singleclick", function (event) {
+ mapView.forEachFeatureAtPixel(
+ event.pixel,
+ (feature) => {
+ feature.dispatchEvent && feature.dispatchEvent({ type: 'click', event: event })
+ }
+ )
+ })
+
+ mapView.getView().on('change:resolution', function () {
+ // console.log('mapView地图缩放事件')
+ })
+
+ that.getAlldata()
+ that.baseInitLayer(that.mapType)
+ })
+ },
+
+ methods: {
+ // 图标点击事件
+ pqfwIconClick (e) {
+ this.generateMapPopup(e)
+ },
+
+ // 获取派遣服务列表
+ getAlldata () {
+ let params = {}
+ let roleName = this.userInfo.role_name
+ if (
+ roleName == "保安公司管理员" ||
+ roleName == "保安" ||
+ roleName == "分公司管理员"
+ ) {
+ params.deptId = this.userInfo.dept_id
+ } else if (roleName == "公安管理员" || roleName == "administrator" || roleName == "民警") {
+ params.jurisdiction = this.userInfo.jurisdiction
+ }
+ getAlldata(params).then(res => {
+ this.$nextTick(() => {
+ this.mapRemoveLayer(['pqfwLayer'])
+ this.mapAddClusterLayer('pqfwLayer', 'img/map/unit.png', res.data.data, this.pqfwIconClick)
+ })
+ })
+ },
+
+ /**
+ * @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 || [32, 32],
+ 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 }),
+ // offsetX: -60,
+ offsetY: 30
+ })
+ }
+
+ iconFeature.setStyle(new Style(styleOptions))
+
+ iconFeature.on('click', (e) => {
+ if (params.event) {//icon事件参数
+ params.event(e.target.values_.attributes)//点击事件触发事件并传参
+ }
+ })
+ 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]) {
+ 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.longitude,
+ lat: item.latitude,
+ text: item.name,
+ url: imgUrl,
+ event: incident
+ }))
+ })
+ mapView.getView().animate({ // 只设置需要的属性即可
+ center: [positionData[0].longitude, positionData[0].latitude], // 中心点
+ // zoom: 18, // 缩放级别
+ rotation: undefined, // 缩放完成view视图旋转弧度
+ // duration: 1000 // 缩放持续时间,默认不需要设置
+ })
+ },
+
+ // 生成地图弹窗
+ generateMapPopup (e) {
+ const that = this
+ this.unitData = e
+ this.isShowUnitInfoPopover = true
+ var container = document.getElementById('popup')
+ var closer = document.getElementById('popup-closer')
+
+ // 创建popup
+ unitInfoPopover = new Overlay({
+ element: container,
+ autoPan: true,
+ positioning: 'bottom-center',
+ stopEvent: false,
+ autoPanAnimation: {
+ duration: 250
+ }
+ })
+ mapView.addOverlay(unitInfoPopover)
+ closer.onclick = function () {
+ unitInfoPopover.setPosition(undefined)
+ closer.blur()
+ return false
+ }
+ unitInfoPopover.setPosition([e.longitude, e.latitude])
+ },
+
+
+ }
+}
+</script>
+
+<style lang='scss' scope>
+.w100 {
+ width: 100%;
+}
+
+.h100 {
+ height: 100%;
+}
+
+.ol-popup {
+ position: absolute;
+ background-color: white;
+ -webkit-filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.2));
+ filter: drop-shadow(0 1px 4px #FFC125);
+ padding: 15px;
+ border-radius: 10px;
+ border: 1px solid #cccccc;
+ bottom: 34px;
+ left: -46px;
+ min-width: 300px;
+}
+
+.ol-popup:after,
+.ol-popup:before {
+ top: 100%;
+ border: solid transparent;
+ content: " ";
+ height: 0;
+ width: 0;
+ position: absolute;
+ pointer-events: none;
+}
+
+.ol-popup:after {
+ border-top-color: white;
+ border-width: 10px;
+ left: 48px;
+ margin-left: -10px;
+}
+
+.ol-popup:before {
+ border-top-color: #cccccc;
+ border-width: 11px;
+ left: 48px;
+ margin-left: -11px;
+}
+
+.ol-popup-closer {
+ text-decoration: none;
+ position: absolute;
+ top: 2px;
+ right: 8px;
+ color: red;
+}
+
+.ol-popup-closer:after {
+ content: "✖";
+}
+</style>
diff --git a/src/views/dispatch/components/dispatchMap.vue b/src/views/dispatch/components/dispatchMap.vue
index 6d81b3a..3c3317e 100644
--- a/src/views/dispatch/components/dispatchMap.vue
+++ b/src/views/dispatch/components/dispatchMap.vue
@@ -1,15 +1,24 @@
<template>
- <div>
- 222
- </div>
+ <div style="width: 100%; height: 100%;">
+ <OlMapBox ref="olmapboxelement"></OlMapBox>
+ </div>
</template>
<script>
+import OlMapBox from "./OlMapBox.vue"
+
export default {
- name: "dispatchMap"
+ name: "dispatchMap",
+ components: { OlMapBox },
+
+ mounted () {
+ this.$nextTick(() => {
+ this.$refs.olmapboxelement.getAlldata()
+ })
+ }
}
+
+
</script>
-<style scoped>
-
-</style>
+<style scoped></style>
diff --git a/src/views/dispatch/dispatchView.vue b/src/views/dispatch/dispatchView.vue
index 10a17d8..e4de296 100644
--- a/src/views/dispatch/dispatchView.vue
+++ b/src/views/dispatch/dispatchView.vue
@@ -1,29 +1,35 @@
<template>
- <el-tabs v-model="activeName" >
- <el-tab-pane label="列表展示" name="list">
- <dispatch-list></dispatch-list>
- </el-tab-pane>
- <el-tab-pane label="地图展示" name="map">
- <dispatch-map></dispatch-map>
- </el-tab-pane>
- </el-tabs>
+ <el-tabs v-model="activeName" style="height: 100%;">
+ <el-tab-pane label="列表展示" name="list">
+ <dispatch-list></dispatch-list>
+ </el-tab-pane>
+ <el-tab-pane label="地图展示" name="map">
+ <dispatch-map :key="new Date().getTime()"></dispatch-map>
+ </el-tab-pane>
+ </el-tabs>
</template>
<script>
-import DispatchMap from "@/views/dispatch/components/dispatchMap.vue";
-import DispatchList from "@/views/dispatch/dispatch.vue";
+import DispatchMap from "@/views/dispatch/components/dispatchMap.vue"
+import DispatchList from "@/views/dispatch/dispatch.vue"
export default {
- name: "dispatchView",
- components: {DispatchList, DispatchMap},
- data(){
- return{
- activeName: 'list'
+ name: "dispatchView",
+ components: { DispatchList, DispatchMap },
+ data () {
+ return {
+ activeName: 'list'
+ }
}
- }
}
</script>
-<style scoped>
+<style lang="scss"scoped>
+::v-deep .el-tabs__content {
+ height: calc(100% - 55px);
+}
+::v-deep .el-tab-pane {
+ height: 100%;
+}
</style>
--
Gitblit v1.9.3