Просмотр исходного кода

核心技术及 进度明细 附件列表

zhangcl 1 день назад
Родитель
Сommit
ef1f895317
27 измененных файлов с 1924 добавлено и 0 удалено
  1. 37 0
      yudao-module-rd/yudao-module-rd-api/src/main/java/cn/iocoder/yudao/module/rd/enums/AttachmentCategoryEnum.java
  2. 37 0
      yudao-module-rd/yudao-module-rd-api/src/main/java/cn/iocoder/yudao/module/rd/enums/AttachmentTypeEnum.java
  3. 4 0
      yudao-module-rd/yudao-module-rd-api/src/main/java/cn/iocoder/yudao/module/rd/enums/ErrorCodeConstant.java
  4. 93 0
      yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/controller/admin/attachment/AttachmentController.java
  5. 57 0
      yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/controller/admin/attachment/vo/AttachmentPageReqVO.java
  6. 55 0
      yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/controller/admin/attachment/vo/AttachmentRespVO.java
  7. 41 0
      yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/controller/admin/attachment/vo/AttachmentSaveReqVO.java
  8. 228 0
      yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/controller/admin/coretechnology/CoreTechnologyController.java
  9. 78 0
      yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/controller/admin/coretechnology/vo/CoreTechnologyPageReqVO.java
  10. 118 0
      yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/controller/admin/coretechnology/vo/CoreTechnologyRespVO.java
  11. 79 0
      yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/controller/admin/coretechnology/vo/CoreTechnologySaveReqVO.java
  12. 93 0
      yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/controller/admin/coretechnologydetail/CoreTechnologyDetailController.java
  13. 46 0
      yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/controller/admin/coretechnologydetail/vo/CoreTechnologyDetailPageReqVO.java
  14. 51 0
      yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/controller/admin/coretechnologydetail/vo/CoreTechnologyDetailRespVO.java
  15. 36 0
      yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/controller/admin/coretechnologydetail/vo/CoreTechnologyDetailSaveReqVO.java
  16. 62 0
      yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/dal/dataobject/attachment/AttachmentDO.java
  17. 102 0
      yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/dal/dataobject/coretechnology/CoreTechnologyDO.java
  18. 60 0
      yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/dal/dataobject/coretechnologydetail/CoreTechnologyDetailDO.java
  19. 49 0
      yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/dal/mysql/attachment/AttachmentMapper.java
  20. 42 0
      yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/dal/mysql/coretechnology/CoreTechnologyMapper.java
  21. 46 0
      yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/dal/mysql/coretechnologydetail/CoreTechnologyDetailMapper.java
  22. 63 0
      yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/service/attachment/AttachmentService.java
  23. 77 0
      yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/service/attachment/AttachmentServiceImpl.java
  24. 55 0
      yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/service/coretechnology/CoreTechnologyService.java
  25. 174 0
      yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/service/coretechnology/CoreTechnologyServiceImpl.java
  26. 64 0
      yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/service/coretechnologydetail/CoreTechnologyDetailService.java
  27. 77 0
      yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/service/coretechnologydetail/CoreTechnologyDetailServiceImpl.java

+ 37 - 0
yudao-module-rd/yudao-module-rd-api/src/main/java/cn/iocoder/yudao/module/rd/enums/AttachmentCategoryEnum.java

@@ -0,0 +1,37 @@
+package cn.iocoder.yudao.module.rd.enums;
+
+/**
+ * @description: 附件类别
+ * @author: ruiqi
+ * @create: 2025-10-20
+ **/
+public enum AttachmentCategoryEnum {
+    EXPERT("EXPERT", "专家库", 1),
+    CORE_TECHNOLOGY("CORE_TECHNOLOGY", "核心技术", 2),
+    SCIENCE_PROJECT("SCIENCE_PROJECT", "科研项目", 3),
+    GOV_PROJECT("GOV_PROJECT", "政府项目", 4),
+    POLICY("POLICY", "政策咨询", 5),
+    PATENT("PATENT", "专利", 6);
+
+    private String code;
+    private String msg;
+    private Integer num;
+
+    AttachmentCategoryEnum(String code, String msg, Integer num) {
+        this.code = code;
+        this.msg = msg;
+        this.num = num;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+
+    public Integer getNum() {
+        return num;
+    }
+}

+ 37 - 0
yudao-module-rd/yudao-module-rd-api/src/main/java/cn/iocoder/yudao/module/rd/enums/AttachmentTypeEnum.java

@@ -0,0 +1,37 @@
+package cn.iocoder.yudao.module.rd.enums;
+
+/**
+ * @description: 附件 细分项
+ * @author: ruiqi
+ * @create: 2025-10-20
+ **/
+public enum AttachmentTypeEnum {
+    PATENT("EXTERNAL_RENTAL", "专利", 1),
+    PAPER("CONSTRUCTION_DESIGN", "论文", 2),
+    OTHER_MATERIAL("GEOLOGICAL_DESIGN", "其他资料", 3),
+    AUTH_NOTICE("COMPLETION_REPORT", "授权通知书", 4),
+    MAINTENANCE_STANDARD("CERTIFICATE", "证书", 5),
+    REGISTER_COPY("REGISTER_COPY", "登记副本", 6);
+
+    private String code;
+    private String msg;
+    private Integer num;
+
+    AttachmentTypeEnum(String code, String msg, Integer num) {
+        this.code = code;
+        this.msg = msg;
+        this.num = num;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+
+    public Integer getNum() {
+        return num;
+    }
+}

+ 4 - 0
yudao-module-rd/yudao-module-rd-api/src/main/java/cn/iocoder/yudao/module/rd/enums/ErrorCodeConstant.java

@@ -9,6 +9,10 @@ public interface ErrorCodeConstant {
     ErrorCode EXPERT_KEYWORD_NOT_EXISTS = new ErrorCode(201, "专家热词字典不存在");
     ErrorCode EXPERT_KEYWORD_REL_NOT_EXISTS = new ErrorCode(202, "专家热词关联不存在");
 
+    ErrorCode CORE_TECHNOLOGY_NOT_EXISTS = new ErrorCode(400, "核心技术不存在");
+    ErrorCode CORE_TECHNOLOGY_DETAIL_NOT_EXISTS = new ErrorCode(401, "核心技术明细不存在");
+
+    ErrorCode ATTACHMENT_NOT_EXISTS = new ErrorCode(300, "R&D 附件不存在");
     /***
      * 数字油藏
      */

+ 93 - 0
yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/controller/admin/attachment/AttachmentController.java

@@ -0,0 +1,93 @@
+package cn.iocoder.yudao.module.rd.controller.admin.attachment;
+
+import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+import cn.iocoder.yudao.module.rd.controller.admin.attachment.vo.AttachmentPageReqVO;
+import cn.iocoder.yudao.module.rd.controller.admin.attachment.vo.AttachmentRespVO;
+import cn.iocoder.yudao.module.rd.controller.admin.attachment.vo.AttachmentSaveReqVO;
+import cn.iocoder.yudao.module.rd.dal.dataobject.attachment.AttachmentDO;
+import cn.iocoder.yudao.module.rd.service.attachment.AttachmentService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+import java.io.IOException;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Tag(name = "管理后台 - R&D 附件")
+@RestController
+@RequestMapping("/rd/attachment")
+@Validated
+public class AttachmentController {
+
+    @Resource
+    private AttachmentService attachmentService;
+
+    @PostMapping("/create")
+    @Operation(summary = "创建R&D 附件")
+    @PreAuthorize("@ss.hasPermission('rd:attachment:create')")
+    public CommonResult<Long> createAttachment(@Valid @RequestBody AttachmentSaveReqVO createReqVO) {
+        return success(attachmentService.createAttachment(createReqVO));
+    }
+
+    @PutMapping("/update")
+    @Operation(summary = "更新R&D 附件")
+    @PreAuthorize("@ss.hasPermission('rd:attachment:update')")
+    public CommonResult<Boolean> updateAttachment(@Valid @RequestBody AttachmentSaveReqVO updateReqVO) {
+        attachmentService.updateAttachment(updateReqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "删除R&D 附件")
+    @Parameter(name = "id", description = "编号", required = true)
+    @PreAuthorize("@ss.hasPermission('rd:attachment:delete')")
+    public CommonResult<Boolean> deleteAttachment(@RequestParam("id") Long id) {
+        attachmentService.deleteAttachment(id);
+        return success(true);
+    }
+
+    @GetMapping("/get")
+    @Operation(summary = "获得R&D 附件")
+    @Parameter(name = "id", description = "编号", required = true, example = "1024")
+    @PreAuthorize("@ss.hasPermission('rd:attachment:query')")
+    public CommonResult<AttachmentRespVO> getAttachment(@RequestParam("id") Long id) {
+        AttachmentDO attachment = attachmentService.getAttachment(id);
+        return success(BeanUtils.toBean(attachment, AttachmentRespVO.class));
+    }
+
+    @GetMapping("/page")
+    @Operation(summary = "获得R&D 附件分页")
+    @PreAuthorize("@ss.hasPermission('rd:attachment:query')")
+    public CommonResult<PageResult<AttachmentRespVO>> getAttachmentPage(@Valid AttachmentPageReqVO pageReqVO) {
+        PageResult<AttachmentDO> pageResult = attachmentService.getAttachmentPage(pageReqVO);
+        return success(BeanUtils.toBean(pageResult, AttachmentRespVO.class));
+    }
+
+    @GetMapping("/export-excel")
+    @Operation(summary = "导出R&D 附件 Excel")
+    @PreAuthorize("@ss.hasPermission('rd:attachment:export')")
+    @ApiAccessLog(operateType = EXPORT)
+    public void exportAttachmentExcel(@Valid AttachmentPageReqVO pageReqVO,
+              HttpServletResponse response) throws IOException {
+        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+        List<AttachmentDO> list = attachmentService.getAttachmentPage(pageReqVO).getList();
+        // 导出 Excel
+        ExcelUtils.write(response, "R&D 附件.xls", "数据", AttachmentRespVO.class,
+                        BeanUtils.toBean(list, AttachmentRespVO.class));
+    }
+
+}

+ 57 - 0
yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/controller/admin/attachment/vo/AttachmentPageReqVO.java

@@ -0,0 +1,57 @@
+package cn.iocoder.yudao.module.rd.controller.admin.attachment.vo;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+import java.util.Collection;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - R&D 附件分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class AttachmentPageReqVO extends PageParam {
+
+    @Schema(description = "所属功能模块(专家库/核心技术/科研项目/政府项目...)")
+    private String category;
+
+    @Schema(description = "业务主键id", example = "13035")
+    private Long bizId;
+
+    @Schema(description = "类别(专利/论文/其他...)", example = "1")
+    private String type;
+
+    @Schema(description = "文件名称", example = "王五")
+    private String filename;
+
+    @Schema(description = "文件类型", example = "1")
+    private String fileType;
+
+    @Schema(description = "文件路径")
+    private String filePath;
+
+    @Schema(description = "文件大小")
+    private String fileSize;
+
+    @Schema(description = "备注", example = "随便")
+    private String remark;
+
+    @Schema(description = "创建时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] createTime;
+
+    /**
+     * 扩展字段
+     */
+    @Schema(description = "业务主键id 集合", example = "3510,3610")
+    private Collection<Long> bizIds;
+
+    @Schema(description = "附件类型 集合", example = "PATENT,PAPER")
+    private Collection<String> types;
+}

+ 55 - 0
yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/controller/admin/attachment/vo/AttachmentRespVO.java

@@ -0,0 +1,55 @@
+package cn.iocoder.yudao.module.rd.controller.admin.attachment.vo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - R&D 附件 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class AttachmentRespVO {
+
+    @Schema(description = "主键id", requiredMode = Schema.RequiredMode.REQUIRED, example = "23930")
+    @ExcelProperty("主键id")
+    private Long id;
+
+    @Schema(description = "所属功能模块(专家库/核心技术/科研项目/政府项目...)")
+    @ExcelProperty("所属功能模块(专家库/核心技术/科研项目/政府项目...)")
+    private String category;
+
+    @Schema(description = "业务主键id", example = "13035")
+    @ExcelProperty("业务主键id")
+    private Long bizId;
+
+    @Schema(description = "类别(专利/论文/其他...)", example = "1")
+    @ExcelProperty("类别(专利/论文/其他...)")
+    private String type;
+
+    @Schema(description = "文件名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五")
+    @ExcelProperty("文件名称")
+    private String filename;
+
+    @Schema(description = "文件类型", example = "1")
+    @ExcelProperty("文件类型")
+    private String fileType;
+
+    @Schema(description = "文件路径", requiredMode = Schema.RequiredMode.REQUIRED)
+    @ExcelProperty("文件路径")
+    private String filePath;
+
+    @Schema(description = "文件大小")
+    @ExcelProperty("文件大小")
+    private String fileSize;
+
+    @Schema(description = "备注", example = "随便")
+    @ExcelProperty("备注")
+    private String remark;
+
+    @Schema(description = "创建时间")
+    @ExcelProperty("创建时间")
+    private LocalDateTime createTime;
+
+}

+ 41 - 0
yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/controller/admin/attachment/vo/AttachmentSaveReqVO.java

@@ -0,0 +1,41 @@
+package cn.iocoder.yudao.module.rd.controller.admin.attachment.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import javax.validation.constraints.NotEmpty;
+
+@Schema(description = "管理后台 - R&D 附件新增/修改 Request VO")
+@Data
+public class AttachmentSaveReqVO {
+
+    @Schema(description = "主键id", requiredMode = Schema.RequiredMode.REQUIRED, example = "23930")
+    private Long id;
+
+    @Schema(description = "所属功能模块(专家库/核心技术/科研项目/政府项目...)")
+    private String category;
+
+    @Schema(description = "业务主键id", example = "13035")
+    private Long bizId;
+
+    @Schema(description = "类别(专利/论文/其他...)", example = "1")
+    private String type;
+
+    @Schema(description = "文件名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五")
+    @NotEmpty(message = "文件名称不能为空")
+    private String filename;
+
+    @Schema(description = "文件类型", example = "1")
+    private String fileType;
+
+    @Schema(description = "文件路径", requiredMode = Schema.RequiredMode.REQUIRED)
+    @NotEmpty(message = "文件路径不能为空")
+    private String filePath;
+
+    @Schema(description = "文件大小")
+    private String fileSize;
+
+    @Schema(description = "备注", example = "随便")
+    private String remark;
+
+}

+ 228 - 0
yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/controller/admin/coretechnology/CoreTechnologyController.java

@@ -0,0 +1,228 @@
+package cn.iocoder.yudao.module.rd.controller.admin.coretechnology;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ObjUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+import cn.iocoder.yudao.module.rd.controller.admin.attachment.vo.AttachmentPageReqVO;
+import cn.iocoder.yudao.module.rd.controller.admin.coretechnology.vo.CoreTechnologyPageReqVO;
+import cn.iocoder.yudao.module.rd.controller.admin.coretechnology.vo.CoreTechnologyRespVO;
+import cn.iocoder.yudao.module.rd.controller.admin.coretechnology.vo.CoreTechnologySaveReqVO;
+import cn.iocoder.yudao.module.rd.controller.admin.coretechnologydetail.vo.CoreTechnologyDetailPageReqVO;
+import cn.iocoder.yudao.module.rd.dal.dataobject.attachment.AttachmentDO;
+import cn.iocoder.yudao.module.rd.dal.dataobject.coretechnology.CoreTechnologyDO;
+import cn.iocoder.yudao.module.rd.dal.dataobject.coretechnologydetail.CoreTechnologyDetailDO;
+import cn.iocoder.yudao.module.rd.enums.AttachmentCategoryEnum;
+import cn.iocoder.yudao.module.rd.service.attachment.AttachmentService;
+import cn.iocoder.yudao.module.rd.service.coretechnology.CoreTechnologyService;
+import cn.iocoder.yudao.module.rd.service.coretechnologydetail.CoreTechnologyDetailService;
+import cn.iocoder.yudao.module.rd.utils.DictDataUtils;
+import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO;
+import cn.iocoder.yudao.module.system.service.dict.DictDataService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Tag(name = "管理后台 - 核心技术")
+@RestController
+@RequestMapping("/rd/core-technology")
+@Validated
+public class CoreTechnologyController {
+
+    @Resource
+    private CoreTechnologyService coreTechnologyService;
+    @Resource
+    private DictDataService dictDataService;
+    @Resource
+    private DictDataUtils dictDataUtils;
+    @Resource
+    private AttachmentService attachmentService;
+    @Resource
+    private CoreTechnologyDetailService coreTechnologyDetailService;
+
+    @PostMapping("/create")
+    @Operation(summary = "创建核心技术")
+    @PreAuthorize("@ss.hasPermission('rd:core-technology:create')")
+    public CommonResult<Long> createCoreTechnology(@Valid @RequestBody CoreTechnologySaveReqVO createReqVO) {
+        return success(coreTechnologyService.createCoreTechnology(createReqVO));
+    }
+
+    @PutMapping("/update")
+    @Operation(summary = "更新核心技术")
+    @PreAuthorize("@ss.hasPermission('rd:core-technology:update')")
+    public CommonResult<Boolean> updateCoreTechnology(@Valid @RequestBody CoreTechnologySaveReqVO updateReqVO) {
+        coreTechnologyService.updateCoreTechnology(updateReqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "删除核心技术")
+    @Parameter(name = "id", description = "编号", required = true)
+    @PreAuthorize("@ss.hasPermission('rd:core-technology:delete')")
+    public CommonResult<Boolean> deleteCoreTechnology(@RequestParam("id") Long id) {
+        coreTechnologyService.deleteCoreTechnology(id);
+        return success(true);
+    }
+
+    @GetMapping("/get")
+    @Operation(summary = "获得核心技术")
+    @Parameter(name = "id", description = "编号", required = true, example = "1024")
+    @PreAuthorize("@ss.hasPermission('rd:core-technology:query')")
+    public CommonResult<CoreTechnologyRespVO> getCoreTechnology(@RequestParam("id") Long id) {
+        CoreTechnologyDO coreTechnology = coreTechnologyService.getCoreTechnology(id);
+        return success(buildCoreTechnology(coreTechnology));
+    }
+
+    /**
+     * 查询核心技术 技术详情
+     * @param technology
+     * @return
+     */
+    private CoreTechnologyRespVO buildCoreTechnology(CoreTechnologyDO technology) {
+        // 如果 technology 为空 返回空对象
+        if (ObjUtil.isEmpty(technology)) {
+            return new CoreTechnologyRespVO();
+        }
+        CoreTechnologyRespVO technologyVO = BeanUtils.toBean(technology, CoreTechnologyRespVO.class);
+        // 查询 核心技术-状态 字典数据
+        Map<String, String> techStatusesPair = dictDataUtils.getDictData("rd_core_technology_status");
+        // 查询 核心技术-级别 字典数据
+        Map<String, String> techLevelPair = dictDataUtils.getDictData("rd_core_technology_level");
+        // 查询 核心技术-类型 字典数据
+        Map<String, String> techTypesPair = dictDataUtils.getDictData("rd_core_technology_type");
+
+        // 核心技术-状态
+        String status = technologyVO.getTechnologyStatus();
+        if (StrUtil.isNotBlank(status) && techStatusesPair.containsKey(status)) {
+            technologyVO.setTechnologyStatusLabel(techStatusesPair.get(status));
+        }
+
+        // 核心技术-级别
+        String level = technologyVO.getTechnologyLevel();
+        if (StrUtil.isNotBlank(level) && techLevelPair.containsKey(level)) {
+            technologyVO.setTechnologyLevelLabel(techLevelPair.get(level));
+        }
+
+        // 核心技术-类型
+        String type = technologyVO.getTechnologyType();
+        if (StrUtil.isNotBlank(type) && techTypesPair.containsKey(type)) {
+            technologyVO.setTechnologyTypeLabel(techTypesPair.get(type));
+        }
+        // 查询核心技术 进度明细 按照进度日期降序排列
+        CoreTechnologyDetailPageReqVO detailReqVO = new CoreTechnologyDetailPageReqVO();
+        detailReqVO.setTechnologyId(technology.getId());
+        List<CoreTechnologyDetailDO> technologyDetails = coreTechnologyDetailService.getCoreTechnologyDetails(detailReqVO);
+        if (CollUtil.isNotEmpty(technologyDetails)) {
+            technologyVO.setDetails(technologyDetails);
+        }
+        // 查询当前核心技术 附件列表
+        AttachmentPageReqVO reqVO = new AttachmentPageReqVO();
+        reqVO.setBizId(technology.getId());
+        reqVO.setCategory(AttachmentCategoryEnum.CORE_TECHNOLOGY.getCode());
+        List<AttachmentDO> attachments = attachmentService.getIotAttachments(reqVO);
+        if (CollUtil.isNotEmpty(attachments)) {
+            technologyVO.setAttachments(attachments);
+        }
+        return technologyVO;
+    }
+
+    @GetMapping("/page")
+    @Operation(summary = "获得核心技术分页")
+    @PreAuthorize("@ss.hasPermission('rd:core-technology:query')")
+    public CommonResult<PageResult<CoreTechnologyRespVO>> getCoreTechnologyPage(@Valid CoreTechnologyPageReqVO pageReqVO) {
+        PageResult<CoreTechnologyDO> pageResult = coreTechnologyService.getCoreTechnologyPage(pageReqVO);
+        return success(new PageResult<>(buildCoreTechnologyList(pageResult.getList()), pageResult.getTotal()));
+    }
+
+    /**
+     * 设置日报的关联信息 部门(施工队伍) 项目 任务 带班干部 日报填报人
+     * @param technologies
+     * @return
+     */
+    private List<CoreTechnologyRespVO> buildCoreTechnologyList(List<CoreTechnologyDO> technologies) {
+        if (CollUtil.isEmpty(technologies)) {
+            return Collections.emptyList();
+        }
+        // 查询数据字典值列表
+        //  核心技术-状态 key字典键值     value字典标签
+        Map<String, String> techStatusesPair = new HashMap<>();
+        //  核心技术-级别 key字典键值     value字典标签
+        Map<String, String> techLevelPair = new HashMap<>();
+        //  核心技术-类型 key字典键值     value字典标签
+        Map<String, String> techTypesPair = new HashMap<>();
+
+        // 查询 核心技术-状态 字典数据
+        List<DictDataDO> techStatuses = dictDataService.getDictDataListByDictType("rd_core_technology_status");
+        // 查询 核心技术-级别 字典数据
+        List<DictDataDO> techLevel = dictDataService.getDictDataListByDictType("rd_core_technology_level");
+        // 查询 核心技术-类型 字典数据
+        List<DictDataDO> techTypes = dictDataService.getDictDataListByDictType("rd_core_technology_type");
+        if (CollUtil.isNotEmpty(techStatuses)) {
+            techStatuses.forEach(tech -> {
+                techStatusesPair.put(tech.getValue(), tech.getLabel());
+            });
+        }
+        if (CollUtil.isNotEmpty(techLevel)) {
+            techLevel.forEach(tech -> {
+                techLevelPair.put(tech.getValue(), tech.getLabel());
+            });
+        }
+        if (CollUtil.isNotEmpty(techTypes)) {
+            techTypes.forEach(tech -> {
+                techTypesPair.put(tech.getValue(), tech.getLabel());
+            });
+        }
+
+        return BeanUtils.toBean(technologies, CoreTechnologyRespVO.class, (techVO) -> {
+            if (StrUtil.isNotBlank(techVO.getTechnologyStatus())) {
+                if (techStatusesPair.containsKey(techVO.getTechnologyStatus())) {
+                    techVO.setTechnologyStatusLabel(techStatusesPair.get(techVO.getTechnologyStatus()));
+                }
+            }
+            if (StrUtil.isNotBlank(techVO.getTechnologyLevel())) {
+                if (techLevelPair.containsKey(techVO.getTechnologyLevel())) {
+                    techVO.setTechnologyLevelLabel(techLevelPair.get(techVO.getTechnologyLevel()));
+                }
+            }
+            if (StrUtil.isNotBlank(techVO.getTechnologyType())) {
+                if (techTypesPair.containsKey(techVO.getTechnologyType())) {
+                    techVO.setTechnologyTypeLabel(techTypesPair.get(techVO.getTechnologyType()));
+                }
+            }
+        });
+    }
+
+    @GetMapping("/export-excel")
+    @Operation(summary = "导出核心技术 Excel")
+    @PreAuthorize("@ss.hasPermission('rd:core-technology:export')")
+    @ApiAccessLog(operateType = EXPORT)
+    public void exportCoreTechnologyExcel(@Valid CoreTechnologyPageReqVO pageReqVO,
+              HttpServletResponse response) throws IOException {
+        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+        List<CoreTechnologyDO> list = coreTechnologyService.getCoreTechnologyPage(pageReqVO).getList();
+        // 导出 Excel
+        ExcelUtils.write(response, "核心技术.xls", "数据", CoreTechnologyRespVO.class,
+                        BeanUtils.toBean(list, CoreTechnologyRespVO.class));
+    }
+
+}

+ 78 - 0
yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/controller/admin/coretechnology/vo/CoreTechnologyPageReqVO.java

@@ -0,0 +1,78 @@
+package cn.iocoder.yudao.module.rd.controller.admin.coretechnology.vo;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - 核心技术分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class CoreTechnologyPageReqVO extends PageParam {
+
+    @Schema(description = "所属部门", example = "3945")
+    private Long deptId;
+
+    @Schema(description = "核心技术名称", example = "芋艿")
+    private String technologyName;
+
+    @Schema(description = "核心技术类型", example = "1")
+    private String technologyType;
+
+    @Schema(description = "当前状态", example = "2")
+    private String technologyStatus;
+
+    @Schema(description = "技术级别")
+    private String technologyLevel;
+
+    @Schema(description = "所属单位id", example = "16494")
+    private Long departmentId;
+
+    @Schema(description = "所属单位")
+    private String department;
+
+    @Schema(description = "合作单位")
+    private String partner;
+
+    @Schema(description = "概述")
+    private String summary;
+
+    @Schema(description = "头像url")
+    private String avatar;
+
+    @Schema(description = "主要原理及内容")
+    private String principles;
+
+    @Schema(description = "应用场景和优势")
+    private String advantages;
+
+    @Schema(description = "排序值")
+    private Integer sort;
+
+    @Schema(description = "备注", example = "你说的对")
+    private String remark;
+
+    @Schema(description = "状态(0启用 1禁用)", example = "2")
+    private Integer status;
+
+    @Schema(description = "流程实例id", example = "26543")
+    private String processInstanceId;
+
+    @Schema(description = "审批状态 未提交、审批中、审批通过、审批不通过、已取消", example = "2")
+    private Integer auditStatus;
+
+    @Schema(description = "审批意见")
+    private String opinion;
+
+    @Schema(description = "创建时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] createTime;
+
+}

+ 118 - 0
yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/controller/admin/coretechnology/vo/CoreTechnologyRespVO.java

@@ -0,0 +1,118 @@
+package cn.iocoder.yudao.module.rd.controller.admin.coretechnology.vo;
+
+import cn.iocoder.yudao.module.rd.dal.dataobject.attachment.AttachmentDO;
+import cn.iocoder.yudao.module.rd.dal.dataobject.coretechnologydetail.CoreTechnologyDetailDO;
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+@Schema(description = "管理后台 - 核心技术 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class CoreTechnologyRespVO {
+
+    @Schema(description = "主键id", requiredMode = Schema.RequiredMode.REQUIRED, example = "19587")
+    @ExcelProperty("主键id")
+    private Long id;
+
+    @Schema(description = "所属部门", example = "3945")
+    @ExcelProperty("所属部门")
+    private Long deptId;
+
+    @Schema(description = "核心技术名称", example = "芋艿")
+    @ExcelProperty("核心技术名称")
+    private String technologyName;
+
+    @Schema(description = "核心技术类型", example = "1")
+    @ExcelProperty("核心技术类型")
+    private String technologyType;
+
+    @Schema(description = "当前状态", example = "2")
+    @ExcelProperty("当前状态")
+    private String technologyStatus;
+
+    @Schema(description = "技术级别")
+    @ExcelProperty("技术级别")
+    private String technologyLevel;
+
+    @Schema(description = "所属单位id", example = "16494")
+    @ExcelProperty("所属单位id")
+    private Long departmentId;
+
+    @Schema(description = "所属单位")
+    @ExcelProperty("所属单位")
+    private String department;
+
+    @Schema(description = "合作单位")
+    @ExcelProperty("合作单位")
+    private String partner;
+
+    @Schema(description = "概述")
+    @ExcelProperty("概述")
+    private String summary;
+
+    @Schema(description = "头像url")
+    @ExcelProperty("头像url")
+    private String avatar;
+
+    @Schema(description = "主要原理及内容")
+    @ExcelProperty("主要原理及内容")
+    private String principles;
+
+    @Schema(description = "应用场景和优势")
+    @ExcelProperty("应用场景和优势")
+    private String advantages;
+
+    @Schema(description = "排序值")
+    @ExcelProperty("排序值")
+    private Integer sort;
+
+    @Schema(description = "备注", example = "你说的对")
+    @ExcelProperty("备注")
+    private String remark;
+
+    @Schema(description = "状态(0启用 1禁用)", example = "2")
+    @ExcelProperty("状态(0启用 1禁用)")
+    private Integer status;
+
+    @Schema(description = "流程实例id", example = "26543")
+    @ExcelProperty("流程实例id")
+    private String processInstanceId;
+
+    @Schema(description = "审批状态 未提交、审批中、审批通过、审批不通过、已取消", example = "2")
+    @ExcelProperty("审批状态 未提交、审批中、审批通过、审批不通过、已取消")
+    private Integer auditStatus;
+
+    @Schema(description = "审批意见")
+    @ExcelProperty("审批意见")
+    private String opinion;
+
+    @Schema(description = "创建时间")
+    @ExcelProperty("创建时间")
+    private LocalDateTime createTime;
+
+    /**
+     * 扩展字段
+     */
+    @Schema(description = "核心技术类型 数据字典标签", example = "1")
+    @ExcelProperty("核心技术类型")
+    private String technologyTypeLabel;
+
+    @Schema(description = "当前状态 数据字典标签", example = "2")
+    @ExcelProperty("当前状态")
+    private String technologyStatusLabel;
+
+    @Schema(description = "技术级别 数据字典标签")
+    @ExcelProperty("技术级别")
+    private String technologyLevelLabel;
+
+    @Schema(description = "进度明细列表", example = "https://aims.deepoil.cc/admin-api/infra/file/29/get/人力资源.png")
+    private List<CoreTechnologyDetailDO> details;
+
+    @Schema(description = "附件列表", example = "https://aims.deepoil.cc/admin-api/infra/file/29/get/人力资源.png")
+    private List<AttachmentDO> attachments;
+}

+ 79 - 0
yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/controller/admin/coretechnology/vo/CoreTechnologySaveReqVO.java

@@ -0,0 +1,79 @@
+package cn.iocoder.yudao.module.rd.controller.admin.coretechnology.vo;
+
+import cn.iocoder.yudao.module.rd.controller.admin.attachment.vo.AttachmentSaveReqVO;
+import cn.iocoder.yudao.module.rd.controller.admin.coretechnologydetail.vo.CoreTechnologyDetailSaveReqVO;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.List;
+
+@Schema(description = "管理后台 - 核心技术新增/修改 Request VO")
+@Data
+public class CoreTechnologySaveReqVO {
+
+    @Schema(description = "主键id", requiredMode = Schema.RequiredMode.REQUIRED, example = "19587")
+    private Long id;
+
+    @Schema(description = "所属部门", example = "3945")
+    private Long deptId;
+
+    @Schema(description = "核心技术名称", example = "芋艿")
+    private String technologyName;
+
+    @Schema(description = "核心技术类型", example = "1")
+    private String technologyType;
+
+    @Schema(description = "当前状态", example = "2")
+    private String technologyStatus;
+
+    @Schema(description = "技术级别")
+    private String technologyLevel;
+
+    @Schema(description = "所属单位id", example = "16494")
+    private Long departmentId;
+
+    @Schema(description = "所属单位")
+    private String department;
+
+    @Schema(description = "合作单位")
+    private String partner;
+
+    @Schema(description = "概述")
+    private String summary;
+
+    @Schema(description = "头像url")
+    private String avatar;
+
+    @Schema(description = "主要原理及内容")
+    private String principles;
+
+    @Schema(description = "应用场景和优势")
+    private String advantages;
+
+    @Schema(description = "排序值")
+    private Integer sort;
+
+    @Schema(description = "备注", example = "你说的对")
+    private String remark;
+
+    @Schema(description = "状态(0启用 1禁用)", example = "2")
+    private Integer status;
+
+    @Schema(description = "流程实例id", example = "26543")
+    private String processInstanceId;
+
+    @Schema(description = "审批状态 未提交、审批中、审批通过、审批不通过、已取消", example = "2")
+    private Integer auditStatus;
+
+    @Schema(description = "审批意见")
+    private String opinion;
+
+    /**
+     * 扩展字段
+     */
+    @Schema(description = "附件列表")
+    private List<AttachmentSaveReqVO> attachments;
+
+    @Schema(description = "进度明细列表")
+    private List<CoreTechnologyDetailSaveReqVO> details;
+}

+ 93 - 0
yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/controller/admin/coretechnologydetail/CoreTechnologyDetailController.java

@@ -0,0 +1,93 @@
+package cn.iocoder.yudao.module.rd.controller.admin.coretechnologydetail;
+
+import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+import cn.iocoder.yudao.module.rd.controller.admin.coretechnologydetail.vo.CoreTechnologyDetailPageReqVO;
+import cn.iocoder.yudao.module.rd.controller.admin.coretechnologydetail.vo.CoreTechnologyDetailRespVO;
+import cn.iocoder.yudao.module.rd.controller.admin.coretechnologydetail.vo.CoreTechnologyDetailSaveReqVO;
+import cn.iocoder.yudao.module.rd.dal.dataobject.coretechnologydetail.CoreTechnologyDetailDO;
+import cn.iocoder.yudao.module.rd.service.coretechnologydetail.CoreTechnologyDetailService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+import java.io.IOException;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Tag(name = "管理后台 - 核心技术明细")
+@RestController
+@RequestMapping("/rd/core-technology-detail")
+@Validated
+public class CoreTechnologyDetailController {
+
+    @Resource
+    private CoreTechnologyDetailService coreTechnologyDetailService;
+
+    @PostMapping("/create")
+    @Operation(summary = "创建核心技术明细")
+    @PreAuthorize("@ss.hasPermission('rd:core-technology-detail:create')")
+    public CommonResult<Long> createCoreTechnologyDetail(@Valid @RequestBody CoreTechnologyDetailSaveReqVO createReqVO) {
+        return success(coreTechnologyDetailService.createCoreTechnologyDetail(createReqVO));
+    }
+
+    @PutMapping("/update")
+    @Operation(summary = "更新核心技术明细")
+    @PreAuthorize("@ss.hasPermission('rd:core-technology-detail:update')")
+    public CommonResult<Boolean> updateCoreTechnologyDetail(@Valid @RequestBody CoreTechnologyDetailSaveReqVO updateReqVO) {
+        coreTechnologyDetailService.updateCoreTechnologyDetail(updateReqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "删除核心技术明细")
+    @Parameter(name = "id", description = "编号", required = true)
+    @PreAuthorize("@ss.hasPermission('rd:core-technology-detail:delete')")
+    public CommonResult<Boolean> deleteCoreTechnologyDetail(@RequestParam("id") Long id) {
+        coreTechnologyDetailService.deleteCoreTechnologyDetail(id);
+        return success(true);
+    }
+
+    @GetMapping("/get")
+    @Operation(summary = "获得核心技术明细")
+    @Parameter(name = "id", description = "编号", required = true, example = "1024")
+    @PreAuthorize("@ss.hasPermission('rd:core-technology-detail:query')")
+    public CommonResult<CoreTechnologyDetailRespVO> getCoreTechnologyDetail(@RequestParam("id") Long id) {
+        CoreTechnologyDetailDO coreTechnologyDetail = coreTechnologyDetailService.getCoreTechnologyDetail(id);
+        return success(BeanUtils.toBean(coreTechnologyDetail, CoreTechnologyDetailRespVO.class));
+    }
+
+    @GetMapping("/page")
+    @Operation(summary = "获得核心技术明细分页")
+    @PreAuthorize("@ss.hasPermission('rd:core-technology-detail:query')")
+    public CommonResult<PageResult<CoreTechnologyDetailRespVO>> getCoreTechnologyDetailPage(@Valid CoreTechnologyDetailPageReqVO pageReqVO) {
+        PageResult<CoreTechnologyDetailDO> pageResult = coreTechnologyDetailService.getCoreTechnologyDetailPage(pageReqVO);
+        return success(BeanUtils.toBean(pageResult, CoreTechnologyDetailRespVO.class));
+    }
+
+    @GetMapping("/export-excel")
+    @Operation(summary = "导出核心技术明细 Excel")
+    @PreAuthorize("@ss.hasPermission('rd:core-technology-detail:export')")
+    @ApiAccessLog(operateType = EXPORT)
+    public void exportCoreTechnologyDetailExcel(@Valid CoreTechnologyDetailPageReqVO pageReqVO,
+              HttpServletResponse response) throws IOException {
+        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+        List<CoreTechnologyDetailDO> list = coreTechnologyDetailService.getCoreTechnologyDetailPage(pageReqVO).getList();
+        // 导出 Excel
+        ExcelUtils.write(response, "核心技术明细.xls", "数据", CoreTechnologyDetailRespVO.class,
+                        BeanUtils.toBean(list, CoreTechnologyDetailRespVO.class));
+    }
+
+}

+ 46 - 0
yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/controller/admin/coretechnologydetail/vo/CoreTechnologyDetailPageReqVO.java

@@ -0,0 +1,46 @@
+package cn.iocoder.yudao.module.rd.controller.admin.coretechnologydetail.vo;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - 核心技术明细分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class CoreTechnologyDetailPageReqVO extends PageParam {
+
+    @Schema(description = "核心技术所属单位id", example = "7639")
+    private Long deptId;
+
+    @Schema(description = "核心技术id", example = "16092")
+    private Long technologyId;
+
+    @Schema(description = "进度日期")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] progressDate;
+
+    @Schema(description = "进度描述")
+    private String overview;
+
+    @Schema(description = "排序值")
+    private Integer sort;
+
+    @Schema(description = "备注", example = "你说的对")
+    private String remark;
+
+    @Schema(description = "状态(0启用 1禁用)", example = "2")
+    private Integer status;
+
+    @Schema(description = "创建时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] createTime;
+
+}

+ 51 - 0
yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/controller/admin/coretechnologydetail/vo/CoreTechnologyDetailRespVO.java

@@ -0,0 +1,51 @@
+package cn.iocoder.yudao.module.rd.controller.admin.coretechnologydetail.vo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - 核心技术明细 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class CoreTechnologyDetailRespVO {
+
+    @Schema(description = "主键id", requiredMode = Schema.RequiredMode.REQUIRED, example = "23655")
+    @ExcelProperty("主键id")
+    private Long id;
+
+    @Schema(description = "核心技术所属单位id", example = "7639")
+    @ExcelProperty("核心技术所属单位id")
+    private Long deptId;
+
+    @Schema(description = "核心技术id", example = "16092")
+    @ExcelProperty("核心技术id")
+    private Long technologyId;
+
+    @Schema(description = "进度日期")
+    @ExcelProperty("进度日期")
+    private LocalDateTime progressDate;
+
+    @Schema(description = "进度描述")
+    @ExcelProperty("进度描述")
+    private String overview;
+
+    @Schema(description = "排序值")
+    @ExcelProperty("排序值")
+    private Integer sort;
+
+    @Schema(description = "备注", example = "你说的对")
+    @ExcelProperty("备注")
+    private String remark;
+
+    @Schema(description = "状态(0启用 1禁用)", example = "2")
+    @ExcelProperty("状态(0启用 1禁用)")
+    private Integer status;
+
+    @Schema(description = "创建时间")
+    @ExcelProperty("创建时间")
+    private LocalDateTime createTime;
+
+}

+ 36 - 0
yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/controller/admin/coretechnologydetail/vo/CoreTechnologyDetailSaveReqVO.java

@@ -0,0 +1,36 @@
+package cn.iocoder.yudao.module.rd.controller.admin.coretechnologydetail.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - 核心技术明细新增/修改 Request VO")
+@Data
+public class CoreTechnologyDetailSaveReqVO {
+
+    @Schema(description = "主键id", requiredMode = Schema.RequiredMode.REQUIRED, example = "23655")
+    private Long id;
+
+    @Schema(description = "核心技术所属单位id", example = "7639")
+    private Long deptId;
+
+    @Schema(description = "核心技术id", example = "16092")
+    private Long technologyId;
+
+    @Schema(description = "进度日期")
+    private LocalDateTime progressDate;
+
+    @Schema(description = "进度描述")
+    private String overview;
+
+    @Schema(description = "排序值")
+    private Integer sort;
+
+    @Schema(description = "备注", example = "你说的对")
+    private String remark;
+
+    @Schema(description = "状态(0启用 1禁用)", example = "2")
+    private Integer status;
+
+}

+ 62 - 0
yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/dal/dataobject/attachment/AttachmentDO.java

@@ -0,0 +1,62 @@
+package cn.iocoder.yudao.module.rd.dal.dataobject.attachment;
+
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.*;
+
+/**
+ * R&D 附件 DO
+ *
+ * @author ruiqi
+ */
+@TableName("rd_attachment")
+@KeySequence("rd_attachment_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class AttachmentDO extends BaseDO {
+
+    /**
+     * 主键id
+     */
+    @TableId
+    private Long id;
+    /**
+     * 所属功能模块(专家库/核心技术/科研项目/政府项目...)
+     */
+    private String category;
+    /**
+     * 业务主键id
+     */
+    private Long bizId;
+    /**
+     * 类别(专利/论文/其他...)
+     */
+    private String type;
+    /**
+     * 文件名称
+     */
+    private String filename;
+    /**
+     * 文件类型
+     */
+    private String fileType;
+    /**
+     * 文件路径
+     */
+    private String filePath;
+    /**
+     * 文件大小
+     */
+    private String fileSize;
+    /**
+     * 备注
+     */
+    private String remark;
+
+}

+ 102 - 0
yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/dal/dataobject/coretechnology/CoreTechnologyDO.java

@@ -0,0 +1,102 @@
+package cn.iocoder.yudao.module.rd.dal.dataobject.coretechnology;
+
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.*;
+
+/**
+ * 核心技术 DO
+ *
+ * @author ruiqi
+ */
+@TableName("rd_core_technology")
+@KeySequence("rd_core_technology_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class CoreTechnologyDO extends BaseDO {
+
+    /**
+     * 主键id
+     */
+    @TableId
+    private Long id;
+    /**
+     * 所属部门
+     */
+    private Long deptId;
+    /**
+     * 核心技术名称
+     */
+    private String technologyName;
+    /**
+     * 核心技术类型
+     */
+    private String technologyType;
+    /**
+     * 当前状态
+     */
+    private String technologyStatus;
+    /**
+     * 技术级别
+     */
+    private String technologyLevel;
+    /**
+     * 所属单位id
+     */
+    private Long departmentId;
+    /**
+     * 所属单位
+     */
+    private String department;
+    /**
+     * 合作单位
+     */
+    private String partner;
+    /**
+     * 概述
+     */
+    private String summary;
+    /**
+     * 头像url
+     */
+    private String avatar;
+    /**
+     * 主要原理及内容
+     */
+    private String principles;
+    /**
+     * 应用场景和优势
+     */
+    private String advantages;
+    /**
+     * 排序值
+     */
+    private Integer sort;
+    /**
+     * 备注
+     */
+    private String remark;
+    /**
+     * 状态(0启用 1禁用)
+     */
+    private Integer status;
+    /**
+     * 流程实例id
+     */
+    private String processInstanceId;
+    /**
+     * 审批状态 未提交、审批中、审批通过、审批不通过、已取消
+     */
+    private Integer auditStatus;
+    /**
+     * 审批意见
+     */
+    private String opinion;
+
+}

+ 60 - 0
yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/dal/dataobject/coretechnologydetail/CoreTechnologyDetailDO.java

@@ -0,0 +1,60 @@
+package cn.iocoder.yudao.module.rd.dal.dataobject.coretechnologydetail;
+
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.*;
+
+import java.time.LocalDateTime;
+
+/**
+ * 核心技术明细 DO
+ *
+ * @author ruiqi
+ */
+@TableName("rd_core_technology_detail")
+@KeySequence("rd_core_technology_detail_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class CoreTechnologyDetailDO extends BaseDO {
+
+    /**
+     * 主键id
+     */
+    @TableId
+    private Long id;
+    /**
+     * 核心技术所属单位id
+     */
+    private Long deptId;
+    /**
+     * 核心技术id
+     */
+    private Long technologyId;
+    /**
+     * 进度日期
+     */
+    private LocalDateTime progressDate;
+    /**
+     * 进度描述
+     */
+    private String overview;
+    /**
+     * 排序值
+     */
+    private Integer sort;
+    /**
+     * 备注
+     */
+    private String remark;
+    /**
+     * 状态(0启用 1禁用)
+     */
+    private Integer status;
+
+}

+ 49 - 0
yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/dal/mysql/attachment/AttachmentMapper.java

@@ -0,0 +1,49 @@
+package cn.iocoder.yudao.module.rd.dal.mysql.attachment;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.module.rd.controller.admin.attachment.vo.AttachmentPageReqVO;
+import cn.iocoder.yudao.module.rd.dal.dataobject.attachment.AttachmentDO;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * R&D 附件 Mapper
+ *
+ * @author ruiqi
+ */
+@Mapper
+public interface AttachmentMapper extends BaseMapperX<AttachmentDO> {
+
+    default PageResult<AttachmentDO> selectPage(AttachmentPageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<AttachmentDO>()
+                .eqIfPresent(AttachmentDO::getCategory, reqVO.getCategory())
+                .eqIfPresent(AttachmentDO::getBizId, reqVO.getBizId())
+                .eqIfPresent(AttachmentDO::getType, reqVO.getType())
+                .likeIfPresent(AttachmentDO::getFilename, reqVO.getFilename())
+                .eqIfPresent(AttachmentDO::getFileType, reqVO.getFileType())
+                .eqIfPresent(AttachmentDO::getFilePath, reqVO.getFilePath())
+                .eqIfPresent(AttachmentDO::getFileSize, reqVO.getFileSize())
+                .eqIfPresent(AttachmentDO::getRemark, reqVO.getRemark())
+                .betweenIfPresent(AttachmentDO::getCreateTime, reqVO.getCreateTime())
+                .orderByDesc(AttachmentDO::getId));
+    }
+
+    default List<AttachmentDO> attachments(AttachmentPageReqVO reqVO) {
+        return selectList(new LambdaQueryWrapperX<AttachmentDO>()
+                .eqIfPresent(AttachmentDO::getCategory, reqVO.getCategory())
+                .eqIfPresent(AttachmentDO::getBizId, reqVO.getBizId())
+                .inIfPresent(AttachmentDO::getBizId, reqVO.getBizIds())
+                .eqIfPresent(AttachmentDO::getType, reqVO.getType())
+                .likeIfPresent(AttachmentDO::getFilename, reqVO.getFilename())
+                .eqIfPresent(AttachmentDO::getFileType, reqVO.getFileType())
+                .inIfPresent(AttachmentDO::getType, reqVO.getTypes())
+                .eqIfPresent(AttachmentDO::getFilePath, reqVO.getFilePath())
+                .eqIfPresent(AttachmentDO::getFileSize, reqVO.getFileSize())
+                .eqIfPresent(AttachmentDO::getRemark, reqVO.getRemark())
+                .betweenIfPresent(AttachmentDO::getCreateTime, reqVO.getCreateTime()));
+    }
+
+}

+ 42 - 0
yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/dal/mysql/coretechnology/CoreTechnologyMapper.java

@@ -0,0 +1,42 @@
+package cn.iocoder.yudao.module.rd.dal.mysql.coretechnology;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.module.rd.controller.admin.coretechnology.vo.CoreTechnologyPageReqVO;
+import cn.iocoder.yudao.module.rd.dal.dataobject.coretechnology.CoreTechnologyDO;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 核心技术 Mapper
+ *
+ * @author ruiqi
+ */
+@Mapper
+public interface CoreTechnologyMapper extends BaseMapperX<CoreTechnologyDO> {
+
+    default PageResult<CoreTechnologyDO> selectPage(CoreTechnologyPageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<CoreTechnologyDO>()
+                .eqIfPresent(CoreTechnologyDO::getDeptId, reqVO.getDeptId())
+                .likeIfPresent(CoreTechnologyDO::getTechnologyName, reqVO.getTechnologyName())
+                .eqIfPresent(CoreTechnologyDO::getTechnologyType, reqVO.getTechnologyType())
+                .eqIfPresent(CoreTechnologyDO::getTechnologyStatus, reqVO.getTechnologyStatus())
+                .eqIfPresent(CoreTechnologyDO::getTechnologyLevel, reqVO.getTechnologyLevel())
+                .eqIfPresent(CoreTechnologyDO::getDepartmentId, reqVO.getDepartmentId())
+                .eqIfPresent(CoreTechnologyDO::getDepartment, reqVO.getDepartment())
+                .eqIfPresent(CoreTechnologyDO::getPartner, reqVO.getPartner())
+                .eqIfPresent(CoreTechnologyDO::getSummary, reqVO.getSummary())
+                .eqIfPresent(CoreTechnologyDO::getAvatar, reqVO.getAvatar())
+                .eqIfPresent(CoreTechnologyDO::getPrinciples, reqVO.getPrinciples())
+                .eqIfPresent(CoreTechnologyDO::getAdvantages, reqVO.getAdvantages())
+                .eqIfPresent(CoreTechnologyDO::getSort, reqVO.getSort())
+                .eqIfPresent(CoreTechnologyDO::getRemark, reqVO.getRemark())
+                .eqIfPresent(CoreTechnologyDO::getStatus, reqVO.getStatus())
+                .eqIfPresent(CoreTechnologyDO::getProcessInstanceId, reqVO.getProcessInstanceId())
+                .eqIfPresent(CoreTechnologyDO::getAuditStatus, reqVO.getAuditStatus())
+                .eqIfPresent(CoreTechnologyDO::getOpinion, reqVO.getOpinion())
+                .betweenIfPresent(CoreTechnologyDO::getCreateTime, reqVO.getCreateTime())
+                .orderByDesc(CoreTechnologyDO::getId));
+    }
+
+}

+ 46 - 0
yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/dal/mysql/coretechnologydetail/CoreTechnologyDetailMapper.java

@@ -0,0 +1,46 @@
+package cn.iocoder.yudao.module.rd.dal.mysql.coretechnologydetail;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.module.rd.controller.admin.coretechnologydetail.vo.CoreTechnologyDetailPageReqVO;
+import cn.iocoder.yudao.module.rd.dal.dataobject.coretechnologydetail.CoreTechnologyDetailDO;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * 核心技术明细 Mapper
+ *
+ * @author ruiqi
+ */
+@Mapper
+public interface CoreTechnologyDetailMapper extends BaseMapperX<CoreTechnologyDetailDO> {
+
+    default PageResult<CoreTechnologyDetailDO> selectPage(CoreTechnologyDetailPageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<CoreTechnologyDetailDO>()
+                .eqIfPresent(CoreTechnologyDetailDO::getDeptId, reqVO.getDeptId())
+                .eqIfPresent(CoreTechnologyDetailDO::getTechnologyId, reqVO.getTechnologyId())
+                .betweenIfPresent(CoreTechnologyDetailDO::getProgressDate, reqVO.getProgressDate())
+                .eqIfPresent(CoreTechnologyDetailDO::getOverview, reqVO.getOverview())
+                .eqIfPresent(CoreTechnologyDetailDO::getSort, reqVO.getSort())
+                .eqIfPresent(CoreTechnologyDetailDO::getRemark, reqVO.getRemark())
+                .eqIfPresent(CoreTechnologyDetailDO::getStatus, reqVO.getStatus())
+                .betweenIfPresent(CoreTechnologyDetailDO::getCreateTime, reqVO.getCreateTime())
+                .orderByDesc(CoreTechnologyDetailDO::getId));
+    }
+
+    default List<CoreTechnologyDetailDO> technologyDetails(CoreTechnologyDetailPageReqVO reqVO) {
+        return selectList(new LambdaQueryWrapperX<CoreTechnologyDetailDO>()
+                .eqIfPresent(CoreTechnologyDetailDO::getDeptId, reqVO.getDeptId())
+                .eqIfPresent(CoreTechnologyDetailDO::getTechnologyId, reqVO.getTechnologyId())
+                .betweenIfPresent(CoreTechnologyDetailDO::getProgressDate, reqVO.getProgressDate())
+                .eqIfPresent(CoreTechnologyDetailDO::getOverview, reqVO.getOverview())
+                .eqIfPresent(CoreTechnologyDetailDO::getSort, reqVO.getSort())
+                .eqIfPresent(CoreTechnologyDetailDO::getRemark, reqVO.getRemark())
+                .eqIfPresent(CoreTechnologyDetailDO::getStatus, reqVO.getStatus())
+                .betweenIfPresent(CoreTechnologyDetailDO::getCreateTime, reqVO.getCreateTime())
+                .orderByDesc(CoreTechnologyDetailDO::getId));
+    }
+
+}

+ 63 - 0
yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/service/attachment/AttachmentService.java

@@ -0,0 +1,63 @@
+package cn.iocoder.yudao.module.rd.service.attachment;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.rd.controller.admin.attachment.vo.AttachmentPageReqVO;
+import cn.iocoder.yudao.module.rd.controller.admin.attachment.vo.AttachmentSaveReqVO;
+import cn.iocoder.yudao.module.rd.dal.dataobject.attachment.AttachmentDO;
+
+import javax.validation.Valid;
+import java.util.List;
+
+/**
+ * R&D 附件 Service 接口
+ *
+ * @author ruiqi
+ */
+public interface AttachmentService {
+
+    /**
+     * 创建R&D 附件
+     *
+     * @param createReqVO 创建信息
+     * @return 编号
+     */
+    Long createAttachment(@Valid AttachmentSaveReqVO createReqVO);
+
+    /**
+     * 更新R&D 附件
+     *
+     * @param updateReqVO 更新信息
+     */
+    void updateAttachment(@Valid AttachmentSaveReqVO updateReqVO);
+
+    /**
+     * 删除R&D 附件
+     *
+     * @param id 编号
+     */
+    void deleteAttachment(Long id);
+
+    /**
+     * 获得R&D 附件
+     *
+     * @param id 编号
+     * @return R&D 附件
+     */
+    AttachmentDO getAttachment(Long id);
+
+    /**
+     * 获得R&D 附件分页
+     *
+     * @param pageReqVO 分页查询
+     * @return R&D 附件分页
+     */
+    PageResult<AttachmentDO> getAttachmentPage(AttachmentPageReqVO pageReqVO);
+
+    /**
+     * 获得附件列表
+     *
+     * @param pageReqVO 列表查询
+     * @return 附件列表
+     */
+    List<AttachmentDO> getIotAttachments(AttachmentPageReqVO pageReqVO);
+}

+ 77 - 0
yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/service/attachment/AttachmentServiceImpl.java

@@ -0,0 +1,77 @@
+package cn.iocoder.yudao.module.rd.service.attachment;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.rd.controller.admin.attachment.vo.AttachmentPageReqVO;
+import cn.iocoder.yudao.module.rd.controller.admin.attachment.vo.AttachmentSaveReqVO;
+import cn.iocoder.yudao.module.rd.dal.dataobject.attachment.AttachmentDO;
+import cn.iocoder.yudao.module.rd.dal.mysql.attachment.AttachmentMapper;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.rd.enums.ErrorCodeConstant.ATTACHMENT_NOT_EXISTS;
+
+/**
+ * R&D 附件 Service 实现类
+ *
+ * @author ruiqi
+ */
+@Service
+@Validated
+public class AttachmentServiceImpl implements AttachmentService {
+
+    @Resource
+    private AttachmentMapper attachmentMapper;
+
+    @Override
+    public Long createAttachment(AttachmentSaveReqVO createReqVO) {
+        // 插入
+        AttachmentDO attachment = BeanUtils.toBean(createReqVO, AttachmentDO.class);
+        attachmentMapper.insert(attachment);
+        // 返回
+        return attachment.getId();
+    }
+
+    @Override
+    public void updateAttachment(AttachmentSaveReqVO updateReqVO) {
+        // 校验存在
+        validateAttachmentExists(updateReqVO.getId());
+        // 更新
+        AttachmentDO updateObj = BeanUtils.toBean(updateReqVO, AttachmentDO.class);
+        attachmentMapper.updateById(updateObj);
+    }
+
+    @Override
+    public void deleteAttachment(Long id) {
+        // 校验存在
+        validateAttachmentExists(id);
+        // 删除
+        attachmentMapper.deleteById(id);
+    }
+
+    private void validateAttachmentExists(Long id) {
+        if (attachmentMapper.selectById(id) == null) {
+            throw exception(ATTACHMENT_NOT_EXISTS);
+        }
+    }
+
+    @Override
+    public AttachmentDO getAttachment(Long id) {
+        return attachmentMapper.selectById(id);
+    }
+
+    @Override
+    public PageResult<AttachmentDO> getAttachmentPage(AttachmentPageReqVO pageReqVO) {
+        return attachmentMapper.selectPage(pageReqVO);
+    }
+
+    @Override
+    public List<AttachmentDO> getIotAttachments(AttachmentPageReqVO pageReqVO) {
+        return attachmentMapper.attachments(pageReqVO);
+    }
+
+}

+ 55 - 0
yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/service/coretechnology/CoreTechnologyService.java

@@ -0,0 +1,55 @@
+package cn.iocoder.yudao.module.rd.service.coretechnology;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.rd.controller.admin.coretechnology.vo.CoreTechnologyPageReqVO;
+import cn.iocoder.yudao.module.rd.controller.admin.coretechnology.vo.CoreTechnologySaveReqVO;
+import cn.iocoder.yudao.module.rd.dal.dataobject.coretechnology.CoreTechnologyDO;
+
+import javax.validation.Valid;
+
+/**
+ * 核心技术 Service 接口
+ *
+ * @author ruiqi
+ */
+public interface CoreTechnologyService {
+
+    /**
+     * 创建核心技术
+     *
+     * @param createReqVO 创建信息
+     * @return 编号
+     */
+    Long createCoreTechnology(@Valid CoreTechnologySaveReqVO createReqVO);
+
+    /**
+     * 更新核心技术
+     *
+     * @param updateReqVO 更新信息
+     */
+    void updateCoreTechnology(@Valid CoreTechnologySaveReqVO updateReqVO);
+
+    /**
+     * 删除核心技术
+     *
+     * @param id 编号
+     */
+    void deleteCoreTechnology(Long id);
+
+    /**
+     * 获得核心技术
+     *
+     * @param id 编号
+     * @return 核心技术
+     */
+    CoreTechnologyDO getCoreTechnology(Long id);
+
+    /**
+     * 获得核心技术分页
+     *
+     * @param pageReqVO 分页查询
+     * @return 核心技术分页
+     */
+    PageResult<CoreTechnologyDO> getCoreTechnologyPage(CoreTechnologyPageReqVO pageReqVO);
+
+}

+ 174 - 0
yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/service/coretechnology/CoreTechnologyServiceImpl.java

@@ -0,0 +1,174 @@
+package cn.iocoder.yudao.module.rd.service.coretechnology;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.rd.controller.admin.attachment.vo.AttachmentSaveReqVO;
+import cn.iocoder.yudao.module.rd.controller.admin.coretechnology.vo.CoreTechnologyPageReqVO;
+import cn.iocoder.yudao.module.rd.controller.admin.coretechnology.vo.CoreTechnologySaveReqVO;
+import cn.iocoder.yudao.module.rd.controller.admin.coretechnologydetail.vo.CoreTechnologyDetailSaveReqVO;
+import cn.iocoder.yudao.module.rd.dal.dataobject.attachment.AttachmentDO;
+import cn.iocoder.yudao.module.rd.dal.dataobject.coretechnology.CoreTechnologyDO;
+import cn.iocoder.yudao.module.rd.dal.dataobject.coretechnologydetail.CoreTechnologyDetailDO;
+import cn.iocoder.yudao.module.rd.dal.mysql.attachment.AttachmentMapper;
+import cn.iocoder.yudao.module.rd.dal.mysql.coretechnology.CoreTechnologyMapper;
+import cn.iocoder.yudao.module.rd.dal.mysql.coretechnologydetail.CoreTechnologyDetailMapper;
+import cn.iocoder.yudao.module.rd.enums.AttachmentCategoryEnum;
+import com.google.common.collect.ImmutableMap;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+import java.util.ArrayList;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.rd.enums.ErrorCodeConstant.CORE_TECHNOLOGY_NOT_EXISTS;
+
+/**
+ * 核心技术 Service 实现类
+ *
+ * @author ruiqi
+ */
+@Service
+@Validated
+public class CoreTechnologyServiceImpl implements CoreTechnologyService {
+
+    @Resource
+    private CoreTechnologyMapper coreTechnologyMapper;
+    @Resource
+    private AttachmentMapper attachmentMapper;
+    @Resource
+    private CoreTechnologyDetailMapper coreTechnologyDetailMapper;
+
+    @Override
+    public Long createCoreTechnology(CoreTechnologySaveReqVO createReqVO) {
+        // 插入
+        CoreTechnologyDO coreTechnology = BeanUtils.toBean(createReqVO, CoreTechnologyDO.class);
+        coreTechnologyMapper.insert(coreTechnology);
+        // 保存进度明细
+        if (CollUtil.isNotEmpty(createReqVO.getDetails())) {
+            // 先删除明细 再新增
+            List<CoreTechnologyDetailSaveReqVO> technologyDetails = createReqVO.getDetails();
+            // 新增 核心技术 进度 明细
+            List<CoreTechnologyDetailDO> details = new ArrayList<>();
+            technologyDetails.forEach(detail -> {
+                CoreTechnologyDetailDO tempDetail = BeanUtils.toBean(detail, CoreTechnologyDetailDO.class);
+                tempDetail.setDeptId(coreTechnology.getDeptId());
+                tempDetail.setTechnologyId(coreTechnology.getId());
+                details.add(tempDetail);
+            });
+            // 插入 进度 明细记录
+            if (CollUtil.isNotEmpty(details)) {
+                coreTechnologyDetailMapper.insertBatch(details);
+            }
+        }
+        // 保存附件列表
+        if (CollUtil.isNotEmpty(createReqVO.getAttachments())) {
+            List<AttachmentSaveReqVO> attachments = createReqVO.getAttachments();
+            List<AttachmentDO> tobeAddedAttachments = new ArrayList<>();
+            attachments.forEach(att -> {
+                AttachmentDO attachment = new AttachmentDO();
+                attachment.setBizId(coreTechnology.getId());
+                attachment.setCategory(AttachmentCategoryEnum.CORE_TECHNOLOGY.getCode());
+                attachment.setType(att.getType());
+                attachment.setFilePath(att.getFilePath());
+                attachment.setFileSize(att.getFileSize());
+                attachment.setFilename(att.getFilename());
+                attachment.setFileType(att.getFileType());
+                attachment.setRemark(att.getRemark());
+                tobeAddedAttachments.add(attachment);
+            });
+            if (CollUtil.isNotEmpty(tobeAddedAttachments)) {
+                attachmentMapper.insertBatch(tobeAddedAttachments);
+            }
+        }
+        // 返回
+        return coreTechnology.getId();
+    }
+
+    @Override
+    public void updateCoreTechnology(CoreTechnologySaveReqVO updateReqVO) {
+        // 校验存在
+        validateCoreTechnologyExists(updateReqVO.getId());
+        // 更新
+        CoreTechnologyDO updateObj = BeanUtils.toBean(updateReqVO, CoreTechnologyDO.class);
+        coreTechnologyMapper.updateById(updateObj);
+        // 更新 核心技术明细
+        if (CollUtil.isNotEmpty(updateReqVO.getDetails())) {
+            // 先删除明细 再新增
+            List<CoreTechnologyDetailSaveReqVO> technologyDetails = updateReqVO.getDetails();
+            int count = coreTechnologyDetailMapper.deleteByMap(ImmutableMap.of(
+                    "technology_id", updateObj.getId()
+            ));
+            // 新增 核心技术 进度 明细
+            List<CoreTechnologyDetailDO> details = new ArrayList<>();
+            technologyDetails.forEach(detail -> {
+                CoreTechnologyDetailDO tempDetail = BeanUtils.toBean(detail, CoreTechnologyDetailDO.class);
+                tempDetail.setDeptId(updateObj.getDeptId());
+                tempDetail.setTechnologyId(updateObj.getId());
+                details.add(tempDetail);
+            });
+            // 插入 进度 明细记录
+            if (CollUtil.isNotEmpty(details)) {
+                coreTechnologyDetailMapper.insertBatch(details);
+            }
+        }
+        // 更新 附件
+        if (CollUtil.isNotEmpty(updateReqVO.getAttachments())) {
+            List<AttachmentSaveReqVO> attachments = updateReqVO.getAttachments();
+            List<AttachmentDO> tobeAddedAttachments = new ArrayList<>();
+            attachments.forEach(att -> {
+                AttachmentDO attachment = new AttachmentDO();
+                attachment.setBizId(updateObj.getId());
+                attachment.setCategory(AttachmentCategoryEnum.CORE_TECHNOLOGY.getCode());
+                attachment.setType(att.getType());
+                attachment.setFilePath(att.getFilePath());
+                attachment.setFileSize(att.getFileSize());
+                attachment.setFilename(att.getFilename());
+                attachment.setFileType(att.getFileType());
+                attachment.setRemark(att.getRemark());
+                tobeAddedAttachments.add(attachment);
+            });
+            if (CollUtil.isNotEmpty(tobeAddedAttachments)) {
+                // 先删除再新增
+                int count = attachmentMapper.deleteByMap(ImmutableMap.of(
+                        "category", AttachmentCategoryEnum.CORE_TECHNOLOGY.getCode(),
+                        "biz_id", updateObj.getId()
+                ));
+                attachmentMapper.insertBatch(tobeAddedAttachments);
+            }
+        } else {
+            // 如果传递的附件列表为空 则删除已有的附件
+            int count = attachmentMapper.deleteByMap(ImmutableMap.of(
+                    "category", AttachmentCategoryEnum.CORE_TECHNOLOGY.getCode(),
+                    "biz_id", updateObj.getId()
+            ));
+        }
+    }
+
+    @Override
+    public void deleteCoreTechnology(Long id) {
+        // 校验存在
+        validateCoreTechnologyExists(id);
+        // 删除
+        coreTechnologyMapper.deleteById(id);
+    }
+
+    private void validateCoreTechnologyExists(Long id) {
+        if (coreTechnologyMapper.selectById(id) == null) {
+            throw exception(CORE_TECHNOLOGY_NOT_EXISTS);
+        }
+    }
+
+    @Override
+    public CoreTechnologyDO getCoreTechnology(Long id) {
+        return coreTechnologyMapper.selectById(id);
+    }
+
+    @Override
+    public PageResult<CoreTechnologyDO> getCoreTechnologyPage(CoreTechnologyPageReqVO pageReqVO) {
+        return coreTechnologyMapper.selectPage(pageReqVO);
+    }
+
+}

+ 64 - 0
yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/service/coretechnologydetail/CoreTechnologyDetailService.java

@@ -0,0 +1,64 @@
+package cn.iocoder.yudao.module.rd.service.coretechnologydetail;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.rd.controller.admin.coretechnologydetail.vo.CoreTechnologyDetailPageReqVO;
+import cn.iocoder.yudao.module.rd.controller.admin.coretechnologydetail.vo.CoreTechnologyDetailSaveReqVO;
+import cn.iocoder.yudao.module.rd.dal.dataobject.coretechnologydetail.CoreTechnologyDetailDO;
+
+import javax.validation.Valid;
+import java.util.List;
+
+/**
+ * 核心技术明细 Service 接口
+ *
+ * @author ruiqi
+ */
+public interface CoreTechnologyDetailService {
+
+    /**
+     * 创建核心技术明细
+     *
+     * @param createReqVO 创建信息
+     * @return 编号
+     */
+    Long createCoreTechnologyDetail(@Valid CoreTechnologyDetailSaveReqVO createReqVO);
+
+    /**
+     * 更新核心技术明细
+     *
+     * @param updateReqVO 更新信息
+     */
+    void updateCoreTechnologyDetail(@Valid CoreTechnologyDetailSaveReqVO updateReqVO);
+
+    /**
+     * 删除核心技术明细
+     *
+     * @param id 编号
+     */
+    void deleteCoreTechnologyDetail(Long id);
+
+    /**
+     * 获得核心技术明细
+     *
+     * @param id 编号
+     * @return 核心技术明细
+     */
+    CoreTechnologyDetailDO getCoreTechnologyDetail(Long id);
+
+    /**
+     * 获得核心技术明细分页
+     *
+     * @param pageReqVO 分页查询
+     * @return 核心技术明细分页
+     */
+    PageResult<CoreTechnologyDetailDO> getCoreTechnologyDetailPage(CoreTechnologyDetailPageReqVO pageReqVO);
+
+    /**
+     * 获得核心技术明细列表
+     *
+     * @param pageReqVO 列表查询
+     * @return 核心技术明细列表
+     */
+    List<CoreTechnologyDetailDO> getCoreTechnologyDetails(CoreTechnologyDetailPageReqVO pageReqVO);
+
+}

+ 77 - 0
yudao-module-rd/yudao-module-rd-biz/src/main/java/cn/iocoder/yudao/module/rd/service/coretechnologydetail/CoreTechnologyDetailServiceImpl.java

@@ -0,0 +1,77 @@
+package cn.iocoder.yudao.module.rd.service.coretechnologydetail;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.rd.controller.admin.coretechnologydetail.vo.CoreTechnologyDetailPageReqVO;
+import cn.iocoder.yudao.module.rd.controller.admin.coretechnologydetail.vo.CoreTechnologyDetailSaveReqVO;
+import cn.iocoder.yudao.module.rd.dal.dataobject.coretechnologydetail.CoreTechnologyDetailDO;
+import cn.iocoder.yudao.module.rd.dal.mysql.coretechnologydetail.CoreTechnologyDetailMapper;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.rd.enums.ErrorCodeConstant.CORE_TECHNOLOGY_DETAIL_NOT_EXISTS;
+
+/**
+ * 核心技术明细 Service 实现类
+ *
+ * @author ruiqi
+ */
+@Service
+@Validated
+public class CoreTechnologyDetailServiceImpl implements CoreTechnologyDetailService {
+
+    @Resource
+    private CoreTechnologyDetailMapper coreTechnologyDetailMapper;
+
+    @Override
+    public Long createCoreTechnologyDetail(CoreTechnologyDetailSaveReqVO createReqVO) {
+        // 插入
+        CoreTechnologyDetailDO coreTechnologyDetail = BeanUtils.toBean(createReqVO, CoreTechnologyDetailDO.class);
+        coreTechnologyDetailMapper.insert(coreTechnologyDetail);
+        // 返回
+        return coreTechnologyDetail.getId();
+    }
+
+    @Override
+    public void updateCoreTechnologyDetail(CoreTechnologyDetailSaveReqVO updateReqVO) {
+        // 校验存在
+        validateCoreTechnologyDetailExists(updateReqVO.getId());
+        // 更新
+        CoreTechnologyDetailDO updateObj = BeanUtils.toBean(updateReqVO, CoreTechnologyDetailDO.class);
+        coreTechnologyDetailMapper.updateById(updateObj);
+    }
+
+    @Override
+    public void deleteCoreTechnologyDetail(Long id) {
+        // 校验存在
+        validateCoreTechnologyDetailExists(id);
+        // 删除
+        coreTechnologyDetailMapper.deleteById(id);
+    }
+
+    private void validateCoreTechnologyDetailExists(Long id) {
+        if (coreTechnologyDetailMapper.selectById(id) == null) {
+            throw exception(CORE_TECHNOLOGY_DETAIL_NOT_EXISTS);
+        }
+    }
+
+    @Override
+    public CoreTechnologyDetailDO getCoreTechnologyDetail(Long id) {
+        return coreTechnologyDetailMapper.selectById(id);
+    }
+
+    @Override
+    public PageResult<CoreTechnologyDetailDO> getCoreTechnologyDetailPage(CoreTechnologyDetailPageReqVO pageReqVO) {
+        return coreTechnologyDetailMapper.selectPage(pageReqVO);
+    }
+
+    @Override
+    public List<CoreTechnologyDetailDO> getCoreTechnologyDetails(CoreTechnologyDetailPageReqVO pageReqVO) {
+        return coreTechnologyDetailMapper.technologyDetails(pageReqVO);
+    }
+
+}