|
|
@@ -15,7 +15,7 @@
|
|
|
</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
- <view class="video-box" :style="{'height':isShu?'calc(100vh - 264rpx)':'420rpx'}">
|
|
|
+ <view class="video-box" :style="{'height':isShu?'calc(100vh - 264rpx)':'420rpx'}" >
|
|
|
<image v-if="!isLogin || isAddKf!=1" class="video-poster" :src="courseInfo.imgUrl" mode="aspectFill">
|
|
|
</image>
|
|
|
<video @timeupdate="onTimeUpdate" @progress="progressChange" @error="videoErrorCallback" @play="getPlay"
|
|
|
@@ -36,7 +36,7 @@
|
|
|
</cover-view>
|
|
|
</cover-view>
|
|
|
<!-- 虚拟下单跑马灯:视频顶层覆盖,向上滚动淡出切换 -->
|
|
|
- <cover-view class="vip-order-cover-wrap vip-order-cover-wrap--triple" v-if="fakeMarqueeEligible && isTripleMarqueeMode && marqueeTriplePayloads.length">
|
|
|
+ <cover-view class="vip-order-cover-wrap vip-order-cover-wrap--triple" v-if="showFakeMarqueeOnVideoCover && isTripleMarqueeMode && marqueeTriplePayloads.length">
|
|
|
<cover-view class="vip-order-cover-triple-panel vip-order-cover-triple-current" :class="[marqueeTripleSwitching ? 'vip-order-triple-leave' : '']">
|
|
|
<cover-view
|
|
|
class="vip-order-cover-item vip-order-cover-triple-item"
|
|
|
@@ -46,8 +46,8 @@
|
|
|
>
|
|
|
<cover-view class="vip-order-cover-content" v-if="row.type === 'virtual' || row.type === 'self'">
|
|
|
<cover-view class="vip-order-seg vip-order-seg-user">{{ row.nickname }}{{ row.maskedId }}</cover-view>
|
|
|
- <cover-view class="vip-order-seg vip-order-seg-time">{{ row.timeOffset }}</cover-view>
|
|
|
- <cover-view class="vip-order-seg vip-order-seg-suffix">{{ row.suffix }}</cover-view>
|
|
|
+ <cover-view class="vip-order-seg vip-order-seg-time">{{ row.timeOffset }}{{ row.suffix }}</cover-view>
|
|
|
+ <!-- <cover-view class="vip-order-seg vip-order-seg-suffix"></cover-view> -->
|
|
|
</cover-view>
|
|
|
<cover-view class="vip-order-cover-content" v-else>
|
|
|
{{ row.fullText }}
|
|
|
@@ -63,8 +63,8 @@
|
|
|
>
|
|
|
<cover-view class="vip-order-cover-content" v-if="row.type === 'virtual' || row.type === 'self'">
|
|
|
<cover-view class="vip-order-seg vip-order-seg-user">{{ row.nickname }}{{ row.maskedId }}</cover-view>
|
|
|
- <cover-view class="vip-order-seg vip-order-seg-time">{{ row.timeOffset }}</cover-view>
|
|
|
- <cover-view class="vip-order-seg vip-order-seg-suffix">{{ row.suffix }}</cover-view>
|
|
|
+ <cover-view class="vip-order-seg vip-order-seg-time">{{ row.timeOffset }}{{ row.suffix }}</cover-view>
|
|
|
+ <!-- <cover-view class="vip-order-seg vip-order-seg-suffix"></cover-view> -->
|
|
|
</cover-view>
|
|
|
<cover-view class="vip-order-cover-content" v-else>
|
|
|
{{ row.fullText }}
|
|
|
@@ -72,8 +72,7 @@
|
|
|
</cover-view>
|
|
|
</cover-view>
|
|
|
</cover-view>
|
|
|
- </cover-view>
|
|
|
- <cover-view class="vip-order-cover-wrap" v-else-if="fakeMarqueeEligible && marqueeDisplayPayload">
|
|
|
+ <cover-view class="vip-order-cover-wrap" v-else-if="showFakeMarqueeOnVideoCover && marqueeDisplayPayload">
|
|
|
<cover-view
|
|
|
class="vip-order-cover-item vip-order-cover-current"
|
|
|
:class="[
|
|
|
@@ -83,8 +82,8 @@
|
|
|
>
|
|
|
<cover-view class="vip-order-cover-content" v-if="marqueeDisplayPayload.type === 'virtual' || marqueeDisplayPayload.type === 'self'">
|
|
|
<cover-view class="vip-order-seg vip-order-seg-user">{{ marqueeDisplayPayload.nickname }}{{ marqueeDisplayPayload.maskedId }}</cover-view>
|
|
|
- <cover-view class="vip-order-seg vip-order-seg-time">{{ marqueeDisplayPayload.timeOffset }}</cover-view>
|
|
|
- <cover-view class="vip-order-seg vip-order-seg-suffix">{{ marqueeDisplayPayload.suffix }}</cover-view>
|
|
|
+ <cover-view class="vip-order-seg vip-order-seg-time">{{ marqueeDisplayPayload.timeOffset }}{{ marqueeDisplayPayload.suffix }}</cover-view>
|
|
|
+ <!-- <cover-view class="vip-order-seg vip-order-seg-suffix"></cover-view> -->
|
|
|
</cover-view>
|
|
|
<cover-view class="vip-order-cover-content" v-else>
|
|
|
{{ marqueeDisplayPayload.fullText }}
|
|
|
@@ -100,8 +99,8 @@
|
|
|
>
|
|
|
<cover-view class="vip-order-cover-content" v-if="marqueeIncomingPayload.type === 'virtual' || marqueeIncomingPayload.type === 'self'">
|
|
|
<cover-view class="vip-order-seg vip-order-seg-user">{{ marqueeIncomingPayload.nickname }}{{ marqueeIncomingPayload.maskedId }}</cover-view>
|
|
|
- <cover-view class="vip-order-seg vip-order-seg-time">{{ marqueeIncomingPayload.timeOffset }}</cover-view>
|
|
|
- <cover-view class="vip-order-seg vip-order-seg-suffix">{{ marqueeIncomingPayload.suffix }}</cover-view>
|
|
|
+ <cover-view class="vip-order-seg vip-order-seg-time">{{ marqueeIncomingPayload.timeOffset }}{{ marqueeIncomingPayload.suffix }}</cover-view>
|
|
|
+ <!-- <cover-view class="vip-order-seg vip-order-seg-suffix"></cover-view> -->
|
|
|
</cover-view>
|
|
|
<cover-view class="vip-order-cover-content" v-else>
|
|
|
{{ marqueeIncomingPayload.fullText }}
|
|
|
@@ -702,6 +701,8 @@
|
|
|
hasReportedAfterCountdown: false,
|
|
|
notice:'',//跑马灯,
|
|
|
isHeight:false,
|
|
|
+ // 跑马灯数据就绪门禁:避免首次进入时使用旧状态导致闪现
|
|
|
+ marqueeDataReady: false,
|
|
|
// 虚拟下单跑马灯
|
|
|
fakeOrderPool: [],
|
|
|
marqueeTriplePayloads: [],
|
|
|
@@ -716,9 +717,14 @@
|
|
|
marqueeSwitching: false,
|
|
|
pendingSelfMarqueeFirst: false,
|
|
|
_fakeMarqueeStarted: false,
|
|
|
+ /** 与 computed fakeMarqueeEligible 上次值比较,避免无 watch 时在 updateProductAndCardDisplay 高频调用中反复重置防抖 */
|
|
|
+ _fakeMarqueeEligiblePrev: undefined,
|
|
|
+ _marqueeStartDebounceTimer: null,
|
|
|
_fakeMarqueeTimer: null,
|
|
|
_marqueeSwitchTimer: null,
|
|
|
_marqueeTripleSwitchTimer: null,
|
|
|
+ /** 本人下单条按缓存 ts 与当前时间差定时回显刷新 */
|
|
|
+ _selfMarqueeClockTimer: null,
|
|
|
}
|
|
|
},
|
|
|
filters: {
|
|
|
@@ -782,26 +788,24 @@
|
|
|
return minSec === Infinity ? Infinity : minSec
|
|
|
},
|
|
|
fakeMarqueeEligible() {
|
|
|
+ // 商品/回放数据未完成刷新前,不允许启动展示,避免首次闪现
|
|
|
+ if (!this.marqueeDataReady) return false
|
|
|
if (this.showTreatment !== 0) return false
|
|
|
- const list = this.treatmentPackage || []
|
|
|
- if (!list.length) return false
|
|
|
- const firstSec = this.firstShelfSecondsAmongProducts
|
|
|
- if (!Number.isFinite(firstSec)) return false
|
|
|
- const cur = Number(this.playTime) || 0
|
|
|
- return cur >= firstSec
|
|
|
+ // 以“当前应展示的商品列表非空”作为跑马灯出现条件
|
|
|
+ // 这样能对齐你说的“商品上架才出现”,避免只用最早上架秒点导致的一帧差异
|
|
|
+ return Array.isArray(this.displayProductList) && this.displayProductList.length > 0
|
|
|
+ },
|
|
|
+ // 竖屏课打开小黄车 goodsList 弹窗时先藏住视频上的虚拟下单条,关闭后再显(不影响底层跑马灯计时)
|
|
|
+ showFakeMarqueeOnVideoCover() {
|
|
|
+ if (!this.fakeMarqueeEligible) return false
|
|
|
+ if (this.displayType === 'portrait' && this.isCart) return false
|
|
|
+ return true
|
|
|
},
|
|
|
isTripleMarqueeMode() {
|
|
|
return !!(this.isShu || this.isFull)
|
|
|
},
|
|
|
},
|
|
|
watch: {
|
|
|
- fakeMarqueeEligible(val) {
|
|
|
- if (val) {
|
|
|
- this.$nextTick(() => this.ensureFakeMarqueeStarted())
|
|
|
- } else {
|
|
|
- this.stopFakeMarqueeLoop()
|
|
|
- }
|
|
|
- },
|
|
|
coureLogin: {
|
|
|
immediate: true, // 页面一进入就检查一次
|
|
|
handler(val) {
|
|
|
@@ -813,6 +817,11 @@
|
|
|
this.goLogin()
|
|
|
}
|
|
|
}
|
|
|
+ },
|
|
|
+ isTripleMarqueeMode(now, was) {
|
|
|
+ if (!now || was) return
|
|
|
+ if (!this.fakeMarqueeEligible || !this._fakeMarqueeStarted) return
|
|
|
+ this.syncTripleMarqueeImmediate()
|
|
|
}
|
|
|
},
|
|
|
onLoad(option) {
|
|
|
@@ -874,6 +883,10 @@
|
|
|
// #endif
|
|
|
},
|
|
|
onShow() {
|
|
|
+ // 每次进入页面先关闭门禁,并清空旧跑马灯状态,等 getH5CourseVideoDetails 拉完数据再开启
|
|
|
+ this.stopFakeMarqueeLoop()
|
|
|
+ this.marqueeDataReady = false
|
|
|
+ this._fakeMarqueeEligiblePrev = undefined
|
|
|
this.userinfos = uni.getStorageSync('userinfos')
|
|
|
this.userInfo = uni.getStorageSync('userInfo')
|
|
|
this.tipsOpen = false
|
|
|
@@ -883,11 +896,6 @@
|
|
|
if (this.videoId) {
|
|
|
this.getH5CourseByVideo()
|
|
|
}
|
|
|
- this.$nextTick(() => {
|
|
|
- if (this.fakeMarqueeEligible && !this._fakeMarqueeStarted) {
|
|
|
- this.ensureFakeMarqueeStarted()
|
|
|
- }
|
|
|
- })
|
|
|
const AppToken = uni.getStorageSync('TOKEN_WEXIN')
|
|
|
console.log(AppToken)
|
|
|
if (AppToken) {
|
|
|
@@ -990,20 +998,45 @@
|
|
|
if (timeStr === '00:00:00') return false
|
|
|
return this._vipTimeStrToSec(timeStr) > 0
|
|
|
},
|
|
|
+ /** 缓存下单时间戳(videovip_myPurchase_*)序列化后可能为字符串,统一为毫秒数 */
|
|
|
+ _normalizePurchaseTs(ts) {
|
|
|
+ if (ts == null || ts === '') return 0
|
|
|
+ const n = typeof ts === 'number' ? ts : Number(ts)
|
|
|
+ return Number.isFinite(n) && n > 0 ? n : 0
|
|
|
+ },
|
|
|
+ _readVipSelfPurchaseTsMs() {
|
|
|
+ const row = uni.getStorageSync('videovip_myPurchase_' + this.videoId)
|
|
|
+ return this._normalizePurchaseTs(row && row.ts)
|
|
|
+ },
|
|
|
refreshVipPurchaseMarqueeFlag() {
|
|
|
const key = 'videovip_myPurchase_' + this.videoId
|
|
|
+ const consumedKey = 'videovip_myPurchaseMarqueeConsumed_' + this.videoId
|
|
|
const row = uni.getStorageSync(key)
|
|
|
- if (row && row.ts && Date.now() - row.ts <= 10 * 60 * 1000) {
|
|
|
- this.pendingSelfMarqueeFirst = true
|
|
|
+ const consumed = uni.getStorageSync(consumedKey)
|
|
|
+ const tsMs = this._normalizePurchaseTs(row && row.ts)
|
|
|
+ if (tsMs && Date.now() - tsMs <= 10 * 60 * 1000) {
|
|
|
+ // 同一笔下单 ts 仅允许跑马灯展示一次;中途退出再进不再展示(新下单 ts 变化后会再展示一次)
|
|
|
+ const consumedTs = this._normalizePurchaseTs(consumed && consumed.ts)
|
|
|
+ this.pendingSelfMarqueeFirst = !(consumedTs > 0 && consumedTs === tsMs)
|
|
|
} else {
|
|
|
this.pendingSelfMarqueeFirst = false
|
|
|
- if (row && row.ts) uni.removeStorageSync(key)
|
|
|
+ if (row && row.ts != null && row.ts !== '') {
|
|
|
+ uni.removeStorageSync(key)
|
|
|
+ const consumedTs = this._normalizePurchaseTs(consumed && consumed.ts)
|
|
|
+ if (consumedTs > 0 && consumedTs === tsMs) uni.removeStorageSync(consumedKey)
|
|
|
+ }
|
|
|
}
|
|
|
},
|
|
|
+ _markSelfPurchaseMarqueeConsumed() {
|
|
|
+ const tsMs = this._readVipSelfPurchaseTsMs()
|
|
|
+ if (!tsMs) return
|
|
|
+ try {
|
|
|
+ uni.setStorageSync('videovip_myPurchaseMarqueeConsumed_' + this.videoId, { ts: tsMs })
|
|
|
+ } catch (e) {}
|
|
|
+ },
|
|
|
formatSelfPurchaseMarqueePayload() {
|
|
|
- const key = 'videovip_myPurchase_' + this.videoId
|
|
|
- const row = uni.getStorageSync(key)
|
|
|
- if (!row || !row.ts) {
|
|
|
+ const tsMs = this._readVipSelfPurchaseTsMs()
|
|
|
+ if (!tsMs) {
|
|
|
return {
|
|
|
type: 'self',
|
|
|
nickname: '您本人',
|
|
|
@@ -1013,7 +1046,7 @@
|
|
|
fullText: '您本人刚刚已下单'
|
|
|
}
|
|
|
}
|
|
|
- const secTotal = Math.floor((Date.now() - row.ts) / 1000)
|
|
|
+ const secTotal = Math.floor((Date.now() - tsMs) / 1000)
|
|
|
if (secTotal < 60) {
|
|
|
const text = `${Math.max(1, secTotal)}秒前`
|
|
|
return {
|
|
|
@@ -1036,6 +1069,29 @@
|
|
|
fullText: `您本人${text}已下单`
|
|
|
}
|
|
|
},
|
|
|
+ _syncFakeMarqueeIfEligibleChanged() {
|
|
|
+ const val = this.fakeMarqueeEligible
|
|
|
+ if (val === this._fakeMarqueeEligiblePrev) return
|
|
|
+ this._fakeMarqueeEligiblePrev = val
|
|
|
+ if (val) {
|
|
|
+ if (this._marqueeStartDebounceTimer) {
|
|
|
+ clearTimeout(this._marqueeStartDebounceTimer)
|
|
|
+ this._marqueeStartDebounceTimer = null
|
|
|
+ }
|
|
|
+ this._marqueeStartDebounceTimer = setTimeout(() => {
|
|
|
+ this._marqueeStartDebounceTimer = null
|
|
|
+ if (this.fakeMarqueeEligible && !this._fakeMarqueeStarted) {
|
|
|
+ this.ensureFakeMarqueeStarted()
|
|
|
+ }
|
|
|
+ }, 300)
|
|
|
+ } else {
|
|
|
+ if (this._marqueeStartDebounceTimer) {
|
|
|
+ clearTimeout(this._marqueeStartDebounceTimer)
|
|
|
+ this._marqueeStartDebounceTimer = null
|
|
|
+ }
|
|
|
+ this.stopFakeMarqueeLoop()
|
|
|
+ }
|
|
|
+ },
|
|
|
ensureFakeMarqueeStarted() {
|
|
|
if (!this.fakeMarqueeEligible || this._fakeMarqueeStarted) return
|
|
|
this._fakeMarqueeStarted = true
|
|
|
@@ -1044,11 +1100,17 @@
|
|
|
}
|
|
|
this.applyFakeMarqueeTick()
|
|
|
this.scheduleFakeMarqueeNext()
|
|
|
+ this._startSelfMarqueeClockIfNeeded()
|
|
|
},
|
|
|
applyFakeMarqueeTick() {
|
|
|
if (this.isTripleMarqueeMode) {
|
|
|
const rows = this.buildTripleMarqueePayloads()
|
|
|
this.setTripleMarqueeDisplayWithAnim(rows)
|
|
|
+ // 本人下单在三联模式也只展示一轮,下一轮起恢复纯虚拟随机
|
|
|
+ if (rows.some(item => item && item.type === 'self')) {
|
|
|
+ this.pendingSelfMarqueeFirst = false
|
|
|
+ this._markSelfPurchaseMarqueeConsumed()
|
|
|
+ }
|
|
|
if (rows.length) {
|
|
|
this.marqueeDisplayPayload = rows[0]
|
|
|
this.marqueeDisplaySelf = this.marqueeDisplayPayload.type === 'self'
|
|
|
@@ -1058,14 +1120,14 @@
|
|
|
this.marqueeTriplePayloads = []
|
|
|
this.marqueeTripleIncomingPayloads = []
|
|
|
this.marqueeTripleSwitching = false
|
|
|
- const key = 'videovip_myPurchase_' + this.videoId
|
|
|
- const row = uni.getStorageSync(key)
|
|
|
- const purchaseOk = row && row.ts && Date.now() - row.ts <= 10 * 60 * 1000
|
|
|
+ const tsMs = this._readVipSelfPurchaseTsMs()
|
|
|
+ const purchaseOk = !!(tsMs && Date.now() - tsMs <= 10 * 60 * 1000)
|
|
|
if (purchaseOk && this.pendingSelfMarqueeFirst) {
|
|
|
const selfPayload = this.formatSelfPurchaseMarqueePayload()
|
|
|
this.marqueeCurrentText = selfPayload.fullText
|
|
|
this.marqueeSelfHighlight = true
|
|
|
this.pendingSelfMarqueeFirst = false
|
|
|
+ this._markSelfPurchaseMarqueeConsumed()
|
|
|
this.setMarqueeDisplayWithAnim(selfPayload, true)
|
|
|
return
|
|
|
}
|
|
|
@@ -1088,14 +1150,18 @@
|
|
|
},
|
|
|
buildTripleMarqueePayloads() {
|
|
|
const rows = []
|
|
|
- const hasSelf = this.hasRecentSelfPurchase()
|
|
|
+ const hasSelf = this.hasRecentSelfPurchase() && this.pendingSelfMarqueeFirst
|
|
|
if (!this.fakeOrderPool.length) {
|
|
|
this.fakeOrderPool = buildFakeOrderPool()
|
|
|
}
|
|
|
let guard = 0
|
|
|
- // 有本人记录时,先补足前两条虚拟数据,最后一条固定放本人下单
|
|
|
+ // 有本人记录时,把本人下单放第一条,其它再补足虚拟数据
|
|
|
+ if (hasSelf) {
|
|
|
+ rows.push(this.formatSelfPurchaseMarqueePayload())
|
|
|
+ }
|
|
|
const targetVirtualCount = hasSelf ? 2 : 3
|
|
|
- while (rows.length < targetVirtualCount && this.fakeOrderPool.length && guard < 10) {
|
|
|
+ let virtualCount = 0
|
|
|
+ while (virtualCount < targetVirtualCount && this.fakeOrderPool.length && guard < 10) {
|
|
|
const line = this.fakeOrderPool.shift()
|
|
|
guard += 1
|
|
|
if (!line) break
|
|
|
@@ -1107,16 +1173,63 @@
|
|
|
timeOffset: line.timeOffset,
|
|
|
suffix: line.suffix
|
|
|
})
|
|
|
- }
|
|
|
- if (hasSelf) {
|
|
|
- rows.push(this.formatSelfPurchaseMarqueePayload())
|
|
|
+ virtualCount += 1
|
|
|
}
|
|
|
return rows.slice(0, 3)
|
|
|
},
|
|
|
hasRecentSelfPurchase() {
|
|
|
- const key = 'videovip_myPurchase_' + this.videoId
|
|
|
- const row = uni.getStorageSync(key)
|
|
|
- return !!(row && row.ts && Date.now() - row.ts <= 10 * 60 * 1000)
|
|
|
+ const tsMs = this._readVipSelfPurchaseTsMs()
|
|
|
+ return !!(tsMs && Date.now() - tsMs <= 10 * 60 * 1000)
|
|
|
+ },
|
|
|
+ /** 按缓存 ts 与当前时间重新计算本人下单文案(停留同一轮跑马灯时也能更新相对时间) */
|
|
|
+ refreshSelfPurchaseMarqueeDisplayedTiming() {
|
|
|
+ const fresh = this.formatSelfPurchaseMarqueePayload()
|
|
|
+ if (this.isTripleMarqueeMode && this.marqueeTriplePayloads.length) {
|
|
|
+ const upd = (arr) =>
|
|
|
+ arr.map((r) => (r && r.type === 'self' ? Object.assign({}, fresh) : r))
|
|
|
+ this.marqueeTriplePayloads = upd(this.marqueeTriplePayloads)
|
|
|
+ if (this.marqueeTripleIncomingPayloads.length) {
|
|
|
+ this.marqueeTripleIncomingPayloads = upd(this.marqueeTripleIncomingPayloads)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (this.marqueeDisplayPayload && this.marqueeDisplayPayload.type === 'self') {
|
|
|
+ this.marqueeDisplayPayload = Object.assign({}, fresh)
|
|
|
+ }
|
|
|
+ if (this.marqueeIncomingPayload && this.marqueeIncomingPayload.type === 'self') {
|
|
|
+ this.marqueeIncomingPayload = Object.assign({}, fresh)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ _startSelfMarqueeClockIfNeeded() {
|
|
|
+ if (this._selfMarqueeClockTimer != null) return
|
|
|
+ if (!this.hasRecentSelfPurchase()) return
|
|
|
+ this._selfMarqueeClockTimer = setInterval(() => {
|
|
|
+ if (!this._fakeMarqueeStarted || !this.hasRecentSelfPurchase()) {
|
|
|
+ this._stopSelfMarqueeClock()
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.refreshSelfPurchaseMarqueeDisplayedTiming()
|
|
|
+ }, 10000)
|
|
|
+ },
|
|
|
+ _stopSelfMarqueeClock() {
|
|
|
+ if (this._selfMarqueeClockTimer != null) {
|
|
|
+ clearInterval(this._selfMarqueeClockTimer)
|
|
|
+ this._selfMarqueeClockTimer = null
|
|
|
+ }
|
|
|
+ },
|
|
|
+ /** 进入三联布局时立即补足 marqueeTriplePayloads,否则 v-if 会因 length 为 0 仍走单条分支直到下一轮定时 tick */
|
|
|
+ syncTripleMarqueeImmediate() {
|
|
|
+ if (!this.fakeMarqueeEligible || !this._fakeMarqueeStarted || !this.isTripleMarqueeMode) return
|
|
|
+ const rows = this.buildTripleMarqueePayloads()
|
|
|
+ if (!rows.length) return
|
|
|
+ this.setTripleMarqueeDisplayWithAnim(rows)
|
|
|
+ if (rows.some(item => item && item.type === 'self')) {
|
|
|
+ this.pendingSelfMarqueeFirst = false
|
|
|
+ this._markSelfPurchaseMarqueeConsumed()
|
|
|
+ }
|
|
|
+ if (rows[0]) {
|
|
|
+ this.marqueeDisplayPayload = rows[0]
|
|
|
+ this.marqueeDisplaySelf = rows[0].type === 'self'
|
|
|
+ }
|
|
|
},
|
|
|
setTripleMarqueeDisplayWithAnim(rows) {
|
|
|
if (!rows || !rows.length) return
|
|
|
@@ -1179,6 +1292,10 @@
|
|
|
}, delay)
|
|
|
},
|
|
|
stopFakeMarqueeLoop() {
|
|
|
+ if (this._marqueeStartDebounceTimer) {
|
|
|
+ clearTimeout(this._marqueeStartDebounceTimer)
|
|
|
+ this._marqueeStartDebounceTimer = null
|
|
|
+ }
|
|
|
if (this._fakeMarqueeTimer) {
|
|
|
clearTimeout(this._fakeMarqueeTimer)
|
|
|
this._fakeMarqueeTimer = null
|
|
|
@@ -1193,11 +1310,17 @@
|
|
|
}
|
|
|
this._fakeMarqueeStarted = false
|
|
|
this.marqueeSwitching = false
|
|
|
+ // 重要:清空非三联跑马灯展示 payload,避免下一次门禁打开前渲染旧内容
|
|
|
+ this.marqueeDisplayPayload = null
|
|
|
+ this.marqueeDisplaySelf = false
|
|
|
+ this.marqueeCurrentText = ''
|
|
|
+ this.marqueeSelfHighlight = false
|
|
|
this.marqueeIncomingPayload = null
|
|
|
this.marqueeIncomingSelf = false
|
|
|
this.marqueeTriplePayloads = []
|
|
|
this.marqueeTripleIncomingPayloads = []
|
|
|
this.marqueeTripleSwitching = false
|
|
|
+ this._stopSelfMarqueeClock()
|
|
|
},
|
|
|
goRate(index){
|
|
|
this.aindex = index
|
|
|
@@ -1758,6 +1881,7 @@
|
|
|
this.displayProductList = []
|
|
|
this.cardPopup = false
|
|
|
this.currentCardItem = null
|
|
|
+ this._syncFakeMarqueeIfEligibleChanged()
|
|
|
return
|
|
|
}
|
|
|
// 按“上架时间”倒序排序,保证后上架商品展示在列表最前
|
|
|
@@ -1817,6 +1941,7 @@
|
|
|
this.cardPopup = !!activeCard && this.dismissedCardKey !== activeCardKey
|
|
|
//this.getVideoContainerHeight()
|
|
|
this.currentCardItem = activeCard
|
|
|
+ this._syncFakeMarqueeIfEligibleChanged()
|
|
|
},
|
|
|
closeCardPopup() {
|
|
|
if (this.currentCardItem) {
|
|
|
@@ -2051,6 +2176,11 @@
|
|
|
this.updateTime();
|
|
|
// 初始扫描商品栏展示(根据上架/下架时间)
|
|
|
this.updateProductAndCardDisplay(this.playTime ?? this.playDuration ?? 0);
|
|
|
+ // 商品栏扫描完成后再允许虚拟跑马灯启动(延后到下一轮渲染,避免一帧闪现)
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.marqueeDataReady = true
|
|
|
+ this._syncFakeMarqueeIfEligibleChanged()
|
|
|
+ })
|
|
|
if (res.data.courseVideoDetails.questionBankList.length == 0) {
|
|
|
this.isquestion = true
|
|
|
} else {
|
|
|
@@ -2713,11 +2843,13 @@
|
|
|
}
|
|
|
.vip-order-cover-wrap {
|
|
|
position: fixed;
|
|
|
- left: 6px;
|
|
|
- top: 10px;
|
|
|
- height: 40px;
|
|
|
- z-index: 99999999;
|
|
|
- overflow: hidden;
|
|
|
+ left: 10px;
|
|
|
+ bottom:40px;
|
|
|
+ height: 26px;
|
|
|
+ z-index: 999;
|
|
|
+ /* 容器按内容宽度自适应 */
|
|
|
+ display: inline-block;
|
|
|
+ overflow: visible;
|
|
|
pointer-events: none;
|
|
|
width: 200px;
|
|
|
}
|
|
|
@@ -2726,9 +2858,12 @@
|
|
|
//width: 240px;
|
|
|
}
|
|
|
.vip-order-cover-triple-panel {
|
|
|
+ display: flex;
|
|
|
+ align-items: flex-start;
|
|
|
+ flex-direction: column;
|
|
|
position: absolute;
|
|
|
left: 0;
|
|
|
- right: 0;
|
|
|
+ right: auto;
|
|
|
top: 0;
|
|
|
}
|
|
|
.vip-order-cover-triple-current {
|
|
|
@@ -2740,24 +2875,27 @@
|
|
|
.vip-order-cover-item {
|
|
|
position: absolute;
|
|
|
left: 0;
|
|
|
- right: 0;
|
|
|
+ /* 不再撑满整块固定宽度,让背景宽度随内容变化 */
|
|
|
+ right: auto;
|
|
|
top: 0;
|
|
|
- padding: 6px 8px;
|
|
|
- border-radius: 50px;
|
|
|
- background: rgba(0, 0, 0, 0.45);
|
|
|
+ display: inline-flex;
|
|
|
+ align-items: center;
|
|
|
+ background: rgba(0,0,0,0.35);
|
|
|
+ border-radius: 26rpx;
|
|
|
text-align: center;
|
|
|
//border: 1px solid rgba(255, 12, 77, 0.2);
|
|
|
font-family: PingFangSC, PingFang SC;
|
|
|
font-size: 16px;
|
|
|
- line-height: 20px;
|
|
|
+ height: 26px;
|
|
|
+ line-height: 26px;
|
|
|
color: #fff;
|
|
|
- font-weight: 500;
|
|
|
+ font-weight: 400;
|
|
|
box-sizing: border-box;
|
|
|
}
|
|
|
.vip-order-cover-triple-item {
|
|
|
position: relative;
|
|
|
top: auto;
|
|
|
- margin-bottom: 6px;
|
|
|
+ margin-bottom: 8px;
|
|
|
}
|
|
|
.vip-order-cover-triple-item:last-child {
|
|
|
margin-bottom: 0;
|
|
|
@@ -2797,8 +2935,11 @@
|
|
|
align-items: center;
|
|
|
flex-wrap: nowrap;
|
|
|
white-space: nowrap;
|
|
|
- overflow: hidden;
|
|
|
- justify-content: center;
|
|
|
+ overflow: visible;
|
|
|
+ justify-content: flex-start;
|
|
|
+ height: 26px;
|
|
|
+ line-height: 26px;
|
|
|
+ padding:0 8px;
|
|
|
}
|
|
|
.vip-order-seg {
|
|
|
display: inline-block;
|
|
|
@@ -2808,15 +2949,16 @@
|
|
|
//font-weight: 600;
|
|
|
}
|
|
|
.vip-order-seg-time {
|
|
|
- font-size: 14px;
|
|
|
- margin-left: 4px;
|
|
|
+ // font-size: 14px;
|
|
|
+ margin-left: 6px;
|
|
|
}
|
|
|
.vip-order-seg-suffix {
|
|
|
color: #fff;
|
|
|
- margin-left: 2px;
|
|
|
+ // margin-left: 2px;
|
|
|
}
|
|
|
.vip-order-cover-self {
|
|
|
- background: rgba(180, 83, 9, 0.45);
|
|
|
+ // width: 180px !important;
|
|
|
+ background: rgba(230,0,26,0.5);
|
|
|
// border: 1px solid #FFB020;
|
|
|
color: #fff;
|
|
|
}
|
|
|
@@ -2826,11 +2968,10 @@
|
|
|
}
|
|
|
.vip-order-cover-self .vip-order-seg-time {
|
|
|
color: #fff;
|
|
|
- margin-left: 4px;
|
|
|
+ margin-left: 6px;
|
|
|
}
|
|
|
.vip-order-cover-self .vip-order-seg-suffix {
|
|
|
color: #fff;
|
|
|
- margin-left: 4px;
|
|
|
}
|
|
|
.vip-order-enter {
|
|
|
animation: vip-order-enter-up 0.46s ease-out forwards;
|