Files
Neo-ZQYY/apps/admin-web/src/components/LogStream.tsx

85 lines
2.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 日志流展示组件。
*
* - 等宽字体展示日志行
* - 自动滚动到底部useRef + scrollIntoView
* - 提供"暂停自动滚动"按钮toggle
*/
import React, { useEffect, useRef, useState } from "react";
import { Button } from "antd";
import { PauseCircleOutlined, PlayCircleOutlined } from "@ant-design/icons";
export interface LogStreamProps {
/** 可选的执行 ID用于标题展示 */
executionId?: string;
/** 日志行数组 */
lines: string[];
}
const LogStream: React.FC<LogStreamProps> = ({ lines }) => {
const [autoscroll, setAutoscroll] = useState(true);
const bottomRef = useRef<HTMLDivElement>(null);
useEffect(() => {
if (autoscroll && bottomRef.current) {
bottomRef.current.scrollIntoView({ behavior: "smooth" });
}
}, [lines, autoscroll]);
const handleToggle = () => {
const next = !autoscroll;
setAutoscroll(next);
// 恢复时立即滚动到底部
if (next && bottomRef.current) {
bottomRef.current.scrollIntoView({ behavior: "smooth" });
}
};
return (
<div style={{ display: "flex", flexDirection: "column", height: "100%" }}>
<div style={{ marginBottom: 8, textAlign: "right" }}>
<Button
size="small"
icon={autoscroll ? <PauseCircleOutlined /> : <PlayCircleOutlined />}
onClick={handleToggle}
>
{autoscroll ? "暂停滚动" : "恢复滚动"}
</Button>
</div>
<div
style={{
flex: 1,
overflow: "auto",
background: "#1e1e1e",
color: "#d4d4d4",
fontFamily: "'Cascadia Code', 'Fira Code', 'Consolas', monospace",
fontSize: 13,
lineHeight: 1.6,
padding: 12,
borderRadius: 4,
minHeight: 300,
}}
>
{lines.length === 0 ? (
<div style={{ color: "#888" }}></div>
) : (
lines.map((line, i) => {
let color = "#d4d4d4";
if (/\bERROR\b/i.test(line)) color = "#f56c6c";
else if (/\bWARN(?:ING)?\b/i.test(line)) color = "#e6a23c";
return (
<div key={i} style={{ whiteSpace: "pre-wrap", wordBreak: "break-all", color }}>
{line}
</div>
);
})
)}
<div ref={bottomRef} />
</div>
</div>
);
};
export default LogStream;