2025-09-11 23:13:47 +08:00

133 lines
2.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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"
crossorigin="anonymous"
referrerpolicy="no-referrer"
/>
<div v-else class="avatar-placeholder">
<span class="avatar-text">{{ avatarText }}</span>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, computed, watch } 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)
// 调试监听src变化
watch(() => props.src, (newSrc) => {
console.log('🖼️ SafeAvatar - 头像URL变化:', newSrc)
console.log('🖼️ SafeAvatar - 头像URL类型:', typeof newSrc)
console.log('🖼️ SafeAvatar - 头像URL长度:', newSrc?.length)
// 重置错误状态
imageError.value = false
}, { immediate: true })
// 根据用户名生成头像文字
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 = (event: Event) => {
console.error('🚨 SafeAvatar - 头像加载失败:', props.src, event)
imageError.value = true
}
const handleImageLoad = () => {
console.log('✅ SafeAvatar - 头像加载成功:', props.src)
imageError.value = false
}
</script>
export default {
name: 'SafeAvatar'
}
<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>