Bladeren bron

tag:no use rtc-dialog

bzkf3 2 jaren geleden
bovenliggende
commit
f702b19b30
2 gewijzigde bestanden met toevoegingen van 284 en 0 verwijderingen
  1. 34 0
      src/components/chat-dialog/index.vue
  2. 250 0
      src/components/rtc-dialog/index.vue

+ 34 - 0
src/components/chat-dialog/index.vue

@@ -0,0 +1,34 @@
+<script setup lang="ts">
+import { UseDraggable } from '@vueuse/components'
+
+let isOpen = $ref<boolean>(false)
+
+function handleClose(){
+    isOpen = false
+}
+defineExpose({
+  open() {
+    isOpen = true
+  },
+  close() {
+    handleClose()
+  }
+})
+</script>
+
+<template>
+  <UseDraggable v-if="isOpen" storage-key="chat-audio" storage-type="session" :initial-value="{ x: 584, y: 207 }"
+    class="fixed w-375px h-670px bg-hex-191919 cursor-move z-4000">
+    <div class="w-full flex justify-end items-center p-2 text-light-50 h-36px">
+      <i:clarity:window-min-line class="cursor-pointer" />
+      <i:ic:outline-close class="cursor-pointer" @click="handleClose" />
+    </div>
+    <div class="h-634px">
+      <slot></slot>
+    </div>
+  </UseDraggable>
+</template>
+
+<style scoped>
+
+</style>

+ 250 - 0
src/components/rtc-dialog/index.vue

@@ -0,0 +1,250 @@
+<script setup lang="ts">
+import AgoraRTC from "agora-rtc-sdk-ng"
+import type { IAgoraRTCClient, IMicrophoneAudioTrack, ICameraVideoTrack } from "agora-rtc-sdk-ng"
+import { CHAT_STATUS, CHAT_OPERATION } from '~/types';
+import { UseDraggable } from '@vueuse/components'
+import request from '~/utils/request';
+import type { type_dyaw_xlfw_zxhd } from '~/types';
+import user, { UserRole } from '~/store/user';
+import { socketSend } from '~/utils/ws';
+
+const props = defineProps<{
+  mode: 'audio' | 'video'
+}>()
+
+let dyaw_xlfw_zxhd = $ref<type_dyaw_xlfw_zxhd>()
+
+const otherInfo = $computed(() => {
+  if (UserRole === 'teacher')
+    return { id: dyaw_xlfw_zxhd?.dxz_tea_user_id, realname: dyaw_xlfw_zxhd?.dxz_tea_user_realname, avatar: dyaw_xlfw_zxhd?.dxx_tea_avatar }
+  if (UserRole === 'student')
+    return { id: dyaw_xlfw_zxhd?.dxz_stu_user_id, realname: dyaw_xlfw_zxhd?.dxz_stu_user_realname, avatar: dyaw_xlfw_zxhd?.dxx_user_avatar }
+})
+
+let isOpen = $ref<boolean>(false)
+let auditChatStatus = $ref<CHAT_STATUS>(CHAT_STATUS.WAITING_OTHERS_ACCEPT)
+
+let ws2: WebSocket;
+function handleClose() {
+  isOpen = false
+}
+defineExpose({
+  open(d: type_dyaw_xlfw_zxhd) {
+    // isOpen = true
+    dyaw_xlfw_zxhd = d
+    handleAuditChatStart()
+  },
+  close() {
+    handleClose()
+  },
+  publisher(ws: WebSocket, operate: CHAT_OPERATION) {
+    ws2 = ws
+    switch (operate) {
+      case CHAT_OPERATION.START:
+        auditChatStatus = CHAT_STATUS.WAITING_YOU_ACCEPT
+        isOpen = true
+        break;
+      case CHAT_OPERATION.CANCEL:
+        isOpen = false
+        break;
+      case CHAT_OPERATION.ACCEPT:
+        auditChatStatus = CHAT_STATUS.CHATING
+        break;
+      case CHAT_OPERATION.DENY:
+        isOpen = false
+        break;
+      case CHAT_OPERATION.END:
+        isOpen = false
+        break;
+      default:
+        break;
+    }
+  }
+})
+
+
+const LocalPlayerContainerRef = $ref<HTMLElement>()
+const RemotePlayerContainerRef = $ref<HTMLElement>()
+// ==========
+// chat audit/video
+// ==========
+let rtcInstance: {
+  client?: IAgoraRTCClient;
+  localAudioTrack?: IMicrophoneAudioTrack;
+  localVideoTrack?: ICameraVideoTrack
+} = {
+  client: undefined,
+  localAudioTrack: undefined,
+  localVideoTrack: undefined,
+}
+
+
+async function handleAuditChatStart() {
+  try {
+    let rtcOptions;
+    await request({
+      url: '/dyaw/xlfw_zxhd/get_rtc_token',
+      data: {
+        dxz_id: dyaw_xlfw_zxhd?.dxz_id
+      }
+    }).then(async res => {
+      if (res.code === '1') {
+        let resp: { jgim_roomid: string; rtc_appid: string; rtc_token: string } = res.data.one_info
+        rtcOptions = {
+          appId: resp.rtc_appid,
+          channel: resp.jgim_roomid,
+          token: resp.rtc_token,
+          uid: user.user_id
+        }
+
+        let client = rtcInstance.client = AgoraRTC.createClient({ mode: "rtc", codec: "vp8" });
+
+        client.on("user-published", async (user, mediaType) => {
+          // 发起订阅
+          await client.subscribe(user, mediaType);
+
+          // 如果订阅的是音频轨道
+          if (mediaType === "audio") {
+            const audioTrack = user.audioTrack;
+            // 自动播放音频
+            audioTrack?.play();
+          } else {
+            const videoTrack = user.videoTrack;
+            // 自动播放视频
+            videoTrack?.play(RemotePlayerContainerRef as HTMLElement);
+          }
+        });
+
+        await rtcInstance.client.join(rtcOptions.appId, rtcOptions.channel, rtcOptions?.token, rtcOptions.uid);
+        rtcInstance.localAudioTrack = await AgoraRTC.createMicrophoneAudioTrack();
+        // rtcInstance.localVideoTrack = await AgoraRTC.createCameraVideoTrack();
+        await rtcInstance.client.publish([rtcInstance.localAudioTrack]);
+        // rtcInstance.localVideoTrack.play(LocalPlayerContainerRef as HTMLElement);
+      }
+    })
+    isOpen = true
+    socketSend(ws2, {
+      dxzl_stu_user_id: dyaw_xlfw_zxhd!.dxz_stu_user_id,
+      dxzl_tea_user_id: dyaw_xlfw_zxhd!.dxz_tea_user_id,
+      operate: CHAT_OPERATION.START,
+      rtcOptions
+    })
+  } catch (error) {
+    console.error(error);
+  }
+
+}
+function handleAuditChatCancel() {
+  socketSend(ws2, {
+    dxzl_stu_user_id: dyaw_xlfw_zxhd!.dxz_stu_user_id,
+    dxzl_tea_user_id: dyaw_xlfw_zxhd!.dxz_tea_user_id,
+    operate: CHAT_OPERATION.CANCEL
+  })
+  isOpen = false
+}
+function handleAuditChatAccept() {
+  socketSend(ws2, {
+    dxzl_stu_user_id: dyaw_xlfw_zxhd!.dxz_stu_user_id,
+    dxzl_tea_user_id: dyaw_xlfw_zxhd!.dxz_tea_user_id,
+    operate: CHAT_OPERATION.ACCEPT
+  })
+  auditChatStatus = CHAT_STATUS.CHATING
+}
+function handleAuditChatDeny() {
+  socketSend(ws2, {
+    dxzl_stu_user_id: dyaw_xlfw_zxhd!.dxz_stu_user_id,
+    dxzl_tea_user_id: dyaw_xlfw_zxhd!.dxz_tea_user_id,
+    operate: CHAT_OPERATION.DENY
+  })
+  isOpen = false
+}
+function handleAuditChatEnd() {
+  socketSend(ws2, {
+    dxzl_stu_user_id: dyaw_xlfw_zxhd!.dxz_stu_user_id,
+    dxzl_tea_user_id: dyaw_xlfw_zxhd!.dxz_tea_user_id,
+    operate: CHAT_OPERATION.END
+  })
+  isOpen = false
+}
+
+
+
+</script>
+
+<template>
+  <UseDraggable v-if="isOpen" storage-key="chat-audio" storage-type="session" :initial-value="{ x: 584, y: 207 }"
+    class="fixed w-375px h-670px bg-hex-191919 cursor-move z-4000">
+    <div class="w-full flex justify-end items-center p-2 text-light-50 h-36px">
+      <i:clarity:window-min-line class="cursor-pointer" />
+      <i:ic:outline-close class="cursor-pointer" @click="handleClose" />
+    </div>
+    <div class="h-634px">
+      <slot>
+        <div class="h-full flex_center flex-col text-light-50 space-y-4">
+          <el-avatar :size="158" :src="otherInfo?.avatar"></el-avatar>
+          <div>{{ otherInfo?.realname }}</div>
+          <!-- <div class="text-hex-909090 flex_center flex-col space-y-2 h-16"> -->
+          <div class="text-hex-909090 flex_center flex-col space-y-2 h-16"
+            v-show="auditChatStatus === CHAT_STATUS.WAITING_OTHERS_ACCEPT">
+            <div>正在等待对方接受邀请</div>
+            <i:line-md:loading-alt-loop class="text-xl" />
+          </div>
+          <div class="text-hex-909090 flex_center flex-col space-y-2 h-16"
+            v-show="auditChatStatus === CHAT_STATUS.WAITING_YOU_ACCEPT">
+            <div>邀请你语音通话...</div>
+          </div>
+          <div class="text-hex-909090 flex_center flex-col space-y-2 h-16"
+            v-show="auditChatStatus === CHAT_STATUS.WAITING_BUSY">
+            <div class="text-red-500">对方忙线中请等待</div>
+            <div class="text-red-500">当前排队:{{ 4 }}</div>
+            <i:line-md:loading-alt-loop class="text-xl" />
+          </div>
+          <div class="text-hex-909090 flex_center flex-col space-y-2 h-16"
+            v-show="auditChatStatus === CHAT_STATUS.CHATING">
+            <div>正在通话中</div>
+            <div>{{ '00:30' }}</div>
+          </div>
+          <!-- </div> -->
+          <!--  -->
+          <div ref="LocalPlayerContainerRef"></div>
+          <div ref="RemotePlayerContainerRef"></div>
+          <!--  -->
+          <div class="pt-16 text-xl flex justify-around w-full">
+            <div v-show="auditChatStatus === CHAT_STATUS.WAITING_YOU_ACCEPT"
+              class="bg-green-600 w-12 h-12 rounded-1 cursor-pointer flex items-center justify-around"
+              @click="handleAuditChatAccept">
+              <i:ic:baseline-phone />
+            </div>
+            <div v-show="auditChatStatus === CHAT_STATUS.WAITING_YOU_ACCEPT"
+              class="bg-red-600 w-12 h-12 rounded-1 cursor-pointer flex items-center justify-around"
+              @click="handleAuditChatDeny">
+              <i:mdi:phone-hangup />
+            </div>
+            <div v-show="auditChatStatus === CHAT_STATUS.CHATING"
+              class="bg-hex-efefef text-hex-272636 w-12 h-12 rounded-1 cursor-pointer flex items-center justify-around"
+              @click="">
+              <i:ant-design:audio-outlined v-show="true" />
+              <i:ant-design:audio-muted-outlined v-show="false" />
+            </div>
+            <div v-show="auditChatStatus === CHAT_STATUS.CHATING"
+              class="bg-red-600 w-12 h-12 rounded-1 cursor-pointer flex items-center justify-around"
+              @click="handleAuditChatEnd">
+              <i:ic:outline-close></i:ic:outline-close>
+            </div>
+            <div
+              v-show="auditChatStatus === CHAT_STATUS.WAITING_OTHERS_ACCEPT || auditChatStatus === CHAT_STATUS.WAITING_BUSY"
+              class="bg-red-600 w-12 h-12 rounded-1 cursor-pointer flex items-center justify-around"
+              @click="handleAuditChatCancel">
+              <i:ic:outline-close></i:ic:outline-close>
+            </div>
+
+          </div>
+        </div>
+      </slot>
+    </div>
+  </UseDraggable>
+</template>
+
+<style scoped>
+
+</style>