Ver Fonte

feat(router): 新增setWorkPage路由和组件用于作业设置

新增setWorkPage路由配置和setIndex.vue组件,用于选择题和问答题的设置。修改pptEasy/addCourse3.vue中的作业链接跳转到setWorkPage页面。添加setQuestionsAndAnswers.vue组件用于问答题设置,支持图片上传和删除功能。更新uploadFile.js工具类支持文件上传和类型判断。
SanHQin há 3 semanas atrás
pai
commit
fd95676142
28 ficheiros alterados com 1728 adições e 72 exclusões
  1. 1 1
      dist/index.html
  2. 0 0
      dist/static/css/app.d34b7851d38f94f9b81ff70b9a4bd97c.css
  3. 0 0
      dist/static/css/app.d34b7851d38f94f9b81ff70b9a4bd97c.css.map
  4. 0 0
      dist/static/css/workPage.74d5f7c7c31f83686c8fc319ef748bbd.css.map
  5. 0 0
      dist/static/css/workPage.8adaee5b2aba93aebc02fcf222739b3e.css
  6. 0 0
      dist/static/css/workPage.8adaee5b2aba93aebc02fcf222739b3e.css.map
  7. 0 0
      dist/static/js/app.c5401c044f695d3cdb30.js
  8. 0 0
      dist/static/js/app.c5401c044f695d3cdb30.js.map
  9. 0 0
      dist/static/js/manifest.23ea04dc469b57e2b4f8.js.map
  10. 0 0
      dist/static/js/vendor.714ff2bfc93f2f096b79.js
  11. 0 0
      dist/static/js/vendor.714ff2bfc93f2f096b79.js.map
  12. 0 0
      dist/static/js/workPage-manifest.2ece51fa34be51c8610a.js.map
  13. 0 0
      dist/static/js/workPage-vendor.7b2c55096449c94cc8fd.js
  14. 0 0
      dist/static/js/workPage-vendor.7b2c55096449c94cc8fd.js.map
  15. 0 0
      dist/static/js/workPage-vendor.7e4b52d86fde7f24e41c.js
  16. 0 0
      dist/static/js/workPage-vendor.7e4b52d86fde7f24e41c.js.map
  17. 0 0
      dist/static/js/workPage.00d59a25625c9c8bdc40.js
  18. 0 0
      dist/static/js/workPage.00d59a25625c9c8bdc40.js.map
  19. 0 0
      dist/static/js/workPage.f7511a4e28d961c6ca3b.js
  20. 0 0
      dist/static/js/workPage.f7511a4e28d961c6ca3b.js.map
  21. 1 1
      dist/workPage.html
  22. 72 70
      src/components/pages/pptEasy/addCourse3.vue
  23. 543 0
      src/components/pages/workPage/components/setChoiceQuestion.vue
  24. 464 0
      src/components/pages/workPage/components/setQuestionsAndAnswers.vue
  25. 110 0
      src/components/pages/workPage/setIndex.vue
  26. 519 0
      src/components/tools/uploadFile.js
  27. 9 0
      src/router/index.js
  28. 9 0
      src/router/index2.js

+ 1 - 1
dist/index.html

@@ -37,7 +37,7 @@
       width: 100%;
       background: #e6eaf0;
       font-family: '黑体';
-    }</style><link href=./static/css/app.e566a66d465a0dd04ebd5eb0a8f3b7b1.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=./static/js/manifest.23ea04dc469b57e2b4f8.js></script><script type=text/javascript src=./static/js/vendor.dfc8a8e3392292c7b8e5.js></script><script type=text/javascript src=./static/js/app.7c8da9ce74b14efd6e7a.js></script></body></html><script>function stopSafari() {
+    }</style><link href=./static/css/app.d34b7851d38f94f9b81ff70b9a4bd97c.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=./static/js/manifest.23ea04dc469b57e2b4f8.js></script><script type=text/javascript src=./static/js/vendor.714ff2bfc93f2f096b79.js></script><script type=text/javascript src=./static/js/app.c5401c044f695d3cdb30.js></script></body></html><script>function stopSafari() {
     //阻止safari浏览器双击放大功能
     let lastTouchEnd = 0  //更新手指弹起的时间
     document.documentElement.addEventListener("touchstart", function (event) {

Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
dist/static/css/app.d34b7851d38f94f9b81ff70b9a4bd97c.css


Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
dist/static/css/app.d34b7851d38f94f9b81ff70b9a4bd97c.css.map


Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
dist/static/css/workPage.74d5f7c7c31f83686c8fc319ef748bbd.css.map


Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
dist/static/css/workPage.8adaee5b2aba93aebc02fcf222739b3e.css


Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
dist/static/css/workPage.8adaee5b2aba93aebc02fcf222739b3e.css.map


Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
dist/static/js/app.c5401c044f695d3cdb30.js


Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
dist/static/js/app.c5401c044f695d3cdb30.js.map


Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
dist/static/js/manifest.23ea04dc469b57e2b4f8.js.map


Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
dist/static/js/vendor.714ff2bfc93f2f096b79.js


Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
dist/static/js/vendor.714ff2bfc93f2f096b79.js.map


Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
dist/static/js/workPage-manifest.2ece51fa34be51c8610a.js.map


Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
dist/static/js/workPage-vendor.7b2c55096449c94cc8fd.js


Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
dist/static/js/workPage-vendor.7b2c55096449c94cc8fd.js.map


Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
dist/static/js/workPage-vendor.7e4b52d86fde7f24e41c.js


Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
dist/static/js/workPage-vendor.7e4b52d86fde7f24e41c.js.map


Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
dist/static/js/workPage.00d59a25625c9c8bdc40.js


Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
dist/static/js/workPage.00d59a25625c9c8bdc40.js.map


Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
dist/static/js/workPage.f7511a4e28d961c6ca3b.js


Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
dist/static/js/workPage.f7511a4e28d961c6ca3b.js.map


+ 1 - 1
dist/workPage.html

@@ -1,4 +1,4 @@
-<!DOCTYPE html><html><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>工作页面 - CocoFlow</title><link rel=icon href=../static/logo.ico><link href=./static/css/workPage.74d5f7c7c31f83686c8fc319ef748bbd.css rel=stylesheet></head><body><noscript><strong>We're sorry but this app doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script type=text/javascript src=./static/js/workPage-manifest.2ece51fa34be51c8610a.js></script><script type=text/javascript src=./static/js/workPage-vendor.7e4b52d86fde7f24e41c.js></script><script type=text/javascript src=./static/js/workPage.f7511a4e28d961c6ca3b.js></script></body></html><script>function stopSafari() {
+<!DOCTYPE html><html><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>工作页面 - CocoFlow</title><link rel=icon href=../static/logo.ico><link href=./static/css/workPage.8adaee5b2aba93aebc02fcf222739b3e.css rel=stylesheet></head><body><noscript><strong>We're sorry but this app doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script type=text/javascript src=./static/js/workPage-manifest.2ece51fa34be51c8610a.js></script><script type=text/javascript src=./static/js/workPage-vendor.7b2c55096449c94cc8fd.js></script><script type=text/javascript src=./static/js/workPage.00d59a25625c9c8bdc40.js></script></body></html><script>function stopSafari() {
     //阻止safari浏览器双击放大功能
     let lastTouchEnd = 0  //更新手指弹起的时间
     document.documentElement.addEventListener("touchstart", function (event) {

+ 72 - 70
src/components/pages/pptEasy/addCourse3.vue

@@ -2473,11 +2473,13 @@ export default {
             }
           ]
         };
-        this.dialogVisibleChoice = true;
+         this.addTest()
+        // this.dialogVisibleChoice = true;
         // this.$message.info("添加选择题");
       } else if (tool == 15) {
         this.answerQ = "";
-        this.dialogVisible8 = true;
+        this.addAnswer();
+        // this.dialogVisible8 = true;
       } else if (tool == 72) {
         this.$refs.appDialog.openG(
           { url: "" },
@@ -2643,72 +2645,72 @@ export default {
       this.setPPtToolList();
     },
     addTest() {
-      var aj = this.testJson.testJson;
-      var b = 1;
-      for (var i = 0; i < aj.length; i++) {
-        if (aj[i].teststitle === "" && aj[i].timuList.length == 0) {
-          var a = 1;
-          for (let index = 0; index < aj[i].testItem; index++) {
-            const element = aj[i].checkList[index]
-              ? aj[i].checkList[index]
-              : "";
-            if (element != "") {
-              b++;
-              this.$message.error(this.lang.ssFillTitle.replace(/\*/g, i + 1));
-              return;
-            } else {
-              a++;
-            }
-          }
-          if (b == 1) {
-            this.$message.error(this.lang.ssOneQues);
-            return;
-          }
-        } else if (aj[i].teststitle != "" || aj[i].timuList.length > 0) {
-          for (let index = 0; index < aj[i].testItem; index++) {
-            const element = aj[i].checkList[index]
-              ? aj[i].checkList[index]
-              : "";
-            var index = 0;
-            for (var z = 0; z < aj[i].checkList.length; z++) {
-              var checkC = aj[i].checkList[z] ? aj[i].checkList[z] : "";
-              if (checkC != "") {
-                index++;
-              } else {
-                this.$message.error(this.lang.ssOptEmpty.replace(/\*/g, i + 1));
-                return;
-              }
-
-              for (var z2 = z + 1; z2 < aj[i].checkList.length; z2++) {
-                let checkC2 = aj[i].checkList[z2] ? aj[i].checkList[z2] : "";
-                if (checkC == checkC2) {
-                  this.$message.error(
-                    this.lang.ssOptDup
-                      .replace(/\*/g, i + 1)
-                      .replace("&", this.optionTypeList[z])
-                      .replace("$", this.optionTypeList[z2])
-                  );
-                  return;
-                }
-              }
-            }
-            b++;
-            if (index < 2) {
-              this.$message.error(this.lang.ssEachQues);
-              return;
-            }
-            if (
-              (aj[i].type == "2" && !aj[i].answer.length) ||
-              (aj[i].type == "1" &&
-                ((typeof aj[i].answer == "object" && !aj[i].answer.length) ||
-                  (aj[i].answer !== 0 && !aj[i].answer)))
-            ) {
-              this.$message.error(this.lang.ssCorrectOpt.replace(/\*/g, i + 1));
-              return;
-            }
-          }
-        }
-      }
+      // var aj = this.testJson.testJson;
+      // var b = 1;
+      // for (var i = 0; i < aj.length; i++) {
+      //   if (aj[i].teststitle === "" && aj[i].timuList.length == 0) {
+      //     var a = 1;
+      //     for (let index = 0; index < aj[i].testItem; index++) {
+      //       const element = aj[i].checkList[index]
+      //         ? aj[i].checkList[index]
+      //         : "";
+      //       if (element != "") {
+      //         b++;
+      //         this.$message.error(this.lang.ssFillTitle.replace(/\*/g, i + 1));
+      //         return;
+      //       } else {
+      //         a++;
+      //       }
+      //     }
+      //     if (b == 1) {
+      //       this.$message.error(this.lang.ssOneQues);
+      //       return;
+      //     }
+      //   } else if (aj[i].teststitle != "" || aj[i].timuList.length > 0) {
+      //     for (let index = 0; index < aj[i].testItem; index++) {
+      //       const element = aj[i].checkList[index]
+      //         ? aj[i].checkList[index]
+      //         : "";
+      //       var index = 0;
+      //       for (var z = 0; z < aj[i].checkList.length; z++) {
+      //         var checkC = aj[i].checkList[z] ? aj[i].checkList[z] : "";
+      //         if (checkC != "") {
+      //           index++;
+      //         } else {
+      //           this.$message.error(this.lang.ssOptEmpty.replace(/\*/g, i + 1));
+      //           return;
+      //         }
+
+      //         for (var z2 = z + 1; z2 < aj[i].checkList.length; z2++) {
+      //           let checkC2 = aj[i].checkList[z2] ? aj[i].checkList[z2] : "";
+      //           if (checkC == checkC2) {
+      //             this.$message.error(
+      //               this.lang.ssOptDup
+      //                 .replace(/\*/g, i + 1)
+      //                 .replace("&", this.optionTypeList[z])
+      //                 .replace("$", this.optionTypeList[z2])
+      //             );
+      //             return;
+      //           }
+      //         }
+      //       }
+      //       b++;
+      //       if (index < 2) {
+      //         this.$message.error(this.lang.ssEachQues);
+      //         return;
+      //       }
+      //       if (
+      //         (aj[i].type == "2" && !aj[i].answer.length) ||
+      //         (aj[i].type == "1" &&
+      //           ((typeof aj[i].answer == "object" && !aj[i].answer.length) ||
+      //             (aj[i].answer !== 0 && !aj[i].answer)))
+      //       ) {
+      //         this.$message.error(this.lang.ssCorrectOpt.replace(/\*/g, i + 1));
+      //         return;
+      //       }
+      //     }
+      //   }
+      // }
       let testJson = JSON.parse(JSON.stringify(this.testJson));
       testJson.testJson = this.testJson.testJson.filter(el => {
         var elc = el.checkList.filter(element => {
@@ -2734,7 +2736,7 @@ export default {
 
       this.dialogVisibleChoice = false;
       this.getWorkPageId(_data.id, 45, testJson).then(res => {
-        let url = `https://beta.pbl.cocorobo.cn/pbl-teacher-table/dist/workPage.html#/workPageNew?id=${res}`
+        let url = `https://beta.pbl.cocorobo.cn/pbl-teacher-table/dist/workPage.html#/setWorkPage?id=${res}&type=${_data.tool}`
         this.pptCourseJson.toolsList.find(i => i.id === _data.id).url = url;
         this.setPPtToolList();
         _data.url = url
@@ -2990,7 +2992,7 @@ export default {
 
       this.dialogVisible8 = false;
       this.getWorkPageId(_data.id, 15, { answerQ: this.answerQ }).then(res => {
-        let url = `https://beta.pbl.cocorobo.cn/pbl-teacher-table/dist/workPage.html#/workPageNew?id=${res}`;
+        let url = `https://beta.pbl.cocorobo.cn/pbl-teacher-table/dist/workPage.html#/setWorkPage?id=${res}&type=${_data.tool}`;
         this.pptCourseJson.toolsList.find(i => i.id === _data.id).url = url;
         this.setPPtToolList();
         _data.url = url

+ 543 - 0
src/components/pages/workPage/components/setChoiceQuestion.vue

@@ -0,0 +1,543 @@
+<template>
+  <div class="setChoiceQuestion">
+    <div class="testItem" v-for="(item, index) in jsonData.testJson" :key="item.id">
+      <div class="ti_header">
+        <span>题目{{ index + 1 }}</span>
+        <div class="ti_h_edit">
+          <span @click="copyTest(item.id)">
+            <svg viewBox="0 0 1024 1024" version="1.1" p-id="4608" width="200" height="200">
+              <path
+                d="M731.68184 676.057473 731.68184 183.323259c0-30.233582-24.512277-54.745858-54.747905-54.745858L184.216093 128.577401c-30.233582 0-54.746882 24.512277-54.746882 54.745858l0 492.734214c0 30.207999 24.5133 54.746882 54.746882 54.746882l492.717841 0C707.16854 730.804355 731.68184 706.265472 731.68184 676.057473zM622.1891 676.057473 238.962975 676.057473c-30.233582 0-54.746882-24.538883-54.746882-54.745858L184.216093 238.07014c0-30.233582 24.5133-54.746882 54.746882-54.746882l383.226125 0c30.233582 0 54.744835 24.512277 54.744835 54.746882l0 383.242498C676.933935 651.51859 652.421658 676.057473 622.1891 676.057473zM841.17458 292.817022l-54.745858 0 0 54.746882c30.232558 0 54.745858 24.5133 54.745858 54.759161l0 383.228171c0 30.206976-24.5133 54.745858-54.745858 54.745858L403.201573 840.297095c-30.233582 0-54.746882-24.538883-54.746882-54.745858l-54.746882 0 0 54.745858c0 30.207999 24.5133 54.747905 54.746882 54.747905l492.719888 0c30.234605 0 54.747905-24.539906 54.747905-54.747905L895.922485 347.563904C895.922485 317.329299 871.408161 292.817022 841.17458 292.817022z"
+                p-id="4609"></path>
+            </svg>
+          </span>
+          <span @click="deleteTest(item.id)">
+            <svg viewBox="0 0 1024 1024" version="1.1" p-id="12415" width="200" height="200">
+              <path
+                d="M902.4 282.1H117.7c-13.4 0-23.5-10.1-23.5-23.5v-3.4c0-13.4 10.1-23.5 23.5-23.5h788.1c13.4 0 23.5 10.1 23.5 23.5v3.4c0 13.4-10.1 23.5-26.9 23.5zM634.1 151.3H386c-13.4 0-26.8-10.1-23.5-23.5v-6.7c0-13.4 10.1-23.5 23.5-23.5h248.2c13.4 0 23.5 10.1 23.5 23.5v3.4c3.3 13.3-10.1 26.8-23.6 26.8z m228.1 238.1c0-13.4-10.1-26.8-26.8-26.8-16.8 0-26.8 10.1-26.8 26.8L775 798.5v13.4c0 23.5-10.1 43.6-30.2 53.7-13.4 6.7-30.2 10.1-50.3 10.1H332.3c-33.5 3.4-60.4 0-70.4-33.5-3.4-6.7-6.7-16.8-6.7-26.8l-10.1-104-36.9-322c0-13.4-10.1-23.5-23.5-23.5s-26.8 10.1-26.8 23.5l47 462.8c0 40.2 40.2 73.8 80.5 73.8h459.5c40.2 0 80.5-33.5 80.5-73.8l36.8-462.8c0 3.3 0 0 0 0z m0 0"
+                p-id="12416"></path>
+            </svg>
+          </span>
+        </div>
+      </div>
+
+      <div class="ti_title">
+        <div class="ti_t_input" contenteditable="true" v-text="item.teststitle"
+          @blur="setTestTitle(item.id, $event.target.innerText)"></div>
+        <div class="uploadImage" @click="uploadImage(item.id)">
+          <svg viewBox="0 0 1024 1024" version="1.1" p-id="15953" width="200" height="200">
+            <path
+              d="M368 480c-62.4 0-112-49.6-112-112s49.6-112 112-112 112 49.6 112 112-49.6 112-112 112z m0-160c-27.2 0-48 20.8-48 48s20.8 48 48 48 48-20.8 48-48-20.8-48-48-48z m464 608H192c-52.8 0-96-43.2-96-96V192c0-52.8 43.2-96 96-96h640c52.8 0 96 43.2 96 96v640c0 52.8-43.2 96-96 96zM192 160c-17.6 0-32 14.4-32 32v640c0 17.6 14.4 32 32 32h640c17.6 0 32-14.4 32-32V192c0-17.6-14.4-32-32-32H192z m259.2 556.8c-25.6 0-51.2-11.2-70.4-30.4l-38.4-40c-12.8-12.8-33.6-12.8-46.4 0l-49.6 52.8c-12.8 12.8-32 12.8-44.8 1.6s-12.8-32-1.6-44.8l49.6-52.8c17.6-19.2 43.2-30.4 68.8-30.4s51.2 11.2 70.4 30.4l38.4 40c12.8 12.8 33.6 12.8 46.4 0l160-168c17.6-19.2 43.2-30.4 70.4-30.4s51.2 11.2 70.4 30.4L920 628.8c12.8 12.8 11.2 33.6-1.6 44.8-12.8 12.8-33.6 11.2-44.8-1.6L728 518.4c-12.8-12.8-33.6-12.8-46.4 0L521.6 688c-19.2 17.6-44.8 28.8-70.4 28.8z"
+              fill="#333333" p-id="15954"></path>
+          </svg>
+        </div>
+      </div>
+      <!-- 图片 -->
+      <div class="imageList">
+        <div v-for="(image, imageIndex) in item.timuList" :key="item.id+'_'+imageIndex">
+          <el-image style="width: 100px; height: 100px" :src="image.url" :preview-src-list="[image.url]"
+            fit="cover"></el-image>
+            <svg @click="delImage(item.id, imageIndex)" t="1774237005199" viewBox="0 0 1024 1024" width="200" height="200"><path d="M512 1024A512 512 0 1 1 512 0a512 512 0 0 1 0 1024zM305.956571 370.395429L447.488 512 305.956571 653.604571a45.568 45.568 0 1 0 64.438858 64.438858L512 576.512l141.604571 141.531429a45.568 45.568 0 0 0 64.438858-64.438858L576.512 512l141.531429-141.604571a45.568 45.568 0 1 0-64.438858-64.438858L512 447.488 370.395429 305.956571a45.568 45.568 0 0 0-64.438858 64.438858z" fill="#FF2525" p-id="4716"></path></svg>
+        </div>
+      </div>
+
+      <!-- 选择题 -->
+      <div class="checkList">
+        <div class="checkItem" v-for="(check, checkIndex) in item.checkList" :key="checkIndex">
+          <div class="check" :class="{ 'checked': item.answer.includes(checkIndex) }"
+            @click="checkClick(item.id, checkIndex)">
+            <svg v-if="item.answer.includes(checkIndex)" t="1773996159000" viewBox="0 0 1024 1024" version="1.1"
+              xmlns="http://www.w3.org/2000/svg" p-id="5894" width="200" height="200">
+              <path
+                d="M404.352 685.354667L789.632 213.333333 853.333333 267.52 409.941333 810.666667 170.666667 566.4l58.581333-59.818667z"
+                p-id="5895"></path>
+            </svg>
+          </div>
+          <el-input v-model="item.checkList[checkIndex]" placeholder="请输入选项" @blur="setTestJson()"></el-input>
+          <div class="btn">
+            <div @click="delCheck(item.id, checkIndex)">
+              <svg viewBox="0 0 1024 1024" version="1.1" p-id="12415" width="200" height="200">
+                <path
+                  d="M902.4 282.1H117.7c-13.4 0-23.5-10.1-23.5-23.5v-3.4c0-13.4 10.1-23.5 23.5-23.5h788.1c13.4 0 23.5 10.1 23.5 23.5v3.4c0 13.4-10.1 23.5-26.9 23.5zM634.1 151.3H386c-13.4 0-26.8-10.1-23.5-23.5v-6.7c0-13.4 10.1-23.5 23.5-23.5h248.2c13.4 0 23.5 10.1 23.5 23.5v3.4c3.3 13.3-10.1 26.8-23.6 26.8z m228.1 238.1c0-13.4-10.1-26.8-26.8-26.8-16.8 0-26.8 10.1-26.8 26.8L775 798.5v13.4c0 23.5-10.1 43.6-30.2 53.7-13.4 6.7-30.2 10.1-50.3 10.1H332.3c-33.5 3.4-60.4 0-70.4-33.5-3.4-6.7-6.7-16.8-6.7-26.8l-10.1-104-36.9-322c0-13.4-10.1-23.5-23.5-23.5s-26.8 10.1-26.8 23.5l47 462.8c0 40.2 40.2 73.8 80.5 73.8h459.5c40.2 0 80.5-33.5 80.5-73.8l36.8-462.8c0 3.3 0 0 0 0z m0 0"
+                  p-id="12416"></path>
+              </svg>
+            </div>
+          </div>
+        </div>
+        <div class="addCheck" @click="addCheck(item.id)">
+          <svg viewBox="0 0 1024 1024" version="1.1" p-id="2732" width="200" height="200">
+            <path
+              d="M925.696 384q19.456 0 37.376 7.68t30.72 20.48 20.48 30.72 7.68 37.376q0 20.48-7.68 37.888t-20.48 30.208-30.72 20.48-37.376 7.68l-287.744 0 0 287.744q0 20.48-7.68 37.888t-20.48 30.208-30.72 20.48-37.376 7.68q-20.48 0-37.888-7.68t-30.208-20.48-20.48-30.208-7.68-37.888l0-287.744-287.744 0q-20.48 0-37.888-7.68t-30.208-20.48-20.48-30.208-7.68-37.888q0-19.456 7.68-37.376t20.48-30.72 30.208-20.48 37.888-7.68l287.744 0 0-287.744q0-19.456 7.68-37.376t20.48-30.72 30.208-20.48 37.888-7.68q39.936 0 68.096 28.16t28.16 68.096l0 287.744 287.744 0z"
+              p-id="2733"></path>
+          </svg>
+          <span>选项</span>
+        </div>
+      </div>
+
+      <!-- 解释说明 -->
+      <div class="explanation">
+        <div class="e_header">
+          <span>解释说明</span>
+          <div v-show="false">
+            <svg t="1774233113566" viewBox="0 0 1027 1024" width="200" height="200">
+              <path
+                d="M511.979521 544.586217a54.525819 54.525819 0 0 1-23.359066-5.247791L31.038758 321.427143a54.397824 54.397824 0 0 1 0-98.236071L488.620455 5.279789c14.719411-7.039718 31.99872-7.039718 46.718131 0l457.581697 217.911283a54.397824 54.397824 0 0 1 0 98.236071l-457.581697 217.911283A54.525819 54.525819 0 0 1 511.979521 544.586217zM180.984761 272.341106L511.979521 429.966801l331.058757-157.625695L511.979521 114.587417 180.984761 272.341106z m354.417823 746.402144l457.517699-217.911283a54.397824 54.397824 0 1 0-46.718131-98.236071L511.979521 909.371625l-434.158634-206.775729a54.397824 54.397824 0 0 0-46.718131 98.236071l457.581697 217.911283a54.525819 54.525819 0 0 0 46.718131 0z m0-239.73441l457.517699-217.847286a54.397824 54.397824 0 1 0-46.718131-98.300068L511.979521 669.573217l-434.158634-206.711731a54.397824 54.397824 0 0 0-46.718131 98.300068l457.581697 217.847286a54.525819 54.525819 0 0 0 46.718131 0z"
+                p-id="9073"></path>
+            </svg>
+            <span>AI生成</span>
+          </div>
+        </div>
+        <el-input type="textarea" rows="3" resize="none" v-model="item.explanation" placeholder="请输入解释说明"
+          @blur="setTestJson()"></el-input>
+      </div>
+    </div>
+
+
+    <!-- 添加题目 -->
+    <div class="addTest" @click="addTest()">
+      <svg viewBox="0 0 1024 1024" version="1.1" p-id="2732" width="200" height="200">
+        <path
+          d="M925.696 384q19.456 0 37.376 7.68t30.72 20.48 20.48 30.72 7.68 37.376q0 20.48-7.68 37.888t-20.48 30.208-30.72 20.48-37.376 7.68l-287.744 0 0 287.744q0 20.48-7.68 37.888t-20.48 30.208-30.72 20.48-37.376 7.68q-20.48 0-37.888-7.68t-30.208-20.48-20.48-30.208-7.68-37.888l0-287.744-287.744 0q-20.48 0-37.888-7.68t-30.208-20.48-20.48-30.208-7.68-37.888q0-19.456 7.68-37.376t20.48-30.72 30.208-20.48 37.888-7.68l287.744 0 0-287.744q0-19.456 7.68-37.376t20.48-30.72 30.208-20.48 37.888-7.68q39.936 0 68.096 28.16t28.16 68.096l0 287.744 287.744 0z"
+          p-id="2733"></path>
+      </svg>
+      <span>题目</span>
+    </div>
+
+  </div>
+</template>
+
+<script>
+import { v4 as uuidv4 } from 'uuid';
+import { uploadOneFile } from '@/components/tools/uploadFile'
+export default {
+  emits: ['setTestJson', 'save'],
+  props: {
+    workData: {
+      type: Object,
+      default: () => { }
+    }
+  },
+  data() {
+    return {
+      jsonData: {}
+    }
+  },
+  watch: {
+    workData: {
+      handler(newVal, oldVal) {
+        if (newVal.type == 45) {
+          if (JSON.stringify(newVal.json) != JSON.stringify(this.jsonData)) {
+            this.jsonData = JSON.parse(JSON.stringify(newVal.json));
+          }
+        }
+      },
+      deep: true,
+      immediate: true
+    }
+  },
+  methods: {
+    // 更新题目
+    setTestJson() {
+      // console.log(this.jsonData)
+      this.jsonData.testCount = this.jsonData.testJson.length;
+      this.$emit('setTestJson', this.jsonData);
+    },
+    // 添加题目
+    addTest() {
+      this.jsonData.testJson.push({
+        id: uuidv4(),
+        type: "2",
+        teststitle: "",
+        checkList: [''],
+        timuList: [],
+        answer: [],
+        userAnswer: [],
+        explanation: '',
+      });
+      this.setTestJson();
+    },
+    //修改标题
+    setTestTitle(id, title) {
+      console.log('修改标题', id, title)
+      let test = this.jsonData.testJson.find(item => item.id == id);
+      if (test) {
+        test.teststitle = title;
+      }
+      this.setTestJson();
+    },
+    // 点击复选框
+    checkClick(id, index) {
+      let test = this.jsonData.testJson.find(item => item.id == id);
+      if (test) {
+        if (test.answer.includes(index)) {
+          test.answer.splice(test.answer.indexOf(index), 1);
+        } else {
+          test.answer.push(index);
+        }
+      }
+      this.setTestJson();
+    },
+    // 删除题目
+    deleteTest(id) {
+      let index = this.jsonData.testJson.findIndex(item => item.id == id);
+      this.jsonData.testJson.splice(index, 1);
+      this.setTestJson();
+    },
+    // 添加选项
+    addCheck(id) {
+      let index = this.jsonData.testJson.findIndex(item => item.id == id);
+      let test = this.jsonData.testJson[index];
+      test.checkList.push('');
+      this.setTestJson();
+    },
+    // 删除选项
+    delCheck(id, index) {
+      let test = this.jsonData.testJson.find(item => item.id == id);
+      if (test) {
+        if (test.checkList.length == 1) {
+          this.$message.error("至少保留一个选项");
+          return;
+        }
+        test.checkList.splice(index, 1);
+      }
+      this.setTestJson();
+    },
+    // 上传图片
+    uploadImage(id) {
+      const input = document.createElement('input');
+      input.type = 'file';
+      input.accept = 'image/*';
+      input.click();
+      input.onchange = (e) => {
+        if (e.target.files[0]) {
+          uploadOneFile(e.target.files[0]).then(res => {
+            this.jsonData.testJson.find(item => item.id == id).timuList = [res];
+            this.setTestJson();
+          })
+        }
+      }
+    },
+    // 复制题目
+    copyTest(id) {
+      let test = this.jsonData.testJson.find(item => item.id == id);
+      if (test) {
+        test = JSON.parse(JSON.stringify(test));
+        test.id = uuidv4();
+        this.jsonData.testJson.push(test);
+        this.setTestJson();
+      }
+    },
+    // 删除图片
+    delImage(id, index) {
+      let test = this.jsonData.testJson.find(item => item.id == id);
+      if (test) {
+        test.timuList.splice(index, 1);
+      }
+      this.setTestJson();
+    },
+  },
+}
+</script>
+
+<style scoped>
+.setChoiceQuestion {
+  width: 100%;
+  height: auto;
+  background: #fff;
+  display: flex;
+  flex-direction: column;
+  overflow: auto;
+  padding: 4rem;
+  box-sizing: border-box;
+  gap: 2rem;
+}
+
+.addTest {
+  border-radius: 5px;
+  border: 1px dashed #d1d5db;
+  padding: .5rem 1rem;
+  height: fit-content;
+  width: fit-content;
+  display: flex;
+  align-items: center;
+  gap: .5rem;
+  cursor: pointer;
+}
+
+.addTest>svg {
+  width: .7rem;
+  height: .7rem;
+  fill: #6E7583;
+}
+
+.addTest>span {
+  font-weight: bold;
+  font-size: .9rem;
+  color: #6b7280;
+}
+
+.testItem {
+  width: 100%;
+  height: auto;
+  display: flex;
+  align-items: center;
+  gap: 1rem;
+  flex-direction: column;
+}
+
+.ti_header {
+  width: 100%;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+
+}
+
+.ti_header>span {
+  font-size: 1rem;
+  font-weight: 600;
+  color: #ff9300;
+}
+
+.ti_h_edit {
+  display: flex;
+  align-items: center;
+  gap: 1rem;
+}
+
+.ti_h_edit>span {
+  width: 1.5rem;
+  height: 1.5rem;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  background: #F9FAFB;
+  border-radius: 4px;
+  cursor: pointer;
+}
+
+.ti_h_edit>span>svg {
+  width: 1rem;
+  height: 1rem;
+  fill: #6B7280;
+}
+
+.ti_title {
+  width: 100%;
+  height: fit-content;
+  padding-bottom: 2rem;
+  min-height: 4rem;
+  background: #FAFBFC;
+  border-radius: 8px;
+  border: 1px solid #E5E7EB;
+  position: relative;
+}
+
+.ti_t_input {
+  width: 100%;
+  height: 100%;
+  padding: 1rem;
+  box-sizing: border-box;
+  border: none;
+  outline: none;
+  background: none;
+  font-size: .8rem;
+  resize: none;
+  /* padding-right: 2rem; */
+}
+
+.uploadImage {
+  position: absolute;
+  bottom: 0.5rem;
+  right: 0.5rem;
+  background: #fff;
+  border-radius: .5rem;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  border: 1px solid #E5E7EB;
+  cursor: pointer;
+  padding: .5rem;
+}
+
+.uploadImage>svg {
+  width: 1rem;
+  height: 1rem;
+}
+
+.checkList {
+  width: 100%;
+  height: auto;
+  display: flex;
+  flex-direction: column;
+  gap: 1rem;
+  padding-left: 4rem;
+}
+
+.checkItem {
+  width: 100%;
+  height: auto;
+  display: flex;
+  align-items: center;
+  justify-content: flex-start;
+  gap: .5rem;
+
+}
+
+.check {
+  width: 1.1rem;
+  height: 1.1rem;
+  border: solid 1px #D1D5DB;
+  border-radius: .25rem;
+  cursor: pointer;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+
+.checked {
+  background: #FF9300;
+}
+
+.checked>svg {
+  width: .7rem;
+  height: .7rem;
+  fill: #fff;
+}
+
+.checkItem>.el-input {
+  width: calc(100% - 10rem);
+}
+
+.addCheck {
+  border-radius: 5px;
+  border: 1px dashed #d1d5db;
+  padding: .3rem .8rem;
+  height: fit-content;
+  width: fit-content;
+  display: flex;
+  align-items: center;
+  gap: .5rem;
+  cursor: pointer;
+  margin-left: 2.2rem;
+}
+
+.addCheck>svg {
+  width: .5rem;
+  height: .5rem;
+  fill: #6E7583;
+}
+
+.addCheck>span {
+  font-weight: bold;
+  font-size: .8rem;
+  color: #6b7280;
+}
+
+.btn {
+  display: flex;
+  align-items: center;
+  gap: .25em;
+}
+
+.btn>div {
+  width: 1.5rem;
+  height: 1.5rem;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  background: #F9FAFB;
+  border-radius: .4px;
+  cursor: pointer;
+}
+
+.btn>div>svg {
+  width: 1rem;
+  height: 1rem;
+  fill: #6B7280;
+}
+
+.explanation {
+  width: 100%;
+  height: auto;
+  padding: 1rem;
+  background: #FAFBFC;
+  border-radius: 5px;
+  display: flex;
+  flex-direction: column;
+  gap: 1rem;
+  border-radius: .8rem;
+}
+
+.e_header {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+}
+
+.e_header>span {
+  color: #6b7280;
+  font-size: .8rem;
+  font-weight: 500;
+}
+
+.e_header>div {
+  display: flex;
+  align-items: center;
+  gap: .5rem;
+  background: #ff9300;
+  color: #fff;
+  padding: .3rem .8rem;
+  font-size: .8rem;
+  font-weight: 500;
+  border-radius: .5rem;
+  cursor: pointer;
+}
+
+.e_header>div>svg {
+  width: .8rem;
+  height: .8rem;
+  fill: #fff;
+}
+
+.imageList {
+  width: 100%;
+  height: auto;
+  display: flex;
+  flex-wrap: wrap;
+  gap: 1rem;
+}
+.imageList>div{
+  width: 100px;
+  height: 100px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  /* overflow: hidden; */
+  border-radius: .5rem;
+  position: relative;
+
+}
+
+.imageList>div:hover>svg{
+  display: flex;
+}
+
+.imageList>div>svg{
+  width: 1rem;
+  height: 1rem;
+  position: absolute;
+  top: -.3rem;
+  right: -.3rem;
+  font-weight: 500;
+  border-radius: .5rem;
+  cursor: pointer;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  display: none;
+}
+
+
+
+</style>

+ 464 - 0
src/components/pages/workPage/components/setQuestionsAndAnswers.vue

@@ -0,0 +1,464 @@
+<template>
+  <div class="setChoiceQuestion">
+    <div class="testItem">
+      <div class="ti_header">
+        <span>题目{{ 1 }}</span>
+      </div>
+
+      <div class="ti_title">
+        <div class="ti_t_input" contenteditable="true" v-text="jsonData.answerQ"
+          @blur="setTestTitle($event.target.innerText)"></div>
+        <div class="uploadImage" @click="uploadImage()">
+          <svg viewBox="0 0 1024 1024" version="1.1" p-id="15953" width="200" height="200">
+            <path
+              d="M368 480c-62.4 0-112-49.6-112-112s49.6-112 112-112 112 49.6 112 112-49.6 112-112 112z m0-160c-27.2 0-48 20.8-48 48s20.8 48 48 48 48-20.8 48-48-20.8-48-48-48z m464 608H192c-52.8 0-96-43.2-96-96V192c0-52.8 43.2-96 96-96h640c52.8 0 96 43.2 96 96v640c0 52.8-43.2 96-96 96zM192 160c-17.6 0-32 14.4-32 32v640c0 17.6 14.4 32 32 32h640c17.6 0 32-14.4 32-32V192c0-17.6-14.4-32-32-32H192z m259.2 556.8c-25.6 0-51.2-11.2-70.4-30.4l-38.4-40c-12.8-12.8-33.6-12.8-46.4 0l-49.6 52.8c-12.8 12.8-32 12.8-44.8 1.6s-12.8-32-1.6-44.8l49.6-52.8c17.6-19.2 43.2-30.4 68.8-30.4s51.2 11.2 70.4 30.4l38.4 40c12.8 12.8 33.6 12.8 46.4 0l160-168c17.6-19.2 43.2-30.4 70.4-30.4s51.2 11.2 70.4 30.4L920 628.8c12.8 12.8 11.2 33.6-1.6 44.8-12.8 12.8-33.6 11.2-44.8-1.6L728 518.4c-12.8-12.8-33.6-12.8-46.4 0L521.6 688c-19.2 17.6-44.8 28.8-70.4 28.8z"
+              fill="#333333" p-id="15954"></path>
+          </svg>
+        </div>
+      </div>
+      <!-- 图片 -->
+      <div class="imageList">
+        <div v-for="(image, imageIndex) in jsonData.imageList" :key="imageIndex">
+          <el-image style="width: 100px; height: 100px" :src="image.url" :preview-src-list="[image.url]"
+            fit="cover"></el-image>
+            <svg @click="delImage(imageIndex)" t="1774237005199" viewBox="0 0 1024 1024" width="200" height="200"><path d="M512 1024A512 512 0 1 1 512 0a512 512 0 0 1 0 1024zM305.956571 370.395429L447.488 512 305.956571 653.604571a45.568 45.568 0 1 0 64.438858 64.438858L512 576.512l141.604571 141.531429a45.568 45.568 0 0 0 64.438858-64.438858L576.512 512l141.531429-141.604571a45.568 45.568 0 1 0-64.438858-64.438858L512 447.488 370.395429 305.956571a45.568 45.568 0 0 0-64.438858 64.438858z" fill="#FF2525" p-id="4716"></path></svg>
+        </div>
+      </div>
+
+      <!-- 选择题 -->
+      <!-- <div class="checkList">
+        <div class="checkItem" v-for="(check, checkIndex) in item.checkList" :key="checkIndex">
+          <div class="check" :class="{ 'checked': item.answer.includes(checkIndex) }"
+            @click="checkClick(item.id, checkIndex)">
+            <svg v-if="item.answer.includes(checkIndex)" t="1773996159000" viewBox="0 0 1024 1024" version="1.1"
+              xmlns="http://www.w3.org/2000/svg" p-id="5894" width="200" height="200">
+              <path
+                d="M404.352 685.354667L789.632 213.333333 853.333333 267.52 409.941333 810.666667 170.666667 566.4l58.581333-59.818667z"
+                p-id="5895"></path>
+            </svg>
+          </div>
+          <el-input v-model="item.checkList[checkIndex]" placeholder="请输入选项" @blur="setTestJson()"></el-input>
+          <div class="btn">
+            <div @click="delCheck(item.id, checkIndex)">
+              <svg viewBox="0 0 1024 1024" version="1.1" p-id="12415" width="200" height="200">
+                <path
+                  d="M902.4 282.1H117.7c-13.4 0-23.5-10.1-23.5-23.5v-3.4c0-13.4 10.1-23.5 23.5-23.5h788.1c13.4 0 23.5 10.1 23.5 23.5v3.4c0 13.4-10.1 23.5-26.9 23.5zM634.1 151.3H386c-13.4 0-26.8-10.1-23.5-23.5v-6.7c0-13.4 10.1-23.5 23.5-23.5h248.2c13.4 0 23.5 10.1 23.5 23.5v3.4c3.3 13.3-10.1 26.8-23.6 26.8z m228.1 238.1c0-13.4-10.1-26.8-26.8-26.8-16.8 0-26.8 10.1-26.8 26.8L775 798.5v13.4c0 23.5-10.1 43.6-30.2 53.7-13.4 6.7-30.2 10.1-50.3 10.1H332.3c-33.5 3.4-60.4 0-70.4-33.5-3.4-6.7-6.7-16.8-6.7-26.8l-10.1-104-36.9-322c0-13.4-10.1-23.5-23.5-23.5s-26.8 10.1-26.8 23.5l47 462.8c0 40.2 40.2 73.8 80.5 73.8h459.5c40.2 0 80.5-33.5 80.5-73.8l36.8-462.8c0 3.3 0 0 0 0z m0 0"
+                  p-id="12416"></path>
+              </svg>
+            </div>
+          </div>
+        </div>
+        <div class="addCheck" @click="addCheck(item.id)">
+          <svg viewBox="0 0 1024 1024" version="1.1" p-id="2732" width="200" height="200">
+            <path
+              d="M925.696 384q19.456 0 37.376 7.68t30.72 20.48 20.48 30.72 7.68 37.376q0 20.48-7.68 37.888t-20.48 30.208-30.72 20.48-37.376 7.68l-287.744 0 0 287.744q0 20.48-7.68 37.888t-20.48 30.208-30.72 20.48-37.376 7.68q-20.48 0-37.888-7.68t-30.208-20.48-20.48-30.208-7.68-37.888l0-287.744-287.744 0q-20.48 0-37.888-7.68t-30.208-20.48-20.48-30.208-7.68-37.888q0-19.456 7.68-37.376t20.48-30.72 30.208-20.48 37.888-7.68l287.744 0 0-287.744q0-19.456 7.68-37.376t20.48-30.72 30.208-20.48 37.888-7.68q39.936 0 68.096 28.16t28.16 68.096l0 287.744 287.744 0z"
+              p-id="2733"></path>
+          </svg>
+          <span>选项</span>
+        </div>
+      </div> -->
+
+      <!-- 解释说明 -->
+      <div class="explanation">
+        <div class="e_header">
+          <span>评价标准</span>
+          <!-- <div v-show="false">
+            <svg t="1774233113566" viewBox="0 0 1027 1024" width="200" height="200">
+              <path
+                d="M511.979521 544.586217a54.525819 54.525819 0 0 1-23.359066-5.247791L31.038758 321.427143a54.397824 54.397824 0 0 1 0-98.236071L488.620455 5.279789c14.719411-7.039718 31.99872-7.039718 46.718131 0l457.581697 217.911283a54.397824 54.397824 0 0 1 0 98.236071l-457.581697 217.911283A54.525819 54.525819 0 0 1 511.979521 544.586217zM180.984761 272.341106L511.979521 429.966801l331.058757-157.625695L511.979521 114.587417 180.984761 272.341106z m354.417823 746.402144l457.517699-217.911283a54.397824 54.397824 0 1 0-46.718131-98.236071L511.979521 909.371625l-434.158634-206.775729a54.397824 54.397824 0 0 0-46.718131 98.236071l457.581697 217.911283a54.525819 54.525819 0 0 0 46.718131 0z m0-239.73441l457.517699-217.847286a54.397824 54.397824 0 1 0-46.718131-98.300068L511.979521 669.573217l-434.158634-206.711731a54.397824 54.397824 0 0 0-46.718131 98.300068l457.581697 217.847286a54.525819 54.525819 0 0 0 46.718131 0z"
+                p-id="9073"></path>
+            </svg>
+            <span>AI生成</span>
+          </div> -->
+        </div>
+        <el-input type="textarea" rows="3" resize="none" v-model="jsonData.evaluationCriteria" placeholder="请输入评价标准"
+          @blur="setTestJson()"></el-input>
+      </div>
+    </div>
+
+  </div>
+</template>
+
+<script>
+import { uploadOneFile } from '@/components/tools/uploadFile'
+export default {
+  emits: ['setTestJson', 'save'],
+  props: {
+    workData: {
+      type: Object,
+      default: () => { }
+    }
+  },
+  data() {
+    return {
+      jsonData: {}
+    }
+  },
+  watch: {
+    workData: {
+      handler(newVal, oldVal) {
+        if (newVal.type == 15) {
+          if (JSON.stringify(newVal.json) != JSON.stringify(this.jsonData)) {
+            let _data = JSON.parse(JSON.stringify(newVal.json))
+
+            if(!_data.imageList){
+              _data.imageList = [];
+            }
+            if(!_data.evaluationCriteria){
+              _data.evaluationCriteria = '';
+            }
+
+            this.jsonData = _data;
+          }
+        }
+      },
+      deep: true,
+      immediate: true
+    }
+  },
+  methods: {
+    // 更新题目
+    setTestJson() {
+      // console.log(this.jsonData)
+      // this.jsonData.testCount = this.jsonData.testJson.length;
+      this.$emit('setTestJson', this.jsonData);
+    },
+    //修改标题
+    setTestTitle( title) {
+      console.log('修改标题', title)
+      this.jsonData.answerQ = title;
+      // let test = this.jsonData..find(item => item.id == id);
+      // if (test) {
+      //   test.teststitle = title;
+      // }
+      this.setTestJson();
+    },
+    // 上传图片
+    uploadImage(id) {
+      const input = document.createElement('input');
+      input.type = 'file';
+      input.accept = 'image/*';
+      input.click();
+      input.onchange = (e) => {
+        if (e.target.files[0]) {
+          uploadOneFile(e.target.files[0]).then(res => {
+            this.jsonData.imageList = [res];
+            // this.jsonData.testJson.find(item => item.id == id).timuList = [res];
+            this.setTestJson();
+          })
+        }
+      }
+    },
+    // 删除图片
+    delImage(index) {
+      this.jsonData.imageList.splice(index, 1);
+      // let test = this.jsonData.testJson.find(item => item.id == id);
+      // if (test) {
+      //   test.timuList.splice(index, 1);
+      // }
+      this.setTestJson();
+    },
+  },
+}
+</script>
+
+<style scoped>
+.setChoiceQuestion {
+  width: 100%;
+  height: auto;
+  background: #fff;
+  display: flex;
+  flex-direction: column;
+  overflow: auto;
+  padding: 4rem;
+  box-sizing: border-box;
+  gap: 2rem;
+}
+
+.addTest {
+  border-radius: 5px;
+  border: 1px dashed #d1d5db;
+  padding: .5rem 1rem;
+  height: fit-content;
+  width: fit-content;
+  display: flex;
+  align-items: center;
+  gap: .5rem;
+  cursor: pointer;
+}
+
+.addTest>svg {
+  width: .7rem;
+  height: .7rem;
+  fill: #6E7583;
+}
+
+.addTest>span {
+  font-weight: bold;
+  font-size: .9rem;
+  color: #6b7280;
+}
+
+.testItem {
+  width: 100%;
+  height: auto;
+  display: flex;
+  align-items: center;
+  gap: 1rem;
+  flex-direction: column;
+}
+
+.ti_header {
+  width: 100%;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+
+}
+
+.ti_header>span {
+  font-size: 1rem;
+  font-weight: 600;
+  color: #ff9300;
+}
+
+.ti_h_edit {
+  display: flex;
+  align-items: center;
+  gap: 1rem;
+}
+
+.ti_h_edit>span {
+  width: 1.5rem;
+  height: 1.5rem;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  background: #F9FAFB;
+  border-radius: 4px;
+  cursor: pointer;
+}
+
+.ti_h_edit>span>svg {
+  width: 1rem;
+  height: 1rem;
+  fill: #6B7280;
+}
+
+.ti_title {
+  width: 100%;
+  height: fit-content;
+  padding-bottom: 2rem;
+  min-height: 4rem;
+  background: #FAFBFC;
+  border-radius: 8px;
+  border: 1px solid #E5E7EB;
+  position: relative;
+}
+
+.ti_t_input {
+  width: 100%;
+  height: 100%;
+  padding: 1rem;
+  box-sizing: border-box;
+  border: none;
+  outline: none;
+  background: none;
+  font-size: .8rem;
+  resize: none;
+  /* padding-right: 2rem; */
+}
+
+.uploadImage {
+  position: absolute;
+  bottom: 0.5rem;
+  right: 0.5rem;
+  background: #fff;
+  border-radius: .5rem;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  border: 1px solid #E5E7EB;
+  cursor: pointer;
+  padding: .5rem;
+}
+
+.uploadImage>svg {
+  width: 1rem;
+  height: 1rem;
+}
+
+.checkList {
+  width: 100%;
+  height: auto;
+  display: flex;
+  flex-direction: column;
+  gap: 1rem;
+  padding-left: 4rem;
+}
+
+.checkItem {
+  width: 100%;
+  height: auto;
+  display: flex;
+  align-items: center;
+  justify-content: flex-start;
+  gap: .5rem;
+
+}
+
+.check {
+  width: 1.1rem;
+  height: 1.1rem;
+  border: solid 1px #D1D5DB;
+  border-radius: .25rem;
+  cursor: pointer;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+
+.checked {
+  background: #FF9300;
+}
+
+.checked>svg {
+  width: .7rem;
+  height: .7rem;
+  fill: #fff;
+}
+
+.checkItem>.el-input {
+  width: calc(100% - 10rem);
+}
+
+.addCheck {
+  border-radius: 5px;
+  border: 1px dashed #d1d5db;
+  padding: .3rem .8rem;
+  height: fit-content;
+  width: fit-content;
+  display: flex;
+  align-items: center;
+  gap: .5rem;
+  cursor: pointer;
+  margin-left: 2.2rem;
+}
+
+.addCheck>svg {
+  width: .5rem;
+  height: .5rem;
+  fill: #6E7583;
+}
+
+.addCheck>span {
+  font-weight: bold;
+  font-size: .8rem;
+  color: #6b7280;
+}
+
+.btn {
+  display: flex;
+  align-items: center;
+  gap: .25em;
+}
+
+.btn>div {
+  width: 1.5rem;
+  height: 1.5rem;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  background: #F9FAFB;
+  border-radius: .4px;
+  cursor: pointer;
+}
+
+.btn>div>svg {
+  width: 1rem;
+  height: 1rem;
+  fill: #6B7280;
+}
+
+.explanation {
+  width: 100%;
+  height: auto;
+  padding: 1rem;
+  background: #FAFBFC;
+  border-radius: 5px;
+  display: flex;
+  flex-direction: column;
+  gap: 1rem;
+  border-radius: .8rem;
+}
+
+.e_header {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+}
+
+.e_header>span {
+  color: #6b7280;
+  font-size: .8rem;
+  font-weight: 500;
+}
+
+.e_header>div {
+  display: flex;
+  align-items: center;
+  gap: .5rem;
+  background: #ff9300;
+  color: #fff;
+  padding: .3rem .8rem;
+  font-size: .8rem;
+  font-weight: 500;
+  border-radius: .5rem;
+  cursor: pointer;
+}
+
+.e_header>div>svg {
+  width: .8rem;
+  height: .8rem;
+  fill: #fff;
+}
+
+.imageList {
+  width: 100%;
+  height: auto;
+  display: flex;
+  flex-wrap: wrap;
+  gap: 1rem;
+}
+.imageList>div{
+  width: 100px;
+  height: 100px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  /* overflow: hidden; */
+  border-radius: .5rem;
+  position: relative;
+
+}
+
+.imageList>div:hover>svg{
+  display: flex;
+}
+
+.imageList>div>svg{
+  width: 1rem;
+  height: 1rem;
+  position: absolute;
+  top: -.3rem;
+  right: -.3rem;
+  font-weight: 500;
+  border-radius: .5rem;
+  cursor: pointer;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  display: none;
+}
+
+</style>

+ 110 - 0
src/components/pages/workPage/setIndex.vue

@@ -0,0 +1,110 @@
+<template>
+  <div class="setWorkPage">
+    <!-- 选择题设置 -->
+    <setChoiceQuestion :workData="workData" v-if="workData.type == 45" @setTestJson="setTestJson" @save="saveTest"/>
+    <setQuestionsAndAnswers :workData="workData" v-if="workData.type == 15" @setTestJson="setTestJson" @save="saveTest"/>
+  </div>
+</template>
+
+<script>
+import setChoiceQuestion from './components/setChoiceQuestion.vue'
+import setQuestionsAndAnswers from './components/setQuestionsAndAnswers.vue'
+export default {
+  components: {
+    setChoiceQuestion,
+    setQuestionsAndAnswers
+  },
+  data() {
+    return {
+      id: this.$route.query.id,
+      courseid: this.$route.query.courseid,
+      userid: this.$route.query.userid,
+      oid: this.$route.query.oid,
+      org: this.$route.query.org,
+      role: this.$route.query.role,
+      stage: this.$route.query.stage,
+      task: this.$route.query.task,
+      tool: this.$route.query.tool,
+      type: "",
+      cid: this.$route.query.cid,
+      workData: {},
+      loading: false
+    }
+  },
+  methods: {
+    getWorkData() {
+      if (!this.id) return console.log("无作业id");
+      let params = {
+        id: this.id
+      };
+      this.loading = true;
+      this.ajax
+        .get(this.$store.state.api + "select_workPageById", params)
+        .then(res => {
+          let _data = res.data[0];
+          if (_data.length) {
+            _data = _data[0];
+            _data.json = JSON.parse(_data.json);
+            if (_data.type == 15) {
+              _data.json.answer = "";
+              _data.json.fileList = [];
+            } else if (_data.type == 45) {
+              _data.json.testJson.forEach(item => {
+                if (item.type == "2") {
+                  item.userAnswer = [];
+                } else if (item.type == "1") {
+                  item.userAnswer = "";
+                }
+              });
+            }
+            this.type = _data.type;
+
+            this.workData = _data;
+
+          }
+          this.loading = false
+        }).catch((err) => {
+          console.log(err);
+          this.loading = false;
+        });
+    },
+    // 设置选择题
+    setTestJson(newVal){
+      this.workData.json = JSON.parse(JSON.stringify(newVal));
+      this.saveTest();
+    },
+    // 保存
+    saveTest(){
+      const params = [{
+        uid: this.userid || '',
+        id: this.workData.id,
+        json: JSON.stringify(this.workData.json),
+      }]
+
+      this.ajax.post(this.$store.state.api + "updata_workPage_json", params).then(res => {
+        if (res.data == 200) {
+          console.log("保存成功")
+          // this.$message.success("保存成功");
+        }
+      }).catch((err) => {
+        console.log("保存失败",err);
+        // this.$message.error("保存失败");
+      })
+    }
+  },
+  mounted() {
+    this.getWorkData();
+  }
+}
+</script>
+
+<style scoped>
+.setWorkPage {
+  width: 100%;
+  height: 100%;
+  /* height: auto; */
+  background: #fff;
+  box-sizing: border-box;
+  overflow-x: hidden;
+}
+</style>

+ 519 - 0
src/components/tools/uploadFile.js

@@ -0,0 +1,519 @@
+import '../../common/aws-sdk-2.235.1.min.js'
+import { v4 as uuidv4 } from 'uuid'
+
+
+
+// 上传单个文件
+const uploadOneFile = (file, progressFn) => {
+  return new Promise((resolve) => {
+    let credentials = {
+      accessKeyId: 'AKIATLPEDU37QV5CHLMH',
+      secretAccessKey: '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',
+    } //秘钥形式的登录上传
+    window.AWS.config.update(credentials)
+    window.AWS.config.region = 'cn-northwest-1' //设置区域
+
+    let bucket = new window.AWS.S3({ params: { Bucket: 'ccrb' } }) //选择桶
+    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) {
+          //这里可以写进度条
+          if (progressFn) {
+            let _progress = {
+              loaded:evt.loaded,
+              total:evt.total,
+              percent:(evt.loaded/evt.total*100).toFixed(2),
+            }
+            progressFn(_progress)
+          }
+        })
+        .send(function (err, data) {
+          if (err) {
+            resolve('')
+          } else {
+            let fileObj = {
+              name: file.name,
+              url: data.Location,
+              size: formatFileSize(file.size), // 格式化文件大小
+              uid: uuidv4(),
+              type: file.type,
+              fileType:getFileType(file),
+            }
+            console.log('uploadFile', fileObj)
+            resolve(fileObj)
+          }
+        })
+    }
+  })
+}
+
+// 获取文件数据
+const getFile = (url) => {
+  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"; //设置区域
+    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
+
+    });
+  });
+};
+
+const getTxtFileContent = (url) => {
+  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"; //设置区域
+    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 {
+        const fileContent = data.Body.toString("utf-8");
+        resolve({ data: fileContent });
+      }
+    });
+  });
+}
+
+const formatFileSize = (size) => {
+  if (size < 1024) {
+    return size + 'B'
+  } else if (size < 1024 * 1024) {
+    return (size / 1024).toFixed(2) + 'KB'
+  } else if (size < 1024 * 1024 * 1024) {
+    return (size / (1024 * 1024)).toFixed(2) + 'MB'
+  } else if (size < 1024 * 1024 * 1024 * 1024) {
+    return (size / (1024 * 1024 * 1024)).toFixed(2) + 'GB'
+  } else {
+    return (size / (1024 * 1024 * 1024 * 1024)).toFixed(2) + 'TB'
+  }
+}
+
+// 常用文件类型清单
+const fileTypes = [
+  { value: 'image', label: '图片', exts: ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg'], mime: ['image/jpeg', 'image/png', 'image/gif', 'image/bmp', 'image/webp', 'image/svg+xml'] },
+  { value: 'video', label: '视频', exts: ['mp4', 'avi', 'mov', 'wmv', 'flv', 'mkv', 'webm'], mime: ['video/mp4', 'video/x-msvideo', 'video/quicktime', 'video/x-ms-wmv', 'video/x-flv', 'video/x-matroska', 'video/webm'] },
+  { value: 'audio', label: '音频', exts: ['mp3', 'wav', 'aac', 'ogg', 'flac', 'm4a'], mime: ['audio/mpeg', 'audio/x-wav', 'audio/aac', 'audio/ogg', 'audio/flac', 'audio/mp4'] },
+  { value: 'doc', label: '文档', exts: ['doc', 'docx', 'pdf', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'md', 'csv'], mime: ['application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/pdf', 'application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.ms-powerpoint', 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'text/plain', 'text/markdown', 'text/csv'] },
+  { value: 'zip', label: '压缩包', exts: ['zip', 'rar', '7z', 'tar', 'gz'], mime: ['application/zip', 'application/x-rar-compressed', 'application/x-7z-compressed', 'application/x-tar', 'application/gzip'] },
+  { value: 'other', label: '其它', exts: [], mime: [] }
+]
+
+// 根据传入的文件类型(文件名/后缀或mime)获取value
+const getFileType = (file) => {
+  if (!file) return 'other';
+  let ext = '';
+  let mime = '';
+
+  // 允许传入 string 或 File/Blob 对象
+  if (typeof file === 'string') {
+    // 从文件名里提取后缀
+    const match = file.match(/\.([^.]+)$/);
+    ext = match ? match[1].toLowerCase() : '';
+  } else if (typeof file === 'object' && file) {
+    // File 或 Blob 情况,取type为mime,name取后缀
+    if (file.type) mime = file.type;
+    if (file.name) {
+      const match = file.name.match(/\.([^.]+)$/);
+      ext = match ? match[1].toLowerCase() : '';
+    }
+  }
+
+  // 先按mime类型查找
+  if (mime) {
+    for (let type of fileTypes) {
+      if (type.mime.includes(mime)) {
+        return type.value;
+      }
+    }
+  }
+  // 再按扩展名查找
+  if (ext) {
+    for (let type of fileTypes) {
+      if (type.exts.includes(ext)) {
+        return type.value;
+      }
+    }
+  }
+  // 未命中则返回other
+  return 'other';
+}
+
+// 分片上传
+/**
+ * AWS S3 分片上传工具,支持进度回调及停止上传功能
+ * 使用方式:
+ *   const uploader = new AwsMultipartUploader(options);
+ *   uploader.upload({ file, keyName, folderName, onProgress, onSuccess, onError });
+ *   uploader.stop(); // 随时可停止
+ */
+class AwsMultipartUploader {
+  constructor({
+    bucketname = "ccrb",
+    accessKeyId = "AKIATLPEDU37QV5CHLMH",
+    secretAccessKey = "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",
+    region = "cn-northwest-1",
+    partsize = 10 * 1024 * 1024 // 10MB
+  } = {}) {
+    this.bucketname = bucketname;
+    this.accessKeyId = accessKeyId;
+    this.secretAccessKey = secretAccessKey;
+    this.region = region;
+    this.partsize = partsize;
+    this.bucket = null;
+    this.flag = true;
+    this.uploadid = "";
+    this.lastFilestate = null; // 缓存上次的filestate, 避免重复回调
+  }
+
+  async init() {
+    const credentials = {
+      accessKeyId: this.accessKeyId,
+      secretAccessKey: this.secretAccessKey,
+      region: this.region
+    };
+    window.AWS.config.update(credentials);
+    this.bucket = new window.AWS.S3({ params: { Bucket: this.bucketname } });
+  }
+
+  async initMultipartUpload(key, file) {
+    const params = {
+      Bucket: this.bucketname,
+      Key: key,
+      ContentType: file.type,
+      ACL: "public-read"
+    };
+    const data = await this.bucket.createMultipartUpload(params).promise();
+    return data.UploadId;
+  }
+
+  async uploadPart(file, keyname, uploadid, pn, start, end) {
+    if (!this.flag) return;
+    const params = {
+      Bucket: this.bucketname,
+      Key: keyname,
+      PartNumber: pn,
+      UploadId: uploadid,
+      Body: file.slice(start, end)
+    };
+    const result = await this.bucket.uploadPart(params).promise();
+    return { ETag: result.ETag, PartNumber: pn };
+  }
+
+  async completeMultipartUpload(parts, keyname, uploadid) {
+    if (!this.flag) return;
+    const params = {
+      Bucket: this.bucketname,
+      Key: keyname,
+      MultipartUpload: { Parts: parts },
+      UploadId: uploadid
+    };
+    return await this.bucket.completeMultipartUpload(params).promise();
+  }
+
+  async abortMultipartUpload(key, uploadid) {
+    const params = {
+      Bucket: this.bucketname,
+      Key: key,
+      UploadId: uploadid
+    };
+    await this.bucket.abortMultipartUpload(params).promise();
+  }
+
+  async getCheckpoint(key) {
+    let partsinfo;
+    let uploadid = "";
+    try {
+      const result = await this.bucket
+        .listMultipartUploads({ Bucket: this.bucketname, Prefix: key })
+        .promise();
+      if (result.Uploads && result.Uploads.length) {
+        uploadid = result.Uploads[result.Uploads.length - 1].UploadId;
+        partsinfo = await this.bucket
+          .listParts({
+            Bucket: this.bucketname,
+            Key: key,
+            UploadId: uploadid
+          })
+          .promise();
+      }
+    } catch (err) {
+      console.log(err);
+    }
+    return { uploadid, partsinfo };
+  }
+
+  // 控制停止
+  stop() {
+    this.flag = false;
+  }
+
+  emitProgress(filestate, onProgress) {
+    // 只回调变化
+    if (typeof onProgress === "function") {
+      if (
+        !this.lastFilestate ||
+        this.lastFilestate.percent !== filestate.percent ||
+        this.lastFilestate.status !== filestate.status
+      ) {
+        onProgress(Object.assign({}, filestate));
+      }
+    }
+    this.lastFilestate = Object.assign({}, filestate);
+  }
+
+  // 分段上传
+  async uploadParts({ file, uploadid, parts = [], key, onProgress }) {
+    let filestate = { status: "processing", percent: 0 };
+    let partarr = [];
+    const completeparts = parts.map((_) => {
+      partarr.push(_.PartNumber);
+      return { PartNumber: _.PartNumber, ETag: _.ETag };
+    });
+    let len = Math.ceil(file.size / this.partsize);
+
+    if (partarr.length) {
+      filestate.percent = parseInt((completeparts.length * 100) / len);
+      this.emitProgress(filestate, onProgress);
+    }
+
+    for (let i = 0; i < len; i++) {
+      if (!this.flag) break;
+      let start = i * this.partsize;
+      let end = (i + 1) * this.partsize;
+      if (!partarr.includes(i + 1)) {
+        const uploadpart = await this.uploadPart(
+          file,
+          key,
+          uploadid,
+          i + 1,
+          start,
+          end
+        );
+        if (uploadpart && uploadpart.ETag != null) {
+          completeparts.push(uploadpart);
+          partarr.push(uploadpart.PartNumber);
+          filestate.percent = parseInt((completeparts.length * 100) / len);
+          filestate.status = "processing";
+          this.emitProgress(filestate, onProgress);
+        } else {
+          filestate.status = "fail";
+          this.emitProgress(filestate, onProgress);
+          this.stop();
+          throw new Error("分片上传失败");
+        }
+      }
+    }
+    if (this.flag) {
+      const data = await this.completeMultipartUpload(
+        completeparts,
+        key,
+        uploadid
+      );
+      filestate.status = "success";
+      filestate.percent = 100;
+      this.emitProgress(filestate, onProgress);
+      return data; // 返回complete后的aws数据
+    } else {
+      filestate.status = "stop";
+      this.emitProgress(filestate, onProgress);
+      throw new Error("上传已中断");
+    }
+  }
+
+  // 主入口(异步,支持await)
+  /**
+   *
+   * @param {*} param0
+   *  file: 要上传的File对象
+   *  keyName: 指定上传key(可选)
+   *  folderName: 文件夹(可选)
+   *  onProgress: function({status, percent})
+   */
+  async upload({
+    file,
+    keyName,
+    folderName,
+    onProgress
+  }) {
+    if (!file) {
+      throw new Error("请上传文件");
+    }
+    this.flag = true;
+    this.lastFilestate = null;
+    await this.init();
+    let key = "";
+    if (keyName) {
+      key = keyName;
+    } else if (folderName) {
+      key = `${folderName}/${file.name}`;
+    } else {
+      const ext = file.name.split(".").length > 1 ?
+        file.name.substring(file.name.lastIndexOf(".") + 1) : "";
+      key =
+        `${file.name.split(".")[0]}${Date.now()}${ext ? "." + ext : ""}`;
+    }
+    let filestate = { percent: 0, status: "start" };
+    this.emitProgress(filestate, onProgress);
+
+    const params = {
+      Bucket: this.bucketname,
+      Key: key
+    };
+
+    // 用Promise包装, 使upload支持await
+    return new Promise(async (resolve, reject) => {
+      try {
+        // 检查是否已上传
+        this.bucket.headObject(params, async (err, data) => {
+          if (err) {
+            // 检查断点
+            let { uploadid, partsinfo } = await this.getCheckpoint(key);
+            let curUploadId = uploadid;
+            let awsParts = [];
+            if (uploadid && partsinfo) {
+              awsParts = partsinfo.Parts || [];
+            }
+
+            try {
+              let completeResult;
+              if (curUploadId) {
+                completeResult = await this.uploadParts({
+                  file,
+                  uploadid: curUploadId,
+                  parts: awsParts,
+                  key,
+                  onProgress
+                });
+              } else {
+                const newUploadId = await this.initMultipartUpload(key, file);
+                completeResult = await this.uploadParts({
+                  file,
+                  uploadid: newUploadId,
+                  parts: [],
+                  key,
+                  onProgress
+                });
+              }
+              let url = `https://${this.bucketname}.s3.${this.region}.amazonaws.com.cn/${key}`;
+              const resObj = {
+                name: file.name,
+                url: url,
+                size: formatFileSize(file.size),
+                uid: uuidv4(),
+                type: file.type,
+                Key: key,
+                Location: url,
+                ETag: completeResult.ETag,
+                Bucket: this.bucketname
+              };
+              console.log(resObj)
+              resolve(resObj);
+            } catch (err) {
+
+              console.log('分片上传失败', err)
+              reject('');
+            }
+          } else if (data) {
+            // 已经100%
+            let url = `https://${this.bucketname}.s3.${this.region}.amazonaws.com.cn/${key}`;
+            const resObj = {
+              name: file.name,
+              url: url,
+              size: formatFileSize(file.size),
+              uid: uuidv4(),
+              type: file.type,
+              Key: key,
+              Location: url,
+              ETag: data.ETag,
+              Bucket: this.bucketname
+            };
+            filestate.percent = 100;
+            filestate.status = "success";
+            this.emitProgress(filestate, onProgress);
+            resolve(resObj);
+          }
+        });
+      } catch (err) {
+        console.log('分片上传失败', err)
+        reject('');
+      }
+    });
+  }
+}
+
+export {
+  uploadOneFile,
+  getFileType,
+  getFile,
+  getTxtFileContent,
+  AwsMultipartUploader,
+  formatFileSize
+}

+ 9 - 0
src/router/index.js

@@ -163,6 +163,7 @@ import Listudent from '@/components/pages/liyuan/page/student'
 import safeTest from '@/components/pages/liyuan/page/safeTest'
 import workPage from '@/components/pages/workPage/index'
 import workPageNew from '@/components/pages/workPage/index_new'
+import setWorkPage from '@/components/pages/workPage/setIndex.vue'
 import pptEasy from '@/components/pages/pptEasy/addCourse'
 import pptEasy2 from '@/components/pages/pptEasy/addCourse2'
 import pptEasy3 from '@/components/pages/pptEasy/addCourse3'
@@ -1494,6 +1495,14 @@ export default new Router({
       requireAuth:''//不需要鉴权
     }
   },
+    {
+      path:"/setWorkPage",
+      name:'setWorkPage',
+      component:setWorkPage,
+      meta:{
+        requireAuth: '',
+      }
+    }
 
 
   ]

+ 9 - 0
src/router/index2.js

@@ -7,6 +7,7 @@ import ElementUI from 'element-ui'
 // 使用路由懒加载,按需加载组件
 import workPage from '@/components/pages/workPage/index'
 import workPageNew from '@/components/pages/workPage/index_new'
+import setWorkPage from '@/components/pages/workPage/setIndex.vue'
 import locale from 'element-ui/lib/locale/lang/en'
 import cn from "../lang/cn.json";
 import hk from "../lang/hk.json";
@@ -58,6 +59,14 @@ export default new Router({
     meta: {
       requireAuth: '' // 是否需要判断是否登录,这里是需要判断
     }
+  },
+  {
+    path:"/setWorkPage",
+    name:'setWorkPage',
+    component:setWorkPage,
+    meta:{
+      requireAuth: '',
+    }
   }
   ]
 })

Alguns ficheiros não foram mostrados porque muitos ficheiros mudaram neste diff