From 3402a6cdef63a87cf046a8bbfdc2898bb842c93f Mon Sep 17 00:00:00 2001
From: kongzy <kongzy>
Date: 星期六, 12 十月 2024 14:09:47 +0800
Subject: [PATCH] 新增学时证书

---
 exam-system/src/main/java/com/gkhy/exam/institutionalaccess/entity/ThQuestionBank.java                              |   40 ++
 exam-system/src/main/java/com/gkhy/exam/institutionalaccess/utils/ValidatorUtils.java                               |   54 ++++
 exam-system/src/main/resources/mapper/institutionaccess/ThCertMapper.xml                                            |   27 ++
 update.sql                                                                                                          |   53 ++++
 exam-system/src/main/java/com/gkhy/exam/institutionalaccess/model/req/ThQuestionBankReqDTO.java                     |   52 +++
 exam-system/src/main/java/com/gkhy/exam/institutionalaccess/controller/TripartiteInterfaceController.java           |   14 +
 exam-system/src/main/java/com/gkhy/exam/institutionalaccess/entity/ThCert.java                                      |   74 ++++++
 exam-system/src/main/java/com/gkhy/exam/institutionalaccess/service/serviceImpl/ThCertServiceImpl.java              |   60 +++++
 exam-system/src/main/java/com/gkhy/exam/institutionalaccess/mapper/ThCertMapper.java                                |   18 +
 exam-system/src/main/java/com/gkhy/exam/institutionalaccess/service/ThCertService.java                              |   41 +++
 ruoyi-common/src/main/java/com/ruoyi/common/constant/ResultConstants.java                                           |    1 
 exam-system/src/main/java/com/gkhy/exam/institutionalaccess/model/req/ThStudytAuthReqDTO.java                       |    6 
 exam-system/src/main/java/com/gkhy/exam/institutionalaccess/model/query/ThCertQuery.java                            |   20 +
 exam-system/src/main/java/com/gkhy/exam/institutionalaccess/service/serviceImpl/TripartiteInterfaceServiceImpl.java |  142 ++++++++---
 exam-system/src/main/java/com/gkhy/exam/institutionalaccess/entity/ThCourseChapter.java                             |    3 
 exam-system/src/main/java/com/gkhy/exam/institutionalaccess/entity/ThStudyAuth.java                                 |    6 
 exam-system/src/main/java/com/gkhy/exam/institutionalaccess/controller/ThCertController.java                        |   24 ++
 exam-system/src/main/java/com/gkhy/exam/institutionalaccess/service/TripartiteInterfaceService.java                 |    8 
 exam-system/src/main/java/com/gkhy/exam/institutionalaccess/model/req/ThCertReqDTO.java                             |   50 ++++
 ruoyi-admin/src/main/resources/application-dev.yml                                                                  |    4 
 20 files changed, 636 insertions(+), 61 deletions(-)

diff --git a/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/controller/ThCertController.java b/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/controller/ThCertController.java
new file mode 100644
index 0000000..4bab197
--- /dev/null
+++ b/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/controller/ThCertController.java
@@ -0,0 +1,24 @@
+package com.gkhy.exam.institutionalaccess.controller;
+
+import com.gkhy.exam.institutionalaccess.model.query.ThCertQuery;
+import com.gkhy.exam.institutionalaccess.model.query.ThQuestionBankQuery;
+import com.gkhy.exam.institutionalaccess.service.ThCertService;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.page.TableDataInfo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/th/cert")
+public class ThCertController extends BaseController {
+    @Autowired
+    private ThCertService certService;
+
+    @GetMapping("/page")
+    public TableDataInfo page(ThCertQuery query) {
+        startPage();
+        return getDataTable(this.certService.listByPage(query));
+    }
+}
diff --git a/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/controller/TripartiteInterfaceController.java b/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/controller/TripartiteInterfaceController.java
index 1fe9fcb..88cc6e3 100644
--- a/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/controller/TripartiteInterfaceController.java
+++ b/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/controller/TripartiteInterfaceController.java
@@ -31,7 +31,7 @@
 
     @PostMapping("/question/bank")
     @RepeatedClick
-    public AjaxResult receiveQuestionBank(@RequestBody JSONObject jsonObject){
+    public AjaxResult receiveQuestionBank(@RequestBody JSONObject jsonObject) throws Exception {
         return success(tripartiteInterfaceService.receiveQuestionBank(jsonObject));
     }
     @PostMapping("/course")
@@ -78,6 +78,18 @@
     }
 
     /**
+     * 学时证书推送
+     * @param jsonObject
+     * @return
+     */
+    @RepeatedClick
+    @PostMapping("/certs")
+    public AjaxResult receiveCerts(@RequestBody JSONObject jsonObject) throws Exception {
+        return tripartiteInterfaceService.receiveCerts(jsonObject);
+    }
+
+
+    /**
      * 题库组卷
      * @param args
      */
diff --git a/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/entity/ThCert.java b/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/entity/ThCert.java
new file mode 100644
index 0000000..46740ec
--- /dev/null
+++ b/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/entity/ThCert.java
@@ -0,0 +1,74 @@
+package com.gkhy.exam.institutionalaccess.entity;
+
+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.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import nonapi.io.github.classgraph.json.Id;
+
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+
+
+@ApiModel("学时证书")
+@Data
+@TableName("th_cert")
+public class ThCert {
+    @Id
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    @ApiModelProperty("学时证书唯一标识")
+    private String uuid;
+
+    @ApiModelProperty("学员姓名")
+    private String name;
+
+    @ApiModelProperty("学员身份证号")
+    private String idcard;
+
+    @ApiModelProperty("批次标识")
+    private String batchUuid;
+
+    @ApiModelProperty("所属机构社会统一信用代码")
+    private String trainOrgName;
+
+    @ApiModelProperty("证书生成时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalTime certTime;
+
+    @ApiModelProperty("证书链接")
+    private String certUrl;
+
+    @ApiModelProperty("机构d")
+    private Long institutionId;
+
+    @ApiModelProperty("机构名称")
+    private String institutionName;
+
+    @ApiModelProperty("删除标识")
+    private Byte delFlag;
+
+    /** 创建者 */
+    private String createBy;
+
+    /** 创建时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime createTime;
+
+    /** 更新者 */
+    private String updateBy;
+
+    /** 更新时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime updateTime;
+
+
+    @ApiModelProperty("批次名称")
+    @TableField(exist = false)
+    private String batchName;
+}
diff --git a/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/entity/ThCourseChapter.java b/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/entity/ThCourseChapter.java
index 9f8718d..fd865f3 100644
--- a/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/entity/ThCourseChapter.java
+++ b/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/entity/ThCourseChapter.java
@@ -29,6 +29,9 @@
     private Long institutionId;
     private String courseUuid;
 
+    //讲师
+    private String teacher;
+
     //删除标志(0代表存在 2代表删除)
     private Byte delFlag;
 
diff --git a/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/entity/ThQuestionBank.java b/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/entity/ThQuestionBank.java
index 11e0eab..cf2e0e4 100644
--- a/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/entity/ThQuestionBank.java
+++ b/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/entity/ThQuestionBank.java
@@ -4,6 +4,7 @@
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import nonapi.io.github.classgraph.json.Id;
 
@@ -15,16 +16,39 @@
     @Id
     @TableId(type = IdType.AUTO)
     private Long id;
+
+    @ApiModelProperty("题库uuid")
     private String uuid;
-    private Long institutionId;;
+
+    @ApiModelProperty("题库名称")
+    private String name;
+
+    @ApiModelProperty("机构id")
+    private Long institutionId;
+
+    @ApiModelProperty("机构名称")
     private String institutionName;
-    private int lastMonthCount;
-    private int addCount;
-    private int reduceCount;
-    private BigDecimal brushRate;
-    private BigDecimal assemblyRate;
-    private String url;
-    private String month;
+
+    @ApiModelProperty("题库题目总数")
+    private Integer totalCount;
+
+    @ApiModelProperty("单选题数量")
+    private Integer singleCount;
+
+    @ApiModelProperty("多选题数量")
+    private Integer multiCount;
+
+    @ApiModelProperty("判断题数量")
+    private Integer judgeCount;
+
+    @ApiModelProperty("简答题数量")
+    private Integer easyCount;
+
+    @ApiModelProperty("混合题数量")
+    private Integer mixCount;
+
+    @ApiModelProperty("其他数量")
+    private Integer otherCount;
 
     //删除标志(0代表存在 2代表删除)
     private Byte delFlag;
diff --git a/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/entity/ThStudyAuth.java b/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/entity/ThStudyAuth.java
index 4a53bba..afff850 100644
--- a/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/entity/ThStudyAuth.java
+++ b/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/entity/ThStudyAuth.java
@@ -4,6 +4,7 @@
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import nonapi.io.github.classgraph.json.Id;
 
@@ -25,4 +26,9 @@
     private Byte faceType;
     private String studyDetailUuid;
     private String authVideo;
+
+    @ApiModelProperty("认证ip")
+    private String ip;
+    @ApiModelProperty("认证mac地址")
+    private String mac;
 }
diff --git a/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/mapper/ThCertMapper.java b/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/mapper/ThCertMapper.java
new file mode 100644
index 0000000..ab373e7
--- /dev/null
+++ b/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/mapper/ThCertMapper.java
@@ -0,0 +1,18 @@
+package com.gkhy.exam.institutionalaccess.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.gkhy.exam.institutionalaccess.entity.ThCert;
+import com.gkhy.exam.institutionalaccess.model.query.ThCertQuery;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+@Mapper
+public interface ThCertMapper extends BaseMapper<ThCert> {
+    /**
+     * 分页查询课时
+     * @param query
+     * @return
+     */
+    List<ThCert> listByPage(ThCertQuery query);
+}
diff --git a/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/model/query/ThCertQuery.java b/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/model/query/ThCertQuery.java
new file mode 100644
index 0000000..53a8f87
--- /dev/null
+++ b/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/model/query/ThCertQuery.java
@@ -0,0 +1,20 @@
+package com.gkhy.exam.institutionalaccess.model.query;
+
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Data
+public class ThCertQuery {
+    private String institutionName;
+
+    //证书生成开始时间
+    private LocalDateTime startTime;
+
+    //证书生成结束时间
+    private LocalDateTime endTime;
+
+    //机构代码
+    private String trainOrgName;
+
+}
diff --git a/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/model/req/ThCertReqDTO.java b/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/model/req/ThCertReqDTO.java
new file mode 100644
index 0000000..596c32f
--- /dev/null
+++ b/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/model/req/ThCertReqDTO.java
@@ -0,0 +1,50 @@
+package com.gkhy.exam.institutionalaccess.model.req;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.hibernate.validator.constraints.Length;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.Pattern;
+import java.time.LocalTime;
+
+
+@ApiModel("学时证书")
+@Data
+public class ThCertReqDTO {
+    @ApiModelProperty("学时证书唯一标识")
+    @NotBlank(message = "学时证书唯一标识不能为空")
+    @Pattern(regexp = "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",message = "uuid格式不正确")
+    private String uuid;
+
+    @ApiModelProperty("学员姓名")
+    @NotBlank(message = "学员姓名不能为空")
+    private String name;
+
+    @ApiModelProperty("学员身份证号")
+    @NotBlank(message = "学员身份证号不能为空")
+    @Length(min = 18, max = 18, message = "身份证号能为18位")
+    private String idcard;
+
+    @ApiModelProperty("批次标识")
+    @NotBlank(message = "批次标识不能为空")
+    @Pattern(regexp = "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",message = "批次标识格式不正确")
+    private String batchUuid;
+
+    @ApiModelProperty("所属机构社会统一信用代码")
+    @NotBlank(message = "机构社会统一信用代码不能为空")
+    private String trainOrgName;
+
+    @ApiModelProperty("证书生成时间")
+    @NotEmpty(message = "证书生成时间不能为空")
+    private LocalTime certTime;
+
+    @ApiModelProperty("证书链接")
+    @NotBlank(message = "证书链接不能为空")
+    private String certUrl;
+
+    @ApiModelProperty("删除标识")
+    private Byte delFlag;
+}
diff --git a/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/model/req/ThQuestionBankReqDTO.java b/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/model/req/ThQuestionBankReqDTO.java
index 1197183..9bbeb95 100644
--- a/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/model/req/ThQuestionBankReqDTO.java
+++ b/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/model/req/ThQuestionBankReqDTO.java
@@ -1,20 +1,58 @@
 package com.gkhy.exam.institutionalaccess.model.req;
 
 
+import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.Pattern;
 import java.math.BigDecimal;
 
 @Data
 public class ThQuestionBankReqDTO {
+    @ApiModelProperty("题库uuid")
+    @NotBlank(message = "题库唯一标识不能为空")
+    @Pattern(regexp = "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$",message = "uuid格式不正确")
     private String uuid;
-    private Integer lastMonthCount;
-    private Integer addCount;
-    private Integer reduceCount;
-    private BigDecimal brushRate;
-    private BigDecimal assemblyRate;
-    private String url;
-    private String month;
+
+    @NotBlank(message = "题库名称不能为空")
+    @ApiModelProperty("题库名称")
+    private String name;
+
+    @NotEmpty(message = "题库题目总数不能为空")
+    @Min(value = 0,message = "题库题目总数格式不正确")
+    @ApiModelProperty("题库题目总数")
+    private Integer totalCount;
+
+    @NotEmpty(message = "单选题数量不能为空")
+    @Min(value = 0,message = "单选题数量格式不正确")
+    @ApiModelProperty("单选题数量")
+    private Integer singleCount;
+
+    @NotEmpty(message = "多选题数量不能为空")
+    @Min(value = 0,message = "多选题数量格式不正确")
+    @ApiModelProperty("多选题数量")
+    private Integer multiCount;
+
+    @NotEmpty(message = "判断题数量不能为空")
+    @Min(value = 0,message = "判读题数量格式不正确")
+    @ApiModelProperty("判断题数量")
+    private Integer judgeCount;
+
+    @NotEmpty(message = "简答题数量不能为空")
+    @Min(value = 0,message = "简答题数量格式不正确")
+    @ApiModelProperty("简答题数量")
+    private Integer easyCount;
+
+    @ApiModelProperty("混合题数量")
+    private Integer mixCount;
+
+    @ApiModelProperty("其他题目数量")
+    private Integer otherCount;
+
+
     //删除标志(0代表存在 2代表删除)
     private Byte delFlag;
 }
diff --git a/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/model/req/ThStudytAuthReqDTO.java b/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/model/req/ThStudytAuthReqDTO.java
index 3e0595a..96e77f8 100644
--- a/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/model/req/ThStudytAuthReqDTO.java
+++ b/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/model/req/ThStudytAuthReqDTO.java
@@ -1,6 +1,7 @@
 package com.gkhy.exam.institutionalaccess.model.req;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
 import java.time.LocalDateTime;
@@ -14,4 +15,9 @@
     private LocalDateTime authTime;
     private Byte faceType;
     private String authVideo;
+
+    @ApiModelProperty("认证ip")
+    private String ip;
+    @ApiModelProperty("认证mac地址")
+    private String mac;
 }
diff --git a/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/service/ThCertService.java b/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/service/ThCertService.java
new file mode 100644
index 0000000..56420e2
--- /dev/null
+++ b/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/service/ThCertService.java
@@ -0,0 +1,41 @@
+package com.gkhy.exam.institutionalaccess.service;
+
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.gkhy.exam.institutionalaccess.entity.ThCert;
+import com.gkhy.exam.institutionalaccess.entity.ThQuestionBank;
+import com.gkhy.exam.institutionalaccess.model.query.ThCertQuery;
+import com.gkhy.exam.institutionalaccess.model.query.ThQuestionBankQuery;
+
+import java.util.List;
+
+public interface ThCertService extends IService<ThCert> {
+    /**
+     * 根据uuid查询学时证书
+     * @param uuid
+     * @return
+     */
+    ThCert getCertByUuid(String uuid);
+
+    /**
+     * 分页查询学时证书
+     * @param query
+     * @return
+     */
+    List<ThCert> listByPage(ThCertQuery query);
+
+    /**
+     * 更新学时证书
+     * @param certList
+     * @return
+     */
+    Integer updateBatch(List<ThCert> certList);
+
+    /**
+     * 批量新增学时证书
+     * @param certList
+     * @return
+     */
+    Integer insertBatch(List<ThCert> certList);
+
+}
diff --git a/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/service/TripartiteInterfaceService.java b/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/service/TripartiteInterfaceService.java
index d2ab937..84c21bc 100644
--- a/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/service/TripartiteInterfaceService.java
+++ b/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/service/TripartiteInterfaceService.java
@@ -5,7 +5,7 @@
 import com.ruoyi.common.core.domain.AjaxResult;
 
 public interface TripartiteInterfaceService {
-    boolean receiveQuestionBank(JSONObject jsonObject);
+    boolean receiveQuestionBank(JSONObject jsonObject) throws Exception;
 
     AjaxResult receiveCourse(JSONObject jsonObject);
 
@@ -23,4 +23,10 @@
 
     AjaxResult receiveBatchEnd(JSONObject jsonObject);
 
+    /**
+     * 学时证书推送
+     * @param jsonObject
+     * @return
+     */
+    AjaxResult receiveCerts(JSONObject jsonObject) throws Exception;
 }
diff --git a/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/service/serviceImpl/ThCertServiceImpl.java b/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/service/serviceImpl/ThCertServiceImpl.java
new file mode 100644
index 0000000..2f0f0d9
--- /dev/null
+++ b/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/service/serviceImpl/ThCertServiceImpl.java
@@ -0,0 +1,60 @@
+package com.gkhy.exam.institutionalaccess.service.serviceImpl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.gkhy.exam.institutionalaccess.entity.ThCert;
+import com.gkhy.exam.institutionalaccess.entity.ThQuestionBank;
+import com.gkhy.exam.institutionalaccess.mapper.ThCertMapper;
+import com.gkhy.exam.institutionalaccess.model.query.ThCertQuery;
+import com.gkhy.exam.institutionalaccess.service.ThCertService;
+import com.ruoyi.common.constant.ResultConstants;
+import com.ruoyi.common.enums.coalmineEnums.DeleteStatusEnum;
+import com.ruoyi.common.exception.BusinessException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+
+@Service("ThCertService")
+public class ThCertServiceImpl extends ServiceImpl<ThCertMapper, ThCert> implements ThCertService {
+    @Autowired
+    private ThCertMapper certMapper;
+    @Override
+    public ThCert getCertByUuid(String uuid) {
+        return getOne(Wrappers.<ThCert>lambdaQuery()
+                .eq(true,ThCert::getUuid,uuid)
+                .last(" limit 1"));
+    }
+
+    @Override
+    public List<ThCert> listByPage(ThCertQuery query) {
+        List<ThCert> certs = certMapper.listByPage(query);
+        return certs;
+    }
+
+
+    @Transactional
+    @Override
+    public Integer updateBatch(List<ThCert> certList) {
+        boolean b= updateBatchById(certList);
+        if(b){
+            return certList.size();
+        }else{
+            throw new BusinessException(this.getClass(), ResultConstants.BUSINESS_ERROR,"学时证书更新失败");
+        }
+    }
+
+    @Transactional
+    @Override
+    public Integer insertBatch(List<ThCert> certList) {
+        boolean b = saveBatch(certList);
+        if(b){
+            return certList.size();
+        }else{
+            throw new BusinessException(this.getClass(), ResultConstants.BUSINESS_ERROR,"学时证书新增失败");
+        }
+    }
+
+}
diff --git a/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/service/serviceImpl/TripartiteInterfaceServiceImpl.java b/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/service/serviceImpl/TripartiteInterfaceServiceImpl.java
index 4db8897..9bb6b63 100644
--- a/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/service/serviceImpl/TripartiteInterfaceServiceImpl.java
+++ b/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/service/serviceImpl/TripartiteInterfaceServiceImpl.java
@@ -3,6 +3,7 @@
 
 import cn.hutool.core.collection.ListUtil;
 import cn.hutool.core.util.IdUtil;
+import cn.hutool.core.util.ObjectUtil;
 import com.alibaba.fastjson2.JSONObject;
 import com.alibaba.fastjson2.TypeReference;
 import com.gkhy.exam.institutionalaccess.entity.*;
@@ -11,6 +12,7 @@
 import com.gkhy.exam.institutionalaccess.model.resp.ThErrorDataRespDTO;
 import com.gkhy.exam.institutionalaccess.model.vo.ThCourseChapterVO;
 import com.gkhy.exam.institutionalaccess.service.*;
+import com.gkhy.exam.institutionalaccess.utils.ValidatorUtils;
 import com.ruoyi.common.constant.ResultConstants;
 import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.common.core.domain.model.InstitutionUser;
@@ -63,9 +65,11 @@
     private ThBatchCourseChapterService batchCourseChapterService;
     @Autowired
     private ThSubjectTypeService subjectTypeService;
+    @Autowired
+    private ThCertService certService;
 
     @Override
-    public boolean receiveQuestionBank(JSONObject jsonObject) {
+    public boolean receiveQuestionBank(JSONObject jsonObject) throws Exception {
         InstitutionUser institutionUser = ThreeInContextHolder.getContext();
 
         String data = jsonObject.getString("data");
@@ -90,8 +94,11 @@
 
         }
 
-        //参数校验
-        validateQuestion(questionBankReqDTO);
+        String valdateMessage=ValidatorUtils.validateFast(questionBankReqDTO);
+        if(!StringUtils.isEmpty(valdateMessage)){
+            throw new BusinessException(this.getClass(), ResultConstants.THREE_INSTITUTION_PARAMM_NULL,valdateMessage);
+        }
+
         //根据uuid查询数据
         ThQuestionBank qb = questionBankService.getQuestionInfoByUuid(questionBankReqDTO.getUuid());
         boolean i = true;
@@ -102,19 +109,18 @@
             qb.setUuid(questionBankReqDTO.getUuid());
             qb.setInstitutionId(institutionUser.getId());
             qb.setInstitutionName(institutionUser.getInstitutionalName());
-            qb.setCreateTime(LocalDateTime.now());
-            qb.setUpdateTime(LocalDateTime.now());
             qb.setCreateBy(institutionUser.getInstitutionalName());
             qb.setUpdateBy(institutionUser.getInstitutionalName());
-            //qb.setDelFlag(DeleteStatusEnum.NO.getStatus());
             i = questionBankService.save(qb);
         }else {
             //修改
             BeanUtils.copyProperties(questionBankReqDTO, qb);
+            qb.setUpdateBy(institutionUser.getInstitutionalName());
             i = questionBankService.updateById(qb);
         }
         return i;
     }
+
     @Transactional
     @Override
     public AjaxResult receiveCourse(JSONObject jsonObject) {
@@ -1848,6 +1854,94 @@
         return AjaxResult.success();
     }
 
+    @Override
+    public AjaxResult receiveCerts(JSONObject jsonObject) throws Exception {
+        InstitutionUser institutionUser = ThreeInContextHolder.getContext();
+        String data = jsonObject.getString("data");
+        if(StringUtils.isEmpty(data)){
+            throw new BusinessException(this.getClass(), ResultConstants.THREE_INSTITUTION_PARAMM_NULL);
+        }
+        //解密
+        String decrypt = "";
+        try {
+            decrypt = AESUtils.decrypt(data);
+        }catch (Exception e){
+            throw new BusinessException(this.getClass(), ResultConstants.THREE_INSTITUTION_PARAMM_NULL);
+        }
+        //反序列化
+        List<ThCertReqDTO> thCertReqDTOs = null;
+        try {
+            thCertReqDTOs = JSONObject.parseObject(decrypt, new TypeReference<List<ThCertReqDTO>>() {});
+        }catch (Exception e){
+            logger.error("学时证书反序列化失败!");
+            throw new BusinessException(this.getClass(), ResultConstants.SERIALIZE_ERROR);
+        }
+        if(thCertReqDTOs.isEmpty() ||thCertReqDTOs.size()>50){
+            throw new BusinessException(this.getClass(), ResultConstants.RECORD_OVER_MAX);
+        }
+
+        //错误
+        List<ThErrorDataRespDTO> errorDataRespDTOS = new ArrayList<>();
+        List<ThCertReqDTO> saveCertReqDTOList = new ArrayList<>();
+        List<String> batchUuidList=thCertReqDTOs.stream().map(ThCertReqDTO::getBatchUuid).filter(batchUuid -> !StringUtils.isEmpty(batchUuid)).distinct().collect(Collectors.toList());
+        //获取批次
+        List<ThBatch> batchList = batchService.getByUuids(batchUuidList);
+
+        for(ThCertReqDTO thCertReqDTO : thCertReqDTOs){
+            String validateMessage=ValidatorUtils.validateFast(thCertReqDTO);
+            if(!StringUtils.isEmpty(validateMessage)){
+                errorDataRespDTOS.add(new ThErrorDataRespDTO(thCertReqDTO.getUuid(),validateMessage));
+                continue;
+            }
+            List<ThBatch> collect = batchList.stream().filter(batchCourse -> batchCourse.getUuid().equals(thCertReqDTO.getBatchUuid())).collect(Collectors.toList());
+            if (CollectionUtils.isEmpty(collect)) {
+                errorDataRespDTOS.add(new ThErrorDataRespDTO(thCertReqDTO.getUuid(), "批次(班级)不存在,请先添加批次(班级)"));
+                continue;
+            }
+            saveCertReqDTOList.add(thCertReqDTO);
+        }
+
+        List<ThCert> saveCertList = new ArrayList<>();
+        List<ThCert> updateCertList = new ArrayList<>();
+        for (ThCertReqDTO thCertReqDTO : saveCertReqDTOList) {
+            ThCert cert=certService.getCertByUuid(thCertReqDTO.getUuid());
+            if (cert!=null) {
+                //修改
+                BeanUtils.copyProperties(thCertReqDTO, cert);
+                cert.setUpdateBy(institutionUser.getInstitutionalName());
+                cert.setUpdateTime(LocalDateTime.now());
+                cert.setInstitutionId(institutionUser.getId());
+                cert.setInstitutionName(institutionUser.getInstitutionalName());
+                updateCertList.add(cert);
+            } else {
+                //新增
+                cert = new ThCert();
+                BeanUtils.copyProperties(thCertReqDTO, cert);
+                cert.setId(IdUtil.getSnowflake(0, 0).nextId());
+                cert.setUpdateBy(institutionUser.getInstitutionalName());
+                cert.setUpdateTime(LocalDateTime.now());
+                cert.setCreateBy(institutionUser.getInstitutionalName());
+                cert.setCreateTime(LocalDateTime.now());
+                cert.setInstitutionId(institutionUser.getId());
+                cert.setInstitutionName(institutionUser.getInstitutionalName());
+                cert.setDelFlag(DeleteStatusEnum.NO.getStatus());
+                saveCertList.add(cert);
+            }
+        }
+        //课时证书表新增
+        if(!saveCertList.isEmpty()){
+            certService.insertBatch(saveCertList);
+        }
+        //课时证书表更新
+        if(!updateCertList.isEmpty()) {
+            certService.updateBatch(updateCertList);
+        }
+        return AjaxResult.success(errorDataRespDTOS);
+    }
+
+    private void validate(){
+
+    }
 
 
     private void validateStudyDetail(ThStudyDetailReqDTO studentDetailReqDTO) {
@@ -2075,43 +2169,7 @@
     }
 
 
-    /**
-     * 校验题库组卷数据
-     * @param questionBankReqDTO
-     */
-     private void validateQuestion(ThQuestionBankReqDTO questionBankReqDTO){
 
-         if(questionBankReqDTO == null){
-             throw new BusinessException(this.getClass(), ResultConstants.THREE_INSTITUTION_PARAMM_ERROR);
-         }
-         if(StringUtils.isEmpty(questionBankReqDTO.getUuid()) || !UUID.checkIsUuid(questionBankReqDTO.getUuid())){
-             throw new BusinessException(this.getClass(), ResultConstants.THREE_INSTITUTION_PARAMM_NULL,"题库组卷uuid不符合规范");
-         }
-         if(StringUtils.isEmpty(questionBankReqDTO.getUrl())){
-             throw new BusinessException(this.getClass(), ResultConstants.THREE_INSTITUTION_PARAMM_NULL,"题库组卷预览路径不可为空");
-         }
-         if(questionBankReqDTO.getLastMonthCount() == null){
-             throw new BusinessException(this.getClass(), ResultConstants.THREE_INSTITUTION_PARAMM_NULL,"上月题库总题目数不可为空");
-         }
-         if(questionBankReqDTO.getAddCount() == null){
-             throw new BusinessException(this.getClass(), ResultConstants.THREE_INSTITUTION_PARAMM_NULL,"新增题目数不可为空");
-         }
-         if(questionBankReqDTO.getReduceCount() == null){
-             throw new BusinessException(this.getClass(), ResultConstants.THREE_INSTITUTION_PARAMM_NULL,"减少题目数不可为空");
-         }
-         if(questionBankReqDTO.getBrushRate() == null){
-             throw new BusinessException(this.getClass(), ResultConstants.THREE_INSTITUTION_PARAMM_NULL,"刷题应用率不可为空");
-         }
-         if(questionBankReqDTO.getAssemblyRate() == null){
-             throw new BusinessException(this.getClass(), ResultConstants.THREE_INSTITUTION_PARAMM_NULL,"组卷应用率不可为空");
-         }
-         if(questionBankReqDTO.getMonth() == null){
-             throw new BusinessException(this.getClass(), ResultConstants.THREE_INSTITUTION_PARAMM_NULL,"年月不可为空");
-         }
-         if(questionBankReqDTO.getDelFlag() == null || DeleteStatusEnum.getDeleteStatusEnum(questionBankReqDTO.getDelFlag()) == null ){
-             throw new BusinessException(this.getClass(), ResultConstants.THREE_INSTITUTION_PARAMM_NULL,"删除标识不符合规范");
-         }
-    }
     private String generateSerialNum() {
         Long count = studyDetailService.getCount();
         String strCount = count.toString();
diff --git a/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/utils/ValidatorUtils.java b/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/utils/ValidatorUtils.java
new file mode 100644
index 0000000..9e79a55
--- /dev/null
+++ b/exam-system/src/main/java/com/gkhy/exam/institutionalaccess/utils/ValidatorUtils.java
@@ -0,0 +1,54 @@
+package com.gkhy.exam.institutionalaccess.utils;
+
+import org.hibernate.validator.HibernateValidator;
+
+import javax.validation.ConstraintViolation;
+import javax.validation.Validation;
+import javax.validation.Validator;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+public class ValidatorUtils {
+
+    private static Validator validatorFast= Validation.byProvider(HibernateValidator.class).configure().failFast(true).buildValidatorFactory().getValidator();
+    private static Validator validatorAll= Validation.byProvider(HibernateValidator.class).configure().failFast(false).buildValidatorFactory().getValidator();
+
+    /**
+     * 校验遇到第一个不合法的字段直接返回不合法信息,后续字段不再校验
+     * @param domain
+     * @return
+     * @param <T>
+     * @throws Exception
+     */
+    public static <T> String validateFast(T domain) throws Exception{
+        Set<ConstraintViolation<T>> validateResult=validatorFast.validate(domain);
+        if(!validateResult.isEmpty()){
+            return validateResult.iterator().next().getPropertyPath()+":"+validateResult.iterator().next().getMessage();
+        }
+        return "";
+    }
+
+    /**
+     * 校验所有字段并返回不合法字段信息
+     * @param domain
+     * @return
+     * @param <T>
+     * @throws Exception
+     */
+    public static <T> List<String> validateAll(T domain) throws Exception{
+        List<String> messages=new ArrayList<>();
+        Set<ConstraintViolation<T>> validateResult=validatorAll.validate(domain);
+        if(!validateResult.isEmpty()){
+            Iterator<ConstraintViolation<T>> it=validateResult.iterator();
+            while (it.hasNext()){
+                ConstraintViolation<T> cv=it.next();
+                messages.add(cv.getPropertyPath()+":"+cv.getMessage());
+            }
+        }
+        return messages;
+    }
+
+
+}
diff --git a/exam-system/src/main/resources/mapper/institutionaccess/ThCertMapper.xml b/exam-system/src/main/resources/mapper/institutionaccess/ThCertMapper.xml
new file mode 100644
index 0000000..23e8467
--- /dev/null
+++ b/exam-system/src/main/resources/mapper/institutionaccess/ThCertMapper.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.gkhy.exam.institutionalaccess.mapper.ThCertMapper">
+
+    <select id="listByPage" resultType="com.gkhy.exam.institutionalaccess.entity.ThCert"
+            parameterType="com.gkhy.exam.institutionalaccess.model.query.ThCertQuery">
+        select a.*,b.batch_name  from th_cert a
+        left join th_batch b on a.batch_uuid=b.uuid
+        <where>
+            and a.del_flag=0
+            <if test="institutionName!=null and institutionName!=''">
+                 and a.institution_name =#{institutionName}
+            </if>
+            <if test="startTime!=null and startTime!=''">
+                and a.cert_ime &gt;= #{startTime}
+            </if>
+            <if test="endTime!=null and endTime!=''">
+                and a.cert_ime &lt;= #{endTime}
+            </if>
+            <if test="trainOrgName!=null and trainOrgName!=''">
+                and a.train_org_name =#{trainOrgName}
+            </if>
+        </where>
+        order by a.create_time desc
+    </select>
+</mapper>
+
diff --git a/ruoyi-admin/src/main/resources/application-dev.yml b/ruoyi-admin/src/main/resources/application-dev.yml
index 2fd873e..c028c4b 100644
--- a/ruoyi-admin/src/main/resources/application-dev.yml
+++ b/ruoyi-admin/src/main/resources/application-dev.yml
@@ -24,9 +24,9 @@
         druid:
             # 主库数据源
             master:
-                url: jdbc:mysql://localhost:3306/swspkmas?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true
+                url: jdbc:mysql://192.168.2.16:7006/swspkmas?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true
                 username: root
-                password: root
+                password: 2farwL3yPXfbH2AP
             # 从库数据源
             slave:
                 # 从数据源开关/默认关闭
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/ResultConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/ResultConstants.java
index b043cfa..6147017 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/constant/ResultConstants.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/ResultConstants.java
@@ -64,6 +64,7 @@
     BATCH_STUDENT_IS_NOT_EXIST(1014,"该学生培训信息不存在"),
     BATCH_IS_OPEN_NO_DELETE(1015,"批次(班级)已开班或已结束,不可删除"),
     THREE_INSTITUTION_OTHER_ERROR(1016,"业务错误"),
+    RECORD_OVER_MAX(1017,"数据条目量超过最大值"),
     ;
 
 
diff --git a/update.sql b/update.sql
new file mode 100644
index 0000000..0587aa5
--- /dev/null
+++ b/update.sql
@@ -0,0 +1,53 @@
+ALTER TABLE `swspkmas`.`th_study_auth`
+ADD COLUMN `ip` varchar(30) NULL,
+ADD COLUMN `max` varchar(40) NULL;
+
+CREATE TABLE `swspkmas`.`tr_cert`  (
+`id` bigint NOT NULL AUTO_INCREMENT,
+`uuid` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+`name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+`idcard` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+`institution_id` bigint NOT NULL,
+`institution_name` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+`batch_uuid` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+`del_flag` tinyint NOT NULL DEFAULT 0,
+`train_org_name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+`cert_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+`cert_time` datetime NOT NULL,
+`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+`create_by` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+`update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+`update_by` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+PRIMARY KEY (`id`) USING BTREE,
+UNIQUE INDEX `index_uuid`(`uuid`) USING BTREE,
+INDEX `index_idcard`(`idcard`) USING BTREE,
+INDEX `index_batchuuid`(`batch_uuid`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC;
+
+
+ALTER TABLE `swspkmas`.`th_course_chapter`
+ADD COLUMN `teacher` varchar(50) NULL COMMENT '讲师';
+
+
+drop table if exists `swspkmas`.`th_question_bank`;
+CREATE TABLE `swspkmas`.`th_question_bank`  (
+`id` bigint NOT NULL AUTO_INCREMENT,
+`uuid` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+`institution_id` bigint NOT NULL,
+`institution_name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+`total_count` int NOT NULL COMMENT '题库题目总数量',
+`single_count` int NOT NULL COMMENT '单选题题目数量',
+`multi_count` int NOT NULL COMMENT '多选题题目数量',
+`judge_count` int NOT NULL COMMENT '判断题题目数量',
+`easy_count` int NOT NULL COMMENT '简答题题目数量',
+`mix_count` int NOT NULL COMMENT '混合题题目数量',
+`other_count` int NOT NULL COMMENT '其他数量',
+`del_flag` tinyint NOT NULL DEFAULT 0,
+`create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP,
+`create_by` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+`update_by` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
+`update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+PRIMARY KEY (`id`) USING BTREE,
+UNIQUE INDEX `index_uuid`(`uuid`) USING BTREE,
+INDEX `index_institution_id`(`institution_id`) USING BTREE
+) ENGINE = InnoDB  AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC;

--
Gitblit v1.9.2