SanHQin 1 ano atrás
pai
commit
b51ba20f40

+ 9 - 0
src/api/classObserve.js

@@ -20,6 +20,15 @@ export function updateObsRequest(data){//保存分析数据
   })
 }
 
+export function chatRequest(data){//对话
+	return request2({
+    url: 'https://gpt4.cocorobo.cn/ai_agent_park_chat',
+    method: 'post',
+    data,
+    hideloading: true
+  })
+}
+
 export function getObsRequest(data){//获取分析数据
 	return request2({
     url: 'https://gpt4.cocorobo.cn/get_classroom_observation_new',

+ 24 - 0
src/assets/images/classObserve/generate.svg

@@ -0,0 +1,24 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g clip-path="url(#clip0_596_2943)">
+<path d="M5.13724 5.78772C5.03644 6.20372 4.98295 6.63824 4.98295 7.08532C4.98295 9.22704 6.21038 11.0821 8.0001 11.9854C7.25816 12.3601 6.41953 12.571 5.53153 12.571C4.57518 12.571 3.67621 12.3262 2.89313 11.8961L2.59941 11.435C1.96673 10.4426 1.6001 9.26384 1.6001 7.99961C1.6001 4.90429 3.79758 2.32212 6.71758 1.7283C7.13198 1.64395 7.56078 1.59961 8.0001 1.59961C8.43941 1.59961 8.86821 1.64395 9.28261 1.7283C8.83187 1.8275 8.4017 1.98224 8.0001 2.18521C6.58387 2.89995 5.51987 4.21058 5.13724 5.78772Z" fill="url(#paint0_linear_596_2943)"/>
+<path d="M13.4008 11.4353C13.4568 11.1214 13.4858 10.7982 13.4858 10.4684C13.4858 8.48783 12.4362 6.75252 10.8629 5.78794C10.0296 5.27709 9.04921 4.98269 8.00006 4.98269C6.95092 4.98269 5.97058 5.27709 5.13721 5.78794C5.51984 4.2108 6.58384 2.90017 8.00006 2.18543C8.40166 1.98246 8.83184 1.82772 9.28258 1.72852C12.2026 2.32234 14.4001 4.90452 14.4001 7.99983C14.4001 9.26406 14.0334 10.4428 13.4008 11.4353Z" fill="url(#paint1_linear_596_2943)"/>
+<path d="M13.4861 10.4676C13.4861 10.8182 13.4534 11.1611 13.3901 11.4934L13.0563 11.9231C11.8856 13.4296 10.0561 14.399 8.00034 14.399C5.94456 14.399 4.11508 13.4296 2.94434 11.9231C3.71531 12.3361 4.59622 12.5704 5.53176 12.5704C6.46731 12.5704 7.25839 12.3595 8.00034 11.9848C9.79005 11.0815 11.0175 9.22642 11.0175 7.08471C11.0175 6.63762 10.964 6.20311 10.8632 5.78711C12.4365 6.75168 13.4861 8.487 13.4861 10.4676Z" fill="url(#paint2_linear_596_2943)"/>
+</g>
+<defs>
+<linearGradient id="paint0_linear_596_2943" x1="2.2321" y1="11.235" x2="10.5107" y2="2.95641" gradientUnits="userSpaceOnUse">
+<stop stop-color="#364EE7"/>
+<stop offset="1" stop-color="#938DFF"/>
+</linearGradient>
+<linearGradient id="paint1_linear_596_2943" x1="6.99824" y1="2.798" x2="14.518" y2="10.318" gradientUnits="userSpaceOnUse">
+<stop stop-color="#364EE7"/>
+<stop offset="1" stop-color="#2CCAFF"/>
+</linearGradient>
+<linearGradient id="paint2_linear_596_2943" x1="11.4051" y1="6.10002" x2="6.53108" y2="14.5421" gradientUnits="userSpaceOnUse">
+<stop stop-color="#364EE7"/>
+<stop offset="1" stop-color="#4DE69A"/>
+</linearGradient>
+<clipPath id="clip0_596_2943">
+<rect width="12.8" height="12.8" fill="white" transform="translate(1.6001 1.59961)"/>
+</clipPath>
+</defs>
+</svg>

+ 3 - 0
src/assets/images/classObserve/success.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="M6.82591 11.9987C6.66084 11.9987 6.50208 11.937 6.38237 11.8248L2.96638 8.63944C2.71059 8.40129 2.70177 8.00563 2.94622 7.75615C3.19067 7.50666 3.59767 7.4991 3.85346 7.73724L6.77047 10.4577L12.0614 4.19651C12.287 3.93064 12.6914 3.89158 12.9649 4.11083C13.2383 4.33008 13.2774 4.72321 13.0531 4.99034L7.32237 11.7719C7.20896 11.9067 7.04264 11.9886 6.86497 11.9987H6.82591Z" fill="#17C469"/>
+</svg>

+ 155 - 13
src/views/classObserve/components/analysisItem.vue

@@ -6,7 +6,7 @@
         <van-icon v-else name="arrow-down" />
         <span class="tit">{{ data.jsonData ? data.jsonData.name : '' }}</span>
       </div>
-      <van-popover placement="bottom-end" v-model="abuShow">
+      <van-popover placement="bottom-end" v-model="abuShow" v-if="[0].includes(status)">
         <div class="abu">
           <!-- <div class="abuBtn">
                 <img src="../../assets/images/classObserve/addTel.png" alt="" />
@@ -21,6 +21,19 @@
           <img @click.stop="abuShowItem" src="../../../assets/images/classObserve/colD.png" alt="" />
         </template>
       </van-popover>
+			<div class="oc_status" v-if="[1,2,3].includes(status)">
+				<div v-if="[1].includes(status)">
+					<img src="../../../assets/images//classObserve/generate.svg">
+					<span>优化中...</span>
+				</div>
+				<div v-if="[2].includes(status)">
+					<span style="color:#e60012;">生成失败</span>
+				</div>
+				<div v-if="[3].includes(status)">
+					<img src="../../../assets/images//classObserve/success.svg">
+					<span style="color:#17C469">生成成功</span>
+				</div>
+			</div>
     </div>
     <div v-show="show">
       <div class="brief">
@@ -30,11 +43,11 @@
         <!-- {{ data.jsonData }} -->
         <mdView :text="data.jsonData ? data.jsonData.content : ''" />
       </div>
-      <div class="outcomeBtn">
-        <div @click.stop="down()">
-          <img src="../../../assets/images/classObserve/revoke.png" alt="" /><span>撤销</span>
+      <div class="outcomeBtn" v-if="[0,2,3].includes(status)">
+        <div @click.stop="down()" :class="[historyIndex==0?'ob_no':'']">
+          <img src="../../../assets/images/classObserve/restore.png" alt="" style="transform:rotateY(180deg);"/><span>撤销</span>
         </div>
-        <div @click.stop="up()">
+        <div @click.stop="up()" :class="[(historyIndex>=history.length-1)?'ob_no':'']">
           <img src="../../../assets/images/classObserve/restore.png" alt="" /><span>恢复</span>
         </div>
         <div @click.stop="optimize()">
@@ -47,12 +60,26 @@
 
 <script>
 import mdView from './mdView.vue'
+import { v4 as uuidv4 } from "uuid";
+import {chatRequest,updateObsRequest} from '@/api/classObserve'
 export default {
   props: {
     data: {
       type: Object,
       default: () => {}
-    }
+    },
+		analysisList:{
+			type:Array,
+			default:()=>[]
+		},
+		bmData:{
+			type:Object,
+			default:()=>{}
+		},
+		fileId:{
+			type:String,
+			default:""
+		}
   },
   components: {
     mdView
@@ -60,30 +87,118 @@ export default {
   data() {
     return {
       show: false,
-      abuShow: false
+      abuShow: false,
+			historyIndex:0,
+			history:[],
+			userId:this.$store.state.user.id,
+			status:0,// 0:正常 1:优化中  2:优化成功  3:优化失败
     }
   },
 
   methods: {
     showItem() {
+			if(![0,2,3].includes(this.status))return this.$toast("正在优化中...")
       this.show = !this.show
+			this.status = 0;
     },
     abuShowItem() {
       this.abuShow = true
     },
     up() {
-      console.log('恢复')
+      if(this.historyIndex < this.history.length - 1){
+				this.historyIndex++;
+				this.data.jsonData = JSON.parse(JSON.stringify(this.history[this.historyIndex]))
+				this.data.json_data = JSON.stringify(this.data.jsonData)
+				this.saveData(this.data).then(_=>{
+					console.log('保存成功')
+				})
+			}
     },
     down() {
-      console.log('撤销')
+      if(this.historyIndex>0){
+				this.historyIndex--;
+				this.data.jsonData = JSON.parse(JSON.stringify(this.history[this.historyIndex]))
+				this.data.json_data = JSON.stringify(this.data.jsonData)
+				this.saveData(this.data).then(_=>{
+					console.log('保存成功')
+				})
+			}
     },
     optimize() {
-      console.log('优化')
+      this.show = false;
+			this.status = 1;
+			let assistant = this.analysisList.find(
+					(i) => i.title == this.data.jsonData.name
+				);
+			if (!assistant.value) {
+					this.status = 2;
+					return this.$toast.fail("未找到对应的AI助手");
+				}
+			let _msg = `使用文件检索的方式完整的去分析文件内容,并请完全按照要求输出。`
+
+			if(assistant.value=='6b4a9650-48be-11ef-936b-12e77c4cb76b'){
+					_msg  = `使用文件检索的方式完整的去分析文件内容,并基于以下的课堂基本内容,使用cpote课程设计模型改编一堂同主题的课程。
+课堂名称:${this.bmData.courseName}  搜课年级:${this.bmData.grade}  授课科目:${this.bmData.subject}`
+					
+				}
+				let params = {
+					assistant_id: assistant?assistant.value:null,
+					message:_msg,
+					session_name: uuidv4(),
+					userId: this.userId,
+					file_ids: this.fileId?[this.fileId]:'',
+					model: "gpt-4o-2024-08-06",
+				};
+				chatRequest(params).then(res=>{
+					let _data = res.FunctionResponse;
+					let _copyData = JSON.parse(JSON.stringify(this.data));
+					_copyData.jsonData.content = _data.message;
+					_copyData.jsonData.dataFileList = [];
+					_copyData.jsonData.fileList = [];
+					_copyData.json_data = JSON.stringify(_copyData.jsonData);
+
+					if (this.history.length == 0) {
+						this.history.push(_copyData.jsonData);
+					} else {
+						this.history.splice(
+							this.historyIndex + 1,
+							0,
+							_copyData.jsonData
+						);
+					}
+					this.up();
+					this.status = 3;
+				}).catch(e=>{
+					console.log(e)
+					this.status = 2;
+				})
+				
     },
+		saveData(params){
+			return new Promise((resolve, reject) => {
+        updateObsRequest({
+          id: params.id,
+          json_data: JSON.stringify(params.jsonData)
+        })
+          .then(res => {
+            resolve()
+          })
+          .catch(e => {
+						console.log(e)
+						console.log("保存失败")
+            // this.$toast.fail('保存失败')
+            resolve()
+          })
+      })
+		},
     del() {
       this.$parent.delItem(this.data)
     }
-  }
+  },
+	mounted(){
+		this.historyIndex = 0;
+		this.history.push(JSON.parse(JSON.stringify(this.data.jsonData)))
+	},
 }
 </script>
 
@@ -122,11 +237,17 @@ export default {
   display: flex;
   justify-content: space-around;
   padding: 10px 0;
+	.ob_no{
+		opacity: .6;
+	}
   div {
     display: flex;
+		align-items: center;
+		font-size: 12px;
     img {
-      width: 16px;
-      height: 16px;
+      width: 18px;
+      height: 18px;
+			margin-right: 5px;
     }
   }
 }
@@ -134,6 +255,7 @@ export default {
 .brief {
   font-style: italic;
   color: #6b798e;
+	font-size: 14px;
 }
 
 .oc_title {
@@ -145,4 +267,24 @@ export default {
 		margin-left: 10px;
   }
 }
+
+.oc_status{
+	width: auto;
+	height: 100%;
+	display: flex;
+	justify-content: flex-end;
+	align-items: center;
+	font-size: 14px;
+	div{
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		img{
+			margin-right: 5px;
+			width: 1.5em;
+			height: 1.5em;
+		}
+
+	}
+}
 </style>

+ 1 - 0
src/views/classObserve/components/mdView.vue

@@ -53,6 +53,7 @@ export default {
 .mdView {
 	max-width: 100%;
 	height: 100%;
+	font-size: 15px;
 }
 
 .mdView >>>.table{

+ 403 - 213
src/views/classObserve/homePage.vue

@@ -43,18 +43,17 @@
 				<div class="nt_btn">创建新的课堂</div>
 			</div> -->
       <div class="chat">
-        <div class="chatTxt" v-text="bmData.jsonData ? bmData.jsonData.transcriptionData : ''"></div>
+        <div
+          ref="transcriptionDataRef"
+          class="chatTxt"
+          v-text="bmData.jsonData ? bmData.jsonData.transcriptionData : ''"
+        ></div>
         <img src="../../assets/images/classObserve/waveanimation.png" alt="" />
         <div class="time">{{ recordedForm.time }}</div>
       </div>
       <div class="controlArea" v-loading="recordedForm.loading">
         <div class="ca_left">
-          <img
-            
-            @click="goChat"
-            src="../../assets/images/classObserve/rootper.svg"
-            alt=""
-          />
+          <img @click="goChat" src="../../assets/images/classObserve/rootper.svg" alt="" />
           <van-popover placement="top" v-model="changeLanguageShow" trigger="click">
             <div class="languageList">
               <div
@@ -67,7 +66,7 @@
               </div>
             </div>
             <template #reference>
-              <img  src="../../assets/images/classObserve/langcut.svg" alt="" />
+              <img src="../../assets/images/classObserve/langcut.svg" alt="" />
             </template>
           </van-popover>
         </div>
@@ -88,21 +87,20 @@
         </div>
         <div class="ca_right">
           <img
-						style="transform: scale(1.1,1.1);"
+            style="transform: scale(1.1,1.1);"
             src="../../assets/images/classObserve/suspend.svg"
             alt=""
             v-if="[1].includes(recordedForm.status)"
             @click.stop="stopRecord"
           />
           <img
-						
             src="../../assets/images/classObserve/start.svg"
             alt=""
             v-if="[2].includes(recordedForm.status)"
             @click.stop="reStartRecord"
           />
           <img
-						style="transform: scale(.8,.8);"
+            style="transform: scale(.8,.8);"
             src="../../assets/images/classObserve/uploadFile.svg"
             alt=""
             v-if="[0, 3].includes(recordedForm.status)"
@@ -182,7 +180,7 @@
       </div>
     </van-action-sheet>
 
-		<!-- 录音转文字 -->
+    <!-- 录音转文字 -->
     <iframe
       allow="camera *; microphone *;display-capture;midi;encrypted-media;"
       src="https://beta.cloud.cocorobo.cn/browser/public/index.html"
@@ -195,46 +193,44 @@
 <script>
 import { Dialog } from 'vant'
 import { loginOut } from '@/api/user'
-import _ from "lodash";
-import Papa from "papaparse";
+import _ from 'lodash'
+import Papa from 'papaparse'
 import '../../utils/aws-sdk-2.235.1.min.js'
-import {upload_file_knowledgeRequest } from '@/api/classObserve.js'
+import { upload_file_knowledgeRequest } from '@/api/classObserve.js'
 
-const getFile = (url) => {
+const getFile = url => {
   return new Promise((resolve, reject) => {
     var credentials = {
-      accessKeyId: "AKIATLPEDU37QV5CHLMH",
-      secretAccessKey: "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",
-    }; //秘钥形式的登录上传
-    window.AWS.config.update(credentials);
-    window.AWS.config.region = "cn-northwest-1"; //设置区域
-    let url2 = url;
-    let _url2 = "";
-    if (url2.indexOf("https://view.officeapps.live.com/op/view.aspx?src=") != -1) {
-      _url2 = url2.split("https://view.officeapps.live.com/op/view.aspx?src=")[1];
+      accessKeyId: 'AKIATLPEDU37QV5CHLMH',
+      secretAccessKey: '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'
+    } //秘钥形式的登录上传
+    window.AWS.config.update(credentials)
+    window.AWS.config.region = 'cn-northwest-1' //设置区域
+    let url2 = url
+    let _url2 = ''
+    if (url2.indexOf('https://view.officeapps.live.com/op/view.aspx?src=') != -1) {
+      _url2 = url2.split('https://view.officeapps.live.com/op/view.aspx?src=')[1]
     } else {
-      _url2 = url2;
+      _url2 = url2
     }
-    var s3 = new window.AWS.S3({ params: { Bucket: "ccrb" } });
-    let name = decodeURIComponent(
-      _url2.split("https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/")[1]
-    );
+    var s3 = new window.AWS.S3({ params: { Bucket: 'ccrb' } })
+    let name = decodeURIComponent(_url2.split('https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/')[1])
     var params = {
-      Bucket: "ccrb",
-      Key: name,
-    };
-    s3.getObject(params, function (err, data) {
+      Bucket: 'ccrb',
+      Key: name
+    }
+    s3.getObject(params, function(err, data) {
       if (err) {
-        console.log(err, err.stack);
-        resolve({ data: 1 });
+        console.log(err, err.stack)
+        resolve({ data: 1 })
       } else {
-        const fileContent = data.Body.toString("utf-8");
-        resolve({ data: fileContent });
+        const fileContent = data.Body.toString('utf-8')
+        resolve({ data: fileContent })
       } // sxuccessful response
-    });
+    })
     // axios({
-  });
-};
+  })
+}
 export default {
   props: {
     page: {
@@ -257,7 +253,7 @@ export default {
   data() {
     return {
       isParse: false,
-			loading:false,
+      loading: false,
       recordedForm: {
         time: '00:00:00', //时间
         status: 0, //0--未录音  1--正在录音  2--暂停  3--录音结束
@@ -270,7 +266,7 @@ export default {
         loading: false
       },
       historyShow: false,
-			uploadFileLoading:false,
+      uploadFileLoading: false,
       abuShowId: '',
       historyListLoading: false,
       addNewCourseShow: false,
@@ -324,108 +320,310 @@ export default {
       this.isParse = !this.isParse
     },
     endRecord() {
-			if(this.recordedForm.loading)return;
-      console.log('结束录音')
-      this.recordedForm.status = 3
+      if (this.recordedForm.loading) return this.$toast('请稍等')
+      if ([1].includes(this.recordedForm.status)) {
+        //正在录音时暂停
+        let iiframe = this.$refs['iiframe']
+        iiframe.contentWindow.window.document.getElementById('scenarioStopButton').click()
+        // 录音借宿
+        iiframe.contentWindow.onSessionStopped = (s, e) => {
+          this.recordedForm.status = 3
+          // this.controlsStatus = 2;
+          // this.showGetTextLoading = false;
+          this.$toast('已结束录音')
+          clearInterval(this.recordedForm.timer)
+          console.log('结束录音👇')
+          console.log('结束录音', e)
+          this.recordedForm.audioBlob.push(e.preaudio)
+          let blob = new Blob(this.recordedForm.audioBlob, {
+            type: 'audio/wav'
+          })
+          let file = new File([blob], 'recordedFile.wav', {
+            type: 'text/plain'
+          })
+          this.uploadFile(file, { changeText: false, flag: true })
+          iiframe.contentWindow.onSessionStopped = null
+          iiframe.contentWindow.onRecognizedResult = null
+        }
+      } else if ([2].includes(this.recordedForm.status)) {
+        //暂停时结束录音
+        //暂停录音时
+        this.recordedForm.status = 3
+        // this.controlsStatus = 2;
+        // this.showGetTextLoading = false;
+        clearInterval(this.recordedForm.timer)
+        let blob = new Blob(this.recordedForm.audioBlob, {
+          type: 'audio/wav'
+        })
+        let file = new File([blob], 'recordedFile.wav', { type: 'text/plain' })
+        this.uploadFile(file, { changeText: false, flag: true })
+      }
     },
     startRecord() {
-			// if(this.recordedForm.loading)return;
-			// if(!this.tid){
-			// 	return this.$parent.addNewCourseByDefault().then(_=>{
-			// 		this.startRecord()
-			// 	})
-			// }
-			// this.$toast.success("已开始录音")
+      if (this.recordedForm.loading) return this.$toast('请稍等')
+      if (!this.tid) {
+        return Dialog.confirm({
+          title: '创建课堂并录音',
+          message: `确定使用默认模板来创建新的课堂并开始录音?`
+        })
+          .then(() => {
+            return this.$parent.addNewCourseByDefault().then(_ => {
+              this.startRecord()
+            })
+          })
+          .catch(_ => {
+            console.log('不创建')
+          })
+      }
+      // this.$toast.success("已开始录音")
       // console.log('开始录音')
-      this.recordedForm.status = 1
+      if (this.uploadFileLoading) return this.$toast('请稍等...')
+      if ([0].includes(this.recordedForm.status)) {
+        Dialog.confirm({
+          title: '开始录音',
+          message: `确定开始录音?`
+        })
+          .then(() => {
+            let iiframe = this.$refs['iiframe']
+            // 设置语言
+            iiframe.contentWindow.window.document.getElementById(
+              'languageOptions'
+            ).selectedIndex = this.choiceLanguageIndex
+
+            iiframe.contentWindow.testdoContinuousPronunciationAssessment()
+
+            this.recordedForm.status = 1
+            this.$toast('已开始录音')
+            this.recordedForm.timer = setInterval(() => {
+              this.recordedForm.timeDuration += 1
+              this.recordedForm.time = this.updateRecordedTime({
+                duration: this.recordedForm.timeDuration
+              })
+            }, 1000)
+
+            let flag = true
+            this.recordedForm.textList = []
+            this.recordedForm.timeDuration = 0
+            this.recordedForm.startTime = 1
+            this.recordedForm.endTime = 0
+
+            iiframe.contentWindow.onRecognizedResult = e => {
+              this.recordedForm.endTime = this.recordedForm.timeDuration
+              if (flag) {
+                // this.controlsStatus = 1
+                // this.showIndexPage = false
+                // this.pageStatus = 2
+                this.$parent.bmData.jsonData.editorBarData.type = '0'
+                flag = false
+                this.uploadFileLoading = false
+                this.$parent.bmData.jsonData.transcriptionData = ''
+                this.$parent.bmData.jsonData.editorBarData.content = ''
+                this.recordedForm.textList = []
+              }
+              let privText = e.privText
+              if (privText == undefined || privText == 'undefined') return
+              console.log('👇转译对象👇')
+              console.log(e)
+              console.log('👇转译结果👇')
+              console.log(privText)
+              this.recordedForm.textList.push({
+                value: privText,
+                startTime: this.updateRecordedTime({
+                  duration: this.recordedForm.startTime
+                }),
+                endTime: this.updateRecordedTime({
+                  duration: this.recordedForm.endTime
+                }),
+                time: this.updateRecordedTime({
+                  duration: this.recordedForm.endTime - this.recordedForm.startTime
+                })
+              })
+              this.recordedForm.startTime = this.recordedForm.timeDuration + 1
+              this.$parent.bmData.jsonData.transcriptionData += privText
+              this.$nextTick(
+                () => (this.$refs.transcriptionDataRef.scrollTop = this.$refs.transcriptionDataRef.scrollHeight)
+              )
+              let _result = `<table border="0" width="100%" cellpadding="0" cellspacing="0" style="text-align: center"><tbody><tr><th>序号</th><th>开始时间</th><th>结束时间</th><th>发言内容</th><th>时长</th><th>说话人身份</th><th>行为编码</th></tr>`
+              this.recordedForm.textList.forEach((item, index) => {
+                _result += `<tr><td>${index + 1}</td><td>${item.startTime}</td><td>${item.endTime}</td><td>${
+                  item.value
+                }</td><td>${item.time}</td><td></td><td></td></tr>`
+              })
+              _result += `<tr><td></td><td></td><td></td><td></td><td></td><td></td></tr></tbody></table>`
+              this.$parent.bmData.jsonData.editorBarData.content = _result
+            }
+          })
+          .catch((e) => {
+						console.log(e)
+            console.log('不录音')
+          })
+      } else if ([1, 2].includes(this.recordedForm.status)) {
+        this.$toast.fail('正在录音中')
+      } else {
+        this.$toast('请稍等...')
+      }
     },
     stopRecord() {
-			if(this.recordedForm.loading)return;
-      console.log('暂停录音')
-      this.recordedForm.status = 2
+      if (this.recordedForm.loading) return this.$toast('请稍等...')
+      if ([1].includes(this.recordedForm.status)) {
+        // 录音暂停
+        //暂停
+        this.recordedForm.loading = true
+        let iiframe = this.$refs['iiframe']
+        iiframe.contentWindow.window.document.getElementById('scenarioStopButton').click()
+        // 录音结束
+        iiframe.contentWindow.onSessionStopped = (s, e) => {
+          this.recordedForm.status = 2
+          this.$toast('已停止录音')
+          clearInterval(this.recordedForm.timer)
+          console.log('停止录音👇')
+          console.log('停止录音', e)
+          this.recordedForm.audioBlob.push(e.preaudio)
+          iiframe.contentWindow.onSessionStopped = null
+          iiframe.contentWindow.onRecognizedResult = null
+          this.recordedForm.loading = false
+        }
+      } else {
+        console.log('状态错误')
+        // this.$toast()
+      }
     },
     reStartRecord() {
-			if(this.recordedForm.loading)return;
-      console.log('继续录音')
-      this.recordedForm.status = 1
+      if ([2].includes(this.recordedForm.status)) {
+        //录音开启
+        this.recordedForm.loading = true
+        let iiframe = this.$refs['iiframe']
+        iiframe.contentWindow.window.document.getElementById('languageOptions').selectedIndex = this.choiceLanguageIndex
+        iiframe.contentWindow.testdoContinuousPronunciationAssessment()
+        // this.controlsStatus = 1;
+        this.recordedForm.status = 1
+        this.$toast('已继续录音')
+        this.recordedForm.loading = false
+        this.recordedForm.timer = setInterval(() => {
+          this.recordedForm.timeDuration += 1
+          this.recordedForm.time = this.updateRecordedTime({
+            duration: this.recordedForm.timeDuration
+          })
+        }, 1000)
+        iiframe.contentWindow.onRecognizedResult = e => {
+          this.recordedForm.endTime = this.recordedForm.timeDuration
+          // this.showGetTextLoading = true;
+          let privText = e.privText
+          if (privText == undefined || privText == 'undefined') return
+          console.log('👇转译对象👇')
+          console.log(e)
+          console.log('👇转译结果👇')
+          console.log(privText)
+          this.recordedForm.textList.push({
+            value: privText,
+            startTime: this.updateRecordedTime({
+              duration: this.recordedForm.startTime
+            }),
+            endTime: this.updateRecordedTime({
+              duration: this.recordedForm.endTime
+            }),
+            time: this.updateRecordedTime({
+              duration: this.recordedForm.endTime - this.recordedForm.startTime
+            })
+          })
+          this.recordedForm.startTime = this.recordedForm.timeDuration + 1
+          this.$parent.bmData.jsonData.transcriptionData += privText
+
+          let _result = `<table border="0" width="100%"	cellpadding="0"	cellspacing="0" style="text-align: center"><tbody><tr><th>序号</th><th>开始时间</th><th>结束时间</th><th>发言内容</th><th>时长</th><th>说话人身份</th><th>行为编码</th></tr>`
+          this.recordedForm.textList.forEach((item, index) => {
+            _result += `<tr><td>${index + 1}</td><td>${item.startTime}</td><td>${item.endTime}</td><td>${
+              item.value
+            }</td><td>${item.time}</td><td></td><td></td></tr>`
+          })
+          _result += `<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr></tbody></table>`
+          this.$parent.bmData.jsonData.editorBarData.content = _result
+        }
+      } else {
+        console.log('状态错误')
+      }
     },
     uploadFileFn() {
-			if(!this.tid){
-				return this.$toast("请先选择课堂或者创建课堂")
-				// return this.$parent.addNewCourseByDefault().then(_=>{
-				// 	this.uploadFileFn()
-				// })
-			}
-			if (this.uploadFileLoading) return this.$toast("请稍等...");
-      let input = document.createElement("input");
-      input.type = "file";
+      if (!this.tid) {
+        return Dialog.confirm({
+          title: '创建课堂并上传文件',
+          message: `确定使用默认模板来创建新的课堂并上传文件?`
+        })
+          .then(() => {
+            return this.$parent.addNewCourseByDefault().then(_ => {
+              this.uploadFileFn()
+            })
+          })
+          .catch(_ => {
+            console.log('不创建')
+          })
+      }
+      if (this.uploadFileLoading) return this.$toast('请稍等...')
+      let input = document.createElement('input')
+      input.type = 'file'
       // input.accept = ".wav";
       // input.accept = "audio/*, .txt, .pdf, .xlsx";
-      input.accept = ".wav,.txt,.pdf,.xlsx,.doc,.docx,.csv";
-      input.click();
+      input.accept = '.wav,.txt,.pdf,.xlsx,.doc,.docx,.csv'
+      input.click()
       input.onchange = () => {
-        this.uploadFileLoading = true;
-        let file = input.files[0];
+        this.uploadFileLoading = true
+        let file = input.files[0]
         if (!/\.(wav|txt|pdf|xlsx|doc|docx|csv)$/i.test(file.name)) {
-          this.uploadFileLoading = false;
-          return this.$toast.error(
-            "请上传.wav,.txt,.pdf,.xlsx,.doc,.docx,.csv格式的文件"
-          );
-        }else{
-					
-					this.uploadFile(file, { changeText: true, flag: true });
-				}
-			}
+          this.uploadFileLoading = false
+          return this.$toast.error('请上传.wav,.txt,.pdf,.xlsx,.doc,.docx,.csv格式的文件')
+        } else {
+          this.uploadFile(file, { changeText: true, flag: true })
+        }
+      }
     },
-		uploadFile(file, { changeText = true, flag = true }) {
+    uploadFile(file, { changeText = true, flag = true }) {
       var credentials = {
-        accessKeyId: "AKIATLPEDU37QV5CHLMH",
-        secretAccessKey: "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",
-      }; //秘钥形式的登录上传
-      window.AWS.config.update(credentials);
-      window.AWS.config.region = "cn-northwest-1"; //设置区域
+        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;
+      var bucket = new window.AWS.S3({ params: { Bucket: 'ccrb' } }) //选择桶
+      var _this = this
 
       if (file) {
-        this.loading = true;
+        this.loading = true
         // this.progressData.uploadLoading = true;
         // this.progressData.value = 0;
         var params = {
           Key:
-            file.name.split(".")[0] +
+            file.name.split('.')[0] +
             new Date().getTime() +
-            "." +
-            file.name.split(".")[file.name.split(".").length - 1],
+            '.' +
+            file.name.split('.')[file.name.split('.').length - 1],
           ContentType: file.type,
           Body: file,
-          "Access-Control-Allow-Credentials": "*",
-          ACL: "public-read",
-        }; //key可以设置为桶的相抵路径,Body为文件, ACL最好要设置
+          'Access-Control-Allow-Credentials': '*',
+          ACL: 'public-read'
+        } //key可以设置为桶的相抵路径,Body为文件, ACL最好要设置
         var options = {
           partSize: 2048 * 1024 * 1024,
           queueSize: 2,
-          leavePartsOnError: true,
-        };
+          leavePartsOnError: true
+        }
         bucket
           .upload(params, options)
-          .on("httpUploadProgress", function (evt) {
+          .on('httpUploadProgress', function(evt) {
             //这里可以写进度条
             // _this.progressData.value = parseInt((evt.loaded * 100) / evt.total);
             // console.log("Uploaded : " + parseInt((evt.loaded * 80) / evt.total) + '%');
           })
-          .send(function (err, data) {
+          .send(function(err, data) {
             if (err) {
-              _this.$toast.fail("上传失败");
-              _this.uploadFileLoading = false;
-              _this.loading = false;
+              _this.$toast.fail('上传失败')
+              _this.uploadFileLoading = false
+              _this.loading = false
               // _this.progressData.uploadLoading = false;
             } else {
               // 判断是不是音频文件
-              const audioRegex = /\.(mp3|wav|ogg|flac|m4a)$/i;
-              const txtRegex = /\.(txt|csv)$/i;
-              const otherRegex = /\.(pdf|xlsx|doc|docx)$/i;
+              const audioRegex = /\.(mp3|wav|ogg|flac|m4a)$/i
+              const txtRegex = /\.(txt|csv)$/i
+              const otherRegex = /\.(pdf|xlsx|doc|docx)$/i
               // if (audioRegex.test(data.Location)) {
               // 	// console.log(data);
               // 	_this.uploadWavFileAndGetText(file)
@@ -439,117 +637,96 @@ export default {
               // } else if(otherRegex.test(data.Location)){
               //
               if (audioRegex.test(data.Location)) {
-                if (changeText) _this.wavFileGetText(file);
-								_this.$parent.changeAudioUrl(data);
+                if (changeText) _this.wavFileGetText(file)
+                _this.$parent.changeAudioUrl(data)
                 // _this.$emit("changeAudioUrl", data);
-                _this.loading = false;
-                _this.recordedForm.audioBlob = [];
-                _this.recordedForm.time = "00:00:00";
-                _this.recordedForm.timeDuration = 0;
+                _this.loading = false
+                _this.recordedForm.audioBlob = []
+                _this.recordedForm.time = '00:00:00'
+                _this.recordedForm.timeDuration = 0
                 // _this.progressData.uploadLoading = false;
-                _this.recordedForm.textList = [];
-                _this.$parent.saveEditorBar();
-                return;
+                _this.recordedForm.textList = []
+                _this.$parent.saveEditorBar()
+                return
               }
 
-							upload_file_knowledgeRequest({
-                  url: data.Location,
-                })
-                .then((res) => {
-                  let _data = res.FunctionResponse;
+              upload_file_knowledgeRequest({
+                url: data.Location
+              })
+                .then(res => {
+                  let _data = res.FunctionResponse
                   if (_data.result && _data.result.id) {
-										_this.$parent.changeFileId(_data.result.id)
+										console.log("👇")
+										console.log(_data.result.id)
+                    _this.$parent.changeFileId(_data.result.id)
                     // _this.$emit("updateFileId", _data.result.id);
                     // _this.$message.success("成功获取fileId");
-                    _this.uploadFileLoading = false;
+                    _this.uploadFileLoading = false
                     //处理文件
                     if (txtRegex.test(data.Location)) {
                       //txt
-                      getFile(data.Location).then((_res) => {
-                        _this.controlsStatus = 2;
-                        _this.showIndexPage = false;
-                        _this.pageStatus = 2;
-                        _this.$parent.bmData.jsonData.editorBarData.type = "0";
-                        // _this.transcriptionData.content = _res.data;
+                      getFile(data.Location).then(_res => {
+                        _this.controlsStatus = 2
+                        _this.showIndexPage = false
+                        _this.pageStatus = 2
+                        _this.$parent.bmData.jsonData.editorBarData.type = '0'
+                        // _this.$parent.bmData.jsonData.transcriptionData = _res.data
                         if (flag) {
                           const arr = Papa.parse(_res.data, {
-                            header: false,
-                          }).data.slice(1);
-                          console.log(arr);
-                          const _editorBarDataContent = `<table
-                          border="0"
-                          width="100%"
-                          cellpadding="0"
-                          cellspacing="0"
-                          style="text-align: center"
-                        >
-                          <tbody>
-                            <tr>
-                              <th>序号</th>
-                              <th>开始时间</th>
-                              <th>结束时间</th>
-                              <th>发言内容</th>
-                              <th>时长</th>
-                              <th>说话人身份</th>
-                              <th>行为编码</th>
-                            </tr>
-                            ${arr
-                              .map(
-                                (row) => `
-                              <tr>
-                                <td>${_.get(row, 0, "")}</td>
-                                <td>${_.get(row, 1, "")}</td>
-                                <td>${_.get(row, 2, "")}</td>
-                                <td>${_.get(row, 3, "")}</td>
-                                <td>${_.get(row, 4, "")}</td>
-                                <td>${_.get(row, 5, "")}</td>
-                                <td>${_.get(row, 6, "")}</td>
-                              </tr>
-                              `
-                              )
-                              .join("\n")}
-                          </tbody>
-                        </table>`;
-                          _this.$parent.bmData.jsonData.editorBarData.content = _editorBarDataContent;
+                            header: false
+                          }).data.slice(1)
+                          const _editorBarDataContent = `<table border="0" width="100%" cellpadding="0" cellspacing="0" style="text-align: center"><tbody><tr><th>序号</th><th>开始时间</th><th>结束时间</th><th>发言内容</th><th>时长</th><th>说话人身份</th><th>行为编码</th></tr>${arr
+                            .map(
+                              row =>
+                                `<tr><td>${_.get(row, 0, '')}</td><td>${_.get(row, 1, '')}</td><td>${_.get(
+                                  row,
+                                  2,
+                                  ''
+                                )}</td><td>${_.get(row, 3, '')}</td><td>${_.get(row, 4, '')}</td><td>${_.get(
+                                  row,
+                                  5,
+                                  ''
+                                )}</td><td>${_.get(row, 6, '')}</td></tr>`
+                            )
+                            .join('\n')}</tbody></table>`
+                          _this.$parent.bmData.jsonData.editorBarData.content = _editorBarDataContent
                         } else {
-                          _this.$parent.bmData.jsonData.editorBarData.content = _res.data;
+                          _this.$parent.bmData.jsonData.editorBarData.content = _res.data
                         }
-                        _this.$parent.bmData.jsonData.editorBarData.url = "";
-                        _this.$parent.saveEditorBar();
-                      });
+                        _this.$parent.bmData.jsonData.editorBarData.url = ''
+                        _this.$parent.saveEditorBar()
+                      })
                     } else if (otherRegex.test(data.Location)) {
                       //pdf、 docx、doc、xlxs
 
-                      _this.$parent.bmData.jsonData.editorBarData.type = "1";
-                      _this.$parent.bmData.jsonData.editorBarData.url = data.Location;
-                      _this.$parent.bmData.jsonData.editorBarData.content = "";
-                      _this.$parent.saveEditorBar();
+                      _this.$parent.bmData.jsonData.editorBarData.type = '1'
+                      _this.$parent.bmData.jsonData.editorBarData.url = data.Location
+                      _this.$parent.bmData.jsonData.editorBarData.content = ''
+                      _this.$parent.saveEditorBar()
                       // console.log("pdf、xlsx、doc、docx文件处理");
                     }
-                    _this.loading = false;
+                    _this.loading = false
                     // _this.progressData.uploadLoading = false;
-        
-                    
                   } else {
-                    _this.$toast.fail("修改fileId失败");
+                    _this.$toast.fail('修改fileId失败')
                   }
 
                   // this.$emit("updateFileId", data.Location)
                 })
-                .catch((e) => {
-                  _this.uploadFileLoading = false;
+                .catch(e => {
+                  _this.uploadFileLoading = false
                   // _this.progressData.uploadLoading = false;
-                  console.log(e);
-                  _this.$toast.fail("获取fileId失败");
-                });
+                  console.log(e)
+                  _this.$toast.fail('获取fileId失败')
+                })
               // }
 
               // console.log(data.Location)
             }
-          });
+          })
       }
     },
-		
+
     analysis() {
       this.$router.push({ path: '/outcome', query: {} })
     },
@@ -614,6 +791,18 @@ export default {
           }
         }
       })
+    },
+    updateRecordedTime({ duration }) {
+      // 更新currentTime,将秒数转换为时分秒格式
+      let hours = Math.floor(duration / 3600)
+      let minutes = Math.floor((duration % 3600) / 60)
+      let seconds = Math.floor(duration % 60)
+      // this.recordedForm.time = `${hours.toString().padStart(2, "0")}:${minutes
+      // 	.toString()
+      // 	.padStart(2, "0")}:${seconds.toString().padStart(2, "0")}`;
+      return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds
+        .toString()
+        .padStart(2, '0')}`
     }
   }
 }
@@ -711,13 +900,14 @@ export default {
     }
     .classInfo {
       background-color: rgba(255, 255, 255, 0.55);
-      font-size: 10px;
+      font-size: 12px;
       border-radius: 3px;
       display: flex;
       align-items: center;
       padding: 0 10px;
       margin-right: 10px;
       color: rgba(0, 0, 0, 0.6);
+			
     }
   }
 }
@@ -756,32 +946,32 @@ export default {
   img {
     object-fit: contain;
   }
-	.ca_left{
-		box-sizing: border-box;
-		padding-right: 10px;
-		width: calc(50% - 30px);
-		height: 100%;
-		display: flex;
-		justify-content: space-around;
-		align-items: center;
-		img{
-			width: 28px;
-			height: 28px;
-		}
-	}
-	.ca_right{
-		box-sizing: border-box;
-		padding-left: 10px;
-		width: calc(50% - 30px);
-		height: 100%;
-		display: flex;
-		justify-content: space-around;
-		align-items: center;
-		img{
-			width: 28px;
-			height: 28px;
-		}
-	}
+  .ca_left {
+    box-sizing: border-box;
+    padding-right: 10px;
+    width: calc(50% - 30px);
+    height: 100%;
+    display: flex;
+    justify-content: space-around;
+    align-items: center;
+    img {
+      width: 28px;
+      height: 28px;
+    }
+  }
+  .ca_right {
+    box-sizing: border-box;
+    padding-left: 10px;
+    width: calc(50% - 30px);
+    height: 100%;
+    display: flex;
+    justify-content: space-around;
+    align-items: center;
+    img {
+      width: 28px;
+      height: 28px;
+    }
+  }
   .recordBtn {
     width: 60px;
     height: 60px;

+ 222 - 7
src/views/classObserve/index.vue

@@ -35,7 +35,10 @@
       @cutPage="cutPage"
       :page="page"
       v-show="page == 8"
+			:bmData="bmData"
       :loading="[currencyLoading, scienceLoading, extendLoading]"
+			:analysisList="analysisList"
+			:fileId="fileId"
       :dataList="dataList"
     />
   </div>
@@ -99,7 +102,220 @@ export default {
       },
 			fileId:"",
 			fileIdId:"",
-      actionTypesMap: {}
+      actionTypesMap: {},
+			analysisList: [
+				{
+					title: "OMO智慧课堂分析",
+					brief: "多维度分析课堂整体情况",
+					value: "4cc367c1-0076-11ef-aaca-12e77c4cb76b",
+					type: 0,
+					sum: 157,
+				},
+				{
+					title: "教学阶段九事件分析",
+					brief: "使用加涅九事件分析教学环节",
+					value: "5e0466b3-0075-11ef-aaca-12e77c4cb76b",
+					type: 0,
+					sum: 540,
+				},
+				{
+					title: "布鲁姆问题分类",
+					brief: "不同认知层次问题分布情况",
+					value: "eac63117-00a7-11ef-aaca-12e77c4cb76b",
+					type: 0,
+					sum: 405,
+				},
+				{
+					title: "麦卡锡问题分类",
+					brief: "不同类型问题分布情况",
+					value: "18545cf7-0125-11ef-aaca-12e77c4cb76b",
+					type: 0,
+					sum: 360,
+				},
+				{
+					title: "学生回答情况",
+					brief: "学生回答情况分析",
+					value: "2c6ede88-0125-11ef-aaca-12e77c4cb76b",
+					type: 0,
+					sum: 206,
+				},
+				{
+					title: "S-T分析:课堂时间分配",
+					brief: "多维度分析课堂整体情况",
+					value: "st1",
+					type: 0,
+					sum: 451,
+				},
+				{
+					title: "S-T分析:师生互动分析",
+					brief: "多维度分析课堂整体情况",
+					value: "st2",
+					type: 0,
+					sum: 342,
+				},
+				{
+					title: "S-T分析:教学模式分析",
+					brief: "多维度分析课堂整体情况",
+					value: "st3",
+					type: 0,
+					sum: 143,
+				},
+				{
+					title: "课堂活动类型",
+					brief: "识别特定的课堂活动类型",
+					value: "41d2d2d4-0125-11ef-aaca-12e77c4cb76b",
+					subject: "科学",
+					type: 1,
+					sum: 430,
+				},
+				{
+					title: "学科核心素养发展",
+					brief: "分析与学科核心素养的匹配情况",
+					value: "a6c0b92b-06de-11ef-aaca-12e77c4cb76b",
+					subject: "科学",
+					type: 1,
+					sum: 234,
+				},
+				{
+					title: "科学教育目标分析",
+					brief: "分析四类科学教育目标的情况",
+					value: "d6cd48ab-0125-11ef-aaca-12e77c4cb76b",
+					subject: "科学",
+					type: 1,
+					sum: 513,
+				},
+				{
+					title: "PORTAAL课堂观察",
+					brief: "使用PORTAAL框架分析科学课堂",
+					value: "8ab07d41-e143-11ee-aaca-12e77c4cb76b",
+					subject: "科学",
+					type: 1,
+					sum: 173,
+				},
+				{
+					title: "UTOP课堂观察",
+					brief: "使用UTOP框架分析科学课堂",
+					value: "8e3a389b-014f-11ef-aaca-12e77c4cb76b",
+					subject: "科学",
+					type: 1,
+					sum: 329,
+				},
+				{
+					title: "L-PST模型",
+					brief: "使用L-PST框架分析科学课堂",
+					value: "e649112e-0150-11ef-aaca-12e77c4cb76b", //e649112e-0150-11ef-aaca-12e77c4cb76b  7daa4c3f-016f-11ef-aaca-12e77c4cb76b
+					subject: "科学",
+					type: 1,
+					sum: 421,
+				},
+				// {
+				// 	title: "RST模型",
+				// 	brief: "多维度分析课堂整体情况",
+				// 	value: "e649112e-0150-11ef-aaca-12e77c4cb76b",
+				// 	type: 1,
+				// },
+				{
+					title: "RTOP课堂观察",
+					brief: "使用RTOP框架分析科学课堂",
+					value: "68265b18-0151-11ef-aaca-12e77c4cb76b", //a7107221-f7f5-11ee-aaca-12e77c4cb76b   bc254ab9-0142-11ef-aaca-12e77c4cb76b    c912ece9-0148-11ef-aaca-12e77c4cb76b  68265b18-0151-11ef-aaca-12e77c4cb76b  2ace7ff6-0154-11ef-aaca-12e77c4cb76b
+					subject: "科学",
+					type: 1,
+					sum: 527,
+				},
+				{
+					title: "课程质量评价",
+					brief: "多维度分析课堂整体情况",
+					value: "25e53379-0152-11ef-aaca-12e77c4cb76b",
+					subject: "科学",
+					type: 1,
+					sum: 391,
+				},
+				{
+					title: "SCOP课堂观察",
+					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教学模型设计一堂课",
+					value: "f757826e-0125-11ef-aaca-12e77c4cb76b",
+					type: 2,
+					sum: 510,
+				},
+				{
+					title: "5EX课程改编",
+					brief: "基于5EX教学模型设计一堂课",
+					value: "0b6b08b7-0126-11ef-aaca-12e77c4cb76b",
+					type: 2,
+					sum: 611,
+				},
+				{
+					title: "C-POTE课程改编",
+					brief: "C-POTE课程改编",
+					value: "6b4a9650-48be-11ef-936b-12e77c4cb76b",
+					type: 2,
+					sum: 165,
+				},
+			],
     }
   },
   methods: {
@@ -280,6 +496,7 @@ export default {
             _bmData.jsonData = JSON.parse(_bmData.jsonData)
             _bmData.jsonData.time ? '' : (_bmData.jsonData.time = '')
 						_bmData.jsonData.editorBarData ? '' :(_bmData.jsonData.editorBarData = { type: '0',content: '',url: ''})
+						_bmData.jsonData.transcriptionData ? '' :(_bmData.jsonData.transcriptionData = '')
             // 图片
             let _imageList = _data.find(i => i.tIndex == 1)
             _imageList.jsonData = JSON.parse(_imageList.jsonData)
@@ -544,12 +761,11 @@ export default {
 				});
 		},
 		changeFileId(newFileId){
-			this.saveData({
+			let params = {
 				id:this.fileIdId,
-				json_data: JSON.stringify({
-          file_ids: newFileId,
-        }),
-			}).then(res=>{
+				jsonData:{file_ids: newFileId}
+			}
+			this.saveData(params).then(res=>{
 				console.log("更改并保存fileID成功")
 				this.getFileIdId();
 			}).catch(e=>{
@@ -636,7 +852,6 @@ export default {
             console.log('词频词汇分析已保存')
           })
         }
-				console.log(this.bmData.jsonData)
         this.saveData(this.bmData).then(_ => {
 					console.log("转录问稿已保存")
           this.loading = false

+ 211 - 151
src/views/classObserve/outcome.vue

@@ -2,36 +2,46 @@
   <div class="outcome" v-loading="saveLoading">
     <bar @cutPage="cutPage(1)" :tit="'分析结果'" :backPage="0"></bar>
     <div class="sortList">
-      <div :class="[showIndex==0?'sortActive':'']" @click.stop="changeShowIndex(0)">通用</div>
-      <div :class="[showIndex==1?'sortActive':'']" @click.stop="changeShowIndex(1)">学科</div>
-      <div :class="[showIndex==2?'sortActive':'']" @click.stop="changeShowIndex(2)">扩展</div>
+      <div :class="[showIndex == 0 ? 'sortActive' : '']" @click.stop="changeShowIndex(0)">通用</div>
+      <div :class="[showIndex == 1 ? 'sortActive' : '']" @click.stop="changeShowIndex(1)">学科</div>
+      <div :class="[showIndex == 2 ? 'sortActive' : '']" @click.stop="changeShowIndex(2)">扩展</div>
     </div>
-		
+
     <div class="stencilList" v-loading="loading[showIndex]">
-			<analysisItem ref="analysisItemRef" v-for="(item,index) in dataList" :key="item.id" :data="item" v-show="showIndex === item.Type" v-if="!(item.Type==0 && item.tIndex==2)"/>
+      <analysisItem
+        ref="analysisItemRef"
+        v-for="(item, index) in dataList"
+        :key="item.id"
+        :data="item"
+        v-show="showIndex === item.Type"
+        v-if="!(item.Type == 0 && item.tIndex == 2)"
+        :analysisList="analysisList"
+        :bmData="bmData"
+        :fileId="fileId"
+      />
     </div>
 
     <div class="botBtn">
       <div class="shareBtn" @click.stop="share()">
-        <img src="../../assets/images/classObserve/share.png" alt=""/>
+        <img src="../../assets/images/classObserve/share.png" alt="" />
         <span>分享</span>
       </div>
 
-			<div class="bb_box">
-				<div class="btn" @click.stop="saveTemplate()">
-        保存模板
-      </div>
-			
-			<div class="btn" @click.stop="AllAnalysis()">
-        一键分析
-      </div>
+      <div class="bb_box">
+        <div class="btn" @click.stop="saveTemplate()">
+          保存模板
+        </div>
+				<!-- :class="['btn', fileId ? '' : 'btnDis']" -->
+        <div class="btn"  @click.stop="AllAnalysis()">
+          一键分析
+        </div>
 
-      <div class="btn" @click.stop="viewTheReport()">
-        查看报告
+        <div class="btn" @click.stop="viewTheReport()">
+          查看报告
+        </div>
       </div>
-			</div>
     </div>
-		<van-popup v-model="showPopup">
+    <van-popup v-model="showPopup">
       <div class="popupCon">
         <div class="tit">模板信息</div>
         <div class="bri">请根据提示补充模版信息</div>
@@ -39,7 +49,12 @@
           <el-input v-model="form.name" placeholder="模版名称"></el-input>
           <el-input type="textarea" :rows="3" resize="none" v-model="form.brief" placeholder="模版简介"></el-input>
           <el-select v-model="form.subject" placeholder="所属学科" style="z-index: 2026;">
-            <el-option v-for="item in subjectList" :key="item.value" :label="item.label" :value="item.value"></el-option>
+            <el-option
+              v-for="item in subjectList"
+              :key="item.value"
+              :label="item.label"
+              :value="item.value"
+            ></el-option>
           </el-select>
         </div>
 
@@ -52,6 +67,19 @@
         <div @click="cancelSaveTemplate">取消</div>
         <div style="color: rgba(54, 129, 252, 1);" @click="saveInfo">保存</div>
       </div>
+    </van-popup>
+
+		<van-popup v-model="sharePopup">
+      <div class="saveBox">
+				<div class="sb_imgArea">
+
+				</div>
+				<div class="sb_inputArea"></div>
+      </div>
+      <div class="btnS">
+        <div @click="sharePopup = false">取消</div>
+        <div style="color: rgba(54, 129, 252, 1);" @click="sharePopup = false">确定</div>
+      </div>
     </van-popup>
   </div>
 </template>
@@ -59,54 +87,66 @@
 <script>
 import bar from './components/bar.vue'
 import analysisItem from './components/analysisItem.vue'
-import { Dialog } from 'vant';
-import {insertClassroomTemplateRequest} from '@/api/classObserve'
+import { Dialog } from 'vant'
+import { insertClassroomTemplateRequest } from '@/api/classObserve'
 export default {
   components: {
     bar,
-		analysisItem
+    analysisItem
   },
   props: {
     page: {
       type: Number,
       default: 1
     },
-		dataList:{
-			type:Array,
-			default:()=>[]
-		},
-		loading:{
-			type:Array,
-			default:()=>[true,true,true]
-		}
+    dataList: {
+      type: Array,
+      default: () => []
+    },
+    loading: {
+      type: Array,
+      default: () => [true, true, true]
+    },
+    analysisList: {
+      type: Array,
+      default: () => []
+    },
+    bmData: {
+      type: Object,
+      default: () => {}
+    },
+    fileId: {
+      type: String,
+      default: ''
+    }
   },
   data() {
     return {
-			userId:this.$store.state.user.id,
+      userId: this.$store.state.user.id,
       abuShow: false,
       cellShow: false,
-			showPopup:false,
-			showIndex:0,
-			saveLoading:false,
-			form:{
-				name:"",
-				brief:"",
-				subject:"",
-				pre:false,
-			},
-			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:'政治'},
-				
-			],
+      showPopup: false,
+			sharePopup:false,
+      showIndex: 0,
+      saveLoading: false,
+      form: {
+        name: '',
+        brief: '',
+        subject: '',
+        pre: false
+      },
+      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: '政治' }
+      ]
     }
   },
   methods: {
@@ -119,89 +159,98 @@ export default {
     showAbu() {
       this.abuShow = true
     },
-		changeShowIndex(newIndex){
-			this.showIndex = newIndex;
-		},
-		delItem(item){
-			Dialog.confirm({
+    changeShowIndex(newIndex) {
+      this.showIndex = newIndex
+    },
+    delItem(item) {
+      Dialog.confirm({
         title: '删除分析',
         message: `确定删除 "${item.jsonData.name}" 这个分析?`
-      }).then(() => {
-				this.$parent.delAnalysis(item);
-      }).catch(() => {
-				console.log("不删除")
-        // on cancel
       })
-		},
-		share(){
-			console.log("分享")
-		},
-		viewTheReport(){
-			console.log("查看报告");
-		},
-		AllAnalysis(){
-			console.log("一键分析")
-		},
-		saveTemplate(){
-			this.showPopup = !this.showPopup;
-		},
-		cancelSaveTemplate(){
-			this.form = {
-				name:"",
-				brief:"",
-				subject:"",
-				per:false,
-			};
-			this.showPopup = false;
-		},
-		saveInfo(){
+        .then(() => {
+          this.$parent.delAnalysis(item)
+        })
+        .catch(() => {
+          console.log('不删除')
+          // on cancel
+        })
+    },
+    share() {
+      // return;
+			this.sharePopup = true;
+    },
+    viewTheReport() {
+      console.log('查看报告')
+    },
+    AllAnalysis() {
+			return;
+      if(!this.fileId)return this.$toast("请先上传文件或者录音");
+			this.$refs.analysisItemRef.forEach(i=>{
+				i.optimize();
+			})
+			this.$toast.success("一键分析成功")
+    },
+    saveTemplate() {
+      this.showPopup = !this.showPopup
+    },
+    cancelSaveTemplate() {
+      this.form = {
+        name: '',
+        brief: '',
+        subject: '',
+        per: false
+      }
+      this.showPopup = false
+    },
+    saveInfo() {
+      if (!this.form.name.trim()) return this.$toast.fail('请填写模板名称')
+      if (!this.form.subject.trim()) return this.$toast.fail('请选择科目')
+      // if(!this.form.brief.trim())return this.$toast.fail("请填写模板简介");
 
-			if(!this.form.name.trim())return this.$toast.fail("请填写模板名称");
-			if(!this.form.subject.trim())return this.$toast.fail("请选择科目");
-			// if(!this.form.brief.trim())return this.$toast.fail("请填写模板简介");
+      this.saveLoading = true
+      let _data = JSON.parse(JSON.stringify(this.dataList))
+      let _result = []
 
-			this.saveLoading = true;
-			let _data = JSON.parse(JSON.stringify(this.dataList));
-			let _result = [];
-			
-			_data.forEach(i=>{
-				if(i.Type==0 && i.tIndex==2 )return;
-				i.jsonData.content = "";
-				i.jsonData.dataFileList = [];
-				i.jsonData.fileList = [];
-				i.createtime = "";
-				i.id = "",
-				i.tId = "",
-				i.userid = "";
-				_result.push(i)
-			})
+      _data.forEach(i => {
+        if (i.Type == 0 && i.tIndex == 2) return
+        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.per?1:0,
-				jsonData:JSON.stringify(_result),
-			}]
+      let params = [
+        {
+          title: this.form.name,
+          subject: this.form.subject,
+          uid: this.userId,
+          brief: this.form.brief,
+          per: this.form.per ? 1 : 0,
+          jsonData: JSON.stringify(_result)
+        }
+      ]
 
-			insertClassroomTemplateRequest(params).then(res=>{
-				this.$toast.success("保存为模板成功");
-				this.cancelSaveTemplate();
-				this.saveLoading = false;
-			}).catch(e=>{
-				this.$toast.fail("另存为模板失败")
-				console.log(e)
-			})
-		}
+      insertClassroomTemplateRequest(params)
+        .then(res => {
+          this.$toast.success('保存为模板成功')
+          this.cancelSaveTemplate()
+          this.saveLoading = false
+        })
+        .catch(e => {
+          this.$toast.fail('另存为模板失败')
+          console.log(e)
+        })
+    }
   }
 }
 </script>
 
 <style lang="scss" scoped>
 .outcome {
-	height: calc(100%);
-	display: flex;
+  height: calc(100%);
+  display: flex;
   flex-direction: column;
   justify-content: space-between;
   box-sizing: border-box;
@@ -211,7 +260,7 @@ export default {
   display: flex;
   box-sizing: border-box;
   justify-content: space-between;
-	margin-top: 55px;
+  margin-top: 55px;
   padding: 15px;
   border-bottom: 0.5px rgba(231, 231, 231, 1) solid;
   div {
@@ -219,8 +268,8 @@ export default {
     text-align: center;
     font-size: 16px;
     font-weight: 400;
-		transition: .3s;
-		position: relative;
+    transition: 0.3s;
+    position: relative;
   }
   .sortImg {
     display: flex;
@@ -228,10 +277,10 @@ export default {
     justify-content: center;
     border-left: 0.5px rgba(231, 231, 231, 1) solid;
   }
-	.sortActive{
-		color: #3681FC;
-		font-weight: bold;
-	}
+  .sortActive {
+    color: #3681fc;
+    font-weight: bold;
+  }
 }
 .stencilList {
   flex: 1;
@@ -259,7 +308,7 @@ export default {
   background-color: #fff;
   width: 100%;
   padding: 10px 10px;
-	padding-left: 15px;
+  padding-left: 15px;
   box-sizing: border-box;
   display: flex;
   align-items: center;
@@ -273,27 +322,29 @@ export default {
     font-size: 400;
     color: rgba(4, 0, 0, 1);
   }
-	.bb_box{
-		flex: 1;
-		display: flex;
-		justify-content: center;
-		align-items: center;
-		justify-content: space-around;
-		padding: 0;
-		.btn {
+  .bb_box {
     flex: 1;
-    background-color: rgba(54, 129, 252, 1);
-    color: #fff;
-    height: 45px;
-    border-radius: 10px;
     display: flex;
-    font-size: 16px;
-		margin: 0 5px;
     justify-content: center;
     align-items: center;
+    justify-content: space-around;
+    padding: 0;
+    .btn {
+      flex: 1;
+      background-color: rgba(54, 129, 252, 1);
+      color: #fff;
+      height: 45px;
+      border-radius: 10px;
+      display: flex;
+      font-size: 16px;
+      margin: 0 5px;
+      justify-content: center;
+      align-items: center;
+    }
+    .btnDis {
+      background-color: rgb(165, 165, 165);
+    }
   }
-	}
-  
 }
 .abu {
   background-color: #fff;
@@ -344,12 +395,12 @@ export default {
   margin: 10px 0;
 }
 
-/deep/.van-overlay{
-	z-index: 1999 !important;
+/deep/.van-overlay {
+  z-index: 1999 !important;
 }
 
-/deep/.van-popup{
-	z-index: 2000 !important;
+/deep/.van-popup {
+  z-index: 2000 !important;
 }
 
 .popupCon {
@@ -387,4 +438,13 @@ export default {
     font-weight: 600;
   }
 }
+
+.saveBox{
+	padding: 10px 15px;
+	.sb_imgArea{
+		width: 100%;
+		height: auto;
+		background-color: red;
+	}
+}
 </style>