• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

ASP.NET Core 一步步搭建个人网站(3)_菜单管理

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

上一章,我们实现了用户的注册和登录,登录之后展示的是我们的主页,页面的左侧是多级的导航菜单,定位并展示用户需要访问的不同页面。目前导航菜单是写死的,考虑以后菜单管理的便捷性,我们这节实现下可视化配置菜单的功能,这样以后我们可以动态的配置导航菜单,不用再编译发布网站程序了。

增加后台管理模块

第1步,左侧导航菜单中,添加后台管理模块,用作管理员登录后,可以进行一些后台管理的操作,当然,目前还没有权限控制(后期加入),所以对所有用户可见。大概菜单结构如下:

有了菜单项,我们还需要控制视图的跳转,所以,接下来需要写对应的控制器和视图。

为了将相关功能组织成一组单独命名空间(路由)和文件夹结构(视图),解决方案中右键添加区域(Area),取名后台管理(Configuration),代表后台管理模块,.Net Core脚手架(scaffold)自动帮我们实现了目录划分:控制器(Controllers)、模型(Models)、视图(Views)

菜单模型定义

菜单的基本属性有:菜单名称、菜单类型、菜单的图标样式、菜单url路径。另外,菜单在逻辑上是树状结构,但是要在物理数据库中存储,需要进行扁平化处理,每个菜单项有个父菜单属性(根节点的父菜单为空),还有同一父节点底下,在组类的排序属性,定义如下:

 1 /// <summary>
 2 /// 菜单
 3 /// </summary>
 4 public class Menu
 5 {
 6     /// <summary>
 7     /// 主键ID
 8     /// </summary>
 9     [DatabaseGenerated(DatabaseGeneratedOption.None)]
10     [Required(ErrorMessage = "请输入菜单编号")]
11     public string Id { get; set; }
12 
13     /// <summary>
14     /// 菜单名称
15     /// </summary>
16     [Required(ErrorMessage = "请输入菜单名称")]
17     [StringLength(256)]
18     public string Name { get; set; }
19 
20     /// <summary>
21     /// 父级ID
22     /// </summary>
23     [DisplayFormat(NullDisplayText = "")]
24     public string ParentId { get; set; }
25 
26     /// <summary>
27     /// 菜单组内排序
28     /// </summary>
29     [Range(0, 99, ErrorMessage = "请选择1-99范围内的整数")]
30     public int IndexCode { get; set; }
31 
32     /// <summary>
33     /// 菜单路径
34     /// </summary>
35     [StringLength(256)]
36     [DisplayFormat(NullDisplayText = "")]
37     public string Url { get; set; }
38 
39     /// <summary>
40     /// 类型:0导航菜单;1操作按钮。
41     /// </summary>
42     [Required(ErrorMessage = "请选择菜单类型")]
43     public MenuTypes? MenuType { get; set; }
44 
45     /// <summary>
46     /// 菜单图标名称
47     /// </summary>
48     [Required(ErrorMessage = "请输入菜单图标")]
49     [StringLength(50)]
50     public string Icon { get; set; }
51 
52     /// <summary>
53     /// 菜单备注
54     /// </summary>
55     public string Remarks { get; set; }
56 }
57 /// <summary>
58 /// 菜单类型
59 /// </summary>
60 public enum MenuTypes
61 {
62     /// <summary>
63     /// 导航菜单
64     /// </summary>
65     导航菜单,
66     /// <summary>
67     /// 操作菜单
68     /// </summary>
69     操作菜单
70 }

 

有了我们的菜单模型,在控制器目录中,我们右键建立第1个自己的控制器,取名MenuController,用来菜单管理,上下文选取定义好的Menu模型,还是利用脚手架,自动帮我们生成增删改查对应的后来逻辑和视图。此时,我们把菜单导向该控制器,其实是可以正常访问的,不过还远远达不到我们的要求,所以我们还得完善下自动生成的代码。

菜单控制器改写

为了方便今后的拓展,新增一个AppController控制器,继承Controller,以后所有的控制器,都继承于AppController,方便一些公共的方法调用。

.Net Core有个比较方便的一点,就是实现了构造器的依赖注入,这样我们不用像以前那样手工New一个DBContext对象,直接在控制器将需要的DBContext注入,调用的时候,直接访问注入的对象即可,有关依赖注入的知识,这里就不在多说了,有兴趣大家可以了解一下:.Net Core依赖注入

首先,在ApplicationDbContext添加Menu数据集

 1 public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
 2 {
 3     public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
 4         : base(options)
 5     {
 6     }
 7 
 8     protected override void OnModelCreating(ModelBuilder builder)
 9     {
10         base.OnModelCreating(builder);
11     }
12 
13     public DbSet<ApplicationUser> ApplicationUsers { get; set; }
14 
15     public DbSet<Menu> Menus { get; set; }
16 }

这里我们修改下MenuController构造器:

1 private readonly ApplicationDbContext _context;
2 
3 public MenuController(ApplicationDbContext context, INavMenuService navMenuService)
4 {
5     _context = context;
6     _NavMenuService = navMenuService;
7 } 

为了后面方便统一提供下拉框选择,这里实现一个下拉框初始化方法:

 1 /// <summary>
 2 /// 初始化下拉选择框
 3 /// </summary>
 4 /// <param name="menu"></param>
 5 private void UpdateDropDownList(Menu menu = null)
 6 {
 7     var menusParent = _context.Menus.AsNoTracking().Where(s => s.MenuType == MenuTypes.导航菜单);
 8     List<SelectListItem> listMenusParent = new List<SelectListItem>();
 9     foreach (var menuParent in menusParent)
10     {
11         listMenusParent.Add(new SelectListItem
12         {
13             Value = menuParent.Id,
14             Text = menuParent.Id + $"({menuParent.Name})",
15             Selected = (menu != null && menuParent.Id == menu.ParentId)
16         });
17     }
18     ViewBag.ParentIds = listMenusParent;
19 
20     if (menu == null)
21     {
22         ViewBag.MenuTypes = MenuTypes.导航菜单.GetSelectListByEnum();
23     }
24     else
25     {
26         ViewBag.MenuTypes = MenuTypes.导航菜单.GetSelectListByEnum(Convert.ToInt32(menu.MenuType));
27     }
28 }

列表页改写

控制器调整:增加查询传入参数,根据参数筛选查询结果;

 1 /// <summary>
 2 /// 列表页
 3 /// </summary>
 4 /// <param name="query"></param>
 5 /// <returns></returns>
 6 public async Task<IActionResult> Index(MenuIndexQuery query)
 7 {
 8     var menus = _context.Menus.AsNoTracking();
 9     if (!string.IsNullOrEmpty(query.QName))
10     {
11         menus = menus.Where(s => s.Name.Contains(query.QName.Trim()));
12     }
13     if (!string.IsNullOrEmpty(query.QId))
14     {
15         menus = menus.Where(s => s.Id.Contains(query.QId.Trim()));
16     }
17     if (!string.IsNullOrEmpty(query.QParentId))
18     {
19         menus = menus.Where(s => s.ParentId == query.QParentId.Trim());
20     }
21     if (query.QMenuType != null)
22     {
23         menus = menus.Where(s => s.MenuType == query.QMenuType);
24     }
25 
26     UpdateDropDownList();
27     return View(new MenuIndexVM { Menus = await menus.ToListAsync(), Query = query });
28 }

视图调整:用户点击删除时,弹出确认框,调用Ajax方式删除数据,不再通过页面跳转;

  1 @using MyWebSite.ViewModels
  2 @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
  3 
  4 @model MyWebSite.Areas.Configuration.ViewModels.MenuIndexVM
  5 @{
  6     ViewData["Title"] = "菜单列表";
  7 
  8     var breadcrumb = new BreadCrumb("菜单列表", "Version 2.0", new List<NavCrumb>
  9     {
 10         new NavCrumb(name:"菜单管理",url: "/Configuration/Menu"),
 11         new NavCrumb(name:"菜单列表"),
 12     });
 13     ViewBag.BreadCrumb = breadcrumb;
 14 
 15     Layout = "~/Views/Shared/_Layout.cshtml";
 16 }
 17 
 18 <div class="row">
 19     <div class="col-xs-12">
 20         <div class="box with-border">
 21             <form class="form" asp-action="Index">
 22                 <div class="box-header">
 23                     <h3 class="box-title"><i class="fa fa-search margin-r-5">查询条件</i></h3>
 24                     <div class="box-tools pull-right">
 25                         <button type="submit" class="btn btn-success margin-r-5"><i class="fa fa-search margin-r-5"></i>查询</button>
 26                         <a class="btn btn-primary" href="/Configuration/Menu/Create"><i class="fa fa-plus margin-r-5"></i>新建</a>
 27                     </div>
 28                     <div asp-validation-summary="All" class="text-danger"></div>
 29                     <div class="row">
 30                         <div class="col-md-3">
 31                             <div class="form-group">
 32                                 <label asp-for="Query.QName">菜单名称:</label>
 33                                 <input asp-for="Query.QName" class="form-control input-sm">
 34                             </div>
 35                         </div>
 36                         <div class="col-md-3">
 37                             <div class="form-group">
 38                                 <label asp-for="Query.QId">菜单编码:</label>
 39                                 <input asp-for="Query.QId" class="form-control input-sm">
 40                             </div>
 41                         </div>
 42                         <div class="col-md-3">
 43                             <div class="form-group">
 44                                 <label asp-for="Query.QParentId">父级菜单:</label>
 45                                 <select asp-for="Query.QParentId" class="form-control input-sm select2" asp-items="ViewBag.ParentIds">
 46                                     <option value="">-- 请选择 --</option>
 47                                 </select>
 48                             </div>
 49                         </div>
 50                         <div class="col-md-3">
 51                             <div class="form-group">
 52                                 <label asp-for="Query.QMenuType">菜单类型:</label>
 53                                 <select asp-for="Query.QMenuType" class="form-control input-sm select2" asp-items="ViewBag.MenuTypes">
 54                                     <option value="">-- 请选择 --</option>
 55                                 </select>
 56                             </div>
 57                         </div>
 58                     </div>
 59                 </div>
 60             </form>
 61             <div class="box-body">
 62                 <table class="table table-bordered table-hover" style="width: 100%">
 63                     <thead>
 64                         <tr>
 65                             <th>#</th>
 66                             <th>菜单名称</th>
 67                             <th>菜单编号</th>
 68                             <th>父级编号</th>
 69                             <th>组内排序</th>
 70                             <th>菜单类型</th>
 71                             <th>菜单图标</th>
 72                             <th>菜单路径</th>
 73                             <th>操作</th>
 74                         </tr>
 75                     </thead>
 76                     <tbody>
 77                         @{
 78                             var index = 0;
 79                         }
 80                         @foreach (var item in Model.Menus)
 81                         {
 82                             index++;
 83                             <tr>
 84                                 <td>
 85                                     @index.ToString("D3")
 86                                 </td>
 87                                 <td>
 88                                     @Html.ActionLink(@item.Name, "Details", new { id = @item.Id })
 89                                 </td>
 90                                 <td>
 91                                     <span>@item.Id</span>
 92                                 </td>
 93                                 <td>
 94                                     <span>@Html.DisplayFor(modelItem => item.ParentId)</span>
 95                                 </td>
 96                                 <td>
 97                                     <span>@item.IndexCode</span>
 98                                 </td>
 99                                 <td>
100                                     <span>@item.MenuType</span>
101                                 </td>
102                                 <td>
103                                     <i class="fa @item.Icon" data-toggle="tooltip" data-placement="right" title="@item.Icon"></i>
104                                 </td>
105                                 <td>
106                                     <i class="fa fa-ellipsis-h" data-toggle="tooltip" data-placement="top" title="@Html.DisplayFor(modelItem => item.Url)"></i>
107                                 </td>
108                                 <td>
109                                     @Html.ActionLink("编辑", "Edit", new { id = @item.Id })|
110                                     @Html.ActionLink("详情", "Details", new { id = @item.Id })|
111                                     <a href="#" onclick="onDelete('@item.Id', '@item.Name');">删除</a>
112                                 </td>
113                             </tr>
114                         }
115                     </tbody>
116                 </table>
117             </div>
118         </div>
119     </div>
120 </div>
121 
122 @section Scripts{
12 

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
ComponentOneWebChartforASP.NET基础发布时间:2022-07-10
下一篇:
ASP.Net缓存总结发布时间:2022-07-10
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap