首页 > 其他分享 >用AntDesignBlazor快速开发一个权限系统

用AntDesignBlazor快速开发一个权限系统

时间:2023-12-09 09:44:41浏览次数:34  
标签:set get await AntDesignBlazor protected async Task 权限 快速

写在前面:如果您是一个C#的后台开发人员,又或是C#的WPF开发人,如果想快速开发自己的网站系统,那么选择Blazor技术是太适合你不过了。(在没有Blazor之前,我会推荐Vue),尤其当我看到Ant Desgin Blazor(https://antblazor.com/zh-CN/)全家桶的时候,毫不犹豫就开始了我的愉快之旅。

一、登录界面

直接使用官方例子(https://gitee.com/ant-design-blazor/ant-design-pro-blazor)。然后换个标即可。

二、主界面

主界面同样也使用官方例子,但是为了对接自己的数据结构,稍微改了点

三、构建标准的增删改业务界面

为了避免业务代码的重复,构建两大基类,一个是List的基类,一个是Edit的基类,如下两个界面:

List基类的代码大致如下:

 public class BaseList<TData> : PageBase where TData : IKeyBaseEntity
 {

     [Inject] //API请求
     protected IDataProvider DataProvider { get; set; }
     [Inject] //用户缓存数据
     protected IUserData UserData { get; set; }
     [Inject] //Ant Design Blazor消息框
     protected MessageService MessageService { get; set; }
     [Inject] //Ant Design Blazor对话框
     protected ModalService ModalService { get; set; }

     [Inject] //调用JS脚本
     IJSRuntime JSRuntime { get; set; }
     protected string? Area { get; set; }//区域
     protected string GetDataList { get; set; } = "GetDataList";
     protected string? Condition { get; set; }
     protected string? KeyWord { get; set; }
     protected List<TData> Data { get; set; } = new List<TData>();
     protected TData? SelectedItem { get; set; }
     protected IEnumerable<TData>? SelectedItems { get; set; }
     protected bool NoneSelectedItems { get { return !(SelectedItems?.Count() > 0); } }
     protected Table<TData>? _table;

     protected virtual string GetDataJson()//查询条件拼接
     {         
     }

     protected override async Task GetData()//请求数据
     {
     }

     protected virtual void Edit(TData para)//编辑数据
     {

     }

     protected virtual async Task Delete(string id)//删除数据
     {

     }   

     //获取路由信息,显示界面地址
     protected override async Task OnInitializedAsync()
     {
         if (string.IsNullOrEmpty(IndexUrl))
         {
             IndexUrl = NavigationManager.Uri;
             var uri = new Uri(IndexUrl);
             IndexUrl = uri.LocalPath;
         }
         await base.OnInitializedAsync();
         await GetData();
     }
 }

Edit基类大致如下:

public class BaseEditFormWithOption<TData, Option> : FeedbackComponent<Option>, ILoading
 {
     [Inject]
     protected IDataProvider DataProvider { get; set; }
     [Inject]
     protected IUserData UserData { get; set; }
     [Inject]
     protected MessageService MessageService { get; set; }

  
     protected bool Disabled { get; set; }
     public bool Loading { get; set; }
     protected string Area { get; set; }

     protected TData Data { get; set; }

     protected Form<TData> _form;

     //获取数据
     protected virtual async Task GetDataAsync(Option option)
     {
         
     }

     //保存数据
     protected virtual async Task SaveData(TData para)
     {
        
     }

     //初始化
     protected override async Task OnInitializedAsync()
     {
         var id = this.Options;
         await GetDataAsync(id);

         await base.OnInitializedAsync();
     }

     //按钮操作
     public override async Task OnFeedbackOkAsync(ModalClosingEventArgs args)
     {
         try
         {
             if (FeedbackRef is ConfirmRef confirmRef)
             {
                 confirmRef.Config.OkButtonProps.Loading = true;
                 await confirmRef.UpdateConfigAsync();
             }
             else if (FeedbackRef is ModalRef modalRef)
             {
                 modalRef.Config.ConfirmLoading = true;
                 await modalRef.UpdateConfigAsync();
             }

             if (_form.Validate())
             {
                 await SaveData(Data);
             }
             else
             {
                 args.Cancel = true;
             }

             await base.OnFeedbackOkAsync(args);
         }
         finally
         {
             if (FeedbackRef is ConfirmRef confirmRef)
             {
                 confirmRef.Config.OkButtonProps.Loading = false;
                 await confirmRef.UpdateConfigAsync();
             }
             else if (FeedbackRef is ModalRef modalRef)
             {
                 modalRef.Config.ConfirmLoading = false;
                 await modalRef.UpdateConfigAsync();
             }
         }
     }
  }

List界面使用的时候代码如下:

@page "/Base_Manage/Base_User/List"

@inherits BaseListWithEdit<Base_UserDTO, EditForm>

<Space Size="@("small")">

    @if (Operator.HasPerm("Base_User.Add"))
    {
        <SpaceItem>
            <Button Type="@ButtonType.Primary" Icon="plus" OnClick="()=>Edit()">新建</Button>
        </SpaceItem>
    }
    @if (Operator.HasPerm("Base_User.Delete"))
    {
        <SpaceItem>
            <Popconfirm Title="确认删除选中项吗?"
                    OnConfirm="()=>Delete()"
                    OnCancel="()=>{}"
                    OkText="确定"
                    CancelText="取消"
                    Disabled=@NoneSelectedItems>
                <Button Type="@ButtonType.Primary" Danger Icon="minus" Disabled=@NoneSelectedItems>删除</Button>
            </Popconfirm>
        </SpaceItem>
    }
    <SpaceItem>
        <Search Placeholder="关键字" EnterButton="true" @bind-Value="@KeyWord" OnSearch="()=>Refresh()" />
    </SpaceItem>
</Space>

<Table @ref="_table"
       TItem="Base_UserDTO"
       DataSource="Data"
       EnableVirtualization
       Loading="Loading"
       @bind-PageSize="Pagination.PageRows"
       @bind-SelectedRows="SelectedItems"
       ScrollX="1400"
       ScrollBarWidth="12px"
       Size="TableSize.Small"
       RowClassName="@(x => x.RowIndex % 2 == 0 ?"gray-2":"")">
    <ChildContent>
        <Selection Key="@(context.Id)" />
        <AntDesign.Column Title="用户名" DataIndex="UserName" TData="string" />
        <AntDesign.Column Title="姓名" DataIndex="RealName" TData="string" />
        <AntDesign.Column Title="性别" DataIndex="SexText" TData="string" />
        <AntDesign.Column Title="出生日期" DataIndex="BirthdayText" TData="string" />
        <AntDesign.Column Title="所属部门" DataIndex="Base_DepartmentName" TData="string" />
        <AntDesign.Column Title="所属角色" DataIndex="RoleNames" TData="string" />
        <ActionColumn Title="Action" Fixed="right">
            <Space Size=@("small")>
                @if (Operator.HasPerm("Base_User.Edit"))
                {
                    <SpaceItem>
                        <Button Type="@ButtonType.Link" Style="padding:0px" OnClick="()=>Edit(context)">Edit</Button>
                    </SpaceItem>
                } 
                @if (Operator.HasPerm("Base_User.Delete"))
                {
                    <SpaceItem>
                        <Popconfirm Title="确认删除吗?"
                                OnConfirm="()=>Delete(context.Id)"
                                OnCancel="()=>{}"
                                OkText="确定"
                                CancelText="取消">
                            <Button Danger Type="@ButtonType.Link" Style="padding:0px">Delete</Button>
                    </Popconfirm>
                </SpaceItem>
                }
            </Space>
        </ActionColumn>
    </ChildContent>
    <PaginationTemplate>
        <div style="float:right;margin-top:10px">
            <Pagination Total="Pagination.Total"
                        ShowTotal="ShowTotal"
                        ShowSizeChanger
                        PageSize="Pagination.PageRows"
                        Current="Pagination.PageIndex"
                        OnChange="PageIndexChanged"
                        OnShowSizeChange="PageSizeChanged" />
        </div>
    </PaginationTemplate>
</Table>

<style>
    .gray-2 {
        #fafafa;
    }
</style>

@code
{
    public List()
    {
        Area = "Base_Manage";
        Condition = "UserName";
        NewTitle = "新建用户";
        EditTitle = "编辑用户";
    }
}

Edit界面使用的时候代码如下:

@inherits BaseEditForm<Base_UserDTO>

<Form @ref="_form" Model="@Data"
      LabelCol="new ColLayoutParam { Span = 8 }"
      WrapperCol="new ColLayoutParam { Span = 16 }">
    <FormItem Label="用户名">
        <Input @bind-Value="@context.UserName" AutoComplete=false/>
    </FormItem>
    <FormItem Label="密码">
        <InputPassword @bind-Value="@context.Password" AutoComplete=false />
    </FormItem>
    <FormItem Label="姓名">
        <Input @bind-Value="@context.RealName" AutoComplete=false />
    </FormItem>
    <FormItem Label="性别">
         <EnumRadioGroup TEnum="Sex" @bind-Value="@context.Sex" Options="GetRadioOptions<Sex>()"></EnumRadioGroup>
    </FormItem>
    <FormItem Label="生日">
        <DatePicker @bind-Value="@context.Birthday" Format="yyyy-MM-dd" />
    </FormItem> 
    <FormItem Label="部门">
        <TreeSelect  
            TItem="TreeModel"
            @bind-Value="@context.DepartmentId" 
         AllowClear
            DataSource="Departments"            
            Placeholder="请选择部门"
            ChildrenExpression="node=>node.DataItem.Children"
            TitleExpression="node=>node.DataItem.Text"
            KeyExpression="node=>node.DataItem.Id"
            IsLeafExpression="node => !(node.DataItem.Children?.Count > 0)"
            TreeDefaultExpandAll />
    </FormItem> 
     <FormItem Label="角色">
        <Select 
            TItem="SelectOption"
            TItemValue="string"
            @bind-Values="@context.RoleIdList"
            AllowClear
            DataSource="Roles"
            Placeholder="请选择角色"
            LabelName="@nameof(SelectOption.Text)"
            ValueName="@nameof(SelectOption.Value)"
            Mode="multiple">
        </Select>
    </FormItem>
</Form>

@code {

    public EditForm()
    {
        Area = "Base_Manage";
    }

    private List<SelectOption> Roles { get; set; }
    private List<TreeModel> Departments { get; set; }

    protected override async Task OnInitializedAsync()
    {
        using (var waitfor = WaitFor.GetWaitFor(this))
        {
            await GetRoles();
            await GetDepartment();
            await base.OnInitializedAsync();
        }
    }

    private async Task GetRoles()
    {
        Roles = await UserData.GetBase_Role();
    }

    private async Task GetDepartment()
    {
        Departments = await UserData.GetBase_DepartmentTree();
    }
    protected override async Task SaveData(Base_UserDTO para)
    {
        await base.SaveData(para);
    }
}

注意代码中的 @if (Operator.HasPerm("...")),可以根据权限判断哪些按钮可以显示。

四、现在越来越多的业务需要流程审批,因此集成了一下流程图界面

五、整个代码结构如下:

另外项目内有后台代码(ASP.NET API),有WPF/Winform/Maui嵌入Blazor的样例。

六、后台代码介绍:

采用ASP.NET Core 7.0的框架,内部实现有jwt验证,DI自动注入,nlog日志,事件总线,SqlSugar,aop拦截,quartz等。

七、相同同框架的WPF框架介绍,使用相同的后台(因为我们的系统使用前后台分离技术,因此客户端可以对接任何技术)

八、写在后面的话

作为一个wpf开发人员去开发BS架构,无论是Ant Desgin Vue,还是Ant Desgin Blazor(https://gitee.com/ant-design-blazor/ant-design-pro-blazor),都是一个不错的选择。

最后上代码地址:

https://gitee.com/akwkevin/AIStudio.Blazor.App

https://github.com/akwkevin/AIStudio.Blazor.App 

标签:set,get,await,AntDesignBlazor,protected,async,Task,权限,快速
From: https://www.cnblogs.com/akwkevin/p/17889497.html

相关文章

  • 快速区分webGL,webGPU,unity3D和UE4
    在3D图形渲染的渲染领域,很多友友们对上述概念傻傻分不清,站在前端开发角度,我用简单语言说下,结论在文章最后。一、四者都能进行3D图形渲染它们之间有一些区别,下面我将对它们进行简单的区分:   WebGPU:WebGPU是一种Web图形API,是基于底层的GPU硬件架构设计的,可以更好地利......
  • .NET开源且好用的权限工作流管理系统
    前言系统权限管理、工作流是企业应用开发中很常见的功能,虽说开发起来难度不大,但是假如从零开始开发一个完整的权限管理和工作流平台的话也是比较耗费时间的。今天推荐一款.NET开源且好用的权限工作流管理系统(值得借鉴参考和使用):OpenAuth.Net。官方项目介绍.Net权限管理及快速开......
  • 第六次课堂上了文件权限
    基本权限UGOU:owner,属主。G:group,属组。O:other,其他用户。1.使用11命令查看文件属性r:read(读取),数字设定为4。W:write(写入),数字设定为2。X:execute(执行),数字设定为1。例如,创建一个文件filel,使用11查看文件属性信息[root@gfedu~]#touchfilel[root@qfedu~]#11filelIw-r-=r--、1......
  • 第七次课堂讲了基本权限ACL
    UGO权限只针对一个用户、一个组与其他用户,使用上有局限性,ACL(AccessControlList主要提供传统的UGO的r、w、x权限之外的具体权限设置,可以对单一用户、单一文件或目录进行权限设置。ACL基本用法创建一个文件,使用getfacl命令查看ACL权限,此时显示的内容与先前使用11命令查看到的内......
  • [20231204]快速删除大量文件测试(rsync版本)4.txt
    [20231204]快速删除大量文件测试(rsync版本)4.txt--//前个星期做了大量文件测试,发现只要顺着inode节点顺序删除文件效率最高.--//还有一种方式使用rsync,利用建立空目录使用同步功能,删除对应目录里面的全部文件.--//我记忆里以前测试效率不错,今天做具体探究.1.建立测试环境:$mo......
  • 文件权限
    权限的意义在于允许某一个用户或某个用户组以规定的方式去访问某个文件。Linux系统通过U、G、O将用户分为三类,并对这三类用户分别设置三种基本权限,这种设置权限的方式称为UGO方式。为了数据的安全,系统需要给予不同身份的用户、用户组对应的文件权限。以下是三个常用的修改权限命令......
  • 文件权限UGO
    一、基本权限UGOLinux系统通过U、G、O将用户分为三类,并对这三类用户分别设置三种基本权限,这种设置权限的方式称作UGO方式1、设置文件属性与权限chown:修改文件属主、属组chgrp:修改文件属组chmod:修改文件权限若要将某目录下的所以子目录或文件同时修改属主或属组,只需要在chown......
  • zabbix使用自定义监控项权限不足
    一、背景zabbix在配置好个人监控项后,最开始基本上都会遇到权限不足的问题。二、解决方法两种解决方法:1、配置sudoers,然后再key值执行命令前加sudo(相对来说比较麻烦)2、配置zabbix_agent#zabbix-agent配置echo"AllowRoot=1">>/etc/zabbix/zabbix_agentd.conffind/-na......
  • 去除PDF加密等权限限制
    importPyPDF2fromCrypto.CipherimportAESimportosdefremove_pdf_restrictions():origi_path=r'C:\Users\yc\PycharmProjects\netmiko\丹凤相关\original_file\\'pdf_path=r'C:\Users\yc\PycharmProjects\netmiko\丹凤相关\pdf_result......
  • 第4章 带你快速入门WebRTC技术
    4-3屏幕共享项目-用golang搭建静态资源服务这段代码是一个使用Go语言编写的简单的HTTP和HTTPS服务器。下面是对代码中涉及的知识点和语法格式的详细解释packagemainimport( "fmt" "net/http")packagemain:这行代码指定了当前文件所属的包是main,表示这是一个可执行程......