Compare commits

...

3 Commits

Author SHA1 Message Date
DESKTOP-9ERGOBP\任维炳
02bc650c1b 【修改】 1、新增项目启动清除所有的任务ID;2、修改ws send方法参数 2025-10-20 12:58:25 +08:00
DESKTOP-9ERGOBP\任维炳
ad2b0b510e 【修改】 修改学生端倒计时闪烁补充项 2025-10-20 12:25:30 +08:00
DESKTOP-9ERGOBP\任维炳
c708a30443 【修改】 修改考试剩余时间异常闪动问题 2025-10-20 11:02:57 +08:00
3 changed files with 61 additions and 18 deletions

View File

@@ -157,11 +157,9 @@ public class AutoToolsController {
securityProperties.getTokenHeader(), securityProperties.getTokenParameter()); securityProperties.getTokenHeader(), securityProperties.getTokenParameter());
// 获取登录用户 // 获取登录用户
LoginUser loginUser = SecurityFrameworkUtils.getLoginUser(); LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
// userId 是否存在 // 通过ID 直接停止
String wsKey = taskManager.getTaskById(String.valueOf(loginUser.getId())); if (loginUser != null) {
if (wsKey != null) { taskManager.stopTaskByUserId(String.valueOf(loginUser.getId()));
// 停止任务
taskManager.stopTask(wsKey);
} }
int startTime = 0; int startTime = 0;
// 查找对应的task // 查找对应的task
@@ -213,7 +211,9 @@ public class AutoToolsController {
// 返回数据-网络状态 // 返回数据-网络状态
stuTheExamInfo.setNetwork(""); stuTheExamInfo.setNetwork("");
// 创建对应的线程池 // 创建对应的线程池
taskManager.startTask(stuInTheExam, stuTheExamInfo, token, countdown, new AtomicInteger(0), loginUser.getId() + "_" + stuInTheExam.getTaskId() + "_" + stuInTheExam.getPaperId()); if (loginUser != null) {
taskManager.startTask(loginUser.getId(), stuInTheExam, stuTheExamInfo, token, countdown, new AtomicInteger(0), loginUser.getId() + "_" + stuInTheExam.getTaskId() + "_" + stuInTheExam.getPaperId());
}
return CommonResult.success(token); return CommonResult.success(token);
} }
return CommonResult.success("未登录"); return CommonResult.success("未登录");
@@ -261,8 +261,10 @@ public class AutoToolsController {
securityProperties.getTokenHeader(), securityProperties.getTokenParameter()); securityProperties.getTokenHeader(), securityProperties.getTokenParameter());
ExamRestartPaperVo examRestartPaperVo = new ExamRestartPaperVo(); ExamRestartPaperVo examRestartPaperVo = new ExamRestartPaperVo();
// 如果继续考试需要关闭之前的重新开始ws // 如果继续考试需要关闭之前的重新开始ws
String taskManagerId = loginUser.getId() + "_" + stuInTheExam.getTaskId() + "_" + stuInTheExam.getPaperId(); // 通过ID 直接停止
taskManager.stopTask(taskManagerId); if (loginUser != null) {
taskManager.stopTaskByUserId(String.valueOf(loginUser.getId()));
}
// 获取试卷详情 // 获取试卷详情
ExamPaperVo examPaperVo = educationPaperQuService.selectPaperQuListByPaperId(stuInTheExam.getPaperId()); ExamPaperVo examPaperVo = educationPaperQuService.selectPaperQuListByPaperId(stuInTheExam.getPaperId());
// 获取剩余的时间 // 获取剩余的时间
@@ -319,7 +321,7 @@ public class AutoToolsController {
stuTheExamInfo.setEndStatus(1); stuTheExamInfo.setEndStatus(1);
// 返回数据-网络状态 // 返回数据-网络状态
stuTheExamInfo.setNetwork(""); stuTheExamInfo.setNetwork("");
taskManager.startTask(stuInTheExam, stuTheExamInfo, token, countdown, new AtomicInteger(0), loginUser.getId() + "_" + stuInTheExam.getTaskId() + "_" + stuInTheExam.getPaperId()); taskManager.startTask(loginUser.getId(), stuInTheExam, stuTheExamInfo, token, countdown, new AtomicInteger(0), loginUser.getId() + "_" + stuInTheExam.getTaskId() + "_" + stuInTheExam.getPaperId());
// 将数组的值进行复制 // 将数组的值进行复制
BeanUtils.copyProperties(examPaperVo, examRestartPaperVo); BeanUtils.copyProperties(examPaperVo, examRestartPaperVo);
examRestartPaperVo.setWsToken(token); examRestartPaperVo.setWsToken(token);
@@ -353,6 +355,12 @@ public class AutoToolsController {
userId += "_" + taskId + "_" + paperId; userId += "_" + taskId + "_" + paperId;
// 删除对应的线程池 // 删除对应的线程池
taskManager.stopTask(userId); taskManager.stopTask(userId);
// 为了确保停止成功,笨办法在请求另一个停止接口
try {
taskManager.stopTaskByUserId(String.valueOf(userId));
} catch (Exception e) {
e.printStackTrace();
}
return CommonResult.success(true); return CommonResult.success(true);
} }
@@ -394,6 +402,8 @@ public class AutoToolsController {
stringRedisTemplate.opsForValue().set(key, JsonUtils.toJsonString(info)); stringRedisTemplate.opsForValue().set(key, JsonUtils.toJsonString(info));
monitorMapper.updateById(info); monitorMapper.updateById(info);
} }
// 删除对应任务
taskManager.stopTaskByUserId(userId);
return CommonResult.success(true); return CommonResult.success(true);
} }
@@ -404,13 +414,9 @@ public class AutoToolsController {
* @return true * @return true
*/ */
@GetMapping("/stopExamForAdmin") @GetMapping("/stopExamForAdmin")
public CommonResult<Boolean> stopExamForAdmin(@RequestParam("userId") String userId, @RequestParam("taskId") String taskId, @RequestParam("paperNum") String paperNum) { public CommonResult<Boolean> stopExamForAdmin(@RequestParam("userId") String userId) {
String paperId = educationPaperService.selectPaperByPaperNum(paperNum);
// 将userId 拼接 taskId 作为key
// 防止不同试卷ID冲突
userId += "_" + taskId + "_" + paperId;
// 删除对应的线程池 // 删除对应的线程池
taskManager.stopTask(userId); taskManager.stopTaskByUserId(userId);
return CommonResult.success(true); return CommonResult.success(true);
} }
@@ -495,7 +501,7 @@ public class AutoToolsController {
stuTheExamInfo.setEndStatus(1); stuTheExamInfo.setEndStatus(1);
// 返回数据-网络状态 // 返回数据-网络状态
stuTheExamInfo.setNetwork(""); stuTheExamInfo.setNetwork("");
taskManager.startTask(stuInTheExam, stuTheExamInfo, token, countdown, new AtomicInteger(0), stuId + "_" + stuInTheExam.getTaskId() + "_" + paperId); taskManager.startTask(Long.valueOf(stuId), stuInTheExam, stuTheExamInfo, token, countdown, new AtomicInteger(0), stuId + "_" + stuInTheExam.getTaskId() + "_" + paperId);
// 将数组的值进行复制 // 将数组的值进行复制
BeanUtils.copyProperties(examPaperVo, examRestartPaperVo); BeanUtils.copyProperties(examPaperVo, examRestartPaperVo);
examRestartPaperVo.setWsToken(token); examRestartPaperVo.setWsToken(token);

View File

@@ -29,7 +29,7 @@ public class TaskManager {
private final Map<String, ScheduledFuture<?>> tasks = new ConcurrentHashMap<>(); private final Map<String, ScheduledFuture<?>> tasks = new ConcurrentHashMap<>();
/** 开始任务(每秒执行一次) */ /** 开始任务(每秒执行一次) */
public void startTask(StuInTheExam stuInTheExam, StuTheExamInfo stuTheExamInfo, String token, AtomicInteger countdown, AtomicInteger counter, String userId) { public void startTask(Long userIds, StuInTheExam stuInTheExam, StuTheExamInfo stuTheExamInfo, String token, AtomicInteger countdown, AtomicInteger counter, String userId) {
// 判断 token 的线程是否存在,存在则不进行任何动作 // 判断 token 的线程是否存在,存在则不进行任何动作
if (tasks.containsKey(userId)) { if (tasks.containsKey(userId)) {
log.info("任务 {} 已存在,未重复启动", userId); log.info("任务 {} 已存在,未重复启动", userId);
@@ -59,7 +59,8 @@ public class TaskManager {
} }
} }
stuTheExamInfo.setTime(formatLongDuration(remaining)); stuTheExamInfo.setTime(formatLongDuration(remaining));
webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), "InTheExam", stuTheExamInfo); webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), userIds, "InTheExam", stuTheExamInfo);
// webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), "InTheExam", stuTheExamInfo);
}); });
return scheduler.scheduleAtFixedRate(task, 0, 1, TimeUnit.SECONDS); return scheduler.scheduleAtFixedRate(task, 0, 1, TimeUnit.SECONDS);
}); });
@@ -93,6 +94,18 @@ public class TaskManager {
.orElse(null); .orElse(null);
} }
/**通过ID结束任务*/
public void stopTaskByUserId(String userId) {
String taskId = tasks.keySet().stream()
.filter(key -> key.startsWith(userId + "_"))
.findFirst()
.orElse(null);
if (taskId != null) {
stopTask(taskId);
}
}
/** 全部停止(可选) */ /** 全部停止(可选) */
public void stopAll() { public void stopAll() {
tasks.forEach((k, f) -> f.cancel(false)); tasks.forEach((k, f) -> f.cancel(false));

View File

@@ -0,0 +1,24 @@
package pc.exam.pp.server.config;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import pc.exam.pp.module.judgement.service.TaskManager;
@Slf4j
@Component
public class TaskToStop {
@Resource
TaskManager taskManager;
@PostConstruct
public void init() {
// 清除所有的任务
taskManager.stopAll();
log.info("✅ 已经清除所有任务ID");
}
}