foreign-admin-ui/src/views/User/Login.vue

141 lines
5.2 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="user-container">
<div class="card">
<!-- 头部标题 -->
<div class="header">
<h1>登录 👋</h1>
</div>
<el-form :model="LoginForm" :rules="formRules" ref="loginFormRef" class="login-form" size="default">
<!-- 用户名输入 -->
<el-form-item label="用户名" prop="username" :label-position="labelPosition" label-width="65px">
<el-input v-model="LoginForm.email" placeholder="请输入用户名" :prefix-icon="User" />
</el-form-item>
<!-- 密码输入 -->
<el-form-item label="密码" prop="password" :label-position="labelPosition" label-width="65px">
<el-input v-model="LoginForm.password" type="password" placeholder="请输入密码" :prefix-icon="Lock"
show-password />
</el-form-item>
<!-- 记住账号 & 忘记密码 -->
<el-form-item class="form-footer">
<div class="form-footer-content">
<el-checkbox v-model="LoginForm.remember" class="remember-checkbox">记住账号</el-checkbox>
<router-link to="/reset-password" class="forgot-password">忘记密码?</router-link>
</div>
</el-form-item>
<!-- 登录按钮Element Plus 主按钮规范) -->
<el-form-item width="100%">
<el-button type="primary" class="login-btn" size="large" @click="handleLogin" style="width: 100%"
:loading="userStore.loading" :disabled="userStore.loading">
{{ userStore.loading ? '登录中...' : '登录' }}
</el-button>
</el-form-item>
</el-form>
</div>
</div>
</template>
<script setup lang="ts">
// element 导入
import type { FormInstance, FormRules, FormProps } from 'element-plus'
import { User, Lock } from '@element-plus/icons-vue'
// type导入
import type { LoginForm as LoginFormType } from '@/type/user'
// 业务导入
import { useUserStore } from '@/stores/user'
import { useLocalStorage, useSessionStorage } from '@/utils/storage'
// 加密导入
import { encryptPassword } from '@/utils/encrypt'
const router = useRouter()
const error = ref('')
const userStore = useUserStore()
// 表单 Ref符合 Element Plus 规范
const loginFormRef = ref<FormInstance>()
const labelPosition = ref<FormProps['labelPosition']>('left')
// 表单数据
const LoginForm = reactive<LoginFormType>({
email: '1241208486@qq.com',
password: encryptPassword('888888'),
login_type: 1,
})
// 表单校验规则Element Plus 标准校验)
const formRules = reactive<FormRules>({
email: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
password: [{ required: true, message: '请输入密码', trigger: 'blur' }]
})
// 登录
const handleLogin = async () => {
if (!loginFormRef.value) return
loginFormRef.value.validate(async (valid) => {
if (valid) {
try {
error.value = ''
await userStore.login(LoginForm)
saveRememberedUsername()
// 如果是登录或者退出登录重新登录,都是跳转首页,如果是从修改密码操作返回登录页,就跳转回修改密码操作前的页面
const isChangePassword = useSessionStorage.get('changePassword');
const backPath = useSessionStorage.get('backPath') || '/';
// 2. 先清理 sessionStorage避免残留执行顺序关键
useSessionStorage.remove('changePassword');
useSessionStorage.remove('backPath');
// 3. 重置菜单折叠状态(提前执行,避免跳转中断)
useLocalStorage.set('isCollapse', false);
const targetPath = isChangePassword ? backPath : '/';
router.push(typeof targetPath === 'string' ? targetPath : targetPath.value || '/');
} catch (err) {
error.value = err instanceof Error ? err.message : '登录失败'
}
} else {
console.log('登录表单验证失败')
}
})
}
// 记住账号
const saveRememberedUsername = () => {
if (LoginForm.remember) {
useLocalStorage.set('rememberedUsername', LoginForm.email)
} else {
useLocalStorage.remove('rememberedUsername')
}
}
// 从本地存储加载记住的用户名
const loadRememberedUsername = () => {
const rememberedUsername = useLocalStorage.get('rememberedUsername')
if (rememberedUsername.value) {
LoginForm.email = rememberedUsername.value
LoginForm.remember = true
}
}
onMounted(() => {
// 组件挂载时加载记住的用户名
loadRememberedUsername()
})
</script>
<style lang="scss" scoped>
.login-form {
.form-footer {
.form-footer-content {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
.forgot-password {
color: #409eff;
text-decoration: none;
}
}
}
}
</style>