Sfoglia il codice sorgente

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

lsc 11 mesi fa
parent
commit
65eeddc8a1

+ 333 - 145
src/components/pages/test/check/docxTemplateDialog.vue

@@ -2,7 +2,7 @@
   <el-dialog
     :visible.sync="show"
     :append-to-body="true"
-    title="word导出"
+    :title="dialogTitle"
     width="60%"
     top="10vh"
     :before-close="handleClose"
@@ -14,15 +14,26 @@
         class="b_left"
         v-loading="wordContentLoading"
         ref="wordAreaRef"
-        contenteditable="true"
+        :contenteditable="downFileData"
       >
         <VueOfficeDocx
           ref="vueOfficeDocxRef"
-          v-if="downFileData &&  !downFileData.txtUrl"
+          v-if="downFileData && !downFileData.txtUrl"
           :src="downFileData ? downFileData.url : ''"
         />
 
-				<txtHtmlView  ref="txtHtmlViewRef" v-if="downFileData && downFileData.txtUrl" :url="downFileData.txtUrl" @getTxtContent="getTxtContent"/>
+        <txtHtmlView
+          ref="txtHtmlViewRef"
+          v-if="downFileData && downFileData.txtUrl"
+          :url="downFileData.txtUrl"
+          @getTxtContent="getTxtContent"
+        />
+
+        <div class="cover_box" v-if="!downFileData">
+          <el-button type="primary" @click.stop="uploadWord"
+            >上传文档</el-button
+          >
+        </div>
       </div>
       <div class="b_right">
         <div class="d_box">
@@ -150,7 +161,7 @@
               class="d_b_s_button"
               type="primary"
               :disabled="!downFileData"
-              @click="exportDocx2()"
+              @click="exportDocx3()"
               >导出Word文档</el-button
             >
           </div>
@@ -171,7 +182,8 @@ import VueOfficeDocx from "@vue-office/docx";
 import "@vue-office/docx/lib/index.css";
 // import { renderAsync } from 'docx-preview/dist/docx-preview.js'
 import htmlDocx from "html-docx-js/dist/html-docx";
-import txtHtmlView from "./txtHtmlView.vue"
+import txtHtmlView from "./txtHtmlView.vue";
+import JSZip from "jszip";
 // import a from './docx-preview.js'
 const getFile = url => {
   return new Promise((resolve, reject) => {
@@ -217,7 +229,7 @@ export default {
   components: {
     topicVue,
     VueOfficeDocx,
-		txtHtmlView
+    txtHtmlView
   },
   data() {
     return {
@@ -233,13 +245,16 @@ export default {
         //     "https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/default%2F%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_202410090922471728436994846.png"
         // }
       ],
+      useFieldList: [],
       uploadTemplateDocxData: null, //上传的模板文档
       downFileData: null, // 下载模板文档的url
       checkJson: [],
       foldField: false,
       wordContent: "",
       wordContentLoading: true,
-			courseId:"",
+      courseId: "",
+      testJson: null
+      // fileList:[],
     };
   },
   methods: {
@@ -249,11 +264,25 @@ export default {
     },
     open(data) {
       this.init();
+      console.log(data);
       let _fileData = data.fileData;
       this.downFileData = _fileData;
-			this.courseId = data.courseId
-      this.checkJson = data.formData.array;
-      this.fieldList = this.getFieldData(data.formData.array);
+      this.courseId = data.courseId;
+      this.checkJson = data.formData[0].array;
+      this.testJson = data.testJson;
+      this.fieldList = this.getFieldData(data.formData[0].array);
+      let useFieldList = [];
+      data.formData.forEach(i => {
+        let obj = {
+          name: i.name,
+          id: i.id,
+          userId: i.userid,
+          fieldList: this.getFieldData(i.array),
+          time: this.formatTime(i.time)
+        };
+        useFieldList.push(obj);
+      });
+      this.useFieldList = useFieldList;
       this.getWordContent(this.downFileData);
       this.show = true;
     },
@@ -267,6 +296,7 @@ export default {
       this.fieldList = [];
       this.uploadTemplateDocxData = null;
       this.foldField = false;
+      // this.fileList = [];
     },
 
     getFieldData(array) {
@@ -368,82 +398,174 @@ export default {
         // this.uploadWavFileAndGetText(file);
       };
     },
-    async exportDocx2() {
-      const el = this.$refs.vueOfficeDocxRef?this.$refs.vueOfficeDocxRef.$el:this.$refs.txtHtmlViewRef.$el;
-			console.log(el)
+    async exportDocx3() {
+      if (!this.downFileData) return this.$message.error("请先上传模板文档");
+      const el = this.$refs.vueOfficeDocxRef
+        ? this.$refs.vueOfficeDocxRef.$el
+        : this.$refs.txtHtmlViewRef.$el;
       const body = el.querySelector(".docx-wrapper");
+      const html = body.innerHTML;
+      let promiseList = [];
+      this.useFieldList.forEach((i, index) => {
+        promiseList.push(
+          this.getUseFieldListFile({
+            fileName: `${i.name}_${this.testJson.title}_${i.time}.docx`,
+            fieldList: i.fieldList,
+            html
+          })
+        );
+      });
+      Promise.all(promiseList).then(async res => {
+        let fileList = res;
+        if (fileList.length == 0) {
+          this.$message.error("无文档导出");
+        } else if (fileList.length == 1) {
+          saveAs(fileList[0], fileList[0].name);
+          this.$message.success("导出成功");
+        } else {
+          const zip = new JSZip();
+          fileList.forEach(i => {
+            zip.file(`${i.name}`, i, { binary: true });
+          });
+          zip.generateAsync({ type: "blob" }).then(content => {
+            // 生成二进制流
+            saveAs(content, `${this.testJson.title}.zip`); // 利用file-saver保存文件  自定义文件名
+          });
+          this.$message.success("导出成功");
+        }
 
-			let _html = body.innerHTML;
+        if (
+          !this.downFileData.txtUrl ||
+          this.downFileData.txt !== el.innerHTML
+        ) {
+          let txt = el.innerHTML;
+          // 创建Blob对象
+          const blob = new Blob([txt], { type: "text/plain;charset=utf-8" });
+          blob.lastModifiedDate = new Date();
+          blob.name = `${this.downFileData.fileName}_wordHtml.txt`;
+          let url = await this.uploadFile(blob);
+          if (url && this.courseId) {
+            this.downFileData.txt = txt;
+            this.downFileData.txtUrl = url;
+            this.changeDownFileData(this.downFileData);
+            this.$forceUpdate();
+          }
+        }
+      });
+    },
+    async getUseFieldListFile({ fileName, fieldList, html }) {
+      return new Promise(async (resolve, reject) => {
+        let _html = html;
+        for (let i = 0; i < fieldList.length; i++) {
+          if (fieldList[i].type == "image") {
+            const img = await this.convertImageUrlToBase64(fieldList[i].value);
+            _html = _html.replaceAll(
+              `{%${fieldList[i].field}}`,
+              `<img src="${img.url}" width="${img.width}" height="${img.height}" />`
+            );
+          } else if (fieldList[i].type == "text") {
+            _html = _html.replaceAll(
+              `{${fieldList[i].field}}`,
+              fieldList[i].value
+            );
+          }
+        }
 
-			for(let i = 0;i<this.fieldList.length;i++){
-				if(this.fieldList[i].type == 'image'){
-					const img = await this.convertImageUrlToBase64(this.fieldList[i].value)
-					_html = _html.replaceAll(`{%${this.fieldList[i].field}}`,`<img src="${img.url}" width="${img.width}" height="${img.height}" />`)
-				}else if(this.fieldList[i].type == 'text'){
-					_html = _html.replaceAll(`{${this.fieldList[i].field}}`,this.fieldList[i].value)
-				}
-			}
-			// this.fieldList.forEach(i => {
-				// _html = _html.replace(`{${i.field}}`,i.value)
-			// })
-			// 下载word文档
-			await this.generateDocx(this.downFileData.fileName,_html)
-
-			if(!this.downFileData.txtUrl || this.downFileData.txt !== el.innerHTML){
-				let txt = el.innerHTML;
-				// 创建Blob对象
-				const blob = new Blob([txt], { type: "text/plain;charset=utf-8" });
-				blob.lastModifiedDate = new Date();
-				blob.name = `${this.downFileData.fileName}_wordHtml.txt`;
-				let url = await this.uploadFile(blob)
-
-				if(url && this.courseId){
-					console.log("修改文件")
-					console.log(url)
-					console.log(this.courseId)
-					this.downFileData.txt = txt
-					this.downFileData.txtUrl = url
-					this.changeDownFileData(this.downFileData)
-					this.$forceUpdate();
-				}
-			}
-			// const uploadBlob = await this.getGenerateDocxHtml(body.out)
+        let blob = await this.getGenerateDocxHtml(_html);
+        const file = new File([blob], fileName, {
+          type: ".docx",
+          lastModified: new Date().getTime()
+        });
+        // this.fileList.push(file)
+        resolve(file);
+      });
+    },
+    async exportDocx2() {
+      const el = this.$refs.vueOfficeDocxRef
+        ? this.$refs.vueOfficeDocxRef.$el
+        : this.$refs.txtHtmlViewRef.$el;
+      console.log(el);
+      const body = el.querySelector(".docx-wrapper");
+
+      let _html = body.innerHTML;
+
+      for (let i = 0; i < this.fieldList.length; i++) {
+        if (this.fieldList[i].type == "image") {
+          const img = await this.convertImageUrlToBase64(
+            this.fieldList[i].value
+          );
+          _html = _html.replaceAll(
+            `{%${this.fieldList[i].field}}`,
+            `<img src="${img.url}" width="${img.width}" height="${img.height}" />`
+          );
+        } else if (this.fieldList[i].type == "text") {
+          _html = _html.replaceAll(
+            `{${this.fieldList[i].field}}`,
+            this.fieldList[i].value
+          );
+        }
+      }
+      // this.fieldList.forEach(i => {
+      // _html = _html.replace(`{${i.field}}`,i.value)
+      // })
+      // 下载word文档
+      await this.generateDocx(this.downFileData.fileName, _html);
+
+      if (!this.downFileData.txtUrl || this.downFileData.txt !== el.innerHTML) {
+        let txt = el.innerHTML;
+        // 创建Blob对象
+        const blob = new Blob([txt], { type: "text/plain;charset=utf-8" });
+        blob.lastModifiedDate = new Date();
+        blob.name = `${this.downFileData.fileName}_wordHtml.txt`;
+        let url = await this.uploadFile(blob);
+
+        if (url && this.courseId) {
+          console.log("修改文件");
+          console.log(url);
+          console.log(this.courseId);
+          this.downFileData.txt = txt;
+          this.downFileData.txtUrl = url;
+          this.changeDownFileData(this.downFileData);
+          this.$forceUpdate();
+        }
+      }
+      // const uploadBlob = await this.getGenerateDocxHtml(body.out)
 
-			// let reader = new FileReader();
+      // let reader = new FileReader();
       // reader.readAsArrayBuffer(uploadBlob);
-			// reader.onload = async e => {
-			// 	try {
-			// 		const binary = new Uint8Array(reader.result);
-			// 		//创建一个PizZip实例
-			// 		const zip = new PizZip(binary);
-			// 		// 将模板内容加载到 Docxtemplater 中
-			// 		const doc = new Docxtemplater().loadZip(zip);
-			// 		const output = doc.getZip().generate({
+      // reader.onload = async e => {
+      // 	try {
+      // 		const binary = new Uint8Array(reader.result);
+      // 		//创建一个PizZip实例
+      // 		const zip = new PizZip(binary);
+      // 		// 将模板内容加载到 Docxtemplater 中
+      // 		const doc = new Docxtemplater().loadZip(zip);
+      // 		const output = doc.getZip().generate({
       //       type: "blob",
       //       mimeType:
       //         "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
       //       compression: "DEFLATE"
       //     });
 
-			// 		const file = new File([output],this.downFileData.fileName,{type:".docx",lastModified:new Date().getTime()})
-
-			// 		const url = await this.uploadFile(file)
-			// 		console.log(url)
-
-			// 	}catch(e){
-			// 		console.log(e)
-			// 	}
-			// }
-			// const file = new File([uploadBlob],this.downFileData.fileName,{type:".docx",lastModified:new Date().getTime()})
-			
-			// const url = await this.uploadFile(file)
-			// console.log(url)
-			// if(url){
-				
-			// }else{
-				
-			// }
-			return
+      // 		const file = new File([output],this.downFileData.fileName,{type:".docx",lastModified:new Date().getTime()})
+
+      // 		const url = await this.uploadFile(file)
+      // 		console.log(url)
+
+      // 	}catch(e){
+      // 		console.log(e)
+      // 	}
+      // }
+      // const file = new File([uploadBlob],this.downFileData.fileName,{type:".docx",lastModified:new Date().getTime()})
+
+      // const url = await this.uploadFile(file)
+      // console.log(url)
+      // if(url){
+
+      // }else{
+
+      // }
+      return;
       // const blob = await this.getGenerateDocxHtml(body.innerHTML);
       // if (!blob) return this.$message.error("导出失败");
 
@@ -501,7 +623,7 @@ export default {
       //         return [newWidth, newHeight];
       //       }
       //     };
-			// 		console.log()
+      // 		console.log()
       //     doc.attachModule(new ImageModule(opts));
       //     //渲染模板
       //     doc.setData(_data);
@@ -533,6 +655,7 @@ export default {
       // };
     },
     async exportDocx() {
+      console.log(this.useFieldList);
       if (!this.uploadTemplateDocxData)
         return this.$message.error("请先上传模板文档");
       let reader = new FileReader();
@@ -760,7 +883,7 @@ export default {
 							.vue-office-docx .docx-wrapper>section.docx{padding:10px!important;width:100%!important}
 						}
 
-.docx-wrapper { background: gray; padding: 30px; padding-bottom: 0px; display: flex; flex-flow: column; align-items: center; } 
+.docx-wrapper { background: gray; padding: 30px; padding-bottom: 0px; display: flex; flex-flow: column; align-items: center; }
 .docx-wrapper>section.docx { background: white; box-shadow: 0 0 10px rgba(0, 0, 0, 0.5); margin-bottom: 30px; }
 .docx { color: black; hyphens: auto; text-underline-position: from-font; }
 section.docx { box-sizing: border-box; display: flex; flex-flow: column nowrap; position: relative; overflow: hidden; }
@@ -913,7 +1036,7 @@ p.docx-num-1-0 {
 							.vue-office-docx .docx-wrapper>section.docx{padding:10px!important;width:100%!important}
 						}
 
-.docx-wrapper { background: gray; padding: 30px; padding-bottom: 0px; display: flex; flex-flow: column; align-items: center; } 
+.docx-wrapper { background: gray; padding: 30px; padding-bottom: 0px; display: flex; flex-flow: column; align-items: center; }
 .docx-wrapper>section.docx { background: white; box-shadow: 0 0 10px rgba(0, 0, 0, 0.5); margin-bottom: 30px; }
 .docx { color: black; hyphens: auto; text-underline-position: from-font; }
 section.docx { box-sizing: border-box; display: flex; flex-flow: column nowrap; position: relative; overflow: hidden; }
@@ -998,75 +1121,132 @@ p.docx-num-1-0 {
 ${html}
 </body>
 </html>`;
-// console.log(content)
-// return console.log(content)
-// debugger
-let blob = htmlDocx.asBlob(content);
-return blob;
+      // console.log(content)
+      // return console.log(content)
+      // debugger
+      let blob = htmlDocx.asBlob(content);
+      return blob;
     },
-		uploadFile(file) {
-      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"; //设置区域
-
-      var bucket = new window.AWS.S3({ params: { Bucket: "ccrb" } }); //选择桶
-      var _this = this;
-
-      if (file) {
-        // this.loading = true;
-        var params = {
-          Key:
-            file.name.split(".")[0] +
-            new Date().getTime() +
-            "." +
-            file.name.split(".")[file.name.split(".").length - 1],
-          ContentType: file.type,
-          Body: file,
-          "Access-Control-Allow-Credentials": "*",
-          ACL: "public-read"
-        }; //key可以设置为桶的相抵路径,Body为文件, ACL最好要设置
-        var options = {
-          partSize: 2048 * 1024 * 1024,
-          queueSize: 2,
-          leavePartsOnError: true
-        };
-        bucket
-          .upload(params, options)
-          .on("httpUploadProgress", function(evt) {
-            //这里可以写进度条
-            _this.progressData.value = parseInt((evt.loaded * 100) / evt.total);
-            // console.log("Uploaded : " + parseInt((evt.loaded * 80) / evt.total) + '%');
-          })
-          .send(function(err, data) {
-            if (err) {
-              _this.$message.error("上传失败");
-            } else {
-							resolve(data.Location)
-            }
-          });
-      }
-			})
+    uploadFile(file) {
+      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"; //设置区域
+
+        var bucket = new window.AWS.S3({ params: { Bucket: "ccrb" } }); //选择桶
+        var _this = this;
+
+        if (file) {
+          // this.loading = true;
+          var params = {
+            Key:
+              file.name.split(".")[0] +
+              new Date().getTime() +
+              "." +
+              file.name.split(".")[file.name.split(".").length - 1],
+            ContentType: file.type,
+            Body: file,
+            "Access-Control-Allow-Credentials": "*",
+            ACL: "public-read"
+          }; //key可以设置为桶的相抵路径,Body为文件, ACL最好要设置
+          var options = {
+            partSize: 2048 * 1024 * 1024,
+            queueSize: 2,
+            leavePartsOnError: true
+          };
+          bucket
+            .upload(params, options)
+            .on("httpUploadProgress", function(evt) {
+              //这里可以写进度条
+              _this.progressData.value = parseInt(
+                (evt.loaded * 100) / evt.total
+              );
+              // console.log("Uploaded : " + parseInt((evt.loaded * 80) / evt.total) + '%');
+            })
+            .send(function(err, data) {
+              if (err) {
+                _this.$message.error("上传失败");
+              } else {
+                resolve(data.Location);
+              }
+            });
+        }
+      });
     },
-		changeDownFileData(data){
-			let _data = JSON.parse(JSON.stringify(data))
-			delete _data.txt;
-
-			let params = [{
-				cid:this.courseId,
-				ncover:JSON.stringify(_data),
-			}]
-			this.$emit("changeCover",JSON.stringify(_data))
-			this.ajax.post(this.$store.state.api+"update_testCourseCoverById",params).then(res=>{
-				console.log(res.data)
-			})
-		},
-		getTxtContent(txt){
-			this.downFileData.txt = txt
+    changeDownFileData(data) {
+      let _data = JSON.parse(JSON.stringify(data));
+      delete _data.txt;
+
+      let params = [
+        {
+          cid: this.courseId,
+          ncover: JSON.stringify(_data)
+        }
+      ];
+      this.$emit("changeCover", JSON.stringify(_data));
+      this.ajax
+        .post(this.$store.state.api + "update_testCourseCoverById", params)
+        .then(res => {
+          console.log(res.data);
+        });
+    },
+    getTxtContent(txt) {
+      this.downFileData.txt = txt;
+    },
+		uploadWord(){
+			let input = document.createElement("input");
+      input.type = "file";
+      // input.accept = ".wav";
+      // input.accept = "audio/*, .txt, .pdf, .xlsx";
+      input.accept = ".docx";
+      input.click();
+      input.onchange = async () => {
+        this.loading = true;
+        let file = input.files[0];
+        if (!/\.(docx)$/i.test(file.name)) {
+          this.loading = false;
+          return this.$message.error("请上传.docx格式的文件");
+        }
+        let uploadData = await this.uploadFile(file);
+        if (uploadData == 1) {
+          this.loading = false;
+          return this.$message.error("文件上传失败");
+        }
+				let obj = {
+					fileName:file.name,
+					url:uploadData,
+				}
+				this.downFileData = obj;
+				this.changeDownFileData(this.downFileData);
+				this.loading = false;
+				console.log(uploadData)
+			}
 		},
+		formatTime(timeString) {
+    let [datePart, timePart] = timeString.split(' ');
+    let formattedTime = timePart.replace(/:/g, (match, offset) => {
+      if (offset === 2) return '时';
+      if (offset === 5) return '分';
+      return match;
+    }) + '秒';
+    return datePart + ' ' + formattedTime;
+  },
+  },
+  computed: {
+    dialogTitle() {
+      let _result = "word导出";
+      if (this.useFieldList.length == 0) {
+        _result = "word导出";
+      } else if (this.useFieldList.length == 1) {
+        _result = `${this.useFieldList[0].name}数据word导出`;
+      } else {
+        _result = `批量word导出`;
+      }
+      return _result;
+    }
   }
 };
 </script>
@@ -1251,4 +1431,12 @@ return blob;
   color: #409eff;
   font-size: 16px;
 }
+
+.cover_box {
+  width: 100%;
+  height: 100%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
 </style>

+ 8 - 3
src/components/pages/test/check/index.vue

@@ -121,10 +121,13 @@
                   <div v-show="btnDisplay" class="buttonBox">
                     <div type="primary" @click="exportExcel">下载汇总表格</div>
                     <div type="primary" @click="exportAllWord">导出人员数据</div>
+										<div type="primary" v-if="stype == 2" @click="exportWordData">word导出</div>
                   </div>
                 </div>
+								
                 <div class="btnA" v-if="stype == 3" @click="exportAllWord2">导出人员数据</div>
                 <div class="btnA" @click="openChat" v-if="this.worksArray.length">AI分析</div><!--v-if="this.worksArray.length"-->
+								
               </div>
             </div>
              <!-- 手机端 查看切换 isDesktop-->
@@ -635,7 +638,7 @@
                 <template slot-scope="scope">
                   <el-button @click="getTest(scope.row)" type="primary" size="small">查看</el-button>
                   <el-button @click="setWordHtml(scope.row)" type="primary" size="small">导出答题信息</el-button>
-									<el-button @click="setWordTemplate(scope.row)" v-if="testJson.cover" type="primary" size="small">word导出</el-button>
+									<el-button @click="setWordTemplate(scope.row)" type="primary" size="small">word导出</el-button>
                   <el-button @click="deleteTest(scope.row.id)" type="primary" size="small">删除</el-button>
                 </template>
               </el-table-column>
@@ -2380,12 +2383,14 @@ export default {
         });
     },
 		setWordTemplate(item){
-			this.$refs.docxTemplateDialogRef.open({fileData:JSON.parse(this.testJson.cover),courseId:this.testJson.courseId,formData:item})//这里可以传数据
-			// console.log(item)
+			this.$refs.docxTemplateDialogRef.open({fileData:this.testJson.cover?JSON.parse(this.testJson.cover):null,testJson:this.testJson,courseId:this.testJson.courseId,formData:[item]})//这里可以传数据
 		},
 		changeCover(data){
 			this.testJson.cover = data
 		},
+		exportWordData(){
+			this.$refs.docxTemplateDialogRef.open({fileData:this.testJson.cover?JSON.parse(this.testJson.cover):null,testJson:this.testJson,courseId:this.testJson.courseId,formData:this.worksArray})//这里可以传数据
+		}
   },
   beforeDestroy() {
     document.getElementsByTagName('html')[0].style.overflow = '';