feat(member): 회원 썸네일 업로드를 작가 미디어와 분리

회원 아바타 자산을 전용 경로로 분리해 작가용 미디어 목록과 섞이지 않게 하고, 설정 화면에서 파일 업로드로 바로 반영할 수 있게 했다.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-05-11 17:16:21 +09:00
parent f5cd73b223
commit 6e8ca97779
8 changed files with 185 additions and 3 deletions

View File

@@ -3,6 +3,7 @@ const loading = ref(true)
const savingProfile = ref(false)
const savingPassword = ref(false)
const deletingAccount = ref(false)
const uploadingAvatar = ref(false)
const profileMessage = ref('')
const passwordMessage = ref('')
const deleteMessage = ref('')
@@ -98,6 +99,41 @@ const saveProfile = async () => {
}
}
/**
* 썸네일 파일을 업로드한다.
* @param {Event} event - 파일 선택 이벤트
* @returns {Promise<void>}
*/
const uploadAvatar = async (event) => {
const target = /** @type {HTMLInputElement | null} */ (event.target instanceof HTMLInputElement ? event.target : null)
const file = target?.files?.[0]
if (!file || uploadingAvatar.value) {
return
}
uploadingAvatar.value = true
profileMessage.value = ''
try {
const formData = new FormData()
formData.append('file', file)
const result = await $fetch('/api/auth/avatar', {
method: 'POST',
body: formData
})
profileForm.avatarUrl = result.avatarUrl || ''
profileMessage.value = '썸네일이 업로드되었습니다. 프로필 저장을 눌러 반영하세요.'
} catch (error) {
profileMessage.value = error?.data?.message || '썸네일 업로드에 실패했습니다.'
} finally {
uploadingAvatar.value = false
if (target) {
target.value = ''
}
}
}
/**
* 비밀번호를 변경한다.
* @returns {Promise<void>}
@@ -195,6 +231,14 @@ onMounted(loadProfile)
class="h-10 rounded-[8px] border border-[var(--site-line)] bg-transparent px-3 text-sm outline-none focus-visible:border-[var(--site-accent)]"
placeholder="https://..."
>
<label class="text-xs site-muted">썸네일 업로드</label>
<input
type="file"
accept="image/jpeg,image/png,image/webp,image/gif"
class="block w-full text-xs site-muted file:mr-3 file:cursor-pointer file:rounded-[8px] file:border file:border-[var(--site-line)] file:bg-[var(--site-panel)] file:px-3 file:py-1.5"
:disabled="uploadingAvatar"
@change="uploadAvatar"
>
<button
type="button"
class="site-accent-button mt-1 w-fit rounded-[10px] px-3 py-1.5 text-xs font-semibold disabled:opacity-60"