username 8067376d43 www
2025-07-28 09:51:21 +08:00

116 lines
2.1 KiB
Vue

<template>
<div
class="safe-avatar"
:style="{
width: size + 'px',
height: size + 'px'
}"
>
<img
v-if="!imageError && src"
:src="src"
:alt="alt"
@error="handleImageError"
@load="handleImageLoad"
/>
<div v-else class="avatar-placeholder">
<span class="avatar-text">{{ avatarText }}</span>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
interface Props {
src?: string
alt?: string
size?: number
name?: string
}
const props = withDefaults(defineProps<Props>(), {
src: '',
alt: '头像',
size: 32,
name: '用户'
})
const imageError = ref(false)
// 根据用户名生成头像文字
const avatarText = computed(() => {
if (props.name) {
// 如果是中文名,取最后一个字
if (/[\u4e00-\u9fa5]/.test(props.name)) {
return props.name.slice(-1)
}
// 如果是英文名,取首字母
return props.name.charAt(0).toUpperCase()
}
return '用'
})
const handleImageError = () => {
imageError.value = true
}
const handleImageLoad = () => {
imageError.value = false
}
</script>
<style scoped>
.safe-avatar {
border-radius: 50%;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
background: #f0f0f0;
}
.safe-avatar img {
width: 100%;
height: 100%;
object-fit: cover;
}
.avatar-placeholder {
width: 100%;
height: 100%;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
display: flex;
align-items: center;
justify-content: center;
}
.avatar-text {
color: white;
font-weight: 500;
font-size: 14px;
}
/* 根据尺寸调整字体大小 */
.safe-avatar[style*="width: 24px"] .avatar-text {
font-size: 10px;
}
.safe-avatar[style*="width: 32px"] .avatar-text {
font-size: 12px;
}
.safe-avatar[style*="width: 40px"] .avatar-text {
font-size: 14px;
}
.safe-avatar[style*="width: 64px"] .avatar-text,
.safe-avatar[style*="width: 80px"] .avatar-text {
font-size: 18px;
}
.safe-avatar[style*="width: 100px"] .avatar-text {
font-size: 24px;
}
</style>