基于uni-app的埋点sdk设计
一、统计app激活状态
在App.vue 中 利用onShow生命周期验证 或者操作
onShow: function () {
uni.showToast({
title: 'onShow'
})
},
二、页面级别的统计 (进入页面、停留时长、手机系统信息、网络状态、页面路径、标题)
需要收集的数据
{
"pageType": "leavePage",
"networkType": "wifi",
"pageInfo": {
"pageUrl": "pages/index/newIndex",
"title": ""
},
"entryTime": "2024-04-10 13:18:50",
"leaveTime": "2024-04-10 13:18:51",
"nowTime": "2024-04-10 13:18:51",
"stayTime": 279,
"sysTemInfo": {
"appName": "某某app",
"appVersion": "2.1.4",
"brand": "apple",
"platform": "ios",
"system": "iOS 17.3.1"
},
"pageLoadTime": 873
}
通过混入mixins 每个页面生命周期埋点统计、编写逻辑方法
三、页面内部事件级别的统计 (各种事件信息集合eventTrack(点击、复制、下载、来源某个特定页面的操作)、 手机系统信息、网络状态、页面路径、标题)
需要收集的数据
{
"networkType": "unknown",
"pageInfo": {
"pageUrl": "pages/order/index",
"title": "订单"
},
"sysTemInfo": {
"appName": "某某app",
"appVersion": "2.1.4",
"brand": "xiaomi",
"platform": "android",
"system": "Android 12"
},
"eventTrack": { // 事件所需要的埋点字段
"eventCode": "B0004"
}
}
通过混入mixins 每个页面生命周期埋点统计、编写逻辑方法
四、具体的设计流程
1、创建 埋点sdk方法 pointCom.js
主要三个方法
myPointPage, 页面级别触发的
toDateDetail, 时间转化函数
myPointEvent, 页面内部事件触发的
详细编码
import { pagesObj } from '@/uni-config/pages.js' // 页面路由和标题的映射map
console.log(pagesObj, 'uni-config')
async function myPointPage(pageType = "", pageUrl = "") {
console.log("埋点", pageType, pageUrl);
let entryTime, leaveTime, stayTime, nowTime;
if (!pageType) return;
if (pageType == "entryPage") {
entryTime = new Date().getTime();
nowTime = new Date().getTime();
leaveTime = null;
uni.setStorageSync("entryTime", entryTime);
} else {
entryTime = uni.getStorageSync("entryTime");
leaveTime = new Date().getTime();
stayTime = leaveTime - entryTime;
nowTime = new Date().getTime();
}
uni.getNetworkType({
success: function (res) {
let networkType = res.networkType;
try {
uni.getSystemInfo({
success: function (res) {
let { appName,
appWgtVersion,
brand,
platform,
system } = res
let data = {
pageType: pageType,
networkType: networkType,
pageInfo: {
pageUrl: pageUrl,
title: pagesObj[pageUrl]
},
entryTime: toDateDetail(entryTime),
leaveTime: toDateDetail(leaveTime),
nowTime: toDateDetail(nowTime),
stayTime: stayTime,
sysTemInfo: {
appName,
appVersion: appWgtVersion,
brand,
platform,
system
},
};
if (pageType === "leavePage") {
data.pageLoadTime = uni.getStorageSync("pageLoadTime");
}
console.log('发送调用埋点接口', data)
},
fail(error) {
sysTemInfo = "null";
},
});
} catch (e) { }
},
});
}
async function myPointEvent(eventTrack = {}, pageUrl = "") {
uni.getNetworkType({
success: function (res) {
let networkType = res.networkType;
try {
uni.getSystemInfo({
success: function (res) {
let { appName,
appWgtVersion,
brand,
platform,
system } = res
let data = {
networkType: networkType,
pageInfo: {
pageUrl: pageUrl,
title: pagesObj[pageUrl]
},
sysTemInfo: {
appName,
appVersion: appWgtVersion,
brand,
platform,
system
},
eventTrack
};
console.log('myPointEvent发送调用埋点接口', data)
},
fail(error) {
sysTemInfo = "null";
},
});
} catch (e) { }
},
});
}
function toDateDetail(number) {
if (!number) return undefined;
// var n = number * 1000
var date = new Date(number);
var Y = date.getFullYear() + "-";
var M =
(date.getMonth() + 1 < 10
? "0" + (date.getMonth() + 1)
: date.getMonth() + 1) + "-";
var D = date.getDate() < 10 ? "0" + date.getDate() : date.getDate();
var h = date.getHours() < 10 ? "0" + date.getHours() : date.getHours();
var mm = date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes();
var s = date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds();
return Y + "" + M + "" + D + " " + h + ":" + mm + ":" + s;
}
export default {
myPointPage,
toDateDetail,
myPointEvent,
};
2、创建 埋点混入的方法和生命周期 pointMixin.js
主要四个方法
eventTrack, 页面事件调用的函数
entryTrack, 页面进入调用的函数
leaveTrack, 页面离开调用的函数
pageLoadTime 页面onReady调用的函数
详细编码
import pointCom from "@/utils/pointCom.js";
export default {
data() {
return {
pointPageUrl: "", //跳转url
pageType: "", //事件类型 进入、离开
loadStartTime: "", //页面加载开始时间
};
},
onLoad() {
this.entryTrack();
},
onReady() {
this.pageLoadTime();
},
onHide() {
this.leaveTrack();
},
onUnload() {
this.leaveTrack();
},
methods: {
eventTrack(eventTrack = {}) {
console.log('eventTrack', eventTrack, this.pointPageUrl)
let pointPageUrl = getCurrentPages()[getCurrentPages().length - 1].route;
this.pointPageUrl = pointPageUrl;
pointCom.myPointEvent(eventTrack, this.pointPageUrl);
},
entryTrack() {
let loadStartTime = pointCom.toDateDetail(Number(new Date()));
let pointPageUrl = getCurrentPages()[getCurrentPages().length - 1].route;
this.pointPageUrl = pointPageUrl;
this.pageType = "entryPage";
this.loadStartTime = loadStartTime;
pointCom.myPointPage("entryPage", this.pointPageUrl);
},
pageLoadTime() {
let pageLoadTime = Number(new Date()) - new Date(this.loadStartTime).getTime()
console.log("pageLoadTime", pageLoadTime, this.loadStartTime)
uni.setStorageSync("pageLoadTime", pageLoadTime);
},
leaveTrack() {
if (this.pageType === "leavePage") return;
this.pageType = "leavePage";
pointCom.myPointPage("leavePage", this.pointPageUrl);
},
},
};
3、main.js 引入 pointMixin.js
详细编码
import pointMixin from "@/utils/pointMixin"; //配合埋点的mixin
Vue.mixin(pointMixin);
4、得到页面路由和标题的映射map
h5中可以得到标题等数据,但是app中无法获取
// 获取当前页面链接和参数
function getCurrentPageUrlWithArgs() {
const pages = getCurrentPages();
const currentPage = pages[pages.length - 1];
const route = currentPage?.route;
const options = currentPage?.options || {};
const title = currentPage?.$holder?.navigationBarTitleText || ''
console.log(title)
let urlWithArgs = /${route}?;
for (let key in options) {
const value = options[key];
urlWithArgs += ${key}=${value}&;
}
urlWithArgs = urlWithArgs.substring(0, urlWithArgs.length - 1);
return {
options, //当前页面的参数
urlWithArgs, //当前页面的参数
route,
title,
};
}
app获取相关数据需要另辟蹊径
通过文件的读取和写入来实现
具体编码
const fs = require("fs-extra")
let path = require("path")
let Hjson = require("hjson")
const chokidar = require("chokidar")
let rootPath = (function () {
let e = path.resolve(__dirname, "./")
return e
})()
function creatPagesJs() {
try {
const fileContent = fs.readFileSync('./pages.json', 'utf8');
const jsonObj = Hjson.rt.parse(fileContent);
let pages = jsonObj.pages
let pagesObj = {}
pages.map(item => {
let path = item.path
let title = item?.style?.navigationBarTitleText || ''
pagesObj[path] = title
})
console.log(pagesObj, 'pagesObj')
let pstr = "export const pagesObj = " + JSON.stringify(pagesObj, null, 2);
fs.outputFileSync(
path.resolve(rootPath, "uni-config", "pages.js"),
pstr
);
} catch (err) {
console.log(err);
}
}
const watcherPagesJson = chokidar
.watch(path.resolve(__dirname, "./pages.json"))
watcherPagesJson.on("all", (event, path) => {
console.log(event, path, 'pages.json')
if (event == "change") {
creatPagesJs()
}
})
creatPagesJs();
如何调用 package.json 配置调用命令
"scripts": {
"getPages": "node getPages.js"
},
相关文章:
基于uni-app的埋点sdk设计
一、统计app激活状态 在App.vue 中 利用onShow生命周期验证 或者操作 onShow: function () { uni.showToast({ title: onShow }) }, 二、页面级别的统计 (进入页面、停留时长、手机系统信息、网络状态、页面路径、标题) 需要收集的数据 { &quo…...
Python学习笔记(三)
一、使用朴素贝叶斯制作鸢尾花数据模型 from sklearn.preprocessing import StandardScaler from sklearn.naive_bayes import MultinomialNB from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split from sklearn.feature_extraction…...
Python办公自动化之Excel做表自动化:全网最全,看这一篇就够了!
0 Python Excel库对比 我们先来看一下python中能操作Excel的库对比(一共九个库): 1 Python xlrd 读取 操作Excel 1.1 xlrd模块介绍 (1)什么是xlrd模块? python操作excel主要用到xlrd和xlwt这两个库&…...
【学习笔记】R语言入门与数据分析1
数据分析 数据分析的过程: 数据采集 数据存储 数据分析 数据挖掘 数据可视化 进行决策 数据挖掘 数据量大 复杂度高,容忍一定的误差限 追求相关性而非因果性 数据可视化 直观明了 R语言介绍 R是免费的(开源软件、扩展性好)…...
MyBatis-Spring整合
引入Spring之前需要了解mybatis-spring包中的一些重要类; http://www.mybatis.org/spring/zh/index.html 什么是 MyBatis-Spring? MyBatis-Spring 会帮助你将 MyBatis 代码无缝地整合到 Spring 中。 知识基础 在开始使用 MyBatis-Spring 之前&#x…...
资深亚马逊运营实战技巧:跨境电商6大选品法
1、工具选品法 比如店雷达, 通过大数据分析工具选出来利基产品或者通过工具选出来利基的市场,然后再通过分析市场来得到产品。 以女装为例,通过大数据分析,全方位对市场需求、款式、质量等进行多维度判断,其中SKU销量…...
bugku-web-需要管理员
页面源码 <html> <head> <meta http-equiv"Content-Type" content"text/html; charsetUTF-8"> <title>404 Not Found</title> </head> <body> <div idmain><i> <h2>Something error:</h2…...
STM32之FreeRTOS移植
1.FreeRTOS的移植过程是将系统需要的文件和代码进行移植和裁剪,其移植的主要过程为: (1)官网上下载FreeRTOS源码:https://www.freertos.org/ (2)移植文件夹,在portable文件夹中只需…...
SpringBoot实用开发(十四)-- 消息(Message)的简单认识
目录 1.消息的概念 2.Java处理消息的标准规范 3.JMS 4.AMQP 5.MQTT 1.消息的概念 广义角度来说,消息其实就是信息,但是和信息又有所不同。信息通常被定义为一组数据,而消息除了具有数据的特征之外,还有...
【Spring Boot 源码学习】SpringApplication 的 run 方法核心流程介绍
《Spring Boot 源码学习系列》 SpringApplication 的 run 方法核心流程介绍 一、引言二、往期内容三、主要内容3.1 run 方法源码初识3.2 引导上下文 BootstrapContext3.3 系统属性【java.awt.headless】3.4 早期启动阶段3.5 准备和配置应用环境3.6 打印 Banner 信息3.7 新建应用…...
如何保证消息不丢失?——使用rabbitmq的死信队列!
如何保证消息不丢失?——使用rabbitmq的死信队列! 1、什么是死信 在 RabbitMQ 中充当主角的就是消息,在不同场景下,消息会有不同地表现。 死信就是消息在特定场景下的一种表现形式,这些场景包括: 消息被拒绝访问&am…...
html、css、京东移动端静态页面,资源免费分享,可作为参考,提供InsCode在线运行演示
CSDN将我上传的免费资源私自变成VIP专享资源,且作为作者的我不可修改为免费资源,不可删除,寻找客服无果,很愤怒,(我发布免费资源就是希望大家能免费一起用、一起学习),接下来继续寻找…...
头歌-机器学习 第13次实验 特征工程——共享单车之租赁需求预估
第1关:数据探索与可视化 任务描述 本关任务:编写python代码,完成一天中不同时间段的平均租赁数量的可视化功能。 相关知识 为了完成本关任务,你需要掌握: 读取数据数据探索与可视化 读取数据 数据保存在./step1/…...
Unity 2D让相机跟随角色移动
相机跟随移动 最简单的方式通过插件Cinemachine 在窗口/包管理器选择全部找到Cinemachine,导入。然后在游戏对象/Cinemachine创建2D Camera。此时层级中创建一个2D相机。选中人物拖入检查器Follow。此时相机跟随人物移动。 修改相机视口距离 在检查器中Lens下调正…...
【面试题】s += 1 和 s = s + 1的区别
文章目录 1.问题2.发现过程3.解析 1.问题 以下两个程序真的完全等同吗? short s 0; s 1; short s 0; s s 1; 2.发现过程 初看s 1 和 s s 1好像是等价的,没有什么区别。很长一段时间内我也是这么觉得,因为当时学习c语言的时候教科书…...
ARM的学习
点亮流水灯 .text .global _start _start: 使能GPIOE的外设时钟 RCC_MP_AHB4ENSETR 0x50000a28 [4]->1LDR R0,0X50000A28 指定基地址LDR R1,[R0] 将寄存器数据读取出来保存到R1中ORR R1,R1,#(0x3<<4) [4]设置为1ORR R1,R1,#(0x3<<5) [5]设置为1STR …...
Restful API接口规范(以Django为例)
Restful API接口规范(以Django为例) Restful API的接口架构风格中制定了一些规范,极大的简化了前后端对接的时间,以及增加了开发效率 安全性保证–使用https路径中带 api标识路径中带版本号数据即资源,通常使用名词操作请求方式决定操作资源…...
AI助力,程序员压力倍增?
讲动人的故事,写懂人的代码 你知道程序员现在在AI辅助编程时最头疼的事情是什么吗?就是怎么在改代码的时候保住小命。 大家都听过程序员因为工作太累导致过劳湿的事情。 无论是写新功能、修bug,还是更改系统配置,都得改代码。 现在有了AI的帮助,本应该轻松很多,为什么…...
LoRA微调
论文:LoRA: Low-Rank Adaptation of Large Language Models 实现:microsoft/LoRA: Code for loralib, an implementation of “LoRA: Low-Rank Adaptation of Large Language Models” (github.com) 摘要 自然语言处理的一个重要的开发范式包括&#…...
45.基于SpringBoot + Vue实现的前后端分离-驾校预约学习系统(项目 + 论文)
项目介绍 本站是一个B/S模式系统,采用SpringBoot Vue框架,MYSQL数据库设计开发,充分保证系统的稳定性。系统具有界面清晰、操作简单,功能齐全的特点,使得基于SpringBoot Vue技术的驾校预约学习系统设计与实现管理工作…...
(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...
React Native 导航系统实战(React Navigation)
导航系统实战(React Navigation) React Navigation 是 React Native 应用中最常用的导航库之一,它提供了多种导航模式,如堆栈导航(Stack Navigator)、标签导航(Tab Navigator)和抽屉…...
Oracle查询表空间大小
1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...
【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...
微信小程序 - 手机震动
一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注:文档 https://developers.weixin.qq…...
Linux离线(zip方式)安装docker
目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1:修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本:CentOS 7 64位 内核版本:3.10.0 相关命令: uname -rcat /etc/os-rele…...
代码规范和架构【立芯理论一】(2025.06.08)
1、代码规范的目标 代码简洁精炼、美观,可持续性好高效率高复用,可移植性好高内聚,低耦合没有冗余规范性,代码有规可循,可以看出自己当时的思考过程特殊排版,特殊语法,特殊指令,必须…...
从面试角度回答Android中ContentProvider启动原理
Android中ContentProvider原理的面试角度解析,分为已启动和未启动两种场景: 一、ContentProvider已启动的情况 1. 核心流程 触发条件:当其他组件(如Activity、Service)通过ContentR…...
