@fle-sdk/event-tracking-web 1.2.2 → 1.2.3

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.min.js CHANGED
@@ -1 +1 @@
1
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).WebTracking=t()}(this,(function(){"use strict";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)};function n(e,t){for(var n=0,r=t.length,i=e.length;n<r;n++,i++)e[i]=t[n];return e}function r(e){return(r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}return new(function(r){function i(){var e=r.call(this)||this;return e.batchQueue=[],e.batchTimer=null,e.BATCH_QUEUE_STORAGE_KEY="web_tracking_batch_queue",e.useCustomPageKey=!1,e.pendingRequests=[],e.isUnloadListenerSetup=!1,e.PENDING_REQUESTS_STORAGE_KEY="web_tracking_pending_requests",e.DEFAULT_PENDING_REQUESTS_MAX_SIZE=50,e.MAX_STORAGE_SIZE=4194304,e.userInfo=null,e.currentUrl="",e.pageKey="",e.deviceId="",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,t.pageKey?(e.pageKey=t.pageKey,e.useCustomPageKey=!0):(e.pageKey=n.replace(/\//g,"_").substring(1),e.useCustomPageKey=!1),e.systemsInfo=e.getSystemsInfo(t.platform),e.deviceId=e.getDeviceId(),t.userInfo&&e.isObject(t.userInfo)&&(e.userInfo=t.userInfo),e.setCookie("retainedStartTime",e.getTimeStamp()),e.initConfig.batchSend&&e.restoreBatchQueueFromStorage(),e.restorePendingRequestsFromStorage(),e.setupBeforeUnloadListener()},e.preset=function(t){if(t instanceof Object){if(void 0!==t.pageKey)if(null===t.pageKey||""===t.pageKey){e.useCustomPageKey=!1;var n=window.location.pathname;e.pageKey=n.replace(/\//g,"_").substring(1)}else e.pageKey=t.pageKey,e.useCustomPageKey=!0;e.each(t,(function(t,n){"pageKey"!==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.initConfig.trackPartKeyClick?e.listener():e.unlistener()},e.login=function(t){e.isObject(t)&&(e.userInfo=t)},e.getDeviceId=function(){if(e.deviceId)return e.deviceId;var t=e.getCookie("device_id")||e.getLocalStorage("device_id");if(t)return e.deviceId=t,e.deviceId;var n=e.collectFingerprint(),r=e.hashFingerprint(n);return e.setCookie("device_id",r,730),e.setLocalStorage("device_id",r),e.deviceId=r,e.deviceId},e.resetDeviceId=function(){return document.cookie="device_id=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;",localStorage.removeItem("device_id"),e.deviceId="",e.getDeviceId()},e.track=function(t){var n=t.desc,r=t.pageKey,i=t.partkey,o=t.business,a=t.header,s=e.getParams({desc:n,event:"CustomTrack",itemKey:e.getItemKey(i,r),privateParamMap:{business:o}});return e.sendData(s,a)},e.listener=function(){e.initConfig.autoTrack&&(e.initConfig.isTrackSinglePage&&(e.rewriteHistory(),e.addSinglePageEvent(e.onPageViewCallback)),e.each(["load","beforeunload"],(function(t){e.addEventListener(window,t,e.onPageViewCallback)}))),(e.initConfig.autoTrack||e.initConfig.trackPartKeyClick)&&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.clearBatchTimer()},e.clearBatchTimer=function(){null!==e.batchTimer&&(clearTimeout(e.batchTimer),e.batchTimer=null)},e.clearBatchQueue=function(){e.batchQueue=[],e.setLocalStorage(e.BATCH_QUEUE_STORAGE_KEY,"[]"),e.initConfig.showLog&&e.printLog("批量队列已清空")},e.setPageKey=function(t,n){if(void 0===n&&(n=!1),null===t||""===t){e.useCustomPageKey=!1;var r=window.location.pathname;e.pageKey=r.replace(/\//g,"_").substring(1),e.initConfig.showLog&&e.printLog("页面标识已恢复自动生成: "+e.pageKey)}else e.pageKey=t,e.useCustomPageKey=!n,e.initConfig.showLog&&e.printLog("页面标识已设置为: "+t+", 自动更新: "+n)},e.getPageKey=function(){return e.pageKey},e.onClickCallback=function(t){var n,r=t.target;if(null===(n=null==r?void 0:r.dataset)||void 0===n?void 0:n.partKey){var i=[t.pageX,t.pageY],o=r.id,a=r.className,s={id:o,nodeName:r.nodeName,className:a,position:i},c=e.getParams({event:"WebClick",desc:e.eventDescMap.WebClick,itemKey:e.getItemKey(r.dataset.partKey),privateParamMap:{targetEle:s,pointerType:t.pointerType,currentUrl:e.currentUrl,elementSelector:e.getDomSelector(r)||""}});return e.sendData(c)}},e.onPageViewCallback=function(t){var n,r;(e.pendingRequests.length>0||e.initConfig.batchSend&&e.batchQueue.length>0)&&e.flushPendingData();var 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.useCustomPageKey||(e.pageKey=window.location.pathname.replace(/\//g,"_").substring(1)),e.sendRetained(t.type),e.sendData(o)},e.getParams=function(t){var n=t.event,r=t.desc,i=t.privateParamMap,o=void 0===i?{}:i,a=t.itemKey,s=e.initConfig.business,c=window.innerWidth,u=window.innerHeight,g=window.screen.width,l=window.screen.height,d=e.filterSensitiveData(s||{}),p=e.filterSensitiveData(e.userInfo||{}),h=e.filterSensitiveData(o||{}),f=e.filterSensitiveData(e.getQueryValue()||{}),v={currentUrl:h.currentUrl||e.currentUrl,business:Object.assign({},d,h.business||{}),pageWidth:c,pageHeight:u,screenWidth:g,screenHeight:l,sdkVersion:e.sdkVersion,systemsInfo:e.systemsInfo,urlParams:f,userInfo:p,deviceId:e.deviceId};return h.targetEle&&(v.targetEle=h.targetEle),h.targetUrl&&(v.targetUrl=h.targetUrl),h.pointerType&&(v.pointerType=h.pointerType),h.elementSelector&&(v.elementSelector=h.elementSelector),h.retainedDuration&&(v.retainedDuration=h.retainedDuration),{event:n,desc:r,itemKey:a||e.getItemKey(),requestTime:e.getTimeStamp(),privateParamMap:v}},e.shouldSample=function(){var t=e.initConfig.sampleRate;return t>=1||!(t<=0)&&Math.random()<t},e.flushBatchQueue=function(){if(0!==e.batchQueue.length){var t=n([],e.batchQueue);e.batchQueue=[],e.saveBatchQueueToStorage(),e.sendBatchData(t)}},e.sendBatchData=function(t){var n=e.initConfig,r=n.serverUrl,i=n.contentType;n.showLog&&(e.printLog("批量发送 "+t.length+" 条数据"),t.forEach((function(t){return e.printLog(t)}))),e.ajax({url:r,type:"POST",data:JSON.stringify({events:t}),contentType:i,credentials:!1,timeout:e.initConfig.sendTimeout,cors:!0,success:function(){e.initConfig.showLog&&e.printLog("批量发送成功: "+t.length+" 条数据")},error:function(n){var r;e.printLog("批量发送失败: "+n+",数据已重新加入队列"),(r=e.batchQueue).unshift.apply(r,t),e.batchQueue.length>2*e.initConfig.batchMaxSize&&(e.batchQueue=e.batchQueue.slice(0,e.initConfig.batchMaxSize)),e.saveBatchQueueToStorage()}})},e.addToBatchQueue=function(t){var n=e.initConfig,r=n.batchInterval,i=n.batchMaxSize;e.batchQueue.push(t),e.saveBatchQueueToStorage(),e.batchQueue.length>=i?e.flushBatchQueue():e.batchTimer||(e.batchTimer=window.setTimeout((function(){e.flushBatchQueue(),e.batchTimer=null}),r))},e.restoreBatchQueueFromStorage=function(){try{var t=e.getLocalStorage(e.BATCH_QUEUE_STORAGE_KEY);if(t){var n=JSON.parse(t);if(Array.isArray(n)&&n.length>0){e.batchQueue=n,e.initConfig.showLog&&e.printLog("从 LocalStorage 恢复 "+n.length+" 条待发送数据");var r=e.initConfig.batchMaxSize;if(e.batchQueue.length>=r)e.flushBatchQueue();else{var i=e.initConfig.batchInterval;e.batchTimer||(e.batchTimer=window.setTimeout((function(){e.flushBatchQueue(),e.batchTimer=null}),i))}}}}catch(t){e.printLog("恢复批量队列失败: "+t),e.setLocalStorage(e.BATCH_QUEUE_STORAGE_KEY,"[]")}},e.addToPendingRequests=function(t){e.pendingRequests.push(t);var n=e.initConfig.pendingRequestsMaxSize||e.DEFAULT_PENDING_REQUESTS_MAX_SIZE;e.pendingRequests.length>n&&(e.pendingRequests=e.pendingRequests.slice(-n),e.initConfig.showLog&&e.printLog("待发送请求队列已满,已移除最旧的数据(最大限制: "+n+")"))},e.restorePendingRequestsFromStorage=function(){try{var t=e.getLocalStorage(e.PENDING_REQUESTS_STORAGE_KEY);if(t){var n=JSON.parse(t);Array.isArray(n)&&n.length>0&&(e.pendingRequests=n,e.initConfig.showLog&&e.printLog("从 LocalStorage 恢复 "+n.length+" 条待发送请求"),e.pendingRequests.length>0&&e.flushPendingRequests())}}catch(t){e.printLog("恢复待发送请求失败: "+t),e.setLocalStorage(e.PENDING_REQUESTS_STORAGE_KEY,"[]")}},e.isPageUnloading=function(){return"hidden"===document.visibilityState},e.sendWithBeacon=function(t,n,r){try{var i=new Blob([JSON.stringify(t)],{type:r||"application/json"});return navigator.sendBeacon(n,i)}catch(t){return e.initConfig.showLog&&e.printLog("sendBeacon 发送失败: "+t),!1}},e.flushPendingRequests=function(){if(0!==e.pendingRequests.length){var t=n([],e.pendingRequests);e.pendingRequests=[],e.setLocalStorage(e.PENDING_REQUESTS_STORAGE_KEY,"[]"),t.forEach((function(t){e.sendData(t).catch((function(t){e.initConfig.showLog&&e.printLog("待发送请求发送失败(不再重试): "+t)}))}))}},e.saveBatchQueueToStorage=function(){try{if(JSON.stringify(e.batchQueue).length>e.MAX_STORAGE_SIZE){var t=Math.floor(.8*e.batchQueue.length);e.batchQueue=e.batchQueue.slice(-t),e.printLog("队列过大,已截断保留最新 "+t+" 条数据(限制: "+e.MAX_STORAGE_SIZE/1024/1024+"MB)")}e.setLocalStorage(e.BATCH_QUEUE_STORAGE_KEY,JSON.stringify(e.batchQueue))}catch(t){e.printLog("保存批量队列到 LocalStorage 失败: "+t)}},e.setupBeforeUnloadListener=function(){e.isUnloadListenerSetup||(e.isUnloadListenerSetup=!0,document.addEventListener("visibilitychange",(function(){e.isPageUnloading()&&e.flushPendingData()})),window.addEventListener("beforeunload",(function(){e.flushPendingData()})),window.addEventListener("pagehide",(function(){e.flushPendingData()})))},e.flushPendingData=function(){var t=[];if(e.batchQueue.length>0&&t.push.apply(t,e.batchQueue),e.pendingRequests.length>0&&t.push.apply(t,e.pendingRequests),0!==t.length)if(navigator.sendBeacon&&e.initConfig.serverUrl)try{var n=1===t.length?t[0]:{events:t},r=new Blob([JSON.stringify(n)],{type:e.initConfig.contentType||"application/json"});if(navigator.sendBeacon(e.initConfig.serverUrl,r))e.batchQueue=[],e.pendingRequests=[],e.setLocalStorage(e.BATCH_QUEUE_STORAGE_KEY,"[]"),e.initConfig.showLog&&e.printLog("页面卸载时成功发送 "+t.length+" 条数据");else if(e.initConfig.batchSend&&e.batchQueue.length>0&&e.saveBatchQueueToStorage(),e.pendingRequests.length>0)try{e.setLocalStorage(e.PENDING_REQUESTS_STORAGE_KEY,JSON.stringify(e.pendingRequests))}catch(t){e.initConfig.showLog&&e.printLog("保存待发送请求到 LocalStorage 失败: "+t)}}catch(t){if(e.initConfig.batchSend&&e.batchQueue.length>0&&e.saveBatchQueueToStorage(),e.pendingRequests.length>0)try{e.setLocalStorage(e.PENDING_REQUESTS_STORAGE_KEY,JSON.stringify(e.pendingRequests))}catch(e){}e.initConfig.showLog&&e.printLog("页面卸载时发送数据失败: "+t)}else if(e.initConfig.batchSend&&e.batchQueue.length>0&&e.saveBatchQueueToStorage(),e.pendingRequests.length>0)try{e.setLocalStorage(e.PENDING_REQUESTS_STORAGE_KEY,JSON.stringify(e.pendingRequests))}catch(e){}},e.sendData=function(t,n){if(!e.shouldSample())return Promise.resolve({success:!0,message:"数据已采样跳过"});var r=e.initConfig,i=r.serverUrl,o=r.sendTimeout,a=r.contentType,s=r.showLog,c=r.header,u=r.batchSend;return s&&e.printLog(t),u?(e.addToBatchQueue(t),Promise.resolve({success:!0,message:"已添加到批量队列"})):!0!==e.isSupportBeaconSend()||n||c?new Promise((function(r,s){if(e.isPageUnloading()&&e.isSupportBeaconSend()&&!n&&!c&&e.sendWithBeacon(t,i,a))return void r({success:!0,message:"页面卸载时使用 sendBeacon 发送成功"});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({success:!0,data:e})},error:function(o,u){if(e.isPageUnloading()&&e.isSupportBeaconSend()&&!n&&!c&&e.sendWithBeacon(t,i,a))return void r({success:!0,message:"XMLHttpRequest 失败,已使用 sendBeacon 发送"});s({success:!1,message:String(o),code:u})}})})):e.isPageUnloading()?e.sendWithBeacon(t,i,a)?Promise.resolve({success:!0,message:"页面卸载时发送成功"}):(e.addToPendingRequests(t),Promise.resolve({success:!0,message:"已添加到待发送队列"})):e.sendBeacon({contentType:a,url:i,data:t}).catch((function(n){return e.addToPendingRequests(t),Promise.resolve({success:!0,message:"sendBeacon 失败,已添加到待发送队列"})}))},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,n){return[e.initConfig.appKey,(n||e.pageKey).toString(),t?t.toString():void 0].filter((function(e){return!!e})).reduce((function(e,t){return e+(e.length?".":"")+t}),"")},e.sdkVersion="1.2.0",e.initConfig={appKey:"",platform:void 0,showLog:!1,serverUrl:"",autoTrack:!1,sendTimeout:3e3,isTrackSinglePage:!1,contentType:"application/json",business:{},header:void 0,sampleRate:1,batchSend:!1,batchInterval:5e3,batchMaxSize:10,trackPartKeyClick:!1,pendingRequestsMaxSize:50},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)}(i,r),i.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)}))},i}(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),g=t.match(/(android)\s([\d\.]+)/i),l=t.match(/(Windows NT)\s([\d\.]+)/i),d=t.match(/(Mac OS X)\s([\d_]+)/i);r=[],g?(r.push("Android "+g[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"):l?(r.push("Windows "+l[2].replace(/_/g,".")),n="pc"):d&&(r.push("Mac, MacOS "+d[2].replace(/_/g,".")),n="pc"),a&&r.push("WeChat "+a),i.client=r.length?r.join(", "):"Unknown",i.platform=e||n;var p=t.toLowerCase().match(/ nettype\/([^ ]+)/g);return p&&p[0]&&(r=[(p=p[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;return!0},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="",g="";e&&(c=s(e)),t&&(u=s(t)),r&&(g=s(r)),c&&u&&(document.cookie=c+"="+encodeURIComponent(u)+i+"; path=/"+g)},this.getLocalStorage=function(e){try{return localStorage.getItem(e)}catch(e){return null}},this.setLocalStorage=function(e,t){try{localStorage.setItem(e,t)}catch(e){}},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.filterSensitiveData=function(t,n){if(void 0===n&&(n=["password","token","secret","key"]),!e.isObject(t))return t;var r={};return e.each(t,(function(t,i){n.some((function(e){return"string"==typeof i&&i.toLowerCase().includes(e.toLowerCase())}))?r[i]="***":e.isObject(t)?r[i]=e.filterSensitiveData(t,n):r[i]=t})),r},this.xssFilter=function(e){return e?"string"!=typeof e?e.toString():e.replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#x27;").replace(/\//g,"&#x2F;"):""},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 Object.keys(t).length>0?t:null},this.ajax=function(t){function n(e){if(!e)return{};if("string"==typeof e)try{return JSON.parse(e)}catch(e){return{}}return"object"===r(e)?e:{}}t.timeout=t.timeout||3e4,t.credentials=void 0===t.credentials||t.credentials;var i=e.xhr(t.cors);if(!i)return!1;t.type||(t.type=t.data?"POST":"GET");var o,a=t.success,s=t.error;t.success=function(e){a&&a(e),o&&(clearTimeout(o),o=null)},t.error=function(e,t){s&&s(e,t),o&&(clearTimeout(o),o=null)},o=window.setTimeout((function(){!function(){try{e.isObject(i)&&i.abort&&i.abort()}catch(t){e.printLog(t)}o&&(clearTimeout(o),o=null,t.error&&t.error(),i.onreadystatechange=null,i.onload=null,i.onerror=null)}()}),t.timeout),i.onreadystatechange=function(){try{4==i.readyState&&(i.status>=200&&i.status<300||304==i.status?t.success&&t.success(n(i.responseText)):t.error&&t.error(n(i.responseText),i.status),i.onreadystatechange=null,i.onload=null)}catch(e){i.onreadystatechange=null,i.onload=null}},i.open(t.type||"GET",t.url,!0);try{t.credentials&&(i.withCredentials=!0),e.isObject(t.header)&&e.each(t.header,(function(e,t){i.setRequestHeader&&i.setRequestHeader(t,e)})),t.data&&(t.cors||i.setRequestHeader&&i.setRequestHeader("X-Requested-With","XMLHttpRequest"),"application/json"===t.contentType?i.setRequestHeader&&i.setRequestHeader("Content-type","application/json; charset=UTF-8"):i.setRequestHeader&&i.setRequestHeader("Content-type","application/x-www-form-urlencoded"))}catch(t){e.printLog(t)}i.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"!==("undefined"==typeof navigator?"undefined":r(navigator))||"function"!=typeof navigator.sendBeacon)return t;var n=e.getUA(),i=navigator.userAgent.toLowerCase();if(/Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent)){var o=(i.match(/os [\d._]*/gi)+"").replace(/[^0-9|_.]/gi,"").replace(/_/gi,".").split(".");void 0===n.safari&&(n.safari=Number(o[0])),o[0]&&+o[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.throttle=function(e,t){var n=null,r=0;return function(){for(var i=[],o=0;o<arguments.length;o++)i[o]=arguments[o];var a=Date.now(),s=t-(a-r);s<=0||s>t?(n&&(clearTimeout(n),n=null),r=a,e.apply(void 0,i)):n||(n=window.setTimeout((function(){r=Date.now(),n=null,e.apply(void 0,i)}),s))}},this.debounce=function(e,t){var n=null;return function(){for(var r=[],i=0;i<arguments.length;i++)r[i]=arguments[i];n&&clearTimeout(n),n=window.setTimeout((function(){e.apply(void 0,r)}),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,message:"发送成功"}):Promise.reject({success:!1,message:"sendBeacon返回false"})}return Promise.reject({success:!1,message:"不支持sendBeacon,发送失败!"})},this.getDeviceId=function(){var t=e.getCookie("device_id")||e.getLocalStorage("device_id");if(t)return t;var n=e.collectFingerprint(),r=e.hashFingerprint(n);return e.setCookie("device_id",r,730),e.setLocalStorage("device_id",r),r},this.collectFingerprint=function(){var t={};return t.userAgent=navigator.userAgent,t.screenWidth=screen.width,t.screenHeight=screen.height,t.colorDepth=screen.colorDepth,t.pixelDepth=screen.pixelDepth,t.timezone=Intl.DateTimeFormat().resolvedOptions().timeZone,t.timezoneOffset=(new Date).getTimezoneOffset(),t.language=navigator.language,t.languages=Array.from(navigator.languages),t.platform=navigator.platform,t.webgl=e.getWebGLFingerprint(),t.canvas=e.getCanvasFingerprint(),t.audio=e.getAudioFingerprint(),t.fonts=e.getFontFingerprint(),t.plugins=e.getPluginsFingerprint(),t.localStorage=e.hasLocalStorage(),t.sessionStorage=e.hasSessionStorage(),t.indexedDB=e.hasIndexedDB(),t.hardwareConcurrency=navigator.hardwareConcurrency,t.deviceMemory=navigator.deviceMemory,t.maxTouchPoints=navigator.maxTouchPoints,t.connection=e.getConnectionFingerprint(),t},this.getWebGLFingerprint=function(){try{var e=document.createElement("canvas"),t=e.getContext("webgl")||e.getContext("experimental-webgl");if(!t)return"not-supported";var n=t.getExtension("WEBGL_debug_renderer_info");return(n?t.getParameter(n.UNMASKED_VENDOR_WEBGL):"unknown")+"|"+(n?t.getParameter(n.UNMASKED_RENDERER_WEBGL):"unknown")}catch(e){return"error"}},this.getCanvasFingerprint=function(){try{var e=document.createElement("canvas"),t=e.getContext("2d");return t?(t.textBaseline="top",t.font="14px Arial",t.fillStyle="#f60",t.fillRect(125,1,62,20),t.fillStyle="#069",t.fillText("Canvas fingerprint",2,15),t.fillStyle="rgba(102, 204, 0, 0.7)",t.fillText("Canvas fingerprint",4,17),e.toDataURL().slice(-50)):"not-supported"}catch(e){return"error"}},this.getAudioFingerprint=function(){try{var e=window.AudioContext||window.webkitAudioContext;if(!e)return"not-supported";var t=new e,n=t.createOscillator(),r=t.createAnalyser(),i=t.createGain(),o=t.createScriptProcessor(4096,1,1);n.type="triangle",n.frequency.value=1e4,i.gain.value=0,n.connect(r),r.connect(o),o.connect(i),i.connect(t.destination),n.start(0);var a=t.sampleRate+"|"+t.currentTime;return n.stop(),t.close(),a}catch(e){return"error"}},this.getFontFingerprint=function(){try{var e=["monospace","sans-serif","serif"],t="mmmmmmmmmmlli",n=document.createElement("canvas").getContext("2d");if(!n)return"not-supported";var r=[],i={};return e.forEach((function(e){n.font="72px "+e,i[e]=n.measureText(t).width})),["Arial","Arial Black","Comic Sans MS","Courier New","Georgia","Helvetica","Impact","Times New Roman","Trebuchet MS","Verdana"].forEach((function(o){var a=!1;e.forEach((function(e){n.font="72px '"+o+"', "+e,n.measureText(t).width!==i[e]&&(a=!0)})),a&&r.push(o)})),r.join(",")}catch(e){return"error"}},this.getPluginsFingerprint=function(){try{var e=[];if(navigator.plugins)for(var t=0;t<navigator.plugins.length;t++){var n=navigator.plugins[t];n&&e.push(n.name+"|"+n.description+"|"+n.filename)}return e.join(";")}catch(e){return"error"}},this.hasLocalStorage=function(){try{var e="__test__";return localStorage.setItem(e,e),localStorage.removeItem(e),!0}catch(e){return!1}},this.hasSessionStorage=function(){try{var e="__test__";return sessionStorage.setItem(e,e),sessionStorage.removeItem(e),!0}catch(e){return!1}},this.hasIndexedDB=function(){return"indexedDB"in window&&null!==indexedDB},this.getConnectionFingerprint=function(){try{var e=navigator.connection||navigator.mozConnection||navigator.webkitConnection;return e?e.effectiveType+"|"+e.downlink+"|"+e.rtt:"not-supported"}catch(e){return"error"}},this.hashFingerprint=function(e){for(var t=JSON.stringify(e,Object.keys(e).sort()),n=5381,r=52711,i=0;i<t.length;i++){var o=t.charCodeAt(i);n=(n<<5)+n+o,r=(r<<5)+r+o}return"fp_"+(4096*(n>>>0)+(r>>>0)).toString(36)}}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"===("undefined"==typeof console?"undefined":r(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){if(!this.isString(e))return!1;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,i=r.split("."),o=[];for(o.unshift(i.pop());i.length;){o.unshift(i.pop());var a=o.join("."),s=e+"=12345;domain=."+a;if(document.cookie=s,t.test(document.cookie))return document.cookie=s+";expires="+n,a}return r},e}()))}));
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).WebTracking=t()}(this,(function(){"use strict";function e(t){return(e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(t)}var t=function(e,n){return(t=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])})(e,n)};var n=function(){return(n=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)};function r(e,t){for(var n=0,r=t.length,i=e.length;n<r;n++,i++)e[i]=t[n];return e}return new(function(i){function a(){var t=i.call(this)||this;return t.batchTimer=null,t.BATCH_QUEUE_STORAGE_KEY="web_tracking_batch_queue",t.useCustomPageKey=!1,t.isUnloadListenerSetup=!1,t.pageDurationTimer=null,t.PENDING_REQUESTS_STORAGE_KEY="web_tracking_pending_requests",t.DEFAULT_PENDING_REQUESTS_MAX_SIZE=50,t.MAX_STORAGE_SIZE=4194304,t.userInfo=null,t.currentUrl="",t.pageKey="",t.deviceId="",t.eventDescMap={PageView:"Web 浏览页面",WebClick:"Web 元素点击",PageRetained:"Web 页面浏览时长",CustomTrack:"Web 自定义代码上报"},t.init=function(e){t.preset(e);var n=window.location.pathname;t.currentUrl=window.location.href,e.pageKey?(t.pageKey=e.pageKey,t.useCustomPageKey=!0):(t.pageKey=n.replace(/\//g,"_").substring(1),t.useCustomPageKey=!1),t.systemsInfo=t.getSystemsInfo(e.platform),t.deviceId=t.getDeviceId(),e.userInfo&&t.isObject(e.userInfo)&&(t.userInfo=e.userInfo),t.setCookie("retainedStartTime",t.getTimeStamp()),t.initConfig.batchSend&&t.restoreBatchQueueFromStorage(),t.restorePendingRequestsFromStorage(),t.setupBeforeUnloadListener(),t.initConfig.autoTrackPageDurationInterval&&t.startPageDurationTimer()},t.preset=function(e){if(e instanceof Object){if(void 0!==e.pageKey)if(null===e.pageKey||""===e.pageKey){t.useCustomPageKey=!1;var n=window.location.pathname;t.pageKey=n.replace(/\//g,"_").substring(1)}else t.pageKey=e.pageKey,t.useCustomPageKey=!0;t.each(e,(function(e,n){if("pageKey"!==n&&t.initConfig.hasOwnProperty(n)){var r=t.validateConfigParam(String(n),e);r.valid?t.initConfig[n]=e:t.printLog("配置参数验证失败: "+String(n)+" = "+e+", 原因: "+r.message)}}))}/^(((ht|f)tps?):\/\/)?[\w-]+(\.[\w-]+)+([\w.,@?^=%&:/~+#-\(\)]*[\w@?^=%&/~+#-\(\)])?$/.test(t.initConfig.serverUrl)||(t.printLog("当前 server_url 为空或不正确,只在控制台打印日志,network 中不会发数据,请配置正确的 server_url!"),t.initConfig.showLog=!0),t.initConfig.autoTrack||t.initConfig.trackPartKeyClick?t.listener():t.unlistener(),t.initConfig.autoTrackPageDurationInterval?t.startPageDurationTimer():t.stopPageDurationTimer()},t.validateConfigParam=function(t,n){switch(t){case"sampleRate":if("number"!=typeof n||n<0||n>1)return{valid:!1,message:"sampleRate 必须是 0-1 之间的数字"};break;case"sendTimeout":if("number"!=typeof n||n<=0)return{valid:!1,message:"sendTimeout 必须是大于 0 的数字"};break;case"batchInterval":if("number"!=typeof n||n<=0)return{valid:!1,message:"batchInterval 必须是大于 0 的数字"};break;case"batchMaxSize":if("number"!=typeof n||n<=0||!Number.isInteger(n))return{valid:!1,message:"batchMaxSize 必须是大于 0 的整数"};break;case"pendingRequestsMaxSize":if("number"!=typeof n||n<=0||!Number.isInteger(n))return{valid:!1,message:"pendingRequestsMaxSize 必须是大于 0 的整数"};break;case"pageDurationInterval":if("number"!=typeof n||n<=0)return{valid:!1,message:"pageDurationInterval 必须是大于 0 的数字"};break;case"sendMethod":if("string"!=typeof n||!["auto","xhr","beacon"].includes(n))return{valid:!1,message:"sendMethod 必须是 auto、xhr 或 beacon"};break;case"showLog":case"autoTrack":case"isTrackSinglePage":case"batchSend":case"trackPartKeyClick":case"autoTrackPageDurationInterval":if("boolean"!=typeof n)return{valid:!1,message:t+" 必须是布尔值"};break;case"business":case"header":if(null!==n&&"object"!==e(n))return{valid:!1,message:t+" 必须是对象或 null"};break;case"contentType":if("application/json"!==n&&"application/x-www-form-urlencoded"!==n)return{valid:!1,message:"contentType 必须是 application/json 或 application/x-www-form-urlencoded"};break;case"platform":if("string"!=typeof n)return{valid:!1,message:"platform 必须是字符串"}}return{valid:!0}},t.login=function(e){t.isObject(e)&&(t.userInfo=e)},t.getDeviceId=function(){if(t.deviceId)return t.deviceId;var e=t.getCookie("device_id")||t.getLocalStorage("device_id");if(e)return t.deviceId=e,t.deviceId;var n=t.collectFingerprint(),r=t.hashFingerprint(n);return t.setCookie("device_id",r,730),t.setLocalStorage("device_id",r),t.deviceId=r,t.deviceId},t.resetDeviceId=function(){return document.cookie="device_id=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;",localStorage.removeItem("device_id"),t.deviceId="",t.getDeviceId()},t.track=function(e){var n=e.desc,r=e.pageKey,i=e.partkey,a=e.business,o=e.header,s=t.getParams({desc:n,event:"CustomTrack",itemKey:t.getItemKey(i,r),privateParamMap:{business:a}});return t.sendData(s,o)},t.listener=function(){t.unlistener(),t.initConfig.autoTrack&&(t.initConfig.isTrackSinglePage&&(t.rewriteHistory(),t.addSinglePageEvent(t.onPageViewCallback)),t.each(["load","beforeunload"],(function(e){t.addEventListener(window,e,t.onPageViewCallback)}))),(t.initConfig.autoTrack||t.initConfig.trackPartKeyClick)&&t.addEventListener(window,"click",t.onClickCallback)},t.unlistener=function(){if(t.initConfig.isTrackSinglePage){var e=window.history.pushState?"popstate":"hashchange";t.each(["pushState","replaceState",e],(function(e){t.removeEventListener(window,e,t.onPageViewCallback)}))}t.each(["load","beforeunload"],(function(e){t.removeEventListener(window,e,t.onPageViewCallback)})),t.removeEventListener(window,"click",t.onClickCallback),t.clearBatchTimer(),t.stopPageDurationTimer()},t.clearBatchTimer=function(){null!==t.batchTimer&&(clearTimeout(t.batchTimer),t.batchTimer=null)},t.clearBatchQueue=function(){t.setLocalStorage(t.BATCH_QUEUE_STORAGE_KEY,"[]"),t.initConfig.showLog&&t.printLog("批量队列已清空")},t.getBatchQueueFromStorage=function(){try{var e=t.getLocalStorage(t.BATCH_QUEUE_STORAGE_KEY);if(e){var n=JSON.parse(e);if(Array.isArray(n))return n}}catch(e){t.printLog("读取批量队列失败: "+e),t.setLocalStorage(t.BATCH_QUEUE_STORAGE_KEY,"[]")}return[]},t.saveBatchQueueToStorage=function(e){try{var n=JSON.stringify(e);if(n.length>t.MAX_STORAGE_SIZE){var r=Math.floor(.8*e.length),i=e.slice(-r);t.printLog("队列过大,已截断保留最新 "+r+" 条数据(限制: "+t.MAX_STORAGE_SIZE/1024/1024+"MB)"),t.setLocalStorage(t.BATCH_QUEUE_STORAGE_KEY,JSON.stringify(i))}else t.setLocalStorage(t.BATCH_QUEUE_STORAGE_KEY,n)}catch(e){t.printLog("保存批量队列到 LocalStorage 失败: "+e)}},t.getPendingRequestsFromStorage=function(){try{var e=t.getLocalStorage(t.PENDING_REQUESTS_STORAGE_KEY);if(e){var n=JSON.parse(e);if(Array.isArray(n))return n}}catch(e){t.printLog("读取待发送请求失败: "+e),t.setLocalStorage(t.PENDING_REQUESTS_STORAGE_KEY,"[]")}return[]},t.savePendingRequestsToStorage=function(e){try{t.setLocalStorage(t.PENDING_REQUESTS_STORAGE_KEY,JSON.stringify(e))}catch(e){t.printLog("保存待发送请求到 LocalStorage 失败: "+e)}},t.setPageKey=function(e,n){if(void 0===n&&(n=!1),null===e||""===e){t.useCustomPageKey=!1;var r=window.location.pathname;t.pageKey=r.replace(/\//g,"_").substring(1),t.initConfig.showLog&&t.printLog("页面标识已恢复自动生成: "+t.pageKey)}else t.pageKey=e,t.useCustomPageKey=!n,t.initConfig.showLog&&t.printLog("页面标识已设置为: "+e+", 自动更新: "+n)},t.getPageKey=function(){return t.pageKey},t.onClickCallback=function(e){var n,r=e.target;if(null===(n=null==r?void 0:r.dataset)||void 0===n?void 0:n.partKey){var i=[e.pageX,e.pageY],a=r.id,o=r.className,s={id:a,nodeName:r.nodeName,className:o,position:i},c=t.getParams({event:"WebClick",desc:t.eventDescMap.WebClick,itemKey:t.getItemKey(r.dataset.partKey),privateParamMap:{targetEle:s,pointerType:e.pointerType,currentUrl:t.currentUrl,elementSelector:t.getDomSelector(r)||""}});t.sendData(c)}},t.onPageViewCallback=function(e){var n,r,i=t.getPendingRequestsFromStorage(),a=t.initConfig.batchSend?t.getBatchQueueFromStorage():[];(i.length>0||a.length>0)&&t.flushPendingData();var o=window.location.origin,s=t.getParams({event:"PageView",desc:t.eventDescMap.PageView,privateParamMap:{currentUrl:t.currentUrl,targetUrl:(null===(n=e.arguments)||void 0===n?void 0:n[2])?o+(null===(r=e.arguments)||void 0===r?void 0:r[2]):null}});t.currentUrl=window.location.href,t.useCustomPageKey||(t.pageKey=window.location.pathname.replace(/\//g,"_").substring(1)),t.initConfig.autoTrackPageDurationInterval&&(t.stopPageDurationTimer(),t.startPageDurationTimer()),t.sendRetained(e.type),t.sendData(s)},t.getParams=function(e){var n=e.event,r=e.desc,i=e.privateParamMap,a=void 0===i?{}:i,o=e.itemKey,s=t.initConfig.business,c=window.innerWidth,u=window.innerHeight,g=window.screen.width,l=window.screen.height,d=t.filterSensitiveData(s||{}),p=t.filterSensitiveData(t.userInfo||{}),f=t.filterSensitiveData(a||{}),h=t.filterSensitiveData(t.getQueryValue()||{}),m={currentUrl:f.currentUrl||t.currentUrl,business:Object.assign({},d,f.business||{}),pageWidth:c,pageHeight:u,screenWidth:g,screenHeight:l,sdkVersion:t.sdkVersion,systemsInfo:t.systemsInfo,urlParams:h,userInfo:p,deviceId:t.deviceId};return f.targetEle&&(m.targetEle=f.targetEle),f.targetUrl&&(m.targetUrl=f.targetUrl),f.pointerType&&(m.pointerType=f.pointerType),f.elementSelector&&(m.elementSelector=f.elementSelector),f.retainedDuration&&(m.retainedDuration=f.retainedDuration),{event:n,desc:r,itemKey:o||t.getItemKey(),requestTime:t.getTimeStamp(),privateParamMap:m}},t.shouldSample=function(){var e=t.initConfig.sampleRate;return e>=1||!(e<=0)&&Math.random()<e},t.flushBatchQueue=function(){var e=t.getBatchQueueFromStorage();if(0!==e.length){var n=t.getTimeStamp(),r=e.filter((function(e){return!e._nextRetryTime||e._nextRetryTime<=n}));if(0!==r.length){var i=e.filter((function(e){return!!e._nextRetryTime&&e._nextRetryTime>n}));t.saveBatchQueueToStorage(i),t.sendBatchData(r)}else t.initConfig.showLog&&t.printLog("批量队列中有 "+e.length+" 条数据等待重试")}},t.sendBatchData=function(e){var n=t.initConfig,r=n.serverUrl,i=n.contentType,a=n.showLog,o=n.sendMethod,s=n.header;if(a&&(t.printLog("批量发送 "+e.length+" 条数据"),e.forEach((function(e){return t.printLog(e)}))),t.shouldUseBeacon(o,void 0,s))try{var c=new Blob([JSON.stringify(e)],{type:i||"application/json"});navigator.sendBeacon(r,c)?(t.saveBatchQueueToStorage([]),a&&t.printLog("批量发送成功: "+e.length+" 条数据")):(t.printLog("批量发送失败: sendBeacon 返回 false,数据已重新加入队列"),t.retryBatchData(e))}catch(n){t.printLog("批量发送失败: "+n+",数据已重新加入队列"),t.retryBatchData(e)}else t.ajax({url:r,type:"POST",data:JSON.stringify({events:e}),contentType:i,credentials:!1,timeout:t.initConfig.sendTimeout,cors:!0,success:function(){t.saveBatchQueueToStorage([]),t.initConfig.showLog&&t.printLog("批量发送成功: "+e.length+" 条数据")},error:function(n){t.printLog("批量发送失败: "+n+",数据已重新加入队列"),t.retryBatchData(e)}})},t.retryBatchData=function(e){var n=t.getBatchQueueFromStorage(),i=function(e){return e.event+"_"+e.itemKey+"_"+e.requestTime},a=new Set(n.map(i)),o=t.getTimeStamp(),s=e.filter((function(e){var n=i(e);if(a.has(n))return!1;var r=(e._retryCount||0)+1;return r>3?(t.initConfig.showLog&&t.printLog("数据已达到最大重试次数,放弃重试: "+n),!1):(e._retryCount=r,e._nextRetryTime=o+1e3*Math.pow(2,r),a.add(n),!0)})),c=r(r([],s),n),u=2*t.initConfig.batchMaxSize,g=c.length>u?c.slice(0,u):c;t.saveBatchQueueToStorage(g),t.initConfig.showLog&&t.printLog("已将 "+s.length+" 条数据加入重试队列")},t.addToBatchQueue=function(e){var n=t.initConfig,r=n.batchInterval,i=n.batchMaxSize;if(t.shouldSample()){var a=t.getBatchQueueFromStorage();a.push(e),t.saveBatchQueueToStorage(a),a.length>=i?t.flushBatchQueue():t.batchTimer||(t.batchTimer=window.setTimeout((function(){t.flushBatchQueue(),t.batchTimer=null}),r))}else t.initConfig.showLog&&t.printLog("数据已采样跳过(批量模式)")},t.restoreBatchQueueFromStorage=function(){var e=t.getBatchQueueFromStorage();if(e.length>0){t.initConfig.showLog&&t.printLog("从 LocalStorage 恢复 "+e.length+" 条待发送数据");var n=t.initConfig.batchMaxSize;if(e.length>=n)t.flushBatchQueue();else{var r=t.initConfig.batchInterval;t.batchTimer||(t.batchTimer=window.setTimeout((function(){t.flushBatchQueue(),t.batchTimer=null}),r))}}},t.addToPendingRequests=function(e){var n=t.getPendingRequestsFromStorage();n.push(e);var r=t.initConfig.pendingRequestsMaxSize||t.DEFAULT_PENDING_REQUESTS_MAX_SIZE;if(n.length>r){var i=n.slice(-r);t.initConfig.showLog&&t.printLog("待发送请求队列已满,已移除最旧的数据(最大限制: "+r+")"),t.savePendingRequestsToStorage(i)}else t.savePendingRequestsToStorage(n)},t.restorePendingRequestsFromStorage=function(){var e=t.getPendingRequestsFromStorage();e.length>0&&t.initConfig.showLog&&t.printLog("从 LocalStorage 恢复 "+e.length+" 条待发送请求")},t.isPageUnloading=function(){return"hidden"===document.visibilityState},t.sendWithBeacon=function(e,n,r){try{var i=new Blob([JSON.stringify(e)],{type:r||"application/json"});return navigator.sendBeacon(n,i)}catch(e){return t.initConfig.showLog&&t.printLog("sendBeacon 发送失败: "+e),!1}},t.flushPendingRequests=function(){var e=t.getPendingRequestsFromStorage();if(0!==e.length){t.savePendingRequestsToStorage([]);var n=t.initConfig,r=n.serverUrl,i=n.sendTimeout,a=n.contentType,o=n.showLog,s=n.header;e.forEach((function(e){t.shouldSample()?(o&&t.printLog(e),t.ajax({header:s,url:r,type:"POST",data:JSON.stringify(e),contentType:a,credentials:!1,timeout:i,cors:!0,success:function(){o&&t.printLog("待发送请求发送成功")},error:function(e){o&&t.printLog("待发送请求发送失败(不再重试): "+e)}})):o&&t.printLog("待发送请求已采样跳过")}))}},t.setupBeforeUnloadListener=function(){t.isUnloadListenerSetup||(t.isUnloadListenerSetup=!0,document.addEventListener("visibilitychange",(function(){t.isPageUnloading()&&t.flushPendingData()})),window.addEventListener("beforeunload",(function(){t.flushPendingData()})),window.addEventListener("pagehide",(function(){t.flushPendingData()})))},t.isFlushingPendingData=!1,t.flushPendingData=function(){if(!t.isFlushingPendingData){t.stopPageDurationTimer();var e=[],n=t.getBatchQueueFromStorage();n.length>0&&e.push.apply(e,n);var r=t.getPendingRequestsFromStorage();if(r.length>0&&e.push.apply(e,r),0!==e.length){t.isFlushingPendingData=!0;try{t.initConfig.batchSend?t.setLocalStorage(t.BATCH_QUEUE_STORAGE_KEY,JSON.stringify(e)):t.setLocalStorage(t.PENDING_REQUESTS_STORAGE_KEY,JSON.stringify(e))}catch(e){t.initConfig.showLog&&t.printLog("保存待发送请求到 LocalStorage 失败: "+e)}if(navigator.sendBeacon&&t.initConfig.serverUrl)try{var i=1===e.length?e[0]:e,a=new Blob([JSON.stringify(i)],{type:t.initConfig.contentType||"application/json"});navigator.sendBeacon(t.initConfig.serverUrl,a)?(t.setLocalStorage(t.BATCH_QUEUE_STORAGE_KEY,"[]"),t.setLocalStorage(t.PENDING_REQUESTS_STORAGE_KEY,"[]"),t.initConfig.showLog&&t.printLog("页面卸载时成功发送 "+e.length+" 条数据")):t.initConfig.showLog&&t.printLog("sendBeacon 返回 false,数据已保存到 LocalStorage 等待下次恢复")}catch(e){t.initConfig.showLog&&t.printLog("页面卸载时发送数据失败: "+e+",数据已保存到 LocalStorage")}finally{t.isFlushingPendingData=!1}else t.initConfig.showLog&&t.printLog("不支持 sendBeacon,数据已保存到 LocalStorage 等待下次恢复"),t.isFlushingPendingData=!1}}},t.sendData=function(e,n){if(!t.shouldSample())return Promise.resolve({success:!0,message:"数据已采样跳过"});var r=t.initConfig,i=r.serverUrl,a=r.sendTimeout,o=r.contentType,s=r.showLog,c=r.header,u=r.batchSend,g=r.sendMethod;return s&&t.printLog(e),u?(t.addToBatchQueue(e),Promise.resolve({success:!0,message:"已添加到批量队列"})):t.shouldUseBeacon(g,n,c)?t.isPageUnloading()?t.sendWithBeacon(e,i,o)?Promise.resolve({success:!0,message:"页面卸载时发送成功"}):(t.addToPendingRequests(e),Promise.resolve({success:!0,message:"已添加到待发送队列"})):t.sendBeacon({contentType:o,url:i,data:e}).catch((function(n){return t.addToPendingRequests(e),Promise.resolve({success:!0,message:"sendBeacon 失败,已添加到待发送队列"})})):new Promise((function(r,s){if(t.isPageUnloading()&&"auto"===g&&t.isSupportBeaconSend()&&!n&&!c&&t.sendWithBeacon(e,i,o))return void r({success:!0,message:"页面卸载时使用 sendBeacon 发送成功"});t.ajax({header:n||c,url:i,type:"POST",data:JSON.stringify(e),contentType:o,credentials:!1,timeout:a,cors:!0,success:function(e){return r({success:!0,data:e})},error:function(a,u){if(t.isPageUnloading()&&"auto"===g&&t.isSupportBeaconSend()&&!n&&!c&&t.sendWithBeacon(e,i,o))return void r({success:!0,message:"XMLHttpRequest 失败,已使用 sendBeacon 发送"});s({success:!1,message:String(a),code:u})}})}))},t.shouldUseBeacon=function(e,n,r){return"xhr"!==e&&("beacon"===e?!0===t.isSupportBeaconSend():!0===t.isSupportBeaconSend()&&!n&&!r)},t.sendRetained=function(e){var r=t.getParams({event:"PageRetained",desc:t.eventDescMap.PageRetained});if(["beforeunload","pushState","replaceState","hashchange","popstate"].indexOf(e)>=0){var i=t.getCookie("retainedStartTime"),a=i?+i:t.getTimeStamp(),o=n(n({},r),{privateParamMap:n(n({},r.privateParamMap),{retainedDuration:Math.max(r.requestTime-a,0)})});t.sendData(o),t.setCookie("retainedStartTime",t.getTimeStamp())}},t.trackPageDuration=function(e,n,r){var i;if(void 0===r&&(r=!0),null!=e)i=Math.max(e,0);else{var a=t.getCookie("retainedStartTime"),o=a?+a:t.getTimeStamp(),s=t.getTimeStamp();i=Math.max(s-o,0)}var c=(null==n?void 0:n.desc)||t.eventDescMap.PageRetained,u=(null==n?void 0:n.pageKey)||t.pageKey,g=(null==n?void 0:n.business)||{},l=null==n?void 0:n.header,d=t.getParams({event:"PageRetained",desc:c,itemKey:t.getItemKey(void 0,u),privateParamMap:{business:g,retainedDuration:i}}),p=t.sendData(d,l);return r&&t.setCookie("retainedStartTime",t.getTimeStamp()),p},t.startPageDurationTimer=function(){t.stopPageDurationTimer();var e=t.initConfig.pageDurationInterval||3e4;e<=0?t.initConfig.showLog&&t.printLog("定时上报间隔时间无效,已禁用定时上报"):(t.pageDurationTimer=window.setInterval((function(){"visible"===document.visibilityState&&t.trackPageDuration(e,{desc:"定时上报页面停留时长",business:{reportType:"interval",interval:e}},!0).catch((function(e){t.initConfig.showLog&&t.printLog("定时上报页面停留时长失败: "+e)}))}),e),t.initConfig.showLog&&t.printLog("定时上报页面停留时长已启动,间隔: "+e+"ms"))},t.stopPageDurationTimer=function(){null!==t.pageDurationTimer&&(clearInterval(t.pageDurationTimer),t.pageDurationTimer=null,t.initConfig.showLog&&t.printLog("定时上报页面停留时长已停止"))},t.getItemKey=function(e,n){return[t.initConfig.appKey,(n||t.pageKey).toString(),e?e.toString():void 0].filter((function(e){return!!e})).reduce((function(e,t){return e+(e.length?".":"")+t}),"")},t.sdkVersion="1.2.3",t.initConfig={appKey:"",platform:void 0,showLog:!1,serverUrl:"",autoTrack:!1,sendTimeout:3e3,isTrackSinglePage:!1,contentType:"application/json",business:{},header:void 0,sampleRate:1,batchSend:!1,batchInterval:5e3,batchMaxSize:10,trackPartKeyClick:!1,pendingRequestsMaxSize:50,autoTrackPageDurationInterval:!1,pageDurationInterval:3e4,sendMethod:"auto"},t.systemsInfo={},t}return function(e,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=e}t(e,n),e.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}(a,i),a.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)}))},a}(function(){function t(){var t=this;this.getSystemsInfo=function(e){var t=navigator.userAgent,n="other",r=[],i={language:navigator.language},a=t.match(/MicroMessenger\/([\d\.]+)/i),o=a&&a[1]?a[1]:null,s=t.match(/(ipod).*\s([\d_]+)/i),c=t.match(/(ipad).*\s([\d_]+)/i),u=t.match(/(iphone)\sos\s([\d_]+)/i),g=t.match(/(android)\s([\d\.]+)/i),l=t.match(/(Windows NT)\s([\d\.]+)/i),d=t.match(/(Mac OS X)\s([\d_]+)/i);r=[],g?(r.push("Android "+g[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"):l?(r.push("Windows "+l[2].replace(/_/g,".")),n="pc"):d&&(r.push("Mac, MacOS "+d[2].replace(/_/g,".")),n="pc"),o&&r.push("WeChat "+o),i.client=r.length?r.join(", "):"Unknown",i.platform=e||n;var p=t.toLowerCase().match(/ nettype\/([^ ]+)/g);return p&&p[0]&&(r=[(p=p[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(e,n,r){if(null==e)return!1;if(t.nativeForEach&&e.forEach===t.nativeForEach)e.forEach(n,r);else if(t.isArray(e)&&e.length===+e.length){for(var i=0,a=e.length;i<a;i++)if(i in e&&n.call(r,e[i],i,e)===t.breaker)return!1}else for(var o in e)if(t.hasOwnProperty.call(e,o)&&n.call(r,e[o],o,e)===t.breaker)return!1;return!0},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(e){var n=e.parentNode&&9==e.parentNode.nodeType?-1:t.getDomIndex(e);return e.getAttribute&&e.getAttribute("id")&&/^[A-Za-z][-A-Za-z0-9_:.]*$/.test(e.getAttribute("id"))?"#"+e.getAttribute("id"):e.tagName.toLowerCase()+(~n?":nth-of-type("+(n+1)+")":"")},this.getDomSelector=function(e,n){if(!e||!e.parentNode||!e.parentNode.children)return!1;n=n&&n.join?n:[];var r=e.nodeName.toLowerCase();return e&&"body"!==r&&1==e.nodeType?(n.unshift(t.selector(e)),e.getAttribute&&e.getAttribute("id")&&/^[A-Za-z][-A-Za-z0-9_:.]*$/.test(e.getAttribute("id"))?n.join(" > "):t.getDomSelector(e.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 a=this.getMainHost();if(r=a?"; domain="+a:"",0!==n){var o=new Date;"s"===String(n).slice(-1)?o.setTime(o.getTime()+1e3*Number(String(n).slice(0,-1))):o.setTime(o.getTime()+24*n*60*60*1e3),i="; expires="+o.toUTCString()}function s(e){return e||!1}var c="",u="",g="";e&&(c=s(e)),t&&(u=s(t)),r&&(g=s(r)),c&&u&&(document.cookie=c+"="+encodeURIComponent(u)+i+"; path=/"+g)},this.getLocalStorage=function(e){try{return localStorage.getItem(e)}catch(e){return null}},this.setLocalStorage=function(e,t){try{localStorage.setItem(e,t)}catch(e){}},this.removeCookie=function(e){t.setCookie(e,"",-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 e=t.getCookie("distinctId");return e||(e=t.uuid(),t.setCookie("distinctId",e),e)},this.filterSensitiveData=function(e,n){if(void 0===n&&(n=["password","token","secret","key"]),!t.isObject(e))return e;var r={};return t.each(e,(function(e,i){n.some((function(e){return"string"==typeof i&&i.toLowerCase().includes(e.toLowerCase())}))?r[i]="***":t.isObject(e)?r[i]=t.filterSensitiveData(e,n):r[i]=e})),r},this.xssFilter=function(e){return e?"string"!=typeof e?e.toString():e.replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#x27;").replace(/\//g,"&#x2F;"):""},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 Object.keys(t).length>0?t:null},this.ajax=function(n){function r(t){if(!t)return{};if("string"==typeof t)try{return JSON.parse(t)}catch(e){return{}}return"object"===e(t)?t:{}}n.timeout=n.timeout||3e4,n.credentials=void 0===n.credentials||n.credentials;var i=t.xhr(n.cors);if(!i)return!1;n.type||(n.type=n.data?"POST":"GET");var a,o=n.success,s=n.error;n.success=function(e){o&&o(e),a&&(clearTimeout(a),a=null)},n.error=function(e,t){s&&s(e,t),a&&(clearTimeout(a),a=null)},a=window.setTimeout((function(){!function(){try{t.isObject(i)&&i.abort&&i.abort()}catch(e){t.printLog(e)}a&&(clearTimeout(a),a=null,n.error&&n.error(),i.onreadystatechange=null,i.onload=null,i.onerror=null)}()}),n.timeout),i.onreadystatechange=function(){try{4==i.readyState&&(i.status>=200&&i.status<300||304==i.status?n.success&&n.success(r(i.responseText)):n.error&&n.error(r(i.responseText),i.status),i.onreadystatechange=null,i.onload=null)}catch(e){i.onreadystatechange=null,i.onload=null}},i.open(n.type||"GET",n.url,!0);try{n.credentials&&(i.withCredentials=!0),t.isObject(n.header)&&t.each(n.header,(function(e,t){i.setRequestHeader&&i.setRequestHeader(t,e)})),n.data&&(n.cors||i.setRequestHeader&&i.setRequestHeader("X-Requested-With","XMLHttpRequest"),"application/json"===n.contentType?i.setRequestHeader&&i.setRequestHeader("Content-type","application/json; charset=UTF-8"):i.setRequestHeader&&i.setRequestHeader("Content-type","application/x-www-form-urlencoded"))}catch(e){t.printLog(e)}i.send(n.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 n=!1;if("object"!==("undefined"==typeof navigator?"undefined":e(navigator))||"function"!=typeof navigator.sendBeacon)return n;var r=t.getUA(),i=navigator.userAgent.toLowerCase();if(/Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent)){var a=(i.match(/os [\d._]*/gi)+"").replace(/[^0-9|_.]/gi,"").replace(/_/gi,".").split(".");void 0===r.safari&&(r.safari=Number(a[0])),a[0]&&+a[0]<13?(r.chrome>41||r.firefox>30||r.opera>25||r.safari>12)&&(n=!0):(r.chrome>41||r.firefox>30||r.opera>25||r.safari>11.3)&&(n=!0)}else(r.chrome>38||r.edge>13||r.firefox>30||r.opera>25||r.safari>11)&&(n=!0);return n},this.throttle=function(e,t){var n=null,r=0;return function(){for(var i=[],a=0;a<arguments.length;a++)i[a]=arguments[a];var o=Date.now(),s=t-(o-r);s<=0||s>t?(n&&(clearTimeout(n),n=null),r=o,e.apply(void 0,i)):n||(n=window.setTimeout((function(){r=Date.now(),n=null,e.apply(void 0,i)}),s))}},this.debounce=function(e,t){var n=null;return function(){for(var r=[],i=0;i<arguments.length;i++)r[i]=arguments[i];n&&clearTimeout(n),n=window.setTimeout((function(){e.apply(void 0,r)}),t)}},this.sendBeacon=function(e){if(!0===t.isSupportBeaconSend()){var n={type:e.contentType},r=new Blob([JSON.stringify(e.data)],n);return navigator.sendBeacon(e.url,r)?Promise.resolve({success:!0,message:"发送成功"}):Promise.reject({success:!1,message:"sendBeacon返回false"})}return Promise.reject({success:!1,message:"不支持sendBeacon,发送失败!"})},this.getDeviceId=function(){var e=t.getCookie("device_id")||t.getLocalStorage("device_id");if(e)return e;var n=t.collectFingerprint(),r=t.hashFingerprint(n);return t.setCookie("device_id",r,730),t.setLocalStorage("device_id",r),r},this.collectFingerprint=function(){var e={};return e.userAgent=navigator.userAgent,e.screenWidth=screen.width,e.screenHeight=screen.height,e.colorDepth=screen.colorDepth,e.pixelDepth=screen.pixelDepth,e.timezone=Intl.DateTimeFormat().resolvedOptions().timeZone,e.timezoneOffset=(new Date).getTimezoneOffset(),e.language=navigator.language,e.languages=Array.from(navigator.languages),e.platform=navigator.platform,e.webgl=t.getWebGLFingerprint(),e.canvas=t.getCanvasFingerprint(),e.audio=t.getAudioFingerprint(),e.fonts=t.getFontFingerprint(),e.plugins=t.getPluginsFingerprint(),e.localStorage=t.hasLocalStorage(),e.sessionStorage=t.hasSessionStorage(),e.indexedDB=t.hasIndexedDB(),e.hardwareConcurrency=navigator.hardwareConcurrency,e.deviceMemory=navigator.deviceMemory,e.maxTouchPoints=navigator.maxTouchPoints,e.connection=t.getConnectionFingerprint(),e},this.getWebGLFingerprint=function(){try{var e=document.createElement("canvas"),t=e.getContext("webgl")||e.getContext("experimental-webgl");if(!t)return"not-supported";var n=t.getExtension("WEBGL_debug_renderer_info");return(n?t.getParameter(n.UNMASKED_VENDOR_WEBGL):"unknown")+"|"+(n?t.getParameter(n.UNMASKED_RENDERER_WEBGL):"unknown")}catch(e){return"error"}},this.getCanvasFingerprint=function(){try{var e=document.createElement("canvas");e.width=200,e.height=50;var t=e.getContext("2d");return t?(t.textBaseline="top",t.font="14px Arial",t.fillStyle="#f60",t.fillRect(125,1,62,20),t.fillStyle="#069",t.fillText("Canvas fingerprint",2,15),t.fillStyle="rgba(102, 204, 0, 0.7)",t.fillText("Canvas fingerprint",4,17),e.toDataURL().slice(-50)):"not-supported"}catch(e){return"error"}},this.getAudioFingerprint=function(){try{var e=window.AudioContext||window.webkitAudioContext;if(!e)return"not-supported";var t=new e,n=String(t.sampleRate||0);return t.close(),n}catch(e){return"error"}},this.getFontFingerprint=function(){try{var e=["monospace","sans-serif","serif"],t="mmmmmmmmmmlli",n=document.createElement("canvas").getContext("2d");if(!n)return"not-supported";var r=[],i={};return e.forEach((function(e){n.font="72px "+e,i[e]=n.measureText(t).width})),["Arial","Arial Black","Comic Sans MS","Courier New","Georgia","Helvetica","Impact","Times New Roman","Trebuchet MS","Verdana"].forEach((function(a){var o=!1;e.forEach((function(e){n.font="72px '"+a+"', "+e,n.measureText(t).width!==i[e]&&(o=!0)})),o&&r.push(a)})),r.join(",")}catch(e){return"error"}},this.getPluginsFingerprint=function(){try{var e=[];if(navigator.plugins)for(var t=0;t<navigator.plugins.length;t++){var n=navigator.plugins[t];n&&e.push(n.name+"|"+n.description+"|"+n.filename)}return e.join(";")}catch(e){return"error"}},this.hasLocalStorage=function(){try{var e="__test__";return localStorage.setItem(e,e),localStorage.removeItem(e),!0}catch(e){return!1}},this.hasSessionStorage=function(){try{var e="__test__";return sessionStorage.setItem(e,e),sessionStorage.removeItem(e),!0}catch(e){return!1}},this.hasIndexedDB=function(){return"indexedDB"in window&&null!==indexedDB},this.getConnectionFingerprint=function(){try{var e=navigator.connection||navigator.mozConnection||navigator.webkitConnection;return e?e.effectiveType||"unknown":"not-supported"}catch(e){return"error"}},this.hashFingerprint=function(e){for(var t=JSON.stringify(e,Object.keys(e).sort()),n=5381,r=52711,i=0;i<t.length;i++){var a=t.charCodeAt(i);n=(n<<5)+n+a,r=(r<<5)+r+a}return"fp_"+(n>>>0).toString(16).padStart(8,"0")+(r>>>0).toString(16).padStart(8,"0")}}return t.prototype.printLog=function(){for(var t=[],n=0;n<arguments.length;n++)t[n]=arguments[n];if(this.isObject(t[0])&&(t[0]=this.formatJsonString(t[0])),"object"===("undefined"==typeof console?"undefined":e(console))&&console.log)try{return console.log.apply(console,t)}catch(e){console.log(t[0])}},t.prototype.isObject=function(e){return null!=e&&"[object Object]"==toString.call(e)},t.prototype.isUndefined=function(e){return void 0===e},t.prototype.isString=function(e){return"[object String]"==toString.call(e)},t.prototype.isDate=function(e){return"[object Date]"==toString.call(e)},t.prototype.isBoolean=function(e){return"[object Boolean]"==toString.call(e)},t.prototype.isNumber=function(e){return"[object Number]"==toString.call(e)&&/[\d\.]+/.test(String(e))},t.prototype.isElement=function(e){return!(!e||1!==e.nodeType)},t.prototype.isFunction=function(e){if(!e)return!1;var t=toString.call(e);return"[object Function]"==t||"[object AsyncFunction]"==t},t.prototype.isJSONString=function(e){if(!this.isString(e))return!1;try{JSON.parse(e)}catch(e){return!1}return!0},t.prototype._decodeURIComponent=function(e){var t=e;try{t=decodeURIComponent(e)}catch(n){t=e}return t},t.prototype.getMainHost=function(){var e="mh_"+Math.random(),t=new RegExp("(^|;)\\s*"+e+"=12345"),n=new Date(0),r=document.domain,i=r.split("."),a=[];for(a.unshift(i.pop());i.length;){a.unshift(i.pop());var o=a.join("."),s=e+"=12345;domain=."+o;if(document.cookie=s,t.test(document.cookie))return document.cookie=s+";expires="+n,o}return r},t}()))}));
@@ -8,17 +8,16 @@
8
8
  * partkey:控件/自定义事件唯一标识,可通过接口获取或自定义
9
9
  */
10
10
  import Tools from "./tools";
11
- import { EventParams, InitParams, SystemsInfoTypes, TrackParams, PresetParams, TrackingPostParams, JsonProps, EventTypes, GetParamsOptions, TrackingResponse } from "./type";
11
+ import { EventParams, InitParams, SystemsInfoTypes, TrackParams, PresetParams, TrackingPostParams, JsonProps, EventTypes, GetParamsOptions, TrackingResponse, TrackPageDurationOptions } from "./type";
12
12
  declare class WebTracking extends Tools {
13
13
  initConfig: InitParams;
14
14
  sdkVersion: string;
15
15
  systemsInfo: SystemsInfoTypes;
16
- private batchQueue;
17
16
  private batchTimer;
18
17
  private readonly BATCH_QUEUE_STORAGE_KEY;
19
18
  private useCustomPageKey;
20
- private pendingRequests;
21
19
  private isUnloadListenerSetup;
20
+ private pageDurationTimer;
22
21
  private readonly PENDING_REQUESTS_STORAGE_KEY;
23
22
  private readonly DEFAULT_PENDING_REQUESTS_MAX_SIZE;
24
23
  private readonly MAX_STORAGE_SIZE;
@@ -34,11 +33,17 @@ declare class WebTracking extends Tools {
34
33
  */
35
34
  init: (initParams: InitParams) => void;
36
35
  /**
37
- * TODO: 需要判断有哪些不能被预制的参数
38
36
  * @description 预置参数
39
37
  * @param {object} PresetParams [预置参数]
40
38
  */
41
39
  preset: (presetParams: PresetParams) => void;
40
+ /**
41
+ * @description 验证配置参数
42
+ * @param key 参数名
43
+ * @param value 参数值
44
+ * @returns 验证结果
45
+ */
46
+ private validateConfigParam;
42
47
  /**
43
48
  * 用户登录
44
49
  */
@@ -76,6 +81,26 @@ declare class WebTracking extends Tools {
76
81
  * @description 清空批量队列(包括 LocalStorage 中的数据)
77
82
  */
78
83
  clearBatchQueue: () => void;
84
+ /**
85
+ * @description 从 LocalStorage 获取批量队列
86
+ * @returns 批量队列数组
87
+ */
88
+ private getBatchQueueFromStorage;
89
+ /**
90
+ * @description 保存批量队列到 LocalStorage
91
+ * @param queue 批量队列数组
92
+ */
93
+ private saveBatchQueueToStorage;
94
+ /**
95
+ * @description 从 LocalStorage 获取待发送请求队列
96
+ * @returns 待发送请求队列数组
97
+ */
98
+ private getPendingRequestsFromStorage;
99
+ /**
100
+ * @description 保存待发送请求队列到 LocalStorage
101
+ * @param requests 待发送请求队列数组
102
+ */
103
+ private savePendingRequestsToStorage;
79
104
  /**
80
105
  * @description 设置自定义页面唯一标识
81
106
  * @param pageKey 页面唯一标识,如果传入 null 或空字符串,则恢复自动生成
@@ -87,7 +112,7 @@ declare class WebTracking extends Tools {
87
112
  * @returns 当前页面唯一标识
88
113
  */
89
114
  getPageKey: () => string;
90
- protected onClickCallback: (e: MouseEvent) => Promise<TrackingResponse>;
115
+ protected onClickCallback: (e: MouseEvent) => void;
91
116
  /**
92
117
  * @description 添加单页面监听事件
93
118
  * @param callback
@@ -112,6 +137,11 @@ declare class WebTracking extends Tools {
112
137
  * @param data 批量数据
113
138
  */
114
139
  private sendBatchData;
140
+ /**
141
+ * @description 批量数据重试逻辑
142
+ * @param data 批量数据
143
+ */
144
+ private retryBatchData;
115
145
  /**
116
146
  * 添加到批量队列
117
147
  * @param params 数据参数
@@ -145,17 +175,14 @@ declare class WebTracking extends Tools {
145
175
  private sendWithBeacon;
146
176
  /**
147
177
  * 刷新待发送的单个请求(正常情况下的发送)
148
- * 注意:这个方法会直接发送,不会再次添加到 pendingRequests,避免循环
178
+ * 注意:这个方法会直接使用 ajax 发送,避免通过 sendData 导致重复
149
179
  */
150
180
  private flushPendingRequests;
151
- /**
152
- * 保存批量队列到 LocalStorage
153
- */
154
- private saveBatchQueueToStorage;
155
181
  /**
156
182
  * 设置页面卸载监听器,确保数据发送
157
183
  */
158
184
  private setupBeforeUnloadListener;
185
+ private isFlushingPendingData;
159
186
  /**
160
187
  * 刷新待发送数据(在页面卸载/跳转时调用)
161
188
  */
@@ -164,11 +191,35 @@ declare class WebTracking extends Tools {
164
191
  * 发送数据通用函数
165
192
  */
166
193
  sendData: (params: TrackingPostParams, header?: JsonProps) => Promise<TrackingResponse>;
194
+ /**
195
+ * @description 判断是否应该使用 sendBeacon
196
+ * @param sendMethod 配置的发送方式
197
+ * @param header 自定义 header
198
+ * @param initHeader 初始化配置的 header
199
+ * @returns 是否使用 sendBeacon
200
+ */
201
+ private shouldUseBeacon;
167
202
  /**
168
203
  * @description 留存时长上报
169
204
  * @param type
170
205
  */
171
206
  sendRetained: (type: string) => void;
207
+ /**
208
+ * @description 用户主动上报页面停留时长
209
+ * @param duration 自定义停留时长(毫秒),如果不传则自动计算从页面加载(或上次调用)到当前的时长
210
+ * @param options 可选参数,包括自定义描述、业务参数等
211
+ * @param resetStartTime 是否重置起始时间,默认 true(手动上报后重置,定时上报不重置)
212
+ * @returns Promise<TrackingResponse> 上报结果
213
+ */
214
+ trackPageDuration: (duration?: number, options?: TrackPageDurationOptions, resetStartTime?: boolean) => Promise<TrackingResponse>;
215
+ /**
216
+ * @description 启动定时上报页面停留时长的定时器
217
+ */
218
+ private startPageDurationTimer;
219
+ /**
220
+ * @description 停止定时上报页面停留时长的定时器
221
+ */
222
+ private stopPageDurationTimer;
172
223
  /**
173
224
  * @description 获取 itemKey
174
225
  * @param {[string]} partkey [控件/自定义事件的唯一标识]
@@ -162,11 +162,13 @@ export default class WebTrackingTools {
162
162
  private getWebGLFingerprint;
163
163
  /**
164
164
  * 获取Canvas指纹
165
+ * 注意:使用固定的尺寸和绘制参数,确保在不同时间生成一致的指纹
165
166
  * @returns Canvas指纹字符串
166
167
  */
167
168
  private getCanvasFingerprint;
168
169
  /**
169
170
  * 获取音频上下文指纹
171
+ * 注意:只使用稳定的 sampleRate,不使用 currentTime(会随时间变化)
170
172
  * @returns 音频指纹字符串
171
173
  */
172
174
  private getAudioFingerprint;
@@ -117,11 +117,26 @@ export interface PresetParams {
117
117
  * @default 50
118
118
  */
119
119
  pendingRequestsMaxSize?: number;
120
+ /**
121
+ * @description 数据发送方式:auto(自动选择)、xhr(XMLHttpRequest)、beacon(sendBeacon)
122
+ * @default "auto"
123
+ */
124
+ sendMethod?: "auto" | "xhr" | "beacon";
120
125
  /**
121
126
  * @description 自定义页面唯一标识,如果不传则自动从路由获取
122
127
  * @default 自动从 window.location.pathname 获取
123
128
  */
124
129
  pageKey?: string;
130
+ /**
131
+ * @description 是否定时上报页面停留时长
132
+ * @default false
133
+ */
134
+ autoTrackPageDurationInterval?: boolean;
135
+ /**
136
+ * @description 定时上报页面停留时长的间隔时间(毫秒)
137
+ * @default 30000 (30秒)
138
+ */
139
+ pageDurationInterval?: number;
125
140
  }
126
141
  export interface InitParams extends PresetParams {
127
142
  /**
@@ -179,6 +194,30 @@ export interface TrackParams {
179
194
  */
180
195
  header?: JsonProps;
181
196
  }
197
+ /**
198
+ * @description 页面停留时长上报参数
199
+ */
200
+ export interface TrackPageDurationOptions {
201
+ /**
202
+ * @description 自定义描述
203
+ * @default "Web 页面浏览时长"
204
+ */
205
+ desc?: string;
206
+ /**
207
+ * @description 自定义业务参数
208
+ * @default {}
209
+ */
210
+ business?: JsonProps;
211
+ /**
212
+ * @description 自定义页面唯一标识
213
+ */
214
+ pageKey?: string;
215
+ /**
216
+ * @description 请求头
217
+ * @default {}
218
+ */
219
+ header?: JsonProps;
220
+ }
182
221
  export interface TargetEleProps {
183
222
  /**
184
223
  * @description dom节点名称
@@ -287,6 +326,14 @@ export interface TrackingPostParams {
287
326
  * @description 私有参数
288
327
  */
289
328
  privateParamMap?: PrivateParamProps;
329
+ /**
330
+ * @description 重试次数(内部使用)
331
+ */
332
+ _retryCount?: number;
333
+ /**
334
+ * @description 下次重试时间戳(内部使用)
335
+ */
336
+ _nextRetryTime?: number;
290
337
  }
291
338
  /**
292
339
  * @description 获取参数选项接口
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fle-sdk/event-tracking-web",
3
- "version": "1.2.2",
3
+ "version": "1.2.3",
4
4
  "description": "event tracking in web",
5
5
  "author": "飞象前端团队",
6
6
  "license": "ISC",
@@ -37,10 +37,10 @@
37
37
  "@rollup/plugin-babel": "^5.3.0",
38
38
  "@rollup/plugin-commonjs": "^19.0.0",
39
39
  "@rollup/plugin-node-resolve": "^13.0.0",
40
+ "@rollup/plugin-typescript": "^11.1.6",
40
41
  "@snowpack/plugin-dotenv": "^2.1.0",
41
42
  "@snowpack/plugin-postcss": "^1.4.1",
42
43
  "@snowpack/plugin-react-refresh": "^2.5.0",
43
- "@snowpack/web-test-runner-plugin": "^0.2.2",
44
44
  "@types/react": "^17.0.0",
45
45
  "@types/react-dom": "^17.0.0",
46
46
  "@types/react-router-dom": "^5.3.3",
@@ -56,7 +56,6 @@
56
56
  "rollup-plugin-node-polyfills": "^0.2.1",
57
57
  "rollup-plugin-sourcemaps": "^0.6.3",
58
58
  "rollup-plugin-terser": "^7.0.2",
59
- "@rollup/plugin-typescript": "^11.1.6",
60
59
  "snowpack": "^3.3.7",
61
60
  "snowpack-plugin-less": "^1.0.7",
62
61
  "typescript": "^4.3.4"