feat: 动态API支持直接执行已有的应用逻辑

This commit is contained in:
wintel 2025-03-30 18:01:22 +08:00
parent d42be4d7c9
commit dfbb150f9b
4 changed files with 106 additions and 25 deletions
OpenAuth.App
OpenAuth.WebApi/Controllers

View File

@ -14,15 +14,17 @@ namespace OpenAuth.App
/// 动态API应用层
/// 用于直接操作数据库表,不依赖实体
/// </summary>
public class DynamicApiApp
public class DynamicApiApp
{
private readonly ISqlSugarClient _client;
private readonly IAuth _auth;
private readonly IServiceProvider _serviceProvider;
public DynamicApiApp(ISqlSugarClient client, IAuth auth)
public DynamicApiApp(ISqlSugarClient client, IAuth auth, IServiceProvider serviceProvider)
{
_client = client;
_auth = auth;
_serviceProvider = serviceProvider;
}
/// <summary>
@ -48,14 +50,14 @@ namespace OpenAuth.App
// 获取表结构
var columns = GetTableColumns(req.TableName);
// 如果有搜索关键字,尝试在常见字段中搜索
if (!string.IsNullOrEmpty(req.key))
{
//todo: 尝试在Name、Title等常见字段中搜索
var nameColumn = columns.FirstOrDefault(c =>
var nameColumn = columns.FirstOrDefault(c =>
c.DbColumnName.Equals("Name", StringComparison.OrdinalIgnoreCase));
if (nameColumn != null)
{
queryable = queryable.Where($"{nameColumn.DbColumnName} like @key", new { key = $"%{req.key}%" });
@ -64,10 +66,10 @@ namespace OpenAuth.App
// 获取总记录数
var total = await queryable.CountAsync();
// 分页查询
var list = await queryable
.OrderBy($"{ columns[0].DbColumnName } DESC")
.OrderBy($"{columns[0].DbColumnName} DESC")
.Skip((req.page - 1) * req.limit)
.Take(req.limit)
.ToListAsync();
@ -108,14 +110,14 @@ namespace OpenAuth.App
.AS(req.TableName)
.Where("Id = @id", new { id = req.Id })
.FirstAsync();
if (entity == null)
{
result.Code = 500;
result.Message = "未找到记录";
return result;
}
result.Result = entity;
}
catch (Exception ex)
@ -150,7 +152,7 @@ namespace OpenAuth.App
// 将对象转换为字典
var dict = req.Obj.ToDictionary();
// 设置ID
if (!dict.ContainsKey("Id"))
{
@ -173,19 +175,19 @@ namespace OpenAuth.App
result.Message = "Id已存在";
return result;
}
}
}
//如果有CreateTime字段自动设置
if (dict.ContainsKey("CreateTime"))
{
dict["CreateTime"] = DateTime.Now;
}
// 添加数据
await _client.Insertable(dict)
.AS(req.TableName)
.ExecuteCommandAsync();
result.Message = "添加成功";
}
catch (Exception ex)
@ -218,7 +220,7 @@ namespace OpenAuth.App
// 将对象转换为字典
var dict = req.Obj.ToDictionary();
// 检查ID是否存在
if (!dict.ContainsKey("Id"))
{
@ -226,13 +228,13 @@ namespace OpenAuth.App
result.Message = "更新数据必须包含Id字段";
return result;
}
// 如果有UpdateTime字段自动设置
if (dict.ContainsKey("UpdateTime"))
{
dict["UpdateTime"] = DateTime.Now;
}
// 如果有用户信息,设置更新用户
var currentUser = _auth.GetCurrentUser();
if (dict.ContainsKey("UpdateUserId") && currentUser != null)
@ -247,7 +249,7 @@ namespace OpenAuth.App
.AS(req.TableName)
.WhereColumns("Id") // 使用Id作为更新条件
.ExecuteCommandAsync();
result.Message = "更新成功";
}
catch (Exception ex)
@ -283,7 +285,7 @@ namespace OpenAuth.App
.AS(req.TableName)
.Where("Id in (@ids)", new { ids = req.Ids })
.ExecuteCommandAsync();
result.Message = "批量删除成功";
}
catch (Exception ex)
@ -305,7 +307,7 @@ namespace OpenAuth.App
// 获取数据库类型
var dbType = _client.CurrentConnectionConfig.DbType;
string sql = string.Empty;
switch (dbType)
{
case DbType.SqlServer:
@ -323,7 +325,7 @@ namespace OpenAuth.App
default:
throw new NotSupportedException($"不支持的数据库类型:{dbType}");
}
var count = _client.Ado.GetInt(sql);
return count > 0;
}
@ -337,6 +339,27 @@ namespace OpenAuth.App
{
return _client.DbMaintenance.GetColumnInfosByTableName(tableName);
}
/// <summary>
/// 调用OpenAuth.App的各种应用
/// </summary>
/// <param name="req">调用参数</param>
/// <returns></returns>
public TableData Invoke(InvokeDynamicReq req)
{
// 获取服务实例
var serviceType = Type.GetType($"OpenAuth.App.{req.ServiceName}");
var service = _serviceProvider.GetService(serviceType);
// 获取并调用方法
var method = serviceType.GetMethod(req.MethodName);
var result = method.Invoke(service, new[] { req.Parameters });
return new TableData
{
data = result,
};
}
}
/// <summary>
@ -352,15 +375,15 @@ namespace OpenAuth.App
public static Dictionary<string, object> ToDictionary(this object obj)
{
var dict = new Dictionary<string, object>();
if (obj == null) return dict;
// 如果已经是字典类型,直接返回
if (obj is Dictionary<string, object> dictionary)
{
return dictionary;
}
// 获取所有属性
foreach (var prop in obj.GetType().GetProperties())
{
@ -370,7 +393,7 @@ namespace OpenAuth.App
dict[prop.Name] = value;
}
}
return dict;
}
}

View File

@ -0,0 +1,21 @@
namespace OpenAuth.App.Request
{
public class InvokeDynamicReq
{
/// <summary>
/// 服务名称,如OpenAuth.App.MoudleApp
/// </summary>
public string ServiceName { get; set; }
/// <summary>
/// 方法名称,如Add
/// </summary>
public string MethodName { get; set; }
/// <summary>
/// 参数,如:{ "Id": 1, "Name": "test" }
/// </summary>
public object Parameters { get; set; }
}
}

View File

@ -73,5 +73,15 @@ namespace OpenAuth.App.Test
var obj = await app.Delete(new DelDynamicReq() { TableName = "noentity", Ids = new string[] { "10" } });
Console.WriteLine(JsonHelper.Instance.Serialize(obj));
}
[Test]
public void TestInvoke()
{
var app = _autofacServiceProvider.GetService<DynamicApiApp>();
var obj = app.Invoke(new InvokeDynamicReq { ServiceName = "UserManagerApp", MethodName = "GetParent",
Parameters = new { userid = "0ceff0f8-f848-440c-bc26-d8605ac858cd" } });
Console.WriteLine(JsonHelper.Instance.Serialize(obj));
}
}
}

View File

@ -11,7 +11,7 @@ namespace OpenAuth.WebApi.Controllers
{
/// <summary>
/// 动态API控制器
/// 用于处理任意表的CRUD操作
/// 用于处理任意表的CRUD操作及直接调用OpenAuth.App的各种应用
/// </summary>
[Route("api/dynamic/[action]")]
[ApiController]
@ -25,6 +25,8 @@ namespace OpenAuth.WebApi.Controllers
_app = app;
}
/// <summary>
/// 获取表数据列表
/// </summary>
@ -145,5 +147,30 @@ namespace OpenAuth.WebApi.Controllers
return result;
}
/// <summary>
/// 直接调用OpenAuth.App的各种应用
/// </summary>
/// <param name="req">调用参数</param>
/// <returns></returns>
[HttpPost]
[AllowAnonymous]
public TableData Invoke([FromBody] InvokeDynamicReq req)
{
var result = new TableData();
try
{
result = _app.Invoke(req);
}
catch (Exception ex)
{
result.code = 500;
result.msg = ex.InnerException?.Message ?? ex.Message;
}
return result;
}
}
}