| 
					
				 | 
			
			
				@@ -9,12 +9,14 @@ import axios from "axios"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import { fetchEventSource } from "@microsoft/fetch-event-source"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import { useRoute, useRouter } from "vue-router"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import delay from "delay"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { fetchTaskStatus } from "./utils/api"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const route = useRoute(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const router = useRouter(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const conversationId = computed(() => route.query.taskId); // 会话ID 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const round = computed(() => route.query.round); // 轮次 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const sessionId = ref(""); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const taskStatus = ref(false) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const currentRate = ref(0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const currentRound = computed(() => { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -53,19 +55,10 @@ const updateChatList = async (message = "", loading = true) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       clearInterval(timer); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   }, 50); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // chatList.value = chatList.value.map((item) => 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  //   item.loading 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  //     ? message 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  //       ? { ...item, text: message, loading } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  //       : { ...item, loading } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  //     : item 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // localStorage.setItem("chatHistory", JSON.stringify(chatList.value)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 // 创建一个队列实例,设置并发数为 1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-const queue = new PQueue({ concurrency: 1 }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const queue = new PQueue({ concurrency: 4 }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const queue1 = new PQueue({ concurrency: 1 }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const queue2 = new PQueue({ concurrency: 1 }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -77,13 +70,13 @@ let lastStrIndex = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 // 将字符串根据标点符号断句分割,并添加到messageQueue中 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const splitMessage = async (str) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  const punctuation = ["。", "!", "?", ";", ":"]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const punctuation = ["。","," ,"!", "?", ";", ":"]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   for (let i = lastStrIndex; i < str.length; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (punctuation.includes(str[i])) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       const message = str.slice(lastStrIndex, i + 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       console.log(message, "=========="); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      await playTTS(message); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      playTTS(message); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       lastStrIndex = i + 1; // 更新上一个字符串的结束位置 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -125,114 +118,229 @@ const handleStopRecord = (message) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   sessionId.value = generateSessionId(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   chatGpt(message); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+let audioQueue = [];  // 音频队列,保存按请求顺序的音频数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+let playingQueue = []; // 用来记录当前正在播放的音频序号 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+let isPlaying = false;  // 当前是否正在播放 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+let orderId = 0;  // 请求顺序号 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 用来控制正在播放音频的锁定机制 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+let playingLock = false;  // 标识是否正在播放 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 1. 发起 TTS 请求 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// const playTTS = async (ttsMessage) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//   const currentOrderId = orderId++;  // 获取当前请求的顺序号 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//   try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//     // 发起请求 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//     const res = await axios.get( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//         `/openapi-prd/ai/ttt/synthesize?text=${ttsMessage}&sessionId=${sessionId.value}`, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//         { responseType: "arraybuffer" } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//     ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//     // 将音频数据和顺序号一起存入 audioQueue 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//     audioQueue.push({ orderId: currentOrderId, audioData: res.data }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//     // 如果当前没有音频在播放,开始播放 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//     if (!isPlaying && !playingLock) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//       await playNextAudio();  // 开始播放 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//   } catch (error) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//     console.error("调用 TTS API 时出错:", error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const playTTS = async (ttsMessage) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  queue.add(async () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const currentOrderId = orderId++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-const playTTS1 = async (ttsMessage) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    const res = await axios.post( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      `/openapi-stg/ai/voice/tts/v2`, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      { sessionId: "N7FB_G0WlrOLjc", text: ttsMessage }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        responseType: "arraybuffer", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        headers: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          "X-Ai-TTS-Appid": "2b1317fb5b284b308dc90a6fdeae6c4e", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const res = await axios.get( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        `/openapi-prd/ai/ttt/synthesize?text=${ttsMessage}&sessionId=${sessionId.value}`, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        { responseType: "arraybuffer" } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      // 按顺序存入音频队列 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      audioQueue.push({ orderId: currentOrderId, audioData: res.data }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      // 仅在没有播放时启动播放 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (!isPlaying) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        await playNextAudio(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    console.log(res.data); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } catch (error) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      console.error("调用 TTS API 时出错:", error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 2. 播放下一个音频 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const playNextAudio = async () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // 如果播放队列为空,停止播放 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (audioQueue.length === 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    isPlaying = false;  // 播放完所有音频 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    console.log("所有音频播放完毕."); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    queue1.add(async () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      // 播放获取到的音频 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      await playAudio(res.data); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } catch (error) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    console.error("Error calling TTS API:", error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // 找到队列中最小序号的音频,确保顺序播放 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const nextAudio = getNextAudioToPlay(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // 如果找不到下一个应该播放的音频,表示队列还没有按顺序准备好 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (!nextAudio) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    console.log("没有找到下一个应该播放的音频,队列尚未按顺序准备好."); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    console.log("当前音频队列:", audioQueue);  // 打印当前音频队列 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    console.log("当前已播放的序列:", playingQueue);  // 打印已经播放的音频序列 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-const playTTS = async (ttsMessage) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // 打印正在播放的音频序号 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  console.log(`正在播放音频,序号:${nextAudio.orderId}`); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    const res = await axios.get( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      `/openapi-prd/ai/ttt/synthesize?text=${ttsMessage}&sessionId=${sessionId.value}`, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        responseType: "arraybuffer", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    console.log(res.data); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    isPlaying = true;  // 标记当前正在播放 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    playingLock = true;  // 锁定播放,避免新的音频插入 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    queue1.add(async () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      // 播放获取到的音频 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      await playAudio(res.data); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } catch (error) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    console.error("Error calling TTS API:", error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 播放当前音频 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    await playAudio(nextAudio.audioData); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-const playAudio1 = (audioData, options = {}) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  return new Promise((resolve, reject) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    const blob = new Blob([audioData], { type: "audio/wav" }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    const url = URL.createObjectURL(blob); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    const audio = new Audio(url); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 播放完成后,移除已播放的音频 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    audioQueue = audioQueue.filter(audio => audio.orderId !== nextAudio.orderId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    playingQueue.push(nextAudio.orderId);  // 将已播放的序号添加到播放记录 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    audio.setAttribute("id", "audio"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    audio.setAttribute("autoplay", "autoplay"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 输出音频播放完成的日志 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    console.log(`音频序号 ${nextAudio.orderId} 播放完成,等待播放下一个包...`); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (options.volume) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      audio.volume = options.volume; // 设置音量 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 解除锁定,等待下一个音频播放 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    playingLock = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    audio.onended = () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      URL.revokeObjectURL(url); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      resolve(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 使用定时器周期性检查是否可以播放下一个音频 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const checkNextAudioTimer = setInterval(async () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (!playingLock) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        await playNextAudio(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        clearInterval(checkNextAudioTimer);  // 清除定时器 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 300); // 每秒检查一次 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } catch (error) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    console.error(`播放音频序号 ${nextAudio.orderId} 时出错:`, error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 如果某个音频播放失败,跳过这个音频,继续播放下一个 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    audioQueue = audioQueue.filter(audio => audio.orderId !== nextAudio.orderId);  // 移除报错的音频 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    playingQueue.push(nextAudio.orderId);  // 将已播放的序号添加到播放记录 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    playingLock = false;  // 解除锁定 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 继续播放下一个音频 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    await playNextAudio(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    audio.onerror = (error) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      URL.revokeObjectURL(url); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      reject(error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    audio 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      .play() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      .then(() => console.log("Audio playing")) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      .catch(reject); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 获取下一个应该播放的音频(保证顺序) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const getNextAudioToPlay = () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // 检查音频队列中是否有下一个应该播放的音频 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  console.log("检查下一个播放的音频..."); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  for (let i = 0; i < audioQueue.length; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const audio = audioQueue[i]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 找到最小的序号,即请求的顺序号 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (audio.orderId === playingQueue.length) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      console.log(`找到了下一个应该播放的音频,序号:${audio.orderId}`); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      return audio; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  console.log("没有找到下一个应该播放的音频,返回 null"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return null;  // 如果没有找到匹配的音频,返回 null 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-const playAudio = (audioData, options = {}) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 播放音频的方法 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const playAudio = (audioData) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return new Promise((resolve, reject) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    const audioContext = new (window.AudioContext || 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      window.webkitAudioContext)(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const audioContext = new (window.AudioContext || window.webkitAudioContext)(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     const blob = new Blob([audioData], { type: "audio/wav" }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     const url = URL.createObjectURL(blob); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     const audioBufferSourceNode = audioContext.createBufferSource(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     fetch(url) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      .then((response) => response.arrayBuffer()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      .then((arrayBuffer) => audioContext.decodeAudioData(arrayBuffer)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      .then((audioBuffer) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        audioBufferSourceNode.buffer = audioBuffer; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        audioBufferSourceNode.connect(audioContext.destination); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (options.volume) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          audioBufferSourceNode.gain.value = options.volume; // 设置音量 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        audioBufferSourceNode.start(0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        audioBufferSourceNode.onended = () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          URL.revokeObjectURL(url); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          resolve(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        audioBufferSourceNode.onerror = (error) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          URL.revokeObjectURL(url); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          reject(error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      }) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      .catch(reject); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        .then((response) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          if (!response.ok) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            console.error("音频文件请求失败: ", response.statusText); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            reject(new Error("音频文件请求失败")); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          return response.arrayBuffer(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        }) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        .then((arrayBuffer) => audioContext.decodeAudioData(arrayBuffer)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        .then((audioBuffer) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          audioBufferSourceNode.buffer = audioBuffer; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          audioBufferSourceNode.connect(audioContext.destination); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          audioBufferSourceNode.start(0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          // 当音频播放完毕时,调用 resolve 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          audioBufferSourceNode.onended = () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            URL.revokeObjectURL(url); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            resolve();  // 播放完成后,继续播放下一个 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          audioBufferSourceNode.onerror = (error) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            console.error("音频播放错误:", error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            URL.revokeObjectURL(url); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            reject(error);  // 播放失败时,返回错误 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        }) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        .catch((error) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          console.error("音频加载或解码时出错:", error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          reject(error);  // 如果解码或播放出错,reject 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// const playTTS1 = async (ttsMessage) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//   try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//     const res = await axios.post( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//       `/openapi-stg/ai/voice/tts/v2`, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//       { sessionId: "N7FB_G0WlrOLjc", text: ttsMessage }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//       { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//         responseType: "arraybuffer", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//         headers: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//           "X-Ai-TTS-Appid": "2b1317fb5b284b308dc90a6fdeae6c4e", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//         }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//     ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//     console.log(res.data); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//     queue1.add(async () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//       // 播放获取到的音频 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//       await playAudio(res.data); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//     }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//   } catch (error) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//     console.error("Error calling TTS API:", error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// const playAudio1 = (audioData, options = {}) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//   return new Promise((resolve, reject) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//     const blob = new Blob([audioData], { type: "audio/wav" }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//     const url = URL.createObjectURL(blob); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//     const audio = new Audio(url); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//     audio.setAttribute("id", "audio"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//     audio.setAttribute("autoplay", "autoplay"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//     if (options.volume) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//       audio.volume = options.volume; // 设置音量 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//     audio.onended = () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//       URL.revokeObjectURL(url); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//       resolve(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//     }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//     audio.onerror = (error) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//       URL.revokeObjectURL(url); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//       reject(error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//     }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//     audio 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//       .play() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//       .then(() => console.log("Audio playing")) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//       .catch(reject); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//   }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const chatGpt = async (userMessage) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   const downloadUrl = "/openapi-prd/ai/intelligent-tutoring/task/dialogue"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   i = 0; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -265,38 +373,17 @@ const chatGpt = async (userMessage) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             queue.add(async () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				               await splitMessage(responseText); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            // const timer = setInterval(() => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //   i = i + 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //   //updateChatList(responseText.substring(0, i)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //   queue2.add( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //     async () => await updateChatList(responseText.substring(0, i)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //   ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //   if (i >= responseText.length) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //     clearInterval(timer); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //   console.log( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //     i, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //     responseText.substring(i), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //     "=======responseText.substring(i)" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //   ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //   if ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //     responseText.substring(i).indexOf("[DONE]") === 0 || 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //     responseText.substring(i).indexOf("[DONE]") === 1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //   ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //     console.log("========done==========="); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //     updateChatList("", false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //     // 保存聊天记录到本地 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //     const chatHistory = JSON.stringify(chatList.value); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //     localStorage.setItem("chatHistory", chatHistory); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //}, 200); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             queue2.add(async () => await updateChatList(responseText)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             //updateChatList(responseText); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    setTimeout(() => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         handleTaskStatus() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     },3000) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     //queue2.add(async () => await updateChatList("", false)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } catch (error) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     //updateChatList("", false); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -380,23 +467,35 @@ const next = () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const loadChatHistory = () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   const chatHistory = localStorage.getItem("chatHistory"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const chatStatus = localStorage.getItem("status"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (chatHistory) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     const history = JSON.parse(chatHistory); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     history.forEach((item) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       chatList.value.push(item); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if(chatStatus){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    taskStatus.value = JSON.parse(chatStatus) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 查询任务结束状态 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const handleTaskStatus = async () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const res =  await fetchTaskStatus(conversationId.value) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if(res.code == 200){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    taskStatus.value = res.body 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    localStorage.setItem("status", res.body); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 // 在组件挂载时调用 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 onMounted(() => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   loadChatHistory(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// onBeforeUnmount(() => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//   localStorage.removeItem("chatHistory"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 </script> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 <template> 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -416,9 +515,9 @@ onMounted(() => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     <BottomArea 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       @startRecord="handleStartRecord" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       @stopRecord="handleStopRecord" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      v-show="rate < 100" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      v-show="rate < 100 || taskStatus" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    <div v-show="rate >= 100" class="next-btn"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    <div v-show="rate >= 100 || taskStatus" class="next-btn"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       <van-button style="width: 100%" @click="next" type="primary" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         >已完成对话,下一步</van-button 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       > 
			 |