actionTemplete.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549
  1. const actionsdk = require('../action_sdk/actionsdk-1.0.0.js');
  2. const REQ_BASE = require('../action_sdk/ReqBase.js');
  3. import PAGES_JSON from "@/pages.json"
  4. export default {
  5. data() {
  6. return {
  7. ACTION_SDK:{},
  8. ACTION_ENTER_TIME : '',//页面进入时间
  9. ACTION_OUT_TIME : '',//页面离开时间
  10. ACTION_STAY_TIME : '',//页面停留时间
  11. BIND_ID:'',//行为对象id
  12. BIND_TYPE:'',//行为对象类型
  13. USER_ID:'',//当前用户id
  14. TYPE_NAME:'',//自定义类型名称
  15. SHARE_USER_ID : '',//分享用户userId
  16. CURRENT_CODE:'',//当前素材的行为code(作为分享出去的PARENT_CODE使用)
  17. PARENT_CODE : '',//当前素材的上级行为code(二次分享可用,保证行为轨迹链条完整)
  18. CURRENT_ROUTE:{},//当前页面实例
  19. USER_TIMER:null,
  20. USER_TIMER_NUM:0,
  21. OPTIONS:{},//页面入参
  22. PAGE_NAME:'',//页面名称
  23. };
  24. },
  25. async onLoad(options) {
  26. this.ACTION_SDK = actionsdk.initAction();
  27. // #ifdef H5
  28. // h5分享跳转启动页加载配置
  29. if(options.isShare){
  30. let url = window.location.href.split('?')[0]
  31. let params = this.getQueryParams()
  32. delete params.isShare
  33. let paramsStr = []
  34. for(let key in params){
  35. paramsStr.push(key + '='+params[key])
  36. }
  37. let url_copy = url
  38. if(paramsStr.length>0){
  39. url_copy = url_copy + '?' + paramsStr.join('&')
  40. }
  41. uni.setStorageSync('window_location', url_copy);
  42. uni.redirectTo({
  43. url:'/pages/launch/launch'
  44. })
  45. return false
  46. }
  47. // #endif
  48. this.OPTIONS = options
  49. if(options.scene){
  50. await this.LOAD_CODE_PARAMS(options.scene)
  51. }else if(options.x_code_id){
  52. await this.LOAD_CODE_PARAMS(options.x_code_id)
  53. }else{
  54. this.BIND_ID = options.id
  55. this.SHARE_USER_ID = options.userId
  56. this.PARENT_CODE = options.parentCode
  57. }
  58. this.CURRENT_CODE = actionsdk.creatBehaviorCode()
  59. let pageList = getCurrentPages()
  60. this.CURRENT_ROUTE = pageList[pageList.length - 1]; //页面实例
  61. this.PAGE_NAME = this.GET_PAGE_NAME()
  62. console.log('this.CURRENT_ROUTE',this.CURRENT_ROUTE)
  63. this.PAGE_BROWSE_FN()
  64. this.USER_ID = this.ACTION_SDK.getStorage('userInfo')?this.ACTION_SDK.getStorage('userInfo').id:''
  65. // 等待用户登陆成功后开始处理
  66. if(!this.USER_ID){
  67. this.USER_TIMER = setInterval(()=>{
  68. console.log('USER_TIMER')
  69. //最多10s,10s内无法获取到userId则清除定时器防止卡死
  70. this.USER_TIMER_NUM = this.USER_TIMER_NUM + 1
  71. if(this.USER_TIMER_NUM>20){
  72. clearInterval(this.USER_TIMER)
  73. this.USER_TIMER = null
  74. }
  75. if(!this.USER_ID){
  76. this.USER_ID = this.ACTION_SDK.getStorage('userInfo')?this.ACTION_SDK.getStorage('userInfo').id:''
  77. }else{
  78. clearInterval(this.USER_TIMER)
  79. this.USER_TIMER = null
  80. if(pageList.length==1){
  81. // 用户退出时间
  82. this.ACTION_ENTER_TIME = new Date();
  83. this.ACTION_OUT_TIME = new Date();
  84. //停留时间(毫秒)
  85. this.ACTION_STAY_TIME = this.ACTION_OUT_TIME.getTime() - this.ACTION_ENTER_TIME.getTime();
  86. console.log('页面隐藏' + this.CURRENT_ROUTE.route + ':' + this.ACTION_STAY_TIME);
  87. console.log('---用户浏览---',Math.ceil(this.ACTION_STAY_TIME/1000))
  88. this.SEND_BROWSE_FN()
  89. }
  90. }
  91. },500)
  92. }else{
  93. if(pageList.length==1){
  94. // 用户退出时间
  95. this.ACTION_ENTER_TIME = new Date();
  96. this.ACTION_OUT_TIME = new Date();
  97. //停留时间(毫秒)
  98. this.ACTION_STAY_TIME = this.ACTION_OUT_TIME.getTime() - this.ACTION_ENTER_TIME.getTime();
  99. console.log('页面隐藏' + this.CURRENT_ROUTE.route + ':' + this.ACTION_STAY_TIME);
  100. console.log('---用户浏览---',Math.ceil(this.ACTION_STAY_TIME/1000))
  101. this.SEND_BROWSE_FN()
  102. }
  103. }
  104. },
  105. onShow() {
  106. this.USER_ID = this.ACTION_SDK.getStorage('userInfo')?this.ACTION_SDK.getStorage('userInfo').id:''
  107. // 用户进入时间
  108. this.ACTION_ENTER_TIME = new Date();
  109. console.log('页面展示',this.ACTION_ENTER_TIME);
  110. switch (this.channel){
  111. case 'home':{
  112. this.PAGE_NAME = '首页' //产品
  113. } break;
  114. case 'service':{
  115. this.PAGE_NAME = '服务项目' //活动
  116. } break;
  117. case 'user':{
  118. this.PAGE_NAME = '我的' //文章
  119. } break;
  120. case 'cart':{
  121. this.PAGE_NAME = '购物车' //文章
  122. } break;
  123. default:{
  124. } break;
  125. }
  126. },
  127. onHide() {
  128. // 解决onHide重复调用问题
  129. if(!this.CURRENT_ROUTE.route) return false
  130. // 用户退出时间
  131. this.ACTION_OUT_TIME = new Date();
  132. //停留时间(毫秒)
  133. this.ACTION_STAY_TIME = this.ACTION_OUT_TIME.getTime() - this.ACTION_ENTER_TIME.getTime();
  134. console.log('页面隐藏' + this.CURRENT_ROUTE.route + ':' + this.ACTION_STAY_TIME);
  135. console.log('---用户浏览---',Math.ceil(this.ACTION_STAY_TIME/1000))
  136. this.SEND_BROWSE_FN()
  137. },
  138. onUnload() {
  139. // 解决onHide重复调用问题
  140. if(!this.CURRENT_ROUTE.route) return false
  141. // 用户退出时间
  142. this.ACTION_OUT_TIME = new Date();
  143. //停留时间(毫秒)
  144. this.ACTION_STAY_TIME = this.ACTION_OUT_TIME.getTime() - this.ACTION_ENTER_TIME.getTime();
  145. console.log('页面卸载' + this.CURRENT_ROUTE.route + ':' + this.ACTION_STAY_TIME);
  146. console.log('---用户浏览总时长---',Math.ceil(this.ACTION_STAY_TIME/1000))
  147. this.SEND_BROWSE_FN()
  148. },
  149. methods: {
  150. // 获取参数
  151. getQueryParams() {
  152. const url = window.location.search;
  153. const params = url
  154. .substring(1)
  155. .split('&')
  156. .reduce((result, param) => {
  157. const [key, value] = param.split('=');
  158. result[decodeURIComponent(key)] = decodeURIComponent(value);
  159. return result;
  160. }, {});
  161. return params;
  162. },
  163. // 页面浏览行为个性化页面处理
  164. PAGE_BROWSE_FN(){
  165. switch (this.CURRENT_ROUTE.route){
  166. case 'product/detail/detail':{
  167. this.BIND_TYPE = 1 //产品
  168. } break;
  169. case 'match/activityDetail/activityDetail':{
  170. this.BIND_TYPE = 2 //活动
  171. } break;
  172. case 'topic/content/content':{
  173. this.BIND_TYPE = 3 //文章
  174. } break;
  175. case 'topic/case/case':{
  176. this.BIND_TYPE = 3 //文章
  177. this.TYPE_NAME = '案例'
  178. } break;
  179. case 'card/index/index':{
  180. this.BIND_TYPE = 7 //名片
  181. this.BIND_ID = this.OPTIONS.cardId
  182. } break;
  183. case 'leaflet/detail/index':{
  184. this.BIND_TYPE = 8 //素材
  185. } break;
  186. case 'topic/solDet/solDet':{
  187. this.BIND_TYPE = 9 //专题
  188. } break;
  189. case 'promote/info/info':{
  190. this.BIND_TYPE = 12 //合伙人招募页面
  191. this.BIND_ID = 0 //
  192. } break;
  193. case 'martial/content/index':{
  194. this.BIND_TYPE = 8 //文章
  195. this.TYPE_NAME = '软文'
  196. } break;
  197. case 'martial/leaflet/index':{
  198. this.BIND_TYPE = 8 //宣传彩页
  199. this.TYPE_NAME = '宣传彩页'
  200. } break;
  201. case 'martial/file/index':{
  202. this.BIND_TYPE = 8 //宣传彩页
  203. this.TYPE_NAME = '文件'
  204. } break;
  205. case 'martial/video/index':{
  206. this.BIND_TYPE = 8 //宣传彩页
  207. this.TYPE_NAME = '文件'
  208. } break;
  209. default:{
  210. this.BIND_TYPE = 14
  211. this.BIND_ID = ''
  212. } break;
  213. }
  214. },
  215. /**
  216. * 修改参数(需要修改参数时传入对应需要修改的参数即可)
  217. * @param BIND_TYPE 行为对象类型
  218. * @param BIND_ID 行为对象id
  219. * @param USER_ID 当前用户id
  220. * @param SHARE_USER_ID 分享用户id
  221. * @param PARENT_CODE 上级行为code(用与二次转发)
  222. * @param TYPE_NAME 自定义类型名称
  223. * @param PAGE_NAME 自定义页面标题
  224. */
  225. PAGE_DATA_INIT_FN({
  226. BIND_TYPE = '',
  227. BIND_ID = '',
  228. USER_ID = '',
  229. SHARE_USER_ID = '',
  230. PARENT_CODE = '',
  231. TYPE_NAME = '',
  232. PAGE_NAME = ''
  233. }={}){
  234. if(BIND_TYPE) this.BIND_TYPE = BIND_TYPE
  235. if(BIND_ID) this.BIND_ID = BIND_ID
  236. if(USER_ID) this.USER_ID = USER_ID
  237. if(SHARE_USER_ID) this.SHARE_USER_ID = SHARE_USER_ID
  238. if(PARENT_CODE) this.PARENT_CODE = PARENT_CODE
  239. if(TYPE_NAME) this.TYPE_NAME = TYPE_NAME
  240. if(PAGE_NAME) this.PAGE_NAME = PAGE_NAME
  241. },
  242. /**
  243. * 记录用户浏览行为,浏览行为上报(参数非必传,只有需要修改参数时传入对应需要修改的参数即可)
  244. * @param BIND_TYPE 行为对象类型
  245. * @param BIND_ID 行为对象id
  246. * @param USER_ID 当前用户id
  247. * @param SHARE_USER_ID 分享用户id
  248. * @param PARENT_CODE 上级行为code(用与二次转发)
  249. */
  250. SEND_BROWSE_FN ({
  251. BIND_TYPE = this.BIND_TYPE,
  252. BIND_ID = this.BIND_ID,
  253. USER_ID = this.USER_ID,
  254. SHARE_USER_ID = this.SHARE_USER_ID,
  255. PARENT_CODE = this.PARENT_CODE
  256. }={}){
  257. // console.log(BIND_TYPE,BIND_ID,USER_ID,SHARE_USER_ID,PARENT_CODE)
  258. let postObj = {
  259. type:BIND_TYPE,
  260. bindId:BIND_ID,
  261. uid:USER_ID,
  262. shareUid:SHARE_USER_ID,
  263. parentCode:PARENT_CODE,
  264. code:this.CURRENT_CODE,
  265. pageUri:this.CURRENT_ROUTE.route,
  266. readTime:this.ACTION_STAY_TIME?Math.ceil(this.ACTION_STAY_TIME/1000):null
  267. }
  268. // 自定义类型名称
  269. if(this.TYPE_NAME) postObj.typeName = this.TYPE_NAME
  270. // 如果是页面浏览
  271. if(postObj.type==14){
  272. postObj.content = `浏览了${this.PAGE_NAME}页面`;
  273. postObj.typeName = this.PAGE_NAME
  274. }
  275. actionsdk.saveBrowse(postObj);
  276. },
  277. /**
  278. * 记录用户分享行为,分享行为上报
  279. * @param BIND_TYPE 行为对象类型
  280. * @param BIND_ID 行为对象id
  281. * @param USER_ID 当前用户id
  282. * @param SHARE_USER_ID 分享用户id
  283. * @param PARENT_CODE 上级行为code(用与二次转发)
  284. */
  285. SEND_SHARE_FN ({
  286. BIND_TYPE = this.BIND_TYPE,
  287. BIND_ID = this.BIND_ID,
  288. USER_ID = this.USER_ID,
  289. SHARE_USER_ID = this.SHARE_USER_ID,
  290. PARENT_CODE = this.PARENT_CODE
  291. }={}){
  292. let postObj = {
  293. behaviorType:5,
  294. type:BIND_TYPE,
  295. bindId:BIND_ID,
  296. uid:USER_ID,
  297. shareUid:SHARE_USER_ID,
  298. parentCode:PARENT_CODE,
  299. code:this.CURRENT_CODE
  300. }
  301. // 自定义类型名称
  302. if(this.TYPE_NAME) postObj.typeName = this.TYPE_NAME
  303. // 分享行为固定behaviorType 5
  304. // 延后分享是因为分享不是在成功回调调用的,导致浏览上报事件在分享上报事件前执行了,延后1s可保证时序性
  305. setTimeout(()=>{
  306. actionsdk.saveBehavior(postObj);
  307. },1000)
  308. },
  309. /**
  310. * 分享行为预处理(处理分享出去的PARENT_CODE,参数按分享参数传入,分享时取该方法返回的参数)
  311. * @param path 分享路径
  312. * @param sendShare 是否立即触发分享行为上报,默认不开启
  313. * @param codeScene 生成小程序码时的自定义参数,object
  314. */
  315. SHARE_BEHAVIOR_FN({
  316. path = '',
  317. sendShare = false,
  318. codeScene = {}
  319. }={}){
  320. if(!this.CURRENT_CODE){
  321. this.CURRENT_CODE = actionsdk.creatBehaviorCode()
  322. }
  323. if(sendShare){
  324. this.SEND_SHARE_FN()
  325. }
  326. // 小程序码参数拼接parentCode
  327. codeScene.parentCode = this.CURRENT_CODE
  328. // 分享路径拼接parentCode
  329. if(path.indexOf('?')>-1){
  330. path = path + '&parentCode='+this.CURRENT_CODE
  331. }else{
  332. path = path + '?parentCode='+this.CURRENT_CODE
  333. }
  334. return {
  335. path:path,
  336. codeScene:codeScene
  337. }
  338. },
  339. /**
  340. * 记录用户收藏行为,收藏行为上报
  341. * @param BIND_TYPE 行为对象类型
  342. * @param BIND_ID 行为对象id
  343. * @param USER_ID 当前用户id
  344. * @param SHARE_USER_ID 分享用户id
  345. * @param PARENT_CODE 上级行为code(用与二次转发)
  346. */
  347. SEND_COLLECT_FN ({
  348. BIND_TYPE = this.BIND_TYPE,
  349. BIND_ID = this.BIND_ID,
  350. USER_ID = this.USER_ID,
  351. SHARE_USER_ID = this.SHARE_USER_ID,
  352. PARENT_CODE = this.PARENT_CODE,
  353. }={}){
  354. let postObj = {
  355. behaviorType:2,
  356. type:BIND_TYPE,
  357. bindId:BIND_ID,
  358. uid:USER_ID,
  359. shareUid:SHARE_USER_ID,
  360. parentCode:PARENT_CODE,
  361. code:this.CURRENT_CODE
  362. }
  363. // 收藏行为固定behaviorType 2
  364. actionsdk.saveBehavior(postObj);
  365. },
  366. /**
  367. * 其他行为上报
  368. * @param BEHAVIOR_TYPE 行为类型
  369. * @param BIND_TYPE 行为对象类型
  370. * @param BIND_ID 行为对象id
  371. * @param USER_ID 当前用户id
  372. * @param CONTENT 日志文案(如:'浏览了xxx文章')
  373. * @param READ_TIME 行为时长(如:'浏览时长',单位s)
  374. * @param TYPE_NAME 自定义类型名称
  375. * @param SHARE_USER_ID 分享用户id
  376. * @param PARENT_CODE 上级行为code(用与二次转发)
  377. */
  378. SEND_SELF_FN ({
  379. BEHAVIOR_TYPE = '',
  380. BIND_TYPE = this.BIND_TYPE,
  381. BIND_ID = this.BIND_ID,
  382. USER_ID = this.USER_ID,
  383. CONTENT = '',
  384. READ_TIME = '',
  385. TYPE_NAME = '',
  386. SHARE_USER_ID = this.SHARE_USER_ID,
  387. PARENT_CODE = this.PARENT_CODE,
  388. }={}){
  389. if(!BEHAVIOR_TYPE) {
  390. throw new Error("未传入行为类型")
  391. return false
  392. }
  393. let postObj = {
  394. behaviorType:BEHAVIOR_TYPE,
  395. type:BIND_TYPE,
  396. bindId:BIND_ID,
  397. uid:USER_ID,
  398. shareUid:SHARE_USER_ID,
  399. parentCode:PARENT_CODE,
  400. code:this.CURRENT_CODE,
  401. content:CONTENT,
  402. pageUri:this.CURRENT_ROUTE.route,
  403. readTime:READ_TIME,
  404. TYPE_NAME:TYPE_NAME
  405. }
  406. actionsdk.saveBehavior(postObj);
  407. },
  408. /**
  409. * 记录用户点赞行为,点赞行为上报
  410. * @param BIND_TYPE 行为对象类型
  411. * @param BIND_ID 行为对象id
  412. * @param USER_ID 当前用户id
  413. * @param SHARE_USER_ID 分享用户id
  414. * @param PARENT_CODE 上级行为code(用与二次转发)
  415. * @param IS_THUMBS 是否是点赞,false为取消点赞
  416. */
  417. SEND_COLLECT_FN ({
  418. BIND_TYPE = this.BIND_TYPE,
  419. BIND_ID = this.BIND_ID,
  420. USER_ID = this.USER_ID,
  421. SHARE_USER_ID = this.SHARE_USER_ID,
  422. PARENT_CODE = this.PARENT_CODE,
  423. IS_THUMBS = true
  424. }={}){
  425. let postObj = {
  426. behaviorType:3,
  427. type:BIND_TYPE,
  428. bindId:BIND_ID,
  429. uid:USER_ID,
  430. shareUid:SHARE_USER_ID,
  431. parentCode:PARENT_CODE,
  432. code:this.CURRENT_CODE,
  433. IS_THUMBS:IS_THUMBS
  434. }
  435. // 点赞行为固定behaviorType 3
  436. if(IS_THUMBS){
  437. actionsdk.saveBehavior(postObj);
  438. }else{
  439. actionsdk.removeBehavior(postObj);
  440. }
  441. },
  442. // 获取行为接口请求参数(为实现部分项目未埋点时可通过后台接口埋点的冗余方案,纯后台埋点无行为完整链条,只有传入前端参数才能保证行为链条完整)
  443. GET_API_DATA(){
  444. let data = {
  445. shareUid: this.SHARE_USER_ID,
  446. code:this.CURRENT_CODE,
  447. shareCode: this.PARENT_CODE,
  448. };
  449. var deviceInfo = this.ACTION_SDK.getStorage('deviceInfo');
  450. // #ifdef APP-PLUS
  451. var sysMac = this.ACTION_SDK.getStorage('sysMac');
  452. // #endif
  453. var device_info = {};
  454. if (deviceInfo) {
  455. data.model = deviceInfo.deviceModel;
  456. data.manufacturer = deviceInfo.deviceBrand;
  457. data.os = deviceInfo.osName;
  458. data.osVersion = deviceInfo.osVersion;
  459. data.browser = deviceInfo.browserName;
  460. data.browserVersion = deviceInfo.browserVersion;
  461. data.deviceId = deviceInfo.deviceId;
  462. // #ifdef APP-PLUS
  463. if (sysMac) {
  464. data.sysMac = sysMac;
  465. }
  466. // #endif
  467. }
  468. return data
  469. },
  470. // 扫码进入时解码方法
  471. LOAD_CODE_PARAMS(scene) {
  472. return new Promise((resolve, reject) => {
  473. let form = {
  474. scene: scene
  475. };
  476. if (!scene) {
  477. resolve();
  478. return false;
  479. }
  480. this.ACTION_SDK.getRequestAPI('/api/code/params', form, data => {
  481. let res = JSON.parse(data.scene);
  482. if(data.userId){
  483. this.SHARE_USER_ID = data.userId
  484. }
  485. if(res.id){
  486. this.BIND_ID = res.id
  487. }
  488. if(res.userId){
  489. this.SHARE_USER_ID = res.userId
  490. }
  491. if(res.parentCode){
  492. this.PARENT_CODE = res.parentCode
  493. }
  494. resolve();
  495. });
  496. });
  497. },
  498. // 获取页面标题
  499. GET_PAGE_NAME(){
  500. let name = this.CURRENT_ROUTE.route
  501. console.log('GET_PAGE_NAME',PAGES_JSON)
  502. for(let key in PAGES_JSON){
  503. let getCurrentStyle = PAGES_JSON.pages.find((item) => item.path == this.CURRENT_ROUTE.route);
  504. if(getCurrentStyle){
  505. return getCurrentStyle.style&&getCurrentStyle.style.navigationBarTitleText?getCurrentStyle.style.navigationBarTitleText:getCurrentStyle.path
  506. }else{
  507. for(let i=0;i<PAGES_JSON.subPackages.length;i++){
  508. let subPackages = PAGES_JSON.subPackages[i]
  509. let getCurrentStyle = subPackages.pages.find((item) => subPackages.root+'/'+item.path == this.CURRENT_ROUTE.route);
  510. if(getCurrentStyle){
  511. return getCurrentStyle.style&&getCurrentStyle.style.navigationBarTitleText?getCurrentStyle.style.navigationBarTitleText:getCurrentStyle.path
  512. }
  513. }
  514. }
  515. }
  516. return name
  517. }
  518. }
  519. };