[update] 修改、优化根据GeoJson创建方阵、光伏板、箱变、逆变器方法 [add] 新增进度计划进度计划、进度计划详情接口

This commit is contained in:
lcj
2025-05-27 19:53:53 +08:00
parent 560ed53f70
commit a81469f405
46 changed files with 1935 additions and 120 deletions

View File

@ -0,0 +1,34 @@
package org.dromara.facility.constant;
/**
* @author lcj
* @date 2025/5/27 18:27
*/
public interface FacRedisKeyConstant {
String FAC_REDIS_PREFIX = "fac:";
String FAC_IN_OPERATION_REDIS_KEY_PREFIX = FAC_REDIS_PREFIX + "inOperation:";
/**
* 批量上传桩点、支架、立柱 Redis 缓存 key
*
* @param sessionId 唯一标识
* @param batchNum 第几批数据
* @return Redis 缓存 key
*/
static String getBatchUploadPartsRedisKey(String sessionId, int batchNum) {
return String.format("%s%s:%s:%s", FAC_REDIS_PREFIX, "panel:parts", sessionId, batchNum);
}
/**
* 当前项目是否正在操作 Redis 缓存 key
*
* @param projectId 项目 ID
* @return Redis 缓存 key
*/
static String getInOperationByProjectRedisKey(Long projectId) {
return String.format("%s%s:%s", FAC_IN_OPERATION_REDIS_KEY_PREFIX, "project", projectId);
}
}

View File

@ -25,7 +25,7 @@ public class FacBoxTransformerCreateByGeoJsonReq implements Serializable {
/**
* 地理位置
*/
private FacGeoJsonByPoint locationGeoJson;
private List<FacGeoJsonByPoint> locationGeoJson;
/**
* 名称

View File

@ -4,6 +4,9 @@ import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lcj
* @date 2025/4/24 10:40
@ -11,7 +14,10 @@ import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class FacFeatureByPoint {
public class FacFeatureByPoint implements Serializable {
@Serial
private static final long serialVersionUID = -3848496198713404019L;
private String type;

View File

@ -4,6 +4,8 @@ import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serial;
import java.io.Serializable;
import java.util.List;
/**
@ -13,7 +15,10 @@ import java.util.List;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class FacGeometryByPoint {
public class FacGeometryByPoint implements Serializable {
@Serial
private static final long serialVersionUID = -5904591901195563882L;
private String type;

View File

@ -4,6 +4,9 @@ import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lcj
* @date 2025/4/24 10:53
@ -11,7 +14,10 @@ import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class FacProperties {
public class FacProperties implements Serializable {
@Serial
private static final long serialVersionUID = -2997401596985220109L;
private String type;

View File

@ -25,7 +25,7 @@ public class FacInverterCreateByGeoJsonReq implements Serializable {
/**
* 地理位置
*/
private FacGeoJsonByPoint locationGeoJson;
private List<FacGeoJsonByPoint> locationGeoJson;
/**
* 名称

View File

@ -26,7 +26,7 @@ public class FacMatrixCreateByGeoJsonReq implements Serializable {
/**
* 地理位置
*/
private FacGeoJson locationGeoJson;
private List<FacGeoJson> locationGeoJson;
/**
* 名称

View File

@ -26,7 +26,7 @@ public class FacPhotovoltaicPanelCreateByGeoJsonReq implements Serializable {
/**
* 地理位置
*/
private FacGeoJsonByPlane locationGeoJson;
private List<FacGeoJsonByPlane> locationGeoJson;
/**
* 名称

View File

@ -26,4 +26,19 @@ public class FacPhotovoltaicPanelPartsCreateByGeoJsonReq implements Serializable
*/
private FacGeoJsonByPoint locationGeoJson;
/**
* 批次上传标识
*/
private String sessionId;
/**
* 当前批次
*/
private int batchNum;
/**
* 总批次
*/
private int totalBatch;
}

View File

@ -154,7 +154,7 @@ public class FacBoxTransformerServiceImpl extends ServiceImpl<FacBoxTransformerM
List<FacMatrix> matrixList = matrixService.lambdaQuery()
.eq(FacMatrix::getProjectId, projectId).list();
if (CollUtil.isEmpty(matrixList)) {
throw new ServiceException("项目下无方阵数据,请先创建方阵息后再添加光伏板信息", HttpStatus.NOT_FOUND);
throw new ServiceException("项目下无方阵数据,请先创建方阵息后再添加箱变信息", HttpStatus.NOT_FOUND);
}
// 获取箱变信息
List<FacBoxTransformer> oldBoxTransformerList = this.lambdaQuery()
@ -164,7 +164,12 @@ public class FacBoxTransformerServiceImpl extends ServiceImpl<FacBoxTransformerM
Function.identity(),
(boxTransformer1, boxTransformer2) -> boxTransformer1
));
List<FacFeatureByPoint> locationGeoJson = geoJson.getLocationGeoJson().getFeatures();
// 获取箱变地理信息
List<FacGeoJsonByPoint> locationGeoJsonList = geoJson.getLocationGeoJson();
List<FacFeatureByPoint> locationGeoJson = new ArrayList<>();
for (FacGeoJsonByPoint geoJsonByPoint : locationGeoJsonList) {
locationGeoJson.addAll(geoJsonByPoint.getFeatures());
}
// 获取所有对应名称的点
List<FacGeoJsonByPoint> nameGeoJsonList = geoJson.getNameGeoJson();
List<FacFeatureByPoint> nameGeoJson = new ArrayList<>();

View File

@ -154,7 +154,7 @@ public class FacInverterServiceImpl extends ServiceImpl<FacInverterMapper, FacIn
List<FacMatrix> matrixList = matrixService.lambdaQuery()
.eq(FacMatrix::getProjectId, projectId).list();
if (CollUtil.isEmpty(matrixList)) {
throw new ServiceException("项目下无方阵数据,请先创建方阵息后再添加光伏板信息", HttpStatus.NOT_FOUND);
throw new ServiceException("项目下无方阵数据,请先创建方阵息后再添加逆变器信息", HttpStatus.NOT_FOUND);
}
// 获取箱变信息
List<FacInverter> oldInverterList = this.lambdaQuery()
@ -164,7 +164,12 @@ public class FacInverterServiceImpl extends ServiceImpl<FacInverterMapper, FacIn
Function.identity(),
(inverter1, inverter2) -> inverter1
));
List<FacFeatureByPoint> locationGeoJson = geoJson.getLocationGeoJson().getFeatures();
// 获取所有逆变器对应名称的点
List<FacGeoJsonByPoint> locationGeoJsonList = geoJson.getLocationGeoJson();
List<FacFeatureByPoint> locationGeoJson = new ArrayList<>();
for (FacGeoJsonByPoint geoJsonByPoint : locationGeoJsonList) {
locationGeoJson.addAll(geoJsonByPoint.getFeatures());
}
// 获取所有对应名称的点
List<FacGeoJsonByPoint> nameGeoJsonList = geoJson.getNameGeoJson();
List<FacFeatureByPoint> nameGeoJson = new ArrayList<>();

View File

@ -13,11 +13,9 @@ import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.facility.constant.FacRedisKeyConstant;
import org.dromara.facility.domain.*;
import org.dromara.facility.domain.dto.geojson.FacFeature;
import org.dromara.facility.domain.dto.geojson.FacFeatureByPoint;
import org.dromara.facility.domain.dto.geojson.FacGeoJsonByPoint;
import org.dromara.facility.domain.dto.geojson.FacGeometry;
import org.dromara.facility.domain.dto.geojson.*;
import org.dromara.facility.domain.dto.matrix.*;
import org.dromara.facility.domain.enums.FacFinishStatusEnum;
import org.dromara.facility.domain.vo.matrix.FacMatrixDetailGisVo;
@ -30,6 +28,7 @@ import org.dromara.project.service.IBusProjectService;
import org.dromara.utils.JSTUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -82,6 +81,9 @@ public class FacMatrixServiceImpl extends ServiceImpl<FacMatrixMapper, FacMatrix
@Resource
private IPgsProgressCategoryService progressCategoryService;
@Resource
private RedisTemplate<String, Object> redisTemplate;
/**
* 查询设施-方阵
*
@ -255,6 +257,13 @@ public class FacMatrixServiceImpl extends ServiceImpl<FacMatrixMapper, FacMatrix
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean insertByGeoJson(FacMatrixCreateByGeoJsonReq geoJson) {
// 判断当前项目是否正在执行桩点、立柱、支架数据
String operationRedisKey = FacRedisKeyConstant.getInOperationByProjectRedisKey(geoJson.getProjectId());
// 判断 redis key 是否存在,存在则返回
Object object = redisTemplate.opsForValue().get(operationRedisKey);
if (object != null && (Boolean) object) {
throw new ServiceException("项目下桩点、立柱、支架数据正在处理中,请等待处理完毕后操作", HttpStatus.BAD_REQUEST);
}
Long projectId = geoJson.getProjectId();
if (projectService.getById(projectId) == null) {
throw new ServiceException("项目不存在", HttpStatus.NOT_FOUND);
@ -263,7 +272,11 @@ public class FacMatrixServiceImpl extends ServiceImpl<FacMatrixMapper, FacMatrix
List<FacMatrix> oldMatrixList = this.lambdaQuery()
.eq(FacMatrix::getProjectId, projectId).list();
List<FacMatrix> matrixList = new ArrayList<>();
List<FacFeature> locationFeatures = geoJson.getLocationGeoJson().getFeatures();
List<FacGeoJson> locationGeoJsonList = geoJson.getLocationGeoJson();
List<FacFeature> locationFeatures = new ArrayList<>();
for (FacGeoJson geoJsonByPoint : locationGeoJsonList) {
locationFeatures.addAll(geoJsonByPoint.getFeatures());
}
// 获取所有对应名称的点
List<FacGeoJsonByPoint> nameGeoJsonList = geoJson.getNameGeoJson();
List<FacFeatureByPoint> nameFeatures = new ArrayList<>();

View File

@ -9,7 +9,10 @@ import org.dromara.common.core.constant.HttpStatus;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.sse.dto.SseMessageDto;
import org.dromara.common.sse.utils.SseMessageUtils;
import org.dromara.facility.constant.FacPhotovoltaicPanelPartsConstant;
import org.dromara.facility.constant.FacRedisKeyConstant;
import org.dromara.facility.domain.FacPhotovoltaicPanel;
import org.dromara.facility.domain.FacPhotovoltaicPanelColumn;
import org.dromara.facility.domain.FacPhotovoltaicPanelPoint;
@ -20,15 +23,14 @@ import org.dromara.facility.domain.dto.photovoltaicpanelparts.FacPhotovoltaicPan
import org.dromara.facility.service.*;
import org.dromara.progress.constant.PgsProgressCategoryConstant;
import org.dromara.progress.domain.PgsProgressCategory;
import org.dromara.progress.domain.PgsProgressCategoryTemplate;
import org.dromara.progress.service.IPgsProgressCategoryService;
import org.dromara.progress.service.IPgsProgressCategoryTemplateService;
import org.dromara.project.service.IBusProjectService;
import org.dromara.utils.JSTUtils;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -36,10 +38,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.*;
import java.util.function.Function;
import java.util.stream.Collectors;
@ -72,6 +71,16 @@ public class FacPhotovoltaicPanelPartsServiceImpl implements IFacPhotovoltaicPan
@Resource
private IPgsProgressCategoryService progressCategoryService;
@Resource
private RedisTemplate<String, Object> redisTemplate;
@Resource
private ScheduledExecutorService scheduledExecutorService;
@Resource
@Lazy
private FacPhotovoltaicPanelPartsServiceImpl self; // 注入自己
/**
* 批量新增设施-光伏板(桩点、立柱、支架)
*
@ -80,17 +89,88 @@ public class FacPhotovoltaicPanelPartsServiceImpl implements IFacPhotovoltaicPan
*/
@Override
public Boolean insertPartsByGeoJson(FacPhotovoltaicPanelPartsCreateByGeoJsonReq geoJson) {
Long projectId = geoJson.getProjectId();
if (projectService.getById(projectId) == null) {
throw new ServiceException("项目不存在", HttpStatus.NOT_FOUND);
// 设置 redis 防止多次操作
String operationRedisKey = FacRedisKeyConstant.getInOperationByProjectRedisKey(geoJson.getProjectId());
// 判断 redis key 是否存在,存在则返回
Object object = redisTemplate.opsForValue().get(operationRedisKey);
if (object != null && (Boolean) object) {
throw new ServiceException("项目下桩点、立柱、支架数据正在处理中,请勿重复操作", HttpStatus.BAD_REQUEST);
}
// 第一次接收请求,进行数据校验
int batchNum = geoJson.getBatchNum();
if (batchNum == 1) {
Long projectId = geoJson.getProjectId();
if (projectService.getById(projectId) == null) {
throw new ServiceException("项目不存在", HttpStatus.NOT_FOUND);
}
// 查询项目下光伏板
List<FacPhotovoltaicPanel> photovoltaicPanelList = photovoltaicPanelService.lambdaQuery()
.eq(FacPhotovoltaicPanel::getProjectId, projectId).list();
if (CollUtil.isEmpty(photovoltaicPanelList)) {
throw new ServiceException("项目下无光伏板信息,请先创建光伏板信息后再添加桩点、立柱、支架信息", HttpStatus.NOT_FOUND);
}
}
// 获取 redis key
String sessionId = geoJson.getSessionId();
int totalBatch = geoJson.getTotalBatch();
List<FacFeatureByPoint> dataList = geoJson.getLocationGeoJson().getFeatures();
String redisKey = FacRedisKeyConstant.getBatchUploadPartsRedisKey(sessionId, batchNum);
// 存储到 Redis设置过期时间 30 分钟
redisTemplate.opsForValue().set(redisKey, dataList, 1800, TimeUnit.SECONDS);
log.info("已接收第 {} 批数据,共 {} 批", batchNum, totalBatch);
Long userId = LoginHelper.getUserId();
SseMessageDto messageDto = new SseMessageDto();
messageDto.setUserIds(List.of(userId));
// 如果是最后一批,开始合并
if (batchNum == totalBatch) {
List<FacFeatureByPoint> allData = new ArrayList<>();
for (int i = 1; i <= totalBatch; i++) {
String batchKey = FacRedisKeyConstant.getBatchUploadPartsRedisKey(sessionId, i);
Object batch = redisTemplate.opsForValue().get(batchKey);
if (batch instanceof List<?>) {
allData.addAll((List<FacFeatureByPoint>) batch);
}
}
// 设置 redis key防止多次操作
redisTemplate.opsForValue().set(operationRedisKey, true);
messageDto.setMessage("桩点、立柱、支架数据上传完毕,等待中");
SseMessageUtils.publishMessage(messageDto);
scheduledExecutorService.execute(() -> {
try {
// 合并后的数据处理,如入库
this.saveBatch(geoJson.getProjectId(), allData, userId);
} catch (Exception e) {
messageDto.setMessage("桩点、立柱、支架数据处理失败,请联系管理员处理");
SseMessageUtils.publishMessage(messageDto);
log.error("桩点、立柱、支架数据处理失败", e);
throw new ServiceException("桩点、立柱、支架数据处理失败", HttpStatus.ERROR);
} finally {
// 清理缓存
for (int i = 1; i <= totalBatch; i++) {
String batchKey = FacRedisKeyConstant.getBatchUploadPartsRedisKey(sessionId, i);
redisTemplate.delete(batchKey);
}
redisTemplate.delete(operationRedisKey);
}
messageDto.setMessage("桩点、立柱、支架数据处理完毕");
SseMessageUtils.publishMessage(messageDto);
});
return true;
}
return true;
}
/**
* 批量保存数据
*
* @param projectId 项目id
* @param features 数据
* @param userId 操作用户id
*/
private void saveBatch(Long projectId, List<FacFeatureByPoint> features, Long userId) {
// 查询项目下光伏板
List<FacPhotovoltaicPanel> photovoltaicPanelList = photovoltaicPanelService.lambdaQuery()
.eq(FacPhotovoltaicPanel::getProjectId, projectId).list();
if (CollUtil.isEmpty(photovoltaicPanelList)) {
throw new ServiceException("项目下未创建光伏板", HttpStatus.NOT_FOUND);
}
List<FacFeatureByPoint> features = geoJson.getLocationGeoJson().getFeatures();
// 获取数据库中所有点的列表
List<FacPhotovoltaicPanelPoint> oldPointList = photovoltaicPanelPointService.lambdaQuery()
.eq(FacPhotovoltaicPanelPoint::getProjectId, projectId).list();
@ -122,8 +202,6 @@ public class FacPhotovoltaicPanelPartsServiceImpl implements IFacPhotovoltaicPan
List<FacPhotovoltaicPanelPoint> pointList = new ArrayList<>();
List<FacPhotovoltaicPanelColumn> columnList = new ArrayList<>();
List<FacPhotovoltaicPanelSupport> supportList = new ArrayList<>();
// 获取当前登录用户
Long userId = LoginHelper.getUserId();
// 获取进度类别
List<String> progressCategoryNameList = List.of(FacPhotovoltaicPanelPartsConstant.POINT,
FacPhotovoltaicPanelPartsConstant.COLUMN,
@ -237,7 +315,7 @@ public class FacPhotovoltaicPanelPartsServiceImpl implements IFacPhotovoltaicPan
List<FacPhotovoltaicPanelSupport> batchSupportList = oldSupportList.subList(i, endIndex);
// 使用事务处理每批数据
// 获取代理
FacPhotovoltaicPanelPartsServiceImpl photovoltaicPanelPartsService = (FacPhotovoltaicPanelPartsServiceImpl) AopContext.currentProxy();
FacPhotovoltaicPanelPartsServiceImpl photovoltaicPanelPartsService = self;
// 异步处理每批数据,将任务添加到异步任务列表
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> photovoltaicPanelPartsService.batchDeletePartsInner(batchPointList, batchColumnList, batchSupportList), customExecutor);
deleteFutures.add(future);
@ -254,7 +332,7 @@ public class FacPhotovoltaicPanelPartsServiceImpl implements IFacPhotovoltaicPan
List<FacPhotovoltaicPanelSupport> batchSupportList = supportList.subList(i, endIndex);
// 使用事务处理每批数据
// 获取代理
FacPhotovoltaicPanelPartsServiceImpl photovoltaicPanelPartsService = (FacPhotovoltaicPanelPartsServiceImpl) AopContext.currentProxy();
FacPhotovoltaicPanelPartsServiceImpl photovoltaicPanelPartsService = self;
// 异步处理每批数据,将任务添加到异步任务列表
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> photovoltaicPanelPartsService.batchInsertPartsInner(batchPointList, batchColumnList, batchSupportList), customExecutor);
insertFutures.add(future);
@ -263,7 +341,6 @@ public class FacPhotovoltaicPanelPartsServiceImpl implements IFacPhotovoltaicPan
CompletableFuture.allOf(insertFutures.toArray(new CompletableFuture[0])).join();
// 关闭线程池
customExecutor.shutdown();
return true;
}
/**

View File

@ -14,12 +14,10 @@ import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.facility.constant.FacRedisKeyConstant;
import org.dromara.facility.domain.FacMatrix;
import org.dromara.facility.domain.FacPhotovoltaicPanel;
import org.dromara.facility.domain.dto.geojson.FacFeatureByPlane;
import org.dromara.facility.domain.dto.geojson.FacFeatureByPoint;
import org.dromara.facility.domain.dto.geojson.FacGeoJsonByPoint;
import org.dromara.facility.domain.dto.geojson.FacGeometryByPlane;
import org.dromara.facility.domain.dto.geojson.*;
import org.dromara.facility.domain.dto.photovoltaicpanel.FacPhotovoltaicPanelCreateByGeoJsonReq;
import org.dromara.facility.domain.dto.photovoltaicpanel.FacPhotovoltaicPanelCreateReq;
import org.dromara.facility.domain.dto.photovoltaicpanel.FacPhotovoltaicPanelQueryReq;
@ -40,6 +38,7 @@ import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -73,6 +72,9 @@ public class FacPhotovoltaicPanelServiceImpl extends ServiceImpl<FacPhotovoltaic
@Resource
private IPgsProgressCategoryService progressCategoryService;
@Resource
private RedisTemplate<String, Object> redisTemplate;
/**
* 查询设施-光伏板
*
@ -157,6 +159,13 @@ public class FacPhotovoltaicPanelServiceImpl extends ServiceImpl<FacPhotovoltaic
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean insertByGeoJson(FacPhotovoltaicPanelCreateByGeoJsonReq geoJson) {
// 判断当前项目是否正在执行桩点、立柱、支架数据
String operationRedisKey = FacRedisKeyConstant.getInOperationByProjectRedisKey(geoJson.getProjectId());
// 判断 redis key 是否存在,存在则返回
Object object = redisTemplate.opsForValue().get(operationRedisKey);
if (object != null && (Boolean) object) {
throw new ServiceException("项目下桩点、立柱、支架数据正在处理中,请等待处理完毕后操作", HttpStatus.BAD_REQUEST);
}
Long projectId = geoJson.getProjectId();
if (projectService.getById(projectId) == null) {
throw new ServiceException("项目不存在", HttpStatus.NOT_FOUND);
@ -165,7 +174,7 @@ public class FacPhotovoltaicPanelServiceImpl extends ServiceImpl<FacPhotovoltaic
List<FacMatrix> matrixList = matrixService.lambdaQuery()
.eq(FacMatrix::getProjectId, projectId).list();
if (CollUtil.isEmpty(matrixList)) {
throw new ServiceException("项目下无方阵数据,请先创建方阵息后再添加光伏板信息", HttpStatus.NOT_FOUND);
throw new ServiceException("项目下无方阵数据,请先创建方阵息后再添加光伏板信息", HttpStatus.NOT_FOUND);
}
// 获取当下项目下光伏板的信息
List<FacPhotovoltaicPanel> oldPhotovoltaicPanelList = this.lambdaQuery()
@ -176,7 +185,11 @@ public class FacPhotovoltaicPanelServiceImpl extends ServiceImpl<FacPhotovoltaic
Function.identity(),
(existing, replacement) -> existing // 如果有重复,保留第一个
));
List<FacFeatureByPlane> locationFeatures = geoJson.getLocationGeoJson().getFeatures();
List<FacGeoJsonByPlane> locationGeoJsonList = geoJson.getLocationGeoJson();
List<FacFeatureByPlane> locationFeatures = new ArrayList<>();
for (FacGeoJsonByPlane geoJsonByPlane : locationGeoJsonList) {
locationFeatures.addAll(geoJsonByPlane.getFeatures());
}
// 获取所有对应名称的点
List<FacGeoJsonByPoint> nameGeoJsonList = geoJson.getNameGeoJson();
List<FacFeatureByPoint> nameFeatures = new ArrayList<>();

View File

@ -12,8 +12,6 @@ import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.dromara.progress.domain.dto.progresscategory.PgsProgressCategoryCreateReq;
import org.dromara.progress.domain.dto.progresscategory.PgsProgressCategoryQueryReq;
@ -39,15 +37,6 @@ public class PgsProgressCategoryController extends BaseController {
@Resource
private IPgsProgressCategoryService pgsProgressCategoryService;
/**
* 分页查询进度类别列表
*/
@SaCheckPermission("progress:progressCategory:page")
@GetMapping("/page")
public TableDataInfo<PgsProgressCategoryVo> page(PgsProgressCategoryQueryReq req, PageQuery pageQuery) {
return pgsProgressCategoryService.queryPageList(req, pageQuery);
}
/**
* 查询进度类别列表
*/

View File

@ -0,0 +1,95 @@
package org.dromara.progress.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.dromara.progress.domain.dto.progressplan.PgsProgressPlanCreateReq;
import org.dromara.progress.domain.dto.progressplan.PgsProgressPlanQueryReq;
import org.dromara.progress.domain.vo.progressplan.PgsProgressPlanVo;
import org.dromara.progress.service.IPgsProgressPlanService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 进度计划
*
* @author lcj
* @date 2025-05-27
*/
@Validated
@RestController
@RequestMapping("/progress/progressPlan")
public class PgsProgressPlanController extends BaseController {
@Resource
private IPgsProgressPlanService pgsProgressPlanService;
/**
* 查询进度计划列表
*/
@SaCheckPermission("progress:progressPlan:list")
@GetMapping("/list")
public TableDataInfo<PgsProgressPlanVo> list(PgsProgressPlanQueryReq req, PageQuery pageQuery) {
return pgsProgressPlanService.queryPageList(req, pageQuery);
}
/**
* 导出进度计划列表
*/
@SaCheckPermission("progress:progressPlan:export")
@Log(title = "进度计划", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(PgsProgressPlanQueryReq req, HttpServletResponse response) {
List<PgsProgressPlanVo> list = pgsProgressPlanService.queryList(req);
ExcelUtil.exportExcel(list, "进度计划", PgsProgressPlanVo.class, response);
}
/**
* 获取进度计划详细信息
*
* @param id 主键
*/
@SaCheckPermission("progress:progressPlan:query")
@GetMapping("/{id}")
public R<PgsProgressPlanVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(pgsProgressPlanService.queryById(id));
}
/**
* 新增进度计划
*/
@SaCheckPermission("progress:progressPlan:add")
@Log(title = "进度计划", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Long> add(@Validated(AddGroup.class) @RequestBody PgsProgressPlanCreateReq req) {
return R.ok(pgsProgressPlanService.insertByBo(req));
}
/**
* 删除进度计划
*
* @param ids 主键串
*/
@SaCheckPermission("progress:progressPlan:remove")
@Log(title = "进度计划", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(pgsProgressPlanService.deleteWithValidByIds(List.of(ids), true));
}
}

View File

@ -0,0 +1,96 @@
package org.dromara.progress.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotNull;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.dromara.progress.domain.dto.progressplandetail.PgsProgressPlanDetailQueryReq;
import org.dromara.progress.domain.dto.progressplandetail.PgsProgressPlanDetailUpdateReq;
import org.dromara.progress.domain.vo.progressplandetail.PgsProgressPlanDetailFacilityVo;
import org.dromara.progress.domain.vo.progressplandetail.PgsProgressPlanDetailVo;
import org.dromara.progress.service.IPgsProgressPlanDetailService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 进度计划详情
*
* @author lcj
* @date 2025-05-27
*/
@Validated
@RestController
@RequestMapping("/progress/progressPlanDetail")
public class PgsProgressPlanDetailController extends BaseController {
@Resource
private IPgsProgressPlanDetailService pgsProgressPlanDetailService;
/**
* 查询进度计划详情列表
*/
@SaCheckPermission("progress:progressPlanDetail:list")
@GetMapping("/list")
public TableDataInfo<PgsProgressPlanDetailVo> list(PgsProgressPlanDetailQueryReq req, PageQuery pageQuery) {
return pgsProgressPlanDetailService.queryPageList(req, pageQuery);
}
/**
* 导出进度计划详情列表
*/
@SaCheckPermission("progress:progressPlanDetail:export")
@Log(title = "进度计划详情", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(PgsProgressPlanDetailQueryReq req, HttpServletResponse response) {
List<PgsProgressPlanDetailVo> list = pgsProgressPlanDetailService.queryList(req);
ExcelUtil.exportExcel(list, "进度计划详情", PgsProgressPlanDetailVo.class, response);
}
/**
* 获取进度计划详情详细信息
*
* @param id 主键
*/
@SaCheckPermission("progress:progressPlanDetail:query")
@GetMapping("/{id}")
public R<PgsProgressPlanDetailVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(pgsProgressPlanDetailService.queryById(id));
}
/**
* 获取进度计划详情详细信息
*
* @param id 主键
*/
@SaCheckPermission("progress:progressPlanDetail:query")
@GetMapping("/detail/{id}")
public R<TableDataInfo<PgsProgressPlanDetailFacilityVo>> getDetail(@NotNull(message = "主键不能为空")
@PathVariable Long id,
PageQuery pageQuery) {
return R.ok(pgsProgressPlanDetailService.queryFacilityById(id, pageQuery));
}
/**
* 修改进度计划详情
*/
@SaCheckPermission("progress:progressPlanDetail:edit")
@Log(title = "进度计划详情", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody PgsProgressPlanDetailUpdateReq req) {
return toAjax(pgsProgressPlanDetailService.updateByBo(req));
}
}

View File

@ -0,0 +1,90 @@
package org.dromara.progress.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import java.io.Serial;
import java.util.Date;
/**
* 进度计划对象 pgs_progress_plan
*
* @author lcj
* @date 2025-05-27
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("pgs_progress_plan")
public class PgsProgressPlan extends BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@TableId(value = "id")
private Long id;
/**
* 项目id
*/
private Long projectId;
/**
* 方阵id
*/
private Long matrixId;
/**
* 方阵名称
*/
private String matrixName;
/**
* 进度类型id
*/
private Long progressCategoryId;
/**
* 进度类别名称
*/
private String progressCategoryName;
/**
* 计划开始时间
*/
private Date startDate;
/**
* 计划结束时间
*/
private Date endDate;
/**
* 计划数量/百分比
*/
private Long planNumber;
/**
* 完成数量/百分比
*/
private Long finishedNumber;
/**
* 删除时间
*/
private Date deletedAt;
/**
* 是否删除0正常 1删除
*/
@TableLogic
private Long isDelete;
}

View File

@ -0,0 +1,75 @@
package org.dromara.progress.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import java.io.Serial;
import java.util.Date;
/**
* 进度计划详情对象 pgs_progress_plan_detail
*
* @author lcj
* @date 2025-05-27
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("pgs_progress_plan_detail")
public class PgsProgressPlanDetail extends BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@TableId(value = "id")
private Long id;
/**
* 项目id
*/
private Long projectId;
/**
* 进度计划id
*/
private Long progressPlanId;
/**
* 计划时间
*/
private Date date;
/**
* 计划数量/百分比
*/
private Long planNumber;
/**
* 完成数量/百分比
*/
private Long finishedNumber;
/**
* AI填入数量
*/
private Long aiFill;
/**
* 删除时间
*/
private Date deletedAt;
/**
* 是否删除0正常 1删除
*/
@TableLogic
private Long isDelete;
}

View File

@ -0,0 +1,59 @@
package org.dromara.progress.domain.dto.progressplan;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.dromara.progress.domain.dto.progressplandetail.PgsProgressPlanDetailCreateDto;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
* @author lcj
* @date 2025/5/27 10:21
*/
@Data
public class PgsProgressPlanCreateReq implements Serializable {
@Serial
private static final long serialVersionUID = -1696848895886843506L;
/**
* 项目id
*/
private Long projectId;
/**
* 方阵id
*/
private Long matrixId;
/**
* 进度类型id
*/
private Long progressCategoryId;
/**
* 计划开始时间
*/
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
private Date startDate;
/**
* 计划结束时间
*/
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
private Date endDate;
/**
* 计划数量/百分比
*/
private Long planNumber;
/**
* 计划详情列表
*/
List<PgsProgressPlanDetailCreateDto> detailList;
}

View File

@ -0,0 +1,47 @@
package org.dromara.progress.domain.dto.progressplan;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* @author lcj
* @date 2025/5/27 10:22
*/
@Data
public class PgsProgressPlanQueryReq implements Serializable {
@Serial
private static final long serialVersionUID = 2964218996260328296L;
/**
* 项目id
*/
private Long projectId;
/**
* 方阵id
*/
private Long matrixId;
/**
* 进度类型id
*/
private Long progressCategoryId;
/**
* 计划开始时间
*/
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
private Date startDate;
/**
* 计划结束时间
*/
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
private Date endDate;
}

View File

@ -0,0 +1,30 @@
package org.dromara.progress.domain.dto.progressplandetail;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
/**
* @author lcj
* @date 2025/5/27 15:06
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PgsProgressPlanDetailCreateDto {
/**
* 计划时间
*/
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
private Date date;
/**
* 计划数量/百分比
*/
private Long planNumber;
}

View File

@ -0,0 +1,34 @@
package org.dromara.progress.domain.dto.progressplandetail;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* @author lcj
* @date 2025/5/27 10:58
*/
@Data
public class PgsProgressPlanDetailQueryReq implements Serializable {
@Serial
private static final long serialVersionUID = -1135087412952022463L;
/**
* 项目id
*/
private Long projectId;
/**
* 进度计划id
*/
private Long progressPlanId;
/**
* 计划时间
*/
private Date date;
}

View File

@ -0,0 +1,18 @@
package org.dromara.progress.domain.dto.progressplandetail;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lcj
* @date 2025/5/27 10:58
*/
@Data
public class PgsProgressPlanDetailUpdateReq implements Serializable {
@Serial
private static final long serialVersionUID = -3397212461695330079L;
}

View File

@ -86,6 +86,16 @@ public class PgsProgressCategoryVo implements Serializable {
@ExcelProperty(value = "计划总数量/百分比")
private BigDecimal planTotal;
/**
* 已完成数量百分比
*/
private String completedPercentage;
/**
* 计划中数量百分比
*/
private String planTotalPercentage;
/**
* 是否超期0否 1是
*/

View File

@ -0,0 +1,77 @@
package org.dromara.progress.domain.vo.progressplan;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.progress.domain.PgsProgressPlan;
import org.dromara.progress.domain.vo.progressplandetail.PgsProgressPlanDetailNumVo;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
* 进度计划视图对象 pgs_progress_plan
*
* @author lcj
* @date 2025-05-27
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = PgsProgressPlan.class)
public class PgsProgressPlanVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@ExcelProperty(value = "主键id")
private Long id;
/**
* 进度类型id
*/
@ExcelProperty(value = "进度类型id")
private Long progressCategoryId;
/**
* 进度类别名称
*/
@ExcelProperty(value = "进度类别名称")
private String progressCategoryName;
/**
* 计划开始时间
*/
@ExcelProperty(value = "计划开始时间")
private Date startDate;
/**
* 计划结束时间
*/
@ExcelProperty(value = "计划结束时间")
private Date endDate;
/**
* 计划数量/百分比
*/
@ExcelProperty(value = "计划数量/百分比")
private Long planNumber;
/**
* 完成数量/百分比
*/
@ExcelProperty(value = "完成数量/百分比")
private Long finishedNumber;
/**
* 进度计划详情
*/
private List<PgsProgressPlanDetailNumVo> detailList;
}

View File

@ -0,0 +1,33 @@
package org.dromara.progress.domain.vo.progressplandetail;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lcj
* @date 2025/5/27 16:08
*/
@Data
public class PgsProgressPlanDetailFacilityVo implements Serializable {
@Serial
private static final long serialVersionUID = -4292009770864819304L;
/**
* 设施id
*/
private Long id;
/**
* 设施名称
*/
private String name;
/**
* 设施完成类型
*/
private String finishType;
}

View File

@ -0,0 +1,43 @@
package org.dromara.progress.domain.vo.progressplandetail;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
/**
* @author lcj
* @date 2025/5/27 14:31
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PgsProgressPlanDetailNumVo {
/**
* 主键id
*/
private Long id;
/**
* 计划时间
*/
private Date date;
/**
* 计划数量/百分比
*/
private Long planNumber;
/**
* 完成数量/百分比
*/
private Long finishedNumber;
/**
* AI填入数量
*/
private Long aiFill;
}

View File

@ -0,0 +1,72 @@
package org.dromara.progress.domain.vo.progressplandetail;
import java.util.Date;
import org.dromara.progress.domain.PgsProgressPlanDetail;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 进度计划详情视图对象 pgs_progress_plan_detail
*
* @author lcj
* @date 2025-05-27
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = PgsProgressPlanDetail.class)
public class PgsProgressPlanDetailVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@ExcelProperty(value = "主键id")
private Long id;
/**
* 项目id
*/
@ExcelProperty(value = "项目id")
private Long projectId;
/**
* 进度计划id
*/
@ExcelProperty(value = "进度计划id")
private Long progressPlanId;
/**
* 计划时间
*/
@ExcelProperty(value = "计划时间")
private Date date;
/**
* 计划数量/百分比
*/
@ExcelProperty(value = "计划数量/百分比")
private Long planNumber;
/**
* 完成数量/百分比
*/
@ExcelProperty(value = "完成数量/百分比")
private Long finishedNumber;
/**
* AI填入数量
*/
@ExcelProperty(value = "AI填入数量")
private Long aiFill;
}

View File

@ -0,0 +1,15 @@
package org.dromara.progress.mapper;
import org.dromara.progress.domain.PgsProgressPlanDetail;
import org.dromara.progress.domain.vo.progressplandetail.PgsProgressPlanDetailVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
/**
* 进度计划详情Mapper接口
*
* @author lcj
* @date 2025-05-27
*/
public interface PgsProgressPlanDetailMapper extends BaseMapperPlus<PgsProgressPlanDetail, PgsProgressPlanDetailVo> {
}

View File

@ -0,0 +1,15 @@
package org.dromara.progress.mapper;
import org.dromara.progress.domain.PgsProgressPlan;
import org.dromara.progress.domain.vo.progressplan.PgsProgressPlanVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
/**
* 进度计划Mapper接口
*
* @author lcj
* @date 2025-05-27
*/
public interface PgsProgressPlanMapper extends BaseMapperPlus<PgsProgressPlan, PgsProgressPlanVo> {
}

View File

@ -1,10 +1,7 @@
package org.dromara.progress.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.progress.domain.PgsProgressCategory;
import org.dromara.progress.domain.dto.progresscategory.PgsProgressCategoryCreateReq;
import org.dromara.progress.domain.dto.progresscategory.PgsProgressCategoryQueryReq;
@ -30,15 +27,6 @@ public interface IPgsProgressCategoryService extends IService<PgsProgressCategor
*/
PgsProgressCategoryVo queryById(Long id);
/**
* 分页查询进度类别
*
* @param req 查询条件
* @param pageQuery 分页参数
* @return 进度类别分页列表
*/
TableDataInfo<PgsProgressCategoryVo> queryPageList(PgsProgressCategoryQueryReq req, PageQuery pageQuery);
/**
* 查询符合条件的进度类别列表
*
@ -89,12 +77,12 @@ public interface IPgsProgressCategoryService extends IService<PgsProgressCategor
LambdaQueryWrapper<PgsProgressCategory> buildQueryWrapper(PgsProgressCategoryQueryReq req);
/**
* 获取进度类别分页对象视图
* 获取进度类别列表对象视图
*
* @param progressCategoryPage 进度类别分页对象
* @return 进度类别分页对象视图
* @param progressCategoryList 进度类别列表对象
* @return 进度类别列表对象视图
*/
Page<PgsProgressCategoryVo> getVoPage(Page<PgsProgressCategory> progressCategoryPage);
List<PgsProgressCategoryVo> getVoList(List<PgsProgressCategory> progressCategoryList);
/**
* 根据模板创建进度类别

View File

@ -0,0 +1,99 @@
package org.dromara.progress.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.progress.domain.PgsProgressPlanDetail;
import org.dromara.progress.domain.dto.progressplandetail.PgsProgressPlanDetailQueryReq;
import org.dromara.progress.domain.dto.progressplandetail.PgsProgressPlanDetailUpdateReq;
import org.dromara.progress.domain.vo.progressplandetail.PgsProgressPlanDetailFacilityVo;
import org.dromara.progress.domain.vo.progressplandetail.PgsProgressPlanDetailNumVo;
import org.dromara.progress.domain.vo.progressplandetail.PgsProgressPlanDetailVo;
import java.util.List;
/**
* 进度计划详情Service接口
*
* @author lcj
* @date 2025-05-27
*/
public interface IPgsProgressPlanDetailService extends IService<PgsProgressPlanDetail> {
/**
* 查询进度计划详情
*
* @param id 主键
* @return 进度计划详情
*/
PgsProgressPlanDetailVo queryById(Long id);
/**
* 分页查询进度计划详情列表
*
* @param req 查询条件
* @param pageQuery 分页参数
* @return 进度计划详情分页列表
*/
TableDataInfo<PgsProgressPlanDetailVo> queryPageList(PgsProgressPlanDetailQueryReq req, PageQuery pageQuery);
/**
* 查询符合条件的进度计划详情列表
*
* @param req 查询条件
* @return 进度计划详情列表
*/
List<PgsProgressPlanDetailVo> queryList(PgsProgressPlanDetailQueryReq req);
/**
* 分页查询进度计划详情设施列表
*
* @param id 主键
* @param pageQuery 分页参数
* @return 进度计划详情设施分页列表
*/
TableDataInfo<PgsProgressPlanDetailFacilityVo> queryFacilityById(Long id, PageQuery pageQuery);
/**
* 修改进度计划详情
*
* @param req 进度计划详情
* @return 是否修改成功
*/
Boolean updateByBo(PgsProgressPlanDetailUpdateReq req);
/**
* 获取进度计划详情视图对象
*
* @param progressPlanDetail 进度计划详情对象
* @return 进度计划详情视图对象
*/
PgsProgressPlanDetailVo getVo(PgsProgressPlanDetail progressPlanDetail);
/**
* 获取进度计划详情视图对象列表
*
* @param progressPlanDetailList 进度计划详情对象列表
* @return 进度计划详情视图对象列表
*/
List<PgsProgressPlanDetailNumVo> getNumVoList(List<PgsProgressPlanDetail> progressPlanDetailList);
/**
* 获取进度计划详情查询条件封装
*
* @param req 查询条件
* @return 查询条件封装
*/
LambdaQueryWrapper<PgsProgressPlanDetail> buildQueryWrapper(PgsProgressPlanDetailQueryReq req);
/**
* 获取进度计划详情分页对象视图
*
* @param progressPlanDetailPage 进度计划详情分页对象
* @return 进度计划详情分页对象视图
*/
Page<PgsProgressPlanDetailVo> getVoPage(Page<PgsProgressPlanDetail> progressPlanDetailPage);
}

View File

@ -0,0 +1,98 @@
package org.dromara.progress.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.progress.domain.PgsProgressPlan;
import org.dromara.progress.domain.dto.progressplan.PgsProgressPlanCreateReq;
import org.dromara.progress.domain.dto.progressplan.PgsProgressPlanQueryReq;
import org.dromara.progress.domain.vo.progressplan.PgsProgressPlanVo;
import java.util.Collection;
import java.util.List;
/**
* 进度计划Service接口
*
* @author lcj
* @date 2025-05-27
*/
public interface IPgsProgressPlanService extends IService<PgsProgressPlan> {
/**
* 查询进度计划
*
* @param id 主键
* @return 进度计划
*/
PgsProgressPlanVo queryById(Long id);
/**
* 分页查询进度计划列表
*
* @param req 查询条件
* @param pageQuery 分页参数
* @return 进度计划分页列表
*/
TableDataInfo<PgsProgressPlanVo> queryPageList(PgsProgressPlanQueryReq req, PageQuery pageQuery);
/**
* 查询符合条件的进度计划列表
*
* @param req 查询条件
* @return 进度计划列表
*/
List<PgsProgressPlanVo> queryList(PgsProgressPlanQueryReq req);
/**
* 新增进度计划
*
* @param req 进度计划
* @return 新增进度计划主键
*/
Long insertByBo(PgsProgressPlanCreateReq req);
/**
* 校验并批量删除进度计划信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
/**
* 获取进度计划视图对象
*
* @param progressPlan 进度计划对象
* @return 进度计划视图对象
*/
PgsProgressPlanVo getVo(PgsProgressPlan progressPlan);
/**
* 获取进度计划查询条件封装
*
* @param req 查询条件
* @return 查询条件封装
*/
LambdaQueryWrapper<PgsProgressPlan> buildQueryWrapper(PgsProgressPlanQueryReq req);
/**
* 获取进度计划分页对象视图
*
* @param progressPlanPage 进度计划分页对象
* @return 进度计划分页对象视图
*/
Page<PgsProgressPlanVo> getVoPage(Page<PgsProgressPlan> progressPlanPage);
/**
* 校验计划数量是否合法
*
* @param planNumber 计划数量
* @param progressCategoryId 进度类别id
*/
void validPlanNumber(Long planNumber, Long progressCategoryId);
}

View File

@ -4,14 +4,11 @@ import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.dromara.common.core.constant.HttpStatus;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.ObjectUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.facility.domain.FacPercentageFacility;
import org.dromara.facility.service.IFacPercentageFacilityService;
import org.dromara.progress.constant.PgsProgressCategoryConstant;
@ -25,12 +22,14 @@ import org.dromara.progress.domain.vo.progresscategory.PgsProgressCategoryVo;
import org.dromara.progress.mapper.PgsProgressCategoryMapper;
import org.dromara.progress.service.IPgsProgressCategoryService;
import org.dromara.progress.service.IPgsProgressCategoryTemplateService;
import org.dromara.utils.BigDecimalUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
/**
* 进度类别Service业务层处理
@ -63,19 +62,6 @@ public class PgsProgressCategoryServiceImpl extends ServiceImpl<PgsProgressCateg
return this.getVo(progressCategory);
}
/**
* 分页查询进度类别
*
* @param req 查询条件
* @param pageQuery 分页参数
* @return 进度类别分页列表
*/
@Override
public TableDataInfo<PgsProgressCategoryVo> queryPageList(PgsProgressCategoryQueryReq req, PageQuery pageQuery) {
Page<PgsProgressCategory> progressCategoryPage = this.page(pageQuery.build(), this.buildQueryWrapper(req));
return TableDataInfo.build(this.getVoPage(progressCategoryPage));
}
/**
* 查询符合条件的进度类别列表
*
@ -85,7 +71,7 @@ public class PgsProgressCategoryServiceImpl extends ServiceImpl<PgsProgressCateg
@Override
public List<PgsProgressCategoryVo> queryList(PgsProgressCategoryQueryReq req) {
List<PgsProgressCategory> list = this.list(this.buildQueryWrapper(req));
return list.stream().map(this::getVo).toList();
return this.getVoList(list);
}
/**
@ -221,27 +207,41 @@ public class PgsProgressCategoryServiceImpl extends ServiceImpl<PgsProgressCateg
}
/**
* 获取进度类别分页对象视图
* 获取进度类别列表对象视图
*
* @param progressCategoryPage 进度类别分页对象
* @return 进度类别分页对象视图
* @param progressCategoryList 进度类别列表对象
* @return 进度类别列表对象视图
*/
@Override
public Page<PgsProgressCategoryVo> getVoPage(Page<PgsProgressCategory> progressCategoryPage) {
List<PgsProgressCategory> progressCategoryList = progressCategoryPage.getRecords();
Page<PgsProgressCategoryVo> progressCategoryVoPage = new Page<>(progressCategoryPage.getCurrent(), progressCategoryPage.getSize(), progressCategoryPage.getTotal());
public List<PgsProgressCategoryVo> getVoList(List<PgsProgressCategory> progressCategoryList) {
if (CollUtil.isEmpty(progressCategoryList)) {
return progressCategoryVoPage;
return List.of();
}
// 1. 构建 pid -> 子节点列表的映射
Map<Long, List<PgsProgressCategory>> parentIdToChildrenMap = progressCategoryList.stream()
.filter(item -> item.getPid() != 0)
.collect(Collectors.groupingBy(PgsProgressCategory::getPid));
// 对象列表 => 封装对象列表
List<PgsProgressCategoryVo> progressCategoryVoList = progressCategoryList.stream().map(progressCategory -> {
// 对象转封装类
PgsProgressCategoryVo progressCategoryVo = new PgsProgressCategoryVo();
BeanUtils.copyProperties(progressCategory, progressCategoryVo);
return progressCategoryVo;
return progressCategoryList.stream().map(progressCategory -> {
PgsProgressCategoryVo vo = new PgsProgressCategoryVo();
BeanUtils.copyProperties(progressCategory, vo);
// 如果是父节点,计算其子节点的总和
if (progressCategory.getPid() == 0) {
List<PgsProgressCategory> children = parentIdToChildrenMap.getOrDefault(progressCategory.getId(), Collections.emptyList());
// 累加子节点数据
BigDecimal total = children.stream().map(PgsProgressCategory::getTotal).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal completed = children.stream().map(PgsProgressCategory::getCompleted).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal planTotal = children.stream().map(PgsProgressCategory::getPlanTotal).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
// 可以在 VO 中额外设置这些总和值(或替换原有字段)
vo.setTotal(total);
vo.setCompleted(completed);
vo.setPlanTotal(planTotal);
}
// 计算百分比(避免除以 0
vo.setCompletedPercentage(BigDecimalUtil.toPercentage(vo.getCompleted(), vo.getTotal()));
vo.setPlanTotalPercentage(BigDecimalUtil.toPercentage(vo.getPlanTotal(), vo.getTotal()));
return vo;
}).toList();
progressCategoryVoPage.setRecords(progressCategoryVoList);
return progressCategoryVoPage;
}
/**
@ -264,9 +264,10 @@ public class PgsProgressCategoryServiceImpl extends ServiceImpl<PgsProgressCateg
}
List<PgsProgressCategory> newList = new ArrayList<>();
List<FacPercentageFacility> percentageFacilityList = new ArrayList<>();
// 每个 matrixId 对应一套新的 ID 映射
for (Long matrixId : matrixIds) {
// 每个 matrixId 对应一套新的 ID 映射
Map<Long, Long> localIdMap = new HashMap<>(); // templateId -> newId
// templateId -> newId
Map<Long, Long> localIdMap = new HashMap<>();
List<PgsProgressCategory> localList = new ArrayList<>();
for (PgsProgressCategoryTemplate template : categoryTemplateList) {
Long newId = IdWorker.getId();
@ -278,7 +279,8 @@ public class PgsProgressCategoryServiceImpl extends ServiceImpl<PgsProgressCateg
newCategory.setWorkType(template.getWorkType());
newCategory.setProjectId(projectId);
newCategory.setMatrixId(matrixId);
newCategory.setPid(template.getPid()); // 先临时设置旧 pid
// 先临时设置旧 pid
newCategory.setPid(template.getPid());
localList.add(newCategory);
// 创建百分比设施
if (template.getPid() != 0 && template.getUnitType().equals(PgsProgressUnitTypeEnum.PERCENTAGE.getValue())) {

View File

@ -0,0 +1,263 @@
package org.dromara.progress.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.dromara.common.core.constant.HttpStatus;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.ObjectUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.facility.domain.FacBoxTransformer;
import org.dromara.facility.domain.FacInverter;
import org.dromara.facility.domain.FacPhotovoltaicPanel;
import org.dromara.facility.domain.enums.FacFinishStatusEnum;
import org.dromara.facility.service.IFacBoxTransformerService;
import org.dromara.facility.service.IFacInverterService;
import org.dromara.facility.service.IFacPhotovoltaicPanelService;
import org.dromara.progress.constant.PgsProgressCategoryConstant;
import org.dromara.progress.domain.PgsProgressCategory;
import org.dromara.progress.domain.PgsProgressPlan;
import org.dromara.progress.domain.PgsProgressPlanDetail;
import org.dromara.progress.domain.dto.progressplandetail.PgsProgressPlanDetailQueryReq;
import org.dromara.progress.domain.dto.progressplandetail.PgsProgressPlanDetailUpdateReq;
import org.dromara.progress.domain.vo.progressplandetail.PgsProgressPlanDetailFacilityVo;
import org.dromara.progress.domain.vo.progressplandetail.PgsProgressPlanDetailNumVo;
import org.dromara.progress.domain.vo.progressplandetail.PgsProgressPlanDetailVo;
import org.dromara.progress.mapper.PgsProgressPlanDetailMapper;
import org.dromara.progress.service.IPgsProgressCategoryService;
import org.dromara.progress.service.IPgsProgressPlanDetailService;
import org.dromara.progress.service.IPgsProgressPlanService;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.List;
/**
* 进度计划详情Service业务层处理
*
* @author lcj
* @date 2025-05-27
*/
@Service
public class PgsProgressPlanDetailServiceImpl extends ServiceImpl<PgsProgressPlanDetailMapper, PgsProgressPlanDetail>
implements IPgsProgressPlanDetailService {
@Lazy
@Resource
private IPgsProgressPlanService progressPlanService;
@Resource
private IFacBoxTransformerService boxTransformerService;
@Resource
private IFacInverterService inverterService;
@Resource
private IFacPhotovoltaicPanelService photovoltaicPanelService;
@Resource
private IPgsProgressCategoryService progressCategoryService;
/**
* 查询进度计划详情
*
* @param id 主键
* @return 进度计划详情
*/
@Override
public PgsProgressPlanDetailVo queryById(Long id) {
PgsProgressPlanDetail progressPlanDetail = this.getById(id);
if (progressPlanDetail == null) {
throw new ServiceException("进度计划详情信息不存在", HttpStatus.NOT_FOUND);
}
return this.getVo(progressPlanDetail);
}
/**
* 分页查询进度计划详情列表
*
* @param req 查询条件
* @param pageQuery 分页参数
* @return 进度计划详情分页列表
*/
@Override
public TableDataInfo<PgsProgressPlanDetailVo> queryPageList(PgsProgressPlanDetailQueryReq req, PageQuery pageQuery) {
Page<PgsProgressPlanDetail> result = this.page(pageQuery.build(), this.buildQueryWrapper(req));
return TableDataInfo.build(this.getVoPage(result));
}
/**
* 查询符合条件的进度计划详情列表
*
* @param req 查询条件
* @return 进度计划详情列表
*/
@Override
public List<PgsProgressPlanDetailVo> queryList(PgsProgressPlanDetailQueryReq req) {
List<PgsProgressPlanDetail> list = this.list(this.buildQueryWrapper(req));
return list.stream().map(this::getVo).toList();
}
/**
* 分页查询进度计划详情设施列表
*
* @param id 主键
* @param pageQuery 分页参数
* @return 进度计划详情设施分页列表
*/
@Override
public TableDataInfo<PgsProgressPlanDetailFacilityVo> queryFacilityById(Long id, PageQuery pageQuery) {
PgsProgressPlanDetail progressPlanDetail = this.getById(id);
if (progressPlanDetail == null) {
throw new ServiceException("进度计划详情信息不存在", HttpStatus.NOT_FOUND);
}
PgsProgressPlan progressPlan = progressPlanService.getById(progressPlanDetail.getProgressPlanId());
if (progressPlan == null) {
throw new ServiceException("进度计划信息不存在", HttpStatus.NOT_FOUND);
}
Long progressCategoryId = progressPlan.getProgressCategoryId();
Long projectId = progressPlan.getProjectId();
Long matrixId = progressPlan.getMatrixId();
PgsProgressCategory progressCategory = progressCategoryService.getById(progressCategoryId);
if (progressCategory == null) {
throw new ServiceException("进度计划类别信息不存在", HttpStatus.NOT_FOUND);
}
String workType = progressCategory.getWorkType();
Page<PgsProgressPlanDetailFacilityVo> resultPage = pageQuery.build();
if (PgsProgressCategoryConstant.PHOTOVOLTAIC_PANEL_PROGRESS_CATEGORY_WORK_TYPE.contains(workType)) {
LambdaQueryWrapper<FacPhotovoltaicPanel> lqw = new LambdaQueryWrapper<>();
lqw.eq(FacPhotovoltaicPanel::getProjectId, projectId);
lqw.eq(FacPhotovoltaicPanel::getMatrixId, matrixId);
lqw.eq(FacPhotovoltaicPanel::getProgressCategoryId, progressCategoryId);
lqw.eq(FacPhotovoltaicPanel::getFinishDate, progressPlanDetail.getDate());
lqw.eq(FacPhotovoltaicPanel::getFinishType, FacFinishStatusEnum.FINISH.getValue());
Page<FacPhotovoltaicPanel> result = photovoltaicPanelService.page(pageQuery.build(), lqw);
List<FacPhotovoltaicPanel> records = result.getRecords();
List<PgsProgressPlanDetailFacilityVo> facilityVoList = records.stream().map(photovoltaicPanel -> {
PgsProgressPlanDetailFacilityVo facilityVo = new PgsProgressPlanDetailFacilityVo();
facilityVo.setId(photovoltaicPanel.getId());
facilityVo.setName(photovoltaicPanel.getName());
facilityVo.setFinishType(photovoltaicPanel.getFinishType());
return facilityVo;
}).toList();
resultPage.setRecords(facilityVoList);
} else if (PgsProgressCategoryConstant.INVERTER_PROGRESS_CATEGORY_WORK_TYPE.contains(workType)) {
LambdaQueryWrapper<FacInverter> lqw = new LambdaQueryWrapper<>();
lqw.eq(FacInverter::getProjectId, projectId);
lqw.eq(FacInverter::getMatrixId, matrixId);
lqw.eq(FacInverter::getProgressCategoryId, progressCategoryId);
lqw.eq(FacInverter::getFinishDate, progressPlanDetail.getDate());
lqw.eq(FacInverter::getFinishType, FacFinishStatusEnum.FINISH.getValue());
Page<FacInverter> result = inverterService.page(pageQuery.build(), lqw);
List<FacInverter> records = result.getRecords();
List<PgsProgressPlanDetailFacilityVo> facilityVoList = records.stream().map(inverter -> {
PgsProgressPlanDetailFacilityVo facilityVo = new PgsProgressPlanDetailFacilityVo();
facilityVo.setId(inverter.getId());
facilityVo.setName(inverter.getName());
facilityVo.setFinishType(inverter.getFinishType());
return facilityVo;
}).toList();
resultPage.setRecords(facilityVoList);
} else if (PgsProgressCategoryConstant.BOX_TRANSFORMER_PROGRESS_CATEGORY_WORK_TYPE.contains(workType)) {
LambdaQueryWrapper<FacBoxTransformer> lqw = new LambdaQueryWrapper<>();
lqw.eq(FacBoxTransformer::getProjectId, projectId);
lqw.eq(FacBoxTransformer::getMatrixId, matrixId);
lqw.eq(FacBoxTransformer::getProgressCategoryId, progressCategoryId);
lqw.eq(FacBoxTransformer::getFinishDate, progressPlanDetail.getDate());
lqw.eq(FacBoxTransformer::getFinishType, FacFinishStatusEnum.FINISH.getValue());
Page<FacBoxTransformer> result = boxTransformerService.page(pageQuery.build(), lqw);
List<FacBoxTransformer> records = result.getRecords();
List<PgsProgressPlanDetailFacilityVo> facilityVoList = records.stream().map(boxTransformer -> {
PgsProgressPlanDetailFacilityVo facilityVo = new PgsProgressPlanDetailFacilityVo();
facilityVo.setId(boxTransformer.getId());
facilityVo.setName(boxTransformer.getName());
facilityVo.setFinishType(boxTransformer.getFinishType());
return facilityVo;
}).toList();
resultPage.setRecords(facilityVoList);
} else {
throw new ServiceException("未知进度计划类别工作类型", HttpStatus.BAD_REQUEST);
}
return TableDataInfo.build(resultPage);
}
/**
* 修改进度计划详情
*
* @param req 进度计划详情
* @return 是否修改成功
*/
@Override
public Boolean updateByBo(PgsProgressPlanDetailUpdateReq req) {
return null;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(PgsProgressPlanDetail entity) {
//TODO 做一些数据校验,如唯一约束
}
/**
* 获取进度计划详情视图对象
*
* @param progressPlanDetail 进度计划详情对象
* @return 进度计划详情视图对象
*/
@Override
public PgsProgressPlanDetailVo getVo(PgsProgressPlanDetail progressPlanDetail) {
return null;
}
/**
* 获取进度计划详情视图对象列表
*
* @param progressPlanDetailList 进度计划详情对象列表
* @return 进度计划详情视图对象列表
*/
@Override
public List<PgsProgressPlanDetailNumVo> getNumVoList(List<PgsProgressPlanDetail> progressPlanDetailList) {
return progressPlanDetailList.stream().map(progressPlanDetail -> {
PgsProgressPlanDetailNumVo progressPlanDetailNumVo = new PgsProgressPlanDetailNumVo();
BeanUtils.copyProperties(progressPlanDetail, progressPlanDetailNumVo);
return progressPlanDetailNumVo;
}).toList();
}
/**
* 获取进度计划详情查询条件封装
*
* @param req 查询条件
* @return 查询条件封装
*/
@Override
public LambdaQueryWrapper<PgsProgressPlanDetail> buildQueryWrapper(PgsProgressPlanDetailQueryReq req) {
LambdaQueryWrapper<PgsProgressPlanDetail> lqw = new LambdaQueryWrapper<>();
if (req == null) {
return lqw;
}
Long projectId = req.getProjectId();
Long progressPlanId = req.getProgressPlanId();
Date date = req.getDate();
lqw.eq(ObjectUtils.isNotEmpty(projectId), PgsProgressPlanDetail::getProjectId, projectId);
lqw.eq(ObjectUtils.isNotEmpty(progressPlanId), PgsProgressPlanDetail::getProgressPlanId, progressPlanId);
lqw.eq(ObjectUtils.isNotEmpty(date), PgsProgressPlanDetail::getDate, date);
return lqw;
}
/**
* 获取进度计划详情分页对象视图
*
* @param progressPlanDetailPage 进度计划详情分页对象
* @return 进度计划详情分页对象视图
*/
@Override
public Page<PgsProgressPlanDetailVo> getVoPage(Page<PgsProgressPlanDetail> progressPlanDetailPage) {
return null;
}
}

View File

@ -0,0 +1,300 @@
package org.dromara.progress.service.impl;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.dromara.common.core.constant.HttpStatus;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.ObjectUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
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.service.IFacMatrixService;
import org.dromara.progress.domain.PgsProgressCategory;
import org.dromara.progress.domain.PgsProgressPlan;
import org.dromara.progress.domain.PgsProgressPlanDetail;
import org.dromara.progress.domain.dto.progressplan.PgsProgressPlanCreateReq;
import org.dromara.progress.domain.dto.progressplan.PgsProgressPlanQueryReq;
import org.dromara.progress.domain.dto.progressplandetail.PgsProgressPlanDetailCreateDto;
import org.dromara.progress.domain.vo.progressplan.PgsProgressPlanVo;
import org.dromara.progress.domain.vo.progressplandetail.PgsProgressPlanDetailNumVo;
import org.dromara.progress.mapper.PgsProgressPlanMapper;
import org.dromara.progress.service.IPgsProgressCategoryService;
import org.dromara.progress.service.IPgsProgressPlanDetailService;
import org.dromara.progress.service.IPgsProgressPlanService;
import org.dromara.project.service.IBusProjectService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
/**
* 进度计划Service业务层处理
*
* @author lcj
* @date 2025-05-27
*/
@Service
public class PgsProgressPlanServiceImpl extends ServiceImpl<PgsProgressPlanMapper, PgsProgressPlan>
implements IPgsProgressPlanService {
@Resource
private IBusProjectService projectService;
@Resource
private IPgsProgressPlanDetailService progressPlanDetailService;
@Resource
private IPgsProgressCategoryService progressCategoryService;
@Resource
private IFacMatrixService matrixService;
/**
* 查询进度计划
*
* @param id 主键
* @return 进度计划
*/
@Override
public PgsProgressPlanVo queryById(Long id) {
PgsProgressPlan progressPlan = this.getById(id);
if (progressPlan == null) {
throw new ServiceException("进度计划信息不存在", HttpStatus.NOT_FOUND);
}
return this.getVo(progressPlan);
}
/**
* 分页查询进度计划列表
*
* @param req 查询条件
* @param pageQuery 分页参数
* @return 进度计划分页列表
*/
@Override
public TableDataInfo<PgsProgressPlanVo> queryPageList(PgsProgressPlanQueryReq req, PageQuery pageQuery) {
Page<PgsProgressPlan> result = this.page(pageQuery.build(), this.buildQueryWrapper(req));
return TableDataInfo.build(this.getVoPage(result));
}
/**
* 查询符合条件的进度计划列表
*
* @param req 查询条件
* @return 进度计划列表
*/
@Override
public List<PgsProgressPlanVo> queryList(PgsProgressPlanQueryReq req) {
List<PgsProgressPlan> list = this.list(this.buildQueryWrapper(req));
return list.stream().map(this::getVo).toList();
}
/**
* 新增进度计划
*
* @param req 进度计划
* @return 新增进度计划主键
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Long insertByBo(PgsProgressPlanCreateReq req) {
// 将实体类和 DTO 进行转换
PgsProgressPlan progressPlan = new PgsProgressPlan();
BeanUtils.copyProperties(req, progressPlan);
// 数据校验
Long projectId = progressPlan.getProjectId();
if (projectService.getById(projectId) == null) {
throw new ServiceException("对应项目不存在", HttpStatus.NOT_FOUND);
}
Long matrixId = progressPlan.getMatrixId();
FacMatrix matrix = matrixService.getById(matrixId);
if (matrix == null) {
throw new ServiceException("对应方阵不存在", HttpStatus.NOT_FOUND);
}
Long progressCategoryId = progressPlan.getProgressCategoryId();
this.validPlanNumber(req.getPlanNumber(), progressCategoryId);
progressPlan.setMatrixName(matrix.getMatrixName());
// 操作数据库
boolean save = this.save(progressPlan);
if (!save) {
throw new ServiceException("新增进度计划失败,数据库异常", HttpStatus.ERROR);
}
// 更新进度计划详情
Long id = progressPlan.getId();
List<PgsProgressPlanDetailCreateDto> detailList = req.getDetailList();
if (CollUtil.isNotEmpty(detailList)) {
List<PgsProgressPlanDetail> detailList1 = detailList.stream().map(detail -> {
PgsProgressPlanDetail progressPlanDetail = new PgsProgressPlanDetail();
BeanUtils.copyProperties(detail, progressPlanDetail);
progressPlanDetail.setProgressPlanId(id);
progressPlanDetail.setProjectId(progressPlan.getProjectId());
return progressPlanDetail;
}).toList();
boolean result = progressPlanDetailService.saveBatch(detailList1);
if (!result) {
throw new ServiceException("新增进度计划详情失败,数据库操作失败", HttpStatus.ERROR);
}
}
// 更新进度分类计划总数量
boolean update = progressCategoryService.lambdaUpdate()
.eq(PgsProgressCategory::getId, progressCategoryId)
.set(PgsProgressCategory::getPlanTotal, progressPlan.getPlanNumber())
.update();
if (!update) {
throw new ServiceException("更新进度分类计划总数量失败,数据库操作失败", HttpStatus.ERROR);
}
return id;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeSave(PgsProgressPlan entity) {
// TODO 做一些数据校验,如唯一约束
Long projectId = entity.getProjectId();
if (projectService.getById(projectId) == null) {
throw new ServiceException("对应项目不存在", HttpStatus.NOT_FOUND);
}
Long matrixId = entity.getMatrixId();
if (matrixService.getById(matrixId) == null) {
throw new ServiceException("对应方阵不存在", HttpStatus.NOT_FOUND);
}
}
/**
* 校验并批量删除进度计划信息
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
* @return 是否删除成功
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
Long userId = LoginHelper.getUserId();
List<PgsProgressPlan> progressPlanList = this.listByIds(ids);
if (isValid) {
//TODO 做一些业务上的校验,判断是否需要校验
List<Long> projectId = progressPlanList.stream().map(PgsProgressPlan::getProjectId).toList();
projectService.validAuth(projectId, userId);
}
return this.removeBatchByIds(ids);
}
/**
* 获取进度计划视图对象
*
* @param progressPlan 进度计划对象
* @return 进度计划视图对象
*/
@Override
public PgsProgressPlanVo getVo(PgsProgressPlan progressPlan) {
// 对象转封装类
PgsProgressPlanVo progressPlanVo = new PgsProgressPlanVo();
if (progressPlan == null) {
return progressPlanVo;
}
BeanUtils.copyProperties(progressPlan, progressPlanVo);
// 获取详情列表
Long id = progressPlan.getId();
List<PgsProgressPlanDetail> detailList = progressPlanDetailService.lambdaQuery()
.eq(PgsProgressPlanDetail::getProgressPlanId, id)
.eq(PgsProgressPlanDetail::getProjectId, progressPlan.getProjectId())
.list();
progressPlanVo.setDetailList(progressPlanDetailService.getNumVoList(detailList));
return progressPlanVo;
}
/**
* 获取进度计划查询条件封装
*
* @param req 查询条件
* @return 查询条件封装
*/
@Override
public LambdaQueryWrapper<PgsProgressPlan> buildQueryWrapper(PgsProgressPlanQueryReq req) {
LambdaQueryWrapper<PgsProgressPlan> lqw = new LambdaQueryWrapper<>();
if (req == null) {
return lqw;
}
Long projectId = req.getProjectId();
Long matrixId = req.getMatrixId();
Long progressCategoryId = req.getProgressCategoryId();
Date startDate = req.getStartDate();
Date endDate = req.getEndDate();
lqw.eq(ObjectUtils.isNotEmpty(projectId), PgsProgressPlan::getProjectId, projectId);
lqw.eq(ObjectUtils.isNotEmpty(matrixId), PgsProgressPlan::getMatrixId, matrixId);
lqw.eq(ObjectUtils.isNotEmpty(progressCategoryId), PgsProgressPlan::getProgressCategoryId, progressCategoryId);
// 日期条件大于startDate小于endDate
lqw.gt(ObjectUtils.isNotEmpty(startDate), PgsProgressPlan::getStartDate, startDate);
lqw.lt(ObjectUtils.isNotEmpty(endDate), PgsProgressPlan::getEndDate, endDate);
return lqw;
}
/**
* 获取进度计划分页对象视图
*
* @param progressPlanPage 进度计划分页对象
* @return 进度计划分页对象视图
*/
@Override
public Page<PgsProgressPlanVo> getVoPage(Page<PgsProgressPlan> progressPlanPage) {
List<PgsProgressPlan> progressPlanList = progressPlanPage.getRecords();
Page<PgsProgressPlanVo> progressPlanVoPage = new Page<>(
progressPlanPage.getCurrent(),
progressPlanPage.getSize(),
progressPlanPage.getTotal());
if (CollUtil.isEmpty(progressPlanList)) {
return progressPlanVoPage;
}
// 获取详情列表
List<Long> idList = progressPlanList.stream().map(PgsProgressPlan::getId).toList();
List<PgsProgressPlanDetail> detailList = progressPlanDetailService.lambdaQuery()
.in(PgsProgressPlanDetail::getProgressPlanId, idList).list();
Map<Long, List<PgsProgressPlanDetail>> detailMap = detailList
.stream().collect(Collectors.groupingBy(PgsProgressPlanDetail::getProgressPlanId));
// 对象列表 => 封装对象列表
List<PgsProgressPlanVo> progressPlanVoList = progressPlanList.stream().map(progressPlan -> {
// 对象转封装类
PgsProgressPlanVo progressPlanVo = new PgsProgressPlanVo();
BeanUtils.copyProperties(progressPlan, progressPlanVo);
// 获取详情列表
Long id = progressPlan.getId();
List<PgsProgressPlanDetailNumVo> numDetailList = new ArrayList<>();
if (detailMap.containsKey(id)) {
numDetailList = progressPlanDetailService.getNumVoList(detailMap.get(id));
}
progressPlanVo.setDetailList(numDetailList);
return progressPlanVo;
}).toList();
progressPlanVoPage.setRecords(progressPlanVoList);
return progressPlanVoPage;
}
/**
* 校验计划数量是否合法
*
* @param planNumber 计划数量
* @param progressCategoryId 进度类别id
*/
@Override
public void validPlanNumber(Long planNumber, Long progressCategoryId) {
PgsProgressCategory progressCategory = progressCategoryService.getById(progressCategoryId);
if (progressCategory == null) {
throw new ServiceException("进度类别不存在", HttpStatus.NOT_FOUND);
}
BigDecimal total = progressCategory.getTotal();
BigDecimal completed = progressCategory.getCompleted();
BigDecimal planTotal = total.subtract(completed);
if (planNumber.compareTo(planTotal.longValue()) > 0) {
throw new ServiceException("计划数量不能大于剩余数量", HttpStatus.BAD_REQUEST);
}
}
}

View File

@ -101,8 +101,8 @@ public class BusProjectFileController extends BaseController {
*/
@Log(title = "项目文件存储", businessType = BusinessType.IMPORT)
@PostMapping("/upload/dxf")
public R<Long> uploadDxf2Json(@RequestParam("file") MultipartFile file, BusProjectFileUploadDxfReq req) {
return R.ok(busProjectFileService.uploadDxf2Json(file, req));
public R<Void> uploadDxf2Json(@RequestParam("file") MultipartFile file, BusProjectFileUploadDxfReq req) {
return toAjax(busProjectFileService.uploadDxf2Json(file, req));
}
/**

View File

@ -79,9 +79,9 @@ public interface IBusProjectFileService extends IService<BusProjectFile> {
*
* @param file 文件
* @param req 请求
* @return 主键
* @return 是否上传文件成功
*/
Long uploadDxf2Json(MultipartFile file, BusProjectFileUploadDxfReq req);
Boolean uploadDxf2Json(MultipartFile file, BusProjectFileUploadDxfReq req);
/**
* 获取项目文件存储视图对象

View File

@ -209,11 +209,11 @@ public class BusProjectFileServiceImpl extends ServiceImpl<BusProjectFileMapper,
*
* @param file 文件
* @param req 请求
* @return 主键
* @return 是否上传文件成功
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Long uploadDxf2Json(MultipartFile file, BusProjectFileUploadDxfReq req) {
public Boolean uploadDxf2Json(MultipartFile file, BusProjectFileUploadDxfReq req) {
Long userId = LoginHelper.getUserId();
// 获取当前登录用户key值
String string = String.valueOf(userId + req.getProjectId());
@ -284,15 +284,7 @@ public class BusProjectFileServiceImpl extends ServiceImpl<BusProjectFileMapper,
throw new ServiceException("数据库更新异常");
}
} else {
BusProjectFile projectFile = new BusProjectFile();
projectFile.setProjectId(projectId);
projectFile.setFileName(fileName);
projectFile.setRemark(dxfFilePath);
boolean save = this.save(projectFile);
if (!save) {
throw new ServiceException("数据库插入异常");
}
projectFileId = projectFile.getId();
projectFileId = null;
}
SseMessageDto messageDto = new SseMessageDto();
messageDto.setMessage("DXF 文件上传成功,正在转换中......");
@ -310,7 +302,9 @@ public class BusProjectFileServiceImpl extends ServiceImpl<BusProjectFileMapper,
projectFile.setFilePath(jsonFilePath);
projectFile.setFileName(jsonFileName);
projectFile.setFileType(DesignMapFileConstant.JSONFileSuffix);
boolean update = this.updateById(projectFile);
projectFile.setProjectId(projectId);
projectFile.setRemark(dxfFilePath);
boolean update = this.saveOrUpdate(projectFile);
if (!update) throw new ServiceException("数据库修改异常");
messageDto.setMessage("DXF 文件转换成 GeoJSON 成功");
SseMessageUtils.publishMessage(messageDto);
@ -323,7 +317,7 @@ public class BusProjectFileServiceImpl extends ServiceImpl<BusProjectFileMapper,
USER_TASK_RUNNING.remove(md5);
}
});
return projectFileId;
return true;
}
/**

View File

@ -413,7 +413,7 @@ public class BusProjectServiceImpl extends ServiceImpl<BusProjectMapper, BusProj
// 关联设计id
List<BusProjectFile> projectFileList = projectFileMap.get(project.getId());
if (CollUtil.isNotEmpty(projectFileList)) {
projectVo.setDesignId(projectFileList.get(0).getId());
projectVo.setDesignId(projectFileList.getFirst().getId());
}
return projectVo;
}).toList();

View File

@ -0,0 +1,27 @@
package org.dromara.utils;
import java.math.BigDecimal;
import java.math.RoundingMode;
/**
* @author lcj
* @date 2025/5/27 9:16
*/
public class BigDecimalUtil {
/**
* 计算百分比
*
* @param dividend 被除数
* @param divisor 除数
* @return 百分比保留2位小数如 12.34%
*/
public static String toPercentage(BigDecimal dividend, BigDecimal divisor) {
if (dividend == null || divisor == null || divisor.compareTo(BigDecimal.ZERO) == 0) {
return "0";
}
BigDecimal percentage = dividend.divide(divisor, 2, RoundingMode.HALF_UP).multiply(new BigDecimal("100"));
return percentage.toPlainString();
}
}

View File

@ -1,5 +1,7 @@
package org.dromara.utils;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.exception.ServiceException;
@ -53,6 +55,11 @@ public class Dxf2JsonUtils {
exePath, inputDXFPath, outputJSONPath, sourceEPSG, targetEPSG);
while ((line = reader.readLine()) != null) {
log.info("dxf 转 json 程序执行中:{}", line);
JSONObject jsonObject = JSONUtil.parseObj(line);
Integer code = jsonObject.get("code", Integer.class);
if (code != 0 && code != 200) {
throw new ServiceException("dxf 转 json 程序执行出错!");
}
}
int exitCode = process.waitFor();
log.info("dxf 转 json 程序执行完毕,程序退出码:{}", exitCode);

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.dromara.progress.mapper.PgsProgressPlanDetailMapper">
</mapper>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.dromara.progress.mapper.PgsProgressPlanMapper">
</mapper>

View File

@ -1016,3 +1016,49 @@ CREATE TABLE `fac_percentage_facility`
INDEX `idx_matrix_id` (`matrix_id` ASC) USING BTREE comment '方阵id',
INDEX `idx_progress_category_id` (`progress_category_id` ASC) USING BTREE comment '进度类别id'
) comment ='设施-百分比设施' COLLATE = utf8mb4_unicode_ci;
DROP TABLE IF EXISTS `pgs_progress_plan`;
CREATE TABLE `pgs_progress_plan`
(
`id` bigint not null auto_increment comment '主键id',
`project_id` bigint not null comment '项目id',
`matrix_id` bigint not null comment '方阵id',
`matrix_name` varchar(64) null comment '方阵名称',
`progress_category_id` bigint null comment '进度类型id',
`progress_category_name` varchar(64) null comment '进度类别名称',
`start_date` date null comment '计划开始时间',
`end_date` date null comment '计划结束时间',
`plan_number` decimal(10) null comment '计划数量/百分比',
`finished_number` decimal(10) null comment '完成数量/百分比',
`create_by` varchar(64) null comment '创建者',
`update_by` varchar(64) null comment '更新者',
`create_time` datetime default CURRENT_TIMESTAMP null comment '创建时间',
`update_time` datetime default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',
`deleted_at` datetime null comment '删除时间',
`is_delete` tinyint(4) default 0 not null comment '是否删除0正常 1删除',
PRIMARY KEY (`id`) USING BTREE,
INDEX `idx_project_id` (`project_id` ASC) USING BTREE comment '项目id',
INDEX `idx_matrix_id` (`matrix_id` ASC) USING BTREE comment '方阵id',
INDEX `idx_progress_category_id` (`progress_category_id` ASC) USING BTREE comment '进度类别id'
) comment ='进度计划' COLLATE = utf8mb4_unicode_ci;
DROP TABLE IF EXISTS `pgs_progress_plan_detail`;
CREATE TABLE `pgs_progress_plan_detail`
(
`id` bigint not null auto_increment comment '主键id',
`project_id` bigint not null comment '项目id',
`progress_plan_id` bigint not null comment '进度计划id',
`date` date null comment '计划时间',
`plan_number` decimal(10) null comment '计划数量/百分比',
`finished_number` decimal(10) null comment '完成数量/百分比',
`ai_fill` decimal(10) null comment 'AI填入数量',
`create_by` varchar(64) null comment '创建者',
`update_by` varchar(64) null comment '更新者',
`create_time` datetime default CURRENT_TIMESTAMP null comment '创建时间',
`update_time` datetime default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间',
`deleted_at` datetime null comment '删除时间',
`is_delete` tinyint(4) default 0 not null comment '是否删除0正常 1删除',
PRIMARY KEY (`id`) USING BTREE,
INDEX `idx_project_id` (`project_id` ASC) USING BTREE comment '项目id',
INDEX `idx_progress_plan_id` (`progress_plan_id` ASC) USING BTREE comment '进度计划id'
) comment ='进度计划详情' COLLATE = utf8mb4_unicode_ci;