mirror of
https://github.com/yyhuni/xingrin.git
synced 2026-01-31 11:46:16 +08:00
feat(system-logs): enhance ANSI log viewer with log level colorization
- Add LOG_LEVEL_COLORS configuration mapping for DEBUG, INFO, WARNING, WARN, ERROR, and CRITICAL levels - Implement hasAnsiCodes() function to detect presence of ANSI escape sequences in log content - Add colorizeLogContent() function to parse plain text logs and apply color styling based on log levels - Support dual-mode log parsing: ANSI color codes and plain text log level detection - Rename converter to ansiConverter for clarity and consistency - Change newline handling from true to false for manual line break control - Apply color-coded styling to timestamps (gray), log levels (level-specific colors), and messages - Add bold font-weight styling for CRITICAL level logs for better visibility
This commit is contained in:
@@ -8,11 +8,21 @@ interface AnsiLogViewerProps {
|
||||
className?: string
|
||||
}
|
||||
|
||||
// 日志级别颜色配置
|
||||
const LOG_LEVEL_COLORS: Record<string, string> = {
|
||||
DEBUG: "#4ec9b0", // cyan
|
||||
INFO: "#6a9955", // green
|
||||
WARNING: "#dcdcaa", // yellow
|
||||
WARN: "#dcdcaa", // yellow
|
||||
ERROR: "#f44747", // red
|
||||
CRITICAL: "#f44747", // red (bold handled separately)
|
||||
}
|
||||
|
||||
// 创建 ANSI 转换器实例
|
||||
const converter = new AnsiToHtml({
|
||||
const ansiConverter = new AnsiToHtml({
|
||||
fg: "#d4d4d4",
|
||||
bg: "#1e1e1e",
|
||||
newline: true,
|
||||
newline: false, // 我们自己处理换行
|
||||
escapeXML: true,
|
||||
colors: {
|
||||
0: "#1e1e1e", // black
|
||||
@@ -34,14 +44,57 @@ const converter = new AnsiToHtml({
|
||||
},
|
||||
})
|
||||
|
||||
// 检测内容是否包含 ANSI 颜色码
|
||||
function hasAnsiCodes(text: string): boolean {
|
||||
// ANSI 转义序列通常以 ESC[ 开头(\x1b[ 或 \u001b[)
|
||||
return /\x1b\[|\u001b\[/.test(text)
|
||||
}
|
||||
|
||||
// 解析纯文本日志内容,为日志级别添加颜色
|
||||
function colorizeLogContent(content: string): string {
|
||||
// 匹配日志格式: [时间] [级别] [模块:行号] 消息
|
||||
// 例如: [2025-01-05 10:30:00] [INFO] [apps.scan:123] 消息内容
|
||||
const logLineRegex = /^(\[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\]) (\[(DEBUG|INFO|WARNING|WARN|ERROR|CRITICAL)\]) (.*)$/
|
||||
|
||||
return content
|
||||
.split("\n")
|
||||
.map((line) => {
|
||||
const match = line.match(logLineRegex)
|
||||
|
||||
if (match) {
|
||||
const [, timestamp, levelBracket, level, rest] = match
|
||||
const color = LOG_LEVEL_COLORS[level] || "#d4d4d4"
|
||||
// ansiConverter.toHtml 已经处理了 HTML 转义
|
||||
const escapedTimestamp = ansiConverter.toHtml(timestamp)
|
||||
const escapedLevelBracket = ansiConverter.toHtml(levelBracket)
|
||||
const escapedRest = ansiConverter.toHtml(rest)
|
||||
|
||||
// 时间戳灰色,日志级别带颜色,其余默认色
|
||||
return `<span style="color:#808080">${escapedTimestamp}</span> <span style="color:${color};font-weight:${level === "CRITICAL" ? "bold" : "normal"}">${escapedLevelBracket}</span> ${escapedRest}`
|
||||
}
|
||||
|
||||
// 非标准格式的行,也进行 HTML 转义
|
||||
return ansiConverter.toHtml(line)
|
||||
})
|
||||
.join("\n")
|
||||
}
|
||||
|
||||
export function AnsiLogViewer({ content, className }: AnsiLogViewerProps) {
|
||||
const containerRef = useRef<HTMLPreElement>(null)
|
||||
const isAtBottomRef = useRef(true) // 跟踪用户是否在底部
|
||||
|
||||
// 将 ANSI 转换为 HTML
|
||||
// 解析日志并添加颜色
|
||||
// 支持两种模式:ANSI 颜色码和纯文本日志级别解析
|
||||
const htmlContent = useMemo(() => {
|
||||
if (!content) return ""
|
||||
return converter.toHtml(content)
|
||||
|
||||
// 如果包含 ANSI 颜色码,直接转换
|
||||
if (hasAnsiCodes(content)) {
|
||||
return ansiConverter.toHtml(content)
|
||||
}
|
||||
|
||||
// 否则解析日志级别添加颜色
|
||||
return colorizeLogContent(content)
|
||||
}, [content])
|
||||
|
||||
// 监听滚动事件,检测用户是否在底部
|
||||
|
||||
Reference in New Issue
Block a user