From da0b8e4b1d0c7ecf206123473201495bff0fe632 Mon Sep 17 00:00:00 2001
From: wangfukang <15630117759@163.com>
Date: Wed, 18 Mar 2026 17:57:27 +0800
Subject: [PATCH] =?UTF-8?q?=E4=B8=8B=E5=8D=95=E9=80=89=E5=95=86=E5=93=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
package1/group/groupBuySingle.vue | 623 +++++++++++++++++++-----------
1 file changed, 394 insertions(+), 229 deletions(-)
diff --git a/package1/group/groupBuySingle.vue b/package1/group/groupBuySingle.vue
index c44aa11..40fcc5c 100644
--- a/package1/group/groupBuySingle.vue
+++ b/package1/group/groupBuySingle.vue
@@ -1,17 +1,18 @@
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
@@ -77,13 +78,14 @@
-
-
+
+
+
-
+
面对面团
-
- 拼团购买¥15.00
+
+ 拼团购买¥{{selectedGroupRule && selectedGroupRule.groupPrice ? parseFloat(selectedGroupRule.groupPrice).toFixed(2) : '0.00'}}
-
- 直接购买
+
+ 加入购物车
@@ -389,16 +330,28 @@
export default {
data() {
return {
+ loadStatus: 'more',
type:'',
shopId:'',
shopItem:{},
- productItem:{},
productId:'',
productItem:[],
- buyCar:new Map(),
+ cartItems: [],
+ currentItem: {},
+ parsedSpecs: [],
+ selectedGroupRule: {},
pageNum:1,
+ total:1,
+ // 导航栏高度(用于sticky top偏移)
+ navBarHeight: 0,
+ // 分类栏距离页面顶部的距离(用于上滑检测)
+ menuListOffsetTop: 0,
+ lastScrollTop: 0,
+ // 防止切换分类之后onPageScroll闪回的标志
+ isSwitching: false,
searchForm:{
shopId:'',
+ delFlag: 1,
pageNum: 1,
pageSize: '10',
categoryId:''
@@ -414,6 +367,14 @@
},
components: {
+ },
+ computed: {
+ cartTotalCount() {
+ return this.cartItems.reduce((acc, curr) => acc + curr.quantity, 0);
+ },
+ cartTotalPrice() {
+ return this.cartItems.reduce((acc, curr) => acc + (curr.quantity * curr.price), 0).toFixed(2);
+ }
},
filters: {
sliceMsg(val) {
@@ -445,38 +406,91 @@
return begin;
}
},
+ onPageScroll(e) {
+ const scrollTop = e.scrollTop;
+ const isScrollingUp = scrollTop < this.lastScrollTop;
+ // 向上滑到靠近页面顶部时(背景头图区域),切换到上一个分类
+ // 门槛用 80px:用户需要明确地滑回头部较大区域,避免误触发
+ if (isScrollingUp && scrollTop < 80 && !this.isSwitching) {
+ const currIdx = this.menuList.findIndex(m => m.checked);
+ if (currIdx > 0) {
+ this._switchCategory(currIdx - 1);
+ }
+ }
+ this.lastScrollTop = scrollTop;
+ },
+ onReachBottom() {
+ // 当前分类还有更多页时,继续加载
+ if (this.searchForm.pageNum < this.total) {
+ this.searchForm.pageNum++;
+ this.getProduct(this.searchForm.categoryId);
+ return;
+ }
+ // 当前分类已是最后一页,自动切换到下一分类
+ const currIdx = this.menuList.findIndex(m => m.checked);
+ if (currIdx !== -1 && currIdx < this.menuList.length - 1) {
+ this._switchCategory(currIdx + 1);
+ }
+ },
onLoad(option) {
- this.type = option.type
- if(this.type == 'shop'){
- this.shopItem = JSON.parse(option.item)
- }else{
- this.productItem = JSON.parse(option.item)
+ this.type = option.type;
+ if (this.type == 'shop') {
+ this.shopItem = JSON.parse(option.item);
+ } else {
+ this.productItem = JSON.parse(option.item);
}
- this.getCategory(this.shopItem.id)
- this.getProduct('')
+ this.getCategory(this.shopItem.id);
+ this.getProduct('');
},
onShow() {
- this.menuButtonInfo = uni.getMenuButtonBoundingClientRect()
+ this.menuButtonInfo = uni.getMenuButtonBoundingClientRect();
+ // 计算导航栏高度用于sticky offset:statusBarHeight + 44px内容区
+ const info = uni.getSystemInfoSync();
+ this.navBarHeight = info.statusBarHeight + 44;
+ },
+ onReady() {
+ // 记录分类栏相对页面的偏移量,用于上滑检测
+ setTimeout(() => {
+ const query = uni.createSelectorQuery().in(this);
+ query.select('#menuList').boundingClientRect(rect => {
+ if (rect) this.menuListOffsetTop = rect.top + this.lastScrollTop;
+ }).exec();
+ }, 500);
},
methods: {
- getProduct(categoryId){
- let that = this
- this.searchForm.shopId = this.shopItem.id
- this.searchForm.categoryId = categoryId
+ getProduct(categoryId) {
+ let that = this;
+ this.loadStatus = 'loading';
+ this.searchForm.shopId = this.shopItem.id;
+ this.searchForm.categoryId = categoryId;
that.tui.request("/app/product/getShareList", "POST", this.searchForm, false, false).then((res) => {
- if (res.code == 200) {
- if (that.pageNum == 1) {
- that.productItem = res.result.records
- } else {
- that.productItem = [...that.productItem, ...res.result.records]
- }
- that.$forceUpdate()
+ that.loadStatus = 'nomore';
+ if (res.code == 200) {
+ if (that.searchForm.pageNum == 1) {
+ that.productItem = res.result.records;
} else {
- that.tui.toast(res.message)
- return
+ that.productItem = [...that.productItem, ...res.result.records];
}
- uni.hideLoading()
- }).catch((res) => {})
+ console.log(res.result.records)
+ that.total = res.result.pages; // pages = 总页数
+ that.pageNum = that.searchForm.pageNum;
+ // 当前分类没有商品,自动跳过到下一个分类
+ // 注意:这里不能用isSwitching拦戚,因为_switchCategory本身已置 isSwitching=true
+ if (res.result.records.length === 0) {
+ const currIdx = that.menuList.findIndex(m => m.checked);
+ if (currIdx !== -1 && currIdx < that.menuList.length - 1) {
+ // 重置锁再跳过,防止连锁导致永远跳不过
+ that.isSwitching = false;
+ that._switchCategory(currIdx + 1);
+ }
+ }
+ that.$forceUpdate();
+ } else {
+ that.tui.toast(res.message);
+ return;
+ }
+ uni.hideLoading();
+ }).catch((res) => {});
},
getCategory(id){
let that = this
@@ -498,33 +512,163 @@
uni.hideLoading()
}).catch((res) => {})
},
- checkTab(index){
- for(let i=0;i { this.isSwitching = false; }, 400);
+ },
+ checkTab(index) {
+ 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);
+ // 滚动到正确位置:分类栏刚好吸顶在nav-bar下方
+ // menuListOffsetTop - navBarHeight 使分类栏正好在sticky位置,首条商品可见
+ const target = this.menuListOffsetTop - this.navBarHeight;
+ uni.pageScrollTo({ scrollTop: target > 0 ? target : 0, duration: 200 });
},
openPopup(type,index,item){
if(type == 'car'){
this.$refs.carPopup.open('bottom')
}else if(type == 'xiadan'){
+ this.currentItem = item;
+ // Parse specifications
+ this.parsedSpecs = [];
+ if(item.attributeList && item.attributeList !== '{}') {
+ try {
+ let attrs = typeof item.attributeList === 'string' ? JSON.parse(item.attributeList) : item.attributeList;
+ for(let key in attrs) {
+ if(attrs[key] && attrs[key].title && attrs[key].title.length > 0) {
+ this.parsedSpecs.push({
+ name: key,
+ options: attrs[key].title,
+ selected: attrs[key].title[0] // Default select first
+ });
+ }
+ }
+ } catch(e) {
+ console.error("Failed to parse specifications", e);
+ }
+ }
+
if(index == 'pintuan'){
- this.isPintuan = true
- }else{
- this.isPintuan = false
+ this.isPintuan = true;
+ // Set default group rule
+ if(item.productGroupBuyPrices && item.productGroupBuyPrices.length > 0) {
+ this.selectedGroupRule = item.productGroupBuyPrices[0];
+ } else {
+ this.selectedGroupRule = {};
+ }
+ this.$refs.pintuanPopup.open('bottom');
+ } else {
+ this.isPintuan = false;
+ // If solo buy and NO specs, add immediately to cart
+ if(this.parsedSpecs.length === 0) {
+ this.addToCart(item, null);
+ uni.showToast({ title: '已加入购物车', icon: 'none' });
+ } else {
+ // Open popup to select specs
+ this.$refs.pintuanPopup.open('bottom');
+ }
}
- if(item.attributeList == '' || item.attributeList == null){
- this.buyCar.has(item.id)
- }else{
- this.$refs.pintuanPopup.open('bottom')
+ }
+ },
+ selectSpec(sIndex, option) {
+ this.parsedSpecs[sIndex].selected = option;
+ this.$forceUpdate();
+ },
+ selectGroupRule(rule) {
+ this.selectedGroupRule = rule;
+ },
+ submitAddToCart() {
+ let specChoices = {};
+ for (let spec of this.parsedSpecs) {
+ specChoices[spec.name] = spec.selected;
+ }
+ this.addToCart(this.currentItem, specChoices);
+ uni.showToast({ title: '已加入购物车', icon: 'none' });
+ this.$refs.pintuanPopup.close();
+ },
+ submitPintuan() {
+ let specChoices = {};
+ for (let spec of this.parsedSpecs) {
+ specChoices[spec.name] = spec.selected;
+ }
+ // Pack data for checkout
+ let goData = {
+ item: this.currentItem,
+ groupRule: this.selectedGroupRule,
+ specs: specChoices
+ };
+ // Directly navigate to checkout
+ uni.navigateTo({
+ // Update this url to actual checkout path
+ url: '/package1/goods/confirmPintuanOrder?item=' + encodeURIComponent(JSON.stringify(goData))
+ });
+ this.$refs.pintuanPopup.close();
+ },
+ addToCart(item, specs) {
+ let specStr = specs ? JSON.stringify(specs) : '';
+ let cartId = item.id + '_' + specStr;
+ let existingItem = this.cartItems.find(c => c.cartId === cartId);
+ if(existingItem) {
+ existingItem.quantity++;
+ } else {
+ let priceToUse = 0;
+ if(item.attributeListPrice) {
+ try {
+ let pObj = typeof item.attributeListPrice === 'string' ? JSON.parse(item.attributeListPrice) : item.attributeListPrice;
+ if(Array.isArray(pObj) && pObj.length > 0) {
+ priceToUse = parseFloat(pObj[0].specPrice);
+ } else {
+ for(let k in pObj) { priceToUse = parseFloat(pObj[k].specPrice); break; }
+ }
+ } catch(e){}
+ }
+ this.cartItems.push({
+ cartId: cartId,
+ item: item,
+ specs: specs,
+ quantity: 1,
+ price: priceToUse.toFixed(2)
+ });
+ }
+ },
+ adjustCart(cartId, delta) {
+ let index = this.cartItems.findIndex(c => c.cartId === cartId);
+ if(index !== -1) {
+ let newQty = this.cartItems[index].quantity + delta;
+ if(newQty <= 0) {
+ this.cartItems.splice(index, 1);
+ } else {
+ this.cartItems[index].quantity = newQty;
}
-
}
},
+ getSpecDisplayString(specs) {
+ if(!specs) return '';
+ let arr = [];
+ for(let k in specs) { arr.push(specs[k]); }
+ return arr.join(',');
+ },
+ submitCartCheckout() {
+ if(this.cartItems.length === 0) {
+ uni.showToast({ title: '购物车为空', icon: 'none' });
+ return;
+ }
+ // 类似普通订单结算逻辑
+ uni.navigateTo({
+ url: '/package1/goods/confirmOrder?cart=' + encodeURIComponent(JSON.stringify(this.cartItems))
+ });
+ },
goDetail(type) {
if (type == 'goodsDetail') {
uni.navigateTo({
@@ -564,30 +708,34 @@
position: relative;
}
+ /* 顶部背景图随页面滚动(不固定) */
.title {
- background: url('https://jewel-shop.oss-cn-beijing.aliyuncs.com/9362dfb66c0f426789584cabb3977ccc.png') no-repeat;
+ background: url('https://jewel-shop.oss-cn-beijing.aliyuncs.com/8bc15960c2dc40268e295d6dd23aecce.png') no-repeat;
width: 100%;
- height: 700rpx;
- background-size: 100%;
- position: fixed;
- top: 0;
- z-index: -1;
+ height: 340rpx;
+ background-size: 100% 100%;
}
- .title-sreach {
- width: 75%;
+ /* 固定在顶部的导航栏,覆盖在背景图上 */
+ .nav-bar {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
display: flex;
- height: 200rpx;
+ align-items: center;
+ z-index: 100;
+ padding: 8px 12px;
+ box-sizing: border-box;
}
.title-search {
- margin-top: 110rpx;
display: flex;
- background: #fff;
+ flex: 1;
+ background: rgba(255,255,255,0.9);
height: 54rpx;
margin-left: 20rpx;
border-radius: 54rpx;
- width: 460rpx;
input {
height: 54rpx;
@@ -596,11 +744,20 @@
}
.back-btn {
- padding-top: 110rpx;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 60rpx;
+ height: 60rpx;
+ background: rgba(0,0,0,0.25);
+ border-radius: 50%;
}
+ /* content 上移,叠在背景图下方,减少头部空白 */
.content {
- margin-top: 430rpx;
+ margin-top: -150rpx;
+ position: relative;
+ z-index: 1;
}
.shop-img {
@@ -766,7 +923,9 @@
width: 95%;
height: auto;
border-radius: 20rpx;
- margin: 20rpx auto 20rpx;
+ margin: 0 auto 20rpx;
+ /* padding-top等于分类栏高度,防止商品内容被sticky栏遮住 */
+ padding-top: 10px;
}
.goods-top {
@@ -1119,11 +1278,17 @@
margin-bottom: 5px;
}
.menu-list{
- height: 35px;
+ height: 45px;
width: 100%;
overflow-x: scroll;
display: flex;
overflow-y: hidden;
+ position: sticky;
+ top: 0;
+ z-index: 90;
+ background: #F5F8F5;
+ align-items: center;
+ padding-bottom: 4px;
}
.checked-img{
width: 90px;