diff --git a/.idea/compiler.xml b/.idea/compiler.xml index c8b1f76..383a244 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -10,4 +10,9 @@ + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..dfc8d74 --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml index 03d9549..0ca621c 100644 --- a/.idea/inspectionProfiles/Project_Default.xml +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -2,5 +2,6 @@ \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100644 index 0000000..712ab9d --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml new file mode 100644 index 0000000..2b63946 --- /dev/null +++ b/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 6c0b863..288b36b 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -2,5 +2,6 @@ + \ No newline at end of file diff --git a/README.md b/README.md index 5f10b26..40c4086 100644 --- a/README.md +++ b/README.md @@ -33,9 +33,9 @@ cd spring-boot-online-exam + 支持单选题、多选题、判断题 + 支持学生(student)、教师(teacher)、管理员(admin)三种角色 - + 学生:参加考试和查看我的考试 - + 教师:学生的所有权限+创建/编辑题目+创建/编辑考试 - + 管理员:教师的所有权限+管理用户 + + 学生:参加考试和查看我的考试 + + 教师:学生的所有权限+创建/编辑题目+创建/编辑考试 + + 管理员:教师的所有权限+管理用户 ### 2.3 软件架构 @@ -55,35 +55,35 @@ cd spring-boot-online-exam + 3.启动后端 > 打开`spring-boot-online-exam/backend/exam`这个Maven项目,可以在IDE里启动或者执行`mvn install`生成jar包启动 + 4.启动前端 - + 进入到前端代码路径 `cd spring-boot-online-exam/frontend/exam/` - + 安装依赖 `npm install` - + 启动前端 `npm run serve` + + 进入到前端代码路径 `cd spring-boot-online-exam/frontend/exam/` + + 安装依赖 `npm install` + + 启动前端 `npm run serve` + 5.部署完毕,查看效果 > 打开 http://localhost:8000 或者 http://本机ip:8000 即可查看演示效果 ## 3.功能图示 + 1.管理题目 - + 1.1 题目列表 - > ![题目查看](doc/images/question_list.png) - + 1.2 题目创建 - > ![题目创建](doc/images/question_create.png) - + 1.3 题目更新 - > ![题目更新](doc/images/question_update.png) + + 1.1 题目列表 + > ![题目查看](doc/images/question_list.png) + + 1.2 题目创建 + > ![题目创建](doc/images/question_create.png) + + 1.3 题目更新 + > ![题目更新](doc/images/question_update.png) + 2.考试管理 - + 2.1 考试列表 - > ![考试查看](doc/images/exam_list.png) - + 2.2 考试创建 - > ![考试创建](doc/images/exam_create.png) - + 2.3 考试更新(`还有点小bug,开发中`) - > ![考试更新](doc/images/exam_update.png) + + 2.1 考试列表 + > ![考试查看](doc/images/exam_list.png) + + 2.2 考试创建 + > ![考试创建](doc/images/exam_create.png) + + 2.3 考试更新(`还有点小bug,开发中`) + > ![考试更新](doc/images/exam_update.png) + 3.我的考试 - + 3.1 参加考试 - > 在"考试列表"模块点击自己想参加的考试卡片即可 - > ![参加考试1](doc/images/exam_join.png) - > ![参加考试2](doc/images/exam_join2.png) - + 3.2 考试记录查看 - > ![考试记录查看](doc/images/exam_detail.png) + + 3.1 参加考试 + > 在"考试列表"模块点击自己想参加的考试卡片即可 + > ![参加考试1](doc/images/exam_join.png) + > ![参加考试2](doc/images/exam_join2.png) + + 3.2 考试记录查看 + > ![考试记录查看](doc/images/exam_detail.png) ## 4.参与贡献 diff --git a/backend/src/main/java/lsgwr/exam/ExamApplication.java b/backend/src/main/java/lsgwr/exam/ExamApplication.java index 28458d1..b192019 100644 --- a/backend/src/main/java/lsgwr/exam/ExamApplication.java +++ b/backend/src/main/java/lsgwr/exam/ExamApplication.java @@ -1,12 +1,17 @@ +// 指定当前类所在的包路径,这是Java中组织类的一种方式,有助于类的管理和访问控制。 package lsgwr.exam; - +// 导入Spring Boot的启动类和应用配置自动装配的注解类。 import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; - +// @SpringBootApplication是一个方便的注解,它包括了@Configuration,@EnableAutoConfiguration,和@ComponentScan注解。 +// 它告诉Spring Boot基于当前类所在包及其子包下的组件来启动自动配置和组件扫描。 @SpringBootApplication public class ExamApplication { - - public static void main(String[] args) { + // main方法是Java应用程序的入口点。当运行这个类时,JVM会调用这个方法。 + public static void main(String[] args) + { + // SpringApplication.run方法启动Spring应用,传入ExamApplication.class(当前启动类)和main方法的参数args。 + // 这个方法会执行一系列的操作,包括启动Spring容器,加载应用上下文,自动配置等。 SpringApplication.run(ExamApplication.class, args); } } diff --git a/backend/src/main/java/lsgwr/exam/controller/ExamController.java b/backend/src/main/java/lsgwr/exam/controller/ExamController.java index e6ed4d0..96d8f98 100644 --- a/backend/src/main/java/lsgwr/exam/controller/ExamController.java +++ b/backend/src/main/java/lsgwr/exam/controller/ExamController.java @@ -1,9 +1,6 @@ -/*********************************************************** - * @Description : 考试服务 - * @author : 梁山广(Laing Shan Guang) - * @date : 2019-05-28 08:04 - * @email : liangshanguang2@gmail.com - ***********************************************************/ +/** + * @Description : 这是一个REST控制器,处理与考试、问题和考试记录相关的HTTP请求,它包括创建、更新和检索考试和问题的方法,以及处理用户提交和评分。 + */ package lsgwr.exam.controller; import lsgwr.exam.entity.Exam; @@ -22,221 +19,350 @@ import java.util.List; @RestController @Api(tags = "Exam APIs") +//将此控制器中的所有端点映射到/api/exam URL路径 @RequestMapping("/api/exam") public class ExamController { - @Autowired + @Autowired //注入一个ExamService实例,用于处理与考试和问题相关的业务逻辑 private ExamService examService; + /** + * @Description: 使用examService.getQuestionAll()获取数据,并将其包装在ResultVO对象中,用于获取所有考试列表 + * @ApiOperation注解用于描述API操作,它将显示在SwaggerUI中 + */ @GetMapping("/question/all") @ApiOperation("获取所有问题的列表") - ResultVO> getQuestionAll() { + // 获取全部问题列表。 +ResultVO> getQuestionAll() { + // 定义返回值。 ResultVO> resultVO; try { + // 调用examService获取全部问题列表。 List questionAll = examService.getQuestionAll(); + // 返回成功结果。 resultVO = new ResultVO<>(0, "获取全部问题列表成功", questionAll); } catch (Exception e) { + // 打印异常信息。 e.printStackTrace(); + // 返回失败结果。 resultVO = new ResultVO<>(-1, "获取全部问题列表失败", null); } + // 返回结果。 return resultVO; } @PostMapping("/question/update") @ApiOperation("更新问题") ResultVO questionUpdate(@RequestBody QuestionVo questionVo) { - // 完成问题的更新 + // 完成问题的更新。 System.out.println(questionVo); try { + // 调用examService的updateQuestion方法,更新问题。 QuestionVo questionVoResult = examService.updateQuestion(questionVo); + // 返回更新成功的结果。 return new ResultVO<>(0, "更新问题成功", questionVoResult); } catch (Exception e) { + // 打印异常信息。 e.printStackTrace(); + // 返回更新失败的结果。 return new ResultVO<>(-1, "更新问题失败", null); } } + /** + * 创建问题 + * @Description: 从请求体中获取一个QuestionCreateSimplifyVo对象,将其属性复制到QuestionCreateVo,设置创建者的ID,并使用examService.questionCreate()创建问题。 + * @param questionCreateSimplifyVo 从请求体中获取的QuestionCreateSimplifyVo对象 + * @param request HttpServletRequest对象,用于获取当前用户的ID + * @return ResultVO 对象,包含操作结果信息 + */ @PostMapping("/question/create") @ApiOperation("创建问题") ResultVO questionCreate(@RequestBody QuestionCreateSimplifyVo questionCreateSimplifyVo, HttpServletRequest request) { + // 创建一个QuestionCreateVo对象。 QuestionCreateVo questionCreateVo = new QuestionCreateVo(); - // 把能拷贝过来的属性都拷贝过来 + // 把能拷贝过来的属性都拷贝过来。 BeanUtils.copyProperties(questionCreateSimplifyVo, questionCreateVo); - // 设置创建者信息 + // 设置创建者信息。 String userId = (String) request.getAttribute("user_id"); questionCreateVo.setQuestionCreatorId(userId); System.out.println(questionCreateVo); try { + // 调用examService的questionCreate方法创建问题。 examService.questionCreate(questionCreateVo); + // 返回问题创建成功的ResultVO。 return new ResultVO<>(0, "问题创建成功", null); } catch (Exception e) { + // 打印异常信息。 e.printStackTrace(); + // 返回创建问题失败的ResultVO。 return new ResultVO<>(-1, "创建问题失败", null); } } + /** + * @Description: 获取全部问题列表,使用examService.getSelections()获取数据,并将其包装在ResultVO对象中 + * @return ResultVO 对象,包含问题列表 + */ @GetMapping("/question/selection") @ApiOperation("获取问题分类的相关选项") - ResultVO getSelections() { + // 获取问题分类选项。 +ResultVO getSelections() { + // 调用examService的getSelections方法获取问题分类选项。 QuestionSelectionVo questionSelectionVo = examService.getSelections(); + // 如果获取成功。 if (questionSelectionVo != null) { + // 返回成功的结果。 return new ResultVO<>(0, "获取问题分类选项成功", questionSelectionVo); } else { + // 否则返回失败的结果。 return new ResultVO<>(-1, "获取问题分类选项失败", null); } } + /** + * @Description: 使用examService.getQuestionDetail(id)获取数据,并将其包装在ResultVO对象中,用于获取全部问题列表 + * @param id 问题id + * @return ResultVO 对象,包含问题详情 + */ @GetMapping("/question/detail/{id}") @ApiOperation("根据问题的id获取问题的详细信息") ResultVO getQuestionDetail(@PathVariable String id) { - // 根据问题id获取问题的详细信息 + // 根据问题id获取问题的详细信息。 System.out.println(id); ResultVO resultVO; try { + // 调用examService的getQuestionDetail方法,根据问题id获取问题的详细信息。 QuestionDetailVo questionDetailVo = examService.getQuestionDetail(id); + // 如果获取成功,则返回ResultVO对象,状态码为0,提示信息为"获取问题详情成功",数据为questionDetailVo。 resultVO = new ResultVO<>(0, "获取问题详情成功", questionDetailVo); } catch (Exception e) { + // 如果获取失败,则打印异常信息,并返回ResultVO对象,状态码为-1,提示信息为"获取问题详情失败",数据为null。 e.printStackTrace(); + // 创建一个表示获取失败的ResultVO对象,状态码设置为 -1,表示获取操作失败,消息设置为"获取问题详情失败",数据部分设置为null resultVO = new ResultVO<>(-1, "获取问题详情失败", null); } + // 返回ResultVO对象。 return resultVO; } + /** + * @Description: 使用examService.getExamAll()获取数据,并将其包装在ResultVO对象中,用于获取全部考试列表 + * @return ResultVO 对象,包含考试列表详情 + */ @GetMapping("/all") @ApiOperation("获取全部考试的列表") ResultVO> getExamAll() { - // 需要拼接前端需要的考试列表对象 + // 需要拼接前端需要的考试列表对象。 ResultVO> resultVO; try { + // 调用examService的getExamAll方法获取全部考试的列表。 List examVos = examService.getExamAll(); + // 将获取到的考试列表封装到ResultVO对象中,并返回。 resultVO = new ResultVO<>(0, "获取全部考试的列表成功", examVos); } catch (Exception e) { + // 捕获异常,并打印异常信息。 e.printStackTrace(); + // 将异常信息封装到ResultVO对象中,并返回。 resultVO = new ResultVO<>(-1, "获取全部考试的列表失败", null); } return resultVO; } + /** + * @Description: 使用examService.getExamQuestionTypeList()获取数据,并将其包装在ResultVO对象中,用于获取问题列表 + * @return ResultVO 对象,包含问题列表 + */ @GetMapping("/question/type/list") @ApiOperation("获取问题列表,按照单选、多选和判断题分类返回") ResultVO getExamQuestionTypeList() { - // 获取问题的分类列表 + // 获取问题的分类列表。 ResultVO resultVO; try { + // 调用examService的getExamQuestionType方法获取问题分类列表。 ExamQuestionTypeVo examQuestionTypeVo = examService.getExamQuestionType(); + // 如果获取成功,则返回成功的结果。 resultVO = new ResultVO<>(0, "获取问题列表成功", examQuestionTypeVo); } catch (Exception e) { + // 如果获取失败,则打印异常信息,并返回失败的结果。 e.printStackTrace(); resultVO = new ResultVO<>(-1, "获取问题列表失败", null); } + // 返回结果。 return resultVO; } + /** + * @Description: 使用examService.createExam()获取数据,并将其包装在ResultVO对象中,用于获取问题列表 + * @param examCreateVo 前端传过来的参数 + * @param request 获取用户id + * @return ResultVO 对象,包含考试信息 + */ @PostMapping("/create") @ApiOperation("创建考试") ResultVO createExam(@RequestBody ExamCreateVo examCreateVo, HttpServletRequest request) { - // 从前端传参数过来,在这里完成考试的入库 + // 定义一个ResultVO类型的变量,用于存放最终要返回给客户端的结果对象,其泛型参数指定为Exam,表示包含新创建考试相关信息的结果封装 ResultVO resultVO; + // 从HttpServletRequest对象中获取用户ID信息,通常这个用户ID是在请求处理的前置环节(比如拦截器中)设置到请求属性中的,用于标识创建这个考试的用户是谁 String userId = (String) request.getAttribute("user_id"); try { + // 调用ExamService的create方法,将创建考试的视图对象(examCreateVo)和获取到的用户ID传递进去,由服务层实现将考试记录数据保存到数据库等具体的创建逻辑操作,返回创建好的Exam对象代表新创建的考试信息 Exam exam = examService.create(examCreateVo, userId); + // 如果创建成功,创建一个表示成功的ResultVO对象,状态码设置为0,表示创建操作成功,消息设置为"创建考试成功",并将创建好的考试对象放入ResultVO对象中返回给客户端 resultVO = new ResultVO<>(0, "创建考试成功", exam); } catch (Exception e) { e.printStackTrace(); + // 如果在创建过程中出现异常,创建一个表示创建失败的ResultVO对象,状态码设置为 -1,表示创建操作失败,消息设置为"创建考试失败",数据部分设置为null resultVO = new ResultVO<>(-1, "创建考试失败", null); } return resultVO; } - + /** + * @Description: 使用examService.updateExam()获取数据,并将其包装在ResultVO对象中,用于更新考试 + * @param examVo 前端传过来的参数 + * @param request 获取用户id + * @return + */ @PostMapping("/update") @ApiOperation("更新考试") ResultVO updateExam(@RequestBody ExamVo examVo, HttpServletRequest request) { - // 从前端传参数过来,在这里完成考试的入库 + // 从前端传参数过来,在这里完成考试的入库。 ResultVO resultVO; + // 获取当前用户id。 String userId = (String) request.getAttribute("user_id"); try { + // 调用service层更新考试。 Exam exam = examService.update(examVo, userId); + // 返回更新成功的resultVO。 resultVO = new ResultVO<>(0, "更新考试成功", exam); } catch (Exception e) { + // 打印异常信息。 e.printStackTrace(); + // 返回更新失败的resultVO。 resultVO = new ResultVO<>(-1, "更新考试失败", null); } return resultVO; } - + /** + * @Description: 获取考试列表,适配前端卡片列表 + * @return ResultVO> 对象,包含考试列表卡片信息 + */ @GetMapping("/card/list") @ApiOperation("获取考试列表,适配前端卡片列表") ResultVO> getExamCardList() { - // 获取考试列表卡片 + // 获取考试列表卡片。 ResultVO> resultVO; try { + // 调用examService的getExamCardList方法获取考试列表卡片。 List examCardVoList = examService.getExamCardList(); + // 如果获取数据成功,创建一个表示成功的ResultVO对象,状态码设置为0,表示获取考试列表卡片成功,消息设置为"获取考试列表卡片成功",并将获取到的考试卡片列表数据放入ResultVO对象中,以便返回给客户端进行展示。 resultVO = new ResultVO<>(0, "获取考试列表卡片成功", examCardVoList); } catch (Exception e) { + // 如果获取失败,则打印异常信息,并返回失败的结果。 e.printStackTrace(); + // 创建一个表示获取失败的ResultVO对象,状态码设置为 -1,表示获取考试列表卡片失败,消息可根据业务实际情况设置为相应的提示语,数据部分设置为null,因为没有成功获取到有效的考试卡片列表数据。 resultVO = new ResultVO<>(-1, "获取考试列表卡片失败", null); } return resultVO; } - + /** + * @Description: 根据考试的id,获取考试详情 + * @param id 考试id + * @return ResultVO 对象,包含考试详情信息 + */ @GetMapping("/detail/{id}") @ApiOperation("根据考试的id,获取考试详情") ResultVO getExamDetail(@PathVariable String id) { - // 根据id获取考试详情 + // 根据id获取考试详情,先定义一个用于存放最终要返回给客户端的ResultVO类型的结果对象,后续根据查询数据的情况进行赋值操作。 ResultVO resultVO; try { + // 调用ExamService的getExamDetail方法,将接收到的考卷唯一标识符(id)传递进去,由服务层实现从数据库或者其他数据源根据该ID查询对应考卷详细信息的逻辑,返回一个ExamDetailVo对象代表该考卷的所有详细信息。 ExamDetailVo examDetail = examService.getExamDetail(id); + // 如果获取详细信息成功,创建一个表示成功的ResultVO对象,状态码设置为0,表示获取考试详情成功,消息设置为"获取考试详情成功",并将获取到的考卷详细信息对象放入ResultVO对象中,以便返回给客户端进行展示。 resultVO = new ResultVO<>(0, "获取考试详情成功", examDetail); } catch (Exception e) { + // 如果在获取考卷详细信息的过程中出现异常,创建一个表示获取失败的ResultVO对象,状态码设置为 -1,表示获取考试详情失败,消息可根据业务实际情况设置为相应的提示语,数据部分设置为null,因为没有成功获取到有效的考卷详细信息。 resultVO = new ResultVO<>(-1, "获取考试详情失败", null); } return resultVO; } - + /** + * @Description: 使用examService.finishExam获取数据,并将其包装在ResultVO对象中,用于考试判分 + * @param examId 考试id + * @param answersMap 用户提交的答案 + * @param request 获取用户id + * @return + */ @PostMapping("/finish/{examId}") @ApiOperation("根据用户提交的答案对指定id的考试判分") ResultVO finishExam(@PathVariable String examId, @RequestBody HashMap> answersMap, HttpServletRequest request) { + // 定义一个用于存放结果的ResultVO类型的数据结构,后续根据评分操作的成功与否以及获取到的相关数据进行赋值,用于最终返回给客户端展示评分结果。 ResultVO resultVO; try { - // 拦截器里设置上的用户id + // 拦截器里设置上的用户id,从HttpServletRequest对象中获取用户ID属性值,该用户ID用于标识当前提交答案并进行评分的用户,是后续业务逻辑处理(如记录答题记录归属、判断是否有权限答题等)的重要依据。 String userId = (String) request.getAttribute("user_id"); - // 下面根据用户提交的信息进行判分,返回用户的得分情况 + // 下面根据用户提交的信息进行判分,返回用户的得分情况,调用ExamService的judge方法,传入获取到的用户ID、考试唯一标识符(examId)以及用户提交的答案集合(answersMap),由服务层实现具体的评分逻辑,比如对比答案、计算得分等操作,并返回一个ExamRecord对象,包含了评分后的成绩记录等详细信息。 ExamRecord examRecord = examService.judge(userId, examId, answersMap); - resultVO = new ResultVO<>(0, "考卷提交成功", examRecord); + // 封装成绩记录到最终结果中,创建一个表示评分成功的ResultVO对象,状态码设置为0,表示考卷提交(评分)成功,消息设置为"考卷提交成功",并将包含成绩记录的ExamRecord对象放入ResultVO对象中,以便返回给客户端展示评分结果。 + resultVO = new ResultVO<>(0, "考卷提交成功", examRecord);// 封装成绩记录到最终结果中 } catch (Exception e) { + // 如果在评分过程中出现异常,打印异常堆栈信息,方便开发人员排查问题,查看是答案解析出错还是其他业务逻辑环节出现的错误导致评分失败。 e.printStackTrace(); + // 创建一个表示评分失败的ResultVO对象,状态码设置为 -1,表示考卷提交(评分)失败,消息可根据业务实际情况设置为相应的提示语,数据部分设置为null,因为没有成功获取到有效的评分成绩记录。 resultVO = new ResultVO<>(-1, "考卷提交失败", null); } return resultVO; } - + /** + * @Description: 使用examService.getExamRecordList获取数据,并将其包装在ResultVO对象中,用于获取当前用户的考试记录 + * @param request 获取用户id + * @return ResultVO> 返回一个包含考试记录列表的ResultVO对象,如果发生异常,则返回一个包含错误信息的ResultVO对象。 + */ @GetMapping("/record/list") @ApiOperation("获取当前用户的考试记录") ResultVO> getExamRecordList(HttpServletRequest request) { + // 定义一个用于存放结果的ResultVO>类型的数据结构,后续根据查询用户考试记录操作的成功与否以及获取到的相关数据进行赋值,用于最终返回给客户端展示查询结果。 ResultVO> resultVO; try { - // 拦截器里设置上的用户id + // 拦截器里设置上的用户id,从HttpServletRequest对象中获取用户ID属性值,该用户ID用于明确要查询其考试记录的目标用户,是服务层准确获取对应数据的关键依据。 String userId = (String) request.getAttribute("user_id"); - // 下面根据用户账号拿到他(她所有的考试信息),注意要用VO封装下 + // 下面根据用户账号拿到他(她)所有的考试信息,注意要用VO封装下,调用ExamService的getExamRecordList方法,传入获取到的用户ID,由服务层实现从数据库或者其他数据源获取该用户所有历史考试记录数据的逻辑,并将其整理封装成List类型的列表返回,每个ExamRecordVo对象包含了如时间、得分等详细信息。 List examRecordVoList = examService.getExamRecordList(userId); - resultVO = new ResultVO<>(0, "获取考试记录成功", examRecordVoList); + // 封装查询得到的信息到最终结果中,创建一个表示获取成功的ResultVO对象,状态码设置为0,表示获取考试记录成功,消息设置为"获取考试记录成功",并将获取到的用户考试记录列表数据放入ResultVO对象中,以便返回给客户端展示历史考试记录情况。 + resultVO = new ResultVO<>(0, "获取考试记录成功", examRecordVoList);//封装查询得到的信息到最终结果中; } catch (Exception e) { + // 如果在获取用户考试记录数据的过程中出现异常,打印异常堆栈信息,方便开发人员排查问题,查看是数据源查询出错还是数据封装等环节出现的错误导致获取失败。 e.printStackTrace(); + // 创建一个表示获取失败的ResultVO对象,状态码设置为 -1,表示获取考试记录失败,消息可根据业务实际情况设置为相应的提示语,数据部分设置为null,因为没有成功获取到有效的用户考试记录数据。 resultVO = new ResultVO<>(-1, "获取考试记录失败", null); } - return resultVO; + return resultVO;//返回封装好的 数据结构 } - + /** + * @Description: 使用examService.getExamRecordDetail获取数据,并将其包装在ResultVO对象中,用于获取指定id的考试记录详情 + * @param recordId 考试记录id + * @return ResultVO 返回一个包含考试记录详情的ResultVO对象,如果发生异常,则返回一个包含错误信息的ResultVO对象。 + */ @GetMapping("/record/detail/{recordId}") @ApiOperation("根据考试记录id获取考试记录详情") ResultVO getExamRecordDetail(@PathVariable String recordId) { + // 定义一个用于存放结果的ResultVO类型的数据结构,后续根据查询测验详细情况操作的成功与否以及获取到的相关数据进行赋值,用于最终返回给客户端展示查询结果。 ResultVO resultVO; try { + // 调用ExamService的getRecordDetail方法,将接收到的测验记录唯一标识符(recordId)传递进去,由服务层实现从数据库或者其他数据源根据该ID查询对应测验详细信息的逻辑,返回一个RecordDetailVo对象代表该次测验的所有详细信息。 RecordDetailVo recordDetailVo = examService.getRecordDetail(recordId); - resultVO = new ResultVO<>(0, "获取考试记录详情成功", recordDetailVo); + // 封装查询得到的信息到最终结果中,创建一个表示获取成功的ResultVO对象,状态码设置为0,表示获取考试记录详情成功,消息设置为"获取考试记录详情成功",并将获取到的测验详细信息对象放入ResultVO对象中,以便返回给客户端展示该次测验的详细情况。 + resultVO = new ResultVO<>(0, "获取考试记录详情成功", recordDetailVo);//封装查询得到的信息到最终结果中; } catch (Exception e) { + // 如果在获取测验详细信息的过程中出现异常,打印异常堆栈信息,方便开发人员排查问题,查看是数据源查询出错还是数据解析等环节出现的错误导致获取失败。 e.printStackTrace(); + // 创建一个ResultVO对象,表示操作失败 + // 状态码设置为-1,表示获取考试记录详情失败 + // 消息设置为"获取考试记录详情失败" + // 由于查询失败,详细信息对象设置为null resultVO = new ResultVO<>(-1, "获取考试记录详情失败", null); } + // 返回封装好的ResultVO对象给客户端 + // 客户端可以根据状态码和消息判断操作是否成功,并根据详细信息对象获取测验的详细记录信息 return resultVO; } } diff --git a/backend/src/main/java/lsgwr/exam/controller/UploadDownloadController.java b/backend/src/main/java/lsgwr/exam/controller/UploadDownloadController.java index e9d2392..35c7cc2 100644 --- a/backend/src/main/java/lsgwr/exam/controller/UploadDownloadController.java +++ b/backend/src/main/java/lsgwr/exam/controller/UploadDownloadController.java @@ -42,37 +42,49 @@ public class UploadDownloadController { @ApiOperation("单文件上传,支持同时传入参数") @PostMapping("/api/upload/singleAndparas") - public String uploadFileSingle(@RequestParam("dir") String dir, @RequestParam("file") MultipartFile uploadfile) { + // 单文件上传。 + public String uploadFileSingle(@RequestParam("dir") String dir, @RequestParam("file") MultipartFile uploadfile) { + // 调用FileTransUtil工具类中的uploadFile方法,将上传的文件和目录作为参数传入。 return FileTransUtil.uploadFile(uploadfile, dir); } + // 单文件上传,支持同时传入参数,Model。 @ApiOperation("单文件上传,支持同时传入参数,Model") @PostMapping("/upload/single/model") public String singleUploadFileModel(@ModelAttribute("model") UploadModel2 model) { + // 调用FileTransUtil工具类中的uploadFile方法,将上传的文件和目录作为参数传入。 return FileTransUtil.uploadFile(model.getFile(), model.getDir()); } + // 多文件上传,支持同时传入参数。 @ApiOperation("多文件上传,支持同时传入参数") @PostMapping("upload/multiAndparas") public String uploadFileMulti(@RequestParam("dir") String dir, @RequestParam("files") MultipartFile[] uploadfiles) { + // 调用FileTransUtil工具类中的uploadFiles方法,将上传的文件数组和目录作为参数传入。 return FileTransUtil.uploadFiles(uploadfiles, dir); } + // 多文件上传,支持同时传入参数。 @ApiOperation("多文件上传,支持同时传入参数") @PostMapping(value = "/upload/multi/model") public String multiUploadFileModel(@ModelAttribute(("model")) UploadModel model) { + // 调用FileTransUtil工具类中的uploadFiles方法,将上传的文件数组和目录作为参数传入。 return FileTransUtil.uploadFiles(model.getFiles(), model.getDir()); } + // Get下载文件 @ApiOperation("Get下载文件") @GetMapping(value = "/download/get") public ResponseEntity downloadFileGet(@RequestParam String filePath) throws IOException { + // 调用FileTransUtil工具类中的downloadFile方法,将文件路径作为参数传入。 return FileTransUtil.downloadFile(filePath); } + // Post下载文件 @ApiOperation("Post下载文件") @PostMapping(value = "/download/post") public ResponseEntity downloadFilePost(@RequestBody DownloadQo downloadQo) throws IOException { + // 调用FileTransUtil工具类中的downloadFile方法,将文件路径作为参数传入。 return FileTransUtil.downloadFile(downloadQo.getPath()); } } diff --git a/backend/src/main/java/lsgwr/exam/controller/UserController.java b/backend/src/main/java/lsgwr/exam/controller/UserController.java index 768b84d..862895f 100644 --- a/backend/src/main/java/lsgwr/exam/controller/UserController.java +++ b/backend/src/main/java/lsgwr/exam/controller/UserController.java @@ -62,18 +62,27 @@ public class UserController { @GetMapping("/user-info") @ApiOperation("获取用户信息") + // 根据请求获取用户信息 ResultVO getUserInfo(HttpServletRequest request) { + // 从请求中获取用户ID String userId = (String) request.getAttribute("user_id"); + // 根据用户ID获取用户信息 UserVo userVo = userService.getUserInfo(userId); + // 返回用户信息 return new ResultVO<>(ResultEnum.GET_INFO_SUCCESS.getCode(), ResultEnum.GET_INFO_SUCCESS.getMessage(), userVo); } @GetMapping("/info") @ApiOperation("获取用户的详细信息,包括个人信息页面和操作权限") + // 获取用户信息的接口 ResultVO getInfo(HttpServletRequest request) { + // 打印进入接口的日志 System.out.println("进入/user/info的获取用户信息的接口"); + // 获取用户ID String userId = (String) request.getAttribute("user_id"); + // 调用userService获取用户信息 UserInfoVo userInfoVo = userService.getInfo(userId); + // 返回结果 return new ResultVO<>(ResultEnum.GET_INFO_SUCCESS.getCode(), ResultEnum.GET_INFO_SUCCESS.getMessage(), userInfoVo); } diff --git a/backend/src/main/java/lsgwr/exam/entity/Action.java b/backend/src/main/java/lsgwr/exam/entity/Action.java index 2c9d1df..8fb8180 100644 --- a/backend/src/main/java/lsgwr/exam/entity/Action.java +++ b/backend/src/main/java/lsgwr/exam/entity/Action.java @@ -11,17 +11,29 @@ import lombok.Data; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; - +/** + * 动作实体类 + * 它记录了操作的相关信息,包括操作ID、操作名称、操作描述以及是否默认选中 + */ @Data @Entity public class Action { + /** + * 动作ID + */ @Id @GeneratedValue private Integer actionId; - + /** + * 动作名称 + */ private String actionName; - + /** + * 动作描述 + */ private String actionDescription; - + /** + * 是否默认选中 + */ private Boolean defaultCheck; } diff --git a/backend/src/main/java/lsgwr/exam/entity/Exam.java b/backend/src/main/java/lsgwr/exam/entity/Exam.java index 5223eb2..4f074bc 100644 --- a/backend/src/main/java/lsgwr/exam/entity/Exam.java +++ b/backend/src/main/java/lsgwr/exam/entity/Exam.java @@ -4,51 +4,60 @@ * @date : 2019/5/14 07:42 * @email : liangshanguang2@gmail.com ***********************************************************/ - +// 定义包名,用于组织类文件,避免命名冲突 package lsgwr.exam.entity; - +// 导入Jackson库的JsonFormat注解,用于JSON序列化时自定义日期格式 import com.fasterxml.jackson.annotation.JsonFormat; +// 导入Lombok库的Data注解,用于自动生成getter、setter、equals、hashCode和toString方法 import lombok.Data; +// 导入Hibernate的DynamicUpdate注解,用于在实体更新时只更新发生变化的字段 import org.hibernate.annotations.DynamicUpdate; - +// 导入JPA的Entity注解,用于声明该类是一个JPA实体类 import javax.persistence.Entity; +// 导入JPA的Id注解,用于声明该类中的某个字段作为主键 import javax.persistence.Id; +// 导入Java的Date类,用于表示日期和时间 import java.util.Date; @Entity @Data @DynamicUpdate public class Exam { + // 使用JPA的@Id注解声明该字段为主键 @Id - private String examId; - private String examName; - private String examAvatar; - private String examDescription; - private String examQuestionIds; - private String examQuestionIdsRadio; - private String examQuestionIdsCheck; - private String examQuestionIdsJudge; - private Integer examScore; - private Integer examScoreRadio; - private Integer examScoreCheck; - private Integer examScoreJudge; - private String examCreatorId; - private Integer examTimeLimit; + private String examId;// 考试ID,唯一标识一场考试 + private String examName;// 考试名称 + private String examAvatar; // 考试头像或图标 + private String examDescription;// 考试描述或简介 + private String examQuestionIds;// 存储所有问题ID的字符串,可能是逗号分隔的ID列表 + private String examQuestionIdsRadio;// 存储所有单选题ID的字符串 + private String examQuestionIdsCheck;// 存储所有多选题ID的字符串 + private String examQuestionIdsJudge;// 存储所有判断题ID的字符串 + private Integer examScore;// 考试总分 + private Integer examScoreRadio;// 单选题总分 + private Integer examScoreCheck;// 多选题总分 + private Integer examScoreJudge;// 判断题总分 + private String examCreatorId;// 创建者ID,标识谁创建了这场考试 + private Integer examTimeLimit;// 考试时间限制,单位可能是分钟 + // 考试开始时间,使用Jackson的@JsonFormat注解自定义日期格式 @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date examStartDate; + // 考试结束时间 @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date examEndDate; /** - * 创建时间, 设计表时设置了自动插入当前时间,无需在Java代码中设置了 + * 创建时间,设计数据库表时设置了自动插入当前时间,因此在Java代码中无需手动设置。 + * 使用Jackson的@JsonFormat注解自定义日期格式以便于前端展示。 */ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date createTime; /** - * 更新时间,设计表时设置了自动插入当前时间,无需在Java代码中设置了。 - * 同时@DynamicUpdate注解可以时间当数据库数据变化时自动更新,无需人工维护 + * 更新时间,设计数据库表时也设置了自动插入当前时间(或更新为当前时间),在Java代码中无需手动维护。 + * 同时,由于使用了Hibernate的@DynamicUpdate注解,当数据库中的实体数据发生变化时,该字段会自动更新为当前时间。 + * 使用Jackson的@JsonFormat注解自定义日期格式以便于前端展示。 */ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date updateTime; diff --git a/backend/src/main/java/lsgwr/exam/entity/ExamRecord.java b/backend/src/main/java/lsgwr/exam/entity/ExamRecord.java index 5adda4b..b9522f2 100644 --- a/backend/src/main/java/lsgwr/exam/entity/ExamRecord.java +++ b/backend/src/main/java/lsgwr/exam/entity/ExamRecord.java @@ -7,42 +7,44 @@ package lsgwr.exam.entity; -import com.fasterxml.jackson.annotation.JsonFormat; -import lombok.Data; +import com.fasterxml.jackson.annotation.JsonFormat;// 引入Jackson库用于日期格式化的注解 +import lombok.Data;// 引入Lombok库用于简化Java实体类的编写,如自动生成getter和setter方法 -import javax.persistence.Entity; +import javax.persistence.Entity;// 引入JPA注解,用于标识这是一个实体类,并映射到数据库中的一张表 +// 引入JPA注解,用于标识实体类的主键字段 import javax.persistence.Id; import java.util.Date; - +// 使用@Data注解自动生成getter和setter方法,以及toString、equals和hashCode方法 @Data +// 使用@Entity注解标识这是一个JPA实体类 @Entity public class ExamRecord { /** - * 主键 + * 主键,用于唯一标识一条考试记录 */ @Id private String examRecordId; /** - * 参与的考试的id + * 关联的考试ID,用于标识考生参加的是哪一场考试 */ private String examId; /** - * 考生作答地每个题目的选项(题目和题目之间用_分隔,题目有多个选项地话用-分隔),用于查看考试详情 + * 考生作答的每个题目的选项,题目之间用下划线_分隔,若题目有多个选项则用短横线-分隔。这个字段用于查看考试详情时展示考生作答情况。 */ private String answerOptionIds; /** - * 参与者,即user的id + * 参与考试的考生ID,即用户的ID */ private String examJoinerId; /** - * 参加考试的日期 + * 参加考试的日期和时间 */ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date examJoinDate; /** - * 考试耗时(秒) + * 考试耗时,单位为秒 */ private Integer examTimeCost; /** @@ -50,7 +52,7 @@ public class ExamRecord { */ private Integer examJoinScore; /** - * 考试得分水平 + * 考试得分水平,通常根据得分划分不同的等级,如优秀、良好、及格等(具体等级需另建表定义) */ private Integer examResultLevel; -} +} \ No newline at end of file diff --git a/backend/src/main/java/lsgwr/exam/entity/ExamRecordLevel.java b/backend/src/main/java/lsgwr/exam/entity/ExamRecordLevel.java index 2aa08b3..f1285f0 100644 --- a/backend/src/main/java/lsgwr/exam/entity/ExamRecordLevel.java +++ b/backend/src/main/java/lsgwr/exam/entity/ExamRecordLevel.java @@ -7,18 +7,22 @@ package lsgwr.exam.entity; -import lombok.Data; - -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; +import lombok.Data;// 引入Lombok库中的@Data注解,用于自动生成getter、setter、toString、equals和hashCode方法 +import javax.persistence.Entity;// 引入JPA(Java Persistence API)中的@Entity注解,标识这是一个实体类,与数据库中的表相对应 +import javax.persistence.GeneratedValue;// 引入JPA中的@GeneratedValue注解,用于指定主键的生成策略,这里未明确指定策略,将使用默认策略 +import javax.persistence.Id;// 引入JPA中的@Id注解,标识实体类的主键字段 +// 使用@Data注解自动生成getter、setter等方法 @Data +// 使用@Entity注解标识这是一个JPA实体类 @Entity public class ExamRecordLevel { + // 考试记录等级的ID,是主键,通过@Id注解标识,并通过@GeneratedValue注解指定主键生成策略 @Id @GeneratedValue private Integer examRecordLevelId; + // 考试记录等级的名称,用于标识等级,如“优秀”、“良好”等 private String examRecordLevelName; + // 考试记录等级的描述,用于对等级进行更详细的说明 private String examRecordLevelDescription; -} +} \ No newline at end of file diff --git a/backend/src/main/java/lsgwr/exam/entity/Question.java b/backend/src/main/java/lsgwr/exam/entity/Question.java index 67adf0b..d2c050a 100644 --- a/backend/src/main/java/lsgwr/exam/entity/Question.java +++ b/backend/src/main/java/lsgwr/exam/entity/Question.java @@ -14,21 +14,54 @@ import org.hibernate.annotations.DynamicUpdate; import javax.persistence.Entity; import javax.persistence.Id; import java.util.Date; - +/** + * 题目实体类,用于存储题目信息 + * 利用注解生成getter/setter方法 + */ @Data @Entity @DynamicUpdate public class Question { + /** + * 题目id + */ @Id private String questionId; + /** + * 题目名称 + */ private String questionName; + /** + * 题目分数 + */ private Integer questionScore; + /** + * 题目创建人id + */ private String questionCreatorId; + /** + * 题目难度id + */ private Integer questionLevelId; + /** + * 题目类型id + */ private Integer questionTypeId; + /** + * 题目分类id + */ private Integer questionCategoryId; + /** + * 题目描述 + */ private String questionDescription; + /** + * 题目选项id,用逗号隔开,例如:A,B,C,D + */ private String questionOptionIds; + /** + * 题目正确答案选项id,用逗号隔开,例如:A + */ private String questionAnswerOptionIds; /** * 创建时间, 设计表时设置了自动插入当前时间,无需在Java代码中设置了 diff --git a/backend/src/main/java/lsgwr/exam/entity/QuestionCategory.java b/backend/src/main/java/lsgwr/exam/entity/QuestionCategory.java index ca08f22..a68dfdd 100644 --- a/backend/src/main/java/lsgwr/exam/entity/QuestionCategory.java +++ b/backend/src/main/java/lsgwr/exam/entity/QuestionCategory.java @@ -13,19 +13,27 @@ import lombok.Data; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; - +/** + * 题目的类别表,从内容角度划分,比如数学、语文、英语等 + */ @Data @Entity public class QuestionCategory { - + /** + * 题目类别的id + */ @Id @GeneratedValue @JsonProperty("id") private Integer questionCategoryId; - + /** + * 题目类别的名称 + */ @JsonProperty("name") private String questionCategoryName; - + /** + * 题目类别的描述 + */ @JsonProperty("description") private String questionCategoryDescription; } diff --git a/backend/src/main/java/lsgwr/exam/entity/QuestionLevel.java b/backend/src/main/java/lsgwr/exam/entity/QuestionLevel.java index a056cbc..d0c0fcd 100644 --- a/backend/src/main/java/lsgwr/exam/entity/QuestionLevel.java +++ b/backend/src/main/java/lsgwr/exam/entity/QuestionLevel.java @@ -14,17 +14,27 @@ import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; +/** + * 题目难度等级实体类,用于表示题目的难度级别信息,如难、中、易等。 + */ @Entity @Data public class QuestionLevel { + /** + * 题目难度等级ID,自增 + */ @Id @GeneratedValue @JsonProperty("id") private Integer questionLevelId; - + /** + * 题目难度等级名称,如难、中、易等 + */ @JsonProperty("name") private String questionLevelName; - + /** + * 题目难度等级描述 + */ @JsonProperty("description") private String questionLevelDescription; } diff --git a/backend/src/main/java/lsgwr/exam/entity/QuestionOption.java b/backend/src/main/java/lsgwr/exam/entity/QuestionOption.java index 3c06ef7..fc29400 100644 --- a/backend/src/main/java/lsgwr/exam/entity/QuestionOption.java +++ b/backend/src/main/java/lsgwr/exam/entity/QuestionOption.java @@ -11,12 +11,23 @@ import lombok.Data; import javax.persistence.Entity; import javax.persistence.Id; - +/** + * 问题选项实体类 + */ @Data @Entity public class QuestionOption { + /** + * 选项的编号,如A、B、C、D + */ @Id private String questionOptionId; + /** + * 选项的内容 + */ private String questionOptionContent; + /** + * 选项的描述,提供关于选项的额外解释或说明 + */ private String questionOptionDescription; } diff --git a/backend/src/main/java/lsgwr/exam/entity/QuestionType.java b/backend/src/main/java/lsgwr/exam/entity/QuestionType.java index 46a4f55..602a7b1 100644 --- a/backend/src/main/java/lsgwr/exam/entity/QuestionType.java +++ b/backend/src/main/java/lsgwr/exam/entity/QuestionType.java @@ -14,17 +14,28 @@ import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; +/** + * QuestionType类代表了一个实体,用于在数据库中存储问题类型的信息。 + * 它包括问题类型的ID、名称和描述。 + */ @Data @Entity public class QuestionType { + /** + * 问题类型ID + */ @Id @GeneratedValue @JsonProperty("id") private Integer questionTypeId; - + /** + * 问题类型名称 + */ @JsonProperty("name") private String questionTypeName; - + /** + * 问题类型的描述 + */ @JsonProperty("description") private String questionTypeDescription; } diff --git a/backend/src/main/java/lsgwr/exam/entity/Role.java b/backend/src/main/java/lsgwr/exam/entity/Role.java index 31d529a..dbb7b8d 100644 --- a/backend/src/main/java/lsgwr/exam/entity/Role.java +++ b/backend/src/main/java/lsgwr/exam/entity/Role.java @@ -13,14 +13,31 @@ import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; +/** + * 角色实体类 + * 用于表示系统中的角色信息,包括角色的ID、名称、描述和详细信息等 + */ @Data @Entity public class Role { + /** + * 角色ID + * @Id标识为主键 + */ @Id @GeneratedValue private Integer roleId; + /** + * 角色名称 + */ private String roleName; + /** + * 角色描述 + */ private String roleDescription; + /** + * 角色详细信息 + */ private String roleDetail; /** * 角色所能访问的页面的主键集合(用-连接起来字符串) diff --git a/backend/src/main/java/lsgwr/exam/entity/User.java b/backend/src/main/java/lsgwr/exam/entity/User.java index 23875bc..417ce93 100644 --- a/backend/src/main/java/lsgwr/exam/entity/User.java +++ b/backend/src/main/java/lsgwr/exam/entity/User.java @@ -14,20 +14,49 @@ import org.hibernate.annotations.DynamicUpdate; import javax.persistence.Entity; import javax.persistence.Id; import java.util.Date; - +/** + * 用户表,记录用户信息 + */ @Data @Entity @DynamicUpdate public class User { + /** + * 用户id,主键 + */ @Id private String userId; + /** + * 用户名,唯一 + */ private String userUsername; + /** + * 昵称 + */ private String userNickname; + /** + * 密码 + */ private String userPassword; + /** + * 角色id + */ private Integer userRoleId; + /** + * 头像 + */ private String userAvatar; + /** + * 描述 + */ private String userDescription; + /** + * 邮箱 + */ private String userEmail; + /** + * 电话 + */ private String userPhone; /** * 创建时间, 设计表时设置了自动插入当前时间,无需在Java代码中设置了 diff --git a/backend/src/main/java/lsgwr/exam/enums/LoginTypeEnum.java b/backend/src/main/java/lsgwr/exam/enums/LoginTypeEnum.java index 410aa30..5387a27 100644 --- a/backend/src/main/java/lsgwr/exam/enums/LoginTypeEnum.java +++ b/backend/src/main/java/lsgwr/exam/enums/LoginTypeEnum.java @@ -3,18 +3,18 @@ package lsgwr.exam.enums; import lombok.Getter; /** - * 用户账号类型的枚举 - * @author liangshanguang + * @Description: 用户账号类型的枚举 */ @Getter public enum LoginTypeEnum { /** - * 用户的账号类型,1代表用户名,2代表邮箱 + * @Description: 用户的账号类型 + * 1代表用户名,2代表邮箱 */ USERNAME(1, "用户名"), EMAIL(2, "邮箱"); - + // 构造函数用于初始化code和description LoginTypeEnum(Integer type, String name) { this.type = type; this.name = name; diff --git a/backend/src/main/java/lsgwr/exam/enums/QuestionEnum.java b/backend/src/main/java/lsgwr/exam/enums/QuestionEnum.java index 06f6b5b..4ce5046 100644 --- a/backend/src/main/java/lsgwr/exam/enums/QuestionEnum.java +++ b/backend/src/main/java/lsgwr/exam/enums/QuestionEnum.java @@ -8,17 +8,16 @@ package lsgwr.exam.enums; import lombok.Getter; +/** + * @Description : 问题类型 + */ @Getter public enum QuestionEnum { - - /** - * 问题类型 - */ RADIO(1, "单选题"), CHECK(2, "多选题"), JUDGE(3, "判断题"); - + // 构造函数用于初始化id和role QuestionEnum(Integer id, String role) { this.id = id; this.role = role; diff --git a/backend/src/main/java/lsgwr/exam/enums/ResultEnum.java b/backend/src/main/java/lsgwr/exam/enums/ResultEnum.java index 8dacff6..bf69fee 100644 --- a/backend/src/main/java/lsgwr/exam/enums/ResultEnum.java +++ b/backend/src/main/java/lsgwr/exam/enums/ResultEnum.java @@ -2,6 +2,9 @@ package lsgwr.exam.enums; import lombok.Getter; +/** + * @Description : 错误码枚举 + */ @Getter public enum ResultEnum { // 下面是本项目用到的所有错误码 @@ -17,6 +20,11 @@ public enum ResultEnum { ORDER_UPDATE_ERR(15, "考试更新异常"), ORDER_DETAIL_EMPTY(16, "用户详情为空"); + /** + * @Description: 构造函数用于初始化错误码code和描述信息message + * @param code 错误码 + * @param message 描述信息 + */ ResultEnum(Integer code, String message) { this.code = code; this.message = message; diff --git a/backend/src/main/java/lsgwr/exam/enums/RoleEnum.java b/backend/src/main/java/lsgwr/exam/enums/RoleEnum.java index d37ab8d..3f29b6b 100644 --- a/backend/src/main/java/lsgwr/exam/enums/RoleEnum.java +++ b/backend/src/main/java/lsgwr/exam/enums/RoleEnum.java @@ -8,6 +8,9 @@ package lsgwr.exam.enums; import lombok.Getter; +/** + * @Description: 账户身份枚举 + */ @Getter public enum RoleEnum { @@ -18,7 +21,11 @@ public enum RoleEnum { TEACHER(2, "教师"), STUDENT(3, "学生"); - + /** + * @Description: 构造函数用于初始化错误码code和描述信息message + * @param id 身份id + * @param role 身份描述 + */ RoleEnum(Integer id, String role) { this.id = id; this.role = role; diff --git a/backend/src/main/java/lsgwr/exam/exception/ExamException.java b/backend/src/main/java/lsgwr/exam/exception/ExamException.java index 22a786e..50e47ff 100644 --- a/backend/src/main/java/lsgwr/exam/exception/ExamException.java +++ b/backend/src/main/java/lsgwr/exam/exception/ExamException.java @@ -11,15 +11,18 @@ import lombok.Getter; @Getter public class ExamException extends RuntimeException { + // 定义异常码 private Integer code; + // 构造函数,传入枚举类型 public ExamException(ResultEnum resultEnum) { super(resultEnum.getMessage()); this.code = resultEnum.getCode(); } + // 构造函数,传入异常码和异常信息 public ExamException( Integer code, String message) { super(message); this.code = code; } -} +} \ No newline at end of file diff --git a/backend/src/main/java/lsgwr/exam/qo/DownloadQo.java b/backend/src/main/java/lsgwr/exam/qo/DownloadQo.java index cc7ac8c..9c58ff9 100644 --- a/backend/src/main/java/lsgwr/exam/qo/DownloadQo.java +++ b/backend/src/main/java/lsgwr/exam/qo/DownloadQo.java @@ -13,5 +13,8 @@ import lombok.NoArgsConstructor; @AllArgsConstructor @NoArgsConstructor public class DownloadQo { + /** + * 文件路径 + */ String path; } diff --git a/backend/src/main/java/lsgwr/exam/repository/ExamRecordLevelRepository.java b/backend/src/main/java/lsgwr/exam/repository/ExamRecordLevelRepository.java index bfbf134..4fda0bf 100644 --- a/backend/src/main/java/lsgwr/exam/repository/ExamRecordLevelRepository.java +++ b/backend/src/main/java/lsgwr/exam/repository/ExamRecordLevelRepository.java @@ -9,5 +9,6 @@ package lsgwr.exam.repository; import lsgwr.exam.entity.ExamRecordLevel; import org.springframework.data.jpa.repository.JpaRepository; +// ExamRecordLevelRepository接口,继承JpaRepository接口,用于操作ExamRecordLevel实体类 public interface ExamRecordLevelRepository extends JpaRepository { -} +} \ No newline at end of file diff --git a/backend/src/main/java/lsgwr/exam/repository/ExamRecordRepository.java b/backend/src/main/java/lsgwr/exam/repository/ExamRecordRepository.java index 28f9565..e20fe27 100644 --- a/backend/src/main/java/lsgwr/exam/repository/ExamRecordRepository.java +++ b/backend/src/main/java/lsgwr/exam/repository/ExamRecordRepository.java @@ -1,9 +1,3 @@ -/*********************************************************** - * @Description : - * @author : 梁山广(Laing Shan Guang) - * @date : 2019-05-14 08:23 - * @email : liangshanguang2@gmail.com - ***********************************************************/ package lsgwr.exam.repository; import lsgwr.exam.entity.ExamRecord; @@ -19,4 +13,4 @@ public interface ExamRecordRepository extends JpaRepository * @return 用户参加过的所有考试 */ List findByExamJoinerIdOrderByExamJoinDateDesc(String userId); -} +} \ No newline at end of file diff --git a/backend/src/main/java/lsgwr/exam/repository/ExamRepository.java b/backend/src/main/java/lsgwr/exam/repository/ExamRepository.java index 3f1ecfd..a189f5d 100644 --- a/backend/src/main/java/lsgwr/exam/repository/ExamRepository.java +++ b/backend/src/main/java/lsgwr/exam/repository/ExamRepository.java @@ -12,7 +12,9 @@ import org.springframework.data.jpa.repository.Query; import java.util.List; +// ExamRepository接口,继承JpaRepository接口,用于操作Exam实体类 public interface ExamRepository extends JpaRepository { + // 使用JPQL查询语句,查询Exam实体类,按照updateTime降序排列 @Query("select e from Exam e order by e.updateTime desc") List findAll(); } diff --git a/backend/src/main/java/lsgwr/exam/repository/PageRepository.java b/backend/src/main/java/lsgwr/exam/repository/PageRepository.java index 6fe86e3..4f62838 100644 --- a/backend/src/main/java/lsgwr/exam/repository/PageRepository.java +++ b/backend/src/main/java/lsgwr/exam/repository/PageRepository.java @@ -8,6 +8,8 @@ package lsgwr.exam.repository; import lsgwr.exam.entity.Page; import org.springframework.data.jpa.repository.JpaRepository; - +/** + * 页面数据库操作类 + */ public interface PageRepository extends JpaRepository { } diff --git a/backend/src/main/java/lsgwr/exam/repository/QuestionCategoryRepository.java b/backend/src/main/java/lsgwr/exam/repository/QuestionCategoryRepository.java index 8182ade..843df45 100644 --- a/backend/src/main/java/lsgwr/exam/repository/QuestionCategoryRepository.java +++ b/backend/src/main/java/lsgwr/exam/repository/QuestionCategoryRepository.java @@ -8,6 +8,8 @@ package lsgwr.exam.repository; import lsgwr.exam.entity.QuestionCategory; import org.springframework.data.jpa.repository.JpaRepository; - +/** + * 题目分类持久层接口 + */ public interface QuestionCategoryRepository extends JpaRepository { } diff --git a/backend/src/main/java/lsgwr/exam/repository/QuestionLevelRepository.java b/backend/src/main/java/lsgwr/exam/repository/QuestionLevelRepository.java index 69af582..b4f0083 100644 --- a/backend/src/main/java/lsgwr/exam/repository/QuestionLevelRepository.java +++ b/backend/src/main/java/lsgwr/exam/repository/QuestionLevelRepository.java @@ -8,6 +8,8 @@ package lsgwr.exam.repository; import lsgwr.exam.entity.QuestionLevel; import org.springframework.data.jpa.repository.JpaRepository; - +/** + * 题目难度的持久层接口 + */ public interface QuestionLevelRepository extends JpaRepository { } diff --git a/backend/src/main/java/lsgwr/exam/repository/QuestionOptionRepository.java b/backend/src/main/java/lsgwr/exam/repository/QuestionOptionRepository.java index 7afb1d9..af2f2b3 100644 --- a/backend/src/main/java/lsgwr/exam/repository/QuestionOptionRepository.java +++ b/backend/src/main/java/lsgwr/exam/repository/QuestionOptionRepository.java @@ -8,6 +8,8 @@ package lsgwr.exam.repository; import lsgwr.exam.entity.QuestionOption; import org.springframework.data.jpa.repository.JpaRepository; - +/** + * 题目选项的持久层接口 + */ public interface QuestionOptionRepository extends JpaRepository { } diff --git a/backend/src/main/java/lsgwr/exam/repository/QuestionRepository.java b/backend/src/main/java/lsgwr/exam/repository/QuestionRepository.java index 97b9260..8234d7d 100644 --- a/backend/src/main/java/lsgwr/exam/repository/QuestionRepository.java +++ b/backend/src/main/java/lsgwr/exam/repository/QuestionRepository.java @@ -11,7 +11,9 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import java.util.List; - +/** + * 题目接口 + */ public interface QuestionRepository extends JpaRepository { List findByQuestionTypeId(Integer id); @Query("select q from Question q order by q.updateTime desc") diff --git a/backend/src/main/java/lsgwr/exam/repository/QuestionTypeRepository.java b/backend/src/main/java/lsgwr/exam/repository/QuestionTypeRepository.java index acdee52..218106b 100644 --- a/backend/src/main/java/lsgwr/exam/repository/QuestionTypeRepository.java +++ b/backend/src/main/java/lsgwr/exam/repository/QuestionTypeRepository.java @@ -8,6 +8,8 @@ package lsgwr.exam.repository; import lsgwr.exam.entity.QuestionType; import org.springframework.data.jpa.repository.JpaRepository; - +/** + * 题目类型接口 + */ public interface QuestionTypeRepository extends JpaRepository { } diff --git a/backend/src/main/java/lsgwr/exam/repository/RoleRepository.java b/backend/src/main/java/lsgwr/exam/repository/RoleRepository.java index 90e59de..6a07451 100644 --- a/backend/src/main/java/lsgwr/exam/repository/RoleRepository.java +++ b/backend/src/main/java/lsgwr/exam/repository/RoleRepository.java @@ -9,5 +9,8 @@ package lsgwr.exam.repository; import lsgwr.exam.entity.Role; import org.springframework.data.jpa.repository.JpaRepository; +/** + * 角色的数据库操作类 + */ public interface RoleRepository extends JpaRepository { } diff --git a/backend/src/main/java/lsgwr/exam/repository/UserRepository.java b/backend/src/main/java/lsgwr/exam/repository/UserRepository.java index 27ab9ff..8ac4852 100644 --- a/backend/src/main/java/lsgwr/exam/repository/UserRepository.java +++ b/backend/src/main/java/lsgwr/exam/repository/UserRepository.java @@ -8,7 +8,9 @@ package lsgwr.exam.repository; import lsgwr.exam.entity.User; import org.springframework.data.jpa.repository.JpaRepository; - +/** + * 用户表的操作类 + */ public interface UserRepository extends JpaRepository { /** * 根据用户名查找到合适的用户 diff --git a/backend/src/main/java/lsgwr/exam/service/ExamService.java b/backend/src/main/java/lsgwr/exam/service/ExamService.java index 93c6239..7115284 100644 --- a/backend/src/main/java/lsgwr/exam/service/ExamService.java +++ b/backend/src/main/java/lsgwr/exam/service/ExamService.java @@ -4,15 +4,15 @@ * @date : 2019-05-28 08:05 * @email : liangshanguang2@gmail.com ***********************************************************/ -package lsgwr.exam.service; +package lsgwr.exam.service;// 定义了接口所属的包名 -import lsgwr.exam.entity.Exam; -import lsgwr.exam.entity.ExamRecord; -import lsgwr.exam.vo.*; - -import java.util.HashMap; -import java.util.List; +import lsgwr.exam.entity.Exam;// 导入了实体类Exam,可能包含考试的基本信息 +import lsgwr.exam.entity.ExamRecord;// 导入了实体类ExamRecord,可能包含考试记录的详细信息 +import lsgwr.exam.vo.*;// 导入了VO对象,VO是值对象,用于在不同层之间传递数据 +import java.util.HashMap;// 导入了HashMap,用于存储键值对 +import java.util.List;// 导入了List,用于存储一系列对象 +// 定义了一个名为ExamService的接口 public interface ExamService { /** * 获取所有的问题列表 diff --git a/backend/src/main/java/lsgwr/exam/service/impl/ExamServiceImpl.java b/backend/src/main/java/lsgwr/exam/service/impl/ExamServiceImpl.java index e58d825..28eeaed 100644 --- a/backend/src/main/java/lsgwr/exam/service/impl/ExamServiceImpl.java +++ b/backend/src/main/java/lsgwr/exam/service/impl/ExamServiceImpl.java @@ -10,8 +10,8 @@ import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.StrUtil; import lsgwr.exam.entity.*; import lsgwr.exam.enums.QuestionEnum; -import lsgwr.exam.service.ExamService; import lsgwr.exam.repository.*; +import lsgwr.exam.service.ExamService; import lsgwr.exam.vo.*; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; @@ -40,9 +40,9 @@ public class ExamServiceImpl implements ExamService { private final QuestionOptionRepository questionOptionRepository; public ExamServiceImpl(QuestionRepository questionRepository, UserRepository userRepository, QuestionLevelRepository questionLevelRepository, QuestionTypeRepository questionTypeRepository, QuestionCategoryRepository questionCategoryRepository, QuestionOptionRepository questionOptionRepository, ExamRepository examRepository, ExamRecordRepository examRecordRepository) { - this.questionRepository = questionRepository; - this.userRepository = userRepository; - this.questionLevelRepository = questionLevelRepository; + this.questionRepository = questionRepository;// + this.userRepository = userRepository;// + this.questionLevelRepository = questionLevelRepository;// this.questionTypeRepository = questionTypeRepository; this.questionCategoryRepository = questionCategoryRepository; this.questionOptionRepository = questionOptionRepository; @@ -57,9 +57,9 @@ public class ExamServiceImpl implements ExamService { } private List getQuestionVos(List questionList) { - // 需要自定义的question列表 + // 需要自定义的question列表, List questionVoList = new ArrayList<>(); - // 循环完成每个属性的定制 + // 循环完成每个属性的定制, for (Question question : questionList) { QuestionVo questionVo = getQuestionVo(question); questionVoList.add(questionVo); @@ -69,9 +69,9 @@ public class ExamServiceImpl implements ExamService { private QuestionVo getQuestionVo(Question question) { QuestionVo questionVo = new QuestionVo(); - // 先复制能复制的属性 + // 先复制能复制的属性, BeanUtils.copyProperties(question, questionVo); - // 设置问题的创建者 + // 设置问题的创建者。 questionVo.setQuestionCreator( Objects.requireNonNull( userRepository.findById( @@ -79,7 +79,7 @@ public class ExamServiceImpl implements ExamService { ).orElse(null) ).getUserUsername()); - // 设置问题的难度 + // 设置问题的难度。 questionVo.setQuestionLevel( Objects.requireNonNull( questionLevelRepository.findById( @@ -87,7 +87,7 @@ public class ExamServiceImpl implements ExamService { ).orElse(null) ).getQuestionLevelDescription()); - // 设置题目的类别,比如单选、多选、判断等 + // 设置题目的类别,比如单选、多选、判断等。 questionVo.setQuestionType( Objects.requireNonNull( questionTypeRepository.findById( @@ -95,7 +95,7 @@ public class ExamServiceImpl implements ExamService { ).orElse(null) ).getQuestionTypeDescription()); - // 设置题目分类,比如数学、语文、英语、生活、人文等 + // 设置题目分类,比如数学、语文、英语、生活、人文等。 questionVo.setQuestionCategory( Objects.requireNonNull( questionCategoryRepository.findById( @@ -104,20 +104,20 @@ public class ExamServiceImpl implements ExamService { ).getQuestionCategoryName() ); - // 选项的自定义Vo列表 + // 选项的自定义Vo列表。 List optionVoList = new ArrayList<>(); - // 获得所有的选项列表 + // 获得所有的选项列表。 List optionList = questionOptionRepository.findAllById( Arrays.asList(question.getQuestionOptionIds().split("-")) ); - // 获取所有的答案列表optionList中每个option的isAnswer选项 + // 获取所有的答案列表optionList中每个option的isAnswer选项。 List answerList = questionOptionRepository.findAllById( Arrays.asList(question.getQuestionAnswerOptionIds().split("-")) ); - // 根据选项和答案的id相同设置optionVo的isAnswer属性 + // 根据选项和答案的id相同设置optionVo的isAnswer属性。 for (QuestionOption option : optionList) { QuestionOptionVo optionVo = new QuestionOptionVo(); BeanUtils.copyProperties(option, optionVo); @@ -129,14 +129,14 @@ public class ExamServiceImpl implements ExamService { optionVoList.add(optionVo); } - // 设置题目的所有选项 + // 设置题目的所有选项。 questionVo.setQuestionOptionVoList(optionVoList); return questionVo; } @Override public QuestionVo updateQuestion(QuestionVo questionVo) { - // 1.把需要的属性都设置好 + // 1.把需要的属性都设置好。 StringBuilder questionAnswerOptionIds = new StringBuilder(); List questionOptionList = new ArrayList<>(); List questionOptionVoList = questionVo.getQuestionOptionVoList(); @@ -148,26 +148,26 @@ public class ExamServiceImpl implements ExamService { questionOptionList.add(questionOption); if (questionOptionVo.getAnswer()) { if (i != size - 1) { - // 把更新后的答案的id加上去,记得用-连到一起 + // 把更新后的答案的id加上去,记得用-连到一起。 questionAnswerOptionIds.append(questionOptionVo.getQuestionOptionId()).append("-"); } else { - // 最后一个不需要用-连接 + // 最后一个不需要用-连接。 questionAnswerOptionIds.append(questionOptionVo.getQuestionOptionId()); } } } - // 1.更新问题 + // 1.更新问题。 Question question = questionRepository.findById(questionVo.getQuestionId()).orElse(null); assert question != null; BeanUtils.copyProperties(questionVo, question); question.setQuestionAnswerOptionIds(questionAnswerOptionIds.toString()); questionRepository.save(question); - // 2.更新所有的option + // 2.更新所有的option。 questionOptionRepository.saveAll(questionOptionList); - // 返回更新后的问题,方便前端局部刷新 + // 返回更新后的问题,方便前端局部刷新。 return getQuestionVo(question); } @@ -175,58 +175,64 @@ public class ExamServiceImpl implements ExamService { public void questionCreate(QuestionCreateVo questionCreateVo) { // 问题创建 Question question = new Question(); - // 把能复制的属性都复制过来 + // 把能复制的属性都复制过来。 BeanUtils.copyProperties(questionCreateVo, question); - // 设置下questionOptionIds和questionAnswerOptionIds,需要自己用Hutool生成下 + // 设置下questionOptionIds和questionAnswerOptionIds,需要自己用Hutool生成下。 List questionOptionList = new ArrayList<>(); List questionOptionCreateVoList = questionCreateVo.getQuestionOptionCreateVoList(); for (QuestionOptionCreateVo questionOptionCreateVo : questionOptionCreateVoList) { QuestionOption questionOption = new QuestionOption(); - // 设置选项的的内容 + // 设置选项的的内容。 questionOption.setQuestionOptionContent(questionOptionCreateVo.getQuestionOptionContent()); - // 设置选项的id + // 设置选项的id。 questionOption.setQuestionOptionId(IdUtil.simpleUUID()); questionOptionList.add(questionOption); } - // 把选项都存起来,然后才能用于下面设置Question的questionOptionIds和questionAnswerOptionIds + // 把选项都存起来,然后才能用于下面设置Question的questionOptionIds和questionAnswerOptionIds。 questionOptionRepository.saveAll(questionOptionList); String questionOptionIds = ""; String questionAnswerOptionIds = ""; - // 经过上面的saveAll方法,所有的option的主键id都已经持久化了 + // 经过上面的saveAll方法,所有的option的主键id都已经持久化了。 for (int i = 0; i < questionOptionCreateVoList.size(); i++) { - // 获取指定选项 + // 获取指定选项。 QuestionOptionCreateVo questionOptionCreateVo = questionOptionCreateVoList.get(i); - // 获取保存后的指定对象 + // 获取保存后的指定对象。 QuestionOption questionOption = questionOptionList.get(i); questionOptionIds += questionOption.getQuestionOptionId() + "-"; if (questionOptionCreateVo.getAnswer()) { - // 如果是答案的话 + // 如果是答案的话。 questionAnswerOptionIds += questionOption.getQuestionOptionId() + "-"; } } - // 把字符串最后面的"-"给去掉 + // 把字符串最后面的"-"给去掉。 questionAnswerOptionIds = replaceLastSeparator(questionAnswerOptionIds); questionOptionIds = replaceLastSeparator(questionOptionIds); - // 设置选项id组成的字符串 + // 设置选项id组成的字符串。 question.setQuestionOptionIds(questionOptionIds); - // 设置答案选项id组成的字符串 + // 设置答案选项id组成的字符串。 question.setQuestionAnswerOptionIds(questionAnswerOptionIds); - // 自己生成问题的id + // 自己生成问题的id。 question.setQuestionId(IdUtil.simpleUUID()); - // 先把创建时间和更新时间每次都取当前时间吧 + // 先把创建时间和更新时间每次都取当前时间吧。 question.setCreateTime(new Date()); question.setUpdateTime(new Date()); - // 保存问题到数据库 + // 保存问题到数据库。 questionRepository.save(question); } @Override + // 重写父类方法,获取问题选择列表 public QuestionSelectionVo getSelections() { + // 创建问题选择对象 QuestionSelectionVo questionSelectionVo = new QuestionSelectionVo(); + // 设置问题类别列表 questionSelectionVo.setQuestionCategoryList(questionCategoryRepository.findAll()); + // 设置问题等级列表 questionSelectionVo.setQuestionLevelList(questionLevelRepository.findAll()); + // 设置问题类型列表 questionSelectionVo.setQuestionTypeList(questionTypeRepository.findAll()); + // 返回问题选择对象 return questionSelectionVo; } @@ -245,10 +251,15 @@ public class ExamServiceImpl implements ExamService { @Override public QuestionDetailVo getQuestionDetail(String id) { + // 根据id查询问题 Question question = questionRepository.findById(id).orElse(null); + // 创建问题详情对象 QuestionDetailVo questionDetailVo = new QuestionDetailVo(); + // 设置问题id questionDetailVo.setId(id); + // 设置问题名称 questionDetailVo.setName(question.getQuestionName()); + // 设置问题描述 questionDetailVo.setDescription(question.getQuestionDescription()); // 问题类型,单选题/多选题/判断题 questionDetailVo.setType( @@ -258,10 +269,10 @@ public class ExamServiceImpl implements ExamService { ).orElse(null) ).getQuestionTypeDescription() ); - // 获取当前问题的选项 + // 获取当前问题的选项。 String optionIdsStr = trimMiddleLine(question.getQuestionOptionIds()); String[] optionIds = optionIdsStr.split("-"); - // 获取选项列表 + // 获取选项列表。 List optionList = questionOptionRepository.findAllById(Arrays.asList(optionIds)); questionDetailVo.setOptions(optionList); return questionDetailVo; @@ -274,14 +285,14 @@ public class ExamServiceImpl implements ExamService { } private List getExamVos(List examList) { - // 需要自定义的exam列表 + // 需要自定义的exam列表。 List examVoList = new ArrayList<>(); - // 循环完成每个属性的定制 + // 循环完成每个属性的定制。 for (Exam exam : examList) { ExamVo examVo = new ExamVo(); - // 先尽量复制能复制的所有属性 + // 先尽量复制能复制的所有属性。 BeanUtils.copyProperties(exam, examVo); - // 设置问题的创建者 + // 设置问题的创建者。 examVo.setExamCreator( Objects.requireNonNull( userRepository.findById( @@ -290,7 +301,7 @@ public class ExamServiceImpl implements ExamService { ).getUserUsername() ); - // 获取所有单选题列表,并赋值到ExamVo的属性ExamQuestionSelectVoRadioList上 + // 获取所有单选题列表,并赋值到ExamVo的属性ExamQuestionSelectVoRadioList上。 List radioQuestionVoList = new ArrayList<>(); List radioQuestionList = questionRepository.findAllById( Arrays.asList(exam.getExamQuestionIdsRadio().split("-")) @@ -298,12 +309,12 @@ public class ExamServiceImpl implements ExamService { for (Question question : radioQuestionList) { ExamQuestionSelectVo radioQuestionVo = new ExamQuestionSelectVo(); BeanUtils.copyProperties(question, radioQuestionVo); - radioQuestionVo.setChecked(true); // 考试中的问题肯定被选中的 + radioQuestionVo.setChecked(true); // 考试中的问题肯定被选中的。 radioQuestionVoList.add(radioQuestionVo); } examVo.setExamQuestionSelectVoRadioList(radioQuestionVoList); - // 获取所有多选题列表,并赋值到ExamVo的属性ExamQuestionSelectVoCheckList上 + // 获取所有多选题列表,并赋值到ExamVo的属性ExamQuestionSelectVoCheckList上。 List checkQuestionVoList = new ArrayList<>(); List checkQuestionList = questionRepository.findAllById( Arrays.asList(exam.getExamQuestionIdsCheck().split("-")) @@ -311,12 +322,12 @@ public class ExamServiceImpl implements ExamService { for (Question question : checkQuestionList) { ExamQuestionSelectVo checkQuestionVo = new ExamQuestionSelectVo(); BeanUtils.copyProperties(question, checkQuestionVo); - checkQuestionVo.setChecked(true); // 考试中的问题肯定被选中的 + checkQuestionVo.setChecked(true); // 考试中的问题肯定被选中的。 checkQuestionVoList.add(checkQuestionVo); } examVo.setExamQuestionSelectVoCheckList(checkQuestionVoList); - // 获取所有多选题列表,并赋值到ExamVo的属性ExamQuestionSelectVoJudgeList上 + // 获取所有多选题列表,并赋值到ExamVo的属性ExamQuestionSelectVoJudgeList上。 List judgeQuestionVoList = new ArrayList<>(); List judgeQuestionList = questionRepository.findAllById( Arrays.asList(exam.getExamQuestionIdsJudge().split("-")) @@ -324,7 +335,7 @@ public class ExamServiceImpl implements ExamService { for (Question question : judgeQuestionList) { ExamQuestionSelectVo judgeQuestionVo = new ExamQuestionSelectVo(); BeanUtils.copyProperties(question, judgeQuestionVo); - judgeQuestionVo.setChecked(true); // 考试中的问题肯定被选中的 + judgeQuestionVo.setChecked(true); // 考试中的问题肯定被选中的。 judgeQuestionVoList.add(judgeQuestionVo); } examVo.setExamQuestionSelectVoJudgeList(judgeQuestionVoList); @@ -340,7 +351,7 @@ public class ExamServiceImpl implements ExamService { @Override public ExamQuestionTypeVo getExamQuestionType() { ExamQuestionTypeVo examQuestionTypeVo = new ExamQuestionTypeVo(); - // 获取所有单选题列表,并赋值到ExamVo的属性ExamQuestionSelectVoRadioList上 + // 获取所有单选题列表,并赋值到ExamVo的属性ExamQuestionSelectVoRadioList上。 List radioQuestionVoList = new ArrayList<>(); List radioQuestionList = questionRepository.findByQuestionTypeId(QuestionEnum.RADIO.getId()); for (Question question : radioQuestionList) { @@ -350,7 +361,7 @@ public class ExamServiceImpl implements ExamService { } examQuestionTypeVo.setExamQuestionSelectVoRadioList(radioQuestionVoList); - // 获取所有多选题列表,并赋值到ExamVo的属性ExamQuestionSelectVoCheckList上 + // 获取所有多选题列表,并赋值到ExamVo的属性ExamQuestionSelectVoCheckList上。 List checkQuestionVoList = new ArrayList<>(); List checkQuestionList = questionRepository.findByQuestionTypeId(QuestionEnum.CHECK.getId()); for (Question question : checkQuestionList) { @@ -360,7 +371,7 @@ public class ExamServiceImpl implements ExamService { } examQuestionTypeVo.setExamQuestionSelectVoCheckList(checkQuestionVoList); - // 获取所有多选题列表,并赋值到ExamVo的属性ExamQuestionSelectVoJudgeList上 + // 获取所有多选题列表,并赋值到ExamVo的属性ExamQuestionSelectVoJudgeList上。 List judgeQuestionVoList = new ArrayList<>(); List judgeQuestionList = questionRepository.findByQuestionTypeId(QuestionEnum.JUDGE.getId()); for (Question question : judgeQuestionList) { @@ -374,7 +385,7 @@ public class ExamServiceImpl implements ExamService { @Override public Exam create(ExamCreateVo examCreateVo, String userId) { - // 在线考试系统创建 + // 在线考试系统创建。 Exam exam = new Exam(); BeanUtils.copyProperties(examCreateVo, exam); exam.setExamId(IdUtil.simpleUUID()); @@ -382,35 +393,53 @@ public class ExamServiceImpl implements ExamService { exam.setCreateTime(new Date()); exam.setUpdateTime(new Date()); // Todo:这两个日志后面是要在前端传入的,这里暂时定为当前日期 - exam.setExamStartDate(new Date()); - exam.setExamEndDate(new Date()); - String radioIdsStr = ""; - String checkIdsStr = ""; - String judgeIdsStr = ""; - List radios = examCreateVo.getRadios(); - List checks = examCreateVo.getChecks(); - List judges = examCreateVo.getJudges(); - int radioCnt = 0, checkCnt = 0, judgeCnt = 0; - for (ExamQuestionSelectVo radio : radios) { - if (radio.getChecked()) { - radioIdsStr += radio.getQuestionId() + "-"; - radioCnt++; - } - } - radioIdsStr = replaceLastSeparator(radioIdsStr); - for (ExamQuestionSelectVo check : checks) { - if (check.getChecked()) { - checkIdsStr += check.getQuestionId() + "-"; - checkCnt++; - } - } - checkIdsStr = replaceLastSeparator(checkIdsStr); - for (ExamQuestionSelectVo judge : judges) { - if (judge.getChecked()) { - judgeIdsStr += judge.getQuestionId() + "-"; - judgeCnt++; - } - } + // 设置考试开始时间和结束时间 + exam.setExamStartDate(new Date()); + exam.setExamEndDate(new Date()); + // 初始化选择题、判断题和单选题的id字符串 + String radioIdsStr = ""; + String checkIdsStr = ""; + String judgeIdsStr = ""; + // 获取选择题、判断题和单选题的列表 + List radios = examCreateVo.getRadios(); + List checks = examCreateVo.getChecks(); + List judges = examCreateVo.getJudges(); + // 初始化选择题、判断题和单选题的计数器 + int radioCnt = 0, checkCnt = 0, judgeCnt = 0; + // 遍历单选题列表 + for (ExamQuestionSelectVo radio : radios) { + // 如果单选题被选中 + if (radio.getChecked()) { + // 将单选题的id添加到字符串中 + radioIdsStr += radio.getQuestionId() + "-"; + // 单选题计数器加1 + radioCnt++; + } + } + // 去掉最后一个分隔符 + radioIdsStr = replaceLastSeparator(radioIdsStr); + // 遍历判断题列表 + for (ExamQuestionSelectVo check : checks) { + // 如果判断题被选中 + if (check.getChecked()) { + // 将判断题的id添加到字符串中 + checkIdsStr += check.getQuestionId() + "-"; + // 判断题计数器加1 + checkCnt++; + } + } + // 去掉最后一个分隔符 + checkIdsStr = replaceLastSeparator(checkIdsStr); + // 遍历选择题列表 + for (ExamQuestionSelectVo judge : judges) { + // 如果选择题被选中 + if (judge.getChecked()) { + // 将选择题的id添加到字符串中 + judgeIdsStr += judge.getQuestionId() + "-"; + // 选择题计数器加1 + judgeCnt++; + } + } judgeIdsStr = replaceLastSeparator(judgeIdsStr); exam.setExamQuestionIds(radioIdsStr + "-" + checkIdsStr + "-" + judgeIdsStr); // 设置各个题目的id @@ -427,49 +456,64 @@ public class ExamServiceImpl implements ExamService { @Override public Exam update(ExamVo examVo, String userId) { + // 创建一个新的Exam对象 Exam exam = new Exam(); + // 将examVo中的属性值复制到exam对象中 BeanUtils.copyProperties(examVo, exam); - exam.setExamCreatorId(userId); // 考试的更新人为最新的创建人 - exam.setUpdateTime(new Date()); // 考试的更新日期要记录下 + // 设置考试更新人为最新的创建人 + exam.setExamCreatorId(userId); + // 记录考试更新日期 + exam.setUpdateTime(new Date()); + // 初始化选择题、判断题、单选题的id字符串 String radioIdsStr = ""; String checkIdsStr = ""; - String judgeIdsStr = ""; + String judgeIdsStr = "";//djfndiosbchjdshjiowceduikmn + // 获取选择题、判断题、单选题的列表 List radios = examVo.getExamQuestionSelectVoRadioList(); List checks = examVo.getExamQuestionSelectVoCheckList(); List judges = examVo.getExamQuestionSelectVoJudgeList(); + // 初始化选择题、判断题、单选题的数量 int radioCnt = 0, checkCnt = 0, judgeCnt = 0; + // 遍历选择题列表,将选中的题目id添加到字符串中,并统计选择题数量 for (ExamQuestionSelectVo radio : radios) { if (radio.getChecked()) { radioIdsStr += radio.getQuestionId() + "-"; radioCnt++; } } + // 去除最后一个分隔符 radioIdsStr = replaceLastSeparator(radioIdsStr); + // 遍历判断题列表,将选中的题目id添加到字符串中,并统计判断题数量 for (ExamQuestionSelectVo check : checks) { if (check.getChecked()) { checkIdsStr += check.getQuestionId() + "-"; checkCnt++; } } + // 去除最后一个分隔符 checkIdsStr = replaceLastSeparator(checkIdsStr); + // 遍历单选题列表,将选中的题目id添加到字符串中,并统计单选题数量 for (ExamQuestionSelectVo judge : judges) { if (judge.getChecked()) { judgeIdsStr += judge.getQuestionId() + "-"; judgeCnt++; } } + // 去除最后一个分隔符。 judgeIdsStr = replaceLastSeparator(judgeIdsStr); + // 设置各个题目的id。 exam.setExamQuestionIds(radioIdsStr + "-" + checkIdsStr + "-" + judgeIdsStr); - // 设置各个题目的id exam.setExamQuestionIdsRadio(radioIdsStr); exam.setExamQuestionIdsCheck(checkIdsStr); exam.setExamQuestionIdsJudge(judgeIdsStr); - // 计算总分数 + // 计算总分数。 int examScore = radioCnt * exam.getExamScoreRadio() + checkCnt * exam.getExamScoreCheck() + judgeCnt * exam.getExamScoreJudge(); exam.setExamScore(examScore); + // 保存exam对象。 examRepository.save(exam); + // 返回exam对象。 return exam; } @@ -499,53 +543,53 @@ public class ExamServiceImpl implements ExamService { @Override public ExamRecord judge(String userId, String examId, HashMap> answersMap) { - // 开始考试判分啦~~~ - // 1.首先获取考试对象和选项数组 + // 开始考试判分啦~~~。 + // 1.首先获取考试对象和选项数组。 ExamDetailVo examDetailVo = getExamDetail(examId); Exam exam = examDetailVo.getExam(); - // 2.然后获取该考试下所有的题目信息 + // 2.然后获取该考试下所有的题目信息。 List questionIds = new ArrayList<>(); - // 2.1 题目id的数组 + // 2.1 题目id的数组。 List radioIdList = Arrays.asList(examDetailVo.getRadioIds()); List checkIdList = Arrays.asList(examDetailVo.getCheckIds()); List judgeIdList = Arrays.asList(examDetailVo.getJudgeIds()); questionIds.addAll(radioIdList); questionIds.addAll(checkIdList); questionIds.addAll(judgeIdList); - // 2.2 每种题目的分数 + // 2.2 每种题目的分数。 int radioScore = exam.getExamScoreRadio(); int checkScore = exam.getExamScoreCheck(); int judgeScore = exam.getExamScoreJudge(); - // 2.3 根据问题id的数组拿到所有的问题对象,供下面步骤用 + // 2.3 根据问题id的数组拿到所有的问题对象,供下面步骤用。 List questionList = questionRepository.findAllById(questionIds); Map questionMap = new HashMap<>(); for (Question question : questionList) { questionMap.put(question.getQuestionId(), question); } - // 3.根据正确答案和用户作答信息进行判分 + // 3.根据正确答案和用户作答信息进行判分。 Set questionIdsAnswer = answersMap.keySet(); - // 存储当前考试每个题目的得分情况 + // 存储当前考试每个题目的得分情况。 Map judgeMap = new HashMap<>(); - // 考生作答地每个题目的选项(题目和题目之间用$分隔,题目有多个选项地话用-分隔,题目和选项之间用_分隔),用于查看考试详情 - // 例子:题目1的id_作答选项1-作答选项2&题目2的id_作答选项1&题目3_作答选项1-作答选项2-作答选项3 + // 考生作答地每个题目的选项(题目和题目之间用$分隔,题目有多个选项地话用-分隔,题目和选项之间用_分隔),用于查看考试详情。 + // 例子:题目1的id_作答选项1-作答选项2&题目2的id_作答选项1&题目3_作答选项1-作答选项2-作答选项3。 StringBuilder answerOptionIdsSb = new StringBuilder(); - // 用户此次考试的总分 + // 用户此次考试的总分。 int totalScore = 0; for (String questionId : questionIdsAnswer) { - // 获取用户作答地这个题的答案信息 + // 获取用户作答地这个题的答案信息。 Question question = questionMap.get(questionId); - // 获取答案选项 + // 获取答案选项。 String questionAnswerOptionIds = replaceLastSeparator(question.getQuestionAnswerOptionIds()); List questionAnswerOptionIdList = Arrays.asList(questionAnswerOptionIds.split("-")); Collections.sort(questionAnswerOptionIdList); String answerStr = listConcat(questionAnswerOptionIdList); - // 获取用户作答 + // 获取用户作答。 List questionUserOptionIdList = answersMap.get(questionId); Collections.sort(questionUserOptionIdList); String userStr = listConcat(questionUserOptionIdList); - // 判断questionAnswerOptionIds和answersMap里面的答案是否相等 + // 判断questionAnswerOptionIds和answersMap里面的答案是否相等。 if (answerStr.equals(userStr)) { - // 说明题目作答正确,下面根据题型给分 + // 说明题目作答正确,下面根据题型给分。 int score = 0; if (radioIdList.contains(questionId)) { score = radioScore; @@ -556,22 +600,22 @@ public class ExamServiceImpl implements ExamService { if (judgeIdList.contains(questionId)) { score = judgeScore; } - // 累计本次考试得分 + // 累计本次考试得分。 totalScore += score; - // True代表题目答对 + // True代表题目答对。 answerOptionIdsSb.append(questionId + "@True_" + userStr + "$"); judgeMap.put(questionId, score); } else { - // 说明题目作答错误,直接判零分,False代表题目答错 + // 说明题目作答错误,直接判零分,False代表题目答错。 answerOptionIdsSb.append(questionId + "@False_" + userStr + "$"); judgeMap.put(questionId, 0); } } - // 4.计算得分,记录本次考试结果,存到ExamRecord中 + // 4.计算得分,记录本次考试结果,存到ExamRecord中。 ExamRecord examRecord = new ExamRecord(); examRecord.setExamRecordId(IdUtil.simpleUUID()); examRecord.setExamId(examId); - // 注意去掉最后可能有的&_- + // 注意去掉最后可能有的&_-。 examRecord.setAnswerOptionIds(replaceLastSeparator(answerOptionIdsSb.toString())); examRecord.setExamJoinerId(userId); examRecord.setExamJoinDate(new Date()); @@ -582,58 +626,60 @@ public class ExamServiceImpl implements ExamService { @Override public List getExamRecordList(String userId) { - // 获取指定用户下的考试记录列表 + // 获取指定用户下的考试记录列表。 List examRecordList = examRecordRepository.findByExamJoinerIdOrderByExamJoinDateDesc(userId); List examRecordVoList = new ArrayList<>(); for (ExamRecord examRecord : examRecordList) { ExamRecordVo examRecordVo = new ExamRecordVo(); + // 根据考试记录中的考试ID获取考试信息 Exam exam = examRepository.findById(examRecord.getExamId()).orElse(null); examRecordVo.setExam(exam); + // 根据用户ID获取用户信息 User user = userRepository.findById(userId).orElse(null); examRecordVo.setUser(user); + // 设置考试记录信息 examRecordVo.setExamRecord(examRecord); examRecordVoList.add(examRecordVo); } return examRecordVoList; } - @Override public RecordDetailVo getRecordDetail(String recordId) { - // 获取考试详情的封装对象 + // 获取考试详情的封装对象。 ExamRecord record = examRecordRepository.findById(recordId).orElse(null); RecordDetailVo recordDetailVo = new RecordDetailVo(); recordDetailVo.setExamRecord(record); - // 用户的答案,需要解析 + // 用户的答案,需要解析。 HashMap> answersMap = new HashMap<>(); HashMap resultsMap = new HashMap<>(); assert record != null; String answersStr = record.getAnswerOptionIds(); - // $分隔题目,因为$在正则中有特殊用途(行尾),所以需要括起来 + // $分隔题目,因为$在正则中有特殊用途(行尾),所以需要括起来。 String[] questionArr = answersStr.split("[$]"); for (String questionStr : questionArr) { System.out.println(questionStr); - // 区分开题目标题和选项 + // 区分开题目标题和选项。 String[] questionTitleResultAndOption = questionStr.split("_"); String[] questionTitleAndResult = questionTitleResultAndOption[0].split("@"); String[] questionOptions = questionTitleResultAndOption[1].split("-"); - // 题目:答案选项 + // 题目:答案选项。 answersMap.put(questionTitleAndResult[0], Arrays.asList(questionOptions)); - // 题目:True / False + // 题目:True / False。 resultsMap.put(questionTitleAndResult[0], questionTitleAndResult[1]); } recordDetailVo.setAnswersMap(answersMap); recordDetailVo.setResultsMap(resultsMap); - // 下面再计算正确答案的map + // 下面再计算正确答案的map。 ExamDetailVo examDetailVo = getExamDetail(record.getExamId()); List questionIdList = new ArrayList<>(); questionIdList.addAll(Arrays.asList(examDetailVo.getRadioIds())); questionIdList.addAll(Arrays.asList(examDetailVo.getCheckIds())); questionIdList.addAll(Arrays.asList(examDetailVo.getJudgeIds())); - // 获取所有的问题对象 + // 获取所有的问题对象。 List questionList = questionRepository.findAllById(questionIdList); HashMap> answersRightMap = new HashMap<>(); for (Question question : questionList) { - // 记得去掉最后可能出现的特殊字符 + // 记得去掉最后可能出现的特殊字符。 String questionAnswerOptionIdsStr = replaceLastSeparator(question.getQuestionAnswerOptionIds()); String[] questionAnswerOptionIds = questionAnswerOptionIdsStr.split("-"); answersRightMap.put(question.getQuestionId(), Arrays.asList(questionAnswerOptionIds)); @@ -641,7 +687,6 @@ public class ExamServiceImpl implements ExamService { recordDetailVo.setAnswersRightMap(answersRightMap); return recordDetailVo; } - /** * 把字符串最后一个字符-替换掉 * @@ -650,7 +695,7 @@ public class ExamServiceImpl implements ExamService { */ private String replaceLastSeparator(String str) { String lastChar = str.substring(str.length() - 1); - // 题目和题目之间用$分隔,题目有多个选项地话用-分隔,题目和选项之间用_分隔 + // 题目和题目之间用$分隔,题目有多个选项地话用-分隔,题目和选项之间用_分隔。 if ("-".equals(lastChar) || "_".equals(lastChar) || "$".equals(lastChar)) { str = StrUtil.sub(str, 0, str.length() - 1); } diff --git a/backend/src/main/java/lsgwr/exam/service/impl/UserServiceImpl.java b/backend/src/main/java/lsgwr/exam/service/impl/UserServiceImpl.java index 3799580..2dc8e38 100644 --- a/backend/src/main/java/lsgwr/exam/service/impl/UserServiceImpl.java +++ b/backend/src/main/java/lsgwr/exam/service/impl/UserServiceImpl.java @@ -47,7 +47,12 @@ public class UserServiceImpl implements UserService { @Autowired ActionRepository actionRepository; - + /** + * 注册用户 + * + * @param registerDTO 前端传来的注册信息 + * @return 注册成功返回用户信息,失败返回null + */ @Override public User register(RegisterDTO registerDTO) { try { @@ -106,7 +111,12 @@ public class UserServiceImpl implements UserService { } return null; } - + /** + * 获取用户信息 + * + * @param userId 用户id + * @return 用户信息 + */ @Override public UserVo getUserInfo(String userId) { User user = userRepository.findById(userId).orElse(null); @@ -115,7 +125,12 @@ public class UserServiceImpl implements UserService { BeanUtils.copyProperties(user, userVo); return userVo; } - + /** + * 获取用户详细信息 + * + * @param userId 用户id + * @return 用户详细信息 + */ @Override public UserInfoVo getInfo(String userId) { User user = userRepository.findById(userId).orElse(null); diff --git a/backend/src/main/java/lsgwr/exam/utils/ResultVOUtil.java b/backend/src/main/java/lsgwr/exam/utils/ResultVOUtil.java index fbd6df1..0694dde 100644 --- a/backend/src/main/java/lsgwr/exam/utils/ResultVOUtil.java +++ b/backend/src/main/java/lsgwr/exam/utils/ResultVOUtil.java @@ -7,22 +7,32 @@ package lsgwr.exam.utils; import lsgwr.exam.vo.ResultVO; - +/** + * 封装返回结果 + */ public class ResultVOUtil { - + /** + * 成功返回结果 + */ public static ResultVO success(Integer code, String msg, Object object) { return new ResultVO(code, msg, object); } - + /** + * 成功返回结果 + */ public static ResultVO success(Object object) { return new ResultVO(0, "成功", object); } - + /** + * 成功返回结果 + */ public static ResultVO success() { return new ResultVO(0, "成功", null); } - + /** + * 失败返回结果 + */ public static ResultVO error(Integer code, String msg) { return new ResultVO(code, msg, null); } diff --git a/backend/src/main/java/lsgwr/exam/vo/ActionVo.java b/backend/src/main/java/lsgwr/exam/vo/ActionVo.java index 98b2a63..283ad72 100644 --- a/backend/src/main/java/lsgwr/exam/vo/ActionVo.java +++ b/backend/src/main/java/lsgwr/exam/vo/ActionVo.java @@ -8,15 +8,24 @@ package lsgwr.exam.vo; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; - +/** + * Action前端展示类 + */ @Data public class ActionVo { + /** + * 动作名称 + */ @JsonProperty("action") private String actionName; - + /** + * 动作描述 + */ @JsonProperty("describe") private String actionDescription; - + /** + * 是否默认选中 + */ @JsonProperty("defaultCheck") private Boolean defaultCheck; } diff --git a/backend/src/main/java/lsgwr/exam/vo/ExamCardVo.java b/backend/src/main/java/lsgwr/exam/vo/ExamCardVo.java index f516f89..70121de 100644 --- a/backend/src/main/java/lsgwr/exam/vo/ExamCardVo.java +++ b/backend/src/main/java/lsgwr/exam/vo/ExamCardVo.java @@ -8,22 +8,39 @@ package lsgwr.exam.vo; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; - +/** + * @Description: 用于表示考试卡片的信息,这个类可以很方便地与JSON数据绑定 + * 用于从API响应中解析考试卡片信息,将考试卡片信息序列化为JSON格式发送到服务器 + * Lombok库的@Data注解用于自动生成getter和setter方法 + * Jackson库的@JsonProperty注解用于指定JSON序列化和反序列化时使用的属性名称。 + */ @Data public class ExamCardVo { @JsonProperty("id") private String examId; + /** + * 考试名称 + */ @JsonProperty("title") private String examName; + /** + * 考试头像 + */ @JsonProperty("avatar") private String examAvatar; + /** + * 考试描述 + */ @JsonProperty("content") private String examDescription; + /** + * 考试分数 + */ @JsonProperty("score") - private Integer examScore; + private Integer examScore;// 考试的分数 /** * 考试限制的时间,单位为分钟 */ @JsonProperty("elapse") - private Integer examTimeLimit; + private Integer examTimeLimit;// 考试的时间限制,以分钟为单位 } diff --git a/backend/src/main/java/lsgwr/exam/vo/ExamCreateVo.java b/backend/src/main/java/lsgwr/exam/vo/ExamCreateVo.java index a43f3d1..23e52c2 100644 --- a/backend/src/main/java/lsgwr/exam/vo/ExamCreateVo.java +++ b/backend/src/main/java/lsgwr/exam/vo/ExamCreateVo.java @@ -5,60 +5,63 @@ * @email : liangshanguang2@gmail.com ***********************************************************/ package lsgwr.exam.vo; - +// 引入Jackson库中的注解,用于JSON序列化和反序列化时自定义属性名 import com.fasterxml.jackson.annotation.JsonProperty; +// 引入Lombok库中的@Data注解,它会自动为你的类的字段生成getter和setter方法,以及toString、equals和hashCode方法 import lombok.Data; import java.util.List; - +// 使用@Data注解来自动生成getter、setter等方法 @Data public class ExamCreateVo { - + // 考试名称,通过@JsonProperty注解指定JSON字段名为"name" @JsonProperty("name") private String examName; - + // 考试头像或图标,通过@JsonProperty注解指定JSON字段名为"avatar" @JsonProperty("avatar") private String examAvatar; - + // 考试描述,通过@JsonProperty注解指定JSON字段名为"desc" @JsonProperty("desc") private String examDescription; /** - * 考试时长,单位分钟 + * 考试时长,单位分钟。通过@JsonProperty注解指定JSON字段名为"elapse" + * 注意:这里的注释说明了字段的用途和单位 */ @JsonProperty("elapse") private Integer examTimeLimit; /** - * 单选题 + * 单选题列表。这里虽然使用了List类型,但注释仅指明了是单选题 + * 注意:ExamQuestionSelectVo可能是一个表示题目信息的VO类,但在此代码段中未给出 */ private List radios; /** - * 多选题 + * 多选题列表。同样使用了List类型,但注释指明了是多选题 */ private List checks; /** - * 判断题 + * 判断题列表。使用了List类型,注释指明了是判断题 */ private List judges; /** - * 单选题的分数 + * 单选题每题的分数。通过@JsonProperty注解指定JSON字段名为"radioScore" */ @JsonProperty("radioScore") private Integer examScoreRadio; /** - * 多选题的分数 + * 多选题每题的分数。通过@JsonProperty注解指定JSON字段名为"checkScore" */ @JsonProperty("checkScore") private Integer examScoreCheck; /** - * 判断题每题的分数 + * 判断题每题的分数。通过@JsonProperty注解指定JSON字段名为"judgeScore" */ @JsonProperty("judgeScore") private Integer examScoreJudge; diff --git a/backend/src/main/java/lsgwr/exam/vo/ExamDetailVo.java b/backend/src/main/java/lsgwr/exam/vo/ExamDetailVo.java index 7e20e7b..d66f9ee 100644 --- a/backend/src/main/java/lsgwr/exam/vo/ExamDetailVo.java +++ b/backend/src/main/java/lsgwr/exam/vo/ExamDetailVo.java @@ -5,29 +5,42 @@ * @email : liangshanguang2@gmail.com ***********************************************************/ package lsgwr.exam.vo; - +// 引入Exam实体类,它可能包含了考试的详细信息,如考试ID、名称、描述等 import lsgwr.exam.entity.Exam; +// 引入Lombok库的@Data注解,用于自动生成getter、setter等方法 import lombok.Data; - +// 使用@Data注解来自动生成这个类的getter、setter等方法 @Data public class ExamDetailVo { /** - * 考试的基本信息对象 + * 考试的基本信息对象。 + * 这个字段存储了一个Exam类型的对象,该对象可能包含了考试的详细信息, + * 如考试ID、名称、描述、时长、状态等。 + * 这里,ExamDetailVo通过持有这个Exam对象来提供关于特定考试的详细信息。 */ private Exam exam; /** - * 单选题的id数组 + * 单选题的id数组。 + * 这个字段是一个字符串数组,用于存储考生所选的单选题的ID。 + * 每个字符串可能代表一个单选题的唯一标识符。 + * 在处理考试结果或进行成绩统计时,这些ID可以用于查找和验证考生所选的答案。 */ private String[] radioIds; /** - * 多选题的id数组 + * 多选题的id数组。 + * 类似于单选题的id数组,这个字段存储了考生所选的多选题的ID。 + * 由于多选题可能允许选择多个选项,因此这个数组可能包含多个字符串, + * 每个字符串代表一个被选中的多选题的唯一标识符。 */ private String[] checkIds; /** - * 判断题的id数组 + * 判断题的id数组。 + * 这个字段也是一个字符串数组,用于存储考生所选的判断题的ID。 + * 每个字符串代表一个判断题的唯一标识符,通常与考生所选的答案(正确或错误)相关联。 + * 在处理考试结果时,这些ID可以用于查找和验证考生对判断题的回答。 */ private String[] judgeIds; diff --git a/backend/src/main/java/lsgwr/exam/vo/ExamPageVo.java b/backend/src/main/java/lsgwr/exam/vo/ExamPageVo.java index 2cac0d1..9638d44 100644 --- a/backend/src/main/java/lsgwr/exam/vo/ExamPageVo.java +++ b/backend/src/main/java/lsgwr/exam/vo/ExamPageVo.java @@ -4,37 +4,40 @@ * @date : 2019-06-22 17:00 * @email : liangshanguang2@gmail.com ***********************************************************/ -package lsgwr.exam.vo; - +package lsgwr.exam.vo;// 定义包名,用于组织类文件,避免命名冲突 +// 导入Jackson库的JsonProperty注解,用于JSON序列化时自定义字段名 import com.fasterxml.jackson.annotation.JsonProperty; +// 导入Lombok库的Data注解,用于自动生成getter、setter、equals、hashCode和toString方法 import lombok.Data; - +// 导入Java的List接口,用于存储ExamVo对象的集合 import java.util.List; - +// 使用Lombok的@Data注解,自动为该类生成getter、setter等方法 @Data public class ExamPageVo { /** - * 分页时每个分页的大小 + * 分页时每个分页的大小,即每页显示多少条记录 */ private Integer pageSize; /** - * 当前是在第几页,注意要比前端传过来地小1 + * 当前是在第几页,注意这里的页码是从1开始计数的,但后端处理时可能需要减1以符合某些分页算法或框架的页码从0开始的要求 + * 这里的注释提醒开发者,后端接收到的页码值可能需要减1处理 */ private Integer pageNo; /** - * 一共有多少条符合条件的记录 + * 一共有多少条符合条件的记录,用于计算总页数 */ private Long totalCount; /** - * 一共有多少页 + * 一共有多少页,根据总记录数和每页大小计算得出 */ private Integer totalPage; /** - * 当前页的详细数据 + * 当前页的详细数据,包含了一个ExamVo对象的列表,ExamVo类通常定义了考试信息的数据结构 + * @JsonProperty("data")注解用于JSON序列化时,将examVoList字段的JSON键名指定为"data" */ @JsonProperty("data") private List examVoList; diff --git a/backend/src/main/java/lsgwr/exam/vo/ExamQuestionSelectVo.java b/backend/src/main/java/lsgwr/exam/vo/ExamQuestionSelectVo.java index a70a03f..7fa14dd 100644 --- a/backend/src/main/java/lsgwr/exam/vo/ExamQuestionSelectVo.java +++ b/backend/src/main/java/lsgwr/exam/vo/ExamQuestionSelectVo.java @@ -4,22 +4,32 @@ * @date : 2019-06-17 23:10 * @email : liangshanguang2@gmail.com ***********************************************************/ -package lsgwr.exam.vo; - +package lsgwr.exam.vo;// 定义包名,用于组织类文件,避免命名冲突 +// 导入Jackson库的JsonProperty注解,用于JSON序列化时自定义字段名 import com.fasterxml.jackson.annotation.JsonProperty; +// 导入Lombok库的Data注解,用于自动生成getter、setter、equals、hashCode和toString方法 import lombok.Data; - +// 使用Lombok的@Data注解,自动为该类生成getter、setter等方法 @Data public class ExamQuestionSelectVo { + /** + * 问题的唯一标识符,在JSON序列化时,该字段的名称被指定为"id" + * 这通常用于前端向后端发送请求时,标识特定的选择题 + */ @JsonProperty("id") private String questionId; - + /** + * 问题的名称,在JSON序列化时,该字段的名称被指定为"name" + * 这通常用于在前端显示问题的名称 + */ @JsonProperty("name") private String questionName; /** - * 这个问题是否被选为了考试中的题目.默认是false,经过前端修改后可能会变成true, - * 传回来用于创建问题 + * 这个问题是否被选为了考试中的题目。默认值是false,表示未被选中。 + * 当前端用户进行选择后,该值可能会变为true,并随请求发送回后端, + * 用于在创建或更新考试时,确定哪些问题被包含在内。 + * 在JSON序列化时,该字段的名称被指定为"checked"。 */ @JsonProperty("checked") private Boolean checked = false; diff --git a/backend/src/main/java/lsgwr/exam/vo/ExamQuestionTypeVo.java b/backend/src/main/java/lsgwr/exam/vo/ExamQuestionTypeVo.java index 318cddc..333b3e0 100644 --- a/backend/src/main/java/lsgwr/exam/vo/ExamQuestionTypeVo.java +++ b/backend/src/main/java/lsgwr/exam/vo/ExamQuestionTypeVo.java @@ -4,21 +4,35 @@ * @date : 2019-06-23 11:00 * @email : liangshanguang2@gmail.com ***********************************************************/ -package lsgwr.exam.vo; - +package lsgwr.exam.vo;// 定义包名,用于组织类文件,避免命名冲突 +// 导入Jackson库的JsonProperty注解,用于JSON序列化时自定义字段名 import com.fasterxml.jackson.annotation.JsonProperty; +// 导入Lombok库的Data注解,用于自动生成getter、setter、equals、hashCode和toString方法 import lombok.Data; - +// 导入Java的List接口,用于存储对象的集合 import java.util.List; - +// 使用Lombok的@Data注解,自动为该类生成getter、setter等方法 @Data public class ExamQuestionTypeVo { + /** + * 单选题列表,包含多个ExamQuestionSelectVo对象,每个对象代表一个单选题。 + * 在JSON序列化时,该字段的名称被指定为"radios"。 + * 注意:这里的"radios"命名可能表示单选按钮(radio buttons)的集合。 + */ @JsonProperty("radios") private List examQuestionSelectVoRadioList; - + /** + * 多选题列表,包含多个ExamQuestionSelectVo对象,每个对象代表一个多选题。 + * 在JSON序列化时,该字段的名称被指定为"checks"。 + * 注意:这里的"checks"命名可能表示复选框(checkboxes)的集合。 + */ @JsonProperty("checks") private List examQuestionSelectVoCheckList; - + /** + * 判断题列表,包含多个ExamQuestionSelectVo对象,每个对象代表一个判断题。 + * 在JSON序列化时,该字段的名称被指定为"judges"。 + * 注意:这里的"judges"命名可能表示判断题(true/false或yes/no)的集合。 + */ @JsonProperty("judges") private List examQuestionSelectVoJudgeList; } diff --git a/backend/src/main/java/lsgwr/exam/vo/ExamRecordVo.java b/backend/src/main/java/lsgwr/exam/vo/ExamRecordVo.java index 5ac65c9..d2218dc 100644 --- a/backend/src/main/java/lsgwr/exam/vo/ExamRecordVo.java +++ b/backend/src/main/java/lsgwr/exam/vo/ExamRecordVo.java @@ -4,27 +4,34 @@ * @date : 2019/10/25 7:42 * @email : liangshanguang2@gmail.com ***********************************************************/ -package lsgwr.exam.vo; - -import lsgwr.exam.entity.Exam; -import lsgwr.exam.entity.ExamRecord; -import lsgwr.exam.entity.User; +package lsgwr.exam.vo;// 定义包名,用于组织类文件,避免命名冲突 +// 导入相关的实体类 +import lsgwr.exam.entity.Exam;// 考试实体类 +import lsgwr.exam.entity.ExamRecord; // 考试记录实体类 +import lsgwr.exam.entity.User;// 用户实体类 +// 导入Lombok库的Data注解,用于自动生成getter、setter、equals、hashCode和toString方法 import lombok.Data; - +// 使用Lombok的@Data注解自动生成getter、setter等方法 @Data public class ExamRecordVo { /** - * 当前考试记录对应的考试 + * 当前考试记录对应的考试。 + * 这个字段包含了考试的详细信息,如考试名称、描述、时间等。 + * 它是一个Exam类型的对象,与数据库中的Exam表相对应。 */ private Exam exam; /** - * 当前考试对应的内容 + * 当前考试对应的内容(或记录)。 + * 这个字段包含了考试记录的具体信息,如用户的答题情况、得分等。 + * 它是一个ExamRecord类型的对象,与数据库中的ExamRecord表相对应。 */ private ExamRecord examRecord; /** - * 参加考试的用户信息 + * 参加考试的用户信息。 + * 这个字段包含了用户的详细信息,如用户名、邮箱、头像等。 + * 它是一个User类型的对象,与数据库中的User表相对应。 */ private User user; } diff --git a/backend/src/main/java/lsgwr/exam/vo/ExamVo.java b/backend/src/main/java/lsgwr/exam/vo/ExamVo.java index 2947746..b8c2228 100644 --- a/backend/src/main/java/lsgwr/exam/vo/ExamVo.java +++ b/backend/src/main/java/lsgwr/exam/vo/ExamVo.java @@ -4,86 +4,83 @@ * @date : 2019/5/14 07:42 * @email : liangshanguang2@gmail.com ***********************************************************/ - +// 定义包名,用于组织类文件并避免命名冲突 package lsgwr.exam.vo; +// 导入所需的库和注解 +import com.fasterxml.jackson.annotation.JsonFormat;// 用于日期格式的序列化和反序列化 +import com.fasterxml.jackson.annotation.JsonProperty;// 用于自定义JSON字段名 +import lombok.Data;// 用于自动生成getter、setter等方法 -import com.fasterxml.jackson.annotation.JsonFormat; -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.Data; - -import java.util.Date; -import java.util.List; - +import java.util.Date;// Java日期类 +import java.util.List;// Java列表接口 +// 使用Lombok的@Data注解自动生成getter、setter等方法 @Data public class ExamVo { + // 使用@JsonProperty注解自定义JSON字段名为"id" @JsonProperty("id") - private String examId; + private String examId;// 考试的唯一标识符 + // 使用@JsonProperty注解自定义JSON字段名为"name" @JsonProperty("name") - private String examName; + private String examName;// 考试名称 + // 使用@JsonProperty注解自定义JSON字段名为"avatar" @JsonProperty("avatar") - private String examAvatar; + private String examAvatar;// 考试图标或头像 + // 使用@JsonProperty注解自定义JSON字段名为"desc" @JsonProperty("desc") - private String examDescription; - + private String examDescription;// 考试描述 + // 单选题列表,JSON字段名为"radios" @JsonProperty("radios") - private List examQuestionSelectVoRadioList; - + private List examQuestionSelectVoRadioList;// 单选题选项列表 + // 多选题列表,JSON字段名为"checks" @JsonProperty("checks") - private List examQuestionSelectVoCheckList; - + private List examQuestionSelectVoCheckList;// 多选题选项列表 + // 判断题列表,JSON字段名为"judges" @JsonProperty("judges") - private List examQuestionSelectVoJudgeList; - + private List examQuestionSelectVoJudgeList;// 判断题选项列表 + // 考试总分,JSON字段名为"score" @JsonProperty("score") - private Integer examScore; - + private Integer examScore;// 考试的总分数 + // 单选题总分,JSON字段名为"radioScore" @JsonProperty("radioScore") - private Integer examScoreRadio; - + private Integer examScoreRadio;// 单选题的总分数 + // 多选题总分,JSON字段名为"checkScore" @JsonProperty("checkScore") - private Integer examScoreCheck; - + private Integer examScoreCheck;// 多选题的总分数 + // 判断题总分,JSON字段名为"judgeScore" @JsonProperty("judgeScore") - private Integer examScoreJudge; + private Integer examScoreJudge;// 判断题的总分数 - /** - * 考试的创建人,根据id从用户表中查取姓名 - */ + // 考试创建人的名称,JSON字段名为"creator" + // 注意:这里假设只存储了创建人的名称,实际可能需要根据ID查询数据库获取 @JsonProperty("creator") - private String examCreator; + private String examCreator;// 考试的创建者名称 - /** - * 考试限制的时间,单位为分钟 - */ + // 考试的时间限制(分钟),JSON字段名为"elapse" @JsonProperty("elapse") - private Integer examTimeLimit; + private Integer examTimeLimit;// 考试的时间限制,单位为分钟 - /** - * 开始时间 - */ + // 考试开始时间,JSON字段名为"startDate" + // 使用@JsonFormat注解指定日期格式和时区 @JsonProperty("startDate") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") - private Date examStartDate; + private Date examStartDate;// 考试的开始时间 - /** - * 结束时间 - */ + // 考试结束时间,JSON字段名为"endDate" + // 使用@JsonFormat注解指定日期格式和时区 @JsonProperty("endDate") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") - private Date examEndDate; + private Date examEndDate;// 考试的结束时间 - /** - * 创建时间 - */ + // 创建时间,JSON字段名为"createTime" + // 使用@JsonFormat注解指定日期格式和时区 @JsonProperty("createTime") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") - private Date createTime; + private Date createTime;// 记录的创建时间 - /** - * 更新时间 - */ + // 更新时间,JSON字段名为"updateTime" + // 使用@JsonFormat注解指定日期格式和时区 @JsonProperty("updateTime") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") - private Date updateTime; + private Date updateTime;// 记录的更新时间 } diff --git a/backend/src/main/java/lsgwr/exam/vo/JsonData.java b/backend/src/main/java/lsgwr/exam/vo/JsonData.java index 9fd3ecd..b9823d4 100644 --- a/backend/src/main/java/lsgwr/exam/vo/JsonData.java +++ b/backend/src/main/java/lsgwr/exam/vo/JsonData.java @@ -16,7 +16,9 @@ import java.io.Serializable; @AllArgsConstructor @NoArgsConstructor public class JsonData implements Serializable { - + /** + * 序列化id + */ private static final long serialVersionUID = 1L; /** diff --git a/backend/src/main/java/lsgwr/exam/vo/PageVo.java b/backend/src/main/java/lsgwr/exam/vo/PageVo.java index 604abc3..45e88d4 100644 --- a/backend/src/main/java/lsgwr/exam/vo/PageVo.java +++ b/backend/src/main/java/lsgwr/exam/vo/PageVo.java @@ -10,15 +10,24 @@ import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; import java.util.List; - +/** + * 页面展示类 + */ @Data public class PageVo { + /** + * 页面动作集合 + */ @JsonProperty("actionEntitySet") private List actionVoList; - + /** + * 页面名称,即路由名称 + */ @JsonProperty("permissionId") private String pageName; - + /** + * 页面描述,即路由描述 + */ @JsonProperty("permissionName") private String pageDescription; } diff --git a/backend/src/main/java/lsgwr/exam/vo/QuestionCreateSimplifyVo.java b/backend/src/main/java/lsgwr/exam/vo/QuestionCreateSimplifyVo.java index 8eba970..9ddecf3 100644 --- a/backend/src/main/java/lsgwr/exam/vo/QuestionCreateSimplifyVo.java +++ b/backend/src/main/java/lsgwr/exam/vo/QuestionCreateSimplifyVo.java @@ -10,7 +10,9 @@ import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; import java.util.List; - +/** + * 问题创建的实体类,简化了下 + */ @Data public class QuestionCreateSimplifyVo { /** diff --git a/backend/src/main/java/lsgwr/exam/vo/QuestionCreateVo.java b/backend/src/main/java/lsgwr/exam/vo/QuestionCreateVo.java index b565a2e..04e2f52 100644 --- a/backend/src/main/java/lsgwr/exam/vo/QuestionCreateVo.java +++ b/backend/src/main/java/lsgwr/exam/vo/QuestionCreateVo.java @@ -10,7 +10,9 @@ import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; import java.util.List; - +/** + * 创建问题的实体类 + */ @Data public class QuestionCreateVo { /** diff --git a/backend/src/main/java/lsgwr/exam/vo/QuestionDetailVo.java b/backend/src/main/java/lsgwr/exam/vo/QuestionDetailVo.java index d6c6fae..85ae017 100644 --- a/backend/src/main/java/lsgwr/exam/vo/QuestionDetailVo.java +++ b/backend/src/main/java/lsgwr/exam/vo/QuestionDetailVo.java @@ -11,7 +11,9 @@ import lombok.Data; import java.util.ArrayList; import java.util.List; - +/** + * 问题详情的实体类 + */ @Data public class QuestionDetailVo { /** diff --git a/backend/src/main/java/lsgwr/exam/vo/QuestionOptionCreateVo.java b/backend/src/main/java/lsgwr/exam/vo/QuestionOptionCreateVo.java index 470088e..75f608e 100644 --- a/backend/src/main/java/lsgwr/exam/vo/QuestionOptionCreateVo.java +++ b/backend/src/main/java/lsgwr/exam/vo/QuestionOptionCreateVo.java @@ -8,7 +8,9 @@ package lsgwr.exam.vo; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; - +/** + * 问题选项的外层对象 + */ @Data public class QuestionOptionCreateVo { diff --git a/backend/src/main/java/lsgwr/exam/vo/QuestionOptionVo.java b/backend/src/main/java/lsgwr/exam/vo/QuestionOptionVo.java index 58cc32a..f7e94f6 100644 --- a/backend/src/main/java/lsgwr/exam/vo/QuestionOptionVo.java +++ b/backend/src/main/java/lsgwr/exam/vo/QuestionOptionVo.java @@ -8,18 +8,29 @@ package lsgwr.exam.vo; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; - +/** + * 问题选项的自定义实体类 + */ @Data public class QuestionOptionVo { + /** + * 问题选项的id + */ @JsonProperty("id") private String questionOptionId; - + /** + * 问题选项的内容 + */ @JsonProperty("content") private String questionOptionContent; - + /** + * 问题选项是否是答案 + */ @JsonProperty("answer") private Boolean answer = false; - + /** + * 问题选项的描述 + */ @JsonProperty("description") private String questionOptionDescription; } diff --git a/backend/src/main/java/lsgwr/exam/vo/QuestionPageVo.java b/backend/src/main/java/lsgwr/exam/vo/QuestionPageVo.java index 17ed650..fcc8678 100644 --- a/backend/src/main/java/lsgwr/exam/vo/QuestionPageVo.java +++ b/backend/src/main/java/lsgwr/exam/vo/QuestionPageVo.java @@ -10,7 +10,9 @@ import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; import java.util.List; - +/** + * 问题列表反馈给前端的对象 + */ @Data public class QuestionPageVo { diff --git a/backend/src/main/java/lsgwr/exam/vo/QuestionSelectionVo.java b/backend/src/main/java/lsgwr/exam/vo/QuestionSelectionVo.java index dfdbf93..423da6f 100644 --- a/backend/src/main/java/lsgwr/exam/vo/QuestionSelectionVo.java +++ b/backend/src/main/java/lsgwr/exam/vo/QuestionSelectionVo.java @@ -13,15 +13,24 @@ import lsgwr.exam.entity.QuestionType; import lombok.Data; import java.util.List; - +/** + * 前端创建问题时的下拉列表选择 + */ @Data public class QuestionSelectionVo { + /** + * 问题类型 + */ @JsonProperty("types") private List questionTypeList; - + /** + * 问题分类 + */ @JsonProperty("categories") private List questionCategoryList; - + /** + * 问题难度 + */ @JsonProperty("levels") private List questionLevelList; } diff --git a/backend/src/main/java/lsgwr/exam/vo/QuestionVo.java b/backend/src/main/java/lsgwr/exam/vo/QuestionVo.java index 5ce1744..e2e9016 100644 --- a/backend/src/main/java/lsgwr/exam/vo/QuestionVo.java +++ b/backend/src/main/java/lsgwr/exam/vo/QuestionVo.java @@ -12,15 +12,24 @@ import lombok.Data; import java.util.Date; import java.util.List; - +/** + * 问题的VO类,用于返回给前端 + */ @Data public class QuestionVo { + /** + * 问题id,从数据库表question中获取 + */ @JsonProperty("id") private String questionId; - + /** + * 问题名称,从数据库表question中获取 + */ @JsonProperty("name") private String questionName; - + /** + * 问题分值,从数据库表question中获取 + */ @JsonProperty("score") private Integer questionScore; diff --git a/backend/src/main/java/lsgwr/exam/vo/RecordDetailVo.java b/backend/src/main/java/lsgwr/exam/vo/RecordDetailVo.java index 21501dc..0605de7 100644 --- a/backend/src/main/java/lsgwr/exam/vo/RecordDetailVo.java +++ b/backend/src/main/java/lsgwr/exam/vo/RecordDetailVo.java @@ -11,7 +11,9 @@ import lombok.Data; import java.util.HashMap; import java.util.List; - +/** + * 考试记录详情的VO + */ @Data public class RecordDetailVo { /** diff --git a/backend/src/main/java/lsgwr/exam/vo/ResultVO.java b/backend/src/main/java/lsgwr/exam/vo/ResultVO.java index 12aa1bb..ec106d8 100644 --- a/backend/src/main/java/lsgwr/exam/vo/ResultVO.java +++ b/backend/src/main/java/lsgwr/exam/vo/ResultVO.java @@ -13,7 +13,12 @@ import lombok.Data; @JsonInclude(JsonInclude.Include.NON_NULL) // 避免返回NULL的字段 public class ResultVO { - + /** + * 构造函数 + * @param code 错误码 + * @param msg 提示信息 + * @param data 具体内容 + */ public ResultVO(Integer code, String msg, T data) { this.code = code; this.msg = msg; diff --git a/backend/src/main/java/lsgwr/exam/vo/RoleVo.java b/backend/src/main/java/lsgwr/exam/vo/RoleVo.java index 11ddba1..cec7e63 100644 --- a/backend/src/main/java/lsgwr/exam/vo/RoleVo.java +++ b/backend/src/main/java/lsgwr/exam/vo/RoleVo.java @@ -10,18 +10,29 @@ import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; import java.util.List; - +/** + * 角色的VO类 + */ @Data public class RoleVo { + /** + * 角色名 + */ @JsonProperty("id") private String roleName; - + /** + * 角色描述 + */ @JsonProperty("name") private String roleDescription; - + /** + * 角色的详细描述 + */ @JsonProperty("describe") private String roleDetail; - + /** + * 角色所拥有的权限 + */ @JsonProperty("permissions") private List pageVoList; } diff --git a/backend/src/main/java/lsgwr/exam/vo/UserInfoVo.java b/backend/src/main/java/lsgwr/exam/vo/UserInfoVo.java index 4bb6c6f..ea096ae 100644 --- a/backend/src/main/java/lsgwr/exam/vo/UserInfoVo.java +++ b/backend/src/main/java/lsgwr/exam/vo/UserInfoVo.java @@ -8,19 +8,29 @@ package lsgwr.exam.vo; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; - +/** + * 用户信息展示类 + */ @Data public class UserInfoVo { - + /** + * 用户ID,唯一 + */ @JsonProperty("id") private String userId; - + /** + * 头像URL + */ @JsonProperty("avatar") private String userAvatar; - + /** + * 用户名,唯一 + */ @JsonProperty("name") private String userNickname; - + /** + * 账号,唯一 + */ @JsonProperty("username") private String userUsername; diff --git a/backend/src/main/java/lsgwr/exam/vo/UserVo.java b/backend/src/main/java/lsgwr/exam/vo/UserVo.java index 056b93c..068d78e 100644 --- a/backend/src/main/java/lsgwr/exam/vo/UserVo.java +++ b/backend/src/main/java/lsgwr/exam/vo/UserVo.java @@ -8,30 +8,49 @@ package lsgwr.exam.vo; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; - +/** + * 用户信息展示类 + */ @Data public class UserVo { + /** + * 用户ID + */ @JsonProperty("id") private String userId; - + /** + * 用户名 + */ @JsonProperty("username") private String userUsername; - + /** + * 昵称 + */ @JsonProperty("nickname") private String userNickname; - + /** + * 角色ID + */ @JsonProperty("role") private Integer userRoleId; - + /** + * 头像 + */ @JsonProperty("avatar") private String userAvatar; - + /** + * 个人简介 + */ @JsonProperty("description") private String userDescription; - + /** + * 邮箱 + */ @JsonProperty("email") private String userEmail; - + /** + * 电话 + */ @JsonProperty("phone") private String userPhone; } diff --git a/frontend/public/index.html b/frontend/public/index.html index fd87ff4..0a9f41a 100644 --- a/frontend/public/index.html +++ b/frontend/public/index.html @@ -6,13 +6,91 @@ 在线考试系统 - + + + +
+
diff --git a/frontend/public/loading/loading.css b/frontend/public/loading/loading.css index a899eac..e06ac36 100644 --- a/frontend/public/loading/loading.css +++ b/frontend/public/loading/loading.css @@ -1 +1,52 @@ -#preloadingAnimation{position:fixed;left:0;top:0;height:100%;width:100%;background:#ffffff;user-select:none;z-index: 9999;overflow: hidden}.lds-roller{display:inline-block;position:relative;left:50%;top:50%;transform:translate(-50%,-50%);width:64px;height:64px;}.lds-roller div{animation:lds-roller 1.2s cubic-bezier(0.5,0,0.5,1) infinite;transform-origin:32px 32px;}.lds-roller div:after{content:" ";display:block;position:absolute;width:6px;height:6px;border-radius:50%;background:#13c2c2;margin:-3px 0 0 -3px;}.lds-roller div:nth-child(1){animation-delay:-0.036s;}.lds-roller div:nth-child(1):after{top:50px;left:50px;}.lds-roller div:nth-child(2){animation-delay:-0.072s;}.lds-roller div:nth-child(2):after{top:54px;left:45px;}.lds-roller div:nth-child(3){animation-delay:-0.108s;}.lds-roller div:nth-child(3):after{top:57px;left:39px;}.lds-roller div:nth-child(4){animation-delay:-0.144s;}.lds-roller div:nth-child(4):after{top:58px;left:32px;}.lds-roller div:nth-child(5){animation-delay:-0.18s;}.lds-roller div:nth-child(5):after{top:57px;left:25px;}.lds-roller div:nth-child(6){animation-delay:-0.216s;}.lds-roller div:nth-child(6):after{top:54px;left:19px;}.lds-roller div:nth-child(7){animation-delay:-0.252s;}.lds-roller div:nth-child(7):after{top:50px;left:14px;}.lds-roller div:nth-child(8){animation-delay:-0.288s;}.lds-roller div:nth-child(8):after{top:45px;left:10px;}#preloadingAnimation .load-tips{color: #13c2c2;font-size:2rem;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);margin-top:80px;text-align:center;width:400px;height:64px;} @keyframes lds-roller{0%{transform:rotate(0deg);} 100%{transform:rotate(360deg);}} \ No newline at end of file +#preloadingAnimation{ + position:fixed;left:0;top:0;height:100%;width:100%;background:#ffffff;user-select:none; + z-index: 9999;overflow: hidden} +.lds-roller{ + display:inline-block; + position:relative; + left:50%; + top:50%; + transform:translate(-50%,-50%); + width:64px; + height:64px; +} +.lds-roller div{ + animation:lds-roller 1.2s cubic-bezier(0.5,0,0.5,1) infinite; + transform-origin:32px 32px; +} +.lds-roller div:after{ + content:" "; + display:block; + position:absolute; + width:6px; + height:6px; + border-radius:50%; + background:#13c2c2; + margin:-3px 0 0 -3px; +} +.lds-roller div:nth-child(1){animation-delay:-0.036s;} +.lds-roller div:nth-child(1):after{top:50px;left:50px;} +.lds-roller div:nth-child(2){animation-delay:-0.072s;} +.lds-roller div:nth-child(2):after{top:54px;left:45px;} +.lds-roller div:nth-child(3){animation-delay:-0.108s;} +.lds-roller div:nth-child(3):after{top:57px;left:39px;} +.lds-roller div:nth-child(4){animation-delay:-0.144s;} +.lds-roller div:nth-child(4):after{top:58px;left:32px;} +.lds-roller div:nth-child(5){animation-delay:-0.18s;} +.lds-roller div:nth-child(5):after{top:57px;left:25px;} +.lds-roller div:nth-child(6){animation-delay:-0.216s;} +.lds-roller div:nth-child(6):after{top:54px;left:19px;} +.lds-roller div:nth-child(7){animation-delay:-0.252s;} +.lds-roller div:nth-child(7):after{top:50px;left:14px;} +.lds-roller div:nth-child(8){animation-delay:-0.288s;} +.lds-roller div:nth-child(8):after{top:45px;left:10px;} +#preloadingAnimation .load-tips{ + color: #13c2c2; + font-size:2rem; + position:absolute; + left:50%; + top:50%; + transform:translate(-50%,-50%);margin-top:80px; + text-align:center;width:400px;height:64px;} +@keyframes lds-roller{0%{transform:rotate(0deg);} + 100%{transform:rotate(360deg);}} \ No newline at end of file diff --git a/frontend/public/loading/loading.html b/frontend/public/loading/loading.html index 9b93196..1d51177 100644 --- a/frontend/public/loading/loading.html +++ b/frontend/public/loading/loading.html @@ -1 +1,27 @@ -
Loading
\ No newline at end of file +
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
Loading
+
\ No newline at end of file diff --git a/frontend/public/loading/option2/html_code_segment.html b/frontend/public/loading/option2/html_code_segment.html index df81b26..fc874e3 100644 --- a/frontend/public/loading/option2/html_code_segment.html +++ b/frontend/public/loading/option2/html_code_segment.html @@ -1,5 +1,31 @@ +/** + * 预加载动画 + */
+
- + + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/frontend/public/loading/option2/loading.css b/frontend/public/loading/option2/loading.css index c35cd73..4486a8a 100644 --- a/frontend/public/loading/option2/loading.css +++ b/frontend/public/loading/option2/loading.css @@ -1 +1,20 @@ -.preloading-animate{background:#ffffff;width:100%;height:100%;position:fixed;left:0;top:0;z-index:299;}.preloading-animate .preloading-wrapper{position:absolute;width:5rem;height:5rem;left:50%;top:50%;transform:translate(-50%,-50%);}.preloading-animate .preloading-wrapper .preloading-balls{font-size:5rem;} \ No newline at end of file +.preloading-animate{ + background:#ffffff; + width:100%; + height:100%; + position:fixed; + left:0; + top:0; + z-index:299; +} +.preloading-animate .preloading-wrapper{ + position:absolute; + width:5rem; + height:5rem; + left:50%; + top:50%; + transform:translate(-50%,-50%); +} +.preloading-animate .preloading-wrapper .preloading-balls{ + font-size:5rem; +} \ No newline at end of file diff --git a/frontend/src/api/exam.js b/frontend/src/api/exam.js index c6d98b5..1344922 100644 --- a/frontend/src/api/exam.js +++ b/frontend/src/api/exam.js @@ -1,8 +1,15 @@ -// 考试相关的接口,包括考试、问题、选项和评分等接口 +/** + * @description: 考试模块接口,包括考试、问题、选项和评分等接口 + */ import api from './index' import { axios } from '../utils/request' +/** + * @description: 根据传入的参数获取问题列表 + * @param {Object} parameter - 查询参数 + * @returns {Promise} - 返回问题列表的Promise对象 + */ export function getQuestionList (parameter) { return axios({ url: api.ExamQuestionList, @@ -11,6 +18,10 @@ export function getQuestionList (parameter) { }) } +/** + * @description: 获取所有问题 + * @returns {Promise} - 返回所有问题的Promise对象 + */ export function getQuestionAll () { return axios({ url: api.ExamQuestionAll, @@ -18,6 +29,11 @@ export function getQuestionAll () { }) } +/** + * @description: 更新问题信息 + * @param {Object} parameter - 问题更新参数 + * @returns {Promise} - 返回更新操作的Promise对象 + */ export function questionUpdate (parameter) { console.log(parameter) return axios({ @@ -27,6 +43,10 @@ export function questionUpdate (parameter) { }) } +/** + * @description: 获取问题的选项 + * @returns {Promise} - 返回问题选项的Promise对象 + */ export function getQuestionSelection () { return axios({ url: api.ExamQuestionSelection, @@ -37,6 +57,11 @@ export function getQuestionSelection () { }) } +/** + * @description: 创建新问题 + * @param {Object} parameter - 问题创建参数 + * @returns {Promise} - 返回创建操作的Promise对象 + */ export function questionCreate (parameter) { console.log(parameter) return axios({ @@ -46,6 +71,11 @@ export function questionCreate (parameter) { }) } +/** + * @description: 根据传入的参数获取考试列表 + * @param {Object} parameter - 查询参数 + * @returns {Promise} - 返回考试列表的Promise对象 + */ export function getExamList (parameter) { return axios({ url: api.ExamList, @@ -54,6 +84,10 @@ export function getExamList (parameter) { }) } +/** + * @description: 获取所有考试 + * @returns {Promise} - 返回所有考试的Promise对象 + */ export function getExamAll () { return axios({ url: api.ExamAll, @@ -61,7 +95,10 @@ export function getExamAll () { }) } -// 获取所有问题,按照单选、多选和判断进行分类 +/** + * @description: 获取所有问题,并按单选、多选和判断进行分类 + * @returns {Promise} - 返回分类问题列表的Promise对象 + */ export function getExamQuestionTypeList () { return axios({ url: api.ExamQuestionTypeList, @@ -72,6 +109,10 @@ export function getExamQuestionTypeList () { }) } +/** + * @description: 获取考试卡片列表 + * @returns {Promise} - 返回考试卡片列表的Promise对象 + */ export function getExamCardList () { return axios({ url: api.ExamCardList, @@ -82,6 +123,11 @@ export function getExamCardList () { }) } +/** + * @description: 创建新考试 + * @param {Object} parameter - 考试创建参数 + * @returns {Promise} - 返回创建操作的Promise对象 + */ export function examCreate (parameter) { console.log(parameter) return axios({ @@ -91,6 +137,11 @@ export function examCreate (parameter) { }) } +/** + * @description: 更新考试信息 + * @param {Object} parameter - 考试更新参数 + * @returns {Promise} - 返回更新操作的Promise对象 + */ export function examUpdate (parameter) { console.log(parameter) return axios({ @@ -100,6 +151,11 @@ export function examUpdate (parameter) { }) } +/** + * @description: 根据考试ID获取考试详情 + * @param {String} examId - 考试ID + * @returns {Promise} - 返回考试详情的Promise对象 + */ export function getExamDetail (examId) { return axios({ url: api.ExamDetail + examId, @@ -110,6 +166,11 @@ export function getExamDetail (examId) { }) } +/** + * @description: 根据记录ID获取考试记录详情 + * @param {String} recordId - 记录ID + * @returns {Promise} - 返回考试记录详情的Promise对象 + */ export function getExamRecordDetail (recordId) { return axios({ url: api.recordDetail + recordId, @@ -120,6 +181,11 @@ export function getExamRecordDetail (recordId) { }) } +/** + * @description: 根据问题ID获取问题详情 + * @param {String} questionId - 问题ID + * @returns {Promise} - 返回问题详情的Promise对象 + */ export function getQuestionDetail (questionId) { return axios({ url: api.QuestionDetail + questionId, @@ -130,6 +196,12 @@ export function getQuestionDetail (questionId) { }) } +/** + * @description: 提交考试答案,完成考试 + * @param {String} examId - 考试ID + * @param {Object} answersMap - 答案映射 + * @returns {Promise} - 返回完成考试的Promise对象 + */ export function finishExam (examId, answersMap) { console.log(answersMap) return axios({ @@ -142,6 +214,10 @@ export function finishExam (examId, answersMap) { }) } +/** + * @description: 获取所有考试记录 + * @returns {Promise} - 返回所有考试记录的Promise对象 + */ export function getExamRecordList () { return axios({ url: api.ExamRecordList, diff --git a/frontend/src/api/index.js b/frontend/src/api/index.js index 05423bf..6867621 100644 --- a/frontend/src/api/index.js +++ b/frontend/src/api/index.js @@ -1,38 +1,117 @@ +/** + * @description: api接口统一管理 + */ const api = { + /** + * @description: 用户登录的接口 + */ Login: '/auth/login', + /** + * @description: 用户注销的接口 + */ Logout: '/auth/logout', + /** + * @description: 重置密码的接口 + */ ForgePassword: '/auth/forge-password', + /** + * @description: 用户注册的接口 + */ Register: '/auth/register', + /** + * @description: 两步验证码的接口 + */ twoStepCode: '/auth/2step-code', + /** + * @description: 发送短信的接口 + */ SendSms: '/account/sms', + /** + * @description: 发送短信错误的接口 + */ SendSmsErr: '/account/sms_err', - // get my info + /** + * @description: 获取用户信息的接口 + */ UserInfo: '/user/info', // 下面是自己的用户认证的接口 + /** + * @description: 用户注册(自定义)的接口 + */ UserRegister: '/user/register', + /** + * @description: 用户登录(自定义)的接口 + */ UserLogin: '/user/login', // 考试的接口 + /** + * @description: 获取考试问题列表的接口 + */ ExamQuestionList: '/exam/question/list', + /** + * @description: 获取所有考试问题的接口 + */ ExamQuestionAll: '/exam/question/all', + /** + * @description: 更新考试问题的接口 + */ ExamQuestionUpdate: '/exam/question/update', + /** + * @description: 选择考试问题的接口 + */ ExamQuestionSelection: '/exam/question/selection', + /** + * @description: 创建考试问题的接口 + */ ExamQuestionCreate: '/exam/question/create', + /** + * @description: 获取考试列表的接口 + */ ExamList: '/exam/list', + /** + * @description: 获取所有考试的接口 + */ ExamAll: '/exam/all', - // 获取问题列表,按照单选、多选和判断进行分类 + /** + * @description: 按照单选、多选和判断分类获取问题列表的接口 + */ ExamQuestionTypeList: '/exam/question/type/list', + /** + * @description: 创建考试的接口 + */ ExamCreate: '/exam/create', + /** + * @description: 更新考试的接口 + */ ExamUpdate: '/exam/update', + /** + * @description: 获取考试卡片列表的接口 + */ ExamCardList: '/exam/card/list', - // 获取考试详情 + /** + * @description: 获取考试详情的接口 + */ ExamDetail: '/exam/detail/', - // 获取考试详情 + /** + * @description: 获取问题详情的接口 + */ QuestionDetail: '/exam/question/detail/', - // 交卷 + /** + * @description: 交卷的接口 + */ FinishExam: '/exam/finish/', + /** + * @description: 获取考试记录列表的接口 + */ ExamRecordList: '/exam/record/list', + /** + * @description: 获取考试记录详情的接口 + */ recordDetail: '/exam/record/detail/' } +/** + * @description: 默认导出api对象 + */ export default api diff --git a/frontend/src/api/login.js b/frontend/src/api/login.js index 9f71d6b..6ab7817 100644 --- a/frontend/src/api/login.js +++ b/frontend/src/api/login.js @@ -2,12 +2,12 @@ import api from './index' import { axios } from '../utils/request' /** - * login func - * parameter: { - * username: '', - * password: '', - * remember_me: true, - * captcha: '12345' + * 用户登录功能 + * 参数: { + * username: 用户名 + * password: 密码 + * remember_me: 是否记住 + * captcha: 验证码 * } * @param parameter * @returns {*} @@ -21,6 +21,11 @@ export function login (parameter) { }) } +/** + * 获取短信验证码 + * @param parameter + * @returns {*} + */ export function getSmsCaptcha (parameter) { return axios({ url: api.SendSms, @@ -29,6 +34,10 @@ export function getSmsCaptcha (parameter) { }) } +/** + * 获取用户信息 + * @returns {*} + */ export function getInfo () { return axios({ url: api.UserInfo, @@ -39,6 +48,10 @@ export function getInfo () { }) } +/** + * 用户登出 + * @returns {*} + */ export function logout () { return axios({ url: api.Logout, @@ -50,8 +63,9 @@ export function logout () { } /** - * get user 2step code open? - * @param parameter {*} + * 获取用户两步验证码开启状态 + * @param parameter + * @returns {*} */ export function get2step (parameter) { return axios({ diff --git a/frontend/src/api/user.js b/frontend/src/api/user.js index 71e361b..162ca03 100644 --- a/frontend/src/api/user.js +++ b/frontend/src/api/user.js @@ -3,6 +3,11 @@ import api from './index' import { axios } from '../utils/request' +/** + * 用户登录 + * @param {Object} parameter - 登录参数 + * @returns {Promise} - 返回登录请求的Promise + */ export function login (parameter) { return axios({ url: api.UserLogin, @@ -11,6 +16,11 @@ export function login (parameter) { }) } +/** + * 用户注册 + * @param {Object} parameter - 注册参数 + * @returns {Promise} - 返回注册请求的Promise + */ export function register (parameter) { return axios({ url: api.UserRegister, diff --git a/frontend/src/components/Exception/ExceptionPage.vue b/frontend/src/components/Exception/ExceptionPage.vue index 132e346..7e9d584 100644 --- a/frontend/src/components/Exception/ExceptionPage.vue +++ b/frontend/src/components/Exception/ExceptionPage.vue @@ -1,24 +1,33 @@ - - diff --git a/frontend/src/components/PageHeader/PageHeader.vue b/frontend/src/components/PageHeader/PageHeader.vue index b9df938..40f5c6b 100644 --- a/frontend/src/components/PageHeader/PageHeader.vue +++ b/frontend/src/components/PageHeader/PageHeader.vue @@ -1,28 +1,38 @@ - - diff --git a/frontend/src/layouts/PageView.vue b/frontend/src/layouts/PageView.vue index 32ce5c2..05fbaea 100644 --- a/frontend/src/layouts/PageView.vue +++ b/frontend/src/layouts/PageView.vue @@ -1,10 +1,16 @@