Browse Source

Merge branch 'beta'

lsc 1 year ago
parent
commit
4b022ffe5e

+ 1 - 1
dist/index.html

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

File diff suppressed because it is too large
+ 0 - 0
dist/static/css/app.c6b3db9bd366cad0eede8e07c529647f.css


File diff suppressed because it is too large
+ 0 - 0
dist/static/css/app.c6b3db9bd366cad0eede8e07c529647f.css.map


File diff suppressed because it is too large
+ 0 - 0
dist/static/css/app.e516004b3514e27d2f56aec941a118b7.css.map


File diff suppressed because it is too large
+ 0 - 0
dist/static/js/app.347b4d0288b40c5c7764.js


File diff suppressed because it is too large
+ 0 - 0
dist/static/js/app.347b4d0288b40c5c7764.js.map


File diff suppressed because it is too large
+ 0 - 0
dist/static/js/manifest.571c38d63f24b1ae9e16.js.map


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


BIN
src/assets/icon/course/edit.png


BIN
src/assets/icon/course/restart.png


+ 123 - 63
src/components/pages/aiAddCourse/addCourse.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="pb_content" style="background: #f0f2f5" v-loading="loading">
     <div class="pb_content_body" style="position: relative; margin: 0">
-      <div class="right">
+      <div class="right" :style="{width:promptShow ? 'calc(100% - 300px)' : '100%'}">
         <div class="courseTop">
           <div class="stepsNav">
             <el-breadcrumb separator-class="el-icon-arrow-right">
@@ -3703,6 +3703,9 @@
           </div>
         </div>
       </div>
+      <div class="leftBar" v-if="promptShow">
+        <aiTips title="课程描述优化" :detail="aiJson.aiDetail" />
+      </div>
     </div>
     <el-dialog title="提示" :visible.sync="dialogVisible" :append-to-body="true" width="25%" :before-close="handleClose"
       class="dialog_diy2 customWidth">
@@ -5067,6 +5070,7 @@ import evaBox from "../evaBox/index.vue";
 import EnglishVoice from "../EnglishVoice/index.vue";
 import aiBox from './aiBox.vue'
 import aiDialog from './aiDialog'
+import aiTips from './aiTips.vue'
 import { v4 as uuidv4 } from "uuid";
 
 export default {
@@ -5083,7 +5087,8 @@ export default {
     evaBox,
     EnglishVoice,
     aiBox,
-    aiDialog
+    aiDialog,
+    aiTips
   },
   data() {
     return {
@@ -5392,12 +5397,21 @@ export default {
       dialogVisibleAiD: false,
       aitype: "",
       aiJson: {
-        aiDetail: "",
+        aiDetail:"请根据<课程简要描述>设计一个名为<课程名字>的<课程学科>学科的,面向<面向年级>的项目式学习课程。",
+        aiOutline:"请根据<课程简要描述>及#补充参考资料为这个名为<课程名字>的<课程学科>学科的,面向<面向年级>的项目式学习课程设计序列教学活动(需要每个任务都需要至少50个token的详细描述),每个教学活动的活动设计(可以直接使用文件内容)以及每个教学活动的评价量规(学生能做到...)。",
+        aiTask:"请根据<教学任务教案>。",
+        aiDetail1:"请根据<课程描述>,重新设计该教学任务。任务需要至少50个token的详细描述,包含任务设计,评价标准。",
+        aiDetail2:"请你在考虑到整个课程的情况下,优化该任务描述和任务名:<任务名>:<任务描述>",
+        aiDetail3:"请你在考虑到整个课程的情况下,**重点考虑该任务及工具名和工具内容的情况下**,优化工具指引。",
+        aiDetail4:"请你在考虑到整个课程的情况下,**重点考虑该任务详情**以及工具的情况下,优化评价标准。",
+        aiTeacher:"请根据<任务大纲>为每个教学任务设计详细的教案,其中包括但不仅限于该任务的教学目标,教学过程,师生研讨,拓展,学生任务单,相关知识点的练习或Qui以及答案等。",
+        teacherDetail:"请根据<教案描述>重新设计该教案。其中包括但不仅限于该任务的教学目标,教学过程,师生研讨,拓展,学生任务单,相关知识点的练习或Qui以及答案等。",
       },
       aiText: "",
       aiCallBack: "",
       aiIndex: "",
       clickType: 1,
+      promptShow: false
     };
   },
   directives: {
@@ -12280,17 +12294,20 @@ export default {
           return;
         }
         this.aitype = "aiDetail"
-        this.aiText = `请根据${this.courseText}设计一个名为${this.courseName}的${sub.length ? sub.join(",") + "学科的" : ""},面向${this.getListClassC(this.checkboxList2)}的项目式学习课程。`
+        // this.aiText = `请根据${this.courseText}设计一个名为${this.courseName}的${sub.length ? sub.join(",") + "学科的" : ""},面向${this.getListClassC(this.checkboxList2)}的项目式学习课程。`
+        this.aiText = this.aiJson.aiDetail
       } else if (type == "aiOutline") {
         this.aitype = "aiOutline"
-        this.aiText = `请根据${this.courseText}设计一个名为${this.courseName}的${sub.length ? sub.join(",") + "学科的" : ""},面向${this.getListClassC(this.checkboxList2)}的项目式学习课程设计序列教学活动(需要每个任务都需要至少50个token的详细描述),每个教学活动的活动设计(可以直接使用文件内容)以及每个教学活动的评价量规(学生能做到...)。`
+        // this.aiText = `请根据${this.courseText}设计一个名为${this.courseName}的${sub.length ? sub.join(",") + "学科的" : ""},面向${this.getListClassC(this.checkboxList2)}的项目式学习课程设计序列教学活动(需要每个任务都需要至少50个token的详细描述),每个教学活动的活动设计(可以直接使用文件内容)以及每个教学活动的评价量规(学生能做到...)。`
+        this.aiText = this.aiJson.aiOutline
       } else if (type == "aiTask") {
         this.aitype = "aiTask"
         var _text = ""
         for (var i = 0; i < this.teacherText.length; i++) {
           _text += `任务名称:${this.teacherText[i].task} 教案:${this.teacherText[i].detail.replaceAll('#','').replaceAll('*','').replaceAll('-','').replaceAll('\n','')}`
         }
-        this.aiText = `请根据${_text}。`
+        // this.aiText = `请根据${_text}。`
+        this.aiText = this.aiJson.aiTask
         this.aiCallBack = callback
       } else if (type == "aiDetail1") {
         if (this.ttaskDetailLoading.indexOf('task-' + index) !== -1) {
@@ -12302,7 +12319,9 @@ export default {
         }
         this.aitype = "aiDetail1"
         // this.aiText = `请帮我优化下列文字内容,更具象化更详细,输出文本格式就行不要带有其他格式\n${callback}`
-        this.aiText = `请根据${callback},重新设计该教学任务。任务需要至少50个token的详细描述,包含任务设计,评价标准 \n`
+        // this.aiText = `请根据${callback},重新设计该教学任务。任务需要至少50个token的详细描述,包含任务设计,评价标准 \n`
+        this.aiText = this.aiJson.aiDetail1
+        this.aiCallBack = callback
         this.aiIndex = index
       } else if (type == "aiDetail2") {
         if (this.ttaskDetailLoading2.indexOf('task-' + index) !== -1) {
@@ -12313,7 +12332,9 @@ export default {
           return;
         }
         this.aitype = "aiDetail2"
-        this.aiText = `请你在考虑到整个课程的情况下,优化该任务描述和任务名:${callback.task}:${callback.taskDetail}`
+        // this.aiText = `请你在考虑到整个课程的情况下,优化该任务描述和任务名:${callback.task}:${callback.taskDetail}`
+        this.aiText = this.aiJson.aiDetail2
+        this.aiCallBack = callback
         this.aiIndex = index
       } else if (type == "aiDetail3") {
         if (this.ttaskDetailLoading3.indexOf('task-' + index + tindex) !== -1) {
@@ -12324,7 +12345,7 @@ export default {
           return;
         }
         this.aitype = "aiDetail3"
-        this.aiText = `请你在考虑到整个课程的情况下,**重点考虑该任务及工具名和工具内容的情况下**,优化工具指引。`
+        this.aiText = this.aiJson.aiDetail3
         this.aiIndex = index + '-' + tindex
       } else if (type == "aiDetail4") {
         var _text = ""
@@ -12332,7 +12353,7 @@ export default {
           _text += `评价维度:${callback[i].value} 维度描述:${callback[i].detail} `
         }
         this.aitype = "aiDetail4"
-        this.aiText = `请你在考虑到整个课程的情况下,**重点考虑该任务详情**以及工具的情况下,优化评价标准。`
+        this.aiText = this.aiJson.aiDetail4
         this.aiIndex = index
       } else if (type == "aiTeacher") {
         this.aitype = "aiTeacher"
@@ -12340,8 +12361,8 @@ export default {
         for (var i = 0; i < this.dArray.length; i++) {
           _text += `任务名称:${this.dArray[i].task} 任务描述:${this.dArray[i].detail} \n`
         }
-        this.aiText = `请根据${_text}为每个教学任务设计详细的教案,其中包括但不仅限于该任务的教学目标,教学过程,师生研讨,拓展,学生任务单,相关知识点的练习或Qui以及答案等。`
-
+        // this.aiText = `请根据${_text}为每个教学任务设计详细的教案,其中包括但不仅限于该任务的教学目标,教学过程,师生研讨,拓展,学生任务单,相关知识点的练习或Qui以及答案等。`
+        this.aiText = this.aiJson.aiTeacher
         this.aiCallBack = callback
 
       } else if (type == "teacherDetail") {
@@ -12353,12 +12374,25 @@ export default {
           return;
         }
         this.aitype = "teacherDetail"
-        this.aiText = `请根据${callback}\n重新设计该教案。其中包括但不仅限于该任务的教学目标,教学过程,师生研讨,拓展,学生任务单,相关知识点的练习或Qui以及答案等。`
+        // this.aiText = `请根据${callback}\n重新设计该教案。其中包括但不仅限于该任务的教学目标,教学过程,师生研讨,拓展,学生任务单,相关知识点的练习或Qui以及答案等。`
+        this.aiText = this.aiJson.teacherDetail
+        this.aiCallBack = callback
         this.aiIndex = index
       }
       this.dialogVisibleAiD = true
     },
     aiConfirm(msg) {
+      let sub = []
+      if (this.courseTypeId.length) {
+        for (var i = 0; i < this.courseTypeId.length; i++) {
+          let _sid = this.courseTypeId[i]
+          for (var j = 0; j < this.CourseTypeJson['34629907-d02f-11ec-8c78-005056b86db5'].length; j++) {
+            if (_sid == this.CourseTypeJson['34629907-d02f-11ec-8c78-005056b86db5'][j].id) {
+              sub.push(this.CourseTypeJson['34629907-d02f-11ec-8c78-005056b86db5'][j].name)
+            }
+          }
+        }
+      }
       let url = []
       if (this.infoData.length) {
         for (var i = 0; i < this.infoData.length; i++) {
@@ -12374,7 +12408,7 @@ ATTENTION: Use '##' to SPLIT SECTIONS, not '#'. Output format carefully referenc
 
 --------
 ## 要求 
-${msg} **你需要使用5EX教学活动设计框架,其定义参考#补充参考资料 中的5EX定义**。以及##补充参考资料,
+${msg} **你需要使用C-POTE教学活动设计框架,其定义参考#补充参考资料 中的C-POTE**。以及##补充参考资料和##参考资料,
 然后根据Format example的要求返回要以数组的格式
 
 --------
@@ -12391,16 +12425,16 @@ ${msg} **你需要使用5EX教学活动设计框架,其定义参考#补充参
 ]
 
 --------
-## 补充参考资料
-- 5EX定义:
-# 角色介绍
-5EX是一种跨学科学习活动设计模型,专门用于STEM(科学、技术、工程和数学)教育项目。它的核心理念是通过整合不同学科的知识和方法,解决真实情境中的问题,从而促进学生的全面发展。5EX模型包含以下五个关键环节:
-1.EQ(Enter and Questions)- 进入情境与提出问题:此环节的目的让学生进入真实的问题情境中,提出问题和任务。教师可以通过多种活动方式,如阅读科普资料、观看相关视频、参观实际场所等,引导学生发现问题并思考。这一步骤强调问题驱动的学习,让学生以项目学习的方式参与主题学习。
-2.EM(Exploration and Mathematics)- 探究学习与数学应用:在这个环节中,学生围绕提出的问题或任务,运用科学探究方法(如实验、观察、调查)和数学方法去寻求解决方案或解析问题。数学应用在此环节中是基础,帮助学生通过数据收集、分析和解释来理解问题和应用知识。
-3.ET(Engineering and Technology)- 工程设计与技术制作:此环节让学生承担任务,通过工程设计和动手制作来完成任务。学生需要进行头脑风暴,提出解决方案,选择材料和工具,并合作完成成品制作。这个过程中,学生将体验完整的工程设计和技术制作流程,并通过测试和改进来完善自己的作品。
-4.EC(Expansion and Creativity)- 知识扩展与创意设计:本环节鼓励学生将所学知识与社会需求相结合,提出更高要求的设计任务,激发学生的创新能力。学生需要进行创意设计,将知识应用于实际问题的解决中,从而扩展知识面并提出创新的设计方案。
-5.ER(Evaluation and Reflection)- 多元评价与学习反思:此环节通过多元评价方式检验学生是否达到了学习目标,并提供课程改进的依据。评价不仅包括教师的评价,还涉及学生自评和同伴评价。此外,学生通过自我反思能够监控和掌握自己的学习状况,识别知识和能力掌握的程度,以及评估还需要参与的学习过程。
+## 参考资料
+课程名字:${this.courseName}
+课程简要描述:${this.courseText ? this.courseText : '暂无'}
+学科:${sub.length ? sub.join(",") : "无"}
+班级:${this.getListClassC(this.checkboxList2)}
 
+--------
+## 补充参考资料
+- C-POTE定义:
+C-POTE模型是一种针对跨学科主题学习的教学设计模型,它是在新课标导向下提出的,旨在帮助教师更好地开展跨学科主题学习活动。C-POTE模型的核心是以大概念为基础,以核心素养为导向,通过合理部署内容组织、问题设计、目标制定、任务设计、教学评价等环节,促进学生的深度学习和创新能力的发展。C-POTE模型的名称来源于其五个核心组成部分,分别是:概念群(Concept Group):作为模型的基础,概念群负责将不同学科的知识点进行整合,形成有意义的认知网络。教师需要遴选重要的大概念,使之形成更大的跨学科概念群,为后续的教学活动奠定基础。问题链(Problem Chain):围绕大概念设计一系列有逻辑结构的问题,从具体到抽象,形成问题链。问题链的目的是引导学生通过问题解决的过程深化对大概念的理解。目标层(Objective Layer):明确教学目标,将核心素养具体化,分为“双基—学科思维—高阶素养”三个层次。教师需要根据学科课程标准中的核心素养,将其转化为具体的教学目标。任务簇(Task Cluster):设计一系列指向核心素养的表现性任务,将大任务拆解为若干个活动序列,确保学生能够通过实践活动实现学习目标。证据集(Evidence Set):评价学生学习成果的依据,通过收集学生在跨学科实践过程中的表现证据,进行综合性评价,以促进学生核心素养的发展。
 补充资料:${url.join(",")}
 补充描述:${this.courseText2}
 `
@@ -12410,6 +12444,10 @@ ${msg} **你需要使用5EX教学活动设计框架,其定义参考#补充参
           this.isOutline = true
         })
       } else if (this.aitype == "aiTask") {
+        var _text = ""
+        for (var i = 0; i < this.teacherText.length; i++) {
+          _text += `任务名称:${this.teacherText[i].task} 教案:${this.teacherText[i].detail.replaceAll('#','').replaceAll('*','').replaceAll('-','').replaceAll('\n','')}`
+        }
         let message = `NOTICE
 Role: 作为学生的学习指导Agent,你熟悉熟悉PBL(基于问题的学习)和5EX教学模型,能够根据学生的学情数据(当前的学习任务设计、学习表现数据、作业数据等)生成自适应的学习任务和对应的5道考核题目。
 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.
@@ -12418,7 +12456,10 @@ Instruction: Based on the context, follow "Format example", write content.
 
 # Context
 ## 要求
-${msg} 以及#补充参考资料 输出格式和内容要求参考##格式与要求
+${msg} 以及#补充参考资料和#教学任务教案 输出格式和内容要求参考##格式与要求
+
+## 教学任务教案
+${_text}
 
 ## 格式与要求
 任务名:
@@ -12509,13 +12550,20 @@ ${msg} 以及#补充参考资料 输出格式和内容要求参考##格式与要
         this.aiDetail5(msg, this.aiIndex)
       } else if (this.aitype == "aiTeacher") {
         this.loading = true
+        var _text = ""
+        for (var i = 0; i < this.dArray.length; i++) {
+          _text += `任务名称:${this.dArray[i].task} 任务描述:${this.dArray[i].detail} \n`
+        }
         let message = `
 ATTENTION: Use '##' to SPLIT SECTIONS, not '#'. Output format carefully referenced "Format example".
 
 --------
 ## 要求
-${msg} 以及##补充参考资料, 然后根据Format example的要求返回要以数组的格式
+${msg} 以及##补充参考资料和##任务大纲, 然后根据Format example的要求返回要以数组的格式
 
+--------
+## 任务大纲
+${_text}
 
 --------
 ## 补充参考资料
@@ -12527,11 +12575,11 @@ ${msg} 以及##补充参考资料, 然后根据Format example的要求返回
 [
   {
     "task": "任务名称1",
-    "detail": "教案"
+    "detail": "教案输出为文本格式就行"
   },
   {
       "task": "任务名称2",
-      "detail": "教案"
+      "detail": "教案输出为文本格式就行"
   }
 ]`
         this.aiGet4(message, () => {
@@ -12543,37 +12591,17 @@ ${msg} 以及##补充参考资料, 然后根据Format example的要求返回
     detailYou(message) {
       this.textLoading = true
       this.ttextLoading = true
-      //       setTimeout(()=>{
-      //         if(this.courseName == '热传递2'){
-      //           this.courseText = `本项目旨在通过一个综合性的学习过程,让学生深入探究“热”的物理现象及其在日常生活中的应用。学生将通过实验、观察、设计和制作等活动,理解热的传递方式、热的良导体与不良导体的概念,以及保温技术的原理和应用。项目的核心是制作一个保温杯,该保温杯需要能够有效地减缓热量散失,保持水温在一定时间内相对稳定。通过这个项目,学生不仅能够巩固和拓展科学知识,还能培养创新思维、问题解决能力和团队合作精神。
-
-      // 该项目的驱动性问题是如何设计并制作一个既实用又环保的保温杯,使其在一定时间内最大限度地减少热量散失?
-
-      // 该项目的最终作品是一个由学生团队设计和制作的保温杯原型,该保温杯应使用合适的材料和技术,以实现良好的保温效果。最终作品需要附上一份详细的设计报告,阐述设计理念、选材依据、制作过程和测试结果。`
-      //             }else if(this.courseName == '热传递1'){
-      //               this.courseText = `项目名:探索热传导:从热到冷
-      // 项目概况:随着气温的变化,孩子们可能对热量如何从热物体传到冷物体的过程产生兴趣。这是热传导的基础知识,对日常生活中的很多现象有深入的解释。例如A小组的孩子们在午餐时注意到,他们的塑料餐具比金属餐具冷得快。引出的驱动性问题是:“为什么塑料餐具比金属餐具冷得快?因此在这个项目中学生需要通过实施一系列的实验的方式,解决这个问题。
-
-      // 本项目需要孩子们了解热传导的基本知识,掌握观察和记录实验数据的基本技能,以及分析和解释数据的能力。并通过实验研究的方式,完成一个关于热传导的实验报告,报告中需要包括实验的设计、实施过程、数据记录、数据分析和结论。
-
-      // 通过了解和掌握热传导的基本原理,以及通过实验测试不同材质的热传导情况,学生们可以了解不同物质的热传导效果的差异,预期的结果是:塑料的热传导效果较差,所以冷得快,而金属的热传导效果好,所以冷得慢。`
-      //             }else if(this.courseName == '热传递'){
-      //               this.courseText = `课程名称:探索热传导的奥秘
-      // 课程介绍:
-      // 在这个为期四周的项目式学习课程中,五年级的学生们将通过实际操作和实验,深入了解热传导的基本原理和日常生活中的应用。学生们将通过探索不同材料的热传导性能,设计实验,收集数据,并最终制作一个展示他们发现的创意项目。本课程旨在激发学生的好奇心,提高他们的科学探究能力,并帮助他们理解热能是如何在不同环境中传递的。
-      // 驱动性问题:
-      // •热传导是如何在不同材料之间发生的?
-      // •哪些日常用品的设计利用了热传导的原理?
-      // •我们如何通过实验来比较不同材料的热传导效率?
-      // •如何设计一个既实用又创新的产品,利用热传导原理解决实际问题?
-      // 期末作品:
-      // •热传导实验报告:详细记录实验过程、数据和结论。
-      // •创意产品:展示学生基于热传导原理设计的创新产品或模型。
-
-      // 通过这个课程,学生不仅能够掌握热传导的科学知识,还能通过实际操作和创造,将理论知识应用于解决实际问题,培养他们的科学素养和创新能力。`
-      //             }
-      //         this.textLoading = false
-      //       }, 5000)
+      let sub = []
+      if (this.courseTypeId.length) {
+        for (var i = 0; i < this.courseTypeId.length; i++) {
+          let _sid = this.courseTypeId[i]
+          for (var j = 0; j < this.CourseTypeJson['34629907-d02f-11ec-8c78-005056b86db5'].length; j++) {
+            if (_sid == this.CourseTypeJson['34629907-d02f-11ec-8c78-005056b86db5'][j].id) {
+              sub.push(this.CourseTypeJson['34629907-d02f-11ec-8c78-005056b86db5'][j].name)
+            }
+          }
+        }
+      }
       let url = []
       if (this.infoData.length) {
         for (var i = 0; i < this.infoData.length; i++) {
@@ -12584,14 +12612,21 @@ ${msg} 以及##补充参考资料, 然后根据Format example的要求返回
 ATTENTION: Use '##' to SPLIT SECTIONS, not '#'. Output format carefully referenced "Format example".
 
 --------
-## 要求
-${message} 以及##补充参考资料 以文本格式输出项目概况,驱动性问题,最终作品,格式参考## Format example
+## 参考资料
+课程名字:${this.courseName}
+课程简要描述:${this.courseText ? this.courseText : '暂无'}
+学科:${sub.length ? sub.join(",") : "无"}
+班级:${this.getListClassC(this.checkboxList2)}
 
 --------
 ## 补充参考资料
 补充资料:${url.join(",")}
 补充描述:${this.courseText2}
 
+--------
+## 要求
+${message} 以及##补充参考资料和##参考资料 以文本格式输出项目概况,驱动性问题,最终作品,格式参考## Format example
+
 --------
 ## Format example
 -课程简要描述:
@@ -12767,7 +12802,7 @@ ${message} 以及##补充参考资料 以文本格式输出项目概况,驱动
             "文档": { tool: 52, type: 1 },
             "思维导图": { tool: 3, type: 1 },
             "表格": { tool: 48, type: 1 },
-            "作业提交": { tool: 16, type: 1 }
+            "作业提交": { tool: 16, type: 2 }
           }
           for (var i = 0; i < tArray.length; i++) {
             let _task = tArray[i]
@@ -12864,11 +12899,16 @@ ATTENTION: Use '##' to SPLIT SECTIONS, not '#'.Output format carefully reference
 
 --------
 ## 要求
-${msg} 以文本格式输出任务设计和评价标准
+${msg} 及#补充参考资料和#教学任务描述 以文本格式输出任务设计和评价标准
+
+--------
+## 教学任务描述
+${_this.aiCallback}
   
+--------
 ## 补充参考资料
 - 补充资料:${url.join(",")}
-- 补充描述:${this.courseText2}
+- 补充描述:${_this.courseText2}
 `
       _this.taskDetailLoading.push(_tindex)
       _this.ttaskDetailLoading.push(_tindex)
@@ -12954,6 +12994,11 @@ ATTENTION: Use '##' to SPLIT SECTIONS, not '#'.Output format carefully reference
 ## 要求
 ${msg} 
 
+--------
+## 优化信息
+任务名字: ${_this.aiCallback.task}
+任务描述: ${_this.aiCallback.taskDetail}
+
 # 格式与要求
 - 任务名:
 - 任务描述:该描述是教师给与学生的指示(用于指导学生如何进行教学活动),对应到学生活动,你应该用友好,但是又清晰明确的口吻来撰写。`
@@ -13206,6 +13251,10 @@ ATTENTION: Use '##' to SPLIT SECTIONS, not '#'.Output format carefully reference
 ## 要求
 ${msg} 
         
+-------
+## 教案描述
+${_this.aiCallBack}
+
 ## 补充参考资料
 - 补充资料:${url.join(",")}
 - 补充描述:${this.courseText2}`
@@ -13428,6 +13477,7 @@ ${msg}
 .pb_content_body {
   width: 100% !important;
   height: 100%;
+  display: flex;
 }
 
 .info_solid {
@@ -13471,6 +13521,16 @@ ${msg}
   flex-direction: column;
 }
 
+.leftBar{
+  width: 290px;
+  height: calc(100% - 50px);
+  overflow: auto;
+  border-radius: 5px;
+  margin: 25px auto;
+  box-sizing: border-box;
+  margin-right: 10px;
+}
+
 .basic_box {
   margin: 0 auto;
   position: relative;

+ 39 - 0
src/components/pages/aiAddCourse/aiTips.vue

@@ -0,0 +1,39 @@
+<template>
+  <div class="at_body">
+    <div class="at_title">{{ title }}</div>
+    <div class="at_text">
+        <div class="at_text_img">
+            <div class="at_restart"></div>
+            <div class="at_edit"></div>
+        </div>
+        <div class="at_text_detail">{{ detail }}</div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+    props: {
+        title: {
+            type: String,
+            default: ''
+        },
+        detail: {
+            type: String,
+            default: ''
+        },
+    },
+    data() {
+        return {
+        }
+    },
+}
+</script>
+
+<style scoped>
+    .at_body{}
+
+    .at_title{}
+
+    .at_text{}
+</style>

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

@@ -33,7 +33,6 @@ export default {
 	},
 	data() {
 		let validateNo = (rule, value, callback) => {
-			console.log(this.courseList.findIndex(i=>i.value==value))
 			if (value.trim().length == 0) {
 				callback(new Error("请输入课堂编号"));
 			}else if(this.courseList.findIndex(i=>i.value==value.trim())!=-1){
@@ -43,8 +42,6 @@ export default {
 			}
 		};
 		let validateName = (rule, value, callback) => {
-			console.log(this.courseList)
-			console.log(rule)
 			if (value.trim().length == 0) {
 				callback(new Error("请输入课堂名称"));
 			} else {

+ 11 - 2
src/components/pages/classroomObservation/components/analysis.vue

@@ -15,7 +15,7 @@
 		<div class="a-main" v-show="showItem">
 			<analysisItem
 				ref="analysisItemRef"
-				v-if="analysisItemList.length > 0"
+				v-if="item.jsonData.name!='词频词汇分析'"
 				v-for="(item, index) in analysisItemList"
 				:dialogTagDataList="dialogTagDataList"
 				:key="item.id"
@@ -23,8 +23,10 @@
 				:tid="tid"
 				:fileId="fileId"
 				:index="index"
+				:showBrief="showBrief"
 				@delItem="delItem"
 				@editItem="editItem"
+				@saveItem="saveItem"
 			/>
 			<div class="a_m_empty" v-if="analysisItemList.length == 0">
 				暂无模块...
@@ -36,12 +38,16 @@
 <script>
 import analysisItem from "./analysisItem";
 export default {
-	emits: ["delItem", "editItem"],
+	emits: ["delItem", "editItem","saveItem"],
 	props: {
 		title: {
 			type: String,
 			default: "分析",
 		},
+		showBrief:{
+			type:Boolean,
+			default:true
+		},
 		dialogTagDataList:{
 			type:Array,
 			default:()=>{
@@ -89,6 +95,9 @@ export default {
 		editItem(id, _data) {
 			this.$emit("editItem", id, _data);
 		},
+		saveItem(id,_data){
+			this.$emit("saveItem",id,_data)
+		},
 		getReport(id) {
 			if (!id) {
 				this.$refs.analysisItemRef.forEach((i) => {

+ 193 - 40
src/components/pages/classroomObservation/components/analysisItem.vue

@@ -21,29 +21,81 @@
 					v-if="loadNum == 0 && !openItem"
 					class="ai-h-r-icon4"
 					@click.stop="delBtn()"
-				></span>
+				>
+					<el-tooltip
+						class="item"
+						effect="light"
+						content="删除"
+						placement="top"
+					>
+						<img
+							:src="
+								require('../../../../assets/icon/classroomObservation/del.png')
+							"
+						/>
+					</el-tooltip>
+				</span>
+
 				<span
 					v-if="loadNum == 0 && openItem"
-					:class="['ai-h-r-icon1',showIndex<=0?'ai_h_r_iconOpacity':'']"
+					:class="['ai-h-r-icon1', showIndex <= 0 ? 'ai_h_r_iconOpacity' : '']"
 					@click.stop="changeShowIndex(-1)"
-				></span>
+				>
+					<el-tooltip
+						class="item"
+						effect="light"
+						content="上一个"
+						placement="top"
+					>
+						<img
+							:src="
+								require('../../../../assets/icon/classroomObservation/back.png')
+							"
+						/>
+					</el-tooltip>
+				</span>
+
 				<span
 					v-if="loadNum != 1 && openItem"
-					:class="['ai-h-r-icon2',showIndex>=historyResult.length-1?'ai_h_r_iconOpacity':'']"
+					:class="[
+						showIndex >= historyResult.length - 1 ? 'ai_h_r_iconOpacity' : '',
+					]"
 					@click.stop="changeShowIndex(1)"
-				></span>
-				<span
-					v-if="loadNum != 1 && openItem"
-					class="ai-h-r-icon3"
-					@click.stop="editBtn()"
-				></span>
+				>
+					<el-tooltip
+						class="item"
+						effect="light"
+						content="下一个"
+						placement="top"
+					>
+						<img
+							:src="
+								require('../../../../assets/icon/classroomObservation/back.png')
+							"
+						/>
+					</el-tooltip>
+				</span>
+
+				<span v-if="loadNum != 1 && openItem" @click.stop="editBtn()">
+					<el-tooltip
+						class="item"
+						effect="light"
+						content="优化"
+						placement="top"
+					>
+						<img
+							:src="
+								require('../../../../assets/icon/classroomObservation/edit.png')
+							"
+						/>
+					</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">
+			<div class="a-m-brief" v-if="showBrief">
 				{{ data.jsonData.result }}
 				<!-- <mdView :text="data.jsonData.result" /> -->
 				<!-- {{ data.jsonData.result }} -->
@@ -79,8 +131,10 @@
 <script>
 import mdView from "./mdView.vue";
 import pieChart from "./pieChart.vue";
+// import { v4 as uuidv4 } from "uuid";
+// import MarkdownIt from "markdown-it";
 export default {
-	emits: ["delItem", "editItem"],
+	emits: ["delItem", "editItem", "saveItem"],
 	components: {
 		mdView,
 		pieChart,
@@ -92,11 +146,11 @@ export default {
 				return {};
 			},
 		},
-		dialogTagDataList:{
-			type:Array,
-			default:()=>{
-				return []
-			}
+		dialogTagDataList: {
+			type: Array,
+			default: () => {
+				return [];
+			},
 		},
 		index: {
 			type: Number,
@@ -110,14 +164,18 @@ export default {
 			type: String,
 			require: true,
 		},
+		showBrief:{
+			type:Boolean,
+			default:true,
+		}
 	},
 	data() {
 		return {
 			openItem: false,
 			loading: false,
 			loadNum: 0,
-			showIndex:0,
-			historyResult:[],
+			showIndex: 0,
+			historyResult: [],
 			imgTypeList: [
 				"png",
 				"jpg",
@@ -129,6 +187,7 @@ export default {
 				"svg",
 				"tiff",
 			],
+			oldData: {},
 		};
 	},
 	computed: {
@@ -138,7 +197,7 @@ export default {
 			};
 		},
 	},
-	watch:{
+	watch: {
 		// showIndex(){
 		// 	let _copyData = JSON.parse(JSON.stringify(this.data));
 		// 	_copyData.jsonData = this.historyResult[this.showIndex];
@@ -158,21 +217,47 @@ export default {
 				this.loading = true;
 				this.openItem = false;
 				this.loadNum = 1;
-				let assistant = this.dialogTagDataList.find(i=>i.title==this.data.jsonData.name);
+				let assistant = this.dialogTagDataList.find(
+					(i) => i.title == this.data.jsonData.name
+				);
 				let parm = {
 					assistant_id: assistant?assistant.value:null,
 					message:
-						"请使用代码解析器获取文件,帮我根据要求完整的分析,输出请按照要求。",
+						"请使用代码解析器分析,帮我根据要求完整的分析,输出请按照要求。",
 					session_name: new Date().getTime(),
 					userId: "1cf9dc4b-d95f-11ea-af4c-52540005ab01",
 					file_ids: this.fileId?[this.fileId]:'',
 				};
 
+				// 👇
+				// const _uid = uuidv4();
+				// let parm = {
+				// 	assistant_id: assistant ? assistant.value : null,
+				// 	userId: "1cf9dc4b-d95f-11ea-af4c-52540005ab01", //602def61-005d-11ee-91d8-005056b86db5
+				// 	message:
+				// 		"请使用代码解析器获取文件,帮我根据要求完整的分析,输出请按照要求。",
+				// 	session_name: new Date().getTime(),
+				// 	uid: _uid,
+				// 	file_ids: this.fileId ? [this.fileId] : [],
+				// };
 				if (!parm.assistant_id) {
 					this.loading = false;
 					this.loadNum = 2;
 					return this.$message.error("未找到对应的AI助手");
 				}
+				// this.ajax
+				// 	.post("https://gpt4.cocorobo.cn/ai_agent_park_chat_new", parm)
+				// 	.then((res) => {
+				// 		if (res.data.FunctionResponse.result == "发送成功") {
+				// 		} else {
+				// 			this.$message.warning(res.data.FunctionResponse.result);
+				// 		}
+				// 	})
+				// 	.catch((err) => {
+				// 		console.log(err);
+				// 	});
+				// this.getAtAuContent(_uid);
+				// 👆
 
 				this.ajax
 					.post("https://gpt4.cocorobo.cn/ai_agent_park_chat", parm)
@@ -183,6 +268,7 @@ export default {
 							_data.message.indexOf("由于我无法直接访问您上传的文件内容") > -1
 						) {
 							this.loading = false;
+							this.loadNum = 2;
 							return this.$message.error("AI无法识别优化");
 						}
 						let _copyData = JSON.parse(JSON.stringify(this.data));
@@ -191,20 +277,80 @@ export default {
 						_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)
+						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);
+					// 处理流数据
+				}
+			};
+		},
 		delBtn() {
 			this.$confirm("确定删除?", "提示", {
 				confirmButtonText: "确定",
@@ -214,12 +360,12 @@ export default {
 				this.$emit("delItem", this.data.id);
 			});
 		},
-		changeShowIndex(value){
-			if(this.historyResult.length==0)return;
-			if(value==-1){
-				if(this.showIndex>0)this.showIndex--;
-			}else if(value==1){
-				if(this.showIndex<this.historyResult.length-1)this.showIndex++;
+		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));
@@ -227,13 +373,15 @@ export default {
 			_copyData.json_data = JSON.stringify(_copyData.jsonData);
 			_oldCopyDate.json_data = JSON.stringify(_oldCopyDate.jsonData);
 			// 一样就不用更新了
-			if(JSON.stringify(_copyData)==JSON.stringify(_oldCopyDate))return;
+			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);
+		},
 	},
-	mounted(){
-		if(this.data.jsonData.content){
-			this.historyResult.push(this.data.jsonData)
+	mounted() {
+		if (this.data.jsonData.content) {
+			this.historyResult.push(this.data.jsonData);
 		}
 	},
 };
@@ -306,6 +454,11 @@ export default {
 	cursor: pointer;
 }
 
+.ai-h-right > span > img {
+	width: 18px;
+	height: 18px;
+}
+
 .ai-h-r-icon1 {
 	background: url("../../../../assets/icon/classroomObservation/back.png");
 	/* 镜像 */
@@ -316,7 +469,7 @@ export default {
 	background: url("../../../../assets/icon/classroomObservation/back.png");
 }
 
-.ai_h_r_iconOpacity{
+.ai_h_r_iconOpacity {
 	opacity: 0.5;
 	cursor: not-allowed !important;
 }

+ 319 - 121
src/components/pages/classroomObservation/components/baseMessage.vue

@@ -1,12 +1,12 @@
 <template>
-	<div class="message" >
+	<div class="message">
 		<div class="m-header" @click.stop="changeShowMain(!showMain)">
 			<span :class="['m-h-icon', showMain ? 'm-h-icon-active' : '']"></span>
 			<span class="m-h-title">{{ title }}</span>
 		</div>
 		<div class="m-main" v-show="showMain">
-			<div class="baseInfoLeft">
-				<div class="m-m-formItem">
+			<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-input">
 						<el-input
@@ -17,62 +17,83 @@
 					</div>
 				</div>
 
-				<div class="baseInfoLeftBot">
-					<div class="m-m-formItemBot">
-						<div class="m-m-fi-label">授课年级</div>
-						<div class="m-m-fi-input">
-							<el-select v-model="data.grade" @change="changeData()" placeholder="请选择年级">
-								<el-option
-									v-for="(item, index) in gradeList"
-									:key="index"
-									:value="item.value"
-									:label="item.label"
-								></el-option>
-							</el-select>
-						</div>
+				<div class="m-m-formItem" style="width: clamp(21%,21%,21%)">
+					<div class="m-m-fi-label">授课老师</div>
+					<div class="m-m-fi-input">
+						<el-input
+							v-model="data.teacherName"
+							placeholder="请输入授课老师"
+							@change="changeData()"
+						></el-input>
 					</div>
+				</div>
 
-					<div class="m-m-formItemBot">
-						<div class="m-m-fi-label">授课科目</div>
-						<div class="m-m-fi-input">
-							<el-select v-model="data.subject" @change="changeData()" placeholder="请选择年级">
-								<el-option
-									v-for="(item, index) in subjectList"
-									:key="index"
-									:value="item.value"
-									:label="item.label"
-								></el-option>
-							</el-select>
-						</div>
+				<div class="m-m-formItem" style="width: clamp(22%,22%,22%)"">
+					<div class="m-m-fi-label">授课时间</div>
+					<div class="m-m-fi-input">
+						<el-date-picker
+							v-model="data.time"
+							type="datetime"
+							format="yyyy-MM-dd HH:mm:ss"
+							value-format="yyyy-MM-dd HH:mm:ss"
+							style="width: 100%"
+							@change="changeData()"
+							placeholder="请选择授课时间"
+						>
+						</el-date-picker>
 					</div>
+				</div>
 
-					<div class="m-m-formItemBot">
-						<div class="m-m-fi-label">教材版本</div>
-						<div class="m-m-fi-input">
-							<el-input
-								v-model="data.textbook"
-								placeholder="请输入教材版本"
-								@change="changeData()"
-							></el-input>
-						</div>
+				<div class="m-m-formItem" style="width: clamp(24%,24%,24%)"">
+					<div class="m-m-fi-label">授课年级</div>
+					<div class="m-m-fi-input">
+						<el-select
+							style="width: 100%"
+							v-model="data.grade"
+							@change="changeData()"
+							placeholder="请选择年级"
+						>
+							<el-option
+								v-for="(item, index) in gradeList"
+								:key="index"
+								:value="item.value"
+								:label="item.label"
+							></el-option>
+						</el-select>
 					</div>
 				</div>
-			</div>
 
-			<!-- 授课老师,学生人数 -->
-			<div class="baseInfoRight">
-				<div class="m-m-formItem">
-					<div class="m-m-fi-label">授课老师</div>
+				<div class="m-m-formItem" style="width: clamp(24.5%,24.5%,24.5%)">
+					<div class="m-m-fi-label">授课科目</div>
+					<div class="m-m-fi-input">
+						<el-select
+							style="width: 100%"
+							v-model="data.subject"
+							@change="changeData()"
+							placeholder="请选择年级"
+						>
+							<el-option
+								v-for="(item, index) in subjectList"
+								:key="index"
+								:value="item.value"
+								:label="item.label"
+							></el-option>
+						</el-select>
+					</div>
+				</div>
+
+				<div class="m-m-formItem" style="width: clamp(21%,21%,21%)"">
+					<div class="m-m-fi-label">教材版本</div>
 					<div class="m-m-fi-input">
 						<el-input
-							v-model="data.teacherName"
-							placeholder="请输入授课老师"
+							v-model="data.textbook"
+							placeholder="请输入教材版本"
 							@change="changeData()"
 						></el-input>
 					</div>
 				</div>
 
-				<div class="m-m-formItem" style="margin: 10px 0">
+				<div class="m-m-formItem" style="width: clamp(22%,22%,22%)"">
 					<div class="m-m-fi-label">学生人数</div>
 					<div class="m-m-fi-input">
 						<el-input
@@ -83,76 +104,155 @@
 					</div>
 				</div>
 			</div>
-			<div class="imgTit">
-				<span>添加课堂图片</span>
-				<span>(建议图片比例16:9,最多上传3张图片)</span>
-			</div>
-			<div class="m-m-formImage" v-loading="uploadImageLoading">
-				<div class="m-m-fi-imageList">
-					<div class="m-m-fi-imageList">
-						<div
-							class="m-m-fi-imageItem"
-							v-for="(value,key,index) in imageList"
-							:key="index"
-							v-if="key.indexOf('fileList')!=-1&&index!=0 && value.length>0"
-							@click.stop="previewImg(value[0].url)"
-						>
-						<el-image
-						class="itemUrl"
-      			:src="value[0].url"
-      			fit="cover"></el-image>
-						<span @click.stop="delImage(key)">x</span>
-							<!-- <img class="itemUrl" :src="value[0].url" alt="" /> -->
+			<div class="fileList">
+				<div class="fl_img">
+					<div class="imgTit">
+						<span>课堂图片</span>
+						<span>(建议图片比例16:9,最多上传3张)</span>
+					</div>
+					<div class="m-m-formImage" v-loading="uploadImageLoading">
+						<div class="m-m-fi-imageList">
+							<div class="m-m-fi-imageList">
+								<div
+									class="m-m-fi-imageItem"
+									v-for="(value, key, index) in imageList"
+									:key="index"
+									v-if="(key == 'fileList1' || key == 'fileList2' || key == 'fileList3') && value.length >0"
+									@click.stop="previewImg(value[0].url)"
+									style="max-width: 32%;"
+								>
+									<el-image
+										class="itemUrl"
+										:src="value[0].url"
+										fit="cover"
+									></el-image>
+									<span @click.stop="delImage(key)">x</span>
+									<!-- <img class="itemUrl" :src="value[0].url" alt="" /> -->
+								</div>
+								<!-- 图片区域 -->
+							</div>
+
+							<div
+								class="m-m-fi-imageItem"
+								@click.stop="addImage()"
+								v-if="
+									imageList.fileList1 &&
+									imageList.fileList1.length +
+										imageList.fileList2.length +
+										imageList.fileList3.length <
+										3
+								"
+							>
+								<img
+									src="../../../../assets/icon/classroomObservation/Union.png"
+									alt=""
+								/>
+								<div
+									style="
+										font-size: 12px;
+										font-weight: 400;
+										margin-top: 5px;
+										color: rgba(0, 0, 0, 0.4);
+									"
+								>
+									点击上传图片
+								</div>
+							</div>
+							<!-- 图片区域 -->
 						</div>
-						<!-- 图片区域 -->
+						<!-- <div class="m-m-fi-btn" >添加课堂图片</div> -->
+					</div>
+				</div>
+				<div class="fl_video">
+					<div class="imgTit">
+						<span>课堂视频</span>
+						<span>(建议图片比例16:9,最多上传1个)</span>
 					</div>
+					<div class="m-m-formImage" v-loading="uploadVideoLoading">
+						<div class="m-m-fi-imageList">
+							<div class="m-m-fi-imageList">
+								<div
+									class="m-m-fi-imageItem"
+									v-for="(item, index) in imageList.videoList?imageList.videoList:[]"
+									:key="index"
+									@click.stop="previewVideo(item.url)"
+								>
+								<!-- <div>{{ item }}</div> -->
+									<el-image
+										class="itemUrl"
+										:src="require('../../../../assets/icon/classroomObservation/isVideo.png')"
+										fit="cover"
+									></el-image>
+									<span @click.stop="delVideo('videoList')">x</span>
+								</div>
+							</div>
 
-					<div class="m-m-fi-imageItem"  @click.stop="addImage()" v-if="imageList.fileList1&&(imageList.fileList1.length+imageList.fileList2.length+imageList.fileList3.length)<3">
-						<img
-							src="../../../../assets/icon/classroomObservation/Union.png"
-							alt=""
-						/>
-						<div
-							style="
-								font-size: 12px;
-								font-weight: 400;
-								margin-top: 5px;
-								color: rgba(0, 0, 0, 0.4);
-							"
-						>
-							点击上传图片
+							<div
+								class="m-m-fi-imageItem"
+								@click.stop="addVideo()"
+								v-if="
+									(imageList.videoList&&imageList.videoList.length<=0) || !imageList.videoList
+								"
+							>
+								<img
+									src="../../../../assets/icon/classroomObservation/Union.png"
+									alt=""
+								/>
+								<div
+									style="
+										font-size: 12px;
+										font-weight: 400;
+										margin-top: 5px;
+										color: rgba(0, 0, 0, 0.4);
+									"
+								>
+									点击上传视频
+								</div>
+							</div>
+							<!-- 图片区域 -->
 						</div>
+						<!-- <div class="m-m-fi-btn" >添加课堂图片</div> -->
 					</div>
-					<!-- 图片区域 -->
 				</div>
-				<!-- <div class="m-m-fi-btn" >添加课堂图片</div> -->
 			</div>
 		</div>
+		<previewVideoDialog ref="previewVideoDialogRef"/>
 	</div>
 </template>
 
 <script>
+import previewVideoDialog from './previewVideoDialog.vue';
 export default {
-	emits:["saveData","saveImage","delImage"],
-	props:{
-		data:{
-			type:Object,
-			default:()=>{
-				return {}
-			}
+	emits: ["saveData", "saveImage", "saveVideo","delImage"],
+	components:{
+		previewVideoDialog
+	},
+	props: {
+		data: {
+			type: Object,
+			default: () => {
+				return {};
+			},
 		},
-		imageList:{
-			type:Object,
-			default:()=>{
-				return {}
-			}
+		imageList: {
+			type: Object,
+			default: () => {
+				return {
+					fileList:[],
+					fileList1:[],
+					fileList2:[],
+					fileList3:[],
+					videoList:[],
+				};
+			},
 		},
 	},
 	data() {
 		return {
 			title: "基本信息",
 			showMain: true,
-			uploadImageLoading:false,
+			uploadImageLoading: false,
+			uploadVideoLoading:false,
 			from: {
 				courseName: "",
 				teacherName: "",
@@ -238,11 +338,11 @@ export default {
 							if (err) {
 								_this.$message.error("上传失败");
 							} else {
-								_this.$emit("saveImage",{
-									name:data.key,
-									status:"success",
-									uid:"1",
-									url:data.Location
+								_this.$emit("saveImage", {
+									name: data.key,
+									status: "success",
+									uid: "1",
+									url: data.Location,
 								});
 								// _this.from.audioUrl = data.Location;
 								// _this.from.audioName = file.name;
@@ -258,15 +358,84 @@ export default {
 			// this.mainBtnStatus = 1;
 			// this.barNum = 4;
 		},
+		// 添加视频
+		addVideo(){
+			let input = document.createElement("input");
+			input.type = "file";
+			input.accept = "video/*";
+			input.click();
+			input.onchange = () => {
+				this.uploadVideoLoading = true;
+				let file = input.files[0];
+				var credentials = {
+					accessKeyId: "AKIATLPEDU37QV5CHLMH",
+					secretAccessKey: "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",
+				}; //秘钥形式的登录上传
+				window.AWS.config.update(credentials);
+				window.AWS.config.region = "cn-northwest-1"; //设置区域
+
+				var bucket = new window.AWS.S3({ params: { Bucket: "ccrb" } }); //选择桶
+				var _this = this;
+
+				if (file) {
+					var params = {
+						Key:
+							file.name.split(".")[0] +
+							new Date().getTime() +
+							"." +
+							file.name.split(".")[file.name.split(".").length - 1],
+						ContentType: file.type,
+						Body: file,
+						"Access-Control-Allow-Credentials": "*",
+						ACL: "public-read",
+					}; //key可以设置为桶的相抵路径,Body为文件, ACL最好要设置
+					var options = {
+						partSize: 2048 * 1024 * 1024,
+						queueSize: 2,
+						leavePartsOnError: true,
+					};
+					bucket
+						.upload(params, options)
+						.on("httpUploadProgress", function (evt) {
+							//这里可以写进度条
+							// console.log("Uploaded : " + parseInt((evt.loaded * 80) / evt.total) + '%');
+						})
+						.send(function (err, data) {
+							if (err) {
+								_this.$message.error("上传失败");
+							} else {
+								_this.$emit('saveVideo',{
+										name: data.key,
+										status: "success",
+										uid: "1",
+										url: data.Location,
+								})
+							}
+							_this.uploadVideoLoading = false;
+						});
+				}
+			};
+		},
+
 		// 删除图片
-		delImage(key){
-			this.$confirm('确定删除该图片吗?', '提示', {
-				confirmButtonText: '确定',
-				cancelButtonText: '取消',
-				type: 'warning'
+		delImage(key) {
+			this.$confirm("确定删除该图片吗?", "提示", {
+				confirmButtonText: "确定",
+				cancelButtonText: "取消",
+				type: "warning",
 			}).then(() => {
-				this.$emit("delImage",key);
-			})
+				this.$emit("delImage", key);
+			});
+		},
+		// 删除视频
+		delVideo(key){
+			this.$confirm("确定删除该视频吗?", "提示", {
+				confirmButtonText: "确定",
+				cancelButtonText: "取消",
+				type: "warning",
+			}).then(() => {
+				this.$emit("delImage", key);
+			});
 		},
 		changeShowMain(newValue) {
 			this.showMain = newValue;
@@ -274,13 +443,15 @@ export default {
 		previewImg(url) {
 			this.$hevueImgPreview(url);
 		},
-		changeData(){
+		previewVideo(url){
+			this.$refs.previewVideoDialogRef.open(url)
+			// this.$message.info(`预览:${url}`)
+		},
+		changeData() {
 			this.$emit("saveData");
 		},
 	},
-	mounted(){
-		
-	}
+	mounted() {},
 };
 </script>
 
@@ -289,9 +460,9 @@ export default {
 	width: 100%;
 	height: auto;
 }
-.imgTit{
-  height: 40px;
-  line-height: 40px;
+.imgTit {
+	height: 40px;
+	line-height: 40px;
 }
 .imgTit :first-child {
 	font-size: 16px;
@@ -305,8 +476,7 @@ export default {
 	font-weight: 400;
 	line-height: 20px;
 	text-align: left;
-  color: rgba(0, 0, 0, 0.4);
-
+	color: rgba(0, 0, 0, 0.4);
 }
 .baseInfoLeft {
 	display: flex;
@@ -370,6 +540,14 @@ export default {
 	box-sizing: border-box;
 	display: flex;
 	flex-wrap: wrap;
+	flex-direction: column;
+}
+
+.m-m-form {
+	display: flex;
+	flex-wrap: wrap;
+	width: 100%;
+
 }
 
 .m-m-formItem {
@@ -378,11 +556,13 @@ export default {
 	display: flex;
 	flex-direction: column;
 	align-items: left;
+	margin-top: 10px;
+	margin-right: 1.5%;
 	/* margin-bottom: 10px; */
 }
 
 .m-m-fi-input {
-	width: 100%;
+	max-width: 100%;
 }
 
 .m-m-fi-label {
@@ -418,7 +598,7 @@ export default {
 	background-color: rgba(238, 238, 238, 1);
 	width: 140px;
 	height: 100px;
-	margin-right: 10px;
+	margin-right: 1%;
 	display: flex;
 	justify-content: center;
 	align-items: center;
@@ -427,14 +607,15 @@ export default {
 	font-size: 14px;
 	cursor: pointer;
 	position: relative;
+	margin-bottom: 10px;
 }
 .m-m-fi-imageItem > .itemUrl {
 	width: 100%;
 	height: 100%;
 }
 
-.m-m-fi-imageItem>span{
-	width:30px;
+.m-m-fi-imageItem > span {
+	width: 30px;
 	height: 30px;
 	position: absolute;
 	right: 0;
@@ -451,7 +632,7 @@ export default {
 	display: none;
 }
 
-.m-m-fi-imageItem:hover>span{
+.m-m-fi-imageItem:hover > span {
 	display: flex;
 }
 
@@ -478,4 +659,21 @@ export default {
 	cursor: pointer;
 	padding: 0 10px;
 }
+
+.fileList{
+	width: 100%;
+	position: relative;
+	display: flex;
+}
+
+.fl_img{
+	width: 50%;
+	height: auto;
+}
+
+.fl_video{
+	width: 48.5%;
+	margin-left: 1.5%;
+	height: auto;
+}
 </style>

+ 14 - 2
src/components/pages/classroomObservation/components/chatArea.vue

@@ -1055,6 +1055,8 @@ export default {
 					_this.editorBarData.type = "0";
 					flag = false;
 					_this.uploadFileLoading = false;
+					_this.transcriptionData.content = ""
+					_this.editorBarData.content = ""
 				}
 				_this.showGetTextLoading = true;
 				let privText = e.privText;
@@ -1088,6 +1090,7 @@ export default {
 			var _this = this;
 
 			if (file) {
+				this.loading = true;
 				var params = {
 					Key:
 						file.name.split(".")[0] +
@@ -1114,6 +1117,7 @@ export default {
 						if (err) {
 							_this.$message.error("上传失败");
 							_this.uploadFileLoading = false;
+							_this.loading = false;
 						} else {
 							// 判断是不是音频文件
 							const audioRegex = /\.(mp3|wav|ogg|flac|m4a)$/i;
@@ -1134,6 +1138,7 @@ export default {
 							if (audioRegex.test(data.Location)) {
 								_this.wavFileGetText(file);
 								_this.$emit("changeAudioUrl", data);
+								_this.loading = false;
 								return;
 							}
 							_this.ajax
@@ -1169,7 +1174,7 @@ export default {
 											_this.saveEditorBar();
 											// console.log("pdf、xlsx、doc、docx文件处理");
 										}
-
+										_this.loading = false;
 										if (!_this.fileIdId) return;
 										let pram2 = {
 											id: _this.fileIdId,
@@ -1289,9 +1294,13 @@ export default {
 			}
 		},
 		getData() {
+			this.loading = true;
 			this.getRoleList();
 			this.getPublicRoleList();
-			this.getChatList().then((_) => this.scrollBottom());
+			this.getChatList().then((_) => {
+				this.loading = false;
+				this.scrollBottom()
+			});
 		},
 		// 保存转录文稿和原文速览
 		saveEditorBar(flag = false) {
@@ -1305,9 +1314,12 @@ export default {
 				blob.name = `${this.tid}-classroomObservation.txt`;
 				this.uploadFile(blob);
 			} else {
+				this.loading = true;
 				this.$emit("updateTranscription", {
 					transcriptionData: this.transcriptionData.content,
 					editorBarData: this.editorBarData,
+				},()=>{
+					this.loading = false;
 				});
 			}
 		},

+ 141 - 28
src/components/pages/classroomObservation/components/messageArea.vue

@@ -23,6 +23,7 @@
 				:imageList="imageList.jsonData"
 				@saveData="saveBaseData"
 				@saveImage="saveBaseImage"
+				@saveVideo="saveBaseVideo"
 				@delImage="delBaseImageList"
 				v-loading="baseMessageLoading"
 			/>
@@ -30,8 +31,10 @@
 			<analysis
 				@updateMessage="updateMessage"
 				ref="analysis0"
+				:showBrief="showBrief"
 				@delItem="delAnalysisItem"
 				@editItem="editAnalysisItem"
+				@saveItem="saveAnalysis"
 				title="通用课堂分析"
 				:dialogTagDataList="dialogTagDataList"
 				:analysisItemList="dataList.filter((i) => i.Type === 0)"
@@ -43,9 +46,11 @@
 			<analysis
 				@updateMessage="updateMessage"
 				ref="analysis1"
+				:showBrief="showBrief"
 				@delItem="delAnalysisItem"
 				@editItem="editAnalysisItem"
-				title="科学课堂分析"
+				@saveItem="saveAnalysis"
+				title="学科课堂分析"
 				:dialogTagDataList="dialogTagDataList"
 				:analysisItemList="dataList.filter((i) => i.Type === 1)"
 				:type="1"
@@ -56,8 +61,10 @@
 			<analysis
 				@updateMessage="updateMessage"
 				ref="analysis2"
+				:showBrief="showBrief"
 				@delItem="delAnalysisItem"
 				@editItem="editAnalysisItem"
+				@saveItem="saveAnalysis"
 				title="扩展分析"
 				:dialogTagDataList="dialogTagDataList"
 				:analysisItemList="dataList.filter((i) => i.Type === 2)"
@@ -69,6 +76,7 @@
 			<!-- <analysis
 				@updateMessage="updateMessage"
 				ref="analysis3"
+				:showBrief="showBrief"
 				@delItem="delAnalysisItem"
 				@editItem="editAnalysisItem"
 				title="增值性分析"
@@ -110,7 +118,7 @@
 			/> -->
 			<!-- <div style="height: 10000px;"></div> -->
 		</div>
-		<el-dialog :center="true" :visible.sync="dialogVisible" width="1200px">
+		<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>
@@ -145,6 +153,10 @@
 					</div>
 				</div>
 				<div class="a-d-box">
+					<div class="a-d-b-subject">
+						<el-button :type="tagSubject==item?'primary':'default'" v-for="(item,index) in tagSubjectList" :key="index+'-'+tagIndex" @click.stop="tagSubject=item">{{ item }}</el-button>
+						<!-- {{ tagSubjectList }} -->
+					</div>
 					<div
 						style="
 							font-family: PingFang SC;
@@ -234,6 +246,7 @@ export default {
 			showBrief: true, //是否显示模块简介
 			dialogVisible: false,
 			tagIndex: 0,
+			tagSubject:'',
 			loading: false,
 			baseMessageLoading: false,
 			currencyLoading: false,
@@ -243,7 +256,7 @@ export default {
 			input2: "",
 			dialogTagList: [
 				{ id: 0, name: "通用课堂分析" },
-				{ id: 1, name: "学课堂分析" },
+				{ id: 1, name: "学课堂分析" },
 				{ id: 2, name: "扩展分析" },
 				//{ id: 3, name: "增值性分析" },
 			],
@@ -264,21 +277,21 @@ export default {
 				},
 				{
 					title: "布鲁姆问题分类",
-					brief: "多维度分析课堂整体情况",
+					brief: "不同认知层次问题分布情况",
 					value: "eac63117-00a7-11ef-aaca-12e77c4cb76b",
 					type: 0,
 					sum:405
 				},
 				{
 					title: "麦卡锡问题分类",
-					brief: "多维度分析课堂整体情况",
+					brief: "不同类型问题分布情况",
 					value: "18545cf7-0125-11ef-aaca-12e77c4cb76b",
 					type: 0,
 					sum:360
 				},
 				{
 					title: "学生回答情况",
-					brief: "多维度分析课堂整体情况",
+					brief: "学生回答情况分析",
 					value: "d3f75199-eb4e-11ee-aaca-12e77c4cb76b",
 					type: 0,
 					sum:206
@@ -300,43 +313,49 @@ export default {
 				// },
 				{
 					title: "课堂活动类型",
-					brief: "多维度分析课堂整体情况",
+					brief: "识别特定的课堂活动类型",
 					value: "41d2d2d4-0125-11ef-aaca-12e77c4cb76b",
+					subject:"科学",
 					type: 1,
 					sum:430
 				},
 				{
 					title: "学科核心素养发展",
-					brief: "学科核心素养发展",
+					brief: "分析与学科核心素养的匹配情况",
 					value: "b13a98de-0125-11ef-aaca-12e77c4cb76b",
+					subject:"科学",
 					type: 1,
 					sum:234
 				},
 				{
 					title: "科学教育目标分析",
-					brief: "科学教育目标分析",
+					brief: "分析四类科学教育目标的情况",
 					value: "b13a98de-0125-11ef-aaca-12e77c4cb76b",
+					subject:"科学",
 					type: 1,
 					sum:513
 				},
 				{
 					title: "PORTAAL课堂观察",
-					brief: "PORTAAL课堂观察",
+					brief: "使用PORTAAL框架分析科学课堂",
 					value: "8ab07d41-e143-11ee-aaca-12e77c4cb76b",
+					subject:"科学",
 					type: 1,
 					sum:173
 				},
 				{
 					title: "UTOP课堂观察",
-					brief: "UTOP课堂观察",
+					brief: "使用UTOP框架分析科学课堂",
 					value: "8e3a389b-014f-11ef-aaca-12e77c4cb76b",
+					subject:"科学",
 					type: 1,
 					sum:329
 				},
 				{
 					title:"L-PST模型",
-					brief: "L-PST模型",
+					brief: "使用L-PST框架分析科学课堂",
 					value: "e649112e-0150-11ef-aaca-12e77c4cb76b",
+					subject:"科学",
 					type: 1,
 					sum:421
 				},
@@ -348,8 +367,9 @@ export default {
 				// },
 				{
 					title: "RTOP课堂观察",
-					brief: "多维度分析课堂整体情况",
+					brief: "使用RTOP框架分析科学课堂",
 					value: "68265b18-0151-11ef-aaca-12e77c4cb76b",
+					subject:"科学",
 					type: 1,
 					sum:527
 				},
@@ -357,26 +377,84 @@ export default {
 					title: "课程质量评价",
 					brief: "多维度分析课堂整体情况", 
 				 	value:"25e53379-0152-11ef-aaca-12e77c4cb76b",
+					 subject:"科学",
 					type: 1,
 					sum:391
 				},
 				{
 					title: "SCOP课堂观察",
-					brief: "多维度分析课堂整体情况",
+					brief: "使用SCOP框架分析科学课堂",
 					value: "d0c76d35-0152-11ef-aaca-12e77c4cb76b",
+					subject:"科学",
 					type: 1,
 					sum:407
 				},
+				{
+					title:"KWL教学策略",
+					brief:"分析课前、课中、课后的教学成果",
+					value:"a5d8664b-1748-11ef-aaca-12e77c4cb76b",
+					subject:"语文",
+					type:1,
+					sum:135
+				},
+				{
+					title:"LICC课堂观察",
+					brief:"崔允漷教授团队的观察框架",
+					value:"9e8e6356-1769-11ef-aaca-12e77c4cb76b",
+					subject:"语文",
+					type:1,
+					sum:614
+				},
+				{
+					title:"读思达教学法",
+					brief:"分析课堂阅读、思考、表达的情况",
+					value:"d139ed78-176c-11ef-aaca-12e77c4cb76b",
+					subject:"语文",
+					type:1,
+					sum:346
+				},
+				{
+					title:"教学内容分析",
+					brief:"从教学内容角度观课评教",
+					value:"9e8e6356-1769-11ef-aaca-12e77c4cb76b",
+					subject:"语文",
+					type:1,
+					sum:527
+				},
+				{
+					title:"提问策略分析",
+					brief:"基于提问观察表分析课堂提问",
+					value:"eb815b01-1769-11ef-aaca-12e77c4cb76b",
+					subject:"语文",
+					type:1,
+					sum:389
+				},
+				{
+					title:"教师反馈分析",
+					brief:"分析语文课堂师生言语互动行为",
+					value:"55ae5176-176a-11ef-aaca-12e77c4cb76b",
+					subject:"语文",
+					type:1,
+					sum:319
+				},
+				{
+					title:"师生互动分析",
+					brief:"分析语文课堂四种不同的互动状态",
+					value:"8e4b6b48-176a-11ef-aaca-12e77c4cb76b",
+					subject:"语文",
+					type:1,
+					sum:191
+				},
 				{
 					title: "5E课程改编",
-					brief: "5E课程改编",
+					brief: "基于5E教学模型设计一堂课",
 					value: "f757826e-0125-11ef-aaca-12e77c4cb76b",
 					type: 2,
 					sum:510
 				},
 				{
 					title: "5EX课程改编",
-					brief: "5EX课程改编",
+					brief: "基于5EX教学模型设计一堂课",
 					value: "0b6b08b7-0126-11ef-aaca-12e77c4cb76b",
 					type: 2,
 					sum:611
@@ -390,13 +468,30 @@ export default {
 	},
 	computed: {
 		searchDataList() {
-			let _data = this.dialogTagDataList.filter((i) => i.type == this.tagIndex);
+			let _result = this.dialogTagDataList.filter((i) => i.type == this.tagIndex);
 			if (this.input2) {
-				return _data.filter((i) => i.title.indexOf(this.input2) > -1);
-			} else {
-				return _data;
+				_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;
+		}
+	},
+	watch:{
+		tagIndex(){
+			this.tagSubject = ''
+		}
 	},
 	methods: {
 		delAnalysisItem(id) {
@@ -425,7 +520,7 @@ export default {
 			let _index = this.dataList.findIndex((i) => i.id == id);
 			if (_index != -1) {
 				this.dataList[_index] = _data;
-				this.saveData(this.dataList[_index])
+				// this.saveData(this.dataList[_index])
 				this.$forceUpdate();
 			} else {
 				this.$message.info("执行错误");
@@ -671,6 +766,14 @@ export default {
 					console.log(e)
 				});
 		},
+		saveAnalysis(id,_data){
+			let data = this.dataList.find(i=>i.id==id);
+			if(data){
+				this.saveData(data).then(()=>{
+					this.$message.success("保存成功");
+				})
+			}
+		},
 		getData() {
 			this.dataList = [];
 			this.getCurrencyAndBaseMessageData();
@@ -758,6 +861,17 @@ export default {
 			this.imageList.json_data = JSON.stringify(this.imageList.jsonData);
 			this.saveData(this.imageList);
 		},
+		saveBaseVideo(newVideo){
+			if((this.imageList.jsonData.videoList && this.imageList.jsonData.videoList.length==0) || !this.imageList.jsonData.videoList){
+				this.imageList.jsonData.videoList = [];
+				this.imageList.jsonData.videoList.push(newVideo)
+			}else{
+				this.$message.error("最多只能上传3张图片");
+				return;
+			}
+			this.imageList.json_data = JSON.stringify(this.imageList.jsonData);
+			this.saveData(this.imageList);
+		},
 		delBaseImageList(key){
 			this.imageList.jsonData[key] = [];
 			this.imageList.json_data = JSON.stringify(this.imageList.jsonData);
@@ -815,6 +929,7 @@ export default {
 						fileList1: [],
 						fileList2: [],
 						fileList3: [],
+						videoList:[],
 					}),
 				};
 				this.ajax
@@ -842,17 +957,15 @@ export default {
 			});
 		},
 		// 修改基本信息的原文速览和转录文稿
-		updateMessageTranscription({transcriptionData,editorBarData}){
+		updateMessageTranscription({transcriptionData,editorBarData},fn){
 			this.bmData.jsonData['transcriptionData'] = transcriptionData;
 			this.bmData.jsonData['editorBarData'] = editorBarData;
 			this.saveData(this.bmData).then(res=>{
 				this.$message.success("保存成功");
+				fn?fn():'';
 			})
 		},
 	},
-	mounted() {
-		
-	},
 };
 </script>
 
@@ -1113,7 +1226,7 @@ export default {
 	align-items: center;
 	cursor: pointer;
 }
-.messageArea >>> .el-dialog {
+.addTemplateDialog >>> .el-dialog {
 	min-width: 1200px;
 
 	height: 700px;
@@ -1124,7 +1237,7 @@ export default {
 	/* margin: 0 auto; */
 	overflow: hidden;
 }
-.messageArea >>> .el-dialog__body {
+.addTemplateDialog >>> .el-dialog__body {
 	height: 100%;
 	min-width: 1200px;
 	flex-shrink: 0;
@@ -1132,7 +1245,7 @@ export default {
 	padding-bottom: 50px;
 	padding-top: 10px;
 }
-.messageArea >>> .el-dialog__header {
+.addTemplateDialog >>> .el-dialog__header {
 	display: none;
 }
 .itemTit {

+ 103 - 0
src/components/pages/classroomObservation/components/previewVideoDialog.vue

@@ -0,0 +1,103 @@
+<template>
+    <!-- <el-dialog
+      title="视频预览"
+      :visible.sync="dialogVisible"
+
+    >
+		<video-player
+			v-if="option.url"
+      style="width: 100%;height: 100%;"
+      :playsinline="true"
+      :options="option"
+    ></video-player>
+    </el-dialog> -->
+
+		<el-dialog
+		  title="视频预览"
+		  :visible.sync="dialogVisible"
+			show-close
+			top="3vh"
+			width="60vw"
+			:before-close="handleClose">
+			<div class="video-player-box" v-if="option.sources!=''">
+				<video-player
+    	  style="width: 100%;height: 100%;display: flex;justify-content: center;align-items: center;"
+    	  :playsinline="true"
+    	  :options="option"
+    	></video-player>
+			</div>
+		  <span slot="footer" class="dialog-footer">
+		    <el-button @click="close()">取 消</el-button>
+		    <el-button type="primary" @click="close()">确 定</el-button>
+		  </span>
+		</el-dialog>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      dialogVisible: false,
+      loading: false,
+      option:{
+				playbackRates: [0.7, 1.0, 1.5, 2.0], // 播放速度
+        autoplay: false, //如果true,浏览器准备好时开始回放。
+        muted: false, // 默认情况下将会消除任何音频。
+        loop: false, // 导致视频一结束就重新开始。
+        preload: 'auto', // 建议浏览器在<video>加载元素后是否应该开始下载视频数据。auto浏览器选择最佳行为,立即开始加载视频(如果浏览器支持)
+        language: 'zh-CN',
+        aspectRatio: '16:9', // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3")
+        fluid: true, // 当true时,Video.js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。
+        sources: "",
+        // poster: "https://p1.music.126.net/5zs7IvmLv7KahY3BFzUmrg==/109951163635241613.jpg?param=600y500", // 你的封面地址
+        notSupportedMessage: '此视频暂无法播放,请稍后再试', // 允许覆盖Video.js无法播放媒体源时显示的默认信息。
+        controlBar: {
+            timeDivider: true,
+            durationDisplay: true,
+            remainingTimeDisplay: false,
+            fullscreenToggle: true  // 全屏按钮
+        }
+
+			}
+    };
+  },
+  watch: {
+    
+  },
+  methods: {
+    open(url) {
+      this.dialogVisible = true;
+			this.option.sources = url;
+    },
+    close() {
+      this.dialogVisible = false;
+      this.option.sources = "";
+    },
+		handleClose(){
+			this.close();
+		}
+  }
+};
+</script>
+
+<style scoped>
+
+.video-player-box{
+	width: 100%;
+	height: 100%;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+}
+
+.video-player-box >>> .video-js{
+	width: 100%;
+	height: 100%;
+}
+
+.video-player-box >>> .vjs-big-play-button{
+	top: 50%;
+	left: 50%;
+	transform: translate(-50%, -50%);
+}
+</style>

+ 34 - 12
src/components/pages/classroomObservation/index.vue

@@ -52,25 +52,32 @@
 			</div>
 			<div class="co-h2-right">
 				<div
-					class="co-h2-r-btn co-h2-r-blueBtn"
+					:class="['co-h2-r-btn',fileId?'':'ca-h2-r-noActive']"
 					style="background: rgba(54, 129, 252, 1)"
 					@click.stop="getReport()"
 				>
 					<span class="co-h2-r-b-icon1"></span>
-					<div>生成报告</div>
+					<div style="color:white">一键分析</div>
 				</div>
-				<div class="co-h2-r-btn2" @click.stop="preview()">
-					<!-- <span class="co-h2-r-b-icon2"></span> -->
+
+				<div
+				:class="['co-h2-r-btn',fileId?'':'ca-h2-r-noActive']"
+					style="background: #FFFFFF"
+					@click.stop="preview()"
+				>
+					<span class="co-h2-r-b-icon2"></span>
+					<div style="color:black">查看报告</div>
+				</div>
+				<!-- <div class="co-h2-r-btn2" @click.stop="preview()">
 					<el-tooltip class="item" effect="light" content="预览" placement="top">
 						<img
 						src="../../../assets/icon/classroomObservation/Syan.png"
 						alt=""
 					/>
     			</el-tooltip>
-					
-					<!-- <div>预览</div> -->
-				</div>
-				<div class="co-h2-r-btn2" @click.stop="shareBtn">
+				</div> -->
+
+				<div :class="['co-h2-r-btn2']" @click.stop="shareBtn">
 					<!-- <span class="co-h2-r-b-icon3"></span> -->
 					<el-tooltip class="item" effect="light" content="分享" placement="top">
 						<img
@@ -206,6 +213,7 @@ export default {
 		},
 		// 生成报告
 		getReport() {
+			if(!this.fileId)return;
 			this.$refs.messageAreaRef.getReport();
 			// let assistant_title = [
 			// 	"课堂观察",
@@ -245,6 +253,7 @@ export default {
 		},
 		//预览
 		preview() {
+			if(!this.fileId)return;
 			window.parent.postMessage(
 				{
 					tools: "classroom_observation_board",
@@ -255,6 +264,7 @@ export default {
 		},
 		// 分享
 		shareBtn() {
+			// if(!this.fileId)return;
 			this.dialogVisibleShare = !this.dialogVisibleShare;
 		},
 		delCourse(_value = this.tid) {
@@ -339,11 +349,11 @@ export default {
 					});
 			});
 		},
-		updateTranscription({ transcriptionData, editorBarData }) {
+		updateTranscription({ transcriptionData, editorBarData },fn) {
 			this.$refs.messageAreaRef.updateMessageTranscription({
 				transcriptionData,
 				editorBarData,
-			});
+			},fn);
 		},
 		changeTranscription({ transcriptionData, editorBarData }) {
 			this.$refs.chatAreaRef.changeEditorBar({
@@ -498,6 +508,12 @@ export default {
 	/* border: solid 1px #3681FC; */
 	border-radius: 5px;
 }
+
+.ca-h2-r-noActive{
+	opacity: .5 !important; 
+	cursor: not-allowed !important;
+}
+
 .co-h2-r-btn2 {
 	width: auto;
 	box-sizing: border-box;
@@ -525,6 +541,12 @@ export default {
 	background-size: 100% 100%;
 }
 
+.co-h2-r-b-icon2{
+	background: url("../../../assets/icon/classroomObservation/Syan.png")
+		no-repeat;
+	background-size: 100% 100%;
+}
+
 /* .co-h2-r-b-icon2 {
 	background: url("../../../assets/icon/classroomObservation/daoChu.png")
 		no-repeat;
@@ -536,11 +558,11 @@ export default {
 	background-size: 100% 100%;
 } */
 
-.co-h2-r-blueBtn {
+/* .co-h2-r-blueBtn {
 	background: rgba(134, 179, 253, 1);
 
 	color: white;
-}
+} */
 
 .co-main {
 	width: 100%;

+ 1 - 1
src/components/pages/course.vue

@@ -32,7 +32,7 @@
               <!-- <div type="primary" @click="goToCourse2()">任务式课程</div> -->
               <!-- <div type="primary" @click="goToCourse()">阶段式课程</div> -->
               <div type="primary" @click="goToCourse4()">阶段式课程</div>
-              <div type="primary" @click="goToCourse5()" v-show="org == '1973f6c7-1561-11ee-91d8-005056b86db5' || org == '777559d2-7239-11ee-b98c-005056b86db5'">AI模式</div>
+              <div type="primary" @click="goToCourse5()" v-show="org == '1973f6c7-1561-11ee-91d8-005056b86db5' || org == '777559d2-7239-11ee-b98c-005056b86db5' || org == '884c5665-a453-46f3-b7b6-01d575290aa9'">AI模式</div>
             </div>
           </button>
         </div>

Some files were not shown because too many files changed in this diff