SanHQin 9 months ago
parent
commit
385e27ea21

+ 146 - 33
src/components/classRoomHelper/component/countdown.vue

@@ -1,10 +1,11 @@
 <template>
   <div class="countdown">
-    <div class="c_changeType">
+    <div class="c_changeType" v-if="showType==0">
       <el-button-group>
         <el-button
           :type="isCountdown ? 'danger' : type == 0 ? 'primary' : ''"
           @click.stop="changeType(0)"
+          :disabled="isCountdown || isKeepTime"
         >
           倒计时
         </el-button>
@@ -12,13 +13,14 @@
         <el-button
           :type="isKeepTime ? 'danger' : type == 1 ? 'primary' : ''"
           @click.stop="changeType(1)"
+          :disabled="isCountdown || isKeepTime"
         >
           计时器
         </el-button>
       </el-button-group>
     </div>
 
-    <div class="c_time">
+    <div class="c_time" v-if="showType==0">
       <div class="c_t_item" v-if="type == 0">
         <div>
           <span v-if="!isCountdown"
@@ -79,7 +81,7 @@
       </div>
     </div>
 
-    <div class="c_choiceTime" v-if="type == 0">
+    <div class="c_choiceTime" v-if="type == 0 && showType == 0">
       <div class="c_title">
         <span>倒计时长</span>
       </div>
@@ -95,7 +97,7 @@
       </div>
     </div>
 
-    <div class="c_behaviorTag">
+    <div class="c_behaviorTag" v-if="showType==0">
       <div class="c_title">
         <span>行为标签</span>
         <div class="c_t_btnArea">
@@ -144,8 +146,10 @@
       </div>
     </div>
 
-    <div class="c_btnArea">
-      <span @click.stop="music()">音乐</span>
+    <div class="c_btnArea" v-if="showType==0">
+      <span @click.stop="music()" :class="[sourceActive ? 'sourceActive' : '']"
+        >音乐</span
+      >
       <div class="c_ba_startArea">
         <div
           :class="[!isCountdown ? 'c_ba_startType' : 'c_ba_startType2']"
@@ -224,13 +228,44 @@
           <!-- <svg v-else t="1721117616634" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="13970" width="64" height="64"><path d="M128 128m53.333333 0l661.333334 0q53.333333 0 53.333333 53.333333l0 661.333334q0 53.333333-53.333333 53.333333l-661.333334 0q-53.333333 0-53.333333-53.333333l0-661.333334q0-53.333333 53.333333-53.333333Z" p-id="13971"></path></svg> -->
         </div>
       </div>
-      <span @click.stop="reset()">重置</span>
+      <span  @click.stop="reset()">重置</span>
     </div>
+
+		<!-- <div style="margin-bottom:30px;padding:20px;cursor: pointer;"  v-if="showType==0">
+			<span @click.stop="showType=1">教学活动备忘>></span>
+		</div>		 -->
+
+		<div v-if="showType==1" style="margin-top:20px">
+			<span style="padding:20px;cursor: pointer;" @click.stop="showType=0"><<返回</span>
+
+			<div class="c_step">
+				<div class="c_s_item" v-for="(item,index) in memorandumList" :key="index">
+					<div>0分9秒</div>
+					<div class="c_s_i_step">
+						<span></span>
+						<div></div>
+						<span></span>
+					</div>
+					<div v-html="item.message"></div>
+				</div>
+			</div>
+		</div>
+    <mini-audio
+      v-show="false"
+      ref="audioRef"
+      :loop="true"
+      :audio-source="sourceUrl"
+    ></mini-audio>
+    <mini-audio
+      v-show="false"
+      ref="endSourceUrlRef"
+      :loop="false"
+      :audio-source="endSourceUrl"
+    ></mini-audio>
   </div>
 </template>
 
 <script>
-import { time } from "echarts";
 import { v4 as uuidv4 } from "uuid";
 export default {
   props: {
@@ -247,6 +282,11 @@ export default {
     return {
       userid: this.$route.query.userid,
       courseId: this.$route.query.courseId,
+			showType:0,
+      sourceUrl:
+        "https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/%E5%80%92%E8%AE%A1%E6%97%B6%E9%9F%B3%E4%B9%901721355956636.mp3",
+      endSourceUrl: "",
+      sourceActive: false,
       type: 0, //0:倒计时   1:计时器
       isCountdown: false,
       isKeepTime: false,
@@ -273,7 +313,13 @@ export default {
         "阅读资料",
         "观察记录"
       ], //常用
-      choiceBehavior: []
+      choiceBehavior: [],
+			memorandumList:[
+				{
+					create_at:"",
+					message:`10:00:01 进入<span style="color:#4A8EDF">授课界面</span>\n10:00:10 点击<span style="color:#4A8EDF">录制</span>按钮,开始录制课堂`
+				}
+			],
     };
   },
   computed: {
@@ -343,10 +389,14 @@ export default {
       } else if (!this.isCountdown && !this.countdownTimeTimer) {
         this.countdownTimeDefault = newValue;
       }
+      if (this.$refs.audioRef.playing && this.sourceActive && newValue <= 10) {
+        this.$refs.audioRef.setVolume(newValue / 10);
+      }
     }
   },
   methods: {
     changeType(newType) {
+      if (this.isCountdown || this.isKeepTime) return;
       this.type = newType;
     },
     changeBehaviorTagType(newType) {
@@ -396,6 +446,9 @@ export default {
         clearInterval(this.countdownTimeTimer);
         this.countdownTimeTimer = null;
         this.isCountdown = false;
+        if (this.$refs.audioRef.playing && this.sourceActive) {
+          this.$refs.audioRef.pause();
+        }
         this.$message.success("已暂停倒计时");
       } else {
         //开始
@@ -403,6 +456,24 @@ export default {
           return this.$message.error("请设置倒计时时间");
         this.isCountdown = true;
         this.$message.success("已开始倒计时");
+        if (this.sourceActive) {
+          this.$refs.audioRef.setVolume(0);
+          this.$refs.audioRef.play();
+        }
+        if (this.countdownTime >= 20 && this.sourceActive) {
+          let volume = 0;
+          let sourceTimer = setInterval(() => {
+            volume += 1;
+            if (volume >= 10) {
+              volume = 10;
+              clearInterval(sourceTimer);
+              sourceTimer = null;
+            }
+            this.$refs.audioRef.setVolume(volume / 10);
+          }, 1000);
+        } else if (this.countdownTime <= 20 && this.sourceActive) {
+          this.$refs.audioRef.setVolume(1);
+        }
         this.countdownTimeTimer = setInterval(() => {
           this.isCountdown = true;
           this.countdownTime -= 1;
@@ -415,30 +486,31 @@ export default {
       this.isCountdown = false;
       this.$parent.type = 1;
       this.$parent.itemType = 3;
+      if (this.$refs.audioRef.playing && this.sourceActive) {
+        this.$refs.audioRef.pause();
+      }
       let _data = {
         type: "countdown",
         time: this.countdownTimeDefault,
         tag: this.choiceBehavior
       };
-      this.$confirm("倒计时已结束!", "提醒", {
-        confirmButtonText: "确定",
-        type: "warning"
-      })
-        .then(_ => {
-          this.insertData(_data);
-        })
-        .catch(_ => {
-          this.insertData(_data);
-        });
+      this.insertData(_data);
     },
     keepTimeFn() {
       if (this.isKeepTime) {
         this.isKeepTime = false;
         clearInterval(this.keepTimeTimer);
         this.keepTimeTimer = null;
+        if (this.$refs.audioRef.playing && this.sourceActive) {
+          this.$refs.audioRef.pause();
+        }
         this.$message.success("已停止计时");
       } else {
         this.isKeepTime = true;
+        if (this.sourceActive) {
+          this.$refs.audioRef.setVolume(1);
+          this.$refs.audioRef.play();
+        }
         this.keepTimeTimer = setInterval(() => {
           this.keepTime += 1;
         }, 1000);
@@ -446,8 +518,14 @@ export default {
       }
     },
     music() {
-      this.$message.info("设置音乐");
-      // this.getBehaviorTagMore()
+      this.sourceActive = !this.sourceActive;
+      if (this.$refs.audioRef.playing && !this.sourceActive) {
+        this.$refs.audioRef.pause();
+      } else if (this.sourceActive) {
+        if (this.isCountdown) {
+          this.$refs.audioRef.play();
+        }
+      }
     },
     reset() {
       if (this.type == 0) {
@@ -465,6 +543,9 @@ export default {
               this.isCountdown = false;
               this.choiceBehavior = [];
               this.$message.success("已重置");
+              if (this.$refs.audioRef.playing) {
+                this.$refs.audioRef.pause();
+              }
             })
             .catch(_ => {
               console.log("取消重置");
@@ -476,6 +557,9 @@ export default {
             type: "warning"
           })
             .then(_ => {
+							if(this.$refs.audioRef.playing){
+								this.$refs.audioRef.pause();
+							}
               // this.countdownTime = this.countdownTimeDefault;
               this.countdownTime = 0;
               this.isCountdown = false;
@@ -494,6 +578,9 @@ export default {
             type: "warning"
           })
             .then(_ => {
+              if (this.$refs.audioRef.playing) {
+                this.$refs.audioRef.pause();
+              }
               clearInterval(this.keepTimeTimer);
               this.keepTimeTimer = null;
               let _data = {
@@ -514,6 +601,9 @@ export default {
             time: this.keepTime,
             tag: this.choiceBehavior
           };
+          if (this.$refs.audioRef.playing) {
+            this.$refs.audioRef.pause();
+          }
           this.insertData(_data);
           this.keepTime = 0;
           this.isKeepTime = false;
@@ -591,16 +681,22 @@ ${_textData}
           content: JSON.stringify(data)
         }
       ];
-      this.ajax.post(this.$store.state.api+"insert_systemOperation_classRoomHelper",params).then(res=>{
-				if(res.data==1){
-					console.log('保存成功')
-				}else{
-					console.log('保存失败')
-				}
-			}).catch(e=>{
-				console.log('保存失败👇')
-				console.log(e);
-			})
+      this.ajax
+        .post(
+          this.$store.state.api + "insert_systemOperation_classRoomHelper",
+          params
+        )
+        .then(res => {
+          if (res.data == 1) {
+            console.log("保存成功");
+          } else {
+            console.log("保存失败");
+          }
+        })
+        .catch(e => {
+          console.log("保存失败👇");
+          console.log(e);
+        });
     }
   }
 };
@@ -610,13 +706,13 @@ ${_textData}
 .countdown {
   width: 100%;
   height: 100%;
-  
+
   /* display: flex;
   flex-direction: column;
   align-items: center; */
   /* justify-content: center; */
   padding: auto;
-	overflow: auto;
+  overflow: auto;
 }
 
 .c_changeType {
@@ -861,4 +957,21 @@ ${_textData}
 .c_ba_startType2:hover > svg {
   fill: #cf1322;
 }
+
+.sourceActive {
+  border: solid 1px #409eff !important;
+  background-color: #409eff !important;
+  color: #fff;
+}
+
+.c_step{
+	width:100%;
+	height:auto;
+	margin-top:20px;
+}
+.c_s_item{
+	display:flex;
+	justify-content:center;
+	align-items:center;
+}
 </style>

+ 564 - 0
src/components/classRoomHelper/component/languageAssistant.vue

@@ -0,0 +1,564 @@
+<template>
+  <div class="languageAssistant">
+		<div class="la_coco">
+			<el-image
+        style="width: 150px; height: 150px"
+        v-show="showIndex == 2"
+        :src="require('../../../assets/icon/course/aiVanish.svg')"
+        fit="fill"
+      ></el-image>
+			<el-image
+       style="width: 150px; height: 150px"
+        v-show="showIndex == 0"
+        :src="require('../../../assets/icon/course/aiWait.svg')"
+        fit="fill"
+      ></el-image>
+			<el-image
+       style="width: 150px; height: 150px"
+        v-show="showIndex == 1"
+        :src="require('../../../assets/icon/course/aiTalk.svg')"
+        fit="fill"
+      ></el-image>
+		</div>
+		<div class="la_message" ref="messageRef" >
+			<div class="la_m_talk" v-if="show">
+				<div v-if="showTextIndex==0" v-html="htmlContent(aiText)"></div>
+				<div v-if="showTextIndex==1">{{userText}}</div>
+				<div v-if="showTextIndex==2">正在组织语言...</div>
+			</div>
+		</div>
+		<div class="la_btn">
+			<div class="la_b_noTel" v-if="!show">
+				<svg @click.stop="recordStart" t="1721367811838"  viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4525" width="64" height="64"><path d="M65.771 502.182c0 246.632 199.937 446.566 446.57 446.565 246.613 0 446.549-199.934 446.551-446.565 0-246.633-199.936-446.549-446.55-446.55-246.635 0.001-446.57 199.917-446.571 446.55z m651.885-173.77c31.489 31.473 1.642 148.828-114.292 264.773C487.396 709.131 370.06 738.929 338.589 707.492c-27.278-27.315-74.96-60.574-12.892-110.423 62.087-49.886 79.429-25.343 107.582 2.772 19.674 19.711 69.436-21.368 112.394-64.328 42.94-42.996 83.986-92.719 64.368-112.43-28.155-28.153-52.679-45.511-2.792-107.562 49.904-62.049 83.125-14.405 110.406 12.891z" p-id="4526"></path></svg>
+			</div>
+			<div class="la_b_isTel" v-else>
+				<span @click.stop="stopTalk">
+					<svg t="1721372070061" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6534" width="64" height="64"><path d="M648.45 247.01c-31.64 0-57.348 27.685-57.348 57.348v427.149c0 31.64 27.685 57.348 57.348 57.348S705.8 761.17 705.8 731.507V304.358c0-31.64-27.686-57.348-57.349-57.348z m-272.9 0c-31.64 0-57.349 27.685-57.349 57.348v427.149c0 31.64 27.686 57.348 57.349 57.348s57.348-27.685 57.348-57.348V304.358c1.978-31.64-25.708-57.348-57.348-57.348z" p-id="6535"></path></svg>
+				</span>
+				<svg @click.stop="stopRecord" t="1721367811838"  viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4525" width="64" height="64"><path d="M65.771 502.182c0 246.632 199.937 446.566 446.57 446.565 246.613 0 446.549-199.934 446.551-446.565 0-246.633-199.936-446.549-446.55-446.55-246.635 0.001-446.57 199.917-446.571 446.55z m651.885-173.77c31.489 31.473 1.642 148.828-114.292 264.773C487.396 709.131 370.06 738.929 338.589 707.492c-27.278-27.315-74.96-60.574-12.892-110.423 62.087-49.886 79.429-25.343 107.582 2.772 19.674 19.711 69.436-21.368 112.394-64.328 42.94-42.996 83.986-92.719 64.368-112.43-28.155-28.153-52.679-45.511-2.792-107.562 49.904-62.049 83.125-14.405 110.406 12.891z" p-id="4526"></path></svg>
+				<span @click.stop="interrupt">
+					<svg t="1721372012678" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5554" width="64" height="64"><path d="M885.6 413.8c-32.3 0-60.1 19.8-71.9 47.9h-18.1c-16.6 0-30 13.4-30 30s13.4 30 30 30h18.1c11.8 28.1 39.5 47.9 71.9 47.9 42.9 0 77.9-34.9 77.9-77.9 0-42.9-35-77.9-77.9-77.9zM690.4 461.7h-21.1c-16.6 0-30 13.4-30 30s13.4 30 30 30h21.1c16.6 0 30-13.4 30-30s-13.4-30-30-30zM564.1 461.7h-10c-16.6 0-30 13.4-30 30s13.4 30 30 30h10c16.6 0 30-13.4 30-30s-13.4-30-30-30zM709.7 115.7c-13.7-9.4-32.3-5.9-41.7 7.8L436.5 461.8c-0.8-0.1-1.6-0.1-2.3-0.1H212.5c-11.8-28.1-39.5-47.9-71.9-47.9-39.4 0-72.1 29.5-77.2 67.5-1.2 3.2-1.8 6.7-1.8 10.3 0 3.6 0.6 7.1 1.8 10.3 5.1 38.1 37.7 67.5 77.2 67.5 32.3 0 60.1-19.8 71.9-47.9h183l-240.1 351c-9.4 13.7-5.9 32.3 7.8 41.7 5.2 3.5 11.1 5.2 16.9 5.2 9.6 0 19-4.6 24.8-13.1l512.6-749c9.4-13.5 5.9-32.2-7.8-41.6z" p-id="5555"></path></svg>
+				</span>
+			</div>
+		</div>
+		 <!-- 录音转文字 -->
+		 <iframe
+      allow="camera *; microphone *;display-capture;midi;encrypted-media;"
+      src="https://beta.cloud.cocorobo.cn/browser/public/index.html"
+      ref="iiframe"
+      v-show="false"
+    ></iframe>
+
+    <!-- 文字转语音-->
+    <iframe
+      allow="camera *; microphone *;display-capture;midi;encrypted-media;"
+      src="https://beta.cloud.cocorobo.cn/browser/public/index1.html"
+      ref="iiframe2"
+      v-show="false"
+    ></iframe>
+  </div>
+</template>
+
+<script>
+import { v4 as uuidv4 } from "uuid";
+import MarkdownIt from "markdown-it";
+export default {
+  props: {
+
+  },
+  data() {
+    return {
+			show: false,
+      showIndex: 2, //0 :在说话 1 : 接收 2:待命
+      aiStatus: 0,
+      aiText: "我是可可同学,我是个小小百事通,你有什么想和我聊一聊?",
+      userText: "",
+      showTextIndex: 0, //0:ai,1:用户, 2:组织语言  3: 无
+      timer: null,
+      isOpen: false,
+      userId: this.$route.query.userid,
+      chatLoading: false,
+      talkLoading: false,
+      source: null,
+      talkTextList: []
+		}
+  },
+	computed: {
+    htmlContent() {
+      const md = new MarkdownIt();
+      return _md => {
+        return md.render(_md);
+      };
+    }
+  },
+  methods: {
+		scrollBottom(){
+			this.$nextTick(() => {
+        this.$refs.messageRef.scrollTop = this.$refs.messageRef.scrollHeight;
+      });
+		},
+		recordStart(_text) {
+			// this.show = true;
+			// this.showIndex = 0;
+			// return
+      var OpenCC = require("opencc-js");
+      let converter = OpenCC.Converter({
+        from: "hk",
+        to: "cn"
+      });
+      if (this.isOpen)return this.$message.info("已开启语音助手,无需重复开启");
+      let iiframe = this.$refs["iiframe"];
+      iiframe.contentWindow.window.document.getElementById(
+        "languageOptions"
+      ).selectedIndex = 2; //普通话
+      iiframe.contentWindow.testdoContinuousPronunciationAssessment();
+      this.isOpen = true;
+			this.show = true;
+			this.aiText = "我是可可同学,我是个小小百事通,你有什么想和我聊一聊?"
+      iiframe.contentWindow.onRecognizedResult = e => {
+        let _msg = converter(e.privText);
+
+        console.log("👇");
+        console.log(_msg);
+        // _msg = converter(_msg)
+        if (!_msg) return console.log("输出为空");
+        if (this.show == true) {
+          if (
+            _msg.indexOf(converter("可可同学")) != -1 &&
+            _msg.indexOf(converter("停止")) != -1
+          ) {
+            this.stopTalk();
+          } else if (
+            this.showTextIndex == 2 ||
+            this.chatLoading ||
+            this.talkLoading
+          ) {
+            return console.log("组织语言中");
+            // }else if(_msg.indexOf('可可同学')!=-1 && _msg.indexOf("停止")!=-1){
+            // 	this.stopTalk();
+          } else {
+            this.showTextIndex = 1;
+            this.aiText = "";
+            this.userText += _msg;
+						this.scrollBottom();
+            this.aiStatus = 1;
+            if (this.timer) {
+              clearTimeout(this.timer);
+              this.timer = null;
+            }
+            this.timer = setTimeout(() => {
+              if (this.userText.indexOf(converter("关闭语音助手")) != -1) {
+                // return setTimeout(()=>{
+                this.show = false;
+                this.showTextIndex = 3;
+                this.aiStatus = 2;
+                this.aiText = "";
+                this.userText = "";
+                this.stopRecord();
+                return;
+                // },1000)
+              }
+              this.showTextIndex = 2;
+              this.aiText = "";
+              let regExp = new RegExp(
+                converter("计时") + "(.+)" + converter("分钟")
+              );
+              if (false && regExp.test(this.userText)) {
+                // setTimeout(() => {
+                // let _number = this.userText.match(regExp)[1];
+                // let _time = 0;
+                // if (!/^\d+$/.test(_number)) {
+                //   _time = this.chineseToNumber(_number) * 60;
+                // } else {
+                //   _time = parseInt(_numberList[1]) * 60;
+                // }
+
+                // this.$emit("startTime", _time);
+                // this.aiStatus = 0;
+                // this.showTextIndex = 0;
+                // this.aiText =
+                //   "好的,我已为您计时" +
+                //   this.userText.match(regExp)[1] +
+                //   "分钟。";
+                // this.userText = "";
+                // this.timer = setTimeout(() => {
+                //   this.showTextIndex = 3;
+                //   this.aiStatus = 2;
+                //   this.aiText = "";
+                //   this.userText = "";
+                // }, 3000);
+                // }, 2000);
+              } else {
+                this.chatLoading = true;
+                const _uuid = uuidv4();
+                let params = {
+                  assistant_id: "f8e1ebb2-2e0d-11ef-8bf4-12e77c4cb76b",
+                  userId: this.userId,
+                  message: this.userText,
+                  session_name: _uuid + "-qgt",
+                  uid: _uuid,
+                  file_ids: []
+                };
+                this.ajax
+                  // .post("https://claude3.cocorobo.cn/chat", params)
+                  // .post("https://gpt4.cocorobo.cn/chat", params)
+                  .post(
+                    "https://gpt4.cocorobo.cn/ai_agent_park_chat_new",
+                    params
+                  )
+                  .then(res => {
+                    if (
+                      converter(res.data.FunctionResponse.result) ==
+                      converter("发送成功")
+                    ) {
+                      this.userText = "";
+                    } else {
+                      // this.$message.warning(res.data.FunctionResponse.result);
+                      console.log(res.data.FunctionResponse.result);
+                      this.chatLoading = false;
+                      this.aiStatus = 0;
+                      this.showTextIndex = 0;
+                      this.aiText = "对不起,我无法理解您的问题,请重新提问";
+                      // this.timer = setTimeout(() => {
+                      //   this.showTextIndex = 3;
+                      //   this.aiStatus = 2;
+                      //   this.aiText = "";
+                      //   this.userText = "";
+                      // }, 3000);
+                    }
+                  })
+                  .catch(e => {
+                    console.log(e);
+                    this.chatLoading = false;
+                    this.aiStatus = 0;
+                    this.showTextIndex = 0;
+                    this.aiText = "对不起,我无法理解您的问题,请重新提问";
+                    // this.timer = setTimeout(() => {
+                    //   this.showTextIndex = 3;
+                    //   this.aiStatus = 2;
+                    //   this.aiText = "";
+                    //   this.userText = "";
+                    // }, 3000);
+                  });
+                // 通过流获取ai对话数据
+                this.getAtAuContent(_uuid);
+              }
+            }, 5000);
+          }
+        } else {
+          console.log("不响应");
+        }
+      };
+    },
+    stopRecord() {
+			// this.show = false;
+			// this.showIndex = 2;
+			// return
+      let iiframe = this.$refs["iiframe"];
+      iiframe.contentWindow.window.document
+        .getElementById("scenarioStopButton")
+        .click();
+      if (this.talkLoading) {
+        this.stopTalk();
+      }
+      // this.stopTalk();
+      // 录音借宿
+      iiframe.contentWindow.onSessionStopped = (s, e) => {
+        this.isOpen = false;
+        this.show = false;
+        this.showTextIndex = 3;
+        this.showIndex = 2;
+        this.$message.success("已关闭语音助手");
+        if (this.talkLoading) {
+          this.$refs.iiframe2.contentWindow.closesynthesizer();
+        }
+        this.userText = "";
+        this.aiText = "";
+      };
+    },
+    chineseToNumber(chinese) {
+      var OpenCC = require("opencc-js");
+      let converter = OpenCC.Converter({
+        from: "hk",
+        to: "cn"
+      });
+      chinese = converter(chinese);
+      const chineseNumbers = {
+        零: 0,
+        一: 1,
+        二: 2,
+        三: 3,
+        四: 4,
+        五: 5,
+        六: 6,
+        七: 7,
+        八: 8,
+        九: 9,
+        十: 10,
+        百: 100,
+        千: 1000,
+        万: 10000,
+        亿: 100000000
+      };
+
+      let result = 0;
+      let tempNum = 0; // 用于累积处理
+      let sectionNum = 0; // 每个段的值
+
+      for (let i = 0; i < chinese.length; i++) {
+        const char = chinese[i];
+        const num = chineseNumbers[char];
+
+        if (num === undefined) {
+          throw new Error(`Unexpected character: ${char}`);
+        }
+
+        if (
+          num === 10 ||
+          num === 100 ||
+          num === 1000 ||
+          num === 10000 ||
+          num === 100000000
+        ) {
+          if (tempNum === 0) tempNum = 1; // 如果前面没有数,默认是1
+          tempNum *= num;
+
+          if (num === 10000 || num === 100000000) {
+            sectionNum += tempNum;
+            result += sectionNum;
+            tempNum = 0;
+            sectionNum = 0;
+          }
+        } else {
+          tempNum += num;
+        }
+      }
+
+      result += sectionNum + tempNum;
+      return result;
+    },
+    removeMarkdown(text) {
+      return text
+        .replace(/[#*_~`>+\-]/g, "") // 移除 #、*、_、~、`、>、+、- 符号
+        .replace(/!\[.*?\]\(.*?\)/g, "") // 移除图片
+        .replace(/\[.*?\]\(.*?\)/g, "") // 移除链接
+        .replace(/```[\s\S]*?```/g, "") // 移除代码块(不使用 s 标志)
+        .replace(/`[^`]*`/g, "") // 移除行内代码
+        .replace(/\d+\./g, "") // 移除有序列表
+        .replace(/^\s*[-*+]\s+/gm, "") // 移除无序列表
+        .replace(/\s+/g, " ") // 将多个空白字符替换为一个空格
+        .trim(); // 去除字符串两端的空白字符
+    },
+    getAtAuContent(_uid) {
+      this.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 _talkText = "";
+      // let _talkIndex = 0;
+      // const md = new MarkdownIt();
+      this.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("_", "");
+          this.aiText = _mdText;
+					this.scrollBottom();
+          if (_talkText != "") {
+            let _resultText = this.removeMarkdown(_talkText);
+            this.talkTextList.push(_resultText);
+            _talkText = "";
+            if (!this.talkLoading) this.talkText();
+          }
+          this.chatLoading = false;
+          this.source.close();
+					this.source = null;
+        } else {
+          // _talkIndex+=1;
+          let _text = _eData.content.replace("'", "").replace("'", "");
+          if (_allText == "") {
+            _allText = _text.replace(/^\n+/, ""); //去掉回复消息中偶尔开头就存在的连续换行符
+            _talkText += _text.replace(/^\n+/, "");
+          } else {
+            _allText += _text;
+            _talkText += _text;
+          }
+          `~`;
+          _mdText = _allText + "_";
+          _mdText = _mdText.replace(/\\n/g, "\n");
+          _mdText = _mdText.replace(/\\/g, "");
+          if (_allText.split("```").length % 2 == 0) _mdText += "\n```\n";
+          this.aiText = _mdText;
+          this.showTextIndex = 0;
+					this.scrollBottom();
+          if (/[,。:;?!)]/.test(_talkText)) {
+            let _resultText = this.removeMarkdown(_talkText);
+            this.talkTextList.push(_resultText);
+            _talkText = "";
+            if (!this.talkLoading) this.talkText();
+          }
+        }
+      };
+    },
+    talkText() {
+      let _text = this.talkTextList.shift();
+      let _talkTextIiframe2 = this.$refs.iiframe2;
+
+      if (_text) {
+        this.talkLoading = true;
+        if (this.timer) {
+          clearTimeout(this.timer);
+          this.timer = null;
+        }
+        console.log(`👉转语音:${_text}`);
+        _talkTextIiframe2.contentWindow.texttospeech(
+          _text,
+          this.talkText,
+          this.endTalk
+        );
+      } else {
+        _talkTextIiframe2.contentWindow.closesynthesizer();
+      }
+    },
+    endTalk() {
+      console.log("👉转语音结束👈");
+      this.talkLoading = false;
+    },
+    stopTalk() {
+			// return this.$message.info("停止")
+      this.talkTextList = [];
+      let _talkTextIiframe2 = this.$refs.iiframe2;
+      _talkTextIiframe2.contentWindow.closesynthesizer();
+      _talkTextIiframe2.contentWindow.pausesynthesizer();
+      this.talkLoading = false;
+    },
+		interrupt(){
+			// return this.$message.info("打断")
+			if(this.source){
+				this.source.close()
+			}
+			this.stopTalk();
+			
+		}
+  }
+};
+</script>
+
+<style scoped>
+.languageAssistant {
+  width: 100%;
+  height: 100%;
+	border-radius: 10px 0 0 10px;
+	/* background-image: linear-gradient(to top, #007adf 0%, #00ecbc 100%);
+	 */
+	 background-image: linear-gradient(-225deg, #2CD8D5 0%, #6B8DD6 48%, #8E37D7 100%);
+  /* display: flex;
+  flex-direction: column;
+  align-items: center; */
+  /* justify-content: center; */
+  overflow: auto;
+	text-align:center;
+}
+
+.la_coco{
+	height: 300px;
+	width: 100%;
+	display: flex;
+	justify-content: center;
+	align-items: flex-end;
+}
+
+.la_message{
+	height: 400px;
+	width: 100%;
+	/* display: flex; */
+	padding:10px;
+	box-sizing: border-box;
+	margin: 20px 0;
+}
+
+.la_m_talk{
+	/* width:100%; */
+	height:auto;
+	max-height:400px;
+	box-sizing: border-box;
+	overflow:auto;
+}
+
+.la_m_talk>div{
+	background:#BFBFBF;
+	padding: 10px;
+	box-sizing: border-box;
+	border-radius:10px;
+}
+
+.la_btn{
+	height: 200px;
+	width: 100%;
+	display: flex;
+	margin-bottom: 100px;
+}
+
+
+.la_b_noTel{
+	width:100%;
+	height:100%;
+	display:flex;
+	justify-content: center;
+	align-items: center;
+}
+
+.la_b_noTel>svg{
+	fill:#52c41a;
+	width:80px;
+	height:80px;
+	cursor: pointer;
+}
+
+.la_b_isTel{
+	width:100%;
+	height:100%;
+	display:flex;
+	justify-content: center;
+	align-items: center;
+}
+
+.la_b_isTel>svg{
+	fill:#FF0E55;
+	width:80px;
+	height:80px;
+	cursor: pointer;
+	transform: rotate(-135deg);
+}
+
+.la_b_isTel>span{
+	display: flex;
+	justify-content: center;
+	align-items:center;
+	width:45px;
+	height:45px;
+	border-radius:50%;
+	cursor: pointer;
+	margin: 0 20px;
+	padding:5px;
+	background:#BFBFBF;
+}
+
+.la_b_isTel>span>svg{
+	border:solid 2px black;
+	border-radius:50%;
+	width:100%;
+	height:100%;
+	display: flex;
+	justify-content: center;
+	align-items:center;
+}
+</style>

+ 0 - 29
src/components/classRoomHelper/component/levitatedSphere.vue

@@ -405,12 +405,6 @@ export default {
             _talkText = "";
             if (!this.talkLoading) this.talkText();
           }
-          // if(_talkIndex==10){
-          // 	_talkIndex = 0;
-          // 	this.talkTextList.push(_talkText)
-          // 	_talkText = "";
-          // 	if(!this.talkLoading)this.talkText();
-          // }
         }
       };
     },
@@ -425,48 +419,25 @@ export default {
           this.timer = null;
         }
         console.log(`👉转语音:${_text}`);
-        // if(this.talkTextList.length==0){
-        // 	console.log("👉最后一个了,执行结束 👈")
-        // 	_talkTextIiframe2.contentWindow.closesynthesizer();
-        // }
-        // setTimeout(()=>{
-        // 	this.talkText();
-        // },2000)
         _talkTextIiframe2.contentWindow.texttospeech(
           _text,
           this.talkText,
           this.endTalk
         );
       } else {
-        // console.log("👉转语音结束👈");
         _talkTextIiframe2.contentWindow.closesynthesizer();
-        // this.talkLoading = false;
-        // this.timer = setTimeout(() => {
-        //   this.showTextIndex = 3;
-        //   this.aiStatus = 2;
-        //   this.aiText = "";
-        //   this.userText = "";
-        // 	this.time = null;
-        // }, 5000);
       }
     },
     endTalk() {
       console.log("👉转语音结束👈");
-      // let _talkTextIiframe2 = this.$refs.iiframe2;
-      // _talkTextIiframe2.contentWindow.closesynthesizer();
       this.talkLoading = false;
     },
     stopTalk() {
       this.talkTextList = [];
-
       let _talkTextIiframe2 = this.$refs.iiframe2;
       _talkTextIiframe2.contentWindow.closesynthesizer();
       _talkTextIiframe2.contentWindow.pausesynthesizer();
       this.talkLoading = false;
-      // this.talkLoading = false;
-      // this.talkLoading = false;
-      // let _talkTextIiframe2 = this.$refs.iiframe2;
-      // _talkTextIiframe2.contentWindow.closesynthesizer();
     }
   },
   mounted() {

+ 16 - 12
src/components/classRoomHelper/index.vue

@@ -23,6 +23,8 @@
         v-if="itemType == 2"
       />
 			<countdown ref="countdownRef"  :fileId="fileId" :courseDetail="courseDetail" v-show="itemType==3"/>
+
+			<languageAssistant ref="languageAssistantRef" v-if="itemType==4"/>
       <!-- <dialogArea
         :courseDetail="courseDetail"
 				:openMegaphone="openMegaphone"
@@ -189,14 +191,14 @@
           </el-tooltip>
 				</div>
 
-				<div @click.stop="startAssistant()" :class="[recordType==1?'ch_nav_box_middle_item_active':'']">
+				<div @click.stop="changeItemType(4)" :class="[itemType == 4?'ch_nav_box_middle_item_active':'']">
 					<el-tooltip
             class="item"
             effect="dark"
-            :content="recordType==0?'开启语音助手':'关闭语音助手'"
+            :content="itemType != 4?'开启语音助手':'关闭语音助手'"
             placement="top"
           >
-            <img v-if="recordType!=1" :src="require('../../assets/icon/course/robot.svg')" />
+            <img v-if="itemType != 4" :src="require('../../assets/icon/course/robot.svg')" />
 						<img v-else :src="require('../../assets/icon/course/robot2.svg')" />
           </el-tooltip>
 				</div>
@@ -235,8 +237,8 @@
         </div>
       </div>
     </div>
-    <levitatedSphere ref="levitatedSphereRef" @startTime="startTime" />
-    <timepiece ref="timepieceRef" />
+    <!-- <levitatedSphere ref="levitatedSphereRef" @startTime="startTime" /> -->
+    <!-- <timepiece ref="timepieceRef" /> -->
 		<AnnotationCanvas ref="AnnotationCanvasRef"/>
   </div>
 </template>
@@ -244,21 +246,23 @@
 <script>
 import searchArea from "./component/searchArea.vue";
 import taskArea from "./component/taskArea.vue";
-import dialogArea from "./component/dialogArea.vue";
-import levitatedSphere from "./component/levitatedSphere.vue";
-import timepiece from "./component/timepiece.vue";
+// import dialogArea from "./component/dialogArea.vue";
+// import levitatedSphere from "./component/levitatedSphere.vue";
+// import timepiece from "./component/timepiece.vue";
 import countdown from "./component/countdown.vue";
 import AnnotationCanvas from './component/AnnotationCanvas.vue'
+import languageAssistant from "./component/languageAssistant.vue";
 export default {
   emits: ["refresh", "goStep", "backPage", "authority", "review","stopRecording","startRecording"],
   components: {
     searchArea,
     taskArea,
-    dialogArea,
-    levitatedSphere,
-    timepiece,
+    // dialogArea,
+    // levitatedSphere,
+    // timepiece,
 		countdown,
-		AnnotationCanvas
+		AnnotationCanvas,
+		languageAssistant
   },
   props: {
     courseDetail: {

+ 1 - 1
src/components/easy2/studyStudent.vue

@@ -12385,7 +12385,7 @@ export default {
 				isScoreList:[],	
 			},
 			classRoomHelperWidth: '85px',
-			orgArray:['1973f6c7-1561-11ee-91d8-005056b86db5','777559d2-7239-11ee-b98c-005056b86db5','884c5665-a453-46f3-b7b6-01d575290aa9','0fec3a8a-ad04-11ed-b13d-005056b86db5'],
+			orgArray:['1973f6c7-1561-11ee-91d8-005056b86db5','777559d2-7239-11ee-b98c-005056b86db5','884c5665-a453-46f3-b7b6-01d575290aa9','0fec3a8a-ad04-11ed-b13d-005056b86db5','c9a6de59-8b4f-4be1-8565-a08081f649d3'],
       oidArray:['f297fbdc-f0a0-11ee-b534-005056b86db5','45facc0a-1211-11ec-80ad-005056b86db5']
     };
   },

+ 1 - 1
src/components/easy3/studyStudent.vue

@@ -12421,7 +12421,7 @@ export default {
 				isScoreList:[],	
 			},
 			classRoomHelperWidth: '85px',
-			orgArray:['1973f6c7-1561-11ee-91d8-005056b86db5','777559d2-7239-11ee-b98c-005056b86db5','884c5665-a453-46f3-b7b6-01d575290aa9','0fec3a8a-ad04-11ed-b13d-005056b86db5'],
+			orgArray:['1973f6c7-1561-11ee-91d8-005056b86db5','777559d2-7239-11ee-b98c-005056b86db5','884c5665-a453-46f3-b7b6-01d575290aa9','0fec3a8a-ad04-11ed-b13d-005056b86db5','c9a6de59-8b4f-4be1-8565-a08081f649d3'],
       oidArray:['f297fbdc-f0a0-11ee-b534-005056b86db5','45facc0a-1211-11ec-80ad-005056b86db5']
     };
   },

+ 1 - 1
src/components/studyStudent.vue

@@ -12358,7 +12358,7 @@ export default {
 				isScoreList:[],	
 			},
       classRoomHelperWidth: '85px',
-			orgArray:['1973f6c7-1561-11ee-91d8-005056b86db5','777559d2-7239-11ee-b98c-005056b86db5','884c5665-a453-46f3-b7b6-01d575290aa9','0fec3a8a-ad04-11ed-b13d-005056b86db5'],
+			orgArray:['1973f6c7-1561-11ee-91d8-005056b86db5','777559d2-7239-11ee-b98c-005056b86db5','884c5665-a453-46f3-b7b6-01d575290aa9','0fec3a8a-ad04-11ed-b13d-005056b86db5','c9a6de59-8b4f-4be1-8565-a08081f649d3'],
       oidArray:['f297fbdc-f0a0-11ee-b534-005056b86db5','45facc0a-1211-11ec-80ad-005056b86db5']
     };
   },