Merge remote-tracking branch 'origin/main'
This commit is contained in:
		
						commit
						630c2dec38
					
				@ -60,7 +60,7 @@ public interface PlanSubMapper extends BaseMapperX<PlanSubDO> {
 | 
			
		||||
                .leftJoin(ProjectOrderSubDO.class, "c", ProjectOrderSubDO::getId, PlanSubDO::getProjectSubId)
 | 
			
		||||
                .eq(ProjectOrderDO::getDeliveryStatus,1)
 | 
			
		||||
                .disableSubLogicDel()
 | 
			
		||||
                .orderByAsc(PlanSubDO::getId)
 | 
			
		||||
                .orderByDesc(PlanSubDO::getId)
 | 
			
		||||
        ;
 | 
			
		||||
        query.like(ObjectUtil.isNotEmpty(reqVO.getProjectCode()), PlanDO::getCode, reqVO.getProjectCode())
 | 
			
		||||
                .like(ObjectUtil.isNotEmpty(reqVO.getProjectSubName()), PlanSubDetailDO::getName, reqVO.getProjectSubName());
 | 
			
		||||
 | 
			
		||||
@ -219,16 +219,16 @@ public class PlanSubServiceImpl implements PlanSubService {
 | 
			
		||||
        for (PlanSubSaveReqVO newTask : processTasks) {
 | 
			
		||||
            // 检查毛坯任务
 | 
			
		||||
            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任务
 | 
			
		||||
            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任务
 | 
			
		||||
            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) {
 | 
			
		||||
            return; // 如果责任人或时间为空,则无需检查
 | 
			
		||||
        }
 | 
			
		||||
@ -256,7 +256,7 @@ public class PlanSubServiceImpl implements PlanSubService {
 | 
			
		||||
        }
 | 
			
		||||
        for (PlanSubDetailDO existingTask : existingTasksForOwner) {
 | 
			
		||||
            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)+"存在交集,请确认!"));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -293,6 +293,7 @@ public class PlanSubDetailServiceImpl implements PlanSubDetailService {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    @Transactional
 | 
			
		||||
    public CommonResult modification(PlanSubDetailSaveReqVO updateReqVO) {
 | 
			
		||||
        LambdaQueryWrapper<PlanSubDetailDO> wrapper = new LambdaQueryWrapper<>();
 | 
			
		||||
        wrapper.eq(PlanSubDetailDO::getProjectSubId,updateReqVO.getProjectSubId());
 | 
			
		||||
@ -300,8 +301,9 @@ public class PlanSubDetailServiceImpl implements PlanSubDetailService {
 | 
			
		||||
        wrapper.gt(PlanSubDetailDO::getSeqNo,updateReqVO.getSeqNo());
 | 
			
		||||
        if (planSubDetailMapper.selectCount(wrapper)>0) return CommonResult.error(400,"该子项目存在多时间段派工,不允许从中间修改!");
 | 
			
		||||
        LambdaQueryWrapper<PlanSubDetailDO> queryWrapper = new LambdaQueryWrapper<>();
 | 
			
		||||
        queryWrapper.eq(PlanSubDetailDO::getProjectSubId,updateReqVO.getProjectSubId());
 | 
			
		||||
        queryWrapper.eq(PlanSubDetailDO::getSubType,updateReqVO.getSubType());
 | 
			
		||||
//        queryWrapper.eq(PlanSubDetailDO::getProjectSubId,updateReqVO.getProjectSubId());
 | 
			
		||||
        queryWrapper.eq(PlanSubDetailDO::getTwoDimOwner,updateReqVO.getTwoDimOwner());
 | 
			
		||||
//        queryWrapper.eq(PlanSubDetailDO::getSubType,updateReqVO.getSubType());
 | 
			
		||||
        if (ObjectUtil.isNotEmpty(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> noSelfList = new ArrayList<>();
 | 
			
		||||
//        if (CollUtil.isNotEmpty(list) && list.size() == 1){
 | 
			
		||||
//            return CommonResult.error(400,"请修改数据后再点击修改");
 | 
			
		||||
//
 | 
			
		||||
//        }
 | 
			
		||||
//        for (PlanSubDetailDO planSubDetailDO : list) {
 | 
			
		||||
//            if (!planSubDetailDO.getId().equals(updateReqVO.getId())){
 | 
			
		||||
//                noSelfList.add(planSubDetailDO);
 | 
			
		||||
//            }
 | 
			
		||||
//        }
 | 
			
		||||
//        if (ObjectUtil.isEmpty( noSelfList) && ((updateReqVO.getStartTwoDimDate().compareTo(noSelfList.get(0).getTwoDimDate()) <=0 )&& (updateReqVO.getTwoDimDate().compareTo(noSelfList.get(0).getStartTwoDimDate()) >= 0))){
 | 
			
		||||
//            if (ObjectUtil.isNotEmpty(updateReqVO.getId())){
 | 
			
		||||
//                planSubDetailMapper.delete(PlanSubDetailDO::getId,updateReqVO.getId());
 | 
			
		||||
//            }
 | 
			
		||||
//            PlanSubDetailDO planSubDetailDO = new PlanSubDetailDO();
 | 
			
		||||
//            planSubDetailDO.setProjectPlanId(updateReqVO.getProjectPlanId());
 | 
			
		||||
//            planSubDetailDO.setProjectId(updateReqVO.getProjectId());
 | 
			
		||||
//            planSubDetailDO.setProjectSubId(updateReqVO.getProjectSubId());
 | 
			
		||||
//            planSubDetailDO.setProjectSubCode(updateReqVO.getProjectSubCode());
 | 
			
		||||
//            planSubDetailDO.setTwoDimDate(updateReqVO.getTwoDimDate());
 | 
			
		||||
//            planSubDetailDO.setTwoDimOwner(updateReqVO.getTwoDimOwner());
 | 
			
		||||
//            planSubDetailDO.setStartTwoDimDate(updateReqVO.getStartTwoDimDate());
 | 
			
		||||
//            planSubDetailDO.setSubType(updateReqVO.getSubType());
 | 
			
		||||
//            planSubDetailDO.setIsOverProcess(0);
 | 
			
		||||
//            planSubDetailDO.setSeqNo(1L);
 | 
			
		||||
//            planSubDetailDO.setDesignNum(updateReqVO.getDesignNum());
 | 
			
		||||
//            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++) {
 | 
			
		||||
//                list.get(i).setSeqNo(Long.valueOf(i + 1)); // 设置顺序为 1, 2, 3
 | 
			
		||||
//            }
 | 
			
		||||
//            planSubDetailMapper.insertOrUpdateBatch(list);
 | 
			
		||||
//            return CommonResult.success(true);
 | 
			
		||||
//        }
 | 
			
		||||
        for (PlanSubDetailDO planSubDetailDO : list) {
 | 
			
		||||
            if (!planSubDetailDO.getId().equals(updateReqVO.getId())){
 | 
			
		||||
                noSelfList.add(planSubDetailDO);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        boolean change = false;
 | 
			
		||||
        if (CollUtil.isNotEmpty(list)){
 | 
			
		||||
            if (list.size() == 1){
 | 
			
		||||
                PlanSubDetailDO planSubDetailDO = list.get(0);
 | 
			
		||||
                if (planSubDetailDO.getId().equals(updateReqVO.getId())){
 | 
			
		||||
                    if (updateReqVO.getStartTwoDimDate().compareTo(planSubDetailDO.getStartTwoDimDate()) == 0 || updateReqVO.getTwoDimDate().compareTo(planSubDetailDO.getTwoDimDate()) == 0){
 | 
			
		||||
                        change = true;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (change || ObjectUtil.isEmpty(list) || (list.get(0).getStartTwoDimDate().compareTo(updateReqVO.getTwoDimDate()) > 0 )){
 | 
			
		||||
            List<PlanSubDetailDO> newList = new ArrayList<>();
 | 
			
		||||
            newList.addAll(list);
 | 
			
		||||
            if (ObjectUtil.isNotEmpty(updateReqVO.getId())){
 | 
			
		||||
                newList.clear();
 | 
			
		||||
                planSubDetailMapper.delete(PlanSubDetailDO::getId,updateReqVO.getId());
 | 
			
		||||
                for (PlanSubDetailDO planSubDetailDO : list) {
 | 
			
		||||
                    if (!planSubDetailDO.getId().equals(updateReqVO.getId())){
 | 
			
		||||
                        newList.add(planSubDetailDO);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            PlanSubDetailDO planSubDetailDO = new PlanSubDetailDO();
 | 
			
		||||
            planSubDetailDO.setProjectPlanId(updateReqVO.getProjectPlanId());
 | 
			
		||||
            planSubDetailDO.setProjectId(updateReqVO.getProjectId());
 | 
			
		||||
            planSubDetailDO.setProjectSubId(updateReqVO.getProjectSubId());
 | 
			
		||||
            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);
 | 
			
		||||
        return CommonResult.success(updateReqVO);
 | 
			
		||||
    }
 | 
			
		||||
@ -1006,18 +1064,14 @@ public class PlanSubDetailServiceImpl implements PlanSubDetailService {
 | 
			
		||||
        return CommonResult.success(updateReqVO);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 执行插活逻辑
 | 
			
		||||
     */
 | 
			
		||||
    private List<PlanSubDetailDO> performInsertLogic(List<PlanSubDetailDO> baseList,
 | 
			
		||||
                                                     List<PlanSubDetailDO> insertList,
 | 
			
		||||
                                                     List<LocalDateTime> holidayList) {
 | 
			
		||||
        List<PlanSubDetailDO> resultList = new ArrayList<>();
 | 
			
		||||
 | 
			
		||||
        // 1. 先处理插活数据,不按节假日分段,保持原始范围
 | 
			
		||||
        // 1. 先处理插活数据,保持原始时间范围,但designNum排除节假日
 | 
			
		||||
        List<PlanSubDetailDO> processedInsertList = new ArrayList<>();
 | 
			
		||||
        for (PlanSubDetailDO insertItem : insertList) {
 | 
			
		||||
            // 插活数据保持原始时间范围,但designNum排除节假日
 | 
			
		||||
            PlanSubDetailDO processedItem = new PlanSubDetailDO();
 | 
			
		||||
            // 复制属性
 | 
			
		||||
            processedItem.setId(null);
 | 
			
		||||
@ -1045,26 +1099,25 @@ public class PlanSubDetailServiceImpl implements PlanSubDetailService {
 | 
			
		||||
 | 
			
		||||
        // 3. 处理baseList为空的情况
 | 
			
		||||
        if (CollUtil.isEmpty(baseList)) {
 | 
			
		||||
            // baseList为空,直接返回插活数据
 | 
			
		||||
            return new ArrayList<>(processedInsertList);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 4. 获取插活数据的时间范围
 | 
			
		||||
        LocalDateTime insertStartTime = processedInsertList.stream()
 | 
			
		||||
        final LocalDateTime insertStartTime = processedInsertList.stream()
 | 
			
		||||
                .map(PlanSubDetailDO::getStartTwoDimDate)
 | 
			
		||||
                .min(LocalDateTime::compareTo)
 | 
			
		||||
                .orElse(null);
 | 
			
		||||
        LocalDateTime insertEndTime = processedInsertList.stream()
 | 
			
		||||
        final LocalDateTime insertEndTime = processedInsertList.stream()
 | 
			
		||||
                .map(PlanSubDetailDO::getTwoDimDate)
 | 
			
		||||
                .max(LocalDateTime::compareTo)
 | 
			
		||||
                .orElse(null);
 | 
			
		||||
 | 
			
		||||
        // 5. 获取baseList的时间范围
 | 
			
		||||
        LocalDateTime baseMinStartTime = baseList.stream()
 | 
			
		||||
        final LocalDateTime baseMinStartTime = baseList.stream()
 | 
			
		||||
                .map(PlanSubDetailDO::getStartTwoDimDate)
 | 
			
		||||
                .min(LocalDateTime::compareTo)
 | 
			
		||||
                .orElse(null);
 | 
			
		||||
        LocalDateTime baseMaxEndTime = baseList.stream()
 | 
			
		||||
        final LocalDateTime baseMaxEndTime = baseList.stream()
 | 
			
		||||
                .map(PlanSubDetailDO::getTwoDimDate)
 | 
			
		||||
                .max(LocalDateTime::compareTo)
 | 
			
		||||
                .orElse(null);
 | 
			
		||||
@ -1084,14 +1137,72 @@ public class PlanSubDetailServiceImpl implements PlanSubDetailService {
 | 
			
		||||
            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:在插活数据之前的、被打断的、在插活数据之后的
 | 
			
		||||
        List<PlanSubDetailDO> beforeInsertList = new ArrayList<>();
 | 
			
		||||
        List<PlanSubDetailDO> interruptedList = new ArrayList<>();
 | 
			
		||||
        List<PlanSubDetailDO> afterInsertList = new ArrayList<>();
 | 
			
		||||
 | 
			
		||||
        if (insertStartTime != null) {
 | 
			
		||||
            for (PlanSubDetailDO baseItem : baseList) {
 | 
			
		||||
            for (PlanSubDetailDO baseItem : newBaseList) {
 | 
			
		||||
                if (baseItem.getTwoDimDate().isBefore(insertStartTime)) {
 | 
			
		||||
                    // 完全在插活数据之前
 | 
			
		||||
                    beforeInsertList.add(baseItem);
 | 
			
		||||
@ -1105,13 +1216,13 @@ public class PlanSubDetailServiceImpl implements PlanSubDetailService {
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            beforeInsertList.addAll(baseList);
 | 
			
		||||
            beforeInsertList.addAll(newBaseList);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 8. 处理插活数据之前的baseList(保持原样)
 | 
			
		||||
        // 10. 处理插活数据之前的baseList(保持原样)
 | 
			
		||||
        resultList.addAll(beforeInsertList);
 | 
			
		||||
 | 
			
		||||
        // 9. 处理被打断的baseList
 | 
			
		||||
        // 11. 处理被打断的baseList
 | 
			
		||||
        List<PlanSubDetailDO> remainingBaseList = new ArrayList<>();
 | 
			
		||||
        for (PlanSubDetailDO interruptedItem : interruptedList) {
 | 
			
		||||
            // 计算插活数据开始前的天数(包含节假日)
 | 
			
		||||
@ -1125,72 +1236,73 @@ public class PlanSubDetailServiceImpl implements PlanSubDetailService {
 | 
			
		||||
                beforeSegment.setDesignNum(calculateWorkDaysExcludeHolidays(interruptedItem.getStartTwoDimDate(), segmentEnd, holidayList));
 | 
			
		||||
                resultList.add(beforeSegment);
 | 
			
		||||
 | 
			
		||||
                // 保存剩余的designNum(原始designNum减去已使用的)
 | 
			
		||||
                Long usedDesignNum = calculateWorkDaysExcludeHolidays(interruptedItem.getStartTwoDimDate(), segmentEnd, holidayList);
 | 
			
		||||
                Long remainingDesignNum = interruptedItem.getDesignNum() - usedDesignNum;
 | 
			
		||||
                if (remainingDesignNum > 0) {
 | 
			
		||||
                    // 创建剩余的baseItem,稍后处理
 | 
			
		||||
                    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.getProjectPlanSubId());
 | 
			
		||||
                    remainingItem.setSubType(interruptedItem.getSubType());
 | 
			
		||||
                    remainingItem.setName(interruptedItem.getName());
 | 
			
		||||
                    remainingItem.setCode(interruptedItem.getCode());
 | 
			
		||||
                    remainingItem.setDesignNum(remainingDesignNum);
 | 
			
		||||
                    remainingBaseList.add(remainingItem);
 | 
			
		||||
                }
 | 
			
		||||
                // 剩余部分保持原始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.getProjectPlanSubId());
 | 
			
		||||
                remainingItem.setSubType(interruptedItem.getSubType());
 | 
			
		||||
                remainingItem.setName(interruptedItem.getName());
 | 
			
		||||
                remainingItem.setCode(interruptedItem.getCode());
 | 
			
		||||
                remainingItem.setDesignNum(interruptedItem.getDesignNum()); // 保持原始designNum
 | 
			
		||||
                remainingBaseList.add(remainingItem);
 | 
			
		||||
            } else {
 | 
			
		||||
                // 整个被打断,全部加入剩余列表
 | 
			
		||||
                remainingBaseList.add(interruptedItem);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 10. 添加插活数据
 | 
			
		||||
        resultList.addAll(processedInsertList);
 | 
			
		||||
        // 12. 添加剩余的插活数据(未被合并的)
 | 
			
		||||
        resultList.addAll(remainingInsertList);
 | 
			
		||||
 | 
			
		||||
        // 11. 处理剩余的baseList(被打断的剩余部分 + 原本在插活数据之后的)
 | 
			
		||||
        List<PlanSubDetailDO> allRemainingList = new ArrayList<>();
 | 
			
		||||
        allRemainingList.addAll(remainingBaseList);
 | 
			
		||||
        allRemainingList.addAll(afterInsertList);
 | 
			
		||||
 | 
			
		||||
        if (!allRemainingList.isEmpty()) {
 | 
			
		||||
        // 13. 处理剩余的baseList
 | 
			
		||||
        if (!remainingBaseList.isEmpty() || !afterInsertList.isEmpty()) {
 | 
			
		||||
            // 获取插活数据的最后结束时间
 | 
			
		||||
            LocalDateTime lastInsertEndTime = processedInsertList.stream()
 | 
			
		||||
                    .map(PlanSubDetailDO::getTwoDimDate)
 | 
			
		||||
                    .max(LocalDateTime::compareTo)
 | 
			
		||||
                    .orElse(null);
 | 
			
		||||
            final LocalDateTime lastInsertEndTime;
 | 
			
		||||
            if (mergedBaseItem != null) {
 | 
			
		||||
                lastInsertEndTime = mergedBaseItem.getTwoDimDate();
 | 
			
		||||
            } else {
 | 
			
		||||
                lastInsertEndTime = processedInsertList.stream()
 | 
			
		||||
                        .map(PlanSubDetailDO::getTwoDimDate)
 | 
			
		||||
                        .max(LocalDateTime::compareTo)
 | 
			
		||||
                        .orElse(null);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // 从插活数据的下一天开始顺延
 | 
			
		||||
            LocalDateTime baseStartTime = lastInsertEndTime.plusDays(1);
 | 
			
		||||
 | 
			
		||||
            for (PlanSubDetailDO baseItem : allRemainingList) {
 | 
			
		||||
                // 按照原有的designNum计算新的时间段(排除节假日)
 | 
			
		||||
                LocalDateTime newStartTime = findNextNonHoliday(baseStartTime, holidayList);
 | 
			
		||||
            // 处理被打断的剩余部分
 | 
			
		||||
            for (PlanSubDetailDO baseItem : remainingBaseList) {
 | 
			
		||||
                // 从插活数据的下一天开始计算
 | 
			
		||||
                LocalDateTime newStartTime = lastInsertEndTime.plusDays(1);
 | 
			
		||||
                // 如果遇到节假日,继续跳过
 | 
			
		||||
                newStartTime = findNextNonHoliday(newStartTime, holidayList);
 | 
			
		||||
                LocalDateTime newEndTime = calculateEndDateByWorkDays(newStartTime, baseItem.getDesignNum(), holidayList);
 | 
			
		||||
 | 
			
		||||
                // 创建新的baseItem
 | 
			
		||||
                PlanSubDetailDO newBaseItem = createBaseItem(baseItem, newStartTime, newEndTime);
 | 
			
		||||
                newBaseItem.setDesignNum(baseItem.getDesignNum()); // 保持原始designNum
 | 
			
		||||
                resultList.add(newBaseItem);
 | 
			
		||||
 | 
			
		||||
                // 更新下一个baseItem的开始时间
 | 
			
		||||
                baseStartTime = newEndTime.plusDays(1);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // 处理原本在插活数据之后的baseList(保持原样)
 | 
			
		||||
            resultList.addAll(afterInsertList);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 12. 按开始时间排序
 | 
			
		||||
        // 14. 按开始时间排序
 | 
			
		||||
        resultList.sort(Comparator.comparing(PlanSubDetailDO::getStartTwoDimDate));
 | 
			
		||||
 | 
			
		||||
        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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 找到下一个非节假日日期
 | 
			
		||||
     */
 | 
			
		||||
    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顺延)
 | 
			
		||||
     */
 | 
			
		||||
@ -1279,6 +1372,18 @@ public class PlanSubDetailServiceImpl implements PlanSubDetailService {
 | 
			
		||||
        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
 | 
			
		||||
 | 
			
		||||
@ -371,7 +371,7 @@ import * as PlansubdetailApi from '@/api/heli/plansubdetail'
 | 
			
		||||
import { DICT_TYPE, getIntDictOptions, getStrDictOptions } from '@/utils/dict'
 | 
			
		||||
import { ref, reactive, onMounted } from 'vue' // 确保导入 onMounted
 | 
			
		||||
import * as UserApi from '@/api/system/user'
 | 
			
		||||
 | 
			
		||||
import routeParamsCache from '@/utils/routeParamsCache';
 | 
			
		||||
import * as PlanSubApi from '@/api/heli/plansub'
 | 
			
		||||
import { formatDate } from '@/utils/formatTime'
 | 
			
		||||
import * as shopCalendarApi from '@/api/heli/shopCalendar'
 | 
			
		||||
@ -466,7 +466,7 @@ const handleSelectionChange = (val) => {
 | 
			
		||||
// 新增按钮方法
 | 
			
		||||
const addForm = () => {
 | 
			
		||||
  resetAddForm()
 | 
			
		||||
  getAddList()
 | 
			
		||||
  // getAddList()
 | 
			
		||||
  addDialogVisible.value = true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -537,7 +537,7 @@ const handleAddConfirm = () => {
 | 
			
		||||
  selectedAddRow.value[0].flag = 1
 | 
			
		||||
  selectedAddRow.value[0].userFlag = true
 | 
			
		||||
  selectedAddRow.value[0].id = null
 | 
			
		||||
  list.value.push(selectedAddRow.value[0])
 | 
			
		||||
  list.value.unshift(selectedAddRow.value[0])
 | 
			
		||||
  addDialogVisible.value = false
 | 
			
		||||
  message.success('项目添加成功')
 | 
			
		||||
}
 | 
			
		||||
@ -637,7 +637,8 @@ const modification = async (row) => {
 | 
			
		||||
    dialogVisible.value = true
 | 
			
		||||
    dialogTitle.value = '插活前'
 | 
			
		||||
  } else {
 | 
			
		||||
    message.success('成功')
 | 
			
		||||
    await getList()
 | 
			
		||||
    message.success('修改成功')
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -652,7 +653,7 @@ const addItemRow = (row) => {
 | 
			
		||||
          item.isOverProcess = 0
 | 
			
		||||
        }
 | 
			
		||||
        if (!item.id) {
 | 
			
		||||
          console.log(item)
 | 
			
		||||
    
 | 
			
		||||
          var type =
 | 
			
		||||
            'BLUEPRINT_WORKBLANK' == item.subType
 | 
			
		||||
              ? '毛坯'
 | 
			
		||||
@ -879,12 +880,19 @@ const resetQuery = () => {
 | 
			
		||||
  })
 | 
			
		||||
  // getList()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const route = useRoute()
 | 
			
		||||
const routeValue = ref('')
 | 
			
		||||
/** 初始化 **/
 | 
			
		||||
onMounted(async () => {
 | 
			
		||||
  try {
 | 
			
		||||
    // 取消注释并正确初始化
 | 
			
		||||
    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()
 | 
			
		||||
  } catch (error) {
 | 
			
		||||
    console.error('初始化失败:', error)
 | 
			
		||||
@ -893,6 +901,19 @@ onMounted(async () => {
 | 
			
		||||
    }, 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>
 | 
			
		||||
<style scoped>
 | 
			
		||||
.dialog-content {
 | 
			
		||||
 | 
			
		||||
@ -2407,11 +2407,11 @@ const submitForm = async () => {
 | 
			
		||||
    //   }
 | 
			
		||||
    //   //subData.id = subData.projectSubId
 | 
			
		||||
    // })
 | 
			
		||||
    reload()
 | 
			
		||||
    message.success(t('common.updateSuccess'))
 | 
			
		||||
    // 发送操作成功的事件
 | 
			
		||||
    // emit('success')
 | 
			
		||||
  } finally {
 | 
			
		||||
        reload()
 | 
			
		||||
    formLoading.value = false
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user