Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
2025-11-13 20:03:10 +08:00
19 changed files with 965 additions and 285 deletions

View File

@ -223,6 +223,9 @@ public class ExcelUtil {
.head(clazz)
.autoCloseStream(false)
.registerConverter(new ExcelBigNumberConvert())
// 自动适配
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
.registerWriteHandler(new DataWriteHandler(clazz))
.build();

View File

@ -544,11 +544,10 @@ public class ProjectBigScreenServiceImpl implements ProjectBigScreenService {
List<PgsProgressCategory> allChildren = progressCategoryService.list(
Wrappers.<PgsProgressCategory>lambdaQuery()
.in(progressName.equals("光伏场区"), PgsProgressCategory::getName, gfcqName)
.and(wrapper -> {
.and(wrapper ->
wrapper.like(PgsProgressCategory::getAncestors, "," + topId + ",")
.or()
.like(PgsProgressCategory::getAncestors, "," + topId);
})
.like(PgsProgressCategory::getAncestors, "," + topId))
);
if (allChildren.isEmpty()) {
return Collections.emptyList();
@ -836,38 +835,38 @@ public class ProjectBigScreenServiceImpl implements ProjectBigScreenService {
if (voList != null && !voList.isEmpty()) {
for (GpsEquipmentSonVo item : voList) {
JSONObject messageObj = new JSONObject();
messageObj.put("type", "location"); // 消息类型
messageObj.set("type", "location"); // 消息类型
JSONObject data = new JSONObject();
data.put("id", item.getModelId());
data.set("id", item.getModelId());
// 位置信息
JSONObject position = new JSONObject();
position.put("lat", item.getLocLatitude()); // 纬度
position.put("lng", item.getLocLongitude()); // 经度
position.put("alt", item.getLocAltitude()); // 海拔
position.set("lat", item.getLocLatitude()); // 纬度
position.set("lng", item.getLocLongitude()); // 经度
position.set("alt", item.getLocAltitude()); // 海拔
data.put("position", position);
messageObj.put("data", data); // 设备唯一标识
data.set("position", position);
messageObj.set("data", data); // 设备唯一标识
maps.add(messageObj.toString());
}
}
if (appList != null && !appList.isEmpty()) {
for (GpsEquipmentSonVo item : appList) {
JSONObject messageObj = new JSONObject();
messageObj.put("type", "location"); // 消息类型
messageObj.set("type", "location"); // 消息类型
JSONObject data = new JSONObject();
data.put("id", item.getModelId());
data.set("id", item.getModelId());
// 位置信息
JSONObject position = new JSONObject();
position.put("lat", item.getLocLatitude()); // 纬度
position.put("lng", item.getLocLongitude()); // 经度
position.put("alt", item.getLocAltitude()); // 海拔
position.set("lat", item.getLocLatitude()); // 纬度
position.set("lng", item.getLocLongitude()); // 经度
position.set("alt", item.getLocAltitude()); // 海拔
data.put("position", position);
messageObj.put("data", data); // 设备唯一标识
data.set("position", position);
messageObj.set("data", data); // 设备唯一标识
maps.add(messageObj.toString());
}
}
@ -883,19 +882,19 @@ public class ProjectBigScreenServiceImpl implements ProjectBigScreenService {
if (object != null) {
JSONObject object1 = JSONUtil.parseObj(object);
JSONObject messageObj = new JSONObject();
messageObj.put("type", "location"); // 消息类型
messageObj.set("type", "location"); // 消息类型
JSONObject data = new JSONObject();
data.put("id", key.getAirplaneModleId());
data.set("id", key.getAirplaneModleId());
// 位置信息
JSONObject position = new JSONObject();
position.put("lat", object1.getJSONObject("data").get("latitude")); // 纬度
position.put("lng", object1.getJSONObject("data").get("longitude")); // 经度
position.put("alt", object1.getJSONObject("data").get("height")); // 海拔
position.set("lat", object1.getJSONObject("data").get("latitude")); // 纬度
position.set("lng", object1.getJSONObject("data").get("longitude")); // 经度
position.set("alt", object1.getJSONObject("data").get("height")); // 海拔
data.put("position", position);
messageObj.put("data", data); // 设备唯一标识
data.set("position", position);
messageObj.set("data", data); // 设备唯一标识
maps.add(messageObj.toString());
} else {
Object object2 = stringRedisTemplate.opsForValue().get("wrj:osd3:" + key);
@ -903,19 +902,19 @@ public class ProjectBigScreenServiceImpl implements ProjectBigScreenService {
JSONObject object3 = JSONUtil.parseObj(object2);
JSONObject messageObj = new JSONObject();
messageObj.put("type", "location"); // 消息类型
messageObj.set("type", "location"); // 消息类型
JSONObject data = new JSONObject();
data.put("id", key.getDroneModleId());
data.set("id", key.getDroneModleId());
// 位置信息
JSONObject position = new JSONObject();
position.put("lat", object3.getJSONObject("data").get("latitude")); // 纬度
position.put("lng", object3.getJSONObject("data").get("longitude")); // 经度
position.put("alt", object3.getJSONObject("data").get("height")); // 海拔
position.set("lat", object3.getJSONObject("data").get("latitude")); // 纬度
position.set("lng", object3.getJSONObject("data").get("longitude")); // 经度
position.set("alt", object3.getJSONObject("data").get("height")); // 海拔
data.put("position", position);
messageObj.put("data", data); // 设备唯一标识
data.set("position", position);
messageObj.set("data", data); // 设备唯一标识
maps.add(messageObj.toString());
}
}

View File

@ -126,9 +126,11 @@ public class RecognizerUtils {
List<Integer> point = targetVo.getLeftTopPoint();
List<Integer> size = targetVo.getSize();
JSONObject pos = new JSONObject();
int x = point.get(0) + size.get(0) / 2;
int y = point.get(1) + size.get(1) / 2;
// 中心点
pos.set("x", (point.get(0) + size.get(0)) / 2);
pos.set("y", (point.get(1) + size.get(1)) / 2);
pos.set("x", x);
pos.set("y", y);
positions.add(pos);
}
reqJson.set("positions", positions);

View File

@ -1,47 +1,24 @@
package org.dromara.progress.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.constant.HttpStatus;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.excel.core.DefaultExcelListener;
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.web.core.BaseController;
import org.dromara.progress.domain.PgsProgressCategory;
import org.dromara.progress.domain.dto.progresscategory.*;
import org.dromara.progress.domain.enums.PgsRelevancyStructureEnum;
import org.dromara.progress.domain.vo.progresscategory.*;
import org.dromara.progress.service.IPgsProgressCategoryService;
import org.dromara.project.domain.BusProject;
import org.dromara.project.service.IBusProjectService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
/**
* 进度类别
@ -58,9 +35,6 @@ public class PgsProgressCategoryController extends BaseController {
@Resource
private IPgsProgressCategoryService pgsProgressCategoryService;
@Resource
private IBusProjectService projectService;
/**
* 查询进度类别列表
*/
@ -116,101 +90,31 @@ public class PgsProgressCategoryController extends BaseController {
*/
@SaCheckPermission("progress:progressCategory:export")
@Log(title = "进度类别", businessType = BusinessType.EXPORT)
@Transactional
@PostMapping("/export")
public void export(@RequestBody PgsProgressCategoryQueryReq req, HttpServletResponse response) {
LambdaQueryWrapper<PgsProgressCategory> lqw = new LambdaQueryWrapper<>();
//要导出的整个sheet所需要的names
List<String> names = new ArrayList<>();
//要导出的list
List<List<PgsProgressCategoryVo>> listValues = new ArrayList<>();
Long parentId = req.getParentId();
String relevancyStructure = req.getRelevancyStructure();
if (relevancyStructure.equals("2")) {
// 父类id不为空导出父类对应的子类
PgsProgressCategory category = pgsProgressCategoryService.getById(parentId);
if (category == null) {
throw new ServiceException("父进度类别不存在", HttpStatus.NOT_FOUND);
}
names.add(category.getName());
QueryWrapper<PgsProgressCategory> queryWrapper = new QueryWrapper<>();
queryWrapper.apply("FIND_IN_SET({0}, ancestors)", parentId);
List<PgsProgressCategoryVo> voList = pgsProgressCategoryService.getVoList(pgsProgressCategoryService.list(queryWrapper));
listValues.add(voList);
} else {
BusProject project = projectService.getById(req.getProjectId());
if (project == null) {
throw new ServiceException("项目不存在", HttpStatus.NOT_FOUND);
}
List<BusProject> projects;
if (project.getPId().equals(0L)) {
projects = projectService.lambdaQuery()
.eq(BusProject::getPId, req.getProjectId())
.list();
projects.add(project);
List<Long> ids = projects.stream().map(BusProject::getId).toList();
lqw.in(CollUtil.isNotEmpty(ids), PgsProgressCategory::getProjectId, ids);
} else {
projects = List.of(project);
lqw.eq(req.getProjectId() != null, PgsProgressCategory::getProjectId, req.getProjectId());
}
lqw.eq(req.getMatrixId() != null, PgsProgressCategory::getMatrixId, req.getMatrixId());
// 查询数据
lqw.eq(PgsProgressCategory::getParentId, 0L);
List<PgsProgressCategory> list = pgsProgressCategoryService.list(lqw);
pgsProgressCategoryService.export(req, response);
}
Map<Long, String> projectNameMap = projects.stream()
.collect(Collectors.toMap(BusProject::getId, BusProject::getProjectName));
// 获取非方阵类别name 非方阵类别有多级 暂定只有2级 也有可能没有父子关系
List<PgsProgressCategory> unMatrixList = list.stream().filter(category ->
!category.getRelevancyStructure().equals(PgsRelevancyStructureEnum.MATRIX.getValue())).toList();
if (!unMatrixList.isEmpty()) {
for (PgsProgressCategory unMatrix : unMatrixList) {
//所有非方阵顶类名
names.add(unMatrix.getName() + "-" + projectNameMap.get(unMatrix.getProjectId()));
//寻找子类
lqw = new LambdaQueryWrapper<>();
lqw.eq(PgsProgressCategory::getParentId, unMatrix.getId());
List<PgsProgressCategoryVo> children = pgsProgressCategoryService.getVoList(pgsProgressCategoryService.list(lqw));
if (!children.isEmpty()) {
//寻找孙类 然后添加
List<PgsProgressCategoryVo> grandson = new ArrayList<>();
for (PgsProgressCategoryVo childrenCategory : children) {
lqw = new LambdaQueryWrapper<>();
lqw.eq(PgsProgressCategory::getParentId, childrenCategory.getId());
List<PgsProgressCategoryVo> grandsonCategory = pgsProgressCategoryService.getVoList(pgsProgressCategoryService.list(lqw));
if (!grandsonCategory.isEmpty()) {
grandson.addAll(grandsonCategory);
} else {
grandson = children;
}
}
listValues.add(grandson);
}
}
}
//获取矩阵类别name
List<PgsProgressCategory> matrixList = list.stream().filter(category ->
category.getRelevancyStructure().equals(PgsRelevancyStructureEnum.MATRIX.getValue())).toList();
if (!matrixList.isEmpty()) {
for (PgsProgressCategory pgsProgressCategory : matrixList) {
//增加矩阵名
names.add(pgsProgressCategory.getName() + "-" + pgsProgressCategory.getMatrixName());
//找到该矩阵下的列表
lqw = new LambdaQueryWrapper<>();
lqw.eq(PgsProgressCategory::getMatrixId, pgsProgressCategory.getMatrixId());
listValues.add(pgsProgressCategoryService.getVoList(pgsProgressCategoryService.list(lqw)));
}
}
}
try {
ExcelUtil.exportMultiSheetExcelEnhanced(listValues, names, PgsProgressCategoryVo.class, null, response);
} catch (IOException e) {
throw new ServiceException("导出失败");
}
/**
* 根据名称导出进度类别统计
*/
@SaCheckPermission("progress:progressCategory:export")
@Log(title = "进度类别", businessType = BusinessType.EXPORT)
@PostMapping("/export/total/{projectId}")
public void exportTotalByName(@NotNull(message = "项目主键不能为空")
@PathVariable Long projectId, HttpServletResponse response) {
pgsProgressCategoryService.exportTotalByName(projectId, response);
}
/**
* 根据父级导出进度类别统计
*/
@SaCheckPermission("progress:progressCategory:export")
@Log(title = "进度类别", businessType = BusinessType.EXPORT)
@PostMapping("/export/total/parent/{parentId}")
public void exportTotalByNameParent(@NotNull(message = "父级主键不能为空")
@PathVariable Long parentId, HttpServletResponse response) {
pgsProgressCategoryService.exportTotalByNameParent(parentId, response);
}
/***
@ -220,111 +124,7 @@ public class PgsProgressCategoryController extends BaseController {
@Log(title = "进度类别导入", businessType = BusinessType.IMPORT)
@PostMapping("/import")
public R<Void> importData(@RequestParam("file") MultipartFile file) {
// 检查文件是否为空
if (file == null || file.isEmpty()) {
return R.fail("上传文件不能为空");
}
// 检查文件大小
if (file.getSize() == 0) {
return R.fail("上传文件不能为空文件");
}
// 检查文件名
if (file.getOriginalFilename() == null || file.getOriginalFilename().isEmpty()) {
return R.fail("文件名不能为空");
}
try {
// 使用EasyExcel读取所有sheet
List<PgsProgressCategoryVo> allData = new ArrayList<>();
// 创建Excel读取监听器
DefaultExcelListener<PgsProgressCategoryVo> listener = new DefaultExcelListener<>(false);
// 读取Excel文件
ExcelReader excelReader = EasyExcel.read(file.getInputStream(), PgsProgressCategoryVo.class, listener).build();
// 获取所有sheet
List<ReadSheet> sheetList = excelReader.excelExecutor().sheetList();
// 遍历所有sheet
for (ReadSheet readSheet : sheetList) {
// 为每个sheet创建新的监听器实例
DefaultExcelListener<PgsProgressCategoryVo> sheetListener = new DefaultExcelListener<>(false);
// 读取当前sheet数据
EasyExcel.read(file.getInputStream(), PgsProgressCategoryVo.class, sheetListener)
.sheet(readSheet.getSheetNo())
.doRead();
List<PgsProgressCategoryVo> list = sheetListener.getExcelResult().getList();
List<PgsProgressCategoryVo> newList = list.stream().filter(vo -> vo.getId() == null).toList();
List<PgsProgressCategoryVo> oldList = list.stream().filter(vo -> vo.getId() != null).toList();
Set<Long> ids = oldList.stream().map(PgsProgressCategoryVo::getId).collect(Collectors.toSet());
List<PgsProgressCategory> categoryList = pgsProgressCategoryService.listByIds(ids);
// 筛选出关联设计图的数据
List<PgsProgressCategoryVo> oldListVo = oldList.stream().filter(vo -> {
PgsProgressCategory category = categoryList.stream().filter(c -> c.getId().equals(vo.getId())).findFirst().orElse(null);
if (category == null) {
return true;
}
String workType = category.getWorkType();
return StringUtils.isBlank(workType);
}).toList();
// 将当前sheet的数据添加到总数据中
allData.addAll(oldListVo);
if (CollUtil.isNotEmpty(newList) && CollUtil.isNotEmpty(oldList)) {
PgsProgressCategoryVo first = oldList.getFirst();
PgsProgressCategory category = pgsProgressCategoryService.getById(first.getId());
newList.forEach(vo -> {
vo.setParentId(category.getParentId());
vo.setProjectId(category.getProjectId());
vo.setMatrixId(category.getMatrixId());
vo.setAncestors(category.getAncestors());
vo.setRelevancyStructure(category.getRelevancyStructure());
});
allData.addAll(newList);
}
}
// 关闭读取器
excelReader.finish();
if (allData.isEmpty()) {
return R.fail("未读取到有效数据");
}
// 处理导入的数据
List<PgsProgressCategory> list = new ArrayList<>();
for (PgsProgressCategoryVo vo : allData) {
list.add(pgsProgressCategoryService.convertVoToEntity(vo));
}
// 计算产值
list.forEach(pgsProgressCategory -> {
BigDecimal ownerPrice = pgsProgressCategory.getOwnerPrice();
BigDecimal constructionPrice = pgsProgressCategory.getConstructionPrice();
BigDecimal total = pgsProgressCategory.getTotal();
if (total != null && total.compareTo(BigDecimal.ZERO) != 0) {
if (ownerPrice != null && ownerPrice.compareTo(BigDecimal.ZERO) != 0) {
pgsProgressCategory.setOwnerOutputValue(ownerPrice.multiply(total).setScale(4, RoundingMode.HALF_UP));
}
if (constructionPrice != null && constructionPrice.compareTo(BigDecimal.ZERO) != 0) {
pgsProgressCategory.setConstructionOutputValue(constructionPrice.multiply(total).setScale(4, RoundingMode.HALF_UP));
}
}
// 关联数据不更新数量
if (pgsProgressCategory.getRemark() != null && pgsProgressCategory.getRemark().equals("关联数据")) {
pgsProgressCategory.setTotal(null);
}
});
boolean b = pgsProgressCategoryService.saveOrUpdateBatch(list);
if (!b) {
return R.fail("更新失败");
}
return R.ok("导入成功,共更新 " + list.size() + " 条数据");
} catch (Exception e) {
log.error("导入Excel文件失败", e);
return R.fail("导入失败: " + e.getMessage());
}
return R.ok(pgsProgressCategoryService.importData(file));
}
/**

View File

@ -23,12 +23,22 @@ public class PgsProgressPlanDetailAINumberReq implements Serializable {
@NotBlank(message = "大图不能为空")
private String file;
/**
* 大图url
*/
private String fileUrl;
/**
* tif文件
*/
@NotBlank(message = "tif文件不能为空")
private String tif;
/**
* tif文件url
*/
private String tifUrl;
/**
* 项目id
*/

View File

@ -0,0 +1,38 @@
package org.dromara.progress.domain.enums;
import lombok.Getter;
/**
* @author lilemy
* @date 2025-11-12 15:47
*/
@Getter
public enum PgsProgressCategoryTypeEnum {
BOOSTER_STATION("升压站"),
COLLECTING_LINE("集电线路"),
SEND_LINE("送出线路"),
PHOTOVOLTAIC_AREA("光伏场区"),
OTHER_PROJECT("其他工程");
private final String text;
PgsProgressCategoryTypeEnum(String text) {
this.text = text;
}
/**
* 根据text获取枚举
*
* @param text 文本
* @return 枚举
*/
public static PgsProgressCategoryTypeEnum fromText(String text) {
for (PgsProgressCategoryTypeEnum e : values()) {
if (e.getText().equals(text)) {
return e;
}
}
return null;
}
}

View File

@ -0,0 +1,57 @@
package org.dromara.progress.domain.vo.progresscategory;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* @author lilemy
* @date 2025-11-12 15:39
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PgsProgressCategoryByDayVo {
/**
* 子项目id
*/
private Long projectId;
/**
* 子项目名称
*/
private String projectName;
/**
* 升压站
*/
private List<PgsProgressCategoryDetailByDayVo> boosterStation;
/**
* 集电线路
*/
private List<PgsProgressCategoryDetailByDayVo> collectingLine;
/**
* 送出线路
*/
private List<PgsProgressCategoryDetailByDayVo> sendLine;
/**
* 光伏场区
*/
private List<PgsProgressCategoryDetailByDayVo> photovoltaicArea;
/**
* 其他工程
*/
private List<PgsProgressCategoryDetailByDayVo> otherProject;
/**
* 总数
*/
private Integer size;
}

View File

@ -0,0 +1,27 @@
package org.dromara.progress.domain.vo.progresscategory;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* @author lilemy
* @date 2025-11-13 19:22
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PgsProgressCategoryDayTotalVo {
/**
* 项目
*/
private PgsProgressCategoryByDayVo project;
/**
* 子项目
*/
private List<PgsProgressCategoryByDayVo> subProjectList;
}

View File

@ -0,0 +1,57 @@
package org.dromara.progress.domain.vo.progresscategory;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
/**
* @author lilemy
* @date 2025-11-12 18:59
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PgsProgressCategoryDetailByDayVo {
/**
* 主键
*/
private Long id;
/**
* 进度类别名称
*/
private String name;
/**
* 总数量
*/
private BigDecimal total;
/**
* 已完成数量
*/
private BigDecimal completed;
/**
* 已完成数量百分比
*/
private BigDecimal completedPercentage;
/**
* 计量单位
*/
private String unit;
/**
* 施工计划
*/
private BigDecimal constructionPlan;
/**
* 施工完成
*/
private BigDecimal constructionCompleted;
}

View File

@ -0,0 +1,66 @@
package org.dromara.progress.domain.vo.progresscategory;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* @author lilemy
* @date 2025-11-13 10:47
*/
@Data
@ExcelIgnoreUnannotated
public class PgsProgressCategoryExportTotalVo implements Serializable {
@Serial
private static final long serialVersionUID = -5830653037297127006L;
/**
* 主键
*/
private Long id;
/**
* 类别名称
*/
@ExcelProperty(value = "类别名称")
private String name;
/**
* 计量方式0无 1数量 2百分比
*/
@ExcelProperty(value = "计量方式", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "0=无,1=数量,2=百分比")
private String unitType;
/**
* 计量单位
*/
@ExcelProperty(value = "计量单位")
private String unit;
/**
* 总数量
*/
@ExcelProperty(value = "总数量")
private BigDecimal total;
/**
* 计划总数量
*/
@ExcelProperty(value = "计划总数量")
private BigDecimal planTotal;
/**
* 已完成数量
*/
@ExcelProperty(value = "已完成总数量")
private BigDecimal completed;
}

View File

@ -2,13 +2,16 @@ package org.dromara.progress.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import jakarta.servlet.http.HttpServletResponse;
import org.dromara.facility.domain.FacMatrix;
import org.dromara.progress.domain.PgsProgressCategory;
import org.dromara.progress.domain.PgsProgressPlan;
import org.dromara.progress.domain.dto.progresscategory.*;
import org.dromara.progress.domain.vo.progresscategory.*;
import org.springframework.web.multipart.MultipartFile;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@ -147,11 +150,15 @@ public interface IPgsProgressCategoryService extends IService<PgsProgressCategor
/**
* 根据父项目id获取项目进度类别列表
*
* @param projectIds 项目id列表
*/
List<PgsProgressCategory> queryListByProjectIds(List<Long> projectIds);
/***
* 获取方阵id及对应数量
*
* @param projectId 项目id
*/
List<Map<String, Object>> getMatrixIdAndNumber(Long projectId);
@ -180,6 +187,15 @@ public interface IPgsProgressCategoryService extends IService<PgsProgressCategor
*/
List<PgsProgressCategory> getLeafNodesByTopId(Long topId, List<PgsProgressCategory> allCategory);
/**
* 获取最底层的叶子节点支持多个顶级id
*
* @param topIdList 顶级节点id集合
* @param allCategory 所有节点
* @return 最底层的叶子节点
*/
List<PgsProgressCategory> getLeafNodesByTopIds(List<Long> topIdList, List<PgsProgressCategory> allCategory);
/**
* 获取最底层的叶子节点支持多个顶级id
*
@ -268,4 +284,44 @@ public interface IPgsProgressCategoryService extends IService<PgsProgressCategor
* @return 进度类别产值
*/
PgsProgressCategoryValueVo getValueByParentId(PgsProgressCategoryQueryByParentReq req);
/**
* 获取指定日期进度类别列表
*
* @param projectId 项目id
* @param date 日期
* @return 进度类别列表
*/
PgsProgressCategoryDayTotalVo getProgressCategoryByDay(Long projectId, LocalDate date);
/**
* 导出项目进度类别列表
*
* @param req 查询条件
* @param response 响应
*/
void export(PgsProgressCategoryQueryReq req, HttpServletResponse response);
/**
* 导出项目进度类别列表,根据名称分类
*
* @param projectId 项目id
* @param response 响应
*/
void exportTotalByName(Long projectId, HttpServletResponse response);
/**
* 导出项目进度类别列表,根据名称分类
*
* @param parentId 父级id
* @param response 响应
*/
void exportTotalByNameParent(Long parentId, HttpServletResponse response);
/**
* 导入项目进度类别列表
*
* @param file 文件
*/
String importData(MultipartFile file);
}

View File

@ -3,17 +3,23 @@ package org.dromara.progress.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
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.core.utils.StringUtils;
import org.dromara.common.excel.core.DefaultExcelListener;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.utils.BigDecimalUtil;
import org.dromara.common.utils.JsonDimensionUtil;
import org.dromara.facility.domain.*;
@ -24,10 +30,7 @@ import org.dromara.progress.domain.PgsProgressCategoryTemplate;
import org.dromara.progress.domain.PgsProgressPlan;
import org.dromara.progress.domain.PgsProgressPlanDetail;
import org.dromara.progress.domain.dto.progresscategory.*;
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.enums.PgsRelevancyStructureEnum;
import org.dromara.progress.domain.enums.*;
import org.dromara.progress.domain.vo.progresscategory.*;
import org.dromara.progress.domain.vo.progressplandetail.PgsProgressPlanDetailDateVo;
import org.dromara.progress.domain.vo.progressplandetail.PgsProgressPlanDetailFinishedVo;
@ -42,7 +45,9 @@ import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
@ -1388,11 +1393,10 @@ public class PgsProgressCategoryServiceImpl extends ServiceImpl<PgsProgressCateg
// 1. 查出所有属于该顶级节点的子孙节点
List<PgsProgressCategory> allChildren = this.list(
Wrappers.<PgsProgressCategory>lambdaQuery()
.and(wrapper -> {
.and(wrapper ->
wrapper.like(PgsProgressCategory::getAncestors, "," + topId + ",")
.or()
.like(PgsProgressCategory::getAncestors, "," + topId);
})
.like(PgsProgressCategory::getAncestors, "," + topId))
);
if (allChildren.isEmpty()) {
@ -1446,6 +1450,53 @@ public class PgsProgressCategoryServiceImpl extends ServiceImpl<PgsProgressCateg
.toList();
}
/**
* 获取最底层的叶子节点支持多个顶级id
*
* @param topIdList 顶级节点id集合
* @param allCategory 所有节点
* @return 最底层的叶子节点
*/
@Override
public List<PgsProgressCategory> getLeafNodesByTopIds(List<Long> topIdList, List<PgsProgressCategory> allCategory) {
if (allCategory == null || allCategory.isEmpty() || topIdList == null || topIdList.isEmpty()) {
return Collections.emptyList();
}
// 1. 找出所有属于任意一个顶级节点的子孙节点Ancestors 字段包含其中任意一个 topId
List<PgsProgressCategory> allChildren = allCategory.stream()
.filter(item -> {
String ancestors = item.getAncestors();
if (ancestors == null) {
return false;
}
// 任意一个 topId 匹配成功即保留
return topIdList.stream().anyMatch(topId ->
ancestors.contains("," + topId + ",") ||
ancestors.endsWith("," + topId) ||
ancestors.startsWith(topId + ",") ||
ancestors.equals(String.valueOf(topId))
);
})
.toList();
if (allChildren.isEmpty()) {
return Collections.emptyList();
}
// 2. 找出所有有孩子的节点 ID即 parentId 出现的节点)
Set<Long> parentIds = allChildren.stream()
.map(PgsProgressCategory::getParentId)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
// 3. 过滤出没有作为别人 parentId 出现的节点 → 叶子节点
return allChildren.stream()
.filter(item -> !parentIds.contains(item.getId()))
.toList();
}
/**
* 获取最底层的叶子节点支持多个顶级id
*
@ -2212,6 +2263,379 @@ public class PgsProgressCategoryServiceImpl extends ServiceImpl<PgsProgressCateg
return vo;
}
/**
* 获取指定日期进度类别列表
*
* @param projectId 项目id
* @param date 日期
* @return 进度类别列表
*/
@Override
public PgsProgressCategoryDayTotalVo getProgressCategoryByDay(Long projectId, LocalDate date) {
BusProject project = projectService.getById(projectId);
if (project == null) {
throw new ServiceException("项目不存在", HttpStatus.NOT_FOUND);
}
// 获取当前项目的子项目
List<BusProject> projects = projectService.lambdaQuery()
.eq(BusProject::getPId, projectId)
.list();
projects.add(project);
List<Long> allProjectIds = projects.stream().map(BusProject::getId).toList();
// 获取当前项目的所有进度类别
List<PgsProgressCategory> allList = this.lambdaQuery()
.in(PgsProgressCategory::getProjectId, allProjectIds)
.list();
// 获取最顶层的进度类别
List<PgsProgressCategory> topList = allList.stream()
.filter(category -> category.getParentId().equals(PgsProgressCategoryConstant.TOP_PARENT_ID))
.toList();
// 获取指定日期的计划详情
List<PgsProgressPlanDetail> detailList = progressPlanDetailService.lambdaQuery()
.in(PgsProgressPlanDetail::getProjectId, allProjectIds)
.eq(PgsProgressPlanDetail::getDate, date)
.list();
// 根据项目id进行分类
Map<Long, String> projectMap = projects.stream()
.collect(Collectors.toMap(BusProject::getId, BusProject::getProjectName));
// 根据项目进行分类
Map<Long, List<PgsProgressCategory>> topMap = topList.stream()
.collect(Collectors.groupingBy(PgsProgressCategory::getProjectId));
PgsProgressCategoryDayTotalVo totalVo = new PgsProgressCategoryDayTotalVo();
List<PgsProgressCategoryByDayVo> voList = new ArrayList<>();
for (Map.Entry<Long, List<PgsProgressCategory>> entry : topMap.entrySet()) {
// 获取当前父类下的最底层子类
List<PgsProgressCategory> value = entry.getValue();
// 根据名称进行分类
Map<String, List<PgsProgressCategory>> topNameMap = value.stream()
.collect(Collectors.groupingBy(PgsProgressCategory::getName));
PgsProgressCategoryByDayVo vo = new PgsProgressCategoryByDayVo();
for (Map.Entry<String, List<PgsProgressCategory>> nameEntry : topNameMap.entrySet()) {
vo.setProjectId(entry.getKey());
vo.setProjectName(projectMap.get(entry.getKey()));
String nameKey = nameEntry.getKey();
List<PgsProgressCategory> nameValue = nameEntry.getValue();
List<Long> topIds = nameValue.stream().map(PgsProgressCategory::getId).toList();
List<PgsProgressCategory> children = this.getLeafNodesByTopIds(topIds, allList);
if (CollUtil.isEmpty(children)) {
continue;
}
// 提取所有 children 的 id
Set<Long> childIds = children.stream()
.map(PgsProgressCategory::getId)
.collect(Collectors.toSet());
List<PgsProgressPlanDetail> planDetailList = detailList.stream()
.filter(detail -> childIds.contains(detail.getProgressCategoryId()))
.toList();
// 将子类根据名称进行分类
List<PgsProgressCategoryDetailByDayVo> detail = this.getChildrenDetailByName(children, planDetailList);
vo.setSize(detail.size());
switch (PgsProgressCategoryTypeEnum.fromText(nameKey)) {
case BOOSTER_STATION:
vo.setBoosterStation(detail);
break;
case COLLECTING_LINE:
vo.setCollectingLine(detail);
break;
case SEND_LINE:
vo.setSendLine(detail);
break;
case PHOTOVOLTAIC_AREA:
vo.setPhotovoltaicArea(detail);
break;
case OTHER_PROJECT:
vo.setOtherProject(detail);
break;
case null, default:
break;
}
}
if (entry.getKey().equals(projectId)) {
totalVo.setProject(vo);
} else {
voList.add(vo);
}
}
totalVo.setSubProjectList(voList);
return totalVo;
}
/**
* 导出项目进度类别列表
*
* @param req 查询条件
* @param response 响应
*/
@Override
public void export(PgsProgressCategoryQueryReq req, HttpServletResponse response) {
LambdaQueryWrapper<PgsProgressCategory> lqw = new LambdaQueryWrapper<>();
//要导出的整个sheet所需要的names
List<String> names = new ArrayList<>();
//要导出的list
List<List<PgsProgressCategoryVo>> listValues = new ArrayList<>();
Long parentId = req.getParentId();
String relevancyStructure = req.getRelevancyStructure();
if (relevancyStructure.equals("2")) {
// 父类id不为空导出父类对应的子类
PgsProgressCategory category = this.getById(parentId);
if (category == null) {
throw new ServiceException("父进度类别不存在", HttpStatus.NOT_FOUND);
}
names.add(category.getName());
QueryWrapper<PgsProgressCategory> queryWrapper = new QueryWrapper<>();
queryWrapper.apply("FIND_IN_SET({0}, ancestors)", parentId);
List<PgsProgressCategoryVo> voList = this.getVoList(this.list(queryWrapper));
listValues.add(voList);
} else {
BusProject project = projectService.getById(req.getProjectId());
if (project == null) {
throw new ServiceException("项目不存在", HttpStatus.NOT_FOUND);
}
List<BusProject> projects;
if (project.getPId().equals(0L)) {
projects = projectService.lambdaQuery()
.eq(BusProject::getPId, req.getProjectId())
.list();
projects.add(project);
List<Long> ids = projects.stream().map(BusProject::getId).toList();
lqw.in(CollUtil.isNotEmpty(ids), PgsProgressCategory::getProjectId, ids);
} else {
projects = List.of(project);
lqw.eq(req.getProjectId() != null, PgsProgressCategory::getProjectId, req.getProjectId());
}
lqw.eq(req.getMatrixId() != null, PgsProgressCategory::getMatrixId, req.getMatrixId());
// 查询数据
lqw.eq(PgsProgressCategory::getParentId, 0L);
List<PgsProgressCategory> list = this.list(lqw);
Map<Long, String> projectNameMap = projects.stream()
.collect(Collectors.toMap(BusProject::getId, BusProject::getProjectName));
// 获取非方阵类别name 非方阵类别有多级 暂定只有2级 也有可能没有父子关系
List<PgsProgressCategory> unMatrixList = list.stream().filter(category ->
!category.getRelevancyStructure().equals(PgsRelevancyStructureEnum.MATRIX.getValue())).toList();
if (!unMatrixList.isEmpty()) {
for (PgsProgressCategory unMatrix : unMatrixList) {
//所有非方阵顶类名
names.add(unMatrix.getName() + "-" + projectNameMap.get(unMatrix.getProjectId()));
//寻找子类
lqw = new LambdaQueryWrapper<>();
lqw.eq(PgsProgressCategory::getParentId, unMatrix.getId());
List<PgsProgressCategoryVo> children = this.getVoList(this.list(lqw));
if (!children.isEmpty()) {
//寻找孙类 然后添加
List<PgsProgressCategoryVo> grandson = new ArrayList<>();
for (PgsProgressCategoryVo childrenCategory : children) {
lqw = new LambdaQueryWrapper<>();
lqw.eq(PgsProgressCategory::getParentId, childrenCategory.getId());
List<PgsProgressCategoryVo> grandsonCategory = this.getVoList(this.list(lqw));
if (!grandsonCategory.isEmpty()) {
grandson.addAll(grandsonCategory);
} else {
grandson = children;
}
}
listValues.add(grandson);
}
}
}
//获取矩阵类别name
List<PgsProgressCategory> matrixList = list.stream().filter(category ->
category.getRelevancyStructure().equals(PgsRelevancyStructureEnum.MATRIX.getValue())).toList();
if (!matrixList.isEmpty()) {
for (PgsProgressCategory pgsProgressCategory : matrixList) {
//增加矩阵名
names.add(pgsProgressCategory.getName() + "-" + pgsProgressCategory.getMatrixName());
//找到该矩阵下的列表
lqw = new LambdaQueryWrapper<>();
lqw.eq(PgsProgressCategory::getMatrixId, pgsProgressCategory.getMatrixId());
listValues.add(this.getVoList(this.list(lqw)));
}
}
}
try {
ExcelUtil.exportMultiSheetExcelEnhanced(listValues, names, PgsProgressCategoryVo.class, null, response);
} catch (IOException e) {
throw new ServiceException("导出失败");
}
}
/**
* 导出项目进度类别列表,根据名称分类
*
* @param projectId 项目id
* @param response 响应
*/
@Override
public void exportTotalByName(Long projectId, HttpServletResponse response) {
BusProject project = projectService.getById(projectId);
if (project == null) {
throw new ServiceException("项目不存在", HttpStatus.NOT_FOUND);
}
// 获取当前项目的子项目
List<BusProject> projects = projectService.lambdaQuery()
.eq(BusProject::getPId, projectId)
.list();
List<Long> allProjectIds = new ArrayList<>(projects.stream().map(BusProject::getId).toList());
allProjectIds.add(projectId);
// 获取当前项目的所有进度类别
List<PgsProgressCategory> allList = this.lambdaQuery()
.in(PgsProgressCategory::getProjectId, allProjectIds)
.list();
// 获取最顶层的进度类别
List<PgsProgressCategory> topList = allList.stream()
.filter(category -> category.getParentId().equals(PgsProgressCategoryConstant.TOP_PARENT_ID))
.toList();
// 根据名字进行分类
List<String> names = new ArrayList<>();
List<List<PgsProgressCategoryExportTotalVo>> listValues = new ArrayList<>();
Map<String, List<PgsProgressCategory>> topMap = topList.stream()
.collect(Collectors.groupingBy(PgsProgressCategory::getName));
for (Map.Entry<String, List<PgsProgressCategory>> entry : topMap.entrySet()) {
names.add(entry.getKey());
// 获取当前父类下的最底层子类
List<PgsProgressCategory> value = entry.getValue();
List<Long> topIds = value.stream().map(PgsProgressCategory::getId).toList();
List<PgsProgressCategory> children = this.getLeafNodesByTopIds(topIds, allList);
if (CollUtil.isEmpty(children)) {
continue;
}
// 将子类根据名称进行分类
List<PgsProgressCategoryExportTotalVo> result = getChildrenTotalByName(children);
listValues.add(result);
}
try {
ExcelUtil.exportMultiSheetExcelEnhanced(listValues, names, PgsProgressCategoryExportTotalVo.class, null, response);
} catch (IOException e) {
throw new ServiceException("导出失败");
}
}
/**
* 导出项目进度类别列表,根据名称分类
*
* @param parentId 父级id
* @param response 响应
*/
@Override
public void exportTotalByNameParent(Long parentId, HttpServletResponse response) {
PgsProgressCategory parent = this.getById(parentId);
if (parent == null) {
throw new ServiceException("父级不存在", HttpStatus.NOT_FOUND);
}
// 获取当前父级的所有进度类别
List<PgsProgressCategory> children = this.getLeafNodesByTopId(parentId);
if (CollUtil.isEmpty(children)) {
throw new ServiceException("没有数据");
}
// 根据名称进行分类,并统计数据
List<PgsProgressCategoryExportTotalVo> total = this.getChildrenTotalByName(children);
ExcelUtil.exportExcel(total, parent.getName(), PgsProgressCategoryExportTotalVo.class, response);
}
/**
* 导入项目进度类别列表
*
* @param file 文件
*/
@Override
@Transactional(rollbackFor = Exception.class)
public String importData(MultipartFile file) {
// 检查文件是否为空
if (file == null || file.isEmpty()) {
throw new ServiceException("上传文件不能为空");
}
// 检查文件大小
if (file.getSize() == 0) {
throw new ServiceException("上传文件不能为空文件");
}
// 检查文件名
if (file.getOriginalFilename() == null || file.getOriginalFilename().isEmpty()) {
throw new ServiceException("文件名不能为空");
}
try {
// 使用EasyExcel读取所有sheet
List<PgsProgressCategoryVo> allData = new ArrayList<>();
// 创建Excel读取监听器
DefaultExcelListener<PgsProgressCategoryVo> listener = new DefaultExcelListener<>(false);
// 读取Excel文件
ExcelReader excelReader = EasyExcel.read(file.getInputStream(), PgsProgressCategoryVo.class, listener).build();
// 获取所有sheet
List<ReadSheet> sheetList = excelReader.excelExecutor().sheetList();
// 遍历所有sheet
for (ReadSheet readSheet : sheetList) {
// 为每个sheet创建新的监听器实例
DefaultExcelListener<PgsProgressCategoryVo> sheetListener = new DefaultExcelListener<>(false);
// 读取当前sheet数据
EasyExcel.read(file.getInputStream(), PgsProgressCategoryVo.class, sheetListener)
.sheet(readSheet.getSheetNo())
.doRead();
List<PgsProgressCategoryVo> list = sheetListener.getExcelResult().getList();
List<PgsProgressCategoryVo> newList = list.stream().filter(vo -> vo.getId() == null).toList();
List<PgsProgressCategoryVo> oldList = list.stream().filter(vo -> vo.getId() != null).toList();
Set<Long> ids = oldList.stream().map(PgsProgressCategoryVo::getId).collect(Collectors.toSet());
List<PgsProgressCategory> categoryList = this.listByIds(ids);
// 筛选出关联设计图的数据
List<PgsProgressCategoryVo> oldListVo = oldList.stream().filter(vo -> {
PgsProgressCategory category = categoryList.stream().filter(c -> c.getId().equals(vo.getId())).findFirst().orElse(null);
if (category == null) {
return true;
}
String workType = category.getWorkType();
return StringUtils.isBlank(workType);
}).toList();
// 将当前sheet的数据添加到总数据中
allData.addAll(oldListVo);
if (CollUtil.isNotEmpty(newList) && CollUtil.isNotEmpty(oldList)) {
PgsProgressCategoryVo first = oldList.getFirst();
PgsProgressCategory category = this.getById(first.getId());
newList.forEach(vo -> {
vo.setParentId(category.getParentId());
vo.setProjectId(category.getProjectId());
vo.setMatrixId(category.getMatrixId());
vo.setAncestors(category.getAncestors());
vo.setRelevancyStructure(category.getRelevancyStructure());
});
allData.addAll(newList);
}
}
// 关闭读取器
excelReader.finish();
if (allData.isEmpty()) {
throw new ServiceException("未读取到有效数据");
}
// 处理导入的数据
List<PgsProgressCategory> list = new ArrayList<>();
for (PgsProgressCategoryVo vo : allData) {
list.add(this.convertVoToEntity(vo));
}
// 计算产值
list.forEach(pgsProgressCategory -> {
BigDecimal ownerPrice = pgsProgressCategory.getOwnerPrice();
BigDecimal constructionPrice = pgsProgressCategory.getConstructionPrice();
BigDecimal total = pgsProgressCategory.getTotal();
if (total != null && total.compareTo(BigDecimal.ZERO) != 0) {
if (ownerPrice != null && ownerPrice.compareTo(BigDecimal.ZERO) != 0) {
pgsProgressCategory.setOwnerOutputValue(ownerPrice.multiply(total).setScale(4, RoundingMode.HALF_UP));
}
if (constructionPrice != null && constructionPrice.compareTo(BigDecimal.ZERO) != 0) {
pgsProgressCategory.setConstructionOutputValue(constructionPrice.multiply(total).setScale(4, RoundingMode.HALF_UP));
}
}
// 关联数据不更新数量
if (pgsProgressCategory.getRemark() != null && pgsProgressCategory.getRemark().equals("关联数据")) {
pgsProgressCategory.setTotal(null);
}
});
boolean b = this.saveOrUpdateBatch(list);
if (!b) {
throw new ServiceException("更新失败");
}
return "导入成功,共更新 " + list.size() + " 条数据";
} catch (Exception e) {
log.error("导入Excel文件失败", e);
throw new ServiceException("导入Excel文件失败" + e.getMessage());
}
}
/**
* 计算进度类别(含子类别)的开始和结束时间。
* <p>
@ -2231,51 +2655,42 @@ public class PgsProgressCategoryServiceImpl extends ServiceImpl<PgsProgressCateg
List<PgsProgressCategory> allChildren,
List<PgsProgressPlan> allPlanList) {
PgsProgressCategoryGanttVo ganttVo = new PgsProgressCategoryGanttVo();
// 获取该类别下的所有叶子节点(无子节点的类别)
List<PgsProgressCategory> children = this.getLeafNodesByTopId(progressCategoryId, allChildren);
if (CollUtil.isEmpty(children)) {
// --- 叶子节点:直接根据计划计算 ---
List<PgsProgressPlan> planList = allPlanList.stream()
.filter(p -> p.getProgressCategoryId().equals(progressCategoryId))
.toList();
if (CollUtil.isNotEmpty(planList)) {
LocalDate startDate = planList.stream()
.map(PgsProgressPlan::getStartDate)
.filter(Objects::nonNull)
.min(LocalDate::compareTo)
.orElse(null);
LocalDate endDate = planList.stream()
.map(PgsProgressPlan::getEndDate)
.filter(Objects::nonNull)
.max(LocalDate::compareTo)
.orElse(null);
ganttVo.setStartDate(startDate);
ganttVo.setEndDate(endDate);
}
} else {
// --- 非叶子节点:递归计算子节点 ---
List<PgsProgressCategoryGanttVo> childVoList = children.stream()
.map(child -> getCategoryStartDateAndEndDate(child.getId(), allChildren, allPlanList))
.toList();
LocalDate minStart = childVoList.stream()
.map(PgsProgressCategoryGanttVo::getStartDate)
.filter(Objects::nonNull)
.min(LocalDate::compareTo)
.orElse(null);
LocalDate maxEnd = childVoList.stream()
.map(PgsProgressCategoryGanttVo::getEndDate)
.filter(Objects::nonNull)
.max(LocalDate::compareTo)
.orElse(null);
ganttVo.setStartDate(minStart);
ganttVo.setEndDate(maxEnd);
}
@ -2370,4 +2785,133 @@ public class PgsProgressCategoryServiceImpl extends ServiceImpl<PgsProgressCateg
}
}
/**
* 根据子级名称分类并统计数据
*
* @param children 子级
* @return 分类后的数据
*/
private List<PgsProgressCategoryExportTotalVo> getChildrenTotalByName(List<PgsProgressCategory> children) {
// 将子类根据名称进行分类
Map<String, List<PgsProgressCategory>> childrenMap = children.stream()
.collect(Collectors.groupingBy(PgsProgressCategory::getName));
return childrenMap.entrySet().stream()
.map(c -> {
String name = c.getKey();
List<PgsProgressCategory> list = c.getValue();
// 汇总
BigDecimal total = list.stream()
.map(PgsProgressCategory::getTotal)
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal planTotal = list.stream()
.map(PgsProgressCategory::getPlanTotal)
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal completed = list.stream()
.map(PgsProgressCategory::getCompleted)
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
// 假设同名类别下的 unit / unitType 一致,取第一个即可
String unit = list.stream()
.map(PgsProgressCategory::getUnit)
.filter(Objects::nonNull)
.findFirst().orElse(null);
String unitType = list.stream()
.map(PgsProgressCategory::getUnitType)
.filter(Objects::nonNull)
.findFirst().orElse(null);
// 封装结果
PgsProgressCategoryExportTotalVo vo = new PgsProgressCategoryExportTotalVo();
vo.setId(list.getFirst().getId());
vo.setName(name);
vo.setUnit(unit);
vo.setUnitType(unitType);
vo.setTotal(total);
vo.setPlanTotal(planTotal);
vo.setCompleted(completed);
return vo;
}).sorted(Comparator.comparing(PgsProgressCategoryExportTotalVo::getId)).toList();
}
/**
* 根据子级名称分类并统计数据
*
* @param children 子级
* @param planList 计划
* @return 分类后的数据
*/
private List<PgsProgressCategoryDetailByDayVo> getChildrenDetailByName(List<PgsProgressCategory> children,
List<PgsProgressPlanDetail> planList) {
// 将子类根据名称进行分类
Map<String, List<PgsProgressCategory>> childrenMap = children.stream()
.collect(Collectors.groupingBy(PgsProgressCategory::getName));
Map<Long, List<PgsProgressPlanDetail>> detailMap = new HashMap<>();
if (CollUtil.isNotEmpty(planList)) {
detailMap = planList.stream()
.collect(Collectors.groupingBy(PgsProgressPlanDetail::getProgressCategoryId));
}
Map<Long, List<PgsProgressPlanDetail>> finalDetailMap = detailMap;
return childrenMap.entrySet().stream()
.map(c -> {
String name = c.getKey();
List<PgsProgressCategory> list = c.getValue();
if (CollUtil.isEmpty(list)) {
return null;
}
// 汇总
BigDecimal total = list.stream()
.map(PgsProgressCategory::getTotal)
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal completed = list.stream()
.map(PgsProgressCategory::getCompleted)
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
// 假设同名类别下的 unit / unitType 一致,取第一个即可
String unit = list.stream()
.map(PgsProgressCategory::getUnit)
.filter(Objects::nonNull)
.findFirst().orElse(null);
// 获取施工计划数量
BigDecimal constructionPlan = BigDecimal.ZERO;
if (CollUtil.isNotEmpty(finalDetailMap)) {
constructionPlan = list.stream()
.map(PgsProgressCategory::getId)
.filter(Objects::nonNull)
.map(finalDetailMap::get)
.filter(Objects::nonNull)
.flatMap(Collection::stream)
.map(PgsProgressPlanDetail::getPlanNumber)
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
// 获取施工完成数量
BigDecimal constructionCompleted = BigDecimal.ZERO;
if (CollUtil.isNotEmpty(finalDetailMap)) {
constructionPlan = list.stream()
.map(PgsProgressCategory::getId)
.filter(Objects::nonNull)
.map(finalDetailMap::get)
.filter(Objects::nonNull)
.flatMap(Collection::stream)
.map(PgsProgressPlanDetail::getFinishedNumber)
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
// 封装结果
PgsProgressCategoryDetailByDayVo vo = new PgsProgressCategoryDetailByDayVo();
vo.setConstructionPlan(constructionPlan);
vo.setConstructionCompleted(constructionCompleted);
vo.setId(list.getFirst().getId());
vo.setName(name);
vo.setUnit(unit);
vo.setTotal(total);
vo.setCompleted(completed);
vo.setCompletedPercentage(BigDecimalUtil.toPercentage(completed, total));
return vo;
}).filter(Objects::nonNull)
.sorted(Comparator.comparing(PgsProgressCategoryDetailByDayVo::getId)).toList();
}
}

View File

@ -16,12 +16,10 @@ import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.enums.AppUserTypeEnum;
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.common.utils.AsyncUtil;
import org.dromara.common.utils.IdCardEncryptorUtil;
import org.dromara.contractor.domain.SubConstructionUser;
import org.dromara.contractor.service.ISubConstructionUserService;
import org.dromara.dataTransmission.clarityPm.method.ClarityPmAsyncMethod;
import org.dromara.project.domain.BusConstructionUserExit;
import org.dromara.project.domain.BusProjectTeam;
import org.dromara.project.domain.BusProjectTeamMember;
@ -185,14 +183,14 @@ public class BusProjectTeamMemberServiceImpl extends ServiceImpl<BusProjectTeamM
LambdaUpdateWrapper<SubConstructionUser> constructionUserLuw = Wrappers.lambdaUpdate(SubConstructionUser.class)
.eq(SubConstructionUser::getId, constructionUser.getId())
.set(SubConstructionUser::getProjectId, req.getProjectId())
.set(req.getContractorId()!=null,SubConstructionUser::getContractorId, req.getContractorId())
.set(req.getContractorId() != null, SubConstructionUser::getContractorId, req.getContractorId())
.set(SubConstructionUser::getTeamId, projectTeamMember.getTeamId())
.set(SubConstructionUser::getTeamName, projectTeam.getTeamName())
.set(SubConstructionUser::getEntryDate, new Date())
.set(SubConstructionUser::getLeaveDate, null)
.set(SubConstructionUser::getExitStatus, "0")
.set(SubConstructionUser::getUserRole, "0")
.set(StrUtil.isNotBlank(req.getTypeOfWork()),SubConstructionUser::getTypeOfWork,req.getTypeOfWork())
.set(StrUtil.isNotBlank(req.getTypeOfWork()), SubConstructionUser::getTypeOfWork, req.getTypeOfWork())
.set(constructionUser.getFirstDate() == null, SubConstructionUser::getFirstDate, LocalDate.now());
constructionUserService.update(constructionUserLuw);
@ -223,8 +221,8 @@ public class BusProjectTeamMemberServiceImpl extends ServiceImpl<BusProjectTeamM
roleService.cleanOnlineUser(Collections.singletonList(constructionUser.getSysUserId()));
if(req.getContractorId()!=null){
userService.updateFb(constructionUser.getSysUserId(),req.getContractorId(),false);
if (req.getContractorId() != null) {
userService.updateFb(constructionUser.getSysUserId(), req.getContractorId(), false);
}
asyncUtil.sendPersonnel(req.getTeamId(), constructionUser);
@ -271,7 +269,7 @@ public class BusProjectTeamMemberServiceImpl extends ServiceImpl<BusProjectTeamM
constructionUserService.update(constructionUserLuw);
}
if(StrUtil.isNotBlank(req.getPostId()) && !oldProjectTeamMember.getPostId().equals(req.getPostId())){
if (StrUtil.isNotBlank(req.getPostId()) && !oldProjectTeamMember.getPostId().equals(req.getPostId())) {
//设置基础角色 先清空已有角色
userRoleMapper.delete(Wrappers.<SysUserRole>lambdaQuery()
.eq(SysUserRole::getUserId, constructionUser.getSysUserId())
@ -333,8 +331,9 @@ public class BusProjectTeamMemberServiceImpl extends ServiceImpl<BusProjectTeamM
Long id = req.getId();
String salaryVoucherFile = req.getSalaryVoucherFile();
String salaryConfirmationFile = req.getSalaryConfirmationFile();
String exitStatus = "2";
if (StringUtils.isAnyBlank(salaryVoucherFile, salaryConfirmationFile)) {
throw new ServiceException("请上传退场文件", HttpStatus.ERROR);
exitStatus = "1";
}
BusProjectTeamMember projectTeamMember = this.getById(id);
if (projectTeamMember == null) {
@ -365,7 +364,7 @@ public class BusProjectTeamMemberServiceImpl extends ServiceImpl<BusProjectTeamM
// 同步修改用户表的team_id字段
LambdaUpdateWrapper<SubConstructionUser> constructionUserLuw = Wrappers.lambdaUpdate(SubConstructionUser.class)
.eq(SubConstructionUser::getId, constructionUser.getId())
.set(SubConstructionUser::getExitStatus, "2")
.set(SubConstructionUser::getExitStatus, exitStatus)
.set(SubConstructionUser::getTeamId, null)
.set(SubConstructionUser::getLeaveDate, new Date());
constructionUserService.update(constructionUserLuw);
@ -394,9 +393,9 @@ public class BusProjectTeamMemberServiceImpl extends ServiceImpl<BusProjectTeamM
if (userVo != null) {
projectTeamMemberVo.setMemberName(userVo.getNickName());
Long avatar = userVo.getAvatar();
if(avatar != null){
if (avatar != null) {
SysOssVo byId = ossService.getById(avatar);
if(byId != null){
if (byId != null) {
projectTeamMemberVo.setAvatar(byId.getUrl());
}
}
@ -489,13 +488,13 @@ public class BusProjectTeamMemberServiceImpl extends ServiceImpl<BusProjectTeamM
}
@Override
public String getPost(Long userId,Long projectId) {
public String getPost(Long userId, Long projectId) {
BusProjectTeamMember busProjectTeamMember = baseMapper.selectOne(Wrappers.<BusProjectTeamMember>lambdaQuery()
.eq(BusProjectTeamMember::getMemberId, userId)
.eq(BusProjectTeamMember::getProjectId, projectId)
.last("limit 1")
);
if(busProjectTeamMember == null){
if (busProjectTeamMember == null) {
return null;
}
return busProjectTeamMember.getPostId();

View File

@ -232,6 +232,11 @@ public class XzdMachineryContractAlterationBo extends BaseEntity {
*/
private String contractText;
private LocalDate startTime;
private LocalDate endTime;
/**
* 组织id
*/

View File

@ -15,6 +15,7 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.common.utils.BatchNumberGenerator;
import org.dromara.system.service.impl.SysOssServiceImpl;
import org.dromara.xzd.biddingManagement.biaoqianlixiang.domain.XzdProjectRiskAssessment;
import org.dromara.xzd.contractManagement.caigouhetongbiangeng.domain.XzdPurchaseContractAlteration;
import org.dromara.xzd.contractManagement.caigouhetongbiangeng.domain.vo.XzdPurchaseContractAlterationVo;
import org.dromara.xzd.contractManagement.jixiehetongxinxi.domain.XzdEquipmentLeasing;
@ -219,6 +220,8 @@ public class XzdMachineryContractAlterationServiceImpl extends ServiceImpl<XzdMa
lqw.eq(StringUtils.isNotBlank(bo.getRevisedTotalAmount()), XzdMachineryContractAlteration::getRevisedTotalAmount, bo.getRevisedTotalAmount());
lqw.eq(StringUtils.isNotBlank(bo.getContractText()), XzdMachineryContractAlteration::getContractText, bo.getContractText());
lqw.eq(bo.getDeptId() != null, XzdMachineryContractAlteration::getDeptId, bo.getDeptId());
lqw.gt(bo.getStartTime() != null, XzdMachineryContractAlteration::getCreateTime, bo.getStartTime());
lqw.lt(bo.getEndTime() != null, XzdMachineryContractAlteration::getCreateTime, bo.getEndTime());
return lqw;
}
@ -232,7 +235,7 @@ public class XzdMachineryContractAlterationServiceImpl extends ServiceImpl<XzdMa
public Boolean insertByBo(XzdMachineryContractAlterationBo bo) {
XzdMachineryContractAlteration add = MapstructUtils.convert(bo, XzdMachineryContractAlteration.class);
validEntityBeforeSave(add);
String banBen = BatchNumberGenerator.generateBatchNumber("JXHTXX-");
String banBen = BatchNumberGenerator.generateBatchNumber("JXHTBG-");
add.setReceiptsCode(banBen);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {

View File

@ -259,6 +259,11 @@ public class XzdContractMachineryBo extends BaseEntity {
private Long deptId;
private LocalDate startTime;
private LocalDate endTime;
/**
* 印章信息
*/

View File

@ -234,6 +234,8 @@ public class XzdContractMachineryServiceImpl extends ServiceImpl<XzdContractMach
lqw.eq(StringUtils.isNotBlank(bo.getFileId()), XzdContractMachinery::getFileId, bo.getFileId());
lqw.eq(StringUtils.isNotBlank(bo.getAuditStatus()), XzdContractMachinery::getAuditStatus, bo.getAuditStatus());
lqw.eq(bo.getDeptId() != null, XzdContractMachinery::getDeptId, bo.getDeptId());
lqw.gt(bo.getStartTime() != null, XzdContractMachinery::getCreateTime, bo.getStartTime());
lqw.lt(bo.getEndTime() != null, XzdContractMachinery::getCreateTime, bo.getEndTime());
return lqw;
}

View File

@ -144,6 +144,10 @@ public class XzdMachineryContractSuspendBo extends BaseEntity {
*/
private Long deptId;
private LocalDate startTime;
private LocalDate endTime;
/**
* 印章信息
*/

View File

@ -19,6 +19,7 @@ import org.dromara.common.utils.BatchNumberGenerator;
import org.dromara.system.service.impl.SysOssServiceImpl;
import org.dromara.xzd.contractManagement.caigoucontractTermination.domain.XzdPurchaseContractSuspend;
import org.dromara.xzd.contractManagement.caigoucontractTermination.domain.vo.XzdPurchaseContractSuspendVo;
import org.dromara.xzd.contractManagement.jixiehetongbiang.domain.XzdMachineryContractAlteration;
import org.dromara.xzd.contractManagement.jixiehetongxinxi.domain.XzdContractMachinery;
import org.dromara.xzd.contractManagement.jixiehetongxinxi.domain.vo.XzdContractMachineryVo;
import org.dromara.xzd.contractManagement.jixiehetongxinxi.mapper.XzdContractMachineryMapper;
@ -158,6 +159,8 @@ public class XzdMachineryContractSuspendServiceImpl extends ServiceImpl<XzdMachi
lqw.eq(StringUtils.isNotBlank(bo.getFileId()), XzdMachineryContractSuspend::getFileId, bo.getFileId());
lqw.eq(StringUtils.isNotBlank(bo.getAuditStatus()), XzdMachineryContractSuspend::getAuditStatus, bo.getAuditStatus());
lqw.eq(bo.getDeptId() != null, XzdMachineryContractSuspend::getDeptId, bo.getDeptId());
lqw.gt(bo.getStartTime() != null, XzdMachineryContractSuspend::getCreateTime, bo.getStartTime());
lqw.lt(bo.getEndTime() != null, XzdMachineryContractSuspend::getCreateTime, bo.getEndTime());
return lqw;
}