基于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技术的驾校预约学习系统设计与实现管理工作…...
【Axure高保真原型】引导弹窗
今天和大家中分享引导弹窗的原型模板,载入页面后,会显示引导弹窗,适用于引导用户使用页面,点击完成后,会显示下一个引导弹窗,直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...
Python如何给视频添加音频和字幕
在Python中,给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加,包括必要的代码示例和详细解释。 环境准备 在开始之前,需要安装以下Python库:…...
JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...
多模态大语言模型arxiv论文略读(108)
CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题:CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者:Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...
探索Selenium:自动化测试的神奇钥匙
目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...
零知开源——STM32F103RBT6驱动 ICM20948 九轴传感器及 vofa + 上位机可视化教程
STM32F1 本教程使用零知标准板(STM32F103RBT6)通过I2C驱动ICM20948九轴传感器,实现姿态解算,并通过串口将数据实时发送至VOFA上位机进行3D可视化。代码基于开源库修改优化,适合嵌入式及物联网开发者。在基础驱动上新增…...
五子棋测试用例
一.项目背景 1.1 项目简介 传统棋类文化的推广 五子棋是一种古老的棋类游戏,有着深厚的文化底蕴。通过将五子棋制作成网页游戏,可以让更多的人了解和接触到这一传统棋类文化。无论是国内还是国外的玩家,都可以通过网页五子棋感受到东方棋类…...
边缘计算网关提升水产养殖尾水处理的远程运维效率
一、项目背景 随着水产养殖行业的快速发展,养殖尾水的处理成为了一个亟待解决的环保问题。传统的尾水处理方式不仅效率低下,而且难以实现精准监控和管理。为了提升尾水处理的效果和效率,同时降低人力成本,某大型水产养殖企业决定…...
