Browse Source

西安工业大学定制课程目标达成度

wangliang 8 months ago
parent
commit
11191736e2

+ 27 - 26
distributed-print/src/main/java/com/qmth/distributed/print/api/obe/TRBasicInfoController.java

@@ -35,8 +35,8 @@ import com.qmth.teachcloud.obe.been.result.ObeScoreResult;
 import com.qmth.teachcloud.obe.been.result.report.PaperStructDimensionResult;
 import com.qmth.teachcloud.obe.been.result.report.ReportChangeResult;
 import com.qmth.teachcloud.obe.been.result.report.ReportResult;
-import com.qmth.teachcloud.obe.been.result.report.word.CourseBasicBean;
-import com.qmth.teachcloud.obe.been.result.report.word.CourseReportBean;
+import com.qmth.teachcloud.obe.been.result.report.word.common.CourseReportBean;
+import com.qmth.teachcloud.obe.been.result.report.word.custom.XagyuCourseReportBean;
 import com.qmth.teachcloud.obe.entity.*;
 import com.qmth.teachcloud.obe.service.*;
 import io.swagger.annotations.*;
@@ -46,6 +46,8 @@ import org.apache.poi.ss.usermodel.*;
 import org.apache.poi.ss.util.CellRangeAddress;
 import org.apache.poi.ss.util.RegionUtil;
 import org.apache.poi.xssf.streaming.SXSSFWorkbook;
+import org.apache.poi.xwpf.usermodel.XWPFDocument;
+import org.apache.poi.xwpf.usermodel.XWPFTable;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.dao.DuplicateKeyException;
@@ -344,42 +346,41 @@ public class TRBasicInfoController {
                 this.reportView(cultureProgramId, courseId, paperNumber);
                 this.reportExport(cultureProgramId, courseId, paperNumber);
             } else {
-                //评价样本的基本信息
-                JSONObject jsonObject = JSONObject.parseObject(trBasicInfo.getCourseEvaluationResultDetail());
-                List<CourseTargetWordDto> courseTargetWordDtoList = JSONArray.parseArray(jsonObject.get("targetWordMap").toString(), CourseTargetWordDto.class);
-
-                StringJoiner courseTarget = new StringJoiner("");
-                courseTargetWordDtoList.stream().peek(s -> {
-                    courseTarget.add("      ").add(s.getTargetName()).add("——").add(s.getGraduationRequirementPoint()).add("\r\n");
-                }).collect(Collectors.toList());
-
-                CourseBasicBean courseBasicBean = new CourseBasicBean(trBasicInfo, courseTarget.toString(), reportCourseEvaluationResultDto.getTargetList().size());
-
-                CourseReportBean courseReportBean = new CourseReportBean(trBasicInfo.getOpenTime() + "《" + trBasicInfo.getCourseName() + "》", courseBasicBean);
-                //table1-课程目标目标与毕业要求指标点的对应关系
-                courseReportBean.setCourseTargetTable1(trBasicInfoService.buildWordTable1(courseTargetWordDtoList));
-
-                //table2-课程目标达成评价依据
-                courseReportBean.setCourseTargetTable2(trBasicInfoService.buildWordTable2(courseTargetWordDtoList));
-
-                //examstudent-课程目标达成评价依据-考生
-                courseReportBean.setExamStudentTable1(trBasicInfoService.buildWordTable5(trBasicInfo, courseReportBean));
-
+                XWPFTemplate template = null;
+                String fileName = null;
                 InputStream inputStream = null;
                 txtFileTemp = SystemConstant.getFileTempVar(SystemConstant.WORD_PREFIX);
                 SysConfig sysConfig = commonCacheService.addSysConfigCache(schoolId, SystemConstant.SCHOOL_COURSE_DEGREE_TEMPLATE);
                 if (Objects.isNull(sysConfig)) {
                     inputStream = FileUtil.getStream("static/" + ImportTemplateEnum.STATIC_COURSE_DEGREE_REPORT.getTemplateName());
+                    FileUtils.copyInputStreamToFile(inputStream, txtFileTemp);
+                    CourseReportBean courseReportBean = trBasicInfoService.buildCommonCourseDegreeReport(trBasicInfo);
+                    template = XWPFTemplate.compile(txtFileTemp.getAbsolutePath()).render(courseReportBean);
+                    fileName = Objects.nonNull(basicSchool) ? basicSchool.getName() + "_" + courseReportBean.getTitle1() + "_" + ImportTemplateEnum.STATIC_COURSE_DEGREE_REPORT.getFileName() + SystemConstant.WORD_PREFIX : courseReportBean.getTitle1() + "_" + ImportTemplateEnum.STATIC_COURSE_DEGREE_REPORT.getFileName() + SystemConstant.WORD_PREFIX;
                 } else {
                     fileTemp = SystemConstant.getFileTempVar(SystemConstant.WORD_PREFIX);
                     fileTemp = fileUploadService.downloadFile(Long.parseLong(sysConfig.getConfigValue()), fileTemp.getPath());
                     inputStream = new FileInputStream(fileTemp);
+                    XWPFDocument xwpfDocument = new XWPFDocument(new FileInputStream(fileTemp));
+                    Objects.requireNonNull(xwpfDocument, "上传的模版有误,请重新上传");
+                    FileUtils.copyInputStreamToFile(inputStream, txtFileTemp);
+                    try {
+                        List<XWPFTable> xwpfTableList = xwpfDocument.getTables();
+                        if (CollectionUtils.isNotEmpty(xwpfTableList)) {
+                            String text = xwpfTableList.get(0).getText();
+                            if (Objects.nonNull(text) && text.contains("xagyuCourseBasicBean")) {
+                                XagyuCourseReportBean xagyuCourseReportBean = trBasicInfoService.buildXagyuCourseDegreeReport(trBasicInfo);
+                                template = XWPFTemplate.compile(txtFileTemp.getAbsolutePath()).render(xagyuCourseReportBean);
+                                fileName = Objects.nonNull(basicSchool) ? basicSchool.getName() + "_" + xagyuCourseReportBean.getXagyuTitle1() + "_" + ImportTemplateEnum.STATIC_COURSE_DEGREE_REPORT.getFileName() + "_定制" + SystemConstant.WORD_PREFIX : xagyuCourseReportBean.getXagyuTitle1() + "_" + ImportTemplateEnum.STATIC_COURSE_DEGREE_REPORT.getFileName() + "_定制" + SystemConstant.WORD_PREFIX;
+                            }
+                        }
+                    } catch (Exception e) {
+                    } finally {
+                        xwpfDocument.close();
+                    }
                 }
-                FileUtils.copyInputStreamToFile(inputStream, txtFileTemp);
-                XWPFTemplate template = XWPFTemplate.compile(txtFileTemp.getAbsolutePath()).render(courseReportBean);
                 template.writeToFile(txtFileTemp.getAbsolutePath());
                 // 导出
-                String fileName = Objects.nonNull(basicSchool) ? basicSchool.getName() + "_" + courseReportBean.getTitle1() + "_" + ImportTemplateEnum.STATIC_COURSE_DEGREE_REPORT.getFileName() + SystemConstant.WORD_PREFIX : courseReportBean.getTitle1() + "_" + ImportTemplateEnum.STATIC_COURSE_DEGREE_REPORT.getFileName() + SystemConstant.WORD_PREFIX;
                 FileUtil.outputFile(ServletUtil.getResponse(), new FileInputStream(txtFileTemp), fileName);
             }
         } catch (Exception e) {

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


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


+ 10 - 0
teachcloud-obe/src/main/java/com/qmth/teachcloud/obe/been/obe/CourseSuggestDto.java

@@ -3,6 +3,7 @@ package com.qmth.teachcloud.obe.been.obe;
 import com.deepoove.poi.data.ChartMultiSeriesRenderData;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import com.qmth.teachcloud.obe.been.report.CourseTargetWebDto;
 import io.swagger.annotations.ApiModelProperty;
 
 import java.io.Serializable;
@@ -35,6 +36,15 @@ public class CourseSuggestDto implements Serializable {
     @ApiModelProperty("课程持续改进")
     private String courseSuggest;
 
+    public CourseSuggestDto() {
+
+    }
+
+    public CourseSuggestDto(CourseTargetWebDto courseTargetWebDto) {
+        this.targetId = courseTargetWebDto.getTargetId();
+        this.targetName = courseTargetWebDto.getTargetName();
+    }
+
     public ChartMultiSeriesRenderData getCourseTargetColumnDiagram3() {
         return courseTargetColumnDiagram3;
     }

+ 12 - 1
teachcloud-obe/src/main/java/com/qmth/teachcloud/obe/been/result/report/word/CourseBasicBean.java → teachcloud-obe/src/main/java/com/qmth/teachcloud/obe/been/result/report/word/common/CourseBasicBean.java

@@ -1,17 +1,22 @@
-package com.qmth.teachcloud.obe.been.result.report.word;
+package com.qmth.teachcloud.obe.been.result.report.word.common;
 
 import cn.hutool.core.date.DateUtil;
 import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
 import com.qmth.teachcloud.common.contant.SystemConstant;
 import com.qmth.teachcloud.obe.been.obe.CourseSuggestDto;
+import com.qmth.teachcloud.obe.been.report.CourseTargetWebDto;
+import com.qmth.teachcloud.obe.been.report.ReportCourseEvaluationResultDto;
 import com.qmth.teachcloud.obe.entity.TRBasicInfo;
 import io.swagger.annotations.ApiModelProperty;
 
 import java.io.Serializable;
 import java.math.BigDecimal;
+import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
 import java.util.Objects;
+import java.util.stream.Collectors;
 
 /**
  * @Description: 课程基本信息bean
@@ -100,6 +105,12 @@ public class CourseBasicBean implements Serializable {
         if (Objects.nonNull(trBasicInfo.getCourseSuggest())) {
             List<CourseSuggestDto> courseSuggestDtoList = JSONArray.parseArray(trBasicInfo.getCourseSuggest(), CourseSuggestDto.class);
             this.courseSuggestList = courseSuggestDtoList;
+        } else {
+            ReportCourseEvaluationResultDto reportCourseEvaluationResultDto = JSONObject.parseObject(trBasicInfo.getCourseEvaluationResult(), ReportCourseEvaluationResultDto.class);
+            List<CourseTargetWebDto> courseTargetWebDtoList = reportCourseEvaluationResultDto.getTargetList();
+            List<CourseSuggestDto> courseSuggestDtoList = new ArrayList<>(courseTargetWebDtoList.size());
+            courseTargetWebDtoList.stream().peek(s -> courseSuggestDtoList.add(new CourseSuggestDto(s))).collect(Collectors.toList());
+            this.courseSuggestList = courseSuggestDtoList;
         }
         this.courseEnName = trBasicInfo.getCourseEnName();
         this.participantCount = trBasicInfo.getParticipantCount();

+ 1 - 1
teachcloud-obe/src/main/java/com/qmth/teachcloud/obe/been/result/report/word/CourseReportBean.java → teachcloud-obe/src/main/java/com/qmth/teachcloud/obe/been/result/report/word/common/CourseReportBean.java

@@ -1,4 +1,4 @@
-package com.qmth.teachcloud.obe.been.result.report.word;
+package com.qmth.teachcloud.obe.been.result.report.word.common;
 
 import com.deepoove.poi.data.ChartMultiSeriesRenderData;
 import com.deepoove.poi.data.TableRenderData;

+ 1 - 1
teachcloud-obe/src/main/java/com/qmth/teachcloud/obe/been/result/report/word/CourseTargetTableBean3.java → teachcloud-obe/src/main/java/com/qmth/teachcloud/obe/been/result/report/word/common/CourseTargetTableBean3.java

@@ -1,4 +1,4 @@
-package com.qmth.teachcloud.obe.been.result.report.word;
+package com.qmth.teachcloud.obe.been.result.report.word.common;
 
 import io.swagger.annotations.ApiModelProperty;
 

+ 1 - 1
teachcloud-obe/src/main/java/com/qmth/teachcloud/obe/been/result/report/word/CourseTargetTableBean4.java → teachcloud-obe/src/main/java/com/qmth/teachcloud/obe/been/result/report/word/common/CourseTargetTableBean4.java

@@ -1,4 +1,4 @@
-package com.qmth.teachcloud.obe.been.result.report.word;
+package com.qmth.teachcloud.obe.been.result.report.word.common;
 
 import io.swagger.annotations.ApiModelProperty;
 

+ 160 - 0
teachcloud-obe/src/main/java/com/qmth/teachcloud/obe/been/result/report/word/custom/XagyuCourseBasicBean.java

@@ -0,0 +1,160 @@
+package com.qmth.teachcloud.obe.been.result.report.word.custom;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.qmth.teachcloud.obe.been.report.CourseTargetWebDto;
+import com.qmth.teachcloud.obe.been.report.ReportCourseEvaluationResultDto;
+import com.qmth.teachcloud.obe.entity.TRBasicInfo;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+/**
+ * @Description: 西安工业大学课程基本信息bean
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2024/10/11
+ */
+public class XagyuCourseBasicBean implements Serializable {
+
+    @ApiModelProperty(name = "课程名称")
+    String courseName;
+
+    @ApiModelProperty(name = "课程编码")
+    String courseCode;
+
+    @ApiModelProperty(name = "学分")
+    String credit;
+
+    @ApiModelProperty(name = "学时")
+    String period;
+
+    @ApiModelProperty(name = "开课专业")
+    String profession;
+
+    @ApiModelProperty(value = "开课时间")
+    private String openTime;
+
+    @ApiModelProperty(value = "授课对象")
+    private String teachingObject;
+
+    @ApiModelProperty(value = "任课老师")
+    private String teacher;
+
+    @ApiModelProperty(value = "课程持续改进")
+    private List<XagyuCourseSuggestDto> courseSuggestList;
+
+    @ApiModelProperty(name = "期末考试权重")
+    BigDecimal finalScoreWeight;
+
+    public XagyuCourseBasicBean() {
+
+    }
+
+    public XagyuCourseBasicBean(TRBasicInfo trBasicInfo) {
+        this.courseName = trBasicInfo.getCourseName();
+        this.courseCode = trBasicInfo.getCourseCode();
+        this.credit = trBasicInfo.getCredit();
+        this.period = trBasicInfo.getPeriod();
+        this.profession = trBasicInfo.getProfession();
+        this.openTime = trBasicInfo.getOpenTime();
+        this.teachingObject = trBasicInfo.getTeachingObject();
+        this.teacher = trBasicInfo.getTeacher();
+        if (Objects.nonNull(trBasicInfo.getCourseSuggest())) {
+            List<XagyuCourseSuggestDto> courseSuggestDtoList = JSONArray.parseArray(trBasicInfo.getCourseSuggest(), XagyuCourseSuggestDto.class);
+            this.courseSuggestList = courseSuggestDtoList;
+        } else {
+            ReportCourseEvaluationResultDto reportCourseEvaluationResultDto = JSONObject.parseObject(trBasicInfo.getCourseEvaluationResult(), ReportCourseEvaluationResultDto.class);
+            List<CourseTargetWebDto> courseTargetWebDtoList = reportCourseEvaluationResultDto.getTargetList();
+            List<XagyuCourseSuggestDto> courseSuggestDtoList = new ArrayList<>(courseTargetWebDtoList.size());
+            courseTargetWebDtoList.stream().peek(s -> courseSuggestDtoList.add(new XagyuCourseSuggestDto(s))).collect(Collectors.toList());
+            this.courseSuggestList = courseSuggestDtoList;
+        }
+    }
+
+    public BigDecimal getFinalScoreWeight() {
+        return finalScoreWeight;
+    }
+
+    public void setFinalScoreWeight(BigDecimal finalScoreWeight) {
+        this.finalScoreWeight = finalScoreWeight;
+    }
+
+    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 getCredit() {
+        return credit;
+    }
+
+    public void setCredit(String credit) {
+        this.credit = credit;
+    }
+
+    public String getPeriod() {
+        return period;
+    }
+
+    public void setPeriod(String period) {
+        this.period = period;
+    }
+
+    public String getProfession() {
+        return profession;
+    }
+
+    public void setProfession(String profession) {
+        this.profession = profession;
+    }
+
+    public String getOpenTime() {
+        return openTime;
+    }
+
+    public void setOpenTime(String openTime) {
+        this.openTime = openTime;
+    }
+
+    public String getTeachingObject() {
+        return teachingObject;
+    }
+
+    public void setTeachingObject(String teachingObject) {
+        this.teachingObject = teachingObject;
+    }
+
+    public String getTeacher() {
+        return teacher;
+    }
+
+    public void setTeacher(String teacher) {
+        this.teacher = teacher;
+    }
+
+    public List<XagyuCourseSuggestDto> getCourseSuggestList() {
+        return courseSuggestList;
+    }
+
+    public void setCourseSuggestList(List<XagyuCourseSuggestDto> courseSuggestList) {
+        this.courseSuggestList = courseSuggestList;
+    }
+}

+ 104 - 0
teachcloud-obe/src/main/java/com/qmth/teachcloud/obe/been/result/report/word/custom/XagyuCourseReportBean.java

@@ -0,0 +1,104 @@
+package com.qmth.teachcloud.obe.been.result.report.word.custom;
+
+import com.deepoove.poi.data.ChartMultiSeriesRenderData;
+import com.deepoove.poi.data.TableRenderData;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.io.Serializable;
+
+/**
+ * @Description: 西安工业大学课程报告bean
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2024/10/11
+ */
+public class XagyuCourseReportBean implements Serializable {
+
+    @ApiModelProperty(name = "标题1")
+    String xagyuTitle1;
+
+    @ApiModelProperty(name = "课程bean")
+    XagyuCourseBasicBean xagyuCourseBasicBean;
+
+    @ApiModelProperty(name = "标题2")
+    String xagyuTitle2;
+
+    @ApiModelProperty(name = "课程报告表格1bean-课程目标对毕业要求的支撑")
+    TableRenderData xagyuCourseTargetTable1;
+
+    @ApiModelProperty(name = "课程报告表格2bean-评价标准")
+    TableRenderData xagyuCourseTargetTable2;
+
+    @ApiModelProperty(name = "考生表格1bean-课程目标达成情况")
+    TableRenderData xagyuExamStudentTable1;
+
+    @ApiModelProperty(name = "达成度分布柱状图")
+    ChartMultiSeriesRenderData xagyuCourseTargetColumnDiagram1;
+
+    public XagyuCourseReportBean() {
+
+    }
+
+    public XagyuCourseReportBean(String xagyuTitle1, XagyuCourseBasicBean xagyuCourseBasicBean) {
+        this.xagyuTitle1 = xagyuTitle1;
+        this.xagyuCourseBasicBean = xagyuCourseBasicBean;
+        this.xagyuTitle2 = xagyuTitle1;
+    }
+
+    public String getXagyuTitle1() {
+        return xagyuTitle1;
+    }
+
+    public void setXagyuTitle1(String xagyuTitle1) {
+        this.xagyuTitle1 = xagyuTitle1;
+    }
+
+    public XagyuCourseBasicBean getXagyuCourseBasicBean() {
+        return xagyuCourseBasicBean;
+    }
+
+    public void setXagyuCourseBasicBean(XagyuCourseBasicBean xagyuCourseBasicBean) {
+        this.xagyuCourseBasicBean = xagyuCourseBasicBean;
+    }
+
+    public String getXagyuTitle2() {
+        return xagyuTitle2;
+    }
+
+    public void setXagyuTitle2(String xagyuTitle2) {
+        this.xagyuTitle2 = xagyuTitle2;
+    }
+
+    public TableRenderData getXagyuCourseTargetTable1() {
+        return xagyuCourseTargetTable1;
+    }
+
+    public void setXagyuCourseTargetTable1(TableRenderData xagyuCourseTargetTable1) {
+        this.xagyuCourseTargetTable1 = xagyuCourseTargetTable1;
+    }
+
+    public TableRenderData getXagyuCourseTargetTable2() {
+        return xagyuCourseTargetTable2;
+    }
+
+    public void setXagyuCourseTargetTable2(TableRenderData xagyuCourseTargetTable2) {
+        this.xagyuCourseTargetTable2 = xagyuCourseTargetTable2;
+    }
+
+    public TableRenderData getXagyuExamStudentTable1() {
+        return xagyuExamStudentTable1;
+    }
+
+    public void setXagyuExamStudentTable1(TableRenderData xagyuExamStudentTable1) {
+        this.xagyuExamStudentTable1 = xagyuExamStudentTable1;
+    }
+
+    public ChartMultiSeriesRenderData getXagyuCourseTargetColumnDiagram1() {
+        return xagyuCourseTargetColumnDiagram1;
+    }
+
+    public void setXagyuCourseTargetColumnDiagram1(ChartMultiSeriesRenderData xagyuCourseTargetColumnDiagram1) {
+        this.xagyuCourseTargetColumnDiagram1 = xagyuCourseTargetColumnDiagram1;
+    }
+}

+ 62 - 0
teachcloud-obe/src/main/java/com/qmth/teachcloud/obe/been/result/report/word/custom/XagyuCourseSuggestDto.java

@@ -0,0 +1,62 @@
+package com.qmth.teachcloud.obe.been.result.report.word.custom;
+
+import com.deepoove.poi.data.ChartMultiSeriesRenderData;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import com.qmth.teachcloud.obe.been.report.CourseTargetWebDto;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.io.Serializable;
+
+/**
+ * @Description: Xagyu课程建议dto
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2024/10/11
+ */
+public class XagyuCourseSuggestDto implements Serializable {
+
+    @ApiModelProperty("目标id")
+    @JsonSerialize(using = ToStringSerializer.class)
+    private Long targetId;
+
+    @ApiModelProperty("目标名称")
+    private String targetName;
+
+    @ApiModelProperty(name = "课程目标散点图")
+    private ChartMultiSeriesRenderData xagyuCourseTargetColumnDiagram2;
+
+    public XagyuCourseSuggestDto() {
+
+    }
+
+    public XagyuCourseSuggestDto(CourseTargetWebDto courseTargetWebDto) {
+        this.targetId = courseTargetWebDto.getTargetId();
+        this.targetName = courseTargetWebDto.getTargetName();
+    }
+
+    public Long getTargetId() {
+        return targetId;
+    }
+
+    public void setTargetId(Long targetId) {
+        this.targetId = targetId;
+    }
+
+    public String getTargetName() {
+        return targetName;
+    }
+
+    public void setTargetName(String targetName) {
+        this.targetName = targetName;
+    }
+
+    public ChartMultiSeriesRenderData getXagyuCourseTargetColumnDiagram2() {
+        return xagyuCourseTargetColumnDiagram2;
+    }
+
+    public void setXagyuCourseTargetColumnDiagram2(ChartMultiSeriesRenderData xagyuCourseTargetColumnDiagram2) {
+        this.xagyuCourseTargetColumnDiagram2 = xagyuCourseTargetColumnDiagram2;
+    }
+}

+ 39 - 1
teachcloud-obe/src/main/java/com/qmth/teachcloud/obe/service/TRBasicInfoService.java

@@ -9,7 +9,9 @@ import com.qmth.teachcloud.obe.been.obe.CourseSuggestDto;
 import com.qmth.teachcloud.obe.been.report.*;
 import com.qmth.teachcloud.obe.been.result.ObeCourseWeightResult;
 import com.qmth.teachcloud.obe.been.result.report.PaperStructDimensionResult;
-import com.qmth.teachcloud.obe.been.result.report.word.CourseReportBean;
+import com.qmth.teachcloud.obe.been.result.report.word.common.CourseReportBean;
+import com.qmth.teachcloud.obe.been.result.report.word.custom.XagyuCourseReportBean;
+import com.qmth.teachcloud.obe.been.result.report.word.custom.XagyuCourseSuggestDto;
 import com.qmth.teachcloud.obe.entity.ObeCourseOutline;
 import com.qmth.teachcloud.obe.entity.TRBasicInfo;
 import org.springframework.util.LinkedMultiValueMap;
@@ -203,4 +205,40 @@ public interface TRBasicInfoService extends IService<TRBasicInfo> {
      * @return
      */
     public LinkedMultiValueMap<Long, Map<String, String>> getFinalScatterValue(Map<Long, ConcurrentMap<String, Integer>> scatterYMap);
+
+    /**
+     * 构建公共课程目标达成度模板
+     *
+     * @param trBasicInfo
+     * @return
+     */
+    public CourseReportBean buildCommonCourseDegreeReport(TRBasicInfo trBasicInfo);
+
+    /**
+     * 构建西安工业大学课程目标达成度模板
+     *
+     * @param trBasicInfo
+     * @return
+     */
+    public XagyuCourseReportBean buildXagyuCourseDegreeReport(TRBasicInfo trBasicInfo);
+
+    /**
+     * 构建西安工业大学课程目标达成度-各课程目标考核样本数据详情
+     *
+     * @param trBasicInfo
+     * @param xagyuCourseReportBean
+     * @return
+     */
+    public TableRenderData buildXagyuWordTable1(TRBasicInfo trBasicInfo, XagyuCourseReportBean xagyuCourseReportBean);
+
+    /**
+     * 构建西安工业大学课程目标达成度(散点图)
+     *
+     * @param finalScatterYMap
+     * @param courseSuggestDtoList
+     * @param courseTargetWebDtoList
+     */
+    public void buildXagyuCourseTargetColumnDiagram1(LinkedMultiValueMap<Long, Map<String, String>> finalScatterYMap,
+                                                     List<XagyuCourseSuggestDto> courseSuggestDtoList,
+                                                     List<CourseTargetWebDto> courseTargetWebDtoList);
 }

+ 370 - 1
teachcloud-obe/src/main/java/com/qmth/teachcloud/obe/service/impl/TRBasicInfoServiceImpl.java

@@ -28,7 +28,11 @@ import com.qmth.teachcloud.obe.been.report.*;
 import com.qmth.teachcloud.obe.been.result.FinalScoreResult;
 import com.qmth.teachcloud.obe.been.result.ObeCourseWeightResult;
 import com.qmth.teachcloud.obe.been.result.report.PaperStructDimensionResult;
-import com.qmth.teachcloud.obe.been.result.report.word.CourseReportBean;
+import com.qmth.teachcloud.obe.been.result.report.word.common.CourseBasicBean;
+import com.qmth.teachcloud.obe.been.result.report.word.common.CourseReportBean;
+import com.qmth.teachcloud.obe.been.result.report.word.custom.XagyuCourseBasicBean;
+import com.qmth.teachcloud.obe.been.result.report.word.custom.XagyuCourseReportBean;
+import com.qmth.teachcloud.obe.been.result.report.word.custom.XagyuCourseSuggestDto;
 import com.qmth.teachcloud.obe.entity.*;
 import com.qmth.teachcloud.obe.mapper.TRBasicInfoMapper;
 import com.qmth.teachcloud.obe.service.*;
@@ -1485,4 +1489,369 @@ public class TRBasicInfoServiceImpl extends ServiceImpl<TRBasicInfoMapper, TRBas
         }
         return finalScatterYMap;
     }
+
+    /**
+     * 构建公共课程目标达成度模板
+     *
+     * @param trBasicInfo
+     * @return
+     */
+    @Override
+    public CourseReportBean buildCommonCourseDegreeReport(TRBasicInfo trBasicInfo) {
+        //评价样本的基本信息
+        JSONObject jsonObject = JSONObject.parseObject(trBasicInfo.getCourseEvaluationResultDetail());
+        List<CourseTargetWordDto> courseTargetWordDtoList = JSONArray.parseArray(jsonObject.get("targetWordMap").toString(), CourseTargetWordDto.class);
+
+        ReportCourseEvaluationResultDto reportCourseEvaluationResultDto = JSONObject.parseObject(trBasicInfo.getCourseEvaluationResult(), ReportCourseEvaluationResultDto.class);
+
+        StringJoiner courseTarget = new StringJoiner("");
+        courseTargetWordDtoList.stream().peek(s -> {
+            courseTarget.add("      ").add(s.getTargetName()).add("——").add(s.getGraduationRequirementPoint()).add("\r\n");
+        }).collect(Collectors.toList());
+
+        CourseBasicBean courseBasicBean = new CourseBasicBean(trBasicInfo, courseTarget.toString(), reportCourseEvaluationResultDto.getTargetList().size());
+
+        CourseReportBean courseReportBean = new CourseReportBean(trBasicInfo.getOpenTime() + "《" + trBasicInfo.getCourseName() + "》", courseBasicBean);
+        //table1-课程目标目标与毕业要求指标点的对应关系
+        courseReportBean.setCourseTargetTable1(trBasicInfoService.buildWordTable1(courseTargetWordDtoList));
+
+        //table2-课程目标达成评价依据
+        courseReportBean.setCourseTargetTable2(trBasicInfoService.buildWordTable2(courseTargetWordDtoList));
+
+        //examstudent-课程目标达成评价依据-考生
+        courseReportBean.setExamStudentTable1(trBasicInfoService.buildWordTable5(trBasicInfo, courseReportBean));
+        return courseReportBean;
+    }
+
+    /**
+     * 构建西安工业大学课程目标达成度模板
+     *
+     * @param trBasicInfo
+     * @return
+     */
+    @Override
+    public XagyuCourseReportBean buildXagyuCourseDegreeReport(TRBasicInfo trBasicInfo) {
+        //评价样本的基本信息
+        JSONObject jsonObject = JSONObject.parseObject(trBasicInfo.getCourseEvaluationResultDetail());
+        List<CourseTargetWordDto> courseTargetWordDtoList = JSONArray.parseArray(jsonObject.get("targetWordMap").toString(), CourseTargetWordDto.class);
+        XagyuCourseBasicBean xagyucourseBasicBean = new XagyuCourseBasicBean(trBasicInfo);
+        XagyuCourseReportBean xagyuCourseReportBean = new XagyuCourseReportBean(trBasicInfo.getOpenTime() + "《" + trBasicInfo.getCourseName() + "》", xagyucourseBasicBean);
+        //table1-课程目标目标与毕业要求指标点的对应关系
+        xagyuCourseReportBean.setXagyuCourseTargetTable1(trBasicInfoService.buildWordTable1(courseTargetWordDtoList));
+        xagyuCourseReportBean.setXagyuCourseTargetTable2(trBasicInfoService.buildWordTable1(courseTargetWordDtoList));
+        //examstudent-课程目标达成评价依据-考生
+        xagyuCourseReportBean.setXagyuExamStudentTable1(trBasicInfoService.buildXagyuWordTable1(trBasicInfo, xagyuCourseReportBean));
+        return xagyuCourseReportBean;
+    }
+
+    /**
+     * 构建西安工业大学课程目标达成度-各课程目标考核样本数据详情
+     *
+     * @param trBasicInfo
+     * @param xagyuCourseReportBean
+     * @return
+     */
+    @Override
+    public TableRenderData buildXagyuWordTable1(TRBasicInfo trBasicInfo, XagyuCourseReportBean xagyuCourseReportBean) {
+        TableRenderData tableRenderDataExamStudent = null;
+        List<TRExamStudent> trExamStudentList = trExamStudentService.list(new QueryWrapper<TRExamStudent>().lambda()
+                .eq(TRExamStudent::getrBasicInfoId, trBasicInfo.getId()).and(w -> w.ne(TRExamStudent::getStudentCode, "目标分")));
+        if (!CollectionUtils.isEmpty(trExamStudentList)) {
+            List<CellRenderData> examStudent_cells_1 = new ArrayList<>(), examStudent_cells_2 = 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);
+
+            Map<String, Integer> targetUsualScoreSizeMap = new LinkedHashMap<>();
+            Map<Long, BigDecimal> targetCourseDegreeMap = new LinkedHashMap<>();
+            TRExamStudent trExamStudentTemp = trExamStudentList.get(0);
+
+            RowRenderData[] rowRenderDataExamStudent = new RowRenderData[trExamStudentList.size() + 3];
+            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());
+
+            rowRenderDataExamStudent[0] = examStudent_header_1;
+            rowRenderDataExamStudent[1] = examStudent_header_2;
+
+            ReportCourseEvaluationResultDto reportCourseEvaluationResultDto = JSONObject.parseObject(trBasicInfo.getCourseEvaluationResult(), ReportCourseEvaluationResultDto.class);
+            List<CourseTargetWebDto> courseTargetWebDtoList = reportCourseEvaluationResultDto.getTargetList();
+            for (CourseTargetWebDto c : courseTargetWebDtoList) {
+                if (!CollectionUtils.isEmpty(c.getEvaluationList())) {
+                    targetUsualScoreSizeMap.put(c.getTargetName(), c.getEvaluationList().size() - 1);
+                } else {
+                    targetUsualScoreSizeMap.put(c.getTargetName(), 0);
+                }
+                targetCourseDegreeMap.put(c.getTargetId(), c.getEvaluationValue());
+            }
+
+            Double courseDegree = 0.0d;
+            if (!CollectionUtils.isEmpty(targetCourseDegreeMap)) {
+                courseDegree = targetCourseDegreeMap.values().stream().filter(s -> Objects.nonNull(s)).collect(Collectors.toList()).stream().mapToDouble(b -> b.doubleValue()).min().orElse(0);
+            }
+            //首行
+            if (Objects.nonNull(trExamStudentTemp.getResultDetail())) {
+                List<ReportExamStudentTargetDto> reportExamStudentTargetDtoList = JSONArray.parseArray(trExamStudentTemp.getResultDetail(), ReportExamStudentTargetDto.class);
+                for (ReportExamStudentTargetDto reportExamStudentTargetDto : reportExamStudentTargetDtoList) {
+                    int finalScoreSize = Objects.nonNull(reportExamStudentTargetDto.getFinalScore()) ? 1 : 0;
+                    int size = finalScoreSize + (Objects.nonNull(reportExamStudentTargetDto.getUsualScore()) && !CollectionUtils.isEmpty(reportExamStudentTargetDto.getUsualScore().getScoreList()) ? reportExamStudentTargetDto.getUsualScore().getScoreList().size() : 0);
+                    examStudent_cells_1.add(Cells.of(reportExamStudentTargetDto.getTargetName()).center().create());
+                    ReportExamStudentUsualScoreDto reportExamStudentUsualScoreDto = reportExamStudentTargetDto.getUsualScore();
+                    //平常作业
+                    if (Objects.nonNull(reportExamStudentUsualScoreDto) && !CollectionUtils.isEmpty(reportExamStudentUsualScoreDto.getScoreList())) {
+                        List<ReportExamStudentUsualScoreObjDto> reportExamStudentUsualScoreObjDtoList = reportExamStudentUsualScoreDto.getScoreList();
+                        for (ReportExamStudentUsualScoreObjDto reportExamStudentUsualScoreObjDto : reportExamStudentUsualScoreObjDtoList) {
+                            examStudent_cells_1.add(Cells.of("").center().create());
+                            examStudent_cells_2.add(Cells.of(reportExamStudentUsualScoreObjDto.getEvaluation()).center().create());
+                        }
+                    }
+                    //期末考试
+                    ReportExamStudentFinalScoreDto reportExamStudentFinalScoreDto = reportExamStudentTargetDto.getFinalScore();
+                    if (Objects.nonNull(reportExamStudentFinalScoreDto) && Objects.equals(reportExamStudentFinalScoreDto.getEvaluation(), SystemConstant.FINAL_SCORE_STR)) {
+                        examStudent_cells_2.add(Cells.of(SystemConstant.FINAL_SCORE_STR).center().create());
+                    } else {
+                        int usualScoreSize = reportExamStudentTargetDto.getUsualScore().getScoreList().size();
+                        while ((size - usualScoreSize) >= 0) {
+                            examStudent_cells_1.remove(examStudent_cells_1.size() - 1);
+                            size = size - 1;
+                        }
+                    }
+                }
+                examStudent_cells_1.add(Cells.of("综合成绩").center().create());
+                examStudent_cells_2.add(Cells.of("综合成绩").center().create());
+                examStudent_cells_1.add(Cells.of("达成系数").center().create());
+                examStudent_cells_2.add(Cells.of("达成系数").center().create());
+            }
+
+            List<BigDecimal> scoreList = new ArrayList<>();
+            List<TRExamStudent> sortTrExamStudentList = new ArrayList<>();
+            sortTrExamStudentList.addAll(trExamStudentList.subList(trExamStudentList.size() - 2, trExamStudentList.size()));
+
+            Collections.reverse(sortTrExamStudentList);
+            trExamStudentList.remove(trExamStudentList.size() - 1);
+            trExamStudentList.remove(trExamStudentList.size() - 1);
+            trExamStudentList.addAll(sortTrExamStudentList);
+
+            List<TRExamStudent> trExamStudentNewList = new ArrayList<>();
+            trExamStudentNewList.addAll(trExamStudentList);
+            trExamStudentNewList.remove(trExamStudentNewList.size() - 1);
+            trExamStudentNewList.remove(trExamStudentNewList.size() - 1);
+
+            BigDecimal targetAvgScore = new BigDecimal(trExamStudentNewList.stream().mapToDouble(s -> s.getScore().doubleValue()).sum()).divide(new BigDecimal(trExamStudentNewList.size()), 2, BigDecimal.ROUND_HALF_UP).setScale(2, BigDecimal.ROUND_HALF_UP);
+            Map<Long, ConcurrentMap<String, Integer>> scatterYMap = new LinkedHashMap<>();
+            for (int i = 0; i < trExamStudentList.size(); i++) {
+                TRExamStudent trExamStudent = trExamStudentList.get(i);
+                RowRenderData examStudent_row = new RowRenderData();
+                List<CellRenderData> examStudent_cells = new ArrayList<>();
+                switch (trExamStudent.getName()) {
+                    case "平均分":
+                        examStudent_cells.add(Cells.of("平均分").create());
+                        examStudent_cells.add(Cells.of("平均分").create());
+                        examStudent_cells.add(Cells.of("平均分").create());
+                        break;
+                    case "各课程目标平均分":
+                        examStudent_cells.add(Cells.of("课程目标达成度").create());
+                        examStudent_cells.add(Cells.of("课程目标达成度").create());
+                        examStudent_cells.add(Cells.of("课程目标达成度").create());
+                        break;
+                    default:
+                        examStudent_cells.add(Cells.of(String.valueOf(i + 1)).create());
+                        examStudent_cells.add(Cells.of(trExamStudent.getStudentCode()).create());
+                        examStudent_cells.add(Cells.of(trExamStudent.getName()).create());
+                        break;
+                }
+                examStudent_cells.add(Cells.of(trExamStudent.getAdministrativeClass()).create());
+
+                if (Objects.nonNull(trExamStudent.getResultDetail())) {
+                    List<ReportExamStudentTargetDto> reportExamStudentTargetDtoList = JSONArray.parseArray(trExamStudent.getResultDetail(), ReportExamStudentTargetDto.class);
+                    for (ReportExamStudentTargetDto reportExamStudentTargetDto : reportExamStudentTargetDtoList) {
+                        if (Objects.nonNull(reportExamStudentTargetDto)) {
+                            BigDecimal matrixDegree = reportExamStudentTargetDto.getMatrixDegree();
+                            if (!Objects.equals(trExamStudent.getName(), "平均分")
+                                    && !Objects.equals(trExamStudent.getName(), "各课程目标平均分")
+                                    && Objects.nonNull(matrixDegree)) {
+                                trBasicInfoService.getScatterValue(scatterYMap, reportExamStudentTargetDto);
+                            }
+                            ReportExamStudentUsualScoreDto reportExamStudentUsualScoreDto = reportExamStudentTargetDto.getUsualScore();
+                            //平常作业
+                            if (Objects.nonNull(reportExamStudentUsualScoreDto) && !CollectionUtils.isEmpty(reportExamStudentUsualScoreDto.getScoreList())) {
+                                List<ReportExamStudentUsualScoreObjDto> reportExamStudentUsualScoreObjDtoList = reportExamStudentUsualScoreDto.getScoreList();
+                                for (ReportExamStudentUsualScoreObjDto reportExamStudentUsualScoreObjDto : reportExamStudentUsualScoreObjDtoList) {
+                                    switch (trExamStudent.getName()) {
+                                        case "平均分":
+                                            examStudent_cells.add(Cells.of(SystemConstant.df.format(reportExamStudentUsualScoreObjDto.getMatrixAvgScore())).create());
+                                            break;
+                                        case "各课程目标平均分":
+                                            examStudent_cells.add(Cells.of(targetCourseDegreeMap.get(reportExamStudentTargetDto.getTargetId()) + "").create());
+                                            break;
+                                        default:
+                                            examStudent_cells.add(Cells.of(SystemConstant.df.format(reportExamStudentUsualScoreObjDto.getScore())).create());
+                                            break;
+                                    }
+                                }
+                            }
+                            //期末考试
+                            ReportExamStudentFinalScoreDto reportExamStudentFinalScoreDto = reportExamStudentTargetDto.getFinalScore();
+                            if (Objects.nonNull(reportExamStudentFinalScoreDto) && Objects.equals(reportExamStudentFinalScoreDto.getEvaluation(), SystemConstant.FINAL_SCORE_STR)) {
+                                xagyuCourseReportBean.getXagyuCourseBasicBean().setFinalScoreWeight(reportExamStudentFinalScoreDto.getTargetWeight());
+                                switch (trExamStudent.getName()) {
+                                    case "平均分":
+                                        examStudent_cells.add(Cells.of(SystemConstant.df.format(reportExamStudentFinalScoreDto.getMatrixAvgScore())).create());
+                                        break;
+                                    case "各课程目标平均分":
+                                        examStudent_cells.add(Cells.of(targetCourseDegreeMap.get(reportExamStudentTargetDto.getTargetId()) + "").create());
+                                        break;
+                                    default:
+                                        examStudent_cells.add(Cells.of(SystemConstant.df.format(reportExamStudentFinalScoreDto.getTargetScoreSum())).create());
+                                        break;
+                                }
+                            }
+                        }
+                    }
+                }
+                switch (trExamStudent.getName()) {
+                    case "平均分":
+                        examStudent_cells.add(Cells.of(SystemConstant.df.format(targetAvgScore.setScale(2, BigDecimal.ROUND_HALF_UP))).create());
+                        break;
+                    case "各课程目标平均分":
+                        examStudent_cells.add(Cells.of("").create());
+                        break;
+                    default:
+                        scoreList.add(trExamStudent.getScore());
+                        examStudent_cells.add(Cells.of(SystemConstant.df.format(trExamStudent.getScore())).create());
+                        break;
+                }
+                String key = examStudent_cells.get(examStudent_cells.size() - 1).getParagraphs().get(0).getContents().get(0).toString();
+                if (!Objects.equals(key.trim(), "") && !Objects.equals(key.trim(), "null")) {
+                    examStudent_cells.add(Cells.of(SystemConstant.df.format(new BigDecimal(key).divide(SystemConstant.PERCENT, 2, BigDecimal.ROUND_HALF_UP))).create());
+                } else {
+                    examStudent_cells.add(Cells.of("").create());
+                }
+                examStudent_row.setCells(examStudent_cells);
+                examStudent_row.setRowStyle(this.getRowStyle());
+                rowRenderDataExamStudent[i + 2] = examStudent_row;
+            }
+            LinkedMultiValueMap<Long, Map<String, String>> finalScatterYMap = trBasicInfoService.getFinalScatterValue(scatterYMap);
+            List<CellRenderData> cellRenderData_last_cell = new ArrayList<>();
+            RowRenderData examStudent_last_row = new RowRenderData();
+            cellRenderData_last_cell.add(Cells.of("课程达成度").create());
+            cellRenderData_last_cell.add(Cells.of("课程达成度").create());
+            cellRenderData_last_cell.add(Cells.of("课程达成度").create());
+            cellRenderData_last_cell.add(Cells.of("课程达成度").create());
+
+            int cellSize = rowRenderDataExamStudent[rowRenderDataExamStudent.length - 2].getCells().size();
+            for (int i = 4; i < cellSize; i++) {
+                cellRenderData_last_cell.add(Cells.of(courseDegree + "").center().create());
+            }
+            examStudent_last_row.setCells(cellRenderData_last_cell);
+            examStudent_last_row.setRowStyle(this.getRowStyle());
+            rowRenderDataExamStudent[rowRenderDataExamStudent.length - 1] = examStudent_last_row;
+
+            //表格合并,根据坐标
+            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)));
+
+            //动态扩展列
+            List<CellRenderData> cellRenderDataList = examStudent_header_1.getCells();
+            for (int i = 0; i < cellRenderDataList.size(); i++) {
+                CellRenderData cellRenderData = cellRenderDataList.get(i);
+                String key = cellRenderData.getParagraphs().get(0).getContents().get(0).toString();
+                if (targetUsualScoreSizeMap.containsKey(key)) {
+                    Integer cellNum = targetUsualScoreSizeMap.get(key);
+                    if (cellNum.intValue() > 0) {
+                        mergeCellRuleExamStudent.getMapping().add(new MergeCellRule.GridRule(MergeCellRule.Grid.of(0, i), MergeCellRule.Grid.of(0, i + cellNum)));
+                        mergeCellRuleExamStudent.getMapping().add(new MergeCellRule.GridRule(MergeCellRule.Grid.of(rowRenderDataExamStudent.length - 2, i), MergeCellRule.Grid.of(rowRenderDataExamStudent.length - 2, i + cellNum)));
+                    }
+                }
+            }
+            mergeCellRuleExamStudent.getMapping().add(new MergeCellRule.GridRule(MergeCellRule.Grid.of(rowRenderDataExamStudent.length - 1, 4), MergeCellRule.Grid.of(rowRenderDataExamStudent.length - 1, cellSize - 1)));
+            mergeCellRuleExamStudent.getMapping().add(new MergeCellRule.GridRule(MergeCellRule.Grid.of(0, rowRenderDataExamStudent[rowRenderDataExamStudent.length - 1].getCells().size() - 2), MergeCellRule.Grid.of(1, rowRenderDataExamStudent[rowRenderDataExamStudent.length - 1].getCells().size() - 2)));
+            mergeCellRuleExamStudent.getMapping().add(new MergeCellRule.GridRule(MergeCellRule.Grid.of(0, rowRenderDataExamStudent[rowRenderDataExamStudent.length - 1].getCells().size() - 1), MergeCellRule.Grid.of(1, rowRenderDataExamStudent[rowRenderDataExamStudent.length - 1].getCells().size() - 1)));
+
+            Tables.TableBuilder tableBuilderExamStudent = Tables.ofPercentWidth(tbPercentWidth);
+            for (int i = 0; i < rowRenderDataExamStudent.length; i++) {
+                tableBuilderExamStudent.addRow(rowRenderDataExamStudent[i]);
+            }
+            tableRenderDataExamStudent = tableBuilderExamStudent.mergeRule(mergeCellRuleExamStudent).left().create();
+
+            if (!CollectionUtils.isEmpty(scoreList)) {
+                Integer[] scoreSizes = new Integer[]{0, 0, 0, 0, 0};
+                BigDecimal[] scorePercent = new BigDecimal[]{new BigDecimal(0), new BigDecimal(0), new BigDecimal(0), new BigDecimal(0), new BigDecimal(0)};
+                Map<String, Object> map = new HashMap<>();
+                Double maxScore = scoreList.stream().mapToDouble(s -> s.doubleValue()).max().orElse(0.0d);
+                Double minScore = scoreList.stream().mapToDouble(s -> s.doubleValue()).min().orElse(0.0d);
+                Double avgScore = scoreList.stream().mapToDouble(s -> s.doubleValue()).average().orElse(0.0d);
+                for (BigDecimal d : scoreList) {
+                    if (d.doubleValue() <= 100 && d.doubleValue() >= 90d) {
+                        scoreSizes[0] = scoreSizes[0] + 1;
+                    } else if (d.doubleValue() <= 89.99d && d.doubleValue() >= 80d) {
+                        scoreSizes[1] = scoreSizes[1] + 1;
+                    } else if (d.doubleValue() <= 79.99d && d.doubleValue() >= 70d) {
+                        scoreSizes[2] = scoreSizes[2] + 1;
+                    } else if (d.doubleValue() <= 69.99d && d.doubleValue() >= 60d) {
+                        scoreSizes[3] = scoreSizes[3] + 1;
+                    } else {
+                        scoreSizes[4] = scoreSizes[4] + 1;
+                    }
+                }
+                for (int i = 0; i < scoreSizes.length; i++) {
+                    scorePercent[i] = new BigDecimal(scoreSizes[i]).divide(new BigDecimal(scoreList.size()), 4, BigDecimal.ROUND_HALF_UP).multiply(SystemConstant.PERCENT).setScale(2, BigDecimal.ROUND_HALF_UP);
+                }
+                map.put("scoreSizes", scoreSizes);
+                map.put("scorePercent", scorePercent);
+                map.put("maxScore", maxScore);
+                map.put("minScore", minScore);
+                map.put("avgScore", avgScore);
+                map.put("courseTargetWebDtoList", courseTargetWebDtoList);
+                xagyuCourseReportBean.setXagyuCourseTargetTable2(this.buildWordTable6(map));
+                xagyuCourseReportBean.setXagyuCourseTargetColumnDiagram1(this.buildCourseTargetColumnDiagram2(map));
+                this.buildXagyuCourseTargetColumnDiagram1(finalScatterYMap, xagyuCourseReportBean.getXagyuCourseBasicBean().getCourseSuggestList(), courseTargetWebDtoList);
+            }
+        }
+        return tableRenderDataExamStudent;
+    }
+
+    /**
+     * 构建西安工业大学课程目标达成度(散点图)
+     *
+     * @param finalScatterYMap
+     * @param courseSuggestDtoList
+     * @param courseTargetWebDtoList
+     */
+    @Override
+    public void buildXagyuCourseTargetColumnDiagram1(LinkedMultiValueMap<Long, Map<String, String>> finalScatterYMap, List<XagyuCourseSuggestDto> courseSuggestDtoList, List<CourseTargetWebDto> courseTargetWebDtoList) {
+        Map<Long, CourseTargetWebDto> courseTargetWebDtoMap = courseTargetWebDtoList.stream().collect(Collectors.toMap(CourseTargetWebDto::getTargetId, Function.identity(), (dto1, dto2) -> dto1));
+        for (XagyuCourseSuggestDto courseSuggestDto : courseSuggestDtoList) {
+            CourseTargetWebDto courseTargetWebDto = courseTargetWebDtoMap.get(courseSuggestDto.getTargetId());
+            List<Map<String, String>> list = finalScatterYMap.get(courseSuggestDto.getTargetId());
+            if (Objects.nonNull(courseTargetWebDto) && !CollectionUtils.isEmpty(list)) {
+                List<String> valueXList = new ArrayList<>();
+                List<Number> titleYList = new ArrayList<>();
+                for (Map<String, String> m : list) {
+                    for (Map.Entry<String, String> entry : m.entrySet()) {
+                        valueXList.add(entry.getValue());
+                        titleYList.add(Double.parseDouble(entry.getKey()));
+                    }
+                }
+                ChartMultiSeriesRenderData scatterMap = Charts.ofMultiSeries(courseTargetWebDto.getTargetName(), valueXList.toArray(new String[valueXList.size()]))
+                        .addSeries("Y值", titleYList.toArray(new Number[titleYList.size()]))
+                        .setxAsixTitle("学生代号")
+                        .setyAsixTitle("达成值" + SystemConstant.df.format(courseTargetWebDto.getEvaluationValue()))
+                        .create();
+                courseSuggestDto.setXagyuCourseTargetColumnDiagram2(scatterMap);
+            }
+        }
+    }
 }