package com.ruoyi.projectManagement.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.ruoyi.basic.service.CustomerFollowUpFileService; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.projectManagement.mapper.PlanMapper; import com.ruoyi.projectManagement.mapper.PlanNodeMapper; import com.ruoyi.projectManagement.pojo.Plan; import com.ruoyi.projectManagement.pojo.PlanNode; import com.ruoyi.projectManagement.service.PlanService; import com.ruoyi.projectManagement.vo.*; import lombok.RequiredArgsConstructor; import org.jetbrains.annotations.Nullable; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.IntStream; /** * @author buhuazhen * @description 项目管理计划的实现 * @createDate 2026-03-06 15:29:26 */ @Service @RequiredArgsConstructor @Transactional(readOnly = true) public class PlanServiceImpl implements PlanService { private final PlanMapper planMapper; private final CustomerFollowUpFileService customerFollowUpFileService; private final PlanNodeMapper planNodeMapper; @Lazy @Autowired private PlanService planService; @Override @Transactional(rollbackFor = Exception.class) public void savePlan(SavePlanVo savePlanVo) { Plan plan = BeanUtil.copyProperties(savePlanVo, Plan.class); // 附件处理 , 拼接 String attachments = String.join(",", Optional.ofNullable(savePlanVo.getAttachmentIds()).orElse(Collections.emptyList())); plan.setAttachment(attachments); if (savePlanVo.getId() == null) { planMapper.insert(plan); } else { planMapper.updateById(plan); } planService.savePlanNode(plan.getId(), savePlanVo.getSavePlanNodeList()); } @Override @Transactional(rollbackFor = Exception.class) public void savePlanNode(Long planId, @Nullable List savePlanNodeVos) { Assert.notNull(planId, () -> new ServiceException("计划ID不能为空")); if (CollUtil.isEmpty(savePlanNodeVos)) { return; } // 删除多余节点 List needDeleteNode = planNodeMapper.selectList(new LambdaQueryWrapper() .select(PlanNode::getId) .eq(PlanNode::getProjectManagementPlanId, planId) .ne(PlanNode::getId, savePlanNodeVos.get(0).getId()) .notIn(PlanNode::getId, savePlanNodeVos.stream().map(SavePlanNodeVo::getId).collect(Collectors.toList()))); deletePlanNode(needDeleteNode.stream().map(PlanNode::getId).collect(Collectors.toList())); List planNodes = BeanUtil.copyToList(savePlanNodeVos, PlanNode.class); // 设置排序索引 IntStream.range(0, savePlanNodeVos.size()).forEach(i -> { planNodes.get(i).setSort(i); planNodes.get(i).setProjectManagementPlanId(planId); if (planNodes.get(i).getId() == null) { planNodeMapper.insert(planNodes.get(i)); } else { planNodeMapper.updateById(planNodes.get(i)); } }); } private List getPlanNodeByPlanId(Long planId) { return planNodeMapper.selectList(new LambdaQueryWrapper() .eq(PlanNode::getIsDelete, 0) .eq(PlanNode::getProjectManagementPlanId, planId)); } private List getPlanNodeByPlanIds(List planIds) { return planNodeMapper.selectList(new LambdaQueryWrapper() .eq(PlanNode::getIsDelete, 0) .in(PlanNode::getProjectManagementPlanId, planIds)); } @Override @Transactional(rollbackFor = Exception.class) public void deletePlan(Long id) { planMapper.update(null, new LambdaUpdateWrapper() .eq(Plan::getId, id) .set(Plan::getIsDelete, 1)); planService.deletePlanNode(getPlanNodeByPlanId(id).stream().map(PlanNode::getId).collect(Collectors.toList())); } @Override @Transactional(rollbackFor = Exception.class) public void deletePlanNode(List ids) { if (CollUtil.isNotEmpty(ids)) { planNodeMapper.update(null, new LambdaUpdateWrapper() .in(PlanNode::getId, ids) .set(PlanNode::getIsDelete, 1)); } } @Override public IPage searchPlan(SearchPlanVo searchPlanVo) { IPage planIPage = planMapper.selectPlanPage(searchPlanVo); IPage resultPage = planIPage.convert(plan -> BeanUtil.copyProperties(plan, PlanVo.class)); // 文件获取 customerFollowUpFileService.fillAttachment(resultPage.getRecords(), PlanVo::getAttachment, PlanVo::setAttachmentList); Map> collect = getPlanNodeByPlanIds(resultPage.getRecords().stream().map(PlanVo::getId).collect(Collectors.toList())) .stream() .map(it -> BeanUtil.copyProperties(it, PlanNodeVo.class)) .collect(Collectors.groupingBy(PlanNodeVo::getProjectManagementPlanId, Collectors.toList())); resultPage.getRecords().forEach(planVo -> planVo.setPlanNodeList(collect.getOrDefault(planVo.getId(), Collections.emptyList()))); return resultPage; } }