前言
需要后端同学配合,不同的用户登录,需要根据用户信息对菜单、按钮等权限进行处理。

1.路由鉴权文件
在src 下新建文件permission.ts 在入口文件main.ts引入并写入以下代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
| import router from '@/router';
import setting from './setting'; import nprogress from 'nprogress';
import "nprogress/nprogress.css"; nprogress.configure({ showSpinner: false });
import useUserStore from './store/modules/user'; import pinia from './store'; let userStore = useUserStore(pinia);
router.beforeEach(async (to: any, from: any, next: any) => { document.title = `${setting.title} - ${to.meta.title}` nprogress.start(); let token = userStore.token; let username = userStore.username; if (token) { if (to.path == '/login') { next({ path: '/' }) } else { if (username) { next(); } else { try { await userStore.userInfo(); next({ ...to }); } catch (error) { await userStore.userLogOut(); next({ path: '/login', query: { redirect: to.path } }) } } }
} else { if (to.path == '/login') { next(); } else { next({ path: '/login', query: { redirect: to.path } }); } } })
router.afterEach((to: any, from: any) => { nprogress.done(); });
|
2.路由拆分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| exprot const constantRoute=[{ path: '/login', component: () => import('@/views/login/login.vue'), name: 'Login', meta: { title: '登录', hidden: true, icon: '' } }]
export const asyncRoute = [ { path: '', component: () => import('@/layout/index.vue'), name: '', meta: { title: '', icon: '' }, children:[] }
|
3.通过vue-router插件实现路由配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import { createRouter, createWebHashHistory } from "vue-router"; import { constantRoute } from "./routes";
let router = createRouter({ history: createWebHashHistory(), routes: constantRoute, scrollBehavior() { return { left: 0, top: 0 } } });
export default router;
|
4.在用户仓库中获取用户信息并进行处理
4.1 创建用户过滤当前用户需要展示的路由
1 2 3 4 5 6 7 8 9 10 11
| function filterAsyncRoute(asyncRoute: any, routes: any) { return asyncRoute.filter((item: any) => { if (routes.includes(item.name)) { if (item.children && item.children.length > 0) { item.children = filterAsyncRoute(item.children, routes) } return true } }) }
|
4.2 获取用户信息接口 调用过滤方法展示当前用户需要展示的路由
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import cloneDeep from 'lodash/cloneDeep' async userInfo() { let result: userInfoResponseData = await userInfo(); if (result.code === 200) { let userAsyncRoute = filterAsyncRoute(cloneDeep(asyncRoute), result.data.routes); this.menuRoutes = [...constantRoute, ...userAsyncRoute, ...anyRoute]; [...userAsyncRoute, ...anyRoute].forEach((route: any) => { router.addRoute(route); }); return 'Ok' } else { return Promise.reject(new Error(result.message)); } }
|
4.3 在退出登录时 需要让路由保持常量路由
1
| menuRoutes = constantRoute ;
|
5.关于全局按钮的鉴权
在获取用户信息一并拿到按钮的权限,然后通过自定义指令处理
5.1 用户仓库初始化并获取用户信息
1 2 3 4 5 6 7 8 9 10 11
| state: (): userState => { return { buttons: [] } }, async userInfo() { ... this.buttons = result.data.buttons; }
|
5.2 src下新建directive文件夹 并新建自定义指令文件并写于以下内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import pinia from "@/store"; import useUserStroe from "@/store/modules/user"; let userState = useUserStroe(pinia); export const isHasButton = (app: any) => { app.directive('has', { mounted(el: any, options: any) { if (!userState.buttons.includes(options.value)) { el.parentNode.removeChild(el); } }, }) }
|
5.3 在main.ts中引入自定义指令
1 2 3 4
| import { isHasButton } from "./directive/has"; const app = createApp(App); isHasButton(app);
|
1
| <el-button v-has="`btn.Trademark.add`">添加</el-button>
|