浏览代码

课堂助手

SanHQin 8 月之前
父节点
当前提交
2f132fbb5e

+ 1 - 0
src/assets/icon/course/foldIcon.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1720058031510" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8647" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><path d="M913.4 400.5c-60.7 0-110.6 49.8-110.6 110.7 0 61 49.7 110.7 110.6 110.7 60.8 0 110.6-49.8 110.6-110.7s-49.9-110.7-110.6-110.7z m-400.7 0.8c-59.1 0-107.6 49.9-107.6 111.1s48.4 111.1 107.6 111.1c59.1 0 107.6-49.9 107.6-111.1S572 401.3 512.7 401.3z m-403.2 0.4C49.3 401.7 0 451.4 0 512.4s49.2 110.7 109.5 110.7S219 573.3 219 512.4c-0.1-61-49.4-110.7-109.5-110.7z" fill="#000000" p-id="8648"></path></svg>

+ 1 - 0
src/assets/icon/course/record.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1720079124747" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="17601" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><path d="M617.792 807.424H173.44c-51.328 0-93.056-45.248-93.056-100.928V384.256c0-55.68 41.728-100.992 93.056-100.992h444.352c51.328 0 93.056 45.312 93.056 100.992v322.24c0 55.68-41.728 100.928-93.056 100.928zM173.44 331.328c-24.832 0-45.056 23.744-45.056 52.992v322.24c0 29.184 20.16 52.928 45.056 52.928h444.352c24.896 0 45.056-23.744 45.056-52.928V384.256c0-29.248-20.16-52.992-45.056-52.992H173.44z" p-id="17602" fill="#000000"></path><path d="M907.328 779.776a48.192 48.192 0 0 1-25.344-7.808L664.256 636.8l25.344-40.768 208.064 129.216 0.128-359.68-208.192 129.216-25.344-40.768 217.664-135.232c14.848-9.152 30.656-10.24 43.584-3.136 12.864 7.168 20.288 21.312 20.288 38.656v382.144c0 17.344-7.36 31.424-20.288 38.656a37.824 37.824 0 0 1-18.176 4.672z" p-id="17603" fill="#000000"></path><path d="M214.528 416.512m-33.024 0a33.024 33.024 0 1 0 66.048 0 33.024 33.024 0 1 0-66.048 0Z" p-id="17604" fill="#000000"></path></svg>

+ 1 - 0
src/assets/icon/course/record2.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1720079124747" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="17601" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><path d="M617.792 807.424H173.44c-51.328 0-93.056-45.248-93.056-100.928V384.256c0-55.68 41.728-100.992 93.056-100.992h444.352c51.328 0 93.056 45.312 93.056 100.992v322.24c0 55.68-41.728 100.928-93.056 100.928zM173.44 331.328c-24.832 0-45.056 23.744-45.056 52.992v322.24c0 29.184 20.16 52.928 45.056 52.928h444.352c24.896 0 45.056-23.744 45.056-52.928V384.256c0-29.248-20.16-52.992-45.056-52.992H173.44z" p-id="17602" fill="#ffffff"></path><path d="M907.328 779.776a48.192 48.192 0 0 1-25.344-7.808L664.256 636.8l25.344-40.768 208.064 129.216 0.128-359.68-208.192 129.216-25.344-40.768 217.664-135.232c14.848-9.152 30.656-10.24 43.584-3.136 12.864 7.168 20.288 21.312 20.288 38.656v382.144c0 17.344-7.36 31.424-20.288 38.656a37.824 37.824 0 0 1-18.176 4.672z" p-id="17603" fill="#ffffff"></path><path d="M214.528 416.512m-33.024 0a33.024 33.024 0 1 0 66.048 0 33.024 33.024 0 1 0-66.048 0Z" p-id="17604" fill="#ffffff"></path></svg>

+ 1 - 0
src/assets/icon/course/robot.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1720074794426" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12952" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><path d="M271.36 107.008l3.982222 3.299556 96.540445 96.597333A334.392889 334.392889 0 0 1 512 176.355556c50.005333 0 97.450667 10.922667 140.117333 30.549333l96.597334-96.597333 3.925333-3.299556a28.444444 28.444444 0 0 1 39.594667 39.594667l-3.299556 3.982222-85.617778 85.617778A335.246222 335.246222 0 0 1 847.644444 512c0 47.331556-9.841778 93.297778-28.501333 135.566222a130.787556 130.787556 0 0 1-42.211555 250.993778l-8.931556 0.284444h-512a130.844444 130.844444 0 0 1-51.086222-251.335111A333.767111 333.767111 0 0 1 176.355556 512a335.246222 335.246222 0 0 1 144.327111-275.797333L235.064889 150.528a28.444444 28.444444 0 0 1 36.295111-43.52zM768 694.044444h-512a73.955556 73.955556 0 0 0-7.566222 147.512889l7.566222 0.398223h512a73.955556 73.955556 0 1 0 0-147.911112zM512 233.244444a278.755556 278.755556 0 0 0-249.173333 403.911112h498.232889l0.568888-0.853334A278.755556 278.755556 0 0 0 512 233.244444zM102.4 381.155556a28.444444 28.444444 0 0 1 27.989333 23.324444l0.455111 5.12v179.2a28.444444 28.444444 0 0 1-56.433777 5.12l-0.455111-5.12V409.6a28.444444 28.444444 0 0 1 28.444444-28.444444z m819.2 0a28.444444 28.444444 0 0 1 27.989333 23.324444l0.455111 5.12v179.2a28.444444 28.444444 0 0 1-56.433777 5.12l-0.455111-5.12V409.6a28.444444 28.444444 0 0 1 28.444444-28.444444z m-512 28.444444a51.2 51.2 0 1 1 0 102.4 51.2 51.2 0 0 1 0-102.4z m204.8 0a51.2 51.2 0 1 1 0 102.4 51.2 51.2 0 0 1 0-102.4z" fill="#000000" p-id="12953"></path></svg>

+ 1 - 0
src/assets/icon/course/robot2.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1720074794426" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12952" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><path d="M271.36 107.008l3.982222 3.299556 96.540445 96.597333A334.392889 334.392889 0 0 1 512 176.355556c50.005333 0 97.450667 10.922667 140.117333 30.549333l96.597334-96.597333 3.925333-3.299556a28.444444 28.444444 0 0 1 39.594667 39.594667l-3.299556 3.982222-85.617778 85.617778A335.246222 335.246222 0 0 1 847.644444 512c0 47.331556-9.841778 93.297778-28.501333 135.566222a130.787556 130.787556 0 0 1-42.211555 250.993778l-8.931556 0.284444h-512a130.844444 130.844444 0 0 1-51.086222-251.335111A333.767111 333.767111 0 0 1 176.355556 512a335.246222 335.246222 0 0 1 144.327111-275.797333L235.064889 150.528a28.444444 28.444444 0 0 1 36.295111-43.52zM768 694.044444h-512a73.955556 73.955556 0 0 0-7.566222 147.512889l7.566222 0.398223h512a73.955556 73.955556 0 1 0 0-147.911112zM512 233.244444a278.755556 278.755556 0 0 0-249.173333 403.911112h498.232889l0.568888-0.853334A278.755556 278.755556 0 0 0 512 233.244444zM102.4 381.155556a28.444444 28.444444 0 0 1 27.989333 23.324444l0.455111 5.12v179.2a28.444444 28.444444 0 0 1-56.433777 5.12l-0.455111-5.12V409.6a28.444444 28.444444 0 0 1 28.444444-28.444444z m819.2 0a28.444444 28.444444 0 0 1 27.989333 23.324444l0.455111 5.12v179.2a28.444444 28.444444 0 0 1-56.433777 5.12l-0.455111-5.12V409.6a28.444444 28.444444 0 0 1 28.444444-28.444444z m-512 28.444444a51.2 51.2 0 1 1 0 102.4 51.2 51.2 0 0 1 0-102.4z m204.8 0a51.2 51.2 0 1 1 0 102.4 51.2 51.2 0 0 1 0-102.4z" fill="#ffffff" p-id="12953"></path></svg>

+ 6 - 1
src/components/classRoomHelper/component/dialogArea.vue

@@ -568,6 +568,7 @@ export default {
 			//http://gpt4.cocorobo.cn:8011/question/   https://gpt4.cocorobo.cn/question/
       let _allText = "";
       let _mdText = "";
+			let _index = 0;
       // const md = new MarkdownIt();
       this.source.onmessage = _e => {
         let _eData = JSON.parse(_e.data);
@@ -590,6 +591,7 @@ export default {
           this.source.close();
           this.insertChat(_uid);
         } else {
+					_index+=1;
           let _text = _eData.content.replace("'", "").replace("'", "");
           if (_allText == "") {
             _allText = _text.replace(/^\n+/, ""); //去掉回复消息中偶尔开头就存在的连续换行符
@@ -602,11 +604,14 @@ export default {
           if (_allText.split("```").length % 2 == 0) _mdText += "\n```\n";
           //转化返回的回复流数据
           // _mdText = md.render(_mdText);
-          this.chatList.find(i => i.uid == _uid).aiContent = _mdText;
+          if(_index==10){
+						this.chatList.find(i => i.uid == _uid).aiContent = _mdText;
           this.chatList.find(i => i.uid == _uid).loading = false;
           this.$nextTick(() => {
             this.$refs.chatRef.scrollTop = this.$refs.chatRef.scrollHeight;
           });
+					_index= 0;
+					}
           // 处理流数据
         }
       };

+ 79 - 107
src/components/classRoomHelper/component/searchArea.vue

@@ -2,32 +2,6 @@
   <div class="search">
     <div class="s_top" ref="chatRef">
       
-      <!-- <div class="s_t_chat">
-        <div class="s_t_c_ai">
-          <div class="s_t_c_a_left">
-            <span>Ai</span>
-          </div>
-          <div class="s_t_c_a_right">
-            <div class="s_t_c_a_r_content2">
-              <div class="s_t_c_a_r_c_title">
-                <img :src="require('../../../assets/icon/course/idea.png')" />
-                <span>猜你想搜:</span>
-              </div>
-              <div
-                class="s_t_c_a_r_c_item"
-                v-for="(item, index) in wantSearch"
-                :key="index"
-                @click="sendAiIdea(item.label)"
-              >
-                {{ index + 1 }}.{{ item.title }}:{{ item.label }}
-              </div>
-            </div>
-            <div class="s_t_c_a_r_time">
-              {{ new Date().toLocaleString().replace(/\//gi, "-") }}
-            </div>
-          </div>
-        </div>
-      </div> -->
       <div class="s_t_chat" v-for="(item, index) in chatList" :key="index">
         <div
           class="s_t_c_user"
@@ -79,6 +53,7 @@
                   alt=""
                   @click="previewImg(i.image)"
                 />
+								
 								<span class="download_image" @click.stop="download(i.image)">
                   <img
                     :src="require('../../../assets/icon/fileIcon/download.png')"
@@ -86,7 +61,7 @@
                 </span>
               </div>
               <!-- {{ item }} -->
-              <div style="margin-top: 10px;width: 100%;display: flex;justify-content: end;" v-if="pan(item.aiContent).length > 0 && chatList.length-2 == index" >
+              <div style="margin-top: 10px;width: 100%;display: flex;justify-content: end;" v-if="pan(item.aiContent).length > 1 && chatList.length-2 == index" >
                 <img style="cursor: pointer;" @click="resetImg(item.content)" src="../../../assets/icon/course/resImg.png" alt="">
               </div>
             </div>
@@ -170,42 +145,32 @@
       </div>
     </div>
     <div class="s_bottom">
-      <!-- <div class="s_b_ba-item" @click.stop="choiceRole()">选择角色</div> -->
+			<!-- <div class="s_b_btnAreaTop">
 
+			</div> -->
       <div class="s_b_btnArea">
-        <!-- <div class="s_b_ba-item">
-          <el-checkbox
-            :disabled="loading"
-            style="display: flex;"
-            v-model="imageCheck"
-            >图片</el-checkbox
-          >
+				<div :class="['s_b_ba-item',sendType==3?'s_b_ba_active':'']" @click="chooseType(3)" >
+          <!-- <img src="../../../assets/icon/course/sImg.png" style="margin-right: 5px;" alt="" v-if="sendType!=3">
+					<img src="../../../assets/icon/course/sImg2.png" style="margin-right: 5px;" alt="" v-else> -->
+					生成图片
         </div>
-        <div class="s_b_ba-item">
-          <el-checkbox
-            :disabled="loading"
-            style="display: flex;"
-            v-model="videoCheck"
-            >视频</el-checkbox
-          >
-        </div> -->
-
         <div :class="['s_b_ba-item',sendType==1?'s_b_ba_active':'']" @click="chooseType(1)" >
-          <img src="../../../assets/icon/course/sImg.png" style="margin-right: 5px;" alt="" v-if="sendType!=1">
-					<img src="../../../assets/icon/course/sImg2.png" style="margin-right: 5px;" alt="" v-else>图片
+          <!-- <img src="../../../assets/icon/course/sImg.png" style="margin-right: 5px;" alt="" v-if="sendType!=1">
+					<img src="../../../assets/icon/course/sImg2.png" style="margin-right: 5px;" alt="" v-else> -->
+					搜索图片
         </div>
         <div :class="['s_b_ba-item',sendType==2?'s_b_ba_active':'']" @click="chooseType(2)">
-          <img src="../../../assets/icon/course/sRio.png" style="margin-right: 5px;" alt="" v-if="sendType!=2">
-					<img src="../../../assets/icon/course/sRio2.png" style="margin-right: 5px;" alt="" v-else>视频
-        </div>
-
-        <div class="s_b_ba-item" @click="clear()" v-if="!openAtBox">
+          <!-- <img src="../../../assets/icon/course/sRio.png" style="margin-right: 5px;" alt="" v-if="sendType!=2">
+					<img src="../../../assets/icon/course/sRio2.png" style="margin-right: 5px;" alt="" v-else> -->
+					搜索视频
+				</div>
+        <!-- <div class="s_b_ba-item" @click="clear()" v-if="!openAtBox">
           清空聊天记录
         </div>
 
 				<div :class="['s_b_ba-item',recordType==1?'s_b_ba_active':'']" @click="$parent.startAssistant()" v-if="!openAtBox">
           语音助手
-        </div>
+        </div> -->
 
       </div>
 
@@ -836,9 +801,12 @@ export default {
       let _msg = ``;
       this.chatLoading = true;
       let _uuid = uuidv4();
+			// if(this.sendType==3){
+			// 	_text = `帮我生成一张图片:`
+			// }
       this.chatList.push({
         role: "user",
-        content: `${_text}`,
+        content: `${this.sendType==3?`帮我生成一张图片:${_text}`:_text}`,
         uid: _uuid,
         AI: "AI",
         aiContent: "",
@@ -851,24 +819,7 @@ export default {
       });
       this.scrollBottom();
 			console.log(this.sendType)
-      if (_text.indexOf("视频") != -1 || this.sendType == 2) {
-				//return this.ajax.get(`https://www.googleapis.com/youtube/v3/search?key=AIzaSyBUvNQ5Wyua4PbStE2vp3t7MIY4htry-4M&part=snippet&q=${_text}&maxResults=10&type=video&order=relevance&regionCode=HK`).then(res=>{
-				//	console.log(res)
-				//	let _dataList = res.data.items;
-				//	let _resultText = ``;
-				//	_dataList.forEach(i=>{
-				//		_resultText+=`名称:${i.snippet.title}\n简介:${i.snippet.description}\n地址:[https://www.youtube.com/embed/${i.id.videoId}](https://www.youtube.com/embed/${i.id.videoId})\n\n`
-				//	})
-				//	this.chatList.find(i => i.uid == _uuid).aiContent =_resultText
-				//	this.chatList.find(i => i.uid == _uuid).loading = false;
-        //  this.chatLoading = false;
-				//	this.scrollBottom();
-        //  this.insertChat(_uuid);
-				//	this.text = "";
-				//}).catch(e=>{
-				//	this.$message.error('获取视频失败');
-				//	this.chatLoading = false;
-				//})
+      if ( this.sendType == 2 || _text.indexOf("视频") != -1) {
 					return this.ajax.post(`https://gpt4.cocorobo.cn/get_network_search`,{
 						 engine:"bilibili",
     				keyword:_text
@@ -890,36 +841,44 @@ export default {
 					this.$message.error('获取视频失败');
 					this.chatLoading = false;
 				})
-//         _msg = `
-// NOTICE
-// Language: Please use the same language as the user requirement, if the user speaks Chinese, the specific text of your answer should also be in Chinese.
-// ATTENTION: Use '##' to SPLIT SECTIONS, not '#'. Output format carefully referenced "Format example".
-// Instruction: Based on the context, follow "Format example", write content.
-
-// # Context
-// ## 任务
-// 你的任务是根据用户的请求,结合“课程信息”,在Ted.com等教育网站上搜索相关视频,并且按照“输出格式”将结果输出给用户。
-// 课程信息
-// 课程标题:${this.courseDetail.title}
-// 分类:${this.courseDetail.name ? this.courseDetail.name : "无"}
-// 学生年级:${this.courseDetail.classname ? this.courseDetail.classname : "无"}
-// 用户搜索:${_text}
-
-// ## 规则
-// 1. 输出结果必须真实有效,不要捏造无效的视频链接
-// 2. 当课程信息中的子条目内容为“无”时,无视这些条目进行输出即可。
-// 3. 如果没有相关内容,请跟用户表明没有找到相关视频链接内容,然后推荐搜索建议
-// 4. 在ted.com等教育网站上搜索视频,并且以有序列表的形式将结果输出给用户
-// 5. 请一步步思考如何根据现有信息推送视频,但是最终输出结果不需要包含你的思考过程,只需要包含视频标题+链接。
-
-// # Format example
-// 视频来源: Ted.com
-// 视频标题:How AI could save (not destroy) education
-// 视频内容:介绍了一款AI教育软件
-// 视频链接https://www.ted.com/talks/sal_khan_how_ai_could_save_not_destroy_education
-// 				`;
-      } else if (_text.indexOf("图片") != -1 || this.sendType == 1) {
+			}else if(this.sendType == 3){
+		
+				this.text = "";
+        let params = {
+          page: this.ppage,
+          pagesize: 1,
+          query: _text
+        };
+        // this.$message.info(_text);
+        this.chatList.push({
+          role: "user",
+          content: `getImage`,
+          uid: _uuid,
+          AI: "AI",
+          aiContent: "",
+          oldContent: "",
+          isShowSynchronization: false,
+          filename: "",
+          index: this.chatList.length,
+          is_mind_map: false,
+          loading: true
+        });
+        this.ajax
+          .post("https://gpt.cocorobo.cn/search_image", params)
+          .then(res => {
+            let data = res.data.FunctionResponse.result;
+            // console.log('res',res.data.FunctionResponse.result);
+            this.chatList.find(i => i.uid == _uuid).aiContent = JSON.stringify(
+              data
+            );
+            this.chatList.find(i => i.uid == _uuid).loading = false;
+            this.chatLoading = false;
+            this.insertChat(_uuid);
+          });
+        return;
+      } else if (this.sendType == 1 || _text.indexOf("图片") != -1 ) {
         // console.log("图片");
+
         this.text = "";
         let params = {
           page: this.ppage,
@@ -1331,6 +1290,7 @@ ${_atList
 			//http://gpt4.cocorobo.cn:8011/question/   https://gpt4.cocorobo.cn/question/
       let _allText = "";
       let _mdText = "";
+			let _index = 0;
       // const md = new MarkdownIt();
       this.source.onmessage = _e => {
         let _eData = JSON.parse(_e.data);
@@ -1353,6 +1313,7 @@ ${_atList
           this.source.close();
           this.insertChat(_uid);
         } else {
+					_index+=1;
           let _text = _eData.content.replace("'", "").replace("'", "");
           if (_allText == "") {
             _allText = _text.replace(/^\n+/, ""); //去掉回复消息中偶尔开头就存在的连续换行符
@@ -1365,11 +1326,14 @@ ${_atList
           if (_allText.split("```").length % 2 == 0) _mdText += "\n```\n";
           //转化返回的回复流数据
           // _mdText = md.render(_mdText);
-          this.chatList.find(i => i.uid == _uid).aiContent = _mdText;
+         if(_index==10){
+					this.chatList.find(i => i.uid == _uid).aiContent = _mdText;
           this.chatList.find(i => i.uid == _uid).loading = false;
           this.$nextTick(() => {
             this.$refs.chatRef.scrollTop = this.$refs.chatRef.scrollHeight;
           });
+					_index= 0;
+				 }
           // 处理流数据
         }
       };
@@ -1499,12 +1463,6 @@ ${_atList
       if (this.loading) return this.$message.info("请稍等");
       this.send(text);
     },
-    sendImage() {
-      this.$message.info("发送图片");
-    },
-    sendVideo() {
-      this.$message.info("发送视频");
-    },
     getWantSearch() {
       this.chatLoading = true;
       let _uuid = uuidv4();
@@ -2447,6 +2405,18 @@ ${_wordData}
   position: relative;
 }
 
+.s_b_btnAreaTop{
+	width: 100%;
+  height: 35px;
+	margin-bottom:5px;
+  display: flex;
+  align-items: center;
+  box-sizing: border-box;
+  padding: 0 10px;
+	overflow: auto;
+	background-color: yellow;
+}
+
 .s_b_btnArea {
   width: 100%;
   height: 30px;
@@ -2454,6 +2424,7 @@ ${_wordData}
   align-items: center;
   box-sizing: border-box;
   padding: 0 10px;
+	overflow: auto;
 }
 
 .s_b_ba-item {
@@ -2471,6 +2442,7 @@ ${_wordData}
   font-size: 14px;
   cursor: pointer;
   margin-right: 10px;
+	white-space: nowrap;
 }
 
 .s_b_ba_active{

+ 6 - 1
src/components/classRoomHelper/component/taskArea.vue

@@ -472,6 +472,7 @@ export default {
 			//http://gpt4.cocorobo.cn:8011/question/   https://gpt4.cocorobo.cn/question/
       let _allText = "";
       let _mdText = "";
+			let _index = 0;
       // const md = new MarkdownIt();
       this.source.onmessage = _e => {
         let _eData = JSON.parse(_e.data);
@@ -494,6 +495,7 @@ export default {
           this.source.close();
           this.insertChat(_uid);
         } else {
+					_index+=1;
           let _text = _eData.content.replace("'", "").replace("'", "");
           if (_allText == "") {
             _allText = _text.replace(/^\n+/, ""); //去掉回复消息中偶尔开头就存在的连续换行符
@@ -506,11 +508,14 @@ export default {
           if (_allText.split("```").length % 2 == 0) _mdText += "\n```\n";
           //转化返回的回复流数据
           // _mdText = md.render(_mdText);
-          this.chatList.find(i => i.uid == _uid).aiContent = _mdText;
+         if(_index==10){
+					this.chatList.find(i => i.uid == _uid).aiContent = _mdText;
           this.chatList.find(i => i.uid == _uid).loading = false;
           this.$nextTick(() => {
             this.$refs.chatRef.scrollTop = this.$refs.chatRef.scrollHeight;
           });
+					_index = 0;
+				 }
           // 处理流数据
         }
       };

+ 171 - 74
src/components/classRoomHelper/index.vue

@@ -6,8 +6,8 @@
         ref="searchAreaRef"
         :navList="navList"
         :tcid="tcid"
-				:fileId="fileId"
-				:recordType="recordType"
+        :fileId="fileId"
+        :recordType="recordType"
         v-if="itemType == 1"
       />
       <taskArea
@@ -17,31 +17,69 @@
         :taskCount="taskCount"
         :worksStudent="worksStudent"
         ref="taskAreaRef"
-				:fileId="fileId"
+        :fileId="fileId"
         v-if="itemType == 2"
       />
       <dialogArea
         :courseDetail="courseDetail"
         ref="dialogAreaRef"
-				:fileId="fileId"
+        :fileId="fileId"
         v-if="itemType == 3"
       />
     </div>
     <div class="ch_nav_box">
       <div class="ch_nav_box_top">
-        <div @click="$emit('backPage')">
-          <el-tooltip class="item" effect="dark" content="返回" placement="top">
-            <img :src="require('../../assets/icon/course/return.png')" alt="" />
-          </el-tooltip>
-        </div>
-
-        <div @click="$emit('refresh')">
-          <el-tooltip class="item" effect="dark" content="刷新" placement="top">
+        <div @click="changeFold(!fold)">
+          <el-tooltip class="item" effect="dark" :content="fold?'折叠':'展开'" placement="top">
             <img
-              :src="require('../../assets/icon/course/refresh.png')"
+              :src="require('../../assets/icon/course/foldIcon.svg')"
               alt=""
+							:style="`${fold?'transform: rotate(90deg);':''}`"
             />
           </el-tooltip>
+          <div v-if="fold" class="itemFold">
+            <div @click="$emit('backPage')">
+              <el-tooltip
+                class="item"
+                effect="dark"
+                content="返回"
+                placement="top"
+              >
+                <img
+                  :src="require('../../assets/icon/course/return.png')"
+                  alt=""
+                />
+              </el-tooltip>
+            </div>
+
+            <div @click="$emit('refresh')">
+              <el-tooltip
+                class="item"
+                effect="dark"
+                content="刷新"
+                placement="top"
+              >
+                <img
+                  :src="require('../../assets/icon/course/refresh.png')"
+                  alt=""
+                />
+              </el-tooltip>
+            </div>
+
+            <div @click="$emit('authority')" v-if="tType == 1 || tType == 4">
+              <el-tooltip
+                class="item"
+                effect="dark"
+                content="权限"
+                placement="top"
+              >
+                <img
+                  :src="require('../../assets/icon/course/setting.png')"
+                  alt=""
+                />
+              </el-tooltip>
+            </div>
+          </div>
         </div>
 
         <div @click="$emit('review')" v-if="tType == 1">
@@ -53,53 +91,68 @@
             />
           </el-tooltip>
         </div>
-        <div @click="$emit('authority')" v-if="tType == 1 || tType == 4">
-          <!-- -->
-          <el-tooltip class="item" effect="dark" content="权限" placement="top">
+
+				<div @click="$emit('startRecording')" v-if="!videoStart && (tType == 1 || tType == 4)">
+          <el-tooltip class="item" effect="dark" content="录制" placement="top">
             <img
-              :src="require('../../assets/icon/course/setting.png')"
+              :src="require('../../assets/icon/course/record.svg')"
               alt=""
+              style="width: 22px;height: 22px;"
             />
           </el-tooltip>
         </div>
+
+				<div @click="$emit('stopRecording')" v-else-if="(tType == 1 || tType == 4)" style="background:#f63564">
+          <el-tooltip class="item" effect="dark" content="下载" placement="top">
+            <img
+              :src="require('../../assets/icon/course/record2.svg')"
+              alt=""
+              style="width: 22px;height: 22px;"
+            />
+          </el-tooltip>
+        </div>
+
+				
       </div>
       <div class="ch_nav_box_middle">
         <div
           :class="[
             'ch_nav_box_middle_item',
-            itemType == 1 ? 'ch_nav_box_middle_item_active' : ''
+            itemType == 2 ? 'ch_nav_box_middle_item_active' : ''
           ]"
-          @click.stop="changeItemType(1)"
+          @click.stop="changeItemType(2)"
         >
           <img
-            v-if="itemType == 1"
-            :src="require('../../assets/icon/course/up_active.png')"
+            v-if="itemType == 2"
+            :src="require('../../assets/icon/course/task_active.png')"
           />
           <img
-            v-if="itemType != 1"
-            :src="require('../../assets/icon/course/up.png')"
+            v-if="itemType != 2"
+            :src="require('../../assets/icon/course/task.png')"
           />
-          <!-- <span :style="`background:url(${itemType==1?require('../../assets/icon/course/up_active.png'):require('../../assets/icon/course/up.png')});`"></span> -->
-          <div>对话</div>
+          <!-- <span :style="`background:url(${itemType==2?require('../../assets/icon/course/task_active.png'):require('../../assets/icon/course/task.png')});`"></span> -->
+          <div>任务</div>
         </div>
-        <div
+
+				<div
           :class="[
             'ch_nav_box_middle_item',
-            itemType == 2 ? 'ch_nav_box_middle_item_active' : ''
+            itemType == 1 ? 'ch_nav_box_middle_item_active' : ''
           ]"
-          @click.stop="changeItemType(2)"
+          @click.stop="changeItemType(1)"
         >
           <img
-            v-if="itemType == 2"
-            :src="require('../../assets/icon/course/task_active.png')"
+            v-if="itemType == 1"
+            :src="require('../../assets/icon/course/up_active.png')"
           />
           <img
-            v-if="itemType != 2"
-            :src="require('../../assets/icon/course/task.png')"
+            v-if="itemType != 1"
+            :src="require('../../assets/icon/course/up.png')"
           />
-          <!-- <span :style="`background:url(${itemType==2?require('../../assets/icon/course/task_active.png'):require('../../assets/icon/course/task.png')});`"></span> -->
-          <div>任务</div>
+          <!-- <span :style="`background:url(${itemType==1?require('../../assets/icon/course/up_active.png'):require('../../assets/icon/course/up.png')});`"></span> -->
+          <div>对话</div>
         </div>
+
         <div
           :class="[
             'ch_nav_box_middle_item',
@@ -120,6 +173,19 @@
         </div>
       </div>
       <div class="ch_nav_box_bottom">
+
+				<div @click.stop="startAssistant()" :class="[recordType==1?'ch_nav_box_middle_item_active':'']">
+					<el-tooltip
+            class="item"
+            effect="dark"
+            :content="recordType==0?'开启语音助手':'关闭语音助手'"
+            placement="top"
+          >
+            <img v-if="recordType!=1" :src="require('../../assets/icon/course/robot.svg')" />
+						<img v-else :src="require('../../assets/icon/course/robot2.svg')" />
+          </el-tooltip>
+				</div>
+
         <div @click.stop="$emit('goStep', 0)">
           <el-tooltip
             class="item"
@@ -166,7 +232,7 @@ import dialogArea from "./component/dialogArea.vue";
 import levitatedSphere from "./component/levitatedSphere.vue";
 import timepiece from "./component/timepiece.vue";
 export default {
-  emits: ["refresh", "goStep", "backPage", "authority", "review"],
+  emits: ["refresh", "goStep", "backPage", "authority", "review","stopRecording","startRecording"],
   components: {
     searchArea,
     taskArea,
@@ -206,14 +272,21 @@ export default {
     fileList: {
       type: Array,
       default: () => []
-    }
+    },
+		videoStart:{
+			type:Boolean,
+			default:false,
+		},
   },
   data() {
     return {
       type: 0,
       itemType: 0, //0--无  1-搜索  2-任务 3-对话
       fileId: [],
-			recordType:0,
+      recordType: 0,
+			recordLoading:false,
+      fold: false,
+
       getFileIdLoading: false
     };
   },
@@ -254,12 +327,12 @@ export default {
     },
     getFileId() {
       if (this.getFileIdLoading) return;
-			this.getFileIdLoading = true;
+      this.getFileIdLoading = true;
       this.fileId = [];
-			let _this = this;
+      let _this = this;
       let _successFileUrl = [];
       if (this.fileList.length <= 0) retrun;
-      let addType = ["DOCX", "DOC", "PPT", "PPTX", "MD", "TXT","PDF"];
+      let addType = ["DOCX", "DOC", "PPT", "PPTX", "MD", "TXT", "PDF"];
       this.fileList.forEach(i => {
         if (
           addType.includes(
@@ -282,7 +355,7 @@ export default {
                 if (_data.result && _data.result.id) {
                   this.fileId.push(_data.result.id);
                 }
-								resolve();
+                resolve();
               });
           })
         );
@@ -291,18 +364,28 @@ export default {
         this.getFileIdLoading = false;
       });
     },
-		startAssistant(){
-			if(this.recordType==0){
-				this.$refs.levitatedSphereRef.recordStart();
-			}else if(this.recordType==1){
-				this.$refs.levitatedSphereRef.stopRecord();
-			}
-		},
-		changeRecordType(type){
-			console.log("修改了")
-			this.recordType = type;
-			console.log(this.recordType)
-		},
+    startAssistant() {
+			if(this.recordLoading)return this.$message.info("请稍等...")
+			this.recordLoading = true;
+      if (this.recordType == 0) {
+			this.$message.info("开启")
+				// this.changeRecordType(1)
+        this.$refs.levitatedSphereRef.recordStart();
+      } else if (this.recordType == 1) {
+				this.$message.info("关闭")
+				// this.changeRecordType(0)
+        this.$refs.levitatedSphereRef.stopRecord();
+      }
+    },
+    // 展开
+    changeFold(newValue) {
+      // this.$message.info("展开");
+			this.fold = newValue;
+    },
+    changeRecordType(type) {
+			this.recordLoading = false;
+      this.recordType = type;
+    }
   }
 };
 </script>
@@ -316,7 +399,6 @@ export default {
   border-radius: 10px;
   box-sizing: border-box;
   right: 20px;
-  /* overflow: hidden; */
   display: flex;
   top: 20px;
   z-index: 1000;
@@ -327,10 +409,10 @@ export default {
   width: 65px;
   display: flex;
   flex-direction: column;
-  /* justify-content: flex-end; */
-  margin-top: auto;
   align-items: center;
-  overflow: auto;
+  /* overflow-y: auto; */
+  overflow-x: visible; /* 确保横向溢出内容可见 */
+  position: relative;
 }
 
 .ch_content_box {
@@ -341,18 +423,14 @@ export default {
 
 .ch_nav_box_bottom {
   width: 100%;
-  height: auto;
   box-sizing: border-box;
   border-top: solid 1px #eaeaea;
   display: flex;
   flex-direction: column;
-  /* justify-content: flex-end; */
 }
 
 .ch_nav_box_middle {
   width: 100%;
-  height: auto;
-  display: flex;
   box-sizing: border-box;
   border-top: solid 1px #eaeaea;
   flex-direction: column;
@@ -371,10 +449,6 @@ export default {
   font-size: 14px;
 }
 
-/* .ch_nav_box_middle_item:hover{
-			background-color: rgb(195, 215, 247);
-		} */
-
 .ch_nav_box_middle_item_active {
   background-color: #3681fc;
   color: white;
@@ -386,14 +460,6 @@ export default {
   margin-bottom: 5px;
 }
 
-/* .ch_nav_box_middle_item>span{
-			width: 24px;
-			height: 24px;
-			background-size: 100% 100%;
-			background-repeat: no-repeat;
-			background-position: center;
-		} */
-
 .ch_nav_box_bottom > div {
   width: 100%;
   height: 65px;
@@ -403,6 +469,7 @@ export default {
   align-items: center;
   cursor: pointer;
 }
+
 .ch_nav_box_bottom > div > img {
   width: 24px;
   height: 24px;
@@ -410,9 +477,9 @@ export default {
 
 .ch_nav_box_top {
   width: 100%;
-  height: auto;
   margin-top: auto;
 }
+
 .ch_nav_box_top > div {
   width: 100%;
   height: 65px;
@@ -420,8 +487,38 @@ export default {
   justify-content: center;
   align-items: center;
   cursor: pointer;
+  position: relative;
 }
+
 .ch_nav_box_top > div > img {
+  width: 24px;
+  height: 24px;
+	transition: .3s;
+}
+
+.itemFold {
+  position: absolute;
+  width: 65px;
+	left:-65px;
+	top: 0;
+  background: rgb(255, 255, 255);
+  box-sizing: border-box;
+  border: solid 1px #eaeaea;
+	/* border-top: solid 1px #eaeaea; */
+  z-index: 1000; /* 确保二级菜单在主菜单上层 */
+	border-radius: 10px;
+}
+
+.itemFold > div {
+  width: 100%;
+  height: 65px;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  cursor: pointer;
+}
+
+.itemFold > div > img {
   width: 24px;
   height: 24px;
 }

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

@@ -8081,7 +8081,7 @@
       </div>
     </div>
 		<!-- v-show="org == '1973f6c7-1561-11ee-91d8-005056b86db5' || org == '777559d2-7239-11ee-b98c-005056b86db5' || org == '884c5665-a453-46f3-b7b6-01d575290aa9'" -->
-		<classRoomHelper :fileList="vChapterData[taskCount]" :worksStudent="worksStudent" :courseType="parseInt(courseType)" :taskCount="taskCount" :tcid="tcid" :navList="navList" v-show="orgArray.includes(org) || oidArray.includes(oid)" ref="classRoomHelperRef" :courseDetail="courseDetail" :tType="tType" @setWidth="setClassRoomHelperWidth" @refresh="refreshCourse" @goStep="nextOrpreSteps" @authority="juriVisible = true" @review="setPz" @backPage="goTo(
+		<classRoomHelper :videoStart="videoStart" @startRecording="startRecording" @stopRecording="stopRecording" :fileList="vChapterData[taskCount]" :worksStudent="worksStudent" :courseType="parseInt(courseType)" :taskCount="taskCount" :tcid="tcid" :navList="navList" v-show="orgArray.includes(org) || oidArray.includes(oid)" ref="classRoomHelperRef" :courseDetail="courseDetail" :tType="tType" @setWidth="setClassRoomHelperWidth" @refresh="refreshCourse" @goStep="nextOrpreSteps" @authority="juriVisible = true" @review="setPz" @backPage="goTo(
                     '/courseDetail?userid=' +
                       userid +
                       '&oid=' +

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

@@ -8111,7 +8111,7 @@
       </div>
     </div>
 				<!-- v-show="org == '1973f6c7-1561-11ee-91d8-005056b86db5' || org == '777559d2-7239-11ee-b98c-005056b86db5' || org == '884c5665-a453-46f3-b7b6-01d575290aa9'" -->
-		<classRoomHelper :fileList="vChapterData[taskCount]" :worksStudent="worksStudent" :courseType="parseInt(courseType)" :taskCount="taskCount" :tcid="tcid" :navList="navList" v-show="orgArray.includes(org) || oidArray.includes(oid)" ref="classRoomHelperRef" :courseDetail="courseDetail" :tType="tType" @setWidth="setClassRoomHelperWidth" @refresh="refreshCourse" @goStep="nextOrpreSteps" @authority="juriVisible = true" @review="setPz" @backPage="goTo(
+		<classRoomHelper :videoStart="videoStart" @startRecording="startRecording" @stopRecording="stopRecording" :fileList="vChapterData[taskCount]" :worksStudent="worksStudent" :courseType="parseInt(courseType)" :taskCount="taskCount" :tcid="tcid" :navList="navList" v-show="orgArray.includes(org) || oidArray.includes(oid)" ref="classRoomHelperRef" :courseDetail="courseDetail" :tType="tType" @setWidth="setClassRoomHelperWidth" @refresh="refreshCourse" @goStep="nextOrpreSteps" @authority="juriVisible = true" @review="setPz" @backPage="goTo(
                     '/courseDetail?userid=' +
                       userid +
                       '&oid=' +

+ 1 - 1
src/components/studyStudent.vue

@@ -8078,7 +8078,7 @@
         </el-dialog>
       </div>
 			<!-- v-show="org == '1973f6c7-1561-11ee-91d8-005056b86db5' || org == '777559d2-7239-11ee-b98c-005056b86db5' || org == '884c5665-a453-46f3-b7b6-01d575290aa9'" -->
-      <classRoomHelper :fileList="vChapterData[taskCount]" :worksStudent="worksStudent" :courseType="parseInt(courseType)" :taskCount="taskCount" :tcid="tcid" :navList="navList" v-show="orgArray.includes(org) || oidArray.includes(oid)"  ref="classRoomHelperRef" :courseDetail="courseDetail" :tType="tType" @setWidth="setClassRoomHelperWidth" @refresh="refreshCourse" @goStep="nextOrpreSteps" @authority="juriVisible = true" @review="setPz" @backPage="goTo(
+      <classRoomHelper :videoStart="videoStart" @startRecording="startRecording" @stopRecording="stopRecording" :fileList="vChapterData[taskCount]" :worksStudent="worksStudent" :courseType="parseInt(courseType)" :taskCount="taskCount" :tcid="tcid" :navList="navList" v-show="orgArray.includes(org) || oidArray.includes(oid)"  ref="classRoomHelperRef" :courseDetail="courseDetail" :tType="tType" @setWidth="setClassRoomHelperWidth" @refresh="refreshCourse" @goStep="nextOrpreSteps" @authority="juriVisible = true" @review="setPz" @backPage="goTo(
                     '/courseDetail?userid=' +
                       userid +
                       '&oid=' +