From 7c3339989147bcdf876d6aea866ddf3f0b08eb6a Mon Sep 17 00:00:00 2001 From: Argo Windows Date: Mon, 4 Nov 2019 18:41:42 +0800 Subject: [PATCH 01/20] =?UTF-8?q?feat:=20=E7=99=BB=E5=BD=95=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/admin/Bootstrap.Admin/App.razor | 20 +++ src/admin/Bootstrap.Admin/BootstrapAdmin.db | Bin 102400 -> 413696 bytes .../Controllers/Api/AppsController.cs | 4 +- .../Controllers/HomeController.cs | 6 +- .../Models/NavigatorBarModel.cs | 16 +- .../Bootstrap.Admin/Pages/Admin/Home.razor | 7 + .../Pages/Admin/_Imports.razor | 1 + src/admin/Bootstrap.Admin/Pages/_Host.cshtml | 48 ++++++ src/admin/Bootstrap.Admin/Shared/Footer.razor | 16 ++ src/admin/Bootstrap.Admin/Shared/Header.razor | 142 ++++++++++++++++++ .../Bootstrap.Admin/Shared/MainLayout.razor | 27 ++++ .../Bootstrap.Admin/Shared/NavMenu.razor | 42 ++++++ .../Shared/NotAuthorizedHandler.razor | 33 ++++ src/admin/Bootstrap.Admin/Startup.cs | 5 +- src/admin/Bootstrap.Admin/_Imports.razor | 12 ++ .../appsettings.Development.json | 1 + .../Bootstrap.DataAccess.csproj | 2 +- 17 files changed, 373 insertions(+), 9 deletions(-) create mode 100644 src/admin/Bootstrap.Admin/App.razor create mode 100644 src/admin/Bootstrap.Admin/Pages/Admin/Home.razor create mode 100644 src/admin/Bootstrap.Admin/Pages/Admin/_Imports.razor create mode 100644 src/admin/Bootstrap.Admin/Pages/_Host.cshtml create mode 100644 src/admin/Bootstrap.Admin/Shared/Footer.razor create mode 100644 src/admin/Bootstrap.Admin/Shared/Header.razor create mode 100644 src/admin/Bootstrap.Admin/Shared/MainLayout.razor create mode 100644 src/admin/Bootstrap.Admin/Shared/NavMenu.razor create mode 100644 src/admin/Bootstrap.Admin/Shared/NotAuthorizedHandler.razor create mode 100644 src/admin/Bootstrap.Admin/_Imports.razor diff --git a/src/admin/Bootstrap.Admin/App.razor b/src/admin/Bootstrap.Admin/App.razor new file mode 100644 index 00000000..31b7f34d --- /dev/null +++ b/src/admin/Bootstrap.Admin/App.razor @@ -0,0 +1,20 @@ + + + + + + + +

Authentication in progress

+

Only visible while authentication is in progress.

+
+
+
+ + + +

Sorry, there's nothing at this address.

+
+
+
+
\ No newline at end of file diff --git a/src/admin/Bootstrap.Admin/BootstrapAdmin.db b/src/admin/Bootstrap.Admin/BootstrapAdmin.db index 78ebda81f41a83d3440eef6cdacc8d719c17b09c..c48b58a8f9af75dff471c6070cb128c96429e239 100644 GIT binary patch literal 413696 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 /// [HttpGet("{id}")] - public IEnumerable Get(string id) => AppHelper.RetrievesByRoleId(id); + public IEnumerable Get(string id) => AppHelper.RetrievesByRoleId(id); } } diff --git a/src/admin/Bootstrap.Admin/Controllers/HomeController.cs b/src/admin/Bootstrap.Admin/Controllers/HomeController.cs index 9e95b7c7..804aab7d 100644 --- a/src/admin/Bootstrap.Admin/Controllers/HomeController.cs +++ b/src/admin/Bootstrap.Admin/Controllers/HomeController.cs @@ -3,6 +3,7 @@ using Bootstrap.DataAccess; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Configuration; namespace Bootstrap.Admin.Controllers { @@ -16,11 +17,12 @@ namespace Bootstrap.Admin.Controllers /// Index View /// /// - public IActionResult Index() + public IActionResult Index([FromServices]IConfiguration configuration) { var model = new HeaderBarModel(User.Identity.Name); var homeUrl = DictHelper.RetrieveHomeUrl(model.AppId); - return homeUrl.Equals("~/Home/Index", System.StringComparison.OrdinalIgnoreCase) ? (IActionResult)View(model) : Redirect(homeUrl); + var useBlazor = configuration.GetValue("UseBlazor", false); + return useBlazor ? Redirect("~/Admin/Home") : homeUrl.Equals("~/Home/Index", System.StringComparison.OrdinalIgnoreCase) ? (IActionResult)View(model) : Redirect(homeUrl); } /// diff --git a/src/admin/Bootstrap.Admin/Models/NavigatorBarModel.cs b/src/admin/Bootstrap.Admin/Models/NavigatorBarModel.cs index 9ef31894..9ecc0611 100644 --- a/src/admin/Bootstrap.Admin/Models/NavigatorBarModel.cs +++ b/src/admin/Bootstrap.Admin/Models/NavigatorBarModel.cs @@ -16,10 +16,20 @@ namespace Bootstrap.Admin.Models /// 构造函数 /// /// - public NavigatorBarModel(ControllerBase controller) : base(controller.User.Identity.Name) + public NavigatorBarModel(ControllerBase controller) : this(controller.User.Identity.Name) { - Navigations = MenuHelper.RetrieveSystemMenus(UserName, $"~{controller.HttpContext.Request.Path}"); - var authApps = AppHelper.RetrievesByUserName(controller.User.Identity.Name); + + } + + /// + /// Blazor 使用构造函数 + /// + /// + /// + public NavigatorBarModel(string userName, string activeUrl = "~/Admin/Index") : base(userName) + { + Navigations = MenuHelper.RetrieveSystemMenus(UserName, activeUrl); + var authApps = AppHelper.RetrievesByUserName(userName); Applications = DictHelper.RetrieveApps().Where(app => app.Key.IsNullOrEmpty() || authApps.Any(key => key.Equals(app.Key, StringComparison.OrdinalIgnoreCase))); } diff --git a/src/admin/Bootstrap.Admin/Pages/Admin/Home.razor b/src/admin/Bootstrap.Admin/Pages/Admin/Home.razor new file mode 100644 index 00000000..2dd49493 --- /dev/null +++ b/src/admin/Bootstrap.Admin/Pages/Admin/Home.razor @@ -0,0 +1,7 @@ +@page "/Admin/Home" + +

Home

+ +@code { + +} diff --git a/src/admin/Bootstrap.Admin/Pages/Admin/_Imports.razor b/src/admin/Bootstrap.Admin/Pages/Admin/_Imports.razor new file mode 100644 index 00000000..b09fed5c --- /dev/null +++ b/src/admin/Bootstrap.Admin/Pages/Admin/_Imports.razor @@ -0,0 +1 @@ +@attribute [Authorize] \ No newline at end of file diff --git a/src/admin/Bootstrap.Admin/Pages/_Host.cshtml b/src/admin/Bootstrap.Admin/Pages/_Host.cshtml new file mode 100644 index 00000000..fd5b1e37 --- /dev/null +++ b/src/admin/Bootstrap.Admin/Pages/_Host.cshtml @@ -0,0 +1,48 @@ +@page "/" +@namespace Bootstrap.Admin.Pages +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers + + + + + + + + + + + + Host + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @(await Html.RenderComponentAsync(RenderMode.ServerPrerendered)) + + + + diff --git a/src/admin/Bootstrap.Admin/Shared/Footer.razor b/src/admin/Bootstrap.Admin/Shared/Footer.razor new file mode 100644 index 00000000..0ec7230f --- /dev/null +++ b/src/admin/Bootstrap.Admin/Shared/Footer.razor @@ -0,0 +1,16 @@ +
+
@Model.Footer(演示系统)
+ + + +
+ +@code { + private AdminModel Model; + + protected override Task OnInitializedAsync() + { + Model = new AdminModel(); + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/src/admin/Bootstrap.Admin/Shared/Header.razor b/src/admin/Bootstrap.Admin/Shared/Header.razor new file mode 100644 index 00000000..cfd4a844 --- /dev/null +++ b/src/admin/Bootstrap.Admin/Shared/Header.razor @@ -0,0 +1,142 @@ +@inject AuthenticationStateProvider authenticationStateProvider + +
+
+
+ + + @Model.Title + + + +
+ +
+ +@code { + private HeaderBarModel Model; + private ClaimsPrincipal User; + + protected override async Task OnInitializedAsync() + { + var state = await authenticationStateProvider.GetAuthenticationStateAsync(); + User = state.User; + if(state.User.Identity.IsAuthenticated) + { + Model = new HeaderBarModel(state.User.Identity.Name); + } + } +} \ No newline at end of file diff --git a/src/admin/Bootstrap.Admin/Shared/MainLayout.razor b/src/admin/Bootstrap.Admin/Shared/MainLayout.razor new file mode 100644 index 00000000..98a77c32 --- /dev/null +++ b/src/admin/Bootstrap.Admin/Shared/MainLayout.razor @@ -0,0 +1,27 @@ +@inherits LayoutComponentBase + +
+ +
+ +
+ +
+ @Body +
+
+ +@code { + private AdminModel Model; + + protected override Task OnInitializedAsync() + { + Model = new AdminModel(); + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/src/admin/Bootstrap.Admin/Shared/NavMenu.razor b/src/admin/Bootstrap.Admin/Shared/NavMenu.razor new file mode 100644 index 00000000..83cbe275 --- /dev/null +++ b/src/admin/Bootstrap.Admin/Shared/NavMenu.razor @@ -0,0 +1,42 @@ +@inject AuthenticationStateProvider authenticationStateProvider + + + +@code { + private NavigatorBarModel Model; + + protected override async Task OnInitializedAsync() + { + var state = await authenticationStateProvider.GetAuthenticationStateAsync(); + if (state.User.Identity.IsAuthenticated) + { + Model = new NavigatorBarModel(state.User.Identity.Name); + } + } +} diff --git a/src/admin/Bootstrap.Admin/Shared/NotAuthorizedHandler.razor b/src/admin/Bootstrap.Admin/Shared/NotAuthorizedHandler.razor new file mode 100644 index 00000000..384a5223 --- /dev/null +++ b/src/admin/Bootstrap.Admin/Shared/NotAuthorizedHandler.razor @@ -0,0 +1,33 @@ +@inject AuthenticationStateProvider authenticationStateProvider +@inject NavigationManager navigationManager + +@if (showNotAuthorizedMessage) +{ +
+
+
+
+
+
+} + +@code { + + private bool showNotAuthorizedMessage = false; + + protected override async Task OnInitializedAsync() + { + var state = await authenticationStateProvider.GetAuthenticationStateAsync(); + + if (!state.User.Identity.IsAuthenticated) + { + // If the user is not authenticated redirect them to the sign in page + navigationManager.NavigateTo("/Account/Login?returnUrl=" + System.Net.WebUtility.UrlEncode(new Uri(navigationManager.Uri).PathAndQuery)); + } + else + { + // If the user is signed in, but authorization failed, display a message + showNotAuthorizedMessage = true; + } + } +} \ No newline at end of file diff --git a/src/admin/Bootstrap.Admin/Startup.cs b/src/admin/Bootstrap.Admin/Startup.cs index 037c7cca..dcd83b9c 100644 --- a/src/admin/Bootstrap.Admin/Startup.cs +++ b/src/admin/Bootstrap.Admin/Startup.cs @@ -1,5 +1,4 @@ using Bootstrap.DataAccess; -using Longbow.Web; using Longbow.Web.SignalR; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Builder; @@ -83,6 +82,8 @@ namespace Bootstrap.Admin options.Filters.Add(); options.Filters.Add>(); }).AddJsonOptions(op => op.JsonSerializerOptions.AddDefaultConverters()); + services.AddRazorPages(); + services.AddServerSideBlazor(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. @@ -122,6 +123,8 @@ namespace Bootstrap.Admin endpoints.MapHub("/NotiHub"); endpoints.MapHub("/TaskLogHub"); endpoints.MapBootstrapHealthChecks(); + endpoints.MapBlazorHub(); + endpoints.MapFallbackToPage("/_Host"); endpoints.MapDefaultControllerRoute(); }); } diff --git a/src/admin/Bootstrap.Admin/_Imports.razor b/src/admin/Bootstrap.Admin/_Imports.razor new file mode 100644 index 00000000..308af86e --- /dev/null +++ b/src/admin/Bootstrap.Admin/_Imports.razor @@ -0,0 +1,12 @@ +@using System.Net.Http +@using System.Security.Claims +@using Microsoft.AspNetCore.Authorization +@using Microsoft.AspNetCore.Components.Authorization +@using Microsoft.AspNetCore.Components.Forms +@using Microsoft.AspNetCore.Components.Routing +@using Microsoft.AspNetCore.Components.Web +@using Microsoft.AspNetCore.Mvc +@using Microsoft.JSInterop +@using Bootstrap.Admin +@using Bootstrap.Admin.Shared +@using Bootstrap.Admin.Models diff --git a/src/admin/Bootstrap.Admin/appsettings.Development.json b/src/admin/Bootstrap.Admin/appsettings.Development.json index 80ec42f5..fb9f17db 100644 --- a/src/admin/Bootstrap.Admin/appsettings.Development.json +++ b/src/admin/Bootstrap.Admin/appsettings.Development.json @@ -57,6 +57,7 @@ } } ], + "UseBlazor": true, "SwaggerPathBase": "", "AllowOrigins": "http://localhost:49185", "FileStorageOptions": { diff --git a/src/admin/Bootstrap.DataAccess/Bootstrap.DataAccess.csproj b/src/admin/Bootstrap.DataAccess/Bootstrap.DataAccess.csproj index 7ab5772c..1d8ad2b4 100644 --- a/src/admin/Bootstrap.DataAccess/Bootstrap.DataAccess.csproj +++ b/src/admin/Bootstrap.DataAccess/Bootstrap.DataAccess.csproj @@ -6,7 +6,7 @@ - + From 5ec8eb4cce606569d0db803ffb9a4fa882876974 Mon Sep 17 00:00:00 2001 From: Argo Window10 Date: Sun, 17 Nov 2019 16:46:51 +0800 Subject: [PATCH 02/20] =?UTF-8?q?feat:=20=E5=AE=8C=E6=88=90=E9=A6=96?= =?UTF-8?q?=E9=A1=B5=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Bootstrap.Admin/Pages/Admin/Home.razor | 8 ----- .../Bootstrap.Admin/Pages/Admin/Index.razor | 10 ++++++ .../Pages/ConfigurationHelperExtensions.cs | 17 ++++++++++ .../{UrlHelper.cs => UrlHelperExtensions.cs} | 2 +- src/admin/Bootstrap.Admin/Pages/_Host.cshtml | 2 +- .../Bootstrap.Admin/Shared/AdminLayout.razor | 31 +++++++++++++++++++ src/admin/Bootstrap.Admin/Shared/Footer.razor | 2 +- .../Bootstrap.Admin/Shared/MainLayout.razor | 5 +-- 8 files changed, 64 insertions(+), 13 deletions(-) delete mode 100644 src/admin/Bootstrap.Admin/Pages/Admin/Home.razor create mode 100644 src/admin/Bootstrap.Admin/Pages/Admin/Index.razor create mode 100644 src/admin/Bootstrap.Admin/Pages/ConfigurationHelperExtensions.cs rename src/admin/Bootstrap.Admin/Pages/{UrlHelper.cs => UrlHelperExtensions.cs} (93%) create mode 100644 src/admin/Bootstrap.Admin/Shared/AdminLayout.razor diff --git a/src/admin/Bootstrap.Admin/Pages/Admin/Home.razor b/src/admin/Bootstrap.Admin/Pages/Admin/Home.razor deleted file mode 100644 index e257c56b..00000000 --- a/src/admin/Bootstrap.Admin/Pages/Admin/Home.razor +++ /dev/null @@ -1,8 +0,0 @@ -@page "/Pages/Admin/Index" -@page "/Pages" - -

Home

- -@code { - -} diff --git a/src/admin/Bootstrap.Admin/Pages/Admin/Index.razor b/src/admin/Bootstrap.Admin/Pages/Admin/Index.razor new file mode 100644 index 00000000..755a1db1 --- /dev/null +++ b/src/admin/Bootstrap.Admin/Pages/Admin/Index.razor @@ -0,0 +1,10 @@ +@page "/Pages/Admin/Index" +@page "/Pages/Admin" +@page "/Pages" +@layout AdminLayout + +

欢迎使用后台管理

+ +@code { + +} diff --git a/src/admin/Bootstrap.Admin/Pages/ConfigurationHelperExtensions.cs b/src/admin/Bootstrap.Admin/Pages/ConfigurationHelperExtensions.cs new file mode 100644 index 00000000..b627cb90 --- /dev/null +++ b/src/admin/Bootstrap.Admin/Pages/ConfigurationHelperExtensions.cs @@ -0,0 +1,17 @@ +using Microsoft.Extensions.Configuration; + +namespace Bootstrap.Admin.Pages +{ + /// + /// 配置文件静态操作类 + /// + public static class ConfigurationHelperExtensions + { + /// + /// 获得本站 AppId + /// + /// + /// + public static string GetAppId(this IConfiguration configuration) => configuration.GetValue("AppId", "BA"); + } +} diff --git a/src/admin/Bootstrap.Admin/Pages/UrlHelper.cs b/src/admin/Bootstrap.Admin/Pages/UrlHelperExtensions.cs similarity index 93% rename from src/admin/Bootstrap.Admin/Pages/UrlHelper.cs rename to src/admin/Bootstrap.Admin/Pages/UrlHelperExtensions.cs index 36fbe642..c8f16c94 100644 --- a/src/admin/Bootstrap.Admin/Pages/UrlHelper.cs +++ b/src/admin/Bootstrap.Admin/Pages/UrlHelperExtensions.cs @@ -3,7 +3,7 @@ /// /// Url 地址辅助操作类 /// - public static class UrlHelper + public static class UrlHelperExtensions { /// /// 转换为 Blazor 地址 diff --git a/src/admin/Bootstrap.Admin/Pages/_Host.cshtml b/src/admin/Bootstrap.Admin/Pages/_Host.cshtml index d730135e..1f1f959e 100644 --- a/src/admin/Bootstrap.Admin/Pages/_Host.cshtml +++ b/src/admin/Bootstrap.Admin/Pages/_Host.cshtml @@ -12,7 +12,7 @@ - Host + 通用后台管理框架 Blazor 版 diff --git a/src/admin/Bootstrap.Admin/Shared/AdminLayout.razor b/src/admin/Bootstrap.Admin/Shared/AdminLayout.razor new file mode 100644 index 00000000..bb5e260b --- /dev/null +++ b/src/admin/Bootstrap.Admin/Shared/AdminLayout.razor @@ -0,0 +1,31 @@ +@inherits LayoutComponentBase +@inject AuthenticationStateProvider authenticationStateProvider +@inject NavigationManager navigationManager +@inject IConfiguration configuration + +
+ +
+ + @Body +
+
+ +@code { + protected AdminModel? Model; + + protected override async Task OnInitializedAsync() + { + var state = await authenticationStateProvider.GetAuthenticationStateAsync(); + if (!state.User.Identity.IsAuthenticated) + { + navigationManager.NavigateTo("/Account/Login?returnUrl=" + WebUtility.UrlEncode(new Uri(navigationManager.Uri).PathAndQuery)); + } + else + { + Model = new AdminModel(configuration.GetAppId()); + } + } +} \ No newline at end of file diff --git a/src/admin/Bootstrap.Admin/Shared/Footer.razor b/src/admin/Bootstrap.Admin/Shared/Footer.razor index d98f874a..3329b33d 100644 --- a/src/admin/Bootstrap.Admin/Shared/Footer.razor +++ b/src/admin/Bootstrap.Admin/Shared/Footer.razor @@ -12,7 +12,7 @@ protected override Task OnInitializedAsync() { - Model = new AdminModel(configuration.GetValue("AppId", "BA")); + Model = new AdminModel(configuration.GetAppId()); return Task.CompletedTask; } } \ No newline at end of file diff --git a/src/admin/Bootstrap.Admin/Shared/MainLayout.razor b/src/admin/Bootstrap.Admin/Shared/MainLayout.razor index 261f8936..93ff660c 100644 --- a/src/admin/Bootstrap.Admin/Shared/MainLayout.razor +++ b/src/admin/Bootstrap.Admin/Shared/MainLayout.razor @@ -1,6 +1,7 @@ @inherits LayoutComponentBase @inject AuthenticationStateProvider authenticationStateProvider @inject NavigationManager navigationManager +@inject IConfiguration configuration
public string DisplayName { get; set; } = ""; - /// - /// 添加新 Tab 栏方法 - /// - /// - public void AddTab(BootstrapMenu? menu) - { - if (menu != null) - { - TabSet?.AddTab(menu); - PageSet?.AddPage(menu); - } - } - - /// - /// - /// - /// - public async Task CloseTab(string? tabId) - { - if (TabSet != null) - { - if (TabSet.TabCount == 1) RootLayout.NavigationManager?.NavigateTo(RootLayout.HomeUrl); - else - { - var pageId = await TabSet.CloseTab(tabId); - PageSet?.RemovePage(tabId, pageId); - } - } - } - /// /// /// @@ -82,7 +45,7 @@ namespace Bootstrap.Admin.Components var path = new Uri(requestUrl).PathAndQuery; var menus = DataAccess.MenuHelper.RetrieveAllMenus(RootLayout.UserName); var menu = menus.FirstOrDefault(menu => path.Contains(menu.Url.ToBlazorMenuUrl())); - AddTab(menu); + if (menu != null) TabSet?.AddTab(menu); } } } diff --git a/src/admin/Bootstrap.Admin/Components/PageContentAttributes.cs b/src/admin/Bootstrap.Admin/Components/PageContentAttributes.cs index 659bb3ca..4074d1db 100644 --- a/src/admin/Bootstrap.Admin/Components/PageContentAttributes.cs +++ b/src/admin/Bootstrap.Admin/Components/PageContentAttributes.cs @@ -1,18 +1,23 @@ namespace Bootstrap.Admin.Components { /// - /// + /// /// public class PageContentAttributes { /// - /// + /// 获得/设置 页面 ID /// public string? Id { get; set; } /// - /// + /// 获得/设置 页面名称 /// public string Name { get; set; } = ""; + + /// + /// 获得/设置 是否显示 + /// + public bool Active { get; set; } } } diff --git a/src/admin/Bootstrap.Admin/Components/PageSetBase.cs b/src/admin/Bootstrap.Admin/Components/PageSetBase.cs deleted file mode 100644 index fadd675d..00000000 --- a/src/admin/Bootstrap.Admin/Components/PageSetBase.cs +++ /dev/null @@ -1,85 +0,0 @@ -using Bootstrap.Admin.Extensions; -using Bootstrap.Security; -using System.Collections.Generic; -using System.Linq; - -namespace Bootstrap.Admin.Components -{ - /// - /// - /// - public class PageSetBase : BootstrapComponentBase - { - /// - /// - /// - protected List Pages { get; set; } = new List(); - private string? curId = ""; - - /// - /// - /// - /// - protected override void OnAfterRender(bool firstRender) - { - if (!string.IsNullOrEmpty(curId)) - { - // Add Page 后设置 active 状态 - Activate(curId); - curId = ""; - } - } - - /// - /// - /// - /// - public void Activate(string? pageId) => JSRuntime.ActivePage(pageId); - - /// - /// - /// - /// - public void AddPage(BootstrapMenu menu) - { - var page = Pages.FirstOrDefault(p => p.Id == menu.Id); - if (page == null) - { - Pages.Add(new PageContentAttributes() { Id = menu.Id, Name = menu.Url }); - curId = menu.Id; - StateHasChanged(); - } - else - { - Activate(menu.Id); - } - } - - /// - /// - /// - /// - /// - public void RemovePage(string? pageId, string? newId) - { - if (!string.IsNullOrEmpty(pageId)) - { - var page = Pages.FirstOrDefault(p => p.Id == pageId); - if (page != null) - { - Pages.Remove(page); - curId = newId; - StateHasChanged(); - } - } - } - - /// - /// - /// - public void RemoveAllPage() - { - Pages.Clear(); - } - } -} diff --git a/src/admin/Bootstrap.Admin/Components/TabBase.cs b/src/admin/Bootstrap.Admin/Components/TabBase.cs index e45b45f8..cd734ad9 100644 --- a/src/admin/Bootstrap.Admin/Components/TabBase.cs +++ b/src/admin/Bootstrap.Admin/Components/TabBase.cs @@ -1,50 +1,57 @@ using Bootstrap.Admin.Extensions; using Bootstrap.Security; using Microsoft.AspNetCore.Components; +using System.Threading.Tasks; namespace Bootstrap.Admin.Components { /// - /// + /// /// public class TabBase : BootstrapComponentBase { /// - /// + /// /// [Parameter] public string Title { get; set; } = ""; /// - /// + /// /// [Parameter] public string? Id { get; set; } /// - /// + /// /// [Parameter] public string Url { get; set; } = ""; /// - /// + /// /// [Parameter] public string Icon { get; set; } = ""; + /// + /// + /// + [Parameter] + public bool Active { get; set; } + private bool closeTab; /// - /// + /// /// - protected void CloseTab() + protected async Task CloseTab() { closeTab = true; - Layout?.CloseTab(Id); + if (Layout.TabSet != null) await Layout.TabSet.CloseTab(Id); } /// - /// + /// /// protected void ClickTab() { @@ -53,7 +60,7 @@ namespace Bootstrap.Admin.Components } /// - /// + /// /// /// public void Init(BootstrapMenu menu) @@ -62,6 +69,13 @@ namespace Bootstrap.Admin.Components Url = menu.Url.ToBlazorMenuUrl(); Icon = menu.Icon; Id = menu.Id; + Active = true; } + + /// + /// + /// + /// + public void SetActive(bool val) => Active = val; } } diff --git a/src/admin/Bootstrap.Admin/Components/TabSetBase.cs b/src/admin/Bootstrap.Admin/Components/TabSetBase.cs index 043eb66f..6cf0e4c9 100644 --- a/src/admin/Bootstrap.Admin/Components/TabSetBase.cs +++ b/src/admin/Bootstrap.Admin/Components/TabSetBase.cs @@ -8,23 +8,23 @@ using System.Threading.Tasks; namespace Bootstrap.Admin.Components { /// - /// + /// TabSet 组件类 /// public class TabSetBase : BootstrapComponentBase { /// - /// + /// 页面集合 /// - public int TabCount { get { return Tabs.Count; } } + protected List Pages { get; set; } = new List(); /// - /// + /// Tab 集合 /// protected List Tabs { get; set; } = new List(); private string? curId; /// - /// + /// 页面呈现后回调方法 /// /// protected override void OnAfterRender(bool firstRender) @@ -48,38 +48,56 @@ namespace Bootstrap.Admin.Components { tab = new Tab(); tab.Init(menu); + Tabs.ForEach(t => t.SetActive(false)); Tabs.Add(tab); - curId = tab.Id; - StateHasChanged(); + Pages.ForEach(p => p.Active = false); + Pages.Add(new PageContentAttributes() { Id = menu.Id, Name = menu.Url, Active = true }); } else { - JSRuntime.ActiveMenu(tab.Id); + Tabs.ForEach(t => t.SetActive(t.Id == tab.Id)); + Pages.ForEach(p => p.Active = p.Id == tab.Id); } + curId = tab.Id; + StateHasChanged(); } /// - /// + /// 关闭指定标签页方法 /// /// /// - public async Task CloseTab(string? tabId) + public async Task CloseTab(string? tabId) { + if (Tabs.Count == 1) + { + CloseAllTab(); + return; + } if (!string.IsNullOrEmpty(tabId)) { var tab = Tabs.FirstOrDefault(tb => tb.Id == tabId); if (tab != null) { + // 移除 PageContent + var page = Pages.FirstOrDefault(p => p.Id == tab.Id); + if (page != null) Pages.Remove(page); + + // 移除 Tab 返回下一个 TabId tabId = await JSRuntime.RemoveTabAsync(tab.Id); Tabs.Remove(tab); + tab = Tabs.FirstOrDefault(t => t.Id == tabId); + tab.SetActive(true); + + page = Pages.FirstOrDefault(p => p.Id == tabId); + if (page != null) page.Active = true; StateHasChanged(); } } - return tabId; } /// - /// + /// 关闭所有标签页方法 /// protected void CloseAllTab() { @@ -87,7 +105,31 @@ namespace Bootstrap.Admin.Components } /// - /// + /// 关闭当前标签页方法 + /// + protected async Task CloseCurrentTab() + { + var tabId = Tabs.FirstOrDefault(t => t.Active)?.Id; + await CloseTab(tabId); + } + + /// + /// 关闭其他标签页方法 + /// + protected void CloseOtherTab() + { + var tabId = Tabs.FirstOrDefault(t => t.Active)?.Id; + if (!string.IsNullOrEmpty(tabId)) + { + Tabs.RemoveAll(t => t.Id != tabId); + Pages.RemoveAll(page => page.Id != tabId); + curId = tabId; + StateHasChanged(); + } + } + + /// + /// 前移标签页方法 /// protected async Task MovePrev() { @@ -96,7 +138,7 @@ namespace Bootstrap.Admin.Components } /// - /// + /// 后移标签页方法 /// /// protected async Task MoveNext() diff --git a/src/admin/Bootstrap.Admin/Extensions/JSRuntimeExtensions.cs b/src/admin/Bootstrap.Admin/Extensions/JSRuntimeExtensions.cs index 2ba36e7e..2db67f40 100644 --- a/src/admin/Bootstrap.Admin/Extensions/JSRuntimeExtensions.cs +++ b/src/admin/Bootstrap.Admin/Extensions/JSRuntimeExtensions.cs @@ -33,16 +33,6 @@ namespace Bootstrap.Admin.Extensions /// public static async ValueTask MoveNextTabAsync(this IJSRuntime? jSRuntime) => jSRuntime == null ? "" : await jSRuntime.InvokeAsync("$.moveNextTab"); - /// - /// - /// - /// - /// - public static void ActivePage(this IJSRuntime? jsRuntime, string? pageId) - { - if (!string.IsNullOrEmpty(pageId) && jsRuntime != null) jsRuntime.InvokeVoidAsync("$.activePage", pageId); - } - /// /// 移除指定 ID 的导航条 /// @@ -52,16 +42,9 @@ namespace Bootstrap.Admin.Extensions public static async ValueTask RemoveTabAsync(this IJSRuntime? jSRuntime, string? tabId) => string.IsNullOrEmpty(tabId) || jSRuntime == null ? "" : await jSRuntime.InvokeAsync("$.removeTab", tabId); /// - /// + /// 启用动画 /// /// public static void EnableAnimation(this IJSRuntime? jSRuntime) => jSRuntime.InvokeVoidAsync("$.enableAnimation"); - - /// - /// - /// - /// - /// - public static void EnableBackground(this IJSRuntime? jSRuntime, bool val) => jSRuntime.InvokeVoidAsync("$.enableBackground", val); } } diff --git a/src/admin/Bootstrap.Admin/Pages/Admin/Profiles.razor b/src/admin/Bootstrap.Admin/Pages/Admin/Profiles.razor index c936ddd6..99df8650 100644 --- a/src/admin/Bootstrap.Admin/Pages/Admin/Profiles.razor +++ b/src/admin/Bootstrap.Admin/Pages/Admin/Profiles.razor @@ -39,17 +39,17 @@
- +
- +
- +
diff --git a/src/admin/Bootstrap.Admin/Shared/AdminLayout.razor b/src/admin/Bootstrap.Admin/Shared/AdminLayout.razor index 6f41a384..8b7e3939 100644 --- a/src/admin/Bootstrap.Admin/Shared/AdminLayout.razor +++ b/src/admin/Bootstrap.Admin/Shared/AdminLayout.razor @@ -4,6 +4,5 @@
-
diff --git a/src/admin/Bootstrap.Admin/Shared/NavItem.razor b/src/admin/Bootstrap.Admin/Shared/NavItem.razor index 2ee4e579..3ef22a38 100644 --- a/src/admin/Bootstrap.Admin/Shared/NavItem.razor +++ b/src/admin/Bootstrap.Admin/Shared/NavItem.razor @@ -3,7 +3,7 @@ @if (Menu.Menus.Any()) {
  • - -
  • +
    + @Title +
    diff --git a/src/admin/Bootstrap.Admin/Shared/TabSet.razor b/src/admin/Bootstrap.Admin/Shared/TabSet.razor index a868db32..3a2f5513 100644 --- a/src/admin/Bootstrap.Admin/Shared/TabSet.razor +++ b/src/admin/Bootstrap.Admin/Shared/TabSet.razor @@ -1,19 +1,30 @@ @inherits TabSetBase -