Переглянути джерело

Merge branch 'beta' into HK

lsc 10 місяців тому
батько
коміт
4248758a9e
31 змінених файлів з 2205 додано та 349 видалено
  1. 4 0
      dist/index.html
  2. 0 0
      dist/static/css/app.3faebb4ab7bb2a1bb7307791b753954b.css
  3. 1 0
      dist/static/css/app.3faebb4ab7bb2a1bb7307791b753954b.css.map
  4. 0 0
      dist/static/css/app.4c895eb5731aa5633687bca5593cc585.css.map
  5. 106 0
      dist/static/img/ropt.c731819.svg
  6. 1 0
      dist/static/js/app.bfff3a361abb57a4b3c9.js
  7. 0 0
      dist/static/js/app.bfff3a361abb57a4b3c9.js.map
  8. 1 0
      dist/static/js/app.e6dab380549fd9937e78.js
  9. 1 0
      dist/static/js/app.e6dab380549fd9937e78.js.map
  10. 0 0
      dist/static/js/manifest.0ad6c5648a38a6d1fa8f.js.map
  11. 0 0
      dist/static/js/vendor.77a666acfa8fe74a3d07.js
  12. 0 0
      dist/static/js/vendor.77a666acfa8fe74a3d07.js.map
  13. 137 0
      package-lock.json
  14. 3 0
      package.json
  15. BIN
      src/assets/icon/classroomObservation/voiceCard.png
  16. 106 0
      src/assets/icon/exportPdfworks/ropt.svg
  17. 187 96
      src/components/pages/aiAddCourse/addCourse.vue
  18. 8 0
      src/components/pages/classroomObservation/components/addNewAnalysisDialog.vue
  19. 1 1
      src/components/pages/classroomObservation/components/analysis.vue
  20. 3 3
      src/components/pages/classroomObservation/components/analysis2.vue
  21. 1 1
      src/components/pages/classroomObservation/components/analysisItem.vue
  22. 2 2
      src/components/pages/classroomObservation/components/analysisItem2.vue
  23. 102 1
      src/components/pages/classroomObservation/components/analysisSpecialItem.vue
  24. 1 1
      src/components/pages/classroomObservation/components/analysisTemplateDialog.vue
  25. 3 0
      src/components/pages/classroomObservation/components/chatArea.vue
  26. 29 0
      src/components/pages/classroomObservation/components/messageArea.vue
  27. 161 36
      src/components/pages/classroomObservation/components/startPage.vue
  28. 775 205
      src/components/pages/components/exportDataDialog.vue
  29. 557 0
      src/components/pages/test/check/docxTemplateDialog.vue
  30. 12 1
      src/components/pages/test/check/index.vue
  31. 3 2
      src/components/pages/works.vue

+ 4 - 0
dist/index.html

@@ -32,7 +32,11 @@
       width: 100%;
       background: #e6eaf0;
       font-family: '黑体';
+<<<<<<< HEAD
     }</style><link href=./static/css/app.4c895eb5731aa5633687bca5593cc585.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=./static/js/manifest.0ad6c5648a38a6d1fa8f.js></script><script type=text/javascript src=./static/js/vendor.8db9a3f753f5644e3c5e.js></script><script type=text/javascript src=./static/js/app.bfff3a361abb57a4b3c9.js></script></body></html><script>function stopSafari() {
+=======
+    }</style><link href=./static/css/app.3faebb4ab7bb2a1bb7307791b753954b.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=./static/js/manifest.571c38d63f24b1ae9e16.js></script><script type=text/javascript src=./static/js/vendor.77a666acfa8fe74a3d07.js></script><script type=text/javascript src=./static/js/app.e6dab380549fd9937e78.js></script></body></html><script>function stopSafari() {
+>>>>>>> beta
     //阻止safari浏览器双击放大功能
     let lastTouchEnd = 0  //更新手指弹起的时间
     document.documentElement.addEventListener("touchstart", function (event) {

Різницю між файлами не показано, бо вона завелика
+ 0 - 0
dist/static/css/app.3faebb4ab7bb2a1bb7307791b753954b.css


Різницю між файлами не показано, бо вона завелика
+ 1 - 0
dist/static/css/app.3faebb4ab7bb2a1bb7307791b753954b.css.map


Різницю між файлами не показано, бо вона завелика
+ 0 - 0
dist/static/css/app.4c895eb5731aa5633687bca5593cc585.css.map


Різницю між файлами не показано, бо вона завелика
+ 106 - 0
dist/static/img/ropt.c731819.svg


Різницю між файлами не показано, бо вона завелика
+ 1 - 0
dist/static/js/app.bfff3a361abb57a4b3c9.js


Різницю між файлами не показано, бо вона завелика
+ 0 - 0
dist/static/js/app.bfff3a361abb57a4b3c9.js.map


Різницю між файлами не показано, бо вона завелика
+ 1 - 0
dist/static/js/app.e6dab380549fd9937e78.js


Різницю між файлами не показано, бо вона завелика
+ 1 - 0
dist/static/js/app.e6dab380549fd9937e78.js.map


Різницю між файлами не показано, бо вона завелика
+ 0 - 0
dist/static/js/manifest.0ad6c5648a38a6d1fa8f.js.map


Різницю між файлами не показано, бо вона завелика
+ 0 - 0
dist/static/js/vendor.77a666acfa8fe74a3d07.js


Різницю між файлами не показано, бо вона завелика
+ 0 - 0
dist/static/js/vendor.77a666acfa8fe74a3d07.js.map


+ 137 - 0
package-lock.json

@@ -13,6 +13,8 @@
         "clipboard": "^2.0.10",
         "cocoroboworkpc": "file:",
         "dayjs": "^1.11.7",
+        "docxtemplater": "^3.50.0",
+        "docxtemplater-image-module-free": "^1.1.1",
         "echarts": "^5.4.2",
         "echarts-wordcloud": "^2.1.0",
         "element-china-area-data": "^5.0.2",
@@ -39,6 +41,7 @@
         "opencc-js": "^1.0.5",
         "papaparse": "^5.4.1",
         "pdfjs-dist": "^2.5.207",
+        "pizzip": "^3.1.7",
         "pptxgenjs": "^3.12.0",
         "qrcodejs2": "^0.0.2",
         "qs": "^6.10.1",
@@ -520,6 +523,14 @@
         "@xtuc/long": "4.2.2"
       }
     },
+    "node_modules/@xmldom/xmldom": {
+      "version": "0.8.10",
+      "resolved": "https://registry.npmmirror.com/@xmldom/xmldom/-/xmldom-0.8.10.tgz",
+      "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==",
+      "engines": {
+        "node": ">=10.0.0"
+      }
+    },
     "node_modules/@xtuc/ieee754": {
       "version": "1.2.0",
       "resolved": "https://registry.npmmirror.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
@@ -5256,6 +5267,25 @@
         "buffer-indexof": "^1.0.0"
       }
     },
+    "node_modules/docxtemplater": {
+      "version": "3.50.0",
+      "resolved": "https://registry.npmmirror.com/docxtemplater/-/docxtemplater-3.50.0.tgz",
+      "integrity": "sha512-6EqYbBFUcdNKVwS6G8vQ+pFOURJ7zoSvUNASIi4MPnCpkRdYDvmaOV2e1XcScMrEQV5pFZUAAbKi30Z+JTbLFA==",
+      "dependencies": {
+        "@xmldom/xmldom": "^0.8.10"
+      },
+      "engines": {
+        "node": ">=0.10"
+      }
+    },
+    "node_modules/docxtemplater-image-module-free": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmmirror.com/docxtemplater-image-module-free/-/docxtemplater-image-module-free-1.1.1.tgz",
+      "integrity": "sha512-aWOzVQN7ggDYjfoy3pTTNrcrZ7/CJrQcI9cT+hmyHE6nRLR67nt5yPFPe9hm9VWbfYIED2fi+3itOnF0TE/RWQ==",
+      "dependencies": {
+        "xmldom": "^0.1.27"
+      }
+    },
     "node_modules/dom-converter": {
       "version": "0.2.0",
       "resolved": "https://registry.npmmirror.com/dom-converter/download/dom-converter-0.2.0.tgz",
@@ -11396,6 +11426,19 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/pizzip": {
+      "version": "3.1.7",
+      "resolved": "https://registry.npmmirror.com/pizzip/-/pizzip-3.1.7.tgz",
+      "integrity": "sha512-VemVeAQtdIA74AN1Fsd5OmbMbEeS4YOwwlcudgzvmUrOIOPrk1idYC5Tw5FUFq/I0c26ziNOw9z//iPmGfp1jA==",
+      "dependencies": {
+        "pako": "^2.1.0"
+      }
+    },
+    "node_modules/pizzip/node_modules/pako": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/pako/-/pako-2.1.0.tgz",
+      "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug=="
+    },
     "node_modules/pkcs7": {
       "version": "0.2.3",
       "resolved": "https://registry.npmmirror.com/pkcs7/download/pkcs7-0.2.3.tgz",
@@ -19126,6 +19169,15 @@
         "node": ">=0.8"
       }
     },
+    "node_modules/xmldom": {
+      "version": "0.1.31",
+      "resolved": "https://registry.npmmirror.com/xmldom/-/xmldom-0.1.31.tgz",
+      "integrity": "sha512-yS2uJflVQs6n+CyjHoaBmVSqIDevTAWrzMmjG1Gc7h1qQ7uVozNhEPJAwZXWyGQ/Gafo3fCwrcaokezLPupVyQ==",
+      "deprecated": "Deprecated due to CVE-2021-21366 resolved in 0.5.0",
+      "engines": {
+        "node": ">=0.1"
+      }
+    },
     "node_modules/xmlhttprequest": {
       "version": "1.8.0",
       "resolved": "https://registry.npmmirror.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz",
@@ -19635,6 +19687,11 @@
         "@xtuc/long": "4.2.2"
       }
     },
+    "@xmldom/xmldom": {
+      "version": "0.8.10",
+      "resolved": "https://registry.npmmirror.com/@xmldom/xmldom/-/xmldom-0.8.10.tgz",
+      "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw=="
+    },
     "@xtuc/ieee754": {
       "version": "1.2.0",
       "resolved": "https://registry.npmmirror.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
@@ -21779,6 +21836,8 @@
         "copy-webpack-plugin": "^4.0.1",
         "css-loader": "^0.28.0",
         "dayjs": "^1.11.7",
+        "docxtemplater": "*",
+        "docxtemplater-image-module-free": "*",
         "echarts": "^5.4.2",
         "echarts-wordcloud": "^2.1.0",
         "element-china-area-data": "^5.0.2",
@@ -21813,6 +21872,7 @@
         "ora": "^1.2.0",
         "papaparse": "^5.4.1",
         "pdfjs-dist": "^2.5.207",
+        "pizzip": "*",
         "portfinder": "^1.0.13",
         "postcss-import": "^11.0.0",
         "postcss-loader": "^2.0.8",
@@ -22234,6 +22294,11 @@
             "@xtuc/long": "4.2.2"
           }
         },
+        "@xmldom/xmldom": {
+          "version": "0.8.10",
+          "resolved": "https://registry.npmmirror.com/@xmldom/xmldom/-/xmldom-0.8.10.tgz",
+          "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw=="
+        },
         "@xtuc/ieee754": {
           "version": "1.2.0",
           "resolved": "https://registry.npmmirror.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
@@ -26276,6 +26341,22 @@
             "buffer-indexof": "^1.0.0"
           }
         },
+        "docxtemplater": {
+          "version": "3.50.0",
+          "resolved": "https://registry.npmmirror.com/docxtemplater/-/docxtemplater-3.50.0.tgz",
+          "integrity": "sha512-6EqYbBFUcdNKVwS6G8vQ+pFOURJ7zoSvUNASIi4MPnCpkRdYDvmaOV2e1XcScMrEQV5pFZUAAbKi30Z+JTbLFA==",
+          "requires": {
+            "@xmldom/xmldom": "^0.8.10"
+          }
+        },
+        "docxtemplater-image-module-free": {
+          "version": "1.1.1",
+          "resolved": "https://registry.npmmirror.com/docxtemplater-image-module-free/-/docxtemplater-image-module-free-1.1.1.tgz",
+          "integrity": "sha512-aWOzVQN7ggDYjfoy3pTTNrcrZ7/CJrQcI9cT+hmyHE6nRLR67nt5yPFPe9hm9VWbfYIED2fi+3itOnF0TE/RWQ==",
+          "requires": {
+            "xmldom": "^0.1.27"
+          }
+        },
         "dom-converter": {
           "version": "0.2.0",
           "resolved": "https://registry.npmmirror.com/dom-converter/download/dom-converter-0.2.0.tgz",
@@ -31199,6 +31280,21 @@
             "pinkie": "^2.0.0"
           }
         },
+        "pizzip": {
+          "version": "3.1.7",
+          "resolved": "https://registry.npmmirror.com/pizzip/-/pizzip-3.1.7.tgz",
+          "integrity": "sha512-VemVeAQtdIA74AN1Fsd5OmbMbEeS4YOwwlcudgzvmUrOIOPrk1idYC5Tw5FUFq/I0c26ziNOw9z//iPmGfp1jA==",
+          "requires": {
+            "pako": "^2.1.0"
+          },
+          "dependencies": {
+            "pako": {
+              "version": "2.1.0",
+              "resolved": "https://registry.npmmirror.com/pako/-/pako-2.1.0.tgz",
+              "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug=="
+            }
+          }
+        },
         "pkcs7": {
           "version": "0.2.3",
           "resolved": "https://registry.npmmirror.com/pkcs7/download/pkcs7-0.2.3.tgz",
@@ -37489,6 +37585,11 @@
             "word": "~0.3.0"
           }
         },
+        "xmldom": {
+          "version": "0.1.31",
+          "resolved": "https://registry.npmmirror.com/xmldom/-/xmldom-0.1.31.tgz",
+          "integrity": "sha512-yS2uJflVQs6n+CyjHoaBmVSqIDevTAWrzMmjG1Gc7h1qQ7uVozNhEPJAwZXWyGQ/Gafo3fCwrcaokezLPupVyQ=="
+        },
         "xmlhttprequest": {
           "version": "1.8.0",
           "resolved": "https://registry.npmmirror.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz",
@@ -39524,6 +39625,22 @@
         "buffer-indexof": "^1.0.0"
       }
     },
+    "docxtemplater": {
+      "version": "3.50.0",
+      "resolved": "https://registry.npmmirror.com/docxtemplater/-/docxtemplater-3.50.0.tgz",
+      "integrity": "sha512-6EqYbBFUcdNKVwS6G8vQ+pFOURJ7zoSvUNASIi4MPnCpkRdYDvmaOV2e1XcScMrEQV5pFZUAAbKi30Z+JTbLFA==",
+      "requires": {
+        "@xmldom/xmldom": "^0.8.10"
+      }
+    },
+    "docxtemplater-image-module-free": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmmirror.com/docxtemplater-image-module-free/-/docxtemplater-image-module-free-1.1.1.tgz",
+      "integrity": "sha512-aWOzVQN7ggDYjfoy3pTTNrcrZ7/CJrQcI9cT+hmyHE6nRLR67nt5yPFPe9hm9VWbfYIED2fi+3itOnF0TE/RWQ==",
+      "requires": {
+        "xmldom": "^0.1.27"
+      }
+    },
     "dom-converter": {
       "version": "0.2.0",
       "resolved": "https://registry.npmmirror.com/dom-converter/download/dom-converter-0.2.0.tgz",
@@ -44447,6 +44564,21 @@
         "pinkie": "^2.0.0"
       }
     },
+    "pizzip": {
+      "version": "3.1.7",
+      "resolved": "https://registry.npmmirror.com/pizzip/-/pizzip-3.1.7.tgz",
+      "integrity": "sha512-VemVeAQtdIA74AN1Fsd5OmbMbEeS4YOwwlcudgzvmUrOIOPrk1idYC5Tw5FUFq/I0c26ziNOw9z//iPmGfp1jA==",
+      "requires": {
+        "pako": "^2.1.0"
+      },
+      "dependencies": {
+        "pako": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmmirror.com/pako/-/pako-2.1.0.tgz",
+          "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug=="
+        }
+      }
+    },
     "pkcs7": {
       "version": "0.2.3",
       "resolved": "https://registry.npmmirror.com/pkcs7/download/pkcs7-0.2.3.tgz",
@@ -50737,6 +50869,11 @@
         "word": "~0.3.0"
       }
     },
+    "xmldom": {
+      "version": "0.1.31",
+      "resolved": "https://registry.npmmirror.com/xmldom/-/xmldom-0.1.31.tgz",
+      "integrity": "sha512-yS2uJflVQs6n+CyjHoaBmVSqIDevTAWrzMmjG1Gc7h1qQ7uVozNhEPJAwZXWyGQ/Gafo3fCwrcaokezLPupVyQ=="
+    },
     "xmlhttprequest": {
       "version": "1.8.0",
       "resolved": "https://registry.npmmirror.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz",

+ 3 - 0
package.json

@@ -15,6 +15,8 @@
     "clipboard": "^2.0.10",
     "cocoroboworkpc": "file:",
     "dayjs": "^1.11.7",
+    "docxtemplater": "^3.50.0",
+    "docxtemplater-image-module-free": "^1.1.1",
     "echarts": "^5.4.2",
     "echarts-wordcloud": "^2.1.0",
     "element-china-area-data": "^5.0.2",
@@ -41,6 +43,7 @@
     "opencc-js": "^1.0.5",
     "papaparse": "^5.4.1",
     "pdfjs-dist": "^2.5.207",
+    "pizzip": "^3.1.7",
     "pptxgenjs": "^3.12.0",
     "qrcodejs2": "^0.0.2",
     "qs": "^6.10.1",

BIN
src/assets/icon/classroomObservation/voiceCard.png


Різницю між файлами не показано, бо вона завелика
+ 106 - 0
src/assets/icon/exportPdfworks/ropt.svg


+ 187 - 96
src/components/pages/aiAddCourse/addCourse.vue

@@ -117,21 +117,19 @@
                           cid && userid != courseUserid && role != '1',
                       }">
                         <div style="width: 100%">
-                          <div class="course_input_box">
-                            <div class="bb_courseIcon">
-                              <img src="../../../assets/icon/new/course.png" />
+                          <div class="course_input_box2">
+                            <div class="course_input_box">
+                              <div class="bb_courseIcon">
+                                <img src="../../../assets/icon/new/course.png" />
+                              </div>
+                              <input type="text" placeholder="请输入课程名称" class="binfo_input" v-model="courseName" @change="setCover" />
+                            </div>
+                            <div style=" margin-bottom: 15px; display:flex;">
+                              <el-switch v-model="isTeacherSee" active-text="是否公开此课程"
+                              style="justify-content: center; min-width: 150px;"></el-switch>
+                              <el-switch v-model="isFileSearch" active-text="是否开启智能检索"
+                                style="justify-content: center; min-width: 175px"></el-switch>
                             </div>
-                            <input type="text" placeholder="请输入课程名称" class="binfo_input" v-model="courseName" style="
-                                border: 1.5px solid rgb(202, 209, 220);
-                                margin: 0px 10px 0px 0px;
-                                border-radius: 5px;
-                                font-weight: 600;
-                                padding: 12px 14px 12px 71px;
-                              " @change="setCover" />
-                            <el-switch v-model="isTeacherSee" active-text="是否公开此课程"
-                              style="justify-content: center; min-width: 150px"></el-switch>
-                            <el-switch v-model="isFileSearch" active-text="是否开启智能检索"
-                              style="justify-content: center; min-width: 175px"></el-switch>
                           </div>
                         </div>
                       </div>
@@ -583,7 +581,7 @@
                             @click="openAiDialog(2, 'aiteacherTextDetail', 2), addCourseBehavior('courseBehavior', '点击已有教案摘要-智能优化按钮')">智能优化</div>
                           </el-tooltip>
                           <div class="r_pub_button_edit" style="margin-left:10px" @click="teacherCourseTextB = !teacherCourseTextB,forceUpdate2(), addCourseBehavior('courseBehavior', '点击已有教案摘要-确定/编辑按钮')">{{ teacherCourseTextB ? '确定' : '编辑'}}</div>
-                          <el-switch style="margin-left: 10px" v-model="isQuote['aiteacherTextDetail']" active-text="引用" active-color="#0061FF"  class="custom-switch" v-if="dialogTemplateArray.indexOf(templateid) != -1"  @change="handleSwitchChange('aiteacherTextDetail'), addCourseBehavior('courseBehavior', '点击已有教案摘要-引用按钮')"></el-switch>
+                          <el-switch style="margin-left: 10px" v-model="isQuote['aiteacherTextDetail']" active-text="引用" active-color="#0061FF"  class="custom-switch" v-if="isDialog == 1"  @change="handleSwitchChange('aiteacherTextDetail'), addCourseBehavior('courseBehavior', '点击已有教案摘要-引用按钮')"></el-switch>
                         </div>
                       </div>
                   </div>
@@ -616,7 +614,7 @@
                             @click="openAiDialog(2, 'aitargetTextDetail', 2), addCourseBehavior('courseBehavior', '点击课程目标-智能优化按钮')">智能优化</div>
                         </el-tooltip>
                         <div class="r_pub_button_edit" style="margin-left:10px" @click="targetCourseTextB = !targetCourseTextB,forceUpdate2(), addCourseBehavior('courseBehavior', '点击课程目标-确定/编辑按钮')">{{ targetCourseTextB ? '确定' : '编辑'}}</div>
-                        <el-switch style="margin-left: 10px" v-model="isQuote['aitargetTextDetail']" active-text="引用" active-color="#0061FF"  class="custom-switch" v-if="dialogTemplateArray.indexOf(templateid) != -1"  @change="handleSwitchChange('aitargetTextDetail'), addCourseBehavior('courseBehavior', '点击课程目标-引用按钮')"></el-switch>
+                        <el-switch style="margin-left: 10px" v-model="isQuote['aitargetTextDetail']" active-text="引用" active-color="#0061FF"  class="custom-switch" v-if="isDialog == 1"  @change="handleSwitchChange('aitargetTextDetail'), addCourseBehavior('courseBehavior', '点击课程目标-引用按钮')"></el-switch>
                       </div>
                     </div>
                   </div>
@@ -1110,7 +1108,7 @@
                               @click="openAiDialog(2, 'aiDetail', 2), addCourseBehavior('courseBehavior', '点击课程简要描述-智能优化按钮')">智能优化</div>
                           </el-tooltip>
                           <div class="r_pub_button_edit" style="margin-left:10px" @click="courseTextB = !courseTextB,forceUpdate2(), addCourseBehavior('courseBehavior', '点击课程简要描述-确定/编辑按钮')">{{ courseTextB ? '确定' : '编辑'}}</div>
-                          <el-switch style="margin-left: 10px" v-model="isQuote['aiDetail']" active-text="引用" active-color="#0061FF"  class="custom-switch" v-if="dialogTemplateArray.indexOf(templateid) != -1"  @change="handleSwitchChange('aiDetail'), addCourseBehavior('courseBehavior', '点击课程简要描述-引用按钮')"></el-switch>
+                          <el-switch style="margin-left: 10px" v-model="isQuote['aiDetail']" active-text="引用" active-color="#0061FF"  class="custom-switch" v-if="isDialog == 1"  @change="handleSwitchChange('aiDetail'), addCourseBehavior('courseBehavior', '点击课程简要描述-引用按钮')"></el-switch>
                         </div>
                       </div>
                   </div>
@@ -1155,7 +1153,7 @@
                               @click="openAiDialog(2, 'aiDetail', 2)">智能优化</div>
                           </el-tooltip> -->
                           <div class="r_pub_button_edit" style="margin-left:10px" @click="courseTextB = !courseTextB,forceUpdate2(), addCourseBehavior('courseBehavior', '点击课程概况-确定/编辑按钮')">{{ courseTextB ? '确定' : '编辑'}}</div>
-                          <el-switch style="margin-left: 10px" v-model="isQuote['aiDetail']" active-text="引用" active-color="#0061FF"  class="custom-switch" v-if="dialogTemplateArray.indexOf(templateid) != -1"  @change="handleSwitchChange('aiDetail'), addCourseBehavior('courseBehavior', '点击课程概况-引用按钮')"></el-switch>
+                          <el-switch style="margin-left: 10px" v-model="isQuote['aiDetail']" active-text="引用" active-color="#0061FF"  class="custom-switch" v-if="isDialog == 1"  @change="handleSwitchChange('aiDetail'), addCourseBehavior('courseBehavior', '点击课程概况-引用按钮')"></el-switch>
                         </div>
                       </div>
                   </div>
@@ -1332,7 +1330,7 @@
                               @click="openAiDialog(2, 'aitargetTextDetail2', 2), addCourseBehavior('courseBehavior', '点击课程目标-智能优化按钮')">智能优化</div>
                           </el-tooltip>
                           <div class="r_pub_button_edit" style="margin-left:10px" @click="targetCourseText2B = !targetCourseText2B,forceUpdate2(), addCourseBehavior('courseBehavior', '点击课程目标-确定/编辑按钮')">{{ targetCourseText2B ? '确定' : '编辑'}}</div>
-                          <el-switch style="margin-left: 10px" v-model="isQuote['aitargetTextDetail2']" active-text="引用" active-color="#0061FF"  class="custom-switch" v-if="dialogTemplateArray.indexOf(templateid) != -1"  @change="handleSwitchChange('aitargetTextDetail2'), addCourseBehavior('courseBehavior', '点击课程目标-引用按钮')"></el-switch>
+                          <el-switch style="margin-left: 10px" v-model="isQuote['aitargetTextDetail2']" active-text="引用" active-color="#0061FF"  class="custom-switch" v-if="isDialog == 1"  @change="handleSwitchChange('aitargetTextDetail2'), addCourseBehavior('courseBehavior', '点击课程目标-引用按钮')"></el-switch>
                         </div>
                       </div>
                   </div>
@@ -1663,7 +1661,7 @@
                           </el-tooltip>
                           <div class="r_pub_button_edit" style="margin-left:10px" @click="editTask2(index), addCourseBehavior('courseBehavior', `点击课程大纲-任务${index + 1}-确定/编辑按钮`)">{{
                             item.isTask2 ? '确定' : '编辑'}}</div>
-                          <el-switch style="margin-left: 10px" v-model="isQuote['aiDetail1-'+index]" active-text="引用" active-color="#0061FF"  class="custom-switch" v-if="dialogTemplateArray.indexOf(templateid) != -1"  @change="handleSwitchChange('aiDetail1-'+index), addCourseBehavior('courseBehavior', `点击课程大纲-任务${index + 1}-引用按钮`)"></el-switch>
+                          <el-switch style="margin-left: 10px" v-model="isQuote['aiDetail1-'+index]" active-text="引用" active-color="#0061FF"  class="custom-switch" v-if="isDialog == 1"  @change="handleSwitchChange('aiDetail1-'+index), addCourseBehavior('courseBehavior', `点击课程大纲-任务${index + 1}-引用按钮`)"></el-switch>
                         </div>
                       </div>
                     </div>
@@ -1693,7 +1691,7 @@
                           </el-tooltip>
                           <div class="r_pub_button_edit" style="margin-left:10px" @click="editCpote('cpote1s'), addCourseBehavior('courseBehavior', `点击概念群-确定/编辑按钮`)">{{
                             cpote.cpote1s ? '确定' : '编辑'}}</div>
-                          <el-switch style="margin-left: 10px" v-model="isQuote['aiCpote1']" active-text="引用" active-color="#0061FF"  class="custom-switch" v-if="dialogTemplateArray.indexOf(templateid) != -1"  @change="handleSwitchChange('aiCpote1'), addCourseBehavior('courseBehavior', `点击概念群-引用按钮`)"></el-switch>
+                          <el-switch style="margin-left: 10px" v-model="isQuote['aiCpote1']" active-text="引用" active-color="#0061FF"  class="custom-switch" v-if="isDialog == 1"  @change="handleSwitchChange('aiCpote1'), addCourseBehavior('courseBehavior', `点击概念群-引用按钮`)"></el-switch>
                         </div>
                     </div>
                   </div>
@@ -1722,7 +1720,7 @@
                           </el-tooltip>
                           <div class="r_pub_button_edit" style="margin-left:10px" @click="editCpote('cpote2s'), addCourseBehavior('courseBehavior', `点击问题链-确定/编辑按钮`)">{{
                             cpote.cpote2s ? '确定' : '编辑'}}</div>
-                          <el-switch style="margin-left: 10px" v-model="isQuote['aiCpote2']" active-text="引用" active-color="#0061FF"  class="custom-switch" v-if="dialogTemplateArray.indexOf(templateid) != -1"  @change="handleSwitchChange('aiCpote2'), addCourseBehavior('courseBehavior', `点击问题链-引用按钮`)"></el-switch>
+                          <el-switch style="margin-left: 10px" v-model="isQuote['aiCpote2']" active-text="引用" active-color="#0061FF"  class="custom-switch" v-if="isDialog == 1"  @change="handleSwitchChange('aiCpote2'), addCourseBehavior('courseBehavior', `点击问题链-引用按钮`)"></el-switch>
                         </div>
                     </div>
                   </div>
@@ -1751,7 +1749,7 @@
                           </el-tooltip>
                           <div class="r_pub_button_edit" style="margin-left:10px" @click="editCpote('cpote3s'), addCourseBehavior('courseBehavior', `点击目标层-确定/编辑按钮`)">{{
                             cpote.cpote3s ? '确定' : '编辑'}}</div>
-                          <el-switch style="margin-left: 10px" v-model="isQuote['aiCpote3']" active-text="引用" active-color="#0061FF"  class="custom-switch" v-if="dialogTemplateArray.indexOf(templateid) != -1"  @change="handleSwitchChange('aiCpote3'), addCourseBehavior('courseBehavior', `点击目标层-引用按钮`)"></el-switch>
+                          <el-switch style="margin-left: 10px" v-model="isQuote['aiCpote3']" active-text="引用" active-color="#0061FF"  class="custom-switch" v-if="isDialog == 1"  @change="handleSwitchChange('aiCpote3'), addCourseBehavior('courseBehavior', `点击目标层-引用按钮`)"></el-switch>
                         </div>
                     </div>
                   </div>
@@ -1780,7 +1778,7 @@
                           </el-tooltip>
                           <div class="r_pub_button_edit" style="margin-left:10px" @click="editCpote('cpote4s'), addCourseBehavior('courseBehavior', `点击任务簇-确定/编辑按钮`)">{{
                             cpote.cpote4s ? '确定' : '编辑'}}</div>
-                          <el-switch style="margin-left: 10px" v-model="isQuote['aiCpote4']" active-text="引用" active-color="#0061FF"  class="custom-switch" v-if="dialogTemplateArray.indexOf(templateid) != -1"  @change="handleSwitchChange('aiCpote4'), addCourseBehavior('courseBehavior', `点击任务簇-引用按钮`)"></el-switch>
+                          <el-switch style="margin-left: 10px" v-model="isQuote['aiCpote4']" active-text="引用" active-color="#0061FF"  class="custom-switch" v-if="isDialog == 1"  @change="handleSwitchChange('aiCpote4'), addCourseBehavior('courseBehavior', `点击任务簇-引用按钮`)"></el-switch>
                         </div>
                     </div>
                   </div>
@@ -1829,7 +1827,7 @@
                           </el-tooltip>
                           <div class="r_pub_button_edit" style="margin-left:10px" @click="editTask3(index)">{{
                             item.isTask3 ? '确定' : '编辑'}}</div>
-                          <el-switch style="margin-left: 10px" v-model="isQuote['teacherDetail2-'+index]" active-text="引用" active-color="#0061FF"  class="custom-switch" v-if="dialogTemplateArray.indexOf(templateid) != -1"  @change="handleSwitchChange('teacherDetail2-'+index), addCourseBehavior('courseBehavior', `点击教案-任务${index + 1}-引用按钮`)"></el-switch>
+                          <el-switch style="margin-left: 10px" v-model="isQuote['teacherDetail2-'+index]" active-text="引用" active-color="#0061FF"  class="custom-switch" v-if="isDialog == 1"  @change="handleSwitchChange('teacherDetail2-'+index), addCourseBehavior('courseBehavior', `点击教案-任务${index + 1}-引用按钮`)"></el-switch>
                         </div>
                       </div>
                     </div>
@@ -2645,11 +2643,14 @@
                                 @contextmenu.prevent="openAiDialog2(1, 'aiTask2',itemTaskIndex)"
                                 @click="openAiDialog2(2, 'aiTask2',itemTaskIndex)">重新生成任务</button>
                             </el-tooltip> -->
+                           <div style="display: flex">
                             <el-tooltip effect="light" content="右键单击可配置提示词" placement="bottom">
                               <button class="c_pub_button_confirm" style="margin: 0 0 0 20px;"
                                 @contextmenu.prevent="openAiDialog2(1, 'aiTask3',itemTaskIndex), addCourseBehavior('courseBehavior', `右键学历案-任务${itemTaskIndex + 1}-重新生成任务按钮`)"
                                 @click="openAiDialog2(2, 'aiTask3',itemTaskIndex), addCourseBehavior('courseBehavior', `点击学历案-任务${itemTaskIndex + 1}-重新生成任务按钮`)">重新生成任务</button>
                             </el-tooltip>
+                            <button v-if="itemTaskIndex == 0" class="c_pub_button_confirm" style="margin: 0 0 0 20px;" @click="openAiDialog2(2, 'aiTask3','all'), addCourseBehavior('courseBehavior', `点击学历案-重新生成所有任务按钮`)">重新生成所有任务</button>
+                           </div>
                             <!-- <el-tooltip effect="light" content="右键单击可配置提示词" placement="bottom">
                               <button class="c_pub_button_confirm" style="margin: 0 0 0 20px;"
                                 @contextmenu.prevent="openAiDialog2(1, 'aiTask3','all')"
@@ -2742,7 +2743,7 @@
                                       itemTaskIndex
                                     ], itemTaskIndex), addCourseBehavior('courseBehavior', `点击学历案-任务${itemTaskIndex + 1}-任务描述-智能优化按钮`)">智能优化</div>
                                   </el-tooltip>
-                                    <el-switch style="margin-left: 10px" v-model="isQuote['aiDetail2-'+itemTaskIndex]" active-text="引用" active-color="#0061FF"  class="custom-switch" v-if="dialogTemplateArray.indexOf(templateid) != -1"  @change="handleSwitchChange('aiDetail2-'+itemTaskIndex)"></el-switch>
+                                    <el-switch style="margin-left: 10px" v-model="isQuote['aiDetail2-'+itemTaskIndex]" active-text="引用" active-color="#0061FF"  class="custom-switch" v-if="isDialog == 1"  @change="handleSwitchChange('aiDetail2-'+itemTaskIndex)"></el-switch>
                                   </div>
                               </div>
                             </div>
@@ -3504,7 +3505,7 @@
                           background: #fff;
                           border-radius: 5px;
                           margin-top: 15px;
-                        " :style="{paddingBottom:pjTemplateArray.indexOf(templateid) == -1?'':'75px'}">
+                        " :style="{paddingBottom: panTaskElist() == 0?'75px':''}">
                         <div v-if="
                           unitJson[unitIndex].easy == 6 ||
                           !unitJson[unitIndex].easy
@@ -4859,7 +4860,7 @@
                                         @click="openAiDialog(2, 'aiDetail3', itemTool.toolDetail, itemTaskIndex, toolIndex), addCourseBehavior('courseBehavior', `点击学历案-任务${itemTaskIndex + 1}-工具${toolIndex + 1}-工具描述-智能优化按钮`)">
                                         智能优化</div>
                                     </el-tooltip>
-                                    <el-switch style="margin-left: 10px" v-model="isQuote['aiDetail3-'+itemTaskIndex+'-'+toolIndex]" active-text="引用" active-color="#0061FF"  class="custom-switch" v-if="dialogTemplateArray.indexOf(templateid) != -1"  @change="handleSwitchChange('aiDetail3-'+itemTaskIndex+'-'+toolIndex)"></el-switch>
+                                    <el-switch style="margin-left: 10px" v-model="isQuote['aiDetail3-'+itemTaskIndex+'-'+toolIndex]" active-text="引用" active-color="#0061FF"  class="custom-switch" v-if="isDialog == 1"  @change="handleSwitchChange('aiDetail3-'+itemTaskIndex+'-'+toolIndex)"></el-switch>
                                   </div>
                                 </div>
                               </div>
@@ -4874,7 +4875,7 @@
                               :aiJson="aiJson"
                               @setEvaList="setEvaList"
                               @addCourseBehavior="addCourseBehavior"
-                              v-if="pjTemplateArray.indexOf(templateid) != -1 && pjIndex.indexOf(itemTool.tool[0]) != -1"
+                              v-if="panTaskElist() == 0 && pjIndex.indexOf(itemTool.tool[0]) != -1"
                               :ref="'evalist'+itemTaskIndex+toolIndex"></evaList>
                             </div>
                             <button class="c_pub_button_add pub_btn_tool_img" @click="addToolFun(itemTaskIndex), addCourseBehavior('courseBehavior', `点击学历案-任务${itemTaskIndex + 1}-工具描述-添加按钮`)" style="
@@ -4886,7 +4887,7 @@
                             </button>
                           </div>
                         </div>
-                        <div class="elist_css" v-if="pjTemplateArray.indexOf(templateid) != -1 && panElist(itemTask) > 0">
+                        <div class="elist_css" v-if="panElist(itemTask) > 0">
                           <div class="elist_title">
                             <div style=" display: flex; flex-direction: row; align-items: center; margin: 20px 0; ">
                               <div class="lineTitle clineTitle" style="width: auto">任务评价体系</div>
@@ -4896,7 +4897,7 @@
                             </div>
                           </div>
                         </div>
-                        <div class="elist_css" v-if="!(unitJson[unitJson.length - 1].easy == 4) && pjTemplateArray.indexOf(templateid) == -1"
+                        <div class="elist_css" v-if="panTaskElist() > 0"
                           v-loading="(taskDetailLoading4.indexOf('task-' + itemTaskIndex) !== -1) || (taskGLoading[itemTaskIndex] && taskGLoading[itemTaskIndex][2])" element-loading-text="小可正在努力生成中,请稍等...">
                           <div class="elist_title">
                             <div style="
@@ -5378,8 +5379,8 @@
         <aiTips ttitle="任务详情" title="任务评价优化" :detail="aiJson.aiDetail4" pan="aiDetail4" @setAiJson="setAiJson" />
         <aiTips ttitle="任务详情" title="生成评价细则" :detail="aiJson.aiRateRule" pan="aiRateRule" @setAiJson="setAiJson"/>
       </div>
-      <div class="leftBar2 " v-show="istemplate != 1 && dialogTemplateArray.indexOf(templateid) != -1 && chatid && isDisplay">
-        <!-- <div class="resizer"></div> resizable-->
+      <div class="leftBar2 resizable" v-show="istemplate != 1 && isDialog == 1 && chatid && isDisplay">
+        <div class="resizer"></div> 
         <aiBoxRight  
         :languageSetting="languageSetting"
         :courseId="chatid" 
@@ -5393,7 +5394,7 @@
         @addCourseBehavior="addCourseBehavior"
         @setIsQuote="setIsQuote"></aiBoxRight>
       </div>
-      <div class="close_btn" @click="closeRight" :class="!isDisplay ? 'close_btn_voice' : ''"  v-show="istemplate != 1 && dialogTemplateArray.indexOf(templateid) != -1 && chatid">
+      <div class="close_btn" @click="closeRight" :class="!isDisplay ? 'close_btn_voice' : ''"  v-show="istemplate != 1 && isDialog == 1 && chatid">
         <img src="../../../assets/icon/course/arrow.svg" >
       </div>
     </div>
@@ -7430,7 +7431,8 @@ export default {
       dialogTemplateArray: [ 'cf5722a4-401b-11ef-b873-005056b86cd2', '68629cfb-e719-48e9-a03d-56f189fb9cb0' ],
       taskCancelToken1: [],
       taskCancelToken2: [],
-      isDisplay: true
+      isDisplay: true,
+      isDialog: 0,
     };
   },
   directives: {
@@ -7608,6 +7610,20 @@ export default {
         return count;
       };
     },
+    panTaskElist(){
+      return function () {
+        let count = 0;
+        for(var i = 0; i < this.unitJson.length; i++){
+          let _task = this.unitJson[i].chapterInfo[0].taskJson
+          for(var j = 0; j < _task.length; j++){
+            if(_task[j].eList && _task[j].eList.length){
+              count++
+            }
+          }
+        }
+        return count;
+      };
+    },
     dataCheckPan(){
       return function (fileid) {
         for(let i = 0; i < this.infoData.length; i++){
@@ -12233,6 +12249,22 @@ ${_this.unitJson[0].chapterInfo[0].taskJson[index].taskDetail3.replaceAll('#',''
             //   this.aiJson.aiTeacher = '请根据<任务名+单一任务描述>和并参考<课程简要描述>和#参考上下文(上下文中可能蕴含不相关的内容,请你无视不相关内容),为该任务设计详细的教案,教案需要包含该任务的教学目标,教学过程(包含分步骤的教师活动和学生活动,教师活动与学生活动应该一一对应),评价标准(学生能做到...),相关知识点的讲解,练习(练习需要包含示例答案)。'
             // }
             this.$forceUpdate();
+            this.isDialog = res.data[0][0].isDialog
+          }
+        })
+        .catch((err) => { });
+      }
+    },
+    getTipsTemplateIsDialog(){
+      if(this.templateid){
+        let params = {
+          id: this.templateid
+        }
+        this.ajax
+        .get(this.$store.state.api + "selectTipsTemplateById", params)
+        .then((res) => {
+          if(res.data[0].length){
+            this.isDialog = res.data[0][0].isDialog
           }
         })
         .catch((err) => { });
@@ -14213,6 +14245,7 @@ ${_this.unitJson[0].chapterInfo[0].taskJson[index].taskDetail3.replaceAll('#',''
                 this.aiJson.agentid = this.aiJson.agentid ? this.aiJson.agentid : '8e71322c-6c2a-11ef-8ce0-12e77c4cb76b'
                 this.aiJson.sagentid = this.aiJson.sagentid ? this.aiJson.sagentid : ''
                 this.templateid = res.data[3][0].template;
+                this.getTipsTemplateIsDialog()
               }catch(error){
                 console.error(error)
               }
@@ -14347,6 +14380,7 @@ ${_this.unitJson[0].chapterInfo[0].taskJson[index].taskDetail3.replaceAll('#',''
               try {
                 this.aiJson = JSON.parse(res.data[3][0].tips);
                 this.templateid = res.data[3][0].template;
+                this.getTipsTemplateIsDialog()
               }catch(error){
                 console.error(error)
               }
@@ -15891,12 +15925,12 @@ ${_this.unitJson[0].chapterInfo[0].taskJson[index].taskDetail3.replaceAll('#',''
       window.course_info = courseInfo
       window.course_lang = this.languageSetting
     },
-    setCover() {
+    setCover(attempts = 0) {
       var _this = this;
-      if(_this.cover.length){
+      if (_this.cover.length || attempts >= 3) {
         return;
       }
-      _this.imageloading2 = true
+      _this.imageloading2 = true;
       _this.ajax
         .post("https://gpt.cocorobo.cn/search_image", {
           page: _this.ppage,
@@ -15904,21 +15938,26 @@ ${_this.unitJson[0].chapterInfo[0].taskJson[index].taskDetail3.replaceAll('#',''
           query: _this.courseName,
         })
         .then(function (response) {
-          // console.log(response.data.data);
-          var data = response.data.FunctionResponse.result;
-          _this.cover = [];
-          setTimeout(() => {
-              _this.cover[0] = {
-              name: "网络图片.png",
-              url: data[0].thumbnail
-            };
-            _this.imgChange1(null, null, 1, null);
-            _this.$forceUpdate();
-          }, 0);
-          _this.imageloading2 = false
+          var data = (response.data && response.data.FunctionResponse) ? response.data.FunctionResponse.result : ''; 
+          if(data){
+            _this.cover = [];
+            setTimeout(() => {
+              _this.cover[0] = {
+                name: "网络图片.png",
+                url: data[0].thumbnail,
+              };
+              _this.imgChange1(null, null, 1, null);
+              _this.$forceUpdate();
+            }, 0);
+            _this.imageloading2 = false;
+          }else {
+            _this.imageloading2 = false;
+            _this.setCover(attempts + 1);
+          }
         })
         .catch(function (error) {
-          _this.imageloading2 = false
+          _this.imageloading2 = false;
+          _this.setCover(attempts + 1);
           console.log(error);
         });
     },
@@ -16501,12 +16540,12 @@ ${_this.unitJson[0].chapterInfo[0].taskJson[index].taskDetail3.replaceAll('#',''
         ); // 利用file-saver保存文件  自定义文件名
         setTimeout(() => {
           this.loading = false
-          if(!this.cid){
-            this.addWork(3)
-          }else{
-            this.updateWork();
-            this.steps = 4;
-          }
+          // if(!this.cid){
+          //   this.addWork(3)
+          // }else{
+          //   this.updateWork();
+          //   this.steps = 4;
+          // }
         }, 2000);
       });
   
@@ -18112,7 +18151,11 @@ ${this.courseText && this.aiCallBack[0] == 2 ? '注意,优化原有的<参考
                     let regex = new RegExp("(?<=```json)([\\s\\S]*?)(?=```)");
                     let match = data.message.match(regex);
                     // eval("var aaa = " + match[0])
-                    dArray = JSON.parse(match[0].replace(/\n/g, '      ').replace(/\s{2,}/g, '      '));
+                    if(match && match[0]){
+                      dArray = JSON.parse(match[0].replace(/\n/g, '      ').replace(/\s{2,}/g, '      '));
+                    }else {
+                      dArray = JSON.parse(data.message.replace(/\n/g, '      ').replace(/\s{2,}/g, '      '));
+                    }
 
                 } catch (error) {
                   _this.$message.error('返回json格式不正确')
@@ -19689,7 +19732,7 @@ ${this.courseText && this.aiCallBack[0] == 2 ? '注意,优化原有的<参考
             _this.$nextTick(()=>{
               setTimeout(() => {
                 for (var j = 0; j < _task.toolChoose.length; j++) {
-                  if(_this.pjTemplateArray.indexOf(_this.templateid) !=-1 && _this.pjIndex.indexOf(_this.unitJson[0].chapterInfo[0].taskJson[index].toolChoose[j].tool[0]) != -1){
+                  if(_this.panTaskElist() == 0 && _this.pjIndex.indexOf(_this.unitJson[0].chapterInfo[0].taskJson[index].toolChoose[j].tool[0]) != -1){
                     _this.$refs['evalist'+index+j][0].openAiDialog('elist');
                   }
                 }
@@ -23748,33 +23791,63 @@ ${msg}
     next();
   },
   mounted(){
-    // const resizable = this.$el.querySelector('.resizable');
-    // const resizer = this.$el.querySelector('.resizer');
-    // let startX, startWidth;
-
-    // const mouseMoveHandler = (e) => {
-    //   const dx = startX - e.clientX;
-    //   const newWidth = startWidth + dx + 40;
-    //   if (newWidth >= 200 && newWidth <= 600) {
-    //     resizable.style.width = `${newWidth}px`;
-    //   }
-    // };
-
-    // const mouseUpHandler = () => {
-    //   document.removeEventListener('mousemove', mouseMoveHandler);
-    //   document.removeEventListener('mouseup', mouseUpHandler);
-    //   document.body.style.cursor = 'default';
-    // };
-
-    // const mouseDownHandler = (e) => {
-    //   startX = e.clientX;
-    //   startWidth = resizable.getBoundingClientRect().width;
-    //   document.addEventListener('mousemove', mouseMoveHandler);
-    //   document.addEventListener('mouseup', mouseUpHandler);
-    //   document.body.style.cursor = 'ew-resize';
-    // };
-
-    // resizer.addEventListener('mousedown', mouseDownHandler);
+    const resizable = this.$el.querySelector('.resizable');
+    const resizer = this.$el.querySelector('.resizer');
+    const maxWidth = document.body.offsetWidth / 2;
+    const maxWidth2 = window.innerWidth / 2;
+    let startX, startWidth;
+
+    const mouseMoveHandler = (e) => {
+      e.preventDefault(); // 添加此行以防止选中其他文本
+      const dx = startX - e.clientX;
+      const newWidth = startWidth + dx;
+      if (newWidth >= 350 && newWidth <= maxWidth) {
+        resizable.style.minWidth = `${newWidth}px`;
+      }
+    };
+
+    const mouseUpHandler = () => {
+      document.removeEventListener('mousemove', mouseMoveHandler);
+      document.removeEventListener('mouseup', mouseUpHandler);
+      document.body.style.cursor = 'default';
+    };
+
+    const mouseDownHandler = (e) => {
+      e.preventDefault(); // 添加此行以防止选中其他文本
+      startX = e.clientX;
+      startWidth = resizable.getBoundingClientRect().width;
+      document.addEventListener('mousemove', mouseMoveHandler);
+      document.addEventListener('mouseup', mouseUpHandler);
+      document.body.style.cursor = 'ew-resize';
+    };
+
+    resizer.addEventListener('mousedown', mouseDownHandler);
+
+    const touchMoveHandler = (e) => {
+      e.preventDefault(); // 添加此行以防止选中其他文本
+      const dx = startX - e.touches[0].clientX;
+      const newWidth = startWidth + dx;
+      if (newWidth >= 350 && newWidth <= maxWidth2) {
+        resizable.style.minWidth = `${newWidth}px`;
+      }
+    };
+
+    const touchEndHandler = () => {
+      document.removeEventListener('touchmove', touchMoveHandler);
+      document.removeEventListener('touchend', touchEndHandler);
+      document.body.style.cursor = 'default';
+    };
+
+    const touchStartHandler = (e) => {
+      e.preventDefault(); // 添加此行以防止选中其他文本
+      startX = e.touches[0].clientX;
+      startWidth = resizable.getBoundingClientRect().width;
+      document.addEventListener('touchmove', touchMoveHandler);
+      document.addEventListener('touchend', touchEndHandler);
+      document.body.style.cursor = 'ew-resize';
+    };
+
+    resizer.addEventListener('touchstart', touchStartHandler);
   },
   created() {
     this.selectFileid();
@@ -24618,14 +24691,29 @@ ${msg}
 .course_input_box {
   display: flex;
   margin-right: 20px;
+  min-width: 400px;
+  width: calc(100% - 350px);
+  align-items: center;
+  position: relative;
+  margin-bottom: 15px;
+}
+
+.course_input_box2 {
+  display: flex;
   width: 100%;
   align-items: center;
   position: relative;
+  flex-wrap: wrap;
 }
 
+
 .course_input_box>.binfo_input {
-  width: calc(100% - 0 - 200px - 20px);
-  margin: 0 10px;
+  width: calc(100%);
+  margin: 0;
+  border: 1.5px solid rgb(202, 209, 220); 
+  border-radius: 5px;
+  font-weight: 600;
+  padding: 12px 14px 12px 71px;
 }
 
 .bb_courseIcon {
@@ -25858,7 +25946,7 @@ ol {
   width: 100%;
   align-items: center;
   justify-content: flex-start;
-  margin: 15px 0;
+  margin: 0 0 15px;
 }
 
 .notice>>>.el-dialog {
@@ -27621,7 +27709,7 @@ ol {
 }
 
 .pType_box {
-  margin-top: 30px;
+  margin: 15px 0;
   align-items: flex-end;
 }
 
@@ -28113,18 +28201,21 @@ ol {
   word-break: break-word;
 }
 
-.info_box_t{
+.info_box_t {
   display: flex;
   align-items: center;
+  flex-wrap: wrap;
 }
 
-.info_box_t + .info_box_t{
+.info_box_t + .info_box_t {
   margin-top: 10px;
 }
 
-.info_box_t_box{
+.info_box_t_box {
   display: flex;
   align-items: center;
+  flex-wrap: wrap;
+  margin-bottom: 5px;
 }
 
 .info_box_t_box + .info_box_t_box{
@@ -28331,9 +28422,8 @@ ol {
 
 .resizable {
   position: relative;
- 
-  min-width: 200px; /* 最小宽度 */
-  max-width: 600px; /* 最大宽度 */
+  min-width: 350px; /* 最小宽度 */
+  max-width: 50%; /* 最大宽度 */
 }
 
 .resizer {
@@ -28345,5 +28435,6 @@ ol {
   left: 0;
   cursor: ew-resize;
   transform: translateY(-50%);
+  border-radius: 43px;
 }
 </style>

+ 8 - 0
src/components/pages/classroomObservation/components/addNewAnalysisDialog.vue

@@ -102,6 +102,7 @@
                 />
                 <div class="a-d-b-i-t-title">{{ item.name }}</div>
               </div>
+							<div class="a_d_b_i_author" v-if="item.username">创作者:{{ item.username }}</div>
               <div class="a-d-b-i-bottom">{{ item.detail }}</div>
               <div class="a-d-b-i-bottomPer" style="display: block">
                 {{ item.count }}人已使用
@@ -1349,4 +1350,11 @@ export default {
 .a_d_b_i_t_t_editDialog > div > span {
   margin: 0 5px 0 10px;
 }
+
+.a_d_b_i_author{
+	font-size: 14px;
+	margin-bottom: 5px;
+	margin-top: -5px;
+	font-weight: normal;
+}
 </style>

+ 1 - 1
src/components/pages/classroomObservation/components/analysis.vue

@@ -596,7 +596,7 @@ export default {
 		},
 		dragSubmit(){
 			this.visible = false;
-			this.$parent.isDrag = false;
+			this.$parent.moveAnalysisSubmit()
 		},
 		moveAnalysisSubmit(data){
 			this.$emit('moveAnalysis',data)

+ 3 - 3
src/components/pages/classroomObservation/components/analysis2.vue

@@ -2,7 +2,7 @@
 	<div class="analysis">
 		<div class="a-header">
 			<div class="a-h-left" @click.stop="changeShowItem(!showItem)">
-				<span :class="['a-h-l-icon', showItem ? 'a-h-l-showIcon' : '']"></span>
+				<!-- <span :class="['a-h-l-icon', showItem ? 'a-h-l-showIcon' : '']"></span> -->
 				<span class="a-h-l-title">{{ title }}</span>
 			</div>
 			<div class="a-h-right" v-if="showAdd">
@@ -85,8 +85,8 @@ export default {
 	padding: 5px 8px 5px 8px;
 	gap: 8px;
 	opacity: 0px;
-	margin: 20px 0;
-	margin-bottom: 10px;
+	margin: 20px 0px 5px 0;
+	margin-bottom: 5px;
 	border-bottom: 1px #ccc solid;
 }
 .analysis {

+ 1 - 1
src/components/pages/classroomObservation/components/analysisItem.vue

@@ -77,7 +77,7 @@
         </span>
 
         <span
-          v-if="loadNum == 0 && !openItem && tid && !isDrag""
+          v-if="loadNum == 0 && !openItem && tid && !isDrag"
           class="ai-h-r-icon4"
           @click="delBtn()"
         >

+ 2 - 2
src/components/pages/classroomObservation/components/analysisItem2.vue

@@ -2,9 +2,9 @@
 	<div class="analysisItem">
 		<div class="ai-header" v-show="data.jsonData.name != '词频词汇分析'">
 			<div class="ai-h-left" @click.stop="changeOpenItem(!openItem)">
-				<span
+				<!-- <span
 					:class="['ai-h-l-icon', openItem ? 'ai-h-l-iconActive' : '']"
-				></span>
+				></span> -->
 				<span class="ai-h-l-text">{{ data.jsonData.name }}</span>
 			</div>
 			<div class="ai-h-right" v-if="showAdd">

+ 102 - 1
src/components/pages/classroomObservation/components/analysisSpecialItem.vue

@@ -1,5 +1,10 @@
 <template>
-  <div class="analysisItem">
+  <div class="analysisItem" ref="analysisItemRef" :style="
+      `top:${moveTop}px;transition:${isDragging ? '0' : '.3s'}s;${
+        isDragging ? 'z-index:999' : ''
+      }`
+    "
+		@mousedown="moveDown($event)">
     <div class="ai-header">
       <div class="ai-h-left" @click.stop="changeOpenItem(!openItem)">
         <span
@@ -1120,6 +1125,101 @@ CH:${_CH}
 
         resolve(_contentTableList);
       });
+    },
+		moveDown(e) {
+			if(!this.isDrag)return;
+      this.isDragging = true;
+      this.startY = e.clientY;
+      this.$nextTick(() => {
+        this.dialogTagList.forEach(i => {
+          this.dragBoxList.push(
+            ...this.$parent.$parent.$refs[`analysis_${i.value}`][0].$refs
+              .dragBoxRefTop
+          );
+					if(this.$parent.$parent.$refs[`analysis_${i.value}`][0].$refs.dragBoxRefBottom.length>0){
+						this.dragBoxList.push(
+            ...this.$parent.$parent.$refs[`analysis_${i.value}`][0].$refs
+              .dragBoxRefBottom
+          );
+					}else if(this.$parent.$parent.$refs[`analysis_${i.value}`][0].$refs.dragBoxRefBottom){
+						this.dragBoxList.push(this.$parent.$parent.$refs[`analysis_${i.value}`][0].$refs.dragBoxRefBottom);
+					}
+          
+        });
+        // 禁用页面文本选择
+        document.body.style.userSelect = "none";
+        document.addEventListener("mousemove", this.onMouseMove);
+        document.addEventListener("mouseup", this.stopDragging);
+      });
+    },
+    onMouseMove(e) {
+      if (!this.isDragging) return;
+
+      const newTop = e.clientY - this.startY; // 计算鼠标移动的Y轴距离
+
+      // // 更新div的top样式,使其跟随鼠标移动
+      this.moveTop = newTop;
+      // this.dragBoxList.forEach(i=>{
+      // 	let _i = i.getBoundingClientRect();
+      // 	if(e.clientX>=_i.left && e.clientX<=_i.right && e.clientY>=_i.top && e.clientY<=_i.bottom){
+      // 		this.enterDrag = i;
+      // 		console.log("👇")
+      // 		console.log(e)
+      // 	}else{
+      // 		this.enterDrag = null;
+      // 	}
+      // })
+      // for (let i = 0; i <= this.dragBoxList.length; i++) {
+      //   let _i = this.dragBoxList[i].getBoundingClientRect();
+      //   if (
+      //     e.clientX >= _i.left &&
+      //     e.clientX <= _i.right &&
+      //     e.clientY >= _i.top &&
+      //     e.clientY <= _i.bottom
+      //   ) {
+      //     this.enterDrag = this.dragBoxList[i];
+      //     console.log("👇");
+      //     console.log(e);
+      // 		break;
+      //   } else {
+      //     this.enterDrag = null;
+      //   }
+      // }
+    },
+    stopDragging(e) {
+      this.isDragging = false;
+      try {
+        for (let i = 0; i <= this.dragBoxList.length; i++) {
+          let _i = this.dragBoxList[i].getBoundingClientRect();
+          if (
+            e.clientX >= _i.left &&
+            e.clientX <= _i.right &&
+            e.clientY >= _i.top &&
+            e.clientY <= _i.bottom
+          ) {
+            this.enterDrag = this.dragBoxList[i];
+            break;
+          } else {
+            this.enterDrag = null;
+          }
+        }
+        // 恢复页面的文本选择
+        document.body.style.userSelect = "";
+        if (!this.enterDrag) {
+          this.moveTop = 0;
+        } else {
+					this.moveTop = 0;
+					let moveData = this.enterDrag.getAttribute('type');
+					this.$emit("moveAnalysis",{form:`${this.data.Type}_${this.index}_${this.data.tIndex}`,to:moveData})
+        }
+        // 移除全局的鼠标移动和释放事件
+        document.removeEventListener("mousemove", this.onMouseMove);
+        document.removeEventListener("mouseup", this.stopDragging);
+      } catch (error) {
+				this.moveTop = 0;
+				document.removeEventListener("mousemove", this.onMouseMove);
+        document.removeEventListener("mouseup", this.stopDragging);
+			}
     }
   },
   mounted() {
@@ -1143,6 +1243,7 @@ CH:${_CH}
   border: 1px solid #e7e7e7;
   border-radius: 4px;
   transition: 0.3s;
+	position: relative;
 }
 
 .analysisItem:hover {

+ 1 - 1
src/components/pages/classroomObservation/components/analysisTemplateDialog.vue

@@ -1238,7 +1238,7 @@ export default {
 .ad_h_b_shu {
   width: 1px;
   height: 10px;
-  background-color: #00000066;
+  background-color: #999999;
   margin: 2px 8px 0 8px;
 }
 

+ 3 - 0
src/components/pages/classroomObservation/components/chatArea.vue

@@ -29,6 +29,9 @@
         @startTape="onClickStartRecord"
         @uploadTape="uploadRecording"
         :uploadFileLoading="uploadFileLoading"
+				:teacherVoiceprintList="teacherVoiceprintList"
+				:chosenVoiceprint="chosenVoiceprint"
+				:controlsStatus="controlsStatus"
         ref="startPageRef"
       />
       <!-- 原文速递 -->

+ 29 - 0
src/components/pages/classroomObservation/components/messageArea.vue

@@ -1268,6 +1268,35 @@ export default {
       this.dataList = JSON.parse(JSON.stringify(this.copyDataList));
       this.copyDataList = [];
     },
+		moveAnalysisSubmit(){
+			this.loading = true;
+			if(JSON.stringify(this.copyDataList)===JSON.stringify(this.dataList)){
+				this.isDrag = false;
+				this.loading = false;
+				// this.$message.success("更换成功")
+				return 
+			}
+
+			let _copyData = JSON.parse(JSON.stringify(this.dataList));
+
+			_copyData = _copyData.filter(i=>!(i.Type==0&&i.tIndex==2));
+
+			let _result = _copyData.map(i=>({id:i.id,tIndex:i.tIndex,Type:i.Type}));
+			
+			let params = {
+				data:JSON.stringify(_result)
+			}
+			this.ajax.post('https://gpt4.cocorobo.cn/batch_update_type_tindex',params).then(res=>{
+				this.isDrag = false;
+				this.loading = false;
+				this.$message.success("保存成功")
+			}).catch(e=>{
+				console.log(e)
+				this.isDrag = true;
+				this.loading = false;
+				this.$message.error("保存失败")
+			})
+		},
     init() {
       this.bmData = {};
       this.getDefaultData();

+ 161 - 36
src/components/pages/classroomObservation/components/startPage.vue

@@ -20,20 +20,52 @@
     </div>
     <div class="sp-main">
       <div class="sp_m_box">
-        <div class="sp_m_b_top"></div>
+        <div class="sp_m_b_top">
+          <div class="sp_m_b_t_voice">
+            <div class="sp_m_b_t_v_title">声纹选择</div>
+            <span>请选择/新增本次课堂授课教师的声纹</span>
+            <div class="sp_m_b_t_v_inputArea">
+              <el-select
+                v-model="inputValue"
+                @change="handleSelect"
+                multiple
+                placeholder="请选择"
+                :multiple-limit="10"
+                filterable
+							 :disabled="controlsStatus === 1"
+              >
+                <el-option
+                  v-for="item in teacherList"
+                  :key="item.id"
+                  :label="item.name"
+                  :value="item.id"
+                >
+                </el-option>
+              </el-select>
+              <span @click="addNew">+</span>
+            </div>
+            <img
+              src="../../../../assets/icon/classroomObservation/voiceCard.png"
+            />
+          </div>
+        </div>
         <div class="sp_m_b_bottom">
-          <div  @click.stop="$emit('startTape')">
-						<div>开始录音</div>
-						<span>实时语音转录文字</span>
-						<span>智能课堂观察</span>
-						<img src="../../../../assets/icon/classroomObservation/startPageIcon2.png">
-					</div>
-          <div  @click.stop="$emit('uploadTape')">
-						<div>上传文件</div>
-						<span>录音复盘</span>
-						<span>一键分析课堂情况</span>
-						<img src="../../../../assets/icon/classroomObservation/startPageIcon1.png">
-					</div>
+          <div @click.stop="$emit('startTape')">
+            <div>开始录音</div>
+            <span>实时语音转录文字</span>
+            <span>智能课堂观察</span>
+            <img
+              src="../../../../assets/icon/classroomObservation/startPageIcon2.png"
+            />
+          </div>
+          <div @click.stop="$emit('uploadTape')">
+            <div>上传文件</div>
+            <span>录音复盘</span>
+            <span>一键分析课堂情况</span>
+            <img
+              src="../../../../assets/icon/classroomObservation/startPageIcon1.png"
+            />
+          </div>
         </div>
       </div>
       <!-- <div class="sp-m-item" @click.stop="$emit('startTape')">
@@ -78,12 +110,43 @@
 <script>
 export default {
   emits: ["startTape", "uploadTape"],
+  props: {
+    teacherVoiceprintList: {
+      type: Array,
+      default: () => []
+    },
+    chosenVoiceprint: {
+      type: Array,
+      default: []
+    },
+		controlsStatus:{
+			type:Number,
+			default:0
+		},
+  },
   data() {
     return {
-      showIntroduce: true
+      showIntroduce: true,
+      inputValue: [],
+      teacherList: []
     };
   },
-  methods: {}
+  watch: {
+    teacherVoiceprintList() {
+      this.teacherList = JSON.parse(JSON.stringify(this.teacherVoiceprintList));
+    },
+    chosenVoiceprint() {
+      this.inputValue = this.chosenVoiceprint;
+    }
+  },
+  methods: {
+    handleSelect(item) {
+      this.$parent.chosenVoiceprint = JSON.parse(JSON.stringify(this.inputValue));
+    },
+		addNew(){
+			this.$parent.onClickAddNewVoiceprint();
+		}
+  }
 };
 </script>
 
@@ -180,13 +243,20 @@ export default {
 .sp_m_box {
   width: 70%;
   height: 100%;
-	/* max-height: 550px; */
-	max-height: 400px;
+  max-height: 500px;
+  /* max-height: 400px; */
   display: flex;
   flex-direction: column;
   margin-bottom: 8%;
 }
 
+.sp_m_b_top {
+  width: 100%;
+  height: 220px;
+  /* background-color: red; */
+  margin-bottom: 20px;
+}
+
 .sp_m_b_bottom {
   width: 100%;
   flex: 1;
@@ -195,7 +265,6 @@ export default {
   justify-content: center;
 }
 
-
 .sp_m_b_bottom > div {
   height: 100%;
   flex: 1;
@@ -207,30 +276,30 @@ export default {
   box-shadow: 0px 4px 10px 0px #1d398314;
 
   box-shadow: 1px 1px 20px 4px #1d39830d;
-	background-color: #fff;
-	border-radius: 8px;
-	padding: 40px;
-	flex-direction: column;
-	cursor: pointer;
-	position: relative;
+  background-color: #fff;
+  border-radius: 8px;
+  padding: 40px;
+  flex-direction: column;
+  cursor: pointer;
+  position: relative;
 }
 
-.sp_m_b_bottom > div>img{
-	width: 50%;
-	position: absolute;
-	right: 0;
-	bottom: 0;
+.sp_m_b_bottom > div > img {
+  width: 50%;
+  position: absolute;
+  right: 0;
+  bottom: 0;
 }
 
-.sp_m_b_bottom > div>div{
-	font-size: 30px;
-	font-weight: bold;
-	margin-bottom: 10px;
+.sp_m_b_bottom > div > div {
+  font-size: 30px;
+  font-weight: bold;
+  margin-bottom: 10px;
 }
 
-.sp_m_b_bottom > div>span{
-	margin-top: 5px;
-	color: #00000066;
+.sp_m_b_bottom > div > span {
+  margin-top: 5px;
+  color: #00000066;
 }
 
 .sp_m_b_bottom > div:nth-of-type(2) {
@@ -301,7 +370,63 @@ export default {
   background-size: 100% 100%;
   margin-bottom: 15px;
 }
+.sp_m_b_t_voice {
+  width: 100%;
+  height: 100%;
+  display: flex;
+  /* align-items: center; */
+  /* justify-content: center; */
+  box-sizing: border-box;
+  border: 1px solid #aeccfe;
+  box-shadow: 0px 4px 10px 0px #1d398314;
+
+  box-shadow: 1px 1px 20px 4px #1d39830d;
+  background-color: #fff;
+  border-radius: 8px;
+  padding: 40px;
+  flex-direction: column;
+  /* cursor: pointer; */
+  position: relative;
+}
+
+.sp_m_b_t_voice > img {
+  height: 80%;
+  position: absolute;
+  right: 0;
+  bottom: 0;
+}
+
+.sp_m_b_t_voice > .sp_m_b_t_v_title {
+  font-size: 30px;
+  font-weight: bold;
+  margin-bottom: 10px;
+}
+
+.sp_m_b_t_voice > span {
+  margin-top: 5px;
+  color: #00000066;
+}
 
+.sp_m_b_t_v_inputArea {
+  margin-top: 10px;
+  display: flex;
+  align-items: center;
+}
+
+.sp_m_b_t_v_inputArea > span {
+  width: 35px;
+  height: 35px;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  background-color: #f3f7fd;
+  border-radius: 3px;
+  margin-left: 10px;
+  cursor: pointer;
+  font-weight: bold;
+  color: #3681fc;
+  font-size: 16px;
+}
 /* .sp-m-i-icon1 {
 	background: url("../../../../assets/icon/classroomObservation/tape.png")
 		no-repeat;

Різницю між файлами не показано, бо вона завелика
+ 775 - 205
src/components/pages/components/exportDataDialog.vue


+ 557 - 0
src/components/pages/test/check/docxTemplateDialog.vue

@@ -0,0 +1,557 @@
+<template>
+  <el-dialog
+    :visible.sync="show"
+    :append-to-body="true"
+    title="word导出"
+    width="1000px"
+    top="10vh"
+    :before-close="handleClose"
+    class="dialog_diy"
+  >
+    <div class="box" v-loading="loading">
+      <div class="b_left"></div>
+      <div class="b_right">
+        <div class="d_box">
+          <div class="d_b_step">
+            <h2>第一步:下载模板文档</h2>
+            <p>点击下载模板文档来下载指定文档</p>
+            <el-button
+              class="d_b_s_button"
+              type="primary"
+              :disabled="!downFileData"
+              @click="downloadTemplateDocx()"
+              >下载模板文档</el-button
+            >
+          </div>
+
+          <div class="d_b_step">
+            <h2>第二步:填入模板变量</h2>
+            <p>按需制作排版Word模板文档,目前支持docx格式</p>
+            <p>
+              在文件中指定位置输入下方的"字段变量",用于显示真实数据的准确位置
+            </p>
+            <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"
+            />
+            <div
+              v-for="(item, index) in fieldList"
+              :key="index"
+              class="d_b_s_fieldListItem"
+            >
+              <span
+                >{{ item.name }}:{{
+                  "{" + (item.type == "image" ? "%" : "") + item.field + "}"
+                }}</span
+              >
+              <span @click="copyContent(`{${item.type == 'image' ? '%' : ''}${item.field}}`)">
+                <svg
+                  width="14"
+                  height="14"
+                  viewBox="0 0 14 14"
+                  xmlns="http://www.w3.org/2000/svg"
+                >
+                  <path
+                    fill-rule="evenodd"
+                    clip-rule="evenodd"
+                    d="M1.85645 2.28599C1.85645 2.0493 2.04832 1.85742 2.28502 1.85742H8.71359C8.95028 1.85742 9.14216 2.0493 9.14216 2.28599C9.14216 2.52269 8.95028 2.71456 8.71359 2.71456H2.71359V8.71456C2.71359 8.95126 2.52171 9.14314 2.28502 9.14314C2.04832 9.14314 1.85645 8.95126 1.85645 8.71456V2.28599Z"
+                  />
+                  <path
+                    fill-rule="evenodd"
+                    clip-rule="evenodd"
+                    d="M4.42871 4.85631C4.42871 4.61961 4.62059 4.42773 4.85728 4.42773H11.7144C11.9511 4.42773 12.143 4.61961 12.143 4.85631V11.7134C12.143 11.9501 11.9511 12.142 11.7144 12.142H4.85728C4.62059 12.142 4.42871 11.9501 4.42871 11.7134V4.85631ZM5.28585 5.28488V11.2849H11.2859V5.28488H5.28585Z"
+                  />
+                </svg>
+              </span>
+            </div>
+          </div>
+
+          <div class="d_b_step">
+            <h2>第三步:上传填入后的模板文档</h2>
+            <div v-if="uploadTemplateDocxData" class="d_b_s_fileCard">
+              <svg
+                t="1728376433028"
+                class="icon"
+                viewBox="0 0 1024 1024"
+                version="1.1"
+                xmlns="http://www.w3.org/2000/svg"
+                p-id="5172"
+                width="200"
+                height="200"
+              >
+                <path
+                  d="M815.5 160v704c0 17.7-14.3 32-32 32h-543c-17.7 0-32-14.3-32-32V160c0-17.7 14.3-32 32-32h543c17.7 0 32 14.3 32 32z m0-96h-607c-35.3 0-64 28.7-64 64v768c0 35.3 28.7 64 64 64h607c35.3 0 64-28.7 64-64V128c0-35.3-28.7-64-64-64z"
+                  p-id="5173"
+                ></path>
+                <path
+                  d="M703.5 320h-384c-17.7 0-32-14.3-32-32s14.3-32 32-32h384c17.7 0 32 14.3 32 32s-14.3 32-32 32zM703.5 512h-384c-17.7 0-32-14.3-32-32s14.3-32 32-32h384c17.7 0 32 14.3 32 32s-14.3 32-32 32zM511.5 704h-192c-17.7 0-32-14.3-32-32s14.3-32 32-32h192c17.7 0 32 14.3 32 32s-14.3 32-32 32z"
+                  p-id="5174"
+                ></path>
+              </svg>
+
+              <span>{{ uploadTemplateDocxData.name }}</span>
+              <span class="d_b_s_f_c_del" @click="clearUploadTemplateDocxData()"
+                >删除</span
+              >
+            </div>
+            <el-button
+              class="d_b_s_button"
+              type="primary"
+              :disabled="uploadTemplateDocxData != null"
+              @click="uploadTemplateDocx()"
+              >上传填入后的模板文档</el-button
+            >
+          </div>
+
+          <div class="d_b_step">
+            <h2>第四步:点击导出</h2>
+            <p></p>
+            <el-button
+              class="d_b_s_button"
+              type="primary"
+              :disabled="!uploadTemplateDocxData"
+              @click="exportDocx()"
+              >导出Word文档</el-button
+            >
+          </div>
+        </div>
+      </div>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import PizZip from "pizzip";
+import Docxtemplater from "docxtemplater";
+import ImageModule from "docxtemplater-image-module-free";
+import { saveAs } from 'file-saver';
+
+const getFile = url => {
+  return new Promise((resolve, reject) => {
+    var credentials = {
+      accessKeyId: "AKIATLPEDU37QV5CHLMH",
+      secretAccessKey: "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"
+    }; //秘钥形式的登录上传
+    window.AWS.config.update(credentials);
+    window.AWS.config.region = "cn-northwest-1"; //设置区域
+    let url2 = url;
+    let _url2 = "";
+    if (
+      url2.indexOf("https://view.officeapps.live.com/op/view.aspx?src=") != -1
+    ) {
+      _url2 = url2.split(
+        "https://view.officeapps.live.com/op/view.aspx?src="
+      )[1];
+    } else {
+      _url2 = url2;
+    }
+    var s3 = new window.AWS.S3({ params: { Bucket: "ccrb" } });
+    let name = decodeURIComponent(
+      _url2.split("https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/")[1]
+    );
+    var params = {
+      Bucket: "ccrb",
+      Key: name
+    };
+    s3.getObject(params, function(err, data) {
+      if (err) {
+        console.log(err, err.stack);
+        resolve({ data: 1 });
+      } else {
+        resolve({ data: data.Body });
+        console.log(data);
+      }
+    });
+  });
+};
+
+export default {
+  props: {},
+  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"
+        }
+      ],
+      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
+    };
+  },
+  methods: {
+    handleClose(done) {
+      this.close();
+      done();
+    },
+    open() {
+      this.show = true;
+    },
+    close() {
+      this.show = false;
+    },
+    init() {
+      // 初始化
+    },
+    downloadTemplateDocx() {
+      getFile(this.downFileData.url).then(data => {
+        if (data.data != 1) {
+          // 下载文件, 并存成ArrayBuffer对象
+          const file_name = this.downFileData.fileName; // 获取文件名
+          const file_data = data.data; // 获取文件数据
+          let url = window.URL.createObjectURL(new Blob([file_data]));
+          let a = document.createElement("a");
+          a.name = file_name;
+          a.href = url;
+          a.download = file_name;
+          a.click();
+          console.log(data);
+          this.$message.success("下载成功");
+        } else {
+          this.$message.error("下载失败");
+        }
+      });
+    },
+    uploadTemplateDocx() {
+      let input = document.createElement("input");
+      input.type = "file";
+      // input.accept = ".wav";
+      // input.accept = "audio/*, .txt, .pdf, .xlsx";
+      input.accept = ".docx";
+      input.click();
+      input.onchange = () => {
+        this.loading = true;
+        let file = input.files[0];
+        if (!/\.(docx)$/i.test(file.name)) {
+          this.loading = false;
+          return this.$message.error("请上传.docx格式的文件");
+        }
+        console.log(file);
+        this.uploadTemplateDocxData = file;
+        this.loading = false;
+        // this.uploadWavFileAndGetText(file);
+      };
+    },
+    async exportDocx() {
+      if (!this.uploadTemplateDocxData)
+        return this.$message.error("请先上传模板文档");
+      let reader = new FileReader();
+      reader.readAsArrayBuffer(this.uploadTemplateDocxData);
+      reader.onload = async e => {
+        try {
+          this.loading = true;
+          const binary = new Uint8Array(reader.result);
+          //创建一个PizZip实例
+          const zip = new PizZip(binary);
+          // 将模板内容加载到 Docxtemplater 中
+          const doc = new Docxtemplater().loadZip(zip);
+
+          let _data = {};
+          let _image = {};
+          // 设置模板值
+          // this.fieldList.forEach(i => {
+          //   _data[i.field] = i.value;
+          // });
+          for (let i = 0; i < this.fieldList.length; i++) {
+						// console.log(this.fieldList[i])
+            if (this.fieldList[i].type == "text") {
+              //文本处理
+              _data[this.fieldList[i].field] = this.fieldList[i].value;
+            } else if (this.fieldList[i].type == "image") {
+              //图片处理
+              let _imageObj = await this.convertImageUrlToBase64(
+                this.fieldList[i].value
+              );
+              _data[this.fieldList[i].field] = _imageObj.url;
+              _image[this.fieldList[i].field] = {
+                width: _imageObj.width,
+                height: _imageObj.height
+              };
+            }
+          }
+					// return this.loading = false;
+
+          // 图片处理
+          const opts = {
+            centered: false,
+            fileType: "docx",
+            getImage: (value, value2, value3) => {
+              return this.base64DataURLToArrayBuffer(value);
+            },
+            getSize: (arrayValue, value, tagName) => {
+							// console.log(_image)
+							// console.log(tagName)
+              let newWidth = _image[tagName].width;
+              let newHeight = _image[tagName].height;
+
+							// let newWidth = 550;
+              // let newHeight = 100;
+              return [newWidth, newHeight];
+            }
+          };
+					doc.attachModule(new ImageModule(opts));
+          //渲染模板
+          doc.setData(_data);
+          doc.render();
+          //获取渲染后的文本
+          const output = doc.getZip().generate({
+            type: "blob",
+            mimeType:
+              "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
+            compression: "DEFLATE"
+          });
+
+					saveAs(output,`${this.uploadTemplateDocxData.name}`)
+          // let link = document.createElement("a");
+          // link.download = this.uploadTemplateDocxData.name;
+          // link.style.display = "none";
+          // let blob = new Blob([output]);
+          // link.href = URL.createObjectURL(blob);
+          // document.body.appendChild(link);
+          // link.click();
+          // document.body.removeChild(link);
+          this.loading = false;
+          this.$message.success("导出成功");
+        } catch (error) {
+          console.log(error);
+          this.loading = false;
+          return this.$message.error("导出失败");
+        }
+      };
+    },
+    clearUploadTemplateDocxData() {
+      this.uploadTemplateDocxData = null;
+    },
+    copyContent(content) {
+      const input = document.createElement("input");
+      // 设置 display为none会导致无法复制
+      // input.style.display = "none";
+      // 所以只能用其他方法隐藏
+      input.style.opacity = 0;
+      // 为了不影响布局
+      input.style.position = "fixed";
+      input.style.left = "-100%";
+      input.style.top = "-100%";
+      input.value = content;
+      document.body.appendChild(input);
+      input.select();
+      const success = document.execCommand("copy");
+      document.body.removeChild(input);
+      if (!success) {
+        return this.$message.error("复制失败");
+      } else {
+        return this.$message.success("复制成功");
+      }
+    },
+    convertImageUrlToBase64(imageUrl) {
+      return new Promise((resolve, reject) => {
+        const img = new Image();
+        img.crossOrigin = "Anonymous"; // 允许跨域请求
+        img.src = imageUrl;
+
+        img.onload = () => {
+          const canvas = document.createElement("canvas");
+          canvas.width = img.width;
+          canvas.height = img.height;
+          const ctx = canvas.getContext("2d");
+          ctx.drawImage(img, 0, 0);
+          const base64 = canvas.toDataURL("image/png");
+          resolve({ url: base64, width: img.width, height: img.height });
+        };
+
+        img.onerror = error => {
+					console.log("图片转base64失败")
+					console.log(error)
+          resolve({url:"",width:0,height:0});
+        };
+      });
+    },
+    base64DataURLToArrayBuffer(dataURL) {
+      const base64Regex = /^data:image\/(png|jpg|svg|svg\+xml);base64,/;
+      if (!base64Regex.test(dataURL)) {
+        return false;
+      }
+      const stringBase64 = dataURL.replace(base64Regex, "");
+      let binaryString;
+      if (typeof window !== "undefined") {
+        binaryString = window.atob(stringBase64);
+      } else {
+        binaryString = new Buffer(stringBase64, "base64").toString("binary");
+      }
+      const len = binaryString.length;
+      const bytes = new Uint8Array(len);
+      for (let i = 0; i < len; i++) {
+        const ascii = binaryString.charCodeAt(i);
+        bytes[i] = ascii;
+      }
+      return bytes.buffer;
+    }
+  }
+};
+</script>
+
+<style scoped>
+.dialog_diy >>> .el-dialog {
+  /* height: 100%; */
+  /* margin: 0 auto !important; */
+}
+
+.dialog_diy >>> .el-dialog__header {
+  background: #fff !important;
+  padding: 15px 20px;
+}
+
+.dialog_diy >>> .el-dialog__body {
+  height: calc(100% - 124px);
+  box-sizing: border-box;
+  padding: 0px;
+}
+
+.dialog_diy >>> .el-dialog__title {
+  color: #000;
+}
+
+.dialog_diy >>> .el-dialog__headerbtn {
+  top: 19px;
+}
+
+.dialog_diy >>> .el-dialog__headerbtn .el-dialog__close {
+  color: #000;
+}
+
+.dialog_diy >>> .el-dialog__headerbtn .el-dialog__close:hover {
+  color: #000;
+}
+
+.dialog_diy >>> .el-dialog__body,
+.dialog_diy >>> .el-dialog__footer {
+  background: #fff;
+}
+
+.box {
+  width: 100%;
+  height: 70vh;
+  padding: 0 20px 15px;
+  display: flex;
+  box-sizing: border-box;
+}
+
+.b_left {
+  width: 400px;
+  height: 100%;
+}
+
+.b_right {
+  flex: 1;
+  height: 100%;
+}
+
+.d_box {
+  width: 100%;
+  height: 100%;
+  overflow: auto;
+}
+
+.d_b_step {
+  width: 100%;
+  max-width: 100%;
+  height: auto;
+  padding: 20px;
+  box-sizing: border-box;
+  /* background-color: red; */
+}
+
+.d_b_step > h2 {
+  margin-bottom: 10px;
+}
+
+.d_b_step > p {
+  font-size: 16px;
+}
+
+.d_b_step > img {
+  width: 100%;
+  margin-top: 10px;
+}
+
+.d_b_s_button {
+  margin-top: 10px;
+}
+
+.d_b_s_fieldListItem {
+  margin-top: 15px;
+  font-size: 16px;
+  display: flex;
+  align-items: center;
+}
+
+.d_b_s_fieldListItem > span {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.d_b_s_fieldListItem > span > svg {
+  width: 15px;
+  height: 15px;
+  cursor: pointer;
+  fill: #000;
+  margin-left: 10px;
+  transition: 0.3s;
+  fill-opacity: 0.6;
+}
+
+.d_b_s_fieldListItem > span > svg:hover {
+  fill: #409eff;
+  fill-opacity: 1;
+}
+
+.d_b_s_fileCard {
+  width: 100%;
+  height: 45px;
+  border-radius: 2px;
+  margin-bottom: 10px;
+  display: flex;
+  align-items: center;
+  box-sizing: border-box;
+  padding: 0 10px;
+  border: solid 1px #dfdfdf;
+  position: relative;
+  cursor: default;
+}
+
+.d_b_s_fileCard > svg {
+  width: 30px;
+  height: 30px;
+  fill: #a3a8ac;
+  margin-right: 10px;
+}
+
+.d_b_s_fileCard > span {
+  max-width: calc(100% - 100px);
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  font-size: 16px;
+}
+
+.d_b_s_f_c_del {
+  position: absolute;
+  right: 10px;
+  cursor: pointer;
+  color: #e60012;
+}
+</style>

+ 12 - 1
src/components/pages/test/check/index.vue

@@ -633,6 +633,7 @@
                 <template slot-scope="scope">
                   <el-button @click="getTest(scope.row)" type="primary" size="small">查看</el-button>
                   <el-button @click="setWordHtml(scope.row)" type="primary" size="small">导出答题信息</el-button>
+									<!-- <el-button @click="setWordTemplate(scope.row)" type="primary" size="small">word导出</el-button> -->
                   <el-button @click="deleteTest(scope.row.id)" type="primary" size="small">删除</el-button>
                 </template>
               </el-table-column>
@@ -893,6 +894,8 @@
     <wpdf :dialogVisiblePdf.sync="dialogVisiblePdf" :url="wurl"></wpdf>
     <wVideo :dialogVisibleVideo.sync="dialogVisibleVideo" :url="wurl"></wVideo>
     <wOffice :dialogVisibleOffice.sync="dialogVisibleOffice" :url="wurl"></wOffice>
+
+		<docxTemplateDialog ref="docxTemplateDialogRef"/>
   </div>
 </template>
 
@@ -916,6 +919,9 @@ import FileSaver from "file-saver";
 import XLSX from "xlsx-js-style";
 import aiBoxRight from './aiBoxRight.vue'
 
+// word模板
+import docxTemplateDialog from './docxTemplateDialog' 
+
 const getFile = (url) => {
     return new Promise((resolve, reject) => {
         var credentials = {
@@ -963,7 +969,8 @@ export default {
     wOffice,
     checkPie,
     wordcloud,
-    aiBoxRight
+    aiBoxRight,
+		docxTemplateDialog
   },
   data() {
     return {
@@ -2326,6 +2333,10 @@ export default {
           console.error(err);
         });
     },
+		setWordTemplate(item){
+			this.$refs.docxTemplateDialogRef.open()//这里可以传数据
+			// console.log(item)
+		}
   },
   beforeDestroy() {
     document.getElementsByTagName('html')[0].style.overflow = '';

+ 3 - 2
src/components/pages/works.vue

@@ -1105,10 +1105,11 @@ export default {
 }
 
 .worksDialogCSSExp >>> .el-dialog__body {
-  width: 635px !important;
+  width: 100% !important;
+  padding: 0 !important;
 }
 .worksDialogCSSExp >>> .el-dialog {
-  width: 676px !important;
+  width: 594pt !important;
 }
 /* .TableCss >>> .el-table-column--selection .cell{
   display: none;

Деякі файли не було показано, через те що забагато файлів було змінено