【新增】 1、监控页面支持考试中的考试增加考试时间

This commit is contained in:
dlaren
2025-09-16 22:59:29 +08:00
parent fddff098ca
commit 355c7e2b45
8 changed files with 150 additions and 106 deletions

View File

@@ -209,7 +209,7 @@ public class MonitorController {
@PostMapping("/updateMonitorStatus") @PostMapping("/updateMonitorStatus")
@Operation(summary = "改变考生状态") @Operation(summary = "改变考生状态")
public CommonResult<Boolean> updateMonitorStatus(@Valid @RequestBody StuMonitorStatusVo stuMonitorStatusVo) { public CommonResult<MonitorWsVo> updateMonitorStatus(@Valid @RequestBody StuMonitorStatusVo stuMonitorStatusVo) {
return success(monitorService.updateMonitorStatus(stuMonitorStatusVo)); return success(monitorService.updateMonitorStatus(stuMonitorStatusVo));
} }

View File

@@ -3,10 +3,13 @@ package pc.exam.pp.module.exam.controller.admin.monitor.vo;
import com.baomidou.mybatisplus.annotation.TableLogic; import com.baomidou.mybatisplus.annotation.TableLogic;
import lombok.*; import lombok.*;
import java.util.*; import java.util.*;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import pc.exam.pp.framework.common.pojo.PageParam; import pc.exam.pp.framework.common.pojo.PageParam;
import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import static pc.exam.pp.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; import static pc.exam.pp.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@@ -54,4 +57,6 @@ private LocalDateTime[] remainingTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime; private LocalDateTime[] createTime;
} }

View File

@@ -48,8 +48,12 @@ public class MonitorRespVO {
@ExcelProperty(value = "剩余时间", converter = SecondsToTimeConverter.class) @ExcelProperty(value = "剩余时间", converter = SecondsToTimeConverter.class)
private String remainingTime; private String remainingTime;
@ExcelProperty("创建时间")
private LocalDateTime createTime; private LocalDateTime createTime;
@ExcelProperty("开始时间")
private String startTime;
@ExcelProperty("结束时间")
private String endTime;
} }

View File

@@ -0,0 +1,16 @@
package pc.exam.pp.module.exam.controller.admin.monitor.vo;
import lombok.Data;
@Data
public class MonitorWsVo {
private String type;
private String stuId;
private String taskId;
private String paperNum;
}

View File

@@ -9,4 +9,5 @@ import java.util.List;
public class StuMonitorStatusVo { public class StuMonitorStatusVo {
private List<String> monitorIds; private List<String> monitorIds;
private String status; private String status;
private String times;
} }

View File

@@ -75,12 +75,16 @@ public class MonitorDO extends BaseDO {
* 临时ID * 临时ID
*/ */
private String temporaryId; private String temporaryId;
/** /**
* 开始时间 * 开始时间
*/ */
private String startTime; private String startTime;
/**
* 结束时间
*/
private String endTime;
/** /**
* 交互时间 * 交互时间
*/ */

View File

@@ -66,5 +66,5 @@ public interface MonitorService {
List<EducationPaperTask> getPaperTaskList(String id); List<EducationPaperTask> getPaperTaskList(String id);
//改变考生状态 //改变考生状态
Boolean updateMonitorStatus(StuMonitorStatusVo stuMonitorStatusVo); MonitorWsVo updateMonitorStatus(StuMonitorStatusVo stuMonitorStatusVo);
} }

View File

@@ -55,7 +55,7 @@ import static pc.exam.pp.module.system.enums.ErrorCodeConstants.MONITOR_NOT_EXIS
@Service @Service
@Validated @Validated
public class MonitorServiceImpl implements MonitorService { public class MonitorServiceImpl implements MonitorService {
@Autowired @Resource
private RedisTemplate redisTemplate; private RedisTemplate redisTemplate;
@Resource @Resource
private MonitorMapper monitorMapper; private MonitorMapper monitorMapper;
@@ -309,6 +309,9 @@ public class MonitorServiceImpl implements MonitorService {
long finalRemaining = Math.min(remainingSeconds, examDurationSeconds); long finalRemaining = Math.min(remainingSeconds, examDurationSeconds);
// 4. 设置和返回 // 4. 设置和返回
info.setRemainingTime(finalRemaining); info.setRemainingTime(finalRemaining);
// 5. 通过计算获取endTime考试结束时间
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
info.setEndTime(end.format(fmt));
// 判分后更新记录 // 判分后更新记录
monitorMapper.updateById(info); monitorMapper.updateById(info);
return finalRemaining; return finalRemaining;
@@ -319,6 +322,12 @@ public class MonitorServiceImpl implements MonitorService {
//开启测评时长限制 没开启场次 -直接返回测评时长 //开启测评时长限制 没开启场次 -直接返回测评时长
if ("1".equals(educationPaperParam.getIsSession()) && "0".equals(educationPaperParam.getIsTime())) { if ("1".equals(educationPaperParam.getIsSession()) && "0".equals(educationPaperParam.getIsTime())) {
info.setRemainingTime((long) examTime.toLocalTime().toSecondOfDay()); info.setRemainingTime((long) examTime.toLocalTime().toSecondOfDay());
// 通过计算获取endTime考试结束时间
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime now = LocalDateTime.now(); // 本地日期时间
LocalDateTime target = now.plusSeconds((long) examTime.toLocalTime().toSecondOfDay());
// 没有考场更新结束时间
info.setEndTime(target.format(fmt));
stringRedisTemplate.opsForValue().set("userCache:" + stuMonitorPaperVo.getTaskId() + ":" + stuMonitorPaperVo.getStuId(), JsonUtils.toJsonString(info)); stringRedisTemplate.opsForValue().set("userCache:" + stuMonitorPaperVo.getTaskId() + ":" + stuMonitorPaperVo.getStuId(), JsonUtils.toJsonString(info));
monitorMapper.updateById(info); monitorMapper.updateById(info);
return (long) examTime.toLocalTime().toSecondOfDay(); return (long) examTime.toLocalTime().toSecondOfDay();
@@ -367,8 +376,9 @@ public class MonitorServiceImpl implements MonitorService {
} }
// 重置开始时间&交互时间 // 重置开始时间&交互时间
if (info != null) { if (info != null) {
info.setStartTime(null); info.setStartTime("");
info.setInteractiveTime(null); info.setInteractiveTime("");
info.setEndTime("");
} }
MonitorDO monitorDOs = null; MonitorDO monitorDOs = null;
if (info != null) { if (info != null) {
@@ -438,86 +448,70 @@ public class MonitorServiceImpl implements MonitorService {
} }
@Override @Override
public Boolean updateMonitorStatus(StuMonitorStatusVo stuMonitorStatusVo) { public MonitorWsVo updateMonitorStatus(StuMonitorStatusVo stuMonitorStatusVo) {
MonitorWsVo monitorWsVo = new MonitorWsVo();
String status = stuMonitorStatusVo.getStatus(); String status = stuMonitorStatusVo.getStatus();
String times = stuMonitorStatusVo.getTimes();
List<String> monitorIds = stuMonitorStatusVo.getMonitorIds(); List<String> monitorIds = stuMonitorStatusVo.getMonitorIds();
if ("1".equals(status) || "0".equals(status)) {
//新增或更新
for (String monitorId : monitorIds) { for (String monitorId : monitorIds) {
MonitorDO monitorDO = monitorMapper.selectById(monitorId); MonitorDO monitorDO = monitorMapper.selectById(monitorId);
// 任务ID
String taskId = monitorDO.getTaskId(); String taskId = monitorDO.getTaskId();
// 学号
String stuId = monitorDO.getStuId(); String stuId = monitorDO.getStuId();
// redis_key
String key = "userCache:" + taskId + ":" + stuId; String key = "userCache:" + taskId + ":" + stuId;
monitorDO.setExamStatus(status); // 获取缓存数据
monitorMapper.updateById(monitorDO);
MonitorDO info = JsonUtils.parseObject(stringRedisTemplate.opsForValue().get(key), MonitorDO.class); MonitorDO info = JsonUtils.parseObject(stringRedisTemplate.opsForValue().get(key), MonitorDO.class);
EducationPaperParam educationPaperParam = educationPaperParamMapper.selectEducationPaperParamByTaskId(taskId); // 如果考试状态存在,更新考试状态
Time examTime = educationPaperParam.getExamTime(); if (status != null) {
if (info != null) {
if (info == null) { info.setExamStatus(status);
MonitorDO monitorDO1 = monitorMapper.selectOne(new QueryWrapper<MonitorDO>().eq("stu_id", stuId).eq("task_id", taskId)); // 如果状态是0和2清除剩余时间
PersonRepDto personRepDto = educationPaperPersonMapper.selectUserById(stuId); if ("0".equals(status) || "2".equals(status)) {
String name = educationPaperTaskMapper.selectEducationPaperTaskNameByid(taskId); info.setRemainingTime(0L);
EducationPaperTask educationPaperTask = educationPaperTaskMapper.selectEducationPaperTaskByTaskId(taskId);
monitorDO1.setScore("0");
monitorDO1.setTaskId(taskId);
monitorDO1.setTaskType(educationPaperTask.getTaskType());
monitorDO1.setExamStatus(status);
monitorDO1.setPaperNum("");
monitorDO1.setIp("");
monitorDO1.setStuId(stuId);
monitorDO1.setUsername(personRepDto.getUsername());
monitorDO1.setNickname(personRepDto.getNickname());
//如果开启了 时长限制 或者考场
if ("0".equals(educationPaperParam.getIsTime()) || "0".equals(educationPaperParam.getIsSession())) {
monitorDO1.setRemainingTime((long) examTime.toLocalTime().toSecondOfDay());
}
stringRedisTemplate.opsForValue().set(key, JsonUtils.toJsonString(monitorDO1));
monitorMapper.updateById(monitorDO1);
} else {
//如果开启了 时长限制 或者考场
if ("0".equals(educationPaperParam.getIsTime()) || "0".equals(educationPaperParam.getIsSession())) {
info.setRemainingTime((long) examTime.toLocalTime().toSecondOfDay());
}
info.setScore("0");
info.setPaperNum(""); info.setPaperNum("");
info.setIp(""); info.setIp("");
info.setExamStatus(status); info.setStartTime("");
info.setEndTime("");
info.setInteractiveTime("");
// 更新
stringRedisTemplate.opsForValue().set(key, JsonUtils.toJsonString(info)); stringRedisTemplate.opsForValue().set(key, JsonUtils.toJsonString(info));
monitorMapper.updateById(info);
monitorWsVo.setStuId(stuId);
monitorWsVo.setType("STOP");
monitorWsVo.setTaskId(taskId);
monitorWsVo.setPaperNum(info.getPaperNum());
return monitorWsVo;
} }
// 如果是考试状态1更新剩余时间
if ("1".equals(status)) {
} long time = parseTimeToSeconds(times);
// 当考试中的状态的时候才获取times字段
} long nowTimes = info.getRemainingTime();
info.setRemainingTime(nowTimes + time);
if ("2".equals(status)) { // 更新结束时间
//删除 String endTime = info.getEndTime();
for (String monitorId : monitorIds) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
MonitorDO monitorDO = monitorMapper.selectById(monitorId); LocalDateTime targetTime = LocalDateTime.parse(endTime, formatter);
String taskId = monitorDO.getTaskId(); LocalDateTime newTime = targetTime.plusSeconds(time);
String stuId = monitorDO.getStuId(); String newEndTimeStr = newTime.format(formatter);
String key = "userCache:" + taskId + ":" + stuId; info.setEndTime(newEndTimeStr);
monitorDO.setRemainingTime(0L); // 更新
if ("0".equals(monitorDO.getTaskType())) { stringRedisTemplate.opsForValue().set(key, JsonUtils.toJsonString(info));
monitorDO.setExamStatus("0"); monitorMapper.updateById(info);
stringRedisTemplate.opsForValue().set(key, JsonUtils.toJsonString(monitorDO)); monitorWsVo.setStuId(stuId);
monitorWsVo.setType("RESTART");
} else { monitorWsVo.setTaskId(taskId);
monitorDO.setExamStatus(status); monitorWsVo.setPaperNum(info.getPaperNum());
redisTemplate.delete(key); return monitorWsVo;
}
monitorMapper.updateById(monitorDO);
} }
} }
return true;
} }
}
return monitorWsVo;
}
public List<TentSpecialy> filterSpecialtyList(List<TentSpecialy> inputList) { public List<TentSpecialy> filterSpecialtyList(List<TentSpecialy> inputList) {
if (inputList == null || inputList.isEmpty()) { if (inputList == null || inputList.isEmpty()) {
@@ -544,5 +538,25 @@ public class MonitorServiceImpl implements MonitorService {
}).collect(Collectors.toList()); }).collect(Collectors.toList());
} }
public static long parseTimeToSeconds(String time) {
if (time == null) throw new IllegalArgumentException("time is null");
String t = time.trim();
if (t.isEmpty()) throw new IllegalArgumentException("time is empty");
String[] parts = t.split(":");
if (parts.length < 1 || parts.length > 3) {
throw new IllegalArgumentException("Unsupported time format: " + time);
}
long total = 0;
for (String p : parts) {
if (!p.matches("\\d+")) {
throw new IllegalArgumentException("Invalid numeric part in time: " + p);
}
int value = Integer.parseInt(p);
if (value < 0) throw new IllegalArgumentException("Negative value not allowed: " + p);
total = total * 60 + value;
}
return total;
}
} }