|
|
|
<template>
|
|
|
|
<view
|
|
|
|
class="swipe-to-next"
|
|
|
|
@touchstart="handleTouchStart"
|
|
|
|
@touchend="handleTouchEnd"
|
|
|
|
>
|
|
|
|
<slot></slot>
|
|
|
|
<!-- 提示文字 -->
|
|
|
|
<view v-if="showTip && shouldShowTip" class="bottom-tip">
|
|
|
|
<text>{{ tipText }}</text>
|
|
|
|
</view>
|
|
|
|
</view>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
|
|
|
export default {
|
|
|
|
name: 'SwipeToNext',
|
|
|
|
props: {
|
|
|
|
// 是否在最后一页
|
|
|
|
isLastSlide: {
|
|
|
|
type: Boolean,
|
|
|
|
default: false
|
|
|
|
},
|
|
|
|
// 跳转的目标路径
|
|
|
|
targetPath: {
|
|
|
|
type: String,
|
|
|
|
required: true
|
|
|
|
},
|
|
|
|
// 是否显示提示文字
|
|
|
|
showTip: {
|
|
|
|
type: Boolean,
|
|
|
|
default: true
|
|
|
|
},
|
|
|
|
// 提示文字内容
|
|
|
|
tipText: {
|
|
|
|
type: String,
|
|
|
|
default: '上滑进入下一章节'
|
|
|
|
},
|
|
|
|
// 滑动阈值(px)
|
|
|
|
swipeThreshold: {
|
|
|
|
type: Number,
|
|
|
|
default: 100
|
|
|
|
},
|
|
|
|
// 延迟时间(ms)
|
|
|
|
delayTime: {
|
|
|
|
type: Number,
|
|
|
|
default: 500
|
|
|
|
},
|
|
|
|
// 是否启用延迟机制
|
|
|
|
enableDelay: {
|
|
|
|
type: Boolean,
|
|
|
|
default: true
|
|
|
|
},
|
|
|
|
// 是否总是启用跳转(忽略isLastSlide状态)
|
|
|
|
alwaysEnable: {
|
|
|
|
type: Boolean,
|
|
|
|
default: false
|
|
|
|
}
|
|
|
|
},
|
|
|
|
data() {
|
|
|
|
return {
|
|
|
|
touchStartY: 0, // 触摸开始Y坐标
|
|
|
|
touchEndY: 0, // 触摸结束Y坐标
|
|
|
|
canJump: false, // 是否允许跳转
|
|
|
|
delayTimer: null // 延迟定时器
|
|
|
|
}
|
|
|
|
},
|
|
|
|
computed: {
|
|
|
|
// 是否应该显示提示
|
|
|
|
shouldShowTip() {
|
|
|
|
return this.alwaysEnable || this.isLastSlide;
|
|
|
|
},
|
|
|
|
// 是否应该允许触摸检测
|
|
|
|
shouldEnableTouch() {
|
|
|
|
return this.alwaysEnable || this.isLastSlide;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
watch: {
|
|
|
|
isLastSlide(newVal) {
|
|
|
|
this.handleSlideChange(newVal);
|
|
|
|
},
|
|
|
|
alwaysEnable: {
|
|
|
|
handler(newVal) {
|
|
|
|
if (newVal) {
|
|
|
|
// 如果启用总是跳转,立即处理
|
|
|
|
this.handleSlideChange(true);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
immediate: true
|
|
|
|
}
|
|
|
|
},
|
|
|
|
beforeDestroy() {
|
|
|
|
// 清理定时器
|
|
|
|
if (this.delayTimer) {
|
|
|
|
clearTimeout(this.delayTimer);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
methods: {
|
|
|
|
// 处理滑动状态变化
|
|
|
|
handleSlideChange(isActive) {
|
|
|
|
console.log('ppsls');
|
|
|
|
if (isActive || this.alwaysEnable) {
|
|
|
|
// 到达最后一页或总是启用
|
|
|
|
this.canJump = false;
|
|
|
|
if (this.enableDelay && !this.alwaysEnable) {
|
|
|
|
// 启用延迟机制(仅当不是总是启用时)
|
|
|
|
this.delayTimer = setTimeout(() => {
|
|
|
|
if (this.shouldEnableTouch) {
|
|
|
|
this.canJump = true;
|
|
|
|
}
|
|
|
|
}, this.delayTime);
|
|
|
|
} else {
|
|
|
|
// 不启用延迟或总是启用,立即允许跳转
|
|
|
|
this.canJump = true;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// 离开最后一页且不是总是启用
|
|
|
|
this.canJump = false;
|
|
|
|
if (this.delayTimer) {
|
|
|
|
clearTimeout(this.delayTimer);
|
|
|
|
this.delayTimer = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
// 触摸开始
|
|
|
|
handleTouchStart(e) {
|
|
|
|
console.log('。。。。。。。。。。///////////');
|
|
|
|
// 检查是否应该允许触摸
|
|
|
|
if (this.shouldEnableTouch && (this.canJump || !this.enableDelay || this.alwaysEnable)) {
|
|
|
|
this.touchStartY = e.touches[0].clientY;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
// 触摸结束
|
|
|
|
handleTouchEnd(e) {
|
|
|
|
// 检查是否满足跳转条件
|
|
|
|
if (!this.shouldEnableTouch || !this.touchStartY) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 如果启用延迟机制但还不能跳转,且不是总是启用模式,则返回
|
|
|
|
if (this.enableDelay && !this.canJump && !this.alwaysEnable) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.touchEndY = e.changedTouches[0].clientY;
|
|
|
|
const deltaY = this.touchStartY - this.touchEndY;
|
|
|
|
|
|
|
|
// 向上滑动且滑动距离大于阈值才跳转
|
|
|
|
if (deltaY > this.swipeThreshold) {
|
|
|
|
console.log('向上滑动触发跳转,目标路径:', this.targetPath);
|
|
|
|
this.$emit('swipe-to-next', this.targetPath);
|
|
|
|
uni.navigateTo({
|
|
|
|
url:this.targetPath
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// 重置触摸位置
|
|
|
|
this.touchStartY = 0;
|
|
|
|
this.touchEndY = 0;
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
.swipe-to-next {
|
|
|
|
width: 100%;
|
|
|
|
height: 100%;
|
|
|
|
position: relative;
|
|
|
|
}
|
|
|
|
|
|
|
|
.bottom-tip {
|
|
|
|
position: absolute;
|
|
|
|
bottom: 50rpx;
|
|
|
|
left: 50%;
|
|
|
|
transform: translateX(-50%);
|
|
|
|
background: rgba(0, 0, 0, 0.6);
|
|
|
|
padding: 10rpx 20rpx;
|
|
|
|
border-radius: 50rpx;
|
|
|
|
z-index: 999;
|
|
|
|
|
|
|
|
text {
|
|
|
|
color: #fff;
|
|
|
|
font-size: 24rpx;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</style>
|