Commit 857a7f32 by pangchong

feat: 视频通话默认图

parent 0d651b6a
......@@ -93,7 +93,7 @@ router.beforeEach(async (to, from, next) => {
next({ path: './' })
} else {
//视频通话页面
if (to.name == 'VideoCall') {
if (to.name == 'VideoCall1') {
if (AnyR.agora && chatChannelState.value.currentState == CallState.calling) {
next()
} else {
......
......@@ -6,9 +6,10 @@
<a-col :flex="10" class="h-full ml-4">
<video-info></video-info>
</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>
</a-col>
<template></template>
</a-row>
</template>
......
<template>
<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>
</div>
<a-row class="mt-2 px-4">
......
<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="text-xs px-2 rounded-sm leading-5 bg-primary-disable text-primary" v-if="userDataForThis.userCallGroup == 1">
{{ userDataForThis.name }}
......@@ -29,6 +30,10 @@
<global-icon :size="20" color="var(--color-bg-white)" icon="phone-hangup"></global-icon>
</a-button>
</div>
</template>
<div class="absolute w-full h-full flex-center" v-else>
<video-loader></video-loader>
</div>
</div>
</template>
......@@ -37,13 +42,14 @@ import { chatChannelState, isUserHost } from 'AnyR/states/chatChannelStates'
import { userStates } from 'AnyR/states/wsStates'
import { computed, onMounted, onUpdated } from 'vue'
import { useAnyR } from 'AnyR/index'
import VideoLoader from './videoLoader.vue'
const ps = defineProps({
isSelf: Boolean,
id: String
})
const isThisUserMuted = computed(function() {
const isThisUserMuted = computed(function () {
return chatChannelState.value.mutedUserIdSet.includes(ps.id) || chatChannelState.value.mutedUserIdSet.includes(userStates.value.currentUserId)
})
......@@ -69,10 +75,19 @@ function cancelCallExact() {
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 () {
if (!ps.isSelf) {
AnyR?.agora.forceReplay(ps.id)
}
observer.observe(remoteVideoRef.value, { childList: true, subtree: true })
})
onUpdated(function () {
......@@ -80,6 +95,9 @@ onUpdated(function () {
AnyR?.agora.forceReplay(ps.id)
}
})
onUnmounted(() => {
observer.disconnect() // 停止监听
})
</script>
<style lang="less" scoped>
: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>
<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>
<image-editor
:before-cancel="beforeEndMarkHandle"
......@@ -26,6 +26,7 @@
class="red-ball absolute z-[999]"
@animationend="centerEnded"
></div>
<template v-if="isVideoVisible">
<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">
{{ userDataForThis.name }}
......@@ -38,12 +39,10 @@
<global-icon v-else :size="12" :icon="'mic-off'"></global-icon>
</div>
</div>
<!-- <div class="absolute top-0 left-0 right-0 bottom-0 flex-center flex-col">
<div class="text-base text-theme-text1">呼叫中...</div>
<a-button shape="circle" status="danger" type="primary" @click="hangupCall">
<global-icon :size="20" color="var(--color-bg-white)" icon="phone-hangup"></global-icon>
</a-button>
</div> -->
</template>
<div class="absolute w-full h-full flex-center" v-else>
<video-loader></video-loader>
</div>
</div>
<div class="flex justify-center w-full">
<div v-if="!isUserHost" class="w-[120px] h-[72px] item" @click="hangupCall">
......@@ -74,7 +73,7 @@
</div>
<div class="w-[120px] h-[72px] item" @click="toggleRecording">
<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 v-if="isUserHost" class="w-[120px] h-[72px] item" @click="allMute">
<global-icon :size="21" icon="mic-off"></global-icon>
......@@ -97,6 +96,7 @@ import { userStates } from 'AnyR/states/wsStates'
import ImageEditor from 'AnyR/widgets/ImageEditor/imageEditor.vue'
import { Message, Modal } from '@arco-design/web-vue'
import { alova } from '@/api/alova-instance.ts'
import VideoLoader from './videoLoader.vue'
const ps = defineProps<{
id: any
......@@ -104,19 +104,19 @@ const ps = defineProps<{
async function toggleRecording() {
if (!chatChannelState.value.recordingData.id) {
const resp = await AnyR?.agora.recordCurrent();
const resp = await AnyR?.agora.recordCurrent()
if (resp) {
Message.success("录制成功开始!")
Message.success('录制成功开始!')
} else {
Message.error("录制失败!")
Message.error('录制失败!')
}
} else {
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)
})
......@@ -179,16 +179,16 @@ async function beforeEndMarkHandle() {
return new Promise(function (resolve) {
Modal.warning({
title: '退出确认',
content: "你是截图发起者,退出后将会要求其他用户一同退出,确认?",
okText: "确认",
cancelText: "取消",
content: '你是截图发起者,退出后将会要求其他用户一同退出,确认?',
okText: '确认',
cancelText: '取消',
hideCancel: false,
onOk() {
resolve(true)
},
onCancel() {
resolve(false)
},
}
})
})
}
......@@ -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 () {
AnyR?.agora.forceReplay(ps.id)
observer.observe(remoteVideoRef.value, { childList: true, subtree: true })
})
onUpdated(function () {
AnyR?.agora.forceReplay(ps.id)
})
onUnmounted(() => {
observer.disconnect() // 停止监听
})
const isVoiceChatOnly = ref(false)
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