feat: Update refresh logic and footer text for real-time data synchronization

- Changed footer text in multiple components to indicate that data refresh occurs automatically when scrolling to the bottom.
- Removed the 30-second refresh timer and implemented a cooldown mechanism to refresh data only after scrolling ends, enhancing performance and user experience.
- Updated the scrolling logic to trigger data refresh upon reaching the end of the scrollable area in both Ladder and Ranking boards.
This commit is contained in:
Ethanfly 2026-02-10 10:37:36 +08:00
parent 3923217e0e
commit f861f82675
4 changed files with 46 additions and 17 deletions

View File

@ -196,7 +196,7 @@
</div> </div>
<div class="footer"> <div class="footer">
<span>数据实时同步 · 每30秒刷新</span> <span>数据实时同步 · 滚动到底部时自动刷新</span>
</div> </div>
</div> </div>
</template> </template>
@ -230,7 +230,6 @@ const loadingBoards = ref(false);
const loadingMatches = ref(false); const loadingMatches = ref(false);
let timer = null; let timer = null;
let refreshTimer = null;
let handleWindowClick = null; let handleWindowClick = null;
let boardsRaf = null; let boardsRaf = null;
let matchesRaf = null; let matchesRaf = null;
@ -243,6 +242,15 @@ const matchesGroup1 = ref(null);
const boardsScrollY = ref(0); const boardsScrollY = ref(0);
const matchesScrollY = ref(0); const matchesScrollY = ref(0);
const REFRESH_COOLDOWN_MS = 3000;
let lastRefreshAt = 0;
const onScrollEndRefresh = () => {
if (Date.now() - lastRefreshAt < REFRESH_COOLDOWN_MS) return;
lastRefreshAt = Date.now();
refreshAll();
};
const updateTime = () => { const updateTime = () => {
currentTime.value = dayjs().format("YYYY-MM-DD HH:mm:ss"); currentTime.value = dayjs().format("YYYY-MM-DD HH:mm:ss");
}; };
@ -373,6 +381,7 @@ const startBoardsScroll = () => {
boardsScrollY.value -= 0.35; boardsScrollY.value -= 0.35;
if (Math.abs(boardsScrollY.value) >= h) { if (Math.abs(boardsScrollY.value) >= h) {
boardsScrollY.value = 0; boardsScrollY.value = 0;
onScrollEndRefresh();
} }
boardsRaf = requestAnimationFrame(tick); boardsRaf = requestAnimationFrame(tick);
}; };
@ -406,6 +415,7 @@ const startMatchesScroll = () => {
matchesScrollY.value -= 0.4; matchesScrollY.value -= 0.4;
if (Math.abs(matchesScrollY.value) >= h) { if (Math.abs(matchesScrollY.value) >= h) {
matchesScrollY.value = 0; matchesScrollY.value = 0;
onScrollEndRefresh();
} }
matchesRaf = requestAnimationFrame(tick); matchesRaf = requestAnimationFrame(tick);
}; };
@ -430,7 +440,6 @@ onMounted(async () => {
await refreshAll(); await refreshAll();
timer = setInterval(updateTime, 1000); timer = setInterval(updateTime, 1000);
refreshTimer = setInterval(refreshAll, 30 * 1000);
handleWindowClick = () => { handleWindowClick = () => {
showStoreMenu.value = false; showStoreMenu.value = false;
@ -445,7 +454,6 @@ onMounted(async () => {
onUnmounted(() => { onUnmounted(() => {
if (timer) clearInterval(timer); if (timer) clearInterval(timer);
if (refreshTimer) clearInterval(refreshTimer);
stopAutoScroll(); stopAutoScroll();
if (handleWindowClick) window.removeEventListener("click", handleWindowClick); if (handleWindowClick) window.removeEventListener("click", handleWindowClick);
}); });

View File

@ -196,7 +196,7 @@
</div> </div>
<div class="footer"> <div class="footer">
<span>数据实时同步 · 每30秒刷新</span> <span>数据实时同步 · 滚动到底部时自动刷新</span>
</div> </div>
</div> </div>
</template> </template>
@ -230,7 +230,6 @@ const loadingBoards = ref(false);
const loadingMatches = ref(false); const loadingMatches = ref(false);
let timer = null; let timer = null;
let refreshTimer = null;
let handleWindowClick = null; let handleWindowClick = null;
let boardsRaf = null; let boardsRaf = null;
let matchesRaf = null; let matchesRaf = null;
@ -243,6 +242,15 @@ const matchesGroup1 = ref(null);
const boardsScrollY = ref(0); const boardsScrollY = ref(0);
const matchesScrollY = ref(0); const matchesScrollY = ref(0);
const REFRESH_COOLDOWN_MS = 3000;
let lastRefreshAt = 0;
const onScrollEndRefresh = () => {
if (Date.now() - lastRefreshAt < REFRESH_COOLDOWN_MS) return;
lastRefreshAt = Date.now();
refreshAll();
};
const updateTime = () => { const updateTime = () => {
currentTime.value = dayjs().format("YYYY-MM-DD HH:mm:ss"); currentTime.value = dayjs().format("YYYY-MM-DD HH:mm:ss");
}; };
@ -373,6 +381,7 @@ const startBoardsScroll = () => {
boardsScrollY.value -= 0.35; boardsScrollY.value -= 0.35;
if (Math.abs(boardsScrollY.value) >= h) { if (Math.abs(boardsScrollY.value) >= h) {
boardsScrollY.value = 0; boardsScrollY.value = 0;
onScrollEndRefresh();
} }
boardsRaf = requestAnimationFrame(tick); boardsRaf = requestAnimationFrame(tick);
}; };
@ -406,6 +415,7 @@ const startMatchesScroll = () => {
matchesScrollY.value -= 0.4; matchesScrollY.value -= 0.4;
if (Math.abs(matchesScrollY.value) >= h) { if (Math.abs(matchesScrollY.value) >= h) {
matchesScrollY.value = 0; matchesScrollY.value = 0;
onScrollEndRefresh();
} }
matchesRaf = requestAnimationFrame(tick); matchesRaf = requestAnimationFrame(tick);
}; };
@ -430,7 +440,6 @@ onMounted(async () => {
await refreshAll(); await refreshAll();
timer = setInterval(updateTime, 1000); timer = setInterval(updateTime, 1000);
refreshTimer = setInterval(refreshAll, 30 * 1000);
handleWindowClick = () => { handleWindowClick = () => {
showStoreMenu.value = false; showStoreMenu.value = false;
@ -445,7 +454,6 @@ onMounted(async () => {
onUnmounted(() => { onUnmounted(() => {
if (timer) clearInterval(timer); if (timer) clearInterval(timer);
if (refreshTimer) clearInterval(refreshTimer);
stopAutoScroll(); stopAutoScroll();
if (handleWindowClick) window.removeEventListener("click", handleWindowClick); if (handleWindowClick) window.removeEventListener("click", handleWindowClick);
}); });

View File

@ -465,7 +465,7 @@
<!-- 底部装饰 --> <!-- 底部装饰 -->
<div class="board-footer"> <div class="board-footer">
<div class="footer-hint">数据实时同步 · 每30秒刷新一次</div> <div class="footer-hint">数据实时同步 · 滚动到底部时自动刷新</div>
</div> </div>
</div> </div>
</template> </template>
@ -492,7 +492,6 @@
const scrollContainer = ref(null); const scrollContainer = ref(null);
const isRefreshing = ref(false); const isRefreshing = ref(false);
let timer = null; let timer = null;
let refreshTimer = null;
let handleWindowClick = null; let handleWindowClick = null;
const scrollReqIdAll = ref(null); const scrollReqIdAll = ref(null);
const scrollReqIdMale = ref(null); const scrollReqIdMale = ref(null);
@ -500,12 +499,21 @@
const scrollYAll = ref(0); const scrollYAll = ref(0);
const scrollYMale = ref(0); const scrollYMale = ref(0);
const scrollYFemale = ref(0); const scrollYFemale = ref(0);
const REFRESH_COOLDOWN_MS = 3000;
let lastRefreshAt = 0;
// //
const updateTime = () => { const updateTime = () => {
currentTime.value = dayjs().format("YYYY-MM-DD HH:mm:ss"); currentTime.value = dayjs().format("YYYY-MM-DD HH:mm:ss");
}; };
//
const onScrollEndRefresh = () => {
if (Date.now() - lastRefreshAt < REFRESH_COOLDOWN_MS) return;
lastRefreshAt = Date.now();
fetchRanking();
};
// (使 Transform ) // (使 Transform )
const startContinuousScroll = (listRef, scrollYRef, reqIdRef) => { const startContinuousScroll = (listRef, scrollYRef, reqIdRef) => {
if (reqIdRef.value) cancelAnimationFrame(reqIdRef.value); if (reqIdRef.value) cancelAnimationFrame(reqIdRef.value);
@ -522,9 +530,10 @@
// 100 * (90px + 12px) // 100 * (90px + 12px)
const singleSetHeight = listRef.value.length * 102; const singleSetHeight = listRef.value.length * 102;
// 0 // 0
if (Math.abs(scrollYRef.value) >= singleSetHeight) { if (Math.abs(scrollYRef.value) >= singleSetHeight) {
scrollYRef.value = 0; scrollYRef.value = 0;
onScrollEndRefresh();
} }
reqIdRef.value = requestAnimationFrame(scroll); reqIdRef.value = requestAnimationFrame(scroll);
@ -663,7 +672,6 @@
onMounted(() => { onMounted(() => {
fetchStores(); fetchStores();
timer = setInterval(updateTime, 1000); timer = setInterval(updateTime, 1000);
refreshTimer = setInterval(fetchRanking, 30 * 1000); // 30
// //
handleWindowClick = () => { handleWindowClick = () => {
@ -674,7 +682,6 @@
onUnmounted(() => { onUnmounted(() => {
if (timer) clearInterval(timer); if (timer) clearInterval(timer);
if (refreshTimer) clearInterval(refreshTimer);
if (scrollReqIdAll.value) cancelAnimationFrame(scrollReqIdAll.value); if (scrollReqIdAll.value) cancelAnimationFrame(scrollReqIdAll.value);
if (scrollReqIdMale.value) cancelAnimationFrame(scrollReqIdMale.value); if (scrollReqIdMale.value) cancelAnimationFrame(scrollReqIdMale.value);
if (scrollReqIdFemale.value) cancelAnimationFrame(scrollReqIdFemale.value); if (scrollReqIdFemale.value) cancelAnimationFrame(scrollReqIdFemale.value);

View File

@ -511,7 +511,7 @@
<div class="footer-bar"> <div class="footer-bar">
<span>REAL-TIME DATA SYNC ACTIVE</span> <span>REAL-TIME DATA SYNC ACTIVE</span>
<div class="dot"></div> <div class="dot"></div>
<span>REFRESH EVERY 30 SECONDS</span> <span>滚动到底部时自动刷新</span>
</div> </div>
</div> </div>
</template> </template>
@ -538,7 +538,6 @@
const scrollContainer = ref(null); const scrollContainer = ref(null);
const isRefreshing = ref(false); const isRefreshing = ref(false);
let timer = null; let timer = null;
let refreshTimer = null;
let handleWindowClick = null; let handleWindowClick = null;
const group1 = ref(null); const group1 = ref(null);
const scrollReqId = ref(null); const scrollReqId = ref(null);
@ -549,11 +548,19 @@
const scrollReqIdFemale = ref(null); const scrollReqIdFemale = ref(null);
const scrollYMale = ref(0); const scrollYMale = ref(0);
const scrollYFemale = ref(0); const scrollYFemale = ref(0);
const REFRESH_COOLDOWN_MS = 3000;
let lastRefreshAt = 0;
const updateTime = () => { const updateTime = () => {
currentTime.value = dayjs().format("HH:mm:ss"); currentTime.value = dayjs().format("HH:mm:ss");
}; };
const onScrollEndRefresh = () => {
if (Date.now() - lastRefreshAt < REFRESH_COOLDOWN_MS) return;
lastRefreshAt = Date.now();
fetchRanking();
};
const startContinuousScroll = (listRef, scrollYRef, reqIdRef, groupRef) => { const startContinuousScroll = (listRef, scrollYRef, reqIdRef, groupRef) => {
if (reqIdRef.value) cancelAnimationFrame(reqIdRef.value); if (reqIdRef.value) cancelAnimationFrame(reqIdRef.value);
@ -569,6 +576,7 @@
if (Math.abs(scrollYRef.value) >= singleSetHeight) { if (Math.abs(scrollYRef.value) >= singleSetHeight) {
scrollYRef.value = 0; scrollYRef.value = 0;
onScrollEndRefresh();
} }
reqIdRef.value = requestAnimationFrame(scroll); reqIdRef.value = requestAnimationFrame(scroll);
@ -693,7 +701,6 @@
onMounted(() => { onMounted(() => {
fetchStores(); fetchStores();
timer = setInterval(updateTime, 1000); timer = setInterval(updateTime, 1000);
refreshTimer = setInterval(fetchRanking, 30 * 1000);
handleWindowClick = () => { handleWindowClick = () => {
showStoreMenu.value = false; showStoreMenu.value = false;
}; };
@ -702,7 +709,6 @@
onUnmounted(() => { onUnmounted(() => {
if (timer) clearInterval(timer); if (timer) clearInterval(timer);
if (refreshTimer) clearInterval(refreshTimer);
if (scrollReqId.value) cancelAnimationFrame(scrollReqId.value); if (scrollReqId.value) cancelAnimationFrame(scrollReqId.value);
if (scrollReqIdMale.value) cancelAnimationFrame(scrollReqIdMale.value); if (scrollReqIdMale.value) cancelAnimationFrame(scrollReqIdMale.value);
if (scrollReqIdFemale.value) cancelAnimationFrame(scrollReqIdFemale.value); if (scrollReqIdFemale.value) cancelAnimationFrame(scrollReqIdFemale.value);