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

一、前言

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

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

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

二、技术选择

三、开始设计

  

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

体验地址:引迈 - JNPF快速开发平台_低代码开发平台_零代码开发平台_流程设计器_表单引擎_工作流引擎_软件架构

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

1320亿参数,性能超LLaMA2、Grok-1!开源大模型DBRX

3月28日&#xff0c;著名数据和AI平台Databricks在官网正式开源大模型——DBRX。 DBRX是一个专家混合模型&#xff08;MoE&#xff09;有1320亿参数&#xff0c;能生成文本/代码、数学推理等&#xff0c;有基础和微调两种模型。 根据DBRX在MMLU、HumanEval和 GSM8K公布的测试…

蓝牙双模音频模块支持串口AT指令控制介绍

目录 一、BT401蓝牙音频模块简介 蓝牙音频模块支持串口AT指令控制介绍&#xff0c;这里推荐BT401蓝牙模块&#xff0c;功能简介如下&#xff1a; BT401模块是一款支持蓝牙、U盘、TF卡播放的5合1的解决方案。模组的亮点在支持无损音乐的播放&#xff0c;以及简单明了的串口控制…

婴儿专用洗衣机哪个牌子好?四大爆款婴儿洗衣机合集安利

婴儿的衣物需要特别的护理&#xff0c;因为婴儿的皮肤非常娇嫩&#xff0c;需要一个无菌&#xff0c;没有刺激性的洗涤环境&#xff0c;于是婴儿洗衣机应运而生。如果你非常注重婴儿衣物的卫生问题&#xff0c;那么婴儿洗衣机则是非常理想的选择。毕竟&#xff0c;在婴儿吃奶或…

文件上传失败原因分析与解决

图片文件上传失败 问题描述&#xff1a;在前端开发时&#xff0c;需要通过表单元素上传图片或其他文本&#xff0c;但是上传不成功&#xff0c;后端接口也没问题 html <!--onChange用来绑定数据 handleUpload用来提交数据--><form onSubmit{handleUpload}><…

Cadence HDL导出BOM并将网页数据导入Excle

【仅供个人学习记录&#xff0c;勿作他用。转载注明出处】 1. 如何导出BOM&#xff1f; 【说明】将后缀改为网页“html”&#xff0c;并勾选下面的网页。 之后就会跳出浏览器中你的BOM表就会显示。 2. 将网页BOM导入Excle&#xff1f; 不想要这个 想要这个&#xff01;&…

vscode配置c/c++调试环境

本文记录win平台使用vscode远程连接ubuntu server服务器下&#xff0c;如何配置c/c调试环境。 过程 1. 服务器配置编译环境 这里的前置条件是vscode已经能够连接到服务器&#xff0c;第一步安装编译构建套件&#xff08;gcc、g、make、链接器等&#xff09;和调试器&#xf…

眼底 Fundus、OCT 图竞赛分析

眼底 Fundus、OCT 图竞赛分析 眼底 Fundus 图竞赛&#xff08;8分类&#xff09;算法设计ResNet简介双路ResNet2d网络的工作原理应用数据预处理训练和验证 代码分析 眼底 OCT 图&#xff08;8分类&#xff09;代码分析眼底图分类最新研究 MuReD 视网膜疾病 &#xff08;20分类&…

必须进行App测试吗?专业第三方软件测试机构分享移动App测试好处

在这个移动互联网时代&#xff0c;移动应用程序App已经成为人们生活中必不可少的一部分。然而&#xff0c;随着市场上App数量不断增加&#xff0c;质量的好坏成为用户选择的重要标准。因此&#xff0c;在发布之前&#xff0c;一个必不可少的步骤就是对移动App进行软件测试。 移…

FlashDB移植到STM32F103内部flash,FatFs、FlashDB 、EasyFlash的不同

文章目录 一、前言二、FatFs、FlashDB 、EasyFlash 区别2.1 FlashDB2.2 EasyFlash2.3 FATFS 三、FatFs、FlashDB、EasyFlash 区使用环境3.1 FlashDB:3.2 FATFS:3.3 EasyFlash: 四、FlashDB移植4.1 项目 GITEE 地址4.2 项目目录4.3 移植的目录树4.4 MDK keil 添加文件4.5 添加头…

Python---Numpy学习

首先&#xff0c;先来认识一下Numpy数组对象&#xff0c;以及如何创建它 import numpy as np# 1.认识数组对象 # 指定取值范围和跨度创建数组对象 # 创建一个3行4列的数组 data np.arange(12).reshape(3, 4)print(data)print(type(data))# 维度 print(data.shape)# 维度的个数…

架构师之路--docker命令实践整理

安装docker sudo yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine sudo yum install -y yum-utils sudo yum-config-manager --add-repo http://mirrors.aliyun.com/…

谭浩强第五版C语言课后习题(编程题)+答案

谭浩强第五版作为初学C语言必读的一本教材&#xff0c;课后习题具有非常大的参考价值&#xff0c;也是很多高校期末考试或者考研的重要参考。在这里我整理了一部分个人认为比较重要的编程题&#xff0c;供大家作参考 1.输入两个数&#xff0c;求他们的最大公约数和最小公倍数&…

Vector授权狗驱动安装方法

安装好主体软件后&#xff0c;建议先安装最新官方正版驱动&#xff1a;Vector Driver Setup。然后再复制补丁到C盘指定位置&#xff0c;替换原文件。如果你之前已安装老版本的驱动&#xff0c;则建议先卸载老版本的驱动&#xff0c;主体软件不需要卸载。卸载建议用原来安装时用…

关于柔性阵列(/三维阵列)波束形成的仿真实践以及稳健波束形成的思考(1)

说明 关于波束形成&#xff0c;我之前写过几篇相关的博文&#xff0c;如参考资料[1]、[2]、[3]。除去在博文[2]中有讨论过阵元相对位置关系对波束形成的影响&#xff1a;“如何基于遗传算法优化阵元相对位置关系以压低旁瓣峰值”以外&#xff0c;似乎我认知里的天线阵列&#x…

【Linux实验室】测试ext4文件系统的最大inode数量

【Linux实验室】测试ext4文件系统的最大inode数量 实验目的 1、熟悉inode的定义与作用 2、熟悉Linux文件系统类型 3、测试ext4文件系统的最大inode数量 实验环境 centos7.10 64-bit 实验原理 inode定义 安装操作系统或格式化磁盘分区的时候&#xff0c;操作系统会自动把…

教你如何快速批量删除文件名中相同的文字

在现代计算机系统中&#xff0c;文件夹是一种重要的组织和管理文件的方式。文件夹名称可以反映其内部文件的内容或属性&#xff0c;有助于用户快速识别和定位所需的文件。然而&#xff0c;有时我们会遇到需要统一删除文件夹名称的部分的情况。统一删除文件夹名称的部分可能是为…

PHiSeg:捕捉医学图像分割中的不确定性

PHiSeg&#xff1a;捕捉医学图像分割中的不确定性 摘要引言方法 PHiSeg Capturing Uncertainty in Medical Image Segmentation 摘要 解剖结构和病理的分割本质上是模糊的。例如&#xff0c;结构边界可能不清晰可见&#xff0c;或者不同的专家可能具有不同的注释风格。大多数当…

80个Python数据分析必备实战案例.pdf(附代码),完全开放下载

大家好&#xff0c;我是彭涛。 随着数据时代的来临&#xff0c;Python数据分析技能现在愈加重要&#xff0c;无论是从事数据科学、商业分析还是决策支持&#xff0c;掌握 Python 数据分析的技能都将成为你事半功倍的利器。 之前为大家陆续梳理了基础资料&#xff0c;爬虫资料…

Navicat 干货 | 通过检查约束确保 PostgreSQL 的数据完整性

数据完整性对于任何数据库系统来说都是很重要的一方面&#xff0c;它确保存储的数据保持准确、一致且有意义的。在 PostgreSQL 中&#xff0c;维护数据完整性的一个强大工具是使用检查约束。这些约束允许你定义数据必须遵守的规则&#xff0c;以防止无效数据的插入或修改。本文…

什么是根据人类反馈的强化学习Reinforcement Learning with Human Feedback(RLHF)?

基于人类反馈的强化学习&#xff08;Reinforcement learning with human feedback&#xff09;是近年来越来越受欢迎的一种前沿技术&#xff0c;用于提高大型语言模型的性能。这是种使用人类反馈训练这些模型的有效方法&#xff0c;而该方法的输入组件与搜索评估也有诸多相似之…