Răsfoiți Sursa

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	doc/table.docx
#	doc/化学中考专项诊断.docx
zengxj 5 ani în urmă
părinte
comite
c397450399
47 a modificat fișierele cu 1041 adăugiri și 280 ștergeri
  1. 4 4
      deploy.sh
  2. BIN
      doc/sub.docx
  3. BIN
      doc/table.docx
  4. BIN
      doc/topic_table.docx
  5. BIN
      doc/中考专项诊断考试说明.pdf
  6. BIN
      doc/化学中考专项诊断.docx
  7. BIN
      doc/数学中考专项诊断.docx
  8. BIN
      doc/数学中考专项诊断思维过程.xlsx
  9. BIN
      doc/数学中考专项诊断报告.pdf
  10. BIN
      doc/数学中考专项诊断知识点列表.xlsx
  11. BIN
      doc/物理中考专项诊断.docx
  12. BIN
      doc/物理中考专项诊断知识点列表.xlsx
  13. 14 1
      src/main/java/com/yaoxiang/diagnosis/config/Constants.java
  14. 1 1
      src/main/java/com/yaoxiang/diagnosis/config/MinioConfig.java
  15. 20 4
      src/main/java/com/yaoxiang/diagnosis/controller/ExcelController.java
  16. 19 4
      src/main/java/com/yaoxiang/diagnosis/controller/PaperController.java
  17. 10 8
      src/main/java/com/yaoxiang/diagnosis/controller/QuestionController.java
  18. 8 7
      src/main/java/com/yaoxiang/diagnosis/controller/ReportController.java
  19. 20 6
      src/main/java/com/yaoxiang/diagnosis/controller/SpecialReportController.java
  20. 5 0
      src/main/java/com/yaoxiang/diagnosis/controller/TestController.java
  21. 2 6
      src/main/java/com/yaoxiang/diagnosis/controller/UserInfoController.java
  22. 1 1
      src/main/java/com/yaoxiang/diagnosis/dao/PaperResultRepo.java
  23. 14 0
      src/main/java/com/yaoxiang/diagnosis/dao/SpecialMindRepo.java
  24. 12 0
      src/main/java/com/yaoxiang/diagnosis/entity/Authority.java
  25. 9 0
      src/main/java/com/yaoxiang/diagnosis/entity/Role.java
  26. 7 5
      src/main/java/com/yaoxiang/diagnosis/entity/SpecialKnowledge.java
  27. 121 0
      src/main/java/com/yaoxiang/diagnosis/entity/SpecialMind.java
  28. 8 0
      src/main/java/com/yaoxiang/diagnosis/model/SpecialKnowledgeVo.java
  29. 59 0
      src/main/java/com/yaoxiang/diagnosis/model/SpecialMindVo.java
  30. 7 0
      src/main/java/com/yaoxiang/diagnosis/service/CommitService.java
  31. 4 2
      src/main/java/com/yaoxiang/diagnosis/service/OptionService.java
  32. 7 5
      src/main/java/com/yaoxiang/diagnosis/service/PaperResultService.java
  33. 112 100
      src/main/java/com/yaoxiang/diagnosis/service/PaperService.java
  34. 14 10
      src/main/java/com/yaoxiang/diagnosis/service/QuestionService.java
  35. 140 5
      src/main/java/com/yaoxiang/diagnosis/service/SpecialKnowledgeService.java
  36. 29 0
      src/main/java/com/yaoxiang/diagnosis/service/SpecialMindService.java
  37. 150 19
      src/main/java/com/yaoxiang/diagnosis/service/SpecialReportService.java
  38. 67 3
      src/main/java/com/yaoxiang/diagnosis/word/KnowledgeUtil.java
  39. 58 34
      src/main/java/com/yaoxiang/diagnosis/word/WordService.java
  40. 0 15
      src/main/resources/application-cloud.properties
  41. 0 9
      src/main/resources/application-dev.properties
  42. 0 8
      src/main/resources/application-docker.properties
  43. 0 11
      src/main/resources/application-prod.properties
  44. 0 4
      src/main/resources/application.properties
  45. 18 0
      src/test/java/com/yaoxiang/diagnosis/service/StringTest.java
  46. 79 1
      src/test/java/com/yaoxiang/diagnosis/service/UploadTest.java
  47. 22 7
      src/test/java/com/yaoxiang/diagnosis/service/WordServiceTest.java

+ 4 - 4
deploy.sh

@@ -2,8 +2,8 @@ date=`date +%Y%m%d_%H%M%S`
 cd /home/jenkins/workspace/diagnosis
 docker build -t feick/diagnosis:$date .
 echo "current tag is $date"
-#sed -i "s/\${date}/$(echo $date)/g" deployment.yaml
-#kubectl apply -f deployment.yaml
-#sed -i "s/\${date}/$(echo $date)/g" deployment-prod.yaml
-#kubectl apply -f deployment-prod.yaml
+sed -i "s/\${date}/$(echo $date)/g" deployment.yaml
+kubectl apply -f deployment.yaml
+sed -i "s/\${date}/$(echo $date)/g" deployment-prod.yaml
+kubectl apply -f deployment-prod.yaml
 echo "build finish."

BIN
doc/sub.docx


BIN
doc/table.docx


BIN
doc/topic_table.docx


BIN
doc/中考专项诊断考试说明.pdf


BIN
doc/化学中考专项诊断.docx


BIN
doc/数学中考专项诊断.docx


BIN
doc/数学中考专项诊断思维过程.xlsx


BIN
doc/数学中考专项诊断报告.pdf


BIN
doc/数学中考专项诊断知识点列表.xlsx


BIN
doc/物理中考专项诊断.docx


BIN
doc/物理中考专项诊断知识点列表.xlsx


+ 14 - 1
src/main/java/com/yaoxiang/diagnosis/config/Constants.java

@@ -3,7 +3,9 @@ package com.yaoxiang.diagnosis.config;
 
 import org.springframework.security.core.authority.SimpleGrantedAuthority;
 
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 public class Constants {
@@ -114,5 +116,16 @@ public class Constants {
     public static final int PAPER_STATUS_INVALIDATE = 2;
 
     public static final String SPECIAL_KNOWLEDGE_MASTER = "掌握";
-    public static final String SPECIAL_KNOWLEDGE_UNMASTER  = "未掌握";
+    public static final String SPECIAL_KNOWLEDGE_UNMASTER = "未掌握";
+
+    public static final String SPECIAL_MASTER_STATUS_KNOW = "认识";
+    public static final String SPECIAL_MASTER_STATUS_UNDERSTAND = "理解";
+    public static final String SPECIAL_MASTER_STATUS_USAGE = "应用";
+
+    public static final List<String> SPECIAL_MASTER_STATUS = new ArrayList<String>() {{
+        add(SPECIAL_MASTER_STATUS_KNOW);
+        add(SPECIAL_MASTER_STATUS_UNDERSTAND);
+        add(SPECIAL_MASTER_STATUS_USAGE);
+    }};
+
 }

+ 1 - 1
src/main/java/com/yaoxiang/diagnosis/config/MinioConfig.java

@@ -65,7 +65,7 @@ public class MinioConfig {
 
     @Bean
     MinioClient minioClient(MinioProperties properties) throws Exception {
-        logger.info("init MinioClient,url is {} , accessKey is {} , secretKey is {}", properties.getUrl(), properties.getAccessKey(), properties.getSecretKey());
+        logger.info("init MinioClient,url is {} , accessKey is {} , secretKey is ***", properties.getUrl(), properties.getAccessKey());
         MinioClient client = null;
         if (properties.isSecure()) {
              client = new MinioClient(properties.getUrl(), properties.getSecurePort(), properties.getAccessKey(), properties.getSecretKey(), null, true, okHttpClient());

+ 20 - 4
src/main/java/com/yaoxiang/diagnosis/controller/ExcelController.java

@@ -2,12 +2,14 @@ package com.yaoxiang.diagnosis.controller;
 
 import com.yaoxiang.diagnosis.config.Constants;
 import com.yaoxiang.diagnosis.entity.SpecialKnowledge;
+import com.yaoxiang.diagnosis.entity.SpecialMind;
 import com.yaoxiang.diagnosis.entity.SubjectKnowledge;
 import com.yaoxiang.diagnosis.model.MatterVo;
 import com.yaoxiang.diagnosis.model.Result;
 import com.yaoxiang.diagnosis.service.KnowledgeService;
 import com.yaoxiang.diagnosis.service.MatterService;
 import com.yaoxiang.diagnosis.service.SpecialKnowledgeService;
+import com.yaoxiang.diagnosis.service.SpecialMindService;
 import com.yaoxiang.diagnosis.word.KnowledgeUtil;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
@@ -28,6 +30,8 @@ public class ExcelController {
     private SpecialKnowledgeService specialKnowledgeService;
     @Resource
     private MatterService matterService;
+    @Resource
+    private SpecialMindService specialMindService;
 
     @PostMapping("/uploadAll")
     public Result uploadAll() {
@@ -57,7 +61,7 @@ public class ExcelController {
     }
 
     @PostMapping("/uploadSpecial")
-    @ApiOperation("上传专项诊断知识点")
+    @ApiOperation("上传小学专项诊断知识点")
     public Result uploadSpecial(@RequestParam(defaultValue = "2") Long subjectId,
                                 @RequestParam(defaultValue = "6Y") String grade,
                                 @RequestBody MultipartFile file) throws Exception {
@@ -67,15 +71,27 @@ public class ExcelController {
         return new Result(result);
     }
 
-    @PostMapping("/uploadSpecialChem")
-    @ApiOperation("上传专项诊断知识点")
+    @PostMapping("/uploadSpecialMiddle")
+    @ApiOperation("上传中考专项诊断知识点")
     public Result uploadSpecialChem(@RequestParam(defaultValue = "4") Long subjectId,
                                     @RequestParam(defaultValue = "9Y") String grade,
                                     @RequestParam(defaultValue = "5") Long pid,
                                     @RequestBody MultipartFile file) throws Exception {
         byte[] data = file.getBytes();
-        List<SpecialKnowledge> list = KnowledgeUtil.importSpecialKnowledge2(subjectId, grade, data,pid);
+        List<SpecialKnowledge> list = KnowledgeUtil.importSpecialKnowledge2(subjectId, grade, data, pid);
         specialKnowledgeService.add(list);
         return Result.ok(list);
     }
+
+    @PostMapping("/uploadSpecialMind")
+    @ApiOperation("上传中考专项诊断思维过程")
+    public Result uploadSpecialMind(@RequestParam(defaultValue = "2") Long subjectId,
+                                    @RequestParam(defaultValue = "9Y") String grade,
+                                    @RequestParam(defaultValue = "5") Long pid,
+                                    @RequestBody MultipartFile file) throws Exception {
+        byte[] data = file.getBytes();
+        List<SpecialMind> list = KnowledgeUtil.importSpecialMind(subjectId, grade, data, pid);
+        specialMindService.add(list);
+        return Result.ok(list);
+    }
 }

+ 19 - 4
src/main/java/com/yaoxiang/diagnosis/controller/PaperController.java

@@ -65,12 +65,27 @@ public class PaperController {
     }
 
     //    @PreAuthorize("hasRole('ROLE_ADMIN')")
-    @ApiOperation(value = "编辑试卷")
-    @RequestMapping(value = "/update", method = RequestMethod.POST)
-    public Result update(@RequestBody Paper paper) {
+//    @ApiOperation(value = "编辑试卷")
+//    @RequestMapping(value = "/update", method = RequestMethod.POST)
+//    public Result update(@RequestBody Paper paper) {
+//        return paperService.update(paper);
+//    }
+
+    @ApiOperation("更新试卷参数")
+    @PostMapping("/updateParams")
+    public Result updateParams(Long pid, String name, String grade, String sectionNums,
+                               String sectionDurations, String sectionRests, String remark) {
+        Paper paper = paperService.getOnePaper(pid);
+        paper.setName(name);
+        paper.setGrade(grade);
+        paper.setSectionNums(sectionNums);
+        paper.setSectionDurations(sectionDurations);
+        paper.setSectionRests(sectionRests);
+        paper.setRemark(remark);
         return paperService.update(paper);
     }
 
+
     @PostMapping("/invalidate")
     @ApiOperation(value = "作废试卷")
     public Result invalidate(Long pid) {
@@ -80,7 +95,7 @@ public class PaperController {
     }
 
     //    @PreAuthorize("hasRole('ROLE_ADMIN')")
-    @ApiOperation(value = "删除试卷")
+    @ApiOperation(value = "删除试卷 假删除")
     @RequestMapping(value = "/delete", method = RequestMethod.POST)
     public void delete(@RequestParam Long id) {
         paperService.delete(id);

+ 10 - 8
src/main/java/com/yaoxiang/diagnosis/controller/QuestionController.java

@@ -31,25 +31,25 @@ public class QuestionController {
     @Resource
     private ExecutorService executorService;
 
-    @ApiOperation(value = "增加 题")
+    @ApiOperation(value = "增加 题")
     @RequestMapping(value = "/addQuestionForPaper", method = RequestMethod.POST)
     public Result addQuestionForPaper(@RequestBody Question question) {
         return questionService.addQuestion(question);
     }
 
-    @ApiOperation(value = "修改 题")
+    @ApiOperation(value = "修改 题")
     @RequestMapping(value = "/updateQuestionForPaper", method = RequestMethod.POST)
     public Result updateQuestionForPaper(@RequestBody Question question) {
         return questionService.updateQuestion(question);
     }
 
-    @ApiOperation(value = "查询 题  ")
+    @ApiOperation(value = "查询 题  ")
     @RequestMapping(value = "/getQuestion", method = RequestMethod.GET)
     public Question getQuestion(@RequestParam Long id) {
         return questionService.getQuestion(id);
     }
 
-    @ApiOperation(value = "删除 题  ")
+    @ApiOperation(value = "删除 题  ")
     @RequestMapping(value = "/deleteQuestion", method = RequestMethod.GET)
     public void deleteQuestion(@RequestParam Long id) {
         questionService.deleteQuestion(id);
@@ -75,9 +75,11 @@ public class QuestionController {
 //                e.printStackTrace();
 //            }
 //        });
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        FileCopyUtils.copy(file.getInputStream(), baos);
-        byte[] data = baos.toByteArray();
-        return questionService.parseQuestion(pid, section, number, data);
+//        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+//        FileCopyUtils.copy(file.getInputStream(), baos);
+//        byte[] data = file.getBytes();
+        //暂时不上传题库
+        return Result.fail("暂时不支持只上传题目");
+//        return questionService.parseQuestion(pid, section, number, data);
     }
 }

+ 8 - 7
src/main/java/com/yaoxiang/diagnosis/controller/ReportController.java

@@ -18,6 +18,7 @@ import org.springframework.web.bind.annotation.RestController;
 
 import javax.annotation.Resource;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 @Api(tags = "报告管理")
@@ -58,18 +59,18 @@ public class ReportController {
         if (paper == null) {
             return Result.fail("未找到试卷");
         }
-        PaperResult paperResult = paperResultService.findByPidAndUid(pid, uid);
-        if (paperResult == null) {
+        List<PaperResult> paperResults = paperResultService.findByPidAndUid(pid, uid);
+        if (paperResults == null) {
             logger.info("正在生成结果");
-            paperResult = (PaperResult) paperResultService.parseResult(pid, uid).getT();
+            paperResults = (List<PaperResult>) paperResultService.parseResult(pid, uid).getT();
         }
         Map<String, Object> result = new HashMap<>();
         result.put("name", info.getName());
         result.put("grade", paper.getGrade());
         result.put("subject", subjectService.get(paper.getSubjectId()).getName());
-        result.put("diagnosisTime", paperResult.getCreatetime());
-        result.put("code", paperResult.getCode());
-        result.put("paperResultId", paperResult.getId());
+        result.put("diagnosisTime", paperResults.get(0).getCreatetime());
+        result.put("code", paperResults.get(0).getCode());
+        result.put("paperResultId", paperResults.get(0).getId());
         return Result.ok(result);
 
     }
@@ -90,7 +91,7 @@ public class ReportController {
     @GetMapping("useTime")
     @ApiOperation("获取作答时间及平均作答时间")
     public Result useTime(Long pid, Long uid) {
-        PaperResult paperResult = paperResultService.findByPidAndUid(pid, uid);
+        List<PaperResult> paperResult = paperResultService.findByPidAndUid(pid, uid);
         if (paperResult == null) {
             return new Result<>(false, "未找到诊断结果");
         }

+ 20 - 6
src/main/java/com/yaoxiang/diagnosis/controller/SpecialReportController.java

@@ -1,15 +1,20 @@
 package com.yaoxiang.diagnosis.controller;
 
+import com.yaoxiang.diagnosis.entity.SpecialMind;
 import com.yaoxiang.diagnosis.entity.SpecialResult;
+import com.yaoxiang.diagnosis.model.SpecialMindVo;
 import com.yaoxiang.diagnosis.service.SpecialReportService;
 import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
 import javax.annotation.Resource;
+import java.util.Comparator;
+import java.util.List;
 
-@Api(tags="专项诊断报告")
+@Api(tags = "专项诊断报告")
 @RestController
 @RequestMapping("/specialReport")
 public class SpecialReportController {
@@ -18,12 +23,21 @@ public class SpecialReportController {
     private SpecialReportService specialReportService;
 
     @GetMapping("/generate")
-    public SpecialResult generate(Long pid,Long uid){
-        return specialReportService.generate2(pid,uid);
+    @ApiOperation("生成专项诊断第一页知识点报告")
+    public SpecialResult generate(Long pid, Long uid) {
+        return specialReportService.generate2(pid, uid);
     }
 
-    @GetMapping("/generate2")
-    public SpecialResult generate2(Long pid,Long uid){
-        return specialReportService.generate(pid,uid);
+    @GetMapping("/generateMind")
+    @ApiOperation("生成专项诊断第二页思维过程报告")
+    public List<SpecialMindVo> generateMind(Long pid, Long uid) {
+        List<SpecialMindVo> list = specialReportService.generateMind(pid, uid);
+        list.sort(Comparator.comparingInt(SpecialMindVo::getSort));
+        return list;
     }
+
+//    @GetMapping("/generate2")
+//    public SpecialResult generate2(Long pid,Long uid){
+//        return specialReportService.generate2(pid,uid);
+//    }
 }

+ 5 - 0
src/main/java/com/yaoxiang/diagnosis/controller/TestController.java

@@ -41,6 +41,11 @@ public class TestController {
 
     private static final Logger logger = LoggerFactory.getLogger(TestController.class);
 
+    @GetMapping("/")
+    public String index(){
+        return "hello";
+    }
+
     @PreAuthorize("hasRole('ROLE_USER')")
     @RequestMapping(value = "/test", method = RequestMethod.GET)
     public String test() {

+ 2 - 6
src/main/java/com/yaoxiang/diagnosis/controller/UserInfoController.java

@@ -28,12 +28,8 @@ public class UserInfoController {
     @GetMapping("/authority")
     public List<String> getAuthorities() {
         AuthUser user = SecurityUtil.getCurrentUser();
-//        if (user.getAuthorities().contains(ConfigConstants.ROLE_ADMIN)) {
-//            return ConfigConstants.ADMIN_AUTHORITY;
-//        } else if (user.getAuthorities().contains(ConfigConstants.ROLE_USER)) {
-//            return ConfigConstants.USER_AUTHORITY;
-//        }
-        return new ArrayList<>();
+        UserInfo userInfo = user.getUser();
+        return userInfo.getAuthorities();
     }
 
     /**

+ 1 - 1
src/main/java/com/yaoxiang/diagnosis/dao/PaperResultRepo.java

@@ -15,7 +15,7 @@ import java.util.List;
 @Repository
 public interface PaperResultRepo extends JpaRepository<PaperResult, Long> {
 
-    PaperResult findByPidAndUid(Long pid, Long uid);
+    List<PaperResult> findByPidAndUid(Long pid, Long uid);
 
     int deleteByPidAndUid(Long pid, Long uid);
 

+ 14 - 0
src/main/java/com/yaoxiang/diagnosis/dao/SpecialMindRepo.java

@@ -0,0 +1,14 @@
+package com.yaoxiang.diagnosis.dao;
+
+import com.yaoxiang.diagnosis.entity.SpecialMind;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+import java.util.List;
+
+public interface SpecialMindRepo extends JpaRepository<SpecialMind,Long> {
+
+    List<SpecialMind> findBySubjectIdAndGrade(Long subjectId,String grade);
+
+    List<SpecialMind> findByPid(Long pid);
+
+}

+ 12 - 0
src/main/java/com/yaoxiang/diagnosis/entity/Authority.java

@@ -1,5 +1,7 @@
 package com.yaoxiang.diagnosis.entity;
 
+import io.swagger.annotations.ApiModelProperty;
+
 import javax.persistence.Entity;
 import javax.persistence.GeneratedValue;
 import javax.persistence.GenerationType;
@@ -11,6 +13,8 @@ public class Authority {
     @GeneratedValue(strategy = GenerationType.IDENTITY)
     private Long id;
     private String name;
+    @ApiModelProperty("权限类型 function business ")
+    private String type;
     private String des;
 
     public Long getId() {
@@ -29,6 +33,14 @@ public class Authority {
         this.name = name;
     }
 
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
     public String getDes() {
         return des;
     }

+ 9 - 0
src/main/java/com/yaoxiang/diagnosis/entity/Role.java

@@ -14,6 +14,7 @@ public class Role {
     private Long id;
     @Column(unique = true, nullable = false)
     private String name;
+    private String code;
     //预留
     private String type;
 
@@ -34,6 +35,14 @@ public class Role {
         this.id = id;
     }
 
+    public String getCode() {
+        return code;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
     public String getName() {
         return name;
     }

+ 7 - 5
src/main/java/com/yaoxiang/diagnosis/entity/SpecialKnowledge.java

@@ -35,7 +35,7 @@ public class SpecialKnowledge {
     @ApiModelProperty("知识点内容")
     private String content;
 
-    @ApiModelProperty("掌握等级 掌握 理解 应用")
+    @ApiModelProperty("认识等级 red yellow green")
     private String masterLevel;
 
     @ApiModelProperty("父Id")
@@ -57,7 +57,7 @@ public class SpecialKnowledge {
     @ApiModelProperty("掌握率")
     private Double master = 100.0;
     @Transient
-    @ApiModelProperty("掌握情况")
+    @ApiModelProperty("掌握情况 掌握 未掌握 ")
     private String masterStatus = Constants.SPECIAL_KNOWLEDGE_MASTER;
 
     @Transient
@@ -220,10 +220,12 @@ public class SpecialKnowledge {
     @Override
     public String toString() {
         return "SpecialKnowledge{" +
-                "level=" + level +
-                ", code='" + code + '\'' +
+                "id=" + id +
+                ", level=" + level +
                 ", content='" + content + '\'' +
-                ", parentId=" + parentId +
+                ", questionNum=" + questionNum +
+                ", collectNum=" + collectNum +
+                ", qids='" + qids + '\'' +
                 '}';
     }
 }

+ 121 - 0
src/main/java/com/yaoxiang/diagnosis/entity/SpecialMind.java

@@ -0,0 +1,121 @@
+package com.yaoxiang.diagnosis.entity;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+import javax.persistence.*;
+
+@Entity
+@ApiModel
+public class SpecialMind {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+
+    @ApiModelProperty("跟第几步对应,排序用")
+    private Integer sort;
+    @ApiModelProperty("第几步")
+    private String step;
+    @ApiModelProperty("问题")
+    private String content;
+    private Long pid;
+    private Long subjectId;
+    private String grade;
+    private String qids;
+    @Transient
+    @ApiModelProperty("是否有错题")
+    private Boolean mistake;
+    @Transient
+    private Integer collectNum;
+    @Transient
+    private Integer questionNum;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public Integer getSort() {
+        return sort;
+    }
+
+    public void setSort(Integer sort) {
+        this.sort = sort;
+    }
+
+    public String getStep() {
+        return step;
+    }
+
+    public void setStep(String step) {
+        this.step = step;
+    }
+
+    public String getContent() {
+        return content;
+    }
+
+    public void setContent(String content) {
+        this.content = content;
+    }
+
+    public Long getPid() {
+        return pid;
+    }
+
+    public void setPid(Long pid) {
+        this.pid = pid;
+    }
+
+    public Long getSubjectId() {
+        return subjectId;
+    }
+
+    public void setSubjectId(Long subjectId) {
+        this.subjectId = subjectId;
+    }
+
+    public String getGrade() {
+        return grade;
+    }
+
+    public void setGrade(String grade) {
+        this.grade = grade;
+    }
+
+    public String getQids() {
+        return qids;
+    }
+
+    public void setQids(String qids) {
+        this.qids = qids;
+    }
+
+    public Boolean getMistake() {
+        return mistake;
+    }
+
+    public void setMistake(Boolean mistake) {
+        this.mistake = mistake;
+    }
+
+    public Integer getCollectNum() {
+        return collectNum;
+    }
+
+    public void setCollectNum(Integer collectNum) {
+        this.collectNum = collectNum;
+    }
+
+    public Integer getQuestionNum() {
+        return questionNum;
+    }
+
+    public void setQuestionNum(Integer questionNum) {
+        this.questionNum = questionNum;
+    }
+}

+ 8 - 0
src/main/java/com/yaoxiang/diagnosis/model/SpecialKnowledgeVo.java

@@ -0,0 +1,8 @@
+package com.yaoxiang.diagnosis.model;
+
+public class SpecialKnowledgeVo {
+
+    private Long id;
+    private Integer collectNum;
+    private Integer questionNum;
+}

+ 59 - 0
src/main/java/com/yaoxiang/diagnosis/model/SpecialMindVo.java

@@ -0,0 +1,59 @@
+package com.yaoxiang.diagnosis.model;
+
+import com.yaoxiang.diagnosis.entity.SpecialMind;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.util.List;
+
+@ApiModel
+public class SpecialMindVo {
+    @ApiModelProperty("达成率")
+    private Double master;
+    private Integer sort;
+    @ApiModelProperty("第几部")
+    private String step;
+    private List<SpecialMind> minds;
+    @ApiModelProperty("涂色 yellow green red")
+    private String masterStatus;
+
+    public Double getMaster() {
+        return master;
+    }
+
+    public void setMaster(Double master) {
+        this.master = master;
+    }
+
+    public Integer getSort() {
+        return sort;
+    }
+
+    public void setSort(Integer sort) {
+        this.sort = sort;
+    }
+
+    public String getStep() {
+        return step;
+    }
+
+    public void setStep(String step) {
+        this.step = step;
+    }
+
+    public List<SpecialMind> getMinds() {
+        return minds;
+    }
+
+    public void setMinds(List<SpecialMind> minds) {
+        this.minds = minds;
+    }
+
+    public String getMasterStatus() {
+        return masterStatus;
+    }
+
+    public void setMasterStatus(String masterStatus) {
+        this.masterStatus = masterStatus;
+    }
+}

+ 7 - 0
src/main/java/com/yaoxiang/diagnosis/service/CommitService.java

@@ -5,12 +5,14 @@ import com.yaoxiang.diagnosis.dao.PaperCommitRepo;
 import com.yaoxiang.diagnosis.dao.QuestionRepo;
 import com.yaoxiang.diagnosis.dao.ReportRepo;
 import com.yaoxiang.diagnosis.entity.*;
+import com.yaoxiang.diagnosis.model.AuthUser;
 import com.yaoxiang.diagnosis.util.CodeUtil;
 import com.yaoxiang.diagnosis.util.CommonUtil;
 import com.yaoxiang.diagnosis.util.ObjectUtil;
 import com.yaoxiang.diagnosis.model.Answer;
 import com.yaoxiang.diagnosis.model.QuestionDetail;
 import com.yaoxiang.diagnosis.model.Result;
+import com.yaoxiang.diagnosis.util.SecurityUtil;
 import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -170,6 +172,11 @@ public class CommitService {
     }
 
     public boolean hasCommit(Long pid, Long uid) {
+        //增加权限校验
+        AuthUser user = SecurityUtil.getCurrentUser();
+        if (user.getUser().getAuthorities().contains("重复提交")) {
+            return false;
+        }
         return paperCommitRepo.existsByPidAndUid(pid, uid);
     }
 

+ 4 - 2
src/main/java/com/yaoxiang/diagnosis/service/OptionService.java

@@ -31,7 +31,8 @@ public class OptionService {
         }
         option.setUpdatetime(new Date());
         option.setCreatetime(new Date());
-        return new Result(optionRepo.save(option) != null);
+        optionRepo.save(option);
+        return Result.ok();
     }
 
     public Result updateOption(QuestionOption option) {
@@ -42,7 +43,8 @@ public class OptionService {
             return new Result(false, "编辑选项不能没有题目id");
         }
         option.setUpdatetime(new Date());
-        return new Result(optionRepo.saveAndFlush(option) != null);
+        optionRepo.saveAndFlush(option);
+        return Result.ok();
     }
 
     public List<QuestionOption> listOptionByQuestion(Question question) {

+ 7 - 5
src/main/java/com/yaoxiang/diagnosis/service/PaperResultService.java

@@ -127,9 +127,13 @@ public class PaperResultService {
         result.setJsonScore(ObjectUtil.object2Json(pData));
         //转换分数为百分制
         double totalScore = paper.getTotalScore();
+        if (totalScore == 0) {
+            logger.error("总分数为0,请检查试卷");
+            return Result.fail("提交失败,请重试");
+        }
         double s = NumberUtil.format(score * 100 / totalScore);
         result.setScore(totalScore == 0 ? score : s);
-        result.setTotalScore(totalScore);
+        result.setTotalScore(100.0d);
         paperResultRepo.save(result);
         logger.info("答案分析保存成功,pid={},uid={},name={},score={},collectQuestion={}", paper.getId(),
                 paperCommit.getUid(), paperCommit.getName(), result.getScore(), result.getCollectQuestion());
@@ -144,7 +148,7 @@ public class PaperResultService {
         return paperResultRepo.getOne(resultId);
     }
 
-    public PaperResult findByPidAndUid(Long pid, Long uid) {
+    public List<PaperResult> findByPidAndUid(Long pid, Long uid) {
         return paperResultRepo.findByPidAndUid(pid, uid);
     }
 
@@ -681,9 +685,7 @@ public class PaperResultService {
             return paperResultRepo.findByUidOrderByCreatetimeDesc(uid);
         }
         if (uid != null) {
-            return new ArrayList<PaperResult>() {{
-                add(paperResultRepo.findByPidAndUid(pid, uid));
-            }};
+            return paperResultRepo.findByPidAndUid(pid, uid);
         }
         return paperResultRepo.findByPidOrderByCreatetimeDesc(pid);
     }

+ 112 - 100
src/main/java/com/yaoxiang/diagnosis/service/PaperService.java

@@ -5,11 +5,13 @@ import com.yaoxiang.diagnosis.dao.PaperRepo;
 import com.yaoxiang.diagnosis.dao.QuestionRepo;
 import com.yaoxiang.diagnosis.dao.RemarkTemplateRepo;
 import com.yaoxiang.diagnosis.entity.*;
+import com.yaoxiang.diagnosis.model.AuthUser;
 import com.yaoxiang.diagnosis.util.CommonUtil;
 import com.yaoxiang.diagnosis.util.ObjectUtil;
 import com.yaoxiang.diagnosis.config.Constants;
 import com.yaoxiang.diagnosis.model.PaperVo;
 import com.yaoxiang.diagnosis.model.Result;
+import com.yaoxiang.diagnosis.util.SecurityUtil;
 import com.yaoxiang.diagnosis.word.WordService;
 import com.yaoxiang.diagnosis.word.WordUtil;
 import org.apache.commons.lang3.StringUtils;
@@ -66,8 +68,13 @@ public class PaperService {
     private static final Logger logger = LoggerFactory.getLogger(PaperService.class);
 
     public List<Paper> listPapers(Long subjectId, Integer status) {
+        AuthUser user = SecurityUtil.getCurrentUser();
         Sort sort = new Sort(Sort.Direction.DESC, "updatetime");
         List<Paper> papers = paperRepo.findAll(sort);
+        if (Constants.USER_TYPE_STUDENT.equals(user.getUser().getUserType())
+                && !user.getUser().getAuthorities().contains("重复提交")) {
+            papers = papers.stream().filter(p -> p.getGrade().contains(user.getUser().getGrade())).collect(Collectors.toList());
+        }
         if (subjectId != null) {
             papers = papers.stream().filter(p -> p.getSubjectId() == subjectId.longValue())
                     .collect(Collectors.toList());
@@ -90,26 +97,15 @@ public class PaperService {
     }
 
     public Paper getOnePaper(Long id) {
-        Paper paper = paperRepo.getOne(id);
+        AuthUser user = SecurityUtil.getCurrentUser();
+        boolean student = Constants.USER_TYPE_STUDENT.equals(user.getUser().getUserType());
+        Paper paper = paperRepo.findById(id).orElse(null);
         if (paper == null || paper.getStatus() == Constants.NOTREADY) {
             return null;
         }
         List<Question> questions = questionRepo.findByPidOrderBySectionAscNumberAsc(id);
         List<Section> sections = sectionService.findByPid(id);
         paper.setSections(sections);
-//        questions.sort((q1, q2) -> {
-//            if (q1.getSection() < q2.getSection()) {
-//                return -1;
-//            } else if (q1.getSection() > q2.getSection()) {
-//                return 1;
-//            }
-//            if (q1.getNumber() < q2.getNumber()) {
-//                return -1;
-//            } else if (q1.getNumber() > q2.getNumber()) {
-//                return 1;
-//            }
-//            return 0;
-//        });
         paper.setQuestions(questions);
         List<Long> qids = questions.stream().map(Question::getId).collect(Collectors.toList());
         //一次查出该试卷所有的选项
@@ -117,14 +113,24 @@ public class PaperService {
         //然后根据Id进行分组
         Map<Long, List<QuestionOption>> group = options.stream().collect(Collectors.groupingBy(QuestionOption::getQid));
         for (Question question : questions) {
-//            List<QuestionOption> options = optionRepo.findByQid(question.getId());
-//            for (QuestionOption option : options) {
-            //todo 判断是否考生,如是  将答案设为null
-//               option.setCorrect(null);
-//                option.setUpdatetime(null);
-//                option.setCreatetime(null);
-//            }
-            question.setOptions(group.get(question.getId()));
+            List<QuestionOption> optionList = group.get(question.getId());
+            List<QuestionOption> os = new ArrayList<>();
+            //学生要去掉答案
+            if (student) {
+                question.setCorrectNum(0);
+                //避免自动持久化
+                for (QuestionOption o : optionList) {
+                    QuestionOption option = new QuestionOption();
+                    option.setId(o.getId());
+                    option.setContent(o.getContent());
+                    option.setOindex(o.getOindex());
+                    option.setQid(o.getQid());
+                    os.add(option);
+                }
+                question.setOptions(os);
+            } else {
+                question.setOptions(optionList);
+            }
         }
         return paper;
     }
@@ -155,10 +161,6 @@ public class PaperService {
         }
         //init json score
         Map<String, Double> data = new HashMap<>();
-        List<SubjectAbility> abilities = subjectAbilityService.list(paper.getSubjectId());
-        //初始化数据
-        abilities.forEach(a -> data.put(a.getCode(), 0d));
-        data.put("A0", 0d);
         double totalScore = 0;
         for (Question question : save.getQuestions()) {
             question.setPid(save.getId());
@@ -176,18 +178,21 @@ public class PaperService {
                 abilityScoreService.add(score);
             }
         }
+
         for (Section section : save.getSections()) {
             section.setPid(save.getId());
             //保存段落
             sectionService.add(section);
         }
         //不使用能力计分,并且能力数量大于0
-        if (!paper.getUseAbility() && abilities.size() > 0) {
-            //put第一个能力进去
-            data.put(abilities.get(0).getCode(), (double) paper.getQuestions().size());
+        if (!paper.getUseAbility()) {
+            //put一个A0能力进去
+            data.put("A0", (double) paper.getQuestions().size());
+            paper.setTotalScore(paper.getQuestionNum());
+        } else {
+            paper.setTotalScore((int) totalScore);
         }
         String jsonScore = ObjectUtil.object2Json(data);
-        paper.setTotalScore((int) totalScore);
         paper.setJsonScore(jsonScore);
         paperRepo.saveAndFlush(paper);
         logger.info("试卷增加成功");
@@ -206,7 +211,8 @@ public class PaperService {
 
     public Result update(Paper paper) {
         paper.setUpdatetime(new Date());
-        return new Result(paperRepo.saveAndFlush(paper) != null);
+        paperRepo.saveAndFlush(paper);
+        return Result.ok();
     }
 
     @Transactional(rollbackFor = Exception.class)
@@ -253,6 +259,7 @@ public class PaperService {
         return addWithQuestion(paper);
 //        return Result.ok(paper);
     }
+
     @Transactional(rollbackFor = Exception.class)
     public Result uploadPaperTest(PaperVo paperVo, Long templateId, String url, byte[] data) {
         Paper paper = init(paperVo, url);
@@ -283,73 +290,13 @@ public class PaperService {
         return Result.ok(paper);
     }
 
-    private Map<String, List<XWPFParagraph>> initSections(Paper paper, String sectionPattern, String questionPattern, String picturePattern, List<XWPFParagraph> paragraphs) {
-        //保证顺序
-        Map<String, List<XWPFParagraph>> sections = new LinkedHashMap<>();
-        String tag = "";
-        boolean betweenSectionAndQuestion = false;
-        logger.info("sectionPattern is {},questionPattern is {}",sectionPattern,questionPattern);
-        StringBuilder material = new StringBuilder();
-        int section = 0;
-        List<Section> sectionList = new ArrayList<>();
-        logger.info("initSections start");
-        boolean hasFormula = false;
-        for (XWPFParagraph paragraph : paragraphs) {
-            String text = paragraph.getText();
-            //此处应判断下是否有图片、文字或者公式
-            if (WordUtil.notContent(paragraph, text)) {
-                continue;
-            }
-            //下一个section
-            if (text.matches(sectionPattern)) {
-                logger.info("match section: text is {} sectionPattern is {}", text, sectionPattern);
-                Matcher matcher = Pattern.compile("\\d+").matcher(text);
-                //获取到section编号
-                if (matcher.find()) {
-                    section = Integer.parseInt(matcher.group());
-                }
-                //1 2 3
-                tag = String.valueOf(section);
-                betweenSectionAndQuestion = true;
-                continue;
-            }
-            if (betweenSectionAndQuestion && text.matches(questionPattern)) {
-                Section s = initSection(section, material.toString());
-                sectionList.add(s);
-                //清空背景材料
-                material = new StringBuilder();
-                betweenSectionAndQuestion = false;
-            }
-            //Session后面可能有背景材料,背景材料里面可能有图片和公式,这个放后面来处理
-            if (betweenSectionAndQuestion) {
-                //解析背景材料的图片和公式
-                wordService.parsePicture(paragraph, picturePattern);
-                hasFormula = wordService.parseFormula(paragraph);
-                material.append("<p>").append(paragraph.getText()).append("</p>");
-            }
-            //此处可能是第一段
-            if (StringUtils.isNotBlank(tag)) {
-                List<XWPFParagraph> list = sections.getOrDefault(tag, new ArrayList<>());
-                list.add(paragraph);
-                sections.put(tag, list);
-            }
-        }
-        paper.setSections(sectionList);
-        logger.info("initSections end,sections num is {}", sectionList.size());
-        return sections;
-    }
-
     private void parsePaper(Paper paper, PaperTemplate template, XWPFDocument document) {
-        String tagPattern = template.getSection();
-        String questionPattern = template.getQuestion();
-        String picturePattern = template.getPicturePattern();
         List<XWPFParagraph> paragraphs = document.getParagraphs();
         Assert.notEmpty(paragraphs, "未检测到段落,请检查上传的文档");
         String name = paragraphs.get(0).getText();
-        //TODO check name of paper
         parsePaperName(paper, name, template);
         //获取模块,根据模块,给段落分组
-        Map<String, List<XWPFParagraph>> sections = initSections(paper, tagPattern, questionPattern, picturePattern, paragraphs);
+        Map<String, List<XWPFParagraph>> sections = initSections(paper, template, paragraphs);
         Assert.notEmpty(sections, "未检测到模块,请检查上传的文档");
 //        List<String> topics = paperTemplateService.getTopic(template);
         Map<String, String> topic = paperTemplateService.getMapTopic(template);
@@ -368,9 +315,9 @@ public class PaperService {
 //            Section current = ss.stream().filter(section -> s.contains(section.getNumber().toString())).findFirst().orElse(null);
             Section current = sectionMap.get(s);
             //根据题目标签,给题目分组
-            Map<String, List<XWPFParagraph>> questions = initQuestions(current, questionPattern, ps);
+            Map<String, List<XWPFParagraph>> questions = initQuestions(current, template, ps);
             current.setStartNumber(currentNumber);
-            List<Question> list = parseQuestions(questions, current, template, topic, abilities);
+            List<Question> list = parseQuestions(questions, current, template, topic, paper.getUseAbility(), abilities);
             current.setNums(list.size());
             currentNumber = currentNumber + list.size();
             qs.put(s, list);
@@ -400,11 +347,68 @@ public class PaperService {
             sb.append(g).append("年级").append(first ? "上学期" : "下学期");
         }
         //取最后一个字为卷,一般为A、B卷
-        sb.append(name.substring(name.length() -1)).append("卷");
+        sb.append(name.substring(name.length() - 1)).append("卷");
         paper.setName(sb.toString());
     }
 
-    private List<Question> parseQuestions(Map<String, List<XWPFParagraph>> questions, Section section, PaperTemplate template, Map<String, String> topic, List<String> abilities) {
+    private Map<String, List<XWPFParagraph>> initSections(Paper paper, PaperTemplate template, List<XWPFParagraph> paragraphs) {
+        //保证顺序
+        Map<String, List<XWPFParagraph>> sections = new LinkedHashMap<>();
+        String tag = "";
+        boolean betweenSectionAndQuestion = false;
+        logger.info("sectionPattern is {},questionPattern is {}", template.getSection(), template.getQuestion());
+        StringBuilder material = new StringBuilder();
+        int section = 0;
+        List<Section> sectionList = new ArrayList<>();
+        logger.info("initSections start");
+        boolean hasFormula = false;
+        for (XWPFParagraph paragraph : paragraphs) {
+            String text = paragraph.getText();
+            //此处应判断下是否有图片、文字或者公式
+            if (WordUtil.notContent(paragraph, text)) {
+                continue;
+            }
+            //下一个section
+            if (text.matches(template.getSection())) {
+                logger.info("match section: text is {} sectionPattern is {}", text, template.getSection());
+                Matcher matcher = Pattern.compile("\\d+").matcher(text);
+                //获取到section编号
+                if (matcher.find()) {
+                    section = Integer.parseInt(matcher.group());
+                }
+                //1 2 3
+                tag = String.valueOf(section);
+                betweenSectionAndQuestion = true;
+                continue;
+            }
+            if (betweenSectionAndQuestion && text.matches(template.getQuestion())) {
+                Section s = initSection(section, material.toString());
+                sectionList.add(s);
+                //清空背景材料
+                material = new StringBuilder();
+                betweenSectionAndQuestion = false;
+            }
+            //Session后面可能有背景材料,背景材料里面可能有图片和公式,这个放后面来处理
+            if (betweenSectionAndQuestion) {
+                //解析背景材料的图片和公式
+                wordService.parseSubScript(paragraph);
+                wordService.parsePicture(paragraph, template.getPicturePattern());
+                hasFormula = wordService.parseFormula(paragraph);
+                material.append("<p>").append(paragraph.getText()).append("</p>");
+            }
+            //此处可能是第一段
+            if (StringUtils.isNotBlank(tag)) {
+                List<XWPFParagraph> list = sections.getOrDefault(tag, new ArrayList<>());
+                list.add(paragraph);
+                sections.put(tag, list);
+            }
+        }
+        paper.setSections(sectionList);
+        logger.info("initSections end,sections num is {}", sectionList.size());
+        return sections;
+    }
+
+    private List<Question> parseQuestions(Map<String, List<XWPFParagraph>> questions, Section section, PaperTemplate template, Map<String, String> topic, Boolean useAbility, List<String> abilities) {
         List<Question> list = new ArrayList<>();
         //问题合集
         Pattern pattern = Pattern.compile("\\d+");
@@ -412,15 +416,15 @@ public class PaperService {
             Matcher matcher = pattern.matcher(k);
             if (k.matches(template.getQuestion()) && matcher.find()) {
                 String code = matcher.group();
-                Question question = questionService.initQuestion(section.getNumber(), section.getStartNumber(), Integer.valueOf(code));
-                wordService.parseQuestion(question, v, topic, template, abilities);
+                Question question = questionService.initQuestion(section.getNumber(), section.getStartNumber(), Integer.valueOf(code), useAbility);
+                wordService.parseQuestion(question, v, topic, template, useAbility);
                 list.add(question);
             }
         });
         return list;
     }
 
-    private Map<String, List<XWPFParagraph>> initQuestions(Section section, String questionPattern, List<XWPFParagraph> ps) {
+    private Map<String, List<XWPFParagraph>> initQuestions(Section section, PaperTemplate paperTemplate, List<XWPFParagraph> ps) {
         Map<String, List<XWPFParagraph>> questions = new ConcurrentHashMap<>();
         String tag = "";
         for (XWPFParagraph paragraph : ps) {
@@ -428,9 +432,17 @@ public class PaperService {
             if (WordUtil.notContent(paragraph, text)) {
                 continue;
             }
+            //识别上下标
+            wordService.parseSubScript(paragraph);
+            //识别图片
+            wordService.parsePicture(paragraph, paperTemplate.getPicturePattern());
+            //识别公式
+            wordService.parseFormula(paragraph);
+            //重新获取text
+            text = paragraph.getText();
             //下一个question
             // questionPattern ^#[A-Z]#(.*)
-            if (text.matches(questionPattern)) {
+            if (text.matches(paperTemplate.getQuestion())) {
                 tag = text;
             }
             logger.info("initQuestions,current tag is {},current text is {}", tag, text);

+ 14 - 10
src/main/java/com/yaoxiang/diagnosis/service/QuestionService.java

@@ -49,7 +49,7 @@ public class QuestionService {
     public Result updateQuestion(Question question) {
         Long id = question.getId();
         if (id == null) {
-            return new Result(false);
+            return Result.fail("未找到该题目Id");
         }
         question.setUpdatetime(new Date());
         for (QuestionOption option : question.getOptions()) {
@@ -65,7 +65,8 @@ public class QuestionService {
                 }
             }
         }
-        return new Result(questionRepo.saveAndFlush(question) != null);
+        questionRepo.saveAndFlush(question);
+        return Result.ok();
     }
 
     public List<Question> listQuestionByPaper(Paper paper) {
@@ -109,13 +110,13 @@ public class QuestionService {
         return question == null ? 0 : question.getNumber();
     }
 
-    @Transactional(rollbackFor = Exception.class)
-    public Result parseQuestion(Long pid, Integer section, Integer number, byte[] data) {
-        Question question = initQuestion(pid, section, number);
-        wordService.parseQuestion(question, data);
-        addQuestion(question);
-        return Result.ok(question);
-    }
+//    @Transactional(rollbackFor = Exception.class)
+//    public Result parseQuestion(Long pid, Integer section, Integer number, byte[] data) {
+//        Question question = initQuestion(pid, section, number);
+//        wordService.parseQuestion(question, data);
+//        addQuestion(question);
+//        return Result.ok(question);
+//    }
 
     private Question initQuestion(Long pid, Integer section, Integer number) {
         Question question = new Question();
@@ -131,11 +132,14 @@ public class QuestionService {
         return question;
     }
 
-    public Question initQuestion(Integer section,Integer startNumber, Integer number) {
+    public Question initQuestion(Integer section,Integer startNumber, Integer number,Boolean useAbility) {
         Question question = new Question();
         question.setCreatetime(new Date());
         question.setScore(1D);
         question.setNumber(number);
+        if(useAbility == null || !useAbility){
+            question.setJsonScore("{\"A0\":1.0}");
+        }
         //更改code
         question.setCode(number - startNumber);
         question.setDuration(60);

+ 140 - 5
src/main/java/com/yaoxiang/diagnosis/service/SpecialKnowledgeService.java

@@ -49,7 +49,7 @@ public class SpecialKnowledgeService {
         return specialKnowledgeRepo.findBySubjectId(subjectId);
     }
 
-    public List<SpecialKnowledge> listByPid(Long pid){
+    public List<SpecialKnowledge> listByPid(Long pid) {
         return specialKnowledgeRepo.findByPid(pid);
     }
 
@@ -75,22 +75,34 @@ public class SpecialKnowledgeService {
     }
 
     public void calcCount(List<SpecialKnowledge> list) {
+        logger.info("specialKnowledge size = {}", list.size());
+        //根据知识点所在层级分组
         Map<Integer, List<SpecialKnowledge>> group = list.stream().collect(Collectors.groupingBy(SpecialKnowledge::getLevel));
+        //将list根据Id变成map
         Map<Long, SpecialKnowledge> knowledgeMap = list.stream().collect(Collectors.toMap(SpecialKnowledge::getId, Function.identity()));
+        //找出最大层级
         int max = group.keySet().stream().max(Comparator.naturalOrder()).orElse(0);
+//        Map<Long,>
+        //根据同一个parentId的进行分组
+//        Map<Long, List<SpecialKnowledge>> parentMap = list.stream().filter(k->k.getParentId() != null)
+//                .collect(Collectors.groupingBy(SpecialKnowledge::getParentId));
+
         if (max == 0) {
             logger.error("最大层级为0,请检查数据");
+            return;
         }
         for (int i = max; i > 1; i--) {
             //全是同一级的
             List<SpecialKnowledge> ss = group.get(i);
-            //找出同一个parentId的
-            Map<Long, List<SpecialKnowledge>> map = ss.stream().collect(Collectors.groupingBy(SpecialKnowledge::getParentId));
+            Map<Long, List<SpecialKnowledge>> parentMap = ss.stream().filter(k -> k.getParentId() != null)
+                    .collect(Collectors.groupingBy(SpecialKnowledge::getParentId));
+
             double rate = 0;
-            for (Map.Entry<Long, List<SpecialKnowledge>> entry : map.entrySet()) {
+            for (Map.Entry<Long, List<SpecialKnowledge>> entry : parentMap.entrySet()) {
                 int collectCount = 0;
                 int questionNum = 0;
                 List<SpecialKnowledge> specialKnowledges = entry.getValue();
+                //如果有值,说明已经统计过了
                 for (SpecialKnowledge s : specialKnowledges) {
                     collectCount += s.getCollectNum();
                     questionNum += s.getQuestionNum();
@@ -103,8 +115,10 @@ public class SpecialKnowledgeService {
                     //小于等于层级3
                     if (i <= 4 && questionNum > 0) {
                         double master = collectCount * 100.0 / questionNum;
+                        logger.info("parent content={},level={},master={},masterStatus={}",
+                                parent.getContent(), parent.getLevel(), parent.getMaster(), parent.getMasterStatus());
                         parent.setMaster(NumberUtil.format(master));
-                        if (master < 0.8) {
+                        if (master < 80) {
                             parent.setMasterStatus(Constants.SPECIAL_KNOWLEDGE_UNMASTER);
                         }
                     }
@@ -134,4 +148,125 @@ public class SpecialKnowledgeService {
         }
         return true;
     }
+
+    public void calcComplex(List<SpecialKnowledge> list) {
+        int max = list.stream().map(SpecialKnowledge::getLevel).max(Comparator.naturalOrder()).orElse(0);
+        if (max == 0) {
+            logger.error("最大层级为0,请检查数据");
+            return;
+        }
+        Map<Long, SpecialKnowledge> mapper = list.stream().collect(Collectors.toMap(SpecialKnowledge::getId, Function.identity()));
+        List<SpecialKnowledge> ks = list.stream().filter(s -> s.getLevel() == max).collect(Collectors.toList());
+        Map<Long, List<SpecialKnowledge>> parentMap = ks.stream().collect(Collectors.groupingBy(SpecialKnowledge::getParentId));
+        for (Map.Entry<Long, List<SpecialKnowledge>> entry : parentMap.entrySet()) {
+            List<SpecialKnowledge> s = entry.getValue();
+            SpecialKnowledge parent = mapper.get(entry.getKey());
+            //TODO 后续优化这个排序
+            SpecialKnowledge know = null, under = null, usage = null;
+            for (SpecialKnowledge k : s) {
+                switch (k.getContent()) {
+                    case Constants.SPECIAL_MASTER_STATUS_KNOW:
+                        know = k;
+                        break;
+                    case Constants.SPECIAL_MASTER_STATUS_UNDERSTAND:
+                        under = k;
+                        break;
+                    case Constants.SPECIAL_MASTER_STATUS_USAGE:
+                        usage = k;
+                        break;
+                }
+            }
+            int weight = calcWeight(know, under, usage,parent);
+            logger.info("当前知识点为parent={}", parent);
+            switch (weight) {
+                case 0:
+                    logger.error("unexpected error,当前知识点没有考试题");
+                    break;
+                case 1:
+                    logger.info("当前知识点只考了认识");
+                    break;
+                case 6:
+                    logger.info("当前知识点考了理解和应用");
+                    if (usage.getMaster() >= 50) {
+                        parent.setMasterLevel("应用");
+                        if (parent.getMaster() >= 75) {
+                            parent.setMasterStatus("green");
+                        } else {
+                            parent.setMasterStatus("yellow");
+                        }
+                        break;
+                    }
+                    //应用小于50
+                    if (under.getMaster() >= 50) {
+                        parent.setMasterLevel("理解");
+                        int collect = under.getCollectNum() + know.getCollectNum();
+                        int questionNum = under.getQuestionNum() + know.getQuestionNum();
+                        if (questionNum == 0) {
+                            logger.error("unexpected error,题目数量为0,认识和理解未考题目");
+                        }
+                        double master = collect * 100.0 / questionNum;
+                        if (master >= 75) {
+                            parent.setMasterStatus("yellow");
+                        } else {
+                            parent.setMasterStatus("red");
+                        }
+                    } else {
+                        //最低评价 理解红色
+                        parent.setMasterLevel("理解");
+                        parent.setMasterStatus("red");
+                    }
+                    break;
+                case 7:
+                    logger.info("当前知识点考了所有题目");
+                    if (usage.getMaster() >= 50) {
+                        parent.setMasterLevel("应用");
+                        if (parent.getMaster() >= 75) {
+                            parent.setMasterStatus("green");
+                        } else {
+                            parent.setMasterStatus("yellow");
+                        }
+                        break;
+                    }
+                    //应用小于50
+                    if (under.getMaster() >= 50) {
+                        parent.setMasterLevel("理解");
+                        int collect = under.getCollectNum() + know.getCollectNum();
+                        int questionNum = under.getQuestionNum() + know.getQuestionNum();
+                        if (questionNum == 0) {
+                            logger.error("unexpected error,题目数量为0,认识和理解未考题目");
+                        }
+                        double master = collect * 100.0 / questionNum;
+                        if (master >= 75) {
+                            parent.setMasterStatus("yellow");
+                        } else {
+                            parent.setMasterStatus("red");
+                        }
+                        break;
+                    }
+                    parent.setMasterLevel("认识");
+                    if (know.getMaster() >= 75) {
+                        parent.setMasterStatus("yellow");
+                    } else {
+                        parent.setMasterStatus("red");
+                    }
+            }
+        }
+    }
+
+    private int calcWeight(SpecialKnowledge know, SpecialKnowledge under, SpecialKnowledge usage,SpecialKnowledge parent) {
+        int a = 1, b = 2, c = 4;
+        if (know == null || StringUtils.isBlank(know.getQids())) {
+            a = 0;
+            logger.warn("未找到认识层级,parent={}", parent.getContent());
+        }
+        if (under == null || StringUtils.isBlank(under.getQids())) {
+            b = 0;
+            logger.warn("未找到理解层级,parent={}", parent.getContent());
+        }
+        if (usage == null || StringUtils.isBlank(usage.getQids())) {
+            c = 0;
+            logger.warn("未找到应用层级,parent={}", parent.getContent());
+        }
+        return a + b + c;
+    }
 }

+ 29 - 0
src/main/java/com/yaoxiang/diagnosis/service/SpecialMindService.java

@@ -0,0 +1,29 @@
+package com.yaoxiang.diagnosis.service;
+
+import com.yaoxiang.diagnosis.dao.SpecialMindRepo;
+import com.yaoxiang.diagnosis.entity.SpecialMind;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import javax.transaction.Transactional;
+import java.util.List;
+
+@Service
+public class SpecialMindService {
+
+    @Resource
+    private SpecialMindRepo specialMindRepo;
+
+    @Transactional(rollbackOn = Exception.class)
+    public boolean add(List<SpecialMind> list) {
+        for (SpecialMind s : list) {
+            specialMindRepo.save(s);
+        }
+        return true;
+    }
+
+    public List<SpecialMind> findByPid(Long pid){
+        return specialMindRepo.findByPid(pid);
+    }
+
+}

+ 150 - 19
src/main/java/com/yaoxiang/diagnosis/service/SpecialReportService.java

@@ -1,7 +1,14 @@
 package com.yaoxiang.diagnosis.service;
 
+import com.google.gson.reflect.TypeToken;
+import com.yaoxiang.diagnosis.config.Constants;
 import com.yaoxiang.diagnosis.entity.*;
+import com.yaoxiang.diagnosis.model.Answer;
+import com.yaoxiang.diagnosis.model.AnswerContrast;
+import com.yaoxiang.diagnosis.model.SpecialMindVo;
 import com.yaoxiang.diagnosis.util.CommonUtil;
+import com.yaoxiang.diagnosis.util.NumberUtil;
+import com.yaoxiang.diagnosis.util.ObjectUtil;
 import io.swagger.models.auth.In;
 import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
@@ -12,6 +19,8 @@ import javax.annotation.Resource;
 import javax.transaction.Transactional;
 import java.util.*;
 import java.util.function.Function;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 
 @Service
@@ -29,23 +38,27 @@ public class SpecialReportService {
     @Resource
     private SpecialKnowledgeService specialKnowledgeService;
 
+    @Resource
+    private SpecialMindService specialMindService;
+
     private static final Logger logger = LoggerFactory.getLogger(SpecialReportService.class);
 
-    public SpecialResult generate(Long pid, Long uid) {
-        Paper paper = paperService.getOnePaper(pid);
-        if (paper == null) {
-            logger.error("未找到试卷 pid={}", pid);
-            return null;
-        }
-        PaperCommit commit = commitService.getPaperCommit(pid, uid);
-        if (commit == null) {
-            logger.error("用户未提交 pid={},uid={}", pid, uid);
-            return null;
-        }
-        return generate(commit, paper);
-    }
+//    public SpecialResult generate(Long pid, Long uid) {
+//        Paper paper = paperService.getOnePaper(pid);
+//        if (paper == null) {
+//            logger.error("未找到试卷 pid={}", pid);
+//            return null;
+//        }
+//        PaperCommit commit = commitService.getPaperCommit(pid, uid);
+//        if (commit == null) {
+//            logger.error("用户未提交 pid={},uid={}", pid, uid);
+//            return null;
+//        }
+//        return generate(commit, paper);
+//    }
 
     public SpecialResult generate2(Long pid, Long uid) {
+        logger.info("正在生成专项诊断报告");
         Paper paper = paperService.getOnePaper(pid);
         if (paper == null) {
             logger.error("未找到试卷 pid={}", pid);
@@ -61,7 +74,7 @@ public class SpecialReportService {
 
     @Transactional(rollbackOn = Exception.class)
     public SpecialResult generate(PaperCommit commit, Paper paper) {
-        PaperResult result = paperResultService.findByPidAndUid(commit.getPid(), commit.getUid());
+        PaperResult result = paperResultService.findByPidAndUid(commit.getPid(), commit.getUid()).get(0);
         List<SpecialKnowledge> list = specialKnowledgeService.list(paper.getSubjectId(), paper.getGrade());
         //找出叶子节点
         Map<String, SpecialKnowledge> map = list.stream().filter(s -> s.getCode() != null)
@@ -111,7 +124,7 @@ public class SpecialReportService {
     }
 
     public SpecialResult generate2(PaperCommit commit, Paper paper) {
-        PaperResult result = paperResultService.findByPidAndUid(commit.getPid(), commit.getUid());
+        PaperResult result = paperResultService.findByPidAndUid(commit.getPid(), commit.getUid()).get(0);
         List<SpecialKnowledge> list = specialKnowledgeService.listByPid(paper.getId());
 
         if (CommonUtil.isEmpty(list)) {
@@ -127,8 +140,10 @@ public class SpecialReportService {
         List<Long> collects = Arrays.stream(collect.split(","))
                 .map(Long::parseLong).collect(Collectors.toList());
 
+        boolean complexMaster = list.stream().anyMatch(s -> Constants.SPECIAL_MASTER_STATUS.contains(s.getContent()));
+
         for (SpecialKnowledge knowledge : list) {
-            //过滤掉非叶子节点
+            //过滤掉非叶子节点,或者叶子节点为null的知识点
             if (StringUtils.isBlank(knowledge.getQids())) {
                 continue;
             }
@@ -139,11 +154,21 @@ public class SpecialReportService {
             knowledge.setQuestionNum(number.size());
             number.retainAll(collects);
             knowledge.setCollectNum(number.size());
-
+            if (knowledge.getQuestionNum() > 0) {
+                double master = knowledge.getCollectNum() * 100.0 / knowledge.getQuestionNum();
+                knowledge.setMaster(NumberUtil.format(master));
+                if (master < 80) {
+                    knowledge.setMasterStatus(Constants.SPECIAL_KNOWLEDGE_UNMASTER);
+                }
+            }
         }
-        List<SpecialKnowledge> tree = specialKnowledgeService.toTree(list);
-        //统计结果并且剪枝,剪掉>3的层级
         specialKnowledgeService.calcCount(list);
+        if (complexMaster) {
+            logger.info("计算认识理解应用情况,pid={},grade={},subjectId={}", paper.getId(), paper.getGrade(), paper.getSubjectId());
+            specialKnowledgeService.calcComplex(list);
+        }
+        //统计结果并且剪枝,剪掉>3的层级
+        List<SpecialKnowledge> tree = specialKnowledgeService.toTree(list);
 
         logger.info(tree.toString());
         SpecialResult r = new SpecialResult();
@@ -158,6 +183,10 @@ public class SpecialReportService {
         return r;
     }
 
+    private void calcMind(List<SpecialMind> list) {
+
+    }
+
     private Integer getCount(List<Question> qs, List<Integer> collects) {
         int count = 0;
         for (Question q : qs) {
@@ -168,4 +197,106 @@ public class SpecialReportService {
         return count;
     }
 
+    public List<SpecialMindVo> generateMind(Long pid, Long uid) {
+        logger.info("正在生成专项诊断报告");
+        Paper paper = paperService.getOnePaper(pid);
+        if (paper == null) {
+            logger.error("未找到试卷 pid={}", pid);
+            return null;
+        }
+        PaperCommit commit = commitService.getPaperCommit(pid, uid);
+        if (commit == null) {
+            logger.error("用户未提交 pid={},uid={}", pid, uid);
+            return null;
+        }
+        return generateMind(commit, paper);
+    }
+
+    public List<SpecialMindVo> generateMind(PaperCommit commit, Paper paper) {
+        PaperResult result = paperResultService.findByPidAndUid(commit.getPid(), commit.getUid()).get(0);
+        List<SpecialMind> list = specialMindService.findByPid(paper.getId());
+        if (CommonUtil.isEmpty(list)) {
+            logger.error("未上传专项诊断思维过程,subjectId={},grade={}", paper.getSubjectId(), paper.getGrade());
+            return null;
+        }
+        String contrast = result.getWrongAnswerContrast();
+        List<AnswerContrast> contrasts = convertAnswerContrast(contrast);
+        if (CommonUtil.isEmpty(contrasts)) {
+            logger.info("没有错题");
+        }
+        Map<Integer, String> map = contrasts.stream().collect(Collectors.toMap(AnswerContrast::getNumber, AnswerContrast::getOptions));
+        //答对的选项
+        Pattern pattern = Pattern.compile("(\\d+)");
+        for (SpecialMind mind : list) {
+            String qids = mind.getQids();
+            if (StringUtils.isBlank(qids)) {
+                logger.error("该问题没有考,请检查,pid={},content={}", paper.getId(), mind.getContent());
+                continue;
+            }
+            String[] qidss = qids.split(",");
+            mind.setCollectNum(qidss.length);
+            mind.setQuestionNum(qidss.length);
+
+            for (String s : qidss) {
+                int number = 0;
+                if (s.matches("\\d+[A-E]")) {
+                    Matcher matcher = pattern.matcher(s);
+                    if (matcher.find()) {
+                        number = Integer.parseInt(matcher.group());
+                    } else {
+                        logger.error("未检测到题号,qids={}", qids);
+                        continue;
+                    }
+                } else {
+                    number = Integer.parseInt(s);
+                }
+                if (map.containsKey(number) && StringUtils.isBlank(map.get(number))) {
+                    //没做题
+                    mind.setCollectNum(mind.getCollectNum() - 1);
+                } else if (map.containsKey(number)) {
+                    String options = map.get(number);
+                    if (s.contains(options)) {
+                        mind.setCollectNum(mind.getCollectNum() - 1);
+                    }
+                }
+            }
+            //设置这个问题有没有错误
+            mind.setMistake(!mind.getQuestionNum().equals(mind.getCollectNum()));
+        }
+        Map<String, List<SpecialMind>> group = list.stream().collect(Collectors.groupingBy(SpecialMind::getStep));
+        List<SpecialMindVo> vos = new ArrayList<>();
+        for (Map.Entry<String, List<SpecialMind>> entry : group.entrySet()) {
+            String step = entry.getKey();
+            List<SpecialMind> minds = entry.getValue();
+            int collectNum = 0;
+            int questionNum = 0;
+            for (SpecialMind mind : minds) {
+                collectNum += mind.getCollectNum();
+                questionNum += mind.getQuestionNum();
+            }
+            if (questionNum == 0) {
+                logger.error("一整个步骤都没考");
+                continue;
+            }
+            SpecialMindVo vo = new SpecialMindVo();
+            double master = collectNum * 100.0 / questionNum;
+            vo.setMasterStatus("red");
+            if (master >= 85) {
+                vo.setMasterStatus("green");
+            } else if (master >= 50) {
+                vo.setMasterStatus("yellow");
+            }
+            vo.setMaster(NumberUtil.format(master));
+            vo.setMinds(minds);
+            vo.setStep(step);
+            vo.setSort(minds.get(0).getSort());
+            vos.add(vo);
+        }
+        return vos;
+    }
+
+    private List<AnswerContrast> convertAnswerContrast(String json) {
+        return ObjectUtil.getGson().fromJson(json, new TypeToken<List<AnswerContrast>>() {
+        }.getType());
+    }
 }

+ 67 - 3
src/main/java/com/yaoxiang/diagnosis/word/KnowledgeUtil.java

@@ -1,6 +1,7 @@
 package com.yaoxiang.diagnosis.word;
 
 import com.yaoxiang.diagnosis.entity.SpecialKnowledge;
+import com.yaoxiang.diagnosis.entity.SpecialMind;
 import com.yaoxiang.diagnosis.entity.SubjectKnowledge;
 import com.yaoxiang.diagnosis.model.MatterVo;
 import org.apache.commons.lang3.StringUtils;
@@ -13,6 +14,8 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import static com.yaoxiang.diagnosis.config.Constants.SPECIAL_MASTER_STATUS;
+
 public class KnowledgeUtil {
 
     public static final int START_ROW = 2;
@@ -218,6 +221,11 @@ public class KnowledgeUtil {
             XSSFRow row = sheet.getRow(i);
             for (int j = 0; j < row.getLastCellNum() - 1; j++) {
                 String content = row.getCell(j).getStringCellValue();
+                String rawContent = content;
+                //对有认识、理解和应用的特色处理
+                if (SPECIAL_MASTER_STATUS.contains(content)) {
+                    content = row.getCell(j - 1).getStringCellValue() + content;
+                }
                 if (map.containsKey(content)) {
                     continue;
                 }
@@ -228,8 +236,10 @@ public class KnowledgeUtil {
                 }
                 if (j == row.getLastCellNum() - 2) {
                     XSSFCell cell = row.getCell(j + 1);
-                    if (CellType.NUMERIC == cell.getCellTypeEnum()) {
-                        k.setQids(String.valueOf(cell.getNumericCellValue()));
+                    if (CellType.BLANK == cell.getCellTypeEnum()) {
+                        k.setQids("");
+                    } else if (CellType.NUMERIC == cell.getCellTypeEnum()) {
+                        k.setQids(String.valueOf((int) cell.getNumericCellValue()));
                     } else {
                         k.setQids(cell.getStringCellValue());
                     }
@@ -238,7 +248,7 @@ public class KnowledgeUtil {
                 k.setGrade(grade);
                 k.setPid(pid);
                 k.setSubjectId(subjectId);
-                k.setContent(content);
+                k.setContent(rawContent);
                 map.put(content, k);
                 result.add(k);
             }
@@ -246,4 +256,58 @@ public class KnowledgeUtil {
         return result;
     }
 
+    public static List<SpecialMind> importSpecialMind(Long subjectId, String grade, byte[] data, Long pid) throws Exception {
+        XSSFWorkbook book = new XSSFWorkbook(new ByteArrayInputStream(data));
+        XSSFSheet sheet = book.getSheetAt(0);
+        List<SpecialMind> result = new ArrayList<>();
+        //先来做个填充
+        for (int i = 1; i < sheet.getLastRowNum(); i++) {
+            XSSFRow row = sheet.getRow(i);
+            XSSFCell cell = row.getCell(0);
+            String content = cell.getStringCellValue();
+            if (StringUtils.isBlank(content)) {
+                cell.setCellValue(sheet.getRow(i - 1).getCell(0).getStringCellValue());
+            }
+        }
+        for (int i = 1; i <= sheet.getLastRowNum(); i++) {
+            XSSFRow row = sheet.getRow(i);
+            SpecialMind mind = new SpecialMind();
+            String step = row.getCell(0).getStringCellValue();
+            mind.setSort(toSort(step));
+            mind.setStep(step);
+            mind.setContent(row.getCell(1).getStringCellValue());
+            XSSFCell cell = row.getCell(2);
+            String qids = "";
+            if (cell.getCellTypeEnum() == CellType.NUMERIC) {
+                qids = String.valueOf((int) cell.getNumericCellValue());
+            } else {
+                qids = cell.getStringCellValue();
+            }
+            mind.setQids(qids);
+            mind.setPid(pid);
+            mind.setGrade(grade);
+            mind.setSubjectId(subjectId);
+            result.add(mind);
+        }
+        return result;
+    }
+
+    private static Integer toSort(String step) {
+        //有点蠢
+        switch (step) {
+            case "第一步":
+                return 1;
+            case "第二步":
+                return 2;
+            case "第三步":
+                return 3;
+            case "第四步":
+                return 4;
+            case "第五步":
+                return 5;
+            case "第六步":
+                return 6;
+        }
+        return 0;
+    }
 }

+ 58 - 34
src/main/java/com/yaoxiang/diagnosis/word/WordService.java

@@ -50,42 +50,42 @@ public class WordService {
         topicTypes = Arrays.asList(topicType);
     }
 
-    public Question parseQuestion(Question question, byte[] data) {
-        XWPFDocument document = WordUtil.open(data);
-        Map<String, List<XWPFParagraph>> group = initMap(document.getParagraphs());
-        List<XWPFPictureData> pictures = document.getAllPictures();
-        pictures.forEach(d -> {
-            logger.debug("check sum " + d.getChecksum());
-            logger.debug("file name " + d.getFileName());
-        });
-        parseQuestion(question, group);
-        WordUtil.close(document);
-        return question;
-    }
-
-    public Question parseQuestion(Question q, List<XWPFParagraph> ps, Map<String, String> topic, PaperTemplate template, List<String> abilities) {
+//    public Question parseQuestion(Question question, byte[] data) {
+//        XWPFDocument document = WordUtil.open(data);
+//        Map<String, List<XWPFParagraph>> group = initMap(document.getParagraphs());
+//        List<XWPFPictureData> pictures = document.getAllPictures();
+//        pictures.forEach(d -> {
+//            logger.debug("check sum " + d.getChecksum());
+//            logger.debug("file name " + d.getFileName());
+//        });
+//        parseQuestion(question, group);
+//        WordUtil.close(document);
+//        return question;
+//    }
+
+    public Question parseQuestion(Question q, List<XWPFParagraph> ps, Map<String, String> topic, PaperTemplate template, Boolean useAbility) {
         logger.info("parsing question,pid={},section={},number={}", q.getPid(), q.getSection(), q.getNumber());
         Map<String, List<XWPFParagraph>> group = initGroup(ps, topic, template);
         //此次是否还需再处理一下?
         parseQuestion(q, group.get(topic.get(Constants.TOPIC_QUESTION)), template.getOptionPattern(), template.getPicturePattern());
         parseAnswer(q, group.get(topic.get(Constants.TOPIC_ANSWER)));
         parseTag(q, group.get(topic.get(Constants.TOPIC_TAG)));
-        parseAbility(q, group.get(topic.get(Constants.TOPIC_ABILITY)), abilities);
+        parseAbility(q, group.get(topic.get(Constants.TOPIC_ABILITY)), useAbility);
         logger.info("parse question finish,pid={},section={},number={}", q.getPid(), q.getSection(), q.getNumber());
         return q;
     }
 
-    private void parseQuestion(Question q, Map<String, List<XWPFParagraph>> group) {
-        logger.info("parsing question,pid={},section={},number={}", q.getPid(), q.getSection(), q.getNumber());
-        String[] a = {"A1", "A2", "A3", "A4", "A5"};
-        parseQuestion(q, group.get(Constants.TOPIC_QUESTION), "^[A-Z]\\.(.*)", "^#(Small|Middle|Large)#");
-        parseAnswer(q, group.get(Constants.TOPIC_ANSWER));
-        parseTag(q, group.get(Constants.TOPIC_TAG));
-        parseAbility(q, group.get(Constants.TOPIC_ABILITY), Arrays.asList(a));
-        parseCollect(q, group.get(Constants.TOPIC_EVALUATE_CORRECT));
-        parseWrong(q, group.get(Constants.TOPIC_EVALUATE_WRONG));
-        logger.info("parse question finish,pid={},section={},number={}", q.getPid(), q.getSection(), q.getNumber());
-    }
+//    private void parseQuestion(Question q, Map<String, List<XWPFParagraph>> group) {
+//        logger.info("parsing question,pid={},section={},number={}", q.getPid(), q.getSection(), q.getNumber());
+//        String[] a = {"A1", "A2", "A3", "A4", "A5"};
+//        parseQuestion(q, group.get(Constants.TOPIC_QUESTION), "^[A-Z]\\.(.*)", "^#(Small|Middle|Large)#");
+//        parseAnswer(q, group.get(Constants.TOPIC_ANSWER));
+//        parseTag(q, group.get(Constants.TOPIC_TAG));
+//        parseAbility(q, group.get(Constants.TOPIC_ABILITY), Arrays.asList(a));
+//        parseCollect(q, group.get(Constants.TOPIC_EVALUATE_CORRECT));
+//        parseWrong(q, group.get(Constants.TOPIC_EVALUATE_WRONG));
+//        logger.info("parse question finish,pid={},section={},number={}", q.getPid(), q.getSection(), q.getNumber());
+//    }
 
     private void parseQuestion(Question question, List<XWPFParagraph> ps, String optionPattern, String picturePattern) {
         List<QuestionOption> options = new ArrayList<>();
@@ -93,16 +93,14 @@ public class WordService {
         StringBuilder content = new StringBuilder();
         boolean hasFormula = false;
         for (XWPFParagraph p : ps) {
-            parsePicture(p, picturePattern);
-            //TODO 图片丢失
-            hasFormula = parseFormula(p);
+
             String text = p.getText();
             //清除掉#Small#
             text = text.replaceAll(picturePattern, "");
             if (text.matches(optionPattern)) {
                 //匹配到选项,至少有2个字符
                 QuestionOption option = initOption(i++, text);
-                String optionNoContent = String.format("parseQuestion,题号为%s的题目选项 %s 未检测到内容,题目内容为“%s”,请检查", question.getNumber(), text.charAt(0), content);
+                String optionNoContent = String.format("parseQuestion,题号为%s的题目选项 %s 未检测到内容,题目内容为“%s”,请检查选项结构", question.getNumber(), text, content);
                 Assert.hasText(option.getContent(), optionNoContent);
                 options.add(option);
             } else {
@@ -111,7 +109,7 @@ public class WordService {
         }
         String noContent = String.format("parseQuestion,题号为 %s 的题目未检测到题干,题目内容为 “%s” ,请检查", question.getNumber(), content);
         String noOptions = String.format("parseQuestion,题号为 %s 的题目未检测到选项,题目内容为 “%s” ,请检查", question.getNumber(), content);
-        String lostOptions = String.format("parseQuestion,题号为 %s 的题目检测到选项数量为 %s ,题目内容为 “%s” ,请检查", question.getNumber(), options.size(), content);
+        String lostOptions = String.format("parseQuestion,题号为 %s 的题目检测到选项数量为 %s ,题目内容为 “%s” ,请检查选项换行情况", question.getNumber(), options.size(), content);
         Assert.hasText(content.toString(), noContent);
         Assert.notEmpty(options, noOptions);
         //TODO 选项数量可能不止5个?
@@ -145,7 +143,7 @@ public class WordService {
         ps.stream().filter(p -> StringUtils.isNotBlank(p.getText())).forEach(p -> question.setTag(p.getText()));
     }
 
-    private void parseAbility(Question question, List<XWPFParagraph> ps, List<String> abilities) {
+    private void parseAbility(Question question, List<XWPFParagraph> ps, Boolean useAbility) {
         List<AbilityScore> list = new ArrayList<>();
         Map<String, Double> json = new HashMap<>();
         //先手动设置1分
@@ -177,7 +175,9 @@ public class WordService {
 //                question.setConversion(score);
 //            }
         }
-        question.setJsonScore(ObjectUtil.object2Json(json));
+        if (useAbility != null && useAbility) {
+            question.setJsonScore(ObjectUtil.object2Json(json));
+        }
         question.setScores(list);
 
     }
@@ -257,7 +257,7 @@ public class WordService {
         QuestionOption option = new QuestionOption();
         option.setOindex(index);
         //去掉选项中的#A#
-        option.setContent(content.substring(3));
+        option.setContent("<p>" + content.substring(3) + "</p>");
         option.setCreatetime(new Date());
         option.setCorrect(false);
         return option;
@@ -419,4 +419,28 @@ public class WordService {
 
     }
 
+    public void parseSubScript(XWPFParagraph paragraph) {
+        Map<Integer, String> insert = new HashMap<>();
+        List<XWPFRun> runs = paragraph.getRuns();
+        for (int i = 0; i < runs.size(); i++) {
+            switch (runs.get(i).getSubscript()) {
+                case BASELINE:
+                    break;
+                case SUBSCRIPT:
+                    insert.put(i, "<sub>");
+                    insert.put(i + 1, "</sub>");
+                    break;
+                case SUPERSCRIPT:
+                    insert.put(i, "<sup>");
+                    insert.put(i + 1, "</sup>");
+                    break;
+            }
+        }
+        int i = 0;
+        for (Map.Entry<Integer, String> entry : insert.entrySet()) {
+            XWPFRun run = paragraph.insertNewRun(entry.getKey() + i++);
+            run.setText(entry.getValue());
+        }
+    }
+
 }

+ 0 - 15
src/main/resources/application-cloud.properties

@@ -1,16 +1,6 @@
 server.port=8080
-#serverAddress=172.18.129.124
-#serverAddress=119.23.22.31
-#serverOutsideAddress=www.yaoxiangedu.com
-
-#uploadPattern=/upload/**
-#baseLocation=/opt/diagnosis/${server.port}
-#baseLocation=/tmp/diagnosis/data
-#uploadLocation=${baseLocation}/upload/
-#spring.servlet.multipart.location=${baseLocation}/uploadTemp/
 spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/
 
-#spring.datasource.url=jdbc:mysql://47.104.200.54:3306/OnlinePapers?useUnicode=true&characterEncoding=utf-8
 spring.datasource.url=jdbc:mysql://mysql:3306/OnlinePapers?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
 spring.datasource.username=onlinepapers
 spring.datasource.password=134679258Aa_
@@ -20,11 +10,6 @@ spring.redis.password=134679258Aa_
 spring.redis.host=redis-master
 spring.redis.port=6379
 
-#不使用localFileService
-#docpath=/root/doc/
-#local.uploadUrl=http://${serverOutsideAddress}:9000/file/upload
-#local.downloadUrl=http://${serverOutsideAddress}:9000/file/download/
-
 #外部要使用,所以不能为内部地址
 minio.url=https://minio.yaoxiangedu.com/
 minio.secure=true

+ 0 - 9
src/main/resources/application-dev.properties

@@ -1,12 +1,6 @@
 server.port=8085
 serverAddress=119.23.22.31
 
-#uploadPattern=/upload/**
-#baseLocation=diagnosis
-#baseLocation=/Users/feick/IdeaProjects/yaoxiang/diagnosis
-#baseLocation=/d:/diagnosis
-#uploadLocation=${baseLocation}/upload/
-#spring.servlet.multipart.location=${baseLocation}/uploadTemp/
 spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/
 
 
@@ -31,11 +25,8 @@ spring.redis.database=0
 spring.redis.password=134679258Aa_
 spring.redis.host=${serverAddress}
 spring.redis.port=32578
-#local.uploadUrl=http://${serverAddress}:9001/file/upload
-#local.downloadUrl=http://${serverAddress}:9001/file/download/
 
 minio.url=http://${serverAddress}:30240/
-#minio.url=https://minio.yaoxiangedu.com/
 minio.secure=false
 minio.buckets=dev
 minio.defaultBucket=dev

+ 0 - 8
src/main/resources/application-docker.properties

@@ -1,13 +1,8 @@
 server.port=8080
 serverAddress=119.23.22.31
 
-#uploadPattern=/upload/**
-#baseLocation=/tmp/diagnosis/data
-#uploadLocation=${baseLocation}/upload/
-#spring.servlet.multipart.location=${baseLocation}/uploadTemp/
 spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/
 
-#spring.datasource.url=jdbc:mysql://47.104.200.54:3306/OnlinePapers?useUnicode=true&characterEncoding=utf-8
 spring.datasource.url=jdbc:mysql://${serverAddress}:30875/OnlinePapers?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
 spring.datasource.username=onlinepapers
 spring.datasource.password=134679258Aa_
@@ -16,9 +11,6 @@ spring.redis.database=0
 spring.redis.password=134679258Aa_
 spring.redis.host=redis-master
 spring.redis.port=6379
-#local.uploadUrl=http://${serverAddress}:9001/file/upload
-#local.downloadUrl=http://${serverAddress}:9001/file/download/
-
 
 minio.url=http://${serverAddress}:30240/
 minio.secure=false

+ 0 - 11
src/main/resources/application-prod.properties

@@ -1,16 +1,9 @@
 server.port=8080
-#serverAddress=172.18.129.124
 serverAddress=119.23.22.31
 serverOutsideAddress=www.yaoxiangedu.com
 
-#uploadPattern=/upload/**
-#baseLocation=/opt/diagnosis/${server.port}
-#baseLocation=d:/diagnosis
-#uploadLocation=${baseLocation}/upload/
-#spring.servlet.multipart.location=${baseLocation}/uploadTemp/
 spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/
 
-#spring.datasource.url=jdbc:mysql://47.104.200.54:3306/OnlinePapers?useUnicode=true&characterEncoding=utf-8
 spring.datasource.url=jdbc:mysql://${serverAddress}:3306/OnlinePapers?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
 spring.datasource.username=root
 spring.datasource.password=134679258Aa_
@@ -20,10 +13,6 @@ spring.redis.password=134679258Aa_
 spring.redis.host=${serverAddress}
 spring.redis.port=6379
 
-#docpath=/root/doc/
-local.uploadUrl=http://${serverOutsideAddress}:9000/file/upload
-local.downloadUrl=http://${serverOutsideAddress}:9000/file/download/
-
 minio.url=http://${serverAddress}:30240/
 minio.secure=false
 minio.buckets=prod

+ 0 - 4
src/main/resources/application.properties

@@ -1,8 +1,6 @@
 spring.profiles.active=dev
 logging.level.* = info
 logging.file=log/log.log
-#logging.pattern.console= %d{yyyy-MM-dd HH:mm:ss} - %msg%n
-#logging.pattern.file= %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
 
 spring.servlet.multipart.enabled=true
 spring.servlet.multipart.max-file-size=50MB
@@ -37,7 +35,5 @@ spring.data.redis.repositories.enabled=false
 #server.tomcat.accesslog.suffix=.log
 
 #ÆôÓÃswagger
-swagger.enabled=true
 web.loginPage=/login
 web.logoutUrl=/logout
-#web.permitUrls=/login,/logout,/**/*.js,/**/*.png,/**/*.jpg,/**/*.css

+ 18 - 0
src/test/java/com/yaoxiang/diagnosis/service/StringTest.java

@@ -6,6 +6,8 @@ import org.junit.Test;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 public class StringTest {
 
@@ -56,4 +58,20 @@ public class StringTest {
         System.out.println(a);
         System.out.println(b);
     }
+
+    @Test
+    public void test1(){
+        String a = "65C";
+        String b = "65ABC";
+        String c = "65ABEF";
+        System.out.println(a.matches("\\d+[A-E]"));
+        System.out.println(b.matches("\\d+[A-E]+"));
+        System.out.println(c.matches("\\d+[A-E]+"));
+
+        Pattern pattern = Pattern.compile("\\d+");
+        Matcher matcher = pattern.matcher(a);
+        System.out.println(matcher.find());
+        System.out.println(matcher.group());
+
+    }
 }

+ 79 - 1
src/test/java/com/yaoxiang/diagnosis/service/UploadTest.java

@@ -1,9 +1,18 @@
 package com.yaoxiang.diagnosis.service;
 
 
+import com.microsoft.schemas.office.office.OLEObjectDocument;
 import com.yaoxiang.diagnosis.entity.Paper;
 import com.yaoxiang.diagnosis.entity.PaperTemplate;
 import com.yaoxiang.diagnosis.util.CommonUtil;
+import com.yaoxiang.diagnosis.util.ObjectUtil;
+import com.yaoxiang.diagnosis.word.WordUtil;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.poi.xwpf.usermodel.VerticalAlign;
+import org.apache.poi.xwpf.usermodel.XWPFDocument;
+import org.apache.poi.xwpf.usermodel.XWPFParagraph;
+import org.apache.poi.xwpf.usermodel.XWPFRun;
 import org.junit.Test;
 import org.springframework.core.io.ByteArrayResource;
 import org.springframework.http.HttpEntity;
@@ -14,7 +23,8 @@ import org.springframework.util.LinkedMultiValueMap;
 import org.springframework.util.MultiValueMap;
 import org.springframework.web.client.RestTemplate;
 
-import java.io.File;
+import java.io.*;
+import java.util.*;
 
 public class UploadTest {
 
@@ -67,4 +77,72 @@ public class UploadTest {
         System.out.println(paper.getCode());
         System.out.println(paper.getGrade());
     }
+
+    @Test
+    public void test3() throws Exception {
+        XWPFDocument document = WordUtil.open("doc/sub.docx");
+        List<XWPFParagraph> paragraphs = document.getParagraphs();
+        for (XWPFParagraph paragraph : paragraphs) {
+            List<XWPFRun> runs = paragraph.getRuns();
+
+            System.out.println("before parse " + paragraph.getText());
+            System.out.println("runs size " + runs.size());
+
+            Map<Integer, String> insert = new HashMap<>();
+            for (int i = 0; i < runs.size(); i++) {
+                switch (runs.get(i).getSubscript()) {
+                    case BASELINE:
+                        break;
+                    case SUBSCRIPT:
+                        insert.put(i, "<sub>");
+                        insert.put(i + 1, "</sub>");
+                        break;
+                    case SUPERSCRIPT:
+                        insert.put(i, "<sup>");
+                        insert.put(i + 1, "</sup>");
+                        break;
+                }
+            }
+            int i = 0;
+            for (Map.Entry<Integer, String> entry : insert.entrySet()) {
+                XWPFRun run = paragraph.insertNewRun(entry.getKey() + i++);
+                run.setText(entry.getValue());
+            }
+
+            System.out.println("after parse " + paragraph.getText());
+            System.out.println("runs size " + runs.size());
+
+        }
+        //OLEObject
+//        OLEObjectDocument
+    }
+
+    @Test
+    public void test4() throws Exception {
+        XWPFDocument document = WordUtil.open("doc/sub.docx");
+        List<XWPFParagraph> paragraphs = document.getParagraphs();
+        for (XWPFParagraph paragraph : paragraphs) {
+            List<XWPFRun> runs = paragraph.getRuns();
+            int i = 0;
+            for (XWPFRun run : runs) {
+                System.out.println("run = " + i + " " + run.getText(0));
+                i++;
+            }
+//            paragraph.insertNewRun(0).setText("asdf");
+            System.out.println(paragraph.getText());
+        }
+    }
+
+
+    public static <T> List<T> deepCopy(List<T> src) throws IOException, ClassNotFoundException {
+        ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream(byteOut);
+        out.writeObject(src);
+
+        ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
+        ObjectInputStream in = new ObjectInputStream(byteIn);
+        @SuppressWarnings("unchecked")
+        List<T> dest = (List<T>) in.readObject();
+        return dest;
+    }
 }

+ 22 - 7
src/test/java/com/yaoxiang/diagnosis/service/WordServiceTest.java

@@ -3,11 +3,11 @@ package com.yaoxiang.diagnosis.service;
 import com.yaoxiang.diagnosis.config.Constants;
 import com.yaoxiang.diagnosis.util.CommonUtil;
 import com.yaoxiang.diagnosis.word.WordUtil;
+import fr.opensagres.poi.xwpf.converter.xhtml.XHTMLConverter;
+import fr.opensagres.poi.xwpf.converter.xhtml.internal.XHTMLMapper;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.poi.xwpf.usermodel.XWPFDocument;
-import org.apache.poi.xwpf.usermodel.XWPFParagraph;
-import org.apache.poi.xwpf.usermodel.XWPFPicture;
-import org.apache.poi.xwpf.usermodel.XWPFRun;
+import org.apache.poi.POIXMLDocumentPart;
+import org.apache.poi.xwpf.usermodel.*;
 import org.apache.xmlbeans.SchemaType;
 import org.apache.xmlbeans.XmlCursor;
 import org.apache.xmlbeans.XmlObject;
@@ -82,9 +82,24 @@ public class WordServiceTest {
     }
 
     @Test
-    public void test222() {
-        XWPFDocument document = WordUtil.open("topic_table.docx");
-        for (XWPFParagraph paragraph : document.getParagraphs()) {
+    public void test222() throws Exception{
+        XWPFDocument document = WordUtil.open("doc/table.docx");
+        List<XWPFParagraph> list = document.getParagraphs();
+        List<IBodyElement> bodyElements = document.getBodyElements();
+        int i=0;
+//        XHTMLMapper mapper = new XHTMLMapper(document,null,null);
+//        mapper.start();
+
+        for (IBodyElement element:bodyElements){
+            if (element instanceof XWPFParagraph){
+                System.out.println(i+"par " + ((XWPFParagraph) element).getText());
+            }else if(element instanceof XWPFTable){
+                XWPFTable table = (XWPFTable) element;
+                System.out.println(i+"table " + table.getText());
+            }
+            i++;
+        }
+        for (XWPFParagraph paragraph : list) {
             System.out.println(paragraph.getText());
         }
     }