feat(CP页面): 处理触摸事件滑动和点击事件冲突的问题

This commit is contained in:
hzj 2026-03-23 19:18:01 +08:00
parent 06bff5843e
commit e8cd6bed98

View File

@ -63,6 +63,7 @@
@touchstart="handleTouchStart"
@touchmove="handleTouchMove"
@touchend="handleTouchEnd"
style="touch-action: pan-x"
>
<!-- 右占位 -->
<div style="width: 9vw; min-width: 0; flex-shrink: 0"></div>
@ -70,38 +71,44 @@
<!-- top1情侣头像 -->
<itemCenter
v-for="(item, index) in seasonTop1List"
:key="`couple-${item.userId || index}`"
style="z-index: 1; min-width: 0; flex-shrink: 0; transition: all 0.8s ease"
:style="{ width: index === centerIndex ? '60vw' : '40vw' }"
:style="{
width: index === centerIndex ? '60vw' : '40vw',
zIndex: index === centerIndex ? 20 : 1,
}"
:imgUrl="twelveSigns[index]?.bgUrl"
:contentStyle="``"
>
<!-- 非居中时显示遮罩层用于移动 -->
<div
v-if="index !== centerIndex"
style="position: absolute; z-index: 10; inset: 0"
style="position: absolute; inset: 0; z-index: 9; pointer-events: auto"
@click.stop="moveToCenter(index)"
></div>
<!-- 点击事件 -->
<div
v-if="index === centerIndex"
style="
position: absolute;
z-index: 9;
inset: 0;
z-index: 20;
display: flex;
justify-content: center;
align-items: center;
pointer-events: none;
"
>
<!-- 情侣1 -->
<div
style="flex: 1; min-width: 0; align-self: stretch"
@click="viewUserInfo(item.userId)"
style="flex: 1; min-width: 0; align-self: stretch; pointer-events: auto"
@click.stop="handleAvatarClick(item.userId)"
></div>
<!-- 情侣2 -->
<div
style="flex: 1; min-width: 0; align-self: stretch"
@click="viewUserInfo(item.cpUserId)"
style="flex: 1; min-width: 0; align-self: stretch; pointer-events: auto"
@click.stop="handleAvatarClick(item.cpUserId)"
></div>
</div>
@ -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'
}