一、保存token,登录使用
index.js
//保存token
localSet(key, value) {
window.localStorage.setItem(key, JSON.stringify(value))
}
login.vue登录页
<script setup>
//登录
const loginMethod = async (data) => {
const params = {
username: data.name,
password: data.pass
}
const res = await http.login(params)
if (res && res.success) {
getLoginResourceTreeData()
const data = res.data
const { id, name, sessionId } = data
utils.localSet('token', sessionId)
utils.localSet('userid', id)
utils.localSet('username', name)
store
.dispatch('user/setUserInfo', data)
.then(() => {})
.catch((res) => {
loading.close()
})
} else {
utils.message('error', res.info, 3000)
loading.close()
}
}
//获取用户属实对应菜单
const getLoginResourceTreeData = async () => {
const params = { resourceCode: '0' }
const res = await http.getLoginResourceTree(params)
if (res && res.success) {
const data = res.data
store
.dispatch('user/getSystemMenus', data)
.then(() => {
router.push('/home')
loading.close()
})
.catch((res) => {
loading.close()
})
} else {
utils.message('error', res.info, 2000)
loading.close()
}
}
//登录确认
const submitForm = (formEl) => {
loading = ElLoading.service({
lock: true,
text: '登录中......',
background: 'rgba(17,28,189,0.25)'
})
if (!formEl) return
formEl.validate((valid) => {
if (valid) {
loginMethod(ruleForm)
} else {
console.log('error submit!')
return false
}
})
}
</script>
<template>
<div>
<el-form ref="ruleFormRef" :model="ruleForm" :rules="rules" class="login-form">
<el-form-item class="item" prop="name">
<template #label>
<el-icon class="label-icon"><User /></el-icon>
</template>
<el-input class="inp" v-model="ruleForm.name" placeholder="请输入账号"></el-input>
</el-form-item>
<el-form-item class="item" prop="pass">
<template #label>
<el-icon class="label-icon"><PassWord /></el-icon>
</template>
<el-input
class="inp"
v-model="ruleForm.pass"
type="password"
@keyup.enter="submitForm(ruleFormRef)"
:show-password="true"
placeholder="请输入密码"
></el-input>
</el-form-item>
<el-form-item class="item center">
<el-button class="login-bt" @click="submitForm(ruleFormRef)">登录</el-button>
</el-form-item>
</el-form>
</div>
</template>
二、获取token
index.js
//获取token
localGet(key) {
const value = window.localStorage.getItem(key)
try {
return JSON.parse(window.localStorage.getItem(key))
} catch (error) {
return value
}
},
//获取token
export function localGet(key) {
const value = window.localStorage.getItem(key)
try {
return JSON.parse(window.localStorage.getItem(key))
} catch (error) {
return value
}
}
/src/router/index.js使用
import { createRouter, createWebHashHistory } from 'vue-router'
import store from '@store'
import utils from '@utils'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import { initDynamicRouter } from '@/router/modules/dynamicRouter'
import { staticRouter, errorRouter } from '@/router/modules/staticRouter'
const { localGet, setPageTitle } = utils
const router = createRouter({
history: createWebHashHistory(),
routes: [...staticRouter, ...errorRouter],
strict: true
})
/**
* @description 路由守卫
* */
router.beforeEach(async (to, from, next) => {
// debugger
const hasToken = localGet('token')
NProgress.start()
document.title = setPageTitle(to.meta.title)
if (to.path === '/login') {
if (!hasToken) return next()
else return next(from.fullPath)
}
if (!hasToken) return next('/login')
if (!store.state.user.routeName.length && to.name !== 'Home') {
initDynamicRouter()
return next({ ...to, replace: true })
} else {
next()
store.dispatch('user/removeLoadMenu')
}
})
/**
* @description 路由结束回调
* */
router.afterEach(() => {
NProgress.done()
})
/**
* @description 错误路由回调
* */
router.onError((handler) => {
NProgress.done()
console.log('路由错误:', handler)
})
/**
* @description 重置路由
* */
export const resetRouter = () => {
const flatMenuListGet = store.state.user.routeName
flatMenuListGet.forEach((route) => {
const { name } = route
router.removeRoute(name)
})
}
export default router
common/header.vue
watch(
() => store.state.user.token,
(newValue, oldValue) => {
if (newValue) {
state.goShow = true
state.userName = utils.localGet('username')
} else {
state.goShow = false
state.userName = '游客'
}
}
)
onMounted(() => {
if (store.state.user.token) {
state.goShow = true
state.userName = utils.localGet('username')
state.userId = store.state.user.userInfo.id
}
})
三、移除本地存储的token
localRemove(key) {
window.localStorage.removeItem(key)
},
/src/api/axios.js
import axios from 'axios'
import store from '@/store/index.js'
import router from '@/router/index.js'
import { ElMessageBox, ElMessage } from 'element-plus'
import { netConfig } from '@/config/net.config'
import utils from '@utils'
const { baseURL, contentType, invalidCode, noPermissionCode, requestTimeout, successCode } = netConfig
let tokenLose = true
/**
* @description 处理code异常
* @param {*} code
* @param {*} msg
*/
const handleCode = (code, msg) => {
console.log('处理code异常-code', code)
console.log('处理code异常-msg', msg)
switch (code) {
case invalidCode:
tokenLose = false
ElMessageBox.confirm('您已掉线,或者访问权限出错,请重新登录!', '重新登录', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(async () => {
// 处理重新登录逻辑
router.push({
path: '/login'
})
window.location.replace().catch((err) => {
console.log('访问出错或者掉线,跳转到登录页面:', err)
})
})
.catch(() => {
tokenLose = true
})
break
case noPermissionCode:
router.push({ path: '/404' }).catch(() => {
console.log('访问出错,跳转到404页面!')
})
break
case 404:
utils.message('error', '服务不存在,请检查服务请求路径是否正确', 3000)
break
case 502:
utils.message('error', '内部服务错误,请联系管理员', 3000)
break
default:
utils.message('error', code + msg, 3000)
break
}
}
const Axios = axios.create({
baseURL,
timeout: requestTimeout,
headers: {
'Content-Type': contentType
}
})
// 请求拦截器
Axios.interceptors.request.use(
(config) => {
//是否允许请求带有验证信息
config.headers['Access-Control-Allow-Credentials'] = false
//允许脚本访问的返回头
config.headers['Access-Control-Allow-Headers'] = 'x-requested-with,content-type,Cache-Control,Pragma,Date,x-timestamp'
//允许使用的请求方法,以逗号隔开
config.headers['Access-Control-Allow-Methods'] = 'POST,GET,OPTIONS,PUT,DELETE'
// 处理token header信息
if (store.getters.token) {
// config.headers['Authorization'] = ''
}
return config
},
(error) => {
return Promise.reject(error)
}
)
// 响应拦截器
Axios.interceptors.response.use(
(response) => {
const res = response.data
const { data, status, message } = response
const { info, success } = data
// 操作成功
if (successCode.indexOf(status) !== -1) {
//info.includes('未登录')
// console.log('拦截器:',info)
if (info == '未登录') {
//判断登录是否过期
utils.localRemove('token')
utils.localRemove('userid')
utils.localRemove('username')
store.dispatch('user/removeUserInfo')
const data = {
menuStyle: {
main_aside: '0px',
aside_box: '0px',
main_content: utils.fontSize(1840) + 'px',
flag: false
}
}
store.dispatch('style/setMenusInfo', data).then(() => {
router.push('/login')
})
return res
} else {
return res
}
} else {
handleCode(status, message)
return Promise.reject(response)
}
},
(error) => {
const { response, message } = error
if (error.response && error.response.data) {
const { status, statusText } = response
handleCode(status, statusText)
// return Promise.reject(error)
return Promise.reject(error.response)
} else {
let { message } = error
if (message === 'Network Error') {
message = '后端接口连接异常'
}
if (message.includes('timeout')) {
message = '后端接口请求超时'
}
if (message.includes('Request failed with status code')) {
const code = message.substr(message.length - 3)
message = '后端接口' + code + '异常'
}
ElMessage(message || `后端接口未知异常`, 'error')
return Promise.reject(error)
}
}
)
Axios.prefix = '/st_api'
export default Axios
/common/header
//退出
const logout = async () => {
const res = await http.logout({})
if (res && res.success) {
utils.localRemove('token')
utils.localRemove('userid')
utils.localRemove('username')
store
.dispatch('user/removeUserInfo')
.then(() => {
store.dispatch('style/removeMenusInfo')
router.push('/login')
})
.catch((res) => {
console.log('退出错误!', res)
})
} else {
utils.message('error', res.info, 3000)
}
}