FlexJobApi.Core/Entities/Users/Menu.cs
@@ -79,6 +79,11 @@ public string Group { get; set; } /// <summary> /// 位置(用于按钮) /// </summary> public string Location { get; set; } /// <summary> /// 列宽(用于按钮/列/元素) /// </summary> public string Width { get; set; } FlexJobApi.Core/FlexJobApi.Core.xml
@@ -864,6 +864,11 @@ 分组名称(用于按钮/字段) </summary> </member> <member name="P:FlexJobApi.Core.Menu.Location"> <summary> 位置(用于按钮) </summary> </member> <member name="P:FlexJobApi.Core.Menu.Width"> <summary> 列宽(用于按钮/列/元素) @@ -1694,7 +1699,7 @@ 模态框 </summary> </member> <member name="F:FlexJobApi.Core.EnumMenuType.Buuton"> <member name="F:FlexJobApi.Core.EnumMenuType.Button"> <summary> 按钮 </summary> @@ -1909,6 +1914,131 @@ 密码登录结果 </summary> </member> <member name="T:FlexJobApi.Core.MenuDeleteCommand"> <summary> 删除菜单 </summary> </member> <member name="T:FlexJobApi.Core.Models.MenuImportFieldCommand"> <summary> 菜单导入字段 </summary> </member> <member name="P:FlexJobApi.Core.Models.MenuImportFieldCommand.Url"> <summary> 接口地址 </summary> </member> <member name="T:FlexJobApi.Core.Models.MenuSubListQuery"> <summary> 查询按钮/字段列表 </summary> </member> <member name="P:FlexJobApi.Core.Models.MenuSubListQuery.ParentId"> <summary> 上级Id </summary> </member> <member name="P:FlexJobApi.Core.Models.MenuSubListCallbackGroup.Name"> <summary> 名称 </summary> </member> <member name="P:FlexJobApi.Core.Models.MenuSubListCallbackGroup.Buttons"> <summary> 按钮 </summary> </member> <member name="P:FlexJobApi.Core.Models.MenuSubListCallbackGroup.Fields"> <summary> 字段 </summary> </member> <member name="P:FlexJobApi.Core.Models.MenuSubListCallbackItem.Id"> <summary> Id </summary> </member> <member name="P:FlexJobApi.Core.Models.MenuSubListCallbackItem.ParentId"> <summary> 上级Id </summary> </member> <member name="P:FlexJobApi.Core.Models.MenuSubListCallbackItem.Path"> <summary> 菜单路径 </summary> </member> <member name="P:FlexJobApi.Core.Models.MenuSubListCallbackItem.Code"> <summary> 编号 </summary> </member> <member name="P:FlexJobApi.Core.Models.MenuSubListCallbackItem.Name"> <summary> 名称 </summary> </member> <member name="P:FlexJobApi.Core.Models.MenuSubListCallbackItem.Type"> <summary> 类型 </summary> </member> <member name="P:FlexJobApi.Core.Models.MenuSubListCallbackItem.VisitLevel"> <summary> 访问级别 </summary> </member> <member name="P:FlexJobApi.Core.Models.MenuSubListCallbackItem.Icon"> <summary> 图标 </summary> </member> <member name="P:FlexJobApi.Core.Models.MenuSubListCallbackItem.Url"> <summary> 链接地址 </summary> </member> <member name="P:FlexJobApi.Core.Models.MenuSubListCallbackItem.Group"> <summary> 分组名称(用于按钮/字段) </summary> </member> <member name="P:FlexJobApi.Core.Models.MenuSubListCallbackItem.Location"> <summary> 位置(用于按钮) </summary> </member> <member name="P:FlexJobApi.Core.Models.MenuSubListCallbackItem.Width"> <summary> 列宽(用于按钮/列/元素) </summary> </member> <member name="P:FlexJobApi.Core.Models.MenuSubListCallbackItem.IsDisabled"> <summary> 是否禁用 </summary> </member> <member name="P:FlexJobApi.Core.Models.MenuSubListCallbackItem.IsHidden"> <summary> 是否隐藏 </summary> </member> <member name="P:FlexJobApi.Core.Models.MenuSubListCallbackItem.IsCache"> <summary> 是否缓存 </summary> </member> <member name="P:FlexJobApi.Core.Models.MenuSubListCallbackItem.Sort"> <summary> 排序 </summary> </member> <member name="P:FlexJobApi.Core.Models.MenuSubListCallbackItem.Remark"> <summary> 备注 </summary> </member> <member name="T:FlexJobApi.Core.MenuSaveCommand"> <summary> 保存菜单 @@ -1959,6 +2089,11 @@ 分组名称(用于按钮/字段) </summary> </member> <member name="P:FlexJobApi.Core.MenuSaveCommand.Location"> <summary> 位置(用于按钮) </summary> </member> <member name="P:FlexJobApi.Core.MenuSaveCommand.Width"> <summary> 列宽(用于按钮/列/元素) @@ -1994,11 +2129,6 @@ 查询所有菜单 </summary> </member> <member name="P:FlexJobApi.Core.MenuListQuery.Types"> <summary> 类型 </summary> </member> <member name="P:FlexJobApi.Core.MenuListQuery.ParentId"> <summary> 上级Id @@ -2027,11 +2157,6 @@ <member name="P:FlexJobApi.Core.MenuListCallbackItem.ParentId"> <summary> 上级Id </summary> </member> <member name="P:FlexJobApi.Core.MenuListCallbackItem.Childrens"> <summary> 下级 </summary> </member> <member name="P:FlexJobApi.Core.MenuListCallbackItem.Path"> FlexJobApi.Core/Models/User/Menus/Commands/MenuDeleteCommand.cs
New file @@ -0,0 +1,22 @@ using MediatR; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace FlexJobApi.Core { /// <summary> /// 删除菜单 /// </summary> public class MenuDeleteCommand : IRequest { public MenuDeleteCommand() { Ids = []; } public List<Guid> Ids { get; set; } } } FlexJobApi.Core/Models/User/Menus/Commands/MenuImportFieldCommand.cs
New file @@ -0,0 +1,20 @@ using MediatR; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace FlexJobApi.Core.Models { /// <summary> /// 菜单导入字段 /// </summary> public class MenuImportFieldCommand : IRequest { /// <summary> /// 接口地址 /// </summary> public string Url { get; set; } } } FlexJobApi.Core/Models/User/Menus/Commands/MenuSaveCommand.cs
@@ -62,6 +62,11 @@ public string Group { get; set; } /// <summary> /// 位置(用于按钮) /// </summary> public string Location { get; set; } /// <summary> /// 列宽(用于按钮/列/元素) /// </summary> public string Width { get; set; } FlexJobApi.Core/Models/User/Menus/Queries/MenuListQuery.cs
FlexJobApi.Core/Models/User/Menus/Queries/MenuSubListQuery.cs
New file @@ -0,0 +1,144 @@ using MediatR; using Swashbuckle.AspNetCore.SwaggerGen; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace FlexJobApi.Core.Models { /// <summary> /// 查询按钮/字段列表 /// </summary> public class MenuSubListQuery : IRequest<MenuSubListCallback> { /// <summary> /// 上级Id /// </summary> public Guid ParentId { get; set; } } public class MenuSubListCallback { public MenuSubListCallback() { Groups = []; } public List<MenuSubListCallbackGroup> Groups { get; set; } } public class MenuSubListCallbackGroup { public MenuSubListCallbackGroup() { Buttons = []; Fields = []; } /// <summary> /// 名称 /// </summary> public string Name { get; set; } /// <summary> /// 按钮 /// </summary> public List<MenuSubListCallbackItem> Buttons { get; set; } /// <summary> /// 字段 /// </summary> public List<MenuSubListCallbackItem> Fields { get; set; } } public class MenuSubListCallbackItem { /// <summary> /// Id /// </summary> public Guid? Id { get; set; } /// <summary> /// 上级Id /// </summary> public Guid? ParentId { get; set; } /// <summary> /// 菜单路径 /// </summary> public string Path { get; set; } /// <summary> /// 编号 /// </summary> public string Code { get; set; } /// <summary> /// 名称 /// </summary> public string Name { get; set; } /// <summary> /// 类型 /// </summary> public EnumMenuType Type { get; set; } /// <summary> /// 访问级别 /// </summary> public EnumMenuVisitLevel VisitLevel { get; set; } /// <summary> /// 图标 /// </summary> public string Icon { get; set; } /// <summary> /// 链接地址 /// </summary> public string Url { get; set; } /// <summary> /// 分组名称(用于按钮/字段) /// </summary> public string Group { get; set; } /// <summary> /// 位置(用于按钮) /// </summary> public string Location { get; set; } /// <summary> /// 列宽(用于按钮/列/元素) /// </summary> public string Width { get; set; } /// <summary> /// 是否禁用 /// </summary> public bool IsDisabled { get; set; } /// <summary> /// 是否隐藏 /// </summary> public bool IsHidden { get; set; } /// <summary> /// 是否缓存 /// </summary> public bool IsCache { get; set; } /// <summary> /// 排序 /// </summary> public int Sort { get; set; } /// <summary> /// 备注 /// </summary> public string Remark { get; set; } } } FlexJobApi.Core/Utils/SwaggerUtils/CustomOperationIdFilter.cs
@@ -3,6 +3,7 @@ using Swashbuckle.AspNetCore.SwaggerGen; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -23,6 +24,29 @@ // 设置最终的 OperationId operation.OperationId = $"{controllerName}-{actionName}"; // 获取接口方法的返回类型(可能是 Task<ApiResult<T>> 或 ApiResult<T>) var returnType = context.MethodInfo.ReturnType; // 步骤 1:如果是 Task 或 Task<ApiResult<T>>,提取内部类型 if (returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(Task<>)) { returnType = returnType.GetGenericArguments()[0]; // 提取 Task<T> 中的 T } // 步骤 3:替换 Swagger 响应类型为 Data 的类型 operation.Responses.Clear(); operation.Responses.Add("200", new OpenApiResponse { Description = "操作成功", Content = new Dictionary<string, OpenApiMediaType> { ["application/json"] = new OpenApiMediaType { Schema = context.SchemaGenerator.GenerateSchema(returnType, context.SchemaRepository) } } }); } } } FlexJobApi.User.Application/FlexJobApi.User.Application.xml
@@ -39,6 +39,11 @@ {0}不存在 </summary> </member> <member name="F:FlexJobApi.User.Application.EnumUserErrorCodeType.s200"> <summary> 参数错误:{0} </summary> </member> <member name="F:FlexJobApi.User.Application.EnumUserErrorCodeType.u1000"> <summary> 账号或密码不存在 @@ -69,7 +74,14 @@ </member> <member name="M:FlexJobApi.User.Application.MenuAppService.ListQuery(FlexJobApi.Core.MenuListQuery)"> <summary> 查询菜单列表 查询菜单/页面/模态框列表 </summary> <param name="query"></param> <returns></returns> </member> <member name="M:FlexJobApi.User.Application.MenuAppService.SubListQuery(FlexJobApi.Core.Models.MenuSubListQuery)"> <summary> 查询按钮/字段列表 </summary> <param name="query"></param> <returns></returns> @@ -83,16 +95,31 @@ </member> <member name="T:FlexJobApi.User.Application.MenuListQueryHandler"> <summary> 查询所有菜单 查询菜单/页面/模态框列表 </summary> </member> <member name="M:FlexJobApi.User.Application.MenuListQueryHandler.#ctor(Furion.DatabaseAccessor.IRepository{FlexJobApi.Core.Menu})"> <summary> 查询所有菜单 查询菜单/页面/模态框列表 </summary> </member> <member name="M:FlexJobApi.User.Application.MenuListQueryHandler.Handle(FlexJobApi.Core.MenuListQuery,System.Threading.CancellationToken)"> <inheritdoc/> </member> <member name="T:FlexJobApi.User.Application.Menus.Queries.MenuSubListQueryHandler"> <summary> 查询按钮/字段列表 </summary> <param name="menuRep"></param> </member> <member name="M:FlexJobApi.User.Application.Menus.Queries.MenuSubListQueryHandler.#ctor(Furion.DatabaseAccessor.IRepository{FlexJobApi.Core.Menu})"> <summary> 查询按钮/字段列表 </summary> <param name="menuRep"></param> </member> <member name="M:FlexJobApi.User.Application.Menus.Queries.MenuSubListQueryHandler.Handle(FlexJobApi.Core.Models.MenuSubListQuery,System.Threading.CancellationToken)"> <inheritdoc/> </member> </members> </doc> FlexJobApi.User.Application/Menus/Commands/MenuImportFieldCommandHandler.cs
New file @@ -0,0 +1,12 @@ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace FlexJobApi.User.Application { internal class MenuImportFieldCommandHandler { } } FlexJobApi.User.Application/Menus/MenuAppService.cs
@@ -1,4 +1,5 @@ using FlexJobApi.Core; using FlexJobApi.Core.Models; using Furion.DynamicApiController; using MediatR; using Microsoft.AspNetCore.Mvc; @@ -29,6 +30,16 @@ } /// <summary> /// 查询按钮/字段列表 /// </summary> /// <param name="query"></param> /// <returns></returns> public async Task<MenuSubListCallback> SubListQuery(MenuSubListQuery query) { return await mediator.Send(query); } /// <summary> /// 保存菜单 /// </summary> /// <param name="command"></param> FlexJobApi.User.Application/Menus/Queries/MenuSubListQueryHandler.cs
New file @@ -0,0 +1,43 @@ using FlexJobApi.Core; using FlexJobApi.Core.Models; using Furion.DatabaseAccessor; 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.Menus.Queries { /// <summary> /// 查询按钮/字段列表 /// </summary> /// <param name="menuRep"></param> public class MenuSubListQueryHandler(IRepository<Menu> menuRep) : IRequestHandler<MenuSubListQuery, MenuSubListCallback> { private readonly IRepository<Menu> menuRep = menuRep; /// <inheritdoc/> public async Task<MenuSubListCallback> Handle(MenuSubListQuery request, CancellationToken cancellationToken) { var callback = new MenuSubListCallback(); var q = menuRep.AsQueryable().AsNoTracking() .Where(it => it.ParentId == request.ParentId) .Where(it => it.Type == EnumMenuType.Button || it.Type == EnumMenuType.Field); var items = await q.ProjectToType<MenuSubListCallbackItem>().ToListAsync(cancellationToken); callback.Groups = items.GroupBy(it => it.Group ?? "Default") .Select(it => new MenuSubListCallbackGroup { Name = it.Key, Buttons = it.Where(g => g.Type == EnumMenuType.Button).ToList(), Fields = it.Where(g => g.Type == EnumMenuType.Field).ToList(), }) .ToList(); return callback; } } }