uni-cloud-stat.cjs.js 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606
  1. 'use strict';
  2. /**
  3. * 获取系统信息
  4. */
  5. const sys = uni.getSystemInfoSync();
  6. // 访问开始即启动小程序,访问结束结分为:进入后台超过5min、在前台无任何操作超过30min、在新的来源打开小程序;
  7. const STAT_VERSION = process.env.UNI_COMPILER_VERSION;
  8. const STAT_URL = 'https://tongji.dcloud.io/uni/stat';
  9. const STAT_H5_URL = 'https://tongji.dcloud.io/uni/stat.gif';
  10. const PAGE_PVER_TIME = 1800; // 页面在前台无操作结束访问时间 单位s
  11. const APP_PVER_TIME = 300; // 应用在后台结束访问时间 单位s
  12. const OPERATING_TIME = 10; // 数据上报时间 单位s
  13. const DIFF_TIME = 60 * 1000 * 60 * 24;
  14. const appid = process.env.UNI_APP_ID; // 做应用隔离
  15. const dbSet = (name, value) => {
  16. let data = uni.getStorageSync('$$STAT__DBDATA:'+appid) || {};
  17. if (!data) {
  18. data = {};
  19. }
  20. data[name] = value;
  21. uni.setStorageSync('$$STAT__DBDATA:'+appid, data);
  22. };
  23. const dbGet = (name) => {
  24. let data = uni.getStorageSync('$$STAT__DBDATA:'+appid) || {};
  25. if (!data[name]) {
  26. let dbdata = uni.getStorageSync('$$STAT__DBDATA:'+appid);
  27. if (!dbdata) {
  28. dbdata = {};
  29. }
  30. if (!dbdata[name]) {
  31. return undefined
  32. }
  33. data[name] = dbdata[name];
  34. }
  35. return data[name]
  36. };
  37. const dbRemove = (name) => {
  38. let data = uni.getStorageSync('$$STAT__DBDATA:'+appid) || {};
  39. if (data[name]) {
  40. delete data[name];
  41. uni.setStorageSync('$$STAT__DBDATA:'+appid, data);
  42. } else {
  43. data = uni.getStorageSync('$$STAT__DBDATA:'+appid);
  44. if (data[name]) {
  45. delete data[name];
  46. uni.setStorageSync('$$STAT__DBDATA:'+appid, data);
  47. }
  48. }
  49. };
  50. // 获取 manifest.json 中统计配置
  51. const uniStatisticsConfig = process.env.UNI_STATISTICS_CONFIG;
  52. let statConfig = {
  53. appid: process.env.UNI_APP_ID,
  54. };
  55. let titleJsons = {};
  56. let debug = !!process.env.UNI_STAT_DEBUG || false;
  57. // #ifdef VUE3
  58. titleJsons = process.env.UNI_STAT_TITLE_JSON;
  59. // #endif
  60. // #ifndef VUE3
  61. // eslint-disable-next-line no-restricted-globals
  62. const pagesTitle = require('uni-pages?{"type":"style"}').default;
  63. let pagesData = pagesTitle.pages;
  64. for (let i in pagesData) {
  65. const style = pagesData[i];
  66. const titleText =
  67. // MP
  68. style.navigationBarTitleText ||
  69. // ali
  70. style.defaultTitle ||
  71. // H5 || App
  72. style.navigationBar?.titleText ||
  73. '';
  74. if (titleText) {
  75. titleJsons[i] = titleText;
  76. }
  77. }
  78. // #endif
  79. // TODO 在云函数中获取,暂时注释
  80. const UUID_KEY = '__DC_STAT_UUID';
  81. const UUID_VALUE = '__DC_UUID_VALUE';
  82. function getUuid() {
  83. let uuid = '';
  84. if (get_platform_name() === 'n') {
  85. try {
  86. uuid = plus.runtime.getDCloudId();
  87. } catch (e) {
  88. uuid = '';
  89. }
  90. return uuid
  91. }
  92. try {
  93. uuid = uni.getStorageSync(UUID_KEY);
  94. } catch (e) {
  95. uuid = UUID_VALUE;
  96. }
  97. if (!uuid) {
  98. uuid = Date.now() + '' + Math.floor(Math.random() * 1e7);
  99. try {
  100. uni.setStorageSync(UUID_KEY, uuid);
  101. } catch (e) {
  102. uni.setStorageSync(UUID_KEY, UUID_VALUE);
  103. }
  104. }
  105. return uuid
  106. }
  107. const get_uuid = (statData) => {
  108. // 有可能不存在 deviceId(一般不存在就是出bug了),就自己生成一个
  109. return sys.deviceId || getUuid()
  110. };
  111. /**
  112. * 获取老版的 deviceid ,兼容以前的错误 deviceid
  113. * @param {*} statData
  114. * @returns
  115. */
  116. const get_odid = (statData) => {
  117. let odid = '';
  118. if (get_platform_name() === 'n') {
  119. try {
  120. odid = plus.device.uuid;
  121. } catch (e) {
  122. odid = '';
  123. }
  124. return odid
  125. }
  126. return sys.deviceId || getUuid()
  127. };
  128. /**
  129. * 获取配置信息 如 appid
  130. */
  131. const stat_config = statConfig;
  132. const get_sgin = (statData) => {
  133. let arr = Object.keys(statData);
  134. let sortArr = arr.sort();
  135. let sgin = {};
  136. let sginStr = '';
  137. for (var i in sortArr) {
  138. sgin[sortArr[i]] = statData[sortArr[i]];
  139. sginStr += sortArr[i] + '=' + statData[sortArr[i]] + '&';
  140. }
  141. return {
  142. sign: '',
  143. options: sginStr.substr(0, sginStr.length - 1),
  144. }
  145. };
  146. const get_encodeURIComponent_options = (statData) => {
  147. let data = {};
  148. for (let prop in statData) {
  149. data[prop] = encodeURIComponent(statData[prop]);
  150. }
  151. return data
  152. };
  153. /**
  154. * 获取当前平台
  155. * 移动端 : 'n',
  156. * h5 : 'h5',
  157. * 微信 : 'wx',
  158. * 阿里 : 'ali',
  159. * 百度 : 'bd',
  160. * 头条 : 'tt',
  161. * qq : 'qq',
  162. * 快应用 : 'qn',
  163. * 快手 : 'ks',
  164. * 飞书 : 'lark',
  165. * 快应用 : 'qw',
  166. * 钉钉 : 'dt'
  167. */
  168. const get_platform_name = () => {
  169. // 苹果审核代码中禁止出现 alipay 字样 ,需要特殊处理一下
  170. const aliArr = ['y', 'a', 'p', 'mp-ali'];
  171. const platformList = {
  172. app: 'n',
  173. 'app-plus': 'n',
  174. h5: 'h5',
  175. 'mp-weixin': 'wx',
  176. [aliArr.reverse().join('')]: 'ali',
  177. 'mp-baidu': 'bd',
  178. 'mp-toutiao': 'tt',
  179. 'mp-qq': 'qq',
  180. 'quickapp-native': 'qn',
  181. 'mp-kuaishou': 'ks',
  182. 'mp-lark': 'lark',
  183. 'quickapp-webview': 'qw',
  184. };
  185. if (platformList[process.env.VUE_APP_PLATFORM] === 'ali') {
  186. if (my && my.env) {
  187. const clientName = my.env.clientName;
  188. if (clientName === 'ap') return 'ali'
  189. if (clientName === 'dingtalk') return 'dt'
  190. // TODO 缺少 ali 下的其他平台
  191. }
  192. }
  193. return platformList[process.env.VUE_APP_PLATFORM]
  194. };
  195. /**
  196. * 获取小程序 appid
  197. */
  198. const get_pack_name = () => {
  199. let packName = '';
  200. if (get_platform_name() === 'wx' || get_platform_name() === 'qq') {
  201. // 兼容微信小程序低版本基础库
  202. if (uni.canIUse('getAccountInfoSync')) {
  203. packName = uni.getAccountInfoSync().miniProgram.appId || '';
  204. }
  205. }
  206. if (get_platform_name() === 'n') ;
  207. return packName
  208. };
  209. /**
  210. * 应用版本
  211. */
  212. const get_version = () => {
  213. return get_platform_name() === 'n' ? plus.runtime.version : ''
  214. };
  215. /**
  216. * 获取渠道
  217. */
  218. const get_channel = () => {
  219. const platformName = get_platform_name();
  220. let channel = '';
  221. if (platformName === 'n') {
  222. channel = plus.runtime.channel;
  223. }
  224. return channel
  225. };
  226. /**
  227. * 获取小程序场景值
  228. * @param {Object} options 页面信息
  229. */
  230. const get_scene = (options) => {
  231. const platformName = get_platform_name();
  232. let scene = '';
  233. if (options) {
  234. return options
  235. }
  236. if (platformName === 'wx') {
  237. scene = uni.getLaunchOptionsSync().scene;
  238. }
  239. return scene
  240. };
  241. /**
  242. * 获取页面url,不包含参数
  243. */
  244. const get_route$1 = (pageVm) => {
  245. let _self = pageVm || get_page_vm();
  246. if (get_platform_name() === 'bd') {
  247. let mp_route = _self.$mp && _self.$mp.page && _self.$mp.page.is;
  248. let scope_route = _self.$scope && _self.$scope.is;
  249. return mp_route || scope_route || ''
  250. } else {
  251. return (
  252. _self.route ||
  253. (_self.$scope && _self.$scope.route) ||
  254. (_self.$mp && _self.$mp.page.route)
  255. )
  256. }
  257. };
  258. /**
  259. * 获取页面url, 包含参数
  260. */
  261. const get_page_route = (pageVm) => {
  262. // 从 app 进入应用 ,没有 $page ,获取不到路由 ,需要获取页面 尝试从 getCurrentPages 获取也页面实例
  263. // FIXME 尽量不使用 getCurrentPages ,大部分获取路由是从 onHide 获取 ,这时可以获取到,如果是 onload ,则可能获取不到,比如 百度
  264. let page = pageVm && (pageVm.$page || (pageVm.$scope && pageVm.$scope.$page));
  265. let lastPageRoute = uni.getStorageSync('_STAT_LAST_PAGE_ROUTE');
  266. if (!page) return lastPageRoute || ''
  267. // 如果找不到 fullPath 就取 route 的值
  268. return page.fullPath === '/' ? page.route : page.fullPath || page.route
  269. };
  270. /**
  271. * 获取页面实例
  272. */
  273. const get_page_vm = () => {
  274. let pages = getCurrentPages();
  275. let $page = pages[pages.length - 1];
  276. if (!$page) return null
  277. return $page.$vm
  278. };
  279. /**
  280. * 获取页面类型
  281. */
  282. const get_page_types = (self) => {
  283. // XXX 百度有问题 ,获取的都是 componet ,等待修复
  284. if (
  285. self.mpType === 'page' ||
  286. self.$mpType === 'page' ||
  287. (self.$mp && self.$mp.mpType === 'page') ||
  288. self.$options.mpType === 'page'
  289. ) {
  290. return 'page'
  291. }
  292. if (
  293. self.mpType === 'app' ||
  294. self.$mpType === 'app' ||
  295. (self.$mp && self.$mp.mpType === 'app') ||
  296. self.$options.mpType === 'app'
  297. ) {
  298. return 'app'
  299. }
  300. return null
  301. };
  302. /**
  303. * 处理上报参数
  304. * @param {Object} 需要处理的数据
  305. */
  306. const handle_data = (statData) => {
  307. let firstArr = [];
  308. let contentArr = [];
  309. let lastArr = [];
  310. for (let i in statData) {
  311. const rd = statData[i];
  312. rd.forEach((elm) => {
  313. let newData = '';
  314. {
  315. newData = elm;
  316. }
  317. if (i === 0) {
  318. firstArr.push(newData);
  319. } else if (i === 3) {
  320. lastArr.push(newData);
  321. } else {
  322. contentArr.push(newData);
  323. }
  324. });
  325. }
  326. firstArr.push(...contentArr, ...lastArr);
  327. // 参数需要处理成字符串,方便上传
  328. return JSON.stringify(firstArr)
  329. };
  330. /**
  331. * 自定义事件参数校验
  332. */
  333. const calibration = (eventName, options) => {
  334. // login 、 share 、pay_success 、pay_fail 、register 、title
  335. if (!eventName) {
  336. console.error(`uni.report Missing [eventName] parameter`);
  337. return true
  338. }
  339. if (typeof eventName !== 'string') {
  340. console.error(
  341. `uni.report [eventName] Parameter type error, it can only be of type String`
  342. );
  343. return true
  344. }
  345. if (eventName.length > 255) {
  346. console.error(
  347. `uni.report [eventName] Parameter length cannot be greater than 255`
  348. );
  349. return true
  350. }
  351. if (typeof options !== 'string' && typeof options !== 'object') {
  352. console.error(
  353. 'uni.report [options] Parameter type error, Only supports String or Object type'
  354. );
  355. return true
  356. }
  357. if (typeof options === 'string' && options.length > 255) {
  358. console.error(
  359. `uni.report [options] Parameter length cannot be greater than 255`
  360. );
  361. return true
  362. }
  363. if (eventName === 'title' && typeof options !== 'string') {
  364. console.error(
  365. `uni.report [eventName] When the parameter is title, the [options] parameter can only be of type String`
  366. );
  367. return true
  368. }
  369. };
  370. const get_page_name = (routepath) => {
  371. return (titleJsons && titleJsons[routepath]) || ''
  372. };
  373. const Report_Data_Time = 'Report_Data_Time';
  374. const Report_Status = 'Report_Status';
  375. const is_report_data = () => {
  376. return new Promise((resolve, reject) => {
  377. let start_time = '';
  378. let end_time = new Date().getTime();
  379. let diff_time = DIFF_TIME;
  380. let report_status = 1;
  381. try {
  382. start_time = uni.getStorageSync(Report_Data_Time);
  383. report_status = uni.getStorageSync(Report_Status);
  384. } catch (e) {
  385. start_time = '';
  386. report_status = 1;
  387. }
  388. if (report_status === '') {
  389. requestData(({ enable }) => {
  390. uni.setStorageSync(Report_Data_Time, end_time);
  391. uni.setStorageSync(Report_Status, enable);
  392. if (enable === 1) {
  393. resolve();
  394. }
  395. });
  396. return
  397. }
  398. if (report_status === 1) {
  399. resolve();
  400. }
  401. if (!start_time) {
  402. uni.setStorageSync(Report_Data_Time, end_time);
  403. start_time = end_time;
  404. }
  405. if (end_time - start_time > diff_time) {
  406. requestData(({ enable }) => {
  407. uni.setStorageSync(Report_Data_Time, end_time);
  408. uni.setStorageSync(Report_Status, enable);
  409. });
  410. }
  411. })
  412. };
  413. const requestData = (done) => {
  414. const appid = process.env.UNI_APP_ID;
  415. let formData = {
  416. usv: STAT_VERSION,
  417. conf: JSON.stringify({
  418. ak: appid,
  419. }),
  420. };
  421. uni.request({
  422. url: STAT_URL,
  423. method: 'GET',
  424. data: formData,
  425. success: (res) => {
  426. const { data } = res;
  427. if (data.ret === 0) {
  428. typeof done === 'function' &&
  429. done({
  430. enable: data.enable,
  431. });
  432. }
  433. },
  434. fail: (e) => {
  435. let report_status_code = 1;
  436. try {
  437. report_status_code = uni.getStorageSync(Report_Status);
  438. } catch (e) {
  439. report_status_code = 1;
  440. }
  441. if (report_status_code === '') {
  442. report_status_code = 1;
  443. }
  444. typeof done === 'function' &&
  445. done({
  446. enable: report_status_code,
  447. });
  448. },
  449. });
  450. };
  451. /**
  452. * 获取uniCloud服务空间配置
  453. * @returns {Object}
  454. */
  455. const uni_cloud_config = () => {
  456. return process.env.UNI_STAT_UNI_CLOUD || {}
  457. };
  458. /**
  459. * 获取服务空间
  460. * @param {*} config
  461. * @returns
  462. */
  463. const get_space = (config) => {
  464. const uniCloudConfig = uni_cloud_config();
  465. const { spaceId, provider, clientSecret ,secretKey,secretId} = uniCloudConfig;
  466. const space_type = ['tcb', 'tencent', 'aliyun','alipay'];
  467. const is_provider = space_type.indexOf(provider) !== -1;
  468. const is_aliyun = provider === 'aliyun' && spaceId && clientSecret;
  469. const is_tcb = (provider === 'tcb' || provider === 'tencent') && spaceId;
  470. const is_alipay = provider === 'alipay' && spaceId && secretKey && secretId;
  471. if (is_provider && (is_aliyun || is_tcb || is_alipay)) {
  472. return uniCloudConfig
  473. } else {
  474. if (config && config.spaceId) {
  475. return config
  476. }
  477. }
  478. return null
  479. };
  480. /**
  481. * 是否开启 debug 模式
  482. */
  483. const is_debug = debug;
  484. /**
  485. * 日志输出
  486. * @param {*} data
  487. */
  488. const log = (data, type) => {
  489. let msg_type = '';
  490. switch (data.lt) {
  491. case '1':
  492. msg_type = '应用启动';
  493. break
  494. case '3':
  495. msg_type = '应用进入后台';
  496. break
  497. case '11':
  498. msg_type = '页面切换';
  499. break
  500. case '21':
  501. msg_type = '事件触发';
  502. break
  503. case '31':
  504. msg_type = '应用错误';
  505. break
  506. case '101':
  507. msg_type = 'PUSH';
  508. break
  509. }
  510. // #ifdef APP
  511. // 在 app 中,日志转为 字符串
  512. if (typeof data === 'object') {
  513. data = JSON.stringify(data);
  514. }
  515. // #endif
  516. if (type) {
  517. console.log(`=== 统计队列数据上报 ===`);
  518. console.log(data);
  519. console.log(`=== 上报结束 ===`);
  520. return
  521. }
  522. if (msg_type) {
  523. console.log(`=== 统计数据采集:${msg_type} ===`);
  524. console.log(data);
  525. console.log(`=== 采集结束 ===`);
  526. }
  527. };
  528. /**
  529. * 获取上报时间间隔
  530. * @param {*} defaultTime 默认上报间隔时间 单位s
  531. */
  532. const get_report_Interval = (defaultTime) => {
  533. let time = uniStatisticsConfig.reportInterval;
  534. // 如果上报时间配置为0 相当于立即上报
  535. if (Number(time) === 0) return 0
  536. time = time || defaultTime;
  537. let reg = /(^[1-9]\d*$)/;
  538. // 如果不是整数,则默认为上报间隔时间
  539. if (!reg.test(time)) return defaultTime
  540. return Number(time)
  541. };
  542. /**
  543. * 获取隐私协议配置
  544. */
  545. const is_push_clientid = () => {
  546. if (uniStatisticsConfig.collectItems) {
  547. const ClientID = uniStatisticsConfig.collectItems.uniPushClientID;
  548. return typeof ClientID === 'boolean' ? ClientID : false
  549. }
  550. return false
  551. };
  552. /**
  553. * 是否上报页面数据
  554. * @returns
  555. */
  556. const is_page_report = ()=>{
  557. if(uniStatisticsConfig.collectItems){
  558. const statPageLog = uniStatisticsConfig.collectItems.uniStatPageLog;
  559. // 如果字段不存在返回 true , 如果是boolean 值按原值返回,如果是其他类型 返回false
  560. if(statPageLog === undefined) return true
  561. return typeof statPageLog === 'boolean' ? statPageLog : true
  562. }
  563. return true
  564. };
  565. /**
  566. * 是否已处理设备 DeviceId
  567. * 如果值为 1 则表示已处理
  568. */
  569. const IS_HANDLE_DEVECE_ID = 'is_handle_device_id';
  570. const is_handle_device = () => {
  571. let isHandleDevice = dbGet(IS_HANDLE_DEVECE_ID) || '';
  572. dbSet(IS_HANDLE_DEVECE_ID, '1');
  573. return isHandleDevice === '1'
  574. };
  575. // 首次访问时间
  576. const FIRST_VISIT_TIME_KEY = '__first__visit__time';
  577. // 最后访问时间
  578. const LAST_VISIT_TIME_KEY = '__last__visit__time';
  579. /**
  580. * 获取当前时间
  581. */
  582. const get_time = () => {
  583. return parseInt(new Date().getTime() / 1000)
  584. };
  585. /**
  586. * 获取首次访问时间
  587. */
  588. const get_first_visit_time = () => {
  589. const timeStorge = dbGet(FIRST_VISIT_TIME_KEY);
  590. let time = 0;
  591. if (timeStorge) {
  592. time = timeStorge;
  593. } else {
  594. time = get_time();
  595. dbSet(FIRST_VISIT_TIME_KEY, time);
  596. // 首次访问需要 将最后访问时间置 0
  597. dbRemove(LAST_VISIT_TIME_KEY);
  598. }
  599. return time
  600. };
  601. /**
  602. * 最后访问时间
  603. */
  604. const get_last_visit_time = () => {
  605. const timeStorge = dbGet(LAST_VISIT_TIME_KEY);
  606. let time = 0;
  607. if (timeStorge) {
  608. time = timeStorge;
  609. }
  610. dbSet(LAST_VISIT_TIME_KEY, get_time());
  611. return time
  612. };
  613. // 页面停留时间记录key
  614. const PAGE_RESIDENCE_TIME = '__page__residence__time';
  615. let First_Page_Residence_Time = 0;
  616. let Last_Page_Residence_Time = 0;
  617. /**
  618. * 设置页面停留时间
  619. */
  620. const set_page_residence_time = () => {
  621. First_Page_Residence_Time = get_time();
  622. dbSet(PAGE_RESIDENCE_TIME, First_Page_Residence_Time);
  623. return First_Page_Residence_Time
  624. };
  625. /**
  626. * 获取页面停留时间
  627. */
  628. const get_page_residence_time = () => {
  629. Last_Page_Residence_Time = get_time();
  630. First_Page_Residence_Time = dbGet(PAGE_RESIDENCE_TIME);
  631. return Last_Page_Residence_Time - First_Page_Residence_Time
  632. };
  633. /**
  634. * 获取总访问次数
  635. */
  636. const TOTAL_VISIT_COUNT = '__total__visit__count';
  637. const get_total_visit_count = () => {
  638. const timeStorge = dbGet(TOTAL_VISIT_COUNT);
  639. let count = 1;
  640. if (timeStorge) {
  641. count = timeStorge;
  642. count++;
  643. }
  644. dbSet(TOTAL_VISIT_COUNT, count);
  645. return count
  646. };
  647. const FIRST_TIME = '__first_time';
  648. /**
  649. * 设置页面首次访问时间,用户获取页面/应用停留时常
  650. */
  651. const set_first_time = () => {
  652. // 获取当前时间 ,以下代码获取到是毫秒级时间戳 ,实际上用到是秒级时间戳,所以需要除以1000
  653. // const time = new Date().getTime()
  654. let time = get_time();
  655. const timeStorge = dbSet(FIRST_TIME,time);
  656. return timeStorge
  657. };
  658. /**
  659. * 获取最后一次时间 ,暂时用不到,直接获取当前时间即可
  660. */
  661. // export const get_last_time = () => {
  662. // let time = new Date().getTime()
  663. // Set__Last__Time = time
  664. // return time
  665. // }
  666. /**
  667. * 获取页面 \ 应用停留时间
  668. */
  669. const get_residence_time = (type) => {
  670. let residenceTime = 0;
  671. const first_time = dbGet(FIRST_TIME);
  672. const last_time = get_time();
  673. if (first_time !== 0) {
  674. residenceTime = last_time - first_time;
  675. }
  676. // 将毫秒级时间戳转换为秒级时间戳,因为直接获取的是秒级时间戳,所以不需要转换
  677. // residenceTime = parseInt(residenceTime / 1000)
  678. residenceTime = residenceTime < 1 ? 1 : residenceTime;
  679. if (type === 'app') {
  680. let overtime = residenceTime > APP_PVER_TIME ? true : false;
  681. return {
  682. residenceTime,
  683. overtime,
  684. }
  685. }
  686. if (type === 'page') {
  687. let overtime = residenceTime > PAGE_PVER_TIME ? true : false;
  688. return {
  689. residenceTime,
  690. overtime,
  691. }
  692. }
  693. return {
  694. residenceTime,
  695. }
  696. };
  697. const eport_Interval = get_report_Interval(OPERATING_TIME);
  698. // 统计数据默认值
  699. let statData = {
  700. uuid: get_uuid(), // 设备标识
  701. ak: stat_config.appid, // uni-app 应用 Appid
  702. p: sys.platform === 'android' ? 'a' : 'i', // 手机系统
  703. ut: get_platform_name(), // 平台类型
  704. mpn: get_pack_name(), // 原生平台包名、小程序 appid
  705. usv: STAT_VERSION, // 统计 sdk 版本
  706. v: get_version(), // 应用版本,仅app
  707. ch: get_channel(), // 渠道信息
  708. cn: '', // 国家
  709. pn: '', // 省份
  710. ct: '', // 城市
  711. t: get_time(), // 上报数据时的时间戳
  712. tt: '',
  713. brand: sys.brand || '', // 手机品牌
  714. md: sys.model, // 手机型号
  715. sv: sys.system.replace(/(Android|iOS)\s/, ''), // 手机系统版本
  716. mpsdk: sys.SDKVersion || '', // x程序 sdk version
  717. mpv: sys.version || '', // 小程序平台版本 ,如微信、支付宝
  718. lang: sys.language, // 语言
  719. pr: sys.pixelRatio, // pixelRatio 设备像素比
  720. ww: sys.windowWidth, // windowWidth 可使用窗口宽度
  721. wh: sys.windowHeight, // windowHeight 可使用窗口高度
  722. sw: sys.screenWidth, // screenWidth 屏幕宽度
  723. sh: sys.screenHeight, // screenHeight 屏幕高度
  724. };
  725. class Report {
  726. constructor() {
  727. // 页面实例
  728. this.self = '';
  729. // 进入应用标识
  730. this.__licationShow = false;
  731. // 离开应用标识
  732. this.__licationHide = false;
  733. // 统计默认值
  734. this.statData = statData;
  735. // 标题默认值
  736. this._navigationBarTitle = {
  737. config: '',
  738. page: '',
  739. report: '',
  740. lt: '',
  741. };
  742. // 页面参数
  743. this._query = {};
  744. // 页面最后停留页面的 url
  745. // this._lastPageRoute = ''
  746. // 注册拦截器
  747. let registerInterceptor = typeof uni.addInterceptor === 'function';
  748. if (registerInterceptor) {
  749. this.addInterceptorInit();
  750. this.interceptLogin();
  751. this.interceptShare(true);
  752. this.interceptRequestPayment();
  753. }
  754. }
  755. addInterceptorInit() {
  756. let self = this;
  757. uni.addInterceptor('setNavigationBarTitle', {
  758. invoke(args) {
  759. self._navigationBarTitle.page = args.title;
  760. },
  761. });
  762. }
  763. interceptLogin() {
  764. let self = this;
  765. uni.addInterceptor('login', {
  766. complete() {
  767. self._login();
  768. },
  769. });
  770. }
  771. interceptShare(type) {
  772. let self = this;
  773. if (!type) {
  774. self._share();
  775. return
  776. }
  777. uni.addInterceptor('share', {
  778. success() {
  779. self._share();
  780. },
  781. fail() {
  782. self._share();
  783. },
  784. });
  785. }
  786. interceptRequestPayment() {
  787. let self = this;
  788. uni.addInterceptor('requestPayment', {
  789. success() {
  790. self._payment('pay_success');
  791. },
  792. fail() {
  793. self._payment('pay_fail');
  794. },
  795. });
  796. }
  797. _login() {
  798. this.sendEventRequest(
  799. {
  800. key: 'login',
  801. },
  802. 0
  803. );
  804. }
  805. _share() {
  806. this.sendEventRequest(
  807. {
  808. key: 'share',
  809. },
  810. 0
  811. );
  812. }
  813. _payment(key) {
  814. this.sendEventRequest(
  815. {
  816. key,
  817. },
  818. 0
  819. );
  820. }
  821. /**
  822. * 进入应用触发
  823. */
  824. applicationShow() {
  825. // 通过 __licationHide 判断保证是进入后台后在次进入应用,避免重复上报数据
  826. if (this.__licationHide) {
  827. const time = get_residence_time('app');
  828. // 需要判断进入后台是否超过时限 ,默认是 30min ,是的话需要执行进入应用的上报
  829. if (time.overtime) {
  830. let lastPageRoute = uni.getStorageSync('_STAT_LAST_PAGE_ROUTE');
  831. let options = {
  832. path: lastPageRoute,
  833. scene: this.statData.sc,
  834. cst: 2,
  835. };
  836. this.sendReportRequest(options);
  837. }
  838. // 状态重置
  839. this.__licationHide = false;
  840. }
  841. }
  842. /**
  843. * 离开应用触发
  844. * @param {Object} self
  845. * @param {Object} type
  846. */
  847. applicationHide(self, type) {
  848. if (!self) {
  849. // 表示应用切换到后台 ,此时需要从页面栈获取页面实例
  850. self = get_page_vm();
  851. }
  852. // 进入应用后台保存状态,方便进入前台后判断是否上报应用数据
  853. this.__licationHide = true;
  854. const time = get_residence_time();
  855. const route = get_page_route(self);
  856. uni.setStorageSync('_STAT_LAST_PAGE_ROUTE', route);
  857. this.sendHideRequest(
  858. {
  859. urlref: route,
  860. urlref_ts: time.residenceTime,
  861. },
  862. type
  863. );
  864. // 更新页面首次访问时间
  865. set_first_time();
  866. }
  867. /**
  868. * 进入页面触发
  869. */
  870. pageShow(self) {
  871. // 清空值 ,初始化 ,避免污染后面的上报数据
  872. this._navigationBarTitle = {
  873. config: '',
  874. page: '',
  875. report: '',
  876. lt: '',
  877. };
  878. const route = get_page_route(self);
  879. const routepath = get_route$1(self);
  880. this._navigationBarTitle.config = get_page_name(routepath);
  881. // 表示应用触发 ,页面切换不触发之后的逻辑
  882. if (this.__licationShow) {
  883. // 更新页面首次访问时间
  884. set_first_time();
  885. // this._lastPageRoute = route
  886. uni.setStorageSync('_STAT_LAST_PAGE_ROUTE', route);
  887. this.__licationShow = false;
  888. return
  889. }
  890. const time = get_residence_time('page');
  891. // 停留时间
  892. if (time.overtime) {
  893. let options = {
  894. path: route,
  895. scene: this.statData.sc,
  896. cst: 3,
  897. };
  898. this.sendReportRequest(options);
  899. }
  900. // 更新页面首次访问时间
  901. set_first_time();
  902. }
  903. /**
  904. * 离开页面触发
  905. */
  906. pageHide(self) {
  907. if (!this.__licationHide) {
  908. const time = get_residence_time('page');
  909. let route = get_page_route(self);
  910. let lastPageRoute = uni.getStorageSync('_STAT_LAST_PAGE_ROUTE');
  911. if (!lastPageRoute) {
  912. lastPageRoute = route;
  913. }
  914. uni.setStorageSync('_STAT_LAST_PAGE_ROUTE', route);
  915. this.sendPageRequest({
  916. url: route,
  917. urlref: lastPageRoute,
  918. urlref_ts: time.residenceTime,
  919. });
  920. // this._lastPageRoute = route
  921. return
  922. }
  923. }
  924. /**
  925. * 发送请求,应用维度上报
  926. * @param {Object} options 页面信息
  927. * @param {Boolean} type 是否立即上报
  928. */
  929. sendReportRequest(options, type) {
  930. this._navigationBarTitle.lt = '1';
  931. this._navigationBarTitle.config = get_page_name(options.path);
  932. let is_opt = options.query && JSON.stringify(options.query) !== '{}';
  933. let query = is_opt ? '?' + JSON.stringify(options.query) : '';
  934. const last_time = get_last_visit_time();
  935. // 非老用户
  936. if(last_time !== 0 || !last_time){
  937. const odid = get_odid();
  938. // 2.0 处理规则
  939. {
  940. const have_device = is_handle_device();
  941. // 如果没有上报过设备信息 ,则需要上报设备信息
  942. if(!have_device) {
  943. this.statData.odid = odid;
  944. }
  945. }
  946. }
  947. Object.assign(this.statData, {
  948. lt: '1',
  949. url: options.path + query || '',
  950. t: get_time(),
  951. sc: get_scene(options.scene),
  952. fvts: get_first_visit_time(),
  953. lvts: last_time,
  954. tvc: get_total_visit_count(),
  955. // create session type 上报类型 ,1 应用进入 2.后台30min进入 3.页面30min进入
  956. cst: options.cst || 1,
  957. });
  958. if (get_platform_name() === 'n') {
  959. this.getProperty(type);
  960. } else {
  961. this.getNetworkInfo(type);
  962. }
  963. }
  964. /**
  965. * 发送请求,页面维度上报
  966. * @param {Object} opt
  967. */
  968. sendPageRequest(opt) {
  969. let { url, urlref, urlref_ts } = opt;
  970. this._navigationBarTitle.lt = '11';
  971. let options = {
  972. ak: this.statData.ak,
  973. uuid: this.statData.uuid,
  974. p: this.statData.p,
  975. lt: '11',
  976. ut: this.statData.ut,
  977. url,
  978. tt: this.statData.tt,
  979. urlref,
  980. urlref_ts,
  981. ch: this.statData.ch,
  982. usv: this.statData.usv,
  983. t: get_time(),
  984. };
  985. this.request(options);
  986. }
  987. /**
  988. * 进入后台上报数据
  989. * @param {Object} opt
  990. * @param {Object} type
  991. */
  992. sendHideRequest(opt, type) {
  993. let { urlref, urlref_ts } = opt;
  994. let options = {
  995. ak: this.statData.ak,
  996. uuid: this.statData.uuid,
  997. p: this.statData.p,
  998. lt: '3',
  999. ut: this.statData.ut,
  1000. urlref,
  1001. urlref_ts,
  1002. ch: this.statData.ch,
  1003. usv: this.statData.usv,
  1004. t: get_time(),
  1005. };
  1006. this.request(options, type);
  1007. }
  1008. /**
  1009. * 自定义事件上报
  1010. */
  1011. sendEventRequest({ key = '', value = '' } = {}) {
  1012. let routepath = '';
  1013. try {
  1014. routepath = get_route$1();
  1015. } catch (error) {
  1016. const launch_options = dbGet('__launch_options');
  1017. routepath = launch_options.path;
  1018. }
  1019. this._navigationBarTitle.config = get_page_name(routepath);
  1020. this._navigationBarTitle.lt = '21';
  1021. let options = {
  1022. ak: this.statData.ak,
  1023. uuid: this.statData.uuid,
  1024. p: this.statData.p,
  1025. lt: '21',
  1026. ut: this.statData.ut,
  1027. url: routepath,
  1028. ch: this.statData.ch,
  1029. e_n: key,
  1030. e_v: typeof value === 'object' ? JSON.stringify(value) : value.toString(),
  1031. usv: this.statData.usv,
  1032. t: get_time(),
  1033. };
  1034. this.request(options);
  1035. }
  1036. sendPushRequest(options, cid) {
  1037. let time = get_time();
  1038. const statData = {
  1039. lt: '101',
  1040. cid: cid,
  1041. t: time,
  1042. ut: this.statData.ut,
  1043. };
  1044. // debug 打印打点信息
  1045. if (is_debug) {
  1046. log(statData);
  1047. }
  1048. const stat_data = handle_data({
  1049. 101: [statData],
  1050. });
  1051. let optionsData = {
  1052. usv: STAT_VERSION, //统计 SDK 版本号
  1053. t: time, //发送请求时的时间戮
  1054. requests: stat_data,
  1055. };
  1056. // XXX 安卓需要延迟上报 ,否则会有未知错误,需要验证处理
  1057. if (get_platform_name() === 'n' && this.statData.p === 'a') {
  1058. setTimeout(() => {
  1059. this.sendRequest(optionsData);
  1060. }, 200);
  1061. return
  1062. }
  1063. this.sendRequest(optionsData);
  1064. }
  1065. /**
  1066. * 获取wgt资源版本
  1067. */
  1068. getProperty(type) {
  1069. plus.runtime.getProperty(plus.runtime.appid, (wgtinfo) => {
  1070. this.statData.v = wgtinfo.version || '';
  1071. this.getNetworkInfo(type);
  1072. });
  1073. }
  1074. /**
  1075. * 获取网络信息
  1076. */
  1077. getNetworkInfo(type) {
  1078. uni.getNetworkType({
  1079. success: (result) => {
  1080. this.statData.net = result.networkType;
  1081. this.getLocation(type);
  1082. },
  1083. });
  1084. }
  1085. /**
  1086. * 获取位置信息
  1087. */
  1088. getLocation(type) {
  1089. if (stat_config.getLocation) {
  1090. uni.getLocation({
  1091. type: 'wgs84',
  1092. geocode: true,
  1093. success: (result) => {
  1094. if (result.address) {
  1095. this.statData.cn = result.address.country;
  1096. this.statData.pn = result.address.province;
  1097. this.statData.ct = result.address.city;
  1098. }
  1099. this.statData.lat = result.latitude;
  1100. this.statData.lng = result.longitude;
  1101. this.request(this.statData, type);
  1102. },
  1103. });
  1104. } else {
  1105. this.statData.lat = 0;
  1106. this.statData.lng = 0;
  1107. this.request(this.statData, type);
  1108. }
  1109. }
  1110. /**
  1111. * 发送请求
  1112. * @param {Object} data 上报数据
  1113. * @param {Object} type 类型
  1114. */
  1115. request(data, type) {
  1116. let time = get_time();
  1117. const title = this._navigationBarTitle;
  1118. Object.assign(data, {
  1119. ttn: title.page,
  1120. ttpj: title.config,
  1121. ttc: title.report,
  1122. });
  1123. let uniStatData = dbGet('__UNI__STAT__DATA') || {};
  1124. if (!uniStatData[data.lt]) {
  1125. uniStatData[data.lt] = [];
  1126. }
  1127. // 加入队列
  1128. uniStatData[data.lt].push(data);
  1129. dbSet('__UNI__STAT__DATA', uniStatData);
  1130. let page_residence_time = get_page_residence_time();
  1131. // debug 打印打点信息
  1132. if (is_debug) {
  1133. log(data);
  1134. }
  1135. // 判断时候到达上报时间 ,默认 10 秒上报
  1136. if (page_residence_time < eport_Interval && !type) return
  1137. // 时间超过,重新获取时间戳
  1138. set_page_residence_time();
  1139. const stat_data = handle_data(uniStatData);
  1140. let optionsData = {
  1141. usv: STAT_VERSION, //统计 SDK 版本号
  1142. t: time, //发送请求时的时间戮
  1143. requests: stat_data,
  1144. };
  1145. // 重置队列
  1146. dbRemove('__UNI__STAT__DATA');
  1147. // XXX 安卓需要延迟上报 ,否则会有未知错误,需要验证处理
  1148. if (get_platform_name() === 'n' && this.statData.p === 'a') {
  1149. setTimeout(() => {
  1150. this.sendRequest(optionsData);
  1151. }, 200);
  1152. return
  1153. }
  1154. this.sendRequest(optionsData);
  1155. }
  1156. getIsReportData() {
  1157. return is_report_data()
  1158. }
  1159. /**
  1160. * 数据上报
  1161. * @param {Object} optionsData 需要上报的数据
  1162. */
  1163. sendRequest(optionsData) {
  1164. {
  1165. if (!uni.__stat_uniCloud_space) {
  1166. console.error(
  1167. '应用未关联服务空间,统计上报失败,请在uniCloud目录右键关联服务空间.'
  1168. );
  1169. return
  1170. }
  1171. const uniCloudObj = uni.__stat_uniCloud_space.importObject(
  1172. 'uni-stat-receiver',
  1173. {
  1174. customUI: true,
  1175. }
  1176. );
  1177. uniCloudObj
  1178. .report(optionsData)
  1179. .then(() => {
  1180. if (is_debug) {
  1181. log(optionsData, true);
  1182. }
  1183. })
  1184. .catch((err) => {
  1185. if (is_debug) {
  1186. console.warn('=== 统计上报错误');
  1187. console.error(err);
  1188. }
  1189. });
  1190. }
  1191. }
  1192. /**
  1193. * h5 请求
  1194. */
  1195. imageRequest(data) {
  1196. this.getIsReportData().then(() => {
  1197. let image = new Image();
  1198. let options = get_sgin(get_encodeURIComponent_options(data)).options;
  1199. image.src = STAT_H5_URL + '?' + options;
  1200. if (is_debug) {
  1201. log(data, true);
  1202. }
  1203. });
  1204. }
  1205. sendEvent(key, value) {
  1206. // 校验 type 参数
  1207. if (calibration(key, value)) return
  1208. if (key === 'title') {
  1209. this._navigationBarTitle.report = value;
  1210. return
  1211. }
  1212. this.sendEventRequest(
  1213. {
  1214. key,
  1215. value: typeof value === 'object' ? JSON.stringify(value) : value,
  1216. },
  1217. 1
  1218. );
  1219. }
  1220. }
  1221. class Stat extends Report {
  1222. static getInstance() {
  1223. if (!uni.__stat_instance) {
  1224. uni.__stat_instance = new Stat();
  1225. }
  1226. // 2.0 init 服务空间
  1227. {
  1228. let space = get_space(uniCloud.config);
  1229. if (!uni.__stat_uniCloud_space) {
  1230. // 判断不为空对象
  1231. if (space && Object.keys(space).length !== 0) {
  1232. let spaceData = {
  1233. provider: space.provider,
  1234. spaceId: space.spaceId,
  1235. clientSecret: space.clientSecret,
  1236. };
  1237. if (space.endpoint) {
  1238. spaceData.endpoint = space.endpoint;
  1239. }
  1240. if(space.provider === 'alipay'){
  1241. spaceData.secretKey = space.secretKey;
  1242. spaceData.accessKey = space.accessKey || space.secretId;
  1243. spaceData.spaceAppId = space.spaceAppId || space.appId;
  1244. }
  1245. uni.__stat_uniCloud_space = uniCloud.init(spaceData);
  1246. // console.log(
  1247. // '=== 当前绑定的统计服务空间spaceId:' +
  1248. // uni.__stat_uniCloud_space.config.spaceId
  1249. // )
  1250. } else {
  1251. console.error('应用未关联服务空间,请在uniCloud目录右键关联服务空间');
  1252. }
  1253. }
  1254. }
  1255. return uni.__stat_instance
  1256. }
  1257. constructor() {
  1258. super();
  1259. }
  1260. /**
  1261. * 获取推送id
  1262. */
  1263. pushEvent(options) {
  1264. const ClientID = is_push_clientid();
  1265. if (uni.getPushClientId && ClientID) {
  1266. uni.getPushClientId({
  1267. success: (res) => {
  1268. const cid = res.cid || false;
  1269. // 只有获取到才会上传
  1270. if (cid) {
  1271. this.sendPushRequest(options, cid);
  1272. }
  1273. },
  1274. });
  1275. }
  1276. }
  1277. /**
  1278. * 进入应用
  1279. * @param {Object} options 页面参数
  1280. * @param {Object} self 当前页面实例
  1281. */
  1282. launch(options, self) {
  1283. // 初始化页面停留时间 start
  1284. set_page_residence_time();
  1285. this.__licationShow = true;
  1286. dbSet('__launch_options', options);
  1287. // 应用初始上报参数为1
  1288. options.cst = 1;
  1289. this.sendReportRequest(options, true);
  1290. }
  1291. load(options, self) {
  1292. this.self = self;
  1293. this._query = options;
  1294. }
  1295. appHide(self) {
  1296. this.applicationHide(self, true);
  1297. }
  1298. appShow(self) {
  1299. this.applicationShow(self);
  1300. }
  1301. show(self) {
  1302. this.self = self;
  1303. if (get_page_types(self) === 'page') {
  1304. const isPageReport = is_page_report();
  1305. if (isPageReport) {
  1306. this.pageShow(self);
  1307. }
  1308. }
  1309. // #ifdef VUE3
  1310. if (get_platform_name() === 'h5' || get_platform_name() === 'n') {
  1311. if (get_page_types(self) === 'app') {
  1312. this.appShow();
  1313. }
  1314. }
  1315. // #endif
  1316. // #ifndef VUE3
  1317. if (get_page_types(self) === 'app') {
  1318. this.appShow();
  1319. }
  1320. // #endif
  1321. }
  1322. hide(self) {
  1323. this.self = self;
  1324. if (get_page_types(self) === 'page') {
  1325. const isPageReport = is_page_report();
  1326. if (isPageReport) {
  1327. this.pageHide(self);
  1328. }
  1329. }
  1330. // #ifdef VUE3
  1331. if (get_platform_name() === 'h5' || get_platform_name() === 'n') {
  1332. if (get_page_types(self) === 'app') {
  1333. this.appHide();
  1334. }
  1335. }
  1336. // #endif
  1337. // #ifndef VUE3
  1338. if (get_page_types(self) === 'app') {
  1339. this.appHide();
  1340. }
  1341. // #endif
  1342. }
  1343. error(em) {
  1344. // 开发工具内不上报错误
  1345. // if (this._platform === 'devtools') {
  1346. // if (process.env.NODE_ENV === 'development') {
  1347. // console.info('当前运行环境为开发者工具,不上报数据。')
  1348. // return
  1349. // }
  1350. // }
  1351. let emVal = '';
  1352. if (!em.message) {
  1353. emVal = JSON.stringify(em);
  1354. } else {
  1355. emVal = em.stack;
  1356. }
  1357. let route = '';
  1358. try {
  1359. route = get_route();
  1360. } catch (e) {
  1361. // 未获取到页面路径
  1362. route = '';
  1363. }
  1364. let options = {
  1365. ak: this.statData.ak,
  1366. uuid: this.statData.uuid,
  1367. p: this.statData.p,
  1368. lt: '31',
  1369. url: route,
  1370. ut: this.statData.ut,
  1371. ch: this.statData.ch,
  1372. mpsdk: this.statData.mpsdk,
  1373. mpv: this.statData.mpv,
  1374. v: this.statData.v,
  1375. em: emVal,
  1376. usv: this.statData.usv,
  1377. t: parseInt(new Date().getTime() / 1000),
  1378. };
  1379. this.request(options);
  1380. }
  1381. }
  1382. var Stat$1 = Stat;
  1383. const stat = Stat$1.getInstance();
  1384. // 用于判断是隐藏页面还是卸载页面
  1385. let isHide = false;
  1386. const lifecycle = {
  1387. onLaunch(options) {
  1388. // 进入应用上报数据
  1389. stat.launch(options, this);
  1390. // 上报push推送id
  1391. stat.pushEvent(options);
  1392. },
  1393. onLoad(options) {
  1394. stat.load(options, this);
  1395. // 重写分享,获取分享上报事件
  1396. if (this.$scope && this.$scope.onShareAppMessage) {
  1397. let oldShareAppMessage = this.$scope.onShareAppMessage;
  1398. this.$scope.onShareAppMessage = function (options) {
  1399. stat.interceptShare(false);
  1400. return oldShareAppMessage.call(this, options)
  1401. };
  1402. }
  1403. },
  1404. onShow() {
  1405. isHide = false;
  1406. stat.show(this);
  1407. },
  1408. onHide() {
  1409. isHide = true;
  1410. stat.hide(this);
  1411. },
  1412. onUnload() {
  1413. if (isHide) {
  1414. isHide = false;
  1415. return
  1416. }
  1417. stat.hide(this);
  1418. },
  1419. onError(e) {
  1420. stat.error(e);
  1421. },
  1422. };
  1423. // 加载统计代码
  1424. function load_stat() {
  1425. // #ifdef VUE3
  1426. uni.onCreateVueApp((app) => {
  1427. app.mixin(lifecycle);
  1428. uni.report = function (type, options) {
  1429. stat.sendEvent(type, options);
  1430. };
  1431. });
  1432. if (get_platform_name() !== 'h5' && get_platform_name() !== 'n') {
  1433. uni.onAppHide(() => {
  1434. stat.appHide(get_page_vm());
  1435. });
  1436. uni.onAppShow(() => {
  1437. stat.appShow(get_page_vm());
  1438. });
  1439. }
  1440. // #endif
  1441. // #ifndef VUE3
  1442. // eslint-disable-next-line no-restricted-globals
  1443. const Vue = require('vue')
  1444. ;(Vue.default || Vue).mixin(lifecycle);
  1445. uni.report = function (type, options) {
  1446. stat.sendEvent(type, options);
  1447. };
  1448. // #endif
  1449. }
  1450. function main() {
  1451. if (is_debug) {
  1452. {
  1453. // #ifndef APP-NVUE
  1454. console.log('=== uni统计开启,version:2.0 ===');
  1455. // #endif
  1456. }
  1457. load_stat();
  1458. } else {
  1459. if (process.env.NODE_ENV === 'development') {
  1460. uni.report = function (type, options) {};
  1461. } else {
  1462. load_stat();
  1463. }
  1464. }
  1465. }
  1466. main();