Asp.Net Core 项目实战之权限管理系统(8) 功能菜单的动态加载

本文介绍如何在ASP.NET Core项目中使用ViewComponent实现功能菜单的动态加载,包括根据用户权限展示相应菜单项的方法。

0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有

1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端

2 Asp.Net Core 项目实战之权限管理系统(2) 功能及实体设计

3 Asp.Net Core 项目实战之权限管理系统(3) 通过EntityFramework Core使用PostgreSQL

4 Asp.Net Core 项目实战之权限管理系统(4) 依赖注入、仓储、服务的多项目分层实现

5 Asp.Net Core 项目实战之权限管理系统(5) 用户登录

6 Asp.Net Core 项目实战之权限管理系统(6) 功能管理

7 Asp.Net Core 项目实战之权限管理系统(7) 组织机构、角色、用户权限

8 Asp.Net Core 项目实战之权限管理系统(8) 功能菜单的动态加载

github源码地址

0 服务层实现

系统登录后,会在session中记录当前登录用户的信息。

//检查用户信息
 var user = _userAppService.CheckUser(model.UserName, model.Password);
 if (user != null)
 {
     //记录Session
     HttpContext.Session.SetString("CurrentUserId", user.Id.ToString());
     HttpContext.Session.Set("CurrentUser", ByteConvertHelper.Object2Bytes(user));
     //跳转到系统首页
     return RedirectToAction("Index", "Home");
 }

由于一个用户可以拥有多个角色,我们需要做的是,根据当前登录用户的Id,得到其拥有的所有角色信息,然后取当前用户所有角色拥有的功能权限求合集,得到的就是当前登录用户所拥有的功能权限信息。

定义应用服务接口

在IMenuAppService中定义接口

/// <summary>
/// 根据用户获取功能菜单
/// </summary>
/// <param name="userId">用户ID</param>
/// <returns></returns>
List<MenuDto> GetMenusByUser(Guid userId);

服务接口实现

在MenuAppService中实现接口

/// <summary>
 /// 根据用户获取功能菜单
 /// </summary>
 /// <param name="userId">用户ID</param>
 /// <returns></returns>
 public List<MenuDto> GetMenusByUser(Guid userId)
 {
     List<MenuDto> result = new List<MenuDto>();
     var allMenus = _menuRepository.GetAllList(it=>it.Type == 0).OrderBy(it => it.SerialNumber);
     if (userId == Guid.Empty) //超级管理员
         return Mapper.Map<List<MenuDto>>(allMenus);
     var user = _userRepository.GetWithRoles(userId);
     if (user == null)
         return result;
     var userRoles = user.UserRoles;
     List<Guid> menuIds = new List<Guid>();
     foreach (var role in userRoles)
     {
         menuIds = menuIds.Union(_roleRepository.GetAllMenuListByRole(role.RoleId)).ToList();
     }
     allMenus = allMenus.Where(it => menuIds.Contains(it.Id)).OrderBy(it => it.SerialNumber);
     return Mapper.Map<List<MenuDto>>(allMenus);
 }

1 使用ViewComponent动态加载菜单

在以前的Asp.net MVC中,我们会经常使用@Html.Action来发起一个ChildAction请求,渲染并得到一个分部视图填充的主功能视图中,以此来实现一些公用的或者是独立的界面区域。在Asp.Net Core中,不在存在将以ViewComponent替代。

你可以将View Component看做是一个mini的Controller——它只负责渲染一小部分内容,而非全部响应,所有分部视图能解决的问题,你都可以使用View Component来解决,比如:动态导航菜单、Tag标签、登录窗口、购物车、最近阅读文章等等。

1.0 ViewComponent创建

ViewComponent创建非常简单,只需要将我们的类继承自ViewComponent类就行了。每个ViewComponent需要包括一个名称为Invoke的约定方法,你可以在此方法中传入你需要的任何参数,系统也支持InvokeAsync方法实现异步功能,此约定方法为该ViewComponent的最终输出出口。

在Fonour.MVC项目中新建一个名称为“Components”的文件夹,用来存放我们所有的视图组件类,在该文件夹下新建一个名称为NavigationViewComponent的组件。

[ViewComponent(Name = "Navigation")]
public class NavigationViewComponent : ViewComponent
{
    private readonly IMenuAppService _menuAppService;
    private readonly IUserAppService _userAppService;
    public NavigationViewComponent(IMenuAppService menuAppService, IUserAppService userAppService)
    {
        _menuAppService = menuAppService;
        _userAppService = userAppService;
    }

    public IViewComponentResult Invoke()
    {
        var userId = HttpContext.Session.GetString("CurrentUserId");
        var menus = _menuAppService.GetMenusByUser(Guid.Parse(userId));
        return View(menus);
    }
}

1.1 组件对应的视图文件创建

上面实现的约定方法Invoke中,最后Return View(Menus),与我们控制器中Action返回视图的方法很相似。ViewComponent寻找视图也是遵照约定的。他会自动从以下路径去寻找对应的视图文件。

/Views/[CurrentController]/Components/[NameOfComponent]/Default.cshtml
/Views/Shared/Components/[NameOfComponent]/Default.cshtml

对于某个具体功能对应的组件,我们最好按照上面第一种路径规则,把对应的视图文件放在功能对应的Controller下面

对于系统级别的视图组件,比如我们现在要实现的左侧功能导航菜单,建议按照第二种路径规则,放在Views/Shared下面。

在Views/Shared文件夹下新建一个名称为Components的文件夹,然后在该文件夹下创建一个名称为“Navigation”的文件夹,注意这个文件夹名与我们上面定义的组件名称是要保持一直的。

image

在“Navigation”文件夹下创建一个名称为Default.cshtml的视图页。内容如下:

@model List<Fonour.Application.MenuApp.Dtos.MenuDto>
<li class="header">权限管理</li>
@foreach (var menu in Model)
{
    var isActive = ViewBag.CurrentMenu == menu.Code; //判断当前功能是否处于激活
    <li class="@(isActive ? "active" : "")"><a href="@menu.Url"><i class="fa fa-link"></i> <span>@menu.Name</span></a></li>
}

该视图接受一个在我们组件类中返回的菜单集合对象,并根据此菜单集合渲染我们需要的菜单。我们根据ViewBag.CurrentMenu是否等于当前菜单的编码,来确定该菜单是否属于激活状态,这样可以实现我们单击某个菜单界面刷新后,该功能菜单处于激活状态。

基于此,我们需要在每个功能页面指定ViewBag.CurrentMenu的值。如用户管理功能,我们在/Views/User/Index.cshtml顶部添加如下代码即可。

@{
    ViewBag.CurrentMenu = "User";
}

当然,如果你觉得这种硬编码的方式你不喜欢,你可以在菜单单击的时候,把当前菜单对应的code值传至服务端,由服务端在返回对应的视图之前,指定ViewBag.CurrentMenu的值即可。

1.2 ViewComponent的使用

我们修改布局页_Layout.cshtml中菜单加载部分的代码,将写死的功能菜单信息,修改为通过使用ViewComponent根据用户Id动态加载功能菜单。

<ul class="sidebar-menu">
    @await Component.InvokeAsync("Navigation");
    @*<li class="treeview">
            <a href="#">
                <i class="fa fa-link"></i> <span>Multilevel</span>
                <span class="pull-right-container">
                    <i class="fa fa-angle-left pull-right"></i>
                </span>
            </a>
            <ul class="treeview-menu">
                <li><a href="#">Link in level 2</a></li>
                <li><a href="#">Link in level 2</a></li>
            </ul>
        </li>*@
</ul>

此时我们使用一个只分配了其中三个菜单权限的账户登录系统,一切按照我们预想的,可以根据当前登录用户动态加载该用户所拥有权限的功能菜单了,而且我们进入某个功能后,页面刷新后已经可以自动把我们进入的功能菜单设置为激活状态了。

image

image

2 总结

本次主要学习了ViewComponent的使用,实现了功能菜单的动态加载。

最开始是本着自己学习的态度写这个系列的,内容总体来说属于基础入门级的,到现在也算是基本功能都已经实现了,里面有很多不足或不完善的地方,可以根据需要进行调整吧。

从孩子出生,转眼间到现在3个月了,每天熬夜熬的精疲力尽,工作上也是忙的不可开交,有些朋友给我的留言中的,我有空看到就回复了,有些朋友的问题,有可能我没时间看到,也有可能实在抽不出时间去帮你找问题所在,还得麻烦您自己多动手实践一下了,请见谅。

FrameWork权限管理 v1.0.8源码 源码描述: 其主要的功能就是,进行后台管理模块整合. 1)其可以支持多个应用,多个模块的权限管理. 2)支持Access和MsSql200/2005及Oracle9i以上. 3)采用角色来进行权限的授权,每个用户可以属于多个角色,享有交差权限. 4)整合方便,权限检测采用httpmodule方式检测.基本不用对原有程序进行修改,便可将原有程序进行整合. 5)可视化编辑,全新的Menu和Tab控件.支持拖拉式编辑. 6)统一的事件日志管理,所有登陆操作都有安全记录. 7)每个模块的每个栏目对应一个目录, 栏目的权限抽象分为(查看/新增/修改/删除/排序/打印/备用A/备用 8).目录里有一个web.config来进行目录文件权限配置,可直接将某个文件名设定到相对应的权限. v1.0.8版更新记录 1.增加树状菜单样式,以适应多分类. 2.“查询”功能的地方,如果第一次查询后进行过翻页操作,再进行第二次的查询结果会停留在之前的页码处 3.Url地址权限判断,需要做长度对比.如设置defautl.aspx?cmd=122 则会自动匹配 defautl.aspx?cmd=122xxxxxxx 4.修改模块分类,提示请输入权限名称,其内容不可以为空 5.插入在线人员出错,重复值InsertOnlineUser 6.应用字段增加后,应用名称为输入框. 7.sys_FieldValueFromKey sys_FieldValueList 方法,排序为顺序acs 8.增加对应用的排序 9.增加操作日志删除和导出 10.date.js控件,选中当前日期返回值出错 11.登陆时,如已经登陆用户,点确认后直接登陆,不要让用户再重新输入用户名和密码 12.http://www.supesoft.com/bbs/disp.asp?B_T_ID=1313 13.修改默认同一ip登陆时出错次数为20次就禁止此ip登陆60分钟. 14.用户资料管理员,管理员只能管理自己部门下的用户(修改/删除) 15.后台增加禁止登陆ip限制.
管理系统,作为一种高效的企业运营管理工具,旨在通过集成化、系统化的手段,对组织内部的各类资源进行规划、协调、控制和优化,以实现企业战略目标,提升运营效率,增强核心竞争力。以下是对管理系统的详细介绍: 一、定义与构成 管理系统是指由硬件设备、软件应用、数据资源、人员以及相关管理制度共同构建的,用于处理、监控、分析和决策各类业务活动的综合信息系统。它通常包括以下几个核心组成部分: 数据采集模块:负责从各类业务环节中实时、准确地收集信息,形成企业的基础数据资源。 数据分析模块:运用统计学、人工智能等技术对数据进行深度挖掘和智能分析,提供决策支持。 业务流程管理模块:设计、执行、监控和优化业务流程,确保各项任务按照预定规则高效运转。 决策支持模块:基于数据分析结果,为管理者提供直观的可视化报告,辅助其进行科学决策。 用户界面与交互模块:提供友好的人机交互界面,方便用户操作使用。 二、主要类型与功能 管理系统根据所针对的管理对象和领域,可分为多种类型,如: 人力资源管理系统(HRM):涵盖招聘、培训、绩效考核、薪酬福利等人力资源全流程管理,提升人才效能。 客户关系管理系统(CRM):集中管理客户信息,优化销售、营销和服务流程,提升客户满意度和忠诚度。 供应链管理系统(SCM):整合供应商、制造商、分销商、零售商等供应链各环节,实现物流、资金流、信息流的协同运作。 企业资源计划系统(ERP):对企业内部财务、生产、采购、库存、销售等各项资源进行全面集成管理,提高整体运营效率。 项目管理系统(PM):对项目全生命周期进行规划、跟踪、控制,确保项目按时、按质、按预算完成。 三、价值与优势 提高效率:自动化工作流程、标准化业务操作,显著减少人工干预,提升工作效率。 优化决策:实时数据分析与预测,提供精准的决策依据,助力管理层做出明智选择。 资源整合:打破部门壁垒,实现信息共享,优化资源配置,降低运营成本。 合规风控:内置法规遵循机制,强化内部控制,降低经营风险。 持续改进:通过对系统数据的持续监控与分析,驱动业务流程持续优化,促进企业创新与发展。 总的来说,管理系统作为现代企业管理的重要工具,以其强大的数据处理能力、智能化的决策支持和高效的业务流程管理,有力推动了企业的数字化转型,助力企业在日益激烈的市场竞争中保持竞争优势。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值