uni-stat.es.js 35 KB

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