B08. BootstrapBlazor實戰 Menu 導航菜單使用(2)

接上篇: B08. BootstrapBlazor實戰 Menu 導航菜單使用(1)

實戰BootstrapBlazorMenu 導航菜單的使用, 以及整合Freesql orm快速製作菜單項資料庫後台維護頁面
demo演示的是Sqlite驅動,FreeSql支援多種資料庫,MySql/SqlServer/PostgreSQL/Oracle/Sqlite/Firebird/達夢/神通/人大金倉/翰高/華為GaussDB/MsAccess

3.項目模板

節省時間,直接使用 Bootstrap Blazor App 模板快速搭建項目

傳送門: //www.blazor.zone/template

3.1. 安裝項目模板

dotnet new -i Bootstrap.Blazor.Templates

3.2. 創建工程

dotnet new bbapp

4. 本次演示使用工程名字 b08Menu ,命令如下

dotnet new bbapp -o b08Menu
dotnet add b08Menu/BootstrapBlazorApp.Shared package FreeSql.Provider.Sqlite
dotnet add b08Menu/BootstrapBlazorApp.Shared package Densen.FreeSql.Extensions.BootstrapBlazor
dotnet sln add b08Menu/BootstrapBlazorApp.Server/BootstrapBlazorApp.Server.csproj
dotnet sln add b08Menu/BootstrapBlazorApp.Shared/BootstrapBlazorApp.Shared.csproj
dotnet sln add b08Menu/BootstrapBlazorApp.WebAssembly/BootstrapBlazorApp.WebAssembly.csproj

注:由於模板使用了共享庫,雙出ServerWebAssembly工程,我們這裡只使用Server工程做演示.

5. 數據服務

添加FreeSql服務到 BootstrapBlazorApp.Server/Program.cs 在 builder.Services.AddBootstrapBlazor(); 之前加入

builder.Services.AddFreeSql(option =>
{
    //demo演示的是Sqlite驅動,FreeSql支援多種資料庫,MySql/SqlServer/PostgreSQL/Oracle/Sqlite/Firebird/達夢/神通/人大金倉/翰高/華為GaussDB/MsAccess
    option.UseConnectionString(FreeSql.DataType.Sqlite, "Data Source=test.db;")  //也可以寫到配置文件中
#if DEBUG
         //開發環境:自動同步實體
         .UseAutoSyncStructure(true)
         .UseNoneCommandParameter(true)
         //調試sql語句輸出
         .UseMonitorCommand(cmd => System.Console.WriteLine(cmd.CommandText))
#endif
    ;
});

傳送門: //github.com/densen2014/Blazor100/wiki/B03.-BootstrapBlazor實戰-10分鐘編寫資料庫維護項目

6. Menu數據實體類

使用FreeSql的父子導航屬性處理樹形分類
傳送門: //github.com/densen2014/Blazor100/wiki/B05.-BootstrapBlazor實戰-Tree樹形控制項使用(2)

新建類文件 Data/WebPages.cs

/// <summary>
/// 頁面
/// </summary>
[AutoGenerateClass(Searchable = true, Filterable = true, Sortable = true)]
public class WebPages
{
    public WebPages() { }

    public WebPages(string PageName,  string? Url = null, string? Icon = null, string? Code = "0", List<WebPages>? Childs = null)
    {
        this.PageName = PageName;
        this.Url = Url ?? $"/{PageName}";
        this.Icon = Icon;
        this.Code = Code;
        this.Childs = Childs;
    }

    /// <summary>
    ///程式碼
    /// </summary>
    [DisplayName("程式碼")]
    [Column(IsPrimary = true)]
    [AutoGenerateColumn(DefaultSort = true, DefaultSortOrder = SortOrder.Asc)]
    public string? Code { get; set; }

    /// <summary>
    ///父級程式碼
    /// </summary>
    [DisplayName("父級程式碼")]
    [Column]
    public string? ParentCode { get; set; }

    [Navigate(nameof(ParentCode))]
    [AutoGenerateColumn(Ignore = true)]
    public WebPages? Parent { get; set; }

    [Navigate(nameof(ParentCode))]
    [AutoGenerateColumn(Ignore = true)]
    public List<WebPages>? Childs { get; set; }

    /// <summary>
    ///頁面名稱
    /// </summary>
    [Required(ErrorMessage = "{0}不能為空")]
    [DisplayName("頁面名稱")]
    public string? PageName { get; set; }

    /// <summary>
    ///Icon
    /// </summary>
    [DisplayName("Icon")]
    [AutoGenerateColumn(Visible = false)]
    public string? Icon { get; set; }

    /// <summary>
    ///Url
    /// </summary>
    [Required(ErrorMessage = "{0}不能為空")]
    [DisplayName("Url")]
    [AutoGenerateColumn(Visible = false)]
    public string? Url { get; set; } 

    /// <summary>
    /// 隱藏
    /// </summary>
    [DisplayName ("隱藏")]
    public bool Hide { get; set; } 

}

7. 擴展工具

寫文章的時候這個方法已經pr進BootstrapBlazor庫,可能讀者們看到的時候已經內置次方法了.如果重複,自行跳過這步.

public static class Utility
{ 
    /// <summary>
    /// 菜單樹狀數據層次化方法
    /// </summary>
    /// <param name="items">數據集合</param>
    /// <param name="parentId">父級節點</param>
    public static IEnumerable<MenuItem> CascadingMenu(this IEnumerable<MenuItem> items, string? parentId = null) => items.Where(i => i.ParentId == parentId).Select(i =>
    {
        i.Items = CascadingMenu(items, i.Id).ToList();
        return i;
    });
}

8. 菜單介面

找到BootstrapBlazorApp.Shared/Shared/MainLayout.razor文件,展開三角符號,打開MainLayout.razor.cs文件編輯

QQ截圖20220426003236

注入FreeSql

    [Inject]
    [NotNull]
    IFreeSql? fsql { get; set; }

Menus 初始化保存到資料庫

using Microsoft.AspNetCore.Components;
using System.Diagnostics.CodeAnalysis;
using BootstrapBlazorApp.Shared.Data;

//private List<MenuItem>? Menus { get; set; }
private List<MenuItem>? Menus { get; set; } = new List<MenuItem>();

   /// <summary>
    /// OnInitialized 方法
    /// </summary>
    protected override void OnInitialized()
    {
        base.OnInitialized();

        //Menus = GetIconSideMenuItems();
    }

    protected override void OnAfterRender(bool firstRender)
    {
        if (firstRender)
        {
            if (fsql.Select<WebPages>().Count() == 0)
            {
                var pages = new List<WebPages>(){
                    new WebPages("首頁","/","fa fa-home","001") ,
                    new WebPages("數據","","fa fa-fw fa-database","002",
                        new List<WebPages>(new[] {
                            new WebPages("FetchData","fetchdata","fa fa-fw fa-database","002_001") ,
                            new WebPages( "Counter","counter","fa fa-fw fa-check-square-o","002_002")  ,
                            new WebPages("後台管理","admins","fa fa-gears","002_003") ,
                        })) ,
                    new WebPages("Table","table","fa fa-fw fa-table","004")  ,
                    new WebPages("花名冊","users","fa fa-fw fa-users","005")
                };

                var repo = fsql.GetRepository<WebPages>();//倉庫類
                repo.DbContextOptions.EnableAddOrUpdateNavigateList = true; //開啟一對多,多對多級聯保存功能
                repo.Insert(pages); 
            }
            Menus =  fsql.Select<WebPages>().OrderBy(a => a.Code)
                        .LeftJoin(d => d.ParentCode == d.Parent!.Code)
                        .ToList(a => new MenuItem()
                        {
                            Text = a.PageName,
                            Id = a.Code,
                            Url = a.Url,
                            ParentId = a.ParentCode,
                            Icon = a.Icon
                        }).CascadingMenu().ToList();
            // 演算法獲取屬性結構數據 .CascadingMenu().ToList()
            StateHasChanged();
        }
    }

到這一步,大家肯定迫不及待要運行一下了,來吧,少年,F5

QQ截圖20220426012542

9. 菜單管理介面

使用Densen.FreeSql.Extensions.BootstrapBlazor庫的資料庫服務直接表格編輯菜單資料庫表格.

先註銷模板工程自帶演示服務,BootstrapBlazorApp.Server/Program.cs 註銷 builder.Services.AddTableDemoDataService();

// 增加 Table 數據服務操作類
//builder.Services.AddTableDemoDataService();

新建BootstrapBlazorApp.Shared/Pages/Admins.razor文件

@page "/admins"
@attribute [TabItemOption(Text = "菜單管理")]
<PageTitle>菜單管理</PageTitle>

<div class="table-users scroll">
    <Table TItem="WebPages"
           IsFixedHeader="true"
           IsPagination="true"
           IsStriped="true"
           AutoGenerateColumns="true"
           ShowSearch="true"
           ShowToolbar="true"
           ShowExtendButtons="true"
           DoubleClickToEdit=true
           ShowColumnList=true
           ShowCardView=true>
    </Table>
</div>

來吧,少年,F5

QQ截圖20220426012346

QQ截圖20220426012400

是不是很有成就感,你怎麼這麼優秀呢? 哈哈哈.

10.添加菜單

QQ截圖20220426013317

刷新頁面

QQ截圖20220426013344

少年, 如期而來!

11.下一篇大概是: Layout 組件

項目源碼

Github | Gitee

關聯項目

FreeSql QQ群:4336577(已滿)、8578575(已滿)、52508226(在線)

BA & Blazor QQ群:795206915、675147445

知識共享許可協議

本作品採用 知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議 進行許可。歡迎轉載、使用、重新發布,但務必保留文章署名AlexChow(包含鏈接: //github.com/densen2014 ),不得用於商業目的,基於本文修改後的作品務必以相同的許可發布。如有任何疑問,請與我聯繫

AlexChow

今日頭條 | 部落格園 | 知乎 | Gitee | GitHub