gemercheung 1 år sedan
förälder
incheckning
50d8eca7ab

+ 2 - 1
package.json

@@ -18,7 +18,7 @@
     "lint:lint-staged": "lint-staged"
   },
   "dependencies": {
-    "agora-rtc-sdk-ng": "^4.18.2",
+    "agora-rtc-sdk-ng": "^4.19.2",
     "axios": "^1.1.3",
     "clipboard": "^2.0.11",
     "consola": "^2.15.3",
@@ -30,6 +30,7 @@
     "pinia-plugin-persistedstate": "^2.3.0",
     "trtc-js-sdk": "^4.14.6",
     "uuid": "^9.0.0",
+    "uuidv4": "^6.2.13",
     "vue": "^3.2.41",
     "vue-i18n": "^9.2.2",
     "vue-types": "^4.2.1",

+ 112 - 5
pnpm-lock.yaml

@@ -6,8 +6,8 @@ settings:
 
 dependencies:
   agora-rtc-sdk-ng:
-    specifier: ^4.18.2
-    version: 4.18.2
+    specifier: ^4.19.2
+    version: 4.19.2
   axios:
     specifier: ^1.1.3
     version: 1.1.3
@@ -41,6 +41,9 @@ dependencies:
   uuid:
     specifier: ^9.0.0
     version: 9.0.0
+  uuidv4:
+    specifier: ^6.2.13
+    version: 6.2.13
   vue:
     specifier: ^3.2.41
     version: 3.2.41
@@ -159,6 +162,37 @@ packages:
     engines: {node: '>=0.10.0'}
     dev: true
 
+  /@agora-js/media@4.19.2:
+    resolution: {integrity: sha512-A83uOxolbWod1ydOPFPi+xKoCN5IfcT7q4oR0H6VyGFoo1IA0OWpPztY/C1ueiU9ct5TSBqewEJUQrwvYKWuYQ==}
+    dependencies:
+      '@agora-js/report': 4.19.2
+      '@agora-js/shared': 4.19.2
+      agora-rte-extension: 1.2.3
+      axios: 0.27.2
+      pako: 2.1.0
+      webrtc-adapter: 8.2.0
+    transitivePeerDependencies:
+      - debug
+    dev: false
+
+  /@agora-js/report@4.19.2:
+    resolution: {integrity: sha512-fT3ShsADEQQQwCbVXFGCj3hmsBR9F69JkpeypdiMmDyUrG9MgKYZub/En+nijk4nZ30wuWYeJBntfx+/4Vfd0g==}
+    dependencies:
+      '@agora-js/shared': 4.19.2
+      axios: 0.27.2
+    transitivePeerDependencies:
+      - debug
+    dev: false
+
+  /@agora-js/shared@4.19.2:
+    resolution: {integrity: sha512-foCSc2tZx99DlMZ3zO47en4eyWYeHtm3Q0dDEWKK7sTaTVqS73aa6O/7CIw9vm2MKfvBv9rFcpXUlYbFKA0/1g==}
+    dependencies:
+      axios: 0.27.2
+      ua-parser-js: 0.7.37
+    transitivePeerDependencies:
+      - debug
+    dev: false
+
   /@ampproject/remapping@2.2.1:
     resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==}
     engines: {node: '>=6.0.0'}
@@ -1240,7 +1274,6 @@ packages:
 
   /@types/uuid@8.3.4:
     resolution: {integrity: sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==}
-    dev: true
 
   /@types/web-bluetooth@0.0.16:
     resolution: {integrity: sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==}
@@ -1758,10 +1791,19 @@ packages:
       indent-string: 4.0.0
     dev: true
 
-  /agora-rtc-sdk-ng@4.18.2:
-    resolution: {integrity: sha512-tvyuXHVL15Eo0lK3wwM3rGPKGPeGYuarAwCs5oyveht1HZO9z3w6vra3d/q3eOCYpvQscCW7P0QNfUIAQTs4RQ==}
+  /agora-rtc-sdk-ng@4.19.2:
+    resolution: {integrity: sha512-5ctCSxhdo2UnTAd/+00ZAuHRQzLUt4yNkopkd7tXAQNAmaTFu0dyOkAK5/ind5cZuqQLTuggX4ctXCHpIzpHTw==}
     dependencies:
+      '@agora-js/media': 4.19.2
+      '@agora-js/report': 4.19.2
+      '@agora-js/shared': 4.19.2
       agora-rte-extension: 1.2.3
+      axios: 0.27.2
+      formdata-polyfill: 4.0.10
+      ua-parser-js: 0.7.37
+      webrtc-adapter: 8.2.0
+    transitivePeerDependencies:
+      - debug
     dev: false
 
   /agora-rte-extension@1.2.3:
@@ -1909,6 +1951,15 @@ packages:
       - debug
     dev: true
 
+  /axios@0.27.2:
+    resolution: {integrity: sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==}
+    dependencies:
+      follow-redirects: 1.15.2(debug@4.3.4)
+      form-data: 4.0.0
+    transitivePeerDependencies:
+      - debug
+    dev: false
+
   /axios@1.1.3:
     resolution: {integrity: sha512-00tXVRwKx/FZr/IDVFt4C+f9FYairX517WoGCL6dpOntqLkZofjhu43F/Xl44UOpqa+9sLFDrG/XAnFsUYgkDA==}
     dependencies:
@@ -3168,6 +3219,14 @@ packages:
       bser: 2.1.1
     dev: true
 
+  /fetch-blob@3.2.0:
+    resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==}
+    engines: {node: ^12.20 || >= 14.13}
+    dependencies:
+      node-domexception: 1.0.0
+      web-streams-polyfill: 3.2.1
+    dev: false
+
   /figures@2.0.0:
     resolution: {integrity: sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==}
     engines: {node: '>=4'}
@@ -3287,6 +3346,13 @@ packages:
       mime-types: 2.1.35
     dev: false
 
+  /formdata-polyfill@4.0.10:
+    resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==}
+    engines: {node: '>=12.20.0'}
+    dependencies:
+      fetch-blob: 3.2.0
+    dev: false
+
   /fs-extra@9.1.0:
     resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==}
     engines: {node: '>=10'}
@@ -4836,6 +4902,11 @@ packages:
     resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==}
     dev: true
 
+  /node-domexception@1.0.0:
+    resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==}
+    engines: {node: '>=10.5.0'}
+    dev: false
+
   /node-fetch@2.6.12:
     resolution: {integrity: sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==}
     engines: {node: 4.x || >=6.0.0}
@@ -5023,6 +5094,10 @@ packages:
     engines: {node: '>=6'}
     dev: true
 
+  /pako@2.1.0:
+    resolution: {integrity: sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==}
+    dev: false
+
   /parent-module@1.0.1:
     resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
     engines: {node: '>=6'}
@@ -5444,6 +5519,10 @@ packages:
       xmlchars: 2.2.0
     dev: true
 
+  /sdp@3.2.0:
+    resolution: {integrity: sha512-d7wDPgDV3DDiqulJjKiV2865wKsJ34YI+NDREbm+FySq6WuKOikwyNQcm+doLAZ1O6ltdO0SeKle2xMpN3Brgw==}
+    dev: false
+
   /select@1.1.2:
     resolution: {integrity: sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA==}
     dev: false
@@ -5956,6 +6035,10 @@ packages:
     engines: {node: '>=4.2.0'}
     hasBin: true
 
+  /ua-parser-js@0.7.37:
+    resolution: {integrity: sha512-xV8kqRKM+jhMvcHWUKthV9fNebIzrNy//2O9ZwWcfiBFR5f25XVZPLlEajk/sf3Ra15V92isyQqnIEXRDaZWEA==}
+    dev: false
+
   /unbox-primitive@1.0.2:
     resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==}
     dependencies:
@@ -6014,11 +6097,23 @@ packages:
     resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
     dev: true
 
+  /uuid@8.3.2:
+    resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==}
+    hasBin: true
+    dev: false
+
   /uuid@9.0.0:
     resolution: {integrity: sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==}
     hasBin: true
     dev: false
 
+  /uuidv4@6.2.13:
+    resolution: {integrity: sha512-AXyzMjazYB3ovL3q051VLH06Ixj//Knx7QnUSi1T//Ie3io6CpsPu9nVMOx5MoLWh6xV0B9J0hIaxungxXUbPQ==}
+    dependencies:
+      '@types/uuid': 8.3.4
+      uuid: 8.3.2
+    dev: false
+
   /v8-compile-cache-lib@3.0.1:
     resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==}
     requiresBuild: true
@@ -6320,6 +6415,11 @@ packages:
       defaults: 1.0.4
     dev: true
 
+  /web-streams-polyfill@3.2.1:
+    resolution: {integrity: sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==}
+    engines: {node: '>= 8'}
+    dev: false
+
   /webidl-conversions@3.0.1:
     resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
     dev: true
@@ -6334,6 +6434,13 @@ packages:
     engines: {node: '>=10.4'}
     dev: true
 
+  /webrtc-adapter@8.2.0:
+    resolution: {integrity: sha512-umxCMgedPAVq4Pe/jl3xmelLXLn4XZWFEMR5Iipb5wJ+k1xMX0yC4ZY9CueZUU1MjapFxai1tFGE7R/kotH6Ww==}
+    engines: {node: '>=6.0.0', npm: '>=3.10.0'}
+    dependencies:
+      sdp: 3.2.0
+    dev: false
+
   /whatwg-encoding@1.0.5:
     resolution: {integrity: sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==}
     dependencies:

+ 4 - 2
src/App.vue

@@ -33,6 +33,7 @@
   import 'kankan-components/theme-chalk/index.css';
 
   import { useSocket } from './hooks/userSocket';
+  import { useRtcSdk } from './hooks/useTRTC';
   const { createTourPlayer } = useTourPlayer();
   const showDebug = ref(Number(import.meta.env.VITE_SHOW_DEBUGPANEL) === 1);
   const { t } = useI18n();
@@ -62,6 +63,7 @@
   const isLoaded = computed(() => appStore.isLoaded);
   const showPasswordDialog = ref(false);
   const { room } = useRoom();
+  const { muteVideoLeader } = useRtcSdk();
   // const connectStatus = computed(() => rtcStore.connectStatus);
   const controls = computed(() => {
     return metadata.value.controls;
@@ -366,12 +368,12 @@
       {{ maxNumber }}
     </span> -->
     <span>
-      {{ t('base.debuginfo') }}V:1.2.0,角色:{{ rtcStore.role }} rId:{{
+      {{ t('base.debuginfo') }}V:1.2.0-11,角色:{{ rtcStore.role }} rId:{{
         rtcStore.roomId || browser.getURLParam('roomId')
       }}
       sceneIndex:{{ currentSceneIndex }} uid::
       {{ rtcStore.userId || browser.getURLParam('vruserId') }}
-      MaxMan: {{ room?.maxMan }}
+      MaxMan: {{ room?.maxMan }} muteVideoLeader:{{ muteVideoLeader }}
     </span>
     <span class="close" @click.stop="showDebug = false">X</span>
   </div>

+ 0 - 108
src/components/chatRoom/camera copy.vue

@@ -1,108 +0,0 @@
-<template>
-  <teleport to=".local" v-if="(isRTCJoined || isPublished) && isLeader">
-    <div class="micBox">
-      <i class="speak_mic" v-if="!roomLeader?.IsMuted"></i>
-      <i class="speak_mic_off" v-else></i>
-    </div>
-  </teleport>
-  <teleport to=".remote" v-if="!isLeader && remoteStreams.length > 0">
-    <div class="micBox">
-      <i class="speak_mic" v-if="!roomLeader?.IsMuted"></i>
-      <i class="speak_mic_off" v-else></i>
-    </div>
-  </teleport>
-</template>
-<script lang="ts" setup>
-  //   import { ref } from 'vue';
-
-  import { computed, onMounted } from 'vue';
-  // import { useRtcSdk } from '/@/hooks/useTRTC';
-  // import { useSocket } from '/@/hooks/userSocket';
-
-  //   import { useRtcSdk } from '/@/hooks/useTRTC';
-  import { useRtcStore } from '/@/store/modules/rtc';
-
-  const rtcStore = useRtcStore();
-  // const destination = computed(() => (rtcStore.isLeader ? '.local' : '.remote'));
-  const isPublished = computed(() => rtcStore.isPublished);
-  const isRTCJoined = computed(() => rtcStore.isRTCJoined);
-  const isLeader = computed(() => rtcStore.isLeader);
-  const remoteStreams = computed(() => rtcStore.remoteStreams);
-  const roomLeader = computed(() => rtcStore.getRoomLeader());
-  // const { muteVideoLeader } = useRtcSdk();
-  // const hasVideo = computed(() => rtcStore.videoDeviceId.length > 0);
-  onMounted(() => {});
-</script>
-<style lang="scss">
-  #PageRtcLive {
-    &.leader + div.local {
-      + div.remote {
-        display: none;
-      }
-    }
-    &.customer + div.local {
-      display: none;
-    }
-  }
-  #PageRtcLive {
-    &.hideCam + div.local {
-      display: none;
-      + div.remote {
-        display: none;
-      }
-    }
-  }
-  .local,
-  .remote {
-    width: 1.94rem;
-    height: 1.94rem;
-    position: fixed;
-    top: 0.69rem;
-    left: 0.53rem;
-    overflow: hidden;
-    z-index: 10000;
-    border-radius: 50%;
-    video {
-      background: transparent;
-    }
-    .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: 720px auto;
-        width: 12px;
-        height: 12px;
-        background-image: url(/@/assets/images/rtcLive/speed.png);
-        // width: 0.69rem;
-        // height: 0.69rem;
-        animation: myAnimation 3s steps(59) infinite;
-      }
-      .speak_mic_off {
-        display: block;
-        background-size: center center;
-        background-size: contain;
-        width: 12px;
-        height: 12px;
-        background-image: url(/@/assets/images/rtcLive/scene_mic_off@2x.png);
-      }
-    }
-  }
-  @keyframes myAnimation {
-    0% {
-      background-position: 0px 0px;
-    }
-
-    100% {
-      background-position: -708px 0px;
-    }
-  }
-</style>

+ 20 - 7
src/components/chatRoom/controls/actions.ts

@@ -116,6 +116,9 @@ export function handleActions({
     case 'sync-tag':
       handleSyncTag(data);
       break;
+    case 'sync-camera':
+      handleSyncCamera(data);
+      break;
     default:
       break;
   }
@@ -313,7 +316,7 @@ const handleUserMuted = (UserId?: string, muted?: boolean) => {
 
     // console.log('audio::status', UserId, muted);
     setTimeout(() => {
-      console.log('被禁人状态-->', UserId, muted);
+      console.log('被动语音状态-->', UserId, muted);
       const { unMutedAudio, mutedAudio } = useRtcSdk();
       if (muted) {
         mutedAudio();
@@ -351,8 +354,8 @@ const handleUserLeave = (user?: UserInfoType, members?: UserInfoType[]) => {
     if (rtcStore.isLeader) {
       console.log('主持人看到', data);
       rtcStore.addToChatList(data);
-      const { muteVideoLeader } = useRtcSdk();
-      muteVideoLeader.value = false;
+      // const { muteVideoLeader } = useRtcSdk();
+      // muteVideoLeader.value = false;
     } else {
       console.log('参与者看到', data);
       user.Role == 'leader' && rtcStore.addToChatList(data);
@@ -387,8 +390,8 @@ const handleUserExit = (user?: UserInfoType, members?: UserInfoType[]) => {
     if (rtcStore.isLeader) {
       console.log('主持人看到', data);
       rtcStore.addToChatList(data);
-      const { muteVideoLeader } = useRtcSdk();
-      muteVideoLeader.value = false;
+      // const { muteVideoLeader } = useRtcSdk();
+      // muteVideoLeader.value = false;
     } else {
       console.log('参与者看到', data);
       user.Role == 'leader' && rtcStore.addToChatList(data);
@@ -591,6 +594,16 @@ const handleSyncTag = (data) => {
       }
     }
   }
-
-  console.log('data', data);
+};
+const handleSyncCamera = (data: any) => {
+  const rtcStore = useRtcStore();
+  if (rtcStore.role !== 'leader') {
+    const { muteVideoLeader } = useRtcSdk();
+    if (data?.show) {
+      muteVideoLeader.value = false;
+    } else {
+      muteVideoLeader.value = true;
+    }
+    console.error('handleSyncCamera', data);
+  }
 };

+ 3 - 6
src/components/chatRoom/controls/join.ts

@@ -9,6 +9,8 @@ import { useRoom } from '/@/hooks/useRoom';
 import { useSocket } from '/@/hooks/userSocket';
 import { UserInfoType, useRtcStore } from '/@/store/modules/rtc';
 import { useAppStore } from '/@/store/modules/app';
+// import { useRtcSdk } from '/@/hooks/useTRTC';
+// import { useMiniApp } from '/@/hooks/useMiniApp';
 const { enterRoom } = useRoom();
 
 // 自已join的方法
@@ -39,7 +41,7 @@ export function handleJoin(data: any) {
         {
           title: t('base.tips'),
           desc: t('base.maxRooms'),
-          okTxt: t('base.freeWalk'),
+          okTxt: t('base.confirm'),
           closeTxt: t('base.cancel'),
           isSingle: true,
         },
@@ -52,11 +54,6 @@ export function handleJoin(data: any) {
       setTimeout(() => {
         closeSocket();
       }, 3000);
-      // Dialog.toast({ content: `房间已满员` });
-      // setTimeout(() => {
-      //   closeSocket();
-      // }, 1500);
-      // return;
     }
   } else {
     members && rtcStore.setMemberList(members);

+ 6 - 6
src/components/chatRoom/dialog/close.vue

@@ -49,12 +49,12 @@
   const endLiveConfirm = () => {
     emit('confirmDialog');
     window.parent &&
-        window.parent.postMessage(
-          {
-            type: 'exit',
-          },
-          '*',
-        );
+      window.parent.postMessage(
+        {
+          type: 'exit',
+        },
+        '*',
+      );
   };
 </script>
 

+ 0 - 1
src/components/chatRoom/dialog/createdName.vue

@@ -84,7 +84,6 @@
       Dialog.toast({ content: t('base.saveSuccess'), type: 'success' });
       ifShow.value = false;
       emit('confirmDialog', unref(userName));
-
     }
   };
 </script>

+ 7 - 2
src/components/chatRoom/dialog/password.vue

@@ -7,7 +7,7 @@
         <div class="dialog_title">请输入房间密码</div>
         <div class="pass_container">
           <input v-model.trim="password" class="pass-input" type="password" maxlength="4" />
-          <span class="limitNum"> {{ `${password.length} / 4`}}</span>
+          <span class="limitNum"> {{ `${password.length} / 4` }}</span>
           <!-- <v-otp-input
             class="otp-input-container"
             ref="otpInput"
@@ -28,7 +28,12 @@
           <div class="created_cancel" v-if="!isSingle" @click="closeCreated">{{
             t('base.cancel')
           }}</div>
-          <div class="created_confirm" :class="password.length !==4 ?'disable':''" @click="createdConfirm">{{ t('base.confirm') }}</div>
+          <div
+            class="created_confirm"
+            :class="password.length !== 4 ? 'disable' : ''"
+            @click="createdConfirm"
+            >{{ t('base.confirm') }}</div
+          >
         </div>
       </div>
     </div>

+ 18 - 13
src/components/chatRoom/index.vue

@@ -27,7 +27,10 @@
           <span v-if="isPanoramaMode && roomCounter > 0 && isNativeLeader"
             >{{ dayjs.duration(roomCounter, 'seconds').format('mm:ss') }} |
           </span>
-          <span>{{ members.length }}{{ t('base.view') }}</span>
+          <span
+            >{{ room?.maxMan && members.length > room.maxMan ? room?.maxMan : members.length
+            }}{{ t('base.view') }}</span
+          >
         </div>
       </div>
     </div>
@@ -208,6 +211,7 @@
   import dayjs from 'dayjs';
   import duration from 'dayjs/plugin/duration';
   import { useMiniApp } from '/@/hooks/useMiniApp';
+  import { v4 as uuidv4 } from 'uuid';
 
   const { closeSocket } = useSocket();
   dayjs.extend(duration);
@@ -348,11 +352,11 @@
   };
   console.log('initParams', rtcStore.userId);
   const nickname = decodeURIComponent(decodeURIComponent(browser.getURLParam('name')));
+
+  const randomUserId = `user_${uuidv4()}`;
+  // debugger;
   const initParams: SocketParams = {
-    userId:
-      browser.getURLParam('vruserId') ||
-      rtcStore.userId ||
-      `user_${Math.floor(Math.random() * 100000000)}`,
+    userId: browser.getURLParam('vruserId') || rtcStore.userId || randomUserId,
     roomId: browser.getURLParam('roomId') || `room_${Math.floor(Math.random() * 100000000)}`,
     role: (browser.getURLParam('role') as RoleType) || 'leader',
     avatar: browser.getURLParam('avatar'),
@@ -657,13 +661,15 @@
     const { muteVideo, muteVideoLeader } = useRtcSdk();
     const { socket } = useSocket();
     muteVideoLeader.value = true;
-    socket.emit('action', {
-      type: 'sync-camera',
-      data: {
-        show: false,
-        userId: rtcStore.userId,
-      },
-    });
+    if (!unref(isUsingMiniApp)) {
+      socket.emit('action', {
+        type: 'sync-camera',
+        data: {
+          show: false,
+          userId: rtcStore.userId,
+        },
+      });
+    }
     muteVideo();
   };
   const handleShowCamera = () => {
@@ -677,7 +683,6 @@
           userId: rtcStore.userId,
         },
       });
-      // localStream && localStream.unmuteVideo();
       unMuteVideo();
       muteVideoLeader.value = false;
     }

+ 26 - 3
src/components/chatRoom/roomControl.ts

@@ -31,7 +31,12 @@ export function initSocketEvent(socket: SocketIOClient.Socket): void {
       const { room } = useRoom();
       const useEndTime = unref(room)?.useEndTime || '';
       const useStartTime = unref(room)?.useStartTime;
-      const limit = unref(room)?.maxMan || 10;
+      let limit = unref(room)?.maxMan || 10;
+      if (Number(import.meta.env.VITE_ROOM_MEMBER_DEBUG) === 1) {
+        limit = Number(import.meta.env.VITE_ROOM_MEMBER);
+      }
+      console.warn(`传入服务器房间人数:${limit}`);
+
       const now = dayjs();
       const roomEnd = dayjs(useEndTime);
       const ttl = roomEnd.diff(now, 'second');
@@ -121,8 +126,26 @@ export function initSocketEvent(socket: SocketIOClient.Socket): void {
           handleMaxRoomsError();
           break;
         case 'room-maxing':
-          Dialog.toast({ content: t('action.errorRoomMaxing') });
-          handleMaxRoomsError();
+          // Dialog.toast({ content: t('action.errorRoomMaxing') });
+          const rtcStore = useRtcStore();
+          rtcStore.showBaseDialog(
+            {
+              title: t('base.tips'),
+              desc: t('action.errorRoomMaxing'),
+              okTxt: t('base.confirm'),
+              closeTxt: t('base.cancel'),
+              isSingle: true,
+            },
+            () => {
+              setTimeout(() => {
+                handleMaxRoomsError();
+              }, 1500);
+            },
+          );
+          setTimeout(() => {
+            handleMaxRoomsError();
+          }, 3000);
+
           break;
         case 'invalid-master':
           Dialog.toast({ content: t('action.errorInvalidMaster') });

+ 62 - 23
src/hooks/useAgora.ts

@@ -3,8 +3,9 @@ import AgoraRTC, { IAgoraRTCClient, ILocalAudioTrack, ILocalVideoTrack } from 'a
 import { useRtcStore } from '/@/store/modules/rtc';
 export type AgoraClient = IAgoraRTCClient;
 export { ILocalAudioTrack, ILocalVideoTrack } from 'agora-rtc-sdk-ng';
-import { useRtcSdk } from './useTRTC';
+// import { useRtcSdk } from './useTRTC';
 import { ref } from 'vue';
+import { muteVideoLeader } from './useTRTC';
 
 export let localAudioTrack: ILocalAudioTrack;
 export let localVideoTrack: ILocalVideoTrack;
@@ -21,13 +22,18 @@ export const createAgoraClient = async (
   userId: string,
 ): Promise<IAgoraRTCClient> => {
   const rtcStore = useRtcStore();
-  const { muteVideoLeader } = useRtcSdk();
+  // const { muteVideoLeader } = useRtcSdk();
 
   const isOK = AgoraRTC.checkSystemRequirements();
   if (!isOK) {
     console.log('当前不支持');
   }
-  const client: IAgoraRTCClient = AgoraRTC.createClient({ mode: 'rtc', codec: 'vp9' });
+
+  AgoraRTC.setLogLevel(4);
+
+  const role = rtcStore.role === 'leader' ? 'host' : 'audience';
+  const client: IAgoraRTCClient = AgoraRTC.createClient({ mode: 'rtc', codec: 'vp9', role: role });
+
   localClient = client;
   const uid = await client.join(String(sdkAppId), roomId, sign, userId);
   userID.value = userId;
@@ -39,7 +45,7 @@ export const createAgoraClient = async (
     });
   });
   client.on('exception', (error) => {
-    console.error(error);
+    console.error('sdk error', error);
   });
   client.on('user-joined', (user) => {
     console.log('userJoin', user);
@@ -47,62 +53,95 @@ export const createAgoraClient = async (
   client.on('user-info-updated', (user) => {
     console.log('userJoin', user);
   });
+  //取消订阅
   client.on('user-unpublished', async (user, mediaType) => {
+    // await client.unsubscribe(user, mediaType);
     if (mediaType === 'audio') {
-      console.error('unpublished', user);
+      console.error('unpublished-audio', user);
     }
     if (mediaType === 'video') {
-      // console.error('unpublished', user);
       //暂时只有leader有video
-      muteVideoLeader.value = true;
+      const remoteVideoEl = document.getElementById(`cameraRemoteBox`);
+      if (remoteVideoEl) {
+        remoteVideoEl.style.display = 'none';
+      }
+      const leader = rtcStore.getRoomLeader();
+      console.error('unpublished-video', leader, user.uid === leader?.Id);
+      if (user.uid === leader?.Id) {
+      }
     }
   });
+  //发布订阅
   client.on('user-published', async (user, mediaType) => {
+    console.warn('远程音视频-published', user, mediaType);
     await client.subscribe(user, mediaType);
     if (mediaType === 'video') {
       console.error('subscribe video success', user);
       const remoteVideoEl = document.getElementById(`cameraRemoteBox`);
-      if (user.videoTrack && remoteVideoEl) {
+      if (user.videoTrack && user.hasVideo && remoteVideoEl) {
         // remoteVideoEl.style.display = 'block';
-        console.warn('video play');
+        remoteVideoEl.style.display = 'block';
+        console.warn(`收到远程视频-->当前用ID${user.uid}`);
         user.videoTrack.play(remoteVideoEl);
-        muteVideoLeader.value = false;
+        // muteVideoLeader.value = false;
       }
     }
     if (mediaType === 'audio') {
+      console.warn(`收到远程音频-->当前用ID${user.uid}`);
       user.audioTrack?.play();
     }
   });
+
   try {
     isHasCamera.value = (await AgoraRTC.getCameras()).length > 0;
     isHasMicrophone.value = (await AgoraRTC.getMicrophones()).length > 0;
 
-    isHasCamera.value && (localVideoTrack = await AgoraRTC.createCameraVideoTrack());
+    if (isHasCamera.value) {
+      localVideoTrack = await AgoraRTC.createCameraVideoTrack();
+      localVideoTrack.setEncoderConfiguration('120p');
+    }
+
     isHasMicrophone.value && (localAudioTrack = await AgoraRTC.createMicrophoneAudioTrack());
   } catch (error) {}
 
   const localVideoEl = document.getElementById(`camera_box_${userId}`);
   console.warn('isHasCamera', isHasCamera.value);
   console.warn('isHasMicrophone', isHasMicrophone.value);
+
   if (rtcStore.role === 'leader') {
     if (isHasCamera.value) {
       rtcStore.setHasCamera();
       if (localVideoEl) {
-        localVideoTrack.play(localVideoEl);
+        try {
+          console.warn('播放本地rtc-localVideoTrack');
+          localVideoTrack.play(localVideoEl);
+        } catch (error) {
+          console.error(error);
+        }
       }
-
-      isHasCamera.value && (await client.publish(localVideoTrack));
-      isHasMicrophone.value && (await client.publish(localAudioTrack));
-    } else {
-      isHasMicrophone.value && (await client.publish([localAudioTrack]));
+      //主持人有相机的
+      console.warn('主持人看到::');
+      console.warn('有VID leader发布流');
+      await client.publish(localVideoTrack);
+      localVideoTrack.setMuted(true);
     }
-  } else {
-    isHasMicrophone.value && (await client.publish([localAudioTrack]));
   }
-  isHasMicrophone.value && localAudioTrack.setMuted(true);
+
+  if (isHasMicrophone.value) {
+    console.warn('所有有MIC静音和发布');
+    await client.publish(localAudioTrack);
+    // 先play
+    localAudioTrack.setVolume(120);
+    localAudioTrack.play();
+    localAudioTrack.setMuted(true);
+  }
+  //默认头闭摄像头
+  muteVideoLeader.value = true;
   rtcStore.setIsRTCJoined(true);
+
   return client;
 };
+
 export const muteVideo = () => {
   //通用开音方法
   localVideoTrack.setMuted(true);
@@ -116,7 +155,6 @@ export const mutedAudio = () => {
   console.error('mutedAudio');
   if (isHasMicrophone.value) {
     localAudioTrack.setMuted(true);
-    // localAudioTrack.stop();
   }
 };
 export const unMutedAudio = () => {
@@ -124,7 +162,6 @@ export const unMutedAudio = () => {
   console.error('unMutedAudio');
   if (isHasMicrophone.value) {
     localAudioTrack.setMuted(false);
-    // localAudioTrack.play();
   }
 };
 
@@ -142,7 +179,6 @@ export const switchToFrontCam = async () => {
 };
 
 export const switchToBackCam = async () => {
-  // localStream.switchDevice('video', 'environment');
   localClient.unpublish(localVideoTrack);
   localVideoTrack = await AgoraRTC.createCameraVideoTrack({
     facingMode: 'environment',
@@ -153,3 +189,6 @@ export const switchToBackCam = async () => {
   }
   await localClient.publish(localVideoTrack);
 };
+export const cleanAll = () => {
+  AgoraRTC.removeAllListeners();
+};

+ 12 - 0
src/hooks/useRoom.ts

@@ -2,6 +2,7 @@ import browser from '/@/utils/browser';
 import axios, { AxiosResponse } from 'axios';
 import { ref, computed, unref } from 'vue';
 import { useRtcStore } from '../store/modules/rtc';
+// import { useRtcSdk } from './useTRTC';
 
 const roomParam = browser.getURLParam('roomId');
 
@@ -109,6 +110,17 @@ export const changeScene = (scene: SceneItemType) => {
     params.set('m', scene.num);
     const url = new URL(location.href);
     url.search = `?` + params.toString();
+    // if (browser.isMobile()) {
+    //   if (browser.detectIOS()) {
+    //     location.replace(url);
+    //   } else {
+    //     console.warn('安卓跳转减少内存');
+    //     history.replaceState(null, document.title, url);
+    //     history.go(0);
+    //   }
+    // } else {
+    // location.replace(url);
+    // }
     location.replace(url);
     rtcStore.clearMemberList();
   } else {

+ 9 - 2
src/hooks/useTRTC.ts

@@ -14,6 +14,7 @@ import {
   muteVideo as argoraMuteVideo,
   switchToFrontCam as argoraSwitchToFrontCam,
   switchToBackCam as argoraSwitchToBackCam,
+  cleanAll as argoraCleanAll,
 } from './useAgora';
 import {
   createRTCSocket as createTXRTCSocket,
@@ -32,7 +33,7 @@ let localClient: Client | AgoraClient;
 const sdkType = ref(0);
 
 // const muteAudioLeader = ref(false);
-export const muteVideoLeader = ref(false);
+export const muteVideoLeader = ref(true);
 export const useCameraFront = ref(true);
 
 const { isUsingMiniApp } = useMiniApp();
@@ -55,7 +56,7 @@ async function createRTCSocket(): Promise<void> {
       const { getSign } = useRoom();
       const rtcStore = useRtcStore();
       const res = await getSign(rtcStore.userId, rtcStore.roomId, rtcStore.role, 'fire');
-      console.warn('web rtc入口', res);
+      // console.warn('web rtc入口', res);
       const { sign, operatorType, sdkAppId } = res;
       sdkType.value = Number(operatorType);
       if (Number(operatorType) === 1) {
@@ -150,6 +151,11 @@ const switchToBackCam = () => {
   useCameraFront.value = false;
 };
 
+const cleanAll = () => {
+  if (sdkType.value === 1) {
+    argoraCleanAll();
+  }
+};
 export function useRtcSdk() {
   return {
     initRtcSDK,
@@ -164,5 +170,6 @@ export function useRtcSdk() {
     useCameraFront,
     client: localClient,
     globalVideoEnable,
+    cleanAll,
   };
 }