| <template> | |
| <div class="login-page"> | |
| <!-- 背景装饰 --> | |
| <div class="bg-decoration"> | |
| <div class="shape shape-1"></div> | |
| <div class="shape shape-2"></div> | |
| <div class="shape shape-3"></div> | |
| </div> | |
| <!-- 登录表单容器 --> | |
| <div class="login-container"> | |
| <div class="login-card"> | |
| <!-- 头部信息 --> | |
| <div class="login-header"> | |
| <div class="logo"> | |
| <el-icon size="48" color="#667eea"><Operation /></el-icon> | |
| </div> | |
| <h1 class="title">PT Tracker</h1> | |
| <p class="subtitle">私有种子分享社区</p> | |
| </div> | |
| <!-- 登录表单 --> | |
| <el-form | |
| ref="loginFormRef" | |
| :model="loginForm" | |
| :rules="loginRules" | |
| class="login-form" | |
| size="large" | |
| > | |
| <el-form-item prop="user"> | |
| <el-input | |
| v-model="loginForm.user" | |
| placeholder="请输入用户名或邮箱" | |
| clearable | |
| :prefix-icon="User" | |
| @keyup.enter="handleLogin" | |
| /> | |
| </el-form-item> | |
| <el-form-item prop="password"> | |
| <el-input | |
| v-model="loginForm.password" | |
| type="password" | |
| placeholder="请输入密码" | |
| show-password | |
| :prefix-icon="Lock" | |
| @keyup.enter="handleLogin" | |
| /> | |
| </el-form-item> | |
| <el-form-item> | |
| <div class="login-options"> | |
| <el-checkbox v-model="rememberMe">记住登录</el-checkbox> | |
| <el-link type="primary" :underline="false">忘记密码?</el-link> | |
| </div> | |
| </el-form-item> | |
| <el-form-item> | |
| <el-button | |
| type="primary" | |
| :loading="loginLoading" | |
| style="width: 100%" | |
| @click="handleLogin" | |
| > | |
| <span v-if="!loginLoading">登录</span> | |
| <span v-else>登录中...</span> | |
| </el-button> | |
| </el-form-item> | |
| </el-form> | |
| <!-- 底部链接 --> | |
| <div class="login-footer"> | |
| <span class="footer-text">还没有账号?</span> | |
| <el-link | |
| type="primary" | |
| :underline="false" | |
| @click="$router.push('/register')" | |
| > | |
| 立即注册 | |
| </el-link> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </template> | |
| <script> | |
| import { ref, reactive, computed } from 'vue' | |
| import { useRouter } from 'vue-router' | |
| import { useStore } from 'vuex' | |
| import { ElMessage } from 'element-plus' | |
| import { User, Lock, Operation } from '@element-plus/icons-vue' | |
| export default { | |
| name: 'LoginView', | |
| components: { | |
| Operation | |
| }, | |
| setup() { | |
| const router = useRouter() | |
| const store = useStore() | |
| const loginFormRef = ref() | |
| const rememberMe = ref(false) | |
| // 安全地从store获取登录加载状态,添加防护检查 | |
| const loginLoading = computed(() => { | |
| try { | |
| return store?.getters?.['auth/loginLoading'] || false | |
| } catch (error) { | |
| console.warn('获取 loginLoading 状态失败:', error) | |
| return false | |
| } | |
| }) | |
| // 表单数据 | |
| const loginForm = reactive({ | |
| user: '', | |
| password: '' | |
| }) | |
| // 验证规则 | |
| const loginRules = { | |
| user: [ | |
| { required: true, message: '请输入用户名或邮箱', trigger: 'blur' }, | |
| { min: 3, message: '用户名至少3个字符', trigger: 'blur' } | |
| ], | |
| password: [ | |
| { required: true, message: '请输入密码', trigger: 'blur' }, | |
| { min: 6, message: '密码至少6个字符', trigger: 'blur' } | |
| ] | |
| } | |
| // 登录处理 | |
| const handleLogin = async () => { | |
| try { | |
| // 表单验证 | |
| if (!loginFormRef.value) { | |
| ElMessage.error('表单未准备就绪') | |
| return | |
| } | |
| const valid = await loginFormRef.value.validate() | |
| if (!valid) return | |
| // 检查 store 是否可用 | |
| if (!store) { | |
| ElMessage.error('系统初始化失败,请刷新页面重试') | |
| return | |
| } | |
| // 调用store的登录action | |
| await store.dispatch('auth/login', { | |
| user: loginForm.user, | |
| password: loginForm.password | |
| }) | |
| // 如果选择记住登录,设置localStorage标记 | |
| if (rememberMe.value) { | |
| localStorage.setItem('rememberLogin', 'true') | |
| } | |
| // 登录成功,跳转到首页 | |
| router.push('/home') | |
| } catch (error) { | |
| console.error('登录失败:', error) | |
| ElMessage.error(error.message || '登录失败,请重试') | |
| } | |
| } | |
| return { | |
| loginFormRef, | |
| loginForm, | |
| loginRules, | |
| loginLoading, | |
| rememberMe, | |
| handleLogin, | |
| User, | |
| Lock | |
| } | |
| } | |
| } | |
| </script> |