@bi-nova/ui-weapp 1.2.1 → 1.3.0-beta.202609181052

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.
@@ -0,0 +1,293 @@
1
+ /**
2
+ * @Description 产品投放位动作执行器
3
+ * @Author wutao
4
+ * @Date 2026-09-14
5
+ * @LastEditors wutao
6
+ * @LastEditTime 2026-09-15 12:02:24
7
+ */
8
+ const { executeNavigationAction } = require('../shared/action-executor')
9
+
10
+ /** 产品投放位动作错误码 */
11
+ const ACTION_ERROR_CODES = {
12
+ invalidAction: 'PRODUCT_PLACEMENT_ACTION_INVALID',
13
+ miniProgramFail: 'PRODUCT_PLACEMENT_NAVIGATE_MINI_PROGRAM_FAIL',
14
+ internalFail: 'PRODUCT_PLACEMENT_NAVIGATE_FAIL',
15
+ apiRequestFail: 'PRODUCT_PLACEMENT_API_REQUEST_FAIL',
16
+ unsupportedApi: 'PRODUCT_PLACEMENT_ACTION_API_UNSUPPORTED'
17
+ }
18
+
19
+ /**
20
+ * 上报业务动作执行错误
21
+ * @param {Record<string, any>} options 执行参数
22
+ * @param {string} errCode 错误码
23
+ * @param {string} errMsg 错误信息
24
+ * @returns {false}
25
+ */
26
+ function emitBusinessError(options, errCode, errMsg) {
27
+ if (typeof options.onError === 'function') {
28
+ options.onError({ errCode, errMsg })
29
+ }
30
+
31
+ return false
32
+ }
33
+
34
+ /**
35
+ * 获取当前标准化业务编码
36
+ * @param {Record<string, any>} options 执行参数
37
+ * @returns {string} 小写业务编码
38
+ */
39
+ function getBusinessCode(options) {
40
+ return String(
41
+ options.action && options.action.businessCode || ''
42
+ ).trim().toLowerCase()
43
+ }
44
+
45
+ /**
46
+ * 处理京东保险服务结果
47
+ * @param {Record<string, any>} options 执行参数
48
+ * @param {Record<string, any>} result 服务结果
49
+ * @returns {void}
50
+ */
51
+ function handleJdInsuranceResult(options, result) {
52
+ const businessCode = getBusinessCode(options)
53
+
54
+ if (!result || result.code !== 0) {
55
+ emitBusinessError(
56
+ options,
57
+ 'PRODUCT_PLACEMENT_BUSINESS_EXECUTE_FAIL',
58
+ result && result.message || '京东保险服务执行失败'
59
+ )
60
+ return
61
+ }
62
+
63
+ const data = result.data || {}
64
+
65
+ if (data.type === 'copy_success') {
66
+ const wxApi = typeof wx === 'undefined' ? null : wx
67
+
68
+ if (wxApi && typeof wxApi.showToast === 'function') {
69
+ wxApi.showToast({
70
+ title: result.message || '口令已复制',
71
+ icon: 'success'
72
+ })
73
+ }
74
+
75
+ if (typeof options.onSuccess === 'function') {
76
+ options.onSuccess({
77
+ actionType: 'business',
78
+ businessCode,
79
+ resultType: 'copy_success'
80
+ })
81
+ }
82
+ return
83
+ }
84
+
85
+ if (data.type === 'mini_program') {
86
+ executeNavigationAction({
87
+ ...options,
88
+ action: {
89
+ type: 'mini_program',
90
+ appId: data.appId,
91
+ path: data.path
92
+ },
93
+ errorCodes: ACTION_ERROR_CODES,
94
+ onSuccess(detail) {
95
+ if (typeof options.onSuccess === 'function') {
96
+ options.onSuccess({
97
+ ...detail,
98
+ actionType: 'business',
99
+ businessCode
100
+ })
101
+ }
102
+ }
103
+ })
104
+ return
105
+ }
106
+
107
+ if (data.type === 'h5') {
108
+ executeNavigationAction({
109
+ ...options,
110
+ action: {
111
+ type: 'web',
112
+ url: data.url
113
+ },
114
+ errorCodes: ACTION_ERROR_CODES,
115
+ onSuccess(detail) {
116
+ if (typeof options.onSuccess === 'function') {
117
+ options.onSuccess({
118
+ ...detail,
119
+ actionType: 'business',
120
+ businessCode
121
+ })
122
+ }
123
+ }
124
+ })
125
+ return
126
+ }
127
+
128
+ emitBusinessError(
129
+ options,
130
+ 'PRODUCT_PLACEMENT_BUSINESS_RESULT_INVALID',
131
+ `京东保险服务返回了不支持的结果类型:${data.type || 'empty'}`
132
+ )
133
+ }
134
+
135
+ /**
136
+ * 执行京东保险内部服务
137
+ * @param {Record<string, any>} options 执行参数
138
+ * @returns {boolean}
139
+ */
140
+ function executeJdInsurance(options) {
141
+ const sdk = options.sdk
142
+ const actionContext = options.actionContext || {}
143
+ const equipmentValue = String(actionContext.equipmentValue || '').trim()
144
+ const phone = String(actionContext.phone || '').trim()
145
+ const entrance = String(actionContext.entrance || '').trim()
146
+
147
+ if (!equipmentValue) {
148
+ return emitBusinessError(
149
+ options,
150
+ 'PRODUCT_PLACEMENT_BUSINESS_PARAM_INVALID',
151
+ '京东保险服务缺少必要参数:equipmentValue'
152
+ )
153
+ }
154
+
155
+ if (!sdk || !sdk.jd || typeof sdk.jd.handleJdInsurance !== 'function') {
156
+ return emitBusinessError(
157
+ options,
158
+ 'PRODUCT_PLACEMENT_BUSINESS_SERVICE_NOT_READY',
159
+ '未获取到京东保险服务,请升级并初始化 @bi-nova/services'
160
+ )
161
+ }
162
+
163
+ Promise.resolve(sdk.jd.handleJdInsurance({
164
+ equipmentValue,
165
+ ...(phone ? { phone } : {}),
166
+ ...(entrance ? { entrance } : {})
167
+ })).then((result) => {
168
+ handleJdInsuranceResult(options, result)
169
+ }).catch((error) => {
170
+ emitBusinessError(
171
+ options,
172
+ 'PRODUCT_PLACEMENT_BUSINESS_EXECUTE_EXCEPTION',
173
+ error && error.message || '京东保险服务执行异常'
174
+ )
175
+ })
176
+
177
+ return true
178
+ }
179
+
180
+ /**
181
+ * 执行京东保险外部对接服务
182
+ * @param {Record<string, any>} options 执行参数
183
+ * @returns {boolean}
184
+ */
185
+ function executeJdInsuranceExt(options) {
186
+ const sdk = options.sdk
187
+ const actionContext = options.actionContext || {}
188
+ const thirdPlatform = String(actionContext.thirdPlatform || '').trim()
189
+ const thirdPlatformUserId = String(actionContext.thirdPlatformUserId || '').trim()
190
+ const thirdPlatformEquipmentValue = String(
191
+ actionContext.thirdPlatformEquipmentValue || ''
192
+ ).trim()
193
+ const phone = String(actionContext.phone || '').trim()
194
+ const extendData = actionContext.extendData
195
+ const missingParamNames = [
196
+ ['thirdPlatform', thirdPlatform],
197
+ ['thirdPlatformUserId', thirdPlatformUserId],
198
+ ['thirdPlatformEquipmentValue', thirdPlatformEquipmentValue]
199
+ ].filter((item) => !item[1]).map((item) => item[0])
200
+
201
+ if (missingParamNames.length) {
202
+ return emitBusinessError(
203
+ options,
204
+ 'PRODUCT_PLACEMENT_BUSINESS_PARAM_INVALID',
205
+ `京东保险外部对接服务缺少必要参数:${missingParamNames.join('、')}`
206
+ )
207
+ }
208
+
209
+ if (!sdk || !sdk.jd || typeof sdk.jd.handleJdInsuranceExt !== 'function') {
210
+ return emitBusinessError(
211
+ options,
212
+ 'PRODUCT_PLACEMENT_BUSINESS_SERVICE_NOT_READY',
213
+ '未获取到京东保险外部对接服务,请升级并初始化 @bi-nova/services'
214
+ )
215
+ }
216
+
217
+ Promise.resolve(sdk.jd.handleJdInsuranceExt({
218
+ thirdPlatform,
219
+ thirdPlatformUserId,
220
+ thirdPlatformEquipmentValue,
221
+ ...(phone ? { phone } : {}),
222
+ ...(extendData && typeof extendData === 'object' && !Array.isArray(extendData)
223
+ ? { extendData: { ...extendData } }
224
+ : {})
225
+ })).then((result) => {
226
+ handleJdInsuranceResult(options, result)
227
+ }).catch((error) => {
228
+ emitBusinessError(
229
+ options,
230
+ 'PRODUCT_PLACEMENT_BUSINESS_EXECUTE_EXCEPTION',
231
+ error && error.message || '京东保险外部对接服务执行异常'
232
+ )
233
+ })
234
+
235
+ return true
236
+ }
237
+
238
+ /** 产品业务动作白名单 */
239
+ const BUSINESS_ACTION_HANDLERS = {
240
+ jd_insurance: executeJdInsurance,
241
+ jd_insurance_ext: executeJdInsuranceExt
242
+ }
243
+
244
+ /**
245
+ * 执行产品业务动作
246
+ * @param {Record<string, any>} options 执行参数
247
+ * @returns {boolean}
248
+ */
249
+ function executeBusinessAction(options) {
250
+ const businessCode = getBusinessCode(options)
251
+ const handler = BUSINESS_ACTION_HANDLERS[businessCode]
252
+
253
+ if (!businessCode || typeof handler !== 'function') {
254
+ return emitBusinessError(
255
+ options,
256
+ 'PRODUCT_PLACEMENT_BUSINESS_UNSUPPORTED',
257
+ `不支持的产品业务:${businessCode || 'empty'}`
258
+ )
259
+ }
260
+
261
+ return handler(options)
262
+ }
263
+
264
+ /**
265
+ * 执行产品投放位标准动作
266
+ * @param {Object} options 动作执行参数
267
+ * @param {Record<string, any>} options.action 标准动作配置
268
+ * @param {Record<string, any>} [options.sdk] Nova SDK 实例
269
+ * @param {Record<string, any>} [options.actionContext] 宿主动作运行时上下文
270
+ * @param {Record<string, any>} [options.apiRequestParams] 动态接口运行时参数
271
+ * @param {(detail: Record<string, any>) => void} [options.onOpenWebview] WebView 回调
272
+ * @param {(detail: Record<string, any>) => void} [options.onSuccess] 成功回调
273
+ * @param {(detail: {errCode: string, errMsg: string}) => void} [options.onError] 失败回调
274
+ * @returns {boolean} 是否已进入动作执行流程
275
+ */
276
+ function executeProductPlacementAction(options) {
277
+ const action = options && options.action || {}
278
+
279
+ if (action.type === 'business') {
280
+ return executeBusinessAction(options)
281
+ }
282
+
283
+ return executeNavigationAction({
284
+ ...options,
285
+ errorCodes: ACTION_ERROR_CODES
286
+ })
287
+ }
288
+
289
+ module.exports = {
290
+ ACTION_ERROR_CODES,
291
+ BUSINESS_ACTION_HANDLERS,
292
+ executeProductPlacementAction
293
+ }
@@ -0,0 +1,106 @@
1
+ /**
2
+ * @Description 产品投放位 Banner 展示组件
3
+ * @Author wutao
4
+ * @Date 2026-09-08
5
+ * @LastEditors wutao
6
+ * @LastEditTime 2026-09-08 17:55:14
7
+ */
8
+ Component({
9
+ properties: {
10
+ creative: { type: Object, value: null },
11
+ panelStyle: { type: Object, value: null },
12
+ actionable: { type: Boolean, value: false },
13
+ actionLoading: { type: Boolean, value: false }
14
+ },
15
+ data: {
16
+ ready: false
17
+ },
18
+ lifetimes: {
19
+ attached() {
20
+ this.syncCreative(this.properties.creative)
21
+ },
22
+ detached() {
23
+ this.clearReadyTimer()
24
+ }
25
+ },
26
+ observers: {
27
+ creative(nextCreative) {
28
+ this.syncCreative(nextCreative)
29
+ }
30
+ },
31
+ methods: {
32
+ /**
33
+ * 素材不包含图片时,在视图完成更新后直接进入可展示状态
34
+ * @param {Record<string, string> | null} creative 标准化素材
35
+ * @returns {void}
36
+ */
37
+ syncCreative(creative) {
38
+ this.clearReadyTimer()
39
+ this.setData({ ready: false })
40
+
41
+ if (creative && creative.imageUrl) return
42
+
43
+ this.readyTimer = setTimeout(() => this.notifyReady('content'), 0)
44
+ },
45
+
46
+ /** 清理延迟就绪任务 */
47
+ clearReadyTimer() {
48
+ if (!this.readyTimer) return
49
+
50
+ clearTimeout(this.readyTimer)
51
+ this.readyTimer = null
52
+ },
53
+
54
+ /**
55
+ * 通知上层组件素材已经可以展示
56
+ * @param {string} mediaType 素材类型
57
+ * @returns {void}
58
+ */
59
+ notifyReady(mediaType) {
60
+ if (this.data.ready) return
61
+
62
+ this.setData({ ready: true })
63
+ this.triggerEvent('ready', { mediaType })
64
+ },
65
+
66
+ /** 处理图片加载完成 */
67
+ handleImageLoad() {
68
+ this.notifyReady('image')
69
+ },
70
+
71
+ /**
72
+ * 处理图片加载失败
73
+ * @param {Record<string, any>} event 小程序图片错误事件
74
+ * @returns {void}
75
+ */
76
+ handleImageError(event) {
77
+ const rawDetail = event && event.detail || {}
78
+
79
+ this.triggerEvent('error', {
80
+ errCode: 'PRODUCT_PLACEMENT_BANNER_IMAGE_LOAD_FAIL',
81
+ errMsg: '产品 Banner 图片加载失败',
82
+ errorType: 'MEDIA_LOAD_FAIL',
83
+ rawErrCode: rawDetail.errCode,
84
+ rawErrMsg: rawDetail.errMsg
85
+ })
86
+ },
87
+
88
+ /** 处理关闭按钮点击 */
89
+ handleClose() {
90
+ this.triggerEvent('close', { reason: 'closeButton' })
91
+ },
92
+
93
+ /**
94
+ * 处理可点击区域操作
95
+ * @param {Record<string, any>} event 点击事件
96
+ * @returns {void}
97
+ */
98
+ handleAction(event) {
99
+ if (!this.properties.actionable || this.properties.actionLoading) return
100
+
101
+ this.triggerEvent('action', {
102
+ source: event && event.currentTarget && event.currentTarget.dataset.source || 'surface'
103
+ })
104
+ }
105
+ }
106
+ })
@@ -0,0 +1,3 @@
1
+ {
2
+ "component": true
3
+ }
@@ -0,0 +1,48 @@
1
+ <!--
2
+ @Description 产品投放位 Banner 展示组件模板
3
+ @Author wutao
4
+ @Date 2026-09-08
5
+ @LastEditors wutao
6
+ @LastEditTime 2026-09-14 14:44:07
7
+ -->
8
+ <view class="bi-product-banner {{panelStyle.skinClass}}">
9
+ <view
10
+ class="bi-product-banner__surface {{actionable ? 'bi-product-banner__surface--actionable' : ''}}"
11
+ data-source="surface"
12
+ bindtap="handleAction"
13
+ >
14
+ <image
15
+ wx:if="{{creative.imageUrl}}"
16
+ class="bi-product-banner__image"
17
+ src="{{creative.imageUrl}}"
18
+ mode="widthFix"
19
+ bindload="handleImageLoad"
20
+ binderror="handleImageError"
21
+ />
22
+
23
+ <view wx:if="{{creative.title || creative.description || creative.buttonText}}" class="bi-product-banner__body">
24
+ <view class="bi-product-banner__copy">
25
+ <text wx:if="{{creative.badgeText}}" class="bi-product-banner__badge">{{creative.badgeText}}</text>
26
+ <text wx:if="{{creative.title}}" class="bi-product-banner__title">{{creative.title}}</text>
27
+ <text wx:if="{{creative.description}}" class="bi-product-banner__description">{{creative.description}}</text>
28
+ </view>
29
+ <button
30
+ wx:if="{{creative.buttonText}}"
31
+ class="bi-product-banner__button {{!actionable || actionLoading ? 'bi-product-banner__button--disabled' : ''}}"
32
+ data-source="button"
33
+ loading="{{actionLoading}}"
34
+ disabled="{{!actionable || actionLoading}}"
35
+ catchtap="handleAction"
36
+ >
37
+ {{creative.buttonText}}
38
+ </button>
39
+ </view>
40
+ </view>
41
+
42
+ <button
43
+ wx:if="{{panelStyle.closeable}}"
44
+ class="bi-product-banner__close"
45
+ aria-label="关闭产品投放位"
46
+ catchtap="handleClose"
47
+ >×</button>
48
+ </view>
@@ -0,0 +1,133 @@
1
+ /*
2
+ * @Description 产品投放位 Banner 展示组件样式
3
+ * @Author wutao
4
+ * @Date 2026-09-08
5
+ * @LastEditors wutao
6
+ * @LastEditTime 2026-09-14 14:44:07
7
+ */
8
+ :host {
9
+ display: block;
10
+ width: 100%;
11
+ }
12
+
13
+ .bi-product-banner {
14
+ position: relative;
15
+ overflow: hidden;
16
+ box-sizing: border-box;
17
+ width: 100%;
18
+ border-radius: 16rpx;
19
+ background: #ffffff;
20
+ box-shadow: 0 8rpx 24rpx rgba(15, 23, 42, 0.08);
21
+ }
22
+
23
+ .bi-product-banner__surface--actionable {
24
+ cursor: pointer;
25
+ }
26
+
27
+ .bi-product-banner__surface {
28
+ width: 100%;
29
+ }
30
+
31
+ .bi-product-banner__image {
32
+ display: block;
33
+ width: 100%;
34
+ height: auto;
35
+ }
36
+
37
+ .bi-product-banner__body {
38
+ display: flex;
39
+ align-items: center;
40
+ box-sizing: border-box;
41
+ min-height: 132rpx;
42
+ padding: 24rpx 28rpx;
43
+ }
44
+
45
+ .bi-product-banner__copy {
46
+ display: flex;
47
+ flex: 1;
48
+ min-width: 0;
49
+ flex-direction: column;
50
+ }
51
+
52
+ .bi-product-banner__badge {
53
+ align-self: flex-start;
54
+ padding: 2rpx 10rpx;
55
+ border-radius: 6rpx;
56
+ background: #fff0e8;
57
+ color: #fa541c;
58
+ font-size: 20rpx;
59
+ line-height: 32rpx;
60
+ }
61
+
62
+ .bi-product-banner__title {
63
+ margin-top: 8rpx;
64
+ overflow: hidden;
65
+ color: #1f2329;
66
+ font-size: 30rpx;
67
+ font-weight: 600;
68
+ line-height: 42rpx;
69
+ text-overflow: ellipsis;
70
+ white-space: nowrap;
71
+ }
72
+
73
+ .bi-product-banner__description {
74
+ display: -webkit-box;
75
+ overflow: hidden;
76
+ color: #646a73;
77
+ font-size: 24rpx;
78
+ line-height: 34rpx;
79
+ -webkit-box-orient: vertical;
80
+ -webkit-line-clamp: 2;
81
+ }
82
+
83
+ .bi-product-banner__button {
84
+ flex: 0 0 auto;
85
+ box-sizing: border-box;
86
+ min-width: 144rpx;
87
+ height: 64rpx;
88
+ margin: 0;
89
+ margin-left: 24rpx;
90
+ padding: 0 24rpx;
91
+ border-radius: 32rpx;
92
+ background: #1677ff;
93
+ color: #ffffff;
94
+ font-size: 24rpx;
95
+ font-weight: 500;
96
+ line-height: 64rpx;
97
+ }
98
+
99
+ .bi-product-banner__button::after,
100
+ .bi-product-banner__close::after {
101
+ border: none;
102
+ }
103
+
104
+ .bi-product-banner__close {
105
+ position: absolute;
106
+ top: 12rpx;
107
+ right: 12rpx;
108
+ z-index: 2;
109
+ width: 48rpx;
110
+ height: 48rpx;
111
+ margin: 0;
112
+ padding: 0;
113
+ border-radius: 50%;
114
+ background: rgba(0, 0, 0, 0.42);
115
+ color: #ffffff;
116
+ font-size: 34rpx;
117
+ font-weight: 300;
118
+ line-height: 44rpx;
119
+ }
120
+
121
+ .bi-product-skin--vip-gold .bi-product-banner__button {
122
+ background: linear-gradient(135deg, #efc77e 0%, #b8893f 100%);
123
+ color: #35230b;
124
+ }
125
+
126
+ .bi-product-skin--insurance-blue .bi-product-banner__button {
127
+ background: #246bfd;
128
+ }
129
+
130
+ .bi-product-banner__button.bi-product-banner__button--disabled {
131
+ background: #a9c9f7;
132
+ color: rgba(255, 255, 255, 0.9);
133
+ }
@@ -0,0 +1,129 @@
1
+ /**
2
+ * @Description 产品投放位底部半屏组件
3
+ * @Author wutao
4
+ * @Date 2026-09-08
5
+ * @LastEditors wutao
6
+ * @LastEditTime 2026-09-08 17:55:14
7
+ */
8
+ Component({
9
+ properties: {
10
+ creative: { type: Object, value: null },
11
+ panelStyle: { type: Object, value: null },
12
+ actionable: { type: Boolean, value: false },
13
+ actionLoading: { type: Boolean, value: false },
14
+ zIndex: { type: Number, value: 999 }
15
+ },
16
+ data: {
17
+ ready: false,
18
+ panelHeight: 68
19
+ },
20
+ lifetimes: {
21
+ attached() {
22
+ this.syncPanelStyle(this.properties.panelStyle)
23
+ this.syncCreative(this.properties.creative)
24
+ },
25
+ detached() {
26
+ this.clearReadyTimer()
27
+ }
28
+ },
29
+ observers: {
30
+ creative(nextCreative) {
31
+ this.syncCreative(nextCreative)
32
+ },
33
+ panelStyle(nextPanelStyle) {
34
+ this.syncPanelStyle(nextPanelStyle)
35
+ }
36
+ },
37
+ methods: {
38
+ /**
39
+ * 同步半屏高度,输入值已经由统一入口限制在安全范围
40
+ * @param {Record<string, any> | null} panelStyle 标准化面板样式
41
+ * @returns {void}
42
+ */
43
+ syncPanelStyle(panelStyle) {
44
+ const heightRatio = Number(panelStyle && panelStyle.heightRatio)
45
+ this.setData({
46
+ panelHeight: Number.isFinite(heightRatio) ? Math.round(heightRatio * 100) : 68
47
+ })
48
+ },
49
+
50
+ /**
51
+ * 同步半屏素材状态
52
+ * @param {Record<string, string> | null} creative 标准化素材
53
+ * @returns {void}
54
+ */
55
+ syncCreative(creative) {
56
+ this.clearReadyTimer()
57
+ this.setData({ ready: false })
58
+
59
+ if (creative && creative.imageUrl) return
60
+
61
+ this.readyTimer = setTimeout(() => this.notifyReady('content'), 0)
62
+ },
63
+
64
+ /** 清理延迟就绪任务 */
65
+ clearReadyTimer() {
66
+ if (!this.readyTimer) return
67
+
68
+ clearTimeout(this.readyTimer)
69
+ this.readyTimer = null
70
+ },
71
+
72
+ /**
73
+ * 通知上层组件半屏已经可以展示
74
+ * @param {string} mediaType 素材类型
75
+ * @returns {void}
76
+ */
77
+ notifyReady(mediaType) {
78
+ if (this.data.ready) return
79
+
80
+ this.setData({ ready: true })
81
+ this.triggerEvent('ready', { mediaType })
82
+ },
83
+
84
+ /** 处理图片加载完成 */
85
+ handleImageLoad() {
86
+ this.notifyReady('image')
87
+ },
88
+
89
+ /**
90
+ * 处理图片加载失败
91
+ * @param {Record<string, any>} event 小程序图片错误事件
92
+ * @returns {void}
93
+ */
94
+ handleImageError(event) {
95
+ const rawDetail = event && event.detail || {}
96
+
97
+ this.triggerEvent('error', {
98
+ errCode: 'PRODUCT_PLACEMENT_HALF_SCREEN_IMAGE_LOAD_FAIL',
99
+ errMsg: '产品半屏图片加载失败',
100
+ errorType: 'MEDIA_LOAD_FAIL',
101
+ rawErrCode: rawDetail.errCode,
102
+ rawErrMsg: rawDetail.errMsg
103
+ })
104
+ },
105
+
106
+ /** 处理关闭按钮点击 */
107
+ handleClose() {
108
+ this.triggerEvent('close', { reason: 'closeButton' })
109
+ },
110
+
111
+ /** 处理遮罩关闭事件 */
112
+ handleMaskClose() {
113
+ this.triggerEvent('close', { reason: 'mask' })
114
+ },
115
+
116
+ /**
117
+ * 处理产品动作
118
+ * @param {Record<string, any>} event 点击事件
119
+ * @returns {void}
120
+ */
121
+ handleAction(event) {
122
+ if (!this.properties.actionable || this.properties.actionLoading) return
123
+
124
+ this.triggerEvent('action', {
125
+ source: event && event.currentTarget && event.currentTarget.dataset.source || 'button'
126
+ })
127
+ }
128
+ }
129
+ })