@tmsfe/tms-core 0.0.53 → 0.0.56
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.js +2 -0
- package/src/report/formatV1.ts +5 -5
- package/src/report/formatV2.ts +16 -13
- package/src/report/helper.ts +36 -34
- package/src/report/sender.ts +3 -1
- package/src/report/types.ts +2 -1
- package/src/timeUtils.js +37 -20
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
formatTime,
|
|
29
29
|
formatTimeStr,
|
|
30
30
|
formatTimeWithDetails,
|
|
31
|
+
formatDateTime,
|
|
31
32
|
dateToString,
|
|
32
33
|
} from './timeUtils';
|
|
33
34
|
import {
|
|
@@ -159,6 +160,7 @@ const api = {
|
|
|
159
160
|
formatTime,
|
|
160
161
|
formatTimeStr,
|
|
161
162
|
formatTimeWithDetails,
|
|
163
|
+
formatDateTime,
|
|
162
164
|
dateToString,
|
|
163
165
|
|
|
164
166
|
/* IPX方法 */
|
package/src/report/formatV1.ts
CHANGED
|
@@ -12,7 +12,7 @@ function getBaseData(deviceData: IDeviceData): DataItem[] {
|
|
|
12
12
|
const { networkType, location } = deviceData;
|
|
13
13
|
const { appVersion, client } = helper.getInitOptions();
|
|
14
14
|
const { host } = helper.getSystemInfo();
|
|
15
|
-
const arr = new Array<
|
|
15
|
+
const arr = new Array<DataItem>(helper.dataArrLen);
|
|
16
16
|
// todo: 如何区分新旧埋点?新:f20不为空,旧:f20为空
|
|
17
17
|
// ++++++++++++++++++++++++++字段列表++++++++++++++++++++++++++
|
|
18
18
|
// 0: log_time,日志入库时间
|
|
@@ -44,15 +44,15 @@ function getBaseData(deviceData: IDeviceData): DataItem[] {
|
|
|
44
44
|
// 18: f18,city - 城市
|
|
45
45
|
arr[18] = location.cityName;
|
|
46
46
|
// 19: f19,当前小程序运行的宿主环境
|
|
47
|
-
arr[19] =
|
|
47
|
+
arr[19] = host;
|
|
48
48
|
// 28: f28,sinan、mycar等
|
|
49
49
|
arr[28] = client;
|
|
50
50
|
// 29: f29,小程序场景值
|
|
51
51
|
arr[29] = helper.getAppScene();
|
|
52
52
|
// 33: f33,系统信息
|
|
53
|
-
arr[33] = helper.
|
|
53
|
+
arr[33] = helper.getSystemInfo();
|
|
54
54
|
// 36: f36,小程序启动时的url和参数
|
|
55
|
-
arr[36] = helper.
|
|
55
|
+
arr[36] = helper.getLaunchOptions();
|
|
56
56
|
// --------------------------字段列表--------------------------
|
|
57
57
|
return arr;
|
|
58
58
|
}
|
|
@@ -64,7 +64,7 @@ function jointData(data: IOldParams, deviceData: IDeviceData): DataItem[] {
|
|
|
64
64
|
const arr = getBaseData(deviceData);
|
|
65
65
|
const keys = Object.keys(data) as any as number[];
|
|
66
66
|
for (const key of keys) {
|
|
67
|
-
arr[key] =
|
|
67
|
+
arr[key] = data[key];
|
|
68
68
|
}
|
|
69
69
|
return arr;
|
|
70
70
|
}
|
package/src/report/formatV2.ts
CHANGED
|
@@ -8,11 +8,10 @@ import helper from './helper';
|
|
|
8
8
|
/**
|
|
9
9
|
* 获取埋点的基础字段
|
|
10
10
|
*/
|
|
11
|
-
function getBaseData(deviceData: IDeviceData): { arr: DataItem[], nextIndex: number } {
|
|
12
|
-
const { page, pageDepth } = helper.getPageInfo();
|
|
11
|
+
function getBaseData(page: IPage, deviceData: IDeviceData): { arr: DataItem[], nextIndex: number } {
|
|
13
12
|
const { networkType, location } = deviceData;
|
|
14
13
|
const { appVersion, client } = helper.getInitOptions();
|
|
15
|
-
const arr = new Array<
|
|
14
|
+
const arr = new Array<DataItem>(helper.dataArrLen);
|
|
16
15
|
// todo: 如何区分新旧埋点?新:f20不为空,旧:f20为空
|
|
17
16
|
// ++++++++++++++++++++++++++字段列表++++++++++++++++++++++++++
|
|
18
17
|
// 0: log_time,日志入库时间
|
|
@@ -43,19 +42,19 @@ function getBaseData(deviceData: IDeviceData): { arr: DataItem[], nextIndex: num
|
|
|
43
42
|
// 18: f18,city - 城市
|
|
44
43
|
arr[18] = location.cityName;
|
|
45
44
|
// 19: f19,系统信息
|
|
46
|
-
arr[19] = helper.
|
|
45
|
+
arr[19] = helper.getSystemInfo();
|
|
47
46
|
// 20: f20,sinan、mycar等
|
|
48
47
|
arr[20] = client;
|
|
49
48
|
// 21: f21,小程序场景值
|
|
50
49
|
arr[21] = helper.getAppScene();
|
|
51
50
|
// 22: f22,小程序启动时的url和参数
|
|
52
|
-
arr[22] = helper.
|
|
51
|
+
arr[22] = helper.getLaunchOptions();
|
|
53
52
|
// 23: f23,当前页面的url
|
|
54
|
-
arr[23] = page
|
|
53
|
+
arr[23] = page.route;
|
|
55
54
|
// 24: f24,当前页面的query
|
|
56
|
-
arr[24] =
|
|
55
|
+
arr[24] = page.options;
|
|
57
56
|
// 25: f25,当前页面深度
|
|
58
|
-
arr[25] =
|
|
57
|
+
arr[25] = page.depth;
|
|
59
58
|
// 26: f26,一次小程序生命周期中的埋点统一标记
|
|
60
59
|
arr[26] = helper.getLifeReportKey();
|
|
61
60
|
// 27 ~ 30: 预留字段给后续扩展使用
|
|
@@ -67,15 +66,15 @@ function getBaseData(deviceData: IDeviceData): { arr: DataItem[], nextIndex: num
|
|
|
67
66
|
/**
|
|
68
67
|
* 拼接埋点数组
|
|
69
68
|
*/
|
|
70
|
-
function jointData(data: any[], deviceData: IDeviceData): DataItem[] {
|
|
71
|
-
const { arr, nextIndex } = getBaseData(deviceData);
|
|
69
|
+
function jointData(page: IPage, data: any[], deviceData: IDeviceData): DataItem[] {
|
|
70
|
+
const { arr, nextIndex } = getBaseData(page, deviceData);
|
|
72
71
|
let index = nextIndex;
|
|
73
72
|
for (const item of data) {
|
|
74
73
|
if (index >= arr.length) {
|
|
75
74
|
console.error('埋点参数个数超出上限而被截断', data);
|
|
76
75
|
break;
|
|
77
76
|
}
|
|
78
|
-
arr[index] =
|
|
77
|
+
arr[index] = item;
|
|
79
78
|
index += 1;
|
|
80
79
|
}
|
|
81
80
|
return arr;
|
|
@@ -85,9 +84,11 @@ function jointData(data: any[], deviceData: IDeviceData): DataItem[] {
|
|
|
85
84
|
* 格式化上报埋点数据
|
|
86
85
|
*/
|
|
87
86
|
function formatData(data: any[]): Promise<DataItem[]> {
|
|
87
|
+
// getDeviceData可能会太慢导致页面已跳转完,所以先获取page比较准确
|
|
88
|
+
const page = helper.getPageInfo();
|
|
88
89
|
return new Promise<DataItem[]>((resolve) => {
|
|
89
90
|
helper.getDeviceData().then((deviceData: IDeviceData) => {
|
|
90
|
-
const arr = jointData(data, deviceData);
|
|
91
|
+
const arr = jointData(page, data, deviceData);
|
|
91
92
|
resolve(arr);
|
|
92
93
|
});
|
|
93
94
|
});
|
|
@@ -97,7 +98,9 @@ function formatData(data: any[]): Promise<DataItem[]> {
|
|
|
97
98
|
* 格式化快速上报埋点数据,不依赖用户位置
|
|
98
99
|
*/
|
|
99
100
|
function formatFastData(data: any[]): DataItem[] {
|
|
100
|
-
|
|
101
|
+
const page = helper.getPageInfo();
|
|
102
|
+
const deviceData = helper.getCacheDeviceData();
|
|
103
|
+
return jointData(page, data, deviceData);
|
|
101
104
|
}
|
|
102
105
|
|
|
103
106
|
export default {
|
package/src/report/helper.ts
CHANGED
|
@@ -53,25 +53,13 @@ function getSystemInfo(): ISystemInfo {
|
|
|
53
53
|
return systemInfo;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
let systemString: string | null = null;
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* 获取系统信息并格式化成字符串
|
|
60
|
-
*/
|
|
61
|
-
function getSystemInfoString(): string {
|
|
62
|
-
if (systemString === null) {
|
|
63
|
-
systemString = JSON.stringify(getSystemInfo());
|
|
64
|
-
}
|
|
65
|
-
return systemString;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
56
|
/**
|
|
69
|
-
*
|
|
57
|
+
* 把值或对象转成字符串
|
|
70
58
|
* @param value
|
|
71
59
|
*/
|
|
72
|
-
function convert2String(value: any): string {
|
|
60
|
+
function convert2String(value: any): string | null {
|
|
73
61
|
if (value === null || value === undefined) {
|
|
74
|
-
return
|
|
62
|
+
return null;
|
|
75
63
|
}
|
|
76
64
|
const type = typeof value;
|
|
77
65
|
if (type === 'string') {
|
|
@@ -83,6 +71,17 @@ function convert2String(value: any): string {
|
|
|
83
71
|
return String(value);
|
|
84
72
|
}
|
|
85
73
|
|
|
74
|
+
/**
|
|
75
|
+
* 转成字符串数据
|
|
76
|
+
* @param arr
|
|
77
|
+
*/
|
|
78
|
+
function convert2StringArray(arr: DataItem[]) {
|
|
79
|
+
for (let i = 0; i < arr.length; i++) {
|
|
80
|
+
// eslint-disable-next-line no-param-reassign
|
|
81
|
+
arr[i] = convert2String(arr[i]);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
86
85
|
function num2Str(num: number, maxLength = 2): string {
|
|
87
86
|
return num.toString().padStart(maxLength, '0');
|
|
88
87
|
}
|
|
@@ -92,7 +91,7 @@ function num2Str(num: number, maxLength = 2): string {
|
|
|
92
91
|
*/
|
|
93
92
|
function getNowString(): string {
|
|
94
93
|
const date = new Date();
|
|
95
|
-
const year = date.getFullYear()
|
|
94
|
+
const year = date.getFullYear();
|
|
96
95
|
const month = num2Str(date.getMonth() + 1);
|
|
97
96
|
const day = num2Str(date.getDate());
|
|
98
97
|
const hours = num2Str(date.getHours());
|
|
@@ -117,31 +116,35 @@ function getLifeReportKey(): string {
|
|
|
117
116
|
/**
|
|
118
117
|
* 获取当前页面信息
|
|
119
118
|
*/
|
|
120
|
-
function getPageInfo():
|
|
119
|
+
function getPageInfo(): IPage {
|
|
121
120
|
const pages = getCurrentPages();
|
|
122
|
-
let
|
|
123
|
-
let
|
|
124
|
-
//
|
|
121
|
+
let route: string;
|
|
122
|
+
let options: object;
|
|
123
|
+
let depth: number; // 页面深度
|
|
124
|
+
// 刚启动时首页未渲染
|
|
125
125
|
if (pages.length === 0) {
|
|
126
126
|
const launch = syncApi.getLaunchOptionsSync() as any;
|
|
127
|
-
|
|
127
|
+
route = launch.path;
|
|
128
|
+
options = launch.qurey;
|
|
129
|
+
depth = 1;
|
|
128
130
|
} else {
|
|
129
|
-
pageDepth = pages.length;
|
|
130
131
|
// 如果最后一个为空,则当前是在插件页,继续找上一个页面
|
|
131
|
-
page = pages.reverse().find((t:
|
|
132
|
+
const page = pages.reverse().find((t: any) => t);
|
|
133
|
+
route = page?.route;
|
|
134
|
+
options = page?.options;
|
|
135
|
+
depth = pages.length;
|
|
132
136
|
}
|
|
133
|
-
return {
|
|
137
|
+
return { route, options, depth };
|
|
134
138
|
}
|
|
135
139
|
|
|
136
|
-
let launchOptions:
|
|
140
|
+
let launchOptions: object | null = null;
|
|
137
141
|
|
|
138
142
|
/**
|
|
139
143
|
* 获取小程序启动参数
|
|
140
144
|
*/
|
|
141
|
-
function
|
|
145
|
+
function getLaunchOptions(): object {
|
|
142
146
|
if (launchOptions === null) {
|
|
143
|
-
|
|
144
|
-
launchOptions = JSON.stringify(obj);
|
|
147
|
+
launchOptions = syncApi.getLaunchOptionsSync();
|
|
145
148
|
}
|
|
146
149
|
return launchOptions;
|
|
147
150
|
}
|
|
@@ -157,9 +160,9 @@ function getLaunchFrom(): string {
|
|
|
157
160
|
/**
|
|
158
161
|
* 获取小程序启动场景值
|
|
159
162
|
*/
|
|
160
|
-
function getAppScene():
|
|
163
|
+
function getAppScene(): number {
|
|
161
164
|
const { scene = -1 } = syncApi.getLaunchOptionsSync() as any;
|
|
162
|
-
return scene
|
|
165
|
+
return scene;
|
|
163
166
|
}
|
|
164
167
|
|
|
165
168
|
// 是否爬虫
|
|
@@ -171,7 +174,7 @@ let isCrawler: boolean | null = null;
|
|
|
171
174
|
function canReport(): boolean {
|
|
172
175
|
if (isCrawler === null) {
|
|
173
176
|
const scene = getAppScene();
|
|
174
|
-
isCrawler = scene ===
|
|
177
|
+
isCrawler = scene === 1129 || scene === 1030;
|
|
175
178
|
}
|
|
176
179
|
// 小程序爬虫,不上报
|
|
177
180
|
return !isCrawler;
|
|
@@ -237,12 +240,11 @@ export default {
|
|
|
237
240
|
getTms,
|
|
238
241
|
getInitOptions,
|
|
239
242
|
getSystemInfo,
|
|
240
|
-
|
|
241
|
-
convert2String,
|
|
243
|
+
convert2StringArray,
|
|
242
244
|
getNowString,
|
|
243
245
|
getLifeReportKey,
|
|
244
246
|
getPageInfo,
|
|
245
|
-
|
|
247
|
+
getLaunchOptions,
|
|
246
248
|
getLaunchFrom,
|
|
247
249
|
getAppScene,
|
|
248
250
|
canReport,
|
package/src/report/sender.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import helper from './helper';
|
|
7
7
|
|
|
8
8
|
// 缓存队列
|
|
9
|
-
const cacheArr = new Array<
|
|
9
|
+
const cacheArr = new Array<string[]>();
|
|
10
10
|
const max = 50; // 超过最大限制就马上发送
|
|
11
11
|
const delay = 3000; // 延迟N毫秒再聚合发送
|
|
12
12
|
let timer = 0; // 计时器
|
|
@@ -73,6 +73,7 @@ function requestFail(batch: DataItem[][]): void {
|
|
|
73
73
|
*/
|
|
74
74
|
function send(arr: DataItem[]): void {
|
|
75
75
|
stopTimer();
|
|
76
|
+
helper.convert2StringArray(arr);
|
|
76
77
|
cacheArr.unshift(arr); // 如果队列中很多,排前面比较稳妥
|
|
77
78
|
batchSendData();
|
|
78
79
|
}
|
|
@@ -82,6 +83,7 @@ function send(arr: DataItem[]): void {
|
|
|
82
83
|
* @param arr
|
|
83
84
|
*/
|
|
84
85
|
function queue(arr: DataItem[]): void {
|
|
86
|
+
helper.convert2StringArray(arr);
|
|
85
87
|
cacheArr.push(arr);
|
|
86
88
|
checkQueue(false);
|
|
87
89
|
}
|
package/src/report/types.ts
CHANGED
package/src/timeUtils.js
CHANGED
|
@@ -110,9 +110,41 @@ const formatTimeStr = (str = '', dateSeprator = '.', keepSeconds = false) => {
|
|
|
110
110
|
return s;
|
|
111
111
|
};
|
|
112
112
|
|
|
113
|
+
/**
|
|
114
|
+
* 格式化时间对象
|
|
115
|
+
* @param {Date|Number} date Date对象
|
|
116
|
+
* @param {String} fmt 目标格式,如:yyyy年MM月dd日,MM/dd/yyyy,yyyyMMdd,yyyy-MM-dd hh:mm:ss等
|
|
117
|
+
* @returns {String} 格式化结果;异常情况下返回空串
|
|
118
|
+
*/
|
|
119
|
+
const formatDateTime = (date, fmt = 'yyyy-MM-dd hh:mm:ss') => {
|
|
120
|
+
const dateObj = date instanceof Date ? date : new Date(date);
|
|
121
|
+
if (isNaN(dateObj.getTime())) return '';
|
|
122
|
+
|
|
123
|
+
const obj = {
|
|
124
|
+
'M+': dateObj.getMonth() + 1, // 月份
|
|
125
|
+
'd+': dateObj.getDate(), // 日
|
|
126
|
+
'h+': dateObj.getHours(), // 小时
|
|
127
|
+
'm+': dateObj.getMinutes(), // 分
|
|
128
|
+
's+': dateObj.getSeconds(), // 秒
|
|
129
|
+
S: dateObj.getMilliseconds(), // 毫秒
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
let dateStr = fmt || 'yyyy-MM-dd hh:mm:ss';
|
|
133
|
+
if (/(y+)/.test(dateStr)) {
|
|
134
|
+
dateStr = dateStr.replace(RegExp.$1, (`${dateObj.getFullYear()}`).substr(4 - RegExp.$1.length));
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
Object.entries(obj).forEach(([key, value]) => {
|
|
138
|
+
if (new RegExp(`(${key})`).test(dateStr)) {
|
|
139
|
+
dateStr = dateStr.replace(RegExp.$1, (RegExp.$1.length === 1) ? (value) : (`${value}`.padStart(2, '0')));
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
return dateStr;
|
|
144
|
+
};
|
|
113
145
|
|
|
114
146
|
/**
|
|
115
|
-
* @description 格式化时间戳为 yyyy-
|
|
147
|
+
* @description 格式化时间戳为 yyyy-MM-dd, yyyy-MM-dd hh:mm, yyyy-MM-dd hh:mm:ss
|
|
116
148
|
* @param {Date} date 日期
|
|
117
149
|
* @param {Boolean} withTime 是否带时间
|
|
118
150
|
* @param {Boolean} withSeconds 是否带秒数
|
|
@@ -120,28 +152,13 @@ const formatTimeStr = (str = '', dateSeprator = '.', keepSeconds = false) => {
|
|
|
120
152
|
* @returns {String} 格式化后的字符串,如 2021-03-18 或者 2021-03-18 10:11
|
|
121
153
|
*/
|
|
122
154
|
const dateToString = (date, withTime = false, withSeconds = false, join = '-') => {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
const month = DATE.getMonth() + 1;
|
|
127
|
-
const day = DATE.getDate();
|
|
128
|
-
const time = DATE.toTimeString().slice(0, 8);
|
|
129
|
-
let dateStr = year + join + month + join + day;
|
|
130
|
-
|
|
131
|
-
if (!withTime) {
|
|
132
|
-
return dateStr.replace(/\b\d\b/g, '0$&');
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
dateStr = `${dateStr} ${time}`.replace(/\b\d\b/g, '0$&');
|
|
136
|
-
|
|
137
|
-
if (!withSeconds) {
|
|
138
|
-
dateStr = dateStr.slice(0, -3);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
return dateStr;
|
|
155
|
+
let fmt = `yyyy${join}MM${join}dd`;
|
|
156
|
+
if (withTime) fmt += withSeconds ? 'hh:mm:ss' : 'hh:mm';
|
|
157
|
+
return formatDateTime(date, fmt);
|
|
142
158
|
};
|
|
143
159
|
|
|
144
160
|
export {
|
|
161
|
+
formatDateTime,
|
|
145
162
|
formatTime,
|
|
146
163
|
formatTimeStr,
|
|
147
164
|
formatTimeWithDetails,
|