SanHQin 5 months ago
parent
commit
2a3e9061d6

+ 6 - 4
src/components/pages/test/add/addTest.vue

@@ -24,7 +24,7 @@
                     <div class="r_pub_button_retrun" @click="retrunCourse">返回</div>
                 </div>
                 <div class="step_box" :style="{ width: steps == 2 && '100%' }">
-                    <editInfo v-if="steps == 2 && !loading" :oid="oid" :org="org" :steps.sync="steps"
+                    <editInfo v-if="steps == 2 && !loading" :oid="oid" :org="org" :steps.sync="steps" :fileData.sync="fileData"
                         :title.sync="title" :brief.sync="brief" :cJson.sync="cJson" @save="save" @publish="publish">
                     </editInfo>
                 </div>
@@ -73,7 +73,8 @@ export default {
             juriList: [],
             typeInfo: [],
             dialogVisible: false,
-            origin: ""
+            origin: "",
+						fileData:null,
         }
     },
     watch: {
@@ -164,7 +165,7 @@ export default {
                     uid: this.userid,
                     title: this.title,
                     brief: this.brief,
-                    cover: "",
+                    cover: JSON.stringify(this.fileData),
                     evaId: "",
                     astudent: this.juri,
                     see: this.see == true ? 1 : 0,
@@ -226,7 +227,7 @@ export default {
                     cid: this.cid,
                     title: this.title,
                     brief: this.brief,
-                    cover: "",
+                    cover: JSON.stringify(this.fileData),
                     evaId: "",
                     astudent: this.juri,
                     see: this.see == true ? 1 : 0,
@@ -315,6 +316,7 @@ export default {
 
                         this.typeid = res.data[0][0].typeid;
                         this.brief = res.data[0][0].brief;
+												this.fileData = res.data[0][0].cover?JSON.parse(res.data[0][0].cover):null;
                         this.testType = [];
                         for (var i = 0; i < res.data[1].length; i++) {
                             this.testType.push(res.data[1][i].typeid);

+ 96 - 5
src/components/pages/test/add/edit/edit/index.vue

@@ -1,7 +1,10 @@
 <template>
   <div class="edit_box">
-    <div class="e_add">
+    <div class="e_add" v-show="showLeftMenu">
       <div class="title" style="margin-bottom: 20px">题目添加</div>
+			<span class="e_a_foldIcon" style="right: 0;" @click="showLeftMenu=false">
+				<svg t="1728443188732" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5721" width="200" height="200"><path d="M110.9 128.34a32 32 0 0 1 32-32h773a32 32 0 0 1 0 64h-773a32 32 0 0 1-32-32z m4.58 402.15L260 651.38c15.62 13.07 39.4 2 39.4-18.41V391.19c0-20.37-23.78-31.48-39.4-18.41L115.48 493.67a24 24 0 0 0 0 36.82z m800.41-50.41H405.54a32 32 0 1 0 0 64h510.35a32 32 0 0 0 0-64z m0 383.58h-773a32 32 0 1 0 0 64h773a32 32 0 0 0 0-64z" p-id="5722"></path></svg>
+			</span>
       <div class="e_add_box">
         <div class="title">基础题型</div>
         <div class="e_add_ci">
@@ -81,7 +84,20 @@
         </div>
       </div>
     </div>
-    <div class="e_content">
+
+		<div class="e_viewFile" v-show="viewFile" :style="`margin-right:${!showLeftMenu?'20px':0};margin-left:${showLeftMenu?'20px':'0'}`">
+			<iframe
+        ref="viframe"
+				v-if="fileData && fileData.url"
+        style="width: 100%; height: 100%; border: none"
+        :src="
+          'https://view.officeapps.live.com/op/view.aspx?src=' +
+            encodeURIComponent(fileData.url)
+        "
+      ></iframe>
+		</div>
+
+    <div class="e_content" :style="`margin-right:${showRightMenu?'20px':0};margin-left:${showLeftMenu?'20px':0};`">
       <div v-if="!isEditing" class="title" @click="editTitle">{{ title ? title : '请填写表单标题' }}</div>
       <input v-if="isEditing" class="titleInput" ref="title" v-model="titleValue" @blur="save" @keyup.enter="save" placeholder="请填写表单标题"/>
       <div v-if="!isEditing2" class="detail" @click="editBref">{{ brief ? brief : '请填写表单说明' }}</div>
@@ -97,11 +113,14 @@
         </checkOrder>
       </div>
     </div>
-    <div class="e_order">
+    <div class="e_order" v-show="showRightMenu">
       <div class="title">
         题目排序
         <span style="font-size: 14px; color: #373737">总分:{{ score }}分</span>
       </div>
+			<span class="e_a_foldIcon" style="left: 0;transform: rotate(180deg);" @click="showRightMenu=false">
+				<svg t="1728443188732" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5721" width="200" height="200"><path d="M110.9 128.34a32 32 0 0 1 32-32h773a32 32 0 0 1 0 64h-773a32 32 0 0 1-32-32z m4.58 402.15L260 651.38c15.62 13.07 39.4 2 39.4-18.41V391.19c0-20.37-23.78-31.48-39.4-18.41L115.48 493.67a24 24 0 0 0 0 36.82z m800.41-50.41H405.54a32 32 0 1 0 0 64h510.35a32 32 0 0 0 0-64z m0 383.58h-773a32 32 0 1 0 0 64h773a32 32 0 0 0 0-64z" p-id="5722"></path></svg>
+			</span>
       <div class="e_order_box" style="margin-top: 20px">
         <checkOrder
           :checkC.sync="checkC"
@@ -113,7 +132,15 @@
         </checkOrder>
       </div>
     </div>
-  </div>
+
+		<span class="e_outside_foldIcon" v-if="!showLeftMenu" style="left: 0;transform: rotate(180deg);" @click="showLeftMenu = true">
+			<svg t="1728443188732" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5721" width="200" height="200"><path d="M110.9 128.34a32 32 0 0 1 32-32h773a32 32 0 0 1 0 64h-773a32 32 0 0 1-32-32z m4.58 402.15L260 651.38c15.62 13.07 39.4 2 39.4-18.41V391.19c0-20.37-23.78-31.48-39.4-18.41L115.48 493.67a24 24 0 0 0 0 36.82z m800.41-50.41H405.54a32 32 0 1 0 0 64h510.35a32 32 0 0 0 0-64z m0 383.58h-773a32 32 0 1 0 0 64h773a32 32 0 0 0 0-64z" p-id="5722"></path></svg>
+		</span>
+
+		<span class="e_outside_foldIcon" v-if="!showRightMenu" style="right: 0;" @click="showRightMenu = true">
+			<svg t="1728443188732" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5721" width="200" height="200"><path d="M110.9 128.34a32 32 0 0 1 32-32h773a32 32 0 0 1 0 64h-773a32 32 0 0 1-32-32z m4.58 402.15L260 651.38c15.62 13.07 39.4 2 39.4-18.41V391.19c0-20.37-23.78-31.48-39.4-18.41L115.48 493.67a24 24 0 0 0 0 36.82z m800.41-50.41H405.54a32 32 0 1 0 0 64h510.35a32 32 0 0 0 0-64z m0 383.58h-773a32 32 0 1 0 0 64h773a32 32 0 0 0 0-64z" p-id="5722"></path></svg>
+		</span>
+</div>
 </template>
 
 <script>
@@ -134,6 +161,14 @@ export default {
     brief: {
       type: String,
     },
+		viewFile:{
+			type:Boolean,
+			default:false,
+		},
+		fileData:{
+			type:Object,
+			default:()=>({fileName:"",url:""})
+		},
   },
   data() {
     return {
@@ -144,6 +179,8 @@ export default {
       titleValue: "",
       isEditing2: false,
       briefValue: "",
+			showLeftMenu:true,
+			showRightMenu:true,
     };
   },
   watch: {
@@ -564,6 +601,7 @@ export default {
   justify-content: space-between;
   padding: 0 0 0;
   box-sizing: border-box;
+	position: relative;
 }
 
 .e_add {
@@ -575,16 +613,20 @@ export default {
   box-sizing: border-box;
   /* border-right: 1px solid #e5e5e5; */
   border-radius: 5px;
+	position: relative;
 }
 
 .e_content {
   height: 100%;
-  width: calc(100% - 640px);
+	flex: 1;
+	/* margin: 0 20px; */
+  /* width: calc(100% - 640px); */
   background: #fff;
   overflow: auto;
   padding: 20px;
   box-sizing: border-box;
   border-radius: 5px;
+
 }
 
 .e_content > .title {
@@ -634,6 +676,7 @@ export default {
   padding: 20px 10px;
   box-sizing: border-box;
   border-radius: 5px;
+	position: relative;
 }
 
 .e_add > .title,
@@ -688,4 +731,52 @@ export default {
   margin-bottom: 10px;
   width: 50%;
 }
+
+.e_a_foldIcon{
+	width: 30px;
+	height: 30px;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	position: absolute;
+	top: 15px;
+	border-radius: 5px 0 0 5px;
+	background-color: #409EFF;
+	cursor: pointer;
+}
+
+.e_a_foldIcon>svg{
+	width: 20px;
+	height: 20px;
+	fill: #fff;
+}
+
+.e_outside_foldIcon{
+	width: 40px;
+	height: 40px;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	position: absolute;
+	top: 15px;
+	border-radius: 5px 0 0 5px;
+	background-color: #409EFF;
+	cursor: pointer;
+}
+
+.e_outside_foldIcon>svg{
+	width: 20px;
+	height: 20px;
+	fill: #fff;
+}
+
+.e_viewFile{
+	height: 100%;
+	flex: 1;
+	margin-left: 20px;
+	background-color: #FFFFFF;
+	border-radius: 5px;
+	box-sizing: border-box;
+	overflow-y: hidden;	
+}
 </style>

+ 273 - 41
src/components/pages/test/add/edit/index.vue

@@ -1,12 +1,25 @@
 <template>
-  <div class="rightBox">
+  <div class="rightBox" v-loading="loading">
     <!-- <div class="title">
       <div class="c_info_title">创建表单内容</div>
     </div> -->
     <div class="edit_top">
+      <div class="e_t_left">
+        <el-button type="primary" size="small" @click="useAiBtn()"
+          >智能生成表单</el-button
+        >
+
+				<el-button :type="viewFile?'primary':''" size="small" v-if="fileData" @click="viewUploadFile()"
+          >预览</el-button
+        >
+      </div>
       <div class="edit_btn">
-        <span class="edit" :class="{ active: type == 1 }" @click="type = 1">编辑</span>
-        <span class="check" :class="{ active: type == 2 }" @click="type = 2">预览</span>
+        <span class="edit" :class="{ active: type == 1 }" @click="type = 1"
+          >编辑</span
+        >
+        <span class="check" :class="{ active: type == 2 }" @click="type = 2"
+          >预览</span
+        >
         <!-- <span :class="{ active: type == 3 }" @click="type = 3">回答</span>
         <span :class="{ active: type == 4 }" @click="type = 4">统计</span> -->
       </div>
@@ -14,20 +27,29 @@
         <!-- <el-button type="primary" size="small" @click="lastSteps">上一步</el-button> -->
         <el-button type="primary" size="small" @click="save">保存</el-button>
         <el-button type="primary" size="small" @click="publish">发布</el-button>
-
       </div>
     </div>
     <div class="e_box">
-      <editBox v-if="type == 1" :checkJson="checkJson" @changeJson="changeJson" :title="title" :brief="brief" @updateTitle="updateTitle" @updateBrief="updateBrief"></editBox>
+      <editBox
+        v-if="type == 1"
+        :checkJson="checkJson"
+        @changeJson="changeJson"
+        :title="title"
+        :brief="brief"
+				:fileData="fileData"
+				:viewFile="viewFile"
+        @updateTitle="updateTitle"
+        @updateBrief="updateBrief"
+      ></editBox>
       <checkBox v-if="type == 2" :cJson="checkJson" :title="title"></checkBox>
     </div>
   </div>
 </template>
 
 <script>
-import editBox from './edit/index.vue'
-import checkBox from './check/index.vue'
-
+import editBox from "./edit/index.vue";
+import checkBox from "./check/index.vue";
+import { v4 as uuidv4 } from "uuid";
 export default {
   components: {
     editBox,
@@ -57,45 +79,251 @@ export default {
     return {
       type: 1,
       checkJson: [],
-    }
+      loading: false,
+			userId: this.$route.query.userid,
+			fileData:null,
+			viewFile:false,
+    };
   },
   watch: {
     cJson: {
-      handler: function (newVal, oldVal) {
+      handler: function(newVal, oldVal) {
         this.checkJson = this.depthCopy(newVal);
       },
-      deep: true,
-    },
+      deep: true
+    }
   },
   methods: {
-    updateTitle(value){
+    updateTitle(value) {
       console.log(value);
-      this.$emit('update:title', value)
+      this.$emit("update:title", value);
     },
-    updateBrief(value){
-      this.$emit('update:brief', value)
+    updateBrief(value) {
+      this.$emit("update:brief", value);
     },
+		updateFileData(value){
+			this.$emit("update:fileData",value)
+		},
     lastSteps() {
-      this.$emit('update:steps', this.steps - 1)
+      this.$emit("update:steps", this.steps - 1);
     },
     save() {
-      this.$emit("save", 4)
+      this.$emit("save", 4);
     },
     publish() {
-      this.$emit("publish")
+      this.$emit("publish");
     },
     depthCopy(s) {
-      return s ? JSON.parse(JSON.stringify(s)) : ''
+      return s ? JSON.parse(JSON.stringify(s)) : "";
     },
     changeJson(json) {
       console.log(json);
       this.$emit("update:cJson", json);
-    }
+    },
+    async useAiBtn(type = 0) {
+      if (type == 0 && this.checkJson.length > 0) {
+        return this.$confirm(
+          "使用智能检索功能会覆盖已有表单,确定使用吗?",
+          "提示",
+          {
+            confirmButtonText: "确定",
+            cancelButtonText: "取消",
+            type: "warning"
+          }
+        )
+          .then(() => {
+            this.useAiBtn(1);
+          })
+          .catch(() => {
+            console.log("不使用");
+          });
+      }
+      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 _fileData = {
+          fileName: uploadData.Key,
+          url: uploadData.Location,
+          fileId: await this.fileGetFileId(uploadData.Location)
+        };
+        if (_fileData.fileId == 1) {
+          this.loading = false;
+          return this.$message.error("文件获取fileId失败");
+        }
+
+				let testData = await this.getCheckJSon(_fileData.fileId);
+				if (testData == 1) {
+          this.loading = false;
+          return this.$message.error("生成题目失败");
+        }
+				let _titleData = testData.find(i=>(i.formName || i.illustrate))
+				testData = testData.filter(i=>!(i.formName || i.illustrate))
+				this.fileData = _fileData;
+				this.updateFileData(_fileData);
+				if(_titleData){
+					this.updateTitle(_titleData.formName)
+					this.updateBrief(_titleData.illustrate)
+				}
+				this.changeJson(testData)
+				this.viewFile = true;
+        console.log(_fileData);
+				console.log(_titleData)
+				console.log(testData)
+        this.loading = false;
+        // this.uploadWavFileAndGetText(file);
+      };
+    },
+    uploadFile(file) {
+      return new Promise(resolve => {
+        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) {
+          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) {
+                resolve(1);
+              } else {
+                resolve(data);
+              }
+            });
+        }
+      });
+    },
+    fileGetFileId(url) {
+      return new Promise(resolve => {
+        this.ajax
+          .put("https://gpt4.cocorobo.cn/upload_file_knowledge", { url: url })
+          .then(res => {
+            let _data = res.data.FunctionResponse;
+            if (_data.result && _data.result.id) {
+              resolve(_data.result.id);
+            } else {
+              resolve(1);
+            }
+          })
+          .catch(e => {
+            console.log(e);
+            resolve(1);
+          });
+      });
+    },
+    getCheckJSon(fileId) {
+      return new Promise(resolve => {
+        let _msg = `Language: Please use the same language as the user requirement, if the user speaks Chinese, the specific text of your answer should also be in Chinese.
+ATTENTION: Use '##' to SPLIT SECTIONS, not '#'. Output format carefully referenced "Format example".
+Instruction: Based on the context, follow "Format example", write content
+
+#Context
+##角色描述
+你是一位行政文员,你需要提取文档中需要收集的信息,梳理出需要收集的信息表格,确定信息收表的题目内容与题目类型。
+##任务描述
+你的任务是阅读上传文档中的内容,提取并输出文档中需要填写的信息,并输出收集信息表单,输出格式为## Format example。你的任务分为三步:
+第一步:提取文档中需要收集的信息内容。信息内容使用文件中的原文,并直接“## Format example”的形式罗列出需要收集的信息清单,不需要二次的分类和总结。通常提取文档中表格中的内容,其他描述性的文字、项目背景、审核意见等内容不应该出现在需要收集的表单内。
+第二步:判断这些需要需要收集的信息以什么题目类型的进行收集,除“年 月 日/日期”等内容使用日期外,其他题目都默认使用文本。
+第三步:输出信息收集表单,你仅仅只需要输出一份## Format example格式的数据,不需要增加任何描述性文字。
+##信息补充
+表单的题目类型包含问答、单选、多选
+文本:需要收集的信息为文本格式的内容,例如“姓名、年级、项目经历、获奖等文本内容”
+单选:需要收集的信息提供了选项,例如文档的表格中出现“性别 男 女” 。或文档中某项收集信息中提供了“是 否”或其他具有选择符号的内容,需要关联上下文判断。
+日期:文档中单独出现需要收集的信息中设计到“年 月 日”“日期”“时间”等,与日期相关的内容。如果文档中出现多个日期相关的题目,只保留一个日期题目类型即可。
+标题:文档中的总标题
+说明:文档中的总标题下的说明性文字
+
+##题目格式
+问答题:{"ttype":1,"type":3,"json":{"title":"标题","type":1,"answer":""}}
+单选题:{"ttype":1,"type":1,"json":{"title":"标题","type":1,"array":[{"option":"选项1","img":""}, {"option":"选项2","img":""}],"answer":""}}
+多选题:{"ttype":1,"type":1,"json":{"title":"标题","type":2,"array":[{"option":"选项1","img":""},{"option":"选项2","img":""}],"answer":""}}
+
+标题和说明:{"formName":"标题","illustrate":"说明"}
+
+## Format example
+[{"formName":"标题","illustrate":"说明"},{"ttype":1,"type":3,"json":{"title":"标题","type":1,"answer":""}},{"ttype":1,"type":1,"json":{"title":"标题","type":1,"array":[{"option":"选项1","img":""},{"option":"选项2","img":""}],"answer":""}},{"ttype":1,"type":1,"json":{"title":"标题","type":2,"array":[{"option":"选项1","img":""},{"option":"选项2","img":""}],"answer":""}}]
+`;
+// 日期:{"ttype":1,"type":8,"json":{"title":"标题","detail":""}}
+
+        let params = {
+          assistant_id: "6063369f-289a-11ef-8bf4-12e77c4cb76b",
+          message: [{ type: "text", text: _msg }],
+          session_name: uuidv4(),
+          userId: this.userId,
+          file_ids: [fileId],
+          model: "gpt-4o-2024-08-06"
+        };
+        this.ajax
+          // .post("https://gpt4.cocorobo.cn/chat", params)
+          // .post("https://claude3.cocorobo.cn/chat", params)
+          .post("https://gpt4.cocorobo.cn/ai_agent_park_chat", params)
+          .then(res => {
+            let _data = res.data.FunctionResponse.message;
+            _data = _data.replaceAll("```json", "").replaceAll("```", "");
+            // const match = _data.match(/\[\s*\{[\s\S]*?\}\s*\]/);
+						// console.log("👇")
+						// console.log(match[0])
+            let _result = JSON.parse(_data) || [];
+            if (_result.length > 0) {
+              resolve(_result);
+            } else {
+              resolve(1);
+            }
+          })
+          .catch(e => {
+            console.log(e);
+            resolve(1);
+          });
+      });
+    },
+		viewUploadFile(){
+			this.viewFile = !this.viewFile;
+		}
   },
   mounted() {
     this.checkJson = this.depthCopy(this.cJson);
-  },
-}
+  }
+};
 </script>
 
 <style scoped>
@@ -111,11 +339,11 @@ export default {
 }
 
 .c_info_title::before {
-  content: '';
+  content: "";
   display: block;
   width: 3px;
   height: 20px;
-  background: #0061FF;
+  background: #0061ff;
   border-radius: 3px;
   margin: 0 5px 0 0;
 }
@@ -131,7 +359,7 @@ export default {
   box-sizing: border-box;
 }
 
-.rightBox>.title {
+.rightBox > .title {
   background: #fff;
   width: 100%;
   padding: 0 20px 0;
@@ -147,17 +375,17 @@ export default {
   position: relative;
 }
 
-.edit_top>.edit_btn {
+.edit_top > .edit_btn {
   display: flex;
   height: 40px;
   align-items: center;
-  border: 1px solid #E5E5E5;
+  border: 1px solid #e5e5e5;
   box-sizing: border-box;
   padding: 4px;
   border-radius: 4px;
 }
 
-.edit_top>.edit_btn>span {
+.edit_top > .edit_btn > span {
   cursor: pointer;
   padding-bottom: 5px;
   display: block;
@@ -172,46 +400,44 @@ export default {
   border-radius: 4px;
 }
 
-.edit_top>.edit_btn>.active {
+.edit_top > .edit_btn > .active {
   color: #3e88f4;
   /* border-bottom: 2px solid #2f80f3; */
   background: rgb(224, 234, 251);
 }
 
-.edit_top>.edit_btn>span+span {
+.edit_top > .edit_btn > span + span {
   margin-left: 10px;
 }
 
-
-.edit_top>.edit_btn>span::before {
-  content: '';
+.edit_top > .edit_btn > span::before {
+  content: "";
   display: block;
   background-size: 100% 100%;
   margin-right: 8px;
 }
 
-.edit_top>.edit_btn>.check::before {
+.edit_top > .edit_btn > .check::before {
   width: 15px;
   height: 15px;
   background-image: url(../../../../../assets/icon/test/add_check_icon.png);
 }
 
-.edit_top>.edit_btn>.edit::before {
+.edit_top > .edit_btn > .edit::before {
   width: 15px;
   height: 16px;
   background-image: url(../../../../../assets/icon/test/add_edit_icon.png);
 }
 
-.edit_top>.edit_btn>.active.check::before {
+.edit_top > .edit_btn > .active.check::before {
   background-image: url(../../../../../assets/icon/test/add_check_icon_active.png);
 }
 
-.edit_top>.edit_btn>.active.edit::before {
+.edit_top > .edit_btn > .active.edit::before {
   background-image: url(../../../../../assets/icon/test/add_edit_icon_active.png);
 }
 
-
-.edit_top>.op_btn {
+.edit_top > .op_btn {
   position: absolute;
   right: 30px;
 }
@@ -227,4 +453,10 @@ export default {
   box-sizing: border-box;
   margin: 20px auto 0;
   border-radius: 5px;
-}</style>
+}
+
+.e_t_left {
+  position: absolute;
+  left: 30px;
+}
+</style>

+ 96 - 26
src/components/pages/test/check/docxTemplateDialog.vue

@@ -3,13 +3,15 @@
     :visible.sync="show"
     :append-to-body="true"
     title="word导出"
-    width="1000px"
+    width="60%"
     top="10vh"
     :before-close="handleClose"
     class="dialog_diy"
   >
     <div class="box" v-loading="loading">
-      <div class="b_left"></div>
+      <div class="b_left">
+				<topicVue :cJson="checkJson" :checktype="2" :see="true" :isTeacher="1" title="" brief="" ref="topicVue"/>
+			</div>
       <div class="b_right">
         <div class="d_box">
           <div class="d_b_step">
@@ -30,13 +32,26 @@
             <p>
               在文件中指定位置输入下方的"字段变量",用于显示真实数据的准确位置
             </p>
+						
+						<h3>文本:</h3>
             <img
               src="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"
             />
+
+						<h3>选择题:</h3>
+						<div class="d_b_s_imgList">
+							<img src="https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/41728546186962.png">
+							<img src="https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/51728546189479.png">
+						</div>
+						<div class="foldMenu">
+							<span v-if="foldField" @click="foldField = false">折叠字段变量</span>
+							<span v-if="!foldField" @click="foldField = true">显示字段变量</span>
+						</div>
             <div
               v-for="(item, index) in fieldList"
               :key="index"
               class="d_b_s_fieldListItem"
+							v-if="foldField"
             >
               <span
                 >{{ item.name }}:{{
@@ -124,7 +139,7 @@ import PizZip from "pizzip";
 import Docxtemplater from "docxtemplater";
 import ImageModule from "docxtemplater-image-module-free";
 import { saveAs } from 'file-saver';
-
+import topicVue from "../../testStudent/view/component/topic.vue";
 const getFile = url => {
   return new Promise((resolve, reject) => {
     var credentials = {
@@ -166,30 +181,27 @@ const getFile = url => {
 
 export default {
   props: {},
+	components:{
+		topicVue
+	},
   data() {
     return {
       show: false,
       loading: false,
       fieldList: [
-        { name: "第一题", field: "ti_01", type: "text", value: "第一题ti_01" },
-        { name: "第二题", field: "ti_02", type: "text", value: "第二题ti_02" },
-        { name: "第三题", field: "ti_03", type: "text", value: "第三题ti_03" },
-        { name: "第四题", field: "ti_04", type: "text", value: "第四题ti_04" },
-        { name: "第五题", field: "ti_05", type: "text", value: "第五题ti_05" },
-        {
-          name: "图片1",
-          field: "image_01",
-          type: "image",
-          value:
-            "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"
-        }
+        // { name: "第五题", field: "ti_05", type: "text", value: "第五题ti_05" },
+        // {
+        //   name: "图片1",
+        //   field: "image_01",
+        //   type: "image",
+        //   value:
+        //     "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"
+        // }
       ],
       uploadTemplateDocxData: null, //上传的模板文档
-      downFileData: {
-        fileName: "大学生重补免缓考申请表.docx",
-        url:
-          "https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/default%2F%E5%A4%A7%E5%AD%A6%E7%94%9F%E9%87%8D%E8%A1%A5%E5%85%8D%E7%BC%93%E8%80%83%E7%94%B3%E8%AF%B7%E8%A1%A81728378389891.docx"
-      } // 下载模板文档的url
+      downFileData: null, // 下载模板文档的url
+			checkJson:[],
+			foldField:false,
     };
   },
   methods: {
@@ -197,15 +209,46 @@ export default {
       this.close();
       done();
     },
-    open() {
+    open(data) {
+			this.init();
+			let _fileData = data.fileData;
+			this.downFileData = _fileData;
+			this.checkJson = data.formData.array
+			this.fieldList = this.getFieldData(data.formData.array)
       this.show = true;
     },
     close() {
       this.show = false;
+			this.init();
     },
-    init() {
-      // 初始化
+    init() { // 初始化
+			this.downFileData = null;
+			this.fieldList = [];
+			this.uploadTemplateDocxData = null;
+			this.foldField = false;
     },
+
+		getFieldData(array){
+			let _list = [];
+			let _index = 0;
+			for(let i=0;i<array.length;i++){
+				let _item = array[i];
+				if(_item.type == 3){
+					let _item2 = _item.json;
+					_list.push({name: _item2.title, field: `ti_${_index}`, type: "text", value: _item2.answer2})
+					_index++;
+				}else if(_item.type==1){
+					let _item2 = _item.json;
+					let choseTxt = ``
+					_item2.array.forEach((i,index2)=>{
+						choseTxt += `${(_item2.answer2===index2 || _item2.answer2.includes(index2)?'☑':'□')}${i.option}    `
+					})
+					_list.push({name:_item2.title,field: `ti_${_index}`, type: "text", value: choseTxt})
+					_index++;
+				}
+			}
+			return _list;
+		},
     downloadTemplateDocx() {
       getFile(this.downFileData.url).then(data => {
         if (data.data != 1) {
@@ -450,12 +493,13 @@ export default {
 }
 
 .b_left {
-  width: 400px;
-  height: 100%;
+	flex: 1;
+	height: 100%;
 }
 
 .b_right {
-  flex: 1;
+	min-width: 700px;
+	max-width: 700px;
   height: 100%;
 }
 
@@ -478,6 +522,10 @@ export default {
   margin-bottom: 10px;
 }
 
+.d_b_step>h3{
+	margin-top: 20px;
+}
+
 .d_b_step > p {
   font-size: 16px;
 }
@@ -554,4 +602,26 @@ export default {
   cursor: pointer;
   color: #e60012;
 }
+
+.d_b_s_imgList{
+	margin-top: 10px;
+}
+
+.d_b_s_imgList>img{
+	width: 100%;
+}
+
+.foldMenu{
+	width: 100%;
+	display: flex;
+	justify-content: flex-end;
+	margin: 10px 0;
+	
+}
+
+.foldMenu>span{
+	cursor: pointer;
+	color: #409EFF;
+	font-size: 16px;
+}
 </style>

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

@@ -628,12 +628,12 @@
                   </div>
                 </template>
               </el-table-column>
-              <el-table-column label="操作" width="300px" fixed="right" v-if="isN!=1">
+              <el-table-column label="操作" width="370px" fixed="right" v-if="isN!=1">
 
                 <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)" type="primary" size="small">word导出</el-button> -->
+									<el-button @click="setWordTemplate(scope.row)" v-if="testJson.cover" type="primary" size="small">word导出</el-button>
                   <el-button @click="deleteTest(scope.row.id)" type="primary" size="small">删除</el-button>
                 </template>
               </el-table-column>
@@ -2334,7 +2334,7 @@ export default {
         });
     },
 		setWordTemplate(item){
-			this.$refs.docxTemplateDialogRef.open()//这里可以传数据
+			this.$refs.docxTemplateDialogRef.open({fileData:JSON.parse(this.testJson.cover),formData:item})//这里可以传数据
 			// console.log(item)
 		}
   },