万恶资本,开启收费模式
自力更生,不做韭菜
实现步骤:
- 小程序前端app.js中添加onAppRoute监听事件
- 在onAppRoute事件中, 再添加监听页面状态事件(onReady 、onShow、onUnload )
- 调用接口保存数据到数据库
- 统计分析并展示(本文略过……)
小程序代码
//用户访问列表
this.UserViewLogsList = [];
//待保存数据库列表,调用后台接口后数组清空
this.UserViewLogsDatas = [];
wx.onAppRoute((route) => {
const pages = getCurrentPages() //获取加载的页面
const view = pages[pages.length - 1] //获取当前页面的对象
var that = this;
var pagekey = "key_" + this.Hashcode(new Date());
view.setData({
pagekey: view.data.pagekey || pagekey
})
view.onReady = () => {
that.SetCache(view.data.pagekey, new Date().getTime(), 60 * 1000 * 10);
that.UserViewLogsList.push({
InTime: new Date().getTime(),
OutTime: new Date().getTime(),
ViewPath: view.route,
Duration: 0,
PathDepth: pages.length,
PageKey: view.data.pagekey,
Query:view.options?JSON.stringify(view.options):"",
TurnOnTimer: true
});
//暂停除当前页面外所有计时
that.UserViewLogsList.forEach(log => {
if (view.data.pagekey != log.PageKey) {
if (log.TurnOnTimer)
{
log.Duration = new Date().getTime() - log.EndTime;
log.EndTime = new Date().getTime()- log.Duration ;
}
log.TurnOnTimer = false;
}
});
};
//重新激活时开启页面计时
view.onShow = () => {
that.UserViewLogsList.forEach(log => {
//开启当前页面计时
if (view.data.pagekey == log.PageKey) {
log.TurnOnTimer = true;
log.OutTime = new Date().getTime() - log.Duration;
}
});
}
view.onHide = () => {
that.UserViewLogsList.forEach(log => {
//离开小程序时停止页面计时
if (view.data.pagekey == log.PageKey && log.TurnOnTimer) {
log.TurnOnTimer = false;
log.Duration = new Date().getTime() - log.EndTime;
log.EndTime = new Date().getTime()- log.Duration ;
}
});
}
view.onUnload = () => {
var _tempLogsList = [];
//注销时,保存到待入库数组,并从用户访问列表中去除
that.UserViewLogsList.forEach(log => {
//注入数据库
if (view.data.pagekey == log.PageKey) {
log.Duration = new Date().getTime() - log.OutTime;
log.OutTime = new Date().getTime();
that.UserViewLogsDatas.push(that.cloneObj(log));
} else {
_tempLogsList.push(log);
}
});
that.UserViewLogsList = _tempLogsList;
if (that.UserViewLogsDatas.length >= 3) {
//调用后台服务保存日志
that.wxRequest('api/Common/saveUserViewLogs', 'POST', {
datas: JSON.stringify(that.UserViewLogsDatas)
}, (suc) => {});
that.UserViewLogsDatas = []
} else {
that.SetCache("_UserViewLogsDatas_", that.UserViewLogsDatas, 7 * 24 * 3600 * 1000)
}
};
后端服务
/// <summary>
/// 记录用户访问日志
/// </summary>
/// <param name="datas"></param>
/// <returns></returns>
[HttpPost("saveUserViewLogs")]
public JsonResult saveUserViewLogs(string datas)
{
string dataList = Request.Form.ContainsKey("datas") ? Request.Form["datas"].ToString() : "";
JArray keys = JsonConvert.DeserializeObject(dataList) as JArray;
if (keys == null || keys.Count == 0)
{
return Json(1);
}
string sql = "insert into t_ViewLog(UserID,InTime,OutTime,ViewPath,Duration,PathDepth,Query) values (@UserID,{0},{1},{2},{3},{4},{5});";
StringBuilder sb = new();
//参数化
Dictionary<string, object> parms = new Dictionary<string, object>();
int i = 1;
parms.Add("UserID", UserID);
foreach (JObject cobj in keys)
{
long ticks = 1714033550178;
long.TryParse(cobj["InTime"].ToString(), out ticks);
DateTime InTime = DateTimeOffset.FromUnixTimeMilliseconds(ticks).LocalDateTime;
long.TryParse(cobj["OutTime"].ToString(), out ticks);
DateTime OutTime = DateTimeOffset.FromUnixTimeMilliseconds(ticks).LocalDateTime;
sb.AppOutLine(string.Format(sql, "@InTime_" + i, "@OutTime_" + i, "@ViewPath_" + i, "@Duration_" + i, "@PathDepth_" + i, "@Query_" + i));
parms.Add("InTime_" + i, InTime.ToString("yyyy-MM-dd HH:mm:ss"));
parms.Add("OutTime_" + i, OutTime.ToString("yyyy-MM-dd HH:mm:ss"));
parms.Add("ViewPath_" + i, cobj["ViewPath"] != null ? cobj["ViewPath"].ToString() : null);
parms.Add("Duration_" + i, cobj["Duration"] != null ? cobj["Duration"].ToString() : null);
parms.Add("PathDepth_" + i, cobj["PathDepth"] != null ? cobj["PathDepth"].ToString() : null);
parms.Add("Query_" + i, cobj["Query"] != null ? cobj["Query"].ToString() : null);
i++;
}
if (sb.Length > 10)
{
Common.ExecuteNonQuery(sb.ToString(), parms);
}
return Json(1);
}
数据库建表脚本
CREATE TABLE `t_ViewLog` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`UserID` varchar(50) DEFAULT NULL COMMENT '用户ID',
`InTime` datetime DEFAULT NULL COMMENT '进入时间',
`OutTime` datetime DEFAULT NULL COMMENT '离开时间',
`ViewPath` varchar(800) DEFAULT NULL COMMENT '访问页面路径',
`Query` varchar(4000) DEFAULT NULL COMMENT '查询参数',
`Duration` int(11) DEFAULT NULL COMMENT '页面停留时长',
`PathDepth` int(11) DEFAULT NULL COMMENT '访问深度',
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=168 DEFAULT CHARSET=utf8mb4;
数据库记录数据截图