yanghao 1 week ago
parent
commit
c70a840119

+ 9 - 2
yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/controller/admin/researchProject/vo/ProjectPageReqVO.java

@@ -8,6 +8,7 @@ import lombok.ToString;
 import org.springframework.format.annotation.DateTimeFormat;
 
 import java.time.LocalDateTime;
+import java.util.List;
 
 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
 
@@ -20,8 +21,8 @@ public class ProjectPageReqVO extends PageParam {
     @Schema(description = "项目级别", example = "国家级")
     private String projectLevel;
 
-    @Schema(description = "执行单位", example = "某某研究院")
-    private String executingUnit;
+    @Schema(description = "执行单位(部门ID数组)", example = "[100, 200]")
+    private List<Long> executingUnit;
 
     @Schema(description = "项目名称", example = "智能仓储系统")
     private String projectName;
@@ -57,4 +58,10 @@ public class ProjectPageReqVO extends PageParam {
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
     private LocalDateTime[] createTime;
 
+    @Schema(description = "正式审批状态:0未提交 1审批中 2通过 3驳回")
+    private Integer formalAuditStatus;
+
+    @Schema(description = "预审状态:0未提交 1审批中 2通过 3驳回")
+    private Integer preAuditStatus;
+
 }

+ 9 - 3
yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/controller/admin/researchProject/vo/ProjectRespVO.java

@@ -7,6 +7,7 @@ import java.math.BigDecimal;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.util.List;
+import com.fasterxml.jackson.annotation.JsonFormat;
 
 @Schema(description = "管理后台 - 项目立项 Response VO")
 @Data
@@ -24,10 +25,10 @@ public class ProjectRespVO {
     @Schema(description = "项目级别", example = "国家级")
     private String projectLevel;
 
-    @Schema(description = "执行单位(部门ID)", example = "100")
-    private Long executingUnit;
+    @Schema(description = "执行单位(部门ID数组)", example = "[100, 200]")
+    private List<Long> executingUnit;
 
-    @Schema(description = "执行单位名称", example = "XX石油技术公司")
+    @Schema(description = "执行单位名称(多个用逗号分隔)", example = "XX研究院, YY研究院")
     private String executingUnitName;
 
     @Schema(description = "项目名称", example = "智能仓储系统")
@@ -39,6 +40,10 @@ public class ProjectRespVO {
     @Schema(description = "项目组成员(多个逗号分隔)", example = "张三,李四,王五")
     private String teamMembers;
 
+    @Schema(description = "计划结题时间", example = "2027-03-01")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private LocalDate planEndDate;
+
     @Schema(description = "项目类型", example = "研发类")
     private String projectType;
 
@@ -128,6 +133,7 @@ public class ProjectRespVO {
         private String workPlan;
 
         @Schema(description = "截止时间", example = "2026-10-01")
+        @JsonFormat(pattern = "yyyy-MM-dd")
         private LocalDate deadline;
 
         @Schema(description = "排序值", example = "0")

+ 7 - 3
yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/controller/admin/researchProject/vo/ProjectSaveReqVO.java

@@ -7,6 +7,7 @@ import javax.validation.constraints.NotEmpty;
 import javax.validation.constraints.NotNull;
 import javax.validation.constraints.Size;
 import java.util.List;
+import java.time.LocalDate;
 
 @Schema(description = "管理后台 - 项目立项新增/修改 Request VO")
 @Data
@@ -22,9 +23,9 @@ public class ProjectSaveReqVO {
     @NotEmpty(message = "项目级别不能为空")
     private String projectLevel;
 
-    @Schema(description = "执行单位(部门ID)", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
-    @NotNull(message = "执行单位不能为空")
-    private Long executingUnit;
+    @Schema(description = "执行单位(部门ID数组)", example = "[100, 200]")
+    @NotEmpty(message = "执行单位不能为空")
+    private List<Long> executingUnit;
 
     @Schema(description = "项目名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "智能仓储系统")
     @NotEmpty(message = "项目名称不能为空")
@@ -66,6 +67,9 @@ public class ProjectSaveReqVO {
     @Schema(description = "备注", example = "你说的对")
     private String remark;
 
+    @Schema(description = "计划结题时间", example = "2027-03-01")
+    private LocalDate planEndDate;
+
     // ==================== 子表数据 ====================
 
     @Schema(description = "进度安排列表")

+ 5 - 4
yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/dal/dataobject/researchProject/ProjectDO.java

@@ -39,10 +39,11 @@ public class ProjectDO extends BaseDO {
      * 项目级别
      */
     private String projectLevel;
-    /**
-     * 执行单位
-     */
-    private Long executingUnit;
+
+    /** 执行单位(部门ID数组) */
+    @TableField(typeHandler = JacksonTypeHandler.class)
+    private List<Long> executingUnit;
+
     /**
      * 项目名称
      */

+ 15 - 2
yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/dal/mysql/researchProject/ProjectMapper.java

@@ -7,6 +7,8 @@ import cn.iocoder.yudao.module.rd.controller.admin.researchProject.vo.ProjectPag
 import cn.iocoder.yudao.module.rd.dal.dataobject.researchProject.ProjectDO;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Select;
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.json.JSONUtil;
 
 
 
@@ -36,14 +38,25 @@ public interface ProjectMapper extends BaseMapperX<ProjectDO> {
      * @param reqVO 查询条件
      */
     default LambdaQueryWrapperX<ProjectDO> buildCommonQuery(ProjectPageReqVO reqVO) {
-        return new LambdaQueryWrapperX<ProjectDO>()
+        LambdaQueryWrapperX<ProjectDO> wrapper = new LambdaQueryWrapperX<ProjectDO>()
                 .likeIfPresent(ProjectDO::getProjectName, reqVO.getProjectName())
                 .eqIfPresent(ProjectDO::getProjectLevel, reqVO.getProjectLevel())
-                .eqIfPresent(ProjectDO::getExecutingUnit, reqVO.getExecutingUnit())   // ⭐ 改成 eqIfPresent
                 .eqIfPresent(ProjectDO::getProjectLeader, reqVO.getProjectLeader())
                 .eqIfPresent(ProjectDO::getProjectType, reqVO.getProjectType())
                 .eqIfPresent(ProjectDO::getStatus, reqVO.getStatus())
+                .eqIfPresent(ProjectDO::getPreAuditStatus, reqVO.getPreAuditStatus())
+                .eqIfPresent(ProjectDO::getFormalAuditStatus, reqVO.getFormalAuditStatus())
                 .betweenIfPresent(ProjectDO::getCreateTime, reqVO.getCreateTime());
+
+        // ⭐ 执行单位:多选(JSON 数组匹配)
+        if (CollUtil.isNotEmpty(reqVO.getExecutingUnit())) {
+            // MySQL 8.0 用 JSON_OVERLAPS(推荐)
+            String jsonStr = JSONUtil.toJsonStr(reqVO.getExecutingUnit());
+            wrapper.apply("JSON_OVERLAPS(executing_unit, CAST({0} AS JSON))", jsonStr);
+
+        }
+
+        return wrapper;
     }
 
     /**

+ 12 - 5
yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/service/researchProject/ResearchProjectServiceImpl.java

@@ -61,17 +61,19 @@ public class ResearchProjectServiceImpl implements ResearchProjectService {
         if (CollUtil.isEmpty(list)) {
             return;
         }
-        // 1. 收集所有需要的部门 id
+        // 1. 收集所有部门 id
         Set<Long> deptIds = new HashSet<>();
         for (ProjectRespVO vo : list) {
             if (vo.getDeptId() != null) deptIds.add(vo.getDeptId());
-            if (vo.getExecutingUnit() != null) deptIds.add(vo.getExecutingUnit());
+            if (CollUtil.isNotEmpty(vo.getExecutingUnit())) {
+                deptIds.addAll(vo.getExecutingUnit());   // ⭐ List 全部加进去
+            }
         }
         if (deptIds.isEmpty()) {
             return;
         }
 
-        // 2. 一次批量查
+        // 2. 批量查
         Map<Long, String> deptNameMap = getDeptNameMap(deptIds);
 
         // 3. 回填
@@ -79,8 +81,13 @@ public class ResearchProjectServiceImpl implements ResearchProjectService {
             if (vo.getDeptId() != null) {
                 vo.setDeptName(deptNameMap.get(vo.getDeptId()));
             }
-            if (vo.getExecutingUnit() != null) {
-                vo.setExecutingUnitName(deptNameMap.get(vo.getExecutingUnit()));
+            if (CollUtil.isNotEmpty(vo.getExecutingUnit())) {
+                // ⭐ 多个名字用逗号拼起来
+                String names = vo.getExecutingUnit().stream()
+                        .map(deptNameMap::get)
+                        .filter(StrUtil::isNotBlank)
+                        .collect(Collectors.joining(", "));
+                vo.setExecutingUnitName(names);
             }
         }
     }