wangfukang 8 months ago
parent
commit
c6cddfc236
  1. 164
      package1/group/groupBuySingle.vue

164
package1/group/groupBuySingle.vue

@ -1,6 +1,6 @@
<template>
<!-- 拼团单一商家 -->
<view class="page1">
<view class="page1" @touchmove="onPageTouchMove">
<!-- 固定顶部导航栏(悬浮在背景图之上) -->
<view class="nav-bar"
:style="{'padding-top': menuButtonInfo.top +'px','background':lastScrollTop>200?'#fff':''}">
@ -90,15 +90,15 @@
</swiper>
</view>
<!-- 分类栏:移到goods-list外层,position:sticky才能生效 -->
<view style="display: flex;height: 72%;margin-top: 10px;">
<view id="menuList" style="border-right: 1px solid #eee;font-weight: 700;font-size: 14px;">
<view class="container" :class="{'container-sticky': isContainerSticky}" :style="{'margin-top': isContainerSticky ? '0' : '10px', 'top': isContainerSticky ? navBarHeight + 'px' : 'auto'}" style="display: flex;height: 72%;">
<scroll-view scroll-y id="menuList" style="border-right: 1px solid #eee;font-weight: 700;font-size: 14px;height: 100%;width: 160rpx;">
<view class="menu1" @tap="checkTab(index)" v-for="(item,index) in menuList" :key="index"
:style="{'border-radius':item.checked?'10px':'','color':item.checked?'rgba(0, 35, 28, 1)':'#777','background':item.checked?'#fff':'','border-right':item.checked?'5px solid #48D1CC;':''}">
<view style="width: 160rpx;">{{item.categoryName}}</view>
</view>
</view>
<view class="goods-list">
<view class="goods-member" v-for="(item,index) in productItem" :key="index"
</scroll-view>
<scroll-view class="goods-list" scroll-y :scroll-into-view="scrollIntoViewId" :scroll-top="goodsListScrollTop" @scroll="onGoodsListScroll" @scrolltoupper="onGoodsListScrollToTop" :scroll-with-animation="true">
<view class="goods-member" :id="'category-' + item.categoryId" v-for="(item,index) in productItem" :key="index"
@tap="goDetail('product',item)">
<view class="goods-top">
<view class="goods-img">
@ -143,7 +143,7 @@
</view>
<uni-load-more :status="loadStatus" @change="onChange" />
<view style="height: 80px;width: 100%;"></view>
</view>
</scroll-view>
</view>
</view>
@ -500,6 +500,13 @@
lastScrollTop: 0,
// 防止切换分类之后onPageScroll闪回的标志
isSwitching: false,
// 吸顶与滚动控制
isContainerSticky: false,
containerOriginalTop: 0,
scrollIntoViewId: '',
goodsListScrollTop: 0,
isAutoScrolling: false,
pageScrollTop: 0,
searchForm: {
shopId: '',
delFlag: 1,
@ -606,15 +613,95 @@
this.navBarHeight = info.statusBarHeight + 40;
},
onReady() {
// 记录分类栏相对页面的偏移量,用于上滑检测
// 记录container相对页面的初始偏移量
setTimeout(() => {
const query = uni.createSelectorQuery().in(this);
query.select('#menuList').boundingClientRect(rect => {
if (rect) this.menuListOffsetTop = rect.top + this.lastScrollTop;
query.select('.container').boundingClientRect(rect => {
if (rect) {
this.containerOriginalTop = rect.top;
this.menuListOffsetTop = rect.top;
}
}).exec();
}, 500);
},
onPageScroll(e) {
this.lastScrollTop = e.scrollTop;
// 当页面滚动到container应该触顶的位置时,启用吸顶
const stickyThreshold = this.containerOriginalTop - this.navBarHeight;
if (e.scrollTop >= stickyThreshold && !this.isContainerSticky) {
this.isContainerSticky = true;
}
},
methods: {
// 页面touchmove事件:吸顶后阻止页面整体滑动(让goods-list接管滚动)
onPageTouchMove(e) {
// 吸顶状态下不需要额外处理,scroll-view会自己处理
},
// goods-list滚动事件:检测分类切换 + 滚回顶部取消吸顶
onGoodsListScroll(e) {
if (this.isAutoScrolling) return;
const scrollTop = e.detail.scrollTop;
// 向下滑动到顶部时,取消吸顶
if (scrollTop <= 0 && this.isContainerSticky) {
this.isContainerSticky = false;
return;
}
// 根据滚动位置自动选中对应分类
this.detectCurrentCategory();
},
onGoodsListScrollToTop() {
if (this.isAutoScrolling) return;
// 滚到顶部了,取消吸顶
this.isContainerSticky = false;
},
// 检测当前可见的分类
detectCurrentCategory() {
if (this.isSwitching) return;
const query = uni.createSelectorQuery().in(this);
// 获取goods-list中所有goods-member的位置
query.selectAll('.goods-member').boundingClientRect();
query.select('.goods-list').boundingClientRect();
query.exec((res) => {
if (!res || !res[0] || !res[1]) return;
const items = res[0];
const listRect = res[1];
const listTop = listRect.top;
let currentCategoryId = '';
// 找到第一个顶部在goods-list可视区域内或刚过顶部的item
for (let i = items.length - 1; i >= 0; i--) {
if (items[i].top <= listTop + 10) {
// 从productItem中获取categoryId
if (this.productItem[i]) {
currentCategoryId = this.productItem[i].categoryId;
}
break;
}
}
if (currentCategoryId !== '' || currentCategoryId === '') {
// 在menuList中找到匹配的菜单并选中
let found = false;
for (let i = 0; i < this.menuList.length; i++) {
if (String(this.menuList[i].id) === String(currentCategoryId)) {
if (!this.menuList[i].checked) {
for (let j = 0; j < this.menuList.length; j++) {
this.menuList[j].checked = (j === i);
}
this.$forceUpdate();
}
found = true;
break;
}
}
// 如果没找到匹配的分类(如categoryId为空),选中"猜你喜欢"
if (!found && currentCategoryId === '') {
for (let j = 0; j < this.menuList.length; j++) {
this.menuList[j].checked = (j === 0);
}
this.$forceUpdate();
}
}
});
},
getProduct(categoryId) {
let that = this;
this.loadStatus = 'loading';
@ -666,15 +753,41 @@
}).catch((res) => {})
},
checkTab(index) {
this.isSwitching = true;
for (let i = 0; i < this.menuList.length; i++) {
this.menuList[i].checked = (i === index);
}
// 重置分页
this.searchForm.pageNum = 1;
this.pageNum = 1;
this.total = 1;
this.productItem = [];
this.getProduct(this.menuList[index].id);
const selectedCategory = this.menuList[index];
// 如果是"猜你喜欢"(id为空),滚动到顶部
if (!selectedCategory.id && selectedCategory.id !== 0) {
this.goodsListScrollTop = 0;
this.$nextTick(() => {
this.goodsListScrollTop = 0;
});
} else {
// 确保吸顶状态
if (!this.isContainerSticky) {
this.isContainerSticky = true;
}
// 通过scroll-into-view滚动到对应分类的第一个商品
const targetId = 'category-' + selectedCategory.id;
// 先清空再设置,确保同一个id也能触发滚动
this.scrollIntoViewId = '';
this.$nextTick(() => {
this.isAutoScrolling = true;
this.scrollIntoViewId = targetId;
// 延迟恢复滚动检测,避免自动滚动触发分类切换
setTimeout(() => {
this.isAutoScrolling = false;
this.isSwitching = false;
}, 500);
});
return;
}
setTimeout(() => {
this.isSwitching = false;
}, 300);
this.$forceUpdate();
},
openOrderWait(item){
this.chooseWaitType = false
@ -1221,7 +1334,6 @@
height: 100%;
font-size: 24rpx;
position: relative;
overflow: hidden;
}
/* 顶部背景图随页面滚动(不固定) */
@ -1443,11 +1555,21 @@
}
.goods-list {
width: 95%;
height: auto;
flex: 1;
height: 100%;
border-radius: 20rpx;
margin: 0 auto 20rpx;
overflow: scroll;
overflow: hidden;
}
.container-sticky {
position: fixed;
left: 0;
width: 100%;
z-index: 50;
height: calc(100vh - 80px);
background: #F5F8F5;
padding: 0 2.5%;
box-sizing: border-box;
}
.goods-top {

Loading…
Cancel
Save