|
|
|
@ -39,7 +39,6 @@ const loading = ref(true) |
|
|
|
const saving = ref(false) |
|
|
|
const uploadingAvatar = ref(false) |
|
|
|
const uploadingHeaderIcon = ref(false) |
|
|
|
const message = ref('') |
|
|
|
const avatarFileInput = ref<HTMLInputElement | null>(null) |
|
|
|
const headerIconFileInput = ref<HTMLInputElement | null>(null) |
|
|
|
|
|
|
|
@ -86,7 +85,6 @@ async function onAvatarFileChange(ev: Event) { |
|
|
|
return |
|
|
|
} |
|
|
|
uploadingAvatar.value = true |
|
|
|
message.value = '' |
|
|
|
try { |
|
|
|
const form = new FormData() |
|
|
|
form.append('file', file) |
|
|
|
@ -97,14 +95,13 @@ async function onAvatarFileChange(ev: Event) { |
|
|
|
}) |
|
|
|
const url = files[0]?.url |
|
|
|
if (!url) { |
|
|
|
message.value = '上传未返回地址' |
|
|
|
toast.add({ title: '上传未返回地址', color: 'error' }) |
|
|
|
return |
|
|
|
} |
|
|
|
state.avatar = url |
|
|
|
message.value = '头像已上传,请点击下方「保存」写入资料' |
|
|
|
toast.add({ title: '头像已上传,请保存资料', color: 'success' }) |
|
|
|
} catch (e: unknown) { |
|
|
|
message.value = getApiErrorMessage(e) |
|
|
|
toast.add({ title: getApiErrorMessage(e), color: 'error' }) |
|
|
|
} finally { |
|
|
|
uploadingAvatar.value = false |
|
|
|
} |
|
|
|
@ -118,7 +115,6 @@ async function onHeaderIconFileChange(ev: Event) { |
|
|
|
return |
|
|
|
} |
|
|
|
uploadingHeaderIcon.value = true |
|
|
|
message.value = '' |
|
|
|
try { |
|
|
|
const form = new FormData() |
|
|
|
form.append('file', file) |
|
|
|
@ -129,14 +125,13 @@ async function onHeaderIconFileChange(ev: Event) { |
|
|
|
}) |
|
|
|
const url = files[0]?.url |
|
|
|
if (!url) { |
|
|
|
message.value = '上传未返回地址' |
|
|
|
toast.add({ title: '上传未返回地址', color: 'error' }) |
|
|
|
return |
|
|
|
} |
|
|
|
state.publicHomeHeaderIconUrl = url |
|
|
|
message.value = '顶栏图标已上传,请点击下方「保存」写入' |
|
|
|
toast.add({ title: '顶栏图标已上传,请保存资料', color: 'success' }) |
|
|
|
} catch (e: unknown) { |
|
|
|
message.value = getApiErrorMessage(e) |
|
|
|
toast.add({ title: getApiErrorMessage(e), color: 'error' }) |
|
|
|
} finally { |
|
|
|
uploadingHeaderIcon.value = false |
|
|
|
} |
|
|
|
@ -170,13 +165,12 @@ onMounted(load) |
|
|
|
|
|
|
|
async function save() { |
|
|
|
saving.value = true |
|
|
|
message.value = '' |
|
|
|
try { |
|
|
|
let links: { label: string; url: string; visibility: string }[] = [] |
|
|
|
try { |
|
|
|
links = JSON.parse(state.linksJson) as { label: string; url: string; visibility: string }[] |
|
|
|
} catch { |
|
|
|
message.value = '社交链接 JSON 无效' |
|
|
|
toast.add({ title: '社交链接 JSON 无效', color: 'error' }) |
|
|
|
return |
|
|
|
} |
|
|
|
await fetchData('/api/me/profile', { |
|
|
|
@ -204,7 +198,6 @@ async function save() { |
|
|
|
body: { key: 'publicHomeHeaderIconUrl', value: state.publicHomeHeaderIconUrl }, |
|
|
|
}), |
|
|
|
]) |
|
|
|
message.value = '已保存' |
|
|
|
toast.add({ title: '资料已保存', color: 'success' }) |
|
|
|
try { |
|
|
|
await refreshAuthSession(true) |
|
|
|
@ -213,7 +206,7 @@ async function save() { |
|
|
|
} |
|
|
|
await load() |
|
|
|
} catch (e: unknown) { |
|
|
|
message.value = getApiErrorMessage(e) |
|
|
|
toast.add({ title: getApiErrorMessage(e), color: 'error' }) |
|
|
|
} finally { |
|
|
|
saving.value = false |
|
|
|
} |
|
|
|
@ -225,10 +218,22 @@ async function save() { |
|
|
|
<h1 class="text-2xl font-semibold"> |
|
|
|
个人资料 |
|
|
|
</h1> |
|
|
|
<div v-if="loading" class="text-muted"> |
|
|
|
加载中… |
|
|
|
</div> |
|
|
|
<UForm v-else :state="state" class="space-y-4" @submit.prevent="save"> |
|
|
|
<div class="relative min-h-[28rem]"> |
|
|
|
<div |
|
|
|
v-show="loading" |
|
|
|
class="absolute inset-0 z-10 flex flex-col items-center justify-center gap-3 rounded-lg bg-default/75 backdrop-blur-[2px]" |
|
|
|
aria-live="polite" |
|
|
|
aria-busy="true" |
|
|
|
> |
|
|
|
<UIcon name="i-lucide-loader-2" class="size-8 animate-spin text-primary" /> |
|
|
|
<span class="text-sm text-muted">加载中…</span> |
|
|
|
</div> |
|
|
|
<UForm |
|
|
|
:state="state" |
|
|
|
class="space-y-4" |
|
|
|
:class="loading ? 'pointer-events-none select-none opacity-50' : ''" |
|
|
|
@submit.prevent="save" |
|
|
|
> |
|
|
|
<UFormField label="公开主页 slug(/@slug)" name="publicSlug"> |
|
|
|
<UInput v-model="state.publicSlug" placeholder="例如 my-id" /> |
|
|
|
</UFormField> |
|
|
|
@ -335,11 +340,11 @@ async function save() { |
|
|
|
<UFormField label="社交链接(JSON 数组)" name="linksJson"> |
|
|
|
<UTextarea v-model="state.linksJson" :rows="8" class="w-full font-mono text-sm" /> |
|
|
|
</UFormField> |
|
|
|
<UButton type="submit" :loading="saving"> |
|
|
|
<UButton type="submit" :loading="saving" :disabled="loading"> |
|
|
|
保存 |
|
|
|
</UButton> |
|
|
|
</UForm> |
|
|
|
<UAlert v-if="message" :title="message" /> |
|
|
|
</div> |
|
|
|
|
|
|
|
<UModal |
|
|
|
v-model:open="bioModalOpen" |
|
|
|
|