wangliang 1 éve
szülő
commit
076130d869
25 módosított fájl, 1223 hozzáadás és 380 törlés
  1. 13 1
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/bean/dto/report/CourseTargetDto.java
  2. 7 7
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/bean/dto/report/ReportCommonDto.java
  3. 13 1
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/bean/dto/report/ReportExamStudentTargetDto.java
  4. 155 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/bean/result/report/word/CourseBasicBean.java
  5. 124 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/bean/result/report/word/CourseReportBean.java
  6. 46 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/bean/result/report/word/CourseTargetTableBean1.java
  7. 85 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/bean/result/report/word/CourseTargetTableBean2.java
  8. 83 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/bean/result/report/word/CourseTargetTableBean3.java
  9. 83 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/bean/result/report/word/CourseTargetTableBean4.java
  10. 74 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/bean/result/report/word/ExamStudentScoreBean.java
  11. 104 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/bean/result/report/word/ExamStudentTableBean.java
  12. 17 18
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/TCFinalScoreServiceImpl.java
  13. 15 15
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/TCUsualScoreServiceImpl.java
  14. 3 5
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/TRBasicInfoServiceImpl.java
  15. 1 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/TRExamStudentServiceImpl.java
  16. 0 227
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/util/excel/BasicExcelListener.java
  17. 0 53
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/util/excel/BasicExcelRow.java
  18. 346 3
      distributed-print/src/main/java/com/qmth/distributed/print/api/TRBasicInfoController.java
  19. 8 8
      distributed-print/src/main/resources/application.properties
  20. BIN
      distributed-print/src/main/resources/static/course_degree_report.docx
  21. 13 12
      pom.xml
  22. 6 6
      teachcloud-common/pom.xml
  23. 11 14
      teachcloud-common/src/main/java/com/qmth/teachcloud/common/util/ExcelUtil.java
  24. 7 6
      teachcloud-common/src/main/java/com/qmth/teachcloud/common/util/excel/ExcelWriter.java
  25. 9 4
      teachcloud-task/src/main/resources/application.properties

+ 13 - 1
distributed-print-business/src/main/java/com/qmth/distributed/print/business/bean/dto/report/CourseTargetDto.java

@@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
 import io.swagger.annotations.ApiModelProperty;
+import org.jetbrains.annotations.NotNull;
 
 import java.io.Serializable;
 import java.util.List;
@@ -16,7 +17,7 @@ import java.util.List;
  * @Date: 2024/2/26
  */
 @JsonInclude(JsonInclude.Include.NON_NULL)
-public class CourseTargetDto implements Serializable {
+public class CourseTargetDto implements Serializable, Comparable<CourseTargetDto> {
 
     @JsonSerialize(using = ToStringSerializer.class)
     @ApiModelProperty(value = "课程目标id")
@@ -142,4 +143,15 @@ public class CourseTargetDto implements Serializable {
     public void setEvaluationDesc(String evaluationDesc) {
         this.evaluationDesc = evaluationDesc;
     }
+
+    @Override
+    public int compareTo(@NotNull CourseTargetDto o) {
+        if (o.getTargetId().longValue() < this.getTargetId().longValue()) {
+            return 1;
+        } else if (o.getTargetId().longValue() > this.getTargetId().longValue()) {
+            return -1;
+        } else {
+            return 0;
+        }
+    }
 }

+ 7 - 7
distributed-print-business/src/main/java/com/qmth/distributed/print/business/bean/dto/report/ReportCommonDto.java

@@ -24,7 +24,7 @@ public class ReportCommonDto implements Serializable {
     private String courseCode;
 
     @ApiModelProperty(value = "课程名称")
-    private String couserName;
+    private String courseName;
 
     @ApiModelProperty(value = "试卷编码")
     private String paperNumber;
@@ -33,10 +33,10 @@ public class ReportCommonDto implements Serializable {
 
     }
 
-    public ReportCommonDto(Long examId, String courseCode, String couserName, String paperNumber) {
+    public ReportCommonDto(Long examId, String courseCode, String courseName, String paperNumber) {
         this.examId = examId;
         this.courseCode = courseCode;
-        this.couserName = couserName;
+        this.courseName = courseName;
         this.paperNumber = paperNumber;
     }
 
@@ -56,12 +56,12 @@ public class ReportCommonDto implements Serializable {
         this.courseCode = courseCode;
     }
 
-    public String getCouserName() {
-        return couserName;
+    public String getCourseName() {
+        return courseName;
     }
 
-    public void setCouserName(String couserName) {
-        this.couserName = couserName;
+    public void setCourseName(String courseName) {
+        this.courseName = courseName;
     }
 
     public String getPaperNumber() {

+ 13 - 1
distributed-print-business/src/main/java/com/qmth/distributed/print/business/bean/dto/report/ReportExamStudentTargetDto.java

@@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
 import io.swagger.annotations.ApiModelProperty;
+import org.jetbrains.annotations.NotNull;
 
 import java.io.Serializable;
 
@@ -15,7 +16,7 @@ import java.io.Serializable;
  * @Date: 2024/2/26
  */
 @JsonInclude(JsonInclude.Include.NON_NULL)
-public class ReportExamStudentTargetDto implements Serializable {
+public class ReportExamStudentTargetDto implements Serializable, Comparable<ReportExamStudentTargetDto> {
 
     @ApiModelProperty(value = "课程目标id")
     @JsonSerialize(using = ToStringSerializer.class)
@@ -83,4 +84,15 @@ public class ReportExamStudentTargetDto implements Serializable {
     public void setUsualScore(ReportExamStudentUsualScoreDto usualScore) {
         this.usualScore = usualScore;
     }
+
+    @Override
+    public int compareTo(@NotNull ReportExamStudentTargetDto o) {
+        if (o.getTargetId().longValue() < this.getTargetId().longValue()) {
+            return 1;
+        } else if (o.getTargetId().longValue() > this.getTargetId().longValue()) {
+            return -1;
+        } else {
+            return 0;
+        }
+    }
 }

+ 155 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/bean/result/report/word/CourseBasicBean.java

@@ -0,0 +1,155 @@
+package com.qmth.distributed.print.business.bean.result.report.word;
+
+import io.swagger.annotations.ApiModelProperty;
+
+import java.io.Serializable;
+
+/**
+ * @Description: 课程基本信息bean
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2024/1/31
+ */
+public class CourseBasicBean implements Serializable {
+
+    @ApiModelProperty(name = "课程名称")
+    String courseName;
+
+    @ApiModelProperty(name = "课程编码")
+    String courseCode;
+
+    @ApiModelProperty(name = "课程英文名称")
+    String courseEnName;
+
+    @ApiModelProperty(name = "课程性质")
+    String courseType;
+
+    @ApiModelProperty(name = "总学时/学分")
+    String credit;
+
+    @ApiModelProperty(name = "理论/实验")
+    String theory;
+
+    @ApiModelProperty(name = "评价样本范围")
+    String sampleRange;
+
+    @ApiModelProperty(name = "评价人")
+    String people;
+
+    @ApiModelProperty(name = "评价时间")
+    String date;
+
+    @ApiModelProperty(name = "课程目标")
+    String courseTarget;
+
+    @ApiModelProperty(name = "课程目标数")
+    String courseTargetNum;
+
+    public CourseBasicBean() {
+
+    }
+
+    public CourseBasicBean(String courseName, String courseCode, String courseEnName, String courseType, String credit
+            , String theory, String sampleRange, String people, String date, String courseTarget, String courseTargetNum) {
+        this.courseName = courseName;
+        this.courseCode = courseCode;
+        this.courseEnName = courseEnName;
+        this.courseType = courseType;
+        this.credit = credit;
+        this.theory = theory;
+        this.sampleRange = sampleRange;
+        this.people = people;
+        this.date = date;
+        this.courseTarget = courseTarget;
+        this.courseTargetNum = courseTargetNum;
+    }
+
+    public String getCourseTarget() {
+        return courseTarget;
+    }
+
+    public void setCourseTarget(String courseTarget) {
+        this.courseTarget = courseTarget;
+    }
+
+    public String getCourseTargetNum() {
+        return courseTargetNum;
+    }
+
+    public void setCourseTargetNum(String courseTargetNum) {
+        this.courseTargetNum = courseTargetNum;
+    }
+
+    public String getCourseName() {
+        return courseName;
+    }
+
+    public void setCourseName(String courseName) {
+        this.courseName = courseName;
+    }
+
+    public String getCourseCode() {
+        return courseCode;
+    }
+
+    public void setCourseCode(String courseCode) {
+        this.courseCode = courseCode;
+    }
+
+    public String getCourseEnName() {
+        return courseEnName;
+    }
+
+    public void setCourseEnName(String courseEnName) {
+        this.courseEnName = courseEnName;
+    }
+
+    public String getCourseType() {
+        return courseType;
+    }
+
+    public void setCourseType(String courseType) {
+        this.courseType = courseType;
+    }
+
+    public String getCredit() {
+        return credit;
+    }
+
+    public void setCredit(String credit) {
+        this.credit = credit;
+    }
+
+    public String getTheory() {
+        return theory;
+    }
+
+    public void setTheory(String theory) {
+        this.theory = theory;
+    }
+
+    public String getSampleRange() {
+        return sampleRange;
+    }
+
+    public void setSampleRange(String sampleRange) {
+        this.sampleRange = sampleRange;
+    }
+
+    public String getPeople() {
+        return people;
+    }
+
+    public void setPeople(String people) {
+        this.people = people;
+    }
+
+    public String getDate() {
+        return date;
+    }
+
+    public void setDate(String date) {
+        this.date = date;
+    }
+}

+ 124 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/bean/result/report/word/CourseReportBean.java

@@ -0,0 +1,124 @@
+package com.qmth.distributed.print.business.bean.result.report.word;
+
+import com.deepoove.poi.data.TableRenderData;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.io.Serializable;
+
+/**
+ * @Description: 课程报告bean
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2024/1/31
+ */
+public class CourseReportBean implements Serializable {
+
+    @ApiModelProperty(name = "标题1")
+    String title1;
+
+    @ApiModelProperty(name = "考生标题1")
+    String examStudentTitle1;
+
+    @ApiModelProperty(name = "考生标题2")
+    String examStudentTitle2;
+
+    @ApiModelProperty(name = "课程bean")
+    CourseBasicBean courseBasicBean;
+
+    @ApiModelProperty(name = "课程报告表格1bean-课程目标与毕业要求指标点的对应关系")
+    TableRenderData courseTargetTable1;
+
+    @ApiModelProperty(name = "课程报告表格2bean-课程目标达成考核/评价环节及目标分值")
+    TableRenderData courseTargetTable2;
+
+    @ApiModelProperty(name = "课程报告表格3bean-课程课后作业考核/评价内容及目标分值")
+    TableRenderData courseTargetTable3;
+
+    @ApiModelProperty(name = "课程报告表格4bean-课程期末考试考核/评价内容及目标分值")
+    TableRenderData courseTargetTable4;
+
+    @ApiModelProperty(name = "考生表格1bean")
+    TableRenderData examStudentTable1;
+
+    public CourseReportBean() {
+
+    }
+
+    public CourseReportBean(String title1, CourseBasicBean courseBasicBean) {
+        this.title1 = title1;
+        this.courseBasicBean = courseBasicBean;
+    }
+
+    public TableRenderData getExamStudentTable1() {
+        return examStudentTable1;
+    }
+
+    public void setExamStudentTable1(TableRenderData examStudentTable1) {
+        this.examStudentTable1 = examStudentTable1;
+    }
+
+    public TableRenderData getCourseTargetTable3() {
+        return courseTargetTable3;
+    }
+
+    public void setCourseTargetTable3(TableRenderData courseTargetTable3) {
+        this.courseTargetTable3 = courseTargetTable3;
+    }
+
+    public TableRenderData getCourseTargetTable4() {
+        return courseTargetTable4;
+    }
+
+    public void setCourseTargetTable4(TableRenderData courseTargetTable4) {
+        this.courseTargetTable4 = courseTargetTable4;
+    }
+
+    public String getExamStudentTitle1() {
+        return examStudentTitle1;
+    }
+
+    public void setExamStudentTitle1(String examStudentTitle1) {
+        this.examStudentTitle1 = examStudentTitle1;
+    }
+
+    public String getExamStudentTitle2() {
+        return examStudentTitle2;
+    }
+
+    public void setExamStudentTitle2(String examStudentTitle2) {
+        this.examStudentTitle2 = examStudentTitle2;
+    }
+
+    public String getTitle1() {
+        return title1;
+    }
+
+    public void setTitle1(String title1) {
+        this.title1 = title1;
+    }
+
+    public CourseBasicBean getCourseBasicBean() {
+        return courseBasicBean;
+    }
+
+    public void setCourseBasicBean(CourseBasicBean courseBasicBean) {
+        this.courseBasicBean = courseBasicBean;
+    }
+
+    public TableRenderData getCourseTargetTable1() {
+        return courseTargetTable1;
+    }
+
+    public void setCourseTargetTable1(TableRenderData courseTargetTable1) {
+        this.courseTargetTable1 = courseTargetTable1;
+    }
+
+    public TableRenderData getCourseTargetTable2() {
+        return courseTargetTable2;
+    }
+
+    public void setCourseTargetTable2(TableRenderData courseTargetTable2) {
+        this.courseTargetTable2 = courseTargetTable2;
+    }
+}

+ 46 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/bean/result/report/word/CourseTargetTableBean1.java

@@ -0,0 +1,46 @@
+package com.qmth.distributed.print.business.bean.result.report.word;
+
+import io.swagger.annotations.ApiModelProperty;
+
+import java.io.Serializable;
+
+/**
+ * @Description: 课程报告表格1bean
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2024/1/31
+ */
+public class CourseTargetTableBean1 implements Serializable {
+
+    @ApiModelProperty(name = "名称")
+    String name;
+
+    @ApiModelProperty(name = "目标")
+    String target;
+
+    public CourseTargetTableBean1() {
+
+    }
+
+    public CourseTargetTableBean1(String name, String target) {
+        this.name = name;
+        this.target = target;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getTarget() {
+        return target;
+    }
+
+    public void setTarget(String target) {
+        this.target = target;
+    }
+}

+ 85 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/bean/result/report/word/CourseTargetTableBean2.java

@@ -0,0 +1,85 @@
+package com.qmth.distributed.print.business.bean.result.report.word;
+
+import io.swagger.annotations.ApiModelProperty;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * @Description: 课程报告表格2bean
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2024/1/31
+ */
+public class CourseTargetTableBean2 extends CourseTargetTableBean1 implements Serializable {
+
+    @ApiModelProperty(name = "平时表现")
+    BigDecimal expression = new BigDecimal(0);
+
+    @ApiModelProperty(name = "课后作业")
+    BigDecimal homework = new BigDecimal(0);
+
+    @ApiModelProperty(name = "课程实验")
+    BigDecimal test = new BigDecimal(0);
+
+    @ApiModelProperty(name = "期末考试")
+    BigDecimal exam = new BigDecimal(0);
+
+    @ApiModelProperty(name = "目标分值")
+    BigDecimal targetSum = new BigDecimal(0);
+
+    public CourseTargetTableBean2() {
+
+    }
+
+    public CourseTargetTableBean2(String name, String target, BigDecimal expression, BigDecimal homework, BigDecimal test, BigDecimal exam, BigDecimal targetSum) {
+        setName(name);
+        setTarget(target);
+        this.expression = expression;
+        this.homework = homework;
+        this.test = test;
+        this.exam = exam;
+        this.targetSum = targetSum;
+    }
+
+    public BigDecimal getTargetSum() {
+        return targetSum;
+    }
+
+    public void setTargetSum(BigDecimal targetSum) {
+        this.targetSum = targetSum;
+    }
+
+    public BigDecimal getExpression() {
+        return expression;
+    }
+
+    public void setExpression(BigDecimal expression) {
+        this.expression = expression;
+    }
+
+    public BigDecimal getHomework() {
+        return homework;
+    }
+
+    public void setHomework(BigDecimal homework) {
+        this.homework = homework;
+    }
+
+    public BigDecimal getTest() {
+        return test;
+    }
+
+    public void setTest(BigDecimal test) {
+        this.test = test;
+    }
+
+    public BigDecimal getExam() {
+        return exam;
+    }
+
+    public void setExam(BigDecimal exam) {
+        this.exam = exam;
+    }
+}

+ 83 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/bean/result/report/word/CourseTargetTableBean3.java

@@ -0,0 +1,83 @@
+package com.qmth.distributed.print.business.bean.result.report.word;
+
+import io.swagger.annotations.ApiModelProperty;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * @Description: 课程报告表格3bean
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2024/1/31
+ */
+public class CourseTargetTableBean3 implements Serializable {
+
+    @ApiModelProperty(name = "序号")
+    String num;
+
+    @ApiModelProperty(name = "项目")
+    String project;
+
+    @ApiModelProperty(name = "考核内容及要求")
+    String content;
+
+    @ApiModelProperty(name = "目标分值")
+    BigDecimal target = new BigDecimal(0);
+
+    @ApiModelProperty(name = "对应的课程目标")
+    String courseTarget;
+
+    public CourseTargetTableBean3() {
+
+    }
+
+    public CourseTargetTableBean3(String num, String project, String content, BigDecimal target, String courseTarget) {
+        this.num = num;
+        this.project = project;
+        this.content = content;
+        this.target = target;
+        this.courseTarget = courseTarget;
+    }
+
+    public String getNum() {
+        return num;
+    }
+
+    public void setNum(String num) {
+        this.num = num;
+    }
+
+    public String getProject() {
+        return project;
+    }
+
+    public void setProject(String project) {
+        this.project = project;
+    }
+
+    public String getContent() {
+        return content;
+    }
+
+    public void setContent(String content) {
+        this.content = content;
+    }
+
+    public BigDecimal getTarget() {
+        return target;
+    }
+
+    public void setTarget(BigDecimal target) {
+        this.target = target;
+    }
+
+    public String getCourseTarget() {
+        return courseTarget;
+    }
+
+    public void setCourseTarget(String courseTarget) {
+        this.courseTarget = courseTarget;
+    }
+}

+ 83 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/bean/result/report/word/CourseTargetTableBean4.java

@@ -0,0 +1,83 @@
+package com.qmth.distributed.print.business.bean.result.report.word;
+
+import io.swagger.annotations.ApiModelProperty;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * @Description: 课程报告表格4bean
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2024/1/31
+ */
+public class CourseTargetTableBean4 implements Serializable {
+
+    @ApiModelProperty(name = "序号")
+    String num;
+
+    @ApiModelProperty(name = "考核项目")
+    String project;
+
+    @ApiModelProperty(name = "考核内容所涵盖的知识单元")
+    String content;
+
+    @ApiModelProperty(name = "目标分值")
+    BigDecimal target = new BigDecimal(0);
+
+    @ApiModelProperty(name = "对应的课程目标")
+    String courseTarget;
+
+    public CourseTargetTableBean4() {
+
+    }
+
+    public CourseTargetTableBean4(String num, String project, String content, BigDecimal target, String courseTarget) {
+        this.num = num;
+        this.project = project;
+        this.content = content;
+        this.target = target;
+        this.courseTarget = courseTarget;
+    }
+
+    public String getNum() {
+        return num;
+    }
+
+    public void setNum(String num) {
+        this.num = num;
+    }
+
+    public String getProject() {
+        return project;
+    }
+
+    public void setProject(String project) {
+        this.project = project;
+    }
+
+    public String getContent() {
+        return content;
+    }
+
+    public void setContent(String content) {
+        this.content = content;
+    }
+
+    public BigDecimal getTarget() {
+        return target;
+    }
+
+    public void setTarget(BigDecimal target) {
+        this.target = target;
+    }
+
+    public String getCourseTarget() {
+        return courseTarget;
+    }
+
+    public void setCourseTarget(String courseTarget) {
+        this.courseTarget = courseTarget;
+    }
+}

+ 74 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/bean/result/report/word/ExamStudentScoreBean.java

@@ -0,0 +1,74 @@
+package com.qmth.distributed.print.business.bean.result.report.word;
+
+import io.swagger.annotations.ApiModelProperty;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * @Description: 考生分数bean
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2024/1/31
+ */
+public class ExamStudentScoreBean implements Serializable {
+
+    @ApiModelProperty(name = "作业分数")
+    BigDecimal score = new BigDecimal(0);
+
+    @ApiModelProperty(name = "课程目标考核要素的目标分")
+    BigDecimal targetAllAvgScore = new BigDecimal(2);
+
+    @ApiModelProperty(name = "课程目标考核要素的平均分")
+    BigDecimal allScore = new BigDecimal(0);
+
+    @ApiModelProperty(name = "各课程目标平均分")
+    BigDecimal avgAllScore = new BigDecimal(0);
+
+    public ExamStudentScoreBean() {
+
+    }
+
+    public ExamStudentScoreBean(BigDecimal score) {
+        this.score = score;
+    }
+
+    public ExamStudentScoreBean(BigDecimal score, BigDecimal targetAllAvgScore, BigDecimal avgAllScore) {
+        this.score = score;
+        this.targetAllAvgScore = targetAllAvgScore;
+        this.avgAllScore = avgAllScore;
+    }
+
+    public BigDecimal getAllScore() {
+        return allScore;
+    }
+
+    public void setAllScore(BigDecimal allScore) {
+        this.allScore = allScore;
+    }
+
+    public BigDecimal getScore() {
+        return score;
+    }
+
+    public void setScore(BigDecimal score) {
+        this.score = score;
+    }
+
+    public BigDecimal getTargetAllAvgScore() {
+        return targetAllAvgScore;
+    }
+
+    public void setTargetAllAvgScore(BigDecimal targetAllAvgScore) {
+        this.targetAllAvgScore = targetAllAvgScore;
+    }
+
+    public BigDecimal getAvgAllScore() {
+        return avgAllScore;
+    }
+
+    public void setAvgAllScore(BigDecimal avgAllScore) {
+        this.avgAllScore = avgAllScore;
+    }
+}

+ 104 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/bean/result/report/word/ExamStudentTableBean.java

@@ -0,0 +1,104 @@
+package com.qmth.distributed.print.business.bean.result.report.word;
+
+import io.swagger.annotations.ApiModelProperty;
+import org.springframework.util.LinkedMultiValueMap;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Map;
+
+/**
+ * @Description: 考生表格bean
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2024/1/31
+ */
+public class ExamStudentTableBean implements Serializable {
+
+    @ApiModelProperty(name = "序号")
+    String num;
+
+    @ApiModelProperty(name = "学号")
+    String examNumber;
+
+    @ApiModelProperty(name = "姓名")
+    String name;
+
+    @ApiModelProperty(name = "行政班级")
+    String clazz;
+
+    @ApiModelProperty(name = "目标成绩")
+    LinkedMultiValueMap<String, Map<String, ExamStudentScoreBean>> map;
+
+    @ApiModelProperty(name = "综合成绩")
+    BigDecimal sumScore = new BigDecimal(0);
+
+    public ExamStudentTableBean() {
+
+    }
+
+    public ExamStudentTableBean(String num, String examNumber, String name, String clazz) {
+        this.num = num;
+        this.examNumber = examNumber;
+        this.name = name;
+        this.clazz = clazz;
+    }
+
+    public ExamStudentTableBean(String num, String examNumber, String name, String clazz, LinkedMultiValueMap<String, Map<String, ExamStudentScoreBean>> map, BigDecimal sumScore) {
+        this.num = num;
+        this.examNumber = examNumber;
+        this.name = name;
+        this.clazz = clazz;
+        this.map = map;
+        this.sumScore = sumScore;
+    }
+
+    public LinkedMultiValueMap<String, Map<String, ExamStudentScoreBean>> getMap() {
+        return map;
+    }
+
+    public void setMap(LinkedMultiValueMap<String, Map<String, ExamStudentScoreBean>> map) {
+        this.map = map;
+    }
+
+    public String getNum() {
+        return num;
+    }
+
+    public void setNum(String num) {
+        this.num = num;
+    }
+
+    public String getExamNumber() {
+        return examNumber;
+    }
+
+    public void setExamNumber(String examNumber) {
+        this.examNumber = examNumber;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getClazz() {
+        return clazz;
+    }
+
+    public void setClazz(String clazz) {
+        this.clazz = clazz;
+    }
+
+    public BigDecimal getSumScore() {
+        return sumScore;
+    }
+
+    public void setSumScore(BigDecimal sumScore) {
+        this.sumScore = sumScore;
+    }
+}

+ 17 - 18
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/TCFinalScoreServiceImpl.java

@@ -1,12 +1,14 @@
 package com.qmth.distributed.print.business.service.impl;
 
-import com.alibaba.excel.EasyExcel;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.qmth.boot.api.exception.ApiException;
+import com.qmth.boot.tools.excel.ExcelReader;
+import com.qmth.boot.tools.excel.enums.ExcelType;
+import com.qmth.boot.tools.excel.model.DataMap;
 import com.qmth.distributed.print.business.bean.dto.FinalScoreDto;
 import com.qmth.distributed.print.business.bean.result.FinalScoreResult;
 import com.qmth.distributed.print.business.entity.TCFinalScore;
@@ -73,26 +75,25 @@ public class TCFinalScoreServiceImpl extends ServiceImpl<TCFinalScoreMapper, TCF
         try {
             StringJoiner errorData = new StringJoiner("");
             StringJoiner successData = new StringJoiner("");
-            List<Map<String, String>> list = EasyExcel.read(file.getInputStream()).headRowNumber(1).sheet(0).doReadSync();
+
+            ExcelReader excelReader = ExcelReader.create(ExcelType.XLSX, file.getInputStream(), 1);
+            List<DataMap> list = excelReader.getDataMapList();
             log.info("list:{}", JacksonUtil.parseJson(list));
 
             SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
             List<TCFinalScore> tcFinalScoreList = new ArrayList<>(list.size());
-            Map<String, String> headMap = list.get(0);
-            for (Map.Entry<String, String> entry : headMap.entrySet()) {
-                if (Objects.equals(entry.getKey(), 0) && Objects.nonNull(entry.getValue()) &&
-                        !Objects.equals(entry.getValue().trim(), "学号")) {
+            String[] columnNames = excelReader.getColumnNames();
+            for (int i = 0; i < columnNames.length; i++) {
+                if (i == 0 && Objects.nonNull(columnNames[i]) && !Objects.equals(columnNames[i].trim(), "学号")) {
                     throw ExceptionResultEnum.ERROR.exception("excel表头第一行为学号");
-                } else if (Objects.equals(entry.getKey(), 1) && Objects.nonNull(entry.getValue()) &&
-                        !Objects.equals(entry.getValue().trim(), "姓名")) {
+                } else if (i == 1 && Objects.nonNull(columnNames[i]) && !Objects.equals(columnNames[i].trim(), "姓名")) {
                     throw ExceptionResultEnum.ERROR.exception("excel表头第二行为姓名");
-                } else if (Objects.equals(entry.getKey(), 2) && Objects.nonNull(entry.getValue()) &&
-                        !Objects.equals(entry.getValue().trim(), "成绩")) {
+                } else if (i == 2 && Objects.nonNull(columnNames[i]) && !Objects.equals(columnNames[i].trim(), "成绩")) {
                     throw ExceptionResultEnum.ERROR.exception("excel表头第三行为成绩");
                 }
             }
 
-            for (int i = 1; i < list.size(); i++) {
+            for (int i = 0; i < list.size(); i++) {
                 Map<String, String> objectMap = list.get(i);
                 boolean error = false;
                 JSONArray jsonArray = new JSONArray();
@@ -100,19 +101,17 @@ public class TCFinalScoreServiceImpl extends ServiceImpl<TCFinalScoreMapper, TCF
                 for (Map.Entry<String, String> entry : objectMap.entrySet()) {
                     JSONObject jsonObject = new JSONObject();
                     if (Objects.isNull(entry.getValue()) || Objects.equals(entry.getValue().trim(), "")) {
-                        errorData.add("excel第" + i + "行[").add(headMap.get(entry.getKey()) + "]为空;").add("\r\n");
+                        errorData.add("excel第" + (i + 1) + "行[").add(entry.getKey() + "]为空;").add("\r\n");
                         error = true;
                     } else {
-                        String head = headMap.get(entry.getKey());
-                        Objects.requireNonNull(head, "表头信息异常");
-                        if (Objects.equals(head.trim(), "学号")) {
+                        if (Objects.equals(entry.getKey().trim(), "学号")) {
                             tcFinalScore.setStudentCode(entry.getValue());
-                        } else if (Objects.equals(head.trim(), "姓名")) {
+                        } else if (Objects.equals(entry.getKey().trim(), "姓名")) {
                             tcFinalScore.setName(entry.getValue());
-                        } else if (Objects.equals(head.trim(), "成绩")) {
+                        } else if (Objects.equals(entry.getKey().trim(), "成绩")) {
                             tcFinalScore.setScore(Double.valueOf(entry.getValue()));
                         } else {
-                            jsonObject.put("name", headMap.get(entry.getKey()));
+                            jsonObject.put("name", entry.getKey());
                             jsonObject.put("score", entry.getValue());
                             jsonArray.add(jsonObject);
                         }

+ 15 - 15
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/TCUsualScoreServiceImpl.java

@@ -1,12 +1,14 @@
 package com.qmth.distributed.print.business.service.impl;
 
-import com.alibaba.excel.EasyExcel;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.qmth.boot.api.exception.ApiException;
+import com.qmth.boot.tools.excel.ExcelReader;
+import com.qmth.boot.tools.excel.enums.ExcelType;
+import com.qmth.boot.tools.excel.model.DataMap;
 import com.qmth.distributed.print.business.entity.TCUsualScore;
 import com.qmth.distributed.print.business.mapper.TCUsualScoreMapper;
 import com.qmth.distributed.print.business.service.PrintCommonService;
@@ -70,23 +72,23 @@ public class TCUsualScoreServiceImpl extends ServiceImpl<TCUsualScoreMapper, TCU
         try {
             StringJoiner errorData = new StringJoiner("");
             StringJoiner successData = new StringJoiner("");
-            List<Map<String, String>> list = EasyExcel.read(file.getInputStream()).headRowNumber(1).sheet(0).doReadSync();
+
+            ExcelReader excelReader = ExcelReader.create(ExcelType.XLSX, file.getInputStream(), 1);
+            List<DataMap> list = excelReader.getDataMapList();
             log.info("list:{}", JacksonUtil.parseJson(list));
 
             SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
             List<TCUsualScore> tcUsualScoreList = new ArrayList<>(list.size());
-            Map<String, String> headMap = list.get(0);
-            for (Map.Entry<String, String> entry : headMap.entrySet()) {
-                if (Objects.equals(entry.getKey(), 0) && Objects.nonNull(entry.getValue()) &&
-                        !Objects.equals(entry.getValue().trim(), "学号")) {
+            String[] columnNames = excelReader.getColumnNames();
+            for (int i = 0; i < columnNames.length; i++) {
+                if (i == 0 && Objects.nonNull(columnNames[i]) && !Objects.equals(columnNames[i].trim(), "学号")) {
                     throw ExceptionResultEnum.ERROR.exception("excel表头第一行为学号");
-                } else if (Objects.equals(entry.getKey(), 1) && Objects.nonNull(entry.getValue()) &&
-                        !Objects.equals(entry.getValue().trim(), "姓名")) {
+                } else if (i == 1 && Objects.nonNull(columnNames[i]) && !Objects.equals(columnNames[i].trim(), "姓名")) {
                     throw ExceptionResultEnum.ERROR.exception("excel表头第二行为姓名");
                 }
             }
 
-            for (int i = 1; i < list.size(); i++) {
+            for (int i = 0; i < list.size(); i++) {
                 Map<String, String> objectMap = list.get(i);
                 boolean error = false;
                 JSONArray jsonArray = new JSONArray();
@@ -94,17 +96,15 @@ public class TCUsualScoreServiceImpl extends ServiceImpl<TCUsualScoreMapper, TCU
                 for (Map.Entry<String, String> entry : objectMap.entrySet()) {
                     JSONObject jsonObject = new JSONObject();
                     if (Objects.isNull(entry.getValue()) || Objects.equals(entry.getValue().trim(), "")) {
-                        errorData.add("excel第" + i + "行[").add(headMap.get(entry.getKey()) + "]为空;").add("\r\n");
+                        errorData.add("excel第" + (i + 1) + "行[").add(entry.getKey() + "]为空;").add("\r\n");
                         error = true;
                     } else {
-                        String head = headMap.get(entry.getKey());
-                        Objects.requireNonNull(head, "表头信息异常");
-                        if (Objects.equals(head.trim(), "学号")) {
+                        if (Objects.equals(entry.getKey().trim(), "学号")) {
                             tcUsualScore.setStudentCode(entry.getValue());
-                        } else if (Objects.equals(head.trim(), "姓名")) {
+                        } else if (Objects.equals(entry.getKey().trim(), "姓名")) {
                             tcUsualScore.setName(entry.getValue());
                         } else {
-                            jsonObject.put("name", headMap.get(entry.getKey()));
+                            jsonObject.put("name", entry.getKey());
                             jsonObject.put("score", entry.getValue());
                             jsonArray.add(jsonObject);
                         }

+ 3 - 5
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/TRBasicInfoServiceImpl.java

@@ -28,7 +28,6 @@ import org.springframework.util.CollectionUtils;
 import javax.annotation.Resource;
 import java.math.BigDecimal;
 import java.util.*;
-import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.Function;
 import java.util.stream.Collectors;
@@ -277,13 +276,12 @@ public class TRBasicInfoServiceImpl extends ServiceImpl<TRBasicInfoMapper, TRBas
         //TODO 课程考核成绩评价结果-待曹子轩补充目标/评价方式数据,有测试数据
         if (!CollectionUtils.isEmpty(paperStructResultList) && !CollectionUtils.isEmpty(targetMap)) {
             List<CourseTargetDto> targetList = new ArrayList<>(targetMap.size());
-            AtomicInteger sequenceId = new AtomicInteger(1);//流程连接id
             AtomicReference<Double> targetValue = new AtomicReference<>(0.0d);
             targetMap.forEach((k, v) -> {
                 Double evaluationValue = 0.0d;
                 List<ReportEvaluationDto> reportEvaluationDtoList = new ArrayList<>();
                 if (!CollectionUtils.isEmpty(usualScoreOverviewDtoMap)) {
-                    UsualScoreOverviewDto usualScoreOverviewDto = usualScoreOverviewDtoMap.get("作业" + sequenceId.get());
+                    UsualScoreOverviewDto usualScoreOverviewDto = usualScoreOverviewDtoMap.get("作业" + k);
                     ReportEvaluationDto reportEvaluationDto = new ReportEvaluationDto(usualScoreOverviewDto.getName(), new BigDecimal(30), 40d, usualScoreOverviewDto.getAvgScore());
                     reportEvaluationDtoList.add(reportEvaluationDto);
 
@@ -310,11 +308,11 @@ public class TRBasicInfoServiceImpl extends ServiceImpl<TRBasicInfoMapper, TRBas
                     }
                 }
 
-                CourseTargetDto courseTargetDto = new CourseTargetDto(k, v.getTargetName(), Long.parseLong(String.valueOf(sequenceId.get())), "评价方式" + sequenceId.get(), "评价方式描述" + sequenceId.get(), reportEvaluationDtoList, evaluationValue);
+                CourseTargetDto courseTargetDto = new CourseTargetDto(k, v.getTargetName(), k, "评价方式" + k, "评价方式描述" + k, reportEvaluationDtoList, evaluationValue);
                 targetList.add(courseTargetDto);
                 targetValue.set(targetValue.get().doubleValue() + courseTargetDto.getEvaluationValue().doubleValue());
-                sequenceId.incrementAndGet();
             });
+            Collections.sort(targetList);
             reportCourseEvaluationResultDto = new ReportCourseEvaluationResultDto("测试课程总目标1", targetValue.get(), targetList);
         }
         return reportCourseEvaluationResultDto;

+ 1 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/TRExamStudentServiceImpl.java

@@ -100,6 +100,7 @@ public class TRExamStudentServiceImpl extends ServiceImpl<TRExamStudentMapper, T
                         }
                     }
                 }
+                Collections.sort(reportExamStudentDto.getTargetList());
                 trExamStudentList.add(new TRExamStudent(trBasicInfo.getId(), reportExamStudentDto));
             }
             //加入平均分

+ 0 - 227
distributed-print-business/src/main/java/com/qmth/distributed/print/business/util/excel/BasicExcelListener.java

@@ -1,227 +0,0 @@
-package com.qmth.distributed.print.business.util.excel;
-
-import com.alibaba.excel.annotation.ExcelProperty;
-import com.alibaba.excel.context.AnalysisContext;
-import com.alibaba.excel.event.AnalysisEventListener;
-import com.alibaba.excel.metadata.CellExtra;
-import com.alibaba.fastjson.JSONObject;
-import org.hibernate.validator.constraints.Length;
-import org.hibernate.validator.constraints.Range;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.util.LinkedMultiValueMap;
-
-import javax.validation.constraints.*;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Field;
-import java.math.BigDecimal;
-import java.util.*;
-
-/**
- * @Description: easyexcel监听
- * @Param:
- * @return:
- * @Author: wangliang
- * @Date: 2022/5/14
- */
-public abstract class BasicExcelListener<T> extends AnalysisEventListener<T> {
-    private final static Logger log = LoggerFactory.getLogger(BasicExcelListener.class);
-
-    /**
-     * 批处理阈值2000
-     */
-    private static int BATCH_COUNT = 2000;
-    public static final String SUCCESS = "success";
-    public static final String ERROR = "error";
-    private LinkedMultiValueMap<String, T> list;
-    private StringJoiner errorDataSj = new StringJoiner("\n");
-    private Exception exception = null;
-
-    public BasicExcelListener() {
-        this.list = new LinkedMultiValueMap<>(BATCH_COUNT);
-    }
-
-    public BasicExcelListener(int batchCount) {
-        BATCH_COUNT = batchCount;
-        this.list = new LinkedMultiValueMap<>(BATCH_COUNT);
-    }
-
-    public abstract void handle(LinkedMultiValueMap<String, T> dataList, StringJoiner errorData, Exception exception);
-
-//    public abstract void errorData(List<String> errorDataList);
-
-    @Override
-    public void invoke(T o, AnalysisContext analysisContext) {
-//        if (validData(o, analysisContext) || (analysisContext.readRowHolder().getRowIndex() == 2001 || analysisContext.readRowHolder().getRowIndex() == 7001)) {
-        if (validData(o, analysisContext)) {
-            list.add(ERROR, o);
-            BasicExcelRow basicExcelRow = (BasicExcelRow) o;
-            errorDataSj.add("第" + basicExcelRow.getSheet() + "个sheet第" + (basicExcelRow.getRow() - 1) + "行" + basicExcelRow.getErrorMessage().toString());
-        } else {
-            list.add(SUCCESS, o);
-        }
-        if (list.size() >= BATCH_COUNT) {
-            handle(list, errorDataSj, this.exception);
-            list.clear();
-        }
-    }
-
-//    @Override
-//    public void invokeHead(Map<Integer, ReadCellData<?>> headMap, AnalysisContext context) {
-//        log.info("表头:{}", JSONObject.toJSONString(headMap));
-//    }
-
-    @Override
-    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
-        log.info("表头:{}", JSONObject.toJSONString(headMap));
-    }
-
-    @Override
-    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
-        log.info("所有数据解析完成!");
-        handle(list, errorDataSj, this.exception);
-    }
-
-    @Override
-    public void onException(Exception exception, AnalysisContext context) {
-        log.info("onException is come in!");
-//        XlsxReadSheetHolder xlsxReadSheetHolder = (XlsxReadSheetHolder) context.currentReadHolder();
-//        errorDataSj.add("第" + (xlsxReadSheetHolder.getSheetNo() + 1) + "个sheet第" + (xlsxReadSheetHolder.getRowIndex() - 1) + "行" + exception.getMessage().toString());
-        this.exception = exception;
-    }
-
-    @Override
-    public void extra(CellExtra extra, AnalysisContext context) {
-        log.info("extra is come in!");
-    }
-
-    private void extendBasicExcelField(T o, AnalysisContext analysisContext, List<String> errorMessage) {
-        try {
-            Field rowField = o.getClass().getField("row");
-            rowField.setAccessible(true);
-            rowField.set(o, analysisContext.readRowHolder().getRowIndex());
-
-            Field sheetField = o.getClass().getField("sheet");
-            sheetField.setAccessible(true);
-            sheetField.set(o, analysisContext.readSheetHolder().getSheetNo() + 1);
-
-            Field errorMessageMapField = o.getClass().getField("errorMessage");
-            errorMessageMapField.setAccessible(true);
-            errorMessageMapField.set(o, errorMessage);
-        } catch (NoSuchFieldException | IllegalAccessException e) {
-            log.error("请求出错:", e);
-        }
-    }
-
-    private boolean validData(T o, AnalysisContext analysisContext) {
-        List<String> errorMessage = new ArrayList<>();
-        Field[] fields = o.getClass().getDeclaredFields();
-        Object object = null;
-        for (int i = 0; i < fields.length; i++) {
-            fields[i].setAccessible(true);
-            try {
-                object = fields[i].get(o);
-            } catch (IllegalAccessException e) {
-                e.printStackTrace();
-            }
-            ExcelProperty excelProperty = fields[i].getDeclaredAnnotation(ExcelProperty.class);
-            if (Objects.isNull(excelProperty)) {
-                continue;
-            }
-            Annotation[] annotations = fields[i].getDeclaredAnnotations();
-            NotBlank notBlank = null;
-            Length length = null;
-            Min min = null;
-            Max max = null;
-            DecimalMin decimalMin = null;
-            DecimalMax decimalMax = null;
-            NotNull notNull = null;
-            Null isnull = null;
-            NotEmpty notEmpty = null;
-            Size size = null;
-            Range range = null;
-            AssertTrue assertTrue = null;
-            AssertFalse assertFalse = null;
-            for (Annotation annotation : annotations) {
-                if (annotation instanceof NotBlank) {
-                    notBlank = (NotBlank) annotation;
-                    if (Objects.isNull(object) || Objects.equals(object, " ")) {
-                        errorMessage.add("列名[" + excelProperty.value()[0] + "]:" + notBlank.message());
-                    }
-                } else if (annotation instanceof Length) {
-                    length = (Length) annotation;
-                    if (Objects.nonNull(object) && (object.toString().length() < length.min() || object.toString().length() > length.max())) {
-                        errorMessage.add("列名[" + excelProperty.value()[0] + "]:" + length.message());
-                    }
-                } else if (annotation instanceof Min) {
-                    min = (Min) annotation;
-                    if (Objects.nonNull(object) && Long.parseLong(object.toString()) < min.value()) {
-                        errorMessage.add("列名[" + excelProperty.value()[0] + "]:" + min.message());
-                    }
-                } else if (annotation instanceof Max) {
-                    max = (Max) annotation;
-                    if (Objects.nonNull(object) && Long.parseLong(object.toString()) > max.value()) {
-                        errorMessage.add("列名[" + excelProperty.value()[0] + "]:" + max.message());
-                    }
-                } else if (annotation instanceof DecimalMin) {
-                    decimalMin = (DecimalMin) annotation;
-                    if (Objects.nonNull(object) && new BigDecimal(object.toString()).compareTo(new BigDecimal(decimalMin.value())) == -1) {
-                        errorMessage.add("列名[" + excelProperty.value()[0] + "]:" + decimalMin.message());
-                    }
-                } else if (annotation instanceof DecimalMax) {
-                    decimalMax = (DecimalMax) annotation;
-                    if (Objects.nonNull(object) && new BigDecimal(object.toString()).compareTo(new BigDecimal(decimalMax.value())) == 1) {
-                        errorMessage.add("列名[" + excelProperty.value()[0] + "]:" + decimalMax.message());
-                    }
-                } else if (annotation instanceof NotNull) {
-                    notNull = (NotNull) annotation;
-                    if (Objects.isNull(object)) {
-                        errorMessage.add("列名[" + excelProperty.value()[0] + "]:" + notNull.message());
-                    }
-                } else if (annotation instanceof Null) {
-                    isnull = (Null) annotation;
-                    if (Objects.nonNull(object)) {
-                        errorMessage.add("列名[" + excelProperty.value()[0] + "]:" + isnull.message());
-                    }
-                } else if (annotation instanceof NotEmpty) {
-                    notEmpty = (NotEmpty) annotation;
-                    if (Objects.isNull(object)) {
-                        errorMessage.add("列名[" + excelProperty.value()[0] + "]:" + notEmpty.message());
-                    }
-                } else if (annotation instanceof Size) {
-                    size = (Size) annotation;
-                    if (Objects.nonNull(object) && (object.toString().length() < size.min() || object.toString().length() > size.max())) {
-                        errorMessage.add("列名[" + excelProperty.value()[0] + "]:" + size.message());
-                    }
-                } else if (annotation instanceof Range) {
-                    range = (Range) annotation;
-                    if (Objects.nonNull(object) && (Long.parseLong(object.toString()) < range.min() || Long.parseLong(object.toString()) > range.max())) {
-                        errorMessage.add("列名[" + excelProperty.value()[0] + "]:" + range.message());
-                    }
-                } else if (annotation instanceof AssertTrue) {
-                    assertTrue = (AssertTrue) annotation;
-                    if (Objects.nonNull(object) && Boolean.valueOf(object.toString())) {
-                        errorMessage.add("列名[" + excelProperty.value()[0] + "]:" + assertTrue.message());
-                    }
-                } else if (annotation instanceof AssertFalse) {
-                    assertFalse = (AssertFalse) annotation;
-                    if (Objects.nonNull(object) && !Boolean.valueOf(object.toString())) {
-                        errorMessage.add("列名[" + excelProperty.value()[0] + "]:" + assertFalse.message());
-                    }
-                }
-            }
-            if (errorMessage.size() > 0) {
-                extendBasicExcelField(o, analysisContext, errorMessage);
-            }
-        }
-        return errorMessage.size() > 0 ? true : false;
-    }
-
-    //可重写的方法:
-//	void invoke(T data, AnalysisContext context); //处理一行数据
-//	void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) //处理表头的一行数据
-//	void extra(CellExtra extra, AnalysisContext context); //获取单元格的额外信息
-//	void doAfterAllAnalysed(AnalysisContext context) //全部读取结束后的操作
-//	boolean hasNext(AnalysisContext context); //是否读取下一行
-//	void onException(Exception exception, AnalysisContext context) //发生异常时调用
-}

+ 0 - 53
distributed-print-business/src/main/java/com/qmth/distributed/print/business/util/excel/BasicExcelRow.java

@@ -1,53 +0,0 @@
-package com.qmth.distributed.print.business.util.excel;
-
-import com.alibaba.excel.annotation.ExcelIgnore;
-import io.swagger.annotations.ApiModelProperty;
-
-import java.io.Serializable;
-import java.util.List;
-
-/**
- * @Description: easyexcel基础列
- * @Param:
- * @return:
- * @Author: wangliang
- * @Date: 2022/5/14
- */
-public class BasicExcelRow implements Serializable {
-
-    @ApiModelProperty(value = "sheet页")
-    @ExcelIgnore
-    public Integer sheet;
-
-    @ApiModelProperty(value = "行号")
-    @ExcelIgnore
-    public Integer row;
-
-    @ApiModelProperty(value = "列名和错误原因")
-    @ExcelIgnore
-    public List<String> errorMessage;
-
-    public Integer getSheet() {
-        return sheet;
-    }
-
-    public void setSheet(Integer sheet) {
-        this.sheet = sheet;
-    }
-
-    public Integer getRow() {
-        return row;
-    }
-
-    public void setRow(Integer row) {
-        this.row = row;
-    }
-
-    public List<String> getErrorMessage() {
-        return errorMessage;
-    }
-
-    public void setErrorMessage(List<String> errorMessage) {
-        this.errorMessage = errorMessage;
-    }
-}

+ 346 - 3
distributed-print/src/main/java/com/qmth/distributed/print/api/TRBasicInfoController.java

@@ -3,10 +3,16 @@ package com.qmth.distributed.print.api;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.deepoove.poi.XWPFTemplate;
+import com.deepoove.poi.data.*;
+import com.deepoove.poi.data.style.CellStyle;
+import com.deepoove.poi.data.style.ParagraphStyle;
+import com.deepoove.poi.data.style.RowStyle;
 import com.qmth.boot.api.constant.ApiConstant;
 import com.qmth.distributed.print.business.bean.dto.report.*;
 import com.qmth.distributed.print.business.bean.result.ScoreResult;
 import com.qmth.distributed.print.business.bean.result.report.ReportResult;
+import com.qmth.distributed.print.business.bean.result.report.word.*;
 import com.qmth.distributed.print.business.entity.TRBasicInfo;
 import com.qmth.distributed.print.business.entity.TRExamStudent;
 import com.qmth.distributed.print.business.service.PrintCommonService;
@@ -21,8 +27,11 @@ import com.qmth.teachcloud.common.util.ServletUtil;
 import com.qmth.teachcloud.mark.entity.MarkPaper;
 import com.qmth.teachcloud.mark.service.MarkPaperService;
 import io.swagger.annotations.*;
+import org.apache.poi.xwpf.usermodel.ParagraphAlignment;
+import org.apache.poi.xwpf.usermodel.XWPFTableCell;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
+import org.springframework.util.LinkedMultiValueMap;
 import org.springframework.validation.BindingResult;
 import org.springframework.web.bind.annotation.*;
 
@@ -31,9 +40,8 @@ import javax.validation.Valid;
 import javax.validation.constraints.Max;
 import javax.validation.constraints.Min;
 import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
+import java.math.BigDecimal;
+import java.util.*;
 
 /**
  * <p>
@@ -148,5 +156,340 @@ public class TRBasicInfoController {
                              @ApiParam(value = "试卷编号", required = true) @RequestParam String paperNumber) throws IOException {
         TRBasicInfo trBasicInfo = trBasicInfoService.getOne(new QueryWrapper<TRBasicInfo>().lambda().eq(TRBasicInfo::getExamId, examId).eq(TRBasicInfo::getCourseCode, courseCode).eq(TRBasicInfo::getPaperNumber, paperNumber));
         Objects.requireNonNull(trBasicInfo, "没有报告信息");
+
+        CourseBasicBean courseBasicBean = new CourseBasicBean("启明科目",
+                "qmth", "qm", "自营", "10/2.0", "10/0", "光谷梦工厂", "理想", "2024年1月30日", "我们的目标是没有目标", "2");
+        CourseReportBean courseReportBean = new CourseReportBean("2022-2023(2)学期《测试输出报告》", courseBasicBean);
+
+        //table1
+        RowRenderData header1 = Rows.of("课程目标", "毕业要求指标点").bgColor("F2F2F2").center().create();
+        Tables.TableBuilder tableBuilder1 = Tables.ofPercentWidth("100%");
+        Map<String, Integer> courseTargetMap = new LinkedHashMap<>();
+        tableBuilder1.addRow(header1);
+        for (int i = 0; i < 2; i++) {
+            CourseTargetTableBean1 courseTargetTableBean1 = new CourseTargetTableBean1("课程目标" + (i + 1), "完成目标" + (i + 1));
+            RowRenderData row = Rows.of(courseTargetTableBean1.getName(), courseTargetTableBean1.getTarget()).rowStyle(this.getRowStyle()).create();
+            tableBuilder1.addRow(row);
+            courseTargetMap.put(courseTargetTableBean1.getName(), i + 1);
+        }
+        TableRenderData tableRenderData1 = tableBuilder1.left().create();
+        courseReportBean.setCourseTargetTable1(tableRenderData1);
+
+        //table2
+        RowRenderData header2_1 = Rows.of("课程目标", "支撑毕业要求", "考核/评价环节及目标分值", "", "", "", "目标分值统计").bgColor("F2F2F2").center().create();
+        RowRenderData header2_2 = Rows.of("课程目标", "支撑毕业要求", "平时表现", "课后作业", "课程实验", "期末考试", "目标分值统计").bgColor("F2F2F2").center().create();
+
+        List<CourseTargetTableBean2> courseTargetTableBean2List = new ArrayList<>();
+        BigDecimal bigDecimalExpressionSum = new BigDecimal(0), homeworkSum = new BigDecimal(0), testSum = new BigDecimal(0), examSum = new BigDecimal(0), targetSum2 = new BigDecimal(0);
+        for (int i = 0; i < 2; i++) {
+            CourseTargetTableBean2 courseTargetTableBean2 = new CourseTargetTableBean2("课程目标" + (i + 1), "考核目标" + (i + 1), new BigDecimal(i + 2), new BigDecimal(i + 3), new BigDecimal(i + 4), new BigDecimal(i + 5), new BigDecimal(i + 10));
+            bigDecimalExpressionSum = bigDecimalExpressionSum.add(courseTargetTableBean2.getExpression());
+            homeworkSum = homeworkSum.add(courseTargetTableBean2.getHomework());
+            testSum = testSum.add(courseTargetTableBean2.getTest());
+            examSum = examSum.add(courseTargetTableBean2.getExam());
+            targetSum2 = targetSum2.add(courseTargetTableBean2.getTargetSum());
+            courseTargetTableBean2List.add(courseTargetTableBean2);
+        }
+
+        RowRenderData[] rowRenderData2 = new RowRenderData[courseTargetTableBean2List.size() + 3];
+        for (int i = 0; i < courseTargetTableBean2List.size(); i++) {
+            CourseTargetTableBean2 courseTargetTableBean2 = courseTargetTableBean2List.get(i);
+            rowRenderData2[i + 2] = Rows.of(courseTargetTableBean2.getName(), courseTargetTableBean2.getTarget(), courseTargetTableBean2.getExpression().toString(), courseTargetTableBean2.getHomework().toString(), courseTargetTableBean2.getTest().toString(), courseTargetTableBean2.getExam().toString(), courseTargetTableBean2.getTargetSum().toString()).rowStyle(this.getRowStyle()).create();
+//            rowRenderData[i + 2] = Rows.of(this.getCell(courseTargetTableBean2.getName()), this.getCell(courseTargetTableBean2.getTarget()), this.getCell(courseTargetTableBean2.getExpression().toString()), this.getCell(courseTargetTableBean2.getHomework().toString()), this.getCell(courseTargetTableBean2.getTest().toString()), this.getCell(courseTargetTableBean2.getExam().toString()), this.getCell(courseTargetTableBean2.getTargetSum().toString())).create();
+        }
+        rowRenderData2[0] = header2_1;
+        rowRenderData2[1] = header2_2;
+
+        RowRenderData header2_foot = Rows.of("合计", "", bigDecimalExpressionSum.toString(), homeworkSum.toString(), testSum.toString(), examSum.toString(), targetSum2.toString()).rowStyle(this.getRowStyle()).create();
+        rowRenderData2[rowRenderData2.length - 1] = header2_foot;
+
+        // 表格合并,根据坐标
+        MergeCellRule mergeCellRule2 = MergeCellRule.builder().map(MergeCellRule.Grid.of(0, 0), MergeCellRule.Grid.of(1, 0)).
+                map(MergeCellRule.Grid.of(0, 1), MergeCellRule.Grid.of(1, 1)).
+                map(MergeCellRule.Grid.of(0, 2), MergeCellRule.Grid.of(0, 5)).
+                map(MergeCellRule.Grid.of(0, 6), MergeCellRule.Grid.of(1, 6)).
+                map(MergeCellRule.Grid.of(rowRenderData2.length - 1, 0), MergeCellRule.Grid.of(rowRenderData2.length - 1, 1)).
+                build();
+
+        Tables.TableBuilder tableBuilder2 = Tables.ofPercentWidth("100%");
+        for (int i = 0; i < rowRenderData2.length; i++) {
+            tableBuilder2.addRow(rowRenderData2[i]);
+        }
+        TableRenderData tableRenderData2 = tableBuilder2.mergeRule(mergeCellRule2).left().create();
+//        TableRenderData tableRenderData2 = Tables.of(rowRenderData2).mergeRule(mergeCellRule2)
+//                .width(17f, new double[]{17 / 6, 22 / 6, 15 / 6, 15 / 6, 15 / 6, 15 / 6, 17 / 6})
+//                .left().create();
+        courseReportBean.setCourseTargetTable2(tableRenderData2);
+
+        //table3
+        RowRenderData header3_1 = Rows.of("序号", "项目", "考核内容及要求", "目标分值", "对应的课程目标").bgColor("F2F2F2").center().create();
+        List<CourseTargetTableBean3> courseTargetTableBean3List = new ArrayList<>();
+        BigDecimal targetSum3 = new BigDecimal(0);
+        String tableFootTitle3 = "合计${sum}分,占课程总评成绩的30%";
+        for (int i = 0; i < 2; i++) {
+            CourseTargetTableBean3 courseTargetTableBean3 = new CourseTargetTableBean3("" + (i + 1), "项目" + (i + 1), "内容" + (i + 1), new BigDecimal(i + 3), "目标分值" + (i + 1));
+            targetSum3 = targetSum3.add(courseTargetTableBean3.getTarget());
+            courseTargetTableBean3List.add(courseTargetTableBean3);
+        }
+        tableFootTitle3 = tableFootTitle3.replace("${sum}", targetSum3.toString());
+
+        RowRenderData[] rowRenderData3 = new RowRenderData[courseTargetTableBean3List.size() + 2];
+        for (int i = 0; i < courseTargetTableBean3List.size(); i++) {
+            CourseTargetTableBean3 courseTargetTableBean3 = courseTargetTableBean3List.get(i);
+            rowRenderData3[i + 1] = Rows.of(courseTargetTableBean3.getNum(), courseTargetTableBean3.getProject(), courseTargetTableBean3.getContent(), courseTargetTableBean3.getTarget().toString(), courseTargetTableBean3.getCourseTarget()).rowStyle(this.getRowStyle()).create();
+        }
+        rowRenderData3[0] = header3_1;
+        RowRenderData header3_foot = Rows.of(tableFootTitle3, "", "", "", "").center().create();
+        rowRenderData3[rowRenderData3.length - 1] = header3_foot;
+
+        // 表格合并,根据坐标
+        MergeCellRule mergeCellRule3 = MergeCellRule.builder().map(MergeCellRule.Grid.of(rowRenderData3.length - 1, 0), MergeCellRule.Grid.of(rowRenderData3.length - 1, 4)).
+                build();
+
+//        TableRenderData tableRenderData3 = Tables.of(rowRenderData3).mergeRule(mergeCellRule3)
+//                .width(17f, new double[]{10 / 6, 15 / 6, 24 / 6, 15 / 6, 20 / 6}).left().create();
+        Tables.TableBuilder tableBuilder3 = Tables.ofPercentWidth("100%");
+        for (int i = 0; i < rowRenderData3.length; i++) {
+            tableBuilder3.addRow(rowRenderData3[i]);
+        }
+        TableRenderData tableRenderData3 = tableBuilder3.mergeRule(mergeCellRule3).left().create();
+        courseReportBean.setCourseTargetTable3(tableRenderData3);
+
+        //table4
+        RowRenderData header4_1 = Rows.of("序号", "考核项目", "考核内容所涵盖的知识单元", "目标分值", "对应的课程目标").bgColor("F2F2F2").center().create();
+        List<CourseTargetTableBean4> courseTargetTableBean4List = new ArrayList<>();
+        BigDecimal targetSum4 = new BigDecimal(0);
+        String tableFootTitle4 = "合计${sum}分,占课程总评成绩的70%";
+        for (int i = 0; i < 2; i++) {
+            CourseTargetTableBean4 courseTargetTableBean4 = new CourseTargetTableBean4("" + (i + 1), "考核项目" + (i + 1), "考核内容" + (i + 1), new BigDecimal(i + 3), "考核目标分值" + (i + 1));
+            targetSum4 = targetSum4.add(courseTargetTableBean4.getTarget());
+            courseTargetTableBean4List.add(courseTargetTableBean4);
+        }
+        tableFootTitle4 = tableFootTitle4.replace("${sum}", targetSum4.toString());
+
+        RowRenderData[] rowRenderData4 = new RowRenderData[courseTargetTableBean4List.size() + 2];
+        for (int i = 0; i < courseTargetTableBean4List.size(); i++) {
+            CourseTargetTableBean4 courseTargetTableBean4 = courseTargetTableBean4List.get(i);
+            rowRenderData3[i + 1] = Rows.of(courseTargetTableBean4.getNum(), courseTargetTableBean4.getProject(), courseTargetTableBean4.getContent(), courseTargetTableBean4.getTarget().toString(), courseTargetTableBean4.getCourseTarget()).rowStyle(this.getRowStyle()).create();
+        }
+        rowRenderData3[0] = header4_1;
+        RowRenderData header4_foot = Rows.of(tableFootTitle4, "", "", "", "").center().create();
+        rowRenderData3[rowRenderData4.length - 1] = header4_foot;
+
+        // 表格合并,根据坐标
+        MergeCellRule mergeCellRule4 = MergeCellRule.builder().map(MergeCellRule.Grid.of(rowRenderData4.length - 1, 0), MergeCellRule.Grid.of(rowRenderData4.length - 1, 4)).
+                build();
+
+//        TableRenderData tableRenderData4 = Tables.of(rowRenderData3).mergeRule(mergeCellRule4)
+//                .width(17f, new double[]{10 / 6, 15 / 6, 24 / 6, 15 / 6, 20 / 6})
+//                .left().create();
+        Tables.TableBuilder tableBuilder4 = Tables.ofPercentWidth("100%");
+        for (int i = 0; i < rowRenderData4.length; i++) {
+            tableBuilder4.addRow(rowRenderData3[i]);
+        }
+        TableRenderData tableRenderData4 = tableBuilder4.mergeRule(mergeCellRule4).left().create();
+        courseReportBean.setCourseTargetTable4(tableRenderData4);
+
+        //examstudent
+        List<CellRenderData> examStudent_cells_1 = new ArrayList<>(), examStudent_cells_2 = new ArrayList<>(), examStudent_cells_3 = new ArrayList<>(), examStudent_cells_4 = new ArrayList<>(), examStudent_cells_5 = new ArrayList<>();
+        examStudent_cells_1.add(Cells.of("序号").center().create());
+        examStudent_cells_1.add(Cells.of("学号").center().create());
+        examStudent_cells_1.add(Cells.of("姓名").center().create());
+        examStudent_cells_1.add(Cells.of("行政班级").center().create());
+        examStudent_cells_2.addAll(examStudent_cells_1);
+
+        examStudent_cells_3.add(Cells.of("课程目标考核要素的目标分").center().create());
+        examStudent_cells_3.add(Cells.of("").center().create());
+        examStudent_cells_3.add(Cells.of("").center().create());
+        examStudent_cells_3.add(Cells.of("").center().create());
+
+        examStudent_cells_4.add(Cells.of("课程目标考核要素的平均分").center().create());
+        examStudent_cells_4.add(Cells.of("").center().create());
+        examStudent_cells_4.add(Cells.of("").center().create());
+        examStudent_cells_4.add(Cells.of("").center().create());
+
+        examStudent_cells_5.add(Cells.of("各课程目标平均分").center().create());
+        examStudent_cells_5.add(Cells.of("").center().create());
+        examStudent_cells_5.add(Cells.of("").center().create());
+        examStudent_cells_5.add(Cells.of("").center().create());
+
+        List<ExamStudentTableBean> examStudentTableBeanList = new ArrayList<>();
+        int randomHomework = new Random().nextInt(20) + 1;//随机作业
+//        int randomHomework = 10;
+        int targetSize = courseTargetMap.size();
+        for (int i = 0; i < 20; i++) {
+            LinkedMultiValueMap<String, Map<String, ExamStudentScoreBean>> scoreMap = new LinkedMultiValueMap<>();
+            int finalI = i;
+            courseTargetMap.forEach((k, v) -> {
+                if (finalI == 0) {
+                    examStudent_cells_1.add(Cells.of("目标" + v.toString()).center().create());
+                }
+                for (int y = 0; y < randomHomework; y++) {
+                    if (finalI == 0) {
+                        examStudent_cells_1.add(Cells.of("").center().create());
+                        examStudent_cells_2.add(Cells.of("作业" + v + "_" + (y + 1)).center().create());
+                    }
+                    scoreMap.add(k, Collections.singletonMap("作业" + v + "_" + (y + 1), new ExamStudentScoreBean(new BigDecimal(new Random().nextInt(100) + 1))));
+                }
+                scoreMap.add(k, Collections.singletonMap("期末考试", new ExamStudentScoreBean(new BigDecimal(new Random().nextInt(100) + 1))));
+                if (finalI == 0) {
+                    examStudent_cells_2.add(Cells.of("期末考试").center().create());
+                }
+            });
+            if (finalI == 0) {
+                examStudent_cells_1.add(Cells.of("综合成绩").center().create());
+                examStudent_cells_2.add(Cells.of("综合成绩").center().create());
+            }
+            examStudentTableBeanList.add(new ExamStudentTableBean(i + 1 + "", "2023000" + (i + 1), "测试考生" + (i + 1), "测试班级", scoreMap, new BigDecimal(new Random().nextInt(100) + 1)));
+        }
+
+        String title = "2023级启明大学";
+        String sumTitle = "学生共${sum}名";
+        sumTitle = sumTitle.replace("${sum}", examStudentTableBeanList.size() + "");
+
+        courseReportBean.setExamStudentTitle1(title + sumTitle);
+        courseReportBean.setExamStudentTitle2(title + "《" + courseReportBean.getCourseBasicBean().getCourseName() + "》");
+
+        RowRenderData[] rowRenderDataExamStudent = new RowRenderData[examStudentTableBeanList.size() + 5];
+
+        RowRenderData examStudent_header_1 = new RowRenderData();
+        examStudent_header_1.setCells(examStudent_cells_1);
+        examStudent_header_1.setRowStyle(this.getHeadRowStyle());
+
+        RowRenderData examStudent_header_2 = new RowRenderData();
+        examStudent_header_2.setCells(examStudent_cells_2);
+        examStudent_header_2.setRowStyle(this.getHeadRowStyle());
+
+        for (int i = 0; i < examStudentTableBeanList.size(); i++) {
+            ExamStudentTableBean e = examStudentTableBeanList.get(i);
+            RowRenderData examStudent_row = new RowRenderData();
+            List<CellRenderData> examStudent_cells = new ArrayList<>();
+            examStudent_cells.add(Cells.of(e.getNum()).create());
+            examStudent_cells.add(Cells.of(e.getExamNumber()).create());
+            examStudent_cells.add(Cells.of(e.getName()).create());
+            examStudent_cells.add(Cells.of(e.getClazz()).create());
+
+            String key = null;
+            LinkedMultiValueMap<String, Map<String, ExamStudentScoreBean>> map = e.getMap();
+            for (Map.Entry<String, List<Map<String, ExamStudentScoreBean>>> entry : map.entrySet()) {
+                List<Map<String, ExamStudentScoreBean>> list = entry.getValue();
+                BigDecimal courseSumAvg = new BigDecimal(0);
+                for (int y = 0; y < list.size(); y++) {
+                    Map<String, ExamStudentScoreBean> m = list.get(y);
+                    for (Map.Entry<String, ExamStudentScoreBean> entry1 : m.entrySet()) {
+                        courseSumAvg = courseSumAvg.add(entry1.getValue().getScore());
+                        entry1.getValue().setAllScore(new BigDecimal(new Random().nextInt(10) + 1));
+                        key = entry1.getKey();
+                        examStudent_cells.add(Cells.of(entry1.getValue().getScore().toString()).create());
+                    }
+                    if (y == list.size() - 1) {
+                        courseSumAvg = courseSumAvg.divide(new BigDecimal(list.size()), 2, BigDecimal.ROUND_HALF_UP)
+                                .setScale(2, BigDecimal.ROUND_HALF_UP);
+                        list.get(y).get(key).setAvgAllScore(courseSumAvg);
+                    }
+                }
+            }
+            if (i == examStudentTableBeanList.size() - 1) {
+                LinkedMultiValueMap<String, Map<String, ExamStudentScoreBean>> map1 = e.getMap();
+                for (Map.Entry<String, List<Map<String, ExamStudentScoreBean>>> entry1 : map1.entrySet()) {
+                    List<Map<String, ExamStudentScoreBean>> list1 = entry1.getValue();
+                    for (int k = 0; k < list1.size(); k++) {
+                        Map<String, ExamStudentScoreBean> m = list1.get(k);
+                        for (Map.Entry<String, ExamStudentScoreBean> entry2 : m.entrySet()) {
+                            examStudent_cells_3.add(Cells.of(entry2.getValue().getTargetAllAvgScore().toString()).create());
+                            examStudent_cells_4.add(Cells.of(entry2.getValue().getAllScore().toString()).create());
+                        }
+                    }
+                    examStudent_cells_5.add(Cells.of(list1.get(list1.size() - 1).get(key).getAvgAllScore().toString()).create());
+                    for (int k = 1; k < list1.size(); k++) {
+                        examStudent_cells_5.add(Cells.of("").create());
+                    }
+                }
+                examStudent_cells_3.add(Cells.of(e.getSumScore().toString()).create());
+                examStudent_cells_4.add(Cells.of(e.getSumScore().toString()).create());
+                examStudent_cells_5.add(Cells.of("").create());
+            }
+            examStudent_cells.add(Cells.of(e.getSumScore().toString()).create());
+            examStudent_row.setCells(examStudent_cells);
+            examStudent_row.setRowStyle(this.getRowStyle());
+            rowRenderDataExamStudent[i + 2] = examStudent_row;
+        }
+
+        rowRenderDataExamStudent[0] = examStudent_header_1;
+        rowRenderDataExamStudent[1] = examStudent_header_2;
+        RowRenderData examStudent_row3 = new RowRenderData();
+        examStudent_row3.setCells(examStudent_cells_3);
+        examStudent_row3.setRowStyle(this.getRowStyle());
+        RowRenderData examStudent_row4 = new RowRenderData();
+        examStudent_row4.setCells(examStudent_cells_4);
+        examStudent_row4.setRowStyle(this.getRowStyle());
+        RowRenderData examStudent_row5 = new RowRenderData();
+        examStudent_row5.setCells(examStudent_cells_5);
+        examStudent_row5.setRowStyle(this.getRowStyle());
+
+        rowRenderDataExamStudent[rowRenderDataExamStudent.length - 3] = examStudent_row3;
+        rowRenderDataExamStudent[rowRenderDataExamStudent.length - 2] = examStudent_row4;
+        rowRenderDataExamStudent[rowRenderDataExamStudent.length - 1] = examStudent_row5;
+
+        // 表格合并,根据坐标
+        MergeCellRule mergeCellRuleExamStudent = MergeCellRule.builder().build();
+        mergeCellRuleExamStudent.getMapping().add(new MergeCellRule.GridRule(MergeCellRule.Grid.of(0, 0), MergeCellRule.Grid.of(1, 0)));
+        mergeCellRuleExamStudent.getMapping().add(new MergeCellRule.GridRule(MergeCellRule.Grid.of(0, 1), MergeCellRule.Grid.of(1, 1)));
+        mergeCellRuleExamStudent.getMapping().add(new MergeCellRule.GridRule(MergeCellRule.Grid.of(0, 2), MergeCellRule.Grid.of(1, 2)));
+        mergeCellRuleExamStudent.getMapping().add(new MergeCellRule.GridRule(MergeCellRule.Grid.of(0, 3), MergeCellRule.Grid.of(1, 3)));
+        mergeCellRuleExamStudent.getMapping().add(new MergeCellRule.GridRule(MergeCellRule.Grid.of(rowRenderDataExamStudent.length - 3, 0), MergeCellRule.Grid.of(rowRenderDataExamStudent.length - 3, 3)));
+        mergeCellRuleExamStudent.getMapping().add(new MergeCellRule.GridRule(MergeCellRule.Grid.of(rowRenderDataExamStudent.length - 2, 0), MergeCellRule.Grid.of(rowRenderDataExamStudent.length - 2, 3)));
+        mergeCellRuleExamStudent.getMapping().add(new MergeCellRule.GridRule(MergeCellRule.Grid.of(rowRenderDataExamStudent.length - 1, 0), MergeCellRule.Grid.of(rowRenderDataExamStudent.length - 1, 3)));
+
+        //动态扩展列
+        int initNum = 4;
+        for (int i = 0; i < targetSize; i++) {
+            mergeCellRuleExamStudent.getMapping().add(new MergeCellRule.GridRule(MergeCellRule.Grid.of(0, initNum), MergeCellRule.Grid.of(0, initNum + randomHomework)));
+            mergeCellRuleExamStudent.getMapping().add(new MergeCellRule.GridRule(MergeCellRule.Grid.of(rowRenderDataExamStudent.length - 1, initNum), MergeCellRule.Grid.of(rowRenderDataExamStudent.length - 1, initNum + randomHomework)));
+            initNum = initNum + randomHomework + 1;
+        }
+        mergeCellRuleExamStudent.getMapping().add(new MergeCellRule.GridRule(MergeCellRule.Grid.of(0, initNum), MergeCellRule.Grid.of(1, initNum)));
+
+        Tables.TableBuilder tableBuilderExamStudent = Tables.ofPercentWidth("100%");
+        for (int i = 0; i < rowRenderDataExamStudent.length; i++) {
+            tableBuilderExamStudent.addRow(rowRenderDataExamStudent[i]);
+        }
+        TableRenderData tableRenderDataExamStudent = tableBuilderExamStudent.mergeRule(mergeCellRuleExamStudent).left().create();
+        courseReportBean.setExamStudentTable1(tableRenderDataExamStudent);
+
+        XWPFTemplate template = XWPFTemplate.compile("/Users/king/git/teachcloud-server/distributed-print/src/main/resources/static/course_degree_report.docx").render(courseReportBean);
+        template.writeToFile("/Users/king/Downloads/demo_course_degree_report.docx");
+    }
+
+    /**
+     * 获取行样式
+     *
+     * @return
+     */
+    protected RowStyle getRowStyle() {
+        RowStyle rowStyle = new RowStyle();
+        ParagraphStyle paragraphStyle = new ParagraphStyle();
+        paragraphStyle.setAlign(ParagraphAlignment.LEFT);
+        CellStyle cellStyle = new CellStyle();
+        cellStyle.setDefaultParagraphStyle(paragraphStyle);
+        cellStyle.setVertAlign(XWPFTableCell.XWPFVertAlign.CENTER);
+        rowStyle.setDefaultCellStyle(cellStyle);
+        return rowStyle;
+    }
+
+    /**
+     * 获取行样式
+     *
+     * @return
+     */
+    protected RowStyle getHeadRowStyle() {
+        RowStyle rowStyle = new RowStyle();
+        ParagraphStyle paragraphStyle = new ParagraphStyle();
+        paragraphStyle.setAlign(ParagraphAlignment.CENTER);
+        CellStyle cellStyle = new CellStyle();
+        cellStyle.setDefaultParagraphStyle(paragraphStyle);
+        cellStyle.setBackgroundColor("F2F2F2");
+        rowStyle.setDefaultCellStyle(cellStyle);
+        return rowStyle;
     }
 }

+ 8 - 8
distributed-print/src/main/resources/application.properties

@@ -47,20 +47,20 @@ spring.activiti.check-process-definitions=false
 #full\uFF1A\u4FDD\u5B58\u5386\u53F2\u6570\u636E\u7684\u6700\u9AD8\u7EA7\u522B\uFF0C\u9664\u4E86\u4F1A\u4FDD\u5B58audit\u7EA7\u522B\u7684\u6570\u636E\u5916\uFF0C\u8FD8\u4F1A\u4FDD\u5B58\u5176\u4ED6\u5168\u90E8\u6D41\u7A0B\u76F8\u5173\u7684\u7EC6\u8282\u6570\u636E\uFF0C\u5305\u62EC\u4E00\u4E9B\u6D41\u7A0B\u53C2\u6570\u7B49\u3002
 spring.activiti.history-level=audit
 
-com.qmth.fss.public.config=oss://key:secret@teachcloud-dps-dev1-public.oss-api.qmth.com.cn
-com.qmth.fss.public.server=https://oss-file.qmth.com.cn/teachcloud-dps-dev1-public
-com.qmth.fss.private.config=oss://key:secret@teachcloud-dps-dev1-private.oss-api.qmth.com.cn
-com.qmth.fss.private.server=https://oss-file.qmth.com.cn/teachcloud-dps-dev1-private
+#com.qmth.fss.public.config=oss://key:secret@teachcloud-dps-dev1-public.oss-api.qmth.com.cn
+#com.qmth.fss.public.server=https://oss-file.qmth.com.cn/teachcloud-dps-dev1-public
+#com.qmth.fss.private.config=oss://key:secret@teachcloud-dps-dev1-private.oss-api.qmth.com.cn
+#com.qmth.fss.private.server=https://oss-file.qmth.com.cn/teachcloud-dps-dev1-private
 
 #com.qmth.fss.public.config=/Users/xiaofei/qmth/temporary/zxzk/file-temp
 #com.qmth.fss.public.server=http://localhost:7001
 #com.qmth.fss.private.config=/Users/xiaofei/qmth/temporary/zxzk/pdf-temp
 #com.qmth.fss.private.server=http://localhost:7001
 
-#com.qmth.fss.public.config=/Users/king/Downloads/file-temp
-#com.qmth.fss.public.server=/file-temp/
-#com.qmth.fss.private.config=/Users/king/Downloads/pdf-temp
-#com.qmth.fss.private.server=/pdf-temp/
+com.qmth.fss.public.config=/Users/king/Downloads/file-temp
+com.qmth.fss.public.server=/file-temp/
+com.qmth.fss.private.config=/Users/king/Downloads/pdf-temp
+com.qmth.fss.private.server=/pdf-temp/
 
 #\u7CFB\u7EDF\u914D\u7F6E
 sys.config.oss=false

BIN
distributed-print/src/main/resources/static/course_degree_report.docx


+ 13 - 12
pom.xml

@@ -28,7 +28,7 @@
         <knife4j.version>2.0.7</knife4j.version>
         <fastjson.version>1.2.68</fastjson.version>
         <fileupload.version>1.4</fileupload.version>
-        <poi.version>3.17</poi.version>
+        <poi.version>5.2.2</poi.version>
         <aliyun.version>3.8.1</aliyun.version>
         <guava.version>27.1-jre</guava.version>
         <hutool.version>5.0.6</hutool.version>
@@ -37,7 +37,7 @@
         <gson.version>2.8.6</gson.version>
         <commons.version>3.10</commons.version>
         <commons.codec.version>1.15</commons.codec.version>
-        <commons-io.version>2.6</commons-io.version>
+        <commons-io.version>2.11.0</commons-io.version>
         <jackson.version>2.11.0</jackson.version>
         <swagger2-bootstrap.version>1.9.6</swagger2-bootstrap.version>
         <jetbrains.version>13.0</jetbrains.version>
@@ -55,7 +55,8 @@
         <zip4j.version>1.3.3</zip4j.version>
         <nanoid.version>2.0.0</nanoid.version>
 <!--        <jasypt.version>3.0.3</jasypt.version>-->
-        <easyexcel.version>3.0.5</easyexcel.version>
+        <poi-tl.version>1.12.1</poi-tl.version>
+        <poi-ooxml-schemas.version>4.1.2</poi-ooxml-schemas.version>
     </properties>
 
     <dependencyManagement>
@@ -165,11 +166,11 @@
                 <artifactId>core-sms</artifactId>
                 <version>${qmth.boot.version}</version>
             </dependency>
-<!--            <dependency>-->
-<!--                <groupId>com.qmth.boot</groupId>-->
-<!--                <artifactId>tools-poi</artifactId>-->
-<!--                <version>${qmth.boot.version}</version>-->
-<!--            </dependency>-->
+            <dependency>
+                <groupId>com.qmth.boot</groupId>
+                <artifactId>tools-poi</artifactId>
+                <version>${qmth.boot.version}</version>
+            </dependency>
 <!--            <dependency>-->
 <!--                <groupId>io.springfox</groupId>-->
 <!--                <artifactId>springfox-swagger-ui</artifactId>-->
@@ -219,7 +220,7 @@
             <dependency>
                 <groupId>org.apache.poi</groupId>
                 <artifactId>poi-ooxml-schemas</artifactId>
-                <version>${poi.version}</version>
+                <version>${poi-ooxml-schemas.version}</version>
             </dependency>
             <dependency>
                 <groupId>org.apache.poi</groupId>
@@ -380,9 +381,9 @@
                 <version>1.5.1-RELEASE</version>
             </dependency>
             <dependency>
-                <groupId>com.alibaba</groupId>
-                <artifactId>easyexcel</artifactId>
-                <version>${easyexcel.version}</version>
+                <groupId>com.deepoove</groupId>
+                <artifactId>poi-tl</artifactId>
+                <version>${poi-tl.version}</version>
             </dependency>
         </dependencies>
     </dependencyManagement>

+ 6 - 6
teachcloud-common/pom.xml

@@ -54,10 +54,10 @@
             <groupId>com.qmth.boot</groupId>
             <artifactId>core-sms</artifactId>
         </dependency>
-<!--        <dependency>-->
-<!--            <groupId>com.qmth.boot</groupId>-->
-<!--            <artifactId>tools-poi</artifactId>-->
-<!--        </dependency>-->
+        <dependency>
+            <groupId>com.qmth.boot</groupId>
+            <artifactId>tools-poi</artifactId>
+        </dependency>
         <dependency>
             <groupId>io.netty</groupId>
             <artifactId>netty-all</artifactId>
@@ -182,8 +182,8 @@
             <artifactId>mybatisplus-plus</artifactId>
         </dependency>
         <dependency>
-            <groupId>com.alibaba</groupId>
-            <artifactId>easyexcel</artifactId>
+            <groupId>com.deepoove</groupId>
+            <artifactId>poi-tl</artifactId>
         </dependency>
     </dependencies>
 </project>

+ 11 - 14
teachcloud-common/src/main/java/com/qmth/teachcloud/common/util/ExcelUtil.java

@@ -8,11 +8,7 @@ import com.qmth.teachcloud.common.util.excel.ExcelCallback;
 import com.qmth.teachcloud.common.util.excel.ExcelError;
 import com.qmth.teachcloud.common.util.excel.ExcelWriter;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.poi.hssf.usermodel.HSSFDateUtil;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellType;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.*;
 import org.apache.poi.xssf.usermodel.XSSFSheet;
 import org.apache.poi.xssf.usermodel.XSSFWorkbook;
 import org.slf4j.Logger;
@@ -130,15 +126,16 @@ public class ExcelUtil {
 
     /**
      * excel读取
+     *
      * @param inputStream inputStream
-     * @param clazz clazz
-     * @param callback callback
-     * @param headRow 表头所在行(从第几行开始是表头) - 默认第一行
+     * @param clazz       clazz
+     * @param callback    callback
+     * @param headRow     表头所在行(从第几行开始是表头) - 默认第一行
      */
-    public static List<LinkedMultiValueMap<Integer, Object>> excelReader(InputStream inputStream, List<Class<?>> clazz, ExcelCallback callback , Integer headRow) throws NoSuchFieldException, IOException {
+    public static List<LinkedMultiValueMap<Integer, Object>> excelReader(InputStream inputStream, List<Class<?>> clazz, ExcelCallback callback, Integer headRow) throws NoSuchFieldException, IOException {
         // 表头行索引
         int headIndex = 0;
-        if (Objects.nonNull(headRow) && headRow > 0){
+        if (Objects.nonNull(headRow) && headRow > 0) {
             headIndex = headRow - 1;
         }
         Object o = null;
@@ -177,7 +174,7 @@ public class ExcelUtil {
                         if (y == 0 && i == headIndex) {
                             for (Field field : fields) {
                                 ExcelNote excelNote = field.getAnnotation(ExcelNote.class);
-                                if(Objects.nonNull(excelNote)) {
+                                if (Objects.nonNull(excelNote)) {
                                     headList.add(excelNote.value());
                                 }
                             }
@@ -294,9 +291,9 @@ public class ExcelUtil {
      * @return
      */
     public static Object convert(Cell cell) {
-        switch (cell.getCellTypeEnum()) {
+        switch (cell.getCellType()) {
             case NUMERIC:
-                if (HSSFDateUtil.isCellDateFormatted(cell)) {
+                if (DateUtil.isCellDateFormatted(cell)) {
                     SimpleDateFormat sdf;
                     // 验证short值
                     if (cell.getCellStyle().getDataFormat() == 14) {
@@ -381,7 +378,7 @@ public class ExcelUtil {
         //判断多少个单元格为空
         for (int c = 0; c < rowCount; c++) {
             Cell cell = row.getCell(c);
-            if (cell == null || cell.getCellTypeEnum() == CellType.BLANK || StringUtils.isEmpty((cell + "").trim())) {
+            if (cell == null || cell.getCellType() == CellType.BLANK || StringUtils.isEmpty((cell + "").trim())) {
                 count += 1;
             }
         }

+ 7 - 6
teachcloud-common/src/main/java/com/qmth/teachcloud/common/util/excel/ExcelWriter.java

@@ -3,6 +3,7 @@ package com.qmth.teachcloud.common.util.excel;
 import com.qmth.teachcloud.common.annotation.excelStyle.ExcelDataStyle;
 import com.qmth.teachcloud.common.annotation.excelStyle.ExcelHeaderStyle;
 import com.qmth.teachcloud.common.contant.SystemConstant;
+import org.apache.poi.ss.usermodel.Font;
 import org.apache.poi.ss.usermodel.*;
 import org.apache.poi.xssf.usermodel.XSSFCellStyle;
 import org.apache.poi.xssf.usermodel.XSSFColor;
@@ -69,7 +70,7 @@ public class ExcelWriter extends ExcelExport {
             int borderRed = excelHeaderStyle.borderColorRed();
             int borderGreen = excelHeaderStyle.borderColorGreen();
             int borderBlue = excelHeaderStyle.borderColorBlue();
-            XSSFColor borderColor = new XSSFColor(new Color(borderRed, borderGreen, borderBlue));
+            XSSFColor borderColor = new XSSFColor(new Color(borderRed, borderGreen, borderBlue), workbook.getStylesSource().getIndexedColors());
             // 上边框
             if (excelHeaderStyle.borderTop().getCode() > 0) {
                 style.setBorderTop(excelHeaderStyle.borderTop());
@@ -93,7 +94,7 @@ public class ExcelWriter extends ExcelExport {
 
             // 背景
             style.setFillPattern(excelHeaderStyle.fillPartner());
-            XSSFColor fillColor = new XSSFColor(new Color(excelHeaderStyle.fillColorRed(), excelHeaderStyle.fillColorGreen(), excelHeaderStyle.fillColorBlue()));
+            XSSFColor fillColor = new XSSFColor(new Color(excelHeaderStyle.fillColorRed(), excelHeaderStyle.fillColorGreen(), excelHeaderStyle.fillColorBlue()), workbook.getStylesSource().getIndexedColors());
             style.setFillForegroundColor(fillColor);
 
             // 字体
@@ -103,7 +104,7 @@ public class ExcelWriter extends ExcelExport {
             font.setColor(excelHeaderStyle.fontColor().getIndex());
             style.setFont(font);
         } else {
-            style.setFillForegroundColor(new XSSFColor(new Color(227, 239, 217)));
+            style.setFillForegroundColor(new XSSFColor(new Color(227, 239, 217), workbook.getStylesSource().getIndexedColors()));
             style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
         }
         for (short i = 0; i < columnSettings.size(); i++) {
@@ -202,7 +203,7 @@ public class ExcelWriter extends ExcelExport {
         for (short i = 0; i < columnSettings.size(); i++) {
             cell = row.createCell(i);
             style = workbook.createCellStyle();
-            style.setFillForegroundColor(new XSSFColor(new Color(227, 239, 217)));
+            style.setFillForegroundColor(new XSSFColor(new Color(227, 239, 217), workbook.getStylesSource().getIndexedColors()));
             style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
             cell.setCellStyle(style);
             XSSFRichTextString text = new XSSFRichTextString(columnSettings.get(i).getHeader());
@@ -231,7 +232,7 @@ public class ExcelWriter extends ExcelExport {
             int borderRed = excelDataStyle.borderColorRed();
             int borderGreen = excelDataStyle.borderColorGreen();
             int borderBlue = excelDataStyle.borderColorBlue();
-            XSSFColor borderColor = new XSSFColor(new Color(borderRed, borderGreen, borderBlue));
+            XSSFColor borderColor = new XSSFColor(new Color(borderRed, borderGreen, borderBlue), workbook.getStylesSource().getIndexedColors());
             // 上边框
             if (excelDataStyle.borderTop().getCode() > 0) {
                 style.setBorderTop(excelDataStyle.borderTop());
@@ -255,7 +256,7 @@ public class ExcelWriter extends ExcelExport {
 
             // 背景
             style.setFillPattern(excelDataStyle.fillPartner());
-            XSSFColor fillColor = new XSSFColor(new Color(excelDataStyle.fillColorRed(), excelDataStyle.fillColorGreen(), excelDataStyle.fillColorBlue()));
+            XSSFColor fillColor = new XSSFColor(new Color(excelDataStyle.fillColorRed(), excelDataStyle.fillColorGreen(), excelDataStyle.fillColorBlue()), workbook.getStylesSource().getIndexedColors());
             style.setFillForegroundColor(fillColor);
 
             // 字体

+ 9 - 4
teachcloud-task/src/main/resources/application.properties

@@ -48,10 +48,10 @@ spring.activiti.check-process-definitions=false
 #full\uFF1A\u4FDD\u5B58\u5386\u53F2\u6570\u636E\u7684\u6700\u9AD8\u7EA7\u522B\uFF0C\u9664\u4E86\u4F1A\u4FDD\u5B58audit\u7EA7\u522B\u7684\u6570\u636E\u5916\uFF0C\u8FD8\u4F1A\u4FDD\u5B58\u5176\u4ED6\u5168\u90E8\u6D41\u7A0B\u76F8\u5173\u7684\u7EC6\u8282\u6570\u636E\uFF0C\u5305\u62EC\u4E00\u4E9B\u6D41\u7A0B\u53C2\u6570\u7B49\u3002
 spring.activiti.history-level=audit
 
-com.qmth.fss.public.config=oss://key:secret@teachcloud-dps-dev1-public.oss-api.qmth.com.cn
-com.qmth.fss.public.server=https://oss-file.qmth.com.cn/teachcloud-dps-dev-public
-com.qmth.fss.private.config=oss://key:secret@teachcloud-dps-dev1-private.oss-api.qmth.com.cn
-com.qmth.fss.private.server=https://oss-file.qmth.com.cn/teachcloud-dps-dev-private
+#com.qmth.fss.public.config=oss://key:secret@teachcloud-dps-dev1-public.oss-api.qmth.com.cn
+#com.qmth.fss.public.server=https://oss-file.qmth.com.cn/teachcloud-dps-dev-public
+#com.qmth.fss.private.config=oss://key:secret@teachcloud-dps-dev1-private.oss-api.qmth.com.cn
+#com.qmth.fss.private.server=https://oss-file.qmth.com.cn/teachcloud-dps-dev-private
 
 #com.qmth.fss.public.config=../static/
 #com.qmth.fss.public.server=/static/
@@ -63,6 +63,11 @@ com.qmth.fss.private.server=https://oss-file.qmth.com.cn/teachcloud-dps-dev-priv
 #com.qmth.fss.private.config=/Users/xiaofei/qmth/temporary/zxzk/pdf-temp
 #com.qmth.fss.private.server=http://localhost:7001
 
+com.qmth.fss.public.config=/Users/king/Downloads/file-temp
+com.qmth.fss.public.server=/file-temp/
+com.qmth.fss.private.config=/Users/king/Downloads/pdf-temp
+com.qmth.fss.private.server=/pdf-temp/
+
 #\u7CFB\u7EDF\u914D\u7F6E
 sys.config.oss=false
 sys.config.htmlToPdfUrl=/usr/local/bin/wkhtmltopdf