vue-element-template|实现登录,根据权限显示路由
文章目录前言一、安装vue-element-template基础模板?二、具体步骤1.修改路由文件2.挂载前的验证3.获取用户角色,保存一些从后台获得的roles相关信息4.筛选路由5.最后的加载6.别忘了修改登录、推出、获取用户信息路径三、遇到的bug1.data functions should return an object:2.配置后台api接口baseUrl不生效3.配置完第2部api
前言
在编辑vue-element-template之前,后台需要实现login等接口。
@RestController
@RequestMapping("/admin")
@CrossOrigin //解决跨域
public class LoginController {
//login
@PostMapping("login")
public R login(){
return R.ok().data("token","admin");
}
//info
@GetMapping("info")
public R info(){
List<String> roles = new ArrayList<>();
roles.add("test");
return R.ok().data("roles",roles).data("name","admin").data("avatar","https://scpic.chinaz.net/files/pic/pic9/201708/zzpic5968.jpg");
}
@PostMapping("logout")
public R logout(){
return R.ok();
}
}
注:roles要返回数据形式
一、安装vue-element-template基础模板?
下载安装链接:
注:这里使用的是基础模板: vue-admin-template。
二、具体步骤
1.修改路由文件
注意文件夹位置:src/router/index.js
添加asyncRoutes
代码如下(示例):
注意:要将 { path: ‘*’, redirect: ‘/404’, hidden: true }放在最后
//异步挂载的路由
//动态需要根据权限加载的路由表
export const asyncRoutes = [
{
path: '/example1',
component: Layout,
redirect: '/example/table',
name: 'Example',
meta: { title: 'Example', icon: 'el-icon-s-help' ,roles: ['test']},
children: [
{
path: 'table',
name: 'Table',
component: () => import('@/views/table/index'),
meta: { title: 'Table', icon: 'table' ,roles: ['test']}
},
{
path: 'tree',
name: 'Tree',
component: () => import('@/views/tree/index'),
meta: { title: 'Tree', icon: 'tree' ,roles: ['test']}
}
]
},
{ path: '*', redirect: '/404', hidden: true }
];
2.挂载前的验证
注意文件夹位置:src/permission.js
这里分了核心三步,第一步获取用户个人信息(角色);第二部筛选用户可以看见的路由;第三步更新加载路由
代码如下(示例):
router.beforeEach(async(to, from, next) => {
// start progress bar
NProgress.start()
// set page title
document.title = getPageTitle(to.meta.title)
// determine whether the user has logged in
const hasToken = getToken()
if (hasToken) {
if (to.path === '/login') { // 判断是否有token
// if is logged in, redirect to the home page
next({ path: '/' })
NProgress.done()
} else {
const hasGetUserInfo = store.getters.name
// const hasRoles = store.getters.roles && store.getters.roles.length > 0//这里指的是src/store/getters.js的roles
// console.log(hasRoles)
if (hasGetUserInfo) {// 判断当前用户是否已拉取完user_info信息
next()
} else {
try {
// get user info
await store.dispatch('user/getInfo') // 拉取info
//获取roles
const { roles } = await store.dispatch('user/getInfo')//第一步
console.log("roles:",roles)
// generate accessible routes map based on roles
//获取通过权限验证的路由
const accessRoutes = await store.dispatch('permission/generateRoutes', roles)//第二步
//更新加载路由
router.options.routes = store.getters.permission_routes//第三步
// dynamically add accessible routes
router.addRoutes(accessRoutes)
// console.log(store)
// hack method to ensure that addRoutes is complete
// set the replace: true, so the navigation will not leave a history record
next({ ...to, replace: true })
// next()
} catch (error) {
// remove token and go to login page to re-login
await store.dispatch('user/resetToken')
Message.error(error || 'Has Error')
next(`/login?redirect=${to.path}`)
NProgress.done()
}
}
}
} else {
/* has no token*/
if (whiteList.indexOf(to.path) !== -1) {
// in the free login whitelist, go directly
next()
} else {
// other pages that do not have permission to access are redirected to the login page.
next(`/login?redirect=${to.path}`)
NProgress.done()
}
}
})
3.获取用户角色,保存一些从后台获得的roles相关信息
注意文件夹位置:src/store/modules/user.js
注意roles和SET_ROLES是必须的
代码如下(示例):
const getDefaultState = () => {
return {
token: getToken(),
name: '',
avatar: '',
roles: []
}
}
const mutations = {
RESET_STATE: (state) => {
Object.assign(state, getDefaultState())
},
SET_TOKEN: (state, token) => {
state.token = token
},
SET_NAME: (state, name) => {
state.name = name
},
SET_AVATAR: (state, avatar) => {
state.avatar = avatar
},
SET_ROLES: (state, roles) => {
state.roles = roles
}
}
// get user info
getInfo({ commit, state }) {
return new Promise((resolve, reject) => {
getInfo(state.token).then(response => {
const { data } = response
if (!data) {
return reject('Verification failed, please Login again.')
}
const { name, avatar , roles } = data
if (!roles || roles.length <= 0) {
reject('getInfo: roles must be a non-null array!')
}
commit('SET_NAME', name)
commit('SET_AVATAR', avatar)
commit('SET_ROLES',roles)
resolve(data)
}).catch(error => {
reject(error)
})
})
},
修改src/store/getters.js
4.筛选路由
注意路径:src/store/modules/permission.js
若没有则新建
代码如下(示例):
import { asyncRoutes, constantRoutes } from '@/router'
/**
* Use meta.role to determine if the current user has permission
* @param roles
* @param route
*/
//匹配权限
function hasPermission(roles, route) {
if (route.meta && route.meta.roles) {
return roles.some(role => route.meta.roles.includes(role))
} else {
return true
}
}
/**
* Filter asynchronous routing tables by recursion
* @param routes asyncRoutes
* @param roles
*/
export function filterAsyncRoutes(routes, roles) {
const res = []
routes.forEach(route => {
const tmp = { ...route }
if (hasPermission(roles, tmp)) {
if (tmp.children) {
tmp.children = filterAsyncRoutes(tmp.children, roles)
}
res.push(tmp)
}
})
return res
}
const state = {
routes: [],
addRoutes: []
}
const mutations = {
SET_ROUTES: (state, routes) => {
state.addRoutes = routes
state.routes = constantRoutes.concat(routes) // 将过滤后的路由和constantRoutes存起来
}
}
//筛选
const actions = {
generateRoutes({ commit }, roles) {
return new Promise(resolve => {
let accessedRoutes
//路由是否有admin,有直接全部显示
if (roles.includes('admin')) {
accessedRoutes = asyncRoutes || []
} else {
//过滤路由
accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)
//accessedRoutes这个就是当前角色可见的动态路由
}
commit('SET_ROUTES', accessedRoutes)
resolve(accessedRoutes)
})
}
}
export default {
namespaced: true,
state,
mutations,
actions
}
5.最后的加载
在第三步已经做过就是这句代码:
router.options.routes = store.getters.permission_routes
很多人直接用router.addRoutes(accessRoutes)发现无法更新路由,但是路由是被定义了的;后面看文档,是因为Router的路由并不是响应式的,所以只能读取到初始路由。然后要在router.addRoutes(accessRoutes),加上那句话就可以了
或者参考一下大佬的加载方法
手摸手,带你用vue撸后台 系列二(登录权限篇)
6.别忘了修改登录、推出、获取用户信息路径
注意路径:src/api/user.js
里的路径改为
前言中的路径
三、遇到的bug
1.data functions should return an object:
后台roles要为数组形式,这里改为List就可以了
@GetMapping("info")
public R info(){
List<String> roles = new ArrayList<>();
roles.add("test");
return R.ok().data("roles",roles).data("name","admin").data("avatar","https://scpic.chinaz.net/files/pic/pic9/201708/zzpic5968.jpg");
}
2.配置后台api接口baseUrl不生效
- 修改env.development文件
# base api
#VUE_APP_BASE_API = '/dev-api'
VUE_APP_BASE_API = 'http://127.0.0.1:8001'
- 修改vue.config.js
注:// before: require(’./mock/mock-server.js’),要注释掉
devServer: {
port: port,
open: true,
overlay: {
warnings: false,
errors: true
},
// before: require('./mock/mock-server.js'),
proxy: {
[process.env.VUE_APP_BASE_API]: {
target: process.env.VUE_APP_BASE_API,
changeOrigin: true, //配置跨域
pathRewrite: {
['^' + process.env.VUE_APP_BASE_API]: ''
}
}
}
},
3.配置完第2部api后,报错Proxy error: Could not proxy request auth/code from 127.0.0.1:9527 to 127.0.0.1:8001
原来,在上一步修改env.development文件时,没有加http,加上后就可以了
4.无法识别generateRoutes方法:“[vuex] unknown action type: permission/generateRoutes”
原因:未声明导出
修改 store/index.js
加两行
import permission from './modules/permission'
permission
总结
本博文参考了
https://blog.csdn.net/luhjkehr/article/details/109656030
其他bug请参考
vue-admin-template动态路由实现+问题解决
更多推荐
所有评论(0)