Browse Source

联考版-迭代

xiaof 4 năm trước cách đây
mục cha
commit
b7171f4713

+ 1 - 1
stmms-ms-admin/src/main/java/cn/com/qmth/stmms/ms/admin/service/TrialService.java

@@ -205,6 +205,6 @@ public class TrialService {
                 cacheService.deleteTokenCache(user.getId().toString());
             }
         }
-        dbBackupUtils.startBackup("试评");
+        dbBackupUtils.startBackup(workId,"试评");
     }
 }

+ 10 - 6
stmms-ms-commons/src/main/java/cn/com/qmth/stmms/ms/commons/utils/DbBackupUtils.java

@@ -26,15 +26,19 @@ public class DbBackupUtils {
     @Autowired
     DbConfig dbConfig;
 
-    public void startBackup(String name) {
-        service.submit(dbBackUp(name));
+    public void startBackup(Long workId, String stage) {
+        service.submit(dbBackUp(workId, stage));
     }
 
-    public Runnable dbBackUp(String name) {
+    public Runnable dbBackUp(Long workId, String stage) {
         return () -> {
-            String pathSql = name + "-" + dbConfig.getDbName() + "-" + DateUtils.formatDate(new Date(), "yyyyMMddHHmmss") + ".sql";
-            File fileSql = new File(pathSql);
+            String path = "beifen";
+            String pathSql = workId + "-" + stage + "-" + DateUtils.formatDate(new Date(), "yyyyMMddHHmmss") + ".sql";
+            File fileSql = new File(path, pathSql);
             try {
+                if (!fileSql.getParentFile().exists()) {
+                    fileSql.getParentFile().mkdirs();
+                }
                 //创建备份sql文件
                 if (!fileSql.exists()) {
                     fileSql.createNewFile();
@@ -46,7 +50,7 @@ public class DbBackupUtils {
                 sb.append(" -u" + dbConfig.getUserName());
                 sb.append(" -p" + dbConfig.getPassword());
                 sb.append(" " + dbConfig.getDbName() + " >");
-                sb.append(pathSql);
+                sb.append(fileSql.getPath());
                 LOGGER.info("cmd命令为:{},开始备份数据库:" + sb.toString(), dbConfig.getDbName());
                 Runtime runtime = Runtime.getRuntime();
                 Process process = runtime.exec("cmd /c" + sb.toString());

+ 6 - 0
stmms-ms-core/src/main/java/cn/com/qmth/stmms/ms/core/repository/MarkUserRepo.java

@@ -6,6 +6,8 @@ import cn.com.qmth.stmms.ms.core.vo.Subject;
 
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
 
 import java.util.List;
 
@@ -27,4 +29,8 @@ public interface MarkUserRepo extends JpaRepository<MarkUser,Long>, JpaSpecifica
 	List<MarkUser> findByRole(Role role);
 
     List<MarkUser> findByWorkIdAndSubject(Long workId, Subject subject);
+
+	@Modifying
+	@Query("update MarkUser set groupId = null where workId = ?1 and subject = ?2")
+    void updateByWorkIdAndSubject(Long workId, Subject subject);
 }

+ 8 - 0
stmms-ms-core/src/main/java/cn/com/qmth/stmms/ms/core/repository/PaperRepo.java

@@ -384,5 +384,13 @@ public interface PaperRepo extends JpaRepository<Paper, Long>, JpaSpecificationE
 
     long countByWorkIdAndQuestionIdAndIsMissingIsFalse(Long workId, Long questionId);
 
+    @Modifying
+    @Query(value = "update paper p set p.score = null, p.score_batch_no = null, p.is_shift = false, p.is_shift_score = false where p.work_id = ?1 and p.subject = ?2", nativeQuery = true)
+    void updateScoreByWorkIdAndSubject(Long workId, String name);
+
+    @Modifying
+    @Query(value = "update paper p set p.level = null, p.redo_level = null, p.batch_no = null, p.is_active = false, p.is_arbitrated = false, p.is_manual = false, p.is_rejected = false, p.is_tagged = false, p.mark_by_leader = false, p.is_one_click = false where p.work_id = ?1 and p.subject = ?2", nativeQuery = true)
+    void updateLevelByWorkIdAndSubject(Long workId, String name);
+
 //    List<Paper> findByWorkIdAndSubjectAndInspectRange(Long workId, Subject subject, Long inspectRange);
 }

+ 2 - 0
stmms-ms-core/src/main/java/cn/com/qmth/stmms/ms/core/repository/TaskPublishSettingRepo.java

@@ -31,4 +31,6 @@ public interface TaskPublishSettingRepo extends JpaRepository<TaskPublishSetting
     Integer maxPublishCountByQuestionId(Long workId, Long questionId, String name);
 
     List<TaskPublishSetting> findByWorkIdAndSubjectAndPublishCount(Long workId, String name, int max);
+
+    void deleteByWorkIdAndSubjectAndPublishCountNot(Long workId, String name, int publishCount);
 }

+ 20 - 6
stmms-ms-log/src/main/java/cn/com/qmth/stmms/ms/log/aop/MarkLogAop.java

@@ -194,11 +194,13 @@ public class MarkLogAop {
         JSONArray jsonArgsArray = (JSONArray) map.get(PARAM_ARGS);
         MarkUser markUser = (MarkUser) map.get(MARK_USER);
         JSONObject aopResult = JSONObject.parseObject(JSONObject.toJSONString(result));
-        boolean isRejected = false, oldRejected = false;
+        boolean isRejected = false, oldRejected = false, oldShift = false, oldShiftScore = false;
         if (Objects.nonNull(aopResult)) {
             MarkTaskDTO resultBody = JSONObject.parseObject(((JSONObject) aopResult.get(BODY)).toJSONString(), MarkTaskDTO.class);
             isRejected = resultBody.isRejected();//新的是否撤档
             oldRejected = resultBody.isOldRejected();//旧的是否撤档
+            oldShift = resultBody.isShift();//旧的改档
+            oldShiftScore = resultBody.isShiftScore();//旧的改档打分
         }
         JSONObject jsonObject = (JSONObject) jsonArgsArray.get(0);
         Paper paper = JSONObject.parseObject(((JSONObject) jsonObject.get(PAPER)).toJSONString(), Paper.class);
@@ -210,9 +212,17 @@ public class MarkLogAop {
         if (markStage.ordinal() == 1 && paper.isMarkByLeader()) {//分档,如果已经有科组长定档,则不允许评卷员再分档
             return;
         } else if (markStage.ordinal() == 1 && oldRejected && !isRejected) {//档位打回回评
-            operType = MarkLogOperType.CALLBACK_ONCE_LEVEL.getId();
+            if(oldShift){
+                operType = MarkLogOperType.CHANGE_LEVEL.getId();
+            } else {
+                operType = MarkLogOperType.CALLBACK_ONCE_LEVEL.getId();
+            }
         } else if (markStage.ordinal() == 2) {//打分
-            operType = MarkLogOperType.SCORE.getId();
+            if(oldShiftScore){
+                operType = MarkLogOperType.CHANGE_SCORE.getId();
+            } else {
+                operType = MarkLogOperType.SCORE.getId();
+            }
         }
         //先查是否有档位或分数打回
         String operResult = DEFAULT_RESULT;
@@ -221,7 +231,11 @@ public class MarkLogAop {
             MarkLog markLogPrev = markLogRepo.findTopByCreateUserIdAndOperTypeAndSubjectAndExamNumberOrderByCreateTimeDesc(markUser.getId(), MarkLogOperType.CALLBACK_ONCE_LEVEL.getId(), markUser.getSubject().toString(), paper.getExamNumber());
             if (Objects.isNull(markLogPrev)) {//如果为null,则再查分档和回评档位
                 if (oldRejected && !isRejected) {//档位打回
-                    operType = MarkLogOperType.CALLBACK_ONCE_LEVEL.getId();
+                    if(oldShift){
+                        operType = MarkLogOperType.CHANGE_LEVEL.getId();
+                    } else {
+                        operType = MarkLogOperType.CALLBACK_ONCE_LEVEL.getId();
+                    }
                 } else {
                     operType = selectOperType(markUser.getId(), MarkLogOperType.LEVEL.getId(), MarkLogOperType.ONCE_LEVEl.getId(), markUser.getSubject().toString(), paper.getExamNumber());
                     markLogPrev = markLogRepo.findTopByCreateUserIdAndOperTypeAndSubjectAndExamNumberOrderByCreateTimeDesc(markUser.getId(), operType, markUser.getSubject().toString(), paper.getExamNumber());
@@ -238,7 +252,7 @@ public class MarkLogAop {
                 operType = MarkLogOperType.CALLBACK_ONCE_LEVEL.getId();//档位打回
                 operResult = Optional.ofNullable(markLogPrev.getOperDataAfter()).orElse(DEFAULT_RESULT);
             }
-        } else if (markStage.ordinal() == 2) {//打分
+        } else if (markStage.ordinal() == 2 && !oldShiftScore) {//打分
             operType = selectOperType(markUser.getId(), MarkLogOperType.SCORE.getId(), MarkLogOperType.ONCE_SCORE.getId(), markUser.getSubject().toString(), paper.getExamNumber());
             MarkLog markLogPrev = markLogRepo.findTopByCreateUserIdAndOperTypeAndSubjectAndExamNumberOrderByCreateTimeDesc(markUser.getId(), operType, markUser.getSubject().toString(), paper.getExamNumber());
             if (Objects.nonNull(markLogPrev)) {
@@ -265,8 +279,8 @@ public class MarkLogAop {
                 Integer deviation = Optional.ofNullable(ParamCache.paramMap.get(work.getId()).getDeviation()).orElse(3);
                 js.put("deviation", deviation.intValue());
                 MarkTaskJob markTaskJob = new MarkTaskJob(js.toJSONString(), false, paper.getWorkId());
-                autoCallback(markTasks, deviation.intValue(), paper, markTaskJob, work.getName());
                 markTaskJobRepo.save(markTaskJob);
+                autoCallback(markTasks, deviation.intValue(), paper, markTaskJob, work.getName());
             }
         }
         //20191107wangliang加入仲裁自动打回算法 end

+ 4 - 0
stmms-ms-marking/pom.xml

@@ -25,5 +25,9 @@
             <groupId>cn.com.qmth</groupId>
             <artifactId>stmms-ms-commons</artifactId>
         </dependency>
+        <dependency>
+            <groupId>cn.com.qmth</groupId>
+            <artifactId>stmms-ms-accesscontrol</artifactId>
+        </dependency>
     </dependencies>
 </project>

+ 71 - 21
stmms-ms-marking/src/main/java/cn/com/qmth/stmms/ms/marking/api/MakrerApi.java

@@ -1,5 +1,6 @@
 package cn.com.qmth.stmms.ms.marking.api;
 
+import cn.com.qmth.stmms.ms.accesscontrol.config.LoginConfig;
 import cn.com.qmth.stmms.ms.commons.threadPool.MyThreadPool;
 import cn.com.qmth.stmms.ms.commons.utils.SqlUtil;
 import cn.com.qmth.stmms.ms.core.cache.ParamCache;
@@ -17,6 +18,7 @@ import cn.com.qmth.stmms.ms.marking.assembler.LevelStatAssembler;
 import cn.com.qmth.stmms.ms.marking.assembler.MarkerAssembler;
 import cn.com.qmth.stmms.ms.marking.assembler.QuestionStatAssembler;
 import cn.com.qmth.stmms.ms.marking.dto.*;
+import cn.com.qmth.stmms.ms.marking.service.MarkingService;
 import javassist.bytecode.stackmap.BasicBlock;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -73,6 +75,12 @@ public class MakrerApi {
     @Autowired
     StudentRepo studentRepo;
 
+    @Autowired
+    private LoginConfig loginConfig;
+
+    @Autowired
+    MarkingService markingService;
+
     /**
      * 评卷员信息
      *
@@ -140,7 +148,7 @@ public class MakrerApi {
         Integer levelShowAllPaper = ParamCache.paramMap.get(marker.getWorkId()).getLevelShowAllPaper();
         Integer propDenominator = ParamCache.paramMap.get(marker.getWorkId()).getPropDenominator();
         Long batchNo = null;
-        if(levelShowAllPaper == 0){
+        if (levelShowAllPaper == 0) {
             batchNo = paperRepo.findMaxBatchNoByWorkIdAndSubject(marker.getWorkId(), marker.getSubject());
         }
         Long finalBatchNo = batchNo;
@@ -159,7 +167,7 @@ public class MakrerApi {
                 }
                 //当前考区内试卷总数
                 long total = 0;
-                if(propDenominator == 1){
+                if (propDenominator == 1) {
                     // 全部考生
                     total = paperRepo.countByWorkIdAndQuestionId(markSubject.getWorkId(), questionId);
                 } else if (propDenominator == 2) {
@@ -174,24 +182,24 @@ public class MakrerApi {
         //当前考区各档位定档数量
         List<Object[]> list = paperRepo.countGroupByLevel(questionId);
         list.forEach(o -> {
-                    LevelStatDTO levelStatDTO = levelStatAssembler.toDTO(o);
-                    levelStatDTO.setGcount(levelStatDTO.getCount());
-                    if (Objects.isNull(levelStatDTO.getId())) {
-                        //求任务数为null的条数
-                        int count;
-                        if (levelShowAllPaper == 1) {
-                            count = markTaskRepo.countByQuestionIdAndMarkerIdAndStageAndResultIsNullAll(questionId, marker.getId(), MarkStage.LEVEL.ordinal());
-                        } else {
-                            count = markTaskRepo.countByQuestionIdAndMarkerIdAndStageAndResultNull(questionId, marker.getId(), MarkStage.LEVEL.ordinal(), finalBatchNo);
-                        }
-                        //查询当前老师打回个数
+            LevelStatDTO levelStatDTO = levelStatAssembler.toDTO(o);
+            levelStatDTO.setGcount(levelStatDTO.getCount());
+            if (Objects.isNull(levelStatDTO.getId())) {
+                //求任务数为null的条数
+                int count;
+                if (levelShowAllPaper == 1) {
+                    count = markTaskRepo.countByQuestionIdAndMarkerIdAndStageAndResultIsNullAll(questionId, marker.getId(), MarkStage.LEVEL.ordinal());
+                } else {
+                    count = markTaskRepo.countByQuestionIdAndMarkerIdAndStageAndResultNull(questionId, marker.getId(), MarkStage.LEVEL.ordinal(), finalBatchNo);
+                }
+                //查询当前老师打回个数
 //                        int rejectCount = markTaskRepo.countByQuestionIdAndMarkerIdAndStageAndIsRejectedTrueAndIsMissing(questionId, marker.getId(), MarkStage.LEVEL.ordinal(), false);
-                        int rejectCount = markTaskRepo.countByQuestionIdAndMarkerIdAndStageAndIsRejectedTrue(questionId, marker.getId(), MarkStage.LEVEL.ordinal());
-                        levelStatDTO.setCount(count);
-                        levelStatDTO.setRejected(rejectCount);
-                    }
-                    levelStatDTOs.add(levelStatDTO);
-                });
+                int rejectCount = markTaskRepo.countByQuestionIdAndMarkerIdAndStageAndIsRejectedTrue(questionId, marker.getId(), MarkStage.LEVEL.ordinal());
+                levelStatDTO.setCount(count);
+                levelStatDTO.setRejected(rejectCount);
+            }
+            levelStatDTOs.add(levelStatDTO);
+        });
         for (Level level : levels) {
             //所有档位依次比较
             long count = levelStatDTOs.stream().filter(l -> String.valueOf(l.getId()).equals(level.getCode())).count();
@@ -264,7 +272,7 @@ public class MakrerApi {
         Integer levelShowAllPaper = ParamCache.paramMap.get(marker.getWorkId()).getLevelShowAllPaper();
         Integer propDenominator = ParamCache.paramMap.get(marker.getWorkId()).getPropDenominator();
         Long batchNo = null;
-        if(levelShowAllPaper == 0){
+        if (levelShowAllPaper == 0) {
             batchNo = paperRepo.findMaxBatchNoByWorkIdAndSubject(marker.getWorkId(), marker.getSubject());
         }
         Long finalBatchNo = batchNo;
@@ -281,7 +289,7 @@ public class MakrerApi {
                 }
                 //当前考区内试卷总数
                 long total = 0;
-                if(propDenominator == 1){
+                if (propDenominator == 1) {
                     // 全部考生
                     total = paperRepo.countByWorkIdAndQuestionId(markSubject.getWorkId(), questionId);
                 } else if (propDenominator == 2) {
@@ -674,4 +682,46 @@ public class MakrerApi {
         return objectMap;
     }
 
+    /**
+     * 清空当前阶段数据
+     *
+     * @param workId
+     * @param subject
+     * @param stage
+     * @param loginName
+     * @param password
+     * @return
+     */
+    @RequestMapping(value = "/subject/reset", method = RequestMethod.POST)
+    public Object subjectReset(@RequestParam Long workId,
+                               @RequestParam Subject subject,
+                               @RequestParam MarkStage stage,
+                               @RequestParam String loginName,
+                               @RequestParam String password) {
+        if (Objects.isNull(workId)) {
+            throw new RuntimeException("工作ID不能为空");
+        }
+        if (Objects.isNull(subject)) {
+            throw new RuntimeException("科目不能为空");
+        }
+        if (Objects.isNull(stage) || (!Objects.equals(MarkStage.LEVEL, stage) && !Objects.equals(MarkStage.SCORE, stage))) {
+            throw new RuntimeException("只有分档和打分阶段才能清除");
+        }
+        if (Objects.isNull(password)) {
+            throw new RuntimeException("密码不能为空");
+        }
+
+        if (!loginConfig.adminLoginConfig().getLoginName().equals(loginName)) {
+            throw new RuntimeException("只有管理员才能操作");
+        }
+        if (!loginConfig.adminLoginConfig().getPassword().equals(password)) {
+            throw new RuntimeException("管理员密码错误");
+        }
+
+        // 清空当前阶段数据
+        markingService.subjectReset(workId, subject, stage);
+
+        return true;
+    }
+
 }

+ 6 - 2
stmms-ms-marking/src/main/java/cn/com/qmth/stmms/ms/marking/api/MarkTaskApi.java

@@ -283,6 +283,8 @@ public class MarkTaskApi {
         MarkStage stage = MarkStage.valueOf(body.get("stage"));
         String result = body.get("result");
         boolean oldRejected = markTask.isRejected();
+        boolean oldShift = markTask.getPaper().isShift();
+        boolean oldShiftScore = markTask.getPaper().isShiftScore();
         if (stage == null || result == null) {
             return new ResponseEntity(HttpStatus.BAD_REQUEST);
         }
@@ -299,7 +301,7 @@ public class MarkTaskApi {
                 }
                 break;
         }
-        return new ResponseEntity(markTaskAssembler.toDTO(markTask, oldRejected), HttpStatus.OK);
+        return new ResponseEntity(markTaskAssembler.toDTO(markTask, oldRejected, oldShift, oldShiftScore), HttpStatus.OK);
     }
 
     /**
@@ -321,6 +323,8 @@ public class MarkTaskApi {
         for (String id : ids) {
             MarkTask markTask = markTaskRepo.findOne(Long.valueOf(id));
             boolean oldRejected = markTask.isRejected();
+            boolean oldShift = markTask.getPaper().isShift();
+            boolean oldShiftScore = markTask.getPaper().isShiftScore();
             if (stage == null || result == null) {
                 return new ResponseEntity(HttpStatus.BAD_REQUEST);
             }
@@ -337,7 +341,7 @@ public class MarkTaskApi {
                     }
                     break;
             }
-            MarkTaskDTO markTaskDTO = markTaskAssembler.toDTO(markTask, oldRejected);
+            MarkTaskDTO markTaskDTO = markTaskAssembler.toDTO(markTask, oldRejected, oldShift, oldShiftScore);
             list.add(markTaskDTO);
         }
 

+ 6 - 2
stmms-ms-marking/src/main/java/cn/com/qmth/stmms/ms/marking/api/PaperApi.java

@@ -256,13 +256,17 @@ public class PaperApi {
             return builder.and(predicates.toArray(new Predicate[predicates.size()]));
         };
 
-        Page<Paper> papers = paperRepo.findAll(specification, pageable);
+        Sort sort = new Sort(Sort.Direction.DESC, "isSample");
+        Pageable pageable1 = new PageRequest(pageable.getPageNumber(), pageable.getPageSize(), sort);
+        Page<Paper> papers = paperRepo.findAll(specification, pageable1);
         List<PaperDTO> paperDTOs = new ArrayList<>();
         papers.forEach(p -> {
             paperDTOs.add(paperAssembler.toDTO(p));
         });
         paperDTOs.sort((o1, o2) -> o2.getSortSum() -o1.getSortSum());
-        return new PageableDTO(paperDTOs, papers.getTotalElements(), papers.getTotalPages(), pageable.getPageNumber());
+        // 先按标准卷排序,再按典型值排序
+        List<PaperDTO> list = paperDTOs.stream().sorted(Comparator.comparing(PaperDTO::isSample).reversed().thenComparing((o1, o2) -> o2.getSortSum() -o1.getSortSum())).collect(Collectors.toList());
+        return new PageableDTO(list, papers.getTotalElements(), papers.getTotalPages(), pageable.getPageNumber());
     }
 
     /**

+ 3 - 1
stmms-ms-marking/src/main/java/cn/com/qmth/stmms/ms/marking/assembler/MarkTaskAssembler.java

@@ -106,7 +106,7 @@ public class MarkTaskAssembler {
         return markTaskDTO;
     }
 
-    public MarkTaskDTO toDTO(MarkTask markTask, boolean oldRejected) {
+    public MarkTaskDTO toDTO(MarkTask markTask, boolean oldRejected, boolean oldShift, boolean oldShiftScore) {
         MarkTaskDTO markTaskDTO = null;
         if (markTask != null) {
             markTaskDTO = new MarkTaskDTO();
@@ -150,6 +150,8 @@ public class MarkTaskAssembler {
             markTaskDTO.setRandomSeqNew(markTask.getRandomSeqNew());
             markTaskDTO.setRandomSeq(markTask.getRandomSeq());
             markTaskDTO.setPaperId(paper.getId());
+            markTaskDTO.setShift(oldShift);
+            markTaskDTO.setShiftScore(oldShiftScore);
         }
         return markTaskDTO;
     }

+ 1 - 1
stmms-ms-marking/src/main/java/cn/com/qmth/stmms/ms/marking/service/AssignTaskService.java

@@ -292,7 +292,7 @@ public class AssignTaskService {
                 cacheService.deleteTokenCache(user.getId().toString());
             }
         }
-        dbBackupUtils.startBackup("分档");
+        dbBackupUtils.startBackup(markSubject.getWorkId(), "分档");
     }
 
     private void initTaskPublishData(MarkSubject markSubject) {

+ 43 - 0
stmms-ms-marking/src/main/java/cn/com/qmth/stmms/ms/marking/service/MarkingService.java

@@ -3,12 +3,14 @@ package cn.com.qmth.stmms.ms.marking.service;
 import cn.com.qmth.stmms.ms.commons.config.LevelConfig;
 import cn.com.qmth.stmms.ms.commons.constant.ArbitrateCallback;
 import cn.com.qmth.stmms.ms.commons.constant.ArbitrateResult;
+import cn.com.qmth.stmms.ms.core.cache.CacheService;
 import cn.com.qmth.stmms.ms.core.cache.ParamCache;
 import cn.com.qmth.stmms.ms.core.domain.*;
 import cn.com.qmth.stmms.ms.core.domain.task.MarkTask;
 import cn.com.qmth.stmms.ms.core.domain.user.MarkUser;
 import cn.com.qmth.stmms.ms.core.domain.user.Role;
 import cn.com.qmth.stmms.ms.core.repository.*;
+import cn.com.qmth.stmms.ms.core.vo.Subject;
 import cn.com.qmth.stmms.ms.marking.config.MarkingConfig;
 import cn.com.qmth.stmms.ms.marking.service.arbitration.ArbitrationService;
 import com.alibaba.fastjson.JSONObject;
@@ -17,6 +19,7 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
 
 import javax.annotation.Resource;
 import java.util.*;
@@ -66,6 +69,15 @@ public class MarkingService {
     @Resource
     MarkTaskJobRepo markTaskJobRepo;
 
+    @Autowired
+    MarkerGroupRepo markerGroupRepo;
+
+    @Autowired
+    TaskPublishSettingRepo taskPublishSettingRepo;
+
+    @Autowired
+    private CacheService cacheService;
+
     /**
      * 提交分档。如果每个评卷都提交了,则进行仲裁判定,如果没有触发仲裁就定档
      *
@@ -395,4 +407,35 @@ public class MarkingService {
         }
 
     }
+
+    public void subjectReset(Long workId, Subject subject, MarkStage stage) {
+        // 删除mark_task阶段数据
+        markTaskRepo.deleteByWorkIdAndSubjectAndStage(workId, subject, stage);
+        // 清除mark_user分组
+        markUserRepo.updateByWorkIdAndSubject(workId, subject);
+        // 删除mark_group分组
+        markerGroupRepo.deleteBySubjectAndWorkId(subject, workId);
+        if (MarkStage.SCORE.equals(stage)) {
+            // 打分阶段
+            // 删除task_publish_setting数据
+            taskPublishSettingRepo.deleteByWorkIdAndSubjectAndPublishCountNot(workId, subject.name(), 0);
+            // 清除paper中的分数
+            paperRepo.updateScoreByWorkIdAndSubject(workId, subject.name());
+        } else if (MarkStage.LEVEL.equals(stage)) {
+            // 分档阶段
+            // 清除paper中的档位,各种状态
+            paperRepo.updateLevelByWorkIdAndSubject(workId, subject.name());
+        } else {
+            throw new RuntimeException("当前阶段无法重置数据");
+        }
+
+        // 所有用户强制退出
+        List<MarkUser> userList = markUserRepo.findByWorkIdAndSubject(workId, subject);
+        userList = userList.stream().filter(m-> Role.MARKER.equals(m.getRole()) || Role.MARK_LEADER.equals(m.getRole())).collect(Collectors.toList());
+        if(!CollectionUtils.isEmpty(userList)){
+            for (MarkUser user : userList) {
+                cacheService.deleteTokenCache(user.getId().toString());
+            }
+        }
+    }
 }