tremble пре 3 година
родитељ
комит
e754767254
4 измењених фајлова са 197 додато и 194 уклоњено
  1. 37 120
      src/components/RTC/PageRtcLive.vue
  2. 150 66
      src/components/RTC/Trtccom.vue
  3. 0 4
      src/components/RTC/index.vue
  4. 10 4
      src/store/modules/rtc.js

+ 37 - 120
src/components/RTC/PageRtcLive.vue

@@ -4,27 +4,11 @@
       <div class="members"></div>
       <span>{{ user_list.length }}观看</span>
     </div>
-    <chat ref="chat$" v-show="chatShow" :chatList="chatList" :user_info="user_info"></chat>
-
-    <Trtccom v-if="showTest" />
-    <div class="videoBox userVideo" id="userVideo" v-show="!hideVideoTop">
-      <img v-if="!userVideoShow" :src="require('@/assets/images/rtcLive/avatar_small@2x.png')" alt="" />
-      <img v-if="!userVideoShow" class="loadingTip" :src="require('@/assets/images/rtcLive/loading@2x.png')" alt="" />
-      <div class="micBox">
-        <i v-if="hideMicTop" class="iconfont iconscene_mic_off1"></i>
-        <i v-else class="speak_mic"></i>
-      </div>
-    </div>
-    <div v-show="mode == '1' && !hideVideoBottom" class="videoBox myVideo" id="myVideo">
-      <img v-if="!myVideoShow" :src="require('@/assets/images/rtcLive/avatar_small@2x.png')" alt="" />
-      <img v-if="!myVideoShow" class="loadingTip" :src="require('@/assets/images/rtcLive/loading@2x.png')" alt="" />
-      <div class="micBox">
-        <i v-if="hideMic" class="iconfont iconscene_mic_off1"></i>
-        <i v-else class="speak_mic"></i>
-      </div>
-    </div>
-    <!-- </div> -->
-    <!-- <input type="text" autocomplete="off"> -->
+    <chat  v-show="chatShow" :chatList="chatList" :user_info="user_info"></chat>
+
+    <Trtccom ref="trtccom$" :audioMuted="audioMuted" :videoMuted="videoMuted" v-if="showTest && isJoined" />
+    
+
     <div class="contorlBar" v-if="!showInput">
       <div v-if="connectStatus == 1" :class="{ disabled: !user_info.IsWords }" class="saySomething" @click="onFocus">
         <!-- <i class="speakIcon"
@@ -47,13 +31,7 @@
         <div v-if="mode == '2' && role == 'leader'" class="members" @click="openMember"></div>
         <div v-if="audioDevices.length != 0 && !disableMic" @click="changeMedia('audio', hideMic)" :class="{ mic_off: hideMic }" class="mic_on"></div>
         <div v-if="audioDevices.length == 0 || disableMic" class="mic_no"></div>
-        <div
-          v-if="(role == 'leader' && videoDevices.length != 0) || (mode == '1' && videoDevices.length != 0)"
-          @click="changeMedia('video', hideVideo)"
-          :class="{ video_off: hideVideo }"
-          class="video_on"
-        ></div>
-        <div v-if="(videoDevices.length == 0 && mode == '1') || (role == 'leader' && videoDevices.length == 0)" class="video_no"></div>
+        <div v-if="role == 'leader'" @click="handleMuteVideo" :class="videoMuted ? 'video_no' : 'video_on'"></div>
         <div class="exit" @click="openDialog('dialogIndex')"></div>
       </div>
     </div>
@@ -93,7 +71,7 @@
               </div>
             </div>
 
-            <div v-show="user_info.UserId != i.UserId && i.Role != 'leader'" class="memberItem" v-for="(i,idx) in user_list" :key="i.UserId">
+            <div v-show="user_info.UserId != i.UserId && i.Role != 'leader'" class="memberItem" v-for="(i, idx) in user_list" :key="i.UserId">
               <div class="userMsg">
                 <div class="avatar">
                   <img :src="require('@/assets/images/rtcLive/avatar_small@2x.png')" alt="" />
@@ -103,7 +81,7 @@
               <div class="button" v-if="user_info.Role == 'leader'">
                 <div class="micBtn" :class="i.IsWords ? 'ban_speak_on' : 'ban_speak_off'" @click="userCanSpeak(i)"></div>
 
-                <div class="outBtn icon_remove" @click="userGetOut(i,idx)"></div>
+                <div class="outBtn icon_remove" @click="userGetOut(i, idx)"></div>
                 <div class="micBtn" :class="i.IsMuted ? 'mute_one_mic_off' : 'mute_one_mic_on'" @click="onMemberMuted(i)"></div>
               </div>
             </div>
@@ -146,10 +124,6 @@ let createSocket = (config) => {
   return socket;
 };
 
-
-store.commit("rtc/setUserId", browser.getURLParam("userId"));
-store.commit("rtc/setRoomId", browser.getURLParam("roomId"));
-
 store.commit("rtc/setSocket", createSocket());
 
 let getUrl = (href, queryArr) => {
@@ -176,6 +150,9 @@ const showInput = ref(false);
 const showMember = ref(false);
 const animateActive = ref(false);
 
+const audioMuted = ref(false);
+const videoMuted = ref(false);
+
 const socket = computed(() => store.getters["rtc/socket"]);
 const showTest = ref(browser.getURLParam("test"));
 
@@ -186,6 +163,8 @@ const user_list = ref([]);
 const mode = ref(browser.getURLParam("mode"));
 const role = ref(browser.getURLParam("role"));
 
+const userId = computed(() => store.getters["rtc/userId"]);
+const roomId = computed(() => store.getters["rtc/roomId"]);
 
 const isJoined = ref(false);
 
@@ -202,18 +181,18 @@ const disableMic = ref(false);
 const chatShow = ref(true);
 const all_mute_mic = ref(true);
 
-const chat$ = ref(null);
+const trtccom$ = ref(null);
 
-const userGetOut = (item,i) => {
+const userGetOut = (item, i) => {
   socket.value &&
     socket.value.emit("action", {
       type: "getout",
       data: {
-        id:item.UserId
+        id: item.UserId,
       },
     });
 
-    user_list.value = user_list.value.splice(i,1)
+  user_list.value = user_list.value.splice(i, 1);
 };
 
 const setUserWords = (res) => {
@@ -222,11 +201,16 @@ const setUserWords = (res) => {
   }
 };
 
+const handleMuteVideo = () =>{
+  console.log(111111111111111);
+  videoMuted.value=!videoMuted.value
+}
+
 const setUserMuted = (res) => {
   if (res.userId == user_info.value.UserId) {
     user_info.value.IsMuted = res.muted;
-    disableMic.value = res.muted
-    hideMic.value = res.muted
+    disableMic.value = res.muted;
+    hideMic.value = res.muted;
   }
 };
 
@@ -244,7 +228,9 @@ const setUserJoin = async (res) => {
   let name = res.user.Nickname;
   if (res.user.Role == "leader") {
     name = "主持人";
+    console.log(trtccom$.value);
     Dialog.toast({ content: `主持人进入房间` });
+
   }
   let data = {
     role: res.user.Role,
@@ -377,7 +363,6 @@ const onMemberLeave = (res) => {
   }
 };
 
-
 const userCanSpeak = (item) => {
   item.IsWords = !item.IsWords;
   socket.value.emit("action", { type: "users-words", words: item.IsWords, userId: item.UserId });
@@ -392,11 +377,14 @@ const onGetOuT = (data) => {
 
 const startFollow = (app) => {
   app.Connect.follow.start({ follow: role.value == "customer" });
- 
+
+  store.commit("rtc/setUserId", browser.getURLParam("userId") || `user_${Math.floor(Math.random() * 100000000)}`);
+  store.commit("rtc/setRoomId", browser.getURLParam("roomId") || Math.floor(Math.random() * 100000));
+
   socket.value.on("connect", () => {
     socket.value.emit("join", {
-      userId: browser.getURLParam("userId") || common.uuid(12),
-      roomId: browser.getURLParam("roomId") || common.uuid(12),
+      userId: userId.value,
+      roomId: roomId.value,
       role: role.value || "leader",
       nickname: browser.getURLParam("name") || common.uuid(12),
     });
@@ -405,7 +393,7 @@ const startFollow = (app) => {
   // 加入房间成功
   socket.value.on("join", (data) => {
     connectStatus.value = 1;
-     if (role.value == "customer") {
+    if (role.value == "customer") {
       socket.value.emit("action", { type: "user-init" });
     }
 
@@ -497,22 +485,20 @@ const startFollow = (app) => {
       //禁言
     } else if (data.type == "user-leave") {
       // 房间解散
-      onMemberLeave(data)
+      onMemberLeave(data);
     }
-
-
   });
 
   // 同屏带看
   socket.value.on("sync", (data) => {
-    if (role.value=='customer') {
+    if (role.value == "customer") {
       app.Connect.follow.receive(data);
     }
   });
 
   // 画笔
   socket.value.on("paint", (data) => {
-    if (role.value=='customer') {
+    if (role.value == "customer") {
       app.Connect.paint.receive(data);
     }
   });
@@ -571,75 +557,6 @@ onMounted(() => {
       color: #fff;
     }
   }
-  .videoBox {
-    width: 1.94rem;
-    height: 1.94rem;
-    border-radius: 50%;
-    overflow: hidden;
-    position: fixed;
-    .loadingTip {
-      position: absolute;
-      z-index: 101;
-      left: 0;
-      top: 0;
-      animation: Rotate 1.5s infinite;
-      @keyframes Rotate {
-        0% {
-          transform: rotate(0deg);
-        }
-        100% {
-          transform: rotate(360deg);
-        }
-      }
-    }
-    > img {
-      width: 1.94rem;
-      height: 1.94rem;
-    }
-    .videoPlayer {
-      width: 1.94rem;
-      height: 1.94rem;
-      position: relative;
-      z-index: 2;
-    }
-    &.userVideo {
-      top: 0.69rem;
-      left: 0.53rem;
-      // background-size: ;
-    }
-    &.myVideo {
-      bottom: 2.72rem;
-      right: 0.69rem;
-    }
-
-    .micBox {
-      width: 100%;
-      height: 0.44rem;
-      background: rgba(0, 0, 0, 0.3);
-      position: absolute;
-      left: 0;
-      bottom: 0;
-      z-index: 100;
-      display: flex;
-      align-items: center;
-      justify-content: center;
-      .speak_mic {
-        display: block;
-        background-size: 13.3344rem auto;
-        width: 0.22rem;
-        height: 0.22rem;
-        background-image: url(~@/assets/images/rtcLive/speed.png);
-        // width: 0.69rem;
-        // height: 0.69rem;
-        animation: myAnimation 3s steps(59) infinite;
-      }
-      .iconscene_mic_off1 {
-        font-size: 0.22rem;
-        color: #f56c6c;
-      }
-    }
-  }
-
   .contorlBar {
     width: 9.51rem;
     height: 1.173333rem;
@@ -1095,7 +1012,7 @@ onMounted(() => {
       background-size: 13.3344rem auto;
     }
 
-    100.00% {
+    100% {
       background-position: -13.1104rem 0px;
       background-size: 13.3344rem auto;
     }

+ 150 - 66
src/components/RTC/Trtccom.vue

@@ -1,11 +1,11 @@
 <template>
   <div class="trtccom" v-if="show">
     <Device @switchDevice="switchDevice" @canUseDevice="canUseDevice" />
-    <div class="local" id="local" v-if="isJoined">
-      <div class="tag">
-        <div :class="audioMuted ? 'muteAudio' : 'unmuteAudio'" @click="muteAudio"></div>
-        <div :class="videoMuted ? 'muteVideo' : 'unmuteVideo'" @click="muteVideo"></div>
-      </div>
+    <div class="local" id="local" v-if="isJoined&&role=='leader'"></div>
+    <div class="local" :id="clientId" v-if="isJoined&&role=='customer'&&clientId"></div>
+    <div class="videoBox userVideo" v-show="props.videoMuted">
+      <img :src="require('@/assets/images/rtcLive/avatar_small@2x.png')" alt="" />
+      <img class="loadingTip" :src="require('@/assets/images/rtcLive/loading@2x.png')" alt="" />
     </div>
   </div>
 </template>
@@ -13,17 +13,27 @@
 <script setup>
 import TRTC, { Client, LocalStream } from "trtc-js-sdk";
 import { Dialog } from "@/global_components/";
-import { ref, computed, watch } from "vue";
+import { ref, computed, watch, defineEmits, defineProps, nextTick } from "vue";
 import Device from "./trtc/Device";
 import { useStore } from "vuex";
+import browser from "@/utils/browser";
+
+const emit = defineEmits(["audioMuted", "videoMuted"]);
+
 const store = useStore();
 
 const show = ref(false);
+const clientId = ref('');
+
+
+const role = ref(browser.getURLParam("role"));
+
+
+
 const isJoined = computed(() => store.getters["rtc/isJoined"]);
 const isPublished = computed(() => store.getters["rtc/isPublished"]);
 const userSig = computed(() => store.getters["rtc/userSig"]);
 
-console.log(userSig.value,'userSig');
 
 const initParamsStates = computed(
   () => !!(store.getters["rtc/sdkAppId"] && store.getters["rtc/secretKey"] && store.getters["rtc/roomId"] && store.getters["rtc/userId"])
@@ -32,8 +42,37 @@ const initParamsStates = computed(
 let localClient = "";
 let localStream = "";
 let shareClient = "";
-const audioMuted = ref(false);
-const videoMuted = ref(false);
+
+const props = defineProps({
+  audioMuted: {
+    default: false,
+  },
+  videoMuted: {
+    default: false,
+  },
+});
+
+watch(
+  () => props.audioMuted,
+  () => {
+    if (props.audioMuted) {
+      localStream.muteAudio();
+    } else {
+      localStream.unmuteAudio();
+    }
+  }
+);
+
+watch(
+  () => props.videoMuted,
+  () => {
+    if (props.videoMuted) {
+      localStream.muteVideo();
+    } else {
+      localStream.unmuteVideo();
+    }
+  }
+);
 
 TRTC.checkSystemRequirements().then((checkResult) => {
   console.log(checkResult.result, "checkResult.result");
@@ -44,12 +83,12 @@ TRTC.checkSystemRequirements().then((checkResult) => {
   }
 });
 
-async function createLocalStream() {
+async function createLocalStream(video=true) {
   try {
     localStream = TRTC.createStream({
       userId: store.getters["rtc/userId"],
       audio: true,
-      video: true,
+      video: video,
       cameraId: store.getters["rtc/videoDeviceId"],
       microphoneId: store.getters["rtc/audioDeviceId"],
     });
@@ -80,10 +119,13 @@ async function handleJoin() {
       userSig: userSig.value,
     });
     installEventHandlers();
+
     await localClient.join({ roomId: parseInt(store.getters["rtc/roomId"], 10) });
     store.commit("rtc/setIsJoined", true);
     // inviteLink.value = store.commit("rtc/createShareLink");
-  } catch (error) {}
+  } catch (error) {
+    console.error(error, "error-----------");
+  }
 
   await createLocalStream();
   await handlePublish();
@@ -103,6 +145,64 @@ async function handlePublish() {
   } catch (error) {}
 }
 
+async function handleStartShare() {
+  shareClient = new ShareClient({
+    sdkAppId: parseInt(store.getters["rtc/sdkAppId"], 10),
+    userId: `share${store.getters["rtc/userId"]}`,
+    roomId: parseInt(store.getters["rtc/roomId"], 10),
+    secretKey: store.getters["rtc/secretKey"],
+  });
+  try {
+    await shareClient.join();
+    await shareClient.publish();
+    console.log('Start share screen success');
+    store.isShared = true;
+  } catch (error) {
+    console.error(`Start share error: ${error.message_}`);
+  }
+}
+
+async function handleClientJoin() {if (!initParamsStates.value) {
+    return;
+  }
+
+  try {
+    localClient = TRTC.createClient({
+      mode: "rtc",
+      sdkAppId: parseInt(store.getters["rtc/sdkAppId"], 10),
+      userId: store.getters["rtc/userId"],
+      userSig: userSig.value,
+    });
+    installEventHandlers();
+
+    await localClient.join({ roomId: parseInt(store.getters["rtc/roomId"], 10) });
+    store.commit("rtc/setIsJoined", true);
+  } catch (error) {
+    console.error(error, "error-----------");
+  }
+
+  await createLocalStream(false);
+  await handlePublish();
+
+  localClient.on('stream-subscribed', handleSubscribed);
+
+}
+
+
+async function handleSubscribed(event) {
+  const remoteStream = event.stream;
+  clientId.value = remoteStream.getId();
+  await nextTick();
+  remoteStream
+    .play(clientId.value)
+    .then(() => {
+      console.log(`RemoteStream play success`);
+    })
+    .catch((error) => {
+      console.log(`RemoteStream play failed:  error: ${error.message_}`);
+    });
+}
+
 async function handleUnpublish() {
   if (!isJoined.value) {
     return;
@@ -246,26 +346,6 @@ function handleStreamUpdated(event) {
   console.log(`RemoteStream updated: [${userId}] audio:${remoteStream.hasAudio()} video:${remoteStream.hasVideo()}`);
 }
 
-const muteAudio = () => {
-  if (!audioMuted.value) {
-    localStream.muteAudio();
-    audioMuted.value = true;
-  } else {
-    localStream.unmuteAudio();
-    audioMuted.value = false;
-  }
-};
-
-const muteVideo = () => {
-  if (!videoMuted.value) {
-    localStream.muteVideo();
-    videoMuted.value = true;
-  } else {
-    localStream.unmuteVideo();
-    videoMuted.value = false;
-  }
-};
-
 let switchDevice = async ({ videoId, audioId }) => {
   if (!isJoined.value) {
     return;
@@ -284,52 +364,56 @@ let switchDevice = async ({ videoId, audioId }) => {
 
 let canUseDevice = () => {
   console.log("可用");
-  handleJoin();
+
+  if (role.value == 'leader') {
+    handleJoin();
+  } else{
+    handleClientJoin()
+  }
 };
 </script>
 
 <style lang="scss" scoped>
 .trtccom {
   .local {
-    width: 120px;
-    height: 120px;
+    width: 70px;
+    height: 70px;
     position: fixed;
     z-index: 9999;
-    left: 10px;
-    top: 10px;
-    background: #000;
-    .muteAudio {
-      background: url(~@/assets/images/icon/mic-mute.svg) center center no-repeat;
-    }
-
-    .unmuteAudio {
-      background: url(~@/assets/images/icon/mic.svg) center center no-repeat;
-    }
-
-    .muteVideo {
-      background: url(~@/assets/images/icon/camera-mute.svg) center center no-repeat;
-    }
-
-    .unmuteVideo {
-      background: url(~@/assets/images/icon/camera.svg) center center no-repeat;
-    }
-
-    .tag {
+    top: 0.69rem;
+    left: 0.53rem;
+    border-radius: 50%;
+    overflow: hidden;
+    background: url(~@/assets/images/rtcLive/avatar_small@2x.png) center center no-repeat;
+  }
+  .videoBox {
+    width: 72px;
+    height: 72px;
+    top: 0.67rem;
+    left: 0.52rem;
+    position: fixed;
+    z-index: 99999;
+    .loadingTip {
       position: absolute;
+      z-index: 101;
+      left: 0;
+      top: 0;
       bottom: 0;
-      width: 100%;
-      height: 25px;
-      z-index: 999;
-      background: rgba(0, 0, 0, 0.3);
-      display: flex;
-      padding: 0 4px;
-      flex-direction: row-reverse;
-      > div {
-        height: 25px;
-        width: 25px;
-        cursor: pointer;
+      right: 0;
+      animation: Rotate 1.5s infinite;
+      @keyframes Rotate {
+        0% {
+          transform: rotate(0deg);
+        }
+        100% {
+          transform: rotate(360deg);
+        }
       }
     }
+    > img {
+      width: 1.94rem;
+      height: 1.94rem;
+    }
   }
 }
 </style>

+ 0 - 4
src/components/RTC/index.vue

@@ -31,10 +31,6 @@ const roomId = ref(browser.getURLParam("roomId"));
 const role = ref(browser.getURLParam("role"));
 const userName = ref(browser.getURLParam("name"));
 const socket = computed(() => store.getters["rtc/socket"]);
-const userSig = computed(() => store.getters["rtc/userSig"]);
-
-console.log(userSig.value,'userSig');
-
 
 
 const openDialog = (str, link) => {

+ 10 - 4
src/store/modules/rtc.js

@@ -1,9 +1,8 @@
 
 
-// import { genTestUserSig } from '@/utils/generateTestUserSig';
+import { genTestUserSig } from '@/utils/generateTestUserSig';
 // import { apis } from '@/apis';
 
-
 export default {
     namespaced: true,
     state() {
@@ -14,7 +13,7 @@ export default {
             userId: '',
             roomId: '',
             secretKey: 'def391b02e6423a6db15eea3d9a0c131f2abac921204246bbe3f36fcea7d111d',
-            userSig: 'eJw1jtEKgjAYhd9l1yH-1tpM6CqCLKULrcw7YVN-JFkqrRG9e6J1eb7DxzlvkkaJp18GO00CAdwHWEzsqTsSEOYBmXOvmsIYVCSgHEDCmgObG1S6HbDESaBLYFT6QMXfw2rEzvZJ7XjGq*YQ3dyprZNY7ONtWFmbHeXjkubdudhdVRlufuKA9-ESFStfsnFPfL6RQTHD',
+            userSig: 'eJw1jlELgjAURv-LnkPunXNToZceosB6SPsBwVbelrLpFCH675XW43c*Dpwnq4oyMpOjzrBcgkgBVjMbTcdyxiNgy*61vThHmuUoABRkAvjykDZtoCvNAsbAUaWA8u-R7YttFno-JNPou7LBuH0MQR6t2tp6cz-5sy75zrXV3heH9U8M1HySUCapirnC7PUGl3Ix6g__',
             audioDeviceId: '',
             videoDeviceId: '',
             cameraList: [],
@@ -38,7 +37,14 @@ export default {
         userId: state => state.userId,
         roomId: state => state.roomId,
         secretKey: state => state.secretKey,
-        userSig: state => state.userSig,
+        userSig: state => {
+            const { userSig } = genTestUserSig({
+                sdkAppId: parseInt(state.sdkAppId, 10),
+                userId:state.userId,
+                secretKey: state.secretKey,
+            });
+            return userSig
+        },
         audioDeviceId: state => state.audioDeviceId,
         videoDeviceId: state => state.videoDeviceId,
         cameraList: state => state.cameraList,