@tmsfe/tms-core 0.0.40 → 0.0.41
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 +1 -1
- package/src/index-proxy.js +2 -0
- package/src/index.js +2 -0
- package/src/report/formatV1.ts +5 -4
- package/src/report/formatV2.ts +4 -3
- package/src/report/helper.ts +49 -47
- package/src/report/proxy/component.ts +42 -0
- package/src/report/proxy/helper.ts +133 -0
- package/src/report/proxy/index.ts +20 -0
- package/src/report/proxy/page.ts +80 -0
package/package.json
CHANGED
package/src/index-proxy.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import syncApi from './syncfnmanager';
|
|
9
|
+
import AutoReport from './report/proxy/index';
|
|
9
10
|
import md5 from './md5';
|
|
10
11
|
import { rpxToPx } from './rpx';
|
|
11
12
|
import { serialize } from './objUtils';
|
|
@@ -39,6 +40,7 @@ function invoke(obj, funcName, args) {
|
|
|
39
40
|
function initProxy(appObj, options) {
|
|
40
41
|
app = appObj;
|
|
41
42
|
initOptions = options;
|
|
43
|
+
AutoReport.init();
|
|
42
44
|
}
|
|
43
45
|
|
|
44
46
|
function awaitTMS() {
|
package/src/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import Request from './request';
|
|
2
|
+
import AutoReport from './report/proxy/index';
|
|
2
3
|
import Reporter from './report/index';
|
|
3
4
|
import { getConfig } from './config';
|
|
4
5
|
import syncApi from './syncfnmanager';
|
|
@@ -101,6 +102,7 @@ const init = (options = {}) => {
|
|
|
101
102
|
setEnvInfo(envInfo);
|
|
102
103
|
setAppPagePaths(appPagePaths, homePage);
|
|
103
104
|
Reporter.init(envInfo);
|
|
105
|
+
AutoReport.init();
|
|
104
106
|
Request.defaultHost = defaultHost;
|
|
105
107
|
// 初始化云环境
|
|
106
108
|
wx.cloud.init({ env: cloudEnvId });
|
package/src/report/formatV1.ts
CHANGED
|
@@ -9,14 +9,15 @@ import helper from './helper';
|
|
|
9
9
|
* 获取埋点的基础字段
|
|
10
10
|
*/
|
|
11
11
|
function getBaseData(deviceData: IDeviceData): DataItem[] {
|
|
12
|
-
const arr = new Array<string>(helper.dataArrLen);
|
|
13
12
|
const { networkType, location } = deviceData;
|
|
14
13
|
const { appVersion, client } = helper.getInitOptions();
|
|
15
14
|
const { host } = helper.getSystemInfo();
|
|
15
|
+
const arr = new Array<string>(helper.dataArrLen);
|
|
16
16
|
// todo: 如何区分新旧埋点?新:f20不为空,旧:f20为空
|
|
17
17
|
// ++++++++++++++++++++++++++字段列表++++++++++++++++++++++++++
|
|
18
18
|
// 0: log_time,日志入库时间
|
|
19
|
-
// 1: access_time
|
|
19
|
+
// 1: access_time,埋点触发时间
|
|
20
|
+
arr[1] = Date.now().toString();
|
|
20
21
|
// 2: user_ip,前端无需赋值
|
|
21
22
|
// 3: qimei,灯塔中的用户ID
|
|
22
23
|
// 4: imei,Android手机的imei IOS系统中的idfv 车联网中的wecarid
|
|
@@ -50,7 +51,7 @@ function getBaseData(deviceData: IDeviceData): DataItem[] {
|
|
|
50
51
|
arr[29] = helper.getAppScene();
|
|
51
52
|
// 33: f33,系统信息
|
|
52
53
|
arr[33] = helper.getSystemInfoString();
|
|
53
|
-
// 36: f36
|
|
54
|
+
// 36: f36,小程序启动时的url和参数
|
|
54
55
|
arr[36] = helper.getLaunchOptionsString();
|
|
55
56
|
// --------------------------字段列表--------------------------
|
|
56
57
|
return arr;
|
|
@@ -84,7 +85,7 @@ function formatData(data: IOldParams): Promise<DataItem[]> {
|
|
|
84
85
|
* 格式化快速上报埋点数据,不依赖用户位置
|
|
85
86
|
*/
|
|
86
87
|
function formatFastData(data: IOldParams): DataItem[] {
|
|
87
|
-
return jointData(data, helper.
|
|
88
|
+
return jointData(data, helper.getCacheDeviceData());
|
|
88
89
|
}
|
|
89
90
|
|
|
90
91
|
export default {
|
package/src/report/formatV2.ts
CHANGED
|
@@ -16,7 +16,8 @@ function getBaseData(deviceData: IDeviceData): { arr: DataItem[], nextIndex: num
|
|
|
16
16
|
// todo: 如何区分新旧埋点?新:f20不为空,旧:f20为空
|
|
17
17
|
// ++++++++++++++++++++++++++字段列表++++++++++++++++++++++++++
|
|
18
18
|
// 0: log_time,日志入库时间
|
|
19
|
-
// 1: access_time
|
|
19
|
+
// 1: access_time,埋点触发时间
|
|
20
|
+
arr[1] = Date.now().toString();
|
|
20
21
|
// 2: user_ip,前端无需赋值
|
|
21
22
|
// 3: qimei,灯塔中的用户ID
|
|
22
23
|
// 4: imei,Android手机的imei IOS系统中的idfv 车联网中的wecarid
|
|
@@ -47,7 +48,7 @@ function getBaseData(deviceData: IDeviceData): { arr: DataItem[], nextIndex: num
|
|
|
47
48
|
arr[20] = client;
|
|
48
49
|
// 21: f21,小程序场景值
|
|
49
50
|
arr[21] = helper.getAppScene();
|
|
50
|
-
// 22: f22
|
|
51
|
+
// 22: f22,小程序启动时的url和参数
|
|
51
52
|
arr[22] = helper.getLaunchOptionsString();
|
|
52
53
|
// 23: f23,当前页面的url
|
|
53
54
|
arr[23] = page.route;
|
|
@@ -92,7 +93,7 @@ function formatData(data: any[]): Promise<DataItem[]> {
|
|
|
92
93
|
* 格式化快速上报埋点数据,不依赖用户位置
|
|
93
94
|
*/
|
|
94
95
|
function formatFastData(data: any[]): DataItem[] {
|
|
95
|
-
return jointData(data, helper.
|
|
96
|
+
return jointData(data, helper.getCacheDeviceData());
|
|
96
97
|
}
|
|
97
98
|
|
|
98
99
|
export default {
|
package/src/report/helper.ts
CHANGED
|
@@ -18,6 +18,16 @@ let initOptions: IInitOptions;
|
|
|
18
18
|
function init(options: IInitOptions): void {
|
|
19
19
|
if (!initOptions) {
|
|
20
20
|
initOptions = options;
|
|
21
|
+
|
|
22
|
+
// 从上次缓存中读取,方便首次Report可以先带上
|
|
23
|
+
const loc = wx.getStorageSync('home.location_city') || wx.getStorageSync('home.city');
|
|
24
|
+
deviceData = {
|
|
25
|
+
networkType: '',
|
|
26
|
+
location: {
|
|
27
|
+
province: loc?.province as string,
|
|
28
|
+
cityName: loc?.cityName as string,
|
|
29
|
+
},
|
|
30
|
+
};
|
|
21
31
|
}
|
|
22
32
|
}
|
|
23
33
|
|
|
@@ -95,8 +105,8 @@ let launchOptions: string | null = null;
|
|
|
95
105
|
*/
|
|
96
106
|
function getLaunchOptionsString(): string {
|
|
97
107
|
if (launchOptions === null) {
|
|
98
|
-
const obj = syncApi.getLaunchOptionsSync()
|
|
99
|
-
launchOptions =
|
|
108
|
+
const obj = syncApi.getLaunchOptionsSync();
|
|
109
|
+
launchOptions = JSON.stringify(obj);
|
|
100
110
|
}
|
|
101
111
|
return launchOptions;
|
|
102
112
|
}
|
|
@@ -106,7 +116,7 @@ function getLaunchOptionsString(): string {
|
|
|
106
116
|
*/
|
|
107
117
|
function getLaunchFrom(): string {
|
|
108
118
|
const obj = syncApi.getLaunchOptionsSync() as any;
|
|
109
|
-
return obj.query?.from
|
|
119
|
+
return obj.query?.from;
|
|
110
120
|
}
|
|
111
121
|
|
|
112
122
|
/**
|
|
@@ -141,46 +151,8 @@ function canReport(): boolean {
|
|
|
141
151
|
*/
|
|
142
152
|
const dataArrLen = 41;
|
|
143
153
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
location: {
|
|
147
|
-
province: null,
|
|
148
|
-
cityName: null,
|
|
149
|
-
},
|
|
150
|
-
} as any as IDeviceData;
|
|
151
|
-
|
|
152
|
-
let networkPromise: Promise<string> | null = null;
|
|
153
|
-
|
|
154
|
-
function getNetworkType(): Promise<string> {
|
|
155
|
-
if (networkPromise === null) {
|
|
156
|
-
networkPromise = new Promise((resolve) => {
|
|
157
|
-
wx.getNetworkType({
|
|
158
|
-
success: (res: any) => resolve(res.networkType),
|
|
159
|
-
fail: () => resolve('unknown'),
|
|
160
|
-
});
|
|
161
|
-
});
|
|
162
|
-
}
|
|
163
|
-
return networkPromise;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
let locPromise: Promise<ILocation> | null = null;
|
|
167
|
-
|
|
168
|
-
function getLocation(): Promise<ILocation> {
|
|
169
|
-
if (locPromise === null) {
|
|
170
|
-
locPromise = new Promise<ILocation>((resolve) => {
|
|
171
|
-
const LOC = getTms().getLocationManager();
|
|
172
|
-
LOC.getIpLocation()
|
|
173
|
-
.then((res: any) => {
|
|
174
|
-
const ad = res.ad_info;
|
|
175
|
-
resolve({ province: ad.province, cityName: ad.city });
|
|
176
|
-
})
|
|
177
|
-
.catch(() => {
|
|
178
|
-
resolve({ province: '', cityName: '' });
|
|
179
|
-
});
|
|
180
|
-
});
|
|
181
|
-
}
|
|
182
|
-
return locPromise;
|
|
183
|
-
}
|
|
154
|
+
// 缓存设备等信息,方便FastReport使用
|
|
155
|
+
let deviceData: IDeviceData;
|
|
184
156
|
|
|
185
157
|
let devicePromise: Promise<IDeviceData> | null = null;
|
|
186
158
|
|
|
@@ -190,15 +162,45 @@ let devicePromise: Promise<IDeviceData> | null = null;
|
|
|
190
162
|
function getDeviceData(): Promise<IDeviceData> {
|
|
191
163
|
if (devicePromise === null) {
|
|
192
164
|
devicePromise = new Promise<IDeviceData>((resolve) => {
|
|
193
|
-
Promise
|
|
194
|
-
|
|
195
|
-
|
|
165
|
+
const networkPromise = new Promise<void>((resolve) => {
|
|
166
|
+
wx.getNetworkType({
|
|
167
|
+
success: (res: any) => {
|
|
168
|
+
deviceData.networkType = res.networkType;
|
|
169
|
+
resolve();
|
|
170
|
+
},
|
|
171
|
+
fail: () => resolve(),
|
|
172
|
+
});
|
|
196
173
|
});
|
|
174
|
+
|
|
175
|
+
const locPromise = new Promise<void>((resolve) => {
|
|
176
|
+
// 首次如果有缓存则先用缓存,请求后再更新给下次用
|
|
177
|
+
if (deviceData.location.province) {
|
|
178
|
+
resolve();
|
|
179
|
+
}
|
|
180
|
+
const LOC = getTms().getLocationManager();
|
|
181
|
+
LOC.getIpLocation()
|
|
182
|
+
.then((res: any) => {
|
|
183
|
+
const ad = res.ad_info;
|
|
184
|
+
deviceData.location.province = ad.province;
|
|
185
|
+
deviceData.location.cityName = ad.city;
|
|
186
|
+
resolve();
|
|
187
|
+
})
|
|
188
|
+
.catch(() => resolve());
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
Promise.all([networkPromise, locPromise]).then(() => resolve(deviceData));
|
|
197
192
|
});
|
|
198
193
|
}
|
|
199
194
|
return devicePromise;
|
|
200
195
|
}
|
|
201
196
|
|
|
197
|
+
/**
|
|
198
|
+
* 获取缓存的设备信息(网络状况,位置信息)
|
|
199
|
+
*/
|
|
200
|
+
function getCacheDeviceData(): IDeviceData {
|
|
201
|
+
return deviceData;
|
|
202
|
+
}
|
|
203
|
+
|
|
202
204
|
export default {
|
|
203
205
|
init,
|
|
204
206
|
getTms,
|
|
@@ -212,6 +214,6 @@ export default {
|
|
|
212
214
|
getAppScene,
|
|
213
215
|
canReport,
|
|
214
216
|
dataArrLen,
|
|
215
|
-
defaultDevice,
|
|
216
217
|
getDeviceData,
|
|
218
|
+
getCacheDeviceData,
|
|
217
219
|
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 负责组件的全埋点
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import helper from './helper';
|
|
6
|
+
|
|
7
|
+
let originalComponent: any = null;
|
|
8
|
+
|
|
9
|
+
// 劫持其他事件
|
|
10
|
+
function proxyHandle(componentName: string, methods: any, methodName: string): void {
|
|
11
|
+
const original = methods[methodName];
|
|
12
|
+
// eslint-disable-next-line no-param-reassign
|
|
13
|
+
methods[methodName] = function (...args: any[]): any {
|
|
14
|
+
// 执行原函数之后再发埋点
|
|
15
|
+
return helper.executeFunc(this, original, args, () => {
|
|
16
|
+
const data = helper.serializeData(this.data);
|
|
17
|
+
helper.reportData(`Component_${componentName}`, methodName, data);
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// 劫持Page
|
|
23
|
+
function init(): void {
|
|
24
|
+
// @ts-ignore
|
|
25
|
+
originalComponent = Component;
|
|
26
|
+
// @ts-ignore
|
|
27
|
+
Component = function (options: any) {
|
|
28
|
+
// 只有tms的页面才需要上报
|
|
29
|
+
if (options.tmsAutoReport) {
|
|
30
|
+
// tmsReportEvents是由工具在编译时分析出的要上报的事件列表
|
|
31
|
+
const methods = options.methods || {};
|
|
32
|
+
for (const name of options.tmsReportEvents) {
|
|
33
|
+
proxyHandle(options.tmsComponentName, methods, name);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
originalComponent(options);
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export default {
|
|
41
|
+
init,
|
|
42
|
+
};
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 自动埋点辅助类
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
let reporter: any = null;
|
|
6
|
+
|
|
7
|
+
function reportData(...args: any[]): any {
|
|
8
|
+
if (reporter === null) {
|
|
9
|
+
// 如果是在app.js的onLaunch中调用,则没有getApp().tms为空
|
|
10
|
+
// @ts-ignore
|
|
11
|
+
const tms = getApp()?.tms || wx.tms;
|
|
12
|
+
reporter = tms.getReporter();
|
|
13
|
+
}
|
|
14
|
+
// console.log('自动埋点:', ...args);
|
|
15
|
+
reporter.report2(...args);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* 空函数
|
|
20
|
+
*/
|
|
21
|
+
function emptyFunc(): void {
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* 执行函数
|
|
26
|
+
* @param context
|
|
27
|
+
* @param func
|
|
28
|
+
* @param args
|
|
29
|
+
* @param doneCallback
|
|
30
|
+
*/
|
|
31
|
+
function executeFunc(context: any, func: Function, args: any[], doneCallback: Function): any {
|
|
32
|
+
const value = func.apply(context, args);
|
|
33
|
+
// 如果不会返回promise
|
|
34
|
+
if (!value || !value.then || typeof value.then !== 'function') {
|
|
35
|
+
doneCallback();
|
|
36
|
+
return value;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return value.then((res: any) => {
|
|
40
|
+
doneCallback();
|
|
41
|
+
return res;
|
|
42
|
+
}).catch((err: any) => {
|
|
43
|
+
doneCallback();
|
|
44
|
+
return Promise.reject(err);
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const maxDepth = 5;
|
|
49
|
+
const maxArrLen = 10;
|
|
50
|
+
const maxStrLen = 30;
|
|
51
|
+
const maxFieldLen = 20;
|
|
52
|
+
|
|
53
|
+
function isBasicsType(obj: any): { isBasics: boolean, value: any } {
|
|
54
|
+
const type = typeof obj;
|
|
55
|
+
if (obj === null || obj === undefined
|
|
56
|
+
|| type === 'number' || type === 'boolean' || type === 'bigint') {
|
|
57
|
+
return { isBasics: true, value: obj };
|
|
58
|
+
}
|
|
59
|
+
if (type === 'string') {
|
|
60
|
+
const value = obj.substr(0, maxStrLen);
|
|
61
|
+
return { isBasics: true, value };
|
|
62
|
+
}
|
|
63
|
+
if (type === 'function' || type === 'symbol') {
|
|
64
|
+
return { isBasics: true, value: undefined };
|
|
65
|
+
}
|
|
66
|
+
return { isBasics: false, value: obj };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function isArrayType(obj: any): { isArray: boolean, value: any } {
|
|
70
|
+
if (Array.isArray(obj)) {
|
|
71
|
+
const arr = obj.slice(0, maxArrLen);
|
|
72
|
+
return { isArray: true, value: arr };
|
|
73
|
+
}
|
|
74
|
+
return { isArray: false, value: obj };
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* 深表克隆
|
|
79
|
+
* @param obj
|
|
80
|
+
* @param depth 当前克隆的深度
|
|
81
|
+
*/
|
|
82
|
+
function deepClone(obj: any, depth: number): any {
|
|
83
|
+
if (depth >= maxDepth) {
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
const res1 = isBasicsType(obj);
|
|
87
|
+
if (res1.isBasics) {
|
|
88
|
+
return res1.value;
|
|
89
|
+
}
|
|
90
|
+
const res2 = isArrayType(obj);
|
|
91
|
+
if (res2.isArray) {
|
|
92
|
+
return res2.value.map((t: any) => deepClone(t, depth + 1));
|
|
93
|
+
}
|
|
94
|
+
const names = Object.getOwnPropertyNames(obj).slice(0, maxFieldLen);
|
|
95
|
+
const newObj = {};
|
|
96
|
+
for (const name of names) {
|
|
97
|
+
if (name === '__webviewId__') {
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
const value = obj[name];
|
|
101
|
+
const res1 = isBasicsType(value);
|
|
102
|
+
if (res1.isBasics) {
|
|
103
|
+
// @ts-ignore
|
|
104
|
+
newObj[name] = res1.value;
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
const res2 = isArrayType(value);
|
|
108
|
+
if (res2.isArray) {
|
|
109
|
+
// @ts-ignore
|
|
110
|
+
newObj[name] = res2.value.map((t: any) => deepClone(t, depth + 1));
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
// @ts-ignore
|
|
114
|
+
newObj[name] = deepClone(value, depth + 1);
|
|
115
|
+
}
|
|
116
|
+
return newObj;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* 序列化data
|
|
121
|
+
* @param data
|
|
122
|
+
*/
|
|
123
|
+
function serializeData(data: any): string {
|
|
124
|
+
const obj = deepClone(data, 0);
|
|
125
|
+
return JSON.stringify(obj);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export default {
|
|
129
|
+
reportData,
|
|
130
|
+
emptyFunc,
|
|
131
|
+
executeFunc,
|
|
132
|
+
serializeData,
|
|
133
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 负责页面和组件的全埋点
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import proxyPage from './page';
|
|
6
|
+
import proxyComponent from './component';
|
|
7
|
+
|
|
8
|
+
let isInit = false;
|
|
9
|
+
|
|
10
|
+
function init(): void {
|
|
11
|
+
if (!isInit) {
|
|
12
|
+
isInit = true;
|
|
13
|
+
proxyPage.init();
|
|
14
|
+
proxyComponent.init();
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export default {
|
|
19
|
+
init,
|
|
20
|
+
};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 负责页面的全埋点
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import helper from './helper';
|
|
6
|
+
|
|
7
|
+
// 必须上报的生命周期函数
|
|
8
|
+
const mustLifeMethods = ['onLoad', 'onShow', 'onReady', 'onHide', 'onUnload'];
|
|
9
|
+
// 可能会有的生命周期函数
|
|
10
|
+
const maybeLifeMethods = [
|
|
11
|
+
'onPullDownRefresh', 'onReachBottom', 'onShareAppMessage',
|
|
12
|
+
'onShareTimeline', 'onAddToFavorites', 'onPageScroll',
|
|
13
|
+
];
|
|
14
|
+
const lifeMethods = mustLifeMethods.concat(maybeLifeMethods);
|
|
15
|
+
|
|
16
|
+
let originalPage: any = null;
|
|
17
|
+
|
|
18
|
+
// 劫持Page的生命周期
|
|
19
|
+
function proxyLifeMethod(pageOptions: any, methodName: string): void {
|
|
20
|
+
if (!pageOptions[methodName] && !mustLifeMethods.includes(methodName)) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const original = pageOptions[methodName] || helper.emptyFunc;
|
|
24
|
+
// eslint-disable-next-line no-param-reassign
|
|
25
|
+
pageOptions[methodName] = function (...args: any[]): any {
|
|
26
|
+
let elapsed: number | '' = ''; // 页面曝光时间
|
|
27
|
+
let showCount: number | '' = ''; // 曝光次数
|
|
28
|
+
if (methodName === 'onShow') {
|
|
29
|
+
this.tmsPageShowCount = (this.tmsPageShowCount || 0) + 1;
|
|
30
|
+
this.tmsPageShowTime = Date.now();
|
|
31
|
+
showCount = this.tmsPageShowCount;
|
|
32
|
+
} else if (methodName === 'onHide' || methodName === 'onUnload') {
|
|
33
|
+
elapsed = Date.now() - this.tmsPageShowTime;
|
|
34
|
+
this.tmsPageShowTime = 0;
|
|
35
|
+
showCount = this.tmsPageShowCount;
|
|
36
|
+
}
|
|
37
|
+
// 执行原函数之后再发埋点
|
|
38
|
+
return helper.executeFunc(this, original, args, () => {
|
|
39
|
+
const data = helper.serializeData(this.data);
|
|
40
|
+
helper.reportData(`Page_${methodName}`, data, showCount, elapsed);
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// 劫持其他事件
|
|
46
|
+
function proxyHandle(pageOptions: any, methodName: string): void {
|
|
47
|
+
const original = pageOptions[methodName] || helper.emptyFunc;
|
|
48
|
+
// eslint-disable-next-line no-param-reassign
|
|
49
|
+
pageOptions[methodName] = function (...args: any[]): any {
|
|
50
|
+
// 执行原函数之后再发埋点
|
|
51
|
+
return helper.executeFunc(this, original, args, () => {
|
|
52
|
+
const data = helper.serializeData(this.data);
|
|
53
|
+
helper.reportData(`Page_${methodName}`, data);
|
|
54
|
+
});
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// 劫持Page
|
|
59
|
+
function init(): void {
|
|
60
|
+
// @ts-ignore
|
|
61
|
+
originalPage = Page;
|
|
62
|
+
// @ts-ignore
|
|
63
|
+
Page = function (options: any) {
|
|
64
|
+
// 只有tms的页面才需要上报
|
|
65
|
+
if (options.tmsAutoReport) {
|
|
66
|
+
for (const methodName of lifeMethods) {
|
|
67
|
+
proxyLifeMethod(options, methodName);
|
|
68
|
+
}
|
|
69
|
+
// tmsReportEvents是由工具在编译时分析出的要上报的事件列表
|
|
70
|
+
for (const methodName of options.tmsReportEvents) {
|
|
71
|
+
proxyHandle(options, methodName);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
originalPage(options);
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export default {
|
|
79
|
+
init,
|
|
80
|
+
};
|