monitor-track 1.10.0

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.
Files changed (65) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +101 -0
  3. package/dist/CHANGELOG.md +21 -0
  4. package/dist/README.md +101 -0
  5. package/dist/cjs/config/global.d.ts +17 -0
  6. package/dist/cjs/config/index.d.ts +33 -0
  7. package/dist/cjs/constant.d.ts +2 -0
  8. package/dist/cjs/handlers/error.d.ts +23 -0
  9. package/dist/cjs/handlers/index.d.ts +3 -0
  10. package/dist/cjs/handlers/pv.d.ts +24 -0
  11. package/dist/cjs/handlers/user-activity.d.ts +9 -0
  12. package/dist/cjs/index.d.ts +30 -0
  13. package/dist/cjs/index.js +1485 -0
  14. package/dist/cjs/main.d.ts +1 -0
  15. package/dist/cjs/reporter.d.ts +198 -0
  16. package/dist/cjs/types/config.d.ts +59 -0
  17. package/dist/cjs/types/global.d.ts +70 -0
  18. package/dist/cjs/types/index.d.ts +189 -0
  19. package/dist/cjs/utils/index.d.ts +45 -0
  20. package/dist/esm/_virtual/_tslib.js +26 -0
  21. package/dist/esm/config/global.d.ts +17 -0
  22. package/dist/esm/config/global.js +271 -0
  23. package/dist/esm/config/index.d.ts +33 -0
  24. package/dist/esm/config/index.js +32 -0
  25. package/dist/esm/constant.d.ts +2 -0
  26. package/dist/esm/constant.js +4 -0
  27. package/dist/esm/handlers/error.d.ts +23 -0
  28. package/dist/esm/handlers/error.js +181 -0
  29. package/dist/esm/handlers/index.d.ts +3 -0
  30. package/dist/esm/handlers/pv.d.ts +24 -0
  31. package/dist/esm/handlers/pv.js +99 -0
  32. package/dist/esm/handlers/user-activity.d.ts +9 -0
  33. package/dist/esm/handlers/user-activity.js +66 -0
  34. package/dist/esm/index.d.ts +30 -0
  35. package/dist/esm/index.js +115 -0
  36. package/dist/esm/main.d.ts +1 -0
  37. package/dist/esm/package.json.js +3 -0
  38. package/dist/esm/reporter.d.ts +198 -0
  39. package/dist/esm/reporter.js +359 -0
  40. package/dist/esm/types/config.d.ts +59 -0
  41. package/dist/esm/types/global.d.ts +70 -0
  42. package/dist/esm/types/index.d.ts +189 -0
  43. package/dist/esm/utils/index.d.ts +45 -0
  44. package/dist/esm/utils/index.js +354 -0
  45. package/dist/index.js +1534 -0
  46. package/dist/package.json +41 -0
  47. package/package.json +42 -0
  48. package/rollup.config.js +66 -0
  49. package/scripts/cp.js +11 -0
  50. package/src/config/global.ts +309 -0
  51. package/src/config/index.ts +53 -0
  52. package/src/constant.ts +2 -0
  53. package/src/handlers/error.ts +187 -0
  54. package/src/handlers/index.ts +3 -0
  55. package/src/handlers/pv.ts +124 -0
  56. package/src/handlers/user-activity.ts +69 -0
  57. package/src/index.ts +127 -0
  58. package/src/main.ts +8 -0
  59. package/src/reporter.ts +372 -0
  60. package/src/types/config.ts +58 -0
  61. package/src/types/global.ts +73 -0
  62. package/src/types/index.ts +227 -0
  63. package/src/typing.d.ts +15 -0
  64. package/src/utils/index.ts +371 -0
  65. package/tsconfig.esm.json +14 -0
@@ -0,0 +1,45 @@
1
+ import { INavigator } from '../types';
2
+ /**
3
+ * @description 获取uuid
4
+ */
5
+ export declare function getUid(): string;
6
+ /**
7
+ * @description 获取session id
8
+ */
9
+ export declare function getSessionId(): string;
10
+ /**
11
+ * @description 获取浏览器信息
12
+ */
13
+ export declare function getNavigator(): INavigator;
14
+ /**
15
+ * @description 获取viewport的宽高
16
+ */
17
+ export declare function getViewport(): string;
18
+ /**
19
+ * @description 获取元素路径,最多保留5层
20
+ * @param e
21
+ */
22
+ export declare const getElmPath: (target: any) => string;
23
+ /**
24
+ * @description 序列化对象
25
+ * @param obj
26
+ */
27
+ export declare function serialize(obj: {
28
+ [key: string]: any;
29
+ }): string;
30
+ /**
31
+ * @description 注册事件监听
32
+ * @param event 事件
33
+ * @param fn 回调方法
34
+ */
35
+ export declare const on: (event: string, fn: (e: Event) => void) => void;
36
+ /**
37
+ * @description 移除事件监听
38
+ * @param event 事件
39
+ * @param fn 回调方法
40
+ */
41
+ export declare const off: (event: any, fn: (e: Event) => void) => any;
42
+ export declare const visualTrackFunc: () => void;
43
+ export declare const initWindowObjectFunction: () => void;
44
+ export declare const handleLocationChange: (e: Event) => void;
45
+ export declare function debounce(fn: Function): (...arg: unknown[]) => void;
@@ -0,0 +1,354 @@
1
+ import { __awaiter } from '../_virtual/_tslib.js';
2
+ import axios from 'axios';
3
+ import { v4 } from 'uuid';
4
+ import { UAParser } from 'ua-parser-js';
5
+ import { shuyunTrackSessionId, shuyunTrackId } from '../constant.js';
6
+ import { setReportValue, getReport } from '../config/global.js';
7
+ import { report } from '../reporter.js';
8
+ import { Config } from '../config/index.js';
9
+ import { version } from '../package.json.js';
10
+ import { getUserEvents, getFullScreenShoot } from '../handlers/error.js';
11
+ import { handleHistoryChange } from '../handlers/pv.js';
12
+
13
+ const parser = new UAParser();
14
+ /**
15
+ * @description 获取uuid
16
+ */
17
+ function getUid() {
18
+ let uid = localStorage.getItem(shuyunTrackId) || '';
19
+ if (!uid) {
20
+ uid = v4();
21
+ localStorage.setItem(shuyunTrackId, uid);
22
+ }
23
+ return uid;
24
+ }
25
+ /**
26
+ * @description 获取session id
27
+ */
28
+ function getSessionId() {
29
+ const sessionId = sessionStorage.getItem(shuyunTrackSessionId);
30
+ if (sessionId) {
31
+ return sessionId;
32
+ }
33
+ else {
34
+ const id = v4();
35
+ sessionStorage.setItem(shuyunTrackSessionId, id);
36
+ return id;
37
+ }
38
+ }
39
+ /**
40
+ * @description 获取浏览器信息
41
+ */
42
+ function getNavigator() {
43
+ var _a;
44
+ const uaResult = parser.getResult();
45
+ return {
46
+ language: navigator.language,
47
+ navigatorVendor: navigator.vendor,
48
+ connectionType: ((_a = navigator === null || navigator === void 0 ? void 0 : navigator.connection) === null || _a === void 0 ? void 0 : _a.effectiveType) || '2g',
49
+ browserName: uaResult.browser.name || '',
50
+ browserVersion: uaResult.browser.version || '',
51
+ engineName: uaResult.engine.name || '',
52
+ engineVersion: uaResult.engine.version || '',
53
+ osName: uaResult.os.name || '',
54
+ osVersion: uaResult.os.version || '',
55
+ };
56
+ }
57
+ /**
58
+ * @description 获取viewport的宽高
59
+ */
60
+ function getViewport() {
61
+ const w = document.documentElement.clientWidth || document.body.clientWidth;
62
+ const h = document.documentElement.clientHeight || document.body.clientHeight;
63
+ return `${w} x ${h}`;
64
+ }
65
+ /**
66
+ * @description 获取元素路径,最多保留5层
67
+ * @param e
68
+ */
69
+ const getElmPath = function (target) {
70
+ if (!target || target.nodeType !== 1) {
71
+ return '';
72
+ }
73
+ const ret = [];
74
+ // 层数,最多5层
75
+ let deepLength = 0;
76
+ // 元素
77
+ let elm = '';
78
+ if (typeof target.innerText === 'string') {
79
+ ret.push(`(${target.innerText.substr(0, 50)})`);
80
+ }
81
+ for (let t = target || null; t && deepLength++ < 5 && !((elm = normalTarget(t)) === 'html');) {
82
+ // eslint-disable-next-line no-sequences
83
+ ret.push(elm), (t = t.parentNode);
84
+ }
85
+ return ret.reverse().join(' > ');
86
+ };
87
+ /**
88
+ * @description 处理html node
89
+ * @param e
90
+ */
91
+ const normalTarget = function (target) {
92
+ let t, n, r, a, i;
93
+ const o = [];
94
+ if (!target || !target.tagName) {
95
+ return '';
96
+ }
97
+ o.push(target.tagName.toLowerCase());
98
+ if (target.id) {
99
+ o.push('#'.concat(target.id));
100
+ }
101
+ if ((t = target.className) && Object.prototype.toString.call(t) === '[object String]') {
102
+ for (n = t.split(/\s+/), i = 0; i < n.length; i++) {
103
+ // className包含active的不加入路径
104
+ if (n[i].indexOf('active') < 0)
105
+ o.push('.'.concat(n[i]));
106
+ }
107
+ }
108
+ const s = ['type', 'name', 'title', 'alt'];
109
+ for (i = 0; i < s.length; i++) {
110
+ r = s[i];
111
+ if ((a = target.getAttribute(r))) {
112
+ o.push('['.concat(r, '="').concat(a, '"]'));
113
+ }
114
+ }
115
+ return o.join('');
116
+ };
117
+ /**
118
+ * @description 序列化对象
119
+ * @param obj
120
+ */
121
+ function serialize(obj) {
122
+ const str = [];
123
+ for (const p in obj) {
124
+ if (Object.prototype.hasOwnProperty.call(obj, p) && typeof obj[p] !== 'undefined') {
125
+ const value = typeof obj[p] === 'object' ? JSON.stringify(obj[p]) : obj[p];
126
+ str.push(encodeURIComponent(p) + '=' + encodeURIComponent(value));
127
+ }
128
+ }
129
+ return str.join('&');
130
+ }
131
+ /**
132
+ * @description 注册事件监听
133
+ * @param event 事件
134
+ * @param fn 回调方法
135
+ */
136
+ const on = function (event, fn) {
137
+ if (window.addEventListener) {
138
+ window.addEventListener(event, fn, true);
139
+ }
140
+ else {
141
+ window.attachEvent(`on${event}`, fn);
142
+ }
143
+ };
144
+ /**
145
+ * @description 移除事件监听
146
+ * @param event 事件
147
+ * @param fn 回调方法
148
+ */
149
+ const off = function (event, fn) {
150
+ if (window.removeEventListener) {
151
+ return window.removeEventListener(event, fn);
152
+ }
153
+ else {
154
+ return window.detachEvent(`on${event}`, fn);
155
+ }
156
+ };
157
+ const formatTrackElementXPath = (xPath) => {
158
+ const result = [];
159
+ const array = xPath.split('/');
160
+ array.forEach((item) => {
161
+ if (!['svg', 'path', 'g', 'image', 'text', 'line', 'rect', 'polygon', 'circle', 'ellipse'].some((child) => {
162
+ if (item.toLowerCase().split('[')[0] === child) {
163
+ result.push(`/*[name()="${child}"]`);
164
+ return true;
165
+ }
166
+ else {
167
+ return false;
168
+ }
169
+ })) {
170
+ result.push(item);
171
+ }
172
+ });
173
+ return result.join('/');
174
+ };
175
+ const formatElementXPath = (info) => {
176
+ var _a;
177
+ let elementXPathValue = '';
178
+ const elementXPath = info.elementXPath;
179
+ if (elementXPath) {
180
+ const xpathElement = document.evaluate(formatTrackElementXPath(elementXPath), document).iterateNext();
181
+ elementXPathValue = xpathElement ? (_a = (xpathElement.textContent || xpathElement.value)) === null || _a === void 0 ? void 0 : _a.trim() : '';
182
+ }
183
+ return {
184
+ elementXPath,
185
+ elementXPathValue,
186
+ };
187
+ };
188
+ let existTrackListenEvent = {};
189
+ const elements = [];
190
+ let timeout;
191
+ const visualTrackFunc = () => {
192
+ if (Config.enableVisualTrack) {
193
+ if (timeout)
194
+ clearTimeout(timeout);
195
+ timeout = setTimeout(() => {
196
+ timeout = null;
197
+ const url = location.href.split('?')[0];
198
+ axios
199
+ .get(`${Config.reportUrl.replace('/s/r', '')}/visual/get_data_list?url=${encodeURIComponent(url)}`)
200
+ .then((res) => {
201
+ var _a, _b;
202
+ const listData = (_b = (_a = res.data.result) === null || _a === void 0 ? void 0 : _a.result) === null || _b === void 0 ? void 0 : _b.dataList;
203
+ if (Array.isArray(listData)) {
204
+ try {
205
+ listData.forEach((item) => {
206
+ if (item.trackType === 'mount') {
207
+ visualReportEvent(item);
208
+ }
209
+ else {
210
+ const element = document
211
+ .evaluate(formatTrackElementXPath(item.trackElementXPath), document)
212
+ .iterateNext();
213
+ const key = url + item.trackElementXPath;
214
+ if (element) {
215
+ if (!existTrackListenEvent[key]) {
216
+ existTrackListenEvent[key] = true;
217
+ elements.push(element);
218
+ //@ts-ignore
219
+ element.setAttribute('visual-track-data-attr', JSON.stringify(item));
220
+ element.addEventListener('click', clickEventFunc);
221
+ }
222
+ }
223
+ else {
224
+ const func = () => {
225
+ var _a;
226
+ const { browserName, browserVersion } = getNavigator();
227
+ const payload = {
228
+ projectID: Config.projectID,
229
+ version,
230
+ url,
231
+ trackElementXPath: item.trackElementXPath,
232
+ trackNameInfo: item.trackNameInfo,
233
+ params: item.params,
234
+ customPayload: Config.customPayload,
235
+ type: 'visual_track_xpath_not_found',
236
+ browser: `${browserName} - ${browserVersion}`,
237
+ };
238
+ if (typeof ((_a = window.navigator) === null || _a === void 0 ? void 0 : _a.sendBeacon) === 'function') {
239
+ const formData = new FormData();
240
+ for (const i in payload) {
241
+ if (Object.prototype.hasOwnProperty.call(payload, i)) {
242
+ const value = payload[i];
243
+ formData.append(i, value && typeof value === 'object' ? JSON.stringify(value) : value);
244
+ }
245
+ }
246
+ window.navigator.sendBeacon(Config.reportUrl, formData);
247
+ }
248
+ else {
249
+ new Image().src = `${Config.reportUrl}?${serialize(payload)}`;
250
+ }
251
+ };
252
+ if (typeof window.requestIdleCallback === 'function') {
253
+ window.requestIdleCallback(() => func(), { timeout: 2000 });
254
+ }
255
+ else {
256
+ setTimeout(() => func(), 0);
257
+ }
258
+ }
259
+ }
260
+ });
261
+ }
262
+ catch (err) {
263
+ // eslint-disable-next-line no-console
264
+ console.log('visual track evaluate err', err);
265
+ }
266
+ }
267
+ });
268
+ }, 1000);
269
+ }
270
+ };
271
+ const visualReportEvent = (item) => {
272
+ var _a;
273
+ const { elementXPath, elementXPathValue } = formatElementXPath(item.trackNameInfo);
274
+ const visualTrackData = {
275
+ trackType: item.trackType,
276
+ trackName: elementXPath ? elementXPathValue : item.trackNameInfo.name,
277
+ params: (_a = item.params) === null || _a === void 0 ? void 0 : _a.map((child) => {
278
+ const { elementXPath, elementXPathValue } = formatElementXPath(child);
279
+ return {
280
+ name: child.name,
281
+ value: elementXPath ? elementXPathValue : child.value,
282
+ };
283
+ }),
284
+ };
285
+ setReportValue('type', 'visual');
286
+ setReportValue('vD', visualTrackData);
287
+ report(getReport());
288
+ setReportValue('vD', undefined);
289
+ };
290
+ const clickEventFunc = (e) => {
291
+ //@ts-ignore
292
+ const item = JSON.parse(e.target.getAttribute('visual-track-data-attr'));
293
+ visualReportEvent(item);
294
+ };
295
+ const initWindowObjectFunction = () => {
296
+ if (typeof window.manualReportTrackFunc === 'undefined') {
297
+ window.manualReportTrackFunc = (data) => {
298
+ if (Object.prototype.toString.call(data) !== '[object Object]') {
299
+ // eslint-disable-next-line no-console
300
+ console.warn('manualReportTrackFunc参数必须是一个对象!');
301
+ }
302
+ else {
303
+ setReportValue('type', 'manual');
304
+ setReportValue('manualReport', data);
305
+ report(getReport());
306
+ setReportValue('manualReport', undefined);
307
+ }
308
+ };
309
+ }
310
+ if (typeof window.getFullScreenShootFunc === 'undefined') {
311
+ //下载页面截图
312
+ window.getFullScreenShootFunc = (filename) => __awaiter(void 0, void 0, void 0, function* () {
313
+ const file = yield getFullScreenShoot(filename);
314
+ const url = window.URL.createObjectURL(file);
315
+ const tagA = document.createElement('a');
316
+ tagA.setAttribute('href', url);
317
+ tagA.setAttribute('download', file.name);
318
+ tagA.setAttribute('target', '_blank');
319
+ document.body.appendChild(tagA);
320
+ tagA.click();
321
+ document.body.removeChild(tagA);
322
+ });
323
+ }
324
+ if (typeof window.getRRWebUserEventsCaptureFunc === 'undefined') {
325
+ window.getRRWebUserEventsCaptureFunc = () => {
326
+ setReportValue('type', 'error');
327
+ setReportValue('error', {
328
+ subType: 'manual',
329
+ message: 'manual trigger',
330
+ events: getUserEvents(true),
331
+ });
332
+ report(getReport());
333
+ };
334
+ }
335
+ };
336
+ let prewHref = '';
337
+ const handleLocationChange = (e) => {
338
+ const curHref = location.href;
339
+ // href中`?`后面的值改变,不触发后续动作
340
+ if (prewHref.split('?')[0] === curHref.split('?')[0]) {
341
+ return;
342
+ }
343
+ prewHref = curHref;
344
+ handleHistoryChange();
345
+ elements.forEach((element) => {
346
+ element === null || element === void 0 ? void 0 : element.removeEventListener('click', clickEventFunc);
347
+ });
348
+ //清空可视化埋点之前的数据
349
+ existTrackListenEvent = {};
350
+ elements.length = 0;
351
+ visualTrackFunc();
352
+ };
353
+
354
+ export { getElmPath, getNavigator, getSessionId, getUid, getViewport, handleLocationChange, initWindowObjectFunction, off, on, serialize, visualTrackFunc };