react-terminal-viewer-cicd 3.0.0-beta.40 → 3.0.0-beta.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/Addon/WorkerLog/LogWorker.js +1 -1
- package/dist/esm/PipelineLogViewer/PipelineLogViewer.d.ts.map +1 -0
- package/dist/esm/PipelineLogViewer/PipelineLogViewer.js +135 -43
- package/dist/esm/PipelineLogViewer/components/GroupHeader.d.ts +2 -2
- package/dist/esm/PipelineLogViewer/components/GroupHeader.d.ts.map +1 -1
- package/dist/esm/PipelineLogViewer/components/GroupHeader.js +18 -5
- package/dist/esm/PipelineLogViewer/components/SearchBar.d.ts.map +1 -0
- package/dist/esm/PipelineLogViewer/components/StickyHeader.d.ts +3 -2
- package/dist/esm/PipelineLogViewer/components/StickyHeader.d.ts.map +1 -1
- package/dist/esm/PipelineLogViewer/components/StickyHeader.js +4 -2
- package/dist/esm/PipelineLogViewer/hooks/useDisplayLogs.d.ts +1 -1
- package/dist/esm/PipelineLogViewer/hooks/useDisplayLogs.d.ts.map +1 -1
- package/dist/esm/PipelineLogViewer/hooks/useDisplayLogs.js +62 -27
- package/dist/esm/PipelineLogViewer/hooks/useLogFetcher.d.ts +15 -5
- package/dist/esm/PipelineLogViewer/hooks/useLogFetcher.d.ts.map +1 -0
- package/dist/esm/PipelineLogViewer/hooks/useLogFetcher.js +236 -173
- package/dist/esm/PipelineLogViewer/index.less +20 -4
- package/dist/esm/PipelineLogViewer/types.d.ts +3 -1
- package/dist/esm/PipelineLogViewer/types.d.ts.map +1 -1
- package/dist/esm/TerminalViewerVirtualDom/HumenTime.d.ts.map +1 -1
- package/dist/esm/TerminalViewerVirtualDom/HumenTime.js +25 -15
- package/dist/worker/src/PipelineLogViewer/components/GroupHeader.d.ts +2 -2
- package/dist/worker/src/PipelineLogViewer/components/StickyHeader.d.ts +3 -2
- package/dist/worker/src/PipelineLogViewer/hooks/useDisplayLogs.d.ts +1 -1
- package/dist/worker/src/PipelineLogViewer/hooks/useLogFetcher.d.ts +15 -5
- package/dist/worker/src/PipelineLogViewer/types.d.ts +3 -1
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
function LogWorker() {
|
|
2
2
|
var workerPath = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '/worker';
|
|
3
3
|
var worker = null;
|
|
4
|
-
var version = "3.0.0-beta.
|
|
4
|
+
var version = "3.0.0-beta.41" || '0.0.0';
|
|
5
5
|
var path = workerPath.includes('http') ? "".concat(workerPath, "/log.worker.js") : "".concat(window.location.origin).concat(workerPath, "/log.worker.js");
|
|
6
6
|
var blob = new Blob(["importScripts(\"".concat(path, "?v=").concat(version, "\")")], {
|
|
7
7
|
type: 'application/javascript'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PipelineLogViewer.d.ts","sourceRoot":"","sources":["../../../src/PipelineLogViewer/PipelineLogViewer.tsx"],"names":[],"mappings":"AAoBA,OAAO,KASN,MAAM,OAAO,CAAC;AAef,OAAO,cAAc,CAAC;AACtB,OAAO,KAAK,EAGV,sBAAsB,EACtB,oBAAoB,EACrB,MAAM,SAAS,CAAC;AAuEjB,QAAA,MAAM,iBAAiB,qGAgrCtB,CAAC;AAIF,eAAe,iBAAiB,CAAC"}
|
|
@@ -99,6 +99,21 @@ var VirtuosoFooterWithLoading = function VirtuosoFooterWithLoading() {
|
|
|
99
99
|
}, /*#__PURE__*/React.createElement(LoadingDots, null)));
|
|
100
100
|
};
|
|
101
101
|
|
|
102
|
+
/** 控制日志:END_stepId_status_timestamp_stepName(用于阶段结束标识,不作为正文展示) */
|
|
103
|
+
var isPipelineEndMarkerText = function isPipelineEndMarkerText(text) {
|
|
104
|
+
if (!text) return false;
|
|
105
|
+
// 日志经 ansi_up 处理后可能夹带 HTML 标签,先转成纯文本再判断。
|
|
106
|
+
var plainText = text.replace(/<[^>]*>/g, '').trim();
|
|
107
|
+
return /^END_[a-zA-Z0-9]+_(running|succeed|failure|cancel)_\d+_.+/.test(plainText);
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
/** 控制日志:START_stepId_status_timestamp_stepName(用于阶段开始标识,不作为正文展示) */
|
|
111
|
+
var isPipelineStartMarkerText = function isPipelineStartMarkerText(text) {
|
|
112
|
+
if (!text) return false;
|
|
113
|
+
var plainText = text.replace(/<[^>]*>/g, '').trim();
|
|
114
|
+
return /^START_[a-zA-Z0-9]+_(running|succeed|failure|cancel)_\d+_.+/.test(plainText);
|
|
115
|
+
};
|
|
116
|
+
|
|
102
117
|
// --------------------------------------------------------------------------
|
|
103
118
|
// 主组件
|
|
104
119
|
// --------------------------------------------------------------------------
|
|
@@ -120,7 +135,7 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
|
|
|
120
135
|
icons = _ref2.icons,
|
|
121
136
|
groupStatusIcons = _ref2.groupStatusIcons,
|
|
122
137
|
onCollapsedChange = _ref2.onCollapsedChange,
|
|
123
|
-
|
|
138
|
+
serverOffsetTime = _ref2.serverOffsetTime,
|
|
124
139
|
highlightOptions = _ref2.highlightOptions;
|
|
125
140
|
// ===================================================================
|
|
126
141
|
// 一、分组数据
|
|
@@ -170,6 +185,7 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
|
|
|
170
185
|
});
|
|
171
186
|
|
|
172
187
|
// 部分折叠模式下,缓冲窗口切换后若某分组已展开但与当前窗口无交集,自动折叠(避免出现展开图标却无日志)
|
|
188
|
+
// 必须随 collapsedGroups 变化重跑:仅折叠某一组时游标往往不变,否则不会自动折起缓冲外的展开组。
|
|
173
189
|
var collapseExpandedGroupsOutsideBuffer = groupManager.collapseExpandedGroupsOutsideBuffer;
|
|
174
190
|
/* eslint-disable react-hooks/exhaustive-deps -- 仅依赖游标起止行,避免整个 cursor 引用抖动 */
|
|
175
191
|
useLayoutEffect(function () {
|
|
@@ -177,7 +193,7 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
|
|
|
177
193
|
currentStartRow = _logFetcherResult$cur.currentStartRow,
|
|
178
194
|
currentEndRow = _logFetcherResult$cur.currentEndRow;
|
|
179
195
|
collapseExpandedGroupsOutsideBuffer(currentStartRow, currentEndRow);
|
|
180
|
-
}, [logFetcherResult.cursor.currentStartRow, logFetcherResult.cursor.currentEndRow, collapseExpandedGroupsOutsideBuffer]);
|
|
196
|
+
}, [logFetcherResult.cursor.currentStartRow, logFetcherResult.cursor.currentEndRow, collapseExpandedGroupsOutsideBuffer, groupManager.collapsedGroups]);
|
|
181
197
|
/* eslint-enable react-hooks/exhaustive-deps */
|
|
182
198
|
|
|
183
199
|
// 传递折叠状态给外部
|
|
@@ -257,6 +273,11 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
|
|
|
257
273
|
var headRemovedFromNextRef = useRef(0);
|
|
258
274
|
// 程序触发滚动(如初始化、搜索跨页)时,短暂屏蔽 rangeChanged 的误触发
|
|
259
275
|
var ignoreBoundaryFetchRef = useRef(0);
|
|
276
|
+
/** 最近一次 Virtuoso rangeChanged,用于 ignore 窗口结束后补一次边界检测(快速拖条时 range 可能不再变化) */
|
|
277
|
+
var lastRangeChangedRef = useRef(null);
|
|
278
|
+
var handleRangeChangedRef = useRef(null);
|
|
279
|
+
var handleStartReachedRef = useRef(null);
|
|
280
|
+
var boundaryIgnoreFollowUpTimeoutRef = useRef(null);
|
|
260
281
|
// 记录当前是否在底部。达到 maxMemoryLines 后 totalCount 可能不再增长,
|
|
261
282
|
// followOutput 不一定会触发,这里用于兜底自动跟随。
|
|
262
283
|
var isAtBottomRef = useRef(true);
|
|
@@ -271,13 +292,13 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
|
|
|
271
292
|
// 用户主动停止跟随:分组操作、置顶等交互后持续抑制自动滚动与 poll,
|
|
272
293
|
// 仅 scrollToBottom 时清除,恢复跟随。
|
|
273
294
|
var userStoppedFollowingRef = useRef(false);
|
|
274
|
-
//
|
|
275
|
-
var _useState3 = useState(
|
|
295
|
+
// 正在空降加载的分组(可多组排队尝试,但 fetch 层同一时刻只跑一个 airdrop)
|
|
296
|
+
var _useState3 = useState([]),
|
|
276
297
|
_useState4 = _slicedToArray(_useState3, 2),
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
/**
|
|
280
|
-
var airdropExpandInFlightRef = useRef(
|
|
298
|
+
loadingGroupNames = _useState4[0],
|
|
299
|
+
setLoadingGroupNames = _useState4[1];
|
|
300
|
+
/** 按分组记录空降展开进行中,仅阻止「同一分组」重复触发,避免全局锁死其它阶段 */
|
|
301
|
+
var airdropExpandInFlightRef = useRef(new Set());
|
|
281
302
|
|
|
282
303
|
// ===================================================================
|
|
283
304
|
// 六、吸顶指示器
|
|
@@ -345,7 +366,8 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
|
|
|
345
366
|
setGroups([]);
|
|
346
367
|
groupManager.expandAll();
|
|
347
368
|
logSearchResult.clearSearch();
|
|
348
|
-
|
|
369
|
+
setLoadingGroupNames([]);
|
|
370
|
+
airdropExpandInFlightRef.current.clear();
|
|
349
371
|
initializedRef.current = false;
|
|
350
372
|
userStoppedFollowingRef.current = false;
|
|
351
373
|
collapseAirdropActiveRef.current = false;
|
|
@@ -451,9 +473,32 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
|
|
|
451
473
|
if (!result.applied) {
|
|
452
474
|
pendingScrollAfterPrevRef.current = null;
|
|
453
475
|
displayLogsLenBeforeLoadPrevRef.current = null;
|
|
476
|
+
// initLoad / loadNext / airdrop 占用 fetching 时 loadPrev 会同步返回 busy,但不会再触发 rangeChanged,需解锁后重试
|
|
477
|
+
if (result.skipReason === 'busy') {
|
|
478
|
+
var rafAttempts = 0;
|
|
479
|
+
var retryWhenUnlocked = function retryWhenUnlocked() {
|
|
480
|
+
rafAttempts += 1;
|
|
481
|
+
if (rafAttempts > 600) return;
|
|
482
|
+
if (logFetcherResult.isFetchLocked()) {
|
|
483
|
+
requestAnimationFrame(retryWhenUnlocked);
|
|
484
|
+
return;
|
|
485
|
+
}
|
|
486
|
+
if (logFetcherResult.isFirstPageLocked()) return;
|
|
487
|
+
if (boundaryFetchingRef.current) return;
|
|
488
|
+
var el = scrollerDomRef.current;
|
|
489
|
+
if (!el) return;
|
|
490
|
+
var topIdx = firstVisibleIndexFromRenderedItems(lastRenderedItemsRef.current, el.scrollTop);
|
|
491
|
+
if (topIdx !== null && topIdx <= BOUNDARY_PREFETCH_INDEX_MARGIN) {
|
|
492
|
+
var _handleStartReachedRe;
|
|
493
|
+
(_handleStartReachedRe = handleStartReachedRef.current) === null || _handleStartReachedRe === void 0 || _handleStartReachedRe.call(handleStartReachedRef);
|
|
494
|
+
}
|
|
495
|
+
};
|
|
496
|
+
requestAnimationFrame(retryWhenUnlocked);
|
|
497
|
+
}
|
|
454
498
|
}
|
|
455
499
|
});
|
|
456
500
|
}, [logFetcherResult]);
|
|
501
|
+
handleStartReachedRef.current = handleStartReached;
|
|
457
502
|
|
|
458
503
|
// 向下滚动触及阈值 → 加载更多新日志
|
|
459
504
|
var handleEndReached = useCallback(function () {
|
|
@@ -497,6 +542,16 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
|
|
|
497
542
|
pendingScrollAfterPrevRef.current = null;
|
|
498
543
|
displayLogsLenBeforeLoadPrevRef.current = null;
|
|
499
544
|
ignoreBoundaryFetchRef.current = Date.now() + 500;
|
|
545
|
+
if (boundaryIgnoreFollowUpTimeoutRef.current) {
|
|
546
|
+
clearTimeout(boundaryIgnoreFollowUpTimeoutRef.current);
|
|
547
|
+
}
|
|
548
|
+
boundaryIgnoreFollowUpTimeoutRef.current = setTimeout(function () {
|
|
549
|
+
boundaryIgnoreFollowUpTimeoutRef.current = null;
|
|
550
|
+
var r = lastRangeChangedRef.current;
|
|
551
|
+
if (r && handleRangeChangedRef.current) {
|
|
552
|
+
handleRangeChangedRef.current(r);
|
|
553
|
+
}
|
|
554
|
+
}, 520);
|
|
500
555
|
applyBoundaryScrollCompensation(v, anchorRowPrev, displayLogs, {
|
|
501
556
|
sameLength: sameLength && prepended > 0,
|
|
502
557
|
sameLengthPixelDeltaCount: prepended,
|
|
@@ -540,6 +595,7 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
|
|
|
540
595
|
// ===================================================================
|
|
541
596
|
var handleRangeChanged = useCallback(function (range) {
|
|
542
597
|
var _el$scrollTop2;
|
|
598
|
+
lastRangeChangedRef.current = range;
|
|
543
599
|
currentStartIndexRef.current = range.startIndex;
|
|
544
600
|
var currentDisplayLogs = displayLogsRef.current;
|
|
545
601
|
// 吸顶:在 rangeChanged 内用当前 scrollTop + 已渲染项算视口顶行,避免先于 itemsRendered
|
|
@@ -573,6 +629,14 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
|
|
|
573
629
|
handleEndReached();
|
|
574
630
|
}
|
|
575
631
|
}, [logFetcherResult.boundaryLock.isFirstPage, logFetcherResult.boundaryLock.isLastPage, logFetcherResult.cursor.currentStartRow, stickyHeader, handleStartReached, handleEndReached]);
|
|
632
|
+
handleRangeChangedRef.current = handleRangeChanged;
|
|
633
|
+
useEffect(function () {
|
|
634
|
+
return function () {
|
|
635
|
+
if (boundaryIgnoreFollowUpTimeoutRef.current) {
|
|
636
|
+
clearTimeout(boundaryIgnoreFollowUpTimeoutRef.current);
|
|
637
|
+
}
|
|
638
|
+
};
|
|
639
|
+
}, []);
|
|
576
640
|
|
|
577
641
|
// 判断用户是否在浏览历史 (防打扰策略)
|
|
578
642
|
var handleAtBottomStateChange = useCallback(function (atBottom) {
|
|
@@ -822,7 +886,7 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
|
|
|
822
886
|
return g.name === name;
|
|
823
887
|
});
|
|
824
888
|
if (group) {
|
|
825
|
-
if (airdropExpandInFlightRef.current) return;
|
|
889
|
+
if (airdropExpandInFlightRef.current.has(name)) return;
|
|
826
890
|
var _logFetcherResult$cur3 = logFetcherResult.cursor,
|
|
827
891
|
bufStart = _logFetcherResult$cur3.currentStartRow,
|
|
828
892
|
bufEnd = _logFetcherResult$cur3.currentEndRow;
|
|
@@ -832,8 +896,10 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
|
|
|
832
896
|
userStoppedFollowingRef.current = true;
|
|
833
897
|
logFetcherResult.setIsUserBrowsingHistory(true);
|
|
834
898
|
if (!groupStartInBuffer) {
|
|
835
|
-
airdropExpandInFlightRef.current
|
|
836
|
-
|
|
899
|
+
airdropExpandInFlightRef.current.add(name);
|
|
900
|
+
setLoadingGroupNames(function (prev) {
|
|
901
|
+
return prev.includes(name) ? prev : [].concat(_toConsumableArray(prev), [name]);
|
|
902
|
+
});
|
|
837
903
|
var runAirdropThenExpand = /*#__PURE__*/function () {
|
|
838
904
|
var _ref8 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4() {
|
|
839
905
|
var ok;
|
|
@@ -865,8 +931,12 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
|
|
|
865
931
|
});
|
|
866
932
|
case 7:
|
|
867
933
|
_context4.prev = 7;
|
|
868
|
-
|
|
869
|
-
|
|
934
|
+
airdropExpandInFlightRef.current.delete(name);
|
|
935
|
+
setLoadingGroupNames(function (prev) {
|
|
936
|
+
return prev.filter(function (n) {
|
|
937
|
+
return n !== name;
|
|
938
|
+
});
|
|
939
|
+
});
|
|
870
940
|
return _context4.finish(7);
|
|
871
941
|
case 11:
|
|
872
942
|
case "end":
|
|
@@ -934,16 +1004,17 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
|
|
|
934
1004
|
return map;
|
|
935
1005
|
}, [groups]);
|
|
936
1006
|
|
|
937
|
-
/**
|
|
938
|
-
var
|
|
1007
|
+
/** START/END 控制行绝对行号集合(用于行号体系扣减,不参与分组边界判断) */
|
|
1008
|
+
var controlMarkerRows = useMemo(function () {
|
|
939
1009
|
var set = new Set();
|
|
940
|
-
var _iterator2 = _createForOfIteratorHelper(
|
|
1010
|
+
var _iterator2 = _createForOfIteratorHelper(displayLogs),
|
|
941
1011
|
_step2;
|
|
942
1012
|
try {
|
|
943
1013
|
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
944
|
-
var
|
|
945
|
-
|
|
946
|
-
|
|
1014
|
+
var line = _step2.value;
|
|
1015
|
+
if (isPipelineEndMarkerText(line.text) || isPipelineStartMarkerText(line.text)) {
|
|
1016
|
+
set.add(line.absoluteRow);
|
|
1017
|
+
}
|
|
947
1018
|
}
|
|
948
1019
|
} catch (err) {
|
|
949
1020
|
_iterator2.e(err);
|
|
@@ -951,7 +1022,7 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
|
|
|
951
1022
|
_iterator2.f();
|
|
952
1023
|
}
|
|
953
1024
|
return set;
|
|
954
|
-
}, [
|
|
1025
|
+
}, [displayLogs]);
|
|
955
1026
|
|
|
956
1027
|
/** 整条流水线日志起算绝对行号(用于全局连续行号) */
|
|
957
1028
|
var pipelineMinAbsoluteRow = useMemo(function () {
|
|
@@ -973,8 +1044,8 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
|
|
|
973
1044
|
searchStateRef.current = logSearchResult.searchState;
|
|
974
1045
|
var lineNumberWidthRef = useRef(lineNumberWidth);
|
|
975
1046
|
lineNumberWidthRef.current = lineNumberWidth;
|
|
976
|
-
var
|
|
977
|
-
|
|
1047
|
+
var controlMarkerRowsRef = useRef(controlMarkerRows);
|
|
1048
|
+
controlMarkerRowsRef.current = controlMarkerRows;
|
|
978
1049
|
var pipelineMinAbsoluteRowRef = useRef(pipelineMinAbsoluteRow);
|
|
979
1050
|
pipelineMinAbsoluteRowRef.current = pipelineMinAbsoluteRow;
|
|
980
1051
|
|
|
@@ -984,13 +1055,13 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
|
|
|
984
1055
|
// 但滑动窗口满载后 head-trim 导致 totalCount 不变、同 index 映射到新数据,
|
|
985
1056
|
// 此时需要通过 currentStartRow 变化来强制刷新。
|
|
986
1057
|
var currentStartRow = logFetcherResult.cursor.currentStartRow;
|
|
987
|
-
var
|
|
988
|
-
|
|
1058
|
+
var loadingGroupNamesRef = useRef(loadingGroupNames);
|
|
1059
|
+
loadingGroupNamesRef.current = loadingGroupNames;
|
|
989
1060
|
var renderVersion = useMemo(function () {
|
|
990
1061
|
return {};
|
|
991
1062
|
},
|
|
992
1063
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
993
|
-
[groupManager.collapsedGroups, logSearchResult.searchState, lineNumberWidth, currentStartRow, highlightOptions, groups,
|
|
1064
|
+
[groupManager.collapsedGroups, logSearchResult.searchState, lineNumberWidth, currentStartRow, highlightOptions, groups, loadingGroupNames]);
|
|
994
1065
|
var itemContent = useCallback(function (index) {
|
|
995
1066
|
var _groupsForHeader;
|
|
996
1067
|
var currentDisplayLogs = displayLogsRef.current;
|
|
@@ -1025,9 +1096,12 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
|
|
|
1025
1096
|
var isMatched = currentSearchState.matchedRowsSet.has(line.absoluteRow);
|
|
1026
1097
|
var activeRow = currentSearchState.currentMatchIndex >= 0 ? currentSearchState.positions[currentSearchState.currentMatchIndex] : -1;
|
|
1027
1098
|
var isActiveMatch = line.absoluteRow === activeRow;
|
|
1028
|
-
var showLogRow = !line.isFoldedGroupStart;
|
|
1029
|
-
var
|
|
1030
|
-
var
|
|
1099
|
+
var showLogRow = !line.isFoldedGroupStart && !line.isEmptyGroupStart;
|
|
1100
|
+
var isControlEndMarker = isPipelineEndMarkerText(line.text);
|
|
1101
|
+
var isControlStartMarker = isPipelineStartMarkerText(line.text);
|
|
1102
|
+
/** 仅压扁 START/END 控制行;行号体系也仅基于控制行扣减 */
|
|
1103
|
+
var collapseGroupEdgeLog = showLogRow && !line.isEmptyGroupStart && (isControlEndMarker || isControlStartMarker);
|
|
1104
|
+
var lineNumberLabel = groups.length > 0 && showLogRow ? getGlobalVisibleLineNumberLabel(line.absoluteRow, controlMarkerRowsRef.current, pipelineMinAbsoluteRowRef.current) : undefined;
|
|
1031
1105
|
var logRow = /*#__PURE__*/React.createElement(LogRow, {
|
|
1032
1106
|
absoluteRow: line.absoluteRow,
|
|
1033
1107
|
lineNumberLabel: lineNumberLabel,
|
|
@@ -1045,10 +1119,10 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
|
|
|
1045
1119
|
key: group.name,
|
|
1046
1120
|
group: group,
|
|
1047
1121
|
collapsed: currentGroupManager.collapsedGroups.has(group.name),
|
|
1048
|
-
loading:
|
|
1122
|
+
loading: loadingGroupNamesRef.current.includes(group.name),
|
|
1049
1123
|
onToggle: handleToggleGroupRef.current,
|
|
1050
1124
|
groupStatusIcons: groupStatusIcons,
|
|
1051
|
-
|
|
1125
|
+
serverOffsetTime: serverOffsetTime
|
|
1052
1126
|
});
|
|
1053
1127
|
}), showLogRow && (collapseGroupEdgeLog ? /*#__PURE__*/React.createElement("div", {
|
|
1054
1128
|
className: "pipeline-log-hidden-row"
|
|
@@ -1081,32 +1155,51 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
|
|
|
1081
1155
|
needsTopWindow = bufStart > globalFirstRow;
|
|
1082
1156
|
ignoreBoundaryFetchRef.current = Date.now() + 500;
|
|
1083
1157
|
if (!needsTopWindow) {
|
|
1084
|
-
_context5.next =
|
|
1158
|
+
_context5.next = 22;
|
|
1085
1159
|
break;
|
|
1086
1160
|
}
|
|
1087
1161
|
// airdropLoad 完成时 React 尚未提交新 displayLogs,单帧 rAF 里 scrollToIndex(0)
|
|
1088
1162
|
// 仍作用在旧列表上(index 0 = 旧缓冲首行),无法置顶;与搜索跨页一致走 pending。
|
|
1089
1163
|
pendingScrollAlignRef.current = 'start';
|
|
1090
1164
|
pendingScrollRowRef.current = globalFirstRow;
|
|
1091
|
-
|
|
1165
|
+
// 轮询 loadNext 可能恰好持有 fetchingRef 锁,等其释放后再空降
|
|
1166
|
+
if (!logFetcherResult.isFetchLocked()) {
|
|
1167
|
+
_context5.next = 13;
|
|
1168
|
+
break;
|
|
1169
|
+
}
|
|
1170
|
+
_context5.next = 13;
|
|
1171
|
+
return new Promise(function (resolve) {
|
|
1172
|
+
var attempts = 0;
|
|
1173
|
+
var check = function check() {
|
|
1174
|
+
attempts += 1;
|
|
1175
|
+
if (!logFetcherResult.isFetchLocked() || attempts > 300) {
|
|
1176
|
+
resolve();
|
|
1177
|
+
return;
|
|
1178
|
+
}
|
|
1179
|
+
requestAnimationFrame(check);
|
|
1180
|
+
};
|
|
1181
|
+
requestAnimationFrame(check);
|
|
1182
|
+
});
|
|
1183
|
+
case 13:
|
|
1184
|
+
_context5.next = 15;
|
|
1092
1185
|
return logFetcherResult.airdropLoad(globalFirstRow, {
|
|
1093
1186
|
window: 'fromStart'
|
|
1094
1187
|
});
|
|
1095
|
-
case
|
|
1188
|
+
case 15:
|
|
1096
1189
|
ok = _context5.sent;
|
|
1097
1190
|
if (ok) {
|
|
1098
|
-
_context5.next =
|
|
1191
|
+
_context5.next = 20;
|
|
1099
1192
|
break;
|
|
1100
1193
|
}
|
|
1101
1194
|
pendingScrollRowRef.current = null;
|
|
1102
1195
|
pendingScrollAlignRef.current = 'center';
|
|
1103
1196
|
return _context5.abrupt("return");
|
|
1104
|
-
case
|
|
1197
|
+
case 20:
|
|
1105
1198
|
logFetcherResult.updateBoundaryLock({
|
|
1106
1199
|
isLastPage: false
|
|
1107
1200
|
});
|
|
1108
1201
|
return _context5.abrupt("return");
|
|
1109
|
-
case
|
|
1202
|
+
case 22:
|
|
1110
1203
|
requestAnimationFrame(function () {
|
|
1111
1204
|
var _virtuosoRef$current6;
|
|
1112
1205
|
(_virtuosoRef$current6 = virtuosoRef.current) === null || _virtuosoRef$current6 === void 0 || _virtuosoRef$current6.scrollToIndex({
|
|
@@ -1115,7 +1208,7 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
|
|
|
1115
1208
|
behavior: 'auto'
|
|
1116
1209
|
});
|
|
1117
1210
|
});
|
|
1118
|
-
case
|
|
1211
|
+
case 23:
|
|
1119
1212
|
case "end":
|
|
1120
1213
|
return _context5.stop();
|
|
1121
1214
|
}
|
|
@@ -1181,7 +1274,7 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
|
|
|
1181
1274
|
var isRunning = lastGroupStatus === 'running';
|
|
1182
1275
|
return {
|
|
1183
1276
|
EmptyPlaceholder: logFetcherResult.loading || isRunning ? undefined : EmptyPlaceholder,
|
|
1184
|
-
Footer:
|
|
1277
|
+
Footer: isRunning ? VirtuosoFooterWithLoading : VirtuosoFooterEmpty
|
|
1185
1278
|
};
|
|
1186
1279
|
}, [lastGroupStatus, logFetcherResult.loading]);
|
|
1187
1280
|
|
|
@@ -1211,9 +1304,10 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
|
|
|
1211
1304
|
}, /*#__PURE__*/React.createElement(StickyHeader, {
|
|
1212
1305
|
group: stickyHeader.stickyGroup,
|
|
1213
1306
|
collapsed: stickyHeader.stickyGroup ? groupManager.collapsedGroups.has(stickyHeader.stickyGroup.name) : false,
|
|
1307
|
+
loading: stickyHeader.stickyGroup != null && loadingGroupNames.includes(stickyHeader.stickyGroup.name),
|
|
1214
1308
|
onToggle: handleToggleGroup,
|
|
1215
1309
|
groupStatusIcons: groupStatusIcons,
|
|
1216
|
-
|
|
1310
|
+
serverOffsetTime: serverOffsetTime
|
|
1217
1311
|
}), /*#__PURE__*/React.createElement(Virtuoso, {
|
|
1218
1312
|
ref: virtuosoRef,
|
|
1219
1313
|
style: {
|
|
@@ -1226,9 +1320,7 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
|
|
|
1226
1320
|
scrollerRef: function scrollerRef(el) {
|
|
1227
1321
|
scrollerDomRef.current = el;
|
|
1228
1322
|
},
|
|
1229
|
-
itemsRendered: handleItemsRendered
|
|
1230
|
-
// overscan={400}
|
|
1231
|
-
,
|
|
1323
|
+
itemsRendered: handleItemsRendered,
|
|
1232
1324
|
defaultItemHeight: DEFAULT_VIRTUOSO_ITEM_HEIGHT,
|
|
1233
1325
|
rangeChanged: handleRangeChanged,
|
|
1234
1326
|
atBottomStateChange: handleAtBottomStateChange,
|
|
@@ -11,8 +11,8 @@ interface GroupHeaderProps {
|
|
|
11
11
|
onToggle: (groupName: string) => void;
|
|
12
12
|
/** 自定义状态图标 (可选) */
|
|
13
13
|
groupStatusIcons?: Record<string, React.ReactNode>;
|
|
14
|
-
/**
|
|
15
|
-
|
|
14
|
+
/** 服务端「当前」时间戳与本地 Date.now() 的偏移时间差 */
|
|
15
|
+
serverOffsetTime?: number;
|
|
16
16
|
}
|
|
17
17
|
declare const _default: React.NamedExoticComponent<GroupHeaderProps>;
|
|
18
18
|
export default _default;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GroupHeader.d.ts","sourceRoot":"","sources":["../../../../src/PipelineLogViewer/components/GroupHeader.tsx"],"names":[],"mappings":"AAOA,OAAO,
|
|
1
|
+
{"version":3,"file":"GroupHeader.d.ts","sourceRoot":"","sources":["../../../../src/PipelineLogViewer/components/GroupHeader.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAiB,MAAM,OAAO,CAAC;AAGtC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAK1C,UAAU,gBAAgB;IACxB,WAAW;IACX,KAAK,EAAE,SAAS,CAAC;IACjB,WAAW;IACX,SAAS,EAAE,OAAO,CAAC;IACnB,gCAAgC;IAChC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,eAAe;IACf,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,mBAAmB;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IACnD,sCAAsC;IACtC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;;AA8ED,wBAAuC"}
|
|
@@ -5,9 +5,11 @@
|
|
|
5
5
|
// 支持点击折叠/展开。独立于 Virtuoso 之外用于吸顶。
|
|
6
6
|
// ============================================================================
|
|
7
7
|
|
|
8
|
-
import React from 'react';
|
|
8
|
+
import React, { useRef } from 'react';
|
|
9
9
|
import ChevronRight from "../../TerminalViewerVirtualDom/ChevronRight";
|
|
10
10
|
import HumenTime from "../../TerminalViewerVirtualDom/HumenTime";
|
|
11
|
+
/** 仅抑制「双击第二下」级间隔(ms);大于此间隔的 detail>1 仍视为用户有意连点 */
|
|
12
|
+
var MULTI_CLICK_SUPPRESS_MS = 140;
|
|
11
13
|
var GroupHeader = function GroupHeader(_ref) {
|
|
12
14
|
var _group$endTime;
|
|
13
15
|
var group = _ref.group,
|
|
@@ -15,21 +17,32 @@ var GroupHeader = function GroupHeader(_ref) {
|
|
|
15
17
|
loading = _ref.loading,
|
|
16
18
|
onToggle = _ref.onToggle,
|
|
17
19
|
groupStatusIcons = _ref.groupStatusIcons,
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
+
serverOffsetTime = _ref.serverOffsetTime;
|
|
21
|
+
/**
|
|
22
|
+
* 原生双击的第二下 click 的 detail>=2,且与上一击间隔极短;需抑制,避免「展开后立刻被再点收起」抖动。
|
|
23
|
+
* 不能用「仅 detail===1 才响应」:系统在约 500ms 内会把连续单击也记成多击,导致第 2、4、6… 次点击被整段丢弃,
|
|
24
|
+
* 用户快速连点分组头会感觉「点了没反应」。
|
|
25
|
+
*/
|
|
26
|
+
var lastHandledClickTsRef = useRef(0);
|
|
20
27
|
var handleClick = function handleClick(e) {
|
|
21
|
-
if (e.detail !== 1) return;
|
|
22
28
|
if (loading) return;
|
|
29
|
+
var t = e.timeStamp;
|
|
30
|
+
if (e.detail > 1 && t - lastHandledClickTsRef.current < MULTI_CLICK_SUPPRESS_MS) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
lastHandledClickTsRef.current = t;
|
|
23
34
|
onToggle(group.name);
|
|
24
35
|
};
|
|
25
36
|
var statusIcon = groupStatusIcons === null || groupStatusIcons === void 0 ? void 0 : groupStatusIcons[group.status];
|
|
26
37
|
var runningIcon = groupStatusIcons === null || groupStatusIcons === void 0 ? void 0 : groupStatusIcons.running;
|
|
27
38
|
return /*#__PURE__*/React.createElement("div", {
|
|
28
39
|
className: "pipeline-log-group-header".concat(loading ? ' pipeline-log-group-header--loading' : ''),
|
|
40
|
+
title: loading ? '正在加载该阶段日志,请稍候' : undefined,
|
|
29
41
|
onClick: handleClick,
|
|
30
42
|
role: "button",
|
|
31
43
|
tabIndex: loading ? -1 : 0,
|
|
32
44
|
"aria-expanded": !collapsed,
|
|
45
|
+
"aria-disabled": loading || undefined,
|
|
33
46
|
"aria-busy": loading || undefined,
|
|
34
47
|
"aria-label": "".concat(collapsed ? '展开' : '折叠', " ").concat(group.name),
|
|
35
48
|
onKeyDown: function onKeyDown(e) {
|
|
@@ -59,7 +72,7 @@ var GroupHeader = function GroupHeader(_ref) {
|
|
|
59
72
|
startTime: group.startTime,
|
|
60
73
|
endTime: (_group$endTime = group.endTime) !== null && _group$endTime !== void 0 ? _group$endTime : undefined,
|
|
61
74
|
timing: group.status === 'running',
|
|
62
|
-
|
|
75
|
+
offsetTime: serverOffsetTime
|
|
63
76
|
})));
|
|
64
77
|
};
|
|
65
78
|
export default /*#__PURE__*/React.memo(GroupHeader);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SearchBar.d.ts","sourceRoot":"","sources":["../../../../src/PipelineLogViewer/components/SearchBar.tsx"],"names":[],"mappings":"AAoBA,OAAO,KAAwC,MAAM,OAAO,CAAC;AAE7D,MAAM,WAAW,cAAc;IAC7B,aAAa;IACb,KAAK,EAAE,MAAM,CAAC;IACd,2BAA2B;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW;IACX,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,eAAe;IACf,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,eAAe;IACf,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,WAAW;IACX,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,sBAAsB;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc;IACd,gBAAgB,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACnC,cAAc;IACd,eAAe,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAClC,YAAY;IACZ,KAAK,CAAC,EAAE;QACN,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;QACzB,EAAE,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;QACrB,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;QACvB,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;KACzB,CAAC;IACF;;OAEG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;;AAgID,wBAAqC"}
|
|
@@ -9,8 +9,9 @@ interface StickyHeaderProps {
|
|
|
9
9
|
onToggle: (groupName: string) => void;
|
|
10
10
|
/** 自定义分组状态图标 */
|
|
11
11
|
groupStatusIcons?: Record<PipelineLogStatus, React.ReactNode>;
|
|
12
|
-
/**
|
|
13
|
-
|
|
12
|
+
/** 服务端「当前」时间戳与本地 Date.now() 的偏移时间差 */
|
|
13
|
+
serverOffsetTime?: number;
|
|
14
|
+
loading?: boolean;
|
|
14
15
|
}
|
|
15
16
|
declare const _default: React.NamedExoticComponent<StickyHeaderProps>;
|
|
16
17
|
export default _default;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StickyHeader.d.ts","sourceRoot":"","sources":["../../../../src/PipelineLogViewer/components/StickyHeader.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAG7D,UAAU,iBAAiB;IACzB,yBAAyB;IACzB,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;IACxB,mCAAmC;IACnC,SAAS,EAAE,OAAO,CAAC;IACnB,+BAA+B;IAC/B,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,gBAAgB;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC,iBAAiB,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IAC9D,
|
|
1
|
+
{"version":3,"file":"StickyHeader.d.ts","sourceRoot":"","sources":["../../../../src/PipelineLogViewer/components/StickyHeader.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAG7D,UAAU,iBAAiB;IACzB,yBAAyB;IACzB,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;IACxB,mCAAmC;IACnC,SAAS,EAAE,OAAO,CAAC;IACnB,+BAA+B;IAC/B,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,gBAAgB;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC,iBAAiB,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IAC9D,sCAAsC;IACtC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;;AA0BD,wBAAwC"}
|
|
@@ -12,7 +12,8 @@ var StickyHeader = function StickyHeader(_ref) {
|
|
|
12
12
|
collapsed = _ref.collapsed,
|
|
13
13
|
onToggle = _ref.onToggle,
|
|
14
14
|
groupStatusIcons = _ref.groupStatusIcons,
|
|
15
|
-
|
|
15
|
+
serverOffsetTime = _ref.serverOffsetTime,
|
|
16
|
+
loading = _ref.loading;
|
|
16
17
|
if (!group) return null;
|
|
17
18
|
return /*#__PURE__*/React.createElement("div", {
|
|
18
19
|
className: "pipeline-log-sticky-header"
|
|
@@ -21,7 +22,8 @@ var StickyHeader = function StickyHeader(_ref) {
|
|
|
21
22
|
collapsed: collapsed,
|
|
22
23
|
onToggle: onToggle,
|
|
23
24
|
groupStatusIcons: groupStatusIcons,
|
|
24
|
-
|
|
25
|
+
serverOffsetTime: serverOffsetTime,
|
|
26
|
+
loading: loading
|
|
25
27
|
}));
|
|
26
28
|
};
|
|
27
29
|
export default /*#__PURE__*/React.memo(StickyHeader);
|
|
@@ -19,7 +19,7 @@ interface UseDisplayLogsReturn {
|
|
|
19
19
|
* 核心策略:
|
|
20
20
|
* 1. 遍历原始 logs,判断当前行所属 Group
|
|
21
21
|
* 2. 若 Group 被折叠,则仅保留该 Group 的第一行,并标记 isFoldedGroupStart = true
|
|
22
|
-
* 3.
|
|
22
|
+
* 3. 剔除折叠区间内的其余日志行
|
|
23
23
|
*/
|
|
24
24
|
declare function useDisplayLogs(options: UseDisplayLogsOptions): UseDisplayLogsReturn;
|
|
25
25
|
export default useDisplayLogs;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDisplayLogs.d.ts","sourceRoot":"","sources":["../../../../src/PipelineLogViewer/hooks/useDisplayLogs.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useDisplayLogs.d.ts","sourceRoot":"","sources":["../../../../src/PipelineLogViewer/hooks/useDisplayLogs.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEpE,UAAU,qBAAqB;IAC7B,eAAe;IACf,IAAI,EAAE,QAAQ,EAAE,CAAC;IACjB,qCAAqC;IACrC,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW;IACX,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,gBAAgB;IAChB,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC9B;AAED,UAAU,oBAAoB;IAC5B,6BAA6B;IAC7B,WAAW,EAAE,cAAc,EAAE,CAAC;CAC/B;AAED;;;;;;;GAOG;AACH,iBAAS,cAAc,CAAC,OAAO,EAAE,qBAAqB,GAAG,oBAAoB,CA8L5E;AAED,eAAe,cAAc,CAAC"}
|