wangfukang 3 weeks ago
parent
commit
cdd4f96d18
  1. 360
      package2/group/groupBuySingle.vue
  2. 2
      package2/group/studentStoreList.vue

360
package2/group/groupBuySingle.vue

@ -126,7 +126,7 @@
<view class="weipincheng">+</view> <view class="weipincheng">+</view>
</view> </view>
<view class="pintuan-right-cha"> <view class="pintuan-right-cha">
差<text class="missing-count">{{item.targetMembers - item.currentMembers}}人</text>拼成 差<text class="missing-count">{{getMissingGroupMembers(item)}}人</text>成团
</view> </view>
</view> </view>
</view> </view>
@ -164,7 +164,7 @@
</view> </view>
<view class="goods-vibe" v-if="isProductGroupBuyAvailable(item)"> <view class="goods-vibe" v-if="isProductGroupBuyAvailable(item)">
<text class="goods-vibe-tag">拼团价更香</text> <text class="goods-vibe-tag">拼团价更香</text>
<text class="goods-vibe-copy">约人一起下单</text> <text class="goods-vibe-copy">店内商品任选拼单</text>
</view> </view>
<view class="goods-content-center"> <view class="goods-content-center">
<view class="goods-deal1"> <view class="goods-deal1">
@ -187,7 +187,7 @@
<view class="weipincheng">+</view> <view class="weipincheng">+</view>
</view> </view>
<view class="pintuan-right-cha" @tap.stop="openOrderWait(item)"> <view class="pintuan-right-cha" @tap.stop="openOrderWait(item)">
差<text style="color: red;">{{item.minGroupCount}}人</text>拼成 差<text style="color: red;">{{getMissingGroupMembers(item)}}人</text>成团
</view> </view>
</view> </view>
</view> </view>
@ -424,11 +424,19 @@
<view class="spec11"> <view class="spec11">
选{{spec.name}}(可选{{spec.canbuy}}个) 选{{spec.name}}(可选{{spec.canbuy}}个)
</view> </view>
<view class="spec22"> <view class="spec-option-row">
<view :class="spec.selected.indexOf(option) !== -1 ? 'spec-check' : 'spec222'" <view class="spec22" :class="{'spec22-expanded': isSpecExpanded(sIndex)}">
v-for="(option, oIndex) in spec.options" :key="oIndex" <view :class="spec.selected.indexOf(option) !== -1 ? 'spec-check' : 'spec222'"
@tap="selectSpec(sIndex, option)"> v-for="(option, oIndex) in spec.options" :key="oIndex"
{{option}} @tap="selectSpec(sIndex, option)">
{{option}}
</view>
</view>
<view class="spec-expand-btn" v-if="shouldShowSpecExpand(spec)"
@tap.stop="toggleSpecExpand(sIndex)">
<text>{{isSpecExpanded(sIndex) ? '收起' : '展开'}}</text>
<uni-icons :type="isSpecExpanded(sIndex) ? 'top' : 'bottom'" size="12"
color="#20cda8"></uni-icons>
</view> </view>
</view> </view>
</view> </view>
@ -547,7 +555,7 @@
</view> </view>
<view style="line-height: 40rpx;padding-left: 10rpx;"> <view style="line-height: 40rpx;padding-left: 10rpx;">
差<text 差<text
class="missing-count">{{item.targetMembers - item.currentMembers}}人</text>拼成 class="missing-count">{{getMissingGroupMembers(item)}}人</text>成团
</view> </view>
</view> </view>
</view> </view>
@ -820,6 +828,18 @@
<view class="share-save-btn" @tap="saveSharePoster">保存图片</view> <view class="share-save-btn" @tap="saveSharePoster">保存图片</view>
</view> </view>
</uni-popup> </uni-popup>
<uni-popup ref="shopUnavailablePopup" background-color="transparent" :mask-click="false">
<view class="shop-unavailable-popup" @tap.stop>
<view class="shop-unavailable-glow"></view>
<view class="shop-unavailable-badge">饭团提醒</view>
<view class="shop-unavailable-title">{{shopUnavailableDialog.title}}</view>
<view class="shop-unavailable-text">{{shopUnavailableDialog.message}}</view>
<view class="shop-unavailable-hours" v-if="shopUnavailableDialog.hours">
营业时间 {{shopUnavailableDialog.hours}}
</view>
<view class="shop-unavailable-btn" @tap="confirmShopUnavailable">返回首页</view>
</view>
</uni-popup>
<common-loading /> <common-loading />
<canvas canvas-id="shopShareCanvas" id="shopShareCanvas" class="share-canvas" <canvas canvas-id="shopShareCanvas" id="shopShareCanvas" class="share-canvas"
:style="{width: posterCanvasWidth + 'px', height: posterCanvasHeight + 'px'}"></canvas> :style="{width: posterCanvasWidth + 'px', height: posterCanvasHeight + 'px'}"></canvas>
@ -885,6 +905,7 @@
detailItem: {}, detailItem: {},
checkMoreBuyIndex: '', checkMoreBuyIndex: '',
parsedSpecs: [], parsedSpecs: [],
specExpandedMap: [],
moreBuyList: [], moreBuyList: [],
selectedGroupRule: {}, selectedGroupRule: {},
pageNum: 1, pageNum: 1,
@ -942,7 +963,12 @@
sharePosterImage: '', sharePosterImage: '',
shareQrcodeUrl: '', shareQrcodeUrl: '',
posterCanvasWidth: 320, posterCanvasWidth: 320,
posterCanvasHeight: 450 posterCanvasHeight: 450,
shopUnavailableDialog: {
title: '',
message: '',
hours: ''
}
} }
}, },
components: { components: {
@ -964,12 +990,12 @@
shopSubtitle() { shopSubtitle() {
if (this.isStoreGroupOrder) { if (this.isStoreGroupOrder) {
return this.isSocialArea return this.isSocialArea
? '到店核销,约上好友一起拼更划算' ? '到店核销,任选商品即可参团'
: '到店核销,约上同学一起拼更划算' : '到店核销,任选商品即可参团'
} }
return this.isSocialArea return this.isSocialArea
? '约上好友一起拼,越快成团越快开吃' ? '约上好友一起拼,任选商品即可参团'
: '约上室友同学一起拼,越快成团越快开吃' : '约上室友同学一起拼,任选商品即可参团'
}, },
shopNameSizeClass() { shopNameSizeClass() {
const nameLength = String(this.shopItem.shopName || '').length; const nameLength = String(this.shopItem.shopName || '').length;
@ -1090,13 +1116,6 @@
if (this.type == 'shop') { if (this.type == 'shop') {
if (parsedItem) { if (parsedItem) {
this.shopItem = 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 { } else {
if (parsedItem) { if (parsedItem) {
@ -1105,8 +1124,7 @@
} }
if (this.shopItem && this.shopItem.id) { if (this.shopItem && this.shopItem.id) {
if (!this.ensureShopInCurrentRegion(this.shopItem)) return; if (!this.ensureShopInCurrentRegion(this.shopItem)) return;
this.getCategory(this.shopItem.id); this.loadShopById(this.shopItem.id, this.shopItem);
this.getProduct('');
} else if (option.shopId) { } else if (option.shopId) {
this.loadShopById(option.shopId); this.loadShopById(option.shopId);
} else if (this.groupId) { } 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() { loadShopByGroupId() {
if (!this.groupId) return; if (!this.groupId) return;
this.tui.request("/mall/order/selectMallOrderByGroupId/" + this.groupId, "GET", {}, false, true).then((res) => { this.tui.request("/mall/order/selectMallOrderByGroupId/" + this.groupId, "GET", {}, false, true).then((res) => {
@ -1329,7 +1426,7 @@
groupDeliveryTimeIncludesTransfer: transferTime > 0 ? 1 : 0 groupDeliveryTimeIncludesTransfer: transferTime > 0 ? 1 : 0
}; };
}, },
loadShopById(shopId) { loadShopById(shopId, fallbackShop) {
if (!shopId) return; if (!shopId) return;
let area = uni.getStorageSync('area'); let area = uni.getStorageSync('area');
let regionId = ''; let regionId = '';
@ -1346,19 +1443,21 @@
}, false, true).then((shopRes) => { }, false, true).then((shopRes) => {
if (shopRes.code != 200 || !shopRes.result || !shopRes.result.shop) { if (shopRes.code != 200 || !shopRes.result || !shopRes.result.shop) {
this.tui.toast(shopRes.message || '商家信息获取失败'); this.tui.toast(shopRes.message || '商家信息获取失败');
if (fallbackShop && this.guardShopAvailability(fallbackShop)) {
this.shopItem = fallbackShop;
this.loadShopContent();
}
return; return;
} }
this.shopItem = this.normalizeShopDeliveryFields(shopRes.result); this.shopItem = this.normalizeShopDeliveryFields(shopRes.result);
if (!this.ensureShopInCurrentRegion(this.shopItem)) return; if (!this.ensureShopInCurrentRegion(this.shopItem)) return;
if (this.shopItem.products) { if (!this.guardShopAvailability(this.shopItem)) return;
this.shopRecommend = this.shopItem.products; this.loadShopContent();
for (let i = 0; i < this.shopRecommend.length; i++) { }).catch(() => {
this.shopRecommend[i].categoryId = '1'; if (fallbackShop && this.guardShopAvailability(fallbackShop)) {
this.shopRecommend[i].isChecked = false; this.shopItem = fallbackShop;
} this.loadShopContent();
} }
this.getCategory(this.shopItem.id);
this.getProduct('');
}); });
}, },
onBottomPopupChange(e) { onBottomPopupChange(e) {
@ -1698,6 +1797,7 @@
} }
} catch (e) {} } catch (e) {}
} }
this.resetSpecExpandedMap();
this.isPintuan = true; this.isPintuan = true;
if (this.groupId) { if (this.groupId) {
@ -1843,6 +1943,7 @@
} }
} catch (e) {} } catch (e) {}
} }
this.resetSpecExpandedMap();
if (index == 'pintuan') { if (index == 'pintuan') {
this.isPintuan = true; 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) { selectSpec(sIndex, option) {
let spec = this.parsedSpecs[sIndex]; let spec = this.parsedSpecs[sIndex];
let idx = spec.selected.indexOf(option); 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 now = new Date();
const currentMinutes = now.getHours() * 60 + now.getMinutes(); const currentMinutes = now.getHours() * 60 + now.getMinutes();
for (let i = 0; i < periods.length; i++) {
// 解析开始和结束时间(格式 "HH:MM") 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 parseTime = (timeStr) => {
const [hours, minutes] = timeStr.split(':').map(Number); const parts = String(timeStr || '00:00').split(':').map(Number);
return hours * 60 + minutes; return (parts[0] || 0) * 60 + (parts[1] || 0);
}; };
const startMinutes = parseTime(begin); const startMinutes = parseTime(begin);
const endMinutes = parseTime(end); const endMinutes = parseTime(end);
if (startMinutes === endMinutes) return true;
// 判断是否在区间内(包含端点) if (startMinutes < endMinutes) {
return currentMinutes >= startMinutes && currentMinutes <= endMinutes; return nowMinutes >= startMinutes && nowMinutes <= endMinutes;
}
return nowMinutes >= startMinutes || nowMinutes <= endMinutes;
}, },
adjustCart(cartId, delta) { adjustCart(cartId, delta) {
let index = this.cartItems.findIndex(c => c.cartId === cartId); let index = this.cartItems.findIndex(c => c.cartId === cartId);
@ -2329,6 +2478,17 @@
return !!(item && Array.isArray(item.productGroupBuyPrices) && item.productGroupBuyPrices.length > 0 && return !!(item && Array.isArray(item.productGroupBuyPrices) && item.productGroupBuyPrices.length > 0 &&
item.isMoreBuy != 1); 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() { buyingye() {
uni.showToast({ uni.showToast({
title: '商品不在售卖时间!', title: '商品不在售卖时间!',
@ -2825,6 +2985,90 @@
position: relative; 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 { .title {
background: url('https://jewel-shop.oss-cn-beijing.aliyuncs.com/8bc15960c2dc40268e295d6dd23aecce.png') no-repeat; background: url('https://jewel-shop.oss-cn-beijing.aliyuncs.com/8bc15960c2dc40268e295d6dd23aecce.png') no-repeat;
@ -3625,14 +3869,43 @@
font-weight: 700; font-weight: 700;
} }
.spec-option-row {
display: flex;
align-items: flex-start;
}
.spec22 { .spec22 {
display: flex; display: flex;
flex: 1;
min-width: 0;
white-space: nowrap; white-space: nowrap;
overflow-x: scroll; 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 { .spec222 {
display: inline-block; display: inline-block;
flex-shrink: 0;
padding: 0 20rpx; padding: 0 20rpx;
background: rgba(247, 248, 248, 0.6); background: rgba(247, 248, 248, 0.6);
color: #777; color: #777;
@ -3645,6 +3918,7 @@
.spec-check { .spec-check {
display: inline-block; display: inline-block;
flex-shrink: 0;
padding: 0 20rpx; padding: 0 20rpx;
background: rgba(166, 255, 234, 1); background: rgba(166, 255, 234, 1);
height: 72rpx; height: 72rpx;

2
package2/group/studentStoreList.vue

@ -679,7 +679,7 @@
}, },
getPreviewProducts(item) { getPreviewProducts(item) {
const products = Array.isArray(item.products) ? item.products : [] 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) { getGroupPrice(product) {
const prices = product.productGroupBuyPrices const prices = product.productGroupBuyPrices

Loading…
Cancel
Save