使用异步处理优化DXF 转 GeoJSON接口响应速度;修改部分逻辑,添加删除功能相关校验

This commit is contained in:
lcj
2025-04-25 15:52:48 +08:00
parent 8abe7be454
commit 19754c1ca9
16 changed files with 316 additions and 70 deletions

View File

@ -3,13 +3,14 @@ package org.dromara;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup; import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup;
import org.springframework.scheduling.annotation.EnableAsync;
/** /**
* 启动程序 * 启动程序
* *
* @author Lion Li * @author Lion Li
*/ */
@EnableAsync
@SpringBootApplication @SpringBootApplication
public class DromaraApplication { public class DromaraApplication {

View File

@ -6,9 +6,9 @@ import java.io.File;
* @author lcj * @author lcj
* @date 2025/4/23 11:09 * @date 2025/4/23 11:09
*/ */
public interface DxfFileConstant { public interface DesignMapFileConstant {
String DXF_BASE_PATH = "file" + File.separator + "resource" + File.separator + "dxf"; String DXF_BASE_PATH = "file" + File.separator + "resource" + File.separator + "design";
/** /**
* WGS 84 * WGS 84
@ -17,6 +17,10 @@ public interface DxfFileConstant {
String EPSG4524 = "4524"; String EPSG4524 = "4524";
String DXFFileSuffix = "dxf";
String JSONFileSuffix = "json";
static String getDxfProjectPath(Long projectId) { static String getDxfProjectPath(Long projectId) {
return DXF_BASE_PATH + File.separator + projectId; return DXF_BASE_PATH + File.separator + projectId;
} }

View File

@ -3,6 +3,8 @@ package org.dromara.facility.service;
import org.dromara.facility.domain.req.photovoltaicpanelparts.PhotovoltaicPanelPartsCreateByGeoJsonReq; import org.dromara.facility.domain.req.photovoltaicpanelparts.PhotovoltaicPanelPartsCreateByGeoJsonReq;
import org.dromara.facility.domain.req.photovoltaicpanelparts.PhotovoltaicPanelPartsCreateReq; import org.dromara.facility.domain.req.photovoltaicpanelparts.PhotovoltaicPanelPartsCreateReq;
import java.util.Collection;
/** /**
* 设施-光伏板桩点、立柱、支架Service接口 * 设施-光伏板桩点、立柱、支架Service接口
* *
@ -27,4 +29,22 @@ public interface IFacPhotovoltaicPanelPartsService {
*/ */
Boolean insertPartsByBatch(PhotovoltaicPanelPartsCreateReq req); Boolean insertPartsByBatch(PhotovoltaicPanelPartsCreateReq req);
/**
* 根据方阵主键判断是否存在光伏板点
*
* @param projectId 项目id
* @param matrixIds 方阵Id列表
* @return 是否存在
*/
Boolean validPartsExistByMatrix(Long projectId, Collection<Long> matrixIds);
/**
* 根据光伏板名称判断是否存在光伏板点
*
* @param projectId 项目id
* @param photovoltaicPanelNames 光伏板名称列表
* @return 是否存在
*/
Boolean validPartsExistByPhotovoltaicPanel(Long projectId, Collection<String> photovoltaicPanelNames);
} }

View File

@ -12,6 +12,7 @@ import org.dromara.common.core.utils.ObjectUtils;
import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.facility.domain.FacBoxTransformer; import org.dromara.facility.domain.FacBoxTransformer;
import org.dromara.facility.domain.req.boxtransformer.BoxTransformerCreateReq; import org.dromara.facility.domain.req.boxtransformer.BoxTransformerCreateReq;
import org.dromara.facility.domain.req.boxtransformer.BoxTransformerQueryReq; import org.dromara.facility.domain.req.boxtransformer.BoxTransformerQueryReq;
@ -194,8 +195,12 @@ public class FacBoxTransformerServiceImpl extends ServiceImpl<FacBoxTransformerM
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) { public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
Long userId = LoginHelper.getUserId();
List<FacBoxTransformer> boxTransformerList = this.listByIds(ids);
if (isValid) { if (isValid) {
//TODO 做一些业务上的校验,判断是否需要校验 //TODO 做一些业务上的校验,判断是否需要校验
List<Long> projectId = boxTransformerList.stream().map(FacBoxTransformer::getProjectId).toList();
projectService.validAuth(projectId, userId);
} }
return this.removeBatchByIds(ids); return this.removeBatchByIds(ids);
} }

View File

@ -12,6 +12,7 @@ import org.dromara.common.core.utils.ObjectUtils;
import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.facility.domain.FacInverter; import org.dromara.facility.domain.FacInverter;
import org.dromara.facility.domain.req.inverter.InverterCreateReq; import org.dromara.facility.domain.req.inverter.InverterCreateReq;
import org.dromara.facility.domain.req.inverter.InverterQueryReq; import org.dromara.facility.domain.req.inverter.InverterQueryReq;
@ -194,8 +195,12 @@ public class FacInverterServiceImpl extends ServiceImpl<FacInverterMapper, FacIn
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) { public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
Long userId = LoginHelper.getUserId();
List<FacInverter> inverterList = this.listByIds(ids);
if (isValid) { if (isValid) {
//TODO 做一些业务上的校验,判断是否需要校验 //TODO 做一些业务上的校验,判断是否需要校验
List<Long> projectId = inverterList.stream().map(FacInverter::getProjectId).toList();
projectService.validAuth(projectId, userId);
} }
return this.removeBatchByIds(ids); return this.removeBatchByIds(ids);
} }

View File

@ -12,8 +12,11 @@ import org.dromara.common.core.utils.ObjectUtils;
import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.constant.GeoJsonConstant; import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.facility.domain.FacBoxTransformer;
import org.dromara.facility.domain.FacInverter;
import org.dromara.facility.domain.FacMatrix; import org.dromara.facility.domain.FacMatrix;
import org.dromara.facility.domain.FacPhotovoltaicPanel;
import org.dromara.facility.domain.req.geojson.Feature; import org.dromara.facility.domain.req.geojson.Feature;
import org.dromara.facility.domain.req.geojson.FeatureByPoint; import org.dromara.facility.domain.req.geojson.FeatureByPoint;
import org.dromara.facility.domain.req.geojson.Geometry; import org.dromara.facility.domain.req.geojson.Geometry;
@ -23,17 +26,17 @@ import org.dromara.facility.domain.req.matrix.MatrixQueryReq;
import org.dromara.facility.domain.req.matrix.MatrixUpdateReq; import org.dromara.facility.domain.req.matrix.MatrixUpdateReq;
import org.dromara.facility.domain.vo.FacMatrixVo; import org.dromara.facility.domain.vo.FacMatrixVo;
import org.dromara.facility.mapper.FacMatrixMapper; import org.dromara.facility.mapper.FacMatrixMapper;
import org.dromara.facility.service.IFacMatrixService; import org.dromara.facility.service.*;
import org.dromara.project.service.IBusProjectService; import org.dromara.project.service.IBusProjectService;
import org.dromara.utils.GeoJsonUtils; import org.dromara.utils.GeoJsonUtils;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
/** /**
* 设施-方阵Service业务层处理 * 设施-方阵Service业务层处理
@ -47,6 +50,22 @@ public class FacMatrixServiceImpl extends ServiceImpl<FacMatrixMapper, FacMatrix
@Resource @Resource
private IBusProjectService projectService; private IBusProjectService projectService;
@Lazy
@Resource
private IFacPhotovoltaicPanelService photovoltaicPanelService;
@Lazy
@Resource
private IFacPhotovoltaicPanelPartsService photovoltaicPanelPartsService;
@Lazy
@Resource
private IFacBoxTransformerService boxTransformerService;
@Lazy
@Resource
private IFacInverterService inverterService;
/** /**
* 查询设施-方阵 * 查询设施-方阵
* *
@ -138,40 +157,15 @@ public class FacMatrixServiceImpl extends ServiceImpl<FacMatrixMapper, FacMatrix
List<FacMatrix> matrixList = new ArrayList<>(); List<FacMatrix> matrixList = new ArrayList<>();
List<Feature> locationFeatures = geoJson.getLocationGeoJson().getFeatures(); List<Feature> locationFeatures = geoJson.getLocationGeoJson().getFeatures();
List<FeatureByPoint> nameFeatures = geoJson.getNameGeoJson().getFeatures(); List<FeatureByPoint> nameFeatures = geoJson.getNameGeoJson().getFeatures();
// 遍历位置信息
for (Feature feature : locationFeatures) { for (Feature feature : locationFeatures) {
FacMatrix matrix = new FacMatrix(); FacMatrix matrix = new FacMatrix();
matrix.setProjectId(projectId); matrix.setProjectId(projectId);
Geometry geometry = feature.getGeometry(); Geometry geometry = feature.getGeometry();
List<Object> coordinates = geometry.getCoordinates(); // 获取坐标信息
if (geometry.getType().equals(GeoJsonConstant.POINT)) { List<List<Double>> coordinatesList = GeoJsonUtils.getTwoDimensionalCoordinates(geometry);
throw new ServiceException("点位无法创建方阵", HttpStatus.BAD_REQUEST);
}
// 获取方阵名称 // 获取方阵名称
String name = null; String name = null;
List<List<Double>> coordinatesList = new ArrayList<>();
if (geometry.getType().equals(GeoJsonConstant.LINE)) {
for (Object obj : coordinates) {
if (obj instanceof List<?> innerList) {
List<Double> point = new ArrayList<>();
for (Object num : innerList) {
if (num instanceof Number) {
point.add(((Number) num).doubleValue());
}
}
coordinatesList.add(point);
}
}
} else if (geometry.getType().equals(GeoJsonConstant.POLYGON)) {
coordinatesList = coordinates.stream()
.filter(obj -> obj instanceof List<?>)
.flatMap(obj -> ((List<?>) obj).stream())
.filter(pointObj -> pointObj instanceof List<?>)
.map(pointObj -> ((List<?>) pointObj).stream()
.filter(num -> num instanceof Number)
.map(num -> ((Number) num).doubleValue())
.collect(Collectors.toList()))
.collect(Collectors.toList());
}
for (FeatureByPoint nameFeature : nameFeatures) { for (FeatureByPoint nameFeature : nameFeatures) {
List<Double> nameCoordinates = nameFeature.getGeometry().getCoordinates(); List<Double> nameCoordinates = nameFeature.getGeometry().getCoordinates();
Boolean result = GeoJsonUtils.pointIsWithInPlane(coordinatesList, nameCoordinates); Boolean result = GeoJsonUtils.pointIsWithInPlane(coordinatesList, nameCoordinates);
@ -183,7 +177,8 @@ public class FacMatrixServiceImpl extends ServiceImpl<FacMatrixMapper, FacMatrix
if (name == null) { if (name == null) {
continue; continue;
} }
String positionStr = JSONUtil.toJsonStr(coordinates); // 将位置信息转换为 JSON 字符串
String positionStr = JSONUtil.toJsonStr(coordinatesList);
matrix.setPositions(positionStr); matrix.setPositions(positionStr);
matrix.setMatrixName(name); matrix.setMatrixName(name);
matrixList.add(matrix); matrixList.add(matrix);
@ -265,8 +260,42 @@ public class FacMatrixServiceImpl extends ServiceImpl<FacMatrixMapper, FacMatrix
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) { public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
Long userId = LoginHelper.getUserId();
List<FacMatrix> matrixList = this.listByIds(ids);
if (isValid) { if (isValid) {
//TODO 做一些业务上的校验,判断是否需要校验 //TODO 做一些业务上的校验,判断是否需要校验
List<Long> projectIds = matrixList.stream().map(FacMatrix::getProjectId).distinct().toList();
if (CollUtil.isNotEmpty(projectIds) && projectIds.size() > 1) {
throw new ServiceException("仅能删除单个项目下的方阵", HttpStatus.BAD_REQUEST);
}
Long projectId = projectIds.get(0);
projectService.validAuth(projectId, userId);
// 判断方阵下是否存在光伏板信息
Long photovoltaicPanelCount = photovoltaicPanelService.lambdaQuery()
.eq(FacPhotovoltaicPanel::getProjectId, projectId)
.in(FacPhotovoltaicPanel::getMatrixId, ids).count();
if (photovoltaicPanelCount > 0) {
throw new ServiceException("删除失败,方阵下存在光伏板信息", HttpStatus.CONFLICT);
}
// 判断方阵下是否存在箱变信息
Long boxTransformerCount = boxTransformerService.lambdaQuery()
.eq(FacBoxTransformer::getProjectId, projectId)
.in(FacBoxTransformer::getMatrixId, ids).count();
if (boxTransformerCount > 0) {
throw new ServiceException("删除失败,方阵下存在箱变信息", HttpStatus.CONFLICT);
}
// 判断方阵下是否存在逆变器信息
Long inverterCount = inverterService.lambdaQuery()
.eq(FacInverter::getProjectId, projectId)
.in(FacInverter::getMatrixId, ids).count();
if (inverterCount > 0) {
throw new ServiceException("删除失败,方阵下存在逆变器信息", HttpStatus.CONFLICT);
}
// 判断方阵下是否存在光伏板点信息
Boolean result = photovoltaicPanelPartsService.validPartsExistByMatrix(projectId, ids);
if (result) {
throw new ServiceException("删除失败,方阵下存在光伏板点信息", HttpStatus.CONFLICT);
}
} }
return this.removeBatchByIds(ids); return this.removeBatchByIds(ids);
} }

View File

@ -12,6 +12,7 @@ import org.dromara.common.core.utils.ObjectUtils;
import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.facility.domain.FacPhotovoltaicPanelColumn; import org.dromara.facility.domain.FacPhotovoltaicPanelColumn;
import org.dromara.facility.domain.req.photovoltaicpanelcolumn.PhotovoltaicPanelColumnCreateReq; import org.dromara.facility.domain.req.photovoltaicpanelcolumn.PhotovoltaicPanelColumnCreateReq;
import org.dromara.facility.domain.req.photovoltaicpanelcolumn.PhotovoltaicPanelColumnQueryReq; import org.dromara.facility.domain.req.photovoltaicpanelcolumn.PhotovoltaicPanelColumnQueryReq;
@ -194,8 +195,12 @@ public class FacPhotovoltaicPanelColumnServiceImpl extends ServiceImpl<FacPhotov
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) { public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
Long userId = LoginHelper.getUserId();
List<FacPhotovoltaicPanelColumn> photovoltaicPanelColumnList = this.listByIds(ids);
if (isValid) { if (isValid) {
//TODO 做一些业务上的校验,判断是否需要校验 //TODO 做一些业务上的校验,判断是否需要校验
List<Long> projectId = photovoltaicPanelColumnList.stream().map(FacPhotovoltaicPanelColumn::getProjectId).toList();
projectService.validAuth(projectId, userId);
} }
return this.removeBatchByIds(ids); return this.removeBatchByIds(ids);
} }

View File

@ -2,6 +2,7 @@ package org.dromara.facility.service.impl;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONUtil; import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.dromara.common.core.constant.HttpStatus; import org.dromara.common.core.constant.HttpStatus;
import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.exception.ServiceException;
@ -21,6 +22,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.List; import java.util.List;
/** /**
@ -61,17 +63,20 @@ public class FacPhotovoltaicPanelPartsServiceImpl implements IFacPhotovoltaicPan
if (projectService.getById(projectId) == null) { if (projectService.getById(projectId) == null) {
throw new ServiceException("项目不存在", HttpStatus.NOT_FOUND); throw new ServiceException("项目不存在", HttpStatus.NOT_FOUND);
} }
// 查询项目下光伏板
List<FacPhotovoltaicPanel> photovoltaicPanelList = photovoltaicPanelService.lambdaQuery() List<FacPhotovoltaicPanel> photovoltaicPanelList = photovoltaicPanelService.lambdaQuery()
.eq(FacPhotovoltaicPanel::getProjectId, projectId).list(); .eq(FacPhotovoltaicPanel::getProjectId, projectId).list();
if (CollUtil.isEmpty(photovoltaicPanelList)) { if (CollUtil.isEmpty(photovoltaicPanelList)) {
throw new ServiceException("项目下未创建光伏板", HttpStatus.NOT_FOUND); throw new ServiceException("项目下未创建光伏板", HttpStatus.NOT_FOUND);
} }
List<FeatureByPoint> features = geoJson.getPointGeoJson().getFeatures(); List<FeatureByPoint> features = geoJson.getPointGeoJson().getFeatures();
// 获取所有点列表
List<List<Double>> pointList = new ArrayList<> List<List<Double>> pointList = new ArrayList<>
(features.stream().map(featureByPoint -> featureByPoint.getGeometry().getCoordinates()).toList()); (features.stream().map(featureByPoint -> featureByPoint.getGeometry().getCoordinates()).toList());
List<FacPhotovoltaicPanelPoint> photovoltaicPanelPointList = new ArrayList<>(); List<FacPhotovoltaicPanelPoint> photovoltaicPanelPointList = new ArrayList<>();
List<FacPhotovoltaicPanelColumn> photovoltaicPanelColumnList = new ArrayList<>(); List<FacPhotovoltaicPanelColumn> photovoltaicPanelColumnList = new ArrayList<>();
List<FacPhotovoltaicPanelSupport> photovoltaicPanelSupportList = new ArrayList<>(); List<FacPhotovoltaicPanelSupport> photovoltaicPanelSupportList = new ArrayList<>();
// 遍历所有光伏板,找到所有匹配的点
for (FacPhotovoltaicPanel photovoltaicPanel : photovoltaicPanelList) { for (FacPhotovoltaicPanel photovoltaicPanel : photovoltaicPanelList) {
String positions = photovoltaicPanel.getPositions(); String positions = photovoltaicPanel.getPositions();
List<List<Double>> positionList = new ArrayList<>(); List<List<Double>> positionList = new ArrayList<>();
@ -79,10 +84,13 @@ public class FacPhotovoltaicPanelPartsServiceImpl implements IFacPhotovoltaicPan
for (String s : arr) { for (String s : arr) {
positionList.add(JSONUtil.toList(s, Double.class)); positionList.add(JSONUtil.toList(s, Double.class));
} }
// 获取点在面内的点
List<List<Double>> pointInPlaneList = GeoJsonUtils.getPointInPlaneList(positionList, pointList); List<List<Double>> pointInPlaneList = GeoJsonUtils.getPointInPlaneList(positionList, pointList);
// 删除点在面内的点
pointList.removeAll(pointInPlaneList); pointList.removeAll(pointInPlaneList);
if (CollUtil.isNotEmpty(pointInPlaneList)) { if (CollUtil.isNotEmpty(pointInPlaneList)) {
int i = 1; int i = 1;
// 遍历点在面内的点,添加实体信息
for (List<Double> list : pointInPlaneList) { for (List<Double> list : pointInPlaneList) {
String str = String.format("%02d", i); String str = String.format("%02d", i);
String name = photovoltaicPanel.getName() + "." + str; String name = photovoltaicPanel.getName() + "." + str;
@ -110,6 +118,7 @@ public class FacPhotovoltaicPanelPartsServiceImpl implements IFacPhotovoltaicPan
} }
} }
} }
// 批量新增
if (CollUtil.isNotEmpty(photovoltaicPanelPointList)) { if (CollUtil.isNotEmpty(photovoltaicPanelPointList)) {
boolean result = photovoltaicPanelPointService.saveBatch(photovoltaicPanelPointList); boolean result = photovoltaicPanelPointService.saveBatch(photovoltaicPanelPointList);
if (!result) { if (!result) {
@ -182,6 +191,72 @@ public class FacPhotovoltaicPanelPartsServiceImpl implements IFacPhotovoltaicPan
return true; return true;
} }
/**
* 根据方阵主键判断是否存在光伏板点
*
* @param projectId 项目id
* @param matrixIds 方阵Id列表
* @return 是否存在
*/
@Override
public Boolean validPartsExistByMatrix(Long projectId, Collection<Long> matrixIds) {
Long pointCount = photovoltaicPanelPointService.lambdaQuery()
.eq(FacPhotovoltaicPanelPoint::getProjectId, projectId)
.in(FacPhotovoltaicPanelPoint::getMatrixId, matrixIds)
.count();
if (pointCount > 0) {
return true;
}
Long columnCount = photovoltaicPanelColumnService.lambdaQuery()
.eq(FacPhotovoltaicPanelColumn::getProjectId, projectId)
.in(FacPhotovoltaicPanelColumn::getMatrixId, matrixIds)
.count();
if (columnCount > 0) {
return true;
}
Long supportCount = photovoltaicPanelSupportService.lambdaQuery()
.eq(FacPhotovoltaicPanelSupport::getProjectId, projectId)
.in(FacPhotovoltaicPanelSupport::getMatrixId, matrixIds)
.count();
return supportCount > 0;
}
/**
* 根据光伏板名称判断是否存在光伏板点
*
* @param projectId 项目id
* @param photovoltaicPanelNames 光伏板名称列表
* @return 是否存在
*/
@Override
public Boolean validPartsExistByPhotovoltaicPanel(Long projectId, Collection<String> photovoltaicPanelNames) {
LambdaQueryWrapper<FacPhotovoltaicPanelPoint> pointWrapper = new LambdaQueryWrapper<>();
pointWrapper.and(query -> {
for (String name : photovoltaicPanelNames) {
query.or().likeRight(FacPhotovoltaicPanelPoint::getName, name + ".");
}
});
if (photovoltaicPanelPointService.count(pointWrapper) > 0) {
return true;
}
LambdaQueryWrapper<FacPhotovoltaicPanelColumn> ColumnWrapper = new LambdaQueryWrapper<>();
ColumnWrapper.and(query -> {
for (String name : photovoltaicPanelNames) {
query.or().likeRight(FacPhotovoltaicPanelColumn::getName, name + ".");
}
});
if (photovoltaicPanelColumnService.count(ColumnWrapper) > 0) {
return true;
}
LambdaQueryWrapper<FacPhotovoltaicPanelSupport> supportWrapper = new LambdaQueryWrapper<>();
supportWrapper.and(query -> {
for (String name : photovoltaicPanelNames) {
query.or().likeRight(FacPhotovoltaicPanelSupport::getName, name + ".");
}
});
return photovoltaicPanelSupportService.count(supportWrapper) > 0;
}
/** /**
* 校验名称是否重复 * 校验名称是否重复
* *

View File

@ -12,6 +12,7 @@ import org.dromara.common.core.utils.ObjectUtils;
import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.facility.domain.FacPhotovoltaicPanelPoint; import org.dromara.facility.domain.FacPhotovoltaicPanelPoint;
import org.dromara.facility.domain.req.photovoltaicpanelpoint.PhotovoltaicPanelPointCreateReq; import org.dromara.facility.domain.req.photovoltaicpanelpoint.PhotovoltaicPanelPointCreateReq;
import org.dromara.facility.domain.req.photovoltaicpanelpoint.PhotovoltaicPanelPointQueryReq; import org.dromara.facility.domain.req.photovoltaicpanelpoint.PhotovoltaicPanelPointQueryReq;
@ -194,8 +195,12 @@ public class FacPhotovoltaicPanelPointServiceImpl extends ServiceImpl<FacPhotovo
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) { public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
Long userId = LoginHelper.getUserId();
List<FacPhotovoltaicPanelPoint> photovoltaicPanelPointList = this.list(this.buildQueryWrapper(null));
if (isValid) { if (isValid) {
//TODO 做一些业务上的校验,判断是否需要校验 //TODO 做一些业务上的校验,判断是否需要校验
List<Long> projectId = photovoltaicPanelPointList.stream().map(FacPhotovoltaicPanelPoint::getProjectId).toList();
projectService.validAuth(projectId, userId);
} }
return this.removeBatchByIds(ids); return this.removeBatchByIds(ids);
} }

View File

@ -12,6 +12,7 @@ import org.dromara.common.core.utils.ObjectUtils;
import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.facility.domain.FacMatrix; import org.dromara.facility.domain.FacMatrix;
import org.dromara.facility.domain.FacPhotovoltaicPanel; import org.dromara.facility.domain.FacPhotovoltaicPanel;
import org.dromara.facility.domain.req.geojson.FeatureByPlane; import org.dromara.facility.domain.req.geojson.FeatureByPlane;
@ -24,10 +25,12 @@ import org.dromara.facility.domain.req.photovoltaicpanel.PhotovoltaicPanelUpdate
import org.dromara.facility.domain.vo.FacPhotovoltaicPanelVo; import org.dromara.facility.domain.vo.FacPhotovoltaicPanelVo;
import org.dromara.facility.mapper.FacPhotovoltaicPanelMapper; import org.dromara.facility.mapper.FacPhotovoltaicPanelMapper;
import org.dromara.facility.service.IFacMatrixService; import org.dromara.facility.service.IFacMatrixService;
import org.dromara.facility.service.IFacPhotovoltaicPanelPartsService;
import org.dromara.facility.service.IFacPhotovoltaicPanelService; import org.dromara.facility.service.IFacPhotovoltaicPanelService;
import org.dromara.project.service.IBusProjectService; import org.dromara.project.service.IBusProjectService;
import org.dromara.utils.GeoJsonUtils; import org.dromara.utils.GeoJsonUtils;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -51,6 +54,10 @@ public class FacPhotovoltaicPanelServiceImpl extends ServiceImpl<FacPhotovoltaic
@Resource @Resource
private IFacMatrixService matrixService; private IFacMatrixService matrixService;
@Lazy
@Resource
private IFacPhotovoltaicPanelPartsService photovoltaicPanelPartsService;
/** /**
* 查询设施-光伏板 * 查询设施-光伏板
* *
@ -271,8 +278,22 @@ public class FacPhotovoltaicPanelServiceImpl extends ServiceImpl<FacPhotovoltaic
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) { public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
Long userId = LoginHelper.getUserId();
List<FacPhotovoltaicPanel> photovoltaicPanelList = this.listByIds(ids);
if (isValid) { if (isValid) {
//TODO 做一些业务上的校验,判断是否需要校验 //TODO 做一些业务上的校验,判断是否需要校验
List<Long> projectIds = photovoltaicPanelList.stream().map(FacPhotovoltaicPanel::getProjectId).distinct().toList();
if (CollUtil.isNotEmpty(projectIds) && projectIds.size() > 1) {
throw new ServiceException("仅能删除单个项目下的光伏板", HttpStatus.BAD_REQUEST);
}
Long projectId = projectIds.get(0);
projectService.validAuth(projectId, userId);
// 判断是否存在光伏板点信息
List<String> matrixNames = photovoltaicPanelList.stream().map(FacPhotovoltaicPanel::getName).toList();
Boolean result = photovoltaicPanelPartsService.validPartsExistByPhotovoltaicPanel(projectId, matrixNames);
if (result) {
throw new ServiceException("删除失败,存在光伏板点信息", HttpStatus.CONFLICT);
}
} }
return this.removeBatchByIds(ids); return this.removeBatchByIds(ids);
} }

View File

@ -12,6 +12,7 @@ import org.dromara.common.core.utils.ObjectUtils;
import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.facility.domain.FacPhotovoltaicPanelSupport; import org.dromara.facility.domain.FacPhotovoltaicPanelSupport;
import org.dromara.facility.domain.req.photovoltaicpanelsupport.PhotovoltaicPanelSupportCreateReq; import org.dromara.facility.domain.req.photovoltaicpanelsupport.PhotovoltaicPanelSupportCreateReq;
import org.dromara.facility.domain.req.photovoltaicpanelsupport.PhotovoltaicPanelSupportQueryReq; import org.dromara.facility.domain.req.photovoltaicpanelsupport.PhotovoltaicPanelSupportQueryReq;
@ -194,8 +195,12 @@ public class FacPhotovoltaicPanelSupportServiceImpl extends ServiceImpl<FacPhoto
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) { public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
Long userId = LoginHelper.getUserId();
List<FacPhotovoltaicPanelSupport> photovoltaicPanelSupportList = this.listByIds(ids);
if (isValid) { if (isValid) {
//TODO 做一些业务上的校验,判断是否需要校验 //TODO 做一些业务上的校验,判断是否需要校验
List<Long> projectId = photovoltaicPanelSupportList.stream().map(FacPhotovoltaicPanelSupport::getProjectId).toList();
projectService.validAuth(projectId, userId);
} }
return this.removeBatchByIds(ids); return this.removeBatchByIds(ids);
} }

View File

@ -101,8 +101,8 @@ public class BusProjectFileController extends BaseController {
*/ */
@Log(title = "项目文件存储", businessType = BusinessType.IMPORT) @Log(title = "项目文件存储", businessType = BusinessType.IMPORT)
@PostMapping("/upload/dxf") @PostMapping("/upload/dxf")
public R<Long> uploadDxf2Json(@RequestParam("file") MultipartFile file, ProjectFileUploadDxfReq req) { public R<Void> uploadDxf2Json(@RequestParam("file") MultipartFile file, ProjectFileUploadDxfReq req) {
return R.ok(busProjectFileService.uploadDxf2Json(file, req)); return toAjax(busProjectFileService.uploadDxf2Json(file, req));
} }
/** /**
@ -113,7 +113,7 @@ public class BusProjectFileController extends BaseController {
@SaCheckPermission("project:projectFile:query") @SaCheckPermission("project:projectFile:query")
@GetMapping("/json/{id}") @GetMapping("/json/{id}")
public R<JSONObject> getJSONFile(@NotNull(message = "主键不能为空") public R<JSONObject> getJSONFile(@NotNull(message = "主键不能为空")
@PathVariable Long id){ @PathVariable Long id) {
return R.ok(busProjectFileService.getJSONFile(id)); return R.ok(busProjectFileService.getJSONFile(id));
} }
} }

View File

@ -81,7 +81,7 @@ public interface IBusProjectFileService extends IService<BusProjectFile> {
* @param req 请求 * @param req 请求
* @return 主键 * @return 主键
*/ */
Long uploadDxf2Json(MultipartFile file, ProjectFileUploadDxfReq req); Boolean uploadDxf2Json(MultipartFile file, ProjectFileUploadDxfReq req);
/** /**
* 获取项目文件存储视图对象 * 获取项目文件存储视图对象

View File

@ -16,7 +16,10 @@ import org.dromara.common.core.utils.ObjectUtils;
import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.constant.DxfFileConstant; import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.sse.dto.SseMessageDto;
import org.dromara.common.sse.utils.SseMessageUtils;
import org.dromara.constant.DesignMapFileConstant;
import org.dromara.project.domain.BusProject; import org.dromara.project.domain.BusProject;
import org.dromara.project.domain.BusProjectFile; import org.dromara.project.domain.BusProjectFile;
import org.dromara.project.domain.req.projectfile.ProjectFileQueryReq; import org.dromara.project.domain.req.projectfile.ProjectFileQueryReq;
@ -26,7 +29,7 @@ import org.dromara.project.domain.vo.BusProjectFileVo;
import org.dromara.project.mapper.BusProjectFileMapper; import org.dromara.project.mapper.BusProjectFileMapper;
import org.dromara.project.service.IBusProjectFileService; import org.dromara.project.service.IBusProjectFileService;
import org.dromara.project.service.IBusProjectService; import org.dromara.project.service.IBusProjectService;
import org.dromara.utils.DxfUtils; import org.dromara.utils.Dxf2JsonUtils;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -41,6 +44,8 @@ import java.nio.file.Paths;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledExecutorService;
/** /**
* 项目文件存储Service业务层处理 * 项目文件存储Service业务层处理
@ -56,6 +61,11 @@ public class BusProjectFileServiceImpl extends ServiceImpl<BusProjectFileMapper,
@Resource @Resource
private IBusProjectService projectService; private IBusProjectService projectService;
@Resource
private ScheduledExecutorService scheduledExecutorService;
private static final ConcurrentHashMap<Long, Boolean> USER_TASK_RUNNING = new ConcurrentHashMap<>();
/** /**
* 查询项目文件存储 * 查询项目文件存储
* *
@ -167,7 +177,7 @@ public class BusProjectFileServiceImpl extends ServiceImpl<BusProjectFileMapper,
} }
String filePath = projectFile.getFilePath(); String filePath = projectFile.getFilePath();
String suffix = FileUtil.getSuffix(FileUtil.getName(filePath)); String suffix = FileUtil.getSuffix(FileUtil.getName(filePath));
if (!suffix.equals("json")) { if (!suffix.equals(DesignMapFileConstant.JSONFileSuffix)) {
throw new ServiceException("文件格式不正确只能解析json文件", HttpStatus.BAD_REQUEST); throw new ServiceException("文件格式不正确只能解析json文件", HttpStatus.BAD_REQUEST);
} }
JSONObject jsonObject; JSONObject jsonObject;
@ -191,7 +201,13 @@ public class BusProjectFileServiceImpl extends ServiceImpl<BusProjectFileMapper,
*/ */
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public Long uploadDxf2Json(MultipartFile file, ProjectFileUploadDxfReq req) { public Boolean uploadDxf2Json(MultipartFile file, ProjectFileUploadDxfReq req) {
Long userId = LoginHelper.getUserId();
// 判断当前用户是否已经有一个正在处理的任务
Boolean alreadyRunning = USER_TASK_RUNNING.putIfAbsent(userId, true);
if (alreadyRunning != null && alreadyRunning) {
throw new ServiceException("当前有一个正在处理的转换任务,请等待完成后再上传", HttpStatus.CONFLICT);
}
// 校验文件是否为空 // 校验文件是否为空
if (file == null) { if (file == null) {
throw new ServiceException("dxf文件不能为空", HttpStatus.BAD_REQUEST); throw new ServiceException("dxf文件不能为空", HttpStatus.BAD_REQUEST);
@ -199,8 +215,8 @@ public class BusProjectFileServiceImpl extends ServiceImpl<BusProjectFileMapper,
// 校验是否为 dxf 文件 // 校验是否为 dxf 文件
String fileName = file.getOriginalFilename(); String fileName = file.getOriginalFilename();
String suffix = FileUtil.getSuffix(fileName); String suffix = FileUtil.getSuffix(fileName);
if (!Objects.equals(suffix, "dxf")) { if (!Objects.equals(suffix, DesignMapFileConstant.DXFFileSuffix)) {
throw new ServiceException("文件格式不正确,只能上传.dxf文件", HttpStatus.BAD_REQUEST); throw new ServiceException("文件格式不正确,只能上传.dxf后缀的文件", HttpStatus.BAD_REQUEST);
} }
// 校验项目是否存在 // 校验项目是否存在
Long projectId = req.getProjectId(); Long projectId = req.getProjectId();
@ -210,8 +226,7 @@ public class BusProjectFileServiceImpl extends ServiceImpl<BusProjectFileMapper,
} }
// 获取当前项目根目录 // 获取当前项目根目录
String projectRoot = System.getProperty("user.dir"); String projectRoot = System.getProperty("user.dir");
// 构造保存 DXF 的目录 String bashPath = DesignMapFileConstant.getDxfProjectPath(projectId);
String bashPath = DxfFileConstant.getDxfProjectPath(projectId);
String filePath = projectRoot + File.separator + bashPath; String filePath = projectRoot + File.separator + bashPath;
if (!FileUtil.exist(filePath)) { if (!FileUtil.exist(filePath)) {
FileUtil.mkdir(filePath); FileUtil.mkdir(filePath);
@ -226,39 +241,58 @@ public class BusProjectFileServiceImpl extends ServiceImpl<BusProjectFileMapper,
} }
// 构造 JSON 输出路径 // 构造 JSON 输出路径
String uuid = IdUtil.fastSimpleUUID(); String uuid = IdUtil.fastSimpleUUID();
String outputJSONPath = filePath + File.separator + uuid + ".json"; String outputJSONPath = filePath + File.separator + uuid + "." + DesignMapFileConstant.JSONFileSuffix;
// 获取 dxf2json.exe 路径 // 获取 dxf2json.exe 路径
String exePath = projectRoot + File.separator + DxfFileConstant.DXF_BASE_PATH + File.separator + "main.exe"; String exePath = projectRoot + File.separator + DesignMapFileConstant.DXF_BASE_PATH + File.separator + "main.exe";
String sourceEPSG = DxfFileConstant.EPSG4524; String sourceEPSG = DesignMapFileConstant.EPSG4524;
String targetEPSG = DxfFileConstant.EPSG4326; String targetEPSG = DesignMapFileConstant.EPSG4326;
// 构造命令行参数
DxfUtils.dxf2json(exePath, inputDXFPath, outputJSONPath, sourceEPSG, targetEPSG);
// 删除之前的数据库记录和文件
BusProjectFile oldProjectFile = this.lambdaQuery() BusProjectFile oldProjectFile = this.lambdaQuery()
.eq(BusProjectFile::getProjectId, projectId) .eq(BusProjectFile::getProjectId, projectId)
.one(); .one();
if (oldProjectFile != null) { if (oldProjectFile != null) {
boolean result = this.removeById(oldProjectFile);
if (!result) {
throw new ServiceException("删除项目文件存储失败,数据库异常", HttpStatus.ERROR);
}
// 删除之前的文件 // 删除之前的文件
try { try {
FileUtil.del(oldProjectFile.getFilePath()); FileUtil.del(projectRoot + File.separator + oldProjectFile.getFilePath());
} catch (Exception e) { } catch (Exception e) {
log.error("删除项目文件失败", e); log.error("删除项目文件失败", e);
} }
} }
// 保存项目文件存储 scheduledExecutorService.execute(() -> {
try {
// 构造命令行参数
Dxf2JsonUtils.dxf2json(exePath, inputDXFPath, outputJSONPath, sourceEPSG, targetEPSG);
String jsonFilePath = bashPath + File.separator + uuid + "." + DesignMapFileConstant.JSONFileSuffix;
String jsonFileName = FileUtil.getPrefix(fileName) + "." + DesignMapFileConstant.JSONFileSuffix;
BusProjectFile projectFile = new BusProjectFile(); BusProjectFile projectFile = new BusProjectFile();
if (oldProjectFile != null) {
projectFile.setId(oldProjectFile.getId());
projectFile.setFileName(jsonFileName);
projectFile.setFilePath(jsonFilePath);
boolean update = this.updateById(projectFile);
if (!update) throw new ServiceException("数据库修改异常");
} else {
projectFile.setProjectId(projectId); projectFile.setProjectId(projectId);
projectFile.setFileName(FileUtil.getPrefix(fileName) + ".json"); projectFile.setFileName(jsonFileName);
projectFile.setFilePath(bashPath + File.separator + uuid + ".json"); projectFile.setFilePath(jsonFilePath);
boolean save = this.save(projectFile); boolean save = this.save(projectFile);
if (!save) { if (!save) throw new ServiceException("数据库新增异常");
throw new ServiceException("保存项目文件存储失败,数据库异常", HttpStatus.ERROR);
} }
return projectFile.getId(); SseMessageDto dto = new SseMessageDto();
dto.setMessage("DXF 文件转换成 GeoJSON 成功");
dto.setUserIds(List.of(userId));
SseMessageUtils.publishMessage(dto);
} catch (Exception e) {
log.error("DXF 转换失败", e);
SseMessageDto dto = new SseMessageDto();
dto.setMessage("DXF 文件转换失败,请联系管理员处理");
dto.setUserIds(List.of(userId));
SseMessageUtils.publishMessage(dto);
} finally {
// 无论成功或失败都释放状态
USER_TASK_RUNNING.remove(userId);
}
});
return true;
} }
/** /**

View File

@ -15,7 +15,7 @@ import java.util.List;
* @date 2025/4/23 10:42 * @date 2025/4/23 10:42
*/ */
@Slf4j @Slf4j
public class DxfUtils { public class Dxf2JsonUtils {
/** /**
* dxf转json * dxf转json

View File

@ -1,8 +1,13 @@
package org.dromara.utils; package org.dromara.utils;
import org.dromara.common.core.constant.HttpStatus;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.constant.GeoJsonConstant;
import org.dromara.facility.domain.req.geojson.Geometry;
import org.locationtech.jts.geom.*; import org.locationtech.jts.geom.*;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
/** /**
* @author lcj * @author lcj
@ -80,4 +85,36 @@ public class GeoJsonUtils {
new Coordinate(planeList.get(0), planeList.get(1))) new Coordinate(planeList.get(0), planeList.get(1)))
.toList().toArray(new Coordinate[0]); .toList().toArray(new Coordinate[0]);
} }
/**
* 获取二维坐标
*
* @param geometry 几何对象
* @return 二维坐标
*/
public static List<List<Double>> getTwoDimensionalCoordinates(Geometry geometry) {
String type = geometry.getType();
List<Object> coordinates = geometry.getCoordinates();
return switch (type) {
case GeoJsonConstant.POINT -> throw new ServiceException("点位无法创建方阵", HttpStatus.BAD_REQUEST);
case GeoJsonConstant.LINE -> coordinates.stream()
.filter(obj -> obj instanceof List<?>)
.map(obj -> ((List<?>) obj).stream()
.filter(num -> num instanceof Number)
.map(num -> ((Number) num).doubleValue())
.collect(Collectors.toList()))
.collect(Collectors.toList());
case GeoJsonConstant.POLYGON -> coordinates.stream()
.filter(obj -> obj instanceof List<?>)
.flatMap(obj -> ((List<?>) obj).stream())
.filter(pointObj -> pointObj instanceof List<?>)
.map(pointObj -> ((List<?>) pointObj).stream()
.filter(num -> num instanceof Number)
.map(num -> ((Number) num).doubleValue())
.collect(Collectors.toList()))
.collect(Collectors.toList());
default -> throw new ServiceException("暂不支持该类型", HttpStatus.BAD_REQUEST);
};
}
} }