Browse Source

Merge branch 'beta' of https://git.cocorobo.cn/CocoRoboLabs/pbl-teacher-table into beta

SanHQin 1 month ago
parent
commit
5bcfc2251c

+ 1 - 1
dist/index.html

@@ -32,7 +32,7 @@
       width: 100%;
       background: #e6eaf0;
       font-family: '黑体';
-    }</style><link href=./static/css/app.6abdbeeaff0b386b1d5bec5bee3f74f5.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=./static/js/manifest.571c38d63f24b1ae9e16.js></script><script type=text/javascript src=./static/js/vendor.a82b79982b082928b294.js></script><script type=text/javascript src=./static/js/app.320e3975a16e27287d9d.js></script></body></html><script>function stopSafari() {
+    }</style><link href=./static/css/app.6e29f274ebd05a0260e498fa7701846d.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=./static/js/manifest.571c38d63f24b1ae9e16.js></script><script type=text/javascript src=./static/js/vendor.a82b79982b082928b294.js></script><script type=text/javascript src=./static/js/app.1af7eaa3be4e2739593c.js></script></body></html><script>function stopSafari() {
     //阻止safari浏览器双击放大功能
     let lastTouchEnd = 0  //更新手指弹起的时间
     document.documentElement.addEventListener("touchstart", function (event) {

File diff suppressed because it is too large
+ 0 - 0
dist/static/css/app.6abdbeeaff0b386b1d5bec5bee3f74f5.css


File diff suppressed because it is too large
+ 0 - 0
dist/static/css/app.6abdbeeaff0b386b1d5bec5bee3f74f5.css.map


File diff suppressed because it is too large
+ 0 - 0
dist/static/css/app.6e29f274ebd05a0260e498fa7701846d.css


File diff suppressed because it is too large
+ 0 - 0
dist/static/css/app.6e29f274ebd05a0260e498fa7701846d.css.map


File diff suppressed because it is too large
+ 6 - 0
dist/static/img/logo2.4f91689.svg


File diff suppressed because it is too large
+ 0 - 0
dist/static/js/app.1af7eaa3be4e2739593c.js


File diff suppressed because it is too large
+ 0 - 0
dist/static/js/app.1af7eaa3be4e2739593c.js.map


File diff suppressed because it is too large
+ 0 - 0
dist/static/js/manifest.571c38d63f24b1ae9e16.js.map


BIN
src/assets/icon/course/pasete.png


+ 5 - 0
src/assets/icon/exportPdfworks/infocircle.svg

@@ -0,0 +1,5 @@
+<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M5.62921 8.99982V4.875H6.37921V8.99982H5.62921Z" fill="black" fill-opacity="0.6"/>
+<path d="M6.44989 3H5.54993V3.89996H6.44989V3Z" fill="black" fill-opacity="0.6"/>
+<path d="M0.75 6C0.75 8.89948 3.10052 11.25 6 11.25C8.89948 11.25 11.25 8.89948 11.25 6C11.25 3.10052 8.89948 0.75 6 0.75C3.10052 0.75 0.75 3.10052 0.75 6ZM1.5 6C1.5 3.51471 3.51471 1.5 6 1.5C8.48529 1.5 10.5 3.51471 10.5 6C10.5 8.48529 8.48529 10.5 6 10.5C3.51471 10.5 1.5 8.48529 1.5 6Z" fill="black" fill-opacity="0.6"/>
+</svg>

BIN
src/assets/icon/exportPdfworks/title.png


File diff suppressed because it is too large
+ 649 - 44
src/components/pages/aiAddCourse/addCourse.vue


+ 75 - 6
src/components/pages/aiAddCourse/aiBoxRight.vue

@@ -19,8 +19,11 @@
             minHeight: item.loading ? '50px' : 'unset',
             minWidth: item.loading ? '50px' : 'unset'
           }" class="content" v-loading="item.loading">
-            <span class="vditor-reset" v-html="item.aiContent"></span><span class="createTime"
-              v-text="item.createtime"></span>
+            <span class="vditor-reset" v-html="item.aiContent"></span>
+            <span class="createTime" v-text="item.createtime"></span>
+          </div>
+          <div class="ai_btn_box" v-if="!pan(item.aiContent).length && !item.loading">
+            <img src="../../../assets/icon/course/pasete.png" @click="onCopy(item.aiContent)" >
           </div>
         </div>
       </div>
@@ -113,7 +116,7 @@
       <div class="ai_b_i_jListPanel" @click="showjList = !showjList" v-if="showjList && jArray.length > 0"></div>
       <div class="ai_b_i_jListBox" v-if="showjList && jArray.length > 0">
         <div class="jlist_box" v-for="(item, index) in jArray" :key="index">
-          <el-tooltip :content="item.area + ':' + item.value" placement="top" effect="dark" popper-class="text_tooltip2">
+          <el-tooltip :content="item.area + ':' + item.value" placement="left" effect="dark" popper-class="text_tooltip2">
             <!-- content to trigger tooltip here -->
             <span>{{ item.area }}:{{ item.value }}</span>
           </el-tooltip>
@@ -162,6 +165,9 @@ import checkImg from "../../../assets/icon/sourceFile/check.png";
 import checkIsImg from "../../../assets/icon/sourceFile/check_is.png";
 import { v4 as uuidv4 } from "uuid";
 import MarkdownIt from "markdown-it";
+import TurndownService from 'turndown';
+
+
 export default {
   props: {
     unitJson: {
@@ -286,7 +292,7 @@ export default {
       showRoleList: false,
       choseRoleItem: 0,
       choseTextItem: 0,
-      continuous: false,
+      continuous: true,
       showjList: false
     };
   },
@@ -1007,9 +1013,62 @@ ATTENTION: Use '##' to SPLIT SECTIONS, not '#'.Output format carefully reference
         } `;
       this.$refs.textareaRef.focus();
       this.showRoleList = false;
-    }
+    },
+    onCopy(content) {
+      const turndownService = new TurndownService();
+      // 添加自定义规则来处理表格
+      turndownService.addRule('table', {
+        filter: 'table',
+        replacement: (content, node) => {
+          const rows = node.querySelectorAll('tr');
+          let markdown = '';
+
+          rows.forEach((row) => {
+            const cells = row.querySelectorAll('th, td');
+            const rowMarkdown = Array.from(cells).map(cell => cell.textContent).join(' | ');
+            markdown += `| ${rowMarkdown} |\n`;
+            if(cells && cells.length && cells[0].tagName == 'TH'){
+              let a = Array.from(cells).map(cell => '').join(' --- |')
+              markdown += `| --- |${a}\n`;
+            }
+          });
+
+          // 添加分隔行
+          // markdown = markdown.replace(/^/, '| --- |\n');
+          return markdown;
+        },
+      });
+      // 创建临时textarea元素
+      const tempInput = document.createElement("textarea");
+      
+      tempInput.value = turndownService.turndown(content); // 设置要复制的内容
+      // 隐藏元素
+      tempInput.style.position = "absolute";
+      tempInput.style.left = "-9999px";
+      // 将元素添加到DOM中
+      document.body.appendChild(tempInput);
+      // 选中元素内容
+      tempInput.select();
+      // 执行复制操作
+      document.execCommand("copy");
+      // 移除临时元素
+      document.body.removeChild(tempInput);
+      this.$message({
+        message: "复制成功",
+        type: "success"
+      });
+    },
   },
   computed: {
+    pan() {
+      return content => {
+        try {
+          return JSON.parse(content);
+        } catch (error) {
+          return [];
+        }
+      };
+    },
     courseTextLength() {
       return this.courseText.length;
     },
@@ -1429,7 +1488,7 @@ ATTENTION: Use '##' to SPLIT SECTIONS, not '#'.Output format carefully reference
   word-break: break-word;
   box-sizing: border-box;
   /* white-space: pre-line; */
-  max-width: calc(100% - 50px);
+  max-width: calc(100% - 85px);
   background: #f6f9ff;
   /* overflow: hidden; */
   margin: 0 10px;
@@ -1665,4 +1724,14 @@ ATTENTION: Use '##' to SPLIT SECTIONS, not '#'.Output format carefully reference
   overflow: hidden;
   word-break: break-all;
 }
+
+.ai_btn_box{
+  min-width: fit-content;
+  margin-top: auto;
+}
+
+.ai_btn_box > img{
+  cursor: pointer;
+  width: 15px;
+}
 </style>

+ 1581 - 0
src/components/pages/components/exportDataDialog.vue

@@ -0,0 +1,1581 @@
+<template>
+  <div class="pbl">
+    <!-- <button @click="lookPage">导出</button> -->
+    <!-- <el-dialog
+      title="导出作业集"
+      :visible.sync="worksDialog"
+      :before-close="handleClose"
+      class="full_diy"
+      :append-to-body="true"
+    > -->
+    <!-- :style="{ backgroundColor: schoolImg.bkColor, position: 'relative' }" -->
+    <div ref="reportPdf" v-loading="loading">
+      <div
+        class="coverPage"
+        :style="{
+          backgroundColor: schoolImg.bkColor ? schoolImg.bkColor : '#E5EFFE'
+        }"
+      >
+        <div class="coverPageLogo">
+          <img :src="schoolImg.logo ? schoolImg.logo : ''" alt="" />
+        </div>
+        <div class="coverPageFrom" style="z-index: 10;">
+          <div class="coverPageFromTit">
+            <img src="../../../assets/icon/exportPdfworks/title.png" alt="" />
+          </div>
+
+          <div class="fromCss">
+            <div>
+              <span>姓名:</span>
+              <div class="txt">{{ worksDialogCon2.sName }}</div>
+            </div>
+            <div>
+              <span>班级:</span>
+              <div class="txt">{{ worksDialogCon2.class }}</div>
+            </div>
+            <div>
+              <span>学校:</span>
+              <div class="txt">{{ worksDialogCon2.schName }}</div>
+            </div>
+          </div>
+        </div>
+        <div class="coverPageFrom">
+          <img
+            style="z-index: 10;"
+            src="../../../assets/icon/exportPdfworks/cocoroboCon.svg"
+            alt=""
+          />
+        </div>
+      </div>
+
+      <div class="coverPageCon">
+        <div
+          style="
+                text-align: center;
+                font-weight: 600;
+                font-size: 26px;
+                margin: 10px 0;
+                color: rgba(58, 59, 152, 1);
+              "
+        >
+          {{ courseTit }}
+        </div>
+        <div
+          style="font-weight: 600; font-size: 16px; color: rgba(0, 0, 0, 0.9);margin: 10px 0;"
+        >
+          <li>学习总览</li>
+        </div>
+        <div
+          style="
+                text-align: center;
+                font-weight: 600;
+                font-size: 14px;
+                color: rgba(0, 0, 0, 0.9);
+                margin: 10px 0;
+              "
+        >
+          综合表现
+        </div>
+
+        <div style="display: flex; justify-content: space-between">
+          <div class="zhBlock">
+            <div class="zhBlockTit">
+              <span style="margin-right: 5px">登录时长</span
+              ><img
+                src="../../../assets/icon/exportPdfworks/infocircle.svg"
+                alt=""
+              />
+            </div>
+            <div class="zhBlockCon">{{ loginTime }}</div>
+          </div>
+          <div class="zhBlock">
+            <div class="zhBlockTit">
+              <span style="margin-right: 5px">学习时长</span
+              ><img
+                src="../../../assets/icon/exportPdfworks/infocircle.svg"
+                alt=""
+              />
+            </div>
+            <div class="zhBlockCon">{{ studyTime }}</div>
+          </div>
+          <div class="zhBlock">
+            <div class="zhBlockTit">
+              <span style="margin-right: 5px">学习成绩</span
+              ><img
+                src="../../../assets/icon/exportPdfworks/infocircle.svg"
+                alt=""
+              />
+            </div>
+            <div class="zhBlockCon">
+              <div class="zhBlockCon">{{ star }} / 5.0</div>
+            </div>
+          </div>
+          <div class="zhBlock">
+            <div class="zhBlockTit">
+              <span style="margin-right: 5px">包含学科</span
+              ><img
+                src="../../../assets/icon/exportPdfworks/infocircle.svg"
+                alt=""
+              />
+            </div>
+            <div class="zhBlockCon2">
+              <div>
+               <span v-for="(i,index) in subject" :key="index">{{ i }}</span>
+              </div>
+            </div>
+          </div>
+        </div>
+        <div
+          style="display: flex;justify-content: space-between; height: 310px;margin-bottom: 30px"
+        >
+          <div class="zxt" style="width: 49%">
+            <div ref="chart" style="width: 100%; height: 300px"></div>
+          </div>
+          <div class="zxt" style="width: 49%">
+            <div ref="ringChart" style="height: 300px; width: 100%"></div>
+          </div>
+        </div>
+        <!-- 作业提交率 -->
+        <div class="zxt">
+          <div style="height: 350px; width: 100%" ref="toolSubEcharts"></div>
+        </div>
+
+        <!-- 分组工具使用数量  -->
+        <div class="zxt">
+          <div style="height: 350px; width: 100%" ref="groupingEcharts"></div>
+        </div>
+        <!-- 师生互动次数  -->
+        <div class="zxt">
+          <div
+            style="height: 350px; width: 100%"
+            ref="interactionEcharts"
+          ></div>
+        </div>
+        <!-- 互动次数主动  -->
+        <div class="zxt">
+          <div
+            style="height: 350px; width: 100%"
+            ref="stuInteractZdEcharts"
+          ></div>
+        </div>
+        <!-- 互动次数主动  -->
+        <div class="zxt">
+          <div
+            style="height: 350px; width: 100%"
+            ref="bdStuInteractZdEcharts"
+          ></div>
+        </div>
+        <!-- 课程得分  -->
+        <div class="zxt">
+          <div style="height: 350px; width: 100%" ref="cScoEcharts"></div>
+        </div>
+        <div style="display: flex;justify-content: flex-end;">
+          <img :src="schoolImg.bjLogo ? schoolImg.bjLogo : ''" alt="" />
+        </div>
+      </div>
+    </div>
+
+    <!-- </el-dialog> -->
+  </div>
+</template>
+
+<script>
+import html2canvas from "html2canvas";
+import jspdf from "jspdf";
+import JSZip from "jszip";
+import * as echarts from "echarts";
+
+export default {
+  props: [
+    "multipleSelection",
+    "cid",
+    "worksDialog",
+    "worksDialogCon",
+    "digNum"
+  ],
+
+  data() {
+    return {
+      star: 0,
+      // 课程类型
+      cState: "",
+      // 课程名称
+      courseTit: "",
+      // 学习时长
+      studyTime: "",
+      // 登录时长
+      loginTime: "",
+
+      // 五边形图开始
+      chartData: [
+        [1, 2, 3, 4, 5],
+        [2, 3, 4, 3, 2]
+      ],
+      categories: ["A", "B", "C", "D", "E"],
+      // 五边形图结束
+
+      // 环形图数据开始
+      toolData: [[], [], [], [], [], [], []],
+      toolRatio: [
+        { name: "互动类", value: 0 },
+        { name: "思维类", value: 0 },
+        { name: "协作类", value: 0 },
+        { name: "测评类", value: 0 },
+        { name: "评价类", value: 0 },
+        { name: "编程类", value: 0 },
+        { name: "学科类", value: 0 }
+      ],
+      // 环形图数据结束
+
+      // 作业提交率折线图开始
+      stageList: [], // 阶段
+      stageListPer: [], // 阶段所占百分比
+      toolPercentage: [], // 每个阶段有的工具
+      // 作业提交率折线图结束
+
+      // 作业得分折线图开始
+      taskList: [], //每个阶段下有几个任务
+      scoFoldLineData: [], //课程得分图数据
+      // 作业得分折线图结束
+
+      // 分数工具柱状图开始
+      columnData: [],
+      // 分数工具柱状图结束
+
+      // 师生在线互动次数开始
+      interact: [], //每个阶段下师生互动工具
+      interactWork: [], //每个工具下提交的作业
+      // 师生在线互动次数结束
+
+      // 生生互动主动开始
+      stuInterAllWork: [],
+      stuInterAllLike: [],
+
+      // 生生互动主动结束
+
+      // 生生互动被动开始
+      bdStuInterAllWork: [],
+      bdStuInterAllLike: [],
+      // 生生互动被动结束
+
+      // 工具类大分类
+      hd: [10, 65],
+      sw: [7, 1, 52, 3, 52],
+      xz: [49],
+      cp: [4, 45, 15, 16, 50, 41, 47],
+      pj: [40],
+      bc: [18, 21, 23, 24, 32, 57, 63, 71],
+      xk: [28, 31, 39, 66, , 68, 69, 70],
+      // 师生互动工具list
+      TeaStuInt: [7, 1, 52, 3, 48, 15, 16, 50, 57],
+      // 处理过的分组
+      TeaStuInt2: [1, 3, 5, 4, 10, 13, 15],
+
+      subject:[],
+
+      data3: [],
+      data4: [],
+      data5: [],
+      data6: [],
+      data7: [],
+      data8: [],
+      data9: [],
+      oid: this.$route.query.oid,
+      org: this.$route.query.org,
+      uid2: "",
+      worksDialogCon2: "",
+
+      loading: false,
+      userInfo: "",
+      tableData: [],
+      courseName: "",
+      imgList: [
+        {
+          schoolId: "45facc0a-1211-11ec-80ad-005056b86db5",
+          logo: require("../../../assets/icon/exportPdfworks/cocoroboLogo.svg"),
+          conImg: require("../../../assets/icon/exportPdfworks/cocoroboCon.svg"),
+          bjLogo: require("../../../assets/icon/exportPdfworks/logo2.svg"),
+          bkColor: "#E5EFFE"
+        }
+      ],
+      schoolImg: {}
+    };
+  },
+  mounted() {
+    if (this.digNum == 0) {
+      this.downPdf();
+    } else {
+      this.getWorks1();
+    }
+    // this.getCourseDetail();
+  },
+
+  methods: {
+    // 下载单个文件
+    async downPdf() {
+      this.loading = true;
+      this.tableData = this.multipleSelection;
+      if (!this.tableData.length) {
+        this.loading = false;
+        return this.$message.info("请选择数据后,再进行导出");
+      }
+      if (this.tableData.length == 1) {
+        this.uid2 = this.tableData[0].userid;
+        this.worksDialogCon2 = this.tableData[0];
+        await this.getData();
+        await this.getPdf();
+      } else {
+        this.circulatePdf();
+      }
+    },
+    // 下载pdf文件
+    async getPdf() {
+      let domHeight = this.$refs.reportPdf.offsetHeight;
+      // console.log('this.$refs.reportPdf',this.$refs.reportPdf.offsetHeight);
+      let maxHeight = 64257;
+      return new Promise((resolve, reject) => {
+        html2canvas(this.$refs.reportPdf, {
+          useCORS: true, // 如果截图的内容里有图片,可能会有跨域的情况,加上这个参数,解决文件跨域问题
+          scale: maxHeight / domHeight > 1 ? 1 : maxHeight / domHeight
+        })
+          .then(canvas => {
+            const contentWidth = canvas.width;
+            const contentHeight = canvas.height;
+
+            var pageData = canvas.toDataURL("image/jpeg", 1.0);
+
+            var pdf = new jspdf("", "pt", [contentWidth, contentHeight]);
+
+            //有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)
+            //当内容未超过pdf一页显示的范围,无需分页
+            // if (leftHeight < pageHeight) {
+            pdf.addImage(pageData, "JPEG", 0, 0, contentWidth, contentHeight);
+
+            pdf.save(
+              this.worksDialogCon2.course +
+                "-作业集-" +
+                this.worksDialogCon2.sName +
+                ".pdf"
+            );
+            return resolve();
+          })
+          .catch(err => {
+            console.log(err);
+          });
+      });
+    },
+    // 获取所有作业然后一键打包压缩包
+    getWorks1() {
+      this.loading = true;
+
+      let params = {
+        cid: this.cid,
+        uname: "",
+        choseClass: "",
+        stage: "",
+        task: ""
+      };
+
+      this.ajax
+        .get(this.$store.state.api + "getCourseWorks6", params) //getCourseWorks4
+        .then(res => {
+          this.tableData = res.data[0];
+
+          if (!this.tableData.length) {
+            this.loading = false;
+            return this.$message.info("课程下未有提交作业");
+          }
+          this.courseName = this.tableData[0].course;
+          this.circulatePdf();
+          // console.log(res.data[0]);
+        })
+        .catch(err => {
+          this.isLoading = false;
+          console.error(err);
+        });
+    },
+    // 一键打包所有作业
+    async circulatePdf() {
+      let _this = this;
+      var zip = new JSZip();
+      let pdfList = [];
+      for (let i = 0; i < this.tableData.length; i++) {
+        this.loading = true;
+
+        this.toolRatio = [
+          { name: "互动类", value: 0 },
+          { name: "思维类", value: 0 },
+          { name: "协作类", value: 0 },
+          { name: "测评类", value: 0 },
+          { name: "评价类", value: 0 },
+          { name: "编程类", value: 0 },
+          { name: "学科类", value: 0 }
+        ];
+        this.uid2 = this.tableData[i].userid;
+        this.worksDialogCon2 = this.tableData[i];
+        await this.getData();
+        let a = await this.getPdf2();
+        pdfList.push(a);
+      }
+
+      pdfList.forEach((e, index) => {
+        zip.file(e.pdfName, e.pdfCon);
+      });
+
+      // 生成压缩包并提供下载链接
+      zip.generateAsync({ type: "blob" }).then(function(content) {
+        // 使用FileSaver保存压缩包
+        saveAs(content, _this.courseTit + "-学生报告汇总.zip");
+      });
+
+      this.$emit("update:worksDialog", false);
+      // this.worksDialog = false;
+    },
+    // 压缩pdf
+    async getPdf2() {
+      let domHeight = this.$refs.reportPdf.offsetHeight;
+      // console.log('this.$refs.reportPdf',this.$refs.reportPdf.offsetHeight);
+      let maxHeight = 64257;
+      return new Promise((resolve, reject) => {
+        html2canvas(this.$refs.reportPdf, {
+          useCORS: true, // 如果截图的内容里有图片,可能会有跨域的情况,加上这个参数,解决文件跨域问题
+          scale: maxHeight / domHeight > 1 ? 1 : maxHeight / domHeight
+        })
+          .then(canvas => {
+            const contentWidth = canvas.width;
+            const contentHeight = canvas.height;
+
+            var pageData = canvas.toDataURL("image/jpeg", 1.0);
+
+            var pdf = new jspdf("", "pt", [contentWidth, contentHeight]);
+
+            //有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)
+            //当内容未超过pdf一页显示的范围,无需分页
+            // if (leftHeight < pageHeight) {
+            pdf.addImage(pageData, "JPEG", 0, 0, contentWidth, contentHeight);
+
+            var pdfData = {
+              pdfName:
+                this.worksDialogCon2.course +
+                "-作业集-" +
+                this.worksDialogCon2.sName +
+                ".pdf",
+              pdfCon: pdf.output("blob")
+            };
+            // pdfArray.push(pdfData);
+
+            return resolve(pdfData);
+          })
+          .catch(err => {
+            console.log(err);
+          });
+      });
+    },
+    async getData() {
+      this.subject=[]
+      let params = {
+        cid: this.cid,
+        uid: this.worksDialogCon2.userid,
+        cla: ""
+      };
+      return new Promise((resolve, reject) => {
+        this.ajax
+          .get(this.$store.state.api + "selectStuCourseReportPdf", params) //getCourseWorksReport
+          .then(res => {
+            this.cState = res.data[0][0].state;
+            this.courseTit = res.data[0][0].title;
+
+            let sub = res.data[9][0].subject
+            this.subject = sub.split(',')
+
+            this.imgList.forEach(e => {
+              if (e.schoolId == this.oid) {
+                this.schoolImg = e;
+              }
+            });
+
+            // 0 课程信息
+            // 1获取登录时长
+            // 3获取学习时长
+            //  4获取学生提交作业
+            //  5获取单个学生作业分数
+            //  6获取教师评价作业
+            //  7获取所有学生提交作业
+            //  8学生点赞评论次数
+            //  9学生被点赞评论次数
+            let oneTime = 0;
+            res.data[1].forEach(e => {
+              oneTime += e.text * 1;
+            });
+            this.loginTime = this.secondsToDhms(oneTime);
+
+            let twoTime = 0;
+            res.data[2].forEach(e => {
+              twoTime += e.text * 1;
+            });
+            this.studyTime = this.secondsToDhms(twoTime);
+
+            this.data3 = res.data[3];
+            this.data4 = res.data[4];
+            this.data5 = res.data[5];
+            this.data6 = res.data[6];
+            this.data7 = res.data[7];
+            this.data8 = res.data[8];
+            this.data9 = res.data[9];
+
+            // 处理这个课程下的工具分类
+            let data = JSON.parse(res.data[0][0].chapters);
+            
+
+            if (this.cState == 1) {
+              this.getDataStageMode(data);
+            } else {
+              this.getDataAiMode(data);
+            }
+
+            // 将课程的所有工具进行分类,然后装在变量里 , 获取所有折线图阶段
+            // console.log("data", data);
+            this.loading = false;
+
+            setTimeout(() => {
+              return resolve();
+            }, 1500);
+          })
+          .catch(err => {
+            console.error(err);
+          });
+      });
+    },
+    // ai模式处理数据
+    getDataAiMode(data) {
+      this.toolData = [[], [], [], [], [], [], []];
+      this.taskList = []; //每个阶段下有几个任务
+      this.toolPercentage = [];
+      this.interact = [];
+      this.interactWork = [];
+      this.stuInterAllWork = [];
+      this.stuInterAllLike = [];
+      this.bdStuInterAllWork = [];
+      this.bdStuInterAllLike = [];
+      this.stageList = [];
+      this.stageListPer = [];
+      data.forEach((e, eInd) => {
+        let toolList = e.chapterInfo[0].taskJson;
+        toolList.forEach((i, iInd) => {
+          this.stageList.push("任务" + (iInd * 1 + 1));
+          this.toolPercentage[iInd] = []; // 每个任务有的工具
+          this.stageListPer.push(0); // 作业提交率基础数据折线图
+          // 课程阶段下互动数据工具
+          this.interact[iInd] = [];
+
+          this.interactWork[iInd] = []; //每个工具下提交的作业
+
+          this.stuInterAllWork[iInd] = []; // 生生互动阶段作业分类
+          this.stuInterAllLike[iInd] = []; // 生生互动阶段点赞评论分类
+
+          this.bdStuInterAllWork[iInd] = []; // 生生互动阶段被动作业分类
+          this.bdStuInterAllLike[iInd] = []; // 生生互动阶段被动点赞评论分类
+
+          i.toolChoose.forEach(k => {
+            if (k.tool[0]) {
+              this.toolPercentage[iInd].push(k.tool[0]);
+              if (this.TeaStuInt.indexOf(k.tool[0]) != -1) {
+                this.interact[iInd].push(k.tool[0]);
+              }
+              if (this.hd.indexOf(k.tool[0]) != -1) {
+                this.toolData[0].push(k);
+              }
+              if (this.sw.indexOf(k.tool[0]) != -1) {
+                this.toolData[1].push(k);
+              }
+              if (this.xz.indexOf(k.tool[0]) != -1) {
+                this.toolData[2].push(k);
+              }
+              if (this.cp.indexOf(k.tool[0]) != -1) {
+                this.toolData[3].push(k);
+              }
+              if (this.pj.indexOf(k.tool[0]) != -1) {
+                this.toolData[4].push(k);
+              }
+              if (this.bc.indexOf(k.tool[0]) != -1) {
+                this.toolData[5].push(k);
+              }
+              if (this.xk.indexOf(k.tool[0]) != -1) {
+                this.toolData[6].push(k);
+              }
+            }
+          });
+        });
+      });
+      // console.log("this.toolData", this.toolData);
+
+      // 环形图占比
+      this.toolRatio[0].value = this.toolData[0].length;
+      this.toolRatio[1].value = this.toolData[1].length;
+      this.toolRatio[2].value = this.toolData[2].length;
+      this.toolRatio[3].value = this.toolData[3].length;
+      this.toolRatio[4].value = this.toolData[4].length;
+      this.toolRatio[5].value = this.toolData[5].length;
+      this.toolRatio[6].value = this.toolData[6].length;
+      this.toolRatio = this.toolRatio.filter(e => {
+        return e.value != 0;
+      });
+      // console.log("this.toolRatio[0]", this.toolRatio);
+      // 作业提交率折线图
+      let repeatWork = this.newArrFn(this.data3);
+      // console.log("repeatWork", repeatWork);
+
+      this.getFoldLineDataAi(repeatWork);
+
+      // 计算任务得分
+      this.getFoldLineSCoDataAi(this.data4);
+
+      // 计算分组工具使用比例
+      this.getColumnData();
+
+      // 师生互动数据
+      let TeaStuHdData = [];
+      repeatWork.forEach(e => {
+        if (this.TeaStuInt2.indexOf(e.type) != -1) {
+          TeaStuHdData.push(e);
+        }
+      });
+      this.getTeaStuHdAi(TeaStuHdData);
+
+      // 生生互动主动
+      this.getStuInterAllWorkAi(this.data6, this.data7);
+
+      // // 生生互动被动
+      this.getBdStuInterAllWorkAi(this.data6, this.data8);
+
+      setTimeout(() => {
+        this.renderChart();
+        this.renderChart2();
+        this.initChart();
+        this.initChart2();
+        this.initChart3();
+        this.initChart4();
+        this.initChart5();
+        this.initChart6();
+      }, 500);
+    },
+    // 阶段模式处理数据
+    getDataStageMode(data) {
+      this.toolData = [[], [], [], [], [], [], []];
+      this.taskList = []; //每个阶段下有几个任务
+      this.toolPercentage = [];
+      this.interact = [];
+      this.interactWork = [];
+      this.stuInterAllWork = [];
+      this.stuInterAllLike = [];
+      this.bdStuInterAllWork = [];
+      this.bdStuInterAllLike = [];
+      this.stageList = [];
+      this.stageListPer = [];
+
+      data.forEach((e, eInd) => {
+        let toolList = e.chapterInfo[0].taskJson;
+        this.toolPercentage[eInd] = []; // 每个任务有的工具
+        // X轴数据
+        this.stageList.push("阶段" + (eInd * 1 + 1));
+        // 作业提交率基础数据
+        this.stageListPer.push(0);
+
+        // 课程阶段下互动数据工具
+        this.interact[eInd] = [];
+        //每个工具下提交的作业
+        this.interactWork[eInd] = [];
+
+        this.stuInterAllWork[eInd] = []; // 生生互动阶段作业分类
+        this.stuInterAllLike[eInd] = []; // 生生互动阶段点赞评论分类
+
+        this.bdStuInterAllWork[eInd] = []; // 生生互动阶段被动作业分类
+        this.bdStuInterAllLike[eInd] = []; // 生生互动阶段被动点赞评论分类
+
+        // 每个阶段下有多少个任务
+        console.log("toolList", JSON.parse(JSON.stringify(toolList)));
+
+        this.taskList[eInd] = toolList;
+
+        toolList.forEach(i => {
+          i.toolChoose.forEach(k => {
+            if (k.tool[0]) {
+              this.toolPercentage[eInd].push(k.tool[0]);
+
+              if (this.TeaStuInt.indexOf(k.tool[0]) != -1) {
+                this.interact[eInd].push(k.tool[0]);
+              }
+              if (this.hd.indexOf(k.tool[0]) != -1) {
+                this.toolData[0].push(k);
+              }
+              if (this.sw.indexOf(k.tool[0]) != -1) {
+                this.toolData[1].push(k);
+              }
+              if (this.xz.indexOf(k.tool[0]) != -1) {
+                this.toolData[2].push(k);
+              }
+              if (this.cp.indexOf(k.tool[0]) != -1) {
+                this.toolData[3].push(k);
+              }
+              if (this.pj.indexOf(k.tool[0]) != -1) {
+                this.toolData[4].push(k);
+              }
+              if (this.bc.indexOf(k.tool[0]) != -1) {
+                this.toolData[5].push(k);
+              }
+              if (this.xk.indexOf(k.tool[0]) != -1) {
+                this.toolData[6].push(k);
+              }
+            }
+          });
+        });
+      });
+      // 环形图占比
+      this.toolRatio[0].value = this.toolData[0].length;
+      this.toolRatio[1].value = this.toolData[1].length;
+      this.toolRatio[2].value = this.toolData[2].length;
+      this.toolRatio[3].value = this.toolData[3].length;
+      this.toolRatio[4].value = this.toolData[4].length;
+      this.toolRatio[5].value = this.toolData[5].length;
+      this.toolRatio[6].value = this.toolData[6].length;
+      this.toolRatio = this.toolRatio.filter(e => {
+        return e.value != 0;
+      });
+      // 作业提交率折线图
+      let repeatWork = this.newArrFn(this.data3);
+      this.getFoldLineData(repeatWork);
+
+      // 计算任务得分
+      this.getFoldLineSCoData(this.data4);
+
+      // 计算分组工具使用比例
+      this.getColumnData();
+
+      // 师生互动数据
+      let TeaStuHdData = [];
+      repeatWork.forEach(e => {
+        if (this.TeaStuInt2.indexOf(e.type) != -1) {
+          TeaStuHdData.push(e);
+        }
+      });
+      this.getTeaStuHd(TeaStuHdData);
+
+      // 生生互动主动
+      this.getStuInterAllWork(this.data6, this.data7);
+
+      // 生生互动被动
+      this.getBdStuInterAllWork(this.data6, this.data8);
+
+      setTimeout(() => {
+        this.renderChart();
+        this.renderChart2();
+        this.initChart();
+        this.initChart2();
+        this.initChart3();
+        this.initChart4();
+        this.initChart5();
+        this.initChart6();
+      }, 500);
+    },
+
+    // 生生互动被动
+    getBdStuInterAllWork(val, likeData) {
+      this.bdStuInterAllWork.forEach((e, index) => {
+        val.forEach(k => {
+          if (k.stage == index) {
+            e.push(k.id);
+          }
+        });
+      });
+      this.bdStuInterAllWork.forEach((e, index) => {
+        likeData.forEach(k => {
+          if (e.indexOf(k.workId) != -1) {
+            this.bdStuInterAllLike[index].push(k);
+          }
+        });
+      });
+    },
+
+    // 生生互动主动
+    getStuInterAllWork(val, likeData) {
+      this.stuInterAllWork.forEach((e, index) => {
+        val.forEach(k => {
+          if (k.stage == index) {
+            e.push(k.id);
+          }
+        });
+      });
+      this.stuInterAllWork.forEach((e, index) => {
+        likeData.forEach(k => {
+          if (e.indexOf(k.workId) != -1) {
+            this.stuInterAllLike[index].push(k);
+          }
+        });
+      });
+    },
+    // 师生互动数据
+    getTeaStuHd(TeaStuHdData) {
+      this.interactWork.forEach((e, index) => {
+        TeaStuHdData.forEach(k => {
+          if (k.stage == index) {
+            e.push(k);
+          }
+        });
+      });
+    },
+    // 计算任务得分
+    getFoldLineSCoData(repeatWork) {
+      // 作业数据e.sco得分
+      repeatWork.forEach(e => {
+        let con = Object.values(JSON.parse(e.rate));
+        e.sco = 0;
+        con.forEach(i => {
+          if (!isNaN(Number(i))) {
+            e.sco += i * 1;
+          }
+        });
+        if (e.sco == 0 || con.length == 0) {
+          e.sco = 0;
+        } else {
+          e.sco = (e.sco / (con.length - 1)).toFixed(1);
+        }
+      });
+
+      let repeatWorkCopy = []; // 阶段分类作业容器
+      let scoList = []; //分数每个阶段的所有任务分的集合
+
+      this.stageList.forEach((e, index) => {
+        repeatWorkCopy[index] = [];
+        scoList[index] = 0;
+      });
+
+      // 将作业进行阶段分类
+      repeatWork.forEach(e => {
+        repeatWorkCopy[e.stage].push(e);
+      });
+
+      repeatWorkCopy.forEach((e, index) => {
+        e.forEach(k => {
+          scoList[index] += k.sco * 1;
+        });
+        scoList[index] = (scoList[index] / this.taskList[index].length).toFixed(
+          1
+        );
+      });
+      this.scoFoldLineData = scoList;
+
+      let zSco = 0;
+      this.scoFoldLineData.forEach(e => {
+        zSco += e * 1;
+      });
+
+      this.star = (zSco / this.scoFoldLineData.length).toFixed(1) * 1;
+    },
+
+    getFoldLineData(repeatWork) {
+      // 阶段分类作业容器
+      let repeatWorkCopy = [];
+      this.stageList.forEach((e, index) => {
+        repeatWorkCopy[index] = [];
+      });
+
+      // 将作业进行阶段分类
+      repeatWork.forEach(e => {
+        repeatWorkCopy[e.stage].push(e);
+      });
+
+      // 计算阶段工具作业提交率
+      this.toolPercentage.forEach((e, index) => {
+        repeatWorkCopy.forEach((k, kin) => {
+          if (index == kin) {
+            if (k.length == 0 || e.length == 0) {
+              this.stageListPer[index] = 0;
+            } else {
+              this.stageListPer[index] = (k.length / e.length).toFixed(2);
+            }
+          }
+        });
+      });
+    },
+
+    // 非阶段模式
+    // 获取作业提交率折线图
+    getFoldLineDataAi(repeatWork) {
+      // 阶段分类作业容器
+      let repeatWorkCopy = [];
+      this.stageList.forEach((e, index) => {
+        repeatWorkCopy[index] = [];
+      });
+
+      // 将作业进行阶段分类
+      repeatWork.forEach(e => {
+        repeatWorkCopy[e.task].push(e);
+      });
+      // console.log("repeatWorkCopy", repeatWorkCopy);
+
+      // 计算阶段工具作业提交率
+      this.toolPercentage.forEach((e, index) => {
+        repeatWorkCopy.forEach((k, kin) => {
+          if (index == kin) {
+            if (k.length == 0 || e.length == 0) {
+              this.stageListPer[index] = 0;
+            } else {
+              this.stageListPer[index] = (k.length / e.length).toFixed(2);
+            }
+          }
+        });
+      });
+    },
+    // 计算任务得分
+    getFoldLineSCoDataAi(repeatWork) {
+      // 作业数据e.sco得分
+      repeatWork.forEach(e => {
+        let con = Object.values(JSON.parse(e.rate));
+        e.sco = 0;
+        con.forEach(i => {
+          if (!isNaN(Number(i))) {
+            e.sco += i * 1;
+          }
+        });
+        if (e.sco == 0 || con.length == 0) {
+          e.sco = 0;
+        } else {
+          e.sco = (e.sco / (con.length - 1)).toFixed(1);
+        }
+      });
+
+      let repeatWorkCopy = []; // 任务分类作业容器
+      let scoList = []; //分数每个任务的所有任务分的集合
+
+      this.stageList.forEach((e, index) => {
+        repeatWorkCopy[index] = [];
+        scoList[index] = 0;
+      });
+
+      // 将作业进行阶段分类
+      repeatWork.forEach(e => {
+        repeatWorkCopy[e.task].push(e);
+      });
+
+      repeatWorkCopy.forEach((e, index) => {
+        e.forEach(k => {
+          scoList[index] += k.sco * 1;
+        });
+      });
+
+      this.scoFoldLineData = scoList;
+
+      let zSco = 0;
+      this.scoFoldLineData.forEach(e => {
+        zSco += e * 1;
+      });
+
+      this.star = (zSco / this.scoFoldLineData.length).toFixed(1) * 1;
+    },
+    // 师生互动数据
+    getTeaStuHdAi(TeaStuHdData) {
+      this.interactWork.forEach((e, index) => {
+        TeaStuHdData.forEach(k => {
+          if (k.task == index) {
+            e.push(k);
+          }
+        });
+      });
+    },
+    // 生生互动主动
+    getStuInterAllWorkAi(val, likeData) {
+      this.stuInterAllWork.forEach((e, index) => {
+        val.forEach(k => {
+          if (k.task == index) {
+            e.push(k.id);
+          }
+        });
+      });
+      this.stuInterAllWork.forEach((e, index) => {
+        likeData.forEach(k => {
+          if (e.indexOf(k.workId) != -1) {
+            this.stuInterAllLike[index].push(k);
+          }
+        });
+      });
+    },
+    // 生生互动被动
+    getBdStuInterAllWorkAi(val, likeData) {
+      this.bdStuInterAllWork.forEach((e, index) => {
+        val.forEach(k => {
+          if (k.task == index) {
+            e.push(k.id);
+          }
+        });
+      });
+      this.bdStuInterAllWork.forEach((e, index) => {
+        likeData.forEach(k => {
+          if (e.indexOf(k.workId) != -1) {
+            this.bdStuInterAllLike[index].push(k);
+          }
+        });
+      });
+    },
+
+    // 通用方法
+    // 五边形
+    renderChart() {
+      let chartObj = echarts.init(this.$refs.chart);
+      const seriesData = this.chartData.map((values, index) => ({
+        value: values
+      }));
+
+      const option = {
+        title: {
+          text: "素养发展雷达图",
+          // subtext: '这是一个副标题',
+          top: "bottom", // 标题在底部显示
+          left: "center" // 标题居中显示
+        },
+        tooltip: {},
+        legend: {
+          //   data: this.bLeg.map((series) => series.name),
+          bottom: 0
+        },
+        radar: {
+          indicator: this.categories.map(category => ({
+            name: category,
+            max: 5
+          }))
+        },
+        series: [
+          {
+            type: "radar",
+            data: seriesData
+          }
+        ]
+      };
+      chartObj.setOption(option);
+    },
+    // 环形
+    renderChart2() {
+      let chartObj2 = echarts.init(this.$refs.ringChart);
+
+      const option = {
+        title: {
+          text: "工具使用情况",
+          // subtext: '这是一个副标题',
+          top: "bottom", // 标题在底部显示
+          left: "center" // 标题居中显示
+        },
+        tooltip: {
+          trigger: "item",
+          formatter: "{a} <br/>{b}: {c} ({d}%)"
+        },
+        legend: {
+          orient: "vertical",
+          right: 0,
+          itemWidth: 10, // 控制图例项的宽度
+          itemHeight: 10, // 控制图例项的高度
+          data: this.toolRatio.map(item => item.name)
+        },
+        series: [
+          {
+            name: "工具占比",
+            type: "pie",
+            radius: ["30%", "70%"],
+            avoidLabelOverlap: false,
+            label: {
+              show: true,
+              position: "inside",
+              formatter: " {d}%"
+            },
+            emphasis: {
+              label: {
+                show: true,
+                fontSize: "20"
+                // fontWeight: 'bold'
+              }
+            },
+            labelLine: {
+              show: false
+            },
+            center: ["40%", "50%"], // 控制饼图的位置
+
+            data: this.toolRatio
+          }
+        ]
+      };
+
+      chartObj2.setOption(option);
+    },
+    // 工具提交折线图
+    initChart() {
+      const chart = echarts.init(this.$refs.toolSubEcharts);
+
+      const option = {
+        title: {
+          text: "作业提交率",
+          left: "left",
+          textStyle: {
+            color: "rgba(140, 140, 140, 1)", // 标题颜色
+            fontSize: 10 // 标题字体大小
+          }
+        },
+        tooltip: {
+          trigger: "axis",
+          formatter: "{b} : {c}%"
+        },
+        xAxis: {
+          type: "category",
+          data: this.stageList.map(item => item),
+          axisTick: {
+            alignWithLabel: true // 使刻度线和标签对齐
+        }
+        },
+        yAxis: {
+          type: "value",
+          axisLabel: {
+            formatter: "{value}%"
+          },
+          max: 100
+        },
+        series: [
+          {
+            data: this.stageListPer.map(item => item * 100),
+            type: "line"
+          }
+        ]
+      };
+
+      chart.setOption(option);
+    },
+    // 课程得分
+    initChart2() {
+      const chart = echarts.init(this.$refs.cScoEcharts);
+      const option = {
+        title: {
+          text: this.cState == 1 ? "阶段成绩" : "任务成绩",
+          left: "left",
+          textStyle: {
+            color: "rgba(140, 140, 140, 1)", // 标题颜色
+            fontSize: 10 // 标题字体大小
+          }
+        },
+        tooltip: {
+          trigger: "axis",
+          formatter: "{b} : {c}"
+        },
+        xAxis: {
+          type: "category",
+          data: this.stageList.map(item => item),
+          axisTick: {
+            alignWithLabel: true // 使刻度线和标签对齐
+        }
+        },
+        yAxis: {
+          type: "value",
+          axisLabel: {
+            formatter: "{value}"
+          },
+          max: 5
+        },
+        series: [
+          {
+            data: this.scoFoldLineData.map(item => item),
+            type: "line"
+          }
+        ]
+      };
+
+      chart.setOption(option);
+    },
+    // 分组工具占比
+    initChart3() {
+      const chart = echarts.init(this.$refs.groupingEcharts);
+
+      const option = {
+        title: {
+          text: "分组工具占比",
+          left: "left",
+          textStyle: {
+            color: "rgba(140, 140, 140, 1)", // 标题颜色
+            fontSize: 10 // 标题字体大小
+          }
+        },
+        tooltip: {
+          trigger: "axis",
+          axisPointer: {
+            type: "shadow"
+          },
+          formatter: "{b} : {c}%"
+        },
+        xAxis: {
+          type: "category",
+          data: this.stageList.map(item => item)
+        },
+        yAxis: {
+          type: "value",
+          axisLabel: {
+            formatter: "{value}%"
+          },
+          max: 100
+        },
+        series: [
+          {
+            data: this.columnData.map(item => item * 100),
+            type: "bar"
+          }
+        ]
+      };
+
+      chart.setOption(option);
+    },
+    // 师生互动折线图
+    initChart4() {
+      const chart = echarts.init(this.$refs.interactionEcharts);
+
+      const option = {
+        title: {
+          text: "师生互动",
+          left: "left",
+          textStyle: {
+            color: "rgba(140, 140, 140, 1)", // 标题颜色
+            fontSize: 10 // 标题字体大小
+          }
+        },
+        tooltip: {
+          trigger: "axis",
+          formatter: "{b} : {c}"
+        },
+        xAxis: {
+          type: "category",
+          data: this.stageList.map(item => item),
+          axisTick: {
+            alignWithLabel: true // 使刻度线和标签对齐
+        }
+        },
+        yAxis: {
+          type: "value",
+          axisLabel: {
+            formatter: "{value}"
+          }
+        },
+        series: [
+          {
+            data: this.interactWork.map(item => item.length),
+            type: "line"
+          }
+        ]
+      };
+
+      chart.setOption(option);
+    },
+    // 学生互动主动折线图
+    initChart5() {
+      const chart = echarts.init(this.$refs.stuInteractZdEcharts);
+
+      const option = {
+        title: {
+          text: "生生互动(主动)",
+          left: "left",
+          textStyle: {
+            color: "rgba(140, 140, 140, 1)", // 标题颜色
+            fontSize: 10 // 标题字体大小
+          }
+        },
+        tooltip: {
+          trigger: "axis",
+          formatter: "{b} : {c}"
+        },
+        xAxis: {
+          type: "category",
+          data: this.stageList.map(item => item),
+          axisTick: {
+            alignWithLabel: true // 使刻度线和标签对齐
+        }
+        },
+        yAxis: {
+          type: "value",
+          axisLabel: {
+            formatter: "{value}"
+          }
+        },
+        series: [
+          {
+            data: this.stuInterAllLike.map(item => item.length),
+            type: "line"
+          }
+        ]
+      };
+
+      chart.setOption(option);
+    },
+    // 学生互动被动折线图
+    initChart6() {
+      const chart = echarts.init(this.$refs.bdStuInteractZdEcharts);
+
+      const option = {
+        title: {
+          text: "生生互动(被动)",
+          left: "left",
+          textStyle: {
+            color: "rgba(140, 140, 140, 1)", // 标题颜色
+            fontSize: 10 // 标题字体大小
+          }
+        },
+        tooltip: {
+          trigger: "axis",
+          formatter: "{b} : {c}"
+        },
+        xAxis: {
+          type: "category",
+          data: this.stageList.map(item => item),
+          axisTick: {
+            alignWithLabel: true // 使刻度线和标签对齐
+        }
+        },
+        yAxis: {
+          type: "value",
+          axisLabel: {
+            formatter: "{value}"
+          }
+        },
+        series: [
+          {
+            data: this.bdStuInterAllLike.map(item => item.length),
+            type: "line"
+          }
+        ]
+      };
+
+      chart.setOption(option);
+    },
+    // 计算分组工具使用比例
+    getColumnData() {
+      let columnDataCopy = [];
+
+      this.toolPercentage.forEach((e, index) => {
+        columnDataCopy[index] = 0;
+        columnDataCopy[index] = e.filter(item => item === 49).length;
+        if (columnDataCopy[index]) {
+          this.columnData[index] = (columnDataCopy[index] / e.length).toFixed(
+            2
+          );
+        } else {
+          this.columnData[index] = 0;
+        }
+      });
+    },
+    // 计算时长
+    secondsToDhms(seconds) {
+      const days = Math.floor(seconds / (3600 * 24));
+      const hours = Math.floor((seconds % (3600 * 24)) / 3600);
+
+      return days + " 天 " + hours + " 时";
+    },
+    // 判断一个工具下是否提交多个作,有重复的只取一个
+    newArrFn(arr) {
+      // 创建一个新的空数组
+      let newArr = [];
+      for (let i = 0; i < arr.length; i++) {
+        // 设置一个开关,如果是true,就存进去,不是就不存
+        let flag = true;
+        for (let j = 0; j < newArr.length; j++) {
+          // 原数组和新数组作比较,如果一致,开关变为 false
+          if (
+            arr[i].stage == newArr[j].stage &&
+            arr[i].task == newArr[j].task &&
+            arr[i].tool == newArr[j].tool
+          ) {
+            flag = false;
+          }
+        }
+        flag ? newArr.push(arr[i]) : newArr;
+      }
+      return newArr;
+    },
+    handleClose(done) {
+      done();
+    }
+  }
+};
+</script>
+
+<style scoped>
+.pbl {
+  width: 100%;
+  height: 100%;
+  box-sizing: border-box;
+  margin: auto;
+  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+  padding: 20px;
+  padding-top: 10px;
+  overflow: auto;
+  border-radius: 10px;
+}
+.pageTit {
+  width: 100%;
+  text-align: left;
+  font-size: 28px;
+  padding: 10px 0;
+  font-weight: bold;
+  border-bottom: 1px solid #ccc;
+  margin-bottom: 10px;
+}
+.full_diy {
+  min-width: 1200px !important;
+}
+.full_diy >>> .el-dialog {
+  height: 80%;
+  width: 598px !important;
+  margin-top: 10vh !important;
+  display: flex;
+  flex-direction: column;
+}
+.full_diy >>> .el-dialog__body {
+  overflow: auto;
+  flex: 1;
+  padding: 0 !important;
+}
+.full_diy >>> .el-dialog__title {
+  color: #fff !important;
+}
+.full_diy >>> .el-dialog__header {
+  padding: 9px 20px 10px;
+  background: #32455b !important;
+}
+.coverPage {
+  min-height: 743px;
+  background-color: #ccc;
+  position: relative;
+  background-image: url("../../../assets/icon/exportPdfworks/bcg1.svg"),
+    url("../../../assets/icon/exportPdfworks/bcg2.svg");
+  /* 设置每个背景的位置和尺寸,可以使用关键字或者具体的像素值,用逗号分隔 */
+  background-position: top left, bottom;
+  /* background-size: cover, cover; */
+
+  /* 设置每个背景图片的重复方式,用逗号分隔 */
+  background-repeat: no-repeat, no-repeat;
+}
+.coverPageLogo {
+  padding: 40px;
+  width: 100%;
+  display: flex;
+  justify-content: flex-end;
+  box-sizing: border-box;
+  margin-bottom: 30px;
+}
+.coverPageFrom {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  width: 70%;
+  margin: 0 auto;
+}
+.coverPageFromTit {
+  display: flex;
+  justify-content: center;
+  width: 100%;
+}
+.fromCss {
+  border: 1.5px dashed rgba(158, 208, 255, 1);
+  border-radius: 16px;
+  background-color: #fff;
+  padding: 24px 32px;
+  width: 300px;
+  margin: 30px;
+  color: rgba(35, 99, 205, 1);
+}
+.fromCss > div {
+  margin-bottom: 10px;
+  display: flex;
+}
+.fromCss > div > span {
+  flex-shrink: 0;
+  margin-right: 5px;
+  font-size: 16px;
+}
+.fromCss > div:last-child {
+  margin-bottom: 0;
+}
+.txt {
+  width: 100%;
+  border-bottom: 1px solid rgba(192, 210, 229, 1);
+  text-align: center;
+  color: #000;
+}
+.coverPageCon {
+  background-color: #e3edfe;
+  display: flex;
+  flex-direction: column;
+  padding: 0 20px;
+  padding-bottom: 30px;
+  box-sizing: border-box;
+}
+.zhBlock {
+  width: 125px;
+  height: 64px;
+  padding: 10px 8px;
+  box-sizing: border-box;
+  background-color: rgba(255, 255, 255, 1);
+  border-radius: 8px;
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+}
+.zhBlockTit {
+  font-size: 10px;
+  font-weight: 400;
+  color: rgba(0, 0, 0, 0.6);
+  display: flex;
+  align-items: center;
+  margin-bottom: 6px;
+}
+.zhBlockCon {
+  flex: 1;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  font-size: 14px;
+  color: rgba(0, 0, 0, 0.9);
+  font-weight: 400;
+  background-color: rgba(243, 247, 253, 1);
+  border-radius: 5px;
+}
+.zhBlockCon >>> .el-rate__icon {
+  margin: 0 !important;
+}
+.zhBlockCon2 {
+  display: flex;
+  flex-direction: column;
+  justify-content: space-between;
+  /* flex-wrap: wrap; */
+  flex: 1;
+  overflow: hidden;
+}
+.zhBlockCon2 > div {
+
+  display: flex;
+  flex-wrap: wrap;
+
+  flex: 1;
+}
+.zhBlockCon2 > div >span{
+  font-size: 8px;
+  font-weight: 400;
+  color: rgba(0, 0, 0, 0.9);
+  background-color: rgba(243, 247, 253, 1);
+  border-radius: 2px;
+  padding: 0px 4px;
+  height: 15px;
+  line-height: 15px;
+  box-sizing: border-box;
+  margin-right: 4px;
+  margin-bottom: 2px;
+}
+.zxt {
+  height: 300px;
+  width: 100%;
+  border: 1px solid #ccc;
+  margin: 10px 0;
+  background-color: rgba(255, 255, 255, 1);
+  padding: 10px 0;
+  border-radius: 15px;
+}
+</style>

+ 13 - 4
src/components/pages/components/exportWorksDialog.vue

@@ -7,9 +7,9 @@
       class="worksDialogCSS"
       :append-to-body="true"
     > -->
-      <div slot="title" class="header-title">
+      <!-- <div slot="title" class="header-title">
         <div style="color: #fff">导出作业集</div>
-      </div>
+      </div> -->
     <div ref="reportPdf" v-loading="loading">
       <div
         class="coverPage"
@@ -60,6 +60,8 @@
           />
         </div>
       </div>
+
+
       <div class="coverPageCon">
         <div
           style="
@@ -414,7 +416,7 @@
                             line-height: 21px;
                           "
                     >
-                      <!-- 提交时间: 2024-07-12 17:36:06 -->
+                      <!-- 提交时间: {{ i.taskList[i.taskList.length-1].create_at }} -->
                     </div>
                   </div>
                   <div style="display: flex; justify-content: space-between">
@@ -456,7 +458,9 @@
                           v-for="(r, tarIndex) in item.data"
                           :key="tarIndex"
                         >
-                          <span> {{ r.target }}</span>
+                        <span v-if="state == 5"> {{ r.target }}</span>
+                        <span v-else> {{ r.target[r.target.length-1] }}</span>
+                          <!-- <span> {{ r.target }}</span> -->
                         </div>
                       </div>
                     </div>
@@ -466,6 +470,10 @@
             </div>
           </div>
         </div>
+        <div style="display: flex;justify-content: flex-end;">
+          <img :src="schoolImg.bjLogo ? schoolImg.bjLogo : ''" alt="" />
+        </div>
+
       </div>
     </div>
   <!-- </el-dialog> -->
@@ -499,6 +507,7 @@ export default {
           schoolId: "45facc0a-1211-11ec-80ad-005056b86db5",
           logo: require("../../../assets/icon/exportPdfworks/cocoroboLogo.svg"),
           conImg: require("../../../assets/icon/exportPdfworks/cocoroboCon.svg"),
+          bjLogo: require("../../../assets/icon/exportPdfworks/logo2.svg"),
           bkColor: "#E5EFFE"
         }
       ],

+ 1 - 1
src/components/pages/components/studentWorksDetail.vue

@@ -1400,7 +1400,7 @@
                           <span>{{ checkJson[sIndex].allRight + "%" }}</span>
                         </div>
                       </div> -->
-                      <div v-if="worksDetail[sIndex].eList.length">
+                      <div v-if="worksDetail[sIndex].eList && worksDetail[sIndex].eList.length">
                         <!-- <div class="ech" style="margin-left: 23px">
                           <img src="../../../assets/icon/pj/score.png" alt="" />
                         </div> -->

+ 22 - 4
src/components/pages/components/worksDetail2.vue

@@ -1362,7 +1362,7 @@
                     </div>
                      
                    
-                      <div v-if="worksDetail[sIndex].eList.length">
+                      <div v-if="worksDetail[sIndex].eList && worksDetail[sIndex].eList.length">
                        
                         <div>
                           <div class="score_boxTit"><span>分数详情</span></div>
@@ -1408,10 +1408,18 @@
 
                             <el-rate
                               class="rate_size"
+                              v-if="worksDetail[sIndex].state == 5"
                               style="min-width: 120px"
                               v-model="worksDetail[sIndex].rateList[item.detail]"
                               @change="getStar(sIndex)"
                             ></el-rate>
+                            <el-rate
+                              class="rate_size"
+                              v-else
+                              style="min-width: 120px"
+                              v-model="worksDetail[sIndex].rateList[item.value]"
+                              @change="getStar(sIndex)"
+                            ></el-rate>
                           </div>
                         </div>
                         <div class="worksTarget" v-if="isShow(worksDetail[sIndex].eList)"><span>目标</span></div>
@@ -2713,7 +2721,11 @@ export default {
                 result[l].eList = eList;
                 for (var i = 0; i < eList.length; i++) {
                   _ooption.push({ value: 0, name: eList[i].value });
-                  result[l].rateList[eList[i].detail] = 0;
+                  if (this.DState == 5) {
+                    result[l].rateList[eList[i].detail] = 0;                          
+                  }else{
+                    result[l].rateList[eList[i].value] = 0;                          
+                  }
                 }
                 result[l].rateList.content = "";
                 this.ooption[l] = _ooption;
@@ -2766,7 +2778,11 @@ export default {
                     
                       for (var i = 0; i < eList.length; i++) {
                         _ooption.push({ value: 0, name: eList[i].value });
-                        result[l].rateList[eList[i].detail] = 0;
+                        if (this.DState == 5) {
+                          result[l].rateList[eList[i].detail] = 0;                          
+                        }else{
+                          result[l].rateList[eList[i].value] = 0;                          
+                        }
                       }
                       result[l].rateList.content = "";
                       this.ooption[l] = _ooption;
@@ -3195,7 +3211,7 @@ export default {
     },
     updatePj() {
       for (var i = 0; i < this.worksDetail.length; i++) {
-        if (!this.worksDetail[i].eList.length) {
+        if (this.worksDetail[i].eList && !this.worksDetail[i].eList.length) {
           continue;
         }
         this.updateWorks(
@@ -3243,6 +3259,8 @@ export default {
         rate: rateList,
         uid: this.studentId,
       };
+      // return console.log('params',params);
+      
       const k = i;
       this.ajax
         .get(this.$store.state.api + "updateWorksEva", params)

+ 1 - 1
src/components/pages/components/worksDetail3.vue

@@ -1051,7 +1051,7 @@
                     </div>
                      
                    
-                      <div v-if="worksDetail[sIndex].eList.length">
+                      <div v-if="worksDetail[sIndex].eList && worksDetail[sIndex].eList.length">
                        
                         <div>
                           <div class="score_boxTit"><span>分数详情</span></div>

+ 99 - 24
src/components/pages/works.vue

@@ -354,25 +354,30 @@
       class="dialog_diy check_diy"
     >
       <div>
-        <div class="student_search" style="margin-bottom: 10px">
-          <div>筛选</div>
-          <div style="display: flex; width: 90%">
-            <el-select
-              class="r_select"
-              v-model="uname"
-              placeholder="请选择班级"
-              filterable
-              @change="searchWork2"
-            >
-              <el-option label="所有班级" value></el-option>
-              <el-option
-                v-for="item in userAarray"
-                :key="item.id"
-                :label="item.name"
-                :value="item.id"
-              ></el-option>
-            </el-select>
+        <div class="student_search" style="margin-bottom: 10px;justify-content: space-between;">
+          <div style="display: flex;justify-content: space-between;">
+            <div style="margin-right: 10px;">筛选</div>
+            <div>
+              <el-select
+                class="r_select"
+                v-model="uname"
+                placeholder="请选择班级"
+                filterable
+                @change="searchWork2"
+              >
+                <el-option label="所有班级" value></el-option>
+                <el-option
+                  v-for="item in userAarray"
+                  :key="item.id"
+                  :label="item.name"
+                  :value="item.id"
+                ></el-option>
+              </el-select>
+            </div>
           </div>
+          
+          <el-button size="small" @click="exportPdfSetAllBtn" type="primary">一键导出</el-button>
+          
         </div>
         <div>
           <el-table
@@ -385,7 +390,12 @@
             style="width: 100%"
             :row-class-name="tableRowClassName"
             :header-cell-style="{ background: 'rgb(238,238,238)' }"
+              @selection-change="handleSelectionChange"
           >
+            <el-table-column
+              type="selection"
+              width="55">
+            </el-table-column>
             <el-table-column
               prop="sName"
               label="姓名"
@@ -413,7 +423,7 @@
               </template>
             </el-table-column>
           </el-table>
-          <div style="margin-top: 10px">
+          <div style="display: flex;justify-content: space-between; padding:15px 0">
             <el-pagination
               background
               layout="prev, pager, next"
@@ -421,12 +431,15 @@
               :total="total2"
               @current-change="handleCurrentChange2"
             ></el-pagination>
+             <div style="display: flex;"  class="dialog-footer">
+              <el-button @click="exportPdfSetBtn" size="small" style="padding: 6px 18px;" type="primary">导出</el-button>
+
+              <el-button  style="margin-left: 10px;padding: 6px 18px;" size="small" @click="signDialog = false">关闭</el-button>
+            </div>
           </div>
         </div>
       </div>
-      <span slot="footer" class="dialog-footer">
-        <el-button @click="signDialog = false">关闭</el-button>
-      </span>
+     
     </el-dialog>
     <div class="report_box" v-if="reportVisible">
       <studentReport
@@ -436,6 +449,19 @@
         :oid="oid"
       ></studentReport>
     </div>
+
+    <el-dialog
+      title="文件预览"
+      :visible.sync="worksDialog"
+      :before-close="handleClose"
+      class="worksDialogCSSExp"
+      :append-to-body="true"
+    >
+      <div slot="title" class="header-title">
+        <div style="color: #fff">导出作业集</div>
+      </div>
+      <exportDataDialog  :key="exportW" :digNum="digNum" :oid="oid" :multipleSelection="multipleSelection" :worksDialog.sync="worksDialog" :cid="checkCourse"></exportDataDialog>
+    </el-dialog>
     <!-- <div class="cancelbox" v-if="reportVisible">
       <el-button @click="cancelR" type="primary" size="small">返回</el-button>
     </div> -->
@@ -448,16 +474,24 @@ import Report from "./components/report";
 import studentReport from "./components/studentReport";
 import "../../common/aws-sdk-2.235.1.min.js";
 import StudentWorksDetail from "./components/studentWorksDetail.vue";
+import exportDataDialog from "./components/exportDataDialog.vue";
+
 
 export default {
   components: {
     WorkDate,
     Report,
     studentReport,
-    StudentWorksDetail
+    StudentWorksDetail,
+    exportDataDialog
   },
   data() {
     return {
+      worksDialog:false,
+      exportW:0,
+      digNum:0,
+      digCid:'',
+
       tableHeight: "500px",
       isLoading: false,
       formLabelWidth: "100px",
@@ -496,7 +530,8 @@ export default {
       uname: "",
       cutTabNum:0,
       tableData:[],
-      dialogVisibleS:false
+      dialogVisibleS:false,
+      multipleSelection: []
     };
   },
   mounted() {
@@ -518,6 +553,35 @@ export default {
     });
   },
   methods: {
+    handleSelectionChange(val) {
+        this.multipleSelection = val;
+    },
+    // 导出pdf
+    exportPdfSetBtn(){
+      this.worksDialog = true;
+      this.digNum = 0
+      this.exportW++
+      
+    },
+    // 一键导出pdf
+    exportPdfSetAllBtn(){
+
+      this.$confirm("是否导出全部学生报告?批量打印需要等待一会哦。", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning",
+      })
+      .then(() => {
+        this.worksDialog = true;
+        this.digNum = 1
+        this.exportW++
+      })
+      .catch(_ => {
+        this.$confirm.visible=false
+      })
+     
+      
+    },
     goTo(path) {
       this.$router.push(path);
     },
@@ -1010,4 +1074,15 @@ export default {
   text-overflow: ellipsis;
   white-space: nowrap;
 }
+.worksDialogCSSExp>>> .el-dialog__header {
+  /* padding: 9px 20px 10px; */
+  background: #32455b !important;
+}
+
+.worksDialogCSSExp >>> .el-dialog__body {
+  width: 635px !important;
+}
+.worksDialogCSSExp >>> .el-dialog {
+  width: 676px !important;
+}
 </style>

Some files were not shown because too many files changed in this diff