Ver Fonte

no message

WIN-2CJ8FMUT9OF\Administrator há 6 meses atrás
pai
commit
cf85e90997
1 ficheiros alterados com 246 adições e 18 exclusões
  1. 246 18
      pages-takeout/new-shop.vue

+ 246 - 18
pages-takeout/new-shop.vue

@@ -98,7 +98,7 @@
 										<span class="fs-24 fw-400 fc-3">¥</span>
 										<span
 											class="fs-40 fw-b fc-3">{{info.seckill_money>0?info.seckill_money:info.price}}</span>
-											<span class="fs-24 fc-9">/份起</span>
+										<span class="fs-24 fc-9">/份起</span>
 									</view>
 									<view class="display-flex align-items-center" v-if="info.spec_type == 1">
 										<image v-show="info.num > 0" class="wh-44" @click="addred(1,info)"
@@ -197,7 +197,8 @@
 						message="快去选购商品吧!~"></en-blank>
 				</view>
 				<view class="pop-shop-buttom-money box-border-box" @click="openBuyCrad()">
-					<view class="shop-buttom-money-1 bgc-f flex-justify-space align-items-center pl-24 box-border-box pr-8 b-rad-200">
+					<view
+						class="shop-buttom-money-1 bgc-f flex-justify-space align-items-center pl-24 box-border-box pr-8 b-rad-200">
 						<view class="align-items-center">
 							<image class="gwc-img mr-36" src="@/static/img/order-food/gwc-img.png" mode="scaleToFill">
 							</image>
@@ -275,7 +276,6 @@
 				heightTwo: '',
 				topHeight: '',
 				idMark: '', //滚动自适应参数
-				idMarkTwo: '', //滚动自适应参数
 				type: '', //默认分类标识
 				categoryList: [],
 				goodsList: [],
@@ -285,23 +285,52 @@
 					pack_price: 0,
 					total_goods_money: 0,
 					goods_list: [],
-				}
+				},
+				categoryTops: [], // 存储每个分类的top位置
+				isScrolling: false, // 防止滚动事件冲突
+				activeScroll: false, // 是否正在滚动
+				scrollTimer: null, // 滚动计时器
+				observer: null, // IntersectionObserver实例
+				categoryDomInfos: [], // 存储分类DOM信息
+				isManualScroll: false, // 是否是手动触发滚动
+				lastActiveCategory: '', // 记录上一次激活的分类,避免重复更新
+			}
+		},
+		// 在onUnload中销毁监听
+		onUnload() {
+			if (this.observer) {
+				this.observer.disconnect();
+				this.observer = null;
+			}
+			if (this.scrollTimer) {
+				clearTimeout(this.scrollTimer);
 			}
 		},
 		onShow() {
 			this.getShopIngList();
+			// 重新计算分类位置
+			setTimeout(() => {
+				this.initCategoryPositions();
+			}, 300);
 		},
 		onLoad(e) {
 			cartStore.setShopId();
 			this.getshopInfo();
 		},
+		onReady() {
+			// 确保DOM完全渲染后初始化位置
+			setTimeout(() => {
+				this.initCategoryPositions();
+			}, 800);
+		},
 		mounted() {},
 		onReachBottom(e) {},
 		// 监听页面滚动
 		onPageScroll(e) {
 			// e.scrollTop 获取滚动条距离页面顶部的距离
 			this.scrollTop = e.scrollTop
-			this.opacity = (Number(this.scrollTop) - 30)
+			// this.opacity = (Number(this.scrollTop) - 30)
+			this.opacity = Math.min((this.scrollTop - 30) / 100, 1);
 			// 可以根据滚动位置执行相应逻辑
 			if (e.scrollTop > 25) {
 				this.navBgType = true
@@ -313,8 +342,202 @@
 			} else {
 				this.menuLeftType = false
 			}
+			// 优化:只在非手动滚动且菜单固定时更新激活分类
+			if (!this.isManualScroll && this.menuLeftType) {
+				this.updateActiveCategoryOnScroll();
+			}
 		},
 		methods: {
+			// 初始化分类位置信息
+			initCategoryPositions() {
+				this.$nextTick(() => {
+					const query = uni.createSelectorQuery().in(this);
+
+					// 清空之前的 DOM 信息
+					this.categoryDomInfos = [];
+					this.categoryTops = [];
+
+					// 收集所有分类的位置信息
+					this.goodsList.forEach((category, index) => {
+						if (category.type) {
+							query.select(`#scroll${category.type}`).boundingClientRect();
+						}
+					});
+
+					query.exec((res) => {
+						if (!res || res.length === 0) return;
+
+						this.categoryDomInfos = res.map((rect, index) => {
+							if (rect && this.goodsList[index]) {
+								const categoryInfo = {
+									id: this.goodsList[index].type,
+									top: rect.top,
+									height: rect.height,
+									index: index
+								};
+								this.categoryTops.push(categoryInfo);
+								return categoryInfo;
+							}
+							return null;
+						}).filter(item => item !== null);
+
+						console.log('分类位置信息:', this.categoryDomInfos);
+					});
+				});
+			},
+			// 更新激活的分类
+			updateActiveCategoryOnScroll() {
+				if (this.scrollTimer) {
+					clearTimeout(this.scrollTimer);
+				}
+
+				this.scrollTimer = setTimeout(() => {
+					this.findCurrentCategory();
+				}, 150); // 增加防抖时间
+			},
+			// 查找当前应该激活的分类
+			findCurrentCategory() {
+				if (this.categoryDomInfos.length === 0 || !this.goodsList) return;
+
+				const query = uni.createSelectorQuery().in(this);
+				query.selectViewport().scrollOffset();
+
+				query.exec((res) => {
+					if (!res || !res[0]) return;
+
+					const scrollTop = res[0].scrollTop;
+
+					// 获取吸顶区域总高度
+					const stickyHeight = this.getStickyHeight();
+
+					// 阈值位置:视口顶部 + 吸顶高度 + 缓冲区域(分类标题高度的 1/3)
+					const threshold = scrollTop + stickyHeight + 10;
+
+					// 找当前应该激活的分类
+					let currentCategoryId = this.categoryList[0]?.category_id;
+					let found = false;
+
+					// 从后往前遍历,找到最后一个在阈值上方的分类
+					for (let i = this.categoryDomInfos.length - 1; i >= 0; i--) {
+						const category = this.categoryDomInfos[i];
+						if (category) {
+							// 元素顶部位置(相对于视口)+ 滚动距离 = 相对于页面顶部的位置
+							const elementTop = category.top + scrollTop;
+
+							// 如果元素顶部在阈值上方或刚好对齐
+							if (elementTop <= threshold) {
+								currentCategoryId = category.id;
+								found = true;
+								break;
+							}
+						}
+					}
+
+					// 如果都没找到,说明第一个分类已经滚动过去了,使用第一个分类
+					if (!found && this.categoryDomInfos.length > 0) {
+						currentCategoryId = this.categoryDomInfos[0].id;
+					}
+
+					// 只有当分类真正改变时才更新,避免频繁触发
+					if (currentCategoryId && this.type !== currentCategoryId) {
+						console.log('滚动激活分类:', currentCategoryId);
+						this.type = currentCategoryId;
+						this.lastActiveCategory = currentCategoryId;
+						this.$forceUpdate();
+					}
+				});
+			},
+			// 优化滚动到分类的方法
+			scrollToCategory(categoryId) {
+				this.isManualScroll = true;
+
+				const query = uni.createSelectorQuery().in(this);
+				const selector = `#scroll${categoryId}`;
+
+				query.select(selector).boundingClientRect();
+				query.selectViewport().scrollOffset();
+
+				query.exec((res) => {
+					if (res[0] && res[1]) {
+						const categoryRect = res[0];
+						const scrollTop = res[1].scrollTop;
+
+						// 获取吸顶区域总高度
+						const stickyHeight = this.getStickyHeight();
+
+						// 计算目标位置(考虑吸顶高度和缓冲)
+						const targetScrollTop = scrollTop + categoryRect.top - stickyHeight + 2;
+
+						// 执行滚动
+						uni.pageScrollTo({
+							scrollTop: targetScrollTop,
+							duration: 300,
+							success: () => {
+								// 滚动完成后,更新左侧激活状态
+								this.type = categoryId;
+								this.lastActiveCategory = categoryId;
+
+								// 延迟恢复手动滚动标记
+								setTimeout(() => {
+									this.isManualScroll = false;
+								}, 400);
+							},
+							fail: () => {
+								this.isManualScroll = false;
+							}
+						});
+					} else {
+						this.isManualScroll = false;
+					}
+				});
+			},
+			// 获取吸顶区域总高度(精确计算版)
+			getStickyHeight() {
+				// 导航栏高度(rpx 转 px)
+				const systemInfo = uni.getSystemInfoSync();
+				const pixelRatio = systemInfo.pixelRatio || 2;
+				const screenWidth = systemInfo.windowWidth || 375;
+				const rpxToPx = screenWidth / 750;
+
+				// 导航栏高度(从组件获取,单位 rpx)
+				const navHeightRpx = this.newNavHeight || 88;
+
+				// 商家信息区域高度(动态获取或估算)
+				let shopInfoHeightRpx = 0;
+				try {
+					const query = uni.createSelectorQuery().in(this);
+					query.select('.shop-info').boundingClientRect();
+					// 同步获取可能失败,使用估算值
+					shopInfoHeightRpx = 140; // 默认估算值
+				} catch (e) {
+					shopInfoHeightRpx = 140;
+				}
+
+				// 分类 tab 高度
+				const tabHeightRpx = 48;
+
+				// 额外间距
+				const extraPaddingRpx = 8;
+
+				// 总高度(rpx)
+				const totalHeightRpx = navHeightRpx;
+
+				// 转换为 px(与 pageScrollTo 保持一致)
+				return totalHeightRpx * rpxToPx;
+			},
+
+			// 优化选择分类的方法
+			selectType(item) {
+				if (this.type !== item.category_id) {
+					this.type = item.category_id;
+					this.$forceUpdate();
+
+					// 延迟执行滚动,确保DOM已更新
+					setTimeout(() => {
+						this.scrollToCategory(item.category_id);
+					}, 100);
+				}
+			},
 			shopInfo() {
 				// 获取商家详情
 				shopInfo().then((res) => {
@@ -342,6 +565,10 @@
 						this.goodsList = res.data
 						// 从购物车数据中回显每个商品的数量
 						this.updateGoodsNumFromCart()
+
+						setTimeout(() => {
+							this.initCategoryPositions();
+						}, 300);
 					}
 				})
 			},
@@ -435,18 +662,18 @@
 					url: 'pages/index/search-record'
 				})
 			},
-			selectType(item, itemTwo) {
-				if (this.type != item.category_id) {
-					this.type = item.category_id;
-					this.idMark = 'scroll' + item.category_id
-					// 立即更新
-					this.$forceUpdate();
-					// 延迟执行滚动
-					setTimeout(() => {
-						this.scrollToCategorySimple(item.category_id);
-					}, 100);
-				}
-			},
+			// selectType(item, itemTwo) {
+			// 	if (this.type != item.category_id) {
+			// 		this.type = item.category_id;
+			// 		this.idMark = 'scroll' + item.category_id
+			// 		// 立即更新
+			// 		this.$forceUpdate();
+			// 		// 延迟执行滚动
+			// 		setTimeout(() => {
+			// 			this.scrollToCategorySimple(item.category_id);
+			// 		}, 100);
+			// 	}
+			// },
 			// 滚动方法
 			scrollToCategorySimple(type) {
 				const query = uni.createSelectorQuery();
@@ -625,9 +852,10 @@
 </script>
 
 <style scoped lang="scss">
-	.min-h{
+	.min-h {
 		min-height: 152rpx;
 	}
+
 	.car-scroll-box {
 		padding: 12rpx 24rpx calc(env(safe-area-inset-bottom) + 48rpx);
 	}