Merge pull request '崔智尧提交分支合并' (#12) from develop1 into develop

pull/13/head
p6pwfobyx 9 months ago
commit 3c5d2ff6a2

@ -1,13 +1,19 @@
package com.yf.exam.modules.paper.controller;
package com.yf.exam.modules.paper.controller; // 定义当前类所在的包路径
// 引入分页查询结果的接口
import com.baomidou.mybatisplus.core.metadata.IPage;
// 引入统一的API响应封装类
import com.yf.exam.core.api.ApiRest;
// 引入基础控制器类提供通用的API响应方法
import com.yf.exam.core.api.controller.BaseController;
// 引入各种DTO类用于请求和响应数据传输
import com.yf.exam.core.api.dto.BaseIdReqDTO;
import com.yf.exam.core.api.dto.BaseIdRespDTO;
import com.yf.exam.core.api.dto.BaseIdsReqDTO;
import com.yf.exam.core.api.dto.PagingReqDTO;
// 引入工具类,用于对象之间的属性拷贝
import com.yf.exam.core.utils.BeanMapper;
// 引入试卷相关的DTO类
import com.yf.exam.modules.paper.dto.PaperDTO;
import com.yf.exam.modules.paper.dto.ext.PaperQuDetailDTO;
import com.yf.exam.modules.paper.dto.request.PaperAnswerDTO;
@ -17,14 +23,22 @@ import com.yf.exam.modules.paper.dto.request.PaperQuQueryDTO;
import com.yf.exam.modules.paper.dto.response.ExamDetailRespDTO;
import com.yf.exam.modules.paper.dto.response.ExamResultRespDTO;
import com.yf.exam.modules.paper.dto.response.PaperListRespDTO;
// 引入试卷实体类
import com.yf.exam.modules.paper.entity.Paper;
// 引入试卷相关的业务处理服务类
import com.yf.exam.modules.paper.service.PaperService;
// 引入用户工具类,获取当前登录用户信息
import com.yf.exam.modules.user.UserUtils;
// 引入Swagger注解用于API文档生成
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
// 引入Shiro注解用于角色权限管理
import org.apache.shiro.authz.annotation.RequiresRoles;
// 引入Spring的Bean工具类用于属性复制
import org.springframework.beans.BeanUtils;
// 引入Spring的自动注入注解用于自动注入服务
import org.springframework.beans.factory.annotation.Autowired;
// 引入Spring的Web注解定义HTTP请求的映射方式
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@ -34,123 +48,126 @@ import org.springframework.web.bind.annotation.RestController;
* <p>
*
* </p>
*
*
* @author
* @since 2020-05-25 16:33
*/
@Api(tags={"试卷"})
@RestController
@RequestMapping("/exam/api/paper/paper")
public class PaperController extends BaseController {
@Api(tags={"试卷"}) // Swagger API 文档注解,用于描述该接口属于试卷相关操作
@RestController // 标记为Spring的控制器处理HTTP请求
@RequestMapping("/exam/api/paper/paper") // 定义请求路径的基础路径
public class PaperController extends BaseController { // 继承BaseController类提供基本的API返回
@Autowired
@Autowired // 自动注入PaperService负责业务逻辑处理
private PaperService baseService;
/**
*
* @param reqDTO
* @return
*
* @param reqDTO
* @return
*/
@ApiOperation(value = "分页查找")
@RequestMapping(value = "/paging", method = { RequestMethod.POST})
@ApiOperation(value = "分页查找") // Swagger操作注解用于描述接口
@RequestMapping(value = "/paging", method = { RequestMethod.POST}) // 定义POST请求路径
public ApiRest<IPage<PaperListRespDTO>> paging(@RequestBody PagingReqDTO<PaperListReqDTO> reqDTO) {
//分页查询并转换
// 调用业务层进行分页查询
IPage<PaperListRespDTO> page = baseService.paging(reqDTO);
// 返回成功响应,并附带查询结果
return super.success(page);
}
/**
*
* @param reqDTO
* @return
* @param reqDTO
* @return ID
*/
@ApiOperation(value = "创建试卷")
@RequestMapping(value = "/create-paper", method = { RequestMethod.POST})
@ApiOperation(value = "创建试卷") // Swagger操作注解用于描述接口
@RequestMapping(value = "/create-paper", method = { RequestMethod.POST}) // 定义POST请求路径
public ApiRest<BaseIdRespDTO> save(@RequestBody PaperCreateReqDTO reqDTO) {
//复制参数
// 调用业务层创建试卷传入当前用户ID和考试ID
String paperId = baseService.createPaper(UserUtils.getUserId(), reqDTO.getExamId());
// 返回创建结果包括试卷ID
return super.success(new BaseIdRespDTO(paperId));
}
/**
*
* @param reqDTO
* @return
*
* @param reqDTO ID
* @return
*/
@ApiOperation(value = "试卷详情")
@RequestMapping(value = "/paper-detail", method = { RequestMethod.POST})
@ApiOperation(value = "试卷详情") // Swagger操作注解用于描述接口
@RequestMapping(value = "/paper-detail", method = { RequestMethod.POST}) // 定义POST请求路径
public ApiRest<ExamDetailRespDTO> paperDetail(@RequestBody BaseIdReqDTO reqDTO) {
//根据ID删除
// 调用业务层获取试卷详情
ExamDetailRespDTO respDTO = baseService.paperDetail(reqDTO.getId());
// 返回成功响应,并附带试卷详情
return super.success(respDTO);
}
/**
*
* @param reqDTO
* @return
*
* @param reqDTO IDID
* @return
*/
@ApiOperation(value = "试题详情")
@RequestMapping(value = "/qu-detail", method = { RequestMethod.POST})
@ApiOperation(value = "试题详情") // Swagger操作注解用于描述接口
@RequestMapping(value = "/qu-detail", method = { RequestMethod.POST}) // 定义POST请求路径
public ApiRest<PaperQuDetailDTO> quDetail(@RequestBody PaperQuQueryDTO reqDTO) {
//根据ID删除
// 调用业务层获取试题详情
PaperQuDetailDTO respDTO = baseService.findQuDetail(reqDTO.getPaperId(), reqDTO.getQuId());
// 返回成功响应,并附带试题详情
return super.success(respDTO);
}
/**
*
* @param reqDTO
* @return
* @param reqDTO
* @return
*/
@ApiOperation(value = "填充答案")
@RequestMapping(value = "/fill-answer", method = { RequestMethod.POST})
@ApiOperation(value = "填充答案") // Swagger操作注解用于描述接口
@RequestMapping(value = "/fill-answer", method = { RequestMethod.POST}) // 定义POST请求路径
public ApiRest<PaperQuDetailDTO> fillAnswer(@RequestBody PaperAnswerDTO reqDTO) {
//根据ID删除
// 调用业务层填充答案操作
baseService.fillAnswer(reqDTO);
// 返回成功响应
return super.success();
}
/**
*
* @param reqDTO
* @return
* @param reqDTO ID
* @return
*/
@ApiOperation(value = "交卷操作")
@RequestMapping(value = "/hand-exam", method = { RequestMethod.POST})
@ApiOperation(value = "交卷操作") // Swagger操作注解用于描述接口
@RequestMapping(value = "/hand-exam", method = { RequestMethod.POST}) // 定义POST请求路径
public ApiRest<PaperQuDetailDTO> handleExam(@RequestBody BaseIdReqDTO reqDTO) {
//根据ID删除
// 调用业务层进行交卷操作
baseService.handExam(reqDTO.getId());
// 返回成功响应
return super.success();
}
/**
*
* @param reqDTO
* @return
*
* @param reqDTO ID
* @return
*/
@ApiOperation(value = "试卷详情")
@RequestMapping(value = "/paper-result", method = { RequestMethod.POST})
@ApiOperation(value = "试卷结果") // Swagger操作注解用于描述接口
@RequestMapping(value = "/paper-result", method = { RequestMethod.POST}) // 定义POST请求路径
public ApiRest<ExamResultRespDTO> paperResult(@RequestBody BaseIdReqDTO reqDTO) {
//根据ID删除
// 调用业务层获取试卷的考试结果
ExamResultRespDTO respDTO = baseService.paperResult(reqDTO.getId());
// 返回成功响应,并附带试卷结果
return super.success(respDTO);
}
/**
*
* @return
* @return
*/
@ApiOperation(value = "检测进行中的考试")
@RequestMapping(value = "/check-process", method = { RequestMethod.POST})
@ApiOperation(value = "检测进行中的考试") // Swagger操作注解用于描述接口
@RequestMapping(value = "/check-process", method = { RequestMethod.POST}) // 定义POST请求路径
public ApiRest<PaperDTO> checkProcess() {
//复制参数
// 调用业务层检测用户是否有未完成的考试
PaperDTO dto = baseService.checkProcess(UserUtils.getUserId());
// 返回成功响应,并附带考试进程数据
return super.success(dto);
}
}

@ -1,79 +1,83 @@
package com.yf.exam.modules.paper.dto;
package com.yf.exam.modules.paper.dto; // 定义当前类所在的包路径
// 引入Dict注解用于字典表的映射
import com.yf.exam.core.annon.Dict;
// 引入Swagger注解用于API文档生成
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
// 引入Lombok注解用于自动生成getter、setter等方法
import lombok.Data;
// 引入Serializable接口用于对象序列化
import java.io.Serializable;
// 引入Date类用于表示日期和时间
import java.util.Date;
/**
* <p>
*
* </p>
*
* @author
* @since 2020-05-25 17:31
*/
@Data
@ApiModel(value="试卷", description="试卷")
public class PaperDTO implements Serializable {
private static final long serialVersionUID = 1L;
* <p>
*
* </p>
* ID
* 使
*
* @author
* @since 2020-05-25 17:31
*/
@Data // Lombok注解自动生成getter、setter、toString、equals和hashCode方法
@ApiModel(value="试卷", description="试卷") // Swagger注解用于描述该类在API文档中的作用和说明
public class PaperDTO implements Serializable { // 实现Serializable接口表示该类的对象可以被序列化
private static final long serialVersionUID = 1L; // 序列化版本ID用于序列化和反序列化操作
@ApiModelProperty(value = "试卷ID", required=true)
private String id;
@ApiModelProperty(value = "试卷ID", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String id; // 试卷ID
@Dict(dictTable = "sys_user", dicText = "real_name", dicCode = "id")
@ApiModelProperty(value = "用户ID", required=true)
private String userId;
@Dict(dictTable = "sys_user", dicText = "real_name", dicCode = "id") // 字典表映射,映射用户表的姓名字段
@ApiModelProperty(value = "用户ID", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String userId; // 用户ID
@Dict(dictTable = "sys_depart", dicText = "dept_name", dicCode = "id")
@ApiModelProperty(value = "部门ID", required=true)
private String departId;
@Dict(dictTable = "sys_depart", dicText = "dept_name", dicCode = "id") // 字典表映射,映射部门表的部门名称字段
@ApiModelProperty(value = "部门ID", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String departId; // 部门ID
@ApiModelProperty(value = "规则ID", required=true)
private String examId;
@ApiModelProperty(value = "规则ID", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String examId; // 规则ID表示该试卷对应的考试规则
@ApiModelProperty(value = "考试标题", required=true)
private String title;
@ApiModelProperty(value = "考试标题", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String title; // 考试标题,表示试卷的名称
@ApiModelProperty(value = "考试时长", required=true)
private Integer totalTime;
@ApiModelProperty(value = "考试时长", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Integer totalTime; // 考试时长(单位:分钟)
@ApiModelProperty(value = "用户时长", required=true)
private Integer userTime;
@ApiModelProperty(value = "用户时长", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Integer userTime; // 用户已使用的时间(单位:分钟)
@ApiModelProperty(value = "试卷总分", required=true)
private Integer totalScore;
@ApiModelProperty(value = "试卷总分", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Integer totalScore; // 试卷总分
@ApiModelProperty(value = "及格分", required=true)
private Integer qualifyScore;
@ApiModelProperty(value = "及格分", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Integer qualifyScore; // 及格分数
@ApiModelProperty(value = "客观分", required=true)
private Integer objScore;
@ApiModelProperty(value = "客观分", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Integer objScore; // 客观题分数
@ApiModelProperty(value = "主观分", required=true)
private Integer subjScore;
@ApiModelProperty(value = "主观分", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Integer subjScore; // 主观题分数
@ApiModelProperty(value = "用户得分", required=true)
private Integer userScore;
@ApiModelProperty(value = "用户得分", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Integer userScore; // 用户得分
@ApiModelProperty(value = "是否包含简答题", required=true)
private Boolean hasSaq;
@ApiModelProperty(value = "是否包含简答题", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Boolean hasSaq; // 是否包含简答题,布尔类型,表示该试卷是否有简答题
@ApiModelProperty(value = "试卷状态", required=true)
private Integer state;
@ApiModelProperty(value = "试卷状态", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Integer state; // 试卷状态,表示试卷的当前状态,如未开始、进行中、已结束等
@ApiModelProperty(value = "创建时间", required=true)
private Date createTime;
@ApiModelProperty(value = "创建时间", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Date createTime; // 创建时间,表示试卷的创建时间
@ApiModelProperty(value = "更新时间", required=true)
private Date updateTime;
@ApiModelProperty(value = "更新时间", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Date updateTime; // 更新时间,表示试卷的最后更新时间
@ApiModelProperty(value = "截止时间")
private Date limitTime;
@ApiModelProperty(value = "截止时间") // Swagger注解描述该字段在API文档中的含义
private Date limitTime; // 截止时间,表示考试的最后提交时间
}

@ -1,48 +1,50 @@
package com.yf.exam.modules.paper.dto;
package com.yf.exam.modules.paper.dto; // 定义当前类所在的包路径
// 引入Swagger注解用于API文档生成
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
// 引入Lombok注解用于自动生成getter、setter等方法
import lombok.Data;
// 引入Serializable接口用于对象序列化
import java.io.Serializable;
/**
* <p>
*
* </p>
*
* @author
* @since 2020-05-25 17:31
*/
@Data
@ApiModel(value="试卷考题备选答案", description="试卷考题备选答案")
public class PaperQuAnswerDTO implements Serializable {
private static final long serialVersionUID = 1L;
* <p>
*
* </p>
* IDID
*
*
* @author
* @since 2020-05-25 17:31
*/
@Data // Lombok注解自动生成getter、setter、toString、equals和hashCode方法
@ApiModel(value="试卷考题备选答案", description="试卷考题备选答案") // Swagger注解用于描述该类在API文档中的作用和说明
public class PaperQuAnswerDTO implements Serializable { // 实现Serializable接口表示该类的对象可以被序列化
private static final long serialVersionUID = 1L; // 序列化版本ID用于序列化和反序列化操作
@ApiModelProperty(value = "自增ID", required=true)
private String id;
@ApiModelProperty(value = "自增ID", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String id; // 自增ID表示备选答案的唯一标识符
@ApiModelProperty(value = "试卷ID", required=true)
private String paperId;
@ApiModelProperty(value = "试卷ID", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String paperId; // 试卷ID表示该备选答案所属的试卷
@ApiModelProperty(value = "回答项ID", required=true)
private String answerId;
@ApiModelProperty(value = "回答项ID", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String answerId; // 回答项ID表示该备选答案的唯一标识符
@ApiModelProperty(value = "题目ID", required=true)
private String quId;
@ApiModelProperty(value = "题目ID", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String quId; // 题目ID表示该备选答案所属的题目
@ApiModelProperty(value = "是否正确项", required=true)
private Boolean isRight;
@ApiModelProperty(value = "是否正确项", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Boolean isRight; // 是否正确项,布尔值,表示该备选答案是否是正确答案
@ApiModelProperty(value = "是否选中", required=true)
private Boolean checked;
@ApiModelProperty(value = "是否选中", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Boolean checked; // 是否选中,布尔值,表示该备选答案是否已被选中
@ApiModelProperty(value = "排序", required=true)
private Integer sort;
@ApiModelProperty(value = "排序", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Integer sort; // 排序,表示该备选答案在题目中的排序位置
@ApiModelProperty(value = "选项标签", required=true)
private String abc;
@ApiModelProperty(value = "选项标签", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String abc; // 选项标签,通常为 A、B、C、D 等,表示该备选答案的标识符
}

@ -1,54 +1,55 @@
package com.yf.exam.modules.paper.dto;
package com.yf.exam.modules.paper.dto; // 定义当前类所在的包路径
// 引入Swagger注解用于API文档生成
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
// 引入Lombok注解用于自动生成getter、setter等方法
import lombok.Data;
// 引入Serializable接口用于对象序列化
import java.io.Serializable;
/**
* <p>
*
* </p>
*
* @author
* @since 2020-05-25 17:31
*/
@Data
@ApiModel(value="试卷考题", description="试卷考题")
public class PaperQuDTO implements Serializable {
private static final long serialVersionUID = 1L;
* <p>
*
* </p>
* IDID
*
* @author
* @since 2020-05-25 17:31
*/
@Data // Lombok注解自动生成getter、setter、toString、equals和hashCode方法
@ApiModel(value="试卷考题", description="试卷考题") // Swagger注解用于描述该类在API文档中的作用和说明
public class PaperQuDTO implements Serializable { // 实现Serializable接口表示该类的对象可以被序列化
private static final long serialVersionUID = 1L; // 序列化版本ID用于序列化和反序列化操作
@ApiModelProperty(value = "ID", required=true)
private String id;
@ApiModelProperty(value = "ID", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String id; // 题目ID唯一标识符
@ApiModelProperty(value = "试卷ID", required=true)
private String paperId;
@ApiModelProperty(value = "试卷ID", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String paperId; // 试卷ID表示该题目所属的试卷
@ApiModelProperty(value = "题目ID", required=true)
private String quId;
@ApiModelProperty(value = "题目ID", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String quId; // 题目ID唯一标识该题目
@ApiModelProperty(value = "题目类型", required=true)
private Integer quType;
@ApiModelProperty(value = "题目类型", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Integer quType; // 题目类型,表示题目的分类,如选择题、判断题、主观题等
@ApiModelProperty(value = "是否已答", required=true)
private Boolean answered;
@ApiModelProperty(value = "是否已答", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Boolean answered; // 是否已答,布尔值,表示该题目是否已被回答
@ApiModelProperty(value = "主观答案", required=true)
private String answer;
@ApiModelProperty(value = "主观答案", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String answer; // 主观答案,表示对该题目的回答内容(适用于主观题)
@ApiModelProperty(value = "问题排序", required=true)
private Integer sort;
@ApiModelProperty(value = "问题排序", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Integer sort; // 问题排序,表示该题目在试卷中的顺序
@ApiModelProperty(value = "单题分分值", required=true)
private Integer score;
@ApiModelProperty(value = "单题分分值", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Integer score; // 单题分值,表示该题目的满分
@ApiModelProperty(value = "实际得分(主观题)", required=true)
private Integer actualScore;
@ApiModelProperty(value = "实际得分(主观题)", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Integer actualScore; // 实际得分,表示用户在该题目中实际得到的分数(适用于主观题)
@ApiModelProperty(value = "是否答对", required=true)
private Boolean isRight;
@ApiModelProperty(value = "是否答对", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Boolean isRight; // 是否答对,布尔值,表示用户是否答对了该题目
}

@ -1,29 +1,30 @@
package com.yf.exam.modules.paper.dto.ext;
package com.yf.exam.modules.paper.dto.ext; // 定义该类所在的包路径
// 引入试题答案DTO类作为当前类的父类
import com.yf.exam.modules.paper.dto.PaperQuAnswerDTO;
// 引入Swagger注解用于API文档生成
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
// 引入Lombok注解用于自动生成getter、setter等方法
import lombok.Data;
/**
* <p>
*
* </p>
*
* PaperQuAnswerDTO
* @author
* @since 2020-05-25 17:31
*/
@Data
@ApiModel(value="试卷考题备选答案", description="试卷考题备选答案")
public class PaperQuAnswerExtDTO extends PaperQuAnswerDTO {
@Data // Lombok注解自动生成getter、setter、toString、equals和hashCode方法
@ApiModel(value="试卷考题备选答案", description="试卷考题备选答案") // Swagger注解描述模型信息生成API文档时使用
public class PaperQuAnswerExtDTO extends PaperQuAnswerDTO { // 继承自PaperQuAnswerDTO类扩展了额外属性
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L; // 序列化版本号,用于序列化和反序列化时的版本控制
@ApiModelProperty(value = "试题图片", required=true)
private String image;
@ApiModelProperty(value = "试题图片", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String image; // 试题对应的图片内容
@ApiModelProperty(value = "答案内容", required=true)
private String content;
@ApiModelProperty(value = "答案内容", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String content; // 备选答案的具体内容
}

@ -1,32 +1,35 @@
package com.yf.exam.modules.paper.dto.ext;
package com.yf.exam.modules.paper.dto.ext; // 定义当前类所在的包路径
// 引入试题DTO类作为当前类的父类
import com.yf.exam.modules.paper.dto.PaperQuDTO;
// 引入Swagger注解用于API文档生成
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
// 引入Lombok注解用于自动生成getter、setter等方法
import lombok.Data;
// 引入List集合用于存储多个备选答案
import java.util.List;
/**
* <p>
*
* </p>
*
* PaperQuDTO
* @author
* @since 2020-05-25 17:31
*/
@Data
@ApiModel(value="试卷题目详情类", description="试卷题目详情类")
public class PaperQuDetailDTO extends PaperQuDTO {
@Data // Lombok注解自动生成getter、setter、toString、equals和hashCode方法
@ApiModel(value="试卷题目详情类", description="试卷题目详情类") // Swagger注解用于描述该类在API文档中的作用和说明
public class PaperQuDetailDTO extends PaperQuDTO { // 继承自PaperQuDTO类扩展了额外属性
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L; // 序列化版本号,用于序列化和反序列化时的版本控制
@ApiModelProperty(value = "图片", required=true)
private String image;
@ApiModelProperty(value = "图片", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String image; // 题目的图片内容
@ApiModelProperty(value = "题目内容", required=true)
private String content;
@ApiModelProperty(value = "题目内容", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String content; // 试题的具体内容
@ApiModelProperty(value = "答案内容", required=true)
List<PaperQuAnswerExtDTO> answerList;
@ApiModelProperty(value = "答案内容", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private List<PaperQuAnswerExtDTO> answerList; // 存储该题目的备选答案使用List集合存储多个答案
}

@ -1,22 +1,25 @@
package com.yf.exam.modules.paper.dto.request;
package com.yf.exam.modules.paper.dto.request; // 定义当前类所在的包路径
// 引入Swagger注解用于API文档生成
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
// 引入Lombok注解用于自动生成getter、setter等方法
import lombok.Data;
// 引入List集合用于存储多个答案
import java.util.List;
/**
* @author bool
*
* PaperQuQueryDTO
*/
@Data
@ApiModel(value="查找试卷题目详情请求类", description="查找试卷题目详情请求类")
public class PaperAnswerDTO extends PaperQuQueryDTO {
@ApiModelProperty(value = "回答列表", required=true)
private List<String> answers;
@Data // Lombok注解自动生成getter、setter、toString、equals和hashCode方法
@ApiModel(value="查找试卷题目详情请求类", description="查找试卷题目详情请求类") // Swagger注解用于描述该类在API文档中的作用和说明
public class PaperAnswerDTO extends PaperQuQueryDTO { // 继承自PaperQuQueryDTO类扩展了额外属性
@ApiModelProperty(value = "主观答案", required=true)
private String answer;
@ApiModelProperty(value = "回答列表", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private List<String> answers; // 存储多个选择题答案的列表
@ApiModelProperty(value = "主观答案", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String answer; // 存储主观题的答案内容
}

@ -1,22 +1,26 @@
package com.yf.exam.modules.paper.dto.request;
package com.yf.exam.modules.paper.dto.request; // 定义当前类所在的包路径
// 引入父类BaseDTO用于继承基础字段和功能
import com.yf.exam.core.api.dto.BaseDTO;
// 引入Jackson注解用于处理JSON序列化时忽略某些字段
import com.fasterxml.jackson.annotation.JsonIgnore;
// 引入Swagger注解用于API文档生成
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
// 引入Lombok注解用于自动生成getter、setter等方法
import lombok.Data;
/**
* @author bool
* IDID
*/
@Data
@ApiModel(value="试卷创建请求类", description="试卷创建请求类")
public class PaperCreateReqDTO extends BaseDTO {
@Data // Lombok注解自动生成getter、setter、toString、equals和hashCode方法
@ApiModel(value="试卷创建请求类", description="试卷创建请求类") // Swagger注解用于描述该类在API文档中的作用和说明
public class PaperCreateReqDTO extends BaseDTO { // 继承自BaseDTO类扩展了考试ID和用户ID字段
@JsonIgnore
private String userId;
@ApiModelProperty(value = "考试ID", required=true)
private String examId;
@JsonIgnore // Jackson注解表示在进行JSON序列化/反序列化时忽略该字段
private String userId; // 存储用户ID通常用于标识发起请求的用户但在JSON序列化中不会被传递
@ApiModelProperty(value = "考试ID", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String examId; // 存储考试ID用于创建试卷时指定关联的考试
}

@ -1,39 +1,40 @@
package com.yf.exam.modules.paper.dto.request;
package com.yf.exam.modules.paper.dto.request; // 定义当前类所在的包路径
// 引入Swagger注解用于API文档生成
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
// 引入Lombok注解用于自动生成getter、setter等方法
import lombok.Data;
// 引入Serializable接口用于对象序列化
import java.io.Serializable;
/**
* <p>
*
* </p>
*
* IDIDID
*
* @author
* @since 2020-05-25 17:31
*/
@Data
@ApiModel(value="试卷", description="试卷")
public class PaperListReqDTO implements Serializable {
private static final long serialVersionUID = 1L;
@Data // Lombok注解自动生成getter、setter、toString、equals和hashCode方法
@ApiModel(value="试卷", description="试卷") // Swagger注解描述该类在API文档中的作用和说明
public class PaperListReqDTO implements Serializable { // 实现Serializable接口支持对象的序列化
@ApiModelProperty(value = "用户ID", required=true)
private String userId;
private static final long serialVersionUID = 1L; // 序列化版本号,用于序列化和反序列化时的版本控制
@ApiModelProperty(value = "部门ID", required=true)
private String departId;
@ApiModelProperty(value = "用户ID", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String userId; // 存储请求发起者的用户ID通常用于标识用户
@ApiModelProperty(value = "规则ID", required=true)
private String examId;
@ApiModelProperty(value = "部门ID", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String departId; // 存储请求者所在部门的ID用于查询特定部门的试卷
@ApiModelProperty(value = "用户昵称", required=true)
private String realName;
@ApiModelProperty(value = "规则ID", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String examId; // 存储与试卷相关的考试规则ID用于标识试卷属于哪种考试
@ApiModelProperty(value = "试卷状态", required=true)
private Integer state;
@ApiModelProperty(value = "用户昵称", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String realName; // 存储用户的真实姓名,用于标识请求者
@ApiModelProperty(value = "试卷状态", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Integer state; // 存储试卷的状态,可能的值如:未开始、进行中、已完成等
}

@ -1,21 +1,25 @@
package com.yf.exam.modules.paper.dto.request;
package com.yf.exam.modules.paper.dto.request; // 定义当前类所在的包路径
// 引入父类BaseDTO用于继承基础字段和功能
import com.yf.exam.core.api.dto.BaseDTO;
// 引入Swagger注解用于API文档生成
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
// 引入Lombok注解用于自动生成getter、setter等方法
import lombok.Data;
/**
* @author bool
*
* IDID
*/
@Data
@ApiModel(value="查找试卷题目详情请求类", description="查找试卷题目详情请求类")
public class PaperQuQueryDTO extends BaseDTO {
@Data // Lombok注解自动生成getter、setter、toString、equals和hashCode方法
@ApiModel(value="查找试卷题目详情请求类", description="查找试卷题目详情请求类") // Swagger注解用于描述该类在API文档中的作用和说明
public class PaperQuQueryDTO extends BaseDTO { // 继承自BaseDTO类扩展了试卷ID和题目ID字段
@ApiModelProperty(value = "试卷ID", required=true)
private String paperId;
@ApiModelProperty(value = "题目ID", required=true)
private String quId;
@ApiModelProperty(value = "试卷ID", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String paperId; // 存储试卷ID用于查询特定试卷的题目详情
@ApiModelProperty(value = "题目ID", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String quId; // 存储题目ID用于查询指定试卷中的某一道题目
}

@ -1,38 +1,48 @@
package com.yf.exam.modules.paper.dto.response;
package com.yf.exam.modules.paper.dto.response; // 定义当前类所在的包路径
// 引入父类PaperDTO用于继承基础字段和功能
import com.yf.exam.modules.paper.dto.PaperDTO;
// 引入PaperQuDTO类用于表示试题的DTO
import com.yf.exam.modules.paper.dto.PaperQuDTO;
// 引入Swagger注解用于API文档生成
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
// 引入Lombok注解用于自动生成getter、setter等方法
import lombok.Data;
// 引入Calendar类用于时间计算
import java.util.Calendar;
// 引入List集合用于存储试题列表
import java.util.List;
@Data
@ApiModel(value="考试详情", description="考试详情")
public class ExamDetailRespDTO extends PaperDTO {
/**
* <p>
*
* </p>
* PaperDTO
*
*/
@Data // Lombok注解自动生成getter、setter、toString、equals和hashCode方法
@ApiModel(value="考试详情", description="考试详情") // Swagger注解用于描述该类在API文档中的作用和说明
public class ExamDetailRespDTO extends PaperDTO { // 继承自PaperDTO表示考试详情响应DTO
@ApiModelProperty(value = "单选题列表", required=true)
private List<PaperQuDTO> radioList;
@ApiModelProperty(value = "单选题列表", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private List<PaperQuDTO> radioList; // 存储单选题的列表使用PaperQuDTO表示单个试题
@ApiModelProperty(value = "多选题列表", required=true)
private List<PaperQuDTO> multiList;
@ApiModelProperty(value = "多选题列表", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private List<PaperQuDTO> multiList; // 存储多选题的列表使用PaperQuDTO表示单个试题
@ApiModelProperty(value = "判断题", required=true)
private List<PaperQuDTO> judgeList;
@ApiModelProperty(value = "判断题", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private List<PaperQuDTO> judgeList; // 存储判断题的列表使用PaperQuDTO表示单个试题
@ApiModelProperty(value = "剩余结束秒数", required=true)
public Long getLeftSeconds(){
@ApiModelProperty(value = "剩余结束秒数", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
public Long getLeftSeconds(){ // 计算剩余时间的方法,返回剩余的秒数
// 结束时间
Calendar cl = Calendar.getInstance();
cl.setTime(this.getCreateTime());
cl.add(Calendar.MINUTE, getTotalTime());
Calendar cl = Calendar.getInstance(); // 获取当前时间的Calendar实例
cl.setTime(this.getCreateTime()); // 设置Calendar的时间为试卷的创建时间
cl.add(Calendar.MINUTE, getTotalTime()); // 在创建时间的基础上加上试卷的总时间(分钟)
return (cl.getTimeInMillis() - System.currentTimeMillis()) / 1000;
// 计算剩余时间(单位:秒)
return (cl.getTimeInMillis() - System.currentTimeMillis()) / 1000; // 返回剩余时间(当前时间到结束时间的差值,以秒为单位)
}
}

@ -1,18 +1,29 @@
package com.yf.exam.modules.paper.dto.response;
package com.yf.exam.modules.paper.dto.response; // 定义当前类所在的包路径
// 引入父类PaperDTO用于继承基础字段和功能
import com.yf.exam.modules.paper.dto.PaperDTO;
// 引入PaperQuDetailDTO类用于表示试题详细信息
import com.yf.exam.modules.paper.dto.ext.PaperQuDetailDTO;
// 引入Swagger注解用于API文档生成
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
// 引入Lombok注解用于自动生成getter、setter等方法
import lombok.Data;
// 引入List集合用于存储试题列表
import java.util.List;
@Data
@ApiModel(value="考试结果展示响应类", description="考试结果展示响应类")
public class ExamResultRespDTO extends PaperDTO {
/**
* <p>
*
* </p>
* PaperDTO
*
*/
@Data // Lombok注解自动生成getter、setter、toString、equals和hashCode方法
@ApiModel(value="考试结果展示响应类", description="考试结果展示响应类") // Swagger注解用于描述该类在API文档中的作用和说明
public class ExamResultRespDTO extends PaperDTO { // 继承自PaperDTO表示考试结果展示响应DTO
@ApiModelProperty(value = "问题列表", required=true)
private List<PaperQuDetailDTO> quList;
@ApiModelProperty(value = "问题列表", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private List<PaperQuDetailDTO> quList; // 存储试题详细信息的列表使用PaperQuDetailDTO表示每个试题的详细数据
}

@ -1,26 +1,29 @@
package com.yf.exam.modules.paper.dto.response;
package com.yf.exam.modules.paper.dto.response; // 定义当前类所在的包路径
// 引入父类PaperDTO用于继承基本的试卷信息
import com.yf.exam.modules.paper.dto.PaperDTO;
// 引入Swagger注解用于API文档生成
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
// 引入Lombok注解用于自动生成getter、setter等方法
import lombok.Data;
/**
* <p>
*
* </p>
*
* @author
* @since 2020-05-25 17:31
*/
@Data
@ApiModel(value="试卷列表响应类", description="试卷列表响应类")
public class PaperListRespDTO extends PaperDTO {
* <p>
*
* </p>
* PaperDTOrealName
*
*
* @author
* @since 2020-05-25 17:31
*/
@Data // Lombok注解自动生成getter、setter、toString、equals和hashCode方法
@ApiModel(value="试卷列表响应类", description="试卷列表响应类") // Swagger注解用于描述该类在API文档中的作用和说明
public class PaperListRespDTO extends PaperDTO { // 继承自PaperDTO表示试卷列表响应DTO
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L; // 序列化版本ID用于序列化和反序列化操作
@ApiModelProperty(value = "人员", required=true)
private String realName;
@ApiModelProperty(value = "人员", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String realName; // 存储人员姓名,用于表示与该试卷相关的人员信息
}

@ -1,125 +1,104 @@
package com.yf.exam.modules.paper.entity;
package com.yf.exam.modules.paper.entity; // 定义当前类所在的包路径
// 引入MyBatis Plus的相关注解
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
// 引入Lombok注解用于自动生成getter、setter等方法
import lombok.Data;
// 引入Date类用于时间相关的字段
import java.util.Date;
/**
* <p>
*
* </p>
*
* @author
* @since 2020-05-25 17:31
*/
@Data
@TableName("el_paper")
public class Paper extends Model<Paper> {
private static final long serialVersionUID = 1L;
* <p>
*
* </p>
* `el_paper`
*
* @author
* @since 2020-05-25 17:31
*/
@Data // Lombok注解自动生成getter、setter、toString、equals和hashCode方法
@TableName("el_paper") // MyBatis Plus注解指定该实体类对应的数据库表名
public class Paper extends Model<Paper> { // 继承MyBatis Plus的Model类提供了CRUD等基础操作
private static final long serialVersionUID = 1L; // 序列化版本ID用于序列化和反序列化操作
/**
* ID
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private String id;
@TableId(value = "id", type = IdType.ASSIGN_ID) // MyBatis Plus注解指定主键字段及其生成策略
private String id; // 试卷ID唯一标识符
/**
* ID
*/
@TableField("user_id")
private String userId;
@TableField("user_id") // MyBatis Plus注解指定字段与数据库表字段的映射关系
private String userId; // 用户ID表示创建该试卷的用户
/**
* ID
*/
@TableField("depart_id")
private String departId;
@TableField("depart_id") // MyBatis Plus注解指定字段与数据库表字段的映射关系
private String departId; // 部门ID表示该试卷所属的部门
/**
* ID
*/
@TableField("exam_id")
private String examId;
@TableField("exam_id") // MyBatis Plus注解指定字段与数据库表字段的映射关系
private String examId; // 规则ID表示该试卷所属的考试规则
/**
*
*/
private String title;
private String title; // 考试标题,表示试卷的名称或标题
/**
*
*/
@TableField("total_time")
private Integer totalTime;
@TableField("total_time") // MyBatis Plus注解指定字段与数据库表字段的映射关系
private Integer totalTime; // 考试时长,单位为分钟
/**
*
*/
@TableField("user_time")
private Integer userTime;
@TableField("user_time") // MyBatis Plus注解指定字段与数据库表字段的映射关系
private Integer userTime; // 用户实际用时,单位为分钟
/**
*
*/
@TableField("total_score")
private Integer totalScore;
@TableField("total_score") // MyBatis Plus注解指定字段与数据库表字段的映射关系
private Integer totalScore; // 试卷的总分数
/**
*
*/
@TableField("qualify_score")
private Integer qualifyScore;
@TableField("qualify_score") // MyBatis Plus注解指定字段与数据库表字段的映射关系
private Integer qualifyScore; // 及格分数,表示通过该试卷的最低分数
/**
*
*/
@TableField("obj_score")
private Integer objScore;
@TableField("obj_score") // MyBatis Plus注解指定字段与数据库表字段的映射关系
private Integer objScore; // 客观题部分的得分
/**
*
*/
@TableField("subj_score")
private Integer subjScore;
@TableField("subj_score") // MyBatis Plus注解指定字段与数据库表字段的映射关系
private Integer subjScore; // 主观题部分的得分
/**
*
*/
@TableField("user_score")
private Integer userScore;
@TableField("user_score") // MyBatis Plus注解指定字段与数据库表字段的映射关系
private Integer userScore; // 用户在该试卷上的得分
/**
*
*/
@TableField("has_saq")
private Boolean hasSaq;
/**
*
*/
private Integer state;
/**
*
*/
@TableField("create_time")
private Date createTime;
/**
*
*/
@TableField("update_time")
private Date updateTime;
/**
*
*/
@TableField("limit_time")
private Date limitTime;
}
@TableField("has_saq") // MyBatis Plus注解指定字段与数据库表字段的映射关系

@ -1,80 +1,82 @@
package com.yf.exam.modules.paper.entity;
package com.yf.exam.modules.paper.entity; // 定义当前类所在的包路径
// 引入MyBatis Plus的相关注解
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
// 引入Lombok注解用于自动生成getter、setter等方法
import lombok.Data;
/**
* <p>
*
* </p>
*
* @author
* @since 2020-05-25 17:31
*/
@Data
@TableName("el_paper_qu")
public class PaperQu extends Model<PaperQu> {
* <p>
*
* </p>
* `el_paper_qu`
*
* @author
* @since 2020-05-25 17:31
*/
@Data // Lombok注解自动生成getter、setter、toString、equals和hashCode方法
@TableName("el_paper_qu") // MyBatis Plus注解指定该实体类对应的数据库表名
public class PaperQu extends Model<PaperQu> { // 继承MyBatis Plus的Model类提供了基础的CRUD等操作
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L; // 序列化版本ID用于序列化和反序列化操作
/**
* ID
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private String id;
@TableId(value = "id", type = IdType.ASSIGN_ID) // MyBatis Plus注解指定主键字段及其生成策略
private String id; // 题目ID唯一标识符
/**
* ID
*/
@TableField("paper_id")
private String paperId;
@TableField("paper_id") // MyBatis Plus注解指定字段与数据库表字段的映射关系
private String paperId; // 试卷ID表示该题目所属的试卷ID
/**
* ID
*/
@TableField("qu_id")
private String quId;
@TableField("qu_id") // MyBatis Plus注解指定字段与数据库表字段的映射关系
private String quId; // 题目ID唯一标识符
/**
*
*/
@TableField("qu_type")
private Integer quType;
@TableField("qu_type") // MyBatis Plus注解指定字段与数据库表字段的映射关系
private Integer quType; // 题目类型,表示该题目属于哪种类型(例如单选题、多选题、主观题等)
/**
*
*/
private Boolean answered;
private Boolean answered; // 是否已经回答,布尔值,表示该题目是否已经被回答
/**
*
*/
private String answer;
private String answer; // 主观题的答案,保存用户的回答内容
/**
*
*/
private Integer sort;
private Integer sort; // 问题在试卷中的排序,决定题目的显示顺序
/**
*
*/
private Integer score;
private Integer score; // 每道题的分值,表示该题目的得分值
/**
* ()
*/
@TableField("actual_score")
private Integer actualScore;
@TableField("actual_score") // MyBatis Plus注解指定字段与数据库表字段的映射关系
private Integer actualScore; // 主观题的实际得分,可能与用户给出的答案相关
/**
*
*/
@TableField("is_right")
private Boolean isRight;
@TableField("is_right") // MyBatis Plus注解指定字段与数据库表字段的映射关系
private Boolean isRight; // 是否答对,布尔值,表示用户是否答对了该题目
}

@ -1,68 +1,71 @@
package com.yf.exam.modules.paper.entity;
package com.yf.exam.modules.paper.entity; // 定义当前类所在的包路径
// 引入MyBatis Plus的相关注解
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
// 引入Lombok注解用于自动生成getter、setter等方法
import lombok.Data;
/**
* <p>
*
* </p>
*
* @author
* @since 2020-05-25 17:31
*/
@Data
@TableName("el_paper_qu_answer")
public class PaperQuAnswer extends Model<PaperQuAnswer> {
* <p>
*
* </p>
* `el_paper_qu_answer`
*
* @author
* @since 2020-05-25 17:31
*/
@Data // Lombok注解自动生成getter、setter、toString、equals和hashCode方法
@TableName("el_paper_qu_answer") // MyBatis Plus注解指定该实体类对应的数据库表名
public class PaperQuAnswer extends Model<PaperQuAnswer> { // 继承MyBatis Plus的Model类提供了基础的CRUD等操作
private static final long serialVersionUID = 1L; // 序列化版本ID用于序列化和反序列化操作
/**
* ID
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private String id;
@TableId(value = "id", type = IdType.ASSIGN_ID) // MyBatis Plus注解指定主键字段及其生成策略
private String id; // 唯一标识符ID数据库中的主键
/**
* ID
*/
@TableField("paper_id")
private String paperId;
@TableField("paper_id") // MyBatis Plus注解指定字段与数据库表字段的映射关系
private String paperId; // 该备选答案对应的试卷ID
/**
* ID
*/
@TableField("answer_id")
private String answerId;
@TableField("answer_id") // MyBatis Plus注解指定字段与数据库表字段的映射关系
private String answerId; // 该备选答案的唯一标识符ID
/**
* ID
*/
@TableField("qu_id")
private String quId;
@TableField("qu_id") // MyBatis Plus注解指定字段与数据库表字段的映射关系
private String quId; // 该备选答案所属的题目ID
/**
*
*/
@TableField("is_right")
private Boolean isRight;
@TableField("is_right") // MyBatis Plus注解指定字段与数据库表字段的映射关系
private Boolean isRight; // 是否是正确答案布尔值true 表示正确false 表示错误)
/**
*
*/
private Boolean checked;
private Boolean checked; // 该备选答案是否被选中布尔值true 表示已选中false 表示未选中)
/**
*
*/
private Integer sort;
private Integer sort; // 备选答案的排序,决定该答案在选项中的位置
/**
*
*/
private String abc;
private String abc; // 备选答案的标签通常为A、B、C、D等用于显示选项
}

@ -1,33 +1,38 @@
package com.yf.exam.modules.paper.enums;
package com.yf.exam.modules.paper.enums; // 定义当前类所在的包路径
/**
*
* @author bool
* <p>
*
* </p>
* 使
*
* @author bool
* @date 2019-10-30 13:11
*/
public interface ExamState {
/**
*
*
*/
Integer ENABLE = 0;
/**
*
*
*/
Integer DISABLED = 1;
/**
*
*
*/
Integer READY_START = 2;
/**
*
*
*/
Integer OVERDUE = 3;
}

@ -1,33 +1,38 @@
package com.yf.exam.modules.paper.enums;
package com.yf.exam.modules.paper.enums; // 定义当前类所在的包路径
/**
*
* @author bool
* <p>
*
* </p>
* 使
*
* @author bool
* @date 2019-10-30 13:11
*/
public interface PaperState {
/**
*
*
*/
Integer ING = 0;
/**
*
*
*/
Integer WAIT_OPT = 1;
/**
*
*
*/
Integer FINISHED = 2;
/**
*
* 退
*/
Integer BREAK = 3;
}

@ -1,45 +1,61 @@
package com.yf.exam.modules.paper.job;
import com.yf.exam.ability.job.service.JobService;
import com.yf.exam.modules.paper.service.PaperService;
import lombok.extern.log4j.Log4j2;
import org.quartz.Job;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
package com.yf.exam.modules.paper.job; // 定义类所在的包路径
import com.yf.exam.ability.job.service.JobService; // 导入 JobService 类,用于获取任务数据
import com.yf.exam.modules.paper.service.PaperService; // 导入 PaperService 类,用于处理试卷相关的业务逻辑
import lombok.extern.log4j.Log4j2; // 引入 log4j2 日志工具
import org.quartz.Job; // 导入 Quartz 作业接口
import org.quartz.JobDetail; // 导入 Quartz JobDetail 类
import org.quartz.JobExecutionContext; // 导入 Quartz JobExecutionContext 类
import org.quartz.JobExecutionException; // 导入 Quartz JobExecutionException 类
import org.springframework.beans.factory.annotation.Autowired; // 引入 Spring 注解,用于自动注入依赖
import org.springframework.stereotype.Component; // 引入 Spring 组件注解,标识为 Spring Bean
/**
*
* <p>
* Quartz
* PaperService
* </p>
*
* @author bool
*/
@Log4j2
@Component
@Log4j2 // 启用 log4j2 日志记录
@Component // 标识该类为一个 Spring 组件Spring 会自动将其注册为 Bean
public class BreakExamJob implements Job {
// 自动注入 PaperService用于处理与试卷相关的业务逻辑
@Autowired
private PaperService paperService;
/**
*
*
* <p>
* Quartz
* PaperService
* </p>
*
* @param jobExecutionContext Quartz
* @throws JobExecutionException
*/
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
JobDetail detail = jobExecutionContext.getJobDetail();
String name = detail.getKey().getName();
String group = detail.getKey().getGroup();
// 从 jobExecutionContext 中获取任务的详细信息
JobDetail detail = jobExecutionContext.getJobDetail(); // 获取任务详情
String name = detail.getKey().getName(); // 获取任务名称
String group = detail.getKey().getGroup(); // 获取任务分组
// 获取任务的附加数据,通常是任务触发时的相关参数
String data = String.valueOf(detail.getJobDataMap().get(JobService.TASK_DATA));
// 打印任务执行日志,便于调试和跟踪
log.info("++++++++++定时任务:处理到期的交卷");
log.info("++++++++++jobName:{}", name);
log.info("++++++++++jobGroup:{}", group);
log.info("++++++++++taskData:{}", data);
// 强制交卷
// 调用 PaperService 进行强制交卷操作
// data 参数通常是考试 ID 或者某种标识符,用于识别需要交卷的考试
paperService.handExam(data);
}
}

@ -1,39 +1,46 @@
package com.yf.exam.modules.paper.mapper;
package com.yf.exam.modules.paper.mapper; // 定义类所在的包路径
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yf.exam.modules.paper.dto.PaperDTO;
import com.yf.exam.modules.paper.dto.request.PaperListReqDTO;
import com.yf.exam.modules.paper.dto.response.PaperListRespDTO;
import com.yf.exam.modules.paper.entity.Paper;
import org.apache.ibatis.annotations.Param;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; // 引入 MyBatis-Plus 的 BaseMapper
import com.baomidou.mybatisplus.core.metadata.IPage; // 引入分页结果接口 IPage
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; // 引入分页插件 Page
import com.yf.exam.modules.paper.dto.PaperDTO; // 引入 DTO 类,表示试卷数据传输对象
import com.yf.exam.modules.paper.dto.request.PaperListReqDTO; // 引入请求 DTO 类,表示查询试卷时的请求参数
import com.yf.exam.modules.paper.dto.response.PaperListRespDTO; // 引入响应 DTO 类,表示查询试卷时的响应结果
import com.yf.exam.modules.paper.entity.Paper; // 引入实体类,表示试卷数据表中的记录
import org.apache.ibatis.annotations.Param; // 引入 MyBatis 注解,用于指定 SQL 查询中的参数
import java.util.List;
/**
* <p>
* Mapper
* </p>
*
* @author
* @since 2020-05-25 16:33
*/
public interface PaperMapper extends BaseMapper<Paper> {
* <p>
* Mapper
* </p>
*
* @author
* @since 2020-05-25 16:33
*/
public interface PaperMapper extends BaseMapper<Paper> { // 继承 MyBatis-Plus 提供的 BaseMapper自动实现 CRUD 操作
/**
*
* @param page
* @param query
* @return
* <p>
* `Page` `PaperListReqDTO`
* </p>
*
* @param page
* @param query ID ID
* @return `IPage<PaperListRespDTO>`
*/
IPage<PaperListRespDTO> paging(Page page, @Param("query") PaperListReqDTO query);
/**
*
* @param query
* @return
* <p>
*
* </p>
*
* @param query ID ID
* @return `List<PaperListRespDTO>` DTO
*/
List<PaperListRespDTO> list(@Param("query") PaperDTO query);
}

@ -1,27 +1,33 @@
package com.yf.exam.modules.paper.mapper;
package com.yf.exam.modules.paper.mapper; // 指定该类所在的包路径
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yf.exam.modules.paper.dto.ext.PaperQuAnswerExtDTO;
import com.yf.exam.modules.paper.entity.PaperQuAnswer;
import org.apache.ibatis.annotations.Param;
// 导入BaseMapper接口提供通用的CRUD操作
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
// 导入PaperQuAnswerExtDTO类表示试卷考题备选答案的扩展数据传输对象
import com.yf.exam.modules.paper.dto.ext.PaperQuAnswerExtDTO;
// 导入PaperQuAnswer实体类表示试卷考题备选答案的数据模型
import com.yf.exam.modules.paper.entity.PaperQuAnswer;
// 导入MyBatis的注解指定方法参数在SQL中的名称
import org.apache.ibatis.annotations.Param;
import java.util.List;
// 导入List接口表示返回类型为List集合用于存储多个备选答案
import java.util.List;
/**
* <p>
* Mapper
* Mapper
* </p>
*
* MyBatis-PlusBaseMapperCRUD
*
* @author
* @since 2020-05-25 16:33
*/
public interface PaperQuAnswerMapper extends BaseMapper<PaperQuAnswer> {
public interface PaperQuAnswerMapper extends BaseMapper<PaperQuAnswer> { // 继承自BaseMapper接口提供了所有的基本CRUD操作
/**
*
* @param paperId
* @param quId
* @return
* @param paperId ID
* @param quId ID
* @return IDID
*/
List<PaperQuAnswerExtDTO> list(@Param("paperId") String paperId, @Param("quId") String quId);
List<PaperQuAnswerExtDTO> list(@Param("paperId") String paperId, @Param("quId") String quId); // 根据试卷ID和题目ID查询对应的备选答案列表
}

@ -1,42 +1,46 @@
package com.yf.exam.modules.paper.mapper;
package com.yf.exam.modules.paper.mapper; // 定义该类所在的包路径
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yf.exam.modules.paper.dto.ext.PaperQuDetailDTO;
import com.yf.exam.modules.paper.entity.PaperQu;
import org.apache.ibatis.annotations.Param;
// 导入BaseMapper接口提供MyBatis-Plus的通用CRUD操作
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
// 导入PaperQuDetailDTO类表示试卷考题详细数据传输对象
import com.yf.exam.modules.paper.dto.ext.PaperQuDetailDTO;
// 导入PaperQu实体类表示试卷考题的数据模型
import com.yf.exam.modules.paper.entity.PaperQu;
// 导入MyBatis的@Param注解用于方法参数与SQL查询中的参数进行映射
import org.apache.ibatis.annotations.Param;
import java.util.List;
// 导入List接口用于返回多个试题
import java.util.List;
/**
* <p>
* Mapper
* Mapper
* </p>
*
* MyBatis-PlusBaseMapperCRUD
*
* @author
* @since 2020-05-25 16:33
*/
public interface PaperQuMapper extends BaseMapper<PaperQu> {
public interface PaperQuMapper extends BaseMapper<PaperQu> { // 继承自BaseMapper接口提供通用的CRUD操作
/**
*
* @param paperId
* @return
* @param paperId ID
* @return
*/
int sumObjective(@Param("paperId") String paperId);
int sumObjective(@Param("paperId") String paperId); // 根据试卷ID统计所有客观题的分数总和
/**
*
* @param paperId
* @return
* @param paperId ID
* @return
*/
int sumSubjective(@Param("paperId") String paperId);
int sumSubjective(@Param("paperId") String paperId); // 根据试卷ID统计所有主观题的分数总和
/**
*
* @param paperId
* @return
* @param paperId ID
* @return PaperQuDetailDTO
*/
List<PaperQuDetailDTO> listByPaper(@Param("paperId") String paperId);
List<PaperQuDetailDTO> listByPaper(@Param("paperId") String paperId); // 根据试卷ID查询所有试题的详细信息
}

@ -1,18 +1,20 @@
// 导入所需的包
package com.yf.exam.modules.paper.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yf.exam.core.api.dto.PagingReqDTO;
import com.yf.exam.modules.paper.dto.PaperQuAnswerDTO;
import com.yf.exam.modules.paper.dto.ext.PaperQuAnswerExtDTO;
import com.yf.exam.modules.paper.entity.PaperQuAnswer;
import com.baomidou.mybatisplus.core.metadata.IPage; // 用于分页查询
import com.baomidou.mybatisplus.extension.service.IService; // 用于继承通用服务接口
import com.yf.exam.core.api.dto.PagingReqDTO; // 分页请求DTO
import com.yf.exam.modules.paper.dto.PaperQuAnswerDTO; // 试卷问题答案DTO
import com.yf.exam.modules.paper.dto.ext.PaperQuAnswerExtDTO; // 扩展的试卷问题答案DTO
import com.yf.exam.modules.paper.entity.PaperQuAnswer; // 试卷问题答案实体类
import java.util.List;
import java.util.List; // 导入List类用于处理集合数据
/**
* <p>
*
* </p>
*
*
* @author
* @since 2020-05-25 16:33
@ -21,24 +23,24 @@ public interface PaperQuAnswerService extends IService<PaperQuAnswer> {
/**
*
* @param reqDTO
* @return
* @param reqDTO DTO
* @return PaperQuAnswerDTO
*/
IPage<PaperQuAnswerDTO> paging(PagingReqDTO<PaperQuAnswerDTO> reqDTO);
/**
*
* @param paperId
* @param quId
* @return
*
* @param paperId ID
* @param quId ID
* @return PaperQuAnswerExtDTO
*/
List<PaperQuAnswerExtDTO> listForExam(String paperId, String quId);
/**
*
* @param paperId
* @param quId
* @return
*
* @param paperId ID
* @param quId ID
* @return PaperQuAnswer
*/
List<PaperQuAnswer> listForFill(String paperId, String quId);
}

@ -1,18 +1,20 @@
// 导入所需的包
package com.yf.exam.modules.paper.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yf.exam.core.api.dto.PagingReqDTO;
import com.yf.exam.modules.paper.dto.PaperQuDTO;
import com.yf.exam.modules.paper.dto.ext.PaperQuDetailDTO;
import com.yf.exam.modules.paper.entity.PaperQu;
import com.baomidou.mybatisplus.core.metadata.IPage; // 用于分页查询
import com.baomidou.mybatisplus.extension.service.IService; // 用于继承通用服务接口
import com.yf.exam.core.api.dto.PagingReqDTO; // 分页请求DTO
import com.yf.exam.modules.paper.dto.PaperQuDTO; // 试卷问题DTO
import com.yf.exam.modules.paper.dto.ext.PaperQuDetailDTO; // 试卷问题详情DTO
import com.yf.exam.modules.paper.entity.PaperQu; // 试卷问题实体类
import java.util.List;
import java.util.List; // 导入List类用于处理集合数据
/**
* <p>
*
* </p>
*
*
* @author
* @since 2020-05-25 16:33
@ -21,50 +23,50 @@ public interface PaperQuService extends IService<PaperQu> {
/**
*
* @param reqDTO
* @return
* @param reqDTO DTO
* @return PaperQuDTO
*/
IPage<PaperQuDTO> paging(PagingReqDTO<PaperQuDTO> reqDTO);
/**
*
* @param paperId
* @return
* @param paperId ID
* @return PaperQuDTO
*/
List<PaperQuDTO> listByPaper(String paperId);
/**
*
* @param paperId
* @param quId
* @return
*
* @param paperId ID
* @param quId ID
* @return PaperQu
*/
PaperQu findByKey(String paperId, String quId);
/**
*
* @param qu
*
* @param qu
*/
void updateByKey(PaperQu qu);
/**
*
* @param paperId
* @return
*
* @param paperId ID
* @return
*/
int sumObjective(String paperId);
/**
*
* @param paperId
* @return
*
* @param paperId ID
* @return
*/
int sumSubjective(String paperId);
/**
*
* @param paperId
* @return
*
* @param paperId ID
* @return PaperQuDetailDTO
*/
List<PaperQuDetailDTO> listForPaperResult(String paperId);
}

@ -1,21 +1,23 @@
// 导入所需的包
package com.yf.exam.modules.paper.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yf.exam.core.api.dto.PagingReqDTO;
import com.yf.exam.modules.paper.dto.PaperDTO;
import com.yf.exam.modules.paper.dto.ext.PaperQuDetailDTO;
import com.yf.exam.modules.paper.dto.request.PaperAnswerDTO;
import com.yf.exam.modules.paper.dto.request.PaperListReqDTO;
import com.yf.exam.modules.paper.dto.response.ExamDetailRespDTO;
import com.yf.exam.modules.paper.dto.response.ExamResultRespDTO;
import com.yf.exam.modules.paper.dto.response.PaperListRespDTO;
import com.yf.exam.modules.paper.entity.Paper;
import com.baomidou.mybatisplus.core.metadata.IPage; // 用于分页查询
import com.baomidou.mybatisplus.extension.service.IService; // 用于继承通用服务接口
import com.yf.exam.core.api.dto.PagingReqDTO; // 分页请求DTO
import com.yf.exam.modules.paper.dto.PaperDTO; // 试卷DTO
import com.yf.exam.modules.paper.dto.ext.PaperQuDetailDTO; // 试卷题目详情DTO
import com.yf.exam.modules.paper.dto.request.PaperAnswerDTO; // 提交答案请求DTO
import com.yf.exam.modules.paper.dto.request.PaperListReqDTO; // 试卷列表请求DTO
import com.yf.exam.modules.paper.dto.response.ExamDetailRespDTO; // 考试详情响应DTO
import com.yf.exam.modules.paper.dto.response.ExamResultRespDTO; // 考试结果响应DTO
import com.yf.exam.modules.paper.dto.response.PaperListRespDTO; // 试卷列表响应DTO
import com.yf.exam.modules.paper.entity.Paper; // 试卷实体类
/**
* <p>
*
* </p>
*
*
* @author
* @since 2020-05-25 16:33
@ -24,60 +26,57 @@ public interface PaperService extends IService<Paper> {
/**
*
* @param userId
* @param examId
* @return
* @param userId ID
* @param examId ID
* @return ID
*/
String createPaper(String userId, String examId);
/**
*
* @param paperId
* @return
*
* @param paperId ID
* @return ExamDetailRespDTO
*/
ExamDetailRespDTO paperDetail(String paperId);
/**
*
* @param paperId
* @return
*
* @param paperId ID
* @return ExamResultRespDTO
*/
ExamResultRespDTO paperResult(String paperId);
/**
*
* @param paperId
* @param quId
* @return
*
* @param paperId ID
* @param quId ID
* @return PaperQuDetailDTO
*/
PaperQuDetailDTO findQuDetail(String paperId, String quId);
/**
*
* @param reqDTO
*
* @param reqDTO DTO
*/
void fillAnswer(PaperAnswerDTO reqDTO);
/**
*
* @param paperId
* @return
*
* @param paperId ID
*/
void handExam(String paperId);
/**
*
* @param reqDTO
* @return
*
* @param reqDTO DTO
* @return IPage<PaperListRespDTO>
*/
IPage<PaperListRespDTO> paging(PagingReqDTO<PaperListReqDTO> reqDTO);
/**
*
* @param userId
* @return
*
* @param userId ID
* @return PaperDTO
*/
PaperDTO checkProcess(String userId);
}

@ -1,61 +1,95 @@
package com.yf.exam.modules.paper.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yf.exam.core.api.dto.PagingReqDTO;
import com.yf.exam.modules.paper.dto.PaperQuAnswerDTO;
import com.yf.exam.modules.paper.dto.ext.PaperQuAnswerExtDTO;
import com.yf.exam.modules.paper.entity.PaperQuAnswer;
import com.yf.exam.modules.paper.mapper.PaperQuAnswerMapper;
import com.yf.exam.modules.paper.service.PaperQuAnswerService;
import org.springframework.stereotype.Service;
import java.util.List;
package com.yf.exam.modules.paper.service.impl; // 指定该类所在的包路径
// 导入FastJSON库用于处理JSON格式数据的转换
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
// 导入MyBatis-Plus的条件查询构造器
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
// 导入分页接口
import com.baomidou.mybatisplus.core.metadata.IPage;
// 导入分页Page类
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
// 导入MyBatis-Plus的服务实现类
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
// 导入分页请求DTO用于分页查询
import com.yf.exam.core.api.dto.PagingReqDTO;
// 导入试卷考题备选答案DTO类
import com.yf.exam.modules.paper.dto.PaperQuAnswerDTO;
// 导入试卷考题备选答案扩展DTO类
import com.yf.exam.modules.paper.dto.ext.PaperQuAnswerExtDTO;
// 导入试卷考题备选答案实体类
import com.yf.exam.modules.paper.entity.PaperQuAnswer;
// 导入试卷考题备选答案Mapper接口
import com.yf.exam.modules.paper.mapper.PaperQuAnswerMapper;
// 导入试卷考题备选答案服务接口
import com.yf.exam.modules.paper.service.PaperQuAnswerService;
// 导入Spring的Service注解表示这是一个服务实现类
import org.springframework.stereotype.Service;
import java.util.List; // 导入List接口用于返回多个结果
/**
* <p>
*
*
* </p>
*
* PaperQuAnswerService
*
* @author
* @since 2020-05-25 16:33
*/
@Service
public class PaperQuAnswerServiceImpl extends ServiceImpl<PaperQuAnswerMapper, PaperQuAnswer> implements PaperQuAnswerService {
@Service // 标注为Spring的服务类
public class PaperQuAnswerServiceImpl extends ServiceImpl<PaperQuAnswerMapper, PaperQuAnswer> implements PaperQuAnswerService { // 继承ServiceImpl类提供基本的数据库操作功能
/**
*
* @param reqDTO
* @return
*/
@Override
public IPage<PaperQuAnswerDTO> paging(PagingReqDTO<PaperQuAnswerDTO> reqDTO) {
//创建分页对象
// 创建分页对象
IPage<PaperQuAnswer> query = new Page<>(reqDTO.getCurrent(), reqDTO.getSize());
//查询条件
// 查询条件,可以根据需要添加更多过滤条件
QueryWrapper<PaperQuAnswer> wrapper = new QueryWrapper<>();
//获得数据
// 执行分页查询操作
IPage<PaperQuAnswer> page = this.page(query, wrapper);
//转换结果
// 将查询结果转换为DTO对象返回分页后的结果
IPage<PaperQuAnswerDTO> pageData = JSON.parseObject(JSON.toJSONString(page), new TypeReference<Page<PaperQuAnswerDTO>>(){});
return pageData;
}
return pageData; // 返回分页结果
}
/**
* IDID
* @param paperId ID
* @param quId ID
* @return DTO
*/
@Override
public List<PaperQuAnswerExtDTO> listForExam(String paperId, String quId) {
// 调用Mapper中的list方法查询并返回试题的备选答案列表
return baseMapper.list(paperId, quId);
}
/**
*
* @param paperId ID
* @param quId ID
* @return
*/
@Override
public List<PaperQuAnswer> listForFill(String paperId, String quId) {
//查询条件
// 创建查询条件
QueryWrapper<PaperQuAnswer> wrapper = new QueryWrapper<>();
wrapper.lambda()
.eq(PaperQuAnswer::getPaperId, paperId)
.eq(PaperQuAnswer::getQuId, quId);
wrapper.lambda() // 使用Lambda表达式进行条件构造
.eq(PaperQuAnswer::getPaperId, paperId) // 通过试卷ID过滤
.eq(PaperQuAnswer::getQuId, quId); // 通过题目ID过滤
// 查询并返回符合条件的结果列表
return this.list(wrapper);
}
}

@ -1,94 +1,150 @@
package com.yf.exam.modules.paper.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yf.exam.core.api.dto.PagingReqDTO;
import com.yf.exam.core.utils.BeanMapper;
import com.yf.exam.modules.paper.dto.PaperQuDTO;
import com.yf.exam.modules.paper.dto.ext.PaperQuDetailDTO;
import com.yf.exam.modules.paper.entity.PaperQu;
import com.yf.exam.modules.paper.mapper.PaperQuMapper;
import com.yf.exam.modules.paper.service.PaperQuService;
import org.springframework.stereotype.Service;
import java.util.List;
package com.yf.exam.modules.paper.service.impl; // 指定该类所在的包路径
// 导入FastJSON库用于处理JSON格式数据的转换
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
// 导入MyBatis-Plus的条件查询构造器
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
// 导入分页接口
import com.baomidou.mybatisplus.core.metadata.IPage;
// 导入分页Page类
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
// 导入MyBatis-Plus的服务实现类
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
// 导入分页请求DTO用于分页查询
import com.yf.exam.core.api.dto.PagingReqDTO;
// 导入BeanMapper工具类用于对象间的转换
import com.yf.exam.core.utils.BeanMapper;
// 导入试卷考题DTO类
import com.yf.exam.modules.paper.dto.PaperQuDTO;
// 导入试卷考题详情DTO类
import com.yf.exam.modules.paper.dto.ext.PaperQuDetailDTO;
// 导入试卷考题实体类
import com.yf.exam.modules.paper.entity.PaperQu;
// 导入试卷考题Mapper接口
import com.yf.exam.modules.paper.mapper.PaperQuMapper;
// 导入试卷考题服务接口
import com.yf.exam.modules.paper.service.PaperQuService;
// 导入Spring的Service注解表示这是一个服务实现类
import org.springframework.stereotype.Service;
import java.util.List; // 导入List接口用于返回多个结果
/**
* <p>
*
*
* </p>
*
* PaperQuService
*
* @author
* @since 2020-05-25 16:33
*/
@Service
public class PaperQuServiceImpl extends ServiceImpl<PaperQuMapper, PaperQu> implements PaperQuService {
@Service // 标注为Spring的服务类
public class PaperQuServiceImpl extends ServiceImpl<PaperQuMapper, PaperQu> implements PaperQuService { // 继承ServiceImpl类提供基本的数据库操作功能
/**
*
* @param reqDTO
* @return
*/
@Override
public IPage<PaperQuDTO> paging(PagingReqDTO<PaperQuDTO> reqDTO) {
//创建分页对象
// 创建分页对象
IPage<PaperQu> query = new Page<>(reqDTO.getCurrent(), reqDTO.getSize());
//查询条件
// 查询条件
QueryWrapper<PaperQu> wrapper = new QueryWrapper<>();
//获得数据
// 执行分页查询操作
IPage<PaperQu> page = this.page(query, wrapper);
//转换结果
// 将查询结果转换为DTO对象返回分页后的结果
IPage<PaperQuDTO> pageData = JSON.parseObject(JSON.toJSONString(page), new TypeReference<Page<PaperQuDTO>>(){});
return pageData;
}
return pageData; // 返回分页结果
}
/**
* ID
* @param paperId ID
* @return DTO
*/
@Override
public List<PaperQuDTO> listByPaper(String paperId) {
//查询条件
// 查询条件
QueryWrapper<PaperQu> wrapper = new QueryWrapper<>();
wrapper.lambda().eq(PaperQu::getPaperId, paperId)
.orderByAsc(PaperQu::getSort);
wrapper.lambda().eq(PaperQu::getPaperId, paperId) // 通过试卷ID过滤
.orderByAsc(PaperQu::getSort); // 按照题目排序字段升序排列
// 执行查询,获取试卷考题列表
List<PaperQu> list = this.list(wrapper);
// 使用BeanMapper工具类将实体对象列表转换为DTO对象列表
return BeanMapper.mapList(list, PaperQuDTO.class);
}
/**
* IDID
* @param paperId ID
* @param quId ID
* @return
*/
@Override
public PaperQu findByKey(String paperId, String quId) {
//查询条件
// 查询条件
QueryWrapper<PaperQu> wrapper = new QueryWrapper<>();
wrapper.lambda().eq(PaperQu::getPaperId, paperId)
.eq(PaperQu::getQuId, quId);
wrapper.lambda().eq(PaperQu::getPaperId, paperId) // 通过试卷ID过滤
.eq(PaperQu::getQuId, quId); // 通过题目ID过滤
return this.getOne(wrapper, false);
// 获取匹配的单个试卷考题对象
return this.getOne(wrapper, false); // 返回查询到的结果false表示未查询到时返回null
}
/**
* IDID
* @param qu
*/
@Override
public void updateByKey(PaperQu qu) {
//查询条件
// 查询条件
QueryWrapper<PaperQu> wrapper = new QueryWrapper<>();
wrapper.lambda().eq(PaperQu::getPaperId, qu.getPaperId())
.eq(PaperQu::getQuId, qu.getQuId());
wrapper.lambda().eq(PaperQu::getPaperId, qu.getPaperId()) // 通过试卷ID过滤
.eq(PaperQu::getQuId, qu.getQuId()); // 通过题目ID过滤
this.update(qu, wrapper);
// 执行更新操作
this.update(qu, wrapper); // 更新满足条件的试卷考题
}
/**
*
* @param paperId ID
* @return
*/
@Override
public int sumObjective(String paperId) {
return baseMapper.sumObjective(paperId);
return baseMapper.sumObjective(paperId); // 调用Mapper方法统计客观题总分
}
/**
*
* @param paperId ID
* @return
*/
@Override
public int sumSubjective(String paperId) {
return baseMapper.sumSubjective(paperId);
return baseMapper.sumSubjective(paperId); // 调用Mapper方法统计主观题总分
}
/**
* ID
* @param paperId ID
* @return
*/
@Override
public List<PaperQuDetailDTO> listForPaperResult(String paperId) {
return baseMapper.listByPaper(paperId);
return baseMapper.listByPaper(paperId); // 调用Mapper方法获取试卷考题详细信息
}
}

@ -1,137 +1,129 @@
// 导入所需的包
package com.yf.exam.modules.qu.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.google.common.collect.Lists;
import com.yf.exam.core.api.ApiRest;
import com.yf.exam.core.api.controller.BaseController;
import com.yf.exam.core.api.dto.BaseIdReqDTO;
import com.yf.exam.core.api.dto.BaseIdRespDTO;
import com.yf.exam.core.api.dto.BaseIdsReqDTO;
import com.yf.exam.core.api.dto.PagingReqDTO;
import com.yf.exam.core.exception.ServiceException;
import com.yf.exam.core.utils.BeanMapper;
import com.yf.exam.core.utils.excel.ExportExcel;
import com.yf.exam.core.utils.excel.ImportExcel;
import com.yf.exam.modules.qu.dto.QuDTO;
import com.yf.exam.modules.qu.dto.export.QuExportDTO;
import com.yf.exam.modules.qu.dto.ext.QuDetailDTO;
import com.yf.exam.modules.qu.dto.request.QuQueryReqDTO;
import com.yf.exam.modules.qu.entity.Qu;
import com.yf.exam.modules.qu.service.QuService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; // 用于构建查询条件
import com.baomidou.mybatisplus.core.metadata.IPage; // 用于分页
import com.google.common.collect.Lists; // 用于操作列表
import com.yf.exam.core.api.ApiRest; // API响应封装类
import com.yf.exam.core.api.controller.BaseController; // 基础控制器类
import com.yf.exam.core.api.dto.BaseIdReqDTO; // 基础ID请求DTO
import com.yf.exam.core.api.dto.BaseIdRespDTO; // 基础ID响应DTO
import com.yf.exam.core.api.dto.BaseIdsReqDTO; // 基础ID数组请求DTO
import com.yf.exam.core.api.dto.PagingReqDTO; // 分页请求DTO
import com.yf.exam.core.exception.ServiceException; // 自定义服务异常
import com.yf.exam.core.utils.BeanMapper; // Bean映射工具
import com.yf.exam.core.utils.excel.ExportExcel; // 导出Excel工具
import com.yf.exam.core.utils.excel.ImportExcel; // 导入Excel工具
import com.yf.exam.modules.qu.dto.QuDTO; // 问题DTO
import com.yf.exam.modules.qu.dto.export.QuExportDTO; // 问题导出DTO
import com.yf.exam.modules.qu.dto.ext.QuDetailDTO; // 问题详情DTO
import com.yf.exam.modules.qu.dto.request.QuQueryReqDTO; // 问题查询请求DTO
import com.yf.exam.modules.qu.entity.Qu; // 问题实体类
import com.yf.exam.modules.qu.service.QuService; // 问题服务类
import io.swagger.annotations.Api; // Swagger API注释
import io.swagger.annotations.ApiOperation; // Swagger API操作注释
import org.apache.commons.lang3.StringUtils; // 字符串操作工具类
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; // 用于处理Excel格式异常
import org.apache.shiro.authz.annotation.RequiresRoles; // Shiro权限控制注解
import org.springframework.beans.factory.annotation.Autowired; // 自动注入依赖
import org.springframework.util.CollectionUtils; // 集合工具类
import org.springframework.web.bind.annotation.RequestBody; // 请求体注解
import org.springframework.web.bind.annotation.RequestMapping; // 请求映射注解
import org.springframework.web.bind.annotation.RequestMethod; // 请求方法类型注解
import org.springframework.web.bind.annotation.RequestParam; // 请求参数注解
import org.springframework.web.bind.annotation.ResponseBody; // 响应体注解
import org.springframework.web.bind.annotation.RestController; // REST控制器注解
import org.springframework.web.multipart.MultipartFile; // 用于处理文件上传
import javax.servlet.http.HttpServletResponse; // 用于处理HTTP响应
import java.io.IOException; // IO异常处理
import java.util.Arrays; // 数组工具类
import java.util.List; // 列表工具类
/**
* <p>
*
* </p>
*
*
* @author
* @since 2020-05-25 13:25
*/
@Api(tags={"问题题目"})
@RestController
@RequestMapping("/exam/api/qu/qu")
@Api(tags={"问题题目"}) // Swagger注解表示该控制器处理"问题题目"相关的请求
@RestController // Spring注解表示这是一个RESTful API控制器
@RequestMapping("/exam/api/qu/qu") // 设置基础路径
public class QuController extends BaseController {
@Autowired
private QuService baseService;
private QuService baseService; // 自动注入问题服务类
/**
*
*
*
* @param reqDTO
* @return
* @param reqDTO
* @return
*/
@RequiresRoles("sa")
@ApiOperation(value = "添加或修改")
@RequestMapping(value = "/save", method = {RequestMethod.POST})
@RequiresRoles("sa") // 限制只有角色为"sa"的用户可以访问此方法
@ApiOperation(value = "添加或修改") // Swagger注解描述该方法的功能
@RequestMapping(value = "/save", method = {RequestMethod.POST}) // POST请求表示保存操作
public ApiRest<BaseIdRespDTO> save(@RequestBody QuDetailDTO reqDTO) {
baseService.save(reqDTO);
return super.success();
baseService.save(reqDTO); // 调用服务层保存或更新问题数据
return super.success(); // 返回成功响应
}
/**
*
*
*
* @param reqDTO
* @return
* @param reqDTO IDID
* @return
*/
@RequiresRoles("sa")
@ApiOperation(value = "批量删除")
@RequestMapping(value = "/delete", method = {RequestMethod.POST})
@RequiresRoles("sa") // 限制只有角色为"sa"的用户可以访问此方法
@ApiOperation(value = "批量删除") // Swagger注解描述该方法的功能
@RequestMapping(value = "/delete", method = {RequestMethod.POST}) // POST请求表示删除操作
public ApiRest edit(@RequestBody BaseIdsReqDTO reqDTO) {
//根据ID删除
baseService.delete(reqDTO.getIds());
return super.success();
baseService.delete(reqDTO.getIds()); // 调用服务层进行批量删除
return super.success(); // 返回成功响应
}
/**
*
*
*
* @param reqDTO
* @return
* @param reqDTO IDID
* @return
*/
@ApiOperation(value = "查找详情")
@RequestMapping(value = "/detail", method = {RequestMethod.POST})
@ApiOperation(value = "查找详情") // Swagger注解描述该方法的功能
@RequestMapping(value = "/detail", method = {RequestMethod.POST}) // POST请求表示获取详情操作
public ApiRest<QuDetailDTO> detail(@RequestBody BaseIdReqDTO reqDTO) {
QuDetailDTO dto = baseService.detail(reqDTO.getId());
return super.success(dto);
QuDetailDTO dto = baseService.detail(reqDTO.getId()); // 调用服务层获取问题题目详情
return super.success(dto); // 返回问题详情
}
/**
*
*
*
* @param reqDTO
* @return
* @param reqDTO
* @return
*/
@RequiresRoles("sa")
@ApiOperation(value = "分页查找")
@RequestMapping(value = "/paging", method = {RequestMethod.POST})
@RequiresRoles("sa") // 限制只有角色为"sa"的用户可以访问此方法
@ApiOperation(value = "分页查找") // Swagger注解描述该方法的功能
@RequestMapping(value = "/paging", method = {RequestMethod.POST}) // POST请求表示分页查询操作
public ApiRest<IPage<QuDTO>> paging(@RequestBody PagingReqDTO<QuQueryReqDTO> reqDTO) {
//分页查询并转换
IPage<QuDTO> page = baseService.paging(reqDTO);
return super.success(page);
IPage<QuDTO> page = baseService.paging(reqDTO); // 调用服务层进行分页查询
return super.success(page); // 返回分页结果
}
/**
* excel
* Excel
*/
@RequiresRoles("sa")
@ResponseBody
@RequestMapping(value = "/export")
@RequiresRoles("sa") // 限制只有角色为"sa"的用户可以访问此方法
@ResponseBody // 标明返回内容直接作为响应体
@RequestMapping(value = "/export") // 导出请求路径
public ApiRest exportFile(HttpServletResponse response, @RequestBody QuQueryReqDTO reqDTO) {
// 导出文件名
String fileName = "导出的试题-" + System.currentTimeMillis() + ".xlsx";
String fileName = "导出的试题-" + System.currentTimeMillis() + ".xlsx"; // 设置导出的文件名
try {
int no = 0;
String quId = "";
List<QuExportDTO> list = baseService.listForExport(reqDTO);
List<QuExportDTO> list = baseService.listForExport(reqDTO); // 获取导出数据
for (QuExportDTO item : list) {
if (!quId.equals(item.getQId())) {
quId = item.getQId();
@ -144,135 +136,101 @@ public class QuController extends BaseController {
item.setQImage("");
item.setQVideo("");
}
item.setNo(String.valueOf(no));
item.setNo(String.valueOf(no)); // 设置题目序号
}
new ExportExcel("试题", QuExportDTO.class).setDataList(list).write(response, fileName).dispose();
return super.success();
new ExportExcel("试题", QuExportDTO.class).setDataList(list).write(response, fileName).dispose(); // 导出数据到Excel文件
return super.success(); // 返回成功响应
} catch (Exception e) {
return failure(e.getMessage());
return failure(e.getMessage()); // 捕获异常并返回失败响应
}
}
/**
* Excel
* Excel
*
* @param file
* @return
* @param file Excel
* @return
*/
@RequiresRoles("sa")
@ResponseBody
@RequestMapping(value = "/import")
@RequiresRoles("sa") // 限制只有角色为"sa"的用户可以访问此方法
@ResponseBody // 标明返回内容直接作为响应体
@RequestMapping(value = "/import") // 导入请求路径
public ApiRest importFile(@RequestParam("file") MultipartFile file) {
try {
ImportExcel ei = new ImportExcel(file, 1, 0);
List<QuExportDTO> list = ei.getDataList(QuExportDTO.class);
// 校验数据
this.checkExcel(list);
// 导入数据条数
baseService.importExcel(list);
// 导入成功
return super.success();
} catch (IOException e) {
} catch (InvalidFormatException e) {
} catch (IllegalAccessException e) {
} catch (InstantiationException e) {
ImportExcel ei = new ImportExcel(file, 1, 0); // 创建导入Excel对象
List<QuExportDTO> list = ei.getDataList(QuExportDTO.class); // 获取Excel中的数据列表
this.checkExcel(list); // 校验数据
baseService.importExcel(list); // 调用服务层进行导入操作
return super.success(); // 返回成功响应
} catch (IOException | InvalidFormatException | IllegalAccessException | InstantiationException e) {
return super.failure(); // 捕获各种异常并返回失败响应
}
return super.failure();
}
/**
* Excel
* Excel
*
* @param list
* @throws Exception
* @param list
* @throws ServiceException
*/
private void checkExcel(List<QuExportDTO> list) throws ServiceException {
// 约定第三行开始导入
// 校验Excel数据的逻辑检查每一行数据的有效性
int line = 3;
StringBuffer sb = new StringBuffer();
if (CollectionUtils.isEmpty(list)) {
throw new ServiceException(1, "您导入的数据似乎是一个空表格!");
throw new ServiceException(1, "您导入的数据似乎是一个空表格!"); // 如果表格为空,抛出异常
}
Integer quNo = null;
for (QuExportDTO item : list) {
System.out.println(item.getNo());
if (StringUtils.isBlank(item.getNo())) {
line++;
continue;
}
System.out.println(item.getQContent());
Integer no;
try {
no = Integer.parseInt(item.getNo());
no = Integer.parseInt(item.getNo()); // 转换题目序号
} catch (Exception e) {
line++;
continue;
}
if (no == null) {
sb.append("第" + line + "行,题目序号不能为空!<br>");
}
// 校验题目内容和其他字段是否为空
if (quNo == null || !quNo.equals(no)) {
if (item.getQuType() == null) {
sb.append("第" + line + "行,题目类型不能为空<br>");
}
if (StringUtils.isBlank(item.getQContent())) {
sb.append("第" + line + "行,题目内容不能为空<br>");
}
if (CollectionUtils.isEmpty(item.getRepoList())) {
sb.append("第" + line + "行,题目必须包含一个题库<br>");
}
}
if (StringUtils.isBlank(item.getAIsRight())) {
sb.append("第" + line + "行,选项是否正确不能为空<br>");
}
if (StringUtils.isBlank(item.getAContent()) && StringUtils.isBlank(item.getAImage())) {
sb.append("第" + line + "行,选项内容和选项图片必须有一个不为空<br>");
}
quNo = no;
line++;
}
// 存在错误
if (!"".equals(sb.toString())) {
throw new ServiceException(1, sb.toString());
throw new ServiceException(1, sb.toString()); // 如果有校验错误,抛出异常
}
}
/**
*
*
*/
@ResponseBody
@RequestMapping(value = "import/template")
@RequestMapping(value = "import/template") // 导入模板下载路径
public ApiRest importFileTemplate(HttpServletResponse response) {
try {
String fileName = "试题导入模板.xlsx";
List<QuExportDTO> list = Lists.newArrayList();
String fileName = "试题导入模板.xlsx"; // 设置文件名
List<QuExportDTO> list = Lists.newArrayList(); // 创建模板数据列表
// 模板数据(包含问题内容、题型、选项等)
QuExportDTO l1 = new QuExportDTO();
l1.setNo("正式导入,请删除此说明行:数字,相同的数字表示同一题的序列");
l1.setQContent("问题内容");
@ -286,39 +244,17 @@ public class QuController extends BaseController {
l1.setAIsRight("只能填写0或10表示否1表示是");
l1.setAAnalysis("这个项是正确的");
QuExportDTO l2 = new QuExportDTO();
l2.setQContent("找出以下可以被2整除的数多选");
l2.setQAnalysis("最基本的数学题,不做过多解析");
l2.setQuType("2");
l2.setNo("1");
l2.setAIsRight("1");
l2.setAContent("数字2");
l2.setAAnalysis("2除以2=1对的");
QuExportDTO l3 = new QuExportDTO();
l3.setNo("1");
l3.setAIsRight("0");
l3.setAContent("数字3");
l3.setAAnalysis("3除以2=1.5,不能被整除");
QuExportDTO l4 = new QuExportDTO();
l4.setNo("1");
l4.setAIsRight("1");
l4.setAContent("数字6");
l4.setAAnalysis("6除以2=3对的");
// 添加模板示例数据
list.add(l1);
list.add(l2);
list.add(l3);
list.add(l4);
// 导出模板文件
new ExportExcel("试题数据", QuExportDTO.class, 1).setDataList(list).write(response, fileName).dispose();
return super.success();
return super.success(); // 返回成功响应
} catch (Exception e) {
return super.failure("导入模板下载失败!失败信息:"+e.getMessage());
return super.failure("导入模板下载失败!失败信息:"+e.getMessage()); // 返回失败响应
}
}
}

@ -1,42 +1,66 @@
package com.yf.exam.modules.qu.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import io.swagger.annotations.ApiModel; // Swagger注解用于生成API文档
import io.swagger.annotations.ApiModelProperty; // Swagger注解用于描述API模型的属性
import lombok.Data; // Lombok注解用于自动生成getter、setter等方法
import java.io.Serializable;
import java.io.Serializable; // 可序列化接口
/**
* <p>
*
* </p>
*
*
*
* @author
* @since 2020-05-25 13:23
*/
@Data
@Data // Lombok注解自动生成getter、setter等方法
@ApiModel(value="候选答案", description="候选答案")
public class QuAnswerDTO implements Serializable {
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L; // 序列化版本UID
/**
* ID
*
*/
@ApiModelProperty(value = "答案ID", required=true) // Swagger注解描述字段信息标明该字段是必填项
private String id; // 答案ID
@ApiModelProperty(value = "答案ID", required=true)
private String id;
/**
* ID
* ID
*/
@ApiModelProperty(value = "问题ID", required=true) // Swagger注解描述字段信息标明该字段是必填项
private String quId; // 题目ID
@ApiModelProperty(value = "问题ID", required=true)
private String quId;
/**
*
* `true``false`
*/
@ApiModelProperty(value = "是否正确", required=true) // Swagger注解描述字段信息标明该字段是必填项
private Boolean isRight; // 是否正确
@ApiModelProperty(value = "是否正确", required=true)
private Boolean isRight;
/**
*
* URL
*/
@ApiModelProperty(value = "选项图片", required=true) // Swagger注解描述字段信息标明该字段是必填项
private String image; // 选项图片URL
@ApiModelProperty(value = "选项图片", required=true)
private String image;
/**
*
*
*/
@ApiModelProperty(value = "答案内容", required=true) // Swagger注解描述字段信息标明该字段是必填项
private String content; // 答案内容
@ApiModelProperty(value = "答案内容", required=true)
private String content;
@ApiModelProperty(value = "答案分析", required=true)
private String analysis;
/**
*
*
*/
@ApiModelProperty(value = "答案分析", required=true) // Swagger注解描述字段信息标明该字段是必填项
private String analysis; // 答案分析
}

@ -1,53 +1,88 @@
package com.yf.exam.modules.qu.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import io.swagger.annotations.ApiModel; // Swagger注解用于生成API文档
import io.swagger.annotations.ApiModelProperty; // Swagger注解用于描述API模型的属性
import lombok.Data; // Lombok注解用于自动生成getter、setter等方法
import java.io.Serializable;
import java.util.Date;
import java.io.Serializable; // 可序列化接口
import java.util.Date; // 日期类型
/**
* <p>
*
* </p>
*
*
*
* @author
* @since 2020-05-25 13:23
*/
@Data
@Data // Lombok注解自动生成getter、setter等方法
@ApiModel(value="问题题目", description="问题题目")
public class QuDTO implements Serializable {
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L; // 序列化版本UID
/**
* ID
* ID
*/
@ApiModelProperty(value = "题目ID", required=true) // Swagger注解描述字段信息标明该字段是必填项
private String id; // 题目ID
@ApiModelProperty(value = "题目ID", required=true)
private String id;
/**
*
*
*/
@ApiModelProperty(value = "题目类型", required=true) // Swagger注解描述字段信息标明该字段是必填项
private Integer quType; // 题目类型
@ApiModelProperty(value = "题目类型", required=true)
private Integer quType;
/**
*
* 12
*/
@ApiModelProperty(value = "1普通,2较难", required=true) // Swagger注解描述字段信息标明该字段是必填项
private Integer level; // 题目难度
@ApiModelProperty(value = "1普通,2较难", required=true)
private Integer level;
/**
*
* URL
*/
@ApiModelProperty(value = "题目图片", required=true) // Swagger注解描述字段信息标明该字段是必填项
private String image; // 题目图片URL
@ApiModelProperty(value = "题目图片", required=true)
private String image;
/**
*
*
*/
@ApiModelProperty(value = "题目内容", required=true) // Swagger注解描述字段信息标明该字段是必填项
private String content; // 题目内容
@ApiModelProperty(value = "题目内容", required=true)
private String content;
/**
*
*
*/
@ApiModelProperty(value = "创建时间", required=true) // Swagger注解描述字段信息标明该字段是必填项
private Date createTime; // 创建时间
/**
*
*
*/
@ApiModelProperty(value = "更新时间", required=true) // Swagger注解描述字段信息标明该字段是必填项
private Date updateTime; // 更新时间
@ApiModelProperty(value = "创建时间", required=true)
private Date createTime;
/**
*
*
*/
@ApiModelProperty(value = "题目备注", required=true) // Swagger注解描述字段信息标明该字段是必填项
private String remark; // 题目备注
@ApiModelProperty(value = "更新时间", required=true)
private Date updateTime;
@ApiModelProperty(value = "题目备注", required=true)
private String remark;
@ApiModelProperty(value = "整题解析", required=true)
private String analysis;
/**
*
*
*/
@ApiModelProperty(value = "整题解析", required=true) // Swagger注解描述字段信息标明该字段是必填项
private String analysis; // 整题解析
}

@ -1,38 +1,58 @@
package com.yf.exam.modules.qu.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import io.swagger.annotations.ApiModel; // Swagger注解用于生成API文档
import io.swagger.annotations.ApiModelProperty; // Swagger注解用于描述API模型的属性
import lombok.Data; // Lombok注解用于自动生成getter、setter等方法
import java.io.Serializable;
import java.io.Serializable; // 可序列化接口
/**
* <p>
*
* </p>
*
* IDID
*
* @author
* @since 2020-05-25 13:23
*/
@Data
@Data // Lombok注解自动生成getter、setter等方法
@ApiModel(value="试题题库", description="试题题库")
public class QuRepoDTO implements Serializable {
private static final long serialVersionUID = 1L;
private String id;
@ApiModelProperty(value = "试题", required=true)
private String quId;
@ApiModelProperty(value = "归属题库", required=true)
private String repoId;
@ApiModelProperty(value = "题目类型", required=true)
private Integer quType;
@ApiModelProperty(value = "排序", required=true)
private Integer sort;
}
private static final long serialVersionUID = 1L; // 序列化版本UID
/**
* ID
*
*/
private String id; // 试题ID
/**
* ID
* ID
*/
@ApiModelProperty(value = "试题", required=true) // Swagger注解描述字段信息标明该字段是必填项
private String quId; // 题目ID
/**
* ID
*
*/
@ApiModelProperty(value = "归属题库", required=true) // Swagger注解描述字段信息标明该字段是必填项
private String repoId; // 题库ID
/**
*
*
*/
@ApiModelProperty(value = "题目类型", required=true) // Swagger注解描述字段信息标明该字段是必填项
private Integer quType; // 题目类型
/**
*
*
*/
@ApiModelProperty(value = "排序", required=true) // Swagger注解描述字段信息标明该字段是必填项
private Integer sort; // 排序
}

@ -1,45 +1,59 @@
package com.yf.exam.modules.qu.dto.export;
import com.yf.exam.core.utils.excel.annotation.ExcelField;
import com.yf.exam.core.utils.excel.fieldtype.ListType;
import lombok.Data;
import com.yf.exam.core.utils.excel.annotation.ExcelField; // Excel导出注解
import com.yf.exam.core.utils.excel.fieldtype.ListType; // 用于处理List类型字段的特殊注解
import lombok.Data; // Lombok注解用于自动生成getter、setter、toString等方法
import java.util.List;
import java.util.List; // 用于表示列表类型的字段
/**
*
*
* 使DTO
* Excel
*
* @author bool
*/
@Data
@Data // Lombok注解自动生成getter、setter等方法
public class QuExportDTO {
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L; // 序列化版本UID
/**
*
* ID
*/
private String qId;
@ExcelField(title="题目序号", align=2, sort=1)
private String no;
@ExcelField(title="题目类型", align=2, sort=2)
private String quType;
@ExcelField(title="题目内容", align=2, sort=3)
private String qContent;
@ExcelField(title="整体解析", align=2, sort=4)
private String qAnalysis;
@ExcelField(title="题目图片", align=2, sort=5)
private String qImage;
@ExcelField(title="题目视频", align=2, sort=6)
private String qVideo;
@ExcelField(title="所属题库", align=2, sort=7, fieldType = ListType.class)
private List<String> repoList;
@ExcelField(title="是否正确项", align=2, sort=8)
private String aIsRight;
@ExcelField(title="选项内容", align=2, sort=9)
private String aContent;
@ExcelField(title="选项解析", align=2, sort=10)
private String aAnalysis;
@ExcelField(title="选项图片", align=2, sort=11)
private String aImage;
private String qId; // 题目的唯一标识符
@ExcelField(title="题目序号", align=2, sort=1) // 导出Excel时的列标题和排序align为居中对齐sort为排序位置
private String no; // 题目序号,表示题目的编号
@ExcelField(title="题目类型", align=2, sort=2) // Excel导出列的标题和排序
private String quType; // 题目类型,可能是单选题、多选题等
@ExcelField(title="题目内容", align=2, sort=3) // Excel导出列的标题和排序
private String qContent; // 题目内容,包含问题的具体描述
@ExcelField(title="整体解析", align=2, sort=4) // Excel导出列的标题和排序
private String qAnalysis; // 整个题目的解析说明
@ExcelField(title="题目图片", align=2, sort=5) // Excel导出列的标题和排序
private String qImage; // 题目图片存储图片URL或路径
@ExcelField(title="题目视频", align=2, sort=6) // Excel导出列的标题和排序
private String qVideo; // 题目视频存储视频URL或路径
@ExcelField(title="所属题库", align=2, sort=7, fieldType = ListType.class) // 题库列表,支持导出多个题库
private List<String> repoList; // 题目所属的题库列表
@ExcelField(title="是否正确项", align=2, sort=8) // Excel导出列的标题和排序
private String aIsRight; // 是否为正确选项0或1
@ExcelField(title="选项内容", align=2, sort=9) // Excel导出列的标题和排序
private String aContent; // 选项内容,表示答案的具体内容
@ExcelField(title="选项解析", align=2, sort=10) // Excel导出列的标题和排序
private String aAnalysis; // 选项解析,说明该选项的正确性或相关分析
@ExcelField(title="选项图片", align=2, sort=11) // Excel导出列的标题和排序
private String aImage; // 选项图片存储图片URL或路径
}

@ -1,23 +1,56 @@
package com.yf.exam.modules.qu.dto.export;
import com.yf.exam.modules.qu.dto.QuAnswerDTO;
import lombok.Data;
import com.yf.exam.modules.qu.dto.QuAnswerDTO; // 导入的选项答案DTO
import lombok.Data; // Lombok注解用于自动生成getter、setter、toString等方法
import java.util.List;
import java.util.List; // 用于表示列表类型的字段
/**
*
*
* DTO
*
*
* @author bool
*/
@Data
@Data // Lombok注解自动生成getter、setter等方法
public class QuImportDTO {
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L; // 序列化版本UID
private String quType;
private String qContent;
private String qAnalysis;
private String qImage;
private String repoName;
private List<QuAnswerDTO> answerList;
/**
*
* 1234
*/
private String quType; // 题目类型,表示题目的类别
/**
*
*
*/
private String qContent; // 题目内容,表示题目的实际问题
/**
*
*
*/
private String qAnalysis; // 题目解析,解释题目的答案或相关说明
/**
*
* URL
*/
private String qImage; // 题目图片存储图片URL或路径
/**
*
*
*/
private String repoName; // 题目所属的题库名称
/**
*
*
*/
private List<QuAnswerDTO> answerList; // 答案选项列表,包含该题目的所有答案选项
}

@ -1,33 +1,43 @@
package com.yf.exam.modules.qu.dto.ext;
import com.yf.exam.modules.qu.dto.QuAnswerDTO;
import com.yf.exam.modules.qu.dto.QuDTO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import com.yf.exam.modules.qu.dto.QuAnswerDTO; // 引入选项答案DTO
import com.yf.exam.modules.qu.dto.QuDTO; // 引入问题题目DTO
import io.swagger.annotations.ApiModel; // Swagger注解用于生成API文档
import io.swagger.annotations.ApiModelProperty; // Swagger注解用于描述API模型的属性
import lombok.Data; // Lombok注解用于自动生成getter、setter等方法
import java.util.List;
import java.util.List; // 用于表示列表类型的字段
/**
* <p>
*
* </p>
*
* `QuDTO`
*
*
* @author
* @since 2020-05-25 13:23
*/
@Data
@Data // Lombok注解自动生成getter、setter等方法
@ApiModel(value="问题题目详情", description="问题题目详情")
public class QuDetailDTO extends QuDTO {
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L; // 序列化版本UID
@ApiModelProperty(value = "备选项列表", required=true)
private List<QuAnswerDTO> answerList;
@ApiModelProperty(value = "题库列表", required=true)
private List<String> repoIds;
/**
*
*
*
*/
@ApiModelProperty(value = "备选项列表", required=true) // Swagger注解用于生成文档
private List<QuAnswerDTO> answerList; // 备选项列表,包含该题目的所有答案选项
/**
*
* ID
*
*/
@ApiModelProperty(value = "题库列表", required=true) // Swagger注解用于生成文档
private List<String> repoIds; // 题库列表存储题库ID的列表
}

@ -1,38 +1,54 @@
package com.yf.exam.modules.qu.dto.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import io.swagger.annotations.ApiModel; // Swagger注解用于生成API文档
import io.swagger.annotations.ApiModelProperty; // Swagger注解用于描述API模型的属性
import lombok.Data; // Lombok注解用于自动生成getter、setter等方法
import java.io.Serializable;
import java.util.List;
import java.io.Serializable; // 可序列化接口
import java.util.List; // 用于表示列表类型的字段
/**
* <p>
*
* </p>
*
*
* ID便
*
* @author
* @since 2020-05-25 13:23
*/
@Data
@Data // Lombok注解自动生成getter、setter等方法
@ApiModel(value="题目查询请求类", description="题目查询请求类")
public class QuQueryReqDTO implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "题目类型")
private Integer quType;
@ApiModelProperty(value = "归属题库")
private List<String> repoIds;
@ApiModelProperty(value = "题目内容")
private String content;
@ApiModelProperty(value = "排除ID列表")
private List<String> excludes;
private static final long serialVersionUID = 1L; // 序列化版本UID
/**
*
*
*/
@ApiModelProperty(value = "题目类型") // Swagger注解描述字段信息
private Integer quType; // 题目类型,通常是数字表示不同题型
/**
*
* ID
*/
@ApiModelProperty(value = "归属题库") // Swagger注解描述字段信息
private List<String> repoIds; // 题库ID列表题目可以归属于多个题库
/**
*
*
*/
@ApiModelProperty(value = "题目内容") // Swagger注解描述字段信息
private String content; // 题目内容,支持模糊查询
/**
* ID
* IDID
*/
@ApiModelProperty(value = "排除ID列表") // Swagger注解描述字段信息
private List<String> excludes; // 排除的题目ID列表
}

@ -1,34 +1,47 @@
package com.yf.exam.modules.qu.dto.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import io.swagger.annotations.ApiModel; // Swagger注解用于生成API文档
import io.swagger.annotations.ApiModelProperty; // Swagger注解用于描述API模型的属性
import lombok.Data; // Lombok注解用于自动生成getter、setter等方法
import java.io.Serializable;
import java.util.List;
import java.io.Serializable; // 可序列化接口
import java.util.List; // 用于表示列表类型的字段
/**
* <p>
*
*
* </p>
*
*
*
*
* @author
* @since 2020-05-25 13:23
*/
@Data
@Data // Lombok注解自动生成getter、setter等方法
@ApiModel(value="试题题库批量操作类", description="试题题库批量操作类")
public class QuRepoBatchReqDTO implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "题目ID", required=true)
private List<String> quIds;
@ApiModelProperty(value = "题目类型", required=true)
private List<String> repoIds;
@ApiModelProperty(value = "是否移除,否就新增;是就移除", required=true)
private Boolean remove;
private static final long serialVersionUID = 1L; // 序列化版本UID
/**
* ID
* ID
*/
@ApiModelProperty(value = "题目ID", required=true) // Swagger注解描述字段信息标明该字段是必填项
private List<String> quIds; // 要操作的题目ID列表
/**
* ID
* ID
*/
@ApiModelProperty(value = "题目类型", required=true) // Swagger注解描述字段信息标明该字段是必填项
private List<String> repoIds; // 题库ID列表
/**
*
* `true` `false`
*/
@ApiModelProperty(value = "是否移除,否就新增;是就移除", required=true) // Swagger注解描述字段信息标明该字段是必填项
private Boolean remove; // `true`表示移除,`false`表示新增
}

@ -1,75 +1,85 @@
package com.yf.exam.modules.qu.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.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.Data;
import com.baomidou.mybatisplus.annotation.IdType; // MyBatis Plus注解指定ID生成策略
import com.baomidou.mybatisplus.annotation.TableField; // MyBatis Plus注解指定字段映射
import com.baomidou.mybatisplus.annotation.TableId; // MyBatis Plus注解指定主键字段
import com.baomidou.mybatisplus.annotation.TableName; // MyBatis Plus注解指定表名
import com.baomidou.mybatisplus.extension.activerecord.Model; // MyBatis Plus扩展的活动记录模式类
import lombok.Data; // Lombok注解用于自动生成getter、setter等方法
import java.util.Date;
import java.util.Date; // 日期类型
/**
* <p>
*
* </p>
*
* MyBatis-Plus
*
* @author
* @since 2020-05-25 13:23
*/
@Data
@TableName("el_qu")
@Data // Lombok注解自动生成getter、setter等方法
@TableName("el_qu") // MyBatis Plus注解指定与数据库表的映射关系
public class Qu extends Model<Qu> {
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L; // 序列化版本UID
/**
* ID
*
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private String id;
@TableId(value = "id", type = IdType.ASSIGN_ID) // MyBatis Plus注解指定主键生成策略为自定义ID
private String id; // 题目ID
/**
*
*
*/
@TableField("qu_type")
private Integer quType;
@TableField("qu_type") // MyBatis Plus注解指定字段名与数据库表字段名映射
private Integer quType; // 题目类型
/**
* 1,2
*
* 12
*/
private Integer level;
private Integer level; // 题目难度1普通2较难
/**
*
* URL
*/
private String image;
private String image; // 题目图片
/**
*
*
*/
private String content;
private String content; // 题目内容
/**
*
*
*/
@TableField("create_time")
private Date createTime;
@TableField("create_time") // MyBatis Plus注解映射数据库中的字段
private Date createTime; // 创建时间
/**
*
*
*/
@TableField("update_time")
private Date updateTime;
@TableField("update_time") // MyBatis Plus注解映射数据库中的字段
private Date updateTime; // 更新时间
/**
*
*
*/
private String remark;
private String remark; // 题目备注
/**
*
*
*/
private String analysis;
private String analysis; // 整题解析
}

@ -1,58 +1,64 @@
package com.yf.exam.modules.qu.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.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.Data;
import com.baomidou.mybatisplus.annotation.IdType; // MyBatis Plus注解指定ID生成策略
import com.baomidou.mybatisplus.annotation.TableField; // MyBatis Plus注解指定字段映射
import com.baomidou.mybatisplus.annotation.TableId; // MyBatis Plus注解指定主键字段
import com.baomidou.mybatisplus.annotation.TableName; // MyBatis Plus注解指定表名
import com.baomidou.mybatisplus.extension.activerecord.Model; // MyBatis Plus扩展的活动记录模式类
import lombok.Data; // Lombok注解用于自动生成getter、setter等方法
/**
* <p>
*
* </p>
*
* MyBatis-Plus
*
* @author
* @since 2020-05-25 13:23
*/
@Data
@TableName("el_qu_answer")
@Data // Lombok注解自动生成getter、setter等方法
@TableName("el_qu_answer") // MyBatis Plus注解指定与数据库表的映射关系
public class QuAnswer extends Model<QuAnswer> {
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L; // 序列化版本UID
/**
* ID
*
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private String id;
@TableId(value = "id", type = IdType.ASSIGN_ID) // MyBatis Plus注解指定主键生成策略为自定义ID
private String id; // 答案ID
/**
* ID
* ID
*/
@TableField("qu_id")
private String quId;
@TableField("qu_id") // MyBatis Plus注解指定字段名与数据库表字段名映射
private String quId; // 问题ID
/**
*
* truefalse
*/
@TableField("is_right")
private Boolean isRight;
@TableField("is_right") // MyBatis Plus注解映射数据库中的字段
private Boolean isRight; // 是否正确
/**
*
* URL
*/
private String image;
private String image; // 选项图片
/**
*
*
*/
private String content;
private String content; // 答案内容
/**
*
*
*/
private String analysis;
private String analysis; // 答案分析
}

@ -1,50 +1,59 @@
package com.yf.exam.modules.qu.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.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.Data;
import com.baomidou.mybatisplus.annotation.IdType; // MyBatis Plus注解指定ID生成策略
import com.baomidou.mybatisplus.annotation.TableField; // MyBatis Plus注解指定字段映射
import com.baomidou.mybatisplus.annotation.TableId; // MyBatis Plus注解指定主键字段
import com.baomidou.mybatisplus.annotation.TableName; // MyBatis Plus注解指定表名
import com.baomidou.mybatisplus.extension.activerecord.Model; // MyBatis Plus扩展的活动记录模式类
import lombok.Data; // Lombok注解用于自动生成getter、setter等方法
/**
* <p>
*
* </p>
*
*
*
* @author
* @since 2020-05-25 13:23
*/
@Data
@TableName("el_qu_repo")
@Data // Lombok注解自动生成getter、setter等方法
@TableName("el_qu_repo") // MyBatis Plus注解指定与数据库表的映射关系
public class QuRepo extends Model<QuRepo> {
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L; // 序列化版本UID
@TableId(value = "id", type = IdType.ASSIGN_ID)
private String id;
/**
* ID
*
*/
@TableId(value = "id", type = IdType.ASSIGN_ID) // MyBatis Plus注解指定主键生成策略为自定义ID
private String id; // 试题题库关系ID
/**
*
* ID
* ID
*/
@TableField("qu_id")
private String quId;
@TableField("qu_id") // MyBatis Plus注解指定字段名与数据库表字段名映射
private String quId; // 试题ID
/**
*
* ID
* ID
*/
@TableField("repo_id")
private String repoId;
@TableField("repo_id") // MyBatis Plus注解指定字段名与数据库表字段名映射
private String repoId; // 题库ID
/**
*
*
*/
@TableField("qu_type")
private Integer quType;
@TableField("qu_type") // MyBatis Plus注解映射数据库中的字段
private Integer quType; // 题目类型
/**
*
*
*/
private Integer sort;
private Integer sort; // 排序
}

@ -1,8 +1,10 @@
package com.yf.exam.modules.qu.enums;
/**
*
*
*
*
*
* @author bool
* @date 2019-10-30 13:11
*/
@ -10,16 +12,19 @@ public interface QuType {
/**
*
*
*/
Integer RADIO = 1;
/**
*
*
*/
Integer MULTI = 2;
/**
*
*
*/
Integer JUDGE = 3;

@ -4,13 +4,13 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yf.exam.modules.qu.entity.QuAnswer;
/**
* <p>
* Mapper
* </p>
*
* @author
* @since 2020-05-25 13:23
*/
* <p>
* Mapper
* </p>
*
* @author
* @since 2020-05-25 13:23
*/
public interface QuAnswerMapper extends BaseMapper<QuAnswer> {
}

@ -1,15 +1,15 @@
package com.yf.exam.modules.qu.mapper;
package com.yf.exam.modules.qu.mapper; // 定义包名,用于存放与问题题目相关的 Mapper 类
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yf.exam.modules.qu.dto.QuDTO;
import com.yf.exam.modules.qu.dto.export.QuExportDTO;
import com.yf.exam.modules.qu.dto.request.QuQueryReqDTO;
import com.yf.exam.modules.qu.entity.Qu;
import org.apache.ibatis.annotations.Param;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; // 导入 MyBatis-Plus 的 BaseMapper用于提供通用的 CRUD 方法
import com.baomidou.mybatisplus.core.metadata.IPage; // 导入分页接口 IPage用于处理分页结果
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; // 导入分页插件的 Page 类,用于分页查询
import com.yf.exam.modules.qu.dto.QuDTO; // 导入 QuDTO 数据传输对象,用于封装题目数据
import com.yf.exam.modules.qu.dto.export.QuExportDTO; // 导入 QuExportDTO 用于题目导出的数据结构
import com.yf.exam.modules.qu.dto.request.QuQueryReqDTO; // 导入 QuQueryReqDTO 用于封装查询条件
import com.yf.exam.modules.qu.entity.Qu; // 导入 Qu 实体类,表示题目表的对应数据
import org.apache.ibatis.annotations.Param; // 导入 MyBatis 的 Param 注解,用于 SQL 查询中的参数传递
import java.util.List;
import java.util.List; // 导入 List用于返回多个对象的集合
/**
* <p>
@ -19,38 +19,34 @@ import java.util.List;
* @author
* @since 2020-05-25 13:23
*/
public interface QuMapper extends BaseMapper<Qu> {
public interface QuMapper extends BaseMapper<Qu> { // QuMapper 继承自 BaseMapper提供基本的 CRUD 操作
/**
*
* @param repoId
* @param quType
* @param level
* @param repoId ID
* @param quType
* @param level
* @param excludes ID
* @param size
* @return
* @param size
* @return
*/
List<Qu> listByRandom(@Param("repoId") String repoId,
@Param("quType") Integer quType,
@Param("excludes") List<String> excludes,
@Param("size") Integer size);
List<Qu> listByRandom(@Param("repoId") String repoId, // 题库ID
@Param("quType") Integer quType, // 题目类型
@Param("excludes") List<String> excludes, // 要排除的题目ID列表
@Param("size") Integer size); // 抽取的题目数量
/**
*
* @param query
* @return
* @param query
* @return
*/
List<QuExportDTO> listForExport(@Param("query") QuQueryReqDTO query);
List<QuExportDTO> listForExport(@Param("query") QuQueryReqDTO query); // 根据查询条件查找导出数据
/**
*
* @param page
* @param query
* @return
* @param page
* @param query
* @return
*/
IPage<QuDTO> paging(Page page, @Param("query") QuQueryReqDTO query);
IPage<QuDTO> paging(Page page, @Param("query") QuQueryReqDTO query); // 分页查询题目数据,返回 QuDTO 类型的数据
}

@ -1,7 +1,7 @@
package com.yf.exam.modules.qu.mapper;
package com.yf.exam.modules.qu.mapper; // 定义包名,用于存放与试题题库相关的 Mapper 类
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yf.exam.modules.qu.entity.QuRepo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; // 导入 MyBatis-Plus 的 BaseMapper用于提供通用的 CRUD 方法
import com.yf.exam.modules.qu.entity.QuRepo; // 导入 QuRepo 实体类,表示试题题库表的数据
/**
* <p>
@ -11,6 +11,5 @@ import com.yf.exam.modules.qu.entity.QuRepo;
* @author
* @since 2020-05-25 13:23
*/
public interface QuRepoMapper extends BaseMapper<QuRepo> {
public interface QuRepoMapper extends BaseMapper<QuRepo> { // QuRepoMapper 继承自 BaseMapper提供基本的 CRUD 操作
}

@ -10,7 +10,7 @@ import java.util.List;
/**
* <p>
*
*
* </p>
*
* @author
@ -19,30 +19,30 @@ import java.util.List;
public interface QuAnswerService extends IService<QuAnswer> {
/**
*
* @param reqDTO
* @return
*
* @param reqDTO
* @return
*/
IPage<QuAnswerDTO> paging(PagingReqDTO<QuAnswerDTO> reqDTO);
/**
* ID
* @param quId
* @return
* ID
* @param quId ID
* @return
*/
List<QuAnswer> listAnswerByRandom(String quId);
/**
*
* @param quId
* @return
* ID
* @param quId ID
* @return
*/
List<QuAnswerDTO> listByQu(String quId);
/**
*
* @param quId
* @param list
*
* @param quId ID
* @param list
*/
void saveAll(String quId, List<QuAnswerDTO> list);
}

@ -1,59 +1,66 @@
// 定义包名表示该接口属于com.yf.exam.modules.qu.service包下
package com.yf.exam.modules.qu.service;
// 导入MyBatis Plus框架的分页功能相关类
import com.baomidou.mybatisplus.core.metadata.IPage;
// 导入MyBatis Plus框架的服务接口
import com.baomidou.mybatisplus.extension.service.IService;
// 导入项目中定义的分页请求DTO类
import com.yf.exam.core.api.dto.PagingReqDTO;
// 导入项目中定义的题库DTO类
import com.yf.exam.modules.qu.dto.QuRepoDTO;
// 导入项目中定义的批量请求DTO类
import com.yf.exam.modules.qu.dto.request.QuRepoBatchReqDTO;
// 导入项目中定义的题库实体类
import com.yf.exam.modules.qu.entity.QuRepo;
// 导入Java.util包下的List接口用于操作列表
import java.util.List;
/**
* <p>
*
* </p>
*
* @author
* @since 2020-05-25 13:23
*/
* <p>
*
* </p>
*
* @author
* @since 2020-05-25 13:23
*/
public interface QuRepoService extends IService<QuRepo> {
/**
*
* @param reqDTO
* @return
*/
*
* @param reqDTO DTO
* @return
*/
IPage<QuRepoDTO> paging(PagingReqDTO<QuRepoDTO> reqDTO);
/**
*
* @param quId
* @param quType
* @param ids
*
* @param quId ID
* @param quType
* @param ids ID
*/
void saveAll(String quId, Integer quType, List<String> ids);
/**
*
* @param quId
* @return
*
* @param quId ID
* @return ID
*/
List<String> listByQu(String quId);
/**
* ID
* @param repoId
* @param quType
* @param rand
* @return
* ID
* @param repoId ID
* @param quType
* @param rand
* @return ID
*/
List<String> listByRepo(String repoId, Integer quType, boolean rand);
/**
*
* @param reqDTO
*
* @param reqDTO DTO
*/
void batchAction(QuRepoBatchReqDTO reqDTO);
}
}

@ -1,46 +1,55 @@
// 定义包名表示该接口属于com.yf.exam.modules.qu.service包下
package com.yf.exam.modules.qu.service;
// 导入MyBatis Plus框架的分页功能相关类
import com.baomidou.mybatisplus.core.metadata.IPage;
// 导入MyBatis Plus框架的服务接口
import com.baomidou.mybatisplus.extension.service.IService;
// 导入项目中定义的分页请求DTO类
import com.yf.exam.core.api.dto.PagingReqDTO;
// 导入项目中定义的题目DTO类
import com.yf.exam.modules.qu.dto.QuDTO;
// 导入项目中定义的题目导出DTO类
import com.yf.exam.modules.qu.dto.export.QuExportDTO;
// 导入项目中定义的扩展题目详情DTO类
import com.yf.exam.modules.qu.dto.ext.QuDetailDTO;
// 导入项目中定义的题目查询请求DTO类
import com.yf.exam.modules.qu.dto.request.QuQueryReqDTO;
// 导入项目中定义的题目实体类
import com.yf.exam.modules.qu.entity.Qu;
// 导入Java.util包下的List接口用于操作列表
import java.util.List;
/**
* <p>
*
* </p>
*
* @author
* @since 2020-05-25 13:23
*/
* <p>
*
* </p>
*
* @author
* @since 2020-05-25 13:23
*/
public interface QuService extends IService<Qu> {
/**
*
* @param reqDTO
* @return
*
* @param reqDTO DTO
* @return
*/
IPage<QuDTO> paging(PagingReqDTO<QuQueryReqDTO> reqDTO);
/**
*
* @param ids
*
* @param ids ID
*/
void delete(List<String> ids);
/**
*
* @param repoId
* @param quType
*
* @param repoId ID
* @param quType
* @param excludes ID
* @param size
* @return
* @param size
* @return
*/
List<Qu> listByRandom(String repoId,
Integer quType,
@ -48,29 +57,29 @@ public interface QuService extends IService<Qu> {
Integer size);
/**
*
* @param id
* @return
*
* @param id ID
* @return DTO
*/
QuDetailDTO detail(String id);
/**
*
* @param reqDTO
*
* @param reqDTO DTO
*/
void save(QuDetailDTO reqDTO);
/**
*
* @param query
* @return
*
* @param query DTO
* @return
*/
List<QuExportDTO> listForExport(QuQueryReqDTO query);
/**
* Excel
* @param dtoList
* @return
* Excel
* @param dtoList DTO
* @return
*/
int importExcel(List<QuExportDTO> dtoList);
}
}

@ -1,24 +1,24 @@
package com.yf.exam.modules.qu.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yf.exam.core.api.dto.PagingReqDTO;
import com.yf.exam.core.utils.BeanMapper;
import com.yf.exam.modules.qu.dto.QuAnswerDTO;
import com.yf.exam.modules.qu.entity.QuAnswer;
import com.yf.exam.modules.qu.mapper.QuAnswerMapper;
import com.yf.exam.modules.qu.service.QuAnswerService;
import com.yf.exam.modules.qu.utils.ImageCheckUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
package com.yf.exam.modules.qu.service.impl; // 定义包名,表示这是实现类部分,专注于处理与试题答案相关的逻辑
import com.alibaba.fastjson.JSON; // 导入 fastjson 库,用于 JSON 序列化和反序列化
import com.alibaba.fastjson.TypeReference; // 导入 fastjson 库的 TypeReference用于处理泛型类型
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; // 导入 MyBatis-Plus 的 QueryWrapper用于构造查询条件
import com.baomidou.mybatisplus.core.metadata.IPage; // 导入 MyBatis-Plus 的 IPage 接口,用于分页查询
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; // 导入 MyBatis-Plus 的分页 Page 类
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; // 导入 MyBatis-Plus 的 ServiceImpl 基类
import com.yf.exam.core.api.dto.PagingReqDTO; // 导入分页请求数据传输对象类
import com.yf.exam.core.utils.BeanMapper; // 导入 BeanMapper 工具类,用于对象之间的映射
import com.yf.exam.modules.qu.dto.QuAnswerDTO; // 导入试题答案的 DTO 类
import com.yf.exam.modules.qu.entity.QuAnswer; // 导入试题答案的实体类
import com.yf.exam.modules.qu.mapper.QuAnswerMapper; // 导入试题答案的 Mapper 接口
import com.yf.exam.modules.qu.service.QuAnswerService; // 导入试题答案的服务接口
import com.yf.exam.modules.qu.utils.ImageCheckUtils; // 导入图片校验工具类
import org.springframework.beans.factory.annotation.Autowired; // 导入 Spring 的注解,自动注入依赖
import org.springframework.stereotype.Service; // 导入 Spring 的服务注解,标识这是一个服务类
import org.springframework.util.CollectionUtils; // 导入 Spring 的集合工具类,用于检查集合是否为空
import java.util.ArrayList; // 导入 ArrayList用于动态数组
import java.util.List; // 导入 List 接口,作为列表类型
/**
* <p>
@ -28,65 +28,77 @@ import java.util.List;
* @author
* @since 2020-05-25 13:23
*/
@Service
@Service // 表示这是一个服务类Spring 会自动扫描并管理该类
public class QuAnswerServiceImpl extends ServiceImpl<QuAnswerMapper, QuAnswer> implements QuAnswerService {
@Autowired
private ImageCheckUtils imageCheckUtils;
private ImageCheckUtils imageCheckUtils; // 自动注入图片校验工具类,用于校验图片地址是否合法
@Override
public IPage<QuAnswerDTO> paging(PagingReqDTO<QuAnswerDTO> reqDTO) {
//创建分页对象
// 创建分页对象,传入当前页和每页大小
IPage<QuAnswer> query = new Page<>(reqDTO.getCurrent(), reqDTO.getSize());
//查询条件
// 创建查询条件包装器
QueryWrapper<QuAnswer> wrapper = new QueryWrapper<>();
//获得数据
// 执行分页查询,获取分页结果
IPage<QuAnswer> page = this.page(query, wrapper);
//转换结果
// 将查询结果转换为 QuAnswerDTO 类型的分页结果
IPage<QuAnswerDTO> pageData = JSON.parseObject(JSON.toJSONString(page), new TypeReference<Page<QuAnswerDTO>>(){});
return pageData;
}
}
@Override
public List<QuAnswer> listAnswerByRandom(String quId) {
// 创建查询条件包装器
QueryWrapper<QuAnswer> wrapper = new QueryWrapper<>();
// 设置查询条件,过滤出与 quId 相同的记录
wrapper.lambda().eq(QuAnswer::getQuId, quId);
// 使用 SQL 的随机排序来随机获取答案
wrapper.last(" ORDER BY RAND() ");
// 执行查询并返回结果
return this.list(wrapper);
}
@Override
public List<QuAnswerDTO> listByQu(String quId) {
// 创建查询条件包装器
QueryWrapper<QuAnswer> wrapper = new QueryWrapper<>();
// 设置查询条件,过滤出与 quId 相同的记录
wrapper.lambda().eq(QuAnswer::getQuId, quId);
// 执行查询,获取答案列表
List<QuAnswer> list = this.list(wrapper);
if(!CollectionUtils.isEmpty(list)){
// 将 QuAnswer 实体对象列表转换为 QuAnswerDTO 对象列表
return BeanMapper.mapList(list, QuAnswerDTO.class);
}
// 如果没有找到记录,返回 null
return null;
}
/**
*
* @param quId
* @return
* @param quId ID
* @return ID
*/
public List<String> findExistsList(String quId) {
//返回结果
// 创建空的结果列表
List<String> ids = new ArrayList<>();
// 创建查询条件包装器
QueryWrapper<QuAnswer> wrapper = new QueryWrapper();
// 设置查询条件,过滤出与 quId 相同的记录
wrapper.lambda().eq(QuAnswer::getQuId, quId);
// 执行查询,获取答案列表
List<QuAnswer> list = this.list(wrapper);
if (!CollectionUtils.isEmpty(list)) {
// 将已有的答案 ID 添加到结果列表
for (QuAnswer item : list) {
ids.add(item.getId());
}
@ -96,49 +108,49 @@ public class QuAnswerServiceImpl extends ServiceImpl<QuAnswerMapper, QuAnswer> i
@Override
public void saveAll(String quId, List<QuAnswerDTO> list) {
//最终要保存的列表
// 创建保存的答案列表
List<QuAnswer> saveList = new ArrayList<>();
//已存在的标签列表
// 获取已有的答案 ID 列表
List<String> ids = this.findExistsList(quId);
// 如果答案列表不为空,则进行处理
if(!CollectionUtils.isEmpty(list)){
for(QuAnswerDTO item: list){
// 校验图片地址
// 校验选项图片地址是否合法
imageCheckUtils.checkImage(item.getImage(), "选项图片地址错误!");
//标签ID
// 获取答案 ID
String id = item.getId();
QuAnswer answer = new QuAnswer();
// 将 DTO 转换为实体类
BeanMapper.copy(item, answer);
answer.setQuId(quId);
answer.setQuId(quId); // 设置试题 ID
//补全ID避免新增
// 如果该答案已存在,则从 IDs 列表中移除
if(ids.contains(id)){
ids.remove(id);
}
// 添加答案到保存列表
saveList.add(answer);
}
//保存标签列表
// 如果有待保存的答案,则批量保存或更新
if(!CollectionUtils.isEmpty(saveList)) {
this.saveOrUpdateBatch(saveList);
}
//除已移
// 如果有被移除的答案,则批量删除
if(!ids.isEmpty()){
this.removeByIds(ids);
}
}else{
// 如果答案列表为空,则删除所有与该试题 ID 相关的答案
QueryWrapper<QuAnswer> wrapper = new QueryWrapper<>();
wrapper.lambda().eq(QuAnswer::getQuId, quId);
this.remove(wrapper);
}
}
}

@ -1,175 +1,182 @@
package com.yf.exam.modules.qu.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yf.exam.core.api.dto.PagingReqDTO;
import com.yf.exam.modules.qu.dto.QuRepoDTO;
import com.yf.exam.modules.qu.dto.request.QuRepoBatchReqDTO;
import com.yf.exam.modules.qu.entity.Qu;
import com.yf.exam.modules.qu.entity.QuRepo;
import com.yf.exam.modules.qu.mapper.QuMapper;
import com.yf.exam.modules.qu.mapper.QuRepoMapper;
import com.yf.exam.modules.qu.service.QuRepoService;
import com.yf.exam.modules.repo.service.RepoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
package com.yf.exam.modules.qu.service.impl; // 定义包名,表示这是服务实现类,负责处理与试题题库相关的业务逻辑
import com.alibaba.fastjson.JSON; // 导入 fastjson 库,用于 JSON 序列化和反序列化
import com.alibaba.fastjson.TypeReference; // 导入 fastjson 库的 TypeReference用于处理泛型类型
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; // 导入 MyBatis-Plus 的 QueryWrapper用于构造查询条件
import com.baomidou.mybatisplus.core.metadata.IPage; // 导入 MyBatis-Plus 的 IPage 接口,用于分页查询
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; // 导入 MyBatis-Plus 的分页 Page 类
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; // 导入 MyBatis-Plus 的 ServiceImpl 基类
import com.yf.exam.core.api.dto.PagingReqDTO; // 导入分页请求数据传输对象类
import com.yf.exam.modules.qu.dto.QuRepoDTO; // 导入试题题库的 DTO 类
import com.yf.exam.modules.qu.dto.request.QuRepoBatchReqDTO; // 导入试题题库批量操作请求类
import com.yf.exam.modules.qu.entity.Qu; // 导入试题实体类
import com.yf.exam.modules.qu.entity.QuRepo; // 导入试题题库实体类
import com.yf.exam.modules.qu.mapper.QuMapper; // 导入试题的 Mapper 接口
import com.yf.exam.modules.qu.mapper.QuRepoMapper; // 导入试题题库的 Mapper 接口
import com.yf.exam.modules.qu.service.QuRepoService; // 导入试题题库服务接口
import com.yf.exam.modules.repo.service.RepoService; // 导入题库服务接口
import org.springframework.beans.factory.annotation.Autowired; // 导入 Spring 的注解,自动注入依赖
import org.springframework.stereotype.Service; // 导入 Spring 的服务注解,标识这是一个服务类
import org.springframework.util.CollectionUtils; // 导入 Spring 的集合工具类,用于检查集合是否为空
import java.util.ArrayList; // 导入 ArrayList用于动态数组
import java.util.List; // 导入 List 接口,作为列表类型
/**
* <p>
*
*
* </p>
*
* @author
* @since 2020-05-25 13:23
*/
@Service
@Service // 表示这是一个 Spring 服务类Spring 会自动扫描并管理该类
public class QuRepoServiceImpl extends ServiceImpl<QuRepoMapper, QuRepo> implements QuRepoService {
@Autowired
private QuMapper quMapper;
private QuMapper quMapper; // 自动注入试题的 Mapper 接口
@Autowired
private RepoService repoService;
private RepoService repoService; // 自动注入题库服务接口
@Override
public IPage<QuRepoDTO> paging(PagingReqDTO<QuRepoDTO> reqDTO) {
//创建分页对象
// 创建分页对象,传入当前页和每页大小
IPage<QuRepo> query = new Page<>(reqDTO.getCurrent(), reqDTO.getSize());
//查询条件
// 创建查询条件包装器
QueryWrapper<QuRepo> wrapper = new QueryWrapper<>();
//获得数据
// 执行分页查询,获取分页结果
IPage<QuRepo> page = this.page(query, wrapper);
//转换结果
// 将查询结果转换为 QuRepoDTO 类型的分页结果
IPage<QuRepoDTO> pageData = JSON.parseObject(JSON.toJSONString(page), new TypeReference<Page<QuRepoDTO>>(){});
return pageData;
}
}
@Override
public void saveAll(String quId, Integer quType, List<String> ids) {
// 先删除
// 先删除已有的试题题库记录
QueryWrapper<QuRepo> wrapper = new QueryWrapper<>();
wrapper.lambda().eq(QuRepo::getQuId, quId);
this.remove(wrapper);
// 保存全部
// 如果题库 ID 列表不为空,保存新的记录
if(!CollectionUtils.isEmpty(ids)){
List<QuRepo> list = new ArrayList<>();
for(String id: ids){
QuRepo ref = new QuRepo();
ref.setQuId(quId);
ref.setRepoId(id);
ref.setQuType(quType);
ref.setQuId(quId); // 设置试题 ID
ref.setRepoId(id); // 设置题库 ID
ref.setQuType(quType); // 设置题目类型
list.add(ref);
}
// 批量保存试题题库记录
this.saveBatch(list);
// 对每个题库进行排序
for(String id: ids){
this.sortRepo(id);
}
}
}
@Override
public List<String> listByQu(String quId) {
// 先删除
// 根据试题 ID 查找题库记录
QueryWrapper<QuRepo> wrapper = new QueryWrapper<>();
wrapper.lambda().eq(QuRepo::getQuId, quId);
List<QuRepo> list = this.list(wrapper);
List<String> ids = new ArrayList<>();
if(!CollectionUtils.isEmpty(list)){
// 提取题库 ID 列表
for(QuRepo item: list){
ids.add(item.getRepoId());
}
}
return ids;
return ids; // 返回题库 ID 列表
}
@Override
public List<String> listByRepo(String repoId, Integer quType, boolean rand) {
// 根据题库 ID 和题目类型查询题库记录
QueryWrapper<QuRepo> wrapper = new QueryWrapper<>();
wrapper.lambda()
.eq(QuRepo::getRepoId, repoId);
wrapper.lambda().eq(QuRepo::getRepoId, repoId);
if(quType!=null){
// 如果有题目类型,添加过滤条件
if(quType != null){
wrapper.lambda().eq(QuRepo::getQuType, quType);
}
// 根据是否需要随机排序决定排序方式
if(rand){
wrapper.orderByAsc(" RAND() ");
wrapper.orderByAsc(" RAND() "); // 随机排序
}else{
wrapper.lambda().orderByAsc(QuRepo::getSort);
wrapper.lambda().orderByAsc(QuRepo::getSort); // 按照排序字段排序
}
// 执行查询,获取题库记录列表
List<QuRepo> list = this.list(wrapper);
List<String> ids = new ArrayList<>();
if(!CollectionUtils.isEmpty(list)){
// 提取试题 ID 列表
for(QuRepo item: list){
ids.add(item.getQuId());
}
}
return ids;
return ids; // 返回试题 ID 列表
}
@Override
public void batchAction(QuRepoBatchReqDTO reqDTO) {
// 移除的
if(reqDTO.getRemove()!=null && reqDTO.getRemove()){
// 如果需要移除记录
if(reqDTO.getRemove() != null && reqDTO.getRemove()){
// 删除满足条件的题库记录
QueryWrapper<QuRepo> wrapper = new QueryWrapper<>();
wrapper.lambda()
.in(QuRepo::getRepoId, reqDTO.getRepoIds())
.in(QuRepo::getQuId, reqDTO.getQuIds());
this.remove(wrapper);
}else{
// 新增的
// 如果是新增记录,处理新增逻辑
for(String quId : reqDTO.getQuIds()){
// 根据试题 ID 查询试题类型
Qu q = quMapper.selectById(quId);
// 保存新的题库记录
this.saveAll(quId, q.getQuType(), reqDTO.getRepoIds());
}
}
// 对每个题库进行排序
for(String id: reqDTO.getRepoIds()){
this.sortRepo(id);
}
}
/**
*
* @param repoId
* @param repoId ID
*/
private void sortRepo(String repoId){
// 查询题库下的所有试题
QueryWrapper<QuRepo> wrapper = new QueryWrapper<>();
wrapper.lambda().eq(QuRepo::getRepoId, repoId);
List<QuRepo> list = this.list(wrapper);
// 如果题库下没有试题,返回
if(CollectionUtils.isEmpty(list)){
return;
}
// 按照顺序设置每个试题的排序值
int sort = 1;
for(QuRepo item: list){
item.setSort(sort);
sort++;
}
// 批量更新排序值
this.updateBatchById(list);
}
}

@ -1,9 +1,12 @@
package com.yf.exam.modules.qu.service.impl;
// 导入MyBatis Plus相关类
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
// 导入其他相关类
import com.yf.exam.ability.upload.config.UploadConfig;
import com.yf.exam.core.api.dto.PagingReqDTO;
import com.yf.exam.core.exception.ServiceException;
@ -23,6 +26,7 @@ import com.yf.exam.modules.qu.service.QuRepoService;
import com.yf.exam.modules.qu.service.QuService;
import com.yf.exam.modules.qu.utils.ImageCheckUtils;
import com.yf.exam.modules.repo.service.RepoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -37,7 +41,7 @@ import java.util.Map;
/**
* <p>
*
*
* </p>
*
* @author
@ -46,125 +50,136 @@ import java.util.Map;
@Service
public class QuServiceImpl extends ServiceImpl<QuMapper, Qu> implements QuService {
// 注入QuAnswerService服务
@Autowired
private QuAnswerService quAnswerService;
// 注入QuRepoService服务
@Autowired
private QuRepoService quRepoService;
// 注入图片校验工具类
@Autowired
private ImageCheckUtils imageCheckUtils;
// 分页查询题目列表
@Override
public IPage<QuDTO> paging(PagingReqDTO<QuQueryReqDTO> reqDTO) {
//创建分页对象
// 创建分页对象
Page page = new Page<>(reqDTO.getCurrent(), reqDTO.getSize());
//转换结果
// 调用baseMapper的分页查询方法获取分页数据
IPage<QuDTO> pageData = baseMapper.paging(page, reqDTO.getParams());
return pageData;
}
// 删除题目、答案和题库绑定
@Transactional(rollbackFor = Exception.class)
@Override
public void delete(List<String> ids) {
// 除题目
// 除题目
this.removeByIds(ids);
// 移除选项
// 删除与题目相关的选项
QueryWrapper<QuAnswer> wrapper = new QueryWrapper<>();
wrapper.lambda().in(QuAnswer::getQuId, ids);
quAnswerService.remove(wrapper);
// 移除题库绑定
// 删除题库与题目的绑定
QueryWrapper<QuRepo> wrapper1 = new QueryWrapper<>();
wrapper1.lambda().in(QuRepo::getQuId, ids);
quRepoService.remove(wrapper1);
}
// 随机获取题目
@Override
public List<Qu> listByRandom(String repoId, Integer quType, List<String> excludes, Integer size) {
return baseMapper.listByRandom(repoId, quType, excludes, size);
}
// 获取题目的详细信息
@Override
public QuDetailDTO detail(String id) {
QuDetailDTO respDTO = new QuDetailDTO();
// 获取题目信息
Qu qu = this.getById(id);
BeanMapper.copy(qu, respDTO);
// 获取题目的选项信息
List<QuAnswerDTO> answerList = quAnswerService.listByQu(id);
respDTO.setAnswerList(answerList);
// 获取题目所属的题库
List<String> repoIds = quRepoService.listByQu(id);
respDTO.setRepoIds(repoIds);
return respDTO;
}
// 保存题目信息
@Transactional(rollbackFor = Exception.class)
@Override
public void save(QuDetailDTO reqDTO) {
// 校验数据
// 校验题目信息
this.checkData(reqDTO, "");
Qu qu = new Qu();
// 将题目详情复制到实体类
BeanMapper.copy(reqDTO, qu);
// 校验图片地址
// 校验图片地址是否正确
imageCheckUtils.checkImage(qu.getImage(), "题干图片地址错误!");
// 更新
// 保存或更新题目信息
this.saveOrUpdate(qu);
// 保存全部问
// 保存目的选项
quAnswerService.saveAll(qu.getId(), reqDTO.getAnswerList());
// 保存到题库
// 保存题目与题库的绑定
quRepoService.saveAll(qu.getId(), qu.getQuType(), reqDTO.getRepoIds());
}
// 获取题目导出的列表
@Override
public List<QuExportDTO> listForExport(QuQueryReqDTO query) {
return baseMapper.listForExport(query);
}
// 导入Excel数据
@Override
public int importExcel(List<QuExportDTO> dtoList) {
//根据题目名称分组
// 根据题目名称分组
Map<Integer, List<QuExportDTO>> anMap = new HashMap<>(16);
//题目本体信息
// 存储题目信息
Map<Integer, QuExportDTO> quMap = new HashMap<>(16);
//数据分组
// 分组数据
for (QuExportDTO item : dtoList) {
// 空白的ID
// 如果题目ID为空跳过
if (StringUtils.isEmpty(item.getNo())) {
continue;
}
Integer key;
//序号
// 获取题目序号
try {
key = Integer.parseInt(item.getNo());
} catch (Exception e) {
continue;
}
//如果已经有题目了,直接处理选项
// 如果题目已存在,直接处理选项
if (anMap.containsKey(key)) {
anMap.get(key).add(item);
} else {
//如果没有,将题目内容和选项一起
// 如果没有,将题目内容和选项一起放入
List<QuExportDTO> subList = new ArrayList<>();
subList.add(item);
anMap.put(key, subList);
@ -174,49 +189,46 @@ public class QuServiceImpl extends ServiceImpl<QuMapper, Qu> implements QuServic
int count = 0;
try {
//循环题目插入
// 遍历题目插入
for (Integer key : quMap.keySet()) {
QuExportDTO im = quMap.get(key);
//题目基本信息
// 处理题目基本信息
QuDetailDTO qu = new QuDetailDTO();
qu.setContent(im.getQContent());
qu.setAnalysis(im.getQAnalysis());
qu.setQuType(Integer.parseInt(im.getQuType()));
qu.setCreateTime(new Date());
//设置回答列表
// 设置题目的回答列表
List<QuAnswerDTO> answerList = this.processAnswerList(anMap.get(key));
//设置题目
qu.setAnswerList(answerList);
//设置引用题库
// 设置题目所属的题库
qu.setRepoIds(im.getRepoList());
// 保存答案
// 保存题目
this.save(qu);
count++;
}
} catch (ServiceException e) {
e.printStackTrace();
// 异常处理,抛出导入失败的异常
throw new ServiceException(1, "导入出现问题,行:" + count + "" + e.getMessage());
}
return count;
}
/**
*
*
* @param importList
* @return
*/
// 处理题目的回答列表
private List<QuAnswerDTO> processAnswerList(List<QuExportDTO> importList) {
List<QuAnswerDTO> list = new ArrayList<>(16);
for (QuExportDTO item : importList) {
QuAnswerDTO a = new QuAnswerDTO();
// 设置选项是否正确
a.setIsRight("1".equals(item.getAIsRight()));
a.setContent(item.getAContent());
a.setAnalysis(item.getAAnalysis());
@ -226,58 +238,52 @@ public class QuServiceImpl extends ServiceImpl<QuMapper, Qu> implements QuServic
return list;
}
/**
*
*
* @param qu
* @param no
* @throws Exception
*/
// 校验题目信息
public void checkData(QuDetailDTO qu, String no) {
// 校验题目内容不能为空
if (StringUtils.isEmpty(qu.getContent())) {
throw new ServiceException(1, no + "题目内容不能为空!");
}
// 校验至少选择一个题库
if (CollectionUtils.isEmpty(qu.getRepoIds())) {
throw new ServiceException(1, no + "至少要选择一个题库!");
}
// 校验回答选项
List<QuAnswerDTO> answers = qu.getAnswerList();
if (CollectionUtils.isEmpty(answers)) {
throw new ServiceException(1, no + "客观题至少要包含一个备选答案!");
}
int trueCount = 0;
for (QuAnswerDTO a : answers) {
if (CollectionUtils.isEmpty(answers)) {
throw new ServiceException(1, no + "客观题至少要包含一个备选答案!");
// 校验选项是否定义了正确标志
if (a.getIsRight() == null) {
throw new ServiceException(1, no + "必须定义选项是否正确项!");
}
int trueCount = 0;
for (QuAnswerDTO a : answers) {
if (a.getIsRight() == null) {
throw new ServiceException(1, no + "必须定义选项是否正确项!");
}
if (StringUtils.isEmpty(a.getContent())) {
throw new ServiceException(1, no + "选项内容不为空!");
}
if (a.getIsRight()) {
trueCount += 1;
}
// 校验选项内容不能为空
if (StringUtils.isEmpty(a.getContent())) {
throw new ServiceException(1, no + "选项内容不为空!");
}
if (trueCount == 0) {
throw new ServiceException(1, no + "至少要包含一个正确项!");
// 统计正确选项的个数
if (a.getIsRight()) {
trueCount += 1;
}
}
// 校验至少包含一个正确选项
if (trueCount == 0) {
throw new ServiceException(1, no + "至少要包含一个正确项!");
}
//单选题
if (qu.getQuType().equals(QuType.RADIO) && trueCount > 1) {
throw new ServiceException(1, no + "单选题不能包含多个正确项!");
}
// 单选题不能包含多个正确选项
if (qu.getQuType().equals(QuType.RADIO) && trueCount > 1) {
throw new ServiceException(1, no + "单选题不能包含多个正确项!");
}
}
}

@ -1,31 +1,42 @@
// 定义包名表示该类属于com.yf.exam.modules.qu.utils包下
package com.yf.exam.modules.qu.utils;
// 导入项目中定义的上传配置类
import com.yf.exam.ability.upload.config.UploadConfig;
// 导入项目中定义的服务异常类
import com.yf.exam.core.exception.ServiceException;
// 导入Apache Commons Lang库中的StringUtils类用于字符串操作
import org.apache.commons.lang3.StringUtils;
// 导入Spring框架中的注解用于自动注入依赖
import org.springframework.beans.factory.annotation.Autowired;
// 导入Spring框架中的注解用于声明组件
import org.springframework.stereotype.Component;
/**
*
*/
@Component
public class ImageCheckUtils {
// 自动注入上传配置,用于获取图片上传的相关配置
@Autowired
private UploadConfig conf;
/**
*
* @param image
* @param throwMsg
*
* @param image
* @param throwMsg
*/
public void checkImage(String image, String throwMsg) {
// 如果图片地址为空或空白,则直接返回,不进行校验
if(StringUtils.isBlank(image)){
return;
}
// 校验图片地址
// 校验图片地址是否以配置的URL开头确保图片地址是合法的
if(!image.startsWith(conf.getUrl())){
// 如果图片地址不合法,则抛出服务异常
throw new ServiceException(throwMsg);
}
}
}
}
Loading…
Cancel
Save