[update] 修改项目列表和进度计划相关逻辑

This commit is contained in:
lcj
2025-06-06 19:52:34 +08:00
parent e67d555685
commit 5bb201b272
26 changed files with 694 additions and 94 deletions

View File

@ -90,7 +90,7 @@
<id>prod</id>
<properties>
<profiles.active>prod</profiles.active>
<logging.level>warn</logging.level>
<logging.level>info</logging.level>
<monitor.username>ruoyi</monitor.username>
<monitor.password>123456</monitor.password>
</properties>

View File

@ -269,3 +269,6 @@ weather:
project-id: 2JTHPUQ5YY
private-key: MC4CAQAwBQYDK2VwBCIEIMAglX7IsxYiTeM+FXXnvCUsIggajeP4s8gAllewm6BN
api-host: n35rk53njv.re.qweatherapi.com
# dxf转 geojson 执行文件名
dxf2GeoJson:
file-name: main.exe

View File

@ -52,9 +52,9 @@ spring:
driverClassName: com.mysql.cj.jdbc.Driver
# jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562
# rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题)
url: jdbc:mysql://mysql:3306/xinnengyuan?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
username: root
password: 123456
url: jdbc:mysql://192.168.110.2:13386/xinnengyuan?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
username: xinnengyuan
password: caJWNthNFaNRpRNy
# # 从库数据源
# slave:
# lazy: true
@ -101,13 +101,13 @@ spring:
spring.data:
redis:
# 地址
host: redis
host: 192.168.110.2
# 端口默认为6379
port: 6379
# 数据库索引
database: 3
database: 1
# redis 密码必须配置
password: 123456
password: HMASKEbyhaASPZXB
# 连接超时时间
timeout: 10s
# 是否开启ssl
@ -265,3 +265,12 @@ justauth:
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=gitlab
# 和风天气 https://dev.qweather.com/
weather:
key-id: T65EAABUXC
project-id: 2JTHPUQ5YY
private-key: MC4CAQAwBQYDK2VwBCIEIMAglX7IsxYiTeM+FXXnvCUsIggajeP4s8gAllewm6BN
api-host: n35rk53njv.re.qweatherapi.com
# dxf转 geojson 执行文件名
dxf2GeoJson:
file-name: main

View File

@ -76,7 +76,7 @@ spring:
servlet:
multipart:
# 单个文件大小
max-file-size: 100MB
max-file-size: 200MB
# 设置总上传的文件大小
max-request-size: 200MB
mvc:

View File

@ -37,7 +37,10 @@ public class IncSyncDeleteProjectCache {
}
// 批量删除
if (!keysToDelete.isEmpty()) {
log.info("清理项目缓存,共 {} 条:{}", keysToDelete.size(), keysToDelete);
stringRedisTemplate.delete(keysToDelete);
} else {
log.info("没有需要清理的项目缓存");
}
}
}

View File

@ -18,6 +18,7 @@ import org.dromara.progress.domain.dto.progresscategory.PgsProgressCategoryQuery
import org.dromara.progress.domain.dto.progresscategory.PgsProgressCategoryUpdateReq;
import org.dromara.progress.domain.vo.progresscategory.PgsProgressCategoryCoordinateVo;
import org.dromara.progress.domain.vo.progresscategory.PgsProgressCategoryLastTimeVo;
import org.dromara.progress.domain.vo.progresscategory.PgsProgressCategoryProjectVo;
import org.dromara.progress.domain.vo.progresscategory.PgsProgressCategoryVo;
import org.dromara.progress.service.IPgsProgressCategoryService;
import org.springframework.validation.annotation.Validated;
@ -84,6 +85,18 @@ public class PgsProgressCategoryController extends BaseController {
return R.ok(pgsProgressCategoryService.getCoordinate(id));
}
/**
* 获取项目总的进度信息
*
* @param projectId 项目主键
*/
@SaCheckPermission("progress:progressCategory:query")
@GetMapping("/project/number/{projectId}")
public R<PgsProgressCategoryProjectVo> getProjectNumber(@NotNull(message = "项目主键不能为空")
@PathVariable Long projectId) {
return R.ok(pgsProgressCategoryService.getProjectNumber(projectId));
}
/**
* 获取进度类别最后一次进度信息
*

View File

@ -0,0 +1,60 @@
package org.dromara.progress.domain.vo.progresscategory;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.dromara.common.json.handler.BigDecimalToIntegerSerializer;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* @author lcj
* @date 2025/6/5 15:41
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PgsProgressCategoryMatrixVo implements Serializable {
@Serial
private static final long serialVersionUID = 3061735290740592145L;
/**
* 方阵id
*/
private Long matrixId;
/**
* 总数量/百分比
*/
@JsonSerialize(using = BigDecimalToIntegerSerializer.class)
private BigDecimal total;
/**
* 已完成数量/百分比
*/
@JsonSerialize(using = BigDecimalToIntegerSerializer.class)
private BigDecimal completed;
/**
* 计划总数量/百分比
*/
@JsonSerialize(using = BigDecimalToIntegerSerializer.class)
private BigDecimal planTotal;
/**
* 已完成数量百分比
*/
@JsonSerialize(using = BigDecimalToIntegerSerializer.class)
private BigDecimal completedPercentage;
/**
* 计划中数量百分比
*/
@JsonSerialize(using = BigDecimalToIntegerSerializer.class)
private BigDecimal planTotalPercentage;
}

View File

@ -0,0 +1,62 @@
package org.dromara.progress.domain.vo.progresscategory;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lombok.Data;
import org.dromara.common.json.handler.BigDecimalToIntegerSerializer;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
/**
* @author lcj
* @date 2025/6/5 15:36
*/
@Data
public class PgsProgressCategoryProjectVo implements Serializable {
@Serial
private static final long serialVersionUID = -8208751933207899365L;
/**
* 项目id
*/
private Long projectId;
/**
* 总数量/百分比
*/
@JsonSerialize(using = BigDecimalToIntegerSerializer.class)
private BigDecimal total;
/**
* 已完成数量/百分比
*/
@JsonSerialize(using = BigDecimalToIntegerSerializer.class)
private BigDecimal completed;
/**
* 计划总数量/百分比
*/
@JsonSerialize(using = BigDecimalToIntegerSerializer.class)
private BigDecimal planTotal;
/**
* 已完成数量百分比
*/
@JsonSerialize(using = BigDecimalToIntegerSerializer.class)
private BigDecimal completedPercentage;
/**
* 计划中数量百分比
*/
@JsonSerialize(using = BigDecimalToIntegerSerializer.class)
private BigDecimal planTotalPercentage;
/**
* 子项目列表
*/
private List<PgsProgressCategorySubProjectVo> children;
}

View File

@ -0,0 +1,66 @@
package org.dromara.progress.domain.vo.progresscategory;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.dromara.common.json.handler.BigDecimalToIntegerSerializer;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
/**
* @author lcj
* @date 2025/6/5 15:39
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PgsProgressCategorySubProjectVo implements Serializable {
@Serial
private static final long serialVersionUID = 7523695525881518366L;
/**
* 子项目id
*/
private Long subProjectId;
/**
* 总数量/百分比
*/
@JsonSerialize(using = BigDecimalToIntegerSerializer.class)
private BigDecimal total;
/**
* 已完成数量/百分比
*/
@JsonSerialize(using = BigDecimalToIntegerSerializer.class)
private BigDecimal completed;
/**
* 计划总数量/百分比
*/
@JsonSerialize(using = BigDecimalToIntegerSerializer.class)
private BigDecimal planTotal;
/**
* 已完成数量百分比
*/
@JsonSerialize(using = BigDecimalToIntegerSerializer.class)
private BigDecimal completedPercentage;
/**
* 计划中数量百分比
*/
@JsonSerialize(using = BigDecimalToIntegerSerializer.class)
private BigDecimal planTotalPercentage;
/**
* 方阵列表
*/
private List<PgsProgressCategoryMatrixVo> children;
}

View File

@ -1,11 +1,15 @@
package org.dromara.progress.domain.vo.progressplandetail;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.dromara.common.json.handler.BigDecimalToIntegerSerializer;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
/**
* @author lcj
@ -27,4 +31,15 @@ public class PgsProgressPlanDetailDateVo {
@JsonFormat(pattern = "yyyy-MM-dd")
private Date date;
/**
* 已完成数量
*/
@JsonSerialize(using = BigDecimalToIntegerSerializer.class)
private BigDecimal finishedNumber;
/**
* 完成详情
*/
private List<PgsProgressPlanDetailFinishedVo> finishedDetail;
}

View File

@ -8,6 +8,7 @@ import org.dromara.progress.domain.dto.progresscategory.PgsProgressCategoryQuery
import org.dromara.progress.domain.dto.progresscategory.PgsProgressCategoryUpdateReq;
import org.dromara.progress.domain.vo.progresscategory.PgsProgressCategoryCoordinateVo;
import org.dromara.progress.domain.vo.progresscategory.PgsProgressCategoryLastTimeVo;
import org.dromara.progress.domain.vo.progresscategory.PgsProgressCategoryProjectVo;
import org.dromara.progress.domain.vo.progresscategory.PgsProgressCategoryVo;
import java.util.Collection;
@ -111,4 +112,12 @@ public interface IPgsProgressCategoryService extends IService<PgsProgressCategor
*/
PgsProgressCategoryCoordinateVo getCoordinate(Long id);
/**
* 根据项目id获取项目进度类别数量信息
*
* @param projectId 项目id
* @return 项目进度类别数量信息
*/
PgsProgressCategoryProjectVo getProjectNumber(Long projectId);
}

View File

@ -11,14 +11,9 @@ import org.dromara.common.core.constant.HttpStatus;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.common.core.utils.ObjectUtils;
import org.dromara.facility.domain.FacBoxTransformer;
import org.dromara.facility.domain.FacInverter;
import org.dromara.facility.domain.FacPercentageFacility;
import org.dromara.facility.domain.FacPhotovoltaicPanel;
import org.dromara.facility.service.IFacBoxTransformerService;
import org.dromara.facility.service.IFacInverterService;
import org.dromara.facility.service.IFacPercentageFacilityService;
import org.dromara.facility.service.IFacPhotovoltaicPanelService;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.facility.domain.*;
import org.dromara.facility.service.*;
import org.dromara.progress.constant.PgsProgressCategoryConstant;
import org.dromara.progress.domain.PgsProgressCategory;
import org.dromara.progress.domain.PgsProgressCategoryTemplate;
@ -30,16 +25,16 @@ import org.dromara.progress.domain.dto.progresscategory.PgsProgressCategoryUpdat
import org.dromara.progress.domain.enums.PgsCoordinateTypeEnum;
import org.dromara.progress.domain.enums.PgsFinishStatusEnum;
import org.dromara.progress.domain.enums.PgsProgressUnitTypeEnum;
import org.dromara.progress.domain.vo.progresscategory.PgsProgressCategoryCoordinateVo;
import org.dromara.progress.domain.vo.progresscategory.PgsProgressCategoryFacilityVo;
import org.dromara.progress.domain.vo.progresscategory.PgsProgressCategoryLastTimeVo;
import org.dromara.progress.domain.vo.progresscategory.PgsProgressCategoryVo;
import org.dromara.progress.domain.vo.progresscategory.*;
import org.dromara.progress.domain.vo.progressplandetail.PgsProgressPlanDetailDateVo;
import org.dromara.progress.domain.vo.progressplandetail.PgsProgressPlanDetailFinishedVo;
import org.dromara.progress.mapper.PgsProgressCategoryMapper;
import org.dromara.progress.service.IPgsProgressCategoryService;
import org.dromara.progress.service.IPgsProgressCategoryTemplateService;
import org.dromara.progress.service.IPgsProgressPlanDetailService;
import org.dromara.progress.service.IPgsProgressPlanService;
import org.dromara.project.domain.BusProject;
import org.dromara.project.service.IBusProjectService;
import org.dromara.utils.BigDecimalUtil;
import org.dromara.utils.JsonDimensionUtil;
import org.springframework.beans.BeanUtils;
@ -88,6 +83,13 @@ public class PgsProgressCategoryServiceImpl extends ServiceImpl<PgsProgressCateg
@Resource
private IFacInverterService inverterService;
@Resource
private IBusProjectService projectService;
@Lazy
@Resource
private IFacMatrixService matrixService;
/**
* 查询进度类别
*
@ -465,18 +467,136 @@ public class PgsProgressCategoryServiceImpl extends ServiceImpl<PgsProgressCateg
return coordinateVo;
}
List<PgsProgressPlanDetailDateVo> detailList = progressPlanDetailService.lambdaQuery()
.select(PgsProgressPlanDetail::getId, PgsProgressPlanDetail::getDate)
.select(PgsProgressPlanDetail::getId,
PgsProgressPlanDetail::getDate,
PgsProgressPlanDetail::getFinishedNumber,
PgsProgressPlanDetail::getFinishedDetail)
.eq(PgsProgressPlanDetail::getProgressCategoryId, id)
.orderByAsc(PgsProgressPlanDetail::getDate)
.list()
.stream().map(detail ->
new PgsProgressPlanDetailDateVo(detail.getId(), detail.getDate()))
.toList();
.stream().map(detail -> {
PgsProgressPlanDetailDateVo detailDateVo = new PgsProgressPlanDetailDateVo();
detailDateVo.setId(detail.getId());
detailDateVo.setDate(detail.getDate());
detailDateVo.setFinishedNumber(new BigDecimal(detail.getFinishedNumber()));
String finishedDetail = detail.getFinishedDetail();
if (StringUtils.isNotBlank(finishedDetail)) {
List<PgsProgressPlanDetailFinishedVo> finishedVoList = JSONUtil.toList(finishedDetail, PgsProgressPlanDetailFinishedVo.class);
detailDateVo.setFinishedDetail(finishedVoList);
}
return detailDateVo;
}).toList();
coordinateVo.setDetailList(detailList);
coordinateVo.setFacilityList(facilityList);
return coordinateVo;
}
/**
* 根据项目id获取项目进度类别数量信息
*
* @param projectId 项目id
* @return 项目进度类别数量信息
*/
@Override
public PgsProgressCategoryProjectVo getProjectNumber(Long projectId) {
// 获取项目信息
BusProject project = projectService.getById(projectId);
if (project == null) {
throw new ServiceException("项目不存在", HttpStatus.NOT_FOUND);
}
// 获取子项目信息
List<BusProject> subProjectList = projectService.lambdaQuery()
.select(BusProject::getId)
.eq(BusProject::getPId, projectId)
.list();
if (CollUtil.isEmpty(subProjectList)) {
return null;
}
List<Long> subProjectIdList = subProjectList.stream().map(BusProject::getId).toList();
// 获取方阵信息
List<FacMatrix> matrixList = matrixService.lambdaQuery()
.select(FacMatrix::getId)
.in(FacMatrix::getProjectId, subProjectIdList)
.list();
if (CollUtil.isEmpty(matrixList)) {
return null;
}
List<Long> matrixIdList = matrixList.stream().map(FacMatrix::getId).toList();
// 分组projectId -> matrixList
Map<Long, List<FacMatrix>> matrixGroupByProject = matrixList.stream()
.collect(Collectors.groupingBy(FacMatrix::getProjectId));
// 获取每个方阵下的进度类别信息
List<PgsProgressCategory> progressCategoryList = this.lambdaQuery()
.select(PgsProgressCategory::getId, PgsProgressCategory::getStatus, PgsProgressCategory::getMatrixId)
.in(PgsProgressCategory::getMatrixId, matrixIdList)
.list();
// 分组matrixId -> categoryList
Map<Long, List<PgsProgressCategory>> categoryGroupByMatrix = progressCategoryList.
stream().collect(Collectors.groupingBy(PgsProgressCategory::getMatrixId));
// 封装结果
List<PgsProgressCategorySubProjectVo> subProjectVoList = new ArrayList<>();
BigDecimal totalAll = BigDecimal.ZERO;
BigDecimal completedAll = BigDecimal.ZERO;
BigDecimal planTotalAll = BigDecimal.ZERO;
for (BusProject subProject : subProjectList) {
Long subProjectId = subProject.getId();
List<FacMatrix> subMatrices = matrixGroupByProject.get(subProjectId);
if (CollUtil.isEmpty(subMatrices)) {
continue;
}
List<PgsProgressCategoryMatrixVo> matrixVoList = new ArrayList<>();
BigDecimal total = BigDecimal.ZERO;
BigDecimal completed = BigDecimal.ZERO;
BigDecimal planTotal = BigDecimal.ZERO;
for (FacMatrix matrix : subMatrices) {
Long matrixId = matrix.getId();
List<PgsProgressCategory> categories = categoryGroupByMatrix.get(matrixId);
if (CollUtil.isEmpty(categories)) {
continue;
}
BigDecimal matrixTotal = categories.stream().map(PgsProgressCategory::getTotal).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal matrixCompleted = categories.stream().map(PgsProgressCategory::getCompleted).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal matrixPlanTotal = categories.stream().map(PgsProgressCategory::getPlanTotal).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
total = total.add(matrixTotal);
completed = completed.add(matrixCompleted);
planTotal = planTotal.add(matrixPlanTotal);
// 构建 matrixVo
PgsProgressCategoryMatrixVo matrixVo = new PgsProgressCategoryMatrixVo();
matrixVo.setMatrixId(matrixId);
matrixVo.setTotal(matrixTotal);
matrixVo.setCompleted(matrixCompleted);
matrixVo.setPlanTotal(matrixPlanTotal);
matrixVo.setCompletedPercentage(BigDecimalUtil.toPercentage(matrixCompleted, matrixTotal));
matrixVo.setPlanTotalPercentage(BigDecimalUtil.toPercentage(matrixPlanTotal, matrixTotal));
matrixVoList.add(matrixVo);
}
// 构建子项目VO
PgsProgressCategorySubProjectVo subProjectVo = new PgsProgressCategorySubProjectVo();
subProjectVo.setSubProjectId(subProjectId);
subProjectVo.setTotal(total);
subProjectVo.setCompleted(completed);
subProjectVo.setPlanTotal(planTotal);
subProjectVo.setCompletedPercentage(BigDecimalUtil.toPercentage(completed, total));
subProjectVo.setPlanTotalPercentage(BigDecimalUtil.toPercentage(planTotal, total));
subProjectVo.setChildren(matrixVoList);
// 累加总项目数据
totalAll = totalAll.add(total);
completedAll = completedAll.add(completed);
planTotalAll = planTotalAll.add(planTotal);
subProjectVoList.add(subProjectVo);
}
// 构建项目VO
PgsProgressCategoryProjectVo projectVo = new PgsProgressCategoryProjectVo();
projectVo.setProjectId(projectId);
projectVo.setTotal(totalAll);
projectVo.setCompleted(completedAll);
projectVo.setPlanTotal(planTotalAll);
projectVo.setCompletedPercentage(BigDecimalUtil.toPercentage(completedAll, totalAll));
projectVo.setPlanTotalPercentage(BigDecimalUtil.toPercentage(planTotalAll, totalAll));
projectVo.setChildren(subProjectVoList);
return projectVo;
}
/**
* 根据子节点完成状态获取父节点完成状态
*

View File

@ -499,8 +499,12 @@ public class PgsProgressPlanDetailServiceImpl extends ServiceImpl<PgsProgressPla
int pageNum = ObjectUtil.defaultIfNull(pageQuery.getPageNum(), PageQuery.DEFAULT_PAGE_NUM);
int pageSize = ObjectUtil.defaultIfNull(pageQuery.getPageSize(), PageQuery.DEFAULT_PAGE_SIZE);
// 保底
if (pageNum < 1) pageNum = 1;
if (pageSize < 1) pageSize = PageQuery.DEFAULT_PAGE_SIZE;
if (pageNum < 1) {
pageNum = 1;
}
if (pageSize < 1) {
pageSize = PageQuery.DEFAULT_PAGE_SIZE;
}
int fromIndex = (pageNum - 1) * pageSize;
int toIndex = Math.min(fromIndex + pageSize, fullList.size());
// 防止越界

View File

@ -133,6 +133,15 @@ public class PgsProgressPlanServiceImpl extends ServiceImpl<PgsProgressPlanMappe
throw new ServiceException("对应方阵不存在", HttpStatus.NOT_FOUND);
}
Long progressCategoryId = progressPlan.getProgressCategoryId();
// 校验日期是否合法
PgsProgressPlan lastProgressPlan = this.lambdaQuery()
.eq(PgsProgressPlan::getProgressCategoryId, progressCategoryId)
.orderByDesc(PgsProgressPlan::getEndDate)
.last("limit 1")
.one();
if (lastProgressPlan != null && startDate.before(lastProgressPlan.getEndDate())) {
throw new ServiceException("开始日期不能早于上一条进度计划结束日期", HttpStatus.BAD_REQUEST);
}
PgsProgressCategory progressCategory = progressCategoryService.getById(progressCategoryId);
this.validPlanNumber(req.getPlanNumber(), progressCategory);
progressPlan.setProgressCategoryName(progressCategory.getName());
@ -146,7 +155,7 @@ public class PgsProgressPlanServiceImpl extends ServiceImpl<PgsProgressPlanMappe
Long id = progressPlan.getId();
List<PgsProgressPlanDetailCreateDto> detailList = req.getDetailList();
if (CollUtil.isNotEmpty(detailList)) {
List<PgsProgressPlanDetail> detailList1 = detailList.stream().map(detail -> {
List<PgsProgressPlanDetail> newDetailList = detailList.stream().map(detail -> {
PgsProgressPlanDetail progressPlanDetail = new PgsProgressPlanDetail();
BeanUtils.copyProperties(detail, progressPlanDetail);
progressPlanDetail.setProgressPlanId(id);
@ -154,7 +163,7 @@ public class PgsProgressPlanServiceImpl extends ServiceImpl<PgsProgressPlanMappe
progressPlanDetail.setProgressCategoryId(progressPlan.getProgressCategoryId());
return progressPlanDetail;
}).toList();
boolean result = progressPlanDetailService.saveBatch(detailList1);
boolean result = progressPlanDetailService.saveBatch(newDetailList);
if (!result) {
throw new ServiceException("新增进度计划详情失败,数据库操作失败", HttpStatus.ERROR);
}
@ -164,6 +173,7 @@ public class PgsProgressPlanServiceImpl extends ServiceImpl<PgsProgressPlanMappe
.eq(PgsProgressCategory::getId, progressCategoryId)
.set(PgsProgressCategory::getPlanTotal, progressPlan.getPlanNumber())
.set(PgsProgressCategory::getStatus, PgsFinishStatusEnum.INPROGRESS.getValue())
.set(PgsProgressCategory::getIsDelay, PgsDelayStatusEnum.UNDELAY.getValue())
.update();
if (!update) {
throw new ServiceException("更新进度分类计划总数量失败,数据库操作失败", HttpStatus.ERROR);

View File

@ -21,4 +21,9 @@ public interface BusProjectConstant {
*/
String PROJECT_CACHE_REDIS_KEY_PREFIX = "project";
/**
* 父级项目id
*/
Long PARENT_PROJECT_ID = 0L;
}

View File

@ -1,10 +1,10 @@
package org.dromara.project.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 lombok.RequiredArgsConstructor;
import org.dromara.common.core.constant.HttpStatus;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.exception.ServiceException;
@ -18,12 +18,10 @@ 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.project.domain.dto.project.BusProjectCreateReq;
import org.dromara.project.domain.dto.project.BusProjectCreateSubReq;
import org.dromara.project.domain.dto.project.BusProjectQueryReq;
import org.dromara.project.domain.dto.project.BusProjectUpdateReq;
import org.dromara.project.domain.vo.project.BusProjectContractorListVo;
import org.dromara.project.domain.vo.project.BusProjectSafetyDayVo;
import org.dromara.project.domain.vo.project.BusProjectVo;
import org.dromara.project.domain.vo.project.BusProjectWeatherVo;
import org.dromara.project.domain.vo.project.*;
import org.dromara.project.service.IBusProjectService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@ -37,12 +35,12 @@ import java.util.List;
* @date 2025-03-04
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/project/project")
public class BusProjectController extends BaseController {
private final IBusProjectService projectService;
@Resource
private IBusProjectService projectService;
/**
* 查询项目列表
@ -53,6 +51,16 @@ public class BusProjectController extends BaseController {
return projectService.queryPageList(req, pageQuery);
}
/**
* 查询项目下的子项目列表
*/
@SaCheckPermission("project:project:list")
@GetMapping("/list/sub/{id}")
public R<List<BusSubProjectVo>> listSubProject(@NotNull(message = "项目id不能为空")
@PathVariable Long id) {
return R.ok(projectService.querySubList(id));
}
/**
* 导出项目列表
*/
@ -99,6 +107,20 @@ public class BusProjectController extends BaseController {
return R.ok(projectService.insertByBo(req));
}
/**
* 新增子项目
*/
@SaCheckPermission("project:project:add")
@Log(title = "项目", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/sub")
public R<Long> addSub(@Validated(AddGroup.class) @RequestBody BusProjectCreateSubReq req) {
if (req == null) {
throw new ServiceException("参数不能为空", HttpStatus.BAD_REQUEST);
}
return R.ok(projectService.insertSubByProject(req));
}
/**
* 修改项目
*/

View File

@ -56,7 +56,6 @@ public class BusUserProjectRelevancyController extends BaseController {
/**
* 查询登录用户与项目关联列表
*/
@SaCheckPermission("project:projectRelevancy:list")
@GetMapping("/login/list")
public R<List<BusLoginUserProjectRelevancyVo>> listByLoginUser() {
Long userId = LoginHelper.getUserId();

View File

@ -25,11 +25,6 @@ public class BusProjectCreateReq implements Serializable {
*/
private String shortName;
/**
* 父项目id
*/
private Long pId;
/**
* 项目图片
*/

View File

@ -0,0 +1,28 @@
package org.dromara.project.domain.dto.project;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lcj
* @date 2025/6/6 11:57
*/
@Data
public class BusProjectCreateSubReq implements Serializable {
@Serial
private static final long serialVersionUID = 6380055877986391291L;
/**
* 项目名称
*/
private String projectName;
/**
* 父项目id
*/
private Long pId;
}

View File

@ -11,6 +11,7 @@ import org.dromara.project.domain.BusProject;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
@ -183,4 +184,9 @@ public class BusProjectVo implements Serializable {
@ExcelProperty(value = "创建时间")
private Date createTime;
/**
* 子项目
*/
private List<BusSubProjectVo> children;
}

View File

@ -0,0 +1,34 @@
package org.dromara.project.domain.vo.project;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* @author lcj
* @date 2025/6/4 9:53
*/
@Data
public class BusSubProjectVo implements Serializable {
@Serial
private static final long serialVersionUID = -5283786195929619472L;
/**
* id
*/
private Long id;
/**
* 项目名称
*/
private String projectName;
/**
* 创建时间
*/
private Date createTime;
}

View File

@ -7,12 +7,10 @@ import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.project.domain.BusProject;
import org.dromara.project.domain.dto.project.BusProjectCreateReq;
import org.dromara.project.domain.dto.project.BusProjectCreateSubReq;
import org.dromara.project.domain.dto.project.BusProjectQueryReq;
import org.dromara.project.domain.dto.project.BusProjectUpdateReq;
import org.dromara.project.domain.vo.project.BusProjectContractorListVo;
import org.dromara.project.domain.vo.project.BusProjectSafetyDayVo;
import org.dromara.project.domain.vo.project.BusProjectVo;
import org.dromara.project.domain.vo.project.BusProjectWeatherVo;
import org.dromara.project.domain.vo.project.*;
import java.util.Collection;
import java.util.List;
@ -50,6 +48,14 @@ public interface IBusProjectService extends IService<BusProject> {
*/
List<BusProjectVo> queryList(BusProjectQueryReq req);
/**
* 查询项目下的子项目列表
*
* @param id 父项目id
* @return 项目下的子项目列表
*/
List<BusSubProjectVo> querySubList(Long id);
/**
* 查询当前登录用户项目列表以及项目列表下的分包公司列表
*
@ -65,6 +71,14 @@ public interface IBusProjectService extends IService<BusProject> {
*/
Long insertByBo(BusProjectCreateReq dto);
/**
* 新增子项目
*
* @param dto 子项目
* @return 子项目 id
*/
Long insertSubByProject(BusProjectCreateSubReq dto);
/**
* 修改项目
*
@ -91,7 +105,7 @@ public interface IBusProjectService extends IService<BusProject> {
BusProjectVo getVo(BusProject project);
/**
* 获取项目查询条件封装
* 获取项目查询条件封装(不查询子项目)
*
* @param req 查询条件
* @return 查询条件封装

View File

@ -32,6 +32,7 @@ import org.dromara.project.service.IBusProjectFileService;
import org.dromara.project.service.IBusProjectService;
import org.dromara.utils.Dxf2JsonUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
@ -67,6 +68,9 @@ public class BusProjectFileServiceImpl extends ServiceImpl<BusProjectFileMapper,
private static final ConcurrentHashMap<String, Boolean> USER_TASK_RUNNING = new ConcurrentHashMap<>();
@Value("${dxf2GeoJson.file-name}")
private String dxf2GeoJsonFileName;
/**
* 查询项目文件存储
*
@ -258,7 +262,7 @@ public class BusProjectFileServiceImpl extends ServiceImpl<BusProjectFileMapper,
// 构造 JSON 输出路径
String outputJSONPath = filePath + File.separator + uuid + "." + DesignMapFileConstant.JSONFileSuffix;
// 获取 dxf2json.exe 路径
String exePath = projectRoot + File.separator + DesignMapFileConstant.DXF_BASE_PATH + File.separator + "main.exe";
String exePath = projectRoot + File.separator + DesignMapFileConstant.DXF_BASE_PATH + File.separator + dxf2GeoJsonFileName;
String sourceEPSG = DesignMapFileConstant.EPSG4524;
String targetEPSG = DesignMapFileConstant.EPSG4326;
BusProjectFile oldProjectFile = this.lambdaQuery()

View File

@ -34,12 +34,10 @@ import org.dromara.project.domain.BusProject;
import org.dromara.project.domain.BusProjectFile;
import org.dromara.project.domain.BusUserProjectRelevancy;
import org.dromara.project.domain.dto.project.BusProjectCreateReq;
import org.dromara.project.domain.dto.project.BusProjectCreateSubReq;
import org.dromara.project.domain.dto.project.BusProjectQueryReq;
import org.dromara.project.domain.dto.project.BusProjectUpdateReq;
import org.dromara.project.domain.vo.project.BusProjectContractorListVo;
import org.dromara.project.domain.vo.project.BusProjectSafetyDayVo;
import org.dromara.project.domain.vo.project.BusProjectVo;
import org.dromara.project.domain.vo.project.BusProjectWeatherVo;
import org.dromara.project.domain.vo.project.*;
import org.dromara.project.mapper.BusProjectMapper;
import org.dromara.project.service.IBusContractorService;
import org.dromara.project.service.IBusProjectFileService;
@ -115,8 +113,21 @@ public class BusProjectServiceImpl extends ServiceImpl<BusProjectMapper, BusProj
*/
@Override
public TableDataInfo<BusProjectVo> queryPageList(BusProjectQueryReq req, PageQuery pageQuery) {
// 获取当前登录用户项目列表
Long userId = LoginHelper.getUserId();
List<Long> projectIdList = userProjectRelevancyService.lambdaQuery()
.select(BusUserProjectRelevancy::getProjectId)
.eq(BusUserProjectRelevancy::getUserId, userId)
.list()
.stream().map(BusUserProjectRelevancy::getProjectId).toList();
LambdaQueryWrapper<BusProject> lqw = this.buildQueryWrapper(req);
if (CollUtil.isEmpty(projectIdList)) {
return TableDataInfo.build(new Page<>());
} else {
lqw.in(BusProject::getId, projectIdList);
}
// 查询数据库
Page<BusProject> result = this.page(pageQuery.build(), this.buildQueryWrapper(req));
Page<BusProject> result = this.page(pageQuery.build(), lqw);
return TableDataInfo.build(this.getVoPage(result));
}
@ -132,6 +143,27 @@ public class BusProjectServiceImpl extends ServiceImpl<BusProjectMapper, BusProj
return this.list(lqw).stream().map(this::getVo).toList();
}
/**
* 查询项目下的子项目列表
*
* @param id 父项目id
* @return 项目下的子项目列表
*/
@Override
public List<BusSubProjectVo> querySubList(Long id) {
BusProject project = this.getById(id);
if (project == null) {
throw new ServiceException("查询项目不存在", HttpStatus.NOT_FOUND);
}
List<BusProject> subProjectList = this.list(new LambdaQueryWrapper<BusProject>()
.eq(BusProject::getPId, id));
return subProjectList.stream().map(subProject -> {
BusSubProjectVo subProjectVo = new BusSubProjectVo();
BeanUtils.copyProperties(subProject, subProjectVo);
return subProjectVo;
}).toList();
}
/**
* 查询当前登录用户项目列表以及项目列表下的分包公司列表
*
@ -214,6 +246,49 @@ public class BusProjectServiceImpl extends ServiceImpl<BusProjectMapper, BusProj
return projectId;
}
/**
* 新增子项目
*
* @param dto 子项目
* @return 子项目 id
*/
@Override
public Long insertSubByProject(BusProjectCreateSubReq dto) {
String projectName = dto.getProjectName();
Long pId = dto.getPId();
if (StringUtils.isBlank(projectName)) {
throw new ServiceException("子项目名称不能为空", HttpStatus.BAD_REQUEST);
}
BusProject project = this.getById(pId);
if (project == null) {
throw new ServiceException("父项目不存在", HttpStatus.NOT_FOUND);
}
// 权限校验
Long userId = LoginHelper.getUserId();
validAuth(project.getId(), userId);
BusProject subProject = new BusProject();
subProject.setPId(pId);
subProject.setProjectName(projectName);
boolean save = this.save(subProject);
if (!save) {
throw new ServiceException("新增子项目失败,数据库异常", HttpStatus.ERROR);
}
Long subProjectId = subProject.getId();
// 同步保存用户与项目关联
Set<Long> userIdList = new HashSet<>(List.of(userId, SystemConstants.SUPER_ADMIN_ID));
List<BusUserProjectRelevancy> userProjectRelevancyList = userIdList.stream().map(id -> {
BusUserProjectRelevancy userProjectRelevancy = new BusUserProjectRelevancy();
userProjectRelevancy.setUserId(id);
userProjectRelevancy.setProjectId(subProjectId);
return userProjectRelevancy;
}).toList();
boolean saveRelevancy = userProjectRelevancyService.saveBatch(userProjectRelevancyList);
if (!saveRelevancy) {
throw new ServiceException("新增用户与项目关联失败,数据库异常", HttpStatus.ERROR);
}
return subProjectId;
}
/**
* 修改项目
*
@ -287,6 +362,13 @@ public class BusProjectServiceImpl extends ServiceImpl<BusProjectMapper, BusProj
if (isValid) {
// 做一些业务上的校验,判断是否需要校验
this.validAuth(ids, userId);
// 查看是否有子项目
Long count = this.lambdaQuery()
.in(BusProject::getPId, ids)
.count();
if (count > 0) {
throw new ServiceException("删除项目中存在子项目,请先删除子项目", HttpStatus.BAD_REQUEST);
}
}
// 删除项目
boolean removeProjectList = this.removeBatchByIds(ids);
@ -330,11 +412,22 @@ public class BusProjectServiceImpl extends ServiceImpl<BusProjectMapper, BusProj
if (projectFile != null) {
projectVo.setDesignId(projectFile.getId());
}
// 关联子项目列表
List<BusProject> subProjectList = this.lambdaQuery()
.select(BusProject::getId, BusProject::getProjectName, BusProject::getCreateTime)
.eq(BusProject::getPId, project.getId())
.list();
List<BusSubProjectVo> subProjectVoList = subProjectList.stream().map(subProject -> {
BusSubProjectVo subProjectVo = new BusSubProjectVo();
BeanUtils.copyProperties(subProject, subProjectVo);
return subProjectVo;
}).toList();
projectVo.setChildren(subProjectVoList);
return projectVo;
}
/**
* 获取项目查询条件封装
* 获取项目查询条件封装(不查询子项目)
*
* @param req 查询条件
* @return 查询条件封装
@ -382,7 +475,11 @@ public class BusProjectServiceImpl extends ServiceImpl<BusProjectMapper, BusProj
lqw.eq(ObjectUtils.isNotEmpty(projectCategory), BusProject::getProjectCategory, projectCategory);
lqw.eq(ObjectUtils.isNotEmpty(designTotal), BusProject::getDesignTotal, designTotal);
lqw.eq(ObjectUtils.isNotEmpty(showHidden), BusProject::getShowHidden, showHidden);
// 排序
lqw.orderByAsc(BusProject::getSort);
// 不查询子项目
final Long PID = 0L;
lqw.eq(BusProject::getPId, PID);
return lqw;
}
@ -399,6 +496,12 @@ public class BusProjectServiceImpl extends ServiceImpl<BusProjectMapper, BusProj
Map<Long, List<BusProjectFile>> projectFileMap = projectFileService.lambdaQuery()
.in(BusProjectFile::getProjectId, projectIdList).list()
.stream().collect(Collectors.groupingBy(BusProjectFile::getProjectId));
// 获取子项目列表
List<BusProject> subProjectList = this.lambdaQuery()
.select(BusProject::getId, BusProject::getPId, BusProject::getProjectName, BusProject::getCreateTime)
.in(BusProject::getPId, projectIdList)
.list();
Map<Long, List<BusProject>> subProjectMap = subProjectList.stream().collect(Collectors.groupingBy(BusProject::getPId));
// 对象列表 => 封装对象列表
List<BusProjectVo> projectVoList = projectList.stream().map(project -> {
// 对象转封装类
@ -415,6 +518,16 @@ public class BusProjectServiceImpl extends ServiceImpl<BusProjectMapper, BusProj
if (CollUtil.isNotEmpty(projectFileList)) {
projectVo.setDesignId(projectFileList.getFirst().getId());
}
// 关联子项目
List<BusSubProjectVo> subProjectVoList = new ArrayList<>();
if (subProjectMap.containsKey(project.getId())){
subProjectVoList = subProjectMap.get(project.getId()).stream().map(subProject -> {
BusSubProjectVo subProjectVo = new BusSubProjectVo();
BeanUtils.copyProperties(subProject, subProjectVo);
return subProjectVo;
}).toList();
}
projectVo.setChildren(subProjectVoList);
return projectVo;
}).toList();
projectVoPage.setRecords(projectVoList);

View File

@ -13,6 +13,7 @@ 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.project.constant.BusProjectConstant;
import org.dromara.project.domain.BusProject;
import org.dromara.project.domain.BusUserProjectRelevancy;
import org.dromara.project.domain.dto.project.BusProjectBatchByProjectListReq;
@ -29,10 +30,8 @@ import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.*;
import java.util.stream.Collectors;
/**
* 系统用户与项目关联Service业务层处理
@ -209,14 +208,22 @@ public class BusUserProjectRelevancyServiceImpl extends ServiceImpl<BusUserProje
queryWrapper.eq(BusUserProjectRelevancy::getUserId, userId);
// 查询数据库,获取数据
List<BusUserProjectRelevancy> list = this.list(queryWrapper);
List<Long> projectIdList = list.stream().map(BusUserProjectRelevancy::getProjectId).toList();
Map<Long, List<BusProject>> projectMap = projectService.lambdaQuery()
.select(BusProject::getId, BusProject::getPId, BusProject::getProjectName, BusProject::getShortName)
.in(BusProject::getId, projectIdList)
.eq(BusProject::getPId, BusProjectConstant.PARENT_PROJECT_ID)
.list()
.stream().collect(Collectors.groupingBy(BusProject::getId));
// 获取封装
return list.stream()
.map(userProjectRelevancy -> {
Long projectId = userProjectRelevancy.getProjectId();
QueryWrapper<BusProject> projectQueryWrapper = new QueryWrapper<>();
projectQueryWrapper.eq("id", projectId);
BusProject project = projectService.getOne(projectQueryWrapper);
if (project != null) {
BusProject project = null;
if (projectMap.containsKey(projectId)) {
project = projectMap.get(projectId).getFirst();
}
if (project != null && project.getPId().equals(BusProjectConstant.PARENT_PROJECT_ID)) {
BusLoginUserProjectRelevancyVo loginUserProjectRelevancy = new BusLoginUserProjectRelevancyVo();
loginUserProjectRelevancy.setId(userProjectRelevancy.getId());
loginUserProjectRelevancy.setUserId(userProjectRelevancy.getUserId());

View File

@ -1,7 +1,7 @@
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
error_log /mnt/disk1/docker/nginx/log/error.log warn;
pid /mnt/disk1/docker/nginx/nginx.pid;
events {
worker_connections 1024;
@ -19,12 +19,11 @@ http {
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
access_log /mnt/disk1/docker/nginx/log/access.log main;
upstream server {
ip_hash;
server 127.0.0.1:8080;
server 127.0.0.1:8081;
server 127.0.0.1:8899;
}
upstream monitor-admin {
@ -68,12 +67,12 @@ http {
}
location / {
root /usr/share/nginx/html; # docker映射路径 不允许更改
root /mnt/disk1/docker/nginx/html; # docker映射路径 不允许更改
try_files $uri $uri/ /index.html;
index index.html index.htm;
}
location /prod-api/ {
location /api/ {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;