Преглед на файлове

Merge branch 'dev_openapi_bugfix'

wangliang преди 4 години
родител
ревизия
659a1910e0
променени са 26 файла, в които са добавени 345 реда и са изтрити 521 реда
  1. 1 1
      themis-admin/src/main/java/com/qmth/themis/admin/api/TBUserController.java
  2. 36 51
      themis-admin/src/main/java/com/qmth/themis/admin/api/TEOpenController.java
  3. 2 2
      themis-admin/src/main/java/com/qmth/themis/admin/interceptor/AuthInterceptor.java
  4. 1 1
      themis-admin/src/main/java/com/qmth/themis/admin/websocket/WebSocketAdminServer.java
  5. 2 26
      themis-business/src/main/java/com/qmth/themis/business/bean/admin/OpenRecordAnswerBean.java
  6. 15 75
      themis-business/src/main/java/com/qmth/themis/business/bean/admin/OpenRecordNeedMarkBean.java
  7. 1 1
      themis-business/src/main/java/com/qmth/themis/business/dao/TEExamStudentMapper.java
  8. 4 6
      themis-business/src/main/java/com/qmth/themis/business/dao/TOeExamAnswerMapper.java
  9. 1 1
      themis-business/src/main/java/com/qmth/themis/business/dao/TOeExamRecordMapper.java
  10. 1 1
      themis-business/src/main/java/com/qmth/themis/business/service/TEExamStudentService.java
  11. 1 2
      themis-business/src/main/java/com/qmth/themis/business/service/TOeExamAnswerService.java
  12. 1 1
      themis-business/src/main/java/com/qmth/themis/business/service/TOeExamRecordService.java
  13. 4 4
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamStudentServiceImpl.java
  14. 1 1
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TEMobileServiceImpl.java
  15. 197 274
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TEOpenServiceImpl.java
  16. 2 3
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TOeExamAnswerServiceImpl.java
  17. 2 2
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TOeExamRecordServiceImpl.java
  18. 6 7
      themis-business/src/main/java/com/qmth/themis/business/util/AuthUtil.java
  19. 19 9
      themis-business/src/main/java/com/qmth/themis/business/util/ServletUtil.java
  20. 24 8
      themis-business/src/main/resources/mapper/TEExamStudentMapper.xml
  21. 10 19
      themis-business/src/main/resources/mapper/TOeExamAnswerMapper.xml
  22. 9 21
      themis-business/src/main/resources/mapper/TOeExamRecordMapper.xml
  23. 1 1
      themis-exam/src/main/java/com/qmth/themis/exam/api/TEStudentController.java
  24. 2 2
      themis-exam/src/main/java/com/qmth/themis/exam/interceptor/AuthInterceptor.java
  25. 1 1
      themis-exam/src/main/java/com/qmth/themis/exam/websocket/WebSocketMobileServer.java
  26. 1 1
      themis-exam/src/main/java/com/qmth/themis/exam/websocket/WebSocketOeServer.java

+ 1 - 1
themis-admin/src/main/java/com/qmth/themis/admin/api/TBUserController.java

@@ -189,7 +189,7 @@ public class TBUserController {
         if (user.getEnable().intValue() == 0) {
             throw new BusinessException(ExceptionResultEnum.USER_ENABLE);
         }
-        Platform platform = Platform.valueOf(ServletUtil.getRequestPlatform());
+        Platform platform = ServletUtil.getRequestPlatform();
         String deviceId = ServletUtil.getRequestDeviceId();
         //添加用户鉴权缓存
         AuthDto authDto = cacheService.addAccountCache(user.getId());

+ 36 - 51
themis-admin/src/main/java/com/qmth/themis/admin/api/TEOpenController.java

@@ -1,11 +1,11 @@
 package com.qmth.themis.admin.api;
 
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
 import com.qmth.themis.business.service.TEOpenService;
-import com.qmth.themis.business.util.RedisUtil;
 import com.qmth.themis.common.exception.BusinessException;
-import com.qmth.themis.common.util.Result;
-import com.qmth.themis.common.util.ResultUtil;
 import io.swagger.annotations.*;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RequestParam;
@@ -29,84 +29,69 @@ public class TEOpenController {
     @Resource
     private TEOpenService openService;
 
-    @Resource
-    RedisUtil redisUtil;
-
     @ApiOperation(value = "获取考试详情")
     @RequestMapping(value = "/exam/query", method = RequestMethod.POST)
     @ApiResponses({ @ApiResponse(code = 200, message = "结果信息") })
-    public Result examQueryPage(@ApiParam(value = "考试id", required = false) @RequestParam(required = false) Long examId,
-            @ApiParam(value = "考试code", required = false) @RequestParam(required = false) String code,
-            @ApiParam(value = "分页页码", required = false) @RequestParam(required = false) Integer pageNumber,
-            @ApiParam(value = "分页数", required = false) @RequestParam(required = false) Integer pageSize) {
-
-        if (pageSize != null && pageSize.intValue() > 20) {
-            throw new BusinessException("每页最大条数为20");
-        }
-        if (pageNumber == null) {
+    public Object examQueryPage(@ApiParam(value = "考试id", required = false) @RequestParam(required = false) Long id,
+                                @ApiParam(value = "考试code", required = false) @RequestParam(required = false) String code,
+                                @ApiParam(value = "分页页码", required = false) @RequestParam(required = false) Integer pageNumber,
+                                @ApiParam(value = "分页数", required = false) @RequestParam(required = false) Integer pageSize) {
+        if (pageNumber == null || pageNumber < 1) {
             pageNumber = 1;
         }
-        if (pageSize == null) {
+        if (pageSize == null || pageSize < 1 || pageSize > 20) {
             pageSize = 20;
         }
-        return ResultUtil.ok(openService.examQueryPage(examId, code, pageNumber, pageSize));
+        return openService.examQueryPage(id, StringUtils.trimToNull(code), pageNumber, pageSize);
     }
 
     @ApiOperation(value = "获取考试课程详情")
     @RequestMapping(value = "/exam/course/query", method = RequestMethod.POST)
     @ApiResponses({ @ApiResponse(code = 200, message = "结果信息") })
-    public Result examCourseQueryPage(@ApiParam(value = "考试id", required = true) @RequestParam Long examId,
-            @ApiParam(value = "课程code", required = false) @RequestParam(required = false) String courseCode,
-            @ApiParam(value = "是否有试卷", required = false) @RequestParam(required = false) Boolean hasPaper,
-            @ApiParam(value = "分页页码", required = false) @RequestParam(required = false) Integer pageNumber,
-            @ApiParam(value = "分页数", required = false) @RequestParam(required = false) Integer pageSize) {
-        if (pageSize != null && pageSize.intValue() > 100) {
-            throw new BusinessException("每页最大条数为100");
-        }
-        if (pageNumber == null) {
+    public Object examCourseQueryPage(@ApiParam(value = "考试id", required = true) @RequestParam Long examId,
+                                      @ApiParam(value = "课程code", required = false) @RequestParam(required = false) String courseCode,
+                                      @ApiParam(value = "是否有试卷", required = false) @RequestParam(required = false) Boolean hasPaper,
+                                      @ApiParam(value = "分页页码", required = false) @RequestParam(required = false) Integer pageNumber,
+                                      @ApiParam(value = "分页数", required = false) @RequestParam(required = false) Integer pageSize) {
+        if (pageNumber == null || pageNumber < 1) {
             pageNumber = 1;
         }
-        if (pageSize == null) {
-            pageSize = 100;
+        if (pageSize == null || pageSize < 1) {
+            pageSize = 20;
         }
-        if (examId == null) {
-            throw new BusinessException("考试id不能为空");
+        if (pageSize > 100) {
+            pageSize = 100;
         }
-        return ResultUtil.ok(openService.examCourseQueryPage(examId, courseCode, hasPaper, pageNumber, pageSize));
+        return openService
+                .examCourseQueryPage(examId, StringUtils.trimToNull(courseCode), hasPaper, pageNumber, pageSize);
     }
 
     @ApiOperation(value = "获取考试试卷详情")
     @RequestMapping(value = "/exam/paper/detail", method = RequestMethod.POST)
     @ApiResponses({ @ApiResponse(code = 200, message = "结果信息") })
-    public Result examPaperDetail(@ApiParam(value = "试卷id", required = true) @RequestParam Long paperId,
-            @ApiParam(value = "内容过滤", required = false) @RequestParam(required = false) String filter)
+    public JSONObject examPaperDetail(@ApiParam(value = "试卷id", required = true) @RequestParam Long id,
+                                      @ApiParam(value = "内容过滤", required = false) @RequestParam(required = false) String filter)
             throws IOException {
-        if (paperId == null) {
-            throw new BusinessException("试卷id不能为空");
+        filter = StringUtils.trimToNull(filter);
+        if (filter != null && !"objective".equals(filter) && !"subjective".equals(filter)) {
+            throw new BusinessException("filter参数无效");
         }
-        return ResultUtil.ok(openService.examPaperDetail(paperId, filter));
+        return openService.examPaperDetail(id, filter);
     }
 
     @ApiOperation(value = "待评卷考试记录查询")
     @RequestMapping(value = "/exam/record/need_mark", method = RequestMethod.POST)
     @ApiResponses({ @ApiResponse(code = 200, message = "结果信息") })
-    public Result examRecordNeedMark(@ApiParam(value = "考试id", required = true) @RequestParam Long examId,
-            @ApiParam(value = "内容过滤卷", required = false) @RequestParam(required = false) String courseCode,
-            @ApiParam(value = "考生ID大于此参数", required = false) @RequestParam(required = false) Long examStudentIdGt,
-            @ApiParam(value = "数量(最大20)", required = false) @RequestParam(required = false) Integer count) {
-        if (examId == null) {
-            throw new BusinessException("考试id不能为空");
-        }
-        if (examStudentIdGt == null) {
+    public JSONArray examRecordNeedMark(@ApiParam(value = "考试id", required = true) @RequestParam Long examId,
+                                        @ApiParam(value = "课程代码", required = false) @RequestParam(required = false) String courseCode,
+                                        @ApiParam(value = "考生ID大于此参数", required = false) @RequestParam(required = false) Long examStudentIdGt,
+                                        @ApiParam(value = "数量(最大20)", required = false) @RequestParam(required = false) Integer count) {
+        if (examStudentIdGt == null || examStudentIdGt < 0) {
             examStudentIdGt = 0L;
         }
-        if (count != null && count.intValue() > 20) {
-            throw new BusinessException("count最大为20");
-        }
-        if (count == null) {
+        if (count == null || count < 0 || count > 20) {
             count = 20;
         }
-        return ResultUtil.ok(openService.examRecordNeedMark(examId, courseCode, examStudentIdGt, count));
+        return openService.examRecordNeedMark(examId, StringUtils.trimToNull(courseCode), examStudentIdGt, count);
     }
-
-}
+}

+ 2 - 2
themis-admin/src/main/java/com/qmth/themis/admin/interceptor/AuthInterceptor.java

@@ -37,10 +37,10 @@ public class AuthInterceptor implements HandlerInterceptor {
         if (url.equalsIgnoreCase(SystemConstant.ERROR)) {
             throw new BusinessException(ExceptionResultEnum.NOT_FOUND);
         }
-        Platform platform = Platform.valueOf(ServletUtil.getRequestPlatform());
+        Platform platform = ServletUtil.getRequestPlatform();
         String deviceId = ServletUtil.getRequestDeviceId();
         String authorization = ServletUtil.getRequestAuthorization();
-        String time = ServletUtil.getRequestTime();
+        Long time = ServletUtil.getRequestTime();
         log.info("Start authorization: url:{}, method:{}, platform:{}, deviceId:{}, authorization:{}, time:{}", url,
                 method, platform, deviceId, authorization, time);
         return AuthUtil.adminAuthInterceptor(platform, deviceId, authorization, time, dictionaryConfig.systemUrlDomain().getUrls(), request, response);

+ 1 - 1
themis-admin/src/main/java/com/qmth/themis/admin/websocket/WebSocketAdminServer.java

@@ -74,7 +74,7 @@ public class WebSocketAdminServer
         this.userId = Long.parseLong(String.valueOf(mapParameter.get(Constants.HEADER_USER_ID).get(0)));
 
         redisUtil = SpringContextHolder.getBean(RedisUtil.class);
-        TBSession tbSession = AuthUtil.websocketAuthInterceptor(Platform.valueOf(platform), deviceId, authorization, String.valueOf(mapParameter.get(Constants.HEADER_TIME).get(0)), SystemConstant.GET, url);
+        TBSession tbSession = AuthUtil.websocketAuthInterceptor(Platform.valueOf(platform), deviceId, authorization, Long.parseLong(mapParameter.get(Constants.HEADER_TIME).get(0)), SystemConstant.GET, url);
         this.session = session;
         session.setMaxIdleTimeout(SystemConstant.WEBSOCKET_MAX_TIME_OUT);
         this.sessionId = tbSession.getId();

+ 2 - 26
themis-business/src/main/java/com/qmth/themis/business/bean/admin/OpenRecordAnswerBean.java

@@ -6,32 +6,18 @@ import io.swagger.annotations.ApiModelProperty;
 @ApiModel("开放接口-待评卷考试记录答案")
 public class OpenRecordAnswerBean {
 
-	@ApiModelProperty("考试记录id")
-	private Long recordId;
-	
-	@ApiModelProperty("试卷id")
-	private Long paperId;
-	
 	@ApiModelProperty("大题号")
 	private Integer mainNumber;
 
 	@ApiModelProperty("小题号")
 	private Integer subNumber;
-	
+
 	@ApiModelProperty("套题子题序号")
 	private Integer subIndex;
-	
+
 	@ApiModelProperty("作答")
 	private String answer;
 
-	public Long getRecordId() {
-		return recordId;
-	}
-
-	public void setRecordId(Long recordId) {
-		this.recordId = recordId;
-	}
-
 	public Integer getMainNumber() {
 		return mainNumber;
 	}
@@ -63,14 +49,4 @@ public class OpenRecordAnswerBean {
 	public void setAnswer(String answer) {
 		this.answer = answer;
 	}
-
-	public Long getPaperId() {
-		return paperId;
-	}
-
-	public void setPaperId(Long paperId) {
-		this.paperId = paperId;
-	}
-	
-	
 }

+ 15 - 75
themis-business/src/main/java/com/qmth/themis/business/bean/admin/OpenRecordNeedMarkBean.java

@@ -1,76 +1,34 @@
 package com.qmth.themis.business.bean.admin;
 
-import java.util.List;
-
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 
+import java.util.List;
+
 @ApiModel("开放接口-待评卷考试记录")
 public class OpenRecordNeedMarkBean {
 
-	
-	@ApiModelProperty(name = "考生id")
-    private Long examStudentId;
-	
 	@ApiModelProperty(name = "考试记录id")
-    private Long examRecordId;
-
-	@ApiModelProperty(value = "证件号")
-    private String identity;
-
-    @ApiModelProperty(value = "姓名")
-    private String name;
-
-    @ApiModelProperty(value = "场次代码")
-    private String activityCode;
-
-    @ApiModelProperty(value = "课程名称")
-    private String courseName;
-
-    @ApiModelProperty(value = "试卷ID")
-    private Long paperId;
-    
-    @ApiModelProperty(value = "客观得分")
-    private Double objectiveScore;
-    
-    @ApiModelProperty(value = "交卷时间")
-    private Long finishTime;
-    
-    
-    @ApiModelProperty(value = "作答结果")
-    private List<OpenRecordAnswerBean> answers;
-
-
-	public String getIdentity() {
-		return identity;
-	}
-
-	public void setIdentity(String identity) {
-		this.identity = identity;
-	}
+	private Long id;
 
-	public String getName() {
-		return name;
-	}
+	@ApiModelProperty(value = "试卷ID")
+	private Long paperId;
 
-	public void setName(String name) {
-		this.name = name;
-	}
+	@ApiModelProperty(value = "客观得分")
+	private Double objectiveScore;
 
-	public String getActivityCode() {
-		return activityCode;
-	}
+	@ApiModelProperty(value = "交卷时间")
+	private Long finishTime;
 
-	public void setActivityCode(String activityCode) {
-		this.activityCode = activityCode;
-	}
+	@ApiModelProperty(value = "作答结果")
+	private List<OpenRecordAnswerBean> answers;
 
-	public String getCourseName() {
-		return courseName;
+	public Long getId() {
+		return id;
 	}
 
-	public void setCourseName(String courseName) {
-		this.courseName = courseName;
+	public void setId(Long id) {
+		this.id = id;
 	}
 
 	public Long getPaperId() {
@@ -97,22 +55,6 @@ public class OpenRecordNeedMarkBean {
 		this.answers = answers;
 	}
 
-	public Long getExamStudentId() {
-		return examStudentId;
-	}
-
-	public void setExamStudentId(Long examStudentId) {
-		this.examStudentId = examStudentId;
-	}
-
-	public Long getExamRecordId() {
-		return examRecordId;
-	}
-
-	public void setExamRecordId(Long examRecordId) {
-		this.examRecordId = examRecordId;
-	}
-
 	public Long getFinishTime() {
 		return finishTime;
 	}
@@ -120,6 +62,4 @@ public class OpenRecordNeedMarkBean {
 	public void setFinishTime(Long finishTime) {
 		this.finishTime = finishTime;
 	}
-    
-	
 }

+ 1 - 1
themis-business/src/main/java/com/qmth/themis/business/dao/TEExamStudentMapper.java

@@ -107,6 +107,6 @@ public interface TEExamStudentMapper extends BaseMapper<TEExamStudent> {
      */
     public List<MarkResultSimpleExportDto> markResultQueryExport(@Param("examId") Long examId, @Param("activityId") Long activityId, @Param("identity") String identity, @Param("name") String name, @Param("courseCode") String courseCode);
 
-	public List<Long> findExamStudentIdsNeedMark(@Param("examId") Long examId, @Param("courseCode") String courseCode,
+	public List<TEExamStudentDto> findExamStudentNeedMark(@Param("examId") Long examId, @Param("courseCode") String courseCode,
             @Param("idGt") Long idGt, @Param("count") Integer count);
 }

+ 4 - 6
themis-business/src/main/java/com/qmth/themis/business/dao/TOeExamAnswerMapper.java

@@ -3,12 +3,11 @@ package com.qmth.themis.business.dao;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.qmth.themis.business.bean.admin.OpenRecordAnswerBean;
 import com.qmth.themis.business.entity.TOeExamAnswer;
-
-import java.util.List;
-
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 
+import java.util.List;
+
 /**
  * @Description: 作答结果 Mapper 接口
  * @Param:
@@ -19,6 +18,5 @@ import org.apache.ibatis.annotations.Param;
 @Mapper
 public interface TOeExamAnswerMapper extends BaseMapper<TOeExamAnswer> {
 
-	List<OpenRecordAnswerBean> findByRecordIds(@Param("ids") List<Long> ids);
-
-}
+	List<OpenRecordAnswerBean> findByExamRecordId(@Param("examRecordId") Long examRecordId);
+}

+ 1 - 1
themis-business/src/main/java/com/qmth/themis/business/dao/TOeExamRecordMapper.java

@@ -348,7 +348,7 @@ public interface TOeExamRecordMapper extends BaseMapper<TOeExamRecord> {
 
     public void updateHasAnswerFile(@Param("recordId") Long recordId, @Param("hasAnswerFile") Integer hasAnswerFile);
 
-    public List<OpenRecordNeedMarkBean> findExamRecordNeedMark(@Param("examId") Long examId, @Param("examStudentIds") List<Long> examStudentIds);
+    public List<OpenRecordNeedMarkBean> findExamRecordNeedMark(@Param("examStudentId") Long examStudentId);
 
     /**
      * 寻找客观分最高

+ 1 - 1
themis-business/src/main/java/com/qmth/themis/business/service/TEExamStudentService.java

@@ -92,5 +92,5 @@ public interface TEExamStudentService extends IService<TEExamStudent> {
      */
     public List<MarkResultSimpleExportDto> markResultQueryExport(Long examId, Long activityId, String identity, String name, String courseCode);
 
-	public List<Long> findExamStudentIdsNeedMark(Long examId, String courseCode, Long idGt, Integer count);
+	public List<TEExamStudentDto> findExamStudentNeedMark(Long examId, String courseCode, Long idGt, Integer count);
 }

+ 1 - 2
themis-business/src/main/java/com/qmth/themis/business/service/TOeExamAnswerService.java

@@ -15,6 +15,5 @@ import com.qmth.themis.business.entity.TOeExamAnswer;
  */
 public interface TOeExamAnswerService extends IService<TOeExamAnswer> {
 
-	List<OpenRecordAnswerBean> findByRecordIds(List<Long> ids);
-
+	List<OpenRecordAnswerBean> findByExamRecordId(Long examRecordId);
 }

+ 1 - 1
themis-business/src/main/java/com/qmth/themis/business/service/TOeExamRecordService.java

@@ -384,7 +384,7 @@ public interface TOeExamRecordService extends IService<TOeExamRecord> {
 
     TOeExamRecord findOneByExamId(Long examId, ExamRecordStatusEnum status);
 
-    public List<OpenRecordNeedMarkBean> findExamRecordNeedMark(Long examId, List<Long> examStudentIds);
+    public List<OpenRecordNeedMarkBean> findExamRecordNeedMark(Long examStudentId);
 
     /**
      * 寻找客观分最高

+ 4 - 4
themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamStudentServiceImpl.java

@@ -176,8 +176,8 @@ public class TEExamStudentServiceImpl extends ServiceImpl<TEExamStudentMapper, T
         return teExamStudentMapper.markResultQueryExport(examId, activityId, identity, name, courseCode);
     }
 
-	@Override
-	public List<Long> findExamStudentIdsNeedMark(Long examId, String courseCode, Long idGt, Integer count) {
-		return teExamStudentMapper.findExamStudentIdsNeedMark( examId, courseCode,  idGt, count);
-	}
+    @Override
+    public List<TEExamStudentDto> findExamStudentNeedMark(Long examId, String courseCode, Long idGt, Integer count) {
+        return teExamStudentMapper.findExamStudentNeedMark(examId, courseCode, idGt, count);
+    }
 }

+ 1 - 1
themis-business/src/main/java/com/qmth/themis/business/service/impl/TEMobileServiceImpl.java

@@ -62,7 +62,7 @@ public class TEMobileServiceImpl implements TEMobileService {
         String code = param.getCode();
         MobileAuthorizationBean ret = null;
         Source source = null;
-        Platform platform = Platform.valueOf(ServletUtil.getRequestPlatform());
+        Platform platform = ServletUtil.getRequestPlatform();
         if (MobileModeEnum.MOBILE_MONITOR.equals(mode)) {
             MobileAuthorizationMonitorBean mb = new MobileAuthorizationMonitorBean();
             ret = mb;

+ 197 - 274
themis-business/src/main/java/com/qmth/themis/business/service/impl/TEOpenServiceImpl.java

@@ -11,23 +11,25 @@ import com.qmth.themis.business.bean.admin.OpenRecordAnswerBean;
 import com.qmth.themis.business.bean.admin.OpenRecordNeedMarkBean;
 import com.qmth.themis.business.cache.RedisKeyHelper;
 import com.qmth.themis.business.cache.bean.ExamPaperCacheBean;
-import com.qmth.themis.business.constant.SystemConstant;
+import com.qmth.themis.business.dto.response.TEExamStudentDto;
 import com.qmth.themis.business.entity.TEExam;
-import com.qmth.themis.business.entity.TEExamCourse;
 import com.qmth.themis.business.enums.InvigilateMonitorStatusEnum;
 import com.qmth.themis.business.enums.RecordSelectStrategyEnum;
 import com.qmth.themis.business.service.*;
 import com.qmth.themis.business.util.OssUtil;
 import com.qmth.themis.common.exception.BusinessException;
-import com.qmth.themis.common.util.FileUtil;
 import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
-import java.io.File;
-import java.util.*;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 import java.util.stream.Collectors;
 
 @Service
@@ -66,7 +68,8 @@ public class TEOpenServiceImpl implements TEOpenService {
 
     @Override
     public List<OpenExamCourseBean> examCourseQueryPage(Long examId, String courseCode, Boolean hasPaper,
-            int pageNumber, int pageSize) {
+                                                        int pageNumber, int pageSize) {
+        checkExam(examId);
         Page<OpenExamCourseBean> ipage = new Page<>(pageNumber, pageSize);
         ipage.addOrder(OrderItem.desc("t.id"));
         IPage<OpenExamCourseBean> ret = examCourseService.examCourseQueryForOpen(ipage, examId, courseCode, hasPaper);
@@ -74,309 +77,229 @@ public class TEOpenServiceImpl implements TEOpenService {
     }
 
     @Override
-    public JSONObject examPaperDetail(Long paperId, String filter) {
-        String tempDir = SystemConstant.TEMP_FILES_DIR;
-        String dir = tempDir + "/" + uuid() + "/";
-        File dfile = new File(dir);
-
-        try {
-            ExamPaperCacheBean paper = examPaperService.getExamPaperCacheBean(paperId);
-            if (paper == null) {
-                throw new BusinessException("未找到试卷信息");
+    public JSONObject examPaperDetail(Long paperId, String filter) throws IOException {
+        ExamPaperCacheBean paper = examPaperService.getExamPaperCacheBean(paperId);
+        if (paper == null) {
+            throw new BusinessException("未找到试卷信息");
+        }
+        checkExam(paper.getExamId());
+        if (StringUtils.isBlank(paper.getAnswerPath())) {
+            throw new BusinessException("该试卷未上传答案");
+        }
+        boolean acceptObjective = filter == null || "objective".equals(filter);
+        boolean acceptSubjective = filter == null || "subjective".equals(filter);
+        //解析答案JSON文件
+        JSONObject answerJson = JSONObject
+                .parseObject(new String(ossUtil.download(false, paper.getAnswerPath()), StandardCharsets.UTF_8));
+        JSONArray answerDetails = answerJson.getJSONArray("details");
+        //解析试卷JSON文件
+        JSONObject paperResult = JSONObject
+                .parseObject(new String(ossUtil.download(false, paper.getPaperViewPath()), StandardCharsets.UTF_8));
+        paperResult.put("id", paper.getId());
+        paperResult.put("code", paper.getCode());
+        paperResult.put("name", paper.getName());
+        JSONArray detailCollection = new JSONArray();
+        JSONArray paperDetails = paperResult.getJSONArray("details");
+        for (int i = 0; i < paperDetails.size(); i++) {
+            //遍历所有大题
+            JSONObject paperDetail = paperDetails.getJSONObject(i);
+            JSONObject answerDetail = findJsonObject(answerDetails, paperDetail.getIntValue("number"));
+            //按条件过滤需要的小题同时合并答案
+            JSONArray questionCollection = filterQuestions(paperDetail.getJSONArray("questions"),
+                    answerDetail != null ? answerDetail.getJSONArray("questions") : null, acceptObjective,
+                    acceptSubjective);
+            //有小题的情况下,本大题才需要被包含
+            if (questionCollection.size() > 0) {
+                paperDetail.put("questions", questionCollection);
+                detailCollection.add(paperDetail);
             }
-            checkExam(paper.getExamId());
-            dfile.mkdirs();
-            String paperPath = paper.getPaperViewPath();
-            String anwserPath = paper.getAnswerPath();
-            File paperFile = new File(dir + uuid() + ".json");
-            File anwserFile = new File(dir + uuid() + ".json");
-            FileUtil.saveUrlAsFile(ossUtil.getAliYunOssPrivateDomain().getPrivateUrl() + "/" + paperPath, paperFile);
-            FileUtil.saveUrlAsFile(ossUtil.getAliYunOssPrivateDomain().getPrivateUrl() + "/" + anwserPath, anwserFile);
-            JSONObject answerJson = JSONObject.parseObject(FileUtil.readFileContent(anwserFile));
-            JSONArray answerdetails = answerJson.getJSONArray("details");
-            JSONObject structJson = JSONObject.parseObject(FileUtil.readFileContent(paperFile));
-            structJson.put("id", paperId);
-            structJson.put("code", paper.getCode());
-            JSONArray structdetails = structJson.getJSONArray("details");
-            for (int i = 0; i < answerdetails.size(); i++) {
-                JSONArray answerdetailquestions = answerdetails.getJSONObject(i).getJSONArray("questions");
-                JSONArray structdetailquestions = structdetails.getJSONObject(i).getJSONArray("questions");
-                for (int j = 0; j < structdetailquestions.size(); j++) {
-                    JSONObject answerquestion = answerdetailquestions.getJSONObject(j);
-                    JSONObject structquestion = structdetailquestions.getJSONObject(j);
-                    if ("objective".equals(filter)) {
-                        if (structquestion.getInteger("structType").intValue() == 1
-                                || structquestion.getInteger("structType").intValue() == 2
-                                || structquestion.getInteger("structType").intValue() == 3) {
-                            if (structquestion.getInteger("structType").intValue() == 3) {
-                                structquestion.put("answer", answerquestion.getBoolean("answer"));
-                            } else {
-                                structquestion.put("answer", answerquestion.getJSONArray("answer"));
-                            }
-                        } else {
-                            if (structquestion.getInteger("structType").intValue() == 6) {
-                                JSONArray answersubQuestions = answerquestion.getJSONArray("subQuestions");
-                                JSONArray structsubQuestions = structquestion.getJSONArray("subQuestions");
-                                for (int k = 0; k < structsubQuestions.size(); k++) {
-                                    JSONObject answersubquestion = answersubQuestions.getJSONObject(k);
-                                    JSONObject structsubquestion = structsubQuestions.getJSONObject(k);
-                                    if (structsubquestion.getInteger("structType").intValue() == 1
-                                            || structsubquestion.getInteger("structType").intValue() == 2
-                                            || structsubquestion.getInteger("structType").intValue() == 3) {
-                                        if (structsubquestion.getInteger("structType").intValue() == 3) {
-                                            structsubquestion.put("answer", answersubquestion.getBoolean("answer"));
-                                        } else {
-                                            structsubquestion.put("answer", answersubquestion.getJSONArray("answer"));
-                                        }
-                                    } else {
-                                        structsubQuestions.remove(k);
-                                        k--;
-                                    }
-                                }
-                            } else {
-                                structdetailquestions.remove(j);
-                                j--;
-                            }
-                        }
+        }
+        paperResult.put("details", detailCollection);
+        return paperResult;
+    }
 
-                    } else if ("subjective".equals(filter)) {
-                        if (structquestion.getInteger("structType").intValue() != 1
-                                && structquestion.getInteger("structType").intValue() != 2
-                                && structquestion.getInteger("structType").intValue() != 3) {
-                            structquestion.put("answer", answerquestion.getJSONArray("answer"));
-                        } else {
-                            if (structquestion.getInteger("structType").intValue() == 6) {
-                                JSONArray answersubQuestions = answerquestion.getJSONArray("subQuestions");
-                                JSONArray structsubQuestions = structquestion.getJSONArray("subQuestions");
-                                for (int k = 0; k < structsubQuestions.size(); k++) {
-                                    JSONObject answersubquestion = answersubQuestions.getJSONObject(k);
-                                    JSONObject structsubquestion = structsubQuestions.getJSONObject(k);
-                                    if (structsubquestion.getInteger("structType").intValue() != 1
-                                            && structsubquestion.getInteger("structType").intValue() != 2
-                                            && structsubquestion.getInteger("structType").intValue() != 3) {
-                                        structsubquestion.put("answer", answersubquestion.getJSONArray("answer"));
-                                    } else {
-                                        structsubQuestions.remove(k);
-                                        k--;
-                                    }
-                                }
-                            } else {
-                                structdetailquestions.remove(j);
-                                j--;
-                            }
-                        }
+    private JSONArray filterQuestions(JSONArray questions, JSONArray answers, boolean acceptObjective,
+                                      boolean acceptSubjective) {
+        JSONArray collection = new JSONArray();
+        for (int i = 0; i < questions.size(); i++) {
+            JSONObject question = questions.getJSONObject(i);
+            //根据题号查找答案
+            JSONObject answer = findJsonObject(answers, question.getIntValue("number"));
+            boolean accept = true;
+            //判断结构类型
+            switch (question.getIntValue("structType")) {
+                case 1:
+                    //单选
+                case 2:
+                    //多选
+                case 3:
+                    //判断
+                    accept = acceptObjective;
+                    break;
+                case 4:
+                    //填空
+                case 5:
+                    //问答
+                    accept = acceptSubjective;
+                    break;
+                case 6:
+                    //套题
+                    //按条件过滤套题下所有子题
+                    JSONArray subAnswers = answer != null ? answer.getJSONArray("subQuestions") : null;
+                    JSONArray subCollection = filterQuestions(question.getJSONArray("subQuestions"), subAnswers,
+                            acceptObjective, acceptSubjective);
+                    //没有子题,则本题也被过滤掉
+                    if (subCollection.size() > 0) {
+                        question.put("subQuestions", subCollection);
                     } else {
-                        if (structquestion.getInteger("structType").intValue() != 6) {
-                            if (structquestion.getInteger("structType").intValue() == 3) {
-                                structquestion.put("answer", answerquestion.getBoolean("answer"));
-                            } else {
-                                structquestion.put("answer", answerquestion.getJSONArray("answer"));
-                            }
-                        } else {
-                            JSONArray answersubQuestions = answerquestion.getJSONArray("subQuestions");
-                            JSONArray structsubQuestions = structquestion.getJSONArray("subQuestions");
-                            for (int k = 0; k < structsubQuestions.size(); k++) {
-                                JSONObject answersubquestion = answersubQuestions.getJSONObject(k);
-                                JSONObject structsubquestion = structsubQuestions.getJSONObject(k);
-                                if (structsubquestion.getInteger("structType").intValue() == 3) {
-                                    structsubquestion.put("answer", answersubquestion.getBoolean("answer"));
-                                } else {
-                                    structsubquestion.put("answer", answersubquestion.getJSONArray("answer"));
-                                }
-                            }
-                        }
+                        accept = false;
                     }
-
+                    break;
+                default:
+                    accept = false;
+            }
+            if (accept) {
+                if (answer != null) {
+                    question.put("answer", answer.get("answer"));
                 }
+                collection.add(question);
             }
-            return structJson;
-        } finally {
-            FileUtil.deleteFolder(dir);
         }
+        return collection;
     }
 
-    private String uuid() {
-        return UUID.randomUUID().toString().replaceAll("-", "");
+    private JSONObject findJsonObject(JSONArray array, int number) {
+        if (array != null) {
+            for (int i = 0; i < array.size(); i++) {
+                JSONObject item = array.getJSONObject(i);
+                if (item.getIntValue("number") == number) {
+                    return item;
+                }
+            }
+        }
+        return null;
     }
 
-    private void checkExam(Long examId) {
+    private TEExam checkExam(Long examId) {
         TEExam exam = examService.getById(examId);
         if (exam == null) {
             throw new BusinessException("未找到考试信息");
         }
-        if (exam.getEnable() == null || exam.getEnable().intValue() == 0) {
+        if (exam.getEnable() == null || exam.getEnable() == 0) {
             throw new BusinessException("考试批次已禁用");
         }
         if (!InvigilateMonitorStatusEnum.FINISHED.equals(exam.getMonitorStatus())) {
             throw new BusinessException("考试批次监考未结束");
         }
-        List<TEExamCourse> courses = examCourseService.findByExamId(examId);
-        if (courses == null || courses.size() == 0) {
-            throw new BusinessException("考试批次下没有课程");
-        }
-        for (TEExamCourse course : courses) {
-            if (course.getHasAnswer() == null || course.getHasAnswer().intValue() == 0) {
-                throw new BusinessException("考试批次下标答未齐全");
-            }
-        }
+        return exam;
+        //        List<TEExamCourse> courses = examCourseService.findByExamId(examId);
+        //        if (courses == null || courses.size() == 0) {
+        //            throw new BusinessException("考试批次下没有课程");
+        //        }
+        //        for (TEExamCourse course : courses) {
+        //            if (course.getHasAnswer() == null || course.getHasAnswer().intValue() == 0) {
+        //                throw new BusinessException("考试批次下标答未齐全");
+        //            }
+        //        }
     }
 
     @Override
     public JSONArray examRecordNeedMark(Long examId, String courseCode, Long idGt, Integer count) {
-        checkExam(examId);
-        List<OpenRecordNeedMarkBean> list;
-        for (; ; ) {
-            List<Long> examStudentIds = examStudentService.findExamStudentIdsNeedMark(examId, courseCode, idGt, count);
-            if (examStudentIds == null || examStudentIds.size() == 0) {
-                return null;
-            }
-            list = findExamRecordNeedMark(examId, examStudentIds);
-            if (list == null || list.size() == 0) {
-                idGt = examStudentIds.get(examStudentIds.size() - 1);
-            } else {
-                break;
-            }
-        }
-        List<Long> ids = list.stream().map(dto -> dto.getExamRecordId()).collect(Collectors.toList());
-        List<OpenRecordAnswerBean> answers = examAnswerService.findByRecordIds(ids);
-        if (answers != null && answers.size() > 0) {
-            for (int i = 0; i < answers.size(); i++) {//剔除客观题答案
-                OpenRecordAnswerBean answer = answers.get(i);
-                Map<String, Integer> struct = examPaperService.getPaperStructCacheBean(answer.getPaperId());
-                Integer type = struct.get(RedisKeyHelper
-                        .examAnswerHashKey(answer.getMainNumber(), answer.getSubNumber(), answer.getSubIndex()));
-                if (type == 1 || type == 2 || type == 3) {
-                    answers.remove(i);
-                    i--;
-                }
-            }
-        }
-        if (answers != null && answers.size() > 0) {
-            Map<Long, Integer> map = new HashMap<>();
-            for (int i = 0; i < list.size(); i++) {
-                map.put(list.get(i).getExamRecordId(), i);
-            }
-            for (OpenRecordAnswerBean anwser : answers) {
-                OpenRecordNeedMarkBean mark = list.get(map.get(anwser.getRecordId()));
-                List<OpenRecordAnswerBean> ans = mark.getAnswers();
-                if (ans == null) {
-                    ans = new ArrayList<OpenRecordAnswerBean>();
-                    mark.setAnswers(ans);
-                }
-                ans.add(anwser);
-            }
-        }
-        JSONArray ja = JSONArray.parseArray(JSONArray.toJSONString(list));
-        for (int i = 0; i < ja.size(); i++) {
-            JSONObject job = ja.getJSONObject(i);
-            JSONArray answersJa = job.getJSONArray("answers");
-            if (answersJa != null) {
-                for (int j = 0; j < answersJa.size(); j++) {
-                    JSONObject answersJob = answersJa.getJSONObject(j);
-                    answersJob.remove("recordId");
-                    answersJob.remove("paperId");
-                    String answerStr = answersJob.getString("answer");
-                    if (StringUtils.isNotBlank(answerStr)) {
-                        if (answerStr.toLowerCase().startsWith("true") || answerStr.toLowerCase().startsWith("false")) {
-                            answersJob.put("answer", Boolean.getBoolean(answerStr.replaceAll("\n", "")));
-                        } else {
-                            answersJob.put("answer", answersJob.getJSONArray("answer"));
+        JSONArray result = new JSONArray();
+        TEExam exam = checkExam(examId);
+        Map<Long, ExamPaperCacheBean> paperMap = new HashMap<>();
+        final Map<Long, Map<String, Integer>> paperStructMap = new HashMap<>();
+        //查询需要参与评卷的考生
+        List<TEExamStudentDto> examStudents = examStudentService
+                .findExamStudentNeedMark(examId, courseCode, idGt, count);
+        if (examStudents != null) {
+            for (TEExamStudentDto examStudent : examStudents) {
+                JSONObject obj = new JSONObject();
+                obj.put("id", examStudent.getId());
+                obj.put("identity", examStudent.getIdentity());
+                obj.put("name", examStudent.getName());
+                obj.put("activityCode", examStudent.getActivityCode());
+                obj.put("courseCode", examStudent.getCourseCode());
+                obj.put("courseName", examStudent.getCourseName());
+                //查询需要主观题评卷的考试记录
+                List<OpenRecordNeedMarkBean> recordList = findExamRecordNeedMark(examStudent.getId(), paperMap,
+                        exam.getRecordSelectStrategy());
+                for (OpenRecordNeedMarkBean record : recordList) {
+                    //查询所有单题作答结果
+                    List<OpenRecordAnswerBean> answers = examAnswerService.findByExamRecordId(record.getId());
+                    record.setAnswers(answers.stream().filter(answer -> {
+                        Map<String, Integer> struct = paperStructMap.get(record.getPaperId());
+                        if (struct == null) {
+                            struct = examPaperService.getPaperStructCacheBean(record.getPaperId());
+                            if (struct != null) {
+                                paperStructMap.put(record.getPaperId(), struct);
+                            } else {
+                                log.error("找不到对应的试卷结构,paperId=" + record.getPaperId());
+                                return false;
+                            }
                         }
-                    }
+                        Integer type = struct.get(RedisKeyHelper
+                                .examAnswerHashKey(answer.getMainNumber(), answer.getSubNumber(),
+                                        answer.getSubIndex()));
+                        //过滤单选、多选、判断题
+                        return type != null && type != 1 && type != 2 && type != 3;
+                    }).collect(Collectors.toList()));
                 }
+                obj.put("records", recordList);
+                result.add(obj);
             }
         }
-        return ja;
+        paperMap.clear();
+        paperStructMap.clear();
+        return result;
     }
 
-    private List<OpenRecordNeedMarkBean> findExamRecordNeedMark(Long examId, List<Long> examStudentIds) {
-        List<OpenRecordNeedMarkBean> list = examRecordService.findExamRecordNeedMark(examId, examStudentIds);
-        if (list == null || list.size() == 0) {
-            return null;
+    private List<OpenRecordNeedMarkBean> findExamRecordNeedMark(Long examStudentId,
+                                                                Map<Long, ExamPaperCacheBean> paperMap, RecordSelectStrategyEnum strategy) {
+        List<OpenRecordNeedMarkBean> list = examRecordService.findExamRecordNeedMark(examStudentId);
+        List<OpenRecordNeedMarkBean> result = new ArrayList<>();
+        if (list == null) {
+            return result;
         }
-        for (int i = 0; i < list.size(); i++) {//剔除没有主观题的试卷考试记录
-            ExamPaperCacheBean paper = examPaperService.getExamPaperCacheBean(list.get(i).getPaperId());
-            if (paper.getTotalSubjectiveScore() == 0) {
-                list.remove(i);
-                i--;
-            }
-        }
-        if (list == null || list.size() == 0) {
-            return null;
-        }
-        TEExam exam = examService.getById(examId);
-        if (RecordSelectStrategyEnum.HIGHEST_TOTAL_SCORE.equals(exam.getRecordSelectStrategy())) {//全阅
-            return list;
-        } else if (RecordSelectStrategyEnum.HIGHEST_OBJECTIVE_SCORE
-                .equals(exam.getRecordSelectStrategy())) {//客观分最高,相同则都阅
-            Map<Long, List<OpenRecordNeedMarkBean>> map = new HashMap<>();
-            for (OpenRecordNeedMarkBean bean : list) {
-                List<OpenRecordNeedMarkBean> temList = map.get(bean.getExamStudentId());
-                if (temList == null) {
-                    temList = new ArrayList<OpenRecordNeedMarkBean>();
-                    temList.add(bean);
-                    map.put(bean.getExamStudentId(), temList);
+        double highestObjectiveScore = 0.0;
+        long maxFinishTime = 0L;
+        for (OpenRecordNeedMarkBean bean : list) {
+            //获取对应的试卷信息
+            ExamPaperCacheBean paper = paperMap.get(bean.getPaperId());
+            if (paper == null) {
+                paper = examPaperService.getExamPaperCacheBean(bean.getPaperId());
+                if (paper == null) {
+                    log.error("找不到对应的试卷信息, paperId=" + bean.getPaperId());
+                    continue;
                 } else {
-                    if (temList.get(0).getObjectiveScore().doubleValue() == bean.getObjectiveScore().doubleValue()) {
-                        temList.add(bean);
-                    } else if (temList.get(0).getObjectiveScore() < bean.getObjectiveScore()) {
-                        temList = new ArrayList<OpenRecordNeedMarkBean>();
-                        temList.add(bean);
-                        map.put(bean.getExamStudentId(), temList);
-                    }
-                }
-            }
-            List<OpenRecordNeedMarkBean> ret = new ArrayList<OpenRecordNeedMarkBean>();
-            for (List<OpenRecordNeedMarkBean> tem : map.values()) {
-                for (OpenRecordNeedMarkBean bean : tem) {
-                    ret.add(bean);
+                    paperMap.put(bean.getPaperId(), paper);
                 }
             }
-            Collections.sort(ret, new Comparator<OpenRecordNeedMarkBean>() {
-
-                @Override
-                public int compare(OpenRecordNeedMarkBean o1, OpenRecordNeedMarkBean o2) {
-                    Long c1 = o1.getExamStudentId();
-                    Long c2 = o2.getExamStudentId();
-                    if (c1 > c2) {
-                        return 1;
-                    } else if (c1 < c2) {
-                        return -1;
-                    } else {
-                        return 0;
-                    }
-                }
-
-            });
-            return ret;
-        } else if (RecordSelectStrategyEnum.LATEST.equals(exam.getRecordSelectStrategy())) {//最后一次提交
-            Map<Long, OpenRecordNeedMarkBean> map = new HashMap<>();
-            for (OpenRecordNeedMarkBean bean : list) {
-                OpenRecordNeedMarkBean old = map.get(bean.getExamStudentId());
-                if (old == null || old.getFinishTime() < bean.getFinishTime()) {
-                    map.put(bean.getExamStudentId(), bean);
-                }
+            //根据试卷结构过滤没有主观题的情况
+            if (paper.getTotalSubjectiveScore() == 0) {
+                continue;
             }
-            List<OpenRecordNeedMarkBean> ret = map.values().stream().collect(Collectors.toList());
-            Collections.sort(ret, new Comparator<OpenRecordNeedMarkBean>() {
-
-                @Override
-                public int compare(OpenRecordNeedMarkBean o1, OpenRecordNeedMarkBean o2) {
-                    Long c1 = o1.getExamStudentId();
-                    Long c2 = o2.getExamStudentId();
-                    if (c1 > c2) {
-                        return 1;
-                    } else if (c1 < c2) {
-                        return -1;
-                    } else {
-                        return 0;
-                    }
-                }
-
-            });
-            return ret;
-        } else {
-            throw new BusinessException("考试批次阅卷类型未定义");
+            highestObjectiveScore = Math.max(highestObjectiveScore, bean.getObjectiveScore());
+            maxFinishTime = Math.max(maxFinishTime, bean.getFinishTime());
+            result.add(bean);
+        }
+        if (result.isEmpty()) {
+            return result;
+        }
+        switch (strategy) {
+            case HIGHEST_OBJECTIVE_SCORE:
+                //客观分最高,客观分相同则全部提交阅卷
+                final double score = highestObjectiveScore;
+                return result.stream().filter(bean -> bean.getObjectiveScore() == score).collect(Collectors.toList());
+            case LATEST:
+                //最后一次提交
+                final long time = maxFinishTime;
+                return result.stream().filter(bean -> bean.getFinishTime() == time).collect(Collectors.toList());
+            default:
+                //总分最高,全部提交阅卷
+                return result;
         }
     }
 }
+
+

+ 2 - 3
themis-business/src/main/java/com/qmth/themis/business/service/impl/TOeExamAnswerServiceImpl.java

@@ -26,8 +26,7 @@ public class TOeExamAnswerServiceImpl extends ServiceImpl<TOeExamAnswerMapper, T
 	TOeExamAnswerMapper examAnswerMapper;
 	
 	@Override
-	public List<OpenRecordAnswerBean> findByRecordIds(List<Long> ids) {
-		return examAnswerMapper.findByRecordIds(ids);
+	public List<OpenRecordAnswerBean> findByExamRecordId(Long examRecordId) {
+		return examAnswerMapper.findByExamRecordId(examRecordId);
 	}
-
 }

+ 2 - 2
themis-business/src/main/java/com/qmth/themis/business/service/impl/TOeExamRecordServiceImpl.java

@@ -914,8 +914,8 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
     }
 
     @Override
-    public List<OpenRecordNeedMarkBean> findExamRecordNeedMark(Long examId, List<Long> examStudentIds) {
-        return tOeExamRecordMapper.findExamRecordNeedMark(examId, examStudentIds);
+    public List<OpenRecordNeedMarkBean> findExamRecordNeedMark(Long examStudentId) {
+        return tOeExamRecordMapper.findExamRecordNeedMark(examStudentId);
     }
 
     /**

+ 6 - 7
themis-business/src/main/java/com/qmth/themis/business/util/AuthUtil.java

@@ -51,7 +51,7 @@ public class AuthUtil {
     public static boolean adminAuthInterceptor(Platform platform,
                                                String deviceId,
                                                String authorization,
-                                               String time,
+                                               long time,
                                                List<String> sysUrls,
                                                HttpServletRequest request,
                                                HttpServletResponse response) {
@@ -86,7 +86,7 @@ public class AuthUtil {
     public static boolean examAuthInterceptor(Platform platform,
                                               String deviceId,
                                               String authorization,
-                                              String time,
+                                              long time,
                                               List<String> sysUrls,
                                               HttpServletRequest request,
                                               HttpServletResponse response) {
@@ -122,7 +122,7 @@ public class AuthUtil {
     public static TBSession websocketAuthInterceptor(Platform platform,
                                                      String deviceId,
                                                      String authorization,
-                                                     String time,
+                                                     long time,
                                                      String method,
                                                      String url) {
         RedisUtil redisUtil = SpringContextHolder.getBean(RedisUtil.class);
@@ -143,18 +143,17 @@ public class AuthUtil {
                                     Platform platform,
                                     String deviceId,
                                     String authorization,
-                                    String time,
+                                    long time,
                                     String method,
                                     String url) {
-        long timestamp = StringUtils.isNumeric(time) ? Long.parseLong(time) : 0L;
-        if (SystemConstant.expire(timestamp)) {
+        if (SystemConstant.expire(time)) {
             log.warn("Authorization faile: time expired, server time=" + System.currentTimeMillis());
             throw new BusinessException(ExceptionResultEnum.AUTHORIZATION_ERROR);
         }
         //测试
 //        final SignatureInfo info = SignatureInfo.parse(authorization);
         //校验签名信息
-        final SignatureInfo info = SignatureInfo.parse(method.toLowerCase(), url, timestamp, authorization);
+        final SignatureInfo info = SignatureInfo.parse(method.toLowerCase(), url, time, authorization);
         if (info == null) {
             log.warn("Authorization faile: signature decode error");
             throw new BusinessException(ExceptionResultEnum.AUTHORIZATION_ERROR);

+ 19 - 9
themis-business/src/main/java/com/qmth/themis/business/util/ServletUtil.java

@@ -3,9 +3,11 @@ package com.qmth.themis.business.util;
 import com.qmth.themis.business.constant.SystemConstant;
 import com.qmth.themis.common.contanst.Constants;
 import com.qmth.themis.common.enums.ExceptionResultEnum;
+import com.qmth.themis.common.enums.Platform;
 import com.qmth.themis.common.exception.BusinessException;
 import com.qmth.themis.common.util.Result;
 import com.qmth.themis.common.util.ResultUtil;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.web.context.request.RequestContextHolder;
 import org.springframework.web.context.request.ServletRequestAttributes;
 
@@ -57,17 +59,21 @@ public class ServletUtil {
      *
      * @return
      */
-    public static String getRequestPlatform() {
+    public static Platform getRequestPlatform() {
         HttpServletRequest request = getRequest();
         // 从header中获取platform
-        String platform = request.getHeader(Constants.HEADER_PLATFORM);
+        String value = request.getHeader(Constants.HEADER_PLATFORM);
         // 如果header中不存在platform,则从参数中获取platform
-        if (Objects.isNull(platform)) {
-            platform = request.getParameter(Constants.HEADER_PLATFORM);
-            if (Objects.isNull(platform)) {
+        if (Objects.isNull(value)) {
+            value = request.getParameter(Constants.HEADER_PLATFORM);
+            if (Objects.isNull(value)) {
                 throw new BusinessException(ExceptionResultEnum.PLATFORM_INVALID);
             }
         }
+        Platform platform = Platform.findByName(value);
+        if (platform == null) {
+            throw new BusinessException(ExceptionResultEnum.PLATFORM_INVALID);
+        }
         return platform;
     }
 
@@ -79,10 +85,10 @@ public class ServletUtil {
     public static String getRequestDeviceId() {
         HttpServletRequest request = getRequest();
         // 从header中获取deviceId
-        String deviceId = request.getHeader(Constants.HEADER_DEVICE_ID);
+        String deviceId = StringUtils.trimToNull(request.getHeader(Constants.HEADER_DEVICE_ID));
         // 如果header中不存在deviceId,则从参数中获取deviceId
         if (Objects.isNull(deviceId)) {
-            deviceId = request.getParameter(Constants.HEADER_DEVICE_ID);
+            deviceId = StringUtils.trimToNull(request.getParameter(Constants.HEADER_DEVICE_ID));
             if (Objects.isNull(deviceId)) {
                 throw new BusinessException(ExceptionResultEnum.DEVICE_ID_INVALID);
             }
@@ -95,7 +101,7 @@ public class ServletUtil {
      *
      * @return
      */
-    public static String getRequestTime() {
+    public static long getRequestTime() {
         HttpServletRequest request = getRequest();
         // 从header中获取time
         String time = request.getHeader(Constants.HEADER_TIME);
@@ -106,7 +112,11 @@ public class ServletUtil {
                 throw new BusinessException(ExceptionResultEnum.TIME_INVALID);
             }
         }
-        return time;
+        try {
+            return Long.parseLong(time);
+        } catch (Exception e) {
+            throw new BusinessException(ExceptionResultEnum.TIME_INVALID);
+        }
     }
 
     /**

+ 24 - 8
themis-business/src/main/resources/mapper/TEExamStudentMapper.xml

@@ -362,14 +362,30 @@
 	<select id="markResultQueryExport" resultType="com.qmth.themis.business.dto.MarkResultSimpleExportDto">
 		<include refid="markResultCommon" />
 	</select>
-	
-	<select id="findExamStudentIdsNeedMark" resultType="java.lang.Long">
-		select t.id from t_e_exam_student t
-		where t.exam_id=#{examId} and t.id&gt;#{idGt}
-		<if test="courseCode != null and courseCode != ''">
-			and t.course_code=#{courseCode}
-		</if>
-		order by t.id
+
+	<select id="findExamStudentNeedMark" resultType="com.qmth.themis.business.dto.response.TEExamStudentDto">
+		select
+		tees.id,
+		tees.name,
+		tees.`identity`,
+		tees.course_code as courseCode,
+		tees.course_name as courseName,
+		teea.code as activityCode
+		from t_e_exam_student tees
+		inner join t_e_exam_activity teea
+		on tees.exam_activity_id = teea.id
+		and teea.enable = 1
+		<where>
+			tees.exam_id = #{examId}
+			and tees.enable = 1
+			and tees.id <![CDATA[ > ]]> #{idGt}
+			and tees.already_exam_count is not null
+			and tees.already_exam_count <![CDATA[ > ]]> 0
+			<if test="courseCode != null and courseCode != ''">
+				and tees.course_code = #{courseCode}
+			</if>
+		</where>
+		order by tees.id
 		limit #{count}
 	</select>
 </mapper>

+ 10 - 19
themis-business/src/main/resources/mapper/TOeExamAnswerMapper.xml

@@ -3,23 +3,14 @@
 <mapper
 	namespace="com.qmth.themis.business.dao.TOeExamAnswerMapper">
 
-	<select id="findByRecordIds"
-		resultType="com.qmth.themis.business.bean.admin.OpenRecordAnswerBean">
-		SELECT
-		t.exam_record_id recordId,
-		t.main_number mainNumber,
-		t.sub_number
-		subNumber,
-		t.sub_index subIndex,
-		t.answer,
-		f.paper_id paperId
-		FROM
-		t_oe_exam_answer t left join t_oe_exam_record f on t.exam_record_id=f.id
-		WHERE t.exam_record_id in
-		<foreach collection="ids" item="rid"
-			index="index" open="(" close=")" separator=",">
-			#{rid}
-		</foreach>
-		order by t.id
-	</select>
+	<select id="findByExamRecordId"
+			resultType="com.qmth.themis.business.bean.admin.OpenRecordAnswerBean">
+        SELECT t.main_number as mainNumber,
+               t.sub_number  as subNumber,
+               t.sub_index   as subIndex,
+               t.answer      as answer
+        FROM t_oe_exam_answer t
+        WHERE t.exam_record_id = #{examRecordId}
+        order by t.main_number, t.sub_number, t.sub_index
+    </select>
 </mapper>

+ 9 - 21
themis-business/src/main/resources/mapper/TOeExamRecordMapper.xml

@@ -832,27 +832,15 @@
 	</update>
 
 	<select id="findExamRecordNeedMark" resultType="com.qmth.themis.business.bean.admin.OpenRecordNeedMarkBean">
-		SELECT
-		t.id examRecordId,
-		t.exam_student_id examStudentId,
-		f.identity,
-		f.NAME,
-		g.CODE activityCode,
-		f.course_code courseCode,
-		f.course_name courseName,
-		t.paper_id paperId,
-		t.objective_score objectiveScore,
-		t.finish_time finishTime
-		FROM
-		t_oe_exam_record t
-		LEFT JOIN t_e_exam_student f ON t.exam_student_id = f.id
-		LEFT JOIN t_e_exam_activity g ON t.exam_activity_id = g.id
-		where t.exam_id=#{examId} and t.breach_status!=1 and t.exam_student_id in
-		<foreach collection="examStudentIds" item="examStudentId"
-			index="index" open="(" close=")" separator=",">
-			#{examStudentId}
-		</foreach>
-	</select>
+        SELECT t.id              as id,
+               t.paper_id        as paperId,
+               t.objective_score as objectiveScore,
+               t.finish_time     as finishTime
+        FROM t_oe_exam_record t
+        where t.exam_student_id = #{examStudentId}
+          and t.finish_time is not null
+          and (t.breach_status is null or t.breach_status != 1)
+    </select>
 
 	<select id="findMaxObjectiveScore" resultType="com.qmth.themis.business.entity.TOeExamRecord">
 		select

+ 1 - 1
themis-exam/src/main/java/com/qmth/themis/exam/api/TEStudentController.java

@@ -197,7 +197,7 @@ public class TEStudentController {
         if (teStudent.getEnable().intValue() == 0) {
             throw new BusinessException(ExceptionResultEnum.STUDENT_ENABLE);
         }
-        Platform platform = Platform.valueOf(ServletUtil.getRequestPlatform());
+        Platform platform = ServletUtil.getRequestPlatform();
         String deviceId = ServletUtil.getRequestDeviceId();
         //添加用户鉴权缓存
         AuthDto authDto = cacheService.addStudentCache(teStudent.getId());

+ 2 - 2
themis-exam/src/main/java/com/qmth/themis/exam/interceptor/AuthInterceptor.java

@@ -37,10 +37,10 @@ public class AuthInterceptor implements HandlerInterceptor {
         if (url.equalsIgnoreCase(SystemConstant.ERROR)) {
             throw new BusinessException(ExceptionResultEnum.NOT_FOUND);
         }
-        Platform platform = Platform.valueOf(ServletUtil.getRequestPlatform());
+        Platform platform = ServletUtil.getRequestPlatform();
         String deviceId = ServletUtil.getRequestDeviceId();
         String authorization = ServletUtil.getRequestAuthorization();
-        String time = ServletUtil.getRequestTime();
+        long time = ServletUtil.getRequestTime();
         log.info("Start authorization: url:{}, method:{}, platform:{}, deviceId:{}, authorization:{}, time:{}", url,
                 method, platform, deviceId, authorization, time);
         return AuthUtil.examAuthInterceptor(platform, deviceId, authorization, time, dictionaryConfig.systemUrlDomain().getUrls(), request, response);

+ 1 - 1
themis-exam/src/main/java/com/qmth/themis/exam/websocket/WebSocketMobileServer.java

@@ -86,7 +86,7 @@ public class WebSocketMobileServer implements Concurrently {
         this.source = MonitorVideoSourceEnum.valueOf(mapParameter.get(Constants.HEADER_SOURCE).get(0));
 
         this.redisUtil = SpringContextHolder.getBean(RedisUtil.class);
-        TBSession tbSession = AuthUtil.websocketAuthInterceptor(Platform.valueOf(platform), deviceId, authorization, String.valueOf(mapParameter.get(Constants.HEADER_TIME).get(0)), SystemConstant.GET, url);
+        TBSession tbSession = AuthUtil.websocketAuthInterceptor(Platform.valueOf(platform), deviceId, authorization, Long.parseLong(mapParameter.get(Constants.HEADER_TIME).get(0)), SystemConstant.GET, url);
         WebsocketUtil.checkExamStatus(this.recordId);
         this.session = session;
         session.setMaxIdleTimeout(SystemConstant.WEBSOCKET_MAX_TIME_OUT);

+ 1 - 1
themis-exam/src/main/java/com/qmth/themis/exam/websocket/WebSocketOeServer.java

@@ -83,7 +83,7 @@ public class WebSocketOeServer implements Concurrently {
         this.recordId = Long.parseLong(String.valueOf(mapParameter.get(Constants.HEADER_RECORD_ID).get(0)));
         redisUtil = SpringContextHolder.getBean(RedisUtil.class);
 
-        TBSession tbSession = AuthUtil.websocketAuthInterceptor(Platform.valueOf(platform), deviceId, authorization, String.valueOf(mapParameter.get(Constants.HEADER_TIME).get(0)), SystemConstant.GET, url);
+        TBSession tbSession = AuthUtil.websocketAuthInterceptor(Platform.valueOf(platform), deviceId, authorization, Long.parseLong(mapParameter.get(Constants.HEADER_TIME).get(0)), SystemConstant.GET, url);
         WebsocketUtil.checkExamStatus(this.recordId);
         this.session = session;
         session.setMaxIdleTimeout(SystemConstant.WEBSOCKET_MAX_TIME_OUT);