visual-buried-point-platform-h5 1.3.4

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.
@@ -0,0 +1,882 @@
1
+ import { Config, getConfig } from "./config";
2
+ import {
3
+ each,
4
+ parseHash,
5
+ warn,
6
+ splitGroup,
7
+ on,
8
+ off,
9
+ isInIframe,
10
+ findIndex,
11
+ checkEdge,
12
+ getLocationHref,
13
+ parsePVUVUrl,
14
+ } from "./utils/tools";
15
+ import { getCommonMsg } from "./utils/index";
16
+ import { request } from "./reporter";
17
+ import {
18
+ setGlobalPage,
19
+ setGlobalSid,
20
+ setGlobalHealth,
21
+ GlobalVal,
22
+ resetGlobalHealth,
23
+ } from "./config/global";
24
+ import { getPathSelector, getXPath } from "./utils/getXPath";
25
+ import { lazyReportCache } from "./utils/lazyReport";
26
+ import {
27
+ ApiMsg,
28
+ avgMsg,
29
+ Behavior,
30
+ behaviorMsg,
31
+ CommonMsg,
32
+ ErrorMsg,
33
+ eventBehavior,
34
+ healthMsg,
35
+ msgMsg,
36
+ perfMsg,
37
+ pvMsg,
38
+ ResourceMsg,
39
+ sumMsg,
40
+ } from "./typings";
41
+
42
+ const CIRCLE_CLASS = "circle-active"; // circle class类名
43
+ const CIRCLE_STYLE_ID = "circle-css-id"; // 插入的style标签id
44
+ // 处理pv
45
+ export function handlePv(page: string): void {
46
+ if (!Config.autoSendPv) return;
47
+ let commonMsg = getCommonMsg();
48
+ let locationPath = getLocationHref();
49
+ let msg: pvMsg = {
50
+ ...commonMsg,
51
+ ...{
52
+ t: "pv",
53
+ dt: document.title,
54
+ dl: locationPath,
55
+ dr: document.referrer,
56
+ dpr: window.devicePixelRatio,
57
+ // de: document.charset,
58
+ },
59
+ page,
60
+ };
61
+ setTimeout(() => {
62
+ parsePVUVUrl();
63
+ }, 50);
64
+ window.parent.postMessage({ ...msg, isOpen: true }, "*");
65
+ lazyReportCache(msg);
66
+ }
67
+
68
+ // 处理html node
69
+ const normalTarget = function (e) {
70
+ var t,
71
+ n,
72
+ r,
73
+ a,
74
+ i,
75
+ o = [];
76
+ if (!e || !e.tagName) return "";
77
+ if (
78
+ (o.push(e.tagName.toLowerCase()),
79
+ e.id && o.push("#".concat(e.id)),
80
+ (t = e.className) &&
81
+ "[object String]" === Object.prototype.toString.call(t))
82
+ ) {
83
+ for (n = t.split(/\s+/), i = 0; i < n.length; i++) {
84
+ // className包含active的不加入路径
85
+ if (n[i].indexOf("active") < 0) o.push(".".concat(n[i]));
86
+ }
87
+ }
88
+ var s = ["type", "name", "title", "alt"];
89
+ for (i = 0; i < s.length; i++)
90
+ (r = s[i]),
91
+ (a = e.getAttribute(r)) && o.push("[".concat(r, '="').concat(a, '"]'));
92
+ return o.join("");
93
+ };
94
+
95
+ // 获取元素路径,最多保留5层
96
+ const getElmPath = function (e) {
97
+ if (!e || 1 !== e.nodeType) return "";
98
+ var ret = [],
99
+ deepLength = 0, // 层数,最多5层
100
+ elm = ""; // 元素
101
+ ret.push(`(${e.innerText.substr(0, 30)})`);
102
+ for (
103
+ var t = e || null;
104
+ t && deepLength++ < 5 && !("html" === (elm = normalTarget(t)));
105
+
106
+ ) {
107
+ ret.push(elm), (t = t.parentNode);
108
+ }
109
+ return ret.reverse().join(" > ");
110
+ };
111
+ // 圈选方法及点击事件拦截
112
+ export function handleClick(event) {
113
+ // 附加参数
114
+ const params = getCommonMsg();
115
+ const _target = event.target || event.srcElement;
116
+ let clientHeight =
117
+ document.documentElement.clientHeight || document.body.clientHeight;
118
+ let clientWidth =
119
+ document.documentElement.clientWidth || document.body.clientWidth;
120
+ let path = getXPath(_target);
121
+ let selector = getPathSelector(_target);
122
+ let targetInnerText = "";
123
+ if (_target.innerText) {
124
+ targetInnerText =
125
+ _target.innerText.length > 30
126
+ ? _target.innerText.substring(0, 30)
127
+ : _target.innerText;
128
+ }
129
+
130
+ let postMessageData = {
131
+ type: "setElmPath",
132
+ page: GlobalVal.page,
133
+ data: {
134
+ time: params.timestamp,
135
+ event: event.type,
136
+ type: event.type,
137
+ properties: {
138
+ $screen_height: screen.height,
139
+ $screen_width: screen.width,
140
+ $viewport_height: clientHeight,
141
+ $viewport_width: clientWidth,
142
+ $lib: "js",
143
+ $lib_version: params.sdk_version,
144
+ $element_type: _target.tagName.toLocaleLowerCase() || "",
145
+ $element_class_name: _target.className,
146
+ $element_content: targetInnerText,
147
+ $url: params.original_url,
148
+ $url_path: "/",
149
+ $title: document.title,
150
+ $element_selector: selector,
151
+ $element_path: path,
152
+ $page_x: _target.offsetLeft,
153
+ $page_y: _target.offsetTop,
154
+ },
155
+ },
156
+ };
157
+ // 正在圈选
158
+ if (GlobalVal.circle) {
159
+ let target = event.target;
160
+ let clsArray = target.className.split(/\s+/);
161
+ let path = getElmPath(event.target);
162
+ // clsArray 为 ['circle-active] 或 ['', 'circle-active]时
163
+ if (
164
+ clsArray.length === 1 ||
165
+ (clsArray.length === 2 && clsArray[0] === "")
166
+ ) {
167
+ path = path.replace(/\.\.circle-active/, "");
168
+ } else {
169
+ path = path.replace(/\.circle-active/, "");
170
+ }
171
+ window.parent.postMessage({ ...postMessageData, isOpen: true }, "*");
172
+ // 圈选的时候阻止默认事件
173
+ event.preventDefault();
174
+ event.stopPropagation();
175
+ return;
176
+ }
177
+ // 非圈选点击事件上报
178
+ let target;
179
+ try {
180
+ target = event.target;
181
+ } catch (u) {
182
+ target = "<unknown>";
183
+ }
184
+
185
+ if (target.nodeName === "INPUT" || target.nodeName === "TEXTAREA") return;
186
+
187
+ if (0 !== target.length) {
188
+ // 空信息不上报
189
+ if (!postMessageData.data.properties["$element_path"]) return;
190
+ lazyReportCache({ ...postMessageData, t: "behavior" });
191
+ }
192
+ }
193
+
194
+ export function handleBlur(event) {
195
+ var target;
196
+ try {
197
+ target = event.target;
198
+ } catch (u) {
199
+ target = "<unknown>";
200
+ }
201
+ if (target.nodeName !== "INPUT" && target.nodeName !== "TEXTAREA") return;
202
+
203
+ if (0 !== target.length) {
204
+ var behavior: eventBehavior = {
205
+ type: "ui.blur",
206
+ data: {
207
+ path: getElmPath(target),
208
+ message: target.value,
209
+ },
210
+ };
211
+ // 空信息不上报
212
+ if (!behavior.data.path || !behavior.data.message) return;
213
+ let commonMsg = getCommonMsg();
214
+ let msg: behaviorMsg = {
215
+ ...commonMsg,
216
+ ...{
217
+ t: "behavior",
218
+ behavior,
219
+ },
220
+ };
221
+ lazyReportCache(msg);
222
+ }
223
+ }
224
+ // 用户行为监听
225
+ export function handleBehavior(behavior: Behavior): void {
226
+ let commonMsg = getCommonMsg();
227
+ let msg: behaviorMsg = {
228
+ ...commonMsg,
229
+ ...{
230
+ t: "behavior",
231
+ behavior,
232
+ },
233
+ };
234
+ lazyReportCache(msg);
235
+ }
236
+
237
+ const TIMING_KEYS = [
238
+ "",
239
+ "fetchStart",
240
+ "domainLookupStart",
241
+ "domainLookupEnd",
242
+ "connectStart",
243
+ "connectEnd",
244
+ "requestStart",
245
+ "responseStart",
246
+ "responseEnd",
247
+ "",
248
+ "domInteractive",
249
+ "",
250
+ "domContentLoadedEventEnd",
251
+ "",
252
+ "loadEventStart",
253
+ "",
254
+ "msFirstPaint",
255
+ "secureConnectionStart",
256
+ ];
257
+
258
+ // 页面性能数据收集
259
+ export function handlePerf(): void {
260
+ const performance = window.performance;
261
+ if (!performance || "object" !== typeof performance) return;
262
+ let data: any = {
263
+ dns: 0, // DNS查询 domainLookupEnd - domainLookupStart
264
+ tcp: 0, // TCP链接
265
+ ssl: 0, // SSL建连
266
+ ttfb: 0, // 请求响应
267
+ trans: 0,
268
+ dom: 0,
269
+ res: 0,
270
+ firstbyte: 0,
271
+ fpt: 0,
272
+ tti: 0,
273
+ ready: 0,
274
+ load: 0, // domready时间
275
+ },
276
+ timing: any = performance.timing || {},
277
+ now = Date.now(),
278
+ type = 1;
279
+ let stateCheck = setInterval(() => {
280
+ if (timing.loadEventEnd) {
281
+ clearInterval(stateCheck);
282
+
283
+ // 根据PerformanceNavigationTiming计算更准确
284
+ if ("function" == typeof window.PerformanceNavigationTiming) {
285
+ var c = performance.getEntriesByType("navigation")[0];
286
+ c && ((timing = c), (type = 2));
287
+ }
288
+
289
+ // 计算data
290
+ each(
291
+ {
292
+ dns: [3, 2],
293
+ tcp: [5, 4],
294
+ ssl: [5, 17],
295
+ ttfb: [7, 6],
296
+ trans: [8, 7],
297
+ dom: [10, 8],
298
+ res: [14, 12],
299
+ firstbyte: [7, 2],
300
+ fpt: [8, 1],
301
+ tti: [10, 1],
302
+ ready: [12, 1],
303
+ load: [14, 1],
304
+ },
305
+ function (e, t) {
306
+ var r = timing[TIMING_KEYS[e[1]]],
307
+ o = timing[TIMING_KEYS[e[0]]];
308
+ var c = Math.round(o - r);
309
+ if (2 === type || (r !== undefined && o !== undefined)) {
310
+ if (t === "dom") {
311
+ var c = Math.round(o - r);
312
+ }
313
+ c >= 0 && c < 36e5 && (data[t] = c);
314
+ }
315
+ }
316
+ );
317
+
318
+ var u =
319
+ window.navigator.connection ||
320
+ (window.navigator as any).mozConnection ||
321
+ (window.navigator as any).webkitConnection,
322
+ f = performance.navigation || { type: undefined };
323
+ data.network = u ? u.effectiveType || u.type : "";
324
+ var l = u ? u.downlink || u.downlinkMax || u.bandwidth || null : null;
325
+ if (
326
+ ((l = l > 999 ? 999 : l) && (data.bandwidth = l),
327
+ (data.navtype = 1 === f.type ? "Reload" : "Other"),
328
+ 1 === type && timing[TIMING_KEYS[16]] > 0 && timing[TIMING_KEYS[1]] > 0)
329
+ ) {
330
+ var h = timing[TIMING_KEYS[16]] - timing[TIMING_KEYS[1]];
331
+ h >= 0 && h < 36e5 && (data.fpt = h);
332
+ }
333
+ 1 === type && timing[TIMING_KEYS[1]] > 0
334
+ ? (data.begin = timing[TIMING_KEYS[1]])
335
+ : 2 === type && data.load > 0
336
+ ? (data.begin = now - data.load)
337
+ : (data.begin = now);
338
+ let commonMsg = getCommonMsg();
339
+ let msg: perfMsg = {
340
+ ...commonMsg,
341
+ t: "perf",
342
+ ...data,
343
+ };
344
+ lazyReportCache(msg);
345
+ }
346
+ }, 50);
347
+ }
348
+
349
+ // 处理hash变化
350
+ // 注意在路由栈的路由不会触发
351
+ export function handleHashchange(): void {
352
+ let page = Config.enableSPA
353
+ ? parseHash(location.hash.toLowerCase())
354
+ : location.pathname.toLowerCase();
355
+ page && setPage(page, false);
356
+ }
357
+
358
+ // 处理hash变化
359
+ export function handleHistorystatechange(e): void {
360
+ let page = Config.enableSPA
361
+ ? parseHash(location.hash.toLowerCase())
362
+ : e.detail.toLowerCase();
363
+ page && setPage(page, false);
364
+ }
365
+
366
+ // 处理pv
367
+ export function handleNavigation(page): void {
368
+ let commonMsg = getCommonMsg();
369
+ let msg: behaviorMsg = {
370
+ ...commonMsg,
371
+ ...{
372
+ t: "behavior",
373
+ behavior: {
374
+ type: "navigation",
375
+ data: {
376
+ from: commonMsg.page,
377
+ to: page,
378
+ },
379
+ },
380
+ },
381
+ };
382
+ lazyReportCache(msg);
383
+ }
384
+
385
+ export function setPage(page, isFirst?: boolean) {
386
+ !isFirst && handleHealth();
387
+ handleNavigation(page);
388
+ if (isInIframe) {
389
+ let locationPath = getLocationHref();
390
+ window.parent.postMessage(
391
+ {
392
+ t: "setPage",
393
+ href: locationPath,
394
+ page,
395
+ },
396
+ "*"
397
+ );
398
+ }
399
+ setGlobalPage(page);
400
+ setGlobalSid();
401
+ handlePv(page);
402
+ }
403
+
404
+ export function handleHealth() {
405
+ let healthy = GlobalVal._health.errcount ? 0 : 1;
406
+ let commonMsg = getCommonMsg();
407
+ let ret: healthMsg = {
408
+ ...commonMsg,
409
+ ...GlobalVal._health,
410
+ ...{
411
+ t: "health",
412
+ healthy, // 健康? 0/1
413
+ stay: Date.now() - GlobalVal.sBegin, // 停留时间
414
+ leavetime: new Date().getTime(), //离开页面的事件
415
+ },
416
+ };
417
+ resetGlobalHealth();
418
+ lazyReportCache(ret);
419
+ }
420
+
421
+ // 处理错误
422
+ export function handleErr(error): void {
423
+ switch (error.type) {
424
+ case "error":
425
+ error instanceof ErrorEvent
426
+ ? reportCaughtError(error)
427
+ : reportResourceError(error);
428
+ break;
429
+ case "unhandledrejection":
430
+ reportPromiseError(error);
431
+ break;
432
+ // case 'httpError':
433
+ // reportHttpError(error)
434
+ // break;
435
+ }
436
+ setGlobalHealth("error");
437
+ }
438
+
439
+ // 捕获js异常
440
+ function reportCaughtError(error: any): void {
441
+ let commonMsg = getCommonMsg();
442
+ let n = error.name || "CustomError",
443
+ a = error.message || "",
444
+ i = error.error.stack || "";
445
+ let msg: ErrorMsg = {
446
+ ...commonMsg,
447
+ ...{
448
+ t: "error",
449
+ st: "caughterror",
450
+ cate: n, // 类别
451
+ msg: a && a.substring(0, 1e3), // 信息
452
+ detail: i && i.substring(0, 1e3), // 错误栈
453
+ file: error.filename || "", // 出错文件
454
+ line: error.lineno || "", // 行
455
+ col: error.colno || "", // 列
456
+ },
457
+ };
458
+ lazyReportCache(msg);
459
+ }
460
+
461
+ // 捕获资源异常
462
+ function reportResourceError(error: any): void {
463
+ let commonMsg = getCommonMsg();
464
+ let target = error.target;
465
+ let msg: ErrorMsg = {
466
+ ...commonMsg,
467
+ ...{
468
+ t: "error",
469
+ st: "resource",
470
+ msg: target.outerHTML,
471
+ file: target.src,
472
+ stack: target.localName.toUpperCase(),
473
+ },
474
+ };
475
+ lazyReportCache(msg);
476
+ }
477
+
478
+ // 捕获promise异常
479
+ function reportPromiseError(error: any): void {
480
+ let commonMsg = getCommonMsg();
481
+ let msg: ErrorMsg = {
482
+ ...commonMsg,
483
+ ...{
484
+ t: "error",
485
+ st: "promise",
486
+ msg: error.reason,
487
+ },
488
+ };
489
+ lazyReportCache(msg);
490
+ }
491
+
492
+ function reportHttpError(msg: CommonMsg, data: any): void {
493
+ // msg.records = [
494
+ // {
495
+ // type:'httpError',
496
+ // data:{
497
+ // occurTime:new Date().getTime(),
498
+ // title:document.title,
499
+ // url:window.location.href,
500
+ // userAgent:window.navigator.userAgent,
501
+ // method:data.method ? data.method : 'GET',
502
+ // status:data.status,
503
+ // statusText:data.statusText,
504
+ // response:data.response,
505
+ // requestUrl:data.url || data.requestUrl
506
+ // }
507
+ // }
508
+ // ]
509
+ // new Image().src = `${Config.reportUrl}?commit=${queryString(msg)}`
510
+ }
511
+
512
+ export function handleResource() {
513
+ var performance = window.performance;
514
+ if (
515
+ !performance ||
516
+ "object" != typeof performance ||
517
+ "function" != typeof performance.getEntriesByType
518
+ )
519
+ return null;
520
+ let commonMsg = getCommonMsg();
521
+ let msg: ResourceMsg = {
522
+ ...commonMsg,
523
+ ...{
524
+ dom: 0,
525
+ load: 0,
526
+ t: "res",
527
+ res: [],
528
+ },
529
+ };
530
+ var i = performance.timing || {},
531
+ o = performance.getEntriesByType("resource") || [];
532
+ if ("function" == typeof window.PerformanceNavigationTiming) {
533
+ var s = performance.getEntriesByType("navigation")[0];
534
+ s && (i = s);
535
+ }
536
+ each(
537
+ {
538
+ dom: [10, 8],
539
+ load: [14, 1],
540
+ },
541
+ function (e, t) {
542
+ var r = i[TIMING_KEYS[e[1]]],
543
+ o = i[TIMING_KEYS[e[0]]];
544
+ if (r !== undefined && o !== undefined) {
545
+ var s = Math.round(o - r);
546
+ s >= 0 && s < 36e5 && (msg[t] = s);
547
+ }
548
+ }
549
+ );
550
+ // 过滤忽略的url
551
+ o = o.filter((item) => {
552
+ var include = findIndex(
553
+ getConfig("ignore")?.ignoreApis,
554
+ (ignoreApi) => item.name.indexOf(ignoreApi) > -1
555
+ );
556
+ return include > -1 ? false : true;
557
+ });
558
+
559
+ // 兼容Edge浏览器无法直接使用PerformanceResourceTiming对象类型的数据进行上报,处理方式是定义变量重新赋值
560
+ if (checkEdge()) {
561
+ var edgeResources = [];
562
+ each(o, function (oItem) {
563
+ edgeResources.push({
564
+ connectEnd: oItem.connectEnd,
565
+ connectStart: oItem.connectStart,
566
+ domainLookupEnd: oItem.connectStart,
567
+ domainLookupStart: oItem.domainLookupStart,
568
+ duration: oItem.duration,
569
+ entryType: oItem.entryType,
570
+ fetchStart: oItem.fetchStart,
571
+ initiatorType: oItem.initiatorType,
572
+ name: oItem.name,
573
+ redirectEnd: oItem.redirectEnd,
574
+ redirectStart: oItem.redirectStart,
575
+ responseEnd: oItem.responseEnd,
576
+ responseStart: oItem.responseStart,
577
+ startTime: oItem.startTime,
578
+ });
579
+ });
580
+ o = edgeResources;
581
+ }
582
+
583
+ msg.res = o;
584
+ lazyReportCache(msg);
585
+ }
586
+
587
+ export function handleApi(url, success, time, code, msg, beigin) {
588
+ if (!url) {
589
+ warn("[retcode] api is null");
590
+ return;
591
+ }
592
+ // 设置健康状态
593
+ setGlobalHealth("api", success);
594
+
595
+ let commonMsg = getCommonMsg();
596
+ let apiMsg: ApiMsg = {
597
+ ...commonMsg,
598
+ ...{
599
+ t: "api",
600
+ beigin,
601
+ url, // 接口
602
+ success, // 成功?
603
+ time, // 耗时
604
+ code, // 接口返回的code
605
+ msg, // 信息
606
+ },
607
+ };
608
+ // 过滤忽略的url
609
+ var include = findIndex(
610
+ getConfig("ignore").ignoreApis,
611
+ (ignoreApi) => url.indexOf(ignoreApi) > -1
612
+ );
613
+ if (include > -1) return;
614
+ lazyReportCache(apiMsg);
615
+ }
616
+
617
+ export function handleSum(key: string, val: number = 1) {
618
+ let commonMsg = getCommonMsg();
619
+ let g = splitGroup(key);
620
+ let ret: sumMsg = {
621
+ ...commonMsg,
622
+ ...g,
623
+ ...{
624
+ t: "sum",
625
+ val,
626
+ },
627
+ };
628
+ lazyReportCache(ret);
629
+ }
630
+
631
+ export function handleAvg(key: string, val: number = 1) {
632
+ let commonMsg = getCommonMsg();
633
+ let g = splitGroup(key);
634
+ let ret: avgMsg = {
635
+ ...commonMsg,
636
+ ...g,
637
+ ...{
638
+ t: "avg",
639
+ val,
640
+ },
641
+ };
642
+ lazyReportCache(ret);
643
+ }
644
+
645
+ export function handleMsg(key: string) {
646
+ let commonMsg = getCommonMsg();
647
+ let g = splitGroup(key);
648
+ let ret: msgMsg = {
649
+ ...commonMsg,
650
+ ...{
651
+ t: "msg",
652
+ group: g.group,
653
+ msg: g.key.substr(0, Config.maxLength),
654
+ },
655
+ };
656
+ lazyReportCache(ret);
657
+ }
658
+
659
+ // export function handlePercent(key: string, val: number = 1) {
660
+ // let commonMsg = getCommonMsg()
661
+ // let g = splitGroup(key)
662
+ // let ret: sumMsg = {
663
+ // ...commonMsg,
664
+ // ...g,
665
+ // ...{
666
+ // t: 'avg',
667
+ // val,
668
+ // }
669
+ // }
670
+ // lazyReportCache(ret)
671
+ // }
672
+
673
+ export function handleHover(e) {
674
+ var cls = document.getElementsByClassName(CIRCLE_CLASS);
675
+ if (cls.length > 0) {
676
+ for (var i = 0; i < cls.length; i++) {
677
+ cls[i].className = cls[i].className.replace(/ circle-active/g, "");
678
+ }
679
+ }
680
+ e.target.className += ` ${CIRCLE_CLASS}`;
681
+ }
682
+
683
+ export function insertCss() {
684
+ var content = `.${CIRCLE_CLASS}{border: 3px solid rgba(112, 182, 3, 0.42) !important;cursor: pointer;}`;
685
+ var style = document.createElement("style");
686
+ style.id = CIRCLE_STYLE_ID;
687
+ try {
688
+ style.appendChild(document.createTextNode(content));
689
+ } catch (ex) {
690
+ style.styleSheet.cssText = content; //针对IE
691
+ }
692
+ var head = document.getElementsByTagName("head")[0];
693
+ head.appendChild(style);
694
+ }
695
+
696
+ export function removeCss() {
697
+ var style = document.getElementById(CIRCLE_STYLE_ID);
698
+ style.parentNode.removeChild(style);
699
+ }
700
+
701
+ export function listenCircleListener() {
702
+ insertCss();
703
+ GlobalVal.cssInserted = true;
704
+ GlobalVal.circle = true;
705
+ on("mouseover", handleHover);
706
+ }
707
+
708
+ export function removeCircleListener() {
709
+ removeCss();
710
+ GlobalVal.cssInserted = false;
711
+ GlobalVal.circle = false;
712
+ off("mouseover", handleHover);
713
+ }
714
+
715
+ export function listenMessageListener() {
716
+ on("message", handleMessage);
717
+ }
718
+
719
+ /**
720
+ *
721
+ * @param {*} event {t: '', v: ''}
722
+ * t: type
723
+ * v: value
724
+ */
725
+ function handleMessage(event) {
726
+ // 防止其他message的干扰
727
+ if (!event.data || !event.data.t) return;
728
+ if (event.data && event.data.token && event.data.token !== Config.token) {
729
+ window.parent.postMessage({ type: "disable-operation", data: false }, "*");
730
+ }
731
+ if (event.data.t === "setCircle") {
732
+ /** 判断操作埋点项目ID和集成SDK所填入的项目ID一致才能开启埋点操作 */
733
+ if (event.data.token === Config.token) {
734
+ if (Boolean(event.data.v)) {
735
+ listenCircleListener();
736
+ } else {
737
+ removeCircleListener();
738
+ }
739
+ }
740
+ } else if (event.data.t === "back") {
741
+ window.history.back();
742
+ } else if (event.data.t === "forward") {
743
+ window.history.forward();
744
+ } else if (event.data.t === "burial-point-operation") {
745
+ queryEventList(true, event.data.token);
746
+ queryMetaConfigList(true, event.data.token);
747
+ }
748
+ }
749
+
750
+ // 回显操作
751
+ function echo(type: boolean, eventList: any[]) {
752
+ // 页面处于可视化操作界面时才会显示回显
753
+ if (type) {
754
+ let head = document.querySelector("head");
755
+ let hasStyleNode = false;
756
+ let oldNode;
757
+ // 查询是否存在回显的STYLE标签
758
+ head.childNodes.forEach((item: Node) => {
759
+ if (item.nodeName === "STYLE") {
760
+ const styleNode = (item as HTMLStyleElement).getAttribute("id");
761
+ if (styleNode === "css-echo-style") {
762
+ hasStyleNode = true;
763
+ oldNode = item;
764
+ }
765
+ }
766
+ });
767
+ if (Config.isOpenCSSHash) {
768
+ let content = "";
769
+ let style = document.createElement("style");
770
+ style.id = "css-echo-style";
771
+ let locationPath = getLocationHref();
772
+ for (let index = 0; index < eventList.length; index++) {
773
+ const el = eventList[index];
774
+ if (el.screenName == locationPath && el.type === "click") {
775
+ const element_text = document.querySelector(el.elementSelector)
776
+ ? document.querySelector(el.elementSelector).innerText.length > 30
777
+ ? document
778
+ .querySelector(el.elementSelector)
779
+ .innerText.substring(0, 30)
780
+ : document.querySelector(el.elementSelector).innerText
781
+ : "";
782
+ if (element_text == el.elementContent) {
783
+ content += `${el.elementSelector}{border: 3px solid rgba(217, 0, 27, 0.42) !important;}`;
784
+ }
785
+ }
786
+ }
787
+ try {
788
+ style.appendChild(document.createTextNode(content));
789
+ } catch (ex) {
790
+ style.styleSheet.cssText = content; //针对IE
791
+ }
792
+ if (hasStyleNode && oldNode) {
793
+ head.replaceChild(style, oldNode);
794
+ } else {
795
+ head.appendChild(style);
796
+ }
797
+ } else {
798
+ // classname 方法
799
+ let content = "";
800
+ let style = document.createElement("style");
801
+ style.id = "css-echo-style";
802
+ let locationPath = getLocationHref();
803
+ for (let index = 0; index < eventList.length; index++) {
804
+ const el = eventList[index];
805
+ if (el.screenName == locationPath && el.type === "click") {
806
+ const els = document.querySelectorAll(el.elementSelector);
807
+ if (els.length > 0) {
808
+ content += `${el.elementSelector}{border: 3px solid rgba(217, 0, 27, 0.42) !important;}`;
809
+ }
810
+ }
811
+ }
812
+ try {
813
+ style.appendChild(document.createTextNode(content));
814
+ } catch (ex) {
815
+ style.styleSheet.cssText = content; //针对IE
816
+ }
817
+ if (hasStyleNode && oldNode) {
818
+ head.replaceChild(style, oldNode);
819
+ } else {
820
+ head.appendChild(style);
821
+ }
822
+ }
823
+ }
824
+ }
825
+
826
+ /*
827
+ * 查询所在项目已埋点页面
828
+ */
829
+ export function queryEventList(type = false, projectId?: string) {
830
+ request({
831
+ url: `${Config.eventListPath}${Config.token}`,
832
+ type: "get",
833
+ async: false,
834
+ success: (res) => {
835
+ try {
836
+ if (res) {
837
+ const data = JSON.parse(res);
838
+ if (data.code === 200) {
839
+ /**
840
+ * 判断当前集成项目ID(token)是否是当前操作埋点项目ID(token)
841
+ * 不同则不进行已埋点区域回显
842
+ */
843
+ if (projectId === Config.token) {
844
+ //延迟反查元素回显操作,否则会不显示已埋点元素
845
+ setTimeout(() => {
846
+ echo(type, data.data);
847
+ }, 500);
848
+ }
849
+ // 缓存埋点事件列表
850
+ sessionStorage.setItem("eventList", JSON.stringify(data.data));
851
+ }
852
+ }
853
+ } catch (error) {
854
+ console.error(error);
855
+ }
856
+ },
857
+ });
858
+ }
859
+
860
+ /*
861
+ * 查询所在项目元数据配置
862
+ */
863
+ export function queryMetaConfigList(type = false, projectId?: string) {
864
+ request({
865
+ url: `${Config.metaConfigPath}${Config.token}`,
866
+ type: "get",
867
+ async: false,
868
+ success: (res) => {
869
+ try {
870
+ if (res) {
871
+ const data = JSON.parse(res);
872
+ if (data.code === 200) {
873
+ // 缓存元数据配置列表
874
+ sessionStorage.setItem("metaList", JSON.stringify(data.data));
875
+ }
876
+ }
877
+ } catch (error) {
878
+ console.error(error);
879
+ }
880
+ },
881
+ });
882
+ }