!102 perf(#I50WR9): 优化 NavigationTree 逻辑提高性能
* refactor: 增加内置滚动条样式 * refactor: 优化 NavigationTree 性能
This commit is contained in:
parent
c516a0064d
commit
89b9bf7e3a
|
@ -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 {
|
@code {
|
||||||
RenderFragment<Navigation> RenderTreeItem => item =>
|
RenderFragment<Navigation> RenderTreeItem => item =>
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
|
||||||
// Website: https://admin.blazor.zone
|
// Website: https://admin.blazor.zone
|
||||||
|
|
||||||
|
using BootstrapAdmin.DataAccess.Models;
|
||||||
using BootstrapAdmin.Web.Core;
|
using BootstrapAdmin.Web.Core;
|
||||||
using BootstrapAdmin.Web.Extensions;
|
using BootstrapAdmin.Web.Extensions;
|
||||||
|
|
||||||
|
@ -15,10 +16,45 @@ public partial class NavigationTree
|
||||||
[NotNull]
|
[NotNull]
|
||||||
private List<TreeItem>? InternalItems { get; set; }
|
private List<TreeItem>? InternalItems { get; set; }
|
||||||
|
|
||||||
|
[NotNull]
|
||||||
|
private Tree? MenusTree { get; set; }
|
||||||
|
|
||||||
[Inject]
|
[Inject]
|
||||||
[NotNull]
|
[NotNull]
|
||||||
private IDict? DictService { get; set; }
|
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>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -29,12 +65,9 @@ public partial class NavigationTree
|
||||||
InternalItems = Items.ToTreeItemList(Value, RenderTreeItem);
|
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 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());
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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);
|
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>
|
||||||
///
|
/// 弹出菜单分配弹窗
|
||||||
/// </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 () =>
|
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 () =>
|
||||||
{
|
{
|
||||||
|
|
|
@ -72,12 +72,12 @@ public partial class Roles
|
||||||
|
|
||||||
private async Task OnAssignmentMenus(Role role)
|
private async Task OnAssignmentMenus(Role role)
|
||||||
{
|
{
|
||||||
var apps = NavigationService.GetAllMenus(AppContext.UserName);
|
var menus = NavigationService.GetAllMenus(AppContext.UserName);
|
||||||
var values = NavigationService.GetMenusByRoleId(role.Id);
|
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);
|
return Task.FromResult(ret);
|
||||||
}, ToastService);
|
}, ToastService);
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,3 +127,7 @@
|
||||||
.layout-menu {
|
.layout-menu {
|
||||||
border-right: 1px solid #ddd;
|
border-right: 1px solid #ddd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.modal-dialog-menu.modal-dialog-scrollable .modal-body {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue