赞
踩
- /src/router/index.ts
- import { 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: 'https://www.cnblogs.com/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;
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
- /src/store/permission
-
- import { 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,tmpRoute.component);
-
- if (hasPermission(roles, tmpRoute)) {
- if (tmpRoute.component?.toString() == "Layout") {
- tmpRoute.component = Layout;
- } else {
- const component = modules[`../../views/${tmpRoute.component}.vue`];
- // console.log(modules['../../views/system/menu/index.vue'],'../../views/system/menu/index.vue');
- if (component) {
- tmpRoute.component = component;
- } else {
- tmpRoute.component = modules[`../../views/error-page/404.vue`];
- }
- }
- // debugger
- if (tmpRoute.children) {
- tmpRoute.children = filterAsyncRoutes(tmpRoute.children, roles);
- }
- // console.log(asyncRoutes);
- asyncRoutes.push(tmpRoute);
- // console.log(asyncRoutes)
- }
- });
-
- return asyncRoutes;
- };
-
- // setup
- export const usePermissionStore = defineStore("permission", () => {
- // state
- const routes = ref<RouteRecordRaw[]>([]);
-
- // actions
- function 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 };
- });
-
- // 非setup
- export function usePermissionStoreHook() {
- return usePermissionStore(store);
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
- /src/permission
-
- import 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) {
- // 未匹配到任何路由,跳转404
- if (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();
- });
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
- main.ts
-
- import { 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');
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
以上是路由菜单管理的权限
- //指令权限 、src/directive/index
- import { 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']\"");
- }
- }
- };
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。