From 9265301c1655fffdc71cca7b0e0cfab1af89afeb Mon Sep 17 00:00:00 2001
From: dengjunjie <dengjunjie@hnkhzn.com>
Date: 星期四, 16 四月 2026 19:07:48 +0800
Subject: [PATCH] 添加接口日志配置文件,优化接口日志记录方法,优化获取阻碍托生成移库任务方法

---
 代码管理/WCS/WIDESEAWCS_Server/WIDESEAWCS_BasicInfoService/ApiInfoService.cs        |   72 ++
 代码管理/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Filter/Log/LogCleanupService.cs    |  426 +++++++++++++++++++++
 代码管理/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/BasicInfo/Dt_InterfaceLog.cs |   18 
 代码管理/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Filter/Log/ApiLogMiddlewareNew.cs  |  144 +++++++
 代码管理/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Server.csproj           |    4 
 代码管理/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Filter/Log/LoggerNew.cs            |  431 +++++++++++++++++++++
 代码管理/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Program.cs                         |   33 +
 代码管理/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/Task/RGVTaskExtend.cs               |    7 
 代码管理/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Filter/Log/MiddlewareHelpersNew.cs |   22 +
 代码管理/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json                   |   31 +
 代码管理/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Controllers/WMS/WMSController.cs   |    2 
 11 files changed, 1,167 insertions(+), 23 deletions(-)

diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_BasicInfoService/ApiInfoService.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_BasicInfoService/ApiInfoService.cs"
index 99a8888..57c0b3a 100644
--- "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_BasicInfoService/ApiInfoService.cs"
+++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_BasicInfoService/ApiInfoService.cs"
@@ -1,6 +1,7 @@
 锘縰sing System;
 using System.Collections.Generic;
 using System.Linq;
+using System.Security.Cryptography;
 using System.Text;
 using System.Threading.Tasks;
 using WIDESEAWCS_Core;
@@ -36,11 +37,15 @@
         {
             WebResponseContent content = new WebResponseContent();
             string response = string.Empty;
+            string requestHash = string.Empty;
+            string responseHash = string.Empty;
             Dt_ApiInfo? apiInfo = null;
             try
             {
                 apiInfo = BaseDal.QueryFirst(x => x.ApiCode == apiCode) ?? throw new Exception($"鏈壘鍒皗remark}鎺ュ彛閰嶇疆淇℃伅锛佽妫�鏌ユ帴鍙i厤缃�");
                 response = HttpHelper.Post(apiInfo.ApiAddress, requestParameters);
+                requestHash = ComputeHash(requestParameters);
+                responseHash = ComputeHash(response);
                 if (apiInfo.Remark.Contains("鍥涘悜杞�"))
                 {
                     FOURBOTReturn fOURBOTReturn = response.DeserializeObject<FOURBOTReturn>();
@@ -70,24 +75,63 @@
             {
                 if (isAdd && !string.IsNullOrEmpty(response) && apiInfo != null)
                 {
-                    Dt_InterfaceLog interfaceLog = new Dt_InterfaceLog()
+                    #region 鏌ヨ褰撳ぉ鏄惁瀛樺湪鐩稿悓璁板綍
+                    var today = DateTime.Now.Date;
+                    var existingLog = _interfaceLogService.Repository.QueryFirst(x =>
+                        x.ApiCode == apiCode &&
+                        x.RequestParametersHash == requestHash &&
+                        x.ResponseParametersHash == responseHash &&
+                        x.CreateDate.Date == today);
+                    if (existingLog != null)
                     {
-                        ApiCode = apiCode,
-                        RequestParameters = requestParameters,
-                        ApiAddress = apiInfo.ApiAddress,
-                        ApiName = apiInfo.ApiName,
-                        PushFrequency = 1,
-                        PushState = content.Status ? 1 : 2,
-                        Requestor = "WCS",
-                        Recipient = apiInfo.Remark,
-                        ResponseParameters = response,
-                        Creater = "System",
-                        Remark = content.Status ? remark : content.Message,
-                    };
-                    _interfaceLogService.Repository.AddData(interfaceLog);
+                        existingLog.PushFrequency = existingLog.PushFrequency + 1;
+                        existingLog.PushState = content.Status ? 1 : 2;
+                        existingLog.ResponseParameters = response;
+                        existingLog.Remark = content.Status ? remark : content.Message;
+                        existingLog.Modifier = App.User?.UserName ?? "System";
+                        existingLog.ModifyDate = DateTime.Now;
+                        _interfaceLogService.Repository.UpdateData(existingLog);
+                    }
+                    #endregion
+                    else
+                    {
+                        Dt_InterfaceLog interfaceLog = new Dt_InterfaceLog()
+                        {
+                            ApiCode = apiCode,
+                            RequestParameters = requestParameters,
+                            ApiAddress = apiInfo.ApiAddress,
+                            ApiName = apiInfo.ApiName,
+                            RequestParametersHash = requestHash,
+                            ResponseParametersHash = responseHash,
+                            PushFrequency = 1,
+                            PushState = content.Status ? 1 : 2,
+                            Requestor = "WCS",
+                            Recipient = apiInfo.Remark,
+                            ResponseParameters = response,
+                            Creater = "System",
+                            Remark = content.Status ? remark : content.Message,
+                        };
+                        _interfaceLogService.Repository.AddData(interfaceLog);
+                    }
                 }
             }
             return content;
         }
+
+        /// <summary>
+        /// 璁$畻瀛楃涓茬殑SHA256鍝堝笇鍊�
+        /// </summary>
+        private static string ComputeHash(string input)
+        {
+            if (string.IsNullOrEmpty(input))
+                return string.Empty;
+
+            using (SHA256 sha256 = SHA256.Create())
+            {
+                byte[] bytes = Encoding.UTF8.GetBytes(input);
+                byte[] hashBytes = sha256.ComputeHash(bytes);
+                return BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
+            }
+        }
     }
 }
diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/BasicInfo/Dt_InterfaceLog.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/BasicInfo/Dt_InterfaceLog.cs"
index 176cd09..7d07c19 100644
--- "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/BasicInfo/Dt_InterfaceLog.cs"
+++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/BasicInfo/Dt_InterfaceLog.cs"
@@ -51,6 +51,12 @@
         public int PushState { get; set; } = 0;
 
         /// <summary>
+        /// 璇锋眰鏂圭敤鎴稩P
+        /// </summary>
+        [SugarColumn(IsNullable = true, Length = 20, ColumnDescription = "璇锋眰鏂圭敤鎴稩P")]
+        public string RequestorUserIP { get; set; }
+
+        /// <summary>
         /// 璇锋眰鏂�
         /// </summary>
         [SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "璇锋眰鏂�")]
@@ -63,6 +69,12 @@
         public string RequestParameters { get; set; }
 
         /// <summary>
+        /// 璇锋眰鍙傛暟鍝堝笇鍊硷紙鐢ㄤ簬绱㈠紩鍜屽幓閲嶏級
+        /// </summary>
+        [SugarColumn(IsNullable = true, Length = 64, ColumnDescription = "璇锋眰鍙傛暟鍝堝笇鍊�")]
+        public string RequestParametersHash { get; set; }
+
+        /// <summary>
         /// 鎺ユ敹鏂�
         /// </summary>
         [SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "鎺ユ敹鏂�")]
@@ -75,6 +87,12 @@
         public string ResponseParameters { get; set; }
 
         /// <summary>
+        /// 鍝嶅簲鍙傛暟鍝堝笇鍊硷紙鐢ㄤ簬绱㈠紩鍜屽幓閲嶏級
+        /// </summary>
+        [SugarColumn(IsNullable = true, Length = 64, ColumnDescription = "鍝嶅簲鍙傛暟鍝堝笇鍊�")]
+        public string ResponseParametersHash { get; set; }
+
+        /// <summary>
         /// 澶囨敞
         /// </summary>
         [SugarColumn(IsNullable = true, Length = 100, ColumnDescription = "澶囨敞")]
diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Controllers/WMS/WMSController.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Controllers/WMS/WMSController.cs"
index 4476a15..999ec40 100644
--- "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Controllers/WMS/WMSController.cs"
+++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Controllers/WMS/WMSController.cs"
@@ -71,7 +71,7 @@
         }
 
         /// <summary>
-        /// 璐ㄦ缁撴灉鍙嶉
+        /// 澶栨缁撴灉鍙嶉
         /// </summary>
         /// <param name="iQC"></param>
         /// <returns></returns>
diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Filter/Log/ApiLogMiddlewareNew.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Filter/Log/ApiLogMiddlewareNew.cs"
new file mode 100644
index 0000000..21d3de3
--- /dev/null
+++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Filter/Log/ApiLogMiddlewareNew.cs"
@@ -0,0 +1,144 @@
+锘縰sing Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Logging;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Reflection;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using WIDESEAWCS_Core.Helper;
+using WIDESEAWCS_Core.LogHelper;
+
+namespace WIDESEAWCS_Core.Middlewares
+{
+    /// <summary>
+    /// 璁板綍璇锋眰鍜屽搷搴旀暟鎹�
+    /// </summary>
+    public class ApiLogMiddlewareNew
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        private readonly RequestDelegate _next;
+
+        public ApiLogMiddlewareNew(RequestDelegate next, ILogger<ApiLogMiddlewareNew> logger)
+        {
+            _next = next;
+        }
+
+        //todo
+        public async Task InvokeAsync(HttpContext context)
+        {
+            if (App.ExpDateTime != null && (DateTime.Now - App.ExpDateTime.GetValueOrDefault()).TotalSeconds > 0)
+            {
+                context.Response.StatusCode = HttpStatusCode.InternalServerError.ObjToInt();
+                context.Response.ContentType = "application/json";
+
+                var json = new WebResponseContent();
+
+                json.Message = HttpStatusCode.InternalServerError.ToString();//閿欒淇℃伅
+                json.Code = 500;//500寮傚父 
+
+                StreamWriter streamWriter = new StreamWriter(context.Response.Body);
+                await streamWriter.WriteAsync(json.Serialize());
+                return;
+            }
+
+            // 杩囨护锛屽彧鏈夋帴鍙�
+            if (context.Request.Path.Value?.Contains("api") ?? false)
+            {
+                context.Request.EnableBuffering();
+                Stream originalBody = context.Response.Body;
+                string requestParam = string.Empty;
+                string responseParam = string.Empty;
+                try
+                {
+                    (context.RequestServices.GetService(typeof(RequestLogModel)) as RequestLogModel).RequestDate = DateTime.Now;
+                    try
+                    {
+                        // 瀛樺偍璇锋眰鏁版嵁
+                        requestParam = RequestDataLog(context);
+                        context.Request.Body.Position = 0;
+                    }
+                    catch { }
+                    using MemoryStream ms = new();
+                    context.Response.Body = ms;
+
+                    await _next(context);
+
+                    try
+                    {
+                        // 瀛樺偍鍝嶅簲鏁版嵁
+                        responseParam = ResponseDataLog(context.Response);
+                    }
+                    catch { }
+
+                    ms.Position = 0;
+                    await ms.CopyToAsync(originalBody);
+                    #region 杩囨护鎺ュ彛
+                    string path = context.Request.Path.Value;
+                    if (!string.IsNullOrEmpty(path))
+                    {
+                        List<string> RequestPaths = new List<string>();
+                        string RequestPath = AppSettings.Configuration[nameof(RequestPath)];
+                        if (!string.IsNullOrEmpty(RequestPath)) RequestPaths = RequestPath.Split(',').ToList();
+                        bool containsAny = RequestPaths.Any(k => path.Contains(k, StringComparison.OrdinalIgnoreCase));
+                        if (!containsAny) Logger.Add(requestParam, responseParam);//璁板綍绯荤粺鏃ュ織
+                        //璁板綍鎺ュ彛鏃ュ織
+                        var ignoreKeywords = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "get" };
+                        containsAny = RequestPaths.Where(k => !ignoreKeywords.Contains(k))
+                           .Any(k => path.Contains(k, StringComparison.OrdinalIgnoreCase));
+                        if (containsAny && context != null) LoggerNew.Add(requestParam, responseParam, context);
+                    }
+                    #endregion
+                    //if (!(context.Request.Path.Value?.Contains("get") ?? true))
+                    //    Logger.Add(requestParam, responseParam);
+                }
+                catch (Exception ex)
+                {
+                    // 璁板綍寮傚父
+
+                }
+                finally
+                {
+                    context.Response.Body = originalBody;
+                }
+            }
+            else
+            {
+                await _next(context);
+            }
+        }
+
+        private string RequestDataLog(HttpContext context)
+        {
+            var request = context.Request;
+            var sr = new StreamReader(request.Body);
+
+            object obj = new
+            {
+                QueryString = request.QueryString.ToString(),
+                BodyData = sr.ReadToEndAsync().Result
+            };
+
+            string data = JsonConvert.SerializeObject(obj);
+
+            request.Body.Position = 0;
+
+            return data;
+        }
+
+        private string ResponseDataLog(HttpResponse response)
+        {
+            response.Body.Position = 0;
+            using StreamReader stream = new StreamReader(response.Body, leaveOpen: true);
+            string body = stream.ReadToEnd();
+            response.Body.Position = 0;
+            return body;
+        }
+    }
+}
diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Filter/Log/LogCleanupService.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Filter/Log/LogCleanupService.cs"
new file mode 100644
index 0000000..002b48b
--- /dev/null
+++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Filter/Log/LogCleanupService.cs"
@@ -0,0 +1,426 @@
+锘縰sing Microsoft.Extensions.Hosting;
+using SqlSugar;
+using System;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+using WIDESEAWCS_Core.DB;
+using WIDESEAWCS_Core.Seed;
+using WIDESEAWCS_Model.Models;
+
+namespace WIDESEAWCS_Core.LogHelper
+{
+    /// <summary>
+    /// 鏃ュ織鏁版嵁娓呯悊鏈嶅姟
+    /// </summary>
+    public class LogCleanupService : IHostedService, IDisposable
+    {
+        private Timer _cleanupTimer;
+        private bool _isDisposed = false;
+        private readonly object _lockObject = new object();
+
+        /// <summary>
+        /// 鏁版嵁淇濈暀澶╂暟锛堥粯璁�90澶╋級
+        /// </summary>
+        public int RetentionDays { get; set; } = 90;
+
+        /// <summary>
+        /// 娓呯悊闂撮殧锛堝皬鏃讹紝榛樿24灏忔椂锛�
+        /// </summary>
+        public int CleanupIntervalHours { get; set; } = 24;
+
+        /// <summary>
+        /// 娓呯悊鎵ц鏃堕棿锛堝皬鏃讹紝0-23锛岄粯璁ゅ噷鏅�2鐐癸級
+        /// </summary>
+        public int CleanupHour { get; set; } = 2;
+
+        /// <summary>
+        /// 鏄惁鍚敤褰掓。
+        /// </summary>
+        public bool EnableArchive { get; set; } = false;
+
+        /// <summary>
+        /// 鏄惁鍚敤鑷姩娓呯悊
+        /// </summary>
+        public bool EnableAutoCleanup { get; set; } = true;
+
+        /// <summary>
+        /// 鏃ュ織鏂囦欢淇濈暀澶╂暟
+        /// </summary>
+        public int LogRetentionDays { get; set; } = 30;
+        /// <summary>
+        /// 鏃ュ織鏂囦欢璺緞
+        /// </summary>
+        private string LogFilePath => Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs", "LogCleanup", $"Cleanup_{DateTime.Now:yyyyMMdd}.log");
+
+        public Task StartAsync(CancellationToken cancellationToken)
+        {
+            if (EnableAutoCleanup)
+            {
+                // 纭繚鏃ュ織鐩綍瀛樺湪
+                EnsureLogDirectoryExists();
+
+                // 璁$畻鍒颁笅涓�涓竻鐞嗘椂闂寸殑闂撮殧
+                var now = DateTime.Now;
+                var nextCleanupTime = DateTime.Today.AddHours(CleanupHour);
+
+                if (now > nextCleanupTime)
+                {
+                    nextCleanupTime = nextCleanupTime.AddDays(1);
+                }
+
+                var timeToFirstCleanup = nextCleanupTime - now;
+
+                // 璁剧疆瀹氭椂鍣紝鍦ㄦ寚瀹氭椂闂存墽琛屾竻鐞�
+                _cleanupTimer = new Timer(CleanupCallback, null,
+                    timeToFirstCleanup,
+                    TimeSpan.FromHours(CleanupIntervalHours));
+
+                WriteLog($"鏃ュ織娓呯悊鏈嶅姟宸插惎鍔紝棣栨娓呯悊鏃堕棿: {nextCleanupTime:yyyy-MM-dd HH:mm:ss}");
+            }
+
+            return Task.CompletedTask;
+        }
+
+        /// <summary>
+        /// 纭繚鏃ュ織鐩綍瀛樺湪
+        /// </summary>
+        private void EnsureLogDirectoryExists()
+        {
+            try
+            {
+                string logDirectory = Path.GetDirectoryName(LogFilePath);
+                if (!Directory.Exists(logDirectory))
+                {
+                    Directory.CreateDirectory(logDirectory);
+                }
+            }
+            catch (Exception ex)
+            {
+                Console.WriteLine($"鍒涘缓鏃ュ織鐩綍澶辫触: {ex.Message}");
+            }
+        }
+
+        /// <summary>
+        /// 鍐欏叆鏃ュ織鍒版枃浠�
+        /// </summary>
+        private void WriteLog(string message, bool isError = false)
+        {
+            try
+            {
+                lock (_lockObject)
+                {
+                    EnsureLogDirectoryExists();
+                    string logMessage = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] {(isError ? "[ERROR]" : "[INFO]")} {message}";
+
+                    // 鍐欏叆鏂囦欢
+                    File.AppendAllText(LogFilePath, logMessage + Environment.NewLine);
+
+                    // 鍚屾椂杈撳嚭鍒版帶鍒跺彴锛堝彲閫夛紝渚夸簬璋冭瘯锛�
+                    Console.WriteLine(logMessage);
+
+                    // 鏃ュ織鏂囦欢杩囧ぇ鏃惰嚜鍔ㄦ竻鐞嗭紙淇濈暀鏈�杩�30澶╃殑鏃ュ織鏂囦欢锛�
+                    AutoCleanupLogFiles();
+                }
+            }
+            catch (Exception ex)
+            {
+                // 濡傛灉鏂囦欢鏃ュ織澶辫触锛岃嚦灏戣緭鍑哄埌鎺у埗鍙�
+                Console.WriteLine($"鍐欏叆鏃ュ織鏂囦欢澶辫触: {ex.Message}");
+                Console.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] {message}");
+            }
+        }
+
+        /// <summary>
+        /// 鑷姩娓呯悊杩囨湡鐨勬棩蹇楁枃浠讹紙淇濈暀30澶╋級
+        /// </summary>
+        private void AutoCleanupLogFiles()
+        {
+            try
+            {
+                string logDirectory = Path.GetDirectoryName(LogFilePath);
+                if (Directory.Exists(logDirectory))
+                {
+                    var files = Directory.GetFiles(logDirectory, "Cleanup_*.log");
+                    DateTime cutoffDate = DateTime.Now.AddDays(-30);
+
+                    foreach (var file in files)
+                    {
+                        try
+                        {
+                            // 浠庢枃浠跺悕涓彁鍙栨棩鏈�
+                            string fileName = Path.GetFileNameWithoutExtension(file);
+                            if (fileName.StartsWith("Cleanup_"))
+                            {
+                                string dateStr = fileName.Replace("Cleanup_", "");
+                                if (DateTime.TryParseExact(dateStr, "yyyyMMdd", null, System.Globalization.DateTimeStyles.None, out DateTime fileDate))
+                                {
+                                    if (fileDate < cutoffDate)
+                                    {
+                                        File.Delete(file);
+                                        WriteLog($"鍒犻櫎杩囨湡鏃ュ織鏂囦欢: {Path.GetFileName(file)}");
+                                    }
+                                }
+                            }
+                        }
+                        catch (Exception ex)
+                        {
+                            Console.WriteLine($"鍒犻櫎杩囨湡鏃ュ織鏂囦欢澶辫触 {file}: {ex.Message}");
+                        }
+                    }
+                }
+            }
+            catch (Exception ex)
+            {
+                Console.WriteLine($"娓呯悊鏃ュ織鏂囦欢澶辫触: {ex.Message}");
+            }
+        }
+
+        private void CleanupCallback(object state)
+        {
+            Task.Run(() => CleanupAsync());
+        }
+
+        /// <summary>
+        /// 鎵ц娓呯悊
+        /// </summary>
+        public async Task CleanupAsync()
+        {
+            try
+            {
+                WriteLog($"寮�濮嬫竻鐞� {RetentionDays} 澶╁墠鐨勬棩蹇楁暟鎹�");
+
+                using (SqlSugarClient sugarClient = new SqlSugarClient(new ConnectionConfig()
+                {
+                    ConnectionString = DBContext.GetMainConnectionDb().Connection,
+                    IsAutoCloseConnection = true,
+                    DbType = DBContext.DbType,
+                }))
+                {
+                    DateTime cutoffDate = DateTime.Now.AddDays(-RetentionDays);
+
+                    WriteLog($"鎴鏃ユ湡: {cutoffDate:yyyy-MM-dd HH:mm:ss}");
+
+                    if (EnableArchive)
+                    {
+                        // 鍏堝綊妗e啀鍒犻櫎
+                        await ArchiveDataAsync(sugarClient, cutoffDate);
+                    }
+
+                    // 鍒犻櫎鍘嗗彶鏁版嵁
+                    int deletedCount = await sugarClient.Deleteable<Dt_InterfaceLog>()
+                        .Where(x => x.CreateDate < cutoffDate)
+                        .ExecuteCommandAsync();
+
+                    WriteLog($"娓呯悊瀹屾垚锛屽叡鍒犻櫎 {deletedCount} 鏉¤褰�");
+
+                    // 鍙�夛細璁板綍娓呯悊鏃ュ織鍒版暟鎹簱
+                    await LogCleanupResult(sugarClient, deletedCount, cutoffDate);
+                }
+            }
+            catch (Exception ex)
+            {
+                WriteLog($"娓呯悊澶辫触: {ex.Message}", true);
+                WriteLog($"璇︾粏閿欒: {ex.ToString()}", true);
+            }
+        }
+
+        private async Task ArchiveDataAsync(SqlSugarClient sugarClient, DateTime cutoffDate)
+        {
+            try
+            {
+                string archiveTableName = $"Dt_InterfaceLog_Archive_{DateTime.Now:yyyyMM}";
+
+                WriteLog($"寮�濮嬪綊妗f暟鎹埌琛�: {archiveTableName}");
+
+                // 鍒涘缓褰掓。琛�
+                string createTableSql = $@"
+                    IF NOT EXISTS (SELECT * FROM sysobjects WHERE name='{archiveTableName}' AND xtype='U')
+                    BEGIN
+                        SELECT * INTO {archiveTableName} FROM Dt_InterfaceLog WHERE 1=0
+                        ALTER TABLE {archiveTableName} ADD ArchiveDate datetime DEFAULT GETDATE()
+                    END";
+                await sugarClient.Ado.ExecuteCommandAsync(createTableSql);
+
+                // 褰掓。鏁版嵁
+                string archiveSql = $@"
+                    INSERT INTO {archiveTableName} (Id, ApiCode, ApiName, ApiAddress, PushFrequency, 
+                        PushState, Requestor, RequestParameters, RequestParametersHash, Recipient, 
+                        ResponseParameters, ResponseParametersHash, Remark, CreateTime, ArchiveDate)
+                    SELECT Id, ApiCode, ApiName, ApiAddress, PushFrequency, PushState, 
+                        Requestor, RequestParameters, RequestParametersHash, Recipient, 
+                        ResponseParameters, ResponseParametersHash, Remark, CreateTime, GETDATE()
+                    FROM Dt_InterfaceLog 
+                    WHERE CreateTime < @CutoffDate";
+
+                int archivedCount = await sugarClient.Ado.ExecuteCommandAsync(archiveSql,
+                    new { CutoffDate = cutoffDate });
+
+                WriteLog($"褰掓。瀹屾垚锛屽叡褰掓。 {archivedCount} 鏉¤褰曞埌 {archiveTableName}");
+            }
+            catch (Exception ex)
+            {
+                WriteLog($"褰掓。澶辫触: {ex.Message}", true);
+            }
+        }
+
+        private async Task LogCleanupResult(SqlSugarClient sugarClient, int deletedCount, DateTime cutoffDate)
+        {
+            try
+            {
+                // 鍒涘缓娓呯悊鏃ュ織琛紙濡傛灉涓嶅瓨鍦級
+                string createLogTableSql = @"
+                    IF NOT EXISTS (SELECT * FROM sysobjects WHERE name='LogCleanupHistory' AND xtype='U')
+                    BEGIN
+                        CREATE TABLE LogCleanupHistory (
+                            Id INT IDENTITY(1,1) PRIMARY KEY,
+                            TableName NVARCHAR(100),
+                            DeletedCount INT,
+                            CutoffDate DATETIME,
+                            CleanupTime DATETIME DEFAULT GETDATE()
+                        )
+                    END";
+                await sugarClient.Ado.ExecuteCommandAsync(createLogTableSql);
+
+                // 璁板綍娓呯悊鏃ュ織
+                string insertLogSql = @"
+                    INSERT INTO LogCleanupHistory (TableName, DeletedCount, CutoffDate, CleanupTime)
+                    VALUES ('Dt_InterfaceLog', @DeletedCount, @CutoffDate, GETDATE())";
+
+                await sugarClient.Ado.ExecuteCommandAsync(insertLogSql,
+                    new { DeletedCount = deletedCount, CutoffDate = cutoffDate });
+
+                WriteLog($"娓呯悊璁板綍宸插啓鍏ユ暟鎹簱鏃ュ織琛�");
+            }
+            catch (Exception ex)
+            {
+                WriteLog($"鍐欏叆鏁版嵁搴撴棩蹇楀け璐�: {ex.Message}", true);
+            }
+        }
+
+        /// <summary>
+        /// 鎵嬪姩鎵ц娓呯悊
+        /// </summary>
+        public async Task<int> ManualCleanup(int days = 90)
+        {
+            try
+            {
+                WriteLog($"鎵嬪姩娓呯悊寮�濮嬶紝鍒犻櫎瓒呰繃 {days} 澶╃殑鏁版嵁");
+
+                using (SqlSugarClient sugarClient = new SqlSugarClient(new ConnectionConfig()
+                {
+                    ConnectionString = DBContext.GetMainConnectionDb().Connection,
+                    IsAutoCloseConnection = true,
+                    DbType = DBContext.DbType,
+                }))
+                {
+                    DateTime cutoffDate = DateTime.Now.AddDays(-days);
+                    int deletedCount = await sugarClient.Deleteable<Dt_InterfaceLog>()
+                        .Where(x => x.CreateDate < cutoffDate)
+                        .ExecuteCommandAsync();
+
+                    WriteLog($"鎵嬪姩娓呯悊瀹屾垚锛屽垹闄� {deletedCount} 鏉¤褰�");
+                    return deletedCount;
+                }
+            }
+            catch (Exception ex)
+            {
+                WriteLog($"鎵嬪姩娓呯悊澶辫触: {ex.Message}", true);
+                return 0;
+            }
+        }
+
+        /// <summary>
+        /// 鑾峰彇娓呯悊缁熻淇℃伅
+        /// </summary>
+        public async Task<CleanupStatistics> GetStatistics()
+        {
+            try
+            {
+                using (SqlSugarClient sugarClient = new SqlSugarClient(new ConnectionConfig()
+                {
+                    ConnectionString = DBContext.GetMainConnectionDb().Connection,
+                    IsAutoCloseConnection = true,
+                    DbType = DBContext.DbType,
+                }))
+                {
+                    var totalCount = await sugarClient.Queryable<Dt_InterfaceLog>().CountAsync();
+                    var oldestLog = await sugarClient.Queryable<Dt_InterfaceLog>()
+                        .OrderBy(x => x.CreateDate)
+                        .FirstAsync();
+                    var newestLog = await sugarClient.Queryable<Dt_InterfaceLog>()
+                        .OrderBy(x => x.CreateDate, OrderByType.Desc)
+                        .FirstAsync();
+
+                    return new CleanupStatistics
+                    {
+                        TotalCount = totalCount,
+                        OldestLogTime = oldestLog?.CreateDate,
+                        NewestLogTime = newestLog?.CreateDate,
+                        RetentionDays = RetentionDays,
+                        LastCleanupTime = GetLastCleanupTime(),
+                        LogFilePath = LogFilePath
+                    };
+                }
+            }
+            catch (Exception ex)
+            {
+                WriteLog($"鑾峰彇缁熻淇℃伅澶辫触: {ex.Message}", true);
+                return null;
+            }
+        }
+
+        private DateTime? GetLastCleanupTime()
+        {
+            try
+            {
+                string logDirectory = Path.GetDirectoryName(LogFilePath);
+                if (Directory.Exists(logDirectory))
+                {
+                    var latestLogFile = Directory.GetFiles(logDirectory, "Cleanup_*.log")
+                        .OrderByDescending(f => f)
+                        .FirstOrDefault();
+
+                    if (latestLogFile != null && File.Exists(latestLogFile))
+                    {
+                        return File.GetLastWriteTime(latestLogFile);
+                    }
+                }
+            }
+            catch (Exception ex)
+            {
+                Console.WriteLine($"鑾峰彇涓婃娓呯悊鏃堕棿澶辫触: {ex.Message}");
+            }
+            return null;
+        }
+
+        public Task StopAsync(CancellationToken cancellationToken)
+        {
+            _cleanupTimer?.Dispose();
+            WriteLog("鏃ュ織娓呯悊鏈嶅姟宸插仠姝�");
+            return Task.CompletedTask;
+        }
+
+        public void Dispose()
+        {
+            if (!_isDisposed)
+            {
+                _cleanupTimer?.Dispose();
+                _isDisposed = true;
+            }
+        }
+    }
+
+    /// <summary>
+    /// 娓呯悊缁熻淇℃伅
+    /// </summary>
+    public class CleanupStatistics
+    {
+        public int TotalCount { get; set; }
+        public DateTime? OldestLogTime { get; set; }
+        public DateTime? NewestLogTime { get; set; }
+        public int RetentionDays { get; set; }
+        public DateTime? LastCleanupTime { get; set; }
+        public string LogFilePath { get; set; }
+    }
+}
\ No newline at end of file
diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Filter/Log/LoggerNew.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Filter/Log/LoggerNew.cs"
new file mode 100644
index 0000000..bd6abe2
--- /dev/null
+++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Filter/Log/LoggerNew.cs"
@@ -0,0 +1,431 @@
+锘縰sing SqlSugar;
+using System.Collections.Concurrent;
+using System.Text;
+using WIDESEAWCS_Core.HttpContextUser;
+using WIDESEAWCS_Core.Seed;
+using WIDESEAWCS_Model.Models;
+using System.Security.Cryptography;
+using WIDESEAWCS_Core.Helper;
+using Newtonsoft.Json.Linq;
+using WIDESEAWCS_DTO.RGV.FOURBOT;
+using WIDESEAWCS_DTO.WMS;
+using WIDESEAWCS_DTO;
+
+namespace WIDESEAWCS_Core.LogHelper
+{
+    public static class LoggerNew
+    {
+        // 鐢ㄤ簬缂撳瓨褰撳ぉ宸插瓨鍦ㄧ殑鏃ュ織锛坘ey: 鏃ユ湡+ApiCode+璇锋眰鍝堝笇+鍝嶅簲鍝堝笇锛�
+        private static ConcurrentDictionary<string, Dt_InterfaceLog> _cacheLogs = new ConcurrentDictionary<string, Dt_InterfaceLog>();
+        // 闃熷垪鐢ㄤ簬瀛樺偍闇�瑕佹柊澧炴垨鏇存柊鐨勬棩蹇�
+        public static ConcurrentQueue<Dt_InterfaceLog> loggerQueueData = new ConcurrentQueue<Dt_InterfaceLog>();
+
+        // 姣忓ぉ鍑屾櫒娓呯┖缂撳瓨
+        private static DateTime _lastClearDate = DateTime.Now.Date;
+
+        static LoggerNew()
+        {
+            Task.Run(() =>
+            {
+                StartWriteLog();
+            });
+
+            // 鍚姩涓�涓悗鍙颁换鍔★紝姣忓ぉ鍑屾櫒娓呯┖缂撳瓨
+            Task.Run(() =>
+            {
+                while (true)
+                {
+                    Thread.Sleep(60000); // 姣忓垎閽熸鏌ヤ竴娆�
+                    DateTime today = DateTime.Now.Date;
+                    if (_lastClearDate < today)
+                    {
+                        _cacheLogs.Clear();
+                        _lastClearDate = today;
+                        Console.WriteLine($"Logger缂撳瓨宸叉竻绌猴紝鏃ユ湡锛歿today:yyyy-MM-dd}");
+                    }
+                }
+            });
+        }
+
+        static void StartWriteLog()
+        {
+            List<Dt_InterfaceLog> batchList = new List<Dt_InterfaceLog>();
+
+            while (true)
+            {
+                try
+                {
+                    if (loggerQueueData.Count() > 0 && batchList.Count < 500)
+                    {
+                        DequeueToBatchList(batchList);
+                        continue;
+                    }
+
+                    Thread.Sleep(5000);
+
+                    if (batchList.Count == 0) { continue; }
+
+                    SqlSugarClient sugarClient = new SqlSugarClient(new ConnectionConfig()
+                    {
+                        ConnectionString = DBContext.GetMainConnectionDb().Connection,
+                        IsAutoCloseConnection = true,
+                        DbType = DBContext.DbType,
+                    });
+
+                    try
+                    {
+                        sugarClient.BeginTran(); // 寮�鍚簨鍔�
+
+                        var toInsert = new List<Dt_InterfaceLog>();
+                        var toUpdate = new List<Dt_InterfaceLog>();
+
+                        foreach (var log in batchList)
+                        {
+                            // 濡傛灉宸茬粡鏈� Id 鎴栬�� IsExisting 鏍囧織锛岀洿鎺ュ鐞�
+                            if (log.Id > 0)
+                            {
+                                toUpdate.Add(log);
+                                continue;
+                            }
+
+                            // 鏍规嵁鍝堝笇鍊兼煡璇㈡槸鍚﹀凡瀛樺湪
+                            var existing = sugarClient.Queryable<Dt_InterfaceLog>()
+                                .First(x => x.RequestParametersHash == log.RequestParametersHash
+                                         && x.ResponseParametersHash == log.ResponseParametersHash
+                                         && x.ApiCode == log.ApiCode
+                                         && SqlFunc.DateIsSame(x.CreateDate, DateTime.Now)); // 鍚屼竴澶�
+
+                            if (existing != null)
+                            {
+                                // 宸插瓨鍦紝鏇存柊
+                                log.Id = existing.Id;
+                                log.PushFrequency = existing.PushFrequency + 1; // 鍙犲姞娆℃暟
+                                log.ModifyDate = DateTime.Now;
+                                toUpdate.Add(log);
+
+                                // 鏇存柊缂撳瓨涓殑 Id
+                                string cacheKey = GenerateCacheKey(log.ApiCode, log.RequestParametersHash, log.ResponseParametersHash);
+                                if (_cacheLogs.TryGetValue(cacheKey, out var cachedLog))
+                                {
+                                    cachedLog.Id = existing.Id;
+                                }
+                            }
+                            else
+                            {
+                                // 涓嶅瓨鍦紝鏂板
+                                toInsert.Add(log);
+                            }
+                        }
+
+                        // 鎵归噺鏂板
+                        if (toInsert.Any())
+                        {
+                            int rows = sugarClient.Fastest<Dt_InterfaceLog>().BulkCopy(toInsert);
+
+                            // 鑾峰彇鏂板鏃ュ織鐨勮嚜澧濱D骞舵洿鏂扮紦瀛�
+                            foreach (var insertedLog in toInsert)
+                            {
+                                var savedLog = sugarClient.Queryable<Dt_InterfaceLog>()
+                                    .First(x => x.RequestParametersHash == insertedLog.RequestParametersHash
+                                             && x.ResponseParametersHash == insertedLog.ResponseParametersHash);
+                                if (savedLog != null)
+                                {
+                                    string cacheKey = GenerateCacheKey(insertedLog.ApiCode,
+                                        insertedLog.RequestParametersHash, insertedLog.ResponseParametersHash);
+                                    if (_cacheLogs.TryGetValue(cacheKey, out var cachedLog))
+                                    {
+                                        cachedLog.Id = savedLog.Id;
+                                    }
+                                }
+                            }
+                        }
+
+                        // 鎵归噺鏇存柊鎺ㄩ�佹鏁�
+                        if (toUpdate.Any())
+                        {
+                            foreach (var log in toUpdate)
+                            {
+                                sugarClient.Updateable<Dt_InterfaceLog>()
+                                    .SetColumns(it => new Dt_InterfaceLog
+                                    {
+                                        PushFrequency = log.PushFrequency,
+                                        PushState = log.PushState,
+                                        Remark = log.Remark,
+                                        //CreateDate = log.CreateDate
+                                        ModifyDate = log.ModifyDate
+                                    })
+                                    .Where(it => it.Id == log.Id)
+                                    .ExecuteCommand();
+                            }
+                        }
+
+                        sugarClient.CommitTran(); // 鎻愪氦浜嬪姟
+                    }
+                    catch (Exception ex)
+                    {
+                        sugarClient.RollbackTran(); // 鍥炴粴浜嬪姟
+                        Console.WriteLine($"澶勭悊鏃ュ織鎵规澶辫触: {ex.Message}");
+                    }
+                    finally
+                    {
+                        batchList.Clear();
+                    }
+                }
+                catch (Exception ex)
+                {
+                    Console.WriteLine(ex.ToString());
+                }
+            }
+        }
+
+        private static void DequeueToBatchList(List<Dt_InterfaceLog> batchList)
+        {
+            if (loggerQueueData.TryDequeue(out Dt_InterfaceLog log) && log != null)
+            {
+                batchList.Add(log);
+            }
+        }
+
+        /// <summary>
+        /// 璁$畻瀛楃涓茬殑SHA256鍝堝笇鍊�
+        /// </summary>
+        private static string ComputeHash(string input)
+        {
+            if (string.IsNullOrEmpty(input))
+                return string.Empty;
+
+            using (SHA256 sha256 = SHA256.Create())
+            {
+                byte[] bytes = Encoding.UTF8.GetBytes(input);
+                byte[] hashBytes = sha256.ComputeHash(bytes);
+                return BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
+            }
+        }
+
+        /// <summary>
+        /// 鐢熸垚缂撳瓨Key
+        /// </summary>
+        private static string GenerateCacheKey(string apiCode, string requestHash, string responseHash)
+        {
+            string today = DateTime.Now.ToString("yyyy-MM-dd");
+            return $"{today}_{apiCode}_{requestHash}_{responseHash}";
+        }
+
+        /// <summary>
+        /// 鑾峰彇鎴栧垱寤烘棩蹇楋紙鐢ㄤ簬鍙犲姞鎺ㄩ�佹鏁帮級
+        /// </summary>
+        /// <param name="apiCode">缂栧彿</param>
+        /// <param name="apiName">鍚嶇О</param>
+        /// <param name="apiAddress">鍦板潃</param>
+        /// <param name="requestParameters">璇锋眰鍐呭</param>
+        /// <param name="responseParameters">鍝嶅簲鍐呭</param>
+        /// <param name="pushState">鐘舵��</param>
+        /// <param name="requestorUserIP">璇锋眰鐢ㄦ埛IP</param>
+        /// <param name="requestor">璇锋眰鏂�</param>
+        /// <param name="recipient">鎺ユ敹鏂�</param>
+        /// <param name="remark">澶囨敞</param>
+        /// <returns></returns>
+        private static Dt_InterfaceLog GetOrCreateLog(string apiCode, string apiName, string apiAddress,
+            string requestParameters, string responseParameters, int pushState,
+            string requestorUserIP, string requestor, string recipient, string remark)
+        {
+            string requestHash = ComputeHash(requestParameters);
+            string responseHash = ComputeHash(responseParameters);
+            string cacheKey = GenerateCacheKey(apiCode, requestHash, responseHash);
+
+            // 灏濊瘯浠庣紦瀛樹腑鑾峰彇
+            if (_cacheLogs.TryGetValue(cacheKey, out Dt_InterfaceLog existingLog))
+            {
+                // 瀛樺湪鐩稿悓鍙傛暟鐨勬棩蹇楋紝澧炲姞鎺ㄩ�佹鏁�
+                existingLog.PushFrequency++;
+                existingLog.PushState = pushState; // 鏇存柊鎺ㄩ�佺姸鎬�
+                existingLog.Remark = remark; // 鏇存柊澶囨敞
+                //existingLog.CreateDate = DateTime.Now; // 鏇存柊鏃堕棿
+                existingLog.ModifyDate = DateTime.Now; // 鏇存柊鏃堕棿
+
+                // 杩斿洖鐜版湁鏃ュ織锛堥渶瑕佹洿鏂版暟鎹簱锛�
+                return existingLog;
+            }
+            else
+            {
+                // 涓嶅瓨鍦紝鍒涘缓鏂版棩蹇�
+                var newLog = new Dt_InterfaceLog
+                {
+                    ApiCode = apiCode,
+                    ApiName = apiName,
+                    ApiAddress = apiAddress,
+                    PushFrequency = 1,
+                    PushState = pushState,
+                    RequestorUserIP = requestorUserIP,
+                    Requestor = requestor,
+                    RequestParameters = requestParameters,
+                    RequestParametersHash = requestHash,
+                    Recipient = recipient,
+                    ResponseParameters = responseParameters,
+                    ResponseParametersHash = responseHash,
+                    Remark = remark,
+                    Creater = "System",
+                    CreateDate = DateTime.Now
+                };
+
+                // 鍔犲叆缂撳瓨
+                _cacheLogs.TryAdd(cacheKey, newLog);
+
+                return newLog;
+            }
+        }
+
+        /// <summary>
+        /// 娣诲姞鎺ュ彛鏃ュ織锛堝甫URL銆佽姹傚弬鏁般�佸搷搴斿弬鏁般�佸紑濮嬫椂闂达級
+        /// </summary>
+        public static void Add(string apiCode, string apiName, string apiAddress,
+            string requestParameters, string responseParameters,
+            int pushState = 0, string recipient = "", string remark = "")
+        {
+            Dt_InterfaceLog log = null;
+            try
+            {
+                // 鑾峰彇褰撳墠鐢ㄦ埛
+                IUser? user = App.User;
+
+                // 鑾峰彇鎴栧垱寤烘棩蹇楋紙鑷姩澶勭悊鍙犲姞锛�
+                log = GetOrCreateLog(apiCode, apiName, apiAddress,
+                    requestParameters, responseParameters, pushState,
+                    "", user?.UserName ?? "", recipient, remark);
+            }
+            catch (Exception exception)
+            {
+                // 濡傛灉鍙戠敓寮傚父锛屽垱寤哄熀纭�鏃ュ織瀵硅薄
+                log = log ?? new Dt_InterfaceLog
+                {
+                    ApiCode = apiCode,
+                    ApiName = apiName,
+                    ApiAddress = apiAddress,
+                    PushFrequency = 1,
+                    PushState = pushState,
+                    RequestParameters = requestParameters,
+                    ResponseParameters = responseParameters,
+                    Creater = "System",
+                    Remark = $"璁板綍鏃ュ織鏃跺彂鐢熷紓甯革細{exception.Message}"
+                };
+            }
+
+            // 娣诲姞绯荤粺鏃ュ織
+            loggerQueueData.Enqueue(log);
+        }
+
+        /// <summary>
+        /// 娣诲姞鎺ュ彛鏃ュ織锛堜粠HttpContext鑷姩鑾峰彇淇℃伅锛�
+        /// </summary>
+        /// <param name="requestParameters">璇锋眰鍐呭</param>
+        /// <param name="responseParameters">鍝嶅簲鍐呭</param>
+        /// <param name="apiCode">鎺ュ彛缂栧彿</param>
+        /// <param name="apiName">鎺ュ彛鍚嶇О</param>
+        /// <param name="pushState">鎺ㄩ�佺姸鎬�</param>
+        /// <param name="recipient">鎺ユ敹鏂�</param>
+        /// <param name="remark">澶囨敞</param>
+        public static void Add(string requestParameters, string responseParameters, HttpContext context, string apiCode = "", string apiName = "", int pushState = 0, string recipient = "WCS", string remark = "")
+        {
+            Dt_InterfaceLog log = null;
+            try
+            {
+                // 濡傛灉璇锋眰鏂规硶涓篛PTIONS锛屽垯杩斿洖
+                if (context.Request.Method == "OPTIONS") return;
+
+                #region 鏁版嵁杞崲
+
+                // 瑙f瀽澶栧眰 JSON
+                JObject outerObj = JObject.Parse(requestParameters);
+
+                // 鑾峰彇 BodyData 鐨勫�硷紙瀹冩槸涓�涓瓧绗︿覆锛�
+                requestParameters = outerObj["BodyData"]?.ToString() ?? requestParameters;
+
+                // 鏋勫缓瀹屾暣鐨勬帴鍙e湴鍧�
+                string apiAddress = context.Request.Scheme + "://" + context.Request.Host + context.Request.PathBase + context.Request.Path;
+                // 鑾峰彇瀹㈡埛绔疘P
+                string clientIP = GetClientIP(context)?.Replace("::ffff:", "") ?? "";
+                string requestor = "";//璇锋眰鏂�
+                if (apiAddress.Contains("/api/WMS"))
+                {
+                    requestor = "WMS";//绉掍紭
+                    var wMSReturn = responseParameters.DeserializeObject<WMSReturn>();
+                    pushState = wMSReturn.code == 0 ? 1 : 2;
+                }
+                else if (apiAddress.Contains("/api/KHAGV"))
+                {
+                    requestor = "娴峰悍AGV";
+                    var hIKROBOTReturn = responseParameters.DeserializeObject<HIKROBOTReturn>();
+                    pushState = hIKROBOTReturn.code == "SUCCESS" ? 1 : 2;
+                }
+                else if (apiAddress.Contains("/api/KLS"))
+                {
+                    requestor = "鍑箰澹獳GV";
+                    ReturnGALAXIS returnGALAXIS = responseParameters.DeserializeObject<ReturnGALAXIS>();
+                    pushState = returnGALAXIS.returnStatus == 0 ? 1 : 2;
+                }
+                else if (apiAddress.Contains("/api/RGV"))
+                {
+                    requestor = "鍥涘悜绌挎杞�";//鏃疯娌冲浘
+                    FOURBOTReturn fOURBOTReturn = responseParameters.DeserializeObject<FOURBOTReturn>();
+                    pushState = fOURBOTReturn.returnCode == 0 ? 1 : 2;
+                }
+                apiCode = apiAddress.Split("/").Last();
+                apiName = AppSettings.Configuration.GetValue($"{requestor}:{apiCode}", apiCode);
+                #endregion
+
+                // 鑾峰彇鎴栧垱寤烘棩蹇楋紙鑷姩澶勭悊鍙犲姞锛�
+                log = GetOrCreateLog(apiCode, apiName, apiAddress,
+                    requestParameters, responseParameters, pushState,
+                    clientIP, requestor, recipient, remark);
+            }
+            catch (Exception exception)
+            {
+                // 濡傛灉鍙戠敓寮傚父锛屽垱寤哄熀纭�鏃ュ織瀵硅薄
+                log = log ?? new Dt_InterfaceLog
+                {
+                    ApiCode = apiCode,
+                    ApiName = apiName,
+                    PushFrequency = 1,
+                    PushState = pushState,
+                    RequestParameters = requestParameters,
+                    ResponseParameters = responseParameters,
+                    Creater = "System",
+                    Remark = $"璁板綍鏃ュ織鏃跺彂鐢熷紓甯革細{exception.Message}"
+                };
+            }
+
+            // 娣诲姞绯荤粺鏃ュ織
+            loggerQueueData.Enqueue(log);
+        }
+
+        /// <summary>
+        /// 鎵嬪姩澧炲姞鎺ㄩ�佹鏁帮紙鐢ㄤ簬閲嶈瘯鍦烘櫙锛�
+        /// </summary>
+        public static void IncrementPushCount(string apiCode, string requestParameters, string responseParameters)
+        {
+            string requestHash = ComputeHash(requestParameters);
+            string responseHash = ComputeHash(responseParameters);
+            string cacheKey = GenerateCacheKey(apiCode, requestHash, responseHash);
+
+            if (_cacheLogs.TryGetValue(cacheKey, out Dt_InterfaceLog existingLog))
+            {
+                existingLog.PushFrequency++;
+                loggerQueueData.Enqueue(existingLog);
+            }
+        }
+
+        public static string GetClientIP(HttpContext context)
+        {
+            // 鑾峰彇璇锋眰澶翠腑鐨刋-Forwarded-For瀛楁锛屽苟灏嗗叾杞崲涓哄瓧绗︿覆
+            var ip = context.Request.Headers["X-Forwarded-For"].ObjToString();
+            // 濡傛灉X-Forwarded-For瀛楁涓虹┖锛屽垯鑾峰彇杩滅▼IP鍦板潃
+            if (string.IsNullOrEmpty(ip))
+            {
+                ip = context.Connection.RemoteIpAddress.ObjToString();
+            }
+
+            // 杩斿洖IP鍦板潃
+            return ip;
+        }
+    }
+}
\ No newline at end of file
diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Filter/Log/MiddlewareHelpersNew.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Filter/Log/MiddlewareHelpersNew.cs"
new file mode 100644
index 0000000..c81600b
--- /dev/null
+++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Filter/Log/MiddlewareHelpersNew.cs"
@@ -0,0 +1,22 @@
+锘縰sing Microsoft.AspNetCore.Builder;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WIDESEAWCS_Core.Middlewares
+{
+    public static class MiddlewareHelpersNew
+    {
+        /// <summary>
+        /// 璇锋眰鍝嶅簲涓棿浠�
+        /// </summary>
+        /// <param name="app"></param>
+        /// <returns></returns>
+        public static IApplicationBuilder UseApiLogMiddlewareNew(this IApplicationBuilder app)
+        {
+            return app.UseMiddleware<ApiLogMiddlewareNew>();
+        }
+    }
+}
diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Program.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Program.cs"
index 75d3af8..8dfbad9 100644
--- "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Program.cs"
+++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Program.cs"
@@ -18,6 +18,7 @@
 using WIDESEAWCS_Core.Extensions;
 using WIDESEAWCS_Core.Filter;
 using WIDESEAWCS_Core.Helper;
+using WIDESEAWCS_Core.LogHelper;
 using WIDESEAWCS_Core.Middlewares;
 using WIDESEAWCS_QuartzJob;
 using WIDESEAWCS_QuartzJob.QuartzExtensions;
@@ -50,6 +51,25 @@
 builder.Services.AddHostedService<SeedDataHostedService>();//初始化数据库
 
 builder.Services.AddDbSetup();//Db 启动服务
+
+#region 添加日志清理服务
+var cleanupRetentionDays = builder.Configuration.GetValue<int>("LogCleanup:RetentionDays", 90);
+var cleanupHour = builder.Configuration.GetValue<int>("LogCleanup:CleanupHour", 2);
+var enableAutoCleanup = builder.Configuration.GetValue<bool>("LogCleanup:EnableAutoCleanup", true);
+var enableArchive = builder.Configuration.GetValue<bool>("LogCleanup:EnableArchive", false);
+var logRetentionDays = builder.Configuration.GetValue<int>("LogCleanup:LogRetentionDays", 30);
+
+builder.Services.AddSingleton(sp => new LogCleanupService
+{
+    RetentionDays = cleanupRetentionDays,
+    CleanupHour = cleanupHour,
+    EnableAutoCleanup = enableAutoCleanup,
+    EnableArchive = enableArchive,
+    LogRetentionDays= logRetentionDays,
+    CleanupIntervalHours = 24
+});
+builder.Services.AddHostedService(sp => sp.GetRequiredService<LogCleanupService>());
+#endregion
 
 //builder.Services.AddScoped<QuartzJobCreateDataTabel>();//任务调度 注入创建QuartzJob数据库表类
 //builder.Services.AddHostedService<QuartzJobDataTableHostedService>();//任务调度 映射QuartzJob数据库表
@@ -123,7 +143,8 @@
 app.UseSwaggerMiddle(() => Assembly.GetExecutingAssembly().GetManifestResourceStream("WIDESEAWCS_Server.index.html") ?? throw new Exception("未找到WIDESEAWCS_Server.index.html文件"));
 
 app.UseIpLimitMiddle();
-app.UseApiLogMiddleware();
+//app.UseApiLogMiddleware();
+app.UseApiLogMiddlewareNew();
 
 app.UseCors(AppSettings.Get(new string[] { "Cors", "PolicyName" }));
 
@@ -148,4 +169,14 @@
 
 app.MapControllers();
 
+#region 应用启动时立即清理一次
+//Task.Run(async () =>
+//{
+//    // 等待应用完全启动
+//    await Task.Delay(30000);
+//    var cleanupService = app.Services.GetRequiredService<LogCleanupService>();
+//    await cleanupService.ManualCleanup(90);
+//});
+#endregion
+
 app.Run();
diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Server.csproj" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Server.csproj"
index 87ccba2..c164b98 100644
--- "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Server.csproj"
+++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/WIDESEAWCS_Server.csproj"
@@ -76,8 +76,4 @@
 		</Content>
 	</ItemGroup>
 
-	<ItemGroup>
-	  <Folder Include="Log\" />
-	</ItemGroup>
-
 </Project>
diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json"
index 0541498..13f9b2e 100644
--- "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json"
+++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json"
@@ -17,6 +17,7 @@
   //5.PostgreSQL
   "DBType": "SqlServer",
   //杩炴帴瀛楃涓�
+  //"ConnectionString": "Data Source=172.16.161.20;Initial Catalog=WIDESEAWCS_GP;User ID=sa;Password=P@ssw0rd;Integrated Security=False;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
   "ConnectionString": "Data Source=.;Initial Catalog=WIDESEAWCS_GP;User ID=sa;Password=P@ssw0rd;Integrated Security=False;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
   //璺ㄥ煙
   "Cors": {
@@ -26,15 +27,39 @@
     // 娉ㄦ剰锛宧ttp://127.0.0.1:1818 鍜� http://localhost:1818 鏄笉涓�鏍风殑
     "IPs": "http://127.0.0.1:8080,http://localhost:8080"
   },
+  "LogCleanup": { //鎺ュ彛鏃ュ織娓呯悊閰嶇疆
+    "RetentionDays": 90, // 鏁版嵁淇濈暀澶╂暟
+    "CleanupHour": 2, // 娓呯悊鎵ц鏃堕棿锛堝皬鏃讹紝0-23锛�
+    "EnableAutoCleanup": true, // 鏄惁鍚敤鑷姩娓呯悊
+    "EnableArchive": true, // 鏄惁鍚敤褰掓。锛堝綊妗e埌鍘嗗彶琛級
+    "LogRetentionDays": 30 // 鏃ュ織鏂囦欢淇濈暀澶╂暟
+  },
   "ApiLogIgnore": "", //璁板綍鏃ュ織鏃讹紝蹇界暐鐨凙PI鍚嶇О锛屽涓敤閫楀彿鍒嗛殧锛岄厤缃殑涓嶈褰曞埌鏁版嵁搴撲腑
   "ApiName": "WIDESEAWCS",
   "ExpMinutes": 120,
+  "RequestPath": "GET,WMS,RGV,KHAGV,KLSAGV", //,
+  ///鎺ュ彛璇存槑锛氭帴鍙f棩蹇楄褰曚娇鐢�
+  "WMS": {
+    "ReceiveTask": "WMS涓嬪彂浠诲姟",
+    "ContainerRequest": "瀹瑰櫒娴佸姩璇锋眰",
+    "UpOrDownContainer": "骞冲簱璐т綅涓婁笅鏋跺鍣�",
+    "CancelWMSTask": "WMS鍙栨秷浠诲姟",
+    "IQCResult": "澶栨缁撴灉鍙嶉",
+    "UpdateArea": "淇敼搴撲綅鍒嗗尯",
+    "UpdateTaskGrade": "WMS淇敼浠诲姟浼樺厛绾�",
+    "QueryStation": "鍖哄煙搴撲綅淇℃伅鏌ヨ",
+    "UpLocationStatus": "鏇存柊浠撳簱搴撲綅鐘舵��"
+  },
+  "娴峰悍AGV": { "UpdateTaskStatus": "娴峰悍AGV浠诲姟鐘舵�佹洿鏂�" },
+  "鍑箰澹獳GV": { "UpdateTaskStatus": "鍑箰澹獳GV浠诲姟鐘舵�佹洿鏂�" },
+  "鍥涘悜绌挎杞�": { "UpdateTaskStatus": "鍥涘悜绌挎杞︿换鍔$姸鎬佹洿鏂�" },
+  ///鎺ュ彛璇存槑
   "QuartzJobAutoStart": true,
   "DBSeedEnable": false,
   "QuartzDBSeedEnable": false,
-  "LogDeubgEnable": true, //鏄惁璁板綍璋冭瘯鏃ュ織
-  "PrintSql": true, //鎵撳嵃SQL璇彞
-  "LogAOPEnable": true, //鏄惁璁板綍AOP鏃ュ織
+  "LogDeubgEnable": false, //鏄惁璁板綍璋冭瘯鏃ュ織
+  "PrintSql": false, //鎵撳嵃SQL璇彞
+  "LogAOPEnable": false, //鏄惁璁板綍AOP鏃ュ織
   "WebSocketEnable": true, //鏄惁寮�鍚疻ebSocket鏈嶅姟
   "WebSocketPort": 9296 //WebSocket鏈嶅姟绔彛
 }
diff --git "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/Task/RGVTaskExtend.cs" "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/Task/RGVTaskExtend.cs"
index a695aa8..aff1ab6 100644
--- "a/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/Task/RGVTaskExtend.cs"
+++ "b/\344\273\243\347\240\201\347\256\241\347\220\206/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/Task/RGVTaskExtend.cs"
@@ -528,6 +528,13 @@
             try
             {
                 List<Dt_RGVLocationInfo> rGVLocationInfos = _rGVLocationInfoService.Repository.QueryData(x => blockPods.Contains(x.PalletCode));
+                var palletCodes = rGVLocationInfos.Select(x => x.PalletCode).ToList();
+                // 鑾峰彇 blockPods 涓瓨鍦ㄤ絾 palletCodes 涓笉瀛樺湪鐨勬墭鐩樼爜
+                var missingPalletCodes = blockPods.Except(palletCodes).ToList();
+                if (missingPalletCodes.Any())
+                {
+                    throw new Exception($"鏈壘鍒颁互涓嬮樆纰嶆墭璐т綅淇℃伅锛歿string.Join(",", missingPalletCodes)}");
+                }
                 var Items = _rGVLocationInfoService.GetMoveFreeLocationInfo(rGVLocationInfos);
 
                 List<Dt_Task> tasks = Items.Item1;

--
Gitblit v1.9.3