|
@@ -227,7 +227,7 @@ public class ExamControlServiceImpl implements ExamControlService {
|
|
*/
|
|
*/
|
|
@Transactional
|
|
@Transactional
|
|
@Override
|
|
@Override
|
|
- public StartExamInfo startExam(Long examStudentId, Long userId, String ip, Boolean allowOnline) {
|
|
|
|
|
|
+ public StartExamInfo startExam(Long examStudentId, Long userId, String ip, Boolean allowOnline, String fromBy) {
|
|
Check.isNull(examStudentId, "examStudentId不能为空");
|
|
Check.isNull(examStudentId, "examStudentId不能为空");
|
|
Check.isNull(userId, "userId不能为空");
|
|
Check.isNull(userId, "userId不能为空");
|
|
|
|
|
|
@@ -312,7 +312,7 @@ public class ExamControlServiceImpl implements ExamControlService {
|
|
initializeExamRecordSession(examingSession, examRecordData, examBean);
|
|
initializeExamRecordSession(examingSession, examRecordData, examBean);
|
|
|
|
|
|
//设置并保存上次活动时间
|
|
//设置并保存上次活动时间
|
|
- setAndSaveActiveTime(examRecordData.getId(), ip, "startExam");
|
|
|
|
|
|
+ setAndSaveActiveTime(examRecordData.getId(), ip, fromBy);
|
|
|
|
|
|
// 保存考试次数控制信息
|
|
// 保存考试次数控制信息
|
|
ExamBoss eb = examBossService.getExamBoss(examingSession.getExamStudentId());
|
|
ExamBoss eb = examBossService.getExamBoss(examingSession.getExamStudentId());
|
|
@@ -341,7 +341,7 @@ public class ExamControlServiceImpl implements ExamControlService {
|
|
|
|
|
|
|
|
|
|
@Override
|
|
@Override
|
|
- public String startExamWithCrypto(String encryptParams, User user, String requestIP, String timestampStr) {
|
|
|
|
|
|
+ public String startExamWithCrypto(String encryptParams, User user, String requestIP, String timestampStr, String fromBy) {
|
|
long timestamp;
|
|
long timestamp;
|
|
try {
|
|
try {
|
|
timestamp = CryptoHelper.parseTimestamp(timestampStr);
|
|
timestamp = CryptoHelper.parseTimestamp(timestampStr);
|
|
@@ -382,7 +382,7 @@ public class ExamControlServiceImpl implements ExamControlService {
|
|
}
|
|
}
|
|
|
|
|
|
Long examStudentId = jsonNode.get("examStudentId").asLong();
|
|
Long examStudentId = jsonNode.get("examStudentId").asLong();
|
|
- StartExamInfo examInfo = this.startExam(examStudentId, user.getUserId(), requestIP, true);
|
|
|
|
|
|
+ StartExamInfo examInfo = this.startExam(examStudentId, user.getUserId(), requestIP, true, fromBy);
|
|
String jsonResult = new JsonMapper().toJson(examInfo);
|
|
String jsonResult = new JsonMapper().toJson(examInfo);
|
|
|
|
|
|
// 按加密方案组合依次加密
|
|
// 按加密方案组合依次加密
|
|
@@ -793,7 +793,7 @@ public class ExamControlServiceImpl implements ExamControlService {
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
@Override
|
|
- public void manualEndExamWithCrypto(String encryptParams, User user, String requestIP, String timestampStr) {
|
|
|
|
|
|
+ public void manualEndExamWithCrypto(String encryptParams, User user, String requestIP, String timestampStr, String fromBy) {
|
|
long timestamp;
|
|
long timestamp;
|
|
try {
|
|
try {
|
|
timestamp = CryptoHelper.parseTimestamp(timestampStr);
|
|
timestamp = CryptoHelper.parseTimestamp(timestampStr);
|
|
@@ -825,11 +825,11 @@ public class ExamControlServiceImpl implements ExamControlService {
|
|
throw new StatusException("400X01", CryptoConstant.REQUEST_PARAM_ERROR);
|
|
throw new StatusException("400X01", CryptoConstant.REQUEST_PARAM_ERROR);
|
|
}
|
|
}
|
|
|
|
|
|
- this.manualEndExam(user.getUserId(), requestIP, false);
|
|
|
|
|
|
+ this.manualEndExam(user.getUserId(), requestIP, false, fromBy);
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
@Override
|
|
- public void manualEndExam(Long studentId, String ip, Boolean force) {
|
|
|
|
|
|
+ public void manualEndExam(Long studentId, String ip, Boolean force, String fromBy) {
|
|
String sequenceLockKey = CacheConstants.LOCK_EXAM_CONTROL + studentId;
|
|
String sequenceLockKey = CacheConstants.LOCK_EXAM_CONTROL + studentId;
|
|
//系统在请求结束后会,自动释放锁,无需手动解锁
|
|
//系统在请求结束后会,自动释放锁,无需手动解锁
|
|
SequenceLockHelper.getLock(sequenceLockKey);
|
|
SequenceLockHelper.getLock(sequenceLockKey);
|
|
@@ -839,7 +839,7 @@ public class ExamControlServiceImpl implements ExamControlService {
|
|
throw new StatusException("8010", "无效的会话,请离开考试");
|
|
throw new StatusException("8010", "无效的会话,请离开考试");
|
|
}
|
|
}
|
|
|
|
|
|
- this.handInExam(examingSession.getExamRecordDataId(), HandInExamType.MANUAL, ip, force);
|
|
|
|
|
|
+ this.handInExam(examingSession.getExamRecordDataId(), HandInExamType.MANUAL, ip, force, fromBy);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -850,7 +850,7 @@ public class ExamControlServiceImpl implements ExamControlService {
|
|
*/
|
|
*/
|
|
@Transactional
|
|
@Transactional
|
|
@Override
|
|
@Override
|
|
- public void handInExam(Long examRecordDataId, HandInExamType handInExamType, String ip, Boolean force) {
|
|
|
|
|
|
+ public void handInExam(Long examRecordDataId, HandInExamType handInExamType, String ip, Boolean force, String fromBy) {
|
|
// 此锁是为了避免自动交卷服务与断点续考交卷或活检失败交卷,同一时刻交卷争抢资源导致死锁
|
|
// 此锁是为了避免自动交卷服务与断点续考交卷或活检失败交卷,同一时刻交卷争抢资源导致死锁
|
|
String sequenceLockKey = CacheConstants.LOCK_HAND_IN_EXAM + examRecordDataId;
|
|
String sequenceLockKey = CacheConstants.LOCK_HAND_IN_EXAM + examRecordDataId;
|
|
// 系统在请求结束后会,自动释放锁,无需手动解锁
|
|
// 系统在请求结束后会,自动释放锁,无需手动解锁
|
|
@@ -870,7 +870,7 @@ public class ExamControlServiceImpl implements ExamControlService {
|
|
examRecordData.setExamRecordStatus(ExamRecordStatus.EXAM_HAND_IN);
|
|
examRecordData.setExamRecordStatus(ExamRecordStatus.EXAM_HAND_IN);
|
|
examRecordData.setEndTime(new Date());
|
|
examRecordData.setEndTime(new Date());
|
|
//设置并保存上次活动时间
|
|
//设置并保存上次活动时间
|
|
- setAndSaveActiveTime(examRecordDataId, ip, "handInExam");
|
|
|
|
|
|
+ setAndSaveActiveTime(examRecordDataId, ip, fromBy);
|
|
} else if (handInExamType == HandInExamType.AUTO) {
|
|
} else if (handInExamType == HandInExamType.AUTO) {
|
|
examRecordData.setExamRecordStatus(ExamRecordStatus.EXAM_AUTO_HAND_IN);
|
|
examRecordData.setExamRecordStatus(ExamRecordStatus.EXAM_AUTO_HAND_IN);
|
|
examRecordData.setCleanTime(new Date());
|
|
examRecordData.setCleanTime(new Date());
|
|
@@ -1695,14 +1695,14 @@ public class ExamControlServiceImpl implements ExamControlService {
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
@Override
|
|
- public ExamProcessResultInfo checkExamInProgress2(Long studentId, String ip) {
|
|
|
|
|
|
+ public ExamProcessResultInfo checkExamInProgress2(Long studentId, String ip, String fromBy) {
|
|
String sequenceLockKey = CacheConstants.LOCK_EXAM_CONTROL + studentId;
|
|
String sequenceLockKey = CacheConstants.LOCK_EXAM_CONTROL + studentId;
|
|
// 系统在请求结束后会,自动释放锁,无需手动解锁
|
|
// 系统在请求结束后会,自动释放锁,无需手动解锁
|
|
SequenceLockHelper.getLock(sequenceLockKey);
|
|
SequenceLockHelper.getLock(sequenceLockKey);
|
|
|
|
|
|
ExamProcessResultInfo res = new ExamProcessResultInfo();
|
|
ExamProcessResultInfo res = new ExamProcessResultInfo();
|
|
try {
|
|
try {
|
|
- CheckExamInProgressInfo info = this.checkExamInProgress(studentId, ip);
|
|
|
|
|
|
+ CheckExamInProgressInfo info = this.checkExamInProgress(studentId, ip, fromBy);
|
|
res.setCode(Constants.COMMON_SUCCESS_CODE);
|
|
res.setCode(Constants.COMMON_SUCCESS_CODE);
|
|
res.setData(info);
|
|
res.setData(info);
|
|
return res;
|
|
return res;
|
|
@@ -1718,7 +1718,7 @@ public class ExamControlServiceImpl implements ExamControlService {
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
@Override
|
|
- public CheckExamInProgressInfo checkExamInProgress(Long studentId, String ip) {
|
|
|
|
|
|
+ public CheckExamInProgressInfo checkExamInProgress(Long studentId, String ip, String fromBy) {
|
|
ExamingSession examSessionInfo = examingSessionService.getExamingSession(studentId);
|
|
ExamingSession examSessionInfo = examingSessionService.getExamingSession(studentId);
|
|
if (examSessionInfo == null || ExamingStatus.INFORMAL.equals(examSessionInfo.getExamingStatus())) {
|
|
if (examSessionInfo == null || ExamingStatus.INFORMAL.equals(examSessionInfo.getExamingStatus())) {
|
|
return null;
|
|
return null;
|
|
@@ -1791,7 +1791,7 @@ public class ExamControlServiceImpl implements ExamControlService {
|
|
checkExamInProgressInfo.setFaceVerifyMinute(faceVerifyMinute);
|
|
checkExamInProgressInfo.setFaceVerifyMinute(faceVerifyMinute);
|
|
|
|
|
|
//设置并保存上次活动时间
|
|
//设置并保存上次活动时间
|
|
- setAndSaveActiveTime(examRecordDataId, ip, "checkExamInProgress");
|
|
|
|
|
|
+ setAndSaveActiveTime(examRecordDataId, ip, fromBy);
|
|
|
|
|
|
//考试过程记录(断点)打点
|
|
//考试过程记录(断点)打点
|
|
ExamingActivityTime lastExamingActivityTime = getExamingActivityTime(examRecordDataId);
|
|
ExamingActivityTime lastExamingActivityTime = getExamingActivityTime(examRecordDataId);
|
|
@@ -1875,7 +1875,8 @@ public class ExamControlServiceImpl implements ExamControlService {
|
|
*/
|
|
*/
|
|
private void delayHandInExamIfLocked(Long examRecordDataId) {
|
|
private void delayHandInExamIfLocked(Long examRecordDataId) {
|
|
try {
|
|
try {
|
|
- this.handInExam(examRecordDataId, HandInExamType.AUTO, null, true);
|
|
|
|
|
|
+ String fromBy = "handInExam-auto-考试时间结束";
|
|
|
|
+ this.handInExam(examRecordDataId, HandInExamType.AUTO, null, true, fromBy);
|
|
} catch (SequenceLockException e) {
|
|
} catch (SequenceLockException e) {
|
|
// 如果发现自动服务正在交卷,则重试1500毫秒获取考试记录状态,判断是否已交卷
|
|
// 如果发现自动服务正在交卷,则重试1500毫秒获取考试记录状态,判断是否已交卷
|
|
int loopTimes = 0;
|
|
int loopTimes = 0;
|
|
@@ -1919,7 +1920,7 @@ public class ExamControlServiceImpl implements ExamControlService {
|
|
* @param user 学生
|
|
* @param user 学生
|
|
*/
|
|
*/
|
|
@Override
|
|
@Override
|
|
- public long examHeartbeat(User user, String ip) {
|
|
|
|
|
|
+ public long examHeartbeat(User user, String ip, String fromBy) {
|
|
Long studentId = user.getUserId();
|
|
Long studentId = user.getUserId();
|
|
ExamingSession examSessionInfo = examingSessionService.getExamingSession(studentId);
|
|
ExamingSession examSessionInfo = examingSessionService.getExamingSession(studentId);
|
|
if (examSessionInfo == null || ExamingStatus.INFORMAL.equals(examSessionInfo.getExamingStatus())) {
|
|
if (examSessionInfo == null || ExamingStatus.INFORMAL.equals(examSessionInfo.getExamingStatus())) {
|
|
@@ -1966,7 +1967,7 @@ public class ExamControlServiceImpl implements ExamControlService {
|
|
redisClient.set(examingHeartbeatKey, examingHeartbeat, OeConstants.TIME_OUT_7_DAY);//更新心跳缓存
|
|
redisClient.set(examingHeartbeatKey, examingHeartbeat, OeConstants.TIME_OUT_7_DAY);//更新心跳缓存
|
|
|
|
|
|
//设置并保存上次活动时间
|
|
//设置并保存上次活动时间
|
|
- setAndSaveActiveTime(examSessionInfo.getExamRecordDataId(), ip, "examHeartbeat");
|
|
|
|
|
|
+ setAndSaveActiveTime(examSessionInfo.getExamRecordDataId(), ip, fromBy);
|
|
|
|
|
|
// 在线考生心跳打点
|
|
// 在线考生心跳打点
|
|
ReportsUtil.report(new OnlineExamStudentReport(user.getRootOrgId(), user.getUserId(),
|
|
ReportsUtil.report(new OnlineExamStudentReport(user.getRootOrgId(), user.getUserId(),
|
|
@@ -1988,10 +1989,12 @@ public class ExamControlServiceImpl implements ExamControlService {
|
|
*
|
|
*
|
|
* @param examRecordDataId 考试记录id
|
|
* @param examRecordDataId 考试记录id
|
|
* @param ip IP地址
|
|
* @param ip IP地址
|
|
- * @param operate 操作
|
|
|
|
|
|
+ * @param fromBy 操作来源
|
|
*/
|
|
*/
|
|
@Override
|
|
@Override
|
|
- public void setAndSaveActiveTime(Long examRecordDataId, String ip, String operate) {
|
|
|
|
|
|
+ public void setAndSaveActiveTime(Long examRecordDataId, String ip, String fromBy) {
|
|
|
|
+ log.warn("setAndSaveActiveTime examRecordDataId:{} ip:{} fromBy:{}", examRecordDataId, ip, fromBy);
|
|
|
|
+
|
|
String examingActiveTimeKey = RedisKeyHelper.getBuilder().examingActiveTimeKey(examRecordDataId);
|
|
String examingActiveTimeKey = RedisKeyHelper.getBuilder().examingActiveTimeKey(examRecordDataId);
|
|
ExamingActivityTime examingActiveTime = redisClient.get(examingActiveTimeKey, ExamingActivityTime.class);
|
|
ExamingActivityTime examingActiveTime = redisClient.get(examingActiveTimeKey, ExamingActivityTime.class);
|
|
if (null == examingActiveTime) {
|
|
if (null == examingActiveTime) {
|
|
@@ -2009,8 +2012,6 @@ public class ExamControlServiceImpl implements ExamControlService {
|
|
examingActiveTime.setRealIp(ip);
|
|
examingActiveTime.setRealIp(ip);
|
|
|
|
|
|
redisClient.set(examingActiveTimeKey, examingActiveTime, OeConstants.TIME_OUT_7_DAY);
|
|
redisClient.set(examingActiveTimeKey, examingActiveTime, OeConstants.TIME_OUT_7_DAY);
|
|
-
|
|
|
|
- log.warn("setAndSaveActiveTime examRecordDataId:{} ip:{} operate:{}", examRecordDataId, ip, operate);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|