!102 perf(#I50WR9): 优化 NavigationTree 逻辑提高性能

* refactor: 增加内置滚动条样式
* refactor: 优化 NavigationTree 性能
This commit is contained in:
Argo 2022-04-02 12:49:54 +00:00
parent c516a0064d
commit 89b9bf7e3a
6 changed files with 110 additions and 14 deletions

View File

@ -1,6 +1,13 @@
@inherits AssignmentBase<Navigation>
@inherits ComponentBase
<Tree Items="InternalItems" ShowCheckbox="true" ShowIcon="true" OnTreeItemChecked="@OnTreeItemChecked" />
<div class="tree-menu">
<Tree Items="InternalItems" ShowCheckbox="true" ShowIcon="true" @ref="MenusTree" />
<div class="form-footer">
<Button Color="Color.Secondary" Icon="fa fa-times" Text="关闭" OnClickWithoutRender="OnClickClose" />
<Button Color="Color.Primary" Icon="fa fa-save" Text="保存" OnClickWithoutRender="OnClickSave" />
</div>
</div>
@code {
RenderFragment<Navigation> RenderTreeItem => item =>

View File

@ -2,6 +2,7 @@
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone
using BootstrapAdmin.DataAccess.Models;
using BootstrapAdmin.Web.Core;
using BootstrapAdmin.Web.Extensions;
@ -15,10 +16,45 @@ public partial class NavigationTree
[NotNull]
private List<TreeItem>? InternalItems { get; set; }
[NotNull]
private Tree? MenusTree { get; set; }
[Inject]
[NotNull]
private IDict? DictService { get; set; }
/// <summary>
///
/// </summary>
[Parameter]
[EditorRequired]
[NotNull]
public List<Navigation>? Items { get; set; }
/// <summary>
///
/// </summary>
[Parameter]
[EditorRequired]
[NotNull]
public List<string>? Value { get; set; }
/// <summary>
/// 关闭弹窗回调委托
/// </summary>
[Parameter]
[EditorRequired]
[NotNull]
public Func<Task>? OnClose { get; set; }
/// <summary>
/// 保存按钮回调委托
/// </summary>
[Parameter]
[EditorRequired]
[NotNull]
public Func<List<string?>, Task>? OnSave { get; set; }
/// <summary>
///
/// </summary>
@ -29,12 +65,9 @@ public partial class NavigationTree
InternalItems = Items.ToTreeItemList(Value, RenderTreeItem);
}
private Task OnTreeItemChecked(List<TreeItem> items)
{
Value = items.Select(i => i.Key!.ToString()!).ToList();
OnValueChanged(Value);
return Task.CompletedTask;
}
private string GetApp(string? app) => DictService.GetApps().FirstOrDefault(i => i.Key == app).Value ?? "未设置";
private Task OnClickClose() => OnClose();
private Task OnClickSave() => OnSave(MenusTree.GetCheckedItems().Select(i => i.Key?.ToString()).ToList());
}

View File

@ -0,0 +1,13 @@
.tree-menu {
display: flex;
flex-direction: column;
}
.tree-menu ::deep .tree {
flex: 1;
margin: -1rem;
padding: 1rem;
max-height: calc(100vh - 173px);
overflow-y: auto;
overflow-x: hidden;
}

View File

@ -18,9 +18,48 @@ public static class DialogExtensions
public static Task ShowAssignmentDialog(this DialogService dialogService, string title, List<SelectedItem> items, List<string> value, Func<Task<bool>> saveCallback, ToastService? toast) => dialogService.ShowDialog<Assignment, SelectedItem>(title, items, value, saveCallback, toast);
/// <summary>
///
/// 弹出菜单分配弹窗
/// </summary>
public static Task ShowNavigationDialog(this DialogService dialogService, string title, List<Navigation> items, List<string> value, Func<Task<bool>> saveCallback, ToastService? toast) => dialogService.ShowDialog<NavigationTree, Navigation>(title, items, value, saveCallback, toast);
/// <param name="dialogService"></param>
/// <param name="title">弹窗标题</param>
/// <param name="menus">当前用户可用所有菜单集合</param>
/// <param name="value">已分配菜单集合</param>
/// <param name="saveCallback"></param>
/// <param name="toast"></param>
/// <returns></returns>
public static async Task ShowNavigationDialog(this DialogService dialogService, string title, List<Navigation> menus, List<string> value, Func<List<string>, Task<bool>> saveCallback, ToastService? toast)
{
var option = new DialogOption
{
Title = title,
ShowFooter = false,
IsScrolling = true,
Class = "modal-dialog-menu"
};
var parameters = new Dictionary<string, object?>()
{
[nameof(NavigationTree.Items)] = menus,
[nameof(NavigationTree.Value)] = value,
[nameof(NavigationTree.OnClose)] = () => option.Dialog.Close(),
[nameof(NavigationTree.OnSave)] = new Func<List<string>, Task>(async items =>
{
var ret = await saveCallback(items);
if (toast != null)
{
if (ret)
{
await toast.Success("分配操作", "操作成功!");
}
else
{
await toast.Error("分配操作", "操作失败,请联系相关管理员!");
}
}
})
};
option.Component = BootstrapDynamicComponent.CreateComponent<NavigationTree>(parameters);
await dialogService.Show(option);
}
private static Task ShowDialog<TBody, TItem>(this DialogService dialogService, string title, List<TItem> items, List<string> value, Func<Task<bool>> saveCallback, ToastService? toast) where TBody : AssignmentBase<TItem> => dialogService.ShowSaveDialog<TBody>(title, async () =>
{

View File

@ -72,12 +72,12 @@ public partial class Roles
private async Task OnAssignmentMenus(Role role)
{
var apps = NavigationService.GetAllMenus(AppContext.UserName);
var menus = NavigationService.GetAllMenus(AppContext.UserName);
var values = NavigationService.GetMenusByRoleId(role.Id);
await DialogService.ShowNavigationDialog($"分配菜单 - 当前角色: {role.RoleName}", apps, values, () =>
await DialogService.ShowNavigationDialog($"分配菜单 - 当前角色: {role.RoleName}", menus, values, items =>
{
var ret = NavigationService.SaveMenusByRoleId(role.Id, values);
var ret = NavigationService.SaveMenusByRoleId(role.Id, items);
return Task.FromResult(ret);
}, ToastService);
}

View File

@ -127,3 +127,7 @@
.layout-menu {
border-right: 1px solid #ddd;
}
.modal-dialog-menu.modal-dialog-scrollable .modal-body {
overflow: hidden;
}