diff --git a/package2/group/groupBuySingle.vue b/package2/group/groupBuySingle.vue
index 4ea3319..4511aa2 100644
--- a/package2/group/groupBuySingle.vue
+++ b/package2/group/groupBuySingle.vue
@@ -126,7 +126,7 @@
+
- 差{{item.targetMembers - item.currentMembers}}人拼成
+ 差{{getMissingGroupMembers(item)}}人成团
@@ -164,7 +164,7 @@
拼团价更香
- 约人一起下单
+ 店内商品任选拼单
@@ -187,7 +187,7 @@
+
- 差{{item.minGroupCount}}人拼成
+ 差{{getMissingGroupMembers(item)}}人成团
@@ -424,11 +424,19 @@
选{{spec.name}}(可选{{spec.canbuy}}个)
-
-
- {{option}}
+
+
+
+ {{option}}
+
+
+
+ {{isSpecExpanded(sIndex) ? '收起' : '展开'}}
+
@@ -547,7 +555,7 @@
差{{item.targetMembers - item.currentMembers}}人拼成
+ class="missing-count">{{getMissingGroupMembers(item)}}人成团
@@ -820,6 +828,18 @@
保存图片
+
+
+
@@ -885,6 +905,7 @@
detailItem: {},
checkMoreBuyIndex: '',
parsedSpecs: [],
+ specExpandedMap: [],
moreBuyList: [],
selectedGroupRule: {},
pageNum: 1,
@@ -942,7 +963,12 @@
sharePosterImage: '',
shareQrcodeUrl: '',
posterCanvasWidth: 320,
- posterCanvasHeight: 450
+ posterCanvasHeight: 450,
+ shopUnavailableDialog: {
+ title: '',
+ message: '',
+ hours: ''
+ }
}
},
components: {
@@ -964,12 +990,12 @@
shopSubtitle() {
if (this.isStoreGroupOrder) {
return this.isSocialArea
- ? '到店核销,约上好友一起拼更划算'
- : '到店核销,约上同学一起拼更划算'
+ ? '到店核销,任选商品即可参团'
+ : '到店核销,任选商品即可参团'
}
return this.isSocialArea
- ? '约上好友一起拼,越快成团越快开吃'
- : '约上室友同学一起拼,越快成团越快开吃'
+ ? '约上好友一起拼,任选商品即可参团'
+ : '约上室友同学一起拼,任选商品即可参团'
},
shopNameSizeClass() {
const nameLength = String(this.shopItem.shopName || '').length;
@@ -1090,13 +1116,6 @@
if (this.type == 'shop') {
if (parsedItem) {
this.shopItem = parsedItem;
- if (this.shopItem.products) {
- this.shopRecommend = this.shopItem.products
- for (let i = 0; i < this.shopRecommend.length; i++) {
- this.shopRecommend[i].categoryId = '1'
- this.shopRecommend[i].isChecked = false
- }
- }
}
} else {
if (parsedItem) {
@@ -1105,8 +1124,7 @@
}
if (this.shopItem && this.shopItem.id) {
if (!this.ensureShopInCurrentRegion(this.shopItem)) return;
- this.getCategory(this.shopItem.id);
- this.getProduct('');
+ this.loadShopById(this.shopItem.id, this.shopItem);
} else if (option.shopId) {
this.loadShopById(option.shopId);
} else if (this.groupId) {
@@ -1280,6 +1298,85 @@
}
}
},
+ prepareShopRecommend() {
+ this.shopRecommend = Array.isArray(this.shopItem.products) ? this.shopItem.products : [];
+ for (let i = 0; i < this.shopRecommend.length; i++) {
+ this.shopRecommend[i].categoryId = '1';
+ this.shopRecommend[i].isChecked = false;
+ }
+ },
+ resetShopContent() {
+ this.menuList = [{
+ categoryName: '推荐',
+ id: 'tuijian',
+ checked: true
+ }];
+ this.productItem = [];
+ this.moreBuyList = [];
+ },
+ loadShopContent() {
+ this.resetShopContent();
+ this.prepareShopRecommend();
+ this.getCategory(this.shopItem.id);
+ this.getProduct('');
+ },
+ getShopStatus(item) {
+ const status = Number(item && item.status);
+ return isNaN(status) ? 1 : status;
+ },
+ getTakeawayStatus(item) {
+ const status = Number(item && item.shopTakeaway && item.shopTakeaway.status);
+ return isNaN(status) ? 0 : status;
+ },
+ isShopPaused(item) {
+ return this.getShopStatus(item) != 1 || this.getTakeawayStatus(item) != 0;
+ },
+ isShopUnavailable(item) {
+ return this.isShopPaused(item) || !this.isShopWithinBusinessHours(item && item.shopTakeaway);
+ },
+ getBusinessHoursText(item) {
+ const takeaway = item && item.shopTakeaway;
+ if (!takeaway) return '';
+ const periods = this.parseBusinessHourPeriods(takeaway);
+ if (!periods.length) return '';
+ return periods.map(p => p.begin + '-' + p.end).join('、');
+ },
+ getShopUnavailableInfo(item) {
+ const hours = this.getBusinessHoursText(item);
+ if (this.isShopPaused(item)) {
+ return {
+ title: '店铺暂停营业',
+ message: '商家当前已暂停接单,先去首页看看其他饭团吧。',
+ hours
+ };
+ }
+ return {
+ title: '现在休息中',
+ message: hours ? '商家还没到营业时间,稍后再来拼团吧。' : '商家暂未配置可营业时段,先去首页看看其他饭团吧。',
+ hours
+ };
+ },
+ guardShopAvailability(shopItem) {
+ if (!this.isShopUnavailable(shopItem)) return true;
+ const info = this.getShopUnavailableInfo(shopItem);
+ this.shopUnavailableDialog = info;
+ this.clearShareRedirectCache();
+ this.$nextTick(() => {
+ if (this.$refs.shopUnavailablePopup) {
+ this.$refs.shopUnavailablePopup.open();
+ } else {
+ this.tui.toast(info.title);
+ this.backHome();
+ }
+ });
+ return false;
+ },
+ confirmShopUnavailable() {
+ if (this.$refs.shopUnavailablePopup) {
+ this.$refs.shopUnavailablePopup.close();
+ }
+ this.backHome();
+ },
loadShopByGroupId() {
if (!this.groupId) return;
this.tui.request("/mall/order/selectMallOrderByGroupId/" + this.groupId, "GET", {}, false, true).then((res) => {
@@ -1329,7 +1426,7 @@
groupDeliveryTimeIncludesTransfer: transferTime > 0 ? 1 : 0
};
},
- loadShopById(shopId) {
+ loadShopById(shopId, fallbackShop) {
if (!shopId) return;
let area = uni.getStorageSync('area');
let regionId = '';
@@ -1346,19 +1443,21 @@
}, false, true).then((shopRes) => {
if (shopRes.code != 200 || !shopRes.result || !shopRes.result.shop) {
this.tui.toast(shopRes.message || '商家信息获取失败');
+ if (fallbackShop && this.guardShopAvailability(fallbackShop)) {
+ this.shopItem = fallbackShop;
+ this.loadShopContent();
+ }
return;
}
this.shopItem = this.normalizeShopDeliveryFields(shopRes.result);
if (!this.ensureShopInCurrentRegion(this.shopItem)) return;
- if (this.shopItem.products) {
- this.shopRecommend = this.shopItem.products;
- for (let i = 0; i < this.shopRecommend.length; i++) {
- this.shopRecommend[i].categoryId = '1';
- this.shopRecommend[i].isChecked = false;
- }
+ if (!this.guardShopAvailability(this.shopItem)) return;
+ this.loadShopContent();
+ }).catch(() => {
+ if (fallbackShop && this.guardShopAvailability(fallbackShop)) {
+ this.shopItem = fallbackShop;
+ this.loadShopContent();
}
- this.getCategory(this.shopItem.id);
- this.getProduct('');
});
},
onBottomPopupChange(e) {
@@ -1698,6 +1797,7 @@
}
} catch (e) {}
}
+ this.resetSpecExpandedMap();
this.isPintuan = true;
if (this.groupId) {
@@ -1843,6 +1943,7 @@
}
} catch (e) {}
}
+ this.resetSpecExpandedMap();
if (index == 'pintuan') {
this.isPintuan = true;
@@ -1928,6 +2029,18 @@
}
}
},
+ resetSpecExpandedMap() {
+ this.specExpandedMap = this.parsedSpecs.map(() => false);
+ },
+ shouldShowSpecExpand(spec) {
+ return spec && Array.isArray(spec.options) && spec.options.length > 4;
+ },
+ isSpecExpanded(sIndex) {
+ return !!this.specExpandedMap[sIndex];
+ },
+ toggleSpecExpand(sIndex) {
+ this.$set(this.specExpandedMap, sIndex, !this.isSpecExpanded(sIndex));
+ },
selectSpec(sIndex, option) {
let spec = this.parsedSpecs[sIndex];
let idx = spec.selected.indexOf(option);
@@ -2173,23 +2286,59 @@
});
}
},
- //判断是否在营业时间内
- isWithinBusinessHours(begin, end) {
- // 获取当前时间的时和分
+ // 判断是否在营业时间内(支持多时段、跨夜)
+ isShopWithinBusinessHours(takeaway) {
+ if (!takeaway) return false;
+ const periods = this.parseBusinessHourPeriods(takeaway);
+ if (!periods.length) return false;
const now = new Date();
const currentMinutes = now.getHours() * 60 + now.getMinutes();
-
- // 解析开始和结束时间(格式 "HH:MM")
+ for (let i = 0; i < periods.length; i++) {
+ if (this.isWithinBusinessHours(periods[i].begin, periods[i].end, currentMinutes)) {
+ return true;
+ }
+ }
+ return false;
+ },
+ parseBusinessHourPeriods(takeaway) {
+ let list = takeaway.businessHourList;
+ if ((!list || !list.length) && takeaway.businessHours) {
+ try {
+ list = typeof takeaway.businessHours === 'string' ? JSON.parse(takeaway.businessHours) : takeaway.businessHours;
+ } catch (e) {
+ list = [];
+ }
+ }
+ if (list && list.length) {
+ return list.filter(item => item && item.begin && item.end).map(item => ({
+ begin: String(item.begin).substring(0, 5),
+ end: String(item.end).substring(0, 5)
+ }));
+ }
+ if (takeaway.businessHourBegin && takeaway.businessHourEnd) {
+ return [{
+ begin: String(takeaway.businessHourBegin).substring(0, 5),
+ end: String(takeaway.businessHourEnd).substring(0, 5)
+ }];
+ }
+ return [];
+ },
+ isWithinBusinessHours(begin, end, currentMinutes) {
+ const nowMinutes = currentMinutes != null ? currentMinutes : (() => {
+ const now = new Date();
+ return now.getHours() * 60 + now.getMinutes();
+ })();
const parseTime = (timeStr) => {
- const [hours, minutes] = timeStr.split(':').map(Number);
- return hours * 60 + minutes;
+ const parts = String(timeStr || '00:00').split(':').map(Number);
+ return (parts[0] || 0) * 60 + (parts[1] || 0);
};
-
const startMinutes = parseTime(begin);
const endMinutes = parseTime(end);
-
- // 判断是否在区间内(包含端点)
- return currentMinutes >= startMinutes && currentMinutes <= endMinutes;
+ if (startMinutes === endMinutes) return true;
+ if (startMinutes < endMinutes) {
+ return nowMinutes >= startMinutes && nowMinutes <= endMinutes;
+ }
+ return nowMinutes >= startMinutes || nowMinutes <= endMinutes;
},
adjustCart(cartId, delta) {
let index = this.cartItems.findIndex(c => c.cartId === cartId);
@@ -2329,6 +2478,17 @@
return !!(item && Array.isArray(item.productGroupBuyPrices) && item.productGroupBuyPrices.length > 0 &&
item.isMoreBuy != 1);
},
+ getMissingGroupMembers(item) {
+ if (!item) return 1;
+ if (item.minGroupCount !== undefined && item.minGroupCount !== null && item.minGroupCount !== '') {
+ const minGroupCount = Number(item.minGroupCount);
+ return Math.max(isNaN(minGroupCount) ? 1 : minGroupCount, 1);
+ }
+ const target = Number(item.targetMembers || 0);
+ const current = Number(item.currentMembers || 0);
+ const missing = target - current;
+ return Math.max(isNaN(missing) ? 1 : missing, 1);
+ },
buyingye() {
uni.showToast({
title: '商品不在售卖时间!',
@@ -2825,6 +2985,90 @@
position: relative;
}
+ .shop-unavailable-popup {
+ width: 610rpx;
+ padding: 46rpx 38rpx 36rpx;
+ box-sizing: border-box;
+ border-radius: 42rpx;
+ background:
+ radial-gradient(circle at 12% 0%, rgba(223, 255, 150, 0.72), transparent 36%),
+ radial-gradient(circle at 92% 16%, rgba(166, 255, 234, 0.66), transparent 40%),
+ linear-gradient(180deg, rgba(255, 255, 255, 0.98), rgba(249, 255, 242, 0.98));
+ box-shadow: 0 26rpx 70rpx rgba(6, 77, 58, 0.22);
+ border: 2rpx solid rgba(255, 255, 255, 0.9);
+ position: relative;
+ overflow: hidden;
+ text-align: center;
+ }
+
+ .shop-unavailable-glow {
+ position: absolute;
+ right: -110rpx;
+ top: -120rpx;
+ width: 300rpx;
+ height: 300rpx;
+ border-radius: 50%;
+ background: rgba(255, 202, 116, 0.22);
+ }
+
+ .shop-unavailable-badge {
+ position: relative;
+ display: inline-block;
+ height: 44rpx;
+ line-height: 44rpx;
+ padding: 0 20rpx;
+ border-radius: 44rpx 44rpx 44rpx 12rpx;
+ background: linear-gradient(90deg, #e3ff96, #a6ffea);
+ color: #08735d;
+ font-size: 22rpx;
+ font-weight: 900;
+ box-shadow: 0 10rpx 20rpx rgba(20, 115, 88, 0.12);
+ }
+
+ .shop-unavailable-title {
+ position: relative;
+ margin-top: 24rpx;
+ font-size: 40rpx;
+ line-height: 52rpx;
+ font-weight: 900;
+ color: #073d33;
+ }
+
+ .shop-unavailable-text {
+ position: relative;
+ margin-top: 16rpx;
+ font-size: 26rpx;
+ line-height: 40rpx;
+ color: rgba(0, 35, 28, 0.66);
+ font-weight: 700;
+ }
+
+ .shop-unavailable-hours {
+ position: relative;
+ margin-top: 22rpx;
+ padding: 14rpx 20rpx;
+ border-radius: 24rpx;
+ background: rgba(255, 247, 225, 0.82);
+ color: #ff6f2c;
+ font-size: 23rpx;
+ line-height: 34rpx;
+ font-weight: 900;
+ word-break: break-all;
+ }
+
+ .shop-unavailable-btn {
+ position: relative;
+ margin-top: 34rpx;
+ height: 78rpx;
+ line-height: 78rpx;
+ border-radius: 78rpx;
+ background: linear-gradient(90deg, #e3ff96, #a6ffea);
+ color: #073d33;
+ font-size: 30rpx;
+ font-weight: 900;
+ box-shadow: 0 16rpx 30rpx rgba(13, 114, 82, 0.18);
+ }
+
/* 顶部背景图随页面滚动(不固定) */
.title {
background: url('https://jewel-shop.oss-cn-beijing.aliyuncs.com/8bc15960c2dc40268e295d6dd23aecce.png') no-repeat;
@@ -3625,14 +3869,43 @@
font-weight: 700;
}
+ .spec-option-row {
+ display: flex;
+ align-items: flex-start;
+ }
+
.spec22 {
display: flex;
+ flex: 1;
+ min-width: 0;
white-space: nowrap;
overflow-x: scroll;
}
+ .spec22-expanded {
+ flex-wrap: wrap;
+ white-space: normal;
+ overflow-x: visible;
+ row-gap: 20rpx;
+ }
+
+ .spec-expand-btn {
+ flex: 0 0 112rpx;
+ height: 72rpx;
+ margin-left: 12rpx;
+ border-radius: 20rpx;
+ background: rgba(166, 255, 234, 0.35);
+ color: #20cda8;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 24rpx;
+ font-weight: 700;
+ }
+
.spec222 {
display: inline-block;
+ flex-shrink: 0;
padding: 0 20rpx;
background: rgba(247, 248, 248, 0.6);
color: #777;
@@ -3645,6 +3918,7 @@
.spec-check {
display: inline-block;
+ flex-shrink: 0;
padding: 0 20rpx;
background: rgba(166, 255, 234, 1);
height: 72rpx;
diff --git a/package2/group/studentStoreList.vue b/package2/group/studentStoreList.vue
index c034673..1cee421 100644
--- a/package2/group/studentStoreList.vue
+++ b/package2/group/studentStoreList.vue
@@ -679,7 +679,7 @@
},
getPreviewProducts(item) {
const products = Array.isArray(item.products) ? item.products : []
- return products.filter(product => product.delFlag == 1).slice(0, 3)
+ return products.filter(product => product.isPush == 1 && product.delFlag == 1)
},
getGroupPrice(product) {
const prices = product.productGroupBuyPrices