浏览代码

联考版-v2.1.0

xiaof 3 年之前
父节点
当前提交
e91656041b
共有 17 个文件被更改,包括 957 次插入148 次删除
  1. 51 27
      stmms-ms-admin/src/main/java/cn/com/qmth/stmms/ms/admin/api/QualityAnalyseController.java
  2. 22 6
      stmms-ms-admin/src/main/java/cn/com/qmth/stmms/ms/admin/api/UserApi.java
  3. 3 3
      stmms-ms-admin/src/main/java/cn/com/qmth/stmms/ms/admin/exporter/StudentExporter.java
  4. 7 4
      stmms-ms-commons/src/main/java/cn/com/qmth/stmms/ms/commons/utils/ServletUtil.java
  5. 109 0
      stmms-ms-core/src/main/java/cn/com/qmth/stmms/ms/core/domain/user/MarkerGroupLeader.java
  6. 28 0
      stmms-ms-core/src/main/java/cn/com/qmth/stmms/ms/core/repository/MarkTaskRepo.java
  7. 2 0
      stmms-ms-core/src/main/java/cn/com/qmth/stmms/ms/core/repository/MarkUserRepo.java
  8. 19 0
      stmms-ms-core/src/main/java/cn/com/qmth/stmms/ms/core/repository/MarkerGroupLeaderRepo.java
  9. 49 1
      stmms-ms-core/src/main/java/cn/com/qmth/stmms/ms/core/repository/PaperRepo.java
  10. 4 0
      stmms-ms-core/src/main/java/cn/com/qmth/stmms/ms/core/specification/StudentSpecification.java
  11. 56 64
      stmms-ms-marking/src/main/java/cn/com/qmth/stmms/ms/marking/api/MakrerApi.java
  12. 175 17
      stmms-ms-marking/src/main/java/cn/com/qmth/stmms/ms/marking/api/MarkSubjectApi.java
  13. 26 3
      stmms-ms-marking/src/main/java/cn/com/qmth/stmms/ms/marking/api/MarkTaskApi.java
  14. 27 5
      stmms-ms-marking/src/main/java/cn/com/qmth/stmms/ms/marking/api/PaperApi.java
  15. 9 7
      stmms-ms-marking/src/main/java/cn/com/qmth/stmms/ms/marking/service/AssignTaskService.java
  16. 178 11
      stmms-ms-marking/src/main/java/cn/com/qmth/stmms/ms/marking/service/GroupingService.java
  17. 192 0
      stmms-ms-marking/src/main/java/cn/com/qmth/stmms/ms/marking/service/MarkerGroupLeaderService.java

+ 51 - 27
stmms-ms-admin/src/main/java/cn/com/qmth/stmms/ms/admin/api/QualityAnalyseController.java

@@ -4,20 +4,26 @@ import cn.com.qmth.stmms.ms.commons.utils.SqlUtil;
 import cn.com.qmth.stmms.ms.core.domain.Level;
 import cn.com.qmth.stmms.ms.core.domain.MarkLogOperType;
 import cn.com.qmth.stmms.ms.core.domain.MarkStage;
+import cn.com.qmth.stmms.ms.core.domain.Paper;
 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.MarkerGroupLeader;
 import cn.com.qmth.stmms.ms.core.repository.LevelRepo;
 import cn.com.qmth.stmms.ms.core.repository.MarkTaskRepo;
 import cn.com.qmth.stmms.ms.core.repository.MarkUserRepo;
+import cn.com.qmth.stmms.ms.core.repository.MarkerGroupLeaderRepo;
 import cn.com.qmth.stmms.ms.core.vo.Subject;
+import cn.com.qmth.stmms.ms.marking.service.MarkerGroupLeaderService;
 import org.apache.commons.lang.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.jpa.domain.Specification;
+import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
+import javax.persistence.criteria.CriteriaBuilder;
 import javax.persistence.criteria.Predicate;
 import java.math.BigDecimal;
 import java.util.*;
@@ -48,6 +54,9 @@ public class QualityAnalyseController {
     @Autowired
     MarkUserRepo markUserRepo;
 
+    @Autowired
+    MarkerGroupLeaderService markerGroupLeaderService;
+
     /**
      * 档位占比报表
      *
@@ -57,21 +66,22 @@ public class QualityAnalyseController {
      * @param startTime
      * @param endTime
      */
-//    @ApiOperation(value = "档位占比报表接口")
     @RequestMapping(value = "levelsPropReport", method = RequestMethod.GET)
     public Object levelsPropReport(
-//            @ApiParam(value = "workId", required = true)
             @RequestParam Long workId,
-//            @ApiParam(value = "科目", required = false)
             @RequestParam(required = false) Subject subject,
-//            @ApiParam(value = "考点", required = false)
             @RequestParam(required = false) String areaCode,
-//            @ApiParam(value = "开始时间", required = false)
+            @RequestParam(required = false) Long groupId,
             @RequestParam(required = false) String startTime,
-//            @ApiParam(value = "结束时间", required = false)
             @RequestParam(required = false) String endTime) {
         List fList = new ArrayList();
         List<Level> levels = levelRepo.findByWorkId(workId);
+        List<Long> markerIds = markerGroupLeaderService.listByWorkIdAndSubjectAndStageAndGroupId(workId, subject, MarkStage.LEVEL, groupId);
+        String markerId = null;
+        if (!CollectionUtils.isEmpty(markerIds)) {
+            markerId = markerIds.stream().map(m -> String.valueOf(m)).collect(Collectors.joining(","));
+        }
+        String finalMarkerId = markerId;
         levels.forEach(l -> {
             StringBuffer sql = new StringBuffer();
             sql.append("  SELECT                                                        ");
@@ -81,7 +91,7 @@ public class QualityAnalyseController {
             sql.append("      COUNT(1) total                                            ");
             sql.append("  FROM                                                          ");
             sql.append("      mark_user mu                                              ");
-            sql.append("          LEFT JOIN                                             ");
+            sql.append("           JOIN                                             ");
             sql.append("      (SELECT                                                   ");
             sql.append("          m.*                                                     ");
             sql.append("      FROM                                                      ");
@@ -92,6 +102,9 @@ public class QualityAnalyseController {
             if (!Objects.isNull(areaCode)) {
                 sql.append(" and p.area_code = " + areaCode);
             }
+            if (StringUtils.isNotBlank(finalMarkerId)) {
+                sql.append(" and m.marker_id in (" + finalMarkerId + ")");
+            }
             if (!Objects.isNull(startTime)) {
                 sql.append(" and m.updated_on >= '" + startTime + "'");
             }
@@ -147,20 +160,16 @@ public class QualityAnalyseController {
      * @param endTime
      * @return
      */
-//    @ApiOperation(value = "打回次数报表接口")
     @RequestMapping(value = "callbackReport", method = RequestMethod.GET)
     public List callbackReport(
-//            @ApiParam(value = "workId", required = true)
             @RequestParam Long workId,
-//            @ApiParam(value = "科目", required = false)
             @RequestParam(required = false) Subject subject,
-//            @ApiParam(value = "考点", required = false)
             @RequestParam(required = false) String areaCode,
-//            @ApiParam(value = "开始时间", required = false)
+            @RequestParam(required = false) Long groupId,
             @RequestParam(required = false) String startTime,
-//            @ApiParam(value = "结束时间", required = false)
             @RequestParam(required = false) String endTime) {
         List list = new ArrayList();
+        List<Long> markerIds = markerGroupLeaderService.listByWorkIdAndSubjectAndStageAndGroupId(workId, subject, MarkStage.LEVEL, groupId);;
         Specification<MarkTask> specification = (root, query, builder) -> {
             List<Predicate> predicates = new ArrayList<>();
             predicates.add(builder.equal(root.get("workId"), workId));
@@ -170,6 +179,13 @@ public class QualityAnalyseController {
             if (Objects.nonNull(areaCode)) {
                 predicates.add(builder.equal(root.get("paper").get("areaCode"), areaCode));
             }
+            if(!CollectionUtils.isEmpty(markerIds)){
+                CriteriaBuilder.In<Object> in = builder.in(root.get("markerId"));
+                for (Long id : markerIds) {
+                    in.value(id);
+                }
+                predicates.add(builder.and(builder.and(in)));
+            }
             return builder.and(predicates.toArray(new Predicate[predicates.size()]));
         };
         List<MarkTask> markTasks = markTaskRepo.findAll(specification);
@@ -200,20 +216,16 @@ public class QualityAnalyseController {
      * @param startTime
      * @param endTime
      */
-//    @ApiOperation(value = "差值和报表接口")
     @RequestMapping(value = "distanceReport", method = RequestMethod.GET)
     public List distanceReport(
-//            @ApiParam(value = "workId", required = true)
             @RequestParam Long workId,
-//            @ApiParam(value = "科目", required = true)
             @RequestParam(required = false) Subject subject,
-//            @ApiParam(value = "考点", required = true)
             @RequestParam(required = false) String areaCode,
-//            @ApiParam(value = "开始时间", required = false)
+            @RequestParam(required = false) Long groupId,
             @RequestParam(required = false) String startTime,
-//            @ApiParam(value = "结束时间", required = false)
             @RequestParam(required = false) String endTime) {
         List list = new ArrayList();
+        List<Long> markerIds = markerGroupLeaderService.listByWorkIdAndSubjectAndStageAndGroupId(workId, subject, MarkStage.LEVEL, groupId);;
         Specification<MarkTask> specification = (root, query, builder) -> {
             List<Predicate> predicates = new ArrayList<>();
             predicates.add(builder.equal(root.get("workId"), workId));
@@ -223,6 +235,13 @@ public class QualityAnalyseController {
             if (Objects.nonNull(areaCode)) {
                 predicates.add(builder.equal(root.get("paper").get("areaCode"), areaCode));
             }
+            if(!CollectionUtils.isEmpty(markerIds)){
+                CriteriaBuilder.In<Object> in = builder.in(root.get("markerId"));
+                for (Long id : markerIds) {
+                    in.value(id);
+                }
+                predicates.add(builder.and(builder.and(in)));
+            }
             return builder.and(predicates.toArray(new Predicate[predicates.size()]));
         };
         List<MarkTask> markTasks = markTaskRepo.findAll(specification);
@@ -258,9 +277,11 @@ public class QualityAnalyseController {
             @RequestParam Long workId,
             @RequestParam(required = false) Subject subject,
             @RequestParam(required = false) String areaCode,
+            @RequestParam(required = false) Long groupId,
             @RequestParam(required = false) String startTime,
             @RequestParam(required = false) String endTime) {
         List list = new ArrayList();
+        List<Long> markerIds = markerGroupLeaderService.listByWorkIdAndSubjectAndStageAndGroupId(workId, subject, MarkStage.LEVEL, groupId);;
         Specification<MarkTask> specification = (root, query, builder) -> {
             List<Predicate> predicates = new ArrayList<>();
             predicates.add(builder.equal(root.get("workId"), workId));
@@ -270,6 +291,13 @@ public class QualityAnalyseController {
             if (Objects.nonNull(areaCode)) {
                 predicates.add(builder.equal(root.get("paper").get("areaCode"), areaCode));
             }
+            if(!CollectionUtils.isEmpty(markerIds)){
+                CriteriaBuilder.In<Object> in = builder.in(root.get("markerId"));
+                for (Long id : markerIds) {
+                    in.value(id);
+                }
+                predicates.add(builder.and(builder.and(in)));
+            }
             return builder.and(predicates.toArray(new Predicate[predicates.size()]));
         };
         List<MarkTask> markTasks = markTaskRepo.findAll(specification);
@@ -312,7 +340,6 @@ public class QualityAnalyseController {
                 for (Long l : distinctIdList) {
                     Map map = new HashMap();
                     MarkUser markUser = markUserRepo.findOne(markerMap.get(l).getMarkerId());
-//                    map.put("userName", markerMap.get(l).getMarkerName());
                     map.put("userName", markUser.getLoginName());
                     map.put("sumCount", 0);
                     map.put("userId", l);
@@ -321,13 +348,10 @@ public class QualityAnalyseController {
             }
         }
         //排序
-        Collections.sort(list, new Comparator<Map<String, Object>>() {
-            @Override
-            public int compare(Map<String, Object> o1, Map<String, Object> o2) {
-                String o1Value = String.valueOf(o1.get("userName"));
-                String o2Value = String.valueOf(o2.get("userName"));
-                return o1Value.compareTo(o2Value);
-            }
+        Collections.sort(list, (Comparator<Map<String, Object>>) (o1, o2) -> {
+            String o1Value = String.valueOf(o1.get("userName"));
+            String o2Value = String.valueOf(o2.get("userName"));
+            return o1Value.compareTo(o2Value);
         });
         return list;
     }

+ 22 - 6
stmms-ms-admin/src/main/java/cn/com/qmth/stmms/ms/admin/api/UserApi.java

@@ -1,24 +1,21 @@
 package cn.com.qmth.stmms.ms.admin.api;
 
-import cn.com.qmth.stmms.ms.admin.dto.MarkUserDTO;
 import cn.com.qmth.stmms.ms.commons.web.PageableDTO;
 import cn.com.qmth.stmms.ms.core.domain.MarkLog;
 import cn.com.qmth.stmms.ms.core.domain.MarkStage;
 import cn.com.qmth.stmms.ms.core.domain.MarkSubject;
 import cn.com.qmth.stmms.ms.core.domain.user.MarkRight;
 import cn.com.qmth.stmms.ms.core.domain.user.MarkUser;
+import cn.com.qmth.stmms.ms.core.domain.user.MarkerGroup;
 import cn.com.qmth.stmms.ms.core.domain.user.Role;
-import cn.com.qmth.stmms.ms.core.repository.MarkLogRepo;
-import cn.com.qmth.stmms.ms.core.repository.MarkSubjectRepo;
-import cn.com.qmth.stmms.ms.core.repository.MarkTaskRepo;
-import cn.com.qmth.stmms.ms.core.repository.MarkUserRepo;
+import cn.com.qmth.stmms.ms.core.repository.*;
 import cn.com.qmth.stmms.ms.core.vo.Subject;
 import cn.com.qmth.stmms.ms.marking.assembler.MarkerAssembler;
 import cn.com.qmth.stmms.ms.marking.dto.MarkerDTO;
+import cn.com.qmth.stmms.ms.marking.service.MarkerGroupLeaderService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Pageable;
-import org.springframework.data.domain.Sort;
 import org.springframework.data.jpa.domain.Specification;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
@@ -27,6 +24,7 @@ import org.springframework.web.bind.annotation.*;
 import javax.persistence.criteria.Predicate;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 import java.util.stream.Collectors;
 
@@ -54,6 +52,9 @@ public class UserApi {
     @Autowired
     MarkerAssembler markerAssembler;
 
+    @Autowired
+    MarkerGroupLeaderService markerGroupLeaderService;
+
     @RequestMapping(value = "{userId}", method = RequestMethod.DELETE)
     public void remove(@PathVariable Long userId) {
         long count = markTaskRepo.countByMarkerId(userId);
@@ -247,4 +248,19 @@ public class UserApi {
         return new ResponseEntity(HttpStatus.OK);
     }
 
+
+    /**
+     * 查询用户分组
+     * @param workId
+     * @param subject
+     * @param stage
+     * @return
+     */
+    @RequestMapping(value = "/list_group", method = RequestMethod.GET)
+    public List<Map<String, Object>> listGroup(@RequestParam Long workId,
+                                               @RequestParam Subject subject,
+                                               @RequestParam(required = false) MarkStage stage) {
+        return markerGroupLeaderService.listGroupByWorkIdAndSubjectAndStage(workId, subject, stage);
+    }
+
 }

+ 3 - 3
stmms-ms-admin/src/main/java/cn/com/qmth/stmms/ms/admin/exporter/StudentExporter.java

@@ -46,17 +46,17 @@ public class StudentExporter {
                     //色彩
                     if (str.contains("SC")) {
                         String[] strings = str.split(":");
-                        studentExpDTO.setSc(strings[1]);
+                        studentExpDTO.setSc("0".equals(strings[1]) ? "缺考" : "");
                     }
                     //素描
                     if (str.contains("SM")) {
                         String[] strings = str.split(":");
-                        studentExpDTO.setSm(strings[1]);
+                        studentExpDTO.setSm("0".equals(strings[1]) ? "缺考" : "");
                     }
                     //速写
                     if (str.contains("SX")) {
                         String[] strings = str.split(":");
-                        studentExpDTO.setSx(strings[1]);
+                        studentExpDTO.setSx("0".equals(strings[1]) ? "缺考" : "");
                     }
                 }
                 list.add(studentExpDTO);

+ 7 - 4
stmms-ms-commons/src/main/java/cn/com/qmth/stmms/ms/commons/utils/ServletUtil.java

@@ -1,5 +1,6 @@
 package cn.com.qmth.stmms.ms.commons.utils;
 
+import org.apache.commons.lang.StringUtils;
 import org.springframework.web.context.request.RequestContextHolder;
 import org.springframework.web.context.request.ServletRequestAttributes;
 
@@ -24,17 +25,19 @@ public class ServletUtil {
      * 获取用户ID
      * @return
      */
-    public static String getUserId() {
+    public static Long getUserId() {
         HttpServletRequest request = getRequest();
-        return request.getHeader("userId");
+        String userId = request.getHeader("userId");
+        return StringUtils.isBlank(userId) ? null : Long.valueOf(userId);
     }
 
     /**
      * 获取工作ID
      * @return
      */
-    public static String getWordId() {
+    public static Long getWordId() {
         HttpServletRequest request = getRequest();
-        return request.getHeader("wordId");
+        String workId = request.getHeader("workId");
+        return StringUtils.isBlank(workId) ? null : Long.valueOf(workId);
     }
 }

+ 109 - 0
stmms-ms-core/src/main/java/cn/com/qmth/stmms/ms/core/domain/user/MarkerGroupLeader.java

@@ -0,0 +1,109 @@
+package cn.com.qmth.stmms.ms.core.domain.user;
+
+import cn.com.qmth.stmms.ms.core.domain.MarkStage;
+import cn.com.qmth.stmms.ms.core.vo.Subject;
+
+import javax.persistence.*;
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * 科组长-评卷员对应关系
+ */
+@Entity
+public class MarkerGroupLeader implements Serializable{
+
+    private static final long serialVersionUID = 966105324299193932L;
+    @Id
+    @GeneratedValue
+    private Long id;
+
+    @NotNull
+    private Long workId;
+
+    @NotNull
+    @Enumerated(value = EnumType.STRING)
+    private Subject subject;
+
+    @NotNull
+    @Enumerated(value = EnumType.ORDINAL)
+    private MarkStage stage;
+
+    @NotNull
+    private Long groupId;
+
+    @NotNull
+    private String groupName;
+
+    @NotNull
+    private Long markLeaderId;
+
+    @NotNull
+    private Long markerId;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public Long getWorkId() {
+        return workId;
+    }
+
+    public void setWorkId(Long workId) {
+        this.workId = workId;
+    }
+
+    public Subject getSubject() {
+        return subject;
+    }
+
+    public void setSubject(Subject subject) {
+        this.subject = subject;
+    }
+
+    public MarkStage getStage() {
+        return stage;
+    }
+
+    public void setStage(MarkStage stage) {
+        this.stage = stage;
+    }
+
+    public Long getGroupId() {
+        return groupId;
+    }
+
+    public void setGroupId(Long groupId) {
+        this.groupId = groupId;
+    }
+
+    public String getGroupName() {
+        return groupName;
+    }
+
+    public void setGroupName(String groupName) {
+        this.groupName = groupName;
+    }
+
+    public Long getMarkLeaderId() {
+        return markLeaderId;
+    }
+
+    public void setMarkLeaderId(Long markLeaderId) {
+        this.markLeaderId = markLeaderId;
+    }
+
+    public Long getMarkerId() {
+        return markerId;
+    }
+
+    public void setMarkerId(Long markerId) {
+        this.markerId = markerId;
+    }
+}

+ 28 - 0
stmms-ms-core/src/main/java/cn/com/qmth/stmms/ms/core/repository/MarkTaskRepo.java

@@ -2,6 +2,7 @@ package cn.com.qmth.stmms.ms.core.repository;
 
 import cn.com.qmth.stmms.ms.core.domain.MarkStage;
 import cn.com.qmth.stmms.ms.core.domain.task.MarkTask;
+import cn.com.qmth.stmms.ms.core.domain.user.MarkerGroupLeader;
 import cn.com.qmth.stmms.ms.core.vo.Subject;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
@@ -114,6 +115,21 @@ public interface MarkTaskRepo extends JpaRepository<MarkTask, Long>, JpaSpecific
             "t.work_id = ? and t.subject = ? and t.stage = ? and p.is_missing = false and p.is_test = ? and p.batch_no = ? GROUP BY t.marker_id,mu.login_name, t.`marker_name` ORDER BY q.`id`,t.marker_id", nativeQuery = true)
     List<Object[]> listGroupByQuestionAndMarkerAndBatchNo(Long workId, String name, Integer stageId, int test, Long batchNo);
 
+    /**
+     * 统计各评卷员各试题已评数及总数(分档阶段)
+     *
+     *
+     * @param name
+     * @param stageId
+     * @param batchNo
+     * @param markers
+     * @return
+     */
+    @Query(value = "SELECT q.`id`,t.`marker_id` markerId,mu.login_name loginName,t.`marker_name` markerName,q.`name`,SUM(IF(t.`result` IS NULL,1,0)) leftCount,COUNT(t.question_id) totalCount, SUM(t.is_rejected) rejectedCount, q.area_code areaCode " +
+            "FROM mark_task t LEFT JOIN mark_user mu on t.marker_id = mu.id LEFT OUTER JOIN exam_question q ON t.`question_id` = q.`id` LEFT  JOIN paper p ON t.paper_id = p.id WHERE " +
+            "t.work_id = ? and t.subject = ? and t.stage = ? and p.is_missing = false and p.is_test = ? and p.batch_no = ? and t.marker_id in (?) GROUP BY t.marker_id,mu.login_name, t.`marker_name` ORDER BY q.`id`,t.marker_id", nativeQuery = true)
+    List<Object[]> listGroupByQuestionAndMarkerAndBatchNoAndMarkerId(Long workId, String name, Integer stageId, int test, Long batchNo, String markers);
+
     /**
      * 考区已评数及总数(分档阶段)
      *
@@ -159,6 +175,16 @@ public interface MarkTaskRepo extends JpaRepository<MarkTask, Long>, JpaSpecific
             "t.work_id = ? and t.subject = ? and t.stage = ? and p.score_batch_no = ? and p.is_missing = false GROUP BY t.marker_id,mu.login_name, t.`marker_name` ORDER BY q.`id`, t.`marker_id`", nativeQuery = true)
     List<Object[]> listGroupByQuestionAndMarkerAndScoreBatchNo(Long workId, String name, Integer stageId, Long batchNo);
 
+    /**
+     * 统计各评卷员各试题已评数及总数(分档阶段)
+     *
+     * @return
+     */
+    @Query(value = "SELECT q.`id`,t.`marker_id` markerId,mu.login_name loginName,t.`marker_name` markerName,q.`name`,SUM(IF(t.`result` IS NULL,1,0)) leftCount,COUNT(t.question_id) totalCount,SUM(t.is_rejected) rejectedCount, q.area_code areaCode " +
+            "FROM mark_task t LEFT JOIN mark_user mu on t.marker_id = mu.id LEFT OUTER JOIN exam_question q ON t.`question_id` = q.`id` LEFT  JOIN paper p ON t.paper_id = p.id WHERE " +
+            "t.work_id = ? and t.subject = ? and t.stage = ? and p.score_batch_no = ? and t.`marker_id` in (?) and p.is_missing = false GROUP BY t.marker_id,mu.login_name, t.`marker_name` ORDER BY q.`id`, t.`marker_id`", nativeQuery = true)
+    List<Object[]> listGroupByQuestionAndMarkerAndScoreBatchNoAndMakerId(Long workId, String name, Integer stageId, Long batchNo, String markers);
+
     /**
      * 统计指定试卷的所有任务数量
      *
@@ -253,4 +279,6 @@ public interface MarkTaskRepo extends JpaRepository<MarkTask, Long>, JpaSpecific
     @Modifying
     @Query(value = "update mark_task m set m.level = ?1 where m.paper_id = ?2", nativeQuery = true)
     void updateLevelByPaperId(String level, Long id);
+
+    List<MarkTask> findByWorkIdAndSubjectAndStageAndMarkerIdIn(Long workId, Subject subject, MarkStage stage, List<Long> markers);
 }

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

@@ -33,4 +33,6 @@ public interface MarkUserRepo extends JpaRepository<MarkUser,Long>, JpaSpecifica
 	@Modifying
 	@Query("update MarkUser set groupId = null where workId = ?1 and subject = ?2")
     void updateByWorkIdAndSubject(Long workId, Subject subject);
+
+	List<MarkUser> findByWorkIdAndSubjectAndRoleAndIdNotIn(Long workId, Subject subject, Role markLeader, List<Long> userMarkLeaders);
 }

+ 19 - 0
stmms-ms-core/src/main/java/cn/com/qmth/stmms/ms/core/repository/MarkerGroupLeaderRepo.java

@@ -0,0 +1,19 @@
+package cn.com.qmth.stmms.ms.core.repository;
+
+import cn.com.qmth.stmms.ms.core.domain.MarkStage;
+import cn.com.qmth.stmms.ms.core.domain.user.MarkerGroupLeader;
+import cn.com.qmth.stmms.ms.core.vo.Subject;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+import java.util.List;
+
+public interface MarkerGroupLeaderRepo extends JpaRepository<MarkerGroupLeader, Long> {
+
+    void deleteByWorkIdAndSubjectAndStageAndGroupId(Long workId, Subject subject, MarkStage stage, Long groupId);
+
+    List<MarkerGroupLeader> findByWorkIdAndSubjectAndStage(Long workId, Subject subject, MarkStage stage);
+
+    List<MarkerGroupLeader> findByWorkIdAndSubjectAndStageAndMarkLeaderId(Long workId, Subject subject, MarkStage stage, Long markLeaderId);
+
+    List<MarkerGroupLeader> findByWorkIdAndSubjectAndStageAndGroupId(Long workId, Subject subject, MarkStage level, Long groupId);
+}

+ 49 - 1
stmms-ms-core/src/main/java/cn/com/qmth/stmms/ms/core/repository/PaperRepo.java

@@ -29,6 +29,8 @@ public interface PaperRepo extends JpaRepository<Paper, Long>, JpaSpecificationE
 
     List<Paper> findByWorkIdAndSubjectAndIsMissingAndTest(Long workId, Subject subject, boolean isMissing, int test);
 
+    List<Paper> findByWorkIdAndSubjectAndIsMissingAndTestAndIdIn(Long workId, Subject subject, boolean isMissing, int test, List<Long> paperIds);
+
     @Query(value = "select * from paper p where p.work_id = ?1 and p.subject = ?2 and p.is_missing = false and p.is_active = false limit ?3", nativeQuery = true)
     List<Paper> findByWorkIdAndSubjectAndIsMissingAndIsActive(Long workId, Subject subject, int taskCount);
 
@@ -110,7 +112,7 @@ public interface PaperRepo extends JpaRepository<Paper, Long>, JpaSpecificationE
     List<Object[]> countScoreGroupByLevel(Long questionId, Long batchNo);
 
     /**
-     * 统计科目指定试题的各档位数量
+     * 管理员-统计科目指定试题的各档位数量
      *
      * @param questionId
      * @return
@@ -125,6 +127,22 @@ public interface PaperRepo extends JpaRepository<Paper, Long>, JpaSpecificationE
             "GROUP BY p.`level` ORDER BY p.`level`", nativeQuery = true)
     List<Object[]> countGroupByLevelAll(Long questionId, int test);
 
+    /**
+     * 科组长-统计科目指定试题的各档位数量
+     *
+     * @param questionId
+     * @return
+     */
+    @Query(value = "SELECT p.`level`,COUNT(*)," +
+            "SUM(IF(p.`is_rejected` = 1, 1, 0))," +
+            "SUM(IF(p.`is_arbitrated` = 1, 1, 0))," +
+            "SUM(IF(p.`is_shift` = 1, 1, 0))," +
+            "SUM(IF(p.`is_shift_score` = 1, 1, 0))" +
+            "FROM paper p " +
+            "WHERE p.`question_id` = :questionId and p.is_missing = false and p.is_test = :test and p.batch_no is not null and p.id in (:paperIds) " +
+            "GROUP BY p.`level` ORDER BY p.`level`", nativeQuery = true)
+    List<Object[]> countGroupByLevelAllAndIdIn(@Param("questionId") Long questionId, @Param("test") int test, @Param("paperIds") List<Long> paperIds);
+
     /**
      * 统计科目指定试题的各档位数量
      *
@@ -191,6 +209,8 @@ public interface PaperRepo extends JpaRepository<Paper, Long>, JpaSpecificationE
 
     long countByWorkIdAndQuestionId(Long workId, Long questionId);
 
+    long countByWorkIdAndQuestionIdAndIdIn(Long workId, Long questionId, List<Long> paperIds);
+
     long countByQuestionId(Long questionId);
 
     /**
@@ -282,6 +302,8 @@ public interface PaperRepo extends JpaRepository<Paper, Long>, JpaSpecificationE
 
     long countByWorkIdAndSubjectAndLevel(Long workId, Subject subject, String code);
 
+    long countByWorkIdAndSubjectAndLevelAndIdIn(Long workId, Subject subject, String code, List<Long> finalPaperIds);
+
     long countByWorkIdAndSubject(Long workId, Subject subject);
 
     long countByWorkIdAndSubjectAndQuestionIdAndLevel(Long workId,
@@ -317,6 +339,8 @@ public interface PaperRepo extends JpaRepository<Paper, Long>, JpaSpecificationE
 
     List<Paper> findByworkIdAndSubjectAndQuestionIdAndIsMissingAndTest(Long workId, Subject subject, Long questionId, boolean missing, int test);
 
+    List<Paper> findByworkIdAndSubjectAndQuestionIdAndIsMissingAndTestAndIdIn(Long workId, Subject subject, Long questionId, boolean missing, int test, List<Long> paperIds);
+
     List<Paper> findByWorkIdAndSubjectAndIsMissingFalseAndActiveTrueAndScoreBatchNoIsNull(Long workId, Subject subject, Sort sort);
 
     int countByWorkIdAndSubjectAndIsArbitratedTrue(Long workId, Subject subject);
@@ -356,8 +380,12 @@ public interface PaperRepo extends JpaRepository<Paper, Long>, JpaSpecificationE
 
     int countByWorkIdAndSubjectAndLevelAndScoreNotNull(Long workId, Subject subject, Object id);
 
+    int countByWorkIdAndSubjectAndLevelAndScoreNotNullAndIdIn(Long workId, Subject subject, Object id, List<Long> paperIds);
+
     int countByWorkIdAndSubjectAndQuestionIdAndLevelAndScoreNotNull(Long workId, Subject subject, Long questionId, String valueOf);
 
+    int countByWorkIdAndSubjectAndQuestionIdAndLevelAndScoreNotNullAndIdIn(Long workId, Subject subject, Long questionId, String valueOf, List<Long> paperIds);
+
     List<Paper> findByWorkIdAndQuestionIdAndSubjectAndIsMissingFalseAndActiveTrueAndScoreBatchNoIsNull(Long workId, Long questionId0, Subject subject, Sort sort);
 
     @Query("select max(p.batchNo) from Paper p where p.workId = ?1")
@@ -371,6 +399,9 @@ public interface PaperRepo extends JpaRepository<Paper, Long>, JpaSpecificationE
     @Query("select max(p.batchNo) from Paper p where p.workId = ?1 and p.subject = ?2")
     Long findMaxBatchNoByWorkIdAndSubject(Long workId, Subject subject);
 
+    @Query("select max(p.batchNo) from Paper p where p.workId = ?1 and p.subject = ?2 and p.id in ?3")
+    Long findMaxBatchNoByWorkIdAndSubjectAndIdIn(Long workId, Subject subject, List<Long> paperIds);
+
     @Query(value = "select cast(p.batch_no as char) from paper p where p.work_id = ?1 and p.subject = ?2 order by p.batch_no desc limit 1", nativeQuery = true)
     List<Object> findBatchNoByWorkIdAndSubject(Long workId, String subject);
 
@@ -392,5 +423,22 @@ public interface PaperRepo extends JpaRepository<Paper, Long>, JpaSpecificationE
     @Query(value = "update paper p set p.level = case p.is_sample when true then p.level else null end, p.redo_level = null,p.sort_num = case p.is_sample when true then p.sort_num else null end, p.batch_no = null, p.is_active = false, p.is_arbitrated = 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);
 
+    int countByWorkIdAndSubjectAndIsArbitratedTrueAndIdIn(Long workId, Subject subject, List<Long> paperIds);
+
+    @Query("select max(p.scoreBatchNo) from Paper p where p.workId = ?1 and p.subject = ?2 and p.id in ?3")
+    Long findMaxScoreBatchNoByWorkIdAndSubjectAndIdIn(Long workId, Subject subject, List<Long> paperIds);
+
+    @Query(value = "SELECT p.`score`,SUM(IF(p.`is_shift` = 0, 1, 0))," +
+            "SUM(IF(p.`is_rejected` = 1, 1, 0))," +
+            "SUM(IF(p.`is_arbitrated` = 1, 1, 0))," +
+            "SUM(IF(p.`is_shift` = 1, 1, 0))," +
+            "SUM(IF(p.`is_shift_score` = 1, 1, 0)) " +
+            "FROM paper p " +
+            "WHERE p.`question_id` = :questionId and p.is_missing = false and p.is_test = :test and p.score is null and p.score_batch_no is not null and p.id in (:paperIds) " +
+            "GROUP BY p.`score`", nativeQuery = true)
+    List<Object[]> countScoreGroupByLevelAllAndIdIn(@Param("questionId") Long questionId, @Param("test") int test, @Param("paperIds") List<Long> paperIds);
+
+    long countByWorkIdAndSubjectAndIdIn(Long workId, Subject subject, List<Long> paperIds);
+
 //    List<Paper> findByWorkIdAndSubjectAndInspectRange(Long workId, Subject subject, Long inspectRange);
 }

+ 4 - 0
stmms-ms-core/src/main/java/cn/com/qmth/stmms/ms/core/specification/StudentSpecification.java

@@ -148,10 +148,14 @@ public class StudentSpecification extends PagingAndSortingSpecification {
             if (getAreaCode() != null && getAreaCode() != "") {
                 predicates.add(cb.equal(root.get("areaCode"), getAreaCode()));
             }
+            // 查漏(缺一科或者两科)
             if ("ONE".equals(getSubject())) {
                 listPermission1.add(cb.equal(root.get("uploadStatus"), "SX:1,SC:1,SM:0"));
                 listPermission1.add(cb.equal(root.get("uploadStatus"), "SX:1,SC:0,SM:1"));
                 listPermission1.add(cb.equal(root.get("uploadStatus"), "SX:0,SC:1,SM:1"));
+                listPermission1.add(cb.equal(root.get("uploadStatus"), "SX:0,SC:0,SM:1"));
+                listPermission1.add(cb.equal(root.get("uploadStatus"), "SX:0,SC:1,SM:0"));
+                listPermission1.add(cb.equal(root.get("uploadStatus"), "SX:1,SC:0,SM:0"));
 
             } else {
                 if (getIsAbsent() != null) {

+ 56 - 64
stmms-ms-marking/src/main/java/cn/com/qmth/stmms/ms/marking/api/MakrerApi.java

@@ -2,6 +2,7 @@ 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.ServletUtil;
 import cn.com.qmth.stmms.ms.commons.utils.SqlUtil;
 import cn.com.qmth.stmms.ms.core.cache.ParamCache;
 import cn.com.qmth.stmms.ms.core.domain.Level;
@@ -11,6 +12,7 @@ import cn.com.qmth.stmms.ms.core.domain.Student;
 import cn.com.qmth.stmms.ms.core.domain.enums.TrialEnum;
 import cn.com.qmth.stmms.ms.core.domain.user.MarkRight;
 import cn.com.qmth.stmms.ms.core.domain.user.MarkUser;
+import cn.com.qmth.stmms.ms.core.domain.user.MarkerGroupLeader;
 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;
@@ -18,12 +20,14 @@ 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.GroupingService;
+import cn.com.qmth.stmms.ms.marking.service.MarkerGroupLeaderService;
 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;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
+import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 
 import java.math.BigDecimal;
@@ -81,6 +85,12 @@ public class MakrerApi {
     @Autowired
     MarkingService markingService;
 
+    @Autowired
+    MarkerGroupLeaderService markerGroupLeaderService;
+
+    @Autowired
+    GroupingService groupingService;
+
     /**
      * 评卷员信息
      *
@@ -125,6 +135,12 @@ public class MakrerApi {
         } else if (MarkStage.LEVEL == markSubject.getStage()) {
             markUsers = markUsers.stream().filter(m -> m.getMarkRight() == MarkRight.ALLOW_SCORING || m.getMarkRight() == MarkRight.ALLOW_ALL).collect(Collectors.toList());
         }
+
+        // 加入科组长
+        List<MarkUser> leaderMarkUsers = markUserRepo.findByWorkIdAndSubjectAndRole(workId, subject, Role.MARK_LEADER);
+        if (!CollectionUtils.isEmpty(leaderMarkUsers)) {
+            markUsers.addAll(leaderMarkUsers);
+        }
         return markUsers;
     }
 
@@ -575,7 +591,7 @@ public class MakrerApi {
     }
 
     /**
-     * 各评卷员评卷进度、考区评卷进度
+     * 管理员-各评卷员评卷进度、考区评卷进度
      *
      * @return
      */
@@ -588,7 +604,6 @@ public class MakrerApi {
         if (markSubject.getStage().name() == MarkStage.INIT.name()) {
             List<Student> students = studentRepo.findByWorkIdAndTest(workId, String.valueOf(TrialEnum.DEFAULT.getId()));
             long stuTotalCount = students.stream().count();
-            long stuAbsentCount = students.stream().filter(s -> s.isAbsent()).count();
             long c = 0L;
             for (Student student : students) {
                 String[] uploadStatus = student.getUploadStatus().split(",");
@@ -610,75 +625,52 @@ public class MakrerApi {
             objectMap.put("totalProgress", progressDTO);
         } else {
             //已评任务数
-            int successCount = 0;
-            if (markSubject.getStage().name() == MarkStage.LEVEL.name()) {
-                successCount = paperRepo.countByWorkIdAndSubjectAndLevelNotNullAndIsMissingFalseAndActiveTrueAndTest(workId, subject, 0);
-            }
-            if (markSubject.getStage().name() == MarkStage.SCORE.name()) {
-                successCount = paperRepo.countByWorkIdAndSubjectAndScoreNotNullAndIsMissingFalseAndActiveTrueAndTest(workId, subject, 0);
-            }
-            //所有任务数(查询所有有效试卷)
-            int totalCount = paperRepo.countByWorkIdAndSubjectAndIsMissingFalseAndTest(workId, subject, markSubject.getTest());
-
-            BigDecimal waitTotal = BigDecimal.valueOf(totalCount).subtract(BigDecimal.valueOf(successCount));
-            //进度
-            BigDecimal progress = BigDecimal.ZERO.compareTo(BigDecimal.valueOf(totalCount)) == 0 ? BigDecimal.ZERO : BigDecimal.valueOf(successCount).multiply(BigDecimal.valueOf(100)).divide(BigDecimal.valueOf(totalCount), 2, BigDecimal.ROUND_HALF_UP);
-
-            LevleProgressDTO progressDTO = new LevleProgressDTO();
-            progressDTO.setSuccessCount(successCount);
-            progressDTO.setTotalCount(totalCount);
-            progressDTO.setWaitCount(waitTotal.intValue());
-            progressDTO.setProgress(progress.doubleValue());
-            objectMap.put("totalProgress", progressDTO);
+            groupingService.getTotalProgress(workId, markSubject, objectMap);
         }
 
 
         //考区进度
-        List<Object[]> areas;
-        if (markSubject.getStage().name() == MarkStage.SCORE.name()) {
-            areas = markTaskRepo.listGroupByAreaName(workId, markSubject.getSubject().name());
-        } else {
-            areas = markTaskRepo.listGroupByAreaName(workId, markSubject.getSubject().name(), markSubject.getTest());
-        }
-        if (areas != null) {
-            List<QuestionStatDTO> questionStatDTOs = new ArrayList<>();
-            for (Object[] objects : areas) {
-                QuestionStatDTO dto = questionStatAssembler.toProgressDTO(objects);
-                questionStatDTOs.add(dto);
-            }
-            objectMap.put("areaProgress", questionStatDTOs);
-        }
+        groupingService.getAreaProgress(workId, markSubject, objectMap);
+
+        // 查询分组内科组长和评卷员
+        List<Long> userMarkLeaders = new ArrayList<>();
+        groupingService.getGroupMarkersProgress(workId, markSubject, userMarkLeaders, null, true, objectMap);
 
         //科组长
-        List<MarkUser> markUser = markUserRepo.findByWorkIdAndSubjectAndRole(workId, subject, Role.MARK_LEADER);
-        //仲裁数量
-        int arbitrate = paperRepo.countByWorkIdAndSubjectAndIsArbitratedTrue(workId, subject);
-        if (markUser != null && markUser.size() > 0) {
-            Map map = new HashMap();
-            map.put("loginName", markUser.get(0).getLoginName());
-            map.put("name", markUser.get(0).getName());
-            map.put("arbitrated", arbitrate);
-            objectMap.put("kzz", map);
-        }
+        groupingService.getMakerLeaderProgress(workId, subject, userMarkLeaders, objectMap);
 
-        //各评卷员评卷进度
-        List<Object[]> qStats;
-        Long batchNo;
-        if (markSubject.getStage().name() == MarkStage.SCORE.name()) {
-            batchNo = paperRepo.findMaxScoreBatchNoByWorkIdAndSubject(workId, markSubject.getSubject());
-            qStats = markTaskRepo.listGroupByQuestionAndMarkerAndScoreBatchNo(workId, markSubject.getSubject().name(), markSubject.getStage().ordinal(), batchNo);
-        } else {
-            batchNo = paperRepo.findMaxBatchNoByWorkIdAndSubject(workId, markSubject.getSubject());
-            qStats = markTaskRepo.listGroupByQuestionAndMarkerAndBatchNo(workId, markSubject.getSubject().name(), markSubject.getStage().ordinal(), markSubject.getTest(), batchNo);
-        }
-        if (qStats != null) {
-            List<MarkQuestionStatDTO> questionStatDTOs = new ArrayList<>();
-            for (Object[] objects : qStats) {
-                MarkQuestionStatDTO dto = questionStatAssembler.toMarkProgressDTO(objects, workId, subject);
-                questionStatDTOs.add(dto);
-            }
-            objectMap.put("markerProgress", questionStatDTOs);
+        return objectMap;
+    }
+
+    /**
+     * 科组长-各评卷员评卷进度、考区评卷进度
+     *
+     * @return
+     */
+    @RequestMapping(value = "/mark_leader/stat/progress", method = RequestMethod.GET)
+    public Map markLeaderProgress(@RequestParam Long workId, @RequestParam Subject subject) {
+        Map<String, Object> objectMap = new HashMap<>();
+        MarkSubject markSubject = markSubjectRepo.findOne(workId + "-" + subject.toString());
+
+        Long markerId = ServletUtil.getUserId();
+        List<MarkerGroupLeader> markerGroupLeaders = markerGroupLeaderService.listByWorkIdAndSubjectAndStageAndMarkLeaderId(workId, markSubject, markerId);
+        boolean isTotalMarkLeader = CollectionUtils.isEmpty(markerGroupLeaders);
+
+        //已评任务数
+        groupingService.getTotalProgress(workId, markSubject, objectMap);
+
+        //考区进度
+        groupingService.getAreaProgress(workId, markSubject, objectMap);
+
+        // 查询分组内科组长和评卷员
+        List<Long> userMarkLeaders = new ArrayList<>();
+        groupingService.getGroupMarkersProgress(workId, markSubject, userMarkLeaders, markerId, isTotalMarkLeader, objectMap);
+
+        if(isTotalMarkLeader) {
+            //科组长
+            groupingService.getMakerLeaderProgress(workId, subject, userMarkLeaders, objectMap);
         }
+
         return objectMap;
     }
 

+ 175 - 17
stmms-ms-marking/src/main/java/cn/com/qmth/stmms/ms/marking/api/MarkSubjectApi.java

@@ -1,21 +1,23 @@
 package cn.com.qmth.stmms.ms.marking.api;
 
+import cn.com.qmth.stmms.ms.commons.utils.ServletUtil;
 import cn.com.qmth.stmms.ms.core.domain.*;
-import cn.com.qmth.stmms.ms.core.domain.user.MarkRight;
-import cn.com.qmth.stmms.ms.core.domain.user.MarkUser;
-import cn.com.qmth.stmms.ms.core.domain.user.MarkerGroup;
-import cn.com.qmth.stmms.ms.core.domain.user.Role;
+import cn.com.qmth.stmms.ms.core.domain.user.*;
 import cn.com.qmth.stmms.ms.core.repository.*;
 import cn.com.qmth.stmms.ms.marking.assembler.LevelStatAssembler;
 import cn.com.qmth.stmms.ms.marking.assembler.QuestionStatAssembler;
 import cn.com.qmth.stmms.ms.marking.dto.LevelStatDTO;
 import cn.com.qmth.stmms.ms.marking.dto.LevleProgressDTO;
 import cn.com.qmth.stmms.ms.marking.dto.QuestionStatDTO;
+import cn.com.qmth.stmms.ms.marking.service.GroupingService;
+import cn.com.qmth.stmms.ms.marking.service.MarkerGroupLeaderService;
 import cn.com.qmth.stmms.ms.marking.service.StageControlService;
 import com.alibaba.fastjson.JSONObject;
+import org.hibernate.annotations.NaturalId;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
+import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
@@ -62,6 +64,9 @@ public class MarkSubjectApi {
     @Autowired
     MarkTaskRepo markTaskRepo;
 
+    @Autowired
+    MarkerGroupLeaderService markerGroupLeaderService;
+
     /**
      * 查询所有科目状态
      *
@@ -125,14 +130,14 @@ public class MarkSubjectApi {
     }
 
     /**
-     * 该评卷科目的分档统计信息
+     * 管理员-该评卷科目的分档统计信息
      *
      * @param markSubject 评卷科目id
      * @param questionId  试题id
      * @return
      */
     @RequestMapping(value = "{markSubject}/stat/levels", method = RequestMethod.GET)
-    public List<LevelStatDTO> levelStat(HttpServletRequest request, @PathVariable MarkSubject markSubject, @RequestParam Long questionId) {
+    public List<LevelStatDTO> levelStat(@PathVariable MarkSubject markSubject, @RequestParam Long questionId) {
         List<LevelStatDTO> levelStatDTOs = new ArrayList<>();
         paperRepo.countGroupByLevelAll(questionId, markSubject.getTest())
                 .forEach(o -> levelStatDTOs.add(levelStatAssembler.toDTO(o)));
@@ -180,6 +185,109 @@ public class MarkSubjectApi {
         return levelStatDTOs;
     }
 
+    /**
+     * 科组长-该评卷科目的分档统计信息
+     *
+     * @param markSubject 评卷科目id
+     * @param questionId  试题id
+     * @return
+     */
+    @RequestMapping(value = "{markSubject}/mark_leader/stat/levels", method = RequestMethod.GET)
+    public List<LevelStatDTO> markLeaderLevelStat(@PathVariable MarkSubject markSubject, @RequestParam Long questionId) {
+        Long markerId = ServletUtil.getUserId();
+        List<MarkerGroupLeader> markerGroupLeaders = markerGroupLeaderService.listByWorkIdAndSubjectAndStageAndMarkLeaderId(markSubject.getWorkId(), markSubject, markerId);
+        List<Long> paperIds = null;
+        if (!CollectionUtils.isEmpty(markerGroupLeaders)) {
+            List<Long> markers = markerGroupLeaders.stream().map(m -> m.getMarkerId()).distinct().collect(Collectors.toList());
+            paperIds = markerGroupLeaderService.listPaperIdsByWorkIdAndSubjectAndStageAndMarkerIds(markSubject.getWorkId(), markSubject.getSubject(), markSubject.getStage(), markers);
+        }
+        List<LevelStatDTO> levelStatDTOs = new ArrayList<>();
+        List<Level> levels = levelRepo.findByWorkId(markSubject.getWorkId());
+        if (CollectionUtils.isEmpty(paperIds)) {
+            paperRepo.countGroupByLevelAll(questionId, markSubject.getTest())
+                    .forEach(o -> levelStatDTOs.add(levelStatAssembler.toDTO(o)));
+            for (Level level : levels) {
+                long count = levelStatDTOs.stream().filter(l -> String.valueOf(l.getId()).equals(level.getCode())).count();
+                //没有该档位,新增
+                if (count == 0) {
+                    LevelStatDTO dto = new LevelStatDTO();
+                    dto.setId(level.getCode());
+                    dto.setCount(0);
+                    dto.setPercent(0.0);
+                    levelStatDTOs.add(dto);
+                }
+            }
+            //当前考区总数
+            long total = paperRepo.countByWorkIdAndQuestionId(markSubject.getWorkId(), questionId);
+            //所有考区总数
+            long gtotal = paperRepo.countByWorkIdAndSubject(markSubject.getWorkId(), markSubject.getSubject());
+            levelStatDTOs.forEach(o -> {
+                if (o.getId() != null) {
+                    //当前考区档位占比
+                    double p = total == 0 ? 0 : (double) o.getCount() / total * 100;
+                    BigDecimal bd = new BigDecimal(p).setScale(3, RoundingMode.HALF_EVEN);
+                    o.setPercent(bd.doubleValue());
+                    //考区阈值
+                    Level level = levels.stream().filter(l -> l.getCode().equals(o.getId())).collect(Collectors.toList()).get(0);
+                    o.setKdpt(level.getKdpt());
+                    //所有考区档位数量
+                    long gcount = paperRepo.countByWorkIdAndSubjectAndLevel(markSubject.getWorkId(), markSubject.getSubject(), String.valueOf(o.getId()));
+                    o.setGcount((int) gcount);
+                    //所有考区档位占比
+                    double gp = gtotal == 0 ? 0 : (double) o.getGcount() / gtotal * 100;
+                    BigDecimal gbd = new BigDecimal(gp).setScale(3, RoundingMode.HALF_EVEN);
+                    o.setGpercent(gbd.doubleValue());
+                    o.setPt(level.getPt());
+                }
+            });
+        } else {
+            paperRepo.countGroupByLevelAllAndIdIn(questionId, markSubject.getTest(), paperIds)
+                    .forEach(o -> levelStatDTOs.add(levelStatAssembler.toDTO(o)));
+            for (Level level : levels) {
+                long count = levelStatDTOs.stream().filter(l -> String.valueOf(l.getId()).equals(level.getCode())).count();
+                //没有该档位,新增
+                if (count == 0) {
+                    LevelStatDTO dto = new LevelStatDTO();
+                    dto.setId(level.getCode());
+                    dto.setCount(0);
+                    dto.setPercent(0.0);
+                    levelStatDTOs.add(dto);
+                }
+            }
+            //当前考区总数
+            long total = paperRepo.countByWorkIdAndQuestionIdAndIdIn(markSubject.getWorkId(), questionId, paperIds);
+            //所有考区总数
+            long gtotal = paperRepo.countByWorkIdAndSubjectAndIdIn(markSubject.getWorkId(), markSubject.getSubject(), paperIds);
+            List<Long> finalPaperIds = paperIds;
+            levelStatDTOs.forEach(o -> {
+                if (o.getId() != null) {
+                    //当前考区档位占比
+                    double p = total == 0 ? 0 : (double) o.getCount() / total * 100;
+                    BigDecimal bd = new BigDecimal(p).setScale(3, RoundingMode.HALF_EVEN);
+                    o.setPercent(bd.doubleValue());
+                    //考区阈值
+                    Level level = levels.stream().filter(l -> l.getCode().equals(o.getId())).collect(Collectors.toList()).get(0);
+                    o.setKdpt(level.getKdpt());
+                    //所有考区档位数量
+                    long gcount = paperRepo.countByWorkIdAndSubjectAndLevelAndIdIn(markSubject.getWorkId(), markSubject.getSubject(), String.valueOf(o.getId()), finalPaperIds);
+                    o.setGcount((int) gcount);
+                    //所有考区档位占比
+                    double gp = gtotal == 0 ? 0 : (double) o.getGcount() / gtotal * 100;
+                    BigDecimal gbd = new BigDecimal(gp).setScale(3, RoundingMode.HALF_EVEN);
+                    o.setGpercent(gbd.doubleValue());
+                    o.setPt(level.getPt());
+                }
+            });
+        }
+        Collections.sort(levelStatDTOs, (o1, o2) -> {
+            if (o1.getId() == null || o2.getId() == null) {
+                return 1;
+            }
+            return o1.getId().toString().compareTo(o2.getId().toString());
+        });
+        return levelStatDTOs;
+    }
+
 
     /**
      * 该评卷科目的分档统计信息
@@ -220,6 +328,63 @@ public class MarkSubjectApi {
         return levelStatDTOs;
     }
 
+    /**
+     * 该评卷科目的分档统计信息
+     *
+     * @param markSubject 评卷科目id
+     * @param questionId  试题id
+     * @return
+     */
+    @RequestMapping(value = "{markSubject}/mark_leader/stat/scores", method = RequestMethod.GET)
+    public List<LevelStatDTO> markLeaderScoreStat(@PathVariable MarkSubject markSubject,
+                                                  @RequestParam Long questionId) {
+        Long markerId = ServletUtil.getUserId();
+        List<MarkerGroupLeader> markerGroupLeaders = markerGroupLeaderService.listByWorkIdAndSubjectAndStageAndMarkLeaderId(markSubject.getWorkId(), markSubject, markerId);
+        List<Long> paperIds = null;
+        if (!CollectionUtils.isEmpty(markerGroupLeaders)) {
+            List<Long> markers = markerGroupLeaders.stream().map(m -> m.getMarkerId()).distinct().collect(Collectors.toList());
+            paperIds = markerGroupLeaderService.listPaperIdsByWorkIdAndSubjectAndStageAndMarkerIds(markSubject.getWorkId(), markSubject.getSubject(), markSubject.getStage(), markers);
+        }
+
+        List<LevelStatDTO> levelStatDTOs = new ArrayList<>();
+        List<Level> levels = levelRepo.findByWorkId(markSubject.getWorkId());
+        if (CollectionUtils.isEmpty(paperIds)) {
+            paperRepo.countScoreGroupByLevelAll(questionId, markSubject.getTest())
+                    .forEach(o -> levelStatDTOs.add(levelStatAssembler.toDTO(o)));
+            for (Level level : levels) {
+                //没有该档位,新增
+                LevelStatDTO dto = new LevelStatDTO();
+                dto.setId(level.getCode());
+                dto.setPercent(0.0);
+                int count = paperRepo.countByWorkIdAndSubjectAndQuestionIdAndLevelAndScoreNotNull(markSubject.getWorkId(), markSubject.getSubject(), questionId, level.getCode());
+                dto.setCount(count);
+                int gcount = paperRepo.countByWorkIdAndSubjectAndLevelAndScoreNotNull(markSubject.getWorkId(), markSubject.getSubject(), level.getCode());
+                dto.setGcount(gcount);
+                levelStatDTOs.add(dto);
+            }
+        } else {
+            paperRepo.countScoreGroupByLevelAllAndIdIn(questionId, markSubject.getTest(), paperIds)
+                    .forEach(o -> levelStatDTOs.add(levelStatAssembler.toDTO(o)));
+            for (Level level : levels) {
+                LevelStatDTO dto = new LevelStatDTO();
+                dto.setId(level.getCode());
+                dto.setPercent(0.0);
+                int count = paperRepo.countByWorkIdAndSubjectAndQuestionIdAndLevelAndScoreNotNullAndIdIn(markSubject.getWorkId(), markSubject.getSubject(), questionId, level.getCode(), paperIds);
+                dto.setCount(count);
+                int gcount = paperRepo.countByWorkIdAndSubjectAndLevelAndScoreNotNullAndIdIn(markSubject.getWorkId(), markSubject.getSubject(), level.getCode(), paperIds);
+                dto.setGcount(gcount);
+                levelStatDTOs.add(dto);
+            }
+        }
+        Collections.sort(levelStatDTOs, (o1, o2) -> {
+            if (o1.getId() == null || o2.getId() == null) {
+                return 1;
+            }
+            return o1.getId().toString().compareTo(o2.getId().toString());
+        });
+        return levelStatDTOs;
+    }
+
     /**
      * 该评卷科目下的评卷员分组列表
      *
@@ -244,14 +409,14 @@ public class MarkSubjectApi {
         }
         if (MarkStage.LEVEL == markSubject.getStage() || MarkStage.SCORE == markSubject.getStage()) {
             int count = markTaskRepo.countByWorkIdAndSubjectAndStage(markSubject.getWorkId(), markSubject.getSubject(), markSubject.getStage());
-            if(count > 0){
+            if (count > 0) {
                 throw new RuntimeException("当前阶段已发布任务,不能编辑分组");
             }
         }
 
         markerGroup.setWorkId(markSubject.getWorkId());
         markerGroup.setSubject(markSubject.getSubject());
-        return markerGroupRepo.save(markerGroup);
+        return markerGroupLeaderService.save(markerGroup, markSubject.getStage().equals(MarkStage.INIT) ? MarkStage.LEVEL : markSubject.getStage());
     }
 
     /**
@@ -275,14 +440,7 @@ public class MarkSubjectApi {
      */
     @RequestMapping(value = "{markSubject}/markergroups/{domain}", method = RequestMethod.DELETE)
     public void removeMarkerGroup(@PathVariable MarkSubject markSubject, @PathVariable MarkerGroup domain) {
-        int count = 0;
-        if (MarkStage.LEVEL == markSubject.getStage() || MarkStage.SCORE == markSubject.getStage()) {
-            count = markTaskRepo.countByWorkIdAndSubjectAndStage(markSubject.getWorkId(), markSubject.getSubject(), markSubject.getStage());
-        }
-        if(count > 0){
-            throw new RuntimeException("当前阶段已发布任务,不能删除分组");
-        }
-        markerGroupRepo.delete(domain);
+        markerGroupLeaderService.delete(markSubject, domain);
     }
 
     /**
@@ -391,7 +549,7 @@ public class MarkSubjectApi {
      * @param markSubject 评卷科目id
      */
     @RequestMapping(value = "{markSubject}/scoreProgress", method = RequestMethod.GET)
-    public List scoreProgress(@PathVariable MarkSubject markSubject,@RequestParam(defaultValue = "") Long questionId) {
+    public List scoreProgress(@PathVariable MarkSubject markSubject, @RequestParam(defaultValue = "") Long questionId) {
         return stageControlService.scoreProgress(markSubject, questionId);
     }
 

+ 26 - 3
stmms-ms-marking/src/main/java/cn/com/qmth/stmms/ms/marking/api/MarkTaskApi.java

@@ -3,6 +3,7 @@ package cn.com.qmth.stmms.ms.marking.api;
 import cn.com.qmth.stmms.ms.commons.config.ScoreConfig;
 import cn.com.qmth.stmms.ms.commons.lock.LockService;
 import cn.com.qmth.stmms.ms.commons.lock.LockType;
+import cn.com.qmth.stmms.ms.commons.utils.ServletUtil;
 import cn.com.qmth.stmms.ms.commons.utils.SqlUtil;
 import cn.com.qmth.stmms.ms.commons.web.PageableDTO;
 import cn.com.qmth.stmms.ms.core.cache.ParamCache;
@@ -10,6 +11,7 @@ import cn.com.qmth.stmms.ms.core.domain.*;
 import cn.com.qmth.stmms.ms.core.domain.enums.TrialEnum;
 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.MarkerGroupLeader;
 import cn.com.qmth.stmms.ms.core.repository.*;
 import cn.com.qmth.stmms.ms.core.vo.Subject;
 import cn.com.qmth.stmms.ms.marking.assembler.MarkTaskAssembler;
@@ -18,6 +20,7 @@ import cn.com.qmth.stmms.ms.marking.assembler.PaperAssembler;
 import cn.com.qmth.stmms.ms.marking.dto.LevelDetailDTO;
 import cn.com.qmth.stmms.ms.marking.dto.MarkTaskDTO;
 import cn.com.qmth.stmms.ms.marking.dto.PaperDTO;
+import cn.com.qmth.stmms.ms.marking.service.MarkerGroupLeaderService;
 import cn.com.qmth.stmms.ms.marking.service.MarkingService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -31,11 +34,13 @@ import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 import org.springframework.orm.jpa.vendor.OpenJpaDialect;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 
 import javax.persistence.criteria.*;
 import java.math.BigDecimal;
 import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * 评卷任务数据api
@@ -82,6 +87,9 @@ public class MarkTaskApi {
     @Autowired
     LockService lockService;
 
+    @Autowired
+    MarkerGroupLeaderService markerGroupLeaderService;
+
     /**
      * 评卷员的评卷任务
      *
@@ -480,15 +488,30 @@ public class MarkTaskApi {
     public List<LevelDetailDTO> levelStatDetail(@RequestParam Long workId,
                                                 @RequestParam Subject subject,
                                                 @RequestParam(required = false) Long questionId) {
+        MarkSubject markSubject = markSubjectRepo.findOne(workId + "-" + subject.name());
+        Long markerId = ServletUtil.getUserId();
+        List<MarkerGroupLeader> markerGroupLeaders = markerGroupLeaderService.listByWorkIdAndSubjectAndStageAndMarkLeaderId(markSubject.getWorkId(), markSubject, markerId);
+        List<Long> paperIds = null;
+        if (!CollectionUtils.isEmpty(markerGroupLeaders)) {
+            List<Long> markers = markerGroupLeaders.stream().map(m -> m.getMarkerId()).distinct().collect(Collectors.toList());
+            paperIds = markerGroupLeaderService.listPaperIdsByWorkIdAndSubjectAndStageAndMarkerIds(markSubject.getWorkId(), markSubject.getSubject(), markSubject.getStage(), markers);
+        }
 
         List<Level> levels = levelRepo.findByWorkIdOrderByCode(workId);
         List<Paper> papers;
         if (questionId == null) {
-            papers = paperRepo.findByWorkIdAndSubjectAndIsMissingAndTest(workId, subject, false, TrialEnum.DEFAULT.getId());
+            if(!CollectionUtils.isEmpty(paperIds)) {
+                papers = paperRepo.findByWorkIdAndSubjectAndIsMissingAndTestAndIdIn(workId, subject, false, TrialEnum.DEFAULT.getId(), paperIds);
+            } else {
+                papers = paperRepo.findByWorkIdAndSubjectAndIsMissingAndTest(workId, subject, false, TrialEnum.DEFAULT.getId());
+            }
         } else {
-            papers = paperRepo.findByworkIdAndSubjectAndQuestionIdAndIsMissingAndTest(workId, subject, questionId, false, TrialEnum.DEFAULT.getId());
+            if(!CollectionUtils.isEmpty(paperIds)) {
+                papers = paperRepo.findByworkIdAndSubjectAndQuestionIdAndIsMissingAndTestAndIdIn(workId, subject, questionId, false, TrialEnum.DEFAULT.getId(), paperIds);
+            } else {
+                papers = paperRepo.findByworkIdAndSubjectAndQuestionIdAndIsMissingAndTest(workId, subject, questionId, false, TrialEnum.DEFAULT.getId());
+            }
         }
-        MarkSubject markSubject = markSubjectRepo.findOne(workId + "-" + subject.name());
 
         List<LevelDetailDTO> list = new ArrayList<>();
         for (Level level : levels) {

+ 27 - 5
stmms-ms-marking/src/main/java/cn/com/qmth/stmms/ms/marking/api/PaperApi.java

@@ -1,12 +1,14 @@
 package cn.com.qmth.stmms.ms.marking.api;
 
 import cn.com.qmth.stmms.ms.commons.config.SystemConfig;
+import cn.com.qmth.stmms.ms.commons.utils.ServletUtil;
 import cn.com.qmth.stmms.ms.commons.web.PageableDTO;
 import cn.com.qmth.stmms.ms.core.domain.ExamQuestion;
 import cn.com.qmth.stmms.ms.core.domain.MarkStage;
 import cn.com.qmth.stmms.ms.core.domain.MarkSubject;
 import cn.com.qmth.stmms.ms.core.domain.Paper;
 import cn.com.qmth.stmms.ms.core.domain.task.MarkTask;
+import cn.com.qmth.stmms.ms.core.domain.user.MarkerGroupLeader;
 import cn.com.qmth.stmms.ms.core.repository.ExamQuestionRepo;
 import cn.com.qmth.stmms.ms.core.repository.MarkSubjectRepo;
 import cn.com.qmth.stmms.ms.core.repository.MarkTaskRepo;
@@ -16,6 +18,7 @@ import cn.com.qmth.stmms.ms.marking.assembler.MarkTaskAssembler;
 import cn.com.qmth.stmms.ms.marking.assembler.PaperAssembler;
 import cn.com.qmth.stmms.ms.marking.dto.MarkTaskDTO;
 import cn.com.qmth.stmms.ms.marking.dto.PaperDTO;
+import cn.com.qmth.stmms.ms.marking.service.MarkerGroupLeaderService;
 import cn.com.qmth.stmms.ms.marking.service.MarkingService;
 import javafx.beans.binding.ObjectExpression;
 import org.apache.commons.codec.digest.DigestUtils;
@@ -28,10 +31,12 @@ import org.springframework.data.jpa.domain.Specification;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
 import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
+import javax.persistence.criteria.CriteriaBuilder;
 import javax.persistence.criteria.Predicate;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
@@ -71,6 +76,9 @@ public class PaperApi {
     @Autowired
     SystemConfig systemConfig;
 
+    @Autowired
+    MarkerGroupLeaderService markerGroupLeaderService;
+
     /**
      * 单个试卷信息
      *
@@ -214,8 +222,17 @@ public class PaperApi {
                             @RequestParam(required = false) Boolean reject,
                             @RequestParam(defaultValue = "false") Boolean isScore,//打分阶段该档位已打分数
                             Pageable pageable) {
-        //查询最大批次号
-//        Long batchNo = paperRepo.findByQuestionId(questionId);
+        ExamQuestion examQuestion = examQuestionRepo.findOne(questionId);
+        MarkSubject markSubject = markSubjectRepo.findOne(examQuestion.getWorkId()+"-" + examQuestion.getSubject().name());
+        Long markerId = ServletUtil.getUserId();
+        List<MarkerGroupLeader> markerGroupLeaders = markerGroupLeaderService.listByWorkIdAndSubjectAndStageAndMarkLeaderId(markSubject.getWorkId(), markSubject, markerId);
+        List<Long> paperIds = null;
+        if (!CollectionUtils.isEmpty(markerGroupLeaders)) {
+            List<Long> markers = markerGroupLeaders.stream().map(m -> m.getMarkerId()).distinct().collect(Collectors.toList());
+            paperIds = markerGroupLeaderService.listPaperIdsByWorkIdAndSubjectAndStageAndMarkerIds(markSubject.getWorkId(), markSubject.getSubject(), markSubject.getStage(), markers);
+        }
+
+        List<Long> finalPaperIds = paperIds;
         Specification<Paper> specification = (root, query, builder) -> {
             List<Predicate> predicates = new ArrayList<>();
             if(Objects.nonNull(questionId)) {
@@ -243,6 +260,13 @@ public class PaperApi {
                         predicates.add(builder.isNotNull(root.get("batchNo")));
                     }
                 }
+                if(!CollectionUtils.isEmpty(finalPaperIds)) {
+                    CriteriaBuilder.In<Object> in = builder.in(root.get("id"));
+                    for (Long id : finalPaperIds) {
+                        in.value(id);
+                    }
+                    predicates.add(builder.and(builder.and(in)));
+                }
             }
             if (arbi != null) {
                 predicates.add(builder.equal(root.get("isArbitrated"), arbi));
@@ -265,9 +289,7 @@ public class PaperApi {
         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));
-        });
+        papers.forEach(p -> paperDTOs.add(paperAssembler.toDTO(p)));
         return new PageableDTO(paperDTOs, papers.getTotalElements(), papers.getTotalPages(), pageable.getPageNumber());
     }
 

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

@@ -173,7 +173,7 @@ public class AssignTaskService {
                     map.put(paper.getLevel() + idx, seq);
 
                     int seqNew = 0;
-                    if(seqNewMap.containsKey(paper.getLevel())){
+                    if (seqNewMap.containsKey(paper.getLevel())) {
                         seqNew = (int) seqNewMap.get(paper.getLevel());
                     }
                     seqNewNumber = ++seqNew;
@@ -181,10 +181,12 @@ public class AssignTaskService {
                 }
             }
             int markerCount = 0;
-            for (MarkUser marker : markerGroups.get(idx).getMarkers()) {
-                markerCount ++ ;
+            Set<MarkUser> markUsers = markerGroups.get(idx).getMarkers();
+            markUsers = markUsers.stream().filter(m -> Role.MARKER.equals(m.getRole())).collect(Collectors.toSet());
+            for (MarkUser marker : markUsers) {
+                markerCount++;
                 Long random = getRandom(marker.getId(), paper.getId(), marker.getWorkId(), paper.getExamNumber(), randomMap);
-                MarkTask markTask = null;
+                MarkTask markTask;
                 if (Objects.equals(MarkStage.SCORE, markSubject.getStage())) {
                     markTask = new MarkTask(marker, paper, markSubject.getStage(), random, markSubject.getTest());
                     String levelValue = String.valueOf(levelMap.get(paper.getLevel()).getLevelValue() + 1);
@@ -205,7 +207,7 @@ public class AssignTaskService {
                         markTask = new MarkTask(marker, paper, level, markSubject.getStage(), random, markSubject.getTest());
 
                         // 初始化排序值
-                        if(markerCount == markerGroups.get(idx).getMarkers().size()){
+                        if (markerCount == markerGroups.get(idx).getMarkers().size()) {
                             paper.setSortNum(level.getWeight() * markerCount);
                         }
                     } else {
@@ -297,8 +299,8 @@ public class AssignTaskService {
 
         // 所有用户强制退出
         List<MarkUser> userList = markUserRepo.findByWorkIdAndSubject(markSubject.getWorkId(), markSubject.getSubject());
-        userList = userList.stream().filter(m-> Role.MARKER.equals(m.getRole()) || Role.MARK_LEADER.equals(m.getRole())).collect(Collectors.toList());
-        if(!CollectionUtils.isEmpty(userList)){
+        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());
             }

+ 178 - 11
stmms-ms-marking/src/main/java/cn/com/qmth/stmms/ms/marking/service/GroupingService.java

@@ -1,15 +1,23 @@
 package cn.com.qmth.stmms.ms.marking.service;
 
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
+import cn.com.qmth.stmms.ms.core.domain.MarkStage;
+import cn.com.qmth.stmms.ms.core.domain.MarkSubject;
+import cn.com.qmth.stmms.ms.core.domain.user.MarkUser;
+import cn.com.qmth.stmms.ms.core.domain.user.MarkerGroup;
+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.assembler.QuestionStatAssembler;
+import cn.com.qmth.stmms.ms.marking.dto.LevleProgressDTO;
+import cn.com.qmth.stmms.ms.marking.dto.MarkQuestionStatDTO;
+import cn.com.qmth.stmms.ms.marking.dto.QuestionStatDTO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
 
-import cn.com.qmth.stmms.ms.core.domain.user.MarkUser;
-import cn.com.qmth.stmms.ms.core.domain.user.MarkerGroup;
-import cn.com.qmth.stmms.ms.core.repository.MarkerGroupRepo;
+import java.math.BigDecimal;
+import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * 分组服务
@@ -18,24 +26,43 @@ import cn.com.qmth.stmms.ms.core.repository.MarkerGroupRepo;
 @Service
 public class GroupingService {
 
+    @Autowired
+    private MarkSubjectRepo markSubjectRepo;
+
+    @Autowired
+    PaperRepo paperRepo;
+
+    @Autowired
+    private MarkTaskRepo markTaskRepo;
+
     @Autowired
     private MarkerGroupRepo markerGroupRepo;
 
+    @Autowired
+    private MarkerGroupLeaderService markerGroupLeaderService;
+
+    @Autowired
+    private MarkUserRepo markUserRepo;
+
+    @Autowired
+    private QuestionStatAssembler questionStatAssembler;
+
     /**
      * 自动分组
-     * @param count 组数
+     *
+     * @param count   组数
      * @param markers 评卷员列表
      * @return
      */
-    public List<MarkerGroup> autoGrouping(int count, Iterable<MarkUser> markers){
+    public List<MarkerGroup> autoGrouping(int count, Iterable<MarkUser> markers) {
         List<MarkerGroup> groups = new ArrayList<>();
         for (int i = 0; i < count; i++) {
             groups.add(new MarkerGroup());
         }
         Iterator<MarkUser> iterator = markers.iterator();
         int idx = 0;
-        while (iterator.hasNext()){
-            if(idx >= count){
+        while (iterator.hasNext()) {
+            if (idx >= count) {
                 idx = 0;
             }
             MarkUser marker = iterator.next();
@@ -47,4 +74,144 @@ public class GroupingService {
         markerGroupRepo.save(groups);
         return groups;
     }
+
+    /**
+     * 总体进度
+     *
+     * @param workId
+     * @param objectMap
+     */
+    public void getTotalProgress(Long workId, MarkSubject markSubject, Map<String, Object> objectMap) {
+        int successCount = 0;
+        if (markSubject.getStage().name() == MarkStage.LEVEL.name()) {
+            successCount = paperRepo.countByWorkIdAndSubjectAndLevelNotNullAndIsMissingFalseAndActiveTrueAndTest(workId, markSubject.getSubject(), 0);
+        }
+        if (markSubject.getStage().name() == MarkStage.SCORE.name()) {
+            successCount = paperRepo.countByWorkIdAndSubjectAndScoreNotNullAndIsMissingFalseAndActiveTrueAndTest(workId, markSubject.getSubject(), 0);
+        }
+        //所有任务数(查询所有有效试卷)
+        int totalCount = paperRepo.countByWorkIdAndSubjectAndIsMissingFalseAndTest(workId, markSubject.getSubject(), markSubject.getTest());
+
+        BigDecimal waitTotal = BigDecimal.valueOf(totalCount).subtract(BigDecimal.valueOf(successCount));
+        //进度
+        BigDecimal progress = BigDecimal.ZERO.compareTo(BigDecimal.valueOf(totalCount)) == 0 ? BigDecimal.ZERO : BigDecimal.valueOf(successCount).multiply(BigDecimal.valueOf(100)).divide(BigDecimal.valueOf(totalCount), 2, BigDecimal.ROUND_HALF_UP);
+
+        LevleProgressDTO progressDTO = new LevleProgressDTO();
+        progressDTO.setSuccessCount(successCount);
+        progressDTO.setTotalCount(totalCount);
+        progressDTO.setWaitCount(waitTotal.intValue());
+        progressDTO.setProgress(progress.doubleValue());
+        objectMap.put("totalProgress", progressDTO);
+    }
+
+    /**
+     * 考区进度
+     *
+     * @param workId
+     * @param markSubject
+     * @param objectMap
+     */
+    public void getAreaProgress(Long workId, MarkSubject markSubject, Map<String, Object> objectMap) {
+        List<Object[]> areas;
+        if (markSubject.getStage().name() == MarkStage.SCORE.name()) {
+            areas = markTaskRepo.listGroupByAreaName(workId, markSubject.getSubject().name());
+        } else {
+            areas = markTaskRepo.listGroupByAreaName(workId, markSubject.getSubject().name(), markSubject.getTest());
+        }
+        if (areas != null) {
+            List<QuestionStatDTO> questionStatDTOs = new ArrayList<>();
+            for (Object[] objects : areas) {
+                QuestionStatDTO dto = questionStatAssembler.toProgressDTO(objects);
+                questionStatDTOs.add(dto);
+            }
+            objectMap.put("areaProgress", questionStatDTOs);
+        }
+    }
+
+    /**
+     * 各评卷员进度
+     *  @param workId
+     * @param markSubject
+     * @param userMarkLeaders
+     * @param isTotalMarkLeader
+     * @param objectMap
+     */
+    public void getGroupMarkersProgress(Long workId, MarkSubject markSubject, List<Long> userMarkLeaders, Long markerId, boolean isTotalMarkLeader, Map<String, Object> objectMap) {
+        List<Map<String, Object>> groupMarkers = new ArrayList<>();
+        List<Map<String, List<Long>>> groupLeaderAndMarkers = markerGroupLeaderService.listGroupLeaderAndMarkersByWorkIdAndSubjectAndStage(workId, markSubject.getSubject(), markSubject.getStage());
+        if(!isTotalMarkLeader && Objects.nonNull(markerId)){
+            groupLeaderAndMarkers = groupLeaderAndMarkers.stream().filter(m->m.get("markLeaders").contains(markerId)).collect(Collectors.toList());
+        }
+        if (!CollectionUtils.isEmpty(groupLeaderAndMarkers)) {
+            for (Map<String, List<Long>> groupLeaderAndMarker : groupLeaderAndMarkers) {
+                Map<String, Object> tempMap = new HashMap<>();
+                List<Long> markerLeaders = groupLeaderAndMarker.get("markLeaders");
+                List<Long> markers = groupLeaderAndMarker.get("markers");
+                List<Long> paperIds = markerGroupLeaderService.listPaperIdsByWorkIdAndSubjectAndStageAndMarkerIds(workId, markSubject.getSubject(), markSubject.getStage(), markers);
+                //仲裁数量
+                int arbitrate = CollectionUtils.isEmpty(paperIds) ? 0 : paperRepo.countByWorkIdAndSubjectAndIsArbitratedTrueAndIdIn(workId, markSubject.getSubject(), paperIds);
+
+                if (!CollectionUtils.isEmpty(markerLeaders)) {
+                    userMarkLeaders.addAll(markerLeaders);
+                    List<Map<String, Object>> markerLeaderList = new ArrayList<>();
+                    for (Long markerLeaderId : markerLeaders) {
+                        Map<String, Object> map = new HashMap();
+                        MarkUser markUser = markUserRepo.findOne(markerLeaderId);
+                        map.put("loginName", markUser.getLoginName());
+                        map.put("name", markUser.getName());
+                        map.put("arbitrated", arbitrate);
+                        markerLeaderList.add(map);
+                    }
+                    tempMap.put("kzzProgress", markerLeaderList);
+                }
+
+                // 评卷员
+                //各评卷员评卷进度
+                List<Object[]> qStats;
+                Long batchNo;
+                String markerString = markers.stream().map(m -> String.valueOf(m)).collect(Collectors.joining(","));
+                if (markSubject.getStage().name() == MarkStage.SCORE.name()) {
+                    batchNo = paperRepo.findMaxScoreBatchNoByWorkIdAndSubjectAndIdIn(workId, markSubject.getSubject(), paperIds);
+                    qStats = markTaskRepo.listGroupByQuestionAndMarkerAndScoreBatchNoAndMakerId(workId, markSubject.getSubject().name(), markSubject.getStage().ordinal(), batchNo, markerString);
+                } else {
+                    batchNo = paperRepo.findMaxBatchNoByWorkIdAndSubjectAndIdIn(workId, markSubject.getSubject(), paperIds);
+                    qStats = markTaskRepo.listGroupByQuestionAndMarkerAndBatchNoAndMarkerId(workId, markSubject.getSubject().name(), markSubject.getStage().ordinal(), markSubject.getTest(), batchNo, markerString);
+                }
+                if (qStats != null) {
+                    List<MarkQuestionStatDTO> questionStatDTOs = new ArrayList<>();
+                    for (Object[] objects : qStats) {
+                        MarkQuestionStatDTO dto = questionStatAssembler.toMarkProgressDTO(objects, workId, markSubject.getSubject());
+                        questionStatDTOs.add(dto);
+                    }
+                    tempMap.put("markerProgress", questionStatDTOs);
+                }
+                groupMarkers.add(tempMap);
+            }
+        }
+        objectMap.put("groupMarkers", groupMarkers);
+    }
+
+    /**
+     * 总科组长进度
+     * @param workId
+     * @param subject
+     * @param userMarkLeaders
+     * @param objectMap
+     */
+    public void getMakerLeaderProgress(Long workId, Subject subject, List<Long> userMarkLeaders, Map<String, Object> objectMap) {
+        List<MarkUser> markUsers = markUserRepo.findByWorkIdAndSubjectAndRoleAndIdNotIn(workId, subject, Role.MARK_LEADER, userMarkLeaders);
+        //仲裁数量
+        int arbitrate = paperRepo.countByWorkIdAndSubjectAndIsArbitratedTrue(workId, subject);
+        if (markUsers != null && markUsers.size() > 0) {
+            List<Map> mapList = new ArrayList<>();
+            for (MarkUser markUser : markUsers) {
+                Map map = new HashMap();
+                map.put("loginName", markUser.getLoginName());
+                map.put("name", markUser.getName());
+                map.put("arbitrated", arbitrate);
+                mapList.add(map);
+            }
+            objectMap.put("kzz", mapList);
+        }
+    }
 }

+ 192 - 0
stmms-ms-marking/src/main/java/cn/com/qmth/stmms/ms/marking/service/MarkerGroupLeaderService.java

@@ -0,0 +1,192 @@
+package cn.com.qmth.stmms.ms.marking.service;
+
+import cn.com.qmth.stmms.ms.core.domain.MarkStage;
+import cn.com.qmth.stmms.ms.core.domain.MarkSubject;
+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.MarkerGroup;
+import cn.com.qmth.stmms.ms.core.domain.user.MarkerGroupLeader;
+import cn.com.qmth.stmms.ms.core.domain.user.Role;
+import cn.com.qmth.stmms.ms.core.repository.MarkTaskRepo;
+import cn.com.qmth.stmms.ms.core.repository.MarkerGroupLeaderRepo;
+import cn.com.qmth.stmms.ms.core.repository.MarkerGroupRepo;
+import cn.com.qmth.stmms.ms.core.vo.Subject;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @Date: 2021/9/22.
+ */
+@Service
+public class MarkerGroupLeaderService {
+
+    @Autowired
+    private MarkTaskRepo markTaskRepo;
+
+    @Autowired
+    private MarkerGroupRepo markerGroupRepo;
+
+    @Autowired
+    private MarkerGroupLeaderRepo markerGroupLeaderRepo;
+
+    /**
+     * 创建分组
+     *
+     * @param markerGroup
+     * @param stage
+     * @return
+     */
+    @Transactional
+    public MarkerGroup save(MarkerGroup markerGroup, MarkStage stage) {
+        if (Objects.nonNull(markerGroup.getId())) {
+            markerGroupLeaderRepo.deleteByWorkIdAndSubjectAndStageAndGroupId(markerGroup.getWorkId(), markerGroup.getSubject(), stage, markerGroup.getId());
+        }
+        Set<MarkUser> groupMarkers = markerGroup.getMarkers();
+        List<MarkUser> markLeaders = groupMarkers.stream().filter(m -> Role.MARK_LEADER.equals(m.getRole())).collect(Collectors.toList());
+        MarkerGroup group = markerGroupRepo.save(markerGroup);
+        if (!CollectionUtils.isEmpty(markLeaders)) {
+            List<MarkUser> markers = groupMarkers.stream().filter(m -> Role.MARKER.equals(m.getRole())).collect(Collectors.toList());
+            if (!CollectionUtils.isEmpty(markers)) {
+                List<MarkerGroupLeader> leaderList = new ArrayList<>();
+                for (MarkUser markLeader : markLeaders) {
+                    for (MarkUser marker : markers) {
+                        MarkerGroupLeader markerGroupLeader = new MarkerGroupLeader();
+                        markerGroupLeader.setWorkId(markerGroup.getWorkId());
+                        markerGroupLeader.setSubject(markerGroup.getSubject());
+                        markerGroupLeader.setStage(stage);
+                        markerGroupLeader.setGroupId(group.getId());
+                        markerGroupLeader.setGroupName(group.getName());
+                        markerGroupLeader.setMarkLeaderId(markLeader.getId());
+                        markerGroupLeader.setMarkerId(marker.getId());
+                        leaderList.add(markerGroupLeader);
+                    }
+                }
+                markerGroupLeaderRepo.save(leaderList);
+            }
+        }
+        return group;
+    }
+
+    /**
+     * 删除分组
+     *
+     * @param markSubject
+     * @param domain
+     */
+    @Transactional
+    public void delete(MarkSubject markSubject, MarkerGroup domain) {
+        int count = 0;
+        if (MarkStage.LEVEL == markSubject.getStage() || MarkStage.SCORE == markSubject.getStage()) {
+            count = markTaskRepo.countByWorkIdAndSubjectAndStage(markSubject.getWorkId(), markSubject.getSubject(), markSubject.getStage());
+        }
+        if (count > 0) {
+            throw new RuntimeException("当前阶段已发布任务,不能删除分组");
+        }
+        markerGroupRepo.delete(domain);
+
+        markerGroupLeaderRepo.deleteByWorkIdAndSubjectAndStageAndGroupId(markSubject.getWorkId(), markSubject.getSubject(), markSubject.getStage(), domain.getId());
+    }
+
+    /**
+     * @param workId
+     * @param subject
+     * @param stage
+     * @return
+     */
+    public List<Map<String, List<Long>>> listGroupLeaderAndMarkersByWorkIdAndSubjectAndStage(Long workId, Subject subject, MarkStage stage) {
+        List<MarkerGroupLeader> markerGroupLeaders = markerGroupLeaderRepo.findByWorkIdAndSubjectAndStage(workId, subject, stage);
+        if (!CollectionUtils.isEmpty(markerGroupLeaders)) {
+            Map<Long, List<MarkerGroupLeader>> maps = markerGroupLeaders.stream().collect(Collectors.groupingBy(MarkerGroupLeader::getGroupId));
+            List<Map<String, List<Long>>> mapList = new ArrayList<>();
+            for (Map.Entry<Long, List<MarkerGroupLeader>> listEntry : maps.entrySet()) {
+                Map<String, List<Long>> map = new HashMap<>();
+                // 科组长
+                List<Long> markLeaderList = listEntry.getValue().stream().map(m -> m.getMarkLeaderId()).distinct().collect(Collectors.toList());
+                map.put("markLeaders", markLeaderList);
+                // 评卷员
+                List<Long> markList = listEntry.getValue().stream().map(m -> m.getMarkerId()).distinct().collect(Collectors.toList());
+                map.put("markers", markList);
+                mapList.add(map);
+            }
+            return mapList;
+        }
+        return null;
+    }
+
+    /**
+     * 根据评卷员,查询试卷
+     *
+     * @param workId
+     * @param subject
+     * @param stage
+     * @param markers
+     * @return
+     */
+    public List<Long> listPaperIdsByWorkIdAndSubjectAndStageAndMarkerIds(Long workId, Subject subject, MarkStage stage, List<Long> markers) {
+        List<MarkTask> markTasks = markTaskRepo.findByWorkIdAndSubjectAndStageAndMarkerIdIn(workId, subject, stage, markers);
+        if (!CollectionUtils.isEmpty(markTasks)) {
+            List<Long> paperIds = markTasks.stream().map(m -> m.getPaper().getId()).distinct().collect(Collectors.toList());
+            return paperIds;
+        }
+        return null;
+    }
+
+    /**
+     * 根据科组长,查询评卷员
+     *
+     * @param workId
+     * @param markSubject
+     * @param markLeaderId
+     * @return
+     */
+    public List<MarkerGroupLeader> listByWorkIdAndSubjectAndStageAndMarkLeaderId(Long workId, MarkSubject markSubject, Long markLeaderId) {
+        return markerGroupLeaderRepo.findByWorkIdAndSubjectAndStageAndMarkLeaderId(workId, markSubject.getSubject(), markSubject.getStage(), markLeaderId);
+    }
+
+    /**
+     * 查询分组
+     *
+     * @param workId
+     * @param subject
+     * @param stage
+     * @return
+     */
+    public List<Map<String, Object>> listGroupByWorkIdAndSubjectAndStage(Long workId, Subject subject, MarkStage stage) {
+        stage = Objects.isNull(stage) ? MarkStage.LEVEL : stage;
+        List<MarkerGroupLeader> markerGroupLeaders = markerGroupLeaderRepo.findByWorkIdAndSubjectAndStage(workId, subject, stage);
+        Map<Long, String> map = markerGroupLeaders.stream().collect(Collectors.toMap(m -> m.getGroupId(), m -> m.getGroupName()));
+        List<Map<String, Object>> list = new ArrayList<>();
+        for (Map.Entry<Long, String> entry : map.entrySet()) {
+            Map<String, Object> stringMap = new HashMap<>();
+            stringMap.computeIfAbsent("groupId", v -> entry.getKey());
+            stringMap.computeIfAbsent("groupName", v -> entry.getValue());
+            list.add(stringMap);
+        }
+        return list;
+    }
+
+    /**
+     * 根据分组查询组内评卷员
+     * @param workId
+     * @param subject
+     * @param level
+     * @param groupId
+     * @return
+     */
+    public List<Long> listByWorkIdAndSubjectAndStageAndGroupId(Long workId, Subject subject, MarkStage level, Long groupId) {
+        if(Objects.isNull(groupId)){
+            return null;
+        }
+        List<MarkerGroupLeader> markerGroupLeaders = markerGroupLeaderRepo.findByWorkIdAndSubjectAndStageAndGroupId(workId, subject, level, groupId);
+        List<Long> markerIds = null;
+        if(!CollectionUtils.isEmpty(markerGroupLeaders)){
+            markerIds = markerGroupLeaders.stream().map(m->m.getMarkerId()).distinct().collect(Collectors.toList());
+        }
+        return markerIds;
+    }
+}