You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

331 lines
11 KiB

using System.Text.RegularExpressions;
namespace LTEMvcApp.Models
{
/// <summary>
/// 日志工具类
/// </summary>
public static class LogUtils
{
/// <summary>
/// 日志级别常量
/// </summary>
public static class LogLevels
{
public const int None = 0;
public const int Error = 1;
public const int Warn = 2;
public const int Info = 3;
public const int Debug = 4;
/// <summary>
/// 获取级别名称
/// </summary>
/// <param name="level">级别值</param>
/// <returns>级别名称</returns>
public static string GetLevelName(int level)
{
return level switch
{
None => "none",
Error => "error",
Warn => "warn",
Info => "info",
Debug => "debug",
_ => "unknown"
};
}
/// <summary>
/// 获取级别值
/// </summary>
/// <param name="levelName">级别名称</param>
/// <returns>级别值</returns>
public static int GetLevelValue(string levelName)
{
return levelName?.ToLower() switch
{
"none" => None,
"error" => Error,
"warn" => Warn,
"info" => Info,
"debug" => Debug,
_ => None
};
}
/// <summary>
/// 获取所有级别选项
/// </summary>
/// <returns>级别选项列表</returns>
public static List<LevelOption> GetLevelOptions()
{
return new List<LevelOption>
{
new() { Value = Error, Text = "Error" },
new() { Value = Warn, Text = "Warning" },
new() { Value = Info, Text = "Info" },
new() { Value = Debug, Text = "Debug" }
};
}
}
/// <summary>
/// 级别选项
/// </summary>
public class LevelOption
{
public int Value { get; set; }
public string Text { get; set; } = string.Empty;
}
/// <summary>
/// 时间戳转换为时间字符串
/// </summary>
/// <param name="timestamp">时间戳(毫秒)</param>
/// <param name="full">是否显示完整日期</param>
/// <returns>时间字符串</returns>
public static string TimestampToTime(long timestamp, bool full = false)
{
// 持续时间 (< 2000-01-01 00:00:00)
if (timestamp < 946681200000)
{
return TimestampToDuration(timestamp);
}
var dateTime = DateTimeOffset.FromUnixTimeMilliseconds(timestamp).DateTime;
if (full)
{
return dateTime.ToString("yyyy-MM-dd HH:mm:ss.fff");
}
return dateTime.ToString("HH:mm:ss.fff");
}
/// <summary>
/// 时间戳转换为持续时间字符串
/// </summary>
/// <param name="timestamp">时间戳(毫秒)</param>
/// <returns>持续时间字符串</returns>
public static string TimestampToDuration(long timestamp)
{
var prefix = timestamp < 0 ? "-" : "";
var absTimestamp = Math.Abs(timestamp);
var timeSpan = TimeSpan.FromMilliseconds(absTimestamp);
return $"{prefix}{timeSpan.Hours:D2}:{timeSpan.Minutes:D2}:{timeSpan.Seconds:D2}.{timeSpan.Milliseconds:D3}";
}
/// <summary>
/// 时间字符串转换为时间戳
/// </summary>
/// <param name="timeString">时间字符串</param>
/// <returns>时间戳,转换失败返回null</returns>
public static long? TimeStringToTimestamp(string timeString)
{
if (string.IsNullOrEmpty(timeString))
return null;
// 匹配格式: HH:mm:ss.fff 或 mm:ss.fff 或 ss.fff
var match = Regex.Match(timeString, @"^(((\d+):)?(\d+):)?(\d+)(\.(\d+))?$");
if (!match.Success)
return null;
var hours = int.Parse(match.Groups[3].Success ? match.Groups[3].Value : "0");
var minutes = int.Parse(match.Groups[4].Success ? match.Groups[4].Value : "0");
var seconds = int.Parse(match.Groups[5].Value);
var milliseconds = match.Groups[7].Success ? int.Parse(match.Groups[7].Value.PadRight(3, '0')) : 0;
return (hours * 3600000L) + (minutes * 60000L) + (seconds * 1000L) + milliseconds;
}
/// <summary>
/// 获取日期偏移量
/// </summary>
/// <param name="timestamp">时间戳</param>
/// <returns>日期偏移量</returns>
public static long GetDayOffset(long timestamp)
{
if (timestamp < 946681200000)
return 0;
var dateTime = DateTimeOffset.FromUnixTimeMilliseconds(timestamp).DateTime;
var dayStart = new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, 0, 0, 0, DateTimeKind.Utc);
return new DateTimeOffset(dayStart).ToUnixTimeMilliseconds();
}
/// <summary>
/// 字符串转ID
/// </summary>
/// <param name="str">字符串</param>
/// <returns>ID值</returns>
public static int StringToId(string str)
{
if (string.IsNullOrEmpty(str))
return 0;
var hash = 5381;
foreach (var c in str)
{
hash = ((hash << 5) + hash) ^ c;
}
return hash;
}
/// <summary>
/// 创建正则表达式
/// </summary>
/// <param name="pattern">模式</param>
/// <param name="ignoreCase">是否忽略大小写</param>
/// <returns>正则表达式,创建失败返回null</returns>
public static Regex? CreateRegex(string pattern, bool ignoreCase = true)
{
if (string.IsNullOrEmpty(pattern))
return null;
try
{
var options = ignoreCase ? RegexOptions.IgnoreCase : RegexOptions.None;
// 检查是否是正则表达式格式 /pattern/flags
var regexMatch = Regex.Match(pattern, @"^/(.+)/([gi]*)$");
if (regexMatch.Success)
{
var regexPattern = regexMatch.Groups[1].Value;
var flags = regexMatch.Groups[2].Value;
if (flags.Contains('i'))
options |= RegexOptions.IgnoreCase;
if (flags.Contains('g'))
options |= RegexOptions.Multiline;
return new Regex(regexPattern, options);
}
// 普通文本搜索,添加转义
var escapedPattern = Regex.Escape(pattern);
return new Regex(escapedPattern, options);
}
catch
{
return null;
}
}
/// <summary>
/// 高亮搜索文本
/// </summary>
/// <param name="text">原文本</param>
/// <param name="searchPattern">搜索模式</param>
/// <returns>高亮后的文本</returns>
public static string HighlightSearchText(string text, string searchPattern)
{
if (string.IsNullOrEmpty(text) || string.IsNullOrEmpty(searchPattern))
return text;
var regex = CreateRegex(searchPattern);
if (regex == null)
return text;
return regex.Replace(text, "<highlight>$&</highlight>");
}
/// <summary>
/// 格式化文件大小
/// </summary>
/// <param name="bytes">字节数</param>
/// <returns>格式化后的字符串</returns>
public static string FormatFileSize(long bytes)
{
string[] sizes = { "B", "KB", "MB", "GB", "TB" };
double len = bytes;
int order = 0;
while (len >= 1024 && order < sizes.Length - 1)
{
order++;
len = len / 1024;
}
return $"{len:0.##} {sizes[order]}";
}
/// <summary>
/// 解析大小字符串
/// </summary>
/// <param name="sizeString">大小字符串</param>
/// <returns>字节数</returns>
public static long ParseSizeString(string sizeString)
{
if (string.IsNullOrEmpty(sizeString))
return 0;
var match = Regex.Match(sizeString, @"^(\d+)([KMG])?$", RegexOptions.IgnoreCase);
if (!match.Success)
return 0;
var size = long.Parse(match.Groups[1].Value);
var unit = match.Groups[2].Value.ToUpper();
return unit switch
{
"K" => size * 1024,
"M" => size * 1024 * 1024,
"G" => size * 1024 * 1024 * 1024,
_ => size
};
}
/// <summary>
/// 获取颜色亮度
/// </summary>
/// <param name="color">颜色代码</param>
/// <returns>亮度值 (0-1)</returns>
public static double GetColorBrightness(string color)
{
var match = Regex.Match(color, @"#([\da-fA-F]{2})([\da-fA-F]{2})([\da-fA-F]{2})");
if (!match.Success)
return 1;
var r = int.Parse(match.Groups[1].Value, System.Globalization.NumberStyles.HexNumber);
var g = int.Parse(match.Groups[2].Value, System.Globalization.NumberStyles.HexNumber);
var b = int.Parse(match.Groups[3].Value, System.Globalization.NumberStyles.HexNumber);
return (r * r * 0.299 + g * g * 0.587 + b * b * 0.114) / (255.0 * 255.0);
}
/// <summary>
/// 获取文本颜色
/// </summary>
/// <param name="backgroundColor">背景颜色</param>
/// <returns>文本颜色</returns>
public static string GetTextColor(string backgroundColor)
{
var brightness = GetColorBrightness(backgroundColor);
return brightness >= 0.15 ? "black" : "white";
}
/// <summary>
/// 生成唯一ID
/// </summary>
/// <returns>唯一ID</returns>
public static string GenerateUniqueId()
{
return Guid.NewGuid().ToString("N");
}
/// <summary>
/// 安全地执行操作
/// </summary>
/// <param name="action">要执行的操作</param>
/// <param name="defaultValue">默认值</param>
/// <returns>操作结果或默认值</returns>
public static T SafeExecute<T>(Func<T> action, T defaultValue)
{
try
{
return action();
}
catch
{
return defaultValue;
}
}
}
}