|
|
@@ -1,10 +1,11 @@
|
|
|
<!--
|
|
|
店铺首页-秒杀专区/团购专区
|
|
|
按 layoutCols(1/2/3) 渲染活动商品,含倒计时;秒杀按钮为「立即抢购」,团购按钮为「去开团」;
|
|
|
+ 仅在活动有效期内(startTime~endTime)展示,未开始或结束后整块隐藏;
|
|
|
点击商品/按钮跳转商品详情页(秒杀/团购下单流程暂沿用商品详情页,未来可扩展专属下单页)
|
|
|
-->
|
|
|
<template>
|
|
|
- <view v-if="data && data.enabled == 1 && data.goods && data.goods.length" class="home-activity">
|
|
|
+ <view v-if="isActive && data && data.enabled == 1 && data.goods && data.goods.length" class="home-activity">
|
|
|
<view class="activity-head">
|
|
|
<view class="activity-head-row">
|
|
|
<view class="activity-title-row">
|
|
|
@@ -83,6 +84,8 @@ export default {
|
|
|
data() {
|
|
|
return {
|
|
|
countdown: { h: '00', m: '00', s: '00' },
|
|
|
+ /** 是否处于活动有效期,控制整块专区显隐 */
|
|
|
+ isActive: false,
|
|
|
_timer: null
|
|
|
}
|
|
|
},
|
|
|
@@ -103,15 +106,19 @@ export default {
|
|
|
}
|
|
|
},
|
|
|
watch: {
|
|
|
- 'data.endTime': {
|
|
|
+ // 活动起止时间变更时重算有效期与倒计时(接口刷新后同步)
|
|
|
+ 'data.startTime': {
|
|
|
immediate: true,
|
|
|
handler() {
|
|
|
this.restartCountdown()
|
|
|
}
|
|
|
+ },
|
|
|
+ 'data.endTime'() {
|
|
|
+ this.restartCountdown()
|
|
|
}
|
|
|
},
|
|
|
beforeDestroy() {
|
|
|
- if (this._timer) clearInterval(this._timer)
|
|
|
+ this.clearTimer()
|
|
|
},
|
|
|
methods: {
|
|
|
formatPrice(val) {
|
|
|
@@ -133,14 +140,63 @@ export default {
|
|
|
url: `/pages/goods/section-list?moduleKey=${this.type}&title=${encodeURIComponent(title)}&account=${this.account}&hdId=${this.hdId}`
|
|
|
})
|
|
|
},
|
|
|
+ /** 清除倒计时定时器,避免页面销毁或活动结束后空转 */
|
|
|
+ clearTimer() {
|
|
|
+ if (this._timer) {
|
|
|
+ clearInterval(this._timer)
|
|
|
+ this._timer = null
|
|
|
+ }
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 重启倒计时:先立即算一次有效期,再每秒刷新;
|
|
|
+ * 未开始时定时器继续跑以便到点展示,结束后停表并隐藏。
|
|
|
+ */
|
|
|
restartCountdown() {
|
|
|
- if (this._timer) clearInterval(this._timer)
|
|
|
+ this.clearTimer()
|
|
|
this.tickCountdown()
|
|
|
- this._timer = setInterval(this.tickCountdown, 1000)
|
|
|
+ // 已结束则无需再开定时器;未开始/进行中继续每秒刷新
|
|
|
+ if (this._shouldKeepTimer()) {
|
|
|
+ this._timer = setInterval(this.tickCountdown, 1000)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 是否还需维持定时器:时间配置有效且未到结束时刻
|
|
|
+ * (未开始也要继续跑,以便到点自动展示)
|
|
|
+ * @returns {boolean}
|
|
|
+ */
|
|
|
+ _shouldKeepTimer() {
|
|
|
+ const start = parseInt(this.data && this.data.startTime, 10) || 0
|
|
|
+ const end = parseInt(this.data && this.data.endTime, 10) || 0
|
|
|
+ if (start <= 0 || end <= 0) return false
|
|
|
+ const now = Math.floor(Date.now() / 1000)
|
|
|
+ return now < end
|
|
|
},
|
|
|
+ /**
|
|
|
+ * 按 startTime/endTime 刷新专区显隐与倒计时数字;
|
|
|
+ * 与后端 calcActivityStatus 一致:仅 now ∈ [start, end] 时展示。
|
|
|
+ */
|
|
|
tickCountdown() {
|
|
|
+ const start = parseInt(this.data && this.data.startTime, 10) || 0
|
|
|
const end = parseInt(this.data && this.data.endTime, 10) || 0
|
|
|
const now = Math.floor(Date.now() / 1000)
|
|
|
+
|
|
|
+ // 无有效时间或已超过结束时间:隐藏专区并停表
|
|
|
+ if (start <= 0 || end <= 0 || now > end) {
|
|
|
+ this.isActive = false
|
|
|
+ this.countdown = { h: '00', m: '00', s: '00' }
|
|
|
+ this.clearTimer()
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 未到开始时间:暂不展示,定时器继续等待到点
|
|
|
+ if (now < start) {
|
|
|
+ this.isActive = false
|
|
|
+ this.countdown = { h: '00', m: '00', s: '00' }
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 活动进行中:展示专区并更新剩余时分秒
|
|
|
+ this.isActive = true
|
|
|
let diff = end - now
|
|
|
if (diff < 0) diff = 0
|
|
|
const h = Math.floor(diff / 3600)
|
|
|
@@ -151,6 +207,11 @@ export default {
|
|
|
m: String(m).padStart(2, '0'),
|
|
|
s: String(s).padStart(2, '0')
|
|
|
}
|
|
|
+ // 刚好走到结束点时下一秒会隐藏;diff 为 0 时也立即隐藏,避免残留 00:00:00
|
|
|
+ if (diff === 0) {
|
|
|
+ this.isActive = false
|
|
|
+ this.clearTimer()
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|