uni-cloud-stat.es.js 37 KB

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