e087dd46e2
Reviewed-on: #1
154 lines
5.5 KiB
Vue
154 lines
5.5 KiB
Vue
<script setup lang="ts">
|
||
import { ref } from 'vue'
|
||
import { useRouter, useRoute } from 'vue-router'
|
||
import { NAlert, NButton, NCard, NForm, NFormItem, NInput } from 'naive-ui'
|
||
import { useAuthStore } from '@/stores/auth'
|
||
|
||
const authStore = useAuthStore()
|
||
const router = useRouter()
|
||
const route = useRoute()
|
||
|
||
const email = ref('')
|
||
const password = ref('')
|
||
const error = ref('')
|
||
const resetMessage = ref('')
|
||
const resetMode = ref(false)
|
||
const loading = ref(false)
|
||
const resetLoading = ref(false)
|
||
|
||
async function handleLogin() {
|
||
error.value = ''
|
||
loading.value = true
|
||
try {
|
||
await authStore.login(email.value, password.value)
|
||
const redirect = (route.query.redirect as string) || '/'
|
||
router.push(redirect)
|
||
} catch (e: unknown) {
|
||
error.value = e instanceof Error ? e.message : '登录失败,请稍后重试'
|
||
} finally {
|
||
loading.value = false
|
||
}
|
||
}
|
||
|
||
async function handleSendResetEmail() {
|
||
error.value = ''
|
||
resetMessage.value = ''
|
||
|
||
if (!email.value) {
|
||
error.value = '请输入需要重置密码的邮箱。'
|
||
return
|
||
}
|
||
|
||
resetLoading.value = true
|
||
try {
|
||
await authStore.sendPasswordReset(email.value)
|
||
resetMessage.value = '重置密码邮件已发送,请查收邮箱。'
|
||
} catch (e: unknown) {
|
||
error.value = e instanceof Error ? e.message : '重置邮件发送失败,请稍后重试'
|
||
} finally {
|
||
resetLoading.value = false
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<template>
|
||
<div class="min-h-[calc(100vh-4rem)] px-4 py-10">
|
||
<div class="mx-auto grid max-w-6xl gap-8 lg:grid-cols-[1.1fr_0.9fr] lg:items-center">
|
||
<section class="border border-slate-200 bg-[linear-gradient(135deg,#f0fdfa_0%,#ffffff_48%,#eff6ff_100%)] p-8 shadow-[10px_10px_0_0_rgba(15,23,42,0.08)]">
|
||
<p class="text-sm uppercase tracking-[0.26em] text-teal-700">Sky Log In</p>
|
||
<h1 class="mt-4 max-w-xl text-5xl font-black leading-[1.05] text-slate-900">
|
||
登录后继续记录
|
||
<span class="block text-teal-700">你眼中的每一朵云</span>
|
||
</h1>
|
||
<p class="mt-6 max-w-lg text-base leading-8 text-slate-600">
|
||
在地图、图鉴和画廊之间同步你的观测记录。上传新的云图后,图鉴会自动点亮,画廊也会按时间收纳你的作品。
|
||
</p>
|
||
<div class="mt-8 flex gap-4">
|
||
<div class="border border-slate-200 bg-white px-4 py-3">
|
||
<div class="text-xs uppercase tracking-[0.2em] text-slate-500">Collection</div>
|
||
<div class="mt-2 text-2xl font-bold text-slate-900">10</div>
|
||
<div class="mt-1 text-sm text-slate-500">基础云属待收集</div>
|
||
</div>
|
||
<div class="border border-slate-200 bg-white px-4 py-3">
|
||
<div class="text-xs uppercase tracking-[0.2em] text-slate-500">Mode</div>
|
||
<div class="mt-2 text-2xl font-bold text-slate-900">Atlas</div>
|
||
<div class="mt-1 text-sm text-slate-500">地图、图鉴、画廊一体</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<NCard class="shadow-[12px_12px_0_0_rgba(15,23,42,0.08)]">
|
||
<div class="mb-8">
|
||
<div class="text-sm uppercase tracking-[0.22em] text-slate-500">Member Access</div>
|
||
<h2 class="mt-3 text-3xl font-bold text-slate-900">登录 OpenCloud</h2>
|
||
<p class="mt-2 text-sm text-slate-500">输入邮箱和密码,继续你的天空档案。</p>
|
||
</div>
|
||
|
||
<NForm @submit.prevent="resetMode ? handleSendResetEmail() : handleLogin()">
|
||
<NFormItem label="邮箱">
|
||
<NInput
|
||
v-model:value="email"
|
||
required
|
||
autocomplete="email"
|
||
placeholder="your@email.com"
|
||
/>
|
||
</NFormItem>
|
||
|
||
<NFormItem v-if="!resetMode" label="密码">
|
||
<NInput
|
||
v-model:value="password"
|
||
type="password"
|
||
required
|
||
show-password-on="click"
|
||
autocomplete="current-password"
|
||
placeholder="输入密码"
|
||
/>
|
||
</NFormItem>
|
||
|
||
<p v-else class="mb-5 text-sm leading-6 text-slate-500">
|
||
输入注册邮箱,我们会发送一封密码重置邮件。点击邮件链接后即可设置新密码。
|
||
</p>
|
||
|
||
<NAlert v-if="error" type="error" class="mb-4">
|
||
{{ error }}
|
||
</NAlert>
|
||
|
||
<NAlert v-if="resetMessage" type="success" class="mb-4">
|
||
{{ resetMessage }}
|
||
</NAlert>
|
||
|
||
<NButton
|
||
attr-type="submit"
|
||
type="primary"
|
||
block
|
||
size="large"
|
||
class="oc-primary-button oc-primary-button--teal"
|
||
:loading="resetMode ? resetLoading : loading"
|
||
>
|
||
<template v-if="resetMode">
|
||
{{ resetLoading ? '发送中...' : '发送重置邮件' }}
|
||
</template>
|
||
<template v-else>
|
||
{{ loading ? '登录中...' : '登录' }}
|
||
</template>
|
||
</NButton>
|
||
</NForm>
|
||
|
||
<div class="mt-6 flex flex-wrap items-center justify-between gap-3 text-sm text-slate-500">
|
||
<p>
|
||
没有账号?
|
||
<RouterLink to="/register" class="font-semibold text-teal-700 hover:text-teal-800">去注册</RouterLink>
|
||
</p>
|
||
<button
|
||
type="button"
|
||
class="font-semibold text-teal-700 transition-colors hover:text-teal-800"
|
||
@click="resetMode = !resetMode; error = ''; resetMessage = ''"
|
||
>
|
||
{{ resetMode ? '返回登录' : '忘记密码?' }}
|
||
</button>
|
||
</div>
|
||
</NCard>
|
||
</div>
|
||
</div>
|
||
</template>
|