@haluo/util 2.0.33 → 2.1.0

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,368 @@
1
+ /**
2
+ * Track 埋点模块
3
+ * 统一封装各项目的埋点上报逻辑
4
+ *
5
+ * @example
6
+ * // 最简初始化(所有配置都有默认值)
7
+ * import { createTracker } from '@haluo/util/dist/modules/track'
8
+ *
9
+ * const tracker = createTracker({})
10
+ * // 或指定 appName
11
+ * const tracker2 = createTracker({ appName: 'emoto' })
12
+ *
13
+ * // 使用
14
+ * tracker.track('EVENT_ID', { key: 'value' })
15
+ * tracker.trackError({ err: 'error message' })
16
+ */
17
+ export * from './types';
18
+ /** 默认埋点上报URL */
19
+ const DEFAULT_LOG_URL = 'https://log-center.58moto.com/am/log/v1/json';
20
+ /** 默认应用名称 */
21
+ const DEFAULT_APP_NAME = 'moto';
22
+ /** 默认错误上报事件ID */
23
+ const ERROR_EVENT_ID = 'S_00000000000082';
24
+ /** 默认错误应用类型(H5异常) */
25
+ const DEFAULT_ERROR_APPTYPE = '2012';
26
+ /**
27
+ * 内置的简易 httpClient
28
+ * 使用 fetch 实现 POST 请求
29
+ */
30
+ const defaultHttpClient = {
31
+ post: (url, data) => {
32
+ if (typeof window === 'undefined' || !window.fetch) {
33
+ console.warn('[Tracker] 当前环境不支持 fetch');
34
+ return Promise.resolve();
35
+ }
36
+ // 构建 form-urlencoded 格式的请求体
37
+ const formBody = Object.keys(data)
38
+ .map(key => encodeURIComponent(key) + '=' + encodeURIComponent(data[key]))
39
+ .join('&');
40
+ return fetch(url, {
41
+ method: 'POST',
42
+ headers: {
43
+ 'Content-Type': 'application/x-www-form-urlencoded'
44
+ },
45
+ body: formBody
46
+ }).then(res => res.json()).catch(err => {
47
+ console.error('[Tracker] 埋点请求失败:', err);
48
+ });
49
+ }
50
+ };
51
+ /**
52
+ * 从 localStorage 安全获取并解析 JSON
53
+ */
54
+ function safeGetLocalStorage(key, defaultValue) {
55
+ try {
56
+ if (typeof window === 'undefined' || !window.localStorage) {
57
+ return defaultValue;
58
+ }
59
+ const value = window.localStorage.getItem(key);
60
+ if (!value || value === 'undefined') {
61
+ return defaultValue;
62
+ }
63
+ return JSON.parse(value);
64
+ }
65
+ catch {
66
+ return defaultValue;
67
+ }
68
+ }
69
+ /**
70
+ * 获取用户代理字符串
71
+ */
72
+ function getUserAgent() {
73
+ if (typeof window === 'undefined' || !window.navigator) {
74
+ return '';
75
+ }
76
+ return window.navigator.userAgent.toLowerCase();
77
+ }
78
+ /**
79
+ * 检测平台类型
80
+ */
81
+ function detectPlatform(ua) {
82
+ const isAndroid = ua.indexOf('android') > -1;
83
+ const isHarmonyos = ua.indexOf('harmonyos') > -1;
84
+ return isAndroid || isHarmonyos ? 'android' : 'ios';
85
+ }
86
+ /**
87
+ * 检测是否在客户端环境
88
+ */
89
+ function isClientEnv() {
90
+ return typeof window !== 'undefined' && !!window.isClient;
91
+ }
92
+ /**
93
+ * 检测是否为开发环境
94
+ */
95
+ function isDevelopment() {
96
+ return process.env.NODE_ENV === 'development';
97
+ }
98
+ /**
99
+ * 获取全局 AppCall 对象
100
+ */
101
+ function getGlobalAppCall() {
102
+ if (typeof window === 'undefined')
103
+ return null;
104
+ return window.AppCall || null;
105
+ }
106
+ /**
107
+ * 内置的 getChannel 方法
108
+ * 根据 UA 检测渠道:微信、QQ、微博等
109
+ */
110
+ function defaultGetChannel() {
111
+ if (typeof window === 'undefined' || !window.navigator) {
112
+ return 'other';
113
+ }
114
+ const ua = window.navigator.userAgent.toLowerCase();
115
+ const isAndroid = ua.indexOf('android') > -1;
116
+ // 区分出微信、QQ、微博平台、其他
117
+ if (ua.indexOf('micromessenger') > -1) {
118
+ // 在微信中打开
119
+ return 'weixin';
120
+ }
121
+ else if (ua.indexOf('weibo') > -1) {
122
+ // 在新浪微博客户端打开
123
+ return 'weibo';
124
+ }
125
+ else if (ua.indexOf(' qq') > -1 && ua.indexOf('mqqbrowser') < 0 && !isAndroid) {
126
+ // ios在QQ空间打开
127
+ return 'qq';
128
+ }
129
+ else if (ua.indexOf(' qq') > -1 && ua.indexOf('mqqbrowser') > -1 && isAndroid) {
130
+ // 安卓在QQ空间打开
131
+ return 'qq';
132
+ }
133
+ else {
134
+ // 使用 AppCall 获取包名,或返回 other
135
+ const appCall = getGlobalAppCall();
136
+ return appCall?.getAppPackage?.() || 'other';
137
+ }
138
+ }
139
+ /**
140
+ * Track 类
141
+ * 提供埋点上报功能
142
+ */
143
+ class Tracker {
144
+ config;
145
+ constructor(config) {
146
+ this.config = config;
147
+ }
148
+ /**
149
+ * 获取当前版本号
150
+ * 优先级:window.AppCall.getAppVersion() > 传入的 appCall > config.version
151
+ */
152
+ getVersion() {
153
+ const { version, appCall } = this.config;
154
+ // 优先使用全局 window.AppCall 获取版本号
155
+ const globalAppCall = getGlobalAppCall();
156
+ if (globalAppCall?.getAppVersion) {
157
+ const appVersion = globalAppCall.getAppVersion();
158
+ if (appVersion)
159
+ return appVersion;
160
+ }
161
+ // 其次使用传入的 appCall
162
+ if (appCall?.getAppVersion) {
163
+ const appVersion = appCall.getAppVersion();
164
+ if (appVersion)
165
+ return appVersion;
166
+ }
167
+ return version || '';
168
+ }
169
+ /**
170
+ * 获取渠道号
171
+ * 优先使用自定义 getChannel,否则使用内置的默认方法
172
+ */
173
+ getChannel() {
174
+ if (this.config.getChannel) {
175
+ return this.config.getChannel();
176
+ }
177
+ // 使用内置的 getChannel 方法
178
+ return defaultGetChannel();
179
+ }
180
+ /**
181
+ * 检查是否命中AB测试
182
+ */
183
+ checkAbTest(eId) {
184
+ if (!this.config.enableAbTest || !this.config.getAbFlags) {
185
+ return undefined;
186
+ }
187
+ try {
188
+ const abFlags = this.config.getAbFlags();
189
+ // 支持数组和对象两种格式
190
+ const flagList = Array.isArray(abFlags) ? abFlags : Object.values(abFlags);
191
+ return flagList.find(item => item?.indexList?.includes(eId));
192
+ }
193
+ catch {
194
+ return undefined;
195
+ }
196
+ }
197
+ /**
198
+ * 构建埋点请求数据
199
+ */
200
+ buildPostData(params) {
201
+ const { eId, eventContent } = params;
202
+ const deviceData = safeGetLocalStorage('deviceData', {});
203
+ const userData = safeGetLocalStorage('user', {});
204
+ const ua = getUserAgent();
205
+ const platform = detectPlatform(ua);
206
+ const isClient = isClientEnv();
207
+ return {
208
+ deviceid: deviceData.deviceId || '',
209
+ plateform: isClient ? platform : 'h5',
210
+ subplateform: 'h5',
211
+ version: this.getVersion(),
212
+ channel: this.getChannel(),
213
+ client: '',
214
+ os: '',
215
+ useragent: ua,
216
+ logs: [
217
+ {
218
+ uid: String(userData.uid || '0'),
219
+ eventid: eId,
220
+ eventcontent: eventContent || '{}',
221
+ begintime: Date.now(),
222
+ pmenu: '',
223
+ menu: '',
224
+ net: deviceData.network || '',
225
+ lon: '',
226
+ lat: '',
227
+ areacode: '',
228
+ address: ''
229
+ }
230
+ ]
231
+ };
232
+ }
233
+ /**
234
+ * 发送埋点请求
235
+ */
236
+ sendRequest(postData) {
237
+ const logUrl = this.config.logUrl || DEFAULT_LOG_URL;
238
+ const appName = this.config.appName || DEFAULT_APP_NAME;
239
+ // 优先使用传入的 httpClient,否则使用内置的默认实现
240
+ const httpClient = this.config.httpClient || defaultHttpClient;
241
+ return httpClient.post(logUrl, {
242
+ json: JSON.stringify(postData),
243
+ appName
244
+ });
245
+ }
246
+ /**
247
+ * 核心埋点方法
248
+ * @param params 埋点参数
249
+ */
250
+ async trackUser(params) {
251
+ const { eId, eventContent } = params;
252
+ // 开发环境不发送埋点
253
+ if (isDevelopment()) {
254
+ console.log('[Tracker] 开发环境,跳过埋点:', { eId, eventContent });
255
+ return Promise.resolve();
256
+ }
257
+ // 检查AB测试
258
+ if (this.config.enableAbTest) {
259
+ const abFlag = this.checkAbTest(eId);
260
+ if (abFlag?.test) {
261
+ // 优先使用全局 window.AppCall,其次使用传入的 appCall
262
+ const globalAppCall = getGlobalAppCall();
263
+ const appCall = globalAppCall || this.config.appCall;
264
+ if (appCall?.sendEventMsg) {
265
+ return appCall.sendEventMsg({ eId, eventContent: eventContent || '{}' });
266
+ }
267
+ }
268
+ }
269
+ // 构建并发送请求
270
+ const postData = this.buildPostData(params);
271
+ return this.sendRequest(postData);
272
+ }
273
+ /**
274
+ * 埋点上报
275
+ * @param eId 事件ID
276
+ * @param contentObj 事件内容对象
277
+ * @param isAbTest 是否AB测试(已废弃,保留兼容)
278
+ */
279
+ track(eId, contentObj = {}, isAbTest = false) {
280
+ return this.trackUser({
281
+ eId,
282
+ eventContent: JSON.stringify(contentObj),
283
+ isAbTest
284
+ });
285
+ }
286
+ /**
287
+ * 错误上报
288
+ * @param contentObj 错误内容对象
289
+ */
290
+ trackError(contentObj = {}) {
291
+ const errorContent = {
292
+ err: contentObj.err || '',
293
+ apptype: contentObj.apptype || DEFAULT_ERROR_APPTYPE,
294
+ url: contentObj.url || (typeof window !== 'undefined' ? window.location?.href : '') || '',
295
+ platform: contentObj.platform || 'wap',
296
+ ...contentObj
297
+ };
298
+ return this.trackUser({
299
+ eId: ERROR_EVENT_ID,
300
+ eventContent: JSON.stringify(errorContent)
301
+ });
302
+ }
303
+ /**
304
+ * 更新配置
305
+ */
306
+ updateConfig(config) {
307
+ this.config = { ...this.config, ...config };
308
+ }
309
+ /**
310
+ * 获取当前配置
311
+ */
312
+ getConfig() {
313
+ return { ...this.config };
314
+ }
315
+ }
316
+ /**
317
+ * 创建 Tracker 实例
318
+ * @param config 配置项
319
+ * @returns Tracker 实例
320
+ *
321
+ * @example
322
+ * const tracker = createTracker({
323
+ * appName: 'emoto'
324
+ * // logUrl 可选,默认: https://log-center.58moto.com/am/log/v1/json
325
+ * // httpClient 可选,默认使用内置 fetch 实现
326
+ * })
327
+ *
328
+ * // 普通埋点
329
+ * tracker.track('EVENT_001', { page: 'home' })
330
+ *
331
+ * // 错误上报
332
+ * tracker.trackError({ err: 'Something went wrong' })
333
+ */
334
+ export function createTracker(config) {
335
+ return new Tracker(config);
336
+ }
337
+ /**
338
+ * 创建简化版埋点方法
339
+ * 返回 postTrack 和 postTrackError 方法,与原有项目用法一致
340
+ *
341
+ * @example
342
+ * const { postTrack, postTrackError } = createTrackMethods({
343
+ * appName: 'moto'
344
+ * })
345
+ *
346
+ * // 等同于原来的 postJddTrack
347
+ * postTrack('EVENT_001', { page: 'home' })
348
+ *
349
+ * // 等同于原来的 postJddTrackError
350
+ * postTrackError({ err: 'error message' })
351
+ */
352
+ export function createTrackMethods(config) {
353
+ const tracker = createTracker(config);
354
+ return {
355
+ /** 埋点上报方法 */
356
+ postTrack: (eId, contentObj = {}, isAbTest = false) => {
357
+ return tracker.track(eId, contentObj, isAbTest);
358
+ },
359
+ /** 错误上报方法 */
360
+ postTrackError: (contentObj = {}) => {
361
+ return tracker.trackError(contentObj);
362
+ },
363
+ /** Tracker 实例 */
364
+ tracker
365
+ };
366
+ }
367
+ export { defaultGetChannel as getChannel };
368
+ export default createTracker;
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Track 模块类型定义
3
+ */
4
+ /** 应用名称类型 */
5
+ export type AppName = 'emoto' | 'moto' | 'watch' | 'drone' | string;
6
+ /** 平台类型 */
7
+ export type Platform = 'android' | 'ios' | 'h5' | 'wap';
8
+ /** Track 初始化配置 */
9
+ export interface TrackConfig {
10
+ /** 应用名称,如 'emoto', 'moto', 'watch',默认: 'moto' */
11
+ appName?: AppName;
12
+ /** 埋点上报URL,默认: https://log-center.58moto.com/am/log/v1/json */
13
+ logUrl?: string;
14
+ /** 应用版本号 */
15
+ version?: string;
16
+ /** HTTP请求方法,需要支持 post(url, data) 形式 */
17
+ httpClient?: HttpClient;
18
+ /** 获取渠道号的方法 */
19
+ getChannel?: () => string;
20
+ /** AppCall实例(用于AB测试等场景) */
21
+ appCall?: AppCallInterface;
22
+ /** 是否启用AB测试逻辑 */
23
+ enableAbTest?: boolean;
24
+ /** 获取当前AB测试标记的方法 */
25
+ getAbFlags?: () => AbFlag[] | Record<string, AbFlag>;
26
+ }
27
+ /** HTTP客户端接口 */
28
+ export interface HttpClient {
29
+ post: (url: string, data: any) => Promise<any>;
30
+ }
31
+ /** AppCall接口(可选) */
32
+ export interface AppCallInterface {
33
+ getAppVersion?: () => string;
34
+ sendEventMsg?: (data: {
35
+ eId: string;
36
+ eventContent: string;
37
+ }) => Promise<any>;
38
+ }
39
+ /** AB测试标记 */
40
+ export interface AbFlag {
41
+ indexList: string[];
42
+ test?: boolean;
43
+ [key: string]: any;
44
+ }
45
+ /** 设备数据 */
46
+ export interface DeviceData {
47
+ deviceId?: string;
48
+ network?: string;
49
+ [key: string]: any;
50
+ }
51
+ /** 用户数据 */
52
+ export interface UserData {
53
+ uid?: string | number;
54
+ [key: string]: any;
55
+ }
56
+ /** 位置数据 */
57
+ export interface PositionData {
58
+ lng?: string | number;
59
+ lat?: string | number;
60
+ [key: string]: any;
61
+ }
62
+ /** 单条日志数据 */
63
+ export interface LogItem {
64
+ uid: string;
65
+ eventid: string;
66
+ eventcontent: string;
67
+ begintime: number;
68
+ pmenu: string;
69
+ menu: string;
70
+ net: string;
71
+ lon: string;
72
+ lat: string;
73
+ areacode: string;
74
+ address: string;
75
+ }
76
+ /** 埋点请求数据 */
77
+ export interface TrackPostData {
78
+ deviceid: string;
79
+ plateform: Platform;
80
+ subplateform: string;
81
+ version: string;
82
+ channel: string;
83
+ client: string;
84
+ os: string;
85
+ useragent: string;
86
+ logs: LogItem[];
87
+ }
88
+ /** 埋点参数 */
89
+ export interface TrackParams {
90
+ /** 事件ID */
91
+ eId: string;
92
+ /** 事件内容(JSON字符串) */
93
+ eventContent?: string;
94
+ /** 是否使用AB测试上报 */
95
+ isAbTest?: boolean;
96
+ }
97
+ /** 错误上报内容 */
98
+ export interface ErrorContent {
99
+ /** 错误信息 */
100
+ err: string;
101
+ /** 应用类型 */
102
+ apptype?: string;
103
+ /** 页面URL */
104
+ url?: string;
105
+ /** 平台 */
106
+ platform?: string;
107
+ [key: string]: any;
108
+ }
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Track 模块类型定义
3
+ */
4
+ export {};
@@ -14,7 +14,10 @@
14
14
  * darkWaterUploadImage: (params) => api.darkWaterUploadImage(params),
15
15
  * multiTransferImage: (params) => api.multiTransferImage(params),
16
16
  * generatePrePresignedUrl: (params) => api.generatePrePresignedUrl(params),
17
- * messageWarning: (msg) => window.$message.warning(msg)
17
+ * messageWarning: (msg) => window.$message.warning(msg),
18
+ * // 可选:开启错误上报
19
+ * enableErrorReport: true,
20
+ * appName: 'emoto'
18
21
  * })
19
22
  *
20
23
  * // 图片上传
@@ -41,6 +44,7 @@
41
44
  * })
42
45
  * ```
43
46
  */
47
+ import type { TrackConfig } from '../track';
44
48
  /**
45
49
  * 业务类型枚举
46
50
  */
@@ -164,6 +168,10 @@ interface ApiResponse<T = any> {
164
168
  * 业务相关的API通过此接口传入,实现业务逻辑解耦
165
169
  */
166
170
  export interface AliOssApiConfig {
171
+ /** 应用名称,用于错误上报 */
172
+ appName?: TrackConfig['appName'];
173
+ /** 是否启用错误上报,默认 false */
174
+ enableErrorReport?: boolean;
167
175
  /** 获取STS,POST V4签名独有的表单元素- 必需 */
168
176
  /** businessType: 业务编码(必传), docType: 文件格式如png(必传),size: _1024_567(可选) */
169
177
  getSts: (params: {
@@ -194,8 +202,15 @@ export interface AliOssApiConfig {
194
202
  export declare class AliOssClass {
195
203
  private static instance;
196
204
  private apiConfig;
205
+ private tracker;
197
206
  private constructor();
198
207
  static getInstance(apiConfig: AliOssApiConfig): AliOssClass;
208
+ /**
209
+ * 上报上传错误
210
+ * @param err 错误信息
211
+ * @param extra 额外信息
212
+ */
213
+ private reportError;
199
214
  /**
200
215
  * 判断文件是否为图片(支持常见图片格式)
201
216
  * @param {File} file - 上传的File对象
@@ -14,7 +14,10 @@
14
14
  * darkWaterUploadImage: (params) => api.darkWaterUploadImage(params),
15
15
  * multiTransferImage: (params) => api.multiTransferImage(params),
16
16
  * generatePrePresignedUrl: (params) => api.generatePrePresignedUrl(params),
17
- * messageWarning: (msg) => window.$message.warning(msg)
17
+ * messageWarning: (msg) => window.$message.warning(msg),
18
+ * // 可选:开启错误上报
19
+ * enableErrorReport: true,
20
+ * appName: 'emoto'
18
21
  * })
19
22
  *
20
23
  * // 图片上传
@@ -42,6 +45,7 @@
42
45
  * ```
43
46
  */
44
47
  import lrz from 'lrz';
48
+ import { createTracker } from '../track';
45
49
  // ==================== 常量定义 ====================
46
50
  /** 支持的图片格式 */
47
51
  const SUPPORTED_IMAGE_TYPES = [
@@ -187,8 +191,15 @@ function getFileSizeInMB(size) {
187
191
  export class AliOssClass {
188
192
  static instance = null;
189
193
  apiConfig;
194
+ tracker = null;
190
195
  constructor(apiConfig) {
191
196
  this.apiConfig = apiConfig;
197
+ // 只有启用错误上报时才创建 tracker 实例
198
+ if (apiConfig.enableErrorReport) {
199
+ this.tracker = createTracker({
200
+ appName: apiConfig.appName
201
+ });
202
+ }
192
203
  }
193
204
  static getInstance(apiConfig) {
194
205
  if (!AliOssClass.instance) {
@@ -196,6 +207,22 @@ export class AliOssClass {
196
207
  }
197
208
  return AliOssClass.instance;
198
209
  }
210
+ /**
211
+ * 上报上传错误
212
+ * @param err 错误信息
213
+ * @param extra 额外信息
214
+ */
215
+ reportError(err, extra) {
216
+ // 只有启用错误上报且 tracker 存在时才上报
217
+ if (!this.apiConfig.enableErrorReport || !this.tracker) {
218
+ return;
219
+ }
220
+ this.tracker.trackError({
221
+ err: err,
222
+ apptype: '10003',
223
+ ...extra
224
+ });
225
+ }
199
226
  /**
200
227
  * 判断文件是否为图片(支持常见图片格式)
201
228
  * @param {File} file - 上传的File对象
@@ -238,10 +265,12 @@ export class AliOssClass {
238
265
  size: size, // _1024_567(可选)
239
266
  });
240
267
  if (signResponse.data.code !== 0) {
241
- const errorMessage = `获取签名失败:${signResponse.data.message}`;
268
+ const errorMessage = `获取签名失败:${signResponse.data.message || signResponse.data.msg}`;
242
269
  callbacks?.onError(errorMessage);
243
270
  reject && reject(errorMessage);
244
271
  console.error(errorMessage);
272
+ this.reportError(errorMessage, { type: 'getSts', businessType, code: signResponse.data.code });
273
+ return result;
245
274
  }
246
275
  const signData = await signResponse.data.data;
247
276
  // console.log('后端返回的签名字段:', signData)
@@ -285,12 +314,15 @@ export class AliOssClass {
285
314
  callbacks?.onError(errorMessage);
286
315
  reject && reject(errorMessage);
287
316
  console.error(errorMessage);
317
+ this.reportError(errorMessage, { type: 'ossUpload', businessType, status: uploadResponse.status });
288
318
  }
289
319
  }
290
320
  catch (err) {
291
- callbacks?.onError(err.message);
292
- reject && reject(err.message);
293
- console.error('上传异常:', err.message);
321
+ const errMsg = err.message || err.msg || '上传异常';
322
+ callbacks?.onError(errMsg);
323
+ reject && reject(errMsg);
324
+ console.error('上传异常:', errMsg);
325
+ this.reportError(errMsg, { type: 'ossUploadException', businessType });
294
326
  }
295
327
  return result;
296
328
  }
@@ -417,6 +449,7 @@ export class AliOssClass {
417
449
  else {
418
450
  callbacks.onError('上传失败');
419
451
  reject('上传失败');
452
+ this.reportError('批量转换水印上传失败', { type: 'batchTransfer', businessType });
420
453
  }
421
454
  return;
422
455
  }
@@ -437,6 +470,7 @@ export class AliOssClass {
437
470
  else {
438
471
  callbacks.onError('上传失败');
439
472
  reject('上传失败');
473
+ this.reportError('暗水印上传失败', { type: 'darkWater', businessType });
440
474
  }
441
475
  return;
442
476
  }
@@ -496,14 +530,16 @@ export class AliOssClass {
496
530
  else {
497
531
  callbacks.onError('生成预签名URL失败');
498
532
  reject('生成预签名URL失败');
533
+ this.reportError('生成预签名URL失败', { type: 'preSignedUrl', businessType });
499
534
  }
500
535
  return;
501
536
  }
502
537
  }
503
538
  catch (error) {
504
- const errorMsg = error.message || '上传异常';
539
+ const errorMsg = error.message || error.msg || '上传异常';
505
540
  callbacks.onError(errorMsg);
506
541
  reject(errorMsg);
542
+ this.reportError(errorMsg, { type: 'ossUploadImage', businessType: option.businessType });
507
543
  }
508
544
  });
509
545
  };
@@ -542,9 +578,10 @@ export class AliOssClass {
542
578
  });
543
579
  }
544
580
  catch (error) {
545
- const errorMsg = error.message || '上传异常';
581
+ const errorMsg = error.message || error.msg || '上传异常';
546
582
  callbacks.onError(errorMsg);
547
583
  reject(errorMsg);
584
+ this.reportError(errorMsg, { type: 'ossUploadFile', businessType: option.businessType });
548
585
  }
549
586
  });
550
587
  };
@@ -605,9 +642,10 @@ export class AliOssClass {
605
642
  });
606
643
  }
607
644
  catch (error) {
608
- const errorMsg = error.message || '上传异常';
645
+ const errorMsg = error.message || error.msg || '上传异常';
609
646
  callbacks.onError(errorMsg);
610
647
  reject(errorMsg);
648
+ this.reportError(errorMsg, { type: 'pureOssUploadImage', businessType: option.businessType });
611
649
  }
612
650
  });
613
651
  };