.Net Core Razor動態選單實現

微風吹過~發表於2022-04-28

準備

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>
            }
         }
    }
}

2.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>

 

相關文章