diff --git a/src/views/Ranking/Couple/index.vue b/src/views/Ranking/Couple/index.vue index 17353ee..61c2ebb 100644 --- a/src/views/Ranking/Couple/index.vue +++ b/src/views/Ranking/Couple/index.vue @@ -63,6 +63,7 @@ @touchstart="handleTouchStart" @touchmove="handleTouchMove" @touchend="handleTouchEnd" + style="touch-action: pan-x" >
@@ -70,38 +71,44 @@
@@ -1448,9 +1455,14 @@ const resultShowIndex = ref(0) // 抽奖结果索引 const seasonTop1List = ref([]) // 赛季榜Top1列表 const listLeftPosition = ref('0') //top历史榜单 const centerIndex = ref(0) // 默认中间项的索引为1 + // 添加触摸滑动相关变量 const touchStartX = ref(0) const touchEndX = ref(0) +const isSwipe = ref(false) // ✅ 新增:标记是否为滑动 +const isMoving = ref(false) +const lastClickTime = ref(0) // ✅ 新增:记录上次点击时间 +const clickLock = ref(false) // ✅ 新增:点击锁,防止同一事件多次触发 const twelveSigns = ref([ { name: 'Aquarius', time: '2026.1.20-2.18', bgUrl: imageUrl('AquariusCoupleFrame') }, // 水瓶座 @@ -1467,54 +1479,141 @@ const twelveSigns = ref([ { name: 'Capricorn', time: '2026.12.22-1.19', bgUrl: imageUrl('') }, // 摩羯座 ]) // 十二星座 -// 计算移动到中心位置的函数 -const moveToCenter = (targetIndex) => { - if (centerIndex.value == targetIndex) return // 如果当前索引和目标索引相同,则不需要移动 +// 点击居中项头像 +const handleAvatarClick = (userId, event) => { + const now = Date.now() - centerIndex.value = targetIndex - updatePosition() // 更新位置 -} - -// 触发触摸开始事件 -const handleTouchStart = (event) => { - touchStartX.value = event.touches[0].clientX -} - -// 触发触摸移动事件 -const handleTouchMove = (event) => { - touchEndX.value = event.touches[0].clientX -} - -// 触发触摸结束事件 -const handleTouchEnd = () => { - if (!touchStartX.value) return - - let minSwipeDistance = 50 //x轴最小滑动距离 - let distance = touchEndX.value - touchStartX.value // 左滑<0 右滑>0 - let isLeftSwipe = distance < -minSwipeDistance // 满足左滑 - let isRightSwipe = distance > minSwipeDistance // 满足右滑 - - if (isLeftSwipe) { - // 左滑 - if (centerIndex.value > 0) { - moveToCenter(centerIndex.value - 1) - } - } else if (isRightSwipe) { - // 右滑 - if (centerIndex.value < seasonTop1List.value.length - 1) { - moveToCenter(centerIndex.value + 1) - } + // 滑动中不触发点击(防止滑动时误触) + if (isSwipe.value) { + event?.stopPropagation() // 滑动中阻止点击 + return } - // 重置触摸变量 + // 移动动画中不触发点击 + if (isMoving.value) { + event?.stopPropagation() + return + } + + // 点击锁检查(防止重复触发) + if (clickLock.value) { + event?.stopPropagation() + return + } + + // 防抖:100ms 内重复点击忽略 + if (now - lastClickTime.value < 100) { + event?.stopPropagation() + return + } + + if (!userId) { + event?.stopPropagation() + return + } + + clickLock.value = true + lastClickTime.value = now + viewUserInfo(userId) + + // 50ms 后释放点击锁 + setTimeout(() => { + clickLock.value = false + }, 50) + + event?.stopPropagation() +} + +// 移动到中心位置 +const moveToCenter = (targetIndex, event) => { + const now = Date.now() + + // 点击锁检查 + if (clickLock.value) { + event?.stopPropagation() + return + } + + // 目标已是中心或正在移动中 + if (centerIndex.value == targetIndex || isMoving.value) { + event?.stopPropagation() + return + } + + // 防抖:100ms 内重复调用忽略 + if (now - lastClickTime.value < 100) { + event?.stopPropagation() + return + } + + clickLock.value = true + isMoving.value = true + centerIndex.value = targetIndex + lastClickTime.value = now + + updatePosition() + + // 800ms 后释放锁(与 CSS transition 时间一致) + setTimeout(() => { + isMoving.value = false + clickLock.value = false + }, 800) + + event?.stopPropagation() +} + +// 触摸开始 +const handleTouchStart = (event) => { + touchStartX.value = event.touches[0].clientX + isSwipe.value = false // 每次触摸开始重置滑动标记 +} + +// 触摸移动 +const handleTouchMove = (event) => { + if (!event.touches || event.touches.length === 0) return + + touchEndX.value = event.touches[0].clientX + const distance = touchEndX.value - touchStartX.value + + // 滑动距离超过 10px 标记为滑动 + if (Math.abs(distance) > 10) { + isSwipe.value = true + } +} + +// 触摸结束 +const handleTouchEnd = (event) => { + if (!touchStartX.value) { + isSwipe.value = false + return + } + + if (event.changedTouches && event.changedTouches.length > 0) { + touchEndX.value = event.changedTouches[0].clientX + } + + const minSwipeDistance = 50 + const distance = touchEndX.value - touchStartX.value + const isLeftSwipe = distance < -minSwipeDistance + const isRightSwipe = distance > minSwipeDistance + + // 先执行移动(此时 isSwipe 仍为 true) + if (isLeftSwipe && centerIndex.value > 0) { + moveToCenter(centerIndex.value - 1) + } else if (isRightSwipe && centerIndex.value < seasonTop1List.value.length - 1) { + moveToCenter(centerIndex.value + 1) + } + + // 最后重置触摸变量 touchStartX.value = 0 touchEndX.value = 0 + isSwipe.value = false } // 更新位置 const updatePosition = () => { - const itemWidth = 40 // vw,根据您的代码中每个项目宽度 - const itemSpacing = 2 // vw,根据您的代码中项目间距 + const itemWidth = 40 // vw,每个项目宽度 + const itemSpacing = 2 // vw,项目间距 const targetOffset = (itemWidth + itemSpacing) * centerIndex.value listLeftPosition.value = targetOffset + 'vw' }