Files
base-vite/src/views/Login.vue
2025-07-09 20:36:32 +08:00

186 lines
3.6 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.

<template>
<div class="login">
<div class="login-card">
<h2>用户登录</h2>
<form @submit.prevent="handleLogin">
<div class="form-group">
<label for="username">用户名</label>
<input
id="username"
v-model="loginForm.username"
type="text"
placeholder="请输入用户名"
required
/>
</div>
<div class="form-group">
<label for="password">密码</label>
<input
id="password"
v-model="loginForm.password"
type="password"
placeholder="请输入密码"
required
/>
</div>
<button type="submit" class="login-btn" :disabled="loading">
{{ loading ? '登录中...' : '登录' }}
</button>
</form>
<div class="tips">
<p>提示输入任意用户名和密码即可登录</p>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { useUserStore } from '../stores/modules/user'
const router = useRouter()
const route = useRoute()
const userStore = useUserStore()
const loading = ref(false)
const loginForm = ref({
username: '',
password: ''
})
const handleLogin = async () => {
if (!loginForm.value.username || !loginForm.value.password) {
alert('请输入用户名和密码')
return
}
loading.value = true
try {
const result = await userStore.login(loginForm.value)
if (result.success) {
// 登录成功,跳转到目标页面或首页
const redirect = route.query.redirect as string || '/'
await router.push(redirect)
} else {
alert(result.error || '登录失败')
}
} catch (error) {
console.error('登录错误:', error)
alert('登录失败,请稍后重试')
} finally {
loading.value = false
}
}
</script>
<style scoped>
.login {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
padding: 1rem;
}
.login-card {
background: white;
padding: 2rem;
border-radius: 8px;
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
width: 100%;
max-width: 400px;
}
.login-card h2 {
text-align: center;
margin-bottom: 2rem;
color: #2d3748;
}
.form-group {
margin-bottom: 1.5rem;
}
.form-group label {
display: block;
margin-bottom: 0.5rem;
color: #4a5568;
font-weight: 500;
}
.form-group input {
width: 100%;
padding: 0.75rem;
border: 1px solid #e2e8f0;
border-radius: 6px;
font-size: 1rem;
transition: border-color 0.2s;
}
.form-group input:focus {
outline: none;
border-color: #3182ce;
box-shadow: 0 0 0 3px rgba(49, 130, 206, 0.1);
}
.login-btn {
width: 100%;
padding: 0.75rem;
background: #3182ce;
color: white;
border: none;
border-radius: 6px;
font-size: 1rem;
cursor: pointer;
transition: background-color 0.2s;
}
.login-btn:hover:not(:disabled) {
background: #2c5aa0;
}
.login-btn:disabled {
opacity: 0.6;
cursor: not-allowed;
}
.tips {
margin-top: 1.5rem;
text-align: center;
}
.tips p {
color: #718096;
font-size: 0.875rem;
margin: 0;
}
[data-theme="dark"] .login-card {
background: #2d3748;
}
[data-theme="dark"] .login-card h2 {
color: #e2e8f0;
}
[data-theme="dark"] .form-group label {
color: #a0aec0;
}
[data-theme="dark"] .form-group input {
background: #4a5568;
border-color: #4a5568;
color: #e2e8f0;
}
[data-theme="dark"] .tips p {
color: #a0aec0;
}
</style>