个人信息卡片
This commit is contained in:
212
src/components/common/UserInfoCard.vue
Normal file
212
src/components/common/UserInfoCard.vue
Normal file
@@ -0,0 +1,212 @@
|
||||
<template>
|
||||
<div
|
||||
v-if="show"
|
||||
class="fixed inset-0 bg-black/80 z-[60] flex items-center justify-center p-4 backdrop-blur-sm"
|
||||
@click.self="$emit('close')"
|
||||
>
|
||||
<div class="bg-[#111827] rounded-2xl w-full max-w-2xl shadow-2xl border border-gray-700 overflow-hidden animate-fade-in max-h-[90vh] flex flex-col relative">
|
||||
<!-- 背景装饰 -->
|
||||
<div class="absolute top-0 left-0 right-0 h-48 bg-gradient-to-b from-primary/20 to-transparent pointer-events-none"></div>
|
||||
|
||||
<!-- 关闭按钮 -->
|
||||
<button
|
||||
class="absolute top-5 right-5 z-50 w-9 h-9 rounded-full bg-black/20 hover:bg-white/10 text-gray-300 hover:text-white flex items-center justify-center transition backdrop-blur-md border border-white/5"
|
||||
@click="$emit('close')"
|
||||
>
|
||||
<i class="fas fa-times"></i>
|
||||
</button>
|
||||
|
||||
<!-- 内容区域 -->
|
||||
<div class="flex-1 overflow-y-auto custom-scrollbar relative z-10 flex flex-col">
|
||||
<!-- 头部:头像与核心信息 -->
|
||||
<div class="pt-14 pb-8 px-8 text-center flex flex-col items-center animate-fade-in">
|
||||
<div class="relative group cursor-pointer" @click="viewAvatar">
|
||||
<Avatar
|
||||
:name="user?.name || '未知'"
|
||||
:avatar="user?.avatar"
|
||||
size="xl"
|
||||
rounded="full"
|
||||
class="border-[6px] border-[#111827] shadow-2xl relative z-10 transition-transform duration-300 group-hover:scale-105"
|
||||
/>
|
||||
<div v-if="user?.is_online" class="absolute bottom-1 right-1 w-5 h-5 bg-emerald-500 rounded-full border-4 border-[#111827] z-20" title="在线"></div>
|
||||
</div>
|
||||
|
||||
<h3 class="text-2xl font-bold text-white mt-5 flex items-center gap-2 justify-center select-text">
|
||||
{{ user?.name || '未知' }}
|
||||
<span v-if="user?.gender" class="w-5 h-5 rounded-full flex items-center justify-center text-[10px]" :class="user.gender === 1 ? 'bg-blue-500/20 text-blue-400' : 'bg-pink-500/20 text-pink-400'">
|
||||
<i :class="user.gender === 1 ? 'fas fa-mars' : 'fas fa-venus'"></i>
|
||||
</span>
|
||||
</h3>
|
||||
|
||||
<p class="text-gray-400 text-sm mt-2 max-w-md truncate px-4 opacity-80">
|
||||
{{ user?.desc || '暂无签名' }}
|
||||
</p>
|
||||
|
||||
<div class="flex gap-3 mt-4 text-xs font-medium text-gray-400">
|
||||
<span class="bg-white/5 px-2.5 py-1 rounded-md border border-white/5 select-text">ID: {{ user?.id || '未知' }}</span>
|
||||
<span v-if="user?.region" class="bg-white/5 px-2.5 py-1 rounded-md border border-white/5">{{ user.region }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 详细信息列表 -->
|
||||
<div class="px-8 py-4 space-y-3 max-w-xl mx-auto w-full animate-slide-up">
|
||||
<div class="bg-white/5 rounded-2xl border border-white/5 overflow-hidden">
|
||||
<!-- 网名 -->
|
||||
<div class="flex items-center p-4 hover:bg-white/5 transition-colors group relative border-b border-white/5">
|
||||
<div class="w-9 h-9 rounded-lg bg-white/5 flex items-center justify-center text-gray-500 mr-4 shrink-0">
|
||||
<i class="far fa-user"></i>
|
||||
</div>
|
||||
<div class="flex-1 min-w-0 mr-8">
|
||||
<div class="text-[10px] text-gray-500 uppercase tracking-wider mb-0.5 font-bold">网名</div>
|
||||
<div class="text-sm text-gray-200 font-medium truncate select-text">{{ user?.name || '未知' }}</div>
|
||||
</div>
|
||||
<button class="absolute right-4 w-8 h-8 rounded-lg hover:bg-white/10 text-gray-500 hover:text-primary transition flex items-center justify-center opacity-0 group-hover:opacity-100"
|
||||
@click="copyText(user?.name)" title="复制">
|
||||
<i class="far fa-copy"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 手机号 -->
|
||||
<div v-if="user?.phone" class="flex items-center p-4 hover:bg-white/5 transition-colors group relative border-b border-white/5 last:border-0">
|
||||
<div class="w-9 h-9 rounded-lg bg-white/5 flex items-center justify-center text-gray-500 mr-4 shrink-0">
|
||||
<i class="fas fa-phone-alt"></i>
|
||||
</div>
|
||||
<div class="flex-1 min-w-0 mr-8">
|
||||
<div class="text-[10px] text-gray-500 uppercase tracking-wider mb-0.5 font-bold">手机号</div>
|
||||
<div class="text-sm text-gray-200 font-medium truncate select-text font-mono">{{ user.phone }}</div>
|
||||
</div>
|
||||
<button class="absolute right-4 w-8 h-8 rounded-lg hover:bg-white/10 text-gray-500 hover:text-primary transition flex items-center justify-center opacity-0 group-hover:opacity-100"
|
||||
@click="copyText(user.phone)" title="复制">
|
||||
<i class="far fa-copy"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 邮箱 -->
|
||||
<div v-if="user?.email" class="flex items-center p-4 hover:bg-white/5 transition-colors group relative border-b border-white/5 last:border-0">
|
||||
<div class="w-9 h-9 rounded-lg bg-white/5 flex items-center justify-center text-gray-500 mr-4 shrink-0">
|
||||
<i class="far fa-envelope"></i>
|
||||
</div>
|
||||
<div class="flex-1 min-w-0 mr-8">
|
||||
<div class="text-[10px] text-gray-500 uppercase tracking-wider mb-0.5 font-bold">邮箱</div>
|
||||
<div class="text-sm text-gray-200 font-medium truncate select-text font-mono">{{ user.email }}</div>
|
||||
</div>
|
||||
<button class="absolute right-4 w-8 h-8 rounded-lg hover:bg-white/10 text-gray-500 hover:text-primary transition flex items-center justify-center opacity-0 group-hover:opacity-100"
|
||||
@click="copyText(user.email)" title="复制">
|
||||
<i class="far fa-copy"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 地区 -->
|
||||
<div v-if="user?.region" class="flex items-center p-4 hover:bg-white/5 transition-colors group relative border-b border-white/5 last:border-0">
|
||||
<div class="w-9 h-9 rounded-lg bg-white/5 flex items-center justify-center text-gray-500 mr-4 shrink-0">
|
||||
<i class="fas fa-map-marker-alt"></i>
|
||||
</div>
|
||||
<div class="flex-1 min-w-0 mr-8">
|
||||
<div class="text-[10px] text-gray-500 uppercase tracking-wider mb-0.5 font-bold">地区</div>
|
||||
<div class="text-sm text-gray-200 font-medium truncate select-text">{{ user.region }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 底部快捷操作栏 -->
|
||||
<div class="mt-auto p-6 bg-gradient-to-t from-[#0f172a] via-[#0f172a]/80 to-transparent">
|
||||
<div class="grid grid-cols-3 gap-4 max-w-lg mx-auto w-full">
|
||||
<!-- 发消息 -->
|
||||
<button class="flex flex-col items-center justify-center gap-1.5 py-3.5 px-2 rounded-2xl transition-all duration-200 active:scale-95 group bg-primary text-white shadow-lg shadow-primary/25 hover:bg-primary-hover hover:-translate-y-0.5"
|
||||
@click="$emit('send-message')"
|
||||
>
|
||||
<i class="fas fa-comment-dots text-xl"></i>
|
||||
<span class="text-xs font-bold">发消息</span>
|
||||
</button>
|
||||
|
||||
<!-- 语音通话 -->
|
||||
<button class="flex flex-col items-center justify-center gap-1.5 py-3.5 px-2 rounded-2xl transition-all duration-200 active:scale-95 group bg-white/5 text-gray-300 hover:bg-white/10 hover:text-white border border-white/5 hover:border-white/10"
|
||||
@click="$emit('audio-call')"
|
||||
>
|
||||
<i class="fas fa-phone text-xl"></i>
|
||||
<span class="text-xs font-medium">语音通话</span>
|
||||
</button>
|
||||
|
||||
<!-- 视频通话 -->
|
||||
<button class="flex flex-col items-center justify-center gap-1.5 py-3.5 px-2 rounded-2xl transition-all duration-200 active:scale-95 group bg-white/5 text-gray-300 hover:bg-white/10 hover:text-white border border-white/5 hover:border-white/10"
|
||||
@click="$emit('video-call')"
|
||||
>
|
||||
<i class="fas fa-video text-xl"></i>
|
||||
<span class="text-xs font-medium">视频通话</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useToastStore } from '@/stores/toast'
|
||||
import Avatar from '@/components/common/Avatar.vue'
|
||||
import type { User } from '@/types/api'
|
||||
|
||||
interface Props {
|
||||
show: boolean
|
||||
user: User | null
|
||||
}
|
||||
|
||||
defineProps<Props>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
close: []
|
||||
'send-message': []
|
||||
'audio-call': []
|
||||
'video-call': []
|
||||
}>()
|
||||
|
||||
const toastStore = useToastStore()
|
||||
|
||||
function copyText(text?: string) {
|
||||
if (!text) return
|
||||
navigator.clipboard.writeText(text).then(() => {
|
||||
toastStore.success('复制成功')
|
||||
}).catch(() => {
|
||||
toastStore.error('复制失败')
|
||||
})
|
||||
}
|
||||
|
||||
function viewAvatar() {
|
||||
// 可以添加查看大图逻辑
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.custom-scrollbar::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
.custom-scrollbar::-webkit-scrollbar-thumb {
|
||||
@apply bg-white/10 rounded-full hover:bg-white/20;
|
||||
}
|
||||
.animate-fade-in {
|
||||
animation: fadeIn 0.4s ease-out;
|
||||
}
|
||||
.animate-slide-up {
|
||||
animation: slideUp 0.4s ease-out;
|
||||
}
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@keyframes slideUp {
|
||||
from {
|
||||
transform: translateY(20px);
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user