Skip to content

Commit d284618

Browse files
author
Taois
committed
feat:搜索恢复滚动位置
1 parent 0f6cbff commit d284618

File tree

2 files changed

+89
-14
lines changed

2 files changed

+89
-14
lines changed

dashboard/src/components/VideoGrid.vue

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -276,10 +276,32 @@ const checkAutoLoadMore = () => {
276276
}
277277
};
278278
279+
// 添加防止递归更新的变量
280+
let lastHeightRestoreTime = 0;
281+
let heightRestoreCount = 0;
282+
const HEIGHT_RESTORE_COOLDOWN = 1000; // 1秒冷却时间
283+
const MAX_HEIGHT_RESTORE_PER_MINUTE = 5; // 每分钟最多5次
284+
279285
// 检查并恢复容器高度到理想状态
280286
const checkHeightRestore = () => {
281287
if (isProcessing) return;
282288
289+
// 防止递归更新的严格检查
290+
const now = Date.now();
291+
if (now - lastHeightRestoreTime < HEIGHT_RESTORE_COOLDOWN) {
292+
return; // 冷却时间内不执行
293+
}
294+
295+
// 重置计数器(每分钟)
296+
if (now - lastHeightRestoreTime > 60000) {
297+
heightRestoreCount = 0;
298+
}
299+
300+
if (heightRestoreCount >= MAX_HEIGHT_RESTORE_PER_MINUTE) {
301+
console.warn('[VideoGrid] 高度恢复操作过于频繁,已暂停');
302+
return;
303+
}
304+
283305
try {
284306
const container = containerRef.value;
285307
if (!container) return;
@@ -296,15 +318,25 @@ const checkHeightRestore = () => {
296318
297319
// 如果内容足够多且当前容器高度小于理想高度,则恢复
298320
if (contentHeight > idealHeight * 0.8 && containerHeight < idealHeight) {
321+
const oldHeight = containerHeight;
299322
containerHeight = idealHeight;
300-
containerHeightTrigger.value++;
301323
302-
console.log('[DEBUG] 主动恢复容器高度:', {
303-
contentHeight,
304-
clientHeight,
305-
idealHeight,
306-
oldContainerHeight: containerHeight,
307-
newContainerHeight: idealHeight
324+
// 使用nextTick延迟触发更新,避免同步递归
325+
nextTick(() => {
326+
if (!isProcessing) { // 再次检查处理状态
327+
containerHeightTrigger.value++;
328+
heightRestoreCount++;
329+
lastHeightRestoreTime = now;
330+
331+
console.log('[DEBUG] 主动恢复容器高度:', {
332+
contentHeight,
333+
clientHeight,
334+
idealHeight,
335+
oldContainerHeight: oldHeight,
336+
newContainerHeight: idealHeight,
337+
restoreCount: heightRestoreCount
338+
});
339+
}
308340
});
309341
}
310342
} catch (error) {

dashboard/src/views/SearchAggregation.vue

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -998,15 +998,48 @@ export default defineComponent({
998998
};
999999
10001000
// 恢复滚动位置
1001-
const restoreScrollPosition = () => {
1001+
const restoreScrollPosition = (retryCount = 0) => {
10021002
if (scrollPosition.value > 0) {
1003-
nextTick(() => {
1003+
const maxRetries = 5;
1004+
const delay = Math.min(100 * Math.pow(2, retryCount), 1000); // 指数退避,最大1秒
1005+
1006+
const attemptRestore = () => {
10041007
const scrollContainer = scrollbarRef.value?.$el?.querySelector('.arco-scrollbar-container');
10051008
if (scrollContainer) {
1006-
scrollContainer.scrollTop = scrollPosition.value;
1007-
console.log('🔄 [滚动位置] 恢复滚动位置:', scrollPosition.value);
1009+
// 检查容器是否有内容
1010+
const hasContent = scrollContainer.scrollHeight > scrollContainer.clientHeight;
1011+
if (hasContent) {
1012+
scrollContainer.scrollTop = scrollPosition.value;
1013+
console.log('🔄 [滚动位置] 恢复滚动位置:', scrollPosition.value);
1014+
return true;
1015+
} else if (retryCount < maxRetries) {
1016+
console.log(`🔄 [滚动位置] 容器内容未完全加载,${delay}ms后重试 (${retryCount + 1}/${maxRetries})`);
1017+
setTimeout(() => restoreScrollPosition(retryCount + 1), delay);
1018+
return false;
1019+
}
1020+
} else if (retryCount < maxRetries) {
1021+
console.log(`🔄 [滚动位置] 滚动容器未找到,${delay}ms后重试 (${retryCount + 1}/${maxRetries})`);
1022+
setTimeout(() => restoreScrollPosition(retryCount + 1), delay);
1023+
return false;
10081024
}
1009-
});
1025+
1026+
if (retryCount >= maxRetries) {
1027+
console.warn('🔄 [滚动位置] 达到最大重试次数,滚动位置恢复失败');
1028+
}
1029+
return false;
1030+
};
1031+
1032+
if (retryCount === 0) {
1033+
// 首次尝试使用nextTick
1034+
nextTick(() => {
1035+
if (!attemptRestore()) {
1036+
// 如果首次失败,开始重试机制
1037+
setTimeout(() => restoreScrollPosition(1), 100);
1038+
}
1039+
});
1040+
} else {
1041+
attemptRestore();
1042+
}
10101043
}
10111044
};
10121045
@@ -1085,11 +1118,12 @@ export default defineComponent({
10851118
10861119
// 延迟恢复滚动位置,确保DOM已渲染
10871120
if (scrollPosition.value > 0) {
1088-
// 使用多重延迟确保搜索结果完全渲染
1121+
console.log('🔄 [滚动位置] 准备恢复滚动位置:', scrollPosition.value);
1122+
// 使用更长的延迟确保搜索结果完全渲染,特别是从详情页返回时
10891123
nextTick(() => {
10901124
setTimeout(() => {
10911125
restoreScrollPosition();
1092-
}, 200);
1126+
}, 300); // 增加延迟时间
10931127
});
10941128
}
10951129
@@ -1132,6 +1166,15 @@ export default defineComponent({
11321166
if (isReturnFromDetail) {
11331167
// 如果是从详情页返回,优先使用恢复的状态,不执行新搜索
11341168
console.log('🔄 [状态恢复] 从详情页返回,使用恢复的状态,不执行新搜索');
1169+
1170+
// 从详情页返回时,需要额外确保滚动位置恢复
1171+
if (scrollPosition.value > 0) {
1172+
console.log('🔄 [滚动位置] 从详情页返回,额外确保滚动位置恢复:', scrollPosition.value);
1173+
// 使用更长的延迟,确保页面完全渲染
1174+
setTimeout(() => {
1175+
restoreScrollPosition();
1176+
}, 500);
1177+
}
11351178
} else if (urlKeyword && urlKeyword === stateKeyword) {
11361179
// URL关键词与恢复状态匹配,使用恢复的状态
11371180
console.log('🔄 [状态恢复] URL关键词与恢复状态匹配,使用恢复的状态');

0 commit comments

Comments
 (0)