liming há 4 dias atrás
pai
commit
39c2051f23

+ 22 - 4
src/views/im/chat/index.vue

@@ -154,11 +154,11 @@
           <div>拍摄</div>
         </div>
         <div class="tool-btn">
-          <svg-icon class="tool-icon" name="yyth" @click="startAudioOnline" />
+          <svg-icon class="tool-icon" name="yyth" @click="startAudioOnline(Constant.DIAL_AUDIO_ONLINE)" />
           <div>语音通话</div>
         </div>
         <div class="tool-btn">
-          <svg-icon class="tool-icon" name="spth" />
+          <svg-icon class="tool-icon" name="spth" @click="startAudioOnline(Constant.DIAL_VIDEO_ONLINE)"  />
           <div>视频通话</div>
         </div>
         <div class="tool-btn">
@@ -425,14 +425,14 @@ const beforeRead = (file) => {
 
 //  创建呼叫:开启语音电话: 调试用,正式逻辑读src/views/im/hook/messagesHook.js
 // ==== 1. 发起语音通话 ====
-const startAudioOnline = async () => {
+const startAudioOnline = async (contentType) => {
   rtcStore.imSate.videoCallModal = true;
   rtcStore.imSate.callAvatar = wsStore.toUserInfo.avatar;
   rtcStore.imSate.callName = wsStore.toUserInfo.nickname;
   rtcStore.isCaller = true;
   wsStore.sendMessage({
     messageType: MESSAGE_TYPE_USER, // 单聊消息
-    contentType: Constant.DIAL_AUDIO_ONLINE,
+    contentType,
     type: Constant.MESSAGE_TRANS_TYPE,
     avatar: walletStore.avatar,
   });
@@ -722,4 +722,22 @@ const goDetail = () => router.push("detail");
   position: relative;
   z-index: 10; /* 确保输入框在上层 */
 }
+
+
+.local-video {
+  position: absolute;
+  bottom: 20px;
+  right: 20px;
+  width: 200px;
+  height: auto;
+  border: 2px solid white;
+  border-radius: 8px;
+}
+
+.remote-video {
+  width: 100%;
+  height: 100vh;
+  background: black;
+  object-fit: cover;
+}
 </style>

+ 40 - 5
src/views/im/components/CallController/index.vue

@@ -2,10 +2,32 @@
   <div v-if="rtcStore.imSate.videoCallModal" class="weixin-call-modal">
     <div class="caller-info">
       <img
+        v-if="rtcStore.streamType == 'audio'"
         class="avatar"
         :src="rtcStore.imSate.callAvatar || defaultAvatar"
         alt="头像"
       />
+      <div v-if="rtcStore.streamType == 'video'">
+        <!-- 本地视频 -->
+        <video
+          ref="localVideo"
+          autoplay
+          playsinline
+          muted
+          class="local-video"
+        ></video>
+
+        <!-- 远程视频 -->
+        <video
+          ref="remoteVideo"
+          autoplay
+          playsinline
+          class="remote-video"
+        ></video>
+      </div>
+
+      <!-- video id="localPreviewSender" width="700px" height="auto" autoPlay muted controls />
+                    <video id="remoteVideoSender" width="700px" height="auto" autoPlay muted controls /> -->
       <div class="name">{{ rtcStore.imSate.callName || "未知用户" }}</div>
       <div class="status">{{ statusText }}</div>
     </div>
@@ -38,12 +60,15 @@ import * as Constant from "@/common/constant/Constant";
 const wsStore = useWebSocketStore();
 const rtcStore = useWebRTCStore();
 
+const localVideo = ref(null);
+const remoteVideo = ref(null);
+
 const inCall = ref(false);
 const defaultAvatar = "https://example.com/default-avatar.png";
 
 const statusText = computed(() => {
-  if(inCall.value && rtcStore.remoteStream){
-    return "通话中..."
+  if (inCall.value && rtcStore.remoteStream) {
+    return "通话中...";
   }
   return inCall.value ? "链接中..." : "正在语音通话请求...";
 });
@@ -111,12 +136,22 @@ function hangupCall() {
 watch(
   () => rtcStore.remoteStream,
   (val) => {
-    if (val && rtcStore.streamType == "video") {
-      console.log("remoteStream===", rtcStore.streamType)
+    if (val && rtcStore.streamType == "video" && remoteVideo.value) {
+      remoteVideo.value.srcObject = val;
     }
   }
 );
- 
+
+watch(
+  () => rtcStore.localStream,
+  (val) => {
+    if (val && rtcStore.streamType == "video" && localVideo.value) {
+      localVideo.value.srcObject = val;
+    }
+  },
+  { immediate: true }
+);
+
 onMounted(() => {
   wsStore.onMessageCallbacks.push(onMessage);
 });

+ 3 - 3
src/views/im/hook/messagesHook.js

@@ -119,7 +119,7 @@ export const handleMessageHook = (message, state) => {
     message.contentType === Constant.ACCEPT_VIDEO_ONLINE ||
     message.contentType === Constant.ACCEPT_AUDIO_ONLINE
   ) {
-     console.log("音频在线:接听")
+     console.log("音频在线:接听", message.contentType)
     const video = message.contentType == Constant.ACCEPT_AUDIO_ONLINE
     startAudioOnline(video, state);
     return;
@@ -157,7 +157,7 @@ export const handleMessageHook = (message, state) => {
       // let preview = null;
 
      
-
+      console.log("message.contentType=", message.contentType)
       let video = false;
       if (message.contentType === Constant.VIDEO_ONLINE) {
         // preview = document.getElementById("localVideoReceiver");
@@ -218,7 +218,7 @@ const startAudioOnline = (video, state) => {
     .then((offer) => {
       // 发送offer
       state.sendMessage({
-        contentType: Constant.AUDIO_ONLINE, // 消息内容类型
+        contentType: video? Constant.VIDEO_ONLINE: Constant.AUDIO_ONLINE, // 消息内容类型
         content: JSON.stringify(offer),
         type: Constant.MESSAGE_TRANS_TYPE,
       });