├── .babelrc ├── .eslintignore ├── .eslintrc.js ├── .github └── workflows │ └── npm-publish.yml ├── .gitignore ├── LICENSE ├── README.md ├── demo ├── index.html ├── javascript │ └── initSdk.js ├── next.html ├── sdk │ ├── AnalysysAgent_Encrypt.amd.min.js │ ├── AnalysysAgent_Encrypt.min.js │ ├── AnalysysAgent_ExposurePoint.amd.min.js │ ├── AnalysysAgent_ExposurePoint.min.js │ ├── AnalysysAgent_GBK.amd.min.js │ ├── AnalysysAgent_GBK.min.js │ ├── AnalysysAgent_JS_SDK.amd.min.js │ ├── AnalysysAgent_JS_SDK.min.js │ ├── AnalysysAgent_JS_SDK_HEATMAP.min.js │ ├── AnalysysAgent_JS_SDK_VISUAL.min.js │ ├── AnalysysAgent_MPAAS.amd.min.js │ ├── AnalysysAgent_MPAAS.min.js │ ├── AnalysysAgent_PageViewStayTime.amd.min.js │ └── AnalysysAgent_PageViewStayTime.min.js └── style │ ├── console.js │ ├── index.js │ └── plugIn │ ├── JSON.js │ └── bootstrap │ ├── css │ ├── bootstrap-theme.css │ ├── bootstrap-theme.css.map │ ├── bootstrap-theme.min.css │ ├── bootstrap.css │ ├── bootstrap.css.map │ └── bootstrap.min.css │ ├── fonts │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.svg │ ├── glyphicons-halflings-regular.ttf │ ├── glyphicons-halflings-regular.woff │ └── glyphicons-halflings-regular.woff2 │ └── js │ ├── bootstrap.js │ ├── bootstrap.min.js │ ├── jquery.min.js │ └── npm.js ├── package.json ├── rollup.config.js ├── rollup.module.config.js ├── rollup.plugins.config.js ├── sdk ├── AnalysysAgent_Encrypt.amd.min.js ├── AnalysysAgent_Encrypt.es6.min.js ├── AnalysysAgent_Encrypt.min.js ├── AnalysysAgent_ExposurePoint.amd.min.js ├── AnalysysAgent_ExposurePoint.es6.min.js ├── AnalysysAgent_ExposurePoint.min.js ├── AnalysysAgent_GBK.amd.min.js ├── AnalysysAgent_GBK.es6.min.js ├── AnalysysAgent_GBK.min.js ├── AnalysysAgent_JS_SDK.amd.min.js ├── AnalysysAgent_JS_SDK.es6.min.js ├── AnalysysAgent_JS_SDK.min.js ├── AnalysysAgent_JS_SDK_HEATMAP.min.js ├── AnalysysAgent_JS_SDK_VISUAL.min.js ├── AnalysysAgent_MPAAS.amd.min.js ├── AnalysysAgent_MPAAS.es6.min.js ├── AnalysysAgent_MPAAS.min.js ├── AnalysysAgent_PageViewStayTime.amd.min.js ├── AnalysysAgent_PageViewStayTime.es6.min.js ├── AnalysysAgent_PageViewStayTime.min.js └── md5.txt ├── src ├── API │ ├── index.js │ └── template │ │ ├── alias.js │ │ ├── clearSuperProperties.js │ │ ├── freeApi.js │ │ ├── getDistinctId.js │ │ ├── getPresetProperties.js │ │ ├── getSuperProperties.js │ │ ├── getSuperProperty.js │ │ ├── identify.js │ │ ├── pageView.js │ │ ├── profileAppend.js │ │ ├── profileDelete.js │ │ ├── profileIncrement.js │ │ ├── profileSet.js │ │ ├── profileSetOnce.js │ │ ├── profileUnset.js │ │ ├── registerSuperProperties.js │ │ ├── registerSuperProperty.js │ │ ├── reset.js │ │ ├── startUp.js │ │ ├── track.js │ │ └── unRegisterSuperProperty.js ├── configure │ ├── base │ │ ├── fieldRules.js │ │ ├── fieldTemplate.js │ │ ├── index.js │ │ └── lifecycle.js │ ├── customized │ │ ├── UA │ │ │ ├── configure │ │ │ │ ├── fieldRules.js │ │ │ │ └── fieldTemplate.js │ │ │ └── index.js │ │ ├── decodeGBK │ │ │ ├── configure │ │ │ │ └── lifecycle.js │ │ │ ├── index.js │ │ │ └── lib │ │ │ │ └── decodeGBK.js │ │ ├── encrypt │ │ │ ├── configure │ │ │ │ ├── fieldRules.js │ │ │ │ ├── fieldTemplate.js │ │ │ │ └── lifecycle.js │ │ │ ├── index.js │ │ │ └── lib │ │ │ │ ├── base64js.min.js │ │ │ │ └── encrypt.js │ │ ├── exposure │ │ │ └── index.js │ │ ├── heatmap │ │ │ ├── configure │ │ │ │ ├── fieldRules.js │ │ │ │ ├── fieldTemplate.js │ │ │ │ └── lifecycle.js │ │ │ ├── heatmapSDK │ │ │ │ ├── common │ │ │ │ │ ├── config.js │ │ │ │ │ ├── iframeMsg.js │ │ │ │ │ └── index.js │ │ │ │ ├── head │ │ │ │ │ ├── heatmap.css │ │ │ │ │ └── index.js │ │ │ │ ├── heatElement │ │ │ │ │ └── heatElement.js │ │ │ │ ├── heatMap │ │ │ │ │ ├── index.js │ │ │ │ │ └── nav.js │ │ │ │ ├── index.js │ │ │ │ ├── lib │ │ │ │ │ ├── colorRange.js │ │ │ │ │ └── heatmap.js │ │ │ │ └── webstay │ │ │ │ │ ├── webStayDom.js │ │ │ │ │ ├── webStayLine.css │ │ │ │ │ └── webstay.js │ │ │ ├── index.js │ │ │ └── lib │ │ │ │ ├── elementContent.js │ │ │ │ ├── getField.js │ │ │ │ └── heatmap.js │ │ ├── hybrid │ │ │ └── lib │ │ │ │ └── hybrid.js │ │ ├── mpaas │ │ │ └── index.js │ │ ├── pageClose │ │ │ └── index.js │ │ ├── userClick │ │ │ ├── configure │ │ │ │ ├── fieldRules.js │ │ │ │ ├── fieldTemplate.js │ │ │ │ └── lifecycle.js │ │ │ ├── index.js │ │ │ └── lib │ │ │ │ └── userClick.js │ │ ├── visual │ │ │ ├── configure │ │ │ │ ├── fieldRules.js │ │ │ │ ├── fieldTemplate.js │ │ │ │ └── lifecycle.js │ │ │ ├── index.js │ │ │ ├── lib │ │ │ │ └── visitor.js │ │ │ └── visualShow │ │ │ │ ├── common │ │ │ │ ├── boxMove.js │ │ │ │ ├── config.js │ │ │ │ ├── iframeMsg.js │ │ │ │ └── index.js │ │ │ │ ├── debug │ │ │ │ └── index.js │ │ │ │ ├── index.js │ │ │ │ ├── templete │ │ │ │ ├── debug.js │ │ │ │ ├── index.js │ │ │ │ └── style.css │ │ │ │ └── visual │ │ │ │ └── index.js │ │ └── webstay │ │ │ ├── configure │ │ │ ├── fieldRules.js │ │ │ ├── fieldTemplate.js │ │ │ └── lifecycle.js │ │ │ ├── index.js │ │ │ └── lib │ │ │ ├── autoWebstay.js │ │ │ └── getField.js │ └── index.js ├── lib │ ├── baseConfig │ │ └── index.js │ ├── checkField │ │ └── index.js │ ├── common │ │ └── index.js │ ├── compatible │ │ ├── JSON2.js │ │ └── index.js │ ├── fillField │ │ ├── UTM.js │ │ ├── deviceType.js │ │ ├── getField.js │ │ ├── id.js │ │ ├── index.js │ │ ├── sessionId.js │ │ └── spider.js │ ├── mergeRules │ │ └── index.js │ ├── printLog │ │ └── index.js │ ├── storage │ │ └── index.js │ └── upload │ │ ├── ajax.js │ │ ├── hybrid.js │ │ └── index.js └── main.js ├── vue-demo ├── .gitignore ├── README.md ├── babel.config.js ├── package.json ├── public │ ├── AnalysysAgent_JS_SDK_HEATMAP.min.js │ ├── favicon.ico │ ├── index.html │ └── js │ │ └── sdk │ │ ├── AnalysysAgent_JS_SDK_HEATMAP.min.js │ │ └── AnalysysAgent_JS_SDK_VISUAL.min.js ├── src │ ├── App.vue │ ├── assets │ │ └── logo.png │ ├── components │ │ ├── index.vue │ │ └── next.vue │ ├── main.js │ ├── routes │ │ └── index.js │ └── sdk │ │ ├── AnalysysAgent_Encrypt.es6.min.js │ │ ├── AnalysysAgent_ExposurePoint.es6.min.js │ │ ├── AnalysysAgent_GBK.es6.min.js │ │ ├── AnalysysAgent_JS_SDK.es6.min.js │ │ ├── AnalysysAgent_MPAAS.es6.min.js │ │ └── AnalysysAgent_PageViewStayTime.es6.min.js └── vue.config.js └── vue-dome └── src └── sdk └── AnalysysAgent_MPAAS.es6.min.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "test": { 4 | "plugins": [ 5 | "@babel/plugin-transform-modules-commonjs" 6 | ] 7 | } 8 | } 9 | } -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/* 2 | ua-parser.js 3 | test/ 4 | **/decodeGBK.js 5 | **/JSON2.js 6 | !src/ 7 | *.html 8 | *.json 9 | *.min.js -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "env": { 3 | "browser": true, 4 | "es6": true, 5 | "jest": true, 6 | "node": true 7 | }, 8 | "extends": "eslint:recommended", 9 | "globals": { 10 | "Atomics": "readonly", 11 | "SharedArrayBuffer": "readonly", 12 | "__static": true 13 | }, 14 | "parser": 'babel-eslint', 15 | "parserOptions": { 16 | "ecmaVersion": 6, 17 | "sourceType": "module", 18 | }, 19 | "rules": { 20 | "no-empty": 0, 21 | "no-control-regex": "off", 22 | "no-misleading-character-class": "off" 23 | } 24 | }; -------------------------------------------------------------------------------- /.github/workflows/npm-publish.yml: -------------------------------------------------------------------------------- 1 | name: Node.js Package 2 | 3 | on: 4 | release: 5 | types: [created] 6 | 7 | jobs: 8 | publish-npm: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v2 12 | - uses: actions/setup-node@v1 13 | with: 14 | node-version: 12 15 | registry-url: https://registry.npmjs.org/ 16 | - run: npm publish 17 | env: 18 | NODE_AUTH_TOKEN: ${{secrets.npm_token}} 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | package-lock.json 2 | node_modules/ 3 | *.zip 4 | .DS_Store 5 | yarn.lock 6 | bac 7 | demo/react/ 8 | demo/vue/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Analysys JavaScript SDK [![NPM version][npm-image]][npm-url] [![License](https://img.shields.io/github/license/analysys/ans-javascript-sdk.svg)](https://github.com/analysys/ans-javascript-sdk/blob/master/LICENSE) [![GitHub release](https://img.shields.io/github/release/analysys/ans-javascript-sdk.svg)](https://github.com/analysys/ans-javascript-sdk/releases) 3 | 4 | ======== 5 | 6 | This is the official JavaScript SDK for Analysys. 7 | 8 | # JavaScript SDK目录说明: 9 | * demo——API调用演示 10 | * SDK——SDK文件 11 | * src——SDK源码 12 | * vue-demo——VUE框架API调用演示 13 | 14 | # 安装 15 | 16 | ``` 17 | npm install ans-javascript-sdk --save 18 | ``` 19 | 20 | # JavaScript 基础说明: 21 | 22 | JS SDK 用于由 HTML 、 Css 及 Javascript 制作成的网站,集成前请先安装SDK 23 | 24 | ## 快速集成 25 | 如果您是第一次使用易观方舟产品,可以通过阅读本文快速了解此产品 26 | 1. 选择集成方式 27 | 目前我们提供了异步集成、同步集成的方式 28 | 2. 设置初始化接口 29 | 通过初始化代码的配置参数配置您的 AppKey 30 | 3. 设置上传地址 31 | 通过初始化代码的配置参数 uploadURL 设置您上传数据的地址。 32 | 4. 设置需要采集的页面或事件 33 | 通过手动埋点,设置需要采集的页面或事件。 34 | 5. 打开Debug模式查看日志 35 | 通过设置 Ddebug 模式,开(debugMode为1或2)/关(debugMode为0或不设置) log 查看日志。 36 | 37 | > 通过以上步骤您即可验证SDK是否已经集成成功,具体使用方法参考:[易观方舟 JavaScript SDK 文档](https://docs.analysys.cn/ark/integration/sdk/js/js) 38 | 39 | > 注意 SDK 可能不完全向前兼容,请查看版本更新说明 [Release及版本升级记录](https://github.com/analysys/ans-javascript-sdk/releases)。如果有说明不兼容的话,需要升级易观方舟对应的版本。 请根据需要前往 [Release](https://github.com/analysys/ans-javascript-sdk/releases) 里下载对应的文件 40 | 41 | ## 版本升级记录 42 | 请参见 [Release及版本升级记录](https://github.com/analysys/ans-wechat-sdk/releases) 43 | 更多Api使用方法参考:[易观方舟 JavaScript SDK 文档](https://docs.analysys.cn/ark/integration/sdk/js/js) 44 | 45 | # 讨论 46 | * 微信号:nlfxwz 47 | * 钉钉群:30099866 48 | * 邮箱:nielifeng@analysys.com.cn 49 | 50 | 51 | # License 52 | 53 | [gpl-3.0](https://www.gnu.org/licenses/gpl-3.0.txt) 54 | 55 | **禁止一切基于易观方舟 javascript 开源 SDK 的所有商业活动!** 56 | 57 | --- 58 | 59 | [![NPM downloads][npm-downloads]][npm-url] 60 | 61 | 62 | [homepage]: https://github.com/analysys/ans-javascript-sdk 63 | [npm-url]: https://www.npmjs.com/package/ans-javascript-sdk 64 | [npm-image]: https://img.shields.io/npm/v/ans-javascript-sdk.svg?style=flat 65 | [npm-downloads]: https://img.shields.io/npm/dm/ans-javascript-sdk.svg?style=flat 66 | -------------------------------------------------------------------------------- /demo/javascript/initSdk.js: -------------------------------------------------------------------------------- 1 | (function (c) { 2 | window.AnalysysAgent = window.AnalysysAgent || {} 3 | var a = window.AnalysysAgent || {} 4 | var ans = ['identify', 'alias', 'reset', 'track', 'profileSet', 'profileSetOnce', 'profileIncrement', 'profileAppend', 'profileUnset', 'profileDelete', 'registerSuperProperty', 'registerSuperProperties', 'unRegisterSuperProperty', 'clearSuperProperties', 'getSuperProperty', 'getSuperProperties', 'pageView', 'getDistinctId'] 5 | a['config'] = c 6 | a['param'] = [] 7 | function factory (b) { 8 | return function () { 9 | a['param'].push([b, arguments]) 10 | return window.AnalysysAgent 11 | } 12 | } 13 | for (var i = 0; i < ans.length; i++) { 14 | a[ans[i]] = factory(ans[i]) 15 | } 16 | if (c.name) { 17 | window[c.name] = a 18 | } 19 | })({ 20 | appkey: "commondebug", //APPKEY 21 | debugMode: 2, 22 | uploadURL: 'https://sdk.analysys.cn:4089/', 23 | visitorConfigURL: 'https://sdk.analysys.cn:4089/', 24 | /**如无自定义配置,则与uploadURL相同**/ 25 | autoHeatmap: true 26 | }) -------------------------------------------------------------------------------- /demo/style/console.js: -------------------------------------------------------------------------------- 1 | console.oldLog = console.log 2 | console.log = a = function () { 3 | if (console.constructor === Object && console.log) { 4 | try { 5 | console.oldLog.apply(console, arguments); 6 | } catch (e) { 7 | console.oldLog(arguments[0]); 8 | } 9 | } 10 | // console.log(arguments) 11 | if (arguments[0] && arguments[0].constructor === String && arguments[0].indexOf("Send") > -1) { 12 | try { 13 | document.getElementById("upLog").innerText = arguments[0] 14 | } catch (e) {} 15 | } 16 | } -------------------------------------------------------------------------------- /demo/style/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * [pageView description] 页面事件 3 | * @param {[String]} pageName [description] 页面标识,支持类型:String;最大长度255字符 4 | * @param {[Object]} pageInfo [description] 页面信息,支持类型:Object/Array;页面信息最多包含100条;Object类型内key以字母或$开头,包括大小写字母、数字、下划线和$,最大长度125字符,不支持乱码和中文;Object/Array中的value,支持类型:String;则最大长度255字符 5 | */ 6 | function pageView(pageName, pageInfo) { 7 | AnalysysAgent.pageView(pageName, pageInfo) 8 | } 9 | /** 10 | * [track description] 点击事件 11 | * @param {[String]} eventName [description] 事件名称。支持类型:String。以字母或$开头,可以包含大小写字母/数字/下划线,不支持中文,不支持乱码,最大长度99字符。 12 | * @param {[Object]} eventInfo [description] 事件属性,支持类型:Object/Array;事件属性最多包含100条;Object类型内key以字母或$开头,包括大小写字母、数字、下划线和$,最大长度125字符,不支持乱码和中文;Object/Array中的value,支持类型:String;则最大长度255字符 13 | */ 14 | function track(eventName, eventInfo) { 15 | AnalysysAgent.track(eventName, eventInfo); 16 | } 17 | /** 18 | * [registerSuperProperty description] 注册通用属性 19 | * @param {[String]} uperPropertyName [description] 属性名称 支持类型:String。以字母或$开头,可以包含大小写字母/数字/下划线,不支持中文,不支持乱码,最大长度99字符。 20 | * @param {[String]} superPropertyValue [description] 事件属性,支持类型:String;则最大长度255字符 21 | */ 22 | function registerSuperProperty(superPropertyName, superPropertyValue) { 23 | AnalysysAgent.registerSuperProperty(superPropertyName, superPropertyValue); 24 | } 25 | 26 | /** 27 | * [registerSuperProperties description] 注册通用属性 28 | * @param {[Object]} superProperties [description] 属性集合 支持类型:Object。key以字母或$开头,可以包含大小写字母/数字/下划线,不支持中文,不支持乱码,最大长度99字符,value支持类型:String;则最大长度255字符。 29 | */ 30 | function registerSuperProperties(superProperties) { 31 | AnalysysAgent.registerSuperProperties(superProperties); 32 | } 33 | /** 34 | * [unregisterSuperProperty description] 删除单个通用属性 35 | * @param {[Object]} superPropertyName [description] 属性名称 支持类型:String。以字母或$开头,可以包含大小写字母/数字/下划线,不支持中文,不支持乱码,最大长度99字符。 36 | */ 37 | function unRegisterSuperProperty(superPropertyName) { 38 | AnalysysAgent.unRegisterSuperProperty(superPropertyName); 39 | } 40 | /** 41 | * [clearSuperProperties description] 清除所有通用属性 42 | */ 43 | function clearSuperProperties() { 44 | AnalysysAgent.clearSuperProperties(); 45 | } 46 | /** 47 | * [clearSuperProperties description] 获取单个通用属性 48 | */ 49 | function getSuperProperty(superPropertyName) { 50 | var superProperty = AnalysysAgent.getSuperProperty(superPropertyName); 51 | console.log('获取单个通用属性[' + superPropertyName + ']:', superProperty) 52 | } 53 | /** 54 | * [clearSuperProperties description] 获取所有通用属性 55 | */ 56 | function getSuperProperties() { 57 | var superProperties = AnalysysAgent.getSuperProperties(); 58 | console.log('获取所有通用属性:', superProperties) 59 | } 60 | /** 61 | * [identify description] 用户ID设置 62 | * @param {[String]} distinctId [description] 唯一身份标识,支持类型:String;长度大于0且小于255字符 63 | */ 64 | function identify(distinctId) { 65 | AnalysysAgent.identify(distinctId); 66 | } 67 | /** 68 | * [alias description]用户关联 新distinctID关联到原有originalID,originalID为原始id. 69 | * @param {[String]} aliasId [description] 支持类型:String;长度大于0,且小于255字符 70 | */ 71 | function alias(aliasId) { 72 | AnalysysAgent.alias(aliasId); 73 | } 74 | /** 75 | * [profileSet description] 设置用户属性 76 | * @param {[String]} propertyName [description] 支持类型:String;以字母或`$`开头,可包含大小写字母/数字/`_`/`$`,最大长度125字符,不支持乱码和中文 77 | * @param {[String/Number/Boolean/Array]} propertyValue [description]支持类型:String/Number/Boolean/Array;若为字符串,则最大长度255字符;若为数组或集合,则最多包含100条,且key约束条件与属性名称一致,value最大长度255字符 78 | */ 79 | function profileSet(propertyName, propertyValue) { 80 | AnalysysAgent.profileSet(propertyName, propertyValue); 81 | } 82 | /** 83 | * [profileSetOnce description] 在首次设置时有效的属性 84 | * @param {[String]} propertyName [description] 支持类型:String;以字母或`$`开头,可包含大小写字母/数字/`_`/`$`,最大长度125字符,不支持乱码和中文 85 | * @param {[String/Number/Boolean/Array]} propertyValue [description] 支持类型:String/Number/Boolean/Array;若为字符串,则最大长度255字符;若为数组或集合,则最多包含100条,且key约束条件与属性名称一致,value最大长度255字符 86 | */ 87 | function profileSetOnce(propertyName, propertyValue) { 88 | AnalysysAgent.profileSetOnce(propertyName, propertyValue); 89 | } 90 | /** 91 | * [profileIncrement description] 设置用户属性相对变化值 92 | * @param {[String]} propertyName [description] 属性名称 支持类型:String;以字母或`$`开头,可包含大小写字母/数字/`_`/`$`,最大长度125字符,不支持乱码和中文 93 | * @param {[String/Number/Boolean/Array]} propertyValue [description] 属性值 支持类型:String/Number/Boolean/Array;若为字符串,则最大长度255字符;若为数组或集合,则最多包含100条,且key约束条件与属性名称一致,value最大长度255字符 94 | */ 95 | function profileIncrement(propertyName, propertyValue) { 96 | AnalysysAgent.profileIncrement(propertyName, propertyValue) 97 | } 98 | /** 99 | * [profileAppend description]设置单个列表类型的属性 100 | * @param {[String]} propertyName [description] 属性名称 支持类型:String;以字母或`$`开头,可包含大小写字母/数字/`_`/`$`,最大长度125字符,不支持乱码和中文 101 | * @param {[String/Number/Boolean]} propertyValue [description] 属性值 支持类型:String/Number/Boolean;最大长度255字符; 102 | */ 103 | function profileAppend(propertyName, propertyValue) { 104 | AnalysysAgent.profileAppend(propertyName, propertyValue); 105 | } 106 | /** 107 | * [profileUnset description] 删除设置的属性 108 | * @param {[String]} property [description] 属性名称 支持类型:String;以字母或`$`开头,可包含大小写字母/数字/`_`/`$`,最大长度125字符,不支持乱码和中文 109 | */ 110 | function profileUnset(property) { 111 | AnalysysAgent.profileUnset(property); 112 | } 113 | /** 114 | * [profileDelete description] 要清除已经设置的所有属性 115 | */ 116 | function profileDelete() { 117 | AnalysysAgent.profileDelete(); 118 | } 119 | /** 120 | * [reset description] 清除本地设置 121 | */ 122 | function reset() { 123 | AnalysysAgent.reset(); 124 | } 125 | 126 | /** 127 | * [historyPage description] 修改history记录跳转页面 128 | * @param {[String]} page [description] 跳转页面地址 129 | */ 130 | function historyPage(page) { 131 | document.title = 'historyPage' //跳转后的页面title 132 | history.pushState(null, null, page) 133 | } 134 | /** 135 | * [historyPage description] 修改hash值跳转页面 136 | * @param {[String]} page [description] 跳转页面地址 137 | */ 138 | function hashPage(page) { 139 | document.title = 'hashPage' 140 | location.href = page 141 | } 142 | 143 | /** 144 | * 获取预置属性 145 | */ 146 | function getPresetProperties() { 147 | var presetProperties = AnalysysAgent.getPresetProperties() 148 | console.log('获取预置属性:', presetProperties) 149 | } 150 | 151 | /** 152 | * 获取匿名ID 153 | */ 154 | function getDistinctId() { 155 | var distinctId = AnalysysAgent.getDistinctId() 156 | console.log("匿名ID:" + distinctId) 157 | } -------------------------------------------------------------------------------- /demo/style/plugIn/bootstrap/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/analysys/ans-javascript-sdk/83a214c8c92f79557107d105c67223b7c32632ee/demo/style/plugIn/bootstrap/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /demo/style/plugIn/bootstrap/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/analysys/ans-javascript-sdk/83a214c8c92f79557107d105c67223b7c32632ee/demo/style/plugIn/bootstrap/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /demo/style/plugIn/bootstrap/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/analysys/ans-javascript-sdk/83a214c8c92f79557107d105c67223b7c32632ee/demo/style/plugIn/bootstrap/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /demo/style/plugIn/bootstrap/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/analysys/ans-javascript-sdk/83a214c8c92f79557107d105c67223b7c32632ee/demo/style/plugIn/bootstrap/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /demo/style/plugIn/bootstrap/js/npm.js: -------------------------------------------------------------------------------- 1 | // This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment. 2 | require('../../js/transition.js') 3 | require('../../js/alert.js') 4 | require('../../js/button.js') 5 | require('../../js/carousel.js') 6 | require('../../js/collapse.js') 7 | require('../../js/dropdown.js') 8 | require('../../js/modal.js') 9 | require('../../js/tooltip.js') 10 | require('../../js/popover.js') 11 | require('../../js/scrollspy.js') 12 | require('../../js/tab.js') 13 | require('../../js/affix.js') -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ans-javascript-sdk", 3 | "version": "4.5.6", 4 | "description": "official analysysAgent javascript sdk", 5 | "main": "./sdk/AnalysysAgent_JS_SDK.min.js", 6 | "module": "./sdk/AnalysysAgent_JS_SDK.es6.min.js", 7 | "scripts": { 8 | "test": "jest", 9 | "dev": "rollup -c rollup.config.js --watch", 10 | "module": "rollup -c rollup.module.config.js --watch", 11 | "plugins": "rollup -c rollup.plugins.config.js --watch", 12 | "build": "rollup -c rollup.config.js&&rollup -c rollup.module.config.js&&rollup -c rollup.plugins.config.js", 13 | "cover": "jest --coverage", 14 | "lint": "standard \"src/**/*.{js,vue}\"", 15 | "lint:fix": "standard \"src/**/*.{js,vue}\" --fix" 16 | }, 17 | "repository": { 18 | "type": "git", 19 | "url": "git+https://github.com/analysys/ans-javascript-sdk.git" 20 | }, 21 | "standard": { 22 | "parser": "babel-eslint", 23 | "rules": { 24 | "no-control-regex": "off", 25 | "no-misleading-character-class": "off" 26 | }, 27 | "ignore": [ 28 | "**/parseUA/**", 29 | "test/", 30 | "decodeGBK.js", 31 | "**/lib/heatmap.js", 32 | "JSON2.js", 33 | "**/upload/index.js", 34 | "*.html", 35 | "*.json" 36 | ] 37 | }, 38 | "author": "zhangyufei@analysys.com.cn", 39 | "license": "ISC", 40 | "devDependencies": { 41 | "@babel/cli": "^7.10.0", 42 | "@babel/core": "^7.10.0", 43 | "@babel/helpers": "^7.7.0", 44 | "@babel/plugin-external-helpers": "^7.8.3", 45 | "@babel/plugin-proposal-class-properties": "^7.7.0", 46 | "@babel/plugin-proposal-decorators": "^7.7.0", 47 | "@babel/plugin-proposal-export-namespace-from": "^7.0.0", 48 | "@babel/plugin-proposal-function-sent": "^7.7.0", 49 | "@babel/plugin-proposal-json-strings": "^7.0.0", 50 | "@babel/plugin-proposal-numeric-separator": "^7.0.0", 51 | "@babel/plugin-proposal-throw-expressions": "^7.0.0", 52 | "@babel/plugin-syntax-dynamic-import": "^7.0.0", 53 | "@babel/plugin-syntax-import-meta": "^7.0.0", 54 | "@babel/plugin-transform-reserved-words": "^7.2.0", 55 | "@babel/plugin-transform-runtime": "^7.0.0", 56 | "@babel/preset-env": "^7.10.0", 57 | "@babel/register": "^7.7.0", 58 | "babel-core": "^7.0.0-bridge.0", 59 | "babel-eslint": "^10.0.3", 60 | "babel-jest": "^26.0.1", 61 | "babel-loader": "^8.1.0", 62 | "babel-plugin-transform-member-expression-literals": "^6.9.4", 63 | "babel-plugin-transform-property-literals": "^6.9.4", 64 | "babel-preset-es2015": "^6.24.1", 65 | "babel-preset-es2015-rollup": "~3.0.0", 66 | "babel-preset-es3": "~1.0.1", 67 | "babel-preset-stage-2": "^6.24.1", 68 | "eslint": "^7.1.0", 69 | "heatmap.js": "^2.0.5", 70 | "jest": "^26.0.1", 71 | "pako": "^1.0.10", 72 | "rollup-plugin-babel": "^4.0.1", 73 | "rollup-plugin-commonjs": "^10.1.0", 74 | "rollup-plugin-es3": "^1.1.0", 75 | "rollup-plugin-eslint": "^7.0.0", 76 | "rollup-plugin-json": "^4.0.0", 77 | "rollup-plugin-node-builtins": "~2.1.2", 78 | "rollup-plugin-node-resolve": "^5.2.0", 79 | "rollup-plugin-postcss": "^3.1.1", 80 | "rollup-plugin-replace": "^2.2.0", 81 | "rollup-plugin-terser": "^6.1.0", 82 | "rollup-plugin-uglify": "^6.0.3", 83 | "rollup-watch": "~4.3.1", 84 | "ua-device": "^0.1.10" 85 | }, 86 | "dependencies": { 87 | "@babel/plugin-proposal-do-expressions": "^7.0.0", 88 | "@babel/plugin-proposal-export-default-from": "^7.0.0", 89 | "@babel/plugin-proposal-export-namespace-from": "^7.0.0", 90 | "@babel/plugin-proposal-function-bind": "^7.0.0", 91 | "@babel/plugin-proposal-json-strings": "^7.0.0", 92 | "@babel/plugin-proposal-logical-assignment-operators": "^7.0.0", 93 | "@babel/plugin-proposal-nullish-coalescing-operator": "^7.0.0", 94 | "@babel/plugin-proposal-numeric-separator": "^7.0.0", 95 | "@babel/plugin-proposal-optional-chaining": "^7.0.0", 96 | "@babel/plugin-proposal-pipeline-operator": "^7.0.0", 97 | "@babel/plugin-proposal-throw-expressions": "^7.0.0", 98 | "@babel/plugin-syntax-dynamic-import": "^7.0.0", 99 | "@babel/plugin-syntax-import-meta": "^7.0.0", 100 | "@babel/plugin-transform-member-expression-literals": "^7.0.0", 101 | "@babel/plugin-transform-modules-commonjs": "^7.10.4", 102 | "@babel/plugin-transform-property-literals": "^7.0.0", 103 | "@babel/polyfill": "^7.8.7", 104 | "@babel/runtime": "^7.7.2", 105 | "babel-plugin-transform-es2015-modules-commonjs": "^6.26.2", 106 | "babel-preset-env": "^1.7.0", 107 | "core-js": "^3.6.5", 108 | "crypto-js": "^3.1.9-1", 109 | "intersection-observer": "^0.11.0", 110 | "mutationobserver-shim": "^0.3.7", 111 | "regenerator-runtime": "^0.13.3", 112 | "rollup": "^1.27.3" 113 | }, 114 | "bugs": { 115 | "url": "https://github.com/analysys/ans-javascript-sdk/issues" 116 | }, 117 | "homepage": "https://github.com/analysys/ans-javascript-sdk#readme", 118 | "keywords": [ 119 | "analysys", 120 | "analysysagent", 121 | "ans", 122 | "analytics", 123 | "sdk", 124 | "js" 125 | ], 126 | "engines": { 127 | "node": ">=6.0" 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import babel from 'rollup-plugin-babel' 2 | import { eslint } from 'rollup-plugin-eslint' 3 | import resolve from 'rollup-plugin-node-resolve' 4 | import commonjs from 'rollup-plugin-commonjs' 5 | import postcss from 'rollup-plugin-postcss' 6 | import { uglify } from 'rollup-plugin-uglify' 7 | import { terser } from 'rollup-plugin-terser' 8 | import es3 from 'rollup-plugin-es3'; 9 | export default [ 10 | { 11 | input: './src/main.js', 12 | output: [ 13 | { 14 | file: './demo/sdk/AnalysysAgent_JS_SDK.min.js', 15 | format: 'umd', 16 | name: 'AnalysysAgent', 17 | freeze: false, 18 | plugins: [ 19 | uglify({ 20 | mangle: { 21 | toplevel: true 22 | }, 23 | ie8: true 24 | }) 25 | ], 26 | amd: { 27 | define: '{}' 28 | } 29 | }, 30 | { 31 | file: './SDK/AnalysysAgent_JS_SDK.min.js', 32 | format: 'umd', 33 | name: 'AnalysysAgent', 34 | freeze: false, 35 | plugins: [ 36 | uglify({ 37 | mangle: { 38 | toplevel: true 39 | }, 40 | ie8: true 41 | }) 42 | ], 43 | amd: { 44 | define: '{}' 45 | } 46 | }, 47 | { 48 | file: './demo/sdk/AnalysysAgent_JS_SDK.amd.min.js', 49 | format: 'amd', 50 | name: 'AnalysysAgent', 51 | freeze: false, 52 | plugins: [ 53 | uglify({ 54 | mangle: { 55 | toplevel: true 56 | }, 57 | ie8: true 58 | }) 59 | ] 60 | }, { 61 | file: './SDK/AnalysysAgent_JS_SDK.es6.min.js', 62 | format: 'esm', 63 | name: 'AnalysysAgent', 64 | plugins: [ 65 | terser({ 66 | mangle: { 67 | toplevel: true 68 | } 69 | }) 70 | ] 71 | }, 72 | { 73 | file: './vue-demo/src/sdk/AnalysysAgent_JS_SDK.es6.min.js', 74 | format: 'esm', 75 | name: 'AnalysysAgent', 76 | freeze: false, 77 | plugins: [ 78 | terser({ 79 | mangle: { 80 | toplevel: true 81 | } 82 | }) 83 | ] 84 | } 85 | ], 86 | plugins: [ 87 | resolve({ 88 | jsnext: true, 89 | main: true, 90 | browser: true 91 | }), 92 | postcss({ 93 | extensions: ['.css'] 94 | }), 95 | commonjs(), 96 | eslint({ 97 | include: 'src/**', 98 | exclude: ['node_modules/**'], 99 | }), 100 | babel({ 101 | 102 | babelrc: false, 103 | 104 | presets: [['@babel/preset-env', { 105 | modules: false, loose: true, "targets": { 106 | "ie": "6" 107 | } 108 | }]], 109 | 110 | include: ['src/**'], 111 | 112 | plugins: ['@babel/plugin-external-helpers'], 113 | 114 | runtimeHelpers: true 115 | 116 | }), 117 | 118 | es3({ 119 | 120 | remove: ['defineProperty', 'freeze'] 121 | 122 | }) 123 | ] 124 | } 125 | ] 126 | -------------------------------------------------------------------------------- /rollup.plugins.config.js: -------------------------------------------------------------------------------- 1 | import babel from 'rollup-plugin-babel' 2 | import { eslint } from 'rollup-plugin-eslint' 3 | import resolve from 'rollup-plugin-node-resolve' 4 | import commonjs from 'rollup-plugin-commonjs' 5 | import postcss from 'rollup-plugin-postcss' 6 | import es3 from 'rollup-plugin-es3'; 7 | import { uglify } from 'rollup-plugin-uglify' 8 | import { terser } from 'rollup-plugin-terser' 9 | var plugin = [ 10 | resolve({ 11 | jsnext: true, 12 | main: true, 13 | browser: true 14 | }), 15 | postcss({ 16 | extensions: ['.css'] 17 | }), 18 | commonjs(), 19 | eslint({ 20 | include: 'src/**', 21 | exclude: ['node_modules/**'], 22 | }), 23 | babel({ 24 | 25 | babelrc: false, 26 | 27 | presets: [['@babel/preset-env', { 28 | modules: false, loose: true, "targets": { 29 | "ie": "6" 30 | } 31 | }]], 32 | 33 | include: ['src/**'], 34 | 35 | plugins: ['@babel/plugin-external-helpers'], 36 | 37 | runtimeHelpers: true 38 | 39 | }), 40 | 41 | es3({ 42 | 43 | remove: ['defineProperty', 'freeze'] 44 | 45 | }) 46 | ] 47 | export default [ 48 | { 49 | input: './src/configure/customized/mpaas/index.js', 50 | output: [{ 51 | file: './demo/sdk/AnalysysAgent_MPAAS.min.js', 52 | format: 'iife', 53 | name: 'Encrypt', 54 | freeze: false, // 禁止使用Object.freeze方式加载模块 55 | plugins: [ 56 | uglify({ 57 | mangle: { 58 | toplevel: true 59 | }, 60 | ie8: true 61 | }) 62 | ] 63 | }, 64 | { 65 | file: './sdk/AnalysysAgent_MPAAS.min.js', 66 | format: 'iife', 67 | name: 'Encrypt', 68 | freeze: false, // 禁止使用Object.freeze方式加载模块 69 | plugins: [ 70 | uglify({ 71 | mangle: { 72 | toplevel: true 73 | }, 74 | ie8: true 75 | }) 76 | ] 77 | }, { 78 | file: './vue-dome/src/sdk/AnalysysAgent_MPAAS.es6.min.js', 79 | format: 'esm', 80 | name: 'Encrypt', 81 | plugins: [ 82 | terser({ 83 | mangle: { 84 | toplevel: true 85 | } 86 | }) 87 | ] 88 | }, 89 | { 90 | file: './sdk/AnalysysAgent_MPAAS.es6.min.js', 91 | format: 'esm', 92 | name: 'Encrypt', 93 | plugins: [ 94 | terser({ 95 | mangle: { 96 | toplevel: true 97 | } 98 | }) 99 | ] 100 | }, 101 | { 102 | file: './demo/sdk/AnalysysAgent_MPAAS.amd.min.js', 103 | format: 'amd', 104 | name: 'Encrypt', 105 | plugins: [ 106 | uglify({ 107 | mangle: { 108 | toplevel: true 109 | }, 110 | ie8: true 111 | }) 112 | ] 113 | }, 114 | { 115 | file: './sdk/AnalysysAgent_MPAAS.amd.min.js', 116 | format: 'amd', 117 | name: 'Encrypt', 118 | plugins: [ 119 | uglify({ 120 | mangle: { 121 | toplevel: true 122 | }, 123 | ie8: true 124 | }) 125 | ] 126 | }], 127 | plugins: plugin 128 | } 129 | ] 130 | -------------------------------------------------------------------------------- /sdk/md5.txt: -------------------------------------------------------------------------------- 1 | AnalysysAgent_Encrypt.amd.min.js : 784433ef6b1f4f6b040ddb566aea0626 2 | AnalysysAgent_Encrypt.es6.min.js : 6a2ee50777d35badecafb442cd38d0a1 3 | AnalysysAgent_Encrypt.min.js : 9053fda19b72f6226960a6bbabc2d2f7 4 | AnalysysAgent_ExposurePoint.amd.min.js : 5ed0d2ef918f77cdf10a343287971bc0 5 | AnalysysAgent_ExposurePoint.es6.min.js : b9c117d8d584443c551bc13cb6783a6f 6 | AnalysysAgent_ExposurePoint.min.js : 69d54c00a1d4d4ebe5d382b720be274a 7 | AnalysysAgent_GBK.amd.min.js : 1b93e2c1ad648a1f85bcd5a11a4d2ef5 8 | AnalysysAgent_GBK.es6.min.js : cba14fe216ea5cda5b1585ad5e9d8ee5 9 | AnalysysAgent_GBK.min.js : 2c2573fd9a7570a4dda6f9561eb3c3c6 10 | AnalysysAgent_JS_SDK.amd.min.js : 0856ef5489080e0c398e4020b7ec1372 11 | AnalysysAgent_JS_SDK.es6.min.js : 9a3e60cd258c7e81c0f0fb24820ec4a0 12 | AnalysysAgent_JS_SDK.min.js : 377b06e05d8a71de0e47d85f571908b8 13 | AnalysysAgent_JS_SDK_HEATMAP.min.js : 38502d01e3423d36bc29f57a8fb45c3b 14 | AnalysysAgent_JS_SDK_VISUAL.min.js : 775cd61493f4ea9de299226b1029dc32 15 | AnalysysAgent_MPAAS.amd.min.js : cc1899d875c3fd25b0aee7c65cac5bd7 16 | AnalysysAgent_MPAAS.es6.min.js : 662d57935949fdad4f6d19b80b06f15c 17 | AnalysysAgent_MPAAS.min.js : 76c03a094e69cd9fd0c68bf8ee4d70f7 18 | AnalysysAgent_PageViewStayTime.amd.min.js : 739b2a6e10971e9b953bebc42767ac14 19 | AnalysysAgent_PageViewStayTime.es6.min.js : 6b1340d9e6b963cfe99a8b1cd36225cb 20 | AnalysysAgent_PageViewStayTime.min.js : 6b245404a732029f33e120904c64e287 21 | -------------------------------------------------------------------------------- /src/API/index.js: -------------------------------------------------------------------------------- 1 | // import '../lib/compatible/index.js' 2 | import { pageView } from './template/pageView.js' 3 | import { track } from './template/track.js' 4 | import { freeApi } from './template/freeApi.js' 5 | import { getPresetProperties } from './template/getPresetProperties.js' 6 | import { alias } from './template/alias.js' 7 | import { identify } from './template/identify.js' 8 | import { profileSet } from './template/profileSet.js' 9 | import { profileSetOnce } from './template/profileSetOnce.js' 10 | import { profileIncrement } from './template/profileIncrement.js' 11 | import { profileAppend } from './template/profileAppend.js' 12 | import { profileUnset } from './template/profileUnset.js' 13 | import { profileDelete } from './template/profileDelete.js' 14 | import { registerSuperProperty } from './template/registerSuperProperty.js' 15 | import { registerSuperProperties } from './template/registerSuperProperties.js' 16 | import { getSuperProperty } from './template/getSuperProperty.js' 17 | import { getSuperProperties } from './template/getSuperProperties.js' 18 | import { unRegisterSuperProperty } from './template/unRegisterSuperProperty.js' 19 | import { clearSuperProperties } from './template/clearSuperProperties.js' 20 | import { reset } from './template/reset.js' 21 | // import { push } from './template/push.js' 22 | import { getDistinctId } from './template/getDistinctId.js' 23 | 24 | export { 25 | pageView, 26 | profileSet, 27 | profileSetOnce, 28 | profileIncrement, 29 | profileAppend, 30 | profileUnset, 31 | profileDelete, 32 | alias, 33 | identify, 34 | track, 35 | registerSuperProperty, 36 | registerSuperProperties, 37 | getSuperProperty, 38 | getSuperProperties, 39 | unRegisterSuperProperty, 40 | clearSuperProperties, 41 | reset, 42 | freeApi, 43 | // push, 44 | getDistinctId, 45 | getPresetProperties 46 | } 47 | -------------------------------------------------------------------------------- /src/API/template/alias.js: -------------------------------------------------------------------------------- 1 | import { temp } from '../../lib/mergeRules/index.js' 2 | import { fillField, checkPrivate, resetCode } from '../../lib/fillField/index.js' 3 | import baseConfig from '../../lib/baseConfig/index.js' 4 | import { upLog } from '../../lib/upload/index.js' 5 | import Util from '../../lib/common/index.js' 6 | import Storage from '../../lib/storage/index.js' 7 | import { transporter, backParamsArray } from '../../lib/upload/hybrid.js' 8 | import { successLog } from '../../lib/printLog/index.js' 9 | function alias (aliasId, callback) { 10 | baseConfig.status.FnName = '$alias' 11 | resetCode() 12 | if (aliasId === Storage.getLocal('ARK_LOGINID')) { 13 | baseConfig.status.successCode = '20013' 14 | successLog() 15 | Util.paramType(callback) === 'Function' && callback.call(callback) 16 | return false 17 | } 18 | if (baseConfig.base.isHybrid === true) { 19 | var backParams = backParamsArray(aliasId, '', callback) 20 | var paramArray = backParams.argArray 21 | transporter('alias', paramArray, backParams.callback) 22 | return 23 | } 24 | // 检测aliasId 25 | var status = checkPrivate(aliasId, '$alias', true) 26 | 27 | if (!status) { 28 | Util.paramType(callback) === 'Function' && callback.call(callback) 29 | return 30 | } 31 | // if (distinctId) { 32 | // //检测distinctId 33 | // status = checkPrivate(distinctId, '$alias', true) 34 | // if (status) { 35 | // Storage.setLocal('ARK_TRACKID', distinctId) 36 | // } 37 | // } 38 | 39 | Storage.setLocal('ARK_LOGINID', aliasId) 40 | 41 | var aliasTemp = temp('$alias') 42 | var aliasLog = fillField(aliasTemp) 43 | 44 | // 去除空数据后上传数据 45 | upLog(Util.delEmpty(aliasLog), callback) 46 | 47 | if (baseConfig.base.autoProfile === true) { 48 | baseConfig.status.FnName = '$profile_set_once' 49 | var profileSetOnceTemp = temp('$profile_set_once') 50 | 51 | var profileSetOnceObj = fillField(profileSetOnceTemp) 52 | var time = Storage.getLocal('ARKFRISTPROFILE') || Util.format(new Date(), 'yyyy-MM-dd hh:mm:ss.SSS') 53 | var obj = { 54 | $first_visit_time: time, 55 | $first_visit_language: (navigator.language || navigator.browserLanguage).toLowerCase() 56 | } 57 | var profileSetOnceLog = Util.objMerge(profileSetOnceObj, { 58 | xcontext: obj 59 | }) 60 | // 去除空数据后上传数据 61 | upLog(Util.delEmpty(profileSetOnceLog)) 62 | Storage.setLocal('ARKFRISTPROFILE', time) 63 | } 64 | } 65 | export { 66 | alias 67 | } 68 | -------------------------------------------------------------------------------- /src/API/template/clearSuperProperties.js: -------------------------------------------------------------------------------- 1 | import { resetCode } from '../../lib/fillField/index.js' 2 | import { successLog } from '../../lib/printLog/index.js' 3 | import baseConfig from '../../lib/baseConfig/index.js' 4 | import Storage from '../../lib/storage/index.js' 5 | import Util from '../../lib/common/index.js' 6 | import { transporter, backParamsArray } from '../../lib/upload/hybrid.js' 7 | function clearSuperProperties (callback) { 8 | baseConfig.status.FnName = '$clearSuperProperties' 9 | resetCode() 10 | if (baseConfig.base.isHybrid === true) { 11 | var backParams = backParamsArray(callback) 12 | var paramArray = backParams.argArray 13 | transporter('clearSuperProperties', paramArray, backParams.callback) 14 | return 15 | } 16 | 17 | Storage.setLocal('ARKSUPER', {}) 18 | 19 | baseConfig.status.successCode = '20004' 20 | successLog() 21 | Util.paramType(callback) === 'Function' && callback.call(callback) 22 | } 23 | export { clearSuperProperties } 24 | -------------------------------------------------------------------------------- /src/API/template/freeApi.js: -------------------------------------------------------------------------------- 1 | import { temp } from '../../lib/mergeRules/index.js' 2 | import { fillField, resetCode } from '../../lib/fillField/index.js' 3 | import baseConfig from '../../lib/baseConfig/index.js' 4 | import { upLog } from '../../lib/upload/index.js' 5 | import Util from '../../lib/common/index.js' 6 | import Storage from '../../lib/storage/index.js' 7 | import { transporter, backParamsArray } from '../../lib/upload/hybrid.js' 8 | function freeApi (apiName, property) { 9 | 10 | baseConfig.status.FnName = apiName 11 | resetCode() 12 | var freeApiTemp = temp(apiName) 13 | if (!freeApiTemp) { 14 | return 15 | } 16 | if (baseConfig.base.isHybrid === true) { 17 | var hybridTemp = temp(apiName + 'base') 18 | var hybridLog = fillField(hybridTemp) 19 | var log = Util.delNotHybrid(Util.delEmpty(hybridLog.xcontext)) 20 | 21 | var backParams = backParamsArray(apiName, log) 22 | var paramArray = backParams.argArray 23 | transporter('track', paramArray) 24 | return 25 | } 26 | var freeApiLog = fillField(freeApiTemp) 27 | var arkSuper = Storage.getLocal('ARKSUPER') || {} 28 | if (Util.paramType(property) === 'Object') { 29 | arkSuper = Util.objMerge(arkSuper, property) 30 | } 31 | freeApiLog = Util.objMerge(freeApiLog, { xcontext: arkSuper }, {arrMerge: false}) 32 | 33 | upLog(Util.delEmpty(freeApiLog)) 34 | } 35 | export { freeApi } 36 | -------------------------------------------------------------------------------- /src/API/template/getDistinctId.js: -------------------------------------------------------------------------------- 1 | import { getUUId, getIdentifyId } from '../../lib/fillField/id.js' 2 | import Util from '../../lib/common/index.js' 3 | import baseConfig from '../../lib/baseConfig/index.js' 4 | import { transporter } from '../../lib/upload/hybrid.js' 5 | function getDistinctId (callback) { 6 | if (baseConfig.base.isHybrid === true) { 7 | var callbackFn = 'AnsCallback' + +new Date() 8 | window[callbackFn] = function () { 9 | callback.apply(callback, arguments) 10 | delete window[callbackFn] 11 | } 12 | transporter('getDistinctId', [], callbackFn) 13 | return 14 | } 15 | var id = getIdentifyId() || getUUId() 16 | if (Util.paramType(callback) === 'Function') { 17 | callback.call(callback, id) 18 | } 19 | return id 20 | } 21 | export { getDistinctId } 22 | -------------------------------------------------------------------------------- /src/API/template/getPresetProperties.js: -------------------------------------------------------------------------------- 1 | import { temp } from '../../lib/mergeRules/index.js' 2 | import { fillField, resetCode } from '../../lib/fillField/index.js' 3 | import baseConfig from '../../lib/baseConfig/index.js' 4 | import Util from '../../lib/common/index.js' 5 | import Storage from '../../lib/storage/index.js' 6 | import { transporter } from '../../lib/upload/hybrid.js' 7 | function getPresetProperties (callback) { 8 | baseConfig.status.FnName = '$getPresetProperties' 9 | resetCode() 10 | if (baseConfig.base.isHybrid === true) { 11 | var callbackFn = 'AnsCallback' + +new Date() 12 | window[callbackFn] = function () { 13 | callback.apply(callback, arguments) 14 | delete window[callbackFn] 15 | } 16 | transporter('getPresetProperties', [], callbackFn) 17 | return 18 | } 19 | // 检测aliasId 20 | var getPresetPropertiesTemp = temp('$getPresetProperties') 21 | var getPresetPropertiesLog = fillField(getPresetPropertiesTemp) 22 | getPresetPropertiesLog.xcontext.$first_visit_time = Storage.getLocal('ARKFRISTPROFILE') || '' 23 | delete getPresetPropertiesLog.xcontext.$is_login 24 | 25 | var presetPropertiesLog = Util.delEmpty(getPresetPropertiesLog.xcontext) 26 | if (Util.paramType(callback) === 'Function') { 27 | callback.call(callback, presetPropertiesLog) 28 | } 29 | return presetPropertiesLog 30 | } 31 | export { 32 | getPresetProperties 33 | } 34 | -------------------------------------------------------------------------------- /src/API/template/getSuperProperties.js: -------------------------------------------------------------------------------- 1 | import { resetCode } from '../../lib/fillField/index.js' 2 | import { successLog } from '../../lib/printLog/index.js' 3 | import baseConfig from '../../lib/baseConfig/index.js' 4 | import Storage from '../../lib/storage/index.js' 5 | import Util from '../../lib/common/index.js' 6 | import { transporter } from '../../lib/upload/hybrid.js' 7 | function getSuperProperties (callback) { 8 | baseConfig.status.FnName = '$getSuperProperties' 9 | resetCode() 10 | if (baseConfig.base.isHybrid === true) { 11 | var callbackFn = 'AnsCallback' + +new Date() 12 | window[callbackFn] = function () { 13 | callback.apply(callback, arguments) 14 | delete window[callbackFn] 15 | } 16 | transporter('getSuperProperties', [], callbackFn) 17 | return 18 | } 19 | var arkSuper = Storage.getLocal('ARKSUPER') || {} 20 | baseConfig.status.successCode = '20010' 21 | baseConfig.status.value = JSON.stringify(arkSuper) 22 | successLog() 23 | if (Util.paramType(callback) === 'Function') { 24 | callback.call(callback, arkSuper) 25 | } 26 | return arkSuper 27 | } 28 | export { getSuperProperties } 29 | -------------------------------------------------------------------------------- /src/API/template/getSuperProperty.js: -------------------------------------------------------------------------------- 1 | import { checkPrivate, resetCode } from '../../lib/fillField/index.js' 2 | import { successLog } from '../../lib/printLog/index.js' 3 | import baseConfig from '../../lib/baseConfig/index.js' 4 | import Storage from '../../lib/storage/index.js' 5 | import Util from '../../lib/common/index.js' 6 | import { backParamsArray, transporter } from '../../lib/upload/hybrid.js' 7 | function getSuperProperty (superPropertyName, callback) { 8 | baseConfig.status.FnName = '$getSuperProperty' 9 | resetCode() 10 | if (baseConfig.base.isHybrid === true) { 11 | var paramArray = backParamsArray(superPropertyName) 12 | var callbackFn = 'AnsCallback' + +new Date() 13 | window[callbackFn] = function () { 14 | callback.apply(callback, arguments) 15 | delete window[callbackFn] 16 | } 17 | transporter('getSuperProperty', paramArray.argArray, callbackFn) 18 | return 19 | } 20 | checkPrivate(superPropertyName, '$getSuperProperty', true) 21 | // if (!status) { 22 | // return 23 | // } 24 | var arkSuper = Storage.getLocal('ARKSUPER') || {} 25 | var superProperty = arkSuper[superPropertyName] 26 | 27 | if (!{}.hasOwnProperty.call(arkSuper, superPropertyName)) { 28 | baseConfig.status.successCode = '20009' 29 | superProperty = '' 30 | } else { 31 | baseConfig.status.successCode = '20010' 32 | baseConfig.status.value = superProperty 33 | } 34 | baseConfig.status.key = superPropertyName 35 | successLog() 36 | if (Util.paramType(callback) === 'Function') { 37 | callback.call(callback, superProperty) 38 | } 39 | return superProperty 40 | } 41 | export { getSuperProperty } 42 | -------------------------------------------------------------------------------- /src/API/template/identify.js: -------------------------------------------------------------------------------- 1 | import { checkPrivate, resetCode } from '../../lib/fillField/index.js' 2 | import { successLog } from '../../lib/printLog/index.js' 3 | import baseConfig from '../../lib/baseConfig/index.js' 4 | import Storage from '../../lib/storage/index.js' 5 | import Util from '../../lib/common/index.js' 6 | import { backParamsArray, transporter } from '../../lib/upload/hybrid.js' 7 | function identify (distinctId, isLogin, callback) { 8 | baseConfig.status.FnName = '$identify' 9 | resetCode() 10 | if (baseConfig.base.isHybrid === true) { 11 | var backParams = backParamsArray(distinctId, callback) 12 | var paramArray = backParams.argArray 13 | transporter('identify', paramArray, backParams.callback) 14 | return 15 | } 16 | var status = checkPrivate(distinctId, '$alias', true) 17 | if (!status) { 18 | return 19 | } 20 | if (Util.paramType(isLogin) === 'Boolean' && isLogin === true) { 21 | Storage.setLocal('ARK_TRACK_LOGIN', true) 22 | } else if (Util.paramType(isLogin) === 'Function') { 23 | callback = isLogin 24 | } 25 | 26 | Storage.setLocal('ARK_TRACKID', distinctId) 27 | Storage.setCookie('ARK_ID', distinctId) 28 | baseConfig.status.successCode = '20002' 29 | baseConfig.status.value = distinctId 30 | successLog() 31 | if (Util.paramType(callback) === 'Function') { 32 | callback.call(callback) 33 | } 34 | if (window.AnalysysModal && typeof (window.AnalysysModal) === 'function') { 35 | window.AnalysysModal([{ xwhat: '$identify', xwho: distinctId }]) 36 | } 37 | } 38 | export { identify } 39 | -------------------------------------------------------------------------------- /src/API/template/pageView.js: -------------------------------------------------------------------------------- 1 | import { temp } from '../../lib/mergeRules/index.js' 2 | import { fillField, checkPrivate, resetCode } from '../../lib/fillField/index.js' 3 | import { setReferrer } from '../../lib/fillField/getField.js' 4 | import baseConfig from '../../lib/baseConfig/index.js' 5 | import { upLog } from '../../lib/upload/index.js' 6 | import Util from '../../lib/common/index.js' 7 | import Storage from '../../lib/storage/index.js' 8 | import { transporter, backParamsArray } from '../../lib/upload/hybrid.js' 9 | 10 | var pageCloseStatus = false 11 | var pageUrl = window.location.href 12 | 13 | /** 14 | * @method pageView 统计页面事件 15 | * 第一个参数为页面名称 类型:String 16 | * 第二个参数为自定义属性 类型:Object/Function 17 | * 第三个参数为回调函数 类型:Function 18 | * 示例: 19 | * AnalysysAgent.pageView('首页') 20 | * AnalysysAgent.pageView('首页',{ 'commodityName': 'iPhone'}) 21 | * AnalysysAgent.pageView('首页',{ 22 | * 'commodityName': function(){ 23 | * return 'iPhone' 24 | * } 25 | * }) 26 | * AnalysysAgent.pageView('首页',{ 27 | * 'commodityName': function(){ 28 | * return 'iPhone' 29 | * } 30 | * },function(){ 31 | * console.log('上报日志成功') 32 | * }) 33 | * @param {String} pageName 34 | * @param {Object} obj 35 | * @param {function} callback 36 | */ 37 | function pageView (pageName, obj, callback) { 38 | var log = pageViewLog(pageName, obj, callback) 39 | 40 | // 去除空数据后上传数据 41 | upLog(log, callback) 42 | } 43 | 44 | function pageViewLog (p, o, c) { 45 | var pageName = p 46 | var obj = o 47 | var callback = c 48 | // 页面关闭组件发送 49 | if (window.AnalysysModule && window.AnalysysModule.pageClose) { 50 | if (pageCloseStatus === true) { 51 | window.AnalysysModule.pageClose.pageEndTrack() 52 | } else { 53 | pageCloseStatus = true 54 | } 55 | if (Util.paramType(pageName) === 'String') { 56 | window.AnalysysModule.pageClose.createTime(+new Date(), pageName) 57 | } else { 58 | window.AnalysysModule.pageClose.createTime(+new Date()) 59 | } 60 | } 61 | 62 | baseConfig.status.FnName = '$pageview' 63 | resetCode() 64 | var nameObj = {} 65 | if (Util.paramType(pageName) === 'String') { 66 | nameObj = { 67 | $title: pageName 68 | } 69 | checkPrivate(nameObj) 70 | } else if (Util.paramType(pageName) === 'Object') { 71 | if (Util.paramType(obj) === 'Function') { 72 | callback = obj 73 | } 74 | obj = pageName 75 | pageName = '' 76 | } else if (Util.paramType(pageName) === 'Function') { 77 | callback = pageName 78 | obj = '' 79 | pageName = '' 80 | } 81 | if (Util.paramType(obj) === 'Function') { 82 | callback = obj 83 | obj = '' 84 | } 85 | var userProp = {} 86 | 87 | if (Util.paramType(obj) === 'Object') { 88 | for (var key in obj) { 89 | if (Util.paramType(obj[key]) === 'Function') { 90 | obj[key] = obj[key].call(obj[key]) 91 | } 92 | } 93 | // 检测用户自定义属性 94 | if (baseConfig.base.isHybrid === false) { 95 | checkPrivate(obj) 96 | } 97 | userProp = { 98 | xcontext: obj || {} 99 | } 100 | } 101 | 102 | var arkSuper = Storage.getLocal('ARKSUPER') || {} 103 | if (baseConfig.base.isHybrid === true) { 104 | arkSuper = {} 105 | } 106 | /** 107 | * 超级属性与用户自定义属性合并 108 | */ 109 | var xcontext = Util.objMerge({ 110 | xcontext: arkSuper 111 | }, userProp, {arrMerge: false}) 112 | /** 113 | * 与$pagename属性合并 114 | */ 115 | xcontext = Util.objMerge(xcontext, { 116 | xcontext: nameObj 117 | }) 118 | 119 | var pageViewTemp = temp('$pageview') 120 | var pageViewObj = Util.delEmpty(fillField(pageViewTemp)) 121 | if (baseConfig.base.isHybrid === true) { 122 | pageViewTemp = temp('$pageviewbase') 123 | pageViewObj = Util.delEmpty(fillField(pageViewTemp)) 124 | var hybridPageViewLog = Util.objMerge(pageViewObj, xcontext) 125 | hybridPageViewLog = Util.delNotHybrid(Util.delEmpty(hybridPageViewLog.xcontext)) 126 | var backParams = backParamsArray(pageName || '', hybridPageViewLog, callback) 127 | var paramArray = backParams.argArray 128 | transporter('pageView', paramArray, backParams.callback) 129 | setReferrer(pageUrl) 130 | 131 | return 132 | } 133 | 134 | setReferrer(pageUrl) 135 | /** 136 | * 自动采集与个性化属性合并 137 | */ 138 | return Util.objMerge(pageViewObj, xcontext) 139 | } 140 | 141 | 142 | function hashPageView () { 143 | Util.changeHash(function () { 144 | if (pageUrl !== window.location.href) { 145 | pageUrl = window.location.href 146 | /** 147 | * 判断黑白名单 148 | * 符合黑名单,不上报 149 | * 有白名单,且不符合白名单,不上报 150 | */ 151 | var listStatus = false 152 | if (baseConfig.base.pageViewWhiteList && Util.checkTypeList(baseConfig.base.pageViewWhiteList)) { 153 | listStatus = true 154 | } else if (!Util.checkTypeList(baseConfig.base.pageViewBlackList)) { 155 | listStatus = true 156 | } 157 | if (listStatus === true) { 158 | pageView() 159 | } 160 | } 161 | }) 162 | } 163 | export { pageView, hashPageView, pageViewLog } 164 | -------------------------------------------------------------------------------- /src/API/template/profileAppend.js: -------------------------------------------------------------------------------- 1 | import { temp } from '../../lib/mergeRules/index.js' 2 | import { fillField, checkPrivate, resetCode } from '../../lib/fillField/index.js' 3 | import baseConfig from '../../lib/baseConfig/index.js' 4 | import { upLog } from '../../lib/upload/index.js' 5 | import Util from '../../lib/common/index.js' 6 | import { backParamsArray, transporter } from '../../lib/upload/hybrid.js' 7 | 8 | function profileAppend (key, value, callback) { 9 | baseConfig.status.FnName = '$profile_append' 10 | resetCode() 11 | 12 | if (Util.paramType(key) === 'Object' && Util.paramType(value) === 'Function') { 13 | callback = value 14 | value = '' 15 | } else if (Util.paramType(key) === 'String' && Util.paramType(value) === 'Function') { 16 | value = value.call(value) 17 | } 18 | var obj = Util.toObj(key, value) 19 | for (var itemKey in obj) { 20 | if (Util.paramType(obj[itemKey]) === 'Function') { 21 | obj[itemKey] = obj[itemKey].call(obj[itemKey]) 22 | } 23 | } 24 | 25 | if (baseConfig.base.isHybrid === true) { 26 | var backParams = backParamsArray(key, value, callback) 27 | var paramArray = backParams.argArray 28 | transporter('profileAppend', paramArray, backParams.callback) 29 | return 30 | } 31 | checkPrivate(obj, '$profile_append') 32 | 33 | var profileAppendTemp = temp('$profile_append') 34 | 35 | var profileAppendObj = Util.delEmpty(fillField(profileAppendTemp)) 36 | 37 | var profileAppendLog = Util.objMerge(profileAppendObj, { xcontext: obj }) 38 | 39 | // 如字段中有不合法内容则打印错误日志 40 | // if (!profileAppendLog) { 41 | // errorLog() 42 | // return 43 | // } 44 | // 去除空数据后上传数据 45 | upLog(profileAppendLog, callback) 46 | } 47 | export { profileAppend } 48 | -------------------------------------------------------------------------------- /src/API/template/profileDelete.js: -------------------------------------------------------------------------------- 1 | import { temp } from '../../lib/mergeRules/index.js' 2 | import { fillField, resetCode } from '../../lib/fillField/index.js' 3 | import baseConfig from '../../lib/baseConfig/index.js' 4 | import { upLog } from '../../lib/upload/index.js' 5 | import { transporter } from '../../lib/upload/hybrid.js' 6 | 7 | function profileDelete (callback) { 8 | baseConfig.status.FnName = '$profile_delete' 9 | resetCode() 10 | if (baseConfig.base.isHybrid === true) { 11 | transporter('profileDelete', [], callback) 12 | return 13 | } 14 | var profileDeleteTemp = temp('$profile_delete') 15 | 16 | var profileDeleteLog = fillField(profileDeleteTemp) 17 | 18 | // 如字段中有不合法内容则打印错误日志 19 | // if (!profileDeleteLog) { 20 | // errorLog() 21 | // return 22 | // } 23 | // 去除空数据后上传数据 24 | upLog(profileDeleteLog, callback) 25 | } 26 | export { profileDelete } 27 | -------------------------------------------------------------------------------- /src/API/template/profileIncrement.js: -------------------------------------------------------------------------------- 1 | import { temp } from '../../lib/mergeRules/index.js' 2 | import { fillField, checkPrivate, resetCode } from '../../lib/fillField/index.js' 3 | import baseConfig from '../../lib/baseConfig/index.js' 4 | import { upLog } from '../../lib/upload/index.js' 5 | import Util from '../../lib/common/index.js' 6 | import { backParamsArray, transporter } from '../../lib/upload/hybrid.js' 7 | function profileIncrement (key, value, callback) { 8 | baseConfig.status.FnName = '$profile_increment' 9 | resetCode() 10 | 11 | if (Util.paramType(key) === 'Object' && Util.paramType(value) === 'Function') { 12 | callback = value 13 | value = '' 14 | } else if (Util.paramType(key) === 'String' && Util.paramType(value) === 'Function') { 15 | value = value.call(value) 16 | } 17 | var obj = Util.toObj(key, value) 18 | 19 | for (var itemKey in obj) { 20 | if (Util.paramType(obj[itemKey]) === 'Function') { 21 | obj[itemKey] = obj[itemKey].call(obj[itemKey]) 22 | } 23 | } 24 | if (baseConfig.base.isHybrid === true) { 25 | var backParams = backParamsArray(key, value, callback) 26 | var paramArray = backParams.argArray 27 | transporter('profileIncrement', paramArray, backParams.callback) 28 | return 29 | } 30 | checkPrivate(obj, '$profile_increment') 31 | 32 | var profileIncrementTemp = temp('$profile_increment') 33 | 34 | var profileIncrementObj = Util.delEmpty(fillField(profileIncrementTemp)) 35 | 36 | var profileIncrementLog = Util.objMerge(profileIncrementObj, { xcontext: obj }) 37 | 38 | // 如字段中有不合法内容则打印错误日志 39 | // if (!profileIncrementLog) { 40 | // errorLog() 41 | // return 42 | // } 43 | // 去除空数据后上传数据 44 | upLog(profileIncrementLog, callback) 45 | } 46 | export { profileIncrement } 47 | -------------------------------------------------------------------------------- /src/API/template/profileSet.js: -------------------------------------------------------------------------------- 1 | import { temp } from '../../lib/mergeRules/index.js' 2 | import { fillField, checkPrivate, resetCode } from '../../lib/fillField/index.js' 3 | import baseConfig from '../../lib/baseConfig/index.js' 4 | import { upLog } from '../../lib/upload/index.js' 5 | import Util from '../../lib/common/index.js' 6 | import { backParamsArray, transporter } from '../../lib/upload/hybrid.js' 7 | function profileSet (key, value, callback) { 8 | baseConfig.status.FnName = '$profile_set' 9 | resetCode() 10 | if (Util.paramType(key) === 'Object' && Util.paramType(value) === 'Function') { 11 | callback = value 12 | value = '' 13 | } else if (Util.paramType(key) === 'String' && Util.paramType(value) === 'Function') { 14 | value = value.call(value) 15 | } 16 | var obj = Util.toObj(key, value) 17 | 18 | for (var itemKey in obj) { 19 | if (Util.paramType(obj[itemKey]) === 'Function') { 20 | obj[itemKey] = obj[itemKey].call(obj[itemKey]) 21 | } 22 | } 23 | if (baseConfig.base.isHybrid === true) { 24 | var backParams = backParamsArray(key, value, callback) 25 | var paramArray = backParams.argArray 26 | transporter('profileSet', paramArray, backParams.callback) 27 | return 28 | } 29 | checkPrivate(obj, '$profile_set') 30 | 31 | var profileSetTemp = temp('$profile_set') 32 | 33 | var profileSetObj = Util.delEmpty(fillField(profileSetTemp)) 34 | 35 | var profileSetLog = Util.objMerge(profileSetObj, { xcontext: obj }) 36 | 37 | // 如字段中有不合法内容则打印错误日志 38 | // if (!profileSetLog) { 39 | // errorLog() 40 | // return 41 | // } 42 | // 去除空数据后上传数据 43 | upLog(profileSetLog, callback) 44 | } 45 | export { profileSet } 46 | -------------------------------------------------------------------------------- /src/API/template/profileSetOnce.js: -------------------------------------------------------------------------------- 1 | import { temp } from '../../lib/mergeRules/index.js' 2 | import { fillField, checkPrivate, resetCode } from '../../lib/fillField/index.js' 3 | import baseConfig from '../../lib/baseConfig/index.js' 4 | import { upLog } from '../../lib/upload/index.js' 5 | import Util from '../../lib/common/index.js' 6 | import { backParamsArray, transporter } from '../../lib/upload/hybrid.js' 7 | function profileSetOnce (key, value, callback) { 8 | baseConfig.status.FnName = '$profile_set_once' 9 | resetCode() 10 | if (Util.paramType(key) === 'Object' && Util.paramType(value) === 'Function') { 11 | callback = value 12 | value = '' 13 | } else if (Util.paramType(key) === 'String' && Util.paramType(value) === 'Function') { 14 | value = value.call(value) 15 | } 16 | var obj = Util.toObj(key, value) 17 | 18 | for (var itemKey in obj) { 19 | if (Util.paramType(obj[itemKey]) === 'Function') { 20 | obj[itemKey] = obj[itemKey].call(obj[itemKey]) 21 | } 22 | } 23 | if (baseConfig.base.isHybrid === true) { 24 | var backParams = backParamsArray(obj, callback) 25 | var paramArray = backParams.argArray 26 | transporter('profileSetOnce', paramArray, backParams.callback) 27 | return 28 | } 29 | checkPrivate(obj, '$profile_set_once') 30 | 31 | var profileSetOnceTemp = temp('$profile_set_once') 32 | 33 | var profileSetOnceObj = Util.delEmpty(fillField(profileSetOnceTemp)) 34 | 35 | var profileSetOnceLog = Util.objMerge(profileSetOnceObj, { xcontext: obj }) 36 | 37 | // 如字段中有不合法内容则打印错误日志 38 | // if (!profileSetOnceLog) { 39 | // errorLog() 40 | // return 41 | // } 42 | // 去除空数据后上传数据 43 | upLog(profileSetOnceLog, callback) 44 | } 45 | export { profileSetOnce } 46 | -------------------------------------------------------------------------------- /src/API/template/profileUnset.js: -------------------------------------------------------------------------------- 1 | import { temp } from '../../lib/mergeRules/index.js' 2 | import { fillField, checkPrivate, resetCode } from '../../lib/fillField/index.js' 3 | import baseConfig from '../../lib/baseConfig/index.js' 4 | import { upLog } from '../../lib/upload/index.js' 5 | import Util from '../../lib/common/index.js' 6 | import { backParamsArray, transporter } from '../../lib/upload/hybrid.js' 7 | function profileUnset (key, callback) { 8 | baseConfig.status.FnName = '$profile_unset' 9 | resetCode() 10 | if (Util.paramType(key) === 'Function') { 11 | key = key.call(key) 12 | } 13 | checkPrivate(key, '$profile_unset', key) 14 | var obj = Util.toObj(key, '') 15 | if (baseConfig.base.isHybrid === true) { 16 | var backParams = backParamsArray(key, callback) 17 | var paramArray = backParams.argArray 18 | transporter('profileUnset', paramArray, backParams.callback) 19 | return 20 | } 21 | checkPrivate(obj, '$profile_unset') 22 | 23 | var profileUnsetTemp = temp('$profile_unset') 24 | 25 | var profileUnsetObj = fillField(profileUnsetTemp) 26 | 27 | var profileUnsetLog = Util.objMerge(profileUnsetObj, { xcontext: obj }) 28 | 29 | // 如字段中有不合法内容则打印错误日志 30 | // if (!profileUnsetLog) { 31 | // errorLog() 32 | // return 33 | // } 34 | // 去除空数据后上传数据 35 | upLog(profileUnsetLog, callback) 36 | } 37 | export { profileUnset } 38 | -------------------------------------------------------------------------------- /src/API/template/registerSuperProperties.js: -------------------------------------------------------------------------------- 1 | import { checkPrivate, resetCode } from '../../lib/fillField/index.js' 2 | import { successLog } from '../../lib/printLog/index.js' 3 | import baseConfig from '../../lib/baseConfig/index.js' 4 | import Util from '../../lib/common/index.js' 5 | import Storage from '../../lib/storage/index.js' 6 | import { backParamsArray, transporter } from '../../lib/upload/hybrid.js' 7 | function registerSuperProperties (key, value, callback) { 8 | baseConfig.status.FnName = '$registerSuperProperties' 9 | resetCode() 10 | if (Util.paramType(key) === 'Object' && Util.paramType(value) === 'Function') { 11 | callback = value 12 | value = '' 13 | } else if (Util.paramType(key) === 'String' && Util.paramType(value) === 'Function') { 14 | value = value.call(value) 15 | } 16 | var obj = Util.toObj(key, value) 17 | for (var itemKey in obj) { 18 | if (Util.paramType(obj[itemKey]) === 'Function') { 19 | obj[itemKey] = obj[itemKey].call(obj[itemKey]) 20 | } 21 | } 22 | if (baseConfig.base.isHybrid === true) { 23 | var backParams = backParamsArray(key, value, callback) 24 | var paramArray = backParams.argArray 25 | transporter('registerSuperProperties', paramArray, backParams.callback) 26 | return 27 | } 28 | checkPrivate(obj, '$registerSuperProperties') 29 | 30 | var arkSuper = Storage.getLocal('ARKSUPER') || {} 31 | // obj = Util.delEmpty(obj) 32 | var saveArkSuper = Util.objMerge(arkSuper, obj, { 33 | arrMerge: false 34 | }) 35 | Storage.setLocal('ARKSUPER', saveArkSuper) 36 | 37 | baseConfig.status.successCode = '20002' 38 | baseConfig.status.value = JSON.stringify(obj) 39 | successLog() 40 | Util.paramType(callback) === 'Function' && callback.call(callback) 41 | } 42 | export { registerSuperProperties } 43 | -------------------------------------------------------------------------------- /src/API/template/registerSuperProperty.js: -------------------------------------------------------------------------------- 1 | import { checkPrivate, resetCode } from '../../lib/fillField/index.js' 2 | import { successLog } from '../../lib/printLog/index.js' 3 | import baseConfig from '../../lib/baseConfig/index.js' 4 | import Util from '../../lib/common/index.js' 5 | import Storage from '../../lib/storage/index.js' 6 | import { backParamsArray, transporter } from '../../lib/upload/hybrid.js' 7 | function registerSuperProperty (key, value, callback) { 8 | baseConfig.status.FnName = '$registerSuperProperty' 9 | resetCode() 10 | if (Util.paramType(key) === 'Object' && Util.paramType(value) === 'Function') { 11 | callback = value 12 | value = '' 13 | } else if (Util.paramType(key) === 'String' && Util.paramType(value) === 'Function') { 14 | value = value.call(value) 15 | } 16 | var obj = Util.toObj(key, value) 17 | for (var itemKey in obj) { 18 | if (Util.paramType(obj[itemKey]) === 'Function') { 19 | obj[itemKey] = obj[itemKey].call(obj[itemKey]) 20 | } 21 | } 22 | if (baseConfig.base.isHybrid === true) { 23 | var backParams = backParamsArray(key, value, callback) 24 | var paramArray = backParams.argArray 25 | transporter('registerSuperProperty', paramArray, backParams.callback) 26 | return 27 | } 28 | checkPrivate(obj, '$registerSuperProperty') 29 | // obj = Util.delEmpty(obj) 30 | var arkSuper = Storage.getLocal('ARKSUPER') || {} 31 | var saveArkSuper = Util.objMerge(arkSuper, obj, { 32 | arrMerge: false 33 | }) 34 | Storage.setLocal('ARKSUPER', saveArkSuper) 35 | baseConfig.status.successCode = '20002' 36 | baseConfig.status.value = JSON.stringify(obj) 37 | successLog() 38 | Util.paramType(callback) === 'Function' && callback.call(callback) 39 | } 40 | export { registerSuperProperty } 41 | -------------------------------------------------------------------------------- /src/API/template/reset.js: -------------------------------------------------------------------------------- 1 | import sessionId from '../../lib/fillField/sessionId.js' 2 | import { clearSuperProperties } from './clearSuperProperties.js' 3 | import baseConfig from '../../lib/baseConfig/index.js' 4 | import { successLog } from '../../lib/printLog/index.js' 5 | import Util from '../../lib/common/index.js' 6 | import { resetCode, clearCache } from '../../lib/fillField/index.js' 7 | import { removeUUId } from '../../lib/fillField/id.js' 8 | import { profileSetOnce } from './profileSetOnce.js' 9 | import { transporter } from '../../lib/upload/hybrid.js' 10 | function reset (callback) { 11 | if (baseConfig.base.isHybrid === true) { 12 | transporter('reset', [], callback) 13 | return 14 | } 15 | resetCode() 16 | removeUUId() 17 | clearSuperProperties() 18 | clearCache(true) 19 | sessionId.setId() 20 | if (baseConfig.base.autoProfile === true) { 21 | var resetTime = { 22 | $reset_time: Util.format(new Date(), 'yyyy-MM-dd hh:mm:ss.SSS') 23 | } 24 | profileSetOnce(resetTime, callback) 25 | } else { 26 | if (Util.paramType(callback) === 'Function') { 27 | callback.call(callback) 28 | } 29 | } 30 | baseConfig.status.FnName = '$reset' 31 | baseConfig.status.successCode = '20005' 32 | successLog() 33 | } 34 | export { reset } 35 | -------------------------------------------------------------------------------- /src/API/template/startUp.js: -------------------------------------------------------------------------------- 1 | import { temp } from '../../lib/mergeRules/index.js' 2 | import { fillField, isStartUp, checkBase } from '../../lib/fillField/index.js' 3 | import { errorLog } from '../../lib/printLog/index.js' 4 | import baseConfig from '../../lib/baseConfig/index.js' 5 | import { upLog } from '../../lib/upload/index.js' 6 | import Util from '../../lib/common/index.js' 7 | import { hashPageView } from './pageView.js' 8 | import Storage from '../../lib/storage/index.js' 9 | import { pageViewLog } from './pageView.js' 10 | 11 | function startUp () { 12 | var log = [] 13 | // 启动前检测appkey、debugModel、uploadURL参数是否合法 14 | if (baseConfig.base.isHybrid === false && !checkBase()) { 15 | errorLog() 16 | return 17 | } 18 | var arkSuper = Storage.getLocal('ARKSUPER') || {} 19 | // 检测启动前状态,appid,debugModel,uploadURL是否存在修改 20 | // 判断是否是已启动 21 | // 如已启动则不发送启动日志 22 | if (baseConfig.base.isHybrid === false && isStartUp() === false) { 23 | var startUpStatus = true 24 | if (Util.checkTypeList(baseConfig.base.startUpBlackList) || (baseConfig.base.startUpWhiteList && !Util.checkTypeList(baseConfig.base.startUpWhiteList))) { 25 | startUpStatus = false 26 | } 27 | if (startUpStatus === true) { 28 | baseConfig.status.FnName = '$startup' 29 | // 更新当前所在事件 30 | // baseConfig.status.FnName = '$startup' 31 | 32 | // 获取事件日志模板 33 | var startUpTemp = temp('$startup') 34 | // 验证及填充日志模板中字段内容 35 | // 如未通过验证则返回值为fasle 36 | var startUpLog = fillField(startUpTemp) 37 | 38 | /** 39 | * 超级属性优先于自动采集属性 40 | */ 41 | startUpLog = Util.objMerge(startUpLog, { 42 | xcontext: arkSuper 43 | }, {arrMerge: false}) 44 | log.push(Util.delEmpty(startUpLog)) 45 | } 46 | } 47 | 48 | // 自动采集首次用户属性 49 | var fristProfile = Storage.getLocal('ARKFRISTPROFILE') || false 50 | if (baseConfig.base.isHybrid === false && baseConfig.base.autoProfile === true && !fristProfile) { 51 | baseConfig.status.FnName = '$profile_set_once' 52 | var profileSetOnceTemp = temp('$profile_set_once') 53 | 54 | var profileSetOnceObj = fillField(profileSetOnceTemp) 55 | var time = Storage.getLocal('ARKFRISTPROFILE') || Util.format(new Date(), 'yyyy-MM-dd hh:mm:ss.SSS') 56 | var obj = { 57 | $first_visit_time: time, 58 | $first_visit_language: (navigator.language || navigator.browserLanguage).toLowerCase() 59 | } 60 | /** 61 | * 自定义属性优先于自动采集属性 62 | */ 63 | var profileSetOnceLog = Util.objMerge(profileSetOnceObj, { 64 | xcontext: obj 65 | }) 66 | log.push(Util.delEmpty(profileSetOnceLog)) 67 | Storage.setLocal('ARKFRISTPROFILE', time) 68 | } 69 | 70 | // 自动采集页面 71 | if (baseConfig.base.auto === true) { 72 | /** 73 | * 判断黑白名单 74 | * 符合黑名单,不上报 75 | * 有白名单,且不符合白名单,不上报 76 | */ 77 | var listStatus = false 78 | if (baseConfig.base.pageViewWhiteList && Util.checkTypeList(baseConfig.base.pageViewWhiteList)) { 79 | listStatus = true 80 | } else if (!Util.checkTypeList(baseConfig.base.pageViewBlackList)) { 81 | listStatus = true 82 | } 83 | if (listStatus === true) { 84 | var pageLog = pageViewLog(baseConfig.base.pageProperty) 85 | 86 | log.push(pageLog) 87 | } 88 | // 开启hash跳转 89 | if (baseConfig.base.hash === true || baseConfig.base.singlePage === true) { 90 | hashPageView() 91 | } 92 | } 93 | if (log.length > 0) { 94 | upLog(log) 95 | } 96 | // 校准时间 97 | } 98 | export { startUp } 99 | -------------------------------------------------------------------------------- /src/API/template/track.js: -------------------------------------------------------------------------------- 1 | import { temp } from '../../lib/mergeRules/index.js' 2 | import { fillField, checkPrivate, resetCode } from '../../lib/fillField/index.js' 3 | import baseConfig from '../../lib/baseConfig/index.js' 4 | import { upLog } from '../../lib/upload/index.js' 5 | import Util from '../../lib/common/index.js' 6 | import Storage from '../../lib/storage/index.js' 7 | import { transporter, backParamsArray } from '../../lib/upload/hybrid.js' 8 | function track (eventName, obj, callback) { 9 | baseConfig.status.FnName = eventName || '$track' 10 | resetCode() 11 | checkPrivate(eventName, '$track', true) 12 | baseConfig.status.FnName = eventName 13 | var userProp = {} 14 | if (Util.paramType(obj) === 'Function') { 15 | callback = obj 16 | obj = {} 17 | } 18 | if (Util.paramType(obj) === 'Object') { 19 | for (var itemKey in obj) { 20 | if (Util.paramType(obj[itemKey]) === 'Function') { 21 | obj[itemKey] = obj[itemKey].call(obj[itemKey]) 22 | } 23 | } 24 | checkPrivate(obj) 25 | userProp = { 26 | xcontext: obj 27 | } 28 | } 29 | var arkSuper = Storage.getLocal('ARKSUPER') || {} 30 | 31 | /** 32 | * 用户自定义属性优先于超级属性 33 | */ 34 | 35 | var xcontext = Util.objMerge({ 36 | xcontext: arkSuper 37 | }, userProp, {arrMerge: false}) 38 | if (baseConfig.base.isHybrid === true) { 39 | var trackHybridTemp = temp('$trackbase') 40 | var trackHybridObj = fillField(trackHybridTemp) 41 | trackHybridObj = Util.delEmpty(trackHybridObj) 42 | var hybridPageViewLog = Util.objMerge(trackHybridObj, xcontext) 43 | hybridPageViewLog = Util.delNotHybrid(Util.delEmpty(hybridPageViewLog.xcontext)) 44 | var backParams = backParamsArray(eventName, hybridPageViewLog, callback) 45 | var paramArray = backParams.argArray 46 | // paramArray.postion = elePostionObj || null 47 | transporter('track', paramArray, backParams.callback) 48 | // window.AnalysysAgentHybrid.track(eventName, JSON.stringify(userProp.xcontext), JSON.stringify(elePostionObj)) 49 | return 50 | } 51 | 52 | var trackTemp = temp('$track') 53 | var trackObj = fillField(trackTemp) 54 | /** 55 | * 去空逻辑,不对xwhat进行去空 56 | */ 57 | trackObj.xcontext = Util.delEmpty(trackObj.xcontext) 58 | /** 59 | * 自定义属性优先于自动采集属性 60 | */ 61 | var trackLog = Util.objMerge(trackObj, xcontext, {arrMerge: false}) 62 | 63 | // 去除空数据后上传数据 64 | upLog(trackLog, callback) 65 | } 66 | export { track } 67 | -------------------------------------------------------------------------------- /src/API/template/unRegisterSuperProperty.js: -------------------------------------------------------------------------------- 1 | import { checkPrivate, resetCode } from '../../lib/fillField/index.js' 2 | import { successLog } from '../../lib/printLog/index.js' 3 | import baseConfig from '../../lib/baseConfig/index.js' 4 | import Storage from '../../lib/storage/index.js' 5 | import Util from '../../lib/common/index.js' 6 | import { backParamsArray, transporter } from '../../lib/upload/hybrid.js' 7 | function unRegisterSuperProperty (superPropertyName, callback) { 8 | baseConfig.status.FnName = '$unregisterSuperProperty' 9 | resetCode() 10 | if (baseConfig.base.isHybrid === true) { 11 | var backParams = backParamsArray.apply(superPropertyName, arguments) 12 | var paramArray = backParams.argArray 13 | transporter('unRegisterSuperProperty', paramArray, backParams.callback) 14 | return 15 | } 16 | checkPrivate(superPropertyName, '$unregisterSuperProperty', true) 17 | var arkSuper = Storage.getLocal('ARKSUPER') || {} 18 | if (!Object.prototype.hasOwnProperty.call(arkSuper, superPropertyName)) { 19 | baseConfig.status.successCode = '20011' 20 | } else { 21 | delete arkSuper[superPropertyName] 22 | Storage.setLocal('ARKSUPER', arkSuper) 23 | baseConfig.status.successCode = '20003' 24 | } 25 | baseConfig.status.value = superPropertyName 26 | successLog() 27 | Util.paramType(callback) === 'Function' && callback.call(callback) 28 | } 29 | export { unRegisterSuperProperty } 30 | -------------------------------------------------------------------------------- /src/configure/base/fieldRules.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 字段填充、字段校验规则模板 3 | * 4 | * ReservedKeywords:不可覆盖字段集合 5 | * 6 | * valueType:获取字段值的方式 0:函数获取 1:默认值 7 | * 8 | * value:根据valueType规则填充字段对应取值 9 | * 10 | * checkList:数据合法检测方法列表,每个方法返回bool值,以用户为准,同名覆盖 11 | * 12 | */ 13 | import { 14 | getAppId, 15 | getUploadURL, 16 | getId, 17 | nowDate, 18 | getXwhat, 19 | getDebugMode, 20 | isLogin, 21 | getLibVersion, 22 | timeZone, 23 | language, 24 | getSessionId, 25 | isFirstTime, 26 | isFirstDay, 27 | originalId, 28 | getReferrer, 29 | getReferrerDomain, 30 | getTitle, 31 | getUrl, 32 | getScreenWidth, 33 | getScreenHeight, 34 | startupTime, 35 | checkSpider, 36 | utmCampaignId, 37 | utmSource, 38 | utmMedium, 39 | utmTerm, 40 | utmContent, 41 | utmCampaign, 42 | timeCalibration 43 | } from '../../lib/fillField/getField.js' 44 | 45 | export default { 46 | resetKeywords: [ 47 | 'appid', 48 | '$debug', 49 | 'uploadUrl' 50 | ], 51 | uploadURL: { 52 | valueType: 0, 53 | value: getUploadURL, 54 | check: { 55 | value: ['isString', 'nimLength', 'isUrl'], 56 | errorCode: '60007', 57 | successCode: '20008' 58 | } 59 | }, 60 | appid: { 61 | valueType: 0, 62 | value: getAppId, 63 | check: { 64 | value: ['isString', 'nimLength'], 65 | errorCode: '60006', 66 | successCode: '20006' 67 | } 68 | }, 69 | hash: { 70 | check: { 71 | value: ['isBoolean'], 72 | errorCode: '60003' 73 | } 74 | }, 75 | auto: { 76 | check: { 77 | value: ['isBoolean'], 78 | errorCode: '60003' 79 | } 80 | }, 81 | autoProfile: { 82 | check: { 83 | value: ['isBoolean'], 84 | errorCode: '60003' 85 | } 86 | }, 87 | pageProperty: { 88 | check: { 89 | value: ['isObject'], 90 | errorCode: '600016' 91 | } 92 | }, 93 | xwho: { 94 | valueType: 0, 95 | value: getId, 96 | check: { 97 | value: ['isString', 'nimLength'] 98 | } 99 | }, 100 | xwhen: { 101 | valueType: 0, 102 | value: nowDate 103 | }, 104 | 105 | xwhat: { 106 | valueType: 0, 107 | value: getXwhat, 108 | check: { 109 | value: ['isString', 'nimLength'] 110 | } 111 | }, 112 | 113 | xcontext: { 114 | $lib: { 115 | valueType: 1, 116 | value: 'JS' 117 | }, 118 | $lib_version: { 119 | valueType: 0, 120 | value: getLibVersion, 121 | check: { 122 | value: ['isString'], 123 | successCode: '20007' 124 | } 125 | }, 126 | $platform: { 127 | valueType: 1, 128 | value: 'JS' 129 | }, 130 | $debug: { 131 | valueType: 0, 132 | value: getDebugMode, 133 | check: { 134 | value: ['isNumber', 'isDebug'] 135 | } 136 | }, 137 | $is_login: { 138 | valueType: 0, 139 | value: isLogin, 140 | check: { 141 | value: ['isBoolean'] 142 | } 143 | }, 144 | $screen_width: { 145 | valueType: 0, 146 | value: getScreenWidth, 147 | check: { 148 | value: ['isNumber'] 149 | } 150 | }, 151 | $screen_height: { 152 | valueType: 0, 153 | value: getScreenHeight, 154 | check: { 155 | value: ['isNumber'] 156 | } 157 | }, 158 | 159 | $time_zone: { 160 | valueType: 1, 161 | value: timeZone 162 | }, 163 | $language: { 164 | valueType: 1, 165 | value: language 166 | }, 167 | $session_id: { 168 | valueType: 0, 169 | value: getSessionId 170 | }, 171 | $is_first_time: { 172 | valueType: 0, 173 | value: isFirstTime 174 | }, 175 | $is_first_day: { 176 | valueType: 0, 177 | value: isFirstDay 178 | }, 179 | $referrer: { 180 | valueType: 0, 181 | value: getReferrer 182 | }, 183 | $referrer_domain: { 184 | valueType: 0, 185 | value: getReferrerDomain 186 | }, 187 | $title: { 188 | valueType: 0, 189 | value: getTitle 190 | }, 191 | $url: { 192 | valueType: 0, 193 | value: getUrl 194 | }, 195 | $startup_time: { 196 | valueType: 0, 197 | value: startupTime 198 | }, 199 | $web_crawler: { 200 | valueType: 0, 201 | value: checkSpider 202 | }, 203 | 204 | $original_id: { 205 | valueType: 0, 206 | value: originalId 207 | }, 208 | $utm_campaign_id: { 209 | valueType: 0, 210 | value: utmCampaignId 211 | }, 212 | $utm_source: { 213 | valueType: 0, 214 | value: utmSource 215 | }, 216 | $utm_medium: { 217 | valueType: 0, 218 | value: utmMedium 219 | }, 220 | $utm_term: { 221 | valueType: 0, 222 | value: utmTerm 223 | }, 224 | $utm_content: { 225 | valueType: 0, 226 | value: utmContent 227 | }, 228 | $utm_campaign: { 229 | valueType: 0, 230 | value: utmCampaign 231 | }, 232 | $is_time_calibrated: { 233 | valueType: 0, 234 | value: timeCalibration 235 | } 236 | 237 | }, 238 | 239 | xcontextCommonRule: { 240 | check: { 241 | key: ['isString', 'length99', 'notSpecialCharacters', 'keywords'], 242 | value: ['notObject', 'isArrayString', 'length255'] 243 | } 244 | }, 245 | $track: { 246 | check: { 247 | key: ['isString', 'notSpecialCharacters', 'length99'] 248 | } 249 | }, 250 | $alias: { 251 | check: { 252 | key: ['isString', 'keyLength255'] 253 | } 254 | }, 255 | $profile_increment: { 256 | check: { 257 | key: ['isString', 'length99', 'notSpecialCharacters'], 258 | value: ['isNumber'] 259 | } 260 | }, 261 | $profile_unset: { 262 | check: { 263 | key: ['isString', 'length99', 'notSpecialCharacters'] 264 | } 265 | }, 266 | $pageview: { 267 | check: { 268 | key: ['isString', 'keyLength255'] 269 | } 270 | } 271 | } 272 | -------------------------------------------------------------------------------- /src/configure/base/fieldTemplate.js: -------------------------------------------------------------------------------- 1 | /** 2 | * SDK 基础字段定义表 3 | * base.outer:上报日志基础结构定义 4 | * base.xcontext:上报报文找中xcontext下的共有字段定义 5 | * $开头的字段为各个事件特殊拥有字段 6 | */ 7 | export default { 8 | base: { 9 | outer: [ 10 | 'appid', 11 | 'xwho', 12 | 'xwhat', 13 | 'xwhen', 14 | 'xcontext' 15 | ], 16 | xcontext: [ 17 | '$lib', 18 | '$lib_version', 19 | '$platform', 20 | '$debug', 21 | '$is_login' 22 | ] 23 | }, 24 | $startup: { 25 | xcontext: [ 26 | '$screen_width', 27 | '$screen_height', 28 | '$web_crawler', 29 | '$time_zone', 30 | '$language', 31 | '$session_id', 32 | '$is_first_time', 33 | '$is_first_day', 34 | '$utm_campaign_id', 35 | '$utm_source', 36 | '$utm_medium', 37 | '$utm_term', 38 | '$utm_content', 39 | '$utm_campaign', 40 | '$is_time_calibrated' 41 | ] 42 | }, 43 | $track: { 44 | xcontext: [ 45 | '$screen_width', 46 | '$screen_height', 47 | '$web_crawler', 48 | '$time_zone', 49 | '$language', 50 | '$is_first_day', 51 | '$session_id', 52 | '$utm_campaign_id', 53 | '$utm_source', 54 | '$utm_medium', 55 | '$utm_term', 56 | '$utm_content', 57 | '$utm_campaign', 58 | '$is_time_calibrated' 59 | ] 60 | }, 61 | $pageview: { 62 | xcontext: [ 63 | '$screen_width', 64 | '$screen_height', 65 | '$web_crawler', 66 | '$time_zone', 67 | '$language', 68 | '$session_id', 69 | '$is_first_day', 70 | '$referrer', 71 | '$referrer_domain', 72 | '$title', 73 | '$url', 74 | '$startup_time', 75 | '$utm_campaign_id', 76 | '$utm_source', 77 | '$utm_medium', 78 | '$utm_term', 79 | '$utm_content', 80 | '$utm_campaign', 81 | '$is_time_calibrated' 82 | ] 83 | }, 84 | $alias: { 85 | xcontext: [ 86 | '$original_id' 87 | ] 88 | }, 89 | $getPresetProperties: { 90 | xcontext: [ 91 | '$screen_width', 92 | '$screen_height', 93 | '$time_zone', 94 | '$session_id', 95 | '$language' 96 | ] 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/configure/base/index.js: -------------------------------------------------------------------------------- 1 | import fieldRules from './fieldRules.js' 2 | import fieldTemplate from './fieldTemplate.js' 3 | import lifecycle from './lifecycle.js' 4 | 5 | export { 6 | fieldRules, 7 | fieldTemplate, 8 | lifecycle 9 | } 10 | -------------------------------------------------------------------------------- /src/configure/base/lifecycle.js: -------------------------------------------------------------------------------- 1 | 2 | export default { 3 | } 4 | -------------------------------------------------------------------------------- /src/configure/customized/UA/configure/fieldRules.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 字段填充、字段校验规则模板 3 | * 4 | * check:数据合法检测方法列表,每个方法返回bool值,以用户为准,同名覆盖 5 | * 6 | */ 7 | export default { 8 | xcontext: { 9 | $user_agent: { 10 | valueType: 1, 11 | value: window.navigator.userAgent.replace(/"/g, '\\"') 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/configure/customized/UA/configure/fieldTemplate.js: -------------------------------------------------------------------------------- 1 | /** 2 | * SDK 基础字段定义表 3 | * base.outer:上报日志基础结构定义 4 | * base.xcontext:上报报文找中xcontext下的共有字段定义 5 | * $开头的字段为各个事件特殊拥有字段 6 | */ 7 | var temp = {} 8 | var event = ['$startup', '$track', '$pageview', '$webstay', '$web_click', '$user_click'] 9 | var common = { 10 | // "base": { 11 | xcontext: [ 12 | '$user_agent' 13 | ] 14 | // } 15 | } 16 | for (var i = 0; i < event.length; i++) { 17 | temp[event[i]] = common 18 | } 19 | export default temp 20 | -------------------------------------------------------------------------------- /src/configure/customized/UA/index.js: -------------------------------------------------------------------------------- 1 | import fieldRules from './configure/fieldRules.js' 2 | import fieldTemplate from './configure/fieldTemplate.js' 3 | export { 4 | fieldRules, 5 | fieldTemplate 6 | } 7 | -------------------------------------------------------------------------------- /src/configure/customized/decodeGBK/configure/lifecycle.js: -------------------------------------------------------------------------------- 1 | import { 2 | decodeGBK 3 | } from '../lib/decodeGBK' 4 | export default { 5 | ParseStr: { 6 | gbkDecode: decodeGBK 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/configure/customized/decodeGBK/index.js: -------------------------------------------------------------------------------- 1 | import lifecycle from './configure/lifecycle.js' 2 | export { 3 | lifecycle 4 | } 5 | -------------------------------------------------------------------------------- /src/configure/customized/encrypt/configure/fieldRules.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 字段填充、字段校验规则模板 3 | * 4 | * check:数据合法检测方法列表,每个方法返回bool值,以用户为准,同名覆盖 5 | * 6 | */ 7 | export default { 8 | encryptType: { 9 | check: { 10 | value: ['isNumber'] 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/configure/customized/encrypt/configure/fieldTemplate.js: -------------------------------------------------------------------------------- 1 | /** 2 | * SDK 基础字段定义表 3 | * base.outer:上报日志基础结构定义 4 | * base.xcontext:上报报文找中xcontext下的共有字段定义 5 | * $开头的字段为各个事件特殊拥有字段 6 | */ 7 | export default { 8 | } 9 | -------------------------------------------------------------------------------- /src/configure/customized/encrypt/configure/lifecycle.js: -------------------------------------------------------------------------------- 1 | import { encryptInit, uploadData } from '../lib/encrypt.js' 2 | export default { 3 | AnalysysAgent: { 4 | init: encryptInit 5 | }, 6 | upload: { 7 | init: uploadData 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/configure/customized/encrypt/index.js: -------------------------------------------------------------------------------- 1 | import fieldRules from './configure/fieldRules.js' 2 | import fieldTemplate from './configure/fieldTemplate.js' 3 | import lifecycle from './configure/lifecycle.js' 4 | export { 5 | fieldRules, 6 | fieldTemplate, 7 | lifecycle 8 | } 9 | -------------------------------------------------------------------------------- /src/configure/customized/encrypt/lib/base64js.min.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | exports.byteLength = byteLength 4 | exports.toByteArray = toByteArray 5 | exports.fromByteArray = fromByteArray 6 | 7 | var lookup = [] 8 | var revLookup = [] 9 | var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array 10 | 11 | var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' 12 | for (var i = 0, len = code.length; i < len; ++i) { 13 | lookup[i] = code[i] 14 | revLookup[code.charCodeAt(i)] = i 15 | } 16 | 17 | // Support decoding URL-safe base64 strings, as Node.js does. 18 | // See: https://en.wikipedia.org/wiki/Base64#URL_applications 19 | revLookup['-'.charCodeAt(0)] = 62 20 | revLookup['_'.charCodeAt(0)] = 63 21 | 22 | function getLens (b64) { 23 | var len = b64.length 24 | 25 | if (len % 4 > 0) { 26 | throw new Error('Invalid string. Length must be a multiple of 4') 27 | } 28 | 29 | // Trim off extra bytes after placeholder bytes are found 30 | // See: https://github.com/beatgammit/base64-js/issues/42 31 | var validLen = b64.indexOf('=') 32 | if (validLen === -1) validLen = len 33 | 34 | var placeHoldersLen = validLen === len 35 | ? 0 36 | : 4 - (validLen % 4) 37 | 38 | return [validLen, placeHoldersLen] 39 | } 40 | 41 | // base64 is 4/3 + up to two characters of the original data 42 | function byteLength (b64) { 43 | var lens = getLens(b64) 44 | var validLen = lens[0] 45 | var placeHoldersLen = lens[1] 46 | return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen 47 | } 48 | 49 | function _byteLength (b64, validLen, placeHoldersLen) { 50 | return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen 51 | } 52 | 53 | function toByteArray (b64) { 54 | var tmp 55 | var lens = getLens(b64) 56 | var validLen = lens[0] 57 | var placeHoldersLen = lens[1] 58 | 59 | var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen)) 60 | 61 | var curByte = 0 62 | 63 | // if there are placeholders, only get up to the last complete 4 chars 64 | var len = placeHoldersLen > 0 65 | ? validLen - 4 66 | : validLen 67 | 68 | var i 69 | for (i = 0; i < len; i += 4) { 70 | tmp = 71 | (revLookup[b64.charCodeAt(i)] << 18) | 72 | (revLookup[b64.charCodeAt(i + 1)] << 12) | 73 | (revLookup[b64.charCodeAt(i + 2)] << 6) | 74 | revLookup[b64.charCodeAt(i + 3)] 75 | arr[curByte++] = (tmp >> 16) & 0xFF 76 | arr[curByte++] = (tmp >> 8) & 0xFF 77 | arr[curByte++] = tmp & 0xFF 78 | } 79 | 80 | if (placeHoldersLen === 2) { 81 | tmp = 82 | (revLookup[b64.charCodeAt(i)] << 2) | 83 | (revLookup[b64.charCodeAt(i + 1)] >> 4) 84 | arr[curByte++] = tmp & 0xFF 85 | } 86 | 87 | if (placeHoldersLen === 1) { 88 | tmp = 89 | (revLookup[b64.charCodeAt(i)] << 10) | 90 | (revLookup[b64.charCodeAt(i + 1)] << 4) | 91 | (revLookup[b64.charCodeAt(i + 2)] >> 2) 92 | arr[curByte++] = (tmp >> 8) & 0xFF 93 | arr[curByte++] = tmp & 0xFF 94 | } 95 | 96 | return arr 97 | } 98 | 99 | function tripletToBase64 (num) { 100 | return lookup[num >> 18 & 0x3F] + 101 | lookup[num >> 12 & 0x3F] + 102 | lookup[num >> 6 & 0x3F] + 103 | lookup[num & 0x3F] 104 | } 105 | 106 | function encodeChunk (uint8, start, end) { 107 | var tmp 108 | var output = [] 109 | for (var i = start; i < end; i += 3) { 110 | tmp = 111 | ((uint8[i] << 16) & 0xFF0000) + 112 | ((uint8[i + 1] << 8) & 0xFF00) + 113 | (uint8[i + 2] & 0xFF) 114 | output.push(tripletToBase64(tmp)) 115 | } 116 | return output.join('') 117 | } 118 | 119 | function fromByteArray (uint8) { 120 | var tmp 121 | var len = uint8.length 122 | var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes 123 | var parts = [] 124 | var maxChunkLength = 16383 // must be multiple of 3 125 | 126 | // go through the array every three bytes, we'll deal with trailing stuff later 127 | for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { 128 | parts.push(encodeChunk( 129 | uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength) 130 | )) 131 | } 132 | 133 | // pad the end with zeros, but make sure to not forget the extra bytes 134 | if (extraBytes === 1) { 135 | tmp = uint8[len - 1] 136 | parts.push( 137 | lookup[tmp >> 2] + 138 | lookup[(tmp << 4) & 0x3F] + 139 | '==' 140 | ) 141 | } else if (extraBytes === 2) { 142 | tmp = (uint8[len - 2] << 8) + uint8[len - 1] 143 | parts.push( 144 | lookup[tmp >> 10] + 145 | lookup[(tmp >> 4) & 0x3F] + 146 | lookup[(tmp << 2) & 0x3F] + 147 | '=' 148 | ) 149 | } 150 | 151 | return parts.join('') 152 | } -------------------------------------------------------------------------------- /src/configure/customized/encrypt/lib/encrypt.js: -------------------------------------------------------------------------------- 1 | import encUtf8 from 'crypto-js/enc-utf8' 2 | import aes from 'crypto-js/aes' 3 | import ecb from 'crypto-js/mode-ecb' 4 | import pako from 'pako' 5 | import base64js from './base64js.min.js' 6 | import Util from '../../../../lib/common/index.js' 7 | 8 | var encryptType = 0 9 | 10 | var reqt = '' 11 | 12 | function getSpv (lib, appid, libVersion) { 13 | var policyversion = '' 14 | var appversion = '' 15 | var spv = lib + '|' + appid + '|' + libVersion + '|' + policyversion + '|' + appversion 16 | return encodeURIComponent(Util.encode(spv)) 17 | } 18 | 19 | function encryptKey (lib, appid, libVersion) { 20 | reqt = +new Date() 21 | var orgkey = lib + appid + libVersion + reqt 22 | var base64Str = '' 23 | // MD5+base64+切割为数组 24 | var baseStr = Util.encode(Util.MD5(orgkey, 32).toUpperCase()).split('') 25 | var F = libVersion.split('.') 26 | var F1 = F[F.length - 1] 27 | var F2 = F[F.length - 2] 28 | if (!(Number(F2) % 2) === false) { 29 | // 倒叙 30 | base64Str = baseStr.reverse() 31 | } else { 32 | base64Str = baseStr 33 | } 34 | var key = '' 35 | for (var i = 0; i < base64Str.length; i++) { 36 | // 偶数位 37 | if (i % 2 === 0 && !(Number(F1) % 2 === 0)) { 38 | key += base64Str[i] 39 | } else if (!(i % 2 === 0) && Number(F1) % 2 === 0) { 40 | key += base64Str[i] 41 | } 42 | } 43 | if (key.length < 16) { 44 | key += key.split('').reverse().join('') 45 | } 46 | return key.slice(0, 16) 47 | } 48 | 49 | function getEncryptData (data, lib, appid, libVersion) { 50 | var key = encryptKey(lib, appid, libVersion) 51 | key = encUtf8.parse(key) 52 | var encryptData = '' 53 | if (encryptType === 1) { 54 | encryptData = aes.encrypt(data, key, { 55 | mode: ecb 56 | }) 57 | } 58 | if (encryptType === 2) { 59 | var iv = encUtf8.parse('Analysys_315$CBC') 60 | encryptData = aes.encrypt(data, key, { 61 | iv: iv 62 | }) 63 | } 64 | encryptData = encryptData.ciphertext.toString().toUpperCase() 65 | var pakoZip = pako.gzip(encryptData) 66 | return base64js.fromByteArray(pakoZip) 67 | } 68 | 69 | function encryptInit (config) { 70 | if (config.encryptType === 1) { 71 | encryptType = 1 72 | } 73 | if (config.encryptType === 2) { 74 | encryptType = 2 75 | } 76 | 77 | return config 78 | } 79 | 80 | function uploadData (option) { 81 | if (encryptType !== 1 && encryptType !== 2) { 82 | return option 83 | } 84 | var dataArray = JSON.parse(option.data) 85 | var lib = dataArray[0].xcontext.$lib 86 | var appid = dataArray[0].appid 87 | var libVersion = dataArray[0].xcontext.$lib_version 88 | option.data = getEncryptData(option.data, lib, appid, libVersion) 89 | option.url += '&spv=' + getSpv(lib, appid, libVersion) + '&reqt=' + reqt + '&reqv=' + encryptType 90 | 91 | return option 92 | } 93 | 94 | function zipInflate (data) { 95 | return JSON.parse(pako.inflate(base64js.toByteArray(data), { 96 | to: 'string' 97 | })) 98 | } 99 | window.AnalysysModule = Util.objMerge(window.AnalysysModule || {}, { 100 | encryptInit: encryptInit, 101 | uploadData: uploadData, 102 | zipInflate: zipInflate 103 | }) 104 | export { 105 | encryptInit, 106 | uploadData, 107 | zipInflate 108 | } 109 | -------------------------------------------------------------------------------- /src/configure/customized/heatmap/configure/fieldRules.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 字段填充、字段校验规则模板 3 | * 4 | * check:数据合法检测方法列表,每个方法返回bool值,以用户为准,同名覆盖 5 | * 6 | */ 7 | import { 8 | getPageWidth, 9 | getPageHeight, 10 | getClickX, 11 | getClickY, 12 | getElementPath, 13 | getUrlPath, 14 | getElementX, 15 | getElementY, 16 | getElementType, 17 | getElementClickable, 18 | getEleContent, 19 | getDeviceType, 20 | getElementId, 21 | getElementName, 22 | getElementClassName, 23 | getElementTargetUrl 24 | } from '../lib/getField.js' 25 | export default { 26 | autoHeatmap: { 27 | check: { 28 | value: ['isBoolean'] 29 | } 30 | }, 31 | xcontext: { 32 | $page_width: { 33 | valueType: 0, 34 | value: getPageWidth 35 | }, 36 | $page_height: { 37 | valueType: 0, 38 | value: getPageHeight 39 | }, 40 | $click_x: { 41 | valueType: 0, 42 | value: getClickX 43 | }, 44 | $click_y: { 45 | valueType: 0, 46 | value: getClickY 47 | }, 48 | $element_path: { 49 | valueType: 0, 50 | value: getElementPath 51 | }, 52 | $url_path: { 53 | valueType: 0, 54 | value: getUrlPath 55 | }, 56 | $element_x: { 57 | valueType: 0, 58 | value: getElementX 59 | }, 60 | $element_y: { 61 | valueType: 0, 62 | value: getElementY 63 | }, 64 | $element_type: { 65 | valueType: 0, 66 | value: getElementType 67 | }, 68 | $element_clickable: { 69 | valueType: 0, 70 | value: getElementClickable 71 | }, 72 | $element_content: { 73 | valueType: 0, 74 | value: getEleContent 75 | }, 76 | $device_type: { 77 | valueType: 0, 78 | value: getDeviceType 79 | }, 80 | $element_id: { 81 | valueType: 0, 82 | value: getElementId 83 | }, 84 | $element_name: { 85 | valueType: 0, 86 | value: getElementName 87 | }, 88 | $element_target_url: { 89 | valueType: 0, 90 | value: getElementTargetUrl 91 | }, 92 | $element_class_name: { 93 | valueType: 0, 94 | value: getElementClassName 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/configure/customized/heatmap/configure/fieldTemplate.js: -------------------------------------------------------------------------------- 1 | /** 2 | * SDK 基础字段定义表 3 | * base.outer:上报日志基础结构定义 4 | * base.xcontext:上报报文找中xcontext下的共有字段定义 5 | * $开头的字段为各个事件特殊拥有字段 6 | */ 7 | export default { 8 | $web_click: { 9 | xcontext: [ 10 | '$page_width', 11 | '$page_height', 12 | '$click_x', 13 | '$click_y', 14 | '$element_path', 15 | '$url_path', 16 | '$url', 17 | '$title', 18 | '$session_id', 19 | '$device_type', 20 | '$session_id', 21 | '$is_time_calibrated', 22 | '$element_x', 23 | '$element_y', 24 | '$element_type', 25 | '$element_clickable', 26 | '$element_content', 27 | '$is_first_day', 28 | '$element_id', 29 | '$element_name', 30 | '$element_target_url', 31 | '$element_class_name' 32 | ] 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/configure/customized/heatmap/configure/lifecycle.js: -------------------------------------------------------------------------------- 1 | import { heatmapInit } from '../lib/heatmap.js' 2 | 3 | export default { 4 | AnalysysAgent: { 5 | init: heatmapInit 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/configure/customized/heatmap/heatmapSDK/common/config.js: -------------------------------------------------------------------------------- 1 | import Util from '../../../../../lib/common/index.js' 2 | import Storage from '../../../../../lib/storage/index.js' 3 | 4 | var heatmapConfig = window.ARK_HEATMAP && window.ARK_HEATMAP.config 5 | var ifarmeMessageList = [] 6 | var showMapConfig = { 7 | type: 'heatmap', 8 | content: {}, 9 | control: {}, 10 | contentText: {}, 11 | isRefresh: false, 12 | max: 10, 13 | rightMaxNum: 100 14 | } 15 | 16 | function backParam () { 17 | var params = { 18 | content: showMapConfig.content, 19 | times: +new Date() + (Storage.getLocal('ANSSERVERTIME') ? Number(Storage.getLocal('ANSSERVERTIME')) : 0) 20 | } 21 | params.content.requestType = 'web' 22 | 23 | params.content.appKey = heatmapConfig.appid 24 | if (!params.content.deviceType) { 25 | params.content.deviceType = Util.deviceType() 26 | } 27 | if (showMapConfig.isRefresh === true) { 28 | params.content.useCache = false 29 | } else { 30 | params.content.useCache = true 31 | } 32 | // if (!params.content["dbUrlDomain"]) { 33 | // var urlPath = params.content["urlDomain"] || params.content["urlPath"] 34 | // if (!urlPath) { 35 | // urlPath = location.protocol + '//' + location.host + location.pathname + location.hash 36 | // urlPath = urlPath.split('?')[0] 37 | // } 38 | // // urlPath = urlPath.split('#')[0] 39 | // params.content["urlDomain"] = params.content["urlPath"] = urlPath 40 | // } 41 | 42 | showMapConfig.isRefresh = false 43 | params.content = JSON.stringify(params.content) 44 | 45 | var param = [] 46 | for (var key in params) { 47 | param.push(key + '=' + encodeURIComponent(params[key])) 48 | } 49 | param = param.join('&') 50 | return param 51 | } 52 | export { 53 | heatmapConfig, 54 | ifarmeMessageList, 55 | showMapConfig, 56 | backParam 57 | } 58 | -------------------------------------------------------------------------------- /src/configure/customized/heatmap/heatmapSDK/common/iframeMsg.js: -------------------------------------------------------------------------------- 1 | import Util from '../../../../../lib/common/index.js' 2 | import { heatmapConfig } from './config.js' 3 | 4 | /** 5 | * [sendMsg description]发送热图SDK初始化完毕信息 6 | * @return {[type]} [description] 7 | */ 8 | function sendMsg () { 9 | var msg = JSON.stringify({ 10 | code: 'ark/heatmap', 11 | appkey: heatmapConfig.appid 12 | }) 13 | // console.log('发送热图SDK初始化完毕消息===>', msg) 14 | window.parent.postMessage(msg, '*') 15 | } 16 | 17 | /** 18 | * [getMsg description]接收iframe消息 19 | * @param {Function} callback [description] 20 | * @return {[type]} [description] 21 | */ 22 | function getMsg (callback) { 23 | Util.addEvent(window, 'message', function (msgObj) { 24 | var msg = msgObj.data 25 | // console.log('获取服务端热图命令===>', JSON.stringify(msgObj.data)) 26 | 27 | try { 28 | if (Util.paramType(msg) === 'String') { 29 | msg = JSON.parse(msg) 30 | } 31 | } catch (e) { } 32 | callback(msg) 33 | }) 34 | } 35 | export { 36 | sendMsg, 37 | getMsg 38 | } 39 | -------------------------------------------------------------------------------- /src/configure/customized/heatmap/heatmapSDK/heatMap/nav.js: -------------------------------------------------------------------------------- 1 | import Util from '../../../../../lib/common/index.js' 2 | 3 | function bindHeadToggle () { 4 | var arkHead = document.getElementById('ARK_HEATMAP_HEAD') 5 | var openHead = document.getElementById('ARK_OPEN') 6 | var closeHead = document.getElementById('ARK_CLOSE') 7 | 8 | function toggleHead () { 9 | // event.stopPropagation(); 10 | arkHead.style.top = Math.abs(arkHead.offsetTop) - arkHead.clientHeight + 'px' 11 | if (openHead.style.display === 'block') { 12 | openHead.style.display = 'none' 13 | } else { 14 | openHead.style.display = 'block' 15 | } 16 | } 17 | Util.addEvent(openHead, 'click', toggleHead) 18 | Util.addEvent(closeHead, 'click', toggleHead) 19 | } 20 | 21 | function initHead () { 22 | // 绑定头部显示隐藏 23 | bindHeadToggle() 24 | } 25 | 26 | export { initHead } 27 | -------------------------------------------------------------------------------- /src/configure/customized/heatmap/heatmapSDK/lib/colorRange.js: -------------------------------------------------------------------------------- 1 | function ColorRangeMaker (option) { 2 | var vRange = option.value[1] - option.value[0] 3 | if (option.color.length === 2) { // 仅有两个颜色 4 | var rA = (option.color[1][0] - option.color[0][0]) / vRange 5 | var gA = (option.color[1][1] - option.color[0][1]) / vRange 6 | var bA = (option.color[1][2] - option.color[0][2]) / vRange 7 | this.option = { 8 | vRange: vRange, 9 | rA: rA, 10 | gA: gA, 11 | bA: bA, 12 | option: option 13 | } 14 | } else { // 两个以上颜色 15 | var makers = [] 16 | var vA = vRange / (option.color.length - 1) 17 | for (var i = 1; i < option.color.length; i++) { 18 | var maker = new ColorRangeMaker({ 19 | color: [option.color[i - 1], option.color[i]], 20 | value: [option.value[0] + vA * (i - 1), 21 | option.value[0] + vA * i 22 | ] 23 | }) 24 | makers.push(maker) 25 | } 26 | this.option = { makers, vA, option } 27 | } 28 | } 29 | 30 | ColorRangeMaker.prototype.make = function (value) { 31 | var makers = this.option.makers 32 | var rA = this.option.rA 33 | var gA = this.option.gA 34 | var bA = this.option.bA 35 | var vA = this.option.vA 36 | var option = this.option.option 37 | if (value < option.value[0]) { 38 | return option.color[0] 39 | } else if (value > option.value[option.value.length - 1]) { 40 | return option.color[option.color.length - 1] 41 | } else { 42 | if (option.color.length === 2) { // 仅有两个颜色 43 | var color = option.color[0].map(a => a) 44 | var vATmp = value - option.value[0] 45 | color[0] += parseInt(rA * vATmp) 46 | color[1] += parseInt(gA * vATmp) 47 | color[2] += parseInt(bA * vATmp) 48 | return color 49 | } else { 50 | for (var i = 1; i < option.color.length; i++) { 51 | if (value <= option.value[0] + vA * i) { 52 | return makers[i - 1].make(value) 53 | } 54 | } 55 | } 56 | } 57 | } 58 | export default ColorRangeMaker 59 | -------------------------------------------------------------------------------- /src/configure/customized/heatmap/heatmapSDK/webstay/webStayDom.js: -------------------------------------------------------------------------------- 1 | var webStayPageLineTemp = `
{LINENUM}%
2 | ` 3 | var webStayMouseLineTemp = `
4 | ` 5 | export { webStayPageLineTemp, webStayMouseLineTemp } 6 | -------------------------------------------------------------------------------- /src/configure/customized/heatmap/heatmapSDK/webstay/webStayLine.css: -------------------------------------------------------------------------------- 1 | .ARK_PAGE_LINE_BOX { 2 | z-index: 1000000000; 3 | position: absolute; 4 | width: 100%; 5 | height: 1px; 6 | /*overflow-x:hidden;*/ 7 | } 8 | 9 | .ARK_PAGE_LINE_LINE { 10 | width: 100%; 11 | height: 0px; 12 | border-bottom: dashed 1px #262d39 !important; 13 | } 14 | 15 | .ARK_PAGE_LINE_VALUE { 16 | /*width: 76px; 17 | height: 32px;*/ 18 | background-color: #262d39; 19 | font-family: Roboto-Bold; 20 | font-size: 16px; 21 | font-weight: normal; 22 | font-stretch: normal; 23 | line-height: 16px; 24 | letter-spacing: 0px; 25 | color: #ffffff; 26 | padding: 8px 16px; 27 | border-radius: 0 4px 0 0; 28 | -moz-border-radius: 0 4px 0 0; 29 | position: absolute; 30 | left: 0; 31 | bottom: 0; 32 | } 33 | 34 | .ARK_MOUSE_LINE_VALUE { 35 | position: relative; 36 | left: -50%; 37 | text-align: center; 38 | padding: 8px 16px; 39 | border-radius: 4px; 40 | -moz-border-radius: 4px; 41 | background-color: #262d39; 42 | font-family: Roboto-Bold; 43 | font-size: 16px; 44 | font-weight: normal; 45 | font-stretch: normal; 46 | line-height: 16px; 47 | letter-spacing: 0px; 48 | color: #ffffff; 49 | } 50 | .ARK_MOUSE_LINE_LINE{ 51 | border-bottom: solid 1px #262d39 !important; 52 | } 53 | .ARK_MOUSE_LINE_VALUE_BOX{ 54 | left: 50%; 55 | position: absolute; 56 | top:-16px; 57 | } -------------------------------------------------------------------------------- /src/configure/customized/heatmap/index.js: -------------------------------------------------------------------------------- 1 | import fieldRules from './configure/fieldRules.js' 2 | import fieldTemplate from './configure/fieldTemplate.js' 3 | import lifecycle from './configure/lifecycle.js' 4 | export { 5 | fieldRules, 6 | fieldTemplate, 7 | lifecycle 8 | } 9 | -------------------------------------------------------------------------------- /src/configure/customized/heatmap/lib/elementContent.js: -------------------------------------------------------------------------------- 1 | import Util from '../../../../lib/common/index.js' 2 | 3 | function getElementContent (ele, status) { 4 | var eleContent = '' 5 | if (ele.tagName.toLowerCase() === 'input') { 6 | eleContent = ele.value || '' 7 | } else if (ele.tagName.toLowerCase() === 'img') { 8 | eleContent = ele.getAttribute('alt') || ele.getAttribute('title') || '' 9 | } else if (ele.tagName.toLowerCase() === 'a') { 10 | eleContent = ele.getAttribute('title') || '' 11 | } 12 | if (!eleContent) { 13 | var children = ele.childNodes 14 | for (var i = 0; i < children.length; i++) { 15 | if (children[i].nodeType === 3) { 16 | eleContent += children[i].nodeValue 17 | } 18 | } 19 | // if (ele.textContent) { 20 | // eleContent = Util.trim(ele.textContent) 21 | // } else { 22 | // if (ele.innerText) { 23 | // eleContent = Util.trim(ele.innerText) 24 | // } 25 | // } 26 | } 27 | if (eleContent && Util.paramType(eleContent) === 'String') { 28 | eleContent = eleContent.replace(/[\r\n]/g, ' ').replace(/[ ]+/g, ' ') 29 | } else { 30 | eleContent = '' 31 | } 32 | if (ele.tagName.toLowerCase() === 'input' && ele.type !== 'button' && ele.type !== 'submit' && status !== true) { 33 | return '' 34 | } 35 | eleContent = Util.trim(eleContent) 36 | // if (eleContent.length > 0) { 37 | // eleContent = 38 | // } 39 | return eleContent 40 | } 41 | export { getElementContent } 42 | -------------------------------------------------------------------------------- /src/configure/customized/heatmap/lib/getField.js: -------------------------------------------------------------------------------- 1 | import Util from '../../../../lib/common/index.js' 2 | import { getElementContent } from './elementContent.js' 3 | import baseConfig from '../../../../lib/baseConfig/index.js' 4 | var elePostion = { 5 | ele: '', 6 | click_x: 0, 7 | click_y: 0, 8 | clickEle: '' 9 | } 10 | 11 | function domParentList (ele) { 12 | var list = [] 13 | var parent = ele 14 | while (parent != null) { 15 | var index = 0 16 | if (parent.parentNode) { 17 | var clildrenEles = parent.parentNode.children 18 | if (clildrenEles) { 19 | for (var i = 0; i < clildrenEles.length; i++) { 20 | if (clildrenEles[i] === parent) { 21 | index = i 22 | } 23 | } 24 | } 25 | } 26 | var tagName = parent.tagName 27 | if (!tagName) { 28 | parent = parent.parentNode 29 | continue 30 | } 31 | tagName = tagName.toLowerCase() 32 | var parentID = parent.id ? ('#' + parent.id) : '' 33 | var eleClassNameList = parent.className && Util.paramType(parent.className) === 'String' ? parent.className.split(' ') : [] 34 | 35 | if (eleClassNameList.length > 0) { 36 | var eleClassName = '' 37 | for (var y = 0; y < eleClassNameList.length; y++) { 38 | if (eleClassNameList[y] && eleClassNameList[y].indexOf('ARK') < 0) { 39 | eleClassName += '.' + eleClassNameList[y] 40 | } 41 | } 42 | list.push(tagName + parentID + eleClassName + '|' + index) 43 | } else { 44 | list.push(tagName + parentID + '|' + index) 45 | } 46 | 47 | parent = parent.parentNode 48 | } 49 | return list.join('<') 50 | } 51 | 52 | function getPageWidth () { 53 | return document.documentElement.scrollWidth 54 | } 55 | 56 | function getPageHeight () { 57 | return document.documentElement.scrollHeight 58 | } 59 | 60 | function getClickX () { 61 | return elePostion.click_x 62 | } 63 | 64 | function getClickY () { 65 | return elePostion.click_y 66 | } 67 | 68 | function getElementPath () { 69 | return domParentList(elePostion.ele) 70 | } 71 | 72 | function getUrlPath () { 73 | var url = window.location.protocol + '//' + window.location.host + window.location.pathname + window.location.hash 74 | try { 75 | url = decodeURIComponent(url) 76 | } catch (e) { } 77 | if (baseConfig.base.isHybrid === true) { 78 | url = url.replace(/"/g, '\\"') 79 | } 80 | return url 81 | } 82 | 83 | function getElementX () { 84 | return elePostion.elementX 85 | } 86 | 87 | function getElementY () { 88 | return elePostion.elementY 89 | } 90 | 91 | function getElementType () { 92 | return elePostion.ele.tagName.toLowerCase() 93 | } 94 | 95 | function getElementClick () { 96 | return Util.paramType(elePostion.ele.onclick) === 'Function' 97 | } 98 | function getElementAttrClick () { 99 | return elePostion.ele && elePostion.ele.getAttribute('data-ark-click') !== null 100 | } 101 | 102 | function checkElementConfig (eleConfig) { 103 | if (!eleConfig || (Util.paramType(eleConfig) === 'Array' && eleConfig.length === 0) || (Util.paramType(eleConfig) === 'String' && eleConfig === '')) { 104 | return false 105 | } 106 | var ele = elePostion.ele 107 | if (Util.paramType(eleConfig) === 'String') { 108 | var tagName = ele.tagName.toLowerCase() 109 | var className = Util.paramType(ele.className) === 'String' ? '.' + ele.className.split(' ').join('.') : '' 110 | var id = ele.id ? '#' + ele.id : '' 111 | if (tagName === eleConfig.toLowerCase() || className === eleConfig || id === eleConfig || tagName + className === eleConfig || tagName + id === eleConfig || id + className === eleConfig || tagName + id + className === eleConfig) { 112 | return true 113 | } 114 | } else if (Util.paramType(eleConfig) === 'Array') { 115 | for (var i = 0; i < eleConfig.length; i++) { 116 | if (checkElementConfig(eleConfig[i]) === true) { 117 | return true 118 | } 119 | } 120 | } else if (Util.paramType(eleConfig) === 'Function') { 121 | return eleConfig.call(eleConfig, ele) || false 122 | } else if (typeof eleConfig === 'object' && eleConfig === ele) { 123 | return true 124 | } 125 | return false 126 | } 127 | function getParentClickableElement () { 128 | var clickEle = elePostion.ele 129 | while (elePostion.ele != null) { 130 | if (elePostion.ele.nodeType !== 1) { 131 | elePostion.ele = elePostion.ele.parentNode 132 | continue 133 | } 134 | 135 | if (getElementClick() || getElementClickable() === 1 || getElementAttrClick() || checkElementConfig(baseConfig.base.trackList)) { 136 | clickEle = elePostion.ele 137 | break 138 | } 139 | elePostion.ele = elePostion.ele.parentNode 140 | } 141 | elePostion.ele = clickEle 142 | } 143 | /** 144 | * 判断当前元素是否为可触控元素 145 | */ 146 | function getElementClickable () { 147 | var tagName = getElementType() 148 | var clickableElementList = ['a', 'button', 'input', 'select', 'textarea', 'svg'] // option无法触发点击事件 149 | if (clickableElementList.indexOf(tagName) > -1 || getElementAttrClick() || checkElementConfig(baseConfig.base.trackList)) { 150 | if (tagName === 'svg' && elePostion.ele.children && elePostion.ele.children.length > 0) { 151 | var svgIsClickable = 0 152 | var svgChildren = elePostion.ele.children 153 | for (var i = 0; i < svgChildren.length; i++) { 154 | if (svgChildren[i].tagName.toLowerCase() === 'use' && 155 | (svgChildren[i].getAttribute('xlink:href') || getElementAttrClick() || checkElementConfig(baseConfig.base.trackList))) { 156 | svgIsClickable = 1 157 | } 158 | } 159 | return svgIsClickable 160 | } 161 | return 1 162 | } 163 | return 0 164 | } 165 | 166 | function getEleContent () { 167 | return getElementContent(elePostion.ele) 168 | } 169 | 170 | function getDeviceType () { 171 | return Util.deviceType() 172 | } 173 | 174 | function getElementId () { 175 | return elePostion.ele.id || elePostion.ele.getAttribute('id') || '' 176 | } 177 | 178 | function getElementName () { 179 | return elePostion.ele.getAttribute('name') || '' 180 | } 181 | 182 | function getElementClassName () { 183 | var eleClassName = elePostion.ele.getAttribute('class') || '' 184 | if (eleClassName) { 185 | var eleClassList = eleClassName.split(' ') 186 | var eleClassArray = [] 187 | for (var i = 0; i < eleClassList.length; i++) { 188 | if (eleClassList[i] !== '') { 189 | eleClassArray.push(eleClassList[i]) 190 | } 191 | } 192 | eleClassName = '.' + eleClassArray.join('.') 193 | return eleClassName 194 | } 195 | return '' 196 | } 197 | 198 | function getElementTargetUrl () { 199 | var href = elePostion.ele.getAttribute('href') 200 | if (href && href.indexOf('javascript:') < 0) { 201 | try { 202 | href = decodeURIComponent(href) 203 | } catch (e) { } 204 | if (baseConfig.base.isHybrid === true) { 205 | href = href.replace(/"/g, '\\"') 206 | } 207 | return href 208 | } 209 | return '' 210 | } 211 | export { 212 | elePostion, 213 | getPageWidth, 214 | getPageHeight, 215 | getClickX, 216 | getClickY, 217 | getElementPath, 218 | getUrlPath, 219 | getElementX, 220 | getElementY, 221 | getElementType, 222 | getElementClickable, 223 | getParentClickableElement, 224 | domParentList, 225 | getEleContent, 226 | getDeviceType, 227 | getElementId, 228 | getElementName, 229 | getElementClassName, 230 | getElementTargetUrl 231 | } 232 | -------------------------------------------------------------------------------- /src/configure/customized/heatmap/lib/heatmap.js: -------------------------------------------------------------------------------- 1 | import Util from '../../../../lib/common/index.js' 2 | import { elePostion, getParentClickableElement } from './getField.js' 3 | import { eleScroll, eleOffset } from '../heatmapSDK/common/index.js' 4 | var heatmapConfig = {} 5 | 6 | function loadHeatmapSDK () { 7 | if (!document.body || !document.getElementsByTagName('body')[0]) { 8 | setTimeout(loadHeatmapSDK, 50) 9 | return 10 | } 11 | Util.addScript('AnalysysAgent_JS_SDK_HEATMAP', heatmapConfig.SDKFileDirectory) 12 | window.ARK_HEATMAP = { 13 | config: heatmapConfig 14 | } 15 | } 16 | 17 | // function offset (obj, direction) { 18 | // var fristText = direction.split('')[0] 19 | // // 将top,left首字母大写,并拼接成offsetTop,offsetLeft 20 | // var offsetDir = 'offset' + fristText.toUpperCase() + direction.substring(1) 21 | 22 | // var realNum = obj[offsetDir] 23 | // var positionParent = obj.offsetParent // 获取上一级定位元素对象 24 | 25 | // while (positionParent != null) { 26 | // realNum += positionParent[offsetDir] 27 | // positionParent = positionParent.offsetParent 28 | // } 29 | // return realNum 30 | // } 31 | 32 | function addClickEvent (event) { 33 | var e = event || window.event 34 | if (e.touches && e.touches.length > 0) { 35 | e = e.touches[0] 36 | } 37 | var ele = e.target || e.srcElement 38 | 39 | if (Util.checkTypeList(heatmapConfig.heatMapBlackList, ele) || 40 | (heatmapConfig.heatMapWhiteList && 41 | !Util.checkTypeList(heatmapConfig.heatMapWhiteList, ele)) 42 | ) return 43 | // e.stopPropagation() 44 | // e.preventDefault() 45 | var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft 46 | var scrollY = document.documentElement.scrollTop || document.body.scrollTop 47 | var x = e.pageX || (e.clientX + scrollX) 48 | var y = e.pageY || (e.clientY + scrollY) 49 | elePostion.click_x = x 50 | elePostion.click_y = y 51 | elePostion.clickEle = elePostion.ele = ele 52 | getParentClickableElement() 53 | var eleScr = eleScroll(elePostion.ele) 54 | var eleOff = eleOffset(elePostion.ele) 55 | elePostion.elementX = x - (eleOff.left - eleScr.scrollLeft) 56 | elePostion.elementY = y - (eleOff.top - eleScr.scrollTop) 57 | if (!x || !y || x <= 0 || y <= 0) { 58 | return 59 | } 60 | if (!window.AnalysysAgent || !window.AnalysysAgent.freeApi) { 61 | setTimeout(function () { 62 | addClickEvent(event) 63 | }, 100) 64 | } else { 65 | window.AnalysysAgent.freeApi('$web_click') 66 | } 67 | } 68 | 69 | function initHeatmap () { 70 | if (Util.deviceType() == 'desktop') { 71 | Util.addEvent(document, 'click', addClickEvent) 72 | } else { 73 | Util.addEvent(document, 'touchstart', addClickEvent) 74 | } 75 | } 76 | 77 | function heatmapInit (config) { 78 | heatmapConfig = config 79 | if (window.location.href.indexOf('arkheatmap=true') > -1 || window.name.indexOf('arkheatmap=true') > -1) { 80 | if (window.name === '') { 81 | window.name = window.location.href 82 | } 83 | loadHeatmapSDK() 84 | } else if (config.autoHeatmap === true && config.isHybrid === false) { 85 | initHeatmap() 86 | } 87 | return config 88 | } 89 | 90 | export { heatmapInit } 91 | -------------------------------------------------------------------------------- /src/configure/customized/mpaas/index.js: -------------------------------------------------------------------------------- 1 | import Util from '../../../lib/common/index.js' 2 | var moduleStatus = Util.isiOS === true ? true : false 3 | function isHybrid () { 4 | document.addEventListener("AlipayJSBridgeReady", function () { 5 | window.AlipayJSBridge.call('isHybrid', {}, function (msg) { 6 | if (msg === true) { 7 | // console.log('mPaas 启动Hybrid模式') 8 | checkAnalysys() 9 | } 10 | }) 11 | }) 12 | } 13 | function checkAnalysys () { 14 | if (window.AnalysysAgent && Util.paramType(window.AnalysysAgent.init) === 'Function') { 15 | var config = Util.objMerge(window.AnalysysAgent.config || {}, { 16 | isHybrid: true 17 | }) 18 | window.AnalysysAgent.init(config) 19 | } else { 20 | setTimeout(checkAnalysys, 30) 21 | } 22 | } 23 | var checkNum = 0 24 | function checkBridge () { 25 | if (checkNum > 3) { 26 | 27 | if (checkNum > 5) { 28 | // console.log('mPaas Hybrid模式失败,为正常接入JS SDK') 29 | return 30 | } else if (window.AnalysysAgent && Util.paramType(window.AnalysysAgent.init) === 'Function') { 31 | window.AnalysysAgent.init({ 32 | isARKH5: true 33 | }) 34 | } else { 35 | checkNum++ 36 | setTimeout(checkBridge, 300) 37 | } 38 | return 39 | } 40 | if (window.AlipayJSBridge) { 41 | isHybrid() 42 | } else { 43 | setTimeout(checkBridge, 300) 44 | } 45 | checkNum++ 46 | } 47 | if (window.AnalysysAgent && !window.AnalysysAgent.isInit && moduleStatus === true) { 48 | checkBridge() 49 | } 50 | 51 | function upData (params) { 52 | // var callback = (function (params) { 53 | // return function (resulut) { 54 | // if (resulut.resulut === 'failure') { 55 | // BaseUpdata(params) 56 | // } 57 | // } 58 | // })(params) 59 | // window.AlipayJSBridge.call('analysysAgentCallNaitve', params, callback) 60 | BaseUpdata(params) 61 | } 62 | function BaseUpdata (params) { 63 | if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.AnalysysAgent) { 64 | window.webkit.messageHandlers.AnalysysAgent.postMessage(params) 65 | } else { 66 | var msg = JSON.stringify(params) 67 | var url = 'analysysagent:' + msg 68 | loadIframeUrl(url) 69 | } 70 | } 71 | function loadIframeUrl (url) { 72 | if (!document.body) { 73 | setTimeout(function () { loadIframeUrl(url) }, 200) 74 | return 75 | } 76 | var iframe = document.createElement('iframe') 77 | iframe.setAttribute('src', url) 78 | iframe.setAttribute('id', 'AnalysysAgentIframe') 79 | iframe.setAttribute('style', 'display:none;') 80 | 81 | document.body.appendChild(iframe) 82 | iframe.parentNode.removeChild(iframe) 83 | } 84 | function track (eventName, pro, elePostion) { 85 | window.AlipayJSBridge.call('AnalysysAgentTrack', { 'props': [eventName, JSON.stringify(pro), JSON.stringify(elePostion)] }, function () { }); 86 | 87 | } 88 | function eventList () { 89 | window.AlipayJSBridge.call('AnalysysAgentGetEventList', {}, function () { }); 90 | 91 | } 92 | function getPro (appRelateds, timeId) { 93 | window.AlipayJSBridge.call('AnalysysAgentGetProperty', { 'props': [JSON.stringify(appRelateds), timeId] }, function () { }); 94 | 95 | } 96 | function onEvent (hybridKey, HybridAns) { 97 | return HybridAns[hybridKey] 98 | } 99 | window.AnalysysModule = Util.objMerge(window.AnalysysModule || {}, { 100 | moduleStatus: moduleStatus, 101 | isHybrid: isHybrid, 102 | upData: upData, 103 | track: track, 104 | eventList: eventList, 105 | getPro: getPro, 106 | onEvent: onEvent 107 | }) -------------------------------------------------------------------------------- /src/configure/customized/pageClose/index.js: -------------------------------------------------------------------------------- 1 | import Util from '../../../lib/common/index.js' 2 | var Version = '4.4.1' 3 | 4 | /** 5 | * @method pageEndTrack [发送页面关闭事件] 6 | * @param {Function} callback 发送数据后的回调函数 7 | */ 8 | function pageEndTrack (callback) { 9 | var time = +new Date() 10 | if (isPageShow === false) { 11 | /** 12 | * 页面离开时间为 关闭时间-切换tab的时间+之前tab切换离开的时间 13 | */ 14 | pageLeaveTime = time - pageHiddenTime + pageLeaveTime 15 | } 16 | /** 17 | * 页面停留时间为 当前时间 - 页面打开时间 - 页面隐藏时间 18 | */ 19 | 20 | var pageStay = Number(time - pageStartTime - pageLeaveTime) 21 | if (pageStay < 0) { 22 | pageStay = Number(time - pageStartTime) 23 | } 24 | if (window.AnalysysAgent && window.AnalysysAgent.track) { 25 | window.AnalysysAgent.track('page_close', { 26 | pageStayTime: pageStay, 27 | $url: url, 28 | $title: pageTitle 29 | // sdkVersion: Version, 30 | // pageOpenTime: Util.format(new Date(pageOpenTime), 'yyyy-MM-dd hh:mm:ss.SSS') 31 | }) 32 | 33 | Util.paramType(callback) === 'Function' && callback.call(callback, null) 34 | } else { 35 | } 36 | createTime() 37 | } 38 | /** 39 | * url标准化 40 | * 41 | * @returns url 42 | */ 43 | function getUrl () { 44 | var url = window.location.href 45 | try { 46 | url = decodeURIComponent(url) 47 | } catch (e) { } 48 | try { 49 | if (window.AnalysysAgent.config.isHybrid === true) { 50 | url = url.replace(/"/g, '\\"') 51 | } 52 | } catch (e) { } 53 | return url 54 | } 55 | /** 56 | * 初始化参数 57 | */ 58 | /** 59 | * @method createTime [初始化参数] 60 | */ 61 | function createTime (startTime, title) { 62 | var time = +new Date() 63 | pageStartTime = startTime || time 64 | pageHiddenTime = startTime || time 65 | pageLeaveTime = 0 66 | isPageShow = true 67 | url = getUrl() 68 | pageTitle = arguments.length > 1 ? title : document.title 69 | } 70 | var pageOpenTime = +new Date() 71 | var pageStartTime = pageOpenTime 72 | var pageHiddenTime = pageOpenTime 73 | var pageLeaveTime = 0 74 | var isPageShow = true 75 | var url = getUrl() 76 | var pageTitle = document.title 77 | var autoPageClose = true 78 | /** 79 | * 监听页面打开与关闭事件 80 | */ 81 | if ('onpageShow' in window) { 82 | Util.addEvent(window, 'pageShow', function () { 83 | pageStartTime = pageHiddenTime = +new Date() 84 | }) 85 | Util.addEvent(window, 'pagehide', function () { 86 | if (autoPageClose === true) { 87 | pageEndTrack() 88 | } 89 | }) 90 | } else { 91 | Util.addEvent(window, 'load', function () { 92 | pageStartTime = pageHiddenTime = +new Date() 93 | }) 94 | Util.addEvent(window, 'beforeunload', function () { 95 | if (autoPageClose === true) { 96 | pageEndTrack() 97 | } 98 | }) 99 | } 100 | /** 101 | * 监听离开/返回tab且未关闭页面 102 | */ 103 | if ('onvisibilitychange' in document) { 104 | Util.addEvent(document, 'visibilitychange', function () { 105 | if (document.hidden) { 106 | isPageShow = false 107 | pageHiddenTime = +new Date() 108 | } else { 109 | isPageShow = true 110 | pageLeaveTime = +new Date() - pageHiddenTime + pageLeaveTime 111 | } 112 | }) 113 | } 114 | 115 | function pageCloseInit (obj) { 116 | if (Util.paramType(obj) === 'Object' && Util.paramType(obj.autoPageClose) === 'Boolean') { 117 | autoPageClose = obj.autoPageClose 118 | } 119 | } 120 | window.AnalysysModule = Util.objMerge(window.AnalysysModule || {}, { 121 | pageClose: { 122 | Version: Version, 123 | pageEndTrack: pageEndTrack, 124 | init: pageCloseInit, 125 | createTime: createTime 126 | } 127 | }) 128 | export { pageCloseInit, pageEndTrack } 129 | -------------------------------------------------------------------------------- /src/configure/customized/userClick/configure/fieldRules.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 字段填充、字段校验规则模板 3 | * 4 | * check:数据合法检测方法列表,每个方法返回bool值,以用户为准,同名覆盖 5 | * 6 | */ 7 | import { 8 | getPageWidth, 9 | getPageHeight, 10 | getElementPath, 11 | getUrlPath, 12 | getElementType, 13 | getElementClickable, 14 | getEleContent, 15 | getDeviceType, 16 | getElementId, 17 | getElementName, 18 | getElementClassName, 19 | getElementTargetUrl 20 | } from '../../heatmap/lib/getField.js' 21 | export default { 22 | xcontext: { 23 | $page_width: { 24 | valueType: 0, 25 | value: getPageWidth 26 | }, 27 | $page_height: { 28 | valueType: 0, 29 | value: getPageHeight 30 | }, 31 | $element_path: { 32 | valueType: 0, 33 | value: getElementPath 34 | }, 35 | $url_path: { 36 | valueType: 0, 37 | value: getUrlPath 38 | }, 39 | $element_type: { 40 | valueType: 0, 41 | value: getElementType 42 | }, 43 | $element_clickable: { 44 | valueType: 0, 45 | value: getElementClickable 46 | }, 47 | $element_content: { 48 | valueType: 0, 49 | value: getEleContent 50 | }, 51 | $device_type: { 52 | valueType: 0, 53 | value: getDeviceType 54 | }, 55 | $element_id: { 56 | valueType: 0, 57 | value: getElementId 58 | }, 59 | $element_name: { 60 | valueType: 0, 61 | value: getElementName 62 | }, 63 | $element_target_url: { 64 | valueType: 0, 65 | value: getElementTargetUrl 66 | }, 67 | $element_class_name: { 68 | valueType: 0, 69 | value: getElementClassName 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/configure/customized/userClick/configure/fieldTemplate.js: -------------------------------------------------------------------------------- 1 | /** 2 | * SDK 基础字段定义表 3 | * base.outer:上报日志基础结构定义 4 | * base.xcontext:上报报文找中xcontext下的共有字段定义 5 | * $开头的字段为各个事件特殊拥有字段 6 | */ 7 | export default { 8 | $user_click: { 9 | xcontext: [ 10 | // '$page_width', 11 | // '$page_height', 12 | '$url_path', 13 | '$url', 14 | '$title', 15 | '$is_first_day', 16 | '$session_id', 17 | '$is_time_calibrated', 18 | '$device_type', 19 | '$element_type', 20 | '$element_path', 21 | '$element_content', 22 | '$element_id', 23 | '$element_name', 24 | '$element_target_url', 25 | '$element_class_name' 26 | ] 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/configure/customized/userClick/configure/lifecycle.js: -------------------------------------------------------------------------------- 1 | import { userClickInit } from '../lib/userClick.js' 2 | 3 | export default { 4 | AnalysysAgent: { 5 | init: userClickInit 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/configure/customized/userClick/index.js: -------------------------------------------------------------------------------- 1 | import fieldRules from './configure/fieldRules.js' 2 | import fieldTemplate from './configure/fieldTemplate.js' 3 | import lifecycle from './configure/lifecycle.js' 4 | export { 5 | fieldRules, 6 | fieldTemplate, 7 | lifecycle 8 | } 9 | -------------------------------------------------------------------------------- /src/configure/customized/userClick/lib/userClick.js: -------------------------------------------------------------------------------- 1 | import Util from '../../../../lib/common/index.js' 2 | import { 3 | getElementClickable, 4 | elePostion, 5 | getParentClickableElement, 6 | } from '../../heatmap/lib/getField.js' 7 | var userClickConfig = {} 8 | 9 | function addClickEvent (event) { 10 | var e = event || window.event 11 | if (e.touches && e.touches.length > 0) { 12 | e = e.touches[0] 13 | } 14 | var ele = e.target || e.srcElement 15 | if (Util.checkTypeList(userClickConfig.autoClickBlackList, ele) || 16 | (userClickConfig.autoClickWhiteList && 17 | !Util.checkTypeList(userClickConfig.autoClickWhiteList, ele))) return 18 | elePostion.ele = ele 19 | getParentClickableElement() 20 | if (getElementClickable() !== 1) return 21 | var config = userClickConfig.user_click_property 22 | var userClickPro = {} 23 | if (Util.paramType(config) === 'Object') { 24 | for (var key in config) { 25 | if (Util.paramType(config[key]) === 'Function') { 26 | config[key] = config[key].call(config[key], ele) 27 | } 28 | } 29 | userClickPro = config 30 | } else if (Util.paramType(config) === 'Function') { 31 | userClickPro = config.call(config, ele) 32 | } 33 | 34 | var property = elePostion.ele.getAttribute('data-ark-click') || {} 35 | if (Util.paramType(property) === 'String') { 36 | try { 37 | property = JSON.parse(property) 38 | } catch (e) { } 39 | } 40 | if (Util.paramType(property) !== 'Object') { 41 | property = {} 42 | } 43 | if (Util.paramType(userClickPro) === 'Object') { 44 | property = Util.objMerge(userClickPro, property) 45 | } 46 | window.AnalysysAgent.freeApi('$user_click', property) 47 | } 48 | 49 | function addListenerUserClick () { 50 | if (Util.deviceType() === 'desktop') { 51 | Util.addEvent(document, 'mousedown', addClickEvent) 52 | } else { 53 | Util.addEvent(document, 'touchstart', addClickEvent) 54 | } 55 | } 56 | 57 | function userClickInit (config) { 58 | userClickConfig = config 59 | if (config.autoTrack === true) { 60 | addListenerUserClick() 61 | } 62 | return config 63 | } 64 | 65 | 66 | export { userClickInit } 67 | -------------------------------------------------------------------------------- /src/configure/customized/visual/configure/fieldRules.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 字段填充、字段校验规则模板 3 | * 4 | * check:数据合法检测方法列表,每个方法返回bool值,以用户为准,同名覆盖 5 | * 6 | */ 7 | export default { 8 | 'visitorConfigURL ': { 9 | check: { 10 | value: ['isUrl'] 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/configure/customized/visual/configure/fieldTemplate.js: -------------------------------------------------------------------------------- 1 | /** 2 | * SDK 基础字段定义表 3 | * base.outer:上报日志基础结构定义 4 | * base.xcontext:上报报文找中xcontext下的共有字段定义 5 | * $开头的字段为各个事件特殊拥有字段 6 | */ 7 | export default { 8 | } 9 | -------------------------------------------------------------------------------- /src/configure/customized/visual/configure/lifecycle.js: -------------------------------------------------------------------------------- 1 | import { visitorInit } from '../lib/visitor.js' 2 | export default { 3 | AnalysysAgent: { 4 | init: visitorInit 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/configure/customized/visual/index.js: -------------------------------------------------------------------------------- 1 | import fieldRules from './configure/fieldRules.js' 2 | import fieldTemplate from './configure/fieldTemplate.js' 3 | import lifecycle from './configure/lifecycle.js' 4 | export { 5 | fieldRules, 6 | fieldTemplate, 7 | lifecycle 8 | } 9 | -------------------------------------------------------------------------------- /src/configure/customized/visual/visualShow/common/boxMove.js: -------------------------------------------------------------------------------- 1 | import Util from '../../../../../lib/common/index.js' 2 | 3 | function MoveBox () { 4 | var _this = this 5 | this.ele = null 6 | this.parent = null 7 | this.parentOption = { 8 | x: 0, 9 | y: 0 10 | } 11 | this.touchOption = { 12 | x: 0, 13 | y: 0 14 | } 15 | 16 | function down (event) { 17 | event.preventDefault() 18 | var touch 19 | if (event.touches) { 20 | touch = event.touches[0] 21 | } else { 22 | touch = event 23 | } 24 | 25 | _this.touchOption = { 26 | x: touch.clientX, 27 | y: touch.clientY 28 | } 29 | _this.parentOption = { 30 | x: _this.parent.offsetLeft, 31 | y: _this.parent.offsetTop 32 | } 33 | Util.addEvent(document, 'touchmove', function () { 34 | event.preventDefault() 35 | }, false) 36 | Util.addEvent(document, 'mousemove', move, false) 37 | Util.addEvent(document, 'mouseup', end, false) 38 | 39 | Util.addEvent(document, 'touchmove', move, false) 40 | Util.addEvent(document, 'touchend', end, false) 41 | } 42 | 43 | function move (event) { 44 | var touch 45 | if (event.touches) { 46 | touch = event.touches[0] 47 | } else { 48 | touch = event 49 | } 50 | var x = _this.parentOption.x + touch.clientX - _this.touchOption.x 51 | var y = _this.parentOption.y + touch.clientY - _this.touchOption.y 52 | 53 | _this.parent.style.left = x + 'px' 54 | _this.parent.style.top = y + 'px' 55 | // _this.parentOption = { 56 | // x: x, 57 | // y: y 58 | // } 59 | } 60 | 61 | function end (event) { 62 | Util.removeEvent(document, 'touchmove', function () { 63 | event.preventDefault() 64 | }, false) 65 | 66 | Util.removeEvent(document, 'touchmove', move, false) 67 | Util.removeEvent(document, 'touchend', end, false) 68 | 69 | Util.removeEvent(document, 'mousemove', move, false) 70 | Util.removeEvent(document, 'mouseup', end, false) 71 | } 72 | this.init = function (ele) { 73 | this.ele = ele 74 | this.parent = this.ele.parentNode 75 | 76 | Util.addEvent(_this.ele, 'mousedown', down, false) 77 | Util.addEvent(_this.ele, 'touchstart', down, false) 78 | } 79 | 80 | this.remove = function () { 81 | if (!this.ele) return 82 | Util.removeEvent(document, 'mousedown', down, false) 83 | Util.removeEvent(document, 'touchstart', down, false) 84 | } 85 | } 86 | export default new MoveBox() 87 | -------------------------------------------------------------------------------- /src/configure/customized/visual/visualShow/common/config.js: -------------------------------------------------------------------------------- 1 | var visualConfig = window.ARK_VISUAL && window.ARK_VISUAL.config 2 | 3 | export { visualConfig } 4 | -------------------------------------------------------------------------------- /src/configure/customized/visual/visualShow/common/iframeMsg.js: -------------------------------------------------------------------------------- 1 | import Util from '../../../../../lib/common/index.js' 2 | 3 | /** 4 | * [sendMsg description]发送热图SDK初始化完毕信息 5 | * @return {[type]} [description] 6 | */ 7 | function sendMsg (msg) { 8 | console.log('发送可视化SDK初始化完毕消息===>', JSON.stringify(msg, null, 2)) 9 | 10 | if (Util.paramType(msg) === 'Object') { 11 | msg = JSON.stringify(msg) 12 | } 13 | window.parent.postMessage(msg, '*') 14 | } 15 | 16 | /** 17 | * [getMsg description]接收iframe消息 18 | * @param {Function} callback [description] 19 | * @return {[type]} [description] 20 | */ 21 | function getMsg (callback) { 22 | Util.addEvent(window, 'message', function (msgObj) { 23 | var msg = msgObj.data 24 | try { 25 | if (Util.paramType(msg) === 'String') { 26 | msg = JSON.parse(msg) 27 | } 28 | } catch (e) { } 29 | console.log('获取可视化消息===>', JSON.stringify(msg, null, 2)) 30 | callback(msg) 31 | }) 32 | } 33 | export { 34 | sendMsg, 35 | getMsg 36 | } 37 | -------------------------------------------------------------------------------- /src/configure/customized/visual/visualShow/index.js: -------------------------------------------------------------------------------- 1 | import { isElmentReady } from './common/index.js' 2 | import { visualConfig } from './common/config.js' 3 | import { sendMsg } from './common/iframeMsg.js' 4 | import { addVisualListener, delEvents, showVisualEvent, delVisualEvent, openVisualEvent, hiddenVisualEvent, backProInputList, openDebugModule, openDebugEvent, setVisualStatus } from './visual/index.js' 5 | // import { addDebugListener, removeDebugListener, openDebugBox, delDebugBox, hiddenDebugEvent } from './debug/index.js' 6 | import Util from '../../../../lib/common/index.js' 7 | var isVisaulInit = true 8 | var visualStatus = false 9 | var highlightStatus = true 10 | 11 | /** 12 | * 监听服务端iframeMessage消息 13 | * 14 | * @param {JSON} msg 消息 15 | */ 16 | function processMsg (msg) { 17 | if (!isVisaulInit) { 18 | return 19 | } 20 | var eventList = [] 21 | var type = msg.type 22 | // var url = window.location.protocol + '//' + window.location.host + window.location.pathname + window.location.hash 23 | switch (type) { 24 | case 'INIT': // 初始化验证 25 | if (msg.appid !== visualConfig.appid) { 26 | sendMsg({ 27 | code: 400, 28 | type: 'INIT', 29 | msg: 'appkey不相同' 30 | }) 31 | isVisaulInit = false 32 | return 33 | } 34 | sendMsg({ 35 | code: 200, 36 | type: 'INIT', 37 | isNewVisual: true 38 | }) 39 | var obj = { 40 | type: 'checkUrl', 41 | code: 200, 42 | url: window.location.href, 43 | skip: true 44 | } 45 | sendMsg(obj) 46 | setVisualStatus(msg.isNewVisual || false) 47 | sendChangeUrl() 48 | break 49 | case 'point_list': // 所有已埋点元素绑定debug模式 50 | 51 | eventList = msg.data || [] 52 | if (highlightStatus === false) { 53 | return 54 | } 55 | if (!isElmentReady() || document.readyState !== 'complete') { 56 | setTimeout(function () { 57 | processMsg(msg) 58 | }, 1000) 59 | return 60 | } else { 61 | var pageList = showVisualEvent(eventList) 62 | sendMsg({ 63 | type: 'check_points', 64 | list: pageList 65 | }) 66 | } 67 | break 68 | // case 'EVENT_URL': 69 | // // 验证埋点元素是否为当前页元素 70 | 71 | // var eventUrlObj = { 72 | // type: 'checkUrl', 73 | // code: 200, 74 | // url: url, 75 | // skip: msg.url === url 76 | // } 77 | // sendMsg(eventUrlObj) 78 | // break 79 | case 'VISUAL': 80 | if (highlightStatus === false) { 81 | visualStatus = msg.visual || false 82 | return 83 | } 84 | if (msg.visual === true) { 85 | // 开始初始化可视化埋点 86 | openDebugModule(false) 87 | 88 | } else if (msg.debugmode === true) { 89 | // 开始初始化debug模式 90 | openDebugModule(true) 91 | } 92 | if (highlightStatus === true) { 93 | addVisualListener() 94 | } 95 | break 96 | case 'change_update': 97 | if (highlightStatus === false) { 98 | return 99 | } 100 | if (msg.path && msg.path.length > 0) { 101 | // if (msg.path[0].url.charAt(msg.path[0].url.length - 1) === '/' && url.charAt(url.length - 1) !== '/') { 102 | // url += '/' 103 | // } 104 | // if (url !== msg.path[0].url) { 105 | // sendMsg({ 106 | // type: 'change_page', 107 | // code: 200, 108 | // msg: '跳转埋点页面', 109 | // path: msg.path, 110 | // url: url 111 | // }) 112 | // } else { 113 | openVisualEvent(msg.path[0]) 114 | // } 115 | } 116 | break 117 | case 'change_delete': 118 | if (visualStatus === false) { 119 | openDebugModule(false) 120 | } 121 | 122 | if (msg.path && msg.path.length > 0) { 123 | delVisualEvent(msg.path[0]) 124 | sendMsg({ 125 | code: 200, 126 | type: 'change_delete' 127 | }) 128 | } else { 129 | sendMsg({ 130 | code: 400, 131 | type: 'change_delete', 132 | msg: '删除失败' 133 | }) 134 | } 135 | break 136 | case 'add_success': 137 | sendMsg({ 138 | code: 200, 139 | type: 'add_success', 140 | msg: '添加成功' 141 | }) 142 | break 143 | case 'success_update': 144 | if (msg.path && msg.path.length > 0) { 145 | showVisualEvent(msg.path) 146 | } 147 | break 148 | case 'debug': 149 | // openDebugBox(msg) 150 | openDebugEvent(msg) 151 | break 152 | case 'highlight': 153 | highlightStatus = msg.highlight 154 | // if (highlightStatus === true) { 155 | // showVisualEvent(eventList) 156 | // } 157 | // if (visualStatus) { 158 | hiddenVisualEvent(highlightStatus) 159 | 160 | // } else { 161 | // hiddenVisualEvent(highlightStatus) 162 | 163 | // } 164 | break 165 | case 'like_pro': 166 | backProInputList(msg) 167 | break 168 | } 169 | } 170 | /** 171 | * [initHeatmap description]初始化可视化并建立通讯 172 | * @return {[type]} [description] 173 | */ 174 | function initVisual () { 175 | Util.changeHash(function () { 176 | highlightStatus = true 177 | visualStatus = true 178 | delEvents() 179 | hiddenVisualEvent(true) 180 | sendChangeUrl() 181 | }) 182 | } 183 | // } 184 | function sendChangeUrl () { 185 | // var url = window.location.protocol + '//' + window.location.host + window.location.pathname + window.location.hash 186 | sendMsg({ 187 | type: 'change_page_now', 188 | code: 200, 189 | msg: '跳转埋点页面', 190 | url: window.location.href.replace('?visual=true&', '?').replace('?visual=true', '') 191 | }) 192 | } 193 | if (window.ARK_VISUAL) { 194 | initVisual() 195 | } 196 | window.AnalysysModule = Util.objMerge(window.AnalysysModule || {}, { 197 | visual: { 198 | init: initVisual, 199 | msg: processMsg, 200 | version: '4.5.1' 201 | } 202 | }) -------------------------------------------------------------------------------- /src/configure/customized/visual/visualShow/templete/debug.js: -------------------------------------------------------------------------------- 1 | var debugTemp = '
' + 2 | '
' + 3 | '
{LOGLIST}
' + 4 | '' + 5 | '
' 6 | 7 | function setDebugTemp (config) { 8 | if (!config) return 9 | 10 | var list = '' 11 | for (var i = 0; i < config.list.length; i++) { 12 | list += '
' + config.list[i].title + ':' + config.list[i].val + '
' 13 | } 14 | var temp = debugTemp.replace('{TOP}', config.top) 15 | .replace('{LEFT}', config.left) 16 | .replace('{LOGLIST}', list) 17 | return temp 18 | } 19 | export { setDebugTemp } 20 | -------------------------------------------------------------------------------- /src/configure/customized/webstay/configure/fieldRules.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 字段填充、字段校验规则模板 3 | * 4 | * check:数据合法检测方法列表,每个方法返回bool值,以用户为准,同名覆盖 5 | * 6 | */ 7 | import { getViewPortWidth, getViewPortHeight, getScrollTop, getDuration, getDeviceType } from '../lib/getField.js' 8 | export default { 9 | autoWebstay: { 10 | check: { 11 | value: ['isBoolean'] 12 | } 13 | }, 14 | xcontext: { 15 | $viewport_width: { 16 | valueType: 0, 17 | value: getViewPortWidth 18 | }, 19 | $viewport_position: { 20 | valueType: 0, 21 | value: getScrollTop 22 | }, 23 | $viewport_height: { 24 | valueType: 0, 25 | value: getViewPortHeight 26 | }, 27 | $event_duration: { 28 | valueType: 0, 29 | value: getDuration 30 | }, 31 | $device_type: { 32 | valueType: 0, 33 | value: getDeviceType 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/configure/customized/webstay/configure/fieldTemplate.js: -------------------------------------------------------------------------------- 1 | /** 2 | * SDK 基础字段定义表 3 | * base.outer:上报日志基础结构定义 4 | * base.xcontext:上报报文找中xcontext下的共有字段定义 5 | * $开头的字段为各个事件特殊拥有字段 6 | */ 7 | export default { 8 | $webstay: { 9 | xcontext: [ 10 | '$referrer', 11 | '$referrer_domain', 12 | '$title', 13 | '$url', 14 | '$viewport_width', 15 | '$viewport_position', 16 | '$viewport_height', 17 | '$event_duration', 18 | '$device_type', 19 | '$session_id', 20 | '$is_time_calibrated', 21 | '$is_first_day' 22 | ] 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/configure/customized/webstay/configure/lifecycle.js: -------------------------------------------------------------------------------- 1 | import { autoWebstayInit } from '../lib/autoWebstay.js' 2 | 3 | export default { 4 | AnalysysAgent: { 5 | init: autoWebstayInit 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/configure/customized/webstay/index.js: -------------------------------------------------------------------------------- 1 | import fieldRules from './configure/fieldRules.js' 2 | import fieldTemplate from './configure/fieldTemplate.js' 3 | import lifecycle from './configure/lifecycle.js' 4 | export { 5 | fieldRules, 6 | fieldTemplate, 7 | lifecycle 8 | } 9 | -------------------------------------------------------------------------------- /src/configure/customized/webstay/lib/autoWebstay.js: -------------------------------------------------------------------------------- 1 | import Util from '../../../../lib/common/index.js' 2 | import { isElmentReady } from '../../heatmap/heatmapSDK/common/index.js' 3 | import { setRootEle } from './getField.js' 4 | var interval = null 5 | var topValue = 0 6 | 7 | function initWebStay () { 8 | // var scroll = window.onscroll 9 | // window.onscroll = function () { 10 | // if (scroll && Util.paramType(scroll) === 'Function') { 11 | // scroll() 12 | // } 13 | // clearTimeout(interval) 14 | // interval = setTimeout(isScroll, 1000) 15 | // topValue = document.documentElement.scrollTop || document.body.scrollTop 16 | // } 17 | function getScroll () { 18 | if (isRoot === true) { 19 | return document.documentElement.scrollTop || document.body.scrollTop 20 | } else { 21 | return rootEle.scrollTop || 0 22 | } 23 | } 24 | function isScroll () { 25 | var m2 = getScroll() 26 | if (topValue === m2) { 27 | clearTimeout(interval) 28 | interval = null 29 | 30 | if (!window.AnalysysAgent || !window.AnalysysAgent.freeApi) { 31 | setTimeout(function () { isScroll() }, 100) 32 | } else { 33 | window.AnalysysAgent.freeApi('$webstay') 34 | } 35 | } 36 | } 37 | Util.addEvent(rootEle, 'scroll', function () { 38 | clearTimeout(interval) 39 | interval = setTimeout(isScroll, 1000) 40 | topValue = getScroll() 41 | }) 42 | // setTimeout(startScroll, 1000) 43 | } 44 | 45 | // function startScroll () { 46 | // if (!window.AnalysysAgent || !window.AnalysysAgent.freeApi || !document.body) { 47 | // setTimeout(function () { startScroll() }, 100) 48 | // } else { 49 | // var fristScrollTop = document.documentElement.scrollTop || document.body.scrollTop 50 | // if (fristScrollTop === 0) { 51 | 52 | // window.AnalysysAgent.freeApi('$webstay') 53 | // } 54 | // } 55 | // } 56 | function getChildEle (ele) { 57 | var parentEle = ele || document.body 58 | var childList = parentEle.childNodes 59 | var scrollEle = document.body 60 | for (var i = 0; i < childList.length; i++) { 61 | if (childList[i].nodeType === 1) { 62 | if (hasScrollbar(childList[i]) === true) { 63 | isRoot = false 64 | return childList[i] 65 | } else { 66 | scrollEle = getChildEle(childList[i]) 67 | } 68 | } 69 | } 70 | return scrollEle 71 | } 72 | function hasScrollbar (ele) { 73 | 74 | var scrollHeight = 0 75 | var innerHeight = 0 76 | var baseHeight = document.body.scrollHeight 77 | if (ele) { 78 | scrollHeight = ele.scrollHeight 79 | innerHeight = ele.clientHeight 80 | } else { 81 | scrollHeight = document.body.scrollHeight 82 | innerHeight = window.innerHeight || document.documentElement.clientHeight 83 | } 84 | return scrollHeight > innerHeight && scrollHeight > baseHeight 85 | } 86 | 87 | var rootEle = null 88 | var isRoot = true 89 | function getRootEle (config) { 90 | var userEle = null 91 | 92 | if (config.autoHeatmap === true && config.autoWebstay === true && config.isHybrid === false) { 93 | var webstayRootEleConfig = config.webstayRootEle 94 | 95 | if (webstayRootEleConfig) { 96 | if (Util.paramType(webstayRootEleConfig) === 'String') { 97 | var eleList = Util.selectorAllEleList(webstayRootEleConfig) 98 | if (eleList.length > 0) { 99 | userEle = eleList[0] 100 | } 101 | } else if (Util.paramType(webstayRootEleConfig) === 'Function') { 102 | userEle = webstayRootEleConfig.call(webstayRootEleConfig) || null 103 | } else if (typeof webstayRootEleConfig === 'object' && webstayRootEleConfig.nodeType === 1) { 104 | userEle = webstayRootEleConfig 105 | } 106 | } 107 | if (userEle) { 108 | isRoot = false 109 | rootEle = userEle 110 | } else { 111 | rootEle = getChildEle() 112 | } 113 | if (rootEle === document.body || !rootEle) { 114 | rootEle = window 115 | } 116 | setRootEle(rootEle) 117 | initWebStay() 118 | } 119 | 120 | } 121 | function autoWebstayInit (config) { 122 | if (window.location.href.indexOf('visual=true') > -1 || window.location.href.indexOf('arkheatmap=true') > -1) { 123 | return config 124 | } 125 | if (isElmentReady() === false) { 126 | setTimeout(function () { 127 | autoWebstayInit(config) 128 | }, 300) 129 | } else { 130 | getRootEle(config) 131 | } 132 | return config 133 | } 134 | 135 | export { autoWebstayInit } 136 | -------------------------------------------------------------------------------- /src/configure/customized/webstay/lib/getField.js: -------------------------------------------------------------------------------- 1 | import Util from '../../../../lib/common/index.js' 2 | import conifg from '../../../../lib/baseConfig/index.js' 3 | var startDate = +new Date() 4 | var root = null 5 | 6 | function setRootEle (ele) { 7 | if (ele) { 8 | root = ele 9 | } else { 10 | root = document.body 11 | } 12 | } 13 | // 获取浏览器窗口的可视区域的宽度 14 | function getViewPortWidth () { 15 | return document.documentElement.clientWidth || document.body.clientWidth 16 | } 17 | 18 | // 获取浏览器窗口的可视区域的高度 19 | function getViewPortHeight () { 20 | return document.documentElement.clientHeight || document.body.clientHeight 21 | } 22 | 23 | // 获取浏览器窗口垂直滚动条的位置 24 | function getScrollTop () { 25 | return root.scrollTop || document.documentElement.scrollTop || document.body.scrollTop 26 | } 27 | 28 | function getDuration () { 29 | var nowTime = +new Date() 30 | var duration = nowTime - startDate 31 | startDate = nowTime 32 | if (Util.paramType(conifg.base.webstayDuration) === 'Number' && conifg.base.webstayDuration > 0) { 33 | if (duration > conifg.base.webstayDuration) { 34 | return conifg.base.webstayDuration 35 | } 36 | } else { 37 | if (duration > 5 * 60 * 60 * 1000) { 38 | return 5 * 60 * 60 * 1000 39 | } 40 | } 41 | return duration 42 | } 43 | function getDeviceType () { 44 | return Util.deviceType() 45 | } 46 | export { getViewPortWidth, getViewPortHeight, getScrollTop, getDuration, getDeviceType, setRootEle } 47 | -------------------------------------------------------------------------------- /src/configure/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 合并定制模块 3 | * 4 | * base:基础模块 5 | * encrypt:数据加密模块 6 | * visitor:可视化模块 7 | * webstay:深度线采集模块 8 | * zh:招行模块 9 | * heatmap:热图采集及展示模块 10 | * device:设备信息模块 11 | * ua:上报ua模块 12 | * errorLog:校验失败上报$errorLog模块 13 | */ 14 | import * as base from './base/index.js' 15 | import * as webstay from './customized/webstay/index.js' 16 | import * as heatmap from './customized/heatmap/index.js' 17 | import * as ua from './customized/UA/index.js' 18 | import * as userClick from './customized/userClick/index.js' 19 | import Util from '../lib/common/index.js' 20 | 21 | var plugList = [webstay, heatmap, ua, userClick] 22 | /** 23 | * 合并定制化模板 根据输入模板列表不同集合出不同的定制化模板 24 | */ 25 | var fieldRules = base.fieldRules || {} 26 | var fieldTemplate = base.fieldTemplate || {} 27 | var lifecycle = base.lifecycle || {} 28 | for (var i = 0; i < plugList.length; i++) { 29 | if (plugList[i].fieldRules) { 30 | fieldRules = Util.objMerge(fieldRules, plugList[i].fieldRules) 31 | } 32 | if (plugList[i].fieldTemplate) { 33 | fieldTemplate = Util.objMerge(fieldTemplate, plugList[i].fieldTemplate) 34 | } 35 | if (plugList[i].lifecycle) { 36 | lifecycle = Util.fnMerge(lifecycle, plugList[i].lifecycle) 37 | } 38 | } 39 | export { fieldRules, fieldTemplate, lifecycle } 40 | -------------------------------------------------------------------------------- /src/lib/baseConfig/index.js: -------------------------------------------------------------------------------- 1 | import fieldTemplate from '../../configure/base/fieldTemplate.js' 2 | export default { 3 | base: { 4 | appid: '', // APPID 5 | $debug: 0, // debug状态 6 | uploadURL: '', // 上传地址 7 | auto: true, // 自动采集页面打开 8 | autoProfile: true, //自动采集用户首次属性 9 | hash: true, // 自动采集单页面应用 10 | autoWebstay: true, // 自动采集访问深度 11 | singlePage: true, // 自动采集单页面应用 12 | pageProperty: {}, // 自动采集页面打开时页面自定义属性 13 | $lib_version: '4.5.6', // sdk版本号 14 | cross_subdomain: true, // 跨子域存储cookie 15 | cross_subdomain_super: true, // 同步跨子域存储cookie时 同步通用属性 16 | allowTimeCheck: false, // ajax上报日志 开启时间校准 17 | isHybrid: false, // 是否为Hybrid模式 18 | getDataTimeout: 10000, // 获取数据超时时间 19 | sendDataTimeout: 10000,// 上报数据超时时间 20 | isMessageSDK: false 21 | }, 22 | status: { 23 | code: 200, 24 | FnName: '', 25 | key: '', 26 | value: '', 27 | errorCode: '', 28 | successCode: '' 29 | }, 30 | keywords: fieldTemplate.base.xcontext, 31 | baseJson: fieldTemplate.base.outer, 32 | sendNum: 1800, 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/lib/checkField/index.js: -------------------------------------------------------------------------------- 1 | import Util from '../common/index.js' 2 | import baseConfig from '../baseConfig/index.js' 3 | var CheckField = function () { 4 | 5 | } 6 | CheckField.prototype = Util 7 | 8 | CheckField.prototype.isString = function (val) { 9 | baseConfig.status.errorCode = '60001' 10 | return Util.paramType(val) === 'String' 11 | } 12 | CheckField.prototype.isNumber = function (val) { 13 | baseConfig.status.errorCode = '60002' 14 | return Util.paramType(val) === 'Number' 15 | } 16 | CheckField.prototype.isBoolean = function (val) { 17 | baseConfig.status.errorCode = '60003' 18 | return Util.paramType(val) === 'Boolean' 19 | } 20 | CheckField.prototype.isObject = function (val) { 21 | return this.paramType(val) === 'Object' 22 | } 23 | CheckField.prototype.lengthRule = function (val, min, max) { 24 | if (!this.isNumber(max)) { 25 | max = Infinity 26 | } 27 | var status = true 28 | 29 | if (!(this.isNumber(min) && val.length && val.length > min && val.length < max + 1)) { 30 | baseConfig.status.errorCode = '60005' 31 | status = false 32 | } 33 | 34 | return status 35 | } 36 | CheckField.prototype.nimLength = function (val) { 37 | return this.lengthRule(val, 0) 38 | } 39 | CheckField.prototype.length99 = function (val) { 40 | var lengthStatus = this.lengthRule(val, 0, 99) 41 | if (!lengthStatus) { 42 | baseConfig.status.errorCode = '600010' 43 | } 44 | return lengthStatus 45 | } 46 | CheckField.prototype.length125 = function (val) { 47 | var lengthStatus = this.lengthRule(val, 0, 125) 48 | if (!lengthStatus) { 49 | baseConfig.status.errorCode = '60009' 50 | } 51 | return lengthStatus 52 | } 53 | CheckField.prototype.length255 = function (val) { 54 | if (!val && !this.isString(val) && !this.isNumber(val) && !this.isBoolean(val)) { 55 | baseConfig.status.errorCode = '60005' 56 | return false 57 | } 58 | if (this.paramType(val) !== 'String') { 59 | val = val.toString() 60 | } 61 | var lengthStatus = this.lengthRule(val, 0, 255) 62 | if (!lengthStatus) { 63 | baseConfig.status.errorCode = '600019' 64 | } 65 | return lengthStatus 66 | } 67 | CheckField.prototype.keyLength255 = function (val) { 68 | var lengthStatus = this.length255(val) 69 | if (!lengthStatus) { 70 | baseConfig.status.errorCode = '600017' 71 | } 72 | return lengthStatus 73 | } 74 | 75 | CheckField.prototype.isUrl = function (URL) { 76 | var str = URL 77 | // 判断URL地址的正则表达式为:http(s)?://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)? 78 | // 下面的代码中应用了转义字符"\"输出一个字符"/" 79 | var Expression = /http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- ./?%&=]*)?/ 80 | var objExp = new RegExp(Expression) 81 | if (objExp.test(str) === true) { 82 | return true 83 | } else { 84 | baseConfig.status.errorCode = '60006' 85 | return false 86 | } 87 | } 88 | 89 | CheckField.prototype.isDebug = function (val) { 90 | if (this.isNumber(val) && (val === 0 || val === 1 || val === 2)) { 91 | return true 92 | } 93 | return false 94 | } 95 | CheckField.prototype.notObject = function (val) { 96 | var status = !this.isObject(val) 97 | if (!status) { 98 | baseConfig.status.errorCode = '600020' 99 | } 100 | return status 101 | } 102 | 103 | CheckField.prototype.notSpecialCharacters = function (val) { 104 | var patrn = new RegExp('[\\u4E00-\\u9FA5]|[\\uFE30-\\uFFA0]', 'gi') 105 | var reg = /^[$a-zA-Z][a-zA-Z0-9_$]{0,}$/ 106 | if (patrn.test(val) || !reg.test(val)) { 107 | baseConfig.status.errorCode = '600011' 108 | return false 109 | } 110 | return true 111 | } 112 | CheckField.prototype.isArrayString = function (val) { 113 | if (this.paramType(val) === 'Array') { 114 | for (var i = 0; i < val.length; i++) { 115 | if (this.paramType(val[i]) !== 'String') { 116 | baseConfig.status.errorCode = '600013' 117 | return false 118 | } 119 | if (!this.length255(val[i])) { 120 | if (val[i] && val[i].length > 500) { 121 | val[i] = Util.stringSlice(val[i], 499) + '$' 122 | } 123 | baseConfig.status.value = val[i] 124 | return false 125 | } 126 | } 127 | } 128 | return true 129 | } 130 | CheckField.prototype.keywords = function (val) { 131 | var key = baseConfig.keywords 132 | if (key.indexOf(val) > -1) { 133 | baseConfig.status.errorCode = '600012' 134 | return false 135 | } 136 | return true 137 | } 138 | 139 | export default new CheckField() 140 | -------------------------------------------------------------------------------- /src/lib/compatible/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 兼容低版本API 3 | */ 4 | function ieCreat () { 5 | if (!Array.prototype.indexOf) { 6 | Array.prototype.indexOf = function (elt /*, from */) { 7 | var len = this.length >>> 0 8 | var from = Number(arguments[1]) || 0 9 | from = (from < 0) 10 | ? Math.ceil(from) 11 | : Math.floor(from) 12 | if (from < 0) { from += len } 13 | for (; from < len; from++) { 14 | if (from in this && 15 | this[from] === elt) { return from } 16 | } 17 | return -1 18 | } 19 | } 20 | } 21 | 22 | export { ieCreat } 23 | -------------------------------------------------------------------------------- /src/lib/fillField/UTM.js: -------------------------------------------------------------------------------- 1 | import Util from '../common/index.js' 2 | var UTM = { 3 | utm_campaign_id: Util.GetUrlParam('campaign_id'), 4 | utm_source: Util.GetUrlParam('utm_source') || Util.GetUrlParam('hmsr'), 5 | utm_medium: Util.GetUrlParam('utm_medium') || Util.GetUrlParam('hmpl'), 6 | utm_term: Util.GetUrlParam('utm_term') || Util.GetUrlParam('hmkw'), 7 | utm_content: Util.GetUrlParam('utm_content') || Util.GetUrlParam('hmci'), 8 | utm_campaign: Util.GetUrlParam('utm_campaign') || Util.GetUrlParam('hmcu') 9 | } 10 | function clearUTM () { 11 | UTM = { 12 | utm_campaign_id: '', 13 | utm_source: '', 14 | utm_medium: '', 15 | utm_term: '', 16 | utm_content: '', 17 | utm_campaign: '' 18 | } 19 | } 20 | export { UTM, clearUTM } 21 | -------------------------------------------------------------------------------- /src/lib/fillField/deviceType.js: -------------------------------------------------------------------------------- 1 | var ua = window.navigator.userAgent.toLowerCase() 2 | 3 | function isPhone () { 4 | var isMobile = /Mobile(\/|\s)/.test(ua) 5 | 6 | // Either: 7 | // - iOS but not iPad 8 | // - Android 2 9 | // - Android with "Mobile" in the UA 10 | 11 | return /(iPhone|iPod)/.test(ua) || 12 | (!/(Silk)/.test(ua) && (/(Android)/.test(ua) && (/(Android 2)/.test(ua) || isMobile))) || 13 | (/(BlackBerry|BB)/.test(ua) && isMobile) || 14 | /(Windows Phone)/.test(ua) 15 | } 16 | 17 | function isTablet () { 18 | return !isPhone() && (/iPad/.test(ua) || /Android/.test(ua) || /(RIM Tablet OS)/.test(ua) || 19 | (/MSIE 10/.test(ua) && /; Touch/.test(ua))) 20 | } 21 | 22 | function isMobile () { 23 | if (isPhone()) { 24 | return 'phone' 25 | } 26 | if (isTablet()) { 27 | return 'tablet' 28 | } 29 | return 'desktop' 30 | } 31 | var deviceType = isMobile() || '' 32 | export { deviceType } 33 | -------------------------------------------------------------------------------- /src/lib/fillField/getField.js: -------------------------------------------------------------------------------- 1 | import baseConfig from '../baseConfig/index.js' 2 | import Util from '../common/index.js' 3 | import Storage from '../storage/index.js' 4 | import sessionId from './sessionId.js' 5 | import { checkSpider } from './spider.js' 6 | import { UTM, clearUTM } from './UTM.js' 7 | 8 | import { getId, getUUId, getAliasId, getIdentifyId } from './id.js' 9 | 10 | var base = baseConfig.base 11 | 12 | function appkey (appkey) { 13 | base.appid = appkey 14 | } 15 | 16 | function getAppId () { 17 | return base.appid 18 | } 19 | 20 | function debugMode (debug) { 21 | base.$debug = debug 22 | } 23 | 24 | function getDebugMode () { 25 | return base.$debug 26 | } 27 | 28 | function uploadURL (url) { 29 | if (url.charAt(url.length - 1) !== '/') { 30 | url += '/' 31 | } 32 | base.uploadURL = url 33 | } 34 | 35 | function getUploadURL () { 36 | if (base.uploadURL.charAt(base.uploadURL.length - 1) !== '/') { 37 | base.uploadURL += '/' 38 | } 39 | return base.uploadURL 40 | } 41 | 42 | function nowDate () { 43 | return +new Date() + (Storage.getLocal('ANSSERVERTIME') ? Number(Storage.getLocal('ANSSERVERTIME')) : 0) 44 | } 45 | 46 | function timeCalibration () { 47 | if (Storage.getLocal('ANSSERVERTIME')) { 48 | return true 49 | } 50 | return false 51 | } 52 | 53 | function getXwhat () { 54 | return baseConfig.status.FnName 55 | } 56 | 57 | function isLogin () { 58 | var status = false 59 | if (getAliasId() || Storage.getLocal('ARK_TRACK_LOGIN')) { 60 | status = true 61 | } 62 | return status 63 | } 64 | 65 | var timeZone = 'GMT' + Util.clientTimeZone() 66 | 67 | var language = (navigator.language || navigator.browserLanguage).toLowerCase() 68 | 69 | // var device_type = deviceType 70 | 71 | function getSessionId () { 72 | return sessionId.getId() 73 | } 74 | 75 | function isFirstTime () { 76 | var timeStatus = Storage.getLocal('FRISTIME') 77 | Storage.setLocal('FRISTIME', false) 78 | return timeStatus 79 | } 80 | 81 | function isFirstDay () { 82 | var todayDate = Util.format(new Date(), 'yyyyMMdd') 83 | var storageDay = Storage.getLocal('FRISTDAY') 84 | if (storageDay && todayDate !== storageDay) { 85 | return false 86 | } 87 | // Storage.setLocal("FRISTDAY", todayDate) 88 | return true 89 | } 90 | 91 | function originalId () { 92 | return getIdentifyId() || getUUId() 93 | } 94 | var referrer = document.referrer || '' 95 | function setReferrer (ref) { 96 | referrer = ref 97 | } 98 | function getReferrer () { 99 | var refer = referrer 100 | try { 101 | refer = decodeURIComponent(referrer) 102 | } catch (e) { } 103 | if (baseConfig.base.isHybrid === true) { 104 | refer = refer.replace(/"/g, '\\"') 105 | } 106 | return refer 107 | } 108 | 109 | function getReferrerDomain () { 110 | return Util.getDomainFromUrl(false, referrer) 111 | } 112 | 113 | function getTitle () { 114 | return document.title 115 | } 116 | 117 | function startupTime () { 118 | return Storage.getSession('STARTUPTIME') || '' 119 | } 120 | 121 | function getUrl () { 122 | var url = window.location.href 123 | try { 124 | url = decodeURIComponent(url) 125 | } catch (e) { } 126 | if (baseConfig.base.isHybrid === true) { 127 | url = url.replace(/"/g, '\\"') 128 | } 129 | return url 130 | } 131 | 132 | function getLibVersion () { 133 | return base.$lib_version 134 | } 135 | 136 | function getScreenWidth () { 137 | var width = Util.paramType(Number(window.screen.width)) === 'Number' ? Number(window.screen.width) : 0 138 | return width 139 | } 140 | 141 | function getScreenHeight () { 142 | var height = Util.paramType(Number(window.screen.height)) === 'Number' ? Number(window.screen.height) : 0 143 | return height 144 | } 145 | /** 146 | * UTM参数控制逻辑 147 | * UTM参数改变切换session 148 | * UTM参数不满足条件 清空UTM参数 149 | */ 150 | 151 | var oldUTM = Storage.getSession('ARK_UTM') || '' 152 | 153 | if (UTM.utm_campaign || UTM.utm_source || UTM.utm_medium || UTM.utm_campaign_id || UTM.utm_term || UTM.utm_content) { 154 | if (oldUTM !== JSON.stringify(UTM)) { 155 | sessionId.setId() 156 | } 157 | Storage.setSession('ARK_UTM', JSON.stringify(UTM)) 158 | } else { 159 | clearUTM() 160 | Storage.removeSession('ARK_UTM') 161 | } 162 | 163 | function utmCampaignId () { 164 | return UTM.utm_campaign_id 165 | } 166 | 167 | function utmSource () { 168 | return UTM.utm_source 169 | } 170 | 171 | function utmMedium () { 172 | return UTM.utm_medium 173 | } 174 | 175 | function utmTerm () { 176 | return UTM.utm_term 177 | } 178 | 179 | function utmContent () { 180 | return UTM.utm_content 181 | } 182 | 183 | function utmCampaign () { 184 | return UTM.utm_campaign 185 | } 186 | 187 | export { 188 | getAppId, 189 | getId, 190 | getUploadURL, 191 | appkey, 192 | debugMode, 193 | uploadURL, 194 | getDebugMode, 195 | nowDate, 196 | getXwhat, 197 | isLogin, 198 | timeZone, 199 | language, 200 | getSessionId, 201 | isFirstTime, 202 | isFirstDay, 203 | originalId, 204 | getReferrer, 205 | getReferrerDomain, 206 | getTitle, 207 | getUrl, 208 | getScreenWidth, 209 | getScreenHeight, 210 | startupTime, 211 | checkSpider, 212 | getLibVersion, 213 | utmCampaignId, 214 | utmSource, 215 | utmMedium, 216 | utmTerm, 217 | utmContent, 218 | utmCampaign, 219 | timeCalibration, 220 | setReferrer 221 | // device_type 222 | } 223 | -------------------------------------------------------------------------------- /src/lib/fillField/id.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 用户ID 操作集 3 | * ARK_LOGINID>ARK_TRACKID>ARK_ID 4 | */ 5 | import Storage from '../storage/index.js' 6 | import Util from '../common/index.js' 7 | 8 | function getId () { 9 | var id = Storage.getLocal('ARK_LOGINID') || Storage.getLocal('ARK_TRACKID') || Storage.getLocal('ARK_ID') 10 | if (!id || id === '[object Object]') { 11 | id = setUUId() 12 | Storage.setLocal('ARK_ID', id) 13 | } 14 | // if(!Storage.getCookie("ARK_ID")){ 15 | Storage.setCookie('ARK_ID', getIdentifyId() || getUUId()) 16 | // } 17 | return id 18 | } 19 | 20 | function setUUId () { 21 | var timeRandom = (new Date().getTime()).toString() + (Math.random() * 10000).toString() 22 | var id = 'JS' + Util.MD5((timeRandom).toString(), 32) + Util.MD5((timeRandom).toString(), 32).slice(0, 4) 23 | 24 | // var storageId = Storage.getCookie("ARK_ID") 25 | // if (storageId && storageId.length > 10) { 26 | // id = Storage.getCookie("ARK_ID") 27 | // } 28 | Storage.setCookie('ARK_ID', id) 29 | return id 30 | } 31 | 32 | function getUUId () { 33 | var id = Storage.getLocal('ARK_ID') 34 | if (!id) { 35 | id = setUUId() 36 | Storage.setLocal('ARK_ID', id) 37 | } 38 | return id 39 | } 40 | 41 | function removeUUId () { 42 | Storage.removeLocal('ARK_ID') 43 | } 44 | 45 | function setAliasId (id) { 46 | Storage.setLocal('ARK_LOGINID', id) 47 | } 48 | 49 | function getAliasId () { 50 | return Storage.getLocal('ARK_LOGINID') 51 | } 52 | 53 | function removeAliasId () { 54 | Storage.removeLocal('ARK_LOGINID') 55 | } 56 | 57 | function setIdentifyId (id) { 58 | Storage.setLocal('ARK_TRACKID', id) 59 | } 60 | 61 | function getIdentifyId () { 62 | return Storage.getLocal('ARK_TRACKID') 63 | } 64 | 65 | function removeIdentifyId () { 66 | Storage.removeLocal('ARK_TRACK_LOGIN') 67 | Storage.removeLocal('ARK_TRACKID') 68 | } 69 | 70 | export { 71 | getId, 72 | setUUId, 73 | getUUId, 74 | removeUUId, 75 | setAliasId, 76 | getAliasId, 77 | removeAliasId, 78 | setIdentifyId, 79 | getIdentifyId, 80 | removeIdentifyId 81 | } 82 | -------------------------------------------------------------------------------- /src/lib/fillField/index.js: -------------------------------------------------------------------------------- 1 | import Util from '../common/index.js' 2 | import baseConfig from '../baseConfig/index.js' 3 | import Storage from '../storage/index.js' 4 | import { errorLog, successLog } from '../printLog/index.js' 5 | import checkRule from '../checkField/index.js' 6 | import { fieldRules } from '../../configure/index.js' 7 | import sessionId from './sessionId.js' 8 | 9 | import { removeAliasId, removeIdentifyId } from './id.js' 10 | 11 | function check (value, checkList) { 12 | for (var i = 0; i < checkList.length; i++) { 13 | var checkStatus = checkRule[checkList[i]](value) 14 | if (!checkStatus) { 15 | return false 16 | } 17 | } 18 | return true 19 | } 20 | 21 | function checkFields (key, value, rule) { 22 | var checkRule = rule.check 23 | var status = true 24 | if (!checkRule) { 25 | return status 26 | } 27 | 28 | var checkKey = checkRule.key 29 | var checkValue = checkRule.value || fieldRules.xcontextCommonRule.value 30 | 31 | if (checkKey) { 32 | baseConfig.status.code = 200 33 | status = check(key, checkKey) 34 | baseConfig.status.key = key 35 | if (!status) { 36 | baseConfig.status.code = 400 37 | errorLog() 38 | } 39 | } 40 | 41 | if (checkValue) { 42 | baseConfig.status.code = 200 43 | status = check(value, checkValue) 44 | if (Util.paramType(value) !== 'Array') { 45 | baseConfig.status.value = value 46 | } 47 | if (!status) { 48 | baseConfig.status.code = 400 49 | errorLog() 50 | } 51 | } 52 | 53 | // if (status && checkRule.successCode) { 54 | // baseConfig.status.successCode = checkRule.successCode 55 | // } 56 | return status 57 | } 58 | 59 | function resetCode () { 60 | baseConfig.status = { 61 | code: 200, 62 | FnName: baseConfig.status.FnName, 63 | key: '', 64 | value: '', 65 | errorCode: '', 66 | successCode: '' 67 | } 68 | } 69 | 70 | function fillField (feilds, rules) { 71 | var rulesList = rules || fieldRules 72 | var obj = {} 73 | for (var key in feilds) { 74 | var feild = feilds[key] 75 | var rule = rulesList[key] 76 | if (!rule) { 77 | continue 78 | } 79 | var feildValue = '' 80 | 81 | if (Util.paramType(feild) === 'Object') { 82 | var content = fillField(feild, rule) 83 | obj[key] = content 84 | } else { 85 | if (Util.objHasKay(rule, 'valueType')) { 86 | if (rule.valueType === 0) { 87 | feildValue = rule.value() 88 | if (Util.paramType(feildValue) === 'String' && feildValue.length > 500) { 89 | obj[key] = Util.stringSlice(feildValue, 499) + '$' 90 | } else { 91 | obj[key] = feildValue 92 | } 93 | // } 94 | // } 95 | } 96 | 97 | if (rule.valueType === 1) { 98 | feildValue = rule.value 99 | 100 | // if (checkFields(key, feildValue, rule)) { 101 | // obj[key] = feildValue 102 | // } else { 103 | // if (baseConfig.status.errorCode === '600019') { 104 | if (Util.paramType(feildValue) === 'String' && feildValue.length > 500) { 105 | obj[key] = Util.stringSlice(feildValue, 499) + '$' 106 | } else { 107 | obj[key] = feildValue 108 | } 109 | // } 110 | // } 111 | } 112 | } 113 | } 114 | } 115 | return obj 116 | } 117 | /** 118 | * [reset description]检测是否重置初始化状态 119 | * @return {[type]} [description] true:需初始化 false:无需初始化 120 | */ 121 | function clearCache (resetStatus) { 122 | resetStatus = resetStatus || false 123 | if (!resetStatus) { 124 | var config = baseConfig.base 125 | for (var key in config) { 126 | if (Util.paramType(config[key]) !== 'Object') { 127 | if (key === '$debug' || key === 'appid' || key === 'uploadURL') { 128 | var keyStorage = Storage.getLocal('ANS' + key.toUpperCase()) 129 | if (keyStorage !== config[key]) { 130 | resetStatus = true 131 | } 132 | if (resetStatus) { 133 | Storage.setLocal('ANS' + key.toUpperCase(), config[key]) 134 | } 135 | } 136 | } 137 | } 138 | } 139 | if (resetStatus) { 140 | removeAliasId() 141 | removeIdentifyId() 142 | Storage.removeLocal('ARKSUPER') 143 | Storage.removeSession('STARTUP') 144 | Storage.setLocal('FRISTDAY', Util.format(new Date(), 'yyyyMMdd')) 145 | Storage.setLocal('FRISTIME', true) 146 | Storage.removeLocal('POSTDATA') 147 | Storage.removeLocal('ANSSERVERTIME') 148 | Storage.removeLocal('ARKFRISTPROFILE') 149 | } 150 | return resetStatus 151 | } 152 | /** 153 | * [isStartUp description]检测启动状态 154 | * @return {Boolean} [description] true:已启动,false:未启动 155 | */ 156 | function isStartUp () { 157 | var startUpStatus = Storage.getSession('STARTUP') || false 158 | var cookieStartup = Storage.getCookie('ARK_STARTUP') 159 | if (document.referrer !== '' && cookieStartup && baseConfig.base.cross_subdomain === true) { 160 | var cookieObj = JSON.parse(Util.decode(decodeURIComponent(cookieStartup))) 161 | var cookieStartUpStatus = cookieObj['STARTUP'] 162 | var cookieStartUpTime = cookieObj['STARTUPTIME'] 163 | Storage.setSession('STARTUP', cookieStartUpStatus) 164 | Storage.setSession('STARTUPTIME', cookieStartUpTime) 165 | // Storage.removeCookie('ARK_STARTUP', baseConfig.base.cross_subdomain, 'session') 166 | startUpStatus = Storage.getSession('STARTUP') || false 167 | } 168 | if (startUpStatus === false) { 169 | var startUpTime = Util.format(new Date(), 'yyyy-MM-dd hh:mm:ss.SSS') 170 | Storage.setSession('STARTUP', true) 171 | Storage.setSession('STARTUPTIME', startUpTime) 172 | sessionId.setId() 173 | if (baseConfig.base.cross_subdomain === true) { 174 | Storage.setCookie('ARK_STARTUP', encodeURIComponent(Util.encode(JSON.stringify({ 'STARTUP': true, 'STARTUPTIME': startUpTime }))), 'session') 175 | } 176 | } 177 | return startUpStatus 178 | } 179 | 180 | function checkBase () { 181 | for (var key in baseConfig.base) { 182 | resetCode() 183 | // baseConfig.status.FnName = 'AnalysysAgentInit' 184 | baseConfig.status.key = key 185 | var rule = fieldRules[key] 186 | if (key === '$debug') { 187 | rule = fieldRules.xcontext[key] 188 | } 189 | if (key === '$lib_version') { 190 | rule = fieldRules.xcontext[key] 191 | } 192 | var checkValue = rule 193 | 194 | if (checkValue && !checkFields(key, baseConfig.base[key], checkValue)) { 195 | baseConfig.base[key] = '' 196 | return false 197 | } 198 | 199 | successLog() 200 | } 201 | return true 202 | } 203 | 204 | function checkPrivate (obj, ruleName, isKey) { 205 | resetCode() 206 | var rule = fieldRules[ruleName] || fieldRules.xcontextCommonRule 207 | if (Util.paramType(obj) !== 'Object' || isKey === true) { 208 | var checkKey = rule.check.key 209 | var status = check(Util.trim(obj), checkKey) 210 | baseConfig.status.key = obj 211 | if (!status) { 212 | errorLog() 213 | return false 214 | } 215 | } else { 216 | for (var key in obj) { 217 | var valueStatus = checkFields(key, obj[key], rule) 218 | if (!valueStatus) { 219 | if (baseConfig.status.errorCode === '600019') { 220 | if (Util.paramType(obj[key]) === 'String' && obj[key].length > 500) { 221 | obj[key] = Util.stringSlice(obj[key], 499) + '$' 222 | } 223 | } 224 | } 225 | } 226 | } 227 | return true 228 | } 229 | 230 | export { fillField, clearCache, isStartUp, checkBase, checkPrivate, resetCode } 231 | -------------------------------------------------------------------------------- /src/lib/fillField/sessionId.js: -------------------------------------------------------------------------------- 1 | import Storage from '../storage/index.js' 2 | import Util from '../common/index.js' 3 | import { clearUTM } from './UTM.js' 4 | function SessionId () { 5 | this.sessionId = Storage.getLocal('SEESIONID') || this.setId() 6 | this.sessionDate = Storage.getLocal('SEESIONDATE') || 0 7 | } 8 | SessionId.prototype.setId = function () { 9 | var date = +new Date() 10 | this.sessionId = Util.MD5('JS' + date.toString() + Math.random() * 10000000) 11 | this.sessionDate = date 12 | Storage.setLocal('SEESIONID', this.sessionId) 13 | Storage.setLocal('SEESIONDATE', this.sessionDate) 14 | return this.sessionId 15 | } 16 | SessionId.prototype.getId = function () { 17 | var date = new Date() 18 | var nowDate = date.getTime() 19 | var offsetGMT = date.getTimezoneOffset() 20 | var nowDay = new Date(nowDate + offsetGMT * 60 * 1000 + 8 * 60 * 60 * 1000).getDate() 21 | this.sessionDate = Storage.getLocal('SEESIONDATE') || 0 22 | 23 | var sessionDay = this.sessionDate === 0 ? 0 : new Date(this.sessionDate + offsetGMT * 60 * 1000 + 8 * 60 * 60 * 1000).getDate() 24 | if (!this.sessionId || !this.sessionDate || Number(nowDate) - Number(this.sessionDate) > 30 * 60 * 1000 || nowDay !== sessionDay) { 25 | clearUTM() 26 | this.setId() 27 | } 28 | this.sessionDate = nowDate 29 | Storage.setLocal('SEESIONDATE', nowDate) 30 | this.sessionId = Storage.getLocal('SEESIONID') || this.setId() 31 | return this.sessionId 32 | } 33 | 34 | export default new SessionId() 35 | -------------------------------------------------------------------------------- /src/lib/fillField/spider.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 1.百度:Baiduspider Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html) 3 | * 百度图片 Baiduspider-image+(+http://www.baidu.com/search/spider.htm) 4 | * 百度PC Mozilla/5.0 (compatible; Baiduspider-render/2.0; +http://www.baidu.com/search/spider.html 5 | * 百度移动端 Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1 (compatible; Baiduspider-render/2.0; +http://www.baidu.com/search/spider.html) 6 | * 7 | * 2.谷歌:Googlebot Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html) 8 | * Google图片 AdsBot-Google-Mobile (+http://www.google.com/mobile/adsbot.html) Mozilla (iPhone; U; CPU iPhone OS 3 0 like Mac OS X) AppleWebKit (KHTML, like Gecko) Mobile Safari 9 | * 3.360蜘蛛:360Spider 360搜索 Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0); 10 | * 360网站安全 360spider (http://webscan.360.cn) 11 | * 4.Bing爬虫: bingbot Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm) 12 | * 5.腾讯搜搜蜘蛛:Sosospider Sosospider+(+http://help.soso.com/webspider.htm) 13 | * 搜搜图片 Sosoimagespider+(+http://help.soso.com/soso-image-spider.htm) 14 | * 6.雅虎蜘蛛:Yahoo! 雅虎英文 Mozilla/5.0 (compatible; Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp) 15 | * 雅虎中国 Mozilla/5.0 (compatible; Yahoo! Slurp China; http://misc.yahoo.com.cn/help.html) 16 | * 4.有道蜘蛛:YoudaoBot Mozilla/5.0 (compatible; YoudaoBot/1.0; http://www.youdao.com/help/webmaster/spider/; ) 17 | * 8.搜狗蜘蛛:Sogou News Spider Sogou web spider/4.0(+http://www.sogou.com/docs/help/webmasters.htm#07) 18 | * Sogou Pic Spider/3.0(+http://www.sogou.com/docs/help/webmasters.htm#07) 19 | * 9.瑞典 Speedy Spider: Speedy Spider Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) Speedy Spider (http://www.entireweb.com/about/search_tech/speedy_spider/) 20 | * 10.俄罗斯 yandex : YandexBot Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/bots) 21 | * 11.MSN蜘蛛:msnbot/msnbot-media msnbot/1.1 (+http://search.msn.com/msnbot.htm) 22 | * 12.必应蜘蛛:bingbot/compatible Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm) 23 | * 13.听云爬虫:networkbench Mozilla/5.0 (Windows NT 10.0; Trident/7.0; rv: 11.0;NetworkBench/8.0.1.309-5774440-2481662) like Gecko 24 | * 14.Alexa蜘蛛:ia_archiver ia_archiver/8.9 (Windows NT 3.1; en-US;) 25 | * 15.宜sou蜘蛛:EasouSpider Mozilla/5.0 (compatible; EasouSpider; +http://www.easou.com/search/spider.html) 26 | * 16.华为赛门铁克蜘蛛:HuaweiSymantecSpider HuaweiSymantecSpider/1.0+DSE-support@huaweisymantec.com+(compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR ; http://www.huaweisymantec.com/cn/IRL/spider) 27 | * 17.七牛镜像蜘蛛:qiniu qiniu-imgstg-spider-1.0 28 | * 18.DNSPod监控:DNSPod DNSPod-Monitor/2.0 29 | * 19.俄罗斯 LinkpadBot:LinkpadBot Mozilla/5.0 (compatible; LinkpadBot/1.06; +http://www.linkpad.ru) 30 | * 20.英国 MJ12bot:MJ12bot Mozilla/5.0 (compatible; MJ12bot/v1.4.0; http://www.majestic12.co.uk/bot.php?+) 31 | * 21.即刻蜘蛛:JikeSpider 32 | * 22.一淘网蜘蛛:EtaoSpider Mozilla/5.0 (compatible; EtaoSpider/1.0; EtaoSpider) 33 | * 23.人工智能爬虫:crawler Mozilla/5.0 (compatible; 008/0.83; http://www.80legs.com/webcrawler.html) Gecko/2008032620 34 | * 24.Scrapy爬虫: scrapy 35 | * 25.监控宝:jiankongbao Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; JianKongBao Monitor 1.1) 36 | * 26.OneAPM爬虫:OneAPM FFAgent Mozilla/5.0 (Windows NT 6.1; WOW64; rv:39.0: OneAPM FFAgent)Gecko/20100101 Firefox/39.0 37 | * 27.PhantomJS:PhantomJS Mozilla/5.0 (Unknown; Linux x86_64)AppleWebKit/538. 1 (KHTML,like Gecko)PhantomJS/2.1.1 Safari/538.1 38 | * 28. BingPreview: Mozilla / 5.0 + (Windows + NT + 6.1; + WOW64) + AppleWebKit / 534++(KHTML, +like + Gecko) + BingPreview / 1.0 b 39 | */ 40 | var UA = navigator.userAgent.toLowerCase() 41 | 42 | function checkSpider () { 43 | if (UA.match(/(bot|crawler|spider|scrapy|dnspod|ia_archiver|jiankongbao|slurp|transcoder|networkbench|oneapm|PhantomJS|BingPreview)/i)) { 44 | return true 45 | } 46 | 47 | return false 48 | } 49 | 50 | export { 51 | checkSpider 52 | } 53 | -------------------------------------------------------------------------------- /src/lib/mergeRules/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 生产事件日志模板 3 | * commonTemp 为公用事件模板,用于自定义事件日志 4 | */ 5 | import { fieldTemplate } from '../../configure/index.js' 6 | import Util from '../common/index.js' 7 | var eventTemp = {} 8 | var commonTemp = {} 9 | var baseTemp = fieldTemplate.base 10 | var outerTemp = baseTemp.outer 11 | for (var i = 0; i < outerTemp.length; i++) { 12 | if (baseTemp[outerTemp[i]]) { 13 | commonTemp[outerTemp[i]] = Util.toObj(baseTemp[outerTemp[i]]) 14 | } else { 15 | commonTemp[outerTemp[i]] = '' 16 | } 17 | } 18 | 19 | for (var key in fieldTemplate) { 20 | if (key !== 'base') { 21 | var keyTemp = Util.toDeepObj(fieldTemplate[key]) 22 | eventTemp[key + 'base'] = keyTemp 23 | eventTemp[key] = Util.objMerge(commonTemp, keyTemp) 24 | } 25 | } 26 | 27 | eventTemp.commonTemp = commonTemp 28 | 29 | function temp (eventName) { 30 | return eventTemp[eventName] || eventTemp.commonTemp 31 | } 32 | 33 | export { temp } 34 | -------------------------------------------------------------------------------- /src/lib/printLog/index.js: -------------------------------------------------------------------------------- 1 | import baseConfig from '../baseConfig/index.js' 2 | import Util from '../common/index.js' 3 | import { lifecycle } from '../../configure/index.js' 4 | var errorMessage = { 5 | common: '{FN}:Property key invalid, nonsupport value: $lib/$lib_version/$platform/$first_visit_time/$debug/$is_login \n' + 6 | 'current KEY:{KEY}', 7 | 60001: '{FN}:Property key invalid, support type: String \n' + 8 | 'current key:{KEY}\n', 9 | 60002: '{FN}:Property value invalid of key[{KEY}], support type: Number \n' + 10 | 'current value:{VALUE}\n' + 11 | 'current type: {VALUETYPE}', 12 | 60003: '{FN}:Property value invalid of key[{KEY}], support type: Boolean \n' + 13 | 'current value:{VALUE}\n' + 14 | 'current type: {VALUETYPE}', 15 | 60004: '{FN}:Property value invalid of key[{KEY}], support type: Array \n' + 16 | 'current value:{VALUE}\n' + 17 | 'current type: {VALUETYPE}', 18 | 60005: '{FN}:The length of the property[{KEY}] value (string[{VALUE}]) needs to be 1-255 !', 19 | 60006: 'Please set appkey first.', 20 | 60007: 'Please set uploadURL first.', 21 | 60008: 'Send message failed.', 22 | 60009: '{FN}:The length of the property key (string[{KEY}]) needs to be 1-125 !', 23 | 600010: '{FN}:The length of the property key (string[{KEY}]) needs to be 1-99 !', 24 | 600011: '{FN}:[{KEY}] does not conform to naming rules!', 25 | 600012: '{FN}:Property key invalid, nonsupport value: $lib/$lib_version/$platform/$first_visit_time/$debug/$is_login \n' + 26 | 'current KEY:{KEY}', 27 | 600013: '{FN}:Property value invalid of key[{KEY}], support type: Array with String as its internal element \n' + 28 | 'current value:{VALUE}\n' + 29 | 'current type: {VALUETYPE}', 30 | 600016: '{FN}:Property value invalid of key[{KEY}], support type: Object \n' + 31 | 'current value:{VALUE}\n' + 32 | 'current type: {VALUETYPE}', 33 | 600017: '{FN}:The length of the property key (string[{KEY}]) needs to be 1-255 !', 34 | 600018: '{FN}:Property value invalid of key[{KEY}] invalid, support type: String \n' + 35 | 'current value:{VALUE}\n' + 36 | 'current type: {VALUETYPE}', 37 | 600019: '{FN}:The length of the property[{KEY}] value (string[{VALUE}]) needs to be 1-255 !', 38 | 600020: '{FN}:Property value invalid of key[{KEY}], support type: Boolean/Array/String/Number \n' + 39 | 'current value:{VALUE}\n' + 40 | 'current type: {VALUETYPE}' 41 | } 42 | var successMessage = { 43 | common: '', 44 | 20001: 'Send message success', 45 | 20002: '{FN}: set success ({VALUE})', 46 | 20003: '{FN}:({VALUE}) delete success', 47 | 20004: '{FN}:clear success', 48 | 20005: '{FN}:reset success', 49 | 20006: 'set appkey success. current appkey : {VALUE}', 50 | 20007: 'Init Analysys JS sdk success, version : {VALUE}', 51 | 20008: 'set uploadURL success. current uploadURL : {VALUE}', 52 | 20009: '{FN}:[{KEY}] : get failed', 53 | 20010: '{FN}:[{KEY}] : get success. ({VALUE})', 54 | 20011: '{FN}:({VALUE}) delete failed', 55 | 20013: 'aliasID already bound' 56 | } 57 | 58 | function successLog (msg) { 59 | if (baseConfig.base.$debug !== 1 && baseConfig.base.$debug !== 2) { 60 | return 61 | } 62 | var status = baseConfig.status 63 | var successCode = status.successCode 64 | var fn = status.FnName 65 | var key = status.key 66 | var value = status.value 67 | var msgTemp = successMessage[successCode] || successMessage.common 68 | if (Util.paramType(key) === 'String' && key.length > 30) { 69 | key = Util.stringSlice(key, 30) + '...' 70 | } 71 | if (Util.paramType(fn) === 'String' && fn.length > 30) { 72 | fn = Util.stringSlice(fn, 30) + '...' 73 | } 74 | var showMsg = msgTemp.replace('{FN}', fn) 75 | .replace('{KEY}', key) 76 | .replace('{VALUE}', value) 77 | if (msg) { 78 | showMsg = msg 79 | } 80 | if (!showMsg) return 81 | 82 | window.console && window.console.log && window.console.log(showMsg) 83 | } 84 | 85 | function errorLog () { 86 | if (baseConfig.base.$debug !== 1 && baseConfig.base.$debug !== 2) { 87 | return 88 | } 89 | 90 | var status = baseConfig.status 91 | var errorCode = status.errorCode 92 | var fn = status.FnName 93 | var key = status.key 94 | var value = status.value 95 | if (Util.paramType(value) === 'Object') { 96 | value = JSON.stringify(value) 97 | } 98 | var valueType = Util.paramType(value) 99 | if (errorCode === '600018' && !key) { 100 | errorCode = '600011' 101 | } 102 | if (errorCode === '60005' && !key) { 103 | errorCode = '600017' 104 | } 105 | if ((errorCode === '600017' || errorCode === '600019' || errorCode === '60009' || errorCode === '600010' || errorCode === '60005') && Util.paramType(value) === 'String' && value.length && value.length > 30) { 106 | value = Util.stringSlice(value, 30) + '...' 107 | } 108 | if (Util.paramType(key) === 'String' && key.length > 30) { 109 | key = Util.stringSlice(key, 30) + '...' 110 | } 111 | if (Util.paramType(fn) === 'String' && fn.length > 30) { 112 | fn = Util.stringSlice(fn, 30) + '...' 113 | } 114 | var msgTemp = errorMessage[errorCode] || errorMessage.common 115 | var showMsg = msgTemp.replace('{FN}', fn) 116 | .replace('{KEY}', key) 117 | .replace('{VALUE}', value) 118 | .replace('{VALUETYPE}', valueType) 119 | 120 | window.console && window.console.warn && window.console.warn(showMsg) 121 | if (lifecycle.errorLog && lifecycle.errorLog.init && errorCode !== '60008') { 122 | var FnName = baseConfig.status.FnName 123 | lifecycle.errorLog.init(showMsg) 124 | baseConfig.status.FnName = FnName 125 | } 126 | } 127 | export { errorLog, successLog } 128 | -------------------------------------------------------------------------------- /src/lib/storage/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 存储模块。集中处理本地缓存内容 3 | * API: 4 | * Local相关:永久存储数据相关操作 5 | * session相关:临时存储数据相关操作 6 | * 7 | */ 8 | 9 | import Util from '../common/index.js' 10 | import baseConfig from '../baseConfig/index.js' 11 | 12 | 13 | var Local = '' 14 | var Session = '' 15 | try { 16 | Local = typeof window.localStorage === 'object' ? window.localStorage : '' 17 | Session = typeof window.sessionStorage === 'object' ? window.sessionStorage : '' 18 | } catch (e) { } 19 | 20 | function Storage () { 21 | this.localName = 'FZ_STROAGE' 22 | this.sessionName = 'FZ_SESSION' 23 | this.cookieName = 'FZ_STROAGE' + '.' + Util.getDomainFromUrl(baseConfig.base.cross_subdomain) 24 | this.checkSubdomain() 25 | this.localObj = this.getLocal() 26 | this.sessionObj = this.getSession() 27 | } 28 | Storage.prototype.checkSubdomain = function () { 29 | var ans = window.AnalysysAgent || [] 30 | if (Util.paramType(ans) === 'Array') { 31 | for (var i = 0; i < ans.length; i++) { 32 | if (ans[i][0] === 'cross_subdomain' && Util.paramType(ans[i][1]) === 'Boolean') { 33 | baseConfig.base.cross_subdomain = ans[i][1] 34 | } 35 | } 36 | } 37 | if (ans && Util.objHasKay(ans.config || {}, 'cross_subdomain')) { 38 | baseConfig.base.cross_subdomain = ans.config.cross_subdomain 39 | } 40 | if (baseConfig.base.cross_subdomain === true) { 41 | var cookieObj = this.getCookie(this.cookieName) || Util.encode('{}') 42 | cookieObj = JSON.parse(Util.decode(decodeURIComponent(cookieObj))) 43 | if (Util.paramType(cookieObj) === 'Object' && !Util.isEmptyObject(cookieObj)) { 44 | var cookieId = cookieObj['ARK_ID'] 45 | var cookieSuper = {} 46 | if (Util.objHasKay(cookieObj, 'ARKSUPER') === true) { 47 | cookieSuper = cookieObj['ARKSUPER'] 48 | delete cookieObj['ARKSUPER'] 49 | } 50 | var mergeObj = Util.objMerge(this.localObj || {}, cookieObj) 51 | if (baseConfig.base.cross_subdomain_super === true && !Util.isEmptyObject(cookieSuper)) { 52 | mergeObj = Util.objMerge({ 'ARKSUPER': cookieSuper }, mergeObj) 53 | } 54 | this.setLocal(this.localName, mergeObj) 55 | this.setCookie('ARK_ID', cookieId) 56 | } 57 | } 58 | } 59 | Storage.prototype.setLocal = function (key, value) { 60 | this.localObj = this.getLocal() 61 | if (key === this.localName) { 62 | this.localObj = value 63 | } else { 64 | this.localObj[key] = value 65 | } 66 | try { 67 | if (!Local) { 68 | if (key !== 'POSTDATA') { 69 | this.setCookie(this.cookieName, encodeURIComponent(Util.encode(JSON.stringify(this.localObj)))) 70 | } 71 | } else { 72 | Local.setItem(this.localName, Util.encode(JSON.stringify(this.localObj))) 73 | Session.setItem(this.localName, Util.encode(JSON.stringify(this.localObj))) 74 | } 75 | if (key !== 'POSTDATA' && baseConfig.base.cross_subdomain === true) { 76 | var saveLocalObj = Util.toDeep(this.localObj) 77 | delete saveLocalObj['POSTDATA'] 78 | this.setCookie(this.cookieName, encodeURIComponent(Util.encode(JSON.stringify(saveLocalObj)))) 79 | } 80 | } catch (e) { } 81 | } 82 | 83 | Storage.prototype.getLocal = function (key) { 84 | try { 85 | var localData = Util.encode('{}') 86 | if (!Local) { 87 | localData = this.getCookie(this.cookieName) 88 | if (localData) { 89 | localData = decodeURIComponent(localData) 90 | } else { 91 | localData = Util.encode(JSON.stringify(this.localObj)) 92 | } 93 | } else { 94 | localData = Local.getItem(this.localName) 95 | if (!localData) { 96 | var sessionLocal = Session.getItem(this.localName) 97 | if (sessionLocal) { 98 | localData = Session.getItem(this.localName) 99 | Local.setItem(this.localName, localData) 100 | } 101 | } 102 | } 103 | this.localObj = JSON.parse(Util.decode(localData)) 104 | if (!key) { 105 | return this.localObj 106 | } 107 | return this.localObj[key] 108 | } catch (e) { 109 | if (!key) { 110 | return {} 111 | } else { 112 | return '' 113 | } 114 | } 115 | } 116 | 117 | Storage.prototype.removeLocal = function (key) { 118 | this.localObj = this.getLocal() 119 | if (Util.objHasKay(this.localObj, key)) { 120 | delete this.localObj[key] 121 | } 122 | 123 | if (Util.isEmptyObject(this.localObj)) { 124 | try { 125 | if (Local) { 126 | Local.removeItem(this.localName) 127 | Session.removeItem(this.localName) 128 | } 129 | this.removeCookie(this.cookieName) 130 | } catch (e) { } 131 | } else { 132 | if (Local) { 133 | Local.setItem(this.localName, Util.encode(JSON.stringify(this.localObj))) 134 | Session.setItem(this.localName, Util.encode(JSON.stringify(this.localObj))) 135 | } 136 | if (key !== 'POSTDATA' && key !== 'ARK_ID' && baseConfig.base.cross_subdomain === true) { 137 | var saveLocalObj = Util.toDeep(this.localObj) 138 | delete saveLocalObj['POSTDATA'] 139 | delete saveLocalObj['ARK_ID'] 140 | 141 | this.setCookie(this.cookieName, Util.encode(JSON.stringify(saveLocalObj))) 142 | } 143 | } 144 | } 145 | 146 | Storage.prototype.setSession = function (key, value) { 147 | this.sessionObj = this.getSession() 148 | this.sessionObj[key] = value 149 | try { 150 | if (!Session) { 151 | if (key !== 'POSTDATA') { 152 | this.setCookie(this.sessionName, Util.encode(JSON.stringify(this.sessionObj)), 'session') 153 | } 154 | } else { 155 | Session.setItem(this.sessionName, Util.encode(JSON.stringify(this.sessionObj))) 156 | this.removeCookie(this.sessionName) 157 | } 158 | } catch (e) { } 159 | } 160 | 161 | Storage.prototype.getSession = function (key) { 162 | try { 163 | var sessionData = Util.encode('{}') 164 | if (!Session) { 165 | sessionData = this.getCookie(this.sessionName) 166 | if (!sessionData) { 167 | sessionData = Util.encode(JSON.stringify(this.sessionObj)) 168 | } 169 | } else { 170 | sessionData = Session.getItem(this.sessionName) || Util.encode('{}') 171 | this.removeCookie(this.sessionName) 172 | } 173 | this.sessionObj = JSON.parse(Util.decode(sessionData)) 174 | 175 | if (!key) { 176 | return this.sessionObj 177 | } 178 | return this.sessionObj[key] 179 | } catch (e) { 180 | return {} 181 | } 182 | } 183 | 184 | Storage.prototype.removeSession = function (key) { 185 | this.sessionObj = this.getSession() 186 | if (Util.objHasKay(this.sessionObj, key)) { 187 | delete this.sessionObj[key] 188 | } 189 | 190 | if (Util.isEmptyObject(this.sessionObj)) { 191 | try { 192 | if (!Session) { 193 | this.removeCookie(this.sessionName) 194 | } else { 195 | Session.removeItem(this.sessionName) 196 | this.removeCookie(this.sessionName) 197 | } 198 | } catch (e) { } 199 | } else { 200 | if (Session) { 201 | Session.setItem(this.sessionName, Util.encode(JSON.stringify(this.sessionObj))) 202 | } 203 | // if (key !== 'POSTDATA' && key !== 'ARK_ID') { 204 | // this.setCookie(this.sessionName, Util.encode(JSON.stringify(this.sessionObj)), 'session') 205 | // } 206 | } 207 | } 208 | Storage.prototype.setCookie = function (name, value, type) { 209 | // if (this.getCookie(name) && this.getCookie(name) !== value) { 210 | // this.removeCookie(name, !baseConfig.base.cross_subdomain, type) 211 | // } 212 | // this.removeCookie(name, baseConfig.base.cross_subdomain, type) 213 | var urlDomain = '.' + Util.getDomainFromUrl(baseConfig.base.cross_subdomain) 214 | var path = '; path=/' 215 | var domain = !urlDomain ? '' : ('; domain=' + urlDomain) 216 | var time = '' 217 | if (type !== 'session') { 218 | var date = new Date() 219 | date.setTime(date.getTime() + 1 * 365 * 24 * 60 * 60 * 1000) 220 | time = '; expires=' + date.toGMTString() 221 | } 222 | document.cookie = name + '=' + value + time + path + domain 223 | } 224 | Storage.prototype.getCookie = function (name) { 225 | name = name || this.localName 226 | var text = document.cookie 227 | if (typeof text !== 'string') { 228 | return '' 229 | } 230 | var nameEQ = name + '=' 231 | var ca = text.split(/[;&]/) 232 | var i; var c 233 | for (i = 0; i < ca.length; i++) { 234 | c = ca[i] 235 | while (c.charAt(0) === ' ') { 236 | c = c.substring(1, c.length) 237 | } 238 | if (c.indexOf(nameEQ) === 0) { 239 | return c.substring(nameEQ.length, c.length) || '' 240 | } 241 | } 242 | } 243 | Storage.prototype.removeCookie = function (name, domainStatus, type) { 244 | domainStatus = Util.paramType(domainStatus) === 'Boolean' ? domainStatus : baseConfig.base.cross_subdomain 245 | var urlDomain = '.' + Util.getDomainFromUrl(domainStatus) 246 | var path = '; path=/' 247 | var domain = !urlDomain ? '' : ('; domain=' + urlDomain) 248 | if (type !== 'session') { 249 | var date = new Date() 250 | date.setTime(date.getTime() - 3 * 365 * 24 * 60 * 60 * 1000) 251 | var time = '; expires=' + date.toGMTString() 252 | } 253 | document.cookie = name + '=' + time + path + domain 254 | } 255 | 256 | 257 | export default new Storage() 258 | -------------------------------------------------------------------------------- /src/lib/upload/ajax.js: -------------------------------------------------------------------------------- 1 | import Storage from '../storage/index.js' 2 | import Util from '../common/index.js' 3 | import baseConfig from '../baseConfig/index.js' 4 | 5 | function getJSON (data) { 6 | if (Util.paramType(data) === 'String') { 7 | if (data.indexOf('\n') > -1) { 8 | data = data.replace(/[\r\n]/g, '') 9 | } 10 | 11 | try { 12 | return JSON.parse(data) 13 | } catch (e) { } 14 | try { 15 | return window.AnalysysModule.zipInflate(data) 16 | } catch (e) { } 17 | if (data === 'H4sIAAAAAAAAAKtWSs5PSVWyMjIwqAUAVAOW6gwAAAA=') { 18 | return { 19 | code: 200 20 | } 21 | } else if (data === 'H4sIAAAAAAAAAKtWSs5PSVWyMjUwqAUA7TtBdwwAAAA=') { 22 | return { 23 | code: 500 24 | } 25 | } else if (data === 'H4sIAAAAAAAAAKtWSs5PSVWyMjEy0FHKLU5XslJySSxJVHBJTS6qLChRcC0qyi/S01OqBQBdATGSKQAAAA==') { 26 | return { 27 | code: 420 28 | } 29 | } 30 | return { 31 | code: 200 32 | } 33 | } else if (Util.paramType(data) === 'Object') { 34 | return data 35 | } else { 36 | return { 37 | code: 200 38 | } 39 | } 40 | } 41 | 42 | function GetHttpObj () { 43 | var httpobj = null 44 | if (window.XDomainRequest) { 45 | return new window.XDomainRequest() 46 | } 47 | if (window.XMLHttpRequest) { 48 | httpobj = new window.XMLHttpRequest() 49 | } else { 50 | try { 51 | httpobj = new window.ActiveXObject('Microsoft.XMLHTTP') 52 | } catch (e) { 53 | try { 54 | httpobj = new window.ActiveXObject('Msxml2.XMLHTTP') 55 | } catch (e1) { 56 | httpobj = new window.XMLHttpRequest() 57 | } 58 | } 59 | } 60 | return httpobj 61 | } 62 | 63 | function xmlhttp (_this) { 64 | var sendStatus = false 65 | var xhr = new GetHttpObj() 66 | // xhr.setRequestHeader("reqt",+new Date()) 67 | // xhr.setRequestHeader("reqv",1) 68 | xhr.onload = function () { 69 | if (sendStatus) return 70 | sendStatus = true 71 | _this.success(getJSON(xhr.responseText), xhr) 72 | } 73 | xhr.onerror = function () { 74 | if (sendStatus) return 75 | sendStatus = true 76 | _this.error(getJSON(xhr.responseText), xhr) 77 | } 78 | xhr.onreadystatechange = (function (xhr, _this) { 79 | return function () { 80 | if (xhr.readyState === 4) { 81 | try { 82 | if (xhr.getAllResponseHeaders().indexOf('Date') > -1 || xhr.getAllResponseHeaders().indexOf('date') > -1) { 83 | var time = +new Date() 84 | var date = xhr.getResponseHeader('Date') || xhr.getResponseHeader('date') 85 | if (date && baseConfig.base.allowTimeCheck === true) { 86 | Storage.setLocal('ANSSERVERTIME', +new Date(date) - time) 87 | } else { 88 | Storage.setLocal('ANSSERVERTIME', 0) 89 | } 90 | } 91 | } catch (e) { } 92 | 93 | if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) { 94 | if (sendStatus) return 95 | sendStatus = true 96 | _this.success(getJSON(xhr.responseText), xhr) 97 | } else { 98 | if (sendStatus) return 99 | sendStatus = true 100 | _this.error() 101 | } 102 | xhr.onreadystatechange = null 103 | xhr.onload = null 104 | } 105 | } 106 | })(xhr, _this) 107 | try { 108 | xhr.open(_this.type, _this.url, true) 109 | // xhr.setRequestHeader("Content-Type","multipart/form-data") 110 | try { 111 | xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded') 112 | } catch (e) { } 113 | var timeNum = baseConfig.base.sendDataTimeout 114 | if (_this.type === 'GET') { 115 | timeNum = baseConfig.base.getDataTimeout 116 | xhr.send(null) 117 | } else { 118 | xhr.send(_this.data) 119 | } 120 | 121 | if (Util.paramType(timeNum) === 'Number') { 122 | if (Util.paramType(xhr.timeout) === 'Number') { 123 | xhr.timeout = timeNum 124 | } else { 125 | var timeCallback = (function (xhr) { 126 | return function () { 127 | xhr.abort() 128 | } 129 | })(xhr) 130 | setTimeout(timeCallback, timeNum) 131 | } 132 | 133 | } 134 | } catch (e) { 135 | } 136 | } 137 | 138 | // function lengthBaty(str) { 139 | // var bytesCount = 0 140 | // for (var i = 0; i < str.length; i++) { 141 | // var c = str.charAt(i) 142 | // if (/^[\u0000-\u00ff]$/.test(c)) //匹配双字节 143 | // { 144 | // bytesCount += 1 145 | // } else { 146 | // bytesCount += 2 147 | // } 148 | // } 149 | // return bytesCount 150 | // } 151 | 152 | function ajax () { 153 | this.url = '' 154 | this.data = '' 155 | this.type = 'GET' 156 | this.success = function () { } 157 | this.error = function () { } 158 | } 159 | ajax.prototype.get = function (option) { 160 | var param = [] 161 | for (var key in option.data) { 162 | param.push(key + '=' + encodeURIComponent(option.data[key])) 163 | } 164 | var url = option.url.indexOf('?') > -1 ? (option.url + '&' + param.join('&')) : (option.url + '?' + param.join('&')) 165 | this.url = url 166 | this.data = option.data 167 | this.type = 'GET' 168 | this.success = option.success || function () { } 169 | this.error = option.error || function () { } 170 | xmlhttp(this) 171 | } 172 | ajax.prototype.post = function (option) { 173 | this.url = option.url 174 | this.data = option.data 175 | this.type = 'POST' 176 | this.success = option.success || function () { } 177 | this.error = option.error || function () { } 178 | xmlhttp(this) 179 | } 180 | export default ajax 181 | -------------------------------------------------------------------------------- /src/lib/upload/hybrid.js: -------------------------------------------------------------------------------- 1 | import Util from '../common/index.js' 2 | import { successLog } from '../printLog/index.js' 3 | function loadIframeUrl (url, callback) { 4 | if (!document.body) { 5 | setTimeout(function () { loadIframeUrl(url, callback) }, 200) 6 | return 7 | } 8 | var iframe = document.createElement('iframe') 9 | iframe.setAttribute('src', url) 10 | iframe.setAttribute('id', 'AnalysysAgentIframe') 11 | iframe.setAttribute('style', 'display:none;') 12 | 13 | document.body.appendChild(iframe) 14 | iframe.parentNode.removeChild(iframe) 15 | } 16 | 17 | function transporter (funName, paramArray, callbackFunName, callback) { 18 | var params = { 19 | functionName: funName, 20 | functionParams: paramArray 21 | } 22 | if (Util.paramType(callbackFunName) === 'String') { 23 | params.callbackFunName = callbackFunName 24 | } else if (Util.paramType(callbackFunName) === 'Function') { 25 | callback = callbackFunName 26 | } 27 | var msg = JSON.stringify(params) 28 | successLog('Send message to app: \ndata:' + msg) 29 | if (window.AnalysysModule && window.AnalysysModule.moduleStatus === true) { 30 | window.AnalysysModule.upData(params) 31 | } else if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.AnalysysAgent) { 32 | postMessage(params) 33 | } else if (window.AnalysysAgentHybrid && window.AnalysysAgentHybrid.analysysHybridCallNative) { 34 | callNative(msg) 35 | } else { 36 | var url = 'analysysagent:' + msg 37 | loadIframeUrl(url) 38 | } 39 | if (Util.paramType(callback) === 'Function') { 40 | callback.call(callback) 41 | } 42 | } 43 | 44 | function backParamsArray () { 45 | var arg = arguments 46 | var argArray = [] 47 | var callback = null 48 | for (var i = 0; i < arg.length; i++) { 49 | if (arg[i] !== undefined) { 50 | if (Util.paramType(arg[i]) === 'Object') { 51 | for (var key in arg[i]) { 52 | if (Util.paramType(arg[i][key]) === 'Function') { 53 | arg[i][key] = arg[i][key].call(arg[i][key]) 54 | } 55 | } 56 | } 57 | if (Util.paramType(arg[i]) === 'Function') { 58 | callback = arg[i] 59 | } else { 60 | argArray.push(arg[i]) 61 | } 62 | } 63 | } 64 | return { 65 | argArray: argArray, 66 | callback: callback 67 | } 68 | } 69 | 70 | function postMessage (obj) { 71 | window.webkit.messageHandlers.AnalysysAgent.postMessage(obj) 72 | } 73 | function callNative (msg) { 74 | window.AnalysysAgentHybrid.analysysHybridCallNative(msg) 75 | } 76 | export { transporter, backParamsArray } -------------------------------------------------------------------------------- /src/lib/upload/index.js: -------------------------------------------------------------------------------- 1 | import Util from '../common/index.js' 2 | import LogAjax from './ajax.js' 3 | import Storage from '../storage/index.js' 4 | import baseConfig from '../baseConfig/index.js' 5 | import { errorLog, successLog } from '../printLog/index.js' 6 | import { lifecycle } from '../../configure/index.js' 7 | 8 | var postStatus = true 9 | var sendType = 'img' 10 | var rxDangerous = /[\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g 11 | 12 | function delRx (list) { 13 | if (Util.paramType(list) === 'Array') { 14 | for (var i = 0; i < list.length; i++) { 15 | list[i] = delRx(list[i]) 16 | } 17 | } 18 | if (Util.paramType(list) === 'Object') { 19 | for (var key in list) { 20 | var value = list[key] 21 | list[key] = delRx(value) 22 | } 23 | } 24 | if (Util.paramType(list) === 'String') { 25 | var rplist = list.replace(rxDangerous, function (a) { 26 | return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4) 27 | }) 28 | if (Util.paramType(rplist) !== 'Sting') { 29 | return list 30 | } else { 31 | return rplist 32 | } 33 | } 34 | return list 35 | } 36 | 37 | function sendPost (data, callback) { 38 | if (Util.GetUrlParam('visual') && Util.GetUrlParam('visual').indexOf('true') > -1) { 39 | return 40 | } 41 | if (sendType !== 'img') { 42 | postStatus = false 43 | } 44 | 45 | var msg = data 46 | if (Util.paramType(data) === 'Array') { 47 | data = delRx(data) 48 | msg = JSON.stringify(data) 49 | } 50 | if (window.AnalysysModal && typeof (window.AnalysysModal) === 'function') { 51 | window.AnalysysModal(data) 52 | } 53 | // 发送日志发送失败,进入缓存序列 54 | var error = function () { 55 | postStatus = true 56 | baseConfig.status.errorCode = '60008' 57 | errorLog() 58 | Util.paramType(callback) === 'Function' && callback.call(callback) 59 | } 60 | // 发送成功后,将缓存序列对应数据去除 61 | var successCheckPost = function (data) { 62 | postStatus = true 63 | 64 | var postDataList = Storage.getLocal('POSTDATA') || [] 65 | if (Util.isEmptyObject(postDataList)) { 66 | postDataList = [] 67 | Storage.removeLocal('POSTDATA') 68 | } 69 | if (postDataList.length === 0) { 70 | Storage.removeLocal('POSTDATA') 71 | return 72 | } 73 | var saveData = [] 74 | for (var i = 0; i < postDataList.length; i++) { 75 | var delData = false 76 | for (var y = 0; y < data.length; y++) { 77 | if (data[y].xwhen === postDataList[i].xwhen || !data[y].xwhen || !postDataList[i].xwhen) { 78 | delData = true 79 | } 80 | } 81 | if (delData === false && Util.paramType(postDataList[i]) === 'Object' && !Util.isEmptyObject(postDataList[i])) { 82 | saveData.push(postDataList[i]) 83 | } 84 | } 85 | if (saveData.length > 0 && sendType !== 'img') { 86 | Storage.setLocal('POSTDATA', saveData) 87 | sendPost(saveData) 88 | } else { 89 | Storage.removeLocal('POSTDATA') 90 | } 91 | } 92 | // 发送成功执行 93 | var success = (function (data) { 94 | return function (msg) { 95 | if (msg.code === 200 || msg.code === 400 || msg.code === 4200) { 96 | baseConfig.status.successCode = '20001' 97 | successLog() 98 | successCheckPost(data) 99 | if (Util.paramType(callback) === 'Function') { 100 | callback.call(callback) 101 | } 102 | } else { 103 | error() 104 | } 105 | } 106 | })(data) 107 | var url = baseConfig.base.uploadURL + 'up?appid=' + baseConfig.base.appid 108 | var postMsg = { 109 | url: url, 110 | data: msg, 111 | success: success, 112 | error: error 113 | } 114 | successLog('Send message to server: ' + baseConfig.base.uploadURL + 'up?appid=' + baseConfig.base.appid + '\ndata:' + msg) 115 | if (lifecycle.upload && lifecycle.upload.init) { 116 | postMsg = lifecycle.upload.init(postMsg) 117 | } else if (window.AnalysysModule && Util.paramType(window.AnalysysModule) === 'Object' && Util.paramType(window.AnalysysModule.uploadData) === 'Function') { 118 | window.AnalysysModule.encryptInit(baseConfig.base) 119 | postMsg = window.AnalysysModule.uploadData(postMsg) 120 | } 121 | // if (sendType === 'get') { 122 | // snedGet(postMsg) 123 | // return 124 | // } 125 | if (sendType === 'img') { 126 | snedGet(postMsg, 'img') 127 | return 128 | } 129 | if (sendType === 'post') { 130 | new LogAjax().post(postMsg) 131 | return 132 | } 133 | if (sendType === 'send') { 134 | snedGet(postMsg, 'send') 135 | return 136 | } 137 | new LogAjax().post(postMsg) 138 | } 139 | 140 | function setValidKey (option) { 141 | var data = { 142 | data: option.data, 143 | send_type: '' 144 | } 145 | var param = [] 146 | for (var key in data) { 147 | param.push(key + '=' + encodeURIComponent(data[key])) 148 | } 149 | var validurl = option.url.indexOf('?') > -1 ? (option.url + '&' + param.join('&')) : (option.url + '?' + param.join('&')) 150 | 151 | validurl = validurl.replace(baseConfig.base.uploadURL, '/') 152 | 153 | var validValue = Util.MD5(validurl, 32).split('') 154 | var validkey = validValue[2] + '' + validValue[0] + '' + validValue[4] 155 | data.send_type = validkey 156 | return data 157 | } 158 | 159 | function snedGet (option, type) { 160 | if (type === 'send' && navigator.sendBeacon) { 161 | var sendStatus = navigator.sendBeacon(option.url, option.data) 162 | if (sendStatus) { 163 | option.success({ 164 | code: 200 165 | }) 166 | } 167 | return 168 | } 169 | if (type === 'send' && !navigator.sendBeacon) { 170 | type = 'img' 171 | } 172 | option.data = Util.encode(option.data) 173 | option.data = setValidKey(option) 174 | // option.data = { 175 | // data: option.data, 176 | // send_type: validkey 177 | // } 178 | if (type === 'img') { 179 | var param = [] 180 | for (var key in option.data) { 181 | param.push(key + '=' + encodeURIComponent(option.data[key])) 182 | } 183 | var url = option.url.indexOf('?') > -1 ? (option.url + '&' + param.join('&')) : (option.url + '?' + param.join('&')) 184 | 185 | var dom = document 186 | var createImg = dom.createElement('img') 187 | var sendTimer = null 188 | createImg.width = 1 189 | createImg.height = 1 190 | createImg.onerror = createImg.onload = function () { 191 | clearTimeout(sendTimer) 192 | option.success({ code: 200 }) 193 | this.src = '' 194 | this.onload = null 195 | this.onerror = null 196 | this.onabort = null 197 | } 198 | createImg.onabort = function () { 199 | this.src = '' 200 | this.onload = null 201 | this.onerror = null 202 | this.onabort = null 203 | option.error() 204 | } 205 | if (Util.paramType(baseConfig.base.sendDataTimeout) === 'Number') { 206 | sendTimer = setTimeout(function () { 207 | createImg.onabort() 208 | }, baseConfig.base.sendDataTimeout) 209 | } 210 | createImg.src = url 211 | } 212 | } 213 | 214 | function checkLogBaseJson (obj) { 215 | if (Util.paramType(obj) === 'Object' && !Util.isEmptyObject(obj)) { 216 | var status = true 217 | for (var i = 0; i < baseConfig.baseJson.length; i++) { 218 | var key = baseConfig.baseJson[i] 219 | if (key === 'xwhat') { 220 | continue 221 | } 222 | if (!obj[key] || (Util.paramType(obj[key]) === 'Object' && Util.isEmptyObject(obj[key]))) { 223 | status = false 224 | } 225 | } 226 | return status 227 | } 228 | return false 229 | } 230 | 231 | function checkSavaData (list) { 232 | var dataList = [] 233 | if (Util.paramType(list) === 'Array' && list.length > 0) { 234 | for (var i = 0; i < list.length; i++) { 235 | var itemList = checkSavaData(list[i]) 236 | if (itemList.length > 0) { 237 | dataList.push.apply(dataList, itemList) 238 | } 239 | } 240 | } 241 | if (Util.paramType(list) === 'Object' && !Util.isEmptyObject(list) && 242 | checkLogBaseJson(list)) { 243 | dataList.push(list) 244 | } 245 | return dataList 246 | } 247 | 248 | function upLog (log, callback) { 249 | try { 250 | if (baseConfig.base.sendType) { 251 | sendType = baseConfig.base.sendType 252 | } 253 | if (baseConfig.base.uploadURL.charAt(baseConfig.base.uploadURL.length - 1) !== '/') { 254 | baseConfig.base.uploadURL += '/' 255 | } 256 | 257 | var upData = [] 258 | if (sendType === 'img') { 259 | upData = checkSavaData(log) 260 | } else { 261 | var postDataList = Storage.getLocal('POSTDATA') || [] 262 | postDataList = checkSavaData(postDataList) 263 | 264 | if (postDataList.length === 0) { 265 | Storage.removeLocal('POSTDATA') 266 | } 267 | upData = postDataList 268 | if (postDataList.length < 500) { 269 | upData.push.apply(upData, checkSavaData(log)) 270 | } else { 271 | upData = checkSavaData(log) 272 | } 273 | Storage.setLocal('POSTDATA', upData) 274 | } 275 | 276 | if (postStatus === false && sendType !== 'img') { 277 | Util.paramType(callback) === 'Function' && callback.call(callback) 278 | return 279 | } 280 | if (upData.length > 0) { 281 | if (sendType === 'img') { 282 | for (var i = 0; i < upData.length; i++) { 283 | if (i === 0) { 284 | sendPost([upData[i]], callback) 285 | } else { 286 | sendPost([upData[i]]) 287 | } 288 | } 289 | } else { 290 | sendPost(upData, callback) 291 | } 292 | } 293 | } catch (e) { 294 | } 295 | } 296 | 297 | export { upLog } 298 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 发布API 3 | */ 4 | import './lib/compatible/JSON2.js' 5 | import * as ans from './API/index.js' 6 | import Util from './lib/common/index.js' 7 | import baseConfig from './lib/baseConfig/index.js' 8 | import * as getField from './lib/fillField/getField.js' 9 | import { lifecycle } from './configure/index.js' 10 | import { startUp } from './API/template/startUp.js' 11 | import { clearCache } from './lib/fillField/index.js' 12 | import { ieCreat } from './lib/compatible/index.js' 13 | import { HybridAns } from './configure/customized/hybrid/lib/hybrid' 14 | window.AnalysysAgent = window.AnalysysAgent || {} 15 | var AnalysysAgent = window.AnalysysAgent 16 | var AnalysysModule = window.AnalysysModule || {} 17 | var config = AnalysysAgent.config || {} 18 | var param = AnalysysAgent.param || [] 19 | if (AnalysysAgent.isInit !== true) { 20 | for (var key in ans) { 21 | AnalysysAgent[key] = (function (key) { 22 | return function () { 23 | var _arguments = arguments 24 | if (key.indexOf('get') > -1) { 25 | return ans[key].apply(ans[key], _arguments) 26 | } 27 | param.push([key, arguments]) 28 | } 29 | })(key) 30 | } 31 | } 32 | function isHybrid () { 33 | if (window.navigator.userAgent.indexOf('AnalysysAgent/Hybrid') > -1 34 | ) { 35 | baseConfig.base.isHybrid = true 36 | } 37 | if (window.AnalysysAgentHybrid && window.AnalysysAgentHybrid.isHybrid() === true) { 38 | baseConfig.base.isHybrid = true 39 | } 40 | if (AnalysysModule && AnalysysModule.moduleStatus === true) { 41 | AnalysysModule.isHybrid() 42 | return 43 | } 44 | } 45 | ieCreat() //ie兼容 46 | isHybrid() //Hybrid模式检测 47 | function _createAnsSDK () { 48 | AnalysysAgent.isInit = true 49 | for (var key in ans) { 50 | AnalysysAgent[key] = ans[key] 51 | } 52 | for (var configKey in config) { 53 | if (Util.paramType(getField[configKey]) === 'Function') { 54 | getField[configKey](config[configKey]) 55 | } else { 56 | baseConfig.base[configKey] = config[configKey] 57 | } 58 | } 59 | if (baseConfig.base.isHybrid === true) { 60 | for (var hybridKey in HybridAns) { 61 | AnalysysAgent[hybridKey] = AnalysysModule.moduleStatus === true ? AnalysysModule.onEvent(hybridKey, HybridAns) : HybridAns[hybridKey] 62 | } 63 | } 64 | AnalysysAgent.config = baseConfig.base 65 | // AnalysysAgent.config.setDebugModel = getField.debugMode 66 | // baseConfig.base = AnalysysAgent.config 67 | 68 | clearCache() 69 | for (var y = 0; y < param.length; y++) { 70 | var yItem = param[y] 71 | if (Util.objHasKay(ans, yItem[0]) && (yItem[0] === 'identify' || yItem[0] === 'alias' || yItem[0].indexOf('Super') > -1)) { 72 | ans[yItem[0]].apply(ans[yItem[0]], yItem[1]) 73 | } 74 | } 75 | if (lifecycle.AnalysysAgent && lifecycle.AnalysysAgent.init) { 76 | lifecycle.AnalysysAgent.init(baseConfig.base) 77 | } 78 | // 如存在修改则重置登录及启动状态 79 | startUp() 80 | for (var z = 0; z < param.length; z++) { 81 | var zItem = param[z] 82 | if (Util.objHasKay(ans, zItem[0]) && zItem[0] !== 'identify' && zItem[0] !== 'alias' && zItem[0].indexOf('Super') < 0) { 83 | ans[zItem[0]].apply(ans[zItem[0]], zItem[1]) 84 | } 85 | } 86 | } 87 | 88 | AnalysysAgent.init = function (conf) { 89 | if (Util.paramType(config) === 'Object' && (!AnalysysAgent.isInit || baseConfig.base.isHybrid === true) && (!AnalysysModule.moduleStatus || AnalysysModule.moduleStatus === true && (conf.isHybrid === true || conf.isARKH5 === true))) { 90 | if (conf.isARKH5 !== true) { 91 | config = conf 92 | } 93 | _createAnsSDK() 94 | } 95 | } 96 | if (!AnalysysAgent.isInit) { 97 | if (Util.paramType(AnalysysAgent) === 'Array') { 98 | 99 | for (var i = 0; i < AnalysysAgent.length; i++) { 100 | if (Util.paramType(ans[AnalysysAgent[i][0]]) === 'Function') { 101 | var fnName = AnalysysAgent[i][0] 102 | AnalysysAgent[i].splice(0, 1) 103 | param.push([fnName, AnalysysAgent[i]]) 104 | } else { 105 | config[AnalysysAgent[i][0]] = AnalysysAgent[i][1] 106 | } 107 | } 108 | } 109 | if (Util.isEmptyObject(config) === false && !AnalysysModule.moduleStatus) { 110 | _createAnsSDK() 111 | } 112 | } 113 | 114 | export default AnalysysAgent -------------------------------------------------------------------------------- /vue-demo/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | # local env files 6 | .env.local 7 | .env.*.local 8 | 9 | # Log files 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | 14 | # Editor directories and files 15 | .idea 16 | .vscode 17 | *.suo 18 | *.ntvs* 19 | *.njsproj 20 | *.sln 21 | *.sw? 22 | 23 | *.lock -------------------------------------------------------------------------------- /vue-demo/README.md: -------------------------------------------------------------------------------- 1 | # vue-demo 2 | 3 | ## Project setup 4 | ``` 5 | npm install 6 | ``` 7 | 8 | ### Compiles and hot-reloads for development 9 | ``` 10 | npm run serve 11 | ``` 12 | 13 | ### Compiles and minifies for production 14 | ``` 15 | npm run build 16 | ``` 17 | 18 | ### Lints and fixes files 19 | ``` 20 | npm run lint 21 | ``` 22 | 23 | ### Customize configuration 24 | See [Configuration Reference](https://cli.vuejs.org/config/). 25 | -------------------------------------------------------------------------------- /vue-demo/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /vue-demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-demo", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build", 8 | "lint": "vue-cli-service lint" 9 | }, 10 | "dependencies": { 11 | "core-js": "^3.3.2", 12 | "element-ui": "^2.13.0", 13 | "vue": "^2.6.10", 14 | "vue-router": "^3.1.3" 15 | }, 16 | "devDependencies": { 17 | "@vue/cli-plugin-babel": "^4.0.0", 18 | "@vue/cli-plugin-eslint": "^4.0.0", 19 | "@vue/cli-service": "^4.0.0", 20 | "babel-eslint": "^10.0.3", 21 | "eslint": "^5.16.0", 22 | "eslint-plugin-vue": "^5.0.0", 23 | "vue-template-compiler": "^2.6.10" 24 | }, 25 | "eslintConfig": { 26 | "root": true, 27 | "env": { 28 | "node": true 29 | }, 30 | "extends": [ 31 | "plugin:vue/essential" 32 | ], 33 | "rules": { 34 | "indent": [ 35 | 1, 36 | 4 37 | ] 38 | }, 39 | "parserOptions": { 40 | "parser": "babel-eslint" 41 | } 42 | }, 43 | "postcss": { 44 | "plugins": { 45 | "autoprefixer": {} 46 | } 47 | }, 48 | "browserslist": [ 49 | "> 1%", 50 | "last 2 versions" 51 | ] 52 | } 53 | -------------------------------------------------------------------------------- /vue-demo/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/analysys/ans-javascript-sdk/83a214c8c92f79557107d105c67223b7c32632ee/vue-demo/public/favicon.ico -------------------------------------------------------------------------------- /vue-demo/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | vue-demo 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /vue-demo/src/App.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 27 | 28 | 64 | -------------------------------------------------------------------------------- /vue-demo/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/analysys/ans-javascript-sdk/83a214c8c92f79557107d105c67223b7c32632ee/vue-demo/src/assets/logo.png -------------------------------------------------------------------------------- /vue-demo/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | import VueRouter from 'vue-router' 4 | import routes from './routes/index' 5 | import ElementUI from 'element-ui'; 6 | import 'element-ui/lib/theme-chalk/index.css'; 7 | import AnalysysAgent from "./sdk/AnalysysAgent_JS_SDK.es6.min.js"; 8 | 9 | import "./sdk/AnalysysAgent_GBK.es6.min.js"; 10 | import "./sdk/AnalysysAgent_Encrypt.es6.min.js"; 11 | import "./sdk/AnalysysAgent_PageViewStayTime.es6.min.js"; 12 | 13 | import "./sdk/AnalysysAgent_ExposurePoint.es6.min.js"; 14 | 15 | AnalysysAgent.init({ 16 | appkey: "commondebug", //APPKEY 17 | debugMode: 2, 18 | uploadURL: "https://sdk.analysys.cn:4089/", 19 | visitorConfigURL: "https://sdk.analysys.cn:4089/", 20 | SDKFileDirectory: "./js/sdk/", 21 | encryptType: 2, 22 | exposure: { 23 | valid_time: 300,//停留有效时间 24 | property: { 25 | cc: function () { 26 | return +new Date() 27 | } 28 | },//自定义参数 29 | exposure_click: true, // 是否自动采集曝光元素点击事件 30 | multiple: 5000,//true或毫秒值, 是否重复采集曝光点数据或多少毫秒后可再次采集 31 | element_list: function () { 32 | var list = [].slice.call(document.getElementsByTagName('a'), 0) 33 | var spanList = [].slice.call(document.getElementsByTagName('span'), 0) 34 | list.push.apply(list, spanList) 35 | return list 36 | } 37 | } 38 | /**如无自定义配置,则与uploadURL相同**/ 39 | }); 40 | Vue.config.productionTip = false 41 | Vue.prototype.AnalysysAgent = AnalysysAgent 42 | Vue.use(VueRouter) 43 | Vue.use(ElementUI) 44 | const router = new VueRouter({ 45 | routes // (缩写) 相当于 routes: routes 46 | }) 47 | new Vue({ 48 | router, 49 | render: h => h(App) 50 | }).$mount('#app') -------------------------------------------------------------------------------- /vue-demo/src/routes/index.js: -------------------------------------------------------------------------------- 1 | import Index from '../components/index.vue' 2 | import Next from '../components/next.vue' 3 | const routes = [{ 4 | path: '/', 5 | component: Index 6 | }, 7 | { 8 | path: '/next', 9 | component: Next 10 | } 11 | ] 12 | export default routes -------------------------------------------------------------------------------- /vue-demo/vue.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | publicPath: './' 3 | } --------------------------------------------------------------------------------