Files
opencloud/src/views/auth/AuthConfirmView.vue
T

75 lines
2.6 KiB
Vue

<script setup lang="ts">
import { onMounted, onUnmounted, ref } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { NButton, NCard, NResult, NSpin } from 'naive-ui'
import { useAuthStore } from '@/stores/auth'
const authStore = useAuthStore()
const route = useRoute()
const router = useRouter()
const state = ref<'loading' | 'success' | 'failed'>('loading')
const error = ref('')
const countdown = ref(5)
const token = typeof route.query.token === 'string' ? route.query.token : ''
let timer: ReturnType<typeof setInterval> | null = null
if (route.query.token !== undefined) {
window.history.replaceState(window.history.state, '', route.path)
}
function startCountdown() {
timer = setInterval(() => {
countdown.value--
if (countdown.value <= 0) {
if (timer) clearInterval(timer)
void router.push('/login')
}
}, 1000)
}
onMounted(async () => {
if (!token) {
error.value = '确认链接缺少验证信息'
state.value = 'failed'
return
}
try {
await authStore.confirmEmail(token)
state.value = 'success'
startCountdown()
} catch (e: unknown) {
error.value = e instanceof Error ? e.message : '确认链接无效或已过期'
state.value = 'failed'
}
})
onUnmounted(() => { if (timer) clearInterval(timer) })
</script>
<template>
<div class="min-h-[calc(100vh-4rem)] px-4 py-10">
<div class="mx-auto max-w-3xl">
<NCard class="oc-panel-card-xl">
<NResult v-if="state === 'success'" status="success" title="邮箱确认成功" description="现在可以使用邮箱和密码登录。">
<template #footer>
<div class="space-y-4">
<p class="text-sm text-slate-500">{{ countdown }} 秒后自动前往登录页面</p>
<RouterLink to="/login" class="no-underline"><NButton type="default" class="oc-panel-button oc-panel-button--teal">立即登录</NButton></RouterLink>
</div>
</template>
</NResult>
<NResult v-else-if="state === 'failed'" status="error" title="邮箱确认失败" :description="error">
<template #footer>
<RouterLink to="/resend-confirmation" class="no-underline"><NButton type="default" class="oc-panel-button oc-panel-button--sky">重新发送验证邮件</NButton></RouterLink>
</template>
</NResult>
<div v-else class="flex flex-col items-center justify-center py-12 text-center">
<NSpin size="large" />
<h1 class="mt-6 text-2xl font-bold text-slate-900">正在确认邮箱...</h1>
<p class="mt-2 text-slate-500">请稍候</p>
</div>
</NCard>
</div>
</div>
</template>