62 lines
2.0 KiB
Vue
62 lines
2.0 KiB
Vue
<script setup lang="ts">
|
|
import { ref } from 'vue'
|
|
import { useRouter } from 'vue-router'
|
|
import { ElButton, ElInput } from 'element-plus'
|
|
import BookMark from '../components/BookMark.vue'
|
|
import { useSessionStore } from '../stores/session'
|
|
const session = useSessionStore()
|
|
const router = useRouter()
|
|
const username = ref('')
|
|
const password = ref('')
|
|
const busy = ref(false)
|
|
const error = ref('')
|
|
async function submit() {
|
|
if (busy.value) return
|
|
error.value = ''
|
|
session.notice = ''
|
|
if (!username.value.trim() || !password.value) {
|
|
error.value = '请输入账号和密码。'
|
|
return
|
|
}
|
|
busy.value = true
|
|
try {
|
|
await session.login(username.value.trim(), password.value)
|
|
if (session.user) await router.replace('/')
|
|
} catch (reason) {
|
|
error.value = reason instanceof Error ? reason.message : '登录失败,请稍后重试。'
|
|
session.notice = ''
|
|
} finally {
|
|
password.value = ''
|
|
busy.value = false
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div class="login-page">
|
|
<aside class="welcome">
|
|
<div class="brand">LexGo<span class="brand-dot">.</span></div>
|
|
<div class="welcome-copy">
|
|
<BookMark />
|
|
</div>
|
|
</aside>
|
|
<main class="login-main">
|
|
<div class="login-form">
|
|
<h1>欢迎回来</h1>
|
|
<p v-if="error || session.notice" role="alert" class="notice">{{ error || session.notice }}</p>
|
|
<form @submit.prevent="submit">
|
|
<div class="field">
|
|
<label for="username">账号</label>
|
|
<ElInput id="username" v-model="username" type="text" autocomplete="username" placeholder="请输入账号" :disabled="busy" />
|
|
</div>
|
|
<div class="field">
|
|
<label for="password">密码</label>
|
|
<ElInput id="password" v-model="password" type="password" autocomplete="current-password" placeholder="请输入密码" show-password :disabled="busy" />
|
|
</div>
|
|
<ElButton class="login-submit" type="primary" native-type="submit" :loading="busy">登录</ElButton>
|
|
</form>
|
|
</div>
|
|
</main>
|
|
</div>
|
|
</template>
|