浏览时长代码优化

This commit is contained in:
zhaol 2025-07-16 09:37:19 +08:00 committed by zhaolei
parent 4857ad16a7
commit 3538df2e5f

View File

@ -647,130 +647,150 @@
});
// 用户停留时间追踪器
const stayTimeTracker = {
totalStayTime: 0, // 总有效停留时间(秒)
intervalStartTime: 0, // 当前间隔开始时间戳
isActive: true, // 是否处于活跃状态
checkInterval: 5000, // 活动检查间隔(毫秒)
// 初始化
init() {
this.intervalStartTime = Date.now();
// 页面可见性变化监听
document.addEventListener('visibilitychange', () => {
if (document.hidden) {
this.pauseTracking();
} else {
this.resumeTracking();
}
});
// 用户活动监听(鼠标移动、点击、滚动、键盘等)
const activityEvents = ['mousemove', 'click', 'scroll', 'keydown', 'touchstart'];
activityEvents.forEach(event => {
window.addEventListener(event, this.resetTimer.bind(this), { passive: true });
});
// 开始检查
this.startChecking();
// 页面卸载前保存数据
window.addEventListener('beforeunload', this.handleUnload.bind(this));
},
// 开始检查活动状态
startChecking() {
setInterval(() => {
if (!this.isActive) return;
const currentTime = Date.now();
const elapsedSeconds = Math.floor((currentTime - this.intervalStartTime) / 1000);
// 达到60秒有效间隔
if (elapsedSeconds >= 10) {
this.totalStayTime += 10;
//this.intervalStartTime = currentTime;
this.reportStayTime(10,this.intervalStartTime,currentTime,this.isActive);
}
}, this.checkInterval);
},
// 重置计时器(用户有活动时调用)
resetTimer() {
if (!this.isActive) {
this.resumeTracking();
}
this.intervalStartTime = Date.now();
},
// 暂停追踪
pauseTracking() {
// 页面停留时间统计
class PageStayTimeTracker {
constructor() {
this.startTime = null;
this.lastReportTime = null;
this.reportInterval = 10000; // 60秒报告一次
this.isActive = false;
console.log('停留追踪已暂停');
},
this.isPageVisible = true; // 默认页面是可见的
this.visibilityBound = false; // 是否已绑定可见性事件
}
// 恢复追踪
resumeTracking() {
this.isActive = true;
this.intervalStartTime = Date.now();
console.log('停留追踪已恢复');
},
// 报告停留时间
reportStayTime(duration,intervalStartTime,currentTime,isActive) {
console.log(`有效停留时间: ${duration}秒 | 总计: ${this.totalStayTime}秒 ${currentTime} ${intervalStartTime}`);
// 延迟绑定可见性事件
bindVisibilityEvents() {
if (this.visibilityBound) return;
// 实际应用中这里发送数据到服务器
$.ajax({
type : "POST",
url : "./w?sid=" + encodeURIComponent($('#sid').val()) + "&cmd=com.awspaas.user.apps.browsing_data.service.insertReadingLog",
data : "userId="+userId+"&userName="+userName+"&ruuid="+ruuid+"&fileName="+fileName+"&intervalStartTime="+intervalStartTime+"&currentTime="+currentTime+"&browserId="+browserId+"&isActive="+isActive,
success : function(msg) {
if (msg.result == "error") {
$.simpleAlert("删除失败", "error");
}
}
});
document.addEventListener('visibilitychange', this.handleVisibilityChange.bind(this));
this.visibilityBound = true;
},
// 发送数据到服务器使用sendBeacon确保页面关闭时也能发送
sendToServer(duration,intervalStartTime,currentTime,isActive) {
// 实际应用中这里发送数据到服务器
$.ajax({
type : "POST",
url : "./w?sid=" + encodeURIComponent($('#sid').val()) + "&cmd=com.awspaas.user.apps.browsing_data.service.insertReadingLog",
data : "userId="+userId+"&userName="+userName+"&ruuid="+ruuid+"&fileName="+fileName+"&intervalStartTime="+intervalStartTime+"&currentTime="+currentTime+"&browserId="+browserId+"&isActive="+isActive,
success : function(msg) {
if (msg.result == "error") {
$.simpleAlert("删除失败", "error");
}
}
});
},
// 页面卸载处理
handleUnload() {
// 如果有部分停留时间但不足60秒
const partialTime = Math.floor((Date.now() - this.intervalStartTime) / 1000);
if (partialTime > 0) {
console.log(`未完成间隔的停留时间: ${partialTime}秒`);
}
const currentTime = Date.now();
// 发送总停留时间
if (this.totalStayTime > 0) {
this.sendToServer(this.totalStayTime,this.intervalStartTime,currentTime,false);
// 初始检查页面可见状态
this.isPageVisible = !document.hidden;
if (!this.isPageVisible) {
this.lastReportTime = new Date(); // 更新最后记录时间
}
}
};
// 启动追踪器
stayTimeTracker.init();
// 开始跟踪
startTracking() {
if (this.isActive) return;
this.startTime = new Date();
this.lastReportTime = this.startTime;
this.isActive = true;
// 设置定时器
this.intervalId = setInterval(() => {
if (this.isPageVisible) {
this.reportStayTime();
}
}, this.reportInterval);
// 页面卸载前发送剩余时间
window.addEventListener('beforeunload', this.finalReport.bind(this));
// 延迟绑定可见性事件(在用户首次交互后)
const bindOnInteraction = () => {
this.bindVisibilityEvents();
// 移除所有交互监听器
['click', 'scroll', 'keydown', 'mousemove', 'touchstart'].forEach(event => {
window.removeEventListener(event, bindOnInteraction);
});
};
// 添加多种交互监听
['click', 'scroll', 'keydown', 'mousemove', 'touchstart'].forEach(event => {
window.addEventListener(event, bindOnInteraction, { once: true });
});
}
// 报告停留时间
reportStayTime() {
const now = new Date();
const elapsed = now - this.lastReportTime;
this.totalStayTime += elapsed;
this.lastReportTime = now;
this.sendStayTimeToServer(elapsed, true);
}
// 最终报告
finalReport() {
if (!this.isActive) return;
if (this.isPageVisible) {
const now = new Date();
const elapsed = now - this.lastReportTime;
}
this.sendStayTimeToServer(elapsed, false);
this.cleanUp();
}
// 处理页面可见性变化
handleVisibilityChange() {
var now = new Date();
if (document.hidden) {
if (this.isPageVisible) {
this.isPageVisible = false;
// 页面不可见,暂停计时
const now = new Date();
const elapsed = now - this.lastReportTime;
this.totalStayTime += elapsed;
this.sendStayTimeToServer(elapsed, false);
clearInterval(this.intervalId);
}
} else {
// 页面恢复可见
if (!this.isPageVisible) {
this.lastReportTime = now; // 重置最后记录时间
}
this.isPageVisible = true;
}
}
// 发送数据到服务器
sendStayTimeToServer(elapsedMs,isActive) {
$.ajax({
type : "POST",
url : "./w?sid=" + encodeURIComponent($('#sid').val()) + "&cmd=com.awspaas.user.apps.browsing_data.service.insertReadingLog",
data : "userId="+userId+"&userName="+userName+"&ruuid="+ruuid+"&fileName="+fileName+"&startTime="+new Date(this.startTime).getTime()+"&currentTime="+new Date().getTime()+"&browserId="+browserId+"&isActive="+isActive,
success : function(msg) {
if (msg.result == "error") {
$.simpleAlert("新增失败", "error");
}
}
});
}
// 清理资源
cleanUp() {
clearInterval(this.intervalId);
document.removeEventListener('visibilitychange', this.handleVisibilityChange);
window.removeEventListener('beforeunload', this.finalReport);
this.isActive = false;
}
}
// 使用示例
const tracker = new PageStayTimeTracker();
tracker.startTracking();
//初始化封面模板
function initCoverTpl(){