ca66c1d53e
CI / build (push) Failing after 13m27s
- UserAvatar 컴포넌트(커스텀>구글>이니셜, 로드 실패 시 이니셜 폴백) - 목록: 작성자 아바타 + 추천 수 표기 - 상세: 작성자 아바타, 추천/비추천 토글 버튼(내 투표 강조), 추천자 본문 하단 아바타 10개 + 초과 시 (+N명이 추천했습니다), 클릭 시 전체 목록 모달 - 댓글: 작성자 아바타 + 추천/비추천 버튼 - 계정정보: 포인트 표기(GET /auth/points 최신값) - boardApi.votePost/voteComment/recommenders, authApi.points 추가 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
63 lines
1.5 KiB
Vue
63 lines
1.5 KiB
Vue
<script setup>
|
|
import { computed, ref, watch } from 'vue'
|
|
|
|
// 작성자/추천자 아바타. 우선순위: 커스텀(profileImage) > 구글(googlePicture) > 이니셜.
|
|
const props = defineProps({
|
|
name: { type: String, default: '' },
|
|
googlePicture: { type: String, default: '' },
|
|
profileImage: { type: String, default: '' },
|
|
size: { type: Number, default: 28 },
|
|
})
|
|
|
|
const broken = ref(false)
|
|
const src = computed(() => props.profileImage || props.googlePicture || '')
|
|
const initial = computed(() => {
|
|
const s = (props.name || '').trim()
|
|
return s ? s[0].toUpperCase() : '?'
|
|
})
|
|
// src 가 바뀌면 깨짐 상태 리셋
|
|
watch(src, () => { broken.value = false })
|
|
</script>
|
|
|
|
<template>
|
|
<span class="user-avatar" :style="{ width: size + 'px', height: size + 'px' }" :title="name">
|
|
<img
|
|
v-if="src && !broken"
|
|
:src="src"
|
|
:alt="name"
|
|
referrerpolicy="no-referrer"
|
|
@error="broken = true"
|
|
/>
|
|
<span v-else class="ua-initial" :style="{ fontSize: Math.round(size * 0.45) + 'px' }">{{ initial }}</span>
|
|
</span>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.user-avatar {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border-radius: 50%;
|
|
overflow: hidden;
|
|
flex: none;
|
|
vertical-align: middle;
|
|
background: var(--color-background-mute);
|
|
}
|
|
.user-avatar img {
|
|
width: 100%;
|
|
height: 100%;
|
|
object-fit: cover;
|
|
display: block;
|
|
}
|
|
.ua-initial {
|
|
font-weight: 700;
|
|
color: #fff;
|
|
width: 100%;
|
|
height: 100%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
background: hsla(160, 100%, 37%, 1);
|
|
}
|
|
</style>
|