فهرست منبع

联考版-迭代

xiaof 3 سال پیش
والد
کامیت
9ef13fee65
18فایلهای تغییر یافته به همراه560 افزوده شده و 82 حذف شده
  1. 21 7
      stmms-ms-accesscontrol/src/main/java/cn/com/qmth/stmms/ms/accesscontrol/api/AuthApi.java
  2. 4 2
      stmms-ms-admin/src/main/java/cn/com/qmth/stmms/ms/admin/service/DataUploadService.java
  3. 2 1
      stmms-ms-collect/src/main/java/cn/com/qmth/stmms/ms/collect/util/RotateTask.java
  4. 6 0
      stmms-ms-commons/pom.xml
  5. 19 0
      stmms-ms-commons/src/main/java/cn/com/qmth/stmms/ms/commons/lock/LockProvider.java
  6. 106 0
      stmms-ms-commons/src/main/java/cn/com/qmth/stmms/ms/commons/lock/LockService.java
  7. 16 0
      stmms-ms-commons/src/main/java/cn/com/qmth/stmms/ms/commons/lock/LockType.java
  8. 99 0
      stmms-ms-commons/src/main/java/cn/com/qmth/stmms/ms/commons/lock/impl/CustomLockProvider.java
  9. 100 0
      stmms-ms-commons/src/main/java/cn/com/qmth/stmms/ms/commons/lock/impl/JdkLockProvider.java
  10. 135 0
      stmms-ms-commons/src/main/java/cn/com/qmth/stmms/ms/commons/lock/impl/ReadWriteLock.java
  11. 0 4
      stmms-ms-commons/src/main/java/cn/com/qmth/stmms/ms/commons/utils/MD5Util.java
  12. 2 1
      stmms-ms-core/src/main/java/cn/com/qmth/stmms/ms/core/repository/MarkTaskRepo.java
  13. 1 1
      stmms-ms-core/src/main/java/cn/com/qmth/stmms/ms/core/repository/PaperRepo.java
  14. 11 22
      stmms-ms-core/src/main/java/cn/com/qmth/stmms/ms/core/specification/StudentSpecification.java
  15. 1 1
      stmms-ms-marking/src/main/java/cn/com/qmth/stmms/ms/marking/api/MakrerApi.java
  16. 23 3
      stmms-ms-marking/src/main/java/cn/com/qmth/stmms/ms/marking/api/MarkTaskApi.java
  17. 14 10
      stmms-ms-marking/src/main/java/cn/com/qmth/stmms/ms/marking/api/PaperApi.java
  18. 0 30
      stmms-ms-marking/src/main/java/cn/com/qmth/stmms/ms/marking/service/MarkingService.java

+ 21 - 7
stmms-ms-accesscontrol/src/main/java/cn/com/qmth/stmms/ms/accesscontrol/api/AuthApi.java

@@ -3,15 +3,21 @@ package cn.com.qmth.stmms.ms.accesscontrol.api;
 import cn.com.qmth.stmms.ms.accesscontrol.config.LoginConfig;
 import cn.com.qmth.stmms.ms.commons.utils.AesUtil;
 import cn.com.qmth.stmms.ms.core.cache.CacheService;
+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.Role;
+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 org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.CollectionUtils;
 import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpSession;
+import java.util.List;
 import java.util.Objects;
 
 /**
@@ -30,6 +36,12 @@ public class AuthApi {
     @Autowired
     private CacheService cacheService;
 
+    @Autowired
+    private MarkTaskRepo markTaskRepo;
+
+    @Autowired
+    private MarkSubjectRepo markSubjectRepo;
+
     @RequestMapping(value = "/login", method = RequestMethod.POST)
     public MarkUser login(MarkUser user, HttpServletRequest request) throws Exception {
         MarkUser domain = null;
@@ -81,13 +93,15 @@ public class AuthApi {
             domain.setSessionId(request.getSession().getId());
             markUserRepo.save(domain);
         }
-//        HttpSession session = request.getSession();
-//        String token = (String) request.getSession().getAttribute("token");
-//        if (!StringUtils.isEmpty(token)) {
-//            session.setAttribute("token", null);
-//        }
-        //session过期时间
-//        session.setMaxInactiveInterval(-1);
+
+        if (Objects.equals(Role.MARKER, domain.getRole())) {
+            MarkSubject markSubject = markSubjectRepo.findOne(domain.getWorkId() + "-" + domain.getSubject().name());
+            List<MarkTask> markTasks = markTaskRepo.findByWorkIdAndSubjectAndMarkerIdAndStageLimit(domain.getWorkId(), domain.getSubject().name(), domain.getId(), markSubject.getStage().ordinal());
+            if (CollectionUtils.isEmpty(markTasks)) {
+                throw new RuntimeException("没有评卷任务");
+            }
+        }
+
         String token = System.currentTimeMillis() + "#" + domain.getLoginName() + "#" + domain.getId();
         token = AesUtil.encoder(token, "token", null);
 //        session.setAttribute("token", System.currentTimeMillis() + "#" + domain.getLoginName() + "#" + domain.getId());

+ 4 - 2
stmms-ms-admin/src/main/java/cn/com/qmth/stmms/ms/admin/service/DataUploadService.java

@@ -407,10 +407,12 @@ public class DataUploadService {
                     Student studentNew = null;
                     Student student = studentRepo.findByWorkIdAndExamNumberAndTest(workId, dto.getExamNumber(), String.valueOf(TrialEnum.DEFAULT.getId()));
                     if (student == null) {
-                        throw new Exception("没有学生" + dto.getName() + "信息");
+                        return null;
+//                        throw new Exception("没有学生" + dto.getName() + "信息");
                     }
                     if (!student.getUploadStatus().contains(subject + ":1")) {
-                        throw new Exception("学生" + student.getName() + "未上传完试卷");
+//                        throw new Exception("学生" + student.getName() + "未上传完试卷");
+                        return null;
                     }
 
                     //复制paper

+ 2 - 1
stmms-ms-collect/src/main/java/cn/com/qmth/stmms/ms/collect/util/RotateTask.java

@@ -11,6 +11,7 @@ import cn.com.qmth.stmms.ms.commons.utils.image.ImageCompression;
 import cn.com.qmth.stmms.ms.core.cache.ParamCache;
 import cn.com.qmth.stmms.ms.core.domain.Paper;
 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.repository.PaperRepo;
 import cn.com.qmth.stmms.ms.core.repository.StudentRepo;
 import org.apache.commons.codec.digest.DigestUtils;
@@ -60,7 +61,7 @@ public class RotateTask implements Runnable {
             LOGGER.info("准备生成缩略和裁切旋转图:{}, paperId:{}", start, paper.getId());
             if (ParamCache.paramMap.get(paper.getWorkId()).getImageEncrypt() == 1) {
                 try {
-                    Student student = studentRepo.findByWorkIdAndExamNumber(paper.getWorkId(), paper.getExamNumber());
+                    Student student = studentRepo.findByWorkIdAndExamNumberAndTest(paper.getWorkId(), paper.getExamNumber(), String.valueOf(TrialEnum.DEFAULT.ordinal()));
                     String imageMd5 = MD5Util.getImageRuleMd5(paper.getWorkId(), paper.getSubject().ordinal(), paper.getAreaCode(), paper.getExamNumber(), student.getId());
                     thumbPath = systemConfig.getThumbDir() + File.separator + paper.getWorkId() + File.separator + paper.getSubject().toString()
                             + File.separator + paper.getAreaCode() + File.separator + imageMd5;

+ 6 - 0
stmms-ms-commons/pom.xml

@@ -71,5 +71,11 @@
             <artifactId>aliyun-sdk-oss</artifactId>
             <version>3.8.0</version>
         </dependency>
+        <dependency>
+            <groupId>commons-lang</groupId>
+            <artifactId>commons-lang</artifactId>
+            <version>2.6</version>
+            <scope>compile</scope>
+        </dependency>
     </dependencies>
 </project>

+ 19 - 0
stmms-ms-commons/src/main/java/cn/com/qmth/stmms/ms/commons/lock/LockProvider.java

@@ -0,0 +1,19 @@
+package cn.com.qmth.stmms.ms.commons.lock;
+
+
+public interface LockProvider {
+
+    void waitLock(LockType type, String key);
+
+    boolean tryLock(LockType type, String key);
+
+    void unlock(LockType type, String key);
+
+    boolean isLocked(LockType type, String key);
+
+    void watch(LockType type, String key);
+
+    void unwatch(LockType type, String key);
+
+    void clear();
+}

+ 106 - 0
stmms-ms-commons/src/main/java/cn/com/qmth/stmms/ms/commons/lock/LockService.java

@@ -0,0 +1,106 @@
+package cn.com.qmth.stmms.ms.commons.lock;
+
+import cn.com.qmth.stmms.ms.commons.lock.impl.CustomLockProvider;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.stereotype.Component;
+
+@Component("lockService")
+public class LockService implements InitializingBean, ApplicationContextAware {
+
+    protected static final Logger log = LoggerFactory.getLogger(LockService.class);
+
+    private static final String KEY_JOINER = "\t";
+
+    private ApplicationContext context;
+
+    private LockProvider provider;
+
+    /**
+     * 尝试获取排他锁,立即返回获取结果
+     *
+     * @param type
+     * @param keys
+     * @return
+     */
+    public boolean trylock(LockType type, Object... keys) {
+        return provider.tryLock(type, getKeys(keys));
+    }
+
+    /**
+     * 等待获取排他锁,线程阻塞直到成功获取
+     *
+     * @param type
+     * @param keys
+     */
+    public void waitlock(LockType type, Object... keys) {
+        provider.waitLock(type, getKeys(keys));
+    }
+
+    /**
+     * 释放已获取的排他锁
+     *
+     * @param type
+     * @param keys
+     */
+    public void unlock(LockType type, Object... keys) {
+        provider.unlock(type, getKeys(keys));
+    }
+
+    /**
+     * 检测排他锁是否已被获取
+     *
+     * @param type
+     * @param keys
+     * @return
+     */
+    public boolean isLocked(LockType type, Object... keys) {
+        return provider.isLocked(type, getKeys(keys));
+    }
+
+    /**
+     * 等待获取可重入的读锁
+     *
+     * @param type
+     * @param keys
+     */
+    public void watch(LockType type, Object... keys) {
+        provider.watch(type, getKeys(keys));
+    }
+
+    /**
+     * 释放已获取的读锁
+     *
+     * @param type
+     * @param keys
+     */
+    public void unwatch(LockType type, Object... keys) {
+        provider.unwatch(type, getKeys(keys));
+    }
+
+    /**
+     * 释放长时间未使用的锁
+     */
+    public void clear() {
+        provider.clear();
+    }
+
+    private String getKeys(Object... keys) {
+        return StringUtils.join(keys, KEY_JOINER);
+    }
+
+    @Override
+    public void afterPropertiesSet() throws Exception {
+        this.provider = this.context.getBean(CustomLockProvider.class);
+    }
+
+    @Override
+    public void setApplicationContext(ApplicationContext context) throws BeansException {
+        this.context = context;
+    }
+}

+ 16 - 0
stmms-ms-commons/src/main/java/cn/com/qmth/stmms/ms/commons/lock/LockType.java

@@ -0,0 +1,16 @@
+package cn.com.qmth.stmms.ms.commons.lock;
+
+public enum LockType {
+    LEVEL("level"), SCORE("score");
+
+    private String name;
+
+    private LockType(String name) {
+        this.name = name;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+}

+ 99 - 0
stmms-ms-commons/src/main/java/cn/com/qmth/stmms/ms/commons/lock/impl/CustomLockProvider.java

@@ -0,0 +1,99 @@
+package cn.com.qmth.stmms.ms.commons.lock.impl;
+
+import cn.com.qmth.stmms.ms.commons.lock.LockProvider;
+import cn.com.qmth.stmms.ms.commons.lock.LockType;
+import org.springframework.stereotype.Component;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+/**
+ * 自己实现的内存锁控制
+ *
+ * @author luoshi
+ */
+@Component("customLockProvider")
+public class CustomLockProvider implements LockProvider {
+
+    private Map<LockType, Map<String, ReadWriteLock>> lockMap = new HashMap<>();
+
+    @Override
+    public void waitLock(LockType type, String key) {
+        getLock(type, key).write();
+    }
+
+    @Override
+    public boolean tryLock(LockType type, String key) {
+        return getLock(type, key).tryWrite();
+    }
+
+    @Override
+    public boolean isLocked(LockType type, String key) {
+        return getLock(type, key).writing();
+    }
+
+    @Override
+    public void unlock(LockType type, String key) {
+        getLock(type, key).unWrite();
+    }
+
+    @Override
+    public void watch(LockType type, String key) {
+        getLock(type, key).read();
+    }
+
+    @Override
+    public void unwatch(LockType type, String key) {
+        getLock(type, key).unRead();
+    }
+
+    private ReadWriteLock getLock(LockType type, String key) {
+        Map<String, ReadWriteLock> map = lockMap.get(type);
+        if (map == null) {
+            synchronized (lockMap) {
+                map = lockMap.get(type);
+                if (map == null) {
+                    map = new HashMap<>();
+                    lockMap.put(type, map);
+                }
+            }
+        }
+
+        ReadWriteLock lock = map.get(key);
+        if (lock == null) {
+            synchronized (map) {
+                lock = map.get(key);
+                if (lock == null) {
+                    lock = new ReadWriteLock();
+                    map.put(key, lock);
+                }
+            }
+        }
+
+        return lock;
+    }
+
+    public void clear() {
+        if (lockMap.isEmpty()) {
+            return;
+        }
+        synchronized (lockMap) {
+            for (Map<String, ReadWriteLock> map : lockMap.values()) {
+                Set<String> keys = new HashSet<>();
+                for (Entry<String, ReadWriteLock> entry : map.entrySet()) {
+                    if (!entry.getValue().writing() && entry.getValue().readCount() == 0) {
+                        keys.add(entry.getKey());
+                    }
+                }
+                for (String key : keys) {
+                    map.remove(key);
+                }
+                keys.clear();
+            }
+        }
+    }
+
+}

+ 100 - 0
stmms-ms-commons/src/main/java/cn/com/qmth/stmms/ms/commons/lock/impl/JdkLockProvider.java

@@ -0,0 +1,100 @@
+package cn.com.qmth.stmms.ms.commons.lock.impl;
+
+import cn.com.qmth.stmms.ms.commons.lock.LockProvider;
+import cn.com.qmth.stmms.ms.commons.lock.LockType;
+import org.springframework.stereotype.Component;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+/**
+ * JVM内存实现的锁控制
+ *
+ * @author luoshi
+ */
+@Component("jdkLockProvider")
+public class JdkLockProvider implements LockProvider {
+
+    private Map<LockType, Map<String, ReentrantReadWriteLock>> lockMap = new HashMap<>();
+
+    @Override
+    public void waitLock(LockType type, String key) {
+        getLock(type, key).writeLock().lock();
+    }
+
+    @Override
+    public boolean tryLock(LockType type, String key) {
+        return getLock(type, key).writeLock().tryLock();
+    }
+
+    @Override
+    public boolean isLocked(LockType type, String key) {
+        return getLock(type, key).isWriteLocked();
+    }
+
+    @Override
+    public void unlock(LockType type, String key) {
+        getLock(type, key).writeLock().unlock();
+    }
+
+    @Override
+    public void watch(LockType type, String key) {
+        getLock(type, key).readLock().lock();
+    }
+
+    @Override
+    public void unwatch(LockType type, String key) {
+        getLock(type, key).readLock().unlock();
+    }
+
+    private ReentrantReadWriteLock getLock(LockType type, String key) {
+        Map<String, ReentrantReadWriteLock> map = lockMap.get(type);
+        if (map == null) {
+            synchronized (lockMap) {
+                map = lockMap.get(type);
+                if (map == null) {
+                    map = new HashMap<>();
+                    lockMap.put(type, map);
+                }
+            }
+        }
+
+        ReentrantReadWriteLock lock = map.get(key);
+        if (lock == null) {
+            synchronized (map) {
+                lock = map.get(key);
+                if (lock == null) {
+                    lock = new ReentrantReadWriteLock();
+                    map.put(key, lock);
+                }
+            }
+        }
+
+        return lock;
+    }
+
+    public void clear() {
+        if (lockMap.isEmpty()) {
+            return;
+        }
+        synchronized (lockMap) {
+            for (Map<String, ReentrantReadWriteLock> map : lockMap.values()) {
+                Set<String> keys = new HashSet<>();
+                for (Entry<String, ReentrantReadWriteLock> entry : map.entrySet()) {
+                    if (!entry.getValue().isWriteLocked() && entry.getValue().getReadLockCount() == 0) {
+                        keys.add(entry.getKey());
+                    }
+                }
+                for (String key : keys) {
+                    map.remove(key);
+                }
+                keys.clear();
+            }
+        }
+    }
+
+}

+ 135 - 0
stmms-ms-commons/src/main/java/cn/com/qmth/stmms/ms/commons/lock/impl/ReadWriteLock.java

@@ -0,0 +1,135 @@
+package cn.com.qmth.stmms.ms.commons.lock.impl;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.IntUnaryOperator;
+
+/**
+ * 简单读写锁实现<br>
+ * 0表示空闲状态,-1表示正在写,>0表示正在读
+ * 
+ * @author luoshi
+ *
+ */
+public class ReadWriteLock {
+
+    private static ReadOperator readOperator = new ReadOperator();
+
+    private static UnReadOperator unreadOperator = new UnReadOperator();
+
+    private AtomicInteger value;
+
+    public ReadWriteLock() {
+        this.value = new AtomicInteger(0);
+    }
+
+    public int read() {
+        int result = 0;
+        while ((result = value.updateAndGet(readOperator)) < 1) {
+            ;
+        }
+        return result;
+    }
+
+    public int unRead() {
+        if (value.get() < 1) {
+            throw new RuntimeException("unread error");
+        }
+        return value.updateAndGet(unreadOperator);
+    }
+
+    public int readCount() {
+        return Math.max(0, value.get());
+    }
+
+    public int write() {
+        while (!value.compareAndSet(0, -1)) {
+            ;
+        }
+        return -1;
+    }
+
+    public boolean tryWrite() {
+        return value.compareAndSet(0, -1);
+    }
+
+    public int unWrite() {
+        while (!value.compareAndSet(-1, 0)) {
+            ;
+        }
+        return 0;
+    }
+
+    public boolean writing() {
+        return value.get() == -1;
+    }
+
+    static class ReadOperator implements IntUnaryOperator {
+
+        @Override
+        public int applyAsInt(int operand) {
+            return operand >= 0 ? operand + 1 : operand;
+        }
+
+    }
+
+    static class UnReadOperator implements IntUnaryOperator {
+
+        @Override
+        public int applyAsInt(int operand) {
+            return operand >= 1 ? operand - 1 : operand;
+        }
+
+    }
+
+    static class LockTestThread implements Runnable {
+
+        private ReadWriteLock lock;
+
+        private int number;
+
+        public LockTestThread(int number, ReadWriteLock lock) {
+            this.lock = lock;
+            this.number = number;
+        }
+
+        @Override
+        public void run() {
+            for (int i = 0; i < 10000; i++) {
+                if (Math.random() < 0.7) {
+                    System.out.println(
+                            "[thread-" + number + "]   read: " + lock.read() + "[" + System.currentTimeMillis() + "]");
+                    try {
+                        Thread.sleep(100 * ((i % 10) + 1));
+                    } catch (InterruptedException e) {
+                        e.printStackTrace();
+                    }
+                    System.out.println("[thread-" + number + "] unread: " + lock.unRead() + "["
+                            + System.currentTimeMillis() + "]");
+                } else {
+                    System.out.println(
+                            "[thread-" + number + "]  write:" + lock.write() + "[" + System.currentTimeMillis() + "]");
+                    try {
+                        Thread.sleep(100 * ((i % 10) + 1));
+                    } catch (InterruptedException e) {
+                        e.printStackTrace();
+                    }
+                    System.out.println("[thread-" + number + "]unwrite: " + lock.unWrite() + "["
+                            + System.currentTimeMillis() + "]");
+                }
+            }
+        }
+    }
+
+    public static void main(String[] args) {
+        ExecutorService executor = Executors.newFixedThreadPool(5);
+        final ReadWriteLock lock = new ReadWriteLock();
+        for (int i = 0; i < 5; i++) {
+            executor.submit(new LockTestThread(i + 1, lock));
+        }
+
+        executor.shutdown();
+    }
+
+}

+ 0 - 4
stmms-ms-commons/src/main/java/cn/com/qmth/stmms/ms/commons/utils/MD5Util.java

@@ -65,10 +65,6 @@ public class MD5Util {
         StringBuffer stringBuffer = new StringBuffer(String.valueOf(workId)).append(subjectId).append(areaCode).append(examNumber).append(studentId);
         String rule = stringBuffer.toString();
         LOGGER.info("rule:{},length:{}", rule, rule.length());
-        if (rule.length() < 16) {
-            rule = String.format("%016d", rule);
-            LOGGER.info("rule补零后:{},length:{}", rule, rule.length());
-        }
         return encoder(rule);
     }
 }

+ 2 - 1
stmms-ms-core/src/main/java/cn/com/qmth/stmms/ms/core/repository/MarkTaskRepo.java

@@ -228,7 +228,8 @@ public interface MarkTaskRepo extends JpaRepository<MarkTask, Long>, JpaSpecific
     @Query(value = "SELECT count(1) from mark_task m where m.question_id = ?1 and m.marker_id = ?2 and m.stage = ?3 and  m.batch_no is not null and m.is_rejected = true", nativeQuery = true)
     int countByQuestionIdAndMarkerIdAndStageAndIsRejectedTrue(Long questionId, Long markerId, int ordinal);
 
-    List<MarkTask> findByWorkIdAndSubjectAndMarkerIdAndStage(Long workId, Subject subject, Long valueOf, MarkStage stage);
+    @Query(value = "select * from mark_task where work_id = ?1 and subject = ?2 and marker_id = ?3 and stage = ?4 limit 1", nativeQuery = true)
+    List<MarkTask> findByWorkIdAndSubjectAndMarkerIdAndStageLimit(Long workId, String subject, Long valueOf, int stage);
 
     int countByWorkIdAndSubjectAndStage(Long workId, Subject subject, MarkStage stage);
 

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

@@ -389,7 +389,7 @@ public interface PaperRepo extends JpaRepository<Paper, Long>, JpaSpecificationE
     void updateScoreByWorkIdAndSubject(Long workId, String name);
 
     @Modifying
-    @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.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)
+    @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);
 
 //    List<Paper> findByWorkIdAndSubjectAndInspectRange(Long workId, Subject subject, Long inspectRange);

+ 11 - 22
stmms-ms-core/src/main/java/cn/com/qmth/stmms/ms/core/specification/StudentSpecification.java

@@ -6,6 +6,7 @@ import cn.com.qmth.stmms.ms.core.domain.enums.TrialEnum;
 import cn.com.qmth.stmms.ms.core.vo.Subject;
 import org.springframework.data.jpa.domain.Specification;
 import org.springframework.util.CollectionUtils;
+import org.springframework.util.StringUtils;
 
 import javax.persistence.criteria.Predicate;
 import java.util.ArrayList;
@@ -20,8 +21,8 @@ public class StudentSpecification extends PagingAndSortingSpecification {
     private String studentName;
     private String uploadStatus;
     private Boolean isAbsent;
-    private Long startNumber;//起始考号
-    private Long endNumber;//终止考号
+    private String startNumber;//起始考号
+    private String endNumber;//终止考号
     private Boolean upload;//上传状态
     private String subject;//科目
 
@@ -44,19 +45,19 @@ public class StudentSpecification extends PagingAndSortingSpecification {
         this.subject = subject;
     }
 
-    public Long getStartNumber() {
+    public String getStartNumber() {
         return startNumber;
     }
 
-    public void setStartNumber(Long startNumber) {
+    public void setStartNumber(String startNumber) {
         this.startNumber = startNumber;
     }
 
-    public Long getEndNumber() {
+    public String getEndNumber() {
         return endNumber;
     }
 
-    public void setEndNumber(Long endNumber) {
+    public void setEndNumber(String endNumber) {
         this.endNumber = endNumber;
     }
 
@@ -138,7 +139,7 @@ public class StudentSpecification extends PagingAndSortingSpecification {
             List<Predicate> predicates = new ArrayList<Predicate>();
             List<Predicate> listPermission1 = new ArrayList<>();
             predicates.add(cb.equal(root.get("test"), String.valueOf(TrialEnum.DEFAULT.getId())));
-            if (getStudentName() != null) {
+            if (!StringUtils.isEmpty(getStudentName())) {
                 predicates.add(cb.like(root.get("name"), "%" + getStudentName() + "%"));
             }
             if (getWorkId() != null) {
@@ -162,18 +163,6 @@ public class StudentSpecification extends PagingAndSortingSpecification {
                     } else {
                         predicates.add(cb.equal(root.get("uploadStatus"), "SX:0,SC:0,SM:0"));
                     }
-                    // 未上传考生不包含标记缺考
-                    if (Subject.SC.name().equals(getSubject())) {
-                        predicates.add(cb.equal(root.get("scMissing"), false));
-                    } else if (Subject.SX.name().equals(getSubject())) {
-                        predicates.add(cb.equal(root.get("sxMissing"), false));
-                    } else if (Subject.SM.name().equals(getSubject())) {
-                        predicates.add(cb.equal(root.get("smMissing"), false));
-                    } else {
-                        predicates.add(cb.equal(root.get("scMissing"), false));
-                        predicates.add(cb.equal(root.get("sxMissing"), false));
-                        predicates.add(cb.equal(root.get("smMissing"), false));
-                    }
                 } else if (getUpload() != null && getUpload()) {
                     if (Objects.nonNull(getSubject())  && !getSubject().isEmpty()) {
                         predicates.add(cb.like(root.get("uploadStatus"), "%" + getSubject() + ":1" + "%"));
@@ -183,11 +172,11 @@ public class StudentSpecification extends PagingAndSortingSpecification {
                 }
             }
 
-            if (startNumber != null && endNumber != null) {
+            if (!StringUtils.isEmpty(startNumber) && !StringUtils.isEmpty(endNumber)) {
                 predicates.add(cb.between(root.get("examNumber"), startNumber, endNumber));
-            } else if (startNumber != null) {
+            } else if (!StringUtils.isEmpty(startNumber)) {
                 predicates.add(cb.equal(root.get("examNumber"), startNumber));
-            } else if (endNumber != null) {
+            } else if (!StringUtils.isEmpty(endNumber)) {
                 predicates.add(cb.equal(root.get("examNumber"), endNumber));
             }
 

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

@@ -618,7 +618,7 @@ public class MakrerApi {
                 successCount = paperRepo.countByWorkIdAndSubjectAndScoreNotNullAndIsMissingFalseAndActiveTrueAndTest(workId, subject, 0);
             }
             //所有任务数(查询所有有效试卷)
-            int totalCount = paperRepo.countByWorkIdAndSubjectAndIsMissingFalseAndTest(workId, subject, 0);
+            int totalCount = paperRepo.countByWorkIdAndSubjectAndIsMissingFalseAndTest(workId, subject, markSubject.getTest());
 
             BigDecimal waitTotal = BigDecimal.valueOf(totalCount).subtract(BigDecimal.valueOf(successCount));
             //进度

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

@@ -1,6 +1,8 @@
 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.SqlUtil;
 import cn.com.qmth.stmms.ms.commons.web.PageableDTO;
 import cn.com.qmth.stmms.ms.core.cache.ParamCache;
@@ -77,6 +79,9 @@ public class MarkTaskApi {
     @Autowired
     SqlUtil sqlUtil;
 
+    @Autowired
+    LockService lockService;
+
     /**
      * 评卷员的评卷任务
      *
@@ -290,14 +295,24 @@ public class MarkTaskApi {
         }
         switch (stage) {
             case LEVEL:
-                synchronized (this) {
+                try {
+                    lockService.waitlock(LockType.LEVEL, markTask.getPaper().getId());
                     markingService.levelMark(markTask, result);
+                } catch (Exception e) {
+                    throw new RuntimeException("分档异常");
+                } finally {
+                    lockService.unlock(LockType.LEVEL, markTask.getPaper().getId());
                 }
                 break;
             case SCORE:
                 Integer score = Integer.parseInt(result);
-                synchronized (this) {
+                try {
+                    lockService.waitlock(LockType.SCORE, markTask.getPaper().getId());
                     markingService.scoring(markTask, score);
+                } catch (Exception e) {
+                    throw new RuntimeException("打分异常");
+                } finally {
+                    lockService.unlock(LockType.SCORE, markTask.getPaper().getId());
                 }
                 break;
         }
@@ -330,8 +345,13 @@ public class MarkTaskApi {
             }
             switch (stage) {
                 case LEVEL:
-                    synchronized (this) {
+                    try {
+                        lockService.waitlock(LockType.LEVEL, markTask.getPaper().getId());
                         markingService.levelMark(markTask, result);
+                    } catch (Exception e) {
+                        throw new RuntimeException("分档异常");
+                    } finally {
+                        lockService.unlock(LockType.LEVEL, markTask.getPaper().getId());
                     }
                     break;
                 case SCORE:

+ 14 - 10
stmms-ms-marking/src/main/java/cn/com/qmth/stmms/ms/marking/api/PaperApi.java

@@ -139,8 +139,8 @@ public class PaperApi {
     public PageableDTO listByQuerion(@RequestParam Long workId,
                                      @RequestParam(required = false) String areaCode,
                                      @RequestParam Subject subject,
-                                     @RequestParam(required = false) Long startNumber,
-                                     @RequestParam(required = false) Long endNumber,
+                                     @RequestParam(required = false) String startNumber,
+                                     @RequestParam(required = false) String endNumber,
                                      @RequestParam(required = false) Boolean isManual,
                                      @RequestParam(required = false) Boolean missing,
                                      @RequestParam(required = false) Boolean isRelate,
@@ -164,11 +164,11 @@ public class PaperApi {
             if (subject != null) {
                 predicates.add(builder.equal(root.get("subject"), subject));
             }
-            if (startNumber != null && endNumber != null) {
+            if (!StringUtils.isEmpty(startNumber) && !StringUtils.isEmpty(endNumber)) {
                 predicates.add(builder.between(root.get("examNumber"), startNumber, endNumber));
-            } else if (startNumber != null && endNumber == null) {
+            } else if (!StringUtils.isEmpty(startNumber) && StringUtils.isEmpty(endNumber)) {
                 predicates.add(builder.equal(root.get("examNumber"), startNumber));
-            } else if (startNumber == null && endNumber != null) {
+            } else if (StringUtils.isEmpty(startNumber) && !StringUtils.isEmpty(endNumber)) {
                 predicates.add(builder.equal(root.get("examNumber"), endNumber));
             }
             if (isManual != null) {
@@ -206,7 +206,7 @@ public class PaperApi {
      * @return
      */
     @RequestMapping(method = RequestMethod.GET)
-    public PageableDTO list(@RequestParam Long questionId,
+    public PageableDTO list(@RequestParam(required = false) Long questionId,
                             @RequestParam(required = false) String level,
                             @RequestParam(required = false) Boolean isSample,
                             @RequestParam(required = false) Boolean markedLogic,
@@ -218,11 +218,13 @@ public class PaperApi {
 //        Long batchNo = paperRepo.findByQuestionId(questionId);
         Specification<Paper> specification = (root, query, builder) -> {
             List<Predicate> predicates = new ArrayList<>();
-            predicates.add(builder.equal(root.get("questionId"), questionId));
+            if(Objects.nonNull(questionId)) {
+                predicates.add(builder.equal(root.get("questionId"), questionId));
+            }
             //isScore为true时,为科组长打分详情页面数据查询条件
             if(isScore) {
                 //level为null时,查询待评数量
-                if (Objects.isNull(level)) {
+                if (StringUtils.isEmpty(level)) {
                     predicates.add(builder.isNotNull(root.get("level")));
                     predicates.add(builder.isNull(root.get("score")));
                     predicates.add(builder.isNotNull(root.get("scoreBatchNo")));
@@ -231,13 +233,15 @@ public class PaperApi {
                     predicates.add(builder.isNotNull(root.get("score")));
                 }
             } else {
-                if (Objects.isNull(level)) {
+                if (StringUtils.isEmpty(level)) {
                     predicates.add(builder.isNull(root.get("level")));
                     //查询当前批次号数据
 //                predicates.add(builder.equal(root.get("batchNo"), batchNo));
                 } else {
                     predicates.add(builder.equal(root.get("level"), level));
-                    predicates.add(builder.isNotNull(root.get("batchNo")));
+                    if(Objects.nonNull(isSample) && !isSample) {
+                        predicates.add(builder.isNotNull(root.get("batchNo")));
+                    }
                 }
             }
             if (arbi != null) {

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

@@ -89,46 +89,16 @@ public class MarkingService {
     public MarkTask levelMark(MarkTask markTask, String levelCode) {
         long start = System.currentTimeMillis();
         LOG.info("提交分档:{}", start);
-        //TODO 回评
-        //boolean isMarked = markTask.getLevel() == null;
 
         //如果已经由科组长定档,则不做处理
         Paper paper = markTask.getPaper();
         if (paper.isMarkByLeader() && Objects.nonNull(paper.getLevel())) {
             return markTask;
         }
-        /**
-         阀值判断
-
-         //控制分档比例
-         List<Level> levels = levelRepo.findByWorkId(markTask.getWorkId());
-         Level targetLevel = null;
-         for (Level l : levels) {
-         if (l.getCode().equals(levelCode)) {
-         targetLevel = l;
-         break;
-         }
-         }
-         int pt = targetLevel.getPt();
-         int count = markTaskRepo.countByWorkIdAndSubjectAndMarkerIdAndStageAndResult(markTask.getWorkId(), markTask.getSubject(), markTask.getMarkerId(), markTask.getStage(), levelCode);
-         int total = markTaskRepo.countByWorkIdAndSubjectAndMarkerIdAndStage(markTask.getWorkId(), markTask.getSubject(), markTask.getMarkerId(), markTask.getStage());
-
-         if ((count + 1.0D) / total * 1.0D > pt / 100.D) {
-         throw new RuntimeException(levelCode + "档已满,占比总阀值已达" + pt + "%。");
-         }
-         //判断考点阀值是否已满
-         int kdpt = targetLevel.getKdpt();
-         int kdcount = markTaskRepo.countByWorkIdAndSubjectAndMarkerIdAndStageAndQuestionIdAndResult(markTask.getWorkId(), markTask.getSubject(), markTask.getMarkerId(), markTask.getStage(), markTask.getQuestionId(), levelCode);
-         int kdtotal = markTaskRepo.countByWorkIdAndSubjectAndMarkerIdAndStageAndQuestionId(markTask.getWorkId(), markTask.getSubject(), markTask.getMarkerId(), markTask.getStage(), markTask.getQuestionId());
-         if ((kdcount + 1.0D) / kdtotal * 1.0D > kdpt / 100.D) {
-         throw new RuntimeException(levelCode + "档已满,考点阀值已达" + kdpt + "%。");
-         }
-         */
 
         MarkUser maker = markUserRepo.findOne(markTask.getMarkerId());
 
         List<Level> levels = levelRepo.findByWorkId(paper.getWorkId());
-//        Level level = levelRepo.findByWorkIdAndCode(markTask.getWorkId(), levelCode);
         Level level = levels.stream().filter(m->levelCode.equals(m.getCode())).findFirst().get();
 
         markTask.setResult(levelCode);