匡文超分支提交到develop里 #16

Merged
pbensvpw6 merged 20 commits from kwc into kuangwenchao_branch 9 months ago

@ -1,17 +1,17 @@
package com.yf.exam; package com.yf.exam; // 定义包路径
import com.yf.exam.core.api.utils.JsonConverter; import com.yf.exam.core.api.utils.JsonConverter; // 导入JsonConverter工具类
import lombok.extern.log4j.Log4j2; import lombok.extern.log4j.Log4j2; // 导入log4j2日志工具
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication; // 导入Spring Boot的SpringApplication类
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; // 导入SpringBoot应用的启动注解
import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.ConfigurableApplicationContext; // 导入Spring上下文配置类
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment; // 导入Spring环境配置类
import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.HttpMessageConverter; // 导入HTTP消息转换器接口
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; // 导入Web MVC配置接口
import java.net.InetAddress; import java.net.InetAddress; // 导入InetAddress类用于获取IP地址
import java.net.UnknownHostException; import java.net.UnknownHostException; // 导入UnknownHostException异常类
import java.util.List; import java.util.List; // 导入List集合类
/** /**
* 线 * 线
@ -19,23 +19,28 @@ import java.util.List;
* @email 18365918@qq.com * @email 18365918@qq.com
* @date 2020-03-04 19:41 * @date 2020-03-04 19:41
*/ */
@Log4j2 @Log4j2 // 使用log4j2进行日志记录
@SpringBootApplication @SpringBootApplication // 声明一个Spring Boot应用程序
public class ExamApplication implements WebMvcConfigurer { public class ExamApplication implements WebMvcConfigurer { // 实现WebMvcConfigurer接口定制MVC配置
public static void main(String[] args) throws UnknownHostException { public static void main(String[] args) throws UnknownHostException { // 主方法,应用程序入口
// 启动Spring Boot应用获取应用上下文
ConfigurableApplicationContext application = SpringApplication.run(ExamApplication.class, args); ConfigurableApplicationContext application = SpringApplication.run(ExamApplication.class, args);
// 获取环境配置信息
Environment env = application.getEnvironment(); Environment env = application.getEnvironment();
// 获取本机IP地址
String ip = InetAddress.getLocalHost().getHostAddress(); String ip = InetAddress.getLocalHost().getHostAddress();
// 获取端口号
String port = env.getProperty("server.port"); String port = env.getProperty("server.port");
// 获取上下文路径
String path = env.getProperty("server.servlet.context-path"); String path = env.getProperty("server.servlet.context-path");
// 未配置默认空白 // 如果没有配置路径,则默认为空字符串
if(path == null){ if(path == null){
path = ""; path = "";
} }
// 输出启动信息到日志
log.info("\n----------------------------------------------------------\n\t" + log.info("\n----------------------------------------------------------\n\t" +
"云帆考试系统启动成功,访问路径如下:\n\t" + "云帆考试系统启动成功,访问路径如下:\n\t" +
"本地路径: \t\thttp://localhost:" + port + path + "/\n\t" + "本地路径: \t\thttp://localhost:" + port + path + "/\n\t" +
@ -45,9 +50,8 @@ public class ExamApplication implements WebMvcConfigurer {
} }
@Override @Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) { public void extendMessageConverters(List<HttpMessageConverter<?>> converters) { // 扩展Spring MVC的消息转换器
//保留原有converter,把新增fastConverter插入集合头,保证优先级 // 保留原有的消息转换器将新的fastConverter插入到集合的头部确保其优先级
converters.add(0, JsonConverter.fastConverter()); converters.add(0, JsonConverter.fastConverter());
} }
} }

@ -1,14 +1,15 @@
package com.yf.exam.modules; package com.yf.exam.modules; // 包名:表示该类属于 modules 包
/** /**
* *
* @author bool * 使
* @ bool
*/ */
public class Constant { public class Constant {
/** /**
* *
* Token
*/ */
public static final String TOKEN = "token"; public static final String TOKEN = "token"; // 定义一个常量 TOKEN表示会话中的 Token 名称
} }

@ -1,151 +1,144 @@
package com.yf.exam.modules.exam.controller; package com.yf.exam.modules.exam.controller; // 定义包名,控制器所在的包路径
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; // 导入MyBatis Plus的查询包装类
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage; // 导入MyBatis Plus的分页接口
import com.yf.exam.core.api.ApiRest; import com.yf.exam.core.api.ApiRest; // 导入自定义的API响应类
import com.yf.exam.core.api.controller.BaseController; import com.yf.exam.core.api.controller.BaseController; // 导入基控制器类
import com.yf.exam.core.api.dto.BaseIdReqDTO; import com.yf.exam.core.api.dto.BaseIdReqDTO; // 导入基础ID请求数据传输对象
import com.yf.exam.core.api.dto.BaseIdsReqDTO; import com.yf.exam.core.api.dto.BaseIdsReqDTO; // 导入基础IDs请求数据传输对象
import com.yf.exam.core.api.dto.BaseStateReqDTO; import com.yf.exam.core.api.dto.BaseStateReqDTO; // 导入基础状态请求数据传输对象
import com.yf.exam.core.api.dto.PagingReqDTO; import com.yf.exam.core.api.dto.PagingReqDTO; // 导入分页请求数据传输对象
import com.yf.exam.modules.exam.dto.ExamDTO; import com.yf.exam.modules.exam.dto.ExamDTO; // 导入考试DTO
import com.yf.exam.modules.exam.dto.request.ExamSaveReqDTO; import com.yf.exam.modules.exam.dto.request.ExamSaveReqDTO; // 导入考试保存请求DTO
import com.yf.exam.modules.exam.dto.response.ExamOnlineRespDTO; import com.yf.exam.modules.exam.dto.response.ExamOnlineRespDTO; // 导入在线考试响应DTO
import com.yf.exam.modules.exam.dto.response.ExamReviewRespDTO; import com.yf.exam.modules.exam.dto.response.ExamReviewRespDTO; // 导入考试审核响应DTO
import com.yf.exam.modules.exam.entity.Exam; import com.yf.exam.modules.exam.entity.Exam; // 导入考试实体类
import com.yf.exam.modules.exam.service.ExamService; import com.yf.exam.modules.exam.service.ExamService; // 导入考试服务接口
import io.swagger.annotations.Api; import io.swagger.annotations.Api; // 导入Swagger注解
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation; // 导入Swagger操作注解
import org.apache.shiro.authz.annotation.RequiresRoles; import org.apache.shiro.authz.annotation.RequiresRoles; // 导入Shiro权限注解
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired; // 导入Spring的自动注入注解
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody; // 导入Spring MVC的请求体注解
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping; // 导入Spring MVC的请求映射注解
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod; // 导入Spring MVC的请求方法注解
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController; // 导入Spring MVC的控制器注解
import java.util.Date; import java.util.Date; // 导入Java的日期类
/** /**
* <p> * <p>
* *
* </p> * </p>
* *
* @author * @author
* @since 2020-07-25 16:18 * @since 2020-07-25 16:18
*/ */
@Api(tags={"考试"}) @Api(tags={"考试"}) // Swagger注解定义API的标签
@RestController @RestController // Spring MVC注解声明这是一个REST控制器
@RequestMapping("/exam/api/exam/exam") @RequestMapping("/exam/api/exam/exam") // Spring MVC注解定义请求的基础路径
public class ExamController extends BaseController { public class ExamController extends BaseController { // 声明控制器类,继承自基控制器
@Autowired @Autowired
private ExamService baseService; private ExamService baseService; // 自动注入考试服务
/** /**
* *
* @param reqDTO * @param reqDTO
* @return * @return ApiRest
*/ */
@RequiresRoles("sa") @RequiresRoles("sa") // Shiro权限注解要求角色为"sa"(超级管理员)
@ApiOperation(value = "添加或修改") @ApiOperation(value = "添加或修改") // Swagger注解定义操作的描述
@RequestMapping(value = "/save", method = { RequestMethod.POST}) @RequestMapping(value = "/save", method = { RequestMethod.POST}) // Spring MVC注解定义请求的映射和方法
public ApiRest save(@RequestBody ExamSaveReqDTO reqDTO) { public ApiRest save(@RequestBody ExamSaveReqDTO reqDTO) { // 定义添加或修改考试的方法
//复制参数 // 复制参数并保存
baseService.save(reqDTO); baseService.save(reqDTO); // 调用服务层保存考试信息
return super.success(); return super.success(); // 返回成功响应
} }
/** /**
* *
* @param reqDTO * @param reqDTO ID
* @return * @return ApiRest
*/ */
@RequiresRoles("sa") @RequiresRoles("sa") // Shiro权限注解要求角色为"sa"(超级管理员)
@ApiOperation(value = "批量删除") @ApiOperation(value = "批量删除") // Swagger注解定义操作的描述
@RequestMapping(value = "/delete", method = { RequestMethod.POST}) @RequestMapping(value = "/delete", method = { RequestMethod.POST}) // Spring MVC注解定义请求的映射和方法
public ApiRest edit(@RequestBody BaseIdsReqDTO reqDTO) { public ApiRest edit(@RequestBody BaseIdsReqDTO reqDTO) { // 定义批量删除考试的方法
//根据ID删除 // 根据ID删除考试
baseService.removeByIds(reqDTO.getIds()); baseService.removeByIds(reqDTO.getIds()); // 调用服务层根据ID列表删除考试
return super.success(); return super.success(); // 返回成功响应
} }
/** /**
* *
* @param reqDTO * @param reqDTO ID
* @return * @return ApiRest<ExamSaveReqDTO>
*/ */
@ApiOperation(value = "查找详情") @ApiOperation(value = "查找详情") // Swagger注解定义操作的描述
@RequestMapping(value = "/detail", method = { RequestMethod.POST}) @RequestMapping(value = "/detail", method = { RequestMethod.POST}) // Spring MVC注解定义请求的映射和方法
public ApiRest<ExamSaveReqDTO> find(@RequestBody BaseIdReqDTO reqDTO) { public ApiRest<ExamSaveReqDTO> find(@RequestBody BaseIdReqDTO reqDTO) { // 定义查找考试详情的方法
ExamSaveReqDTO dto = baseService.findDetail(reqDTO.getId()); ExamSaveReqDTO dto = baseService.findDetail(reqDTO.getId()); // 调用服务层查找考试详情
return super.success(dto); return super.success(dto); // 返回成功响应和考试详情
} }
/** /**
* *
* @param reqDTO * @param reqDTO ID
* @return * @return ApiRest
*/ */
@RequiresRoles("sa") @RequiresRoles("sa") // Shiro权限注解要求角色为"sa"(超级管理员)
@ApiOperation(value = "查找详情") @ApiOperation(value = "更新考试状态") // Swagger注解定义操作的描述
@RequestMapping(value = "/state", method = { RequestMethod.POST}) @RequestMapping(value = "/state", method = { RequestMethod.POST}) // Spring MVC注解定义请求的映射和方法
public ApiRest state(@RequestBody BaseStateReqDTO reqDTO) { public ApiRest state(@RequestBody BaseStateReqDTO reqDTO) { // 定义更新考试状态的方法
// 创建查询条件
QueryWrapper<Exam> wrapper = new QueryWrapper<>(); QueryWrapper<Exam> wrapper = new QueryWrapper<>();
wrapper.lambda().in(Exam::getId, reqDTO.getIds()); wrapper.lambda().in(Exam::getId, reqDTO.getIds()); // 构造查询条件查询指定ID的考试
Exam exam = new Exam(); Exam exam = new Exam(); // 创建考试实体
exam.setState(reqDTO.getState()); exam.setState(reqDTO.getState()); // 设置新状态
exam.setUpdateTime(new Date()); exam.setUpdateTime(new Date()); // 设置更新时间为当前时间
baseService.update(exam, wrapper); baseService.update(exam, wrapper); // 调用服务层更新考试状态
return super.success(); return super.success(); // 返回成功响应
} }
/** /**
* *
* @param reqDTO * @param reqDTO
* @return * @return ApiRest<IPage<ExamOnlineRespDTO>>
*/ */
@ApiOperation(value = "考试视角") @ApiOperation(value = "考试视角") // Swagger注解定义操作的描述
@RequestMapping(value = "/online-paging", method = { RequestMethod.POST}) @RequestMapping(value = "/online-paging", method = { RequestMethod.POST}) // Spring MVC注解定义请求的映射和方法
public ApiRest<IPage<ExamOnlineRespDTO>> myPaging(@RequestBody PagingReqDTO<ExamDTO> reqDTO) { public ApiRest<IPage<ExamOnlineRespDTO>> myPaging(@RequestBody PagingReqDTO<ExamDTO> reqDTO) { // 定义分页查找考试的方法
// 分页查询并转换
//分页查询并转换 IPage<ExamOnlineRespDTO> page = baseService.onlinePaging(reqDTO); // 调用服务层进行分页查询
IPage<ExamOnlineRespDTO> page = baseService.onlinePaging(reqDTO); return super.success(page); // 返回成功响应和分页结果
return super.success(page);
} }
/** /**
* *
* @param reqDTO * @param reqDTO
* @return * @return ApiRest<IPage<ExamDTO>>
*/ */
@RequiresRoles("sa") @RequiresRoles("sa") // Shiro权限注解要求角色为"sa"(超级管理员)
@ApiOperation(value = "分页查找") @ApiOperation(value = "分页查找") // Swagger注解定义操作的描述
@RequestMapping(value = "/paging", method = { RequestMethod.POST}) @RequestMapping(value = "/paging", method = { RequestMethod.POST}) // Spring MVC注解定义请求的映射和方法
public ApiRest<IPage<ExamDTO>> paging(@RequestBody PagingReqDTO<ExamDTO> reqDTO) { public ApiRest<IPage<ExamDTO>> paging(@RequestBody PagingReqDTO<ExamDTO> reqDTO) { // 定义分页查找考试的方法
// 分页查询并转换
//分页查询并转换 IPage<ExamDTO> page = baseService.paging(reqDTO); // 调用服务层进行分页查询
IPage<ExamDTO> page = baseService.paging(reqDTO); return super.success(page); // 返回成功响应和分页结果
return super.success(page);
} }
/** /**
* *
* @param reqDTO * @param reqDTO
* @return * @return ApiRest<IPage<ExamReviewRespDTO>>
*/ */
@RequiresRoles("sa") @RequiresRoles("sa") // Shiro权限注解要求角色为"sa"(超级管理员)
@ApiOperation(value = "待阅试卷") @ApiOperation(value = "待阅试卷") // Swagger注解定义操作的描述
@RequestMapping(value = "/review-paging", method = { RequestMethod.POST}) @RequestMapping(value = "/review-paging", method = { RequestMethod.POST}) // Spring MVC注解定义请求的映射和方法
public ApiRest<IPage<ExamReviewRespDTO>> reviewPaging(@RequestBody PagingReqDTO<ExamDTO> reqDTO) { public ApiRest<IPage<ExamReviewRespDTO>> reviewPaging(@RequestBody PagingReqDTO<ExamDTO> reqDTO) { // 定义分页查找待阅试卷的方法
//分页查询并转换 // 分页查询并转换
IPage<ExamReviewRespDTO> page = baseService.reviewPaging(reqDTO); IPage<ExamReviewRespDTO> page = baseService.reviewPaging(reqDTO); // 调用服务层进行分页查询
return super.success(page); return super.success(page); // 返回成功响应和分页结果
} }
} }

@ -1,101 +1,93 @@
package com.yf.exam.modules.exam.dto; package com.yf.exam.modules.exam.dto; // 定义包名DTO类所在的包路径
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat; // 导入Jackson库的注解用于格式化日期
import com.yf.exam.modules.paper.enums.ExamState; import com.yf.exam.modules.paper.enums.ExamState; // 导入考试状态枚举
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel; // 导入Swagger注解用于描述模型
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty; // 导入Swagger注解用于描述模型属性
import lombok.Data; import lombok.Data; // 导入Lombok注解用于简化数据类的编写
import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.DateTimeFormat; // 导入Spring的日期格式化注解
import java.io.Serializable; import java.io.Serializable; // 导入Java的序列化接口用于确保对象可以被序列化
import java.util.Date; import java.util.Date; // 导入Java的日期类
/** /**
* <p> * <p>
* *
* </p> * </p>
* * 便
* @author *
* @since 2020-07-25 16:18 * @author
*/ * @since 2020-07-25 16:18
@Data */
@ApiModel(value="考试", description="考试") @Data // Lombok注解标记这个类为数据类自动生成getter和setter方法
public class ExamDTO implements Serializable { @ApiModel(value="考试", description="考试") // Swagger注解描述这个类的用途
public class ExamDTO implements Serializable { // 声明类实现Serializable接口以确保可以序列化
private static final long serialVersionUID = 1L; // 序列化ID用于版本控制确保类的版本唯一性
private static final long serialVersionUID = 1L; @ApiModelProperty(value = "ID", required=true) // Swagger注解描述字段的用途和是否必填
private String id; // 考试ID
@ApiModelProperty(value = "考试名称", required=true) // Swagger注解描述字段的用途和是否必填
private String title; // 考试名称
@ApiModelProperty(value = "ID", required=true) @ApiModelProperty(value = "考试描述", required=true) // Swagger注解描述字段的用途和是否必填
private String id; private String content; // 考试描述
@ApiModelProperty(value = "考试名称", required=true) @ApiModelProperty(value = "1公开2部门3定员", required=true) // Swagger注解描述字段的用途和是否必填
private String title; private Integer openType; // 开放类型1表示公开2表示部门3表示定员
@ApiModelProperty(value = "考试描述", required=true) @ApiModelProperty(value = "考试状态", required=true) // Swagger注解描述字段的用途和是否必填
private String content; private Integer state; // 考试状态
@ApiModelProperty(value = "1公开2部门3定员", required=true) @ApiModelProperty(value = "是否限时", required=true) // Swagger注解描述字段的用途和是否必填
private Integer openType; private Boolean timeLimit; // 是否限时
@ApiModelProperty(value = "考试状态", required=true) @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd") // Jackson注解格式化日期
private Integer state; @DateTimeFormat(pattern = "yyyy-MM-dd") // Spring注解格式化日期
@ApiModelProperty(value = "开始时间", required=true) // Swagger注解描述字段的用途和是否必填
private Date startTime; // 考试开始时间
@ApiModelProperty(value = "是否限时", required=true) @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd") // Jackson注解格式化日期
private Boolean timeLimit; @DateTimeFormat(pattern = "yyyy-MM-dd") // Spring注解格式化日期
@ApiModelProperty(value = "结束时间", required=true) // Swagger注解描述字段的用途和是否必填
private Date endTime; // 考试结束时间
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd") @ApiModelProperty(value = "创建时间", required=true) // Swagger注解描述字段的用途和是否必填
@DateTimeFormat(pattern = "yyyy-MM-dd") private Date createTime; // 创建时间
@ApiModelProperty(value = "开始时间", required=true)
private Date startTime;
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd") @ApiModelProperty(value = "更新时间", required=true) // Swagger注解描述字段的用途和是否必填
@DateTimeFormat(pattern = "yyyy-MM-dd") private Date updateTime; // 更新时间
@ApiModelProperty(value = "结束时间", required=true)
private Date endTime;
@ApiModelProperty(value = "创建时间", required=true)
private Date createTime;
@ApiModelProperty(value = "更新时间", required=true)
private Date updateTime;
@ApiModelProperty(value = "总分数", required=true)
private Integer totalScore;
@ApiModelProperty(value = "总时长(分钟)", required=true)
private Integer totalTime;
@ApiModelProperty(value = "及格分数", required=true)
private Integer qualifyScore;
@ApiModelProperty(value = "总分数", required=true) // Swagger注解描述字段的用途和是否必填
private Integer totalScore; // 总分数
@ApiModelProperty(value = "总时长(分钟)", required=true) // Swagger注解描述字段的用途和是否必填
private Integer totalTime; // 总时长(分钟)
@ApiModelProperty(value = "及格分数", required=true) // Swagger注解描述字段的用途和是否必填
private Integer qualifyScore; // 及格分数
/** /**
* *
* @return *
*
* @return
*/ */
public Integer getState(){ public Integer getState() {
if (this.timeLimit != null && this.timeLimit) {
if(this.timeLimit!=null && this.timeLimit){ if (System.currentTimeMillis() < startTime.getTime()) {
return ExamState.READY_START; // 如果当前时间小于开始时间,状态为准备开始
if(System.currentTimeMillis() < startTime.getTime() ){
return ExamState.READY_START;
} }
if (System.currentTimeMillis() > endTime.getTime()) {
if(System.currentTimeMillis() > endTime.getTime()){ return ExamState.OVERDUE; // 如果当前时间大于结束时间,状态为已过期
return ExamState.OVERDUE;
} }
if (System.currentTimeMillis() > startTime.getTime()
if(System.currentTimeMillis() > startTime.getTime()
&& System.currentTimeMillis() < endTime.getTime() && System.currentTimeMillis() < endTime.getTime()
&& !ExamState.DISABLED.equals(this.state)){ && !ExamState.DISABLED.equals(this.state)) {
return ExamState.ENABLE; return ExamState.ENABLE; // 如果当前时间在开始时间和结束时间之间,并且状态不是禁用,状态为正在进行
} }
} }
return this.state; // 如果不满足上述条件,返回当前状态
return this.state;
} }
} }

@ -1,33 +1,32 @@
package com.yf.exam.modules.exam.dto; package com.yf.exam.modules.exam.dto; // 定义包名DTO类所在的包路径
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel; // 导入Swagger注解用于描述模型
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty; // 导入Swagger注解用于描述模型属性
import lombok.Data; import lombok.Data; // 导入Lombok注解用于简化数据类的编写
import java.io.Serializable; import java.io.Serializable; // 导入Java的序列化接口用于确保对象可以被序列化
/** /**
* <p> * <p>
* *
* </p> * </p>
* * 便
* @author *
* @since 2020-09-03 17:24 * @author
*/ * @since 2020-09-03 17:24
@Data */
@ApiModel(value="考试部门", description="考试部门") @Data // Lombok注解标记这个类为数据类自动生成getter和setter方法
public class ExamDepartDTO implements Serializable { @ApiModel(value="考试部门", description="考试部门") // Swagger注解描述这个类的用途
public class ExamDepartDTO implements Serializable { // 声明类实现Serializable接口以确保可以序列化
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L; // 序列化ID用于版本控制确保类的版本唯一性
@ApiModelProperty(value = "ID", required=true) @ApiModelProperty(value = "ID", required=true) // Swagger注解描述字段的用途和是否必填
private String id; private String id; // 唯一标识符标识考试部门记录的ID
@ApiModelProperty(value = "考试ID", required=true) @ApiModelProperty(value = "考试ID", required=true) // Swagger注解描述字段的用途和是否必填
private String examId; private String examId; // 考试的唯一标识符,关联到具体的考试
@ApiModelProperty(value = "部门ID", required=true) @ApiModelProperty(value = "部门ID", required=true) // Swagger注解描述字段的用途和是否必填
private String departId; private String departId; // 部门的唯一标识符,关联到具体的部门
} }

@ -1,51 +1,50 @@
package com.yf.exam.modules.exam.dto; package com.yf.exam.modules.exam.dto; // 定义包名DTO类所在的包路径
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel; // 导入Swagger注解用于描述模型
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty; // 导入Swagger注解用于描述模型属性
import lombok.Data; import lombok.Data; // 导入Lombok注解用于简化数据类的编写
import java.io.Serializable; import java.io.Serializable; // 导入Java的序列化接口用于确保对象可以被序列化
/** /**
* <p> * <p>
* *
* </p> * </p>
* * 便
* @author *
* @since 2020-09-05 11:14 * @author
*/ * @since 2020-09-05 11:14
@Data */
@ApiModel(value="考试题库", description="考试题库") @Data // Lombok注解标记这个类为数据类自动生成getter和setter方法
public class ExamRepoDTO implements Serializable { @ApiModel(value="考试题库", description="考试题库") // Swagger注解描述这个类的用途
public class ExamRepoDTO implements Serializable { // 声明类实现Serializable接口以确保可以序列化
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L; // 序列化ID用于版本控制确保类的版本唯一性
@ApiModelProperty(value = "ID", required=true) // Swagger注解描述字段的用途和是否必填
private String id; // 题库ID唯一标识符
@ApiModelProperty(value = "ID", required=true) @ApiModelProperty(value = "考试ID", required=true) // Swagger注解描述字段的用途和是否必填
private String id; private String examId; // 关联的考试ID标识与哪个考试相关联
@ApiModelProperty(value = "考试ID", required=true) @ApiModelProperty(value = "题库ID", required=true) // Swagger注解描述字段的用途和是否必填
private String examId; private String repoId; // 题库ID标识具体的题库
@ApiModelProperty(value = "题库ID", required=true) @ApiModelProperty(value = "单选题数量", required=true) // Swagger注解描述字段的用途和是否必填
private String repoId; private Integer radioCount; // 单选题数量,表示题库中单选题的总数
@ApiModelProperty(value = "单选题", required=true) @ApiModelProperty(value = "单选题数", required=true) // Swagger注解描述字段的用途和是否必填
private Integer radioCount; private Integer radioScore; // 单选题分数,表示单选题的总分
@ApiModelProperty(value = "单选题分数", required=true) @ApiModelProperty(value = "多选题数量", required=true) // Swagger注解描述字段的用途和是否必填
private Integer radioScore; private Integer multiCount; // 多选题数量,表示题库中多选题的总数
@ApiModelProperty(value = "多选题", required=true) @ApiModelProperty(value = "多选题数", required=true) // Swagger注解描述字段的用途和是否必填
private Integer multiCount; private Integer multiScore; // 多选题分数,表示多选题的总分
@ApiModelProperty(value = "多选题分数", required=true) @ApiModelProperty(value = "判断题数量", required=true) // Swagger注解描述字段的用途和是否必填
private Integer multiScore; private Integer judgeCount; // 判断题数量,表示题库中判断题的总数
@ApiModelProperty(value = "判断题数量", required=true)
private Integer judgeCount;
@ApiModelProperty(value = "判断题分数", required=true)
private Integer judgeScore;
@ApiModelProperty(value = "判断题分数", required=true) // Swagger注解描述字段的用途和是否必填
private Integer judgeScore; // 判断题分数,表示判断题的总分
} }

@ -1,32 +1,30 @@
package com.yf.exam.modules.exam.dto.ext; package com.yf.exam.modules.exam.dto.ext; // 定义包名DTO扩展类所在的包路径
import com.yf.exam.modules.exam.dto.ExamRepoDTO; import com.yf.exam.modules.exam.dto.ExamRepoDTO; // 导入考试题库数据传输类
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel; // 导入Swagger注解用于描述模型
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty; // 导入Swagger注解用于描述模型属性
import lombok.Data; import lombok.Data; // 导入Lombok注解用于简化数据类的编写
/** /**
* <p> * <p>
* *
* </p> * </p>
* *
* @author * @author
* @since 2020-09-05 11:14 * @since 2020-09-05 11:14
*/ */
@Data @Data // Lombok注解标记这个类为数据类自动生成getter和setter方法
@ApiModel(value="考试题库扩展响应类", description="考试题库扩展响应类") @ApiModel(value="考试题库扩展响应类", description="考试题库扩展响应类") // Swagger注解描述这个类的用途
public class ExamRepoExtDTO extends ExamRepoDTO { public class ExamRepoExtDTO extends ExamRepoDTO { // 声明类继承自ExamRepoDTO
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L; // 序列化ID用于版本控制
@ApiModelProperty(value = "单选题总量", required=true) // Swagger注解描述字段的用途和是否必填
@ApiModelProperty(value = "单选题总量", required=true) private Integer totalRadio; // 单选题总量
private Integer totalRadio;
@ApiModelProperty(value = "多选题总量", required=true) // Swagger注解描述字段的用途和是否必填
@ApiModelProperty(value = "多选题总量", required=true) private Integer totalMulti; // 多选题总量
private Integer totalMulti;
@ApiModelProperty(value = "判断题总量", required=true) // Swagger注解描述字段的用途和是否必填
@ApiModelProperty(value = "判断题总量", required=true) private Integer totalJudge; // 判断题总量
private Integer totalJudge;
} }

@ -1,32 +1,30 @@
package com.yf.exam.modules.exam.dto.request; package com.yf.exam.modules.exam.dto.request; // 定义包名请求DTO类所在的包路径
import com.yf.exam.modules.exam.dto.ExamDTO; import com.yf.exam.modules.exam.dto.ExamDTO; // 导入基础考试DTO类
import com.yf.exam.modules.exam.dto.ext.ExamRepoExtDTO; import com.yf.exam.modules.exam.dto.ext.ExamRepoExtDTO; // 导入考试题库扩展DTO类
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel; // 导入Swagger注解用于描述模型
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty; // 导入Swagger注解用于描述模型属性
import lombok.Data; import lombok.Data; // 导入Lombok注解用于简化数据类的编写
import java.util.List; import java.util.List; // 导入Java的List接口用于定义列表类型的属性
/** /**
* <p> * <p>
* *
* </p> * </p>
* *
* @author * @author
* @since 2020-07-25 16:18 * @since 2020-07-25 16:18
*/ */
@Data @Data // Lombok注解标记这个类为数据类自动生成getter和setter方法
@ApiModel(value="考试保存请求类", description="考试保存请求类") @ApiModel(value="考试保存请求类", description="考试保存请求类") // Swagger注解描述这个类的用途
public class ExamSaveReqDTO extends ExamDTO { public class ExamSaveReqDTO extends ExamDTO { // 声明类继承自ExamDTO
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L; // 序列化ID用于版本控制
@ApiModelProperty(value = "题库列表", required=true) // Swagger注解描述字段的用途和是否必填
@ApiModelProperty(value = "题库列表", required=true) private List<ExamRepoExtDTO> repoList; // 题库列表,存储与考试相关的题库信息
private List<ExamRepoExtDTO> repoList;
@ApiModelProperty(value = "考试部门列表", required=true) // Swagger注解描述字段的用途和是否必填
@ApiModelProperty(value = "考试部门列表", required=true) private List<String> departIds; // 考试部门ID列表存储与考试相关的部门ID
private List<String> departIds;
} }

@ -1,22 +1,21 @@
package com.yf.exam.modules.exam.dto.response; package com.yf.exam.modules.exam.dto.response; // 定义包名响应DTO类所在的包路径
import com.yf.exam.modules.exam.dto.ExamDTO; import com.yf.exam.modules.exam.dto.ExamDTO; // 导入基础考试DTO类
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel; // 导入Swagger注解用于描述模型
import lombok.Data; import lombok.Data; // 导入Lombok注解用于简化数据类的编写
/** /**
* <p> * <p>
* * 线线
* </p> * </p>
* * 线
* @author *
* @since 2020-07-25 16:18 * @author
*/ * @since 2020-07-25 16:18
@Data */
@ApiModel(value="在线考试分页响应类", description="在线考试分页响应类") @Data // Lombok注解标记这个类为数据类自动生成getter和setter方法
public class ExamOnlineRespDTO extends ExamDTO { @ApiModel(value="在线考试分页响应类", description="在线考试分页响应类") // Swagger注解描述这个类的用途
public class ExamOnlineRespDTO extends ExamDTO { // 声明类继承自ExamDTO
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L; // 序列化ID用于版本控制确保类的版本唯一性
} }

@ -1,31 +1,28 @@
package com.yf.exam.modules.exam.dto.response; package com.yf.exam.modules.exam.dto.response; // 定义包名响应DTO类所在的包路径
import com.yf.exam.modules.exam.dto.ExamDTO; import com.yf.exam.modules.exam.dto.ExamDTO; // 导入基础考试DTO类
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel; // 导入Swagger注解用于描述模型
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty; // 导入Swagger注解用于描述模型属性
import lombok.Data; import lombok.Data; // 导入Lombok注解用于简化数据类的编写
/** /**
* <p> * <p>
* *
* </p> * </p>
* *
* @author *
* @since 2020-07-25 16:18 * @author
*/ * @since 2020-07-25 16:18
@Data */
@ApiModel(value="阅卷分页响应类", description="阅卷分页响应类") @Data // Lombok注解标记这个类为数据类自动生成getter和setter方法
public class ExamReviewRespDTO extends ExamDTO { @ApiModel(value="阅卷分页响应类", description="阅卷分页响应类") // Swagger注解描述这个类的用途
public class ExamReviewRespDTO extends ExamDTO { // 声明类继承自ExamDTO
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L; // 序列化ID用于版本控制确保类的版本唯一性
@ApiModelProperty(value = "考试人数", required=true) @ApiModelProperty(value = "考试人数", required=true) // Swagger注解描述字段的用途和是否必填
private Integer examUser; private Integer examUser; // 考试人数,表示参与考试的用户总数
@ApiModelProperty(value = "待阅试卷", required=true) @ApiModelProperty(value = "待阅试卷", required=true) // Swagger注解描述字段的用途和是否必填
private Integer unreadPaper; private Integer unreadPaper; // 待阅试卷数量,表示尚未被阅卷的试卷数量
} }

@ -1,100 +1,61 @@
package com.yf.exam.modules.exam.entity; package com.yf.exam.modules.exam.entity; // 定义包名,实体类所在的包路径
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType; // 导入MyBatis Plus的ID类型注解
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField; // 导入MyBatis Plus的表字段注解
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId; // 导入MyBatis Plus的表ID注解
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName; // 导入MyBatis Plus的表名注解
import com.baomidou.mybatisplus.extension.activerecord.Model; import com.baomidou.mybatisplus.extension.activerecord.Model; // 导入MyBatis Plus的模型类
import lombok.Data; import lombok.Data; // 导入Lombok注解用于简化数据类的编写
import java.util.Date; import java.util.Date; // 导入Java的日期类
/** /**
* <p> * <p>
* *
* </p> * </p>
* *
* @author *
* @since 2020-07-25 16:18 * @author
*/ * @since 2020-07-25 16:18
@Data */
@TableName("el_exam") @Data // Lombok注解标记这个类为数据类自动生成getter和setter方法
public class Exam extends Model<Exam> { @TableName("el_exam") // MyBatis Plus注解指定这个实体类对应的数据库表名
public class Exam extends Model<Exam> { // 声明类继承自MyBatis Plus的Model类用于数据库操作
private static final long serialVersionUID = 1L;
/**
* ID
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private String id;
/**
*
*/
private String title;
/**
*
*/
private String content;
/**
* 123
*/
@TableField("open_type")
private Integer openType;
/**
*
*/
private Integer state;
/**
*
*/
@TableField("time_limit")
private Boolean timeLimit;
/**
*
*/
@TableField("start_time")
private Date startTime;
/**
*
*/
@TableField("end_time")
private Date endTime;
/**
*
*/
@TableField("create_time")
private Date createTime;
/**
*
*/
@TableField("update_time")
private Date updateTime;
/**
*
*/
@TableField("total_score")
private Integer totalScore;
/**
*
*/
@TableField("total_time")
private Integer totalTime;
/**
*
*/
@TableField("qualify_score")
private Integer qualifyScore;
private static final long serialVersionUID = 1L; // 序列化ID用于版本控制确保类的唯一性
@TableId(value = "id", type = IdType.ASSIGN_ID) // MyBatis Plus注解指定这个字段为表的主键类型为自增ID
private String id; // 考试ID唯一标识符
private String title; // 考试名称,描述考试的标题
private String content; // 考试描述,详细描述考试的内容
@TableField("open_type") // MyBatis Plus注解指定这个字段在数据库表中的列名
private Integer openType; // 开放类型表示考试的开放范围1公开2部门3定员
private Integer state; // 考试状态,表示考试的当前状态(如:未开始、进行中、已结束)
@TableField("time_limit") // MyBatis Plus注解指定这个字段在数据库表中的列名
private Boolean timeLimit; // 是否限时,表示考试是否有时间限制
@TableField("start_time") // MyBatis Plus注解指定这个字段在数据库表中的列名
private Date startTime; // 开始时间,表示考试的开始时间
@TableField("end_time") // MyBatis Plus注解指定这个字段在数据库表中的列名
private Date endTime; // 结束时间,表示考试的结束时间
@TableField("create_time") // MyBatis Plus注解指定这个字段在数据库表中的列名
private Date createTime; // 创建时间,表示记录的创建时间
@TableField("update_time") // MyBatis Plus注解指定这个字段在数据库表中的列名
private Date updateTime; // 更新时间,表示记录的最后更新时间
@TableField("total_score") // MyBatis Plus注解指定这个字段在数据库表中的列名
private Integer totalScore; // 总分数,表示考试的总分
@TableField("total_time") // MyBatis Plus注解指定这个字段在数据库表中的列名
private Integer totalTime; // 总时长(分钟),表示考试的总时长
@TableField("qualify_score") // MyBatis Plus注解指定这个字段在数据库表中的列名
private Integer qualifyScore; // 及格分数,表示考试的及格分数线
} }

@ -1,42 +1,47 @@
package com.yf.exam.modules.exam.entity; package com.yf.exam.modules.exam.entity; // 定义包名,实体类所在的包路径
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType; // 导入MyBatis Plus的ID类型注解
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField; // 导入MyBatis Plus的表字段注解
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId; // 导入MyBatis Plus的表ID注解
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName; // 导入MyBatis Plus的表名注解
import com.baomidou.mybatisplus.extension.activerecord.Model; import com.baomidou.mybatisplus.extension.activerecord.Model; // 导入MyBatis Plus的模型类
import lombok.Data; import lombok.Data; // 导入Lombok注解用于简化数据类的编写
import java.io.Serializable; // 导入Java的序列化接口用于确保对象可以被序列化
/** /**
* <p> * <p>
* *
* </p> * </p>
* *
* @author *
* @since 2020-09-03 17:24 * @author
*/ * @since 2020-09-03 17:24
@Data */
@TableName("el_exam_depart") @Data // Lombok注解标记这个类为数据类自动生成getter和setter方法
public class ExamDepart extends Model<ExamDepart> { @TableName("el_exam_depart") // MyBatis Plus注解指定这个实体类对应的数据库表名
public class ExamDepart extends Model<ExamDepart> { // 声明类继承自MyBatis Plus的Model类用于数据库操作
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L; // 序列化ID用于版本控制确保类的唯一性
/** /**
* ID * ID
*/ *
@TableId(value = "id", type = IdType.ASSIGN_ID) */
@TableId(value = "id", type = IdType.ASSIGN_ID) // MyBatis Plus注解指定这个字段为表的主键类型为自增ID
private String id; private String id;
/** /**
* ID * ID
*/ * ID
@TableField("exam_id") */
@TableField("exam_id") // MyBatis Plus注解指定这个字段在数据库表中的列名
private String examId; private String examId;
/** /**
* ID * ID
*/ * ID
@TableField("depart_id") */
@TableField("depart_id") // MyBatis Plus注解指定这个字段在数据库表中的列名
private String departId; private String departId;
} }

@ -1,78 +1,87 @@
package com.yf.exam.modules.exam.entity; package com.yf.exam.modules.exam.entity; // 定义包名,实体类所在的包路径
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType; // 导入MyBatis Plus的ID类型注解
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField; // 导入MyBatis Plus的表字段注解
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId; // 导入MyBatis Plus的表ID注解
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName; // 导入MyBatis Plus的表名注解
import com.baomidou.mybatisplus.extension.activerecord.Model; import com.baomidou.mybatisplus.extension.activerecord.Model; // 导入MyBatis Plus的模型类
import lombok.Data; import lombok.Data; // 导入Lombok注解用于简化数据类的编写
/** /**
* <p> * <p>
* *
* </p> * </p>
* *
* @author *
* @since 2020-09-05 11:14 * @author
*/ * @since 2020-09-05 11:14
@Data */
@TableName("el_exam_repo") @Data // Lombok注解标记这个类为数据类自动生成getter和setter方法
public class ExamRepo extends Model<ExamRepo> { @TableName("el_exam_repo") // MyBatis Plus注解指定这个实体类对应的数据库表名
public class ExamRepo extends Model<ExamRepo> { // 声明类继承自MyBatis Plus的Model类用于数据库操作
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L; // 序列化ID用于版本控制确保类的唯一性
/** /**
* ID * ID
*/ *
@TableId(value = "id", type = IdType.ASSIGN_ID) */
@TableId(value = "id", type = IdType.ASSIGN_ID) // MyBatis Plus注解指定这个字段为表的主键类型为自增ID
private String id; private String id;
/** /**
* ID * ID
*/ * ID
@TableField("exam_id") */
@TableField("exam_id") // MyBatis Plus注解指定这个字段在数据库表中的列名
private String examId; private String examId;
/** /**
* ID * ID
*/ * ID
@TableField("repo_id") */
@TableField("repo_id") // MyBatis Plus注解指定这个字段在数据库表中的列名
private String repoId; private String repoId;
/** /**
* *
*/ *
@TableField("radio_count") */
@TableField("radio_count") // MyBatis Plus注解指定这个字段在数据库表中的列名
private Integer radioCount; private Integer radioCount;
/** /**
* *
*/ *
@TableField("radio_score") */
@TableField("radio_score") // MyBatis Plus注解指定这个字段在数据库表中的列名
private Integer radioScore; private Integer radioScore;
/** /**
* *
*/ *
@TableField("multi_count") */
@TableField("multi_count") // MyBatis Plus注解指定这个字段在数据库表中的列名
private Integer multiCount; private Integer multiCount;
/** /**
* *
*/ *
@TableField("multi_score") */
@TableField("multi_score") // MyBatis Plus注解指定这个字段在数据库表中的列名
private Integer multiScore; private Integer multiScore;
/** /**
* *
*/ *
@TableField("judge_count") */
@TableField("judge_count") // MyBatis Plus注解指定这个字段在数据库表中的列名
private Integer judgeCount; private Integer judgeCount;
/** /**
* *
*/ *
@TableField("judge_score") */
@TableField("judge_score") // MyBatis Plus注解指定这个字段在数据库表中的列名
private Integer judgeScore; private Integer judgeScore;
} }

@ -1,15 +1,17 @@
package com.yf.exam.modules.exam.mapper; package com.yf.exam.modules.exam.mapper; // 定义包名Mapper接口所在的包路径
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; // 导入MyBatis Plus的基础Mapper接口
import com.yf.exam.modules.exam.entity.ExamDepart; import com.yf.exam.modules.exam.entity.ExamDepart; // 导入考试部门实体类
/**
* <p>
* Mapper
* </p>
*
* @author
* @since 2020-09-03 17:24
*/
public interface ExamDepartMapper extends BaseMapper<ExamDepart> {
/**
* <p>
* Mapper
* </p>
* MapperMyBatis PlusBaseMapper
*
* @author
* @since 2020-09-03 17:24
*/
public interface ExamDepartMapper extends BaseMapper<ExamDepart> { // 声明接口继承自BaseMapper并指定操作的实体类为ExamDepart
// 继承BaseMapper提供基本的CRUD操作创建、读取、更新、删除
} }

@ -1,45 +1,52 @@
package com.yf.exam.modules.exam.mapper; package com.yf.exam.modules.exam.mapper; // 定义包名Mapper接口所在的包路径
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; // 导入MyBatis Plus的基础Mapper接口
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage; // 导入MyBatis Plus的分页结果接口
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; // 导入MyBatis Plus的分页对象
import com.yf.exam.modules.exam.dto.ExamDTO; import com.yf.exam.modules.exam.dto.ExamDTO; // 导入考试DTO
import com.yf.exam.modules.exam.dto.response.ExamReviewRespDTO; import com.yf.exam.modules.exam.dto.response.ExamReviewRespDTO; // 导入阅卷分页响应DTO
import com.yf.exam.modules.exam.dto.response.ExamOnlineRespDTO; import com.yf.exam.modules.exam.dto.response.ExamOnlineRespDTO; // 导入在线考试分页响应DTO
import com.yf.exam.modules.exam.entity.Exam; import com.yf.exam.modules.exam.entity.Exam; // 导入考试实体类
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param; // 导入MyBatis的参数注解
/** /**
* <p> * <p>
* Mapper * Mapper
* </p> * </p>
* * MapperMyBatis PlusBaseMapper
* @author *
* @since 2020-07-25 16:18 * @author
*/ * @since 2020-07-25 16:18
public interface ExamMapper extends BaseMapper<Exam> { */
public interface ExamMapper extends BaseMapper<Exam> { // 声明接口继承自BaseMapper并指定操作的实体类为Exam
/** /**
* *
* @param page *
* @param query *
* @return * @param page
* @param query
* @return IPage<ExamDTO> DTO
*/ */
IPage<ExamDTO> paging(Page page, @Param("query") ExamDTO query); IPage<ExamDTO> paging(Page page, @Param("query") ExamDTO query);
/** /**
* *
* @param page *
* @param query *
* @return * @param page
* @param query
* @return IPage<ExamReviewRespDTO> DTO
*/ */
IPage<ExamReviewRespDTO> reviewPaging(Page page, @Param("query") ExamDTO query); IPage<ExamReviewRespDTO> reviewPaging(Page page, @Param("query") ExamDTO query);
/** /**
* 线- * 线-
* @param page * 线
* @param query *
* @return * @param page
* @param query
* @return IPage<ExamOnlineRespDTO> 线DTO
*/ */
IPage<ExamOnlineRespDTO> online(Page page, @Param("query") ExamDTO query); IPage<ExamOnlineRespDTO> online(Page page, @Param("query") ExamDTO query);
} }

@ -1,26 +1,29 @@
package com.yf.exam.modules.exam.mapper; package com.yf.exam.modules.exam.mapper; // 定义包名Mapper接口所在的包路径
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; // 导入MyBatis Plus的基础Mapper接口
import com.yf.exam.modules.exam.dto.ext.ExamRepoExtDTO; import com.yf.exam.modules.exam.dto.ext.ExamRepoExtDTO; // 导入考试题库扩展DTO
import com.yf.exam.modules.exam.entity.ExamRepo; import com.yf.exam.modules.exam.entity.ExamRepo; // 导入考试题库实体类
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param; // 导入MyBatis的参数注解
import java.util.List; import java.util.List; // 导入Java的List接口
/** /**
* <p> * <p>
* Mapper * Mapper
* </p> * </p>
* * MapperMyBatis PlusBaseMapper
* @author *
* @since 2020-09-05 11:14 * @author
*/ * @since 2020-09-05 11:14
public interface ExamRepoMapper extends BaseMapper<ExamRepo> { */
public interface ExamRepoMapper extends BaseMapper<ExamRepo> { // 声明接口继承自BaseMapper并指定操作的实体类为ExamRepo
/** /**
* *
* @param examId * IDDTO
* @return *
* @param examId ID
* @return List<ExamRepoExtDTO>
*/ */
List<ExamRepoExtDTO> listByExam(@Param("examId") String examId); List<ExamRepoExtDTO> listByExam(@Param("examId") String examId); // 使用MyBatis的@Param注解来指定方法参数的名称
} }

@ -1,32 +1,36 @@
package com.yf.exam.modules.exam.service; package com.yf.exam.modules.exam.service; // 定义包名,服务接口所在的包路径
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService; // 导入MyBatis Plus的服务接口
import com.yf.exam.modules.exam.entity.ExamDepart; import com.yf.exam.modules.exam.entity.ExamDepart; // 导入考试部门实体类
import java.util.List; import java.util.List; // 导入Java的List接口
/** /**
* <p> * <p>
* *
* </p> * </p>
* * MyBatis PlusIService
* @author *
* @since 2020-09-03 17:24 * @author
*/ * @since 2020-09-03 17:24
public interface ExamDepartService extends IService<ExamDepart> { */
public interface ExamDepartService extends IService<ExamDepart> { // 声明接口继承自IService并指定操作的实体类为ExamDepart
/** /**
* *
* @param examId * IDID
* @param departs *
* @param examId ID
* @param departs IDID
*/ */
void saveAll(String examId, List<String> departs); void saveAll(String examId, List<String> departs);
/** /**
* *
* @param examId * IDID
* @return *
* @param examId ID
* @return List<String> IDID
*/ */
List<String> listByExam(String examId); List<String> listByExam(String examId);
} }

@ -1,40 +1,45 @@
package com.yf.exam.modules.exam.service; package com.yf.exam.modules.exam.service; // 定义包名,服务接口所在的包路径
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService; // 导入MyBatis Plus的服务接口
import com.yf.exam.modules.exam.dto.ext.ExamRepoExtDTO; import com.yf.exam.modules.exam.dto.ext.ExamRepoExtDTO; // 导入考试题库扩展DTO
import com.yf.exam.modules.exam.entity.ExamRepo; import com.yf.exam.modules.exam.entity.ExamRepo; // 导入考试题库实体类
import java.util.List; import java.util.List; // 导入Java的List接口
/** /**
* <p> * <p>
* *
* </p> * </p>
* * MyBatis PlusIService
* @author *
* @since 2020-09-05 11:14 * @author
*/ * @since 2020-09-05 11:14
public interface ExamRepoService extends IService<ExamRepo> { */
public interface ExamRepoService extends IService<ExamRepo> { // 声明接口继承自IService并指定操作的实体类为ExamRepo
/** /**
* *
* @param examId * ID
* @param list *
* @param examId ID
* @param list
*/ */
void saveAll(String examId, List<ExamRepoExtDTO> list); void saveAll(String examId, List<ExamRepoExtDTO> list);
/** /**
* *
* @param examId * ID
* @return *
* @param examId ID
* @return List<ExamRepoExtDTO>
*/ */
List<ExamRepoExtDTO> listByExam(String examId); List<ExamRepoExtDTO> listByExam(String examId);
/** /**
* *
* @param examId * ID
*
* @param examId ID
*/ */
void clear(String examId); void clear(String examId);
} }

@ -1,64 +1,75 @@
package com.yf.exam.modules.exam.service; package com.yf.exam.modules.exam.service; // 定义包名,服务接口所在的包路径
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage; // 导入MyBatis Plus的分页结果接口
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService; // 导入MyBatis Plus的服务接口
import com.yf.exam.core.api.dto.PagingReqDTO; import com.yf.exam.core.api.dto.PagingReqDTO; // 导入分页请求DTO
import com.yf.exam.modules.exam.dto.ExamDTO; import com.yf.exam.modules.exam.dto.ExamDTO; // 导入考试DTO
import com.yf.exam.modules.exam.dto.request.ExamSaveReqDTO; import com.yf.exam.modules.exam.dto.request.ExamSaveReqDTO; // 导入考试保存请求DTO
import com.yf.exam.modules.exam.dto.response.ExamOnlineRespDTO; import com.yf.exam.modules.exam.dto.response.ExamOnlineRespDTO; // 导入在线考试响应DTO
import com.yf.exam.modules.exam.dto.response.ExamReviewRespDTO; import com.yf.exam.modules.exam.dto.response.ExamReviewRespDTO; // 导入阅卷响应DTO
import com.yf.exam.modules.exam.entity.Exam; import com.yf.exam.modules.exam.entity.Exam; // 导入考试实体类
/** /**
* <p> * <p>
* *
* </p> * </p>
* * MyBatis PlusIService
* @author *
* @since 2020-07-25 16:18 * @author
*/ * @since 2020-07-25 16:18
public interface ExamService extends IService<Exam> { */
public interface ExamService extends IService<Exam> { // 声明接口继承自IService并指定操作的实体类为Exam
/** /**
* *
* @param reqDTO *
*
* @param reqDTO
*/ */
void save(ExamSaveReqDTO reqDTO); void save(ExamSaveReqDTO reqDTO);
/** /**
* *
* @param id * ID
* @return *
* @param id ID
* @return ExamSaveReqDTO
*/ */
ExamSaveReqDTO findDetail(String id); ExamSaveReqDTO findDetail(String id);
/** /**
* -- * --
* @param id * ID
* @return *
* @param id ID
* @return ExamDTO
*/ */
ExamDTO findById(String id); ExamDTO findById(String id);
/** /**
* *
* @param reqDTO *
* @return *
*/ * @param reqDTO
* @return IPage<ExamDTO>
*/
IPage<ExamDTO> paging(PagingReqDTO<ExamDTO> reqDTO); IPage<ExamDTO> paging(PagingReqDTO<ExamDTO> reqDTO);
/** /**
* 线- * 线-
* @param reqDTO * 线
* @return *
* @param reqDTO
* @return IPage<ExamOnlineRespDTO> 线线
*/ */
IPage<ExamOnlineRespDTO> onlinePaging(PagingReqDTO<ExamDTO> reqDTO); IPage<ExamOnlineRespDTO> onlinePaging(PagingReqDTO<ExamDTO> reqDTO);
/** /**
* *
* @param reqDTO *
* @return *
* @param reqDTO
* @return IPage<ExamReviewRespDTO>
*/ */
IPage<ExamReviewRespDTO> reviewPaging(PagingReqDTO<ExamDTO> reqDTO); IPage<ExamReviewRespDTO> reviewPaging(PagingReqDTO<ExamDTO> reqDTO);
} }

@ -1,66 +1,64 @@
package com.yf.exam.modules.exam.service.impl; package com.yf.exam.modules.exam.service.impl; // 定义包名,服务实现类所在的包路径
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; // 导入MyBatis Plus的查询包装类
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; // 导入MyBatis Plus的服务实现类
import com.yf.exam.core.exception.ServiceException; import com.yf.exam.core.exception.ServiceException; // 导入自定义的服务异常类
import com.yf.exam.modules.exam.entity.ExamDepart; import com.yf.exam.modules.exam.entity.ExamDepart; // 导入考试部门实体类
import com.yf.exam.modules.exam.mapper.ExamDepartMapper; import com.yf.exam.modules.exam.mapper.ExamDepartMapper; // 导入考试部门Mapper接口
import com.yf.exam.modules.exam.service.ExamDepartService; import com.yf.exam.modules.exam.service.ExamDepartService; // 导入考试部门服务接口
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service; // 导入Spring的服务注解
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils; // 导入Spring的集合工具类
import java.util.ArrayList; import java.util.ArrayList; // 导入Java的ArrayList类
import java.util.List; import java.util.List; // 导入Java的List接口
/** /**
* <p> * <p>
* *
* </p> * </p>
* * ExamDepartService
* @author *
* @since 2020-09-03 17:24 * @author
*/ * @since 2020-09-03 17:24
@Service */
public class ExamDepartServiceImpl extends ServiceImpl<ExamDepartMapper, ExamDepart> implements ExamDepartService { @Service // Spring注解声明这是一个服务组件
public class ExamDepartServiceImpl extends ServiceImpl<ExamDepartMapper, ExamDepart> implements ExamDepartService { // 声明类继承自ServiceImpl并实现ExamDepartService接口
@Override @Override
public void saveAll(String examId, List<String> departs) { public void saveAll(String examId, List<String> departs) {
// 先删除已有的部门
// 先删除
QueryWrapper<ExamDepart> wrapper = new QueryWrapper<>(); QueryWrapper<ExamDepart> wrapper = new QueryWrapper<>();
wrapper.lambda().eq(ExamDepart::getExamId, examId); wrapper.lambda().eq(ExamDepart::getExamId, examId); // 构造查询条件查询指定考试ID的部门
this.remove(wrapper); this.remove(wrapper); // 根据条件删除部门
// 再增加 // 再增加新的部门
if(CollectionUtils.isEmpty(departs)){ if (CollectionUtils.isEmpty(departs)) { // 检查部门列表是否为空
throw new ServiceException(1, "请至少选择选择一个部门!!"); throw new ServiceException(1, "请至少选择选择一个部门!!"); // 如果为空,抛出异常
} }
List<ExamDepart> list = new ArrayList<>(); List<ExamDepart> list = new ArrayList<>(); // 创建考试部门列表
for(String id: departs){ for (String id : departs) {
ExamDepart depart = new ExamDepart(); ExamDepart depart = new ExamDepart(); // 创建考试部门对象
depart.setDepartId(id); depart.setDepartId(id); // 设置部门ID
depart.setExamId(examId); depart.setExamId(examId); // 设置考试ID
list.add(depart); list.add(depart); // 添加到列表
} }
this.saveBatch(list); this.saveBatch(list); // 批量保存部门
} }
@Override @Override
public List<String> listByExam(String examId) { public List<String> listByExam(String examId) {
// 先删除 // 查找考试对应的部门
QueryWrapper<ExamDepart> wrapper = new QueryWrapper<>(); QueryWrapper<ExamDepart> wrapper = new QueryWrapper<>();
wrapper.lambda().eq(ExamDepart::getExamId, examId); wrapper.lambda().eq(ExamDepart::getExamId, examId); // 构造查询条件查询指定考试ID的部门
List<ExamDepart> list = this.list(wrapper); List<ExamDepart> list = this.list(wrapper); // 根据条件查询部门列表
List<String> ids = new ArrayList<>(); List<String> ids = new ArrayList<>(); // 创建部门ID列表
if(!CollectionUtils.isEmpty(list)){ if (!CollectionUtils.isEmpty(list)) { // 检查部门列表是否为空
for(ExamDepart item: list){ for (ExamDepart item : list) {
ids.add(item.getDepartId()); ids.add(item.getDepartId()); // 添加部门ID到列表
} }
} }
return ids; // 返回部门ID列表
return ids;
} }
} }

@ -1,67 +1,63 @@
package com.yf.exam.modules.exam.service.impl; package com.yf.exam.modules.exam.service.impl; // 定义包名,服务实现类所在的包路径
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; // 导入MyBatis Plus的查询包装类
import com.baomidou.mybatisplus.core.toolkit.IdWorker; import com.baomidou.mybatisplus.core.toolkit.IdWorker; // 导入MyBatis Plus的ID生成工具类
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; // 导入MyBatis Plus的服务实现类
import com.yf.exam.core.exception.ServiceException; import com.yf.exam.core.exception.ServiceException; // 导入自定义的服务异常类
import com.yf.exam.core.utils.BeanMapper; import com.yf.exam.core.utils.BeanMapper; // 导入自定义的Bean映射工具类
import com.yf.exam.modules.exam.dto.ext.ExamRepoExtDTO; import com.yf.exam.modules.exam.dto.ext.ExamRepoExtDTO; // 导入考试题库扩展DTO
import com.yf.exam.modules.exam.entity.ExamRepo; import com.yf.exam.modules.exam.entity.ExamRepo; // 导入考试题库实体类
import com.yf.exam.modules.exam.mapper.ExamRepoMapper; import com.yf.exam.modules.exam.mapper.ExamRepoMapper; // 导入考试题库Mapper接口
import com.yf.exam.modules.exam.service.ExamRepoService; import com.yf.exam.modules.exam.service.ExamRepoService; // 导入考试题库服务接口
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service; // 导入Spring的服务注解
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional; // 导入Spring的事务注解
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils; // 导入Spring的集合工具类
import java.util.List; import java.util.List; // 导入Java的List接口
/** /**
* <p> * <p>
* *
* </p> * </p>
* * ExamRepoService
* @author *
* @since 2020-09-05 11:14 * @author
*/ * @since 2020-09-05 11:14
@Service */
public class ExamRepoServiceImpl extends ServiceImpl<ExamRepoMapper, ExamRepo> implements ExamRepoService { @Service // Spring注解声明这是一个服务组件
public class ExamRepoServiceImpl extends ServiceImpl<ExamRepoMapper, ExamRepo> implements ExamRepoService { // 声明类继承自ServiceImpl并实现ExamRepoService接口
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class) // Spring事务注解声明事务边界和回滚条件
@Override @Override
public void saveAll(String examId, List<ExamRepoExtDTO> list) { public void saveAll(String examId, List<ExamRepoExtDTO> list) {
// 先删除已有的题库
// 先删除
QueryWrapper<ExamRepo> wrapper = new QueryWrapper<>(); QueryWrapper<ExamRepo> wrapper = new QueryWrapper<>();
wrapper.lambda().eq(ExamRepo::getExamId, examId); wrapper.lambda().eq(ExamRepo::getExamId, examId); // 构造查询条件查询指定考试ID的题库
this.remove(wrapper); this.remove(wrapper); // 根据条件删除题库
// 再增加 // 再增加新的题库
if(CollectionUtils.isEmpty(list)){ if (CollectionUtils.isEmpty(list)) { // 检查题库列表是否为空
throw new ServiceException(1, "必须选择题库!"); throw new ServiceException(1, "必须选择题库!"); // 如果为空,抛出异常
} }
List<ExamRepo> repos = BeanMapper.mapList(list, ExamRepo.class); List<ExamRepo> repos = BeanMapper.mapList(list, ExamRepo.class); // 使用BeanMapper将DTO列表转换为实体类列表
for(ExamRepo item: repos){ for (ExamRepo item : repos) {
item.setExamId(examId); item.setExamId(examId); // 设置考试ID
item.setId(IdWorker.getIdStr()); item.setId(IdWorker.getIdStr()); // 使用IdWorker生成ID
} }
this.saveBatch(repos); this.saveBatch(repos); // 批量保存题库
} }
@Override @Override
public List<ExamRepoExtDTO> listByExam(String examId) { public List<ExamRepoExtDTO> listByExam(String examId) {
return baseMapper.listByExam(examId); return baseMapper.listByExam(examId); // 调用Mapper接口的方法查找考试题库列表
} }
@Override @Override
public void clear(String examId) { public void clear(String examId) {
// 先删除已有的题库
// 先删除
QueryWrapper<ExamRepo> wrapper = new QueryWrapper<>(); QueryWrapper<ExamRepo> wrapper = new QueryWrapper<>();
wrapper.lambda().eq(ExamRepo::getExamId, examId); wrapper.lambda().eq(ExamRepo::getExamId, examId); // 构造查询条件查询指定考试ID的题库
this.remove(wrapper); this.remove(wrapper); // 根据条件删除题库
} }
} }

@ -1,194 +1,173 @@
package com.yf.exam.modules.exam.service.impl; package com.yf.exam.modules.exam.service.impl; // 定义包名,服务实现类所在的包路径
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage; // 导入MyBatis Plus的分页结果接口
import com.baomidou.mybatisplus.core.toolkit.IdWorker; import com.baomidou.mybatisplus.core.toolkit.IdWorker; // 导入MyBatis Plus的ID生成工具类
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; // 导入MyBatis Plus的分页对象
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; // 导入MyBatis Plus的服务实现类
import com.yf.exam.core.api.dto.PagingReqDTO; import com.yf.exam.core.api.dto.PagingReqDTO; // 导入分页请求DTO
import com.yf.exam.core.enums.OpenType; import com.yf.exam.core.enums.OpenType; // 导入开放类型枚举
import com.yf.exam.core.exception.ServiceException; import com.yf.exam.core.exception.ServiceException; // 导入自定义的服务异常类
import com.yf.exam.core.utils.BeanMapper; import com.yf.exam.core.utils.BeanMapper; // 导入自定义的Bean映射工具类
import com.yf.exam.modules.exam.dto.ExamDTO; import com.yf.exam.modules.exam.dto.ExamDTO; // 导入考试DTO
import com.yf.exam.modules.exam.dto.ExamRepoDTO; import com.yf.exam.modules.exam.dto.ExamRepoDTO; // 导入考试题库DTO
import com.yf.exam.modules.exam.dto.ext.ExamRepoExtDTO; import com.yf.exam.modules.exam.dto.ext.ExamRepoExtDTO; // 导入考试题库扩展DTO
import com.yf.exam.modules.exam.dto.request.ExamSaveReqDTO; import com.yf.exam.modules.exam.dto.request.ExamSaveReqDTO; // 导入考试保存请求DTO
import com.yf.exam.modules.exam.dto.response.ExamOnlineRespDTO; import com.yf.exam.modules.exam.dto.response.ExamOnlineRespDTO; // 导入在线考试响应DTO
import com.yf.exam.modules.exam.dto.response.ExamReviewRespDTO; import com.yf.exam.modules.exam.dto.response.ExamReviewRespDTO; // 导入阅卷响应DTO
import com.yf.exam.modules.exam.entity.Exam; import com.yf.exam.modules.exam.entity.Exam; // 导入考试实体类
import com.yf.exam.modules.exam.mapper.ExamMapper; import com.yf.exam.modules.exam.mapper.ExamMapper; // 导入考试Mapper接口
import com.yf.exam.modules.exam.service.ExamDepartService; import com.yf.exam.modules.exam.service.ExamDepartService; // 导入考试部门服务接口
import com.yf.exam.modules.exam.service.ExamRepoService; import com.yf.exam.modules.exam.service.ExamRepoService; // 导入考试题库服务接口
import com.yf.exam.modules.exam.service.ExamService; import com.yf.exam.modules.exam.service.ExamService; // 导入考试服务接口
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils; // 导入Apache Commons Lang的字符串工具类
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired; // 导入Spring的自动注入注解
import org.springframework.dao.DuplicateKeyException; import org.springframework.dao.DuplicateKeyException; // 导入Spring的重复键异常类
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service; // 导入Spring的服务注解
import java.util.List; import java.util.List; // 导入Java的List接口
/** /**
* <p> * <p>
* *
* </p> * </p>
* * ExamService
* @author *
* @since 2020-07-25 16:18 * @author
*/ * @since 2020-07-25 16:18
@Service */
public class ExamServiceImpl extends ServiceImpl<ExamMapper, Exam> implements ExamService { @Service // Spring注解声明这是一个服务组件
public class ExamServiceImpl extends ServiceImpl<ExamMapper, Exam> implements ExamService { // 声明类继承自ServiceImpl并实现ExamService接口
@Autowired @Autowired
private ExamRepoService examRepoService; private ExamRepoService examRepoService; // 自动注入考试题库服务
@Autowired @Autowired
private ExamDepartService examDepartService; private ExamDepartService examDepartService; // 自动注入考试部门服务
@Override @Override
public void save(ExamSaveReqDTO reqDTO) { public void save(ExamSaveReqDTO reqDTO) {
// ID // ID
String id = reqDTO.getId(); String id = reqDTO.getId();
if(StringUtils.isBlank(id)){ if(StringUtils.isBlank(id)){ // 如果ID为空则生成新的ID
id = IdWorker.getIdStr(); id = IdWorker.getIdStr(); // 使用IdWorker生成ID
} }
//复制参数 // 复制参数
Exam entity = new Exam(); Exam entity = new Exam(); // 创建考试实体
// 计算分值 // 计算分值
this.calcScore(reqDTO); this.calcScore(reqDTO); // 调用方法计算分值
// 复制基本数据 // 复制基本数据
BeanMapper.copy(reqDTO, entity); BeanMapper.copy(reqDTO, entity); // 使用BeanMapper复制属性
entity.setId(id); entity.setId(id); // 设置ID
// 修复状态 // 修复状态
if (reqDTO.getTimeLimit()!=null if (reqDTO.getTimeLimit() != null
&& !reqDTO.getTimeLimit() && !reqDTO.getTimeLimit()
&& reqDTO.getState()!=null && reqDTO.getState() != null
&& reqDTO.getState() == 2) { && reqDTO.getState() == 2) {
entity.setState(0); entity.setState(0); // 如果不限时且状态为2则状态设置为0
} else { } else {
entity.setState(reqDTO.getState()); entity.setState(reqDTO.getState()); // 否则直接设置状态
} }
// 题库组卷 // 题库组卷
try { try {
examRepoService.saveAll(id, reqDTO.getRepoList()); examRepoService.saveAll(id, reqDTO.getRepoList()); // 调用考试题库服务保存题库
}catch (DuplicateKeyException e){ }catch (DuplicateKeyException e){
throw new ServiceException(1, "不能选择重复的题库!"); throw new ServiceException(1, "不能选择重复的题库!"); // 如果出现重复键异常,则抛出服务异常
} }
// 开放的部门 // 开放的部门
if(OpenType.DEPT_OPEN.equals(reqDTO.getOpenType())){ if(OpenType.DEPT_OPEN.equals(reqDTO.getOpenType())){ // 如果开放类型为部门开放
examDepartService.saveAll(id, reqDTO.getDepartIds()); examDepartService.saveAll(id, reqDTO.getDepartIds()); // 调用考试部门服务保存部门
} }
this.saveOrUpdate(entity); this.saveOrUpdate(entity); // 保存或更新考试实体
} }
@Override @Override
public ExamSaveReqDTO findDetail(String id) { public ExamSaveReqDTO findDetail(String id) {
ExamSaveReqDTO respDTO = new ExamSaveReqDTO(); ExamSaveReqDTO respDTO = new ExamSaveReqDTO(); // 创建响应DTO
Exam exam = this.getById(id); Exam exam = this.getById(id); // 根据ID查询考试实体
BeanMapper.copy(exam, respDTO); BeanMapper.copy(exam, respDTO); // 使用BeanMapper复制属性
// 考试部门 // 考试部门
List<String> departIds = examDepartService.listByExam(id); List<String> departIds = examDepartService.listByExam(id); // 调用考试部门服务查询部门ID列表
respDTO.setDepartIds(departIds); respDTO.setDepartIds(departIds); // 设置部门ID列表
// 题库 // 题库
List<ExamRepoExtDTO> repos = examRepoService.listByExam(id); List<ExamRepoExtDTO> repos = examRepoService.listByExam(id); // 调用考试题库服务查询题库列表
respDTO.setRepoList(repos); respDTO.setRepoList(repos); // 设置题库列表
return respDTO; return respDTO; // 返回响应DTO
} }
@Override @Override
public ExamDTO findById(String id) { public ExamDTO findById(String id) {
ExamDTO respDTO = new ExamDTO(); ExamDTO respDTO = new ExamDTO(); // 创建响应DTO
Exam exam = this.getById(id); Exam exam = this.getById(id); // 根据ID查询考试实体
BeanMapper.copy(exam, respDTO); BeanMapper.copy(exam, respDTO); // 使用BeanMapper复制属性
return respDTO; return respDTO; // 返回响应DTO
} }
@Override @Override
public IPage<ExamDTO> paging(PagingReqDTO<ExamDTO> reqDTO) { public IPage<ExamDTO> paging(PagingReqDTO<ExamDTO> reqDTO) {
// 创建分页对象
Page page = new Page(reqDTO.getCurrent(), reqDTO.getSize()); // 使用分页请求DTO创建分页对象
//创建分页对象 // 转换结果
Page page = new Page(reqDTO.getCurrent(), reqDTO.getSize()); IPage<ExamDTO> pageData = baseMapper.paging(page, reqDTO.getParams()); // 调用Mapper接口的分页方法
return pageData; // 返回分页结果
//转换结果 }
IPage<ExamDTO> pageData = baseMapper.paging(page, reqDTO.getParams());
return pageData;
}
@Override @Override
public IPage<ExamOnlineRespDTO> onlinePaging(PagingReqDTO<ExamDTO> reqDTO) { public IPage<ExamOnlineRespDTO> onlinePaging(PagingReqDTO<ExamDTO> reqDTO) {
// 创建分页对象 // 创建分页对象
Page page = new Page(reqDTO.getCurrent(), reqDTO.getSize()); Page page = new Page(reqDTO.getCurrent(), reqDTO.getSize()); // 使用分页请求DTO创建分页对象
// 查找分页 // 查找分页
IPage<ExamOnlineRespDTO> pageData = baseMapper.online(page, reqDTO.getParams()); IPage<ExamOnlineRespDTO> pageData = baseMapper.online(page, reqDTO.getParams()); // 调用Mapper接口的在线考试分页方法
return pageData; // 返回分页结果
return pageData;
} }
@Override @Override
public IPage<ExamReviewRespDTO> reviewPaging(PagingReqDTO<ExamDTO> reqDTO) { public IPage<ExamReviewRespDTO> reviewPaging(PagingReqDTO<ExamDTO> reqDTO) {
// 创建分页对象 // 创建分页对象
Page page = new Page(reqDTO.getCurrent(), reqDTO.getSize()); Page page = new Page(reqDTO.getCurrent(), reqDTO.getSize()); // 使用分页请求DTO创建分页对象
// 查找分页 // 查找分页
IPage<ExamReviewRespDTO> pageData = baseMapper.reviewPaging(page, reqDTO.getParams()); IPage<ExamReviewRespDTO> pageData = baseMapper.reviewPaging(page, reqDTO.getParams()); // 调用Mapper接口的阅卷分页方法
return pageData; // 返回分页结果
return pageData;
} }
/** /**
* *
* @param reqDTO *
*
* @param reqDTO DTO
*/ */
private void calcScore(ExamSaveReqDTO reqDTO){ private void calcScore(ExamSaveReqDTO reqDTO) {
// 主观题分数 // 主观题分数
int objScore = 0; int objScore = 0;
// 题库组卷 // 题库组卷
List<ExamRepoExtDTO> repoList = reqDTO.getRepoList(); List<ExamRepoExtDTO> repoList = reqDTO.getRepoList(); // 获取题库列表
for(ExamRepoDTO item: repoList){ for(ExamRepoDTO item : repoList){ // 遍历题库列表
if(item.getRadioCount()!=null if(item.getRadioCount() != null && item.getRadioCount() > 0 && item.getRadioScore() != null && item.getRadioScore() > 0){
&& item.getRadioCount()>0 objScore += item.getRadioCount() * item.getRadioScore(); // 计算单选题分数
&& item.getRadioScore()!=null
&& item.getRadioScore()>0){
objScore+=item.getRadioCount()*item.getRadioScore();
} }
if(item.getMultiCount()!=null if(item.getMultiCount() != null && item.getMultiCount() > 0 && item.getMultiScore() != null && item.getMultiScore() > 0){
&& item.getMultiCount()>0 objScore += item.getMultiCount() * item.getMultiScore(); // 计算多选题分数
&& item.getMultiScore()!=null
&& item.getMultiScore()>0){
objScore+=item.getMultiCount()*item.getMultiScore();
} }
if(item.getJudgeCount()!=null if(item.getJudgeCount() != null && item.getJudgeCount() > 0 && item.getJudgeScore() != null && item.getJudgeScore() > 0){
&& item.getJudgeCount()>0 objScore += item.getJudgeCount() * item.getJudgeScore(); // 计算判断题分数
&& item.getJudgeScore()!=null
&& item.getJudgeScore()>0){
objScore+=item.getJudgeCount()*item.getJudgeScore();
} }
} }
reqDTO.setTotalScore(objScore); // 设置总分值
reqDTO.setTotalScore(objScore);
} }
} }

@ -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; import com.baomidou.mybatisplus.core.metadata.IPage;
// 引入统一的API响应封装类
import com.yf.exam.core.api.ApiRest; import com.yf.exam.core.api.ApiRest;
// 引入基础控制器类提供通用的API响应方法
import com.yf.exam.core.api.controller.BaseController; import com.yf.exam.core.api.controller.BaseController;
// 引入各种DTO类用于请求和响应数据传输
import com.yf.exam.core.api.dto.BaseIdReqDTO; import com.yf.exam.core.api.dto.BaseIdReqDTO;
import com.yf.exam.core.api.dto.BaseIdRespDTO; import com.yf.exam.core.api.dto.BaseIdRespDTO;
import com.yf.exam.core.api.dto.BaseIdsReqDTO; import com.yf.exam.core.api.dto.BaseIdsReqDTO;
import com.yf.exam.core.api.dto.PagingReqDTO; import com.yf.exam.core.api.dto.PagingReqDTO;
// 引入工具类,用于对象之间的属性拷贝
import com.yf.exam.core.utils.BeanMapper; import com.yf.exam.core.utils.BeanMapper;
// 引入试卷相关的DTO类
import com.yf.exam.modules.paper.dto.PaperDTO; import com.yf.exam.modules.paper.dto.PaperDTO;
import com.yf.exam.modules.paper.dto.ext.PaperQuDetailDTO; 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.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.ExamDetailRespDTO;
import com.yf.exam.modules.paper.dto.response.ExamResultRespDTO; import com.yf.exam.modules.paper.dto.response.ExamResultRespDTO;
import com.yf.exam.modules.paper.dto.response.PaperListRespDTO; import com.yf.exam.modules.paper.dto.response.PaperListRespDTO;
// 引入试卷实体类
import com.yf.exam.modules.paper.entity.Paper; import com.yf.exam.modules.paper.entity.Paper;
// 引入试卷相关的业务处理服务类
import com.yf.exam.modules.paper.service.PaperService; import com.yf.exam.modules.paper.service.PaperService;
// 引入用户工具类,获取当前登录用户信息
import com.yf.exam.modules.user.UserUtils; import com.yf.exam.modules.user.UserUtils;
// 引入Swagger注解用于API文档生成
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
// 引入Shiro注解用于角色权限管理
import org.apache.shiro.authz.annotation.RequiresRoles; import org.apache.shiro.authz.annotation.RequiresRoles;
// 引入Spring的Bean工具类用于属性复制
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
// 引入Spring的自动注入注解用于自动注入服务
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
// 引入Spring的Web注解定义HTTP请求的映射方式
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
@ -34,123 +48,126 @@ import org.springframework.web.bind.annotation.RestController;
* <p> * <p>
* *
* </p> * </p>
* *
* @author * @author
* @since 2020-05-25 16:33 * @since 2020-05-25 16:33
*/ */
@Api(tags={"试卷"}) @Api(tags={"试卷"}) // Swagger API 文档注解,用于描述该接口属于试卷相关操作
@RestController @RestController // 标记为Spring的控制器处理HTTP请求
@RequestMapping("/exam/api/paper/paper") @RequestMapping("/exam/api/paper/paper") // 定义请求路径的基础路径
public class PaperController extends BaseController { public class PaperController extends BaseController { // 继承BaseController类提供基本的API返回
@Autowired @Autowired // 自动注入PaperService负责业务逻辑处理
private PaperService baseService; private PaperService baseService;
/** /**
* *
* @param reqDTO * @param reqDTO
* @return * @return
*/ */
@ApiOperation(value = "分页查找") @ApiOperation(value = "分页查找") // Swagger操作注解用于描述接口
@RequestMapping(value = "/paging", method = { RequestMethod.POST}) @RequestMapping(value = "/paging", method = { RequestMethod.POST}) // 定义POST请求路径
public ApiRest<IPage<PaperListRespDTO>> paging(@RequestBody PagingReqDTO<PaperListReqDTO> reqDTO) { public ApiRest<IPage<PaperListRespDTO>> paging(@RequestBody PagingReqDTO<PaperListReqDTO> reqDTO) {
//分页查询并转换 // 调用业务层进行分页查询
IPage<PaperListRespDTO> page = baseService.paging(reqDTO); IPage<PaperListRespDTO> page = baseService.paging(reqDTO);
// 返回成功响应,并附带查询结果
return super.success(page); return super.success(page);
} }
/** /**
* *
* @param reqDTO * @param reqDTO
* @return * @return ID
*/ */
@ApiOperation(value = "创建试卷") @ApiOperation(value = "创建试卷") // Swagger操作注解用于描述接口
@RequestMapping(value = "/create-paper", method = { RequestMethod.POST}) @RequestMapping(value = "/create-paper", method = { RequestMethod.POST}) // 定义POST请求路径
public ApiRest<BaseIdRespDTO> save(@RequestBody PaperCreateReqDTO reqDTO) { public ApiRest<BaseIdRespDTO> save(@RequestBody PaperCreateReqDTO reqDTO) {
//复制参数 // 调用业务层创建试卷传入当前用户ID和考试ID
String paperId = baseService.createPaper(UserUtils.getUserId(), reqDTO.getExamId()); String paperId = baseService.createPaper(UserUtils.getUserId(), reqDTO.getExamId());
// 返回创建结果包括试卷ID
return super.success(new BaseIdRespDTO(paperId)); return super.success(new BaseIdRespDTO(paperId));
} }
/** /**
* *
* @param reqDTO * @param reqDTO ID
* @return * @return
*/ */
@ApiOperation(value = "试卷详情") @ApiOperation(value = "试卷详情") // Swagger操作注解用于描述接口
@RequestMapping(value = "/paper-detail", method = { RequestMethod.POST}) @RequestMapping(value = "/paper-detail", method = { RequestMethod.POST}) // 定义POST请求路径
public ApiRest<ExamDetailRespDTO> paperDetail(@RequestBody BaseIdReqDTO reqDTO) { public ApiRest<ExamDetailRespDTO> paperDetail(@RequestBody BaseIdReqDTO reqDTO) {
//根据ID删除 // 调用业务层获取试卷详情
ExamDetailRespDTO respDTO = baseService.paperDetail(reqDTO.getId()); ExamDetailRespDTO respDTO = baseService.paperDetail(reqDTO.getId());
// 返回成功响应,并附带试卷详情
return super.success(respDTO); return super.success(respDTO);
} }
/** /**
* *
* @param reqDTO * @param reqDTO IDID
* @return * @return
*/ */
@ApiOperation(value = "试题详情") @ApiOperation(value = "试题详情") // Swagger操作注解用于描述接口
@RequestMapping(value = "/qu-detail", method = { RequestMethod.POST}) @RequestMapping(value = "/qu-detail", method = { RequestMethod.POST}) // 定义POST请求路径
public ApiRest<PaperQuDetailDTO> quDetail(@RequestBody PaperQuQueryDTO reqDTO) { public ApiRest<PaperQuDetailDTO> quDetail(@RequestBody PaperQuQueryDTO reqDTO) {
//根据ID删除 // 调用业务层获取试题详情
PaperQuDetailDTO respDTO = baseService.findQuDetail(reqDTO.getPaperId(), reqDTO.getQuId()); PaperQuDetailDTO respDTO = baseService.findQuDetail(reqDTO.getPaperId(), reqDTO.getQuId());
// 返回成功响应,并附带试题详情
return super.success(respDTO); return super.success(respDTO);
} }
/** /**
* *
* @param reqDTO * @param reqDTO
* @return * @return
*/ */
@ApiOperation(value = "填充答案") @ApiOperation(value = "填充答案") // Swagger操作注解用于描述接口
@RequestMapping(value = "/fill-answer", method = { RequestMethod.POST}) @RequestMapping(value = "/fill-answer", method = { RequestMethod.POST}) // 定义POST请求路径
public ApiRest<PaperQuDetailDTO> fillAnswer(@RequestBody PaperAnswerDTO reqDTO) { public ApiRest<PaperQuDetailDTO> fillAnswer(@RequestBody PaperAnswerDTO reqDTO) {
//根据ID删除 // 调用业务层填充答案操作
baseService.fillAnswer(reqDTO); baseService.fillAnswer(reqDTO);
// 返回成功响应
return super.success(); return super.success();
} }
/** /**
* *
* @param reqDTO * @param reqDTO ID
* @return * @return
*/ */
@ApiOperation(value = "交卷操作") @ApiOperation(value = "交卷操作") // Swagger操作注解用于描述接口
@RequestMapping(value = "/hand-exam", method = { RequestMethod.POST}) @RequestMapping(value = "/hand-exam", method = { RequestMethod.POST}) // 定义POST请求路径
public ApiRest<PaperQuDetailDTO> handleExam(@RequestBody BaseIdReqDTO reqDTO) { public ApiRest<PaperQuDetailDTO> handleExam(@RequestBody BaseIdReqDTO reqDTO) {
//根据ID删除 // 调用业务层进行交卷操作
baseService.handExam(reqDTO.getId()); baseService.handExam(reqDTO.getId());
// 返回成功响应
return super.success(); return super.success();
} }
/** /**
* *
* @param reqDTO * @param reqDTO ID
* @return * @return
*/ */
@ApiOperation(value = "试卷详情") @ApiOperation(value = "试卷结果") // Swagger操作注解用于描述接口
@RequestMapping(value = "/paper-result", method = { RequestMethod.POST}) @RequestMapping(value = "/paper-result", method = { RequestMethod.POST}) // 定义POST请求路径
public ApiRest<ExamResultRespDTO> paperResult(@RequestBody BaseIdReqDTO reqDTO) { public ApiRest<ExamResultRespDTO> paperResult(@RequestBody BaseIdReqDTO reqDTO) {
//根据ID删除 // 调用业务层获取试卷的考试结果
ExamResultRespDTO respDTO = baseService.paperResult(reqDTO.getId()); ExamResultRespDTO respDTO = baseService.paperResult(reqDTO.getId());
// 返回成功响应,并附带试卷结果
return super.success(respDTO); return super.success(respDTO);
} }
/** /**
* *
* @return * @return
*/ */
@ApiOperation(value = "检测进行中的考试") @ApiOperation(value = "检测进行中的考试") // Swagger操作注解用于描述接口
@RequestMapping(value = "/check-process", method = { RequestMethod.POST}) @RequestMapping(value = "/check-process", method = { RequestMethod.POST}) // 定义POST请求路径
public ApiRest<PaperDTO> checkProcess() { public ApiRest<PaperDTO> checkProcess() {
//复制参数 // 调用业务层检测用户是否有未完成的考试
PaperDTO dto = baseService.checkProcess(UserUtils.getUserId()); PaperDTO dto = baseService.checkProcess(UserUtils.getUserId());
// 返回成功响应,并附带考试进程数据
return super.success(dto); 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; import com.yf.exam.core.annon.Dict;
// 引入Swagger注解用于API文档生成
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
// 引入Lombok注解用于自动生成getter、setter等方法
import lombok.Data; import lombok.Data;
// 引入Serializable接口用于对象序列化
import java.io.Serializable; import java.io.Serializable;
// 引入Date类用于表示日期和时间
import java.util.Date; import java.util.Date;
/** /**
* <p> * <p>
* *
* </p> * </p>
* * ID
* @author * 使
* @since 2020-05-25 17:31 *
*/ * @author
@Data * @since 2020-05-25 17:31
@ApiModel(value="试卷", description="试卷") */
public class PaperDTO implements Serializable { @Data // Lombok注解自动生成getter、setter、toString、equals和hashCode方法
@ApiModel(value="试卷", description="试卷") // Swagger注解用于描述该类在API文档中的作用和说明
private static final long serialVersionUID = 1L; public class PaperDTO implements Serializable { // 实现Serializable接口表示该类的对象可以被序列化
@ApiModelProperty(value = "试卷ID", required=true) private static final long serialVersionUID = 1L; // 序列化版本ID用于序列化和反序列化操作
private String id;
@Dict(dictTable = "sys_user", dicText = "real_name", dicCode = "id") @ApiModelProperty(value = "试卷ID", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
@ApiModelProperty(value = "用户ID", required=true) private String id; // 试卷ID
private String userId;
@Dict(dictTable = "sys_depart", dicText = "dept_name", dicCode = "id") @Dict(dictTable = "sys_user", dicText = "real_name", dicCode = "id") // 字典表映射,映射用户表的姓名字段
@ApiModelProperty(value = "部门ID", required=true) @ApiModelProperty(value = "用户ID", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String departId; private String userId; // 用户ID
@ApiModelProperty(value = "规则ID", required=true) @Dict(dictTable = "sys_depart", dicText = "dept_name", dicCode = "id") // 字典表映射,映射部门表的部门名称字段
private String examId; @ApiModelProperty(value = "部门ID", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String departId; // 部门ID
@ApiModelProperty(value = "考试标题", required=true) @ApiModelProperty(value = "规则ID", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String title; private String examId; // 规则ID表示该试卷对应的考试规则
@ApiModelProperty(value = "考试时长", required=true) @ApiModelProperty(value = "考试标题", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Integer totalTime; private String title; // 考试标题,表示试卷的名称
@ApiModelProperty(value = "用户时长", required=true) @ApiModelProperty(value = "考试时长", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Integer userTime; private Integer totalTime; // 考试时长(单位:分钟)
@ApiModelProperty(value = "试卷总分", required=true) @ApiModelProperty(value = "用户时长", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Integer totalScore; private Integer userTime; // 用户已使用的时间(单位:分钟)
@ApiModelProperty(value = "及格分", required=true) @ApiModelProperty(value = "试卷总分", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Integer qualifyScore; private Integer totalScore; // 试卷总分
@ApiModelProperty(value = "客观分", required=true) @ApiModelProperty(value = "及格分", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Integer objScore; private Integer qualifyScore; // 及格分数
@ApiModelProperty(value = "观分", required=true) @ApiModelProperty(value = "观分", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Integer subjScore; private Integer objScore; // 客观题分数
@ApiModelProperty(value = "用户得分", required=true) @ApiModelProperty(value = "主观分", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Integer userScore; private Integer subjScore; // 主观题分数
@ApiModelProperty(value = "是否包含简答题", required=true) @ApiModelProperty(value = "用户得分", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Boolean hasSaq; private Integer userScore; // 用户得分
@ApiModelProperty(value = "试卷状态", required=true) @ApiModelProperty(value = "是否包含简答题", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Integer state; private Boolean hasSaq; // 是否包含简答题,布尔类型,表示该试卷是否有简答题
@ApiModelProperty(value = "创建时间", required=true) @ApiModelProperty(value = "试卷状态", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Date createTime; private Integer state; // 试卷状态,表示试卷的当前状态,如未开始、进行中、已结束等
@ApiModelProperty(value = "更新时间", required=true) @ApiModelProperty(value = "创建时间", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Date updateTime; private Date createTime; // 创建时间,表示试卷的创建时间
@ApiModelProperty(value = "截止时间") @ApiModelProperty(value = "更新时间", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Date limitTime; private Date updateTime; // 更新时间,表示试卷的最后更新时间
@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.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
// 引入Lombok注解用于自动生成getter、setter等方法
import lombok.Data; import lombok.Data;
// 引入Serializable接口用于对象序列化
import java.io.Serializable; import java.io.Serializable;
/** /**
* <p> * <p>
* *
* </p> * </p>
* * IDID
* @author *
* @since 2020-05-25 17:31 *
*/ * @author
@Data * @since 2020-05-25 17:31
@ApiModel(value="试卷考题备选答案", description="试卷考题备选答案") */
public class PaperQuAnswerDTO implements Serializable { @Data // Lombok注解自动生成getter、setter、toString、equals和hashCode方法
@ApiModel(value="试卷考题备选答案", description="试卷考题备选答案") // Swagger注解用于描述该类在API文档中的作用和说明
private static final long serialVersionUID = 1L; public class PaperQuAnswerDTO implements Serializable { // 实现Serializable接口表示该类的对象可以被序列化
@ApiModelProperty(value = "自增ID", required=true) private static final long serialVersionUID = 1L; // 序列化版本ID用于序列化和反序列化操作
private String id;
@ApiModelProperty(value = "试卷ID", required=true) @ApiModelProperty(value = "自增ID", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String paperId; private String id; // 自增ID表示备选答案的唯一标识符
@ApiModelProperty(value = "回答项ID", required=true) @ApiModelProperty(value = "试卷ID", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String answerId; private String paperId; // 试卷ID表示该备选答案所属的试卷
@ApiModelProperty(value = "题目ID", required=true) @ApiModelProperty(value = "回答项ID", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String quId; private String answerId; // 回答项ID表示该备选答案的唯一标识符
@ApiModelProperty(value = "是否正确项", required=true) @ApiModelProperty(value = "题目ID", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Boolean isRight; private String quId; // 题目ID表示该备选答案所属的题目
@ApiModelProperty(value = "是否选中", required=true) @ApiModelProperty(value = "是否正确项", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Boolean checked; private Boolean isRight; // 是否正确项,布尔值,表示该备选答案是否是正确答案
@ApiModelProperty(value = "排序", required=true) @ApiModelProperty(value = "是否选中", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Integer sort; private Boolean checked; // 是否选中,布尔值,表示该备选答案是否已被选中
@ApiModelProperty(value = "选项标签", required=true) @ApiModelProperty(value = "排序", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String abc; private Integer sort; // 排序,表示该备选答案在题目中的排序位置
@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.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
// 引入Lombok注解用于自动生成getter、setter等方法
import lombok.Data; import lombok.Data;
// 引入Serializable接口用于对象序列化
import java.io.Serializable; import java.io.Serializable;
/** /**
* <p> * <p>
* *
* </p> * </p>
* * IDID
* @author *
* @since 2020-05-25 17:31 * @author
*/ * @since 2020-05-25 17:31
@Data */
@ApiModel(value="试卷考题", description="试卷考题") @Data // Lombok注解自动生成getter、setter、toString、equals和hashCode方法
public class PaperQuDTO implements Serializable { @ApiModel(value="试卷考题", description="试卷考题") // Swagger注解用于描述该类在API文档中的作用和说明
public class PaperQuDTO implements Serializable { // 实现Serializable接口表示该类的对象可以被序列化
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "ID", required=true) private static final long serialVersionUID = 1L; // 序列化版本ID用于序列化和反序列化操作
private String id;
@ApiModelProperty(value = "试卷ID", required=true) @ApiModelProperty(value = "ID", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String paperId; private String id; // 题目ID唯一标识符
@ApiModelProperty(value = "题目ID", required=true) @ApiModelProperty(value = "试卷ID", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String quId; private String paperId; // 试卷ID表示该题目所属的试卷
@ApiModelProperty(value = "题目类型", required=true) @ApiModelProperty(value = "题目ID", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Integer quType; private String quId; // 题目ID唯一标识该题目
@ApiModelProperty(value = "是否已答", required=true) @ApiModelProperty(value = "题目类型", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Boolean answered; private Integer quType; // 题目类型,表示题目的分类,如选择题、判断题、主观题等
@ApiModelProperty(value = "主观答案", required=true) @ApiModelProperty(value = "是否已答", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String answer; private Boolean answered; // 是否已答,布尔值,表示该题目是否已被回答
@ApiModelProperty(value = "问题排序", required=true) @ApiModelProperty(value = "主观答案", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Integer sort; private String answer; // 主观答案,表示对该题目的回答内容(适用于主观题)
@ApiModelProperty(value = "单题分分值", required=true) @ApiModelProperty(value = "问题排序", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Integer score; private Integer sort; // 问题排序,表示该题目在试卷中的顺序
@ApiModelProperty(value = "实际得分(主观题)", required=true) @ApiModelProperty(value = "单题分分值", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Integer actualScore; private Integer score; // 单题分值,表示该题目的满分
@ApiModelProperty(value = "是否答对", required=true) @ApiModelProperty(value = "实际得分(主观题)", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Boolean isRight; private Integer actualScore; // 实际得分,表示用户在该题目中实际得到的分数(适用于主观题)
@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; import com.yf.exam.modules.paper.dto.PaperQuAnswerDTO;
// 引入Swagger注解用于API文档生成
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
// 引入Lombok注解用于自动生成getter、setter等方法
import lombok.Data; import lombok.Data;
/** /**
* <p> * <p>
* *
* </p> * </p>
* * PaperQuAnswerDTO
* @author * @author
* @since 2020-05-25 17:31 * @since 2020-05-25 17:31
*/ */
@Data @Data // Lombok注解自动生成getter、setter、toString、equals和hashCode方法
@ApiModel(value="试卷考题备选答案", description="试卷考题备选答案") @ApiModel(value="试卷考题备选答案", description="试卷考题备选答案") // Swagger注解描述模型信息生成API文档时使用
public class PaperQuAnswerExtDTO extends PaperQuAnswerDTO { 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)
private String content;
@ApiModelProperty(value = "试题图片", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String image; // 试题对应的图片内容
@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; import com.yf.exam.modules.paper.dto.PaperQuDTO;
// 引入Swagger注解用于API文档生成
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
// 引入Lombok注解用于自动生成getter、setter等方法
import lombok.Data; import lombok.Data;
// 引入List集合用于存储多个备选答案
import java.util.List; import java.util.List;
/** /**
* <p> * <p>
* *
* </p> * </p>
* * PaperQuDTO
* @author * @author
* @since 2020-05-25 17:31 * @since 2020-05-25 17:31
*/ */
@Data @Data // Lombok注解自动生成getter、setter、toString、equals和hashCode方法
@ApiModel(value="试卷题目详情类", description="试卷题目详情类") @ApiModel(value="试卷题目详情类", description="试卷题目详情类") // Swagger注解用于描述该类在API文档中的作用和说明
public class PaperQuDetailDTO extends PaperQuDTO { public class PaperQuDetailDTO extends PaperQuDTO { // 继承自PaperQuDTO类扩展了额外属性
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L; // 序列化版本号,用于序列化和反序列化时的版本控制
@ApiModelProperty(value = "图片", required=true) @ApiModelProperty(value = "图片", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String image; private String image; // 题目的图片内容
@ApiModelProperty(value = "题目内容", required=true) @ApiModelProperty(value = "题目内容", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String content; private String content; // 试题的具体内容
@ApiModelProperty(value = "答案内容", required=true) @ApiModelProperty(value = "答案内容", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
List<PaperQuAnswerExtDTO> answerList; 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.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
// 引入Lombok注解用于自动生成getter、setter等方法
import lombok.Data; import lombok.Data;
// 引入List集合用于存储多个答案
import java.util.List; import java.util.List;
/** /**
* @author bool * @author bool
*
* PaperQuQueryDTO
*/ */
@Data @Data // Lombok注解自动生成getter、setter、toString、equals和hashCode方法
@ApiModel(value="查找试卷题目详情请求类", description="查找试卷题目详情请求类") @ApiModel(value="查找试卷题目详情请求类", description="查找试卷题目详情请求类") // Swagger注解用于描述该类在API文档中的作用和说明
public class PaperAnswerDTO extends PaperQuQueryDTO { public class PaperAnswerDTO extends PaperQuQueryDTO { // 继承自PaperQuQueryDTO类扩展了额外属性
@ApiModelProperty(value = "回答列表", required=true)
private List<String> answers;
@ApiModelProperty(value = "主观答案", required=true) @ApiModelProperty(value = "回答列表", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String answer; 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; import com.yf.exam.core.api.dto.BaseDTO;
// 引入Jackson注解用于处理JSON序列化时忽略某些字段
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
// 引入Swagger注解用于API文档生成
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
// 引入Lombok注解用于自动生成getter、setter等方法
import lombok.Data; import lombok.Data;
/** /**
* @author bool * @author bool
* IDID
*/ */
@Data @Data // Lombok注解自动生成getter、setter、toString、equals和hashCode方法
@ApiModel(value="试卷创建请求类", description="试卷创建请求类") @ApiModel(value="试卷创建请求类", description="试卷创建请求类") // Swagger注解用于描述该类在API文档中的作用和说明
public class PaperCreateReqDTO extends BaseDTO { public class PaperCreateReqDTO extends BaseDTO { // 继承自BaseDTO类扩展了考试ID和用户ID字段
@JsonIgnore @JsonIgnore // Jackson注解表示在进行JSON序列化/反序列化时忽略该字段
private String userId; private String userId; // 存储用户ID通常用于标识发起请求的用户但在JSON序列化中不会被传递
@ApiModelProperty(value = "考试ID", required=true)
private String examId;
@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.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
// 引入Lombok注解用于自动生成getter、setter等方法
import lombok.Data; import lombok.Data;
// 引入Serializable接口用于对象序列化
import java.io.Serializable; import java.io.Serializable;
/** /**
* <p> * <p>
* *
* </p> * </p>
* * IDIDID
*
* @author * @author
* @since 2020-05-25 17:31 * @since 2020-05-25 17:31
*/ */
@Data @Data // Lombok注解自动生成getter、setter、toString、equals和hashCode方法
@ApiModel(value="试卷", description="试卷") @ApiModel(value="试卷", description="试卷") // Swagger注解描述该类在API文档中的作用和说明
public class PaperListReqDTO implements Serializable { public class PaperListReqDTO implements Serializable { // 实现Serializable接口支持对象的序列化
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "用户ID", required=true)
private String userId;
@ApiModelProperty(value = "部门ID", required=true) private static final long serialVersionUID = 1L; // 序列化版本号,用于序列化和反序列化时的版本控制
private String departId;
@ApiModelProperty(value = "规则ID", required=true) @ApiModelProperty(value = "用户ID", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String examId; private String userId; // 存储请求发起者的用户ID通常用于标识用户
@ApiModelProperty(value = "用户昵称", required=true) @ApiModelProperty(value = "部门ID", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String realName; private String departId; // 存储请求者所在部门的ID用于查询特定部门的试卷
@ApiModelProperty(value = "试卷状态", required=true) @ApiModelProperty(value = "规则ID", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private Integer state; private String examId; // 存储与试卷相关的考试规则ID用于标识试卷属于哪种考试
@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; import com.yf.exam.core.api.dto.BaseDTO;
// 引入Swagger注解用于API文档生成
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
// 引入Lombok注解用于自动生成getter、setter等方法
import lombok.Data; import lombok.Data;
/** /**
* @author bool * @author bool
*
* IDID
*/ */
@Data @Data // Lombok注解自动生成getter、setter、toString、equals和hashCode方法
@ApiModel(value="查找试卷题目详情请求类", description="查找试卷题目详情请求类") @ApiModel(value="查找试卷题目详情请求类", description="查找试卷题目详情请求类") // Swagger注解用于描述该类在API文档中的作用和说明
public class PaperQuQueryDTO extends BaseDTO { public class PaperQuQueryDTO extends BaseDTO { // 继承自BaseDTO类扩展了试卷ID和题目ID字段
@ApiModelProperty(value = "试卷ID", required=true) @ApiModelProperty(value = "试卷ID", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private String paperId; private String paperId; // 存储试卷ID用于查询特定试卷的题目详情
@ApiModelProperty(value = "题目ID", required=true)
private String quId;
@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; import com.yf.exam.modules.paper.dto.PaperDTO;
// 引入PaperQuDTO类用于表示试题的DTO
import com.yf.exam.modules.paper.dto.PaperQuDTO; import com.yf.exam.modules.paper.dto.PaperQuDTO;
// 引入Swagger注解用于API文档生成
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
// 引入Lombok注解用于自动生成getter、setter等方法
import lombok.Data; import lombok.Data;
// 引入Calendar类用于时间计算
import java.util.Calendar; import java.util.Calendar;
// 引入List集合用于存储试题列表
import java.util.List; import java.util.List;
@Data /**
@ApiModel(value="考试详情", description="考试详情") * <p>
public class ExamDetailRespDTO extends PaperDTO { *
* </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) @ApiModelProperty(value = "单选题列表", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private List<PaperQuDTO> radioList; private List<PaperQuDTO> radioList; // 存储单选题的列表使用PaperQuDTO表示单个试题
@ApiModelProperty(value = "多选题列表", required=true) @ApiModelProperty(value = "多选题列表", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private List<PaperQuDTO> multiList; private List<PaperQuDTO> multiList; // 存储多选题的列表使用PaperQuDTO表示单个试题
@ApiModelProperty(value = "判断题", required=true) @ApiModelProperty(value = "判断题", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private List<PaperQuDTO> judgeList; private List<PaperQuDTO> judgeList; // 存储判断题的列表使用PaperQuDTO表示单个试题
@ApiModelProperty(value = "剩余结束秒数", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
@ApiModelProperty(value = "剩余结束秒数", required=true) public Long getLeftSeconds(){ // 计算剩余时间的方法,返回剩余的秒数
public Long getLeftSeconds(){
// 结束时间 // 结束时间
Calendar cl = Calendar.getInstance(); Calendar cl = Calendar.getInstance(); // 获取当前时间的Calendar实例
cl.setTime(this.getCreateTime()); cl.setTime(this.getCreateTime()); // 设置Calendar的时间为试卷的创建时间
cl.add(Calendar.MINUTE, getTotalTime()); 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; import com.yf.exam.modules.paper.dto.PaperDTO;
// 引入PaperQuDetailDTO类用于表示试题详细信息
import com.yf.exam.modules.paper.dto.ext.PaperQuDetailDTO; import com.yf.exam.modules.paper.dto.ext.PaperQuDetailDTO;
// 引入Swagger注解用于API文档生成
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
// 引入Lombok注解用于自动生成getter、setter等方法
import lombok.Data; import lombok.Data;
// 引入List集合用于存储试题列表
import java.util.List; import java.util.List;
@Data /**
@ApiModel(value="考试结果展示响应类", description="考试结果展示响应类") * <p>
public class ExamResultRespDTO extends PaperDTO { *
* </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) @ApiModelProperty(value = "问题列表", required=true) // Swagger注解描述该字段在API文档中的含义并标注该字段为必填项
private List<PaperQuDetailDTO> quList; 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; import com.yf.exam.modules.paper.dto.PaperDTO;
// 引入Swagger注解用于API文档生成
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
// 引入Lombok注解用于自动生成getter、setter等方法
import lombok.Data; import lombok.Data;
/** /**
* <p> * <p>
* *
* </p> * </p>
* * PaperDTOrealName
* @author *
* @since 2020-05-25 17:31 *
*/ * @author
@Data * @since 2020-05-25 17:31
@ApiModel(value="试卷列表响应类", description="试卷列表响应类") */
public class PaperListRespDTO extends PaperDTO { @Data // Lombok注解自动生成getter、setter、toString、equals和hashCode方法
@ApiModel(value="试卷列表响应类", description="试卷列表响应类") // Swagger注解用于描述该类在API文档中的作用和说明
private static final long serialVersionUID = 1L; public class PaperListRespDTO extends PaperDTO { // 继承自PaperDTO表示试卷列表响应DTO
@ApiModelProperty(value = "人员", required=true)
private String realName;
private static final long serialVersionUID = 1L; // 序列化版本ID用于序列化和反序列化操作
@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.IdType;
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model; import com.baomidou.mybatisplus.extension.activerecord.Model;
// 引入Lombok注解用于自动生成getter、setter等方法
import lombok.Data; import lombok.Data;
// 引入Date类用于时间相关的字段
import java.util.Date; import java.util.Date;
/** /**
* <p> * <p>
* *
* </p> * </p>
* * `el_paper`
* @author *
* @since 2020-05-25 17:31 * @author
*/ * @since 2020-05-25 17:31
@Data */
@TableName("el_paper") @Data // Lombok注解自动生成getter、setter、toString、equals和hashCode方法
public class Paper extends Model<Paper> { @TableName("el_paper") // MyBatis Plus注解指定该实体类对应的数据库表名
public class Paper extends Model<Paper> { // 继承MyBatis Plus的Model类提供了CRUD等基础操作
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L; // 序列化版本ID用于序列化和反序列化操作
/** /**
* ID * ID
*/ */
@TableId(value = "id", type = IdType.ASSIGN_ID) @TableId(value = "id", type = IdType.ASSIGN_ID) // MyBatis Plus注解指定主键字段及其生成策略
private String id; private String id; // 试卷ID唯一标识符
/** /**
* ID * ID
*/ */
@TableField("user_id") @TableField("user_id") // MyBatis Plus注解指定字段与数据库表字段的映射关系
private String userId; private String userId; // 用户ID表示创建该试卷的用户
/** /**
* ID * ID
*/ */
@TableField("depart_id") @TableField("depart_id") // MyBatis Plus注解指定字段与数据库表字段的映射关系
private String departId; private String departId; // 部门ID表示该试卷所属的部门
/** /**
* ID * ID
*/ */
@TableField("exam_id") @TableField("exam_id") // MyBatis Plus注解指定字段与数据库表字段的映射关系
private String examId; private String examId; // 规则ID表示该试卷所属的考试规则
/** /**
* *
*/ */
private String title; private String title; // 考试标题,表示试卷的名称或标题
/** /**
* *
*/ */
@TableField("total_time") @TableField("total_time") // MyBatis Plus注解指定字段与数据库表字段的映射关系
private Integer totalTime; private Integer totalTime; // 考试时长,单位为分钟
/** /**
* *
*/ */
@TableField("user_time") @TableField("user_time") // MyBatis Plus注解指定字段与数据库表字段的映射关系
private Integer userTime; private Integer userTime; // 用户实际用时,单位为分钟
/** /**
* *
*/ */
@TableField("total_score") @TableField("total_score") // MyBatis Plus注解指定字段与数据库表字段的映射关系
private Integer totalScore; private Integer totalScore; // 试卷的总分数
/** /**
* *
*/ */
@TableField("qualify_score") @TableField("qualify_score") // MyBatis Plus注解指定字段与数据库表字段的映射关系
private Integer qualifyScore; private Integer qualifyScore; // 及格分数,表示通过该试卷的最低分数
/** /**
* *
*/ */
@TableField("obj_score") @TableField("obj_score") // MyBatis Plus注解指定字段与数据库表字段的映射关系
private Integer objScore; private Integer objScore; // 客观题部分的得分
/** /**
* *
*/ */
@TableField("subj_score") @TableField("subj_score") // MyBatis Plus注解指定字段与数据库表字段的映射关系
private Integer subjScore; private Integer subjScore; // 主观题部分的得分
/** /**
* *
*/ */
@TableField("user_score") @TableField("user_score") // MyBatis Plus注解指定字段与数据库表字段的映射关系
private Integer userScore; private Integer userScore; // 用户在该试卷上的得分
/** /**
* *
*/ */
@TableField("has_saq") @TableField("has_saq") // MyBatis Plus注解指定字段与数据库表字段的映射关系
private Boolean hasSaq;
/**
*
*/
private Integer state;
/**
*
*/
@TableField("create_time")
private Date createTime;
/**
*
*/
@TableField("update_time")
private Date updateTime;
/**
*
*/
@TableField("limit_time")
private Date limitTime;
}

@ -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.IdType;
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model; import com.baomidou.mybatisplus.extension.activerecord.Model;
// 引入Lombok注解用于自动生成getter、setter等方法
import lombok.Data; import lombok.Data;
/** /**
* <p> * <p>
* *
* </p> * </p>
* * `el_paper_qu`
* @author *
* @since 2020-05-25 17:31 * @author
*/ * @since 2020-05-25 17:31
@Data */
@TableName("el_paper_qu") @Data // Lombok注解自动生成getter、setter、toString、equals和hashCode方法
public class PaperQu extends Model<PaperQu> { @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 * ID
*/ */
@TableId(value = "id", type = IdType.ASSIGN_ID) @TableId(value = "id", type = IdType.ASSIGN_ID) // MyBatis Plus注解指定主键字段及其生成策略
private String id; private String id; // 题目ID唯一标识符
/** /**
* ID * ID
*/ */
@TableField("paper_id") @TableField("paper_id") // MyBatis Plus注解指定字段与数据库表字段的映射关系
private String paperId; private String paperId; // 试卷ID表示该题目所属的试卷ID
/** /**
* ID * ID
*/ */
@TableField("qu_id") @TableField("qu_id") // MyBatis Plus注解指定字段与数据库表字段的映射关系
private String quId; private String quId; // 题目ID唯一标识符
/** /**
* *
*/ */
@TableField("qu_type") @TableField("qu_type") // MyBatis Plus注解指定字段与数据库表字段的映射关系
private Integer quType; 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") @TableField("actual_score") // MyBatis Plus注解指定字段与数据库表字段的映射关系
private Integer actualScore; private Integer actualScore; // 主观题的实际得分,可能与用户给出的答案相关
/** /**
* *
*/ */
@TableField("is_right") @TableField("is_right") // MyBatis Plus注解指定字段与数据库表字段的映射关系
private Boolean isRight; 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.IdType;
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model; import com.baomidou.mybatisplus.extension.activerecord.Model;
// 引入Lombok注解用于自动生成getter、setter等方法
import lombok.Data; import lombok.Data;
/** /**
* <p> * <p>
* *
* </p> * </p>
* * `el_paper_qu_answer`
* @author *
* @since 2020-05-25 17:31 * @author
*/ * @since 2020-05-25 17:31
@Data */
@TableName("el_paper_qu_answer") @Data // Lombok注解自动生成getter、setter、toString、equals和hashCode方法
public class PaperQuAnswer extends Model<PaperQuAnswer> { @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 * ID
*/ */
@TableId(value = "id", type = IdType.ASSIGN_ID) @TableId(value = "id", type = IdType.ASSIGN_ID) // MyBatis Plus注解指定主键字段及其生成策略
private String id; private String id; // 唯一标识符ID数据库中的主键
/** /**
* ID * ID
*/ */
@TableField("paper_id") @TableField("paper_id") // MyBatis Plus注解指定字段与数据库表字段的映射关系
private String paperId; private String paperId; // 该备选答案对应的试卷ID
/** /**
* ID * ID
*/ */
@TableField("answer_id") @TableField("answer_id") // MyBatis Plus注解指定字段与数据库表字段的映射关系
private String answerId; private String answerId; // 该备选答案的唯一标识符ID
/** /**
* ID * ID
*/ */
@TableField("qu_id") @TableField("qu_id") // MyBatis Plus注解指定字段与数据库表字段的映射关系
private String quId; private String quId; // 该备选答案所属的题目ID
/** /**
* *
*/ */
@TableField("is_right") @TableField("is_right") // MyBatis Plus注解指定字段与数据库表字段的映射关系
private Boolean isRight; 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; // 定义当前类所在的包路径
/** /**
* * <p>
*
* </p>
* 使
*
* @author bool * @author bool
* @date 2019-10-30 13:11 * @date 2019-10-30 13:11
*/ */
public interface ExamState { public interface ExamState {
/** /**
* *
*
*/ */
Integer ENABLE = 0; Integer ENABLE = 0;
/** /**
* *
*
*/ */
Integer DISABLED = 1; Integer DISABLED = 1;
/** /**
* *
*
*/ */
Integer READY_START = 2; Integer READY_START = 2;
/** /**
* *
*
*/ */
Integer OVERDUE = 3; Integer OVERDUE = 3;
} }

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

@ -1,45 +1,61 @@
package com.yf.exam.modules.paper.job; package com.yf.exam.modules.paper.job; // 定义类所在的包路径
import com.yf.exam.ability.job.service.JobService; import com.yf.exam.ability.job.service.JobService; // 导入 JobService 类,用于获取任务数据
import com.yf.exam.modules.paper.service.PaperService; import com.yf.exam.modules.paper.service.PaperService; // 导入 PaperService 类,用于处理试卷相关的业务逻辑
import lombok.extern.log4j.Log4j2; import lombok.extern.log4j.Log4j2; // 引入 log4j2 日志工具
import org.quartz.Job; import org.quartz.Job; // 导入 Quartz 作业接口
import org.quartz.JobDetail; import org.quartz.JobDetail; // 导入 Quartz JobDetail 类
import org.quartz.JobExecutionContext; import org.quartz.JobExecutionContext; // 导入 Quartz JobExecutionContext 类
import org.quartz.JobExecutionException; import org.quartz.JobExecutionException; // 导入 Quartz JobExecutionException 类
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired; // 引入 Spring 注解,用于自动注入依赖
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component; // 引入 Spring 组件注解,标识为 Spring Bean
/** /**
* *
* <p>
* Quartz
* PaperService
* </p>
*
* @author bool * @author bool
*/ */
@Log4j2 @Log4j2 // 启用 log4j2 日志记录
@Component @Component // 标识该类为一个 Spring 组件Spring 会自动将其注册为 Bean
public class BreakExamJob implements Job { public class BreakExamJob implements Job {
// 自动注入 PaperService用于处理与试卷相关的业务逻辑
@Autowired @Autowired
private PaperService paperService; private PaperService paperService;
/**
*
*
* <p>
* Quartz
* PaperService
* </p>
*
* @param jobExecutionContext Quartz
* @throws JobExecutionException
*/
@Override @Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
JobDetail detail = jobExecutionContext.getJobDetail(); // 从 jobExecutionContext 中获取任务的详细信息
String name = detail.getKey().getName(); JobDetail detail = jobExecutionContext.getJobDetail(); // 获取任务详情
String group = detail.getKey().getGroup(); String name = detail.getKey().getName(); // 获取任务名称
String group = detail.getKey().getGroup(); // 获取任务分组
// 获取任务的附加数据,通常是任务触发时的相关参数
String data = String.valueOf(detail.getJobDataMap().get(JobService.TASK_DATA)); String data = String.valueOf(detail.getJobDataMap().get(JobService.TASK_DATA));
// 打印任务执行日志,便于调试和跟踪
log.info("++++++++++定时任务:处理到期的交卷"); log.info("++++++++++定时任务:处理到期的交卷");
log.info("++++++++++jobName:{}", name); log.info("++++++++++jobName:{}", name);
log.info("++++++++++jobGroup:{}", group); log.info("++++++++++jobGroup:{}", group);
log.info("++++++++++taskData:{}", data); log.info("++++++++++taskData:{}", data);
// 调用 PaperService 进行强制交卷操作
// 强制交卷 // data 参数通常是考试 ID 或者某种标识符,用于识别需要交卷的考试
paperService.handExam(data); 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.mapper.BaseMapper; // 引入 MyBatis-Plus 的 BaseMapper
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage; // 引入分页结果接口 IPage
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; // 引入分页插件 Page
import com.yf.exam.modules.paper.dto.PaperDTO; import com.yf.exam.modules.paper.dto.PaperDTO; // 引入 DTO 类,表示试卷数据传输对象
import com.yf.exam.modules.paper.dto.request.PaperListReqDTO; import com.yf.exam.modules.paper.dto.request.PaperListReqDTO; // 引入请求 DTO 类,表示查询试卷时的请求参数
import com.yf.exam.modules.paper.dto.response.PaperListRespDTO; import com.yf.exam.modules.paper.dto.response.PaperListRespDTO; // 引入响应 DTO 类,表示查询试卷时的响应结果
import com.yf.exam.modules.paper.entity.Paper; import com.yf.exam.modules.paper.entity.Paper; // 引入实体类,表示试卷数据表中的记录
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param; // 引入 MyBatis 注解,用于指定 SQL 查询中的参数
import java.util.List; import java.util.List;
/** /**
* <p> * <p>
* Mapper * Mapper
* </p> * </p>
* *
* @author * @author
* @since 2020-05-25 16:33 * @since 2020-05-25 16:33
*/ */
public interface PaperMapper extends BaseMapper<Paper> { public interface PaperMapper extends BaseMapper<Paper> { // 继承 MyBatis-Plus 提供的 BaseMapper自动实现 CRUD 操作
/** /**
* *
* @param page * <p>
* @param query * `Page` `PaperListReqDTO`
* @return * </p>
*
* @param page
* @param query ID ID
* @return `IPage<PaperListRespDTO>`
*/ */
IPage<PaperListRespDTO> paging(Page page, @Param("query") PaperListReqDTO query); IPage<PaperListRespDTO> paging(Page page, @Param("query") PaperListReqDTO query);
/** /**
* *
* @param query * <p>
* @return *
* </p>
*
* @param query ID ID
* @return `List<PaperListRespDTO>` DTO
*/ */
List<PaperListRespDTO> list(@Param("query") PaperDTO query); 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; // 指定该类所在的包路径
// 导入BaseMapper接口提供通用的CRUD操作
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
// 导入PaperQuAnswerExtDTO类表示试卷考题备选答案的扩展数据传输对象
import com.yf.exam.modules.paper.dto.ext.PaperQuAnswerExtDTO; import com.yf.exam.modules.paper.dto.ext.PaperQuAnswerExtDTO;
// 导入PaperQuAnswer实体类表示试卷考题备选答案的数据模型
import com.yf.exam.modules.paper.entity.PaperQuAnswer; import com.yf.exam.modules.paper.entity.PaperQuAnswer;
// 导入MyBatis的注解指定方法参数在SQL中的名称
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
// 导入List接口表示返回类型为List集合用于存储多个备选答案
import java.util.List; import java.util.List;
/** /**
* <p> * <p>
* Mapper * Mapper
* </p> * </p>
* MyBatis-PlusBaseMapperCRUD
* *
* @author * @author
* @since 2020-05-25 16:33 * @since 2020-05-25 16:33
*/ */
public interface PaperQuAnswerMapper extends BaseMapper<PaperQuAnswer> { public interface PaperQuAnswerMapper extends BaseMapper<PaperQuAnswer> { // 继承自BaseMapper接口提供了所有的基本CRUD操作
/** /**
* *
* @param paperId * @param paperId ID
* @param quId * @param quId ID
* @return * @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; // 定义该类所在的包路径
// 导入BaseMapper接口提供MyBatis-Plus的通用CRUD操作
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
// 导入PaperQuDetailDTO类表示试卷考题详细数据传输对象
import com.yf.exam.modules.paper.dto.ext.PaperQuDetailDTO; import com.yf.exam.modules.paper.dto.ext.PaperQuDetailDTO;
// 导入PaperQu实体类表示试卷考题的数据模型
import com.yf.exam.modules.paper.entity.PaperQu; import com.yf.exam.modules.paper.entity.PaperQu;
// 导入MyBatis的@Param注解用于方法参数与SQL查询中的参数进行映射
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
// 导入List接口用于返回多个试题
import java.util.List; import java.util.List;
/** /**
* <p> * <p>
* Mapper * Mapper
* </p> * </p>
* MyBatis-PlusBaseMapperCRUD
* *
* @author * @author
* @since 2020-05-25 16:33 * @since 2020-05-25 16:33
*/ */
public interface PaperQuMapper extends BaseMapper<PaperQu> { public interface PaperQuMapper extends BaseMapper<PaperQu> { // 继承自BaseMapper接口提供通用的CRUD操作
/** /**
* *
* @param paperId * @param paperId ID
* @return * @return
*/ */
int sumObjective(@Param("paperId") String paperId); int sumObjective(@Param("paperId") String paperId); // 根据试卷ID统计所有客观题的分数总和
/** /**
* *
* @param paperId * @param paperId ID
* @return * @return
*/ */
int sumSubjective(@Param("paperId") String paperId); int sumSubjective(@Param("paperId") String paperId); // 根据试卷ID统计所有主观题的分数总和
/** /**
* *
* @param paperId * @param paperId ID
* @return * @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; package com.yf.exam.modules.paper.service;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage; // 用于分页查询
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService; // 用于继承通用服务接口
import com.yf.exam.core.api.dto.PagingReqDTO; import com.yf.exam.core.api.dto.PagingReqDTO; // 分页请求DTO
import com.yf.exam.modules.paper.dto.PaperQuAnswerDTO; import com.yf.exam.modules.paper.dto.PaperQuAnswerDTO; // 试卷问题答案DTO
import com.yf.exam.modules.paper.dto.ext.PaperQuAnswerExtDTO; import com.yf.exam.modules.paper.dto.ext.PaperQuAnswerExtDTO; // 扩展的试卷问题答案DTO
import com.yf.exam.modules.paper.entity.PaperQuAnswer; import com.yf.exam.modules.paper.entity.PaperQuAnswer; // 试卷问题答案实体类
import java.util.List; import java.util.List; // 导入List类用于处理集合数据
/** /**
* <p> * <p>
* *
* </p> * </p>
*
* *
* @author * @author
* @since 2020-05-25 16:33 * @since 2020-05-25 16:33
@ -21,24 +23,24 @@ public interface PaperQuAnswerService extends IService<PaperQuAnswer> {
/** /**
* *
* @param reqDTO * @param reqDTO DTO
* @return * @return PaperQuAnswerDTO
*/ */
IPage<PaperQuAnswerDTO> paging(PagingReqDTO<PaperQuAnswerDTO> reqDTO); IPage<PaperQuAnswerDTO> paging(PagingReqDTO<PaperQuAnswerDTO> reqDTO);
/** /**
* *
* @param paperId * @param paperId ID
* @param quId * @param quId ID
* @return * @return PaperQuAnswerExtDTO
*/ */
List<PaperQuAnswerExtDTO> listForExam(String paperId, String quId); List<PaperQuAnswerExtDTO> listForExam(String paperId, String quId);
/** /**
* *
* @param paperId * @param paperId ID
* @param quId * @param quId ID
* @return * @return PaperQuAnswer
*/ */
List<PaperQuAnswer> listForFill(String paperId, String quId); List<PaperQuAnswer> listForFill(String paperId, String quId);
} }

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

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

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

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

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

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

@ -1,38 +1,58 @@
package com.yf.exam.modules.qu.dto; package com.yf.exam.modules.qu.dto;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel; // Swagger注解用于生成API文档
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty; // Swagger注解用于描述API模型的属性
import lombok.Data; import lombok.Data; // Lombok注解用于自动生成getter、setter等方法
import java.io.Serializable; import java.io.Serializable; // 可序列化接口
/** /**
* <p> * <p>
* *
* </p> * </p>
* *
* IDID
*
* @author * @author
* @since 2020-05-25 13:23 * @since 2020-05-25 13:23
*/ */
@Data @Data // Lombok注解自动生成getter、setter等方法
@ApiModel(value="试题题库", description="试题题库") @ApiModel(value="试题题库", description="试题题库")
public class QuRepoDTO implements Serializable { public class QuRepoDTO implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L; // 序列化版本UID
/**
private String id; * ID
*
@ApiModelProperty(value = "试题", required=true) */
private String quId; private String id; // 试题ID
@ApiModelProperty(value = "归属题库", required=true) /**
private String repoId; * ID
* ID
@ApiModelProperty(value = "题目类型", required=true) */
private Integer quType; @ApiModelProperty(value = "试题", required=true) // Swagger注解描述字段信息标明该字段是必填项
private String quId; // 题目ID
@ApiModelProperty(value = "排序", required=true)
private Integer sort; /**
* 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; package com.yf.exam.modules.qu.dto.export;
import com.yf.exam.core.utils.excel.annotation.ExcelField; import com.yf.exam.core.utils.excel.annotation.ExcelField; // Excel导出注解
import com.yf.exam.core.utils.excel.fieldtype.ListType; import com.yf.exam.core.utils.excel.fieldtype.ListType; // 用于处理List类型字段的特殊注解
import lombok.Data; import lombok.Data; // Lombok注解用于自动生成getter、setter、toString等方法
import java.util.List; import java.util.List; // 用于表示列表类型的字段
/** /**
* *
*
* 使DTO
* Excel
*
* @author bool * @author bool
*/ */
@Data @Data // Lombok注解自动生成getter、setter等方法
public class QuExportDTO { public class QuExportDTO {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L; // 序列化版本UID
/** /**
* * ID
*/ */
private String qId; private String qId; // 题目的唯一标识符
@ExcelField(title="题目序号", align=2, sort=1) @ExcelField(title="题目序号", align=2, sort=1) // 导出Excel时的列标题和排序align为居中对齐sort为排序位置
private String no; private String no; // 题目序号,表示题目的编号
@ExcelField(title="题目类型", align=2, sort=2)
private String quType; @ExcelField(title="题目类型", align=2, sort=2) // Excel导出列的标题和排序
@ExcelField(title="题目内容", align=2, sort=3) private String quType; // 题目类型,可能是单选题、多选题等
private String qContent;
@ExcelField(title="整体解析", align=2, sort=4) @ExcelField(title="题目内容", align=2, sort=3) // Excel导出列的标题和排序
private String qAnalysis; private String qContent; // 题目内容,包含问题的具体描述
@ExcelField(title="题目图片", align=2, sort=5)
private String qImage; @ExcelField(title="整体解析", align=2, sort=4) // Excel导出列的标题和排序
@ExcelField(title="题目视频", align=2, sort=6) private String qAnalysis; // 整个题目的解析说明
private String qVideo;
@ExcelField(title="所属题库", align=2, sort=7, fieldType = ListType.class) @ExcelField(title="题目图片", align=2, sort=5) // Excel导出列的标题和排序
private List<String> repoList; private String qImage; // 题目图片存储图片URL或路径
@ExcelField(title="是否正确项", align=2, sort=8)
private String aIsRight; @ExcelField(title="题目视频", align=2, sort=6) // Excel导出列的标题和排序
@ExcelField(title="选项内容", align=2, sort=9) private String qVideo; // 题目视频存储视频URL或路径
private String aContent;
@ExcelField(title="选项解析", align=2, sort=10) @ExcelField(title="所属题库", align=2, sort=7, fieldType = ListType.class) // 题库列表,支持导出多个题库
private String aAnalysis; private List<String> repoList; // 题目所属的题库列表
@ExcelField(title="选项图片", align=2, sort=11)
private String aImage; @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; package com.yf.exam.modules.qu.dto.export;
import com.yf.exam.modules.qu.dto.QuAnswerDTO; import com.yf.exam.modules.qu.dto.QuAnswerDTO; // 导入的选项答案DTO
import lombok.Data; import lombok.Data; // Lombok注解用于自动生成getter、setter、toString等方法
import java.util.List; import java.util.List; // 用于表示列表类型的字段
/** /**
* *
*
* DTO
*
*
* @author bool * @author bool
*/ */
@Data @Data // Lombok注解自动生成getter、setter等方法
public class QuImportDTO { 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; * 1234
private String qImage; */
private String repoName; private String quType; // 题目类型,表示题目的类别
private List<QuAnswerDTO> answerList;
/**
*
*
*/
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; package com.yf.exam.modules.qu.dto.ext;
import com.yf.exam.modules.qu.dto.QuAnswerDTO; import com.yf.exam.modules.qu.dto.QuAnswerDTO; // 引入选项答案DTO
import com.yf.exam.modules.qu.dto.QuDTO; import com.yf.exam.modules.qu.dto.QuDTO; // 引入问题题目DTO
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel; // Swagger注解用于生成API文档
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty; // Swagger注解用于描述API模型的属性
import lombok.Data; import lombok.Data; // Lombok注解用于自动生成getter、setter等方法
import java.util.List; import java.util.List; // 用于表示列表类型的字段
/** /**
* <p> * <p>
* *
* </p> * </p>
* *
* `QuDTO`
*
*
* @author * @author
* @since 2020-05-25 13:23 * @since 2020-05-25 13:23
*/ */
@Data @Data // Lombok注解自动生成getter、setter等方法
@ApiModel(value="问题题目详情", description="问题题目详情") @ApiModel(value="问题题目详情", description="问题题目详情")
public class QuDetailDTO extends QuDTO { 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; package com.yf.exam.modules.qu.dto.request;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel; // Swagger注解用于生成API文档
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty; // Swagger注解用于描述API模型的属性
import lombok.Data; import lombok.Data; // Lombok注解用于自动生成getter、setter等方法
import java.io.Serializable; import java.io.Serializable; // 可序列化接口
import java.util.List; import java.util.List; // 用于表示列表类型的字段
/** /**
* <p> * <p>
* *
* </p> * </p>
* *
*
* ID便
*
* @author * @author
* @since 2020-05-25 13:23 * @since 2020-05-25 13:23
*/ */
@Data @Data // Lombok注解自动生成getter、setter等方法
@ApiModel(value="题目查询请求类", description="题目查询请求类") @ApiModel(value="题目查询请求类", description="题目查询请求类")
public class QuQueryReqDTO implements Serializable { public class QuQueryReqDTO implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L; // 序列化版本UID
/**
@ApiModelProperty(value = "题目类型") *
private Integer quType; *
*/
@ApiModelProperty(value = "归属题库") @ApiModelProperty(value = "题目类型") // Swagger注解描述字段信息
private List<String> repoIds; private Integer quType; // 题目类型,通常是数字表示不同题型
@ApiModelProperty(value = "题目内容") /**
private String content; *
* ID
@ApiModelProperty(value = "排除ID列表") */
private List<String> excludes; @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; package com.yf.exam.modules.qu.dto.request;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel; // Swagger注解用于生成API文档
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty; // Swagger注解用于描述API模型的属性
import lombok.Data; import lombok.Data; // Lombok注解用于自动生成getter、setter等方法
import java.io.Serializable; import java.io.Serializable; // 可序列化接口
import java.util.List; import java.util.List; // 用于表示列表类型的字段
/** /**
* <p> * <p>
* *
* </p> * </p>
* *
*
*
*
* @author * @author
* @since 2020-05-25 13:23 * @since 2020-05-25 13:23
*/ */
@Data @Data // Lombok注解自动生成getter、setter等方法
@ApiModel(value="试题题库批量操作类", description="试题题库批量操作类") @ApiModel(value="试题题库批量操作类", description="试题题库批量操作类")
public class QuRepoBatchReqDTO implements Serializable { public class QuRepoBatchReqDTO implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L; // 序列化版本UID
/**
@ApiModelProperty(value = "题目ID", required=true) * ID
private List<String> quIds; * ID
*/
@ApiModelProperty(value = "题目类型", required=true) @ApiModelProperty(value = "题目ID", required=true) // Swagger注解描述字段信息标明该字段是必填项
private List<String> repoIds; private List<String> quIds; // 要操作的题目ID列表
@ApiModelProperty(value = "是否移除,否就新增;是就移除", required=true) /**
private Boolean remove; * 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; package com.yf.exam.modules.qu.entity;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType; // MyBatis Plus注解指定ID生成策略
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField; // MyBatis Plus注解指定字段映射
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId; // MyBatis Plus注解指定主键字段
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName; // MyBatis Plus注解指定表名
import com.baomidou.mybatisplus.extension.activerecord.Model; import com.baomidou.mybatisplus.extension.activerecord.Model; // MyBatis Plus扩展的活动记录模式类
import lombok.Data; import lombok.Data; // Lombok注解用于自动生成getter、setter等方法
import java.util.Date; import java.util.Date; // 日期类型
/** /**
* <p> * <p>
* *
* </p> * </p>
* *
* MyBatis-Plus
*
* @author * @author
* @since 2020-05-25 13:23 * @since 2020-05-25 13:23
*/ */
@Data @Data // Lombok注解自动生成getter、setter等方法
@TableName("el_qu") @TableName("el_qu") // MyBatis Plus注解指定与数据库表的映射关系
public class Qu extends Model<Qu> { public class Qu extends Model<Qu> {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L; // 序列化版本UID
/** /**
* ID * ID
*
*/ */
@TableId(value = "id", type = IdType.ASSIGN_ID) @TableId(value = "id", type = IdType.ASSIGN_ID) // MyBatis Plus注解指定主键生成策略为自定义ID
private String id; private String id; // 题目ID
/** /**
* *
*
*/ */
@TableField("qu_type") @TableField("qu_type") // MyBatis Plus注解指定字段名与数据库表字段名映射
private Integer quType; 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") @TableField("create_time") // MyBatis Plus注解映射数据库中的字段
private Date createTime; private Date createTime; // 创建时间
/** /**
* *
*
*/ */
@TableField("update_time") @TableField("update_time") // MyBatis Plus注解映射数据库中的字段
private Date updateTime; 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; package com.yf.exam.modules.qu.entity;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType; // MyBatis Plus注解指定ID生成策略
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField; // MyBatis Plus注解指定字段映射
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId; // MyBatis Plus注解指定主键字段
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName; // MyBatis Plus注解指定表名
import com.baomidou.mybatisplus.extension.activerecord.Model; import com.baomidou.mybatisplus.extension.activerecord.Model; // MyBatis Plus扩展的活动记录模式类
import lombok.Data; import lombok.Data; // Lombok注解用于自动生成getter、setter等方法
/** /**
* <p> * <p>
* *
* </p> * </p>
* *
* MyBatis-Plus
*
* @author * @author
* @since 2020-05-25 13:23 * @since 2020-05-25 13:23
*/ */
@Data @Data // Lombok注解自动生成getter、setter等方法
@TableName("el_qu_answer") @TableName("el_qu_answer") // MyBatis Plus注解指定与数据库表的映射关系
public class QuAnswer extends Model<QuAnswer> { public class QuAnswer extends Model<QuAnswer> {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L; // 序列化版本UID
/** /**
* ID * ID
*
*/ */
@TableId(value = "id", type = IdType.ASSIGN_ID) @TableId(value = "id", type = IdType.ASSIGN_ID) // MyBatis Plus注解指定主键生成策略为自定义ID
private String id; private String id; // 答案ID
/** /**
* ID * ID
* ID
*/ */
@TableField("qu_id") @TableField("qu_id") // MyBatis Plus注解指定字段名与数据库表字段名映射
private String quId; private String quId; // 问题ID
/** /**
* *
* truefalse
*/ */
@TableField("is_right") @TableField("is_right") // MyBatis Plus注解映射数据库中的字段
private Boolean isRight; 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; package com.yf.exam.modules.qu.entity;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType; // MyBatis Plus注解指定ID生成策略
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField; // MyBatis Plus注解指定字段映射
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId; // MyBatis Plus注解指定主键字段
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName; // MyBatis Plus注解指定表名
import com.baomidou.mybatisplus.extension.activerecord.Model; import com.baomidou.mybatisplus.extension.activerecord.Model; // MyBatis Plus扩展的活动记录模式类
import lombok.Data; import lombok.Data; // Lombok注解用于自动生成getter、setter等方法
/** /**
* <p> * <p>
* *
* </p> * </p>
* *
*
*
* @author * @author
* @since 2020-05-25 13:23 * @since 2020-05-25 13:23
*/ */
@Data @Data // Lombok注解自动生成getter、setter等方法
@TableName("el_qu_repo") @TableName("el_qu_repo") // MyBatis Plus注解指定与数据库表的映射关系
public class QuRepo extends Model<QuRepo> { 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") @TableField("qu_id") // MyBatis Plus注解指定字段名与数据库表字段名映射
private String quId; private String quId; // 试题ID
/** /**
* * ID
* ID
*/ */
@TableField("repo_id") @TableField("repo_id") // MyBatis Plus注解指定字段名与数据库表字段名映射
private String repoId; private String repoId; // 题库ID
/** /**
* *
*
*/ */
@TableField("qu_type") @TableField("qu_type") // MyBatis Plus注解映射数据库中的字段
private Integer quType; private Integer quType; // 题目类型
/** /**
* *
*
*/ */
private Integer sort; private Integer sort; // 排序
} }

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

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

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

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

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

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

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

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

@ -1,117 +1,113 @@
package com.yf.exam.modules.repo.controller; package com.yf.exam.modules.repo.controller; // 包名:表示该类属于 repo.controller 包
import com.baomidou.mybatisplus.core.metadata.IPage; // 导入所需的类和包
import com.yf.exam.core.api.ApiRest; import com.baomidou.mybatisplus.core.metadata.IPage; // 分页元数据接口
import com.yf.exam.core.api.controller.BaseController; import com.yf.exam.core.api.ApiRest; // 统一 API 响应类
import com.yf.exam.core.api.dto.BaseIdReqDTO; import com.yf.exam.core.api.controller.BaseController; // 控制器基类,提供通用控制功能
import com.yf.exam.core.api.dto.BaseIdsReqDTO; import com.yf.exam.core.api.dto.BaseIdReqDTO; // 数据传输对象,用于封装单个 ID 请求
import com.yf.exam.core.api.dto.PagingReqDTO; import com.yf.exam.core.api.dto.BaseIdsReqDTO; // 数据传输对象,用于封装多个 ID 请求
import com.yf.exam.modules.qu.dto.request.QuRepoBatchReqDTO; import com.yf.exam.core.api.dto.PagingReqDTO; // 数据传输对象,用于分页请求
import com.yf.exam.modules.qu.service.QuRepoService; import com.yf.exam.modules.qu.dto.request.QuRepoBatchReqDTO; // 数据传输对象,用于题库批量操作请求
import com.yf.exam.modules.repo.dto.RepoDTO; import com.yf.exam.modules.qu.service.QuRepoService; // 服务接口,用于题库的批量操作
import com.yf.exam.modules.repo.dto.request.RepoReqDTO; import com.yf.exam.modules.repo.dto.RepoDTO; // 数据传输对象,封装题库信息
import com.yf.exam.modules.repo.dto.response.RepoRespDTO; import com.yf.exam.modules.repo.dto.request.RepoReqDTO; // 数据传输对象,用于题库分页查询请求
import com.yf.exam.modules.repo.entity.Repo; import com.yf.exam.modules.repo.dto.response.RepoRespDTO; // 数据传输对象,用于题库分页查询响应
import com.yf.exam.modules.repo.service.RepoService; import com.yf.exam.modules.repo.entity.Repo; // 题库实体类
import io.swagger.annotations.Api; import com.yf.exam.modules.repo.service.RepoService; // 服务接口,用于题库操作
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.Api; // Swagger 注解,用于 API 文档生成
import org.apache.shiro.authz.annotation.RequiresRoles; import io.swagger.annotations.ApiOperation; // Swagger 注解,用于定义接口操作说明
import org.springframework.beans.BeanUtils; import org.apache.shiro.authz.annotation.RequiresRoles; // Shiro 注解,用于权限控制
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.BeanUtils; // 工具类,用于对象属性拷贝
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.beans.factory.annotation.Autowired; // Spring 注解,用于依赖注入
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestBody; // 注解,用于绑定请求体
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMapping; // 注解,用于定义请求路径
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RequestMethod; // 注解,用于指定 HTTP 请求方法
import org.springframework.web.bind.annotation.RestController; // 注解,标识为 REST 控制器
/** /**
* <p> * <p>
* *
* </p> * </p>
* *
* @author *
* @since 2020-05-25 13:25 * @
*/ * @ 2020-05-25 13:25
@Api(tags={"题库"}) */
@RestController @Api(tags = {"题库"}) // Swagger 注解:定义 API 文档中该控制器的标签为“题库”
@RequestMapping("/exam/api/repo") @RestController // Spring 注解:标识该类为 REST 控制器
public class RepoController extends BaseController { @RequestMapping("/exam/api/repo") // 定义请求路径前缀为 /exam/api/repo
public class RepoController extends BaseController { // 题库控制器类,继承基础控制器
@Autowired @Autowired // 自动注入题库服务
private RepoService baseService; private RepoService baseService;
@Autowired @Autowired // 自动注入题库批量操作服务
private QuRepoService quRepoService; private QuRepoService quRepoService;
/** /**
* *
* @param reqDTO * @param reqDTO
* @return * @return
*/ */
@RequiresRoles("sa") @RequiresRoles("sa") // 权限控制:要求用户具有 "sa" 角色
@ApiOperation(value = "添加或修改") @ApiOperation(value = "添加或修改") // Swagger 注解:定义接口操作说明为“添加或修改”
@RequestMapping(value = "/save", method = { RequestMethod.POST}) @RequestMapping(value = "/save", method = {RequestMethod.POST}) // 定义请求路径为 /save请求方法为 POST
public ApiRest save(@RequestBody RepoDTO reqDTO) { public ApiRest save(@RequestBody RepoDTO reqDTO) { // 添加或修改题库的方法
baseService.save(reqDTO); baseService.save(reqDTO); // 调用服务保存题库信息
return super.success(); return super.success(); // 返回成功结果
} }
/** /**
* *
* @param reqDTO * @param reqDTO ID
* @return * @return
*/ */
@RequiresRoles("sa") @RequiresRoles("sa") // 权限控制:要求用户具有 "sa" 角色
@ApiOperation(value = "批量删除") @ApiOperation(value = "批量删除") // Swagger 注解:定义接口操作说明为“批量删除”
@RequestMapping(value = "/delete", method = { RequestMethod.POST}) @RequestMapping(value = "/delete", method = {RequestMethod.POST}) // 定义请求路径为 /delete请求方法为 POST
public ApiRest edit(@RequestBody BaseIdsReqDTO reqDTO) { public ApiRest edit(@RequestBody BaseIdsReqDTO reqDTO) { // 批量删除题库的方法
//根据ID删除 baseService.removeByIds(reqDTO.getIds()); // 根据 ID 列表删除题库
baseService.removeByIds(reqDTO.getIds()); return super.success(); // 返回成功结果
return super.success();
} }
/** /**
* *
* @param reqDTO * @param reqDTO ID
* @return * @return
*/ */
@RequiresRoles("sa") @RequiresRoles("sa") // 权限控制:要求用户具有 "sa" 角色
@ApiOperation(value = "查找详情") @ApiOperation(value = "查找详情") // Swagger 注解:定义接口操作说明为“查找详情”
@RequestMapping(value = "/detail", method = { RequestMethod.POST}) @RequestMapping(value = "/detail", method = {RequestMethod.POST}) // 定义请求路径为 /detail请求方法为 POST
public ApiRest<RepoDTO> find(@RequestBody BaseIdReqDTO reqDTO) { public ApiRest<RepoDTO> find(@RequestBody BaseIdReqDTO reqDTO) { // 查找题库详情的方法
Repo entity = baseService.getById(reqDTO.getId()); Repo entity = baseService.getById(reqDTO.getId()); // 根据 ID 查找题库实体
RepoDTO dto = new RepoDTO(); RepoDTO dto = new RepoDTO(); // 创建题库数据传输对象
BeanUtils.copyProperties(entity, dto); BeanUtils.copyProperties(entity, dto); // 将实体属性拷贝到 DTO 中
return super.success(dto); return super.success(dto); // 返回成功结果,包含题库详情
} }
/** /**
* *
* @param reqDTO * @param reqDTO
* @return * @return
*/ */
@RequiresRoles("sa") @RequiresRoles("sa") // 权限控制:要求用户具有 "sa" 角色
@ApiOperation(value = "分页查找") @ApiOperation(value = "分页查找") // Swagger 注解:定义接口操作说明为“分页查找”
@RequestMapping(value = "/paging", method = { RequestMethod.POST}) @RequestMapping(value = "/paging", method = {RequestMethod.POST}) // 定义请求路径为 /paging请求方法为 POST
public ApiRest<IPage<RepoRespDTO>> paging(@RequestBody PagingReqDTO<RepoReqDTO> reqDTO) { public ApiRest<IPage<RepoRespDTO>> paging(@RequestBody PagingReqDTO<RepoReqDTO> reqDTO) { // 分页查找题库的方法
IPage<RepoRespDTO> page = baseService.paging(reqDTO); // 调用服务进行分页查询
//分页查询并转换 return super.success(page); // 返回成功结果,包含分页数据
IPage<RepoRespDTO> page = baseService.paging(reqDTO);
return super.success(page);
} }
/** /**
* *
* @param reqDTO * @param reqDTO
* @return * @return
*/ */
@RequiresRoles("sa") @RequiresRoles("sa") // 权限控制:要求用户具有 "sa" 角色
@ApiOperation(value = "批量操作", notes = "批量加入或从题库移除") @ApiOperation(value = "批量操作", notes = "批量加入或从题库移除") // Swagger 注解:定义接口操作说明为“批量操作”,并提供备注
@RequestMapping(value = "/batch-action", method = { RequestMethod.POST}) @RequestMapping(value = "/batch-action", method = {RequestMethod.POST}) // 定义请求路径为 /batch-action请求方法为 POST
public ApiRest batchAction(@RequestBody QuRepoBatchReqDTO reqDTO) { public ApiRest batchAction(@RequestBody QuRepoBatchReqDTO reqDTO) { // 批量操作题库的方法
quRepoService.batchAction(reqDTO); // 调用服务执行批量操作
//分页查询并转换 return super.success(); // 返回成功结果
quRepoService.batchAction(reqDTO);
return super.success();
} }
} }

@ -1,43 +1,42 @@
package com.yf.exam.modules.repo.dto; package com.yf.exam.modules.repo.dto; // 包名:表示该类属于 repo.dto 包
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel; // 导入 Swagger 注解,用于定义 API 模型
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty; // 导入 Swagger 注解,用于描述 API 模型的属性
import lombok.Data; import lombok.Data; // 导入 Lombok 注解,用于自动生成 Getter、Setter、toString 等方法
import java.io.Serializable; import java.io.Serializable; // 导入 Serializable 接口,用于支持序列化
import java.util.Date; import java.util.Date; // 导入 Date 类,用于处理日期和时间
/** /**
* <p> * <p>
* *
* </p> * </p>
* *
* @author *
* @since 2020-05-25 13:23 * @
*/ * @ 2020-05-25 13:23
@Data */
@ApiModel(value="题库", description="题库") @Data // Lombok 注解,自动生成 Getter、Setter 和其他方法
public class RepoDTO implements Serializable { @ApiModel(value = "题库", description = "题库") // Swagger 注解,定义该类的 API 模型名称及描述
public class RepoDTO implements Serializable { // 定义类 RepoDTO实现 Serializable 接口以支持序列化
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L; // 序列化版本号,用于序列化和反序列化的一致性检查
@ApiModelProperty(value = "题库ID", required = true) // Swagger 注解,描述该属性为“题库 ID”
private String id; // 定义属性:题库的唯一标识符
@ApiModelProperty(value = "题库ID", required=true) @ApiModelProperty(value = "题库编号", required = true) // Swagger 注解,描述该属性为“题库编号”
private String id; private String code; // 定义属性:题库编号
@ApiModelProperty(value = "题库编号", required=true) @ApiModelProperty(value = "题库名称", required = true) // Swagger 注解,描述该属性为“题库名称”
private String code; private String title; // 定义属性:题库名称
@ApiModelProperty(value = "题库名称", required=true) @ApiModelProperty(value = "题库备注", required = true) // Swagger 注解,描述该属性为“题库备注”
private String title; private String remark; // 定义属性:题库备注信息
@ApiModelProperty(value = "题库备注", required=true) @ApiModelProperty(value = "创建时间", required = true) // Swagger 注解,描述该属性为“创建时间”
private String remark; private Date createTime; // 定义属性:题库的创建时间
@ApiModelProperty(value = "创建时间", required=true)
private Date createTime;
@ApiModelProperty(value = "更新时间", required=true)
private Date updateTime;
@ApiModelProperty(value = "更新时间", required = true) // Swagger 注解,描述该属性为“更新时间”
private Date updateTime; // 定义属性:题库的最后更新时间
} }

@ -1,30 +1,30 @@
package com.yf.exam.modules.repo.dto.request; package com.yf.exam.modules.repo.dto.request; // 包名:表示该类属于 repo.dto.request 包
import com.yf.exam.modules.repo.dto.RepoDTO; import com.yf.exam.modules.repo.dto.RepoDTO; // 导入 RepoDTO 类,题库数据传输对象
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel; // 导入 Swagger 注解,用于定义 API 模型
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty; // 导入 Swagger 注解,用于描述 API 模型的属性
import lombok.Data; import lombok.Data; // 导入 Lombok 注解,用于自动生成 Getter、Setter、toString 等方法
import java.util.List; import java.util.List; // 导入 Java 的 List 接口,用于存储排除的题库 ID 列表
/** /**
* <p> * <p>
* *
* </p> * </p>
* *
* @author *
* @since 2020-05-25 13:23 * @
*/ * @ 2020-05-25 13:23
@Data */
@ApiModel(value="题库分页请求类", description="题库分页请求类") @Data // Lombok 注解,自动生成 Getter、Setter 和其他方法
public class RepoReqDTO extends RepoDTO { @ApiModel(value = "题库分页请求类", description = "题库分页请求类") // Swagger 注解,定义该类的 API 模型名称及描述
public class RepoReqDTO extends RepoDTO { // 定义类 RepoReqDTO继承自 RepoDTO
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L; // 序列化版本号,用于序列化和反序列化的一致性检查
@ApiModelProperty(value = "排除题库ID", required=true) @ApiModelProperty(value = "排除题库ID", required = true) // Swagger 注解,描述该属性为“需要排除的题库 ID 列表”
private List<String> excludes; private List<String> excludes; // 定义属性:排除的题库 ID 列表
@ApiModelProperty(value = "单选题数量", required=true)
private String title;
@ApiModelProperty(value = "单选题数量", required = true) // Swagger 注解,描述该属性为“单选题数量”
private String title; // 定义属性:单选题数量(注意:变量名可能存在歧义,建议确认或重命名)
} }

@ -1,31 +1,31 @@
package com.yf.exam.modules.repo.dto.response; package com.yf.exam.modules.repo.dto.response; // 包名:表示该类属于 repo.dto.response 包
import com.yf.exam.modules.repo.dto.RepoDTO; import com.yf.exam.modules.repo.dto.RepoDTO; // 导入 RepoDTO 类,题库通用数据传输对象
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel; // 导入 Swagger 注解,用于定义 API 模型
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty; // 导入 Swagger 注解,用于描述 API 模型的属性
import lombok.Data; import lombok.Data; // 导入 Lombok 注解,用于自动生成 Getter、Setter、toString 等方法
/** /**
* <p> * <p>
* *
* </p> * </p>
* *
* @author *
* @since 2020-05-25 13:23 * @
*/ * @ 2020-05-25 13:23
@Data */
@ApiModel(value="题库分页响应类", description="题库分页响应类") @Data // Lombok 注解,自动生成 Getter、Setter 和其他方法
public class RepoRespDTO extends RepoDTO { @ApiModel(value = "题库分页响应类", description = "题库分页响应类") // Swagger 注解,定义该类的 API 模型名称及描述
public class RepoRespDTO extends RepoDTO { // 定义类 RepoRespDTO继承自 RepoDTO
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L; // 序列化版本号,用于序列化和反序列化的一致性检查
@ApiModelProperty(value = "多选题数量", required=true) @ApiModelProperty(value = "多选题数量", required = true) // Swagger 注解,描述该属性为“多选题数量”
private Integer multiCount; private Integer multiCount; // 定义属性:多选题的数量
@ApiModelProperty(value = "单选题数量", required=true) @ApiModelProperty(value = "单选题数量", required = true) // Swagger 注解,描述该属性为“单选题数量”
private Integer radioCount; private Integer radioCount; // 定义属性:单选题的数量
@ApiModelProperty(value = "判断题数量", required=true)
private Integer judgeCount;
@ApiModelProperty(value = "判断题数量", required = true) // Swagger 注解,描述该属性为“判断题数量”
private Integer judgeCount; // 定义属性:判断题的数量
} }

@ -1,59 +1,59 @@
package com.yf.exam.modules.repo.entity; package com.yf.exam.modules.repo.entity; // 包名:表示该类属于 repo.entity 包
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType; // 导入 MyBatis-Plus 注解,用于定义主键类型
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField; // 导入 MyBatis-Plus 注解,用于映射数据库字段
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId; // 导入 MyBatis-Plus 注解,用于标识主键字段
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName; // 导入 MyBatis-Plus 注解,用于映射数据库表名
import com.baomidou.mybatisplus.extension.activerecord.Model; import com.baomidou.mybatisplus.extension.activerecord.Model; // 导入 MyBatis-Plus ActiveRecord 模式基类
import lombok.Data; import lombok.Data; // 导入 Lombok 注解,用于自动生成 Getter、Setter、toString 等方法
import java.util.Date; import java.util.Date; // 导入 Java 的 Date 类,用于表示日期和时间
/** /**
* <p> * <p>
* *
* </p> * </p>
* *
* @author *
* @since 2020-05-25 13:23 * @
*/ * @ 2020-05-25 13:23
@Data */
@TableName("el_repo") @Data // Lombok 注解,自动生成 Getter、Setter 和其他方法
public class Repo extends Model<Repo> { @TableName("el_repo") // MyBatis-Plus 注解,指定该实体类映射的数据库表名为 "el_repo"
public class Repo extends Model<Repo> { // 定义类 Repo继承 MyBatis-Plus 的 Model 类以支持 ActiveRecord 模式
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L; // 序列化版本号,用于序列化和反序列化的一致性检查
/** /**
* ID * ID
*/ */
@TableId(value = "id", type = IdType.ASSIGN_ID) @TableId(value = "id", type = IdType.ASSIGN_ID) // MyBatis-Plus 注解,标识主键字段,并指定主键生成策略为分配 ID
private String id; private String id; // 定义字段:题库的唯一标识符
/** /**
* *
*/ */
private String code; private String code; // 定义字段:题库编号
/** /**
* *
*/ */
private String title; private String title; // 定义字段:题库名称
/** /**
* *
*/ */
private String remark; private String remark; // 定义字段:题库备注信息
/** /**
* *
*/ */
@TableField("create_time") @TableField("create_time") // MyBatis-Plus 注解,指定该字段映射数据库中的 "create_time" 列
private Date createTime; private Date createTime; // 定义字段:题库的创建时间
/** /**
* *
*/ */
@TableField("update_time") @TableField("update_time") // MyBatis-Plus 注解,指定该字段映射数据库中的 "update_time" 列
private Date updateTime; private Date updateTime; // 定义字段:题库的最后更新时间
} }

@ -1,29 +1,29 @@
package com.yf.exam.modules.repo.mapper; package com.yf.exam.modules.repo.mapper; // 包名:表示该类属于 repo.mapper 包
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; // 导入 MyBatis-Plus 的 BaseMapper 接口,用于基本的数据库操作
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage; // 导入 MyBatis-Plus 分页接口
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; // 导入 MyBatis-Plus 分页插件中的 Page 类
import com.yf.exam.modules.repo.dto.request.RepoReqDTO; import com.yf.exam.modules.repo.dto.request.RepoReqDTO; // 导入用于分页查询的请求数据传输对象 RepoReqDTO
import com.yf.exam.modules.repo.dto.response.RepoRespDTO; import com.yf.exam.modules.repo.dto.response.RepoRespDTO; // 导入用于分页查询的响应数据传输对象 RepoRespDTO
import com.yf.exam.modules.repo.entity.Repo; import com.yf.exam.modules.repo.entity.Repo; // 导入题库实体类 Repo
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param; // 导入 MyBatis 注解,用于标注参数
/** /**
* <p> * <p>
* Mapper * Mapper
* </p> * </p>
* * Mapper
* @author *
* @since 2020-05-25 13:23 * @
*/ * @ 2020-05-25 13:23
public interface RepoMapper extends BaseMapper<Repo> { */
public interface RepoMapper extends BaseMapper<Repo> { // RepoMapper 接口,继承自 MyBatis-Plus 的 BaseMapper提供常见的数据库操作
/** /**
* *
* @param page * @param page
* @param query * @param query
* @return * @return
*/ */
IPage<RepoRespDTO> paging(Page page, @Param("query") RepoReqDTO query); IPage<RepoRespDTO> paging(Page page, @Param("query") RepoReqDTO query); // 自定义分页查询方法,返回题库分页响应数据
} }

@ -1,34 +1,34 @@
package com.yf.exam.modules.repo.service; package com.yf.exam.modules.repo.service; // 包名:表示该类属于 repo.service 包
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage; // 导入 MyBatis-Plus 分页接口
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService; // 导入 MyBatis-Plus 服务接口,提供通用的数据库操作
import com.yf.exam.core.api.dto.PagingReqDTO; import com.yf.exam.core.api.dto.PagingReqDTO; // 导入分页请求数据传输对象
import com.yf.exam.modules.repo.dto.RepoDTO; import com.yf.exam.modules.repo.dto.RepoDTO; // 导入 RepoDTO 类,题库数据传输对象
import com.yf.exam.modules.repo.dto.request.RepoReqDTO; import com.yf.exam.modules.repo.dto.request.RepoReqDTO; // 导入 RepoReqDTO 类,用于封装分页查询条件
import com.yf.exam.modules.repo.dto.response.RepoRespDTO; import com.yf.exam.modules.repo.dto.response.RepoRespDTO; // 导入 RepoRespDTO 类,题库分页响应数据传输对象
import com.yf.exam.modules.repo.entity.Repo; import com.yf.exam.modules.repo.entity.Repo; // 导入 Repo 实体类,表示题库
/** /**
* <p> * <p>
* *
* </p> * </p>
* * MyBatis-Plus IService
* @author *
* @since 2020-05-25 13:23 * @
*/ * @ 2020-05-25 13:23
public interface RepoService extends IService<Repo> { */
public interface RepoService extends IService<Repo> { // RepoService 接口,继承 MyBatis-Plus 的 IService提供常见数据库操作
/** /**
* *
* @param reqDTO * @param reqDTO
* @return * @return
*/ */
IPage<RepoRespDTO> paging(PagingReqDTO<RepoReqDTO> reqDTO); IPage<RepoRespDTO> paging(PagingReqDTO<RepoReqDTO> reqDTO); // 分页查询方法,接收分页请求数据对象,并返回分页结果
/** /**
* *
* @param reqDTO * @param reqDTO
*/ */
void save(RepoDTO reqDTO); void save(RepoDTO reqDTO); // 保存题库方法,用于保存或更新题库信息
} }

@ -1,39 +1,49 @@
package com.yf.exam.modules.repo.service.impl; package com.yf.exam.modules.repo.service.impl; // 包名:表示该类属于 repo.service.impl 包
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage; // 导入 MyBatis-Plus 分页接口
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; // 导入 MyBatis-Plus 服务实现类,用于提供通用的数据库操作
import com.yf.exam.core.api.dto.PagingReqDTO; import com.yf.exam.core.api.dto.PagingReqDTO; // 导入分页请求数据传输对象
import com.yf.exam.core.utils.BeanMapper; import com.yf.exam.core.utils.BeanMapper; // 导入 BeanMapper 工具类,用于对象属性拷贝
import com.yf.exam.modules.repo.dto.RepoDTO; import com.yf.exam.modules.repo.dto.RepoDTO; // 导入 RepoDTO题库数据传输对象
import com.yf.exam.modules.repo.dto.request.RepoReqDTO; import com.yf.exam.modules.repo.dto.request.RepoReqDTO; // 导入 RepoReqDTO封装分页查询条件的请求数据传输对象
import com.yf.exam.modules.repo.dto.response.RepoRespDTO; import com.yf.exam.modules.repo.dto.response.RepoRespDTO; // 导入 RepoRespDTO题库分页响应数据传输对象
import com.yf.exam.modules.repo.entity.Repo; import com.yf.exam.modules.repo.entity.Repo; // 导入 Repo 实体类,表示题库实体
import com.yf.exam.modules.repo.mapper.RepoMapper; import com.yf.exam.modules.repo.mapper.RepoMapper; // 导入 RepoMapper数据访问层接口
import com.yf.exam.modules.repo.service.RepoService; import com.yf.exam.modules.repo.service.RepoService; // 导入 RepoService题库服务接口
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service; // 导入 Spring 的 Service 注解,标识该类为服务层组件
/** /**
* <p> * <p>
* *
* </p> * </p>
* * RepoService
* @author *
* @since 2020-05-25 13:23 * @
*/ * @ 2020-05-25 13:23
@Service */
public class RepoServiceImpl extends ServiceImpl<RepoMapper, Repo> implements RepoService { @Service // Spring 注解,标识该类为服务层组件
public class RepoServiceImpl extends ServiceImpl<RepoMapper, Repo> implements RepoService { // 继承 MyBatis-Plus 提供的 ServiceImpl简化数据库操作
/**
*
* @param reqDTO
* @return
*/
@Override @Override
public IPage<RepoRespDTO> paging(PagingReqDTO<RepoReqDTO> reqDTO) { public IPage<RepoRespDTO> paging(PagingReqDTO<RepoReqDTO> reqDTO) {
return baseMapper.paging(reqDTO.toPage(), reqDTO.getParams()); return baseMapper.paging(reqDTO.toPage(), reqDTO.getParams()); // 调用 Mapper 的分页查询方法,传入分页信息和查询条件
} }
/**
*
* @param reqDTO
*/
@Override @Override
public void save(RepoDTO reqDTO) { public void save(RepoDTO reqDTO) {
//复制参数 // 复制参数,将请求数据传输对象的属性复制到实体类中
Repo entity = new Repo(); Repo entity = new Repo(); // 创建 Repo 实体对象
BeanMapper.copy(reqDTO, entity); BeanMapper.copy(reqDTO, entity); // 使用 BeanMapper 工具类复制属性
this.saveOrUpdate(entity); this.saveOrUpdate(entity); // 调用 MyBatis-Plus 提供的 saveOrUpdate 方法,保存或更新实体
} }
} }

@ -1,70 +1,71 @@
package com.yf.exam.modules.sys.config.controller; package com.yf.exam.modules.sys.config.controller; // 包名:表示该类属于 sys.config.controller 包
import com.yf.exam.core.api.ApiRest; import com.yf.exam.core.api.ApiRest; // 导入统一的 API 响应类
import com.yf.exam.core.api.controller.BaseController; import com.yf.exam.core.api.controller.BaseController; // 导入控制器基类,提供通用的控制器功能
import com.yf.exam.core.api.dto.BaseIdRespDTO; import com.yf.exam.core.api.dto.BaseIdRespDTO; // 导入基础响应 DTO用于返回 ID 响应
import com.yf.exam.core.utils.BeanMapper; import com.yf.exam.core.utils.BeanMapper; // 导入 BeanMapper 工具类,用于对象属性拷贝
import com.yf.exam.modules.qu.utils.ImageCheckUtils; import com.yf.exam.modules.qu.utils.ImageCheckUtils; // 导入图片检查工具类,用于校验图片地址
import com.yf.exam.modules.sys.config.dto.SysConfigDTO; import com.yf.exam.modules.sys.config.dto.SysConfigDTO; // 导入 SysConfigDTO 类,用于封装系统配置的数据传输对象
import com.yf.exam.modules.sys.config.entity.SysConfig; import com.yf.exam.modules.sys.config.entity.SysConfig; // 导入 SysConfig 实体类,表示系统配置
import com.yf.exam.modules.sys.config.service.SysConfigService; import com.yf.exam.modules.sys.config.service.SysConfigService; // 导入 SysConfigService 服务接口
import io.swagger.annotations.Api; import io.swagger.annotations.Api; // 导入 Swagger 注解,用于 API 文档生成
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation; // 导入 Swagger 注解,用于定义接口操作说明
import org.apache.shiro.authz.annotation.RequiresRoles; import org.apache.shiro.authz.annotation.RequiresRoles; // 导入 Shiro 权限控制注解,限制角色访问
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired; // 导入 Spring 注解,用于依赖注入
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody; // 导入注解,用于绑定请求体
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping; // 导入注解,用于定义请求路径
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod; // 导入注解,用于指定请求方法
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController; // 导入注解,标识该类为 REST 控制器
/** /**
* <p> * <p>
* *
* </p> * </p>
* *
* @author *
* @since 2020-04-17 09:12 * @
*/ * @ 2020-04-17 09:12
@Api(tags={"通用配置"}) */
@RestController @Api(tags = {"通用配置"}) // Swagger 注解:定义该类的 API 文档标签为“通用配置”
@RequestMapping("/exam/api/sys/config") @RestController // Spring 注解:标识该类为 REST 控制器
public class SysConfigController extends BaseController { @RequestMapping("/exam/api/sys/config") // 定义请求路径前缀为 /exam/api/sys/config
public class SysConfigController extends BaseController { // SysConfigController 类,继承自 BaseController提供通用功能
@Autowired @Autowired // 自动注入 SysConfigService 服务
private SysConfigService baseService; private SysConfigService baseService;
@Autowired @Autowired // 自动注入 ImageCheckUtils 工具类
private ImageCheckUtils imageCheckUtils; private ImageCheckUtils imageCheckUtils;
/** /**
* *
* @param reqDTO * @param reqDTO
* @return * @return ID
*/ */
@RequiresRoles("sa") @RequiresRoles("sa") // 权限控制:要求用户具有 "sa" 角色
@ApiOperation(value = "添加或修改") @ApiOperation(value = "添加或修改") // Swagger 注解:定义接口操作说明为“添加或修改”
@RequestMapping(value = "/save", method = { RequestMethod.POST}) @RequestMapping(value = "/save", method = { RequestMethod.POST}) // 定义请求路径为 /save方法为 POST
public ApiRest<BaseIdRespDTO> save(@RequestBody SysConfigDTO reqDTO) { public ApiRest<BaseIdRespDTO> save(@RequestBody SysConfigDTO reqDTO) { // 定义保存或修改系统配置的方法
//复制参数 // 复制请求参数到实体对象
SysConfig entity = new SysConfig(); SysConfig entity = new SysConfig(); // 创建 SysConfig 实体对象
BeanMapper.copy(reqDTO, entity); BeanMapper.copy(reqDTO, entity); // 使用 BeanMapper 工具类将 DTO 的属性拷贝到实体对象
// 校验图片地址 // 校验图片地址是否有效
imageCheckUtils.checkImage(entity.getBackLogo(), "系统LOGO地址错误"); imageCheckUtils.checkImage(entity.getBackLogo(), "系统LOGO地址错误"); // 检查系统LOGO地址是否有效
baseService.saveOrUpdate(entity); baseService.saveOrUpdate(entity); // 调用服务的保存或更新方法
return super.success(new BaseIdRespDTO(entity.getId())); return super.success(new BaseIdRespDTO(entity.getId())); // 返回成功响应,并包含系统配置 ID
} }
/** /**
* *
* @return * @return
*/ */
@ApiOperation(value = "查找详情") @ApiOperation(value = "查找详情") // Swagger 注解:定义接口操作说明为“查找详情”
@RequestMapping(value = "/detail", method = { RequestMethod.POST}) @RequestMapping(value = "/detail", method = { RequestMethod.POST}) // 定义请求路径为 /detail方法为 POST
public ApiRest<SysConfigDTO> find() { public ApiRest<SysConfigDTO> find() { // 定义查找系统配置详情的方法
SysConfigDTO dto = baseService.find(); SysConfigDTO dto = baseService.find(); // 调用服务查找系统配置详情
return super.success(dto); return super.success(dto); // 返回成功响应,包含系统配置详情
} }
} }

@ -1,39 +1,38 @@
package com.yf.exam.modules.sys.config.dto; package com.yf.exam.modules.sys.config.dto; // 包名:表示该类属于 sys.config.dto 包
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel; // 导入 Swagger 注解,用于定义 API 模型
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty; // 导入 Swagger 注解,用于描述 API 模型的属性
import lombok.Data; import lombok.Data; // 导入 Lombok 注解,用于自动生成 Getter、Setter、toString 等方法
import java.io.Serializable; import java.io.Serializable; // 导入 Serializable 接口,用于对象序列化
/** /**
* <p> * <p>
* *
* </p> * </p>
* * API
* @author *
* @since 2020-04-17 09:12 * @
*/ * @ 2020-04-17 09:12
@Data */
@ApiModel(value="通用配置", description="通用配置") @Data // Lombok 注解,自动生成 Getter、Setter 和其他方法
public class SysConfigDTO implements Serializable { @ApiModel(value = "通用配置", description = "通用配置") // Swagger 注解:定义该类的 API 模型名称和描述
public class SysConfigDTO implements Serializable { // 定义 SysConfigDTO 类,实现 Serializable 接口以支持序列化
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L; // 序列化版本号,用于序列化和反序列化的一致性检查
@ApiModelProperty(value = "ID", required=true) @ApiModelProperty(value = "ID", required = true) // Swagger 注解描述该属性为“ID”并标记为必填
private String id; private String id; // 定义字段:系统配置的唯一标识符
@ApiModelProperty(value = "系统名称") @ApiModelProperty(value = "系统名称") // Swagger 注解:描述该属性为“系统名称”
private String siteName; private String siteName; // 定义字段:系统名称
@ApiModelProperty(value = "前端LOGO") @ApiModelProperty(value = "前端LOGO") // Swagger 注解描述该属性为“前端LOGO”
private String frontLogo; private String frontLogo; // 定义字段:前端展示用的 LOGO 图片地址
@ApiModelProperty(value = "后台LOGO") @ApiModelProperty(value = "后台LOGO") // Swagger 注解描述该属性为“后台LOGO”
private String backLogo; private String backLogo; // 定义字段:后台管理用的 LOGO 图片地址
@ApiModelProperty(value = "版权信息") @ApiModelProperty(value = "版权信息") // Swagger 注解:描述该属性为“版权信息”
private String copyRight; private String copyRight; // 定义字段:版权信息
} }

@ -1,53 +1,54 @@
package com.yf.exam.modules.sys.config.entity; package com.yf.exam.modules.sys.config.entity; // 包名:表示该类属于 sys.config.entity 包
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType; // 导入 MyBatis-Plus 注解,用于定义主键类型
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField; // 导入 MyBatis-Plus 注解,用于映射数据库字段
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId; // 导入 MyBatis-Plus 注解,用于标识主键字段
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName; // 导入 MyBatis-Plus 注解,用于映射数据库表名
import com.baomidou.mybatisplus.extension.activerecord.Model; import com.baomidou.mybatisplus.extension.activerecord.Model; // 导入 MyBatis-Plus ActiveRecord 模式基类
import lombok.Data; import lombok.Data; // 导入 Lombok 注解,用于自动生成 Getter、Setter、toString 等方法
/** /**
* <p> * <p>
* *
* </p> * </p>
* * `sys_config`
* @author *
* @since 2020-04-17 09:12 * @
*/ * @ 2020-04-17 09:12
@Data */
@TableName("sys_config") @Data // Lombok 注解,自动生成 Getter、Setter 和其他方法
public class SysConfig extends Model<SysConfig> { @TableName("sys_config") // MyBatis-Plus 注解,指定该实体类映射数据库表名为 `sys_config`
public class SysConfig extends Model<SysConfig> { // SysConfig 类继承自 MyBatis-Plus 的 Model 类,启用 ActiveRecord 模式
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L; // 序列化版本号,用于序列化和反序列化的一致性检查
/** /**
* ID * ID
*/ */
@TableId(value = "id", type = IdType.ASSIGN_ID) @TableId(value = "id", type = IdType.ASSIGN_ID) // MyBatis-Plus 注解,标识主键字段,并指定主键生成策略为分配 ID
private String id; private String id; // 定义字段:系统配置的唯一标识符
/** /**
* *
*/ */
@TableField("site_name") @TableField("site_name") // MyBatis-Plus 注解,指定该字段映射数据库中的 "site_name" 列
private String siteName; private String siteName; // 定义字段:系统名称
/** /**
* LOGO * LOGO
*/ */
@TableField("front_logo") @TableField("front_logo") // MyBatis-Plus 注解,指定该字段映射数据库中的 "front_logo" 列
private String frontLogo; private String frontLogo; // 定义字段:前端展示的 LOGO 图片地址
/** /**
* LOGO * LOGO
*/ */
@TableField("back_logo") @TableField("back_logo") // MyBatis-Plus 注解,指定该字段映射数据库中的 "back_logo" 列
private String backLogo; private String backLogo; // 定义字段:后台管理系统的 LOGO 图片地址
/** /**
* *
*/ */
@TableField("copy_right") @TableField("copy_right") // MyBatis-Plus 注解,指定该字段映射数据库中的 "copy_right" 列
private String copyRight; private String copyRight; // 定义字段:版权信息
} }

@ -1,16 +1,18 @@
package com.yf.exam.modules.sys.config.mapper; package com.yf.exam.modules.sys.config.mapper; // 包名:表示该类属于 sys.config.mapper 包
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; // 导入 MyBatis-Plus 的 BaseMapper 接口,用于基本的数据库操作
import com.yf.exam.modules.sys.config.entity.SysConfig; import com.yf.exam.modules.sys.config.entity.SysConfig; // 导入 SysConfig 实体类,表示系统配置
/** /**
* <p> * <p>
* Mapper * Mapper
* </p> * </p>
* * MyBatis-Plus BaseMapper
* @author *
* @since 2020-04-17 09:12 * @
*/ * @ 2020-04-17 09:12
public interface SysConfigMapper extends BaseMapper<SysConfig> { */
public interface SysConfigMapper extends BaseMapper<SysConfig> { // SysConfigMapper 接口,继承自 MyBatis-Plus 的 BaseMapper
// 该接口继承了 BaseMapper<SysConfig>,因此自动具备了 CRUD 方法,无需手动实现
} }

@ -1,22 +1,23 @@
package com.yf.exam.modules.sys.config.service; package com.yf.exam.modules.sys.config.service; // 包名:表示该类属于 sys.config.service 包
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService; // 导入 MyBatis-Plus 提供的 IService 接口,提供通用的数据库操作
import com.yf.exam.modules.sys.config.dto.SysConfigDTO; import com.yf.exam.modules.sys.config.dto.SysConfigDTO; // 导入 SysConfigDTO 类,封装系统配置的数据传输对象
import com.yf.exam.modules.sys.config.entity.SysConfig; import com.yf.exam.modules.sys.config.entity.SysConfig; // 导入 SysConfig 实体类,表示系统配置
/** /**
* <p> * <p>
* *
* </p> * </p>
* *
* @author *
* @since 2020-04-17 09:12 * @
*/ * @ 2020-04-17 09:12
public interface SysConfigService extends IService<SysConfig> { */
public interface SysConfigService extends IService<SysConfig> { // SysConfigService 接口继承 MyBatis-Plus 的 IService 接口,提供 CRUD 操作
/** /**
* *
* @return * @return DTO
*/ */
SysConfigDTO find(); SysConfigDTO find(); // 定义查找系统配置信息的方法,返回一个 SysConfigDTO 对象
} }

@ -1,34 +1,44 @@
package com.yf.exam.modules.sys.config.service.impl; package com.yf.exam.modules.sys.config.service.impl; // 包名:表示该类属于 sys.config.service.impl 包
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; // 导入 MyBatis-Plus 的 QueryWrapper用于构建查询条件
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; // 导入 MyBatis-Plus 的 ServiceImpl 类,用于提供常见的数据库操作
import com.yf.exam.core.utils.BeanMapper; import com.yf.exam.core.utils.BeanMapper; // 导入 BeanMapper 工具类,用于对象属性拷贝
import com.yf.exam.modules.sys.config.dto.SysConfigDTO; import com.yf.exam.modules.sys.config.dto.SysConfigDTO; // 导入 SysConfigDTO 类,封装系统配置的数据传输对象
import com.yf.exam.modules.sys.config.entity.SysConfig; import com.yf.exam.modules.sys.config.entity.SysConfig; // 导入 SysConfig 实体类,表示系统配置
import com.yf.exam.modules.sys.config.mapper.SysConfigMapper; import com.yf.exam.modules.sys.config.mapper.SysConfigMapper; // 导入 SysConfigMapper数据访问层接口
import com.yf.exam.modules.sys.config.service.SysConfigService; import com.yf.exam.modules.sys.config.service.SysConfigService; // 导入 SysConfigService系统配置服务接口
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service; // 导入 Spring 注解,用于标识该类为服务层组件
/** /**
* <p> * <p>
* *
* </p> * </p>
* * SysConfigService
* @author *
* @since 2020-04-17 09:12 * @
*/ * @ 2020-04-17 09:12
@Service */
public class SysConfigServiceImpl extends ServiceImpl<SysConfigMapper, SysConfig> implements SysConfigService { @Service // Spring 注解,标识该类为服务层组件
public class SysConfigServiceImpl extends ServiceImpl<SysConfigMapper, SysConfig> implements SysConfigService { // 继承 MyBatis-Plus 的 ServiceImpl 类,简化数据库操作
/**
*
* @return DTO
*/
@Override @Override
public SysConfigDTO find() { public SysConfigDTO find() {
// 创建 QueryWrapper 对象,用于构建查询条件
QueryWrapper<SysConfig> wrapper = new QueryWrapper<>(); QueryWrapper<SysConfig> wrapper = new QueryWrapper<>();
wrapper.last(" LIMIT 1"); wrapper.last(" LIMIT 1"); // 限制查询结果为一条记录
SysConfig entity = this.getOne(wrapper, false); // 使用 getOne 方法查询系统配置的第一条记录
SysConfigDTO dto = new SysConfigDTO(); SysConfig entity = this.getOne(wrapper, false); // false 表示不抛出异常,如果没有结果会返回 null
BeanMapper.copy(entity, dto);
return dto; // 将查询到的实体对象复制到 DTO 对象
SysConfigDTO dto = new SysConfigDTO(); // 创建 SysConfigDTO 对象
BeanMapper.copy(entity, dto); // 使用 BeanMapper 工具类将 SysConfig 实体对象的属性复制到 DTO 中
return dto; // 返回系统配置 DTO
} }
} }

@ -1,150 +1,136 @@
package com.yf.exam.modules.sys.depart.controller; package com.yf.exam.modules.sys.depart.controller; // 包名:表示该类属于 sys.depart.controller 包
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; // 导入 MyBatis-Plus 的 QueryWrapper用于构建查询条件
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage; // 导入 MyBatis-Plus 分页接口
import com.yf.exam.core.api.ApiRest; import com.yf.exam.core.api.ApiRest; // 导入统一的 API 响应类
import com.yf.exam.core.api.controller.BaseController; import com.yf.exam.core.api.controller.BaseController; // 导入控制器基类,提供通用的控制器功能
import com.yf.exam.core.api.dto.BaseIdReqDTO; import com.yf.exam.core.api.dto.BaseIdReqDTO; // 导入基本请求 DTO用于单个 ID 请求
import com.yf.exam.core.api.dto.BaseIdsReqDTO; import com.yf.exam.core.api.dto.BaseIdsReqDTO; // 导入基本请求 DTO用于多个 ID 请求
import com.yf.exam.core.api.dto.PagingReqDTO; import com.yf.exam.core.api.dto.PagingReqDTO; // 导入分页请求 DTO
import com.yf.exam.core.utils.BeanMapper; import com.yf.exam.core.utils.BeanMapper; // 导入 BeanMapper 工具类,用于对象属性拷贝
import com.yf.exam.modules.sys.depart.dto.SysDepartDTO; import com.yf.exam.modules.sys.depart.dto.SysDepartDTO; // 导入 SysDepartDTO 数据传输对象
import com.yf.exam.modules.sys.depart.dto.request.DepartSortReqDTO; import com.yf.exam.modules.sys.depart.dto.request.DepartSortReqDTO; // 导入部门排序请求 DTO
import com.yf.exam.modules.sys.depart.dto.response.SysDepartTreeDTO; import com.yf.exam.modules.sys.depart.dto.response.SysDepartTreeDTO; // 导入部门树状结构响应 DTO
import com.yf.exam.modules.sys.depart.entity.SysDepart; import com.yf.exam.modules.sys.depart.entity.SysDepart; // 导入 SysDepart 实体类,表示部门
import com.yf.exam.modules.sys.depart.service.SysDepartService; import com.yf.exam.modules.sys.depart.service.SysDepartService; // 导入部门服务接口
import io.swagger.annotations.Api; import io.swagger.annotations.Api; // 导入 Swagger 注解,用于 API 文档生成
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation; // 导入 Swagger 注解,用于定义接口操作说明
import org.apache.shiro.authz.annotation.RequiresRoles; import org.apache.shiro.authz.annotation.RequiresRoles; // 导入 Shiro 权限控制注解,限制角色访问
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils; // 导入 Spring 的 BeanUtils用于对象属性拷贝
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired; // 导入 Spring 注解,用于依赖注入
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody; // 导入注解,用于绑定请求体
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping; // 导入注解,用于定义请求路径
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod; // 导入注解,用于指定请求方法
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController; // 导入注解,标识该类为 REST 控制器
import java.util.List;
/** /**
* <p> * <p>
* *
* </p> * </p>
* *
* @author *
* @since 2020-09-02 17:25 * @
*/ * @ 2020-09-02 17:25
@Api(tags={"部门信息"}) */
@RestController @Api(tags = {"部门信息"}) // Swagger 注解:定义该类的 API 文档标签为“部门信息”
@RequestMapping("/exam/api/sys/depart") @RestController // Spring 注解:标识该类为 REST 控制器
public class SysDepartController extends BaseController { @RequestMapping("/exam/api/sys/depart") // 定义请求路径前缀为 /exam/api/sys/depart
public class SysDepartController extends BaseController { // SysDepartController 类,继承自 BaseController提供通用功能
@Autowired
@Autowired // 自动注入 SysDepartService 服务
private SysDepartService baseService; private SysDepartService baseService;
/** /**
* *
* @param reqDTO * @param reqDTO
* @return * @return
*/ */
@RequiresRoles("sa") @RequiresRoles("sa") // 权限控制:要求用户具有 "sa" 角色
@ApiOperation(value = "添加或修改") @ApiOperation(value = "添加或修改") // Swagger 注解:定义接口操作说明为“添加或修改”
@RequestMapping(value = "/save", method = { RequestMethod.POST}) @RequestMapping(value = "/save", method = {RequestMethod.POST}) // 定义请求路径为 /save方法为 POST
public ApiRest save(@RequestBody SysDepartDTO reqDTO) { public ApiRest save(@RequestBody SysDepartDTO reqDTO) { // 添加或修改部门的方法
baseService.save(reqDTO); baseService.save(reqDTO); // 调用服务保存或更新部门信息
return super.success(); return super.success(); // 返回成功响应
} }
/** /**
* *
* @param reqDTO * @param reqDTO ID
* @return * @return
*/ */
@RequiresRoles("sa") @RequiresRoles("sa") // 权限控制:要求用户具有 "sa" 角色
@ApiOperation(value = "批量删除") @ApiOperation(value = "批量删除") // Swagger 注解:定义接口操作说明为“批量删除”
@RequestMapping(value = "/delete", method = { RequestMethod.POST}) @RequestMapping(value = "/delete", method = {RequestMethod.POST}) // 定义请求路径为 /delete方法为 POST
public ApiRest edit(@RequestBody BaseIdsReqDTO reqDTO) { public ApiRest edit(@RequestBody BaseIdsReqDTO reqDTO) { // 批量删除部门的方法
//根据ID删除 baseService.removeByIds(reqDTO.getIds()); // 根据 ID 列表删除部门
baseService.removeByIds(reqDTO.getIds()); return super.success(); // 返回成功响应
return super.success();
} }
/** /**
* *
* @param reqDTO * @param reqDTO ID
* @return * @return
*/ */
@RequiresRoles("sa") @RequiresRoles("sa") // 权限控制:要求用户具有 "sa" 角色
@ApiOperation(value = "查找详情") @ApiOperation(value = "查找详情") // Swagger 注解:定义接口操作说明为“查找详情”
@RequestMapping(value = "/detail", method = { RequestMethod.POST}) @RequestMapping(value = "/detail", method = {RequestMethod.POST}) // 定义请求路径为 /detail方法为 POST
public ApiRest<SysDepartDTO> find(@RequestBody BaseIdReqDTO reqDTO) { public ApiRest<SysDepartDTO> find(@RequestBody BaseIdReqDTO reqDTO) { // 查找部门详情的方法
SysDepart entity = baseService.getById(reqDTO.getId()); SysDepart entity = baseService.getById(reqDTO.getId()); // 根据 ID 查找部门实体
SysDepartDTO dto = new SysDepartDTO(); SysDepartDTO dto = new SysDepartDTO(); // 创建部门数据传输对象
BeanUtils.copyProperties(entity, dto); BeanUtils.copyProperties(entity, dto); // 将实体对象属性拷贝到 DTO 对象
return super.success(dto); return super.success(dto); // 返回成功响应,包含部门详情
} }
/** /**
* *
* @param reqDTO * @param reqDTO
* @return * @return
*/ */
@RequiresRoles("sa") @RequiresRoles("sa") // 权限控制:要求用户具有 "sa" 角色
@ApiOperation(value = "分页查找") @ApiOperation(value = "分页查找") // Swagger 注解:定义接口操作说明为“分页查找”
@RequestMapping(value = "/paging", method = { RequestMethod.POST}) @RequestMapping(value = "/paging", method = {RequestMethod.POST}) // 定义请求路径为 /paging方法为 POST
public ApiRest<IPage<SysDepartTreeDTO>> paging(@RequestBody PagingReqDTO<SysDepartDTO> reqDTO) { public ApiRest<IPage<SysDepartTreeDTO>> paging(@RequestBody PagingReqDTO<SysDepartDTO> reqDTO) { // 分页查找部门的方法
IPage<SysDepartTreeDTO> page = baseService.paging(reqDTO); // 调用服务进行分页查询
//分页查询并转换 return super.success(page); // 返回成功响应,包含分页数据
IPage<SysDepartTreeDTO> page = baseService.paging(reqDTO);
return super.success(page);
} }
/** /**
* 200 * 200
* @param reqDTO * @param reqDTO
* @return * @return
*/ */
@RequiresRoles("sa") @RequiresRoles("sa") // 权限控制:要求用户具有 "sa" 角色
@ApiOperation(value = "查找列表") @ApiOperation(value = "查找列表") // Swagger 注解:定义接口操作说明为“查找列表”
@RequestMapping(value = "/list", method = { RequestMethod.POST}) @RequestMapping(value = "/list", method = {RequestMethod.POST}) // 定义请求路径为 /list方法为 POST
public ApiRest<List<SysDepartDTO>> list(@RequestBody SysDepartDTO reqDTO) { public ApiRest<List<SysDepartDTO>> list(@RequestBody SysDepartDTO reqDTO) { // 查找部门列表的方法
QueryWrapper<SysDepart> wrapper = new QueryWrapper<>(); // 创建查询条件
//分页查询并转换 List<SysDepart> list = baseService.list(wrapper); // 获取部门列表
QueryWrapper<SysDepart> wrapper = new QueryWrapper<>(); List<SysDepartDTO> dtoList = BeanMapper.mapList(list, SysDepartDTO.class); // 将部门实体列表转换为 DTO 列表
return super.success(dtoList); // 返回成功响应,包含部门列表
//转换并返回
List<SysDepart> list = baseService.list(wrapper);
//转换数据
List<SysDepartDTO> dtoList = BeanMapper.mapList(list, SysDepartDTO.class);
return super.success(dtoList);
} }
/** /**
* *
* @return * @return
*/ */
@RequiresRoles("sa") @RequiresRoles("sa") // 权限控制:要求用户具有 "sa" 角色
@ApiOperation(value = "树列表") @ApiOperation(value = "树列表") // Swagger 注解:定义接口操作说明为“树列表”
@RequestMapping(value = "/tree", method = { RequestMethod.POST}) @RequestMapping(value = "/tree", method = {RequestMethod.POST}) // 定义请求路径为 /tree方法为 POST
public ApiRest<List<SysDepartTreeDTO>> tree() { public ApiRest<List<SysDepartTreeDTO>> tree() { // 查找部门树状结构的方法
List<SysDepartTreeDTO> dtoList = baseService.findTree(); List<SysDepartTreeDTO> dtoList = baseService.findTree(); // 获取部门树状结构
return super.success(dtoList); return super.success(dtoList); // 返回成功响应,包含部门树状结构
} }
/** /**
* *
* @param reqDTO * @param reqDTO
* @return * @return
*/ */
@RequiresRoles("sa") @RequiresRoles("sa") // 权限控制:要求用户具有 "sa" 角色
@ApiOperation(value = "分类排序") @ApiOperation(value = "分类排序") // Swagger 注解:定义接口操作说明为“分类排序”
@RequestMapping(value = "/sort", method = { RequestMethod.POST}) @RequestMapping(value = "/sort", method = {RequestMethod.POST}) // 定义请求路径为 /sort方法为 POST
public ApiRest sort(@RequestBody DepartSortReqDTO reqDTO) { public ApiRest sort(@RequestBody DepartSortReqDTO reqDTO) { // 部门排序的方法
baseService.sort(reqDTO.getId(), reqDTO.getSort()); baseService.sort(reqDTO.getId(), reqDTO.getSort()); // 调用服务进行排序
return super.success(); return super.success(); // 返回成功响应
} }
} }

@ -1,42 +1,41 @@
package com.yf.exam.modules.sys.depart.dto; package com.yf.exam.modules.sys.depart.dto; // 包名:表示该类属于 sys.depart.dto 包
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel; // 导入 Swagger 注解,用于定义 API 模型
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty; // 导入 Swagger 注解,用于描述 API 模型的属性
import lombok.Data; import lombok.Data; // 导入 Lombok 注解,用于自动生成 Getter、Setter、toString 等方法
import java.io.Serializable; import java.io.Serializable; // 导入 Serializable 接口,用于支持对象序列化
/** /**
* <p> * <p>
* *
* </p> * </p>
* *
* @author *
* @since 2020-09-02 17:25 * @
*/ * @ 2020-09-02 17:25
@Data */
@ApiModel(value="部门信息", description="部门信息") @Data // Lombok 注解,自动生成 Getter、Setter 和其他方法
public class SysDepartDTO implements Serializable { @ApiModel(value = "部门信息", description = "部门信息") // Swagger 注解:定义该类的 API 模型名称和描述
public class SysDepartDTO implements Serializable { // 实现 Serializable 接口以支持序列化
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L; // 序列化版本号,用于序列化和反序列化的一致性检查
@ApiModelProperty(value = "ID", required = true) // Swagger 注解描述该属性为“ID”并标记为必填
private String id; // 定义字段:部门的唯一标识符
@ApiModelProperty(value = "ID", required=true) @ApiModelProperty(value = "1公司2部门", required = true) // Swagger 注解描述该属性为“1公司2部门”并标记为必填
private String id; private Integer deptType; // 定义字段部门类型1 表示公司2 表示部门
@ApiModelProperty(value = "1公司2部门", required=true) @ApiModelProperty(value = "所属上级", required = true) // Swagger 注解:描述该属性为“所属上级”,并标记为必填
private Integer deptType; private String parentId; // 定义字段:上级部门的 ID
@ApiModelProperty(value = "所属上级", required=true) @ApiModelProperty(value = "部门名称", required = true) // Swagger 注解:描述该属性为“部门名称”,并标记为必填
private String parentId; private String deptName; // 定义字段:部门名称
@ApiModelProperty(value = "部门名称", required=true) @ApiModelProperty(value = "部门编码", required = true) // Swagger 注解:描述该属性为“部门编码”,并标记为必填
private String deptName; private String deptCode; // 定义字段:部门的唯一编码,用于标识部门
@ApiModelProperty(value = "部门编码", required=true)
private String deptCode;
@ApiModelProperty(value = "排序", required=true)
private Integer sort;
@ApiModelProperty(value = "排序", required = true) // Swagger 注解:描述该属性为“排序”,并标记为必填
private Integer sort; // 定义字段:部门排序序号,用于定义显示顺序
} }

@ -1,28 +1,29 @@
package com.yf.exam.modules.sys.depart.dto.request; package com.yf.exam.modules.sys.depart.dto.request; // 包名:表示该类属于 sys.depart.dto.request 包
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel; // 导入 Swagger 注解,用于定义 API 模型
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty; // 导入 Swagger 注解,用于描述 API 模型的属性
import lombok.Data; import lombok.Data; // 导入 Lombok 注解,用于自动生成 Getter、Setter、toString 等方法
import java.io.Serializable; import java.io.Serializable; // 导入 Serializable 接口,用于对象序列化
/** /**
* <p> * <p>
* *
* </p> * </p>
* *
* @author *
* @since 2020-03-14 10:37 * @
*/ * @ 2020-03-14 10:37
@Data */
@ApiModel(value="部门排序请求类", description="部门排序请求类") @Data // Lombok 注解,自动生成 Getter、Setter 和其他方法
public class DepartSortReqDTO implements Serializable { @ApiModel(value = "部门排序请求类", description = "部门排序请求类") // Swagger 注解:定义该类的 API 模型名称和描述
public class DepartSortReqDTO implements Serializable { // 实现 Serializable 接口以支持序列化
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L; // 序列化版本号,用于序列化和反序列化的一致性检查
@ApiModelProperty(value = "分类ID") @ApiModelProperty(value = "分类ID") // Swagger 注解描述该属性为“分类ID”
private String id; private String id; // 定义字段:分类的唯一标识符
@ApiModelProperty(value = "排序0下降1上升") @ApiModelProperty(value = "排序0下降1上升") // Swagger 注解描述该属性为“排序”0 表示下降1 表示上升
private Integer sort; private Integer sort; // 定义字段排序方式0 为下降排序1 为上升排序
} }

@ -1,28 +1,27 @@
package com.yf.exam.modules.sys.depart.dto.response; package com.yf.exam.modules.sys.depart.dto.response; // 包名:表示该类属于 sys.depart.dto.response 包
import com.yf.exam.modules.sys.depart.dto.SysDepartDTO; import com.yf.exam.modules.sys.depart.dto.SysDepartDTO; // 导入 SysDepartDTO 类,表示部门的基本信息
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel; // 导入 Swagger 注解,用于定义 API 模型
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty; // 导入 Swagger 注解,用于描述 API 模型的属性
import lombok.Data; import lombok.Data; // 导入 Lombok 注解,用于自动生成 Getter、Setter、toString 等方法
import java.util.List; import java.util.List; // 导入 List 接口,用于存储子部门列表
/** /**
* <p> * <p>
* *
* </p> * </p>
* *
* @author *
* @since 2020-09-02 17:25 * @
*/ * @ 2020-09-02 17:25
@Data */
@ApiModel(value="部门树结构响应类", description="部门树结构响应类") @Data // Lombok 注解,自动生成 Getter、Setter 和其他方法
public class SysDepartTreeDTO extends SysDepartDTO { @ApiModel(value = "部门树结构响应类", description = "部门树结构响应类") // Swagger 注解:定义该类的 API 模型名称和描述
public class SysDepartTreeDTO extends SysDepartDTO { // 继承 SysDepartDTO扩展支持树形结构
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "子列表", required=true)
private List<SysDepartTreeDTO> children;
private static final long serialVersionUID = 1L; // 序列化版本号,用于序列化和反序列化的一致性检查
@ApiModelProperty(value = "子列表", required = true) // Swagger 注解:描述该属性为“子列表”,标记为必填
private List<SysDepartTreeDTO> children; // 定义字段:子部门列表,支持递归嵌套表示树形结构
} }

@ -1,59 +1,59 @@
package com.yf.exam.modules.sys.depart.entity; package com.yf.exam.modules.sys.depart.entity; // 包名:表示该类属于 sys.depart.entity 包
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType; // 导入 MyBatis-Plus 注解,用于定义主键类型
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField; // 导入 MyBatis-Plus 注解,用于映射数据库字段
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId; // 导入 MyBatis-Plus 注解,用于标识主键字段
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName; // 导入 MyBatis-Plus 注解,用于映射数据库表名
import com.baomidou.mybatisplus.extension.activerecord.Model; import com.baomidou.mybatisplus.extension.activerecord.Model; // 导入 MyBatis-Plus 的 Model 基类,用于支持 ActiveRecord 模式
import lombok.Data; import lombok.Data; // 导入 Lombok 注解,用于自动生成 Getter、Setter、toString 等方法
/** /**
* <p> * <p>
* *
* </p> * </p>
* * `sys_depart`
* @author *
* @since 2020-09-02 17:25 * @
*/ * @ 2020-09-02 17:25
@Data */
@TableName("sys_depart") @Data // Lombok 注解,自动生成 Getter、Setter 和其他方法
public class SysDepart extends Model<SysDepart> { @TableName("sys_depart") // MyBatis-Plus 注解,指定该类映射的数据库表名为 `sys_depart`
public class SysDepart extends Model<SysDepart> { // 继承 MyBatis-Plus 的 Model 类,支持 ActiveRecord 模式
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L; // 序列化版本号,用于序列化和反序列化的一致性检查
/** /**
* ID * ID
*/ */
@TableId(value = "id", type = IdType.ASSIGN_ID) @TableId(value = "id", type = IdType.ASSIGN_ID) // MyBatis-Plus 注解,指定主键字段及其生成策略为 ASSIGN_ID
private String id; private String id; // 部门的唯一标识符
/** /**
* 12 * 12
*/ */
@TableField("dept_type") @TableField("dept_type") // MyBatis-Plus 注解,指定该字段映射数据库中的 `dept_type` 列
private Integer deptType; private Integer deptType; // 部门类型1 表示公司2 表示部门
/** /**
* *
*/ */
@TableField("parent_id") @TableField("parent_id") // MyBatis-Plus 注解,指定该字段映射数据库中的 `parent_id` 列
private String parentId; private String parentId; // 上级部门的 ID用于定义层级关系
/** /**
* *
*/ */
@TableField("dept_name") @TableField("dept_name") // MyBatis-Plus 注解,指定该字段映射数据库中的 `dept_name` 列
private String deptName; private String deptName; // 部门的名称,用于显示和标识部门
/** /**
* *
*/ */
@TableField("dept_code") @TableField("dept_code") // MyBatis-Plus 注解,指定该字段映射数据库中的 `dept_code` 列
private String deptCode; private String deptCode; // 部门的唯一编码,用于标识部门
/** /**
* *
*/ */
private Integer sort; private Integer sort; // 排序字段,用于定义部门显示的顺序
} }

@ -1,28 +1,29 @@
package com.yf.exam.modules.sys.depart.mapper; package com.yf.exam.modules.sys.depart.mapper; // 包名:表示该类属于 sys.depart.mapper 包
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; // 导入 MyBatis-Plus 的 BaseMapper 接口,用于提供基础的数据库操作
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage; // 导入 MyBatis-Plus 的分页接口
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; // 导入 MyBatis-Plus 的分页插件中的 Page 类
import com.yf.exam.modules.sys.depart.dto.SysDepartDTO; import com.yf.exam.modules.sys.depart.dto.SysDepartDTO; // 导入部门数据传输对象,用于封装查询条件
import com.yf.exam.modules.sys.depart.dto.response.SysDepartTreeDTO; import com.yf.exam.modules.sys.depart.dto.response.SysDepartTreeDTO; // 导入部门树形结构响应对象
import com.yf.exam.modules.sys.depart.entity.SysDepart; import com.yf.exam.modules.sys.depart.entity.SysDepart; // 导入部门实体类
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param; // 导入 MyBatis 注解,用于标注参数
/** /**
* <p> * <p>
* Mapper * Mapper
* </p> * </p>
* *
* @author *
* @since 2020-09-02 17:25 * @
*/ * @ 2020-09-02 17:25
public interface SysDepartMapper extends BaseMapper<SysDepart> { */
public interface SysDepartMapper extends BaseMapper<SysDepart> { // SysDepartMapper 接口,继承 MyBatis-Plus 的 BaseMapper
/** /**
* *
* @param page * @param page
* @param query * @param query
* @return * @return
*/ */
IPage<SysDepartTreeDTO> paging(Page page, @Param("query") SysDepartDTO query); IPage<SysDepartTreeDTO> paging(Page page, @Param("query") SysDepartDTO query); // 自定义分页查询方法,返回部门树形结构的分页数据
} }

@ -1,62 +1,62 @@
package com.yf.exam.modules.sys.depart.service; package com.yf.exam.modules.sys.depart.service; // 包名:表示该接口属于 sys.depart.service 包
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage; // 导入 MyBatis-Plus 的分页接口,用于返回分页查询结果
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService; // 导入 MyBatis-Plus 的 IService 接口,用于提供通用的数据库操作
import com.yf.exam.core.api.dto.PagingReqDTO; import com.yf.exam.core.api.dto.PagingReqDTO; // 导入分页请求数据传输对象
import com.yf.exam.modules.sys.depart.dto.SysDepartDTO; import com.yf.exam.modules.sys.depart.dto.SysDepartDTO; // 导入 SysDepartDTO 数据传输对象,用于封装部门数据
import com.yf.exam.modules.sys.depart.dto.response.SysDepartTreeDTO; import com.yf.exam.modules.sys.depart.dto.response.SysDepartTreeDTO; // 导入 SysDepartTreeDTO 类,用于表示部门树形结构
import com.yf.exam.modules.sys.depart.entity.SysDepart; import com.yf.exam.modules.sys.depart.entity.SysDepart; // 导入 SysDepart 实体类,表示部门
import java.util.List; import java.util.List; // 导入 List 接口,用于存储部门 ID 或部门列表
/** /**
* <p> * <p>
* *
* </p> * </p>
* *
* @author *
* @since 2020-09-02 17:25 * @
*/ * @ 2020-09-02 17:25
public interface SysDepartService extends IService<SysDepart> { */
public interface SysDepartService extends IService<SysDepart> { // SysDepartService 接口继承 MyBatis-Plus 的 IService 接口,提供 CRUD 操作
/** /**
* *
* @param reqDTO * @param reqDTO
*/ */
void save(SysDepartDTO reqDTO); void save(SysDepartDTO reqDTO); // 保存部门信息方法,接收部门数据传输对象
/** /**
* *
* @param reqDTO * @param reqDTO
* @return * @return
*/ */
IPage<SysDepartTreeDTO> paging(PagingReqDTO<SysDepartDTO> reqDTO); IPage<SysDepartTreeDTO> paging(PagingReqDTO<SysDepartDTO> reqDTO); // 分页查询部门树的方法
/** /**
* *
* @return * @return
*/ */
List<SysDepartTreeDTO> findTree(); List<SysDepartTreeDTO> findTree(); // 查找所有部门树的方法,返回树形结构数据
/** /**
* * ID
* @param ids * @param ids ID
* @return * @return
*/ */
List<SysDepartTreeDTO> findTree(List<String> ids); List<SysDepartTreeDTO> findTree(List<String> ids); // 查找指定部门ID列表下的部门树的方法
/** /**
* *
* @param id * @param id ID
* @param sort * @param sort 01
*/ */
void sort(String id, Integer sort); void sort(String id, Integer sort); // 排序部门的方法,支持上升和下降排序
/** /**
* IDID * IDID
* @param id * @param id ID
* @return * @return ID
*/ */
List<String> listAllSubIds( String id); List<String> listAllSubIds(String id); // 获取某个部门下所有子部门ID的方法
} }

@ -1,227 +1,233 @@
package com.yf.exam.modules.sys.depart.service.impl; package com.yf.exam.modules.sys.depart.service.impl; // 包名:表示该类属于 sys.depart.service.impl 包
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; // 导入 MyBatis-Plus 的 QueryWrapper用于构建查询条件
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage; // 导入 MyBatis-Plus 分页接口
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; // 导入 MyBatis-Plus 分页插件中的 Page 类
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; // 导入 MyBatis-Plus 的 ServiceImpl 类,用于提供通用的数据库操作
import com.yf.exam.core.api.dto.PagingReqDTO; import com.yf.exam.core.api.dto.PagingReqDTO; // 导入分页请求数据传输对象
import com.yf.exam.core.utils.BeanMapper; import com.yf.exam.core.utils.BeanMapper; // 导入 BeanMapper 工具类,用于对象属性拷贝
import com.yf.exam.modules.sys.depart.dto.SysDepartDTO; import com.yf.exam.modules.sys.depart.dto.SysDepartDTO; // 导入 SysDepartDTO 类,封装部门数据传输对象
import com.yf.exam.modules.sys.depart.dto.response.SysDepartTreeDTO; import com.yf.exam.modules.sys.depart.dto.response.SysDepartTreeDTO; // 导入 SysDepartTreeDTO 类,用于部门树形结构
import com.yf.exam.modules.sys.depart.entity.SysDepart; import com.yf.exam.modules.sys.depart.entity.SysDepart; // 导入 SysDepart 实体类,表示部门
import com.yf.exam.modules.sys.depart.mapper.SysDepartMapper; import com.yf.exam.modules.sys.depart.mapper.SysDepartMapper; // 导入部门的 Mapper 接口,用于数据库交互
import com.yf.exam.modules.sys.depart.service.SysDepartService; import com.yf.exam.modules.sys.depart.service.SysDepartService; // 导入部门服务接口
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils; // 导入 Apache Commons Lang3 库中的 StringUtils用于字符串操作
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service; // 导入 Spring 注解,用于标识该类为服务层组件
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils; // 导入 Spring 的 CollectionUtils 工具类,用于集合操作
import java.util.ArrayList; import java.util.ArrayList; // 导入 ArrayList 类,用于列表数据存储
import java.util.HashMap; import java.util.HashMap; // 导入 HashMap 类,用于映射键值对
import java.util.List; import java.util.List; // 导入 List 接口,用于存储列表数据
import java.util.Map; import java.util.Map; // 导入 Map 接口,用于映射键值对
/** /**
* <p> * <p>
* *
* </p> * </p>
* * SysDepartService
* @author *
* @since 2020-09-02 17:25 * @
*/ * @ 2020-09-02 17:25
@Service */
public class SysDepartServiceImpl extends ServiceImpl<SysDepartMapper, SysDepart> implements SysDepartService { @Service // Spring 注解,标识该类为服务层组件
public class SysDepartServiceImpl extends ServiceImpl<SysDepartMapper, SysDepart> implements SysDepartService { // 继承 MyBatis-Plus 的 ServiceImpl 类,简化数据库操作
/** /**
* 0 * 0
*/ */
private static final String ROOT_TAG = "0"; private static final String ROOT_TAG = "0"; // 顶级部门标识符
/**
*
* @param reqDTO
*/
@Override @Override
public void save(SysDepartDTO reqDTO) { public void save(SysDepartDTO reqDTO) {
// 如果部门ID为空生成部门编码
if(StringUtils.isBlank(reqDTO.getId())) { if(StringUtils.isBlank(reqDTO.getId())) {
this.fillCode(reqDTO); this.fillCode(reqDTO); // 填充部门编码
}else{ } else {
reqDTO.setSort(null); reqDTO.setSort(null); // 如果有ID则清空排序字段
reqDTO.setDeptCode(null); reqDTO.setDeptCode(null); // 清空部门编码
} }
SysDepart entity = new SysDepart(); SysDepart entity = new SysDepart(); // 创建部门实体对象
BeanMapper.copy(reqDTO, entity); BeanMapper.copy(reqDTO, entity); // 将 DTO 数据拷贝到实体对象
this.saveOrUpdate(entity); this.saveOrUpdate(entity); // 保存或更新部门信息
} }
/**
*
* @param reqDTO
* @return
*/
@Override @Override
public IPage<SysDepartTreeDTO> paging(PagingReqDTO<SysDepartDTO> reqDTO) { public IPage<SysDepartTreeDTO> paging(PagingReqDTO<SysDepartDTO> reqDTO) {
// 创建分页对象 // 创建分页对象
Page query = new Page(reqDTO.getCurrent(), reqDTO.getSize()); Page query = new Page(reqDTO.getCurrent(), reqDTO.getSize());
// 请求参数 // 获取查询条件
SysDepartDTO params = reqDTO.getParams(); SysDepartDTO params = reqDTO.getParams();
//转换结果 // 执行分页查询
IPage<SysDepartTreeDTO> pageData = baseMapper.paging(query, params); IPage<SysDepartTreeDTO> pageData = baseMapper.paging(query, params);
return pageData; return pageData; // 返回分页结果
} }
/**
*
* @return
*/
@Override @Override
public List<SysDepartTreeDTO> findTree() { public List<SysDepartTreeDTO> findTree() {
return this.findTree(null); return this.findTree(null); // 默认查找所有部门
} }
/**
* ID
* @param ids ID
* @return
*/
@Override @Override
public List<SysDepartTreeDTO> findTree(List<String> ids) { public List<SysDepartTreeDTO> findTree(List<String> ids) {
QueryWrapper<SysDepart> wrapper = new QueryWrapper<>(); // 创建查询条件
wrapper.lambda().orderByAsc(SysDepart::getSort); // 按照排序字段升序排列
QueryWrapper<SysDepart> wrapper = new QueryWrapper(); // 如果传入了部门ID列表递归获取所有父级部门
wrapper.lambda().orderByAsc(SysDepart::getSort);
if(!CollectionUtils.isEmpty(ids)){ if(!CollectionUtils.isEmpty(ids)){
List<String> fullIds = new ArrayList<>(); List<String> fullIds = new ArrayList<>(); // 用于存储所有父部门ID
for(String id: ids){ for(String id: ids){
this.cycleAllParent(fullIds, id); this.cycleAllParent(fullIds, id); // 递归获取所有父部门ID
} }
if(!CollectionUtils.isEmpty(fullIds)){ if(!CollectionUtils.isEmpty(fullIds)){
wrapper.lambda().in(SysDepart::getId, fullIds); wrapper.lambda().in(SysDepart::getId, fullIds); // 根据部门ID列表查询
} }
} }
//全部列表 // 获取所有部门数据
List<SysDepart> list = this.list(wrapper); List<SysDepart> list = this.list(wrapper);
List<SysDepartTreeDTO> dtoList = BeanMapper.mapList(list, SysDepartTreeDTO.class); List<SysDepartTreeDTO> dtoList = BeanMapper.mapList(list, SysDepartTreeDTO.class); // 将部门实体列表转换为部门树形结构DTO列表
//子结构的列表
Map<String,List<SysDepartTreeDTO>> map = new HashMap<>(16);
// 构建子部门的映射关系
Map<String, List<SysDepartTreeDTO>> map = new HashMap<>(16);
for(SysDepartTreeDTO item: dtoList){ for(SysDepartTreeDTO item: dtoList){
// 如果当前部门已经有子部门,直接添加
//如果存在
if(map.containsKey(item.getParentId())){ if(map.containsKey(item.getParentId())){
map.get(item.getParentId()).add(item); map.get(item.getParentId()).add(item);
continue; continue;
} }
//增加新的结构 // 如果没有子部门,则新建一个子部门列表
List<SysDepartTreeDTO> a = new ArrayList<>(); List<SysDepartTreeDTO> a = new ArrayList<>();
a.add(item); a.add(item);
map.put(item.getParentId(), a); map.put(item.getParentId(), a);
} }
//注意第0级为顶级的 // 获取顶级部门parentId 为 ROOT_TAG
List<SysDepartTreeDTO> topList = map.get(ROOT_TAG); List<SysDepartTreeDTO> topList = map.get(ROOT_TAG);
if(!CollectionUtils.isEmpty(topList)){ if(!CollectionUtils.isEmpty(topList)){
for(SysDepartTreeDTO item: topList){ for(SysDepartTreeDTO item: topList){
this.fillChildren(map, item); this.fillChildren(map, item); // 填充子部门
} }
} }
return topList; return topList; // 返回顶级部门及其子部门树
} }
/**
*
* @param id ID
* @param sort 01
*/
@Override @Override
public void sort(String id, Integer sort) { public void sort(String id, Integer sort) {
SysDepart depart = this.getById(id); SysDepart depart = this.getById(id); // 获取部门实体
SysDepart exchange = null; SysDepart exchange = null;
QueryWrapper<SysDepart> wrapper = new QueryWrapper<>(); QueryWrapper<SysDepart> wrapper = new QueryWrapper<>(); // 创建查询条件
// 同级排序 // 根据部门的父ID查询同级别的部门
wrapper.lambda() wrapper.lambda().eq(SysDepart::getParentId, depart.getParentId());
.eq(SysDepart::getParentId, depart.getParentId());
wrapper.last("LIMIT 1"); wrapper.last("LIMIT 1");
// 上升 // 上升排序
if(sort == 0){ if(sort == 0){
// 同级排序 wrapper.lambda().lt(SysDepart::getSort, depart.getSort()).orderByDesc(SysDepart::getSort); // 查找排序小于当前部门的部门
wrapper.lambda() exchange = this.getOne(wrapper, false); // 获取交换部门
.lt(SysDepart::getSort, depart.getSort())
.orderByDesc(SysDepart::getSort);
exchange = this.getOne(wrapper, false);
} }
// 下降 // 下降排序
if(sort == 1){ if(sort == 1){
// 同级排序 wrapper.lambda().gt(SysDepart::getSort, depart.getSort()).orderByAsc(SysDepart::getSort); // 查找排序大于当前部门的部门
wrapper.lambda() exchange = this.getOne(wrapper, false); // 获取交换部门
.gt(SysDepart::getSort, depart.getSort())
.orderByAsc(SysDepart::getSort);
exchange = this.getOne(wrapper, false);
} }
// 如果找到了交换的部门,进行交换排序
if(exchange!=null) { if(exchange != null) {
SysDepart a = new SysDepart(); SysDepart a = new SysDepart();
a.setId(id); a.setId(id);
a.setSort(exchange.getSort()); a.setSort(exchange.getSort());
SysDepart b = new SysDepart(); SysDepart b = new SysDepart();
b.setId(exchange.getId()); b.setId(exchange.getId());
b.setSort(depart.getSort()); b.setSort(depart.getSort());
this.updateById(a); this.updateById(a); // 更新部门a的排序
this.updateById(b); this.updateById(b); // 更新部门b的排序
} }
} }
/** /**
* *
* @param reqDTO * @param reqDTO
* @return
*/ */
private void fillCode(SysDepartDTO reqDTO){ private void fillCode(SysDepartDTO reqDTO){
// 前缀
String code = ""; String code = "";
if(StringUtils.isNotBlank(reqDTO.getParentId()) // 获取上级部门编码
&& !ROOT_TAG.equals(reqDTO.getParentId())){ if(StringUtils.isNotBlank(reqDTO.getParentId()) && !ROOT_TAG.equals(reqDTO.getParentId())){
SysDepart parent = this.getById(reqDTO.getParentId()); SysDepart parent = this.getById(reqDTO.getParentId());
code = parent.getDeptCode(); code = parent.getDeptCode(); // 获取上级部门的编码
} }
QueryWrapper<SysDepart> wrapper = new QueryWrapper<>(); QueryWrapper<SysDepart> wrapper = new QueryWrapper<>();
wrapper.lambda().eq(SysDepart::getParentId, reqDTO.getParentId()).orderByDesc(SysDepart::getSort); // 查询同级部门
// 同级排序
wrapper.lambda()
.eq(SysDepart::getParentId, reqDTO.getParentId())
.orderByDesc(SysDepart::getSort);
wrapper.last("LIMIT 1");
SysDepart depart = this.getOne(wrapper, false); SysDepart depart = this.getOne(wrapper, false);
if(depart != null){
if(depart !=null){ code += this.formatCode(depart.getSort() + 1); // 根据排序生成部门编码
code += this.formatCode(depart.getSort()+1); reqDTO.setSort(depart.getSort() + 1); // 设置部门的排序
reqDTO.setSort(depart.getSort()+1); } else {
}else{ code += this.formatCode(1); // 如果没有同级部门则从1开始
code += this.formatCode(1); reqDTO.setSort(1); // 设置部门的排序为1
reqDTO.setSort(1);
} }
reqDTO.setDeptCode(code); reqDTO.setDeptCode(code); // 设置部门编码
} }
/** /**
* 0 *
* @param sort * @param sort
* @return * @return
*/ */
private String formatCode(Integer sort){ private String formatCode(Integer sort){
if(sort < 10){ if(sort < 10){
return "A0"+sort; return "A0" + sort; // 排序小于10时返回带前导零的编码
} }
return "A"+sort; return "A" + sort; // 排序大于或等于10时返回正常编码
} }
/** /**
* *
* @param map * @param map
* @param item * @param item
*/ */
private void fillChildren(Map<String,List<SysDepartTreeDTO>> map, SysDepartTreeDTO item){ private void fillChildren(Map<String, List<SysDepartTreeDTO>> map, SysDepartTreeDTO item){
//设置子类 //设置子类
if(map.containsKey(item.getId())){ if(map.containsKey(item.getId())){
@ -229,60 +235,61 @@ public class SysDepartServiceImpl extends ServiceImpl<SysDepartMapper, SysDepart
List<SysDepartTreeDTO> children = map.get(item.getId()); List<SysDepartTreeDTO> children = map.get(item.getId());
if(!CollectionUtils.isEmpty(children)){ if(!CollectionUtils.isEmpty(children)){
for(SysDepartTreeDTO sub: children){ for(SysDepartTreeDTO sub: children){
this.fillChildren(map, sub); this.fillChildren(map, sub); // 递归填充子部门
} }
} }
item.setChildren(children); item.setChildren(children); // 设置子部门列表
} }
} }
/**
* ID
* @param id ID
* @return ID
*/
@Override @Override
public List<String> listAllSubIds( String id){ public List<String> listAllSubIds(String id){
List<String> ids = new ArrayList<>(); List<String> ids = new ArrayList<>();
this.cycleAllSubs(ids, id); this.cycleAllSubs(ids, id); // 递归获取所有子部门的ID
return ids; return ids;
} }
/** /**
* ID * ID
* @param list * @param list ID
* @param id * @param id ID
*/ */
private void cycleAllSubs(List<String> list, String id){ private void cycleAllSubs(List<String> list, String id){
// 添加ID // 添加当前部门ID
list.add(id); list.add(id);
QueryWrapper<SysDepart> wrapper = new QueryWrapper<>(); QueryWrapper<SysDepart> wrapper = new QueryWrapper<>();
wrapper.lambda() wrapper.lambda()
.eq(SysDepart::getParentId, id) .eq(SysDepart::getParentId, id)
.orderByDesc(SysDepart::getSort); .orderByDesc(SysDepart::getSort); // 查询当前部门的所有子部门
List<SysDepart> subList = this.list(wrapper); List<SysDepart> subList = this.list(wrapper);
if(!CollectionUtils.isEmpty(subList)){ if(!CollectionUtils.isEmpty(subList)){
for(SysDepart item: subList){ for(SysDepart item: subList){
this.cycleAllSubs(list, item.getId()); this.cycleAllSubs(list, item.getId()); // 递归查询子部门
} }
} }
} }
/** /**
* ID * ID
* @param list * @param list ID
* @param id * @param id ID
*/ */
private void cycleAllParent(List<String> list, String id){ private void cycleAllParent(List<String> list, String id){
// 往上递归获得父类 // 往上递归获取父部门
list.add(id); list.add(id);
SysDepart depart = this.getById(id); SysDepart depart = this.getById(id);
if(StringUtils.isNotBlank(depart.getParentId()) if(StringUtils.isNotBlank(depart.getParentId()) && !ROOT_TAG.equals(depart.getParentId())){
&& !ROOT_TAG.equals(depart.getParentId())){ this.cycleAllParent(list, depart.getParentId()); // 递归查询父部门
this.cycleAllParent(list, depart.getParentId());
} }
} }
} }

@ -1,29 +1,30 @@
package com.yf.exam.modules.sys.system.mapper; package com.yf.exam.modules.sys.system.mapper; // 包名:表示该接口属于 sys.system.mapper 包
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper; // 导入 MyBatis 的 @Mapper 注解,表示这是一个 Mapper 接口
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param; // 导入 MyBatis 的 @Param 注解,用于指定参数名称
/** /**
* <p> * <p>
* Mapper * Mapper
* </p> * </p>
* *
* @author *
* @since 2020-08-22 13:46 * @
*/ * @ 2020-08-22 13:46
@Mapper */
@Mapper // MyBatis 注解,表示该接口为 Mapper 接口MyBatis 会自动生成相应的实现
public interface SysDictMapper { public interface SysDictMapper {
/** /**
* *
* @param table * @param table
* @param text * @param text
* @param key * @param key
* @param value * @param value
* @return * @return
*/ */
String findDict(@Param("table") String table, String findDict(@Param("table") String table, // 使用 @Param 注解绑定 SQL 参数名
@Param("text") String text, @Param("text") String text, // 绑定 SQL 参数 text
@Param("key") String key, @Param("key") String key, // 绑定 SQL 参数 key
@Param("value") String value); @Param("value") String value); // 绑定 SQL 参数 value
} }

@ -1,21 +1,25 @@
package com.yf.exam.modules.sys.system.service; package com.yf.exam.modules.sys.system.service; // 包名:表示该接口属于 sys.system.service 包
/** /**
* *
* @author bool *
*
* @ bool
*/ */
public interface SysDictService { public interface SysDictService { // 定义 SysDictService 接口,提供数据字典的服务
/** /**
* *
* @param table *
* @param text *
* @param key * @param table
* @param value * @param text
* @return * @param key
* @param value
* @return
*/ */
String findDict(String table, String findDict(String table, // 表示字典数据的表名
String text, String text, // 字段文本,用于描述字段
String key, String key, // 字段的键
String value); String value); // 字段的值,查询条件之一
} }

@ -1,21 +1,30 @@
package com.yf.exam.modules.sys.system.service.impl; package com.yf.exam.modules.sys.system.service.impl; // 包名:表示该类属于 sys.system.service.impl 包
import com.yf.exam.modules.sys.system.mapper.SysDictMapper; import com.yf.exam.modules.sys.system.mapper.SysDictMapper; // 导入 SysDictMapper 接口,用于操作数据字典
import com.yf.exam.modules.sys.system.service.SysDictService; import com.yf.exam.modules.sys.system.service.SysDictService; // 导入 SysDictService 接口,定义数据字典的业务逻辑
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired; // 导入 Spring 的 @Autowired 注解,用于自动注入依赖
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service; // 导入 Spring 的 @Service 注解,用于标识该类为服务层组件
/** /**
* SysDictServiceImpl
* @author bool * @author bool
*/ */
@Service @Service // Spring 注解,标识该类为服务层组件
public class SysDictServiceImpl implements SysDictService { public class SysDictServiceImpl implements SysDictService { // 实现 SysDictService 接口
@Autowired @Autowired // 自动注入 SysDictMapper
private SysDictMapper sysDictMapper; private SysDictMapper sysDictMapper;
/**
*
* @param table
* @param text
* @param key
* @param value
* @return
*/
@Override @Override
public String findDict(String table, String text, String key, String value) { public String findDict(String table, String text, String key, String value) {
return sysDictMapper.findDict(table, text, key, value); return sysDictMapper.findDict(table, text, key, value); // 调用 Mapper 层的方法查找字典数据
} }
} }

@ -1,77 +1,75 @@
package com.yf.exam.modules.sys.user.controller; package com.yf.exam.modules.sys.user.controller; // 包名:表示该类属于 sys.user.controller 包
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; // 导入 MyBatis-Plus 的 QueryWrapper用于构建查询条件
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage; // 导入 MyBatis-Plus 分页接口
import com.yf.exam.core.api.ApiRest; import com.yf.exam.core.api.ApiRest; // 导入统一的 API 响应类
import com.yf.exam.core.api.controller.BaseController; import com.yf.exam.core.api.controller.BaseController; // 导入基类控制器,提供通用功能
import com.yf.exam.core.api.dto.PagingReqDTO; import com.yf.exam.core.api.dto.PagingReqDTO; // 导入分页请求数据传输对象
import com.yf.exam.core.utils.BeanMapper; import com.yf.exam.core.utils.BeanMapper; // 导入 BeanMapper 工具类,用于对象属性拷贝
import com.yf.exam.modules.sys.user.dto.SysRoleDTO; import com.yf.exam.modules.sys.user.dto.SysRoleDTO; // 导入 SysRoleDTO 数据传输对象
import com.yf.exam.modules.sys.user.entity.SysRole; import com.yf.exam.modules.sys.user.entity.SysRole; // 导入 SysRole 实体类,表示角色
import com.yf.exam.modules.sys.user.service.SysRoleService; import com.yf.exam.modules.sys.user.service.SysRoleService; // 导入 SysRoleService 服务接口
import io.swagger.annotations.Api; import io.swagger.annotations.Api; // 导入 Swagger 注解,用于定义 API 文档
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation; // 导入 Swagger 注解,用于描述接口操作
import org.apache.shiro.authz.annotation.RequiresRoles; import org.apache.shiro.authz.annotation.RequiresRoles; // 导入 Shiro 注解,用于权限控制,限制访问角色
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired; // 导入 Spring 注解,用于自动注入依赖
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody; // 导入注解,用于绑定请求体
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping; // 导入注解,用于定义请求路径
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod; // 导入注解,用于指定请求方法
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController; // 导入注解,标识该类为 REST 控制器
import java.util.List; import java.util.List; // 导入 List 接口,用于存储角色列表
/** /**
* <p> * <p>
* *
* </p> * </p>
*
* *
* @author * @
* @since 2020-04-13 16:57 * @ 2020-04-13 16:57
*/ */
@Api(tags = {"管理用户"}) @Api(tags = {"管理用户"}) // Swagger 注解:定义该类的 API 文档标签为“管理用户”
@RestController @RestController // Spring 注解:标识该类为 REST 控制器,处理 HTTP 请求
@RequestMapping("/exam/api/sys/role") @RequestMapping("/exam/api/sys/role") // 定义请求路径前缀为 /exam/api/sys/role
public class SysRoleController extends BaseController { public class SysRoleController extends BaseController { // SysRoleController 继承自 BaseController提供通用功能
@Autowired @Autowired // 自动注入 SysRoleService 服务
private SysRoleService baseService; private SysRoleService baseService;
/** /**
* *
* @param reqDTO * @param reqDTO
* @return * @return
*/ */
@RequiresRoles("sa") @RequiresRoles("sa") // 权限控制:要求用户具有 "sa" 角色
@ApiOperation(value = "分页查找") @ApiOperation(value = "分页查找") // Swagger 注解:描述接口操作为“分页查找”
@RequestMapping(value = "/paging", method = { RequestMethod.POST}) @RequestMapping(value = "/paging", method = { RequestMethod.POST}) // 请求路径为 /paging方法为 POST
public ApiRest<IPage<SysRoleDTO>> paging(@RequestBody PagingReqDTO<SysRoleDTO> reqDTO) { public ApiRest<IPage<SysRoleDTO>> paging(@RequestBody PagingReqDTO<SysRoleDTO> reqDTO) {
//分页查询并转换 // 调用服务层进行分页查询,并返回角色数据
IPage<SysRoleDTO> page = baseService.paging(reqDTO); IPage<SysRoleDTO> page = baseService.paging(reqDTO);
return super.success(page); return super.success(page); // 返回成功响应,包含分页数据
} }
/** /**
* 200 * 200
* @return * @return
*/ */
@RequiresRoles("sa") @RequiresRoles("sa") // 权限控制:要求用户具有 "sa" 角色
@ApiOperation(value = "查找列表") @ApiOperation(value = "查找列表") // Swagger 注解:描述接口操作为“查找列表”
@RequestMapping(value = "/list", method = { RequestMethod.POST}) @RequestMapping(value = "/list", method = { RequestMethod.POST}) // 请求路径为 /list方法为 POST
public ApiRest<List<SysRoleDTO>> list() { public ApiRest<List<SysRoleDTO>> list() {
//分页查询并转换 // 创建查询条件
QueryWrapper<SysRole> wrapper = new QueryWrapper<>(); QueryWrapper<SysRole> wrapper = new QueryWrapper<>();
//转换并返回 // 获取所有角色数据
List<SysRole> list = baseService.list(wrapper); List<SysRole> list = baseService.list(wrapper);
//转换数据 // 将角色实体数据转换为角色数据传输对象
List<SysRoleDTO> dtoList = BeanMapper.mapList(list, SysRoleDTO.class); List<SysRoleDTO> dtoList = BeanMapper.mapList(list, SysRoleDTO.class);
return super.success(dtoList); return super.success(dtoList); // 返回成功响应,包含角色列表
} }
} }

@ -1,182 +1,185 @@
package com.yf.exam.modules.sys.user.controller; package com.yf.exam.modules.sys.user.controller; // 包名:表示该类属于 sys.user.controller 包
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; // 导入 MyBatis-Plus 的 QueryWrapper用于构建查询条件
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage; // 导入 MyBatis-Plus 分页接口
import com.yf.exam.core.api.ApiRest; import com.yf.exam.core.api.ApiRest; // 导入统一的 API 响应类
import com.yf.exam.core.api.controller.BaseController; import com.yf.exam.core.api.controller.BaseController; // 导入基类控制器,提供通用功能
import com.yf.exam.core.api.dto.BaseIdsReqDTO; import com.yf.exam.core.api.dto.BaseIdsReqDTO; // 导入基本请求 DTO用于处理多个 ID 请求
import com.yf.exam.core.api.dto.BaseStateReqDTO; import com.yf.exam.core.api.dto.BaseStateReqDTO; // 导入基本状态请求 DTO用于更新状态
import com.yf.exam.core.api.dto.PagingReqDTO; import com.yf.exam.core.api.dto.PagingReqDTO; // 导入分页请求 DTO
import com.yf.exam.modules.sys.user.dto.SysUserDTO; import com.yf.exam.modules.sys.user.dto.SysUserDTO; // 导入 SysUserDTO 数据传输对象
import com.yf.exam.modules.sys.user.dto.request.SysUserLoginReqDTO; import com.yf.exam.modules.sys.user.dto.request.SysUserLoginReqDTO; // 导入 SysUserLoginReqDTO 登录请求 DTO
import com.yf.exam.modules.sys.user.dto.request.SysUserSaveReqDTO; import com.yf.exam.modules.sys.user.dto.request.SysUserSaveReqDTO; // 导入 SysUserSaveReqDTO 保存请求 DTO
import com.yf.exam.modules.sys.user.dto.response.SysUserLoginDTO; import com.yf.exam.modules.sys.user.dto.response.SysUserLoginDTO; // 导入 SysUserLoginDTO 登录响应 DTO
import com.yf.exam.modules.sys.user.entity.SysUser; import com.yf.exam.modules.sys.user.entity.SysUser; // 导入 SysUser 实体类,表示系统用户
import com.yf.exam.modules.sys.user.service.SysUserService; import com.yf.exam.modules.sys.user.service.SysUserService; // 导入 SysUserService 服务接口
import io.swagger.annotations.Api; import io.swagger.annotations.Api; // 导入 Swagger 注解,用于定义 API 文档
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation; // 导入 Swagger 注解,用于描述接口操作
import org.apache.shiro.authz.annotation.RequiresRoles; import org.apache.shiro.authz.annotation.RequiresRoles; // 导入 Shiro 注解,用于角色权限控制
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired; // 导入 Spring 注解,用于自动注入依赖
import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.CrossOrigin; // 导入 Spring 注解,用于启用跨域请求
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody; // 导入 Spring 注解,用于请求体绑定
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping; // 导入 Spring 注解,用于指定请求路径
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod; // 导入 Spring 注解,用于指定请求方法
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam; // 导入 Spring 注解,用于请求参数绑定
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController; // 导入 Spring 注解,标识该类为 REST 控制器
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest; // 导入 HttpServletRequest 类,用于获取 HTTP 请求
/** /**
* <p> * <p>
* *
* </p> * </p>
*
* *
* @author * @
* @since 2020-04-13 16:57 * @ 2020-04-13 16:57
*/ */
@Api(tags = {"管理用户"}) @Api(tags = {"管理用户"}) // Swagger 注解:定义该类的 API 文档标签为“管理用户”
@RestController @RestController // Spring 注解:标识该类为 REST 控制器,处理 HTTP 请求
@RequestMapping("/exam/api/sys/user") @RequestMapping("/exam/api/sys/user") // 定义请求路径前缀为 /exam/api/sys/user
public class SysUserController extends BaseController { public class SysUserController extends BaseController { // SysUserController 类继承 BaseController提供通用功能
@Autowired @Autowired // 自动注入 SysUserService 服务
private SysUserService baseService; private SysUserService baseService;
/** /**
* *
* @return * @param reqDTO DTO
* @return
*/ */
@CrossOrigin @CrossOrigin // 允许跨域请求
@ApiOperation(value = "用户登录") @ApiOperation(value = "用户登录") // Swagger 注解:描述接口操作为“用户登录”
@RequestMapping(value = "/login", method = {RequestMethod.POST}) @RequestMapping(value = "/login", method = {RequestMethod.POST}) // 请求路径为 /login方法为 POST
public ApiRest<SysUserLoginDTO> login(@RequestBody SysUserLoginReqDTO reqDTO) { public ApiRest<SysUserLoginDTO> login(@RequestBody SysUserLoginReqDTO reqDTO) {
SysUserLoginDTO respDTO = baseService.login(reqDTO.getUsername(), reqDTO.getPassword()); SysUserLoginDTO respDTO = baseService.login(reqDTO.getUsername(), reqDTO.getPassword()); // 调用服务层的登录方法
return super.success(respDTO); return super.success(respDTO); // 返回成功响应,包含用户登录信息
} }
/** /**
* *
* @return * @param request HTTP token
* @return
*/ */
@CrossOrigin @CrossOrigin // 允许跨域请求
@ApiOperation(value = "用户登录") @ApiOperation(value = "用户登出") // Swagger 注解:描述接口操作为“用户登出”
@RequestMapping(value = "/logout", method = {RequestMethod.POST}) @RequestMapping(value = "/logout", method = {RequestMethod.POST}) // 请求路径为 /logout方法为 POST
public ApiRest logout(HttpServletRequest request) { public ApiRest logout(HttpServletRequest request) {
String token = request.getHeader("token"); String token = request.getHeader("token"); // 获取请求头中的 token
System.out.println("+++++当前会话为:"+token); System.out.println("+++++当前会话为:" + token); // 打印当前会话的 token
baseService.logout(token); baseService.logout(token); // 调用服务层的登出方法
return super.success(); return super.success(); // 返回成功响应
} }
/** /**
* *
* @return * @param token token
* @return
*/ */
@ApiOperation(value = "获取会话") @ApiOperation(value = "获取会话") // Swagger 注解:描述接口操作为“获取会话”
@RequestMapping(value = "/info", method = {RequestMethod.POST}) @RequestMapping(value = "/info", method = {RequestMethod.POST}) // 请求路径为 /info方法为 POST
public ApiRest info(@RequestParam("token") String token) { public ApiRest info(@RequestParam("token") String token) {
SysUserLoginDTO respDTO = baseService.token(token); SysUserLoginDTO respDTO = baseService.token(token); // 根据 token 获取当前会话信息
return success(respDTO); return success(respDTO); // 返回会话信息
} }
/** /**
* *
* @return * @param reqDTO DTO
* @return
*/ */
@ApiOperation(value = "修改用户资料") @ApiOperation(value = "修改用户资料") // Swagger 注解:描述接口操作为“修改用户资料”
@RequestMapping(value = "/update", method = {RequestMethod.POST}) @RequestMapping(value = "/update", method = {RequestMethod.POST}) // 请求路径为 /update方法为 POST
public ApiRest update(@RequestBody SysUserDTO reqDTO) { public ApiRest update(@RequestBody SysUserDTO reqDTO) {
baseService.update(reqDTO); baseService.update(reqDTO); // 调用服务层的更新方法
return success(); return success(); // 返回成功响应
} }
/** /**
* *
* @return * @param reqDTO DTO
* @return
*/ */
@RequiresRoles("sa") @RequiresRoles("sa") // 权限控制:要求用户具有 "sa" 角色
@ApiOperation(value = "保存或修改") @ApiOperation(value = "保存或修改") // Swagger 注解:描述接口操作为“保存或修改”
@RequestMapping(value = "/save", method = {RequestMethod.POST}) @RequestMapping(value = "/save", method = {RequestMethod.POST}) // 请求路径为 /save方法为 POST
public ApiRest save(@RequestBody SysUserSaveReqDTO reqDTO) { public ApiRest save(@RequestBody SysUserSaveReqDTO reqDTO) {
baseService.save(reqDTO); baseService.save(reqDTO); // 调用服务层的保存方法
return success(); return success(); // 返回成功响应
} }
/** /**
* *
* @param reqDTO * @param reqDTO DTO ID
* @return * @return
*/ */
@RequiresRoles("sa") @RequiresRoles("sa") // 权限控制:要求用户具有 "sa" 角色
@ApiOperation(value = "批量删除") @ApiOperation(value = "批量删除") // Swagger 注解:描述接口操作为“批量删除”
@RequestMapping(value = "/delete", method = { RequestMethod.POST}) @RequestMapping(value = "/delete", method = {RequestMethod.POST}) // 请求路径为 /delete方法为 POST
public ApiRest edit(@RequestBody BaseIdsReqDTO reqDTO) { public ApiRest edit(@RequestBody BaseIdsReqDTO reqDTO) {
//根据ID删除 baseService.removeByIds(reqDTO.getIds()); // 根据 ID 列表删除用户
baseService.removeByIds(reqDTO.getIds()); return super.success(); // 返回成功响应
return super.success();
} }
/** /**
* *
* @param reqDTO * @param reqDTO DTO
* @return * @return
*/ */
@RequiresRoles("sa") @RequiresRoles("sa") // 权限控制:要求用户具有 "sa" 角色
@ApiOperation(value = "分页查找") @ApiOperation(value = "分页查找") // Swagger 注解:描述接口操作为“分页查找”
@RequestMapping(value = "/paging", method = { RequestMethod.POST}) @RequestMapping(value = "/paging", method = {RequestMethod.POST}) // 请求路径为 /paging方法为 POST
public ApiRest<IPage<SysUserDTO>> paging(@RequestBody PagingReqDTO<SysUserDTO> reqDTO) { public ApiRest<IPage<SysUserDTO>> paging(@RequestBody PagingReqDTO<SysUserDTO> reqDTO) {
//分页查询并转换 // 调用服务层的分页查询方法
IPage<SysUserDTO> page = baseService.paging(reqDTO); IPage<SysUserDTO> page = baseService.paging(reqDTO);
return super.success(page); return super.success(page); // 返回成功响应,包含分页数据
} }
/** /**
* *
* @param reqDTO * @param reqDTO DTO ID
* @return * @return
*/ */
@RequiresRoles("sa") @RequiresRoles("sa") // 权限控制:要求用户具有 "sa" 角色
@ApiOperation(value = "修改状态") @ApiOperation(value = "修改状态") // Swagger 注解:描述接口操作为“修改状态”
@RequestMapping(value = "/state", method = { RequestMethod.POST}) @RequestMapping(value = "/state", method = {RequestMethod.POST}) // 请求路径为 /state方法为 POST
public ApiRest state(@RequestBody BaseStateReqDTO reqDTO) { public ApiRest state(@RequestBody BaseStateReqDTO reqDTO) {
// 条件 // 构建查询条件:排除 admin 用户
QueryWrapper<SysUser> wrapper = new QueryWrapper<>(); QueryWrapper<SysUser> wrapper = new QueryWrapper<>();
wrapper.lambda() wrapper.lambda()
.in(SysUser::getId, reqDTO.getIds()) .in(SysUser::getId, reqDTO.getIds()) // 根据 ID 列表查询
.ne(SysUser::getUserName, "admin"); .ne(SysUser::getUserName, "admin"); // 排除用户名为 admin 的用户
SysUser record = new SysUser(); SysUser record = new SysUser();
record.setState(reqDTO.getState()); record.setState(reqDTO.getState()); // 设置用户状态
baseService.update(record, wrapper); baseService.update(record, wrapper); // 更新状态
return super.success(); return super.success(); // 返回成功响应
} }
/** /**
* *
* @return * @param reqDTO DTO
* @return
*/ */
@ApiOperation(value = "学员注册") @ApiOperation(value = "学员注册") // Swagger 注解:描述接口操作为“学员注册”
@RequestMapping(value = "/reg", method = {RequestMethod.POST}) @RequestMapping(value = "/reg", method = {RequestMethod.POST}) // 请求路径为 /reg方法为 POST
public ApiRest<SysUserLoginDTO> reg(@RequestBody SysUserDTO reqDTO) { public ApiRest<SysUserLoginDTO> reg(@RequestBody SysUserDTO reqDTO) {
SysUserLoginDTO respDTO = baseService.reg(reqDTO); SysUserLoginDTO respDTO = baseService.reg(reqDTO); // 调用服务层的注册方法
return success(respDTO); return success(respDTO); // 返回注册后的用户登录信息
} }
/** /**
* *
* @return * @param reqDTO DTO
* @return
*/ */
@ApiOperation(value = "快速注册") @ApiOperation(value = "快速注册") // Swagger 注解:描述接口操作为“快速注册”
@RequestMapping(value = "/quick-reg", method = {RequestMethod.POST}) @RequestMapping(value = "/quick-reg", method = {RequestMethod.POST}) // 请求路径为 /quick-reg方法为 POST
public ApiRest<SysUserLoginDTO> quick(@RequestBody SysUserDTO reqDTO) { public ApiRest<SysUserLoginDTO> quick(@RequestBody SysUserDTO reqDTO) {
SysUserLoginDTO respDTO = baseService.quickReg(reqDTO); SysUserLoginDTO respDTO = baseService.quickReg(reqDTO); // 调用服务层的快速注册方法
return success(respDTO); return success(respDTO); // 返回快速注册后的用户登录信息
} }
} }

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save