wangfukang 3 weeks ago
parent
commit
ad24ca736f
  1. 336
      package2/group/groupBuySingle.vue

336
package2/group/groupBuySingle.vue

@ -1,6 +1,6 @@
<template>
<!-- 拼团单一商家 -->
<view class="page1" @touchmove="onPageTouchMove">
<view class="page1">
<!-- 固定顶部导航栏悬浮在背景图之上 -->
<view class="nav-bar"
:style="{'padding-top': menuButtonInfo.top +'px','background':((orderListWait.length > 0 && lastScrollTop>217) || (orderListWait.length == 0 && lastScrollTop>149))?'#fff':''}">
@ -111,22 +111,20 @@
</swiper-item>
</swiper>
</view>
<!-- 分类栏移到goods-list外层position:sticky才能生效 -->
<!-- 占位元素当container吸顶时保持页面高度不塌缩 -->
<view v-if="isContainerSticky" :style="'height:' + containerHeight + 'px;margin-top:20rpx;'"></view>
<view class="container goods-panel" :style="containerStyle">
<scroll-view scroll-y id="menuList" class="menu-scroll"
style="border-right: 1px solid #eee;font-weight: 700;font-size: 28rpx;height: 100%;width: 160rpx;">
<view class="menu1" @tap="checkTab(index)" v-for="(item,index) in menuList" :key="index"
:style="{'border-top-right-radius':item.checked?'20rpx':'','border-bottom-right-radius':item.checked?'20rpx':'','color':item.checked?'rgba(0, 35, 28, 1)':'#777','background':item.checked?'#fff':''}">
<image class="menu-active-dot" v-if="item.checked" src="/static/images/img/loading.gif"
mode="aspectFit"></image>
<view style="width: 160rpx;">{{item.categoryName}}</view>
</view>
</scroll-view>
<scroll-view class="goods-list" scroll-y :scroll-into-view="scrollIntoViewId"
:scroll-top="goodsListScrollTop" @scroll="onGoodsListScroll" @scrolltoupper="onGoodsListScrollToTop"
:scroll-with-animation="true">
<!-- 整页 page-scroll左侧分类条 sticky 吸顶右侧商品跟随页面滚动 -->
<view class="catalog-row" id="catalog-row">
<view class="catalog-menu-wrap" :style="{ top: navBarHeight + 'px' }">
<scroll-view scroll-y id="menuList" class="menu-scroll"
:style="{ height: stickyInnerHeight + 'px' }">
<view class="menu1" @tap="checkTab(index)" v-for="(item,index) in menuList" :key="index"
:style="{'border-top-right-radius':item.checked?'20rpx':'','border-bottom-right-radius':item.checked?'20rpx':'','color':item.checked?'rgba(0, 35, 28, 1)':'#777','background':item.checked?'#fff':''}">
<image class="menu-active-dot" v-if="item.checked" src="/static/images/img/loading.gif"
mode="aspectFit"></image>
<view style="width: 160rpx;">{{item.categoryName}}</view>
</view>
</scroll-view>
</view>
<view class="catalog-goods">
<view class="goods-member goods-card" :id="'category-' + item.categoryId"
v-for="(item,index) in productItem" :key="index" @tap="goDetail('product',item)">
<view class="goods-card-shine"></view>
@ -192,8 +190,7 @@
</view>
<uni-load-more :status="loadStatus" @change="onChange" />
<view style="width: 100%;height: 160rpx;"></view>
</scroll-view>
</view>
</view>
</view>
<view style="width: 100%;height: 160rpx;"></view>
@ -681,21 +678,14 @@
pageNum: 1,
total: 1,
chooseWaitType: false,
// sticky top
navBarHeight: 0,
orderListWait: [],
//
menuListOffsetTop: 0,
lastScrollTop: 0,
// onPageScroll
isSwitching: false,
containerOriginalTop: 0,
scrollIntoViewId: '',
goodsListScrollTop: 0,
isAutoScrolling: false,
isContainerSticky: false,
containerHeight: 0,
pageScrollTop: 0,
// sticky top
navBarHeight: 0,
orderListWait: [],
lastScrollTop: 0,
// onPageScroll
isSwitching: false,
// onPageScroll data undefined
_lastDetectTs: 0,
searchForm: {
shopId: '',
delFlag: 1,
@ -733,17 +723,15 @@
cartTotalPrice() {
return this.cartItems.reduce((acc, curr) => acc + (curr.quantity * curr.price), 0).toFixed(2);
},
containerStyle() {
if (this.isContainerSticky) {
// fixed = - -
const sysInfo = uni.getSystemInfoSync();
const bottomBarPx = Math.round(80 * sysInfo.windowWidth / 375);
const h = sysInfo.windowHeight - this.navBarHeight - bottomBarPx;
return 'display:flex;position:fixed;left:0;top:' + this.navBarHeight +
'px;margin:0 auto;right:0;height:' + h + 'px;z-index:50;background:#F5F8F5;box-sizing:border-box;';
} else {
return 'display:flex;height:72%;margin-top:20rpx;';
}
stickyInnerHeight() {
// sticky
// iPhone
const sysInfo = uni.getSystemInfoSync();
const safeBottom = sysInfo.safeArea ? Math.max(sysInfo.windowHeight - sysInfo.safeArea.bottom, 0) : 0;
const checkoutBarPx = Math.round(126 * sysInfo.windowWidth / 750);
const checkoutOffsetPx = Math.round(18 * sysInfo.windowWidth / 750);
const bottomReservedPx = checkoutBarPx + checkoutOffsetPx + safeBottom;
return Math.max(240, sysInfo.windowHeight - this.navBarHeight - bottomReservedPx);
}
},
filters: {
@ -821,113 +809,89 @@
onShow() {
this.menuButtonInfo = uni.getMenuButtonBoundingClientRect();
this.fetchCoupons();
// sticky offsetstatusBarHeight + 40px
// (menuButton)
// / iPhone statusBarHeight + 40
const info = uni.getSystemInfoSync();
this.navBarHeight = info.statusBarHeight + 40;
if (this.menuButtonInfo && this.menuButtonInfo.height) {
const top = this.menuButtonInfo.top;
const padding = Math.max(top - info.statusBarHeight, 0);
this.navBarHeight = info.statusBarHeight + padding * 2 + this.menuButtonInfo.height;
} else {
this.navBarHeight = info.statusBarHeight + 40;
}
},
onPullDownRefresh() {
this.getCategory(this.shopItem.id);
this.getProduct('');
},
onReady() {
// container
setTimeout(() => {
const query = uni.createSelectorQuery().in(this);
query.select('.container').boundingClientRect(rect => {
if (rect) {
this.containerOriginalTop = rect.top;
this.menuListOffsetTop = rect.top;
this.containerHeight = rect.height;
}
}).exec();
}, 500);
},
onPageScroll(e) {
this.lastScrollTop = e.scrollTop;
// container
const stickyThreshold = this.containerOriginalTop - this.navBarHeight;
if (stickyThreshold <= 0) return;
if (e.scrollTop >= stickyThreshold) {
if (!this.isContainerSticky) {
this.isContainerSticky = true;
}
//
if (e.scrollTop > stickyThreshold + 5) {
uni.pageScrollTo({
scrollTop: stickyThreshold,
duration: 0
});
}
} else {
if (this.isContainerSticky) {
this.isContainerSticky = false;
}
}
// 80ms selectorQuery
const now = Date.now();
if (now - this._lastDetectTs < 80) return;
this._lastDetectTs = now;
this.detectCurrentCategory();
},
methods: {
nowMakeMethod(){
this.nowMake = !this.nowMake
},
// touchmovegoods-list
onPageTouchMove(e) {
},
// goods-list +
onGoodsListScroll(e) {
if (this.isAutoScrolling) return;
const scrollTop = e.detail.scrollTop;
//
this.detectCurrentCategory();
},
onGoodsListScrollToTop() {
if (this.isAutoScrolling) return;
scrollGoodsListToTop() {
// catalog-row nav-bar
const query = uni.createSelectorQuery().in(this);
query.select('#catalog-row').boundingClientRect();
query.selectViewport().scrollOffset();
query.exec((res) => {
if (!res || !res[0] || !res[1]) {
this.isSwitching = false;
return;
}
const target = Math.max(res[1].scrollTop + res[0].top - this.navBarHeight, 0);
uni.pageScrollTo({
scrollTop: target,
duration: 200
});
setTimeout(() => {
this.isSwitching = false;
}, 350);
});
},
//
// nav-bar 沿
detectCurrentCategory() {
if (this.isSwitching) return;
const query = uni.createSelectorQuery().in(this);
// goods-listgoods-member
query.selectAll('.goods-member').boundingClientRect();
query.select('.goods-list').boundingClientRect();
query.exec((res) => {
if (!res || !res[0] || !res[1]) return;
if (!res || !res[0]) return;
const items = res[0];
const listRect = res[1];
const listTop = listRect.top;
// navBarHeight
const baseline = this.navBarHeight + 20;
let currentCategoryId = '';
// goods-listitem
for (let i = items.length - 1; i >= 0; i--) {
if (items[i].top <= listTop + 10) {
// productItemcategoryId
if (items[i].top <= baseline) {
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();
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);
}
found = true;
break;
}
found = true;
break;
}
// categoryId""
if (!found && currentCategoryId === '') {
for (let j = 0; j < this.menuList.length; j++) {
this.menuList[j].checked = (j === 0);
}
this.$forceUpdate();
}
if (!found && currentCategoryId === '') {
for (let j = 0; j < this.menuList.length; j++) {
this.menuList[j].checked = (j === 0);
}
}
});
@ -977,9 +941,9 @@
//
that.getOrderWait();
that.total = res.result.pages; // pages =
that.pageNum = that.searchForm.pageNum;
that.$forceUpdate();
that.total = res.result.pages; // pages =
that.pageNum = that.searchForm.pageNum;
that.$forceUpdate();
} else {
that.tui.toast(res.message, 1000);
return;
@ -1007,57 +971,42 @@
uni.hideLoading()
}).catch((res) => {})
},
checkTab(index) {
this.isSwitching = true;
for (let i = 0; i < this.menuList.length; i++) {
this.menuList[i].checked = (i === index);
}
const selectedCategory = this.menuList[index];
// ""idtuijian
if (!selectedCategory.id && selectedCategory.id !== 0) {
this.goodsListScrollTop = 0;
this.$nextTick(() => {
this.goodsListScrollTop = 0;
});
setTimeout(() => {
this.isSwitching = false;
}, 300);
this.$forceUpdate();
return;
}
checkTab(index) {
this.isSwitching = true;
for (let i = 0; i < this.menuList.length; i++) {
this.menuList[i].checked = (i === index);
}
//
const doScrollToCategory = () => {
const targetId = 'category-' + selectedCategory.id;
this.scrollIntoViewId = '';
this.$nextTick(() => {
this.isAutoScrolling = true;
this.scrollIntoViewId = targetId;
setTimeout(() => {
this.isAutoScrolling = false;
this.isSwitching = false;
}, 500);
});
};
const selectedCategory = this.menuList[index];
if (!selectedCategory.id && selectedCategory.id !== 0) {
this.scrollGoodsListToTop();
return;
}
//
if (!this.isContainerSticky) {
const stickyThreshold = this.containerOriginalTop - this.navBarHeight;
// scroll #category-<id> nav-bar 沿
const targetSelector = '#category-' + selectedCategory.id;
this.$nextTick(() => {
const query = uni.createSelectorQuery().in(this);
query.select(targetSelector).boundingClientRect();
query.selectViewport().scrollOffset();
query.exec((res) => {
if (!res || !res[0] || !res[1]) {
this.isSwitching = false;
return;
}
const rect = res[0];
const vp = res[1];
const target = Math.max(vp.scrollTop + rect.top - this.navBarHeight, 0);
uni.pageScrollTo({
scrollTop: stickyThreshold,
duration: 200,
complete: () => {
setTimeout(() => {
doScrollToCategory();
}, 250);
}
scrollTop: target,
duration: 200
});
} else {
doScrollToCategory();
}
this.$forceUpdate();
},
setTimeout(() => {
this.isSwitching = false;
}, 350);
});
});
},
openOrderWait(item) {
this.chooseWaitType = false
if (item != '') {
@ -1175,15 +1124,15 @@
}
}
that.$forceUpdate();
} else {
that.tui.toast(res.message, 1000);
return;
}
uni.hideLoading();
}).catch((res) => {});
},
chooseOrderWait(item) {
that.$forceUpdate();
} else {
that.tui.toast(res.message, 1000);
return;
}
uni.hideLoading();
}).catch((res) => {});
},
chooseOrderWait(item) {
this.$refs.pintuanGroupPopup.close();
this.isPindan = true;
this.$refs.tishiPopup.open();
@ -2051,8 +2000,9 @@
.goods-list {
flex: 1;
height: 100%;
min-height: 0;
border-radius: 20rpx;
overflow: hidden;
}
.fee-value {
color: #00231C;
@ -2805,9 +2755,37 @@
box-shadow: 0 -8rpx 28rpx rgba(0, 35, 28, 0.04);
}
/* 单一 page-scroll 结构下的目录布局:左侧分类条 sticky,右侧商品跟随页面滚动 */
.catalog-row {
display: flex;
align-items: flex-start;
margin-top: 20rpx;
background: transparent;
}
.catalog-menu-wrap {
position: sticky;
z-index: 50;
flex-shrink: 0;
width: 160rpx;
background: rgba(247, 255, 251, 0.95);
border-right: 1rpx solid #eee;
border-top-left-radius: 34rpx;
}
.catalog-goods {
flex: 1;
min-width: 0;
padding-left: 4rpx;
}
.menu-scroll {
background: rgba(247, 255, 251, 0.9);
border-right: 0 !important;
flex-shrink: 0;
width: 160rpx;
font-weight: 700;
font-size: 28rpx;
}
.menu1 {

Loading…
Cancel
Save