树形节点优化,对接上传接口
This commit is contained in:
@ -76,6 +76,42 @@ export const upLoadProjectDXF = (data: any) => {
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 通过GeoJson新增设施-光伏板
|
||||
* @param data
|
||||
*/
|
||||
export const addProjectFacilities = (data: any) => {
|
||||
return request({
|
||||
url: '/facility/photovoltaicPanel/geoJson',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 通过GeoJson新增设施-光伏板桩点、立柱、支架
|
||||
* @param data
|
||||
*/
|
||||
export const addProjectPilePoint = (data: any) => {
|
||||
return request({
|
||||
url: '/facility/photovoltaicPanelPoint/parts/geoJson',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 通过GeoJson新增设施-方阵
|
||||
* @param data
|
||||
*/
|
||||
export const addProjectSquare = (data: any) => {
|
||||
return request({
|
||||
url: '/facility/matrix/geoJson',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 删除项目
|
||||
* @param id
|
||||
|
@ -1,13 +1,15 @@
|
||||
<template>
|
||||
<div class="flex justify-between">
|
||||
<div class="flex justify-between" v-loading="treeLoading">
|
||||
<el-tree-v2
|
||||
style="width: 340px; overflow-y: auto"
|
||||
style="width: 340px; overflow: auto"
|
||||
show-checkbox
|
||||
:data="jsonData"
|
||||
:height="500"
|
||||
@check-change="handleCheckChange"
|
||||
:props="treeProps"
|
||||
@node-contextmenu="showMenu"
|
||||
ref="treeRef"
|
||||
@node-click="isMenuVisible = false"
|
||||
>
|
||||
<template #default="{ node, data }">
|
||||
<span @dblclick="handlePosition(data)">{{ data.name }}</span>
|
||||
@ -15,15 +17,28 @@
|
||||
</el-tree-v2>
|
||||
<div>
|
||||
<div class="ol-map" id="olMap"></div>
|
||||
<div class="bg-#909399 p-1 m-0 border-rd c-white w-100 pl-xl mt-2 text-3 pr" v-if="selectLayer.length">
|
||||
<p v-for="(item, index) in selectLayer" class="flex justify-between items-center cursor-pointer" @click="delLayer(index)">
|
||||
{{ item }}
|
||||
<div class="h15" v-if="!selectLayer.length"></div>
|
||||
<div class="m-0 c-white text-3 flex" v-else>
|
||||
<p
|
||||
v-for="(item, index) in selectLayer"
|
||||
class="pl-xl border-rd pr mt-2 p-3 w-111 mr-1 bg-#909399 flex items-center cursor-pointer justify-between"
|
||||
@click="delLayer(index)"
|
||||
>
|
||||
{{ item.location.name + '被选中为' + item.option }}
|
||||
<el-icon>
|
||||
<Close />
|
||||
</el-icon>
|
||||
</p>
|
||||
</div>
|
||||
<el-form-item label="类型" class="items-center">
|
||||
<el-radio-group v-model="layerType">
|
||||
<el-radio value="1" size="large">光伏板</el-radio>
|
||||
<el-radio value="2" size="large">桩点/支架</el-radio>
|
||||
<el-radio value="3" size="large">方阵</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<div v-if="isMenuVisible" :style="{ left: menuX + 'px', top: menuY + 'px' }" class="fixed bg-white shadow-md rounded-md overflow-hidden">
|
||||
<ul class="py-1 pl-0">
|
||||
<li class="px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 cursor-pointer" @click="handleMenuItemClick('光伏板')">
|
||||
@ -41,6 +56,10 @@
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="float-right">
|
||||
<el-button @click="emit('close')">取消</el-button>
|
||||
<el-button type="primary" @click="addFacilities" :loading="loading">确定</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
@ -59,37 +78,47 @@ import { Circle, Style, Stroke, Fill, Icon, Text } from 'ol/style'; // OpenLayer
|
||||
import LineString from 'ol/geom/LineString'; // OpenLayers的线几何类,用于表示线状的地理数据
|
||||
import Polygon from 'ol/geom/Polygon'; // OpenLayers的多边形几何类,用于表示面状的地理数据
|
||||
import * as turf from '@turf/turf';
|
||||
import { SnowflakeIdGenerator } from '@/utils/snowflake';
|
||||
import { TreeInstance } from 'element-plus';
|
||||
import { addProjectFacilities, addProjectPilePoint, addProjectSquare, listDXFProject } from '@/api/project/project';
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
|
||||
const props = defineProps({
|
||||
treeData: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
projectId: String
|
||||
projectId: String,
|
||||
designId: String
|
||||
});
|
||||
const treeData = ref<any>([]);
|
||||
const layerType = ref(null);
|
||||
const contextMenu = ref(null);
|
||||
const selectLayer = ref([]);
|
||||
const treeRef = ref<TreeInstance>();
|
||||
const treeProps = {
|
||||
value: 'name'
|
||||
};
|
||||
const snowflake = new SnowflakeIdGenerator(1, 1);
|
||||
const loading = ref(false);
|
||||
const treeLoading = ref(false);
|
||||
const emit = defineEmits(['handleCheckChange', 'close']);
|
||||
let map: any = null;
|
||||
|
||||
const layerData = reactive<any>({});
|
||||
const centerPosition = ref(fromLonLat([107.13761560163239, 23.80480003743964]));
|
||||
const nodeMenu = (e: any) => {
|
||||
console.log(e);
|
||||
};
|
||||
|
||||
const jsonData = computed(() => {
|
||||
let id = 0;
|
||||
props.treeData.forEach((item: any) => {
|
||||
item.features.forEach((itm) => {
|
||||
let arr = [];
|
||||
treeData.value.forEach((item: any, index: any) => {
|
||||
arr.push({
|
||||
name: item.name,
|
||||
index
|
||||
});
|
||||
for (const itm of item.features) {
|
||||
if (itm.geometry.id) {
|
||||
break;
|
||||
}
|
||||
itm.geometry.id = ++id;
|
||||
itm.geometry.coordinates = convertStrToNum(itm.geometry.coordinates);
|
||||
});
|
||||
}
|
||||
});
|
||||
return props.treeData;
|
||||
return arr; // treeData.value;
|
||||
});
|
||||
console.log(jsonData);
|
||||
|
||||
@ -101,18 +130,20 @@ const handlePosition = (data: any) => {
|
||||
map.getView().setCenter(centerPosition.value);
|
||||
};
|
||||
const handleCheckChange = (data: any, bool) => {
|
||||
let features = treeData.value[data.index].features;
|
||||
if (isMenuVisible.value) isMenuVisible.value = false;
|
||||
if (bool) {
|
||||
if (!layerData[data.features[0].properties.id]) {
|
||||
data.features.forEach((item: any) => {
|
||||
if (!layerData[features[0].properties.id]) {
|
||||
features.forEach((item: any) => {
|
||||
creatPoint(item.geometry.coordinates, item.geometry.type, item.geometry.id, item.properties.text);
|
||||
});
|
||||
} else {
|
||||
data.features.forEach((item: any) => {
|
||||
features.forEach((item: any) => {
|
||||
map.addLayer(layerData[item.geometry.id]);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
data.features.forEach((item, index) => {
|
||||
features.forEach((item, index) => {
|
||||
map.removeLayer(layerData[item.geometry.id]);
|
||||
});
|
||||
}
|
||||
@ -167,23 +198,23 @@ function initOLMap() {
|
||||
});
|
||||
|
||||
// 事件
|
||||
map.on('moveend', (e: any) => {
|
||||
// console.log('地图移动', e);
|
||||
// 获取当前缩放级别
|
||||
var zoomLevel = map.getView().getZoom();
|
||||
// console.log('当前缩放级别:', zoomLevel);
|
||||
});
|
||||
map.on('rendercomplete', () => {
|
||||
// console.log('渲染完成');
|
||||
});
|
||||
map.on('click', (e: any) => {
|
||||
var coordinate = e.coordinate;
|
||||
// map.on('moveend', (e: any) => {
|
||||
// // console.log('地图移动', e);
|
||||
// // 获取当前缩放级别
|
||||
// var zoomLevel = map.getView().getZoom();
|
||||
// // console.log('当前缩放级别:', zoomLevel);
|
||||
// });
|
||||
// map.on('rendercomplete', () => {
|
||||
// // console.log('渲染完成');
|
||||
// });
|
||||
// map.on('click', (e: any) => {
|
||||
// var coordinate = e.coordinate;
|
||||
|
||||
// 将投影坐标转换为经纬度坐标
|
||||
var lonLatCoordinate = toLonLat(coordinate);
|
||||
// 输出转换后的经纬度坐标
|
||||
console.log('经纬度坐标:', lonLatCoordinate);
|
||||
});
|
||||
// // 将投影坐标转换为经纬度坐标
|
||||
// var lonLatCoordinate = toLonLat(coordinate);
|
||||
// // 输出转换后的经纬度坐标
|
||||
// console.log('经纬度坐标:', lonLatCoordinate);
|
||||
// });
|
||||
}
|
||||
|
||||
//递归字符串数组变成数字
|
||||
@ -267,8 +298,8 @@ const menuY = ref(0);
|
||||
|
||||
// 显示菜单的方法
|
||||
const showMenu = (event: MouseEvent, data) => {
|
||||
console.log(data);
|
||||
contextMenu.value = data.name;
|
||||
console.log('🚀 ~ showMenu ~ data:', data, treeData.value[data.index]);
|
||||
contextMenu.value = data;
|
||||
isMenuVisible.value = true;
|
||||
menuX.value = event.clientX;
|
||||
menuY.value = event.clientY;
|
||||
@ -276,13 +307,19 @@ const showMenu = (event: MouseEvent, data) => {
|
||||
|
||||
// 处理菜单项点击事件的方法
|
||||
const handleMenuItemClick = (option: string) => {
|
||||
selectLayer.value.push(`${contextMenu.value}被选中为${option}`);
|
||||
isMenuVisible.value = false;
|
||||
if (selectLayer.value.length == 2) {
|
||||
ElMessage.warning('最多只能选择两个图层');
|
||||
return;
|
||||
}
|
||||
selectLayer.value.push({ location: contextMenu.value, option });
|
||||
emit('handleCheckChange', selectLayer.value);
|
||||
};
|
||||
|
||||
//删除菜单
|
||||
const delLayer = (index) => {
|
||||
selectLayer.value.splice(index, 1);
|
||||
emit('handleCheckChange', selectLayer.value);
|
||||
};
|
||||
|
||||
// 点击页面其他区域隐藏菜单
|
||||
@ -297,29 +334,119 @@ const closeMenuOnClickOutside = (event: MouseEvent) => {
|
||||
|
||||
// 添加全局点击事件监听器
|
||||
window.addEventListener('click', closeMenuOnClickOutside);
|
||||
const getTreeData = async () => {
|
||||
treeLoading.value = true;
|
||||
try {
|
||||
const res = await listDXFProject(props.designId);
|
||||
treeData.value = res.data.layers;
|
||||
treeLoading.value = false;
|
||||
} catch (err) {
|
||||
treeLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 组件卸载时移除事件监听器
|
||||
const onUnmounted = () => {
|
||||
window.removeEventListener('click', closeMenuOnClickOutside);
|
||||
};
|
||||
|
||||
const addFacilities = async () => {
|
||||
console.log(layerType.value);
|
||||
|
||||
if (!layerType.value) {
|
||||
return proxy?.$modal.msgError('请选择图层类型');
|
||||
}
|
||||
if (!selectLayer.value.length) {
|
||||
return proxy?.$modal.msgError('请选择需要上传的图层');
|
||||
}
|
||||
const data = {
|
||||
projectId: props.projectId,
|
||||
nameGeoJson: null,
|
||||
locationGeoJson: null,
|
||||
pointGeoJson: null
|
||||
};
|
||||
|
||||
if (layerType.value == 1) {
|
||||
if (!checkOptions(selectLayer.value, '光伏板')) {
|
||||
return proxy?.$modal.msgError('请选择名称和光伏板');
|
||||
}
|
||||
loading.value = true;
|
||||
if (selectLayer.value[0].option == '名称') {
|
||||
data.nameGeoJson = treeData.value[selectLayer.value[0].location.index];
|
||||
data.locationGeoJson = treeData.value[selectLayer.value[1].location.index];
|
||||
} else {
|
||||
data.nameGeoJson = treeData.value[selectLayer.value[1].location.index];
|
||||
data.locationGeoJson = treeData.value[selectLayer.value[0].location.index];
|
||||
}
|
||||
|
||||
await addProjectFacilities(data);
|
||||
await proxy?.$modal.msgSuccess('添加成功');
|
||||
} else if (layerType.value == 2) {
|
||||
if (selectLayer.value.length > 1) return proxy?.$modal.msgError('最多选择一个桩点/支架');
|
||||
if (selectLayer.value[0].option != '桩点/支架') return proxy?.$modal.msgError('请选择类型为桩点/支架');
|
||||
loading.value = true;
|
||||
data.pointGeoJson = treeData.value[selectLayer.value[0].location.index];
|
||||
await addProjectPilePoint(data);
|
||||
await proxy?.$modal.msgSuccess('添加成功');
|
||||
} else if (layerType.value == 3) {
|
||||
if (!checkOptions(selectLayer.value, '方阵')) {
|
||||
return proxy?.$modal.msgError('请选择名称和方阵');
|
||||
}
|
||||
loading.value = true;
|
||||
if (selectLayer.value[0].option == '名称') {
|
||||
data.nameGeoJson = treeData.value[selectLayer.value[0].location.index];
|
||||
data.locationGeoJson = treeData.value[selectLayer.value[1].location.index];
|
||||
} else {
|
||||
data.nameGeoJson = treeData.value[selectLayer.value[1].location.index];
|
||||
data.locationGeoJson = treeData.value[selectLayer.value[0].location.index];
|
||||
}
|
||||
|
||||
await addProjectSquare(data);
|
||||
await proxy?.$modal.msgSuccess('添加成功');
|
||||
}
|
||||
reset();
|
||||
loading.value = false;
|
||||
};
|
||||
|
||||
const reset = () => {
|
||||
selectLayer.value = [];
|
||||
treeRef.value?.setCheckedKeys([]);
|
||||
for (const key in layerData) {
|
||||
map.removeLayer(layerData[key]);
|
||||
}
|
||||
layerType.value = null;
|
||||
};
|
||||
//校验
|
||||
function checkOptions(arr, type) {
|
||||
let hasName = false;
|
||||
let hasJson = false;
|
||||
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
if (arr[i].option === '名称') {
|
||||
hasName = true;
|
||||
} else if (arr[i].option === type) {
|
||||
hasJson = true;
|
||||
}
|
||||
}
|
||||
|
||||
return hasName && hasJson;
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.designId,
|
||||
(newId, oldId) => {
|
||||
if (newId !== oldId) {
|
||||
reset();
|
||||
getTreeData();
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
// 地图初始化
|
||||
initOLMap();
|
||||
creatPoint(
|
||||
[
|
||||
[
|
||||
[107.13761912095511, 23.80479336386864],
|
||||
[107.13776644838967, 23.804823038597075],
|
||||
[107.13775276784109, 23.80486256412652],
|
||||
[107.1376054403658, 23.80483288938397],
|
||||
[107.13761912095511, 23.80479336386864]
|
||||
]
|
||||
],
|
||||
'Polygon',
|
||||
'1'
|
||||
);
|
||||
// creatPoint([107.13761560163239, 23.80480003743964], 'Point', '2', '点');
|
||||
console.log(props.designId);
|
||||
});
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
|
@ -260,25 +260,28 @@
|
||||
<amap height="620px" @setLocation="setPoi"></amap>
|
||||
</el-dialog>
|
||||
<!-- 选取方阵地址 -->
|
||||
<el-dialog title="设置方阵" v-model="polygonStatus" width="1400px">
|
||||
<open-layers-map :tree-data="jsonData" :project-id="projectId" v-if="polygonStatus"></open-layers-map>
|
||||
<el-radio-group v-model="layerType" class="ml-100">
|
||||
<el-radio value="1" size="large">光伏板</el-radio>
|
||||
<el-radio value="2" size="large">桩点/支架</el-radio>
|
||||
<el-radio value="3" size="large">方阵</el-radio>
|
||||
</el-radio-group>
|
||||
<template #footer>
|
||||
<span>
|
||||
<el-button @click="polygonStatus = false">取消</el-button>
|
||||
<el-button type="primary" @click="">确定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
<el-dialog title="设置方阵" v-model="polygonStatus" width="1400px" :close-on-click-modal="false">
|
||||
<open-layers-map
|
||||
:project-id="projectId"
|
||||
:design-id="designId"
|
||||
@handleCheckChange="setCheckedNodes"
|
||||
@close="polygonStatus = false"
|
||||
></open-layers-map>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="Project" lang="ts">
|
||||
import { addProject, delProject, getProject, listDXFProject, listProject, updateProject } from '@/api/project/project';
|
||||
import {
|
||||
addProject,
|
||||
addProjectFacilities,
|
||||
addProjectPilePoint,
|
||||
addProjectSquare,
|
||||
delProject,
|
||||
getProject,
|
||||
listProject,
|
||||
updateProject
|
||||
} from '@/api/project/project';
|
||||
import { ProjectForm, ProjectQuery, ProjectVO, locationType } from '@/api/project/project/types';
|
||||
import amap from '@/components/amap/index.vue';
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
@ -299,7 +302,9 @@ const projectFormRef = ref<ElFormInstance>();
|
||||
const polygonStatus = ref(false);
|
||||
const dxfFile = ref(null);
|
||||
const projectId = ref<string>('');
|
||||
const layerType = ref(null);
|
||||
const designId = ref<string>('');
|
||||
//被选中的节点
|
||||
const nodes = ref<any>([]);
|
||||
const dialog = reactive<DialogOption>({
|
||||
visible: false,
|
||||
title: ''
|
||||
@ -413,7 +418,52 @@ const setPoi = (location: locationType) => {
|
||||
|
||||
amapStatus.value = false;
|
||||
};
|
||||
|
||||
//设置需要上传的节点
|
||||
const setCheckedNodes = (nodeList: any) => {
|
||||
nodes.value = nodeList;
|
||||
};
|
||||
//上传节点
|
||||
// const addFacilities = async () => {
|
||||
// if (!layerType.value) {
|
||||
// return proxy?.$modal.msgError('请选择图层类型');
|
||||
// }
|
||||
// if (!nodes.value.length) {
|
||||
// return proxy?.$modal.msgError('请选择需要上传的图层');
|
||||
// }
|
||||
// const data = {
|
||||
// projectId: projectId.value,
|
||||
// nameGeoJson: null,
|
||||
// locationGeoJson: null,
|
||||
// pointGeoJson: null
|
||||
// };
|
||||
// loading.value = true;
|
||||
// if (layerType.value == 1) {
|
||||
// if (nodes.value[0].option == '名称') {
|
||||
// data.nameGeoJson = jsonData.value[nodes.value[0].location.index];
|
||||
// data.locationGeoJson = jsonData.value[nodes.value[1].location.index];
|
||||
// } else {
|
||||
// data.nameGeoJson = jsonData.value[nodes.value[1].location.index];
|
||||
// data.locationGeoJson = jsonData.value[nodes.value[0].location.index];
|
||||
// }
|
||||
// await addProjectFacilities(data);
|
||||
// await proxy?.$modal.msgSuccess('添加成功');
|
||||
// } else if (layerType.value == 2) {
|
||||
// data.pointGeoJson = jsonData.value[nodes.value[0].location.index];
|
||||
// await addProjectPilePoint(data);
|
||||
// await proxy?.$modal.msgSuccess('添加成功');
|
||||
// } else if (layerType.value == 3) {
|
||||
// if (nodes.value[0].option == '名称') {
|
||||
// data.nameGeoJson = jsonData.value[nodes.value[0].location.index];
|
||||
// data.locationGeoJson = jsonData.value[nodes.value[1].location.index];
|
||||
// } else {
|
||||
// data.nameGeoJson = jsonData.value[nodes.value[1].location.index];
|
||||
// data.locationGeoJson = jsonData.value[nodes.value[0].location.index];
|
||||
// }
|
||||
// await addProjectSquare(data);
|
||||
// await proxy?.$modal.msgSuccess('添加成功');
|
||||
// }
|
||||
// loading.value = false;
|
||||
// };
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.value.pageNum = 1;
|
||||
@ -463,14 +513,9 @@ const handleShowUpload = (row?: ProjectVO) => {
|
||||
};
|
||||
|
||||
const handleOpenLayer = async (row: ProjectVO) => {
|
||||
if (projectId.value == row.id) return (polygonStatus.value = true);
|
||||
fullscreenLoading.value = true;
|
||||
|
||||
const res = await listDXFProject(row.designId);
|
||||
projectId.value = row.id;
|
||||
jsonData.value = res.data.layers;
|
||||
polygonStatus.value = true;
|
||||
fullscreenLoading.value = false;
|
||||
projectId.value = row.id;
|
||||
designId.value = row.designId;
|
||||
};
|
||||
|
||||
const updateProjectFile = async () => {
|
||||
|
Reference in New Issue
Block a user