Merge remote-tracking branch 'origin/main'

This commit is contained in:
z 2025-10-09 22:20:38 +08:00
commit 630c2dec38
5 changed files with 253 additions and 127 deletions

View File

@ -60,7 +60,7 @@ public interface PlanSubMapper extends BaseMapperX<PlanSubDO> {
.leftJoin(ProjectOrderSubDO.class, "c", ProjectOrderSubDO::getId, PlanSubDO::getProjectSubId) .leftJoin(ProjectOrderSubDO.class, "c", ProjectOrderSubDO::getId, PlanSubDO::getProjectSubId)
.eq(ProjectOrderDO::getDeliveryStatus,1) .eq(ProjectOrderDO::getDeliveryStatus,1)
.disableSubLogicDel() .disableSubLogicDel()
.orderByAsc(PlanSubDO::getId) .orderByDesc(PlanSubDO::getId)
; ;
query.like(ObjectUtil.isNotEmpty(reqVO.getProjectCode()), PlanDO::getCode, reqVO.getProjectCode()) query.like(ObjectUtil.isNotEmpty(reqVO.getProjectCode()), PlanDO::getCode, reqVO.getProjectCode())
.like(ObjectUtil.isNotEmpty(reqVO.getProjectSubName()), PlanSubDetailDO::getName, reqVO.getProjectSubName()); .like(ObjectUtil.isNotEmpty(reqVO.getProjectSubName()), PlanSubDetailDO::getName, reqVO.getProjectSubName());

View File

@ -219,16 +219,16 @@ public class PlanSubServiceImpl implements PlanSubService {
for (PlanSubSaveReqVO newTask : processTasks) { for (PlanSubSaveReqVO newTask : processTasks) {
// 检查毛坯任务 // 检查毛坯任务
if (!newTask.isHasSaveInBlankDetail() && newTask.getBlankOwner() != null){ if (!newTask.isHasSaveInBlankDetail() && newTask.getBlankOwner() != null){
checkTaskAgainstExisting(Long.valueOf(newTask.getBlankOwner()), newTask.getStartBlankDate(), newTask.getBlankDate(), "BLUEPRINT_WORKBLANK", tasksByOwner); checkTaskAgainstExisting(newTask.getProjectNameSim(),Long.valueOf(newTask.getBlankOwner()), newTask.getStartBlankDate(), newTask.getBlankDate(), "BLUEPRINT_WORKBLANK", tasksByOwner);
} }
// 检查2D任务 // 检查2D任务
if (!newTask.isHasSaveIn2DDetail() && newTask.getTwoDimOwner() != null){ if (!newTask.isHasSaveIn2DDetail() && newTask.getTwoDimOwner() != null){
checkTaskAgainstExisting(Long.valueOf(newTask.getTwoDimOwner()), newTask.getStartTwoDimDate(), newTask.getTwoDimDate(), "BLUEPRINT_2D", tasksByOwner); checkTaskAgainstExisting(newTask.getProjectNameSim(),Long.valueOf(newTask.getTwoDimOwner()), newTask.getStartTwoDimDate(), newTask.getTwoDimDate(), "BLUEPRINT_2D", tasksByOwner);
} }
// 检查3D任务 // 检查3D任务
if (!newTask.isHasSaveIn3DDetail() && newTask.getThreeDimOwner() != null){ if (!newTask.isHasSaveIn3DDetail() && newTask.getThreeDimOwner() != null){
checkTaskAgainstExisting(Long.valueOf(newTask.getThreeDimOwner()), newTask.getStartThreeDimDate(), newTask.getThreeDimDate(), "BLUEPRINT_3D", tasksByOwner); checkTaskAgainstExisting(newTask.getProjectNameSim(),Long.valueOf(newTask.getThreeDimOwner()), newTask.getStartThreeDimDate(), newTask.getThreeDimDate(), "BLUEPRINT_3D", tasksByOwner);
} }
} }
@ -237,7 +237,7 @@ public class PlanSubServiceImpl implements PlanSubService {
/** /**
* 辅助方法检查单个新任务与已存在任务的冲突 * 辅助方法检查单个新任务与已存在任务的冲突
*/ */
private void checkTaskAgainstExisting(Long owner, LocalDateTime start, LocalDateTime end, String taskType, Map<Long, List<PlanSubDetailDO>> tasksByOwner) { private void checkTaskAgainstExisting(String name,Long owner, LocalDateTime start, LocalDateTime end, String taskType, Map<Long, List<PlanSubDetailDO>> tasksByOwner) {
if (owner == null || start == null || end == null) { if (owner == null || start == null || end == null) {
return; // 如果责任人或时间为空则无需检查 return; // 如果责任人或时间为空则无需检查
} }
@ -256,7 +256,7 @@ public class PlanSubServiceImpl implements PlanSubService {
} }
for (PlanSubDetailDO existingTask : existingTasksForOwner) { for (PlanSubDetailDO existingTask : existingTasksForOwner) {
if (hasOverlap(start, end, existingTask.getStartTwoDimDate(), existingTask.getTwoDimDate())) { if (hasOverlap(start, end, existingTask.getStartTwoDimDate(), existingTask.getTwoDimDate())) {
throw exception(new ErrorCode(1_007_006,"当前插入"+start.toString().substring(0,10)+" -"+end.toString().substring(0,10)+""+existingTask.getName()+"-"+typeName+existingTask.getStartTwoDimDate().toString().substring(0,10)+existingTask.getTwoDimDate().toString().substring(0,10)+"存在交集,请确认!")); throw exception(new ErrorCode(1_007_006,"当前插入:"+name+" "+start.toString().substring(0,10)+" -"+end.toString().substring(0,10)+""+existingTask.getName()+"-"+typeName+existingTask.getStartTwoDimDate().toString().substring(0,10)+existingTask.getTwoDimDate().toString().substring(0,10)+"存在交集,请确认!"));
} }
} }
} }

View File

@ -293,6 +293,7 @@ public class PlanSubDetailServiceImpl implements PlanSubDetailService {
} }
@Override @Override
@Transactional
public CommonResult modification(PlanSubDetailSaveReqVO updateReqVO) { public CommonResult modification(PlanSubDetailSaveReqVO updateReqVO) {
LambdaQueryWrapper<PlanSubDetailDO> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<PlanSubDetailDO> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(PlanSubDetailDO::getProjectSubId,updateReqVO.getProjectSubId()); wrapper.eq(PlanSubDetailDO::getProjectSubId,updateReqVO.getProjectSubId());
@ -300,8 +301,9 @@ public class PlanSubDetailServiceImpl implements PlanSubDetailService {
wrapper.gt(PlanSubDetailDO::getSeqNo,updateReqVO.getSeqNo()); wrapper.gt(PlanSubDetailDO::getSeqNo,updateReqVO.getSeqNo());
if (planSubDetailMapper.selectCount(wrapper)>0) return CommonResult.error(400,"该子项目存在多时间段派工,不允许从中间修改!"); if (planSubDetailMapper.selectCount(wrapper)>0) return CommonResult.error(400,"该子项目存在多时间段派工,不允许从中间修改!");
LambdaQueryWrapper<PlanSubDetailDO> queryWrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<PlanSubDetailDO> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(PlanSubDetailDO::getProjectSubId,updateReqVO.getProjectSubId()); // queryWrapper.eq(PlanSubDetailDO::getProjectSubId,updateReqVO.getProjectSubId());
queryWrapper.eq(PlanSubDetailDO::getSubType,updateReqVO.getSubType()); queryWrapper.eq(PlanSubDetailDO::getTwoDimOwner,updateReqVO.getTwoDimOwner());
// queryWrapper.eq(PlanSubDetailDO::getSubType,updateReqVO.getSubType());
if (ObjectUtil.isNotEmpty(updateReqVO.getId())){ if (ObjectUtil.isNotEmpty(updateReqVO.getId())){
queryWrapper.ne(PlanSubDetailDO::getId,updateReqVO.getId()); queryWrapper.ne(PlanSubDetailDO::getId,updateReqVO.getId());
} }
@ -344,40 +346,96 @@ public class PlanSubDetailServiceImpl implements PlanSubDetailService {
// } // }
List<PlanSubDetailDO> list = planSubDetailMapper.selectList(lambdaQueryWrapper); List<PlanSubDetailDO> list = planSubDetailMapper.selectList(lambdaQueryWrapper);
List<PlanSubDetailDO> noSelfList = new ArrayList<>(); List<PlanSubDetailDO> noSelfList = new ArrayList<>();
// if (CollUtil.isNotEmpty(list) && list.size() == 1){ for (PlanSubDetailDO planSubDetailDO : list) {
// return CommonResult.error(400,"请修改数据后再点击修改"); if (!planSubDetailDO.getId().equals(updateReqVO.getId())){
// noSelfList.add(planSubDetailDO);
// } }
// for (PlanSubDetailDO planSubDetailDO : list) { }
// if (!planSubDetailDO.getId().equals(updateReqVO.getId())){ boolean change = false;
// noSelfList.add(planSubDetailDO); if (CollUtil.isNotEmpty(list)){
// } if (list.size() == 1){
// } PlanSubDetailDO planSubDetailDO = list.get(0);
// if (ObjectUtil.isEmpty( noSelfList) && ((updateReqVO.getStartTwoDimDate().compareTo(noSelfList.get(0).getTwoDimDate()) <=0 )&& (updateReqVO.getTwoDimDate().compareTo(noSelfList.get(0).getStartTwoDimDate()) >= 0))){ if (planSubDetailDO.getId().equals(updateReqVO.getId())){
// if (ObjectUtil.isNotEmpty(updateReqVO.getId())){ if (updateReqVO.getStartTwoDimDate().compareTo(planSubDetailDO.getStartTwoDimDate()) == 0 || updateReqVO.getTwoDimDate().compareTo(planSubDetailDO.getTwoDimDate()) == 0){
// planSubDetailMapper.delete(PlanSubDetailDO::getId,updateReqVO.getId()); change = true;
// } }
// PlanSubDetailDO planSubDetailDO = new PlanSubDetailDO(); }
// planSubDetailDO.setProjectPlanId(updateReqVO.getProjectPlanId()); }
// planSubDetailDO.setProjectId(updateReqVO.getProjectId()); }
// planSubDetailDO.setProjectSubId(updateReqVO.getProjectSubId()); if (change || ObjectUtil.isEmpty(list) || (list.get(0).getStartTwoDimDate().compareTo(updateReqVO.getTwoDimDate()) > 0 )){
// planSubDetailDO.setProjectSubCode(updateReqVO.getProjectSubCode()); List<PlanSubDetailDO> newList = new ArrayList<>();
// planSubDetailDO.setTwoDimDate(updateReqVO.getTwoDimDate()); newList.addAll(list);
// planSubDetailDO.setTwoDimOwner(updateReqVO.getTwoDimOwner()); if (ObjectUtil.isNotEmpty(updateReqVO.getId())){
// planSubDetailDO.setStartTwoDimDate(updateReqVO.getStartTwoDimDate()); newList.clear();
// planSubDetailDO.setSubType(updateReqVO.getSubType()); planSubDetailMapper.delete(PlanSubDetailDO::getId,updateReqVO.getId());
// planSubDetailDO.setIsOverProcess(0); for (PlanSubDetailDO planSubDetailDO : list) {
// planSubDetailDO.setSeqNo(1L); if (!planSubDetailDO.getId().equals(updateReqVO.getId())){
// planSubDetailDO.setDesignNum(updateReqVO.getDesignNum()); newList.add(planSubDetailDO);
// planSubDetailDO.setCode(updateReqVO.getCode()); }
// list.add(planSubDetailDO); }
// list.sort(Comparator.comparing(PlanSubDetailDO::getStartTwoDimDate, Comparator.nullsLast(Comparator.naturalOrder()))); }
// for (int i = 0; i < list.size(); i++) { PlanSubDetailDO planSubDetailDO = new PlanSubDetailDO();
// list.get(i).setSeqNo(Long.valueOf(i + 1)); // 设置顺序为 1, 2, 3 planSubDetailDO.setProjectPlanId(updateReqVO.getProjectPlanId());
// } planSubDetailDO.setProjectId(updateReqVO.getProjectId());
// planSubDetailMapper.insertOrUpdateBatch(list); planSubDetailDO.setProjectSubId(updateReqVO.getProjectSubId());
// return CommonResult.success(true); planSubDetailDO.setProjectSubCode(updateReqVO.getProjectSubCode());
// } planSubDetailDO.setTwoDimDate(updateReqVO.getTwoDimDate());
planSubDetailDO.setTwoDimOwner(updateReqVO.getTwoDimOwner());
planSubDetailDO.setStartTwoDimDate(updateReqVO.getStartTwoDimDate());
planSubDetailDO.setSubType(updateReqVO.getSubType());
planSubDetailDO.setName(updateReqVO.getName());
planSubDetailDO.setProjectPlanSubId(updateReqVO.getProjectPlanSubId());
planSubDetailDO.setIsOverProcess(0);
planSubDetailDO.setSeqNo(1L);
planSubDetailDO.setDesignNum(updateReqVO.getDesignNum());
planSubDetailDO.setCode(updateReqVO.getCode());
newList.add(planSubDetailDO);
newList.sort(Comparator.comparing(PlanSubDetailDO::getStartTwoDimDate, Comparator.nullsLast(Comparator.naturalOrder())));
for (int i = 0; i < newList.size(); i++) {
newList.get(i).setSeqNo(Long.valueOf(i + 1)); // 设置顺序为 1, 2, 3
}
planSubDetailMapper.insertOrUpdateBatch(newList);
Map<Long, List<PlanSubDetailDO>> collect = newList.stream().collect(Collectors.groupingBy(PlanSubDetailDO::getProjectSubId));
for (Map.Entry<Long, List<PlanSubDetailDO>> entry : collect.entrySet()) {
Long subId = entry.getKey();
List<PlanSubDetailDO> subList = entry.getValue();
//再根据设计类型来
Map<String, List<PlanSubDetailDO>> collect1 = subList.stream().collect(Collectors.groupingBy(PlanSubDetailDO::getSubType));
for (Map.Entry<String, List<PlanSubDetailDO>> entry1 : collect1.entrySet()) {
String type = entry1.getKey();
List<PlanSubDetailDO> subTypeList = entry1.getValue();
List<PlanSubDetailDO> sortedList = subTypeList.stream()
.sorted(Comparator.comparing(PlanSubDetailDO::getSeqNo).reversed())
.collect(Collectors.toList());
Long num = 0L;
for (PlanSubDetailDO planSubDetailDO1 : sortedList) {
Long designNum = planSubDetailDO1.getDesignNum();
num += designNum;
}
LambdaUpdateWrapper<PlanSubDO> lambdaUpdateWrapper1 = new LambdaUpdateWrapper<>();
lambdaUpdateWrapper1.eq(PlanSubDO::getProjectSubId,subId);
LocalDateTime startTwoDimDate = sortedList.get(subTypeList.size()-1).getStartTwoDimDate();
LocalDateTime twoDimDate = sortedList.get(0).getTwoDimDate();
//取最大值就是第一个
if ("BLUEPRINT_WORKBLANK".equals(type)){
lambdaUpdateWrapper1.set(PlanSubDO::getStartBlankDate,startTwoDimDate);
lambdaUpdateWrapper1.set(PlanSubDO::getBlankDate,twoDimDate);
lambdaUpdateWrapper1.set(PlanSubDO::getBlankNum,num);
}else if ("BLUEPRINT_2D".equals(type)){
lambdaUpdateWrapper1.set(PlanSubDO::getStartTwoDimDate,startTwoDimDate);
lambdaUpdateWrapper1.set(PlanSubDO::getTwoDimDate,twoDimDate);
lambdaUpdateWrapper1.set(PlanSubDO::getTwoDimNum,num);
}else {
lambdaUpdateWrapper1.set(PlanSubDO::getStartThreeDimDate,startTwoDimDate);
lambdaUpdateWrapper1.set(PlanSubDO::getThreeDimDate,twoDimDate);
lambdaUpdateWrapper1.set(PlanSubDO::getThreeDimNum,num);
}
planSubMapper.update(lambdaUpdateWrapper1);
}
}
return CommonResult.success(true);
}
updateReqVO.setList( list); updateReqVO.setList( list);
return CommonResult.success(updateReqVO); return CommonResult.success(updateReqVO);
} }
@ -1006,18 +1064,14 @@ public class PlanSubDetailServiceImpl implements PlanSubDetailService {
return CommonResult.success(updateReqVO); return CommonResult.success(updateReqVO);
} }
/**
* 执行插活逻辑
*/
private List<PlanSubDetailDO> performInsertLogic(List<PlanSubDetailDO> baseList, private List<PlanSubDetailDO> performInsertLogic(List<PlanSubDetailDO> baseList,
List<PlanSubDetailDO> insertList, List<PlanSubDetailDO> insertList,
List<LocalDateTime> holidayList) { List<LocalDateTime> holidayList) {
List<PlanSubDetailDO> resultList = new ArrayList<>(); List<PlanSubDetailDO> resultList = new ArrayList<>();
// 1. 先处理插活数据不按节假日分段保持原始范围 // 1. 先处理插活数据保持原始时间范围但designNum排除节假日
List<PlanSubDetailDO> processedInsertList = new ArrayList<>(); List<PlanSubDetailDO> processedInsertList = new ArrayList<>();
for (PlanSubDetailDO insertItem : insertList) { for (PlanSubDetailDO insertItem : insertList) {
// 插活数据保持原始时间范围但designNum排除节假日
PlanSubDetailDO processedItem = new PlanSubDetailDO(); PlanSubDetailDO processedItem = new PlanSubDetailDO();
// 复制属性 // 复制属性
processedItem.setId(null); processedItem.setId(null);
@ -1045,26 +1099,25 @@ public class PlanSubDetailServiceImpl implements PlanSubDetailService {
// 3. 处理baseList为空的情况 // 3. 处理baseList为空的情况
if (CollUtil.isEmpty(baseList)) { if (CollUtil.isEmpty(baseList)) {
// baseList为空直接返回插活数据
return new ArrayList<>(processedInsertList); return new ArrayList<>(processedInsertList);
} }
// 4. 获取插活数据的时间范围 // 4. 获取插活数据的时间范围
LocalDateTime insertStartTime = processedInsertList.stream() final LocalDateTime insertStartTime = processedInsertList.stream()
.map(PlanSubDetailDO::getStartTwoDimDate) .map(PlanSubDetailDO::getStartTwoDimDate)
.min(LocalDateTime::compareTo) .min(LocalDateTime::compareTo)
.orElse(null); .orElse(null);
LocalDateTime insertEndTime = processedInsertList.stream() final LocalDateTime insertEndTime = processedInsertList.stream()
.map(PlanSubDetailDO::getTwoDimDate) .map(PlanSubDetailDO::getTwoDimDate)
.max(LocalDateTime::compareTo) .max(LocalDateTime::compareTo)
.orElse(null); .orElse(null);
// 5. 获取baseList的时间范围 // 5. 获取baseList的时间范围
LocalDateTime baseMinStartTime = baseList.stream() final LocalDateTime baseMinStartTime = baseList.stream()
.map(PlanSubDetailDO::getStartTwoDimDate) .map(PlanSubDetailDO::getStartTwoDimDate)
.min(LocalDateTime::compareTo) .min(LocalDateTime::compareTo)
.orElse(null); .orElse(null);
LocalDateTime baseMaxEndTime = baseList.stream() final LocalDateTime baseMaxEndTime = baseList.stream()
.map(PlanSubDetailDO::getTwoDimDate) .map(PlanSubDetailDO::getTwoDimDate)
.max(LocalDateTime::compareTo) .max(LocalDateTime::compareTo)
.orElse(null); .orElse(null);
@ -1084,14 +1137,72 @@ public class PlanSubDetailServiceImpl implements PlanSubDetailService {
return resultList; return resultList;
} }
// 7. 正常插活逻辑插活数据与baseList有重叠 // 7. 检查是否有插活数据紧挨着某个baseItem的结束时间
PlanSubDetailDO mergedBaseItem = null;
List<PlanSubDetailDO> remainingInsertList = new ArrayList<>();
for (PlanSubDetailDO insertItem : processedInsertList) {
boolean merged = false;
for (PlanSubDetailDO baseItem : baseList) {
LocalDateTime nextDay = baseItem.getTwoDimDate().plusDays(1);
if (insertItem.getStartTwoDimDate().isEqual(nextDay)) {
// 插活数据紧挨着baseItem的结束时间需要合并
mergedBaseItem = new PlanSubDetailDO();
// 复制baseItem的属性
mergedBaseItem.setId(baseItem.getId());
mergedBaseItem.setProjectPlanId(baseItem.getProjectPlanId());
mergedBaseItem.setProjectId(baseItem.getProjectId());
mergedBaseItem.setProjectPlanSubId(baseItem.getProjectPlanSubId());
mergedBaseItem.setProjectSubCode(baseItem.getProjectSubCode());
mergedBaseItem.setTwoDimOwner(baseItem.getTwoDimOwner());
mergedBaseItem.setProjectSubId(baseItem.getProjectSubId());
mergedBaseItem.setSubType(baseItem.getSubType());
mergedBaseItem.setName(baseItem.getName());
mergedBaseItem.setCode(baseItem.getCode());
// 合并时间范围
mergedBaseItem.setStartTwoDimDate(baseItem.getStartTwoDimDate());
mergedBaseItem.setTwoDimDate(insertItem.getTwoDimDate());
// 重新计算designNum排除节假日
mergedBaseItem.setDesignNum(calculateWorkDaysExcludeHolidays(
baseItem.getStartTwoDimDate(),
insertItem.getTwoDimDate(),
holidayList
));
merged = true;
break;
}
}
if (!merged) {
remainingInsertList.add(insertItem);
}
}
// 8. 如果有合并的情况重新构建baseList
List<PlanSubDetailDO> newBaseList = new ArrayList<>();
if (mergedBaseItem != null) {
// 添加合并后的item
newBaseList.add(mergedBaseItem);
// 添加其他未被合并的baseItem
for (PlanSubDetailDO baseItem : baseList) {
if (!baseItem.getStartTwoDimDate().isEqual(mergedBaseItem.getStartTwoDimDate()) ||
!baseItem.getTwoDimDate().isEqual(mergedBaseItem.getTwoDimDate())) {
newBaseList.add(baseItem);
}
}
// 重新排序
newBaseList.sort(Comparator.comparing(PlanSubDetailDO::getStartTwoDimDate));
} else {
newBaseList.addAll(baseList);
}
// 9. 正常插活逻辑插活数据与baseList有重叠
// 分离baseList在插活数据之前的被打断的在插活数据之后的 // 分离baseList在插活数据之前的被打断的在插活数据之后的
List<PlanSubDetailDO> beforeInsertList = new ArrayList<>(); List<PlanSubDetailDO> beforeInsertList = new ArrayList<>();
List<PlanSubDetailDO> interruptedList = new ArrayList<>(); List<PlanSubDetailDO> interruptedList = new ArrayList<>();
List<PlanSubDetailDO> afterInsertList = new ArrayList<>(); List<PlanSubDetailDO> afterInsertList = new ArrayList<>();
if (insertStartTime != null) { if (insertStartTime != null) {
for (PlanSubDetailDO baseItem : baseList) { for (PlanSubDetailDO baseItem : newBaseList) {
if (baseItem.getTwoDimDate().isBefore(insertStartTime)) { if (baseItem.getTwoDimDate().isBefore(insertStartTime)) {
// 完全在插活数据之前 // 完全在插活数据之前
beforeInsertList.add(baseItem); beforeInsertList.add(baseItem);
@ -1105,13 +1216,13 @@ public class PlanSubDetailServiceImpl implements PlanSubDetailService {
} }
} }
} else { } else {
beforeInsertList.addAll(baseList); beforeInsertList.addAll(newBaseList);
} }
// 8. 处理插活数据之前的baseList保持原样 // 10. 处理插活数据之前的baseList保持原样
resultList.addAll(beforeInsertList); resultList.addAll(beforeInsertList);
// 9. 处理被打断的baseList // 11. 处理被打断的baseList
List<PlanSubDetailDO> remainingBaseList = new ArrayList<>(); List<PlanSubDetailDO> remainingBaseList = new ArrayList<>();
for (PlanSubDetailDO interruptedItem : interruptedList) { for (PlanSubDetailDO interruptedItem : interruptedList) {
// 计算插活数据开始前的天数包含节假日 // 计算插活数据开始前的天数包含节假日
@ -1125,72 +1236,73 @@ public class PlanSubDetailServiceImpl implements PlanSubDetailService {
beforeSegment.setDesignNum(calculateWorkDaysExcludeHolidays(interruptedItem.getStartTwoDimDate(), segmentEnd, holidayList)); beforeSegment.setDesignNum(calculateWorkDaysExcludeHolidays(interruptedItem.getStartTwoDimDate(), segmentEnd, holidayList));
resultList.add(beforeSegment); resultList.add(beforeSegment);
// 保存剩余的designNum原始designNum减去已使用的 // 剩余部分保持原始designNum稍后处理
Long usedDesignNum = calculateWorkDaysExcludeHolidays(interruptedItem.getStartTwoDimDate(), segmentEnd, holidayList); PlanSubDetailDO remainingItem = new PlanSubDetailDO();
Long remainingDesignNum = interruptedItem.getDesignNum() - usedDesignNum; // 复制属性
if (remainingDesignNum > 0) { remainingItem.setId(interruptedItem.getId());
// 创建剩余的baseItem稍后处理 remainingItem.setProjectPlanId(interruptedItem.getProjectPlanId());
PlanSubDetailDO remainingItem = new PlanSubDetailDO(); remainingItem.setProjectId(interruptedItem.getProjectId());
// 复制属性 remainingItem.setProjectPlanSubId(interruptedItem.getProjectPlanSubId());
remainingItem.setId(interruptedItem.getId()); remainingItem.setProjectSubCode(interruptedItem.getProjectSubCode());
remainingItem.setProjectPlanId(interruptedItem.getProjectPlanId()); remainingItem.setTwoDimOwner(interruptedItem.getTwoDimOwner());
remainingItem.setProjectId(interruptedItem.getProjectId()); remainingItem.setProjectSubId(interruptedItem.getProjectPlanSubId());
remainingItem.setProjectPlanSubId(interruptedItem.getProjectPlanSubId()); remainingItem.setSubType(interruptedItem.getSubType());
remainingItem.setProjectSubCode(interruptedItem.getProjectSubCode()); remainingItem.setName(interruptedItem.getName());
remainingItem.setTwoDimOwner(interruptedItem.getTwoDimOwner()); remainingItem.setCode(interruptedItem.getCode());
remainingItem.setProjectSubId(interruptedItem.getProjectPlanSubId()); remainingItem.setDesignNum(interruptedItem.getDesignNum()); // 保持原始designNum
remainingItem.setSubType(interruptedItem.getSubType()); remainingBaseList.add(remainingItem);
remainingItem.setName(interruptedItem.getName());
remainingItem.setCode(interruptedItem.getCode());
remainingItem.setDesignNum(remainingDesignNum);
remainingBaseList.add(remainingItem);
}
} else { } else {
// 整个被打断全部加入剩余列表 // 整个被打断全部加入剩余列表
remainingBaseList.add(interruptedItem); remainingBaseList.add(interruptedItem);
} }
} }
// 10. 添加插活数据 // 12. 添加剩余的插活数据未被合并的
resultList.addAll(processedInsertList); resultList.addAll(remainingInsertList);
// 11. 处理剩余的baseList被打断的剩余部分 + 原本在插活数据之后的 // 13. 处理剩余的baseList
List<PlanSubDetailDO> allRemainingList = new ArrayList<>(); if (!remainingBaseList.isEmpty() || !afterInsertList.isEmpty()) {
allRemainingList.addAll(remainingBaseList);
allRemainingList.addAll(afterInsertList);
if (!allRemainingList.isEmpty()) {
// 获取插活数据的最后结束时间 // 获取插活数据的最后结束时间
LocalDateTime lastInsertEndTime = processedInsertList.stream() final LocalDateTime lastInsertEndTime;
.map(PlanSubDetailDO::getTwoDimDate) if (mergedBaseItem != null) {
.max(LocalDateTime::compareTo) lastInsertEndTime = mergedBaseItem.getTwoDimDate();
.orElse(null); } else {
lastInsertEndTime = processedInsertList.stream()
.map(PlanSubDetailDO::getTwoDimDate)
.max(LocalDateTime::compareTo)
.orElse(null);
}
// 从插活数据的下一天开始顺延 // 处理被打断的剩余部分
LocalDateTime baseStartTime = lastInsertEndTime.plusDays(1); for (PlanSubDetailDO baseItem : remainingBaseList) {
// 从插活数据的下一天开始计算
for (PlanSubDetailDO baseItem : allRemainingList) { LocalDateTime newStartTime = lastInsertEndTime.plusDays(1);
// 按照原有的designNum计算新的时间段排除节假日 // 如果遇到节假日继续跳过
LocalDateTime newStartTime = findNextNonHoliday(baseStartTime, holidayList); newStartTime = findNextNonHoliday(newStartTime, holidayList);
LocalDateTime newEndTime = calculateEndDateByWorkDays(newStartTime, baseItem.getDesignNum(), holidayList); LocalDateTime newEndTime = calculateEndDateByWorkDays(newStartTime, baseItem.getDesignNum(), holidayList);
// 创建新的baseItem
PlanSubDetailDO newBaseItem = createBaseItem(baseItem, newStartTime, newEndTime); PlanSubDetailDO newBaseItem = createBaseItem(baseItem, newStartTime, newEndTime);
newBaseItem.setDesignNum(baseItem.getDesignNum()); // 保持原始designNum newBaseItem.setDesignNum(baseItem.getDesignNum()); // 保持原始designNum
resultList.add(newBaseItem); resultList.add(newBaseItem);
// 更新下一个baseItem的开始时间
baseStartTime = newEndTime.plusDays(1);
} }
// 处理原本在插活数据之后的baseList保持原样
resultList.addAll(afterInsertList);
} }
// 12. 按开始时间排序 // 14. 按开始时间排序
resultList.sort(Comparator.comparing(PlanSubDetailDO::getStartTwoDimDate)); resultList.sort(Comparator.comparing(PlanSubDetailDO::getStartTwoDimDate));
return resultList; return resultList;
} }
private LocalDateTime findNextNonHoliday(LocalDateTime startDate, List<LocalDateTime> holidayList) {
LocalDateTime current = startDate;
while (holidayList.contains(current)) {
current = current.plusDays(1);
}
return current;
}
/** /**
* 计算排除节假日的工作天数 * 计算排除节假日的工作天数
*/ */
@ -1239,25 +1351,6 @@ public class PlanSubDetailServiceImpl implements PlanSubDetailService {
return current; return current;
} }
/**
* 找到下一个非节假日日期
*/
private LocalDateTime findNextNonHoliday(LocalDateTime startDate, List<LocalDateTime> holidayList) {
LocalDateTime current = startDate;
while (true) {
LocalDateTime finalCurrent = current;
boolean isHoliday = holidayList.stream()
.anyMatch(holiday -> holiday.isEqual(finalCurrent));
if (!isHoliday) {
return current;
}
current = current.plusDays(1);
}
}
/** /**
* 创建baseItem对象用于baseList顺延 * 创建baseItem对象用于baseList顺延
*/ */
@ -1279,6 +1372,18 @@ public class PlanSubDetailServiceImpl implements PlanSubDetailService {
return baseItem; return baseItem;
} }
/**
* 获取时间段内的节假日
*/
private List<LocalDateTime> getHolidaysInRange(LocalDateTime startDate, LocalDateTime endDate,
List<LocalDateTime> holidayList) {
return holidayList.stream()
.filter(holiday -> !holiday.isBefore(startDate) && !holiday.isAfter(endDate))
.sorted()
.collect(Collectors.toList());
}
@Override @Override

View File

@ -371,7 +371,7 @@ import * as PlansubdetailApi from '@/api/heli/plansubdetail'
import { DICT_TYPE, getIntDictOptions, getStrDictOptions } from '@/utils/dict' import { DICT_TYPE, getIntDictOptions, getStrDictOptions } from '@/utils/dict'
import { ref, reactive, onMounted } from 'vue' // onMounted import { ref, reactive, onMounted } from 'vue' // onMounted
import * as UserApi from '@/api/system/user' import * as UserApi from '@/api/system/user'
import routeParamsCache from '@/utils/routeParamsCache';
import * as PlanSubApi from '@/api/heli/plansub' import * as PlanSubApi from '@/api/heli/plansub'
import { formatDate } from '@/utils/formatTime' import { formatDate } from '@/utils/formatTime'
import * as shopCalendarApi from '@/api/heli/shopCalendar' import * as shopCalendarApi from '@/api/heli/shopCalendar'
@ -466,7 +466,7 @@ const handleSelectionChange = (val) => {
// //
const addForm = () => { const addForm = () => {
resetAddForm() resetAddForm()
getAddList() // getAddList()
addDialogVisible.value = true addDialogVisible.value = true
} }
@ -537,7 +537,7 @@ const handleAddConfirm = () => {
selectedAddRow.value[0].flag = 1 selectedAddRow.value[0].flag = 1
selectedAddRow.value[0].userFlag = true selectedAddRow.value[0].userFlag = true
selectedAddRow.value[0].id = null selectedAddRow.value[0].id = null
list.value.push(selectedAddRow.value[0]) list.value.unshift(selectedAddRow.value[0])
addDialogVisible.value = false addDialogVisible.value = false
message.success('项目添加成功') message.success('项目添加成功')
} }
@ -637,7 +637,8 @@ const modification = async (row) => {
dialogVisible.value = true dialogVisible.value = true
dialogTitle.value = '插活前' dialogTitle.value = '插活前'
} else { } else {
message.success('成功') await getList()
message.success('修改成功')
} }
} }
@ -652,7 +653,7 @@ const addItemRow = (row) => {
item.isOverProcess = 0 item.isOverProcess = 0
} }
if (!item.id) { if (!item.id) {
console.log(item)
var type = var type =
'BLUEPRINT_WORKBLANK' == item.subType 'BLUEPRINT_WORKBLANK' == item.subType
? '毛坯' ? '毛坯'
@ -879,12 +880,19 @@ const resetQuery = () => {
}) })
// getList() // getList()
} }
const route = useRoute()
const routeValue = ref('')
/** 初始化 **/ /** 初始化 **/
onMounted(async () => { onMounted(async () => {
try { try {
// //
userInit.value = await UserApi.getDeptName('设计部') userInit.value = await UserApi.getDeptName('设计部')
let params = routeParamsCache.get(route.path);
routeValue.value = route.path
if (params ) {
Object.assign(queryParams, params);
}
routeValue.value = route.path
// await getList() // await getList()
} catch (error) { } catch (error) {
console.error('初始化失败:', error) console.error('初始化失败:', error)
@ -893,6 +901,19 @@ onMounted(async () => {
}, 100) }, 100)
} }
}) })
onBeforeUnmount(() => {
console.log(route.path)
const plainParams = JSON.parse(JSON.stringify(queryParams));
routeParamsCache.set(routeValue.value, plainParams);
});
window.addEventListener('beforeunload', () => {
const plainParams = JSON.parse(JSON.stringify(queryParams));
routeParamsCache.set(routeValue.value, plainParams);
});
</script> </script>
<style scoped> <style scoped>
.dialog-content { .dialog-content {

View File

@ -2407,11 +2407,11 @@ const submitForm = async () => {
// } // }
// //subData.id = subData.projectSubId // //subData.id = subData.projectSubId
// }) // })
reload()
message.success(t('common.updateSuccess')) message.success(t('common.updateSuccess'))
// //
// emit('success') // emit('success')
} finally { } finally {
reload()
formLoading.value = false formLoading.value = false
} }
} }