Kaynağa Gözat

Merge branch 'beta'

lsc 1 yıl önce
ebeveyn
işleme
9fedbd3e51
69 değiştirilmiş dosya ile 6403 ekleme ve 963 silme
  1. 1 1
      dist/index.html
  2. 0 0
      dist/static/css/app.3afa3c622e1cc5a4f8bfe4592e65ea9e.css
  3. 0 0
      dist/static/css/app.3afa3c622e1cc5a4f8bfe4592e65ea9e.css.map
  4. 0 0
      dist/static/css/app.ea64c8574fe04ba4b05b8b685277836b.css
  5. 0 0
      dist/static/css/app.ea64c8574fe04ba4b05b8b685277836b.css.map
  6. BIN
      dist/static/img/rt-ch.5bf72bb.png
  7. 6 0
      dist/static/img/videoFile.8b2406f.svg
  8. 0 0
      dist/static/js/app.dda05761b81a9d74fa44.js
  9. 0 0
      dist/static/js/app.dda05761b81a9d74fa44.js.map
  10. 0 0
      dist/static/js/manifest.571c38d63f24b1ae9e16.js.map
  11. 0 0
      dist/static/js/vendor.85f22e7b4ab99591785c.js
  12. 0 0
      dist/static/js/vendor.85f22e7b4ab99591785c.js.map
  13. 146 294
      package-lock.json
  14. 2 0
      package.json
  15. BIN
      src/assets/icon/classroomObservation/bmRefresh.png
  16. 3 0
      src/assets/icon/classroomObservation/collect1.svg
  17. 3 0
      src/assets/icon/classroomObservation/collect2.svg
  18. 3 0
      src/assets/icon/classroomObservation/delFile.svg
  19. 1 0
      src/assets/icon/classroomObservation/editIcon.svg
  20. BIN
      src/assets/icon/classroomObservation/rt-ch.png
  21. 6 0
      src/assets/icon/classroomObservation/videoFile.svg
  22. BIN
      src/assets/icon/fileIcon/downImg.png
  23. BIN
      src/assets/icon/fileIcon/retractImg.png
  24. BIN
      src/assets/icon/fileIcon/upImg.png
  25. 189 14
      src/components/pages/CaseDesign.vue
  26. 461 120
      src/components/pages/aiAddCourse/addCourse.vue
  27. 487 0
      src/components/pages/aiAddCourse/aiCreateDialog.vue
  28. 299 0
      src/components/pages/aiAddCourse/aiCreateVideoDialog.vue
  29. 1 1
      src/components/pages/aiAddCourse/aiTips.vue
  30. 14 8
      src/components/pages/aiAddCourse/templateDialog.vue
  31. 74 30
      src/components/pages/aiAddCourse/tipsDialog.vue
  32. 442 0
      src/components/pages/classroomObservation/components/addNewAnalysisDialog.vue
  33. 30 5
      src/components/pages/classroomObservation/components/analysis.vue
  34. 401 0
      src/components/pages/classroomObservation/components/analysis2.vue
  35. 4 2
      src/components/pages/classroomObservation/components/analysisItem.vue
  36. 258 0
      src/components/pages/classroomObservation/components/analysisItem2.vue
  37. 758 0
      src/components/pages/classroomObservation/components/analysisSpecialItem.vue
  38. 47 0
      src/components/pages/classroomObservation/components/analysisTemplateDialog.vue
  39. 343 23
      src/components/pages/classroomObservation/components/baseMessage.vue
  40. 4 3
      src/components/pages/classroomObservation/components/bindingFormDialog.vue
  41. 79 0
      src/components/pages/classroomObservation/components/changeCourseNameDialog.vue
  42. 483 234
      src/components/pages/classroomObservation/components/chatArea.vue
  43. 46 0
      src/components/pages/classroomObservation/components/eChartTemplate.vue
  44. 46 26
      src/components/pages/classroomObservation/components/messageArea.vue
  45. 280 0
      src/components/pages/classroomObservation/components/saveTemplateDialog.vue
  46. 1 1
      src/components/pages/classroomObservation/components/sharePdf.vue
  47. 48 0
      src/components/pages/classroomObservation/components/wordcloudEChart.vue
  48. 202 92
      src/components/pages/classroomObservation/index.vue
  49. 172 0
      src/components/pages/components/wOffice.vue
  50. 194 33
      src/components/pages/contrastObservation/index.vue
  51. 35 4
      src/components/pages/course.vue
  52. 1 0
      src/components/pages/kindStudentEva/test/component/sharePdf.vue
  53. 2 2
      src/components/pages/newCourse/addCourse.vue
  54. 7 2
      src/components/pages/pblCourse/index.vue
  55. 2 2
      src/components/pages/student.vue
  56. 22 6
      src/components/pages/studentManage/student.vue
  57. 14 4
      src/components/pages/sz/teacher.vue
  58. 28 0
      src/components/pages/test/add/components/checkOrder.vue
  59. 1 0
      src/components/pages/test/add/edit/index.vue
  60. 649 21
      src/components/pages/test/check/index.vue
  61. 15 0
      src/components/pages/test/examine/index.vue
  62. 1 1
      src/components/pages/test/index.vue
  63. 20 2
      src/components/pages/test/shareBox/index.vue
  64. 7 5
      src/components/pages/testStudent/view/component/course.vue
  65. 4 2
      src/components/pages/testStudent/view/component/eva.vue
  66. 5 3
      src/components/pages/testStudent/view/component/file.vue
  67. 4 3
      src/components/pages/testStudent/view/component/topic.vue
  68. 43 19
      src/components/pages/testStudent/view/preview.vue
  69. 9 0
      src/router/index.js

+ 1 - 1
dist/index.html

@@ -32,7 +32,7 @@
       width: 100%;
       background: #e6eaf0;
       font-family: '黑体';
-    }</style><link href=./static/css/app.3afa3c622e1cc5a4f8bfe4592e65ea9e.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.558d332d6613a7d8ae2d.js></script></body></html><script>function stopSafari() {
+    }</style><link href=./static/css/app.ea64c8574fe04ba4b05b8b685277836b.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.85f22e7b4ab99591785c.js></script><script type=text/javascript src=./static/js/app.dda05761b81a9d74fa44.js></script></body></html><script>function stopSafari() {
     //阻止safari浏览器双击放大功能
     let lastTouchEnd = 0  //更新手指弹起的时间
     document.documentElement.addEventListener("touchstart", function (event) {

Dosya farkı çok büyük olduğundan ihmal edildi
+ 0 - 0
dist/static/css/app.3afa3c622e1cc5a4f8bfe4592e65ea9e.css


Dosya farkı çok büyük olduğundan ihmal edildi
+ 0 - 0
dist/static/css/app.3afa3c622e1cc5a4f8bfe4592e65ea9e.css.map


Dosya farkı çok büyük olduğundan ihmal edildi
+ 0 - 0
dist/static/css/app.ea64c8574fe04ba4b05b8b685277836b.css


Dosya farkı çok büyük olduğundan ihmal edildi
+ 0 - 0
dist/static/css/app.ea64c8574fe04ba4b05b8b685277836b.css.map


BIN
dist/static/img/rt-ch.5bf72bb.png


Dosya farkı çok büyük olduğundan ihmal edildi
+ 6 - 0
dist/static/img/videoFile.8b2406f.svg


Dosya farkı çok büyük olduğundan ihmal edildi
+ 0 - 0
dist/static/js/app.dda05761b81a9d74fa44.js


Dosya farkı çok büyük olduğundan ihmal edildi
+ 0 - 0
dist/static/js/app.dda05761b81a9d74fa44.js.map


Dosya farkı çok büyük olduğundan ihmal edildi
+ 0 - 0
dist/static/js/manifest.571c38d63f24b1ae9e16.js.map


Dosya farkı çok büyük olduğundan ihmal edildi
+ 0 - 0
dist/static/js/vendor.85f22e7b4ab99591785c.js


Dosya farkı çok büyük olduğundan ihmal edildi
+ 0 - 0
dist/static/js/vendor.85f22e7b4ab99591785c.js.map


Dosya farkı çok büyük olduğundan ihmal edildi
+ 146 - 294
package-lock.json


+ 2 - 0
package.json

@@ -15,6 +15,7 @@
     "clipboard": "^2.0.10",
     "dayjs": "^1.11.7",
     "echarts": "^5.4.2",
+    "echarts-wordcloud": "^2.1.0",
     "element-china-area-data": "^5.0.2",
     "element-ui": "^2.15.1",
     "file-saver": "^2.0.5",
@@ -36,6 +37,7 @@
     "language-hk-loader": "^1.0.1",
     "markdown-it": "^14.1.0",
     "pdfjs-dist": "^2.5.207",
+    "pptxgenjs": "^3.12.0",
     "qrcodejs2": "^0.0.2",
     "qs": "^6.10.1",
     "relation-graph": "^1.1.0",

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


+ 3 - 0
src/assets/icon/classroomObservation/collect1.svg

@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M8.00001 1.5C8.1894 1.5 8.36253 1.61128 8.44723 1.78745L10.3276 5.69853L14.062 6.18401C14.2515 6.20865 14.411 6.34338 14.4729 6.53124C14.5349 6.71909 14.4886 6.92726 14.3536 7.06769L11.5537 9.9795L12.4851 13.8539C12.5302 14.0413 12.4715 14.2393 12.3329 14.368C12.1942 14.4967 11.9984 14.5347 11.8245 14.4669L8.00001 12.9754L4.17558 14.4669C4.0016 14.5347 3.80578 14.4967 3.66714 14.368C3.52849 14.2393 3.46988 14.0413 3.51494 13.8539L4.44628 9.9795L1.64646 7.06769C1.51143 6.92726 1.4651 6.71909 1.52708 6.53124C1.58905 6.34338 1.7485 6.20865 1.938 6.18401L5.67247 5.69853L7.5528 1.78745C7.6375 1.61128 7.81063 1.5 8.00001 1.5ZM8.00001 3.18275L6.44723 6.41255C6.37246 6.56806 6.22792 6.67442 6.06203 6.69598L3.07646 7.08411L5.35357 9.4523C5.47776 9.58146 5.52768 9.76891 5.48509 9.94611L4.71603 13.1454L7.82445 11.9331C7.93764 11.889 8.06238 11.889 8.17558 11.9331L11.284 13.1454L10.5149 9.94611C10.4723 9.76891 10.5223 9.58146 10.6465 9.4523L12.9236 7.08411L9.938 6.69598C9.77211 6.67442 9.62756 6.56806 9.5528 6.41255L8.00001 3.18275Z" fill="black" fill-opacity="0.4"/>
+</svg>

+ 3 - 0
src/assets/icon/classroomObservation/collect2.svg

@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M8 2L10.3041 5.82865L14.6574 6.83688L11.7281 10.2113L12.1145 14.6631L8 12.92L3.8855 14.6631L4.27186 10.2113L1.3426 6.83688L5.69588 5.82865L8 2Z" fill="#F6C826" stroke="#F6C826" stroke-linejoin="round"/>
+</svg>

+ 3 - 0
src/assets/icon/classroomObservation/delFile.svg

@@ -0,0 +1,3 @@
+<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M6.97031 6.43595L4.9125 4.30469C4.75 4.13751 4.48437 4.13438 4.31718 4.29688C4.23593 4.37344 4.18906 4.47969 4.1875 4.59219C4.18437 4.70469 4.22812 4.81251 4.30468 4.8922L6.3625 7.02345L4.23125 9.08126C4.06406 9.24376 4.06093 9.50938 4.22343 9.67657C4.29999 9.75782 4.40625 9.8047 4.51875 9.80626C4.63125 9.80938 4.73906 9.76563 4.81875 9.68907L6.95 7.63126L9.00781 9.76251C9.17031 9.9297 9.43593 9.93282 9.60312 9.77032C9.68437 9.69376 9.73125 9.58751 9.73281 9.47501C9.73593 9.36251 9.69218 9.25469 9.61562 9.17501L7.55781 7.04376L9.68906 4.98595C9.85625 4.82345 9.85937 4.55782 9.69687 4.39063C9.62031 4.30938 9.51406 4.26251 9.40156 4.26095C9.28906 4.25782 9.18124 4.30157 9.10156 4.37813L6.97031 6.43595ZM2.44375 11.3938C0.0109327 8.87345 0.0812452 4.85938 2.6 2.42501C5.12031 -0.00780511 9.13437 0.0625074 11.5687 2.58126C14.0016 5.10157 13.9328 9.11563 11.4125 11.55C8.89218 13.9828 4.87812 13.9141 2.44375 11.3938Z" fill="#FFBBBB"/>
+</svg>

+ 1 - 0
src/assets/icon/classroomObservation/editIcon.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1718184710434" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6130" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><path d="M620.8 179.2c20.053333-20.053333 52.906667-19.626667 72.533333 0.853333l151.893334 156.586667c19.626667 20.053333 19.2 52.48-0.853334 72.106667L392.106667 855.466667c-9.386667 9.386667-22.613333 14.933333-35.84 14.933333H204.8c-28.16 0-51.2-23.04-51.2-51.2v-157.013333c0-13.653333 5.546667-26.88 15.36-36.266667L620.8 179.2z m35.84 36.266667L204.8 662.186667v157.013333h151.466667l452.266666-447.146667-151.893333-156.586666zM537.6 844.8c0-14.08 11.52-25.6 25.6-25.6h256c14.08 0 25.6 11.52 25.6 25.6s-11.52 25.6-25.6 25.6h-256c-14.08 0-25.6-11.52-25.6-25.6z" fill="#1A2029" p-id="6131"></path></svg>

BIN
src/assets/icon/classroomObservation/rt-ch.png


Dosya farkı çok büyük olduğundan ihmal edildi
+ 6 - 0
src/assets/icon/classroomObservation/videoFile.svg


BIN
src/assets/icon/fileIcon/downImg.png


BIN
src/assets/icon/fileIcon/retractImg.png


BIN
src/assets/icon/fileIcon/upImg.png


+ 189 - 14
src/components/pages/CaseDesign.vue

@@ -21,7 +21,29 @@
             <el-option label="工具" value="tool"> </el-option>
             <el-option label="字数" value="font"> </el-option>
           </el-select>
-          <el-input v-model="search" class="student_input" placeholder="请输入教师名称或学校名称" @input="getData"></el-input>
+          <el-input v-model="search" class="student_input" placeholder="请输入教师名称或学校名称" @input="getTypeName"></el-input>
+          <div
+            class="student_input"
+            v-for="(item, index) in CourseType[0]"
+            :key="index"
+          >
+            <el-select
+              v-if="CourseTypeJson[item.id].length"
+              v-model="courseTypeId[item.id]"
+              :placeholder="'请选择'+item.name"
+              @change="getTypeName"
+            >
+              <el-option label="全部" value="1">全部</el-option>
+              <el-option
+                v-for="item1 in CourseTypeJson[item.id]"
+                :key="item1.id"
+                :label="item1.name"
+                :value="item1.id"
+              >
+              </el-option>
+            </el-select>
+          </div>
+          <el-button type="primary" class="bgColor" style="margin-left: 10px;" @click="reset">重置</el-button>
         </div>
       </div>
     </div>
@@ -71,6 +93,9 @@
                 <div>
                   <span>{{ scope.row.jdz.fontC }}</span><span>字</span>
                 </div>
+                <div>
+                  <span>{{ scope.row.jdz.ziyuanC }}</span><span>资源</span>
+                </div>
               </div>
             </div>
           </template>
@@ -288,6 +313,10 @@ export default {
       total: 0,
       page: 1,
       pageSize: 10,
+      CourseType: [],
+      CourseType2: [],
+      courseTypeId: [],
+      CourseTypeJson: [],
     };
   },
   methods: {
@@ -304,16 +333,139 @@ export default {
         return "";
       }
     },
+    reset(){
+      this.choose = ''
+      this.search = ''
+      for (var i = 0; i < this.CourseType[0].length; i++) {
+        this.courseTypeId[this.CourseType[0][i].id] = ''
+      }
+      this.page = 1;
+      this.isLoading = true
+      this.getData();
+    },
+    getTypeName() {
+      this.$forceUpdate();
+      this.page = 1;
+      this.isLoading = true
+      this.getData();
+    },
+    selectAllType() {
+      let params = {
+        org: this.org && this.org != "" ? this.org : "",
+        oid: this.oid && this.oid != "" ? this.oid : "",
+      };
+      this.ajax
+        .get(this.$store.state.api + "selectAllType", params)
+        .then((res) => {
+          if (this.oid == "69893dca-1d47-11ed-8c78-005056b86db5") {
+            res.data[0] = [...res.data[0], ...res.data[4]]
+          }
+          this.CourseType = res.data;
+          this.CourseType2 = [
+            { name: "智见课程", id: [] },
+            { name: "智行课程", id: [] },
+            { name: "智创课程", id: [] },
+          ];
+
+          for (var cti = 0; cti < res.data[0].length; cti++) {
+            if (
+              res.data[0][cti].id == "34628934-d02f-11ec-8c78-005056b86db5" ||
+              res.data[0][cti].id == "34629907-d02f-11ec-8c78-005056b86db5"
+            ) {
+              this.CourseType2[0].id.push(res.data[0][cti].id);
+            } else if (res.data[0][cti].id == "34628934-d02f-11ec-8c78-005056b86ac5" ||
+              res.data[0][cti].id == "34629907-d02f-11ec-8c78-005056b86ac5") {
+              this.CourseType2[1].id.push(res.data[0][cti].id);
+            } else if (res.data[0][cti].id == "34629bcc-d02f-11ec-8c78-005056b86db5") {
+              this.CourseType2[2].id.push(res.data[0][cti].id);
+            }
+            if (res.data[0][cti].id == "34628934-d02f-11ec-8c78-005056b86db5" || res.data[0][cti].id == "34628934-d02f-11ec-8c78-005056b86ac5") {
+              res.data[0][cti].name = "年级";
+            } else if (res.data[0][cti].id == "34629907-d02f-11ec-8c78-005056b86db5" || res.data[0][cti].id == "34629907-d02f-11ec-8c78-005056b86ac5") {
+              res.data[0][cti].name = "学科";
+            } else if (res.data[0][cti].id == "34629bcc-d02f-11ec-8c78-005056b86db5") {
+              res.data[0][cti].name = "主题";
+            }
+          }
+          for (var i = 0; i < res.data[0].length; i++) {
+            if (!this.cid) {
+              this.courseTypeId[res.data[0][i].id] = [];
+            }
+            if (!this.CourseTypeJson[res.data[0][i].id]) {
+              this.CourseTypeJson[res.data[0][i].id] = [];
+            }
+            if (this.oid == "69893dca-1d47-11ed-8c78-005056b86db5") {
+              if (res.data[0][i].name == "栏目") {
+                this.CourseType[0][i].name = "主题";
+              }
+            }
+            if (res.data[2].length == 0 && res.data[3].length == 0) {
+              for (var j = 0; j < res.data[1].length; j++) {
+                if (res.data[0][i].id == res.data[1][j].pid) {
+                  this.CourseTypeJson[res.data[0][i].id].push(res.data[1][j]); // 去除公共分类
+                }
+              }
+            } else {
+              if (res.data[2].length > 0) {
+                for (var j = 0; j < res.data[2].length; j++) {
+                  if (res.data[0][i].id == res.data[2][j].pid) {
+                    this.CourseTypeJson[res.data[0][i].id].push(res.data[2][j]); // 去除公共分类
+                  }
+                }
+              }
+              if (res.data[3].length > 0) {
+                for (var j = 0; j < res.data[3].length; j++) {
+                  if (res.data[0][i].id == res.data[3][j].pid) {
+                    this.CourseTypeJson[res.data[0][i].id].push(res.data[3][j]); // 去除公共分类
+                  }
+                }
+              }
+            }
+          }
+          this.getData();
+        })
+        .catch((err) => {
+          console.error(err);
+        });
+    },
     getData() {
+      var typeE = [];
+      var typea = '', typeb = '', typec = '', typed = '';
+      for (var i = 0; i < this.CourseType[0].length; i++) {
+        if (this.courseTypeId[this.CourseType[0][i].id] == "1") {
+          typeE.push(this.CourseType[0][i].id);
+        } else if (this.courseTypeId[this.CourseType[0][i].id] != "") {
+          if (this.CourseType[0][i].name == "年级") {
+            typea = this.courseTypeId[this.CourseType[0][i].id];
+          } else if (this.CourseType[0][i].name == "专栏") {
+            typeb = this.courseTypeId[this.CourseType[0][i].id];
+          } else if (this.CourseType[0][i].name == "栏目") {
+            typeb = this.courseTypeId[this.CourseType[0][i].id];
+          } else if (this.CourseType[0][i].name == "学院") {
+            typeb = this.courseTypeId[this.CourseType[0][i].id];
+          } else if (this.CourseType[0][i].name == "主题") {
+            typeb = this.courseTypeId[this.CourseType[0][i].id];
+          } else if (this.CourseType[0][i].name == "新技能") {
+            typec = this.courseTypeId[this.CourseType[0][i].id];
+          } else if (this.CourseType[0][i].name == "学科") {
+            typed = this.courseTypeId[this.CourseType[0][i].id];
+          }
+        }
+      }
       let params = {
         org: this.org,
         oid: this.oid,
+        typeA: typea,
+        typeB: typeb,
+        typeC: typec,
+        typeD: typed,
+        typeE: typeE.join(","),
         page: this.page,
         pageSize: this.pageSize
         // this.org
       };
       this.ajax
-        .get(this.$store.state.api + "selectCase3", params)
+        .get(this.$store.state.api + "selectCase4", params)
         .then((res) => {
           this.isLoading = false;
           let _res = res.data[0];
@@ -326,6 +478,7 @@ export default {
             let toolC = 0;
             let evalC = 0;
             let fontC = 0;
+            let ziyuanC = 0;
             let course = [];
             if (_user.indexOf(_res[i].tuid) == -1) {
               _res[i].course = []
@@ -333,6 +486,14 @@ export default {
               _user.push(_res[i].tuid)
             }
             for (var j = 0; j < _res2.length; j++) {
+              if(!_res2[j]["jdz"]){
+                _res2[j]["jdz"] = {};
+                _res2[j]["jdz"].taskC = 0;
+                _res2[j]["jdz"].toolC = 0;
+                _res2[j]["jdz"].evalC = 0;
+                _res2[j]["jdz"].fontC = 0;
+                _res2[j]["jdz"].ziyuanC = 0;
+              }
               if (_res[i].tuid == _res2[j].tuid) {
                 if (_res[i].userid) {
                   _res2[j].course.push({
@@ -345,6 +506,7 @@ export default {
                     let toolC2 = 0;
                     let evalC2 = 0;
                     let fontC2 = 0;
+                    let ziyuanC2 = 0;
                     fontC2 += _chapter[k].dyName ? _chapter[k].dyName.length : 0;
                     taskC2 = _chapter[k].chapterInfo[0].taskJson.length;
                     let _tasks = _chapter[k].chapterInfo[0].taskJson;
@@ -355,6 +517,9 @@ export default {
                       if (_tasks[task].toolChoose[0].tool.length > 0) {
                         toolC2 += _tasks[task].toolChoose.length;
                       }
+                      if(_tasks[task].chapterData.length){
+                        ziyuanC2 += _tasks[task].chapterData.length;
+                      }
                       console.log(_tasks[task].task);
                       fontC2 += _tasks[task].task ? _tasks[task].task.length : 0;
                       console.log(_tasks[task].taskDetail);
@@ -371,30 +536,35 @@ export default {
                       _res2[j]["jd" + (k + 1)].toolC += toolC2;
                       _res2[j]["jd" + (k + 1)].evalC += evalC2;
                       _res2[j]["jd" + (k + 1)].fontC += fontC2;
+                      _res2[j]["jd" + (k + 1)].ziyuanC += ziyuanC2;
                     } else {
                       _res2[j]["jd" + (k + 1)] = {};
                       _res2[j]["jd" + (k + 1)].taskC = taskC2;
                       _res2[j]["jd" + (k + 1)].toolC = toolC2;
                       _res2[j]["jd" + (k + 1)].evalC = evalC2;
                       _res2[j]["jd" + (k + 1)].fontC = fontC2;
+                      _res2[j]["jd" + (k + 1)].ziyuanC = ziyuanC2;
                     }
                     taskC += taskC2;
                     toolC += toolC2;
                     evalC += evalC2;
                     fontC += fontC2;
+                    ziyuanC += ziyuanC2;
                   }
-                  _res2[j]["jdz"] = {};
-                  _res2[j]["jdz"].taskC = taskC;
-                  _res2[j]["jdz"].toolC = toolC;
-                  _res2[j]["jdz"].evalC = evalC;
-                  _res2[j]["jdz"].fontC = fontC;
+                  // _res2[j]["jdz"] = {};
+                  _res2[j]["jdz"].taskC += taskC;
+                  _res2[j]["jdz"].toolC += toolC;
+                  _res2[j]["jdz"].evalC += evalC;
+                  _res2[j]["jdz"].fontC += fontC;
+                  _res2[j]["jdz"].ziyuanC += ziyuanC;
                   // _res2[j].course = course;
                 }else{
-                  _res2[j]["jdz"] = {};
-                  _res2[j]["jdz"].taskC = 0;
-                  _res2[j]["jdz"].toolC = 0;
-                  _res2[j]["jdz"].evalC = 0;
-                  _res2[j]["jdz"].fontC = 0;
+                  // _res2[j]["jdz"] = {};
+                  // _res2[j]["jdz"].taskC = 0;
+                  // _res2[j]["jdz"].toolC = 0;
+                  // _res2[j]["jdz"].evalC = 0;
+                  // _res2[j]["jdz"].fontC = 0;
+                  // _res2[j]["jdz"].ziyuanC = 0;
                 }
 
               }
@@ -467,7 +637,7 @@ export default {
   },
   mounted() {
     this.isLoading = true;
-    this.getData();
+    this.selectAllType();
     this.timer = setInterval(() => {
       this.getData();
     }, 60000);
@@ -479,7 +649,7 @@ export default {
 .student_input {
   width: 190px;
   font-size: 13px;
-  padding: 0 10px;
+  padding: 0 0 0 10px;
 }
 
 .cd_body {
@@ -609,6 +779,11 @@ export default {
   color: #3887fe;
 }
 
+.cd_d_span div:nth-child(5) span:nth-child(1) {
+  color: #f900ff;
+}
+
+
 .cd_d_span div span:nth-child(1) {
   margin-right: 5px;
 }

Dosya farkı çok büyük olduğundan ihmal edildi
+ 461 - 120
src/components/pages/aiAddCourse/addCourse.vue


+ 487 - 0
src/components/pages/aiAddCourse/aiCreateDialog.vue

@@ -0,0 +1,487 @@
+<template>
+    <el-dialog title="AI生成PPT" :visible.sync="dialogVisibleAiCreate" :append-to-body="true" width="700px"
+        :before-close="handleClose" class="dialog_diy">
+        <div style="height: 500px;padding:15px" v-loading="loading">
+            <!-- <div class="t_box">
+                <span>选择:</span>
+                <el-radio-group v-model="radio" @change="changeRadio">
+                    <el-radio :label="0">PPT</el-radio>
+                    <el-radio :label="1">教案</el-radio>
+                    <el-radio :label="2">视频</el-radio>
+                </el-radio-group>
+            </div> -->
+            <!-- <div class="t_box">
+                <span>提示词:</span>
+                <textarea rows="10" class="binfo_input binfo_textarea" cols placeholder="请输入提示词"
+                    v-model="detail"></textarea>
+            </div> -->
+            <wOffice v-if="url" :url="url"></wOffice>
+        </div>
+        <span slot="footer" class="dialog-footer">
+            <el-button @click="aiGet" type="primary">重新生成</el-button>
+            <el-button @click="confirm" type="primary">确 定</el-button>
+            <el-button @click="close">关 闭</el-button>
+        </span>
+    </el-dialog>
+</template>
+
+<script>
+import Pptxgen from "pptxgenjs"
+import wOffice from '../components/wOffice.vue'
+import { v4 as uuidv4 } from "uuid";
+
+export default {
+    components: {
+        wOffice,
+    },
+    props: {
+        dialogVisibleAiCreate: {
+            type: Boolean,
+            default: false
+        },
+        courseName: {
+            type: String,
+            default: ""
+        },
+        infoData: {
+            type: Array,
+            default: ""
+        }
+    },
+    // 根据用户给你的参考资料
+    data() {
+        return {
+            userid: this.$route.query.userid,
+            radio: 0,
+            aiJson: {
+                ppt: `## 任务
+请生成关于${this.courseName},为教师生成这节课的教学ppt,页数在20页左右。PPT的内容主要是讲解该课程中所有可能涉及到的知识点。
+
+## 工作流
+1. 从用户提供的参考资料中提取10个最重要的知识点(知识点水平限制在小学和初中),并输出。
+2. 针对10个知识点中的每个,你使用1~3页ppt详细的对知识点进行讲解。你的讲解词应该在100token左右
+3. 讲解完所有知识点后,再根据知识点出5道单选题(放在5页ppt中)
+
+## 限制
+- 你不能输出错误的知识,如果你实在不清楚,输出“对不起,我不确定”
+- 你不能输出违反伦理的内容`,
+                word: '',
+                video: ''
+            },
+            aiUrl: {
+                ppt: '',
+                word: '',
+                video: ''
+            },
+            detail: "",
+            loading: false,
+            url: "",
+            uJson: {}
+        }
+    },
+    watch: {
+        dialogVisibleAiCreate(newValue, oldValue) {
+            if (newValue) {
+                // if (this.radio == 0) {
+                    this.detail =  `## 任务
+请根据用户给你的参考资料,生成关于${this.courseName},为教师生成这节课的教学ppt,页数在20页左右。PPT的内容主要是讲解该课程中所有可能涉及到的知识点。
+
+## 工作流
+1. 从用户提供的参考资料中提取10个最重要的知识点(知识点水平限制在小学和初中),并输出。
+2. 针对10个知识点中的每个,你使用1~3页ppt详细的对知识点进行讲解。你的讲解词应该在100token左右
+3. 讲解完所有知识点后,再根据知识点出5道单选题(放在5页ppt中)
+
+## 限制
+- 你不能输出错误的知识,如果你实在不清楚,输出“对不起,我不确定”
+- 你不能输出违反伦理的内容`
+                // }
+                // if (this.radio == 1) {
+                //     this.detail = this.aiJson.word
+                // }
+                // if (this.radio == 2) {
+                //     this.detail = this.aiJson.video
+                // }
+                // this.loading = false
+                this.aiGet()
+            }
+        },
+    },
+    methods: {
+        handleClose(done) {
+            this.close()
+            done();
+        },
+        close() {
+            this.$emit('update:dialogVisibleAiCreate', false)
+        },
+        confirm() {
+            if(this.url){
+                this.$emit('createAiPpt', this.uJson)
+            }else {
+                this.$message.error('请先生成ppt');
+            }
+        },
+        changeRadio() {
+            if (this.radio == 0) {
+                this.detail = this.aiJson.ppt
+            }
+            if (this.radio == 1) {
+                this.detail = this.aiJson.word
+            }
+            if (this.radio == 2) {
+                this.detail = this.aiJson.video
+            }
+        },
+        createFileid(url) {
+            let _this = this
+            return new Promise((resolve, reject) => {
+                try {
+                _this.ajax
+                .put("https://gpt4.cocorobo.cn/upload_file_knowledge", {
+                    url: url,
+                })
+                .then((res) => {
+                    let _data = res.data.FunctionResponse;
+                    if (_data.result && _data.result.id) {
+                    resolve(_data.result.id)
+                    }
+                }).catch(function (error) {
+                    resolve('')
+                });
+                }catch (e){
+                resolve()
+                }
+                
+            });
+        },
+        async aiGet() {
+            if(this.loading){
+                this.$message.error('正在生成中,请稍后');
+                return;
+            }
+            this.url = ''
+            this.uJson = {}
+            let _this = this
+
+            let fileid = []
+            if (_this.infoData.length) {
+                for (var i = 0; i < _this.infoData.length; i++) {
+                if(_this.infoData[i].fileid){
+                    fileid.push(_this.infoData[i].fileid)
+                }else {
+                    let _fileid = await _this.createFileid(_this.infoData[i].url)
+                    if(_fileid){
+                    _this.infoData[i].fileid = _fileid
+                    _this.$forceUpdate();
+                    fileid.push(_fileid)
+                    }
+                }
+                }
+            }
+            console.log('fileid=========',fileid)  
+
+
+            let message = ''
+            if (_this.radio == 0) {
+                message = `NOTICE
+Role: 提供的参考资料中读取10个最重要的知识点(知识点水平限制在小学和初中,作为ppt内容。
+Output: Provide your output in json format.
+ATTENTION: Use '##' to SPLIT SECTIONS, not '#'. Output format carefully referenced "Format example".
+Instruction: Based on the context, follow "Format example", write content.
+
+# Context 
+## 任务
+请根据用户给你的参考资料,生成关于${this.courseName},为教师生成这节课的教学ppt,页数在20页左右。PPT的内容主要是讲解该课程中所有可能涉及到的知识点。
+
+## 工作流
+1. 提供的参考资料中读取10个最重要的知识点(知识点水平限制在小学和初中,作为ppt内容。
+2. 针对10个知识点中的每个,你使用1~3页ppt详细的对知识点进行讲解。你的讲解词应该在100token左右
+3. 讲解完所有知识点后,再根据知识点出5道单选题(放在5页ppt中)。
+
+# Format example
+[{"page": "页码(数字)","title": "标题","task": "对应教学任务:依据用户输入的参考资料而定,如果用户未提供则不输出","points": "知识点讲解:针对知识点的详细讲解,你的语气应该让小学或初中的学生清晰易懂的讲解。你的讲解词在100 token左右。请尽可能的详细,这对我很重要。"}]`
+            } else if (_this.radio == 1) {
+
+            } else if (_this.radio == 2) {
+
+            }
+
+
+            // let params = JSON.stringify({
+            //     // "model": "Chat",
+            //     model: 'gpt-3.5-turbo',
+            //     temperature: 0,
+            //     max_tokens: 4096,
+            //     top_p: 1,
+            //     frequency_penalty: 0,
+            //     presence_penalty: 0,
+            //     messages: [{
+            //         content: message,
+            //         role: 'user'
+            //     }],
+            //     stream: false,
+            //     uid: this.userid,
+            //     mind_map_question: "",
+            // })
+
+            // _this.loading = true
+            // _this.ajax.post('https://gpt4.cocorobo.cn/chat', params).then(function (response) {
+            //     console.log(response);
+            //     let data = response.data.FunctionResponse
+            //     if (data.choices && data.choices.length && data.choices[0].message) {
+            //         console.log(data.choices[0].message.content);
+            //         try {
+            //             let _data = JSON.parse(data.choices[0].message.content)
+            //             _this.createPpt(_data)
+            //         } catch (e) {
+            //             console.log('error_________________'+e);
+            //             _this.$message.error(data.choices[0].message.content)
+            //             _this.loading = false
+            //         }
+
+            //     }
+            // }).catch(function (error) {
+            //     _this.loading = false
+            //     console.log(error);
+            // });
+
+
+            let parm = {
+                assistant_id: '6063369f-289a-11ef-8bf4-12e77c4cb76b',
+                message: [{"type":"text", "text":message}],
+                session_name: uuidv4(),
+                userId: this.userid,
+                file_ids: fileid.length ? [...fileid] : '',
+            }
+            _this.loading = true
+            this.ajax
+                .post("https://gpt4.cocorobo.cn/ai_agent_park_chat", parm)
+                .then((response) => {
+                console.log(response);
+                let data = response.data.FunctionResponse
+                if (data.message) {
+                    console.log(data.message);
+                    try {
+                        let _data = JSON.parse(data.message.replaceAll('```json','').replaceAll('```',''))
+                        _this.createPpt(_data)
+                    } catch (e) {
+                        console.log('error_________________'+e);
+                        // _this.$message.error(data.message)
+                        try {
+                            // let _data = JSON.parse(data.message.match(/(?<=```json).*?(?=```)/)[0])
+                            var message = data.message;
+                            var jsonStart = message.indexOf("```json") + 7; // `+ 7` 是为了跳过 ```json
+                            var jsonEnd = message.indexOf("```", jsonStart);
+                            if (jsonStart !== -1 && jsonEnd !== -1) {
+                                var jsonString = message.substring(jsonStart, jsonEnd).trim();
+                                var _data2 = JSON.parse(jsonString);
+                                _this.createPpt(_data2);
+                            }else {
+                                _this.$message.error('生成失败,正在重新生成')
+                                _this.aiGet()
+                            }
+                        } catch (error) {
+                            _this.$message.error('生成失败,正在重新生成')
+                            _this.aiGet()
+                            _this.loading = false   
+                        }
+                    }
+                }
+                })
+                .catch((error) => {
+                _this.loading = false
+                console.log(error);
+                });
+        },
+        createPpt(array) {
+            // 1. 创建PPT
+            const pres = new Pptxgen()
+            for (var i = 0; i < array.length; i++) {
+                // 2. 创建一个PPT页面,每调用一次 pres.addSlide() 都可以生成一张新的页面
+                // 建议把每个页面的构造抽成一个个函数,然后通过函数调用生成新页面,代码不会很乱
+                const _slide = pres.addSlide()
+
+                // 3. 调用addTetx(),在PPT页面中插入文字“Hello World from PptxGenJS...”
+                // 括号里面是对文字的配置,文字横坐标x为1.5,纵坐标y为1.5,字体颜色 363636……
+                // 关于坐标长度与px的转换 x 1 = 127~128px 左右
+                const tempResult1 = array[i].title
+                _slide.addText(tempResult1, {
+                    x: 0.5, // 横坐标
+                    y: 0.5,
+                    color: '363636',
+                    fontSize: 24, // 字号
+                    fill: { color: 'F1F1F1' },
+                    align: 'center'
+                })
+                const tempResult2 = array[i].task
+                _slide.addText(tempResult2, {
+                    x: 0.5, // 横坐标
+                    y: 2,
+                    color: '363636',
+                    fontSize: 18, // 字号
+                    fill: { color: 'F1F1F1' },
+                    align: 'center'
+                })
+                const tempResult3 = array[i].points
+                _slide.addText(tempResult3, {
+                    x: 0.5, // 横坐标
+                    y: 4,
+                    color: '363636',
+                    fontSize: 18, // 字号
+                    fill: { color: 'F1F1F1' },
+                    align: 'center'
+                })
+            }
+
+            // 获取PPTX文件的ArrayBuffer
+
+            // 保存为 Blob 并处理
+            pres.write('blob').then((blob) => {
+                // 现在你有了一个 Blob 对象
+                console.log(blob);
+
+                const file = new File([blob], 'aiPpt.pptx', { type: "application/vnd.openxmlformats-officedocument.presentationml.presentation" });
+                console.log(pres)
+                this.beforeUpload(file)
+            });
+
+        },
+        beforeUpload(event) {
+            var file = event;
+            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) {
+                        _this.loading = false
+                        if (err) {
+                            _this.$message.error("上传失败");
+                        } else {
+                            _this.url = data.Location
+                            _this.uJson = {
+                              name: file.name,
+                              url: data.Location,
+                              type: 3,
+                            }
+                            console.log(data.Location);
+                        }
+                    });
+            }
+        },
+    },
+}
+</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;
+}
+
+.binfo_input {
+    width: 100%;
+    margin: 0;
+    padding: 5px 7px;
+    display: block;
+    min-width: 0;
+    outline: none;
+    box-sizing: border-box;
+    background: none;
+    border: none;
+    border-radius: 4px;
+    background: #fff;
+    font-size: 15px;
+    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: 15px;
+    resize: none;
+    /* background: #f6f6f6; */
+    font-family: "Microsoft YaHei";
+}
+
+.binfo_input:focus-visible {
+    border: 1.5px solid #3681fc !important;
+}
+
+
+.t_box {
+    display: flex;
+    margin-bottom: 15px;
+}
+
+.t_box>span:nth-child(1) {
+    min-width: 80px;
+    font-size: 16px;
+    color: #000;
+}
+</style>

+ 299 - 0
src/components/pages/aiAddCourse/aiCreateVideoDialog.vue

@@ -0,0 +1,299 @@
+<template>
+    <el-dialog title="AI生成视频" :visible.sync="dialogVisibleAiCreateVideo" :append-to-body="true" width="700px"
+        :before-close="handleClose" class="dialog_diy">
+        <div style="height: 500px;padding:15px" v-loading="loading">
+            <div style="position: relative; width: 100%;height: 40px;margin-bottom: 10px;">
+                <el-input class="inputC" style="height: 100%;" placeholder="搜索视频关键字" v-model="detail"
+                @keyup.enter.native="aiGet()"></el-input>
+                <div class="search_img" @click="aiGet" style="right: 10px">
+                <img src="../../../assets/icon/search.png" alt />
+                </div>
+            </div>
+            <div class="Box">
+                <div class="video_box" v-for="(item,index) in data" :key="index">
+                    <img :src="item.snippet.thumbnails.high.url" />
+                    <span class="name">{{ item.snippet.title }}</span> 
+                    <span class="detail">{{ item.snippet.description }}</span> 
+                    <div class="btn">
+                        <span @click="openUrl(item.id.videoId)">查看</span>
+                        <span @click="checkUrl(item.snippet.title,item.id.videoId)">选择</span>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <span slot="footer" class="dialog-footer">
+            <!-- <el-button @click="aiGet" type="primary">重新生成</el-button> -->
+            <!-- <el-button @click="confirm" type="primary">确 定</el-button> -->
+            <el-button @click="close">关 闭</el-button>
+        </span>
+    </el-dialog>
+</template>
+
+<script>
+
+export default {
+    components: {
+    },
+    props: {
+        dialogVisibleAiCreateVideo: {
+            type: Boolean,
+            default: false
+        },
+        courseName: {
+            type: String,
+            default: ""
+        },
+    },
+    // 根据用户给你的参考资料
+    data() {
+        return {
+            userid: this.$route.query.userid,
+            radio: 0,
+            aiJson: {
+                ppt: ``,
+                word: '',
+                video: ''
+            },
+            aiUrl: {
+                ppt: '',
+                word: '',
+                video: ''
+            },
+            detail: "",
+            loading: false,
+            url: "",
+            data: [],
+            uJson: {}
+        }
+    },
+    watch: {
+        dialogVisibleAiCreateVideo(newValue, oldValue) {
+            if (newValue) {
+                // if (this.radio == 0) {
+                this.detail = this.courseName
+                // }
+                // if (this.radio == 1) {
+                //     this.detail = this.aiJson.word
+                // }
+                // if (this.radio == 2) {
+                //     this.detail = this.aiJson.video
+                // }
+                // this.loading = false
+                this.aiGet()
+            }
+        },
+    },
+    methods: {
+        handleClose(done) {
+            this.close()
+            done();
+        },
+        close() {
+            this.$emit('update:dialogVisibleAiCreateVideo', false)
+        },
+        openUrl(url){
+            window.open('https://www.youtube.com/embed/'+url)
+        },
+        checkUrl(name,id) {
+            let json = {
+                name: "链接",
+                title: name,
+                url: 'https://www.youtube.com/embed/'+id,
+                type: 8,
+            }
+            this.$emit('createAiVideo', json)
+        },
+        changeRadio() {
+            if (this.radio == 0) {
+                this.detail = this.aiJson.ppt
+            }
+            if (this.radio == 1) {
+                this.detail = this.aiJson.word
+            }
+            if (this.radio == 2) {
+                this.detail = this.aiJson.video
+            }
+        },
+        async aiGet() {
+            let _this = this
+            _this.loading = true
+            this.ajax
+                .get(`https://www.googleapis.com/youtube/v3/search?key=AIzaSyBUvNQ5Wyua4PbStE2vp3t7MIY4htry-4M&part=snippet&q=${this.detail}`)
+                .then((response) => {
+                    console.log(response);
+                    _this.data = response.data.items
+                    _this.loading = false
+
+                })
+                .catch((error) => {
+                    _this.loading = false
+                    console.log(error);
+                });
+        },
+    },
+}
+</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;
+}
+
+.binfo_input {
+    width: 100%;
+    margin: 0;
+    padding: 5px 7px;
+    display: block;
+    min-width: 0;
+    outline: none;
+    box-sizing: border-box;
+    background: none;
+    border: none;
+    border-radius: 4px;
+    background: #fff;
+    font-size: 15px;
+    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: 15px;
+    resize: none;
+    /* background: #f6f6f6; */
+    font-family: "Microsoft YaHei";
+}
+
+.binfo_input:focus-visible {
+    border: 1.5px solid #3681fc !important;
+}
+
+
+.t_box {
+    display: flex;
+    margin-bottom: 15px;
+}
+
+.t_box>span:nth-child(1) {
+    min-width: 80px;
+    font-size: 16px;
+    color: #000;
+}
+
+.inputC >>> .el-input__inner{
+    padding: '0 35px 0 15px'
+}
+.search_img {
+  width: 20px;
+  height: 20px;
+  position: absolute;
+  right: 10px;
+  top: 50%;
+  transform: translateY(-50%);
+}
+
+.search_img>img {
+  width: 100%;
+  height: 100%;
+}
+
+
+.Box{
+    width: 100%;
+    height: calc(100% - 50px);
+    overflow: auto;
+    display: flex;
+    flex-direction: row;
+    justify-content: flex-start;
+    flex-wrap: wrap;
+}
+.video_box {
+    width: calc(100% / 2 - 10px);
+    /* overflow: hidden; */
+    margin-right: 10px;
+    display: flex;
+    flex-direction: column;
+    margin-bottom: 15px;
+    cursor: pointer;
+}
+.video_box > img{
+    height: 200px;
+    object-fit: cover;
+}
+
+.video_box > .detail{
+    color: #cecece;
+}
+.video_box > .name{
+    color: #000;
+    margin: 5px 0;
+    height: 32px;
+}
+
+.btn{
+    width: 100%;
+    height: 35px;
+    display: flex;
+    align-items: center;
+    margin-top: auto;
+}
+
+.btn > span:hover{
+    background: #4087f1;
+}
+
+.btn > span{
+    width: 100%;
+    height: 100%;
+    background: #3681fc;
+    color: #fff;
+    border-radius: 5px;
+    margin-top: 10px;
+    cursor: pointer;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+}
+
+.btn > span + span{
+    margin-left: 10px;
+}
+</style>

+ 1 - 1
src/components/pages/aiAddCourse/aiTips.vue

@@ -163,7 +163,7 @@ export default {
 .binfo_textarea {
     border: 1.5px solid #cad1dc;
     font-size: 15px;
-    resize: none;
+    resize: vertical;
     /* background: #f6f6f6; */
     font-family: "Microsoft YaHei";
 }

+ 14 - 8
src/components/pages/aiAddCourse/templateDialog.vue

@@ -10,6 +10,7 @@
                 </el-input>
             </div>
             <div class="a-d-t-right">
+                <el-button @click="open2()" type="primary" size="small" style="margin-right: 10px;">设置模板</el-button>
                 <span @click.stop="close">×</span>
             </div>
         </div>
@@ -58,6 +59,8 @@
 									">
                                 <div class="a-d-b-i-t-btn" v-if="item.userid == userid" style="margin-right: 10px;"
                                     @click="deleteA(item.id)">删除</div>
+                                <div class="a-d-b-i-t-btn1" v-if="item.userid == userid" style="margin-right: 10px;"
+                                    @click="open2(item.id)">修改</div>
                                 <div class="a-d-b-i-t-btn1" @click="open(item.id)">
                                     使用
                                 </div>
@@ -137,6 +140,9 @@ export default {
         open(id) {
             this.$emit('goToCourseTemplate', id)
         },
+        open2(id) {
+            this.$emit('goToCourseTemplate2', id)
+        },
         deleteA(id) {
             let _this = this
             _this.$confirm(
@@ -305,7 +311,7 @@ export default {
 }
 
 .a-d-t-right {
-    width: 40px;
+    /* width: 40px; */
     height: 40px;
     margin-right: 10px;
     display: flex;
@@ -342,8 +348,8 @@ export default {
 }
 
 .a-d-b-item {
-    width: 22%;
-    height: 200px;
+    width: 30%;
+    height: 240px;
     display: flex;
     flex-direction: column;
     background-color: #fff;
@@ -410,10 +416,10 @@ export default {
     overflow: hidden;
     /* max-height: 186px; */
     max-height: 100px;
-    height: 100px;
-    min-height: 100px;
+    height: 140px;
+    min-height: 140px;
     font-size: 14px;
-    -webkit-line-clamp: 5;
+    -webkit-line-clamp: 7;
     line-height: 20px;
     display: -webkit-box;
     -webkit-box-orient: vertical;
@@ -425,7 +431,7 @@ export default {
     font-size: 14px;
     width: 98%;
     box-sizing: border-box;
-    padding: 8px 25px;
+    padding: 8px 0;
     border: 1px solid rgb(247, 30, 30);
     border-radius: 5px;
     color: rgb(247, 30, 30);
@@ -439,7 +445,7 @@ export default {
     font-size: 14px;
     width: 98%;
     box-sizing: border-box;
-    padding: 8px 25px;
+    padding: 8px 0;
     border: 1px solid rgba(54, 129, 252, 1);
     border-radius: 5px;
     background-color: rgba(54, 129, 252, 1);

+ 74 - 30
src/components/pages/aiAddCourse/tipsDialog.vue

@@ -47,6 +47,10 @@ export default {
             type: String,
             default: ''
         },
+        templateid: {
+            type: String,
+            default: ''
+        }
     },
     data() {
         return {
@@ -61,11 +65,11 @@ export default {
                 this.title = this.tipsJson.name ? this.tipsJson.name : ''
                 this.detail = this.tipsJson.detail ? this.tipsJson.detail : ''
                 this.radio = this.tipsJson.open ? parseInt(this.tipsJson.open) : 0
-            }else {
+            } else {
                 this.$emit('update:tipsJson', {
-                    name:this.title,
-                    detail:this.detail,
-                    open:this.radio,
+                    name: this.title,
+                    detail: this.detail,
+                    open: this.radio,
                 })
             }
         },
@@ -83,50 +87,90 @@ export default {
                 this.$message.error('请输入模板名称');
                 return
             }
-            let params = {
-                userid: this.userid,
-                name: this.title
+            if (this.templateid) {
+                this.$confirm(
+                    "确定修改此模板嘛?",
+                    "提示",
+                    {
+                        confirmButtonText: "确定",
+                        cancelButtonText: "取消",
+                        type: "warning",
+                    }
+                )
+                    .then(() => {
+                        this.updateTipsTemplate();
+                    })
+                    .catch(() => {
+                        return;
+                    });
+            }else{
+                this.addTipsTemplate();
             }
+            // let params = {
+            //     userid: this.userid,
+            //     name: this.title
+            // }
+            // this.ajax
+            //     .get(this.$store.state.api + "selectTipsTemplateB", params)
+            //     .then((res) => {
+            //         if (res.data[0].length) {
+            //             this.$confirm(
+            //                 "发现已有此模板,是否以现在的内容覆盖此模板?",
+            //                 "提示",
+            //                 {
+            //                     confirmButtonText: "确定",
+            //                     cancelButtonText: "取消",
+            //                     type: "warning",
+            //                 }
+            //             )
+            //                 .then(() => {
+            //                     this.addTipsTemplate();
+            //                 })
+            //                 .catch(() => {
+            //                     return;
+            //                 });
+            //         } else {
+            //             this.addTipsTemplate();
+            //         }
+            //     })
+            //     .catch((err) => {
+            //         this.$message.error("网络不佳");
+            //         console.error(err);
+            //     });
+        },
+        addTipsTemplate() {
+            let params = [{
+                n: this.title,
+                d: this.detail,
+                json: JSON.stringify(this.aiJson),
+                o: this.radio,
+                uid: this.userid
+            }]
             this.ajax
-                .get(this.$store.state.api + "selectTipsTemplateB", params)
+                .post(this.$store.state.api + "addTipsTemplate", params)
                 .then((res) => {
-                    if (res.data[0].length) {
-                        this.$confirm(
-                            "发现已有此模板,是否以现在的内容覆盖此模板?",
-                            "提示",
-                            {
-                                confirmButtonText: "确定",
-                                cancelButtonText: "取消",
-                                type: "warning",
-                            }
-                        )
-                            .then(() => {
-                                this.addTipsTemplate();
-                            })
-                            .catch(() => {
-                                return;
-                            });
-                    } else {
-                        this.addTipsTemplate();
-                    }
+                    this.$message.success("保存成功");
+                    this.$emit('retrunCourse')
+                    this.close();
                 })
                 .catch((err) => {
                     this.$message.error("网络不佳");
                     console.error(err);
                 });
         },
-        addTipsTemplate() {
+        updateTipsTemplate() {
             let params = [{
                 n: this.title,
                 d: this.detail,
                 json: JSON.stringify(this.aiJson),
                 o: this.radio,
-                uid: this.userid
+                uid: this.templateid
             }]
             this.ajax
                 .post(this.$store.state.api + "addTipsTemplate", params)
                 .then((res) => {
-                    this.$message.success("保存成功");
+                    this.$message.success("修改成功");
+                    this.$emit('retrunCourse')
                     this.close();
                 })
                 .catch((err) => {

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

@@ -0,0 +1,442 @@
+<template>
+	<div>
+		<el-dialog :center="true" :visible.sync="dialogVisible" width="1200px" class="addTemplateDialog">
+			<!-- <div v-if="showDialog == true" class="a-dialog" v-el-drag-dialog> -->
+			<div class="a-d-top">
+				<div class="a-d-topTit"><div style="width: 136px">添加模块</div></div>
+				<div>
+					<el-input
+						placeholder="请输入内容"
+						prefix-icon="el-icon-search"
+						v-model="input2"
+						clearable
+					>
+					</el-input>
+				</div>
+				<div class="a-d-t-right">
+					<span @click.stop="close()">×</span>
+				</div>
+			</div>
+			<div style="display: flex; height: 100%">
+				<div class="a-d-t-left">
+					<!-- <div class="itemTit">我的模块</div> -->
+					<div
+						:style="
+							tagIndex == index
+								? 'background: rgba(226, 238, 255, 1);color: rgba(54, 129, 252, 1)'
+								: ''
+						"
+						class="a-d-t-l-item"
+						v-for="(item, index) in dialogTagList"
+						:key="item.id"
+						@click.stop="tagIndex = index"
+					>
+						{{ item.name }}
+					</div>
+				</div>
+				<div class="a-d-box">
+					
+					<div
+						style="
+							font-family: PingFang SC;
+							font-size: 16px;
+							font-weight: 600;
+							line-height: 22px;
+							text-align: left;
+							margin: 20px 0;
+							margin-bottom: 10px;
+						"
+					>
+						推荐
+					</div>
+					<div class="a-d-b-subject">
+						<span v-for="(item,index) in tagSubjectList" :class="['a_d_b_s_btn',tagSubject==item?'a_d_b_s_ActiveBtn':'']"  :key="index+'-'+tagIndex" @click.stop="tagSubject==item?tagSubject='':tagSubject=item">{{ item }}</span>
+					</div>
+					<div style="display: flex; flex-wrap: wrap">
+						<div
+							class="a-d-b-item"
+							v-for="(item, index) in searchDataList"
+							:key="index"
+						>
+							<div class="a-d-b-i-top">
+								<img
+									style="height: 22px; width: 22px"
+									:src="
+										require('../../../../assets/icon/classroomObservation/digImg.svg')
+									"
+								/>
+								<div class="a-d-b-i-t-title">{{ item.title }}</div>
+							</div>
+							<div class="a-d-b-i-bottom">{{ item.brief }}</div>
+							<div class="a-d-b-i-bottomPer" style="display: block">
+								{{item.sum}}人已使用
+							</div>
+							<div class="a-d-b-i-bottomBtn" style="display: none">
+								<div
+									style="
+										display: flex;
+										width: 100%;
+										justify-content: space-around;
+									"
+								>
+									<!-- <div class="a-d-b-i-t-btn">详情</div> -->
+									<div
+										class="a-d-b-i-t-btn1"
+										@click="addAnalysisItem(item.title)"
+									>
+										添加
+									</div>
+								</div>
+							</div>
+						</div>
+					</div>
+				</div>
+			</div>
+			<!-- </div> -->
+		</el-dialog>
+	</div>
+</template>
+
+<script>
+	export default {
+		props:{
+			dialogTagDataList:{
+				type:Array,
+				default:()=>{
+					return []
+				}
+			}
+		},
+		data(){
+			return{
+				dialogVisible:false,
+				input2:"",
+				tagIndex: 0,
+			tagSubject:'',
+				dialogTagList: [
+				{ id: 0, name: "通用课堂分析", },
+				{ id: 1, name: "学科课堂分析" },
+				{ id: 2, name: "扩展分析" },
+				//{ id: 3, name: "增值性分析" },
+			],
+			}
+		},
+		computed:{
+			searchDataList() {
+			let _result = this.dialogTagDataList.filter((i) => i.type == this.tagIndex);
+			if (this.input2) {
+				_result = _result.filter((i) => i.title.indexOf(this.input2) > -1);
+			}
+			if(this.tagSubject){
+				_result = _result.filter((i) => i.subject == this.tagSubject);
+			}
+
+			return _result
+		},
+		tagSubjectList(){
+			let _result = [];
+			this.dialogTagDataList.filter((i) => i.type == this.tagIndex).forEach(i=>{
+				if(i.subject && !_result.includes(i.subject)){
+					_result.push(i.subject)
+				}
+			})
+			return _result;
+		}
+		},
+		methods:{
+			open(type){
+				this.tagIndex = type;
+				this.input2 = "";
+				this.tagSubject = "";
+				this.dialogVisible = true;
+			},
+			close(){
+				this.dialogVisible = false;
+				this.tagIndex = 0;
+				this.input2 = "";
+				this.tagSubject = "";
+			},
+			addAnalysisItem(title){
+				this.$emit("success",title)
+			}
+		}
+	}
+</script>
+
+<style scoped>
+.a-d-top {
+	/* background: #adadad; */
+	display: flex;
+	flex-direction: row;
+	flex-wrap: nowrap;
+	align-items: center;
+	justify-content: space-between;
+	height: 54px;
+	border-radius: 8px 8px 0 0;
+	user-select: none;
+	border-bottom: 1px #ccc solid;
+}
+.a-d-top >>> .el-input__inner {
+	width: 320px;
+	height: 32px;
+}
+.a-d-top >>> .el-input__icon {
+	line-height: 32px;
+}
+.a-d-topTit {
+	width: 171px;
+	height: 32px;
+	display: flex;
+	align-items: center;
+	font-family: PingFang SC;
+	box-sizing: border-box;
+	padding: 5px;
+	line-height: 22px;
+	justify-content: center;
+	/* text-align: left; */
+}
+.a-d-t-left {
+	width: 200px;
+	height: 100%;
+	display: flex;
+	align-items: center;
+	flex-direction: column;
+	justify-content: flex-start;
+	box-sizing: border-box;
+	padding-left: 5px;
+}
+
+.a-d-t-l-item {
+	/* width: auto;
+	height: 90%;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	padding: 0 10px;
+	border-radius: 10px;
+	background-color: #d4d9da;
+	margin-right: 3px;
+	cursor: pointer; */
+	cursor: pointer;
+	width: 136px;
+	height: 32px;
+	display: flex;
+	align-items: center;
+	border-radius: 5px;
+	font-family: PingFang SC;
+	box-sizing: border-box;
+	padding: 5px;
+	font-size: 14px;
+	font-weight: 600;
+	line-height: 22px;
+	text-align: left;
+	margin-top: 20px;
+	/* margin-bottom: 20px; */
+}
+
+.a-d-t-l-item:hover {
+	background-color: white;
+}
+
+.a-d-t-right {
+	width: 40px;
+	height: 40px;
+	margin-right: 10px;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	color: black !important;
+}
+
+.a-d-t-right > span {
+	width: 25px;
+	height: 25px;
+	border-radius: 25px;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	/* align-items: center; */
+	font-size: 22px;
+	color: #fff;
+	/* background-color: #adadad; */
+	cursor: pointer;
+	/* background-color: #e6e6e6; */
+	color: #adadad;
+}
+
+.a-d-box {
+	width: 100%;
+	height: 100%;
+	background-color: #f0f2f5;
+	overflow: scroll;
+	overflow-x: hidden;
+	box-sizing: border-box;
+	padding: 15px;
+	padding-bottom: 50px;
+}
+
+.a-d-b-item {
+	width: 22%;
+	height: 200px;
+	display: flex;
+	flex-direction: column;
+	background-color: #fff;
+	border-radius: 10px;
+	padding: 15px;
+	float: left;
+	box-sizing: border-box;
+	margin-bottom: 10px;
+	margin-right: 20px;
+	transform: .3s;
+	box-shadow: 0 16px 24px 2px #f0f2f5;
+	/* position: relative; */
+}
+
+.a-d-b-item:hover{
+	box-shadow: 0 16px 24px 2px #0000001c;
+}
+
+.a-d-b-item:hover .a-d-b-i-bottomBtn {
+	display: block !important;
+}
+.a-d-b-item:hover .a-d-b-i-bottomPer {
+	display: none !important;
+}
+.a-d-b-i-top {
+	width: 100%;
+	/* height: 50%; */
+	height: 20px;
+	margin-bottom: 15px;
+	display: flex;
+	align-items: center;
+	/* justify-content: space-between; */
+}
+.a-d-b-i-top > img {
+	width: 35px;
+	height: 35px;
+}
+/* .a-d-b-i-top>div{ */
+/* width: auto;
+	height: 35px;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	margin-left: 10px; */
+/* } */
+
+.a-d-b-i-t-title {
+	width: 100%;
+	height: 35px;
+	display: block;
+	align-items: center;
+	box-sizing: border-box;
+	padding: 0 10px;
+	text-overflow: ellipsis;
+	overflow: hidden;
+	word-break: break-all;
+	white-space: nowrap;
+	line-height: 35px;
+	/* display: -webkit-box;
+	-webkit-box-orient: vertical;
+	-webkit-line-clamp: 1;
+	overflow: hidden; */
+}
+
+.a-d-b-i-bottom {
+	width: 100%;
+	flex: 1;
+	overflow: hidden;
+	/* max-height: 186px; */
+	font-size: 14px;
+	-webkit-line-clamp: 5;
+	line-height: 20px;
+	display: -webkit-box;
+	-webkit-box-orient: vertical;
+	overflow: hidden;
+	text-overflow: ellipsis;
+}
+
+.a-d-b-i-t-btn {
+	font-size: 14px;
+	box-sizing: border-box;
+	padding: 8px 25px;
+	border: 1px solid rgba(54, 129, 252, 1);
+	border-radius: 5px;
+	color: rgba(54, 129, 252, 1);
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	cursor: pointer;
+}
+.a-d-b-i-t-btn1 {
+	font-size: 14px;
+	width: 98%;
+	box-sizing: border-box;
+	padding: 8px 25px;
+	border: 1px solid rgba(54, 129, 252, 1);
+	border-radius: 5px;
+	background-color: rgba(54, 129, 252, 1);
+	display: flex;
+	color: #fff;
+	justify-content: center;
+	align-items: center;
+	cursor: pointer;
+}
+.addTemplateDialog >>> .el-dialog {
+	min-width: 1200px;
+
+	height: 700px;
+	box-shadow: 0px 0 8px 0px #555555;
+	border-radius: 8px;
+	background-color: #fff;
+	/* top: 0px; */
+	/* margin: 0 auto; */
+	overflow: hidden;
+}
+.addTemplateDialog >>> .el-dialog__body {
+	height: 100%;
+	min-width: 1200px;
+	flex-shrink: 0;
+	box-sizing: border-box;
+	padding-bottom: 50px;
+	padding-top: 10px;
+}
+.addTemplateDialog >>> .el-dialog__header {
+	display: none;
+}
+.itemTit {
+	width: 136px;
+	height: 32px;
+	padding: 5px 8px 5px 8px;
+	gap: 8px;
+	opacity: 0px;
+	margin: 20px 0;
+	margin-bottom: 10px;
+	border-bottom: 1px #ccc solid;
+}
+
+.a-d-b-subject{
+	margin: 20px 0 20px 0;
+}
+
+.a_d_b_s_btn{
+	padding: 5px 10px;
+	border-radius: 4px;
+	border: solid 1px #3681FC;
+	color: #3681FC;
+	background-color: white;
+	margin-right: 10px;
+	cursor: pointer;
+	transition: .3s;
+}
+
+.a_d_b_s_ActiveBtn{
+	background-color: #3681FC;
+	color: white;
+}
+
+.a-d-b-i-t-btn:hover {
+	background-color: rgba(54, 129, 252, 1);
+	color: #fff;
+}
+</style>

+ 30 - 5
src/components/pages/classroomObservation/components/analysis.vue

@@ -13,10 +13,10 @@
 			</div>
 		</div>
 		<div class="a-main" v-show="showItem">
-			<analysisItem
+			<template v-for="(item, index) in analysisItemList">
+				<analysisItem
 				ref="analysisItemRef"
-				v-if="item.jsonData.name!='词频词汇分析'"
-				v-for="(item, index) in analysisItemList"
+				v-if="(item.jsonData.name!='词频词汇分析') && !['S-T分析:课堂时间分配','S-T分析:师生互动分析','S-T分析:教学模式分析'].includes(item.jsonData.name) "
 				:dialogTagDataList="dialogTagDataList"
 				:key="item.id"
 				:data="item"
@@ -28,6 +28,22 @@
 				@editItem="editItem"
 				@saveItem="saveItem"
 			/>
+			<analysisSpecialItem
+				v-if="['S-T分析:课堂时间分配','S-T分析:师生互动分析','S-T分析:教学模式分析'].includes(item.jsonData.name)"
+				:dialogTagDataList="dialogTagDataList"
+				ref="analysisItemRef"
+				:bmData="bmData"
+				:key="item.id"
+				:data="item"
+				:tid="tid"
+				:fileId="fileId"
+				:index="index"
+				:showBrief="showBrief"
+				@delItem="delItem"
+				@editItem="editItem"
+				@saveItem="saveItem"
+			/>
+			</template>
 			<div class="a_m_empty" v-if="analysisItemList.length == 0">
 				暂无模块...
 			</div>
@@ -37,9 +53,16 @@
 
 <script>
 import analysisItem from "./analysisItem";
+import analysisSpecialItem from './analysisSpecialItem'
 export default {
 	emits: ["delItem", "editItem","saveItem"],
 	props: {
+		bmData:{
+			type:Object,
+			default:()=>{
+				return {}
+			}
+		},
 		title: {
 			type: String,
 			default: "分析",
@@ -75,6 +98,7 @@ export default {
 	},
 	components: {
 		analysisItem,
+		analysisSpecialItem
 	},
 	data() {
 		return {
@@ -84,6 +108,7 @@ export default {
 	},
 	methods: {
 		addTemplate() {
+			if(!this.tid)return this.$message.error("请选择课堂")
 			this.$emit("updateMessage", this.type);
 		},
 		changeShowItem(newValue) {
@@ -101,11 +126,11 @@ export default {
 		getReport(id) {
 			if (!id) {
 				this.$refs.analysisItemRef.forEach((i) => {
-					i.editBtn();
+					i.editBtn(false);
 				});
 			} else {
 				this.$nextTick(()=>{
-					this.$refs.analysisItemRef[this.analysisItemList.findIndex((i) => i.id == id)].editBtn();
+					this.$refs.analysisItemRef[this.analysisItemList.findIndex((i) => i.id == id)].editBtn(false);
 				})
 				
 			}

+ 401 - 0
src/components/pages/classroomObservation/components/analysis2.vue

@@ -0,0 +1,401 @@
+<template>
+	<div class="analysis">
+		<div class="a-header">
+			<div class="a-h-left" @click.stop="changeShowItem(!showItem)">
+				<span :class="['a-h-l-icon', showItem ? 'a-h-l-showIcon' : '']"></span>
+				<span class="a-h-l-title">{{ title }}</span>
+			</div>
+			<div class="a-h-right" v-if="showAdd">
+				<div class="a-h-r-btn" @click.stop="addTemplate">
+					<img src="@/assets/icon/classroomObservation/newcon.svg" alt="" />
+					添加模块
+				</div>
+			</div>
+		</div>
+		<div class="a-main" v-show="showItem">
+			<analysisItem
+				ref="analysisItemRef"
+				v-if="item.jsonData.name!='词频词汇分析'"
+				v-for="(item, index) in analysisItemList"
+				:key="index"
+				:data="item"
+				
+				:index="index"
+				:showAdd="showAdd"
+				@delItem="delItem"
+			/>
+			<div class="a_m_empty" v-if="analysisItemList.length == 0">
+				暂无模块...
+			</div>
+		</div>
+	</div>
+</template>
+
+<script>
+import analysisItem from "./analysisItem2";
+export default {
+	emits: ["delItem","addAnalysisItem"],
+	props: {
+		title: {
+			type: String,
+			default: "分析",
+		},
+		analysisItemList: {
+			type: Array,
+			default: () => {
+				return [];
+			},
+		},
+		type: {
+			type: Number,
+			default: 0,
+		},
+		showAdd:{
+			type:Boolean,
+			default:false
+		}
+	},
+	components: {
+		analysisItem,
+	},
+	data() {
+		return {
+			showDialog: false,
+			showItem: true,
+		};
+	},
+	methods: {
+		addTemplate() {
+			this.$emit('addAnalysisItem',this.type)
+		},
+		changeShowItem(newValue) {
+			this.showItem = newValue;
+		},
+		delItem(index) {
+			this.$emit("delItem",this.type,index);
+		},
+	},
+};
+</script>
+
+<style scoped>
+.itemTit {
+	width: 136px;
+	height: 32px;
+	padding: 5px 8px 5px 8px;
+	gap: 8px;
+	opacity: 0px;
+	margin: 20px 0;
+	margin-bottom: 10px;
+	border-bottom: 1px #ccc solid;
+}
+.analysis {
+	width: 100%;
+	height: auto;
+}
+
+.a-header {
+	width: 100%;
+	height: 50px;
+	display: flex;
+	align-items: center;
+	justify-content: space-between;
+	box-sizing: border-box;
+	padding-right: 10px;
+}
+
+.a-h-left {
+	display: flex;
+	align-items: center;
+	cursor: pointer;
+}
+
+.a-h-l-icon {
+	width: 16px;
+	height: 16px;
+	background: url("../../../../assets/icon/classroomObservation/right.svg")
+		no-repeat;
+	background-size: 100% 100%;
+	margin-right: 5px;
+	transition: 0.3s;
+}
+
+.a-h-l-showIcon {
+	transform: rotate(90deg);
+}
+
+.a-h-l-title {
+	font-size: 18px;
+}
+
+.a-h-r-btn {
+	font-size: 16px;
+	height: 35px;
+	width: auto;
+	box-sizing: border-box;
+	/* padding: 0 20px; */
+	/* border: solid 1px #C5C5C5; */
+	/* border-radius: 18px; */
+	cursor: pointer;
+	/* background-color: white; */
+	display: flex;
+	color: rgba(54, 129, 252, 1);
+	justify-content: center;
+	align-items: center;
+}
+
+.a-h-r-btn > img {
+	width: 16px;
+	height: 16px;
+	margin-right: 5px;
+}
+
+.a-main {
+	width: calc(100%);
+	height: auto;
+}
+
+.a-dialog {
+	position: fixed;
+	width: 1200px;
+	height: 500px;
+	min-height: 600px;
+	box-shadow: 0px 0 8px 0px #555555;
+	border-radius: 8px;
+	z-index: 999;
+	background-color: #fff;
+	left: 0;
+	right: 0;
+	top: 100px;
+	margin: 0 auto;
+	/* margin: 0 auto; */
+	/* top: 50%; */
+	/* margin: -18% 0 0 -300px; */
+	overflow: hidden;
+}
+
+.a-d-top {
+	/* background: #adadad; */
+	display: flex;
+	flex-direction: row;
+	flex-wrap: nowrap;
+	align-items: center;
+	justify-content: space-between;
+	height: 54px;
+	border-radius: 8px 8px 0 0;
+	user-select: none;
+	border-bottom: 1px #ccc solid;
+}
+.a-d-top >>> .el-input__inner {
+	width: 320px;
+	height: 32px;
+}
+.a-d-top >>> .el-input__icon {
+	line-height: 32px;
+}
+.a-d-topTit {
+	width: 171px;
+	height: 32px;
+	display: flex;
+	align-items: center;
+	font-family: PingFang SC;
+	box-sizing: border-box;
+	padding: 5px;
+	line-height: 22px;
+	justify-content: center;
+	/* text-align: left; */
+}
+.a-d-t-left {
+	width: 200px;
+	height: 100%;
+	display: flex;
+	align-items: center;
+	flex-direction: column;
+	justify-content: flex-start;
+	box-sizing: border-box;
+	padding-left: 5px;
+}
+
+.a-d-t-l-item {
+	/* width: auto;
+	height: 90%;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	padding: 0 10px;
+	border-radius: 10px;
+	background-color: #d4d9da;
+	margin-right: 3px;
+	cursor: pointer; */
+	cursor: pointer;
+	width: 136px;
+	height: 32px;
+	display: flex;
+	align-items: center;
+	border-radius: 5px;
+	font-family: PingFang SC;
+	box-sizing: border-box;
+	padding: 5px;
+	font-size: 14px;
+	font-weight: 600;
+	line-height: 22px;
+	text-align: left;
+	margin-bottom: 20px;
+}
+
+.a-d-t-l-item:hover {
+	background-color: white;
+}
+
+.a-d-t-right {
+	width: 40px;
+	height: 40px;
+	margin-right: 10px;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	color: black !important;
+}
+
+.a-d-t-right > span {
+	width: 25px;
+	height: 25px;
+	border-radius: 25px;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	/* align-items: center; */
+	font-size: 22px;
+	color: #fff;
+	/* background-color: #adadad; */
+	cursor: pointer;
+	/* background-color: #e6e6e6; */
+	color: #adadad;
+}
+
+.a-d-box {
+	width: 100%;
+	height: 100%;
+	/* height: calc(100% - 40px); */
+	background-color: #f0f2f5;
+	overflow: auto;
+
+	box-sizing: border-box;
+	padding: 15px;
+	padding-bottom: 50px;
+}
+
+.a-d-b-item {
+	width: 22%;
+	height: 200px;
+	display: flex;
+	flex-direction: column;
+	background-color: #fff;
+	border-radius: 10px;
+	padding: 15px;
+	float: left;
+	box-sizing: border-box;
+	margin-bottom: 10px;
+	/* position: relative; */
+}
+.a-d-b-item:hover .a-d-b-i-bottomBtn {
+	display: block !important;
+}
+.a-d-b-item:hover .a-d-b-i-bottomPer {
+	display: none !important;
+}
+.a-d-b-i-top {
+	width: 100%;
+	/* height: 50%; */
+	height: 20px;
+	margin-bottom: 15px;
+	display: flex;
+	align-items: center;
+	/* justify-content: space-between; */
+}
+.a-d-b-i-top > img {
+	width: 35px;
+	height: 35px;
+}
+/* .a-d-b-i-top>div{ */
+/* width: auto;
+	height: 35px;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	margin-left: 10px; */
+/* } */
+
+.a-d-b-i-t-title {
+	width: 100%;
+	height: 35px;
+	display: block;
+	align-items: center;
+	box-sizing: border-box;
+	padding: 0 10px;
+	text-overflow: ellipsis;
+	overflow: hidden;
+	word-break: break-all;
+	white-space: nowrap;
+	line-height: 35px;
+	/* display: -webkit-box;
+	-webkit-box-orient: vertical;
+	-webkit-line-clamp: 1;
+	overflow: hidden; */
+}
+
+.a-d-b-i-bottom {
+	width: 100%;
+	flex: 1;
+	overflow: hidden;
+	/* max-height: 186px; */
+	font-size: 14px;
+	-webkit-line-clamp: 5;
+	line-height: 20px;
+	display: -webkit-box;
+	-webkit-box-orient: vertical;
+	overflow: hidden;
+	text-overflow: ellipsis;
+}
+
+.a-d-b-i-t-btn {
+	font-size: 14px;
+	/* height: 30px; */
+	/* position: relative; */
+	/* top: 5px; */
+	box-sizing: border-box;
+	padding: 8px 25px;
+	/* background-color: #f3f3f3; */
+	border: 1px solid rgba(54, 129, 252, 1);
+	border-radius: 5px;
+	color: rgba(54, 129, 252, 1);
+
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	cursor: pointer;
+	/* position: absolute; */
+	/* right: 10px; */
+	/* top: 10px; */
+}
+.a-d-b-i-t-btn1 {
+	font-size: 14px;
+	box-sizing: border-box;
+	padding: 8px 25px;
+	border: 1px solid rgba(54, 129, 252, 1);
+	border-radius: 5px;
+	background-color: rgba(54, 129, 252, 1);
+	display: flex;
+	color: #fff;
+	justify-content: center;
+	align-items: center;
+	cursor: pointer;
+}
+.a_m_empty {
+	display: flex;
+	width: 100%;
+	justify-content: center;
+	font-size: 14px;
+	color: #555555;
+}
+</style>

+ 4 - 2
src/components/pages/classroomObservation/components/analysisItem.vue

@@ -25,7 +25,7 @@
 					</span>
 				</span>
 				<span
-					v-if="loadNum == 0 && !openItem"
+					v-if="loadNum == 0 && !openItem && tid"
 					class="ai-h-r-icon4"
 					@click.stop="delBtn()"
 				>
@@ -83,7 +83,7 @@
 					</el-tooltip>
 				</span>
 
-				<span v-if="loadNum != 1 && openItem" @click.stop="editBtn()">
+				<span v-if="loadNum != 1 && openItem && tid" @click.stop="editBtn()">
 					<el-tooltip
 						class="item"
 						effect="light"
@@ -364,6 +364,8 @@ export default {
 				type: "error",
 			}).then(() => {
 				this.$emit("delItem", this.data.id);
+			}).catch(_=>{
+				console.log("取消")
 			});
 		},
 		changeShowIndex(value) {

+ 258 - 0
src/components/pages/classroomObservation/components/analysisItem2.vue

@@ -0,0 +1,258 @@
+<template>
+	<div class="analysisItem">
+		<div class="ai-header" v-show="data.jsonData.name != '词频词汇分析'">
+			<div class="ai-h-left" @click.stop="changeOpenItem(!openItem)">
+				<span
+					:class="['ai-h-l-icon', openItem ? 'ai-h-l-iconActive' : '']"
+				></span>
+				<span class="ai-h-l-text">{{ data.jsonData.name }}</span>
+			</div>
+			<div class="ai-h-right" v-if="showAdd">
+				<span
+					class="ai-h-r-icon4"
+					@click.stop="delBtn()"
+				>
+					<el-tooltip
+						class="item"
+						effect="light"
+						content="删除"
+						placement="top"
+					>
+						<img
+							:src="
+								require('../../../../assets/icon/classroomObservation/del.svg')
+							"
+						/>
+					</el-tooltip>
+				</span>
+			</div>
+		</div>
+		<div class="ai-main" v-if="openItem">
+			<div class="a-m-brief">
+				{{ data.jsonData.result }}
+			</div>
+		</div>
+	</div>
+</template>
+
+<script>
+export default {
+	emits: ["delItem"],
+	props: {
+		data: {
+			type: Object,
+			default: () => {
+				return {};
+			},
+		},
+		index: {
+			type: Number,
+			default: 0,
+		},
+		showAdd:{
+			type:Boolean,
+			default:false
+		},
+	},
+	data() {
+		return {
+			openItem: false,
+			loading: false,
+			loadNum: 0,
+			userId:this.$route.query['userid'],
+			showIndex: 0,
+		};
+	},
+	computed: {
+
+	},
+	watch: {
+
+	},
+	methods: {
+		changeOpenItem(newValue) {
+			this.openItem = newValue;
+		},
+
+		delBtn() {
+			this.$confirm("确定删除?", "提示", {
+				confirmButtonText: "确定",
+				cancelButtonText: "取消",
+				type: "error",
+			}).then(() => {
+				this.$emit("delItem", this.index);
+			}).catch(_=>{
+				console.log("取消")
+			});
+		},
+
+	},
+	mounted() {
+	
+	},
+};
+</script>
+
+<style scoped>
+.analysisItem {
+	width: 100%;
+	height: auto;
+	margin: 11.7px 0px;
+	padding-right: 10px;
+	box-sizing: border-box;
+	border: solid 1px #F0F0F0;
+	border-radius: 3px;
+}
+.text1 {
+	color: rgba(54, 129, 252, 1);
+}
+.text2 {
+	color: rgba(23, 196, 105, 1);
+}
+.ai-header {
+	width: 100%;
+	height: 50px;
+	display: flex;
+	background-color: white;
+	border-radius: 5px;
+}
+.ai-h-left {
+	flex: 1;
+	height: 100%;
+	display: flex;
+	align-items: center;
+	box-sizing: border-box;
+	padding: 0 10px;
+	cursor: pointer;
+}
+
+.ai-h-l-icon {
+	width: 16px;
+	height: 16px;
+	background: url("../../../../assets/icon/classroomObservation/right.svg")
+		no-repeat;
+	background-size: 100% 100%;
+	margin-right: 10px;
+	transition: 0.3s;
+}
+
+.ai-h-l-iconActive {
+	transform: rotate(90deg);
+}
+.ai-h-l-text {
+	font-size: 18px;
+}
+
+.ai-h-right {
+	width: auto;
+	height: 100%;
+	display: flex;
+	align-items: center;
+	justify-content: space-around;
+	position: relative;
+}
+
+.ai-h-right > span {
+	width: 18px;
+	height: 18px;
+	background-size: 100% 100%;
+	margin: 0 10px;
+	cursor: pointer;
+}
+
+.ai-h-right > span > img {
+	width: 18px;
+	height: 18px;
+}
+
+.ai-h-r-icon1 {
+	background: url("../../../../assets/icon/classroomObservation/back.svg");
+	/* 镜像 */
+	transform: scaleX(-1);
+}
+
+.ai-h-r-icon2 {
+	background: url("../../../../assets/icon/classroomObservation/back.svg");
+}
+
+.ai_h_r_iconOpacity {
+	opacity: 0.5;
+	cursor: not-allowed !important;
+}
+
+.ai-h-r-icon3 {
+	background: url("../../../../assets/icon/classroomObservation/edit.svg");
+	/* display: none; */
+}
+
+.ai-header:hover .ai-h-r-icon4 {
+	display: block;
+}
+
+.ai-h-r-icon4 {
+	background: url("../../../../assets/icon/classroomObservation/del.svg");
+	/* position: absolute; */
+	/* right: -40px; */
+	display: none;
+}
+
+.analysisItem:hover .ai-h-r-icon4 {
+	display: block;
+}
+
+.ai-main {
+	width: 100%;
+	height: auto;
+	background-color: white;
+	border-radius: 0 0 5px 5px;
+	overflow: auto;
+	box-sizing: border-box;
+	padding: 10px 20px;
+}
+
+.a-m-brief {
+	font-size: 16px;
+	/* 斜体 */
+	font-style: italic;
+	margin-bottom: 10px;
+	color: #6b798e;
+}
+
+td,
+th {
+	padding: 10px;
+}
+
+.generate{
+	color: #00000099;
+	font-size: 16px;
+	display: flex;
+	align-items: center;
+}
+
+.generate>img{
+	margin-right: 5px;
+	width: 20px;
+	height: 20px;
+}
+
+.generateSuccess{ 
+	color: #17C469;
+	font-size: 16px;
+	display: flex;
+	align-items: center;
+}
+
+.generateSuccess>img{
+	margin-right: 5px;
+	width: 20px;
+	height: 20px;
+}
+
+.generateError{
+	color: #e60012;
+	font-size: 16px;
+	display: flex;
+	align-items: center;
+}
+</style>

+ 758 - 0
src/components/pages/classroomObservation/components/analysisSpecialItem.vue

@@ -0,0 +1,758 @@
+<template>
+	<div class="analysisItem">
+		<div class="ai-header" v-show="data.jsonData.name != '词频词汇分析'">
+			<div class="ai-h-left" @click.stop="changeOpenItem(!openItem)">
+				<span
+					:class="['ai-h-l-icon', openItem ? 'ai-h-l-iconActive' : '']"
+				></span>
+				<span class="ai-h-l-text">{{ data.jsonData.name }}</span>
+			</div>
+			<div class="ai-h-right">
+				<span style="width: 100px" class="generateError" v-if="loadNum == 2"
+					>优化失败
+				</span>
+				<span style="width: 100px" v-if="loadNum == 1">
+					<span v-if="loading" class="generate">
+						<img
+							:src="
+								require('../../../../assets/icon/classroomObservation/generate.svg')
+							"
+						/>
+						生成中...
+					</span>
+					<span v-else class="generateSuccess">
+						<img
+							:src="
+								require('../../../../assets/icon/classroomObservation/success.svg')
+							"
+						/>
+						生成完成
+					</span>
+				</span>
+				<span
+					v-if="loadNum == 0 && !openItem && tid"
+					class="ai-h-r-icon4"
+					@click.stop="delBtn()"
+				>
+					<el-tooltip
+						class="item"
+						effect="light"
+						content="删除"
+						placement="top"
+					>
+						<img
+							:src="
+								require('../../../../assets/icon/classroomObservation/del.svg')
+							"
+						/>
+					</el-tooltip>
+				</span>
+
+				<span
+					v-if="loadNum == 0 && openItem"
+					:class="['ai-h-r-icon1', showIndex <= 0 ? 'ai_h_r_iconOpacity' : '']"
+					@click.stop="changeShowIndex(-1)"
+				>
+					<el-tooltip
+						class="item"
+						effect="light"
+						content="上一个"
+						placement="top"
+					>
+						<img
+							:src="
+								require('../../../../assets/icon/classroomObservation/back.svg')
+							"
+						/>
+					</el-tooltip>
+				</span>
+
+				<span
+					v-if="loadNum != 1 && openItem"
+					:class="[
+						showIndex >= historyResult.length - 1 ? 'ai_h_r_iconOpacity' : '',
+					]"
+					@click.stop="changeShowIndex(1)"
+				>
+					<el-tooltip
+						class="item"
+						effect="light"
+						content="下一个"
+						placement="top"
+					>
+						<img
+							:src="
+								require('../../../../assets/icon/classroomObservation/back.svg')
+							"
+						/>
+					</el-tooltip>
+				</span>
+
+				<span
+					v-if="loadNum != 1 && openItem && tid"
+					@click.stop="editBtn(true)"
+				>
+					<el-tooltip
+						class="item"
+						effect="light"
+						content="优化"
+						placement="top"
+					>
+						<img
+							:src="
+								require('../../../../assets/icon/classroomObservation/edit.svg')
+							"
+						/>
+					</el-tooltip>
+				</span>
+
+				<!-- <span class="ai-h-r-icon4" @click.stop="delBtn()"></span> -->
+			</div>
+		</div>
+		<div class="ai-main" v-if="openItem">
+			<div class="a-m-brief" v-if="showBrief">
+				{{ data.jsonData.result }}
+			</div>
+			<!-- 图 -->
+			<eChartTemplate
+				style="width: 100%; height: 400px"
+				:data="data.jsonData.eChartData"
+				v-if="data.jsonData.eChartData"
+			/>
+			<div class="rtCh" v-if="data.jsonData.RT && data.jsonData.CH">
+				<img :src="require('../../../../assets/icon/classroomObservation/rt-ch.png')">
+				<div>
+					<span>RT={{ data.jsonData.RT }}</span>
+					<span>CH={{ data.jsonData.CH }}</span>
+				</div>
+			</div>
+			<mdView :text="data.jsonData.content" />
+		</div>
+	</div>
+</template>
+
+<script>
+import mdView from "./mdView.vue";
+import eChartTemplate from "./eChartTemplate";
+import { v4 as uuidv4 } from "uuid";
+export default {
+	emits: ["delItem", "editItem", "saveItem"],
+	components: {
+		mdView,
+		eChartTemplate,
+	},
+	props: {
+		data: {
+			type: Object,
+			default: () => {
+				return {};
+			},
+		},
+		bmData: {
+			type: Object,
+			default: () => {
+				return {};
+			},
+		},
+		dialogTagDataList: {
+			type: Array,
+			default: () => {
+				return [];
+			},
+		},
+		index: {
+			type: Number,
+			default: 0,
+		},
+		tid: {
+			type: String,
+			require: true,
+		},
+		fileId: {
+			type: String,
+			require: true,
+		},
+		showBrief: {
+			type: Boolean,
+			default: true,
+		},
+	},
+	data() {
+		return {
+			openItem: false,
+			loading: false,
+			loadNum: 0,
+			userId: this.$route.query["userid"],
+			showIndex: 0,
+			historyResult: [],
+			tableData: [],
+			imgTypeList: [
+				"png",
+				"jpg",
+				"jpeg",
+				"bmp",
+				"gif",
+				"webp",
+				"psd",
+				"svg",
+				"tiff",
+			],
+			oldData: {},
+		};
+	},
+	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;
+		},
+		editBtn(flag = false) {
+			if (!flag) return console.log("不执行获取");
+			this.loadNum = 1;
+			this.getData();
+
+			// this.ajax
+			// 	.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;
+			// 			this.loadNum = 2;
+			// 			return this.$message.error("AI无法识别优化");
+			// 		}
+			// 		let _copyData = JSON.parse(JSON.stringify(this.data));
+			// 		// _copyData.jsonData.result = "";
+			// 		_copyData.jsonData.content = _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.loadNum = 2;
+			// 		this.$message.error("AI无法识别优化");
+			// 		this.loading = false;
+			// 	});
+		},
+		getAtAuContent(_uid, _text, _headUrl, _assistantName) {
+			let _source = new EventSource(
+				`https://gpt4.cocorobo.cn/question/${_uid}`
+			); //http://gpt4.cocorobo.cn:8011/question/   https://gpt4.cocorobo.cn/question/
+			let _allText = "";
+			let _mdText = "";
+			let _copyData = JSON.parse(JSON.stringify(this.data));
+			// _copyData.jsonData.result = "";
+			_copyData.jsonData.content = "";
+			_copyData.jsonData.dataFileList = [];
+			_copyData.jsonData.fileList = [];
+			if (this.historyResult.length == 0) {
+				this.historyResult.push(_copyData.jsonData);
+			} else {
+				this.historyResult.splice(this.showIndex + 1, 0, _copyData.jsonData);
+			}
+			this.showIndex++;
+			this.$emit("editItem", this.data.id, _copyData);
+			// const md = new MarkdownIt();
+			_source.onmessage = (_e) => {
+				let _eData = JSON.parse(_e.data);
+				if (_eData.content.replace("'", "").replace("'", "") == "[DONE]") {
+					let _result = [];
+					if ("result" in _eData) {
+						_result = _eData.result;
+						for (let i = 0; i < _result.length; i++) {
+							_mdText = _mdText.replace(_result[i].text, _result[i].fileName);
+						}
+					}
+					_mdText = _mdText.replace("_", "");
+					_copyData.jsonData.content = _mdText;
+					this.loading = false;
+					this.loadNum = 0;
+					this.$emit("editItem", this.data.id, _copyData);
+					this.$emit("saveItem", this.data.id, _copyData);
+					_source.close();
+				} else {
+					let _text = _eData.content.replace("'", "").replace("'", "");
+					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);
+					_copyData.jsonData.content = _mdText;
+					this.$emit("editItem", this.data.id, _copyData);
+					// 处理流数据
+				}
+			};
+		},
+		getData() {
+			if (this.bmData.editorBarData.type != 0) {
+				return this.$message.info("请上传表格形式的转录文稿");
+			}
+			try {
+				let _result = [];
+				let _data = this.bmData.editorBarData.content;
+				let _div = document.createElement("div");
+				_div.innerHTML = _data;
+				let _tableRows = _div.querySelectorAll(`table tbody tr`);
+				_tableRows.forEach((i, index) => {
+					if (index == 0) return;
+					let obj = {
+						index: i.cells[0].textContent,
+						startTime: i.cells[1].textContent,
+						endTime: i.cells[2].textContent,
+						message: i.cells[3].textContent,
+						time: i.cells[4].textContent,
+						role: i.cells[5].textContent,
+						behavior: i.cells[6].textContent,
+					};
+					_result.push(obj);
+				});
+				if (_result.length == 0) return this.$message.error("未找到表格数据");
+				if (this.data.jsonData.name == "S-T分析:课堂时间分配") {
+					this.getTimeAllocationData(_result);
+				} else if (this.data.jsonData.name == "S-T分析:师生互动分析") {
+					this.getInteractionAnalysisData(_result);
+				} else if (this.data.jsonData.name == "S-T分析:教学模式分析") {
+					this.getTeachingModeData(_result);
+				} else {
+					return this.$message.error("未找到对应的分析");
+				}
+			} catch (error) {
+				console.log(error);
+				this.loadNum = 2;
+				this.loading = false;
+				return this.$message.error("生成分析失败");
+			}
+		},
+		// 课堂时间分配
+		getTimeAllocationData(_dataList) {
+			this.loading = true;
+			this.openItem = false;
+			let _data = _dataList.reduce((pre,cur)=>{
+				if(cur.role == '学生'){
+					pre[1].value += this.convertToSeconds(cur.time)
+				}else if(cur.role=='老师'){
+					pre[0].value += this.convertToSeconds(cur.time)
+				}
+				return pre;
+			},[
+				{value:0,name:"老师"},
+				{value:0,name:'学生'}
+			])
+			const _option = {
+				tooltip: {
+					trigger: "item",
+				},
+				legend: {
+					top: "5%",
+					left: "center",
+				},
+				series: [
+					{
+						name: "课堂时间分配",
+						type: "pie",
+						radius: ["40%", "70%"],
+						avoidLabelOverlap: false,
+						label: {
+							show: false,
+							position: "center",
+						},
+						emphasis: {
+							label: {
+								show: true,
+								fontSize: 40,
+								fontWeight: "bold",
+							},
+						},
+						labelLine: {
+							show: false,
+						},
+						data: _data
+					},
+				],
+			};
+			let _copyData = JSON.parse(JSON.stringify(this.data));
+			_copyData.jsonData.eChartData = _option;
+			_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;
+		},
+		// 师生互动分析
+		getInteractionAnalysisData(_dataList) {
+			this.loading = true;
+			this.openItem = false;
+			let _pushData = [0,0]
+			let _result = []
+			_dataList.forEach(i=>{
+				if(i.role=='老师'){
+					_pushData[0] += this.convertToSeconds(i.time)
+				}else if(i.role=='学生'){
+					_pushData[1] += this.convertToSeconds(i.time)
+				}
+				return _result.push(JSON.parse(JSON.stringify(_pushData)))
+			})
+			const _option = {
+				xAxis: {
+					name: "老师", // X轴标题
+					nameLocation: "end", // 标题位置
+				},
+				yAxis: {
+					name: "学生", // Y轴标题
+					nameLocation: "end", // 标题位置
+				},
+				series: [
+					{
+						data: _result,
+						type: "line",
+					},
+				],
+			};
+
+			let _copyData = JSON.parse(JSON.stringify(this.data));
+			_copyData.jsonData.eChartData = _option;
+			_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;
+
+		},
+		// 教学模式分析
+		getTeachingModeData(_dataList) {
+			this.openItem = false;
+			this.loading = true
+			let _continuousTime = 0;
+			let _totalTime = 0;
+			let _continuousRole = "老师"
+			let _teacherTime = 0;
+			_dataList.forEach((item,index)=>{
+				if(index==0){//第一个
+					_continuousRole = item.role
+				}else if(_dataList.length-1==index){//最后一个
+					if(_continuousRole==item.role){//连续对话了
+						_continuousTime += this.convertToSeconds(_dataList[index-1].time)
+						_continuousTime += this.convertToSeconds(item.time)
+					}else{//没连续对话
+						if(index>=2){
+							if(_dataList[index-2].role==_dataList[index-1].role){
+								_continuousTime += this.convertToSeconds(_dataList[index-1].time)
+							}else{
+								_continuousRole = item.role;
+							}
+						}else{
+							_continuousRole = item.role;
+						}
+					}
+				}else{
+					if(_continuousRole==item.role){//连续对话了
+						_continuousTime += this.convertToSeconds(_dataList[index-1].time)
+					}else{//没连续对话
+						if(index>=2){
+							if(_dataList[index-2].role==_dataList[index-1].role){
+								_continuousTime += this.convertToSeconds(_dataList[index-1].time)
+							}else{
+								_continuousRole = item.role;
+							}
+						}else{
+							_continuousRole = item.role;
+						}
+					}
+				}
+
+				if(item.role == "老师"){
+					_teacherTime+=this.convertToSeconds(item.time);
+				}
+
+				_totalTime += this.convertToSeconds(item.time);
+			})
+
+			let _RT = (_teacherTime/_totalTime).toFixed(2)
+			let _CH = (_continuousTime/_totalTime).toFixed(2)
+			let _copyData = JSON.parse(JSON.stringify(this.data));
+			_copyData.jsonData.RT = _RT;
+			_copyData.jsonData.CH = _CH;
+			_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;
+		},
+		delBtn() {
+			this.$confirm("确定删除?", "提示", {
+				confirmButtonText: "确定",
+				cancelButtonText: "取消",
+				type: "error",
+			})
+				.then(() => {
+					this.$emit("delItem", this.data.id);
+				})
+				.catch((_) => {
+					console.log("取消");
+				});
+		},
+		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.data = _copyData;
+			this.$emit("editItem", this.data.id, _copyData);
+			this.$emit("saveItem", this.data.id, _copyData);
+		},
+		convertToSeconds(time) {
+		  let parts = time.split(':');
+		  let seconds = (+parts[0]) * 3600 + (+parts[1]) * 60 + (+parts[2]);
+		  return seconds;
+		}
+	},
+	mounted() {
+		if (this.data.jsonData.content) {
+			this.historyResult.push(this.data.jsonData);
+		}
+	},
+};
+</script>
+
+<style scoped>
+.analysisItem {
+	width: 100%;
+	height: auto;
+
+	margin: 11.7px 0px;
+
+	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;
+	display: flex;
+	background-color: white;
+	border-radius: 5px;
+}
+.ai-h-left {
+	flex: 1;
+	height: 100%;
+	display: flex;
+	align-items: center;
+	box-sizing: border-box;
+	padding: 0 10px;
+	cursor: pointer;
+}
+
+.ai-h-l-icon {
+	width: 16px;
+	height: 16px;
+	background: url("../../../../assets/icon/classroomObservation/right.svg")
+		no-repeat;
+	background-size: 100% 100%;
+	margin-right: 10px;
+	transition: 0.3s;
+}
+
+.ai-h-l-iconActive {
+	transform: rotate(90deg);
+}
+.ai-h-l-text {
+	font-size: 18px;
+}
+
+.ai-h-right {
+	width: auto;
+	height: 100%;
+	display: flex;
+	align-items: center;
+	justify-content: space-around;
+	position: relative;
+}
+
+.ai-h-right > span {
+	width: 18px;
+	height: 18px;
+	background-size: 100% 100%;
+	margin: 0 10px;
+	cursor: pointer;
+}
+
+.ai-h-right > span > img {
+	width: 18px;
+	height: 18px;
+}
+
+.ai-h-r-icon1 {
+	background: url("../../../../assets/icon/classroomObservation/back.svg");
+	/* 镜像 */
+	transform: scaleX(-1);
+}
+
+.ai-h-r-icon2 {
+	background: url("../../../../assets/icon/classroomObservation/back.svg");
+}
+
+.ai_h_r_iconOpacity {
+	opacity: 0.5;
+	cursor: not-allowed !important;
+}
+
+.ai-h-r-icon3 {
+	background: url("../../../../assets/icon/classroomObservation/edit.svg");
+	/* display: none; */
+}
+
+.ai-header:hover .ai-h-r-icon4 {
+	display: block;
+}
+
+.ai-h-r-icon4 {
+	background: url("../../../../assets/icon/classroomObservation/del.svg");
+	/* position: absolute; */
+	/* right: -40px; */
+	display: none;
+}
+
+.analysisItem:hover .ai-h-r-icon4 {
+	display: block;
+}
+
+.ai-main {
+	width: 100%;
+	height: auto;
+	background-color: white;
+	border-radius: 0 0 5px 5px;
+	overflow: auto;
+	box-sizing: border-box;
+	padding: 10px 20px;
+}
+
+.a-m-brief {
+	font-size: 16px;
+	/* 斜体 */
+	font-style: italic;
+	margin-bottom: 10px;
+	color: #6b798e;
+}
+
+td,
+th {
+	padding: 10px;
+}
+
+.generate {
+	color: #00000099;
+	font-size: 16px;
+	display: flex;
+	align-items: center;
+}
+
+.generate > img {
+	margin-right: 5px;
+	width: 20px;
+	height: 20px;
+}
+
+.generateSuccess {
+	color: #17c469;
+	font-size: 16px;
+	display: flex;
+	align-items: center;
+}
+
+.generateSuccess > img {
+	margin-right: 5px;
+	width: 20px;
+	height: 20px;
+}
+
+.generateError {
+	color: #e60012;
+	font-size: 16px;
+	display: flex;
+	align-items: center;
+}
+
+.rtCh{
+	width: 100%;
+	height: 300px;
+	display: flex;
+	flex-direction: column;
+	align-items: center;
+	justify-content: center;
+}
+
+.rtCh>img{
+	max-height: 250px;
+}
+
+.rtCh>div{
+	margin-top: 20px;
+}
+
+.rtCh>div>span{
+	margin: 0 10px;
+	font-size: 20px;
+	font-weight: bold;
+	color: #1A7AD3;
+	/* 斜体字 */
+	font-style: italic;
+}
+</style>

Dosya farkı çok büyük olduğundan ihmal edildi
+ 47 - 0
src/components/pages/classroomObservation/components/analysisTemplateDialog.vue


+ 343 - 23
src/components/pages/classroomObservation/components/baseMessage.vue

@@ -7,11 +7,11 @@
 		<div class="m-main" v-show="showMain">
 			<div class="m-m-form">
 				<div class="m-m-formItem" style="width: clamp(50%, 50%, 50%)">
-					<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.courseName"
-							placeholder="请输入课名称"
+							placeholder="请输入课名称"
 							@change="changeData()"
 						></el-input>
 					</div>
@@ -125,7 +125,7 @@
 										fit="cover"
 										style="width: 100%;"
 									></el-image>
-									<span @click.stop="delImage(key)">x</span>
+									<span @click.stop="delImage(key)"></span>
 									<!-- <img class="itemUrl" :src="value[0].url" alt="" /> -->
 								</div>
 								<!-- 图片区域 -->
@@ -133,7 +133,7 @@
 							<div
 								class="m-m-fi-imageItem"
 								@click.stop="addImage()"
-								style="max-width:32%;"
+								style="max-width:60%;"
 								v-if="
 									imageList.fileList1 &&
 									imageList.fileList1.length +
@@ -170,8 +170,8 @@
 					<div class="m-m-formImage" v-loading="uploadVideoLoading">
 								<div
 									class="m-m-fi-imageItem"
-									style="max-width:33%;"
-									v-if="imageList.videoList.length"
+									style="max-width:60%;"
+									v-if="!imageList.videoList.length==0"
 									v-for="(item, index) in imageList.videoList?imageList.videoList:[]"
 									:key="index"
 									@click.stop="previewVideo(item.url)"
@@ -182,13 +182,13 @@
 										:src="require('../../../../assets/icon/classroomObservation/isVideo.png')"
 										fit="cover"
 									></el-image>
-									<span @click.stop="delVideo('videoList')">x</span>
+									<span @click.stop="delVideo('videoList')"></span>
 								</div>
-							<el-progress v-if="progressData.uploadVideo && !imageList.videoList.length" class="m_m_fi_progress" :percentage="progressData.value"></el-progress>
+							<!-- <el-progress v-if="progressData.uploadVideo && !imageList.videoList.length" class="m_m_fi_progress" :percentage="progressData.value"></el-progress> -->
 							<div
 								class="m-m-fi-imageItem"
 								@click.stop="addVideo()"
-								style="max-width:33%;"
+								style="max-width:60%;"
 								v-if="(((imageList.videoList&&imageList.videoList.length<=0) || !imageList.videoList) && !progressData.uploadVideo)"
 							>
 								<img
@@ -206,10 +206,73 @@
 									点击上传视频
 								</div>
 							</div>
+
+							<div
+								class="m-m-fi-imageItem"
+								style="max-width:60%;border-radius: 8px;overflow: hidden;"
+								v-if="progressData.uploadVideo && !imageList.videoList.length""
+							>
+							<el-image
+								class="itemUrl"
+								:src="require('../../../../assets/icon/classroomObservation/videoFile.svg')"
+								fit="cover"
+							></el-image>
+							<div class="m_m_fi_progress">
+									<div>{{ progressData.value }}%</div>
+									<span>上传中...</span>
+									<div class="m_m_fi_p_bar">
+										<div :style="{width:progressData.value+'%'}"></div>
+									</div>
+							</div>
+						</div>
 						<!-- <div class="m-m-fi-btn" >添加课堂图片</div> -->
 					</div>
 				</div>
+				<!-- <div class="nephogramArea"> -->
+				<div class="fl_nephogram">
+					<div class="imgTit">
+						<span>词云图</span>
+						<span></span>
+					</div>
+					<div class="m-m-formImage">
+								<div
+									class="m-m-fi-nephogramItem"
+									style="width:100%;"
+									 v-loading="uploadNephogramLoading"
+									v-if="(imageList.NephogramList&&imageList.NephogramList.length>0)"
+								>
+									<wordcloudEChart :data="imageList.NephogramList[0]"/>
+									<span @click.stop="delNephogram('NephogramList')"></span>
+								</div>
+							<div
+								class="m-m-fi-nephogramItem"
+								 v-loading="uploadNephogramLoading"
+								@click.stop="addNephogram()"
+								style="width:60%;max-height: 100px;"
+								v-if="((imageList.NephogramList&&imageList.NephogramList.length<=0) || !imageList.NephogramList)"
+							>
+								<img
+									:src="require('../../../../assets/icon/classroomObservation/bmRefresh.png')"
+									alt=""
+									style="width:20px"
+								/>
+								<div
+									style="
+										font-size: 12px;
+										font-weight: 400;
+										margin-top: 5px;
+										color: rgba(0, 0, 0, 0.4);
+									"
+								>
+									生成词云图
+								</div>
+							</div>
+					</div>
+				<!-- </div> -->
+			</div>
+				
 			</div>
+			
 		</div>
 		<previewVideoDialog ref="previewVideoDialogRef"/>
 	</div>
@@ -217,10 +280,13 @@
 
 <script>
 import previewVideoDialog from './previewVideoDialog.vue';
+import wordcloudEChart from './wordcloudEChart.vue'
+import { v4 as uuidv4 } from "uuid";
 export default {
-	emits: ["saveData", "saveImage", "saveVideo","delImage"],
+	emits: ["saveData", "saveImage", "saveVideo","delImage","saveNephogram"],
 	components:{
-		previewVideoDialog
+		previewVideoDialog,
+		wordcloudEChart
 	},
 	props: {
 		data: {
@@ -229,6 +295,10 @@ export default {
 				return {};
 			},
 		},
+		tid:{
+			type:String,
+			default:"",
+		},
 		imageList: {
 			type: Object,
 			default: () => {
@@ -241,13 +311,19 @@ export default {
 				};
 			},
 		},
+		dataList:{
+			type:Array,
+			default:()=>[]
+		}
 	},
 	data() {
 		return {
 			title: "基本信息",
+			chartObj:null,
 			showMain: true,
 			uploadImageLoading: false,
 			uploadVideoLoading:false,
+			uploadNephogramLoading:false,
 			from: {
 				courseName: "",
 				teacherName: "",
@@ -289,9 +365,15 @@ export default {
 			}
 		};
 	},
+	watch:{
+		imageList(){
+			this.$forceUpdate();
+		}
+	},
 	methods: {
 		// 添加图片
 		addImage() {
+			if(!this.tid)return this.$message.error("请选择课堂")
 			// 上传录音
 			let input = document.createElement("input");
 			input.type = "file";
@@ -359,6 +441,7 @@ export default {
 		},
 		// 添加视频
 		addVideo(){
+			if(!this.tid)return this.$message.error("请选择课堂")
 			let input = document.createElement("input");
 			input.type = "file";
 			input.accept = "video/*";
@@ -420,6 +503,121 @@ export default {
 				}
 			};
 		},
+		//添加云图
+		addNephogram(){
+			if(!this.tid)return this.$message.error("请选择课堂")
+			if(this.uploadNephogramLoading)return this.$message.info("请稍等");
+			this.uploadNephogramLoading = true;
+			const _msg = `NOTICE
+Language: Please use the same language as the user requirement, if the user speaks Chinese, the specific text of your answer should also be in Chinese.
+ATTENTION: Use '##' to SPLIT SECTIONS, not '#'. Output format carefully referenced "Format example".
+Instruction: Based on the context, follow "Format example", write content.
+
+## 任务
+
+请基于以下课堂实录文本(大约5000字),提炼出20-30个关键词,用于绘制词云图。请给出相应的关键词,关键词出现的频次,词云图上的大小。请确保输出的关键字准确反映课堂实录的主要内容和主题。
+
+## 要求
+
+1. **提取关键词**:从提供的课堂实录文本中提取出20-30个最具代表性的关键字。关键词应该涵盖课堂实录中的主要概念、重要术语和核心主题。尽量选择多样化的关键词,避免过于集中在某一个主题或概念上。
+2. **词频统计**:计算每个关键字在文本中出现的频率。
+3. **词汇大小**:根据词频数量,确定每个关键字在词云图中的大小。词频越高,词汇大小数值越大,数值范围1-100。
+4. **输出格式**:输出结果应包含每个关键字、对应的词频数量以及词汇大小数值。
+
+## 输出格式
+
+### 输出格式
+
+[
+	{"value":1,"name":"氯化钠","textStyle":{"color":"#ee7959"}},
+	{"value":2,"name":"溶液","textStyle":{"color":"#db9b34"}},
+	{"value":1,"name":"实验","textStyle":{"color":"#9d9d82"}},
+	{"value":3,"name":"质量分数","textStyle":{"color":"#ea5514"}},
+	{"value":1,"name":"溶质","textStyle":{"color":"#c8161d"}},
+	{"value":2,"name":"氢氧化钠","textStyle":{"color":"#e60012"}},
+	{"value":1,"name":"溶解度","textStyle":{"color":"#1e2732"}},
+	{"value":4,"name":"饱和溶液","textStyle":{"color":"#e3adb9"}}
+]
+
+请仅仅输出表头,输出关键词和相应的内容,无需其它任何说明文字。
+冒号、逗号等符号均使用英文字符。
+
+### 输出示例
+
+[
+	{"value":1,"name":"氯化钠","textStyle":{"color":"#ee7959"}},
+	{"value":2,"name":"溶液","textStyle":{"color":"#db9b34"}},
+	{"value":1,"name":"实验","textStyle":{"color":"#9d9d82"}},
+	{"value":3,"name":"质量分数","textStyle":{"color":"#ea5514"}},
+	{"value":1,"name":"溶质","textStyle":{"color":"#c8161d"}},
+	{"value":2,"name":"氢氧化钠","textStyle":{"color":"#e60012"}},
+	{"value":1,"name":"溶解度","textStyle":{"color":"#1e2732"}},
+	{"value":4,"name":"饱和溶液","textStyle":{"color":"#e3adb9"}}
+]
+
+## 课堂实录 
+${this.data.editorBarData.content}
+`;
+				const _uuid = uuidv4();
+				let params = {
+					model: "gpt-3.5-turbo",
+					temperature: 0,
+					max_tokens: 4096,
+					top_p: 1,
+					frequency_penalty: 0,
+					presence_penalty: 0,
+					messages: [{ role: "user", content: _msg }],
+					uid: _uuid,
+					mind_map_question: "",
+					stream: false,
+				};
+				this.ajax
+					.post("https://gpt4.cocorobo.cn/chat", params)
+					.then((res) => {
+						let _data = res.data.FunctionResponse.choices[0];
+						let _jsonData = _data.message.content;
+						_jsonData = _jsonData.replaceAll("```json", "").replaceAll("```", "");
+						let _result = JSON.parse(_jsonData);
+						console.log(_jsonData)
+						this.$emit('saveNephogram',{
+    tooltip: {
+      show: false,
+    },
+    series: [
+      {
+        type: 'wordCloud',
+        sizeRange: [14, 38],
+        rotationRange: [0, 0],
+				keepAspect:false,
+				shape: 'circle',
+        left: 'center',
+        top: 'center',
+        right: null,
+        bottom: null,
+        width: '90%',
+        height: '90%',
+        // maskImage: maskImage,
+				// sizeRange: [12, 60],
+				rotationRange: [-90, 90],
+        rotationStep: 45,
+        // gridSize: 12,
+        // autoSize: {
+        //   enable: true,
+        //   minSize: 12,
+        // },
+        data: _result,
+      },
+    ],
+  })
+					})
+					.catch((e) => {
+						console.log(e);
+						this.$message.error("生成词云图失败");
+					})
+					.finally((_) => {
+						this.uploadNephogramLoading = false;
+					});
+		},
 
 		// 删除图片
 		delImage(key) {
@@ -439,6 +637,20 @@ export default {
 				type: "warning",
 			}).then(() => {
 				this.$emit("delImage", key);
+			}).catch(e=>{
+				console.log("取消删除")
+			});
+		},
+		//删除词云图
+		delNephogram(key){
+			this.$confirm("确定删除该词云图吗?", "提示", {
+				confirmButtonText: "确定",
+				cancelButtonText: "取消",
+				type: "warning",
+			}).then(() => {
+				this.$emit("delImage", key);
+			}).catch(e=>{
+				console.log("取消删除")
 			});
 		},
 		changeShowMain(newValue) {
@@ -452,10 +664,13 @@ export default {
 			// this.$message.info(`预览:${url}`)
 		},
 		changeData() {
+			if(!this.tid)return this.$message.error("请选择课堂")
 			this.$emit("saveData");
 		},
 	},
-	mounted() {},
+	mounted() {
+		// this.showNephogram();
+	},
 };
 </script>
 
@@ -603,6 +818,7 @@ export default {
 	background-color: rgba(238, 238, 238, 1);
 	width: 140px;
 	height: 100px;
+	min-width: 110px !important;
 	margin-right: 1%;
 	display: flex;
 	justify-content: center;
@@ -620,21 +836,27 @@ export default {
 }
 
 .m-m-fi-imageItem > span {
-	width: 30px;
-	height: 30px;
+	width: 20px;
+	height: 20px;
 	position: absolute;
-	right: 0;
-	top: 0;
-	display: flex;
+	right: 4px;
+	top: 4px;
+	background-image: url("../../../../assets/icon/classroomObservation/delFile.svg");
+	background-repeat: no-repeat;
+	background-size: 100% 100%;
+	display: none;
+	z-index: 9999;
+	/* display: flex;
 	justify-content: flex-end;
 	align-items: flex-start;
 	box-sizing: border-box;
 	padding: 2px 10px;
-	color: white;
-	background-color: #e60012;
+	color: #666666;
+	font-size: 18px;
+	background-color: #FFBBBB;
 	cursor: pointer;
-	border-radius: 0 0 0 100%;
-	display: none;
+	border-radius: 100%;
+	display: none; */
 }
 
 .m-m-fi-imageItem:hover > span {
@@ -677,12 +899,110 @@ export default {
 }
 
 .fl_video{
-	width: 48.5%;
-	margin-left: 1.5%;
+	width: 21.8%;
+	margin-left: 1.6%;
+	height: auto;
+
+}
+
+.nephogramArea{
+	width: 20%;
+	height: auto;
+}
+
+.fl_nephogram{
+	width: 20%;
+	/* margin-left: 1.5%; */
 	height: auto;
+	margin-left: 1%;
+	/* margin-top: -2%; */
 }
 
+
 .m_m_fi_progress{
 	width: 100%;
+	height: 100%;
+	position: absolute;
+	display: flex;
+	flex-direction: column;
+	justify-content: center;
+	align-items: center;
+	/* 加载 */
+	cursor:wait !important;
+	background-color: #00000099;
+}
+
+.m_m_fi_progress>div:nth-child(1){
+	font-size: 20px;
+	color: white;
+}
+
+.m_m_fi_progress>span:nth-child(2){
+	font-size: 16px;
+	color: #FFFFFF8C;
+}
+
+.m_m_fi_p_bar{
+	width: 100%;
+	height: 5px;
+	position: absolute;
+	bottom: 0;
+	background-color: #D8E3F7;
+}
+
+.m_m_fi_p_bar>div{
+	background-color: #3975CE;
+	max-width: 100%;
+	height: 100%;
+}
+
+.m-m-fi-nephogramItem{
+	width: 140px;
+	height: 100px;
+	background-color: rgba(238, 238, 238, 1);
+	min-width: 140px;
+	min-height: 100px;
+	margin-right: 1%;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	flex-direction: column;
+	box-sizing: border-box;
+	font-size: 14px;
+	cursor: pointer;
+	position: relative;
+	margin-bottom: 10px;
+}
+.m-m-fi-nephogramItem> .itemUrl {
+	width: 100%;
+	height: 100%;
+}
+
+.m-m-fi-nephogramItem > span {
+	width: 20px;
+	height: 20px;
+	position: absolute;
+	right: 4px;
+	top: 4px;
+	background-image: url("../../../../assets/icon/classroomObservation/delFile.svg");
+	background-repeat: no-repeat;
+	background-size: 100% 100%;
+	display: none;
+	z-index: 99999;
+	/* display: flex;
+	justify-content: flex-end;
+	align-items: flex-start;
+	box-sizing: border-box;
+	padding: 2px 10px;
+	color: #666666;
+	font-size: 18px;
+	background-color: #FFBBBB;
+	cursor: pointer;
+	border-radius: 100%;
+	display: none; */
+}
+
+.m-m-fi-nephogramItem:hover > span {
+	display: flex;
 }
 </style>

+ 4 - 3
src/components/pages/classroomObservation/components/bindingFormDialog.vue

@@ -32,8 +32,8 @@
 					<span @click.stop="dialogVisible = false">×</span>
 				</div>
 			</div>
-			<div class="bfd_box" v-loading="loading">
-				<el-table :data="list" border>
+			<div class="bfd_box">
+				<el-table :data="list" border  v-loading="loading">
 					<el-table-column
 						prop="title"
 						label="标题"
@@ -82,6 +82,7 @@
 						@current-change="currentChange"
 						:page-size="pageData.pageSize"
 						:total="pageData.total"
+						:disabled="loading"
 					>
 					</el-pagination>
 				</div>
@@ -201,7 +202,7 @@ export default {
 				pageSize: this.pageData.pageSize,
 			};
 			this.ajax
-				.get(this.$store.state.api + "selectTesttCourse", params)
+				.get(this.$store.state.api + "selectTesttCourse3", params) //selectTesttCourse
 				.then((res) => {
 					let _data = res.data[0];
 					this.pageData.total = 0

+ 79 - 0
src/components/pages/classroomObservation/components/changeCourseNameDialog.vue

@@ -0,0 +1,79 @@
+<template>
+	<div class="changeCourseNameDialog">
+		<el-dialog title="修改课堂名称" :close-on-click-modal="false" :visible.sync="dialogVisible" width="500px" >
+			<div>
+				<el-form ref="form" :model="form" :rules="rules" label-position="top">
+					<!-- <el-form-item label="课堂编号" prop="no">
+						<el-input v-model="form.no" placeholder="请输入课堂编号,支持英文和数数字结合"></el-input>
+					</el-form-item> -->
+					<el-form-item label="课堂名称" prop="name">
+						<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('form')">确 定</el-button>
+			</span>
+		</el-dialog>
+	</div>
+</template>
+
+<script>
+export default {
+	emits: ["success"],
+	props: {
+
+	},
+	data() {
+		let validateName = (rule, value, callback) => {
+			if (value.trim().length == 0) {
+				callback(new Error("请输入课堂名称"));
+			} else {
+				callback();
+			}
+		};
+		return {
+			dialogVisible: false,
+			loading:true,
+			form: {
+				id:"",
+				name: "",
+				tid:"",
+			},
+			rules: {
+				name: [{ validator: validateName, trigger: "change" }],
+			},
+		};
+	},
+	methods: {
+		open(item) {
+			this.form = {
+				id:item.id,
+				tid:item.value,
+				name: item.label,
+			};
+			this.dialogVisible = true;
+		},
+		submit(formName) {
+			this.$refs[formName].validate((valid) => {
+				if (valid) {
+					this.$emit("success", this.form);
+					this.dialogVisible = false;
+				} else {
+					console.log("error submit!!");
+					return false;
+				}
+			});
+		},
+	},
+};
+</script>
+
+<style scoped>
+.addNewCourse {
+}
+</style>

Dosya farkı çok büyük olduğundan ihmal edildi
+ 483 - 234
src/components/pages/classroomObservation/components/chatArea.vue


+ 46 - 0
src/components/pages/classroomObservation/components/eChartTemplate.vue

@@ -0,0 +1,46 @@
+<template>
+	<div class="chart" id="charts_canvas" ref="chartRef"></div>
+</template>
+
+<script>
+import * as echarts from 'echarts';
+export default {
+	props: {
+		data: {
+			type: Object,
+			default: () => {},
+		},
+	},
+	data() {
+		return {
+			chartObj: null,
+			chartData: null,
+		};
+	},
+	watch: {
+		data() {
+			this.getChartData();
+		},
+	},
+	methods: {
+		getChartData() {
+			this.chartObj = echarts.init(this.$refs.chartRef);
+			this.chartObj.setOption(this.data);
+			window.addEventListener("resize", () => {
+					this.chartObj.resize();
+      });
+		},
+	},
+	mounted() {
+		this.getChartData();
+	},
+};
+</script>
+
+<style scoped>
+.chart {
+	max-width: 100%;
+	width: 100%;
+	height: 100%;
+}
+</style>

Dosya farkı çok büyük olduğundan ihmal edildi
+ 46 - 26
src/components/pages/classroomObservation/components/messageArea.vue


+ 280 - 0
src/components/pages/classroomObservation/components/saveTemplateDialog.vue

@@ -0,0 +1,280 @@
+<template>
+	<div>
+		<el-dialog
+			:center="true"
+			:visible.sync="dialogVisible"
+			:close-on-click-modal="false"
+			width="500px"
+			class="bindingFormDialog"
+		>
+			<div class="a-d-top">
+				<div class="a-d-topTit">
+					<div>另存为模板</div>
+				</div>
+				<div class="a-d-t-right">
+					<span @click.stop="close()">×</span>
+				</div>
+			</div>
+			<div class="bfd_box" v-loading="loading" label-position="top">
+				<el-form :model="form" :rules="rules" ref="ruleForm">
+					<div style="display: flex;width: 100%;justify-content: space-between;">
+						<el-form-item label="模板名称" prop="name">
+  				  <el-input v-model="form.name" placeholder="请输入模板名称" style="width: 300px;"></el-input>
+  				</el-form-item>
+					<el-form-item label="所属学科" prop="subject">
+						<el-select v-model="form.subject" placeholder="请选择所属学科" style="width: 300px;">
+  					  <el-option
+  					    v-for="item in subjectList"
+  					    :key="item.value"
+  					    :label="item.label"
+  					    :value="item.value">
+  					  </el-option>
+  					</el-select>
+  				  <!-- <el-input v-model="form.subject" placeholder="请输入所属学科" style="width: 300px;"></el-input> -->
+  				</el-form-item>
+					</div>
+					<el-form-item label="模板简介(40字以内)" prop="brief">
+						<el-input type="textarea" v-model="form.brief" style="width: 100%;" :rows="3" :maxlength="40" resize="none" placeholder="请输入模板简介"></el-input>
+					</el-form-item>
+					<el-form-item label="权限管理" style="display: flex;flex-direction: column;align-items: flex-start;">
+						<div>公开到社区:<el-switch v-model="form.permissions"></el-switch></div>
+					</el-form-item>
+				</el-form>
+			</div>
+			<div class="bfd_bottom" v-loading="loading">
+				<el-button @click="close()">取消</el-button>
+				<el-button type="primary" @click="submitBtn('ruleForm')">保存</el-button>
+			</div>
+		</el-dialog>
+	</div>
+</template>
+
+<script>
+export default {
+	emits: ["success"],
+	props: {
+		dataList:{
+			type:Array,
+			default:()=>{return []}
+		}
+	},
+	data() {
+		return {
+			loading: false,
+			dialogVisible: false,
+			userId: this.$route.query["userid"],
+			oid: this.$route.query["oid"],
+			org: this.$route.query["org"],
+			subjectList:[
+				{value:'1',label:'语文'},
+				{value:'2',label:'数学'},
+				{value:'3',label:'英语'},
+				{value:'4',label:'科学'},
+				{value:'5',label:'物理'},
+				{value:'6',label:'化学'},
+				{value:'7',label:'生物'},
+				{value:'8',label:'历史'},
+				{value:'9',label:'地理'},
+				{value:'10',label:'政治'},
+				
+			],
+			form:{
+				name:"",
+				subject:"",
+				brief:"",
+				permissions:false,
+			},
+			rules:{
+				name:[{required:true,message:"请输入课程名称",trigger:"blur"}],
+				subject:[{required:true,message:"请输入所属学科",trigger:"blur"}]
+			},
+
+		};
+	},
+	methods: {
+		open(_json) {
+			this.form = {
+				name:"",
+				subject:"",
+				brief:"",
+				permissions:false,
+			}
+			this.loading = false;
+			this.dialogVisible = true;
+		},
+		close() {
+			this.dialogVisible = false;
+			this.form = {
+				name:"",
+				subject:"",
+				brief:"",
+				permissions:false,
+			};
+		},
+		search(){
+			
+		},
+		submitBtn(ref) {
+			this.$refs[ref].validate((valid) => {
+          if (valid) {
+						this.loading = true;
+						let _data = JSON.parse(JSON.stringify(this.dataList));
+						let _result = [];
+						
+						_data.forEach(i=>{
+							i.jsonData.content = "";
+							i.jsonData.dataFileList = [];
+							i.jsonData.fileList = [];
+							i.createtime = "";
+							i.id = "",
+							i.tId = "",
+							i.userid = "";
+							_result.push(i)
+						})
+						let params = [{
+							title:this.form.name,
+							subject:this.form.subject,
+							uid:this.userId,
+							brief:this.form.brief,
+							per:this.form.permissions?1:0,
+							jsonData:JSON.stringify(_result),
+						}]
+						// this.loading = false;
+						// return console.log(params);
+						this.ajax.post(this.$store.state.api+"insertClassroomTemplate",params).then(res=>{
+							console.log(res)
+							this.$message.success("另存模板成功");
+							this.loading = false;
+							this.close();
+						}).catch(e=>{
+							console.log(e);
+							this.$message.error("另存失败");
+							this.loading = false;
+						})
+						// return console.log(params)
+          }
+        });
+		},
+
+	},
+};
+</script>
+
+<style scoped>
+.bindingFormDialog >>> .el-dialog {
+	min-width: 700px;
+
+	height: 500px;
+	box-shadow: 0px 0 8px 0px #555555;
+	border-radius: 8px;
+	background-color: #fff;
+	/* top: 0px; */
+	/* margin: 0 auto; */
+	overflow: hidden;
+}
+.bindingFormDialog >>> .el-dialog__body {
+	height: 100%;
+	min-width: 700px;
+	flex-shrink: 0;
+	box-sizing: border-box;
+	padding-bottom: 50px;
+	padding-top: 10px;
+}
+.bindingFormDialog >>> .el-dialog__header {
+	display: none !important;
+}
+
+.a-d-top {
+	/* background: #adadad; */
+	display: flex;
+	flex-direction: row;
+	flex-wrap: nowrap;
+	align-items: center;
+	justify-content: space-between;
+	height: 54px;
+	border-radius: 8px 8px 0 0;
+	user-select: none;
+	border-bottom: 1px #ccc solid;
+}
+.a-d-top >>> .el-input__inner {
+	width: 320px;
+	height: 32px;
+}
+.a-d-top >>> .el-input__icon {
+	line-height: 32px;
+}
+
+.a-d-topTit {
+	/* width: 171px; */
+	/* margin-left: 20px; */
+	height: 32px;
+	display: flex;
+	align-items: center;
+	font-family: PingFang SC;
+	box-sizing: border-box;
+	padding: 5px;
+	line-height: 22px;
+	justify-content: center;
+	/* text-align: left; */
+}
+
+.a-d-t-right {
+	width: 40px;
+	height: 40px;
+	margin-right: 10px;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	color: black !important;
+}
+
+.a-d-t-right > span {
+	width: 25px;
+	height: 25px;
+	border-radius: 25px;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	/* align-items: center; */
+	font-size: 22px;
+	color: #fff;
+	/* background-color: #adadad; */
+	cursor: pointer;
+	/* background-color: #e6e6e6; */
+	color: #adadad;
+}
+
+.bfd_box {
+	width: 100%;
+	height: calc(100% - 80px);
+	overflow: hidden;
+}
+
+.bfd_bottom {
+	width: 100%;
+	height: calc(40px);
+	margin-top: 10px;
+	display: flex;
+	justify-content: flex-end;
+}
+
+.bfd_b_left {
+	flex: 1;
+	height: 100%;
+	display: flex;
+	align-items: center;
+}
+
+.a_d_t_input {
+	display: flex;
+	align-items: center;
+}
+
+/* .bfd_b_right {
+	width: 200px;
+	height: 100%;
+	display: flex;
+	align-items: center;
+	justify-content: flex-end;
+} */
+</style>

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

@@ -293,7 +293,7 @@ export default {
   width: 100%;
   display: flex;
   align-items: center;
-  border: 1px solid #e7e7e7;
+  /*border: 1px solid #e7e7e7;*/
   border-radius: 4px;
   height: 35px;
   padding: 0 7px;

+ 48 - 0
src/components/pages/classroomObservation/components/wordcloudEChart.vue

@@ -0,0 +1,48 @@
+<template>
+	<div class="chart" id="charts_canvas" ref="chartRef"></div>
+</template>
+
+<script>
+import * as echarts from 'echarts';
+import "echarts-wordcloud";
+export default {
+	props: {
+		data: {
+			type: Object,
+			default: () => {},
+		},
+	},
+	data() {
+		return {
+			chartObj: null,
+			chartData: null,
+		};
+	},
+	watch: {
+		data() {
+			this.getChartData();
+		},
+	},
+	methods: {
+		getChartData() {
+			this.chartObj = echarts.init(this.$refs.chartRef);
+			this.chartObj.setOption(this.data);
+			window.addEventListener("resize", () => {
+					this.chartObj.resize();
+      });
+		},
+	},
+	mounted() {
+		this.getChartData();
+	},
+};
+</script>
+
+<style scoped>
+.chart {
+	max-width: 100%;
+	width: 100%;
+	height: 100%;
+	background-color: #fff;
+}
+</style>

+ 202 - 92
src/components/pages/classroomObservation/index.vue

@@ -12,16 +12,17 @@
 		</div> -->
 		<div class="co-header2">
 			<div class="co-h2-left">
-				<span
+				<!-- <span
 					class="co-h2-l-icon"
 					@click="$refs.addNewCourseDialogRef.open()"
-				></span>
+				></span> -->
+				<span class="co-h2-l-icon" @click="addNewCourse()"></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="请选择"
+						placeholder="查看历史课堂"
 						@change="changeTid"
 					>
 						<el-option
@@ -31,12 +32,15 @@
 							:value="item.value"
 						>
 							<div class="selectBox">
-								<span style="float: left">{{ item.label }}</span>
-								<span
+								<span>{{ item.label }}</span>
+								<div class="controlsBox">
+									<span class="changeSelect" @click.stop="changeCourse(item)"></span>
+									<span
 									class="delSelect"
 									@click.stop="delCourse(item.id)"
-									style="float: right"
 								></span>
+								</div>
+								
 							</div>
 						</el-option>
 					</el-select>
@@ -152,12 +156,13 @@
 			:tid="tid"
 			@shareBtn="shareBtn"
 		></sharePdf>
-
-		<addNewCourseDialog
+		<changeCourseNameDialog :tid="tid" ref="changeCourseNameDialogRef" @success="changeCourseSuccess"/>
+		
+		<!-- <addNewCourseDialog
 			:courseList="optionData"
 			ref="addNewCourseDialogRef"
 			@success="addNewCourse"
-		/>
+		/> -->
 	</div>
 </template>
 
@@ -168,25 +173,32 @@ import chatArea from "./components/chatArea.vue";
 import messageArea from "./components/messageArea.vue";
 
 import sharePdf from "./components/sharePdf.vue";
-// 添加课程弹窗
-import addNewCourseDialog from "./components/addNewCourseDialog.vue";
+
+import { v4 as uuidv4 } from "uuid";
+// 添加课堂弹窗
+// import addNewCourseDialog from "./components/addNewCourseDialog.vue";
+//修改课程名称弹窗
+import changeCourseNameDialog from './components/changeCourseNameDialog';
+//保存模板弹窗
+
 export default {
 	components: {
 		chatArea,
 		messageArea,
 		sharePdf,
-		addNewCourseDialog,
+		changeCourseNameDialog,
+		// addNewCourseDialog,
 	},
 	data() {
 		return {
-			title: "12月19日会议录音",
 			loading: false,
 			dialogVisibleShare: false,
-			createTime:new Date().toLocaleString().replaceAll('/','-'),
+			createTime: new Date().toLocaleString().replaceAll("/", "-"),
 			tid: "",
 			fileId: "",
 			fileIdId: "",
 			optionData: [],
+			userId: this.$route.query["userid"],
 		};
 	},
 	methods: {
@@ -198,53 +210,70 @@ export default {
 				this.getFileIdId();
 			});
 		},
-		addNewCourse(form) {
-			if (this.loading) return this.$message.info("请稍等");
-			this.loading = true;
-			let params = {
-				tid: form.no,
-				name: form.name,
-			};
-			this.ajax
-				.post(
-					"https://gpt4.cocorobo.cn/insert_classroom_observation_tid",
-					params
-				)
-				.then((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.loading = false;
-									this.$nextTick(() => {
-										this.getCourseList().then((_) => {
-											this.getFileIdId();
-											this.$refs.messageAreaRef.getData();
-											this.$refs.chatAreaRef.getData();
+		addNewCourse() {
+			return new Promise((resolve, reject) => {
+				if (this.loading) return this.$message.info("请稍等");
+				this.loading = true;
+				let date = new Date();
+				let month = date.getMonth() + 1;
+				let day = date.getDate();
+				let classroomName = `${month < 10 ? "0" + month : month}${
+					day < 10 ? "0" + day : day
+				}新建课堂`;
+				let sum = this.optionData.filter(
+					(i) => i.label.indexOf(classroomName) != -1
+				).length;
+				if (!sum == 0) {
+					classroomName += sum;
+				}
+				let params = {
+					tid: uuidv4(),
+					name: classroomName,
+					userid: this.userId,
+				};
+				this.ajax
+					.post(
+						"https://gpt4.cocorobo.cn/insert_classroom_observation_tid",
+						params
+					)
+					.then((res) => {
+						let _data = res.data.FunctionResponse;
+						if (_data.message == "创建成功") {
+							// 设置该课堂的tid
+							this.tid = params.tid;
+							this.ajax
+								.post("https://gpt4.cocorobo.cn/insert_classroom_observation", {
+									tid: params.tid,
+									type: 10,
+									index: 0,
+									json_data: JSON.stringify({ file_ids: "" }),
+									userid: this.userId,
+								})
+								.then((res2) => {
+									let _data2 = res2.data.FunctionResponse;
+									if (_data2.message == "创建成功") {
+										this.loading = false;
+										this.$nextTick(() => {
+											this.getCourseList().then((_) => {
+												this.getFileIdId();
+												this.$refs.messageAreaRef.getData();
+												this.$refs.chatAreaRef.getData();
+												resolve();
+											});
 										});
-									});
-								} else {
-									this.$message.error("创建fileIds失败");
-								}
-							});
-					} else if (_data.message == "tid重复") {
-						this.$message.error("该课程已存在");
-						this.loading = false;
-					} else {
-						this.$message.error("创建失败");
-						this.loading = false;
-					}
-				});
+									} else {
+										this.$message.error("创建fileIds失败");
+									}
+								});
+						} else if (_data.message == "tid重复") {
+							this.$message.error("该课堂已存在");
+							this.loading = false;
+						} else {
+							this.$message.error("创建失败");
+							this.loading = false;
+						}
+					});
+			});
 		},
 		updateFileId(newValue) {
 			this.fileId = newValue;
@@ -252,7 +281,18 @@ export default {
 		// 生成报告
 		getReport() {
 			if (!this.fileId) return;
-			this.$refs.messageAreaRef.getReport();
+			this.$confirm("操作将覆盖原有内容,是否继续?", "提示", {
+				confirmButtonText: "确定",
+				cancelButtonText: "取消",
+				type: "warning",
+			})
+				.then(() => {
+					this.$refs.messageAreaRef.getReport();
+				})
+				.catch((e) => {
+					console.log(e)
+					console.log("取消生成报告");
+				});
 		},
 		//预览
 		preview() {
@@ -286,7 +326,7 @@ export default {
 			this.$message.info("主页");
 		},
 		delCourse(_value) {
-			this.$confirm("此操作将永久删除该课, 是否继续?", "提示", {
+			this.$confirm("此操作将永久删除该课, 是否继续?", "提示", {
 				confirmButtonText: "确定",
 				cancelButtonText: "取消",
 				type: "warning",
@@ -304,23 +344,26 @@ export default {
 					// });
 					let params = {
 						tid: _value,
-					}
+					};
 					this.ajax
-					.post("https://gpt4.cocorobo.cn/update_classroom_observation_isdel", params)
-					.then((res) => {
-						this.$message({
-							type: "success",
-							message: "删除成功!",
-						});
-						// 清空tid
-						this.tid = "";
-						this.getCourseList().then((_) => {
-							if (!this.tid) return;
-							this.getFileIdId();
-							this.$refs.messageAreaRef.getData();
-							this.$refs.chatAreaRef.getData();
+						.post(
+							"https://gpt4.cocorobo.cn/update_classroom_observation_isdel",
+							params
+						)
+						.then((res) => {
+							this.$message({
+								type: "success",
+								message: "删除成功!",
+							});
+							// 清空tid
+							this.tid = "";
+							this.getCourseList().then((_) => {
+								if (!this.tid) return;
+								this.getFileIdId();
+								this.$refs.messageAreaRef.getData();
+								this.$refs.chatAreaRef.getData();
+							});
 						});
-					});
 				})
 				.catch(() => {});
 		},
@@ -360,28 +403,30 @@ export default {
 			this.loading = true;
 			return new Promise((resolve, reject) => {
 				this.ajax
-					.post("https://gpt4.cocorobo.cn/get_classroom_observation_all")
+					.post("https://gpt4.cocorobo.cn/get_classroom_observation_all", {
+						userid: this.userId,
+					})
 					.then((res) => {
 						let _data = res.data.FunctionResponse.result;
-						let _result = []
+						let _result = [];
 						try {
 							_result = _data ? JSON.parse(_data) : [];
 						} catch (error) {
-							_result = []
+							_result = [];
 						}
 
-						if (_result.length <= 0) { 
+						if (_result.length <= 0) {
 							this.loading = false;
-							return
-						};
+							return;
+						}
 						let _optionData = _result.map((item) => {
 							item.jsonData = item.jsonData ? JSON.parse(item.jsonData) : {};
 							return {
 								label: item.jsonData.courseName
 									? item.jsonData.courseName
-									: `${item.tId}课`,
+									: `${item.tId}课`,
 								value: item.tId,
-								id:item.id
+								id: item.id,
 							};
 						});
 						_optionData = _optionData.filter(
@@ -389,9 +434,10 @@ export default {
 						);
 						this.optionData = _optionData;
 						if (this.optionData.length > 0) {
-							if (!this.tid) this.tid = this.optionData[0].value;
+							this.$refs.chatAreaRef.$refs.startPageRef.showIntroduce = false;
 						}
 						this.loading = false;
+						console.log(this.optionData);
 						resolve();
 					});
 			});
@@ -417,11 +463,51 @@ export default {
 				this.optionData[_index] = { ...this.optionData[_index], ..._newObj };
 				this.$forceUpdate();
 			}
-			console.log(this.optionData);
 		},
-		updateTime(time){
+		updateTime(time) {
 			this.createTime = time;
-		}
+		},
+		// 修改课程名称
+		changeCourse(item){
+			this.$refs.changeCourseNameDialogRef.open(item);
+			// console.log(item);
+		},
+		// 修改课程名称确定
+		changeCourseSuccess(data){
+			this.loading = true;
+			if(this.tid==data.tid){
+				this.$refs.messageAreaRef.bmData.jsonData.courseName = data.name;
+				this.$refs.messageAreaRef.saveData(this.$refs.messageAreaRef.bmData).then(res=>{
+					this.loading = false;
+					this.optionData.find(i=>i.id==data.id).label=data.name
+					this.$message.success('修改成功')
+				})
+			}else{
+				this.ajax.post("https://gpt4.cocorobo.cn/get_classroom_observation_new",{
+				tid:data.tid,
+				type:0
+			}).then(res=>{
+				let _data = res.data.FunctionResponse.result;
+				_data = JSON.parse(_data);
+				let _bmData = _data.find(i=>i.tIndex==0);
+				_bmData.jsonData = JSON.parse(_bmData.jsonData);
+				_bmData.jsonData.courseName = data.name;
+				this.$refs.messageAreaRef.saveData(_bmData).then(res=>{
+					this.loading = false;
+					this.optionData.find(i=>i.id==data.id).label=data.name
+					this.$message.success('修改成功')
+				})
+			}).catch(e=>{
+				console.log(e);
+				this.$message.error('修改失败')
+				this.loading = false;
+			})
+			}
+		},
+		//保存词频词汇分析
+		saveWordFrequency({_sentence=0,_words=0}){
+			this.$refs.messageAreaRef.saveWordFrequency({_sentence,_words})
+		},
 	},
 	mounted() {
 		this.getCourseList().then((_) => {
@@ -676,20 +762,44 @@ export default {
 .selectBox {
 	width: 100%;
 	height: 100%;
+	display: flex;
+	align-items: center;
+	justify-content: space-between;
+}
+
+.controlsBox{
+	display: flex;
+	align-items: center;
+	width: auto;
+	height: 100%;
+	display: none;
 }
-.selectBox:hover .delSelect {
+
+.selectBox:hover>.controlsBox{
 	display: flex;
 }
 
+.changeSelect{
+	width: 16px;
+	height: 16px;
+	/* display: none; */
+	align-items: center;
+	justify-content: center;
+	background: url("../../../assets/icon/classroomObservation/editIcon.svg") no-repeat;
+	background-size: 100% 100%;
+	box-sizing: border-box;
+	margin-right: 10px;
+}
+
 .delSelect {
 	width: 16px;
 	height: 16px;
-	display: none;
+	/* display: none; */
 	align-items: center;
 	justify-content: center;
 	background: url("../../../assets/icon/classroomObservation/del.svg") no-repeat;
 	background-size: 100% 100%;
 	box-sizing: border-box;
-	transform: translateY(7px);
+	/* transform: translateY(7px); */
 }
 </style>

+ 172 - 0
src/components/pages/components/wOffice.vue

@@ -0,0 +1,172 @@
+<template>
+  <!--使用 pdfvuer 实现 滑动浏览 单印章-->
+  <div class="pdf">
+    <iframe ref="viframe" style="width: 100%; height: 99%; border: none"
+    :src="'https://view.officeapps.live.com/op/view.aspx?src=' + encodeURIComponent(url)"></iframe>
+  </div>
+</template>
+
+<script>
+
+export default {
+  name: "Pdfvuer",
+  components: {
+    // pdf: pdfvuer,
+  },
+  props: {
+    // 当前pdf路径
+    url: {
+      type: String,
+      default:
+        "",
+    },
+  },
+  data() {
+    return {
+
+    };
+  },
+  mounted() {
+  
+  },
+  beforeDestroy() { },
+  watch: {
+  },
+  methods: {
+   
+  },
+};
+</script>
+<style scoped>
+.loading {
+  height: 100%;
+  width: 100%;
+  /* background: #000; */
+  position: absolute;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  /* background-color: rgba(255, 255, 255, 0.7); */
+  background-color: rgba(255, 255, 255, 1);
+  z-index: 9;
+  font-size: 20px;
+  color: #007fff;
+}
+
+.pdf {
+  height: 100%;
+  width: 100%;
+  position: relative;
+  box-sizing: border-box;
+  overflow-x: hidden;
+  overflow-y: auto;
+}
+
+.pdf .show {
+  margin: auto;
+  width: 100%;
+  display: flex;
+  flex-wrap: wrap;
+}
+
+.pdf .show .p-pdf {
+  overflow: hidden;
+}
+
+.pdf .show .p-pdf .line {
+  position: absolute;
+  width: 50px;
+  right: -50px;
+  background: rgb(255, 186, 96);
+  height: 2px;
+}
+
+.pdf .show .p-pdf span {
+  width: 100%;
+  text-align: center;
+  color: #fff;
+}
+
+.pdf .show .p-pdf span+span {
+  margin-top: 10px;
+}
+
+.pdfbox {
+  /* border: 3px solid #000; */
+  /* box-sizing: border-box; */
+  /* border-radius: 4px; */
+  /* overflow: hidden; */
+}
+
+.pdf .pdf_footer {
+  position: sticky;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  padding: 10px 0;
+  width: 100%;
+  height: 75px;
+  background-color: rgba(255, 255, 255, 0.5);
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  flex-direction: column;
+}
+
+.pdf .pdf_footer .info {
+  display: flex;
+  flex-wrap: wrap;
+  width: 100%;
+  justify-content: center;
+}
+
+.pdf .p-pdf .viewerContainer {
+  width: 100%;
+}
+
+/* .pdf .pdf_footer .info div {
+  width: 30%;
+} */
+.pdf .pdf_footer .operate {
+  margin: 10px 0 0;
+  display: flex;
+  flex-wrap: wrap;
+  justify-content: center;
+  width: 100%;
+}
+
+.pdf .pdf_footer .operate div {
+  text-align: center;
+  font-size: 15px;
+}
+
+.pdf .pdf_footer .operate .btn {
+  cursor: pointer;
+  margin: 5px 10px;
+  width: 100px;
+  border-radius: 10px;
+  padding: 5px;
+  color: #fff;
+  background-color: #066ebe;
+}
+
+.pdf::-webkit-scrollbar {
+  /*滚动条整体样式*/
+  width: 6px;
+  /*高宽分别对应横竖滚动条的尺寸*/
+  height: 6px;
+}
+
+/*定义滚动条轨道 内阴影+圆角*/
+.pdf::-webkit-scrollbar {
+  border-radius: 10px;
+  background-color: #b8bdc9;
+}
+
+/*定义滑块 内阴影+圆角*/
+.pdf::-webkit-scrollbar-thumb {
+  border-radius: 10px;
+  -webkit-box-shadow: inset 0 0 6px rgb(96, 125, 184);
+  background-color: #2c5ab3;
+}
+</style>

+ 194 - 33
src/components/pages/contrastObservation/index.vue

@@ -1,6 +1,51 @@
 <template>
 	<div class="contrastObservation" v-loading="loading">
-		<div class="co_card co_aggregateData" v-loading="aggregateLoading">
+		<div class="co_nav">
+			<div class="co_n_left">
+				<span
+					:class="showIndex == 0 ? 'co_n_l_active' : ''"
+					@click="showIndex = 0"
+					v-loading="aggregateLoading"
+					>总览</span
+				>
+				<span
+					:class="showIndex == 1 ? 'co_n_l_active' : ''"
+					@click="showIndex = 1"
+						v-loading="aiLoading"
+					>AI观察</span
+				>
+				<span
+					:class="showIndex == 2 ? 'co_n_l_active' : ''"
+					@click="showIndex = 2"
+						v-loading="teacherLoading"
+					>教师观察</span
+				>
+				<span
+					:class="showIndex == 3 ? 'co_n_l_active' : ''"
+					@click="showIndex = 3"
+					v-loading="contrastLoading"
+					>对比观察</span
+				>
+			</div>
+			<div class="co_n_right" v-loading="
+				loading ||
+				aggregateLoading ||
+				aiLoading ||
+				teacherLoading ||
+				contrastLoading
+			">
+				<div @click.stop="refresh()">
+					<img
+						:src="require('../../../assets/icon/contrastObservation/refresh.svg')"
+					/>
+				</div>
+			</div>
+		</div>
+		<div
+			class="co_card co_aggregateData"
+			:style="`z-index:${showIndex == 0 ? 11 : 10}`"
+			v-loading="aggregateLoading"
+		>
 			<div class="co_ad_title">
 				<img
 					:src="
@@ -14,7 +59,10 @@
 			</div>
 			<div class="co_ad_messageArea" v-html="aggregateData.message"></div>
 		</div>
-		<div class="co_card co_ai_card">
+		<div
+			class="co_card co_ai_card"
+			:style="`z-index:${showIndex == 1 ? 11 : 10}`"
+		>
 			<div class="co_c_main" v-loading="aiLoading">
 				<div class="co_c_title">AI观察结果</div>
 				<div
@@ -54,7 +102,10 @@
 				</div>
 			</div>
 		</div>
-		<div class="co_card co_teacher_card">
+		<div
+			class="co_card co_teacher_card"
+			:style="`z-index:${showIndex == 2 ? 11 : 10}`"
+		>
 			<div class="co_c_main" v-loading="teacherLoading">
 				<div class="co_c_title">教师观察结果</div>
 				<div
@@ -94,7 +145,10 @@
 				</div>
 			</div>
 		</div>
-		<div class="co_card co_contrast_card">
+		<div
+			class="co_card co_contrast_card"
+			:style="`z-index:${showIndex == 3 ? 11 : 10}`"
+		>
 			<div class="co_c_main" v-loading="contrastLoading">
 				<div class="co_c_title">对比观察结果</div>
 				<div
@@ -206,7 +260,8 @@ export default {
 				checkUrl: "",
 				doUrl: "",
 			},
-			bmData:null,
+			showIndex: 0,
+			bmData: null,
 			editorBarData: {
 				type: 0,
 				content: "",
@@ -291,13 +346,15 @@ export default {
 							let _testData = baseMessage.jsonData.testData;
 							this.editorBarData = baseMessage.jsonData.editorBarData;
 							this.bmData = baseMessage;
-							if(!flag){//判断是否是需要生成数据
-								if(baseMessage.jsonData.contrastObservationData){//如果有这个字段则只取里面的数据
+							if (!flag) {
+								//判断是否是需要生成数据
+								if (baseMessage.jsonData.contrastObservationData) {
+									//如果有这个字段则只取里面的数据
 									let _data = baseMessage.jsonData.contrastObservationData;
-									this.aggregateData=_data.aggregateData;
-									this.aiData=_data.aiData;
-									this.teacherData=_data.teacherData;
-									this.contrastData=_data.contrastData;
+									this.aggregateData = _data.aggregateData;
+									this.aiData = _data.aiData;
+									this.teacherData = _data.teacherData;
+									this.contrastData = _data.contrastData;
 									return;
 								}
 							}
@@ -1160,16 +1217,19 @@ ${_aiWorkText}
 			this.getBindTestId(flag).then((_) => {
 				// 后去表单的数据
 				this.getBindTestData().then((_) => {
+					Promise.all([
+						this.getTeacherResultData(),
+						this.getAiResultData(),
+					]).then((_) => {
+						this.getAggregateChartData();
 						Promise.all([
-							this.getTeacherResultData(),
-							this.getAiResultData(),
+							this.getContrastResultData(),
+							this.getAggregateResultData(),
 						]).then((_) => {
-							this.getAggregateChartData();
-							Promise.all([this.getContrastResultData(),this.getAggregateResultData()]).then(_=>{
-								this.saveData()
-							})
+							this.saveData();
 						});
 					});
+				});
 			});
 		},
 		//储存数据
@@ -1177,11 +1237,11 @@ ${_aiWorkText}
 			return new Promise((resolve, reject) => {
 				let _saveData = JSON.parse(JSON.stringify(this.bmData));
 				_saveData.jsonData.contrastObservationData = {
-						aggregateData: this.aggregateData,
-						aiData: this.aiData,
-						teacherData: this.teacherData,
-						contrastData: this.contrastData,
-				}
+					aggregateData: this.aggregateData,
+					aiData: this.aiData,
+					teacherData: this.teacherData,
+					contrastData: this.contrastData,
+				};
 				let params = {
 					id: _saveData.id,
 					json_data: JSON.stringify(_saveData.jsonData),
@@ -1189,16 +1249,14 @@ ${_aiWorkText}
 				// console.log(params)
 				// return resolve();
 				this.ajax
-					.post(
-						"https://gpt4.cocorobo.cn/update_classroom_observation",
-						params
-					)
+					.post("https://gpt4.cocorobo.cn/update_classroom_observation", params)
 					.then((res) => {
-						this.$message.success("保存数据成功")
+						this.$message.success("保存数据成功");
 						resolve();
-					}).catch(e=>{
+					})
+					.catch((e) => {
 						console.log(e);
-						this.$message.info('保存数据失败')
+						this.$message.info("保存数据失败");
 					});
 			});
 		},
@@ -1211,9 +1269,9 @@ ${_aiWorkText}
 
 <style scoped>
 .contrastObservation {
-	min-width: 1500px;
+	/* min-width: 1500px; */
 	/* min-height: 800px; */
-	width: 100%;
+	width: 100vw;
 	height: 100vh;
 	display: flex;
 	background-color: #f0f2f5;
@@ -1224,6 +1282,7 @@ ${_aiWorkText}
 	justify-content: space-around;
 	align-items: center;
 	position: relative;
+	overflow-x: hidden
 }
 
 .refresh {
@@ -1239,6 +1298,7 @@ ${_aiWorkText}
 	align-items: center;
 	box-shadow: 0 16px 24px 2px #0000000a;
 	cursor: pointer;
+	z-index: 11;
 }
 
 .refreshDisabled {
@@ -1264,7 +1324,9 @@ ${_aiWorkText}
 	box-sizing: border-box;
 	padding: 20px;
 	position: relative;
-	overflow: hidden;
+	/* overflow: hidden; */
+	z-index: 10;
+	overflow-x:hidden ;
 }
 
 .co_aggregateData {
@@ -1436,7 +1498,9 @@ ${_aiWorkText}
 .titleBlob {
 	font-weight: bold;
 }
-
+.co_nav {
+	display: none;
+}
 /* .compareTitle{
 	margin-left: 10px;
 	position: relative;
@@ -1449,4 +1513,101 @@ ${_aiWorkText}
 	height: 20px;
 	position: relative;
 } */
+/* 手机 */
+@media screen and (max-width: 600px) {
+	.refresh {
+		display: none;
+	}
+	.co_nav {
+		display: flex;
+		width: 100vw;
+		height: 50px;
+		position: absolute;
+		top: 0;
+		justify-content: space-between;
+		align-items: center;
+		background-color: #fff;
+	}
+	.co_n_left {
+		flex: 1;
+		height: 100%;
+		background-color: #fff;
+		display: flex;
+		display: flex;
+		align-items: center;
+		max-width: (100% - 50px);
+		overflow-y: hidden;
+	}
+	.co_n_left > span {
+		height: 100%;
+		padding: 0 10px;
+		margin: 0 5px;
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		font-size: 1em;
+		white-space: nowrap;
+		position: relative;
+
+	}
+	.co_n_right {
+		width: 50px;
+		height: 100%;
+		background-color: #fff;
+		display: flex;
+		justify-content: center;
+		align-items: center;
+	}
+	.co_n_right>div{
+		width: 100%;
+		height: 100%;
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		position: relative;
+	}
+	.co_n_right>div::after{
+		content:"";
+		width: 2px;
+		height: 20px;
+		position: absolute;
+		left: 0;
+		top: 15px;
+		background-color: #E7E7E7;
+	}
+	.co_n_l_active {
+		color: #3681fc;
+	}
+	.co_n_l_active::after {
+		content: "";
+		width: 100%;
+		height: 2px;
+		background-color: #3681fc;
+		position: absolute;
+		bottom: 0;
+	}
+	.co_card {
+		position: absolute !important;
+		min-width: 100vw !important;
+		max-width: 100vw !important;
+		width: 100vw !important;
+		height: calc(100vh - 50px) !important;
+		margin-top: 50px;
+		border-radius: 0;
+	}
+	.co_ai_card {
+		padding: 0;
+	}
+
+	.co_teacher_card {
+		padding: 0;
+	}
+
+	.co_contrast_card {
+		padding: 0;
+	}
+	.co_card>.co_c_main{
+		border-radius: 0;
+	}
+}
 </style>

+ 35 - 4
src/components/pages/course.vue

@@ -397,7 +397,7 @@
       </span>
     </el-dialog>
 		<shareDialog ref="shareDialogRef"/>
-    <templateDialog :dialogVisibleTemplate.sync="dialogVisibleTemplate" :userid="userid" :org="org" :oid="oid" @goToCourseTemplate="goToCourseTemplate"></templateDialog>
+    <templateDialog :dialogVisibleTemplate.sync="dialogVisibleTemplate" :userid="userid" :org="org" :oid="oid" @goToCourseTemplate="goToCourseTemplate" @goToCourseTemplate2="goToCourseTemplate2"></templateDialog>
   </div>
 </template>
 
@@ -461,8 +461,8 @@ export default {
       pTypeCheckName: [],
       btnDisplay: false,
       dialogVisibleTemplate: false,
-      orgArray:['1973f6c7-1561-11ee-91d8-005056b86db5','777559d2-7239-11ee-b98c-005056b86db5','884c5665-a453-46f3-b7b6-01d575290aa9'],
-      oidArray:['f297fbdc-f0a0-11ee-b534-005056b86db5']
+      orgArray:['1973f6c7-1561-11ee-91d8-005056b86db5','777559d2-7239-11ee-b98c-005056b86db5','884c5665-a453-46f3-b7b6-01d575290aa9','0fec3a8a-ad04-11ed-b13d-005056b86db5'],
+      oidArray:['f297fbdc-f0a0-11ee-b534-005056b86db5','45facc0a-1211-11ec-80ad-005056b86db5']
     };
   },
   methods: {
@@ -594,7 +594,8 @@ export default {
       // this.$router.push(path);
     },
     oepnTemplate(){
-      this.dialogVisibleTemplate = true;
+      this.goToCourseTemplate('');
+      // this.dialogVisibleTemplate = true;
     },
     goToCourseTemplate(tid){
       this.$router.push(
@@ -610,6 +611,36 @@ export default {
           tid 
         );
     },
+    goToCourseTemplate2(tid){
+      if(tid){
+        this.$router.push(
+          "/aiAddCourse?userid=" +
+          this.userid +
+          "&oid=" +
+          this.oid +
+          "&org=" +
+          this.org +
+          "&role=" +
+          this.role +
+          "&templateid=" +
+          tid +
+          "&istemplate=1"
+        );
+      }else{
+        this.$router.push(
+          "/aiAddCourse?userid=" +
+          this.userid +
+          "&oid=" +
+          this.oid +
+          "&org=" +
+          this.org +
+          "&role=" +
+          this.role +
+          "&templateid=" +
+          "&istemplate=1"
+        );
+      }
+    },
     goToCourse5(courseId) {
       if (courseId) {
         this.$router.push(

+ 1 - 0
src/components/pages/kindStudentEva/test/component/sharePdf.vue

@@ -269,6 +269,7 @@ export default {
 
 .url_box {
   margin-bottom: 20px;
+  margin-top: 10px;
 }
 
 .qrcode_box {

+ 2 - 2
src/components/pages/newCourse/addCourse.vue

@@ -10005,7 +10005,7 @@ export default {
       //   ic
       // ].name = JSON.parse(JSON.stringify(e.target.value));
       this.line =
-        this.unitJson[i].chapterInfo[0].taskJson[0].chapterData[ic].name;
+        this.unitJson[i].chapterInfo[0].taskJson[j].chapterData[ic].name;
       this.taskCount = j;
       this.lineCount = ic;
       this.dialogVisibleupdataVideoT = true;
@@ -18196,7 +18196,7 @@ ol {
 
 .rb_c_box_right {
   height: auto;
-  width: calc(100%);
+  width: calc(100% - 280px);
   /* overflow: hidden; */
 }
 

+ 7 - 2
src/components/pages/pblCourse/index.vue

@@ -42,13 +42,13 @@
         :pdfUrl="priFile"
         v-if="/\.(pdf)$/i.test(priFile)"
       />
-      <img
+      <!-- <img
         v-if="/\.(jpeg|jpg|png|img)$/i.test(priFile)"
         :src="priFile"
         @click="previewImg(priFile)"
         style="max-width: 100%;max-height: 100%;"
         alt=""
-      />
+      /> -->
       <span slot="footer" class="dialog-footer">
         <el-button @click="priDiaVisible = false">关闭</el-button>
       </span>
@@ -272,6 +272,8 @@ Instruction: Based on the context, follow "Format example", write content.
     choiceAnswer(_data) {
       this.taskList[this.phase.atPhase].answerArray[_data[0]].userAnswer =
         _data[1];
+      this.saveTopic();
+
       this.$forceUpdate();
     },
     savaDoIndex() {
@@ -370,10 +372,13 @@ Instruction: Based on the context, follow "Format example", write content.
     },
     addFile(obj) {
       this.taskList[this.phase.atPhase].fileList.push(obj);
+      this.saveTopic();
       this.$forceUpdate();
     },
     deleteFile(index) {
       this.taskList[this.phase.atPhase].fileList.splice(index, 1);
+      this.saveTopic();
+      // this.savaDoIndex();
       this.$forceUpdate();
     }
   },

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

@@ -386,7 +386,7 @@ export default {
       if(/^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-])+/.test(this.sMail)){
         mail = this.sMail;
       }else{
-        this.sMail + "@" + this.userSuffix
+        mail = this.sMail + "@" + this.userSuffix
       }
       if (this.time()) {
         // let params = { un: this.sPhone };
@@ -433,7 +433,7 @@ export default {
       if(/^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-])+/.test(this.sMail)){
         mail = this.sMail;
       }else{
-        this.sMail + "@" + this.userSuffix
+        mail = this.sMail + "@" + this.userSuffix
       }
       let params = [
         {

+ 22 - 6
src/components/pages/studentManage/student.vue

@@ -405,7 +405,7 @@ export default {
       if(/^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-])+/.test(this.sMail)){
         mail = this.sMail;
       }else{
-        this.sMail + "@" + this.userSuffix
+        mail = this.sMail + "@" + this.userSuffix
       }
       if (this.time()) {
         // let params = { un: this.sPhone };
@@ -452,7 +452,7 @@ export default {
       if(/^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-])+/.test(this.sMail)){
         mail = this.sMail;
       }else{
-        this.sMail + "@" + this.userSuffix
+        mail = this.sMail + "@" + this.userSuffix
       }
       let params = [
         {
@@ -690,13 +690,27 @@ export default {
             for (var cj = 0; cj < 3; cj++) {
               num += Math.floor(Math.random() * 10);
             }
-            a =
+            // a =
+            //   pinyin.getFullChars(v["学生姓名"]).toLowerCase() +
+            //   num +
+            //   "@cocorobo.cc";
+             a =
               pinyin.getFullChars(v["学生姓名"]).toLowerCase() +
-              num +
-              "@cocorobo.cc";
+              num + _this.userSuffix;
             obj.sId = v["学号"];
             obj.name = v["学生姓名"];
-            obj.mail = v["学生账号"] ? v["学生账号"] : a;
+            // obj.mail = v["学生账号"] ? v["学生账号"] : a;
+            // console.log('v["学生账号"]',v["学生账号"]==true,v["学生账号"]);
+            if (v["学生账号"]) {
+              if(/^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-])+/.test(v["学生账号"])){
+                obj.mail = v["学生账号"];
+              }else{
+                obj.mail = v["学生账号"] + "@" + _this.userSuffix
+              }
+              
+            }else{
+              obj.mail = a;
+            }
             obj.phone = v["学生手机号"];
             obj.class = v["班级"];
             arr.push(obj);
@@ -739,6 +753,7 @@ export default {
               _this.$message.error("有学生账号格式不正确,请重新上传");
               break;
             }
+            //#region 
             //  else if (item.school === "") {
             // 	_b = 1;
             // 	_this.$message.error("学生学校不能为空,请重新上传");
@@ -964,6 +979,7 @@ export default {
             // }
             // } else {
             //   loading.close();
+            //#endregion
           }
           let z = 2;
           let newArr = JSON.stringify(arr);

+ 14 - 4
src/components/pages/sz/teacher.vue

@@ -195,7 +195,6 @@
         <el-form-item
           label="角色"
           :label-width="formLabelWidth"
-          v-if="org && org != 'undefined' && org != 'null'"
         >
           <template>
             <el-radio v-model="modifyDiaData.radio" :label="0">管理员</el-radio>
@@ -389,8 +388,11 @@ export default {
         return;
       }
 
+
       let uRole = null;
-      let uType = 1;
+      // let uType = 1;
+
+      // role 1是管理员  0普通教师
       if (!this.modifyDiaData.radio) {
         uRole = 1;
       } else {
@@ -402,9 +404,11 @@ export default {
           uid: this.modifyDiaData.userid,
           uname: this.modifyDiaData.dName,
           rol: uRole,
-          typ: uType
+          typ: this.modifyDiaData.type
         }
       ];
+      // return console.log('paramsparamsparams',params);
+
       this.ajax
         .post(this.$store.state.api + "updateYTeacherInfo", params)
         .then(res => {
@@ -437,6 +441,7 @@ export default {
       this.modifyDiaData.type = val.type;
       this.modifyDiaData.mail = val.un;
 
+      // role 1是管理员  0普通教师
       if (val.role == 1) {
         this.modifyDiaData.radio = 0;
       } else {
@@ -845,7 +850,12 @@ export default {
           this.da.map(v => {
             let obj = {};
             obj.name = v["教师姓名"];
-            obj.mail = v["教师账号"];
+            // obj.mail = v["教师账号"];
+            if(/^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-])+/.test(v["教师账号"])){
+              obj.mail = v["教师账号"];
+            }else{
+              obj.mail = v["教师账号"] + "@" + _this.userSuffix
+            }
             obj.school = v["学校"];
             arr.push(obj);
           });

+ 28 - 0
src/components/pages/test/add/components/checkOrder.vue

@@ -440,6 +440,19 @@ export default {
         },
         editCheck(index, item) {
 
+        },
+        setJsonCheck(newItems){
+            let _index = this.checkC.replace("x", "").split("-");
+            let cJson = {}
+            if (this.ctype == 1) {
+                cJson = newItems[_index[0]].json ? JSON.parse(JSON.stringify(newItems[_index[0]].json)) : '';
+            } else if (this.ctype == 2) {
+                cJson = newItems[_index[0]].array[_index[1]].json ? JSON.parse(JSON.stringify(newItems[_index[0]].array[_index[1]].json)) : '';
+            } else if (this.ctype == 3) {
+                cJson = newItems[_index[0]].array[_index[1]].array[_index[2]].json ? JSON.parse(JSON.stringify(newItems[_index[0]].array[_index[1]].array[_index[2]].json)) : '';
+            }
+            this.$emit("update:cJson", cJson)
+            this.$forceUpdate()
         },
         dragStart(val, i, index) {
             if (this.isdrag != index) {
@@ -478,7 +491,12 @@ export default {
             newItems.splice(this.oldIndex, 1);
             // 在列表中目标位置增加新的节点
             newItems.splice(this.newIndex, 0, this.oldData);
+            console.log('................',...newItems);
+            /* 修改选中的并且切换的题目 */
+            this.setJsonCheck(newItems)
+
             this.$emit("changeJson", [...newItems]);
+
             this.typeIndex = "";
             this.newIndex = "";
             this.dragType = "";
@@ -536,6 +554,11 @@ export default {
             } else {
                 newItems[this.newIndex].array.splice(this.newIndex2, 0, this.oldData);
             }
+
+            /* 修改选中的并且切换的题目 */
+            this.setJsonCheck(newItems)
+            
+
             this.$emit("changeJson", [...newItems]);
             this.typeIndex = "";
             this.newIndex = "";
@@ -597,6 +620,11 @@ export default {
             } else {
                 newItems[this.newIndex].array.splice(this.newIndex2, 0, this.oldData);
             }
+
+            /* 修改选中的并且切换的题目 */
+            this.setJsonCheck(newItems)
+
+
             this.$emit("changeJson", [...newItems]);
             this.typeIndex = "";
             this.newIndex = "";

+ 1 - 0
src/components/pages/test/add/edit/index.vue

@@ -78,6 +78,7 @@ export default {
       return s ? JSON.parse(JSON.stringify(s)) : ''
     },
     changeJson(json) {
+      console.log(json);
       this.$emit("update:cJson", json);
     }
   },

+ 649 - 21
src/components/pages/test/check/index.vue

@@ -24,10 +24,10 @@
           <div class="r_pub_button_retrun" @click="retrunCourse">返回</div>
         </div>
         <div class="step_box" ref="stepBox" v-loading="pdfLoading">
-          <div class="test_title">
+          <div class="test_title" :style="!isDesktop?'justify-content: center;':''">
             <div class="left">
               <div class="title">{{ testJson.title }}</div>
-              <div class="info">
+              <div class="info"  v-if="isDesktop">
                 <div class="info_box" v-if="testJson.typeN">
                   <span>类型:</span>
                   <span>{{ testJson.typeN }}</span>
@@ -42,7 +42,7 @@
                 </div>
               </div>
             </div>
-            <div class="right">
+            <div class="right" v-if="isDesktop">
               <div class="data_box">
                 <span>提交数量</span>
                 <span><span class="big">{{ works.length }}</span>份</span>
@@ -61,13 +61,48 @@
               </div>
             </div>
           </div>
-          <div class="search_nav">
+          <div class="search_nav" v-if="isDesktop">
             <div class="right">
               <span :class="{ active: stype == 1 }" @click="checkDataType(1)">按题目查看</span>
               <span :class="{ active: stype == 2 }" @click="checkDataType(2)">按人员查看</span>
               <span :class="{ active: stype == 3 }" @click="checkDataType(3)" v-show="false">按数量查看</span>
             </div>
-            <div class="left">
+            <div class="left"  v-if="isDesktop">
+              <div style="margin-right: 10px;position: relative;" v-if="stype == 2 || stype == 3">
+                <el-select v-model="TeachingValue" @change="searchCourse" placeholder="按教研室">
+                  <el-option
+                    label="全部"
+                    value="">
+                  </el-option>
+                  <el-option
+                    v-for="item in TeachingOptions"
+                    :key="item.id"
+                    :label="item.name"
+                    :value="item.id">
+                  </el-option>
+                </el-select>
+              </div>
+              <div style="margin-right: 10px;position: relative;" v-if="stype == 2 || stype == 3">
+                <el-date-picker
+                  v-model="SubmitTime"
+                  type="date"
+                   @change="searchCourse"
+                  value-format="yyyy-MM-dd"
+                  placeholder="选择日期">
+                </el-date-picker>
+                <!-- <el-select v-model="SubmitTime" placeholder="按提交时间筛选">
+                  <el-option
+                    label="全部"
+                    value="">
+                  </el-option>
+                  <el-option
+                    v-for="item in SubmitTimeOptions"
+                    :key="item.id"
+                    :label="item.name"
+                    :value="item.id">
+                  </el-option>
+                </el-select> -->
+              </div>
               <div style="margin-right: 10px;position: relative;" v-if="stype == 2 || stype == 3">
                 <el-input v-model="courseName" class="student_input" placeholder="请输入需要搜索的姓名"></el-input>
                 <span class="serach_icon" @click="searchCourse"></span>
@@ -83,7 +118,15 @@
               <div class="btnA" v-if="stype == 3" @click="exportAllWord2">导出人员数据</div>
             </div>
           </div>
-          <div class="title_content" v-if="stype == 1">
+          <div class="search_nav" style="display:flex;justify-content:space-evenly;border: none;" v-if="!isDesktop">
+            <div class="right">
+              <span :class="{ active2: stype == 1 }" @click="checkDataType(1)">按题目查看</span>
+              <span :class="{ active2: stype == 2 }" @click="checkDataType(2)">按人员查看</span>
+              <span :class="{ active2: stype == 3 }" @click="checkDataType(3)" v-show="false">按数量查看</span>
+            </div>
+          </div>
+
+          <div class="title_content" v-if="stype == 1 && isDesktop" v-loading="isLoading">
             <div class="title_box" v-if="!testArray.length"
               style="display: flex;align-items: center;justify-content: center;height: 500px;">
               暂无内容
@@ -96,6 +139,7 @@
                 </el-tooltip>
                 <span>{{ item.title }}</span>
 								<el-button v-if="item.type == 5 && item.array.length>0" class="title_downBtn" type="primary" size="small" @click.stop="downloadFileType5(item.array,item.title)">批量下载附件</el-button>
+								<div v-if="item.type==7" style="right:0;position: absolute;">平均分:{{ getAverageScore(index) }}</div>
               </div>
               <div class="detail" v-if="item.detail">{{ item.detail }}</div>
               <div class="content1" v-if="item.type == 1">
@@ -240,7 +284,190 @@
               </div>
             </div>
           </div>
-          <div class="table_content" v-if="stype == 2">
+          <div class="title_content" v-if="stype == 1 && !isDesktop" v-loading="isLoading">
+            <div class="title_box" v-if="!testArray.length"
+              style="display: flex;align-items: center;justify-content: center;height: 500px;">
+              暂无内容
+            </div>
+            <div class="title_box" v-for="(item, index) in testArray" :key="index">
+              <div class="title" style="font-size: 16px;display: flex;justify-content: space-between;align-items: center;">
+                <!-- <el-tooltip :content="selectType(item)" placement="top" effect="dark">
+                  <span class="test_icon"
+                    :class="{ test_icon_check: item.type == 1 && item.atype == 2, test_icon_checkO: item.type == 1 && item.atype == 1, test_icon_gap: item.type == 3, test_icon_file: item.type == 5, test_course_file: item.type == 6, test_eva_file: item.type == 7,test_icon_time: item.type == 8 }"></span>
+                </el-tooltip> -->
+                <div style="display: flex;">
+                  <div class="topicTitCss">第{{ index+1 }}题:</div>
+                  <el-tooltip :content="item.title" placement="top" effect="dark">
+                    <div style="width: 100px;overflow: hidden;white-space: nowrap;text-overflow: ellipsis;">{{ item.title }}</div>
+                  </el-tooltip>
+
+                  
+                </div>
+                <div style="display: flex;">
+                  <!-- <div v-if="item.type==7" style="right:0;position: absolute;">平均分:{{ getAverageScore(index) }}</div> -->
+                  <div style="color: rgba(0, 0, 0, 0.4);display: flex;align-items: center;">[{{ selectType(item) }}]</div>
+                  <!-- <el-button style="padding: 5px;" v-if="item.type == 5 && item.array.length>0" class="title_downBtn" type="primary" size="small" @click.stop="downloadFileType5(item.array,item.title)">批量下载附件</el-button> -->
+                </div>
+              </div>
+              <div class="detail" v-if="item.detail">{{ item.detail }}</div>
+              <div class="content1" style="width:100%;display: block;" v-if="item.type == 1">
+                <div class="left" style="width:100%" v-if="!item.cut">
+                  <div class="isDesktopTitle">
+                    <div>选项</div>
+                    <div>小计</div>
+                    <div>比例</div>
+                  </div>
+                  <div class="isDesktopTitle" v-for="(data, index2) in item.array" :key="index + '-' + index2">
+                    <!-- <span> -->
+                      <el-tooltip :content="data.name" placement="top" effect="dark">
+                        <!-- content to trigger tooltip here -->
+                        <div>{{ data.name }}</div>
+                      </el-tooltip>
+                    <!-- </span> -->
+                    <div>{{ data.count }}</div>
+                    <div>
+                      {{ data.count ? parseFloat(((data.count / item.count) * 100).toFixed(2)) : 0 }}
+                       <!-- <el-progress style="display: flex;align-items: center;" :stroke-width="12" color="#3681fc"
+                        :percentage="data.count ? parseFloat(((data.count / item.count) * 100).toFixed(2)) : 0"></el-progress> -->
+                    </div>
+                  </div>
+                </div>
+                <div class="right isDesktopRight" v-if="item.cut">
+                  <checkPie :dataJ="item.array"></checkPie>
+                </div>
+                <div class="cutBtnBlockCss">
+                  <div class="cutBtnCss" @click="item.cut=!item.cut">{{ item.cut?'查看详情':'查看视图' }}</div>
+                </div>
+              </div>
+              <div class="content2"  style="width:100%;display: block;" v-if="item.type == 3">
+                <div class="left" style="width:100%" v-if="!item.cut">
+                  <div class="title">
+                    <span>序号</span>
+                    <span>词频</span>
+                    <span>答案文本</span>
+                  </div>
+                  <div class="data" v-for="(data, index2) in item.array" :key="index + '-' + index2">
+                    <span>{{ index2 + 1 }}</span>
+                    <span>{{ data.count }}次</span>
+                    <el-tooltip :content="data.name" placement="top" effect="dark">
+                      <!-- content to trigger tooltip here -->
+                      <span>{{ data.name }}</span>
+                    </el-tooltip>
+                  </div>
+                </div>
+                <div class="right isDesktopRight" v-if="item.cut">
+                  <wordcloud :data="item.array" nameKey="name" valueKey="count" :showTooltip="false"
+                    :wordClick="wordClickHandler">
+                  </wordcloud>
+                </div>
+                <div class="cutBtnBlockCss">
+                  <div class="cutBtnCss" @click="item.cut=!item.cut">{{ item.cut?'查看详情':'查看视图' }}</div>
+                </div>
+              </div>
+              <div class="content3" v-if="item.type == 5">
+                <div class="file" v-for="(file, index2) in item.array" :key="index + '-' + index2"
+                  @click.stop="checkFile(file)">
+                  <img class="download" src="../../../../assets/icon/fileIcon/download.png"
+                    @click.stop="downloadFile(file)" :style="{ right: '10px' }" />
+                  <img class="img" :src="wordIcon" alt="" v-if="file.type == 1" />
+                  <img class="img" :src="videoIcon" alt="" v-if="file.type == 2" />
+                  <img class="img" :src="file.url" alt="" v-if="file.type == 3" />
+                  <img class="img" :src="wordIcon" alt="" v-if="file.type == 4" />
+                  <img class="img" :src="fileIcon" alt="" v-if="file.type == 5" />
+                  <div class="name">
+                    <el-tooltip :content="file.name" placement="top" effect="dark">
+                      <span>{{ file.name }}</span>
+                    </el-tooltip>
+                  </div>
+                </div>
+              </div>
+              <div class="content4" v-if="item.type == 6">
+                <div class="out_box" v-for="(item, index) in item.courseArray" :key="index + '-' + index2">
+                  <div class="tup">
+                    <img :src="item.cover != null && item.cover != ''
+    ? JSON.parse(item.cover).length > 0
+      ? JSON.parse(item.cover)[0].url
+      : mr
+    : mr
+    " alt />
+                    <div class="bottom_box">
+                      <div>
+                        <el-tooltip :content="item.title" popper-class="text_tooltip" placement="top" effect="dark">
+                          <span>{{ item.title }}</span>
+                        </el-tooltip>
+                      </div>
+                      <div class="kc_t">
+                        <span>{{ item.username }}</span>
+                        <span>{{ item.state == 1 ? '阶段模式' : item.state == 2 ? '任务模式' : '极简模式' }}</span>
+                      </div>
+                      <div class="kc_time">
+                        <span style="color: #717C8D">创建日期:</span>{{ item.time }}
+                      </div>
+                      <div class="kc_time">
+                        <span style="color: #717C8D">修改日期:</span>{{ item.update_at }}
+                      </div>
+                    </div>
+                  </div>
+                </div>
+                <!-- <div class="courses" v-for="(courses, index2) in item.array" :key="index + '-' + index2">
+                  {{ courses }}
+                </div> -->
+              </div>
+              <div class="content1" style="width:100%;display: block;" v-if="item.type == 7">
+                <div class="left" style="width:100%" v-if="!item.cut">
+                  <div class="isDesktopTitle">
+                    <div>评分</div>
+                    <div>小计</div>
+                    <div style="width: 120px;">比例</div>
+                  </div>
+                  <div class="isDesktopTitle" v-for="(data, index2) in item.array" :key="index + '-' + index2">
+                    <!-- <span> -->
+                    <div>{{ data.name }}</div>
+                    <!-- </span> -->
+                    <div>{{ data.count }}</div>
+                    <div style="width: 120px;">
+                      {{ data.count ? parseFloat(((data.count / item.count) * 100).toFixed(2)) : 0 }}
+                      <!-- <el-progress style="display: flex;align-items: center;" :stroke-width="12" color="#3681fc"
+                        :percentage="data.count ? parseFloat(((data.count / item.count) * 100).toFixed(2)) : 0"></el-progress> -->
+                    </div>
+                  </div>
+                </div>
+                <div class="right isDesktopRight"  v-if="item.cut">
+                  <checkPie :dataJ="item.array"></checkPie>
+                </div>
+                <div class="cutBtnBlockCss">
+                  <div class="cutBtnCss" @click="item.cut=!item.cut">{{ item.cut?'查看详情':'查看视图' }}</div>
+                </div>
+
+              </div>
+              <div class="content2"  style="width:100%;display: block;" v-if="item.type == 8">
+                <div class="left" style="width:100%" v-if="!item.cut">
+                  <div class="title">
+                    <span>序号</span>
+                    <span>词频</span>
+                    <span>日期</span>
+                  </div>
+                  <div class="data" v-for="(data, index2) in item.array" :key="index + '-' + index2">
+                    <span>{{ index2 + 1 }}</span>
+                    <span>{{ data.count }}次</span>
+                    <el-tooltip :content="data.name" placement="top" effect="dark">
+                      <!-- content to trigger tooltip here -->
+                      <span>{{ data.name }}</span>
+                    </el-tooltip>
+                  </div>
+                </div>
+                <div class="right isDesktopRight" v-if="item.cut">
+                  <wordcloud :data="item.array" nameKey="name" valueKey="count" :showTooltip="false"
+                    :wordClick="wordClickHandler">
+                  </wordcloud>
+                </div>
+                <div class="cutBtnBlockCss">
+                  <div class="cutBtnCss" @click="item.cut=!item.cut">{{ item.cut?'查看详情':'查看视图' }}</div>
+                </div>
+              </div>
+            </div>
+          </div>
+          <div class="table_content" v-if="stype == 2 && isDesktop">
             <el-table class="el-table" ref="table" :data="worksArray" border :fit="true" :key="2" v-loading="isLoading"
               style="width: 100%" :header-cell-style="{ background: '#f1f1f1', fontSize: '17px' }"
               @filter-change="handleFilterChange">
@@ -295,7 +522,7 @@
                   </div>
                 </template>
               </el-table-column>
-              <el-table-column label="操作" width="300px" fixed="right">
+              <el-table-column label="操作" width="300px" fixed="right" v-if="isN!=1">
 
                 <template slot-scope="scope">
                   <el-button @click="getTest(scope.row)" type="primary" size="small">查看</el-button>
@@ -305,6 +532,205 @@
               </el-table-column>
             </el-table>
           </div>
+          <div class="table_content" v-if="stype == 2 && !isDesktop">
+
+            <div v-for="(i,index) in worksArray"  :key="i.id" class="isDesktopTable_content">
+              <div class="isDTitle CutCss">
+                <div style="font-size: 16px;font-weight: 600;">{{ i.name }}</div>
+                <div :style="'font-size: 14px',i.cut?'color:rgba(54, 129, 252, 1)':'color: rgba(0, 0, 0, 0.6);'">{{ i.time }}</div>
+                <div @click="i.cut=!i.cut">
+                  <img v-if="!i.cut" src="../../../../assets/icon/fileIcon/downImg.png" alt="">
+                  <img v-else src="../../../../assets/icon/fileIcon/upImg.png" alt="">
+                </div>
+              </div>
+              <div v-if="i.cut">
+                <div class="isDBri">
+                  <div>序号:{{ i.time }}</div>
+                  <div>提交时间:{{ i.time }}</div>
+                  <div>评课人:</div>
+                </div>
+                <div style="height: 1px;background-color: #717C8D;width: 100%;margin-bottom: 10px;"></div>
+                <div>
+                  <div v-for="(k,kin) in chapters" :key="k.id" class="isCTiBlc">
+                    <div v-if="k.type == 1">
+                      <div class="isDTitle2">
+                        <div style="display: flex;justify-content: space-between;">
+                          <div style="display: flex;">
+                            <span class="topicTitCss">第{{kin+1}}题:</span>
+                            <div class="isDTitle2JsonTit">
+                              {{ k.json.title }}
+                            </div>
+                          </div>
+                          <div style="color: rgba(0, 0, 0, 0.4);">[{{ selectType2(k.type,k.json.type) }}]</div>  
+                        </div>
+                        <div class="IsDAnswer">
+                          <div v-for="(r, index2) in i.array[kin].json.answer2"
+                          :key="index + '-' + index2">
+                          {{ i.array[kin].json.array[r].option }}
+                          </div>
+                        </div>
+                      </div>
+                    </div>
+                    <div v-if="k.type == 3 || k.type == 8">
+                      <div class="isDTitle2">
+                        <div style="display: flex;justify-content: space-between;">
+                          <div style="display: flex;">
+                            <span class="topicTitCss">第{{kin+1}}题:</span>
+                            <div class="isDTitle2JsonTit">
+                              {{ k.json.title }}
+                            </div>
+                          </div>
+                          <div style="color: rgba(0, 0, 0, 0.4);">[{{ selectType2(k.type,k.json.type) }}]</div>
+                        </div>
+                        <div class="IsDAnswer">
+                          {{ i.array[kin].json.answer2 }}
+                        </div>
+                      </div>
+                    </div>
+                    <div v-if="k.type == 5">
+                      <div class="isDTitle2">
+                        <div style="display: flex;justify-content: space-between;">
+                          <div style="display: flex;">
+                            <span class="topicTitCss">第{{kin+1}}题:</span>
+                            <div class="isDTitle2JsonTit">
+                              {{ k.json.title }}
+                            </div>
+                          </div>
+                          <div style="color: rgba(0, 0, 0, 0.4);">[{{ selectType2(k.type,k.json.type) }}]</div>
+                        </div>
+                        <div class="IsDAnswer">
+                          <div class="IsDFile" v-for="(file, index2) in i.array[kin].json.file"
+                            :key="index + '-' + index2" @click.stop="checkFile(file)">
+                            <img class="IsDownload" src="../../../../assets/icon/fileIcon/download.png"
+                              @click.stop="downloadFile(file)" :style="{ right: '10px' }" />
+                            <img class="IsDImg" :src="wordIcon" alt="" v-if="file.type == 1" />
+                            <img class="IsDImg" :src="videoIcon" alt="" v-if="file.type == 2" />
+                            <img class="IsDImg" :src="file.url" alt="" v-if="file.type == 3" />
+                            <img class="IsDImg" :src="wordIcon" alt="" v-if="file.type == 4" />
+                            <img class="IsDImg" :src="fileIcon" alt="" v-if="file.type == 5" />
+                            <div class="name" style="height: 30px;background-color: #ccc;overflow: hidden;white-space: nowrap;text-overflow: ellipsis;">
+                              <!-- <el-tooltip :content="file.name" placement="top" effect="dark"> -->
+                                {{ file.name }}
+                              <!-- </el-tooltip> -->
+                            </div>
+                          </div>
+                        </div>
+                      </div>
+                    </div>
+                    <div v-if="k.type.type == 6">
+                      <div class="isDTitle2">
+                        <div style="display: flex;justify-content: space-between;">
+                          <div style="display: flex;">
+                            <span class="topicTitCss">第{{kin+1}}题:</span>
+                            <div class="isDTitle2JsonTit">
+                              {{ k.json.title }}
+                            </div>
+                          </div>
+                          <div style="color: rgba(0, 0, 0, 0.4);">[{{ selectType2(k.type,k.json.type) }}]</div>
+                        </div>
+                        <div class="IsDAnswer">
+                          {{ i.array[kin].json.answer2 }}
+                        </div>
+                      </div>
+                    </div>
+                    <div v-if="k.type == 7">
+                      <div class="isDTitle2">
+                        <div style="display: flex;justify-content: space-between;">
+                          <div style="display: flex;">
+                            <span class="topicTitCss">第{{kin+1}}题:</span>
+                            <div class="isDTitle2JsonTit">
+                              {{ k.json.title }}
+                            </div>
+                          </div>
+                          <div style="color: rgba(0, 0, 0, 0.4);">[{{ selectType2(k.type,k.json.type) }}]</div>
+                        </div>
+                        <div class="IsDAnswer">
+                          {{ getScore(i.array[index].json) }}
+                        </div>
+                      </div>
+                    </div>
+                  </div>
+
+                </div>
+                
+                <div style="width: 100%;display: flex;justify-content: end;">
+                  <div @click="i.cut=!i.cut" style="display: flex;flex-direction: column;align-items: center">
+                    <img src="../../../../assets/icon/fileIcon/retractImg.png" alt="">
+                    <div style="color: rgba(0, 0, 0, 0.4);font-size: 16px;">收起</div>
+                  </div>
+                </div>
+              </div>
+
+              <div style="height: 1px;background-color: #717C8D;width: 100%;margin-bottom: 10px;"></div>
+
+            </div>
+
+
+
+            <!-- <el-table class="el-table" ref="table" :data="worksArray" border :fit="true" :key="2" v-loading="isLoading"
+              style="width: 100%" :header-cell-style="{ background: '#f1f1f1', fontSize: '17px' }"
+              @filter-change="handleFilterChange">
+              <el-table-column fixed label="序号" width="80px" align="left">
+                <template slot-scope="scope">
+                  {{ scope.$index + 1 }}
+                </template>
+              </el-table-column>
+              <el-table-column fixed prop="name" label="提交人" width="120px" align="left">
+              </el-table-column>
+              <el-table-column prop="time" label="提交时间" width="170px" align="left">
+								<template slot-scope="scope">
+									<span :style="`${testJson.overtime&&new Date(testJson.overtime)<new Date(scope.row.time)?'color:#d12920':''}`">{{ scope.row.time }}</span>
+								</template>
+              </el-table-column>
+              <el-table-column v-for="(item, index) in chapters" :key="index" :label="item.json.title"
+                :min-width="item.type == 5 ? 200 : 150" align="left" :filters="item.type == 1 ? item.nameFilters : item.type ==  6? item.nameFilters : null"
+                :filter-method="item.type == 1 ? (value, row) => { return filterName(value, row, index) } : item.type == 6?(value, row) => { return filterCourse(value, row, index)}:null"
+                :filter-placement="item.type == 1 || item.type ==6 ? filterPlacement : null">
+
+                <template slot-scope="scope">
+                  <div v-if="scope.row.array[index].type == 1" style="display: flex; flex-wrap: wrap;">
+                    <span class="answer_type" v-for="(answer2, index2) in scope.row.array[index].json.answer2"
+                      :key="index + '-' + index2">{{ scope.row.array[index].json.array[answer2].option }}</span>
+                  </div>
+                  <div v-if="scope.row.array[index].type == 3 || scope.row.array[index].type == 8" style="display: flex; flex-wrap: wrap;">
+                    {{ scope.row.array[index].json.answer2 }}
+                  </div>
+                  <div v-if="scope.row.array[index].type == 5" style="display: flex; flex-wrap: wrap;"
+                    class="table_file">
+                    <div class="file" v-for="(file, index2) in scope.row.array[index].json.file"
+                      :key="index + '-' + index2" @click.stop="checkFile(file)">
+                      <img class="download" src="../../../../assets/icon/fileIcon/download.png"
+                        @click.stop="downloadFile(file)" :style="{ right: '10px' }" />
+                      <img class="img" :src="wordIcon" alt="" v-if="file.type == 1" />
+                      <img class="img" :src="videoIcon" alt="" v-if="file.type == 2" />
+                      <img class="img" :src="file.url" alt="" v-if="file.type == 3" />
+                      <img class="img" :src="wordIcon" alt="" v-if="file.type == 4" />
+                      <img class="img" :src="fileIcon" alt="" v-if="file.type == 5" />
+                      <div class="name">
+                        <el-tooltip :content="file.name" placement="top" effect="dark">
+                          <span>{{ file.name }}</span>
+                        </el-tooltip>
+                      </div>
+                    </div>
+                  </div>
+                  <div v-if="scope.row.array[index].type == 6" style="display: flex; flex-wrap: wrap;">
+                    {{ scope.row.array[index].json.answer2}}
+                  </div>
+                  <div v-if="scope.row.array[index].type == 7" style="display: flex; flex-wrap: wrap;">
+                    {{ getScore(scope.row.array[index].json) }}
+                  </div>
+                </template>
+              </el-table-column>
+              <el-table-column label="操作" width="300px" fixed="right" v-if="isN!=1">
+
+                <template slot-scope="scope">
+                  <el-button @click="getTest(scope.row)" type="primary" size="small">查看</el-button>
+                  <el-button @click="setWordHtml(scope.row)" type="primary" size="small">导出答题信息</el-button>
+                  <el-button @click="deleteTest(scope.row.id)" type="primary" size="small">删除</el-button>
+                </template>
+              </el-table-column>
+            </el-table> -->
+          </div>
           <div class="table_content" v-if="stype == 3">
             <div class="student_table">
               <el-table ref="table" :data="tableData" border :fit="true" v-loading="isLoading" style="width: 100%"
@@ -319,9 +745,9 @@
                     <div>{{ scope.row.type == 3 ? '是' : '否' }}</div>
                   </template>
                 </el-table-column>
-                <el-table-column label="操作" width="300px">
+                <el-table-column label="操作" width="300px"  v-if="isDesktop">
 
-                  <template slot-scope="scope">
+                  <template slot-scope="scope" >
                     <el-button @click="getTest(scope.row)" type="primary" size="small">查看</el-button>
                     <el-button @click="setWordHtml2(scope.row)" type="primary" size="small">导出答题信息</el-button>
                     <el-button @click="deleteTest(scope.row.id)" type="primary" size="small">删除</el-button>
@@ -338,7 +764,7 @@
         </div>
       </div>
     </div>
-    <share-box :testJson="testJson" :dialogVisibleShare.sync="dialogVisibleShare"></share-box>
+    <share-box :testJson="testJson" :TeachingValue="TeachingValue" :TeachName="TeachNameCpt"   :dialogVisibleShare.sync="dialogVisibleShare"></share-box>
     <wpdf :dialogVisiblePdf.sync="dialogVisiblePdf" :url="wurl"></wpdf>
     <wVideo :dialogVisibleVideo.sync="dialogVisibleVideo" :url="wurl"></wVideo>
     <wOffice :dialogVisibleOffice.sync="dialogVisibleOffice" :url="wurl"></wOffice>
@@ -420,12 +846,18 @@ export default {
       role: this.$route.query.role,
       cid: this.$route.query.cid,
       isN: this.$route.query.isN,
+      screenWidth: window.innerWidth,
+      isDesktop: false,
       title: "",
       testType: [],
       see: false,
       cJson: [],
       loading: false,
       look: "",
+      TeachingOptions:[],
+      TeachingValue :'',
+      SubmitTimeOptions: [],
+      SubmitTime: '',
       tableHeight: 500,
       isLoading: false,
       pageSize: 10,
@@ -463,6 +895,10 @@ export default {
   },
   watch: {},
   computed: {
+    TeachNameCpt: function () {
+        // `this` 指向 vm 实例
+        return this.TeachingOptions.filter(i => {return i.id == this.TeachingValue})
+    },
     // vcWords() {
     //   return function (array) {
     //     let _array = [];
@@ -507,9 +943,57 @@ export default {
           return '日期'
         }
       };
-    }
+    },
+    selectType2() {
+      return function (val1,val2) {
+        if (val1 == 1 && val2 == 2) {
+          return '多选题'
+        } else if (val1 == 1 && val2 == 1) {
+          return '单选题'
+        } else if (val1 == 3) {
+          return '问答题'
+        } else if (val1 == 5) {
+          return '附件'
+        } else if (val1 == 6) {
+          return '课程'
+        } else if (val1 == 7) {
+          return '评分'
+        } else if (val1 == 8) {
+          return '日期'
+        }
+      };
+    },
+		// 获取评分的平均分
+		getAverageScore(){
+			return (_index)=>{
+				let _result = 0;
+				let _sum = 0;
+				this.worksArray.forEach(i1=>{
+					_result+=i1.array[_index].json.answer2
+					_sum+=1;
+				})
+				_result = _sum ? (_result/_sum).toFixed(2) : 0
+				return _result ? _result : 0;
+			}
+		}
   },
   methods: {
+    //获取教研室列表
+    getClass2() {
+      let params = {
+          oid: this.oid,
+      };
+      this.ajax
+          .get(this.$store.state.api + "selectTeacherOfficeBySchool", params)
+          .then((res) => {
+              this.TeachingOptions = res.data[0];
+              console.log('this.TeachingOptions',this.TeachingOptions);
+          })
+          .catch((err) => {
+              this.isLoading = false;
+              console.error(err);
+          });
+    },
     filterName(value, row, index) {
       let name = []
       for (var i = 0; i < row.array[index].json.answer2.length; i++) {
@@ -618,13 +1102,28 @@ export default {
       this.isLoading = true;
       let params = {
         cid: this.cid,
-        cn: this.courseName
+        cn: this.courseName,
+        tim : !this.SubmitTime? '' : this.SubmitTime,
+        tea: this.TeachingValue
       };
       this.ajax
-        .get(this.$store.state.api + "getTestWorksNoPage", params)
+        .get(this.$store.state.api + "getTestWorksNoPageCopy", params)
         .then(async (res) => {
-          this.isLoading = false;
           this.testJson = res.data[0][0]
+          console.log('this.testJson',JSON.parse(JSON.stringify(this.testJson)));
+          if (this.testJson.juriP) {
+            let ajuri2 =  this.testJson.juri2.split (',');
+            let ajurip =  this.testJson.juriP.split (',');
+            let JData = ajuri2.reverse()
+            this.TeachingOptions = JData.map((key, index) => ({
+              id : key,
+              name: ajurip[index]
+            }));
+          }else{
+            this.getClass2()
+          }
+          // console.log('dddd',this.TeachingOptions);
+
           this.works = res.data[1]
           this.iscount = res.data[2][0].count
           this.pcount = res.data[3][0].count
@@ -642,7 +1141,7 @@ export default {
                 let _json2 = _json[ja].json
                 if (_json[ja].type == 6) {
                   let _cjson = await this.getCourse(_json2.answer2)
-                  _json2.answer2 =  _cjson.title
+                  _json2.answer2 =  _cjson ? _cjson.title : ''
                 }
               }
               array.push({
@@ -652,6 +1151,7 @@ export default {
                 name: this.works[i].username ? this.works[i].username : '匿名',
                 time: this.works[i].time,
                 array: _json,
+                cut:0,
                 courseJson: JSON.parse(this.works[i].courseJson),
               })
             }
@@ -661,6 +1161,7 @@ export default {
             let el = this.chapters[i]
             let topic = {
               type: el.type,
+              cut: 0,
               title: el.json ? el.json.title : '',
               detail: el.json ? el.json.detail : '',
               atype: el.json ? el.json.type : '',
@@ -688,7 +1189,7 @@ export default {
               topic.array = _answer
               topic.courseArray = [];
 							let params = {
-								cid:topic.array.join(",")
+								cid:topic.array ? topic.array.join(",") : ''
 							}
 
 							let data = await this.ajax.get(this.$store.state.api + 'getCourseInfoTestAll',params);
@@ -758,11 +1259,13 @@ export default {
                 }
               }
             }
-            console.log(topic)
+            console.log('topictopictopictopic',topic)
             testArray.push(topic)
           }
           this.testArray = testArray
           this.worksArray = array
+          this.isLoading = false;
+          
         })
         .catch((err) => {
           console.error(err);
@@ -1246,7 +1749,7 @@ export default {
           }
         } else if (item.type == 6 && item.json.answer2) {
             let _cjson = await this.getCourse(item.json.answer2)
-            let _option = `<div style='margin:10px 0 0 40px;'>打分课程:${_cjson.title}</div>`
+            let _option = `<div style='margin:10px 0 0 40px;'>打分课程:${ _cjson ? _cjson.title : ''}</div>`
             _test += _option
         } else if (item.type == 7 && item.json.answer2 ) {
             let _score = this.getScore2(item.json)
@@ -1444,6 +1947,10 @@ export default {
           array.push(i)
         }
         return item.answer2 ? array[item.answer2] : ''
+    },
+    checkScreenSize() {
+      this.screenWidth = window.innerWidth;
+      this.isDesktop = this.screenWidth > 750; // 你可以根据需要调整这个阈值
     },
 		downloadFileType5(fileData,title="附件"){
 			let data = fileData;
@@ -1511,13 +2018,17 @@ export default {
 		},
   },
   beforeDestroy() {
-    document.getElementsByTagName('html')[0].style.overflow = ''
+    document.getElementsByTagName('html')[0].style.overflow = '';
+    window.removeEventListener("resize", this.checkScreenSize);
   },
   mounted() {
+    this.checkScreenSize();
+    window.addEventListener("resize", this.checkScreenSize);
     document.getElementsByTagName('html')[0].scrollTop = 0
     document.getElementsByTagName('html')[0].style.overflow = 'hidden'
     this.$nextTick(function () {
       this.getData();
+      // this.getClass2()
       this.changeHeight()
     });
   },
@@ -1529,7 +2040,68 @@ export default {
   height: 100% !important;
   /* margin: 0 20px 0 20px; */
 }
+.cutBtnBlockCss{
+  width: 100%;display: flex;justify-content: end;
+}
+.cutBtnCss{
+  width: 68px;
+  height: 27px;
+  font-size: 14px;
+  border-radius: 5px;
+  display: flex;
+  color: rgba(54, 129, 252, 1);
+  justify-content: center;
+  align-items: center;
+  margin-top: 10px;
+  border: 1px rgba(54, 129, 252, 1) solid;
+}
+.isDesktopRight{
+  width:100% !important;
+  margin:0 !important;
+  height: 300px !important;
+  border: none !important;
+}
+.isDTitle2JsonTit{
+  width: 130px;
+  color: rgba(0, 0, 0, 0.9);
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+}
+.IsDAnswer{
+  margin: 20px 0 30px;color: rgba(0, 0, 0, 0.6);
+}
 
+.CutCss{
+  height: 60px;
+  line-height: 60px;
+}
+.topicTitCss{
+  color:  rgba(0, 0, 0, 0.9);
+  font-weight: 600;
+  margin-right: 5px;
+}
+.IsDFile{
+  width: 150px;
+  height: 120px;
+  border-radius: 10px;
+  position: relative;
+  display: flex;
+  flex-direction: column;
+  overflow: hidden;
+  margin-bottom: 5px;
+}
+.IsDownload{
+  position: absolute;
+  width: 30px;
+  top: 5px;
+  right: 5px;
+}
+.IsDImg{
+  width: 100%;
+  height: 70px;
+  flex: 1;
+}
 .pb_content_body {
   width: 100% !important;
   height: 100%;
@@ -1705,7 +2277,11 @@ export default {
   cursor: pointer;
   position: relative;
 }
-
+.search_nav>.isDesktopRightCut{
+  display: flex;
+  justify-content: space-between;
+  width: 60%;
+}
 .search_nav>.right>span+span {
   margin-left: 35px;
 }
@@ -1732,6 +2308,21 @@ export default {
   margin-left: auto;
 }
 
+.search_nav>.right>span.active2 {
+  color: #3681FC;
+  font-weight: 600;
+}
+.search_nav>.right>span.active2::before {
+  content: "";
+  position: absolute;
+  bottom: -10px;
+  width: 100%;
+  height: 3px;
+  background: #3681fc;
+  left: 50%;
+  transform: translateX(-50%);
+}
+
 
 .student_input>>>.el-input__inner {
   height: 40px;
@@ -1834,6 +2425,27 @@ export default {
 .title_content>.title_box>.content1>.left>.data>span:nth-child(3) {
   width: 320px;
 }
+.isDesktopTitle{
+  display: flex;
+  justify-content: space-around;
+}
+.isDesktopTitle >div {
+  width: 60px;
+  height: 30px;
+  line-height: 30px;
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+}
+/* .isDesktopTitle:nth-child(1){
+  width: 60px;
+}
+.isDesktopTitle:nth-child(2){
+  width: 60px;
+}
+.isDesktopTitle:nth-child(3){
+  flex: 1;
+} */
 
 .title_content>.title_box>.content1>.left>.title {
   font-weight: 700;
@@ -1986,6 +2598,22 @@ export default {
 .table_content>>>.el-table td {
   padding: 5px 0;
 }
+.isDesktopTable_content{
+  width: 100%;
+}
+.isDTitle{
+  display: flex;
+  justify-content: space-between;
+}
+.isDBri{
+  display: flex;
+  padding: 15px 0;
+  font-size: 14px;
+  color: rgba(0, 0, 0, 0.4);
+  flex-direction: column;
+  height: 80px;
+  justify-content: space-between;
+}
 
 .answer_type {
   background: #F0F2F5;

+ 15 - 0
src/components/pages/test/examine/index.vue

@@ -0,0 +1,15 @@
+<template>
+  <div>
+    审核页面
+  </div>
+</template>
+
+<script>
+export default {
+
+}
+</script>
+
+<style>
+
+</style>

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

@@ -40,7 +40,7 @@
                         <pie-1 :dataJ="dataJ"></pie-1>
                     </div>
                 </div>
-                <div class="data_box">
+                <div class="data_box" v-show="false">
                     <div class="left">
                         <div class="title">教师完成情况</div>
                         <div class="box">

+ 20 - 2
src/components/pages/test/shareBox/index.vue

@@ -8,8 +8,9 @@
                     <span>{{ testJson.title }}</span>
                 </div>
                 <div class="info" >
+                    <!-- {{ reversedMessage }} -->
                     <span>表单范围:</span>
-                    <span>{{ testJson.juriP ? testJson.juriP : '所有人' }}</span>
+                    <span>{{ reversedMessage }}</span>
                 </div>
                 <div class="info" v-if="testJson && testJson.overtime">
                     <span>截止时间:</span>
@@ -72,6 +73,12 @@ export default {
         testJson: {
             type: Object
         },
+        TeachingValue: {
+            type: String
+        },
+        TeachName: {
+            type: Array
+        }
     },
     data() {
         return {
@@ -83,6 +90,15 @@ export default {
             isSuo: true
         };
     },
+    computed: {
+        reversedMessage() {
+            if (this.TeachingValue == '') {
+                return this.testJson.juriP ? this.testJson.juriP : '所有人'
+            }else{
+                return this.TeachName ? this.TeachName[0].name :'所有人'
+            }
+        }
+    },
     methods: {
         handleClose(done) {
             this.close();
@@ -150,10 +166,12 @@ export default {
             // }
             let params = {
                 id: this.testJson.courseId,
+                tea: this.TeachingValue
             };
             this.ajax
-                .get(this.$store.state.api + "getTestWorkShare", params)
+                .get(this.$store.state.api + "getTestWorkShareCopy", params)
                 .then((res) => {
+                    console.log('res.datares.datares.datares.datares.datares.data',res.data);
                     let parray = res.data[0]
                     let is = res.data[1]
                     this.noCount = parray.length - is.length

+ 7 - 5
src/components/pages/testStudent/view/component/course.vue

@@ -10,7 +10,7 @@
             </div>
             <div class="choices" v-if="checkJson.courses.length">
                 <div class="course" @click="openCourse()">
-                    <div class="banner">
+                    <div class="banner" :style=" isN==1? 'width:140px;height:90px;' : ''">
                         <div v-if="tid" class="isRate">已评分</div>
                         <img :src="courseDetail.cover" alt="">
                     </div>
@@ -18,25 +18,25 @@
                         <div class="c_c">
                             <span>课程名称:</span>
                             <el-tooltip :content="courseDetail.title" placement="top" effect="dark">
-                                <span>{{ courseDetail.title }}</span>
+                                <span :style=" isN==1? 'max-width:75px;' : ''">{{ courseDetail.title }}</span>
                             </el-tooltip>
                         </div>
                         <div class="c_c">
                             <span>课程类型:</span>
                             <span v-if="!courseDetail.name">{{ '暂无' }}</span>
                             <el-tooltip v-else :content="courseDetail.name" placement="top" effect="dark">
-                                <span>{{ courseDetail.name }}</span>
+                                <span :style=" isN==1? 'max-width:75px;' : ''">{{ courseDetail.name }}</span>
                             </el-tooltip>
                         </div>
                         <div class="c_c">
                             <span>创建人:</span>
-                            <span>{{ courseDetail.username }}</span>
+                            <span :style=" isN==1? 'max-width:75px;' : ''">{{ courseDetail.username }}</span>
                         </div>
                         <div class="c_c">
                             <span>协作者:</span>
                             <span v-if="!courseDetail.xieName">{{ '暂无' }}</span>
                             <el-tooltip v-else :content="courseDetail.xieName" placement="top" effect="dark">
-                                <span>{{ courseDetail.xieName }}</span>
+                                <span :style=" isN==1? 'max-width:75px;' : ''">{{ courseDetail.xieName }}</span>
                             </el-tooltip>
                         </div>
                     </div>
@@ -85,6 +85,8 @@ export default {
                 1: { name: '附件' },
             },
             userid: this.$route.query.userid,
+            isN: this.$route.query.isN,
+
             checkJson: undefined,
             progress: 0,
             isFinishSize: 0,

+ 4 - 2
src/components/pages/testStudent/view/component/eva.vue

@@ -8,8 +8,8 @@
             <div class="detail" v-if="checkJson.detail" v-html="checkJson.detail"
                 style="color: #00000099;margin-top: 5px;">
             </div>
-            <div class="choices">
-                <div class="score" :class="{active: (checkJson.answer2 || checkJson.answer2 === 0) && (checkJson.answer2 > index || checkJson.answer2 === index)}" @click="score(index)" v-for="(item, index) in (parseInt(checkJson.big) - parseInt(checkJson.small) + 1)" :key="index">{{ parseInt(checkJson.small) + index }}</div>
+            <div class="choices" :style=" isN==1? 'justify-content: space-around;width:100%' : ''">
+                <div class="score" :style=" isN==1? 'width:25px;height:25px;margin:0;' : ''" :class="{active: (checkJson.answer2 || checkJson.answer2 === 0) && (checkJson.answer2 > index || checkJson.answer2 === index)}" @click="score(index)" v-for="(item, index) in (parseInt(checkJson.big) - parseInt(checkJson.small) + 1)" :key="index">{{ parseInt(checkJson.small) + index }}</div>
             </div>
         </div>
     </div>
@@ -40,6 +40,8 @@ export default {
                 1: { name: '附件' },
             },
             userid: this.$route.query.userid,
+            isN: this.$route.query.isN,
+
             checkJson: undefined,
             progress: 0,
             isFinishSize: 0,

+ 5 - 3
src/components/pages/testStudent/view/component/file.vue

@@ -32,19 +32,19 @@
             <div class="choices">
                 <div class="uploadBtn" v-if="checktype == 1">
                     <div class="btn" @click.stop="addImg($event)">
-                        <span>添加本地文件</span>
+                        <span :style="isN==1? 'font-size: 12px;' : ''">添加本地文件</span>
                         <input type="file" accept="*" style="display: none" multiple="multiple"
                             @change="beforeUpload($event)" />
                     </div>
                     <div class="btn" @click="openFileBox()">
-                        <span>从资源库添加</span>
+                        <span :style="isN==1? 'font-size: 12px;' : ''">从资源库添加</span>
                     </div>
                     <div class="switch">
                         <el-switch
                             active-color="#3681fc"
                             v-model="isTong">
                         </el-switch>
-                        <span @click="isTong = !isTong">同步至资源库</span>
+                        <span :style="isN==1? 'font-size: 12px;' : ''" @click="isTong = !isTong">同步至资源库</span>
                     </div>
                 </div>
                 <div class="binfo_input">
@@ -197,6 +197,8 @@ export default {
                 1: { name: '附件' },
             },
             userid: this.$route.query.userid,
+            isN: this.$route.query.isN,
+
             checkJson: undefined,
             progress: 0,
             isFinishSize: 0,

+ 4 - 3
src/components/pages/testStudent/view/component/topic.vue

@@ -1,8 +1,8 @@
 <template>
   <div class="c_box">
     <div class="c_box_title">{{ title }}</div>
-    <div class="c_box_brief" v-if="brief">{{ brief }}</div>
-    <div class="c_box_score">
+    <div class="c_box_brief" :style="isN==1?'text-align:center':''" v-if="brief">{{ brief }}</div>
+    <div class="c_box_score" v-if="isN!=1">
       <span>总分:{{ score }}</span>
       <span v-if="name" style="margin-left: 10px;">答题人:{{ name }}</span>
       <span style="margin-left: 10px;">总得分:{{ score2 }}</span>
@@ -157,6 +157,7 @@ export default {
       checkArray: [],
       type: 1,
       page: 0,
+			isN: this.$route.query.isN,
       options2: {
         1: "选择题",
         // 2: "问答题",
@@ -261,7 +262,7 @@ export default {
         let checkArray = _json.filter((item) => {
           if (item.array) {
             item.array = item.array.filter((item2) => {
-              if (item2.ttype == 1 && item2.json && !item2.json.answer2 && item2.type != 6 && item.type != 7 && item.type != 8) {
+              if (item2.ttype == 1 && item2.json && !item2.json.answer2 && item2.type != 6 && item2.type != 7 && item2.type != 8) {
                 item2.json.answer2 = [];
               } else if (item2.ttype == 1 && item2.json && !item2.json.answer2 && item2.type == 6) {
                 item2.json.answer2 = this.gcourseid ? this.gcourseid : item2.json.courses[0];

+ 43 - 19
src/components/pages/testStudent/view/preview.vue

@@ -2,8 +2,8 @@
   <div class="pb_content" style="background: #F0F2F5;" v-loading="loading || isloading">
     <div class="pb_content_body" style="position: relative; margin: 0">
       <div class="right">
-        <div class="courseTop">
-          <div class="stepsNav">
+        <div class="courseTop" :style="`justify-content: ${isN==1?'flex-end':'space-between'};`">
+          <div class="stepsNav" v-if="isN !=1">
             <el-breadcrumb separator-class="el-icon-arrow-right">
               <el-breadcrumb-item :to="{
     path:
@@ -39,13 +39,14 @@
           <div class="r_pub_button_retrun" @click="retrunCourse">返回</div>
         </div>
         <div class="step_box">
-          <div class="edit_top">
+          <div class="edit_top" :style="isN==1?'border-bottom:none;justify-content:space-between;padding:10px':''">
+						<div v-if="isN==1" class="edit_title"  :style=" isN==1? 'margin-left : 12px' : ''">提交记录</div>
             <div class="op_btn">
-							<el-button type="primary" size="small" @click="autoFill" v-if="showAutoFillBtn">智能填写</el-button>
-              <el-button type="primary" size="small" @click="refresh" v-if="isReset">刷新</el-button>
-              <el-button type="primary" size="small" @click="reset">重置</el-button>
-              <el-button type="primary" size="small" @click="save" v-if="type != 3">保存</el-button>
-              <el-button type="primary" size="small" @click="publish">提交</el-button>
+							<el-button type="primary" :style=" isN==1? 'padding: 5px 10px;' : ''" size="small" @click="autoFill" v-if="(showAutoFillBtn && isN!=1)">智能填写</el-button>
+              <el-button type="primary" :style=" isN==1? 'padding: 5px 10px;' : ''" size="small" @click="refresh" v-if="isReset">刷新</el-button>
+              <el-button :type="isN!=1?'primary':'info'" :style=" isN==1? 'padding: 5px 10px;' : ''" size="small" @click="reset">重置</el-button>
+              <el-button type="primary" :style=" isN==1? 'padding: 5px 10px;' : ''" size="small" @click="save" v-if="(type != 3 && isN!=1)">保存</el-button>
+              <el-button type="primary" :style=" isN==1? 'padding: 5px 10px;' : ''" size="small" @click="publish">提交</el-button>
             </div>
           </div>
           <topicVue :cJson.sync="cJson" :title="title" :brief="brief" ref="topicVue" v-if="!loading"
@@ -406,20 +407,20 @@ export default {
       let checkArray = _json.filter((item) => {
         if (item.array) {
           item.array = item.array.filter((item2) => {
-            if (item2.ttype == 1 && item2.json && !item2.json.answer2 && item2.type != 6 && item2.type != 7) {
+            if (item2.ttype == 1 && item2.json && !item2.json.answer2 && item2.type != 6 && item2.type != 7 && item2.type != 8) {
               item2.json.answer2 = [];
             }else if(item2.type == 6){
               item2.json.answer2 = this.courseid ? this.courseid : '';
-            }else if(item2.type == 7){
+            }else if(item2.type == 7 || item2.type == 8){
               item2.json.answer2 = '';
             }
             if (item2.array) {
               item2.array = item2.array.filter((item3) => {
-                if (item3.ttype == 1 && item3.json && !item3.json.answer2 && item3.type != 6 && item3.type != 7) {
+                if (item3.ttype == 1 && item3.json && !item3.json.answer2 && item3.type != 6 && item3.type != 7 && item3.type != 8) {
                   item3.json.answer2 = [];
                 }else if(item3.type == 6){
                   item3.json.answer2 = this.courseid ? this.courseid : '';
-                }else if(item3.type == 7){
+                }else if(item3.type == 7 || item3.type == 8){
                   item3.json.answer2 = '';
                 }
                 return item3;
@@ -430,11 +431,11 @@ export default {
             );
           });
         }
-        if (item.ttype == 1 && item.json && !item.json.answer2 && item.type != 6 && item.type != 6 && item.type != 7) {
+        if (item.ttype == 1 && item.json && !item.json.answer2 && item.type != 6 && item.type != 6 && item.type != 7 && item.type != 8) {
           item.json.answer2 = [];
         }else if(item.type == 6){
           item.json.answer2 = this.courseid ? this.courseid : '';
-        }else if(item.type == 7){
+        }else if(item.type == 7 || item.type == 8){
           item.json.answer2 = '';
         }
         console.log(item.array);
@@ -466,11 +467,16 @@ export default {
           }
           console.log(this.testType);
           this.look = res.data[0][0].look
-          if (this.type == 3) {
-            this.getTestWorks2()
-          } else {
-            this.getTestWorks()
-          }
+         	if(this.isN!=1){
+						if (this.type == 3) {
+         	   this.getTestWorks2()
+         	 } else {
+         	   this.getTestWorks()
+         	 }
+				 	}else{
+						this.loading = false;
+						this.isReset = true;
+					}
           this.$forceUpdate();
 
         })
@@ -721,4 +727,22 @@ export default {
   margin: 0 auto;
   box-sizing: border-box;
 }
+
+.edit_title{
+	font-size: 22px;
+	margin-left: 30px;
+	position: relative;
+}
+
+.edit_title::after{
+	content: "";
+	width: 5px;
+	height: 100%;
+	background-color: #078DFF;
+	border-radius: 2px;
+	position: absolute;
+	left: -10px;
+	top: 0;
+}
+
 </style>

+ 9 - 0
src/router/index.js

@@ -128,6 +128,7 @@ import classroomObservation from '@/components/pages/classroomObservation/index'
 import contrastObservation from '@/components/pages/contrastObservation/index'//对比分析
 import pblCourse from '@/components/pages/pblCourse/index'
 import guide from '@/components/pages/pblCourse/guide'
+import testExamine from '@/components/pages/test/examine'
 
 // 全局修改默认配置,点击空白处不能关闭弹窗
 ElementUI.Dialog.props.closeOnClickModal.default = false
@@ -1100,6 +1101,14 @@ export default new Router({
 					meta:{
 						requireAuth:''//不需要鉴权
 					}
+				},
+                 {//pblCourse
+					path:"/testExamine",
+					name:"testExamine",
+					component:testExamine,
+					meta:{
+						requireAuth:''//不需要鉴权
+					}
 				}
     ]
 })

Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor