You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							187 lines
						
					
					
						
							3.9 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							187 lines
						
					
					
						
							3.9 KiB
						
					
					
				| <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> |