lsc 1 год назад
Родитель
Сommit
c65bfe3fbd

+ 1 - 1
dist/index.html

@@ -25,7 +25,7 @@
       height: 100%;
       width: 100%;
       background: #e6eaf0;
-    }</style><link href=./static/css/app.8d998595051e367e321cc6d8618b9b33.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.df9ff6be207cf68c7d9a.js></script><script type=text/javascript src=./static/js/app.f3bcb329fde5648ab774.js></script></body></html><script>function stopSafari() {
+    }</style><link href=./static/css/app.4bbebff235ee2844206d70ad501fd103.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.bd1670b339dc7e372852.js></script><script type=text/javascript src=./static/js/app.f8f9d62cb0366f184490.js></script></body></html><script>function stopSafari() {
     //阻止safari浏览器双击放大功能
     let lastTouchEnd = 0  //更新手指弹起的时间
     document.documentElement.addEventListener("touchstart", function (event) {

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
dist/static/css/app.4bbebff235ee2844206d70ad501fd103.css


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
dist/static/css/app.4bbebff235ee2844206d70ad501fd103.css.map


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
dist/static/js/app.f8f9d62cb0366f184490.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
dist/static/js/app.f8f9d62cb0366f184490.js.map


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
dist/static/js/manifest.571c38d63f24b1ae9e16.js.map


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
dist/static/js/vendor.bd1670b339dc7e372852.js


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
dist/static/js/vendor.bd1670b339dc7e372852.js.map


+ 1 - 0
package.json

@@ -31,6 +31,7 @@
     "js-pinyin": "^0.1.9",
     "jsmind": "^0.4.8",
     "jspdf": "^2.5.1",
+    "jszip": "^3.10.1",
     "lamejs": "^1.2.1",
     "language-hk-loader": "^1.0.1",
     "pdfjs-dist": "^2.5.207",

+ 66 - 63
src/components/pages/test/check/index.vue

@@ -23,7 +23,7 @@
           </div>
           <div class="r_pub_button_retrun" @click="retrunCourse">返回</div>
         </div>
-        <div class="step_box" ref="stepBox">
+        <div class="step_box" ref="stepBox" v-loading="pdfLoading">
           <div class="test_title">
             <div class="left">
               <div class="title">{{ testJson.title }}</div>
@@ -72,6 +72,7 @@
                 <el-input v-model="courseName" class="student_input" placeholder="请输入需要搜索的姓名"></el-input>
                 <span class="serach_icon" @click="searchCourse"></span>
               </div>
+              <div class="btnA" v-if="stype == 1 && !pdfLoading" @click="exportPDF">导出PDF</div>
             </div>
           </div>
           <div class="title_content" v-if="stype == 1">
@@ -167,9 +168,8 @@
               <el-table-column prop="time" label="提交时间" width="170px" align="left">
               </el-table-column>
               <el-table-column v-for="(item, index) in chapters" :key="index" :label="item.json.title" min-width="150"
-                align="left" 
-                :filters="item.type == 1 ? item.nameFilters : null"
-                :filter-method="item.type == 1 ? (value,row)=>{return filterName(value,row,index)} : null"
+                align="left" :filters="item.type == 1 ? item.nameFilters : null"
+                :filter-method="item.type == 1 ? (value, row) => { return filterName(value, row, index) } : null"
                 :filter-placement="item.type == 1 ? filterPlacement : null">
                 <template slot-scope="scope">
                   <div v-if="scope.row.array[index].type == 1" style="display: flex; flex-wrap: wrap;">
@@ -208,62 +208,29 @@
           </div>
           <div class="table_content" v-if="stype == 3">
             <div class="student_table">
-              <el-table
-                ref="table"
-                :data="tableData"
-                border
-                :height="tableHeight"
-                :fit="true"
-                v-loading="isLoading"
-                style="width: 100%"
-                :header-cell-style="{ background: '#f1f1f1', fontSize: '17px' }"
-                :row-class-name="tableRowClassName"
-              >
-                <el-table-column
-                  prop="username"
-                  label="提交人"
-                  min-width="15"
-                  align="center"
-                >
+              <el-table ref="table" :data="tableData" border :height="tableHeight" :fit="true" v-loading="isLoading"
+                style="width: 100%" :header-cell-style="{ background: '#f1f1f1', fontSize: '17px' }"
+                :row-class-name="tableRowClassName">
+                <el-table-column prop="username" label="提交人" min-width="15" align="center">
                 </el-table-column>
-                <el-table-column
-                  prop="time"
-                  label="提交时间"
-                  min-width="15"
-                  align="center"
-                >
+                <el-table-column prop="time" label="提交时间" min-width="15" align="center">
                 </el-table-column>
-                <el-table-column
-                  prop="time"
-                  label="是否批改"
-                  min-width="15"
-                  align="center"
-                >
+                <el-table-column prop="time" label="是否批改" min-width="15" align="center">
                   <template slot-scope="scope">
                     <div>{{ scope.row.type == 3 ? '是' : '否' }}</div>
                   </template>
                 </el-table-column>
                 <el-table-column label="操作" width="200px">
                   <template slot-scope="scope">
-                    <el-button
-                      @click="getTest(scope.row)"
-                      type="primary"
-                      size="small"
-                      >查看</el-button
-                    >
-                  <el-button @click="deleteTest(scope.row.id)" type="primary" size="small">删除</el-button>
+                    <el-button @click="getTest(scope.row)" type="primary" size="small">查看</el-button>
+                    <el-button @click="deleteTest(scope.row.id)" type="primary" size="small">删除</el-button>
                   </template>
                 </el-table-column>
               </el-table>
             </div>
             <div class="student_page">
-              <el-pagination
-                background
-                layout="prev, pager, next"
-                :page-size="pageSize"
-                :total="total"
-                @current-change="handleCurrentChange"
-              >
+              <el-pagination background layout="prev, pager, next" :page-size="pageSize" :total="total"
+                @current-change="handleCurrentChange">
               </el-pagination>
             </div>
           </div>
@@ -289,6 +256,8 @@ import wOffice from "../file/wOffice.vue";
 
 import wordcloud from 'vue-wordcloud';
 import checkPie from '../data/checkPie.vue';
+
+import { downloadPDF } from '../../../tools/pdf'
 export default {
   components: {
     shareBox,
@@ -342,6 +311,7 @@ export default {
       wurl: "",
       chapters: [],
       filterPlacement: 'bottom-end',
+      pdfLoading: false
     };
   },
   watch: {},
@@ -378,9 +348,9 @@ export default {
     }
   },
   methods: {
-    filterName(value, row,index) {
+    filterName(value, row, index) {
       let name = []
-      for(var i=0;i<row.array[index].json.answer2.length;i++){
+      for (var i = 0; i < row.array[index].json.answer2.length; i++) {
         name.push(row.array[index].json.array[row.array[index].json.answer2[i]].option)
       }
       console.log(name.indexOf(value) != -1);
@@ -462,18 +432,18 @@ export default {
       if (this.stype != type) {
         this.stype = type
         this.courseName = ''
-        if(type == 3){
+        if (type == 3) {
           this.getData2();
-        }else{
+        } else {
           this.getData();
         }
         this.changeHeight();
       }
     },
     searchCourse() {
-      if(this.stype == 3){
+      if (this.stype == 3) {
         this.getData2()
-      }else{
+      } else {
         this.getData()
       }
     },
@@ -687,17 +657,17 @@ export default {
       console.log(array);
       return array;
     },
-    setFilter(json){
+    setFilter(json) {
       let _json = json
       let array = []
       _json.filter((item) => {
         item.nameFilters = [],
-        item.filterParams = {
-                  name: [],
-                }
-        if(item.type == 1){
-          for(var i = 0; i < item.json.array.length; i++){
-            item.nameFilters.push({text: item.json.array[i].option, value: item.json.array[i].option})
+          item.filterParams = {
+            name: [],
+          }
+        if (item.type == 1) {
+          for (var i = 0; i < item.json.array.length; i++) {
+            item.nameFilters.push({ text: item.json.array[i].option, value: item.json.array[i].option })
           }
         }
         array.push(item)
@@ -779,9 +749,9 @@ export default {
             .post(_this.$store.state.api + "deleteTestCourseWorks", params)
             .then((res) => {
               _this.$message.success("删除成功");
-              if(_this.stype == 3){
+              if (_this.stype == 3) {
                 _this.getData2();
-              }else{
+              } else {
                 _this.getData();
               }
             })
@@ -793,6 +763,21 @@ export default {
           return;
         });
 
+    },
+    exportPDF() {
+      this.pdfLoading = true
+      var a = document.getElementsByTagName("img")
+      for (var i = 0; i < a.length; i++) { a[i].crossOrigin = "*" }
+      downloadPDF(this.$refs.stepBox, this.testJson.title, () => {
+        var _a = document.getElementsByTagName("img")
+        for (var i = 0; i < _a.length; i++) {
+          _a[i].removeAttribute("crossorigin")
+        }
+        setTimeout(() => {
+          this.pdfLoading = false
+
+        }, 2000);
+      })
     }
   },
   beforeDestroy() {
@@ -1339,5 +1324,23 @@ export default {
   overflow: hidden;
 }
 
-
+.btnA {
+  color: #fff;
+  background-color: #0061FF;
+  padding: 0 24px;
+  font-size: 14px;
+  min-width: 64px;
+  font-weight: 500;
+  border-radius: 4px;
+  box-sizing: border-box;
+  border: none;
+  cursor: pointer;
+  transition: all 0.2s ease-in-out;
+  height: 36px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  line-height: 1;
+  margin-right: 10px;
+}
 </style>

+ 105 - 2
src/components/pages/testStudent/view/component/file.vue

@@ -1,5 +1,5 @@
 <template>
-    <div class="c_box">
+    <div class="c_box" v-loading="isloading">
         <!-- <div class="mask"></div> -->
         <div v-if="!checkJson">暂未设置题目</div>
         <div v-else class="choice_box">
@@ -13,6 +13,9 @@
                 </div>
 
                 <!-- </div><div v-html="checkJson.title"></div> -->
+                <div class="p_box" v-if="checkJson.file && checkJson.file.length > 1">
+                    <span class="btnU" @click="uploadCourse">批量下载</span>
+                </div>
                 <div class="p_box" v-if="isTeacher == 1 && checkJson.score">
                     <el-input v-model="checkJson.score2" class="c_input" @change="numberPan"
                         placeholder="请输入得分"></el-input><span style="margin: 0 10px;">/</span><span>{{ checkJson.score
@@ -96,6 +99,47 @@ import wpdf from "../../../test/file/wPdf2.vue";
 import wVideo from "../../../test/file/wVideo.vue";
 import wOffice from "../../../test/file/wOffice.vue";
 import checkfile from "../../../test/file/checkfile.vue";
+import JSZip from "jszip";
+import FileSaver from "file-saver";
+
+const getFile = (url) => {
+  return new Promise((resolve, reject) => {
+    var credentials = {
+        accessKeyId: "AKIATLPEDU37QV5CHLMH",
+        secretAccessKey: "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",
+      }; //秘钥形式的登录上传
+      window.AWS.config.update(credentials);
+      window.AWS.config.region = "cn-northwest-1"; //设置区域
+      let url2 = url;
+      let _url2 = "";
+      if (
+        url2.indexOf("https://view.officeapps.live.com/op/view.aspx?src=") != -1
+      ) {
+        _url2 = url2.split(
+          "https://view.officeapps.live.com/op/view.aspx?src="
+        )[1];
+      } else {
+        _url2 = url2;
+      }
+      var s3 = new window.AWS.S3({ params: { Bucket: "ccrb" } });
+      let name = decodeURIComponent(_url2.split("https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/")[1])
+      var params = {
+        Bucket: "ccrb",
+        Key: name
+      };
+      s3.getObject(params, function (err, data) {
+        if (err) {
+          console.log(err, err.stack)
+          resolve({ data: 1 });
+        }else {
+          resolve({ data: data.Body });
+          console.log(data); 
+        }          // sxuccessful response
+
+      });
+    // axios({
+  });
+};
 
 export default {
     components: {
@@ -143,6 +187,7 @@ export default {
             dialogVisibleOffice:false,
             dialogVisiblefile: false,
             wurl: "",
+            isloading: false,
         }
     },
     watch: {
@@ -428,7 +473,46 @@ export default {
         delFile(index) {
             this.checkJson.file.splice(index, 1)
             this.$forceUpdate();
-        }
+        },
+        uploadCourse() {
+          this.isloading = true;
+          const _chapInfo = this.checkJson.file;
+          let url = [];
+          for (let i = 0; i < _chapInfo.length; i++) {
+            url.push({
+                name: _chapInfo[i].name,
+                url: _chapInfo[i].url,
+            });
+          }
+          console.log(url);
+          this.downLoadAll(url);
+    },
+    downLoadAll(url) {
+      const data = url; // 需要下载打包的路径, 可以是本地相对路径, 也可以是跨域的全路径
+      const zip = new JSZip();
+      const cache = {};
+      const promises = [];
+      data.forEach((item) => {
+        const promise = getFile(item.url).then((data) => {
+          if (data.data != 1) {
+            // 下载文件, 并存成ArrayBuffer对象
+            const file_name = item.name; // 获取文件名
+            zip.file(file_name, data.data, { binary: true }); // 逐个添加文件
+            cache[file_name] = data.data;
+          }
+        });
+        promises.push(promise);
+      });
+      Promise.all(promises).then(() => {
+        zip.generateAsync({ type: "blob" }).then((content) => {
+          // 生成二进制流
+          FileSaver.saveAs(content, "附件.zip"); // 利用file-saver保存文件  自定义文件名
+          setTimeout(() => {
+            this.isloading = false;
+          }, 2000);
+        });
+      });
+    },
     },
     mounted() {
         this.checkJson = this.cJson ? this.depthCopy(this.cJson) : undefined
@@ -649,6 +733,25 @@ export default {
     align-items: center;
 }
 
+.p_box > .btnU{
+color: #fff;
+  background-color: #0061FF;
+  padding: 0 24px;
+  font-size: 14px;
+  min-width: 64px;
+  font-weight: 500;
+  border-radius: 4px;
+  box-sizing: border-box;
+  border: none;
+  cursor: pointer;
+  transition: all 0.2s ease-in-out;
+  height: 36px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  line-height: 1;
+}
+
 .c_input {
     width: 90px;
 }

+ 71 - 0
src/components/tools/pdf.js

@@ -0,0 +1,71 @@
+import html2canvas from "html2canvas";
+import jsPDF from "jspdf";
+
+export const downloadPDF = (page, fileName = 'test', callBack) => {
+    html2canvas(page,{allowTaint: true,useCORS: true,height: page.scrollHeight,windowHeight: page.scrollHeight}).then(function(canvas) {
+        canvas2PDF(canvas, fileName, callBack);
+    });
+};
+const canvas2PDF = (canvas, fileName, callBack) => {
+    let contentWidth = canvas.width;
+    console.log(contentWidth);
+    let contentHeight = canvas.height;
+    // 一页pdf显示html页面生成的canvas高度;
+    let pageHeight = contentWidth / 592.28 * 841.89;
+    // let pageHeight = 841.89;
+
+    // 未生成pdf的html页面高度
+    let leftHeight = contentHeight;
+    // 页面偏移
+    let position = 0;
+    // html页面生成的canvas在pdf中图片的宽高(本例为:横向a4纸[841.89,592.28],纵向需调换尺寸)
+    let imgWidth = 550;
+    let imgHeight = 592.28 / contentWidth * contentHeight;
+    // let imgHeight = 841.89;
+
+    let pageData = canvas.toDataURL('image/jpeg', 1.0);
+    let PDF = new jsPDF('', 'pt', 'a4');
+    // 两个高度需要区分: 一个是html页面的实际高度,和生成pdf的页面高度
+    // 当内容未超过pdf一页显示的范围,无需分页
+    if (leftHeight < pageHeight) {
+        PDF.addImage(pageData, 'JPEG', 20, 0, imgWidth, imgHeight)
+    } else {
+        while (leftHeight > 0) {
+            PDF.addImage(pageData, 'JPEG', 20, position, imgWidth, imgHeight)
+            leftHeight -= pageHeight;
+            position -= 841.89;
+            // 避免添加空白页
+            if (leftHeight > 0) {
+                PDF.addPage();
+            }
+        }
+    }
+    PDF.save(fileName + '.pdf')
+
+    callBack()
+
+
+
+
+
+
+    // let contentWidth = canvas.width;
+    // let contentHeight = canvas.height;
+    // console.log(contentWidth,contentHeight);
+    // let imgHeight = contentHeight;
+    // let imgWidth = contentWidth/2;
+
+    // // 第一个参数: l:横向  p:纵向
+    // // 第二个参数:测量单位("pt","mm", "cm", "m", "in" or "px")
+    // let pdf = new jsPDF('l', 'pt', 'a4');
+
+    // pdf.addImage(
+    //   canvas.toDataURL("image/jpeg", 1.0),
+    //   "JPEG",
+    //   0,
+    //   0,
+    //   imgWidth,
+    //   imgHeight
+    // );
+    // pdf.save("导出.pdf");
+};

Некоторые файлы не были показаны из-за большого количества измененных файлов