@tmsfe/tms-core 0.0.101 → 0.0.103
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/report/clone.ts +0 -26
- package/src/report/proxy/component.ts +30 -11
- package/src/report/proxy/helper.ts +46 -1
- package/src/report/proxy/page.ts +48 -14
package/package.json
CHANGED
package/src/report/clone.ts
CHANGED
|
@@ -86,32 +86,6 @@ function deepClone(obj: any, depth = 0, maxDepth = 2): any {
|
|
|
86
86
|
return newObj;
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
/**
|
|
90
|
-
* 获取触发绑定事件的携带数据
|
|
91
|
-
* @param event
|
|
92
|
-
*/
|
|
93
|
-
function getEventExtra(event: any): any {
|
|
94
|
-
if (!event) {
|
|
95
|
-
return '';
|
|
96
|
-
}
|
|
97
|
-
const { currentTarget, mark, detail } = event;
|
|
98
|
-
const obj = {};
|
|
99
|
-
// 一般把数据放在dataset或者mark中
|
|
100
|
-
const dataset = currentTarget?.dataset;
|
|
101
|
-
if (dataset && Object.keys(dataset).length) {
|
|
102
|
-
Object.assign(obj, { dataset });
|
|
103
|
-
}
|
|
104
|
-
if (mark && Object.keys(mark).length) {
|
|
105
|
-
Object.assign(obj, { mark });
|
|
106
|
-
}
|
|
107
|
-
// 如果以上都没有,那可能就是在detail中
|
|
108
|
-
if (detail && Object.keys(obj).length === 0) {
|
|
109
|
-
Object.assign(obj, { detail });
|
|
110
|
-
}
|
|
111
|
-
return deepClone(obj);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
89
|
export default {
|
|
115
90
|
deepClone,
|
|
116
|
-
getEventExtra,
|
|
117
91
|
};
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
|
|
6
6
|
// / <reference path='./types.ts'/>
|
|
7
7
|
|
|
8
|
-
import clone from '../clone';
|
|
9
8
|
import helper from './helper';
|
|
10
9
|
|
|
11
10
|
// 劫持Component的生命周期
|
|
@@ -18,17 +17,20 @@ function proxyLifeMethod(componentName: string, componentOptions: any, methodNam
|
|
|
18
17
|
let original = obj[methodName] || helper.emptyFunc;
|
|
19
18
|
obj[methodName] = function (...args: any[]): any {
|
|
20
19
|
// 生命周期函数先发埋点,避免次过程用户退出而丢失埋点
|
|
21
|
-
|
|
22
|
-
// vue下组件ready事件名是mounted,这里统一改为跟小程序一样用ready
|
|
23
|
-
const funcName = methodName === 'mounted' ? 'ready' : methodName;
|
|
24
|
-
const eventName = `Component_${componentName}_${funcName}`;
|
|
25
|
-
helper.reportData(eventName, data);
|
|
20
|
+
reportLifeEvent(this, componentName, methodName);
|
|
26
21
|
// 执行原函数
|
|
27
22
|
return helper.executeFunc(this, original, args, helper.emptyFunc);
|
|
28
23
|
}
|
|
29
24
|
/* eslint-enable */
|
|
30
25
|
}
|
|
31
26
|
|
|
27
|
+
// 上报生命周期事件
|
|
28
|
+
function reportLifeEvent(instance: any, componentName: string, methodName: string): void {
|
|
29
|
+
const data = helper.cloneData(instance);
|
|
30
|
+
const eventName = `Component_${componentName}_${methodName}`;
|
|
31
|
+
helper.reportData(eventName, data);
|
|
32
|
+
}
|
|
33
|
+
|
|
32
34
|
// 劫持绑定事件
|
|
33
35
|
function proxyBindEvent(componentName: string, methods: any, methodName: string, bindType: string): void {
|
|
34
36
|
const original = methods[methodName];
|
|
@@ -39,8 +41,8 @@ function proxyBindEvent(componentName: string, methods: any, methodName: string,
|
|
|
39
41
|
methods[methodName] = function (...args: any[]): any {
|
|
40
42
|
// 执行原函数之后再发埋点
|
|
41
43
|
return helper.executeFunc(this, original, args, () => {
|
|
42
|
-
const extra =
|
|
43
|
-
const data =
|
|
44
|
+
const extra = helper.getEventExtra(args[0]) ; // 把触发事件附加数据也带上
|
|
45
|
+
const data = helper.cloneData(this);
|
|
44
46
|
const eventName = `Component_${componentName}_${methodName}`;
|
|
45
47
|
helper.setLastBindEvent({ eventName, data, extra, bindType });
|
|
46
48
|
helper.reportData(eventName, data, extra, bindType);
|
|
@@ -69,22 +71,39 @@ function proxyMpComponent(): void {
|
|
|
69
71
|
|
|
70
72
|
// 劫持vue的Component
|
|
71
73
|
function proxyVueComponent(): void {
|
|
74
|
+
const isComponent = function (options): boolean {
|
|
75
|
+
// options可能为空
|
|
76
|
+
// uniapp转换之后,Component的tmsAutoReport被放在组件属性中,而Page的被放在data中
|
|
77
|
+
return options?.tmsAutoReport;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
// uniapp转换工具执行后会在本文件开头插入Vue的引入
|
|
72
81
|
// @ts-ignore
|
|
73
82
|
Vue.mixin({
|
|
74
83
|
beforeCreate() {
|
|
75
84
|
const options = this.$options;
|
|
76
|
-
|
|
77
|
-
if (!options.tmsAutoReport || !options.tmsComponentName) {
|
|
85
|
+
if (!isComponent(options)) {
|
|
78
86
|
return;
|
|
79
87
|
}
|
|
80
88
|
|
|
81
89
|
const { methods } = options;
|
|
90
|
+
if (methods.tmsReportBinded) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
// 加个标记,避免二次挂载时重复劫持
|
|
94
|
+
methods.tmsReportBinded = () => {};
|
|
95
|
+
|
|
82
96
|
for (const event of options.tmsReportEvents) {
|
|
83
97
|
const { name, type } = event;
|
|
84
98
|
proxyBindEvent(options.tmsComponentName, methods, name, type);
|
|
85
99
|
}
|
|
100
|
+
},
|
|
86
101
|
|
|
87
|
-
|
|
102
|
+
mounted() {
|
|
103
|
+
const options = this.$options;
|
|
104
|
+
if (isComponent(options)) {
|
|
105
|
+
reportLifeEvent(this, options.tmsComponentName, 'ready');
|
|
106
|
+
}
|
|
88
107
|
},
|
|
89
108
|
});
|
|
90
109
|
}
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
|
|
6
6
|
// / <reference path='./types.ts'/>
|
|
7
7
|
|
|
8
|
+
import clone from '../clone';
|
|
9
|
+
|
|
8
10
|
function getReporter(): any {
|
|
9
11
|
// 如果是在app.js的onLaunch中调用,则没有getApp().tms为空
|
|
10
12
|
const tms = getApp()?.tms || (wx as any).tms;
|
|
@@ -97,12 +99,55 @@ function executeFunc(context: any, func: Function, args: any[], callback: Functi
|
|
|
97
99
|
});
|
|
98
100
|
}
|
|
99
101
|
|
|
102
|
+
/**
|
|
103
|
+
* 复制组件的data
|
|
104
|
+
* @param instance 组件实例
|
|
105
|
+
*/
|
|
106
|
+
function cloneData(instance: any): any {
|
|
107
|
+
if (!wx.isH5) {
|
|
108
|
+
return clone.deepClone(instance.data);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// 取出vue的props跟data
|
|
112
|
+
const data = { ...instance.$options.propsData };
|
|
113
|
+
if (instance.$options.data) {
|
|
114
|
+
Object.assign(data, instance.$options.data());
|
|
115
|
+
}
|
|
116
|
+
return clone.deepClone(data);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* 获取触发绑定事件的携带数据
|
|
121
|
+
*/
|
|
122
|
+
function getEventExtra(event: any): any {
|
|
123
|
+
if (!event) {
|
|
124
|
+
return '';
|
|
125
|
+
}
|
|
126
|
+
const { currentTarget, mark, detail } = event;
|
|
127
|
+
const obj = {};
|
|
128
|
+
// 一般把数据放在dataset或者mark中
|
|
129
|
+
const dataset = currentTarget?.dataset;
|
|
130
|
+
if (dataset && Object.keys(dataset).length) {
|
|
131
|
+
Object.assign(obj, { dataset });
|
|
132
|
+
}
|
|
133
|
+
if (mark && Object.keys(mark).length) {
|
|
134
|
+
Object.assign(obj, { mark });
|
|
135
|
+
}
|
|
136
|
+
// 如果以上都没有,那可能就是在detail中
|
|
137
|
+
if (detail && Object.keys(obj).length === 0) {
|
|
138
|
+
Object.assign(obj, { detail });
|
|
139
|
+
}
|
|
140
|
+
return clone.deepClone(obj);
|
|
141
|
+
}
|
|
142
|
+
|
|
100
143
|
export default {
|
|
101
144
|
emptyFunc,
|
|
145
|
+
cloneData,
|
|
102
146
|
reportData,
|
|
103
|
-
fastReportData,
|
|
104
147
|
executeFunc,
|
|
105
148
|
getSystemInfo,
|
|
149
|
+
getEventExtra,
|
|
150
|
+
fastReportData,
|
|
106
151
|
getLastBindEvent,
|
|
107
152
|
setLastBindEvent,
|
|
108
153
|
};
|
package/src/report/proxy/page.ts
CHANGED
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
|
|
6
6
|
// / <reference path='./types.ts'/>
|
|
7
7
|
|
|
8
|
-
import clone from '../clone';
|
|
9
8
|
import helper from './helper';
|
|
10
9
|
|
|
11
10
|
// 工具为页面根节点插入的触摸事件
|
|
@@ -28,14 +27,19 @@ function proxyLifeMethod(pageOptions: any, methodName: string): void {
|
|
|
28
27
|
// eslint-disable-next-line no-param-reassign
|
|
29
28
|
pageOptions[methodName] = function (...args: any[]): any {
|
|
30
29
|
// 生命周期函数先发埋点,避免次过程用户退出而丢失埋点
|
|
31
|
-
|
|
32
|
-
helper.reportData(`Page_${methodName}`, extra);
|
|
30
|
+
reportLifeEvent(this, methodName, args);
|
|
33
31
|
|
|
34
32
|
// 执行原函数
|
|
35
33
|
return helper.executeFunc(this, original, args, helper.emptyFunc);
|
|
36
34
|
};
|
|
37
35
|
}
|
|
38
36
|
|
|
37
|
+
// 上报生命周期事件
|
|
38
|
+
function reportLifeEvent(instance: any, methodName: string, args: any[]): void {
|
|
39
|
+
const extra = getPageLifeExtra(instance, methodName, args);
|
|
40
|
+
helper.reportData(`Page_${methodName}`, extra);
|
|
41
|
+
}
|
|
42
|
+
|
|
39
43
|
// 获取生命周期函数上报时的附加信息
|
|
40
44
|
function getPageLifeExtra(page: any, methodName: string, args: any[]): IPageLifeExtra | IPageTouchExtra {
|
|
41
45
|
/* eslint-disable */
|
|
@@ -91,10 +95,10 @@ function proxyBindEvent(pageOptions: any, methodName: string, bindType: string):
|
|
|
91
95
|
}
|
|
92
96
|
// eslint-disable-next-line no-param-reassign
|
|
93
97
|
pageOptions[methodName] = function (...args: any[]): any {
|
|
94
|
-
const extra =
|
|
98
|
+
const extra = helper.getEventExtra(args[0]) ; // 把触发事件附加数据也带上
|
|
95
99
|
// 执行原函数之后再发埋点
|
|
96
100
|
return helper.executeFunc(this, original, args, () => {
|
|
97
|
-
const data =
|
|
101
|
+
const data = helper.cloneData(this);
|
|
98
102
|
const eventName = `Page_${methodName}`;
|
|
99
103
|
helper.setLastBindEvent({ eventName, data, extra, bindType });
|
|
100
104
|
helper.reportData(eventName, data, extra, bindType);
|
|
@@ -123,24 +127,54 @@ function proxyMpPage(): void {
|
|
|
123
127
|
|
|
124
128
|
// 劫持vue的Page
|
|
125
129
|
function proxyVuePage(): void {
|
|
126
|
-
|
|
127
|
-
|
|
130
|
+
const isPage = (options): boolean => {
|
|
131
|
+
// options可能为空
|
|
132
|
+
// uniapp转换之后,Component的tmsAutoReport被放在组件属性中,而Page的被放在data中
|
|
133
|
+
if (!options?.data) {
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// todo: 不知为啥非我们自定义页面或组件这里会报错
|
|
138
|
+
try {
|
|
139
|
+
return options.data().tmsAutoReport;
|
|
140
|
+
} catch {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
const mixinObj = {
|
|
128
146
|
beforeCreate() {
|
|
129
147
|
const options = this.$options;
|
|
130
|
-
|
|
131
|
-
if (!options.tmsAutoReport || options.tmsComponentName) {
|
|
148
|
+
if (!isPage(options)) {
|
|
132
149
|
return;
|
|
133
150
|
}
|
|
134
151
|
|
|
135
|
-
|
|
136
|
-
|
|
152
|
+
const { methods } = options;
|
|
153
|
+
if (methods.tmsReportBinded) {
|
|
154
|
+
return;
|
|
137
155
|
}
|
|
138
|
-
|
|
156
|
+
// 加个标记,避免二次挂载时重复劫持
|
|
157
|
+
methods.tmsReportBinded = () => {};
|
|
158
|
+
|
|
159
|
+
const { tmsReportEvents } = options.data();
|
|
160
|
+
for (const event of tmsReportEvents) {
|
|
139
161
|
const { name, type } = event;
|
|
140
|
-
proxyBindEvent(
|
|
162
|
+
proxyBindEvent(methods, name, type);
|
|
141
163
|
}
|
|
142
164
|
},
|
|
143
|
-
}
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
for (const methodName of mustLifeMethods) {
|
|
168
|
+
mixinObj[methodName] = function (...args: any[]) {
|
|
169
|
+
if (isPage(this.$options)) {
|
|
170
|
+
reportLifeEvent(this, methodName, args);
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// uniapp转换工具执行后会在本文件开头插入Vue的引入
|
|
176
|
+
// @ts-ignore
|
|
177
|
+
Vue.mixin(mixinObj);
|
|
144
178
|
}
|
|
145
179
|
|
|
146
180
|
// 劫持Page
|