src/main/java/com/ruoyi/basic/service/CustomerFollowUpFileService.java
@@ -4,6 +4,7 @@ import com.ruoyi.basic.pojo.CustomerFollowUpFile; import com.ruoyi.common.vo.SimpleFileVo; import javax.annotation.Nullable; import javax.validation.constraints.NotNull; import javax.validation.constraints.Null; import java.util.List; @@ -29,7 +30,7 @@ * @param <T> */ <T> void fillAttachment( @Null List<T> list, @Nullable List<T> list, @NotNull Function<T, String> getAttachmentIds, @NotNull BiConsumer<T, List<SimpleFileVo>> setAttachmentList ); src/main/java/com/ruoyi/projectManagement/controller/PlanController.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,49 @@ package com.ruoyi.projectManagement.controller; import com.ruoyi.framework.web.domain.AjaxResult; import com.ruoyi.projectManagement.service.PlanService; import com.ruoyi.projectManagement.vo.SavePlanNodeVo; import com.ruoyi.projectManagement.vo.SavePlanVo; import com.ruoyi.projectManagement.vo.SearchPlanVo; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.AllArgsConstructor; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; import javax.validation.Valid; /** * @author buhuazhen * @date 2026/3/7 * @email 3038525872@qq.com */ @RestController @RequestMapping("/projectManagement/plan") @Api(value = "PlanController", tags = "项ç®ç®¡ç计å表(项ç®ç®¡çç±»å)") @RequiredArgsConstructor public class PlanController { private final PlanService planService; @PostMapping("/save") @ApiOperation("ä¿å") public AjaxResult save(@RequestBody @Valid SavePlanVo savePlanVo) { planService.savePlan(savePlanVo); return AjaxResult.success(); } @PostMapping("/delete/{id}") @ApiOperation("å é¤") public AjaxResult delete(@PathVariable Long id) { planService.deletePlan(id); return AjaxResult.success(); } @PostMapping("/listPage") @ApiOperation("å页å表") public AjaxResult listPage(@RequestBody SearchPlanVo searchPlanVo) { return AjaxResult.success(planService.searchPlan(searchPlanVo)); } } src/main/java/com/ruoyi/projectManagement/pojo/Plan.java
@@ -36,9 +36,9 @@ /** * 计åæè¿° */ @TableField(value = "describe") @TableField(value = "description") @ApiModelProperty(value="计åæè¿°") private String describe; private String description; /** * éä»¶ ,è¿è¡åå² @@ -73,12 +73,12 @@ */ @TableField(value = "create_user",fill = FieldFill.INSERT) @ApiModelProperty(value="å建人") private String createUser; private Integer createUser; /** * */ @TableField(value = "update_user",fill = FieldFill.INSERT_UPDATE) @ApiModelProperty(value="æ´æ°äºº") private String updateUser; private Integer updateUser; } src/main/java/com/ruoyi/projectManagement/pojo/PlanNode.java
@@ -1,10 +1,9 @@ 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 com.baomidou.mybatisplus.annotation.*; import java.io.Serializable; import java.time.LocalDateTime; import java.util.Date; import lombok.Data; @@ -19,72 +18,86 @@ * */ @TableId(type = IdType.AUTO) @TableField(value = "id") private Long id; /** * 对åºid */ @TableField(value = "project_management_plan_id") private Long projectManagementPlanId; /** * æåº */ @TableField(value = "sort") private Integer sort; /** * é¶æ®µåç§° */ @TableField(value = "name") private String name; /** * è´è´£ä»»ID */ @TableField(value = "leader_id") private Long leaderId; /** * è´è´£ä»»åç§° */ @TableField(value = "leader_name") private String leaderName; /** * é¢è®¡å·¥æ(天) */ @TableField(value = "estimated_duration") private Integer estimatedDuration; /** * * 工价 */ @TableField(value = "hourly_rate") private String hourlyRate; /** * ä½ä¸å 容 */ @TableField(value = "work_content") private String workContent; /** * */ @TableField(value = "is_delete") private Integer isDelete; /** * */ private Date createTime; @TableField(value = "create_time",fill = FieldFill.INSERT) private LocalDateTime createTime; /** * */ private Date updateTime; @TableField(value = "update_time",fill = FieldFill.INSERT_UPDATE) private LocalDateTime updateTime; /** * */ private String createUser; @TableField(value = "create_user",fill = FieldFill.INSERT) private Integer createUser; /** * */ private String updateUser; @TableField(value = "update_user",fill = FieldFill.INSERT_UPDATE) private Integer updateUser; @TableField(exist = false) private static final long serialVersionUID = 1L; src/main/java/com/ruoyi/projectManagement/service/PlanService.java
@@ -4,10 +4,13 @@ import com.ruoyi.projectManagement.pojo.Plan; import com.baomidou.mybatisplus.extension.service.IService; import com.ruoyi.projectManagement.vo.PlanVo; import com.ruoyi.projectManagement.vo.SavePlanNodeVo; import com.ruoyi.projectManagement.vo.SavePlanVo; import com.ruoyi.projectManagement.vo.SearchPlanVo; import javax.annotation.Nullable; import javax.validation.constraints.NotNull; import javax.validation.constraints.Null; import java.util.List; /** @@ -24,11 +27,19 @@ void savePlan(@NotNull SavePlanVo savePlanVo); /** * ä¿å计åèç¹ * @param planId * @param savePlanNodeVos */ void savePlanNode(@NotNull Long planId,@Nullable List<SavePlanNodeVo> savePlanNodeVos); /** * å é¤é¡¹ç®ç®¡ç计å * @param id */ void deletePlan(@NotNull Long id); void deletePlanNode(@Nullable List<Long> ids); IPage<PlanVo> searchPlan(@NotNull SearchPlanVo searchPlanVo); } src/main/java/com/ruoyi/projectManagement/service/impl/PlanServiceImpl.java
@@ -1,21 +1,32 @@ 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.PlanVo; import com.ruoyi.projectManagement.vo.SavePlanVo; import com.ruoyi.projectManagement.vo.SearchPlanVo; 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 @@ -31,6 +42,12 @@ private final CustomerFollowUpFileService customerFollowUpFileService; private final PlanNodeMapper planNodeMapper; @Lazy @Autowired private PlanService planService; @Override @Transactional(rollbackFor = Exception.class) public void savePlan(SavePlanVo savePlanVo) { @@ -38,18 +55,55 @@ // éä»¶å¤ç , æ¼æ¥ 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); } // todo@ èç¹ä¿å planService.savePlanNode(plan.getId(), savePlanVo.getSavePlanNodeList()); } @Override @Transactional(rollbackFor = Exception.class) public void savePlanNode(Long planId, @Nullable List<SavePlanNodeVo> savePlanNodeVos) { Assert.notNull(planId, () -> new ServiceException("计åIDä¸è½ä¸ºç©º")); if (CollUtil.isEmpty(savePlanNodeVos)) { return; } // å é¤å¤ä½èç¹ List<PlanNode> needDeleteNode = planNodeMapper.selectList(new LambdaQueryWrapper<PlanNode>() .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<PlanNode> 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<PlanNode> getPlanNodeByPlanId(Long planId) { return planNodeMapper.selectList(new LambdaQueryWrapper<PlanNode>() .eq(PlanNode::getIsDelete, 0) .eq(PlanNode::getProjectManagementPlanId, planId)); } private List<PlanNode> getPlanNodeByPlanIds(List<Long> planIds) { return planNodeMapper.selectList(new LambdaQueryWrapper<PlanNode>() .eq(PlanNode::getIsDelete, 0) .in(PlanNode::getProjectManagementPlanId, planIds)); } @Override @Transactional(rollbackFor = Exception.class) @@ -58,9 +112,18 @@ new LambdaUpdateWrapper<Plan>() .eq(Plan::getId, id) .set(Plan::getIsDelete, 1)); // todo@ 对åºèç¹å ¨é¨å é¤ planService.deletePlanNode(getPlanNodeByPlanId(id).stream().map(PlanNode::getId).collect(Collectors.toList())); } @Override @Transactional(rollbackFor = Exception.class) public void deletePlanNode(List<Long> ids) { if (CollUtil.isNotEmpty(ids)) { planNodeMapper.update(null, new LambdaUpdateWrapper<PlanNode>() .in(PlanNode::getId, ids) .set(PlanNode::getIsDelete, 1)); } } @Override @@ -69,8 +132,11 @@ IPage<PlanVo> resultPage = planIPage.convert(plan -> BeanUtil.copyProperties(plan, PlanVo.class)); // æä»¶è·å customerFollowUpFileService.fillAttachment(resultPage.getRecords(), PlanVo::getAttachment, PlanVo::setAttachmentList); // todo@ node èç¹è·å Map<Long, List<PlanNodeVo>> 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; } src/main/java/com/ruoyi/projectManagement/vo/PlanNodeVo.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,35 @@ package com.ruoyi.projectManagement.vo; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.io.Serializable; /** * @author buhuazhen * @date 2026/3/7 * @email 3038525872@qq.com */ @Data @AllArgsConstructor @NoArgsConstructor public class PlanNodeVo implements Serializable { private Long id; private Long projectManagementPlanId; private Integer sort; private String name; private Long leaderId; private String leaderName; private Integer estimatedDuration; private String hourlyRate; private String workContent; } src/main/java/com/ruoyi/projectManagement/vo/PlanVo.java
@@ -1,10 +1,12 @@ package com.ruoyi.projectManagement.vo; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonIgnore; import com.ruoyi.common.vo.SimpleFileVo; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.springframework.format.annotation.DateTimeFormat; import java.io.Serializable; import java.time.LocalDateTime; @@ -25,7 +27,7 @@ private String name; private String describe; private String description; // éä»¶ private List<SimpleFileVo> attachmentList; @@ -33,8 +35,14 @@ @JsonIgnore private String attachment; @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime createTime; @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime updateTime; private List<PlanNodeVo> planNodeList; } src/main/java/com/ruoyi/projectManagement/vo/SavePlanNodeVo.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,41 @@ package com.ruoyi.projectManagement.vo; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import java.io.Serializable; /** * @author buhuazhen * @date 2026/3/7 * @email 3038525872@qq.com */ @Data @AllArgsConstructor @NoArgsConstructor public class SavePlanNodeVo implements Serializable { private Long id; private Long projectManagementPlanId; private Integer sort; @NotBlank private String name; @NotNull private Long leaderId; @NotBlank private String leaderName; private Integer estimatedDuration; private String hourlyRate; private String workContent; } src/main/java/com/ruoyi/projectManagement/vo/SavePlanVo.java
@@ -4,6 +4,7 @@ import lombok.Data; import lombok.NoArgsConstructor; import javax.validation.Valid; import javax.validation.constraints.NotBlank; import java.io.Serializable; import java.util.List; @@ -22,10 +23,11 @@ @NotBlank private String name; @NotBlank private String describe; private String description; private List<String> attachmentIds; @Valid private List<SavePlanNodeVo> savePlanNodeList; } src/main/resources/mapper/projectManagement/PlanMapper.xml
@@ -7,17 +7,17 @@ <resultMap id="BaseResultMap" type="com.ruoyi.projectManagement.pojo.Plan"> <id property="id" column="id" jdbcType="BIGINT"/> <result property="name" column="name" jdbcType="VARCHAR"/> <result property="describe" column="describe" jdbcType="VARCHAR"/> <result property="description" column="description" jdbcType="VARCHAR"/> <result property="attachment" column="attachment" jdbcType="VARCHAR"/> <result property="is_delete" column="is_delete" jdbcType="INTEGER"/> <result property="create_time" column="create_time" jdbcType="TIMESTAMP"/> <result property="update_time" column="update_time" jdbcType="TIMESTAMP"/> <result property="create_user" column="create_user" jdbcType="VARCHAR"/> <result property="update_user" column="update_user" jdbcType="VARCHAR"/> <result property="isDelete" column="is_delete" jdbcType="INTEGER"/> <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/> <result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/> <result property="createUser" column="create_user" jdbcType="VARCHAR"/> <result property="updateUser" column="update_user" jdbcType="VARCHAR"/> </resultMap> <sql id="Base_Column_List"> id,name,describe, id,name,description, attachment,is_delete,create_time, update_time,create_user,update_user </sql> @@ -25,6 +25,7 @@ <select id="selectPlanPage" resultMap="BaseResultMap"> select t1.* from project_management_plan as t1 where t1.is_delete = 0 order by t1.create_time desc </select> </mapper>