基于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技术的驾校预约学习系统设计与实现管理工作…...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

React第五十七节 Router中RouterProvider使用详解及注意事项
前言 在 React Router v6.4 中,RouterProvider 是一个核心组件,用于提供基于数据路由(data routers)的新型路由方案。 它替代了传统的 <BrowserRouter>,支持更强大的数据加载和操作功能(如 loader 和…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...
vue3 定时器-定义全局方法 vue+ts
1.创建ts文件 路径:src/utils/timer.ts 完整代码: import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...

技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...

视觉slam十四讲实践部分记录——ch2、ch3
ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...

深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用
文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么?1.1.2 感知机的工作原理 1.2 感知机的简单应用:基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...

Golang——6、指针和结构体
指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...

打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用
一、方案背景 在现代生产与生活场景中,如工厂高危作业区、医院手术室、公共场景等,人员违规打手机的行为潜藏着巨大风险。传统依靠人工巡查的监管方式,存在效率低、覆盖面不足、判断主观性强等问题,难以满足对人员打手机行为精…...

消防一体化安全管控平台:构建消防“一张图”和APP统一管理
在城市的某个角落,一场突如其来的火灾打破了平静。熊熊烈火迅速蔓延,滚滚浓烟弥漫开来,周围群众的生命财产安全受到严重威胁。就在这千钧一发之际,消防救援队伍迅速行动,而豪越科技消防一体化安全管控平台构建的消防“…...