feat: 完善菜单维护父级菜单功能
This commit is contained in:
parent
1f2a169cc7
commit
32d74ea81a
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="BootstrapBlazor" Version="6.2.9-beta07" />
|
<PackageReference Include="BootstrapBlazor" Version="6.3.4-beta03" />
|
||||||
<PackageReference Include="Longbow.Security.Cryptography" Version="5.2.0" />
|
<PackageReference Include="Longbow.Security.Cryptography" Version="5.2.0" />
|
||||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="6.0.1" />
|
<PackageReference Include="Microsoft.Data.Sqlite" Version="6.0.1" />
|
||||||
<PackageReference Include="PetaPoco.Extensions" Version="6.0.0" />
|
<PackageReference Include="PetaPoco.Extensions" Version="6.0.0" />
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
<div class="row g-3 form-inline">
|
||||||
|
<div class="col-12 col-sm-6 col-md-6">
|
||||||
|
<BootstrapInput @bind-Value="Value.Name" DisplayText="菜单名称" ShowLabel="true"></BootstrapInput>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-sm-6 col-md-6">
|
||||||
|
<MenuTree @bind-Value="Value.ParentId" Lookup="@ParementMenus" DisplayText="父级菜单"></MenuTree>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-sm-6 col-md-6">
|
||||||
|
<BootstrapInput @bind-Value="Value.Order"></BootstrapInput>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-sm-6 col-md-6">
|
||||||
|
<BootstrapInput @bind-Value="Value.Icon"></BootstrapInput>
|
||||||
|
</div>
|
||||||
|
<div class="col-12">
|
||||||
|
<BootstrapInput @bind-Value="Value.Url"></BootstrapInput>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-sm-6 col-md-6">
|
||||||
|
<Select @bind-Value="Value.Category"></Select>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-sm-6 col-md-6">
|
||||||
|
<Select Items="@Targets" @bind-Value="Value.Target"></Select>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-sm-6 col-md-6">
|
||||||
|
<Select @bind-Value="Value.IsResource"></Select>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-sm-6 col-md-6">
|
||||||
|
<Select Items="@Apps" @bind-Value="Value.Application"></Select>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -0,0 +1,42 @@
|
||||||
|
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
namespace BootstrapAdmin.Web.Components;
|
||||||
|
|
||||||
|
public partial class MenuEditor
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
[EditorRequired]
|
||||||
|
[NotNull]
|
||||||
|
public Navigation? Value { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
[EditorRequired]
|
||||||
|
[NotNull]
|
||||||
|
public List<SelectedItem>? ParementMenus { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
[EditorRequired]
|
||||||
|
[NotNull]
|
||||||
|
public List<SelectedItem>? Targets { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
[EditorRequired]
|
||||||
|
[NotNull]
|
||||||
|
public List<SelectedItem>? Apps { get; set; }
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
<div class="tree-dialog">
|
||||||
|
<label class="form-label">@DisplayText</label>
|
||||||
|
<BootstrapInputGroup>
|
||||||
|
<Display Value="Value" Lookup="Lookup" ShowLabel="false"></Display>
|
||||||
|
<Button Icon="fa fa-times" Color="Color.Secondary" OnClick="OnClearText"></Button>
|
||||||
|
<Button Icon="fa fa-bars" OnClick="OnSelectMenu"></Button>
|
||||||
|
</BootstrapInputGroup>
|
||||||
|
</div>
|
|
@ -0,0 +1,87 @@
|
||||||
|
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||||
|
// 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.Web.Core;
|
||||||
|
using BootstrapAdmin.Web.Services;
|
||||||
|
using Microsoft.AspNetCore.Components.Web;
|
||||||
|
|
||||||
|
namespace BootstrapAdmin.Web.Components;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public partial class MenuTree
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
[NotNull]
|
||||||
|
public List<SelectedItem>? Lookup { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
[NotNull]
|
||||||
|
public string? DisplayText { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
[NotNull]
|
||||||
|
public string? Value { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
[NotNull]
|
||||||
|
public EventCallback<string> ValueChanged { get; set; }
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
[NotNull]
|
||||||
|
private DialogService? DialogService { get; set; }
|
||||||
|
|
||||||
|
private DialogOption? Option { get; set; }
|
||||||
|
|
||||||
|
private async Task OnSelectMenu()
|
||||||
|
{
|
||||||
|
Option = new DialogOption()
|
||||||
|
{
|
||||||
|
IsScrolling = true,
|
||||||
|
Title = "选择菜单",
|
||||||
|
BodyTemplate = BootstrapDynamicComponent.CreateComponent<ParentMenuTree>(new Dictionary<string, object?>
|
||||||
|
{
|
||||||
|
[nameof(ParentMenuTree.Value)] = Value,
|
||||||
|
[nameof(ParentMenuTree.ValueChanged)] = EventCallback.Factory.Create<string>(this, v => OnValueChanged(v))
|
||||||
|
}).Render(),
|
||||||
|
FooterTemplate = BootstrapDynamicComponent.CreateComponent<Button>(new Dictionary<string, object?>
|
||||||
|
{
|
||||||
|
[nameof(Button.Color)] = Color.Primary,
|
||||||
|
[nameof(Button.Text)] = "确认",
|
||||||
|
[nameof(Button.OnClick)] = EventCallback.Factory.Create<MouseEventArgs>(this, () =>
|
||||||
|
{
|
||||||
|
Option?.Dialog.Close();
|
||||||
|
}),
|
||||||
|
}).Render()
|
||||||
|
};
|
||||||
|
await DialogService.Show(Option);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task OnClearText() => OnValueChanged("0");
|
||||||
|
|
||||||
|
private async Task OnValueChanged(string v)
|
||||||
|
{
|
||||||
|
if (Value != v)
|
||||||
|
{
|
||||||
|
Value = v;
|
||||||
|
if (ValueChanged.HasDelegate)
|
||||||
|
{
|
||||||
|
await ValueChanged.InvokeAsync(Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
.tree-dialog {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-dialog ::deep .input-group {
|
||||||
|
flex-wrap: nowrap !important
|
||||||
|
}
|
|
@ -5,4 +5,4 @@
|
||||||
@code {
|
@code {
|
||||||
RenderFragment<Navigation> RenderTreeItem => item =>
|
RenderFragment<Navigation> RenderTreeItem => item =>
|
||||||
@<div class="d-flex flex-fill"><span class="flex-fill">@item.Name</span><span class="mx-3">@item.Order</span><span class="app-type">@item.IsResource.ToDescriptionString()</span><span class="app-text">@GetApp(item.Application)</span></div>;
|
@<div class="d-flex flex-fill"><span class="flex-fill">@item.Name</span><span class="mx-3">@item.Order</span><span class="app-type">@item.IsResource.ToDescriptionString()</span><span class="app-text">@GetApp(item.Application)</span></div>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
<Tree Items="InternalItems" ShowRadio="true" ShowIcon="true" OnTreeItemChecked="@OnTreeItemChecked" />
|
||||||
|
|
||||||
|
@code {
|
||||||
|
RenderFragment<Navigation> RenderTreeItem => item =>
|
||||||
|
@<div class="d-flex flex-fill"><span class="flex-fill">@item.Name</span><span class="mx-3">@item.Order</span><span class="app-type">@item.IsResource.ToDescriptionString()</span><span class="app-text">@GetApp(item.Application)</span></div>;
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||||
|
// 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.Web.Core;
|
||||||
|
using BootstrapAdmin.Web.Extensions;
|
||||||
|
using BootstrapAdmin.Web.Services;
|
||||||
|
|
||||||
|
namespace BootstrapAdmin.Web.Components;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public partial class ParentMenuTree
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
[EditorRequired]
|
||||||
|
[NotNull]
|
||||||
|
public string? Value { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
[Parameter]
|
||||||
|
public EventCallback<string> ValueChanged { get; set; }
|
||||||
|
|
||||||
|
[NotNull]
|
||||||
|
private List<TreeItem>? InternalItems { get; set; }
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
[NotNull]
|
||||||
|
private INavigation? NavigationService { get; set; }
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
[NotNull]
|
||||||
|
private IDict? DictService { get; set; }
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
[NotNull]
|
||||||
|
private BootstrapAppContext? Context { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
protected override void OnInitialized()
|
||||||
|
{
|
||||||
|
base.OnInitialized();
|
||||||
|
|
||||||
|
var items = NavigationService.GetAllMenus(Context.UserName);
|
||||||
|
InternalItems = items.ToTreeItemList(new List<string> { Value }, RenderTreeItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task OnTreeItemChecked(List<TreeItem> items)
|
||||||
|
{
|
||||||
|
Value = items.First().Key?.ToString();
|
||||||
|
if (ValueChanged.HasDelegate)
|
||||||
|
{
|
||||||
|
await ValueChanged.InvokeAsync(Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetApp(string? app) => DictService.GetApps().FirstOrDefault(i => i.Key == app).Value ?? "未设置";
|
||||||
|
}
|
|
@ -23,35 +23,7 @@
|
||||||
<TableColumn @bind-Field="@context.Application" Filterable="true" Lookup="Apps"></TableColumn>
|
<TableColumn @bind-Field="@context.Application" Filterable="true" Lookup="Apps"></TableColumn>
|
||||||
</TableColumns>
|
</TableColumns>
|
||||||
<EditTemplate Context="v">
|
<EditTemplate Context="v">
|
||||||
<div class="row g-3 form-inline">
|
<MenuEditor Value="v" ParementMenus="ParementMenus" Targets="Targets" Apps="Apps" />
|
||||||
<div class="col-12 col-sm-6 col-md-6">
|
|
||||||
<BootstrapInput @bind-Value="v.Name" DisplayText="菜单名称" ShowLabel="true"></BootstrapInput>
|
|
||||||
</div>
|
|
||||||
<div class="col-12 col-sm-6 col-md-6">
|
|
||||||
<Select @bind-Value="v.ParentId" Items="@ParementMenus" IsDisabled="@(v.ParentId == "0")" DisplayText="父级菜单" ShowLabel="true"></Select>
|
|
||||||
</div>
|
|
||||||
<div class="col-12 col-sm-6 col-md-6">
|
|
||||||
<BootstrapInput @bind-Value="v.Order"></BootstrapInput>
|
|
||||||
</div>
|
|
||||||
<div class="col-12 col-sm-6 col-md-6">
|
|
||||||
<BootstrapInput @bind-Value="v.Icon"></BootstrapInput>
|
|
||||||
</div>
|
|
||||||
<div class="col-12">
|
|
||||||
<BootstrapInput @bind-Value="v.Url"></BootstrapInput>
|
|
||||||
</div>
|
|
||||||
<div class="col-12 col-sm-6 col-md-6">
|
|
||||||
<Select @bind-Value="v.Category"></Select>
|
|
||||||
</div>
|
|
||||||
<div class="col-12 col-sm-6 col-md-6">
|
|
||||||
<Select Items="@Targets" @bind-Value="v.Target"></Select>
|
|
||||||
</div>
|
|
||||||
<div class="col-12 col-sm-6 col-md-6">
|
|
||||||
<Select @bind-Value="v.IsResource"></Select>
|
|
||||||
</div>
|
|
||||||
<div class="col-12 col-sm-6 col-md-6">
|
|
||||||
<Select Items="@Apps" @bind-Value="v.Application"></Select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</EditTemplate>
|
</EditTemplate>
|
||||||
<RowButtonTemplate>
|
<RowButtonTemplate>
|
||||||
<TableCellButton Size="Size.ExtraSmall" IsShow="@AuthorizeButton("assignRole")" Color="Color.Info" Icon="fa fa-sitemap" Text="分配角色" OnClick="() => OnAssignmentRoles(context)" />
|
<TableCellButton Size="Size.ExtraSmall" IsShow="@AuthorizeButton("assignRole")" Color="Color.Info" Icon="fa fa-sitemap" Text="分配角色" OnClick="() => OnAssignmentRoles(context)" />
|
||||||
|
|
|
@ -44,5 +44,5 @@ class AdminTaskService : BackgroundService
|
||||||
|
|
||||||
// 真实任务负责周期性设置健康检查结果开关为开启
|
// 真实任务负责周期性设置健康检查结果开关为开启
|
||||||
TaskServicesManager.GetOrAdd("健康检查", token => Task.FromResult(DictService.SaveHealthCheck()), TriggerBuilder.Build(Cron.Minutely(10)));
|
TaskServicesManager.GetOrAdd("健康检查", token => Task.FromResult(DictService.SaveHealthCheck()), TriggerBuilder.Build(Cron.Minutely(10)));
|
||||||
});
|
}, stoppingToken);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,4 +13,4 @@
|
||||||
|
|
||||||
@using BootstrapAdmin.Web.Components
|
@using BootstrapAdmin.Web.Components
|
||||||
@using BootstrapAdmin.Web.Models
|
@using BootstrapAdmin.Web.Models
|
||||||
@using BootstrapAdmin.Web.Shared
|
@using BootstrapAdmin.Web.Shared
|
||||||
|
|
Loading…
Reference in New Issue