群视频通话
This commit is contained in:
@@ -1,31 +1,45 @@
|
||||
<template>
|
||||
<div
|
||||
v-if="showBanner"
|
||||
class="mx-4 mb-2 p-2 bg-gradient-to-r from-green-900/40 to-emerald-900/40 border border-green-500/20 rounded-xl flex items-center justify-between backdrop-blur-sm shadow-lg animate-fade-in-down"
|
||||
class="mx-4 mb-2 p-3 bg-[#1e1e24]/90 border border-white/5 rounded-xl flex items-center justify-between shadow-lg backdrop-blur-md animate-fade-in-down group hover:bg-[#25252b] transition-colors"
|
||||
>
|
||||
<div class="flex items-center gap-3 px-2">
|
||||
<!-- 动态波纹图标 -->
|
||||
<div class="relative w-8 h-8 flex items-center justify-center">
|
||||
<div class="flex items-center gap-4">
|
||||
<!-- 动态图标 -->
|
||||
<div class="relative w-10 h-10 flex-shrink-0">
|
||||
<div class="absolute inset-0 bg-green-500 rounded-full opacity-20 animate-ping"></div>
|
||||
<div class="relative w-8 h-8 rounded-full bg-green-500/20 flex items-center justify-center border border-green-500/30">
|
||||
<i class="fas fa-video text-green-400 text-xs"></i>
|
||||
<div class="relative w-full h-full rounded-full bg-gradient-to-br from-green-500 to-emerald-700 flex items-center justify-center text-white shadow-inner">
|
||||
<i class="fas fa-video text-sm"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p class="text-green-100 text-xs font-bold tracking-wide">群通话进行中</p>
|
||||
<p class="text-green-400/70 text-[10px] flex items-center gap-1">
|
||||
<span class="w-1.5 h-1.5 rounded-full bg-green-500 inline-block"></span>
|
||||
{{ participantsCount }} 人参与
|
||||
</p>
|
||||
<div class="flex flex-col">
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-white font-bold text-sm tracking-wide">群通话进行中</span>
|
||||
<span class="px-1.5 py-0.5 bg-green-500/20 text-green-400 text-[10px] rounded font-mono">{{ participantsCount }}人</span>
|
||||
</div>
|
||||
|
||||
<!-- 头像堆叠 -->
|
||||
<div class="flex -space-x-2 mt-1.5 overflow-hidden py-0.5 pl-0.5">
|
||||
<div v-for="user in previewParticipants" :key="user.userId" class="relative transition-transform hover:scale-110 hover:z-10">
|
||||
<Avatar
|
||||
:name="user.name"
|
||||
:avatar="user.avatar"
|
||||
size="sm"
|
||||
class="w-5 h-5 ring-2 ring-[#1e1e24]"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="participantsCount > 5" class="w-5 h-5 rounded-full bg-gray-700 text-[8px] text-white flex items-center justify-center ring-2 ring-[#1e1e24] font-medium">
|
||||
+{{ participantsCount - 5 }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button
|
||||
class="px-3 py-1.5 bg-green-600 hover:bg-green-500 text-white text-xs font-bold rounded-lg transition shadow-lg shadow-green-900/30 flex items-center gap-1 active:scale-95"
|
||||
class="px-4 py-2 bg-white text-black text-xs font-bold rounded-lg transition hover:bg-gray-200 active:scale-95 flex items-center gap-1.5 shadow-lg shadow-white/5"
|
||||
@click="groupWebRTC.joinCurrentCall()"
|
||||
>
|
||||
<i class="fas fa-phone-alt text-[10px]"></i>
|
||||
<i class="fas fa-phone-alt"></i>
|
||||
<span>加入</span>
|
||||
</button>
|
||||
</div>
|
||||
@@ -34,6 +48,7 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { useGroupWebRTC } from '@/composables/useGroupWebRTC'
|
||||
import Avatar from '@/components/common/Avatar.vue'
|
||||
|
||||
const props = defineProps<{
|
||||
roomId: string
|
||||
@@ -50,6 +65,7 @@ const showBanner = computed(() => {
|
||||
})
|
||||
|
||||
const participantsCount = computed(() => participants.value.length)
|
||||
const previewParticipants = computed(() => participants.value.slice(0, 5))
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -1,48 +1,66 @@
|
||||
<template>
|
||||
<Teleport to="body">
|
||||
<!-- 全屏背景遮罩:磨砂玻璃效果 -->
|
||||
<div
|
||||
class="fixed z-[9999] top-8 right-8 w-80 bg-[#1e1e24] border border-gray-700 rounded-2xl shadow-2xl overflow-hidden animate-slide-in"
|
||||
class="fixed inset-0 z-[10000] flex flex-col items-center justify-center bg-gray-900/80 backdrop-blur-xl animate-fade-in select-none"
|
||||
>
|
||||
<div class="p-6 flex flex-col items-center">
|
||||
<!-- 头像区 -->
|
||||
<div class="relative mb-4">
|
||||
<!-- 动态背景光晕 -->
|
||||
<div class="absolute inset-0 overflow-hidden pointer-events-none">
|
||||
<div class="absolute top-1/4 left-1/4 w-96 h-96 bg-purple-500/20 rounded-full blur-[100px] animate-pulse-slow"></div>
|
||||
<div class="absolute bottom-1/4 right-1/4 w-96 h-96 bg-blue-500/20 rounded-full blur-[100px] animate-pulse-slow delay-1000"></div>
|
||||
</div>
|
||||
|
||||
<!-- 主要内容卡片 -->
|
||||
<div class="relative z-10 flex flex-col items-center animate-slide-up">
|
||||
|
||||
<!-- 头像区域 (带波纹动画) -->
|
||||
<div class="relative mb-8">
|
||||
<div class="absolute inset-0 bg-white/10 rounded-full animate-ping-slow"></div>
|
||||
<div class="absolute inset-[-10px] bg-white/5 rounded-full animate-ping-slower"></div>
|
||||
|
||||
<Avatar
|
||||
:name="callState.inviterName"
|
||||
size="xl"
|
||||
class="ring-4 ring-gray-800 shadow-lg"
|
||||
:avatar="callState.inviterAvatar"
|
||||
size="2xl"
|
||||
class="w-32 h-32 text-4xl shadow-2xl border-4 border-white/10 relative z-20"
|
||||
/>
|
||||
<div class="absolute -bottom-1 -right-1 w-6 h-6 bg-green-500 rounded-full border-4 border-gray-800 flex items-center justify-center">
|
||||
<i class="fas fa-video text-white text-[10px]"></i>
|
||||
|
||||
<!-- 类型图标 -->
|
||||
<div class="absolute bottom-0 right-0 w-10 h-10 bg-gradient-to-br from-green-400 to-emerald-600 rounded-full flex items-center justify-center shadow-lg z-30 border-4 border-gray-900">
|
||||
<i class="fas" :class="callState.type === 'video' ? 'fa-video' : 'fa-phone-alt'"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3 class="text-white font-bold text-lg mb-1">{{ callState.inviterName }}</h3>
|
||||
<p class="text-gray-400 text-sm mb-6">邀请你进行群视频通话...</p>
|
||||
<!-- 文本信息 -->
|
||||
<h2 class="text-3xl font-bold text-white mb-2 tracking-tight">{{ callState.inviterName }}</h2>
|
||||
<p class="text-gray-300 text-lg mb-12 flex items-center gap-2">
|
||||
<span>邀请你加入群{{ callState.type === 'video' ? '视频' : '语音' }}通话</span>
|
||||
<span class="flex gap-1">
|
||||
<span class="w-1 h-1 bg-gray-400 rounded-full animate-bounce"></span>
|
||||
<span class="w-1 h-1 bg-gray-400 rounded-full animate-bounce delay-100"></span>
|
||||
<span class="w-1 h-1 bg-gray-400 rounded-full animate-bounce delay-200"></span>
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<!-- 按钮区 -->
|
||||
<div class="flex gap-4 w-full">
|
||||
<button
|
||||
class="flex-1 py-2.5 bg-red-500/10 hover:bg-red-500/20 text-red-500 rounded-xl font-medium transition flex items-center justify-center gap-2"
|
||||
@click="groupWebRTC.rejectInvite()"
|
||||
>
|
||||
<i class="fas fa-times"></i>
|
||||
拒绝
|
||||
</button>
|
||||
<!-- 操作按钮 -->
|
||||
<div class="flex items-center gap-16">
|
||||
<!-- 拒绝 -->
|
||||
<div class="flex flex-col items-center gap-3 group cursor-pointer" @click="groupWebRTC.rejectInvite()">
|
||||
<div class="w-16 h-16 rounded-full bg-red-500/20 group-hover:bg-red-500 text-red-500 group-hover:text-white flex items-center justify-center transition-all duration-300 backdrop-blur-md border border-red-500/30">
|
||||
<i class="fas fa-times text-2xl"></i>
|
||||
</div>
|
||||
<span class="text-sm text-gray-400 group-hover:text-white transition-colors">拒绝</span>
|
||||
</div>
|
||||
|
||||
<button
|
||||
class="flex-1 py-2.5 bg-green-500 hover:bg-green-600 text-white rounded-xl font-medium transition shadow-lg shadow-green-500/20 flex items-center justify-center gap-2"
|
||||
@click="groupWebRTC.acceptInvite()"
|
||||
>
|
||||
<i class="fas fa-video"></i>
|
||||
接听
|
||||
</button>
|
||||
<!-- 接听 -->
|
||||
<div class="flex flex-col items-center gap-3 group cursor-pointer" @click="groupWebRTC.acceptInvite()">
|
||||
<div class="w-20 h-20 rounded-full bg-green-500 text-white flex items-center justify-center transition-all duration-300 shadow-lg shadow-green-500/40 group-hover:scale-110 group-hover:shadow-green-500/60 animate-pulse-border">
|
||||
<i class="fas" :class="callState.type === 'video' ? 'fa-video' : 'fa-phone'"></i>
|
||||
</div>
|
||||
<span class="text-sm text-gray-400 group-hover:text-white transition-colors">接听</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 进度条倒计时 -->
|
||||
<div class="h-1 bg-gray-800 w-full">
|
||||
<div class="h-full bg-green-500 animate-progress origin-left"></div>
|
||||
</div>
|
||||
</div>
|
||||
</Teleport>
|
||||
</template>
|
||||
@@ -56,19 +74,23 @@ const { callState } = groupWebRTC
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@keyframes slideIn {
|
||||
from { transform: translateX(100%); opacity: 0; }
|
||||
to { transform: translateX(0); opacity: 1; }
|
||||
.animate-fade-in {
|
||||
animation: fadeIn 0.5s ease-out;
|
||||
}
|
||||
.animate-slide-in {
|
||||
animation: slideIn 0.4s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
.animate-slide-up {
|
||||
animation: slideUp 0.6s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
}
|
||||
.animate-ping-slow {
|
||||
animation: ping 2s cubic-bezier(0, 0, 0.2, 1) infinite;
|
||||
}
|
||||
.animate-ping-slower {
|
||||
animation: ping 3s cubic-bezier(0, 0, 0.2, 1) infinite;
|
||||
}
|
||||
.animate-pulse-slow {
|
||||
animation: pulse 6s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
||||
}
|
||||
|
||||
@keyframes progress {
|
||||
from { transform: scaleX(1); }
|
||||
to { transform: scaleX(0); }
|
||||
}
|
||||
.animate-progress {
|
||||
animation: progress 30s linear forwards;
|
||||
}
|
||||
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
|
||||
@keyframes slideUp { from { transform: translateY(20px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
|
||||
@keyframes pulse { 0%, 100% { opacity: 0.2; } 50% { opacity: 0.5; } }
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user