vue根据接口数据配置动态路由(动态配置后台管理系统路由权限)

news2025/1/17 5:51:28

文章目录

  • 前言
  • 一、什么是动态路由
  • 二、以 后台管理系统路由权限配置为例
    • 静态路由配置
    • 动态路由配置
  • 总结
    • `如有启发,可点赞收藏哟~`


前言

其几天记录了根据目录接口动态配置vue的静态路由
本文结合addRoute记录下配置动态路由


一、什么是动态路由

动态路由是根据实际配置数据、不同链接参数等动态的添加路由或者删除路由的总称

动态路由主要通过两个函数实现。

  • router.addRoute()
  • router.removeRoute()
  • 它们只注册一个新的路由,也就是说,如果新增加的路由与当前位置相匹配,就需要你用 router.push() 或 router.replace() 来手动导航,才能显示该新路由。

二、以 后台管理系统路由权限配置为例

废话不说,直接上代码,以下代码简单记录了在登录获取用户信息后动态添加当前用户路由权限等配置

先看效果
在这里插入图片描述

静态路由配置

在这里插入图片描述

动态路由配置

  • 新建router/permission.ts 文件
import router from "@/router";
import { UserStore } from "@/stores/modules/user";
import NProgress from "nprogress";
import "nprogress/nprogress.css";
import { storeToRefs } from "pinia";

NProgress.configure({ showSpinner: false }); // 进度条

/**
 * 跳转路由前
 */
router.beforeEach(async(to, from, next) => {
  NProgress.start();
  const { userInfo } = storeToRefs(UserStore())
  if (Object.keys(userInfo.value).length) {
    // 未匹配到任何路由,跳转404
    if (to.matched.length === 0) {
      NProgress.done();
      from.name ? next({ name: from.name }) : next("/error");
    } else {
      NProgress.done();
      next();
    }
  } else {
    try {
      const { setUserInfo, filterAsyncRoutes } = UserStore()
      await setUserInfo()
      const accessRoutes = await filterAsyncRoutes()
      if (accessRoutes) {
        accessRoutes.forEach(route => {
          router.addRoute(route)
        });
      }
      if (to.meta.title) {
        document.title = to.meta.title as string
      }
      next({ ...to, replace: true });
    } catch (error){
      // TODO 移除 token 并跳转登录页 
      next(`/login?redirect=${to.path}`);
      NProgress.done();
    }
  }
})
/**
 * 路由完成后
 */
router.afterEach((to) => {
  if (!to.meta.skeleton) {
  }
  if (!to.meta.background) {
  }
  NProgress.done();
})
  • 新建stores/modules/user.ts
import { SUCCESS_CODE } from "@/const/base/result-code";
import type { MenuType } from "@/interface/menu";
import { getMenu, getUserInfo } from "@/server/user";
import type { getUserInfoDataType } from "@/server/user/interface";
import { ElMessage } from "element-plus";
import { defineStore } from "pinia";
import { reactive, ref } from "vue";
import type { RouteRecordRaw } from "vue-router";
const modules = import.meta.glob("../../views/contents-pages/**/index.ts");
const systemModules = import.meta.glob("../../views/system-pages/**/index.ts");
const { SIS_STORE_NAME } = import.meta.env;
export const UserStore = defineStore(`${SIS_STORE_NAME}-user-store`, () => {
  /**
   * 用户信息
   */
  const userInfo = ref({} as getUserInfoDataType)
  /**
   * 侧边栏数据
   */
  const menu: Array<MenuType> = reactive([])
  /**
   * 获取用户信息
   * @returns 
   */
  const setUserInfo = async() => {
    const response = await getUserInfo()
    if (response.code !== SUCCESS_CODE) {
      ElMessage.error(response.msg)
      return false
    }
    userInfo.value = response.data
    return true
  }
  const getRoutes = (route: RouteRecordRaw[]) => {
    const asyncRoutes: RouteRecordRaw[] = [];
    route.forEach(item => {
      const tmpRoute = {
        ...item,
      }
      const component = modules[`../../views/contents-pages/${item.component}.ts`];
      if (component) {
        tmpRoute.component = component;
      } else {
        tmpRoute.component = systemModules[`../../views/system-pages/error/index.ts`];
      }
      if (item.children) {
        tmpRoute.children = getRoutes(item.children)
      }
      asyncRoutes.push(tmpRoute)
    });
    return asyncRoutes
  }
  /**
   * 获取路由配置
   * @returns 
   */
  const filterAsyncRoutes = async() => {
    const response = await getMenu()
    if (response.code !== SUCCESS_CODE) {
      ElMessage.error(response.msg)
      return false
    }
    return getRoutes(response.data)
  }
  return {
    userInfo,
    menu,
    setUserInfo,
    filterAsyncRoutes
  };
});

  • 新建stores/index.ts
import type { App } from "vue";
import { createPinia } from "pinia";
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'

const store = createPinia().use(piniaPluginPersistedstate);

// 全局注册 store
export function setupStore(app: App<Element>) {
  app.use(store);
}

export { store };

  • main.js

import { createApp } from "vue";
import App from "./App/index.vue";
import router from "./router";
import "@/router/permission";

import { setupStore } from "./stores";
const app = createApp(App);
// 全局注册 状态管理(store)
setupStore(app)
app.use(router);
app.mount("#app");

简单配置个模拟数据实验下
根目录 新建 mock/menu.tsmock/userInfo.ts

  • menu.ts
import type { MockMethod } from "vite-plugin-mock";

export default [
  {
    url: "/api/usr/menu",
    timeout: 200,
    method: "get",
    response: ({ query }) => {
      return {
        code: 200,
        data: [
          {
            // 路由
            path: "/",
            // 组件路径 
            component: "layout/index",
            // 重定向路由
            redirect: "/index",
            // 路由名称
            name: "Index",
            children: [
              {
                path: "index",
                component: "index/index",
                name: "Index",
                meta: {
                  title: "首页",
                  icon: "index",
                  hidden: false,
                  roles: ["ADMIN"],
                  keepAlive: true,
                },
              },
            ]
          },
          {
            // 路由
            path: "/system",
            // 组件路径 
            component: "layout/index",
            // 重定向路由
            redirect: "/system/user",
            // 路由名称
            name: "/system",
            meta: {
              // 当前路由标题
              title: "系统管理",
              // 当前路由图标
              icon: "system",
              // 是否在menu隐藏
              hidden: false,
              // 权限等级
              roles: ["ADMIN"],
            },
            children: [
              {
                path: "user",
                component: "system/user/index",
                name: "User",
                meta: {
                  title: "用户管理",
                  icon: "user",
                  hidden: false,
                  roles: ["ADMIN"],
                  keepAlive: true,
                },
              },
              {
                path: "role",
                component: "system/role/index",
                name: "Role",
                meta: {
                  title: "角色管理",
                  icon: "role",
                  hidden: false,
                  roles: ["ADMIN"],
                  keepAlive: true,
                },
              },
              {
                path: "menu",
                component: "system/menu/index",
                name: "Menu",
                meta: {
                  title: "菜单管理",
                  icon: "menu",
                  hidden: false,
                  roles: ["ADMIN"],
                  keepAlive: true,
                },
              },
              {
                path: "dict",
                component: "system/dict/index",
                name: "Dict",
                meta: {
                  title: "字典管理",
                  icon: "dict",
                  hidden: false,
                  roles: ["ADMIN"],
                  keepAlive: true,
                },
              },
            ],
          },
          {
            // 路由
            path: "/log",
            // 组件路径 
            component: "layout/index",
            children: [
              {
                path: "log",
                component: "log/index",
                name: "Log",
                meta: {
                  title: "日志",
                  icon: "log",
                  hidden: false,
                  roles: ["ADMIN"],
                  keepAlive: true,
                },
              },
            ]
          },
        ],
        msg: "OK",
      };
    },
  },
] as MockMethod[];

  • userInfo.ts
import type { MockMethod } from "vite-plugin-mock";

export default [
  {
    url: "/api/usr/userInfo",
    timeout: 200,
    method: "get",
    response: ({ query }) => {
      return {
        code: 200,
        data: {
          userId: 1,
          userName: "admin",
          nickName: "系统管理员",
          avatar: "xxx.gif",
          roles: ["admin"],
          operationPermissions: [
            "sys:menu:delete",
            "sys:menu:add",
            "sys:menu:edit",

            "sys:user:add",
            "sys:user:edit",
            "sys:user:delete",
            "sys:user:reset_pwd",

            "sys:dict_type:add",
            "sys:dict_type:edit",
            "sys:dict_type:delete",

            "sys:dict:add",
            "sys:dict:edit",
            "sys:dict:delete",

            "sys:role:add",
            "sys:role:edit",
            "sys:role:delete",

            "sys:dept:add",
            "sys:dept:edit",
            "sys:dept:delete",
          ],
        },
        msg: "OK",
      };
    },
  },
] as MockMethod[];


总结

如有启发,可点赞收藏哟~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1239505.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于材料生成算法优化概率神经网络PNN的分类预测 - 附代码

基于材料生成算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于材料生成算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于材料生成优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神…

Gradle常用命令与参数依赖管理和版本决议

一、Gradle 常用命令与参数 本课程全程基于 Gradle8.0 环境 1、Gradle 命令 介绍 gradle 命令之前我们先来了解下 gradle 命令怎么在项目中执行。 1.1、gradlew gradlew 即 Gradle Wrapper&#xff0c;在学习小组的第一课时已经介绍过了这里就不多赘述。提一下执行命令&am…

msvcp140.dll是什么?msvcp140.dll丢失的有哪些解决方法

在计算机使用过程中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中之一就是“msvcp140.dll丢失”。这个错误通常会导致某些应用程序无法正常运行。为了解决这个问题&#xff0c;我们需要采取一些措施来修复丢失的msvcp140.dll文件。本文将详细介绍5个解决msvcp140.dl…

所有产品都值得用AI再做一遍,让AGI与品牌营销双向奔赴

微软 CEO Satya Nadella 曾经说过&#xff1a;“所有的产品都值得用 AI 重做一遍。” AI 大模型的出现&#xff0c;开启了一个全新的智能化时代&#xff0c;重新定义了人机交互。这让生成式 AI 技术变得「触手可得」&#xff0c;也让各行业看到 AGI 驱动商业增长的更大可能性。…

【开源】基于Vue和SpringBoot的高校宿舍调配管理系统

项目编号&#xff1a; S 051 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S051&#xff0c;文末获取源码。} 项目编号&#xff1a;S051&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能需求2.1 学生端2.2 宿管2.3 老师端 三、系统…

Axios 请求响应结果的结构

发送请求 this.$axios.get(https://apis.jxcxin.cn/api/title?urlhttps://apis.jxcxin.cn/,{params: {id: 10}}).then(res > {console.log(res)})输出返回结果 confing 请求时的配置对象&#xff0c;如果请求的url&#xff0c;请求的方法&#xff0c;请求的参数&#xff0c…

如何解决msvcp110.dll丢失问题,分享5个有效的解决方法

最近&#xff0c;我在使用电脑时遇到了一个令人头疼的问题——msvcp110.dll丢失。这个错误通常会导致某些应用程序无法正常运行。为了解决这个问题&#xff0c;我们需要采取一些有效的方法来修复丢失的msvcp110.dll文件。那么&#xff0c;msvcp110.dll到底是什么呢&#xff1f;…

【python基础(三)】操作列表:for循环、正确缩进、切片的使用、元组

文章目录 一. 遍历整个列表1. 在for循环中执行更多操作2. 在for循环结束后执行一些操作 二. 避免缩进错误三. 创建数值列表1. 使用函数range()2. 使用range()创建数字列表3. 指定步长。4. 对数字列表执行简单的统计计算5. 列表解析 五. 使用列表的一部分-切片1. 切片2. 遍历切片…

一文搞懂什么是 GNU/Linux 操作系统

Author&#xff1a;rab 目录 前言一、UNIX二、Linux三、GNU 前言 你是否经常看见或听说过这么一句话&#xff1a;这是一个类 Unix 的 GNU/Linux 操作系统&#xff0c;你是怎么理解这句话的呢&#xff1f;想要搞懂这句话的含义&#xff0c;你需要了解以下三点基本常识。 一、U…

RedisTemplate使用详解

RedisTemplate介绍StringRedisTemplate介绍RedisConnectionFactory介绍RedisConnectionFactory源码解析 RedisOperations介绍RedisOperations源码解析 RedisTemplate使用连接池配置RedisTemplate连接池连接池配置 RedisTemplate应用场景RedisTemplate主要特点RedisTemplate使用…

Nuxt.js Next.js Nest.js

Nuxt.js和Next.js都是服务端渲染框架(SSR)&#xff0c;属于前端框架,Nest.js则是node框架,属于后端框架。 其中Nuxt.js是vue的ssr框架&#xff0c;Next.js是react的ssr框架。 都是比vue和react更上层的前端框架。 文章目录 1.SSR2.Nuxt2.1 Nuxt的下载2.2 Nuxt的集成2.3 Nuxt…

【tomcat】java.lang.Exception: Socket bind failed: [730048

项目中一些旧工程运行情况处理 问题 1、启动端口占用 2、打印编码乱码 ʮһ&#xfffd;&#xfffd; 13, 2023 9:33:26 &#xfffd;&#xfffd;&#xfffd;&#xfffd; org.apache.coyote.AbstractProtocol init &#xfffd;&#xfffd;&#xfffd;&#xfffd;: Fa…

【DevOps】Git 图文详解(八):后悔药 - 撤销变更

Git 图文详解&#xff08;八&#xff09;&#xff1a;后悔药 - 撤销变更 1.后悔指令 &#x1f525;2.回退版本 reset3.撤销提交 revert4.checkout / reset / revert 总结 发现写错了要回退怎么办&#xff1f;看看下面几种后悔指令吧&#xff01; ❓ 还没提交的怎么撤销&#x…

人工智能基础_机器学习047_用逻辑回归实现二分类以上的多分类_手写代码实现逻辑回归OVR概率计算---人工智能工作笔记0087

然后我们再来看一下如何我们自己使用代码实现逻辑回归的,对二分类以上,比如三分类的概率计算 我们还是使用莺尾花数据 首先我们把公式写出来 def sigmoid(z): 定义出来这个函数 可以看看到这需要我们理解OVR是如何进行多分类的,我们先来看这个 OVR分类器 思想 OVR(One-vs-…

如何用cmd命令快速搭建FTP服务

环境&#xff1a; Win10专业版 问题描述&#xff1a; 如何用cmd命令快速搭建FTP服务 解决方案&#xff1a; 1.输入以下命令来安装IIS&#xff08;Internet Information Services&#xff09;&#xff1a; dism /online /enable-feature /featurename:IIS-FTPServer /all …

好用的博客评论系统 Valine 使用及避坑指南

评论系统&#xff0c;即网站的一个小功能&#xff0c;展示评论内容和用户输入框。开源免费的评论系统可不多&#xff0c;原来很火的"多说"评论系统都关闭了&#xff0c;而Disqus又是国外的访问受限。无意间发现了Valine&#xff0c;挺不错的&#xff0c;分享给大家。…

9、鸿蒙应用桌面图标外观和国际化

一、项目资源目录 项目下的resoueces目录为资源配置目录&#xff0c;其中base为基础配置&#xff0c;即在任何语言环境下都会加载的资源&#xff0c; color.json&#xff1a;用于配置颜色&#xff0c;如页面的背景和文字的颜色。 string.json&#xff1a;用于设置文字&#…

java_函数式接口

文章目录 一、什么是函数式接口二、四大核心函数式接口三、使用举例 一、什么是函数式接口 如果一个接口只有一个抽象方法&#xff0c;那么该接口就是一个函数式接口函数式接口的实例可以通过 lambda 表达式、方法引用或者构造方法引用来创建如果我们在某个接口上声明了 Funct…

Pandas一键爬取解析代理IP与代理IP池的维护

目录 前言 一、获取代理IP 二、解析代理IP 三、维护代理IP池 四、完整代码 总结 前言 在爬虫过程中&#xff0c;我们经常会使用代理IP来绕过一些限制&#xff0c;比如防止被封IP等问题。而代理IP的获取和维护是一个比较麻烦的问题&#xff0c;需要花费一定的时间和精力。…

重磅!这本30w人都在看的Python数据分析畅销书:更新了!

想学习python进行数据分析&#xff0c;这本《利用python进行数据分析》是绕不开的一本书。目前该书根据Python3.10已经更新到第三版。 Python 语言极具吸引力。自从 1991 年诞生以来&#xff0c;Python 如今已经成为最受欢迎的解释型编程语言。 pandas 诞生于2008年。它是由韦…