huangxiaoqiang
9 小时以前 960b33fa24c47a330e51a2c24859d681ae62caeb
Code Management/WCS/WIDESEA_WCSServer/WIDESEAWCS_SystemServices/Sys_LogService.cs
@@ -3,6 +3,7 @@
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WIDESEAWCS_Core;
using WIDESEAWCS_Core.BaseServices;
using WIDESEAWCS_ISystemRepository;
using WIDESEAWCS_ISystemServices;
@@ -12,8 +13,281 @@
{
    public class Sys_LogService : ServiceBase<Sys_Log, ISys_LogRepository>, ISys_LogService
    {
        private readonly string[] LogFolders = new[] { "Log", "Log_PLCReadWrite" };
        private int fileId = 2020;
        public Sys_LogService(ISys_LogRepository BaseDal) : base(BaseDal)
        {
        }
        public WebResponseContent GetLogName()
        {
            WebResponseContent content = new WebResponseContent();
            try
            {
                var data = new List<object>();
                fileId = 2020; // 重置ID
                foreach (string folderName in LogFolders)
                {
                    var folderPath = Path.Combine(AppContext.BaseDirectory, folderName);
                    var folderInfo = new DirectoryInfo(folderPath);
                    if (!folderInfo.Exists)
                    {
                        continue;
                    }
                    var folderData = BuildFolderTree(folderInfo, folderName);
                    data.Add(folderData);
                }
                return data.Any()
                    ? WebResponseContent.Instance.OK(data: data)
                    : WebResponseContent.Instance.Error("未找到日志文件夹");
            }
            catch (Exception ex)
            {
                return WebResponseContent.Instance.Error(ex.Message);
            }
        }
        public WebResponseContent GetLog(string fileName)
        {
            try
            {
                if (string.IsNullOrEmpty(fileName))
                {
                    return WebResponseContent.Instance.Error("文件名不能为空");
                }
                FileSearchResult searchResult = null;
                foreach (string folderName in LogFolders)
                {
                    var folderPath = Path.Combine(AppContext.BaseDirectory, folderName);
                    var folderInfo = new DirectoryInfo(folderPath);
                    if (!folderInfo.Exists)
                    {
                        continue;
                    }
                    searchResult = FindFileWithInfo(folderInfo, fileName, folderName);
                    if (searchResult != null)
                    {
                        break;
                    }
                }
                if (searchResult == null)
                {
                    return WebResponseContent.Instance.Error($"未找到日志文件: {fileName}");
                }
                // 读取文件内容
                var fileContent = ReadLogFileContent(searchResult.File.FullName);
                // 返回包含元数据的结果
                var result = new
                {
                    fileName = searchResult.File.Name,
                    fullPath = searchResult.File.FullName,
                    fatherNode = searchResult.SourceFolder,
                    fileSize = GetFileSize(searchResult.File.Length),
                    lastWriteTime = searchResult.File.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss"),
                    content = fileContent,
                    lineCount = fileContent.Count
                };
                return WebResponseContent.Instance.OK(data: result);
            }
            catch (IOException ex)
            {
                if (IsFileLockedException(ex))
                {
                    return WebResponseContent.Instance.Error($"日志文件正在被系统写入,请稍后再试");
                }
                return WebResponseContent.Instance.Error($"打开日志文件错误,{ex.Message}");
            }
            catch (Exception ex)
            {
                return WebResponseContent.Instance.Error($"打开日志文件错误,{ex.Message}");
            }
        }
        #region MyRegion
        private object BuildFolderTree(DirectoryInfo folder, string displayName)
        {
            var children = new List<object>();
            // 处理子目录
            foreach (var subDir in folder.GetDirectories().Where(x => x.Name != "Info").OrderByDescending(x => x.CreationTime))
            {
                var files = subDir.GetFiles()
                    .Select(file => new
                    {
                        label = file.Name,
                        id = fileId++,
                        hidden = true,
                        fatherNode = subDir.Name,
                        fullPath = file.FullName,
                        lastWriteTime = file.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss")
                    })
                    .ToList();
                if (files.Any())
                {
                    children.Add(new
                    {
                        label = subDir.Name,
                        children = files,
                        id = subDir.Name.GetHashCode(),
                        hidden = false
                    });
                }
            }
            // 处理根目录文件
            var rootFiles = folder.GetFiles()
                .Select(file => new
                {
                    label = file.Name,
                    id = fileId++,
                    hidden = true,
                    fatherNode = folder.Name,
                    fullPath = file.FullName,
                    lastWriteTime = file.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss")
                })
                .ToList();
            if (rootFiles.Any())
            {
                children.Add(new
                {
                    label = folder.Name,
                    children = rootFiles,
                    id = folder.Name.GetHashCode(),
                    hidden = false
                });
            }
            return new
            {
                label = displayName,
                children = children,
                id = displayName.GetHashCode(),
                hidden = false,
                fatherNode = folder.Name,
                isRoot = true
            };
        }
        private List<string> ReadLogFileContent(string filePath)
        {
            var lines = new List<string>();
            using (FileStream stream = new FileStream(
                filePath,
                FileMode.Open,
                FileAccess.Read,
                FileShare.ReadWrite))
            using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
            {
                // 如果文件太大,只读取最后1000行(可选)
                var fileInfo = new FileInfo(filePath);
                if (fileInfo.Length > 5 * 1024 * 1024) // 大于5MB
                {
                    return ReadLastLines(reader, 1000);
                }
                // 读取全部内容
                while (!reader.EndOfStream)
                {
                    var line = reader.ReadLine();
                    lines.Add(line);
                }
            }
            return lines;
        }
        private List<string> ReadLastLines(StreamReader reader, int lineCount)
        {
            var lines = new Queue<string>();
            string line;
            while ((line = reader.ReadLine()) != null)
            {
                lines.Enqueue(line);
                if (lines.Count > lineCount)
                {
                    lines.Dequeue();
                }
            }
            return lines.ToList();
        }
        /// <summary>
        /// 文件查找结果
        /// </summary>
        private class FileSearchResult
        {
            public FileInfo File { get; set; }
            public string SourceFolder { get; set; }
        }
        /// <summary>
        /// 查找文件并返回详细信息
        /// </summary>
        private FileSearchResult FindFileWithInfo(DirectoryInfo folder, string fileName, string sourceFolder)
        {
            // 查找当前目录
            var file = folder.GetFiles().FirstOrDefault(x => x.Name == fileName);
            if (file != null)
            {
                return new FileSearchResult
                {
                    File = file,
                    SourceFolder = sourceFolder
                };
            }
            // 递归查找子目录
            foreach (var subDir in folder.GetDirectories().Where(x => x.Name != "Info"))
            {
                var result = FindFileWithInfo(subDir, fileName, sourceFolder);
                if (result != null)
                {
                    return result;
                }
            }
            return null;
        }
        /// <summary>
        /// 获取可读的文件大小
        /// </summary>
        private string GetFileSize(long bytes)
        {
            string[] sizes = { "B", "KB", "MB", "GB" };
            double len = bytes;
            int order = 0;
            while (len >= 1024 && order < sizes.Length - 1)
            {
                order++;
                len = len / 1024;
            }
            return $"{len:0.##} {sizes[order]}";
        }
        private bool IsFileLockedException(IOException ex)
        {
            int errorCode = ex.HResult & 0xFFFF;
            return errorCode == 32 || errorCode == 33; // ERROR_SHARING_VIOLATION or ERROR_LOCK_VIOLATION
        }
        #endregion
    }
}