fix: large logs page stuck

This commit is contained in:
jialin
2024-11-05 19:46:47 +08:00
parent 5f2115fff6
commit f684a3b0ae
8 changed files with 114 additions and 40 deletions
+1
View File
@@ -12,3 +12,4 @@
/.mfsu
.swc
.DS_Store
.idea
+10
View File
@@ -19,6 +19,16 @@ export default defineConfig({
history: {
type: 'hash'
},
analyze: {
analyzerMode: 'server',
analyzerPort: 8888,
openAnalyzer: true,
// generate stats file while ANALYZE_DUMP exist
generateStatsFile: false,
statsFilename: 'stats.json',
logLevel: 'info',
defaultSizes: 'parsed' // stat // gzip
},
base: process.env.npm_config_base || '/',
...(isProduction
? {
+3 -8
View File
@@ -26,10 +26,9 @@ const LogsInner: React.FC<LogsInnerProps> = (props) => {
index: data.length - 1,
align: 'bottom'
});
console.log('scrollToBottom', stopScroll.current, data.length);
}
}, 200),
[scroller.current, stopScroll.current, data]
[data, scroller.current, stopScroll.current]
);
const debounceResetStopScroll = _.debounce(() => {
@@ -66,7 +65,6 @@ const LogsInner: React.FC<LogsInnerProps> = (props) => {
(e: any) => {
const isBottom = isScrollBottom(logsWrapper.current);
const isTop = isScrollTop(logsWrapper.current);
console.log('isBottom===', isBottom);
if (isBottom) {
stopScroll.current = false;
} else {
@@ -79,10 +77,7 @@ const LogsInner: React.FC<LogsInnerProps> = (props) => {
);
useEffect(() => {
if (!stopScroll.current && data.length > 0) {
updataPositionToBottom();
console.log('updataPositionToBottom', stopScroll.current);
}
updataPositionToBottom();
}, [updataPositionToBottom]);
useEffect(() => {
@@ -115,7 +110,7 @@ const LogsInner: React.FC<LogsInnerProps> = (props) => {
}
}}
>
{(item: any) => (
{(item: any, index: number) => (
<div key={item.uid} className="text">
{item.content}
</div>
+1 -1
View File
@@ -97,7 +97,6 @@ const useParseAnsi = () => {
break;
case 'J': // clear the screen
if (n === 2) {
console.log('clear====');
screen = [['']];
cursorRow = 0;
cursorCol = 0;
@@ -132,6 +131,7 @@ const useParseAnsi = () => {
uid: setId()
});
}
result.push({
content: output,
uid: setId()
+38 -4
View File
@@ -5,6 +5,44 @@
position: absolute;
top: 16px;
right: 16px;
width: 40px;
height: 130px;
.pg-inner {
position: relative;
&::before {
content: '';
position: absolute;
top: 30px;
bottom: 30px;
right: 0;
width: 100px;
height: 60px;
&:hover {
.pagination {
display: flex;
}
}
}
.pagination {
display: none;
}
&:hover {
.pagination {
display: flex;
}
}
&.at-top {
.pagination {
display: flex;
}
}
}
}
.loading {
@@ -18,10 +56,6 @@
display: flex;
justify-content: center;
background-color: rgba(255, 255, 255, 25%);
.ant-spin-dot-holder {
color: rgba(255, 255, 255, 90%);
}
}
.copy {
+50 -25
View File
@@ -1,9 +1,16 @@
import useSetChunkFetch from '@/hooks/use-chunk-fetch';
import useSetChunkRequest from '@/hooks/use-chunk-request';
import { Spin } from 'antd';
import classNames from 'classnames';
import _ from 'lodash';
import { memo, useCallback, useEffect, useRef, useState } from 'react';
import {
forwardRef,
memo,
useCallback,
useEffect,
useImperativeHandle,
useRef,
useState
} from 'react';
import { controlSeqRegex, replaceLineRegex } from './config';
import LogsInner from './logs-inner';
import LogsPagination from './logs-pagination';
@@ -15,28 +22,38 @@ interface LogsViewerProps {
content?: string;
url: string;
params?: object;
ref?: any;
diffHeight?: number;
}
const LogsViewer: React.FC<LogsViewerProps> = (props) => {
const LogsViewer: React.FC<LogsViewerProps> = forwardRef((props, ref) => {
const { diffHeight, url } = props;
const { pageSize, page, setPage, setTotalPage, totalPage } =
useLogsPagination();
const { setChunkRequest } = useSetChunkRequest();
const { setChunkFetch } = useSetChunkFetch();
const chunkRequedtRef = useRef<any>(null);
const cacheDataRef = useRef<any>('');
const [logs, setLogs] = useState<any[]>([]);
const logParseWorker = useRef<any>(null);
const tail = useRef<any>(pageSize);
const isLoadend = useRef<any>(false);
const [isLoadend, setIsLoadend] = useState(false);
const [loading, setLoading] = useState(false);
const [isAtTop, setIsAtTop] = useState(false);
useImperativeHandle(ref, () => ({
abort() {
chunkRequedtRef.current?.current?.abort?.();
}
}));
useEffect(() => {
logParseWorker.current?.terminate?.();
logParseWorker.current = new Worker(
new URL('./parse-worker.ts', import.meta.url)
// @ts-ignore
new URL('./parse-worker.ts', import.meta.url),
{
type: 'module'
}
);
logParseWorker.current.onmessage = (event: any) => {
@@ -53,7 +70,7 @@ const LogsViewer: React.FC<LogsViewerProps> = (props) => {
const debounceLoading = _.debounce(() => {
setLoading(false);
}, 100);
}, 200);
const isClean = useCallback((input: string) => {
let match = controlSeqRegex.exec(input) || [];
@@ -64,9 +81,9 @@ const LogsViewer: React.FC<LogsViewerProps> = (props) => {
const getLastPage = useCallback(
(data: string) => {
const list = _.split(data, '\n');
isLoadend.current = list.length < pageSize;
console.log('isLoadend.current===', isLoadend.current, list.length);
const list = _.split(data.trim(), '\n');
console.log('list.length', list.length);
if (list.length <= pageSize) {
setTotalPage(1);
return data;
@@ -84,7 +101,7 @@ const LogsViewer: React.FC<LogsViewerProps> = (props) => {
);
const getPrePage = useCallback(() => {
const list = _.split(cacheDataRef.current, '\n');
const list = _.split(cacheDataRef.current.trim(), '\n');
let newPage = page - 1;
if (newPage < 1) {
newPage = 1;
@@ -99,7 +116,7 @@ const LogsViewer: React.FC<LogsViewerProps> = (props) => {
}, [page, pageSize]);
const getNextPage = useCallback(() => {
const list = _.split(cacheDataRef.current, '\n');
const list = _.split(cacheDataRef.current.trim(), '\n');
let newPage = page + 1;
if (newPage > totalPage) {
newPage = totalPage;
@@ -146,17 +163,18 @@ const LogsViewer: React.FC<LogsViewerProps> = (props) => {
};
const handleOnScroll = useCallback(
(isTop: boolean) => {
setIsAtTop(isTop && isLoadend.current);
if (loading || isLoadend.current) {
async (isTop: boolean) => {
setIsAtTop(isTop);
if (loading || isLoadend || logs.length < pageSize) {
return;
}
if (isTop && !isLoadend.current) {
if (isTop && !isLoadend) {
tail.current = undefined;
createChunkConnection();
setIsLoadend(true);
}
},
[loading, isLoadend.current]
[loading, isLoadend, logs.length, pageSize]
);
useEffect(() => {
@@ -182,19 +200,26 @@ const LogsViewer: React.FC<LogsViewerProps> = (props) => {
loading: loading && isAtTop
})}
></Spin>
{totalPage > 1 && isAtTop && (
{totalPage > 1 && (
<div className="pg">
<LogsPagination
page={page}
total={totalPage}
onNext={getNextPage}
onPrev={getPrePage}
></LogsPagination>
<div
className={classNames('pg-inner', {
'at-top': isAtTop
})}
>
<LogsPagination
page={page}
total={totalPage}
pageSize={pageSize}
onNext={getNextPage}
onPrev={getPrePage}
></LogsPagination>
</div>
</div>
)}
</div>
</div>
);
};
});
export default memo(LogsViewer);
+3 -1
View File
@@ -8,6 +8,7 @@ interface RequestConfig {
beforeReconnect?: () => void;
params?: object;
byLine?: boolean;
watch?: boolean;
contentType?: 'json' | 'text';
}
@@ -70,6 +71,7 @@ const useSetChunkFetch = () => {
const fetchChunkRequest = async ({
url,
handler,
watch,
byLine = false,
params = {}
}: RequestConfig) => {
@@ -79,7 +81,7 @@ const useSetChunkFetch = () => {
const response = await fetch(
`v1${url}?${qs.stringify({
...params,
watch: true
watch: watch === undefined ? true : watch
})}`,
{
method: 'GET',
@@ -17,6 +17,7 @@ const ViewCodeModal: React.FC<ViewModalProps> = (props) => {
height: 420
});
const isFullScreenRef = React.useRef(false);
const logsViewerRef = React.useRef<any>(null);
const intl = useIntl();
const viewportHeight = window.innerHeight;
const viewHeight = viewportHeight - 86;
@@ -31,6 +32,11 @@ const ViewCodeModal: React.FC<ViewModalProps> = (props) => {
});
}, []);
const handleCancel = useCallback(() => {
logsViewerRef.current?.abort();
onCancel();
}, [onCancel]);
useEffect(() => {
if (open) {
isFullScreenRef.current = false;
@@ -53,7 +59,7 @@ const ViewCodeModal: React.FC<ViewModalProps> = (props) => {
}
open={open}
centered={true}
onCancel={onCancel}
onCancel={handleCancel}
destroyOnClose={true}
closeIcon={true}
maskClosable={false}
@@ -67,6 +73,7 @@ const ViewCodeModal: React.FC<ViewModalProps> = (props) => {
footer={null}
>
<LogsViewer
ref={logsViewerRef}
height={modalSize.height}
diffHeight={93}
url={url}