kongzy
2024-10-12 3402a6cdef63a87cf046a8bbfdc2898bb842c93f
新增学时证书
已修改10个文件
已添加10个文件
697 ■■■■■ 文件已修改
exam-system/src/main/java/com/gkhy/exam/institutionalaccess/controller/ThCertController.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/institutionalaccess/controller/TripartiteInterfaceController.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/institutionalaccess/entity/ThCert.java 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/institutionalaccess/entity/ThCourseChapter.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/institutionalaccess/entity/ThQuestionBank.java 40 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/institutionalaccess/entity/ThStudyAuth.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/institutionalaccess/mapper/ThCertMapper.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/institutionalaccess/model/query/ThCertQuery.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/institutionalaccess/model/req/ThCertReqDTO.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/institutionalaccess/model/req/ThQuestionBankReqDTO.java 52 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/institutionalaccess/model/req/ThStudytAuthReqDTO.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/institutionalaccess/service/ThCertService.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/institutionalaccess/service/TripartiteInterfaceService.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/institutionalaccess/service/serviceImpl/ThCertServiceImpl.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/institutionalaccess/service/serviceImpl/TripartiteInterfaceServiceImpl.java 142 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/java/com/gkhy/exam/institutionalaccess/utils/ValidatorUtils.java 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
exam-system/src/main/resources/mapper/institutionaccess/ThCertMapper.xml 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/resources/application-dev.yml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/constant/ResultConstants.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
update.sql 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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));
    }
}
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
     */
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;
}
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;
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;
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;
}
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);
}
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;
}
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;
}
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;
}
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;
}
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);
}
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;
}
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,"学时证书新增失败");
        }
    }
}
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();
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;
    }
}
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>
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:
                # 从数据源开关/默认关闭
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,"数据条目量超过最大值"),
    ;
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;