liming 1 week ago
parent
commit
bff355ab48
1 changed files with 81 additions and 26 deletions
  1. 81 26
      src/views/im/chat/index.vue

+ 81 - 26
src/views/im/chat/index.vue

@@ -36,7 +36,7 @@
     <!-- 输入框 -->
     <div class="page-foot">
       <div class="flex-box">
-        <svg-icon class="page-icon" name="voice" @mousedown="startAudio" />
+        <svg-icon class="page-icon" name="voice" @mousedown="startAudio" @mouseup="sendAudioMessage" />
         <van-field
           rows="1"
           type="textarea"
@@ -101,7 +101,8 @@ const isMobile = Capacitor.getPlatform() !== "web";
 
 // 底部高度动态计算
 // 语音
-const mediaRecorder = ref(null); 
+const mediaRecorder = ref(null);  // 录音对象
+const audioChunks = ref([]) // 录音数据
 
 // 计算当前底部总高度
 const currentBottomHeight = computed(() => {
@@ -110,58 +111,112 @@ const currentBottomHeight = computed(() => {
   return 0;
 });
 
-// 输入框聚焦
+// 切换表情/工具面板
+const toggleAppBox = async (type) => {
+  if (isMobile) await Keyboard.hide();
+  keyboardHeight.value = 0;
+  if (type === 1) {
+    showEmoji.value = !showEmoji.value;
+    showTools.value = false;
+  } else {
+    showTools.value = !showTools.value;
+    showEmoji.value = false;
+  }
+};
+
 const onFocus = () => {
+  // 隐藏所有面板
   showEmoji.value = false;
   showTools.value = false;
-  if (isMobile) setupKeyboardListeners();
+  // 判断是不是web
+  if (Capacitor.getPlatform() != "web") {
+    setupKeyboardListeners();
+  }
 };
 
-// 监听键盘高度
-const setupKeyboardListeners = () => {
+// 键盘监听
+const setupKeyboardListeners = async () => {
   Keyboard.addListener("keyboardWillShow", (info) => {
     keyboardHeight.value = info.keyboardHeight;
   });
+
   Keyboard.addListener("keyboardWillHide", () => {
     keyboardHeight.value = 0;
   });
 };
 
-// 切换表情/工具面板
-const toggleAppBox = async (type) => {
-  if (isMobile) await Keyboard.hide();
-  keyboardHeight.value = 0;
-  if (type === 1) {
-    showEmoji.value = !showEmoji.value;
-    showTools.value = false;
-  } else {
-    showTools.value = !showTools.value;
-    showEmoji.value = false;
-  }
-};
+// 录音
 const startAudio = async () => {
     try {
     // 请求麦克风权限
     const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
-    
+
     // 创建 MediaRecorder 实例
-    mediaRecorder.value = new MediaRecorder(stream);
+    mediaRecorder.value = new MediaRecorder(stream, { mimeType: 'audio/webm; codecs=opus' });
     
     // 收集音频数据
     mediaRecorder.value.ondataavailable = (e) => {
-      audioChunks.push(e.data);
+      audioChunks.value.push(e.data);
     };
     
-    mediaRecorder.value.onerror = (e) => {
-      console.error('Recording error:', e.error);
-    };
-    
-    mediaRecorder.value.start();
+    mediaRecorder.value.start(1000); // 每1秒收集一次数据
     console.log('Recording started');
   } catch (error) {
     console.error('Error accessing microphone:', error);
   }
 }
+// 停止录音
+const stopRecording = async () => {
+  return new Promise<Uint8Array>(async (resolve) => {
+    if (!mediaRecorder.value) {
+      resolve(new Uint8Array());
+      return;
+    }
+    
+    // 停止录音
+    mediaRecorder.value.stop();
+    mediaRecorder.value.stream.getTracks().forEach(track => track.stop());
+    
+    // 等待最后的数据可用
+    mediaRecorder.value.onstop = async () => {
+      // 合并所有音频片段
+      const audioBlob = new Blob(audioChunks.value, { type: 'audio/webm' });
+      
+      // 转换为 Uint8Array
+      const arrayBuffer = await audioBlob.arrayBuffer();
+      const audioData = new Uint8Array(arrayBuffer);
+      
+      resolve(audioData);
+    };
+  });
+}
+
+const sendAudioMessage = async () => {
+  try {
+    // 1. 停止录音并获取音频数据
+    const audioData = await stopRecording();
+    
+    // 2. 准备消息体
+    const message = {
+      content: text.value, // 如果有文本内容
+      contentType: MSG_TYPE.AUDIO,  // 音频消息类型
+      messageType: MESSAGE_TYPE_USER, // 单聊消息
+      to: route.query.uuid, // 接收方ID
+      fileSuffix: "webm", // 使用webm后缀更准确
+      file: Array.from(audioData) // 将Uint8Array转为普通数组
+    };
+    
+    // 3. 通过WebSocket发送
+    wsStore.sendMessage(message);
+    
+    // 4. 重置状态
+    mediaRecorder.value = null;
+    audioChunks.value = [];
+    
+  } catch (error) {
+    console.error('Error sending audio message:', error);
+  }
+}
 // 发送消息
 const sendMessage = () => {
   if (!text.value.trim()) return;