SanHQin пре 11 месеци
родитељ
комит
b6f2d90cc0

+ 287 - 136
src/components/pages/classroomObservation/components/chatArea.vue

@@ -38,7 +38,7 @@
 			<tape
 				ref="tapeRef"
 				:aiNameList="roleList"
-				:chatData="[]"
+				:chatData="chatList"
 				v-show="pageStatus == 0 && !showIndexPage"
 			/>
 			<!-- <div class="t-t-m-Item" v-show="cardStatus==1"> -->
@@ -187,7 +187,7 @@
 							></textarea>
 						</div>
 						<div class="ca-b-o-m-right">
-							<span @click.stop="tapeSubmit()"></span>
+							<!-- <span @click.stop="tapeSubmit()"></span> -->
 							<!-- <div :class="sendBtnDsiable ? 'ca-b-o-m-r-dsiableBtn' : ''">
 								发送
 							</div> -->
@@ -206,10 +206,14 @@
 							v-if="showRoleList && choseRoleList.length != 0"
 						>
 							<div
-								:class="['ca_b_o_m_rl_item',roleListIndex==index?'ca_b_o_m_rl_itemActive':'']"
-								v-for="(item,index) in choseRoleList"
+								:class="[
+									'ca_b_o_m_rl_item',
+									roleListIndex == index ? 'ca_b_o_m_rl_itemActive' : '',
+								]"
+								v-for="(item, index) in choseRoleList"
 								:key="item.assistant_id"
 								@click="choseRole(item)"
+								@mouseover="() => (roleListIndex = index)"
 							>
 								<div class="ca_b-o_m_rl_i_top">
 									<el-avatar
@@ -295,6 +299,13 @@
 				</div>
 			</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>
 	</div>
 </template>
 
@@ -304,7 +315,7 @@ import transcription from "./transcription.vue";
 import tape from "./tape.vue";
 import { v4 as uuidv4 } from "uuid";
 import Recorder from "js-audio-recorder";
-// import MarkdownIt from "markdown-it";
+import MarkdownIt from "markdown-it";
 const lamejs = require("lamejs");
 
 const recorder = new Recorder({
@@ -379,7 +390,7 @@ export default {
 			textareaValue: "",
 			textareaLoading: false,
 			showRoleList: false,
-			roleListIndex:0,
+			roleListIndex: 0,
 			recordedForm: {
 				time: "00:00:00", //时间
 				status: 0, //0--未录音  1--正在录音  2--暂停  3--录音结束
@@ -424,52 +435,52 @@ export default {
 				},
 			],
 			transcriptionData: {
-				time: "2024-01-13 15:58:00",
-				content: `对爱整洁,有精神、不拖拉,多思考。老师你好,同学们好。
-请坐。前几天白老师关注到一则新闻,我们大鹏新区政府提出要将2024年作为旅游高质量发展年,为了吸引更多的游客来到咱们大鹏,你认为最重要的是什么来?第一小组。
-我认为最重要的是要先把环境、绿水青山环境弄好,这样才能吸引更多的人来,大鹏是的。
-大家同意他的想法吗?保护大棚环境人人有责,上周咱们班的两位环境调查员就去到葵冲进行了实地调查,我们来看看他们发现了什么。
-大家好,我们是人大附中深圳学校五1班的张龙溪,何瑞一为了响应区政府的号召,今天我们作为环境调查员,准备实地调查一下葵冲的环境情况,走跟随我们的镜头一起去看一看我们调查到的情况有什么样,这样的。
-应该是这样的,就是这样的,像这样的。
-像这种情况。
-像这种情况。
-像这样的。
-我们调查到的情况不是很好,同学们你们。
-谁知谁知。
-刚刚视频有一些小小的不同步,但不影响我们去观察里面的内容。
-好,来,同学们,通过刚才的视频,你看到了哪些环境问题?第五小组。
-我看到了菜市场上到处是垃圾,到处是那些烂掉的瓜果皮,是的。
-其他小组呢?来第八小组我。
-看我看到了路上还有很多漂移的垃圾就路上了。
-你观察得很认真,是的,在咱们生活的这片区域确实存在很多的垃圾问题,这些垃圾主要是家庭里面产生的生活垃圾。
-根据调查,一个家庭一天产生的垃圾大约是三千克,咱们班一共有45位同学,所有同学的家庭一天产生的生活垃圾总质量是多少?老师还调查到一些数据。我校小学部一共有1556人,整个大鹏新区共有55,224户家庭,整个深圳市有6,424,556户家庭,他们一天分别产生多少垃圾呢?现在请小组长从材料框当中拿出实验记录单,我们用计算器来速算一下,将结果记录下来。
-好,可以开始计算。二十五六场这样做的之前工作。
-还差一些,这样更准确一点。
-用计算器这样更准确算完了没有?
-你们。
-算完了吗老师?
-拍一下照片。
-大家算完了吗?
-好,算完的小组面向老师坐,好好表扬第八小组。好,第五、第四、第三。
-好,这是第四小组的数据,我们来看跟大家的一样吗?一样,在刚刚大家记录数据的时候,你发现了什么?在你刚刚写下这些数据,有什么发现?第三小组。
-我发现每天生产的垃圾会非常多。
-垃圾很多多,到什么程度?我们来看。多到全班同学一天产生的垃圾,相当于一头成年公羊这么重,多到全校小学部家庭的垃圾,一天有一头非洲大象这么重。大鹏新区所有家庭一天产生的垃圾量相当于32头,非洲大象这么重,整个深圳市一天产生的垃圾高达3800头,非洲大象这么重。
-老师看到很多同学发出来很惊讶的表情,整个深圳市就产生这么多的垃圾,整个广东省全国23个省加起来,放眼全球,全世界一年产生的垃圾是多少?我们来看这个统计图,把各个地区的垃圾量加起来,全球一年产生垃圾量高达20.17亿吨。这么多的垃圾如果填埋高度是一米的话,它可以埋掉三个深圳或者一个广州的面积。
-面对这组数据,你有什么样的感受跟大家分享一下。来,第一小组,垃圾好多。
-垃圾很多。
-其他小组有什么样的感受?第八小组。
-如果我们一直都以填埋的方式去处理垃圾的话,可能全球的土地都用于填埋垃圾了。
-你还告诉了大家处理垃圾的一种方式是的,这么多的垃圾如果没有得到及时的处理,他们会侵占大量的土地包围我们的城市家园,我们就会陷入到一种垃圾围城的现状,面对这么庞大的垃圾量,我们该怎么办?
-第七小组。
-我觉得我们可以按照垃圾的种类来进行分类,比如说回收垃圾,它可以是回收,然后再利用的或者就是有害垃圾,比如说电池会污染,将会人们将会对它处以专业的处理。
-你想到了垃圾分类,其他小组。
-第五小组。
-并且像很多我们要应该少用一次性的垃圾,比如说你买菜的时候要少用一次性的塑料袋,尽量用布袋,这样子的话可以节省既节省资源,又节省了垃圾的。
-生产量,你说的是一个非常实用的方法,大家刚刚都说出来了,实际的行动是的。今天就让我们一起行动起来,一起共同想办法来解决垃圾问题。
-面对垃圾问题。
-正如第八小组刚刚说的,咱们国家早期的处理方式是直接填埋和焚烧发电,这两种方法在一定程度上减少了垃圾,但也存在着很严重的弊端。现在我们就一起来说一说这两种方法的好处和弊端。第一小组。
-直接填埋这种方法会占用大量土地,而且还会污染土地,焚烧发电这种方法会会污_
-`,
+// 				time: "2024-01-13 15:58:00",
+// 				content: `对爱整洁,有精神、不拖拉,多思考。老师你好,同学们好。
+// 请坐。前几天白老师关注到一则新闻,我们大鹏新区政府提出要将2024年作为旅游高质量发展年,为了吸引更多的游客来到咱们大鹏,你认为最重要的是什么来?第一小组。
+// 我认为最重要的是要先把环境、绿水青山环境弄好,这样才能吸引更多的人来,大鹏是的。
+// 大家同意他的想法吗?保护大棚环境人人有责,上周咱们班的两位环境调查员就去到葵冲进行了实地调查,我们来看看他们发现了什么。
+// 大家好,我们是人大附中深圳学校五1班的张龙溪,何瑞一为了响应区政府的号召,今天我们作为环境调查员,准备实地调查一下葵冲的环境情况,走跟随我们的镜头一起去看一看我们调查到的情况有什么样,这样的。
+// 应该是这样的,就是这样的,像这样的。
+// 像这种情况。
+// 像这种情况。
+// 像这样的。
+// 我们调查到的情况不是很好,同学们你们。
+// 谁知谁知。
+// 刚刚视频有一些小小的不同步,但不影响我们去观察里面的内容。
+// 好,来,同学们,通过刚才的视频,你看到了哪些环境问题?第五小组。
+// 我看到了菜市场上到处是垃圾,到处是那些烂掉的瓜果皮,是的。
+// 其他小组呢?来第八小组我。
+// 看我看到了路上还有很多漂移的垃圾就路上了。
+// 你观察得很认真,是的,在咱们生活的这片区域确实存在很多的垃圾问题,这些垃圾主要是家庭里面产生的生活垃圾。
+// 根据调查,一个家庭一天产生的垃圾大约是三千克,咱们班一共有45位同学,所有同学的家庭一天产生的生活垃圾总质量是多少?老师还调查到一些数据。我校小学部一共有1556人,整个大鹏新区共有55,224户家庭,整个深圳市有6,424,556户家庭,他们一天分别产生多少垃圾呢?现在请小组长从材料框当中拿出实验记录单,我们用计算器来速算一下,将结果记录下来。
+// 好,可以开始计算。二十五六场这样做的之前工作。
+// 还差一些,这样更准确一点。
+// 用计算器这样更准确算完了没有?
+// 你们。
+// 算完了吗老师?
+// 拍一下照片。
+// 大家算完了吗?
+// 好,算完的小组面向老师坐,好好表扬第八小组。好,第五、第四、第三。
+// 好,这是第四小组的数据,我们来看跟大家的一样吗?一样,在刚刚大家记录数据的时候,你发现了什么?在你刚刚写下这些数据,有什么发现?第三小组。
+// 我发现每天生产的垃圾会非常多。
+// 垃圾很多多,到什么程度?我们来看。多到全班同学一天产生的垃圾,相当于一头成年公羊这么重,多到全校小学部家庭的垃圾,一天有一头非洲大象这么重。大鹏新区所有家庭一天产生的垃圾量相当于32头,非洲大象这么重,整个深圳市一天产生的垃圾高达3800头,非洲大象这么重。
+// 老师看到很多同学发出来很惊讶的表情,整个深圳市就产生这么多的垃圾,整个广东省全国23个省加起来,放眼全球,全世界一年产生的垃圾是多少?我们来看这个统计图,把各个地区的垃圾量加起来,全球一年产生垃圾量高达20.17亿吨。这么多的垃圾如果填埋高度是一米的话,它可以埋掉三个深圳或者一个广州的面积。
+// 面对这组数据,你有什么样的感受跟大家分享一下。来,第一小组,垃圾好多。
+// 垃圾很多。
+// 其他小组有什么样的感受?第八小组。
+// 如果我们一直都以填埋的方式去处理垃圾的话,可能全球的土地都用于填埋垃圾了。
+// 你还告诉了大家处理垃圾的一种方式是的,这么多的垃圾如果没有得到及时的处理,他们会侵占大量的土地包围我们的城市家园,我们就会陷入到一种垃圾围城的现状,面对这么庞大的垃圾量,我们该怎么办?
+// 第七小组。
+// 我觉得我们可以按照垃圾的种类来进行分类,比如说回收垃圾,它可以是回收,然后再利用的或者就是有害垃圾,比如说电池会污染,将会人们将会对它处以专业的处理。
+// 你想到了垃圾分类,其他小组。
+// 第五小组。
+// 并且像很多我们要应该少用一次性的垃圾,比如说你买菜的时候要少用一次性的塑料袋,尽量用布袋,这样子的话可以节省既节省资源,又节省了垃圾的。
+// 生产量,你说的是一个非常实用的方法,大家刚刚都说出来了,实际的行动是的。今天就让我们一起行动起来,一起共同想办法来解决垃圾问题。
+// 面对垃圾问题。
+// 正如第八小组刚刚说的,咱们国家早期的处理方式是直接填埋和焚烧发电,这两种方法在一定程度上减少了垃圾,但也存在着很严重的弊端。现在我们就一起来说一说这两种方法的好处和弊端。第一小组。
+// 直接填埋这种方法会占用大量土地,而且还会污染土地,焚烧发电这种方法会会污_
+// `,
 			},
 			chatList: [],
 		};
@@ -488,10 +499,10 @@ export default {
 			return result;
 		},
 	},
-	watch:{
-		choseRoleList(){
+	watch: {
+		choseRoleList() {
 			this.roleListIndex = 0;
-		}
+		},
 	},
 	methods: {
 		handleBlur(event) {
@@ -502,11 +513,14 @@ export default {
 		uploadRecording() {
 			let input = document.createElement("input");
 			input.type = "file";
-			input.accept = "audio/*, .txt, .pdf, .xlsx";
+			input.accept = ".wav";
+			// input.accept = "audio/*, .txt, .pdf, .xlsx";
 			input.click();
 			input.onchange = () => {
 				this.loading = true;
 				let file = input.files[0];
+				this.uploadWavFileAndGetText(file)
+				return;
 				var credentials = {
 					accessKeyId: "AKIATLPEDU37QV5CHLMH",
 					secretAccessKey: "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",
@@ -688,18 +702,23 @@ export default {
 			this.continuousDialogue = newValue;
 		},
 		// 点击发送旁的录音
-		tapeSubmit() {
-			// this.$message.info("发送旁的录音");
-			// this.mainBtnStatus = 0;
-			// this.pageStatus = 1;
-			// this.TapeNum = 0;
-		},
+		// tapeSubmit() {
+		// this.$message.info("发送旁的录音");
+		// this.mainBtnStatus = 0;
+		// this.pageStatus = 1;
+		// this.TapeNum = 0;
+		// },
 		async finishRecorded() {
 			this.loading = true;
 			recorder.stop();
 			this.$message.success("已结束录音");
 
+			
 			let file = this.convertToMp3(recorder.getWAV());
+			const mp3Blob = recorder.getWAVBlob();
+			let audioFile = this.dataURLtoAudio(mp3Blob, "wav");
+			this.uploadWavFileAndGetText(audioFile)
+			return;
 			file.lastModifiedDate = new Date();
 			file.name = "recordedFile.mp3";
 			var credentials = {
@@ -831,24 +850,91 @@ export default {
 		},
 		// 发送消息
 		send(_text = this.textareaValue) {
+			this.textareaValue = "";
+			// 判断输入的文本是否为空
+			if (!_text.trim()) return;
 			// 这里处理@的角色
-			return;
 			let _atRoleList = [];
-			let _roleList = [...this.roleList,...this.publicRoleList];
-			_roleList.forEach((i)=>{
-				if(_text.indexOf(`@${i.assistantName}`)!=-1){
-					_atRoleList.push(i)
+			let _roleList = [...this.roleList, ...this.publicRoleList];
+			_roleList.forEach((i) => {
+				if (_text.indexOf(`@${i.assistantName}`) != -1) {
+					_atRoleList.push(i);
 				}
-			})
+			});
 			if (_atRoleList.length > 0) {
-				let _oldText = _text;
-				_atRoleList.forEach(i=>_oldText = _text.replace(`@${i.assistantName}`,``))
-				console.log(_text);
-				console.log(_oldText)
 				//有@角色
-				console.log(_atRoleList);
+				let _replaceText = _text;
+				let _htmlText = _text;
+				_atRoleList.forEach((_i) => {
+					_replaceText = _replaceText.replaceAll(`@${_i.assistantName}`, ``);
+					_htmlText = _htmlText.replaceAll(
+						`@${_i.assistantName}`,
+						`<span class='aite-name'>@${_i.assistantName}</span>`
+					);
+				});
+				_atRoleList.forEach((_item, _index) => {
+					const _uid = uuidv4();
+					if (_index == 0) {
+						this.chatList.push({
+							loading: true,
+							role: "user",
+							content: _htmlText,
+							uid: _uid,
+							AI: "AI",
+							aiContent: "",
+							oldContent: "",
+							isShowSynchronization: false,
+							filename: _item.file_names,
+							index: this.chatList.length,
+							is_mind_map: false,
+							fileid: _item.assistantName,
+						});
+					} else {
+						this.chatList.push({
+							loading: true,
+							role: "user",
+							content: "",
+							uid: _uid,
+							AI: "AI",
+							aiContent: "",
+							oldContent: "",
+							isShowSynchronization: false,
+							filename: _item.file_names,
+							index: this.chatList.length,
+							is_mind_map: false,
+							fileid: _item.assistantName,
+						});
+					}
+					this.scrollBottom();
+					let params = {
+						assistant_id: _item.assistant_id,
+						userId: "602def61-005d-11ee-91d8-005056b86db5",
+						message: _replaceText,
+						session_name: "",
+						uid: _uid,
+						file_ids: this.fileId ? [this.fileId] : [],
+					};
+					this.ajax
+						.post("https://gpt4.cocorobo.cn/ai_agent_park_chat_new", params)
+						.then((res) => {
+							if (res.data.FunctionResponse.result == "发送成功") {
+							} else {
+								this.$message.warning(response.data.FunctionResponse.result);
+							}
+						})
+						.catch((err) => {
+							console.log(err);
+						});
+					this.getAtAuContent(
+						_uid,
+						_htmlText,
+						_item.headUrl,
+						_item.assistantName
+					);
+				});
 			} else {
 				//未@角色
+
 				let _uuid = uuidv4();
 				this.chatList.push({
 					role: "user",
@@ -863,78 +949,120 @@ export default {
 					is_mind_map: false,
 					loading: true,
 				});
-				this.textareaValue = "";
 				this.scrollBottom();
 				// 连续对话设置
 				let _historyMessage = [];
 				// this.chatList.forEach(i=>{
 
 				// })
-				_historyMessage.push({role:'user',content:_text})
+				_historyMessage.push({ role: "user", content: _text });
 				let params = JSON.stringify({
-          model: 'gpt-3.5-turbo',
-          temperature: 0,
-          max_tokens: 4096,
-          top_p: 1,
-          frequency_penalty: 0,
-          presence_penalty: 0,
-          messages: _historyMessage,
-          uid: _uuid,
-          mind_map_question: '',
-        });
-				this.ajax.post("https://gpt4.cocorobo.cn/chat",params).then(res=>{
-					if(res.data.FunctionResponse.result == '发送成功'){
-						this.getAiContent(_uuid);
-					}else{
-						this.$message.warning(response.data.FunctionResponse.result)
-					}
-				}).catch(e=>{
-					console.log(e)
-				})
-				
-				
+					model: "gpt-3.5-turbo",
+					temperature: 0,
+					max_tokens: 4096,
+					top_p: 1,
+					frequency_penalty: 0,
+					presence_penalty: 0,
+					messages: _historyMessage,
+					uid: _uuid,
+					mind_map_question: "",
+				});
+				this.ajax
+					.post("https://gpt4.cocorobo.cn/chat", params)
+					.then((res) => {
+						if (res.data.FunctionResponse.result == "发送成功") {
+						} else {
+							this.$message.warning(response.data.FunctionResponse.result);
+						}
+					})
+					.catch((e) => {
+						console.log(e);
+					});
+				this.getAiContent(_uuid);
 			}
 		},
-		getAiContent(_uid){
-			let _source = new EventSource(`https://gpt4.cocorobo.cn/stream/${_uid}`);
+		getAiContent(_uid) {
+			let _source = new EventSource(`https://gpt4.cocorobo.cn/stream/${_uid}`); //http://gpt4.cocorobo.cn:8011/stream/     https://gpt4.cocorobo.cn/stream/
 			let _allText = "";
 			let _mdText = "";
-			// const md = new MarkdownIt()
-			_source.onmessage = (_e) =>{
-				this.chatList.find(i=>i.uid==_uid).loading = false;
-				if(_e.data.replace("'", '').replace("'", '') == '[DONE]'){//对话已经完成
-					_mdText = _mdText.replace("_",'');
+			const md = new MarkdownIt();
+			_source.onmessage = (_e) => {
+				if (_e.data.replace("'", "").replace("'", "") == "[DONE]") {
+					//对话已经完成
+					_mdText = _mdText.replace("_", "");
 					_source.close();
-					this.chatList.find(i=>i.uid==_uid).aiContent = _mdText;
-					this.chatList.find(i=>i.uid==_uid).isalltext = true;
-					this.chatList.find(i=>i.uid==_uid).isShowSynchronization = true;
+					this.chatList.find((i) => i.uid == _uid).aiContent = _mdText;
+					this.chatList.find((i) => i.uid == _uid).isalltext = true;
+					this.chatList.find((i) => i.uid == _uid).isShowSynchronization = true;
+					this.chatList.find((i) => i.uid == _uid).loading = false;
 					// 保存对话👇 #TODO保存对话
 
-
 					return;
-				}else{//对话还在继续
-					let _text = ""
-					_text = _e.data.replaceAll("'", '');
-					if(_allText==""){
-						_allText = _text.replace(/^\n+/,'');//去掉回复消息中偶尔开头就存在的连续换行符
-					}else{
-						_allText +=_text;
+				} else {
+					//对话还在继续
+					let _text = "";
+					_text = _e.data.replaceAll("'", "");
+					if (_allText == "") {
+						_allText = _text.replace(/^\n+/, ""); //去掉回复消息中偶尔开头就存在的连续换行符
+					} else {
+						_allText += _text;
 					}
 					_mdText = _allText + "_";
-					_mdText = _mdText.replace(/\\n/g,'\n');
-					_mdText = _mdText.replace(/\\/g,'');
-					if(_allText.split('```').length % 2 == 0)_mdText +='\n```\n';
+					_mdText = _mdText.replace(/\\n/g, "\n");
+					_mdText = _mdText.replace(/\\/g, "");
+					if (_allText.split("```").length % 2 == 0) _mdText += "\n```\n";
 					//转化返回的回复流数据
 					_mdText = md.render(_mdText);
-					this.chatList.find(i=>i.uid==_uid).aiContent = _mdText;
+					this.chatList.find((i) => i.uid == _uid).aiContent = _mdText;
+					this.chatList.find((i) => i.uid == _uid).loading = false;
 					this.scrollBottom();
 					// 处理流数据
-
 				}
-			}
+			};
 		},
-		getAtAuContent(_uid,_text,_headUrl,_assistantName){
-			console.log(_uid,_text,_headUrl,_assistantName)
+		getAtAuContent(_uid, _text, _headUrl, _assistantName) {
+			let _source = new EventSource(
+				`https://gpt4.cocorobo.cn/question/${_uid}`
+			); //http://gpt4.cocorobo.cn:8011/question/   https://gpt4.cocorobo.cn/question/
+			let _allText = "";
+			let _mdText = "";
+			const md = new MarkdownIt();
+			_source.onmessage = (_e) => {
+				let _eData = JSON.parse(_e.data);
+				if (_eData.content.replace("'", "").replace("'", "") == "[DONE]") {
+					let _result = [];
+					if ("result" in _eData) {
+						_result = _eData.result;
+						for (let i = 0; i < _result.length; i++) {
+							_mdText = _mdText.replace(_result[i].text, _result[i].fileName);
+						}
+					}
+					_mdText = _mdText.replace("_", "");
+					this.chatList.find((i) => i.uid == _uid).aiContent = _mdText;
+					this.chatList.find((i) => i.uid == _uid).isalltext = true;
+					this.chatList.find((i) => i.uid == _uid).isShowSynchronization = true;
+					this.chatList.find((i) => i.uid == _uid).loading = false;
+					this.scrollBottom();
+					//#TODO 这里保存对话
+				} else {
+					let _text = _eData.content.replace("'", "").replace("'", "");
+					if (_allText == "") {
+						_allText = _text.replace(/^\n+/, ""); //去掉回复消息中偶尔开头就存在的连续换行符
+					} else {
+						_allText += _text;
+					}
+					_mdText = _allText + "_";
+					_mdText = _mdText.replace(/\\n/g, "\n");
+					_mdText = _mdText.replace(/\\/g, "");
+					if (_allText.split("```").length % 2 == 0) _mdText += "\n```\n";
+					//转化返回的回复流数据
+					_mdText = md.render(_mdText);
+					this.chatList.find((i) => i.uid == _uid).aiContent = _mdText;
+					this.chatList.find((i) => i.uid == _uid).loading = false;
+					this.scrollBottom();
+					// 处理流数据
+				}
+			};
 		},
 		textareaChange() {
 			if (this.textareaValue.at(-1) == "@") {
@@ -1003,6 +1131,23 @@ export default {
 			}
 			return new Blob(buffer, { type: "audio/mp3" });
 		},
+		uploadWavFileAndGetText(audioFile) {
+			let iiframe = this.$refs["iiframe"];
+			let _this = this;
+			iiframe.contentWindow.onRecognizedResult = function (e) {
+				console.log("onRecognizedResult", e);
+				let privText = e.privText;
+				console.log(privText)
+				_this.transcriptionData.content = privText;
+			};
+			iiframe.contentWindow.doContinuousPronunciationAssessment("", {
+				files: [audioFile],
+			});
+		},
+		// 录音转wav
+		dataURLtoAudio(blob, filename) {
+      return new File([blob], filename, { type: "audio/wav" });
+    },
 		getRoleList() {
 			this.roleList = [];
 			let params = {
@@ -1046,25 +1191,30 @@ export default {
 		// 选择了@的角色
 		choseRole(_data) {
 			let _lastAtIndex = this.textareaValue.lastIndexOf("@");
-			this.textareaValue = `${this.textareaValue.slice(0,_lastAtIndex)}@${_data.assistantName} `
+			this.textareaValue = `${this.textareaValue.slice(0, _lastAtIndex)}@${
+				_data.assistantName
+			} `;
 			this.$refs.textareaRef.focus();
 			this.showRoleList = false;
 		},
 		// 输入框键盘按下监听
-		textareaKeydown(_e){
-			if(this.showRoleList && this.choseRoleList.length>0){
-				switch(_e.keyCode){
-					case 38://小键盘上
+		textareaKeydown(_e) {
+			if (this.showRoleList && this.choseRoleList.length > 0) {
+				switch (_e.keyCode) {
+					case 38: //小键盘上
 						_e.preventDefault();
-						if(this.roleListIndex==0)return;
+						if (this.roleListIndex == 0) return;
 						this.roleListIndex--;
+						// 修改滚动条高度
+						this.$refs.roleListRef.scrollTop = this.roleListIndex * 105;
 						break;
-					case 40://小键盘下
+					case 40: //小键盘下
 						_e.preventDefault();
-						if(this.roleListIndex==this.choseRoleList.length-1)return;
+						if (this.roleListIndex == this.choseRoleList.length - 1) return;
 						this.roleListIndex++;
+						this.$refs.roleListRef.scrollTop = this.roleListIndex * 105;
 						break;
-					case 13://回车
+					case 13: //回车
 						_e.preventDefault();
 						this.choseRole(this.choseRoleList[this.roleListIndex]);
 						break;
@@ -1075,9 +1225,14 @@ export default {
 			this.getRoleList();
 			this.getPublicRoleList();
 		},
+		//保存消息
+		insertChat(answer, problem, type, alltext, assistant_id, headUrl, file_id) {
+			let params = {};
+		},
 	},
 	mounted() {
 		this.getData();
+		this.scrollBottom();
 	},
 };
 </script>
@@ -1548,11 +1703,7 @@ export default {
 	padding: 10px;
 }
 
-.ca_b_o_m_rl_item:hover {
-	background-color: #c3ddfa;
-}
-
-.ca_b_o_m_rl_itemActive{
+.ca_b_o_m_rl_itemActive {
 	background-color: #c3ddfa;
 }
 

+ 44 - 39
src/components/pages/classroomObservation/components/tape.vue

@@ -42,43 +42,51 @@
 			</div> -->
 		<!-- </div> -->
 		<div class="t-chartArea" ref="chartAreaRef">
-			<div class="t_ca_box" v-for="(item, index) in chatData" :key="index">
-				<div class="t_ca_b_roleAi" v-if="item.role == 'ai'">
-					<div class="t_ca_b_ai_avatar">
-						<el-avatar
-							size="medium"
-							:src="
-								require('../../../../assets/icon/classroomObservation/ai.png')
-							"
-						></el-avatar>
-					</div>
-					<div class="t_ca_b_ai_content">
-						<div class="t_ca_b_ai_c_name">{{ item.name }}</div>
-						<div class="t_ca_b_ai_c_main">
-							<div class="t_ca_b_ai_c_m_left">{{ item.content }}</div>
-							<div class="t_ca_b_ai_c_m_right">
-								<img
+			<div class="t_ca_box" v-for="(item, index) in chatData" :key="item.uid">
+			
+				<div class="t_ca_b_roleUser" v-if="item.content">
+					<div class="t_ca_b_u_content">
+						<div class="t_ca_b_u_c_main">
+							<div class="t_ca_b_u_c_m_left">
+								<!-- <img
 									:src="
 										require('../../../../assets/icon/classroomObservation/addWork.png')
 									"
 									@click="addWork()"
-								/>
-								<img
+								/> -->
+								<!-- <img
 									:src="
 										require('../../../../assets/icon/classroomObservation/copy.png')
 									"
 									@click="copyContent(item.content)"
-								/>
+								/> -->
 							</div>
+							<div class="t_ca_b_u_c_m_right" v-html="item.content"></div>
 						</div>
-						<div class="t_ca_b_ai_c_time">{{ item.create_at }}</div>
+						<div class="t_ca_b_u_c_time">{{ item.createtime }}</div>
+					</div>
+					<div class="t_ca_b_u_avatar">
+						<el-avatar
+							size="medium"
+							:src="
+								require('../../../../assets/icon/classroomObservation/userAvatar.png')
+							"
+						></el-avatar>
 					</div>
 				</div>
+				<div class="t_ca_b_roleAi">
+					<div class="t_ca_b_ai_avatar">
+						<el-avatar
+							size="medium"
+							:src="item.filename?item.filename:require('../../../../assets/icon/classroomObservation/ai.png')"
 
-				<div class="t_ca_b_roleUser" v-if="item.role == 'user'">
-					<div class="t_ca_b_u_content">
-						<div class="t_ca_b_u_c_main">
-							<div class="t_ca_b_u_c_m_left">
+						></el-avatar>
+					</div>
+					<div class="t_ca_b_ai_content">
+						<div class="t_ca_b_ai_c_name">{{ item.fileid }}</div>
+						<div class="t_ca_b_ai_c_main">
+							<div class="t_ca_b_ai_c_m_left" v-loading="item.loading" v-html="item.aiContent"></div>
+							<div class="t_ca_b_ai_c_m_right">
 								<img
 									:src="
 										require('../../../../assets/icon/classroomObservation/addWork.png')
@@ -89,20 +97,11 @@
 									:src="
 										require('../../../../assets/icon/classroomObservation/copy.png')
 									"
-									@click="copyContent(item.content)"
+									@click="copyContent(item.aiContent)"
 								/>
 							</div>
-							<div class="t_ca_b_u_c_m_right" v-html="item.content"></div>
 						</div>
-						<div class="t_ca_b_u_c_time">{{ item.create_at }}</div>
-					</div>
-					<div class="t_ca_b_u_avatar">
-						<el-avatar
-							size="medium"
-							:src="
-								require('../../../../assets/icon/classroomObservation/userAvatar.png')
-							"
-						></el-avatar>
+						<div class="t_ca_b_ai_c_time">{{ item.createtime }}</div>
 					</div>
 				</div>
 			</div>
@@ -422,16 +421,17 @@ export default {
 }
 
 .t_ca_b_ai_c_m_left {
-	max-width: calc(100% - 60px);
+	min-width: 50px;
 	height: auto;
 	padding: 12px;
 	display: block;
 	border-radius: 2px 8px 8px 8px;
 	box-shadow: 0 4px 10px 0 #1d388354;
 	margin-top: 10px;
-	white-space: pre-line;
+	/* white-space: pre-line; */
 	word-break: break-all;
 	background-color: white;
+	overflow: hidden;
 }
 
 .t_ca_b_ai_c_m_right {
@@ -499,7 +499,6 @@ export default {
 	justify-content: flex-end;
 }
 .t_ca_b_u_c_m_right {
-	max-width: calc(100% - 60px);
 	height: auto;
 	padding: 12px;
 	display: block;
@@ -519,11 +518,17 @@ export default {
 	margin-top: 10px;
 	text-align: right;
 }
-.t_ca_b_u_c_m_right>>>.atName{
+.t_ca_b_u_c_m_right>>>.aite-name{
+	display: inline;
 	background-color: #063a708c;
 	border-radius: 5px;
 	box-sizing: border-box;
 	padding: 2px 5px;
 	color: white;
+	margin-right: 5px;
+}
+
+.t_ca_b_ai_c_m_left>>>ol{
+	margin-left: 15px;
 }
 </style>

+ 3 - 3
src/components/pages/classroomObservation/components/transcription.vue

@@ -5,13 +5,13 @@
 			<div class="t-h-time">{{ data.time }}</div>
 		</div> -->
 		<div class="t-content">
-			<!-- {{ data.content }} -->
-			<div class="contentCon" v-for="(i, index) in chatList" :key="index">
+			{{ data.content }}
+			<!-- <div class="contentCon" v-for="(i, index) in chatList" :key="index">
 				<div class="conTim">{{ i.timer }}</div>
 				<div class="conTxt">
 					{{ i.con }}
 				</div>
-			</div>
+			</div> -->
 		</div>
 	</div>
 </template>