From 4950d547503c7c1d5d0ff6487e6768937170ddf7 Mon Sep 17 00:00:00 2001
From: sunpengfei <i@angelzzz.com>
Date: 星期一, 04 八月 2025 17:29:00 +0800
Subject: [PATCH] feat:角色授权

---
 FlexJobApi.Core/Utils/PagedListUtils/PagedListUtils.cs                    |   11 ++-
 FlexJobApi.User.Application/FlexJobApi.User.Application.xml               |    3 
 FlexJobApi.User.Application/Resources/Queries/GetResourcesQueryHandler.cs |   10 +++
 FlexJobApi.User.Application/Menus/Queries/GetMenusQueryHandler.cs         |   18 ++++--
 FlexJobApi.Core/Utils/SwaggerUtils/CustomOperationIdFilter.cs             |    2 
 FlexJobApi.Core/Models/User/Menus/Queries/GetMenusQuery.cs                |   12 +++
 FlexJobApi.Core/FlexJobApi.Core.xml                                       |   45 +++++++++++++++
 FlexJobApi.Core/Models/User/Resources/Queries/GetResourcesQuery.cs        |   10 +++
 FlexJobApi.Core/Models/User/Menus/Queries/GetMenuQuery.cs                 |   25 ++++++++
 FlexJobApi.Application/Dictionaries/DictionaryAppService.cs               |    2 
 FlexJobApi.Application/FlexJobApi.Application.xml                         |    4 
 FlexJobApi.User.Application/Menus/Queries/GetMenuQueryHandler.cs          |   31 ++++++++--
 12 files changed, 149 insertions(+), 24 deletions(-)

diff --git a/FlexJobApi.Application/Dictionaries/DictionaryAppService.cs b/FlexJobApi.Application/Dictionaries/DictionaryAppService.cs
index 42c7f0e..77900de 100644
--- a/FlexJobApi.Application/Dictionaries/DictionaryAppService.cs
+++ b/FlexJobApi.Application/Dictionaries/DictionaryAppService.cs
@@ -6,7 +6,7 @@
 namespace FlexJobApi.Application
 {
     /// <summary>
-    /// 璧勬簮
+    /// 鏁版嵁瀛楀吀
     /// </summary>
     [Route("api/main/[controller]")]
     public class DictionaryAppService(IMediator mediator) : IDynamicApiController
diff --git a/FlexJobApi.Application/FlexJobApi.Application.xml b/FlexJobApi.Application/FlexJobApi.Application.xml
index 1cd4ea2..ccec683 100644
--- a/FlexJobApi.Application/FlexJobApi.Application.xml
+++ b/FlexJobApi.Application/FlexJobApi.Application.xml
@@ -6,12 +6,12 @@
     <members>
         <member name="T:FlexJobApi.Application.DictionaryAppService">
             <summary>
-            璧勬簮
+            鏁版嵁瀛楀吀
             </summary>
         </member>
         <member name="M:FlexJobApi.Application.DictionaryAppService.#ctor(MediatR.IMediator)">
             <summary>
-            璧勬簮
+            鏁版嵁瀛楀吀
             </summary>
         </member>
         <member name="M:FlexJobApi.Application.DictionaryAppService.GetDictionaryDatas(FlexJobApi.Core.GetDictionaryDatasQuery)">
diff --git a/FlexJobApi.Core/FlexJobApi.Core.xml b/FlexJobApi.Core/FlexJobApi.Core.xml
index d899a9b..dea062f 100644
--- a/FlexJobApi.Core/FlexJobApi.Core.xml
+++ b/FlexJobApi.Core/FlexJobApi.Core.xml
@@ -2184,6 +2184,11 @@
             Id
             </summary>
         </member>
+        <member name="P:FlexJobApi.Core.Models.GetMenuQuery.RoleId">
+            <summary>
+            瑙掕壊Id
+            </summary>
+        </member>
         <member name="T:FlexJobApi.Core.Models.GetMenuQueryResult">
             <summary>
             鏌ヨ鑿滃崟璇︽儏-缁撴灉
@@ -2192,6 +2197,11 @@
         <member name="P:FlexJobApi.Core.Models.GetMenuQueryResult.Id">
             <summary>
             Id
+            </summary>
+        </member>
+        <member name="P:FlexJobApi.Core.Models.GetMenuQueryResult.IsChecked">
+            <summary>
+            鏄惁閫夋嫨锛堢敤鎴疯鑹叉巿鏉冿級
             </summary>
         </member>
         <member name="P:FlexJobApi.Core.Models.GetMenuQueryResult.UserType">
@@ -2314,6 +2324,11 @@
             Id
             </summary>
         </member>
+        <member name="P:FlexJobApi.Core.Models.GetMenuQueryResultButton.IsChecked">
+            <summary>
+            鏄惁閫夋嫨锛堢敤鎴疯鑹叉巿鏉冿級
+            </summary>
+        </member>
         <member name="P:FlexJobApi.Core.Models.GetMenuQueryResultButton.Code">
             <summary>
             缂栧彿
@@ -2354,6 +2369,11 @@
             Id
             </summary>
         </member>
+        <member name="P:FlexJobApi.Core.Models.GetMenuQueryResultField.IsChecked">
+            <summary>
+            鏄惁閫夋嫨锛堢敤鎴疯鑹叉巿鏉冿級
+            </summary>
+        </member>
         <member name="P:FlexJobApi.Core.Models.GetMenuQueryResultField.Code">
             <summary>
             缂栧彿
@@ -2387,6 +2407,11 @@
         <member name="P:FlexJobApi.Core.Models.GetMenuQueryResultItem.Id">
             <summary>
             Id
+            </summary>
+        </member>
+        <member name="P:FlexJobApi.Core.Models.GetMenuQueryResultItem.IsChecked">
+            <summary>
+            鏄惁閫夋嫨锛堢敤鎴疯鑹叉巿鏉冿級
             </summary>
         </member>
         <member name="P:FlexJobApi.Core.Models.GetMenuQueryResultItem.Code">
@@ -2449,6 +2474,11 @@
             瀹㈡埛绔被鍨�
             </summary>
         </member>
+        <member name="P:FlexJobApi.Core.GetMenusQuery.RoleId">
+            <summary>
+            瑙掕壊Id
+            </summary>
+        </member>
         <member name="T:FlexJobApi.Core.GetMenusQueryResultItem">
             <summary>
             鏌ヨ鎵�鏈夎彍鍗�-缁撴灉-椤�
@@ -2457,6 +2487,11 @@
         <member name="P:FlexJobApi.Core.GetMenusQueryResultItem.Id">
             <summary>
             Id
+            </summary>
+        </member>
+        <member name="P:FlexJobApi.Core.GetMenusQueryResultItem.IsChecked">
+            <summary>
+            鏄惁閫夋嫨锛堢敤鎴疯鑹叉巿鏉冿級
             </summary>
         </member>
         <member name="P:FlexJobApi.Core.GetMenusQueryResultItem.ParentId">
@@ -2569,6 +2604,11 @@
             鍏抽敭瀛�
             </summary>
         </member>
+        <member name="P:FlexJobApi.Core.GetResourcesQuery.RoleId">
+            <summary>
+            瑙掕壊Id
+            </summary>
+        </member>
         <member name="T:FlexJobApi.Core.GetResourcesQueryResultItem">
             <summary>
             鑾峰彇璧勬簮鍒楄〃-缁撴灉-椤�
@@ -2579,6 +2619,11 @@
             Id
             </summary>
         </member>
+        <member name="P:FlexJobApi.Core.GetResourcesQueryResultItem.IsChecked">
+            <summary>
+            鏄惁閫変腑锛堢敤浜庤鑹叉巿鏉冿級
+            </summary>
+        </member>
         <member name="P:FlexJobApi.Core.GetResourcesQueryResultItem.Service">
             <summary>
             寰湇鍔�
diff --git a/FlexJobApi.Core/Models/User/Menus/Queries/GetMenuQuery.cs b/FlexJobApi.Core/Models/User/Menus/Queries/GetMenuQuery.cs
index 643b38f..700b2da 100644
--- a/FlexJobApi.Core/Models/User/Menus/Queries/GetMenuQuery.cs
+++ b/FlexJobApi.Core/Models/User/Menus/Queries/GetMenuQuery.cs
@@ -17,6 +17,11 @@
         /// Id
         /// </summary>
         public Guid Id { get; set; }
+
+        /// <summary>
+        /// 瑙掕壊Id
+        /// </summary>
+        public Guid? RoleId { get; set; }
     }
 
     /// <summary>
@@ -33,6 +38,11 @@
         /// Id
         /// </summary>
         public Guid Id { get; set; }
+
+        /// <summary>
+        /// 鏄惁閫夋嫨锛堢敤鎴疯鑹叉巿鏉冿級
+        /// </summary>
+        public bool IsChecked { get; set; }
 
         /// <summary>
         /// 鐢ㄦ埛绫诲瀷
@@ -169,6 +179,11 @@
         public Guid Id { get; set; }
 
         /// <summary>
+        /// 鏄惁閫夋嫨锛堢敤鎴疯鑹叉巿鏉冿級
+        /// </summary>
+        public bool IsChecked { get; set; }
+
+        /// <summary>
         /// 缂栧彿
         /// </summary>
         public string Code { get; set; }
@@ -210,6 +225,11 @@
         public Guid Id { get; set; }
 
         /// <summary>
+        /// 鏄惁閫夋嫨锛堢敤鎴疯鑹叉巿鏉冿級
+        /// </summary>
+        public bool IsChecked { get; set; }
+
+        /// <summary>
         /// 缂栧彿
         /// </summary>
         public string Code { get; set; }
@@ -246,6 +266,11 @@
         public Guid Id { get; set; }
 
         /// <summary>
+        /// 鏄惁閫夋嫨锛堢敤鎴疯鑹叉巿鏉冿級
+        /// </summary>
+        public bool IsChecked { get; set; }
+
+        /// <summary>
         /// 缂栧彿
         /// </summary>
         public string Code { get; set; }
diff --git a/FlexJobApi.Core/Models/User/Menus/Queries/GetMenusQuery.cs b/FlexJobApi.Core/Models/User/Menus/Queries/GetMenusQuery.cs
index 28bc02a..bedcf4d 100644
--- a/FlexJobApi.Core/Models/User/Menus/Queries/GetMenusQuery.cs
+++ b/FlexJobApi.Core/Models/User/Menus/Queries/GetMenusQuery.cs
@@ -28,6 +28,11 @@
         /// 瀹㈡埛绔被鍨�
         /// </summary>
         public EnumClientType ClientType { get; set; }
+
+        /// <summary>
+        /// 瑙掕壊Id
+        /// </summary>
+        public Guid? RoleId { get; set; }
     }
 
     /// <summary>
@@ -43,7 +48,12 @@
         /// <summary>
         /// Id
         /// </summary>
-        public Guid? Id { get; set; }
+        public Guid Id { get; set; }
+
+        /// <summary>
+        /// 鏄惁閫夋嫨锛堢敤鎴疯鑹叉巿鏉冿級
+        /// </summary>
+        public bool IsChecked { get; set; }
 
         /// <summary>
         /// 涓婄骇Id
diff --git a/FlexJobApi.Core/Models/User/Resources/Queries/GetResourcesQuery.cs b/FlexJobApi.Core/Models/User/Resources/Queries/GetResourcesQuery.cs
index 7b01d98..ad8c621 100644
--- a/FlexJobApi.Core/Models/User/Resources/Queries/GetResourcesQuery.cs
+++ b/FlexJobApi.Core/Models/User/Resources/Queries/GetResourcesQuery.cs
@@ -27,6 +27,11 @@
         /// 鍏抽敭瀛�
         /// </summary>
         public string Keywords { get; set; }
+
+        /// <summary>
+        /// 瑙掕壊Id
+        /// </summary>
+        public Guid? RoleId { get; set; }
     }
 
     /// <summary>
@@ -40,6 +45,11 @@
         public Guid Id { get; set; }
 
         /// <summary>
+        /// 鏄惁閫変腑锛堢敤浜庤鑹叉巿鏉冿級
+        /// </summary>
+        public bool IsChecked { get; set; }
+
+        /// <summary>
         /// 寰湇鍔�
         /// </summary>
         public string Service { get; set; }
diff --git a/FlexJobApi.Core/Utils/PagedListUtils/PagedListUtils.cs b/FlexJobApi.Core/Utils/PagedListUtils/PagedListUtils.cs
index 3ff720c..5bb58e6 100644
--- a/FlexJobApi.Core/Utils/PagedListUtils/PagedListUtils.cs
+++ b/FlexJobApi.Core/Utils/PagedListUtils/PagedListUtils.cs
@@ -51,12 +51,13 @@
             var entityType = typeof(T);
             int index = 0;
 
+            var props = entityType.GetProperties();
             foreach (var order in orders)
             {
                 if (string.IsNullOrEmpty(order.Property)) continue;
 
                 // 鑾峰彇鎺掑簭瀛楁鐨勫睘鎬т俊鎭�
-                var propertyInfo = entityType.GetProperty(order.Property);
+                var propertyInfo = props.FirstOrDefault(it => it.Name.Equals(order.Property, StringComparison.OrdinalIgnoreCase));
                 if (propertyInfo == null) throw Oops.Oh(EnumErrorCodeType.s404, $"璇ユ帓搴忓瓧娈祘order.Property}");
 
                 // 鍒涘缓琛ㄨ揪寮忔爲
@@ -68,15 +69,15 @@
                 if (index == 0)
                 {
                     // 棣栨鎺掑簭
-                    methodName = order.Order == EnumPagedListOrder.Ascending 
-                        ? "OrderBy" 
+                    methodName = order.Order == EnumPagedListOrder.Ascending
+                        ? "OrderBy"
                         : "OrderByDescending";
                 }
                 else
                 {
                     // 浜屾鍙婁互鍚庢帓搴�
-                    methodName = order.Order == EnumPagedListOrder.Ascending 
-                        ? "ThenBy" 
+                    methodName = order.Order == EnumPagedListOrder.Ascending
+                        ? "ThenBy"
                         : "ThenByDescending";
                 }
 
diff --git a/FlexJobApi.Core/Utils/SwaggerUtils/CustomOperationIdFilter.cs b/FlexJobApi.Core/Utils/SwaggerUtils/CustomOperationIdFilter.cs
index 0fc25b2..e199858 100644
--- a/FlexJobApi.Core/Utils/SwaggerUtils/CustomOperationIdFilter.cs
+++ b/FlexJobApi.Core/Utils/SwaggerUtils/CustomOperationIdFilter.cs
@@ -23,7 +23,7 @@
             var actionName = actionDescriptor.ActionName;
 
             // 璁剧疆鏈�缁堢殑 OperationId
-            operation.OperationId = $"{controllerName}-{actionName}";
+            operation.OperationId = $"{actionName}";
 
             var returnType = context.MethodInfo.ReturnType;
 
diff --git a/FlexJobApi.User.Application/FlexJobApi.User.Application.xml b/FlexJobApi.User.Application/FlexJobApi.User.Application.xml
index c12e7f6..8529978 100644
--- a/FlexJobApi.User.Application/FlexJobApi.User.Application.xml
+++ b/FlexJobApi.User.Application/FlexJobApi.User.Application.xml
@@ -194,12 +194,13 @@
         <member name="M:FlexJobApi.User.Application.GetMenusQueryHandler.Handle(FlexJobApi.Core.GetMenusQuery,System.Threading.CancellationToken)">
             <inheritdoc/>
         </member>
-        <member name="M:FlexJobApi.User.Application.GetMenusQueryHandler.LoopChildrens(System.Collections.Generic.List{FlexJobApi.Core.GetMenusQueryResultItem},System.Collections.Generic.List{FlexJobApi.Core.GetMenusQueryResultItem})">
+        <member name="M:FlexJobApi.User.Application.GetMenusQueryHandler.LoopChildrens(System.Collections.Generic.List{FlexJobApi.Core.GetMenusQueryResultItem},System.Collections.Generic.List{FlexJobApi.Core.GetMenusQueryResultItem},System.Collections.Generic.List{System.Guid})">
             <summary>
             閫掑綊璧嬪�间笅绾ц彍鍗�
             </summary>
             <param name="models"></param>
             <param name="all"></param>
+            <param name="roleMenuIds"></param>
         </member>
         <member name="T:FlexJobApi.User.Application.GetResourceFieldsQueryHandler">
             <summary>
diff --git a/FlexJobApi.User.Application/Menus/Queries/GetMenuQueryHandler.cs b/FlexJobApi.User.Application/Menus/Queries/GetMenuQueryHandler.cs
index 2f422db..6763485 100644
--- a/FlexJobApi.User.Application/Menus/Queries/GetMenuQueryHandler.cs
+++ b/FlexJobApi.User.Application/Menus/Queries/GetMenuQueryHandler.cs
@@ -30,6 +30,11 @@
                 .ProjectToType<GetMenuQueryResult>()
                 .FirstOrDefaultAsync(cancellationToken);
             if (model == null) throw Oops.Oh(EnumErrorCodeType.s404, "璇ヨ彍鍗�");
+            var roleMenuIds =
+                request.RoleId.HasValue
+                ? rep.Change<RoleMenu>().Where(it => it.RoleId == request.RoleId).DistinctSelect(it => it.MenuId)
+                : [];
+            model.IsChecked = roleMenuIds.Contains(model.Id);
             var items = await rep.AsQueryable().AsNoTracking()
                 .Where(it => it.ParentId == model.Id)
                 .Where(it => it.Type == EnumMenuType.Button || it.Type == EnumMenuType.Field)
@@ -40,16 +45,28 @@
                 {
                     Group = it.Key,
                     ButtonLocations = it
-                        .Where(it => it.Type == EnumMenuType.Button)
-                        .GroupBy(it => it.Location ?? "default")
-                        .Select(it => new GetMenuQueryResultButtonLocation
-                        { 
-                            Location = it.Key,
-                            Buttons = it.ToList().Adapt<List<GetMenuQueryResultButton>>()
+                        .Where(l => l.Type == EnumMenuType.Button)
+                        .GroupBy(l => l.Location ?? "default")
+                        .Select(l => new GetMenuQueryResultButtonLocation
+                        {
+                            Location = l.Key,
+                            Buttons = l
+                                .Select(b =>
+                                {
+                                    b.IsChecked = roleMenuIds.Contains(b.Id);
+                                    return b;
+                                })
+                                .ToList()
+                                .Adapt<List<GetMenuQueryResultButton>>()
                         })
                         .ToList(),
                     Fields = it
-                        .Where(it => it.Type == EnumMenuType.Field)
+                        .Where(f => f.Type == EnumMenuType.Field)
+                        .Select(f =>
+                        {
+                            f.IsChecked = roleMenuIds.Contains(f.Id);
+                            return f;
+                        })
                         .ToList()
                         .Adapt<List<GetMenuQueryResultField>>()
                 })
diff --git a/FlexJobApi.User.Application/Menus/Queries/GetMenusQueryHandler.cs b/FlexJobApi.User.Application/Menus/Queries/GetMenusQueryHandler.cs
index 323df8c..30f0999 100644
--- a/FlexJobApi.User.Application/Menus/Queries/GetMenusQueryHandler.cs
+++ b/FlexJobApi.User.Application/Menus/Queries/GetMenusQueryHandler.cs
@@ -16,20 +16,24 @@
     /// 鏌ヨ鑿滃崟鍒楄〃
     /// </summary>
     public class GetMenusQueryHandler(
-        IRepository<Menu> menuRep)
+        IRepository<Menu> rep)
         : IRequestHandler<GetMenusQuery, List<GetMenusQueryResultItem>>
     {
-        private readonly IRepository<Menu> menuRep = menuRep;
+        private readonly IRepository<Menu> rep = rep;
 
         /// <inheritdoc/>
         public async Task<List<GetMenusQueryResultItem>> Handle(GetMenusQuery request, CancellationToken cancellationToken)
         {
-            var q = menuRep.AsQueryable().AsNoTracking()
+            var q = rep.AsQueryable().AsNoTracking()
                 .Where(it => it.UserType == request.UserType && it.ClientType == request.ClientType)
                 .Where(it => it.Type == EnumMenuType.Menu || it.Type == EnumMenuType.Page || it.Type == EnumMenuType.Modal);
             var all = await q.ProjectToType<GetMenusQueryResultItem>().ToListAsync();
             var models = all.Where(it => it.ParentId == null).ToList();
-            LoopChildrens(models, all);
+            var roleMenuIds =
+                request.RoleId.HasValue
+                ? rep.Change<RoleMenu>().Where(it => it.RoleId == request.RoleId).DistinctSelect(it => it.MenuId)
+                : [];
+            LoopChildrens(models, all, roleMenuIds);
             return models;
         }
 
@@ -38,14 +42,16 @@
         /// </summary>
         /// <param name="models"></param>
         /// <param name="all"></param>
-        private void LoopChildrens(List<GetMenusQueryResultItem> models, List<GetMenusQueryResultItem> all)
+        /// <param name="roleMenuIds"></param>
+        private void LoopChildrens(List<GetMenusQueryResultItem> models, List<GetMenusQueryResultItem> all, List<Guid> roleMenuIds)
         {
             foreach (var item in models)
             {
+                item.IsChecked = roleMenuIds.Contains(item.Id);
                 item.Childrens = all.Where(it => it.ParentId == item.Id).ToList();
                 if (item.Childrens.IsNotNull())
                 {
-                    LoopChildrens(item.Childrens, all);
+                    LoopChildrens(item.Childrens, all, roleMenuIds);
                 }
             }
         }
diff --git a/FlexJobApi.User.Application/Resources/Queries/GetResourcesQueryHandler.cs b/FlexJobApi.User.Application/Resources/Queries/GetResourcesQueryHandler.cs
index 127146b..1ea5149 100644
--- a/FlexJobApi.User.Application/Resources/Queries/GetResourcesQueryHandler.cs
+++ b/FlexJobApi.User.Application/Resources/Queries/GetResourcesQueryHandler.cs
@@ -39,6 +39,16 @@
                     || it.RequestTypeName.Contains(request.Keywords)
                     || it.ResponseTypeName.Contains(request.Keywords));
             var items = await q.ProjectToType<GetResourcesQueryResultItem>().ToListAsync();
+
+            if (request.RoleId.HasValue)
+            {
+                var roleResourceIds = rep.Change<RoleResource>().Where(it => it.RoleId == request.RoleId).DistinctSelect(it => it.ResourceId);
+                foreach (var item in items)
+                {
+                    item.IsChecked = roleResourceIds.Contains(item.Id);
+                }
+            }
+
             return items;
         }
     }

--
Gitblit v1.9.1