Selaa lähdekoodia

Merge branch 'beta' into HK

lsc 1 vuosi sitten
vanhempi
commit
ab7a679a47
56 muutettua tiedostoa jossa 5149 lisäystä ja 1972 poistoa
  1. 0 0
      dist/69aa1a632fa75fd4d2e4.worker.js
  2. 0 0
      dist/69aa1a632fa75fd4d2e4.worker.js.map
  3. 7 2
      dist/index.html
  4. 0 0
      dist/static/css/app.39bac6ead33d50f3ff3ae1405004738a.css
  5. 0 0
      dist/static/css/app.39bac6ead33d50f3ff3ae1405004738a.css.map
  6. BIN
      dist/static/img/aiAvatar.237f433.png
  7. BIN
      dist/static/img/tapetime.2f06a0a.png
  8. 1 0
      dist/static/js/app.4be4ccbb336f7bd8ba5f.js
  9. 1 0
      dist/static/js/app.4be4ccbb336f7bd8ba5f.js.map
  10. 1 0
      dist/static/js/app.e49c65a09ce9c7d87277.js
  11. 0 0
      dist/static/js/app.e49c65a09ce9c7d87277.js.map
  12. 0 0
      dist/static/js/manifest.6c4ea0d95d82bb3e7d94.js.map
  13. 0 0
      dist/static/js/vendor.3cd0a0187ca1f70ded67.js
  14. 1 0
      dist/static/js/vendor.3cd0a0187ca1f70ded67.js.map
  15. 0 0
      dist/static/js/vendor.4e92b9786542a979bd57.js
  16. 0 0
      dist/static/js/vendor.4e92b9786542a979bd57.js.map
  17. 3 3
      index.html
  18. 107 0
      package-lock.json
  19. 1 0
      package.json
  20. BIN
      src/assets/icon/classroomObservation/aiAvatar.png
  21. BIN
      src/assets/icon/classroomObservation/isTape.png
  22. BIN
      src/assets/icon/classroomObservation/start.png
  23. 6 0
      src/assets/icon/course/copy.svg
  24. 6 0
      src/assets/icon/course/del.svg
  25. 6 0
      src/assets/icon/course/edit.svg
  26. 6 0
      src/assets/icon/course/lookeye.svg
  27. 6 0
      src/assets/icon/course/share.svg
  28. 1 1
      src/common/axios.config.js
  29. 29 17
      src/components/pages/EnglishVoice/component/component/testRole.vue
  30. 6 4
      src/components/pages/EnglishVoice/index.vue
  31. 19 14
      src/components/pages/addCourse.vue
  32. 177 161
      src/components/pages/aiAddCourse/addCourse.vue
  33. 716 450
      src/components/pages/aiAddCourse/aiBox.vue
  34. 158 0
      src/components/pages/aiAddCourse/aiDialog.vue
  35. 63 0
      src/components/pages/classroomObservation/components/addNewCourseDialog.vue
  36. 56 29
      src/components/pages/classroomObservation/components/analysis.vue
  37. 176 181
      src/components/pages/classroomObservation/components/analysisItem.vue
  38. 123 17
      src/components/pages/classroomObservation/components/baseMessage.vue
  39. 1132 245
      src/components/pages/classroomObservation/components/chatArea.vue
  40. 4 0
      src/components/pages/classroomObservation/components/mdView.vue
  41. 433 289
      src/components/pages/classroomObservation/components/messageArea.vue
  42. 325 0
      src/components/pages/classroomObservation/components/sharePdf.vue
  43. 351 478
      src/components/pages/classroomObservation/components/tape.vue
  44. 7 4
      src/components/pages/classroomObservation/components/transcription.vue
  45. 326 0
      src/components/pages/classroomObservation/components/wangEnduit.vue
  46. 283 39
      src/components/pages/classroomObservation/index.vue
  47. 100 14
      src/components/pages/course.vue
  48. 2 2
      src/components/pages/data.vue
  49. 477 0
      src/components/pages/dialog/shareDialog.vue
  50. 3 0
      src/components/pages/easy/addCourse.vue
  51. 24 16
      src/components/pages/newCourse/addCourse.vue
  52. 1 1
      src/components/pages/student/addCourse.vue
  53. 1 1
      src/components/pages/student/addCourseJiu.vue
  54. 1 1
      src/components/pages/studentManage/class.vue
  55. 1 1
      src/components/pages/studio/addCourse.vue
  56. 2 2
      src/components/pages/tencent/data.vue

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/69aa1a632fa75fd4d2e4.worker.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/69aa1a632fa75fd4d2e4.worker.js.map


+ 7 - 2
dist/index.html

@@ -1,10 +1,10 @@
 <!DOCTYPE html><html><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>PBL教师端</title><link rel="shortcut icon" type=image/x-icon href=static/logo.ico><style>@charset "utf-8";
-    @font-face {
+    /* @font-face {
         font-family: 'Source Han Sans SC';
         src: url('./static/SourceHanSans-Regular.otf') format('truetype');
         font-weight: normal;
         font-style: normal;
-      }
+      } */
 
     div::-webkit-scrollbar {
       /*滚动条整体样式*/
@@ -31,8 +31,13 @@
       height: 100%;
       width: 100%;
       background: #e6eaf0;
+<<<<<<< HEAD
       font-family: 'Source Han Sans SC', sans-serif;
     }</style><link href=./static/css/app.86fc69a2fb2da822170862028b96f55f.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=./static/js/manifest.6c4ea0d95d82bb3e7d94.js></script><script type=text/javascript src=./static/js/vendor.4e92b9786542a979bd57.js></script><script type=text/javascript src=./static/js/app.e49c65a09ce9c7d87277.js></script></body></html><script>function stopSafari() {
+=======
+      font-family: '黑体';
+    }</style><link href=./static/css/app.39bac6ead33d50f3ff3ae1405004738a.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.3cd0a0187ca1f70ded67.js></script><script type=text/javascript src=./static/js/app.4be4ccbb336f7bd8ba5f.js></script></body></html><script>function stopSafari() {
+>>>>>>> beta
     //阻止safari浏览器双击放大功能
     let lastTouchEnd = 0  //更新手指弹起的时间
     document.documentElement.addEventListener("touchstart", function (event) {

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/static/css/app.39bac6ead33d50f3ff3ae1405004738a.css


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/static/css/app.39bac6ead33d50f3ff3ae1405004738a.css.map


BIN
dist/static/img/aiAvatar.237f433.png


BIN
dist/static/img/tapetime.2f06a0a.png


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 0
dist/static/js/app.4be4ccbb336f7bd8ba5f.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 0
dist/static/js/app.4be4ccbb336f7bd8ba5f.js.map


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 0
dist/static/js/app.e49c65a09ce9c7d87277.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/static/js/app.e49c65a09ce9c7d87277.js.map


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/static/js/manifest.6c4ea0d95d82bb3e7d94.js.map


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/static/js/vendor.3cd0a0187ca1f70ded67.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 0
dist/static/js/vendor.3cd0a0187ca1f70ded67.js.map


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/static/js/vendor.4e92b9786542a979bd57.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
dist/static/js/vendor.4e92b9786542a979bd57.js.map


+ 3 - 3
index.html

@@ -8,12 +8,12 @@
   <link rel="shortcut icon" type="image/x-icon" href="static/logo.ico">
   <style>
     @charset "utf-8";
-    @font-face {
+    /* @font-face {
         font-family: 'Source Han Sans SC';
         src: url('./static/SourceHanSans-Regular.otf') format('truetype');
         font-weight: normal;
         font-style: normal;
-      }
+      } */
 
     div::-webkit-scrollbar {
       /*滚动条整体样式*/
@@ -40,7 +40,7 @@
       height: 100%;
       width: 100%;
       background: #e6eaf0;
-      font-family: 'Source Han Sans SC', sans-serif;
+      font-family: '黑体';
     }
   </style>
 </head>

+ 107 - 0
package-lock.json

@@ -32,6 +32,7 @@
         "jszip": "^3.10.1",
         "lamejs": "^1.2.1",
         "language-hk-loader": "^1.0.1",
+        "markdown-it": "^14.1.0",
         "pdfjs-dist": "^2.5.207",
         "qrcodejs2": "^0.0.2",
         "qs": "^6.10.1",
@@ -8151,6 +8152,14 @@
         "immediate": "~3.0.5"
       }
     },
+    "node_modules/linkify-it": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz",
+      "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==",
+      "dependencies": {
+        "uc.micro": "^2.0.0"
+      }
+    },
     "node_modules/load-json-file": {
       "version": "2.0.0",
       "resolved": "https://registry.npm.taobao.org/load-json-file/download/load-json-file-2.0.0.tgz",
@@ -8633,6 +8642,22 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/markdown-it": {
+      "version": "14.1.0",
+      "resolved": "https://registry.npmmirror.com/markdown-it/-/markdown-it-14.1.0.tgz",
+      "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==",
+      "dependencies": {
+        "argparse": "^2.0.1",
+        "entities": "^4.4.0",
+        "linkify-it": "^5.0.0",
+        "mdurl": "^2.0.0",
+        "punycode.js": "^2.3.1",
+        "uc.micro": "^2.1.0"
+      },
+      "bin": {
+        "markdown-it": "bin/markdown-it.mjs"
+      }
+    },
     "node_modules/markdown-it-abbr": {
       "version": "1.0.4",
       "resolved": "https://registry.npmmirror.com/markdown-it-abbr/-/markdown-it-abbr-1.0.4.tgz",
@@ -8703,6 +8728,22 @@
         "node": ">=0.8"
       }
     },
+    "node_modules/markdown-it/node_modules/argparse": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+      "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
+    },
+    "node_modules/markdown-it/node_modules/entities": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+      "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+      "engines": {
+        "node": ">=0.12"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/entities?sponsor=1"
+      }
+    },
     "node_modules/match-at": {
       "version": "0.1.1",
       "resolved": "https://registry.npmmirror.com/match-at/-/match-at-0.1.1.tgz",
@@ -8730,6 +8771,11 @@
       "integrity": "sha1-aZs8OKxvHXKAkaZGULZdOIUC/Vs=",
       "dev": true
     },
+    "node_modules/mdurl": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz",
+      "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w=="
+    },
     "node_modules/media-typer": {
       "version": "0.3.0",
       "resolved": "https://registry.npm.taobao.org/media-typer/download/media-typer-0.3.0.tgz",
@@ -14007,6 +14053,14 @@
         "node": ">=6"
       }
     },
+    "node_modules/punycode.js": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz",
+      "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==",
+      "engines": {
+        "node": ">=6"
+      }
+    },
     "node_modules/q": {
       "version": "1.5.1",
       "resolved": "https://registry.npm.taobao.org/q/download/q-1.5.1.tgz",
@@ -16298,6 +16352,11 @@
       "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==",
       "dev": true
     },
+    "node_modules/uc.micro": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz",
+      "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A=="
+    },
     "node_modules/uglify-js": {
       "version": "3.4.10",
       "resolved": "https://registry.npm.taobao.org/uglify-js/download/uglify-js-3.4.10.tgz?cache=0&sync_timestamp=1614626121570&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fuglify-js%2Fdownload%2Fuglify-js-3.4.10.tgz",
@@ -25644,6 +25703,14 @@
         "immediate": "~3.0.5"
       }
     },
+    "linkify-it": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz",
+      "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==",
+      "requires": {
+        "uc.micro": "^2.0.0"
+      }
+    },
     "load-json-file": {
       "version": "2.0.0",
       "resolved": "https://registry.npm.taobao.org/load-json-file/download/load-json-file-2.0.0.tgz",
@@ -26060,6 +26127,31 @@
         "object-visit": "^1.0.0"
       }
     },
+    "markdown-it": {
+      "version": "14.1.0",
+      "resolved": "https://registry.npmmirror.com/markdown-it/-/markdown-it-14.1.0.tgz",
+      "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==",
+      "requires": {
+        "argparse": "^2.0.1",
+        "entities": "^4.4.0",
+        "linkify-it": "^5.0.0",
+        "mdurl": "^2.0.0",
+        "punycode.js": "^2.3.1",
+        "uc.micro": "^2.1.0"
+      },
+      "dependencies": {
+        "argparse": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+          "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
+        },
+        "entities": {
+          "version": "4.5.0",
+          "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+          "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="
+        }
+      }
+    },
     "markdown-it-abbr": {
       "version": "1.0.4",
       "resolved": "https://registry.npmmirror.com/markdown-it-abbr/-/markdown-it-abbr-1.0.4.tgz",
@@ -26156,6 +26248,11 @@
       "integrity": "sha1-aZs8OKxvHXKAkaZGULZdOIUC/Vs=",
       "dev": true
     },
+    "mdurl": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz",
+      "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w=="
+    },
     "media-typer": {
       "version": "0.3.0",
       "resolved": "https://registry.npm.taobao.org/media-typer/download/media-typer-0.3.0.tgz",
@@ -30438,6 +30535,11 @@
       "resolved": "https://registry.npm.taobao.org/punycode/download/punycode-2.1.1.tgz",
       "integrity": "sha1-tYsBCsQMIsVldhbI0sLALHv0eew="
     },
+    "punycode.js": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz",
+      "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA=="
+    },
     "q": {
       "version": "1.5.1",
       "resolved": "https://registry.npm.taobao.org/q/download/q-1.5.1.tgz",
@@ -32338,6 +32440,11 @@
       "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==",
       "dev": true
     },
+    "uc.micro": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz",
+      "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A=="
+    },
     "uglify-js": {
       "version": "3.4.10",
       "resolved": "https://registry.npm.taobao.org/uglify-js/download/uglify-js-3.4.10.tgz?cache=0&sync_timestamp=1614626121570&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fuglify-js%2Fdownload%2Fuglify-js-3.4.10.tgz",

+ 1 - 0
package.json

@@ -34,6 +34,7 @@
     "jszip": "^3.10.1",
     "lamejs": "^1.2.1",
     "language-hk-loader": "^1.0.1",
+    "markdown-it": "^14.1.0",
     "pdfjs-dist": "^2.5.207",
     "qrcodejs2": "^0.0.2",
     "qs": "^6.10.1",

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


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


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


+ 6 - 0
src/assets/icon/course/copy.svg

@@ -0,0 +1,6 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32" width="24" height="24" style="" filter="none">
+    
+    <g>
+    <path d="M9.333 8v-4c0-0.736 0.597-1.333 1.333-1.333v0h16c0.736 0 1.333 0.597 1.333 1.333v0 18.667c0 0.736-0.597 1.333-1.333 1.333v0h-4v4c0 0.736-0.6 1.333-1.343 1.333h-15.981c-0.002 0-0.005 0-0.008 0-0.737 0-1.334-0.597-1.335-1.333v-0l0.004-18.667c0-0.736 0.6-1.333 1.343-1.333h3.987zM6.671 10.667l-0.004 16h13.333v-16h-13.329zM12 8h10.667v13.333h2.667v-16h-13.333v2.667z" fill="rgba(79,79,79,1)"></path>
+    </g>
+  </svg>

+ 6 - 0
src/assets/icon/course/del.svg

@@ -0,0 +1,6 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32" width="24" height="24" style="" filter="none">
+    
+    <g>
+    <path d="M22.129 5.301l-1.614-3.687h-8.758l-1.614 3.687h-7.837v2.305h2.766v22.822h22.358v-22.823h2.536v-2.304h-7.837zM12.909 3.918h5.992l0.691 1.384h-7.146l0.462-1.38zM24.895 28.121h-17.749v-20.515h17.749v20.515zM9.451 11.526h2.305v13.138h-2.305zM14.752 11.526h2.305v13.138h-2.305zM20.285 11.526h2.305v13.138h-2.305z" fill="rgba(79,79,79,1)"></path>
+    </g>
+  </svg>

+ 6 - 0
src/assets/icon/course/edit.svg

@@ -0,0 +1,6 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="64 64 896 896" width="24" height="24" style="" filter="none">
+    
+    <g>
+    <path d="M257.7 752c2 0 4-.2 6-.5L431.9 722c2-.4 3.9-1.3 5.3-2.8l423.9-423.9a9.96 9.96 0 0 0 0-14.1L694.9 114.9c-1.9-1.9-4.4-2.9-7.1-2.9s-5.2 1-7.1 2.9L256.8 538.8c-1.5 1.5-2.4 3.3-2.8 5.3l-29.5 168.2a33.5 33.5 0 0 0 9.4 29.8c6.6 6.4 14.9 9.9 23.8 9.9zm67.4-174.4L687.8 215l73.3 73.3-362.7 362.6-88.9 15.7 15.6-89zM880 836H144c-17.7 0-32 14.3-32 32v36c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-36c0-17.7-14.3-32-32-32z" fill="rgba(79,79,79,1)"></path>
+    </g>
+  </svg>

+ 6 - 0
src/assets/icon/course/lookeye.svg

@@ -0,0 +1,6 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 48 48" width="24" height="24" style="" filter="none">
+    
+    <g>
+    <path fill-rule="evenodd" clip-rule="evenodd" d="M24 37C30.6274 37 36.6274 32.6667 42 24C36.6274 15.3333 30.6274 11 24 11C17.3726 11 11.3726 15.3333 6 24C11.3726 32.6667 17.3726 37 24 37Z" stroke="rgba(79,79,79,1)" stroke-width="4" fill="none"></path><path d="M29 24C29 26.7614 26.7614 29 24 29C21.2386 29 19 26.7614 19 24C19 21.2386 21.2386 19 24 19C26.7614 19 29 21.2386 29 24Z" stroke="rgba(79,79,79,1)" stroke-width="4" fill="none"></path>
+    </g>
+  </svg>

+ 6 - 0
src/assets/icon/course/share.svg

@@ -0,0 +1,6 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32" width="24" height="24" style="" filter="none">
+    
+    <g>
+    <path d="M13.333 4v2.667h-6.667v18.667h18.667v-6.667h2.667v8c0 0.736-0.597 1.333-1.333 1.333v0h-21.333c-0.736 0-1.333-0.597-1.333-1.333v0-21.333c0-0.736 0.597-1.333 1.333-1.333v0h8zM23.448 6.667h-6.115v-2.667h10.667v10.667h-2.667v-6.115l-9.333 9.333-1.885-1.885 9.333-9.333z" fill="rgba(79,79,79,1)"></path>
+    </g>
+  </svg>

+ 1 - 1
src/common/axios.config.js

@@ -1,6 +1,6 @@
 import axios from "axios"
 import qs from "qs"
-axios.defaults.timeout = 90000   //响应时间
+axios.defaults.timeout = 180000   //响应时间
 axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';        //配置请求头
 axios.defaults.baseURL = process.env.NODE_HOST;   //配置接口地址
 console.log(process.env)

+ 29 - 17
src/components/pages/EnglishVoice/component/component/testRole.vue

@@ -113,24 +113,36 @@ export default {
         },
         answerCode(msg) {
             var _this = this;
-            _this.ajax.post('https://gpt4.cocorobo.cn/assistants_completion_response', {
-                uid: _this.id,
-                message: msg,
-            }).then(function (response) {
-                console.log(response);
+            if(msg){
+                _this.ajax.post('https://gpt4.cocorobo.cn/assistants_completion_response', {
+                    uid: _this.id,
+                    message: msg,
+                }).then(function (response) {
+                    console.log(response);
+                    _this.answerArray.push(
+                        {
+                            isY: false,
+                            content: response.data.FunctionResponse,
+                            name: _this.answerArray[0].name,
+                            img: _this.answerArray[0].img
+                        }
+                    )
+                    _this.isloading = false
+                }).catch(function (error) {
+                    _this.isloading = false
+                    console.log(error);
+                });
+            }else{
                 _this.answerArray.push(
-                    {
-                        isY: false,
-                        content: response.data.FunctionResponse,
-                        name: _this.answerArray[0].name,
-                        img: _this.answerArray[0].img
-                    }
-                )
-                _this.isloading = false
-            }).catch(function (error) {
-                _this.isloading = false
-                console.log(error);
-            });
+                        {
+                            isY: false,
+                            content: "抱歉,您刚刚没有成功录入内容,请再说一遍!",
+                            name: _this.answerArray[0].name,
+                            img: _this.answerArray[0].img
+                        }
+                    )
+                    _this.isloading = false
+            }
         },
         // 开始录音
         startRecorder() {

+ 6 - 4
src/components/pages/EnglishVoice/index.vue

@@ -71,10 +71,11 @@ export default {
     },
     methods: {
         handleClose(done) {
-            this.close();
-            done();
+            this.close(()=>{
+                done();
+            });
         },
-        close() {
+        close(callback) {
             let a = {
                 title: this.title,
                 detail: this.detail,
@@ -94,6 +95,7 @@ export default {
                     })
                     .catch(() => {
                         this.$emit("update:EnglishVoiceDialog", false);
+                        callback ? callback() : '';
                     });
             }
         },
@@ -162,7 +164,7 @@ export default {
             this.checkJson2 = JSON.parse(JSON.stringify(a));
             this.title = a.title;
             this.detail = a.detail;
-            this.checkJson = a.array
+            this.checkJson = a.array ? a.array : []
             this.checkType = -1
         }
     },

+ 19 - 14
src/components/pages/addCourse.vue

@@ -11258,20 +11258,25 @@ export default {
                 ].toolChoose[toolIndex].englishVoiceJson
               )
             )
-          : {
-              time: "",
-              class: "",
-              difficulty: 0,
-              topic: "",
-              isShow: false,
-              eva: 0,
-              aiEva: {
-                isAiEva: false,
-                aiEvaChoose: [],
-              },
-              allfType: [],
-              englishJson: {},
-            };
+          : { 
+            title:'',
+            detail:'',
+            array:[]
+           };
+          //  {
+          //     time: "",
+          //     class: "",
+          //     difficulty: 0,
+          //     topic: "",
+          //     isShow: false,
+          //     eva: 0,
+          //     aiEva: {
+          //       isAiEva: false,
+          //       aiEvaChoose: [],
+          //     },
+          //     allfType: [],
+          //     englishJson: {},
+          //   };
         this.$forceUpdate();
         this.EnglishVoiceDialog = true;
       }

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 177 - 161
src/components/pages/aiAddCourse/addCourse.vue


+ 716 - 450
src/components/pages/aiAddCourse/aiBox.vue

@@ -1,547 +1,813 @@
 <template>
-    <div class="ai_body" v-loading="loading">
-        <div class="ai_body_dialog">
-            <div class="dialog_content" :class="{ right: item.role == 2 }" v-for="(item, index) in array" :key="index">
-                <div class="role">
-                    <img src="../../../assets/icon/new/role1.png" v-if="item.role == 1">
-                    <img src="../../../assets/icon/new/role2.png" v-else>
-                </div>
-                <div class="content" :class="{ content2: item.role == 2 }">{{ item.text }}</div>
-            </div>
+  <div class="ai_body">
+    <div class="ai_body_dialog" v-loading="loading" ref="chatDialog">
+      <div
+        class="dialog_content"
+        v-for="(item, index) in array"
+        :key="item.uid"
+      >
+        <div v-if="item.content">
+          <div class="content content2" v-html="item.content"></div>
+          <div class="role">
+            <img src="../../../assets/icon/new/role2.png" />
+          </div>
+        </div>
+        <div style="margin-top:10px ;">
+          <div class="role">
+            <img src="../../../assets/icon/new/role1.png" />
+          </div>
+          <div
+            class="content"
+            v-loading="item.loading"
+            v-html="item.aiContent"
+          ></div>
+        </div>
+        <!-- <div class="role">
+          <img src="../../../assets/icon/new/role1.png"/>
+          <img src="../../../assets/icon/new/role2.png"/>
+        </div>
+        <div class="content content2" :class="{ content2: item.role == 2 }">
+          {{ item.text }}
         </div>
-        <div class="ai_body_select">
-            <div class="checkBox" v-if="checkBool">
-                <div class="task">
-                    <div class="title">选择需要优化的任务:</div>
-                    <div class="content">
-                        <div class="span" @click="addAllTask()">
-                            <div class="check">
-                                <img :src="checkImg" alt="" v-if="checkArray.length !== course.length">
-                                <img :src="checkIsImg" alt="" v-else>
-                            </div>
-                            <span>全选</span>
-                        </div>
-                        <div class="span" v-for="(item, index) in course" :key="index" @click="addTask(index)">
-                            <div class="check">
-                                <img :src="checkImg" alt="" v-if="checkArray.indexOf(index) === -1">
-                                <img :src="checkIsImg" alt="" v-else>
-                            </div>
-                            <span>任务{{ index + 1 }}</span>
-                        </div>
-                    </div>
-                </div>
-                <div class="part">
-                    <div class="title">选择优化的部分:</div>
-                    <div class="content">
-                        <div class="span" v-for="(item, index) in partArray" :key="index"
-                            :class="{ active: part == item.name }" @click="checkPart(item.name)">
-                            {{ item.name }}
-                        </div>
-                    </div>
-                </div>
+				<div class="role">
+          <img src="../../../assets/icon/new/role1.png"/>
+        </div>
+        <div class="content">
+          {{ item.text }}
+        </div> -->
+      </div>
+    </div>
+    <div class="ai_body_select">
+      <div class="checkBox" v-if="checkBool">
+        <div class="task">
+          <div class="title">选择需要优化的任务:</div>
+          <div class="content">
+            <div class="span" @click="addAllTask()">
+              <div class="check">
+                <img
+                  :src="checkImg"
+                  alt=""
+                  v-if="checkArray.length !== course.length"
+                />
+                <img :src="checkIsImg" alt="" v-else />
+              </div>
+              <span>全选</span>
             </div>
-            <span class="check" :class="{ isCheck: checkBool }" v-if="!checkArray.length && !part"
-                @click="checkBool = !checkBool">选择优化内容</span>
-            <span class="check" :class="{ isCheck: checkBool }" @click="checkBool = !checkBool" v-else>
-                <el-tooltip :content="taskName" placement="top" effect="dark">
-                    <!-- content to trigger tooltip here -->
-                    <span>{{ taskName }}</span>
-                </el-tooltip>
-
-            </span>
+            <div
+              class="span"
+              v-for="(item, index) in course"
+              :key="index"
+              @click="addTask(index)"
+            >
+              <div class="check">
+                <img
+                  :src="checkImg"
+                  alt=""
+                  v-if="checkArray.indexOf(index) === -1"
+                />
+                <img :src="checkIsImg" alt="" v-else />
+              </div>
+              <span>任务{{ index + 1 }}</span>
+            </div>
+          </div>
         </div>
-        <div class="ai_body_input">
-            <textarea rows="5" class="binfo_input binfo_textarea" cols v-model="courseText" placeholder="在此输入您想了解的内容"
-                style="padding-right: 86px;"></textarea>
-            <div class="c_pub_button_confirm" @click="addContent">发送</div>
+        <div class="part">
+          <div class="title">选择优化的部分:</div>
+          <div class="content">
+            <div
+              class="span"
+              v-for="(item, index) in partArray"
+              :key="index"
+              :class="{ active: part == item.name }"
+              @click="checkPart(item.name)"
+            >
+              {{ item.name }}
+            </div>
+          </div>
         </div>
+      </div>
+      <span
+        class="check"
+        :class="{ isCheck: checkBool }"
+        v-if="!checkArray.length && !part"
+        @click="checkBool = !checkBool"
+        >选择优化内容</span
+      >
+      <span
+        class="check"
+        :class="{ isCheck: checkBool }"
+        @click="checkBool = !checkBool"
+        v-else
+      >
+        <el-tooltip :content="taskName" placement="top" effect="dark">
+          <!-- content to trigger tooltip here -->
+          <span>{{ taskName }}</span>
+        </el-tooltip>
+      </span>
     </div>
+    <div class="ai_body_input">
+      <textarea
+        rows="3"
+        @keyup.enter="addContent"
+        class="binfo_input binfo_textarea"
+        cols
+        v-model.trim="courseText"
+        placeholder="在此输入您想了解的内容"
+      ></textarea>
+      <div
+        class="c_pub_button_confirm"
+        v-if="!loading && courseText"
+        @click="addContent"
+      >
+        发送
+      </div>
+      <div class="c_pub_button_confirm" @click="promptTit" v-else>发送</div>
+    </div>
+  </div>
 </template>
 
 <script>
-import checkImg from '../../../assets/icon/sourceFile/check.png'
-import checkIsImg from '../../../assets/icon/sourceFile/check_is.png'
-
+import checkImg from "../../../assets/icon/sourceFile/check.png";
+import checkIsImg from "../../../assets/icon/sourceFile/check_is.png";
+import { v4 as uuidv4 } from "uuid";
+import MarkdownIt from "markdown-it";
 export default {
-    props: {
-        unitJson: {
-            type: Array,
-        },
+  props: {
+    unitJson: {
+      type: Array
     },
-    data() {
-        return {
-            array: [
-                { text: '你好,有说么可以帮你', role: 1 },
-
-            ],
-            courseText: '',
-            checkImg: checkImg,
-            checkIsImg: checkIsImg,
-            checkArray: [],
-            course: [
-                { title: '任务1' },
-                { title: '任务2' },
-                { title: '任务3' }
-            ],
-            partArray: [{ name: '全部内容' }, { name: '任务设计' }, { name: '评价设计' }],
-            part: '',
-            checkBool: false,
-            loading: false
-        }
+		courseId:{
+			type:String,
+			default:""
+		},
+  },
+  data() {
+    return {
+      array: [],
+      courseText: "",
+      checkImg: checkImg,
+      checkIsImg: checkIsImg,
+			userid: this.$route.query.userid,
+      checkArray: [],
+      course: [{ title: "任务1" }, { title: "任务2" }, { title: "任务3" }],
+      partArray: [
+        { name: "全部内容" },
+        { name: "任务设计" },
+        { name: "评价设计" }
+      ],
+      part: "",
+      checkBool: false,
+      loading: false
+    };
+  },
+  watch: {
+    unitJson: {
+      immediate: true,
+      deep: true,
+      handler(newValue, oldValue) {
+        this.course = this.unitJson[0].chapterInfo[0].taskJson;
+      }
+    }
+  },
+  methods: {
+    promptTit() {
+      if (!this.loading && !this.courseText) {
+        this.$message({
+          message: "请输入您想要了解的内容",
+          type: "warning"
+        });
+      } else {
+        this.$message({
+          message: "请回答完毕后再次发送",
+          type: "warning"
+        });
+      }
     },
-    watch: {
-        unitJson: {
-            immediate: true,
-            deep: true,
-            handler(newValue, oldValue) {
-               this.course = this.unitJson[0].chapterInfo[0].taskJson
-            }
-        },
-    },
-    methods: {
-        addContent() {
-            if (this.courseText) {
-                this.loading = true
-                this.array.push({ text: this.courseText, role: 2 })
-                setTimeout(() => {
-                    this.loading = false
-                    if (this.courseText == '请告诉我任务四该具体如何实施?') {
-                        this.array.push({
-                            text: `任务四:设计保温杯的初步方案
-
-教学目标:
-•学会应用热传递原理设计保温杯。
-•掌握基本的设计思维和创新方法。
-•理解材料选择对保温效果的影响。
-
-教学过程:
-1.复习:回顾热传递的基本原理和不同材料的导热性能。
-2.需求分析:讨论保温杯的使用场景和功能需求,如保温时间、容量、便携性等。
-3.设计指导:教师介绍设计原则和考虑因素,如材料的导热性能、结构设计、成本和环保等。
-4.创意发散:学生团队进行头脑风暴,提出多种设计方案,并选出最可行的方案。
-5.方案绘制:学生绘制保温杯的设计图,包括尺寸、形状、结构和所用材料。
-
-师生研讨:
-•分享各组的设计方案,讨论设计的创新点和实用性。
-•教师提供专业意见和建议,帮助学生完善设计方案。
-•讨论如何将设计方案转化为实际操作的步骤。
-
-拓展:
-•学生研究市场上不同类型保温杯的设计和功能。
-•分析保温杯的改进空间和潜在的创新点。
-
-学生任务单:
-•列出保温杯的功能需求和设计目标。
-•绘制保温杯的设计方案图,并标注所用材料和尺寸。
-•简述所选材料的导热性能和对保温效果的影响。
-
-知识点练习:
-1.为什么保温杯通常使用不锈钢或陶瓷作为内胆材料?
-2.描述一个创新的保温杯设计方案,并解释其工作原理。
-3.讨论在设计保温杯时需要考虑的环境因素。
-
-答案:
-1.保温杯通常使用不锈钢或陶瓷作为内胆材料,因为这些材料是热的不良导体,可以有效减缓热量的散失。
-2.一个创新的保温杯设计方案可能是采用多层结构,内层为不锈钢,中间层为真空隔热层,外层为塑料保护层。这种设计可以有效隔绝外界温度对热水温度的影响。
-在设计保温杯时,需要考虑的环境因素包括材料的可回收性、生产过程中的能源消耗和废弃物处理等。`, role: 1
-                        })
-                    }else if(this.courseText == '请你重新设计该任务,我没有感温粉末。'){
-                        this.array.push({text:`任务一:探究热的传递方式
-
-任务名: 观察热在水中的传递
-
-任务描述:
-同学们,今天我们将通过一个有趣的实验来探究热是如何在水中传递的。你将需要加热水并观察温度是如何分布的。请准备好实验器材,并按照安全指南进行操作。在实验过程中,请注意观察热水和冷水之间的相互作用,以及水温是如何随时间和空间变化的。你将需要记录你的观察结果,并思考热是如何从一个地方传递到另一个地方的。
-
-工具名字: 电子白板
-
-工具指引:
-使用电子白板工具来绘制你的实验设置和观察到的热传递过程。你可以使用电子白板的绘图功能来创建一个温度分布图,展示热水和冷水相遇时的情况。同时,你可以用它来记录实验步骤和关键观察点,以便于你和同学们进行讨论和分享。
-
-评价维度:
-•实验观察和记录:学生应该能够准确地记录实验过程中的观察结果,包括水温变化和热传递的现象。
-•数据分析和解释:学生应该能够分析实验数据,解释热在水中的传递方式,并能够用自己的话描述热对流的原理。
-•实验报告撰写:学生应该能够撰写一份清晰的实验报告,包括实验目的、方法、结果和结论,以及对实验过程的反思。`,role: 1})
-                            this.$emit('setUnitJson')
-                    }else if(this.checkArray.indexOf(0) !== -1 && this.courseText == '请告诉该具体如何实施?'){
-                        this.array.push({text:`教学活动1:探究热的传递方式
-教学目标:
-•理解热的三种传递方式:传导、对流和辐射。
-•掌握热对流现象的基本概念。
-•学会通过实验观察和分析热在水中的传递过程。
-教学过程:
-1.引入:讨论日常生活中的热现象,如热水变凉、金属勺柄变热等,引出热传递的概念。
-2.实验准备:介绍实验材料(试管、大烧杯、滴管、三脚架、石棉网、酒精灯、火柴、铁架台、试管架、感温粉末、红墨水、清水等)和安全注意事项。
-3.实验操作:学生分组进行实验,加热试管和烧杯中的水,并加入感温粉末或红墨水以观察热的传递。
-4.观察记录:学生记录实验现象,包括水温的变化、感温粉末或红墨水的颜色变化等。
-5.结果分析:师生共同讨论实验结果,理解热对流的形成机制。
-师生研讨:
-•讨论实验中观察到的热在水中的传递方式。
-•分析为什么水受热后会产生对流现象。
-•探讨热对流在生活中的应用,如暖气系统、热水器等。
-拓展:
-•学生研究热在其他物质(如空气)中的传递方式。
-•设计并执行一个简单的实验,比较热在不同物质中的传递速度。
-学生任务单:
-•描述实验中观察到的热在水中的传递过程。
-•解释热对流的形成原理。
-•提出一个生活中热对流的应用实例。
-知识点练习:
-1.热传递的三种方式是什么?
-2.为什么加热试管底部的水会使试管上部的水也变热?
-3.描述热对流的一个实际应用,并解释其工作原理。
-答案:
-1.热传递的三种方式是传导、对流和辐射。
-2.加热试管底部的水会使试管上部的水也变热,因为热通过水的对流传递到了上部。
-一个热对流的实际应用是暖气系统。它通过加热空气,使热空气上升,冷空气下降,形成对流循环,从而使房间变暖。`,role:1})
-                    }else if(this.checkArray.indexOf(0) !== -1 && this.courseText == '我没有感温粉末怎么办'){
-                        this.array.push({text:`如果您没有感温粉末,不用担心,我们仍然可以探究热的传递方式,只是需要采用不同的方法来观察和记录热在水中的传递。以下是几种替代方案:
-
-1. **温度计**:您可以使用普通温度计或数字温度计来测量水在加热过程中的温度变化。通过在不同时间点记录水温,您可以绘制出温度随时间变化的曲线,从而理解热是如何在水中传播的。
-
-2. **红墨水或其他有色液体**:如果家里有红墨水或其他任何有颜色的液体,您可以在水加热前滴入几滴。当红墨水在加热的水中扩散时,您可以观察到颜色的变化,这可以帮助您可视化水的流动和混合。
-
-3. **视频记录**:您可以使用手机或相机录制水加热的过程,特别是观察加热区域与未加热区域之间的界面。通过回放视频,您可以分析和讨论热传递的现象。
-
-4. **实验日志**:在实验过程中,详细记录您的观察和思考。包括您使用的替代方法、观察到的现象、遇到的问题以及您对这些现象的解释。
-
-5. **讨论和交流**:与同学或老师讨论您的发现,即使没有感温粉末,您也可以通过交流想法和观察结果来增进对热传递现象的理解。
-
-记住,科学探究的本质在于提出问题、设计实验、收集数据、分析结果和得出结论。即使缺少某些工具或材料,创新和适应性也是科学探究的重要部分。`,role:1})
-                    } else {
-                        this.array.push({ text: '请输入正确的文案', role: 1 })
-                    }
-                    // this.array.push({text: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', role: 1})
-                    this.courseText = ''
-                }, 5000);
-            }
-        },
-        addTask(index) {
-            if (this.checkArray.indexOf(index) !== -1) {
-                this.checkArray.splice(this.checkArray.indexOf(index), 1)
-            } else {
-                this.checkArray.push(index)
-            }
-            console.log(index);
-        },
-        addAllTask() {
-            if (this.checkArray.length === this.course.length) {
-                this.checkArray = []
+    addContent() {
+      if (this.courseText) {
+        let _uuid = uuidv4();
+        this.array.push({
+          role: "user",
+          content: `${this.courseText}`,
+          uid: _uuid,
+          AI: "AI",
+          aiContent: "",
+          oldContent: "",
+          isShowSynchronization: false,
+          filename: "",
+          index: this.array.length,
+          is_mind_map: false,
+          loading: true
+        });
+        this.$nextTick(() => {
+          this.$refs.chatDialog.scrollTop = this.$refs.chatDialog.scrollHeight;
+        });
+        let params = JSON.stringify({
+          model: "gpt-3.5-turbo",
+          temperature: 0,
+          max_tokens: 4096,
+          top_p: 1,
+          frequency_penalty: 0,
+          presence_penalty: 0,
+          messages: [{ role: "user", content: this.courseText }],
+          uid: _uuid,
+          mind_map_question: ""
+        });
+        this.courseText = "";
+
+        this.ajax
+          .post("https://gpt4.cocorobo.cn/chat", params)
+          .then(res => {
+            if (res.data.FunctionResponse.result == "发送成功") {
             } else {
-                this.checkArray = []
-                this.course.forEach((item, index) => {
-                    this.checkArray.push(index)
-                })
+              this.$message.warning(res.data.FunctionResponse.result);
             }
-        },
-        checkPart(name) {
-            this.part = name
+          })
+          .catch(e => {
+            console.log(e);
+          });
+        this.getAiContent(_uuid);
+      }
+      //             if (this.courseText) {
+
+      //                 this.loading = true
+      //                 this.array.push({ text: this.courseText, role: 2 })
+      //                 this.courseText = ''
+
+      //                 setTimeout(() => {
+      //                     this.loading = false
+      //                     if (this.courseText == '请告诉我任务四该具体如何实施?') {
+      //                         this.array.push({
+      //                             text: `任务四:设计保温杯的初步方案
+
+      // 教学目标:
+      // •学会应用热传递原理设计保温杯。
+      // •掌握基本的设计思维和创新方法。
+      // •理解材料选择对保温效果的影响。
+
+      // 教学过程:
+      // 1.复习:回顾热传递的基本原理和不同材料的导热性能。
+      // 2.需求分析:讨论保温杯的使用场景和功能需求,如保温时间、容量、便携性等。
+      // 3.设计指导:教师介绍设计原则和考虑因素,如材料的导热性能、结构设计、成本和环保等。
+      // 4.创意发散:学生团队进行头脑风暴,提出多种设计方案,并选出最可行的方案。
+      // 5.方案绘制:学生绘制保温杯的设计图,包括尺寸、形状、结构和所用材料。
+
+      // 师生研讨:
+      // •分享各组的设计方案,讨论设计的创新点和实用性。
+      // •教师提供专业意见和建议,帮助学生完善设计方案。
+      // •讨论如何将设计方案转化为实际操作的步骤。
+
+      // 拓展:
+      // •学生研究市场上不同类型保温杯的设计和功能。
+      // •分析保温杯的改进空间和潜在的创新点。
+
+      // 学生任务单:
+      // •列出保温杯的功能需求和设计目标。
+      // •绘制保温杯的设计方案图,并标注所用材料和尺寸。
+      // •简述所选材料的导热性能和对保温效果的影响。
+
+      // 知识点练习:
+      // 1.为什么保温杯通常使用不锈钢或陶瓷作为内胆材料?
+      // 2.描述一个创新的保温杯设计方案,并解释其工作原理。
+      // 3.讨论在设计保温杯时需要考虑的环境因素。
+
+      // 答案:
+      // 1.保温杯通常使用不锈钢或陶瓷作为内胆材料,因为这些材料是热的不良导体,可以有效减缓热量的散失。
+      // 2.一个创新的保温杯设计方案可能是采用多层结构,内层为不锈钢,中间层为真空隔热层,外层为塑料保护层。这种设计可以有效隔绝外界温度对热水温度的影响。
+      // 在设计保温杯时,需要考虑的环境因素包括材料的可回收性、生产过程中的能源消耗和废弃物处理等。`, role: 1
+      //                         })
+      //                     }else if(this.courseText == '请你重新设计该任务,我没有感温粉末。'){
+      //                         this.array.push({text:`任务一:探究热的传递方式
+
+      // 任务名: 观察热在水中的传递
+
+      // 任务描述:
+      // 同学们,今天我们将通过一个有趣的实验来探究热是如何在水中传递的。你将需要加热水并观察温度是如何分布的。请准备好实验器材,并按照安全指南进行操作。在实验过程中,请注意观察热水和冷水之间的相互作用,以及水温是如何随时间和空间变化的。你将需要记录你的观察结果,并思考热是如何从一个地方传递到另一个地方的。
+
+      // 工具名字: 电子白板
+
+      // 工具指引:
+      // 使用电子白板工具来绘制你的实验设置和观察到的热传递过程。你可以使用电子白板的绘图功能来创建一个温度分布图,展示热水和冷水相遇时的情况。同时,你可以用它来记录实验步骤和关键观察点,以便于你和同学们进行讨论和分享。
+
+      // 评价维度:
+      // •实验观察和记录:学生应该能够准确地记录实验过程中的观察结果,包括水温变化和热传递的现象。
+      // •数据分析和解释:学生应该能够分析实验数据,解释热在水中的传递方式,并能够用自己的话描述热对流的原理。
+      // •实验报告撰写:学生应该能够撰写一份清晰的实验报告,包括实验目的、方法、结果和结论,以及对实验过程的反思。`,role: 1})
+      //                             this.$emit('setUnitJson')
+      //                     }else if(this.checkArray.indexOf(0) !== -1 && this.courseText == '请告诉该具体如何实施?'){
+      //                         this.array.push({text:`教学活动1:探究热的传递方式
+      // 教学目标:
+      // •理解热的三种传递方式:传导、对流和辐射。
+      // •掌握热对流现象的基本概念。
+      // •学会通过实验观察和分析热在水中的传递过程。
+      // 教学过程:
+      // 1.引入:讨论日常生活中的热现象,如热水变凉、金属勺柄变热等,引出热传递的概念。
+      // 2.实验准备:介绍实验材料(试管、大烧杯、滴管、三脚架、石棉网、酒精灯、火柴、铁架台、试管架、感温粉末、红墨水、清水等)和安全注意事项。
+      // 3.实验操作:学生分组进行实验,加热试管和烧杯中的水,并加入感温粉末或红墨水以观察热的传递。
+      // 4.观察记录:学生记录实验现象,包括水温的变化、感温粉末或红墨水的颜色变化等。
+      // 5.结果分析:师生共同讨论实验结果,理解热对流的形成机制。
+      // 师生研讨:
+      // •讨论实验中观察到的热在水中的传递方式。
+      // •分析为什么水受热后会产生对流现象。
+      // •探讨热对流在生活中的应用,如暖气系统、热水器等。
+      // 拓展:
+      // •学生研究热在其他物质(如空气)中的传递方式。
+      // •设计并执行一个简单的实验,比较热在不同物质中的传递速度。
+      // 学生任务单:
+      // •描述实验中观察到的热在水中的传递过程。
+      // •解释热对流的形成原理。
+      // •提出一个生活中热对流的应用实例。
+      // 知识点练习:
+      // 1.热传递的三种方式是什么?
+      // 2.为什么加热试管底部的水会使试管上部的水也变热?
+      // 3.描述热对流的一个实际应用,并解释其工作原理。
+      // 答案:
+      // 1.热传递的三种方式是传导、对流和辐射。
+      // 2.加热试管底部的水会使试管上部的水也变热,因为热通过水的对流传递到了上部。
+      // 一个热对流的实际应用是暖气系统。它通过加热空气,使热空气上升,冷空气下降,形成对流循环,从而使房间变暖。`,role:1})
+      //                     }else if(this.checkArray.indexOf(0) !== -1 && this.courseText == '我没有感温粉末怎么办'){
+      //                         this.array.push({text:`如果您没有感温粉末,不用担心,我们仍然可以探究热的传递方式,只是需要采用不同的方法来观察和记录热在水中的传递。以下是几种替代方案:
+
+      // 1. **温度计**:您可以使用普通温度计或数字温度计来测量水在加热过程中的温度变化。通过在不同时间点记录水温,您可以绘制出温度随时间变化的曲线,从而理解热是如何在水中传播的。
+
+      // 2. **红墨水或其他有色液体**:如果家里有红墨水或其他任何有颜色的液体,您可以在水加热前滴入几滴。当红墨水在加热的水中扩散时,您可以观察到颜色的变化,这可以帮助您可视化水的流动和混合。
+
+      // 3. **视频记录**:您可以使用手机或相机录制水加热的过程,特别是观察加热区域与未加热区域之间的界面。通过回放视频,您可以分析和讨论热传递的现象。
+
+      // 4. **实验日志**:在实验过程中,详细记录您的观察和思考。包括您使用的替代方法、观察到的现象、遇到的问题以及您对这些现象的解释。
+
+      // 5. **讨论和交流**:与同学或老师讨论您的发现,即使没有感温粉末,您也可以通过交流想法和观察结果来增进对热传递现象的理解。
+
+      // 记住,科学探究的本质在于提出问题、设计实验、收集数据、分析结果和得出结论。即使缺少某些工具或材料,创新和适应性也是科学探究的重要部分。`,role:1})
+      //                     } else {
+      //                         this.array.push({ text: '请输入正确的文案', role: 1 })
+      //                     }
+      //                     // this.array.push({text: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', role: 1})
+      //                 }, 5000);
+      //             }
+    },
+    getAiContent(_uid) {
+      let _source = new EventSource(`https://gpt4.cocorobo.cn/stream/${_uid}`); //http://gpt4.cocorobo.cn:8011/stream/     https://gpt4.cocorobo.cn/stream/
+      let _allText = "";
+      let _mdText = "";
+      const md = new MarkdownIt();
+      _source.onmessage = _e => {
+        if (_e.data.replace("'", "").replace("'", "") == "[DONE]") {
+          //对话已经完成
+          _mdText = _mdText.replace("_", "");
+          _source.close();
+          this.$nextTick(() => {
+            this.$refs.chatDialog.scrollTop = this.$refs.chatDialog.scrollHeight;
+          });
+          this.array.find(i => i.uid == _uid).aiContent = _mdText;
+          this.array.find(i => i.uid == _uid).isalltext = true;
+          this.array.find(i => i.uid == _uid).isShowSynchronization = true;
+          this.array.find(i => i.uid == _uid).loading = false;
+          // 这里保存对话
+          this.insertChat(_uid);
+          return;
+        } else {
+          //对话还在继续
+          let _text = "";
+          _text = _e.data.replaceAll("'", "");
+          if (_allText == "") {
+            _allText = _text.replace(/^\n+/, ""); //去掉回复消息中偶尔开头就存在的连续换行符
+          } else {
+            _allText += _text;
+          }
+          _mdText = _allText + "_";
+          _mdText = _mdText.replace(/\\n/g, "\n");
+          _mdText = _mdText.replace(/\\/g, "");
+          if (_allText.split("```").length % 2 == 0) _mdText += "\n```\n";
+          //转化返回的回复流数据
+          _mdText = md.render(_mdText);
+          this.array.find(i => i.uid == _uid).aiContent = _mdText;
+          this.array.find(i => i.uid == _uid).loading = false;
+          this.$nextTick(() => {
+            this.$refs.chatDialog.scrollTop = this.$refs.chatDialog.scrollHeight;
+          });
+          // 处理流数据
         }
+      };
     },
-    computed: {
-        courseTextLength() {
-            return this.courseText.length
-        },
-        taskName() {
-            let task = ''
-            if (this.checkArray.length) {
-                task = '任务'
-                this.checkArray = this.checkArray.sort((a, b) => a - b)
-                let a = JSON.parse(JSON.stringify(this.checkArray))
-                for (let index = 0; index < a.length; index++) {
-                    a[index]++;
-                }
-                task += a.join('/')
+    //保存消息
+    insertChat(_uid) {
+      let _data = this.array.find(i => i.uid == _uid);
+      if (!_data) return;
+      let params = {
+        userId: this.userid,
+        userName: "qgt",
+        groupId: "602def61-005d-11ee-91d8-005056b8q12w",
+        answer: _data.aiContent,
+        problem: _data.content,
+        file_id: _data.fileid ? _data.fileid : "",
+        alltext: _data.aiContent,
+        type: "chat",
+        filename: _data.filename,
+        session_name: `${this.courseId}-addCourse` //这是对话记录位置
+      };
+      this.ajax
+        .post("https://gpt4.cocorobo.cn/insert_chat", params)
+        .then(res => {});
+    },
+    // 获取对应的聊天记录
+    getChatList() {
+      return new Promise((resolve, reject) => {
+        if (this.loading) return this.$message.info("请稍等...");
+        this.chatList = [];
+        this.loading = true;
+        let params = {
+          userid: this.userid,
+          groupid: "602def61-005d-11ee-91d8-005056b8q12w",
+          // session_name:``
+          session_name: `${this.courseId}-addCourse`
+        };
+        this.ajax
+          .post("https://gpt4.cocorobo.cn/get_agent_park_chat", params)
+          .then(res => {
+            let _data = JSON.parse(res.data.FunctionResponse);
+            if (_data.length > 0) {
+              let _chatList = [];
+              for (let i = 0; i < _data.length; i++) {
+                _chatList.push({
+                  loading: false,
+                  role: "user",
+                  content: _data[i].problem,
+                  uid: _data[i].id,
+                  AI: "AI",
+                  aiContent: _data[i].answer,
+                  oldContent: _data[i].answer,
+                  isShowSynchronization: false,
+                  filename: _data[i].filename,
+                  index: i,
+                  is_mind_map: false,
+                  fileid: _data[i].fileid
+                });
+              }
+              this.array = _chatList;
+              this.loading = false;
+            } else {
+              //没有对话记录
+              this.loading = false;
             }
-            return task + ' ' + this.part
-        }
+            resolve();
+          })
+          .catch(err => {
+            console.log(err);
+            this.$message.error("获取对话记录失败");
+            this.loading = false;
+            resolve();
+          });
+      });
     },
-}
+    addTask(index) {
+      if (this.checkArray.indexOf(index) !== -1) {
+        this.checkArray.splice(this.checkArray.indexOf(index), 1);
+      } else {
+        this.checkArray.push(index);
+      }
+      console.log(index);
+    },
+    addAllTask() {
+      if (this.checkArray.length === this.course.length) {
+        this.checkArray = [];
+      } else {
+        this.checkArray = [];
+        this.course.forEach((item, index) => {
+          this.checkArray.push(index);
+        });
+      }
+    },
+    checkPart(name) {
+      this.part = name;
+    }
+  },
+  computed: {
+    courseTextLength() {
+      return this.courseText.length;
+    },
+    taskName() {
+      let task = "";
+      if (this.checkArray.length) {
+        task = "任务";
+        this.checkArray = this.checkArray.sort((a, b) => a - b);
+        let a = JSON.parse(JSON.stringify(this.checkArray));
+        for (let index = 0; index < a.length; index++) {
+          a[index]++;
+        }
+        task += a.join("/");
+      }
+      return task + " " + this.part;
+    }
+  },
+  mounted() {
+    this.getChatList().then(_ => {
+      this.$nextTick(() => {
+				console.log(this.$refs.chatDialog.scrollHeight)
+        this.$refs.chatDialog.scrollTop = this.$refs.chatDialog.scrollHeight;
+      });
+    });
+  }
+};
 </script>
 
 <style scoped>
 .ai_body {
-    height: 100%;
-    width: calc(100% - 20px);
-    margin: 0 auto;
+  height: 100%;
+  width: calc(100% - 20px);
+  margin: 0 auto;
 }
 
 .binfo_input {
-    width: 100%;
-    margin: 0;
-    padding: 12px 14px;
-    display: block;
-    min-width: 0;
-    outline: none;
-    box-sizing: border-box;
-    background: none;
-    border: none;
-    border-radius: 4px;
-    background: #fff;
-    font-size: 14px;
-    resize: none;
-    font-family: "Microsoft YaHei";
-    min-height: 48px;
-    /* border: 1px solid #3682fc00; */
-    border: 1.5px solid #cad1dc;
+  width: 100%;
+  margin: 0;
+  padding: 12px 14px;
+  display: block;
+  min-width: 0;
+  outline: none;
+  box-sizing: border-box;
+  background: none;
+  border: none;
+  border-radius: 4px;
+  background: #fff;
+  font-size: 14px;
+  resize: none;
+  font-family: "Microsoft YaHei";
+  min-height: 48px;
+  /* border: 1px solid #3682fc00; */
+  border: 1.5px solid #cad1dc;
 }
 
 .binfo_textarea {
-    border: 1.5px solid #cad1dc;
-    font-size: 14px;
-    resize: none;
-    /* background: #f6f6f6; */
-    font-family: "Microsoft YaHei";
+  border: 1.5px solid #cad1dc;
+  font-size: 14px;
+  resize: none;
+  /* background: #f6f6f6; */
+  font-family: "Microsoft YaHei";
 }
 
 .binfo_textarea::-webkit-scrollbar {
-    /*滚动条整体样式*/
-    width: 6px;
-    /*高宽分别对应横竖滚动条的尺寸*/
-    height: 6px;
+  /*滚动条整体样式*/
+  width: 6px;
+  /*高宽分别对应横竖滚动条的尺寸*/
+  height: 6px;
 }
 
 /*定义滚动条轨道 内阴影+圆角*/
 .binfo_textarea::-webkit-scrollbar-track {
-    border-radius: 10px;
-    background-color: rgba(0, 0, 0, 0.1);
+  border-radius: 10px;
+  background-color: rgba(0, 0, 0, 0.1);
 }
 
 /*定义滑块 内阴影+圆角*/
 .binfo_textarea::-webkit-scrollbar-thumb {
-    border-radius: 10px;
-    -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, .3);
-    background-color: rgba(0, 0, 0, 0.1);
+  border-radius: 10px;
+  -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
+  background-color: rgba(0, 0, 0, 0.1);
 }
 
 .binfo_input:focus-visible {
-    border: 1.5px solid #3681fc !important;
+  border: 1.5px solid #3681fc !important;
 }
 
 .ai_body_input {
-    position: relative;
+  /* position: relative; */
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: end;
 }
 
 .c_pub_button_confirm {
-    position: absolute;
+  /* position: absolute;
     bottom: 13px;
-    right: 13px;
+    right: 13px; */
+  margin-top: 10px;
+  width: 80px;
+  display: flex;
+  justify-content: center;
 }
 
 .ai_body_dialog {
-    padding: 10px 0;
-    box-sizing: border-box;
-    height: calc(100% - 180px);
-    overflow: auto;
-    margin-bottom: 10px;
+  padding: 10px 0;
+  box-sizing: border-box;
+  height: calc(100% - 180px);
+  overflow: auto;
+  margin-bottom: 10px;
 }
 
-
 .dialog_content {
-    width: 100%;
-    display: flex;
+  width: 100%;
+  display: flex;
+  flex-direction: column;
 }
 
-.dialog_content+.dialog_content {
-    margin-top: 20px;
+.dialog_content > div {
+  display: flex;
+  align-items: flex-start;
 }
 
-.dialog_content.right {
-    flex-direction: row-reverse;
+.dialog_content + .dialog_content {
+  margin: 15px 0;
 }
 
-.dialog_content.right .role {
-    margin-right: 0;
-    margin-left: 10px;
+.dialog_content > div .right {
+  flex-direction: row-reverse;
 }
 
-.dialog_content .role {
-    min-width: 30px;
-    width: 30px;
-    height: 30px;
-    margin-right: 10px;
-    border-radius: 50%;
+.dialog_content > div .right .role {
+  margin-right: 0;
+  margin-left: 10px;
 }
 
-.dialog_content .role>img {
-    height: 100%;
-    width: 100%;
+.dialog_content > div .role {
+  min-width: 30px;
+  width: 30px;
+  height: 30px;
+  margin-right: 10px;
+  border-radius: 50%;
 }
 
-.dialog_content .content {
-    padding: 5px;
-    border-radius: 5px;
-    width: 100%;
-    word-break: break-word;
-    box-sizing: border-box;
-    white-space: pre-line;
-    max-width: 100%;
-    overflow: hidden;
+.dialog_content > div .role > img {
+  height: 100%;
+  width: 100%;
 }
 
-.dialog_content .content2 {
-    background: #3681fc;
-    color: #fff;
+.dialog_content > div .content {
+  padding: 10px 5px;
+  border-radius: 5px;
+  width: 100%;
+  word-break: break-word;
+  box-sizing: border-box;
+  /* white-space: pre-line; */
+  max-width: 100%;
+  background: #f7f7f7;
+  overflow: hidden;
+  margin: 0 10px;
 }
 
+.dialog_content > div .content2 {
+  background: #3681fc;
+  color: #fff;
+}
 
 .ai_body_select {
-    position: relative;
-}
-
-.ai_body_select>.check {
-    background: #e7e7e7;
-    display: flex;
-    width: fit-content;
-    padding: 0 10px;
-    height: 30px;
-    border-radius: 21px;
-    font-size: 14px;
-    align-items: center;
-    justify-content: center;
-    color: #0061FF;
-    font-weight: 700;
-    margin: 10px 0;
-    cursor: pointer;
-}
-
-.ai_body_select>.check::before {
-    content: '';
-    width: 15px;
-    height: 15px;
-    display: block;
-    background-image: url('../../../assets/icon/course/aiPart.png');
-    background-size: 100% 100%;
-    margin-right: 5px;
-}
-
-.ai_body_select>.check::after {
-    content: '';
-    width: 15px;
-    height: 15px;
-    display: block;
-    background-image: url('../../../assets/icon/course/aiPart_arrow.png');
-    background-size: 100% 100%;
-    margin-right: 5px;
-}
-
-.ai_body_select>.isCheck {
-    background: #0061FF;
-    display: flex;
-    width: fit-content;
-    padding: 0 10px;
-    height: 30px;
-    border-radius: 21px;
-    font-size: 14px;
-    align-items: center;
-    justify-content: center;
-    color: #fff;
-    font-weight: 700;
-    margin: 10px 0;
-    cursor: pointer;
-    max-width: 100%;
-    box-sizing: border-box;
-}
-
-.ai_body_select>.isCheck>span {
-    width: calc(100% - 40px);
-    display: block;
-    overflow: hidden;
-    white-space: nowrap;
-    text-overflow: ellipsis;
+  position: relative;
+}
+
+.ai_body_select > .check {
+  background: #e7e7e7;
+  display: flex;
+  width: fit-content;
+  padding: 0 10px;
+  height: 30px;
+  border-radius: 21px;
+  font-size: 14px;
+  align-items: center;
+  justify-content: center;
+  color: #0061ff;
+  font-weight: 700;
+  margin: 10px 0;
+  cursor: pointer;
+}
+
+.ai_body_select > .check::before {
+  content: "";
+  width: 15px;
+  height: 15px;
+  display: block;
+  background-image: url("../../../assets/icon/course/aiPart.png");
+  background-size: 100% 100%;
+  margin-right: 5px;
+}
+
+.ai_body_select > .check::after {
+  content: "";
+  width: 15px;
+  height: 15px;
+  display: block;
+  background-image: url("../../../assets/icon/course/aiPart_arrow.png");
+  background-size: 100% 100%;
+  margin-right: 5px;
+}
+
+.ai_body_select > .isCheck {
+  background: #0061ff;
+  display: flex;
+  width: fit-content;
+  padding: 0 10px;
+  height: 30px;
+  border-radius: 21px;
+  font-size: 14px;
+  align-items: center;
+  justify-content: center;
+  color: #fff;
+  font-weight: 700;
+  margin: 10px 0;
+  cursor: pointer;
+  max-width: 100%;
+  box-sizing: border-box;
+}
+
+.ai_body_select > .isCheck > span {
+  width: calc(100% - 40px);
+  display: block;
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
 }
 
-.ai_body_select>.isCheck::before {
-    content: '';
-    width: 15px;
-    height: 15px;
-    display: block;
-    background-image: url('../../../assets/icon/course/aiPart_active.png');
-    background-size: 100% 100%;
-    margin-right: 5px;
+.ai_body_select > .isCheck::before {
+  content: "";
+  width: 15px;
+  height: 15px;
+  display: block;
+  background-image: url("../../../assets/icon/course/aiPart_active.png");
+  background-size: 100% 100%;
+  margin-right: 5px;
 }
 
-.ai_body_select>.isCheck::after {
-    content: '';
-    width: 15px;
-    height: 15px;
-    display: block;
-    background-image: url('../../../assets/icon/course/aiPart_arrow_active.png');
-    background-size: 100% 100%;
-    margin-right: 5px;
+.ai_body_select > .isCheck::after {
+  content: "";
+  width: 15px;
+  height: 15px;
+  display: block;
+  background-image: url("../../../assets/icon/course/aiPart_arrow_active.png");
+  background-size: 100% 100%;
+  margin-right: 5px;
 }
 
-
-.ai_body_select>.checkBox {
-    position: absolute;
-    bottom: 40px;
-    border: 1px solid #E0EAFB;
-    width: 100%;
-    height: 300px;
-    background: #fff;
-    border-radius: 5px;
-    padding: 10px;
-    box-sizing: border-box;
-}
-
-.ai_body_select>.checkBox>.task>.title,
-.ai_body_select>.checkBox>.part>.title {
-    font-size: 14px;
-    font-weight: 700;
-    margin-bottom: 5px;
-}
-
-.ai_body_select>.checkBox>.task {
-    height: calc(100% - 60px);
+.ai_body_select > .checkBox {
+  position: absolute;
+  bottom: 40px;
+  border: 1px solid #e0eafb;
+  width: 100%;
+  height: 300px;
+  background: #fff;
+  border-radius: 5px;
+  padding: 10px;
+  box-sizing: border-box;
 }
 
-.ai_body_select>.checkBox>.part {}
+.ai_body_select > .checkBox > .task > .title,
+.ai_body_select > .checkBox > .part > .title {
+  font-size: 14px;
+  font-weight: 700;
+  margin-bottom: 5px;
+}
+
+.ai_body_select > .checkBox > .task {
+  height: calc(100% - 60px);
+}
+
+.ai_body_select > .checkBox > .part {
+}
 
-.ai_body_select>.checkBox>.task>.content {
-    height: calc(100% - 40px);
-    overflow: auto;
+.ai_body_select > .checkBox > .task > .content {
+  height: calc(100% - 40px);
+  overflow: auto;
 }
 
-.ai_body_select>.checkBox>.task>.content>.span+.span {
-    margin-top: 5px;
+.ai_body_select > .checkBox > .task > .content > .span + .span {
+  margin-top: 5px;
 }
 
-.ai_body_select>.checkBox>.task>.content>.span {
-    display: flex;
-    align-items: center;
-    font-size: 14px;
-    cursor: pointer;
+.ai_body_select > .checkBox > .task > .content > .span {
+  display: flex;
+  align-items: center;
+  font-size: 14px;
+  cursor: pointer;
 }
 
-.ai_body_select>.checkBox>.task>.content>.span>.check {
-    width: 13px;
-    height: 13px;
-    display: flex;
-    align-items: center;
-    margin-right: 5px;
+.ai_body_select > .checkBox > .task > .content > .span > .check {
+  width: 13px;
+  height: 13px;
+  display: flex;
+  align-items: center;
+  margin-right: 5px;
 }
 
-.ai_body_select>.checkBox>.task>.content>.span>.check>img {
-    width: 100%;
-    height: 100%;
+.ai_body_select > .checkBox > .task > .content > .span > .check > img {
+  width: 100%;
+  height: 100%;
 }
 
-.ai_body_select>.checkBox>.part>.content {
-    display: flex;
-    align-items: center;
-    font-size: 14px;
-    justify-content: space-between;
+.ai_body_select > .checkBox > .part > .content {
+  display: flex;
+  align-items: center;
+  font-size: 14px;
+  justify-content: space-between;
 }
 
-.ai_body_select>.checkBox>.part>.content>.span {
-    padding: 3px 6px;
-    border: 1px solid #E0EAFB;
-    border-radius: 40px;
-    cursor: pointer;
+.ai_body_select > .checkBox > .part > .content > .span {
+  padding: 3px 6px;
+  border: 1px solid #e0eafb;
+  border-radius: 40px;
+  cursor: pointer;
 }
 
-.ai_body_select>.checkBox>.part>.content>.span.active {
-    color: #0061ff;
-    border-color: #0061ff;
+.ai_body_select > .checkBox > .part > .content > .span.active {
+  color: #0061ff;
+  border-color: #0061ff;
 }
-</style>
+</style>

+ 158 - 0
src/components/pages/aiAddCourse/aiDialog.vue

@@ -0,0 +1,158 @@
+<template>
+    <el-dialog title="提示词设置" :visible.sync="dialogVisibleAiD" :append-to-body="true" width="650px" :before-close="handleClose"
+        class="dialog_diy">
+        <div style="height: 100%;padding:15px">
+            <div class="ai_nav">
+                <span :class="{active: type == 1}">基础创建</span>
+            </div>
+            <div class="ai_detail" v-if="type == 1">
+                <span class="title">默认的提示词</span>
+                <textarea rows="10" class="binfo_input binfo_textarea" cols v-model="text"
+                      placeholder="请输入...."></textarea>
+            </div>
+        </div>
+        <span slot="footer" class="dialog-footer">
+            <el-button @click="confirm" type="primary">确 定</el-button>
+            <el-button @click="close">关 闭</el-button>
+        </span>
+    </el-dialog>
+</template>
+  
+<script>
+export default {
+    props: {
+        dialogVisibleAiD: {
+            type: Boolean,
+            default: false
+        },
+        aiText: {
+            type: String,
+        }
+    },
+    data() {
+        return {
+            type: 1,
+            text: ""
+        }
+    },
+    watch:{
+        dialogVisibleAiD(newValue, oldValue) {
+            this.text = JSON.parse(JSON.stringify(this.aiText))
+        }
+    },
+    methods: {
+        handleClose(done) {
+            this.close()
+            done();
+        },
+        close() {
+            this.$emit('update:dialogVisibleAiD', false)
+        },
+        confirm(){
+            this.$emit("aiConfirm",this.text);
+            this.$emit('update:dialogVisibleAiD', false)
+        }
+    },
+}
+</script>
+  
+<style scoped>
+.dialog_diy>>>.el-dialog {
+    height: auto;
+    margin: 15vh auto 0 !important;
+}
+
+.dialog_diy>>>.el-dialog__header {
+    background: #454545 !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: #fff;
+}
+
+.dialog_diy>>>.el-dialog__headerbtn {
+    top: 19px;
+}
+
+.dialog_diy>>>.el-dialog__headerbtn .el-dialog__close {
+    color: #fff;
+}
+
+.dialog_diy>>>.el-dialog__headerbtn .el-dialog__close:hover {
+    color: #fff;
+}
+
+
+.dialog_diy>>>.el-dialog__body,
+.dialog_diy>>>.el-dialog__footer {
+    background: #fafafa;
+}
+
+.ai_detail > .binfo_input {
+  width: 100%;
+  margin: 0;
+  padding: 12px 14px;
+  display: block;
+  min-width: 0;
+  outline: none;
+  box-sizing: border-box;
+  background: none;
+  border: none;
+  border-radius: 4px;
+  background: #fff;
+  font-size: 16px;
+  resize: none;
+  font-family: "Microsoft YaHei";
+  min-height: 48px;
+  /* border: 1px solid #3682fc00; */
+  border: 1.5px solid #cad1dc;
+}
+
+.ai_detail > .binfo_textarea {
+  border: 1.5px solid #cad1dc;
+  font-size: 16px;
+  resize: none;
+  /* background: #f6f6f6; */
+  font-family: "Microsoft YaHei";
+}
+
+.ai_detail > .binfo_input:focus-visible {
+  border: 1.5px solid #3681fc !important;
+}
+
+
+.ai_nav{
+    font-size: 16px;
+    margin-bottom: 10px;
+    display: flex;
+    align-items: center;
+}
+.ai_nav > span{
+    cursor: pointer;
+}
+
+.ai_nav > span + span{
+    margin-left: 15px;
+}
+.ai_nav > span.active{
+    color: #3681fc;
+}
+
+.ai_detail{
+    display: flex;
+    flex-direction: column;
+}
+
+.ai_detail > .title{
+    margin-bottom: 5px;
+}
+
+</style>

+ 63 - 0
src/components/pages/classroomObservation/components/addNewCourseDialog.vue

@@ -0,0 +1,63 @@
+<template>
+	<div class="addNewCourse">
+		<el-dialog
+			title="添加课堂"
+			:visible.sync="dialogVisible"
+			width="500px"		>
+		<div>
+			<el-form ref="form" :model="form" label-position="top">
+			  <el-form-item label="课堂编号">
+  			  <el-input v-model="form.no" placeholder="请输入课堂编号"></el-input>
+  			</el-form-item>
+				<!-- <el-form-item label="课堂名称">
+  			  <el-input v-model="form.name" placeholder="请输入课堂名称"></el-input>
+  			</el-form-item> -->
+			</el-form>
+		</div>
+			<span slot="footer" class="dialog-footer">
+				<el-button @click="dialogVisible = false">取 消</el-button>
+				<el-button type="primary" @click="submit()"
+					>确 定</el-button
+				>
+			</span>
+		</el-dialog>
+	</div>
+</template>
+
+<script>
+export default {
+	emits:["success"],
+	data(){
+		return{
+			dialogVisible:false,
+			form:{
+				no:"",
+				name:"",
+			},
+		}
+	},
+	methods:{
+		open(){
+			this.form = {
+				name:"",
+				no:"",
+			}
+			this.dialogVisible = true;
+		},
+		submit(){
+			if(this.form.no.trim().length==0 ){//|| this.form.name.trim().length==0
+				this.$message.error("请输入课堂编号")
+				return;
+			}
+			this.$emit("success",this.form)
+			this.dialogVisible = false;
+		}
+	}
+};
+</script>
+
+<style  scoped>
+.addNewCourse{
+
+}
+</style>

+ 56 - 29
src/components/pages/classroomObservation/components/analysis.vue

@@ -13,8 +13,22 @@
 			</div>
 		</div>
 		<div class="a-main" v-show="showItem">
-			<analysisItem ref="analysisItemRef" v-if="analysisItemList.length > 0" v-for="(item,index) in analysisItemList" :key="item.id" :data="item" :tid="tid" :fileId="fileId" :index="index" @delItem="delItem" @editItem="editItem"/>
-			<div class="a_m_empty" v-if="analysisItemList.length == 0">暂无模块...</div>
+			<analysisItem
+				ref="analysisItemRef"
+				v-if="analysisItemList.length > 0"
+				v-for="(item, index) in analysisItemList"
+				:dialogTagDataList="dialogTagDataList"
+				:key="item.id"
+				:data="item"
+				:tid="tid"
+				:fileId="fileId"
+				:index="index"
+				@delItem="delItem"
+				@editItem="editItem"
+			/>
+			<div class="a_m_empty" v-if="analysisItemList.length == 0">
+				暂无模块...
+			</div>
 		</div>
 	</div>
 </template>
@@ -22,30 +36,36 @@
 <script>
 import analysisItem from "./analysisItem";
 export default {
-	emits:["delItem","editItem"],
+	emits: ["delItem", "editItem"],
 	props: {
-		title:{
-			type:String,
-			default:"分析"
+		title: {
+			type: String,
+			default: "分析",
 		},
-		analysisItemList:{
+		dialogTagDataList:{
 			type:Array,
 			default:()=>{
-				return []
+				return [];
 			}
 		},
-		type:{
-			type:Number,
-			default:0
+		analysisItemList: {
+			type: Array,
+			default: () => {
+				return [];
+			},
+		},
+		type: {
+			type: Number,
+			default: 0,
+		},
+		tid: {
+			type: String,
+			require: true,
 		},
-		tid:{
-			type:String,
-			require:true,
+		fileId: {
+			type: String,
+			require: true,
 		},
-		fileId:{
-			type:String,
-			require:true,
-		}
 	},
 	components: {
 		analysisItem,
@@ -58,22 +78,29 @@ export default {
 	},
 	methods: {
 		addTemplate() {
-			this.$emit('updateMessage',  this.type);
+			this.$emit("updateMessage", this.type);
 		},
 		changeShowItem(newValue) {
 			this.showItem = newValue;
 		},
-		delItem(id){
-			this.$emit("delItem",id)
+		delItem(id) {
+			this.$emit("delItem", id);
 		},
-		editItem(id,_data){
-			this.$emit("editItem",id,_data)
+		editItem(id, _data) {
+			this.$emit("editItem", id, _data);
+		},
+		getReport(id) {
+			if (!id) {
+				this.$refs.analysisItemRef.forEach((i) => {
+					i.editBtn();
+				});
+			} else {
+				this.$nextTick(()=>{
+					this.$refs.analysisItemRef[this.analysisItemList.findIndex((i) => i.id == id)].editBtn();
+				})
+				
+			}
 		},
-		getReport(){
-			this.$refs.analysisItemRef.forEach(i=>{
-				i.editBtn();
-			})
-		}
 	},
 };
 </script>
@@ -391,7 +418,7 @@ export default {
 	align-items: center;
 	cursor: pointer;
 }
-.a_m_empty{
+.a_m_empty {
 	display: flex;
 	width: 100%;
 	justify-content: center;

+ 176 - 181
src/components/pages/classroomObservation/components/analysisItem.vue

@@ -1,5 +1,5 @@
 <template>
-	<div class="analysisItem" v-loading="loading">
+	<div class="analysisItem">
 		<div class="ai-header">
 			<div class="ai-h-left" @click.stop="changeOpenItem(!openItem)">
 				<span
@@ -8,47 +8,66 @@
 				<span class="ai-h-l-text">{{ data.jsonData.name }}</span>
 			</div>
 			<div class="ai-h-right">
-				<!-- <span class="ai-h-r-icon1" @click.stop="backLeft()"></span> -->
-				<!-- <span class="ai-h-r-icon2" @click.stop="backRight()"></span> -->
-				<!-- <span class="ai-h-r-icon3" @click.stop="editBtn()"></span> -->
-				<span v-if="!openItem" class="ai-h-r-icon4" @click.stop="delBtn()"></span>
-				<span v-if="openItem" class="ai-h-r-icon1" @click.stop="backLeft()"></span>
-				<span v-if="openItem" class="ai-h-r-icon2" @click.stop="backRight()"></span>
-				<span v-if="openItem" class="ai-h-r-icon3" @click.stop="editBtn()"></span>
+				<span style="width: 100px; color: red" v-if="loadNum == 2"
+					>优化失败
+				</span>
+				<span
+					:class="loading ? 'text1' : 'text2'"
+					style="width: 100px"
+					v-if="loadNum == 1"
+					>{{ loading ? "优化中..." : "优化完成" }}
+				</span>
+				<span
+					v-if="loadNum == 0 && !openItem"
+					class="ai-h-r-icon4"
+					@click.stop="delBtn()"
+				></span>
+				<span
+					v-if="loadNum == 0 && openItem"
+					:class="['ai-h-r-icon1',showIndex<=0?'ai_h_r_iconOpacity':'']"
+					@click.stop="changeShowIndex(-1)"
+				></span>
+				<span
+					v-if="loadNum != 1 && openItem"
+					:class="['ai-h-r-icon2',showIndex>=historyResult.length-1?'ai_h_r_iconOpacity':'']"
+					@click.stop="changeShowIndex(1)"
+				></span>
+				<span
+					v-if="loadNum != 1 && openItem"
+					class="ai-h-r-icon3"
+					@click.stop="editBtn()"
+				></span>
 				<!-- <span class="ai-h-r-icon4" @click.stop="delBtn()"></span> -->
 			</div>
 		</div>
-		<div class="ai-main" v-if="openItem" >
-			<!-- <div class="a-m-title">
-				<span></span>
-				<div>{{ data.title }}分析</div>
-			</div> -->
+		<div class="ai-main" v-if="openItem">
+
 
 			<div class="a-m-brief">
-				<mdView :text="data.jsonData.result"/>
+				<mdView :text="data.jsonData.result" />
 				<!-- {{ data.jsonData.result }} -->
 			</div>
-			<div v-for="(item,index) in data.jsonData.dataFileList" :key="item.uid">
+			<div v-for="(item, index) in data.jsonData.dataFileList" :key="item.uid">
 				<div v-if="imgTypeList.includes(checkFileType(item.url))">
-					<img style="max-width: 100%;" :src="item.url" alt="" />
+					<img style="max-width: 100%" :src="item.url" alt="" />
 				</div>
-				<div v-else-if="checkFileType(item.url)=='md'">
-					<mdView :url="item.url"/>
+				<div v-else-if="checkFileType(item.url) == 'md'">
+					<mdView :url="item.url" />
 				</div>
-				<div v-else-if="checkFileType(item.url)=='json'">
-					<pieChart :url="item.url"/>
+				<div v-else-if="checkFileType(item.url) == 'json'">
+					<pieChart :url="item.url" />
 				</div>
 			</div>
 
-			<div v-for="(item,index) in data.jsonData.fileList" :key="item.uid">
+			<div v-for="(item, index) in data.jsonData.fileList" :key="item.uid">
 				<div v-if="imgTypeList.includes(checkFileType(item.url))">
-					<img style="max-width: 100%;" :src="item.url" alt="" />
+					<img style="max-width: 100%" :src="item.url" alt="" />
 				</div>
-				<div v-else-if="checkFileType(item.url)=='md'">
-					<mdView :url="item.url"/>
+				<div v-else-if="checkFileType(item.url) == 'md'">
+					<mdView :url="item.url" />
 				</div>
-				<div v-else-if="checkFileType(item.url)=='json'">
-					<pieChart :url="item.url"/>
+				<div v-else-if="checkFileType(item.url) == 'json'">
+					<pieChart :url="item.url" />
 				</div>
 			</div>
 		</div>
@@ -56,13 +75,13 @@
 </template>
 
 <script>
-import mdView from './mdView.vue';
-import pieChart from './pieChart.vue';
+import mdView from "./mdView.vue";
+import pieChart from "./pieChart.vue";
 export default {
-	emits:["delItem","editItem"],
-	components:{
+	emits: ["delItem", "editItem"],
+	components: {
 		mdView,
-		pieChart
+		pieChart,
 	},
 	props: {
 		data: {
@@ -71,183 +90,148 @@ export default {
 				return {};
 			},
 		},
-		index:{
-			type:Number,
-			default:0
+		dialogTagDataList:{
+			type:Array,
+			default:()=>{
+				return []
+			}
+		},
+		index: {
+			type: Number,
+			default: 0,
 		},
-		tid:{
-			type:String,
-			require:true,
+		tid: {
+			type: String,
+			require: true,
+		},
+		fileId: {
+			type: String,
+			require: true,
 		},
-		fileId:{
-			type:String,
-			require:true,
-		}
 	},
 	data() {
 		return {
 			openItem: false,
-			loading:false,
-			imgTypeList:[
+			loading: false,
+			loadNum: 0,
+			showIndex:0,
+			historyResult:[],
+			imgTypeList: [
 				"png",
-    		"jpg",
-    		"jpeg",
-    		"bmp",
-    		"gif",
-    		"webp",
-    		"psd",
-    		"svg",
-    		"tiff",
-			]
+				"jpg",
+				"jpeg",
+				"bmp",
+				"gif",
+				"webp",
+				"psd",
+				"svg",
+				"tiff",
+			],
 		};
 	},
-	computed:{
-		checkFileType(){
-			return (url)=>{
-				return url.split('.').pop();
-			}
-		}
+	computed: {
+		checkFileType() {
+			return (url) => {
+				return url.split(".").pop();
+			};
+		},
+	},
+	watch:{
+		// showIndex(){
+		// 	let _copyData = JSON.parse(JSON.stringify(this.data));
+		// 	_copyData.jsonData = this.historyResult[this.showIndex];
+		// 	_copyData.json_data = JSON.stringify(_copyData.jsonData);
+		// 	this.$emit("editItem", this.data.id, _copyData);
+		// }
 	},
 	methods: {
 		changeOpenItem(newValue) {
+			if (this.loading == true && this.loadNum != 0)
+				return this.$message("请稍后...");
+			this.loadNum = 0;
 			this.openItem = newValue;
 		},
-		backLeft() {
-			this.$message.info("回退左");
-		},
-		backRight() {
-			this.$message.info("回退右");
-		},
 		editBtn() {
-			console.log("👇")
-			this.loading = true;
-			let assistant_id = {
-					"课堂观察": { value: "8ab07d41-e143-11ee-aaca-12e77c4cb76b", type: 0 },
-					"教学阶段九事件分析": {
-						value: "5e0466b3-0075-11ef-aaca-12e77c4cb76b",
-						type: 0,
-					},
-					"OMO智慧课堂分析": {
-						value: "4cc367c1-0076-11ef-aaca-12e77c4cb76b",
-						type: 0,
-					},
-					"布鲁姆问题分类": {
-						value: "eac63117-00a7-11ef-aaca-12e77c4cb76b",
-						type: 0,
-					},
-					"麦卡锡问题分类": {
-						value: "18545cf7-0125-11ef-aaca-12e77c4cb76b",
-						type: 0,
-					},
-					"学生回答统计": {
-						value: "2c6ede88-0125-11ef-aaca-12e77c4cb76b",
-						type: 0,
-					},
-					"课堂活动类型": {
-						value: "41d2d2d4-0125-11ef-aaca-12e77c4cb76b",
-						type: 1,
-					},
-					"素养目标分析": {
-						value: "b13a98de-0125-11ef-aaca-12e77c4cb76b",
-						type: 1,
-					},
-					"科学教育目标分析": {
-						value: "d6cd48ab-0125-11ef-aaca-12e77c4cb76b",
-						type: 1,
-					},
-					"5E课程改编": {
-						value: "f757826e-0125-11ef-aaca-12e77c4cb76b",
-						type: 2,
-					},
-					"5EX课程改编": {
-						value: "0b6b08b7-0126-11ef-aaca-12e77c4cb76b",
-						type: 2,
-					},
-					"UTOP课程观察":{
-						value: "8e3a389b-014f-11ef-aaca-12e77c4cb76b",
-						type: 3,
-					},
-					"RST模型":{
-						value:"e649112e-0150-11ef-aaca-12e77c4cb76b",
-						type:3,
-					},
-					"RTOP模型":{
-						value:"68265b18-0151-11ef-aaca-12e77c4cb76b",
-						type:3,
-					},
-					"课堂质量评价":{
-						value:"25e53379-0152-11ef-aaca-12e77c4cb76b",
-						type:3,
-					},
-					"SCOP课堂观察":{
-						value:"d0c76d35-0152-11ef-aaca-12e77c4cb76b",
-						type:3,
-					},
-					"RTOP课堂观察":{
-						value:"2ace7ff6-0154-11ef-aaca-12e77c4cb76b",
-						type:3
-					}
+			this.$nextTick(() => {
+				this.loading = true;
+				this.openItem = false;
+				this.loadNum = 1;
+				let assistant = this.dialogTagDataList.find(i=>i.title==this.data.jsonData.name);
+				let parm = {
+					assistant_id: assistant?assistant.value:null,
+					message:
+						"请使用代码解析器获取文件,帮我根据要求完整的分析,输出请按照要求。",
+					session_name: new Date().getTime(),
+					userId: "1cf9dc4b-d95f-11ea-af4c-52540005ab01",
+					file_ids: this.fileId?[this.fileId]:'',
 				};
-			let file_ids = {
-				'03':["file-E8SvjCHbmhmjKczRWr11OuHx"],
-				'04':["file-r5phg4I2oFqly4WpW7oOOTnA"],
-			}
-			let parm = {
-				assistant_id:assistant_id[this.data.jsonData.name]?assistant_id[this.data.jsonData.name].value:null,
-				message: "请使用代码解析器获取文件,帮我根据要求完整的分析,输出请按照要求。",
-				session_name: new Date().getTime(),
-				userId:"1cf9dc4b-d95f-11ea-af4c-52540005ab01",
-				file_ids:this.fileId?[this.fileId]:file_ids[this.tid],
-			}
 
-			if(!parm.assistant_id){
-				this.loading = false;
-				return this.$message.error("未找到对应的AI助手")
-			}
-
-			this.ajax.post("https://gpt4.cocorobo.cn/ai_agent_park_chat",parm).then(res=>{
-				console.log("👇👇")
-				let _data = res.data.FunctionResponse;
-				if(!_data.message || _data.message.indexOf('由于我无法直接访问您上传的文件内容')>-1){
+				if (!parm.assistant_id) {
 					this.loading = false;
-					return this.$message.error("AI无法识别优化")
+					this.loadNum = 2;
+					return this.$message.error("未找到对应的AI助手");
 				}
-				let _copyData = JSON.parse(JSON.stringify(this.data))
-				_copyData.jsonData.result = _data.message;
-				_copyData.jsonData.dataFileList = [];
-				_copyData.jsonData.fileList = [];
-				_copyData.json_data = JSON.stringify(_copyData.jsonData)
-				this.$emit("editItem",this.data.id,_copyData);
-				let pram2 = {
-					id: _copyData.id,
-					json_data: _copyData.json_data,
-				};
+
 				this.ajax
-				.post(
-					"https://gpt4.cocorobo.cn/update_classroom_observation",
-					pram2
-				)
-				this.loading = false;
-			}).catch(err=>{
-				this.$message.error("AI无法识别优化")
-				this.loading = false;
-			})
-			// this.$emit
-			// setTimeout(()=>{
-			// 	this.loading = false;
-			// 	this.$emit("editItem", this.data);
-			// },1000)
+					.post("https://gpt4.cocorobo.cn/ai_agent_park_chat", parm)
+					.then((res) => {
+						let _data = res.data.FunctionResponse;
+						if (
+							!_data.message ||
+							_data.message.indexOf("由于我无法直接访问您上传的文件内容") > -1
+						) {
+							this.loading = false;
+							return this.$message.error("AI无法识别优化");
+						}
+						let _copyData = JSON.parse(JSON.stringify(this.data));
+						_copyData.jsonData.result = _data.message;
+						_copyData.jsonData.dataFileList = [];
+						_copyData.jsonData.fileList = [];
+						_copyData.json_data = JSON.stringify(_copyData.jsonData);
+						if(this.historyResult.length==0){
+							this.historyResult.push(_copyData.jsonData)
+						}else{
+							this.historyResult.splice(this.showIndex+1,0,_copyData.jsonData)
+						}
+						this.changeShowIndex(1);
+						this.loading = false;
+					})
+					.catch((err) => {
+						this.$message.error("AI无法识别优化");
+						this.loading = false;
+					});
+			});
 		},
 		delBtn() {
 			this.$confirm("确定删除?", "提示", {
 				confirmButtonText: "确定",
 				cancelButtonText: "取消",
 				type: "error",
-			})
-			.then(() => {
-				this.$emit("delItem", this.data.id)
-			})
+			}).then(() => {
+				this.$emit("delItem", this.data.id);
+			});
 		},
+		changeShowIndex(value){
+			if(this.historyResult.length==0)return;
+			if(value==-1){
+				if(this.showIndex>0)this.showIndex--;
+			}else if(value==1){
+				if(this.showIndex<this.historyResult.length-1)this.showIndex++;
+			}
+			let _copyData = JSON.parse(JSON.stringify(this.data));
+			let _oldCopyDate = JSON.parse(JSON.stringify(this.data));
+			_copyData.jsonData = this.historyResult[this.showIndex];
+			_copyData.json_data = JSON.stringify(_copyData.jsonData);
+			_oldCopyDate.json_data = JSON.stringify(_oldCopyDate.jsonData);
+			// 一样就不用更新了
+			if(JSON.stringify(_copyData)==JSON.stringify(_oldCopyDate))return;
+			this.$emit("editItem", this.data.id, _copyData);
+		}
+	},
+	mounted(){
+		if(this.data.jsonData.result){
+			this.historyResult.push(this.data.jsonData)
+		}
 	},
 };
 </script>
@@ -262,6 +246,12 @@ export default {
 	padding-right: 10px;
 	box-sizing: border-box;
 }
+.text1 {
+	color: rgba(54, 129, 252, 1);
+}
+.text2 {
+	color: rgba(23, 196, 105, 1);
+}
 .ai-header {
 	width: 100%;
 	height: 50px;
@@ -323,6 +313,11 @@ export default {
 	background: url("../../../../assets/icon/classroomObservation/back.png");
 }
 
+.ai_h_r_iconOpacity{
+	opacity: 0.5;
+	cursor: not-allowed !important;
+}
+
 .ai-h-r-icon3 {
 	background: url("../../../../assets/icon/classroomObservation/edit.png");
 	/* background: url("../../../../assets/icon/classroomObservation/del.png"); */

+ 123 - 17
src/components/pages/classroomObservation/components/baseMessage.vue

@@ -1,5 +1,5 @@
 <template>
-	<div class="message">
+	<div class="message" >
 		<div class="m-header" @click.stop="changeShowMain(!showMain)">
 			<span :class="['m-h-icon', showMain ? 'm-h-icon-active' : '']"></span>
 			<span class="m-h-title">{{ title }}</span>
@@ -12,6 +12,7 @@
 						<el-input
 							v-model="data.courseName"
 							placeholder="请输入课程名称"
+							@change="changeData()"
 						></el-input>
 					</div>
 				</div>
@@ -20,7 +21,7 @@
 					<div class="m-m-formItemBot">
 						<div class="m-m-fi-label">授课年级</div>
 						<div class="m-m-fi-input">
-							<el-select v-model="data.grade" placeholder="请选择年级">
+							<el-select v-model="data.grade" @change="changeData()" placeholder="请选择年级">
 								<el-option
 									v-for="(item, index) in gradeList"
 									:key="index"
@@ -34,7 +35,7 @@
 					<div class="m-m-formItemBot">
 						<div class="m-m-fi-label">授课科目</div>
 						<div class="m-m-fi-input">
-							<el-select v-model="data.subject" placeholder="请选择年级">
+							<el-select v-model="data.subject" @change="changeData()" placeholder="请选择年级">
 								<el-option
 									v-for="(item, index) in subjectList"
 									:key="index"
@@ -46,11 +47,12 @@
 					</div>
 
 					<div class="m-m-formItemBot">
-						<div class="m-m-fi-label">授课班级</div>
+						<div class="m-m-fi-label">教材版本</div>
 						<div class="m-m-fi-input">
 							<el-input
-								v-model="data.class"
-								placeholder="请输入班级"
+								v-model="data.textbook"
+								placeholder="请输入教材版本"
+								@change="changeData()"
 							></el-input>
 						</div>
 					</div>
@@ -65,6 +67,7 @@
 						<el-input
 							v-model="data.teacherName"
 							placeholder="请输入授课老师"
+							@change="changeData()"
 						></el-input>
 					</div>
 				</div>
@@ -75,6 +78,7 @@
 						<el-input
 							v-model.number="data.studentNum"
 							placeholder="请输入学生人数"
+							@change="changeData()"
 						></el-input>
 					</div>
 				</div>
@@ -83,23 +87,27 @@
 				<span>添加课堂图片</span>
 				<span>(建议图片比例16:9,最多上传3张图片)</span>
 			</div>
-			<div class="m-m-formImage">
+			<div class="m-m-formImage" v-loading="uploadImageLoading">
 				<div class="m-m-fi-imageList">
 					<div class="m-m-fi-imageList">
 						<div
 							class="m-m-fi-imageItem"
 							v-for="(value,key,index) in imageList"
 							:key="index"
-							v-if="key.indexOf('fileList')!=-1&&index!=0"
+							v-if="key.indexOf('fileList')!=-1&&index!=0 && value.length>0"
 							@click.stop="previewImg(value[0].url)"
 						>
-
-							<img class="itemUrl" :src="value[0].url" alt="" />
+						<el-image
+						class="itemUrl"
+      			:src="value[0].url"
+      			fit="cover"></el-image>
+						<span @click.stop="delImage(key)">x</span>
+							<!-- <img class="itemUrl" :src="value[0].url" alt="" /> -->
 						</div>
 						<!-- 图片区域 -->
 					</div>
 
-					<div class="m-m-fi-imageItem" @click.stop="addImage()">
+					<div class="m-m-fi-imageItem"  @click.stop="addImage()" v-if="imageList.fileList1&&(imageList.fileList1.length+imageList.fileList2.length+imageList.fileList3.length)<3">
 						<img
 							src="../../../../assets/icon/classroomObservation/Union.png"
 							alt=""
@@ -125,6 +133,7 @@
 
 <script>
 export default {
+	emits:["saveData","saveImage","delImage"],
 	props:{
 		data:{
 			type:Object,
@@ -143,6 +152,7 @@ export default {
 		return {
 			title: "基本信息",
 			showMain: true,
+			uploadImageLoading:false,
 			from: {
 				courseName: "",
 				teacherName: "",
@@ -162,14 +172,83 @@ export default {
 			subjectList: [{ value: "科学", label: "科学" }],
 		};
 	},
-	watch:{
-		data(newValue){
-			this.from = newValue;
-		}
-	},
 	methods: {
+		// 添加图片
 		addImage() {
-			this.$message.info("添加课堂图片");
+			// 上传录音
+			let input = document.createElement("input");
+			input.type = "file";
+			input.accept = "image/*";
+			input.click();
+			input.onchange = () => {
+				this.uploadImageLoading = true;
+				let file = input.files[0];
+				var credentials = {
+					accessKeyId: "AKIATLPEDU37QV5CHLMH",
+					secretAccessKey: "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",
+				}; //秘钥形式的登录上传
+				window.AWS.config.update(credentials);
+				window.AWS.config.region = "cn-northwest-1"; //设置区域
+
+				var bucket = new window.AWS.S3({ params: { Bucket: "ccrb" } }); //选择桶
+				var _this = this;
+
+				if (file) {
+					var params = {
+						Key:
+							file.name.split(".")[0] +
+							new Date().getTime() +
+							"." +
+							file.name.split(".")[file.name.split(".").length - 1],
+						ContentType: file.type,
+						Body: file,
+						"Access-Control-Allow-Credentials": "*",
+						ACL: "public-read",
+					}; //key可以设置为桶的相抵路径,Body为文件, ACL最好要设置
+					var options = {
+						partSize: 2048 * 1024 * 1024,
+						queueSize: 2,
+						leavePartsOnError: true,
+					};
+					bucket
+						.upload(params, options)
+						.on("httpUploadProgress", function (evt) {
+							//这里可以写进度条
+							// console.log("Uploaded : " + parseInt((evt.loaded * 80) / evt.total) + '%');
+						})
+						.send(function (err, data) {
+							if (err) {
+								_this.$message.error("上传失败");
+							} else {
+								_this.$emit("saveImage",{
+									name:data.key,
+									status:"success",
+									uid:"1",
+									url:data.Location
+								});
+								// _this.from.audioUrl = data.Location;
+								// _this.from.audioName = file.name;
+								// _this.from.audioSize = file.size;
+								// _this.from.audioTime = file.lastModified;
+
+								// console.log(data.Location)
+							}
+							_this.uploadImageLoading = false;
+						});
+				}
+			};
+			// this.mainBtnStatus = 1;
+			// this.barNum = 4;
+		},
+		// 删除图片
+		delImage(key){
+			this.$confirm('确定删除该图片吗?', '提示', {
+				confirmButtonText: '确定',
+				cancelButtonText: '取消',
+				type: 'warning'
+			}).then(() => {
+				this.$emit("delImage",key);
+			})
 		},
 		changeShowMain(newValue) {
 			this.showMain = newValue;
@@ -177,6 +256,9 @@ export default {
 		previewImg(url) {
 			this.$hevueImgPreview(url);
 		},
+		changeData(){
+			this.$emit("saveData");
+		},
 	},
 	mounted(){
 		
@@ -326,9 +408,33 @@ export default {
 	box-sizing: border-box;
 	font-size: 14px;
 	cursor: pointer;
+	position: relative;
 }
 .m-m-fi-imageItem > .itemUrl {
 	width: 100%;
+	height: 100%;
+}
+
+.m-m-fi-imageItem>span{
+	width:30px;
+	height: 30px;
+	position: absolute;
+	right: 0;
+	top: 0;
+	display: flex;
+	justify-content: flex-end;
+	align-items: flex-start;
+	box-sizing: border-box;
+	padding: 2px 10px;
+	color: white;
+	background-color: #e60012;
+	cursor: pointer;
+	border-radius: 0 0 0 100%;
+	display: none;
+}
+
+.m-m-fi-imageItem:hover>span{
+	display: flex;
 }
 
 .m-m-fi-i-icon {

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1132 - 245
src/components/pages/classroomObservation/components/chatArea.vue


+ 4 - 0
src/components/pages/classroomObservation/components/mdView.vue

@@ -114,4 +114,8 @@ export default {
     text-align: center;
     padding: 10px 10px;
 }
+
+.mdView>>>ol{
+	margin-left: 20px;
+}
 </style>

+ 433 - 289
src/components/pages/classroomObservation/components/messageArea.vue

@@ -21,49 +21,64 @@
 			<baseMessage
 				:data="bmData.jsonData"
 				:imageList="imageList.jsonData"
+				@saveData="saveBaseData"
+				@saveImage="saveBaseImage"
+				@delImage="delBaseImageList"
 				v-loading="baseMessageLoading"
 			/>
 
-			<analysis @updateMessage="updateMessage"
+			<analysis
+				@updateMessage="updateMessage"
 				ref="analysis0"
 				@delItem="delAnalysisItem"
 				@editItem="editAnalysisItem"
 				title="通用课堂分析"
+				:dialogTagDataList="dialogTagDataList"
 				:analysisItemList="dataList.filter((i) => i.Type === 0)"
 				:type="0"
 				:tid="tid"
 				:fileId="fileId"
-				v-loading="currencyLoading"/>
-			<analysis @updateMessage="updateMessage"
+				v-loading="currencyLoading"
+			/>
+			<analysis
+				@updateMessage="updateMessage"
 				ref="analysis1"
 				@delItem="delAnalysisItem"
 				@editItem="editAnalysisItem"
 				title="科学课堂分析"
+				:dialogTagDataList="dialogTagDataList"
 				:analysisItemList="dataList.filter((i) => i.Type === 1)"
 				:type="1"
 				:tid="tid"
 				:fileId="fileId"
-				v-loading="scienceLoading"/>
-			<analysis @updateMessage="updateMessage"
+				v-loading="scienceLoading"
+			/>
+			<analysis
+				@updateMessage="updateMessage"
 				ref="analysis2"
 				@delItem="delAnalysisItem"
 				@editItem="editAnalysisItem"
 				title="扩展分析"
+				:dialogTagDataList="dialogTagDataList"
 				:analysisItemList="dataList.filter((i) => i.Type === 2)"
 				:type="2"
 				:tid="tid"
 				:fileId="fileId"
-				v-loading="extendLoading"/>
-			<analysis @updateMessage="updateMessage"
+				v-loading="extendLoading"
+			/>
+			<analysis
+				@updateMessage="updateMessage"
 				ref="analysis3"
 				@delItem="delAnalysisItem"
 				@editItem="editAnalysisItem"
 				title="增值性分析"
+				:dialogTagDataList="dialogTagDataList"
 				:analysisItemList="dataList.filter((i) => i.Type === 3)"
 				:type="3"
 				:tid="tid"
 				:fileId="fileId"
-				v-loading="valueAddedLoading"/>
+				v-loading="valueAddedLoading"
+			/>
 			<!-- <currencyAnalysis
 				@updateMessage="updateMessage"
 				@delItem="delAnalysisItem"
@@ -104,6 +119,7 @@
 						placeholder="请输入内容"
 						prefix-icon="el-icon-search"
 						v-model="input2"
+						clearable
 					>
 					</el-input>
 				</div>
@@ -145,7 +161,7 @@
 					<div style="display: flex; flex-wrap: wrap">
 						<div
 							class="a-d-b-item"
-							v-for="(item, index) in dialogTagDataList.filter(i=>i.type==tagIndex)"
+							v-for="(item, index) in searchDataList"
 							:key="index"
 						>
 							<div class="a-d-b-i-top">
@@ -170,7 +186,10 @@
 									"
 								>
 									<!-- <div class="a-d-b-i-t-btn">详情</div> -->
-									<div class="a-d-b-i-t-btn1" @click="addAnalysisItem(item.title)">
+									<div
+										class="a-d-b-i-t-btn1"
+										@click="addAnalysisItem(item.title)"
+									>
 										添加
 									</div>
 								</div>
@@ -192,22 +211,23 @@ import baseMessage from "./baseMessage.vue"; //基本信息
 import analysis from "./analysis.vue";
 
 export default {
+	emits:["changeChatAreaAudioUrl","changeTranscription","changeOptionData"],
 	components: {
 		baseMessage,
 		// currencyAnalysis,
 		// scienceAnalysis,
 		// extendAnalysis,
-		analysis
+		analysis,
 	},
 	props: {
 		tid: {
 			type: String,
 			default: "",
 		},
-		fileId:{
-			type:String,
-			default:""
-		}
+		fileId: {
+			type: String,
+			default: "",
+		},
 	},
 	data() {
 		return {
@@ -215,135 +235,182 @@ export default {
 			dialogVisible: false,
 			tagIndex: 0,
 			loading: false,
-			baseMessageLoading:false,
+			baseMessageLoading: false,
 			currencyLoading: false,
 			scienceLoading: false,
 			extendLoading: false,
-			valueAddedLoading:false,
+			valueAddedLoading: false,
 			input2: "",
 			dialogTagList: [
 				{ id: 0, name: "通用课堂分析" },
 				{ id: 1, name: "科学课堂分析" },
 				{ id: 2, name: "扩展分析" },
-				{ id: 3, name: "增值性分析"}
+				{ id: 3, name: "增值性分析" },
 			],
 			dialogTagDataList: [
-					{
-						title: "OMO智慧课堂分析",
-						brief: "多维度分析课堂整体情况",
-						type:0
-					},
-					{
-						title: "教学阶段九事件分析",
-						brief: "使用加涅九事件分析教学环节",
-						type:0
-					},
-					{
-						title: "布鲁姆问题分类",
-						brief: "多维度分析课堂整体情况",
-						type:0
-					},
-					{
-						title: "麦卡锡问题分类",
-						brief: "多维度分析课堂整体情况",
-						type:0
-					},
-					{
-						title: "学生回答情况",
-						brief: "多维度分析课堂整体情况",
-						type:0
-					},
-					{ title: "课堂时间分配", brief: "多维度分析课堂整体情况",type:0 },
-					{ title: "师生互动分析", brief: "多维度分析课堂整体情况",type:0 },
-					{ title: "教学模式分析", brief: "多维度分析课堂整体情况",type:0 },
-					{
-						title: "课堂活动类型",
-						brief: "多维度分析课堂整体情况",
-						type:1
-					},
-					{
-						title: "学科核心素养发展",
-						brief: "使用加涅九事件分析教学环节",
-						type:1
-					},
-					{
-						title: "科学教育目标分析",
-						brief: "多维度分析课堂整体情况",
-						type:1
-					},
-					{
-						title: "PORTAAL课堂观察",
-						brief: "使用加涅九事件分析教学环节",
-						type:1
-					},
-					{
-						title: "5E课程改编",
-						brief: "多维度分析课堂整体情况",
-						type:2
-					},
-					{
-						title: "5EX课程改编",
-						brief: "使用加涅九事件分析教学环节",
-						type:2
-					},
-					{
-						title:"UTOP课程观察",
-						brief:"多维度分析课堂整体情况",
-						value: "8e3a389b-014f-11ef-aaca-12e77c4cb76b",
-						type: 3,
-					},
-					{
-						title:"RST模型",
-						brief:"多维度分析课堂整体情况",
-						value:"e649112e-0150-11ef-aaca-12e77c4cb76b",
-						type:3,
-					},
-					{
-						title:"RTOP模型",
-						brief:"多维度分析课堂整体情况",
-						value:"68265b18-0151-11ef-aaca-12e77c4cb76b",
-						type:3,
-					},
-					{
-						title:"课堂质量评价",
-						brief:"多维度分析课堂整体情况",
-						value:"25e53379-0152-11ef-aaca-12e77c4cb76b",
-						type:3,
-					},
-					{
-						title:"SCOP课堂观察",
-						brief:"多维度分析课堂整体情况",
-						value:"d0c76d35-0152-11ef-aaca-12e77c4cb76b",
-						type:3,
-					},
-					{
-						title:"RTOP课堂观察",
-						brief:"多维度分析课堂整体情况",
-						value:"2ace7ff6-0154-11ef-aaca-12e77c4cb76b",
-						type:3
-					}
+				{
+					title: "OMO智慧课堂分析",
+					brief: "多维度分析课堂整体情况",
+					value: "4cc367c1-0076-11ef-aaca-12e77c4cb76b",
+					type: 0,
+				},
+				{
+					title: "教学阶段九事件分析",
+					brief: "使用加涅九事件分析教学环节",
+					value: "5e0466b3-0075-11ef-aaca-12e77c4cb76b",
+					type: 0,
+				},
+				{
+					title: "布鲁姆问题分类",
+					brief: "多维度分析课堂整体情况",
+					value: "eac63117-00a7-11ef-aaca-12e77c4cb76b",
+					type: 0,
+				},
+				{
+					title: "麦卡锡问题分类",
+					brief: "多维度分析课堂整体情况",
+					value: "18545cf7-0125-11ef-aaca-12e77c4cb76b",
+					type: 0,
+				},
+				{
+					title: "学生回答情况",
+					brief: "多维度分析课堂整体情况",
+					value: "d3f75199-eb4e-11ee-aaca-12e77c4cb76b",
+					type: 0,
+				},
+				// {
+				// 	title: "课堂时间分配",
+				// 	brief: "多维度分析课堂整体情况",
+				// 	type: 0
+				// },
+				// {
+				// 	title: "师生互动分析",
+				// 	brief: "多维度分析课堂整体情况",
+				// 	type: 0
+				// },
+				// {
+				// 	title: "教学模式分析",
+				// 	brief: "多维度分析课堂整体情况",
+				// 	type: 0
+				// },
+				{
+					title: "课堂活动类型",
+					brief: "多维度分析课堂整体情况",
+					value: "41d2d2d4-0125-11ef-aaca-12e77c4cb76b",
+					type: 1,
+				},
+				{
+					title: "学科核心素养发展",
+					brief: "学科核心素养发展",
+					value: "b13a98de-0125-11ef-aaca-12e77c4cb76b",
+					type: 1,
+				},
+				{
+					title: "科学教育目标分析",
+					brief: "科学教育目标分析",
+					value: "b13a98de-0125-11ef-aaca-12e77c4cb76b",
+					type: 1,
+				},
+				{
+					title: "PORTAAL课堂观察",
+					brief: "PORTAAL课堂观察",
+					value: "8ab07d41-e143-11ee-aaca-12e77c4cb76b",
+					type: 1,
+				},
+				{
+					title: "UTOP课堂观察",
+					brief: "UTOP课堂观察",
+					value: "8e3a389b-014f-11ef-aaca-12e77c4cb76b",
+					type: 1,
+				},
+				{
+					title:"L-PST模型",
+					brief: "L-PST模型",
+					value: "e649112e-0150-11ef-aaca-12e77c4cb76b",
+					type: 1,
+				},
+				// {
+				// 	title: "RST模型",
+				// 	brief: "多维度分析课堂整体情况",
+				// 	value: "e649112e-0150-11ef-aaca-12e77c4cb76b",
+				// 	type: 1,
+				// },
+				{
+					title: "RTOP模型",
+					brief: "多维度分析课堂整体情况",
+					value: "68265b18-0151-11ef-aaca-12e77c4cb76b",
+					type: 1,
+				},
+				{
+					title: "课程质量评价",
+					brief: "多维度分析课堂整体情况", 
+				 	value:"25e53379-0152-11ef-aaca-12e77c4cb76b",
+					type: 1,
+				},
+				{
+					title: "SCOP课堂观察",
+					brief: "多维度分析课堂整体情况",
+					value: "d0c76d35-0152-11ef-aaca-12e77c4cb76b",
+					type: 1,
+				},
+				{
+					title: "5E课程改编",
+					brief: "5E课程改编",
+					value: "f757826e-0125-11ef-aaca-12e77c4cb76b",
+					type: 2,
+				},
+				{
+					title: "5EX课程改编",
+					brief: "5EX课程改编",
+					value: "0b6b08b7-0126-11ef-aaca-12e77c4cb76b",
+					type: 2,
+				},
+
 			],
 			bmData: {},
 			dataList: [],
 			imageList: {},
 		};
 	},
+	computed: {
+		searchDataList() {
+			let _data = this.dialogTagDataList.filter((i) => i.type == this.tagIndex);
+			if (this.input2) {
+				return _data.filter((i) => i.title.indexOf(this.input2) > -1);
+			} else {
+				return _data;
+			}
+		},
+	},
 	methods: {
 		delAnalysisItem(id) {
 			let _index = this.dataList.findIndex((i) => i.id == id);
 			if (_index > -1) {
-				this.dataList.splice(_index, 1);
-				this.$message.success("删除成功");
+				let _data = this.dataList[_index];
+				let params = {
+					id: _data.id,
+					type: _data.Type,
+					tid: this.tid,
+				};
+				this.ajax
+					.post("https://gpt4.cocorobo.cn/delete_classroom_observation", params)
+					.then((res) => {
+						this.dataList.splice(_index, 1);
+						this.$message.success("删除成功");
+					})
+					.catch((e) => {
+						this.$message.error("删除失败");
+					});
 			} else {
 				this.$message.error("删除失败");
 			}
 		},
 		editAnalysisItem(id, _data) {
 			let _index = this.dataList.findIndex((i) => i.id == id);
-			if (_index > -1) {
+			if (_index != -1) {
 				this.dataList[_index] = _data;
+				this.saveData(this.dataList[_index])
 				this.$forceUpdate();
-				this.$message.success("执行成功");
 			} else {
 				this.$message.info("执行错误");
 			}
@@ -374,146 +441,65 @@ export default {
 		addAnalysisItem(title) {
 			return new Promise((resolve, reject) => {
 				this.dialogVisible = false;
-				this.loading = true;
-				let assistant_id = {
-					"课堂观察": { value: "8ab07d41-e143-11ee-aaca-12e77c4cb76b", type: 0 },
-					"教学阶段九事件分析": {
-						value: "5e0466b3-0075-11ef-aaca-12e77c4cb76b",
-						type: 0,
-					},
-					"OMO智慧课堂分析": {
-						value: "4cc367c1-0076-11ef-aaca-12e77c4cb76b",
-						type: 0,
-					},
-					"布鲁姆问题分类": {
-						value: "eac63117-00a7-11ef-aaca-12e77c4cb76b",
-						type: 0,
-					},
-					"麦卡锡问题分类": {
-						value: "18545cf7-0125-11ef-aaca-12e77c4cb76b",
-						type: 0,
-					},
-					"学生回答统计": {
-						value: "2c6ede88-0125-11ef-aaca-12e77c4cb76b",
-						type: 0,
-					},
-					"课堂活动类型": {
-						value: "41d2d2d4-0125-11ef-aaca-12e77c4cb76b",
-						type: 1,
-					},
-					"素养目标分析": {
-						value: "b13a98de-0125-11ef-aaca-12e77c4cb76b",
-						type: 1,
-					},
-					"科学教育目标分析": {
-						value: "d6cd48ab-0125-11ef-aaca-12e77c4cb76b",
-						type: 1,
-					},
-					"5E课程改编": {
-						value: "f757826e-0125-11ef-aaca-12e77c4cb76b",
-						type: 2,
-					},
-					"5EX课程改编": {
-						value: "0b6b08b7-0126-11ef-aaca-12e77c4cb76b",
-						type: 2,
-					},
-					"UTOP课程观察":{
-						value: "8e3a389b-014f-11ef-aaca-12e77c4cb76b",
-						type: 3,
-					},
-					"RST模型":{
-						value:"e649112e-0150-11ef-aaca-12e77c4cb76b",
-						type:3,
-					},
-					"RTOP模型":{
-						value:"68265b18-0151-11ef-aaca-12e77c4cb76b",
-						type:3,
-					},
-					"课堂质量评价":{
-						value:"25e53379-0152-11ef-aaca-12e77c4cb76b",
-						type:3,
-					},
-					"SCOP课堂观察":{
-						value:"d0c76d35-0152-11ef-aaca-12e77c4cb76b",
-						type:3,
-					},
-					"RTOP课堂观察":{
-						value:"2ace7ff6-0154-11ef-aaca-12e77c4cb76b",
-						type:3
-					}
-				};
-				let file_ids = {
-					'03':["file-E8SvjCHbmhmjKczRWr11OuHx"],
-					'04':["file-r5phg4I2oFqly4WpW7oOOTnA"],
-				};
+				let assistant = this.dialogTagDataList.find((i) => i.title == title);
+				
 				let parm = {
-					assistant_id: assistant_id[title]
-						? assistant_id[title].value
-						: null,
-					message: "请使用代码解析器获取文件,帮我根据要求完整的分析,输出请按照要求。",
+					assistant_id: assistant ? assistant.value : null,
+					message:
+						"请使用代码解析器获取文件,帮我根据要求完整的分析,输出请按照要求。",
 					session_name: new Date().getTime(),
 					userId: "1cf9dc4b-d95f-11ea-af4c-52540005ab01",
-					file_ids: this.fileId?[this.fileId]:file_ids[this.tid],
+					file_ids: this.fileId,
 				};
 
 				if (!parm.assistant_id) {
-					this.loading = false;
 					resolve();
 					return this.$message.error("未找到对应的AI助手");
 				}
+				let newIndexData = this.dataList.filter((i) => i.Type == assistant.type).sort((a,b)=>new Date(a.createtime)-new Date(b.createtime))
+				newIndexData = newIndexData.length?newIndexData[newIndexData.length-1]:null;
+				let newIndex = newIndexData?newIndexData.tIndex+1:assistant.type==0?2:0;
+				let params = {
+					index: newIndex,
+					json_data: JSON.stringify({
+						name: assistant.title,
+						result: "",
+						fileList: [],
+						dataFileList: [],
+						content: "",
+					}),
+					tid: this.tid,
+					type: assistant.type.toString(),
+				};
+
+				// 这里调用添加
 				this.ajax
-					.post("https://gpt4.cocorobo.cn/ai_agent_park_chat", parm)
+					.post("https://gpt4.cocorobo.cn/insert_classroom_observation", params)
 					.then((res) => {
-						let result = res.data.FunctionResponse;
-						if(!result.message || result.message.indexOf('由于我无法直接访问您上传的文件内容')>-1){
-							this.loading = false;
+						let _data = res.data.FunctionResponse;
+						if (_data.message && _data.message == "创建成功") {
+							let _result = JSON.parse(_data.result)[0];
+							_result.jsonData = JSON.parse(_result.jsonData);
+							this.dataList.push(_result);
+							if (_result.Type == 0) {
+								this.$refs.analysis0.getReport(_result.id);
+							} else if (_result.Type == 1) {
+								this.$refs.analysis1.getReport(_result.id);
+							} else if (_result.Type == 2) {
+								this.$refs.analysis2.getReport(_result.id);
+							} else if (_result.Type == 3) {
+								this.$refs.analysis3.getReport(_result.id);
+							}
+							this.$message.success("添加成功");
 							resolve();
-							return this.$message.error(`${title}无法生成`)
+						} else {
+							this.$message.error("创建失败");
 						}
-						this.dataList.push({
-							id:assistant_id[result.title].value,
-							Type:assistant_id[result.title].type,
-							createTime:new Date(),
-							tId:this.tid,
-							tIndex:2,
-							jsonData:{
-								dataFileList:[],
-								fileList:[],
-								fileList2:[],
-								name:result.title,
-								result:result.message
-							}
-						})
-						resolve();
-						this.loading = false;
-					})
-					.catch((e) => {
-						this.$message.error(`${title}无法生成`)
-						this.loading = false;
-						resolve();
 					});
 			});
 		},
-		getFileId() {
-			let pram = {
-				tid: this.tid,
-				type: "10",
-			};
-			this.ajax
-				.post("https://gpt4.cocorobo.cn/get_classroom_observation_new", pram)
-				.then((res) => {
-					let _data = res.data.FunctionResponse.result.length
-						? JSON.parse(res.data.FunctionResponse.result)
-						: [];
-					this.$emit('updateFileIdid', _data[0].id)
-					if(_data[0].jsonData !='' ){
-						this.$emit("updateFileId", JSON.parse(_data[0].jsonData).file_ids)				
-					}else {
-						this.$emit("updateFileId", '')				
-					}
-				});
-		},
 		getCurrencyAndBaseMessageData() {
+			if(!this.tid)return;
 			let pram = {
 				tid: this.tid,
 				// tid:'02',
@@ -521,6 +507,23 @@ export default {
 			};
 			this.currencyLoading = true;
 			this.baseMessageLoading = true;
+			this.bmData = {
+				id: "",
+				tId: this.tid,
+				tIndex: 0,
+				jsonData: {
+					activity_methods: "",
+					activity_structure: "",
+					classroom_resources: "",
+					courseName: "",
+					name: "",
+					studentNum: 0,
+					subject: "",
+					textbook: "",
+				},
+			};
+			this.imageList = [];
+			this.dataList = [];
 			this.ajax
 				.post("https://gpt4.cocorobo.cn/get_classroom_observation_new", pram)
 				.then((res) => {
@@ -528,14 +531,15 @@ export default {
 						? JSON.parse(res.data.FunctionResponse.result)
 						: [];
 					if (_data.length == 0) {
-						this.baseMessageLoading = false;
-						return (this.currencyLoading = false);
+						return this.insertBaseMessage().then(_=>{
+							this.getCurrencyAndBaseMessageData();
+						})
 					}
-					let _bmData = _data[0];
+					let _bmData = _data.find(i=>i.tIndex==0);
 					// 基础信息
 					_bmData.jsonData = JSON.parse(_bmData.jsonData);
 					// 图片
-					let _imageList = _data[1];
+					let _imageList = _data.find(i=>i.tIndex==1);
 					_imageList.jsonData = JSON.parse(_imageList.jsonData);
 					//通用分析
 					let currency = [];
@@ -547,12 +551,22 @@ export default {
 
 					this.dataList.push(...currency);
 					this.bmData = _bmData;
+					this.$emit("changeTranscription",{transcriptionData:this.bmData.jsonData.transcriptionData?this.bmData.jsonData.transcriptionData:"",editorBarData:this.bmData.jsonData.editorBarData?this.bmData.jsonData.editorBarData:{type:"0",content:"",url:""}})
 					this.imageList = _imageList;
+					if(this.imageList.jsonData.fileList.length>0){
+						this.$emit("changeChatAreaAudioUrl",this.imageList.jsonData.fileList[0]);
+					}else{
+						this.$emit("changeChatAreaAudioUrl",{name:"",url:""});
+					}
 					this.baseMessageLoading = false;
 					this.currencyLoading = false;
+				}).catch(e=>{
+					this.$message.error("获取通用分析失败");
+					console.log(e)
 				});
 		},
 		getScienceData() {
+			if(!this.tid)return;
 			let pram = {
 				tid: this.tid,
 				// tid:'02',
@@ -576,9 +590,13 @@ export default {
 					}
 					this.dataList.push(...science);
 					this.scienceLoading = false;
+				}).catch(e=>{
+					this.$message.error("获取科学分析失败");
+					console.log(e)
 				});
 		},
 		getExtendData() {
+			if(!this.tid)return;
 			let pram = {
 				tid: this.tid,
 				// tid:'02',
@@ -602,9 +620,13 @@ export default {
 					}
 					this.dataList.push(...extent);
 					this.extendLoading = false;
+				}).catch(e=>{
+					this.$message.error("获取扩展分析失败");
+					console.log(e)
 				});
 		},
-		getValueAddedData(){
+		getValueAddedData() {
+			if(!this.tid)return;
 			let pram = {
 				tid: this.tid,
 				// tid:'02',
@@ -628,6 +650,9 @@ export default {
 					}
 					this.dataList.push(...valueAdded);
 					this.valueAddedLoading = false;
+				}).catch(e=>{
+					this.$message.error("获取增值性分析失败");
+					console.log(e)
 				});
 		},
 		getData() {
@@ -636,62 +661,181 @@ export default {
 			this.getScienceData();
 			this.getExtendData();
 			this.getValueAddedData();
-			this.getFileId();
+			// this.getFileId();
 		},
-		saveData(fn) {
+		saveData(data) {
+			return new Promise((resolve,reject)=>{
+				this.ajax.post(
+						"https://gpt4.cocorobo.cn/update_classroom_observation",
+						{
+							id: data.id,
+							json_data: JSON.stringify(data.jsonData),
+						}
+					).then(res=>{
+						resolve();
+					}).catch(e=>{
+						this.$message.error('保存失败');
+						resolve();
+					})
+			})
 			// return;
-			let saveDataList = [];
+			// let saveDataList = [];
 
-			// 保存基础信息
-			saveDataList.push({
-				id: this.bmData.id,
-				json_data: JSON.stringify(this.bmData.jsonData),
-			});
+			// // 保存基础信息
+			// saveDataList.push({
+			// 	id: this.bmData.id,
+			// 	json_data: JSON.stringify(this.bmData.jsonData),
+			// });
 
-			// 所有分析
-			this.dataList.forEach((i1) => {
-				i1.forEach((i2) => {
-					saveDataList.push({
-						id: i2.id,
-						json_data: JSON.stringify(i2.jsonData),
-					});
-				});
+			// // 所有分析
+			// this.dataList.forEach((i1) => {
+			// 	i1.forEach((i2) => {
+			// 		saveDataList.push({
+			// 			id: i2.id,
+			// 			json_data: JSON.stringify(i2.jsonData),
+			// 		});
+			// 	});
+			// });
+			// let promises = [];
+			// saveDataList.forEach((i) => {
+			// 	promises.push(
+			// 		new Promise((resolve) => {
+			// 			let pram = {
+			// 				id: i.id,
+			// 				json_data: i.json_data,
+			// 			};
+			// 			this.ajax
+			// 				.post(
+			// 					"https://gpt4.cocorobo.cn/update_classroom_observation",
+			// 					pram
+			// 				)
+			// 				.then((res) => {
+			// 					console.log(res);
+			// 					resolve();
+			// 				});
+			// 		})
+			// 	);
+			// });
+
+			// Promise.all(promises).then((res) => {
+			// 	this.$message.success("保存成功");
+			// 	fn ? fn() : "";
+			// });
+		},
+		saveBaseData(){
+			this.bmData.json_data = JSON.stringify(this.bmData.jsonData);
+			this.saveData(this.bmData).then(res=>{
+				this.$emit("changeOptionData",this.tid,{label:this.bmData.jsonData.courseName})
+			})
+		},
+		saveBaseImage(newImage){
+			if(this.imageList.jsonData.fileList1.length==0){
+				this.imageList.jsonData.fileList1.push(newImage);
+			}else if(this.imageList.jsonData.fileList2.length==0){
+				this.imageList.jsonData.fileList2.push(newImage)
+			}else if(this.imageList.jsonData.fileList3.length==0){
+				this.imageList.jsonData.fileList3.push(newImage)
+			}else{
+				this.$message.error("最多只能上传3张图片");
+				return;
+			}
+			this.imageList.json_data = JSON.stringify(this.imageList.jsonData);
+			this.saveData(this.imageList);
+		},
+		delBaseImageList(key){
+			this.imageList.jsonData[key] = [];
+			this.imageList.json_data = JSON.stringify(this.imageList.jsonData);
+			this.saveData(this.imageList).then(res=>{
+				this.$message.success("删除图片成功")
 			});
-			let promises = [];
-			saveDataList.forEach((i) => {
-				promises.push(
-					new Promise((resolve) => {
-						let pram = {
-							id: i.id,
-							json_data: i.json_data,
-						};
-						this.ajax
-							.post(
-								"https://gpt4.cocorobo.cn/update_classroom_observation",
-								pram
-							)
-							.then((res) => {
-								console.log(res);
-								resolve();
-							});
+		},
+		// 切换录音文件
+		changeAudioUrl(data){
+			this.imageList.jsonData.fileList = [];
+			let audio = {
+				name:data.key,
+				status:"success",
+				uid:"1",
+				url:data.Location
+			}
+			this.imageList.jsonData.fileList.push(audio)
+			this.saveData(this.imageList).then(res=>{
+				this.$message.success("更换录文件成功");
+				this.$emit("changeChatAreaAudioUrl",audio);
+			})
+		},
+		getReport() {
+			this.$refs.analysis0.getReport();
+			this.$refs.analysis1.getReport();
+			this.$refs.analysis2.getReport();
+			this.$refs.analysis3.getReport();
+		},
+		insertBaseMessage() {
+			return new Promise((resolve, reject) => {
+				// 添加基础信息
+				let params = {
+					index: "0",
+					json_data: JSON.stringify({
+						courseName: "",
+						studentNum: "0",
+						subject: "",
+						textbook: "",
+						classroom_resources: "",
+						activity_structure: "",
+						activity_methods: "",
+						name: "",
+					}),
+					tid: this.tid,
+					type: "0",
+				};
+				// 添加课堂图片
+				let params2 = {
+					index: "1",
+					tid: this.tid,
+					type: "0",
+					json_data: JSON.stringify({
+						fileList: [],
+						name: "课堂记录",
+						fileList1: [],
+						fileList2: [],
+						fileList3: [],
+					}),
+				};
+				this.ajax
+					.post("https://gpt4.cocorobo.cn/insert_classroom_observation", params)
+					.then((res) => {
+						let _data = res.data.FunctionResponse;
+						if (_data.message && _data.message == "创建成功") {
+							this.ajax
+								.post(
+									"https://gpt4.cocorobo.cn/insert_classroom_observation",
+									params2
+								)
+								.then((res2) => {
+									let _data2 = res2.data.FunctionResponse;
+									if (_data2.message && _data2.message == "创建成功") {
+									} else {
+										this.$message.error("创建课堂图片失败");
+									}
+									resolve();
+								});
+						} else {
+							this.$message.error("创建基础信息失败");
+						}
 					})
-				);
 			});
-
-			Promise.all(promises).then((res) => {
+		},
+		// 修改基本信息的原文速览和转录文稿
+		updateMessageTranscription({transcriptionData,editorBarData}){
+			this.bmData.jsonData['transcriptionData'] = transcriptionData;
+			this.bmData.jsonData['editorBarData'] = editorBarData;
+			this.saveData(this.bmData).then(res=>{
 				this.$message.success("保存成功");
-				fn ? fn() : "";
-			});
+			})
 		},
-		getReport(){
-			this.$refs.analysis0.getReport()
-			this.$refs.analysis1.getReport()
-			this.$refs.analysis2.getReport()
-			this.$refs.analysis3.getReport()
-		}
 	},
 	mounted() {
-		this.getData();
+		
 	},
 };
 </script>

+ 325 - 0
src/components/pages/classroomObservation/components/sharePdf.vue

@@ -0,0 +1,325 @@
+<template>
+  <el-dialog
+    :visible.sync="localDialogVisibleShare"
+    :append-to-body="true"
+    width="560px"
+    :before-close="handleClose"
+    class="dialog_diy"
+  >
+    <div class="share_box">
+     
+   
+      <div class="url_box">
+        <div class="title">
+          分享链接
+        </div>
+        <div class="url">
+          <el-tooltip :content="origin" placement="top" effect="dark">
+            <!-- content to trigger tooltip here -->
+            <span>{{ origin }}</span>
+          </el-tooltip>
+          <span @click="copy" :data-clipboard-text="copyText" class="tag-read"
+            >复制链接</span
+          >
+        </div>
+      </div>
+      <div class="qrcode_box">
+        <div class="title">
+          分享二维码
+        </div>
+        <div class="qrcode">
+          <span class="qrcodeUrl" ref="qrCodeUrl"></span>
+          <span @click="downQr">下载二维码</span>
+        </div>
+      </div>
+      <div class="btn_box">
+        <button
+          class="c_pub_button_confirm tag-read2"
+          @click="copy2"
+          :data-clipboard-text="copyText2"
+        >
+          复制信息
+        </button>
+      </div>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import Clipboard from "clipboard";
+import QRCode from "qrcodejs2";
+export default {
+  props: {
+    dialogVisibleShare: {
+      type: Boolean,
+      default: false
+    }
+  },
+  data() {
+    return {
+      origin: "",
+      copyText: "",
+      copyText2: "",
+      noCount: 0,
+      pname: [],
+      localDialogVisibleShare: this.dialogVisibleShare
+    };
+  },
+  methods: {
+    handleClose(done) {
+      this.close();
+      done();
+    },
+    close() {
+    //   this.$emit("update:dialogVisibleShare", false);
+      this.$emit('shareBtn');
+
+    },
+    setQr() {
+      setTimeout(() => {
+        let url = 'https://beta.cloud.cocorobo.cn/#/classroomObservation';
+        this.origin = url;
+        this.$refs.qrCodeUrl.innerHTML = "";
+        var qrcode = new QRCode(this.$refs.qrCodeUrl, {
+          text: url, // 需要转换为二维码的内容
+          width: 100,
+          height: 100,
+          colorDark: "#000000",
+          colorLight: "#ffffff",
+          correctLevel: QRCode.CorrectLevel.H
+        });
+      }, 500);
+    },
+    downQr() {
+      // 创建一个虚拟链接,并将 canvas 转换为图片文件
+      const link = document.createElement("a");
+      link.href = this.$refs.qrCodeUrl.querySelector("img").src;
+      link.download = "qrcode.png";
+
+      // 模拟点击链接进行下载
+      link.click();
+    },
+    copy() {
+      this.copyText = 'https://beta.cloud.cocorobo.cn/#/classroomObservation';
+      var clipboard = new Clipboard(".tag-read");
+      clipboard.on("success", e => {
+        this.$message.success("复制成功");
+        console.log("复制成功");
+        clipboard.destroy(); // 释放内存
+      });
+      clipboard.on("error", e => {
+        console.log("不支持复制,该浏览器不支持自动复制");
+        clipboard.destroy(); // 释放内存
+      });
+    },
+    copy2() {
+      let url = 'https://beta.cloud.cocorobo.cn/#/classroomObservation';
+      this.copyText2 = `链接提醒:${url}`;
+      var clipboard = new Clipboard(".tag-read2");
+      clipboard.on("success", e => {
+        this.$message.success("复制成功");
+        console.log("复制成功");
+        clipboard.destroy(); // 释放内存
+      });
+      clipboard.on("error", e => {
+        console.log("不支持复制,该浏览器不支持自动复制");
+        clipboard.destroy(); // 释放内存
+      });
+    }
+    // getData() {
+    //   // if(!this.testJson.juriP){
+    //   //     return;
+    //   // }
+    //   let params = {
+    //     id: this.testJson.courseId
+    //   };
+    //   this.ajax
+    //     .get(this.$store.state.api + "getTestWorkShare", params)
+    //     .then(res => {
+    //       let parray = res.data[0];
+    //       let is = res.data[1];
+    //       this.noCount = parray.length - is.length;
+    //       let isA = [];
+    //       for (var i = 0; i < is.length; i++) {
+    //         isA.push(is[i].userid);
+    //       }
+    //       let pname = [];
+    //       for (var i = 0; i < parray.length; i++) {
+    //         if (isA.indexOf(parray[i].userid) == -1) {
+    //           pname.push(parray[i].username);
+    //         }
+    //       }
+    //       this.pname = pname;
+    //     })
+    //     .catch(err => {
+    //       console.error(err);
+    //     });
+    // }
+  },
+  watch: {
+    dialogVisibleShare(newValue, oldValue) {
+      console.log("newValue", newValue);
+      if (newValue) {
+        this.localDialogVisibleShare=newValue
+        this.setQr();
+        // this.getData();
+        // console.log(top.origin);
+        // this.origin = top.origin
+      }
+    }
+  },
+  mounted() {
+    // console.log("this.info", this.info);
+
+    // console.log(top.origin);
+    // this.origin = top.origin
+  }
+};
+</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;
+}
+
+.share_box {
+  width: 100%;
+  height: 100%;
+  padding: 0 20px 15px;
+  box-sizing: border-box;
+}
+
+.info_box {
+  margin: 0 0 20px;
+}
+
+.info_box > .info {
+  line-height: 18px;
+}
+
+.info_box > .info > span:nth-child(1) {
+  color: #00000099;
+}
+
+.info_box > .info > span:nth-child(2) {
+  color: #000000;
+}
+
+.info_box > .info + .info {
+  margin-top: 10px;
+}
+
+.url_box {
+  margin-bottom: 20px;
+}
+
+.qrcode_box {
+  margin-bottom: 20px;
+}
+
+.url_box > .url {
+  width: 100%;
+  display: flex;
+  align-items: center;
+  border: 1px solid #e7e7e7;
+  border-radius: 4px;
+  height: 35px;
+  padding: 0 7px;
+  box-sizing: border-box;
+}
+
+.url_box > .url > span {
+  font-size: 16px;
+  color: #000000;
+}
+
+.url_box > .url > span:nth-child(1) {
+  width: 100%;
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+
+.url_box > .url > span:nth-child(2) {
+  margin-left: auto;
+  border-left: 1px solid #e7e7e7;
+  padding-left: 7px;
+  cursor: pointer;
+  min-width: fit-content;
+}
+
+.url_box > .title,
+.qrcode_box > .title {
+  font-size: 16px;
+  font-weight: 700;
+  margin-bottom: 10px;
+}
+
+.qrcode_box > .qrcode {
+  padding: 7px;
+  border: 1px solid #e7e7e7;
+  width: fit-content;
+  border-radius: 4px;
+  display: flex;
+  align-items: flex-end;
+}
+
+.qrcode_box > .qrcode > span:nth-child(1) {
+  width: 100px;
+  display: block;
+  height: 100px;
+}
+
+.qrcode_box > .qrcode > span:nth-child(2) {
+  background: #f0f2f5;
+  padding: 7px 15px;
+  font-size: 16px;
+  border-radius: 4px;
+  cursor: pointer;
+  color: #000;
+  margin-left: 7px;
+}
+
+.btn_box {
+  display: flex;
+  justify-content: flex-end;
+}
+
+.more {
+  cursor: pointer;
+  color: #0061ff;
+}
+</style>

+ 351 - 478
src/components/pages/classroomObservation/components/tape.vue

@@ -1,20 +1,111 @@
 <template>
-	<div class="tape">
+	<div class="tape" v-loading="loading">
+		<!-- <div class="t-header">
+			<div class="t-h-title">课堂录音</div>
+			<div class="t-h-time">2024-04-13 17:30:00</div>
+		</div> -->
+		<!-- <div class="t-tapeAudio">
+			<mini-audio :audio-source="audioUrl" class="audio_class"></mini-audio>
+		</div> -->
+		<!-- <div class="t-tapeFile"> -->
+			<!-- <div class="t-t-header">
+				<div class="t-t-h-left">
+					<div class="t-t-h-l-Item" :style="cardStatus==0&&foldStatus?'background:white':''" @click.stop="changeCardStatus(0)">
+						<span class="t-t-h-l-i-icon"></span>
+						<div class="t-t-h-l-i-text">录音原文</div>
+					</div>
+					<div class="t-t-h-l-Item" :style="cardStatus==1&&foldStatus?'background:white':''" @click.stop="changeCardStatus(1)">
+						<span class="t-t-h-l-i-icon"></span>
+						<div class="t-t-h-l-i-text">转录文稿.xlsx</div>
+					</div>
+				</div>
+				<div class="t-t-h-right" @click.stop="changeFoldStatus(!foldStatus)">
+					<span class="t-t-h-r-icon" :style="`transform: scaleY(${foldStatus==0?1:-1});`"></span>
+					<div class="t-t-h-r-text">{{ foldStatus==0 ? '展开' : '收起'}}</div>
+				</div>
+			</div> -->
+			<!-- <div class="t-t-main" v-show="foldStatus">
+				<div class="t-t-m-Item" v-show="cardStatus == 0">
+					<p v-for="(item, index) in pList" :key="index" v-text="item"></p>
+				</div>
 
-		<!-- <div class="t-tapeFile">
-		
-			<div class="t-t-main" v-show="foldStatus">
-				<div class="t-t-m-Item" v-show="cardStatus==0">
-					<p v-for="(item,index) in pList" :key="index" v-text="item"></p>
+				<div class="t-t-m-Item" v-show="cardStatus == 1">
+					<iframe
+						ref="viframe"
+						style="width: 100%; height: 99%; border: none"
+						:src="
+							'https://view.officeapps.live.com/op/view.aspx?src=' +
+							encodeURIComponent(fileUrl)
+						"
+					></iframe>
 				</div>
+			</div> -->
+		<!-- </div> -->
+		<div class="t-chartArea" ref="chartAreaRef">
+			<div class="t_ca_box" v-for="(item, index) in chatData" :key="item.uid+index">
+			
+				<div class="t_ca_b_roleUser" v-if="item.content">
+					<div class="t_ca_b_u_content">
+						<div class="t_ca_b_u_c_main">
+							<div class="t_ca_b_u_c_m_left">
+								<!-- <img
+									:src="
+										require('../../../../assets/icon/classroomObservation/addWork.png')
+									"
+									@click="addWork()"
+								/> -->
+								<!-- <img
+									:src="
+										require('../../../../assets/icon/classroomObservation/copy.png')
+									"
+									@click="copyContent(item.content)"
+								/> -->
+							</div>
+							<div class="t_ca_b_u_c_m_right" v-html="item.content"></div>
+						</div>
+						<div class="t_ca_b_u_c_time">{{ item.createtime }}</div>
+					</div>
+					<div class="t_ca_b_u_avatar">
+						<el-avatar
+							size="medium"
+							:src="
+								require('../../../../assets/icon/classroomObservation/userAvatar.png')
+							"
+						></el-avatar>
+					</div>
+				</div>
+				<div class="t_ca_b_roleAi">
+					<div class="t_ca_b_ai_avatar">
+						<el-avatar
+							size="medium"
+							:src="item.filename?item.filename:require('../../../../assets/icon/classroomObservation/ai.png')"
 
-				<div class="t-t-m-Item" v-show="cardStatus==1">
-					<iframe ref="viframe" style="width: 100%; height: 100%; border: none" :src="'https://view.officeapps.live.com/op/view.aspx?src=' + encodeURIComponent(fileUrl)"></iframe>
+						></el-avatar>
+					</div>
+					<div class="t_ca_b_ai_content">
+						<div class="t_ca_b_ai_c_name">{{ item.fileid }}</div>
+						<div class="t_ca_b_ai_c_main">
+							<div class="t_ca_b_ai_c_m_left" v-loading="item.loading" v-html="item.aiContent"></div>
+							<div class="t_ca_b_ai_c_m_right">
+								<!-- <img
+									:src="
+										require('../../../../assets/icon/classroomObservation/addWork.png')
+									"
+									@click="addWork()"
+								/> -->
+								<img
+									:src="
+										require('../../../../assets/icon/classroomObservation/copy.png')
+									"
+									@click="copyContent(item.aiContent)"
+								/>
+							</div>
+						</div>
+						<div class="t_ca_b_ai_c_time">{{ item.createtime }}</div>
+					</div>
 				</div>
 			</div>
-		</div> -->
-		<div class="t-chartArea" v-show="!foldStatus">
-			<div class="t-ca-item" v-for="(item,index) in chatData" :key="index">
+			<!-- <div class="t-ca-item" v-for="(item,index) in chatData" :key="index">
 				<div class="t-ca-i-left">
 					<div class="t-ca-i-l-avatar">
 						<el-avatar size="medium" :src="require('../../../../assets/icon/classroomObservation/ai.png')"></el-avatar>
@@ -25,465 +116,118 @@
 					<div class="t-ca-i-r-time">{{ item.create_at }}</div>
 					<div class="t-ca-i-r-content">{{ item.content }}</div>
 				</div>
-			</div>
+			</div> -->
 		</div>
 	</div>
 </template>
 
 <script>
-import pdf from './pdf.vue';
-	export default {
-		components:{
-			pdf,
+import pdf from "./pdf.vue";
+export default {
+	components: {
+		pdf,
+	},
+	props: {
+		chatData: {
+			type: Array,
+			default: () => {
+				return [];
+			},
 		},
-		props:{
-			chatData:{
-				type:Array,
-				default:()=>{
-					return [];
-				}
+		aiNameList:{
+			type:Array,
+			default:()=>{
+				return [];
 			}
 		},
-		data(){
-			return {
-				foldStatus:false,//0--收起状态   1--展开状态
-				cardStatus:0,//0--录音原文   1--转录文稿
-
-				pList:[
-    "说话人1 00:00",
-    "对爱整洁,有精神、不拖拉,多思考。老师你好,同学们好。",
-    "说话人2 00:10",
-    "请坐。前几天白老师关注到一则新闻,我们大鹏新区政府提出要将2024年作为旅游高质量发展年,为了吸引更多的游客来到咱们大鹏,你认为最重要的是什么来?第一小组。",
-    "说话人1 00:42",
-    "我认为最重要的是要先把环境、绿水青山环境弄好,这样才能吸引更多的人来,大鹏是的。",
-    "说话人2 00:51",
-    "大家同意他的想法吗?保护大棚环境人人有责,上周咱们班的两位环境调查员就去到葵冲进行了实地调查,我们来看看他们发现了什么。",
-    "说话人1 01:12",
-    "大家好,我们是人大附中深圳学校五1班的张龙溪,何瑞一为了响应区政府的号召,今天我们作为环境调查员,准备实地调查一下葵冲的环境情况,走跟随我们的镜头一起去看一看我们调查到的情况有什么样,这样的。",
-    "说话人3 01:36",
-    "应该是这样的,就是这样的,像这样的。",
-    "说话人2 01:41",
-    "像这种情况。",
-    "",
-    "像这种情况。",
-    "说话人3 01:52",
-    "像这样的。",
-    "说话人1 01:54",
-    "我们调查到的情况不是很好,同学们你们。",
-    "说话人3 02:02",
-    "谁知谁知。",
-    "说话人2 02:33",
-    "刚刚视频有一些小小的不同步,但不影响我们去观察里面的内容。",
-    "",
-    "好,来,同学们,通过刚才的视频,你看到了哪些环境问题?第五小组。",
-    "说话人1 02:51",
-    "我看到了菜市场上到处是垃圾,到处是那些烂掉的瓜果皮,是的。",
-    "说话人2 02:57",
-    "其他小组呢?来第八小组我。",
-    "说话人1 02:59",
-    "看我看到了路上还有很多漂移的垃圾就路上了。",
-    "说话人2 03:06",
-    "你观察得很认真,是的,在咱们生活的这片区域确实存在很多的垃圾问题,这些垃圾主要是家庭里面产生的生活垃圾。",
-    "",
-    "根据调查,一个家庭一天产生的垃圾大约是三千克,咱们班一共有45位同学,所有同学的家庭一天产生的生活垃圾总质量是多少?老师还调查到一些数据。我校小学部一共有1556人,整个大鹏新区共有55,224户家庭,整个深圳市有6,424,556户家庭,他们一天分别产生多少垃圾呢?现在请小组长从材料框当中拿出实验记录单,我们用计算器来速算一下,将结果记录下来。",
-    "",
-    "好,可以开始计算。二十五六场这样做的之前工作。",
-    "说话人1 04:49",
-    "还差一些,这样更准确一点。",
-    "说话人2 05:29",
-    "用计算器这样更准确算完了没有?",
-    "说话人1 05:38",
-    "你们。",
-    "说话人2 05:38",
-    "算完了吗老师?",
-    "说话人1 05:44",
-    "拍一下照片。",
-    "说话人2 06:05",
-    "大家算完了吗?",
-    "",
-    "好,算完的小组面向老师坐,好好表扬第八小组。好,第五、第四、第三。",
-    "",
-    "好,这是第四小组的数据,我们来看跟大家的一样吗?一样,在刚刚大家记录数据的时候,你发现了什么?在你刚刚写下这些数据,有什么发现?第三小组。",
-    "说话人1 06:42",
-    "我发现每天生产的垃圾会非常多。",
-    "说话人2 06:46",
-    "垃圾很多多,到什么程度?我们来看。多到全班同学一天产生的垃圾,相当于一头成年公羊这么重,多到全校小学部家庭的垃圾,一天有一头非洲大象这么重。大鹏新区所有家庭一天产生的垃圾量相当于32头,非洲大象这么重,整个深圳市一天产生的垃圾高达3800头,非洲大象这么重。",
-    "",
-    "老师看到很多同学发出来很惊讶的表情,整个深圳市就产生这么多的垃圾,整个广东省全国23个省加起来,放眼全球,全世界一年产生的垃圾是多少?我们来看这个统计图,把各个地区的垃圾量加起来,全球一年产生垃圾量高达20.17亿吨。这么多的垃圾如果填埋高度是一米的话,它可以埋掉三个深圳或者一个广州的面积。",
-    "",
-    "面对这组数据,你有什么样的感受跟大家分享一下。来,第一小组,垃圾好多。",
-    "说话人4 08:27",
-    "垃圾很多。",
-    "说话人2 08:29",
-    "其他小组有什么样的感受?第八小组。",
-    "说话人1 08:36",
-    "如果我们一直都以填埋的方式去处理垃圾的话,可能全球的土地都用于填埋垃圾了。",
-    "说话人2 08:45",
-    "你还告诉了大家处理垃圾的一种方式是的,这么多的垃圾如果没有得到及时的处理,他们会侵占大量的土地包围我们的城市家园,我们就会陷入到一种垃圾围城的现状,面对这么庞大的垃圾量,我们该怎么办?",
-    "",
-    "第七小组。",
-    "说话人1 09:15",
-    "我觉得我们可以按照垃圾的种类来进行分类,比如说回收垃圾,它可以是回收,然后再利用的或者就是有害垃圾,比如说电池会污染,将会人们将会对它处以专业的处理。",
-    "说话人2 09:37",
-    "你想到了垃圾分类,其他小组。",
-    "",
-    "第五小组。",
-    "说话人1 09:44",
-    "并且像很多我们要应该少用一次性的垃圾,比如说你买菜的时候要少用一次性的塑料袋,尽量用布袋,这样子的话可以节省既节省资源,又节省了垃圾的。",
-    "说话人2 09:58",
-    "生产量,你说的是一个非常实用的方法,大家刚刚都说出来了,实际的行动是的。今天就让我们一起行动起来,一起共同想办法来解决垃圾问题。",
-    "说话人1 10:14",
-    "面对垃圾问题。",
-    "说话人2 10:22",
-    "正如第八小组刚刚说的,咱们国家早期的处理方式是直接填埋和焚烧发电,这两种方法在一定程度上减少了垃圾,但也存在着很严重的弊端。现在我们就一起来说一说这两种方法的好处和弊端。第一小组。",
-    "说话人4 10:50",
-    "直接填埋这种方法会占用大量土地,而且还会污染土地,焚烧发电这种方法会会污染大气。",
-    "说话人2 11:00",
-    "你对两种方法思考得很深入,其他小组有补充吗?好,第五小组。",
-    "说话人1 11:09",
-    "如果是填埋电池的话,可能对土壤有害,以后要是在这片土上种。",
-    "说话人4 11:15",
-    "植物的话,可能植物很快就会死掉,无法进行光合作用。",
-    "说话人1 11:20",
-    "和传输氧气。",
-    "说话人2 11:23",
-    "你思考了一种垃圾,电池可能对我们土壤产生的危害想法很深入,你。",
-    "说话人1 11:34",
-    "我觉得直接填埋有个好处就是比较方便比较迅速,而直接填埋就会污染土地和水源。",
-    "",
-    "而焚烧发电可以把垃圾发电站也利用了一下垃圾,但是却会污染大气,造成我们一些呼吸上的问题。",
-    "说话人2 11:53",
-    "他说的有没有道理?大家点头赞同,是的,这两种方法看来存在着很严重的环境污染问题,并且这两种做法也是政府的行为,我们个人是没有办法进行的。那面对垃圾问题,我们自己能做些什么?减少它的量,现在就请我们小组展开头脑风暴,讨论解决垃圾问题,我们自己能做的行为。",
-    "",
-    "好,以关键词或句子的方式写到记录单当中,好,现在可以开始。",
-    "说话人3 12:34",
-    "谁知因为我还是你平常拉着我的东西,谁知到什么道路了,他可能对结果就不到了。把拿起来,谁知发生 Ew。好了,有的话写作业的时候就到里面,但是我今天的话我再给您说,谁知位置主要的地方可以通过文章的方式来进行数据上传,谁知10月份20 6 18 14号28号20分钟应该把这个问题没有谢谢。",
-    "",
-    "就不知道2.62.6性格你说的对。这句话谁知你知道你怎么说话。谁知谁知还有什么?还有谁知。后面的测试出来的一样,当时的好的也吗?",
-    "",
-    "我写好了吗?谁知这样的地方。这个也是可以的,少都买少买菜的时候去,因为那个时候出来还有什么?为什么我想说然后找一些画面,如果你生了一个兔是吧?吐了人家不知道,不代表他有回复利用的物质,谁知道?老师看你们写网上看看,我们写了好多,我能拍一下你的可以吗?我看一下好不好?你看到了尽量,谁知小宠物去网上买的一般,确实对教育较高的分了。我喜欢光盘,不是光盘,就是关系方向,他用的倍数。",
-    "",
-    "好,时间到。",
-    "说话人2 15:26",
-    "好说,停。",
-    "",
-    "第一小组第四、第五。好,我们来看这是第四小组他们的做法。先看第一个少,用一次性工具,这种方法你们是怎么想的?来。",
-    "",
-    "第四小组。第四小这是他们的做法,你想补充可以。",
-    "说话人4 15:51",
-    "如果你用一次一次性工具的话,它用了一次你就只能扔掉,但如果你不用它的话,你用的这些东西可以循环很多次的话,那就不用它了,那就可以减少垃圾的产生。",
-    "说话人2 16:13",
-    "这种方法是相当的厉害,我们从一开始就减少了这个工具的使用,相当于垃圾的量就减少了,科学上我们把这种处理方式叫做减量化。",
-    "",
-    "刚刚那个同学说我们减少使用这个一次性的工具再次重复利用起来。好,大家想把垃圾变成了重复利用的一种资源,它被重新利用起来了,相当于是一种新的资源,科学上把这种方法叫做资源化处理。我们来看第二条,垃圾分类,关于垃圾分类,老师有疑问,请你们小组起立。",
-    "说话人1 17:13",
-    "垃圾分类的话,因为我们现在有一些可回收垃圾、厨余垃圾和有害垃圾,其他垃圾可回收垃圾,我们在经过特殊处理以后可以重复利用起来,相当于是变变废为宝,而有害垃圾要经过特殊的处理,才可以让我们的环境不受到污染,所以我们认为把垃圾分类以后可以做到环保护环境,而且也可以解决一些浪费的问题。",
-    "说话人2 17:43",
-    "垃圾被分类后,垃圾的数量减少了吗?",
-    "",
-    "没有。",
-    "",
-    "垃圾问题依然存在,我们需要经过进一步的处理,就像他刚刚说的。",
-    "",
-    "好,关于你的回答,老师有一点小疑问,你说到了有害垃圾,有害垃圾是对什么有害?",
-    "说话人1 18:06",
-    "我们认为有害垃圾如果它像进行填埋或者说把它进行发电的话,可能会对环境有一些污染,比如说填埋的话,有一些电池和过期药品埋到地地下以后会影响土地里面的一些一些的营养,然后让一些植物就不太好生长,对环境有害。",
-    "说话人2 18:35",
-    "很可能对什么有害。",
-    "说话人1 18:40",
-    "可能对人体有害,因为有些过期的那种化妆品,它里面有一些那种化学成分,而这些化学成分可能对人体有害,所以说有害垃圾它是对人体有害的。",
-    "说话人2 18:53",
-    "大家赞同这种垃圾太可怕了,我们得远离它,当然咱们也不可以随地的乱丢这种垃圾,这种垃圾就需要我们经过专业的无害化的处理,让它对人和环境的危害最小,科学上把这种方法叫做无害化处理。我们继续往下看第四条循环利用,废物利用。好,这种方法你们小组是怎么思考的?是哪个小组写的?来。",
-    "说话人4 19:38",
-    "一些可能没他原来没有用的东西,你可能可以用它来做些手工,或者对别人还有用,你也可以捐给别人,这样他就又有用了。",
-    "说话人2 19:54",
-    "是个非常有爱心的孩子,我们把垃圾相当于又再次利用起来了,大家想垃圾的量怎么样?这是哪种方式?",
-    "",
-    "是的,好,换另外一个角度,我们继续想把垃圾做成了手工艺品,把它变成了一种这是资源化的处理方式。",
-    "",
-    "对的。",
-    "",
-    "好,除了这个小组提出的这些想法,其他小组有要补充的吗?第六小组。",
-    "说话人1 20:34",
-    "我们小组认为吃完饭之后,剩饭剩菜可以喂给小动物吃,比如那些小猫小狗的什么的。",
-    "说话人2 20:46",
-    "也就是说你们把一些剩饭剩菜这样的垃圾又再次用起来了,这种方式是哪种方法?资源化。换另外一个角度。",
-    "说话人4 21:02",
-    "想。",
-    "说话人2 21:04",
-    "为什么是减量化?来我们来听听他怎么说。",
-    "说话人1 21:12",
-    "因为本来如果是倒掉的话,它就会增加垃圾,但是如果喂给那些小猫的话,垃圾量就减少了。",
-    "说话人2 21:21",
-    "他思考的好不好?把掌声送给他。",
-    "",
-    "其他小组还有要补充的吗?第八小组。",
-    "说话人1 21:31",
-    "我认为厨余垃圾可以拿去堆肥。",
-    "说话人2 21:35",
-    "也就是说把垃圾做成肥料,默默的奉献自己变成了一种什么?养分,它相当养分。",
-    "说话人3 21:47",
-    "相当于是资源一种资源。",
-    "说话人2 21:51",
-    "这种方式叫做资源化的处理。",
-    "",
-    "好,其他小组还有要补充的吗?",
-    "",
-    "好,没有了。",
-    "",
-    "经过我们刚刚的讨论,我们发现解决垃圾问题最常用的是三种方法,分别是无害化。是的,面对垃圾问题,这三种方法其实是有先后顺序的,我们首先应该做到的是减量化的处理,在生活当中咱们还是不可避免实在没有办法产生的一些垃圾,该怎么办呢?",
-    "",
-    "好,具体一点怎么资源化第七小组。",
-    "说话人1 22:48",
-    "比如说我们喝那些饮料,剩下来的易拉罐我们可以不用丢,可以把它与另外一些垃圾组成一一种手工用品,这样子还增加了趣味性。",
-    "说话人2 23:01",
-    "大家同意吗?老师想问了,所有的垃圾都可以做成这样的手工艺品吗?",
-    "",
-    "第三小组。",
-    "说话人1 23:14",
-    "一些有害垃圾是不能做成手工艺品的,因为如果做的话,它可能会释放那些有毒的东西,然后污染。",
-    "说话人2 23:24",
-    "那个环境是的,什么样的垃圾可以去做手工艺品呢?意思叫做我。",
-    "说话人1 23:32",
-    "认为我认为比如说一些可回收垃圾,就像是一些易拉罐,还有那些纸制品都可以用来作为咱们的。",
-    "说话人2 23:49",
-    "做成手工,大家同意吗?你有没有这样的变废为宝的经历,有吗?有没有?",
-    "",
-    "有同学点头了,是的,我们就把这类塑料,刚才说的玻璃等等,它其实是一种有价值的垃圾,我们是不是应该把它给分出来?这类垃圾可以叫做。",
-    "说话人3 24:15",
-    "回收回收垃圾。",
-    "说话人2 24:17",
-    "垃圾回收再次利用,它对应的解决方法应该是。",
-    "说话人3 24:25",
-    "减轻了什么?",
-    "说话人2 24:26",
-    "计划有不一样的想法了,谁来分享一下?",
-    "",
-    "第八小组。",
-    "说话人1 24:39",
-    "我觉得是资源化,因为它已经是可回收的垃圾了,就没有必要再去减量了,而且可回收垃圾可以做成像我们刚才说的手工制品,变成资源。",
-    "说话人2 24:51",
-    "成为资源化其他小组。",
-    "",
-    "第六小组第四小组。",
-    "说话人1 24:59",
-    "我觉得它既是减量化也是资源化,因为可回收垃圾它不仅减少了我们我们产出的垃圾,它不仅从这垃圾的部分中减少了一部分,而且它还将这些垃圾又回收利用,再形成了一种新的物体。",
-    "说话人2 25:18",
-    "所以是减量化和资源化一起来解决可回收的垃圾。",
-    "",
-    "好,继续思考,剩下的还有很多不可以回收的垃圾,这些垃圾该怎么办?比如说我们的剩饭剩菜,第三小组。",
-    "说话人1 25:44",
-    "那些剩饭剩菜也可以资源化,可以像刚才黄家俊说的,喂给小猫小狗那些小动物吃。",
-    "说话人2 25:54",
-    "好,你打算把这些垃圾剩饭剩菜喂给小猫小狗,其他同学有不同观点吗?好,第五小组。",
-    "说话人1 26:04",
-    "还可以像刚刚第八小组说的,把它变成堆肥,这样子的话可以灌溉农田,这样子的话也可以让植物养得更好,这个也是资源化。",
-    "说话人2 26:17",
-    "不管是喂给小猫小狗或者是做成肥料,总的来说垃圾又被我们变成了资源,这样的垃圾有价值,我们需要把它单独给分出来,叫做厨余垃圾,厨余垃圾。",
-    "",
-    "好,垃圾变成了资源,它的处理方式应该是资源化。咱们刚刚第五小组补充举手的女生。",
-    "说话人1 26:51",
-    "如果是电池的话要扔掉的话也可以我见过一种给电池充电的设备,用电池充好电之后还能重复利用。",
-    "说话人2 27:06",
-    "充电的电池可以重复利用,好它重复利用充电的次数是有限的。",
-    "",
-    "当这些电池报废之后,这些电池老师产生了疑问,它还有一些金属的元件,还有我们废弃的灯泡,也有一些玻璃的成分在这,两种垃圾可不可以直接回收?大家都在摇头,为什么不可以?",
-    "",
-    "老师很疑惑,来第七小组。",
-    "说话人1 27:39",
-    "因为如果我们把电池这些里面含有特殊元素的,比如说给它转为资源化的话,那么资源化就像做手工艺品一样,它并不能做手工艺品,而且它里面的化学里面一些不明物质和化学物质会对周围的环境以及人体产生相对的伤害。",
-    "说话人2 28:03",
-    "是的。",
-    "",
-    "像这类的垃圾它含有有毒有害的成分,我们不能直接回收,而且现在咱们国家的垃圾处理技术,还不能够将这些有毒有害的垃圾变成无毒可回收的垃圾,所以他们怎么办?需要单独的给它处理起来,把它叫做无害化,这类垃圾叫做。",
-    "说话人1 28:37",
-    "有害垃圾。好。",
-    "说话人2 28:42",
-    "我们继续思考,有些垃圾它既不可以回收,也不是厨房里产生的,也无毒无害,这类垃圾通通的叫做其他垃圾。我们采用焚烧和填埋的方式来解决,因为他们的量已经很小了。",
-    "",
-    "好,在刚刚我们讨论过程当中,我们逐渐的将垃圾分成了4大类,其实咱们国家把垃圾就分成的是这4类,看来垃圾分类很重要,垃圾分类只是解决垃圾问题的前提条件,后续回收回来还是要进一步的去处理的。",
-    "",
-    "好,老师这里有8种生活垃圾,请大家按照刚刚的4种分类方法将它们进行分类,把序号写在相应的垃圾桶身上。好,现在请小组长翻开记录单的背面,完成分类开始。",
-    "说话人3 29:59",
-    "塑料瓶上面都要给哥哥烧,谁知餐具其他垃圾,其他的垃圾沙发正在处置垃圾残缺,落叶处置垃圾。他们4号回来吃饭,他应该是12头肌土地有害了,一起讨论了,大多数人的意志就是必须要的但是它里面有一个化学都不能对烟头应该是烟头是其他的,为什么?因为它已经被燃烧过了,燃烧过了之后就只剩下后面那点了。快递纸箱应该是一个点,你们看好了吗?你分的这么快。对,快递只能把它打破物流质量不错的服务。",
-    "",
-    "谁知谁知我们再讨论一下,我只是表演一下,没有。写完了,要不然你们分的好看再讨论一下,看看有没有你不确定的,谁知看来还是太大了。",
-    "说话人1 31:35",
-    "难道我就想问一下。",
-    "说话人3 31:37",
-    "难道难道你的处理垃圾就一件事还能给小猫小狗搞个香蕉?他就是我小狗。再说过期,过期了以后。",
-    "说话人2 31:54",
-    "大家都分完了吗?分完的小组面向老师坐好好。",
-    "",
-    "第七第八456123好看这里我们来看这个小组它的分类,先从可回收垃圾看起,他们将1号塑料瓶,7号快递纸箱归为可回收垃圾,有和大家不一样的吗?有不一样的吗?好,没有,我们来看厨余垃圾,他们将三号剩饭剩菜归为厨余垃圾,有不一样的吗?有好多。",
-    "",
-    "来,第六小组。",
-    "说话人1 32:43",
-    "我觉得4号残枝落叶也是厨余垃圾。",
-    "说话人2 32:47",
-    "你的理由是?我暂时还没想好小组内有要帮帮他的吗?你们小组是怎么想的?和他们一样认为4号属于厨余垃圾的。说一下理由。第三小组。",
-    "说话人1 33:10",
-    "我觉得残枝落叶也是厨余垃圾,因为剩菜剩饭还没有变成剩饭,全是蔬菜,蔬菜跟那些落叶是差不多的,而且它们腐烂之后腐烂之后也会变成泥土,就像那些残枝落叶也是会变成那些肥料的。",
-    "说话人2 33:32",
-    "老师听明白了,你认为残枝落叶也可以腐烂,归为了厨余垃圾是吗?好,来第六小组。",
-    "说话人1 33:41",
-    "我不认同石新宇的观点,因为厨余垃圾我们从字面分析。",
-    "",
-    "食用后的垃圾,而残肢过夜是不能是不属于可以用来使用的。所以我认为残这个也不是厨余垃圾。",
-    "说话人2 34:05",
-    "也就是说你的标准4号残枝落叶它不是我们吃剩下的,对吗?归为其他垃圾。",
-    "",
-    "关于4号看来两个小组产生了分歧,来,第八小组。",
-    "说话人1 34:22",
-    "但是我们知道残枝落叶它也就是埋在土里,它以后很快就可以销毁,然后然后厨余垃圾一般就是指那些食物,而且比较容易在土里土里销毁的一些物品,然后黄家俊刚才说说残枝落叶得是吃过的才算,但是残枝落叶是算树叶,也算是一种食品。",
-    "说话人2 34:55",
-    "所以你赞同的是第三小组的观点,是吧?",
-    "",
-    "好,来。",
-    "说话人1 35:02",
-    "我不认同黄家俊的看法,因为其他垃圾它是既不能归为可回收垃圾,也不能归为厨余垃圾,也不能归为有害垃圾的。厨余垃圾它可以做成肥料罐,让植物长得更好,残枝落叶就可以用来当做肥料,所以我觉得黄家俊说的是错误的。",
-    "说话人2 35:23",
-    "大家看来对4号产生了很大的争议,我们先放一放,来看厨余垃圾还有不一样的吗?没了,来,咱们看有害垃圾有不同的吗?第五小组。",
-    "说话人1 35:41",
-    "我们小组认为6号的烟头它并不是有害垃圾,因为烟头它是燃烧过后的才叫做烟头,而没有燃烧过后的那叫做烟,而烟头燃烧过后,它那些烟草已经燃烧完毕了,而后面那些那些纸团棉花之类的,它就是其他垃圾,因为已经被嘴巴给含过了,所以说应该就是有害垃圾,应该就是其他垃圾。",
-    "说话人2 36:10",
-    "也就是说你认为抽完的烟头没有危害了,把它归到了其他垃圾。",
-    "",
-    "好,6号两个小组产生了分歧,我们采访一下,来,这是第六小组的,你们把6号作为有害垃圾的依据是什么?",
-    "说话人1 36:32",
-    "我认为烟头虽然现在灭了,但如果一一不小心死灰复燃了,就有可能燃起一场大火,所以我把烟头归到了有害垃圾里面。",
-    "说话人2 36:46",
-    "烟头很可能引发火灾。来,其他有补充的吗?来,你说。",
-    "说话人1 36:52",
-    "因为我们都知道抽烟有害身体健康,那么烟里面肯定是有一些有害身体的,如果你不能保证烟里边有害身体的都被抽完了的话,我觉得没熄灭的烟头就是有害垃圾。",
-    "说话人2 37:11",
-    "说的也有道理。",
-    "",
-    "来第七小组。",
-    "说话人1 37:15",
-    "我是不赞成曾静纯的观点的,因为烟中含有含有尼古丁,尼古丁能对人的身体产生危害,而且烟头它不一定里面有害物质都是全抽完,可能还有一点残留在里面,况且没有熄灭的烟头,我之前了解过没熄灭的烟头,如果产生火灾的话将称为燃阴,燃的话可能阴燃扑灭火的可能性很低,也就是说它火会很大,可能也会影响到人的生命安全。",
-    "说话人2 37:53",
-    "好,他关于烟头展开了一番很深入的全面的一番思考,非常不错,来。",
-    "",
-    "第六小组第四小组。",
-    "说话人1 38:03",
-    "我们认为烟头它是其他垃圾,因为有害垃圾像杀虫剂过期药品,它们是自身不需要处理,就会散发出有毒的气体或者有毒的物质,而烟头它需要再次的燃烧才能产生尼古,才能让尼古丁散发出去,从而对人体有伤害,所以我认为烟头它属于其他垃圾。",
-    "说话人2 38:27",
-    "好,请坐。",
-    "",
-    "你和你们小组和第七小组观点最大不同的是你认为烟头里的尼古丁没有燃烧,没有害,归为其他垃圾,他们认为烟头里的尼古丁即使没有燃烧也有害,所以归为了有害垃圾,是吗?",
-    "",
-    "好,关于6号我们又产生了很大的分歧,好,我们也先再放一放,来看有害垃圾还有不同的吗?来看其他垃圾有不一样的吗?好,现在我们来看大家存在很大争议的垃圾是三个,一个是一共是两个,一个是4号残枝落叶,还有6号烟头。好,我们国家把这两类垃圾归为哪一类?我们来看一下国家的分类标准。",
-    "",
-    "好,来看,我们国家把可以回收利用的垃圾投在可回收垃圾箱,容易腐烂的垃圾投在厨余垃圾箱,对人和环境有害的垃圾投在有害垃圾箱。除了这三类难以回收的全部放在其他垃圾箱,残枝落叶,我们来看它可以回收利用吗?没有重复利用的价值它容易腐烂吗?所以国家把它归为厨余垃圾。好,接下来再看烟头是大家争议很大的一个垃圾,好,我们依次来看,它可以回收利用吗?",
-    "说话人3 40:28",
-    "没有价值。",
-    "说话人2 40:31",
-    "容易腐烂吗?对。人和环境有害吗?",
-    "",
-    "有是这样的,抽剩下的熄灭的烟头,它对人和环境危害性很小,我们的尼古丁只有在燃烧的时候才会产生有毒有害的气体或物质,但这个烟头已经是一般情况下已经熄灭了,它的危害性比较小,所以把它归为灾害其他垃圾。好,对比我们小组的分类标准和国家的标准,我们发现有的小组和国家一样,有的不一样,国家的这种分类标准你有什么样的建议?",
-    "",
-    "第一小组。",
-    "说话人1 41:31",
-    "我觉得烟头虽然它的危害很小,不过世界上有很多人都是吸烟的,但所有烟头都在一起的话,它的危害就会慢慢变大。",
-    "说话人2 41:44",
-    "你认为怎么我。",
-    "说话人1 41:45",
-    "认为它可以变成有害垃圾。",
-    "说话人2 41:48",
-    "变成有害垃圾,这是你的想法,跟我们国家的标准是不一样的,可不可以在这个基础上改进,提出自己的新的想法?好。",
-    "",
-    "来第五小组。",
-    "说话人1 42:07",
-    "我建议再提出一个垃圾桶专门回收烟类的,这样子的话就好区分一点,也好,分类一点也好,后面也好。",
-    "说话人2 42:21",
-    "处理一点有想法的孩子,大家同意吗?",
-    "说话人1 42:25",
-    "关于烟头每个人的标准不一样。",
-    "说话人2 42:28",
-    "太难区分它了,是不是?我们就不如在再放一个垃圾箱,就专门来放烟头,好不好?放烟头之类的物品,看来有一定的道理。好,其他小组还有不同的建议吗?",
-    "",
-    "第四小组我。",
-    "说话人1 42:45",
-    "要反驳一下第一小组的账号君说的话,如果把烟头放进有害垃圾的话,要是烟头当时没有完全熄灭,然后有害垃圾箱里面又有电池,那些都东西,然后烟没熄灭导致火灾,然后电池爆炸,那就会炸,可能会炸伤许多人。",
-    "",
-    "所以我不建议把那烟头放进有害垃圾箱里。",
-    "说话人2 43:17",
-    "是的,很多人很粗心,有时候烟并没有完全熄灭就扔掉了,他这种情况有可能发生吗?怎么改进呢?有什么好的建议?来,你们小组。",
-    "说话人1 43:33",
-    "我是认为烟头它如果是没有完全燃烧结束,它还有火的话,它不管放到哪个垃圾桶里面,它都会引发或燃烧和爆炸。而且一般烟头它如果没有熄灭的话,很多人他习惯没熄灭,往地上一扔一踩就走了。很多烟头都是环卫工人捡起来以后,收集好以后再去再去扔到垃圾桶里面的。",
-    "",
-    "再一个我就觉得可以说不一定非要在垃圾桶的分类上进行一些改变,可以我们对在平时我们生活的时候提出一些新的要求或者建议,比如说多设一多设立一些吸烟的站,让我们吸烟的地方也吸完烟以后就可以找到一个比较近的地方将烟掐灭,这样就可以阻止尼古丁的释放和爆炸着火的风险。",
-    "说话人2 44:34",
-    "非常有个人想法的一个建议。",
-    "",
-    "好,其他小组第五小组。",
-    "说话人1 44:43",
-    "我是这样认为的,其实我觉得国家可以少生产一点烟,这样子就不会有那么多烟头了。",
-    "说话人2 44:51",
-    "少抽烟大家同意吗?少抽烟烟对人有害健康。",
-    "",
-    "来,4小组补充。",
-    "说话人1 45:02",
-    "我想补充一下第五小组郑明达决定重新设一设立一个垃圾桶的想法,我觉得再可以再设立一个垃圾桶,只有我在外界条件允许下才会变成有害垃圾的一个垃圾桶,因为垃圾桶做一个就是保护措施,就防止像刚刚我们小组说的,里面还有其他的物质引引发爆炸之类的有道理。",
-    "说话人2 45:28",
-    "好,来第八小组用话筒。",
-    "说话人1 45:34",
-    "我认为没有改进的必要,因为现在很多垃圾桶上面都有一个面噎的地方。",
-    "说话人2 45:40",
-    "你很赞成现在的4分法,同学们刚刚提的建议都有一定的道理,有合理的地方,随着我们国家垃圾处理技术的不断提高,我们国家的分类标准在以后也可能会发生变化,在未来作为国家公民,我们每个孩子都有机会为更好的垃圾分类方案提出自己的建议。",
-    "",
-    "好,但是目前4分法国家的4分法还是能够有效的解决很多的垃圾问题的。生活当中咱们还按照4分法来分类。",
-    "",
-    "好了,孩子们,今天。",
-    "说话人1 46:23",
-    "我们。",
-    "说话人2 46:24",
-    "学了很多关于垃圾分类不同的国家,其实分类标准也不一样,我们来了解一下,德国将垃圾分成6类,日本是世界上垃圾分类做得最好的国家,瑞士将垃圾分成了10多种,今天我们讨论了很多的问题,也达成了一些共识。好,那么作为大棚的一份子保护环境,我们每个人责无旁贷。五一班的小朋友们,五一班的环保小卫士们,让我们就从现在行动起来,垃圾分类从我做起,好不好?好好,今天大家表现都非常棒,好,大家辛苦了,下课。",
-    "说话人1 47:16",
-    "丽丽老师再见。",
-    ""
-],
-				fileUrl:"https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/%E8%BD%AC%E5%BD%95%E6%96%87%E7%A8%BF1713172600896.xlsx",
-				audioUrl:"https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/%E8%A7%A3%E5%86%B3%E5%9E%83%E5%9C%BE%E9%97%AE%E9%A2%981713172672090.m4a",
-			}
+		loading:{
+			type:Boolean,
+			default:true,
+		}
+	},
+	data() {
+		return {
+			// foldStatus: false, //0--收起状态   1--展开状态
+
+			fileUrl:
+				"https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/%E8%BD%AC%E5%BD%95%E6%96%87%E7%A8%BF1713172600896.xlsx",
+			audioUrl:
+				"https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/%E8%A7%A3%E5%86%B3%E5%9E%83%E5%9C%BE%E9%97%AE%E9%A2%981713172672090.m4a",
+		};
+	},
+	computed:{
+		contentValue(){
+			// return (text)=>{
+			// 	let newText = text;
+			// 	this.aiNameList.forEach(i=>{
+			// 		const regex = new RegExp(`@(${i.name})`,"g");
+			// 		newText = newText.replace(regex,`<span class='atName'>@$1</span>`);
+			// 	})
+			// 	return newText;
+			// }
 		},
-		methods:{
-			// 切换折叠状态
-			changeFoldStatus(newValue){
-				this.foldStatus = newValue;
-			},
-			//切换卡片
-			changeCardStatus(newValue){
-				this.foldStatus = 1;
-				this.cardStatus = newValue;
+	},
+	methods: {
+		// 切换折叠状态
+		// changeFoldStatus(newValue) {
+		// 	this.foldStatus = newValue;
+		// },
+		//切换卡片
+		// changeCardStatus(newValue) {
+		// 	this.foldStatus = 1;
+		// 	this.cardStatus = newValue;
+		// },
+		addWork() {
+			this.$message.info("添加到工作区");
+		},
+		copyContent(value) {
+			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 = value;
+			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("复制成功")
 			}
-		}
-	}
+		},
+	},
+};
 </script>
 
 <style scoped>
-.tape{
+.tape {
 	width: 100%;
 	height: 100%;
-} 
-.t-header{
+	overflow: auto;
+}
+.t-header {
 	width: 100%;
 	height: 30px;
 	display: flex;
 	align-items: center;
 }
 
-.t-h-title{
+.t-h-title {
 	font-size: 20px;
 	margin-right: 10px;
 }
-.t-h-time{
+.t-h-time {
 	font-size: 14px;
-	color: #A8A9AB;
+	color: #a8a9ab;
 }
 
-.t-tapeAudio{
+.t-tapeAudio {
 	width: 100%;
 	height: 50px;
 	margin-top: 10px;
@@ -494,47 +238,46 @@ import pdf from './pdf.vue';
 .audio_class {
 	/* width: 100% !important; */
 	/* height: 100% !important; */
-  background: #3680fb !important;
-  margin: 0 !important;
+	background: #3680fb !important;
+	margin: 0 !important;
 }
 
-.t-tapeAudio>>>.vueAudioBetter span:before {
-  color: #fff;
+.t-tapeAudio >>> .vueAudioBetter span:before {
+	color: #fff;
 }
 
 /* .t-tapeAudio>>>.slider{
 	width: 80% !important;
 } */
 
-.audio_class>>>.slider .process {
-  background: #000;
+.audio_class >>> .slider .process {
+	background: #000;
 }
 
-.t-tapeAudio>>>.vueAudioBetter .iconfont:active {
-  position: unset;
+.t-tapeAudio >>> .vueAudioBetter .iconfont:active {
+	position: unset;
 }
 
-.t-tapeFile{
+.t-tapeFile {
 	width: 100%;
 	max-height: calc(100vh - 294px);
 	overflow: auto;
-	margin-top: 10px;
 	/* background-color: red; */
 }
 
-.t-t-header{
+.t-t-header {
 	width: 100%;
 	height: 35px;
 	display: flex;
 	justify-content: space-between;
 	align-items: center;
-	background-color: #E5E5E5;
+	background-color: #e5e5e5;
 	border-radius: 5px 5px 0 0;
 	box-sizing: border-box;
 	padding-right: 10px;
 }
 
-.t-t-h-left{
+.t-t-h-left {
 	width: calc(100% - 80px);
 	height: 100%;
 	overflow: auto;
@@ -545,7 +288,7 @@ import pdf from './pdf.vue';
 	padding-left: 5px;
 }
 
-.t-t-h-l-Item{
+.t-t-h-l-Item {
 	width: auto;
 	height: 90%;
 	box-sizing: border-box;
@@ -559,20 +302,21 @@ import pdf from './pdf.vue';
 	border-radius: 5px;
 }
 
-.t-t-h-l-i-icon{
+.t-t-h-l-i-icon {
 	width: 20px;
 	height: 20px;
-	background: url("../../../../assets/icon/classroomObservation/file.png") no-repeat;
+	background: url("../../../../assets/icon/classroomObservation/file.png")
+		no-repeat;
 	background-size: 100% 100%;
 	margin-right: 5px;
 	background-position: center;
 }
 
-.t-t-h-l-Item:hover{
+.t-t-h-l-Item:hover {
 	background-color: white;
 }
 
-.t-t-h-right{
+.t-t-h-right {
 	width: 80px;
 	height: 100%;
 	display: flex;
@@ -581,10 +325,11 @@ import pdf from './pdf.vue';
 	cursor: pointer;
 }
 
-.t-t-h-r-icon{
+.t-t-h-r-icon {
 	width: 25px;
 	height: 25px;
-	background: url("../../../../assets/icon/classroomObservation/foldIcon.png") no-repeat;
+	background: url("../../../../assets/icon/classroomObservation/foldIcon.png")
+		no-repeat;
 	background-size: 100% 100%;
 	margin-right: 10px;
 	background-position: center;
@@ -592,11 +337,11 @@ import pdf from './pdf.vue';
 	transform: scaleY(-1);
 }
 
-.t-t-h-r-text{
+.t-t-h-r-text {
 	font-size: 16px;
 }
 
-.t-t-main{
+.t-t-main {
 	width: 100%;
 	height: calc(100vh - 354px);
 	/* height: calc(100% - 35px); */
@@ -604,30 +349,30 @@ import pdf from './pdf.vue';
 	background-color: white;
 }
 
-.t-t-m-Item{
+.t-t-m-Item {
 	width: 100%;
 	height: 100%;
 }
 
-.t-t-m-Item>p{
+.t-t-m-Item > p {
 	margin: 10px;
 }
 
-.t-chartArea{
+.t-chartArea {
 	width: 100%;
-	height: calc(100vh - 290px);
+	height: calc(100vh - 280px);
 	overflow: auto;
 }
 
-.t-ca-item{
+.t-ca-item {
 	width: 100%;
 	height: auto;
-	margin-top:20px ;
+	margin-top: 20px;
 	display: flex;
 	justify-content: flex-start;
 }
 
-.t-ca-i-left{
+.t-ca-i-left {
 	width: 50px;
 	height: 50px;
 	display: flex;
@@ -635,31 +380,159 @@ import pdf from './pdf.vue';
 	justify-content: center;
 }
 
-.t-ca-i-right{
+.t-ca-i-right {
 	flex: 1;
 	height: auto;
 	padding: 10px;
 	box-sizing: border-box;
 }
 
-.t-ca-i-r-name{
+.t-ca-i-r-name {
 	width: 100%;
 	font-size: 16px;
 	font-weight: 600;
 }
 
-.t-ca-i-r-time{
+.t-ca-i-r-time {
 	width: 100%;
 	font-size: 14px;
-	color: #A8A9AB;
+	color: #a8a9ab;
+	margin-top: 10px;
+}
+
+.t-ca-i-r-content {
+	margin-top: 10px;
+	width: 100%;
+	height: auto;
+	white-space: pre-line;
+	word-break: break-all;
+}
+
+.t_ca_b_roleAi {
+	width: 100%;
+	height: auto;
+	box-sizing: border-box;
+	padding: 10px;
+	display: flex;
+}
+
+.t_ca_b_ai_c_name {
+	font-weight: 600;
+}
+.t_ca_b_ai_c_main {
+	width: auto;
+	display: flex;
+}
+
+.t_ca_b_ai_c_m_left {
+	min-width: 50px;
+	height: auto;
+	padding: 12px;
+	display: block;
+	border-radius: 2px 8px 8px 8px;
+	box-shadow: 0 4px 10px 0 #1d388354;
+	margin-top: 10px;
+	/* white-space: pre-line; */
+	word-break: break-all;
+	background-color: white;
+	overflow: hidden;
+}
+
+.t_ca_b_ai_c_m_right {
+	min-width: 30px;
+	min-height: 50px;
+	display: flex;
+	flex-direction: column;
 	margin-top: 10px;
+	margin-left: 5px;
 }
 
-.t-ca-i-r-content{
+.t_ca_b_ai_c_m_right > img {
+	width: 20px;
+	height: 20px;
+	margin-bottom: 15px;
+	cursor: pointer;
+}
+
+.t_ca_b_u_c_m_left {
+	min-width: 30px;
+	min-height: 50px;
+	display: flex;
+	flex-direction: column;
 	margin-top: 10px;
+	margin-right: 5px;
+}
+
+.t_ca_b_u_c_m_left > img {
+	width: 20px;
+	height: 20px;
+	margin-bottom: 15px;
+	cursor: pointer;
+}
+
+.t_ca_b_ai_c_time {
+	font-size: 14px;
+	color: #a8a9ab;
+	margin-top: 10px;
+}
+
+.t_ca_b_ai_avatar {
+	width: 30px;
+	height: 30px;
+	margin-right: 10px;
+}
+
+.t_ca_b_roleUser {
 	width: 100%;
 	height: auto;
+	box-sizing: border-box;
+	padding: 10px;
+	display: flex;
+	justify-content: flex-end;
+}
+
+.t_ca_b_u_avatar {
+	width: 30px;
+	height: 30px;
+	margin-left: 10px;
+}
+
+.t_ca_b_u_c_main {
+	display: flex;
+	width: auto;
+	justify-content: flex-end;
+}
+.t_ca_b_u_c_m_right {
+	height: auto;
+	padding: 12px;
+	display: block;
+	border-radius: 8px 2px 8px 8px;
+	box-shadow: 0 4px 10px 0 #1d388346;
+	margin-top: 10px;
 	white-space: pre-line;
 	word-break: break-all;
+	background-color: #3681fc;
+	color: white;
+}
+
+.t_ca_b_u_c_time {
+	white-space: nowrap;
+	font-size: 14px;
+	color: #a8a9ab;
+	margin-top: 10px;
+	text-align: right;
+}
+.t_ca_b_u_c_m_right>>>.aite-name{
+	display: inline;
+	background-color: #063a708c;
+	border-radius: 5px;
+	box-sizing: border-box;
+	padding: 2px 5px;
+	color: white;
+	margin-right: 5px;
+}
+
+.t_ca_b_ai_c_m_left>>>ol{
+	margin-left: 15px;
 }
-</style>
+</style>

+ 7 - 4
src/components/pages/classroomObservation/components/transcription.vue

@@ -5,14 +5,15 @@
 			<div class="t-h-time">{{ data.time }}</div>
 		</div> -->
 		<div class="t-content">
-			<!-- {{ data.content }} -->
-			<div class="contentCon" v-for="(i, index) in chatList" :key="i + 'a'">
+			{{ data.content?data.content:"暂无..." }}
+			<!-- <div class="contentCon" v-for="(i, index) in chatList" :key="index">
 				<div class="conTim">{{ i.timer }}</div>
 				<div class="conTxt">
 					{{ i.con }}
 				</div>
-			</div>
+			</div> -->
 		</div>
+		<slot></slot>
 	</div>
 </template>
 
@@ -67,7 +68,9 @@ export default {
 .transcription {
 	width: 100%;
 	height: 100%;
-	max-height: calc(100% - 290px);
+	/* height: calc(100vh - 300px); */
+	max-height: calc(100vh - 300px);
+	position: relative;
 	/* display: flex; */
 	/* flex-direction: column; */
 	/* overflow: auto; */

+ 326 - 0
src/components/pages/classroomObservation/components/wangEnduit.vue

@@ -0,0 +1,326 @@
+<template lang="html">
+  <div class="editor cont">
+    <div ref="toolbar" class="toolbar">
+    </div>
+    <div ref="editor" class="text">
+    </div>
+		<slot></slot>
+    <div v-if="proVisible" class="mask">
+      <div class="progressBox">
+        <div class="lbox">
+          <img src="../../../../assets/loading.gif" />上传中,请稍后
+        </div>
+      </div>
+    </div>
+  </div>
+</template>  
+  
+<script>
+import E from "wangeditor";
+import "../../../../common/aws-sdk-2.235.1.min";
+import { Loading } from 'element-ui';
+// import 'wangeditor/release/wangEditor.min.css'
+export default {
+  name: "editoritem",
+  data() {
+    return {
+      // uploadPath,
+      editor: null,
+      info_: null,
+      proVisible:false,
+      progress:0
+    };
+  },
+  model: {
+    prop: "value",
+    event: "change",
+  },
+  props: {
+    value: {
+      type: String,
+      default: "",
+    },
+    isClear: {
+      type: Boolean,
+      default: false,
+    },
+    placeholder: {
+      type: String,
+      default: "请输入正文"
+    }
+  },
+  watch: {
+    isClear(val) {
+      // 触发清除文本域内容
+      if (val) {
+        this.editor.txt.clear();
+        this.info_ = null;
+      }
+    },
+    value: function (value) {
+      if (value !== this.editor.txt.html()) {
+        this.editor.txt.html(this.value);
+      }
+    },
+    //value为编辑框输入的内容,这里我监听了一下值,当父组件调用得时候,如果给value赋值了,子组件将会显示父组件赋给的值
+  },
+  mounted() {
+    this.seteditor();
+    this.editor.txt.html(this.value);
+  },
+  methods: {
+    seteditor() {
+      this.editor = new E(this.$refs.toolbar, this.$refs.editor);
+      // 关闭菜单栏fixed
+      this.editor.config.menuFixed = false;
+      // 普通的自定义菜单
+      this.editor.config.menus = [
+        "head", //标题
+        "bold", //加粗
+        "fontSize", //字体大小
+        // "fontName", //字体
+        // "italic", //斜体
+        // "underline", //下划线
+        // "strikeThrough", //删除线
+        "indent", //缩进
+        // "lineHeight", //行高
+        // "foreColor",
+        // "backColor",
+        // "link",
+        // "list",
+        // "todo",
+        "justify",
+        // "quote",
+        // "emoticon",
+        "image",
+        // "video",
+        "table",
+        // "code",
+        // "splitLine",
+        "undo",
+        "redo",
+      ];
+      // 带格式粘贴
+      this.editor.config.pasteFilterStyle = false;
+      //忽略粘贴内容中的图片
+      this.editor.config.pasteIgnoreImg = false;
+      this.editor.config.showLinkImg = false;
+      this.editor.config.placeholder = this.placeholder;
+      var that = this;
+      this.editor.config.customUploadImg = function (files, insert) {
+        // const loading = Loading.service({
+        //   lock: true,
+        //   background: 'rgba(0, 0, 0, 0.7)'
+        // });
+        // 图片自定义上传方法
+        var kk = 0
+        for (var i = 0; i < files.length; i++) {
+          var file = files[i];
+          var credentials = {
+            accessKeyId: "AKIATLPEDU37QV5CHLMH",
+            secretAccessKey: "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",
+          }; //秘钥形式的登录上传
+          window.AWS.config.update(credentials);
+          window.AWS.config.region = "cn-northwest-1"; //设置区域
+
+          var bucket = new window.AWS.S3({ params: { Bucket: "ccrb" } }); //选择桶
+          that.proVisible = true
+          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) {
+                //这里可以写进度条
+                // console.log("Uploaded : " + parseInt((evt.loaded * 80) / evt.total) + '%');
+              })
+              .send(function (err, data) {
+                kk++
+                if(kk == files.length - 1 || kk > files.length - 1){
+                  that.proVisible = false
+                }
+                // loading.close();
+                if (err) {
+                  that.$message.error("上传失败");
+                } else {
+                  //上传成功处理
+                  insert(data.Location);
+                }
+              });
+          }
+        }
+      };
+      //配置 自定义处理粘贴的文本内容
+      this.editor.config.pasteTextHandle = function (content) {
+        if (content == '' && !content) return ''
+        var str = content
+        str = str.replace(/<xml>[\s\S]*?<\/xml>/ig, '')
+        str = str.replace(/<style>[\s\S]*?<\/style>/ig, '')
+        str = str.replace(/<\/?[^>]*>/g, '')
+        str = str.replace(/[ | ]*\n/g, '\n')
+        str = str.replace(/&nbsp;/ig, '')
+        // console.log('****', content)
+        // console.log('****', str)
+        return str
+      };
+      this.editor.config.onchange = (html) => {
+        this.info_ = html; // 绑定当前逐渐地值
+        this.$emit("change", this.info_); // 将内容同步到父组件中
+      };
+      // 创建富文本编辑器
+      this.editor.create();
+    },
+  },
+};
+</script>  
+  
+<style lang="css" scoped>
+.editor {
+   width: 100%;
+   margin: 10px auto;
+   position: relative;
+   z-index: 0;
+ }
+
+ .toolbar {
+   border: 1px solid #ccc;
+ }
+
+ .text {
+   border: 1px solid #ccc;
+   height: 230px;
+   overflow: auto;
+ }
+
+
+ /* table 样式 */
+ .cont>>>table {
+  border-top: 1px solid #ccc;
+  border-left: 1px solid #ccc;
+}
+
+.cont>>>table td,
+.cont>>>table th {
+  border-bottom: 1px solid #ccc;
+  border-right: 1px solid #ccc;
+  /* padding: 20px 5px; */
+  padding: 5px 10px;
+  max-width: 0px;
+  height: 30px;
+  vertical-align: baseline;
+}
+
+.cont>>>table th {
+  border-bottom: 2px solid #ccc;
+  text-align: center;
+}
+
+ /* blockquote 样式 */
+ .cont>>>blockquote {
+   display: block;
+   border-left: 8px solid #d0e5f2;
+   padding: 5px 10px;
+   margin: 10px 0;
+   line-height: 1.4;
+   font-size: 100%;
+   background-color: #f1f1f1;
+ }
+
+ /* code 样式 */
+ .cont>>>code {
+   display: inline-block;
+   *display: inline;
+   *zoom: 1;
+   background-color: #f1f1f1;
+   border-radius: 3px;
+   padding: 3px 5px;
+   margin: 0 3px;
+ }
+
+ .cont>>>pre code {
+   display: block;
+ }
+
+ /* ul ol 样式 */
+ .cont>>>ul,
+ ol {
+   margin: 0 !important;
+ }
+
+ /* .cont>>>.w-e-droplist{
+  width: 80px !important;
+ } */
+
+ .mask {
+  background-color: rgb(0 0 0 / 30%);
+  /* position: fixed; */
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  z-index: 99999;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.mask2 {
+  position: fixed !important;
+  z-index: 999999;
+}
+
+.progressBox {
+  width: 300px;
+  height: 150px;
+  background: #fff;
+  border-radius: 10px;
+  box-shadow: 0 0 6px 1px #bfbfbf;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  flex-direction: column;
+}
+
+.progressBox .lbox {
+  height: 100px;
+  font-size: 16px;
+  display: flex;
+  align-items: center;
+}
+
+.progressBox .lbox img {
+  width: 40px;
+  margin-right: 20px;
+}
+
+.progressBox>>>.el-progress-bar__outer {
+  background-color: #d1dfff !important;
+}
+
+.progressBox .lbox {
+  height: 100px;
+  font-size: 19px;
+  display: flex;
+  align-items: center;
+}
+
+.progressBox .lbox img {
+  width: 40px;
+  margin-right: 20px;
+}
+</style>  

+ 283 - 39
src/components/pages/classroomObservation/index.vue

@@ -12,18 +12,43 @@
 		</div> -->
 		<div class="co-header2">
 			<div class="co-h2-left">
-				<span class="co-h2-l-icon"></span>
+				<span
+					class="co-h2-l-icon"
+					@click="$refs.addNewCourseDialogRef.open()"
+				></span>
 				<span class="co-h2-l-hr"></span>
 				<span class="co-h2-l-text">
-					<el-select class="co_h2_l_t_select" v-model="tid" placeholder="请选择" @change="changeTid">
-  				  <el-option
-  				    v-for="item in optionData"
-  				    :key="item.value"
-  				    :label="item.label"
-  				    :value="item.value">
-  				  </el-option>
-  				</el-select>
+					<el-select
+						class="co_h2_l_t_select"
+						v-model="tid"
+						placeholder="请选择"
+						@change="changeTid"
+					>
+						<el-option
+							v-for="item in optionData"
+							:key="item.value"
+							:label="item.label"
+							:value="item.value"
+						>
+						<div class="selectBox">
+							<span style="float: left">{{ item.label }}</span>
+							<span
+								class="delSelect"
+								@click.stop="delCourse(item.value)"
+								style="float: right"
+							></span>
+						</div>
+							
+						</el-option>
+					</el-select>
 				</span>
+				<!-- <div
+					class="co_h2_l_del"
+					@click.stop="delCourse()"
+					v-if="optionData.length > 0"
+				>
+					<span></span>
+				</div> -->
 			</div>
 			<div class="co-h2-right">
 				<div
@@ -42,7 +67,7 @@
 					/>
 					<!-- <div>预览</div> -->
 				</div>
-				<div class="co-h2-r-btn2" @click.stop="share()">
+				<div class="co-h2-r-btn2" @click.stop="shareBtn">
 					<!-- <span class="co-h2-r-b-icon3"></span> -->
 					<img
 						src="../../../assets/icon/classroomObservation/daoChu.png"
@@ -54,12 +79,34 @@
 		</div>
 		<div class="co-main">
 			<div class="co-m-left">
-				<chatArea :tid="tid" @updateFileId="updateFileId" :fileIdid="fileIdid"/>
+				<chatArea
+					ref="chatAreaRef"
+					:tid="tid"
+					@updateFileId="updateFileId"
+					@changeAudioUrl="changeAudioUrl"
+					@updateTranscription="updateTranscription"
+					:fileId="fileId"
+					:fileIdId="fileIdId"
+				/>
 			</div>
 			<div class="co-m-right">
-				<messageArea :tid="tid" :fileId="fileId" ref="messageAreaRef" @updateFileId="updateFileId"  @updateFileIdid="updateFileIdid"/>
+				<messageArea
+					:tid="tid"
+					:fileId="fileId"
+					ref="messageAreaRef"
+					@changeAudioUrl="changeAudioUrl"
+					@changeChatAreaAudioUrl="changeChatAreaAudioUrl"
+					@changeTranscription="changeTranscription"
+					@changeOptionData="changeOptionData"
+				/>
 			</div>
 		</div>
+		<sharePdf
+			:dialogVisibleShare="dialogVisibleShare"
+			@shareBtn="shareBtn"
+		></sharePdf>
+
+		<addNewCourseDialog ref="addNewCourseDialogRef" @success="addNewCourse" />
 	</div>
 </template>
 
@@ -68,46 +115,87 @@
 import chatArea from "./components/chatArea.vue";
 // 信息区域
 import messageArea from "./components/messageArea.vue";
+
+import sharePdf from "./components/sharePdf.vue";
+// 添加课程弹窗
+import addNewCourseDialog from "./components/addNewCourseDialog.vue";
 export default {
 	components: {
 		chatArea,
 		messageArea,
+		sharePdf,
+		addNewCourseDialog,
 	},
 	data() {
 		return {
 			title: "12月19日会议录音",
 			loading: false,
-			tid:'03',
-			fileId:"",
-			fileIdid:"",
-			optionData:[
-				{label:"03课程",value:'03'},
-				{label:"04课程",value:'04'},
-			],
+			dialogVisibleShare: false,
+			tid: "",
+			fileId: "",
+			fileIdId: "",
+			optionData: [],
 		};
 	},
 	methods: {
 		//切换了课堂
-		changeTid(newValue){
-			// console.log(this.tid)
-			// console.log(newValue)
-			this.$nextTick(()=>{
+		changeTid(newValue) {
+			this.$nextTick(() => {
 				this.$refs.messageAreaRef.getData();
-			})
-		},
-		updateFileId(newValue){
-			this.fileId = newValue;
+				this.$refs.chatAreaRef.getData();
+				this.getFileIdId();
+			});
 		},
-		updateFileIdid(newValue){
-			this.fileIdid = newValue;
+		addNewCourse(form) {
+			let params = {
+				tid: form.no,
+				type: "10",
+			};
+			this.ajax
+				.post(
+					"https://gpt4.cocorobo.cn/insert_classroom_observation_tid",
+					params
+				)
+				.then((res) => {
+					console.log(res);
+					let _data = res.data.FunctionResponse;
+					if (_data.message == "创建成功") {
+						this.tid = form.no;
+						// 设置该课程的tid
+						this.ajax
+							.post("https://gpt4.cocorobo.cn/insert_classroom_observation", {
+								tid: this.tid,
+								type: 10,
+								index: 0,
+								json_data: JSON.stringify({ file_ids: "" }),
+							})
+							.then((res2) => {
+								let _data2 = res2.data.FunctionResponse;
+								if (_data2.message == "创建成功") {
+									this.$nextTick(() => {
+										this.getCourseList().then((_) => {
+											this.getFileIdId();
+											this.$refs.messageAreaRef.getData();
+											this.$refs.chatAreaRef.getData();
+										});
+									});
+								} else {
+									this.$message.error("创建fileIds失败");
+								}
+							});
+					} else if (_data.message == "tid重复") {
+						this.$message.error("该课程已存在");
+					} else {
+						this.$message.error("创建失败");
+					}
+				});
 		},
-		// 跳转
-		goTo(path) {
-			this.$message.info(`去到:${path}`);
+		updateFileId(newValue) {
+			this.fileId = newValue;
 		},
 		// 生成报告
 		getReport() {
-			this.$refs.messageAreaRef.getReport()
+			this.$refs.messageAreaRef.getReport();
 			// let assistant_title = [
 			// 	"课堂观察",
 			// 	"教学阶段九事件分析",
@@ -149,21 +237,130 @@ export default {
 			window.parent.postMessage(
 				{
 					tools: "classroom_observation_board",
-					type:this.tid,
+					type: this.tid,
 				},
 				"*"
 			);
 		},
 		// 分享
-		share() {
-			this.$message.info("分享");
+		shareBtn() {
+			this.dialogVisibleShare = !this.dialogVisibleShare;
+		},
+		delCourse(_value = this.tid) {
+			this.$confirm("此操作将永久删除该课程, 是否继续?", "提示", {
+				confirmButtonText: "确定",
+				cancelButtonText: "取消",
+				type: "warning",
+			})
+				.then(() => {
+					this.optionData.splice(
+						this.optionData.findIndex((item) => item.value == _value),
+						1
+					);
+					this.tid = this.optionData[0] ? this.optionData[0].value : "";
+					this.changeTid(this.tid);
+					this.$message({
+						type: "success",
+						message: "删除成功!",
+					});
+				})
+				.catch(() => {});
+		},
+		// 获取修改fileId的ID
+		getFileIdId() {
+			if (!this.tid) return;
+			let pram = {
+				tid: this.tid,
+				type: "10",
+			};
+			this.fileIdId = "";
+			this.fileId = "";
+			this.ajax
+				.post("https://gpt4.cocorobo.cn/get_classroom_observation_new", pram)
+				.then((res) => {
+					console.log(res);
+					let _data = res.data.FunctionResponse.result.length
+						? JSON.parse(res.data.FunctionResponse.result)
+						: [];
+					if (_data.length <= 0) return;
+					this.fileIdId = _data[0].id;
+					if (_data[0].jsonData != "") {
+						this.fileId = JSON.parse(_data[0].jsonData).file_ids;
+					} else {
+						this.fileId = "";
+					}
+				});
+		},
+		// 切换录音文件
+		changeAudioUrl(data) {
+			this.$refs.messageAreaRef.changeAudioUrl(data);
+		},
+		changeChatAreaAudioUrl(data) {
+			this.$refs.chatAreaRef.changeAudioUrl(data.url);
 		},
+		getCourseList() {
+			return new Promise((resolve, reject) => {
+				this.ajax
+					.post("https://gpt4.cocorobo.cn/get_classroom_observation_all")
+					.then((res) => {
+						let _data = res.data.FunctionResponse.result;
+						let _result = _data ? JSON.parse(_data) : [];
+						if (_result.length <= 0) return;
+						let _optionData = _result.map((item) => {
+							item.jsonData = item.jsonData ? JSON.parse(item.jsonData) : {};
+							return {
+								label: item.jsonData.courseName
+									? item.jsonData.courseName
+									: `${item.tId}课程`,
+								value: item.tId,
+							};
+						});
+						_optionData = _optionData.filter(
+							(i) => i.label != "" && i.tId != ""
+						);
+						this.optionData = _optionData;
+						if (this.optionData.length > 0) {
+							if (!this.tid) this.tid = this.optionData[0].value;
+						}
+						resolve();
+					});
+			});
+		},
+		updateTranscription({ transcriptionData, editorBarData }) {
+			this.$refs.messageAreaRef.updateMessageTranscription({
+				transcriptionData,
+				editorBarData,
+			});
+		},
+		changeTranscription({ transcriptionData, editorBarData }) {
+			this.$refs.chatAreaRef.changeEditorBar({
+				transcriptionData,
+				editorBarData,
+			});
+		},
+		changeOptionData(_tid,_newObj){
+			let _index = this.optionData.findIndex(i=>i.value==_tid);
+			if(_index!=-1){
+				this.optionData[_index] = {...this.optionData[_index],..._newObj}
+				this.$forceUpdate();
+			};
+			console.log(this.optionData)
+		},
+	},
+	mounted() {
+		this.getCourseList().then((_) => {
+			if(!this.tid)return;
+			this.getFileIdId();
+			this.$refs.messageAreaRef.getData();
+			this.$refs.chatAreaRef.getData();
+		});
 	},
 };
 </script>
 
 <style scoped>
 .classroomObservation {
+	min-width: 1500px;
 	width: 100%;
 	height: 100%;
 	display: flex;
@@ -252,8 +449,10 @@ export default {
 	width: 20px;
 	height: 20px;
 	position: relative;
-	background: url("../../../assets/icon/classroomObservation/Zkicon.png")
+	background: url("../../../assets/icon/classroomObservation/close.png")
 		no-repeat;
+	transform: rotate(45deg);
+	cursor: pointer;
 	background-size: 100% 100%;
 }
 .co-h2-l-hr {
@@ -354,10 +553,55 @@ export default {
 	overflow: auto;
 }
 
-.co_h2_l_t_select>>>.el-input__inner{
+.co_h2_l_t_select >>> .el-input__inner {
 	border: none;
 }
-.co_h2_l_t_select>>>.el-input__suffix{
+/* .co_h2_l_t_select >>> .el-input__suffix {
 	display: none;
+} */
+
+.co_h2_l_del {
+	width: 35px;
+	height: 35px;
+	margin-left: 10px;
+	border-radius: 5px;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	cursor: pointer;
+}
+
+.co_h2_l_del > span {
+	width: 20px;
+	height: 20px;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	background: url("../../../assets/icon/classroomObservation/del.png") no-repeat;
+	background-size: 100% 100%;
+}
+
+.co_h2_l_del:hover {
+	background-color: #eaeef1;
+}
+
+.selectBox{
+	width: 100%;
+	height: 100%;
+}
+.selectBox:hover .delSelect{
+	display: flex;
+}
+
+.delSelect {
+	width: 16px;
+	height: 16px;
+	display: none;
+	align-items: center;
+	justify-content: center;
+	background: url("../../../assets/icon/classroomObservation/del.png") no-repeat;
+	background-size: 100% 100%;
+	box-sizing: border-box;
+	transform: translateY(7px);
 }
 </style>

+ 100 - 14
src/components/pages/course.vue

@@ -32,7 +32,7 @@
               <!-- <div type="primary" @click="goToCourse2()">任务式课程</div> -->
               <!-- <div type="primary" @click="goToCourse()">阶段式课程</div> -->
               <div type="primary" @click="goToCourse4()">阶段式课程</div>
-              <!-- <div type="primary" @click="goToCourse5()">AI模式</div> -->
+              <div type="primary" @click="goToCourse5()">AI模式</div>
             </div>
           </button>
         </div>
@@ -204,7 +204,7 @@
               <!-- v-if="item.isCourseType == 2 || groupA == 1" -->
               <div class="kc_t">
                 <span>{{ item.uname }}</span>
-                <span>{{ item.state == 1 ? '阶段模式' : item.state == 2 ? '任务模式' : '极简模式' }}</span>
+                <span>{{ item.state == 1 ? '阶段模式' : item.state == 2 ? '任务模式' :  item.state == 3 ? '极简模式' : 'AI模式' }}</span>
               </div>
               <div class="kc_time">
                 <span style="color: #717C8D">创建日期:</span>{{ item.time }}
@@ -214,10 +214,67 @@
               </div>
             </div>
             <div class="three_bottom">
-              <!-- v-if="role == '1'" -->
-              <div @click="get(item)">预览</div>
+							<el-tooltip effect="dark" content="预览" placement="top">
+    					  <div class="t_b_Item" @click="get(item)">
+									<img style="height: 90%;width: 90%;" src="../../assets/icon/course/lookeye.svg">
+								</div>
+    					</el-tooltip>
+
+							<el-tooltip effect="dark" content="复制" placement="top">
+    					  <div class="t_b_Item" @click="copyCourse(item.courseId)">
+									<img src="../../assets/icon/course/copy.svg">
+								</div>
+    					</el-tooltip>
+
+							<el-tooltip effect="dark" content="修改" placement="top">
+    					  <div class="t_b_Item" v-if="((item.userid == userid) ||
+                (item.course_teacher &&
+                  item.course_teacher.indexOf(userid) !== -1) || role == '1') &&
+                item.state == 1
+                " @click="goToCourse(item.courseId)">
+									<img src="../../assets/icon/course/edit.svg">
+								</div>
+
+								<div class="t_b_Item" v-if="((item.userid == userid) ||
+                (item.course_teacher &&
+                  item.course_teacher.indexOf(userid) !== -1) || role == '1') &&
+                item.state == 2
+                "  @click="goToCourse(item.courseId)">
+									<img src="../../assets/icon/course/edit.svg">
+								</div>
+
+								<div class="t_b_Item" v-if="((item.userid == userid) ||
+                (item.course_teacher &&
+                  item.course_teacher.indexOf(userid) !== -1) || role == '1') &&
+                item.state == 3
+                " @click="goToCourse3(item.courseId)">
+									<img src="../../assets/icon/course/edit.svg">
+								</div>
+                <div class="t_b_Item" v-if="((item.userid == userid) ||
+                (item.course_teacher &&
+                  item.course_teacher.indexOf(userid) !== -1) || role == '1') &&
+                item.state == 4
+                " @click="goToCourse5(item.courseId)">
+									<img src="../../assets/icon/course/edit.svg">
+								</div>
+    					</el-tooltip>
+
+							<el-tooltip effect="dark" content="删除" placement="top">
+    					  <div class="t_b_Item" @click="deleteCourse(item.courseId)">
+									<img src="../../assets/icon/course/del.svg">
+								</div>
+    					</el-tooltip>
+
+							<el-tooltip effect="dark" content="分享" placement="top">
+    					  <div class="t_b_Item" @click="shareCourse(item.courseId)">
+									<img src="../../assets/icon/course/share.svg">
+								</div>
+    					</el-tooltip>
+
+							<!-- v-if="role == '1'" -->
+              <!-- <div @click="get(item)">预览</div> -->
               <!-- <div @click="jump(item.courseId)" v-else>评课</div> -->
-              <div v-if="((item.userid == userid) ||
+              <!-- <div v-if="((item.userid == userid) ||
                 (item.course_teacher &&
                   item.course_teacher.indexOf(userid) !== -1) || role == '1') &&
                 item.state == 1
@@ -237,7 +294,7 @@
                 item.state == 3
                 " @click="goToCourse3(item.courseId)">
                 修改
-              </div>
+              </div> -->
               <!-- <div v-if="groupA == '0'" @click="
                 goTo(
                   '/works?cid=' +
@@ -254,12 +311,12 @@
                 ">
                 评价
               </div> -->
-              <div @click="copyCourse(item.courseId)">
+              <!-- <div @click="copyCourse(item.courseId)">
                 复制
               </div>
               <div v-if="item.isCourseType == 1 || role == '1'" @click="deleteCourse(item.courseId)">
                 删除
-              </div>
+              </div> -->
               <!-- <div class="more">
                 <span style="font-size: 18px; font-weight: 700">...</span>
                 <div>
@@ -334,6 +391,7 @@
         <el-button @click="dialogVisibleCourse = false">关 闭</el-button>
       </span>
     </el-dialog>
+		<shareDialog ref="shareDialogRef"/>
   </div>
 </template>
 
@@ -341,8 +399,9 @@
 import "../../common/aws-sdk-2.235.1.min";
 import EditorBar from "../../components/tools/wangEnduit";
 import CourseProblem from "./components/courseProblem";
+import shareDialog from './dialog/shareDialog.vue'
 export default {
-  components: { EditorBar, CourseProblem },
+  components: { EditorBar, CourseProblem,shareDialog },
   data() {
     return {
       itemCount: 1,
@@ -396,6 +455,10 @@ export default {
     };
   },
   methods: {
+		// 分析按钮
+		shareCourse(courseId){
+			this.$refs.shareDialogRef.open(courseId)
+		},
     change(val) {
       console.log(val);
     },
@@ -1601,7 +1664,8 @@ export default {
 .three_bottom {
   display: flex;
   flex-direction: row;
-  justify-content: space-around;
+  /* justify-content: space-around; */
+	justify-content: flex-end;
   height: 45px;
   align-items: center;
   background: #fff;
@@ -1610,7 +1674,29 @@ export default {
   box-sizing: border-box;
 }
 
-.three_bottom>div {
+.t_b_Item{
+	width: 30px;
+	height: 30px;
+	background-color: white;
+	border-radius: 2px;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	transition: .3s;
+	margin-right: 10px;
+	cursor: pointer;
+}
+
+.t_b_Item:hover{
+	background-color: #E8E8E8;
+}
+
+.t_b_Item>img{
+	width: 80%;
+	height: 80%;
+}
+
+/* .three_bottom>div {
   cursor: pointer;
   width: 100%;
   text-align: center;
@@ -1618,12 +1704,12 @@ export default {
 
 .three_bottom>div+div {
   border-left: 1px solid #ddd;
-}
+} */
 
-.three_bottom>div:hover {
+/* .three_bottom>div:hover {
   color: #3681FC;
   font-weight: bold;
-}
+} */
 
 .three_bottom .deleteB {
   color: #E96E6E;

+ 2 - 2
src/components/pages/data.vue

@@ -36,7 +36,7 @@
         </div>
         <div class="data_nav">
           <span @click="type = 1" :class="{ active: type == 1 }">我的资料</span>
-          <span @click="type = 2" :class="{ active: type == 2 }">修改密码</span>
+          <span @click="type = 2" v-if="ruleForm.type !== '学生'" :class="{ active: type == 2 }">修改密码</span>
         </div>
         <el-form
           v-if="type == 1"
@@ -152,7 +152,7 @@
             ></el-input>
           </el-form-item> -->
           <el-form-item>
-            <el-button type="primary" @click="submitForm('ruleForm')"
+            <el-button type="primary"  v-if="ruleForm.type !== '学生'" @click="submitForm('ruleForm')"
               >保存</el-button
             >
           </el-form-item>

+ 477 - 0
src/components/pages/dialog/shareDialog.vue

@@ -0,0 +1,477 @@
+<template>
+  <div>
+    <el-dialog
+      title="分享设置"
+      :visible.sync="dialogVisible"
+      width="600px"
+      v-loading="loading"
+    >
+      <!-- <div class="shareContent">
+        <div class="sc_formItemDate">
+          <div>有效期:</div>
+          <el-radio
+            class="sc_fd_radio"
+            :disabled="form.id ? true : false"
+            v-model="date"
+            label="7"
+            >7天</el-radio
+          >
+          <el-radio
+            class="sc_fd_radio"
+            :disabled="form.id ? true : false"
+            v-model="date"
+            label="31"
+            >31天</el-radio
+          >
+          <el-radio
+            class="sc_fd_radio"
+            :disabled="form.id ? true : false"
+            v-model="date"
+            label="0"
+            >永久有效</el-radio
+          >
+        </div>
+
+        <div class="sc_formAuthorityItem">
+          <el-switch
+            class="sc_fai_switch"
+            :disabled="form.id ? true : false"
+            v-model="form.setPassword"
+            active-text="密码设置"
+          >
+          </el-switch>
+          <el-input
+            class="sc_fai_input"
+            :disabled="!form.setPassword || form.id ? true : false"
+            placeholder="请输入密码"
+            v-model="form.password"
+          ></el-input>
+          <span>仅支持数字及英文字母</span>
+        </div>
+
+        <div class="sc_formAuthorityItem">
+          <el-switch
+            class="sc_fai_switch"
+            :disabled="form.id ? true : false"
+            v-model="form.setStudentLook"
+            active-text="查看学生作业权限"
+          >
+          </el-switch>
+          <el-radio
+            class="sc_fai_radio"
+            :disabled="!form.setStudentLook || form.id ? true : false"
+            v-model="form.studentLook"
+            label="0"
+            >显示学生姓名</el-radio
+          >
+          <el-radio
+            class="sc_fai_radio"
+            :disabled="!form.setStudentLook || form.id ? true : false"
+            v-model="form.studentLook"
+            label="1"
+            >不显示学生真实姓名</el-radio
+          >
+        </div>
+
+        <div class="sc_formAuthorityItem">
+          <el-switch
+            class="sc_fai_switch"
+            :disabled="form.id ? true : false"
+            v-model="form.setComment"
+            active-text="评论权限"
+          >
+          </el-switch>
+          <el-radio
+            class="sc_fai_radio"
+            :disabled="!form.setComment || form.id ? true : false"
+            v-model="form.comment"
+            label="0"
+            >组织内人员</el-radio
+          >
+          <el-radio
+            class="sc_fai_radio"
+            :disabled="!form.setComment || form.id ? true : false"
+            v-model="form.comment"
+            label="1"
+            >所有人(包括游客用户)</el-radio
+          >
+        </div>
+
+        <div class="sc_formAuthorityItem">
+          <el-switch
+            class="sc_fai_switch"
+            :disabled="form.id ? true : false"
+            v-model="form.setDownload"
+            active-text="课程资源下载权限"
+          >
+          </el-switch>
+          <el-radio
+            class="sc_fai_radio"
+            :disabled="!form.setDownload || form.id ? true : false"
+            v-model="form.download"
+            label="0"
+            >组织内人员</el-radio
+          >
+          <el-radio
+            class="sc_fai_radio"
+            :disabled="!form.setDownload || form.id ? true : false"
+            v-model="form.download"
+            label="1"
+            >所有人(包括游客用户)</el-radio
+          >
+        </div>
+
+        <div class="sc_formAuthorityItem">
+          <el-switch
+            class="sc_fai_switch"
+            :disabled="form.id ? true : false"
+            v-model="form.setHomeWorkUpload"
+            active-text="作业上传权限"
+          >
+          </el-switch>
+          <span>仅组织内成员可使用工具上传内容</span>
+        </div>
+      </div> -->
+
+      <div class="sc_formUrl" v-show="form.url">
+        <el-input
+          class="sc_fu_input"
+          style="color: black"
+          disabled
+          v-model="form.url"
+        >
+          <template slot="append"
+            ><div class="sc_fu_copyBtn" @click.stop="copyUrl()">
+              复制链接
+            </div></template
+          >
+        </el-input>
+        <div class="qrcode" ref="qrCodeRef"></div>
+				<el-link class="qrcodeBtn" type="primary" @click="downloadQrCode()">下载二维码</el-link>
+      </div>
+      <span slot="footer" class="shareFooter">
+        <el-button @click="close()">取 消</el-button>
+        <!-- <el-button type="primary" v-if="!form.id" @click="generate()"
+					>生成</el-button
+				>
+				<el-button type="primary" v-else @click="resetGenerate()"
+					>重置生成</el-button
+				> -->
+      </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import QRCode from "qrcodejs2";
+export default {
+  data() {
+    return {
+      dialogVisible: false,
+      loading: false,
+      date: "0",
+      courseId: "",
+      form: {
+        setPassword: false,
+        password: "",
+        setStudentLook: false,
+        studentLook: "1",
+        setComment: false,
+        comment: "1",
+        setDownload: false,
+        download: "1",
+        setHomeWorkUpload: false,
+        url: ""
+      }
+    };
+  },
+  watch: {
+    "form.url"(newValue) {
+      this.$nextTick(() => {
+        this.$refs.qrCodeRef.innerHTML = "";
+        if (!newValue) return;
+        new QRCode(this.$refs.qrCodeRef, {
+          text: `https://beta.cloud.cocorobo.cn/#/?shareCourseId=${this.courseId}`, // 需要转换为二维码的内容
+          width: 100,
+          height: 100,
+          colorDark: "#000000",
+          colorLight: "#ffffff",
+          correctLevel: QRCode.CorrectLevel.H
+        });
+      });
+    }
+  },
+  methods: {
+    open(courseId) {
+      this.courseId = courseId;
+      this.dialogVisible = true;
+      this.form.id = "default";
+      this.form.url = `https://beta.cloud.cocorobo.cn/#/?shareCourseId=${this.courseId}`;
+      // this.getData();
+    },
+    close() {
+      this.dialogVisible = false;
+      this.form = {
+        setPassword: false,
+        password: "",
+        setStudentLook: false,
+        studentLook: "1",
+        setComment: false,
+        comment: "1",
+        setDownload: false,
+        download: "1",
+        setHomeWorkUpload: false,
+        url: ""
+      };
+      this.date = "0";
+      this.courseId = "";
+    },
+    generate() {
+      if (!this.courseId) return this.$message.error("错误:无课程ID");
+      if (this.loading) return;
+      this.loading = true;
+      if (this.form.setPassword) {
+        // 判断密码是否没输入
+        if (!this.form.password) {
+          this.loading = false;
+          return this.$message.error("请输入密码");
+        }
+        // 判断密码是否符合规则
+        const reg = /^[A-Za-z0-9]+$/;
+        if (!reg.test(this.form.password)) {
+          this.loading = false;
+          return this.$message.error("密码仅支持数字及英文字母");
+        }
+      }
+      this.form.url = `https://beta.cloud.cocorobo.cn/#/?shareCourseId=${this.courseId}`;
+      let pram = [
+        {
+          cid: this.courseId,
+          jsonData: JSON.stringify(this.form),
+          date: this.date,
+          type: 1
+        }
+      ];
+      this.ajax
+        .post(this.$store.state.api + "addShareCourse", pram)
+        .then(res => {
+          if (res.data == 1) {
+            this.$message.success("生成成功");
+          } else {
+            this.$message.error("生成失败");
+          }
+          this.getData();
+        })
+        .catch(err => {
+          console.log(err);
+          this.$message.error("生成失败");
+          this.getData();
+          this.loading = false;
+        });
+
+      // this.$message.success("生成成功");
+      this.loading = false;
+    },
+    resetGenerate() {
+      this.$confirm("此操作将重置分享链接, 是否继续?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        this.loading = true;
+        let pram = [
+          {
+            cid: this.courseId,
+            type: 1
+          }
+        ];
+        this.ajax
+          .post(this.$store.state.api + "delShareCourse", pram)
+          .then(res => {
+            if (res.data == 1) {
+              this.$message.success("重置成功");
+            } else {
+              this.$message.error("重置失败");
+            }
+            this.getData();
+          })
+          .catch(err => {
+            console.log(err);
+            this.$message.error("重置失败");
+            this.getData();
+            this.loading = false;
+          });
+        // this.form = {
+        // 	setPassword: false,
+        // 	password: "",
+        // 	setStudentLook: false,
+        // 	studentLook: "1",
+        // 	setComment: false,
+        // 	comment: "1",
+        // 	setDownload: false,
+        // 	download: "1",
+        // 	setHomeWorkUpload: false,
+        // 	url: "",
+        // };
+        // this.date = "0";
+        // this.$message.success('重置成功')
+      });
+    },
+    copyUrl() {
+      if (!this.form.url) {
+        return this.$message.info("请先生成链接");
+      }
+      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 = this.form.url;
+      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("复制成功");
+      }
+    },
+    getData() {
+      this.form = {
+        setPassword: false,
+        password: "",
+        setStudentLook: false,
+        studentLook: "1",
+        setComment: false,
+        comment: "1",
+        setDownload: false,
+        download: "1",
+        setHomeWorkUpload: false,
+        url: ""
+      };
+      this.date = "0";
+      this.loading = true;
+      // 这里查询数据库是否有数据
+      this.ajax
+        .get(this.$store.state.api + "getShareCourse", {
+          cid: this.courseId,
+          type: 1
+        })
+        .then(res => {
+          let _data = res.data[0];
+          if (_data.length == 0) return (this.loading = false);
+          let jsonData = _data[0].json ? JSON.parse(_data[0].json) : {};
+          this.form = { ...jsonData, id: _data[0].id };
+          this.date = _data[0].time;
+          this.loading = false;
+        })
+        .catch(err => {
+          this.loading = false;
+          console.error(err);
+        });
+    },
+		downloadQrCode(){
+			let canvas = this.$refs.qrCodeRef.getElementsByTagName('canvas')[0];
+			let ctx = canvas.getContext('2d');
+
+			// 创建一个新的canvas,大小为原来的两倍
+			var newCanvas = document.createElement("canvas");
+			newCanvas.width = canvas.width * 2;
+			newCanvas.height = canvas.height * 2;
+
+			// 获取新canvas的context,并绘制原来的canvas到新canvas上
+			var newCtx = newCanvas.getContext("2d");
+			newCtx.drawImage(canvas, 0, 0, newCanvas.width, newCanvas.height);
+
+			// 创建一个链接来下载图片
+			var link = document.createElement("a");
+			link.download = "课程分享二维码.png";
+			link.href = newCanvas.toDataURL();
+			link.click();
+		}
+  }
+};
+</script>
+
+<style scoped>
+.shareContent {
+  width: 600px;
+  max-width: 600px;
+  height: auto;
+}
+
+.shareFooter {
+  display: flex;
+  justify-content: flex-end;
+}
+
+.sc_formItemDate {
+  width: 100%;
+  height: auto;
+  display: flex;
+  align-items: center;
+  margin: 10px 0;
+}
+
+.sc_fd_radio {
+  margin-left: 55px;
+}
+
+.sc_formAuthorityItem {
+  margin-top: 30px;
+  margin-bottom: 20px;
+}
+
+.sc_formAuthorityItem > span {
+  font-size: 14px;
+  color: #7f7f7f;
+  margin-left: 20px;
+}
+
+.sc_fai_switch {
+  width: 190px;
+}
+
+.sc_fai_input {
+  width: 120px;
+  text-align: center;
+  margin-left: 20px;
+}
+
+.sc_fai_radio {
+  width: 120px;
+  margin-left: 20px;
+}
+.sc_fu_copyBtn {
+  color: black;
+  cursor: pointer;
+}
+
+.qrcode {
+  width: 100px;
+  height: 100px;
+  margin-top: 20px;
+}
+
+.sc_fu_input /deep/.el-input__inner {
+  color: black !important;
+  cursor: text !important;
+}
+
+.sc_fu_input >>> .el-input__inner {
+  color: black !important;
+  cursor: text !important;
+}
+
+.qrcodeBtn{
+	width: 100px;
+	display: flex;
+	justify-content: center;
+	margin-top: 10px;
+}
+</style>

+ 3 - 0
src/components/pages/easy/addCourse.vue

@@ -5092,6 +5092,9 @@ export default {
     },
     steps(newValue) {
       if (newValue == 4) {
+        if(this.org == '16ace517-b5c7-4168-a9bb-a9e0035df840'){
+          top.U.UF.F.closeWindow(top.$("#openCourseUpdate"))
+        }
         this.goTo(
           "/course?userid=" +
           this.userid +

+ 24 - 16
src/components/pages/newCourse/addCourse.vue

@@ -7782,7 +7782,7 @@ export default {
           JSON.stringify(this.unitJson2[_unitIndex]) ==
           JSON.stringify(this.unitJson[_unitIndex])
         ) {
-          this.$refs.rightboxR.scrollTop = 0;
+          // this.$refs.rightboxR.scrollTop = 0;
           return;
         }
         let cPan = 1;
@@ -7836,7 +7836,7 @@ export default {
             delete this.unitJson[i].isUpdate;
           }
         }
-        this.$refs.rightboxR.scrollTop = 0;
+        // this.$refs.rightboxR.scrollTop = 0;
         this.addindex = -1;
         let params = [
           {
@@ -7905,6 +7905,9 @@ export default {
           this.steps = old;
           return;
         }
+        if(this.org == '16ace517-b5c7-4168-a9bb-a9e0035df840'){
+          top.U.UF.F.closeWindow(top.$("#openCourseUpdate"))
+        }
         this.goTo(
           "/course?userid=" +
             this.userid +
@@ -11282,20 +11285,25 @@ export default {
                 ].toolChoose[toolIndex].englishVoiceJson
               )
             )
-          : {
-              time: "",
-              class: "",
-              difficulty: 0,
-              topic: "",
-              isShow: false,
-              eva: 0,
-              aiEva: {
-                isAiEva: false,
-                aiEvaChoose: [],
-              },
-              allfType: [],
-              englishJson: {},
-            };
+          : { 
+            title:'',
+            detail:'',
+            array:[]
+           };
+          //  {
+          //     time: "",
+          //     class: "",
+          //     difficulty: 0,
+          //     topic: "",
+          //     isShow: false,
+          //     eva: 0,
+          //     aiEva: {
+          //       isAiEva: false,
+          //       aiEvaChoose: [],
+          //     },
+          //     allfType: [],
+          //     englishJson: {},
+          //   };
         this.$forceUpdate();
         this.EnglishVoiceDialog = true;
       }

+ 1 - 1
src/components/pages/student/addCourse.vue

@@ -4642,7 +4642,7 @@ export default {
         "BMP",
         "GIF",
         "PNG",
-        "JPGE",
+        "JPEG",
         "JPG",
         "TIF",
         "PCX",

+ 1 - 1
src/components/pages/student/addCourseJiu.vue

@@ -4741,7 +4741,7 @@ export default {
         "BMP",
         "GIF",
         "PNG",
-        "JPGE",
+        "JPEG",
         "JPG",
         "TIF",
         "PCX",

+ 1 - 1
src/components/pages/studentManage/class.vue

@@ -106,7 +106,7 @@
             </el-table>
           </div>
           <div class="student_page">
-            <el-pagination background layout="prev, pager, next" :page-size="10" :total="total" v-if="page"
+            <el-pagination background layout="prev, pager, next" :page-size="10" :current-page="page" :total="total" v-if="page"
               @current-change="handleCurrentChange">
             </el-pagination>
           </div>

+ 1 - 1
src/components/pages/studio/addCourse.vue

@@ -5691,7 +5691,7 @@ export default {
         "BMP",
         "GIF",
         "PNG",
-        "JPGE",
+        "JPEG",
         "JPG",
         "TIF",
         "PCX",

+ 2 - 2
src/components/pages/tencent/data.vue

@@ -33,7 +33,7 @@
         </div>
         <div class="data_nav">
           <span @click="type = 1" :class="{ active: type == 1 }">我的资料</span>
-          <span @click="type = 2" :class="{ active: type == 2 }">修改密码</span>
+          <span @click="type = 2"  v-if="ruleForm.type !== '学生'" :class="{ active: type == 2 }">修改密码</span>
         </div>
         <el-form
           v-if="type == 1"
@@ -119,7 +119,7 @@
             </el-select>
           </el-form-item>
           <el-form-item>
-            <el-button type="primary" @click="submitForm('ruleForm')"
+            <el-button type="primary"  v-if="ruleForm.type !== '学生'" @click="submitForm('ruleForm')"
               >修改</el-button
             >
           </el-form-item>

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä