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

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bi-nova/ui-weapp",
3
- "version": "1.1.3",
3
+ "version": "1.2.0-beta.202608131817",
4
4
  "description": "BI Nova SDK WeChat Mini Program Components",
5
5
  "miniprogram": "src",
6
6
  "license": "ISC",
package/src/ad/README.md CHANGED
@@ -73,6 +73,10 @@ yarn add @bi-nova/core @bi-nova/services @bi-nova/ui-weapp
73
73
 
74
74
  广告位配置由我方维护,通常包含实际投放渠道、广告素材、展示开关等信息。业务方一般不需要关心底层配置结构,只需要确保传入的 `ad-id` 与投放场景一致。
75
75
 
76
+ ### 小程序合法域名
77
+
78
+ 请在微信公众平台将 `https://nad.ehuoke.com` 配置为小程序的 `request 合法域名`。如果未配置,广告位配置请求会被微信拦截,组件无法获取可展示的广告内容。
79
+
76
80
  使用 `ad-id` 前,请确认 SDK 已完成以下初始化:
77
81
 
78
82
  1. 通过 `createNova` 创建 SDK 实例,并在微信小程序环境开启 `autoEnv: true`。
@@ -161,6 +165,8 @@ getApp().globalData.biNova.clearToken()
161
165
 
162
166
  开屏广告支持微信原生广告、自定义图片广告、自定义视频广告,并提供倒计时跳过和画中画能力。
163
167
 
168
+ 广告来源、展示顺序和加载失败后的降级均由广告位配置与组件自动处理。业务方不需要判断广告平台或实现兜底逻辑,只需通过 `load`、`error`、`close` 等事件接收最终状态。
169
+
164
170
  建议承载开屏广告的页面在页面配置中设置 `"navigationStyle": "custom"`,隐藏默认导航栏后开屏广告展示更完整,整体视觉效果更好。
165
171
 
166
172
  ```json
@@ -171,54 +177,6 @@ getApp().globalData.biNova.clearToken()
171
177
 
172
178
  `ad-id` 需要使用开屏类型广告位,具体广告位 ID 请向我方获取。
173
179
 
174
- ## 广告素材能力
175
-
176
- 以下字段由广告位配置生成,业务方通常不需要在页面中直接传入。这里仅用于说明广告素材支持的配置能力,便于和我方确认广告位需求。
177
-
178
- ### 通用字段
179
-
180
- | 字段 | 类型 | 说明 |
181
- | --- | --- | --- |
182
- | `image` / `imageUrl` | `string` | 图片素材地址。Banner 广告和开屏图片广告使用。 |
183
- | `title` | `string` | 广告标题。 |
184
- | `description` | `string` | 广告描述。 |
185
- | `buttonText` | `string` | 操作按钮文案。 |
186
- | `badgeText` / `adLabel` | `string` | 广告角标文案,默认 `广告`。 |
187
- | `loadTimeout` / `timeout` | `number` | 自定义素材加载超时时间,单位毫秒,最小值为 `1000`,默认 `5000`。 |
188
-
189
- ### 开屏扩展字段
190
-
191
- | 字段 | 类型 | 说明 |
192
- | --- | --- | --- |
193
- | `video` / `videoUrl` | `string` | 视频素材地址。存在时开屏广告按视频广告渲染。 |
194
- | `poster` | `string` | 视频封面地址。未传时优先使用 `image`。 |
195
- | `muted` | `boolean` | 视频是否静音。默认静音,传 `false` 可开启声音。 |
196
- | `jumpSeconds` | `number` | 当前广告独立倒计时秒数,优先级高于组件 `jump-seconds`。 |
197
- | `adSpec` / `spec` | `1 \| 2` | 广告规格,`1` 为横版,`2` 为竖版。 |
198
- | `width` / `videoWidth` | `number` | 素材宽度,用于推断广告规格。 |
199
- | `height` / `videoHeight` | `number` | 素材高度,用于推断广告规格。 |
200
-
201
- ### 跳转字段
202
-
203
- | 跳转类型 | 字段 | 说明 |
204
- | --- | --- | --- |
205
- | 跳转其他小程序 | `appId` / `miniProgramAppId` / `jumpAppId` | 目标小程序 appId。 |
206
- | 跳转小程序内部页面 | `path` / `pagePath` / `jumpPath` / `targetUrl` | 当前小程序页面路径。 |
207
- | 打开 WebView | `url` / `webUrl` / `h5Url` / `jumpUrl` | H5 地址。组件不会直接打开 WebView,会触发 `openWebview` 事件交给业务处理。 |
208
-
209
- 跳转优先级为:其他小程序 > 小程序内部页面 > WebView。
210
-
211
- ### 示例
212
-
213
- ```js
214
- Page({
215
- data: {
216
- bannerAdId: 'ad_123456',
217
- splashAdId: 'launch_splash'
218
- }
219
- })
220
- ```
221
-
222
180
  ## 事件
223
181
 
224
182
  ### 通用事件
@@ -229,6 +187,7 @@ Page({
229
187
  | `error` | 接口请求失败或返回失败码;SDK 未初始化;广告素材加载失败;广告跳转失败 | `{ provider?, type, adId?, errCode, errMsg }` |
230
188
  | `close` | 广告关闭;远程配置成功但无可展示广告时也会触发 | `{ provider, type, adId?, reason? }`,无可展示广告时 `reason` 为 `noAd` |
231
189
  | `action` | 自定义广告点击 | `{ provider, type, adId? }` |
190
+ | `feedback` | 自研 Banner 反馈操作 | 不感兴趣:`{ provider, type, adId?, action: 'dislike', reason, reasonText }`;反馈问题:`{ provider, type, adId?, action: 'report' }` |
232
191
  | `openWebview` | 自定义广告命中 WebView 跳转 | `{ provider, type, adId?, url }` |
233
192
 
234
193
  ### 统一广告组件扩展事件
@@ -268,6 +227,7 @@ Page({
268
227
  | `DISPLAY_AD_REMOTE_CONFIG_FAIL` | 广告位配置接口返回失败。 |
269
228
  | `DISPLAY_AD_REMOTE_CONFIG_EXCEPTION` | 广告位配置请求异常。 |
270
229
  | `UNSUPPORTED_DISPLAY_AD_TYPE` | `type` 不是 `banner` 或 `splash`。 |
230
+ | `BI_BANNER_WECHAT_AD_LOAD_FAIL` | 微信原生 Banner 加载失败;存在自研 Banner 时组件会自动降级。 |
271
231
  | `BI_BANNER_CUSTOM_MEDIA_LOAD_TIMEOUT` | Banner 自定义图片加载超时。 |
272
232
  | `BI_BANNER_CUSTOM_MEDIA_LOAD_FAIL` | Banner 自定义图片加载失败。 |
273
233
  | `BI_BANNER_NAVIGATE_MINI_PROGRAM_FAIL` | Banner 自定义广告跳转其他小程序失败。 |
@@ -285,3 +245,4 @@ Page({
285
245
  3. WebView 地址不会由组件直接打开,必须由业务页面监听 `openWebview` 后处理。
286
246
  4. 使用 `ad-id` 前,需要先把业务 SDK 实例挂载到 `app.biNova`。
287
247
  5. 开屏广告页面推荐设置 `"navigationStyle": "custom"`,避免默认导航栏占用展示空间,提升开屏展示效果。
248
+ 6. 请将 `https://nad.ehuoke.com` 配置为小程序的 `request 合法域名`,否则无法获取广告位配置。
@@ -3,7 +3,7 @@
3
3
  * @Author wutao
4
4
  * @Date 2026-04-10
5
5
  * @LastEditors wutao
6
- * @LastEditTime 2026-04-17
6
+ * @LastEditTime 2026-08-13 15:02:40
7
7
  */
8
8
  const {
9
9
  navigateCustomAd
@@ -13,26 +13,34 @@ 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
  adIntervals: { type: Number, value: 30 }
17
18
  },
18
19
  data: {
19
20
  isWechatAd: false,
21
+ visible: false,
22
+ hasCustomMedia: false,
20
23
  customLoaded: false,
21
- customFailed: false
24
+ customFailed: false,
25
+ feedbackVisible: false,
26
+ feedbackStage: 'primary',
27
+ dislikeReasons: [
28
+ { label: '与我无关', value: 'irrelevant' },
29
+ { label: '重复收到多次', value: 'repeated' },
30
+ { label: '内容太差', value: 'poorContent' }
31
+ ]
22
32
  },
23
33
  lifetimes: {
24
34
  attached() {
25
- this.syncProvider(this.properties.unitId)
26
- this.resetCustomLoadState()
35
+ this.syncAdSource(this.properties.unitId, this.properties.customAd, this.properties.priority)
27
36
  },
28
37
  detached() {
29
38
  this.clearCustomLoadTimeout()
30
39
  }
31
40
  },
32
41
  observers: {
33
- 'unitId, customAd'(nextUnitId) {
34
- this.syncProvider(nextUnitId)
35
- this.resetCustomLoadState()
42
+ 'unitId, customAd, priority'(nextUnitId, nextCustomAd, nextPriority) {
43
+ this.syncAdSource(nextUnitId, nextCustomAd, nextPriority)
36
44
  }
37
45
  },
38
46
  methods: {
@@ -42,9 +50,17 @@ Component({
42
50
  * @returns {{provider: 'wechat' | 'custom', type: 'banner'}}
43
51
  */
44
52
  createEventDetail(provider) {
53
+ const customAd = provider === 'custom' && this.properties.customAd || null
54
+
45
55
  return {
46
56
  provider,
47
- type: 'banner'
57
+ type: 'banner',
58
+ ...(customAd ? {
59
+ configId: customAd.configId,
60
+ placementId: customAd.placementId,
61
+ configName: customAd.configName,
62
+ advertPlatform: customAd.advertPlatform
63
+ } : {})
48
64
  }
49
65
  },
50
66
 
@@ -81,12 +97,128 @@ Component({
81
97
  },
82
98
 
83
99
  /**
84
- * 根据 `unitId` 同步广告来源
100
+ * 同步 Banner 广告来源与展示状态
101
+ * @param {string} unitId 微信广告位 ID
102
+ * @param {Record<string, any> | null} customAd 自研广告配置
103
+ * @param {string} priority 广告展示优先级
104
+ * @returns {void}
105
+ */
106
+ syncAdSource(unitId, customAd, priority) {
107
+ const hasCustomMedia = Boolean(customAd && customAd.image)
108
+ const isWechatAd = this.shouldStartWechatAd(unitId, hasCustomMedia, priority)
109
+
110
+ this.clearCustomLoadTimeout()
111
+ this.resetProviderFailures()
112
+ this.setData({
113
+ isWechatAd,
114
+ visible: Boolean(unitId || hasCustomMedia),
115
+ hasCustomMedia,
116
+ customLoaded: false,
117
+ customFailed: false,
118
+ feedbackVisible: false,
119
+ feedbackStage: 'primary'
120
+ }, () => {
121
+ if (!isWechatAd && hasCustomMedia) {
122
+ this.startCustomLoadTimeout()
123
+ }
124
+ })
125
+ },
126
+
127
+ /**
128
+ * 根据广告配置和优先级判断是否首发微信广告
85
129
  * @param {string} unitId 微信广告位 ID
130
+ * @param {boolean} hasCustomMedia 是否存在自研 Banner 素材
131
+ * @param {string} priority 广告展示优先级
132
+ * @returns {boolean}
133
+ */
134
+ shouldStartWechatAd(unitId, hasCustomMedia, priority) {
135
+ if (!unitId) return false
136
+ if (!hasCustomMedia) return true
137
+ return !['custom-first', 'custom-only'].includes(priority)
138
+ },
139
+
140
+ /**
141
+ * 重置当前展示周期的广告来源失败记录
142
+ * @returns {void}
143
+ */
144
+ resetProviderFailures() {
145
+ this.failedProviders = {
146
+ wechat: false,
147
+ custom: false
148
+ }
149
+ },
150
+
151
+ /**
152
+ * 记录指定广告来源加载失败
153
+ * @param {'wechat' | 'custom'} provider 广告来源
86
154
  * @returns {void}
87
155
  */
88
- syncProvider(unitId) {
89
- this.setData({ isWechatAd: Boolean(unitId) })
156
+ markProviderFailed(provider) {
157
+ if (!this.failedProviders) this.resetProviderFailures()
158
+ this.failedProviders[provider] = true
159
+ },
160
+
161
+ /**
162
+ * 判断指定广告来源是否已经失败
163
+ * @param {'wechat' | 'custom'} provider 广告来源
164
+ * @returns {boolean}
165
+ */
166
+ hasProviderFailed(provider) {
167
+ return Boolean(this.failedProviders && this.failedProviders[provider])
168
+ },
169
+
170
+ /**
171
+ * 切换当前展示的广告来源
172
+ * @param {'wechat' | 'custom'} provider 目标广告来源
173
+ * @returns {void}
174
+ */
175
+ switchProvider(provider) {
176
+ const isWechatAd = provider === 'wechat'
177
+
178
+ this.clearCustomLoadTimeout()
179
+ this.setData({
180
+ isWechatAd,
181
+ visible: true,
182
+ customLoaded: false,
183
+ customFailed: false,
184
+ feedbackVisible: false,
185
+ feedbackStage: 'primary'
186
+ }, () => {
187
+ if (!isWechatAd) {
188
+ this.startCustomLoadTimeout()
189
+ }
190
+ })
191
+ },
192
+
193
+ /**
194
+ * 所有可用广告来源均失败后结束当前 Banner 展示流程
195
+ * @param {'wechat' | 'custom'} provider 最后失败的广告来源
196
+ * @param {Record<string, any>} errorDetail 错误详情
197
+ * @returns {void}
198
+ */
199
+ finishProviderFailure(provider, errorDetail) {
200
+ const hasWechatAd = Boolean(this.properties.unitId)
201
+ const hasCustomAd = Boolean(this.data.hasCustomMedia)
202
+ const reason = hasWechatAd && hasCustomAd
203
+ ? 'allProvidersFailed'
204
+ : provider === 'wechat'
205
+ ? 'wechatAdLoadFail'
206
+ : 'customMediaLoadFail'
207
+
208
+ this.clearCustomLoadTimeout()
209
+ this.setData({
210
+ visible: false,
211
+ customLoaded: false,
212
+ customFailed: provider === 'custom',
213
+ feedbackVisible: false,
214
+ feedbackStage: 'primary'
215
+ })
216
+ this.triggerEvent('close', {
217
+ provider,
218
+ type: 'banner',
219
+ reason,
220
+ error: errorDetail
221
+ })
90
222
  },
91
223
 
92
224
  /**
@@ -103,18 +235,11 @@ Component({
103
235
  },
104
236
 
105
237
  /**
106
- * 重置自定义广告加载状态
238
+ * 启动自研 Banner 素材加载超时检测
107
239
  * @returns {void}
108
240
  */
109
- resetCustomLoadState() {
241
+ startCustomLoadTimeout() {
110
242
  this.clearCustomLoadTimeout()
111
- this.setData({
112
- customLoaded: false,
113
- customFailed: false
114
- })
115
-
116
- if (this.properties.unitId || !this.properties.customAd || !this.properties.customAd.image) return
117
-
118
243
  this.customLoadTimer = setTimeout(() => {
119
244
  this.handleCustomLoadTimeout()
120
245
  }, this.getCustomLoadTimeout())
@@ -137,6 +262,8 @@ Component({
137
262
  * @returns {void}
138
263
  */
139
264
  handleLoad(event) {
265
+ if (!this.data.isWechatAd) return
266
+
140
267
  this.triggerEvent('load', this.resolveEventDetail('wechat', event))
141
268
  },
142
269
 
@@ -146,7 +273,25 @@ Component({
146
273
  * @returns {void}
147
274
  */
148
275
  handleError(event) {
149
- this.triggerEvent('error', this.resolveEventDetail('wechat', event))
276
+ if (!this.data.isWechatAd) return
277
+
278
+ const rawDetail = event && event.detail && typeof event.detail === 'object' ? event.detail : {}
279
+ const errorDetail = this.resolveEventDetail('wechat', event, {
280
+ errCode: 'BI_BANNER_WECHAT_AD_LOAD_FAIL',
281
+ errMsg: rawDetail.errMsg || '微信 Banner 广告加载失败',
282
+ rawErrCode: rawDetail.errCode,
283
+ rawErrMsg: rawDetail.errMsg
284
+ })
285
+
286
+ this.triggerEvent('error', errorDetail)
287
+ this.markProviderFailed('wechat')
288
+
289
+ if (this.data.hasCustomMedia && !this.hasProviderFailed('custom')) {
290
+ this.switchProvider('custom')
291
+ return
292
+ }
293
+
294
+ this.finishProviderFailure('wechat', errorDetail)
150
295
  },
151
296
 
152
297
  /**
@@ -155,6 +300,8 @@ Component({
155
300
  * @returns {void}
156
301
  */
157
302
  handleClose(event) {
303
+ if (!this.data.isWechatAd) return
304
+
158
305
  this.triggerEvent('close', this.resolveEventDetail('wechat', event))
159
306
  },
160
307
 
@@ -163,7 +310,7 @@ Component({
163
310
  * @returns {void}
164
311
  */
165
312
  handleCustomLoad() {
166
- if (this.data.customLoaded) return
313
+ if (this.data.isWechatAd || this.data.customLoaded) return
167
314
 
168
315
  this.clearCustomLoadTimeout()
169
316
  this.setData({ customLoaded: true })
@@ -175,29 +322,48 @@ Component({
175
322
  * @returns {void}
176
323
  */
177
324
  handleCustomLoadTimeout() {
178
- if (this.data.customLoaded || this.data.customFailed) return
325
+ if (this.data.isWechatAd || this.data.customLoaded || this.data.customFailed) return
179
326
 
180
- this.setData({ customFailed: true })
181
- this.triggerEvent('error', this.resolveEventDetail('custom', null, {
327
+ this.handleCustomMediaFail(null, {
182
328
  errCode: 'BI_BANNER_CUSTOM_MEDIA_LOAD_TIMEOUT',
183
329
  errMsg: 'Banner 广告素材加载超时'
184
- }))
330
+ })
185
331
  },
186
332
 
187
333
  /**
188
- * 处理自定义广告素材加载失败事件
189
- * @param {Record<string, any>} event 素材错误事件
334
+ * 统一处理自研 Banner 素材加载失败
335
+ * @param {Record<string, any> | null} event 素材错误事件
336
+ * @param {Record<string, any>} detail 错误详情
190
337
  * @returns {void}
191
338
  */
192
- handleCustomMediaError(event) {
193
- if (this.data.customFailed) return
339
+ handleCustomMediaFail(event, detail) {
340
+ if (this.data.isWechatAd || this.data.customFailed) return
194
341
 
195
342
  this.clearCustomLoadTimeout()
343
+ const errorDetail = this.resolveEventDetail('custom', event, detail)
344
+
196
345
  this.setData({ customFailed: true })
197
- this.triggerEvent('error', this.resolveEventDetail('custom', event, {
346
+ this.triggerEvent('error', errorDetail)
347
+ this.markProviderFailed('custom')
348
+
349
+ if (this.properties.unitId && !this.hasProviderFailed('wechat')) {
350
+ this.switchProvider('wechat')
351
+ return
352
+ }
353
+
354
+ this.finishProviderFailure('custom', errorDetail)
355
+ },
356
+
357
+ /**
358
+ * 处理自定义广告素材加载失败事件
359
+ * @param {Record<string, any>} event 素材错误事件
360
+ * @returns {void}
361
+ */
362
+ handleCustomMediaError(event) {
363
+ this.handleCustomMediaFail(event, {
198
364
  errCode: 'BI_BANNER_CUSTOM_MEDIA_LOAD_FAIL',
199
365
  errMsg: 'Banner 广告素材加载失败'
200
- }))
366
+ })
201
367
  },
202
368
 
203
369
  /**
@@ -205,6 +371,11 @@ Component({
205
371
  * @returns {void}
206
372
  */
207
373
  handleCustomAction() {
374
+ if (this.data.feedbackVisible) {
375
+ this.closeFeedbackPanel()
376
+ return
377
+ }
378
+
208
379
  const actionDetail = this.createEventDetail('custom')
209
380
 
210
381
  this.triggerEvent('action', actionDetail)
@@ -215,8 +386,100 @@ Component({
215
386
  * 处理自定义广告关闭事件
216
387
  * @returns {void}
217
388
  */
218
- handleCustomClose() {
219
- this.triggerEvent('close', this.createEventDetail('custom'))
389
+ handleCustomClose(extraDetail) {
390
+ this.clearCustomLoadTimeout()
391
+ this.setData({
392
+ visible: false,
393
+ feedbackVisible: false,
394
+ feedbackStage: 'primary'
395
+ })
396
+ this.triggerEvent('close', {
397
+ ...this.createEventDetail('custom'),
398
+ ...extraDetail
399
+ })
400
+ },
401
+
402
+ /**
403
+ * 处理广告标识点击,切换反馈菜单显隐
404
+ * @returns {void}
405
+ */
406
+ handleBadgeTap() {
407
+ const feedbackVisible = !this.data.feedbackVisible
408
+
409
+ this.setData({
410
+ feedbackVisible,
411
+ feedbackStage: 'primary'
412
+ })
413
+ },
414
+
415
+ /**
416
+ * 拦截反馈浮层内部点击,避免触发 Banner 整体跳转
417
+ * @returns {void}
418
+ */
419
+ handleFeedbackPanelTap() {},
420
+
421
+ /**
422
+ * 关闭反馈菜单并重置一级菜单
423
+ * @returns {void}
424
+ */
425
+ closeFeedbackPanel() {
426
+ this.setData({
427
+ feedbackVisible: false,
428
+ feedbackStage: 'primary'
429
+ })
430
+ },
431
+
432
+ /**
433
+ * 处理一级反馈选项
434
+ * @param {Record<string, any>} event 点击事件
435
+ * @returns {void}
436
+ */
437
+ handleFeedbackOptionTap(event) {
438
+ const action = event && event.currentTarget && event.currentTarget.dataset && event.currentTarget.dataset.action
439
+
440
+ if (action === 'dislike') {
441
+ this.setData({ feedbackStage: 'dislike' })
442
+ return
443
+ }
444
+
445
+ if (action === 'report') {
446
+ this.closeFeedbackPanel()
447
+ this.triggerEvent('feedback', {
448
+ ...this.createEventDetail('custom'),
449
+ action: 'report'
450
+ })
451
+
452
+ if (typeof wx !== 'undefined' && typeof wx.showToast === 'function') {
453
+ wx.showToast({
454
+ title: '已收到您的反馈,我们会尽快处理~',
455
+ icon: 'none',
456
+ duration: 2000
457
+ })
458
+ }
459
+ }
460
+ },
461
+
462
+ /**
463
+ * 处理不感兴趣原因并关闭当前 Banner
464
+ * @param {Record<string, any>} event 点击事件
465
+ * @returns {void}
466
+ */
467
+ handleDislikeReasonTap(event) {
468
+ const dataset = event && event.currentTarget && event.currentTarget.dataset || {}
469
+ const reason = dataset.reason || ''
470
+ const reasonText = dataset.label || ''
471
+
472
+ this.triggerEvent('feedback', {
473
+ ...this.createEventDetail('custom'),
474
+ action: 'dislike',
475
+ reason,
476
+ reasonText
477
+ })
478
+ this.handleCustomClose({
479
+ reason: 'notInterested',
480
+ feedbackReason: reason,
481
+ feedbackReasonText: reasonText
482
+ })
220
483
  },
221
484
 
222
485
  /**
@@ -1,5 +1,5 @@
1
1
  <ad-custom
2
- wx:if="{{isWechatAd && unitId}}"
2
+ wx:if="{{visible && isWechatAd && unitId}}"
3
3
  unit-id="{{unitId}}"
4
4
  ad-intervals="{{adIntervals}}"
5
5
  bind:load="handleLoad"
@@ -8,31 +8,50 @@
8
8
  />
9
9
 
10
10
  <view
11
- wx:elif="{{customAd && customAd.image && !customFailed}}"
11
+ wx:elif="{{visible && !isWechatAd && customAd && customAd.image && !customFailed}}"
12
12
  class="bi-banner-ad"
13
13
  >
14
14
  <view class="bi-banner-ad__surface" bindtap="handleCustomAction">
15
- <view class="bi-banner-ad__media">
16
- <text class="bi-banner-ad__badge bi-banner-ad__badge--overlay">{{customAd.badgeText || '广告'}}</text>
17
- <image
18
- class="bi-banner-ad__image"
19
- src="{{customAd.image}}"
20
- mode="aspectFill"
21
- bindload="handleCustomLoad"
22
- binderror="handleCustomMediaError"
23
- />
24
- </view>
25
- <view class="bi-banner-ad__content">
26
- <view class="bi-banner-ad__body">
27
- <text wx:if="{{customAd.title}}" class="bi-banner-ad__title">{{customAd.title}}</text>
15
+ <image
16
+ class="bi-banner-ad__image"
17
+ src="{{customAd.image}}"
18
+ mode="widthFix"
19
+ bindload="handleCustomLoad"
20
+ binderror="handleCustomMediaError"
21
+ />
22
+ </view>
23
+
24
+ <view class="bi-banner-ad__badge" catchtap="handleBadgeTap">
25
+ <text>{{customAd.badgeText || '广告'}}</text>
26
+ <view class="bi-banner-ad__badge-arrow"></view>
27
+ </view>
28
+
29
+ <view
30
+ wx:if="{{feedbackVisible}}"
31
+ class="bi-banner-ad__feedback-panel"
32
+ catchtap="handleFeedbackPanelTap"
33
+ >
34
+ <block wx:if="{{feedbackStage === 'primary'}}">
35
+ <view class="bi-banner-ad__feedback-source">由赞助商提供的内容</view>
36
+ <view class="bi-banner-ad__feedback-item" data-action="dislike" catchtap="handleFeedbackOptionTap">
37
+ 不感兴趣
38
+ </view>
39
+ <view class="bi-banner-ad__feedback-item" data-action="report" catchtap="handleFeedbackOptionTap">
40
+ 反馈问题
28
41
  </view>
29
- <view class="bi-banner-ad__footer">
30
- <text wx:if="{{customAd.description}}" class="bi-banner-ad__description">{{customAd.description}}</text>
31
- <button class="bi-banner-ad__button" catchtap="handleCustomAction">
32
- {{customAd.buttonText || '立即查看'}}
33
- </button>
42
+ </block>
43
+
44
+ <block wx:else>
45
+ <view
46
+ wx:for="{{dislikeReasons}}"
47
+ wx:key="value"
48
+ class="bi-banner-ad__feedback-item"
49
+ data-reason="{{item.value}}"
50
+ data-label="{{item.label}}"
51
+ catchtap="handleDislikeReasonTap"
52
+ >
53
+ {{item.label}}
34
54
  </view>
35
- </view>
55
+ </block>
36
56
  </view>
37
- <button class="bi-banner-ad__close" catchtap="handleCustomClose">×</button>
38
57
  </view>