瀏覽代碼

exam process api

deason 3 年之前
父節點
當前提交
39423470a1

+ 124 - 12
examcloud-core-oe-student-api-provider/src/main/java/cn/com/qmth/examcloud/core/oe/student/api/controller/client/ExamProcessController.java

@@ -1,11 +1,17 @@
 package cn.com.qmth.examcloud.core.oe.student.api.controller.client;
 
 import cn.com.qmth.examcloud.api.commons.security.bean.User;
+import cn.com.qmth.examcloud.commons.exception.StatusException;
+import cn.com.qmth.examcloud.commons.util.JsonUtil;
 import cn.com.qmth.examcloud.core.oe.student.base.utils.Check;
 import cn.com.qmth.examcloud.core.oe.student.bean.*;
-import cn.com.qmth.examcloud.core.oe.student.service.ExamRecordQuestionsService;
-import cn.com.qmth.examcloud.support.examing.ExamQuestion;
-import cn.com.qmth.examcloud.support.examing.ExamRecordPaperStruct;
+import cn.com.qmth.examcloud.core.oe.student.service.*;
+import cn.com.qmth.examcloud.support.Constants;
+import cn.com.qmth.examcloud.support.enums.HandInExamType;
+import cn.com.qmth.examcloud.support.examing.*;
+import cn.com.qmth.examcloud.support.redis.RedisKeyHelper;
+import cn.com.qmth.examcloud.web.helpers.SequenceLockHelper;
+import cn.com.qmth.examcloud.web.redis.RedisClient;
 import cn.com.qmth.examcloud.web.support.ControllerSupport;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
@@ -24,52 +30,143 @@ public class ExamProcessController extends ControllerSupport {
     @Autowired
     private ExamRecordQuestionsService examRecordQuestionsService;
 
+    @Autowired
+    private ExamRecordPaperStructService examRecordPaperStructService;
+
+    @Autowired
+    private ExamControlService examControlService;
+
+    @Autowired
+    private ExamingSessionService examingSessionService;
+
+    @Autowired
+    private ExamRecordDataService examRecordDataService;
+
+    @Autowired
+    private RedisClient redisClient;
+
     @ApiOperation(value = "开始考试")
     @PostMapping("/startExam")
     public StartExamInfo startExam(@RequestParam Long examStudentId) {
-        return new StartExamInfo();
+        User user = getAccessUser();
+        String sequenceLockKey = Constants.EXAM_CONTROL_LOCK_PREFIX + user.getUserId();
+        StartExamInfo startExamInfo;
+        // 开始考试上锁,分布式锁,系统在请求结束后会,自动释放锁,无需手动解锁
+        SequenceLockHelper.getLock(sequenceLockKey);
+        Check.isNull(examStudentId, "examStudentId不能为空");
+
+        startExamInfo = examControlService.startExam(examStudentId, user, getIp(getRequest()));
+        return startExamInfo;
     }
 
     @ApiOperation(value = "开始答题")
     @PostMapping("/startAnswer")
     public StartAnswerInfo startAnswer(@RequestParam @ApiParam(value = "考试记录ID") Long examRecordDataId) {
-        return new StartAnswerInfo();
+        User user = getAccessUser();
+        String sequenceLockKey = Constants.EXAM_CONTROL_LOCK_PREFIX + user.getUserId();
+        // 开始考试上锁,分布式锁,系统在请求结束后会,自动释放锁,无需手动解锁
+        SequenceLockHelper.getLock(sequenceLockKey);
+        Check.isNull(examRecordDataId, "examRecordDataId不能为空");
+
+        return examControlService.startAnswer(examRecordDataId);
     }
 
     @ApiOperation(value = "断点续考:检查正在进行中的考试")
     @PostMapping("/checkExamInProgress")
     public ExamProcessResultInfo checkExamInProgress() {
-        return new ExamProcessResultInfo();
+        User user = getAccessUser();
+        String sequenceLockKey = Constants.EXAM_CONTROL_LOCK_PREFIX + user.getUserId();
+        // 系统在请求结束后会,自动释放锁,无需手动解锁
+        SequenceLockHelper.getLock(sequenceLockKey);
+        ExamProcessResultInfo res = new ExamProcessResultInfo();
+        try {
+            CheckExamInProgressInfo info = examControlService.checkExamInProgress(user.getUserId(), getIp(getRequest()));
+            res.setCode(Constants.COMMON_SUCCESS_CODE);
+            res.setData(info);
+            return res;
+        } catch (StatusException e) {
+            if (e.getCode().equals(Constants.EXAM_RECORD_NOT_END_STATUS_CODE)) {
+                res.setCode(Constants.PROCESSING_EXAM_RECORD_CODE);
+                return res;
+            }
+            throw e;
+        } catch (Exception e) {
+            throw e;
+        }
     }
 
     @ApiOperation(value = "考试心跳")
     @PostMapping("/examHeartbeat")
     public Long examHeartbeat(HttpServletRequest request) {
-        return null;
+        User user = getAccessUser();
+        return examControlService.examHeartbeat(user, getIp(request));
     }
 
     @ApiOperation(value = "结束考试:交卷")
     @PostMapping("/endExam")
     public void endExam(HttpServletRequest request) {
-
+        User user = getAccessUser();
+        Long studentId = user.getUserId();
+        String sequenceLockKey = Constants.EXAM_CONTROL_LOCK_PREFIX + user.getUserId();
+        //系统在请求结束后会,自动释放锁,无需手动解锁
+        SequenceLockHelper.getLock(sequenceLockKey);
+
+        long st = System.currentTimeMillis();
+        long startTime = System.currentTimeMillis();
+
+        ExamingSession examingSession = examingSessionService.getExamingSession(studentId);
+
+        if (examingSession == null) {
+            throw new StatusException("8010", "无效的会话,请离开考试");
+        }
+
+        if (LOGGER.isDebugEnabled()) {
+            LOGGER.debug("0 [END_EXAM] 交卷前处理耗时:" + (System.currentTimeMillis() - startTime) + " ms");
+        }
+        examControlService.handInExam(examingSession.getExamRecordDataId(), HandInExamType.MANUAL, getIp(request));
+        if (LOGGER.isDebugEnabled()) {
+            LOGGER.debug("1 [END_EXAM]合计 耗时:" + (System.currentTimeMillis() - st) + " ms");
+        }
     }
 
     @ApiOperation(value = "获取考试记录信息")
     @PostMapping("/getEndExamInfo")
     public EndExamInfo getEndExamInfo(@RequestParam Long examRecordDataId) {
-        return new EndExamInfo();
+        return examControlService.getEndExamInfo(examRecordDataId);
     }
 
     @ApiOperation(value = "获取考试记录试卷结构")
     @PostMapping("/getExamRecordPaperStruct")
     public ExamRecordPaperStruct getExamRecordPaperStruct(@RequestParam Long examRecordDataId) {
-        return null;
+        Check.isNull(examRecordDataId, "examRecordDataId不能为空");
+        return examRecordPaperStructService.getExamRecordPaperStruct(examRecordDataId);
     }
 
     @ApiOperation(value = "考试过程中-获取试题列表")
     @PostMapping("/findExamQuestionList")
     public List<ExamQuestion> findExamQuestionList() {
-        return null;
+        User user = getAccessUser();
+        ExamingSession examSessionInfo = examingSessionService.getExamingSession(user.getUserId());
+        if (examSessionInfo == null
+                || examSessionInfo.getExamingStatus().equals(ExamingStatus.INFORMAL)) {
+            throw new StatusException("1001", "考试会话已过期,请重新开考");
+        }
+
+        String examingHeartbeatKey = RedisKeyHelper.getBuilder().examingHeartbeatKey(examSessionInfo.getExamRecordDataId());
+        ExamingHeartbeat examingHeartbeat = redisClient.get(examingHeartbeatKey, ExamingHeartbeat.class);
+
+        if (null != examingHeartbeat
+                && examingHeartbeat.getCost() >= examSessionInfo.getExamDuration()) {
+            throw new StatusException("1001", "考试会话已过期,请重新开考");
+        }
+
+        ExamRecordQuestions qers = examRecordQuestionsService.getExamRecordQuestions(examSessionInfo.getExamRecordDataId());
+        List<ExamQuestion> examQuestionList = qers.getExamQuestions();
+        for (ExamQuestion examQuestion : examQuestionList) {
+            examQuestion.setCorrectAnswer(null);
+            examQuestion.setStudentScore(null);
+        }
+        return examQuestionList;
     }
 
     @ApiOperation(value = "考试过程中-获取试题内容")
@@ -84,6 +181,21 @@ public class ExamProcessController extends ControllerSupport {
     @PostMapping("/submitQuestionAnswer")
     public void submitQuestionAnswer(@RequestBody List<ExamStudentQuestionInfo> examQuestionInfos,
                                      HttpServletRequest request) {
+        if (LOGGER.isDebugEnabled()) {
+            String strJosn = JsonUtil.toJson(examQuestionInfos);
+            LOGGER.debug("ExamQuestionController--submitQuestionAnswer参数信息:" + strJosn);
+        }
+        User user = getAccessUser();
+        if (examQuestionInfos != null && examQuestionInfos.size() > 0) {
+            for (ExamStudentQuestionInfo examStudentQuestionInfo : examQuestionInfos) {
+                if (examStudentQuestionInfo.getOrder() == null) {
+                    throw new StatusException("2001", "illegal params");
+                }
+            }
+            String referer = request.getHeader("REFERER");
+            String agent = request.getHeader("USER-AGENT");
+            examRecordQuestionsService.submitQuestionAnswer(user.getUserId(), examQuestionInfos, referer, agent);
+        }
     }
 
     @ApiOperation(value = "保存活体检测结果")
@@ -95,7 +207,7 @@ public class ExamProcessController extends ControllerSupport {
     @ApiOperation(value = "获取课程名称")
     @PostMapping("/courseName/{id}")
     public String courseName(@PathVariable Long id) {
-        return null;
+        return examRecordDataService.findCourseNameById(id);
     }
 
 }