225 lines
5.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!--
* @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>