【修改】 1、多任务创建ID更改;2、获取学生是否处在考试中;3、继续考试
This commit is contained in:
@@ -15,4 +15,5 @@ public class StuMonitorPaperVo {
|
||||
|
||||
private String taskId;
|
||||
|
||||
private String temporaryId;
|
||||
}
|
||||
|
@@ -7,6 +7,8 @@ import pc.exam.pp.module.exam.dal.dataobject.EducationPaperSession;
|
||||
import pc.exam.pp.module.exam.dal.dataobject.ExamQuestion;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@Data
|
||||
public class ExamPaperVo {
|
||||
String paperId;
|
||||
@@ -24,19 +26,4 @@ public class ExamPaperVo {
|
||||
this.educationPaperSchemeList = educationPaperSchemeList;
|
||||
}
|
||||
|
||||
public List<ExamQuestion> getExamQuestionList() {
|
||||
return examQuestionList;
|
||||
}
|
||||
|
||||
public void setExamQuestionList(List<ExamQuestion> examQuestionList) {
|
||||
this.examQuestionList = examQuestionList;
|
||||
}
|
||||
|
||||
public List<EducationPaperScheme> getEducationPaperSchemeList() {
|
||||
return educationPaperSchemeList;
|
||||
}
|
||||
|
||||
public void setEducationPaperSchemeList(List<EducationPaperScheme> educationPaperSchemeList) {
|
||||
this.educationPaperSchemeList = educationPaperSchemeList;
|
||||
}
|
||||
}
|
||||
|
@@ -38,7 +38,6 @@ public class EducationPaperParam
|
||||
private String isAnswerId;
|
||||
|
||||
/** 是否使用监考密码验证(0是1否) */
|
||||
// @Excel(name = "是否使用监考密码验证", readConverterExp = "0=是1否")
|
||||
private String isExamPassword;
|
||||
|
||||
/** 监考密码 */
|
||||
@@ -46,15 +45,12 @@ public class EducationPaperParam
|
||||
private String examPassword;
|
||||
|
||||
/** 禁止学生使用U盘(0是1否) */
|
||||
// @Excel(name = "禁止学生使用U盘", readConverterExp = "0=是1否")
|
||||
private String usb;
|
||||
|
||||
/** 练习成绩保存0最高成绩1最新成绩 */
|
||||
// @Excel(name = "练习成绩保存0最高成绩1最新成绩")
|
||||
private String saveGrades;
|
||||
|
||||
/** 驱动器为学生文件存放系统盘(C,D) */
|
||||
// @Excel(name = "驱动器为学生文件存放系统盘", readConverterExp = "C=,D")
|
||||
private String driver;
|
||||
|
||||
/** 考试目录名称 */
|
||||
@@ -62,11 +58,9 @@ public class EducationPaperParam
|
||||
private String directory;
|
||||
|
||||
/** 考试的模式下定时上传考试目录,每{x}分钟传一次 */
|
||||
// @Excel(name = "考试的模式下定时上传考试目录,每{x}分钟传一次")
|
||||
private String uploadTime;
|
||||
|
||||
/** 是否允许复制题干(0是1否) */
|
||||
// @Excel(name = "完成考试后是否删除考试目录", readConverterExp = "0=是1否")
|
||||
private String isCopy;
|
||||
|
||||
//是否显示重答按钮
|
||||
|
@@ -260,6 +260,7 @@ public class MonitorServiceImpl implements MonitorService {
|
||||
LocalDateTime nowTime = LocalDateTime.now();
|
||||
DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
info.setStartTime(nowTime.format(formatter1));
|
||||
info.setTemporaryId(stuMonitorPaperVo.getTemporaryId());
|
||||
info.setIp(stuMonitorPaperVo.getIp());
|
||||
|
||||
if (info.getRemainingTime() == null) {
|
||||
|
@@ -5,6 +5,7 @@ import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
@@ -15,7 +16,10 @@ import pc.exam.pp.framework.common.util.servlet.ServletUtils;
|
||||
import pc.exam.pp.framework.security.config.SecurityProperties;
|
||||
import pc.exam.pp.framework.security.core.LoginUser;
|
||||
import pc.exam.pp.framework.security.core.util.SecurityFrameworkUtils;
|
||||
import pc.exam.pp.module.exam.controller.admin.paper.vo.ExamPaperVo;
|
||||
import pc.exam.pp.module.exam.dal.dataobject.*;
|
||||
import pc.exam.pp.module.exam.dal.dataobject.monitor.MonitorDO;
|
||||
import pc.exam.pp.module.exam.dal.dataobject.student.StuPaperFileDO;
|
||||
import pc.exam.pp.module.exam.dal.dataobject.student.StuPaperScoreDO;
|
||||
import pc.exam.pp.module.exam.dal.mysql.paper.EducationPaperPersonMapper;
|
||||
import pc.exam.pp.module.exam.dal.mysql.paper.EducationPaperQuMapper;
|
||||
@@ -23,16 +27,17 @@ import pc.exam.pp.module.exam.dal.mysql.paper.EducationPaperSessionMapper;
|
||||
import pc.exam.pp.module.exam.dal.mysql.question.ExamQuestionMapper;
|
||||
import pc.exam.pp.module.exam.dal.mysql.student.StuScoreVo;
|
||||
import pc.exam.pp.module.exam.service.paper.IEducationPaperParamService;
|
||||
import pc.exam.pp.module.exam.service.paper.IEducationPaperQuService;
|
||||
import pc.exam.pp.module.exam.service.stuPaperScore.StuPaperScoreService;
|
||||
import pc.exam.pp.module.judgement.controller.admin.autoTools.vo.StuInTheExam;
|
||||
import pc.exam.pp.module.judgement.controller.admin.autoTools.vo.StuPaperReqVo;
|
||||
import pc.exam.pp.module.judgement.controller.admin.autoTools.vo.StuPaperScoreInfoVo;
|
||||
import pc.exam.pp.module.judgement.controller.admin.autoTools.vo.StuTheExamInfo;
|
||||
import pc.exam.pp.module.exam.service.stu_paper_file.StuPaperFileService;
|
||||
import pc.exam.pp.module.judgement.controller.admin.autoTools.vo.*;
|
||||
import pc.exam.pp.module.judgement.service.TaskManager;
|
||||
import pc.exam.pp.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -67,6 +72,10 @@ public class AutoToolsController {
|
||||
IEducationPaperParamService educationPaperParamService;
|
||||
@Resource
|
||||
StringRedisTemplate stringRedisTemplate;
|
||||
@Resource
|
||||
IEducationPaperQuService educationPaperQuService;
|
||||
@Resource
|
||||
StuPaperFileService stuPaperFileService;
|
||||
|
||||
@GetMapping("/getStuScoreInfo")
|
||||
@Operation(summary = "通过学生ID、试卷ID获取")
|
||||
@@ -161,31 +170,120 @@ public class AutoToolsController {
|
||||
stuTheExamInfo.setTime(formatLongDuration(countdown.get()));
|
||||
// 返回数据-上传文件状态 0:上传;1:不上传
|
||||
stuTheExamInfo.setUpload(1);
|
||||
// 返回数据-上传文件状态 0:结束;1:不结束
|
||||
// 返回数据-结束考试 0:结束;1:不结束
|
||||
stuTheExamInfo.setEndStatus(1);
|
||||
// 返回数据-网络状态
|
||||
stuTheExamInfo.setNetwork("强");
|
||||
// 创建对应的线程池
|
||||
if (loginUser != null) {
|
||||
taskManager.startTask(stuInTheExam, stuTheExamInfo, token, countdown, new AtomicInteger(0), String.valueOf(loginUser.getId()));
|
||||
taskManager.startTask(stuInTheExam, stuTheExamInfo, token, countdown, new AtomicInteger(0), loginUser.getId() + "_" + stuInTheExam.getTaskId() + "_" + stuInTheExam.getPaperId());
|
||||
}
|
||||
System.out.println("--------------token------------------" + token);
|
||||
return CommonResult.success(token);
|
||||
}
|
||||
return CommonResult.success("未登录");
|
||||
}
|
||||
|
||||
// 学生端重新登录,判断是否上一次考试没有结束就退出了
|
||||
@GetMapping("/reStartExamStatus")
|
||||
public CommonResult<String> reStartExamStatus() {
|
||||
HttpServletRequest request = ServletUtils.getRequest();
|
||||
// 获取学生ID
|
||||
LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
|
||||
if (loginUser != null) {
|
||||
long userId = loginUser.getId();
|
||||
String key = taskManager.getTaskById(String.valueOf(userId));
|
||||
if (key == null) {
|
||||
return CommonResult.success("0");
|
||||
}
|
||||
return CommonResult.success(key);
|
||||
}
|
||||
return CommonResult.success("0");
|
||||
}
|
||||
|
||||
// 学生端考试没有结束对出,继续进行开始(需要返回下载文件地址,任务ID)
|
||||
@PostMapping("/reStartExam")
|
||||
public CommonResult<ExamRestartPaperVo> reStartExam(@RequestBody StuInTheExam stuInTheExam) {
|
||||
// 获取学生ID
|
||||
LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
|
||||
HttpServletRequest request = ServletUtils.getRequest();
|
||||
String token = SecurityFrameworkUtils.obtainAuthorization(request,
|
||||
securityProperties.getTokenHeader(), securityProperties.getTokenParameter());
|
||||
ExamRestartPaperVo examRestartPaperVo = new ExamRestartPaperVo();
|
||||
// 如果继续考试,需要关闭之前的,重新开始ws
|
||||
String taskManagerId = loginUser.getId() + "_" + stuInTheExam.getTaskId() + "_" + stuInTheExam.getPaperId();
|
||||
taskManager.stopTask(taskManagerId);
|
||||
if (loginUser != null) {
|
||||
// 获取试卷详情
|
||||
ExamPaperVo examPaperVo = educationPaperQuService.selectPaperQuListByPaperId(stuInTheExam.getPaperId());
|
||||
// 获取剩余的时间
|
||||
String key = "userCache:" + stuInTheExam.getTaskId() + ":" + loginUser.getId();
|
||||
MonitorDO info = JsonUtils.parseObject(stringRedisTemplate.opsForValue().get(key), MonitorDO.class);
|
||||
if (info != null) {
|
||||
// 获取随机ID
|
||||
String temporaryId = info.getTemporaryId();
|
||||
// 获取开始时间
|
||||
String startTimeExam = info.getStartTime();
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
LocalDateTime targetTime = LocalDateTime.parse(startTimeExam, formatter);
|
||||
LocalDateTime currentTime = LocalDateTime.now();
|
||||
Duration duration = Duration.between(currentTime, targetTime);
|
||||
// 两者相差的时间
|
||||
long secondsDifference = duration.getSeconds();
|
||||
// 获取一共要考试多长时间
|
||||
long remainingTime = info.getRemainingTime();
|
||||
// 判断剩余时间是否大于等于两者相差的时间
|
||||
long times = remainingTime - secondsDifference;
|
||||
// 开启ws
|
||||
// 获取上传文件时间
|
||||
String time = examPaperVo.getEducationPaperParam().getUploadTime();
|
||||
// 将分钟继续转换成秒
|
||||
stuInTheExam.setTimes(Integer.parseInt(time) * 60);
|
||||
// 倒计时
|
||||
AtomicInteger countdown = new AtomicInteger((int) times);
|
||||
// 创建初始返回数据
|
||||
StuTheExamInfo stuTheExamInfo = new StuTheExamInfo();
|
||||
// 返回数据-剩余时间
|
||||
stuTheExamInfo.setTime(formatLongDuration(countdown.get()));
|
||||
// 返回数据-上传文件状态 0:上传;1:不上传
|
||||
stuTheExamInfo.setUpload(1);
|
||||
// 返回数据-结束考试 0:结束;1:不结束
|
||||
stuTheExamInfo.setEndStatus(1);
|
||||
// 返回数据-网络状态
|
||||
stuTheExamInfo.setNetwork("强");
|
||||
taskManager.startTask(stuInTheExam, stuTheExamInfo, token, countdown, new AtomicInteger(0), loginUser.getId() + "_" + stuInTheExam.getTaskId() + "_" + stuInTheExam.getPaperId());
|
||||
// 将数组的值进行复制
|
||||
BeanUtils.copyProperties(examPaperVo, examRestartPaperVo);
|
||||
examRestartPaperVo.setWsToken(token);
|
||||
// 查询学生文件下载地址
|
||||
examRestartPaperVo.setTemporaryId(temporaryId);
|
||||
List<StuPaperFileDO> stuPaperFileS = stuPaperFileService.findByStuIDAndPaperId(loginUser.getId(), stuInTheExam.getPaperId(), temporaryId);
|
||||
stuPaperFileS.forEach(stuPaperFileDO -> {
|
||||
if (stuPaperFileDO.getType() == 0) {
|
||||
// 将文件地址存放,方便前端继续下载处理
|
||||
examRestartPaperVo.setFileUrl(stuPaperFileDO.getUrl());
|
||||
}
|
||||
});
|
||||
return CommonResult.success(examRestartPaperVo);
|
||||
} else {
|
||||
return CommonResult.error(1_0001_001,"没有找到对应的考试信息");
|
||||
}
|
||||
}
|
||||
return CommonResult.error(1_0001_002,"没有找到对应的学生信息");
|
||||
}
|
||||
/**
|
||||
* 停止考试
|
||||
*
|
||||
* @return true
|
||||
*/
|
||||
@GetMapping("/stopExam")
|
||||
public CommonResult<Boolean> stopExam() {
|
||||
public CommonResult<Boolean> stopExam(@RequestParam("taskId") String taskId, @RequestParam("paperId") String paperId) {
|
||||
HttpServletRequest request = ServletUtils.getRequest();
|
||||
String userId = null;
|
||||
if (request != null) {
|
||||
userId = String.valueOf(SecurityFrameworkUtils.getLoginUserId());
|
||||
// 将userId 拼接 taskId 作为key
|
||||
// 防止不同试卷ID冲突
|
||||
userId += "_" + taskId + "_" + paperId;
|
||||
// 删除对应的线程池
|
||||
taskManager.stopTask(userId);
|
||||
return CommonResult.success(true);
|
||||
@@ -195,10 +293,6 @@ public class AutoToolsController {
|
||||
|
||||
// 时间转换
|
||||
public static String formatLongDuration(int totalSeconds) {
|
||||
int hours = totalSeconds / 3600;
|
||||
int minutes = (totalSeconds % 3600) / 60;
|
||||
int seconds = totalSeconds % 60;
|
||||
|
||||
return String.format("%02d:%02d:%02d", hours, minutes, seconds);
|
||||
return TaskManager.formatLongDuration(totalSeconds);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,34 @@
|
||||
package pc.exam.pp.module.judgement.controller.admin.autoTools.vo;
|
||||
|
||||
import lombok.Data;
|
||||
import pc.exam.pp.module.exam.controller.admin.paper.vo.StuInfoPaper;
|
||||
import pc.exam.pp.module.exam.dal.dataobject.EducationPaperParam;
|
||||
import pc.exam.pp.module.exam.dal.dataobject.EducationPaperScheme;
|
||||
import pc.exam.pp.module.exam.dal.dataobject.EducationPaperSession;
|
||||
import pc.exam.pp.module.exam.dal.dataobject.ExamQuestion;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class ExamRestartPaperVo {
|
||||
// 试卷iD
|
||||
String paperId;
|
||||
// 试卷编号
|
||||
String paperNum;
|
||||
// 试题列表
|
||||
List<ExamQuestion> examQuestionList;
|
||||
// 试卷方案
|
||||
List<EducationPaperScheme> educationPaperSchemeList;
|
||||
// 试卷参数
|
||||
EducationPaperParam educationPaperParam;
|
||||
// 试卷场次
|
||||
EducationPaperSession educationPaperSession;
|
||||
// 学生信息
|
||||
StuInfoPaper stuInfoPaper;
|
||||
// 试卷文件
|
||||
String fileUrl;
|
||||
// ws token
|
||||
String wsToken;
|
||||
// 随机ID
|
||||
String temporaryId;
|
||||
}
|
@@ -15,4 +15,6 @@ public class StuInTheExam {
|
||||
private String taskId;
|
||||
// 延迟时间 单位min
|
||||
private Integer delayTime;
|
||||
// 试卷ID
|
||||
private String paperId;
|
||||
}
|
||||
|
@@ -32,8 +32,8 @@ public class TaskManager {
|
||||
if (tasks.containsKey(userId)) {
|
||||
log.info("任务 {} 已存在,未重复启动", userId);
|
||||
// TODO 删除,重置倒计时
|
||||
tasks.remove(userId);
|
||||
// return;
|
||||
// tasks.remove(userId);
|
||||
return;
|
||||
}
|
||||
tasks.computeIfAbsent(userId, k -> {
|
||||
Runnable task = safe(() -> {
|
||||
@@ -44,6 +44,9 @@ public class TaskManager {
|
||||
if (current == stuInTheExam.getTimes()) {
|
||||
stuTheExamInfo.setUpload(0);
|
||||
counter.set(0);
|
||||
current = 0;
|
||||
} else {
|
||||
stuTheExamInfo.setUpload(1);
|
||||
}
|
||||
if (remaining <= 0) {
|
||||
ScheduledFuture<?> future = tasks.remove(userId);
|
||||
@@ -73,6 +76,14 @@ public class TaskManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**通过ID查询*/
|
||||
public String getTaskById(String userId) {
|
||||
return tasks.keySet().stream()
|
||||
.filter(key -> key.startsWith(userId + "_"))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
/** 全部停止(可选) */
|
||||
public void stopAll() {
|
||||
tasks.forEach((k, f) -> f.cancel(false));
|
||||
|
Reference in New Issue
Block a user