Parcourir la source

阅卷待办短信

wangliang il y a 3 mois
Parent
commit
9217ac5d19

+ 3 - 3
distributed-print-business/src/main/resources/mapper/ConditionMapper.xml

@@ -1193,12 +1193,12 @@
             left join basic_course bc on bc.id = mp.course_id
         <where>
             <if test="semesterId != null and semesterId != ''">
-                and be.semester_id = ${semesterId}
+                and be.semester_id = #{semesterId}
             </if>
             <if test="examId != null and examId != ''">
-                and mp.exam_id = ${examId}
+                and mp.exam_id = #{examId}
             </if>
-            and exists(select 1 from basic_exam_student bes where bes.exam_id = ${examId} and mp.course_id = bes.course_id
+            and exists(select 1 from basic_exam_student bes where bes.exam_id = #{examId} and mp.course_id = bes.course_id
             <if test="dpr != null">
                 <if test="dpr.requestUserId != null">
                     AND bes.create_id = #{dpr.requestUserId}

+ 108 - 0
teachcloud-common/src/main/java/com/qmth/teachcloud/common/bean/dto/MarkTaskSmsDto.java

@@ -0,0 +1,108 @@
+package com.qmth.teachcloud.common.bean.dto;
+
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.io.Serializable;
+
+/**
+ * @Description: 阅卷任务dto
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2025/3/11
+ */
+public class MarkTaskSmsDto implements Serializable {
+
+    @ApiModelProperty(value = "考试id")
+    @JsonSerialize(using = ToStringSerializer.class)
+    private Long examId;
+
+    @ApiModelProperty(value = "试卷编码")
+    private String paperNumber;
+
+    @ApiModelProperty(value = "课程id")
+    @JsonSerialize(using = ToStringSerializer.class)
+    private Long courseId;
+
+    @ApiModelProperty(value = "用户id")
+    @JsonSerialize(using = ToStringSerializer.class)
+    private Long userId;
+
+    @ApiModelProperty(value = "考试名称")
+    private String examName;
+
+    @ApiModelProperty(value = "课程名称")
+    private String courseName;
+
+    @ApiModelProperty(value = "手机号")
+    private String mobileNumber;
+
+    @ApiModelProperty(value = "阅卷题目数")
+    private Integer markQuestionCount;
+
+    public Long getExamId() {
+        return examId;
+    }
+
+    public void setExamId(Long examId) {
+        this.examId = examId;
+    }
+
+    public String getPaperNumber() {
+        return paperNumber;
+    }
+
+    public void setPaperNumber(String paperNumber) {
+        this.paperNumber = paperNumber;
+    }
+
+    public Long getCourseId() {
+        return courseId;
+    }
+
+    public void setCourseId(Long courseId) {
+        this.courseId = courseId;
+    }
+
+    public Long getUserId() {
+        return userId;
+    }
+
+    public void setUserId(Long userId) {
+        this.userId = userId;
+    }
+
+    public String getExamName() {
+        return examName;
+    }
+
+    public void setExamName(String examName) {
+        this.examName = examName;
+    }
+
+    public String getCourseName() {
+        return courseName;
+    }
+
+    public void setCourseName(String courseName) {
+        this.courseName = courseName;
+    }
+
+    public String getMobileNumber() {
+        return mobileNumber;
+    }
+
+    public void setMobileNumber(String mobileNumber) {
+        this.mobileNumber = mobileNumber;
+    }
+
+    public Integer getMarkQuestionCount() {
+        return markQuestionCount;
+    }
+
+    public void setMarkQuestionCount(Integer markQuestionCount) {
+        this.markQuestionCount = markQuestionCount;
+    }
+}

+ 55 - 44
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/mapper/MarkUserQuestionMapper.java

@@ -1,44 +1,55 @@
-package com.qmth.teachcloud.mark.mapper;
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.qmth.teachcloud.common.entity.MarkQuestion;
-import com.qmth.teachcloud.common.entity.SysUser;
-import com.qmth.teachcloud.mark.dto.mark.entrance.MarkEntranceDto;
-import com.qmth.teachcloud.mark.dto.mark.manage.MarkQualityDto;
-import com.qmth.teachcloud.mark.dto.mark.manage.MarkUserGroupProgressDto;
-import com.qmth.teachcloud.common.bean.dto.mark.MarkUser;
-import com.qmth.teachcloud.mark.entity.MarkUserQuestion;
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import org.apache.ibatis.annotations.Param;
-
-import java.util.List;
-
-/**
- * <p>
- * 评卷员表 Mapper 接口
- * </p>
- *
- * @author xf
- * @since 2023-09-22
- */
-public interface MarkUserQuestionMapper extends BaseMapper<MarkUserQuestion> {
-
-    IPage<MarkEntranceDto> listEntranceGroup(@Param("page") Page<MarkUserQuestion> page, @Param("examId") Long examId, @Param("openCollegeId") Long openCollegeId, @Param("courseId") Long courseId, @Param("paperNumber") String paperNumber, @Param("userId") Long userId, @Param("status") String status);
-
-    List<MarkUser> listGroupUserByExamIdAndPaperNumberAndQuestionId(@Param("examId") Long examId, @Param("paperNumber") String paperNumber, @Param("questionId") Long questionId, @Param("className") String className);
-
-    IPage<MarkUserGroupProgressDto> pageGroupUserByExamIdAndPaperNumberAndQuestionId(@Param("page") Page<MarkUserGroupProgressDto> page, @Param("examId") Long examId, @Param("paperNumber") String paperNumber, @Param("questionId") Long questionId, @Param("loginName") String loginName, @Param("className") String className, @Param("marked") Boolean marked);
-
-    IPage<MarkQualityDto> pageQuality(@Param("page") Page<MarkQualityDto> page, @Param("examId") Long examId, @Param("paperNumber") String paperNumber, @Param("questionId") Long questionId, @Param("loginName") String loginName);
-
-    int countByMarkTask(@Param("userId") Long userId, @Param("status") String status);
-
-    void updateRejectCountByExamIdAndPaperNumberAndQuestionIdAndUserId(@Param("examId") Long examId, @Param("paperNumber") String paperNumber, @Param("questionId") Long questionId, @Param("userId") Long userId);
-
-    List<SysUser> listDefaultMarkerByExamIdAndPaperNumber(@Param("examId") Long examId, @Param("paperNumber") String paperNumber);
-
-    List<String > countClassByExamIdAndPaperNumberAndQuestionId(@Param("examId") Long examId, @Param("paperNumber") String paperNumber, @Param("questionId") Long questionId);
-
-    List<MarkQuestion> listSubjectiveQuestionByUserId(@Param("examId") Long examId, @Param("paperNumber") String paperNumber, @Param("userId") Long userId);
-}
+package com.qmth.teachcloud.mark.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.qmth.teachcloud.common.bean.dto.MarkTaskSmsDto;
+import com.qmth.teachcloud.common.bean.dto.mark.MarkUser;
+import com.qmth.teachcloud.common.entity.MarkQuestion;
+import com.qmth.teachcloud.common.entity.SysUser;
+import com.qmth.teachcloud.mark.dto.mark.entrance.MarkEntranceDto;
+import com.qmth.teachcloud.mark.dto.mark.manage.MarkQualityDto;
+import com.qmth.teachcloud.mark.dto.mark.manage.MarkUserGroupProgressDto;
+import com.qmth.teachcloud.mark.entity.MarkUserQuestion;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 评卷员表 Mapper 接口
+ * </p>
+ *
+ * @author xf
+ * @since 2023-09-22
+ */
+public interface MarkUserQuestionMapper extends BaseMapper<MarkUserQuestion> {
+
+    IPage<MarkEntranceDto> listEntranceGroup(@Param("page") Page<MarkUserQuestion> page, @Param("examId") Long examId, @Param("openCollegeId") Long openCollegeId, @Param("courseId") Long courseId, @Param("paperNumber") String paperNumber, @Param("userId") Long userId, @Param("status") String status);
+
+    List<MarkUser> listGroupUserByExamIdAndPaperNumberAndQuestionId(@Param("examId") Long examId, @Param("paperNumber") String paperNumber, @Param("questionId") Long questionId, @Param("className") String className);
+
+    IPage<MarkUserGroupProgressDto> pageGroupUserByExamIdAndPaperNumberAndQuestionId(@Param("page") Page<MarkUserGroupProgressDto> page, @Param("examId") Long examId, @Param("paperNumber") String paperNumber, @Param("questionId") Long questionId, @Param("loginName") String loginName, @Param("className") String className, @Param("marked") Boolean marked);
+
+    IPage<MarkQualityDto> pageQuality(@Param("page") Page<MarkQualityDto> page, @Param("examId") Long examId, @Param("paperNumber") String paperNumber, @Param("questionId") Long questionId, @Param("loginName") String loginName);
+
+    int countByMarkTask(@Param("userId") Long userId, @Param("status") String status);
+
+    void updateRejectCountByExamIdAndPaperNumberAndQuestionIdAndUserId(@Param("examId") Long examId, @Param("paperNumber") String paperNumber, @Param("questionId") Long questionId, @Param("userId") Long userId);
+
+    List<SysUser> listDefaultMarkerByExamIdAndPaperNumber(@Param("examId") Long examId, @Param("paperNumber") String paperNumber);
+
+    List<String> countClassByExamIdAndPaperNumberAndQuestionId(@Param("examId") Long examId, @Param("paperNumber") String paperNumber, @Param("questionId") Long questionId);
+
+    List<MarkQuestion> listSubjectiveQuestionByUserId(@Param("examId") Long examId, @Param("paperNumber") String paperNumber, @Param("userId") Long userId);
+
+    /**
+     * 根据考试id&课程id&试卷编码查询待发送阅卷待办任务
+     *
+     * @param examId
+     * @param courseId
+     * @param paperNumber
+     * @return
+     */
+    List<MarkTaskSmsDto> findMarkTaskSms(@Param("examId") Long examId, @Param("courseId") Long courseId, @Param("paperNumber") String paperNumber);
+}

+ 95 - 84
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/MarkUserQuestionService.java

@@ -1,84 +1,95 @@
-package com.qmth.teachcloud.mark.service;
-
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.qmth.teachcloud.common.entity.MarkQuestion;
-import com.qmth.teachcloud.common.enums.mark.MarkPaperStatus;
-import com.qmth.teachcloud.mark.bean.marker.MarkerAddParam;
-import com.qmth.teachcloud.mark.dto.mark.entrance.MarkEntranceDto;
-import com.qmth.teachcloud.mark.dto.mark.manage.MarkQualityChartDto;
-import com.qmth.teachcloud.mark.dto.mark.manage.MarkQualityDto;
-import com.qmth.teachcloud.mark.dto.mark.manage.MarkUserGroupProgressDto;
-import com.qmth.teachcloud.common.bean.dto.mark.MarkUser;
-import com.qmth.teachcloud.mark.entity.MarkUserQuestion;
-import com.baomidou.mybatisplus.extension.service.IService;
-
-import java.util.List;
-
-/**
- * <p>
- * 评卷员表 服务类
- * </p>
- *
- * @author xf
- * @since 2023-09-22
- */
-public interface MarkUserQuestionService extends IService<MarkUserQuestion> {
-
-    IPage<MarkEntranceDto> listEntranceGroup(Long examId, Long openCollegeId, Long courseCode, String paperNumber,
-            Integer pageNumber, Integer pageSize);
-
-    List<MarkUser> listGroupUserByExamIdAndPaperNumberAndQuestionIdAndClassName(Long examId, String paperNumber, Long questionId, String className);
-
-    IPage<MarkUserGroupProgressDto> pageGroupUserByExamIdAndPaperNumberAndQuestionId(Long examId, String paperNumber,
-                                                                                     Long questionId, String loginName, String className, Boolean marked, Integer pageNumber, Integer pageSize);
-
-    void addMarkUserQuestion(MarkerAddParam markerAddParam);
-
-    void setTopCount(List<Long> markUserQuestionIds, Integer topCount);
-
-    MarkUserQuestion getByExamIdAndPaperNumberAndQuestionIdAndUserId(Long examId, String paperNumber, Long questionId, Long userId);
-
-    void deleteMarker(MarkUserQuestion markUserQuestion);
-
-    void releaseMarker(List<Long> markUserGroupIds);
-
-    boolean resetMarker(MarkUserQuestion markUserGroup);
-
-    void resetById(Long id);
-
-    IPage<MarkQualityDto> pageQuality(Long examId, String paperNumber, Long questionId, String loginName, Integer pageNumber, Integer pageSize);
-
-    void updateQuality(Long examId, String paperNumber, Long questionId);
-
-    List<MarkUserQuestion> listByExamIdAndPaperNumberAndQuestionId(Long examId, String paperNumber, Long questionId);
-
-    void updateQualityById(Long markUserGroupId, int finishCount, int headerFinishCount, int validCount, double v,
-            double avgScore, double stdevScore, double maxScore, double minScore);
-
-    List<MarkQualityChartDto> listQualityChart(Long examId, String paperNumber, Long questionId);
-
-    List<MarkUserQuestion> listByExamIdAndPaperNumberAndUserIdAndEnableTure(Long examId, String paperNumber, Long userId);
-
-    void deleteByExamIdAndPaperNumberAndQuestionId(Long examId, String paperNumber, Long questionId);
-
-    List<String> listBindMarkers(Long examId, String paperNumber, Long questionId);
-
-    /**
-     * 查询评卷任务待办/已办数量
-     *
-     * @param userId 用户id
-     * @param status 试卷状态
-     * @return 任务数量
-     */
-    int countByMarkTask(Long userId, MarkPaperStatus status);
-
-    void updateRejectCountByExamIdAndPaperNumberAndQuestionIdAndUserId(Long examId, String paperNumber, Long questionId, Long userId);
-
-    void saveDefaultMarker(Long examId, String paperNumber, List<MarkQuestion> markQuestions);
-
-    List<String> countClassByExamIdAndPaperNumberAndQuestionId(Long examId, String paperNumber, Long questionId);
-
-    List<MarkQuestion> listSubjectiveQuestionByUserId(Long examId, String paperNumber, Long id);
-
-    int countByExamIdAndPaperNumberAndAndUserId(Long examId, String paperNumber, Long userId);
-}
+package com.qmth.teachcloud.mark.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.qmth.teachcloud.common.bean.dto.MarkTaskSmsDto;
+import com.qmth.teachcloud.common.bean.dto.mark.MarkUser;
+import com.qmth.teachcloud.common.entity.MarkQuestion;
+import com.qmth.teachcloud.common.enums.mark.MarkPaperStatus;
+import com.qmth.teachcloud.mark.bean.marker.MarkerAddParam;
+import com.qmth.teachcloud.mark.dto.mark.entrance.MarkEntranceDto;
+import com.qmth.teachcloud.mark.dto.mark.manage.MarkQualityChartDto;
+import com.qmth.teachcloud.mark.dto.mark.manage.MarkQualityDto;
+import com.qmth.teachcloud.mark.dto.mark.manage.MarkUserGroupProgressDto;
+import com.qmth.teachcloud.mark.entity.MarkUserQuestion;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 评卷员表 服务类
+ * </p>
+ *
+ * @author xf
+ * @since 2023-09-22
+ */
+public interface MarkUserQuestionService extends IService<MarkUserQuestion> {
+
+    IPage<MarkEntranceDto> listEntranceGroup(Long examId, Long openCollegeId, Long courseCode, String paperNumber,
+                                             Integer pageNumber, Integer pageSize);
+
+    List<MarkUser> listGroupUserByExamIdAndPaperNumberAndQuestionIdAndClassName(Long examId, String paperNumber, Long questionId, String className);
+
+    IPage<MarkUserGroupProgressDto> pageGroupUserByExamIdAndPaperNumberAndQuestionId(Long examId, String paperNumber,
+                                                                                     Long questionId, String loginName, String className, Boolean marked, Integer pageNumber, Integer pageSize);
+
+    void addMarkUserQuestion(MarkerAddParam markerAddParam);
+
+    void setTopCount(List<Long> markUserQuestionIds, Integer topCount);
+
+    MarkUserQuestion getByExamIdAndPaperNumberAndQuestionIdAndUserId(Long examId, String paperNumber, Long questionId, Long userId);
+
+    void deleteMarker(MarkUserQuestion markUserQuestion);
+
+    void releaseMarker(List<Long> markUserGroupIds);
+
+    boolean resetMarker(MarkUserQuestion markUserGroup);
+
+    void resetById(Long id);
+
+    IPage<MarkQualityDto> pageQuality(Long examId, String paperNumber, Long questionId, String loginName, Integer pageNumber, Integer pageSize);
+
+    void updateQuality(Long examId, String paperNumber, Long questionId);
+
+    List<MarkUserQuestion> listByExamIdAndPaperNumberAndQuestionId(Long examId, String paperNumber, Long questionId);
+
+    void updateQualityById(Long markUserGroupId, int finishCount, int headerFinishCount, int validCount, double v,
+                           double avgScore, double stdevScore, double maxScore, double minScore);
+
+    List<MarkQualityChartDto> listQualityChart(Long examId, String paperNumber, Long questionId);
+
+    List<MarkUserQuestion> listByExamIdAndPaperNumberAndUserIdAndEnableTure(Long examId, String paperNumber, Long userId);
+
+    void deleteByExamIdAndPaperNumberAndQuestionId(Long examId, String paperNumber, Long questionId);
+
+    List<String> listBindMarkers(Long examId, String paperNumber, Long questionId);
+
+    /**
+     * 查询评卷任务待办/已办数量
+     *
+     * @param userId 用户id
+     * @param status 试卷状态
+     * @return 任务数量
+     */
+    int countByMarkTask(Long userId, MarkPaperStatus status);
+
+    void updateRejectCountByExamIdAndPaperNumberAndQuestionIdAndUserId(Long examId, String paperNumber, Long questionId, Long userId);
+
+    void saveDefaultMarker(Long examId, String paperNumber, List<MarkQuestion> markQuestions);
+
+    List<String> countClassByExamIdAndPaperNumberAndQuestionId(Long examId, String paperNumber, Long questionId);
+
+    List<MarkQuestion> listSubjectiveQuestionByUserId(Long examId, String paperNumber, Long id);
+
+    int countByExamIdAndPaperNumberAndAndUserId(Long examId, String paperNumber, Long userId);
+
+    /**
+     * 根据考试id&课程id&试卷编码查询待发送阅卷待办任务
+     *
+     * @param examId
+     * @param courseId
+     * @param paperNumber
+     * @return
+     */
+    List<MarkTaskSmsDto> findMarkTaskSms(Long examId, Long courseId, String paperNumber);
+}

+ 416 - 401
teachcloud-mark/src/main/java/com/qmth/teachcloud/mark/service/impl/MarkUserQuestionServiceImpl.java

@@ -1,401 +1,416 @@
-package com.qmth.teachcloud.mark.service.impl;
-
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
-import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.qmth.teachcloud.common.bean.dto.mark.MarkUser;
-import com.qmth.teachcloud.common.entity.MarkQuestion;
-import com.qmth.teachcloud.common.entity.SysUser;
-import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
-import com.qmth.teachcloud.common.enums.mark.MarkPaperStatus;
-import com.qmth.teachcloud.common.service.SysUserService;
-import com.qmth.teachcloud.common.util.ServletUtil;
-import com.qmth.teachcloud.mark.bean.marker.MarkerAddParam;
-import com.qmth.teachcloud.mark.dto.mark.entrance.MarkEntranceDto;
-import com.qmth.teachcloud.mark.dto.mark.manage.MarkQualityChartDto;
-import com.qmth.teachcloud.mark.dto.mark.manage.MarkQualityDto;
-import com.qmth.teachcloud.mark.dto.mark.manage.MarkUserGroupProgressDto;
-import com.qmth.teachcloud.mark.entity.*;
-import com.qmth.teachcloud.mark.enums.LockType;
-import com.qmth.teachcloud.mark.enums.MarkTaskStatus;
-import com.qmth.teachcloud.mark.lock.LockService;
-import com.qmth.teachcloud.mark.mapper.MarkUserQuestionMapper;
-import com.qmth.teachcloud.mark.service.*;
-import com.qmth.teachcloud.mark.utils.Calculator;
-import org.apache.commons.collections4.CollectionUtils;
-import org.springframework.stereotype.Service;
-
-import javax.annotation.Resource;
-import java.math.BigDecimal;
-import java.math.RoundingMode;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.stream.Collectors;
-
-/**
- * <p>
- * 评卷员表 服务实现类
- * </p>
- *
- * @author xf
- * @since 2023-09-22
- */
-@Service
-public class MarkUserQuestionServiceImpl extends ServiceImpl<MarkUserQuestionMapper, MarkUserQuestion> implements MarkUserQuestionService {
-
-    @Resource
-    private MarkQuestionService markQuestionService;
-    @Resource
-    private MarkTaskService markTaskService;
-    @Resource
-    private MarkPaperService markPaperService;
-    @Resource
-    private MarkUserClassService markUserClassService;
-    @Resource
-    private MarkUserPaperService markUserPaperService;
-    @Resource
-    private MarkSyncService markSyncService;
-    @Resource
-    private SysUserService sysUserService;
-    @Resource
-    private MarkService markService;
-    @Resource
-    private LockService lockService;
-
-    @Override
-    public IPage<MarkEntranceDto> listEntranceGroup(Long examId, Long openCollegeId, Long courseId, String paperNumber, Integer pageNumber, Integer pageSize) {
-        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
-        Page<MarkUserQuestion> page = new Page<>(pageNumber, pageSize);
-        IPage<MarkEntranceDto> markEntranceDtoIPage = this.baseMapper.listEntranceGroup(page, examId, openCollegeId, courseId, paperNumber, sysUser.getId(), MarkPaperStatus.FORMAL.name());
-        for (MarkEntranceDto record : markEntranceDtoIPage.getRecords()) {
-            MarkPaper markPaper = markPaperService.getByExamIdAndPaperNumber(record.getExamId(), record.getPaperNumber());
-            // 分班阅
-            List<String> classNames = null;
-            if (markPaper != null && markPaper.getClassMark() != null && markPaper.getClassMark()) {
-                List<MarkUserClass> markUserClassList = markUserClassService.listByExamIdAndPaperNumberAndUserId(record.getExamId(), record.getPaperNumber(), sysUser.getId());
-                if (CollectionUtils.isNotEmpty(markUserClassList)) {
-                    classNames = markUserClassList.stream().map(MarkUserClass::getClassName).collect(Collectors.toList());
-                }
-            }
-
-            List<MarkQuestion> markQuestionList = this.listSubjectiveQuestionByUserId(record.getExamId(), record.getPaperNumber(), sysUser.getId());
-            List<Long> questionIds = markQuestionList.stream().map(MarkQuestion::getId).collect(Collectors.toList());
-
-            int taskCount = markTaskService.countByExamIdAndPaperNumberAndUserIdAndAndClassNameAndQuestionIdIn(record.getExamId(), record.getPaperNumber(), null, classNames, questionIds);
-            record.setTaskCount(taskCount);
-            int unMarkedCount = markTaskService.countByExamIdAndPaperNumberAndUserIdAndAndClassNameAndQuestionIdIn(record.getExamId(), record.getPaperNumber(), null, classNames, questionIds, MarkTaskStatus.WAITING, MarkTaskStatus.WAIT_ARBITRATE, MarkTaskStatus.REJECTED, MarkTaskStatus.PROBLEM);
-            record.setLeftCount(unMarkedCount);
-            record.setMarkedCount(taskCount == 0 ? 0 : taskCount - unMarkedCount);
-            // 评卷进度
-            if (taskCount == 0) {
-                record.setPercent(0D);
-            } else {
-                BigDecimal bigDecimal = new BigDecimal(record.getMarkedCount() * 100).divide(new BigDecimal(taskCount), 2, RoundingMode.HALF_UP);
-                record.setPercent(bigDecimal.doubleValue());
-            }
-            // 分组题目
-            record.setQuestionNumber(markQuestionList.stream().map(m -> m.getMainNumber() + "-" + m.getSubNumber()).collect(Collectors.joining(",")));
-        }
-
-        return markEntranceDtoIPage;
-    }
-
-    @Override
-    public List<MarkUser> listGroupUserByExamIdAndPaperNumberAndQuestionIdAndClassName(Long examId, String paperNumber, Long questionId, String className) {
-        return this.baseMapper.listGroupUserByExamIdAndPaperNumberAndQuestionId(examId, paperNumber, questionId, className);
-    }
-
-    @Override
-    public IPage<MarkUserGroupProgressDto> pageGroupUserByExamIdAndPaperNumberAndQuestionId(Long examId, String paperNumber, Long questionId, String loginName, String className, Boolean marked, Integer pageNumber, Integer pageSize) {
-        Page<MarkUserGroupProgressDto> page = new Page<>(pageNumber, pageSize);
-        IPage<MarkUserGroupProgressDto> markUserGroupProgressDtoIPage = this.baseMapper.pageGroupUserByExamIdAndPaperNumberAndQuestionId(page, examId, paperNumber, questionId, loginName, className, marked);
-        for (MarkUserGroupProgressDto record : markUserGroupProgressDtoIPage.getRecords()) {
-            MarkQuestion markQuestion = markQuestionService.getById(record.getQuestionId());
-            record.setQuestionNumber(markQuestion.getQuestionNumber());
-            List<MarkTask> markTaskList = markTaskService.listByExamIdAndPaperNumberAndQuestionIdAndUserIdAndClassName(examId, paperNumber, record.getQuestionId(), record.getUserId(), null);
-            record.setResetting(lockService.isLocked(LockType.MARKER_RESET, record.getMarkUserQuestionId()));
-            record.setMarkedCount(markTaskService.markedCount(markTaskList));
-            record.setCurrentCount(markService.applyCurrentCount(markQuestion, record.getMarkUserQuestionId()));
-        }
-        return markUserGroupProgressDtoIPage;
-    }
-
-    @Override
-    public void addMarkUserQuestion(MarkerAddParam markerAddParam) {
-        if (CollectionUtils.isNotEmpty(markerAddParam.getUserIds())) {
-            // 根据是否合并设置评卷员参数,做合并
-            List<Long> questionIds = listMergeQuestionId(markerAddParam.getExamId(), markerAddParam.getPaperNumber(), markerAddParam.getQuestionId());
-
-            List<MarkUserQuestion> markUserGroups = new ArrayList<>();
-            for (Long userId : markerAddParam.getUserIds()) {
-                for (Long questionId : questionIds) {
-                    MarkUserQuestion markUserGroup = this.getByExamIdAndPaperNumberAndQuestionIdAndUserId(markerAddParam.getExamId(), markerAddParam.getPaperNumber(), questionId, userId);
-                    if (markUserGroup == null) {
-                        markUserGroups.add(new MarkUserQuestion(markerAddParam.getExamId(), markerAddParam.getPaperNumber(), questionId, userId));
-                    } else if (!markUserGroup.getEnable()) {
-                        markUserGroup.setEnable(true);
-                        markUserGroups.add(markUserGroup);
-                    }
-                }
-            }
-            if (CollectionUtils.isNotEmpty(markUserGroups)) {
-                this.saveOrUpdateBatch(markUserGroups);
-            }
-        }
-    }
-
-    private List<Long> listMergeQuestionId(Long examId, String paperNumber, Long questionId) {
-        MarkPaper markPaper = markPaperService.getByExamIdAndPaperNumber(examId, paperNumber);
-
-        MarkQuestion markQuestion = markQuestionService.getById(questionId);
-        if (markQuestion == null) {
-            throw ExceptionResultEnum.ERROR.exception("题目不存在");
-        }
-        List<Long> questionIds = new ArrayList<>();
-        if (markQuestion.getQuestionType() == 4 && markPaper != null && markPaper.getMergeMarker() != null && markPaper.getMergeMarker()) {
-            List<MarkQuestion> markQuestionList = markQuestionService.listByExamIdAndPaperNumberAndObjective(examId, paperNumber, false);
-            // 填空题,整个大题一起解绑
-            return markQuestionList.stream().filter(m -> markQuestion.getMainNumber().equals(m.getMainNumber()) && m.getQuestionType() == 4).map(MarkQuestion::getId).collect(Collectors.toList());
-        } else {
-            questionIds.add(questionId);
-        }
-        return questionIds;
-    }
-
-    @Override
-    public void setTopCount(List<Long> markUserQuestionIds, Integer topCount) {
-        for (Long markUserQuestionId : markUserQuestionIds) {
-            MarkUserQuestion markUserQuestion = this.getById(markUserQuestionId);
-            if (markUserQuestion != null) {
-                markUserQuestion.setTopCount(topCount);
-                this.updateById(markUserQuestion);
-            }
-        }
-    }
-
-    @Override
-    public MarkUserQuestion getByExamIdAndPaperNumberAndQuestionIdAndUserId(Long examId, String paperNumber, Long questionId, Long userId) {
-        QueryWrapper<MarkUserQuestion> queryWrapper = new QueryWrapper<>();
-        queryWrapper.lambda().eq(MarkUserQuestion::getExamId, examId)
-                .eq(MarkUserQuestion::getPaperNumber, paperNumber)
-                .eq(MarkUserQuestion::getQuestionId, questionId)
-                .eq(MarkUserQuestion::getUserId, userId);
-        return this.getOne(queryWrapper);
-    }
-
-    @Override
-    public void deleteMarker(MarkUserQuestion markUserQuestion) {
-        // 先回收,再删除
-        releaseMarker(Arrays.asList(markUserQuestion.getId()));
-        // 逻辑解绑
-        List<Long> ids = listMergeQuestionId(markUserQuestion.getExamId(), markUserQuestion.getPaperNumber(), markUserQuestion.getQuestionId());
-        UpdateWrapper<MarkUserQuestion> updateWrapper = new UpdateWrapper<>();
-        updateWrapper.lambda().set(MarkUserQuestion::getEnable, false)
-                .eq(MarkUserQuestion::getUserId, markUserQuestion.getUserId())
-                .in(MarkUserQuestion::getQuestionId, ids);
-        this.update(updateWrapper);
-    }
-
-    @Override
-    public void releaseMarker(List<Long> markUserGroupIds) {
-        for (Long markUserGroupId : markUserGroupIds) {
-            MarkUserQuestion markUserGroup = this.getById(markUserGroupId);
-            if (markUserGroup != null) {
-                try {
-                    lockService.waitlock(LockType.MARK_USER_QUESTION, markUserGroupId);
-                    markService.releaseByMarkUserGroup(markUserGroup);
-                } catch (Exception e) {
-                    log.error("release marker error", e);
-                } finally {
-                    lockService.unlock(LockType.MARK_USER_QUESTION, markUserGroupId);
-                }
-            }
-        }
-    }
-
-    @Override
-    public boolean resetMarker(MarkUserQuestion markUserQuestion) {
-        if (markUserQuestion != null) {
-            if (lockService.trylock(LockType.MARKER_RESET, markUserQuestion.getId())) {
-                markSyncService.markerResetSync(markUserQuestion);
-                return true;
-            } else {
-                throw ExceptionResultEnum.ERROR.exception("评卷员正在重置");
-            }
-        }
-        return true;
-    }
-
-    @Override
-    public void resetById(Long id) {
-        UpdateWrapper<MarkUserQuestion> updateWrapper = new UpdateWrapper<>();
-        updateWrapper.lambda().set(MarkUserQuestion::getFinishCount, null)
-                .set(MarkUserQuestion::getHeaderFinishCount, null)
-                .set(MarkUserQuestion::getValidCount, null)
-                .set(MarkUserQuestion::getAvgScore, null)
-                .set(MarkUserQuestion::getAvgSpeed, null)
-                .set(MarkUserQuestion::getStdevScore, null)
-                .set(MarkUserQuestion::getMaxScore, null)
-                .set(MarkUserQuestion::getMinScore, null)
-                .eq(MarkUserQuestion::getId, id);
-        this.update(updateWrapper);
-    }
-
-    @Override
-    public IPage<MarkQualityDto> pageQuality(Long examId, String paperNumber, Long questionId, String loginName, Integer pageNumber, Integer pageSize) {
-        Page<MarkQualityDto> page = new Page<>(pageNumber, pageSize);
-        IPage<MarkQualityDto> markQualityDtoIPage = this.baseMapper.pageQuality(page, examId, paperNumber, questionId, loginName);
-        for (MarkQualityDto qualityDto : markQualityDtoIPage.getRecords()) {
-            MarkQuestion markQuestion = markQuestionService.getById(qualityDto.getQuestionId());
-            qualityDto.setQuestionNumber(markQuestion.getQuestionNumber());
-            if (qualityDto.getUserId() != null) {
-                SysUser sysUser = sysUserService.getByUserId(qualityDto.getUserId());
-                qualityDto.setLoginName(sysUser.getLoginName());
-                qualityDto.setName(sysUser.getRealName());
-                qualityDto.setOrgName(sysUser.getOrgName());
-                qualityDto.setAdoptionRate(Calculator.divide2String(Calculator.multiply(qualityDto.getValidCount(), 100), Double.valueOf(qualityDto.getFinishCount()), 2));
-                qualityDto.setAvgScore(Calculator.round(qualityDto.getAvgScore(), 2));
-            }
-        }
-        return markQualityDtoIPage;
-    }
-
-    @Override
-    public void updateQuality(Long examId, String paperNumber, Long questionId) {
-        if (questionId == null) {
-            throw ExceptionResultEnum.ERROR.exception("请选择评阅题目");
-        }
-        MarkQuestion markQuestion = markQuestionService.getById(questionId);
-        if (markQuestion != null) {
-            String lockKey = markService.getGroupKey(markQuestion);
-            if (lockService.trylock(LockType.BATCH_QUALITY, lockKey)) {
-                markSyncService.updateQuality(this.listByExamIdAndPaperNumberAndQuestionId(examId, paperNumber, questionId), lockKey);
-            }
-        }
-    }
-
-    @Override
-    public List<MarkUserQuestion> listByExamIdAndPaperNumberAndQuestionId(Long examId, String paperNumber, Long questionId) {
-        QueryWrapper<MarkUserQuestion> queryWrapper = new QueryWrapper<>();
-        queryWrapper.lambda().eq(MarkUserQuestion::getExamId, examId)
-                .eq(MarkUserQuestion::getPaperNumber, paperNumber)
-                .eq(MarkUserQuestion::getQuestionId, questionId)
-                .orderByAsc(MarkUserQuestion::getId);
-        return this.list(queryWrapper);
-    }
-
-    @Override
-    public void updateQualityById(Long markUserGroupId, int finishCount, int headerFinishCount, int validCount, double avgSpeed, double avgScore, double stdevScore, double maxScore, double minScore) {
-        UpdateWrapper<MarkUserQuestion> updateWrapper = new UpdateWrapper<>();
-        updateWrapper.lambda().set(MarkUserQuestion::getFinishCount, finishCount)
-                .set(MarkUserQuestion::getHeaderFinishCount, headerFinishCount)
-                .set(MarkUserQuestion::getValidCount, validCount)
-                .set(MarkUserQuestion::getAvgSpeed, avgSpeed)
-                .set(MarkUserQuestion::getAvgScore, avgScore)
-                .set(MarkUserQuestion::getStdevScore, stdevScore)
-                .set(MarkUserQuestion::getMaxScore, maxScore)
-                .set(MarkUserQuestion::getMinScore, minScore)
-                .eq(MarkUserQuestion::getId, markUserGroupId);
-        this.update(updateWrapper);
-    }
-
-    @Override
-    public List<MarkQualityChartDto> listQualityChart(Long examId, String paperNumber, Long questionId) {
-        if (questionId == null) {
-            throw ExceptionResultEnum.ERROR.exception("请选择对应的科目及题目,再查看给分曲线");
-        }
-        List<MarkQualityChartDto> markQualityChartDtoList = new ArrayList<>();
-        List<MarkUserQuestion> markUserQuestionList = this.listByExamIdAndPaperNumberAndQuestionId(examId, paperNumber, questionId);
-        Double totalAvgScore = markUserQuestionList.stream().filter(m -> m.getAvgScore() != null).collect(Collectors.averagingDouble(MarkUserQuestion::getAvgScore));
-        for (MarkUserQuestion markUserQuestion : markUserQuestionList) {
-            MarkQualityChartDto markQualityChartDto = new MarkQualityChartDto();
-            markQualityChartDto.setUserId(markUserQuestion.getUserId());
-            SysUser sysUser = sysUserService.getById(markUserQuestion.getUserId());
-            markQualityChartDto.setLoginName(sysUser.getLoginName());
-            markQualityChartDto.setName(sysUser.getRealName());
-            markQualityChartDto.setTotalAvgScore(Calculator.round(totalAvgScore, 2));
-            markQualityChartDto.setAvgScore(markUserQuestion.getAvgScore() == null ? null : Calculator.round(markUserQuestion.getAvgScore(), 2));
-            markQualityChartDto.setMaxScore(markUserQuestion.getMaxScore() == null ? null : Calculator.round(markUserQuestion.getMaxScore(), 2));
-            markQualityChartDto.setMinScore(markUserQuestion.getMinScore() == null ? null : Calculator.round(markUserQuestion.getMinScore(), 2));
-            markQualityChartDtoList.add(markQualityChartDto);
-        }
-        return markQualityChartDtoList;
-    }
-
-    @Override
-    public List<MarkUserQuestion> listByExamIdAndPaperNumberAndUserIdAndEnableTure(Long examId, String paperNumber, Long userId) {
-        QueryWrapper<MarkUserQuestion> queryWrapper = new QueryWrapper<>();
-        queryWrapper.lambda().eq(MarkUserQuestion::getExamId, examId)
-                .eq(MarkUserQuestion::getPaperNumber, paperNumber)
-                .eq(MarkUserQuestion::getUserId, userId)
-                .eq(MarkUserQuestion::getEnable, true);
-        return this.list(queryWrapper);
-    }
-
-    @Override
-    public void deleteByExamIdAndPaperNumberAndQuestionId(Long examId, String paperNumber, Long questionId) {
-        UpdateWrapper<MarkUserQuestion> updateWrapper = new UpdateWrapper<>();
-        LambdaUpdateWrapper<MarkUserQuestion> lambda = updateWrapper.lambda();
-        lambda.eq(MarkUserQuestion::getExamId, examId)
-                .eq(MarkUserQuestion::getPaperNumber, paperNumber);
-        if (questionId != null) {
-            lambda.eq(MarkUserQuestion::getQuestionId, questionId);
-        }
-        this.remove(updateWrapper);
-    }
-
-    @Override
-    public List<String> listBindMarkers(Long examId, String paperNumber, Long questionId) {
-        List<MarkUserQuestion> markUserQuestions = listByExamIdAndPaperNumberAndQuestionId(examId, paperNumber, questionId);
-        List<String> userIds = new ArrayList<>();
-        if (CollectionUtils.isNotEmpty(markUserQuestions)) {
-            userIds = markUserQuestions.stream().filter(m -> m.getEnable()).map(m -> String.valueOf(m.getUserId())).collect(Collectors.toList());
-        }
-        return userIds;
-    }
-
-    @Override
-    public int countByMarkTask(Long userId, MarkPaperStatus status) {
-        return this.baseMapper.countByMarkTask(userId, status.name());
-    }
-
-    @Override
-    public void updateRejectCountByExamIdAndPaperNumberAndQuestionIdAndUserId(Long examId, String paperNumber, Long questionId, Long userId) {
-        this.baseMapper.updateRejectCountByExamIdAndPaperNumberAndQuestionIdAndUserId(examId, paperNumber, questionId, userId);
-    }
-
-    @Override
-    public void saveDefaultMarker(Long examId, String paperNumber, List<MarkQuestion> markQuestions) {
-        List<SysUser> sysUserList = this.baseMapper.listDefaultMarkerByExamIdAndPaperNumber(examId, paperNumber);
-        List<MarkUserQuestion> markUserQuestions = new ArrayList<>();
-        for (SysUser sysUser : sysUserList) {
-            for (MarkQuestion markQuestion : markQuestions) {
-                markUserQuestions.add(new MarkUserQuestion(examId, paperNumber, markQuestion.getId(), sysUser.getId()));
-            }
-        }
-        this.saveBatch(markUserQuestions);
-    }
-
-    @Override
-    public List<String> countClassByExamIdAndPaperNumberAndQuestionId(Long examId, String paperNumber, Long questionId) {
-        return this.baseMapper.countClassByExamIdAndPaperNumberAndQuestionId(examId, paperNumber, questionId);
-    }
-
-    @Override
-    public List<MarkQuestion> listSubjectiveQuestionByUserId(Long examId, String paperNumber, Long userId) {
-        return this.baseMapper.listSubjectiveQuestionByUserId(examId, paperNumber, userId);
-    }
-
-    @Override
-    public int countByExamIdAndPaperNumberAndAndUserId(Long examId, String paperNumber, Long userId) {
-        QueryWrapper<MarkUserQuestion> queryWrapper = new QueryWrapper<>();
-        queryWrapper.lambda().eq(MarkUserQuestion::getExamId, examId)
-                .eq(MarkUserQuestion::getPaperNumber, paperNumber)
-                .eq(MarkUserQuestion::getUserId, userId);
-        return this.count(queryWrapper);
-    }
-}
+package com.qmth.teachcloud.mark.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.qmth.teachcloud.common.bean.dto.MarkTaskSmsDto;
+import com.qmth.teachcloud.common.bean.dto.mark.MarkUser;
+import com.qmth.teachcloud.common.entity.MarkQuestion;
+import com.qmth.teachcloud.common.entity.SysUser;
+import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
+import com.qmth.teachcloud.common.enums.mark.MarkPaperStatus;
+import com.qmth.teachcloud.common.service.SysUserService;
+import com.qmth.teachcloud.common.util.ServletUtil;
+import com.qmth.teachcloud.mark.bean.marker.MarkerAddParam;
+import com.qmth.teachcloud.mark.dto.mark.entrance.MarkEntranceDto;
+import com.qmth.teachcloud.mark.dto.mark.manage.MarkQualityChartDto;
+import com.qmth.teachcloud.mark.dto.mark.manage.MarkQualityDto;
+import com.qmth.teachcloud.mark.dto.mark.manage.MarkUserGroupProgressDto;
+import com.qmth.teachcloud.mark.entity.MarkPaper;
+import com.qmth.teachcloud.mark.entity.MarkTask;
+import com.qmth.teachcloud.mark.entity.MarkUserClass;
+import com.qmth.teachcloud.mark.entity.MarkUserQuestion;
+import com.qmth.teachcloud.mark.enums.LockType;
+import com.qmth.teachcloud.mark.enums.MarkTaskStatus;
+import com.qmth.teachcloud.mark.lock.LockService;
+import com.qmth.teachcloud.mark.mapper.MarkUserQuestionMapper;
+import com.qmth.teachcloud.mark.service.*;
+import com.qmth.teachcloud.mark.utils.Calculator;
+import org.apache.commons.collections4.CollectionUtils;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * <p>
+ * 评卷员表 服务实现类
+ * </p>
+ *
+ * @author xf
+ * @since 2023-09-22
+ */
+@Service
+public class MarkUserQuestionServiceImpl extends ServiceImpl<MarkUserQuestionMapper, MarkUserQuestion> implements MarkUserQuestionService {
+
+    @Resource
+    private MarkQuestionService markQuestionService;
+    @Resource
+    private MarkTaskService markTaskService;
+    @Resource
+    private MarkPaperService markPaperService;
+    @Resource
+    private MarkUserClassService markUserClassService;
+    @Resource
+    private MarkSyncService markSyncService;
+    @Resource
+    private SysUserService sysUserService;
+    @Resource
+    private MarkService markService;
+    @Resource
+    private LockService lockService;
+
+    @Override
+    public IPage<MarkEntranceDto> listEntranceGroup(Long examId, Long openCollegeId, Long courseId, String paperNumber, Integer pageNumber, Integer pageSize) {
+        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
+        Page<MarkUserQuestion> page = new Page<>(pageNumber, pageSize);
+        IPage<MarkEntranceDto> markEntranceDtoIPage = this.baseMapper.listEntranceGroup(page, examId, openCollegeId, courseId, paperNumber, sysUser.getId(), MarkPaperStatus.FORMAL.name());
+        for (MarkEntranceDto record : markEntranceDtoIPage.getRecords()) {
+            MarkPaper markPaper = markPaperService.getByExamIdAndPaperNumber(record.getExamId(), record.getPaperNumber());
+            // 分班阅
+            List<String> classNames = null;
+            if (markPaper != null && markPaper.getClassMark() != null && markPaper.getClassMark()) {
+                List<MarkUserClass> markUserClassList = markUserClassService.listByExamIdAndPaperNumberAndUserId(record.getExamId(), record.getPaperNumber(), sysUser.getId());
+                if (CollectionUtils.isNotEmpty(markUserClassList)) {
+                    classNames = markUserClassList.stream().map(MarkUserClass::getClassName).collect(Collectors.toList());
+                }
+            }
+
+            List<MarkQuestion> markQuestionList = this.listSubjectiveQuestionByUserId(record.getExamId(), record.getPaperNumber(), sysUser.getId());
+            List<Long> questionIds = markQuestionList.stream().map(MarkQuestion::getId).collect(Collectors.toList());
+
+            int taskCount = markTaskService.countByExamIdAndPaperNumberAndUserIdAndAndClassNameAndQuestionIdIn(record.getExamId(), record.getPaperNumber(), null, classNames, questionIds);
+            record.setTaskCount(taskCount);
+            int unMarkedCount = markTaskService.countByExamIdAndPaperNumberAndUserIdAndAndClassNameAndQuestionIdIn(record.getExamId(), record.getPaperNumber(), null, classNames, questionIds, MarkTaskStatus.WAITING, MarkTaskStatus.WAIT_ARBITRATE, MarkTaskStatus.REJECTED, MarkTaskStatus.PROBLEM);
+            record.setLeftCount(unMarkedCount);
+            record.setMarkedCount(taskCount == 0 ? 0 : taskCount - unMarkedCount);
+            // 评卷进度
+            if (taskCount == 0) {
+                record.setPercent(0D);
+            } else {
+                BigDecimal bigDecimal = new BigDecimal(record.getMarkedCount() * 100).divide(new BigDecimal(taskCount), 2, RoundingMode.HALF_UP);
+                record.setPercent(bigDecimal.doubleValue());
+            }
+            // 分组题目
+            record.setQuestionNumber(markQuestionList.stream().map(m -> m.getMainNumber() + "-" + m.getSubNumber()).collect(Collectors.joining(",")));
+        }
+
+        return markEntranceDtoIPage;
+    }
+
+    @Override
+    public List<MarkUser> listGroupUserByExamIdAndPaperNumberAndQuestionIdAndClassName(Long examId, String paperNumber, Long questionId, String className) {
+        return this.baseMapper.listGroupUserByExamIdAndPaperNumberAndQuestionId(examId, paperNumber, questionId, className);
+    }
+
+    @Override
+    public IPage<MarkUserGroupProgressDto> pageGroupUserByExamIdAndPaperNumberAndQuestionId(Long examId, String paperNumber, Long questionId, String loginName, String className, Boolean marked, Integer pageNumber, Integer pageSize) {
+        Page<MarkUserGroupProgressDto> page = new Page<>(pageNumber, pageSize);
+        IPage<MarkUserGroupProgressDto> markUserGroupProgressDtoIPage = this.baseMapper.pageGroupUserByExamIdAndPaperNumberAndQuestionId(page, examId, paperNumber, questionId, loginName, className, marked);
+        for (MarkUserGroupProgressDto record : markUserGroupProgressDtoIPage.getRecords()) {
+            MarkQuestion markQuestion = markQuestionService.getById(record.getQuestionId());
+            record.setQuestionNumber(markQuestion.getQuestionNumber());
+            List<MarkTask> markTaskList = markTaskService.listByExamIdAndPaperNumberAndQuestionIdAndUserIdAndClassName(examId, paperNumber, record.getQuestionId(), record.getUserId(), null);
+            record.setResetting(lockService.isLocked(LockType.MARKER_RESET, record.getMarkUserQuestionId()));
+            record.setMarkedCount(markTaskService.markedCount(markTaskList));
+            record.setCurrentCount(markService.applyCurrentCount(markQuestion, record.getMarkUserQuestionId()));
+        }
+        return markUserGroupProgressDtoIPage;
+    }
+
+    @Override
+    public void addMarkUserQuestion(MarkerAddParam markerAddParam) {
+        if (CollectionUtils.isNotEmpty(markerAddParam.getUserIds())) {
+            // 根据是否合并设置评卷员参数,做合并
+            List<Long> questionIds = listMergeQuestionId(markerAddParam.getExamId(), markerAddParam.getPaperNumber(), markerAddParam.getQuestionId());
+
+            List<MarkUserQuestion> markUserGroups = new ArrayList<>();
+            for (Long userId : markerAddParam.getUserIds()) {
+                for (Long questionId : questionIds) {
+                    MarkUserQuestion markUserGroup = this.getByExamIdAndPaperNumberAndQuestionIdAndUserId(markerAddParam.getExamId(), markerAddParam.getPaperNumber(), questionId, userId);
+                    if (markUserGroup == null) {
+                        markUserGroups.add(new MarkUserQuestion(markerAddParam.getExamId(), markerAddParam.getPaperNumber(), questionId, userId));
+                    } else if (!markUserGroup.getEnable()) {
+                        markUserGroup.setEnable(true);
+                        markUserGroups.add(markUserGroup);
+                    }
+                }
+            }
+            if (CollectionUtils.isNotEmpty(markUserGroups)) {
+                this.saveOrUpdateBatch(markUserGroups);
+            }
+        }
+    }
+
+    private List<Long> listMergeQuestionId(Long examId, String paperNumber, Long questionId) {
+        MarkPaper markPaper = markPaperService.getByExamIdAndPaperNumber(examId, paperNumber);
+
+        MarkQuestion markQuestion = markQuestionService.getById(questionId);
+        if (markQuestion == null) {
+            throw ExceptionResultEnum.ERROR.exception("题目不存在");
+        }
+        List<Long> questionIds = new ArrayList<>();
+        if (markQuestion.getQuestionType() == 4 && markPaper != null && markPaper.getMergeMarker() != null && markPaper.getMergeMarker()) {
+            List<MarkQuestion> markQuestionList = markQuestionService.listByExamIdAndPaperNumberAndObjective(examId, paperNumber, false);
+            // 填空题,整个大题一起解绑
+            return markQuestionList.stream().filter(m -> markQuestion.getMainNumber().equals(m.getMainNumber()) && m.getQuestionType() == 4).map(MarkQuestion::getId).collect(Collectors.toList());
+        } else {
+            questionIds.add(questionId);
+        }
+        return questionIds;
+    }
+
+    @Override
+    public void setTopCount(List<Long> markUserQuestionIds, Integer topCount) {
+        for (Long markUserQuestionId : markUserQuestionIds) {
+            MarkUserQuestion markUserQuestion = this.getById(markUserQuestionId);
+            if (markUserQuestion != null) {
+                markUserQuestion.setTopCount(topCount);
+                this.updateById(markUserQuestion);
+            }
+        }
+    }
+
+    @Override
+    public MarkUserQuestion getByExamIdAndPaperNumberAndQuestionIdAndUserId(Long examId, String paperNumber, Long questionId, Long userId) {
+        QueryWrapper<MarkUserQuestion> queryWrapper = new QueryWrapper<>();
+        queryWrapper.lambda().eq(MarkUserQuestion::getExamId, examId)
+                .eq(MarkUserQuestion::getPaperNumber, paperNumber)
+                .eq(MarkUserQuestion::getQuestionId, questionId)
+                .eq(MarkUserQuestion::getUserId, userId);
+        return this.getOne(queryWrapper);
+    }
+
+    @Override
+    public void deleteMarker(MarkUserQuestion markUserQuestion) {
+        // 先回收,再删除
+        releaseMarker(Arrays.asList(markUserQuestion.getId()));
+        // 逻辑解绑
+        List<Long> ids = listMergeQuestionId(markUserQuestion.getExamId(), markUserQuestion.getPaperNumber(), markUserQuestion.getQuestionId());
+        UpdateWrapper<MarkUserQuestion> updateWrapper = new UpdateWrapper<>();
+        updateWrapper.lambda().set(MarkUserQuestion::getEnable, false)
+                .eq(MarkUserQuestion::getUserId, markUserQuestion.getUserId())
+                .in(MarkUserQuestion::getQuestionId, ids);
+        this.update(updateWrapper);
+    }
+
+    @Override
+    public void releaseMarker(List<Long> markUserGroupIds) {
+        for (Long markUserGroupId : markUserGroupIds) {
+            MarkUserQuestion markUserGroup = this.getById(markUserGroupId);
+            if (markUserGroup != null) {
+                try {
+                    lockService.waitlock(LockType.MARK_USER_QUESTION, markUserGroupId);
+                    markService.releaseByMarkUserGroup(markUserGroup);
+                } catch (Exception e) {
+                    log.error("release marker error", e);
+                } finally {
+                    lockService.unlock(LockType.MARK_USER_QUESTION, markUserGroupId);
+                }
+            }
+        }
+    }
+
+    @Override
+    public boolean resetMarker(MarkUserQuestion markUserQuestion) {
+        if (markUserQuestion != null) {
+            if (lockService.trylock(LockType.MARKER_RESET, markUserQuestion.getId())) {
+                markSyncService.markerResetSync(markUserQuestion);
+                return true;
+            } else {
+                throw ExceptionResultEnum.ERROR.exception("评卷员正在重置");
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public void resetById(Long id) {
+        UpdateWrapper<MarkUserQuestion> updateWrapper = new UpdateWrapper<>();
+        updateWrapper.lambda().set(MarkUserQuestion::getFinishCount, null)
+                .set(MarkUserQuestion::getHeaderFinishCount, null)
+                .set(MarkUserQuestion::getValidCount, null)
+                .set(MarkUserQuestion::getAvgScore, null)
+                .set(MarkUserQuestion::getAvgSpeed, null)
+                .set(MarkUserQuestion::getStdevScore, null)
+                .set(MarkUserQuestion::getMaxScore, null)
+                .set(MarkUserQuestion::getMinScore, null)
+                .eq(MarkUserQuestion::getId, id);
+        this.update(updateWrapper);
+    }
+
+    @Override
+    public IPage<MarkQualityDto> pageQuality(Long examId, String paperNumber, Long questionId, String loginName, Integer pageNumber, Integer pageSize) {
+        Page<MarkQualityDto> page = new Page<>(pageNumber, pageSize);
+        IPage<MarkQualityDto> markQualityDtoIPage = this.baseMapper.pageQuality(page, examId, paperNumber, questionId, loginName);
+        for (MarkQualityDto qualityDto : markQualityDtoIPage.getRecords()) {
+            MarkQuestion markQuestion = markQuestionService.getById(qualityDto.getQuestionId());
+            qualityDto.setQuestionNumber(markQuestion.getQuestionNumber());
+            if (qualityDto.getUserId() != null) {
+                SysUser sysUser = sysUserService.getByUserId(qualityDto.getUserId());
+                qualityDto.setLoginName(sysUser.getLoginName());
+                qualityDto.setName(sysUser.getRealName());
+                qualityDto.setOrgName(sysUser.getOrgName());
+                qualityDto.setAdoptionRate(Calculator.divide2String(Calculator.multiply(qualityDto.getValidCount(), 100), Double.valueOf(qualityDto.getFinishCount()), 2));
+                qualityDto.setAvgScore(Calculator.round(qualityDto.getAvgScore(), 2));
+            }
+        }
+        return markQualityDtoIPage;
+    }
+
+    @Override
+    public void updateQuality(Long examId, String paperNumber, Long questionId) {
+        if (questionId == null) {
+            throw ExceptionResultEnum.ERROR.exception("请选择评阅题目");
+        }
+        MarkQuestion markQuestion = markQuestionService.getById(questionId);
+        if (markQuestion != null) {
+            String lockKey = markService.getGroupKey(markQuestion);
+            if (lockService.trylock(LockType.BATCH_QUALITY, lockKey)) {
+                markSyncService.updateQuality(this.listByExamIdAndPaperNumberAndQuestionId(examId, paperNumber, questionId), lockKey);
+            }
+        }
+    }
+
+    @Override
+    public List<MarkUserQuestion> listByExamIdAndPaperNumberAndQuestionId(Long examId, String paperNumber, Long questionId) {
+        QueryWrapper<MarkUserQuestion> queryWrapper = new QueryWrapper<>();
+        queryWrapper.lambda().eq(MarkUserQuestion::getExamId, examId)
+                .eq(MarkUserQuestion::getPaperNumber, paperNumber)
+                .eq(MarkUserQuestion::getQuestionId, questionId)
+                .orderByAsc(MarkUserQuestion::getId);
+        return this.list(queryWrapper);
+    }
+
+    @Override
+    public void updateQualityById(Long markUserGroupId, int finishCount, int headerFinishCount, int validCount, double avgSpeed, double avgScore, double stdevScore, double maxScore, double minScore) {
+        UpdateWrapper<MarkUserQuestion> updateWrapper = new UpdateWrapper<>();
+        updateWrapper.lambda().set(MarkUserQuestion::getFinishCount, finishCount)
+                .set(MarkUserQuestion::getHeaderFinishCount, headerFinishCount)
+                .set(MarkUserQuestion::getValidCount, validCount)
+                .set(MarkUserQuestion::getAvgSpeed, avgSpeed)
+                .set(MarkUserQuestion::getAvgScore, avgScore)
+                .set(MarkUserQuestion::getStdevScore, stdevScore)
+                .set(MarkUserQuestion::getMaxScore, maxScore)
+                .set(MarkUserQuestion::getMinScore, minScore)
+                .eq(MarkUserQuestion::getId, markUserGroupId);
+        this.update(updateWrapper);
+    }
+
+    @Override
+    public List<MarkQualityChartDto> listQualityChart(Long examId, String paperNumber, Long questionId) {
+        if (questionId == null) {
+            throw ExceptionResultEnum.ERROR.exception("请选择对应的科目及题目,再查看给分曲线");
+        }
+        List<MarkQualityChartDto> markQualityChartDtoList = new ArrayList<>();
+        List<MarkUserQuestion> markUserQuestionList = this.listByExamIdAndPaperNumberAndQuestionId(examId, paperNumber, questionId);
+        Double totalAvgScore = markUserQuestionList.stream().filter(m -> m.getAvgScore() != null).collect(Collectors.averagingDouble(MarkUserQuestion::getAvgScore));
+        for (MarkUserQuestion markUserQuestion : markUserQuestionList) {
+            MarkQualityChartDto markQualityChartDto = new MarkQualityChartDto();
+            markQualityChartDto.setUserId(markUserQuestion.getUserId());
+            SysUser sysUser = sysUserService.getById(markUserQuestion.getUserId());
+            markQualityChartDto.setLoginName(sysUser.getLoginName());
+            markQualityChartDto.setName(sysUser.getRealName());
+            markQualityChartDto.setTotalAvgScore(Calculator.round(totalAvgScore, 2));
+            markQualityChartDto.setAvgScore(markUserQuestion.getAvgScore() == null ? null : Calculator.round(markUserQuestion.getAvgScore(), 2));
+            markQualityChartDto.setMaxScore(markUserQuestion.getMaxScore() == null ? null : Calculator.round(markUserQuestion.getMaxScore(), 2));
+            markQualityChartDto.setMinScore(markUserQuestion.getMinScore() == null ? null : Calculator.round(markUserQuestion.getMinScore(), 2));
+            markQualityChartDtoList.add(markQualityChartDto);
+        }
+        return markQualityChartDtoList;
+    }
+
+    @Override
+    public List<MarkUserQuestion> listByExamIdAndPaperNumberAndUserIdAndEnableTure(Long examId, String paperNumber, Long userId) {
+        QueryWrapper<MarkUserQuestion> queryWrapper = new QueryWrapper<>();
+        queryWrapper.lambda().eq(MarkUserQuestion::getExamId, examId)
+                .eq(MarkUserQuestion::getPaperNumber, paperNumber)
+                .eq(MarkUserQuestion::getUserId, userId)
+                .eq(MarkUserQuestion::getEnable, true);
+        return this.list(queryWrapper);
+    }
+
+    @Override
+    public void deleteByExamIdAndPaperNumberAndQuestionId(Long examId, String paperNumber, Long questionId) {
+        UpdateWrapper<MarkUserQuestion> updateWrapper = new UpdateWrapper<>();
+        LambdaUpdateWrapper<MarkUserQuestion> lambda = updateWrapper.lambda();
+        lambda.eq(MarkUserQuestion::getExamId, examId)
+                .eq(MarkUserQuestion::getPaperNumber, paperNumber);
+        if (questionId != null) {
+            lambda.eq(MarkUserQuestion::getQuestionId, questionId);
+        }
+        this.remove(updateWrapper);
+    }
+
+    @Override
+    public List<String> listBindMarkers(Long examId, String paperNumber, Long questionId) {
+        List<MarkUserQuestion> markUserQuestions = listByExamIdAndPaperNumberAndQuestionId(examId, paperNumber, questionId);
+        List<String> userIds = new ArrayList<>();
+        if (CollectionUtils.isNotEmpty(markUserQuestions)) {
+            userIds = markUserQuestions.stream().filter(m -> m.getEnable()).map(m -> String.valueOf(m.getUserId())).collect(Collectors.toList());
+        }
+        return userIds;
+    }
+
+    @Override
+    public int countByMarkTask(Long userId, MarkPaperStatus status) {
+        return this.baseMapper.countByMarkTask(userId, status.name());
+    }
+
+    @Override
+    public void updateRejectCountByExamIdAndPaperNumberAndQuestionIdAndUserId(Long examId, String paperNumber, Long questionId, Long userId) {
+        this.baseMapper.updateRejectCountByExamIdAndPaperNumberAndQuestionIdAndUserId(examId, paperNumber, questionId, userId);
+    }
+
+    @Override
+    public void saveDefaultMarker(Long examId, String paperNumber, List<MarkQuestion> markQuestions) {
+        List<SysUser> sysUserList = this.baseMapper.listDefaultMarkerByExamIdAndPaperNumber(examId, paperNumber);
+        List<MarkUserQuestion> markUserQuestions = new ArrayList<>();
+        for (SysUser sysUser : sysUserList) {
+            for (MarkQuestion markQuestion : markQuestions) {
+                markUserQuestions.add(new MarkUserQuestion(examId, paperNumber, markQuestion.getId(), sysUser.getId()));
+            }
+        }
+        this.saveBatch(markUserQuestions);
+    }
+
+    @Override
+    public List<String> countClassByExamIdAndPaperNumberAndQuestionId(Long examId, String paperNumber, Long questionId) {
+        return this.baseMapper.countClassByExamIdAndPaperNumberAndQuestionId(examId, paperNumber, questionId);
+    }
+
+    @Override
+    public List<MarkQuestion> listSubjectiveQuestionByUserId(Long examId, String paperNumber, Long userId) {
+        return this.baseMapper.listSubjectiveQuestionByUserId(examId, paperNumber, userId);
+    }
+
+    @Override
+    public int countByExamIdAndPaperNumberAndAndUserId(Long examId, String paperNumber, Long userId) {
+        QueryWrapper<MarkUserQuestion> queryWrapper = new QueryWrapper<>();
+        queryWrapper.lambda().eq(MarkUserQuestion::getExamId, examId)
+                .eq(MarkUserQuestion::getPaperNumber, paperNumber)
+                .eq(MarkUserQuestion::getUserId, userId);
+        return this.count(queryWrapper);
+    }
+
+    /**
+     * 根据考试id&课程id&试卷编码查询待发送阅卷待办任务
+     *
+     * @param examId
+     * @param courseId
+     * @param paperNumber
+     * @return
+     */
+    @Override
+    public List<MarkTaskSmsDto> findMarkTaskSms(Long examId, Long courseId, String paperNumber) {
+        return this.baseMapper.findMarkTaskSms(examId, courseId, paperNumber);
+    }
+}

+ 2 - 1
teachcloud-mark/src/main/resources/mapper/MarkStudentMapper.xml

@@ -1112,9 +1112,10 @@
                           mark_task mt
                       WHERE
                           ms.id = mt.student_id)
+        </where>
+        order by ms.id
         <if test="limit != null and limit != ''">
             ${limit}
         </if>
-        </where>
     </select>
 </mapper>

+ 38 - 0
teachcloud-mark/src/main/resources/mapper/MarkUserQuestionMapper.xml

@@ -251,4 +251,42 @@
           AND question_id = #{questionId}
           AND user_id = #{userId}
     </update>
+
+    <select id="findMarkTaskSms" resultType="com.qmth.teachcloud.common.bean.dto.MarkTaskSmsDto">
+        select
+            muq.exam_id as examId,
+            muq.paper_number as paperNumber,
+            mq.course_id as courseId,
+            muq.user_id as userId,
+            be.name as examName,
+            bc.name as courseName,
+            su.mobile_number as mobileNumber,
+            count(muq.user_id) as markQuestionCount
+        from
+            mark_user_question muq
+            join mark_question mq on mq.id = muq.question_id
+            join basic_course bc on bc.id = mq.course_id
+            join sys_user su on su.id = muq.user_id
+            join basic_exam be on be.id = muq.exam_id
+        <where>
+            <if test="examId != null and examId != ''">
+                and muq.exam_id = #{examId}
+            </if>
+            <if test="courseId != null and courseId != ''">
+                and mq.course_id = #{courseId}
+            </if>
+            <if test="paperNumber != null and paperNumber != ''">
+                and muq.paper_number = #{paperNumber}
+            </if>
+        </where>
+        group by
+            muq.exam_id,
+            muq.paper_number,
+            mq.course_id,
+            muq.user_id,
+            be.name,
+            bc.name,
+            su.mobile_number
+        order by muq.user_id
+    </select>
 </mapper>

+ 2 - 0
teachcloud-task/src/main/java/com/qmth/teachcloud/task/job/BuildMarkTaskJob.java

@@ -2,6 +2,7 @@ package com.qmth.teachcloud.task.job;
 
 import com.qmth.teachcloud.common.contant.SystemConstant;
 import com.qmth.teachcloud.task.job.service.JobService;
+import org.quartz.DisallowConcurrentExecution;
 import org.quartz.JobExecutionContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -12,6 +13,7 @@ import javax.annotation.Resource;
 /**
  * 生成评卷任务
  */
+@DisallowConcurrentExecution//串行执行
 public class BuildMarkTaskJob extends QuartzJobBean {
     private final static Logger log = LoggerFactory.getLogger(BuildMarkTaskJob.class);
 

+ 7 - 0
teachcloud-task/src/main/java/com/qmth/teachcloud/task/job/service/impl/JobServiceImpl.java

@@ -7,6 +7,7 @@ import com.qmth.distributed.print.business.enums.ExamDetailStatusEnum;
 import com.qmth.distributed.print.business.service.*;
 import com.qmth.distributed.print.business.templete.execute.AsyncCreatePdfTemplateService;
 import com.qmth.distributed.print.business.util.ExamTaskUtil;
+import com.qmth.teachcloud.common.bean.dto.MarkTaskSmsDto;
 import com.qmth.teachcloud.common.bean.dto.MqDto;
 import com.qmth.teachcloud.common.bean.vo.PaperInfoVo;
 import com.qmth.teachcloud.common.contant.SystemConstant;
@@ -150,6 +151,12 @@ public class JobServiceImpl implements JobService {
             List<MarkPaper> markPaperList = markPaperService.listQualityMarkPaperByStatus(MarkPaperStatus.FORMAL, 0);
             for (MarkPaper markPaper : markPaperList) {
                 markService.buildMarkTask(markPaper);
+                List<MarkTaskSmsDto> markTaskSmsDtoList = markUserQuestionService.findMarkTaskSms(markPaper.getExamId(), markPaper.getCourseId(), markPaper.getPaperNumber());
+                if (CollectionUtils.isNotEmpty(markTaskSmsDtoList)) {
+                    for (MarkTaskSmsDto m : markTaskSmsDtoList) {
+
+                    }
+                }
             }
         } catch (Exception e) {
             log.error("auto-create library error", e);