写点什么

一步一步搭建,功能最全的权限管理系统之动态路由菜单

  • 2024-03-28
    福建
  • 本文字数:3616 字

    阅读完需:约 12 分钟

一、前言


  这是一篇搭建权限管理系统的系列文章。

  随着网络的发展,信息安全对应任何企业来说都越发的重要,而本系列文章将和大家一起一步一步搭建一个全新的权限管理系统。

  说明:由于搭建一个全新的项目过于繁琐,所有作者将挑选核心代码和核心思路进行分享。


二、技术选择



三、开始设计

  

1、自主搭建 vue 前端和.net core webapi 后端,网上有很多搭建教程。

  这是我搭建的

 后端: 

  前端:


  搭建好之后,vue 需要把基础配置做好,比如路由、响应请求等,网上都有教程。

   vue 配置较为简单,webapi 的框架我使用 DDD 领域启动设计方式,各个层的介绍如下下。

  • ProjectManageWebApi webapi 接口层,属于启动项

  • Model 业务模型,代表着系统中的具体业务对象。

  • Infrastructure 仓储层,是数据存储层,提供持久化对象的方法。

  • Domain  领域层,是整个系统运行时核心业务对象的载体,是业务逻辑处理的领域。

  • Subdomain 子域,子域是领域层更加细微的划分,处理整个系统最核心业务逻辑。

  • Utility  工具层,存放系统的辅助工具类。

  

2、搭建数据库

  菜单对于一个系统来说,是必不可少的,我们搭建权限管理系统就从这里开始

  任务:建立菜单表,并通过程序把菜单动态加载到页面,实现树形菜单。

  这是我的菜单表结构

  


  我采用的是一张表存储系统菜单,用 id 和 pid 存储上下级关系。当然这不是唯一的,根据情况可以把它拆分层多张表。

  

3、创建基础仓储和菜单仓储


  在 webapi 中 Infrastructure 仓储层创建基础仓储,以便提供持久化支持。

  我 orm 框架使用的是 dapper 来提共数据库和编程语言间的映射关系。

  首先需要建立一个增删改查的仓储接口,大致如下:


View Code


  然后实现这个仓储接口


View Code


以上两段代码就实现了对数据库的增删改查。当然在上述仓储接口中有一个分页查询接口,它对于的模型如下

/// <summary>/// 分页模型/// </summary>public class PageResultModel{    /// <summary>    /// 当前页    /// </summary>    public int pageIndex { get; set; }
/// <summary> /// 每页显示条数 /// </summary> public int pageSize { get; set; }
/// <summary> /// 查询表字段 /// </summary> public string tableField { get; set; }
/// <summary> /// 查询表 /// </summary> public string tableName { get; set; }
/// <summary> /// 查询条件 /// </summary> public string selectWhere { get; set; }
/// <summary> /// 查询条件json /// </summary> public string filterJson { get; set; }
/// <summary> /// 当前菜单id /// </summary> public string menuId { get; set; }
/// <summary> /// 排序字段(不能为空) /// </summary> public string orderByField { get; set; }
/// <summary> /// 排序类型 /// </summary> public string sortType { get; set; }
/// <summary> /// 总数 /// </summary> public int total { get; set; }}
/// <summary>/// 查询数据/// </summary>/// <typeparam name="T"></typeparam>public class PageResultModel<T> : PageResultModel { /// <summary> /// 数据 /// </summary> public List<T> data { get; set; }}
复制代码


上述代码解释:上述仓储接口中定义了所有基础接口,因为它们都是数据库操作最基本的存在,为了统一管理,降低耦合把它们定义到仓储中,以备后用。

  建立好基础仓储后,我们需要建立菜单表的仓储

  菜单仓储接口

 /// <summary> /// 菜单仓储 /// </summary> public interface ISysMenuRepository : IRepository<Menu> {}
复制代码


菜单仓储接口实现

/// <summary>/// 菜单仓储/// </summary>public class SysMenuRepository : Repository<Menu>, ISysMenuRepository{}
复制代码

  上述代码解释:可以看见上述代码继承了 IRepository 和 Repository,这说明菜单拥有了增删改查等功能。

   

4、创建领域服务,递归组织树形菜单结构


  在 Domain 领域层创建领域服务接口和实现接口

  领域服务接口

/// <summary> /// 菜单服务接口 /// </summary> public interface ISysMenuService {      /// <summary>     /// 获取所有菜单--上下级关系     /// </summary>     /// <returns></returns>     List<MenuDao> GetAllChildren();}
复制代码


  领域接口实现

/// <summary>/// 菜单服务实现/// </summary>public class SysMenuService : ISysMenuService{
//仓储接口 private readonly ISysMenuRepository _menuRepository;
/// <summary> /// 构造函数 实现依赖注入 /// </summary> /// <param name="userRepository">仓储对象</param> public SysMenuService(ISysMenuRepository menuRepository) { _menuRepository = menuRepository; }
/// <summary> /// 获取菜单--上下级关系 /// </summary> /// <returns></returns> public List<MenuDao> GetAllChildren() { var list = _menuRepository.GetMenusList(); var menuDaoList = MenuCore.GetMenuDao(list); return menuDaoList; }}
复制代码


5、在 Subdomain 子域中创建菜单核心代码


  为什么在子域中创建菜单核心,应该菜单是整个系统的核心之一,考虑到之后系统会频繁使用,所以创建在子域中,以便提供给其他业务领域使用

  下面是递归菜单实现树形结构的核心

public static class MenuCore {     #region 用于菜单导航的树形结构
/// <summary> /// 递归获取菜单结构--呈现上下级关系 /// 用于菜单的树形结构 /// </summary> /// <returns></returns> public static List<MenuDao> GetMenuDao(List<Menu> menuList) { List<MenuDao> list = new(); List<MenuDao> menuListDto = new(); foreach (var item in menuList) { MenuDao model = new() { Title = item.MenuTitle, Icon = item.MenuIcon, Id = item.MenuUrl + "?MneuId=" + item.Id, MenuKey = item.Id, PMenuKey = item.Pid, Component = item.Component, Path = item.Path, RequireAuth = item.RequireAuth, Name = item.Name, Redirect = item.Redirect, IsOpen = item.IsOpen }; list.Add(model); } foreach (var data in list.Where(f => f.PMenuKey == 0 && f.IsOpen)) { var childrenList = GetChildrenMenu(list, data.MenuKey); data.children = childrenList.Count == 0 ? null : childrenList; menuListDto.Add(data); } return menuListDto; }
/// <summary> /// 实现递归 /// </summary> /// <param name="moduleOutput"></param> /// <param name="id"></param> /// <returns></returns> private static List<MenuDao> GetChildrenMenu(List<MenuDao> moduleOutput, int id) { List<MenuDao> sysShowTempMenus = new(); //得到子菜单 var info = moduleOutput.Where(w => w.PMenuKey == id && w.IsOpen).ToList(); //循环 foreach (var sysMenuInfo in info) { var childrenList = GetChildrenMenu(moduleOutput, sysMenuInfo.MenuKey); //把子菜单放到Children集合里 sysMenuInfo.children = childrenList.Count == 0 ? null : childrenList; //添加父级菜单 sysShowTempMenus.Add(sysMenuInfo); } return sysShowTempMenus; }}
复制代码


以上便是后端实现动态菜单的核心代码,到这一节点,后端的工作基本完成。

  在 Controller 创建好接口后,运行后端代码,出现如图所示,便说明成功。

  


   6、vue 动态路由搭建

  配置 vue 动态路由前,需要看你选择的前端框架是什么,不同的框架,解析的字段不一样,我选择的是 layui vue,动态配置如下:


 View Code


  通过以上代码,获取动态路由,然后把它加入到你的路由菜单中,这样便实现了页面菜单动态加载。


四、项目效果



五、说明


  以上便是实现 vue+webapi 实现动态路由的全部核心代码


文章转载自:陈逸子风

原文链接:https://www.cnblogs.com/cyzf/p/18096545

体验地址:http://www.jnpfsoft.com/?from=001

用户头像

还未添加个人签名 2023-06-19 加入

还未添加个人简介

评论

发布
暂无评论
一步一步搭建,功能最全的权限管理系统之动态路由菜单_Java_不在线第一只蜗牛_InfoQ写作社区