@haluo/util 2.0.33 → 2.0.35
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/dist/index.d.ts +3 -0
- package/dist/index.js +23 -19
- package/dist/modules/app-call/configs.d.ts +9 -0
- package/dist/modules/app-call/configs.js +44 -0
- package/dist/modules/app-call/core.d.ts +53 -0
- package/dist/modules/app-call/core.js +175 -0
- package/dist/modules/app-call/extensions.d.ts +187 -0
- package/dist/modules/app-call/extensions.js +1297 -0
- package/dist/modules/app-call/index.d.ts +16 -0
- package/dist/modules/app-call/index.js +84 -0
- package/dist/modules/app-call/offline.d.ts +12 -0
- package/dist/modules/app-call/offline.js +191 -0
- package/dist/modules/app-call/types.d.ts +67 -0
- package/dist/modules/app-call/types.js +4 -0
- package/dist/modules/cookie/index.js +22 -17
- package/dist/modules/date/index.js +54 -48
- package/dist/modules/dom/index.js +21 -15
- package/dist/modules/filter/index.js +14 -8
- package/dist/modules/format/index.js +9 -5
- package/dist/modules/match/index.js +8 -5
- package/dist/modules/monitor/lib/jsError.js +27 -38
- package/dist/modules/monitor/lib/timing.js +15 -17
- package/dist/modules/monitor/lib/xhr.js +26 -25
- package/dist/modules/monitor/utils/tracker.js +22 -10
- package/dist/modules/number/index.js +33 -30
- package/dist/modules/open-app/index.d.ts +3 -7
- package/dist/modules/open-app/index.js +55 -63
- package/dist/modules/sentry/index.js +16 -12
- package/dist/modules/tools/index.js +164 -154
- package/dist/modules/track/index.d.ts +122 -0
- package/dist/modules/track/index.js +421 -0
- package/dist/modules/track/types.d.ts +108 -0
- package/dist/modules/track/types.js +4 -0
- package/dist/modules/upload/aliOss.d.ts +52 -5
- package/dist/modules/upload/aliOss.js +589 -378
- package/dist/modules/upload/index.js +32 -29
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +27 -2
|
@@ -0,0 +1,421 @@
|
|
|
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
|
+
var __assign = (this && this.__assign) || function () {
|
|
18
|
+
__assign = Object.assign || function(t) {
|
|
19
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
20
|
+
s = arguments[i];
|
|
21
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
22
|
+
t[p] = s[p];
|
|
23
|
+
}
|
|
24
|
+
return t;
|
|
25
|
+
};
|
|
26
|
+
return __assign.apply(this, arguments);
|
|
27
|
+
};
|
|
28
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
29
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
30
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
31
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
32
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
33
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
34
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
38
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
39
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
40
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
41
|
+
function step(op) {
|
|
42
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
43
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
44
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
45
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
46
|
+
switch (op[0]) {
|
|
47
|
+
case 0: case 1: t = op; break;
|
|
48
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
49
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
50
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
51
|
+
default:
|
|
52
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
53
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
54
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
55
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
56
|
+
if (t[2]) _.ops.pop();
|
|
57
|
+
_.trys.pop(); continue;
|
|
58
|
+
}
|
|
59
|
+
op = body.call(thisArg, _);
|
|
60
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
61
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
export * from './types';
|
|
65
|
+
/** 默认埋点上报URL */
|
|
66
|
+
var DEFAULT_LOG_URL = 'https://log-center.58moto.com/am/log/v1/json';
|
|
67
|
+
/** 默认应用名称 */
|
|
68
|
+
var DEFAULT_APP_NAME = 'moto';
|
|
69
|
+
/** 默认错误上报事件ID */
|
|
70
|
+
var ERROR_EVENT_ID = 'S_00000000000082';
|
|
71
|
+
/** 默认错误应用类型(H5异常) */
|
|
72
|
+
var DEFAULT_ERROR_APPTYPE = '2012';
|
|
73
|
+
/**
|
|
74
|
+
* 内置的简易 httpClient
|
|
75
|
+
* 使用 fetch 实现 POST 请求
|
|
76
|
+
*/
|
|
77
|
+
var defaultHttpClient = {
|
|
78
|
+
post: function (url, data) {
|
|
79
|
+
if (typeof window === 'undefined' || !window.fetch) {
|
|
80
|
+
console.warn('[Tracker] 当前环境不支持 fetch');
|
|
81
|
+
return Promise.resolve();
|
|
82
|
+
}
|
|
83
|
+
// 构建 form-urlencoded 格式的请求体
|
|
84
|
+
var formBody = Object.keys(data)
|
|
85
|
+
.map(function (key) { return encodeURIComponent(key) + '=' + encodeURIComponent(data[key]); })
|
|
86
|
+
.join('&');
|
|
87
|
+
return fetch(url, {
|
|
88
|
+
method: 'POST',
|
|
89
|
+
headers: {
|
|
90
|
+
'Content-Type': 'application/x-www-form-urlencoded'
|
|
91
|
+
},
|
|
92
|
+
body: formBody
|
|
93
|
+
}).then(function (res) { return res.json(); }).catch(function (err) {
|
|
94
|
+
console.error('[Tracker] 埋点请求失败:', err);
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
/**
|
|
99
|
+
* 从 localStorage 安全获取并解析 JSON
|
|
100
|
+
*/
|
|
101
|
+
function safeGetLocalStorage(key, defaultValue) {
|
|
102
|
+
try {
|
|
103
|
+
if (typeof window === 'undefined' || !window.localStorage) {
|
|
104
|
+
return defaultValue;
|
|
105
|
+
}
|
|
106
|
+
var value = window.localStorage.getItem(key);
|
|
107
|
+
if (!value || value === 'undefined') {
|
|
108
|
+
return defaultValue;
|
|
109
|
+
}
|
|
110
|
+
return JSON.parse(value);
|
|
111
|
+
}
|
|
112
|
+
catch (_a) {
|
|
113
|
+
return defaultValue;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* 获取用户代理字符串
|
|
118
|
+
*/
|
|
119
|
+
function getUserAgent() {
|
|
120
|
+
if (typeof window === 'undefined' || !window.navigator) {
|
|
121
|
+
return '';
|
|
122
|
+
}
|
|
123
|
+
return window.navigator.userAgent.toLowerCase();
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* 检测平台类型
|
|
127
|
+
*/
|
|
128
|
+
function detectPlatform(ua) {
|
|
129
|
+
var isAndroid = ua.indexOf('android') > -1;
|
|
130
|
+
var isHarmonyos = ua.indexOf('harmonyos') > -1;
|
|
131
|
+
return isAndroid || isHarmonyos ? 'android' : 'ios';
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* 检测是否在客户端环境
|
|
135
|
+
*/
|
|
136
|
+
function isClientEnv() {
|
|
137
|
+
return typeof window !== 'undefined' && !!window.isClient;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* 检测是否为开发环境
|
|
141
|
+
*/
|
|
142
|
+
function isDevelopment() {
|
|
143
|
+
return process.env.NODE_ENV === 'development';
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* 获取全局 AppCall 对象
|
|
147
|
+
*/
|
|
148
|
+
function getGlobalAppCall() {
|
|
149
|
+
if (typeof window === 'undefined')
|
|
150
|
+
return null;
|
|
151
|
+
return window.AppCall || null;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* 内置的 getChannel 方法
|
|
155
|
+
* 根据 UA 检测渠道:微信、QQ、微博等
|
|
156
|
+
*/
|
|
157
|
+
function defaultGetChannel() {
|
|
158
|
+
var _a;
|
|
159
|
+
if (typeof window === 'undefined' || !window.navigator) {
|
|
160
|
+
return 'other';
|
|
161
|
+
}
|
|
162
|
+
var ua = window.navigator.userAgent.toLowerCase();
|
|
163
|
+
var isAndroid = ua.indexOf('android') > -1;
|
|
164
|
+
// 区分出微信、QQ、微博平台、其他
|
|
165
|
+
if (ua.indexOf('micromessenger') > -1) {
|
|
166
|
+
// 在微信中打开
|
|
167
|
+
return 'weixin';
|
|
168
|
+
}
|
|
169
|
+
else if (ua.indexOf('weibo') > -1) {
|
|
170
|
+
// 在新浪微博客户端打开
|
|
171
|
+
return 'weibo';
|
|
172
|
+
}
|
|
173
|
+
else if (ua.indexOf(' qq') > -1 && ua.indexOf('mqqbrowser') < 0 && !isAndroid) {
|
|
174
|
+
// ios在QQ空间打开
|
|
175
|
+
return 'qq';
|
|
176
|
+
}
|
|
177
|
+
else if (ua.indexOf(' qq') > -1 && ua.indexOf('mqqbrowser') > -1 && isAndroid) {
|
|
178
|
+
// 安卓在QQ空间打开
|
|
179
|
+
return 'qq';
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
// 使用 AppCall 获取包名,或返回 other
|
|
183
|
+
var appCall = getGlobalAppCall();
|
|
184
|
+
return ((_a = appCall === null || appCall === void 0 ? void 0 : appCall.getAppPackage) === null || _a === void 0 ? void 0 : _a.call(appCall)) || 'other';
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Track 类
|
|
189
|
+
* 提供埋点上报功能
|
|
190
|
+
*/
|
|
191
|
+
var Tracker = /** @class */ (function () {
|
|
192
|
+
function Tracker(config) {
|
|
193
|
+
this.config = config;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* 获取当前版本号
|
|
197
|
+
* 优先级:window.AppCall.getAppVersion() > 传入的 appCall > config.version
|
|
198
|
+
*/
|
|
199
|
+
Tracker.prototype.getVersion = function () {
|
|
200
|
+
var _a = this.config, version = _a.version, appCall = _a.appCall;
|
|
201
|
+
// 优先使用全局 window.AppCall 获取版本号
|
|
202
|
+
var globalAppCall = getGlobalAppCall();
|
|
203
|
+
if (globalAppCall === null || globalAppCall === void 0 ? void 0 : globalAppCall.getAppVersion) {
|
|
204
|
+
var appVersion = globalAppCall.getAppVersion();
|
|
205
|
+
if (appVersion)
|
|
206
|
+
return appVersion;
|
|
207
|
+
}
|
|
208
|
+
// 其次使用传入的 appCall
|
|
209
|
+
if (appCall === null || appCall === void 0 ? void 0 : appCall.getAppVersion) {
|
|
210
|
+
var appVersion = appCall.getAppVersion();
|
|
211
|
+
if (appVersion)
|
|
212
|
+
return appVersion;
|
|
213
|
+
}
|
|
214
|
+
return version || '';
|
|
215
|
+
};
|
|
216
|
+
/**
|
|
217
|
+
* 获取渠道号
|
|
218
|
+
* 优先使用自定义 getChannel,否则使用内置的默认方法
|
|
219
|
+
*/
|
|
220
|
+
Tracker.prototype.getChannel = function () {
|
|
221
|
+
if (this.config.getChannel) {
|
|
222
|
+
return this.config.getChannel();
|
|
223
|
+
}
|
|
224
|
+
// 使用内置的 getChannel 方法
|
|
225
|
+
return defaultGetChannel();
|
|
226
|
+
};
|
|
227
|
+
/**
|
|
228
|
+
* 检查是否命中AB测试
|
|
229
|
+
*/
|
|
230
|
+
Tracker.prototype.checkAbTest = function (eId) {
|
|
231
|
+
if (!this.config.enableAbTest || !this.config.getAbFlags) {
|
|
232
|
+
return undefined;
|
|
233
|
+
}
|
|
234
|
+
try {
|
|
235
|
+
var abFlags = this.config.getAbFlags();
|
|
236
|
+
// 支持数组和对象两种格式
|
|
237
|
+
var flagList = Array.isArray(abFlags) ? abFlags : Object.values(abFlags);
|
|
238
|
+
return flagList.find(function (item) { var _a; return (_a = item === null || item === void 0 ? void 0 : item.indexList) === null || _a === void 0 ? void 0 : _a.includes(eId); });
|
|
239
|
+
}
|
|
240
|
+
catch (_a) {
|
|
241
|
+
return undefined;
|
|
242
|
+
}
|
|
243
|
+
};
|
|
244
|
+
/**
|
|
245
|
+
* 构建埋点请求数据
|
|
246
|
+
*/
|
|
247
|
+
Tracker.prototype.buildPostData = function (params) {
|
|
248
|
+
var eId = params.eId, eventContent = params.eventContent;
|
|
249
|
+
var deviceData = safeGetLocalStorage('deviceData', {});
|
|
250
|
+
var userData = safeGetLocalStorage('user', {});
|
|
251
|
+
var ua = getUserAgent();
|
|
252
|
+
var platform = detectPlatform(ua);
|
|
253
|
+
var isClient = isClientEnv();
|
|
254
|
+
return {
|
|
255
|
+
deviceid: deviceData.deviceId || '',
|
|
256
|
+
plateform: isClient ? platform : 'h5',
|
|
257
|
+
subplateform: 'h5',
|
|
258
|
+
version: this.getVersion(),
|
|
259
|
+
channel: this.getChannel(),
|
|
260
|
+
client: '',
|
|
261
|
+
os: '',
|
|
262
|
+
useragent: ua,
|
|
263
|
+
logs: [
|
|
264
|
+
{
|
|
265
|
+
uid: String(userData.uid || '0'),
|
|
266
|
+
eventid: eId,
|
|
267
|
+
eventcontent: eventContent || '{}',
|
|
268
|
+
begintime: Date.now(),
|
|
269
|
+
pmenu: '',
|
|
270
|
+
menu: '',
|
|
271
|
+
net: deviceData.network || '',
|
|
272
|
+
lon: '',
|
|
273
|
+
lat: '',
|
|
274
|
+
areacode: '',
|
|
275
|
+
address: ''
|
|
276
|
+
}
|
|
277
|
+
]
|
|
278
|
+
};
|
|
279
|
+
};
|
|
280
|
+
/**
|
|
281
|
+
* 发送埋点请求
|
|
282
|
+
*/
|
|
283
|
+
Tracker.prototype.sendRequest = function (postData) {
|
|
284
|
+
var _a, _b;
|
|
285
|
+
var logUrl = this.config.logUrl || DEFAULT_LOG_URL;
|
|
286
|
+
var appName = this.config.appName || DEFAULT_APP_NAME;
|
|
287
|
+
// 优先使用传入的 httpClient,否则使用内置的默认实现
|
|
288
|
+
var httpClient = ((_b = (_a = this.config).httpClient) === null || _b === void 0 ? void 0 : _b.call(_a)) || defaultHttpClient;
|
|
289
|
+
return httpClient.post(logUrl, {
|
|
290
|
+
json: JSON.stringify(postData),
|
|
291
|
+
appName: appName
|
|
292
|
+
});
|
|
293
|
+
};
|
|
294
|
+
/**
|
|
295
|
+
* 核心埋点方法
|
|
296
|
+
* @param params 埋点参数
|
|
297
|
+
*/
|
|
298
|
+
Tracker.prototype.trackUser = function (params) {
|
|
299
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
300
|
+
var eId, eventContent, abFlag, globalAppCall, appCall, postData;
|
|
301
|
+
return __generator(this, function (_a) {
|
|
302
|
+
eId = params.eId, eventContent = params.eventContent;
|
|
303
|
+
// 开发环境不发送埋点
|
|
304
|
+
if (isDevelopment()) {
|
|
305
|
+
console.log('[Tracker] 开发环境,跳过埋点:', { eId: eId, eventContent: eventContent });
|
|
306
|
+
return [2 /*return*/, Promise.resolve()];
|
|
307
|
+
}
|
|
308
|
+
// 检查AB测试
|
|
309
|
+
if (this.config.enableAbTest) {
|
|
310
|
+
abFlag = this.checkAbTest(eId);
|
|
311
|
+
if (abFlag === null || abFlag === void 0 ? void 0 : abFlag.test) {
|
|
312
|
+
globalAppCall = getGlobalAppCall();
|
|
313
|
+
appCall = globalAppCall || this.config.appCall;
|
|
314
|
+
if (appCall === null || appCall === void 0 ? void 0 : appCall.sendEventMsg) {
|
|
315
|
+
return [2 /*return*/, appCall.sendEventMsg({ eId: eId, eventContent: eventContent || '{}' })];
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
postData = this.buildPostData(params);
|
|
320
|
+
return [2 /*return*/, this.sendRequest(postData)];
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
};
|
|
324
|
+
/**
|
|
325
|
+
* 埋点上报
|
|
326
|
+
* @param eId 事件ID
|
|
327
|
+
* @param contentObj 事件内容对象
|
|
328
|
+
* @param isAbTest 是否AB测试(已废弃,保留兼容)
|
|
329
|
+
*/
|
|
330
|
+
Tracker.prototype.track = function (eId, contentObj, isAbTest) {
|
|
331
|
+
if (contentObj === void 0) { contentObj = {}; }
|
|
332
|
+
if (isAbTest === void 0) { isAbTest = false; }
|
|
333
|
+
return this.trackUser({
|
|
334
|
+
eId: eId,
|
|
335
|
+
eventContent: JSON.stringify(contentObj),
|
|
336
|
+
isAbTest: isAbTest
|
|
337
|
+
});
|
|
338
|
+
};
|
|
339
|
+
/**
|
|
340
|
+
* 错误上报
|
|
341
|
+
* @param contentObj 错误内容对象
|
|
342
|
+
*/
|
|
343
|
+
Tracker.prototype.trackError = function (contentObj) {
|
|
344
|
+
var _a;
|
|
345
|
+
if (contentObj === void 0) { contentObj = {}; }
|
|
346
|
+
var errorContent = __assign({ err: contentObj.err || '', apptype: contentObj.apptype || DEFAULT_ERROR_APPTYPE, url: contentObj.url || (typeof window !== 'undefined' ? (_a = window.location) === null || _a === void 0 ? void 0 : _a.href : '') || '', platform: contentObj.platform || 'wap' }, contentObj);
|
|
347
|
+
return this.trackUser({
|
|
348
|
+
eId: ERROR_EVENT_ID,
|
|
349
|
+
eventContent: JSON.stringify(errorContent)
|
|
350
|
+
});
|
|
351
|
+
};
|
|
352
|
+
/**
|
|
353
|
+
* 更新配置
|
|
354
|
+
*/
|
|
355
|
+
Tracker.prototype.updateConfig = function (config) {
|
|
356
|
+
this.config = __assign(__assign({}, this.config), config);
|
|
357
|
+
};
|
|
358
|
+
/**
|
|
359
|
+
* 获取当前配置
|
|
360
|
+
*/
|
|
361
|
+
Tracker.prototype.getConfig = function () {
|
|
362
|
+
return __assign({}, this.config);
|
|
363
|
+
};
|
|
364
|
+
return Tracker;
|
|
365
|
+
}());
|
|
366
|
+
/**
|
|
367
|
+
* 创建 Tracker 实例
|
|
368
|
+
* @param config 配置项
|
|
369
|
+
* @returns Tracker 实例
|
|
370
|
+
*
|
|
371
|
+
* @example
|
|
372
|
+
* const tracker = createTracker({
|
|
373
|
+
* appName: 'emoto'
|
|
374
|
+
* // logUrl 可选,默认: https://log-center.58moto.com/am/log/v1/json
|
|
375
|
+
* // httpClient 可选,默认使用内置 fetch 实现
|
|
376
|
+
* })
|
|
377
|
+
*
|
|
378
|
+
* // 普通埋点
|
|
379
|
+
* tracker.track('EVENT_001', { page: 'home' })
|
|
380
|
+
*
|
|
381
|
+
* // 错误上报
|
|
382
|
+
* tracker.trackError({ err: 'Something went wrong' })
|
|
383
|
+
*/
|
|
384
|
+
export function createTracker(config) {
|
|
385
|
+
return new Tracker(config);
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* 创建简化版埋点方法
|
|
389
|
+
* 返回 postTrack 和 postTrackError 方法,与原有项目用法一致
|
|
390
|
+
*
|
|
391
|
+
* @example
|
|
392
|
+
* const { postTrack, postTrackError } = createTrackMethods({
|
|
393
|
+
* appName: 'moto'
|
|
394
|
+
* })
|
|
395
|
+
*
|
|
396
|
+
* // 等同于原来的 postJddTrack
|
|
397
|
+
* postTrack('EVENT_001', { page: 'home' })
|
|
398
|
+
*
|
|
399
|
+
* // 等同于原来的 postJddTrackError
|
|
400
|
+
* postTrackError({ err: 'error message' })
|
|
401
|
+
*/
|
|
402
|
+
export function createTrackMethods(config) {
|
|
403
|
+
var tracker = createTracker(config);
|
|
404
|
+
return {
|
|
405
|
+
/** 埋点上报方法 */
|
|
406
|
+
postTrack: function (eId, contentObj, isAbTest) {
|
|
407
|
+
if (contentObj === void 0) { contentObj = {}; }
|
|
408
|
+
if (isAbTest === void 0) { isAbTest = false; }
|
|
409
|
+
return tracker.track(eId, contentObj, isAbTest);
|
|
410
|
+
},
|
|
411
|
+
/** 错误上报方法 */
|
|
412
|
+
postTrackError: function (contentObj) {
|
|
413
|
+
if (contentObj === void 0) { contentObj = {}; }
|
|
414
|
+
return tracker.trackError(contentObj);
|
|
415
|
+
},
|
|
416
|
+
/** Tracker 实例 */
|
|
417
|
+
tracker: tracker
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
export { defaultGetChannel as getChannel };
|
|
421
|
+
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
|
+
}
|
|
@@ -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对象
|
|
@@ -248,28 +263,60 @@ export declare class AliOssClass {
|
|
|
248
263
|
* 图片上传主方法
|
|
249
264
|
* 整合了所有项目的图片上传逻辑
|
|
250
265
|
* @param option 上传选项
|
|
251
|
-
* @returns Promise
|
|
266
|
+
* @returns Promise - 成功时返回图片信息对象,失败时reject错误信息字符串
|
|
267
|
+
* @returns 成功返回结构: {
|
|
268
|
+
* url: string - 上传后的图片URL,
|
|
269
|
+
* imgUrl: string - 上传后的图片URL(可能包含尺寸信息),
|
|
270
|
+
* imgOrgUrl: string - 原始图片URL(包含尺寸信息),
|
|
271
|
+
* name: string - 文件名,
|
|
272
|
+
* fileName: string - 文件名
|
|
273
|
+
* }
|
|
274
|
+
* @returns 失败返回: 错误信息字符串,如"文件类型不支持"、"上传失败"等
|
|
252
275
|
*/
|
|
253
276
|
ossUploadImage: (option: UploadOption) => Promise<any>;
|
|
254
277
|
/**
|
|
255
278
|
* 文件上传方法
|
|
256
279
|
* 支持视频、文档、APK等文件类型
|
|
257
280
|
* @param option 上传选项
|
|
258
|
-
* @returns Promise
|
|
281
|
+
* @returns Promise - 成功时返回文件信息对象,失败时reject错误信息字符串
|
|
282
|
+
* @returns 成功返回结构: {
|
|
283
|
+
* url: string - 上传后的文件URL,
|
|
284
|
+
* imgUrl: string - 上传后的文件URL,
|
|
285
|
+
* imgOrgUrl: string - 上传后的文件URL,
|
|
286
|
+
* name: string - 文件名,
|
|
287
|
+
* fileName: string - 文件名
|
|
288
|
+
* }
|
|
289
|
+
* @returns 失败返回: 错误信息字符串,如"文件类型不支持"、"上传失败"等
|
|
259
290
|
*/
|
|
260
291
|
ossUploadFile: (option: UploadOption) => Promise<any>;
|
|
261
292
|
/**
|
|
262
293
|
* 纯图片上传 pureOssUploadImage
|
|
263
294
|
* 注释:图片上传,不压缩
|
|
264
295
|
* @param option 上传选项
|
|
265
|
-
* @returns Promise
|
|
296
|
+
* @returns Promise - 成功时返回图片信息对象,失败时reject错误信息字符串
|
|
297
|
+
* @returns 成功返回结构: {
|
|
298
|
+
* url: string - 上传后的图片URL,
|
|
299
|
+
* imgUrl: string - 上传后的图片URL,
|
|
300
|
+
* imgOrgUrl: string - 上传后的图片URL,
|
|
301
|
+
* name: string - 文件名,
|
|
302
|
+
* fileName: string - 文件名
|
|
303
|
+
* }
|
|
304
|
+
* @returns 失败返回: 错误信息字符串,如"文件类型不支持"、"上传失败"等
|
|
266
305
|
*/
|
|
267
306
|
pureOssUploadImage: (option: UploadOption) => Promise<any>;
|
|
268
307
|
/**
|
|
269
308
|
* 商品详情图片上传(不建议直接使用,请使用 pureOssUploadImage)
|
|
270
309
|
* 注释:图片上传,不压缩
|
|
271
310
|
* @param option 上传选项
|
|
272
|
-
* @returns Promise
|
|
311
|
+
* @returns Promise - 成功时返回图片信息对象,失败时reject错误信息字符串
|
|
312
|
+
* @returns 成功返回结构: {
|
|
313
|
+
* url: string - 上传后的图片URL,
|
|
314
|
+
* imgUrl: string - 上传后的图片URL,
|
|
315
|
+
* imgOrgUrl: string - 上传后的图片URL,
|
|
316
|
+
* name: string - 文件名,
|
|
317
|
+
* fileName: string - 文件名
|
|
318
|
+
* }
|
|
319
|
+
* @returns 失败返回: 错误信息字符串,如"文件类型不支持"、"上传失败"等
|
|
273
320
|
*/
|
|
274
321
|
shopDetailUpdate: (option: UploadOption) => Promise<any>;
|
|
275
322
|
/**
|