wkw 4 dagar sedan
förälder
incheckning
8160876834
2 ändrade filer med 162 tillägg och 30 borttagningar
  1. 43 11
      src/views/im/chat/index.vue
  2. 119 19
      src/views/im/components/CallController/index.vue

+ 43 - 11
src/views/im/chat/index.vue

@@ -154,7 +154,7 @@
           <div>拍摄</div>
         </div>
         <div class="tool-btn">
-          <svg-icon class="tool-icon" name="yyth" @click="startVoiceCall"/>
+          <svg-icon class="tool-icon" name="yyth" @click="startAudioOnline"/>
           <div>语音通话</div>
         </div>
         <div class="tool-btn">
@@ -167,19 +167,27 @@
         </div>
       </div>
     </div>
-
+    <CallController
+      :visible="rtcStore.imSate.videoCallModal || inCall"
+      :inCall="inCall"
+      :callName="rtcStore.imSate.callName"
+      :callAvatar="rtcStore.imSate.callAvatar"
+      @accept="acceptCall"
+      @reject="rejectCall"
+      @hangup="hangupCall"
+    ></CallController>
     <!-- 来电弹窗 -->
-    <div v-if="rtcStore.imSate.videoCallModal && !inCall" class="call-modal">
+    <!-- <div v-if="rtcStore.imSate.videoCallModal && !inCall" class="call-modal">
       <p>{{ rtcStore.imSate.callName }} 正在呼叫你</p>
       <button @click="acceptCall">接听</button>
       <button @click="rejectCall">拒接</button>
-    </div>
+    </div> -->
 
     <!-- 通话中显示挂断按钮 -->
-    <div v-if="inCall" class="call-modal">
+    <!-- <div v-if="inCall" class="call-modal">
       <p>与 {{ rtcStore.imSate.callName }} 通话中...</p>
       <button @click="hangupCall">挂断</button>
-    </div>
+    </div> -->
   </div>
 </template>
 
@@ -443,7 +451,29 @@ const startAudioOnline = async () => {
   });
 };
 // ==== 2. 接听来电 ====
-async function acceptCall() {}
+async function acceptCall() {
+  try {
+    // 标记为通话中状态
+    inCall.value = true;
+
+    // 发送接听消息给对方
+    wsStore.sendMessage({
+      messageType: MESSAGE_TYPE_USER, // 单聊消息
+      contentType: Constant.ACCEPT_AUDIO_ONLINE, // 接听语音通话的消息类型
+      type: Constant.MESSAGE_TRANS_TYPE, // webrtc类型
+    });
+
+    // 这里你可以加上开启 WebRTC 连接或媒体流处理逻辑
+    // 例如调用 rtcStore 的方法,启动本地音频/视频流
+    // await rtcStore.startLocalAudio();
+
+  } catch (error) {
+    console.error("接听失败", error);
+    // 如果接听失败,考虑重置状态或提示用户
+    inCall.value = false;
+  }
+}
+
 
 // ==== 3. 拒接来电 ====
 function rejectCall() {
@@ -452,17 +482,19 @@ function rejectCall() {
     contentType: Constant.REJECT_AUDIO_ONLINE,
     type: Constant.MESSAGE_TRANS_TYPE,
   });
+  // 隐藏弹窗
+  rtcStore.imSate.videoCallModal = false;
+  inCall.value = false;
 }
 
 // ==== 4. 挂断通话 ====
 function hangupCall() {
   rtcStore.cleanup();
+  // 隐藏弹窗
+  rtcStore.imSate.videoCallModal = false;
+  inCall.value = false;
 }
 
-// ==== 5. 监听信令消息 ====
-// 建议你在 useWebSocketStore 里实现 onMessage 订阅信令消息
-// 这里模拟简易监听,示范关键流程
-
 // 时间格式化
 const formatTime = (timestamp) => {
   const date = new Date(timestamp);

+ 119 - 19
src/views/im/components/CallController/index.vue

@@ -1,28 +1,128 @@
 <template>
-    <div v-if="rtcStore.callStatus === 'incoming'" class="call-box">
-      <div>{{ rtcStore.imSate.callName }} 呼叫你</div>
-      <button @click="accept">接听</button>
-      <button @click="reject">拒接</button>
-    </div>
-  
-    <div v-if="rtcStore.callStatus === 'dialing'">
-      正在呼叫 {{ rtcStore.callTarget?.name || '对方' }}...
-      <button @click="cancel">取消</button>
-    </div>
+    <div v-if="visible" class="weixin-call-modal">
+      <div class="caller-info">
+        <img class="avatar" :src="callAvatar || defaultAvatar" alt="头像" />
+        <div class="name">{{ callName || '未知用户' }}</div>
+        <div class="status">{{ statusText }}</div>
+      </div>
+      <div class="btn-group">
+        <!-- 来电状态显示接听/拒绝按钮 -->
+        <template v-if="!inCall">
+          <button class="btn reject" @click="$emit('reject')">拒绝</button>
+          <button class="btn accept" @click="$emit('accept')">接听</button>
+        </template>
   
-    <div v-if="rtcStore.callStatus === 'in-call'">
-      通话中...
-      <button @click="hangup">挂断</button>
+        <!-- 通话中状态显示挂断按钮 -->
+        <template v-else>
+          <button class="btn hangup" @click="$emit('hangup')">挂断</button>
+        </template>
+      </div>
     </div>
   </template>
   
   <script setup>
-  import { useWebRTCStore } from "@/stores/modules/webrtcStore";
-  const rtcStore = useWebRTCStore();
+  import { defineProps, computed } from "vue";
+  
+  const props = defineProps({
+    visible: Boolean,           // 是否显示弹窗
+    inCall: Boolean,            // 是否通话中
+    callName: String,           // 来电人姓名
+    callAvatar: String,         // 来电人头像
+  });
+  
+  const defaultAvatar = "https://example.com/default-avatar.png";
   
-  const accept = () => rtcStore.acceptCall(false);
-  const reject = () => rtcStore.rejectCall(false);
-  const cancel = () => rtcStore.cancelCall(false);
-  const hangup = () => rtcStore.hangup();
+  const statusText = computed(() => {
+    if (!props.inCall) {
+      return "正在语音通话请求...";
+    } else {
+      return "通话中...";
+    }
+  });
   </script>
+  
+  <style scoped>
+  .weixin-call-modal {
+    position: fixed;
+    inset: 0;
+    background-color: rgba(0, 0, 0, 0.85);
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    z-index: 9999;
+    color: white;
+  }
+  
+  .caller-info {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    margin-bottom: 80px;
+  }
+  
+  .avatar {
+    width: 80px;
+    height: 80px;
+    border-radius: 50%;
+    margin-bottom: 16px;
+    border: 2px solid rgba(255, 255, 255, 0.2);
+  }
+  
+  .name {
+    font-size: 20px;
+    font-weight: bold;
+    margin-bottom: 8px;
+  }
+  
+  .status {
+    font-size: 14px;
+    color: #ccc;
+  }
+  
+  .btn-group {
+    display: flex;
+    gap: 60px;
+  }
+  
+  .btn {
+    width: 64px;
+    height: 64px;
+    border-radius: 50%;
+    border: none;
+    font-size: 14px;
+    color: white;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    cursor: pointer;
+    user-select: none;
+    outline: none;
+    transition: background-color 0.3s ease;
+  }
+  
+  .btn.accept {
+    background-color: #4cd964; /* 绿色接听 */
+  }
+  
+  .btn.accept:hover {
+    background-color: #40c150;
+  }
+  
+  .btn.reject {
+    background-color: #ff3b30; /* 红色拒绝 */
+  }
+  
+  .btn.reject:hover {
+    background-color: #e02d22;
+  }
+  
+  .btn.hangup {
+    background-color: #ff3b30;
+  }
+  
+  .btn.hangup:hover {
+    background-color: #e02d22;
+  }
+  </style>