1114 lines
34 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: 2024-11-20 11:58:33
* @LastEditors: SunTao 328867980@qq.com
* @LastEditTime: 2025-02-21 15:20:25
* @FilePath: \znxjxt-ui\src\views\xj\document\maintenance-notice\components\edit-dialog.vue
* @Description: 养护通知单编辑弹窗
-->
<template>
<div class="edit-dialog">
<el-form class="editForm" ref="editForm" :model="editForm" :rules="rules" label-width="7rem">
<el-row :gutter="24">
<el-col :span="6">
<el-form-item label="路段类型:" prop="diseRoadPosiType">
<el-select v-model="editForm.diseRoadPosiType" placeholder="请选择路段类型" clearable>
<el-option v-for="item in segmentTypeList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="病害成因:" prop="diseCauses">
<el-select v-model="editForm.diseCauses" placeholder="请选择病害成因" clearable>
<el-option v-for="item in causesList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-col>
<!-- <el-col :span="6">
<el-form-item label="病害来源:" prop="diseFrom">
<el-select v-model="editForm.diseFrom" placeholder="请选择病害来源" clearable>
<el-option v-for="item in value4List" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-col> -->
<el-col :span="6">
<el-form-item label="所在路段:" prop="diseRoadPart">
<el-select v-model="editForm.diseRoadPart" placeholder="请选择所在路段" filterable remote clearable reserve-keyword
:filter-method="handleDiseRoadPart" @change="changeDiseRoadPart">
<el-option v-for="(item, index) in roadPartList" :key="`diseRoadPart-name-${index}`" :label="item.label"
:value="item.value"></el-option> </el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="病害类型:" prop="diseFirstType">
<el-select v-model="editForm.diseFirstType" placeholder="请选择病害类型" clearable @change="changeDetailed">
<el-option v-for="item in diseFirstType" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="6">
<el-form-item label="病害二级类型:" prop="diseTypeDetailed">
<el-select v-model="editForm.diseTypeDetailed" placeholder="请选择病害二级类型" filterable clearable>
<el-option v-for="item in diseTypeDetailedList" :key="item.value" :label="item.label"
:value="item.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="工区:" prop="matTaskAreaId">
<el-select v-model="editForm.matTaskAreaId" placeholder="请选择工区" filterable remote clearable reserve-keyword
:filter-method="handleMatTaskArea" @change="changeMatTaskArea">
<el-option v-for="(item, index) in taskAreaList" :key="`taskAreaList-name-${index}`" :label="item.label"
:value="item.value"></el-option> </el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="工作站:" prop="matTWorkStationId">
<el-select v-model="editForm.matTWorkStationId" placeholder="请选择工作站" filterable remote clearable
reserve-keyword :filter-method="handleMatWorkStation" @change="changeMatWorkStation">
<el-option v-for="(item, index) in matWorkStationList" :key="`WorkStationId-name-${index}`"
:label="item.label" :value="item.value"></el-option> </el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="车道:" prop="diseRoadLine">
<el-input v-model="editForm.diseRoadLine" placeholder="请填写车道" clearable>
</el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="6">
<el-form-item label="桥梁:" prop="connBridge" v-if="editForm.diseRoadPosiType !== '1'">
<el-select v-model="editForm.connBridge" placeholder="请选择桥梁" filterable remote clearable reserve-keyword
:filter-method="handleConnBridge" @change="changeConnBridge">
<el-option v-for="(item, index) in connBridgeList" :key="`connBridge-name-${index}`" :label="item.label"
:value="item.value"></el-option> </el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="隧道:" prop="connTunnel" v-if="editForm.diseRoadPosiType !== '1'">
<el-select v-model="editForm.connTunnel" placeholder="请选择隧道" filterable remote clearable reserve-keyword
:filter-method="handleConnTunnel" @change="changeConnTunnel">
<el-option v-for="(item, index) in connTunnelList" :key="`connTunnel-name-${index}`" :label="item.label"
:value="item.value"></el-option> </el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="收费站:" prop="stationCode" v-if="editForm.diseRoadPosiType === '1'">
<el-select v-model="editForm.stationCode" placeholder="请选择收费站" filterable remote clearable reserve-keyword
:filter-method="handleStationCode" @change="changeStationCode">
<el-option v-for="(item, index) in stationCodeList" :key="`stationCode-name-${index}`" :label="item.label"
:value="item.value"></el-option> </el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="收费站位置:" prop="stationLocation" v-if="editForm.diseRoadPosiType === '1'">
<el-select v-model="editForm.stationLocation" placeholder="请选择收费站位置" clearable>
<el-option v-for="item in stationLocationList" :key="item.value" :label="item.label"
:value="item.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="方向:" prop="diseRoadDirec">
<el-select v-model="editForm.diseRoadDirec" placeholder="请选择方向" clearable>
<el-option v-for="item in roadDirectionList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="开始桩号:" prop="diseStartStake">
<el-input v-model="editForm.diseStartStake" placeholder="K0000+000" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="6">
<el-form-item label="结束桩号:" prop="diseEndStake">
<el-input v-model="editForm.diseEndStake" placeholder="K0000+000" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="匝道类型:" prop="rampType">
<el-select v-model="editForm.rampType" placeholder="请选择匝道类型" clearable>
<el-option v-for="item in rampTypeList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="匝道立交:" prop="rampIntOrientation">
<el-select v-model="editForm.rampIntOrientation" placeholder="请选择匝道立交" filterable remote clearable
reserve-keyword :filter-method="handleRampIntOrientation" @change="changeRampIntOrientation">
<el-option v-for="(item, index) in rampIntOrientationList" :key="`rampIntOrientation-name-${index}`"
:label="item.label" :value="item.value"></el-option> </el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="匝道立交方向:" prop="rampInterchangeCode">
<el-select v-model="editForm.rampInterchangeCode" placeholder="请选择匝道立交方向" clearable>
<el-option v-for="item in rampInterchangeCodeList" :key="item.value" :label="item.label"
:value="item.value" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="24"><el-form-item label="详细说明:" prop="diseElaDecs">
<el-input v-model="editForm.diseElaDecs" type="textarea" :rows="3" placeholder="请输入内容" resize="none">
</el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
<el-card shadow="never">
<div slot="header" class="clearfix">
<span style="font-size: 1.2rem">选择病害</span>
<el-button style="float: right; padding: 3px 0" type="text" @click="viewSelected">选择病害</el-button>
<el-button style="float: right; padding: 3px 1rem" type="text" v-if="mapTip"
@click="viewMapSelected(false)">地图查看</el-button>
<el-button style="float: right; padding: 3px 1rem" type="text" v-if="!mapTip"
@click="viewMapSelected(true)">列表查看</el-button>
</div>
<div style="height: 33rem;">
<!-- 列表 -->
<el-table v-if="mapTip" ref="roadTable" :data="checkedDiseaseList" :row-key="getRowKey" height="33rem"
style="width: 100%">
<el-table-column type="selection" :reserve-selection="true" width="55" align="center" />
<el-table-column label="路段名称" align="center" prop="segmentName" />
<el-table-column label="采集时间" align="center" prop="createdTimeLocal">
</el-table-column>
<el-table-column label="病害类型" align="center" prop="defectTypeName">
</el-table-column>
<!-- <el-table-column label="病害状态" align="center" prop="state">
<template slot-scope="scope">
<span>{{ filterState(scope.row.state) }}</span>
</template>
</el-table-column> -->
<el-table-column label="开始桩号" align="center" prop="stakeStart" />
<el-table-column label="结束桩号" align="center" prop="stakeEnd" />
<el-table-column label="病害图片" align="center" prop="media">
<template slot-scope="scope">
<img @click="showScreenImg(scope.row)" height="50" :src="scope.row.mediaUrl" />
</template>
</el-table-column>
<el-table-column label="病害长度" align="center" prop="targetLen">
<template slot-scope="scope">
{{ scope.row.targetLen * 1 <= 0 ? "" : `${scope.row.targetLen}` }} </template>
</el-table-column>
<el-table-column label="病害面积" align="center" prop="targetArea" />
<el-table-column label="道路方向" align="center" prop="inspectDirection">
<template slot-scope="scope">
<span>{{
scope.row.inspectDirection === "0" ? "上行" : "下行"
}}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.$index)">删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 地图 -->
<fssm-map ref="diseaseMap" v-if="!mapTip" @map-zoom="getZoom" @feature-select="featureSelect"></fssm-map>
</div>
</el-card>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
<!-- 查看图片大图 -->
<el-dialog title="查看图片" :visible.sync="showImageDialog" width="85rem" append-to-body destroy-on-close
@close="imgCancel">
<div class="image-container" ref="imageContainer">
<img :src="currentImageItem.mediaUrl" alt="Main Image" ref="mainImage" @load="updateRects" />
<div v-for="(rect, index) in rects" :key="index" class="rect-overlay" :style="getRectStyle(rect)"></div>
<div class="rect-image">
采集时间:
{{ new Date(currentImageItem.createdTime).toLocaleString() }}
起始桩号 {{ currentImageItem.stakeStart || "暂无数据" }} 终止桩号
{{ currentImageItem.stakeEnd || "暂无数据" }}
病害类型
{{ currentImageItem.defectTypeName || "暂无数据" }}
病害面积{{ currentImageItem.targetArea }}平方米 病害长度{{
currentImageItem.targetLen * 1 <= 0 ? "暂无数据" : `${currentImageItem.targetLen}` }} </div>
</div>
</el-dialog>
<!-- 选择病害弹窗 -->
<el-dialog title="选择病害" :visible.sync="diseaseVisible" width="90%" append-to-body :close-on-click-modal="false"
destroy-on-close @close="diseaseCancel">
<disease-dialog :checkedDiseaseList="checkedDiseaseList" :segmentList="segmentList" :tableDefect="tableDefect"
v-if="diseaseVisible" @cancel="diseaseCancel" @checkedList="getCheckedList" />
</el-dialog>
</div>
</template>
<script>
import {
addMaintenanceNotice,
getDiseRoadPartDropDown,
getDiseTypeDetailed,
getTaskareaDropDown,
getWorkstationDropDown,
getBridgeDropDown,
getTunnelDropDown,
getStationDropDown,
getCrossDropDown,
getRampDropDown,
} from "@/api/xj/document";
import FssmScroll from "@/components/scroll/fssm-scroll.vue";
import DiseaseDialog from "./disease-dialog.vue";
import FssmMap from '@/components/map/fssm-map.vue';
import { Feature } from "ol";
import { Point } from "ol/geom";
import { Style, Icon, Fill, Text } from "ol/style";
import VectorSource from "ol/source/Vector";
import VectorLayer from "ol/layer/Vector";
import Cluster from "ol/source/Cluster";
export default {
name: "EditDialog",
components: { FssmScroll, DiseaseDialog, FssmMap },
props: {
dialogItem: {
type: Array,
default: () => [],
},
tableDefect: {
type: Array,
default: () => [],
},
// 病害成因下拉数据
causesList: {
type: Array,
default: () => [],
},
// 病害类型下拉数据
diseFirstType: {
type: Array,
default: () => []
},
// 路段类型下拉数据
segmentTypeList: {
type: Array,
default: () => [],
},
// 匝道类型下拉数据
rampTypeList: {
type: Array,
default: () => [],
},
// 道路方向下拉数据
roadDirectionList: {
type: Array,
default: () => [],
},
// 收费站位置下拉数据
stationLocationList: {
type: Array,
default: () => []
},
segmentList: {
type: Array,
default: () => [],
},
},
data() {
return {
// 编辑表单
editForm: {
// 病害成因
diseCauses: "",
// 路段类型
diseRoadPosiType: "",
// 病害类型
diseFirstType: "",
// 病害二级id
diseTypeDetailed: "",
// 工区id
matTaskAreaId: "",
// 病害来源
diseFrom: "7",
// 工作站id
matTWorkStationId: "",
// 方向
diseRoadDirec: "",
// 车道
diseRoadLine: "",
// 桥梁
connBridge: "",
// 隧道
connTunnel: "",
// 收费站
stationCode: "",
// 收费站位置
stationLocation: "",
// 匝道类型
rampType: "",
// 匝道立交方向
rampInterchangeCode: "",
// 匝道立交
rampIntOrientation: "",
// 病害id
defectId: "",
// 道路名称
segmentId: "",
// 开始桩号
diseStartStake: "",
// 结束桩号
diseEndStake: "",
// 所在路段
diseRoadPart: "",
// 详细描述
diseElaDecs: ""
},
// 病害类型二级下拉数据
diseTypeDetailedList: [],
// 工区下拉数据
taskAreaList: [],
// 病害来源下拉数据
value4List: [],
// 工作站下拉数据
matWorkStationList: [],
// 车道下拉
value7List: [],
// 桥梁下拉
connBridgeList: [],
// 隧道下拉
connTunnelList: [],
// 收费站下拉
stationCodeList: [],
// 匝道立交方向下拉
rampInterchangeCodeList: [],
// 匝道立交下拉
rampIntOrientationList: [],
// 所在路段下拉
roadPartList: [],
// 表格是否显示控制
mapTip: true,
// 已选病害列表
checkedDiseaseList: [],
// 点位图层
clusters: null,
// 地图图层层级
mapZoom: "",
// 查看图片大图弹窗显隐控制
showImageDialog: false,
// 查看大图片路径
currentImageItem: {},
// 图片病害位置信息
rects: [],
// 选择病害弹窗显隐控制
diseaseVisible: false,
};
},
computed: {
rules() {
return {
diseCauses: [
{
required: true,
message: "请选择病害成因",
trigger: "change",
},
],
diseRoadPosiType: [
{ required: true, message: "请选择路段类型", trigger: "change" },
],
diseTypeDetailed: [{ required: true, message: "请选择病害二级类型", trigger: "change" }],
matTaskAreaId: [{ required: true, message: "请选择工区", trigger: "change" }],
diseFirstType: [
{ required: true, message: "请选择病害类型", trigger: "change" },
],
matTWorkStationId: [
{ required: true, message: "请选择工作站", trigger: "change" },
],
diseRoadDirec: [{ required: true, message: "请选择方向", trigger: "change" }],
diseRoadLine: [{ required: true, message: "请选择车道", trigger: "blur" }],
stationCode: [
{ required: true, message: "请选择收费站", trigger: "change" },
],
stationLocation: [
{ required: true, message: "请选择收费站位置", trigger: "change" },
],
rampType: [{ required: true, message: "请选择匝道", trigger: "change" }],
rampInterchangeCode: [
{ required: true, message: "请选择匝道立交方向", trigger: "change" },
],
rampIntOrientation: [
{ required: true, message: "请选择匝道立交", trigger: "change" },
],
segmentId: [
{ required: true, message: "请选择路段", trigger: "change" },
],
diseStartStake: [
{
required: this.isStakeStartRequired,
message: "请输入开始桩号",
trigger: "blur",
},
{
pattern: /^K\d{4}\+\d{3}$/,
message: "请输入正确的桩号格式",
trigger: "blur",
},
],
diseEndStake: [
{
required: this.isStakeStartRequired,
message: "请输入结束桩号",
trigger: "blur",
},
{
pattern: /^K\d{4}\+\d{3}$/,
message: "请输入正确的桩号格式",
trigger: "blur",
},
],
diseRoadPart: [
{ required: true, message: "请选择所在路段", trigger: "change" },
],
}
},
isStakeStartRequired() {
return this.editForm.diseRoadPosiType !== '2'
}
},
watch: {
dialogItem: {
handler(val) {
this.checkedDiseaseList = val
},
deep: true,
immediate: true,
},
},
mounted() {
this.handleDiseRoadPart()
this.handleMatTaskArea()
this.handleMatWorkStation()
this.handleConnBridge()
this.handleConnTunnel()
this.handleStationCode()
this.handleRampIntOrientation()
},
methods: {
/**
* @description: 获取所在路段下拉数据
* @param {*}
* @return {*}
*/
handleDiseRoadPart(str) {
getDiseRoadPartDropDown({ name: str }).then(({ code, data }) => {
if (code === 200) {
this.roadPartList = data
}
})
},
/**
* @description: 修改所在路段事件
* @param {*}
* @return {*}
*/
changeDiseRoadPart(value) {
if (!value) {
this.handleDiseRoadPart()
}
},
/**
* @description: 获取工区下拉数据
* @param {*}
* @return {*}
*/
handleMatTaskArea(str) {
getTaskareaDropDown({ name: str }).then(({ code, data }) => {
if (code === 200) {
this.taskAreaList = data
}
})
},
/**
* @description: 修改工区事件
* @param {*}
* @return {*}
*/
changeMatTaskArea(value) {
if (!value) {
this.handleMatTaskArea()
}
},
/**
* @description: 获取工作站下拉数据
* @param {*}
* @return {*}
*/
handleMatWorkStation(str) {
getWorkstationDropDown({ name: str }).then(({ code, data }) => {
if (code === 200) {
this.matWorkStationList = data
}
})
},
/**
* @description: 工作站修改事件
* @param {*}
* @return {*}
*/
changeMatWorkStation(value) {
if (!value) {
this.handleMatWorkStation()
}
},
/**
* @description: 获取桥梁下拉数据
* @param {*}
* @return {*}
*/
handleConnBridge(str) {
getBridgeDropDown({ name: str }).then(({ code, data }) => {
if (code === 200) {
this.connBridgeList = data
}
})
},
/**
* @description: 桥梁修改事件
* @param {*}
* @return {*}
*/
changeConnBridge(value) {
if (!value) {
this.handleConnBridge()
}
},
/**
* @description: 获取隧道下拉数据
* @param {*}
* @return {*}
*/
handleConnTunnel(str) {
getTunnelDropDown({ name: str }).then(({ code, data }) => {
if (code === 200) {
this.connTunnelList = data
}
})
},
/**
* @description: 隧道修改事件
* @param {*}
* @return {*}
*/
changeConnTunnel(value) {
if (!value) {
this.handleConnTunnel()
}
},
/**
* @description: 获取收费站下拉数据
* @param {*}
* @return {*}
*/
handleStationCode(str) {
getStationDropDown({ name: str }).then(({ code, data }) => {
if (code === 200) {
this.stationCodeList = data
}
})
},
/**
* @description: 收费站修改事件
* @param {*}
* @return {*}
*/
changeStationCode(value) {
if (!value) {
this.handleStationCode()
}
},
/**
* @description: 获取互通立交下拉数据
* @param {*}
* @return {*}
*/
handleRampIntOrientation(str) {
getCrossDropDown({ name: str }).then(({ code, data }) => {
if (code === 200) {
this.rampIntOrientationList = data
}
})
},
/**
* @description: 互通立交修改事件
* @param {*}
* @return {*}
*/
changeRampIntOrientation(value) {
if (!value) {
this.handleRampIntOrientation()
}
this.editForm.rampInterchangeCode = ""
this.handleRampInterchangeCode()
},
/**
* @description: 获取匝道下拉数据
* @param {*}
* @return {*}
*/
handleRampInterchangeCode() {
getRampDropDown({ crossid: this.editForm.rampIntOrientation }).then(({ code, data }) => {
if (code === 200) {
this.rampInterchangeCodeList = data
}
})
},
/**
* @description: 病害类型一级修改事件
* @param {*} row
* @return {*}
*/
changeDetailed(value) {
this.editForm.diseTypeDetailed = "";
const [child] = this.diseFirstType.filter(item => item.value === value)
getDiseTypeDetailed({ parentId: child.key }).then(({ code, data }) => {
if (code === 200) {
this.diseTypeDetailedList = data;
}
})
},
/**
* @description: 列表行绑定id
* @param {*} row
* @return {*}
*/
getRowKey(row) {
return row.snapshotId;
},
/**
* @description: 列表行删除事件
* @param {*} row
* @return {*}
*/
handleDelete(index) {
this.checkedDiseaseList.splice(index, 1);
},
/**
* @description: 取消
*/
cancel() {
this.$emit("cancel");
},
/**
* @description: 提交表单
*/
submitForm() {
this.$refs.editForm.validate((valid) => {
if (valid) {
const defectId = this.checkedDiseaseList?.map(item => item.id)
addMaintenanceNotice({ ...this.editForm, defectId }).then(({ code, data }) => {
if (code === 200) {
this.$message.success("生成成功");
this.$emit("cancel");
} else {
this.$message.error(data);
}
});
}
});
},
/**
* @description: 查看地图的已选中数据
* @param {*}
* @return {*}
*/
viewMapSelected(tip) {
this.mapTip = tip
// 地图打点
if (!tip && this.checkedDiseaseList.length > 0) {
// 修改地图中心点位
const pointArray = this.checkedDiseaseList.map((item) => {
if (item.coordinates) {
return item.coordinates;
}
return [];
});
this.$nextTick(() => {
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]),
];
});
// 获取地图实例
const map = this.$refs.diseaseMap.instance.get("map");
// 使用 fit 方法根据边界框计算最佳缩放级别
map.getView().fit(extent, {
duration: 500, // 动画持续时间
padding: [10, 10, 10, 10], // 边缘填充
});
}
},
/**
* @description: 传回来的地图图层
* @param {number} zoom
* @return {void}
*/
getZoom(zoom) {
this.mapZoom = zoom;
if (this.clusters && zoom * 1 > 15) {
this.clusters.getSource().setDistance(0);
} else if (this.clusters && zoom * 1 <= 15) {
this.clusters.getSource().setDistance(100);
}
},
/**
* @description: 绘制地图点位
* @return {void}
*/
drawPoint() {
const features = [];
this.checkedDiseaseList.forEach((element) => {
// 修改坐标样式
const point = new Point(element.coordinates);
const feature = new Feature({
geometry: point,
data: element,
// 自己设置一个标识
type: "icon",
});
features.push(feature);
});
const clusterSource = new Cluster({
distance: this.mapZoom > 15 ? 0 : 100,
minDistance: this.mapZoom > 15 ? 0 : 100,
source: new VectorSource({
features,
}),
type: "Cluster",
});
this.clusters = new VectorLayer({
source: clusterSource,
name: "clusterLayer",
zIndex: 1,
style: (feature) => {
const count = feature.get("features").length;
if (count > 1) {
return new Style({
image: new Icon({
crossOrigin: "anonymous",
src: require(`@/assets/screen/index/龟裂.png`),
// 图标缩放比例
scale: 0.5,
displacement: [0, 30],
// 0.3为30度
// rotation: 0.3,
}),
text: new Text({
textAlign: "center", //位置
textBaseline: "middle",
font: "normal 14px 微软雅黑",
offsetY: -40,
fill: new Fill({
color: "black",
}),
text: count.toString(),
}),
});
} else {
return new Style({
image: new Icon({
crossOrigin: "anonymous",
src: require(`@/assets/screen/index/${feature.getProperties().features[0].get("data").defectTypeName
|| "龟裂"
}.png`),
// 图标缩放比例
scale: 0.5,
displacement: [0, 30],
// 0.3为30度
// rotation: 0.3,
}),
text: new Text({
textAlign: "center", //位置
textBaseline: "middle",
font: "normal 14px 微软雅黑",
offsetY: -40,
fill: new Fill({
color: "#ffffff",
}),
text: "",
}),
});
}
},
});
this.$nextTick(() => {
const map = this.$refs.diseaseMap.instance.get("map");
map.addLayer(this.clusters);
});
},
/**
* @description: 点击地图图标事件
* @param {*}
* @return {*}
*/
featureSelect(e) {
const map = this.$refs.diseaseMap.instance.get("map");
const selectedFeatures = e.selected;
if (selectedFeatures.length > 0) {
let feature = selectedFeatures[0];
let features = feature.get("features");
if (features.length === 1) {
// 单个点位
// 执行之前的业务逻辑
// 获取点击的图层信息
const selectFeature = feature.getProperties().features[0];
console.log(selectFeature, "点位");
// 获取点位数据
this.currentImageItem = selectFeature.get("data");
this.showImageDialog = true;
// console.log(selectFeature.get("data"));
} else {
// 聚合点
// 放大地图层级
map.getView().animate({
center: feature.getGeometry().getCoordinates(),
zoom: map.getView().getZoom() + 1,
});
}
}
},
/**
* @description: 选择病害弹窗
* @param {*}
* @return {*}
*/
viewSelected() {
this.diseaseVisible = true
},
/**
* @description: 获取选择的病害列表
* @param {*}
* @return {*}
*/
getCheckedList(value) {
this.checkedDiseaseList = value;
this.diseaseVisible = false;
},
/**
* @description: 选择病害弹窗关闭方法
* @param {*}
* @return {*}
*/
diseaseCancel() {
this.diseaseVisible = false
},
/**
* @description: 打开查看图片弹窗
* @param {*} item
* @return {*}
*/
showScreenImg(item) {
this.currentImageItem = item;
this.showImageDialog = true;
},
/**
* @description: 图片位置信息获取
* @param {*} val
* @return {*}
*/
updateRects() {
this.rects = [];
this.rectsItem = {};
const rects = this.currentImageItem?.rect?.split(",").map(Number) || [];
this.rects = [
{
left: rects[0],
top: rects[1],
width: rects[2],
height: rects[3],
},
];
},
/**
* @description: 图片红框位置
* @param {*} left
* @param {*} top
* @param {*} width
* @param {*} height
* @return {*}
*/
getRectStyle({ left, top, width, height }) {
const image = this.$refs.mainImage;
const container = this.$refs.imageContainer;
if (!image || !container) return {};
const scaleX = container.clientWidth / image.naturalWidth;
const scaleY = container.clientHeight / image.naturalHeight;
const scale = Math.min(scaleX, scaleY);
const renderedWidth = image.naturalWidth * scale;
const renderedHeight = image.naturalHeight * scale;
const offsetX = (container.clientWidth - renderedWidth) / 2;
const offsetY = (container.clientHeight - renderedHeight) / 2;
return {
position: "absolute",
left: `${left * scale + offsetX}px`,
top: `${top * scale + offsetY}px`,
width: `${width * scale}px`,
height: `${height * scale}px`,
border: "2px solid #FF0000",
boxSizing: "border-box",
};
},
/**
* @description: 关闭查看图片弹窗
* @param {*} val
* @return {*}
*/
imgCancel() {
if (this.$refs.diseaseMap) {
this.$refs.diseaseMap.removeSelectClick();
}
this.showImageDialog = false;
this.currentImageItem = {};
this.rects = [];
},
},
};
</script>
<style scoped lang="scss">
.edit-dialog {
width: 100%;
height: 100%;
}
.editForm {
.el-select {
width: 100%;
}
.content-box {
display: flex;
span {
font-size: 1.5rem;
line-height: 3rem;
}
.el-icon-circle-plus-outline {
color: #08ce29;
}
.el-icon-delete {
color: #f01515;
}
>div {
margin: 0.5rem 0;
}
}
}
/* 页脚 */
.dialog-footer {
padding: 1rem 0;
display: flex;
justify-content: flex-end;
}
/* 查看大图弹窗 */
.image-container {
position: relative;
width: 100%;
height: 80%;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
}
.image-container img {
max-width: 100%;
max-height: 100%;
object-fit: contain;
}
.rect-overlay {
position: absolute;
pointer-events: none;
border: 2px solid red;
}
// 图片信息
.rect-image {
width: 90%;
position: absolute;
top: 0;
font-size: 1.2rem;
color: #ffffff;
background-color: rgba(0, 0, 0, 0.5);
}
</style>