You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

81 lines
2.2 KiB

<script setup lang="ts">
definePageMeta({ middleware: "auth" });
type User = {
id: number;
name: string;
age: number;
email: string;
emailVerified: boolean;
};
const fetch = useRequestFetch();
const { data, refresh } = await useAsyncData("me", () =>
fetch<{ user: User }>("/api/me", { credentials: "include" }),
);
const name = ref(data.value?.user.name ?? "");
const age = ref(data.value?.user.age ?? 0);
const patchError = ref("");
watch(
() => data.value?.user,
(u) => {
if (u) {
name.value = u.name;
age.value = u.age;
}
},
{ immediate: true },
);
async function saveProfile() {
patchError.value = "";
try {
await $fetch("/api/me", {
method: "PATCH",
body: { name: name.value, age: age.value },
credentials: "include",
});
await refresh();
} catch (e: unknown) {
const err = e as { statusCode?: number; data?: { error?: { message?: string } } };
if (err.statusCode === 403) {
patchError.value = "需先完成邮箱验证后才能修改资料。";
} else {
patchError.value = err.data?.error?.message ?? "保存失败";
}
}
}
async function logout() {
await $fetch("/api/auth/logout", { method: "POST", credentials: "include" });
await navigateTo("/login");
}
</script>
<template>
<div style="max-width: 420px; margin: 2rem auto; font-family: system-ui">
<h1>个人资料</h1>
<p v-if="data?.user">
邮箱{{ data.user.email }}
<span v-if="data.user.emailVerified">已验证</span>
<span v-else>未验证</span>
</p>
<p v-if="patchError" style="color: darkorange">{{ patchError }}</p>
<form @submit.prevent="saveProfile">
<label>
姓名
<input v-model="name" type="text" required style="display: block; width: 100%; margin: 0.25rem 0 1rem" />
</label>
<label>
年龄
<input v-model.number="age" type="number" min="1" max="150" required style="display: block; width: 100%; margin: 0.25rem 0 1rem" />
</label>
<button type="submit">保存</button>
</form>
<p style="margin-top: 2rem">
<button type="button" @click="logout">退出登录</button>
</p>
</div>
</template>