mirror of
https://github.com/router-for-me/Cli-Proxy-API-Management-Center.git
synced 2026-02-02 19:00:49 +08:00
feat:log update
This commit is contained in:
@@ -27,11 +27,28 @@ export function LogsPage() {
|
|||||||
const [errorLogs, setErrorLogs] = useState<ErrorLogItem[]>([]);
|
const [errorLogs, setErrorLogs] = useState<ErrorLogItem[]>([]);
|
||||||
const [loadingErrors, setLoadingErrors] = useState(false);
|
const [loadingErrors, setLoadingErrors] = useState(false);
|
||||||
|
|
||||||
|
const logViewerRef = useRef<HTMLPreElement | null>(null);
|
||||||
|
const pendingScrollToBottomRef = useRef(false);
|
||||||
|
|
||||||
// 保存最新时间戳用于增量获取
|
// 保存最新时间戳用于增量获取
|
||||||
const latestTimestampRef = useRef<number>(0);
|
const latestTimestampRef = useRef<number>(0);
|
||||||
|
|
||||||
const disableControls = connectionStatus !== 'connected';
|
const disableControls = connectionStatus !== 'connected';
|
||||||
|
|
||||||
|
const isNearBottom = (node: HTMLPreElement | null) => {
|
||||||
|
if (!node) return true;
|
||||||
|
const threshold = 24;
|
||||||
|
return node.scrollHeight - node.scrollTop - node.clientHeight <= threshold;
|
||||||
|
};
|
||||||
|
|
||||||
|
const scrollToBottom = () => {
|
||||||
|
const node = logViewerRef.current;
|
||||||
|
if (!node) return;
|
||||||
|
node.scrollTop = node.scrollHeight;
|
||||||
|
};
|
||||||
|
|
||||||
|
const isWarningLine = (line: string) => /\bwarn(?:ing)?\b/i.test(line) || line.includes('警告');
|
||||||
|
|
||||||
const loadLogs = async (incremental = false) => {
|
const loadLogs = async (incremental = false) => {
|
||||||
if (connectionStatus !== 'connected') {
|
if (connectionStatus !== 'connected') {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
@@ -44,6 +61,8 @@ export function LogsPage() {
|
|||||||
setError('');
|
setError('');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
pendingScrollToBottomRef.current = !incremental || isNearBottom(logViewerRef.current);
|
||||||
|
|
||||||
const params = incremental && latestTimestampRef.current > 0
|
const params = incremental && latestTimestampRef.current > 0
|
||||||
? { after: latestTimestampRef.current }
|
? { after: latestTimestampRef.current }
|
||||||
: {};
|
: {};
|
||||||
@@ -166,6 +185,15 @@ export function LogsPage() {
|
|||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [autoRefresh, connectionStatus]);
|
}, [autoRefresh, connectionStatus]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!pendingScrollToBottomRef.current) return;
|
||||||
|
if (loading) return;
|
||||||
|
if (!logViewerRef.current) return;
|
||||||
|
|
||||||
|
scrollToBottom();
|
||||||
|
pendingScrollToBottomRef.current = false;
|
||||||
|
}, [loading, logLines]);
|
||||||
|
|
||||||
const logsText = logLines.join('\n');
|
const logsText = logLines.join('\n');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -193,7 +221,13 @@ export function LogsPage() {
|
|||||||
{loading ? (
|
{loading ? (
|
||||||
<div className="hint">{t('logs.loading')}</div>
|
<div className="hint">{t('logs.loading')}</div>
|
||||||
) : logsText ? (
|
) : logsText ? (
|
||||||
<pre className="log-viewer">{logsText}</pre>
|
<pre ref={logViewerRef} className="log-viewer log-viewer-lines">
|
||||||
|
{logLines.map((line, index) => (
|
||||||
|
<span key={index} className={`log-line${isWarningLine(line) ? ' log-line-warning' : ''}`}>
|
||||||
|
{line}
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
</pre>
|
||||||
) : (
|
) : (
|
||||||
<EmptyState title={t('logs.empty_title')} description={t('logs.empty_desc')} />
|
<EmptyState title={t('logs.empty_title')} description={t('logs.empty_desc')} />
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -615,6 +615,20 @@ textarea {
|
|||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.log-viewer-lines {
|
||||||
|
.log-line {
|
||||||
|
display: block;
|
||||||
|
padding: 1px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.log-line-warning {
|
||||||
|
color: var(--warning-text, #92400e);
|
||||||
|
background: var(--warning-bg, rgba(251, 191, 36, 0.18));
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 2px 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.hint {
|
.hint {
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user