FlexJobApi.Application/Dictionaries/DictionaryAppService.cs
@@ -18,7 +18,7 @@ /// </summary> /// <param name="query"></param> /// <returns></returns> public Task<GetDictionaryDatasQueryResult> GetDictionaryDatasQuery(GetDictionaryDatasQuery query) public Task<GetDictionaryDatasQueryResult> GetDictionaryDatas(GetDictionaryDatasQuery query) { return mediator.Send(query); } FlexJobApi.Application/FlexJobApi.Application.xml
@@ -14,7 +14,7 @@ 资源 </summary> </member> <member name="M:FlexJobApi.Application.DictionaryAppService.GetDictionaryDatasQuery(FlexJobApi.Core.GetDictionaryDatasQuery)"> <member name="M:FlexJobApi.Application.DictionaryAppService.GetDictionaryDatas(FlexJobApi.Core.GetDictionaryDatasQuery)"> <summary> 获取字典数据分页列表 </summary> FlexJobApi.Core/Entities/Users/RoleResource.cs
@@ -22,18 +22,18 @@ public Role Role { get; set; } /// <summary> /// 菜单Id /// 资源Id /// </summary> public Guid MenuId { get; set; } public Guid ResourceId { get; set; } /// <summary> /// 菜单 /// 资源 /// </summary> public Menu Menu { get; set; } public Resource Resource { get; set; } /// <summary> /// 数据权限 /// </summary> public EnumRoleWebApiDataPower? DataPower { get; set; } public EnumRoleWebApiDataPower DataPower { get; set; } } } FlexJobApi.Core/FlexJobApi.Core.xml
@@ -989,14 +989,14 @@ 角色 </summary> </member> <member name="P:FlexJobApi.Core.RoleResource.MenuId"> <member name="P:FlexJobApi.Core.RoleResource.ResourceId"> <summary> 菜单Id 资源Id </summary> </member> <member name="P:FlexJobApi.Core.RoleResource.Menu"> <member name="P:FlexJobApi.Core.RoleResource.Resource"> <summary> 菜单 资源 </summary> </member> <member name="P:FlexJobApi.Core.RoleResource.DataPower"> @@ -1969,11 +1969,6 @@ 删除菜单 </summary> </member> <member name="P:FlexJobApi.Core.DeleteMenuCommand.Ids"> <summary> Id </summary> </member> <member name="T:FlexJobApi.Core.SaveMenuCommand"> <summary> 保存菜单 @@ -2604,6 +2599,116 @@ 响应类型名称 </summary> </member> <member name="T:FlexJobApi.Core.DeleteRoleCommand"> <summary> 删除角色 </summary> </member> <member name="T:FlexJobApi.Core.SaveRoleCommand"> <summary> 保存角色 </summary> </member> <member name="P:FlexJobApi.Core.SaveRoleCommand.Id"> <summary> Id </summary> </member> <member name="P:FlexJobApi.Core.SaveRoleCommand.Name"> <summary> 名称 </summary> </member> <member name="P:FlexJobApi.Core.SaveRoleCommand.UserType"> <summary> 用户类型 </summary> </member> <member name="P:FlexJobApi.Core.SaveRoleCommand.ClientType"> <summary> 客户端类型 </summary> </member> <member name="P:FlexJobApi.Core.SaveRoleCommand.MinLevel"> <summary> 最低级别 </summary> </member> <member name="P:FlexJobApi.Core.SaveRoleCommand.MenuIds"> <summary> 菜单Id </summary> </member> <member name="P:FlexJobApi.Core.SaveRoleCommand.Resources"> <summary> 资源 </summary> </member> <member name="T:FlexJobApi.Core.GetRoleQuery"> <summary> 查询角色详情 </summary> </member> <member name="P:FlexJobApi.Core.GetRoleQuery.Id"> <summary> Id </summary> </member> <member name="T:FlexJobApi.Core.GetRoleQueryResult"> <summary> 查询角色详情-结果 </summary> </member> <member name="P:FlexJobApi.Core.GetRoleQueryResult.Id"> <summary> Id </summary> </member> <member name="P:FlexJobApi.Core.GetRoleQueryResult.Name"> <summary> 名称 </summary> </member> <member name="P:FlexJobApi.Core.GetRoleQueryResult.UserType"> <summary> 用户类型 </summary> </member> <member name="P:FlexJobApi.Core.GetRoleQueryResult.ClientType"> <summary> 客户端类型 </summary> </member> <member name="P:FlexJobApi.Core.GetRoleQueryResult.MinLevel"> <summary> 最低级别 </summary> </member> <member name="P:FlexJobApi.Core.GetRoleQueryResult.MenuIds"> <summary> 菜单Id </summary> </member> <member name="P:FlexJobApi.Core.GetRoleQueryResult.Resources"> <summary> 资源 </summary> </member> <member name="T:FlexJobApi.Core.GetRoleQueryResultResource"> <summary> 查询角色详情-结果-资源 </summary> </member> <member name="P:FlexJobApi.Core.GetRoleQueryResultResource.ResourceId"> <summary> 资源Id </summary> </member> <member name="P:FlexJobApi.Core.GetRoleQueryResultResource.DataPower"> <summary> 数据权限 </summary> </member> <member name="T:FlexJobApi.Core.GetRolesQuery"> <summary> 查询角色分页列表 @@ -2757,6 +2862,11 @@ <param name="modelBuilder"></param> <param name="dbContextLocator"></param> <returns></returns> </member> <member name="T:FlexJobApi.Core.DeleteCommand"> <summary> 删除命令 </summary> </member> <member name="P:FlexJobApi.Core.EnumModel.Name"> <summary> @@ -3036,7 +3146,7 @@ <summary> 查询分页列表 </summary> <typeparam name="TCallback"></typeparam> <typeparam name="TResult"></typeparam> <typeparam name="TItem"></typeparam> </member> <member name="P:FlexJobApi.Core.PagedListQuery`2.PageModel"> @@ -3059,9 +3169,9 @@ 页码 </summary> </member> <member name="P:FlexJobApi.Core.PagedListQueryPageModel.TotalCount"> <member name="P:FlexJobApi.Core.PagedListQueryPageModel.OrderInput"> <summary> 总数 排序 </summary> </member> <member name="T:FlexJobApi.Core.PagedListQueryPageModelOrderInput"> @@ -3100,11 +3210,35 @@ 查询分页列表-分页信息 </summary> </member> <member name="P:FlexJobApi.Core.PagedListQueryResultPageModel.TotalCount"> <summary> 总数 </summary> </member> <member name="P:FlexJobApi.Core.PagedListQueryResultPageModel.TotalPage"> <summary> 页数 </summary> </member> <member name="M:FlexJobApi.Core.PagedListUtils.ToPagedListAsync``1(System.Linq.IQueryable{``0},FlexJobApi.Core.PagedListQueryPageModel,System.Threading.CancellationToken)"> <summary> 查询分页列表数据 </summary> <typeparam name="TItem"></typeparam> <param name="q"></param> <param name="page"></param> <param name="cancellationToken"></param> <returns></returns> </member> <member name="M:FlexJobApi.Core.PagedListUtils.OrderBy``1(System.Linq.IQueryable{``0},System.Collections.Generic.List{FlexJobApi.Core.PagedListQueryPageModelOrderInput})"> <summary> 排序 </summary> <typeparam name="T"></typeparam> <param name="q"></param> <param name="orders"></param> <returns></returns> </member> <member name="P:FlexJobApi.Core.ResourceModel.TraceId"> <summary> 跟踪Id FlexJobApi.Core/Models/User/Auths/Commands/PasswordLoginCommand.cs
@@ -43,6 +43,15 @@ /// </summary> public class PasswordLoginCommandCallback { /// <summary> /// 用户访问令牌 /// </summary> public string AccessToken { get; set; } /// <summary> /// 刷新令牌 /// </summary> public string RefreshToken { get; set; } } } FlexJobApi.Core/Models/User/Menus/Commands/DeleteMenuCommand.cs
@@ -11,17 +11,8 @@ /// <summary> /// 删除菜单 /// </summary> public class DeleteMenuCommand : IRequest<int> public class DeleteMenuCommand : DeleteCommand, IRequest<int> { public DeleteMenuCommand() { Ids = []; } /// <summary> /// Id /// </summary> [Required] public List<Guid> Ids { get; set; } } } FlexJobApi.Core/Models/User/Roles/Commands/DeleteRoleCommand.cs
@@ -1,12 +1,17 @@ using System; using MediatR; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace FlexJobApi.Core.Models.User.Roles.Commands namespace FlexJobApi.Core { internal class DeleteRoleCommand /// <summary> /// 删除角色 /// </summary> public class DeleteRoleCommand : DeleteCommand, IRequest<int> { } } FlexJobApi.Core/Models/User/Roles/Commands/SaveRoleCommand.cs
@@ -1,12 +1,56 @@ using System; using MediatR; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace FlexJobApi.Core.Models.User.Roles.Commands namespace FlexJobApi.Core { internal class SaveRoleCommand /// <summary> /// 保存角色 /// </summary> public class SaveRoleCommand : IRequest<Guid> { public SaveRoleCommand() { MenuIds = []; Resources = []; } /// <summary> /// Id /// </summary> public Guid? Id { get; set; } /// <summary> /// 名称 /// </summary> public string Name { get; set; } /// <summary> /// 用户类型 /// </summary> public EnumUserType UserType { get; set; } /// <summary> /// 客户端类型 /// </summary> public EnumClientType ClientType { get; set; } /// <summary> /// 最低级别 /// </summary> public int MinLevel { get; set; } /// <summary> /// 菜单Id /// </summary> public List<Guid> MenuIds { get; set; } /// <summary> /// 资源 /// </summary> public List<GetRoleQueryResultResource> Resources { get; set; } } } FlexJobApi.Core/Models/User/Roles/Queries/GetRoleQuery.cs
@@ -1,12 +1,83 @@ using System; using MediatR; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace FlexJobApi.Core.Models.User.Roles.Queries namespace FlexJobApi.Core { internal class GetRoleQuery /// <summary> /// 查询角色详情 /// </summary> public class GetRoleQuery : IRequest<GetRoleQueryResult> { /// <summary> /// Id /// </summary> public Guid Id { get; set; } } /// <summary> /// 查询角色详情-结果 /// </summary> public class GetRoleQueryResult { public GetRoleQueryResult() { MenuIds = []; Resources = []; } /// <summary> /// Id /// </summary> public Guid Id { get; set; } /// <summary> /// 名称 /// </summary> public string Name { get; set; } /// <summary> /// 用户类型 /// </summary> public EnumUserType UserType { get; set; } /// <summary> /// 客户端类型 /// </summary> public EnumClientType ClientType { get; set; } /// <summary> /// 最低级别 /// </summary> public int MinLevel { get; set; } /// <summary> /// 菜单Id /// </summary> public List<Guid> MenuIds { get; set; } /// <summary> /// 资源 /// </summary> public List<GetRoleQueryResultResource> Resources { get; set; } } /// <summary> /// 查询角色详情-结果-资源 /// </summary> public class GetRoleQueryResultResource { /// <summary> /// 资源Id /// </summary> public Guid ResourceId { get; set; } /// <summary> /// 数据权限 /// </summary> public EnumRoleWebApiDataPower DataPower { get; set; } } } FlexJobApi.Core/Utils/DeleteUtils/DeleteCommand.cs
New file @@ -0,0 +1,23 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Text; using System.Threading.Tasks; namespace FlexJobApi.Core { /// <summary> /// 删除命令 /// </summary> public abstract class DeleteCommand { protected DeleteCommand() { Ids = []; } [Required] public List<Guid> Ids { get; set; } } } FlexJobApi.Core/Utils/PagedListUtils/PagedListQuery.cs
@@ -10,12 +10,17 @@ /// <summary> /// 查询分页列表 /// </summary> /// <typeparam name="TCallback"></typeparam> /// <typeparam name="TResult"></typeparam> /// <typeparam name="TItem"></typeparam> public abstract class PagedListQuery<TCallback, TItem> where TCallback : PagedListQueryResult<TItem>, new() public abstract class PagedListQuery<TResult, TItem> where TResult : PagedListQueryResult<TItem>, new() where TItem : class, new() { protected PagedListQuery() { PageModel = new PagedListQueryPageModel(); } /// <summary> /// 分页信息 /// </summary> @@ -27,6 +32,13 @@ /// </summary> public class PagedListQueryPageModel { public PagedListQueryPageModel() { Page = 1; Rows = 40; OrderInput = []; } /// <summary> /// 行数 /// </summary> @@ -38,9 +50,9 @@ public int Page { get; set; } /// <summary> /// 总数 /// 排序 /// </summary> public int TotalCount { get; set; } public List<PagedListQueryPageModelOrderInput> OrderInput { get; set; } } /// <summary> @@ -88,6 +100,11 @@ public class PagedListQueryResultPageModel : PagedListQueryPageModel { /// <summary> /// 总数 /// </summary> public int TotalCount { get; set; } /// <summary> /// 页数 /// </summary> public int TotalPage { get; set; } FlexJobApi.Core/Utils/PagedListUtils/PagedListUtils.cs
@@ -1,12 +1,99 @@ using System; using FlexJobApi.User.Application; using Furion.DatabaseAccessor; using Furion.FriendlyException; using Mapster; using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Text; using System.Threading; using System.Threading.Tasks; namespace FlexJobApi.Core { public class PagedListUtils public static class PagedListUtils { /// <summary> /// 查询分页列表数据 /// </summary> /// <typeparam name="TItem"></typeparam> /// <param name="q"></param> /// <param name="page"></param> /// <param name="cancellationToken"></param> /// <returns></returns> public static async Task<PagedListQueryResult<TItem>> ToPagedListAsync<TItem>(this IQueryable<TItem> q, PagedListQueryPageModel page, CancellationToken cancellationToken = default) where TItem : class, new() { var pagedList = await q .OrderBy(page.OrderInput) .ToPagedListAsync(page.Page, page.Rows, cancellationToken); var result = new PagedListQueryResult<TItem>(); result.PageModel = page.Adapt<PagedListQueryResultPageModel>(); result.PageModel.TotalCount = pagedList.TotalCount; result.PageModel.TotalPage = pagedList.TotalPages; result.Data = pagedList.Items.ToList(); return result; } /// <summary> /// 排序 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="q"></param> /// <param name="orders"></param> /// <returns></returns> public static IQueryable<T> OrderBy<T>(this IQueryable<T> q, List<PagedListQueryPageModelOrderInput> orders) { if (orders.IsNull()) return q; var entityType = typeof(T); int index = 0; foreach (var order in orders) { if (string.IsNullOrEmpty(order.Property)) continue; // 获取排序字段的属性信息 var propertyInfo = entityType.GetProperty(order.Property); if (propertyInfo == null) throw Oops.Oh(EnumErrorCodeType.s404, $"该排序字段{order.Property}"); // 创建表达式树 var parameter = Expression.Parameter(entityType, "x"); var propertyAccess = Expression.Property(parameter, propertyInfo); var lambda = Expression.Lambda(propertyAccess, parameter); string methodName; if (index == 0) { // 首次排序 methodName = order.Order == EnumPagedListOrder.Ascending ? "OrderBy" : "OrderByDescending"; } else { // 二次及以后排序 methodName = order.Order == EnumPagedListOrder.Ascending ? "ThenBy" : "ThenByDescending"; } // 调用相应的排序方法 var resultExpression = Expression.Call( typeof(Queryable), methodName, [entityType, propertyInfo.PropertyType], q.Expression, Expression.Quote(lambda) ); q = q.Provider.CreateQuery<T>(resultExpression); index++; } return q; } } } FlexJobApi.User.Application/Auths/Commands/PasswordLoginCommandHandler.cs
@@ -54,7 +54,11 @@ }; JwtUtils.GenerateToken(logier); return new PasswordLoginCommandCallback(); return new PasswordLoginCommandCallback { AccessToken = logier.AccessToken, RefreshToken = logier.RefreshToken, }; } } } FlexJobApi.User.Application/FlexJobApi.User.Application.xml
@@ -236,6 +236,45 @@ <param name="query"></param> <returns></returns> </member> <member name="T:FlexJobApi.User.Application.DeleteRoleCommandHandler"> <summary> 删除角色 </summary> </member> <member name="M:FlexJobApi.User.Application.DeleteRoleCommandHandler.#ctor(Furion.DatabaseAccessor.IRepository{FlexJobApi.Core.Role})"> <summary> 删除角色 </summary> </member> <member name="M:FlexJobApi.User.Application.DeleteRoleCommandHandler.Handle(FlexJobApi.Core.DeleteRoleCommand,System.Threading.CancellationToken)"> <inheritdoc/> </member> <member name="T:FlexJobApi.User.Application.SaveRoleCommandHandler"> <summary> 保存角色 </summary> </member> <member name="M:FlexJobApi.User.Application.SaveRoleCommandHandler.#ctor(Furion.DatabaseAccessor.IRepository{FlexJobApi.Core.Role})"> <summary> 保存角色 </summary> </member> <member name="M:FlexJobApi.User.Application.SaveRoleCommandHandler.Handle(FlexJobApi.Core.SaveRoleCommand,System.Threading.CancellationToken)"> <inheritdoc/> </member> <member name="T:FlexJobApi.User.Application.GetRoleQueryHandler"> <summary> 获取角色详情 </summary> </member> <member name="M:FlexJobApi.User.Application.GetRoleQueryHandler.#ctor(Furion.DatabaseAccessor.IRepository{FlexJobApi.Core.Role})"> <summary> 获取角色详情 </summary> </member> <member name="M:FlexJobApi.User.Application.GetRoleQueryHandler.Handle(FlexJobApi.Core.GetRoleQuery,System.Threading.CancellationToken)"> <inheritdoc/> </member> <member name="T:FlexJobApi.User.Application.GetRolesQueryHandler"> <summary> 查询角色分页列表 FlexJobApi.User.Application/Roles/Commands/DeleteRoleCommandHandler.cs
New file @@ -0,0 +1,35 @@ using FlexJobApi.Core; using Furion.DatabaseAccessor; using MediatR; using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace FlexJobApi.User.Application { /// <summary> /// 删除角色 /// </summary> public class DeleteRoleCommandHandler( IRepository<Role> rep ) : IRequestHandler<DeleteRoleCommand, int> { private readonly IRepository<Role> rep = rep; /// <inheritdoc/> public async Task<int> Handle(DeleteRoleCommand request, CancellationToken cancellationToken) { var entities = await rep.AsQueryable() .Include(it => it.RoleMenus) .Include(it => it.RoleResources) .Where(it => request.Ids.Contains(it.Id)) .ToListAsync(cancellationToken); return entities.Any() ? await rep.DeleteNowAsync(entities, cancellationToken) : 0; } } } FlexJobApi.User.Application/Roles/Commands/SaveRoleCommandHandler.cs
New file @@ -0,0 +1,60 @@ using FlexJobApi.Core; using Furion.DatabaseAccessor; using Furion.FriendlyException; using Mapster; using MediatR; using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace FlexJobApi.User.Application { /// <summary> /// 保存角色 /// </summary> public class SaveRoleCommandHandler( IRepository<Role> rep ) : IRequestHandler<SaveRoleCommand, Guid> { private readonly IRepository<Role> rep = rep; /// <inheritdoc/> public async Task<Guid> Handle(SaveRoleCommand request, CancellationToken cancellationToken) { if (request.Id.HasValue) { var entity = await rep.AsQueryable() .Include(it => it.RoleMenus) .Include(it => it.RoleResources) .FirstOrDefaultAsync(it => it.Id == request.Id, cancellationToken); if (entity == null) throw Oops.Oh(EnumErrorCodeType.s404, "角色"); request.Adapt(entity); await rep.UpdateAsync(entity); return entity.Id; } else { var entity = new Role(); request.Adapt(entity); entity.RoleMenus = request.MenuIds .Select(it => new RoleMenu { MenuId = it }) .ToList(); entity.RoleResources = request.Resources .Select(it => new RoleResource { ResourceId = it.ResourceId, DataPower = it.DataPower }) .ToList(); await rep.InsertAsync(entity); return entity.Id; } } } } FlexJobApi.User.Application/Roles/Queries/GetRoleQueryHandler.cs
New file @@ -0,0 +1,47 @@ using FlexJobApi.Core; using Furion.DatabaseAccessor; using Furion.FriendlyException; using Mapster; using MediatR; using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace FlexJobApi.User.Application { /// <summary> /// 获取角色详情 /// </summary> public class GetRoleQueryHandler( IRepository<Role> rep ) : IRequestHandler<GetRoleQuery, GetRoleQueryResult> { private readonly IRepository<Role> rep = rep; /// <inheritdoc/> public async Task<GetRoleQueryResult> Handle(GetRoleQuery request, CancellationToken cancellationToken) { var entity = await rep.AsQueryable().AsNoTracking() .Where(it => it.Id == request.Id) .ProjectToType<GetRoleQueryResult>() .FirstOrDefaultAsync(cancellationToken); if (entity == null) throw Oops.Oh(EnumErrorCodeType.s404, "该角色"); entity.MenuIds = await rep.Change<RoleMenu>().AsQueryable().AsNoTracking() .Where(it => it.RoleId == request.Id) .Select(it => it.MenuId) .ToListAsync(cancellationToken); entity.Resources = await rep.Change<RoleResource>().AsQueryable().AsNoTracking() .Where(it => it.RoleId == request.Id) .ProjectToType<GetRoleQueryResultResource>() .ToListAsync(cancellationToken); return entity; } } } FlexJobApi.User.Application/Roles/Queries/GetRolesQueryHandler.cs
@@ -1,5 +1,6 @@ using FlexJobApi.Core; using Furion.DatabaseAccessor; using Mapster; using MediatR; using Microsoft.EntityFrameworkCore; using System; @@ -32,7 +33,11 @@ { q = q.Where(it => it.ClientType == request.ClientType); } throw new NotImplementedException(); var result = q .ProjectToType<GetRolesQueryResultItem>() .ToPagedListAsync(request.PageModel, cancellationToken); return result; } } }