diff --git a/mes-module-heli/mes-module-heli-biz/src/main/java/com/chanko/yunxi/mes/module/heli/controller/admin/plansub/PlanSubController.java b/mes-module-heli/mes-module-heli-biz/src/main/java/com/chanko/yunxi/mes/module/heli/controller/admin/plansub/PlanSubController.java index 97a1d278..4196b605 100644 --- a/mes-module-heli/mes-module-heli-biz/src/main/java/com/chanko/yunxi/mes/module/heli/controller/admin/plansub/PlanSubController.java +++ b/mes-module-heli/mes-module-heli-biz/src/main/java/com/chanko/yunxi/mes/module/heli/controller/admin/plansub/PlanSubController.java @@ -97,8 +97,8 @@ public class PlanSubController { @PostMapping("/operate") @Operation(summary = "创建生产计划子项目") @PreAuthorize("@ss.hasPermission('heli:plan-sub:create')") - public void operate(@RequestBody List list) { - planSubService.operate(list); + public CommonResult operate(@RequestBody List list) { + return planSubService.operate(list); } @PutMapping("/update") @Operation(summary = "更新生产计划子项目") diff --git a/mes-module-heli/mes-module-heli-biz/src/main/java/com/chanko/yunxi/mes/module/heli/service/plansub/PlanSubService.java b/mes-module-heli/mes-module-heli-biz/src/main/java/com/chanko/yunxi/mes/module/heli/service/plansub/PlanSubService.java index 7a38156f..26718c5d 100644 --- a/mes-module-heli/mes-module-heli-biz/src/main/java/com/chanko/yunxi/mes/module/heli/service/plansub/PlanSubService.java +++ b/mes-module-heli/mes-module-heli-biz/src/main/java/com/chanko/yunxi/mes/module/heli/service/plansub/PlanSubService.java @@ -2,6 +2,8 @@ package com.chanko.yunxi.mes.module.heli.service.plansub; import java.util.*; import javax.validation.*; + +import com.chanko.yunxi.mes.framework.common.pojo.CommonResult; import com.chanko.yunxi.mes.module.heli.controller.admin.plansub.vo.*; import com.chanko.yunxi.mes.module.heli.dal.dataobject.plansub.PlanSubDO; import com.chanko.yunxi.mes.framework.common.pojo.PageResult; @@ -24,7 +26,7 @@ public interface PlanSubService { Long createPlanSub(@Valid PlanSubSaveReqVO createReqVO); - void operate(List list); + CommonResult operate(List list); /** * 更新生产计划子项目 * diff --git a/mes-module-heli/mes-module-heli-biz/src/main/java/com/chanko/yunxi/mes/module/heli/service/plansub/PlanSubServiceImpl.java b/mes-module-heli/mes-module-heli-biz/src/main/java/com/chanko/yunxi/mes/module/heli/service/plansub/PlanSubServiceImpl.java index 10715bec..bed9c584 100644 --- a/mes-module-heli/mes-module-heli-biz/src/main/java/com/chanko/yunxi/mes/module/heli/service/plansub/PlanSubServiceImpl.java +++ b/mes-module-heli/mes-module-heli-biz/src/main/java/com/chanko/yunxi/mes/module/heli/service/plansub/PlanSubServiceImpl.java @@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.chanko.yunxi.mes.framework.common.exception.ErrorCode; +import com.chanko.yunxi.mes.framework.common.pojo.CommonResult; import com.chanko.yunxi.mes.framework.mybatis.core.query.LambdaQueryWrapperX; import com.chanko.yunxi.mes.module.heli.controller.admin.shopCalendar.vo.ShopCalendarPageReqVO; import com.chanko.yunxi.mes.module.heli.dal.dataobject.plansubdetail.PlanSubDetailDO; @@ -66,7 +67,7 @@ public class PlanSubServiceImpl implements PlanSubService { } @Override - public void operate(List list) { + public CommonResult operate(List list) { HashSet userIds = new HashSet<>(); List inserList = new ArrayList<>(); for (PlanSubSaveReqVO planSubSaveReqVO : list) { @@ -156,6 +157,7 @@ public class PlanSubServiceImpl implements PlanSubService { planSubDetailMapper.insertOrUpdateBatch(details); } } + return CommonResult.success(true); } @@ -614,11 +616,14 @@ public class PlanSubServiceImpl implements PlanSubService { PageResult planSubDOPageResult = planSubMapper.selectPage(pageReqVO); List list = planSubDOPageResult.getList(); for (PlanSubDO planSubDO : list) { - List planSubDetailDOS1 = planSubDetailMapper.selectList(new LambdaQueryWrapperX().eq(PlanSubDetailDO::getProjectPlanSubId, planSubDO.getId()) + List planSubDetailDOS1 = planSubDetailMapper.selectList(new LambdaQueryWrapperX() + .eq(PlanSubDetailDO::getProjectSubId, planSubDO.getProjectSubId()) .eq(PlanSubDetailDO::getSubType,"BLUEPRINT_WORKBLANK")); - List planSubDetailDOS2 = planSubDetailMapper.selectList(new LambdaQueryWrapperX().eq(PlanSubDetailDO::getProjectPlanSubId, planSubDO.getId()) + List planSubDetailDOS2 = planSubDetailMapper.selectList(new LambdaQueryWrapperX() + .eq(PlanSubDetailDO::getProjectSubId, planSubDO.getProjectSubId()) .eq(PlanSubDetailDO::getSubType,"BLUEPRINT_2D")); - List planSubDetailDOS3 = planSubDetailMapper.selectList(new LambdaQueryWrapperX().eq(PlanSubDetailDO::getProjectPlanSubId, planSubDO.getId()) + List planSubDetailDOS3 = planSubDetailMapper.selectList(new LambdaQueryWrapperX() + .eq(PlanSubDetailDO::getProjectSubId, planSubDO.getProjectSubId()) .eq(PlanSubDetailDO::getSubType,"BLUEPRINT_3D")); if (CollUtil.isNotEmpty(planSubDetailDOS1)) { diff --git a/mes-module-heli/mes-module-heli-biz/src/main/java/com/chanko/yunxi/mes/module/heli/service/plansubdetail/PlanSubDetailServiceImpl.java b/mes-module-heli/mes-module-heli-biz/src/main/java/com/chanko/yunxi/mes/module/heli/service/plansubdetail/PlanSubDetailServiceImpl.java index 1ee9fd39..14e5a276 100644 --- a/mes-module-heli/mes-module-heli-biz/src/main/java/com/chanko/yunxi/mes/module/heli/service/plansubdetail/PlanSubDetailServiceImpl.java +++ b/mes-module-heli/mes-module-heli-biz/src/main/java/com/chanko/yunxi/mes/module/heli/service/plansubdetail/PlanSubDetailServiceImpl.java @@ -332,8 +332,20 @@ public class PlanSubDetailServiceImpl implements PlanSubDetailService { LambdaQueryWrapper wrapper1 = new LambdaQueryWrapper<>(); wrapper1.eq(PlanSubDetailDO::getProjectSubId,updateReqVO.getProjectSubId()); wrapper1.eq(PlanSubDetailDO::getSubType,updateReqVO.getSubType()); - String type="BLUEPRINT_WORKBLANK".equals(updateReqVO.getSubType())?"毛坯":"BLUEPRINT_2D".equals(updateReqVO.getSubType())?"2D":"3D"; - if (planSubDetailMapper.selectCount(wrapper1)> 0 ) return CommonResult.error(400,"该子项目"+updateReqVO.getName()+" 设计类型"+type+" 存在派工数据,请确认!"); + List planSubDetailDOS1 = planSubDetailMapper.selectList(wrapper1); + for (PlanSubDetailDO planSubDetailDO : planSubDetailDOS1) { + LocalDateTime reqStart = updateReqVO.getStartTwoDimDate(); + LocalDateTime reqEnd = updateReqVO.getTwoDimDate(); + LocalDateTime existStart = planSubDetailDO.getStartTwoDimDate(); + LocalDateTime existEnd = planSubDetailDO.getTwoDimDate(); + // 判断请求时间段是否与已有时间段有重叠 + boolean hasOverlap = !(reqEnd.compareTo(existStart) < 0) && !(reqStart.compareTo(existEnd) > 0); + if (hasOverlap) { + return CommonResult.error(400,"当前子项目,当前设计类型时间存在交集,请确认!"); + } + } + + // if (planSubDetailMapper.selectCount(wrapper1)> 0 ) return CommonResult.error(400,"该子项目"+updateReqVO.getName()+" 设计类型"+type+" 存在派工数据,请确认!"); } @@ -363,7 +375,7 @@ public class PlanSubDetailServiceImpl implements PlanSubDetailService { } } } - if (change || ObjectUtil.isEmpty(list) ||(CollUtil.isNotEmpty(noSelfList)&& (noSelfList.get(0).getStartTwoDimDate().compareTo(updateReqVO.getTwoDimDate()) > 0 ))){ + if (change || ObjectUtil.isEmpty(noSelfList) ||(noSelfList.get(0).getStartTwoDimDate().compareTo(updateReqVO.getTwoDimDate()) > 0 )){ List newList = new ArrayList<>(); newList.addAll(list); if (ObjectUtil.isNotEmpty(updateReqVO.getId())){ @@ -434,14 +446,17 @@ public class PlanSubDetailServiceImpl implements PlanSubDetailService { if ("BLUEPRINT_WORKBLANK".equals(type)){ lambdaUpdateWrapper1.set(PlanSubDO::getStartBlankDate,startTwoDimDate); lambdaUpdateWrapper1.set(PlanSubDO::getBlankDate,twoDimDate); + lambdaUpdateWrapper1.set(PlanSubDO::getBlankOwner,sortedList.get(0).getTwoDimOwner()); lambdaUpdateWrapper1.set(PlanSubDO::getBlankNum,num); }else if ("BLUEPRINT_2D".equals(type)){ lambdaUpdateWrapper1.set(PlanSubDO::getStartTwoDimDate,startTwoDimDate); lambdaUpdateWrapper1.set(PlanSubDO::getTwoDimDate,twoDimDate); + lambdaUpdateWrapper1.set(PlanSubDO::getTwoDimOwner,sortedList.get(0).getTwoDimOwner()); lambdaUpdateWrapper1.set(PlanSubDO::getTwoDimNum,num); }else { lambdaUpdateWrapper1.set(PlanSubDO::getStartThreeDimDate,startTwoDimDate); lambdaUpdateWrapper1.set(PlanSubDO::getThreeDimDate,twoDimDate); + lambdaUpdateWrapper1.set(PlanSubDO::getThreeDimOwner,sortedList.get(0).getTwoDimOwner()); lambdaUpdateWrapper1.set(PlanSubDO::getThreeDimNum,num); } planSubMapper.update(lambdaUpdateWrapper1); @@ -569,22 +584,25 @@ public class PlanSubDetailServiceImpl implements PlanSubDetailService { } } } - Map> collect1 = list.stream().collect(Collectors.groupingBy(PlanSubDetailDO::getProjectSubId)); - collect1.forEach((id,detailList) -> { - Map> collect2 = detailList.stream().collect(Collectors.groupingBy(PlanSubDetailDO::getSubType)); - collect2.forEach((type,list2) ->{ - int i = 1; - for (PlanSubDetailDO planSubDetailDO : list2) { - planSubDetailDO.setSeqNo(Long.valueOf(i++)); - } - }); - }); - - planSubDetailMapper.deleteBatchIds(deleteId); +// Map> collect1 = list.stream().collect(Collectors.groupingBy(PlanSubDetailDO::getProjectSubId)); +// collect1.forEach((id,detailList) -> { +// Map> collect2 = detailList.stream().collect(Collectors.groupingBy(PlanSubDetailDO::getSubType)); +// collect2.forEach((type,list2) ->{ +// int i = 1; +// for (PlanSubDetailDO planSubDetailDO : list2) { +// planSubDetailDO.setSeqNo(Long.valueOf(i++)); +// } +// }); +// }); + if (CollUtil.isNotEmpty(deleteId)){ + planSubDetailMapper.deleteBatchIds(deleteId); + } + //查询子项目 planSubDetailMapper.insertOrUpdateBatch(list); //更新表主表数据 + // //先看有多少个子项目 - Map> groupBySubId = list.stream().collect(Collectors.groupingBy(PlanSubDetailDO::getProjectPlanSubId)); + Map> groupBySubId = list.stream().collect(Collectors.groupingBy(PlanSubDetailDO::getProjectSubId)); groupBySubId.forEach((subId,subList) -> { //再根据设计类型来 Map> groupByType = subList.stream().collect(Collectors.groupingBy(PlanSubDetailDO::getSubType)); @@ -595,21 +613,27 @@ public class PlanSubDetailServiceImpl implements PlanSubDetailService { .collect(Collectors.toList()); LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper<>(); lambdaUpdateWrapper.eq(PlanSubDO::getProjectSubId,subId); - LocalDateTime startTwoDimDate = sortedList.get(0).getStartTwoDimDate(); + LocalDateTime startTwoDimDate = sortedList.get(sortedList.size() - 1 ).getStartTwoDimDate(); LocalDateTime twoDimDate = sortedList.get(0).getTwoDimDate(); - Long num = sortedList.get(0).getDesignNum(); + Long num = 0L; + for (PlanSubDetailDO planSubDetailDO : sortedList) { + num += planSubDetailDO.getDesignNum(); + } //取最大值就是第一个 if ("BLUEPRINT_WORKBLANK".equals(type)){ lambdaUpdateWrapper.set(PlanSubDO::getStartBlankDate,startTwoDimDate); lambdaUpdateWrapper.set(PlanSubDO::getBlankDate,twoDimDate); + lambdaUpdateWrapper.set(PlanSubDO::getBlankOwner, sortedList.get(0).getTwoDimOwner()); lambdaUpdateWrapper.set(PlanSubDO::getBlankNum,num); }else if ("BLUEPRINT_2D".equals(type)){ lambdaUpdateWrapper.set(PlanSubDO::getStartTwoDimDate,startTwoDimDate); lambdaUpdateWrapper.set(PlanSubDO::getTwoDimDate,twoDimDate); + lambdaUpdateWrapper.set(PlanSubDO::getTwoDimOwner, sortedList.get(0).getTwoDimOwner()); lambdaUpdateWrapper.set(PlanSubDO::getTwoDimNum,num); }else { lambdaUpdateWrapper.set(PlanSubDO::getStartThreeDimDate,startTwoDimDate); lambdaUpdateWrapper.set(PlanSubDO::getThreeDimDate,twoDimDate); + lambdaUpdateWrapper.set(PlanSubDO::getThreeDimOwner, sortedList.get(0).getTwoDimOwner()); lambdaUpdateWrapper.set(PlanSubDO::getThreeDimNum,num); } planSubMapper.update(lambdaUpdateWrapper); @@ -1048,8 +1072,9 @@ public class PlanSubDetailServiceImpl implements PlanSubDetailService { // 2. 查询最大时间往后90天内的节假日 LocalDateTime endDate = maxDate.plusDays(90); + LocalDateTime begDate = minDate.minusDays(30); List shopCalendarDOList = shopCalendarMapper.selectList(new LambdaQueryWrapper().eq(ShopCalendarDO::getIfjiejiari, "true") - .between(ShopCalendarDO::getDates, minDate, endDate).orderByAsc(ShopCalendarDO::getDates)); + .between(ShopCalendarDO::getDates, begDate, endDate).orderByAsc(ShopCalendarDO::getDates)); List holidayList = new ArrayList<>(); for (ShopCalendarDO shopCalendarDO : shopCalendarDOList) { holidayList.add(shopCalendarDO.getDates()); @@ -1071,18 +1096,10 @@ public class PlanSubDetailServiceImpl implements PlanSubDetailService { // 5. 执行插活逻辑 List resultList = performInsertLogic(baseList, insertList, holidayList); - Map> collect1 = resultList.stream().collect(Collectors.groupingBy(PlanSubDetailDO::getProjectSubId)); - collect1.forEach((id,detailList) -> { - Map> collect2 = detailList.stream().collect(Collectors.groupingBy(PlanSubDetailDO::getSubType)); - collect2.forEach((type,list2) ->{ - int i = 1; - for (PlanSubDetailDO planSubDetailDO : list2) { - planSubDetailDO.setSeqNo(Long.valueOf(i++)); - } - }); - }); + // 6. 重新排序和设置序号 + resultList.sort(Comparator.comparing(PlanSubDetailDO::getStartTwoDimDate)); - // 6. 保存结果 + // 7. 保存结果 updateReqVO.setList(resultList); return CommonResult.success(updateReqVO); } @@ -1094,8 +1111,7 @@ public class PlanSubDetailServiceImpl implements PlanSubDetailService { List insertList, List holidayList) { List resultList = new ArrayList<>(); - - // 1. 先处理插活数据,保持原始时间范围,但designNum排除节假日 + // 1. 处理插活数据 List processedInsertList = new ArrayList<>(); for (PlanSubDetailDO insertItem : insertList) { PlanSubDetailDO processedItem = new PlanSubDetailDO(); @@ -1106,7 +1122,7 @@ public class PlanSubDetailServiceImpl implements PlanSubDetailService { processedItem.setProjectPlanSubId(insertItem.getProjectPlanSubId()); processedItem.setProjectSubCode(insertItem.getProjectSubCode()); processedItem.setTwoDimOwner(insertItem.getTwoDimOwner()); - processedItem.setProjectSubId(insertItem.getProjectPlanSubId()); + processedItem.setProjectSubId(insertItem.getProjectSubId()); processedItem.setSubType(insertItem.getSubType()); processedItem.setName(insertItem.getName()); processedItem.setCode(insertItem.getCode()); @@ -1138,195 +1154,189 @@ public class PlanSubDetailServiceImpl implements PlanSubDetailService { .max(LocalDateTime::compareTo) .orElse(null); - // 5. 获取baseList的时间范围 - final LocalDateTime baseMinStartTime = baseList.stream() - .map(PlanSubDetailDO::getStartTwoDimDate) - .min(LocalDateTime::compareTo) - .orElse(null); - final LocalDateTime baseMaxEndTime = baseList.stream() - .map(PlanSubDetailDO::getTwoDimDate) - .max(LocalDateTime::compareTo) - .orElse(null); + // 5. 获取baseList第一条数据 + PlanSubDetailDO firstBaseItem = baseList.get(0); - // 6. 边界情况处理 - if (insertEndTime != null && baseMinStartTime != null && insertEndTime.isBefore(baseMinStartTime)) { - // 情况1:插活数据在所有baseList之前 - resultList.addAll(processedInsertList); - resultList.addAll(baseList); - return resultList; - } + // 6. 判断属于哪种情况 + boolean isCase1 = insertStartTime != null && insertEndTime != null && + insertStartTime.compareTo(firstBaseItem.getTwoDimDate()) <= 0 && + insertEndTime.compareTo(firstBaseItem.getStartTwoDimDate()) >= 0 && + firstBaseItem.getStartTwoDimDate().compareTo(insertStartTime) >= 0; - if (insertStartTime != null && baseMaxEndTime != null && insertStartTime.isAfter(baseMaxEndTime)) { - // 情况2:插活数据在所有baseList之后 - resultList.addAll(baseList); - resultList.addAll(processedInsertList); - return resultList; - } + boolean isCase2 = insertStartTime != null && + insertStartTime.compareTo(firstBaseItem.getStartTwoDimDate()) > 0 && + insertStartTime.compareTo(firstBaseItem.getTwoDimDate()) <= 0; - // 7. 检查是否有插活数据紧挨着某个baseItem的结束时间 - PlanSubDetailDO mergedBaseItem = null; - List remainingInsertList = new ArrayList<>(); + if (isCase1) { + // 情况1:插活开始时间在第一条范围内 + // 创建合并的插活项 + PlanSubDetailDO mergedInsertItem = new PlanSubDetailDO(); + PlanSubDetailDO firstInsert = processedInsertList.get(0); + mergedInsertItem.setId(null); + mergedInsertItem.setProjectPlanId(firstInsert.getProjectPlanId()); + mergedInsertItem.setProjectId(firstInsert.getProjectId()); + mergedInsertItem.setProjectPlanSubId(firstInsert.getProjectPlanSubId()); + mergedInsertItem.setProjectSubCode(firstInsert.getProjectSubCode()); + mergedInsertItem.setTwoDimOwner(firstInsert.getTwoDimOwner()); + mergedInsertItem.setProjectSubId(firstInsert.getProjectSubId()); + mergedInsertItem.setSubType(firstInsert.getSubType()); + mergedInsertItem.setName(firstInsert.getName()); + mergedInsertItem.setCode(firstInsert.getCode()); + mergedInsertItem.setStartTwoDimDate(insertStartTime); + mergedInsertItem.setTwoDimDate(insertEndTime); + mergedInsertItem.setIsCha("Y"); + mergedInsertItem.setDesignNum(calculateWorkDaysExcludeHolidays(insertStartTime, insertEndTime, holidayList)); + resultList.add(mergedInsertItem); - 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; - } + // 处理第一条剩余部分 + LocalDateTime newStartTime = insertEndTime.plusDays(1); + // 跳过节假日 + newStartTime = findNextNonHoliday(newStartTime, holidayList); + + // 计算第一条剩余的designNum + Long firstSegmentDesignNum = calculateWorkDaysExcludeHolidays( + firstBaseItem.getStartTwoDimDate(), + insertStartTime.minusDays(1), + holidayList + ); + Long remainingDesignNum = firstBaseItem.getDesignNum() - firstSegmentDesignNum; + + if (remainingDesignNum > 0) { + LocalDateTime newEndTime = calculateEndDateByWorkDays(newStartTime, remainingDesignNum, holidayList); + PlanSubDetailDO remainingItem = createBaseItem(firstBaseItem, newStartTime, newEndTime); + remainingItem.setDesignNum(remainingDesignNum); + resultList.add(remainingItem); + newStartTime = newEndTime.plusDays(1); } - if (!merged) { - remainingInsertList.add(insertItem); - } - } - // 8. 如果有合并的情况,重新构建baseList - List 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); - } + // 处理后续baseList项 + for (int i = 1; i < baseList.size(); i++) { + PlanSubDetailDO baseItem = baseList.get(i); + // 检查是否有交集(使用原始结束时间) + boolean hasIntersection = (insertStartTime.compareTo(baseItem.getStartTwoDimDate()) <= 0) && + (newStartTime.compareTo(baseItem.getStartTwoDimDate()) >=0); - // 9. 正常插活逻辑(插活数据与baseList有重叠) - // 分离baseList:在插活数据之前的、被打断的、在插活数据之后的 - List beforeInsertList = new ArrayList<>(); - List interruptedList = new ArrayList<>(); - List afterInsertList = new ArrayList<>(); - - if (insertStartTime != null) { - for (PlanSubDetailDO baseItem : newBaseList) { - if (baseItem.getTwoDimDate().isBefore(insertStartTime)) { - // 完全在插活数据之前 - beforeInsertList.add(baseItem); - } else if (baseItem.getStartTwoDimDate().isBefore(insertStartTime) && - baseItem.getTwoDimDate().isAfter(insertStartTime.minusDays(1))) { - // 被插活数据打断 - interruptedList.add(baseItem); + if (hasIntersection) { + // 有交集,需要顺延 + newStartTime = findNextNonHoliday(newStartTime, holidayList); + LocalDateTime newEndTime = calculateEndDateByWorkDays(newStartTime, baseItem.getDesignNum(), holidayList); + PlanSubDetailDO shiftedItem = createBaseItem(baseItem, newStartTime, newEndTime); + shiftedItem.setDesignNum(baseItem.getDesignNum()); + resultList.add(shiftedItem); + newStartTime = newEndTime.plusDays(1); } else { - // 在插活数据之后 - afterInsertList.add(baseItem); + // 没有交集,保持原样 + resultList.add(baseItem); } } + + } else if (isCase2) { + // 情况2:插活开始时间在第一条开始时间之前 + // 第一段:从原开始时间到插活开始时间-1 + LocalDateTime firstSegmentEnd = findBeforeNonHoliday(insertStartTime.minusDays(1),holidayList); + Long firstSegmentDesignNum = calculateWorkDaysExcludeHolidays( + firstBaseItem.getStartTwoDimDate(), + firstSegmentEnd, + holidayList + ); + + if (firstSegmentDesignNum > 0) { + PlanSubDetailDO firstSegment = createBaseItem(firstBaseItem, firstBaseItem.getStartTwoDimDate(), firstSegmentEnd); + firstSegment.setDesignNum(firstSegmentDesignNum); + resultList.add(firstSegment); + } + + // 添加插活数据 + resultList.addAll(processedInsertList); + + // 第二段:从插活结束时间+1开始 + LocalDateTime newStartTime = insertEndTime.plusDays(1); + newStartTime = findNextNonHoliday(newStartTime, holidayList); + + Long remainingDesignNum = firstBaseItem.getDesignNum() - firstSegmentDesignNum; + if (remainingDesignNum > 0) { + LocalDateTime newEndTime = calculateEndDateByWorkDays(newStartTime, remainingDesignNum, holidayList); + PlanSubDetailDO secondSegment = createBaseItem(firstBaseItem, newStartTime, newEndTime); + secondSegment.setDesignNum(remainingDesignNum); + resultList.add(secondSegment); + newStartTime = newEndTime.plusDays(1); + } + + // 处理后续baseList项 + for (int i = 1; i < baseList.size(); i++) { + PlanSubDetailDO baseItem = baseList.get(i); + + // 检查当前条的开始时间是否 <= 前一条的结束时间 + if (baseItem.getStartTwoDimDate().compareTo(newStartTime.minusDays(1)) <= 0) { + // 需要顺延 + newStartTime = findNextNonHoliday(newStartTime, holidayList); + LocalDateTime newEndTime = calculateEndDateByWorkDays(newStartTime, baseItem.getDesignNum(), holidayList); + PlanSubDetailDO shiftedItem = createBaseItem(baseItem, newStartTime, newEndTime); + shiftedItem.setDesignNum(baseItem.getDesignNum()); + resultList.add(shiftedItem); + newStartTime = newEndTime.plusDays(1); + } else { + // 不需要顺延,保持原样 + resultList.add(baseItem); + } + } + } else { - beforeInsertList.addAll(newBaseList); + // 不属于两种情况,保持原样 + resultList.addAll(baseList); + resultList.addAll(processedInsertList); } - - // 10. 处理插活数据之前的baseList(保持原样) - resultList.addAll(beforeInsertList); - - // 11. 处理被打断的baseList - List remainingBaseList = new ArrayList<>(); - for (PlanSubDetailDO interruptedItem : interruptedList) { - // 计算插活数据开始前的天数(包含节假日) - long daysBeforeInsert = ChronoUnit.DAYS.between(interruptedItem.getStartTwoDimDate(), insertStartTime); - - if (daysBeforeInsert > 0) { - // 创建插活前的段落 - LocalDateTime segmentEnd = interruptedItem.getStartTwoDimDate().plusDays(daysBeforeInsert - 1); - PlanSubDetailDO beforeSegment = createBaseItem(interruptedItem, interruptedItem.getStartTwoDimDate(), segmentEnd); - // designNum排除节假日 - beforeSegment.setDesignNum(calculateWorkDaysExcludeHolidays(interruptedItem.getStartTwoDimDate(), segmentEnd, holidayList)); - resultList.add(beforeSegment); - - // 剩余部分保持原始designNum,稍后处理 - PlanSubDetailDO remainingItem = new PlanSubDetailDO(); - // 复制属性 - remainingItem.setId(interruptedItem.getId()); - remainingItem.setProjectPlanId(interruptedItem.getProjectPlanId()); - remainingItem.setProjectId(interruptedItem.getProjectId()); - remainingItem.setProjectPlanSubId(interruptedItem.getProjectPlanSubId()); - remainingItem.setProjectSubCode(interruptedItem.getProjectSubCode()); - remainingItem.setTwoDimOwner(interruptedItem.getTwoDimOwner()); - remainingItem.setProjectSubId(interruptedItem.getProjectSubId()); - remainingItem.setSubType(interruptedItem.getSubType()); - remainingItem.setName(interruptedItem.getName()); - remainingItem.setCode(interruptedItem.getCode()); - remainingItem.setDesignNum(interruptedItem.getDesignNum()); // 保持原始designNum - remainingBaseList.add(remainingItem); - } else { - // 整个被打断,全部加入剩余列表 - remainingBaseList.add(interruptedItem); - } - } - - // 12. 添加剩余的插活数据(未被合并的) - resultList.addAll(remainingInsertList); - - // 13. 处理剩余的baseList(被打断的剩余部分 + 原本在插活数据之后的) - List allRemainingList = new ArrayList<>(); - allRemainingList.addAll(remainingBaseList); - allRemainingList.addAll(afterInsertList); - - if (!allRemainingList.isEmpty()) { - // 获取插活数据的最后结束时间 - final LocalDateTime lastInsertEndTime; - if (mergedBaseItem != null) { - lastInsertEndTime = mergedBaseItem.getTwoDimDate(); - } else { - lastInsertEndTime = processedInsertList.stream() - .map(PlanSubDetailDO::getTwoDimDate) - .max(LocalDateTime::compareTo) - .orElse(null); + // 7 处理SeqNo逻辑 + // 从baseList获取每个ProjectSubId下每种SubType的最小SeqNo + Map minSeqNoMap = new HashMap<>(); + if (!baseList.isEmpty()) { + Map> tempMap = new HashMap<>(); + for (PlanSubDetailDO item : baseList) { + String key = item.getProjectSubId() + "|" + item.getSubType(); + tempMap.computeIfAbsent(key, k -> new HashMap<>()) + .merge("min", item.getSeqNo(), Math::min); + } + tempMap.forEach((k, v) -> minSeqNoMap.put(k, v.get("min"))); } - // 从插活数据的下一天开始顺延 - LocalDateTime baseStartTime = lastInsertEndTime.plusDays(1); - - for (PlanSubDetailDO baseItem : allRemainingList) { - // 找到下一个非节假日开始时间 - LocalDateTime newStartTime = findNextNonHoliday(baseStartTime, holidayList); - - // 根据designNum计算结束日期(包含节假日) - LocalDateTime newEndTime = calculateEndDateByWorkDays(newStartTime, baseItem.getDesignNum(), holidayList); - - PlanSubDetailDO newBaseItem = createBaseItem(baseItem, newStartTime, newEndTime); - newBaseItem.setDesignNum(baseItem.getDesignNum()); // 保持原始designNum - resultList.add(newBaseItem); - - // 更新下一个baseItem的开始时间 - baseStartTime = newEndTime.plusDays(1); + // 为resultList设置SeqNo + Map> resultGroupMap = new HashMap<>(); + for (PlanSubDetailDO item : resultList) { + String key = item.getProjectSubId() + "|" + item.getSubType(); + resultGroupMap.computeIfAbsent(key, k -> new ArrayList<>()).add(item); } - } - // 14. 按开始时间排序 + for (Map.Entry> entry : resultGroupMap.entrySet()) { + String[] keys = entry.getKey().split("\\|"); + String projectSubId = keys[0]; + String subType = keys[1]; + + // 获取对应分组的最小SeqNo + Long baseMinSeq = minSeqNoMap.get(entry.getKey()); + if (baseMinSeq == null) { + // 没有base数据时取默认值或根据业务逻辑处理 + baseMinSeq = 1L; + } + + List sortedList = entry.getValue().stream() + .sorted(Comparator.comparing(PlanSubDetailDO::getStartTwoDimDate)) + .collect(Collectors.toList()); + + // 分配SeqNo + long currentSeq = baseMinSeq; + for (PlanSubDetailDO item : sortedList) { + item.setSeqNo(currentSeq++); + } + } + // 8. 按开始时间排序 resultList.sort(Comparator.comparing(PlanSubDetailDO::getStartTwoDimDate)); return resultList; } + + /** + * 找到下一个非节假日日期 + */ private LocalDateTime findNextNonHoliday(LocalDateTime startDate, List holidayList) { LocalDateTime current = startDate; while (holidayList.contains(current)) { @@ -1334,19 +1344,29 @@ public class PlanSubDetailServiceImpl implements PlanSubDetailService { } return current; } + private LocalDateTime findBeforeNonHoliday(LocalDateTime startDate, List holidayList) { + LocalDateTime current = startDate; + while (holidayList.contains(current)) { + current = current.minusDays(1); + } + return current; + } + /** * 计算排除节假日的工作天数 */ private Long calculateWorkDaysExcludeHolidays(LocalDateTime startDate, LocalDateTime endDate, List holidayList) { + if (startDate.isAfter(endDate)) { + return 0L; + } + long workDays = 0; LocalDateTime current = startDate.toLocalDate().atStartOfDay(); LocalDateTime end = endDate.toLocalDate().atStartOfDay(); while (!current.isAfter(end)) { // 检查是否是节假日 - LocalDateTime finalCurrent = current; - boolean isHoliday = holidayList.stream() - .anyMatch(holiday -> holiday.isEqual(finalCurrent)); + boolean isHoliday = holidayList.contains(current); if (!isHoliday) { workDays++; @@ -1366,9 +1386,7 @@ public class PlanSubDetailServiceImpl implements PlanSubDetailService { while (countedWorkDays < workDays) { // 检查是否是节假日 - LocalDateTime finalCurrent = current; - boolean isHoliday = holidayList.stream() - .anyMatch(holiday -> holiday.isEqual(finalCurrent)); + boolean isHoliday = holidayList.contains(current); if (!isHoliday) { countedWorkDays++; @@ -1383,7 +1401,7 @@ public class PlanSubDetailServiceImpl implements PlanSubDetailService { } /** - * 创建baseItem对象(用于baseList顺延) + * 创建baseItem对象 */ private PlanSubDetailDO createBaseItem(PlanSubDetailDO original, LocalDateTime startDate, LocalDateTime endDate) { PlanSubDetailDO baseItem = new PlanSubDetailDO(); @@ -1394,7 +1412,7 @@ public class PlanSubDetailServiceImpl implements PlanSubDetailService { baseItem.setProjectPlanSubId(original.getProjectPlanSubId()); baseItem.setProjectSubCode(original.getProjectSubCode()); baseItem.setTwoDimOwner(original.getTwoDimOwner()); - baseItem.setProjectSubId(original.getProjectPlanSubId()); + baseItem.setProjectSubId(original.getProjectSubId()); baseItem.setSubType(original.getSubType()); baseItem.setName(original.getName()); baseItem.setCode(original.getCode()); @@ -1403,18 +1421,6 @@ public class PlanSubDetailServiceImpl implements PlanSubDetailService { return baseItem; } - /** - * 获取时间段内的节假日 - */ - private List getHolidaysInRange(LocalDateTime startDate, LocalDateTime endDate, - List holidayList) { - return holidayList.stream() - .filter(holiday -> !holiday.isBefore(startDate) && !holiday.isAfter(endDate)) - .sorted() - .collect(Collectors.toList()); - } - - @Override diff --git a/mes-ui/mes-ui-admin-vue3/src/views/heli/interrupt/index.vue b/mes-ui/mes-ui-admin-vue3/src/views/heli/interrupt/index.vue index 9bcc87e7..975308c9 100644 --- a/mes-ui/mes-ui-admin-vue3/src/views/heli/interrupt/index.vue +++ b/mes-ui/mes-ui-admin-vue3/src/views/heli/interrupt/index.vue @@ -316,7 +316,7 @@ - + @@ -510,6 +510,8 @@ const handleAddCancel = () => { }) .then(() => { addDialogVisible.value = false + selectedAddRow.value = [] + multipleTableRef.value.clearSelection() }) .catch(() => {}) } @@ -528,6 +530,7 @@ const handleAddConfirm = () => { return } selectedAddRow.value[0].twoDimDate = null + selectedAddRow.value[0].projectPlanSubId = null selectedAddRow.value[0].startTwoDimDate = null selectedAddRow.value[0].twoDimOwner = null selectedAddRow.value[0].subType = null @@ -539,6 +542,8 @@ const handleAddConfirm = () => { selectedAddRow.value[0].id = null list.value.unshift(selectedAddRow.value[0]) addDialogVisible.value = false + selectedAddRow.value = [] + multipleTableRef.value.clearSelection() message.success('项目添加成功') } @@ -688,8 +693,13 @@ const addItemRow = (row) => { flag: 1, // 标记为可编辑状态 userFlag: true } - + const currentIndex = list.value.findIndex(item=> item === row); + if(currentIndex !== -1){ + list.value.splice(currentIndex+1,0,newRow); + }else{ list.value.unshift(newRow) + } + //message.success('新增行成功') } else { @@ -766,12 +776,13 @@ const handleConfirm = async () => { if (res) { message.success('插活成功') dialogVisible.value = false + await getList() } } catch (error) { message.error('插活失败:' + error.message) + await getList() } finally { loading2.value = false - reload() // 刷新列表 } dialogVisible.value = false diff --git a/mes-ui/mes-ui-admin-vue3/src/views/heli/plan/edit.vue b/mes-ui/mes-ui-admin-vue3/src/views/heli/plan/edit.vue index a0e9ac87..6d9e86ce 100644 --- a/mes-ui/mes-ui-admin-vue3/src/views/heli/plan/edit.vue +++ b/mes-ui/mes-ui-admin-vue3/src/views/heli/plan/edit.vue @@ -1460,10 +1460,12 @@ const handleDateChange = async ( const rowData = formData.value.projectPlanSubs[index] // 使用一个数组来收集所有遇到的错误信息 const errors = [] - + var deleteBlankNum = false; + var deleteEndNum = false; // --- 检查开始日期 --- if (typeof startBlankDate === 'undefined' || startBlankDate === null || startBlankDate === '') { errors.push('请选择开始日期,否则无法计算设计天数') + deleteBlankNum = true; } else { const starDateStr = new Date(startBlankDate).toLocaleDateString('en-CA') if (starDateStr < nowDataStr) { @@ -1484,6 +1486,7 @@ const handleDateChange = async ( // --- 检查结束日期 --- if (typeof blankDate === 'undefined' || blankDate === null || blankDate === '') { errors.push('请选择结束日期,否则无法计算设计天数') + deleteEndNum = true; } else { const endDateStr = new Date(blankDate).toLocaleDateString('en-CA') if (endDateStr < nowDataStr) { @@ -1508,12 +1511,13 @@ const handleDateChange = async ( // 统一更新 rowData,清空无效的日期 if (startBlankDate === null) { + rowData[dataNumField] = null rowData[startField] = null } if (blankDate === null) { + rowData[dataNumField] = null rowData[endField] = null } - return // 最后再 return,终止函数 } //用户选择完成后要取数据库中检索是否存在时间冲突,存在弹出插活框 @@ -2379,39 +2383,14 @@ const submitForm = async () => { await PlanApi.updatePlan(data) await PlanSubApi.operate(formData.value.projectPlanSubs) - // formData.value.projectPlanSubs.forEach((item) => { - // var subData = item as unknown as PlanSubApid.PlanSubVo - // // subData.projectId = item.projectOrderId - // // subData.projectPlanId = formData.value.id - // // subData.projectSubShortName = item.projectSubShortName - // // subData.projectSubCode = item.projectSubCode - // // subData.projectSubId = item.projectSubId - // if (subData.id == undefined) { - // subData.id = 0 - // subData.id = PlanSubApi.createPlanSub(subData) - // } else { - // //subData.id = item.planSubId - // PlanSubApi.updatePlanSub(subData) - // } - // //subData.id = subData.projectSubId - // }) - // //更新其余项目 - // prods.value.projectPlanSubs.forEach((item) => { - // var subData = item as unknown as PlanSubApid.PlanSubVo - // if (subData.id == undefined) { - // subData.id = 0 - // subData.id = PlanSubApi.createPlanSub(subData) - // } else { - // //subData.id = item.planSubId - // PlanSubApi.updatePlanSub(subData) - // } - // //subData.id = subData.projectSubId - // }) + setTimeout(() => { + reload() + },1000) + console.log() message.success(t('common.updateSuccess')) // 发送操作成功的事件 // emit('success') } finally { - reload() formLoading.value = false } }