feat: 菜单维护页面增加对角色授权功能

This commit is contained in:
Argo Zhang 2020-02-05 17:46:28 +08:00
parent 928afdf0d5
commit 7ea6d0a4e1
No known key found for this signature in database
GPG Key ID: 152E398953DDF19F
11 changed files with 241 additions and 32 deletions

View File

@ -0,0 +1,114 @@
using Bootstrap.Admin.Pages.Shared;
using Microsoft.AspNetCore.Components;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Bootstrap.Admin.Pages.Components
{
/// <summary>
/// 模态框组件类
/// </summary>
public class AssignModalBase<TItem> : ComponentBase
{
#nullable disable
/// <summary>
/// 获得/设置 数据绑定项
/// </summary>
[Parameter]
public TItem Item { get; set; }
#nullable restore
/// <summary>
/// 获得/设置 Modal 实例
/// </summary>
[Parameter]
public ModalBase? Modal { get; set; }
/// <summary>
/// 获得/设置 Id
/// </summary>
[Parameter]
public string Id { get; set; } = "";
/// <summary>
/// 获得/设置 弹窗标题
/// </summary>
[Parameter]
public string Title { get; set; } = "未设置";
/// <summary>
/// 获得/设置 表格 Toolbar 按钮模板
/// </summary>
[Parameter]
public RenderFragment<TItem>? ItemTemplate { get; set; }
/// <summary>
/// 获得/设置 Items
/// </summary>
public IEnumerable<TItem> Items { get; set; } = new TItem[0];
/// <summary>
/// Toast 组件实例
/// </summary>
protected Toast? Toast { get; set; }
/// <summary>
/// 显示提示信息
/// </summary>
/// <param name="title"></param>
/// <param name="text"></param>
/// <param name="cate"></param>
protected void ShowMessage(string title, string text, ToastCategory cate = ToastCategory.Success) => Toast?.ShowMessage(title, text, cate);
/// <summary>
/// 获得/设置 保存回调事件
/// </summary>
[Parameter]
public Func<IEnumerable<TItem>, bool>? OnSave { get; set; }
/// <summary>
/// OnAfterRender 方法
/// </summary>
/// <param name="firstRender"></param>
protected override void OnAfterRender(bool firstRender)
{
if (show)
{
show = false;
Modal?.Toggle();
}
}
/// <summary>
/// SetParametersAsync 方法
/// </summary>
public override Task SetParametersAsync(ParameterView parameters)
{
parameters.SetParameterProperties(this);
if (string.IsNullOrEmpty(Id)) throw new InvalidOperationException("Modal Component Id property must be set");
return base.SetParametersAsync(ParameterView.Empty);
}
/// <summary>
/// Save 方法
/// </summary>
protected void Save()
{
bool ret = OnSave?.Invoke(Items) ?? false;
Modal?.Toggle();
ShowMessage(Title, ret ? "保存成功" : "保存失败", ret ? ToastCategory.Success : ToastCategory.Error);
}
private bool show;
/// <summary>
/// Update 方法
/// </summary>
public void Update(IEnumerable<TItem> items)
{
Items = items;
show = true;
StateHasChanged();
}
}
}

View File

@ -32,31 +32,31 @@ namespace Bootstrap.Admin.Pages.Components
/// 勾选回调方法 /// 勾选回调方法
/// </summary> /// </summary>
[Parameter] [Parameter]
public Action<TItem, bool> ToggleCallback { get; set; } = new Action<TItem, bool>((v, c) => { }); public Action<TItem, bool>? OnClick { get; set; }
/// <summary> /// <summary>
/// /// 组件状态改变回调方法
/// </summary> /// </summary>
[Parameter] [Parameter]
public Func<TItem, CheckBoxState> SetCheckCallback { get; set; } = new Func<TItem, CheckBoxState>(item => CheckBoxState.UnChecked); public Func<TItem, CheckBoxState>? SetCheckCallback { get; set; }
/// <summary> /// <summary>
/// /// OnParametersSet 方法
/// </summary> /// </summary>
protected override void OnParametersSet() protected override void OnParametersSet()
{ {
State = SetCheckCallback(Item); State = SetCheckCallback?.Invoke(Item) ?? CheckBoxState.UnChecked;
Checked = State == CheckBoxState.Checked; Checked = State == CheckBoxState.Checked;
} }
/// <summary> /// <summary>
/// /// 获得/设置 选择框状态
/// </summary> /// </summary>
[Parameter] [Parameter]
public CheckBoxState State { get; set; } public CheckBoxState State { get; set; }
/// <summary> /// <summary>
/// /// RenderStateCss 方法
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
protected string RenderStateCss() protected string RenderStateCss()
@ -75,5 +75,15 @@ namespace Bootstrap.Admin.Pages.Components
} }
return ret; return ret;
} }
/// <summary>
/// 点击选择框方法
/// </summary>
protected void ToggleClick()
{
Checked = !Checked;
State = Checked ? CheckBoxState.Checked : CheckBoxState.UnChecked;
OnClick?.Invoke(Item, Checked);
}
} }
} }

View File

@ -160,6 +160,11 @@ namespace Bootstrap.Admin.Pages.Components
} }
} }
/// <summary>
/// 获得 Table 组件选择项目集合
/// </summary>
public IEnumerable<TItem> SelectedItems { get { return Table?.SelectedItems ?? new List<TItem>(); } }
/// <summary> /// <summary>
/// 分页查询方法 /// 分页查询方法
/// </summary> /// </summary>

View File

@ -1,7 +1,7 @@
using Bootstrap.Admin.Pages.Extensions; using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop; using Microsoft.JSInterop;
using System; using System;
using System.Threading.Tasks;
namespace Bootstrap.Admin.Pages.Components namespace Bootstrap.Admin.Pages.Components
{ {
@ -11,13 +11,13 @@ namespace Bootstrap.Admin.Pages.Components
public class ModalBase : ComponentBase public class ModalBase : ComponentBase
{ {
/// <summary> /// <summary>
/// /// 获得/设置 IJSRuntime 实例
/// </summary> /// </summary>
[Inject] [Inject]
protected IJSRuntime? JSRuntime { get; set; } protected IJSRuntime? JSRuntime { get; set; }
/// <summary> /// <summary>
/// /// 获得/设置 ModalBody 代码块
/// </summary> /// </summary>
[Parameter] [Parameter]
public RenderFragment? ModalBody { get; set; } public RenderFragment? ModalBody { get; set; }
@ -29,13 +29,13 @@ namespace Bootstrap.Admin.Pages.Components
public RenderFragment? ModalFooter { get; set; } public RenderFragment? ModalFooter { get; set; }
/// <summary> /// <summary>
/// /// 获得/设置 Id
/// </summary> /// </summary>
[Parameter] [Parameter]
public string Id { get; set; } = ""; public string Id { get; set; } = "";
/// <summary> /// <summary>
/// /// 获得/设置 弹窗标题
/// </summary> /// </summary>
[Parameter] [Parameter]
public string Title { get; set; } = "未设置"; public string Title { get; set; } = "未设置";
@ -65,7 +65,7 @@ namespace Bootstrap.Admin.Pages.Components
public bool ShowFooter { get; set; } = true; public bool ShowFooter { get; set; } = true;
/// <summary> /// <summary>
/// /// OnAfterRender 方法
/// </summary> /// </summary>
/// <param name="firstRender"></param> /// <param name="firstRender"></param>
protected override void OnAfterRender(bool firstRender) protected override void OnAfterRender(bool firstRender)
@ -111,7 +111,7 @@ namespace Bootstrap.Admin.Pages.Components
} }
/// <summary> /// <summary>
/// /// Toggle 弹窗方法
/// </summary> /// </summary>
public void Toggle() public void Toggle()
{ {
@ -125,19 +125,19 @@ namespace Bootstrap.Admin.Pages.Components
public enum ModalSize public enum ModalSize
{ {
/// <summary> /// <summary>
/// /// 默认大小
/// </summary> /// </summary>
Default, Default,
/// <summary> /// <summary>
/// /// 小窗口
/// </summary> /// </summary>
Small, Small,
/// <summary> /// <summary>
/// /// 大窗口
/// </summary> /// </summary>
Large, Large,
/// <summary> /// <summary>
/// /// 超大窗口
/// </summary> /// </summary>
ExtraLarge, ExtraLarge,
} }

View File

@ -0,0 +1,29 @@
@typeparam TItem
@inherits AssignModalBase<TItem>
<Modal @ref="Modal" Id="@Id" Title="@Title" Size="ModalSize.Large">
<ModalBody>
<form class="form-inline">
<div class="row">
@foreach(var item in Items)
{
<div class="form-group col-md-3 col-sm-4 col-6">
@ItemTemplate?.Invoke(item)
</div>
}
</div>
</form>
</ModalBody>
<ModalFooter>
<button type="button" class="btn btn-secondary" data-dismiss="modal">
<i class="fa fa-times"></i>
<span>关闭</span>
</button>
<button type="button" class="btn btn-primary" @onclick="Save">
<i class="fa fa-save"></i>
<span>保存</span>
</button>
</ModalFooter>
</Modal>
<Toast @ref="Toast" Id="@($"{Id}_toast")"></Toast>

View File

@ -1,7 +1,7 @@
@typeparam TItem @typeparam TItem
@inherits CheckboxBase<TItem> @inherits CheckboxBase<TItem>
<label role="checkbox" aria-checked="@State.ToCss()" class="@RenderStateCss()" @onclick="e => ToggleCallback(Item, !Checked)"> <label role="checkbox" aria-checked="@State.ToCss()" class="@RenderStateCss()" @onclick="ToggleClick">
<span class="checkbox-input"> <span class="checkbox-input">
<span class="checkbox-inner"></span> <span class="checkbox-inner"></span>
</span> </span>

View File

@ -21,7 +21,3 @@
</div> </div>
</div> </div>
</div> </div>
@code {
}

View File

@ -54,7 +54,7 @@
<tr> <tr>
@if (ShowCheckbox) @if (ShowCheckbox)
{ {
<th class="table-col-checkbox"><Checkbox TItem="TItem" SetCheckCallback="CheckState" ToggleCallback="ToggleCheck"></Checkbox></th> <th class="table-col-checkbox"><Checkbox TItem="TItem" SetCheckCallback="CheckState" OnClick="ToggleCheck"></Checkbox></th>
} }
@if (ShowLineNo) @if (ShowLineNo)
{ {
@ -77,7 +77,7 @@
<tr> <tr>
@if (ShowCheckbox) @if (ShowCheckbox)
{ {
<th class="table-col-checkbox"><Checkbox TItem="TItem" SetCheckCallback="CheckState" ToggleCallback="ToggleCheck"></Checkbox></th> <th class="table-col-checkbox"><Checkbox TItem="TItem" SetCheckCallback="CheckState" OnClick="ToggleCheck"></Checkbox></th>
} }
@if (ShowLineNo) @if (ShowLineNo)
{ {
@ -98,7 +98,7 @@
<tr> <tr>
@if (ShowCheckbox) @if (ShowCheckbox)
{ {
<td class="table-col-checkbox"><Checkbox TItem="TItem" Item="Items.ElementAt(index)" SetCheckCallback="item => SelectedItems.Contains(item) ? CheckBoxState.Checked : CheckBoxState.UnChecked" ToggleCallback="ToggleCheck"></Checkbox></td> <td class="table-col-checkbox"><Checkbox TItem="TItem" Item="Items.ElementAt(index)" SetCheckCallback="item => SelectedItems.Contains(item) ? CheckBoxState.Checked : CheckBoxState.UnChecked" OnClick="ToggleCheck"></Checkbox></td>
} }
@if (ShowLineNo) @if (ShowLineNo)
{ {
@ -125,7 +125,7 @@
<tr> <tr>
@if (ShowCheckbox) @if (ShowCheckbox)
{ {
<th class="table-col-checkbox"><Checkbox TItem="TItem" SetCheckCallback="CheckState" ToggleCallback="ToggleCheck"></Checkbox></th> <th class="table-col-checkbox"><Checkbox TItem="TItem" SetCheckCallback="CheckState" OnClick="ToggleCheck"></Checkbox></th>
} }
@if (ShowLineNo) @if (ShowLineNo)
{ {
@ -146,7 +146,7 @@
<tr> <tr>
@if (ShowCheckbox) @if (ShowCheckbox)
{ {
<td class="table-col-checkbox"><Checkbox TItem="TItem" Item="Items.ElementAt(index)" SetCheckCallback="item => SelectedItems.Contains(item) ? CheckBoxState.Checked : CheckBoxState.UnChecked" ToggleCallback="ToggleCheck"></Checkbox></td> <td class="table-col-checkbox"><Checkbox TItem="TItem" Item="Items.ElementAt(index)" SetCheckCallback="item => SelectedItems.Contains(item) ? CheckBoxState.Checked : CheckBoxState.UnChecked" OnClick="ToggleCheck"></Checkbox></td>
} }
@if (ShowLineNo) @if (ShowLineNo)
{ {

View File

@ -1,6 +1,6 @@
@inherits MenusBase @inherits MenusBase
<EditPage Id="menu" FixedHeader="@FixedHeader" TItem="Bootstrap.Security.BootstrapMenu" SubmitModalTitle="菜单编辑窗口" QueryModel="QueryModel" OnQuery="Query" OnAdd="Add" OnDelete="Delete" OnSave="Save" OnResetSearch="ResetSearch"> <EditPage @ref="EditPage" Id="menu" FixedHeader="@FixedHeader" TItem="Bootstrap.Security.BootstrapMenu" SubmitModalTitle="菜单编辑窗口" QueryModel="QueryModel" OnQuery="Query" OnAdd="Add" OnDelete="Delete" OnSave="Save" OnResetSearch="ResetSearch">
<QueryBody> <QueryBody>
<LgbInputText ColumnClass="col-sm-auto" @bind-Value="@context.Name" maxlength="50" /> <LgbInputText ColumnClass="col-sm-auto" @bind-Value="@context.Name" maxlength="50" />
<LgbInputText ColumnClass="col-sm-auto" @bind-Value="@context.ParentName" maxlength="50" /> <LgbInputText ColumnClass="col-sm-auto" @bind-Value="@context.ParentName" maxlength="50" />
@ -54,3 +54,9 @@
</div> </div>
</EditTemplate> </EditTemplate>
</EditPage> </EditPage>
<AssignModal @ref="AssignRoleModal" TItem="Bootstrap.DataAccess.Role" Id="menu-role" Title="角色授权窗口" OnSave="SaveRoles">
<ItemTemplate>
<Checkbox TItem="Bootstrap.DataAccess.Role" Item="@context" Text="@context.RoleName" SetCheckCallback="SetCheck" OnClick="OnClick" />
</ItemTemplate>
</AssignModal>

View File

@ -20,6 +20,11 @@ namespace Bootstrap.Admin.Pages.Views.Admin.Components
[Inject] [Inject]
protected AuthenticationStateProvider? AuthenticationStateProvider { get; set; } protected AuthenticationStateProvider? AuthenticationStateProvider { get; set; }
/// <summary>
/// 获得/设置 Modal 实例
/// </summary>
protected AssignModalBase<Role>? AssignRoleModal { get; set; }
/// <summary> /// <summary>
/// 获得/设置 菜单类别 /// 获得/设置 菜单类别
/// </summary> /// </summary>
@ -168,11 +173,50 @@ namespace Bootstrap.Admin.Pages.Views.Admin.Components
} }
/// <summary> /// <summary>
/// 分配角色方法 /// 弹窗分配角色方法
/// </summary> /// </summary>
protected void AssignRoles() protected void AssignRoles()
{ {
// 菜单对角色授权操作
if (EditPage != null && EditPage.SelectedItems.Any())
{
var menuId = EditPage.SelectedItems.First().Id;
if (!string.IsNullOrEmpty(menuId))
{
var roles = RoleHelper.RetrievesByMenuId(menuId);
AssignRoleModal?.Update(roles);
}
}
} }
/// <summary>
/// 保存授权角色方法
/// </summary>
protected bool SaveRoles(IEnumerable<Role> roles)
{
bool ret = false;
if (EditPage != null && EditPage.SelectedItems.Any())
{
var menuId = EditPage.SelectedItems.First().Id;
var roleIds = roles.Where(r => r.Checked == "checked").Select(r => r.Id ?? "");
if (!string.IsNullOrEmpty(menuId)) ret = RoleHelper.SavaByMenuId(menuId, roleIds);
}
return ret;
}
/// <summary>
/// 选择框点击时调用此方法
/// </summary>
/// <param name="item"></param>
/// <param name="check"></param>
protected void OnClick(Role item, bool check)
{
item.Checked = check ? "checked" : "";
}
/// <summary>
/// 设置初始化值
/// </summary>
protected CheckBoxState SetCheck(Role item) => item.Checked == "checked" ? CheckBoxState.Checked : CheckBoxState.UnChecked;
} }
} }

View File

@ -16,6 +16,11 @@ namespace Bootstrap.Admin.Pages.Views.Admin.Components
[Parameter] [Parameter]
public bool FixedHeader { get; set; } public bool FixedHeader { get; set; }
/// <summary>
/// 获得/设置 EditPage 实例
/// </summary>
protected EditPageBase<TItem>? EditPage { get; set; }
/// <summary> /// <summary>
/// 获得/设置 TItem 实例 /// 获得/设置 TItem 实例
/// </summary> /// </summary>