600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > vue3权限管理实现以及按钮权限实现

vue3权限管理实现以及按钮权限实现

时间:2019-01-05 03:26:19

相关推荐

vue3权限管理实现以及按钮权限实现

/src/router/index.tsimport { createRouter, createWebHashHistory, RouteRecordRaw } from "vue-router";export const Layout = () => import("@/layout/index.vue");// 静态路由export const constantRoutes: RouteRecordRaw[] = [{path: "/redirect",component: Layout,meta: { hidden: true },children: [{path: "/redirect/:path(.*)",component: () => import("@/views/redirect/index.vue"),},],},{path: "/login",component: () => import("@/views/login/index.vue"),meta: { hidden: true },},{path: "/",component: Layout,redirect: "/dashboard",children: [{path: "dashboard",component: () => import("@/views/dashboard/index.vue"),name: "Dashboard",meta: { title: "dashboard", icon: "homepage", affix: true },},{path: "401",component: () => import("@/views/error-page/401.vue"),meta: { hidden: true },},{path: "404",component: () => import("@/views/error-page/404.vue"),meta: { hidden: true },},],},// 外部链接/*{path: '/external-link',component: Layout,children: [{path: '/haoxianrui/',meta: { title: '外部链接', icon: 'link' }}]}*/// 多级嵌套路由/* {path: '/nested',component: Layout,redirect: '/nested/level1/level2',name: 'Nested',meta: {title: '多级菜单', icon: 'nested'},children: [{path: 'level1',component: () => import('@/views/nested/level1/index.vue'),name: 'Level1',meta: {title: '菜单一级'},redirect: '/nested/level1/level2',children: [{path: 'level2',component: () => import('@/views/nested/level1/level2/index.vue'),name: 'Level2',meta: {title: '菜单二级'},redirect: '/nested/level1/level2/level3',children: [{path: 'level3-1',component: () => import('@/views/nested/level1/level2/level3/index1.vue'),name: 'Level3-1',meta: {title: '菜单三级-1'}},{path: 'level3-2',component: () => import('@/views/nested/level1/level2/level3/index2.vue'),name: 'Level3-2',meta: {title: '菜单三级-2'}}]}]},]}*/];/*** 创建路由*/const router = createRouter({history: createWebHashHistory(),routes: constantRoutes as RouteRecordRaw[],// 刷新时,滚动条位置还原scrollBehavior: () => ({ left: 0, top: 0 }),});/*** 重置路由*/export function resetRouter() {router.replace({ path: "/login" });location.reload();}export default router;

/src/store/permissionimport { RouteRecordRaw } from "vue-router";import { defineStore } from "pinia";import { constantRoutes } from "@/router";import { store } from "@/store";import { listRoutes } from "@/api/menu";const modules = import.meta.glob("../../views/**/**.vue");const Layout = () => import("@/layout/index.vue");/*** Use meta.role to determine if the current user has permission** @param roles 用户角色集合* @param route 路由* @returns*/const hasPermission = (roles: string[], route: RouteRecordRaw) => {if (route.meta && route.meta.roles) {// 角色【超级管理员】拥有所有权限,忽略校验if (roles.includes("ROOT")) {return true;}return roles.some((role) => {if (route.meta?.roles !== undefined) {return (route.meta.roles as string[]).includes(role);}});}return false;};/*** 递归过滤有权限的异步(动态)路由** @param routes 接口返回的异步(动态)路由* @param roles 用户角色集合* @returns 返回用户有权限的异步(动态)路由*/const filterAsyncRoutes = (routes: RouteRecordRaw[], roles: string[]) => {const asyncRoutes: RouteRecordRaw[] = [];routes.forEach((route) => {const tmpRoute = { ...route }; // ES6扩展运算符复制新对象// console.log(tmpRoute,route);// 判断用户(角色)是否有该路由的访问权限// console.log(modules,ponent);if (hasPermission(roles, tmpRoute)) {if (ponent?.toString() == "Layout") {ponent = Layout;} else {const component = modules[`../../views/${ponent}.vue`];// console.log(modules['../../views/system/menu/index.vue'],'../../views/system/menu/index.vue');if (component) {ponent = component;} else {ponent = modules[`../../views/error-page/404.vue`];}}// debuggerif (tmpRoute.children) {tmpRoute.children = filterAsyncRoutes(tmpRoute.children, roles);}// console.log(asyncRoutes);asyncRoutes.push(tmpRoute);// console.log(asyncRoutes)}});return asyncRoutes;};// setupexport const usePermissionStore = defineStore("permission", () => {// stateconst routes = ref<RouteRecordRaw[]>([]);// actionsfunction setRoutes(newRoutes: RouteRecordRaw[]) {routes.value = constantRoutes.concat(newRoutes);}/*** 生成动态路由** @param roles 用户角色集合* @returns*/function generateRoutes(roles: string[]) {return new Promise<RouteRecordRaw[]>((resolve, reject) => {// 接口获取所有路由listRoutes().then(({ data: asyncRoutes }) => {console.log(asyncRoutes,'asyncRoutes');// 根据角色获取有访问权限的路由const accessedRoutes = filterAsyncRoutes(asyncRoutes, roles);console.log(accessedRoutes,'accessedRoutes');setRoutes(accessedRoutes);resolve(accessedRoutes);}).catch((error) => {reject(error);});});}return { routes, setRoutes, generateRoutes };});// 非setupexport function usePermissionStoreHook() {return usePermissionStore(store);}

/src/permissionimport router from "@/router";import { useUserStoreHook } from "@/store/modules/user";import { usePermissionStoreHook } from "@/store/modules/permission";import NProgress from "nprogress";import "nprogress/nprogress.css";NProgress.configure({ showSpinner: false }); // 进度条const permissionStore = usePermissionStoreHook();// 白名单路由const whiteList = ["/login"];router.beforeEach(async (to, from, next) => {NProgress.start();const hasToken = localStorage.getItem("accessToken");if (hasToken) {if (to.path === "/login") {// 如果已登录,跳转首页next({ path: "/" });NProgress.done();} else {const userStore = useUserStoreHook();const hasRoles = userStore.roles && userStore.roles.length > 0;if (hasRoles) {// 未匹配到任何路由,跳转404if (to.matched.length === 0) {from.name ? next({ name: from.name }) : next("/404");} else {next();}} else {try {const { roles,perms } = await userStore.getInfo();console.log(roles,'roles');const accessRoutes = await permissionStore.generateRoutes(roles);accessRoutes.forEach((route) => {router.addRoute(route);});next({ ...to, replace: true });} catch (error) {// 移除 token 并跳转登录页await userStore.resetToken();next(`/login?redirect=${to.path}`);NProgress.done();}}}} else {// 未登录可以访问白名单页面if (whiteList.indexOf(to.path) !== -1) {next();} else {next(`/login?redirect=${to.path}`);NProgress.done();}}});router.afterEach(() => {NProgress.done();});

main.tsimport { createApp } from 'vue';import App from './App.vue';import router from '@/router';import { setupStore } from '@/store';import { setupDirective } from '@/directive';//引入权限过滤功能import '@/permission';// 本地SVG图标import 'virtual:svg-icons-register';// 国际化import i18n from '@/lang/index';// 样式import 'element-plus/theme-chalk/dark/css-vars.css';import '@/styles/index.scss';import 'uno.css';const app = createApp(App);// 全局注册 自定义指令(directive)setupDirective(app);// 全局注册 状态管理(store)setupStore(app);app.use(router).use(i18n).mount('#app');

以上是路由菜单管理的权限

//指令权限 、src/directive/indeximport { useUserStoreHook } from '@/store/modules/user';import { Directive, DirectiveBinding } from 'vue';/*** 按钮权限*/export const hasPerm: Directive = {mounted(el: HTMLElement, binding: DirectiveBinding) {// 「超级管理员」拥有所有的按钮权限const { roles, perms } = useUserStoreHook();if (roles.includes('ROOT')) {return true;}// 「其他角色」按钮权限校验const { value } = binding;if (value) {const requiredPerms = value; // DOM绑定需要的按钮权限标识const hasPerm = perms?.some(perm => {return requiredPerms.includes(perm);});if (!hasPerm) {el.parentNode && el.parentNode.removeChild(el);}} else {throw new Error("need perms! Like v-has-perm=\"['sys:user:add','sys:user:edit']\"");}}};/*** 角色权限*/export const hasRole: Directive = {mounted(el: HTMLElement, binding: DirectiveBinding) {const { value } = binding;if (value) {const requiredRoles = value; // DOM绑定需要的角色编码const { roles } = useUserStoreHook();const hasRole = roles.some(perm => {return requiredRoles.includes(perm);});if (!hasRole) {el.parentNode && el.parentNode.removeChild(el);}} else {throw new Error("need roles! Like v-has-role=\"['admin','test']\"");}}};

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。