前端登陆业务逻辑
- 封装axios
- 封装接口请求
- 封装登录请求动作
- 保存服务端返回的token
- 登录鉴权
代码实现
- 创建登录表单
<template>
<div class="login-container">
<el-form
class="login-form"
ref="loginFormRef"
:model="loginForm"
:rules="loginRules"
>
<div class="title-container">
<h3 class="title">用户登陆</h3>
</div>
<!-- username -->
<el-form-item prop="username">
<span class="svg-container">
<svg-icon icon="user"></svg-icon>
</span>
<el-input
placeholder="username"
name="username"
type="text"
v-model="loginForm.username"
></el-input>
</el-form-item>
<!-- password -->
<el-form-item prop="password">
<span class="svg-container">
<svg-icon icon="password"></svg-icon>
</span>
<el-input
placeholder="password"
name="password"
:type="passwordType"
v-model="loginForm.password"
></el-input>
<span class="show-pwd">
<span class="svg-container" @click="onChangePwdType">
<svg-icon
:icon="passwordType === 'password' ? 'eye' : 'eye-open'"
></svg-icon>
</span>
</span>
</el-form-item>
<!-- 登陆按钮 -->
<el-button
type="primary"
style="width: 100%; margin-bottom: 30px"
:loading="loading"
@click="handlerLogin"
>
登陆
</el-button>
</el-form>
</div>
</template>
- 数据源
// 数据源
const loginForm = ref({
username: 'sysadmin@thingsboard.org',
password: 'sysadmin'
})
- 封装验证规则
// 外部封装规则
export const validatePassword = () => {
return (rule, value, callback) => {
if (value.length < 6) {
callback(new Error('密码不能小于6位'))
} else {
callback()
}
}
}
// 验证规则
const loginRules = ref({
username: [
{
required: true,
trigger: 'blur',
message: '用户名为必填项'
}
],
password: [
{
required: true,
trigger: 'blur',
validator: validatePassword()
}
]
})
// 处理密码框文本显示
const passwordType = ref('password')
// template中绑定的方法直接声明即可
const onChangePwdType = () => {
// 当passwordType的值为password的时候改为text
// 使用ref声明的数据,在script中使用时需要加value来获取具体的值 Templates中使用的时候 不需要加value
if (passwordType.value === 'password') {
passwordType.value = 'text'
} else {
passwordType.value = 'password'
}
}
- 处理登录请求
// 处理登陆
const loading = ref(false)
const store = useStore()
const loginFormRef = ref(null)
const handlerLogin = () => {
// 进行表单校验
// console.log(loginFormRef.value)
loginFormRef.value.validate((valid) => {
if (!valid) return
// 触发登陆动作
loading.value = true
store
.dispatch('user/login', loginForm.value)
.then(() => {
loading.value = false
// 进行登陆后处理
})
.catch((err) => {
console.log(err)
loading.value = false
})
})
}
- 封装登录请求动作
import { login } from '@/api/sys'
// import md5 from 'md5'
import { setItem, getItem } from '@/utils/storage'
import { TOKEN, REFRESHTOKEN } from '@/constant'
import router from '@/router'
export default {
namespaced: true,
state: () => ({
token: getItem(TOKEN) || ''
}),
mutations: {
setToken(state, data) {
state.token = data.token
setItem(TOKEN, data.token)
setItem(REFRESHTOKEN, data.refreshToken)
}
},
/**
* 登陆请求动作
*/
actions: {
login(context, userInfo) {
const { username, password } = userInfo
return new Promise((resolve, reject) => {
login({
username,
password
// password: md5(password)
})
.then((data) => {
// console.log(data)
this.commit('user/setToken', data)
// 跳转
router.push('/')
resolve()
})
.catch((err) => {
reject(err)
})
})
}
}
}
- 创建响应拦截器
import axios from 'axios'
import { ElMessage } from 'element-plus'
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API,
timeout: 5000
})
// 响应拦截器
service.interceptors.response.use(
// 请求成功
(response) => {
const data = response.data
// 需要判断当前请求是否成功
if (data != null) {
// 成功返回解析后的数据
const message1 = '-登陆成功-'
ElMessage.success(message1)
return data
} else {
// 失败(请求成功,业务失败) 消息提示
const message1 = '-请求成功,业务失败-'
ElMessage.error(message1)
return Promise.reject(new Error(message1))
}
},
// 请求失败
(error) => {
const message2 = '-请求失败-'
ElMessage.error(message2)
return Promise.reject(error)
}
)
export default service
设置登录鉴权
import { createRouter, createWebHashHistory } from 'vue-router'
/**
* 公开路由表
*/
const publicRoutes = [
{
path: '/login',
component: () => import('@/views/login/index')
},
{
path: '/',
component: () => import('@/layout/index')
}
]
const router = createRouter({
history: createWebHashHistory(),
routes: publicRoutes
})
export default router
- 前置导航守卫
import router from '@/router'
import store from '@/store'
// 白名单
const whileList = ['/login']
/**
* 路由前置守卫
* @param {*} to 要到那里去
* @param {*} from 你从哪里来
* @param {*} next 是否要去
*/
router.beforeEach((to, from, next) => {
// 用户以登陆,不允许进入login
// 用户未登陆,只允许进入login
if (store.getters.token) {
// 用户以登陆,不允许进入login
if (to.path === '/login') {
next('/')
} else {
next()
}
} else {
// 用户未登陆,只允许进入login
if (whileList.indexOf(to.path) > -1) {
next()
} else {
next('/login')
}
}
})