1. 登录流程
- 提交用户名密码
- 后端校验成功后返回及用户相关信息
- 本地存储相关信息
- 跳转首页
2. 使用pinia保存用户信息
在src/stores/userInfo.ts, 创建pina 保存用户信息
import { defineStore } from "pinia"
import {ref} from 'vue'
export const useUserInfoStore = defineStore('userInfo', () => {
const userInfo = ref<Record<string, any>>()
const permissionList = ref<Array<string>>([])
const roleList = ref<Array<string>>([])
const setInfo = (newInfo: Record<string, any>, newPermissionList: Array<string>, newRoleList: Array<string> ) => {
userInfo.value = newInfo
permissionList.value = newPermissionList
roleList.value = newRoleList
}
const removeInfo = () => {
userInfo.value = {}
permissionList.value = []
roleList.value = []
}
return {userInfo, setInfo, removeInfo, permissionList, roleList}
},
{
persist: true
}
)
3. 使用ts接口规范数据
在src/interface/auth/LoginData.ts
// 登录数据接口
export interface LoginData {
username: string,
password: string,
rememberMe: boolean
}
4. 封装axios请求函数
在src/api/auth/index.ts
import axiosInstance from '@/request/axios-config'
import type { LoginData } from '@/interface/auth/index'
// 登录
export const loginService = (longData: LoginData): Promise<any> =>{
return axiosInstance.post('/auth/login', longData)
}
5. 登录
src/views/Login.vue
<template>
<!-- 根div -->
<div class="login_container">
<div class="login_form">
<h2 class="title">Vue3 TS Vite Springboot3 快速开发平台</h2>
<el-form :model="loginForm" ref="ruleFormRef" :rules="rules">
<!-- 用户名 -->
<el-form-item prop="username">
<el-input v-model="loginForm.username" placeholder="请输入账号">
<template #prefix>
<el-icon class="el-input__icon"><i-ep-User /></el-icon>
</template>
</el-input>
</el-form-item>
<!-- 密码 -->
<el-form-item prop="password">
<el-input v-model="loginForm.password" type="password" placeholder="请输入密码">
<template #prefix>
<el-icon class="el-input__icon"><i-ep-Lock /></el-icon>
</template>
</el-input>
</el-form-item>
<!-- 记住我和忘记密码 -->
<div class="rememberMe">
<el-checkbox v-model="loginForm.rememberMe" label="记住我" size="large" />
<!-- 忘记密码 -->
<el-text class="forgetpass mx-1" type="primary">忘记密码?</el-text>
</div>
<!-- 分割线 -->
<el-divider>其他登录方式</el-divider>
<!-- 其他的登录方式 -->
<div class="other_login">
<el-icon class="other_login_item"><i-epChromeFilled /></el-icon>
<el-icon class="other_login_item"><i-ep-ElemeFilled /></el-icon>
<el-icon class="other_login_item"><i-ep-wind-power /></el-icon>
</div>
<el-form-item>
<!-- 按钮 -->
<el-button style="width: 100%;" type="primary" @click="handleLogin">登录</el-button>
</el-form-item>
</el-form>
</div>
</div>
</template>
<script setup lang="ts">
import { reactive, ref } from 'vue';
// 导入login方法
import { loginService } from '@/api/auth'
import type { LoginData } from '@/interface/auth/index'
import type { FormInstance, FormRules } from 'element-plus'
import {useTokenStore } from '@/stores/token'
import {useUserInfoStore} from '@/stores/userInfo'
import {useRouter} from 'vue-router'
const tokenStore = useTokenStore()
const userInfoStore = useUserInfoStore()
const router = useRouter()
// 声明表单绑定值
const loginForm = reactive<LoginData>({
username: 'admin',
password: '123456',
rememberMe: false
})
// 声明 登录 方法
const handleLogin = async () => {
// 校验表单
if (!ruleFormRef.value) return
let validata
try {
await ruleFormRef.value.validate(async (valid) => {
console.log("login validate", valid)
if (valid) {
// 调用接口,完成登录
try {
let result = await loginService(loginForm)
if (result.code == 0) {
ElMessage.success(result.messge ? result.messge : '登录成功')
//token存储到pinia中
let tokenInfo = result.data.saTokenInfo;
tokenStore.setToken(tokenInfo.tokenName, tokenInfo.tokenValue)
// 存储用户信息
let data = result.data;
userInfoStore.setInfo(data.userInfo, data.permissionList, data.roleLabelList)
//跳转到首页 路由完成跳转
router.push('/index')
return
} else {
ElMessage.error(result.messge ? result.messge : '登录失败')
}
} catch (e) {
console.error("login:", e)
}
} else {
//console.log("输入信息校验失败")
return
}
})
} catch (e) {
console.log("exception:", e)
ElMessage.info('登录信息校验失败')
}
}
// 定义表单组件的引用
const ruleFormRef = ref<FormInstance>()
//定义表单校验规则
const rules = ref<FormRules<LoginData>>({
username: [{
required: true,
message: '请输入用户名',
trigger: 'blur'
},
{
min: 5,
max: 16,
message: '长度为5~16位非空字符',
trigger: 'blur'
}
],
password: [{
required: true,
message: '请输入密码',
trigger: 'blur'
},
{
min: 4,
max: 16,
message: '长度为5~16位非空字符',
trigger: 'blur'
}
]
})
</script>
<style lang="scss" scoped>
.login_container {
// 背景图
background-image: url('../assets/bgimg/bg1.jpg');
background-size: 100%;
height: 100vh;
display: flex;
justify-content: flex-end;
.login_form {
display: flex;
justify-content: center;
align-items: center;
//设置换行
flex-direction: column;
width: 50%;
background-color: #fff;
.title {
margin-bottom: 80px;
}
.rememberMe {
display: flex;
justify-content: space-between;
align-items: center;
.forgetpass {
cursor: pointer;
}
}
// 其他登录
.other_login {
display: flex;
justify-content: center;
margin-bottom: 20px;
.other_login_item {
margin-right: 60px;
cursor: pointer;
}
}
}
}
// 设置form的宽度
.el-form {
width: 60%;
}
.el-form-item {
width: 100%;
}
</style>