const actionsdk = require('../action_sdk/actionsdk-1.0.0.js'); const REQ_BASE = require('../action_sdk/ReqBase.js'); import PAGES_JSON from "@/pages.json" export default { data() { return { ACTION_SDK:{}, ACTION_ENTER_TIME : '',//页面进入时间 ACTION_OUT_TIME : '',//页面离开时间 ACTION_STAY_TIME : '',//页面停留时间 BIND_ID:'',//行为对象id BIND_TYPE:'',//行为对象类型 USER_ID:'',//当前用户id TYPE_NAME:'',//自定义类型名称 SHARE_USER_ID : '',//分享用户userId CURRENT_CODE:'',//当前素材的行为code(作为分享出去的PARENT_CODE使用) PARENT_CODE : '',//当前素材的上级行为code(二次分享可用,保证行为轨迹链条完整) CURRENT_ROUTE:{},//当前页面实例 USER_TIMER:null, USER_TIMER_NUM:0, OPTIONS:{},//页面入参 PAGE_NAME:'',//页面名称 }; }, async onLoad(options) { this.ACTION_SDK = actionsdk.initAction(); // #ifdef H5 // h5分享跳转启动页加载配置 if(options.isShare){ let url = window.location.href.split('?')[0] let params = this.getQueryParams() delete params.isShare let paramsStr = [] for(let key in params){ paramsStr.push(key + '='+params[key]) } let url_copy = url if(paramsStr.length>0){ url_copy = url_copy + '?' + paramsStr.join('&') } uni.setStorageSync('window_location', url_copy); uni.redirectTo({ url:'/pages/launch/launch' }) return false } // #endif this.OPTIONS = options if(options.scene){ await this.LOAD_CODE_PARAMS(options.scene) }else if(options.x_code_id){ await this.LOAD_CODE_PARAMS(options.x_code_id) }else{ this.BIND_ID = options.id this.SHARE_USER_ID = options.userId this.PARENT_CODE = options.parentCode } this.CURRENT_CODE = actionsdk.creatBehaviorCode() let pageList = getCurrentPages() this.CURRENT_ROUTE = pageList[pageList.length - 1]; //页面实例 this.PAGE_NAME = this.GET_PAGE_NAME() console.log('this.CURRENT_ROUTE',this.CURRENT_ROUTE) this.PAGE_BROWSE_FN() this.USER_ID = this.ACTION_SDK.getStorage('userInfo')?this.ACTION_SDK.getStorage('userInfo').id:'' // 等待用户登陆成功后开始处理 if(!this.USER_ID){ this.USER_TIMER = setInterval(()=>{ console.log('USER_TIMER') //最多10s,10s内无法获取到userId则清除定时器防止卡死 this.USER_TIMER_NUM = this.USER_TIMER_NUM + 1 if(this.USER_TIMER_NUM>20){ clearInterval(this.USER_TIMER) this.USER_TIMER = null } if(!this.USER_ID){ this.USER_ID = this.ACTION_SDK.getStorage('userInfo')?this.ACTION_SDK.getStorage('userInfo').id:'' }else{ clearInterval(this.USER_TIMER) this.USER_TIMER = null if(pageList.length==1){ // 用户退出时间 this.ACTION_ENTER_TIME = new Date(); this.ACTION_OUT_TIME = new Date(); //停留时间(毫秒) this.ACTION_STAY_TIME = this.ACTION_OUT_TIME.getTime() - this.ACTION_ENTER_TIME.getTime(); console.log('页面隐藏' + this.CURRENT_ROUTE.route + ':' + this.ACTION_STAY_TIME); console.log('---用户浏览---',Math.ceil(this.ACTION_STAY_TIME/1000)) this.SEND_BROWSE_FN() } } },500) }else{ if(pageList.length==1){ // 用户退出时间 this.ACTION_ENTER_TIME = new Date(); this.ACTION_OUT_TIME = new Date(); //停留时间(毫秒) this.ACTION_STAY_TIME = this.ACTION_OUT_TIME.getTime() - this.ACTION_ENTER_TIME.getTime(); console.log('页面隐藏' + this.CURRENT_ROUTE.route + ':' + this.ACTION_STAY_TIME); console.log('---用户浏览---',Math.ceil(this.ACTION_STAY_TIME/1000)) this.SEND_BROWSE_FN() } } }, onShow() { this.USER_ID = this.ACTION_SDK.getStorage('userInfo')?this.ACTION_SDK.getStorage('userInfo').id:'' // 用户进入时间 this.ACTION_ENTER_TIME = new Date(); console.log('页面展示',this.ACTION_ENTER_TIME); switch (this.channel){ case 'home':{ this.PAGE_NAME = '首页' //产品 } break; case 'service':{ this.PAGE_NAME = '服务项目' //活动 } break; case 'user':{ this.PAGE_NAME = '我的' //文章 } break; case 'cart':{ this.PAGE_NAME = '购物车' //文章 } break; default:{ } break; } }, onHide() { // 解决onHide重复调用问题 if(!this.CURRENT_ROUTE.route) return false // 用户退出时间 this.ACTION_OUT_TIME = new Date(); //停留时间(毫秒) this.ACTION_STAY_TIME = this.ACTION_OUT_TIME.getTime() - this.ACTION_ENTER_TIME.getTime(); console.log('页面隐藏' + this.CURRENT_ROUTE.route + ':' + this.ACTION_STAY_TIME); console.log('---用户浏览---',Math.ceil(this.ACTION_STAY_TIME/1000)) this.SEND_BROWSE_FN() }, onUnload() { // 解决onHide重复调用问题 if(!this.CURRENT_ROUTE.route) return false // 用户退出时间 this.ACTION_OUT_TIME = new Date(); //停留时间(毫秒) this.ACTION_STAY_TIME = this.ACTION_OUT_TIME.getTime() - this.ACTION_ENTER_TIME.getTime(); console.log('页面卸载' + this.CURRENT_ROUTE.route + ':' + this.ACTION_STAY_TIME); console.log('---用户浏览总时长---',Math.ceil(this.ACTION_STAY_TIME/1000)) this.SEND_BROWSE_FN() }, methods: { // 获取参数 getQueryParams() { const url = window.location.search; const params = url .substring(1) .split('&') .reduce((result, param) => { const [key, value] = param.split('='); result[decodeURIComponent(key)] = decodeURIComponent(value); return result; }, {}); return params; }, // 页面浏览行为个性化页面处理 PAGE_BROWSE_FN(){ switch (this.CURRENT_ROUTE.route){ case 'product/detail/detail':{ this.BIND_TYPE = 1 //产品 } break; case 'match/activityDetail/activityDetail':{ this.BIND_TYPE = 2 //活动 } break; case 'topic/content/content':{ this.BIND_TYPE = 3 //文章 } break; case 'topic/case/case':{ this.BIND_TYPE = 3 //文章 this.TYPE_NAME = '案例' } break; case 'card/index/index':{ this.BIND_TYPE = 7 //名片 this.BIND_ID = this.OPTIONS.cardId } break; case 'leaflet/detail/index':{ this.BIND_TYPE = 8 //素材 } break; case 'topic/solDet/solDet':{ this.BIND_TYPE = 9 //专题 } break; case 'promote/info/info':{ this.BIND_TYPE = 12 //合伙人招募页面 this.BIND_ID = 0 // } break; case 'martial/content/index':{ this.BIND_TYPE = 8 //文章 this.TYPE_NAME = '软文' } break; case 'martial/leaflet/index':{ this.BIND_TYPE = 8 //宣传彩页 this.TYPE_NAME = '宣传彩页' } break; case 'martial/file/index':{ this.BIND_TYPE = 8 //宣传彩页 this.TYPE_NAME = '文件' } break; case 'martial/video/index':{ this.BIND_TYPE = 8 //宣传彩页 this.TYPE_NAME = '文件' } break; default:{ this.BIND_TYPE = 14 this.BIND_ID = '' } break; } }, /** * 修改参数(需要修改参数时传入对应需要修改的参数即可) * @param BIND_TYPE 行为对象类型 * @param BIND_ID 行为对象id * @param USER_ID 当前用户id * @param SHARE_USER_ID 分享用户id * @param PARENT_CODE 上级行为code(用与二次转发) * @param TYPE_NAME 自定义类型名称 * @param PAGE_NAME 自定义页面标题 */ PAGE_DATA_INIT_FN({ BIND_TYPE = '', BIND_ID = '', USER_ID = '', SHARE_USER_ID = '', PARENT_CODE = '', TYPE_NAME = '', PAGE_NAME = '' }={}){ if(BIND_TYPE) this.BIND_TYPE = BIND_TYPE if(BIND_ID) this.BIND_ID = BIND_ID if(USER_ID) this.USER_ID = USER_ID if(SHARE_USER_ID) this.SHARE_USER_ID = SHARE_USER_ID if(PARENT_CODE) this.PARENT_CODE = PARENT_CODE if(TYPE_NAME) this.TYPE_NAME = TYPE_NAME if(PAGE_NAME) this.PAGE_NAME = PAGE_NAME }, /** * 记录用户浏览行为,浏览行为上报(参数非必传,只有需要修改参数时传入对应需要修改的参数即可) * @param BIND_TYPE 行为对象类型 * @param BIND_ID 行为对象id * @param USER_ID 当前用户id * @param SHARE_USER_ID 分享用户id * @param PARENT_CODE 上级行为code(用与二次转发) */ SEND_BROWSE_FN ({ BIND_TYPE = this.BIND_TYPE, BIND_ID = this.BIND_ID, USER_ID = this.USER_ID, SHARE_USER_ID = this.SHARE_USER_ID, PARENT_CODE = this.PARENT_CODE }={}){ // console.log(BIND_TYPE,BIND_ID,USER_ID,SHARE_USER_ID,PARENT_CODE) let postObj = { type:BIND_TYPE, bindId:BIND_ID, uid:USER_ID, shareUid:SHARE_USER_ID, parentCode:PARENT_CODE, code:this.CURRENT_CODE, pageUri:this.CURRENT_ROUTE.route, readTime:this.ACTION_STAY_TIME?Math.ceil(this.ACTION_STAY_TIME/1000):null } // 自定义类型名称 if(this.TYPE_NAME) postObj.typeName = this.TYPE_NAME // 如果是页面浏览 if(postObj.type==14){ postObj.content = `浏览了${this.PAGE_NAME}页面`; postObj.typeName = this.PAGE_NAME } actionsdk.saveBrowse(postObj); }, /** * 记录用户分享行为,分享行为上报 * @param BIND_TYPE 行为对象类型 * @param BIND_ID 行为对象id * @param USER_ID 当前用户id * @param SHARE_USER_ID 分享用户id * @param PARENT_CODE 上级行为code(用与二次转发) */ SEND_SHARE_FN ({ BIND_TYPE = this.BIND_TYPE, BIND_ID = this.BIND_ID, USER_ID = this.USER_ID, SHARE_USER_ID = this.SHARE_USER_ID, PARENT_CODE = this.PARENT_CODE }={}){ let postObj = { behaviorType:5, type:BIND_TYPE, bindId:BIND_ID, uid:USER_ID, shareUid:SHARE_USER_ID, parentCode:PARENT_CODE, code:this.CURRENT_CODE } // 自定义类型名称 if(this.TYPE_NAME) postObj.typeName = this.TYPE_NAME // 分享行为固定behaviorType 5 // 延后分享是因为分享不是在成功回调调用的,导致浏览上报事件在分享上报事件前执行了,延后1s可保证时序性 setTimeout(()=>{ actionsdk.saveBehavior(postObj); },1000) }, /** * 分享行为预处理(处理分享出去的PARENT_CODE,参数按分享参数传入,分享时取该方法返回的参数) * @param path 分享路径 * @param sendShare 是否立即触发分享行为上报,默认不开启 * @param codeScene 生成小程序码时的自定义参数,object */ SHARE_BEHAVIOR_FN({ path = '', sendShare = false, codeScene = {} }={}){ if(!this.CURRENT_CODE){ this.CURRENT_CODE = actionsdk.creatBehaviorCode() } if(sendShare){ this.SEND_SHARE_FN() } // 小程序码参数拼接parentCode codeScene.parentCode = this.CURRENT_CODE // 分享路径拼接parentCode if(path.indexOf('?')>-1){ path = path + '&parentCode='+this.CURRENT_CODE }else{ path = path + '?parentCode='+this.CURRENT_CODE } return { path:path, codeScene:codeScene } }, /** * 记录用户收藏行为,收藏行为上报 * @param BIND_TYPE 行为对象类型 * @param BIND_ID 行为对象id * @param USER_ID 当前用户id * @param SHARE_USER_ID 分享用户id * @param PARENT_CODE 上级行为code(用与二次转发) */ SEND_COLLECT_FN ({ BIND_TYPE = this.BIND_TYPE, BIND_ID = this.BIND_ID, USER_ID = this.USER_ID, SHARE_USER_ID = this.SHARE_USER_ID, PARENT_CODE = this.PARENT_CODE, }={}){ let postObj = { behaviorType:2, type:BIND_TYPE, bindId:BIND_ID, uid:USER_ID, shareUid:SHARE_USER_ID, parentCode:PARENT_CODE, code:this.CURRENT_CODE } // 收藏行为固定behaviorType 2 actionsdk.saveBehavior(postObj); }, /** * 其他行为上报 * @param BEHAVIOR_TYPE 行为类型 * @param BIND_TYPE 行为对象类型 * @param BIND_ID 行为对象id * @param USER_ID 当前用户id * @param CONTENT 日志文案(如:'浏览了xxx文章') * @param READ_TIME 行为时长(如:'浏览时长',单位s) * @param TYPE_NAME 自定义类型名称 * @param SHARE_USER_ID 分享用户id * @param PARENT_CODE 上级行为code(用与二次转发) */ SEND_SELF_FN ({ BEHAVIOR_TYPE = '', BIND_TYPE = this.BIND_TYPE, BIND_ID = this.BIND_ID, USER_ID = this.USER_ID, CONTENT = '', READ_TIME = '', TYPE_NAME = '', SHARE_USER_ID = this.SHARE_USER_ID, PARENT_CODE = this.PARENT_CODE, }={}){ if(!BEHAVIOR_TYPE) { throw new Error("未传入行为类型") return false } let postObj = { behaviorType:BEHAVIOR_TYPE, type:BIND_TYPE, bindId:BIND_ID, uid:USER_ID, shareUid:SHARE_USER_ID, parentCode:PARENT_CODE, code:this.CURRENT_CODE, content:CONTENT, pageUri:this.CURRENT_ROUTE.route, readTime:READ_TIME, TYPE_NAME:TYPE_NAME } actionsdk.saveBehavior(postObj); }, /** * 记录用户点赞行为,点赞行为上报 * @param BIND_TYPE 行为对象类型 * @param BIND_ID 行为对象id * @param USER_ID 当前用户id * @param SHARE_USER_ID 分享用户id * @param PARENT_CODE 上级行为code(用与二次转发) * @param IS_THUMBS 是否是点赞,false为取消点赞 */ SEND_COLLECT_FN ({ BIND_TYPE = this.BIND_TYPE, BIND_ID = this.BIND_ID, USER_ID = this.USER_ID, SHARE_USER_ID = this.SHARE_USER_ID, PARENT_CODE = this.PARENT_CODE, IS_THUMBS = true }={}){ let postObj = { behaviorType:3, type:BIND_TYPE, bindId:BIND_ID, uid:USER_ID, shareUid:SHARE_USER_ID, parentCode:PARENT_CODE, code:this.CURRENT_CODE, IS_THUMBS:IS_THUMBS } // 点赞行为固定behaviorType 3 if(IS_THUMBS){ actionsdk.saveBehavior(postObj); }else{ actionsdk.removeBehavior(postObj); } }, // 获取行为接口请求参数(为实现部分项目未埋点时可通过后台接口埋点的冗余方案,纯后台埋点无行为完整链条,只有传入前端参数才能保证行为链条完整) GET_API_DATA(){ let data = { shareUid: this.SHARE_USER_ID, code:this.CURRENT_CODE, shareCode: this.PARENT_CODE, }; var deviceInfo = this.ACTION_SDK.getStorage('deviceInfo'); // #ifdef APP-PLUS var sysMac = this.ACTION_SDK.getStorage('sysMac'); // #endif var device_info = {}; if (deviceInfo) { data.model = deviceInfo.deviceModel; data.manufacturer = deviceInfo.deviceBrand; data.os = deviceInfo.osName; data.osVersion = deviceInfo.osVersion; data.browser = deviceInfo.browserName; data.browserVersion = deviceInfo.browserVersion; data.deviceId = deviceInfo.deviceId; // #ifdef APP-PLUS if (sysMac) { data.sysMac = sysMac; } // #endif } return data }, // 扫码进入时解码方法 LOAD_CODE_PARAMS(scene) { return new Promise((resolve, reject) => { let form = { scene: scene }; if (!scene) { resolve(); return false; } this.ACTION_SDK.getRequestAPI('/api/code/params', form, data => { let res = JSON.parse(data.scene); if(data.userId){ this.SHARE_USER_ID = data.userId } if(res.id){ this.BIND_ID = res.id } if(res.userId){ this.SHARE_USER_ID = res.userId } if(res.parentCode){ this.PARENT_CODE = res.parentCode } resolve(); }); }); }, // 获取页面标题 GET_PAGE_NAME(){ let name = this.CURRENT_ROUTE.route console.log('GET_PAGE_NAME',PAGES_JSON) for(let key in PAGES_JSON){ let getCurrentStyle = PAGES_JSON.pages.find((item) => item.path == this.CURRENT_ROUTE.route); if(getCurrentStyle){ return getCurrentStyle.style&&getCurrentStyle.style.navigationBarTitleText?getCurrentStyle.style.navigationBarTitleText:getCurrentStyle.path }else{ for(let i=0;i subPackages.root+'/'+item.path == this.CURRENT_ROUTE.route); if(getCurrentStyle){ return getCurrentStyle.style&&getCurrentStyle.style.navigationBarTitleText?getCurrentStyle.style.navigationBarTitleText:getCurrentStyle.path } } } } return name } } };