@fle-sdk/event-tracking-web 1.2.0-beta.1 → 1.2.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.
package/lib/index.esm.js CHANGED
@@ -1,16 +1,1979 @@
1
- /*! *****************************************************************************
2
- Copyright (c) Microsoft Corporation.
3
-
4
- Permission to use, copy, modify, and/or distribute this software for any
5
- purpose with or without fee is hereby granted.
6
-
7
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
8
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
9
- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
10
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
11
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
12
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
13
- PERFORMANCE OF THIS SOFTWARE.
14
- ***************************************************************************** */
15
- var e=function(t,n){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])})(t,n)};var t=function(){return(t=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)},n=new(function(n){function r(){var e=n.call(this)||this;return e.userInfo=null,e.currentUrl="",e.pageKey="",e.eventDescMap={PageView:"Web 浏览页面",WebClick:"Web 元素点击",PageRetained:"Web 页面浏览时长",CustomTrack:"Web 自定义代码上报"},e.init=function(t){e.preset(t);var n=window.location.pathname;e.currentUrl=window.location.href,e.pageKey=n.replace(/\//g,"_").substr(1),e.systemsInfo=e.getSystemsInfo(t.platform),e.setCookie("retainedStartTime",e.getTimeStamp())},e.preset=function(t){t instanceof Object&&e.each(t,(function(t,n){e.initConfig.hasOwnProperty(n)&&(e.initConfig[n]=t)})),/^(((ht|f)tps?):\/\/)?[\w-]+(\.[\w-]+)+([\w.,@?^=%&:/~+#-\(\)]*[\w@?^=%&/~+#-\(\)])?$/.test(e.initConfig.serverUrl)||(e.printLog("当前 server_url 为空或不正确,只在控制台打印日志,network 中不会发数据,请配置正确的 server_url!"),e.initConfig.showLog=!0),e.initConfig.autoTrack?e.listener():e.unlistener()},e.login=function(t){e.isObject(t)&&(e.userInfo=t)},e.track=function(t){var n=t.desc,r=t.partkey,i=t.business,o=t.header,a=e.getParams({desc:n,event:"CustomTrack",itemKey:e.getItemKey(r),privateParamMap:{business:i}});return e.sendData(a,o)},e.listener=function(){e.initConfig.isTrackSinglePage&&(e.rewriteHistory(),e.addSinglePageEvent(e.onPageViewCallback)),e.each(["load","beforeunload"],(function(t){e.addEventListener(window,t,e.onPageViewCallback)})),e.addEventListener(window,"click",e.onClickCallback)},e.unlistener=function(){if(e.initConfig.isTrackSinglePage){var t=window.history.pushState?"popstate":"hashchange";e.each(["pushState","replaceState",t],(function(t){e.removeEventListener(window,t,e.onPageViewCallback)}))}e.each(["load","beforeunload"],(function(t){e.removeEventListener(window,t,e.onPageViewCallback)})),e.removeEventListener(window,"click",e.onClickCallback)},e.onClickCallback=function(t){var n,r;if(null===(r=null===(n=null==t?void 0:t.target)||void 0===n?void 0:n.dataset)||void 0===r?void 0:r.partKey){var i=[t.pageX,t.pageY],o=t.target.id,a=t.target.className,s={id:o,nodeName:t.target.nodeName,className:a,position:i},c=e.getParams({event:"WebClick",desc:e.eventDescMap.WebClick,itemKey:e.getItemKey(t.target.dataset.partKey),privateParamMap:{targetEle:s,pointerType:t.pointerType,currentUrl:e.currentUrl,elementSelector:e.getDomSelector(t.target)}});return e.sendData(c)}},e.onPageViewCallback=function(t){var n,r,i=window.location.origin,o=e.getParams({event:"PageView",desc:e.eventDescMap.PageView,privateParamMap:{currentUrl:e.currentUrl,targetUrl:(null===(n=t.arguments)||void 0===n?void 0:n[2])?i+(null===(r=t.arguments)||void 0===r?void 0:r[2]):null}});e.currentUrl=window.location.href,e.pageKey=window.location.pathname.replace(/\//g,"_").substring(1),e.sendRetained(t.type),e.sendData(o)},e.getParams=function(n){var r=n.event,i=n.desc,o=n.privateParamMap,a=void 0===o?{}:o,s=n.itemKey,c=e.initConfig.business,u=window.innerWidth,l=window.innerHeight,d=window.screen.width,p=window.screen.height;return{desc:i,event:r,itemKey:s||e.getItemKey(),requestTime:e.getTimeStamp(),deviceId:e.getDistinctId(),privateParamMap:t(t({},a),{pageWidth:u,pageHeight:l,screenWidth:d,screenHeight:p,sdkVersion:e.sdkVersion,systemsInfo:e.systemsInfo,urlParams:e.getQueryValue(),userInfo:e.userInfo,currentUrl:a.currentUrl||e.currentUrl,business:t(t({},c||{}),a.business||{})})}},e.sendData=function(t,n){var r=e.initConfig,i=r.serverUrl,o=r.sendTimeout,a=r.contentType,s=r.showLog,c=r.header;return s&&e.printLog(t),!0!==e.isSupportBeaconSend()||n||c?new Promise((function(r,s){e.ajax({header:n||c,url:i,type:"POST",data:JSON.stringify(t),contentType:a,credentials:!1,timeout:o,cors:!0,success:function(e){return r(e)},error:function(e){return s(e)}})})):e.sendBeacon({contentType:a,url:i,data:t})},e.sendRetained=function(n){var r=e.getParams({event:"PageRetained",desc:e.eventDescMap.PageRetained});if(["beforeunload","pushState","replaceState","hashchange","popstate"].indexOf(n)>=0){var i=e.getCookie("retainedStartTime"),o=i?+i:e.getTimeStamp(),a=t(t({},r),{privateParamMap:t(t({},r.privateParamMap),{retainedDuration:Math.max(r.requestTime-o,0)})});e.sendData(a),e.setCookie("retainedStartTime",e.getTimeStamp())}},e.getItemKey=function(t){return[e.initConfig.appKey,e.pageKey,t?t.toString():void 0].filter((function(e){return!!e})).reduce((function(e,t){return e+(e.length?".":"")+t}),"")},e.sdkVersion="1.1.0",e.initConfig={appKey:"",platform:void 0,showLog:!1,serverUrl:"",autoTrack:!1,sendTimeout:3e3,isTrackSinglePage:!1,contentType:"application/json",business:{},header:void 0},e.systemsInfo={},e}return function(t,n){if("function"!=typeof n&&null!==n)throw new TypeError("Class extends value "+String(n)+" is not a constructor or null");function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}(r,n),r.prototype.addSinglePageEvent=function(e){var t=this,n=window.history.pushState?"popstate":"hashchange";this.each(["pushState","replaceState",n],(function(n){t.addEventListener(window,n,e)}))},r}(function(){function e(){var e=this;this.getSystemsInfo=function(e){var t=navigator.userAgent,n="other",r=[],i={language:navigator.language},o=t.match(/MicroMessenger\/([\d\.]+)/i),a=o&&o[1]?o[1]:null,s=t.match(/(ipod).*\s([\d_]+)/i),c=t.match(/(ipad).*\s([\d_]+)/i),u=t.match(/(iphone)\sos\s([\d_]+)/i),l=t.match(/(android)\s([\d\.]+)/i),d=t.match(/(Windows NT)\s([\d\.]+)/i),p=t.match(/(Mac OS X)\s([\d_]+)/i);r=[],l?(r.push("Android "+l[2]),n="h5"):u?(r.push("iPhone, iOS "+u[2].replace(/_/g,".")),n="h5"):c?(r.push("iPad, iOS "+c[2].replace(/_/g,".")),n="ipad"):s?(r.push("iPod, iOS "+s[2].replace(/_/g,".")),n="h5"):d?(r.push("Windows "+d[2].replace(/_/g,".")),n="pc"):p&&(r.push("Mac, MacOS "+p[2].replace(/_/g,".")),n="pc"),a&&r.push("WeChat "+a),i.client=r.length?r.join(", "):"Unknown",i.platform=e||n;var g=t.toLowerCase().match(/ nettype\/([^ ]+)/g);return g&&g[0]&&(r=[(g=g[0].split("/"))[1]],i.network=r.length?r.join(", "):"Unknown"),i.ua=t,i},this.addEventListener=function(e,t,n){e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent&&e.attachEvent("on"+t,(function(t){return n.call(e,t)}),!1)},this.removeEventListener=function(e,t,n){e.removeEventListener?e.removeEventListener(t,n):e.detachEvent&&e.detachEvent("on"+t,(function(t){return n.call(e,t)}),!0)},this.rewriteHistory=function(){var e=window.history,t=function(e){var t=window.history,n=t[e],r=new Event(e);return function(){var e=n.apply(t,arguments);return r.arguments=arguments,window.dispatchEvent(r),e}};window.history.pushState&&(e.pushState=t("pushState"),e.replaceState=t("replaceState"))},this.isArray=Array.isArray||function(e){return"[object Array]"===toString.call(e)},this.formatJsonString=function(e){try{return JSON.stringify(e,null," ")}catch(t){return JSON.stringify(e)}},this.nativeForEach=Array.prototype.forEach,this.slice=Array.prototype.slice,this.hasOwnProperty=Object.prototype.hasOwnProperty,this.breaker={},this.each=function(t,n,r){if(null==t)return!1;if(e.nativeForEach&&t.forEach===e.nativeForEach)t.forEach(n,r);else if(e.isArray(t)&&t.length===+t.length){for(var i=0,o=t.length;i<o;i++)if(i in t&&n.call(r,t[i],i,t)===e.breaker)return!1}else for(var a in t)if(e.hasOwnProperty.call(t,a)&&n.call(r,t[a],a,t)===e.breaker)return!1},this.getDomIndex=function(e){if(!e.parentNode)return-1;for(var t=0,n=e.tagName,r=e.parentNode.children,i=0;i<r.length;i++)if(r[i].tagName===n){if(e===r[i])return t;t++}return-1},this.selector=function(t){var n=t.parentNode&&9==t.parentNode.nodeType?-1:e.getDomIndex(t);return t.getAttribute&&t.getAttribute("id")&&/^[A-Za-z][-A-Za-z0-9_:.]*$/.test(t.getAttribute("id"))?"#"+t.getAttribute("id"):t.tagName.toLowerCase()+(~n?":nth-of-type("+(n+1)+")":"")},this.getDomSelector=function(t,n){if(!t||!t.parentNode||!t.parentNode.children)return!1;n=n&&n.join?n:[];var r=t.nodeName.toLowerCase();return t&&"body"!==r&&1==t.nodeType?(n.unshift(e.selector(t)),t.getAttribute&&t.getAttribute("id")&&/^[A-Za-z][-A-Za-z0-9_:.]*$/.test(t.getAttribute("id"))?n.join(" > "):e.getDomSelector(t.parentNode,n)):(n.unshift("body"),n.join(" > "))},this.getCookie=function(e){for(var t=e+"=",n=document.cookie.split(";"),r=0;r<n.length;r++){for(var i=n[r];" "==i.charAt(0);)i=i.substring(1,i.length);if(0==i.indexOf(t))return this._decodeURIComponent(i.substring(t.length,i.length))}return null},this.setCookie=function(e,t,n){var r,i="";n=null==n?73e3:n;var o=this.getMainHost();if(r=o?"; domain="+o:"",0!==n){var a=new Date;"s"===String(n).slice(-1)?a.setTime(a.getTime()+1e3*Number(String(n).slice(0,-1))):a.setTime(a.getTime()+24*n*60*60*1e3),i="; expires="+a.toUTCString()}function s(e){return e||!1}var c="",u="",l="";e&&(c=s(e)),t&&(u=s(t)),r&&(l=s(r)),c&&u&&(document.cookie=c+"="+encodeURIComponent(u)+i+"; path=/"+l)},this.removeCookie=function(t){e.setCookie(t,"",-1)},this.getTimeStamp=function(){return(new Date).getTime()},this.uuid=function(){return"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".replace(/[xy]/g,(function(e){var t=16*Math.random()|0;return("x"==e?t:3&t|8).toString(16)}))},this.getDistinctId=function(){var t=e.getCookie("distinctId");return t||(t=e.uuid(),e.setCookie("distinctId",t),t)},this.getQueryValue=function(){for(var e=decodeURI(window.location.href).match(new RegExp("[?&][^?&]+=[^?&]+","g"))||[],t={},n=0;n<e.length;n++){var r=e[n].replace(/\?|\&/,"").split("=");t[r[0]]=r[1]}return t},this.ajax=function(t){function n(e){if(!e)return"";try{return JSON.parse(e)}catch(e){return{}}}t.timeout=t.timeout||3e4,t.credentials=void 0===t.credentials||t.credentials;var r=e.xhr(t.cors);if(!r)return!1;t.type||(t.type=t.data?"POST":"GET");var i,o=t.success,a=t.error;t.success=function(e){o(e),i&&(clearTimeout(i),i=null)},t.error=function(e){a(e),i&&(clearTimeout(i),i=null)},i=setTimeout((function(){!function(){try{e.isObject(r)&&r.abort&&r.abort()}catch(t){e.printLog(t)}i&&(clearTimeout(i),i=null,t.error&&t.error(),r.onreadystatechange=null,r.onload=null,r.onerror=null)}()}),t.timeout),r.onreadystatechange=function(){try{4==r.readyState&&(r.status>=200&&r.status<300||304==r.status?t.success(n(r.responseText)):t.error(n(r.responseText),r.status),r.onreadystatechange=null,r.onload=null)}catch(e){r.onreadystatechange=null,r.onload=null}},r.open(t.type,t.url,!0);try{t.credentials&&(r.withCredentials=!0),e.isObject(t.header)&&e.each(t.header,(function(e,t){r.setRequestHeader&&r.setRequestHeader(t,e)})),t.data&&(t.cors||r.setRequestHeader&&r.setRequestHeader("X-Requested-With","XMLHttpRequest"),"application/json"===t.contentType?r.setRequestHeader&&r.setRequestHeader("Content-type","application/json; charset=UTF-8"):r.setRequestHeader&&r.setRequestHeader("Content-type","application/x-www-form-urlencoded"))}catch(t){e.printLog(t)}r.send(t.data||null)},this.xhr=function(e){return e?void 0!==window.XMLHttpRequest&&"withCredentials"in new XMLHttpRequest?new XMLHttpRequest:null:void 0!==window.XMLHttpRequest?new XMLHttpRequest:null},this.getUA=function(){var e,t={},n=navigator.userAgent.toLowerCase();return(e=n.match(/opera.([\d.]+)/))?t.opera=Number(e[1].split(".")[0]):(e=n.match(/msie ([\d.]+)/))?t.ie=Number(e[1].split(".")[0]):(e=n.match(/edge.([\d.]+)/))?t.edge=Number(e[1].split(".")[0]):(e=n.match(/firefox\/([\d.]+)/))?t.firefox=Number(e[1].split(".")[0]):(e=n.match(/chrome\/([\d.]+)/))?t.chrome=Number(e[1].split(".")[0]):(e=n.match(/version\/([\d.]+).*safari/))?t.safari=Number(e[1].match(/^\d*.\d*/)):(e=n.match(/trident\/([\d.]+)/))&&(t.ie=11),t},this.isSupportBeaconSend=function(){var t=!1;if("object"!=typeof navigator||"function"!=typeof navigator.sendBeacon)return t;var n=e.getUA(),r=navigator.userAgent.toLowerCase();if(/Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent)){var i=(r.match(/os [\d._]*/gi)+"").replace(/[^0-9|_.]/gi,"").replace(/_/gi,".").split(".");void 0===n.safari&&(n.safari=i[0]),i[0]&&+i[0]<13?(n.chrome>41||n.firefox>30||n.opera>25||n.safari>12)&&(t=!0):(n.chrome>41||n.firefox>30||n.opera>25||n.safari>11.3)&&(t=!0)}else(n.chrome>38||n.edge>13||n.firefox>30||n.opera>25||n.safari>11)&&(t=!0);return t},this.sendBeacon=function(t){if(!0===e.isSupportBeaconSend()){var n={type:t.contentType},r=new Blob([JSON.stringify(t.data)],n);return navigator.sendBeacon(t.url,r)?Promise.resolve({success:!0}):Promise.reject({success:!1})}return Promise.reject({message:"不支持sendBeacon,发送失败!",success:!1})}}return e.prototype.printLog=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];if(this.isObject(e[0])&&(e[0]=this.formatJsonString(e[0])),"object"==typeof console&&console.log)try{return console.log.apply(console,e)}catch(t){console.log(e[0])}},e.prototype.isObject=function(e){return null!=e&&"[object Object]"==toString.call(e)},e.prototype.isUndefined=function(e){return void 0===e},e.prototype.isString=function(e){return"[object String]"==toString.call(e)},e.prototype.isDate=function(e){return"[object Date]"==toString.call(e)},e.prototype.isBoolean=function(e){return"[object Boolean]"==toString.call(e)},e.prototype.isNumber=function(e){return"[object Number]"==toString.call(e)&&/[\d\.]+/.test(String(e))},e.prototype.isElement=function(e){return!(!e||1!==e.nodeType)},e.prototype.isFunction=function(e){if(!e)return!1;var t=toString.call(e);return"[object Function]"==t||"[object AsyncFunction]"==t},e.prototype.isJSONString=function(e){try{JSON.parse(e)}catch(e){return!1}return!0},e.prototype._decodeURIComponent=function(e){var t=e;try{t=decodeURIComponent(e)}catch(n){t=e}return t},e.prototype.getMainHost=function(){var e="mh_"+Math.random(),t=new RegExp("(^|;)\\s*"+e+"=12345"),n=new Date(0),r=document.domain.split("."),i=[];for(i.unshift(r.pop());r.length;){i.unshift(r.pop());var o=i.join("."),a=e+"=12345;domain=."+o;if(document.cookie=a,t.test(document.cookie))return document.cookie=a+";expires="+n,o}},e}()));export default n;
16
- //# sourceMappingURL=index.esm.js.map
1
+ /*! *****************************************************************************
2
+ Copyright (c) Microsoft Corporation.
3
+
4
+ Permission to use, copy, modify, and/or distribute this software for any
5
+ purpose with or without fee is hereby granted.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
8
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
9
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
10
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
11
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
12
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
13
+ PERFORMANCE OF THIS SOFTWARE.
14
+ ***************************************************************************** */
15
+ /* global Reflect, Promise */
16
+
17
+ var extendStatics = function(d, b) {
18
+ extendStatics = Object.setPrototypeOf ||
19
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
20
+ function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
21
+ return extendStatics(d, b);
22
+ };
23
+
24
+ function __extends(d, b) {
25
+ if (typeof b !== "function" && b !== null)
26
+ throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
27
+ extendStatics(d, b);
28
+ function __() { this.constructor = d; }
29
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
30
+ }
31
+
32
+ var __assign = function() {
33
+ __assign = Object.assign || function __assign(t) {
34
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
35
+ s = arguments[i];
36
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
37
+ }
38
+ return t;
39
+ };
40
+ return __assign.apply(this, arguments);
41
+ };
42
+
43
+ function __spreadArray(to, from) {
44
+ for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)
45
+ to[j] = from[i];
46
+ return to;
47
+ }
48
+
49
+ function _typeof(obj) {
50
+ "@babel/helpers - typeof";
51
+
52
+ if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
53
+ _typeof = function (obj) {
54
+ return typeof obj;
55
+ };
56
+ } else {
57
+ _typeof = function (obj) {
58
+ return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
59
+ };
60
+ }
61
+
62
+ return _typeof(obj);
63
+ }
64
+
65
+ var WebTrackingTools =
66
+ /** @class */
67
+ function () {
68
+ function WebTrackingTools() {
69
+ var _this = this;
70
+ /**
71
+ * 系统信息
72
+ */
73
+
74
+
75
+ this.getSystemsInfo = function (platform) {
76
+ // print system info
77
+ var ua = navigator.userAgent;
78
+ var language = navigator.language;
79
+ var _platform = "other";
80
+ var logMsg = [];
81
+ var systemsInfo = {
82
+ language: language
83
+ }; // wechat client version
84
+
85
+ var wxVersionMatch = ua.match(/MicroMessenger\/([\d\.]+)/i);
86
+ var wxVersion = wxVersionMatch && wxVersionMatch[1] ? wxVersionMatch[1] : null; // device & system
87
+
88
+ var ipod = ua.match(/(ipod).*\s([\d_]+)/i),
89
+ ipad = ua.match(/(ipad).*\s([\d_]+)/i),
90
+ iphone = ua.match(/(iphone)\sos\s([\d_]+)/i),
91
+ android = ua.match(/(android)\s([\d\.]+)/i),
92
+ windows = ua.match(/(Windows NT)\s([\d\.]+)/i),
93
+ mac = ua.match(/(Mac OS X)\s([\d_]+)/i);
94
+ logMsg = [];
95
+
96
+ if (android) {
97
+ logMsg.push("Android " + android[2]);
98
+ _platform = "h5";
99
+ } else if (iphone) {
100
+ logMsg.push("iPhone, iOS " + iphone[2].replace(/_/g, "."));
101
+ _platform = "h5";
102
+ } else if (ipad) {
103
+ logMsg.push("iPad, iOS " + ipad[2].replace(/_/g, "."));
104
+ _platform = "ipad";
105
+ } else if (ipod) {
106
+ logMsg.push("iPod, iOS " + ipod[2].replace(/_/g, "."));
107
+ _platform = "h5";
108
+ } else if (windows) {
109
+ logMsg.push("Windows " + windows[2].replace(/_/g, "."));
110
+ _platform = "pc";
111
+ } else if (mac) {
112
+ logMsg.push("Mac, MacOS " + mac[2].replace(/_/g, "."));
113
+ _platform = "pc";
114
+ }
115
+
116
+ if (wxVersion) {
117
+ logMsg.push("WeChat " + wxVersion);
118
+ }
119
+
120
+ systemsInfo["client"] = logMsg.length ? logMsg.join(", ") : "Unknown";
121
+ systemsInfo["platform"] = platform || _platform; // network type
122
+
123
+ var network = ua.toLowerCase().match(/ nettype\/([^ ]+)/g);
124
+
125
+ if (network && network[0]) {
126
+ // @ts-ignore
127
+ network = network[0].split("/");
128
+ logMsg = [network[1]];
129
+ systemsInfo["network"] = logMsg.length ? logMsg.join(", ") : "Unknown";
130
+ } // User Agent
131
+
132
+
133
+ systemsInfo["ua"] = ua;
134
+ return systemsInfo;
135
+ };
136
+ /**
137
+ * 监听事件
138
+ * @param {Window | Element} target
139
+ * @param {String} type
140
+ * @param {Function} handler
141
+ */
142
+
143
+
144
+ this.addEventListener = function (target, type, handler) {
145
+ if (target.addEventListener) {
146
+ target.addEventListener(type, handler, false);
147
+ } else {
148
+ target.attachEvent && target.attachEvent("on" + type, function (event) {
149
+ return handler.call(target, event);
150
+ }, false);
151
+ }
152
+ };
153
+ /**
154
+ * 移除监听事件
155
+ * @param {Element} target
156
+ * @param {String} type
157
+ * @param {Funtion} handler
158
+ */
159
+
160
+
161
+ this.removeEventListener = function (target, type, handler) {
162
+ if (target.removeEventListener) {
163
+ target.removeEventListener(type, handler);
164
+ } else {
165
+ target.detachEvent && target.detachEvent("on" + type, function (event) {
166
+ return handler.call(target, event);
167
+ }, true);
168
+ }
169
+ };
170
+ /**
171
+ * 重写history[pushState][replaceState]方法
172
+ */
173
+
174
+
175
+ this.rewriteHistory = function () {
176
+ var history = window.history;
177
+
178
+ var historyWrap = function historyWrap(type) {
179
+ var history = window.history;
180
+ var orig = history[type];
181
+ var e = new Event(type);
182
+ return function () {
183
+ var rv = orig.apply(history, arguments);
184
+ e.arguments = arguments;
185
+ window.dispatchEvent(e);
186
+ return rv;
187
+ };
188
+ }; // 重写
189
+
190
+
191
+ if (!!window.history.pushState) {
192
+ history.pushState = historyWrap("pushState");
193
+ history.replaceState = historyWrap("replaceState");
194
+ }
195
+ };
196
+
197
+ this.isArray = Array.isArray || function (obj) {
198
+ return toString.call(obj) === "[object Array]";
199
+ };
200
+ /**
201
+ * 将json序列化成json字符串
202
+ * @param obj
203
+ * @returns {[JsonString]} [json字符串]
204
+ */
205
+
206
+
207
+ this.formatJsonString = function (obj) {
208
+ try {
209
+ return JSON.stringify(obj, null, " ");
210
+ } catch (e) {
211
+ return JSON.stringify(obj);
212
+ }
213
+ };
214
+
215
+ this.nativeForEach = Array.prototype.forEach;
216
+ this.slice = Array.prototype.slice;
217
+ this.hasOwnProperty = Object.prototype.hasOwnProperty;
218
+ this.breaker = {};
219
+ /**
220
+ * @description 循环遍历
221
+ */
222
+
223
+ this.each = function (obj, iterator, context) {
224
+ if (obj == null) {
225
+ return false;
226
+ }
227
+
228
+ if (_this.nativeForEach && obj.forEach === _this.nativeForEach) {
229
+ obj.forEach(iterator, context);
230
+ } else if (_this.isArray(obj) && obj.length === +obj.length) {
231
+ for (var i = 0, l = obj.length; i < l; i++) {
232
+ if (i in obj && iterator.call(context, obj[i], i, obj) === _this.breaker) {
233
+ return false;
234
+ }
235
+ }
236
+ } else {
237
+ for (var key in obj) {
238
+ if (_this.hasOwnProperty.call(obj, key)) {
239
+ if (iterator.call(context, obj[key], key, obj) === _this.breaker) {
240
+ return false;
241
+ }
242
+ }
243
+ }
244
+ }
245
+
246
+ return true;
247
+ };
248
+
249
+ this.getDomIndex = function (el) {
250
+ if (!el.parentNode) return -1;
251
+ var i = 0;
252
+ var nodeName = el.tagName;
253
+ var list = el.parentNode.children;
254
+
255
+ for (var n = 0; n < list.length; n++) {
256
+ if (list[n].tagName === nodeName) {
257
+ if (el === list[n]) {
258
+ return i;
259
+ } else {
260
+ i++;
261
+ }
262
+ }
263
+ }
264
+
265
+ return -1;
266
+ };
267
+
268
+ this.selector = function (el) {
269
+ var i = el.parentNode && 9 == el.parentNode.nodeType ? -1 : _this.getDomIndex(el);
270
+
271
+ if (el.getAttribute && el.getAttribute("id") && /^[A-Za-z][-A-Za-z0-9_:.]*$/.test(el.getAttribute("id"))) {
272
+ return "#" + el.getAttribute("id");
273
+ } else {
274
+ return el.tagName.toLowerCase() + (~i ? ":nth-of-type(" + (i + 1) + ")" : "");
275
+ }
276
+ };
277
+
278
+ this.getDomSelector = function (el, arr) {
279
+ if (!el || !el.parentNode || !el.parentNode.children) {
280
+ return false;
281
+ }
282
+
283
+ arr = arr && arr.join ? arr : [];
284
+ var name = el.nodeName.toLowerCase();
285
+
286
+ if (!el || name === "body" || 1 != el.nodeType) {
287
+ arr.unshift("body");
288
+ return arr.join(" > ");
289
+ }
290
+
291
+ arr.unshift(_this.selector(el));
292
+ if (el.getAttribute && el.getAttribute("id") && /^[A-Za-z][-A-Za-z0-9_:.]*$/.test(el.getAttribute("id"))) return arr.join(" > ");
293
+ return _this.getDomSelector(el.parentNode, arr);
294
+ };
295
+ /**
296
+ * @description 增强cookie操作
297
+ */
298
+
299
+
300
+ this.getCookie = function (name) {
301
+ var nameEQ = name + "=";
302
+ var ca = document.cookie.split(";");
303
+
304
+ for (var i = 0; i < ca.length; i++) {
305
+ var c = ca[i];
306
+
307
+ while (c.charAt(0) == " ") {
308
+ c = c.substring(1, c.length);
309
+ }
310
+
311
+ if (c.indexOf(nameEQ) == 0) {
312
+ return this._decodeURIComponent(c.substring(nameEQ.length, c.length));
313
+ }
314
+ }
315
+
316
+ return null;
317
+ };
318
+
319
+ this.setCookie = function (name, value, days) {
320
+ var cdomain = "",
321
+ expires = "",
322
+ secure = "",
323
+ samesite = "";
324
+ days = days == null ? 73000 : days;
325
+ var domain = this.getMainHost();
326
+ cdomain = domain ? "; domain=" + domain : "";
327
+
328
+ if (days !== 0) {
329
+ var date = new Date();
330
+
331
+ if (String(days).slice(-1) === "s") {
332
+ date.setTime(date.getTime() + Number(String(days).slice(0, -1)) * 1000);
333
+ } else {
334
+ date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000);
335
+ }
336
+
337
+ expires = "; expires=" + date.toUTCString();
338
+ }
339
+
340
+ function getValid(data) {
341
+ if (data) {
342
+ return data;
343
+ } else {
344
+ return false;
345
+ }
346
+ }
347
+
348
+ var valid_name = "";
349
+ var valid_value = "";
350
+ var valid_domain = "";
351
+
352
+ if (name) {
353
+ valid_name = getValid(name);
354
+ }
355
+
356
+ if (value) {
357
+ valid_value = getValid(value);
358
+ }
359
+
360
+ if (cdomain) {
361
+ valid_domain = getValid(cdomain);
362
+ }
363
+
364
+ if (valid_name && valid_value) {
365
+ document.cookie = valid_name + "=" + encodeURIComponent(valid_value) + expires + "; path=/" + valid_domain + samesite + secure;
366
+ }
367
+ };
368
+ /**
369
+ * 获取localStorage值
370
+ * @param key 存储键名
371
+ * @returns 存储值
372
+ */
373
+
374
+
375
+ this.getLocalStorage = function (key) {
376
+ try {
377
+ return localStorage.getItem(key);
378
+ } catch (e) {
379
+ return null;
380
+ }
381
+ };
382
+ /**
383
+ * 设置localStorage值
384
+ * @param key 存储键名
385
+ * @param value 存储值
386
+ */
387
+
388
+
389
+ this.setLocalStorage = function (key, value) {
390
+ try {
391
+ localStorage.setItem(key, value);
392
+ } catch (e) {// 静默失败
393
+ }
394
+ };
395
+
396
+ this.removeCookie = function (name) {
397
+ _this.setCookie(name, "", -1);
398
+ };
399
+ /**
400
+ * 获取当前时间戳
401
+ * @return {number} [当前时间戳]
402
+ */
403
+
404
+
405
+ this.getTimeStamp = function () {
406
+ return new Date().getTime();
407
+ };
408
+ /**
409
+ * 获取 UUID
410
+ * @return {string} [UUID唯一值]
411
+ */
412
+
413
+
414
+ this.uuid = function () {
415
+ return "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".replace(/[xy]/g, function (c) {
416
+ var r = Math.random() * 16 | 0,
417
+ v = c == "x" ? r : r & 0x3 | 0x8;
418
+ return v.toString(16);
419
+ });
420
+ };
421
+ /**
422
+ * 获取设备Id
423
+ * @return {number} [设备Id]
424
+ */
425
+
426
+
427
+ this.getDistinctId = function () {
428
+ var distinctId = _this.getCookie("distinctId");
429
+
430
+ if (distinctId) return distinctId;
431
+ distinctId = _this.uuid();
432
+
433
+ _this.setCookie("distinctId", distinctId);
434
+
435
+ return distinctId;
436
+ };
437
+ /**
438
+ * 敏感字段过滤
439
+ * @param obj 需要过滤的对象
440
+ * @param sensitiveKeys 敏感字段列表
441
+ * @returns 过滤后的对象
442
+ */
443
+
444
+
445
+ this.filterSensitiveData = function (obj, sensitiveKeys) {
446
+ if (sensitiveKeys === void 0) {
447
+ sensitiveKeys = ['password', 'token', 'secret', 'key'];
448
+ }
449
+
450
+ if (!_this.isObject(obj)) return obj;
451
+ var filteredObj = {};
452
+
453
+ _this.each(obj, function (value, key) {
454
+ // 检查是否是敏感字段
455
+ var isSensitive = sensitiveKeys.some(function (sensitiveKey) {
456
+ return typeof key === 'string' && key.toLowerCase().includes(sensitiveKey.toLowerCase());
457
+ });
458
+
459
+ if (isSensitive) {
460
+ filteredObj[key] = '***';
461
+ } else if (_this.isObject(value)) {
462
+ // 递归过滤嵌套对象
463
+ filteredObj[key] = _this.filterSensitiveData(value, sensitiveKeys);
464
+ } else {
465
+ filteredObj[key] = value;
466
+ }
467
+ });
468
+
469
+ return filteredObj;
470
+ };
471
+ /**
472
+ * XSS过滤
473
+ * @param str 需要过滤的字符串
474
+ * @returns 过滤后的字符串
475
+ */
476
+
477
+
478
+ this.xssFilter = function (str) {
479
+ if (!str) return '';
480
+ if (typeof str !== 'string') return str.toString();
481
+ return str.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#x27;').replace(/\//g, '&#x2F;');
482
+ };
483
+ /**
484
+ * 获取url中的参数
485
+ * @param {[string]} name [参数名]
486
+ */
487
+
488
+
489
+ this.getQueryValue = function () {
490
+ var _href = decodeURI(window.location.href);
491
+
492
+ var queryArr = _href.match(new RegExp("[?&][^?&]+=[^?&]+", "g")) || [];
493
+ var paramsObj = {};
494
+
495
+ for (var i = 0; i < queryArr.length; i++) {
496
+ var _item = queryArr[i].replace(/\?|\&/, "");
497
+
498
+ var pair = _item.split("=");
499
+
500
+ paramsObj[pair[0]] = pair[1];
501
+ }
502
+
503
+ return Object.keys(paramsObj).length > 0 ? paramsObj : null;
504
+ };
505
+ /**
506
+ * Ajax请求方法
507
+ * @param para Ajax请求参数
508
+ * @returns 是否成功发起请求
509
+ */
510
+
511
+
512
+ this.ajax = function (para) {
513
+ para.timeout = para.timeout || 30000;
514
+ para.credentials = typeof para.credentials === "undefined" ? true : para.credentials;
515
+
516
+ function getJSON(data) {
517
+ if (!data) {
518
+ return {};
519
+ }
520
+
521
+ if (typeof data === 'string') {
522
+ try {
523
+ return JSON.parse(data);
524
+ } catch (e) {
525
+ return {};
526
+ }
527
+ }
528
+
529
+ if (_typeof(data) === 'object') {
530
+ return data;
531
+ }
532
+
533
+ return {};
534
+ }
535
+
536
+ var g = _this.xhr(para.cors);
537
+
538
+ if (!g) {
539
+ return false;
540
+ }
541
+
542
+ if (!para.type) {
543
+ para.type = para.data ? "POST" : "GET";
544
+ }
545
+
546
+ var oldsuccess = para.success;
547
+ var olderror = para.error;
548
+ var errorTimer;
549
+
550
+ var abort = function abort() {
551
+ try {
552
+ if (_this.isObject(g) && g.abort) {
553
+ g.abort();
554
+ }
555
+ } catch (error) {
556
+ _this.printLog(error);
557
+ }
558
+
559
+ if (errorTimer) {
560
+ clearTimeout(errorTimer);
561
+ errorTimer = null;
562
+ para.error && para.error();
563
+ g.onreadystatechange = null;
564
+ g.onload = null;
565
+ g.onerror = null;
566
+ }
567
+ };
568
+
569
+ para.success = function (data) {
570
+ oldsuccess && oldsuccess(data);
571
+
572
+ if (errorTimer) {
573
+ clearTimeout(errorTimer);
574
+ errorTimer = null;
575
+ }
576
+ };
577
+
578
+ para.error = function (err, status) {
579
+ olderror && olderror(err, status);
580
+
581
+ if (errorTimer) {
582
+ clearTimeout(errorTimer);
583
+ errorTimer = null;
584
+ }
585
+ };
586
+
587
+ errorTimer = window.setTimeout(function () {
588
+ abort();
589
+ }, para.timeout);
590
+
591
+ g.onreadystatechange = function () {
592
+ try {
593
+ if (g.readyState == 4) {
594
+ if (g.status >= 200 && g.status < 300 || g.status == 304) {
595
+ para.success && para.success(getJSON(g.responseText));
596
+ } else {
597
+ para.error && para.error(getJSON(g.responseText), g.status);
598
+ }
599
+
600
+ g.onreadystatechange = null;
601
+ g.onload = null;
602
+ }
603
+ } catch (e) {
604
+ g.onreadystatechange = null;
605
+ g.onload = null;
606
+ }
607
+ };
608
+
609
+ g.open(para.type || "GET", para.url, true);
610
+
611
+ try {
612
+ if (para.credentials) {
613
+ g.withCredentials = true;
614
+ }
615
+
616
+ if (_this.isObject(para.header)) {
617
+ _this.each(para.header, function (v, i) {
618
+ g.setRequestHeader && g.setRequestHeader(i, v);
619
+ });
620
+ }
621
+
622
+ if (para.data) {
623
+ if (!para.cors) {
624
+ g.setRequestHeader && g.setRequestHeader("X-Requested-With", "XMLHttpRequest");
625
+ }
626
+
627
+ if (para.contentType === "application/json") {
628
+ g.setRequestHeader && g.setRequestHeader("Content-type", "application/json; charset=UTF-8");
629
+ } else {
630
+ g.setRequestHeader && g.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
631
+ }
632
+ }
633
+ } catch (e) {
634
+ _this.printLog(e);
635
+ }
636
+
637
+ g.send(para.data || null);
638
+ };
639
+
640
+ this.xhr = function (cors) {
641
+ if (cors) {
642
+ if (typeof window.XMLHttpRequest !== "undefined" && "withCredentials" in new XMLHttpRequest()) {
643
+ return new XMLHttpRequest();
644
+ } else {
645
+ return null;
646
+ }
647
+ } else if (typeof window.XMLHttpRequest !== "undefined") {
648
+ return new XMLHttpRequest();
649
+ } else {
650
+ return null;
651
+ }
652
+ };
653
+
654
+ this.getUA = function () {
655
+ var Sys = {};
656
+ var ua = navigator.userAgent.toLowerCase();
657
+ var s;
658
+
659
+ if (s = ua.match(/opera.([\d.]+)/)) {
660
+ Sys.opera = Number(s[1].split(".")[0]);
661
+ } else if (s = ua.match(/msie ([\d.]+)/)) {
662
+ Sys.ie = Number(s[1].split(".")[0]);
663
+ } else if (s = ua.match(/edge.([\d.]+)/)) {
664
+ Sys.edge = Number(s[1].split(".")[0]);
665
+ } else if (s = ua.match(/firefox\/([\d.]+)/)) {
666
+ Sys.firefox = Number(s[1].split(".")[0]);
667
+ } else if (s = ua.match(/chrome\/([\d.]+)/)) {
668
+ Sys.chrome = Number(s[1].split(".")[0]);
669
+ } else if (s = ua.match(/version\/([\d.]+).*safari/)) {
670
+ Sys.safari = Number(s[1].match(/^\d*.\d*/));
671
+ } else if (s = ua.match(/trident\/([\d.]+)/)) {
672
+ Sys.ie = 11;
673
+ }
674
+
675
+ return Sys;
676
+ };
677
+
678
+ this.isSupportBeaconSend = function () {
679
+ var supported = false;
680
+
681
+ if ((typeof navigator === "undefined" ? "undefined" : _typeof(navigator)) !== "object" || typeof navigator.sendBeacon !== "function") {
682
+ return supported;
683
+ }
684
+
685
+ var Sys = _this.getUA();
686
+
687
+ var ua = navigator.userAgent.toLowerCase();
688
+
689
+ if (/Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent)) {
690
+ var reg = /os [\d._]*/gi;
691
+ var verinfo = ua.match(reg);
692
+ var version = (verinfo + "").replace(/[^0-9|_.]/gi, "").replace(/_/gi, ".");
693
+ var ver = version.split(".");
694
+
695
+ if (typeof Sys.safari === "undefined") {
696
+ Sys.safari = Number(ver[0]);
697
+ }
698
+
699
+ if (ver[0] && +ver[0] < 13) {
700
+ if (Sys.chrome > 41 || Sys.firefox > 30 || Sys.opera > 25 || Sys.safari > 12) {
701
+ supported = true;
702
+ }
703
+ } else if (Sys.chrome > 41 || Sys.firefox > 30 || Sys.opera > 25 || Sys.safari > 11.3) {
704
+ supported = true;
705
+ }
706
+ } else {
707
+ if (Sys.chrome > 38 || Sys.edge > 13 || Sys.firefox > 30 || Sys.opera > 25 || Sys.safari > 11.0) {
708
+ supported = true;
709
+ }
710
+ }
711
+
712
+ return supported;
713
+ };
714
+ /**
715
+ * 节流函数
716
+ * @param func 需要节流的函数
717
+ * @param wait 等待时间
718
+ * @returns 节流后的函数
719
+ */
720
+
721
+
722
+ this.throttle = function (func, wait) {
723
+ var timeout = null;
724
+ var previous = 0;
725
+ return function () {
726
+ var args = [];
727
+
728
+ for (var _i = 0; _i < arguments.length; _i++) {
729
+ args[_i] = arguments[_i];
730
+ }
731
+
732
+ var now = Date.now();
733
+ var remaining = wait - (now - previous);
734
+
735
+ if (remaining <= 0 || remaining > wait) {
736
+ if (timeout) {
737
+ clearTimeout(timeout);
738
+ timeout = null;
739
+ }
740
+
741
+ previous = now;
742
+ func.apply(void 0, args);
743
+ } else if (!timeout) {
744
+ timeout = window.setTimeout(function () {
745
+ previous = Date.now();
746
+ timeout = null;
747
+ func.apply(void 0, args);
748
+ }, remaining);
749
+ }
750
+ };
751
+ };
752
+ /**
753
+ * 防抖函数
754
+ * @param func 需要防抖的函数
755
+ * @param wait 等待时间
756
+ * @returns 防抖后的函数
757
+ */
758
+
759
+
760
+ this.debounce = function (func, wait) {
761
+ var timeout = null;
762
+ return function () {
763
+ var args = [];
764
+
765
+ for (var _i = 0; _i < arguments.length; _i++) {
766
+ args[_i] = arguments[_i];
767
+ }
768
+
769
+ if (timeout) {
770
+ clearTimeout(timeout);
771
+ }
772
+
773
+ timeout = window.setTimeout(function () {
774
+ func.apply(void 0, args);
775
+ }, wait);
776
+ };
777
+ };
778
+ /**
779
+ * beacon请求
780
+ * @param para SendBeacon参数
781
+ * @returns Promise<TrackingResponse>
782
+ */
783
+
784
+
785
+ this.sendBeacon = function (para) {
786
+ if (_this.isSupportBeaconSend() === true) {
787
+ var headers = {
788
+ type: para.contentType
789
+ };
790
+ var blob = new Blob([JSON.stringify(para.data)], headers);
791
+ var supportType = navigator.sendBeacon(para.url, blob);
792
+
793
+ if (supportType) {
794
+ return Promise.resolve({
795
+ success: true,
796
+ message: "发送成功"
797
+ });
798
+ } else {
799
+ return Promise.reject({
800
+ success: false,
801
+ message: "sendBeacon返回false"
802
+ });
803
+ }
804
+ } else {
805
+ return Promise.reject({
806
+ success: false,
807
+ message: "不支持sendBeacon,发送失败!"
808
+ });
809
+ }
810
+ };
811
+ /**
812
+ * 获取设备唯一标识
813
+ * 基于浏览器指纹技术,通过收集浏览器特征生成唯一ID
814
+ * @returns 返回设备唯一标识字符串
815
+ */
816
+
817
+
818
+ this.getDeviceId = function () {
819
+ // 获取已存储的设备ID
820
+ var storedDeviceId = _this.getCookie('device_id') || _this.getLocalStorage('device_id');
821
+
822
+ if (storedDeviceId) {
823
+ return storedDeviceId;
824
+ } // 收集浏览器指纹信息
825
+
826
+
827
+ var fingerprint = _this.collectFingerprint(); // 生成设备ID
828
+
829
+
830
+ var deviceId = _this.hashFingerprint(fingerprint); // 存储设备ID
831
+
832
+
833
+ _this.setCookie('device_id', deviceId, 365 * 2); // 存储2年
834
+
835
+
836
+ _this.setLocalStorage('device_id', deviceId);
837
+
838
+ return deviceId;
839
+ };
840
+ /**
841
+ * 收集浏览器指纹信息
842
+ * @returns 返回浏览器指纹对象
843
+ */
844
+
845
+
846
+ this.collectFingerprint = function () {
847
+ var fingerprint = {}; // 1. 用户代理
848
+
849
+ fingerprint.userAgent = navigator.userAgent; // 2. 屏幕信息
850
+
851
+ fingerprint.screenWidth = screen.width;
852
+ fingerprint.screenHeight = screen.height;
853
+ fingerprint.colorDepth = screen.colorDepth;
854
+ fingerprint.pixelDepth = screen.pixelDepth; // 3. 时区
855
+
856
+ fingerprint.timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
857
+ fingerprint.timezoneOffset = new Date().getTimezoneOffset(); // 4. 语言设置
858
+
859
+ fingerprint.language = navigator.language;
860
+ fingerprint.languages = Array.from(navigator.languages); // 5. 平台信息
861
+
862
+ fingerprint.platform = navigator.platform; // 6. WebGL 指纹
863
+
864
+ fingerprint.webgl = _this.getWebGLFingerprint(); // 7. Canvas 指纹
865
+
866
+ fingerprint.canvas = _this.getCanvasFingerprint(); // 8. 音频上下文指纹
867
+
868
+ fingerprint.audio = _this.getAudioFingerprint(); // 9. 字体检测
869
+
870
+ fingerprint.fonts = _this.getFontFingerprint(); // 10. 插件信息
871
+
872
+ fingerprint.plugins = _this.getPluginsFingerprint(); // 11. 存储检测
873
+
874
+ fingerprint.localStorage = _this.hasLocalStorage();
875
+ fingerprint.sessionStorage = _this.hasSessionStorage();
876
+ fingerprint.indexedDB = _this.hasIndexedDB(); // 12. 硬件信息
877
+
878
+ fingerprint.hardwareConcurrency = navigator.hardwareConcurrency;
879
+ fingerprint.deviceMemory = navigator.deviceMemory;
880
+ fingerprint.maxTouchPoints = navigator.maxTouchPoints; // 13. 连接信息
881
+
882
+ fingerprint.connection = _this.getConnectionFingerprint();
883
+ return fingerprint;
884
+ };
885
+ /**
886
+ * 获取WebGL指纹
887
+ * @returns WebGL指纹字符串
888
+ */
889
+
890
+
891
+ this.getWebGLFingerprint = function () {
892
+ try {
893
+ var canvas = document.createElement('canvas');
894
+ var gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
895
+ if (!gl) return 'not-supported';
896
+ var debugInfo = gl.getExtension('WEBGL_debug_renderer_info');
897
+ var vendor = debugInfo ? gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL) : 'unknown';
898
+ var renderer = debugInfo ? gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL) : 'unknown';
899
+ return vendor + "|" + renderer;
900
+ } catch (e) {
901
+ return 'error';
902
+ }
903
+ };
904
+ /**
905
+ * 获取Canvas指纹
906
+ * @returns Canvas指纹字符串
907
+ */
908
+
909
+
910
+ this.getCanvasFingerprint = function () {
911
+ try {
912
+ var canvas = document.createElement('canvas');
913
+ var ctx = canvas.getContext('2d');
914
+ if (!ctx) return 'not-supported'; // 绘制特定图形
915
+
916
+ ctx.textBaseline = 'top';
917
+ ctx.font = '14px Arial';
918
+ ctx.fillStyle = '#f60';
919
+ ctx.fillRect(125, 1, 62, 20);
920
+ ctx.fillStyle = '#069';
921
+ ctx.fillText('Canvas fingerprint', 2, 15);
922
+ ctx.fillStyle = 'rgba(102, 204, 0, 0.7)';
923
+ ctx.fillText('Canvas fingerprint', 4, 17);
924
+ return canvas.toDataURL().slice(-50); // 取后50个字符
925
+ } catch (e) {
926
+ return 'error';
927
+ }
928
+ };
929
+ /**
930
+ * 获取音频上下文指纹
931
+ * @returns 音频指纹字符串
932
+ */
933
+
934
+
935
+ this.getAudioFingerprint = function () {
936
+ try {
937
+ var AudioContextClass = window.AudioContext || window.webkitAudioContext;
938
+ if (!AudioContextClass) return 'not-supported';
939
+ var context = new AudioContextClass();
940
+ var oscillator = context.createOscillator();
941
+ var analyser = context.createAnalyser();
942
+ var gain = context.createGain();
943
+ var scriptProcessor = context.createScriptProcessor(4096, 1, 1);
944
+ oscillator.type = 'triangle';
945
+ oscillator.frequency.value = 10000;
946
+ gain.gain.value = 0;
947
+ oscillator.connect(analyser);
948
+ analyser.connect(scriptProcessor);
949
+ scriptProcessor.connect(gain);
950
+ gain.connect(context.destination);
951
+ oscillator.start(0);
952
+ var fingerprint = context.sampleRate + '|' + context.currentTime;
953
+ oscillator.stop();
954
+ context.close();
955
+ return fingerprint;
956
+ } catch (e) {
957
+ return 'error';
958
+ }
959
+ };
960
+ /**
961
+ * 获取字体指纹
962
+ * @returns 字体指纹字符串
963
+ */
964
+
965
+
966
+ this.getFontFingerprint = function () {
967
+ try {
968
+ var baseFonts_1 = ['monospace', 'sans-serif', 'serif'];
969
+ var testString_1 = 'mmmmmmmmmmlli';
970
+ var testSize_1 = '72px';
971
+ var canvas = document.createElement('canvas');
972
+ var ctx_1 = canvas.getContext('2d');
973
+ if (!ctx_1) return 'not-supported';
974
+ var detectedFonts_1 = []; // 测试字体列表
975
+
976
+ var fonts = ['Arial', 'Arial Black', 'Comic Sans MS', 'Courier New', 'Georgia', 'Helvetica', 'Impact', 'Times New Roman', 'Trebuchet MS', 'Verdana']; // 获取基准宽度
977
+
978
+ var baseWidths_1 = {};
979
+ baseFonts_1.forEach(function (font) {
980
+ ctx_1.font = testSize_1 + " " + font;
981
+ baseWidths_1[font] = ctx_1.measureText(testString_1).width;
982
+ }); // 测试每个字体
983
+
984
+ fonts.forEach(function (font) {
985
+ var detected = false;
986
+ baseFonts_1.forEach(function (baseFont) {
987
+ ctx_1.font = testSize_1 + " '" + font + "', " + baseFont;
988
+ var width = ctx_1.measureText(testString_1).width;
989
+
990
+ if (width !== baseWidths_1[baseFont]) {
991
+ detected = true;
992
+ }
993
+ });
994
+
995
+ if (detected) {
996
+ detectedFonts_1.push(font);
997
+ }
998
+ });
999
+ return detectedFonts_1.join(',');
1000
+ } catch (e) {
1001
+ return 'error';
1002
+ }
1003
+ };
1004
+ /**
1005
+ * 获取插件指纹
1006
+ * @returns 插件指纹字符串
1007
+ */
1008
+
1009
+
1010
+ this.getPluginsFingerprint = function () {
1011
+ try {
1012
+ var plugins = [];
1013
+
1014
+ if (navigator.plugins) {
1015
+ for (var i = 0; i < navigator.plugins.length; i++) {
1016
+ var plugin = navigator.plugins[i];
1017
+
1018
+ if (plugin) {
1019
+ plugins.push(plugin.name + "|" + plugin.description + "|" + plugin.filename);
1020
+ }
1021
+ }
1022
+ }
1023
+
1024
+ return plugins.join(';');
1025
+ } catch (e) {
1026
+ return 'error';
1027
+ }
1028
+ };
1029
+ /**
1030
+ * 检测localStorage支持
1031
+ * @returns 是否支持localStorage
1032
+ */
1033
+
1034
+
1035
+ this.hasLocalStorage = function () {
1036
+ try {
1037
+ var test = '__test__';
1038
+ localStorage.setItem(test, test);
1039
+ localStorage.removeItem(test);
1040
+ return true;
1041
+ } catch (e) {
1042
+ return false;
1043
+ }
1044
+ };
1045
+ /**
1046
+ * 检测sessionStorage支持
1047
+ * @returns 是否支持sessionStorage
1048
+ */
1049
+
1050
+
1051
+ this.hasSessionStorage = function () {
1052
+ try {
1053
+ var test = '__test__';
1054
+ sessionStorage.setItem(test, test);
1055
+ sessionStorage.removeItem(test);
1056
+ return true;
1057
+ } catch (e) {
1058
+ return false;
1059
+ }
1060
+ };
1061
+ /**
1062
+ * 检测IndexedDB支持
1063
+ * @returns 是否支持IndexedDB
1064
+ */
1065
+
1066
+
1067
+ this.hasIndexedDB = function () {
1068
+ return 'indexedDB' in window && indexedDB !== null;
1069
+ };
1070
+ /**
1071
+ * 获取网络连接指纹
1072
+ * @returns 网络连接指纹字符串
1073
+ */
1074
+
1075
+
1076
+ this.getConnectionFingerprint = function () {
1077
+ try {
1078
+ var connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
1079
+ if (!connection) return 'not-supported';
1080
+ return connection.effectiveType + "|" + connection.downlink + "|" + connection.rtt;
1081
+ } catch (e) {
1082
+ return 'error';
1083
+ }
1084
+ };
1085
+ /**
1086
+ * 将指纹信息哈希为唯一ID
1087
+ * @param fingerprint 指纹信息
1088
+ * @returns 返回哈希后的设备ID
1089
+ */
1090
+
1091
+
1092
+ this.hashFingerprint = function (fingerprint) {
1093
+ // 将指纹对象转换为字符串
1094
+ var fingerprintString = JSON.stringify(fingerprint, Object.keys(fingerprint).sort()); // 使用更强大的哈希算法生成ID
1095
+
1096
+ var hash1 = 5381; // DJB2哈希算法的初始值
1097
+
1098
+ var hash2 = 52711; // 第二个哈希的初始值
1099
+
1100
+ for (var i = 0; i < fingerprintString.length; i++) {
1101
+ var char = fingerprintString.charCodeAt(i);
1102
+ hash1 = (hash1 << 5) + hash1 + char; // hash1 * 33 + char
1103
+
1104
+ hash2 = (hash2 << 5) + hash2 + char; // hash2 * 33 + char
1105
+ } // 组合两个哈希值并转换为64位整数
1106
+
1107
+
1108
+ var combinedHash = (hash1 >>> 0) * 4096 + (hash2 >>> 0); // 转换为36进制并添加前缀,增加长度和唯一性
1109
+
1110
+ var deviceId = 'fp_' + combinedHash.toString(36);
1111
+ return deviceId;
1112
+ };
1113
+ }
1114
+ /**
1115
+ * 打印log
1116
+ */
1117
+
1118
+
1119
+ WebTrackingTools.prototype.printLog = function () {
1120
+ var rest = [];
1121
+
1122
+ for (var _i = 0; _i < arguments.length; _i++) {
1123
+ rest[_i] = arguments[_i];
1124
+ }
1125
+
1126
+ if (this.isObject(rest[0])) {
1127
+ rest[0] = this.formatJsonString(rest[0]);
1128
+ }
1129
+
1130
+ if ((typeof console === "undefined" ? "undefined" : _typeof(console)) === "object" && console.log) {
1131
+ try {
1132
+ return console.log.apply(console, rest);
1133
+ } catch (e) {
1134
+ console.log(rest[0]);
1135
+ }
1136
+ }
1137
+ };
1138
+ /**
1139
+ * @description 检验是否是对象
1140
+ */
1141
+
1142
+
1143
+ WebTrackingTools.prototype.isObject = function (obj) {
1144
+ if (obj == null) {
1145
+ return false;
1146
+ } else {
1147
+ return toString.call(obj) == "[object Object]";
1148
+ }
1149
+ };
1150
+
1151
+ WebTrackingTools.prototype.isUndefined = function (obj) {
1152
+ return obj === void 0;
1153
+ };
1154
+
1155
+ WebTrackingTools.prototype.isString = function (obj) {
1156
+ return toString.call(obj) == "[object String]";
1157
+ };
1158
+
1159
+ WebTrackingTools.prototype.isDate = function (obj) {
1160
+ return toString.call(obj) == "[object Date]";
1161
+ };
1162
+
1163
+ WebTrackingTools.prototype.isBoolean = function (obj) {
1164
+ return toString.call(obj) == "[object Boolean]";
1165
+ };
1166
+
1167
+ WebTrackingTools.prototype.isNumber = function (obj) {
1168
+ return toString.call(obj) == "[object Number]" && /[\d\.]+/.test(String(obj));
1169
+ };
1170
+
1171
+ WebTrackingTools.prototype.isElement = function (obj) {
1172
+ return !!(obj && obj.nodeType === 1);
1173
+ };
1174
+
1175
+ WebTrackingTools.prototype.isFunction = function (f) {
1176
+ if (!f) {
1177
+ return false;
1178
+ }
1179
+
1180
+ var type = toString.call(f);
1181
+ return type == "[object Function]" || type == "[object AsyncFunction]";
1182
+ };
1183
+
1184
+ WebTrackingTools.prototype.isJSONString = function (str) {
1185
+ if (!this.isString(str)) return false;
1186
+
1187
+ try {
1188
+ JSON.parse(str);
1189
+ } catch (e) {
1190
+ return false;
1191
+ }
1192
+
1193
+ return true;
1194
+ };
1195
+
1196
+ WebTrackingTools.prototype._decodeURIComponent = function (val) {
1197
+ var result = val;
1198
+
1199
+ try {
1200
+ result = decodeURIComponent(val);
1201
+ } catch (e) {
1202
+ result = val;
1203
+ }
1204
+
1205
+ return result;
1206
+ };
1207
+
1208
+ WebTrackingTools.prototype.getMainHost = function () {
1209
+ var key = "mh_" + Math.random();
1210
+ var keyR = new RegExp("(^|;)\\s*" + key + "=12345");
1211
+ var expiredTime = new Date(0);
1212
+ var domain = document.domain;
1213
+ var domainList = domain.split(".");
1214
+ var urlItems = []; // 主域名一定会有两部分组成
1215
+
1216
+ urlItems.unshift(domainList.pop()); // 慢慢从后往前测试
1217
+
1218
+ while (domainList.length) {
1219
+ urlItems.unshift(domainList.pop());
1220
+ var mainHost = urlItems.join(".");
1221
+ var cookie = key + "=" + 12345 + ";domain=." + mainHost;
1222
+ document.cookie = cookie; //如果cookie存在,则说明域名合法
1223
+
1224
+ if (keyR.test(document.cookie)) {
1225
+ document.cookie = cookie + ";expires=" + expiredTime;
1226
+ return mainHost;
1227
+ }
1228
+ }
1229
+
1230
+ return domain;
1231
+ };
1232
+
1233
+ return WebTrackingTools;
1234
+ }();
1235
+
1236
+ var WebTracking =
1237
+ /** @class */
1238
+ function (_super) {
1239
+ __extends(WebTracking, _super);
1240
+
1241
+ function WebTracking() {
1242
+ var _this = _super.call(this) || this; // 批量发送队列
1243
+
1244
+
1245
+ _this.batchQueue = []; // 批量发送定时器
1246
+
1247
+ _this.batchTimer = null; // LocalStorage 存储 key
1248
+
1249
+ _this.BATCH_QUEUE_STORAGE_KEY = 'web_tracking_batch_queue'; // 用户信息
1250
+
1251
+ _this.userInfo = null; // 当前路由
1252
+
1253
+ _this.currentUrl = ""; // 页面唯一标识,取当前路由 window.location.pathname.replace(/\//g, '_').substr(1)
1254
+
1255
+ _this.pageKey = ""; // 设备唯一标识
1256
+
1257
+ _this.deviceId = ""; // 上传事件描述
1258
+
1259
+ _this.eventDescMap = {
1260
+ PageView: "Web 浏览页面",
1261
+ WebClick: "Web 元素点击",
1262
+ PageRetained: "Web 页面浏览时长",
1263
+ CustomTrack: "Web 自定义代码上报"
1264
+ };
1265
+ /**
1266
+ * @description 初始化函数
1267
+ * @param {object} InitParams [初始化参数]
1268
+ */
1269
+
1270
+ _this.init = function (initParams) {
1271
+ _this.preset(initParams);
1272
+
1273
+ var pathname = window.location.pathname;
1274
+ _this.currentUrl = window.location.href;
1275
+ _this.pageKey = pathname.replace(/\//g, "_").substring(1);
1276
+ _this.systemsInfo = _this.getSystemsInfo(initParams.platform); // 获取设备ID
1277
+
1278
+ _this.deviceId = _this.getDeviceId();
1279
+
1280
+ _this.setCookie("retainedStartTime", _this.getTimeStamp()); // 如果启用了批量发送,从 LocalStorage 恢复队列
1281
+
1282
+
1283
+ if (_this.initConfig.batchSend) {
1284
+ _this.restoreBatchQueueFromStorage(); // 监听页面卸载事件,保存队列
1285
+
1286
+
1287
+ _this.setupBeforeUnloadListener();
1288
+ }
1289
+ };
1290
+ /**
1291
+ * TODO: 需要判断有哪些不能被预制的参数
1292
+ * @description 预置参数
1293
+ * @param {object} PresetParams [预置参数]
1294
+ */
1295
+
1296
+
1297
+ _this.preset = function (presetParams) {
1298
+ if (presetParams instanceof Object) {
1299
+ _this.each(presetParams, function (val, key) {
1300
+ if (_this.initConfig.hasOwnProperty(key)) {
1301
+ // TODO:后面加一些校验
1302
+ _this.initConfig[key] = val;
1303
+ }
1304
+ });
1305
+ }
1306
+
1307
+ if (!/^(((ht|f)tps?):\/\/)?[\w-]+(\.[\w-]+)+([\w.,@?^=%&:/~+#-\(\)]*[\w@?^=%&/~+#-\(\)])?$/.test(_this.initConfig["serverUrl"])) {
1308
+ _this.printLog("当前 server_url 为空或不正确,只在控制台打印日志,network 中不会发数据,请配置正确的 server_url!");
1309
+
1310
+ _this.initConfig["showLog"] = true;
1311
+ } // 如果启用了全埋点
1312
+
1313
+
1314
+ if (!!_this.initConfig["autoTrack"]) {
1315
+ // 启用监听
1316
+ _this.listener();
1317
+ } else {
1318
+ // 取消监听
1319
+ _this.unlistener();
1320
+ }
1321
+ };
1322
+ /**
1323
+ * 用户登录
1324
+ */
1325
+
1326
+
1327
+ _this.login = function (userInfo) {
1328
+ if (_this.isObject(userInfo)) _this.userInfo = userInfo;
1329
+ };
1330
+ /**
1331
+ * 获取设备唯一标识
1332
+ * @returns 设备唯一标识
1333
+ */
1334
+
1335
+
1336
+ _this.getDeviceId = function () {
1337
+ // 如果已有设备ID,直接返回
1338
+ if (_this.deviceId) {
1339
+ return _this.deviceId;
1340
+ } // 获取已存储的设备ID
1341
+
1342
+
1343
+ var storedDeviceId = _this.getCookie('device_id') || _this.getLocalStorage('device_id');
1344
+
1345
+ if (storedDeviceId) {
1346
+ _this.deviceId = storedDeviceId;
1347
+ return _this.deviceId;
1348
+ } // 收集浏览器指纹信息
1349
+
1350
+
1351
+ var fingerprint = _this.collectFingerprint(); // 生成设备ID
1352
+
1353
+
1354
+ var deviceId = _this.hashFingerprint(fingerprint); // 存储设备ID(统一使用2年过期时间,与tools.ts保持一致)
1355
+
1356
+
1357
+ _this.setCookie('device_id', deviceId, 365 * 2); // 存储2年
1358
+
1359
+
1360
+ _this.setLocalStorage('device_id', deviceId);
1361
+
1362
+ _this.deviceId = deviceId;
1363
+ return _this.deviceId;
1364
+ };
1365
+ /**
1366
+ * 重置设备ID
1367
+ * 清除存储的设备ID并重新生成
1368
+ * @returns 新的设备ID
1369
+ */
1370
+
1371
+
1372
+ _this.resetDeviceId = function () {
1373
+ // 清除cookie和localStorage中的设备ID
1374
+ document.cookie = 'device_id=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
1375
+ localStorage.removeItem('device_id'); // 清除内存中的设备ID
1376
+
1377
+ _this.deviceId = ''; // 重新生成设备ID
1378
+
1379
+ var newDeviceId = _this.getDeviceId();
1380
+
1381
+ return newDeviceId;
1382
+ };
1383
+ /**
1384
+ * 自定义代码埋点上报
1385
+ * @param {object} TrackParams [自定义上报参数]
1386
+ * @return {Promise<TrackingResponse>} [回调]
1387
+ */
1388
+
1389
+
1390
+ _this.track = function (_a) {
1391
+ var desc = _a.desc,
1392
+ partkey = _a.partkey,
1393
+ business = _a.business,
1394
+ header = _a.header;
1395
+
1396
+ var params = _this.getParams({
1397
+ desc: desc,
1398
+ event: "CustomTrack",
1399
+ itemKey: _this.getItemKey(partkey),
1400
+ privateParamMap: {
1401
+ business: business
1402
+ }
1403
+ });
1404
+
1405
+ return _this.sendData(params, header);
1406
+ };
1407
+ /**
1408
+ * @description 监听全埋点事件
1409
+ */
1410
+
1411
+
1412
+ _this.listener = function () {
1413
+ if (!!_this.initConfig.isTrackSinglePage) {
1414
+ _this.rewriteHistory();
1415
+
1416
+ _this.addSinglePageEvent(_this.onPageViewCallback);
1417
+ }
1418
+
1419
+ _this.each(["load", "beforeunload"], function (historyType) {
1420
+ _this.addEventListener(window, historyType, _this.onPageViewCallback);
1421
+ });
1422
+
1423
+ _this.addEventListener(window, "click", _this.onClickCallback);
1424
+ };
1425
+ /**
1426
+ * @description 取消全埋点事件
1427
+ */
1428
+
1429
+
1430
+ _this.unlistener = function () {
1431
+ if (!!_this.initConfig.isTrackSinglePage) {
1432
+ var historyPushState = window.history.pushState;
1433
+ var singlePageEvent = !!historyPushState ? "popstate" : "hashchange";
1434
+
1435
+ _this.each(["pushState", "replaceState", singlePageEvent], function (historyName) {
1436
+ _this.removeEventListener(window, historyName, _this.onPageViewCallback);
1437
+ });
1438
+ }
1439
+
1440
+ _this.each(["load", "beforeunload"], function (historyType) {
1441
+ _this.removeEventListener(window, historyType, _this.onPageViewCallback);
1442
+ });
1443
+
1444
+ _this.removeEventListener(window, "click", _this.onClickCallback); // 清理批量发送定时器
1445
+
1446
+
1447
+ _this.clearBatchTimer();
1448
+ };
1449
+ /**
1450
+ * @description 清理批量发送定时器
1451
+ */
1452
+
1453
+
1454
+ _this.clearBatchTimer = function () {
1455
+ if (_this.batchTimer !== null) {
1456
+ clearTimeout(_this.batchTimer);
1457
+ _this.batchTimer = null;
1458
+ }
1459
+ };
1460
+ /**
1461
+ * @description 清空批量队列(包括 LocalStorage 中的数据)
1462
+ */
1463
+
1464
+
1465
+ _this.clearBatchQueue = function () {
1466
+ _this.batchQueue = [];
1467
+
1468
+ _this.setLocalStorage(_this.BATCH_QUEUE_STORAGE_KEY, '[]');
1469
+
1470
+ if (_this.initConfig.showLog) {
1471
+ _this.printLog('批量队列已清空');
1472
+ }
1473
+ };
1474
+
1475
+ _this.onClickCallback = function (e) {
1476
+ var _a;
1477
+
1478
+ var target = e.target;
1479
+ if (!((_a = target === null || target === void 0 ? void 0 : target.dataset) === null || _a === void 0 ? void 0 : _a.partKey)) return;
1480
+ var position = [e.pageX, e.pageY];
1481
+ var id = target.id;
1482
+ var className = target.className;
1483
+ var nodeName = target.nodeName;
1484
+ var targetEle = {
1485
+ id: id,
1486
+ nodeName: nodeName,
1487
+ className: className,
1488
+ position: position
1489
+ };
1490
+
1491
+ var params = _this.getParams({
1492
+ event: "WebClick",
1493
+ desc: _this.eventDescMap["WebClick"],
1494
+ itemKey: _this.getItemKey(target.dataset.partKey),
1495
+ privateParamMap: {
1496
+ targetEle: targetEle,
1497
+ pointerType: e.pointerType,
1498
+ currentUrl: _this.currentUrl,
1499
+ elementSelector: _this.getDomSelector(target) || ''
1500
+ }
1501
+ });
1502
+
1503
+ return _this.sendData(params);
1504
+ };
1505
+ /**
1506
+ * @description 路由触发事件
1507
+ */
1508
+
1509
+
1510
+ _this.onPageViewCallback = function (e) {
1511
+ var _a, _b;
1512
+
1513
+ var ORGIN = window.location.origin;
1514
+
1515
+ var params = _this.getParams({
1516
+ event: "PageView",
1517
+ desc: _this.eventDescMap["PageView"],
1518
+ privateParamMap: {
1519
+ currentUrl: _this.currentUrl,
1520
+ targetUrl: ((_a = e.arguments) === null || _a === void 0 ? void 0 : _a[2]) ? ORGIN + ((_b = e.arguments) === null || _b === void 0 ? void 0 : _b[2]) : null
1521
+ }
1522
+ });
1523
+
1524
+ _this.currentUrl = window.location.href;
1525
+ _this.pageKey = window.location.pathname.replace(/\//g, "_").substring(1);
1526
+
1527
+ _this.sendRetained(e.type);
1528
+
1529
+ _this.sendData(params);
1530
+ };
1531
+
1532
+ _this.getParams = function (_a) {
1533
+ var event = _a.event,
1534
+ desc = _a.desc,
1535
+ _b = _a.privateParamMap,
1536
+ privateParamMap = _b === void 0 ? {} : _b,
1537
+ itemKey = _a.itemKey;
1538
+ var business = _this.initConfig.business;
1539
+ var pageWidth = window.innerWidth;
1540
+ var pageHeight = window.innerHeight;
1541
+ var screenWidth = window.screen.width;
1542
+ var screenHeight = window.screen.height; // 过滤敏感数据
1543
+
1544
+ var filteredBusiness = _this.filterSensitiveData(business || {});
1545
+
1546
+ var filteredUserInfo = _this.filterSensitiveData(_this.userInfo || {});
1547
+
1548
+ var filteredPrivateParamMap = _this.filterSensitiveData(privateParamMap || {});
1549
+
1550
+ var filteredUrlParams = _this.filterSensitiveData(_this.getQueryValue() || {}); // 创建私有参数对象
1551
+
1552
+
1553
+ var privateParamMapData = {
1554
+ currentUrl: filteredPrivateParamMap.currentUrl || _this.currentUrl,
1555
+ business: Object.assign({}, filteredBusiness, filteredPrivateParamMap.business || {}),
1556
+ pageWidth: pageWidth,
1557
+ pageHeight: pageHeight,
1558
+ screenWidth: screenWidth,
1559
+ screenHeight: screenHeight,
1560
+ sdkVersion: _this.sdkVersion,
1561
+ systemsInfo: _this.systemsInfo,
1562
+ urlParams: filteredUrlParams,
1563
+ userInfo: filteredUserInfo,
1564
+ deviceId: _this.deviceId // 添加设备ID
1565
+
1566
+ }; // 添加其他可能的属性
1567
+
1568
+ if (filteredPrivateParamMap.targetEle) {
1569
+ privateParamMapData.targetEle = filteredPrivateParamMap.targetEle;
1570
+ }
1571
+
1572
+ if (filteredPrivateParamMap.targetUrl) {
1573
+ privateParamMapData.targetUrl = filteredPrivateParamMap.targetUrl;
1574
+ }
1575
+
1576
+ if (filteredPrivateParamMap.pointerType) {
1577
+ privateParamMapData.pointerType = filteredPrivateParamMap.pointerType;
1578
+ }
1579
+
1580
+ if (filteredPrivateParamMap.elementSelector) {
1581
+ privateParamMapData.elementSelector = filteredPrivateParamMap.elementSelector;
1582
+ }
1583
+
1584
+ if (filteredPrivateParamMap.retainedDuration) {
1585
+ privateParamMapData.retainedDuration = filteredPrivateParamMap.retainedDuration;
1586
+ }
1587
+
1588
+ return {
1589
+ event: event,
1590
+ desc: desc,
1591
+ itemKey: itemKey || _this.getItemKey(),
1592
+ requestTime: _this.getTimeStamp(),
1593
+ privateParamMap: privateParamMapData
1594
+ };
1595
+ };
1596
+ /**
1597
+ * 数据采样判断
1598
+ * @returns 是否应该采样
1599
+ */
1600
+
1601
+
1602
+ _this.shouldSample = function () {
1603
+ var sampleRate = _this.initConfig.sampleRate;
1604
+ if (sampleRate >= 1) return true;
1605
+ if (sampleRate <= 0) return false;
1606
+ return Math.random() < sampleRate;
1607
+ };
1608
+ /**
1609
+ * 批量发送数据
1610
+ */
1611
+
1612
+
1613
+ _this.flushBatchQueue = function () {
1614
+ if (_this.batchQueue.length === 0) return;
1615
+
1616
+ var batchData = __spreadArray([], _this.batchQueue);
1617
+
1618
+ _this.batchQueue = []; // 从 LocalStorage 中移除已发送的数据
1619
+
1620
+ _this.saveBatchQueueToStorage(); // 发送批量数据
1621
+
1622
+
1623
+ _this.sendBatchData(batchData);
1624
+ };
1625
+ /**
1626
+ * 发送批量数据
1627
+ * @param data 批量数据
1628
+ */
1629
+
1630
+
1631
+ _this.sendBatchData = function (data) {
1632
+ var _a = _this.initConfig,
1633
+ serverUrl = _a.serverUrl,
1634
+ contentType = _a.contentType,
1635
+ showLog = _a.showLog;
1636
+
1637
+ if (showLog) {
1638
+ _this.printLog("\u6279\u91CF\u53D1\u9001 " + data.length + " \u6761\u6570\u636E");
1639
+
1640
+ data.forEach(function (item) {
1641
+ return _this.printLog(item);
1642
+ });
1643
+ } // 这里可以根据实际需求决定是逐条发送还是打包发送
1644
+ // 这里选择打包发送
1645
+
1646
+
1647
+ _this.ajax({
1648
+ url: serverUrl,
1649
+ type: "POST",
1650
+ data: JSON.stringify({
1651
+ events: data
1652
+ }),
1653
+ contentType: contentType,
1654
+ credentials: false,
1655
+ timeout: _this.initConfig.sendTimeout,
1656
+ cors: true,
1657
+ success: function success() {
1658
+ // 批量发送成功,数据已从队列中移除,无需额外操作
1659
+ if (_this.initConfig.showLog) {
1660
+ _this.printLog("\u6279\u91CF\u53D1\u9001\u6210\u529F: " + data.length + " \u6761\u6570\u636E");
1661
+ }
1662
+ },
1663
+ error: function error(err) {
1664
+ var _a; // 批量发送失败,重新加入队列以便重试
1665
+
1666
+
1667
+ _this.printLog("\u6279\u91CF\u53D1\u9001\u5931\u8D25: " + err + "\uFF0C\u6570\u636E\u5DF2\u91CD\u65B0\u52A0\u5165\u961F\u5217"); // 将失败的数据重新加入队列,避免数据丢失
1668
+
1669
+
1670
+ (_a = _this.batchQueue).unshift.apply(_a, data); // 限制重试队列大小,避免内存溢出
1671
+
1672
+
1673
+ if (_this.batchQueue.length > _this.initConfig.batchMaxSize * 2) {
1674
+ _this.batchQueue = _this.batchQueue.slice(0, _this.initConfig.batchMaxSize);
1675
+ } // 保存失败的数据到 LocalStorage
1676
+
1677
+
1678
+ _this.saveBatchQueueToStorage();
1679
+ }
1680
+ });
1681
+ };
1682
+ /**
1683
+ * 添加到批量队列
1684
+ * @param params 数据参数
1685
+ */
1686
+
1687
+
1688
+ _this.addToBatchQueue = function (params) {
1689
+ var _a = _this.initConfig,
1690
+ batchInterval = _a.batchInterval,
1691
+ batchMaxSize = _a.batchMaxSize;
1692
+
1693
+ _this.batchQueue.push(params); // 保存到 LocalStorage
1694
+
1695
+
1696
+ _this.saveBatchQueueToStorage(); // 如果队列达到最大数量,立即发送
1697
+
1698
+
1699
+ if (_this.batchQueue.length >= batchMaxSize) {
1700
+ _this.flushBatchQueue();
1701
+
1702
+ return;
1703
+ } // 设置定时发送
1704
+
1705
+
1706
+ if (!_this.batchTimer) {
1707
+ _this.batchTimer = window.setTimeout(function () {
1708
+ _this.flushBatchQueue();
1709
+
1710
+ _this.batchTimer = null;
1711
+ }, batchInterval);
1712
+ }
1713
+ };
1714
+ /**
1715
+ * 从 LocalStorage 恢复批量队列
1716
+ */
1717
+
1718
+
1719
+ _this.restoreBatchQueueFromStorage = function () {
1720
+ try {
1721
+ var storedQueue = _this.getLocalStorage(_this.BATCH_QUEUE_STORAGE_KEY);
1722
+
1723
+ if (storedQueue) {
1724
+ var parsedQueue = JSON.parse(storedQueue);
1725
+
1726
+ if (Array.isArray(parsedQueue) && parsedQueue.length > 0) {
1727
+ _this.batchQueue = parsedQueue;
1728
+
1729
+ if (_this.initConfig.showLog) {
1730
+ _this.printLog("\u4ECE LocalStorage \u6062\u590D " + parsedQueue.length + " \u6761\u5F85\u53D1\u9001\u6570\u636E");
1731
+ } // 恢复后立即尝试发送(如果达到条件)
1732
+
1733
+
1734
+ var batchMaxSize = _this.initConfig.batchMaxSize;
1735
+
1736
+ if (_this.batchQueue.length >= batchMaxSize) {
1737
+ _this.flushBatchQueue();
1738
+ } else {
1739
+ // 设置定时发送
1740
+ var batchInterval = _this.initConfig.batchInterval;
1741
+
1742
+ if (!_this.batchTimer) {
1743
+ _this.batchTimer = window.setTimeout(function () {
1744
+ _this.flushBatchQueue();
1745
+
1746
+ _this.batchTimer = null;
1747
+ }, batchInterval);
1748
+ }
1749
+ }
1750
+ }
1751
+ }
1752
+ } catch (e) {
1753
+ _this.printLog("\u6062\u590D\u6279\u91CF\u961F\u5217\u5931\u8D25: " + e); // 如果解析失败,清除损坏的数据
1754
+
1755
+
1756
+ _this.setLocalStorage(_this.BATCH_QUEUE_STORAGE_KEY, '[]');
1757
+ }
1758
+ };
1759
+ /**
1760
+ * 保存批量队列到 LocalStorage
1761
+ */
1762
+
1763
+
1764
+ _this.saveBatchQueueToStorage = function () {
1765
+ try {
1766
+ var queueString = JSON.stringify(_this.batchQueue); // 检查存储大小,避免超出 LocalStorage 限制(通常 5-10MB)
1767
+ // 如果队列过大,只保留最新的数据
1768
+
1769
+ if (queueString.length > 4 * 1024 * 1024) {
1770
+ // 4MB 限制
1771
+ var maxItems = Math.floor(_this.batchQueue.length * 0.8); // 保留 80%
1772
+
1773
+ _this.batchQueue = _this.batchQueue.slice(-maxItems);
1774
+
1775
+ _this.printLog("\u961F\u5217\u8FC7\u5927\uFF0C\u5DF2\u622A\u65AD\u4FDD\u7559\u6700\u65B0 " + maxItems + " \u6761\u6570\u636E");
1776
+ }
1777
+
1778
+ _this.setLocalStorage(_this.BATCH_QUEUE_STORAGE_KEY, JSON.stringify(_this.batchQueue));
1779
+ } catch (e) {
1780
+ // LocalStorage 可能已满或不可用
1781
+ _this.printLog("\u4FDD\u5B58\u6279\u91CF\u961F\u5217\u5230 LocalStorage \u5931\u8D25: " + e);
1782
+ }
1783
+ };
1784
+ /**
1785
+ * 设置页面卸载监听器,保存队列
1786
+ */
1787
+
1788
+
1789
+ _this.setupBeforeUnloadListener = function () {
1790
+ // 使用 visibilitychange 事件(更可靠)
1791
+ document.addEventListener('visibilitychange', function () {
1792
+ if (document.visibilityState === 'hidden' && _this.batchQueue.length > 0) {
1793
+ _this.saveBatchQueueToStorage();
1794
+ }
1795
+ }); // 使用 beforeunload 事件作为备用
1796
+
1797
+ window.addEventListener('beforeunload', function () {
1798
+ if (_this.batchQueue.length > 0) {
1799
+ // 使用 sendBeacon 尝试发送数据(如果支持)
1800
+ if (navigator.sendBeacon && _this.initConfig.serverUrl) {
1801
+ try {
1802
+ var data = JSON.stringify({
1803
+ events: _this.batchQueue
1804
+ });
1805
+ var blob = new Blob([data], {
1806
+ type: 'application/json'
1807
+ });
1808
+ navigator.sendBeacon(_this.initConfig.serverUrl, blob); // 如果 sendBeacon 成功,清除队列
1809
+
1810
+ _this.batchQueue = [];
1811
+
1812
+ _this.setLocalStorage(_this.BATCH_QUEUE_STORAGE_KEY, '[]');
1813
+ } catch (e) {
1814
+ // sendBeacon 失败,保存到 LocalStorage
1815
+ _this.saveBatchQueueToStorage();
1816
+ }
1817
+ } else {
1818
+ // 不支持 sendBeacon,保存到 LocalStorage
1819
+ _this.saveBatchQueueToStorage();
1820
+ }
1821
+ }
1822
+ });
1823
+ };
1824
+ /**
1825
+ * 发送数据通用函数
1826
+ */
1827
+
1828
+
1829
+ _this.sendData = function (params, header) {
1830
+ // 数据采样判断
1831
+ if (!_this.shouldSample()) {
1832
+ return Promise.resolve({
1833
+ success: true,
1834
+ message: "数据已采样跳过"
1835
+ });
1836
+ }
1837
+
1838
+ var _a = _this.initConfig,
1839
+ serverUrl = _a.serverUrl,
1840
+ sendTimeout = _a.sendTimeout,
1841
+ contentType = _a.contentType,
1842
+ showLog = _a.showLog,
1843
+ initHeader = _a.header,
1844
+ batchSend = _a.batchSend;
1845
+ if (!!showLog) _this.printLog(params); // 如果启用批量发送
1846
+
1847
+ if (batchSend) {
1848
+ _this.addToBatchQueue(params);
1849
+
1850
+ return Promise.resolve({
1851
+ success: true,
1852
+ message: "已添加到批量队列"
1853
+ });
1854
+ }
1855
+
1856
+ if (_this.isSupportBeaconSend() === true && !header && !initHeader) {
1857
+ return _this.sendBeacon({
1858
+ contentType: contentType,
1859
+ url: serverUrl,
1860
+ data: params
1861
+ });
1862
+ } else {
1863
+ return new Promise(function (resolve, reject) {
1864
+ _this.ajax({
1865
+ header: header || initHeader,
1866
+ url: serverUrl,
1867
+ type: "POST",
1868
+ data: JSON.stringify(params),
1869
+ contentType: contentType,
1870
+ credentials: false,
1871
+ timeout: sendTimeout,
1872
+ cors: true,
1873
+ success: function success(res) {
1874
+ return resolve({
1875
+ success: true,
1876
+ data: res
1877
+ });
1878
+ },
1879
+ error: function error(err, status) {
1880
+ return reject({
1881
+ success: false,
1882
+ message: String(err),
1883
+ code: status
1884
+ });
1885
+ }
1886
+ });
1887
+ });
1888
+ }
1889
+ };
1890
+ /**
1891
+ * @description 留存时长上报
1892
+ * @param type
1893
+ */
1894
+
1895
+
1896
+ _this.sendRetained = function (type) {
1897
+ var params = _this.getParams({
1898
+ event: "PageRetained",
1899
+ desc: _this.eventDescMap["PageRetained"]
1900
+ });
1901
+
1902
+ if (["beforeunload", "pushState", "replaceState", "hashchange", "popstate"].indexOf(type) >= 0) {
1903
+ var __time = _this.getCookie("retainedStartTime");
1904
+
1905
+ var retainedStartTime = __time ? +__time : _this.getTimeStamp();
1906
+
1907
+ var retainedData = __assign(__assign({}, params), {
1908
+ privateParamMap: __assign(__assign({}, params.privateParamMap), {
1909
+ retainedDuration: Math.max(params.requestTime - retainedStartTime, 0)
1910
+ })
1911
+ });
1912
+
1913
+ _this.sendData(retainedData);
1914
+
1915
+ _this.setCookie("retainedStartTime", _this.getTimeStamp());
1916
+ }
1917
+ };
1918
+ /**
1919
+ * @description 获取 itemKey
1920
+ * @param {[string]} partkey [控件/自定义事件的唯一标识]
1921
+ * @return {[string]}
1922
+ */
1923
+
1924
+
1925
+ _this.getItemKey = function (partkey) {
1926
+ var appKey = _this.initConfig.appKey;
1927
+ var keys = [appKey, _this.pageKey, partkey ? partkey.toString() : undefined].filter(function (key) {
1928
+ return !!key;
1929
+ });
1930
+ return keys.reduce(function (str, key) {
1931
+ return str + ("" + (str.length ? "." : "")) + key;
1932
+ }, "");
1933
+ };
1934
+
1935
+ _this.sdkVersion = "1.2.0"; // sdk版本
1936
+
1937
+ _this.initConfig = {
1938
+ appKey: "",
1939
+ platform: undefined,
1940
+ showLog: false,
1941
+ serverUrl: "",
1942
+ autoTrack: false,
1943
+ sendTimeout: 3000,
1944
+ isTrackSinglePage: false,
1945
+ contentType: "application/json",
1946
+ business: {},
1947
+ header: undefined,
1948
+ sampleRate: 1,
1949
+ batchSend: false,
1950
+ batchInterval: 5000,
1951
+ batchMaxSize: 10 // 批量发送最大数量
1952
+
1953
+ }; // 系统信息
1954
+
1955
+ _this.systemsInfo = {};
1956
+ return _this;
1957
+ }
1958
+ /**
1959
+ * @description 添加单页面监听事件
1960
+ * @param callback
1961
+ */
1962
+
1963
+
1964
+ WebTracking.prototype.addSinglePageEvent = function (callback) {
1965
+ var _this = this;
1966
+
1967
+ var historyPushState = window.history.pushState;
1968
+ var singlePageEvent = historyPushState ? "popstate" : "hashchange";
1969
+ this.each(["pushState", "replaceState", singlePageEvent], function (historyType) {
1970
+ _this.addEventListener(window, historyType, callback);
1971
+ });
1972
+ };
1973
+
1974
+ return WebTracking;
1975
+ }(WebTrackingTools);
1976
+
1977
+ var index = new WebTracking();
1978
+
1979
+ export default index;