Files
opencloud/src/views/auth/LoginView.vue
T
2026-05-30 00:39:20 +08:00

154 lines
5.5 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<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>