小程序埋点工具类

import { reportUrl } from '@/utils/conf.js'
import { getJsonHead } from '@/utils/header.js'
import request from '@/utils/request.js'
import Taro,{getCurrentInstance} from '@tarojs/taro'

const maxlength = 1 //最大上传数据, 当本地存有10条数据的时候才开始上报,1即每次手收集到数据就上报
// 是否验证会员以及已经登录的开关
const MEMBER_VALIDATION = true;
let statArr = []
/*
 * 埋点数据处理
 */
function checkMinmum() {
  return maxlength === 1
}
// 字符串前补充字符
function padStart(target, targetLength, padString) {
  targetLength = targetLength >> 0 //数字向下取整,并且不为数字转为0
  padString = String(typeof padString !== 'undefined' ? padString : ' ')
  if (target.length > targetLength) {
    return String(target)
  } else {
    targetLength = targetLength - target.length
    if (targetLength > padString.length) {
      const repeatLength = targetLength / padString.length
      for (let i = 0; i < repeatLength; i++) {
        padString += padString
      }
    }
    return padString.slice(0, targetLength) + String(target)
  }
}
// 字符串数据前补充0
const fillZero = (num) => {
  try {
    return num ? padStart(num.toString(), 2, '0') : ''
  } catch (e) {
    return ''
  }
}

// 过滤数据并且对数据操作,整理出上传数据
const filterData = (data) => {
  const memberId = Taro.getStorageSync('memberId')

  // params是通用数据,就是每次上报都会收集的数据,例如用户id,openid
  // 需要的通用数据都可以在这里加
  let params = {
    uid: memberId ? memberId : null
  }
  let paramsData = {}
  // 对传入的data中的index键值补充前缀0
  for (let [k, v] of Object.entries(data)) {
    if (v) {
      paramsData[k] = k === 'index' ? fillZero(v) : v
    }
  }

  paramsData = Object.assign(params, paramsData)
  Object.keys(paramsData).forEach((i) => !paramsData[i] && delete paramsData[i])
  return paramsData
}

function getStorageDataStatus(data) {
  const paramsData = filterData(data);
  // 本地储存
  statArr = Taro.getStorageSync('statArr') || []
  statArr.push(paramsData)
  if (statArr.length <= maxlength) {
    // console.info(`%c stat:${JSON.stringify(params)}`, 'color:	#EE00EE')
    Taro.setStorageSync('statArr', statArr)
  }
  return statArr.length === maxlength
}
// 判断是否会员登录
function validateMemberSwitch() {
  if (!MEMBER_VALIDATION) return true;
  const userInfo = Taro.getStorageSync('memberInfo') || null
  const isRegistered = userInfo && userInfo.openid && userInfo.mobile;
  if (isRegistered) {
    return true;
  }
  return false;
}
/**
 * 上报数据
 * @param {Object} base base.url, 必传,上报的接口名,不传调用会中止。
 *                      base.immediate. immediate默认为false,为true的时候直接上报(即上报当前缓存的全部数据,相当于手动取消maxLength机制),不会经过10条才上报的条件阈值(阈值为1时没有必要设置)
 * @param {Object} params 上报数据
 * 例子
 * statReport({ url: 'wowcolour_10001.txt' }, { num: 1, str: 'test' })
 * statReport({ url }, { index, skuId });
 * statReport({ url, immediate: true });立即上传全部本地数据
 * 谨记,statReport必须在调用堆栈的最后调用,即,加入调用函数,要在函数的最后一步执行,例如
 * function test() {
 *  xxx其他逻辑
 *  statReport({ url }, { skuId })
 * }
 */

export const statReport = ({ url = '', immediate = false } = {} , params = {}) => {
  // url不传,即无法上报
  if (!url) { return false }
  try {
    params.uuid = uuid(32, 64)
    params.timestamp = new Date().getTime()

    const isValid = validateMemberSwitch();
    // console.info(isValid, 333);
    if (!isValid) {
      return false
    }
    // 判断是否每次上传
    const isEvery = checkMinmum()
    // 如果是
    if (isEvery) {
      const data = filterData(params);
      requestReport(data, { url })
    } else {
      // 否则本地储存数据,按阈值上传
      const isValid = !immediate ? getStorageDataStatus(params) : true
      if (isValid) {
        const reportData = Taro.getStorageSync('statArr')
        Taro.removeStorageSync('statArr')
        if (Array.isArray(reportData)) {
          requestReport(reportData, { url })
        }
      }
    }
  } catch (e) {
    console.info(e)
  }
}

function requestReport(reportData, { url = '' } = {}) {
  console.info(reportData, 333);

  // 如果来源时场景值,将缓存launchOptions中的isReport改为true
  if (reportData && reportData.sourceFormScene) {
    let launchOptions = Taro.getStorageSync('launchOptions')
    launchOptions.isReport = true
    Taro.setStorageSync('launchOptions', launchOptions)
    delete reportData.sourceFormScene
  }

  request({
    header: getJsonHead(),
    // 这里的url仅作为展示用,wow的埋点可能会新建服务, 接口可能会变
    url: `${reportUrl}/data/watch/${url}`,
    data: reportData,
    success: function (res) {},
    fail: function (err) {
      console.info(`%c stat:fail`, 'color:	#EE00EE')
    }
  }).catch(e => {
    // console.info(e);
  })
}

function uuid(len, radix) {
  var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
  var uuid = [], i;
  radix = radix || chars.length;

  if (len) {
    // Compact form
    for (i = 0; i < len; i++) uuid[i] = chars[0 | Math.random()*radix];
  } else {
    // rfc4122, version 4 form
    var r;

    // rfc4122 requires these characters
    uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
    uuid[14] = '4';

    // Fill in random data.  At i==19 set the high bits of clock sequence as
    // per rfc4122, sec. 4.1.5
    for (i = 0; i < 36; i++) {
      if (!uuid[i]) {
        r = 0 | Math.random()*16;
        uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
      }
    }
  }

  return uuid.join('');
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值