qinchaoyue před 3 měsíci
rodič
revize
c8c44635e7

+ 157 - 9
src/Hotline.Api/Controllers/ExportData/ExportDataController.cs

@@ -1,23 +1,171 @@
-using Microsoft.AspNetCore.Components;
+using Hotline.Application.ExportExcel;
+using Hotline.Share.Dtos.Order;
+using Hotline.Share.Dtos.Snapshot;
+using Hotline.Share.Tools;
 using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Routing;
+using MongoDB.Bson.IO;
+using SqlSugar;
+using System.ComponentModel;
+using System.Reflection;
+using System.Text.Json;
+using XF.Domain.Dependency;
+using XF.Domain.Exceptions;
 
 namespace Hotline.Api.Controllers.ExportData;
 
 [ApiController]
-[Microsoft.AspNetCore.Mvc.Route("{*path:regex(.*export_data$)}")]
+[Route("{*path:regex(.*export_excel$)}")]
 public class ExportDataController : BaseController
 {
-    [HttpGet]
-    public IActionResult HandleExport()
+
+    private readonly IServiceProvider _serviceProvider;
+    private readonly EndpointDataSource _endpointDataSource;
+    private readonly IExportApplication _exportApplication;
+
+    public ExportDataController(IServiceProvider serviceProvider, EndpointDataSource endpointDataSource, IExportApplication exportApplication)
     {
-        // 处理 GET 请求
-        return Ok("This is a GET export request.");
+        _serviceProvider = serviceProvider;
+        _endpointDataSource = endpointDataSource;
+        _exportApplication = exportApplication;
     }
 
+    /// <summary>
+    /// 动态导出数据
+    /// </summary>
+    /// <returns></returns>
     [HttpPost]
-    public IActionResult HandleExportPost()
+    public async Task<FileStreamResult> HandleExportPost()
+    {
+        var fullPath = HttpContext.Request.Path.Value;
+        var originalPath = fullPath?.Substring(0, fullPath.LastIndexOf("/export_excel")).TrimStart('/');
+        if (string.IsNullOrEmpty(originalPath))
+            throw UserFriendlyException.SameMessage("Invalid export path.");
+
+        var matchingEndpoint = _endpointDataSource.Endpoints
+            .OfType<RouteEndpoint>()
+            .FirstOrDefault(endpoint => endpoint.RoutePattern.RawText == originalPath);
+
+        if (matchingEndpoint == null)
+            throw UserFriendlyException.SameMessage($"No route matches '{originalPath}'.");
+
+        var controllerName = matchingEndpoint.RoutePattern.RequiredValues["controller"]?.ToString();
+        var actionName = matchingEndpoint.RoutePattern.RequiredValues["action"]?.ToString();
+
+        var applicationServiceType = GetApplicationServiceType(controllerName);
+        if (applicationServiceType == null)
+            throw UserFriendlyException.SameMessage($"Application service for '{controllerName}' not found.");
+
+        var method = applicationServiceType.GetMethod(actionName);
+        if (method == null)
+        {
+            method = applicationServiceType.GetMethod(actionName + "Async");
+            if (method == null)
+                throw UserFriendlyException.SameMessage($"Action '{actionName}' not found in Application service.");
+        }
+
+        var serviceInstance = _serviceProvider.GetService(applicationServiceType);
+        if (serviceInstance == null)
+        {
+            serviceInstance = _serviceProvider.GetService(applicationServiceType.GetInterfaces()[0]);
+            if (serviceInstance == null)
+                throw UserFriendlyException.SameMessage($"Unable to create instance of Application service '{applicationServiceType.Name}'.");
+        }
+
+        try
+        {
+            var parameters = method.GetParameters();
+
+            using var reader = new StreamReader(HttpContext.Request.Body);
+            var body = await reader.ReadToEndAsync();
+            var param = parameters[0];
+            var genericType = typeof(ExportExcelDto<>).MakeGenericType(param.ParameterType);
+            var exportData = body.FromJson(genericType);
+            var queryDto = genericType.GetProperty("QueryDto")?.GetValue(exportData);
+            var isExportAll = genericType.GetProperty("IsExportAll")?.GetValue(exportData);
+            var pageIndex = param.ParameterType.GetProperty("PageIndex")?.GetValue(queryDto);
+            var pageSize = param.ParameterType.GetProperty("PageSize")?.GetValue(queryDto);
+            var result = method.Invoke(serviceInstance, [queryDto]);
+
+            var returnType = method.ReturnType.GetGenericArguments()[0];
+            var description = method.GetCustomAttribute<DescriptionAttribute>()?.Description;
+
+            return _exportApplication.GetExcelFile(returnType, genericType, exportData, ConvertToList(result, (bool)isExportAll, (int)pageIndex, (int)pageSize), description);
+
+        }
+        catch (Exception e)
+        {
+            var msg = e.Message;
+            throw;
+        }
+        throw UserFriendlyException.SameMessage("失败");
+    }
+
+    public static List<object>? ConvertToList(object? result, bool isExportAll, int pageIndex, int pageSize)
     {
-        // 处理 POST 请求
-        return Ok("This is a POST export request.");
+        if (result == null)
+        {
+            return null;
+        }
+
+        var type = result.GetType();
+
+        if (!type.IsGenericType || type.GetGenericTypeDefinition() != typeof(PostgreSQLQueryable<>))
+        {
+            throw UserFriendlyException.SameMessage("被导出方法的返回类型不是 ISugarQueryable");
+        }
+
+        var genericArgument = type.GetGenericArguments()[0];
+
+        if (isExportAll)
+        {
+            var toListMethod = type.GetMethods()
+            .Where(m => m.Name == "ToList" && m.GetParameters().Length == 0)
+            .First();
+            var list = toListMethod.Invoke(result, null) as IEnumerable<object>;
+            return list?.ToList();
+        }
+        else
+        {
+            var toListMethod = type.GetMethods()
+            .Where(m => m.Name == "ToPageList" && m.GetParameters().Length == 2)
+            .First();
+            var list = toListMethod.Invoke(result, [pageIndex, pageSize]) as IEnumerable<object>;
+            return list?.ToList();
+        }
     }
+
+    private Type GetApplicationServiceType(string controllerName)
+    {
+        // 根据约定规则,将 Controller 映射到 Application 服务类
+        // 假设 Application 服务类命名规则为 "{ControllerName}Application"
+        var applicationServiceName = $"Hotline.Application.Snapshot.{controllerName}Application";
+        var name = controllerName + "Application";
+
+        var type = AppDomain.CurrentDomain.GetAssemblies().ToList()
+        .SelectMany(d => d.GetTypes())
+           .Where(d => d.Name == name)
+           .First();
+        return type;
+    }
+
+    private async Task<object[]> BindMethodParameters(System.Reflection.MethodInfo method)
+    {
+        // 动态解析方法的参数绑定
+        var parameters = method.GetParameters();
+        var result = new List<object>();
+
+        foreach (var param in parameters)
+        {
+            using var reader = new StreamReader(HttpContext.Request.Body);
+            var body = await reader.ReadToEndAsync();
+            var genericType = typeof(ExportExcelDto<>).MakeGenericType(param.ParameterType);
+            var deserializedObject = body.FromJson(genericType);
+            var queryDto = genericType.GetProperty("QueryDto")?.GetValue(deserializedObject);
+            result.Add(queryDto);
+        }
+
+        return result.ToArray();
+    }
+
 }

+ 17 - 0
src/Hotline.Api/Controllers/TestController.cs

@@ -73,6 +73,11 @@ using static System.Runtime.InteropServices.JavaScript.JSType;
 using Order = Hotline.Orders.Order;
 using Hotline.Share.Dtos.Settings;
 using OrderDto = Hotline.Share.Dtos.Order.OrderDto;
+using Hotline.Share.Dtos.Home;
+using Google.Protobuf.WellKnownTypes;
+using Microsoft.AspNetCore.DataProtection;
+using Hotline.Share.Tools;
+using NETCore.Encrypt;
 using Hotline.Ai.Quality;
 
 namespace Hotline.Api.Controllers;
@@ -1462,4 +1467,16 @@ ICallApplication callApplication,
 
 	}
 
+    /// <summary>
+    /// 加密验证
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpPost("check_token")]
+    [AllowAnonymous]
+    public async Task<string> CheckAES([FromBody] CheckTokenDto dto)
+    {
+        var strString = dto.AppId + dto.Timestamp;
+        return dto.AppId + EncryptProvider.AESEncrypt(strString, dto.Secret, dto.AppId);
+    }
 }

+ 1 - 0
src/Hotline.Api/Hotline.Api.csproj

@@ -16,6 +16,7 @@
     <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.10" />
     <PackageReference Include="Microsoft.AspNetCore.SignalR.StackExchangeRedis" Version="8.0.10" />
     <PackageReference Include="MiniExcel" Version="1.36.0" />
+    <PackageReference Include="NETCore.Encrypt" Version="2.1.1" />
     <PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
     <PackageReference Include="Serilog.Sinks.Grafana.Loki" Version="8.3.0" />
     <PackageReference Include="Serilog.Sinks.MongoDB" Version="6.0.0" />

+ 0 - 7
src/Hotline.Api/StartupExtensions.cs

@@ -40,7 +40,6 @@ using Microsoft.AspNetCore.ResponseCompression;
 using Hotline.WeChat;
 using Hotline.Snapshot.Interfaces;
 using TianQue.Sdk;
-using Hotline.Settings.SystemLogDomain;
 using Hotline.Application.Snapshot;
 using Hotline.Orders;
 using XF.Domain.Repository.Events;
@@ -137,9 +136,6 @@ internal static class StartupExtensions
         //mediatr
         services.RegisterMediatR(appConfiguration);
 
-        services.AddScoped<LoggingInterceptor>();
-        services.AddScoped<AsyncLoggingInterceptor>();
-
         //app scope
         switch (appConfiguration.AppScope)
         {
@@ -155,14 +151,11 @@ internal static class StartupExtensions
                 services.AddYbEnterpriseSdk(appConfiguration.YiBin.Enterprise.AddressUrl)
                     .AddKeyedScoped<ISessionContext, YbEnterpriseSessionContext>(YbEnterpriseSessionContext.Key)
                     .AddKeyedScoped<ISessionContext, ZzptSessionContext>(ZzptSessionContext.Key);
-                //services.AddProxiedScoped<ISnapshotApplication, DefaultSnapshotApplication>();
                 break;
             case AppDefaults.AppScope.ZiGong:
 				services.AddAiXingTang(appConfiguration.ZiGong.AiQuality.Url);
-				//services.AddProxiedScoped<ISnapshotApplication, ZiGongSnapshotApplication>();
                 break;
             case AppDefaults.AppScope.LuZhou:
-                //services.AddProxiedScoped<ISnapshotApplication, DefaultSnapshotApplication>();
                 break;
         }
 

+ 40 - 0
src/Hotline.Application.Tests/Application/ThirdIdentifyApplicationTest.cs

@@ -0,0 +1,40 @@
+using NETCore.Encrypt.Internal;
+using NETCore.Encrypt;
+using Org.BouncyCastle.Asn1.IsisMtt.X509;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using NETCore.Encrypt.Extensions;
+using Hotline.Share.Tools;
+using System.Security.Cryptography;
+
+namespace Hotline.Application.Tests.Application;
+public class ThirdIdentifyApplicationTest
+{
+    [Fact]
+    public async Task ThirdSystem_Test()
+    {
+        var appId = "companyName";
+        var secret = "4x1q6YCWLDnHkpLTCWMwx3XQF7bA5QAd";
+
+
+        var iv = Guid.NewGuid().ToString().Substring(0, 16);
+
+
+        var unixTimespan = DateTimeOffset.Now.ToUnixTimeSeconds();
+        var strString = appId + unixTimespan;
+        var entrypted = EncryptProvider.AESEncrypt(strString, secret, iv);
+        var token = appId + iv + entrypted;
+
+        var decrypted = EncryptProvider.AESDecrypt(entrypted, secret, iv);
+        Console.WriteLine(decrypted);
+
+
+                                                        //"4x1q6YCWLDnHkpLTCWMwx3XQF7bA5QAd   WD7MEjbCySsniwKz
+        entrypted = EncryptProvider.AESEncrypt(strString, "NBdabUfdsabwB7382fdsab18v321udab");
+        decrypted = EncryptProvider.AESDecrypt(entrypted, "NBdabUfdsabwB7382fdsab18v321udab");
+        Console.WriteLine(decrypted);
+    }
+}

+ 1 - 0
src/Hotline.Application.Tests/Hotline.Application.Tests.csproj

@@ -26,6 +26,7 @@
     <PackageReference Include="coverlet.collector" Version="3.2.0" />
     <PackageReference Include="Microsoft.AspNetCore.TestHost" Version="7.0.20" />
     <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.1" />
+    <PackageReference Include="NETCore.Encrypt" Version="2.1.1" />
     <PackageReference Include="Senparc.Weixin" Version="6.19.1" />
     <PackageReference Include="Senparc.Weixin.AspNet" Version="1.3.1" />
     <PackageReference Include="Senparc.Weixin.WxOpen" Version="3.20.1" />

+ 0 - 5
src/Hotline.Application.Tests/Startup.cs

@@ -63,7 +63,6 @@ using Hotline.Snapshot.Interfaces;
 using TianQue.Sdk;
 using Hotline.Snapshot.Notifications;
 using Hotline.File;
-using Hotline.Settings.SystemLogDomain;
 using Hotline.Application.Tests.Mock.Interfaces;
 using Hotline.Orders.DatabaseEventHandler;
 using Hotline.Orders;
@@ -194,11 +193,7 @@ public class Startup
             services.AddScoped<IFileDomainService, FileDomainService>();
             services.AddXingTangDb(callCenterConfiguration.XingTang);
             services.AddScoped<IGuiderSystemService, TiqnQueService>();
-            services.AddScoped<LoggingInterceptor>();
-            services.AddScoped<AsyncLoggingInterceptor>();
 
-            // application services
-            services.AddProxiedScoped<ISnapshotApplication, DefaultSnapshotApplication>();
             //ServiceLocator.Instance = services.BuildServiceProvider();
         }
 

+ 20 - 0
src/Hotline.Application/ExportExcel/ExportApplication.cs

@@ -11,6 +11,7 @@ using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.Extensions.DependencyInjection;
 using MiniExcelLibs;
+using NPOI.HPSF;
 using System.Net.Http;
 using System.Reflection;
 using XF.Domain.Dependency;
@@ -67,6 +68,25 @@ namespace Hotline.Application.ExportExcel
             return GetExcelStream(dto, items, func).GetExcelFile(fileName);
         }
 
+        public FileStreamResult GetExcelFile(Type typeT, Type typeD, object dto, IList<object> items, string fileName)
+        {
+            var columnInfos = typeD.GetProperty("ColumnInfos")?.GetValue(dto) as List<ColumnInfo>;
+            if (columnInfos == null)
+            {
+                throw new ArgumentException("ColumnInfos not found in dto");
+            }
+
+            dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(columnInfos);
+
+            var dtos = items
+                .Select(item => _mapper.Map(item, typeT, dynamicClass))
+                .Cast<object>()
+                .ToList();
+
+            return ExcelHelper.CreateStream(dtos).GetExcelFile(fileName);
+        }
+
+
         public FileStreamResult GetExcelFile<T, D>(ExportExcelDto<D> dto, IList<T> items, string fileName, string totalName) where T : new()
         {
             var fieldsAll = typeof(T).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

+ 2 - 0
src/Hotline.Application/ExportExcel/IExportApplication.cs

@@ -26,6 +26,8 @@ namespace Hotline.Application.ExportExcel
 
         FileStreamResult GetExcelFile<T, D>(ExportExcelDto<D> dto, IList<T> items,string fileName, Func<IList<T>, T>? func = null);
 
+        FileStreamResult GetExcelFile(Type typeT, Type typeD, object dto, IList<object> items, string fileName);
+
         /// <summary>
         /// 导入数据
         /// </summary>

+ 1 - 2
src/Hotline.Application/Snapshot/ISnapshotApplication.cs

@@ -1,5 +1,4 @@
-using Hotline.Settings.SystemLogDomain;
-using Hotline.Share.Dtos;
+using Hotline.Share.Dtos;
 using Hotline.Share.Dtos.Article;
 using Hotline.Share.Dtos.Snapshot;
 using Hotline.Snapshot;

+ 4 - 0
src/Hotline.Application/Snapshot/IndustryApplication.cs

@@ -13,6 +13,7 @@ using Mapster;
 using SqlSugar;
 using System;
 using System.Collections.Generic;
+using System.ComponentModel;
 using System.Linq;
 using System.Text;
 using System.Threading;
@@ -71,6 +72,7 @@ public class IndustryApplication : IIndustryApplication, IScopeDependency
         return id;
     }
 
+    [Description("行业集合")]
     public ISugarQueryable<IndustryItemsOutDto> GetIndustres(IndustryListInDto dto)
     {
         var query = _industryRepository.Queryable()
@@ -122,6 +124,7 @@ public class IndustryApplication : IIndustryApplication, IScopeDependency
     }
 
     #region 行业线索
+    [Description("行业线索")]
     public ISugarQueryable<IndustryCaseItemOutDto> GetIndustryCaseItems(IndustryCaseItemInDto dto)
     {
         var query = _industryCaseRepository.Queryable()
@@ -179,6 +182,7 @@ public class IndustryApplication : IIndustryApplication, IScopeDependency
     /// </summary>
     /// <param name="dto"></param>
     /// <returns></returns>
+    [Description("行业模板")]
     public ISugarQueryable<SnapshotSMSTemplateItemsOutDto> GetSMSTemplates(SnapshotSMSTemplateItemsInDto dto)
     {
         var query = _snapshotSMSTemplateRepository.Queryable()

+ 12 - 0
src/Hotline.Application/Snapshot/RedPackApplication.cs

@@ -9,6 +9,7 @@ using Hotline.Snapshot.Interfaces;
 using Mapster;
 using SqlSugar;
 using SqlSugar.Extensions;
+using System.ComponentModel;
 using XF.Domain.Authentications;
 using XF.Domain.Dependency;
 using XF.Domain.Exceptions;
@@ -202,6 +203,7 @@ public class RedPackApplication : IRedPackApplication, IScopeDependency
     /// </summary>
     /// <param name="dto"></param>
     /// <returns></returns>
+    [Description("市民红包审批")]
     public ISugarQueryable<SnapshotOrderAuditItemsOutDto> GetRedPackAuditItemsAsync(SnapshotOrderAuditItemsInDto dto)
     {
         ERedPackAuditStatus? status = null;
@@ -279,6 +281,7 @@ public class RedPackApplication : IRedPackApplication, IScopeDependency
     /// </summary>
     /// <param name="dto"></param>
     /// <returns></returns>
+    [Description("网格员红包审批")]
     public ISugarQueryable<SnapshotOrderGuiderAuditItemsOutDto> GetRedPackGuiderAuditItemsAsync(SnapshotOrderGuiderAuditItemsInDto dto)
     {
         var areaCode = _sessionContext.OrgAreaCode;
@@ -426,6 +429,7 @@ public class RedPackApplication : IRedPackApplication, IScopeDependency
     /// </summary>
     /// <param name="dto"></param>
     /// <returns></returns>
+    [Description("市民红包发放记录")]
     public ISugarQueryable<SnapshotRedPackRecordItemsOutDto> GetRedPackRecordItemsAsync(SnapshotRedPackRecordItemsInDto dto)
     {
         var query = _redPackRecordRepository.Queryable()
@@ -462,6 +466,7 @@ public class RedPackApplication : IRedPackApplication, IScopeDependency
         return order;
     }
 
+    [Description("网格员红包发放记录")]
     public ISugarQueryable<SnapshotRedPackRecordItemsGuiderOutDto> GetRedPackRecordGuiderItemsAsync(SnapshotRedPackRecordItemsGuiderInDto dto)
     {
         var query = _redPackRecordRepository.Queryable()
@@ -482,6 +487,7 @@ public class RedPackApplication : IRedPackApplication, IScopeDependency
         return query;
     }
 
+    [Description("红包发放明细")]
     public ISugarQueryable<SnapshotRedPackRecordSendOutDto> GetRedPackRecordDetailAsync(SnapshotRedPackRecordSendInDto dto)
     {
         var query = _redPackRecordRepository.Queryable()
@@ -508,6 +514,12 @@ public class RedPackApplication : IRedPackApplication, IScopeDependency
         return query;
     }
 
+    /// <summary>
+    /// 补充发放集合
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [Description("补充发放")]
     public ISugarQueryable<SnapshotRedPackRecordSupplementItemsOutDto> GetRedPackRecordSupplementItemsAsync(SnapshotRedPackRecordSupplementItemsInDto dto)
     {
         var query = _supplementRecordRepository.Queryable()

+ 0 - 3
src/Hotline.Application/Snapshot/SnapshotApplicationBase.cs

@@ -34,7 +34,6 @@ using Hotline.Share.Mq;
 using Hotline.Snapshot.Notifications;
 using Hotline.EventBus;
 using Hotline.Quality.Notifications;
-using Hotline.Settings.SystemLogDomain;
 using XF.Utility.EnumExtensions;
 
 namespace Hotline.Application.Snapshot;
@@ -628,7 +627,6 @@ public abstract class SnapshotApplicationBase
     /// </summary>
     /// <param name="dto"></param>
     /// <returns></returns>
-    [LogToData("ReplyCode")]
     public async Task SaveGuiderSystemReplyAsync(GuiderSystemInDto dto, CancellationToken token)
     {
         var orderSnapshot = await _orderSnapshotRepository.GetByNetworkENumberAsync(dto.AppealNumber)
@@ -827,7 +825,6 @@ public abstract class SnapshotApplicationBase
     /// <param name="id"></param>
     /// <param name="cancellationToken"></param>
     /// <returns></returns>
-    [LogToData]
     public async Task<string> AddRedPardAsync(string orderId, CancellationToken cancellationToken)
     {
         var order = await _orderRepository.Queryable()

+ 24 - 0
src/Hotline.Share/Dtos/Home/CheckTokenDto.cs

@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Share.Dtos.Home;
+public class CheckTokenDto
+{
+    /// <summary>
+    /// AppId
+    /// </summary>
+    public string AppId { get; set; }
+
+    /// <summary>
+    /// Secret
+    /// </summary>
+    public string Secret { get; set; }
+
+    /// <summary>
+    /// timestamp
+    /// </summary>
+    public long Timestamp { get; set; }
+}

+ 6 - 1
src/Hotline.Share/Tools/ObjectExtensions.cs

@@ -75,7 +75,7 @@ public static class ObjectExtensions
     /// <typeparam name="T"></typeparam>
     /// <param name="model"></param>
     /// <param name="func">返回 true: contions; false: break</param>
-    public static void ForeachClassProperties<T>(this T model, Func<T, PropertyInfo , string, object, Task<bool>> func)
+    public static void ForeachClassProperties<T>(this T model, Func<T, PropertyInfo, string, object, Task<bool>> func)
     {
         var t = model.GetType();
         var propertyList = t.GetProperties();
@@ -103,4 +103,9 @@ public static class ObjectExtensions
     {
         return json.IsNullOrEmpty() ? default(T) : JsonConvert.DeserializeObject<T>(json);
     }
+
+    public static object? FromJson(this string json, Type returnType)
+    {
+        return json.IsNullOrEmpty() ? null : JsonConvert.DeserializeObject(json, returnType);
+    }
 }

+ 0 - 2
src/Hotline/Hotline.csproj

@@ -8,8 +8,6 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <PackageReference Include="Castle.Core" Version="5.1.1" />
-    <PackageReference Include="Castle.Core.AsyncInterceptor" Version="2.1.0" />
     <PackageReference Include="Mapster" Version="7.4.0" />
     <PackageReference Include="MediatR" Version="12.4.1" />
     <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.1" />

+ 0 - 134
src/Hotline/Settings/SystemLogDomain/AsyncLoggingInterceptor.cs

@@ -1,134 +0,0 @@
-using Castle.DynamicProxy;
-using DotNetCore.CAP;
-using Hotline.Share.Mq;
-using Hotline.Share.Tools;
-using Microsoft.Extensions.Logging;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
-using System.Text;
-using System.Threading.Tasks;
-using XF.Domain.Dependency;
-
-namespace Hotline.Settings.SystemLogDomain;
-public class AsyncLoggingInterceptor : AsyncInterceptorBase
-{
-
-    private readonly ICapPublisher _capPublisher;
-    private readonly ILogger<AsyncLoggingInterceptor> _logger;
-
-    public AsyncLoggingInterceptor(ICapPublisher capPublisher, ILogger<AsyncLoggingInterceptor> logger)
-    {
-        _capPublisher = capPublisher;
-        _logger = logger;
-    }
-
-    protected override async Task InterceptAsync(IInvocation invocation, IInvocationProceedInfo proceedInfo, Func<IInvocation, IInvocationProceedInfo, Task> proceed)
-    {
-        var logAttribute = GetLogAttribute(invocation);
-        var logEntity = GetSystemLog(invocation, logAttribute);
-        try
-        {
-            // 执行原始方法
-            await proceed(invocation, proceedInfo);
-            PublishLog(logEntity, null);
-        }
-        catch (Exception ex)
-        {
-            throw;
-        }
-    }
-
-    protected override async Task<TResult> InterceptAsync<TResult>(IInvocation invocation, IInvocationProceedInfo proceedInfo, Func<IInvocation, IInvocationProceedInfo, Task<TResult>> proceed)
-    {
-        var logEntity = GetSystemLog(invocation, GetLogAttribute(invocation));
-        try
-        {
-            // 执行原始方法
-            TResult result = await proceed(invocation, proceedInfo);
-            PublishLog(logEntity, result);
-            return result;
-        }
-        catch (Exception ex)
-        {
-            throw;
-        }
-    }
-
-    private LogToDataAttribute? GetLogAttribute(IInvocation invocation)
-    {
-        var methodInfo = invocation.MethodInvocationTarget ?? invocation.Method;
-        return methodInfo.GetCustomAttributes(typeof(LogToDataAttribute), true)
-                                     .FirstOrDefault() as LogToDataAttribute;
-    }
-
-    private SystemLog GetSystemLog(IInvocation invocation, LogToDataAttribute logAttribute)
-    {
-        if (logAttribute == null) return null;
-        var entity = new SystemLog
-        {
-            Name = invocation.Method.Name,
-            StartTime = DateTime.Now
-        };
-        for (int i = 0;i < invocation.Arguments.Length;i++)
-        {
-            var argument = invocation.Arguments[i];
-            if (argument == null || argument is CancellationToken) continue;
-            entity.ExecuteParam = argument;
-            Type argType = argument.GetType();
-            if (argument is string)
-            {
-                entity.ExternalId = argument.ToString();
-                continue;
-            }
-
-            var properties = argType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
-            foreach (var property in properties)
-            {
-                var value = property.GetValue(argument);
-                if (value != null && property.Name.ToUpper() == logAttribute.ExternalIdName.ToUpper())
-                {
-                    entity.ExternalId = value.ToString();
-                    break;
-                }
-            }
-        }
-        return entity;
-    }
-
-    private void PublishLog(SystemLog logEntity, object? result)
-    {
-        try
-        {
-            if (logEntity != null)
-            {
-                logEntity.EndTime = DateTime.Now;
-                logEntity.ExecuteResult = result;
-                _capPublisher.Publish(EventNames.LoggingInterceptor, logEntity);
-            }
-
-        }
-        catch (Exception e)
-        {
-            _logger.LogError(e, "PublishLog Error");
-        }
-    }
-}
-
-public class LoggingInterceptorHandler : ICapSubscribe, ITransientDependency
-{
-    private readonly ISystemLogRepository _systemLogRepository;
-
-    public LoggingInterceptorHandler(ISystemLogRepository systemLogRepository)
-    {
-        _systemLogRepository = systemLogRepository;
-    }
-
-    [CapSubscribe(EventNames.LoggingInterceptor)]
-    public async Task Handle(SystemLog logEntity)
-    {
-        logEntity.Interval = (int)(logEntity.EndTime.Value - logEntity.StartTime.Value).TotalSeconds;
-        await _systemLogRepository.AddAsync(logEntity);
-    }
-}

+ 0 - 17
src/Hotline/Settings/SystemLogDomain/LogToDataAttribute.cs

@@ -1,17 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Hotline.Settings.SystemLogDomain;
-[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
-public class LogToDataAttribute : Attribute
-{
-    public string ExternalIdName { get; set; }
-
-    public LogToDataAttribute(string externalIdName = "Id")
-    {
-        ExternalIdName = externalIdName;
-    }
-}

+ 0 - 64
src/Hotline/Settings/SystemLogDomain/LoggingInterceptor.cs

@@ -1,64 +0,0 @@
-using Castle.DynamicProxy;
-using DotNetCore.CAP;
-using Hotline.Share.Mq;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Hotline.Settings.SystemLogDomain;
-public class LoggingInterceptor : IInterceptor
-{
-    private readonly ICapPublisher _cap;
-
-    public LoggingInterceptor(ICapPublisher cap)
-    {
-        _cap = cap;
-    }
-
-    public void Intercept(IInvocation invocation)
-    {
-        // 检查实现类的方法是否有 LogToDatabaseAttribute
-        var methodInfo = invocation.MethodInvocationTarget ?? invocation.Method;
-        var logAttribute = methodInfo.GetCustomAttributes(typeof(LogToDataAttribute), true)
-                                     .FirstOrDefault() as LogToDataAttribute;
-
-        SystemLog entity = null;
-        if (logAttribute != null)
-        {
-            entity = new SystemLog
-            {
-                Name = invocation.Method.Name,
-            };
-            // 遍历所有参数
-            for (int i = 0;i < invocation.Arguments.Length;i++)
-            {
-                var argument = invocation.Arguments[i];
-                if (argument == null) continue;
-                Type argType = argument.GetType();
-
-                // 遍历参数的所有属性及其值
-                var properties = argType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
-                foreach (var property in properties)
-                {
-                    var value = property.GetValue(argument);
-                    if (value != null && property.Name.ToUpper() == logAttribute.ExternalIdName.ToUpper())
-                    {
-                        entity.ExternalId = value.ToString();
-                        break;
-                    }
-                }
-            }
-        }
-
-        // 执行实际方法
-        invocation.Proceed();
-
-        if (logAttribute != null && entity != null)
-        {
-            _cap.Publish(EventNames.LoggingInterceptor, entity);
-        }
-    }
-}

+ 0 - 42
src/Hotline/Settings/SystemLogDomain/SystemLogServiceCollectionExtensions.cs

@@ -1,42 +0,0 @@
-using Castle.DynamicProxy;
-using Microsoft.Extensions.DependencyInjection;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Hotline.Settings.SystemLogDomain;
-public static class SystemLogServiceCollectionExtensions
-{
-    public static IServiceCollection AddProxiedScoped<TInterface, TImplementation>(this IServiceCollection services)
-        where TInterface : class
-        where TImplementation : class, TInterface
-    {
-        services.AddScoped<TImplementation>();
-        services.AddScoped<TInterface>(provider =>
-        {
-            var proxyGenerator = new ProxyGenerator();
-            var target = provider.GetRequiredService<TImplementation>();
-            var interceptor = provider.GetRequiredService<AsyncLoggingInterceptor>();
-            return proxyGenerator.CreateInterfaceProxyWithTarget<TInterface>(target, interceptor);
-        });
-
-        return services;
-    }
-
-    public static IServiceCollection AddProxiedScoped(this IServiceCollection services, Type serviceType, Type implementationType)
-    {
-        services.AddScoped(implementationType);
-        services.AddScoped(serviceType, provider =>
-        {
-            var proxyGenerator = new ProxyGenerator();
-            var target = provider.GetRequiredService(implementationType);
-            var interceptor = provider.GetRequiredService<AsyncLoggingInterceptor>();
-
-            return proxyGenerator.CreateInterfaceProxyWithTarget(serviceType, target, interceptor);
-        });
-
-        return services;
-    }
-}