src/main/java/com/ruoyi/projectManagement/controller/InfoController.java
@@ -1,8 +1,11 @@ package com.ruoyi.projectManagement.controller; import com.ruoyi.framework.web.domain.AjaxResult; import com.ruoyi.projectManagement.dto.InfoStageDto; import com.ruoyi.projectManagement.dto.UpdateStateInfo; import com.ruoyi.projectManagement.service.InfoService; import com.ruoyi.projectManagement.service.impl.handle.InfoStageHandleService; import com.ruoyi.projectManagement.vo.SaveInfoStageVo; import com.ruoyi.projectManagement.vo.SaveInfoVo; import com.ruoyi.projectManagement.vo.SearchInfoVo; import io.swagger.annotations.Api; @@ -24,6 +27,7 @@ public class InfoController { private final InfoService infoService; private final InfoStageHandleService infoStageHandleService; @PostMapping("/save") @ApiOperation("ä¿å") @@ -59,5 +63,25 @@ return AjaxResult.success(infoService.getInfoById(id)); } @PostMapping("/saveStage") @ApiOperation("ä¿åé¶æ®µ") public AjaxResult saveStage(@RequestBody @Valid SaveInfoStageVo dto) { infoStageHandleService.save(dto); return AjaxResult.success(); } @PostMapping("/listStage/{id}") @ApiOperation("åè¡¨é¶æ®µ") public AjaxResult listStage(@PathVariable Long id) { return AjaxResult.success(infoStageHandleService.getListVoByInfoId(id)); } @PostMapping("/deleteStage/{id}") @ApiOperation("å é¤é¶æ®µ") public AjaxResult deleteStage(@PathVariable Long id) { infoStageHandleService.deleteById(id); return AjaxResult.success(); } } src/main/java/com/ruoyi/projectManagement/dto/InfoStageDto.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,92 @@ package com.ruoyi.projectManagement.dto; import com.fasterxml.jackson.annotation.JsonFormat; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.springframework.format.annotation.DateTimeFormat; import javax.validation.constraints.NotNull; import java.time.LocalDate; import java.time.LocalDateTime; /** * @author buhuazhen * @date 2026/3/11 * @email 3038525872@qq.com */ @Data @AllArgsConstructor @NoArgsConstructor public class InfoStageDto implements java.io.Serializable { private Long id; /** * 对åºè®¡åèç¹id */ @NotNull(message = "对åºè®¡åèç¹projectManagementPlanNodeIdä¸è½ä¸ºç©º") private Long projectManagementPlanNodeId; /** * 对åºé¡¹ç®id */ @NotNull(message = "对åºé¡¹ç®projectManagementInfoIdä¸è½ä¸ºç©º") private Long projectManagementInfoId; /** * æè¿° */ private String description; /** * å®é è´è´£äººid */ private Long actuallyLeaderId; /** * å®é è´è´£äººåç§° */ private String actuallyLeaderName; /** * é¢è®¡å·¥æ */ private Integer estimatedDuration; /** * 计åå¼å§ */ @JsonFormat(pattern = "yyyy-MM-dd") @DateTimeFormat(pattern = "yyyy-MM-dd") private LocalDate planStartTime; /** * è¿åº¦ */ private Integer progress; /** * å®é å¼å§æ¶é´ */ @JsonFormat(pattern = "yyyy-MM-dd") @DateTimeFormat(pattern = "yyyy-MM-dd") private LocalDate actualStartTime; /** * å®é ç»ææ¶é´ */ @JsonFormat(pattern = "yyyy-MM-dd") @DateTimeFormat(pattern = "yyyy-MM-dd") private LocalDate actualEndTime; /** * å建æ¶é´ */ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime createTime; private String attachment; } src/main/java/com/ruoyi/projectManagement/dto/PlanStageDto.java
@@ -19,4 +19,6 @@ private Long id; private String name; private PlanStageEnum planStageEnum; private Integer sort; private Integer estimatedDuration; // é¢è®¡å·¥æ } src/main/java/com/ruoyi/projectManagement/mapper/InfoStageMapper.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,18 @@ package com.ruoyi.projectManagement.mapper; import com.ruoyi.projectManagement.pojo.InfoStage; import com.baomidou.mybatisplus.core.mapper.BaseMapper; /** * @author buhuazhen * @description é对表ãproject_management_info_stage(项ç®é¶æ®µ)ãçæ°æ®åºæä½Mapper * @createDate 2026-03-11 10:28:27 * @Entity com.ruoyi.projectManagement.pojo.InfoStage */ public interface InfoStageMapper extends BaseMapper<InfoStage> { } src/main/java/com/ruoyi/projectManagement/pojo/InfoStage.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,141 @@ package com.ruoyi.projectManagement.pojo; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import java.io.Serializable; import java.time.LocalDate; import java.time.LocalDateTime; import lombok.Data; /** * 项ç®é¶æ®µ * @TableName project_management_info_stage */ @TableName(value ="project_management_info_stage") @Data public class InfoStage implements Serializable { /** * */ @TableId(value = "id", type = IdType.AUTO) private Long id; /** * 对åºè®¡åèç¹id */ @TableField(value = "project_management_plan_node_id") private Long projectManagementPlanNodeId; /** * 对åºé¡¹ç®id */ @TableField(value = "project_management_info_id") private Long projectManagementInfoId; /** * æè¿° */ @TableField(value = "description") private String description; /** * å®é è´è´£äººid */ @TableField(value = "actually_leader_id") private Long actuallyLeaderId; /** * å®é è´è´£äººåç§° */ @TableField(value = "actually_leader_name") private String actuallyLeaderName; /** * é¢è®¡å·¥æ */ @TableField(value = "estimated_duration") private Integer estimatedDuration; /** * 计åå¼å§ */ @TableField(value = "plan_start_time") private LocalDate planStartTime; /** * 计åç»æ */ @TableField(value = "plan_end_time") private LocalDate planEndTime; /** * è¿åº¦ */ @TableField(value = "progress") private Integer progress; /** * å®é å¼å§æ¶é´ */ @TableField(value = "actual_start_time") private LocalDate actualStartTime; /** * å®é ç»ææ¶é´ */ @TableField(value = "actual_end_time") private LocalDate actualEndTime; /** * éä»¶ */ @TableField(value = "attachment") private String attachment; /** * */ @TableField(value = "create_time") private LocalDateTime createTime; /** * */ @TableField(value = "update_time") private LocalDateTime updateTime; /** * */ @TableField(value = "is_delete") private Integer isDelete; /** * */ @TableField(value = "create_user") private Long createUser; /** * */ @TableField(value = "update_user") private Long updateUser; /** * */ @TableField(value = "create_user_name") private String createUserName; /** * */ @TableField(value = "update_user_name") private String updateUserName; @TableField(exist = false) private static final long serialVersionUID = 1L; } src/main/java/com/ruoyi/projectManagement/service/impl/handle/InfoHandleService.java
@@ -4,10 +4,12 @@ import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.google.common.collect.Lists; import com.ruoyi.basic.service.CustomerFollowUpFileService; import com.ruoyi.common.enums.PlanStageEnum; import com.ruoyi.common.enums.ReviewStatusEnum; import com.ruoyi.projectManagement.dto.InfoStageDto; import com.ruoyi.projectManagement.dto.PlanStageDto; import com.ruoyi.projectManagement.dto.SaveInfoDto; import com.ruoyi.projectManagement.mapper.InfoMapper; @@ -68,6 +70,11 @@ return info.getId(); } @Transactional public void updateById(@NotNull Info info){ infoMapper.updateById(info); } public SaveInfoDto getInfoById(@NotNull Long id) { Info info = infoMapper.selectById(id); return convert(info); @@ -99,7 +106,7 @@ private List<PlanStageDto> getPlanStageList(@NotNull Long planId) { List<PlanNode> planNodeByPlanId = planService.getPlanNodeByPlanId(planId); return planNodeByPlanId.stream().map(it -> new PlanStageDto(it.getId(), it.getName(), PlanStageEnum.TO_BEGIN)).collect(Collectors.toList()); return planNodeByPlanId.stream().map(it -> new PlanStageDto(it.getId(), it.getName(), PlanStageEnum.TO_BEGIN, it.getSort(), it.getEstimatedDuration())).collect(Collectors.toList()); } src/main/java/com/ruoyi/projectManagement/service/impl/handle/InfoStageHandleService.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,161 @@ package com.ruoyi.projectManagement.service.impl.handle; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.ruoyi.basic.service.CustomerFollowUpFileService; import com.ruoyi.common.enums.IsDeleteEnum; import com.ruoyi.common.enums.PlanStageEnum; import com.ruoyi.projectManagement.dto.InfoStageDto; import com.ruoyi.projectManagement.dto.PlanStageDto; import com.ruoyi.projectManagement.dto.SaveInfoDto; import com.ruoyi.projectManagement.mapper.InfoStageMapper; import com.ruoyi.projectManagement.pojo.Info; import com.ruoyi.projectManagement.pojo.InfoStage; import com.ruoyi.projectManagement.vo.InfoStageVo; import com.ruoyi.projectManagement.vo.SaveInfoStageVo; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import javax.validation.constraints.NotNull; import java.util.*; import java.util.stream.Collectors; /** * @author buhuazhen * @date 2026/3/11 * @email 3038525872@qq.com */ @Component @RequiredArgsConstructor @Transactional(rollbackFor = Exception.class, readOnly = true) public class InfoStageHandleService { private final InfoStageMapper infoStageMapper; private final InfoHandleService infoHandleService; private final CustomerFollowUpFileService customerFollowUpFileService; @Autowired @Lazy private InfoStageHandleService infoStageHandleService; @Transactional public void save(@NotNull SaveInfoStageVo saveInfoStageVo) { InfoStage infoStage = BeanUtil.copyProperties(saveInfoStageVo, InfoStage.class); // éä»¶å¤ç String attachmentIds = StrUtil.join(",", Optional.ofNullable(saveInfoStageVo.getAttachmentIds()).orElse(Collections.emptyList())); infoStage.setAttachment(attachmentIds); if (infoStage.getId() == null) { infoStageMapper.insert(infoStage); } else { infoStageMapper.updateById(infoStage); } infoStageHandleService.syncInfoStage(infoStage.getProjectManagementInfoId()); } /** * 忥项ç®é¶æ®µç¶æ * * @param infoId */ @Transactional public void syncInfoStage(@NotNull Long infoId) { SaveInfoDto infoById = infoHandleService.getInfoById(infoId); List<PlanStageDto> planStage = infoById.getPlanStage(); // è·å便§åå¨çé¶æ®µä¿¡æ¯ List<InfoStageDto> infoStageNow = getListDtoByInfoId(infoId); Map<Long, Integer> maxProgressMap = infoStageNow.stream() .filter(e -> e.getProjectManagementPlanNodeId() != null) .collect(Collectors.toMap( InfoStageDto::getProjectManagementPlanNodeId, e -> Optional.ofNullable(e.getProgress()).orElse(0), Integer::max )); for (PlanStageDto stage : planStage) { int progress = maxProgressMap.getOrDefault(stage.getId(), 0); stage.setPlanStageEnum(calcStage(progress)); } // è¿è¡è°æ´ Info info = new Info(); info.setId(infoId); info.setPlanStage(planStage); infoHandleService.updateById(info); } private PlanStageEnum calcStage(int progress) { if (progress <= 0) { return PlanStageEnum.TO_BEGIN; } else if (progress < 100) { return PlanStageEnum.ON_GOING; } return PlanStageEnum.ENDED; } @Transactional(rollbackFor = Exception.class) public void deleteById(@NotNull Long id) { InfoStage infoStage = infoStageMapper.selectById(id); if (infoStage == null) { return; } LambdaUpdateWrapper<InfoStage> updateWrapper = new LambdaUpdateWrapper<InfoStage>(); updateWrapper.eq(InfoStage::getId, id); updateWrapper.set(InfoStage::getIsDelete, IsDeleteEnum.DELETED.getCode()); infoStageMapper.update(null, updateWrapper); infoStageHandleService.syncInfoStage(infoStage.getProjectManagementInfoId()); } public List<InfoStageDto> getListDtoByInfoId(@NotNull Long infoId) { LambdaQueryWrapper<InfoStage> queryWrapper = new LambdaQueryWrapper<InfoStage>(); queryWrapper.eq(InfoStage::getProjectManagementInfoId, infoId); queryWrapper.eq(InfoStage::getIsDelete, IsDeleteEnum.NOT_DELETED.getCode()); List<InfoStageDto> infoStageDtos = BeanUtil.copyToList(infoStageMapper.selectList(queryWrapper), InfoStageDto.class); /* * è¿è¡æåº å æç §å¯¹åºçsortè¿è¡æåºï¼åæç §å建æ¶é´æåº * å¯è½ä¼åºç°å鍿 åµ æ¯å¦ * ç«é¡¹ 100% * ç«é¡¹ 50% è¿ç§æ åµï¼å½ç¶ä¹æ¯æä¿®æ¹æä½ */ SaveInfoDto infoById = infoHandleService.getInfoById(infoId); List<PlanStageDto> planStage = infoById.getPlanStage(); // æå»º id -> sort æ å° Map<Long, Integer> stageSortMap = planStage.stream() .collect(Collectors.toMap( PlanStageDto::getId, PlanStageDto::getSort )); // æåº infoStageDtos.sort( Comparator // å æé¶æ®µæåº .comparing((InfoStageDto dto) -> stageSortMap.getOrDefault(dto.getProjectManagementPlanNodeId(), Integer.MAX_VALUE) ) // åæå建æ¶é´æåº .thenComparing(InfoStageDto::getCreateTime) ); return infoStageDtos; } public List<InfoStageVo> getListVoByInfoId(@NotNull Long infoId) { List<InfoStageDto> listByInfoId = getListDtoByInfoId(infoId); List<InfoStageVo> infoStageVos = BeanUtil.copyToList(listByInfoId, InfoStageVo.class); // å¤çéä»¶ customerFollowUpFileService.fillAttachment(infoStageVos, InfoStageVo::getAttachment, InfoStageVo::setAttachmentList); return infoStageVos; } } src/main/java/com/ruoyi/projectManagement/vo/InfoStageVo.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,24 @@ package com.ruoyi.projectManagement.vo; import com.ruoyi.common.vo.SimpleFileVo; import com.ruoyi.projectManagement.dto.InfoStageDto; import lombok.AllArgsConstructor; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import java.util.List; /** * @author buhuazhen * @date 2026/3/11 * @email 3038525872@qq.com */ @EqualsAndHashCode(callSuper = true) @Data @AllArgsConstructor @NoArgsConstructor public class InfoStageVo extends InfoStageDto implements java.io.Serializable { private List<SimpleFileVo> attachmentList; // éä»¶å表 } src/main/java/com/ruoyi/projectManagement/vo/ListInfoVo.java
@@ -1,6 +1,7 @@ package com.ruoyi.projectManagement.vo; import com.fasterxml.jackson.annotation.JsonFormat; import com.ruoyi.projectManagement.dto.PlanStageDto; import com.ruoyi.projectManagement.dto.SaveInfoDto; import lombok.AllArgsConstructor; import lombok.Data; @@ -10,6 +11,7 @@ import java.io.Serializable; import java.time.LocalDateTime; import java.util.List; /** * 页é¢åè¡¨ä¿¡æ¯ @@ -39,4 +41,6 @@ private String createUserName; // å建人åç§° private String updateUserName; // æ´æ°äººåç§° // å ¨é¨é¶æ®µä¿¡æ¯ private List<PlanStageDto> planStage; } src/main/java/com/ruoyi/projectManagement/vo/SaveInfoStageVo.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,28 @@ package com.ruoyi.projectManagement.vo; import com.baomidou.mybatisplus.annotation.TableField; import com.fasterxml.jackson.annotation.JsonFormat; import com.ruoyi.projectManagement.dto.InfoStageDto; import lombok.AllArgsConstructor; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDate; import java.util.List; /** * @author buhuazhen * @date 2026/3/11 * @email 3038525872@qq.com */ @EqualsAndHashCode(callSuper = true) @Data @AllArgsConstructor @NoArgsConstructor public class SaveInfoStageVo extends InfoStageDto implements java.io.Serializable { private List<String> attachmentIds; } src/main/resources/mapper/projectManagement/InfoMapper.xml
@@ -48,7 +48,14 @@ department_name,order_date,order_amount, remark,attachment </sql> <select id="searchListInfo" resultType="com.ruoyi.projectManagement.vo.ListInfoVo"> <resultMap id="ListInfoVoMap" type="com.ruoyi.projectManagement.vo.ListInfoVo"> <result column="plan_stage" property="planStage" typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"/> </resultMap> <select id="searchListInfo" resultMap="ListInfoVoMap"> select t1.*, t2.name as project_management_plan_name,t3.title as projectManagementInfoParentName from project_management_info as t1 left join project_management_plan as t2 on t1.project_management_plan_id = t2.id src/main/resources/mapper/projectManagement/InfoStageMapper.xml
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,42 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ruoyi.projectManagement.mapper.InfoStageMapper"> <resultMap id="BaseResultMap" type="com.ruoyi.projectManagement.pojo.InfoStage"> <id property="id" column="id" jdbcType="BIGINT"/> <result property="projectManagementPlanNodeId" column="project_management_plan_node_id" jdbcType="BIGINT"/> <result property="projectManagementInfoId" column="project_management_info_id" jdbcType="BIGINT"/> <result property="description" column="description" jdbcType="VARCHAR"/> <result property="actuallyLeaderId" column="actually_leader_id" jdbcType="BIGINT"/> <result property="actuallyLeaderName" column="actually_leader_name" jdbcType="VARCHAR"/> <result property="estimatedDuration" column="estimated_duration" jdbcType="INTEGER"/> <result property="planStartTime" column="plan_start_time" jdbcType="DATE"/> <result property="planEndTime" column="plan_end_time" jdbcType="DATE"/> <result property="actualStartTime" column="actual_start_time" jdbcType="DATE"/> <result property="actualEndTime" column="actual_end_time" jdbcType="DATE"/> <result property="progress" column="progress" jdbcType="INTEGER"/> <result property="actuallyStartTime" column="actually_start_time" jdbcType="DATE"/> <result property="actuallyEndTime" column="actually_end_time" jdbcType="DATE"/> <result property="attachment" column="attachment" jdbcType="VARCHAR"/> <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/> <result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/> <result property="isDelete" column="is_delete" jdbcType="INTEGER"/> <result property="createUser" column="create_user" jdbcType="BIGINT"/> <result property="updateUser" column="update_user" jdbcType="BIGINT"/> <result property="createUserName" column="create_user_name" jdbcType="VARCHAR"/> <result property="updateUserName" column="update_user_name" jdbcType="VARCHAR"/> </resultMap> <sql id="Base_Column_List"> id,project_management_plan_node_id,project_management_info_id, description,actually_leader_id,actually_leader_name, estimated_duration,plan_start_time,plan_end_time, actual_start_time,actual_end_time,progress, actually_start_time,actually_end_time,attachment, create_time,update_time,is_delete, create_user,update_user,create_user_name, update_user_name </sql> </mapper>