From 960b33fa24c47a330e51a2c24859d681ae62caeb Mon Sep 17 00:00:00 2001
From: huangxiaoqiang <huangxiaoqiang@hnkhzn.com>
Date: 星期四, 16 四月 2026 10:09:49 +0800
Subject: [PATCH] 重构任务与库存模型,增强日志管理与区域接口

---
 Code Management/WCS/WIDESEA_WCSServer/WIDESEAWCS_Server/Controllers/System/Sys_LogController.cs |  212 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 205 insertions(+), 7 deletions(-)

diff --git a/Code Management/WCS/WIDESEA_WCSServer/WIDESEAWCS_Server/Controllers/System/Sys_LogController.cs b/Code Management/WCS/WIDESEA_WCSServer/WIDESEAWCS_Server/Controllers/System/Sys_LogController.cs
index 5ad637c..f7a730a 100644
--- a/Code Management/WCS/WIDESEA_WCSServer/WIDESEAWCS_Server/Controllers/System/Sys_LogController.cs
+++ b/Code Management/WCS/WIDESEA_WCSServer/WIDESEAWCS_Server/Controllers/System/Sys_LogController.cs
@@ -1,25 +1,28 @@
-锘縰sing Microsoft.AspNetCore.Authorization;
+锘縰sing Autofac.Core;
+using Microsoft.AspNetCore.Authorization;
 using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Mvc;
+using System.Text;
 using WIDESEAWCS_Core;
 using WIDESEAWCS_Core.BaseController;
+using WIDESEAWCS_DTO.AGV;
 using WIDESEAWCS_ISystemServices;
-using WIDESEAWCS_ITaskInfoService;
 using WIDESEAWCS_Model.Models;
 
-namespace WIDESEAWCS_Server.Controllers.System
+namespace WIDESEAWCSServer.Controllers
 {
     [Route("api/Sys_Log")]
     [ApiController]
     public class Sys_LogController : ApiBaseController<ISys_LogService, Sys_Log>
     {
+        private const int MAX_FILE_SIZE_MB = 50;
+        private static readonly string[] ALLOWED_FILE_TYPES = { ".txt", ".log", ".csv", ".json", ".xml" };
+        private readonly string[] LogFolders = { "Log", "Log_PLCReadWrite" };
         private readonly IHttpContextAccessor _httpContextAccessor;
         public Sys_LogController(ISys_LogService service, IHttpContextAccessor httpContextAccessor) : base(service)
         {
             _httpContextAccessor = httpContextAccessor;
         }
-
-
 
         [HttpPost, Route("GetLogList"), AllowAnonymous]
         public WebResponseContent GetLogList()
@@ -32,6 +35,201 @@
         {
             return Service.GetLogData(parm);
         }
+
+        [HttpPost, Route("GetLogName"), AllowAnonymous]
+        public WebResponseContent GetLogName()
+        {
+            return Service.GetLogName();
+        }
+
+        [HttpPost, Route("GetLog"), AllowAnonymous]
+        public WebResponseContent GetLog(string fileName)
+        {
+            return Service.GetLog(fileName);
+        }
+
+        [HttpPost, HttpGet, Route("DownLoadLog"), AllowAnonymous]
+        public virtual async Task<ActionResult> DownLoadLog(string fileName)
+        {
+            try
+            {
+                // 鍙傛暟楠岃瘉
+                if (string.IsNullOrWhiteSpace(fileName))
+                {
+                    return BadRequest("鏂囦欢鍚嶄笉鑳戒负绌�");
+                }
+
+                // 瀹夊叏鎬ф鏌�
+                if (fileName.Contains("..") || Path.IsPathRooted(fileName) || fileName.Contains("/") || fileName.Contains("\\"))
+                {
+                    return BadRequest("鏃犳晥鐨勬枃浠跺悕");
+                }
+
+                // 妫�鏌ユ枃浠剁被鍨�
+                string extension = Path.GetExtension(fileName).ToLowerInvariant();
+                if (!IsAllowedFileType(extension))
+                {
+                    return BadRequest($"涓嶆敮鎸佺殑鏂囦欢绫诲瀷: {extension}");
+                }
+
+                // 鏌ユ壘鏂囦欢
+                var fileInfo = await FindLogFileAsync(fileName);
+
+                if (fileInfo == null)
+                {
+                    return NotFound($"鏂囦欢 {fileName} 涓嶅瓨鍦�");
+                }
+
+                // 妫�鏌ユ枃浠跺ぇ灏忥紙浠呯敤浜庨檺鍒讹紝涓嶅姞杞藉埌鍐呭瓨锛�
+                if (fileInfo.Length > MAX_FILE_SIZE_MB * 1024 * 1024)
+                {
+                    return BadRequest($"鏂囦欢杩囧ぇ锛岃秴杩噞MAX_FILE_SIZE_MB}MB闄愬埗");
+                }
+
+                string contentType = GetContentType(extension);
+
+                // 璁剧疆涓嬭浇澶�
+                Response.Headers.Add("Content-Disposition", $"attachment; filename=\"{System.Web.HttpUtility.UrlEncode(fileName, Encoding.UTF8)}\"");
+                Response.Headers.Add("Content-Length", fileInfo.Length.ToString());
+                Response.Headers.Add("Cache-Control", "no-cache, no-store, must-revalidate");
+                Response.Headers.Add("Pragma", "no-cache");
+                Response.Headers.Add("Expires", "0");
+
+                // 娴佸紡杩斿洖锛屼笉鍔犺浇鏁翠釜鏂囦欢鍒板唴瀛�
+                return File(CreateFileStream(fileInfo.FullName), contentType, fileName);
+            }
+            catch (UnauthorizedAccessException)
+            {
+                return StatusCode(403, "娌℃湁璁块棶璇ユ枃浠剁殑鏉冮檺");
+            }
+            catch (PathTooLongException)
+            {
+                return BadRequest("鏂囦欢璺緞杩囬暱");
+            }
+            catch (IOException ex)
+            {
+                if (IsFileLockedException(ex))
+                {
+                    return StatusCode(500, "鏂囦欢琚攣瀹氾紝鍙兘姝e湪琚郴缁熷啓鍏ワ紝璇风◢鍚庡啀璇�");
+                }
+                return StatusCode(500, $"鏂囦欢璇诲彇澶辫触: {ex.Message}");
+            }
+            catch (Exception ex)
+            {
+                return StatusCode(500, $"鏈嶅姟鍣ㄥ唴閮ㄩ敊璇�: {ex.Message}");
+            }
+        }
+
+        private async Task<FileInfo> FindLogFileAsync(string fileName)
+        {
+            var tasks = LogFolders.Select(folderName => Task.Run(() =>
+            {
+                var folderPath = Path.Combine(AppContext.BaseDirectory, folderName);
+                var folderInfo = new DirectoryInfo(folderPath);
+
+                if (!folderInfo.Exists)
+                {
+                    return null;
+                }
+
+                return FindFileInFolderAsync(folderInfo, fileName);
+            }));
+
+            var results = await Task.WhenAll(tasks);
+            return results.FirstOrDefault(result => result != null);
+        }
+        private async Task<FileInfo> FindFileInFolderAsync(DirectoryInfo folder, string fileName)
+        {
+            try
+            {
+                // 鍏堟煡鎵惧綋鍓嶇洰褰曚笅鐨勬枃浠�
+                var files = folder.GetFiles();
+                var file = files.FirstOrDefault(x => x.Name.Equals(fileName, StringComparison.OrdinalIgnoreCase));
+
+                if (file != null)
+                {
+                    return await Task.FromResult(file);
+                }
+
+                // 閫掑綊鏌ユ壘瀛愮洰褰曪紙鎺掗櫎Info鐩綍锛�
+                foreach (var subDir in folder.GetDirectories())
+                {
+                    // 璺宠繃Info鐩綍
+                    if (subDir.Name.Equals("Info", StringComparison.OrdinalIgnoreCase))
+                    {
+                        continue;
+                    }
+
+                    // 璺宠繃鏃犳硶璁块棶鐨勭洰褰�
+                    try
+                    {
+                        file = await FindFileInFolderAsync(subDir, fileName);
+                        if (file != null)
+                        {
+                            return file;
+                        }
+                    }
+                    catch (UnauthorizedAccessException)
+                    {
+                        // 璺宠繃鏃犳潈闄愯闂殑鐩綍
+                        continue;
+                    }
+                }
+            }
+            catch (UnauthorizedAccessException)
+            {
+                // 蹇界暐鏃犳潈璁块棶鐨勭洰褰�
+            }
+            catch (DirectoryNotFoundException)
+            {
+                // 蹇界暐涓嶅瓨鍦ㄧ殑鐩綍
+            }
+
+            return await Task.FromResult<FileInfo>(null);
+        }
+
+        private FileStream CreateFileStream(string filePath)
+        {
+            return new FileStream(
+                filePath,
+                FileMode.Open,
+                FileAccess.Read,
+                FileShare.ReadWrite, // 鍏佽鍏朵粬杩涚▼鍚屾椂璇诲彇/鍐欏叆
+                81920, // 缂撳啿鍖哄ぇ灏�
+                useAsync: true);
+        }
+
+        /// <summary>
+        /// 鍒ゆ柇鏄惁涓烘枃浠惰閿佸畾鐨勫紓甯�
+        /// </summary>
+        private bool IsFileLockedException(IOException ex)
+        {
+            int errorCode = ex.HResult & 0xFFFF;
+            return errorCode == 32 || errorCode == 33; // ERROR_SHARING_VIOLATION or ERROR_LOCK_VIOLATION
+        }
+
+        /// <summary>
+        /// 妫�鏌ユ枃浠剁被鍨嬫槸鍚﹀厑璁�
+        /// </summary>
+        private bool IsAllowedFileType(string extension)
+        {
+            return ALLOWED_FILE_TYPES.Contains(extension);
+        }
+
+        /// <summary>
+        /// 鑾峰彇Content-Type
+        /// </summary>
+        private string GetContentType(string extension)
+        {
+            return extension.ToLowerInvariant() switch
+            {
+                ".txt" => "text/plain; charset=utf-8",
+                ".log" => "text/plain; charset=utf-8",
+                ".csv" => "text/csv; charset=utf-8",
+                ".json" => "application/json; charset=utf-8",
+                ".xml" => "application/xml; charset=utf-8",
+                _ => "application/octet-stream"
+            };
+        }
     }
-   
-}
+}
\ No newline at end of file

--
Gitblit v1.9.3