Ver Fonte

Merge branch 'dev'
111

wangliang há 4 anos atrás
pai
commit
9b615c499a
16 ficheiros alterados com 540 adições e 140 exclusões
  1. 15 0
      themis-backend/src/main/java/com/qmth/themis/backend/api/TBUserController.java
  2. 8 3
      themis-backend/src/main/java/com/qmth/themis/backend/api/TEExamActivityController.java
  3. 12 3
      themis-backend/src/main/java/com/qmth/themis/backend/api/TEExamController.java
  4. 1 1
      themis-backend/src/main/java/com/qmth/themis/backend/api/TEStudentController.java
  5. 21 0
      themis-backend/src/main/java/com/qmth/themis/backend/api/TIeReportController.java
  6. 54 0
      themis-business/src/main/java/com/qmth/themis/business/bean/backend/ExamExceptionDetailListBean.java
  7. 148 0
      themis-business/src/main/java/com/qmth/themis/business/bean/backend/ExamExceptionListBean.java
  8. 1 1
      themis-business/src/main/java/com/qmth/themis/business/constant/SystemConstant.java
  9. 1 0
      themis-business/src/main/java/com/qmth/themis/business/dao/TEExamStudentMapper.java
  10. 13 2
      themis-business/src/main/java/com/qmth/themis/business/dao/TIeInvigilateExceptionInfoMapper.java
  11. 2 2
      themis-business/src/main/java/com/qmth/themis/business/entity/TEExam.java
  12. 7 0
      themis-business/src/main/java/com/qmth/themis/business/service/TIeReportService.java
  13. 37 0
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TIeReportServiceImpl.java
  14. 24 2
      themis-business/src/main/java/com/qmth/themis/business/util/RedisUtil.java
  15. 139 125
      themis-business/src/main/resources/mapper/TEExamStudentMapper.xml
  16. 57 1
      themis-business/src/main/resources/mapper/TIeInvigilateExceptionInfoMapper.xml

+ 15 - 0
themis-backend/src/main/java/com/qmth/themis/backend/api/TBUserController.java

@@ -586,6 +586,9 @@ public class TBUserController {
             if (Objects.nonNull(roleList) && roleList.size() > 0) {
                 roleSet = new HashSet<>(roleList);
             }
+            if (Objects.nonNull(roleSet) && roleSet.size() > 1) {
+                throw new BusinessException("暂不支持多个角色");
+            }
             if (Objects.isNull(tbUser.getId())) {
                 tbUser.setId(Constants.idGen.next());
                 tbUser.setOrgId(orgId);
@@ -611,6 +614,18 @@ public class TBUserController {
                 tbUser.setUpdateId(loginUser.getId());
             }
             tbUserService.saveOrUpdate(tbUser);
+            //清除用户缓存
+            if (Objects.nonNull(roleSet) && roleSet.size() > 0) {
+                AuthDto authDto = (AuthDto) redisUtil.get(SystemConstant.userOauth + "::" + tbUser.getId());
+                if (Objects.nonNull(authDto)) {
+                    for (Source s : Source.values()) {
+                        String sessionId = SessionUtil.digest(tbUser.getId(), Math.abs(authDto.getRoleCodes().toString().hashCode()), s.name());
+                        redisUtil.deleteUserSession(sessionId);
+                    }
+                }
+                redisUtil.deleteUser(tbUser.getId());
+                cacheService.removeAccountCache(tbUser.getId());
+            }
         } catch (Exception e) {
             e.printStackTrace();
             if (e instanceof DuplicateKeyException) {

+ 8 - 3
themis-backend/src/main/java/com/qmth/themis/backend/api/TEExamActivityController.java

@@ -63,6 +63,7 @@ public class TEExamActivityController {
         if (Objects.isNull(teExamActivityList) || teExamActivityList.size() == 0) {
             throw new BusinessException(ExceptionResultEnum.EXAM_INFO_IS_NULL);
         }
+        Long examId = null;
         try {
             TBUser tbUser = (TBUser) ServletUtil.getRequestAccount();
             teExamActivityList.forEach(s -> {
@@ -71,9 +72,10 @@ public class TEExamActivityController {
                 } else {
                     s.setId(Constants.idGen.next());
                     s.setCreateId(tbUser.getId());
-                    s.setCode(String.valueOf(redisUtil.getRedisActivityCodeSequence()));
+                    s.setCode(String.valueOf(redisUtil.getRedisActivityCodeSequence(s.getExamId())));
                 }
             });
+            examId = teExamActivityList.get(0).getExamId();
             teExamActivityService.saveOrUpdateBatch(teExamActivityList);
             TEExam teExam = teExamService.getById(teExamActivityList.get(0).getExamId());
             //新增quartz任务,发送mq消息start
@@ -90,6 +92,9 @@ public class TEExamActivityController {
             });
         } catch (Exception e) {
             e.printStackTrace();
+            if (Objects.nonNull(examId) && Objects.nonNull(teExamActivityList) && (Objects.nonNull(teExamActivityList) && teExamActivityList.size() > 0 && Objects.nonNull(teExamActivityList.get(0)))) {
+                redisUtil.setRedisActivityCodeSequence(examId, Integer.parseInt(teExamActivityList.get(0).getCode()) - 1);
+            }
             if (e instanceof DuplicateKeyException) {
                 String errorColumn = e.getCause().toString();
                 String columnStr = errorColumn.substring(errorColumn.lastIndexOf("key") + 3, errorColumn.length()).replaceAll("'", "");
@@ -106,8 +111,8 @@ public class TEExamActivityController {
     @ApiOperation(value = "考试场次查询接口")
     @RequestMapping(value = "/query", method = RequestMethod.POST)
     @ApiResponses({@ApiResponse(code = 200, message = "考试场次信息", response = TEExamActivity.class)})
-    public Result query(@ApiParam(value = "主键", required = false) @RequestParam(required = false) Long id,@ApiParam(value = "考试批次id", required = false) @RequestParam(required = false) Long examId, @ApiParam(value = "考试场次编码", required = false) @RequestParam(required = false) String code, @ApiParam(value = "开始日期", required = false) @RequestParam(required = false) String startDate, @ApiParam(value = "结束日期", required = false) @RequestParam(required = false) String finishDate, @ApiParam(value = "分页页码", required = true) @RequestParam int pageNumber, @ApiParam(value = "分页数", required = true) @RequestParam int pageSize) {
-        IPage<TEExamActivityQueryDto> teExamActivityIPage = teExamActivityService.examActivityQuery(new Page<>(pageNumber, pageSize), id,examId, code, startDate, finishDate);
+    public Result query(@ApiParam(value = "主键", required = false) @RequestParam(required = false) Long id, @ApiParam(value = "考试批次id", required = false) @RequestParam(required = false) Long examId, @ApiParam(value = "考试场次编码", required = false) @RequestParam(required = false) String code, @ApiParam(value = "开始日期", required = false) @RequestParam(required = false) String startDate, @ApiParam(value = "结束日期", required = false) @RequestParam(required = false) String finishDate, @ApiParam(value = "分页页码", required = true) @RequestParam int pageNumber, @ApiParam(value = "分页数", required = true) @RequestParam int pageSize) {
+        IPage<TEExamActivityQueryDto> teExamActivityIPage = teExamActivityService.examActivityQuery(new Page<>(pageNumber, pageSize), id, examId, code, startDate, finishDate);
         BasePage basePage = new BasePage(teExamActivityIPage.getRecords(), teExamActivityIPage.getCurrent(), teExamActivityIPage.getSize(), teExamActivityIPage.getTotal());
         return ResultUtil.ok(basePage);
     }

+ 12 - 3
themis-backend/src/main/java/com/qmth/themis/backend/api/TEExamController.java

@@ -87,6 +87,7 @@ public class TEExamController {
         }
         TEExam teExam = null;
         Long oldId = null;
+        String activityCode = null;
         try {
             TBUser tbUser = (TBUser) ServletUtil.getRequestAccount();
             TBOrg tbOrg = (TBOrg) ServletUtil.getRequestOrg();
@@ -153,7 +154,8 @@ public class TEExamController {
                     });
                 } else {
                     TEExamActivity teExamActivity = new TEExamActivity(teExam.getId(), teExam.getPrepareSeconds(), teExam.getMaxDurationSeconds(), teExam.getOpeningSeconds(), teExam.getStartTime(), teExam.getEndTime(), tbUser.getId());
-                    teExamActivity.setCode(String.valueOf(redisUtil.getRedisActivityCodeSequence()));
+                    teExamActivity.setCode(String.valueOf(redisUtil.getRedisActivityCodeSequence(teExam.getId())));
+                    activityCode = teExamActivity.getCode();
                     teExamActivity.setEnable(1);
                     teExamActivityService.saveOrUpdate(teExamActivity);
 
@@ -169,6 +171,9 @@ public class TEExamController {
             }
         } catch (Exception e) {
             e.printStackTrace();
+            if (Objects.nonNull(teExam) && Objects.nonNull(teExam.getId()) && Objects.nonNull(activityCode)) {
+                redisUtil.setRedisActivityCodeSequence(teExam.getId(), Integer.parseInt(activityCode) - 1);
+            }
             if (e instanceof DuplicateKeyException) {
                 String errorColumn = e.getCause().toString();
                 String columnStr = errorColumn.substring(errorColumn.lastIndexOf("key") + 3, errorColumn.length()).replaceAll("'", "");
@@ -277,6 +282,7 @@ public class TEExamController {
         if (Objects.isNull(teExam)) {
             throw new BusinessException(ExceptionResultEnum.EXAM_NO);
         }
+        List<TEExamActivity> teExamActivityList = null;
         try {
             teExam.setId(null);
             teExam.setUpdateId(null);
@@ -289,7 +295,7 @@ public class TEExamController {
 
             QueryWrapper<TEExamActivity> teExamActivityQueryWrapper = new QueryWrapper<>();
             teExamActivityQueryWrapper.lambda().eq(TEExamActivity::getExamId, examId);
-            List<TEExamActivity> teExamActivityList = teExamActivityService.list(teExamActivityQueryWrapper);
+            teExamActivityList = teExamActivityService.list(teExamActivityQueryWrapper);
             if (Objects.nonNull(teExamActivityList)) {
                 teExamActivityList.forEach(s -> {
                     s.setId(null);
@@ -297,12 +303,15 @@ public class TEExamController {
                     s.setCreateId(teExam.getCreateId());
                     s.setUpdateId(null);
                     s.setUpdateTime(null);
-                    s.setCode(String.valueOf(redisUtil.getRedisActivityCodeSequence()));
+                    s.setCode(String.valueOf(redisUtil.getRedisActivityCodeSequence(teExam.getId())));
                 });
                 teExamActivityService.saveOrUpdateBatch(teExamActivityList);
             }
         } catch (Exception e) {
             e.printStackTrace();
+            if (Objects.nonNull(examId) && Objects.nonNull(teExam.getId()) && (Objects.nonNull(teExamActivityList) && teExamActivityList.size() > 0 && Objects.nonNull(teExamActivityList.get(0)))) {
+                redisUtil.setRedisActivityCodeSequence(examId, Integer.parseInt(teExamActivityList.get(0).getCode()) - 1);
+            }
             if (e instanceof DuplicateKeyException) {
                 String errorColumn = e.getCause().toString();
                 String columnStr = errorColumn.substring(errorColumn.lastIndexOf("key") + 3, errorColumn.length()).replaceAll("'", "");

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

@@ -141,7 +141,7 @@ public class TEStudentController {
     }
     
     @ApiOperation(value = "底照上传")
-    @RequestMapping(value = "/photo/upload", method = RequestMethod.POST)
+    @RequestMapping(value = "/base_photo/upload", method = RequestMethod.POST)
     @ApiResponses({@ApiResponse(code = 200, message = "结果信息")})
     public Result photoUpload(@ApiParam(value = "证件号", required = true) @RequestParam String identity,
                              @ApiParam(value = "上传文件", required = true) @RequestParam MultipartFile file,

+ 21 - 0
themis-backend/src/main/java/com/qmth/themis/backend/api/TIeReportController.java

@@ -70,4 +70,25 @@ public class TIeReportController {
                              @ApiParam(value = "分页数", required = true) @RequestParam int pageSize) {
         return ResultUtil.ok(reportService.examDeficiencyList(examId, examActivityId, roomCode, courseCode, name, identity,pageNumber,pageSize));
     }
+    
+    @ApiOperation(value = "异常处理")
+    @RequestMapping(value = "/exam_exception_list", method = RequestMethod.POST)
+    @ApiResponses({@ApiResponse(code = 200, message = "结果信息")})
+    public Result examExceptionList(@ApiParam(value = "考试id", required = true) @RequestParam Long examId,
+                             @ApiParam(value = "考场场次id", required = false) @RequestParam Long examActivityId,
+                             @ApiParam(value = "虚拟考场代码", required = false) @RequestParam String roomCode,
+                             @ApiParam(value = "科目编码", required = false) @RequestParam String courseCode,
+                             @ApiParam(value = "姓名", required = false) @RequestParam String name,
+                             @ApiParam(value = "唯一码", required = false) @RequestParam String identity,
+                             @ApiParam(value = "分页页码", required = true) @RequestParam int pageNumber,
+                             @ApiParam(value = "分页数", required = true) @RequestParam int pageSize) {
+        return ResultUtil.ok(reportService.examExceptionList(examId, examActivityId, roomCode, courseCode, name, identity,pageNumber,pageSize));
+    }
+    
+    @ApiOperation(value = "异常处理明细")
+    @RequestMapping(value = "/exam_exception_list_detail", method = RequestMethod.POST)
+    @ApiResponses({@ApiResponse(code = 200, message = "结果信息")})
+    public Result examExceptionListDetail(@ApiParam(value = "考生id", required = true) @RequestParam Long examStudentId) {
+        return ResultUtil.ok(reportService.examExceptionDetailList(examStudentId));
+    }
 }

+ 54 - 0
themis-business/src/main/java/com/qmth/themis/business/bean/backend/ExamExceptionDetailListBean.java

@@ -0,0 +1,54 @@
+package com.qmth.themis.business.bean.backend;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+@ApiModel("报表-异常处理明细返回对象")
+public class ExamExceptionDetailListBean {
+
+	@ApiModelProperty(name = "异常开始时间")
+    private Long startTime;
+	@ApiModelProperty(name = "异常结束时间")
+    private Long endTime;
+	
+    
+    @ApiModelProperty(name = "异常原因")
+    private String reason;
+    
+    @ApiModelProperty(name = "持续时长")
+    private Long totalTime;
+
+	public Long getStartTime() {
+		return startTime;
+	}
+
+	public void setStartTime(Long startTime) {
+		this.startTime = startTime;
+	}
+
+	public Long getEndTime() {
+		return endTime;
+	}
+
+	public void setEndTime(Long endTime) {
+		this.endTime = endTime;
+	}
+
+	public String getReason() {
+		return reason;
+	}
+
+	public void setReason(String reason) {
+		this.reason = reason;
+	}
+
+	public Long getTotalTime() {
+		return totalTime;
+	}
+
+	public void setTotalTime(Long totalTime) {
+		this.totalTime = totalTime;
+	}
+
+    
+}

+ 148 - 0
themis-business/src/main/java/com/qmth/themis/business/bean/backend/ExamExceptionListBean.java

@@ -0,0 +1,148 @@
+package com.qmth.themis.business.bean.backend;
+
+import java.io.Serializable;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+@ApiModel("报表-异常处理返回对象")
+public class ExamExceptionListBean implements Serializable {
+
+
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = -1956027901114789306L;
+	@ApiModelProperty(name = "考生id")
+    private String examStudentId;
+	@ApiModelProperty(name = "考试名称")
+    private String examName;
+	
+	@ApiModelProperty(name = "考试id")
+    private Long examId;
+
+    @ApiModelProperty(name = "场次id")
+    private Long examActivityId;
+
+    @ApiModelProperty(name = "虚拟考场代码")
+    private String roomCode;
+
+    @ApiModelProperty(name = "虚拟考场名称")
+    private String roomName;
+
+    @ApiModelProperty(name = "唯一码")
+    private String identity;
+    
+    @ApiModelProperty(name = "姓名")
+    private String name;
+    
+    @ApiModelProperty(name = "科目名称")
+    private String courseCode;
+    
+    @ApiModelProperty(name = "科目编码")
+    private String courseName;
+    
+    @ApiModelProperty(name = "异常次数")
+    private Long exceptionCount;
+    
+    @ApiModelProperty(name = "累计持续时长")
+    private Long exceptionTotalTime;
+
+	public String getExamName() {
+		return examName;
+	}
+
+	public void setExamName(String examName) {
+		this.examName = examName;
+	}
+
+	public Long getExamId() {
+		return examId;
+	}
+
+	public void setExamId(Long examId) {
+		this.examId = examId;
+	}
+
+	public Long getExamActivityId() {
+		return examActivityId;
+	}
+
+	public void setExamActivityId(Long examActivityId) {
+		this.examActivityId = examActivityId;
+	}
+
+	public String getRoomCode() {
+		return roomCode;
+	}
+
+	public void setRoomCode(String roomCode) {
+		this.roomCode = roomCode;
+	}
+
+	public String getRoomName() {
+		return roomName;
+	}
+
+	public void setRoomName(String roomName) {
+		this.roomName = roomName;
+	}
+
+	public String getIdentity() {
+		return identity;
+	}
+
+	public void setIdentity(String identity) {
+		this.identity = identity;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public String getCourseCode() {
+		return courseCode;
+	}
+
+	public void setCourseCode(String courseCode) {
+		this.courseCode = courseCode;
+	}
+
+	public String getCourseName() {
+		return courseName;
+	}
+
+	public void setCourseName(String courseName) {
+		this.courseName = courseName;
+	}
+
+	public Long getExceptionCount() {
+		return exceptionCount;
+	}
+
+	public void setExceptionCount(Long exceptionCount) {
+		this.exceptionCount = exceptionCount;
+	}
+
+	public Long getExceptionTotalTime() {
+		return exceptionTotalTime;
+	}
+
+	public void setExceptionTotalTime(Long exceptionTotalTime) {
+		this.exceptionTotalTime = exceptionTotalTime;
+	}
+
+	public String getExamStudentId() {
+		return examStudentId;
+	}
+
+	public void setExamStudentId(String examStudentId) {
+		this.examStudentId = examStudentId;
+	}
+    
+    
+}

+ 1 - 1
themis-business/src/main/java/com/qmth/themis/business/constant/SystemConstant.java

@@ -89,7 +89,7 @@ public class SystemConstant {
     public static final String MONITOR_STATUS_ = "monitorStatus_";
     public static final String MONITOR_CALL_STATUS_ = "monitorCallStatus_";
     public final static String REDIS_MONITOR_SEQUENCE = "redis:seq:monitor";
-    public final static String REDIS_ACTIVITY_CODE_SEQUENCE = "redis:seq:activity:code";
+    public final static String REDIS_ACTIVITY_CODE_SEQUENCE = "redis:seq:activity:code:";
 
     /**
      * session过期时间

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

@@ -65,4 +65,5 @@ public interface TEExamStudentMapper extends BaseMapper<TEExamStudent> {
     public IPage<ExamDeficiencyListBean> getExamDeficiencyPage(IPage<ExamDeficiencyListBean> iPage, @Param("examId") Long examId,
 			@Param("activityId") Long activityId, @Param("roomCode") String roomCode,
 			@Param("courseCode") String courseCode, @Param("name") String name, @Param("identity") String identity,@Param("activityIds") List<Long> activityIds);
+
 }

+ 13 - 2
themis-business/src/main/java/com/qmth/themis/business/dao/TIeInvigilateExceptionInfoMapper.java

@@ -1,8 +1,15 @@
 package com.qmth.themis.business.dao;
 
+import java.util.List;
+
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.qmth.themis.business.bean.backend.ExamExceptionDetailListBean;
+import com.qmth.themis.business.bean.backend.ExamExceptionListBean;
 import com.qmth.themis.business.entity.TIeInvigilateExceptionInfo;
-import org.apache.ibatis.annotations.Mapper;
 
 /**
  * @Description: 监考异常信息 Mapper 接口
@@ -13,5 +20,9 @@ import org.apache.ibatis.annotations.Mapper;
  */
 @Mapper
 public interface TIeInvigilateExceptionInfoMapper extends BaseMapper<TIeInvigilateExceptionInfo> {
-
+	public IPage<ExamExceptionListBean> getExamExceptionPage(IPage<ExamExceptionListBean> iPage, @Param("examId") Long examId,
+			@Param("activityId") Long activityId, @Param("roomCode") String roomCode,
+			@Param("courseCode") String courseCode, @Param("name") String name, @Param("identity") String identity);
+	
+	public List<ExamExceptionDetailListBean> getExamExceptionDetailList(@Param("examStudentId") Long examStudentId);
 }

+ 2 - 2
themis-business/src/main/java/com/qmth/themis/business/entity/TEExam.java

@@ -75,11 +75,11 @@ public class TEExam extends BaseEntity {
     private Integer examCount;
 
     @ApiModelProperty(value = "断点失效时间(秒)")
-    @TableField(value = "break_expire_seconds")
+    @TableField(value = "break_expire_seconds", updateStrategy = FieldStrategy.IGNORED)
     private Integer breakExpireSeconds;
 
     @ApiModelProperty(value = "断点续考次数")
-    @TableField(value = "break_resume_count")
+    @TableField(value = "break_resume_count", updateStrategy = FieldStrategy.IGNORED)
     private Integer breakResumeCount;
 
     @ApiModelProperty(value = "是否允许使用摄像头拍照答题,0:不允许,1:允许")

+ 7 - 0
themis-business/src/main/java/com/qmth/themis/business/service/TIeReportService.java

@@ -1,8 +1,10 @@
 package com.qmth.themis.business.service;
 
+import java.util.List;
 import java.util.Map;
 
 import com.qmth.themis.business.base.BasePage;
+import com.qmth.themis.business.bean.backend.ExamExceptionDetailListBean;
 
 public interface TIeReportService {
 	public Map<String, Object> examView(Long examId, Long examActivityId, String roomCode, String courseCode,
@@ -13,4 +15,9 @@ public interface TIeReportService {
 
 	public BasePage examDeficiencyList(Long examId, Long examActivityId, String roomCode, String courseCode, String name,
 			String identity, int pageNumber, int pageSize);
+
+	public BasePage examExceptionList(Long examId, Long examActivityId, String roomCode, String courseCode, String name,
+			String identity, int pageNumber, int pageSize);
+
+	public List<ExamExceptionDetailListBean> examExceptionDetailList(Long examStudentId);
 }

+ 37 - 0
themis-business/src/main/java/com/qmth/themis/business/service/impl/TIeReportServiceImpl.java

@@ -18,12 +18,16 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.google.common.collect.Lists;
 import com.qmth.themis.business.base.BasePage;
 import com.qmth.themis.business.bean.backend.ExamDeficiencyListBean;
+import com.qmth.themis.business.bean.backend.ExamExceptionDetailListBean;
+import com.qmth.themis.business.bean.backend.ExamExceptionListBean;
 import com.qmth.themis.business.bean.backend.ExamViewCountListBean;
 import com.qmth.themis.business.cache.bean.ExamActivityCacheBean;
 import com.qmth.themis.business.cache.bean.ExamCacheBean;
 import com.qmth.themis.business.dao.TEExamStudentMapper;
+import com.qmth.themis.business.dao.TIeInvigilateExceptionInfoMapper;
 import com.qmth.themis.business.dao.TOeExamRecordMapper;
 import com.qmth.themis.business.entity.TEExamActivity;
+import com.qmth.themis.business.enums.ExceptionEnum;
 import com.qmth.themis.business.service.TEExamActivityService;
 import com.qmth.themis.business.service.TEExamService;
 import com.qmth.themis.business.service.TIeReportService;
@@ -42,6 +46,9 @@ public class TIeReportServiceImpl implements TIeReportService {
     
     @Resource
     TEExamService examService;
+    
+    @Resource
+    TIeInvigilateExceptionInfoMapper invigilateExceptionInfoMapper;
 
 	@Override
 	public Map<String, Object> examView(Long examId, Long examActivityId, String roomCode, String courseCode,
@@ -198,5 +205,35 @@ public class TIeReportServiceImpl implements TIeReportService {
         return basePage;
 	}
 
+	@Override
+	public BasePage examExceptionList(Long examId, Long examActivityId, String roomCode, String courseCode, String name,
+			String identity, int pageNumber, int pageSize) {
+		Page<ExamExceptionListBean> ipage=new Page<>(pageNumber, pageSize);
+		ipage.addOrder(OrderItem.asc("f.exam_student_id"));
+		IPage<ExamExceptionListBean> total = invigilateExceptionInfoMapper.getExamExceptionPage(ipage,examId, examActivityId, roomCode, courseCode,name,identity);
+        List<ExamExceptionListBean> data=total.getRecords();
+        if(data==null||data.size()==0) {
+        	BasePage basePage = new BasePage(total.getRecords(), total.getCurrent(), total.getSize(), total.getTotal());
+        	return basePage;
+        }
+        ExamCacheBean exam=examService.getExamCacheBean(examId);
+		for(ExamExceptionListBean b:data) {
+			b.setExamName(exam.getName());
+		}
+		BasePage basePage = new BasePage(total.getRecords(), total.getCurrent(), total.getSize(), total.getTotal());
+        return basePage;
+	}
+
+	@Override
+	public List<ExamExceptionDetailListBean> examExceptionDetailList(Long examStudentId) {
+		List<ExamExceptionDetailListBean> ret=invigilateExceptionInfoMapper.getExamExceptionDetailList(examStudentId);
+		if(ret!=null&&ret.size()>0) {
+			for(ExamExceptionDetailListBean b:ret) {
+				b.setReason(ExceptionEnum.valueOf(b.getReason()).getCode());
+			}
+		}
+		return ret;
+	}
+
 
 }

+ 24 - 2
themis-business/src/main/java/com/qmth/themis/business/util/RedisUtil.java

@@ -338,10 +338,32 @@ public class RedisUtil {
     /**
      * 获取redis activity code序列
      *
+     * @param key
      * @return
      */
-    public Integer getRedisActivityCodeSequence() {
-        RedisAtomicInteger entityIdCounter = new RedisAtomicInteger(SystemConstant.REDIS_ACTIVITY_CODE_SEQUENCE, redisTemplate.getConnectionFactory());
+    public Integer getRedisActivityCodeSequence(Long key) {
+        RedisAtomicInteger entityIdCounter = new RedisAtomicInteger(SystemConstant.REDIS_ACTIVITY_CODE_SEQUENCE + key, redisTemplate.getConnectionFactory());
         return entityIdCounter.incrementAndGet();
     }
+
+    /**
+     * 设置redis activity code序列
+     *
+     * @param key
+     * @param initialValue
+     * @return
+     */
+    public Integer setRedisActivityCodeSequence(Long key, int initialValue) {
+        RedisAtomicInteger entityIdCounter = new RedisAtomicInteger(SystemConstant.REDIS_ACTIVITY_CODE_SEQUENCE + key, redisTemplate.getConnectionFactory(), initialValue);
+        return entityIdCounter.get();
+    }
+
+    /**
+     * 删除redis activity code序列
+     *
+     * @param key
+     */
+    public void deleteRedisActivityCodeSequence(Long key) {
+        this.delete(SystemConstant.REDIS_ACTIVITY_CODE_SEQUENCE + key);
+    }
 }

+ 139 - 125
themis-business/src/main/resources/mapper/TEExamStudentMapper.xml

@@ -1,131 +1,144 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.qmth.themis.business.dao.TEExamStudentMapper">
+<mapper
+	namespace="com.qmth.themis.business.dao.TEExamStudentMapper">
 
-    <select id="examStudentQuery" resultType="com.qmth.themis.business.dto.response.TEExamStudentDto">
-        select
-            tees.id,
-            tee.id as examId,
-            tee.name as examName,
-            tees.name,
-            tees.`identity`,
-            teea.code,
-            teec.course_code as courseCode,
-            teec.course_name as courseName,
-            tees.enable,
-            tees.room_code as roomCode,
-            tees.room_name as roomName,
-            tees.grade,
-            tees.class_no as classNo,
-            teea.id as examActivityId,
-            teea.code as activityCode
-        from
-            t_e_exam_student tees
-        left join t_e_exam tee on
-            tees.exam_id = tee.id
-        left join t_e_exam_activity teea on
-            tees.exam_activity_id = teea.id
-        left join t_e_exam_course teec on
-            tees.course_code = teec.course_code
-        <where>
-            <if test="examId != null and examId != ''">
-                and tees.exam_id = #{examId}
-            </if>
-            <if test="activityId != null and activityId != ''">
-                and tees.exam_activity_id = #{activityId}
-            </if>
-            <if test="identity != null and identity != ''">
-                and tees.identity like concat('%', #{identity}, '%')
-            </if>
-            <if test="name != null and name != ''">
-                and tees.name like concat('%', #{name}, '%')
-            </if>
-            <if test="roomCode != null and roomCode != ''">
-                and tees.room_code like concat('%', #{roomCode}, '%')
-            </if>
-            <if test="courseCode != null and courseCode != ''">
-                and tees.course_code = #{courseCode}
-            </if>
-            <if test="enable != null and enable != '' or enable == 0">
-                and tees.enable = #{enable}
-            </if>
-            <if test="grade != null and grade != ''">
-                and tees.grade like concat('%', #{grade}, '%')
-            </if>
-            <if test="classNo != null and classNo != ''">
-                and tees.class_no like concat('%', #{classNo}, '%')
-            </if>
-        </where>
-    </select>
-    <select id="getTotalCount" resultType="java.util.Map">
-    	select t.exam_activity_id activityId,count(1) cc from t_e_exam_student t
-    	where  t.exam_id = #{examId}
-            <if test="activityId != null and activityId != ''">
-                and t.exam_activity_id = #{activityId}
-            </if>
-            <if test="roomCode != null and roomCode != ''">
-                and t.room_code =#{roomCode}
-            </if>
-            <if test="courseCode != null and courseCode != ''">
-                and t.course_code = #{courseCode}
-            </if>
-         group by t.exam_activity_id
-    </select>
-    
-    <select id="getTotalCountInfo" resultType="com.qmth.themis.business.bean.backend.ExamViewCountListBean">
-    	select t.exam_id examId,t.exam_activity_id examActivityId,t.room_code roomCode,t.room_name roomName, count(1) examTotal from t_e_exam_student t
-    	where  t.exam_id = #{examId}
-            <if test="activityId != null and activityId != ''">
-                and t.exam_activity_id = #{activityId}
-            </if>
-            <if test="roomCode != null and roomCode != ''">
-                and t.room_code =#{roomCode}
-            </if>
-            <if test="courseCode != null and courseCode != ''">
-                and t.course_code = #{courseCode}
-            </if>
-         group by t.exam_id,t.exam_activity_id, t.room_code,t.room_name
-    </select>
-    
-    <select id="getDoneCountByActivityIds" resultType="java.util.Map">
-    	select t.exam_activity_id activityId,t.room_code roomCode,count(1) cc from t_e_exam_student t
-    	where  t.exam_id = #{examId} and t.current_record_id is not null
-        <if test="activityIds != null">
-            and t.exam_activity_id in 
-            <foreach collection="activityIds" item="acid" index="index" open="(" close=")" separator=",">
-		    	#{acid}
-		   	</foreach>
-        </if>
-        group by t.exam_activity_id, t.room_code
-    </select>
-    
-    <select id="getAbsentCountByActivityIds" resultType="java.util.Map">
-    	select t.exam_activity_id activityId,t.room_code roomCode,count(1) cc from t_e_exam_student t
-    	where  t.exam_id = #{examId} and t.current_record_id is null
-        <if test="activityIds != null">
-            and t.exam_activity_id in 
-            <foreach collection="activityIds" item="acid" index="index" open="(" close=")" separator=",">
-		    	#{acid}
-		   	</foreach>
-        </if>
-        group by t.exam_activity_id, t.room_code
-    </select>
+	<select id="examStudentQuery"
+		resultType="com.qmth.themis.business.dto.response.TEExamStudentDto">
+		select
+		tees.id,
+		tee.id as examId,
+		tee.name as examName,
+		tees.name,
+		tees.`identity`,
+		teea.code,
+		teec.course_code as courseCode,
+		teec.course_name as courseName,
+		tees.enable,
+		tees.room_code as roomCode,
+		tees.room_name as roomName,
+		tees.grade,
+		tees.class_no as classNo,
+		teea.id as examActivityId,
+		teea.code as activityCode
+		from
+		t_e_exam_student tees
+		left join t_e_exam tee on
+		tees.exam_id = tee.id
+		left join t_e_exam_activity teea on
+		tees.exam_activity_id = teea.id
+		left join t_e_exam_course teec on
+		tees.course_code = teec.course_code
+		<where>
+			<if test="examId != null and examId != ''">
+				and tees.exam_id = #{examId}
+			</if>
+			<if test="activityId != null and activityId != ''">
+				and tees.exam_activity_id = #{activityId}
+			</if>
+			<if test="identity != null and identity != ''">
+				and tees.identity like concat('%', #{identity}, '%')
+			</if>
+			<if test="name != null and name != ''">
+				and tees.name like concat('%', #{name}, '%')
+			</if>
+			<if test="roomCode != null and roomCode != ''">
+				and tees.room_code like concat('%', #{roomCode}, '%')
+			</if>
+			<if test="courseCode != null and courseCode != ''">
+				and tees.course_code = #{courseCode}
+			</if>
+			<if test="enable != null and enable != '' or enable == 0">
+				and tees.enable = #{enable}
+			</if>
+			<if test="grade != null and grade != ''">
+				and tees.grade like concat('%', #{grade}, '%')
+			</if>
+			<if test="classNo != null and classNo != ''">
+				and tees.class_no like concat('%', #{classNo}, '%')
+			</if>
+		</where>
+	</select>
+	<select id="getTotalCount" resultType="java.util.Map">
+		select t.exam_activity_id activityId,count(1) cc from t_e_exam_student
+		t
+		where t.exam_id = #{examId}
+		<if test="activityId != null and activityId != ''">
+			and t.exam_activity_id = #{activityId}
+		</if>
+		<if test="roomCode != null and roomCode != ''">
+			and t.room_code =#{roomCode}
+		</if>
+		<if test="courseCode != null and courseCode != ''">
+			and t.course_code = #{courseCode}
+		</if>
+		group by t.exam_activity_id
+	</select>
+
+	<select id="getTotalCountInfo"
+		resultType="com.qmth.themis.business.bean.backend.ExamViewCountListBean">
+		select t.exam_id examId,t.exam_activity_id examActivityId,t.room_code
+		roomCode,t.room_name roomName, count(1) examTotal from
+		t_e_exam_student t
+		where t.exam_id = #{examId}
+		<if test="activityId != null and activityId != ''">
+			and t.exam_activity_id = #{activityId}
+		</if>
+		<if test="roomCode != null and roomCode != ''">
+			and t.room_code =#{roomCode}
+		</if>
+		<if test="courseCode != null and courseCode != ''">
+			and t.course_code = #{courseCode}
+		</if>
+		group by t.exam_id,t.exam_activity_id, t.room_code,t.room_name
+	</select>
+
+	<select id="getDoneCountByActivityIds"
+		resultType="java.util.Map">
+		select t.exam_activity_id activityId,t.room_code roomCode,count(1) cc
+		from t_e_exam_student t
+		where t.exam_id = #{examId} and t.current_record_id is not null
+		<if test="activityIds != null">
+			and t.exam_activity_id in
+			<foreach collection="activityIds" item="acid" index="index"
+				open="(" close=")" separator=",">
+				#{acid}
+			</foreach>
+		</if>
+		group by t.exam_activity_id, t.room_code
+	</select>
+
+	<select id="getAbsentCountByActivityIds"
+		resultType="java.util.Map">
+		select t.exam_activity_id activityId,t.room_code roomCode,count(1) cc
+		from t_e_exam_student t
+		where t.exam_id = #{examId} and t.current_record_id is null
+		<if test="activityIds != null">
+			and t.exam_activity_id in
+			<foreach collection="activityIds" item="acid" index="index"
+				open="(" close=")" separator=",">
+				#{acid}
+			</foreach>
+		</if>
+		group by t.exam_activity_id, t.room_code
+	</select>
+
+	<select id="examRoomQuery"
+		resultType="com.qmth.themis.business.dto.response.RoomCodeQueryDto">
+		select
+		DISTINCT
+		tees.room_code as roomCode,
+		tees.room_name as roomName
+		from
+		t_e_exam_student tees
+		<where>
+			<if test="roomName != null and roomName != ''">
+				and tees.room_name like concat('%', #{roomName}, '%')
+			</if>
+		</where>
+	</select>
 
-    <select id="examRoomQuery" resultType="com.qmth.themis.business.dto.response.RoomCodeQueryDto">
-        select
-        DISTINCT
-        tees.room_code as roomCode,
-        tees.room_name as roomName
-        from
-        t_e_exam_student tees
-        <where>
-            <if test="roomName != null and roomName != ''">
-                and tees.room_name like concat('%', #{roomName}, '%')
-            </if>
-        </where>
-    </select>
-    
-    <select id="getExamDeficiencyPage"
+	<select id="getExamDeficiencyPage"
 		resultType="com.qmth.themis.business.bean.backend.ExamDeficiencyListBean">
 		select t.exam_id examId,t.exam_activity_id
 		examActivityId,t.room_code
@@ -158,4 +171,5 @@
 			and t.name like concat(#{name},'%')
 		</if>
 	</select>
-</mapper>
+	
+</mapper>

+ 57 - 1
themis-business/src/main/resources/mapper/TIeInvigilateExceptionInfoMapper.xml

@@ -1,5 +1,61 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.qmth.themis.business.dao.TIeInvigilateExceptionInfoMapper">
-
+<select id="getExamExceptionPage"
+		resultType="com.qmth.themis.business.bean.backend.ExamExceptionListBean">
+		SELECT
+		f.exam_student_id examStudentId,
+		t.exam_id examId,
+		t.exam_activity_id examActivityId,
+		t.room_code roomCode,
+		t.course_code courseCode,
+		t.course_name courseName,
+		t.NAME,
+		t.identity,
+		t.room_name roomName,
+		count(f.exam_student_id) exceptionCount,
+		sum(
+		timestampdiff(
+		MINUTE,
+		f.create_time,
+		f.update_time
+		)
+		) exceptionTotalTime
+		FROM
+		t_ie_invigilate_exception_info f
+		LEFT JOIN t_e_exam_student t ON f.exam_student_id = t.id
+		where f.exam_id =#{examId}
+		<if test="activityId != null and activityId != ''">
+			and f.exam_activity_id = #{activityId}
+		</if>
+		<if test="roomCode != null and roomCode != ''">
+			and t.room_code =#{roomCode}
+		</if>
+		<if test="courseCode != null and courseCode != ''">
+			and t.course_code = #{courseCode}
+		</if>
+		<if test="identity != null and identity != ''">
+			and t.identity like concat(#{identity},'%')
+		</if>
+		<if test="name != null and name != ''">
+			and t.name like concat(#{name},'%')
+		</if>
+		GROUP BY f.exam_student_id
+	</select>
+	
+	<select id="getExamExceptionDetailList"
+		resultType="com.qmth.themis.business.bean.backend.ExamExceptionDetailListBean">
+		SELECT
+		UNIX_TIMESTAMP(f.create_time) * 1000 startTime,
+		UNIX_TIMESTAMP(f.update_time) * 1000 endTime,
+		f.type reason,
+		timestampdiff(
+		MINUTE,
+		f.create_time,
+		f.update_time) totalTime
+		FROM
+		t_ie_invigilate_exception_info f
+		where f.exam_student_id =#{examStudentId}
+		order by f.exam_student_id
+	</select>
 </mapper>