| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545 |
- /**
- * 获取系统信息
- */
- const sys = uni.getSystemInfoSync();
- // 访问开始即启动小程序,访问结束结分为:进入后台超过5min、在前台无任何操作超过30min、在新的来源打开小程序;
- const STAT_VERSION = process.env.UNI_COMPILER_VERSION;
- const STAT_URL = 'https://tongji.dcloud.io/uni/stat';
- const STAT_H5_URL = 'https://tongji.dcloud.io/uni/stat.gif';
- const PAGE_PVER_TIME = 1800; // 页面在前台无操作结束访问时间 单位s
- const APP_PVER_TIME = 300; // 应用在后台结束访问时间 单位s
- const OPERATING_TIME = 10; // 数据上报时间 单位s
- const DIFF_TIME = 60 * 1000 * 60 * 24;
- const appid = process.env.UNI_APP_ID; // 做应用隔离
- const dbSet = (name, value) => {
- let data = uni.getStorageSync('$$STAT__DBDATA:'+appid) || {};
- if (!data) {
- data = {};
- }
- data[name] = value;
- uni.setStorageSync('$$STAT__DBDATA:'+appid, data);
- };
- const dbGet = (name) => {
- let data = uni.getStorageSync('$$STAT__DBDATA:'+appid) || {};
- if (!data[name]) {
- let dbdata = uni.getStorageSync('$$STAT__DBDATA:'+appid);
- if (!dbdata) {
- dbdata = {};
- }
- if (!dbdata[name]) {
- return undefined
- }
- data[name] = dbdata[name];
- }
- return data[name]
- };
- const dbRemove = (name) => {
- let data = uni.getStorageSync('$$STAT__DBDATA:'+appid) || {};
- if (data[name]) {
- delete data[name];
- uni.setStorageSync('$$STAT__DBDATA:'+appid, data);
- } else {
- data = uni.getStorageSync('$$STAT__DBDATA:'+appid);
- if (data[name]) {
- delete data[name];
- uni.setStorageSync('$$STAT__DBDATA:'+appid, data);
- }
- }
- };
- // 获取 manifest.json 中统计配置
- const uniStatisticsConfig = process.env.UNI_STATISTICS_CONFIG;
- let statConfig = {
- appid: process.env.UNI_APP_ID,
- };
- let titleJsons = {};
- let debug = !!process.env.UNI_STAT_DEBUG || false;
- // #ifdef VUE3
- titleJsons = process.env.UNI_STAT_TITLE_JSON;
- // #endif
- // #ifndef VUE3
- // eslint-disable-next-line no-restricted-globals
- const pagesTitle = require('uni-pages?{"type":"style"}').default;
- let pagesData = pagesTitle.pages;
- for (let i in pagesData) {
- const style = pagesData[i];
- const titleText =
- // MP
- style.navigationBarTitleText ||
- // ali
- style.defaultTitle ||
- // H5 || App
- style.navigationBar?.titleText ||
- '';
- if (titleText) {
- titleJsons[i] = titleText;
- }
- }
- // #endif
- // TODO 在云函数中获取,暂时注释
- const UUID_KEY = '__DC_STAT_UUID';
- const UUID_VALUE = '__DC_UUID_VALUE';
- function getUuid() {
- let uuid = '';
- if (get_platform_name() === 'n') {
- try {
- uuid = plus.runtime.getDCloudId();
- } catch (e) {
- uuid = '';
- }
- return uuid
- }
- try {
- uuid = uni.getStorageSync(UUID_KEY);
- } catch (e) {
- uuid = UUID_VALUE;
- }
- if (!uuid) {
- uuid = Date.now() + '' + Math.floor(Math.random() * 1e7);
- try {
- uni.setStorageSync(UUID_KEY, uuid);
- } catch (e) {
- uni.setStorageSync(UUID_KEY, UUID_VALUE);
- }
- }
- return uuid
- }
- const get_uuid = (statData) => {
- // 有可能不存在 deviceId(一般不存在就是出bug了),就自己生成一个
- return sys.deviceId || getUuid()
- };
- /**
- * 获取老版的 deviceid ,兼容以前的错误 deviceid
- * @param {*} statData
- * @returns
- */
- const get_odid = (statData) => {
- let odid = '';
- if (get_platform_name() === 'n') {
- try {
- odid = plus.device.uuid;
- } catch (e) {
- odid = '';
- }
- return odid
- }
- return sys.deviceId || getUuid()
- };
- /**
- * 获取配置信息 如 appid
- */
- const stat_config = statConfig;
- const get_sgin = (statData) => {
- let arr = Object.keys(statData);
- let sortArr = arr.sort();
- let sgin = {};
- let sginStr = '';
- for (var i in sortArr) {
- sgin[sortArr[i]] = statData[sortArr[i]];
- sginStr += sortArr[i] + '=' + statData[sortArr[i]] + '&';
- }
- return {
- sign: '',
- options: sginStr.substr(0, sginStr.length - 1),
- }
- };
- const get_encodeURIComponent_options = (statData) => {
- let data = {};
- for (let prop in statData) {
- data[prop] = encodeURIComponent(statData[prop]);
- }
- return data
- };
- /**
- * 获取当前平台
- * 移动端 : 'n',
- * h5 : 'h5',
- * 微信 : 'wx',
- * 阿里 : 'ali',
- * 百度 : 'bd',
- * 头条 : 'tt',
- * qq : 'qq',
- * 快应用 : 'qn',
- * 快手 : 'ks',
- * 飞书 : 'lark',
- * 快应用 : 'qw',
- * 钉钉 : 'dt'
- */
- const get_platform_name = () => {
- // 苹果审核代码中禁止出现 alipay 字样 ,需要特殊处理一下
- const aliArr = ['y', 'a', 'p', 'mp-ali'];
- const platformList = {
- app: 'n',
- 'app-plus': 'n',
- h5: 'h5',
- 'mp-weixin': 'wx',
- [aliArr.reverse().join('')]: 'ali',
- 'mp-baidu': 'bd',
- 'mp-toutiao': 'tt',
- 'mp-qq': 'qq',
- 'quickapp-native': 'qn',
- 'mp-kuaishou': 'ks',
- 'mp-lark': 'lark',
- 'quickapp-webview': 'qw',
- };
- if (platformList[process.env.VUE_APP_PLATFORM] === 'ali') {
- if (my && my.env) {
- const clientName = my.env.clientName;
- if (clientName === 'ap') return 'ali'
- if (clientName === 'dingtalk') return 'dt'
- // TODO 缺少 ali 下的其他平台
- }
- }
- return platformList[process.env.VUE_APP_PLATFORM]
- };
- /**
- * 获取小程序 appid
- */
- const get_pack_name = () => {
- let packName = '';
- if (get_platform_name() === 'wx' || get_platform_name() === 'qq') {
- // 兼容微信小程序低版本基础库
- if (uni.canIUse('getAccountInfoSync')) {
- packName = uni.getAccountInfoSync().miniProgram.appId || '';
- }
- }
- if (get_platform_name() === 'n') ;
- return packName
- };
- /**
- * 应用版本
- */
- const get_version = () => {
- return get_platform_name() === 'n' ? plus.runtime.version : ''
- };
- /**
- * 获取渠道
- */
- const get_channel = () => {
- const platformName = get_platform_name();
- let channel = '';
- if (platformName === 'n') {
- channel = plus.runtime.channel;
- }
- return channel
- };
- /**
- * 获取小程序场景值
- * @param {Object} options 页面信息
- */
- const get_scene = (options) => {
- const platformName = get_platform_name();
- let scene = '';
- if (options) {
- return options
- }
- if (platformName === 'wx') {
- scene = uni.getLaunchOptionsSync().scene;
- }
- return scene
- };
- /**
- * 获取拼接参数
- */
- const get_splicing = (data) => {
- let str = '';
- for (var i in data) {
- str += i + '=' + data[i] + '&';
- }
- return str.substr(0, str.length - 1)
- };
- /**
- * 获取页面url,不包含参数
- */
- const get_route$1 = (pageVm) => {
- let _self = pageVm || get_page_vm();
- if (get_platform_name() === 'bd') {
- let mp_route = _self.$mp && _self.$mp.page && _self.$mp.page.is;
- let scope_route = _self.$scope && _self.$scope.is;
- return mp_route || scope_route || ''
- } else {
- return (
- _self.route ||
- (_self.$scope && _self.$scope.route) ||
- (_self.$mp && _self.$mp.page.route)
- )
- }
- };
- /**
- * 获取页面url, 包含参数
- */
- const get_page_route = (pageVm) => {
- // 从 app 进入应用 ,没有 $page ,获取不到路由 ,需要获取页面 尝试从 getCurrentPages 获取也页面实例
- // FIXME 尽量不使用 getCurrentPages ,大部分获取路由是从 onHide 获取 ,这时可以获取到,如果是 onload ,则可能获取不到,比如 百度
- let page = pageVm && (pageVm.$page || (pageVm.$scope && pageVm.$scope.$page));
- let lastPageRoute = uni.getStorageSync('_STAT_LAST_PAGE_ROUTE');
- if (!page) return lastPageRoute || ''
- // 如果找不到 fullPath 就取 route 的值
- return page.fullPath === '/' ? page.route : page.fullPath || page.route
- };
- /**
- * 获取页面实例
- */
- const get_page_vm = () => {
- let pages = getCurrentPages();
- let $page = pages[pages.length - 1];
- if (!$page) return null
- return $page.$vm
- };
- /**
- * 获取页面类型
- */
- const get_page_types = (self) => {
- // XXX 百度有问题 ,获取的都是 componet ,等待修复
- if (
- self.mpType === 'page' ||
- self.$mpType === 'page' ||
- (self.$mp && self.$mp.mpType === 'page') ||
- self.$options.mpType === 'page'
- ) {
- return 'page'
- }
- if (
- self.mpType === 'app' ||
- self.$mpType === 'app' ||
- (self.$mp && self.$mp.mpType === 'app') ||
- self.$options.mpType === 'app'
- ) {
- return 'app'
- }
- return null
- };
- /**
- * 处理上报参数
- * @param {Object} 需要处理的数据
- */
- const handle_data = (statData) => {
- let firstArr = [];
- let contentArr = [];
- let lastArr = [];
- for (let i in statData) {
- const rd = statData[i];
- rd.forEach((elm) => {
- let newData = '';
- {
- newData = get_splicing(elm);
- }
- if (i === 0) {
- firstArr.push(newData);
- } else if (i === 3) {
- lastArr.push(newData);
- } else {
- contentArr.push(newData);
- }
- });
- }
- firstArr.push(...contentArr, ...lastArr);
- // 参数需要处理成字符串,方便上传
- return JSON.stringify(firstArr)
- };
- /**
- * 自定义事件参数校验
- */
- const calibration = (eventName, options) => {
- // login 、 share 、pay_success 、pay_fail 、register 、title
- if (!eventName) {
- console.error(`uni.report Missing [eventName] parameter`);
- return true
- }
- if (typeof eventName !== 'string') {
- console.error(
- `uni.report [eventName] Parameter type error, it can only be of type String`
- );
- return true
- }
- if (eventName.length > 255) {
- console.error(
- `uni.report [eventName] Parameter length cannot be greater than 255`
- );
- return true
- }
- if (typeof options !== 'string' && typeof options !== 'object') {
- console.error(
- 'uni.report [options] Parameter type error, Only supports String or Object type'
- );
- return true
- }
- if (typeof options === 'string' && options.length > 255) {
- console.error(
- `uni.report [options] Parameter length cannot be greater than 255`
- );
- return true
- }
- if (eventName === 'title' && typeof options !== 'string') {
- console.error(
- `uni.report [eventName] When the parameter is title, the [options] parameter can only be of type String`
- );
- return true
- }
- };
- const get_page_name = (routepath) => {
- return (titleJsons && titleJsons[routepath]) || ''
- };
- const Report_Data_Time = 'Report_Data_Time';
- const Report_Status = 'Report_Status';
- const is_report_data = () => {
- return new Promise((resolve, reject) => {
- let start_time = '';
- let end_time = new Date().getTime();
- let diff_time = DIFF_TIME;
- let report_status = 1;
- try {
- start_time = uni.getStorageSync(Report_Data_Time);
- report_status = uni.getStorageSync(Report_Status);
- } catch (e) {
- start_time = '';
- report_status = 1;
- }
- if (report_status === '') {
- requestData(({ enable }) => {
- uni.setStorageSync(Report_Data_Time, end_time);
- uni.setStorageSync(Report_Status, enable);
- if (enable === 1) {
- resolve();
- }
- });
- return
- }
- if (report_status === 1) {
- resolve();
- }
- if (!start_time) {
- uni.setStorageSync(Report_Data_Time, end_time);
- start_time = end_time;
- }
- if (end_time - start_time > diff_time) {
- requestData(({ enable }) => {
- uni.setStorageSync(Report_Data_Time, end_time);
- uni.setStorageSync(Report_Status, enable);
- });
- }
- })
- };
- const requestData = (done) => {
- const appid = process.env.UNI_APP_ID;
- let formData = {
- usv: STAT_VERSION,
- conf: JSON.stringify({
- ak: appid,
- }),
- };
- uni.request({
- url: STAT_URL,
- method: 'GET',
- data: formData,
- success: (res) => {
- const { data } = res;
- if (data.ret === 0) {
- typeof done === 'function' &&
- done({
- enable: data.enable,
- });
- }
- },
- fail: (e) => {
- let report_status_code = 1;
- try {
- report_status_code = uni.getStorageSync(Report_Status);
- } catch (e) {
- report_status_code = 1;
- }
- if (report_status_code === '') {
- report_status_code = 1;
- }
- typeof done === 'function' &&
- done({
- enable: report_status_code,
- });
- },
- });
- };
- /**
- * 是否开启 debug 模式
- */
- const is_debug = debug;
- /**
- * 日志输出
- * @param {*} data
- */
- const log = (data, type) => {
- let msg_type = '';
- switch (data.lt) {
- case '1':
- msg_type = '应用启动';
- break
- case '3':
- msg_type = '应用进入后台';
- break
- case '11':
- msg_type = '页面切换';
- break
- case '21':
- msg_type = '事件触发';
- break
- case '31':
- msg_type = '应用错误';
- break
- case '101':
- msg_type = 'PUSH';
- break
- }
- // #ifdef APP
- // 在 app 中,日志转为 字符串
- if (typeof data === 'object') {
- data = JSON.stringify(data);
- }
- // #endif
- if (type) {
- console.log(`=== 统计队列数据上报 ===`);
- console.log(data);
- console.log(`=== 上报结束 ===`);
- return
- }
- if (msg_type) {
- console.log(`=== 统计数据采集:${msg_type} ===`);
- console.log(data);
- console.log(`=== 采集结束 ===`);
- }
- };
- /**
- * 获取上报时间间隔
- * @param {*} defaultTime 默认上报间隔时间 单位s
- */
- const get_report_Interval = (defaultTime) => {
- let time = uniStatisticsConfig.reportInterval;
- // 如果上报时间配置为0 相当于立即上报
- if (Number(time) === 0) return 0
- time = time || defaultTime;
- let reg = /(^[1-9]\d*$)/;
- // 如果不是整数,则默认为上报间隔时间
- if (!reg.test(time)) return defaultTime
- return Number(time)
- };
- /**
- * 获取隐私协议配置
- */
- const is_push_clientid = () => {
- if (uniStatisticsConfig.collectItems) {
- const ClientID = uniStatisticsConfig.collectItems.uniPushClientID;
- return typeof ClientID === 'boolean' ? ClientID : false
- }
- return false
- };
- /**
- * 是否上报页面数据
- * @returns
- */
- const is_page_report = ()=>{
- if(uniStatisticsConfig.collectItems){
- const statPageLog = uniStatisticsConfig.collectItems.uniStatPageLog;
- // 如果字段不存在返回 true , 如果是boolean 值按原值返回,如果是其他类型 返回false
- if(statPageLog === undefined) return true
- return typeof statPageLog === 'boolean' ? statPageLog : true
- }
- return true
- };
- // 首次访问时间
- const FIRST_VISIT_TIME_KEY = '__first__visit__time';
- // 最后访问时间
- const LAST_VISIT_TIME_KEY = '__last__visit__time';
- /**
- * 获取当前时间
- */
- const get_time = () => {
- return parseInt(new Date().getTime() / 1000)
- };
- /**
- * 获取首次访问时间
- */
- const get_first_visit_time = () => {
- const timeStorge = dbGet(FIRST_VISIT_TIME_KEY);
- let time = 0;
- if (timeStorge) {
- time = timeStorge;
- } else {
- time = get_time();
- dbSet(FIRST_VISIT_TIME_KEY, time);
- // 首次访问需要 将最后访问时间置 0
- dbRemove(LAST_VISIT_TIME_KEY);
- }
- return time
- };
- /**
- * 最后访问时间
- */
- const get_last_visit_time = () => {
- const timeStorge = dbGet(LAST_VISIT_TIME_KEY);
- let time = 0;
- if (timeStorge) {
- time = timeStorge;
- }
- dbSet(LAST_VISIT_TIME_KEY, get_time());
- return time
- };
- // 页面停留时间记录key
- const PAGE_RESIDENCE_TIME = '__page__residence__time';
- let First_Page_Residence_Time = 0;
- let Last_Page_Residence_Time = 0;
- /**
- * 设置页面停留时间
- */
- const set_page_residence_time = () => {
- First_Page_Residence_Time = get_time();
- dbSet(PAGE_RESIDENCE_TIME, First_Page_Residence_Time);
- return First_Page_Residence_Time
- };
- /**
- * 获取页面停留时间
- */
- const get_page_residence_time = () => {
- Last_Page_Residence_Time = get_time();
- First_Page_Residence_Time = dbGet(PAGE_RESIDENCE_TIME);
- return Last_Page_Residence_Time - First_Page_Residence_Time
- };
- /**
- * 获取总访问次数
- */
- const TOTAL_VISIT_COUNT = '__total__visit__count';
- const get_total_visit_count = () => {
- const timeStorge = dbGet(TOTAL_VISIT_COUNT);
- let count = 1;
- if (timeStorge) {
- count = timeStorge;
- count++;
- }
- dbSet(TOTAL_VISIT_COUNT, count);
- return count
- };
- const FIRST_TIME = '__first_time';
- /**
- * 设置页面首次访问时间,用户获取页面/应用停留时常
- */
- const set_first_time = () => {
- // 获取当前时间 ,以下代码获取到是毫秒级时间戳 ,实际上用到是秒级时间戳,所以需要除以1000
- // const time = new Date().getTime()
- let time = get_time();
- const timeStorge = dbSet(FIRST_TIME,time);
- return timeStorge
- };
- /**
- * 获取最后一次时间 ,暂时用不到,直接获取当前时间即可
- */
- // export const get_last_time = () => {
- // let time = new Date().getTime()
- // Set__Last__Time = time
- // return time
- // }
- /**
- * 获取页面 \ 应用停留时间
- */
- const get_residence_time = (type) => {
- let residenceTime = 0;
- const first_time = dbGet(FIRST_TIME);
- const last_time = get_time();
- if (first_time !== 0) {
- residenceTime = last_time - first_time;
- }
- // 将毫秒级时间戳转换为秒级时间戳,因为直接获取的是秒级时间戳,所以不需要转换
- // residenceTime = parseInt(residenceTime / 1000)
- residenceTime = residenceTime < 1 ? 1 : residenceTime;
- if (type === 'app') {
- let overtime = residenceTime > APP_PVER_TIME ? true : false;
- return {
- residenceTime,
- overtime,
- }
- }
- if (type === 'page') {
- let overtime = residenceTime > PAGE_PVER_TIME ? true : false;
- return {
- residenceTime,
- overtime,
- }
- }
- return {
- residenceTime,
- }
- };
- const eport_Interval = get_report_Interval(OPERATING_TIME);
- // 统计数据默认值
- let statData = {
- uuid: get_uuid(), // 设备标识
- ak: stat_config.appid, // uni-app 应用 Appid
- p: sys.platform === 'android' ? 'a' : 'i', // 手机系统
- ut: get_platform_name(), // 平台类型
- mpn: get_pack_name(), // 原生平台包名、小程序 appid
- usv: STAT_VERSION, // 统计 sdk 版本
- v: get_version(), // 应用版本,仅app
- ch: get_channel(), // 渠道信息
- cn: '', // 国家
- pn: '', // 省份
- ct: '', // 城市
- t: get_time(), // 上报数据时的时间戳
- tt: '',
- brand: sys.brand || '', // 手机品牌
- md: sys.model, // 手机型号
- sv: sys.system.replace(/(Android|iOS)\s/, ''), // 手机系统版本
- mpsdk: sys.SDKVersion || '', // x程序 sdk version
- mpv: sys.version || '', // 小程序平台版本 ,如微信、支付宝
- lang: sys.language, // 语言
- pr: sys.pixelRatio, // pixelRatio 设备像素比
- ww: sys.windowWidth, // windowWidth 可使用窗口宽度
- wh: sys.windowHeight, // windowHeight 可使用窗口高度
- sw: sys.screenWidth, // screenWidth 屏幕宽度
- sh: sys.screenHeight, // screenHeight 屏幕高度
- };
- class Report {
- constructor() {
- // 页面实例
- this.self = '';
- // 进入应用标识
- this.__licationShow = false;
- // 离开应用标识
- this.__licationHide = false;
- // 统计默认值
- this.statData = statData;
- // 标题默认值
- this._navigationBarTitle = {
- config: '',
- page: '',
- report: '',
- lt: '',
- };
- // 页面参数
- this._query = {};
- // 页面最后停留页面的 url
- // this._lastPageRoute = ''
- // 注册拦截器
- let registerInterceptor = typeof uni.addInterceptor === 'function';
- if (registerInterceptor) {
- this.addInterceptorInit();
- this.interceptLogin();
- this.interceptShare(true);
- this.interceptRequestPayment();
- }
- }
- addInterceptorInit() {
- let self = this;
- uni.addInterceptor('setNavigationBarTitle', {
- invoke(args) {
- self._navigationBarTitle.page = args.title;
- },
- });
- }
- interceptLogin() {
- let self = this;
- uni.addInterceptor('login', {
- complete() {
- self._login();
- },
- });
- }
- interceptShare(type) {
- let self = this;
- if (!type) {
- self._share();
- return
- }
- uni.addInterceptor('share', {
- success() {
- self._share();
- },
- fail() {
- self._share();
- },
- });
- }
- interceptRequestPayment() {
- let self = this;
- uni.addInterceptor('requestPayment', {
- success() {
- self._payment('pay_success');
- },
- fail() {
- self._payment('pay_fail');
- },
- });
- }
- _login() {
- this.sendEventRequest(
- {
- key: 'login',
- },
- 0
- );
- }
- _share() {
- this.sendEventRequest(
- {
- key: 'share',
- },
- 0
- );
- }
- _payment(key) {
- this.sendEventRequest(
- {
- key,
- },
- 0
- );
- }
- /**
- * 进入应用触发
- */
- applicationShow() {
- // 通过 __licationHide 判断保证是进入后台后在次进入应用,避免重复上报数据
- if (this.__licationHide) {
- const time = get_residence_time('app');
- // 需要判断进入后台是否超过时限 ,默认是 30min ,是的话需要执行进入应用的上报
- if (time.overtime) {
- let lastPageRoute = uni.getStorageSync('_STAT_LAST_PAGE_ROUTE');
- let options = {
- path: lastPageRoute,
- scene: this.statData.sc,
- cst: 2,
- };
- this.sendReportRequest(options);
- }
- // 状态重置
- this.__licationHide = false;
- }
- }
- /**
- * 离开应用触发
- * @param {Object} self
- * @param {Object} type
- */
- applicationHide(self, type) {
- if (!self) {
- // 表示应用切换到后台 ,此时需要从页面栈获取页面实例
- self = get_page_vm();
- }
- // 进入应用后台保存状态,方便进入前台后判断是否上报应用数据
- this.__licationHide = true;
- const time = get_residence_time();
- const route = get_page_route(self);
- uni.setStorageSync('_STAT_LAST_PAGE_ROUTE', route);
- this.sendHideRequest(
- {
- urlref: route,
- urlref_ts: time.residenceTime,
- },
- type
- );
- // 更新页面首次访问时间
- set_first_time();
- }
- /**
- * 进入页面触发
- */
- pageShow(self) {
- // 清空值 ,初始化 ,避免污染后面的上报数据
- this._navigationBarTitle = {
- config: '',
- page: '',
- report: '',
- lt: '',
- };
- const route = get_page_route(self);
- const routepath = get_route$1(self);
- this._navigationBarTitle.config = get_page_name(routepath);
- // 表示应用触发 ,页面切换不触发之后的逻辑
- if (this.__licationShow) {
- // 更新页面首次访问时间
- set_first_time();
- // this._lastPageRoute = route
- uni.setStorageSync('_STAT_LAST_PAGE_ROUTE', route);
- this.__licationShow = false;
- return
- }
- const time = get_residence_time('page');
- // 停留时间
- if (time.overtime) {
- let options = {
- path: route,
- scene: this.statData.sc,
- cst: 3,
- };
- this.sendReportRequest(options);
- }
- // 更新页面首次访问时间
- set_first_time();
- }
- /**
- * 离开页面触发
- */
- pageHide(self) {
- if (!this.__licationHide) {
- const time = get_residence_time('page');
- let route = get_page_route(self);
- let lastPageRoute = uni.getStorageSync('_STAT_LAST_PAGE_ROUTE');
- if (!lastPageRoute) {
- lastPageRoute = route;
- }
- uni.setStorageSync('_STAT_LAST_PAGE_ROUTE', route);
- this.sendPageRequest({
- url: route,
- urlref: lastPageRoute,
- urlref_ts: time.residenceTime,
- });
- // this._lastPageRoute = route
- return
- }
- }
- /**
- * 发送请求,应用维度上报
- * @param {Object} options 页面信息
- * @param {Boolean} type 是否立即上报
- */
- sendReportRequest(options, type) {
- this._navigationBarTitle.lt = '1';
- this._navigationBarTitle.config = get_page_name(options.path);
- let is_opt = options.query && JSON.stringify(options.query) !== '{}';
- let query = is_opt ? '?' + JSON.stringify(options.query) : '';
- const last_time = get_last_visit_time();
- // 非老用户
- if(last_time !== 0 || !last_time){
- const odid = get_odid();
- // 1.0 处理规则
- {
- this.statData.odid = odid;
- }
- }
- Object.assign(this.statData, {
- lt: '1',
- url: options.path + query || '',
- t: get_time(),
- sc: get_scene(options.scene),
- fvts: get_first_visit_time(),
- lvts: last_time,
- tvc: get_total_visit_count(),
- // create session type 上报类型 ,1 应用进入 2.后台30min进入 3.页面30min进入
- cst: options.cst || 1,
- });
- if (get_platform_name() === 'n') {
- this.getProperty(type);
- } else {
- this.getNetworkInfo(type);
- }
- }
- /**
- * 发送请求,页面维度上报
- * @param {Object} opt
- */
- sendPageRequest(opt) {
- let { url, urlref, urlref_ts } = opt;
- this._navigationBarTitle.lt = '11';
- let options = {
- ak: this.statData.ak,
- uuid: this.statData.uuid,
- p: this.statData.p,
- lt: '11',
- ut: this.statData.ut,
- url,
- tt: this.statData.tt,
- urlref,
- urlref_ts,
- ch: this.statData.ch,
- usv: this.statData.usv,
- t: get_time(),
- };
- this.request(options);
- }
- /**
- * 进入后台上报数据
- * @param {Object} opt
- * @param {Object} type
- */
- sendHideRequest(opt, type) {
- let { urlref, urlref_ts } = opt;
- let options = {
- ak: this.statData.ak,
- uuid: this.statData.uuid,
- p: this.statData.p,
- lt: '3',
- ut: this.statData.ut,
- urlref,
- urlref_ts,
- ch: this.statData.ch,
- usv: this.statData.usv,
- t: get_time(),
- };
- this.request(options, type);
- }
- /**
- * 自定义事件上报
- */
- sendEventRequest({ key = '', value = '' } = {}) {
- let routepath = '';
- try {
- routepath = get_route$1();
- } catch (error) {
- const launch_options = dbGet('__launch_options');
- routepath = launch_options.path;
- }
- this._navigationBarTitle.config = get_page_name(routepath);
- this._navigationBarTitle.lt = '21';
- let options = {
- ak: this.statData.ak,
- uuid: this.statData.uuid,
- p: this.statData.p,
- lt: '21',
- ut: this.statData.ut,
- url: routepath,
- ch: this.statData.ch,
- e_n: key,
- e_v: typeof value === 'object' ? JSON.stringify(value) : value.toString(),
- usv: this.statData.usv,
- t: get_time(),
- };
- this.request(options);
- }
- sendPushRequest(options, cid) {
- let time = get_time();
- const statData = {
- lt: '101',
- cid: cid,
- t: time,
- ut: this.statData.ut,
- };
- // debug 打印打点信息
- if (is_debug) {
- log(statData);
- }
- const stat_data = handle_data({
- 101: [statData],
- });
- let optionsData = {
- usv: STAT_VERSION, //统计 SDK 版本号
- t: time, //发送请求时的时间戮
- requests: stat_data,
- };
- {
- if (statData.ut === 'h5') {
- this.imageRequest(optionsData);
- return
- }
- }
- // XXX 安卓需要延迟上报 ,否则会有未知错误,需要验证处理
- if (get_platform_name() === 'n' && this.statData.p === 'a') {
- setTimeout(() => {
- this.sendRequest(optionsData);
- }, 200);
- return
- }
- this.sendRequest(optionsData);
- }
- /**
- * 获取wgt资源版本
- */
- getProperty(type) {
- plus.runtime.getProperty(plus.runtime.appid, (wgtinfo) => {
- this.statData.v = wgtinfo.version || '';
- this.getNetworkInfo(type);
- });
- }
- /**
- * 获取网络信息
- */
- getNetworkInfo(type) {
- uni.getNetworkType({
- success: (result) => {
- this.statData.net = result.networkType;
- this.getLocation(type);
- },
- });
- }
- /**
- * 获取位置信息
- */
- getLocation(type) {
- if (stat_config.getLocation) {
- uni.getLocation({
- type: 'wgs84',
- geocode: true,
- success: (result) => {
- if (result.address) {
- this.statData.cn = result.address.country;
- this.statData.pn = result.address.province;
- this.statData.ct = result.address.city;
- }
- this.statData.lat = result.latitude;
- this.statData.lng = result.longitude;
- this.request(this.statData, type);
- },
- });
- } else {
- this.statData.lat = 0;
- this.statData.lng = 0;
- this.request(this.statData, type);
- }
- }
- /**
- * 发送请求
- * @param {Object} data 上报数据
- * @param {Object} type 类型
- */
- request(data, type) {
- let time = get_time();
- const title = this._navigationBarTitle;
- Object.assign(data, {
- ttn: title.page,
- ttpj: title.config,
- ttc: title.report,
- });
- let uniStatData = dbGet('__UNI__STAT__DATA') || {};
- if (!uniStatData[data.lt]) {
- uniStatData[data.lt] = [];
- }
- // 加入队列
- uniStatData[data.lt].push(data);
- dbSet('__UNI__STAT__DATA', uniStatData);
- let page_residence_time = get_page_residence_time();
- // debug 打印打点信息
- if (is_debug) {
- log(data);
- }
- // 判断时候到达上报时间 ,默认 10 秒上报
- if (page_residence_time < eport_Interval && !type) return
- // 时间超过,重新获取时间戳
- set_page_residence_time();
- const stat_data = handle_data(uniStatData);
- let optionsData = {
- usv: STAT_VERSION, //统计 SDK 版本号
- t: time, //发送请求时的时间戮
- requests: stat_data,
- };
- // 重置队列
- dbRemove('__UNI__STAT__DATA');
- {
- if (data.ut === 'h5') {
- this.imageRequest(optionsData);
- return
- }
- }
- // XXX 安卓需要延迟上报 ,否则会有未知错误,需要验证处理
- if (get_platform_name() === 'n' && this.statData.p === 'a') {
- setTimeout(() => {
- this.sendRequest(optionsData);
- }, 200);
- return
- }
- this.sendRequest(optionsData);
- }
- getIsReportData() {
- return is_report_data()
- }
- /**
- * 数据上报
- * @param {Object} optionsData 需要上报的数据
- */
- sendRequest(optionsData) {
- {
- this.getIsReportData().then(() => {
- uni.request({
- url: STAT_URL,
- method: 'POST',
- data: optionsData,
- success: () => {
- if (is_debug) {
- log(optionsData, true);
- }
- },
- fail: (e) => {
- if (++this._retry < 3) {
- if (is_debug) {
- console.warn('=== 统计上报错误,尝试重新上报!');
- console.error(e);
- }
- setTimeout(() => {
- this.sendRequest(optionsData);
- }, 1000);
- }
- },
- });
- });
- }
- }
- /**
- * h5 请求
- */
- imageRequest(data) {
- this.getIsReportData().then(() => {
- let image = new Image();
- let options = get_sgin(get_encodeURIComponent_options(data)).options;
- image.src = STAT_H5_URL + '?' + options;
- if (is_debug) {
- log(data, true);
- }
- });
- }
- sendEvent(key, value) {
- // 校验 type 参数
- if (calibration(key, value)) return
- if (key === 'title') {
- this._navigationBarTitle.report = value;
- return
- }
- this.sendEventRequest(
- {
- key,
- value: typeof value === 'object' ? JSON.stringify(value) : value,
- },
- 1
- );
- }
- }
- class Stat extends Report {
- static getInstance() {
- if (!uni.__stat_instance) {
- uni.__stat_instance = new Stat();
- }
- return uni.__stat_instance
- }
- constructor() {
- super();
- }
- /**
- * 获取推送id
- */
- pushEvent(options) {
- const ClientID = is_push_clientid();
- if (uni.getPushClientId && ClientID) {
- uni.getPushClientId({
- success: (res) => {
- const cid = res.cid || false;
- // 只有获取到才会上传
- if (cid) {
- this.sendPushRequest(options, cid);
- }
- },
- });
- }
- }
- /**
- * 进入应用
- * @param {Object} options 页面参数
- * @param {Object} self 当前页面实例
- */
- launch(options, self) {
- // 初始化页面停留时间 start
- set_page_residence_time();
- this.__licationShow = true;
- dbSet('__launch_options', options);
- // 应用初始上报参数为1
- options.cst = 1;
- this.sendReportRequest(options, true);
- }
- load(options, self) {
- this.self = self;
- this._query = options;
- }
- appHide(self) {
- this.applicationHide(self, true);
- }
- appShow(self) {
- this.applicationShow(self);
- }
- show(self) {
- this.self = self;
- if (get_page_types(self) === 'page') {
- const isPageReport = is_page_report();
- if (isPageReport) {
- this.pageShow(self);
- }
- }
- // #ifdef VUE3
- if (get_platform_name() === 'h5' || get_platform_name() === 'n') {
- if (get_page_types(self) === 'app') {
- this.appShow();
- }
- }
- // #endif
- // #ifndef VUE3
- if (get_page_types(self) === 'app') {
- this.appShow();
- }
- // #endif
- }
- hide(self) {
- this.self = self;
- if (get_page_types(self) === 'page') {
- const isPageReport = is_page_report();
- if (isPageReport) {
- this.pageHide(self);
- }
- }
- // #ifdef VUE3
- if (get_platform_name() === 'h5' || get_platform_name() === 'n') {
- if (get_page_types(self) === 'app') {
- this.appHide();
- }
- }
- // #endif
- // #ifndef VUE3
- if (get_page_types(self) === 'app') {
- this.appHide();
- }
- // #endif
- }
- error(em) {
- // 开发工具内不上报错误
- // if (this._platform === 'devtools') {
- // if (process.env.NODE_ENV === 'development') {
- // console.info('当前运行环境为开发者工具,不上报数据。')
- // return
- // }
- // }
- let emVal = '';
- if (!em.message) {
- emVal = JSON.stringify(em);
- } else {
- emVal = em.stack;
- }
- let route = '';
- try {
- route = get_route();
- } catch (e) {
- // 未获取到页面路径
- route = '';
- }
- let options = {
- ak: this.statData.ak,
- uuid: this.statData.uuid,
- p: this.statData.p,
- lt: '31',
- url: route,
- ut: this.statData.ut,
- ch: this.statData.ch,
- mpsdk: this.statData.mpsdk,
- mpv: this.statData.mpv,
- v: this.statData.v,
- em: emVal,
- usv: this.statData.usv,
- t: parseInt(new Date().getTime() / 1000),
- };
- this.request(options);
- }
- }
- var Stat$1 = Stat;
- const stat = Stat$1.getInstance();
- // 用于判断是隐藏页面还是卸载页面
- let isHide = false;
- const lifecycle = {
- onLaunch(options) {
- // 进入应用上报数据
- stat.launch(options, this);
- // 上报push推送id
- stat.pushEvent(options);
- },
- onLoad(options) {
- stat.load(options, this);
- // 重写分享,获取分享上报事件
- if (this.$scope && this.$scope.onShareAppMessage) {
- let oldShareAppMessage = this.$scope.onShareAppMessage;
- this.$scope.onShareAppMessage = function (options) {
- stat.interceptShare(false);
- return oldShareAppMessage.call(this, options)
- };
- }
- },
- onShow() {
- isHide = false;
- stat.show(this);
- },
- onHide() {
- isHide = true;
- stat.hide(this);
- },
- onUnload() {
- if (isHide) {
- isHide = false;
- return
- }
- stat.hide(this);
- },
- onError(e) {
- stat.error(e);
- },
- };
- // 加载统计代码
- function load_stat() {
- // #ifdef VUE3
- uni.onCreateVueApp((app) => {
- app.mixin(lifecycle);
- uni.report = function (type, options) {
- stat.sendEvent(type, options);
- };
- });
- if (get_platform_name() !== 'h5' && get_platform_name() !== 'n') {
- uni.onAppHide(() => {
- stat.appHide(get_page_vm());
- });
- uni.onAppShow(() => {
- stat.appShow(get_page_vm());
- });
- }
- // #endif
- // #ifndef VUE3
- // eslint-disable-next-line no-restricted-globals
- const Vue = require('vue')
- ;(Vue.default || Vue).mixin(lifecycle);
- uni.report = function (type, options) {
- stat.sendEvent(type, options);
- };
- // #endif
- }
- function main() {
- if (is_debug) {
- {
- // #ifndef APP-NVUE
- console.log('=== uni统计开启,version:1.0 ===');
- // #endif
- }
- load_stat();
- } else {
- if (process.env.NODE_ENV === 'development') {
- uni.report = function (type, options) {};
- } else {
- load_stat();
- }
- }
- }
- main();
|