fix: 修改bug

This commit is contained in:
zerosaturation 2026-05-09 14:38:56 +08:00
parent 5208bde803
commit 63f46da2b4
2 changed files with 227 additions and 33 deletions

View File

@ -3,7 +3,7 @@
"appid" : "__UNI__F199FF4",
"description" : "",
"versionName" : "1.0.4",
"versionCode" : 101,
"versionCode" : 102,
"transformPx" : false,
/* 5+App */
"app-plus" : {

View File

@ -10,7 +10,11 @@
@touchend="onTouchEnd"
@touchcancel="onTouchEnd"
>
<view class="waterfall-inner" :style="{ width: totalWidth + 'px', height: '100%' }">
<view
class="waterfall-inner"
:class="{ 'ios-animate': isIOS && !iosScrollPaused }"
:style="{ width: totalWidth + 'px', height: '100%' }"
>
<view
v-for="card in cards"
:key="card.id"
@ -94,6 +98,7 @@ let isComponentMounted = false // 标记组件是否已卸载
let mockDataOffset = 0 //
let appendFailed = false //
let isInitialLoading = true //
let isIOS = false // iOS
// ========== RAF ==========
const rafFn = (cb) => {
@ -107,7 +112,71 @@ const cafFn = (id) => {
clearTimeout(id)
}
// ========== ==========
// ========== iOS ==========
// iOS 使 setInterval + scroll-left
let iosScrollTimer = null
let iosScrollPaused = false
let iosLastUpdateTime = 0
let iosLastScrollValue = 0 // scrollLeft
const IOS_SCROLL_INTERVAL = 16 // ~60fps
const IOS_MIN_DELTA = 0.5 //
const startIOSAutoScroll = () => {
console.log('[iOS] startIOSAutoScroll called, isIOS:', isIOS, 'isComponentMounted:', isComponentMounted)
if (!isComponentMounted) return
if (!isIOS) return
stopIOSAutoScroll()
iosScrollPaused = false
iosLastUpdateTime = 0
iosLastScrollValue = autoScrollPos
iosScrollTimer = setInterval(() => {
if (!isComponentMounted || iosScrollPaused) return
const now = Date.now()
// 16ms
if (now - iosLastUpdateTime >= IOS_SCROLL_INTERVAL) {
iosLastUpdateTime = now
const newPos = autoScrollPos + AUTO_SCROLL_SPEED
//
if (Math.abs(newPos - iosLastScrollValue) >= IOS_MIN_DELTA) {
autoScrollPos = newPos
iosLastScrollValue = newPos
scrollLeft.value = newPos
} else {
autoScrollPos = newPos // autoScrollPos scrollLeft
}
//
const remainingScroll = totalWidth.value - autoScrollPos - props.screenWidth
if (remainingScroll < Math.max(totalWidth.value / 2, props.screenWidth)) {
if (!isLoadingMore && !appendFailed && !isInitialLoading && props.useMockData) {
appendMore()
}
}
}
}, 16)
}
const stopIOSAutoScroll = () => {
console.log('[iOS] stopIOSAutoScroll')
clearInterval(iosScrollTimer)
iosScrollTimer = null
}
const pauseIOSAutoScroll = () => {
console.log('[iOS] pauseIOSAutoScroll')
iosScrollPaused = true
}
const resumeIOSAutoScroll = () => {
console.log('[iOS] resumeIOSAutoScroll')
iosScrollPaused = false
iosLastUpdateTime = 0
autoScrollPos = currentScrollLeft
iosLastScrollValue = currentScrollLeft
}
let rafId = null
let userInteracting = false
let resumeTimer = null
@ -115,9 +184,10 @@ let appendTimer = null // 防抖定时器
let autoScrollPos = 0 //
let momentumTimer = null // iOS
let scrollUpdateTimer = null // scrollLeft
let iosAutoScrollTimer = null // iOS
const startAutoScroll = () => {
if (!isComponentMounted) return
if (!isComponentMounted || isIOS) return
if (rafId) {
cafFn(rafId)
rafId = null
@ -155,11 +225,13 @@ const stopAutoScroll = () => {
resumeTimer = null
clearTimeout(momentumTimer)
momentumTimer = null
clearTimeout(iosAutoScrollTimer)
iosAutoScrollTimer = null
userInteracting = false
isLoadingMore = false
}
// iOS
// Android
let lastTouchEndPos = 0 // touchend
const detectMomentumEnd = () => {
@ -169,6 +241,7 @@ const detectMomentumEnd = () => {
momentumTimer = setTimeout(() => {
// lastTouchEndPostouchend
if (Math.abs(currentScrollLeft - lastTouchEndPos) < 3) {
//
autoScrollPos = currentScrollLeft
startAutoScroll()
} else {
@ -194,21 +267,60 @@ const scheduleAppend = () => {
}
// ========== / ==========
const onTouchStart = () => {
userInteracting = true
clearTimeout(momentumTimer)
clearInterval(scrollUpdateTimer)
let isManualScrolling = false //
const onTouchStart = (e) => {
if (isIOS) {
// iOS
stopIOSAutoScroll()
isManualScrolling = true
clearTimeout(momentumTimer)
} else {
//
userInteracting = true
clearTimeout(momentumTimer)
clearInterval(scrollUpdateTimer)
}
}
const onTouchEnd = () => {
// iOS
detectMomentumEnd()
if (isIOS) {
// iOS
clearTimeout(momentumTimer)
lastTouchEndPos = currentScrollLeft
const tick = () => {
momentumTimer = setTimeout(() => {
if (Math.abs(currentScrollLeft - lastTouchEndPos) < 2) {
// 300ms
clearTimeout(momentumTimer)
momentumTimer = setTimeout(() => {
isManualScrolling = false
autoScrollPos = currentScrollLeft
startIOSAutoScroll()
}, 300)
} else {
//
lastTouchEndPos = currentScrollLeft
tick()
}
}, 80)
}
tick()
} else {
//
detectMomentumEnd()
}
}
const onScroll = (e) => {
if (!isComponentMounted) return
currentScrollLeft = e.detail.scrollLeft
// iOS
if (isIOS && isManualScrolling) {
return
}
const remainingScroll = totalWidth.value - currentScrollLeft - props.screenWidth
if (remainingScroll < Math.max(totalWidth.value / 2, props.screenWidth)) {
if (!isLoadingMore && !appendFailed && !isInitialLoading && props.useMockData) {
@ -668,60 +780,134 @@ onMounted(() => {
userInteracting = false
currentScrollLeft = 0
scrollLeft.value = 0
// iOS 使
const sysInfo = uni.getSystemInfoSync()
isIOS = sysInfo.platform === 'ios'
console.log('[WaterfallGrid] onMounted, platform:', sysInfo.platform, 'isIOS:', isIOS)
const containerH = props.screenHeight - props.bannerBottom
layout = new WaterfallLayout(containerH, props.category)
loadUsers().then(() => {
isInitialLoading = false
nextTick(() => startAutoScroll())
nextTick(() => {
console.log('[WaterfallGrid] loadUsers done, calling auto scroll, isIOS:', isIOS)
if (isIOS) {
startIOSAutoScroll()
} else {
startAutoScroll()
}
})
})
})
//
const handleVisibilityChange = () => {
// ========== ==========
const stopAllAutoScroll = () => {
stopAutoScroll()
stopIOSAutoScroll()
}
const resumeAllAutoScroll = () => {
// /
clearTimeout(momentumTimer)
momentumTimer = null
stopAllAutoScroll()
if (!isComponentMounted) return
if (document.hidden) {
stopAutoScroll()
// 使 scrollLeft.value currentScrollLeft
// currentScrollLeft onScroll isManualScrolling return
autoScrollPos = scrollLeft.value
if (isIOS) {
startIOSAutoScroll()
} else {
//
stopAutoScroll()
setTimeout(() => {
if (isComponentMounted) {
autoScrollPos = currentScrollLeft
startAutoScroll()
}
}, 150)
startAutoScroll()
}
}
// H5
const handleVisibilityChange = () => {
if (!isComponentMounted) return
if (document.hidden) {
stopAllAutoScroll()
} else {
// momentum stopAllAutoScroll
resumeAllAutoScroll()
}
}
// uni-app App /
let appShowListener = null
let appHideListener = null
// iOS/Android onShow/onHide
// uni-app App /
const onAppShowHandler = () => {
if (!isComponentMounted) return
// momentum stopAllAutoScroll
// resumeiOS RAF Android setInterval
resumeAllAutoScroll()
}
const onAppHideHandler = () => {
if (!isComponentMounted) return
stopAllAutoScroll()
}
if (typeof uni !== 'undefined') {
uni.onAppShow(onAppShowHandler)
uni.onAppHide(onAppHideHandler)
}
// H5 visibilitychange
if (typeof document !== 'undefined') {
document.addEventListener('visibilitychange', handleVisibilityChange)
}
// defineExpose
const handleAppShow = () => {
if (!isComponentMounted) return
setTimeout(() => {
resumeAllAutoScroll()
}, AUTO_RESUME_DELAY)
}
const handleAppHide = () => {
if (!isComponentMounted) return
stopAllAutoScroll()
}
//
defineExpose({
handleAppShow,
handleAppHide,
})
// isActive
watch(() => props.isActive, (active) => {
if (!isComponentMounted) return
if (active) {
stopAutoScroll()
stopAllAutoScroll()
setTimeout(() => {
if (isComponentMounted) {
autoScrollPos = currentScrollLeft
startAutoScroll()
}
resumeAllAutoScroll()
}, 150)
} else {
stopAutoScroll()
stopAllAutoScroll()
}
}, { immediate: false })
onUnmounted(() => {
isComponentMounted = false
stopAutoScroll()
stopAllAutoScroll()
clearTimeout(resumeTimer)
clearTimeout(appendTimer)
clearTimeout(momentumTimer)
if (typeof document !== 'undefined') {
document.removeEventListener('visibilitychange', handleVisibilityChange)
}
// uni-app
if (typeof uni !== 'undefined') {
try {
uni.offAppShow(onAppShowHandler)
uni.offAppHide(onAppHideHandler)
} catch (_) {}
}
})
watch(() => [props.screenHeight, props.bannerBottom], () => {
@ -736,7 +922,7 @@ watch(() => [props.screenHeight, props.bannerBottom], () => {
//
watch(() => props.category, (newCategory) => {
if (isComponentMounted) {
stopAutoScroll()
stopAllAutoScroll()
//
if (appendTimer) {
@ -766,7 +952,11 @@ watch(() => props.category, (newCategory) => {
loadUsers().then(() => {
nextTick(() => {
startAutoScroll()
if (isIOS) {
startIOSAutoScroll()
} else {
startAutoScroll()
}
})
})
}
@ -785,6 +975,10 @@ watch(() => props.category, (newCategory) => {
top: 32rpx;
}
.ios-animate {
will-change: transform;
}
.wf-card {
position: absolute;
cursor: pointer;