準備
1.框架
.netcore 版本 yishaadmin開源框架
2.模板
本文模板使用adminlte3.0,文件地址https://adminlte.io/docs/3.0/
3.選單表
關鍵欄位
id 表主鍵(當前選單)ParentId 父級ID(父級選單 為0時為頂級選單,也可能為內容)
MenuUrl 選單地址(只有頁面有地址,本身選單是空)
MenuType 選單型別(1是選單 2是頁面 3是按鈕)
MenuIcon 圖示樣式
4.選單表實體
using Newtonsoft.Json; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; using System.Text; using System.Threading.Tasks; using YiSha.Util; namespace YiSha.Entity.SystemManage { [Table("SysMenu")] public class MenuEntity : BaseExtensionEntity { [JsonConverter(typeof(StringJsonConverter))] public long? ParentId { get; set; } public string MenuName { get; set; } public string MenuIcon { get; set; } public string MenuUrl { get; set; } public string MenuTarget { get; set; } public int? MenuSort { get; set; } public int? MenuType { get; set; } public int? MenuStatus { get; set; } public string Authorize { get; set; } public string Remark { get; set; } [NotMapped] public string ParentName { get; set; } } }
開始開發
本文是由於框架內建選單不支援頂級選單顯示為內容,以及選單最多隻支援三級選單的問題,故進行了調整。
1.實現思路
下圖1區域渲染為選單,選單通過點選URL將內容填充到2區域。
2.編碼
2.1 建立渲染內容填充方法
將傳進來的url通過ajax呼叫最終渲染到內容區域(id為#Content的Div中),其中beforeSend方法顯示Loadding 可根據需要自行調整。url為{area:exists}/{controller=Home}/{action=Index}以及{controller=Home}/{action=Index}根據框架配置填寫至選單
function LoadContent(url) { if (url == null || url == "") return; $.ajax({ url: url, beforeSend: function (XHR) { $.blockUI({ message: '<div class="loaderbox"><div class="loading-activity"></div> '
+ "載入中..." + '</div>', css: { border: "none", backgroundColor: 'transparent' } }); }, success: function (data) { $("#Content").html(data); setTimeout(function () { $.unblockUI(); }, 100); }, error: function (data, status, e) { $("#Content").html("頁面載入失敗," + data.status + "," + url + "<br />" + data.responseText); setTimeout(function () { $.unblockUI(); }, 100); } }); }
2.2 建立分部檢視
通過建立分部檢視MenuTree,迴圈傳入的選單,初始化時先獲取父級ID(ParentId)為0並且類別(MenuType)不為按鈕的選單集合進行迴圈,根據menuEntity.MenuUrl判斷是否為頁面,如果依然為選單則使用Html.PartialAsync("MenuTree")呼叫自身來實現遞迴,第二次則根據ViewData["Menu"]傳入的當前id作為父級id來尋找子集,直到尋找到最後的層級。@using System.Collections.Generic @using YiSha.Entity.SystemManage; @model List<MenuEntity> @{ if (Model.Any()) { long id = 0L; var menu = ViewData["Menu"] as MenuEntity; if (menu != null) id = menu.Id.Value; @foreach (var menuEntity in Model.Where(o => o.ParentId == id && o.MenuType != (int)MenuTypeEnum.Button)) { var icno = string.IsNullOrEmpty(menuEntity.MenuIcon) ? "fa fa-comment" : menuEntity.MenuIcon; @if (!string.IsNullOrEmpty(menuEntity.MenuUrl)) { <li class="nav-item"> <a href="#" class="nav-link" onclick="LoadContent('@menuEntity.MenuUrl')"> <i class="nav-icon @icno"></i> <p> @menuEntity.MenuName </p> </a> </li> } else { ViewData["Menu"] = menuEntity; <li class="nav-item"> <a href="#" class="nav-link"> <i class="nav-icon @icno"></i> <p> @menuEntity.MenuName <i class="fas fa-angle-left right"></i> </p> </a> <ul class="nav nav-treeview"> @await Html.PartialAsync("MenuTree", Model,new ViewDataDictionary(ViewData)) </ul> </li> } } } }
3.呼叫分佈檢視
<aside class="main-sidebar sidebar-dark-primary elevation-4" style="width:200px;position:fixed"> <!-- Brand Logo --> <!-- Sidebar --> <div class="sidebar"> <!-- Sidebar Menu --> <nav class="mt-2"> <ul class="nav nav-pills nav-sidebar flex-column" data-widget="treeview" role="menu" data-accordion="false"> <!-- Add icons to the links using the .nav-icon class with font-awesome or any other icon font library --> <li class="nav-header" style="font-size:1.0rem"> <img src="~/yisha/img/logo1.png" style="width: 30px; height: 30px; " /> 任務管理系統 </li> @await Html.PartialAsync("MenuTree", Model) </ul> </nav> <!-- /.sidebar-menu --> </div> <!-- /.sidebar --> </aside> <!-- Content Wrapper. Contains page content --> <div class="content-wrapper" id="mainhead"> <div id="Content"> </div> </div>