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>
|