Commit 857a7f32 by pangchong

feat: 视频通话默认图

parent 0d651b6a
...@@ -93,7 +93,7 @@ router.beforeEach(async (to, from, next) => { ...@@ -93,7 +93,7 @@ router.beforeEach(async (to, from, next) => {
next({ path: './' }) next({ path: './' })
} else { } else {
//视频通话页面 //视频通话页面
if (to.name == 'VideoCall') { if (to.name == 'VideoCall1') {
if (AnyR.agora && chatChannelState.value.currentState == CallState.calling) { if (AnyR.agora && chatChannelState.value.currentState == CallState.calling) {
next() next()
} else { } else {
......
...@@ -6,9 +6,10 @@ ...@@ -6,9 +6,10 @@
<a-col :flex="10" class="h-full ml-4"> <a-col :flex="10" class="h-full ml-4">
<video-info></video-info> <video-info></video-info>
</a-col> </a-col>
<a-col :flex="3" class="h-full" v-if="!fullScreen"> <a-col :flex="3" class="h-full" v-show="!fullScreen">
<video-chat></video-chat> <video-chat></video-chat>
</a-col> </a-col>
<template></template>
</a-row> </a-row>
</template> </template>
......
<template> <template>
<div class="g-block ml-4 pb-0"> <div class="g-block ml-4 pb-0">
<div class="px-4 h-[300px]"> <div class="px-4 h-[172px]">
<video-item :id="''" :is-self="true"></video-item> <video-item :id="''" :is-self="true"></video-item>
</div> </div>
<a-row class="mt-2 px-4"> <a-row class="mt-2 px-4">
......
<template> <template>
<div :id="ps.isSelf ? 'LocalVideo' : `RemoteVideo${ps.id}`" class="relative h-full video-cont"> <div :id="ps.isSelf ? 'LocalVideo' : `RemoteVideo${ps.id}`" class="relative h-full video-cont bg-fill-bg1" ref="remoteVideoRef">
<template v-if="isVideoVisible">
<div class="absolute flex justify-between items-center p-1 top-0 left-0 w-full z-10"> <div class="absolute flex justify-between items-center p-1 top-0 left-0 w-full z-10">
<div class="text-xs px-2 rounded-sm leading-5 bg-primary-disable text-primary" v-if="userDataForThis.userCallGroup == 1"> <div class="text-xs px-2 rounded-sm leading-5 bg-primary-disable text-primary" v-if="userDataForThis.userCallGroup == 1">
{{ userDataForThis.name }} {{ userDataForThis.name }}
...@@ -29,6 +30,10 @@ ...@@ -29,6 +30,10 @@
<global-icon :size="20" color="var(--color-bg-white)" icon="phone-hangup"></global-icon> <global-icon :size="20" color="var(--color-bg-white)" icon="phone-hangup"></global-icon>
</a-button> </a-button>
</div> </div>
</template>
<div class="absolute w-full h-full flex-center" v-else>
<video-loader></video-loader>
</div>
</div> </div>
</template> </template>
...@@ -37,13 +42,14 @@ import { chatChannelState, isUserHost } from 'AnyR/states/chatChannelStates' ...@@ -37,13 +42,14 @@ import { chatChannelState, isUserHost } from 'AnyR/states/chatChannelStates'
import { userStates } from 'AnyR/states/wsStates' import { userStates } from 'AnyR/states/wsStates'
import { computed, onMounted, onUpdated } from 'vue' import { computed, onMounted, onUpdated } from 'vue'
import { useAnyR } from 'AnyR/index' import { useAnyR } from 'AnyR/index'
import VideoLoader from './videoLoader.vue'
const ps = defineProps({ const ps = defineProps({
isSelf: Boolean, isSelf: Boolean,
id: String id: String
}) })
const isThisUserMuted = computed(function() { const isThisUserMuted = computed(function () {
return chatChannelState.value.mutedUserIdSet.includes(ps.id) || chatChannelState.value.mutedUserIdSet.includes(userStates.value.currentUserId) return chatChannelState.value.mutedUserIdSet.includes(ps.id) || chatChannelState.value.mutedUserIdSet.includes(userStates.value.currentUserId)
}) })
...@@ -69,10 +75,19 @@ function cancelCallExact() { ...@@ -69,10 +75,19 @@ function cancelCallExact() {
AnyR?.agora.cancelExactCall(ps.id) AnyR?.agora.cancelExactCall(ps.id)
} }
//监听视频是否渲染成功
const remoteVideoRef = ref()
const isVideoVisible = ref(false)
const checkVideoExists = () => {
const video = remoteVideoRef.value.querySelector('video')
isVideoVisible.value = video ? true : false
}
const observer = new MutationObserver(checkVideoExists)
onMounted(function () { onMounted(function () {
if (!ps.isSelf) { if (!ps.isSelf) {
AnyR?.agora.forceReplay(ps.id) AnyR?.agora.forceReplay(ps.id)
} }
observer.observe(remoteVideoRef.value, { childList: true, subtree: true })
}) })
onUpdated(function () { onUpdated(function () {
...@@ -80,6 +95,9 @@ onUpdated(function () { ...@@ -80,6 +95,9 @@ onUpdated(function () {
AnyR?.agora.forceReplay(ps.id) AnyR?.agora.forceReplay(ps.id)
} }
}) })
onUnmounted(() => {
observer.disconnect() // 停止监听
})
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
:deep(.video-cont video) { :deep(.video-cont video) {
......
<template>
<div class="flex-center flex-col">
<div style="height: 70px"><div class="loader"></div></div>
<span>正在通话中...</span>
</div>
</template>
<script setup lang="ts"></script>
<style lang="less" scoped>
.loader {
width: 8px;
height: 40px;
border-radius: 4px;
display: block;
background-color: currentColor;
margin: 20px auto;
position: relative;
color: rgb(var(--primary-6));
animation: animloader 0.3s 0.3s linear infinite alternate;
}
.loader::after,
.loader::before {
content: '';
width: 8px;
height: 40px;
border-radius: 4px;
background: currentColor;
position: absolute;
top: 50%;
transform: translateY(-50%);
left: 20px;
animation: animloader 0.3s 0.45s linear infinite alternate;
}
.loader::before {
left: -20px;
animation-delay: 0s;
}
@keyframes animloader {
0% {
height: 48px;
}
100% {
height: 4px;
}
}
</style>
<template> <template>
<div> <div>
<div :id="`RemoteVideo${ps.id}`" class="relative mb-4 flex-auto" data-self="remote-main" @mousedown.capture="handleBlinkingStart"> <div :id="`RemoteVideo${ps.id}`" class="relative mb-4 flex-auto bg-fill-bg1" data-self="remote-main" @mousedown.capture="handleBlinkingStart" ref="remoteVideoRef">
<n-message-provider> <n-message-provider>
<image-editor <image-editor
:before-cancel="beforeEndMarkHandle" :before-cancel="beforeEndMarkHandle"
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
class="red-ball absolute z-[999]" class="red-ball absolute z-[999]"
@animationend="centerEnded" @animationend="centerEnded"
></div> ></div>
<template v-if="isVideoVisible">
<div class="absolute flex justify-between items-center p-1 t-0 l-0 w-full z-10"> <div class="absolute flex justify-between items-center p-1 t-0 l-0 w-full z-10">
<div v-if="userDataForThis.userCallGroup == 1" class="text-xs px-2 rounded-sm leading-5 bg-primary-disable text-primary"> <div v-if="userDataForThis.userCallGroup == 1" class="text-xs px-2 rounded-sm leading-5 bg-primary-disable text-primary">
{{ userDataForThis.name }} {{ userDataForThis.name }}
...@@ -38,12 +39,10 @@ ...@@ -38,12 +39,10 @@
<global-icon v-else :size="12" :icon="'mic-off'"></global-icon> <global-icon v-else :size="12" :icon="'mic-off'"></global-icon>
</div> </div>
</div> </div>
<!-- <div class="absolute top-0 left-0 right-0 bottom-0 flex-center flex-col"> </template>
<div class="text-base text-theme-text1">呼叫中...</div> <div class="absolute w-full h-full flex-center" v-else>
<a-button shape="circle" status="danger" type="primary" @click="hangupCall"> <video-loader></video-loader>
<global-icon :size="20" color="var(--color-bg-white)" icon="phone-hangup"></global-icon> </div>
</a-button>
</div> -->
</div> </div>
<div class="flex justify-center w-full"> <div class="flex justify-center w-full">
<div v-if="!isUserHost" class="w-[120px] h-[72px] item" @click="hangupCall"> <div v-if="!isUserHost" class="w-[120px] h-[72px] item" @click="hangupCall">
...@@ -74,7 +73,7 @@ ...@@ -74,7 +73,7 @@
</div> </div>
<div class="w-[120px] h-[72px] item" @click="toggleRecording"> <div class="w-[120px] h-[72px] item" @click="toggleRecording">
<global-icon :size="21" icon="record"></global-icon> <global-icon :size="21" icon="record"></global-icon>
<span class="mt-1 color-text-2">{{!chatChannelState.recordingData.id ? '开始录制' : '结束录制'}}</span> <span class="mt-1 color-text-2">{{ !chatChannelState.recordingData.id ? '开始录制' : '结束录制' }}</span>
</div> </div>
<div v-if="isUserHost" class="w-[120px] h-[72px] item" @click="allMute"> <div v-if="isUserHost" class="w-[120px] h-[72px] item" @click="allMute">
<global-icon :size="21" icon="mic-off"></global-icon> <global-icon :size="21" icon="mic-off"></global-icon>
...@@ -97,6 +96,7 @@ import { userStates } from 'AnyR/states/wsStates' ...@@ -97,6 +96,7 @@ import { userStates } from 'AnyR/states/wsStates'
import ImageEditor from 'AnyR/widgets/ImageEditor/imageEditor.vue' import ImageEditor from 'AnyR/widgets/ImageEditor/imageEditor.vue'
import { Message, Modal } from '@arco-design/web-vue' import { Message, Modal } from '@arco-design/web-vue'
import { alova } from '@/api/alova-instance.ts' import { alova } from '@/api/alova-instance.ts'
import VideoLoader from './videoLoader.vue'
const ps = defineProps<{ const ps = defineProps<{
id: any id: any
...@@ -104,19 +104,19 @@ const ps = defineProps<{ ...@@ -104,19 +104,19 @@ const ps = defineProps<{
async function toggleRecording() { async function toggleRecording() {
if (!chatChannelState.value.recordingData.id) { if (!chatChannelState.value.recordingData.id) {
const resp = await AnyR?.agora.recordCurrent(); const resp = await AnyR?.agora.recordCurrent()
if (resp) { if (resp) {
Message.success("录制成功开始!") Message.success('录制成功开始!')
} else { } else {
Message.error("录制失败!") Message.error('录制失败!')
} }
} else { } else {
const resp = await AnyR?.agora.stopRecordCurrent() const resp = await AnyR?.agora.stopRecordCurrent()
console.log("录制结果提示?", resp); console.log('录制结果提示?', resp)
} }
} }
const isCenterUserMuted = computed(function() { const isCenterUserMuted = computed(function () {
return chatChannelState.value.mutedUserIdSet.includes(ps.id) return chatChannelState.value.mutedUserIdSet.includes(ps.id)
}) })
...@@ -179,16 +179,16 @@ async function beforeEndMarkHandle() { ...@@ -179,16 +179,16 @@ async function beforeEndMarkHandle() {
return new Promise(function (resolve) { return new Promise(function (resolve) {
Modal.warning({ Modal.warning({
title: '退出确认', title: '退出确认',
content: "你是截图发起者,退出后将会要求其他用户一同退出,确认?", content: '你是截图发起者,退出后将会要求其他用户一同退出,确认?',
okText: "确认", okText: '确认',
cancelText: "取消", cancelText: '取消',
hideCancel: false, hideCancel: false,
onOk() { onOk() {
resolve(true) resolve(true)
}, },
onCancel() { onCancel() {
resolve(false) resolve(false)
}, }
}) })
}) })
} }
...@@ -239,14 +239,27 @@ const userDataForThis = computed(function () { ...@@ -239,14 +239,27 @@ const userDataForThis = computed(function () {
} }
}) })
//监听视频是否渲染成功
const remoteVideoRef = ref()
const isVideoVisible = ref(false)
const checkVideoExists = () => {
const video = remoteVideoRef.value.querySelector('video')
isVideoVisible.value = video ? true : false
}
const observer = new MutationObserver(checkVideoExists)
onMounted(function () { onMounted(function () {
AnyR?.agora.forceReplay(ps.id) AnyR?.agora.forceReplay(ps.id)
observer.observe(remoteVideoRef.value, { childList: true, subtree: true })
}) })
onUpdated(function () { onUpdated(function () {
AnyR?.agora.forceReplay(ps.id) AnyR?.agora.forceReplay(ps.id)
}) })
onUnmounted(() => {
observer.disconnect() // 停止监听
})
const isVoiceChatOnly = ref(false) const isVoiceChatOnly = ref(false)
const AnyR = useAnyR() const AnyR = useAnyR()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment