@tmsfe/tms-core 0.0.42 → 0.0.45

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tmsfe/tms-core",
3
- "version": "0.0.42",
3
+ "version": "0.0.45",
4
4
  "description": "tms运行时框架",
5
5
  "repository": {
6
6
  "type": "git",
@@ -63,7 +63,7 @@ const asyncFuncNames = [
63
63
  // 这行是tms-runtime的
64
64
  'getPhone', 'login', 'getLoginInfo', 'getOpenId', 'getMycarPubOpenId', 'getSinanPubOpenId',
65
65
  // tms-core
66
- 'setAuthInfo', 'getConfig', 'navigateToWebview', 'callCloudFunc',
66
+ 'setAuthInfo', 'getConfig', 'navigateToWebview', 'callCloudFunc', 'getEncryptUserInfo',
67
67
  'setUserLocation', 'getUserLocation', 'getMpOpenId', 'getOuterOpenId',
68
68
  ];
69
69
  asyncFuncNames.forEach((funcName) => {
package/src/index.js CHANGED
@@ -37,7 +37,7 @@ import {
37
37
  } from './ipxHelper';
38
38
  import getLocInstance from './location/index';
39
39
  import LocationBase from './location/base';
40
- import { getMpOpenId, getOuterOpenId } from './mpInfo';
40
+ import { getMpOpenId, getOuterOpenId, getEncryptUserInfo } from './mpInfo';
41
41
  import * as storage from './storage';
42
42
 
43
43
  /**
@@ -173,6 +173,9 @@ const api = {
173
173
  getMpOpenId, // 变更为 getOuterOpenId
174
174
  getOuterOpenId,
175
175
 
176
+ /* 获取加密的用户信息 */
177
+ getEncryptUserInfo,
178
+
176
179
  /** rpx转px */
177
180
  rpxToPx,
178
181
 
package/src/mpInfo.js CHANGED
@@ -32,7 +32,23 @@ async function getOuterOpenId(apiKey) {
32
32
  return openId;
33
33
  }
34
34
 
35
+ async function getEncryptUserInfo(mpId = '', queryTypes = '') {
36
+ if (!mpId) return Promise.reject('缺少服务标志mpId');
37
+ if (!queryTypes) return Promise.reject('缺少需要加密的用户信息字段描述');
38
+ return new Request().get('user/info/encrypt', { mpId, queryTypes })
39
+ .then((res) => {
40
+ const { resData, errCode, errMsg } = res || {};
41
+ if (errCode === 0) {
42
+ // 请求成功
43
+ return resData;
44
+ }
45
+ return Promise.reject(errMsg);
46
+ })
47
+ .catch(e => Promise.reject('请求发生错误,请重试'));
48
+ }
49
+
35
50
  export {
36
51
  getMpOpenId,
37
52
  getOuterOpenId,
53
+ getEncryptUserInfo,
38
54
  };
@@ -17,7 +17,7 @@ function getBaseData(deviceData: IDeviceData): DataItem[] {
17
17
  // ++++++++++++++++++++++++++字段列表++++++++++++++++++++++++++
18
18
  // 0: log_time,日志入库时间
19
19
  // 1: access_time,埋点触发时间
20
- arr[1] = Date.now().toString();
20
+ arr[1] = helper.getNowString();
21
21
  // 2: user_ip,前端无需赋值
22
22
  // 3: qimei,灯塔中的用户ID
23
23
  // 4: imei,Android手机的imei IOS系统中的idfv 车联网中的wecarid
@@ -17,7 +17,7 @@ function getBaseData(deviceData: IDeviceData): { arr: DataItem[], nextIndex: num
17
17
  // ++++++++++++++++++++++++++字段列表++++++++++++++++++++++++++
18
18
  // 0: log_time,日志入库时间
19
19
  // 1: access_time,埋点触发时间
20
- arr[1] = Date.now().toString();
20
+ arr[1] = helper.getNowString();
21
21
  // 2: user_ip,前端无需赋值
22
22
  // 3: qimei,灯塔中的用户ID
23
23
  // 4: imei,Android手机的imei IOS系统中的idfv 车联网中的wecarid
@@ -51,9 +51,9 @@ function getBaseData(deviceData: IDeviceData): { arr: DataItem[], nextIndex: num
51
51
  // 22: f22,小程序启动时的url和参数
52
52
  arr[22] = helper.getLaunchOptionsString();
53
53
  // 23: f23,当前页面的url
54
- arr[23] = page.route;
54
+ arr[23] = page?.route;
55
55
  // 24: f24,当前页面的query
56
- arr[24] = JSON.stringify(page.options);
56
+ arr[24] = JSON.stringify(page?.options);
57
57
  // 25 ~ 30: 预留字段给后续扩展使用
58
58
  // 31 ~ 40: 提供给开发自定义
59
59
  // --------------------------字段列表--------------------------
@@ -83,6 +83,25 @@ function convert2String(value: any): string {
83
83
  return String(value);
84
84
  }
85
85
 
86
+ function num2Str(num: number, maxLength = 2): string {
87
+ return num.toString().padStart(maxLength, '0');
88
+ }
89
+
90
+ /**
91
+ * 获取当前时间格式化后的字符串
92
+ */
93
+ function getNowString(): string {
94
+ const date = new Date();
95
+ const year = date.getFullYear().toString();
96
+ const month = num2Str(date.getMonth() + 1);
97
+ const day = num2Str(date.getDate());
98
+ const hours = num2Str(date.getHours());
99
+ const minutes = num2Str(date.getMinutes());
100
+ const seconds = num2Str(date.getSeconds());
101
+ const ms = num2Str(date.getMilliseconds(), 3);
102
+ return `${year}${month}${day}${hours}${minutes}${seconds}${ms}`;
103
+ }
104
+
86
105
  /**
87
106
  * 获取当前页面信息
88
107
  */
@@ -93,12 +112,8 @@ function getPageInfo(): IPage | null {
93
112
  const launch = syncApi.getLaunchOptionsSync() as any;
94
113
  return { route: launch.path, options: launch.query };
95
114
  }
96
- const page = pages.pop();
97
- // 插件页
98
- if (!page) {
99
- return null;
100
- }
101
- return page;
115
+ // 如果最后一个为空,则当前是在插件页,继续找上一个页面
116
+ return pages.reverse().find((t: IPage) => t);
102
117
  }
103
118
 
104
119
  let launchOptions: string | null = null;
@@ -142,11 +157,7 @@ function canReport(): boolean {
142
157
  isCrawler = scene === '1129' || scene === '1030';
143
158
  }
144
159
  // 小程序爬虫,不上报
145
- if (isCrawler) {
146
- return false;
147
- }
148
- // 插件页不上报埋点
149
- return getPageInfo() !== null;
160
+ return !isCrawler;
150
161
  }
151
162
 
152
163
  /**
@@ -211,6 +222,7 @@ export default {
211
222
  getSystemInfo,
212
223
  getSystemInfoString,
213
224
  convert2String,
225
+ getNowString,
214
226
  getPageInfo,
215
227
  getLaunchOptionsString,
216
228
  getLaunchFrom,
@@ -6,15 +6,19 @@ import helper from './helper';
6
6
 
7
7
  let originalComponent: any = null;
8
8
 
9
- // 劫持其他事件
10
- function proxyHandle(componentName: string, methods: any, methodName: string): void {
9
+ // 劫持绑定事件
10
+ function proxyBindEvent(componentName: string, methods: any, methodName: string): void {
11
11
  const original = methods[methodName];
12
+ if (!original) {
13
+ return;
14
+ }
12
15
  // eslint-disable-next-line no-param-reassign
13
16
  methods[methodName] = function (...args: any[]): any {
17
+ const extend = helper.getEventExtend(args[0]) ; // 把触发事件附加数据也带上
14
18
  // 执行原函数之后再发埋点
15
19
  return helper.executeFunc(this, original, args, () => {
16
- const data = helper.serializeData(this.data);
17
- helper.reportData(`Component_${componentName}`, methodName, data);
20
+ const data = helper.deepClone(this.data);
21
+ helper.reportData(`Component_${componentName}`, methodName, data, extend);
18
22
  });
19
23
  };
20
24
  }
@@ -30,7 +34,7 @@ function init(): void {
30
34
  // tmsReportEvents是由工具在编译时分析出的要上报的事件列表
31
35
  const methods = options.methods || {};
32
36
  for (const name of options.tmsReportEvents) {
33
- proxyHandle(options.tmsComponentName, methods, name);
37
+ proxyBindEvent(options.tmsComponentName, methods, name);
34
38
  }
35
39
  }
36
40
  originalComponent(options);
@@ -45,7 +45,6 @@ function executeFunc(context: any, func: Function, args: any[], doneCallback: Fu
45
45
  });
46
46
  }
47
47
 
48
- const maxDepth = 5;
49
48
  const maxArrLen = 10;
50
49
  const maxStrLen = 30;
51
50
  const maxFieldLen = 20;
@@ -78,9 +77,10 @@ function isArrayType(obj: any): { isArray: boolean, value: any } {
78
77
  * 深表克隆
79
78
  * @param obj
80
79
  * @param depth 当前克隆的深度
80
+ * @param maxDepth 最大克隆深度
81
81
  */
82
- function deepClone(obj: any, depth: number): any {
83
- if (depth >= maxDepth) {
82
+ function deepClone(obj: any, depth = 0, maxDepth = 5): any {
83
+ if (depth > maxDepth) {
84
84
  return undefined;
85
85
  }
86
86
  const res1 = isBasicsType(obj);
@@ -89,7 +89,7 @@ function deepClone(obj: any, depth: number): any {
89
89
  }
90
90
  const res2 = isArrayType(obj);
91
91
  if (res2.isArray) {
92
- return res2.value.map((t: any) => deepClone(t, depth + 1));
92
+ return res2.value.map((t: any) => deepClone(t, depth + 1, maxDepth));
93
93
  }
94
94
  const names = Object.getOwnPropertyNames(obj).slice(0, maxFieldLen);
95
95
  const newObj = {};
@@ -107,27 +107,44 @@ function deepClone(obj: any, depth: number): any {
107
107
  const res2 = isArrayType(value);
108
108
  if (res2.isArray) {
109
109
  // @ts-ignore
110
- newObj[name] = res2.value.map((t: any) => deepClone(t, depth + 1));
110
+ newObj[name] = res2.value.map((t: any) => deepClone(t, depth + 1, maxDepth));
111
111
  continue;
112
112
  }
113
113
  // @ts-ignore
114
- newObj[name] = deepClone(value, depth + 1);
114
+ newObj[name] = deepClone(value, depth + 1, maxDepth);
115
115
  }
116
116
  return newObj;
117
117
  }
118
118
 
119
119
  /**
120
- * 序列化data
121
- * @param data
120
+ * 获取触发绑定事件的携带数据
121
+ * @param event
122
122
  */
123
- function serializeData(data: any): string {
124
- const obj = deepClone(data, 0);
125
- return JSON.stringify(obj);
123
+ function getEventExtend(event: any): string {
124
+ if (!event) {
125
+ return '';
126
+ }
127
+ const { currentTarget, mark, detail } = event;
128
+ const obj = {};
129
+ // 一般把数据放在dataset或者mark中
130
+ const dataset = currentTarget?.dataset;
131
+ if (dataset && Object.keys(dataset).length) {
132
+ Object.assign(obj, { dataset });
133
+ }
134
+ if (mark && Object.keys(mark).length) {
135
+ Object.assign(obj, { mark });
136
+ }
137
+ // 如果以上都没有,那可能就是在detail中
138
+ if (detail && Object.keys(obj).length === 0) {
139
+ Object.assign(obj, { detail });
140
+ }
141
+ return deepClone(obj);
126
142
  }
127
143
 
128
144
  export default {
129
145
  reportData,
130
146
  emptyFunc,
131
147
  executeFunc,
132
- serializeData,
148
+ deepClone,
149
+ getEventExtend,
133
150
  };
@@ -23,34 +23,41 @@ function proxyLifeMethod(pageOptions: any, methodName: string): void {
23
23
  const original = pageOptions[methodName] || helper.emptyFunc;
24
24
  // eslint-disable-next-line no-param-reassign
25
25
  pageOptions[methodName] = function (...args: any[]): any {
26
- let elapsed: number | '' = ''; // 页面曝光时间
27
- let showCount: number | '' = ''; // 曝光次数
26
+ let exposureTime = 0; // 页面曝光时长
27
+ let showCount = 0; // 曝光次数
28
28
  if (methodName === 'onShow') {
29
29
  this.tmsPageShowCount = (this.tmsPageShowCount || 0) + 1;
30
30
  this.tmsPageShowTime = Date.now();
31
31
  showCount = this.tmsPageShowCount;
32
32
  } else if (methodName === 'onHide' || methodName === 'onUnload') {
33
- elapsed = Date.now() - this.tmsPageShowTime;
33
+ exposureTime = Date.now() - this.tmsPageShowTime;
34
34
  this.tmsPageShowTime = 0;
35
35
  showCount = this.tmsPageShowCount;
36
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
- });
37
+
38
+ // 生命周期函数先发埋点,避免次过程用户退出而丢失埋点
39
+ const options = helper.deepClone(args[0], 0, 1);
40
+ const showInfo = showCount ? { showCount, exposureTime } : null;
41
+ helper.reportData(`Page_${methodName}`, options, showInfo);
42
+
43
+ // 执行原函数
44
+ return helper.executeFunc(this, original, args, helper.emptyFunc);
42
45
  };
43
46
  }
44
47
 
45
- // 劫持其他事件
46
- function proxyHandle(pageOptions: any, methodName: string): void {
47
- const original = pageOptions[methodName] || helper.emptyFunc;
48
+ // 劫持绑定事件
49
+ function proxyBindEvent(pageOptions: any, methodName: string): void {
50
+ const original = pageOptions[methodName];
51
+ if (!original) {
52
+ return;
53
+ }
48
54
  // eslint-disable-next-line no-param-reassign
49
55
  pageOptions[methodName] = function (...args: any[]): any {
56
+ const extend = helper.getEventExtend(args[0]) ; // 把触发事件附加数据也带上
50
57
  // 执行原函数之后再发埋点
51
58
  return helper.executeFunc(this, original, args, () => {
52
- const data = helper.serializeData(this.data);
53
- helper.reportData(`Page_${methodName}`, data);
59
+ const data = helper.deepClone(this.data);
60
+ helper.reportData(`Page_${methodName}`, data, extend);
54
61
  });
55
62
  };
56
63
  }
@@ -68,7 +75,7 @@ function init(): void {
68
75
  }
69
76
  // tmsReportEvents是由工具在编译时分析出的要上报的事件列表
70
77
  for (const methodName of options.tmsReportEvents) {
71
- proxyHandle(options, methodName);
78
+ proxyBindEvent(options, methodName);
72
79
  }
73
80
  }
74
81
  originalPage(options);