Browse Source

测试bug修复-0831-图片导出

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

+ 181 - 123
stmms-ms-collect/src/main/java/cn/com/qmth/stmms/ms/collect/api/CollectApi.java

@@ -8,10 +8,7 @@ import cn.com.qmth.stmms.ms.collect.dto.LoginDTO;
 import cn.com.qmth.stmms.ms.collect.util.OssUploadUtil;
 import cn.com.qmth.stmms.ms.commons.config.*;
 import cn.com.qmth.stmms.ms.commons.constant.SystemConstant;
-import cn.com.qmth.stmms.ms.commons.utils.CommandUtil;
-import cn.com.qmth.stmms.ms.commons.utils.FileUtil;
-import cn.com.qmth.stmms.ms.commons.utils.MD5Util;
-import cn.com.qmth.stmms.ms.commons.utils.SqlUtil;
+import cn.com.qmth.stmms.ms.commons.utils.*;
 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.*;
@@ -26,6 +23,7 @@ import net.sf.json.JSONObject;
 import org.apache.commons.codec.binary.Hex;
 import org.apache.commons.codec.digest.DigestUtils;
 import org.apache.commons.lang.StringUtils;
+import org.assertj.core.util.Compatibility;
 import org.assertj.core.util.Strings;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -45,6 +43,8 @@ import java.security.MessageDigest;
 import java.text.SimpleDateFormat;
 import java.util.List;
 import java.util.*;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.function.Consumer;
 import java.util.stream.Collectors;
@@ -107,9 +107,14 @@ public class CollectApi {
     @Autowired
     OssUploadUtil ossUploadUtil;
 
+    @Autowired
+    OssUtil ossUtil;
+
     @Autowired
     ImageServerConfig imageServerConfig;
 
+    ExecutorService executors = Executors.newFixedThreadPool(10);
+
     @RequestMapping("user/login")
     public LoginDTO login(@RequestParam String loginname, @RequestParam String password) throws Exception {
         LoginDTO loginDTO = null;
@@ -788,10 +793,6 @@ public class CollectApi {
      * 分数图片导出
      *
      * @param imageType
-     * @param areaId
-     * @param school
-     * @param examRoom
-     * @param subject
      * @param nameRule   1:考号+姓名,2:流水号
      * @param startScore
      * @param endScore
@@ -799,42 +800,38 @@ public class CollectApi {
      * @throws IOException
      */
     @RequestMapping(value = "file/image/exportScorePictures", method = {RequestMethod.GET})
-    public String exportScorePictures(@RequestParam(defaultValue = "分数图片") String exportType,
-                                      @RequestParam Long workId,
-                                      @RequestParam String imageType,
-                                      @RequestParam(required = false) Long areaId,
-                                      @RequestParam(required = false) String school,
-                                      @RequestParam(required = false) String examRoom,
-                                      @RequestParam String subject,
-                                      @RequestParam String nameRule,
-                                      @RequestParam(required = false) Integer startScore,
-                                      @RequestParam(required = false) Integer endScore) throws IOException {
+    public void exportScorePictures(@RequestParam(defaultValue = "score-images") String exportType,
+                                    @RequestParam Long workId,
+                                    @RequestParam String imageType,
+                                    @RequestParam String isWatermark,
+                                    @RequestParam String isResume,
+                                    @RequestParam String nameRule,
+                                    @RequestParam(required = false) Integer startScore,
+                                    @RequestParam(required = false) Integer endScore,
+                                    @RequestParam String savePath) throws Exception {
+        String[] strings = {"{{workId}}","{{areaCode}}","{{school}}","{{subject}}"};
+        List<String> stringList = Arrays.asList(strings);
+        String[] savePaths = savePath.split("\\\\");
+        for (String string : savePaths) {
+            if(StringUtils.isEmpty(string)){
+                continue;
+            }
+            if(!stringList.contains(string)){
+                throw new Exception("文档路径格式不对");
+            }
+        }
+
         if (StringUtils.isBlank(imageType)) {
             throw new RuntimeException("请选择图片类型");
         }
-        if (StringUtils.isBlank(subject)) {
-            throw new RuntimeException("请选择科目");
-        }
         if (StringUtils.isBlank(nameRule)) {
             throw new RuntimeException("请选择命名规则");
         }
 
-        InputStream inputStream = null;
-        OutputStream outputStream = null;
-        int count = 0;
         try {
             //首先根据workId和阶段去查所有试卷
             StringBuffer sql = new StringBuffer();
-            sql.append("SELECT s.id studentId,s.name studentName, p.work_id workId, p.subject, p.area_code areaCode, p.exam_number examNumber, 0+cast(p.score as char) as score FROM paper p LEFT JOIN student s ON p.work_id = s.work_id AND p.exam_number = s.exam_number WHERE p.score is not null and p.work_id = ").append(workId).append(" AND p.subject = '").append(subject).append("'");
-            if (areaId != null) {
-                sql.append(" and p.area_code = ").append(areaId);
-            }
-            if (StringUtils.isNotBlank(school)) {
-                sql.append(" and s.school = '").append(school).append("'");
-            }
-            if (StringUtils.isNotBlank(examRoom)) {
-                sql.append(" and s.exam_room = '").append(examRoom).append("'");
-            }
+            sql.append("SELECT s.id studentId,s.name studentName,s.school, p.work_id workId, p.subject, p.area_code areaCode, p.exam_number examNumber, 0+cast(p.score as char) as score FROM paper p LEFT JOIN student s ON p.work_id = s.work_id AND p.exam_number = s.exam_number WHERE p.score is not null and p.work_id = ").append(workId);
             if (startScore != null && endScore != null) {
                 sql.append(" and p.score >= ").append(startScore);
                 sql.append(" and p.score <= ").append(endScore);
@@ -848,101 +845,156 @@ public class CollectApi {
             List<Map<String, Object>> paperList = jdbcTemplate.queryForList(sql.toString());
             AtomicInteger atomicInteger = new AtomicInteger(0);
             for (Map map : paperList) {
-                Long studentId = Long.valueOf(map.get("studentId").toString());
-                String studentName = map.get("studentName").toString();
-                String subject0 = map.get("subject").toString();
-                Subject subject1 = Subject.valueOf(subject0);
-                String areaCode = map.get("areaCode").toString();
-                String examNumber = map.get("examNumber").toString();
-                Double score = Double.parseDouble(map.get("score").toString());
-
-                String fileName = examNumber;
-                //图片加密、命名规则为随机码的,都是需要md5
-                if (ParamCache.paramMap.get(workId).getNameRule() == 1 || ParamCache.paramMap.get(workId).getImageEncrypt() == 1) {
-                    fileName = MD5Util.getImageRuleMd5(workId, subject1.ordinal(), areaCode, examNumber, studentId);
-                }
-                String path = systemConfig.getSheetDir() + File.separator + workId + File.separator + subject1
-                        + File.separator + areaCode;
-                File file = new File(path + File.separator + fileName + ".jpg");
-                //组装导出目录
-                StringJoiner expSj = new StringJoiner(File.separator);
-                expSj.add(systemConfig.getLocalhostPath()).add("图片导出").add(exportType).add(String.valueOf(workId)).add(subject);
-                if (areaId != null) {
-                    expSj.add(String.valueOf(areaId));
-                }
-                if (StringUtils.isNotBlank(school)) {
-                    expSj.add(school);
-                }
-                if (StringUtils.isNotBlank(examRoom)) {
-                    expSj.add(examRoom);
-                }
-                //原图或者水印图
-                if (Objects.equals("1", imageType)) {
-                    expSj.add("sheet");
-                } else if (Objects.equals("2", imageType)) {
-                    expSj.add("watermark");
-                }
-                //分数
-                if (startScore != null && endScore != null) {
-                    expSj.add(startScore + "-" + endScore);
-                } else if (startScore != null && endScore == null) {
-                    expSj.add(startScore.toString());
-                } else if (startScore == null && endScore != null) {
-                    expSj.add(endScore.toString());
-                }
-                File out = new File(expSj.toString());
-                if (!out.exists()) {
-                    out.mkdirs();
-                }
-                //输出命名
-                String outFileName;
-                if (Objects.equals("1", nameRule)) {
-                    StringJoiner sj = new StringJoiner("-");
-                    sj.add(examNumber).add(studentName);
-                    outFileName = sj.toString();
-                } else if (Objects.equals("2", nameRule)) {
-                    outFileName = String.valueOf(atomicInteger.incrementAndGet());
-                } else {
-                    throw new RuntimeException("命名参数有误");
-                }
-                File expFile = new File(expSj.toString() + File.separator + outFileName + ".jpg");
-                //水印图片
-                if (Objects.equals("1", imageType)) {
-                    //读取指定路径下面的文件
-                    inputStream = new FileInputStream(file);
-                    outputStream = new FileOutputStream(expFile);
-                    if (ParamCache.paramMap.get(workId).getImageEncrypt() == 1) {
-                        outputStream = SystemConstant.writeStream(inputStream, outputStream);
-                    } else {
-                        outputStream = SystemConstant.writeStreamFomal(inputStream, outputStream);
+                LOGGER.info("==========================导出分数图片开始,共{}数据================================", paperList.size());
+                executors.submit(() -> {
+                    InputStream inputStream = null;
+                    OutputStream outputStream = null;
+                    long start = System.currentTimeMillis();
+                    try {
+                        Long studentId = Long.valueOf(map.get("studentId").toString());
+                        String studentName = map.get("studentName").toString();
+                        String subject = map.get("subject").toString();
+                        Subject subject1 = Subject.valueOf(subject);
+                        String areaCode = map.get("areaCode").toString();
+                        String school = String.valueOf(map.get("school"));
+                        String examNumber = map.get("examNumber").toString();
+                        Double score = Double.parseDouble(map.get("score").toString());
+
+                        String fileName = examNumber;
+                        //图片加密、命名规则为随机码的,都是需要md5
+                        if (ParamCache.paramMap.get(workId).getNameRule() == 1 || ParamCache.paramMap.get(workId).getImageEncrypt() == 1) {
+                            fileName = MD5Util.getImageRuleMd5(workId, subject1.ordinal(), areaCode, examNumber, studentId);
+                        }
+
+                        //组装导出目录
+                        StringJoiner expSj = new StringJoiner(File.separator);
+                        expSj.add(systemConfig.getLocalhostPath()).add("image-export").add(exportType);
+                        //原图或者裁切图
+                        String imageTypeStr = Objects.equals("1", imageType) ? "sheet" : Objects.equals("2", imageType) ? "images" : "default";
+                        //是否水印
+                        String waterTypeStr = Objects.equals("1", isWatermark) ? "yes" : Objects.equals("0", isWatermark) ? "no" : "default";
+                        expSj.add(imageTypeStr.concat("-").concat(waterTypeStr));
+                        LOGGER.info("{},【{}】开始导出,参数:图片类型:{},是否有水印:{},是否续传:{},命名规则:{}",examNumber, studentName,imageTypeStr, waterTypeStr, isResume == "1"?"是":"否", nameRule == "1"?"考号+姓名":"流水号");
+                        //是否加水印
+                        for (String spath : savePaths) {
+                            if (stringPath("workId").equals(spath)) {
+                                expSj.add(String.valueOf(workId));
+                            }
+                            if (stringPath("areaCode").equals(spath)) {
+                                expSj.add(areaCode);
+                            }
+                            if (stringPath("school").equals(spath)) {
+                                expSj.add(school);
+                            }
+                            if (stringPath("subject").equals(spath)) {
+                                expSj.add(subject);
+                            }
+                        }
+                        File out = new File(expSj.toString());
+                        if (!out.exists()) {
+                            out.mkdirs();
+                        }
+                        //输出命名
+                        String outFileName;
+                        if (Objects.equals("1", nameRule)) {
+                            StringJoiner sj = new StringJoiner("-");
+                            sj.add(examNumber).add(studentName);
+                            outFileName = sj.toString();
+                        } else if (Objects.equals("2", nameRule)) {
+                            outFileName = String.valueOf(atomicInteger.incrementAndGet());
+                        } else {
+                            throw new RuntimeException("命名参数有误");
+                        }
+
+                        String path;
+                        String dir;
+                        if (Objects.equals("1", imageType)) {
+                            path = systemConfig.getSheetDir() + File.separator + workId + File.separator + subject1
+                                    + File.separator + areaCode;
+                            dir = systemConfig.getSheetDir();
+                        } else if (Objects.equals("2", imageType)) {
+                            path = systemConfig.getImageDir() + File.separator + workId + File.separator + subject1
+                                    + File.separator + areaCode;
+                            dir = systemConfig.getImageDir();
+                        } else {
+                            throw new RuntimeException("图片类型有误");
+                        }
+
+                        String outFile = expSj.toString() + File.separator + outFileName + ".jpg";
+                        if (imageServerConfig.isAliyunOss()) {
+                            //是否断点续传
+                            if (Objects.equals("1", isResume) && new File(outFile).exists()) {
+                                return;
+                            }
+                            StringJoiner ossSavePath = new StringJoiner("/").add(imageServerConfig.getDir()).add(dir.replace("\\", "/")).add(String.valueOf(workId)).add(subject).add(areaCode);
+                            String saveFileName = fileName + ".jpg";
+                            String saveFile = ossSavePath.toString().concat("/").concat(saveFileName);
+                            if (Objects.equals("0", isWatermark)) {
+                                ossUtil.ossDownload(saveFile, outFile);
+                            }
+                            //下载临时原图
+                            if (Objects.equals("1", isWatermark)) {
+                                String outSheetFile = expSj.toString() + File.separator + outFileName + "_" + start + ".jpg";
+                                File sheetFileTemp = ossUtil.ossDownload(saveFile, outSheetFile);
+                                File expFile = new File(outFile);
+                                //生成分数水印图片
+                                BufferedImage watermarkImage = createWaterImage(score.intValue() + "分");
+                                Thumbnails.of(sheetFileTemp).scale(0.8).watermark(Positions.BOTTOM_CENTER, watermarkImage, 1f).toFile(expFile);
+                                sheetFileTemp.delete();
+                            }
+                        } else {
+                            File file = new File(path + File.separator + fileName + ".jpg");
+                            File expFile = new File(outFile);
+                            //是否断点续传
+                            if (Objects.equals("1", isResume) && expFile.exists()) {
+                                return;
+                            }
+                            if (Objects.equals("0", isWatermark)) {
+                                //读取指定路径下面的文件
+                                inputStream = new FileInputStream(file);
+                                outputStream = new FileOutputStream(expFile);
+                                if (ParamCache.paramMap.get(workId).getImageEncrypt() == 1) {
+                                    outputStream = SystemConstant.writeStream(inputStream, outputStream);
+                                } else {
+                                    outputStream = SystemConstant.writeStreamFomal(inputStream, outputStream);
+                                }
+                                inputStream.close();
+                                outputStream.flush();
+                                outputStream.close();
+                            }
+                            if (Objects.equals("1", isWatermark)) {
+                                //生成分数水印图片
+                                BufferedImage watermarkImage = createWaterImage(score.intValue() + "分");
+                                Thumbnails.of(file).scale(0.8).watermark(Positions.BOTTOM_CENTER, watermarkImage, 1f).toFile(expFile);
+                            }
+                        }
+                        long end = System.currentTimeMillis();
+                        LOGGER.info("{},【{}】结束导出,总耗时:{}秒", examNumber, studentName, (end-start)/1000);
+                    } catch (Exception e) {
+                        LOGGER.info("{},【{}】导出失败");
+                    } finally {
+                        try {
+                            //强制将缓存区的数据进行输出
+                            if (Objects.nonNull(outputStream)) {
+                                outputStream.flush();
+                                //关流
+                                outputStream.close();
+                            }
+                            if (Objects.nonNull(inputStream)) {
+                                inputStream.close();
+                            }
+
+                        } catch (Exception e) {
+
+                        }
                     }
-                    inputStream.close();
-                    outputStream.flush();
-                    outputStream.close();
-                }
-                if (Objects.equals("2", imageType)) {
-                    //生成分数水印图片
-                    BufferedImage watermarkImage = createWaterImage(score.intValue() + "分");
-                    Thumbnails.of(file).scale(0.8).watermark(Positions.BOTTOM_CENTER, watermarkImage, 1f).toFile(expFile);
-                }
-                count++;
+                });
+                LOGGER.info("==========================导出分数图片结束================================");
 
-                LOGGER.info("studentId:{},subjdect:{},md5:{}", studentId, subject1, fileName);
             }
         } catch (Exception e) {
             e.printStackTrace();
-        } finally {
-            //强制将缓存区的数据进行输出
-            if (Objects.nonNull(outputStream)) {
-                outputStream.flush();
-                //关流
-                outputStream.close();
-            }
-            if (Objects.nonNull(inputStream)) {
-                inputStream.close();
-            }
         }
-        return "导出照片成功,共导出了" + count + "张照片";
     }
 
 
@@ -1092,6 +1144,12 @@ public class CollectApi {
         }
     }
 
+    private String stringPath(String s) {
+        StringJoiner stringJoiner = new StringJoiner("", "{{", "}}");
+        stringJoiner.add(s);
+        return stringJoiner.toString();
+    }
+
     public static void main(String[] args) throws IOException {
         String msg1 = "90分";
         BufferedImage bi = createWaterImage(msg1);

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

@@ -362,5 +362,7 @@ public interface PaperRepo extends JpaRepository<Paper, Long>, JpaSpecificationE
     @Query("select max(p.scoreBatchNo) from Paper p where p.workId = ?1")
     Long findMaxScoreBatchNoByWorkId(Long workId);
 
+    List<Paper> findByWorkIdAndQuestionIdAndSubjectAndLevelAndIsMissingFalseAndActiveTrueAndScoreBatchNoIsNull(Long workId, Long questionId0, Subject subject, String code, Sort sort);
+
 //    List<Paper> findByWorkIdAndSubjectAndInspectRange(Long workId, Subject subject, Long inspectRange);
 }

+ 10 - 0
stmms-ms-marking/src/main/java/cn/com/qmth/stmms/ms/marking/assembler/MarkTaskAssembler.java

@@ -5,11 +5,13 @@ import cn.com.qmth.stmms.ms.commons.config.SystemConfig;
 import cn.com.qmth.stmms.ms.commons.constant.SystemConstant;
 import cn.com.qmth.stmms.ms.commons.utils.MD5Util;
 import cn.com.qmth.stmms.ms.core.cache.ParamCache;
+import cn.com.qmth.stmms.ms.core.domain.MarkLogOperType;
 import cn.com.qmth.stmms.ms.core.domain.MarkStage;
 import cn.com.qmth.stmms.ms.core.domain.Paper;
 import cn.com.qmth.stmms.ms.core.domain.Student;
 import cn.com.qmth.stmms.ms.core.domain.enums.TrialEnum;
 import cn.com.qmth.stmms.ms.core.domain.task.MarkTask;
+import cn.com.qmth.stmms.ms.core.repository.MarkLogRepo;
 import cn.com.qmth.stmms.ms.core.repository.StudentRepo;
 import cn.com.qmth.stmms.ms.marking.dto.MarkTaskDTO;
 import org.apache.commons.codec.digest.DigestUtils;
@@ -33,6 +35,9 @@ public class MarkTaskAssembler {
     @Autowired
     StudentRepo studentRepo;
 
+    @Autowired
+    MarkLogRepo markLogRepo;
+
     public MarkTaskDTO toDTO(MarkTask markTask) {
 
         MarkTaskDTO markTaskDTO = null;
@@ -84,6 +89,11 @@ public class MarkTaskAssembler {
             }
             markTaskDTO.setShift(paper.isShift());
             markTaskDTO.setShiftScore(paper.isShiftScore());
+
+            markTaskDTO.setIsRejectedByLeader(paper.isRejectedByLeader() == null ? false : paper.isRejectedByLeader());
+            //打回总次数
+            int rejectedCount = markLogRepo.countByWorkIdAndPaperIdAndOperType(paper.getWorkId(), paper.getId(), MarkLogOperType.SYSTEM_CALLBACK_LEVEl.getId(), MarkLogOperType.CALLBACK_LEVEl.getId());
+            markTaskDTO.setRejectedCount(rejectedCount);
         }
         return markTaskDTO;
     }

+ 20 - 0
stmms-ms-marking/src/main/java/cn/com/qmth/stmms/ms/marking/dto/MarkTaskDTO.java

@@ -33,6 +33,10 @@ public class MarkTaskDTO implements Serializable{
     private boolean displayNumber;
     private boolean shift;
     private boolean shiftScore;
+    //是否科组长打回
+    private Boolean isRejectedByLeader;
+    //打回总次数
+    private Integer rejectedCount;
 
     public Integer getRandomSeq() {
         return randomSeq;
@@ -221,4 +225,20 @@ public class MarkTaskDTO implements Serializable{
     public void setShiftScore(boolean shiftScore) {
         this.shiftScore = shiftScore;
     }
+
+    public Boolean getIsRejectedByLeader() {
+        return isRejectedByLeader;
+    }
+
+    public void setIsRejectedByLeader(Boolean rejectedByLeader) {
+        isRejectedByLeader = rejectedByLeader;
+    }
+
+    public Integer getRejectedCount() {
+        return rejectedCount;
+    }
+
+    public void setRejectedCount(Integer rejectedCount) {
+        this.rejectedCount = rejectedCount;
+    }
 }

+ 11 - 2
stmms-ms-marking/src/main/java/cn/com/qmth/stmms/ms/marking/service/StageControlService.java

@@ -415,9 +415,18 @@ public class StageControlService {
             }
         } else {
             Long questionId0 = Long.valueOf(questionId.toString());
-            papers = paperRepo.findByWorkIdAndQuestionIdAndSubjectAndIsMissingFalseAndActiveTrueAndScoreBatchNoIsNull(workId, questionId0, subject, sort);
+//            papers = paperRepo.findByWorkIdAndQuestionIdAndSubjectAndIsMissingFalseAndActiveTrueAndScoreBatchNoIsNull(workId, questionId0, subject, sort);
+            papers = new ArrayList<>();
+            for (TaskPublishSetting taskPublishSetting : taskList) {
+                if(taskPublishSetting.getTaskCount() == 0){
+                    continue;
+                }
+                List<Paper> paperList = paperRepo.findByWorkIdAndQuestionIdAndSubjectAndLevelAndIsMissingFalseAndActiveTrueAndScoreBatchNoIsNull(workId, questionId0, subject, taskPublishSetting.getCode(),  sort);
+                List<Paper> subPaperList = paperList.subList(0, taskPublishSetting.getTaskCount());
+                papers.addAll(subPaperList);
+            }
         }
-        papers = papers.subList(0, totalTaskCount);
+//        papers = papers.subList(0, totalTaskCount);
 
         assignTaskService.assignForGrouping(papers, markerGroups, markSubject, taskList);