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:
parent
3923217e0e
commit
f861f82675
@ -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);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -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);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user