xiatian 5 vuotta sitten
vanhempi
commit
780305cf2e

+ 5 - 0
themis-business/src/main/java/com/qmth/themis/business/cache/RedisKeyHelper.java

@@ -2,8 +2,13 @@ package com.qmth.themis.business.cache;
 
 public class RedisKeyHelper {
 	private static String examActivityKeyPrefix = "exam_activity::";
+	private static String examStudentKeyPrefix = "exam_student::";
 
 	public static String examActivityCacheKey(Long activityId) {
 		return examActivityKeyPrefix + activityId;
 	}
+
+	public static String examStudentCacheKey(Long examStudentId) {
+		return examStudentKeyPrefix + examStudentId;
+	}
 }

+ 9 - 11
themis-business/src/main/java/com/qmth/themis/business/cache/bean/ExamActivityCacheBean.java

@@ -3,38 +3,36 @@ package com.qmth.themis.business.cache.bean;
 import java.io.Serializable;
 import java.util.Date;
 
-import io.swagger.annotations.ApiModelProperty;
-
 public class ExamActivityCacheBean implements Serializable {
 	/**
 	 * 
 	 */
 	private static final long serialVersionUID = -5888311300472703230L;
 
-	@ApiModelProperty(value = "主键")
+	//主键
 	private Long id;
-	@ApiModelProperty(value = "批次id")
+	//批次id
 	private Long examId;
 
-	@ApiModelProperty(value = "场次代码")
+	//场次代码
 	private String code;
 
-	@ApiModelProperty(value = "提前多长时间开始候考(分钟)")
+	//提前多长时间开始候考(分钟)
 	private Integer prepareSeconds;
 
-	@ApiModelProperty(value = "最大考试时长")
+	//最大考试时长
 	private Integer maxDurationSeconds;
 
-	@ApiModelProperty(value = "是否启用,0:停用,1:启用")
+	//是否启用,0:停用,1:启用
 	private Integer enable;
 
-	@ApiModelProperty(value = "允许开考时长(分钟)")
+	//允许开考时长(分钟)
 	private Integer openingSeconds;
 
-	@ApiModelProperty(value = "开考时间")
+	//开考时间
 	private Date startTime;
 
-	@ApiModelProperty(value = "结束时间")
+	//结束时间
 	private Date finishTime;
 
 	public Long getExamId() {

+ 134 - 0
themis-business/src/main/java/com/qmth/themis/business/cache/bean/ExamCourseCacheBean.java

@@ -0,0 +1,134 @@
+package com.qmth.themis.business.cache.bean;
+
+import java.io.Serializable;
+import java.util.List;
+
+public class ExamCourseCacheBean implements Serializable {
+
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = -9033695063460046875L;
+
+	// 主键
+	private Long id;
+
+	// 考试ID
+	private Long examId;
+
+	// 科目编码
+	private String courseCode;
+
+	// 科目名称
+	private String courseName;
+
+	// 是否开启客观题乱序,0:不开启,1:开启
+	private Integer objectiveShuffle;
+
+	// 是否选项乱序,针对一个科目进行设置,0:不开启,1:开启
+	private Integer optionShuffle;
+
+	// 已绑定试卷数量
+	private Integer paperCount;
+
+	// 是否已补齐标答,0:否,1:是
+	private Integer hasAnswer;
+
+	// 音频播放次数
+	private Integer audioPlayTime;
+
+	// 试卷id
+	private List<Long> paperIds;
+
+	// 调卷比例
+	private List<Long> paperWeight;
+
+	public Long getId() {
+		return id;
+	}
+
+	public void setId(Long id) {
+		this.id = id;
+	}
+
+	public Long getExamId() {
+		return examId;
+	}
+
+	public void setExamId(Long examId) {
+		this.examId = examId;
+	}
+
+	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 Integer getObjectiveShuffle() {
+		return objectiveShuffle;
+	}
+
+	public void setObjectiveShuffle(Integer objectiveShuffle) {
+		this.objectiveShuffle = objectiveShuffle;
+	}
+
+	public Integer getOptionShuffle() {
+		return optionShuffle;
+	}
+
+	public void setOptionShuffle(Integer optionShuffle) {
+		this.optionShuffle = optionShuffle;
+	}
+
+	public Integer getPaperCount() {
+		return paperCount;
+	}
+
+	public void setPaperCount(Integer paperCount) {
+		this.paperCount = paperCount;
+	}
+
+	public Integer getHasAnswer() {
+		return hasAnswer;
+	}
+
+	public void setHasAnswer(Integer hasAnswer) {
+		this.hasAnswer = hasAnswer;
+	}
+
+	public Integer getAudioPlayTime() {
+		return audioPlayTime;
+	}
+
+	public void setAudioPlayTime(Integer audioPlayTime) {
+		this.audioPlayTime = audioPlayTime;
+	}
+
+	public List<Long> getPaperIds() {
+		return paperIds;
+	}
+
+	public void setPaperIds(List<Long> paperIds) {
+		this.paperIds = paperIds;
+	}
+
+	public List<Long> getPaperWeight() {
+		return paperWeight;
+	}
+
+	public void setPaperWeight(List<Long> paperWeight) {
+		this.paperWeight = paperWeight;
+	}
+
+}

+ 131 - 0
themis-business/src/main/java/com/qmth/themis/business/cache/bean/ExamStudentCacheBean.java

@@ -0,0 +1,131 @@
+package com.qmth.themis.business.cache.bean;
+
+import java.io.Serializable;
+
+public class ExamStudentCacheBean implements Serializable {
+
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = -7154063361894874051L;
+
+	// 主键
+	private Long id;
+
+	// 批次id
+	private Long examId;
+
+	// 场次id
+	private Long examActivityId;
+
+	// 学生id
+	private Long studentId;
+
+	// 科目代码
+	private String courseCode;
+
+	// 科目名称
+	private String courseName;
+
+	// 虚拟考场代码,考试唯一
+	private String roomCode;
+
+	// 考场名称
+	private String roomName;
+
+	// 剩余考试次数
+	private Integer leftExamCount;
+	// 当前考试是第几次
+	private Integer currentSerialNumber;
+	// 当前考试记录ID
+	private Long currentRecordId;
+
+	public Integer getCurrentSerialNumber() {
+		return currentSerialNumber;
+	}
+
+	public void setCurrentSerialNumber(Integer currentSerialNumber) {
+		this.currentSerialNumber = currentSerialNumber;
+	}
+
+	public String getCourseName() {
+		return courseName;
+	}
+
+	public void setCourseName(String courseName) {
+		this.courseName = courseName;
+	}
+
+	public String getRoomName() {
+		return roomName;
+	}
+
+	public void setRoomName(String roomName) {
+		this.roomName = roomName;
+	}
+
+	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 Long getStudentId() {
+		return studentId;
+	}
+
+	public void setStudentId(Long studentId) {
+		this.studentId = studentId;
+	}
+
+	public String getCourseCode() {
+		return courseCode;
+	}
+
+	public void setCourseCode(String courseCode) {
+		this.courseCode = courseCode;
+	}
+
+	public String getRoomCode() {
+		return roomCode;
+	}
+
+	public void setRoomCode(String roomCode) {
+		this.roomCode = roomCode;
+	}
+
+	public Integer getLeftExamCount() {
+		return leftExamCount;
+	}
+
+	public void setLeftExamCount(Integer leftExamCount) {
+		this.leftExamCount = leftExamCount;
+	}
+
+	public Long getCurrentRecordId() {
+		return currentRecordId;
+	}
+
+	public void setCurrentRecordId(Long currentRecordId) {
+		this.currentRecordId = currentRecordId;
+	}
+
+	public Long getId() {
+		return id;
+	}
+
+	public void setId(Long id) {
+		this.id = id;
+	}
+
+}

+ 4 - 5
themis-business/src/main/java/com/qmth/themis/business/service/TEExamService.java

@@ -1,13 +1,12 @@
 package com.qmth.themis.business.service;
 
+import java.util.List;
+import java.util.Map;
+
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.qmth.themis.business.bean.exam.ExamPrepareBean;
 import com.qmth.themis.business.entity.TEExam;
-import org.apache.ibatis.annotations.Param;
-
-import java.util.List;
-import java.util.Map;
 
 /**
  * @Description: 考试批次 服务类
@@ -44,5 +43,5 @@ public interface TEExamService extends IService<TEExam> {
 	 * @param activityId
 	 * @return
 	 */
-	public ExamPrepareBean prepare(Long studentId, Long activityId);
+	public ExamPrepareBean prepare(Long studentId, Long examStudentId);
 }

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

@@ -2,6 +2,7 @@ package com.qmth.themis.business.service;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.qmth.themis.business.cache.bean.ExamStudentCacheBean;
 import com.qmth.themis.business.entity.TEExamStudent;
 
 import java.util.Map;
@@ -30,4 +31,6 @@ public interface TEExamStudentService extends IService<TEExamStudent> {
      * @return
      */
     public IPage<Map> examStudentQuery(IPage<Map> iPage, Long examId, Long activityId, String identity, String name, String roomCode, String courseCode, String grade, Integer enable);
+
+	ExamStudentCacheBean getExamStudnetCacheBean(Long examStudentId);
 }

+ 54 - 12
themis-business/src/main/java/com/qmth/themis/business/service/impl/TEExamServiceImpl.java

@@ -1,19 +1,28 @@
 package com.qmth.themis.business.service.impl;
 
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+import javax.annotation.Resource;
+
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.qmth.themis.business.bean.exam.ExamPrepareBean;
+import com.qmth.themis.business.cache.RedisKeyHelper;
+import com.qmth.themis.business.cache.bean.ExamActivityCacheBean;
+import com.qmth.themis.business.cache.bean.ExamStudentCacheBean;
 import com.qmth.themis.business.dao.TEExamMapper;
 import com.qmth.themis.business.entity.TEExam;
 import com.qmth.themis.business.service.TEExamActivityService;
 import com.qmth.themis.business.service.TEExamService;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-import javax.annotation.Resource;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
+import com.qmth.themis.business.service.TEExamStudentService;
+import com.qmth.themis.business.util.RedisUtil;
+import com.qmth.themis.common.exception.BusinessException;
 
 /**
  * @Description: 考试批次 服务实现类
@@ -29,8 +38,13 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
     TEExamMapper teExamMapper;
 
     @Resource
-    TEExamActivityService examActivityService;
+    TEExamActivityService teExamActivityService;
+    
+    @Resource
+    TEExamStudentService teExamStudentService;
 
+    @Resource
+    RedisUtil redisUtil;
     /**
      * 查询考试批次
      *
@@ -59,7 +73,7 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
         if (Objects.nonNull(list) && list.size() > 0) {
             for (int i = 0; i < list.size(); i++) {
                 Map m = list.get(i);
-                List<Map> teExamActivityList = examActivityService.getWaitingExam(studentId, Long.parseLong(String.valueOf(m.get("id"))), Long.parseLong(String.valueOf(m.get("examActivityId"))));
+                List<Map> teExamActivityList = teExamActivityService.getWaitingExam(studentId, Long.parseLong(String.valueOf(m.get("id"))), Long.parseLong(String.valueOf(m.get("examActivityId"))));
                 m.put("activities", teExamActivityList);
             }
         }
@@ -68,8 +82,36 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
 
     @Transactional
 	@Override
-	public ExamPrepareBean prepare(Long studentId, Long activityId) {
-		// TODO Auto-generated method stub
-		return null;
+	public ExamPrepareBean prepare(Long studentId, Long examStudentId) {
+    	ExamPrepareBean ret=null;
+    	ExamStudentCacheBean es=null;
+    	es=(ExamStudentCacheBean)redisUtil.get(RedisKeyHelper.examStudentCacheKey(examStudentId));
+    	if(es==null) {
+    		es=teExamStudentService.getExamStudnetCacheBean(examStudentId);
+    	}
+    	if(es==null) {
+    		throw new BusinessException("未找到考试");
+    	}
+    	if(studentId.equals(es.getStudentId())) {
+    		throw new BusinessException("考生Id和当前登录用户不一致");
+    	}
+    	if(es.getLeftExamCount()==0) {
+    		throw new BusinessException("没有剩余考试次数");
+    	}
+    	Long activityId=es.getExamActivityId();
+    	ExamActivityCacheBean ac=teExamActivityService.getExamActivityCacheBean(activityId);
+    	if(ac==null) {
+    		throw new BusinessException("未找到场次");
+    	}
+    	Date now=new Date();
+    	Long start=ac.getStartTime().getTime()-(ac.getPrepareSeconds()*1000);
+    	Long end=ac.getStartTime().getTime()+(ac.getOpeningSeconds()*1000);
+    	if(now.getTime()<start) {
+    		throw new BusinessException("没有到允许开考的时间");
+    	}
+    	if(now.getTime()>end) {
+    		throw new BusinessException("允许开考的时间已结束");
+    	}
+		return ret;
 	}
 }

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

@@ -1,14 +1,17 @@
 package com.qmth.themis.business.service.impl;
 
+import java.util.Map;
+
+import javax.annotation.Resource;
+
+import org.springframework.stereotype.Service;
+
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.qmth.themis.business.cache.bean.ExamStudentCacheBean;
 import com.qmth.themis.business.dao.TEExamStudentMapper;
 import com.qmth.themis.business.entity.TEExamStudent;
 import com.qmth.themis.business.service.TEExamStudentService;
-import org.springframework.stereotype.Service;
-
-import javax.annotation.Resource;
-import java.util.Map;
 
 /**
  * @Description: 考生库 服务实现类
@@ -41,4 +44,29 @@ public class TEExamStudentServiceImpl extends ServiceImpl<TEExamStudentMapper, T
     public IPage<Map> examStudentQuery(IPage<Map> iPage, Long examId, Long activityId, String identity, String name, String roomCode, String courseCode, String grade, Integer enable) {
         return teExamStudentMapper.examStudentQuery(iPage, examId, activityId, identity, name, roomCode, courseCode, grade, enable);
     }
+    
+    @Override
+    public ExamStudentCacheBean getExamStudnetCacheBean(Long examStudentId) {
+    	ExamStudentCacheBean ret=null;
+    	TEExamStudent es=getById(examStudentId);
+    	if(es==null) {
+    		return ret;
+    	}
+    	if(es.getEnable()!=null&&es.getEnable().intValue()==0) {
+    		return ret;
+    	}
+    	ret=new ExamStudentCacheBean();
+    	ret.setId(es.getId());
+    	ret.setExamId(es.getExamId());
+    	ret.setExamActivityId(es.getExamActivityId());
+    	ret.setStudentId(es.getStudentId());
+    	ret.setCourseCode(es.getCourseCode());
+    	ret.setCourseName(es.getCourseName());
+    	ret.setRoomCode(es.getRoomCode());
+    	ret.setRoomName(es.getRoomName());
+    	ret.setLeftExamCount(es.getLeftExamCount());
+    	ret.setCurrentRecordId(es.getCurrentRecordId());
+    	ret.setCurrentSerialNumber(null);
+        return ret;
+    }
 }

+ 2 - 2
themis-exam/src/main/java/com/qmth/themis/exam/api/TEExamController.java

@@ -62,7 +62,7 @@ public class TEExamController {
 	@ApiOperation(value = "开始候考")
 	@RequestMapping(value = "/prepare", method = RequestMethod.POST)
 	@ApiResponses({ @ApiResponse(code = 200, message = "试卷信息") })
-	public ExamPrepareBean prepare(@ApiParam(value = "考试场次ID", required = true) @RequestParam Long activityId) {
+	public ExamPrepareBean prepare(@ApiParam(value = "考生ID", required = true) @RequestParam Long examStudentId) {
 		TEStudent teStudent = (TEStudent) ServletUtil.getRequestStudentAccount();
 		String lockKey=SystemConstant.REDIS_LOCK_STUDENT_PREFIX+teStudent.getId();
 		Boolean lock=redisUtil.lock(lockKey, SystemConstant.REDIS_CACHE_TIME_OUT);
@@ -70,7 +70,7 @@ public class TEExamController {
 			throw new BusinessException(ExceptionResultEnum.REQUEST_AWAIT);
 		}
 		try {
-			return teExamService.prepare(teStudent.getId(), activityId);
+			return teExamService.prepare(teStudent.getId(), examStudentId);
 		} finally {
 			redisUtil.releaseLock(lockKey);
 		}