diff --git a/src/5.shared/ATS.NonCustodial.AdminUi/Helpers/Logs/ApiHelper.cs b/src/5.shared/ATS.NonCustodial.AdminUi/Helpers/Logs/ApiHelper.cs
new file mode 100644
index 0000000..4ecfe89
--- /dev/null
+++ b/src/5.shared/ATS.NonCustodial.AdminUi/Helpers/Logs/ApiHelper.cs
@@ -0,0 +1,85 @@
+using ATS.NonCustodial.Application.Contracts.Interfaces.Admins.Api;
+using ATS.NonCustodial.Application.Contracts.Interfaces.Admins.Api.Output;
+using ATS.NonCustodial.Shared.Common.Attributes;
+using ATS.NonCustodial.Shared.Common.UnifiedResults;
+using ATS.NonCustodial.Shared.Extensions;
+
+namespace ATS.NonCustodial.AdminUi.Helpers.Logs
+{
+ ///
+ /// Api帮助类
+ ///
+ /// Author:mxg
+ /// CreatedTimed:2022-05-18 09:46 AM
+ [SingleInstance]
+ public class ApiHelper
+ {
+ #region Identity
+
+ private List _apis;
+ private static readonly object LockObject = new();
+ private readonly IApiService _apiService;
+
+ public ApiHelper(IApiService apiService)
+ {
+ _apiService = apiService;
+ }
+
+ #endregion Identity
+
+ ///
+ /// 主要是在Action 操作的时候添加操作日志时候用
+ ///
+ ///
+ public List GetApis()
+ {
+ if (_apis != null && _apis.Any()) return _apis;
+
+ lock (LockObject)
+ {
+ if (_apis != null && _apis.Any()) return _apis;
+
+ _apis = new List();
+
+ var apis = ((ResultOutput>)_apiService.GetListAsync("").Result)
+ .Data
+ .Select(a => new
+ {
+ a.Id,
+ a.ParentId,
+ a.Label,
+ a.Path
+ });
+
+ foreach (var api in apis)
+ {
+ var parentLabel = apis.FirstOrDefault(a => a.Id == api.ParentId)?.Label;
+
+ _apis.Add(new ApiHelperDto
+ {
+ Label = parentLabel.NotNull() ? $"{parentLabel} / {api.Label}" : api.Label,
+ Path = api.Path?.ToLower().Trim('/')
+ });
+ }
+
+ return _apis;
+ }
+ }
+ }
+
+ ///
+ ///
+ ///
+ public class ApiHelperDto
+ {
+ ///
+ /// 接口名称
+ ///
+ public string Label { get; set; }
+
+ ///
+ /// 接口地址
+ ///
+ public string Path { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/5.shared/ATS.NonCustodial.AdminUi/Helpers/Logs/ILogHandler.cs b/src/5.shared/ATS.NonCustodial.AdminUi/Helpers/Logs/ILogHandler.cs
new file mode 100644
index 0000000..3eacae8
--- /dev/null
+++ b/src/5.shared/ATS.NonCustodial.AdminUi/Helpers/Logs/ILogHandler.cs
@@ -0,0 +1,20 @@
+using Microsoft.AspNetCore.Mvc.Filters;
+
+namespace ATS.NonCustodial.AdminUi.Helpers.Logs
+{
+ ///
+ /// 操作日志处理接口
+ ///
+ /// Author:mxg
+ /// CreatedTimed:2022-05-18 09:46 AM
+ public interface ILogHandler
+ {
+ ///
+ /// 写操作日志
+ ///
+ ///
+ ///
+ ///
+ Task LogAsync(ActionExecutingContext context, ActionExecutionDelegate next);
+ }
+}
\ No newline at end of file
diff --git a/src/5.shared/ATS.NonCustodial.AdminUi/Helpers/Logs/LogHandler.cs b/src/5.shared/ATS.NonCustodial.AdminUi/Helpers/Logs/LogHandler.cs
new file mode 100644
index 0000000..267a1e7
--- /dev/null
+++ b/src/5.shared/ATS.NonCustodial.AdminUi/Helpers/Logs/LogHandler.cs
@@ -0,0 +1,175 @@
+using ATS.NonCustodial.Application.Contracts.Interfaces.Logs.OprationLog;
+using ATS.NonCustodial.Application.Contracts.Interfaces.Logs.OprationLog.Input;
+using ATS.NonCustodial.AuditLogging.AuditLoggings.Services;
+using ATS.NonCustodial.Shared.Common.UnifiedResults;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.Controllers;
+using Microsoft.AspNetCore.Mvc.Filters;
+using Microsoft.Extensions.Logging;
+using Newtonsoft.Json;
+using System.Diagnostics;
+using System.Reflection;
+
+namespace ATS.NonCustodial.AdminUi.Helpers.Logs
+{
+ ///
+ /// 控制器操作日志记录 ==> 操作日志处理
+ ///
+ /// Author:mxg
+ /// CreatedTimed:2022-05-18 09:46 AM
+ public class LogHandler : ILogHandler
+ {
+ #region Identity
+
+ private readonly ILogger _logger;
+ private readonly ApiHelper _apiHelper;
+ private readonly IOperationLogService _operationLogService;
+ private readonly IAuditEventLogger _auditEventLogger;
+
+ public LogHandler(
+ ILogger logger,
+ ApiHelper apiHelper,
+ IOperationLogService operationLogService,
+ IAuditEventLogger auditEventLogger
+ )
+ {
+ _logger = logger;
+ _apiHelper = apiHelper;
+ _operationLogService = operationLogService;
+ _auditEventLogger = auditEventLogger;
+ }
+
+ #endregion Identity
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public async Task LogAsync(ActionExecutingContext context, ActionExecutionDelegate next)
+ {
+ var sw = new Stopwatch();
+ sw.Start();
+ //调用接口
+ var actionExecutedContext = await next();
+ sw.Stop();
+
+ try
+ {
+ //接口Type
+ var controllerType = (context.ActionDescriptor as ControllerActionDescriptor)?.ControllerTypeInfo.AsType().GetSummary();
+
+ //方法信息
+ var controllerAction = (context.ActionDescriptor as ControllerActionDescriptor)?.MethodInfo.GetSummary();
+
+ var input = new OprationLogAddInput
+ {
+ ApiLabel = $"{controllerType}/{controllerAction}".Trim('/'),
+ ApiMethod = context.HttpContext.Request.Method.ToLower(),
+ ApiPath = context.ActionDescriptor.AttributeRouteInfo?.Template?.ToLower(),
+ ElapsedMilliseconds = sw.ElapsedMilliseconds,
+ Params = JsonConvert.SerializeObject(context.ActionArguments)
+ };
+
+ if (actionExecutedContext.Result is ObjectResult { Value: IResultOutput res })
+ {
+ input.Status = res.Success;
+ input.Msg = res.Msg;
+ }
+
+ #region 设置参数
+
+ //switch (context.HttpContext.Request.Method)
+ //{
+ // case "GET":
+ // case "DELETE":
+ // input.Params = context.HttpContext.Request.Path;
+ // break;
+ // case "PUT":
+ // case "POST":
+ // context.HttpContext.Request.EnableBuffering();
+ // context.HttpContext.Request.Body.Position = 0;
+ // StreamReader reader = new StreamReader(context.HttpContext.Request.Body, Encoding.UTF8);
+ // input.Params = reader.ReadToEndAsync().GetAwaiter().GetResult();
+ // context.HttpContext.Request.Body.Position = 0;
+ // break;
+ // default: break;
+ //}
+ //if (input.Params is { Length: > 1024 })
+ //{
+ // input.Params = input.Params.Substring(0, 1021) + "...";
+ //}
+
+ #endregion 设置参数
+
+ #region 设置返回值
+
+ try
+ {
+ if (actionExecutedContext.Exception != null && !actionExecutedContext.ExceptionHandled)
+ {
+ input.Exception = actionExecutedContext.Exception.StackTrace;
+ }
+ }
+ catch (Exception ex)
+ {
+ input.Exception = ex.StackTrace;
+ throw;
+ }
+ finally
+ {
+ if (input.Exception is { Length: > 2048 })
+ {
+ input.Exception = input.Exception.Substring(0, 2045) + "...";
+ }
+
+ if (actionExecutedContext != null)
+ {
+ input.Result = actionExecutedContext.Result switch
+ {
+ ObjectResult objectResult => JsonConvert.SerializeObject(objectResult.Value),
+ JsonResult jsonResult => JsonConvert.SerializeObject(jsonResult.Value),
+ ContentResult contentResult => contentResult.Content,
+ _ => input.Result
+ };
+ if (input.Result is { Length: > 2048 })
+ {
+ input.Result = input.Result.Substring(0, 2045) + "...";
+ }
+ }
+ }
+
+ #endregion 设置返回值
+
+ //接口名称
+ //input.ApiLabel = _apiHelper.GetApis().FirstOrDefault(a => a.Path == input.ApiPath)?.Label;
+
+ //添加操作日志
+ await _operationLogService.AddAsync(input);
+
+ #region 添加审计日志
+
+ //var apiAuditLog = new CustomizedLogEvent()
+ //{
+ // Category = nameof(CustomizedLogEvent),
+ // SubjectType = AuditSubjectTypes.machine,
+ // SubjectName = Environment.MachineName,
+ // SubjectIdentifier = Environment.MachineName,
+ // Action = new { Method = input.ApiPath, Class = context.Controller.ToString() }
+ //};
+ //await _auditEventLogger.LogEventAsync(apiAuditLog, options =>
+ //{
+ // options.UseDefaultSubject = false;
+ // options.UseDefaultAction = false;
+ //});
+
+ #endregion 添加审计日志
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError("操作日志插入异常:{@ex}", ex);
+ }
+ }
+ }
+}
\ No newline at end of file