@bi-nova/ui-weapp 1.1.3 → 1.2.0-beta.202608171048

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,7 +3,7 @@
3
3
  * @Author wutao
4
4
  * @Date 2026-04-10
5
5
  * @LastEditors wutao
6
- * @LastEditTime 2026-05-13
6
+ * @LastEditTime 2026-08-14 16:14:20
7
7
  */
8
8
  const {
9
9
  navigateCustomAd
@@ -13,6 +13,7 @@ Component({
13
13
  properties: {
14
14
  unitId: { type: String, value: '' },
15
15
  customAd: { type: Object, value: null },
16
+ priority: { type: String, value: 'wechat-first' },
16
17
  show: { type: Boolean, value: true },
17
18
  zIndex: { type: Number, value: 999 },
18
19
  pictureInPicture: { type: Boolean, value: false },
@@ -27,13 +28,14 @@ Component({
27
28
  mediaUrl: '',
28
29
  posterUrl: '',
29
30
  isImage: true,
30
- adSpec: 2,
31
+ mediaFitMode: 'contain',
31
32
  hasCustomMedia: false,
32
33
  customLoaded: false,
34
+ isFullScreen: false,
33
35
  skipStyle: '',
36
+ disclosureStyle: '',
37
+ combinedControlStyle: '',
34
38
  adBadgeText: '广告',
35
- contentStyle: '',
36
- badgeStyle: '',
37
39
  pipAnimating: false,
38
40
  nativeSplashActive: false
39
41
  },
@@ -42,8 +44,7 @@ Component({
42
44
  /** 系统开屏状态重试次数 */
43
45
  this.checkSplashNum = 0
44
46
  this.initSkipStyle()
45
- this.initSafeAreaStyle()
46
- this.syncAdSource(this.properties.unitId, this.properties.customAd)
47
+ this.syncAdSource(this.properties.unitId, this.properties.customAd, this.properties.priority)
47
48
  this.syncVisible(this.properties.show)
48
49
  },
49
50
  detached() {
@@ -51,8 +52,8 @@ Component({
51
52
  }
52
53
  },
53
54
  observers: {
54
- 'unitId, customAd'(nextUnitId, nextCustomAd) {
55
- this.syncAdSource(nextUnitId, nextCustomAd)
55
+ 'unitId, customAd, priority'(nextUnitId, nextCustomAd, nextPriority) {
56
+ this.syncAdSource(nextUnitId, nextCustomAd, nextPriority)
56
57
  this.syncVisible(this.properties.show)
57
58
  },
58
59
  show(nextShow) {
@@ -82,9 +83,17 @@ Component({
82
83
  * @returns {{provider: 'wechat' | 'custom', type: 'splash'}}
83
84
  */
84
85
  createEventDetail(provider) {
86
+ const customAd = provider === 'custom' && this.properties.customAd || null
87
+
85
88
  return {
86
89
  provider,
87
- type: 'splash'
90
+ type: 'splash',
91
+ ...(customAd ? {
92
+ configId: customAd.configId,
93
+ placementId: customAd.placementId,
94
+ configName: customAd.configName,
95
+ advertPlatform: customAd.advertPlatform
96
+ } : {})
88
97
  }
89
98
  },
90
99
 
@@ -125,21 +134,22 @@ Component({
125
134
  * 同步广告来源与媒体数据
126
135
  * @param {string} unitId 微信广告位 ID
127
136
  * @param {Record<string, any> | null} customAd 自定义广告数据
137
+ * @param {string} priority 广告展示优先级
128
138
  * @returns {void}
129
139
  */
130
- syncAdSource(unitId, customAd) {
131
- /** 是否为微信原生广告 */
132
- const isWechatAd = Boolean(unitId)
140
+ syncAdSource(unitId, customAd, priority) {
133
141
  /** 主媒体地址 */
134
142
  const mediaUrl = this.getMediaUrl(customAd)
135
143
  /** 视频封面地址 */
136
144
  const posterUrl = this.getPosterUrl(customAd, mediaUrl)
137
145
  /** 是否存在自定义媒体 */
138
146
  const hasCustomMedia = Boolean(mediaUrl)
147
+ /** 是否优先展示微信广告 */
148
+ const isWechatAd = this.shouldStartWechatAd(unitId, hasCustomMedia, priority)
139
149
  /** 是否为图片媒体 */
140
150
  const isImage = this.getIsImage(customAd, mediaUrl)
141
- /** 广告规格,1 横版,2 竖版 */
142
- const adSpec = this.getAdSpec(customAd)
151
+ /** 自定义素材填充模式 */
152
+ const mediaFitMode = this.getMediaFitMode(customAd)
143
153
  /** 广告角标文案 */
144
154
  const adBadgeText = this.getAdBadgeText(customAd)
145
155
 
@@ -149,11 +159,54 @@ Component({
149
159
  posterUrl,
150
160
  hasCustomMedia,
151
161
  isImage,
152
- adSpec,
162
+ mediaFitMode,
153
163
  adBadgeText
154
164
  })
155
165
  },
156
166
 
167
+ /**
168
+ * 根据广告配置和优先级判断是否首发微信广告
169
+ * @param {string} unitId 微信广告位 ID
170
+ * @param {boolean} hasCustomMedia 是否存在自研素材
171
+ * @param {string} priority 广告展示优先级
172
+ * @returns {boolean}
173
+ */
174
+ shouldStartWechatAd(unitId, hasCustomMedia, priority) {
175
+ if (!unitId) return false
176
+ if (!hasCustomMedia) return true
177
+ return !['custom-first', 'custom-only'].includes(priority)
178
+ },
179
+
180
+ /**
181
+ * 重置当前展示周期的广告来源失败记录
182
+ * @returns {void}
183
+ */
184
+ resetProviderFailures() {
185
+ this.failedProviders = {
186
+ wechat: false,
187
+ custom: false
188
+ }
189
+ },
190
+
191
+ /**
192
+ * 记录指定广告来源加载失败
193
+ * @param {'wechat' | 'custom'} provider 广告来源
194
+ * @returns {void}
195
+ */
196
+ markProviderFailed(provider) {
197
+ if (!this.failedProviders) this.resetProviderFailures()
198
+ this.failedProviders[provider] = true
199
+ },
200
+
201
+ /**
202
+ * 判断指定广告来源是否已经失败
203
+ * @param {'wechat' | 'custom'} provider 广告来源
204
+ * @returns {boolean}
205
+ */
206
+ hasProviderFailed(provider) {
207
+ return Boolean(this.failedProviders && this.failedProviders[provider])
208
+ },
209
+
157
210
  /**
158
211
  * 同步组件显隐状态
159
212
  * @param {boolean} nextShow 是否展示
@@ -162,6 +215,7 @@ Component({
162
215
  syncVisible(nextShow) {
163
216
  if (!nextShow) {
164
217
  this.clearAllTimers()
218
+ this.resetProviderFailures()
165
219
  this.setData({
166
220
  visible: false,
167
221
  showPiP: false,
@@ -173,6 +227,7 @@ Component({
173
227
  return
174
228
  }
175
229
 
230
+ this.resetProviderFailures()
176
231
  this.checkSplashNum = 0
177
232
  this.resetVisibleState()
178
233
  this.checkSplashAdStatus()
@@ -201,7 +256,7 @@ Component({
201
256
  this.startWechatCountDownIfNeeded()
202
257
  })
203
258
 
204
- if (visible && !this.properties.unitId && this.data.hasCustomMedia) {
259
+ if (visible && !this.data.isWechatAd && this.data.hasCustomMedia) {
205
260
  this.startCustomLoadTimeout()
206
261
  }
207
262
  },
@@ -225,7 +280,13 @@ Component({
225
280
  */
226
281
  getMediaUrl(customAd) {
227
282
  if (!customAd) return ''
228
- return customAd.image || customAd.video || ''
283
+
284
+ const mediaType = String(customAd.mediaType || '').trim().toLowerCase()
285
+
286
+ if (mediaType === 'video') return customAd.video || ''
287
+ if (mediaType === 'image') return customAd.image || ''
288
+
289
+ return customAd.video || customAd.image || ''
229
290
  },
230
291
 
231
292
  /**
@@ -247,33 +308,25 @@ Component({
247
308
  */
248
309
  getIsImage(customAd, mediaUrl) {
249
310
  if (!customAd) return true
311
+
312
+ const mediaType = String(customAd.mediaType || '').trim().toLowerCase()
313
+
314
+ if (mediaType === 'video') return false
315
+ if (mediaType === 'image') return true
250
316
  if (customAd.video) return false
251
317
  if (customAd.image) return true
252
318
  return /\.(jpg|jpeg|png|gif|bmp|webp|svg|ico)$/i.test(String(mediaUrl || '').trim())
253
319
  },
254
320
 
255
321
  /**
256
- * 获取广告规格
322
+ * 获取自定义素材填充模式
257
323
  * @param {Record<string, any> | null} customAd 自定义广告数据
258
- * @returns {number}
324
+ * @returns {'contain' | 'cover'}
259
325
  */
260
- getAdSpec(customAd) {
261
- if (!customAd) return 2
262
-
263
- /** 显式传入的广告规格 */
264
- const adSpec = Number(customAd.adSpec || customAd.spec || 0)
265
- if (adSpec === 1 || adSpec === 2) return adSpec
266
-
267
- /** 媒体宽度 */
268
- const width = Number(customAd.videoWidth || customAd.width || 0)
269
- /** 媒体高度 */
270
- const height = Number(customAd.videoHeight || customAd.height || 0)
271
-
272
- if (width > 0 && height > 0) {
273
- return width > height ? 1 : 2
274
- }
275
-
276
- return customAd.video ? 1 : 2
326
+ getMediaFitMode(customAd) {
327
+ return customAd && String(customAd.fitMode || '').trim().toLowerCase() === 'cover'
328
+ ? 'cover'
329
+ : 'contain'
277
330
  },
278
331
 
279
332
  /**
@@ -287,7 +340,7 @@ Component({
287
340
  },
288
341
 
289
342
  /**
290
- * 初始化跳过按钮位置样式
343
+ * 初始化开屏顶部控件位置样式
291
344
  * @returns {void}
292
345
  */
293
346
  initSkipStyle() {
@@ -296,7 +349,7 @@ Component({
296
349
  typeof wx.getMenuButtonBoundingClientRect === 'function'
297
350
  ? wx.getMenuButtonBoundingClientRect()
298
351
  : {}
299
- /** @type {{windowWidth?: number, windowHeight?: number, screenHeight?: number}} */
352
+ /** @type {{windowWidth?: number, windowHeight?: number, screenHeight?: number, safeArea?: {left?: number}}} */
300
353
  const windowInfo =
301
354
  typeof wx.getWindowInfo === 'function'
302
355
  ? wx.getWindowInfo()
@@ -305,7 +358,11 @@ Component({
305
358
  : {}
306
359
 
307
360
  /** 是否可按原生菜单胶囊对齐 */
308
- const isFullScreen = windowInfo.windowHeight === windowInfo.screenHeight
361
+ const isFullScreen = Boolean(
362
+ windowInfo.windowHeight
363
+ && windowInfo.screenHeight
364
+ && windowInfo.windowHeight === windowInfo.screenHeight
365
+ )
309
366
  /** 默认顶部距离 */
310
367
  const defaultTop = 16
311
368
  /** 默认右侧距离 */
@@ -320,46 +377,32 @@ Component({
320
377
  const height = isFullScreen && menuButtonRect.height ? menuButtonRect.height : defaultHeight
321
378
  /** 跳过按钮水平定位样式 */
322
379
  const horizontalStyle = isFullScreen ? `left:${defaultLeft}px` : `right:${defaultRight}px`
380
+ /** 广告标识顶部偏移 */
381
+ const disclosureTop = top
382
+ /** 广告标识左侧偏移,兼容安全区域可能存在的水平边距 */
383
+ const disclosureLeft = Math.max(defaultLeft, Number(windowInfo.safeArea && windowInfo.safeArea.left || 0) + defaultLeft)
323
384
 
324
385
  this.setData({
386
+ isFullScreen,
325
387
  skipStyle: [
326
388
  `top:${top}px`,
327
389
  horizontalStyle,
328
390
  `height:${height}px`,
329
391
  `line-height:${height}px`,
330
392
  `border-radius:${Math.round(height / 2)}px`
393
+ ].join(';'),
394
+ disclosureStyle: [
395
+ `top:${disclosureTop}px`,
396
+ `left:${disclosureLeft}px`
397
+ ].join(';'),
398
+ combinedControlStyle: [
399
+ `top:${top}px`,
400
+ `left:${disclosureLeft}px`,
401
+ `height:${height}px`
331
402
  ].join(';')
332
403
  })
333
404
  },
334
405
 
335
- /**
336
- * 初始化安全区相关样式
337
- * @returns {void}
338
- */
339
- initSafeAreaStyle() {
340
- /** @type {{safeArea?: {bottom?: number}, screenHeight?: number, windowHeight?: number}} */
341
- const systemInfo =
342
- typeof wx.getWindowInfo === 'function'
343
- ? wx.getWindowInfo()
344
- : typeof wx.getSystemInfoSync === 'function'
345
- ? wx.getSystemInfoSync()
346
- : {}
347
- /** 底部安全区高度 */
348
- const safeBottom = Math.max(
349
- 0,
350
- Number(systemInfo.screenHeight || 0) - Number(systemInfo.safeArea && systemInfo.safeArea.bottom || systemInfo.windowHeight || 0)
351
- )
352
- /** 内容区底部间距 */
353
- const contentBottom = safeBottom > 0 ? safeBottom + 42 : 84
354
- /** 角标底部间距 */
355
- const badgeBottom = safeBottom > 0 ? safeBottom + 88 : 130
356
-
357
- this.setData({
358
- contentStyle: `bottom:${contentBottom}px;`,
359
- badgeStyle: `bottom:${badgeBottom}px;`
360
- })
361
- },
362
-
363
406
  /**
364
407
  * 启动广告倒计时
365
408
  * @returns {void}
@@ -473,11 +516,68 @@ Component({
473
516
  */
474
517
  startWechatCountDownIfNeeded() {
475
518
  // 微信原生广告 load 回调在重新编译、缓存恢复等场景下可能不稳定;只要原生广告容器已展示,就允许兜底启动倒计时。
476
- if (!this.properties.show || !this.properties.unitId || !this.data.visible || this.data.showPiP) return
519
+ if (!this.properties.show || !this.properties.unitId || !this.data.isWechatAd || !this.data.visible || this.data.showPiP) return
477
520
 
478
521
  this.startCountDown()
479
522
  },
480
523
 
524
+ /**
525
+ * 切换当前展示的广告来源
526
+ * @param {'wechat' | 'custom'} provider 目标广告来源
527
+ * @returns {void}
528
+ */
529
+ switchProvider(provider) {
530
+ const isWechatAd = provider === 'wechat'
531
+
532
+ this.clearAllTimers()
533
+ this.setData({
534
+ isWechatAd,
535
+ visible: true,
536
+ showPiP: false,
537
+ remainingSeconds: this.getJumpSeconds(),
538
+ customLoaded: false,
539
+ pipAnimating: false
540
+ }, () => {
541
+ if (isWechatAd) {
542
+ this.startWechatCountDownIfNeeded()
543
+ return
544
+ }
545
+
546
+ this.startCustomLoadTimeout()
547
+ })
548
+ },
549
+
550
+ /**
551
+ * 所有可用广告来源均失败后结束当前开屏流程
552
+ * @param {'wechat' | 'custom'} provider 最后失败的广告来源
553
+ * @param {Record<string, any>} errorDetail 错误详情
554
+ * @returns {void}
555
+ */
556
+ finishProviderFailure(provider, errorDetail) {
557
+ const hasWechatAd = Boolean(this.properties.unitId)
558
+ const hasCustomAd = Boolean(this.data.hasCustomMedia)
559
+ const reason = hasWechatAd && hasCustomAd
560
+ ? 'allProvidersFailed'
561
+ : provider === 'wechat'
562
+ ? 'wechatAdLoadFail'
563
+ : 'customMediaLoadFail'
564
+
565
+ this.clearAllTimers()
566
+ this.setData({
567
+ visible: false,
568
+ showPiP: false,
569
+ remainingSeconds: 0,
570
+ customLoaded: false,
571
+ pipAnimating: false
572
+ })
573
+ this.triggerEvent('close', {
574
+ provider,
575
+ type: 'splash',
576
+ reason,
577
+ error: errorDetail
578
+ })
579
+ },
580
+
481
581
  /**
482
582
  * 设置开屏广告可见状态并按需启动微信原生广告倒计时
483
583
  * @param {boolean} visible 是否展示开屏广告
@@ -554,6 +654,8 @@ Component({
554
654
  * @returns {void}
555
655
  */
556
656
  handleLoad(event) {
657
+ if (!this.data.isWechatAd) return
658
+
557
659
  this.startCountDown()
558
660
  this.triggerEvent('load', this.resolveEventDetail('wechat', event))
559
661
  },
@@ -564,6 +666,8 @@ Component({
564
666
  * @returns {void}
565
667
  */
566
668
  handleError(event) {
669
+ if (!this.data.isWechatAd) return
670
+
567
671
  const rawDetail = event && event.detail && typeof event.detail === 'object' ? event.detail : {}
568
672
  const errorDetail = this.resolveEventDetail('wechat', event, {
569
673
  errCode: 'BI_SPLASH_WECHAT_AD_LOAD_FAIL',
@@ -584,34 +688,14 @@ Component({
584
688
  fallbackFromWechatAd(errorDetail) {
585
689
  if (!this.data.isWechatAd) return
586
690
 
587
- this.clearAllTimers()
691
+ this.markProviderFailed('wechat')
588
692
 
589
- if (this.data.hasCustomMedia) {
590
- this.setData({
591
- isWechatAd: false,
592
- visible: true,
593
- showPiP: false,
594
- remainingSeconds: this.getJumpSeconds(),
595
- customLoaded: false,
596
- pipAnimating: false
597
- })
598
- this.startCustomLoadTimeout()
693
+ if (this.data.hasCustomMedia && !this.hasProviderFailed('custom')) {
694
+ this.switchProvider('custom')
599
695
  return
600
696
  }
601
697
 
602
- this.setData({
603
- visible: false,
604
- showPiP: false,
605
- remainingSeconds: 0,
606
- customLoaded: false,
607
- pipAnimating: false
608
- })
609
- this.triggerEvent('close', {
610
- provider: 'wechat',
611
- type: 'splash',
612
- reason: 'wechatAdLoadFail',
613
- error: errorDetail
614
- })
698
+ this.finishProviderFailure('wechat', errorDetail)
615
699
  },
616
700
 
617
701
  /**
@@ -619,7 +703,7 @@ Component({
619
703
  * @returns {void}
620
704
  */
621
705
  handleCustomLoad() {
622
- if (this.data.customLoaded) return
706
+ if (this.data.isWechatAd || this.data.customLoaded) return
623
707
 
624
708
  this.clearCustomLoadTimeout()
625
709
  this.setData({ customLoaded: true })
@@ -635,8 +719,12 @@ Component({
635
719
  if (this.data.customLoaded) return
636
720
 
637
721
  this.handleCustomMediaFail(null, {
722
+ errorType: 'CUSTOM_MEDIA_LOAD_TIMEOUT',
638
723
  errCode: 'BI_SPLASH_CUSTOM_MEDIA_LOAD_TIMEOUT',
639
- errMsg: '开屏自定义广告素材加载超时'
724
+ errMsg: '开屏自定义广告素材加载超时',
725
+ mediaType: this.data.isImage ? 'image' : 'video',
726
+ rawErrCode: undefined,
727
+ rawErrMsg: undefined
640
728
  })
641
729
  },
642
730
 
@@ -647,15 +735,19 @@ Component({
647
735
  * @returns {void}
648
736
  */
649
737
  handleCustomMediaFail(event, detail) {
650
- this.clearAllTimers()
651
- this.setData({
652
- visible: false,
653
- showPiP: false,
654
- remainingSeconds: 0,
655
- customLoaded: false,
656
- pipAnimating: false
657
- })
658
- this.triggerEvent('error', this.resolveEventDetail('custom', event, detail))
738
+ if (this.data.isWechatAd) return
739
+
740
+ const errorDetail = this.resolveEventDetail('custom', event, detail)
741
+
742
+ this.triggerEvent('error', errorDetail)
743
+ this.markProviderFailed('custom')
744
+
745
+ if (this.properties.unitId && !this.hasProviderFailed('wechat')) {
746
+ this.switchProvider('wechat')
747
+ return
748
+ }
749
+
750
+ this.finishProviderFailure('custom', errorDetail)
659
751
  },
660
752
 
661
753
  /**
@@ -664,9 +756,20 @@ Component({
664
756
  * @returns {void}
665
757
  */
666
758
  handleCustomMediaError(event) {
759
+ /** @type {Record<string, any>} 微信媒体组件返回的原始错误信息 */
760
+ const rawDetail = event && event.detail && typeof event.detail === 'object'
761
+ ? event.detail
762
+ : event && typeof event === 'object'
763
+ ? event
764
+ : {}
765
+
667
766
  this.handleCustomMediaFail(event, {
767
+ errorType: 'CUSTOM_MEDIA_LOAD_FAIL',
668
768
  errCode: 'BI_SPLASH_CUSTOM_MEDIA_LOAD_FAIL',
669
- errMsg: '开屏自定义广告素材加载失败'
769
+ errMsg: '开屏自定义广告素材加载失败',
770
+ mediaType: this.data.isImage ? 'image' : 'video',
771
+ rawErrCode: rawDetail.errCode,
772
+ rawErrMsg: rawDetail.errMsg
670
773
  })
671
774
  },
672
775
 
@@ -18,30 +18,25 @@
18
18
  </view>
19
19
 
20
20
  <!-- 自定义广告 -->
21
- <view wx:elif="{{mediaUrl}}" class="bi-splash-ad__popup">
21
+ <view wx:elif="{{mediaUrl}}" class="bi-splash-ad__popup bi-splash-ad__custom">
22
22
  <view class="bi-splash-ad__media-shell" bindtap="handleAction">
23
23
  <image
24
24
  wx:if="{{isImage}}"
25
- class="bi-splash-ad__media bi-splash-ad__media--background"
25
+ class="bi-splash-ad__media"
26
26
  src="{{mediaUrl}}"
27
- mode="aspectFill"
27
+ mode="{{mediaFitMode === 'cover' ? 'aspectFill' : 'aspectFit'}}"
28
28
  bindload="handleCustomLoad"
29
29
  binderror="handleCustomMediaError"
30
30
  />
31
31
  <block wx:else>
32
- <image
33
- class="bi-splash-ad__media bi-splash-ad__media--background"
34
- src="{{posterUrl}}"
35
- mode="aspectFill"
36
- />
37
32
  <video
38
- class="bi-splash-ad__video {{adSpec === 1 ? 'bi-splash-ad__video--landscape' : ''}}"
33
+ class="bi-splash-ad__video"
39
34
  src="{{mediaUrl}}"
40
35
  poster="{{posterUrl}}"
41
36
  autoplay="{{true}}"
42
37
  muted="{{customAd.muted !== false}}"
43
38
  loop="{{true}}"
44
- object-fit="cover"
39
+ object-fit="{{mediaFitMode}}"
45
40
  show-center-play-btn="{{false}}"
46
41
  show-play-btn="{{false}}"
47
42
  controls="{{false}}"
@@ -52,13 +47,17 @@
52
47
 
53
48
  <view wx:if="{{showPiP}}" class="bi-splash-ad__pip-mask"></view>
54
49
 
55
- <view wx:if="{{!showPiP}}" class="bi-splash-ad__badge" style="{{badgeStyle}}">{{adBadgeText}}</view>
56
-
57
- <view wx:if="{{customAd && (customAd.title || (!showPiP && (customAd.description || customAd.buttonText)))}}" class="bi-splash-ad__content" style="{{contentStyle}}">
58
- <text wx:if="{{customAd.title}}" class="bi-splash-ad__title">{{customAd.title}}</text>
59
- <text wx:if="{{!showPiP && customAd.description}}" class="bi-splash-ad__description">{{customAd.description}}</text>
60
- <button wx:if="{{!showPiP && customAd.buttonText}}" class="bi-splash-ad__action">{{customAd.buttonText}}</button>
50
+ <view wx:if="{{!showPiP && !isFullScreen}}" class="bi-splash-ad__disclosure" style="{{disclosureStyle}}">
51
+ <text>{{adBadgeText}}</text>
52
+ <view class="bi-splash-ad__disclosure-arrow"></view>
61
53
  </view>
54
+
55
+ <image
56
+ wx:if="{{!showPiP && customAd.bottomImage}}"
57
+ class="bi-splash-ad__bottom-image"
58
+ src="{{customAd.bottomImage}}"
59
+ mode="widthFix"
60
+ />
62
61
  </view>
63
62
  </view>
64
63
 
@@ -66,7 +65,23 @@
66
65
  <view class="bi-splash-ad__pip-close-text">关闭</view>
67
66
  </view>
68
67
 
69
- <view wx:if="{{!showPiP}}" class="bi-splash-ad__skip" style="{{skipStyle}}" bindtap="handleSkip">
68
+ <view
69
+ wx:if="{{!showPiP && isFullScreen && !isWechatAd}}"
70
+ class="bi-splash-ad__combined-control"
71
+ style="{{combinedControlStyle}}"
72
+ >
73
+ <view class="bi-splash-ad__combined-capsule">
74
+ <view class="bi-splash-ad__combined-disclosure">
75
+ <text>{{adBadgeText}}</text>
76
+ <view class="bi-splash-ad__disclosure-arrow"></view>
77
+ </view>
78
+ <view class="bi-splash-ad__combined-divider"></view>
79
+ <view class="bi-splash-ad__combined-skip" catchtap="handleSkip">跳过</view>
80
+ </view>
81
+ <text class="bi-splash-ad__combined-countdown">{{remainingSeconds}} 秒</text>
82
+ </view>
83
+
84
+ <view wx:elif="{{!showPiP}}" class="bi-splash-ad__skip" style="{{skipStyle}}" bindtap="handleSkip">
70
85
  <text>{{remainingSeconds}}s</text>
71
86
  <view class="bi-splash-ad__skip-divider"></view>
72
87
  <text class="bi-splash-ad__skip-text">跳过</text>