src/main/java/com/mindskip/xzs/controller/admin/ExamMissController.java
New file @@ -0,0 +1,20 @@ package com.mindskip.xzs.controller.admin; import com.mindskip.xzs.service.ExamMissService; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.RestController; /** * @author gonghl * @since 2024/5/9 下午 5:58 */ @RestController @RequiredArgsConstructor public class ExamMissController { private final ExamMissService examMissService; } src/main/java/com/mindskip/xzs/controller/admin/ExamPaperController.java
@@ -1,11 +1,11 @@ package com.mindskip.xzs.controller.admin; import com.github.pagehelper.PageInfo; import com.mindskip.xzs.base.BaseApiController; import com.mindskip.xzs.base.RestResponse; import com.mindskip.xzs.domain.ExamPaper; import com.mindskip.xzs.domain.ExamPaperSubject; import com.mindskip.xzs.domain.vo.PaperExcelVO; import com.mindskip.xzs.domain.vo.UserCountExcelVO; import com.mindskip.xzs.service.ExamPaperDepartmentService; import com.mindskip.xzs.service.ExamPaperService; import com.mindskip.xzs.service.ExamPaperSubjectService; @@ -13,11 +13,10 @@ import com.mindskip.xzs.utility.DateTimeUtil; import com.mindskip.xzs.utility.PageInfoHelper; import com.mindskip.xzs.utility.excel.ExcelUtils; import com.mindskip.xzs.viewmodel.admin.exam.ExamPaperEditRequestVM; import com.mindskip.xzs.viewmodel.admin.exam.ExamPaperEditRequestVO; import com.mindskip.xzs.viewmodel.admin.exam.ExamPaperPageRequestVM; import com.mindskip.xzs.viewmodel.admin.exam.ExamPaperEditRequestVM; import com.mindskip.xzs.viewmodel.admin.exam.ExamResponseVM; import com.github.pagehelper.PageInfo; import lombok.SneakyThrows; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @@ -87,6 +86,11 @@ model.setUserIds(userIds); ExamPaper examPaper = examPaperService.savePaperFromVM(model, getCurrentUser()); ExamPaperEditRequestVO newVM = examPaperService.examPaperToVM(examPaper.getId()); // 加入延时队列,定时试卷结束时记录缺考学生 if (examPaper.getPaperType() == 4) { examPaperService.addTimeTask(examPaper); } return RestResponse.ok(newVM); } src/main/java/com/mindskip/xzs/controller/student/ExamPaperAnswerController.java
@@ -1,5 +1,6 @@ package com.mindskip.xzs.controller.student; import com.github.pagehelper.PageInfo; import com.mindskip.xzs.base.BaseApiController; import com.mindskip.xzs.base.RestResponse; import com.mindskip.xzs.domain.*; @@ -10,14 +11,11 @@ import com.mindskip.xzs.utility.DateTimeUtil; import com.mindskip.xzs.utility.ExamUtil; import com.mindskip.xzs.utility.PageInfoHelper; import com.mindskip.xzs.viewmodel.admin.exam.ExamPaperEditRequestVM; import com.mindskip.xzs.viewmodel.admin.exam.ExamPaperEditRequestVO; import com.mindskip.xzs.viewmodel.student.exam.ExamPaperReadVM; import com.mindskip.xzs.viewmodel.student.exam.ExamPaperReadVO; import com.mindskip.xzs.viewmodel.student.exam.ExamPaperSubmitVM; import com.mindskip.xzs.viewmodel.student.exampaper.ExamPaperAnswerPageResponseVM; import com.mindskip.xzs.viewmodel.student.exampaper.ExamPaperAnswerPageVM; import com.github.pagehelper.PageInfo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; import org.springframework.web.bind.annotation.*; @@ -36,15 +34,17 @@ private final ApplicationEventPublisher eventPublisher; private final ExamPaperSubjectService examPaperSubjectService; private final ExamTemplatesUserCountService examTemplatesUserCountService; private final ExamMissService examMissService; @Autowired public ExamPaperAnswerController(ExamPaperAnswerService examPaperAnswerService, ExamPaperService examPaperService, SubjectService subjectService, ApplicationEventPublisher eventPublisher, ExamPaperSubjectService examPaperSubjectService, ExamTemplatesUserCountService examTemplatesUserCountService) { public ExamPaperAnswerController(ExamPaperAnswerService examPaperAnswerService, ExamPaperService examPaperService, SubjectService subjectService, ApplicationEventPublisher eventPublisher, ExamPaperSubjectService examPaperSubjectService, ExamTemplatesUserCountService examTemplatesUserCountService, ExamMissService examMissService) { this.examPaperAnswerService = examPaperAnswerService; this.examPaperService = examPaperService; this.subjectService = subjectService; this.eventPublisher = eventPublisher; this.examPaperSubjectService = examPaperSubjectService; this.examTemplatesUserCountService = examTemplatesUserCountService; this.examMissService = examMissService; } @@ -99,6 +99,14 @@ examTemplatesUserCount.setExamTemplatesId(examPaperSubmitVM.getTemplatesId()); examTemplatesUserCountService.add(examTemplatesUserCount); } // 自动提交定义为缺考 if (examPaperSubmitVM.isAutoCommit()) { ExamMiss examMiss = new ExamMiss(); examMiss.setExamId(examPaperSubmitVM.getId()); examMiss.setUserId(user.getId()); examMissService.save(examMiss); } return RestResponse.ok(scoreVm); } src/main/java/com/mindskip/xzs/domain/ExamMiss.java
New file @@ -0,0 +1,25 @@ package com.mindskip.xzs.domain; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import java.io.Serializable; /** * @author gonghl */ @TableName(value = "t_exam_miss") @Data public class ExamMiss implements Serializable { @TableId(type = IdType.AUTO) private Integer id; private Integer examId; private Integer userId; private static final long serialVersionUID = 1L; } src/main/java/com/mindskip/xzs/domain/User.java
@@ -80,7 +80,13 @@ */ private String deptAdmin; /** * 状况 */ private UserConditionEnum condition; /** * 具体情况 */ private String conditionDetail; } src/main/java/com/mindskip/xzs/domain/vo/ExamMissVO.java
New file @@ -0,0 +1,24 @@ package com.mindskip.xzs.domain.vo; import lombok.Data; import java.io.Serializable; /** * @author gonghl */ @Data public class ExamMissVO implements Serializable { private Integer id; private Integer examId; private Integer examName; private Integer userId; private Integer userName; private static final long serialVersionUID = 1L; } src/main/java/com/mindskip/xzs/queue/ExamPaperTimeTask.java
New file @@ -0,0 +1,31 @@ package com.mindskip.xzs.queue; import lombok.Getter; import lombok.Setter; import java.util.concurrent.Delayed; import java.util.concurrent.TimeUnit; /** * @author gonghl */ @Getter @Setter public class ExamPaperTimeTask implements Delayed { private long examPaperId; private long expiry; @Override public long getDelay(TimeUnit unit) { return unit.convert(expiry - System.currentTimeMillis(), TimeUnit.MILLISECONDS); } @Override public int compareTo(Delayed o) { return Long.compare(expiry, ((ExamPaperTimeTask) o).expiry); } } src/main/java/com/mindskip/xzs/repository/ExamMissMapper.java
New file @@ -0,0 +1,20 @@ package com.mindskip.xzs.repository; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.mindskip.xzs.domain.ExamMiss; import org.apache.ibatis.annotations.Mapper; /** * @author gonghl * @description 针对表【t_exam_miss(试卷缺考)】的数据库操作Mapper * @createDate 2024-05-09 15:41:36 * @Entity com.mindskip.xzs.examMiss.ExamMiss */ @Mapper public interface ExamMissMapper extends BaseMapper<ExamMiss> { } src/main/java/com/mindskip/xzs/repository/ExamPaperMapper.java
@@ -1,5 +1,6 @@ package com.mindskip.xzs.repository; import com.mindskip.xzs.domain.ExamMiss; import com.mindskip.xzs.domain.ExamPaper; import com.mindskip.xzs.domain.other.KeyValue; import com.mindskip.xzs.domain.vo.PaperExcelVO; @@ -38,4 +39,7 @@ List<PaperExcelVO> getPaperExcelById(@Param("id") Integer id); void saveMissExamUser(long examPaperId); List<ExamPaper> selectTimeTaskPaper(Date time); } src/main/java/com/mindskip/xzs/service/ExamMissService.java
New file @@ -0,0 +1,13 @@ package com.mindskip.xzs.service; import com.baomidou.mybatisplus.extension.service.IService; import com.mindskip.xzs.domain.ExamMiss; /** * @author gonghl * @description 针对表【t_exam_miss(试卷缺考)】的数据库操作Service * @createDate 2024-05-09 15:41:36 */ public interface ExamMissService extends IService<ExamMiss> { } src/main/java/com/mindskip/xzs/service/ExamPaperService.java
@@ -37,4 +37,8 @@ List<ExamPaper> gets(Integer[] ids); List<PaperExcelVO> getPaperExcelById(Integer id); void addTimeTask(ExamPaper examPaper); void saveMissExamUser(long examPaperId); } src/main/java/com/mindskip/xzs/service/impl/ExamMissServiceImpl.java
New file @@ -0,0 +1,21 @@ package com.mindskip.xzs.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.mindskip.xzs.domain.ExamMiss; import com.mindskip.xzs.repository.ExamMissMapper; import com.mindskip.xzs.service.ExamMissService; import org.springframework.stereotype.Service; /** * @author gonghl * @description 针对表【t_exam_miss(试卷缺考)】的数据库操作Service实现 * @createDate 2024-05-09 15:41:36 */ @Service public class ExamMissServiceImpl extends ServiceImpl<ExamMissMapper, ExamMiss> implements ExamMissService { } src/main/java/com/mindskip/xzs/service/impl/ExamPaperServiceImpl.java
@@ -1,41 +1,41 @@ package com.mindskip.xzs.service.impl; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import com.mindskip.xzs.configuration.spring.exception.QuestionException; import com.mindskip.xzs.domain.*; import com.mindskip.xzs.domain.TextContent; import com.mindskip.xzs.domain.enums.ExamPaperTypeEnum; import com.mindskip.xzs.domain.enums.QuestionTypeEnum; import com.mindskip.xzs.domain.exam.ExamPaperQuestionItemObject; import com.mindskip.xzs.domain.exam.ExamPaperTitleItemObject; import com.mindskip.xzs.domain.other.KeyValue; import com.mindskip.xzs.domain.vo.PaperExcelVO; import com.mindskip.xzs.queue.ExamPaperTimeTask; import com.mindskip.xzs.repository.ExamPaperMapper; import com.mindskip.xzs.repository.QuestionMapper; import com.mindskip.xzs.repository.UserDepartmentMapper; import com.mindskip.xzs.service.*; import com.mindskip.xzs.service.enums.ActionEnum; import com.mindskip.xzs.utility.DateTimeUtil; import com.mindskip.xzs.utility.ExamUtil; import com.mindskip.xzs.utility.JsonUtil; import com.mindskip.xzs.utility.ModelMapperSingle; import com.mindskip.xzs.utility.ExamUtil; import com.mindskip.xzs.utility.minio.DateUtils; import com.mindskip.xzs.viewmodel.admin.exam.*; import com.mindskip.xzs.viewmodel.admin.question.ExamQuestionVO; import com.mindskip.xzs.viewmodel.admin.question.QuestionEditRequestVM; import com.mindskip.xzs.viewmodel.student.dashboard.PaperFilter; import com.mindskip.xzs.viewmodel.student.dashboard.PaperInfo; import com.mindskip.xzs.viewmodel.student.exam.ExamPaperPageVM; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import com.mindskip.xzs.domain.ExamPaper; import com.mindskip.xzs.domain.Question; import com.mindskip.xzs.domain.User; import org.modelmapper.ModelMapper; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.PostConstruct; import java.util.*; import java.util.concurrent.DelayQueue; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; @@ -55,8 +55,24 @@ private final UserService userService; private final UserDepartmentMapper userDepartmentMapper; private final DepartmentService departmentService; private final DelayQueue<ExamPaperTimeTask> QUEUE = new DelayQueue<>(); /** * 将进行中的定时试卷加入到队列中,并启动一个线程来轮询队列 */ @PostConstruct public void pollQueue() { examPaperMapper.selectTimeTaskPaper(DateUtils.getNowDate()).forEach(this::addTimeTask); new Thread(() -> { try { ExamPaperTimeTask task = QUEUE.take(); saveMissExamUser(task.getExamPaperId()); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }).start(); } @Autowired public ExamPaperServiceImpl(ExamPaperMapper examPaperMapper, QuestionMapper questionMapper, TextContentService textContentService, QuestionService questionService, SubjectService subjectService, ExamPaperDepartmentService examPaperDepartmentService, ExamPaperSubjectService examPaperSubjectService, QuestionSubjectService questionSubjectService, ExamPaperUserService examPaperUserService, UserService userService, UserDepartmentMapper userDepartmentMapper, DepartmentService departmentService) { @@ -599,4 +615,17 @@ return randomNumber; } @Override public void addTimeTask(ExamPaper examPaper) { ExamPaperTimeTask examPaperTimeTask = new ExamPaperTimeTask(); examPaperTimeTask.setExamPaperId(examPaper.getId()); examPaperTimeTask.setExpiry(examPaper.getLimitEndTime().getTime()); QUEUE.add(examPaperTimeTask); } @Override public void saveMissExamUser(long examPaperId) { examPaperMapper.saveMissExamUser(examPaperId); } } src/main/java/com/mindskip/xzs/viewmodel/student/exam/ExamPaperSubmitVM.java
@@ -23,6 +23,19 @@ //模板id private Integer templatesId; /** * 是否时间结束自动提交 */ private boolean isAutoCommit; public boolean isAutoCommit() { return isAutoCommit; } public void setAutoCommit(boolean autoCommit) { isAutoCommit = autoCommit; } public Integer getId() { return id; } src/main/resources/mapper/ExamMissMapper.xml
New file @@ -0,0 +1,16 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.mindskip.xzs.repository.ExamMissMapper"> <resultMap id="BaseResultMap" type="com.mindskip.xzs.domain.ExamMiss"> <id property="id" column="id" jdbcType="INTEGER"/> <result property="examId" column="exam_id" jdbcType="INTEGER"/> <result property="userId" column="user_id" jdbcType="INTEGER"/> </resultMap> <sql id="Base_Column_List"> id,exam_id,user_id </sql> </mapper> src/main/resources/mapper/ExamPaperMapper.xml
@@ -423,4 +423,19 @@ where a.exam_paper_id = #{id} </select> <select id="saveMissExamUser" resultType="com.mindskip.xzs.domain.ExamMiss"> INSERT INTO t_exam_miss(exam_id, user_id) SELECT a.id, b.user_id FROM t_exam_paper a left join t_exam_paper_user b on a.id = b.exam_paper_id left join t_exam_paper_answer c on a.id = c.exam_paper_id and c.create_user = b.user_id WHERE a.id = #{examPaperId} and c.id is null </select> <select id="selectTimeTaskPaper" resultType="com.mindskip.xzs.domain.ExamPaper"> select id, limit_end_time from t_exam_paper where paper_type = 4 and limit_end_time >= #{time} and deleted = 0 </select> </mapper>