225 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			225 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
| <!--
 | ||
|  * @Author: SunTao 328867980@qq.com
 | ||
|  * @Date: 2025-01-02 11:56:20
 | ||
|  * @LastEditors: SunTao 328867980@qq.com
 | ||
|  * @LastEditTime: 2025-01-02 15:54:11
 | ||
|  * @FilePath: \znxjxt-ui\src\views\xj\inspection\task-management\components\task-map.vue
 | ||
|  * @Description: 巡检任务-地图弹窗
 | ||
| -->
 | ||
| <template>
 | ||
|   <div class="content">
 | ||
|     <!-- 多选框切换坐标类型 -->
 | ||
|     <div class="check-box">
 | ||
|       <el-cascader
 | ||
|         ref="screenCascader"
 | ||
|         v-model="mapCareSelect"
 | ||
|         placeholder="病害类型筛选"
 | ||
|         :options="defectCascaderList"
 | ||
|         collapse-tags
 | ||
|         :props="{
 | ||
|           multiple: true,
 | ||
|           emitPath: false,
 | ||
|           children: 'subTypes',
 | ||
|         }"
 | ||
|         @change="changeMapCareSelect"
 | ||
|         clearable
 | ||
|       ></el-cascader>
 | ||
|     </div>
 | ||
|     <fssm-map ref="taskMap"></fssm-map>
 | ||
|   </div>
 | ||
| </template>
 | ||
| 
 | ||
| <script>
 | ||
| // 接口
 | ||
| import { getDefectPoint } from "@/api/xj/task";
 | ||
| import FssmMap from "@/components/map/fssm-map.vue";
 | ||
| import { Feature } from "ol";
 | ||
| import { Point } from "ol/geom";
 | ||
| import VectorSource from "ol/source/Vector";
 | ||
| import VectorLayer from "ol/layer/Vector";
 | ||
| import { Style, Icon } from "ol/style";
 | ||
| export default {
 | ||
|   name: "TaskMap",
 | ||
|   components: {
 | ||
|     FssmMap,
 | ||
|   },
 | ||
|   props: {
 | ||
|     // 弹窗传的数据
 | ||
|     dialogItem: {
 | ||
|       type: Object,
 | ||
|       default: () => {},
 | ||
|     },
 | ||
|     // 病害类型筛选下拉数据
 | ||
|     defectCascaderList: {
 | ||
|       type: Array,
 | ||
|       default: () => [],
 | ||
|     },
 | ||
|   },
 | ||
|   data() {
 | ||
|     return {
 | ||
|       // 病害类型筛选绑定
 | ||
|       mapCareSelect: [],
 | ||
|       // 地图打点图层
 | ||
|       markLayerPoints: null,
 | ||
|       // 中心点集合(过滤后得点位)
 | ||
|       centerPiont: [],
 | ||
|       // 中心点集合(所有点位)
 | ||
|       drawPointList: [],
 | ||
|     };
 | ||
|   },
 | ||
|   mounted() {
 | ||
|     this.getMapPoint();
 | ||
|   },
 | ||
|   methods: {
 | ||
|     /**
 | ||
|      * @description: 病害类型筛选改变事件
 | ||
|      * @return {void}
 | ||
|      */
 | ||
|     changeMapCareSelect(value) {
 | ||
|       if (value.length > 0) {
 | ||
|         this.centerPiont = this.drawPointList.filter((item) => {
 | ||
|           return value.includes(item.iconType);
 | ||
|         });
 | ||
|       } else {
 | ||
|         this.centerPiont = this.drawPointList;
 | ||
|       }
 | ||
|       this.drawPoint();
 | ||
|     },
 | ||
| 
 | ||
|     /**
 | ||
|      * @description: 获取地图点位的方法
 | ||
|      * @return {void}
 | ||
|      */
 | ||
|     getMapPoint() {
 | ||
|       getDefectPoint({ id: this.dialogItem.extId }).then(({ code, data }) => {
 | ||
|         if (code === 200) {
 | ||
|           this.drawPointList = data.map((item) => {
 | ||
|             if (item.geometry) {
 | ||
|               return {
 | ||
|                 ...item,
 | ||
|                 geometry: [item.geometry[0], item.geometry[1]],
 | ||
|               };
 | ||
|             }
 | ||
|             return [];
 | ||
|           });
 | ||
|           this.centerPiont = data.map((item) => {
 | ||
|             if (item.geometry) {
 | ||
|               return {
 | ||
|                 ...item,
 | ||
|                 geometry: [item.geometry[0], item.geometry[1]],
 | ||
|               };
 | ||
|             }
 | ||
|             return [];
 | ||
|           });
 | ||
|           // 如果不是病害巡检,则绘制点位
 | ||
|           // 如果图片弹窗打开,则绘制点位
 | ||
|           // if (!this.shouldLoadClusters) {
 | ||
|           // 修改地图中心点位
 | ||
|           const pointArray = data.map((item) => {
 | ||
|             if (item.geometry) {
 | ||
|               return [item.geometry[0], item.geometry[1]];
 | ||
|             }
 | ||
|             return [];
 | ||
|           });
 | ||
|           this.fitMapToPoints(pointArray);
 | ||
|           this.drawPoint();
 | ||
|           // }
 | ||
|         }
 | ||
|       });
 | ||
|     },
 | ||
| 
 | ||
|     /**
 | ||
|      * @description: 根据点位计算地图中心点
 | ||
|      * @return {void}
 | ||
|      */
 | ||
|     fitMapToPoints(points) {
 | ||
|       if (points.length > 0) {
 | ||
|         // 创建一个空的 extent
 | ||
|         let extent = [Infinity, Infinity, -Infinity, -Infinity];
 | ||
|         // 计算所有点的边界框(extent)
 | ||
|         points.forEach((point) => {
 | ||
|           extent = [
 | ||
|             Math.min(extent[0], point[0]),
 | ||
|             Math.min(extent[1], point[1]),
 | ||
|             Math.max(extent[2], point[0]),
 | ||
|             Math.max(extent[3], point[1]),
 | ||
|           ];
 | ||
|         });
 | ||
|         this.$nextTick(() => {
 | ||
|           // 获取地图实例
 | ||
|           const map = this.$refs.taskMap.instance.get("map");
 | ||
| 
 | ||
|           // 使用 fit 方法根据边界框计算最佳缩放级别
 | ||
|           map.getView().fit(extent, {
 | ||
|             duration: 500, // 动画持续时间
 | ||
|             padding: [10, 10, 10, 10], // 边缘填充
 | ||
|           });
 | ||
|         });
 | ||
|       }
 | ||
|     },
 | ||
| 
 | ||
|     /**
 | ||
|      * @description: 绘制地图点位
 | ||
|      * @return {void}
 | ||
|      */
 | ||
|     drawPoint() {
 | ||
|       const features = [];
 | ||
|       this.centerPiont.forEach((element) => {
 | ||
|         // 修改坐标样式
 | ||
|         const point = new Point(element.geometry);
 | ||
|         const feature = new Feature({
 | ||
|           geometry: point,
 | ||
|           data: element,
 | ||
|           // 自己设置一个标识
 | ||
|           type: "icon",
 | ||
|         });
 | ||
|         // 设置点位样式
 | ||
|         feature.setStyle([
 | ||
|           new Style({
 | ||
|             image: new Icon({
 | ||
|               crossOrigin: "anonymous",
 | ||
|               src: require(`@/assets/screen/index/${element.iconTypeName}.png`),
 | ||
|               // size: [40, 40],
 | ||
|               scale: 0.5, // 图标缩放比例
 | ||
|               displacement: [0, 30],
 | ||
|             }),
 | ||
|           }),
 | ||
|         ]);
 | ||
|         features.push(feature);
 | ||
|       });
 | ||
|       //设置地图的数据源
 | ||
|       const pointSource = new VectorSource({
 | ||
|         features,
 | ||
|       });
 | ||
|       if (!this.markLayerPoints) {
 | ||
|         this.markLayerPoints = new VectorLayer({
 | ||
|           source: pointSource,
 | ||
|           properties: {
 | ||
|             type: "point",
 | ||
|           },
 | ||
|         });
 | ||
|         this.$nextTick(() => {
 | ||
|           const map = this.$refs.taskMap.instance.get("map");
 | ||
|           map.addLayer(this.markLayerPoints);
 | ||
|         });
 | ||
|       } else {
 | ||
|         this.markLayerPoints.setSource(pointSource);
 | ||
|       }
 | ||
|     },
 | ||
|   },
 | ||
| };
 | ||
| </script>
 | ||
| 
 | ||
| <style lang="scss" scoped>
 | ||
| .content {
 | ||
|   width: 100%;
 | ||
|   height: 45rem;
 | ||
|   position: relative;
 | ||
| 
 | ||
|   .check-box {
 | ||
|     position: absolute;
 | ||
|     z-index: 1;
 | ||
|   }
 | ||
| }
 | ||
| </style>
 |