179 lines
5.9 KiB
JavaScript
179 lines
5.9 KiB
JavaScript
/**
|
||
* channel-analytics.js
|
||
* 频道数据采集核心·环节8 + 环节9设置联动
|
||
* 记录模块访问次数、停留时间、页面加载速度
|
||
*/
|
||
|
||
const ChannelAnalytics = (function() {
|
||
const STORAGE_KEY = 'channel-analytics-data';
|
||
|
||
// 数据结构初始化
|
||
function getDefaultData() {
|
||
return {
|
||
modules: {}, // {moduleId: {visits: 0, totalDuration: 0, loadTimes: [], dailyVisits: {} }}
|
||
globalDaily: {}, // {'YYYY-MM-DD': totalVisits}
|
||
lastUpdated: null
|
||
};
|
||
}
|
||
|
||
// localStorage 读写
|
||
function loadData() {
|
||
try {
|
||
const raw = localStorage.getItem(STORAGE_KEY);
|
||
if (raw) return JSON.parse(raw);
|
||
} catch(e) {
|
||
console.log('⚠️ 读取分析数据失败,重新初始化');
|
||
}
|
||
return getDefaultData();
|
||
}
|
||
|
||
function saveData(data) {
|
||
data.lastUpdated = new Date().toISOString();
|
||
localStorage.setItem(STORAGE_KEY, JSON.stringify(data));
|
||
}
|
||
|
||
// 日期工具
|
||
function today() {
|
||
return new Date().toISOString().split('T')[0];
|
||
}
|
||
|
||
// 确保模块数据结构存在
|
||
function ensureModule(data, moduleId) {
|
||
if (!data.modules[moduleId]) {
|
||
data.modules[moduleId] = {
|
||
visits: 0,
|
||
totalDuration: 0,
|
||
loadTimes: [],
|
||
dailyVisits: {}
|
||
};
|
||
}
|
||
return data.modules[moduleId];
|
||
}
|
||
|
||
// 当前会话状态
|
||
let currentModule = null;
|
||
let enterTime = null;
|
||
let loadStartTime = null;
|
||
|
||
// 公开方法
|
||
return {
|
||
// 记录模块访问(环节9:检查数据采集开关)
|
||
recordVisit: function(moduleId) {
|
||
// 数据采集开关检查(环节9新增)
|
||
if (typeof ChannelSettings !== 'undefined' && !ChannelSettings.get('analyticsEnabled')) {
|
||
console.log('📊 数据采集已关闭(设置中心)');
|
||
return;
|
||
}
|
||
if (!moduleId) return;
|
||
const data = loadData();
|
||
const mod = ensureModule(data, moduleId);
|
||
|
||
// 访问计数 +1
|
||
mod.visits++;
|
||
|
||
// 每日访问计数
|
||
const d = today();
|
||
mod.dailyVisits[d] = (mod.dailyVisits[d] || 0) + 1;
|
||
|
||
// 全局每日访问
|
||
data.globalDaily[d] = (data.globalDaily[d] || 0) + 1;
|
||
|
||
saveData(data);
|
||
console.log('📊 已记录:模块 ' + moduleId + ' 被访问,累计 ' + mod.visits + ' 次');
|
||
|
||
// 记录进入时间
|
||
this.startSession(moduleId);
|
||
},
|
||
|
||
// 开始计时
|
||
startSession: function(moduleId) {
|
||
// 先结束上一个模块的计时
|
||
if (currentModule && enterTime) {
|
||
this.endSession();
|
||
}
|
||
currentModule = moduleId;
|
||
enterTime = performance.now();
|
||
loadStartTime = performance.now();
|
||
},
|
||
|
||
// 结束计时(切换模块或离开时调用)
|
||
endSession: function() {
|
||
if (!currentModule || !enterTime) return;
|
||
// 数据采集开关检查(环节9新增)
|
||
if (typeof ChannelSettings !== 'undefined' && !ChannelSettings.get('analyticsEnabled')) {
|
||
// 如果关闭采集,清空当前会话但不记录
|
||
currentModule = null;
|
||
enterTime = null;
|
||
return;
|
||
}
|
||
const duration = Math.round((performance.now() - enterTime) / 1000); // 秒
|
||
const data = loadData();
|
||
const mod = ensureModule(data, currentModule);
|
||
mod.totalDuration += duration;
|
||
saveData(data);
|
||
console.log('⏱️ 停留时间:模块 ' + currentModule + ' 停留约 ' + duration + ' 秒');
|
||
currentModule = null;
|
||
enterTime = null;
|
||
},
|
||
|
||
// 记录加载性能
|
||
recordLoadTime: function(moduleId, loadTimeMs) {
|
||
if (!moduleId) return;
|
||
// 数据采集开关检查(环节9新增)
|
||
if (typeof ChannelSettings !== 'undefined' && !ChannelSettings.get('analyticsEnabled')) {
|
||
return;
|
||
}
|
||
const data = loadData();
|
||
const mod = ensureModule(data, moduleId);
|
||
mod.loadTimes.push(loadTimeMs);
|
||
// 只保留最近50次
|
||
if (mod.loadTimes.length > 50) {
|
||
mod.loadTimes = mod.loadTimes.slice(-50);
|
||
}
|
||
saveData(data);
|
||
console.log('⚡ 加载耗时:模块 ' + moduleId + ' 加载 ' + Math.round(loadTimeMs) + ' 毫秒');
|
||
},
|
||
|
||
// 标记加载开始
|
||
markLoadStart: function() {
|
||
loadStartTime = performance.now();
|
||
},
|
||
|
||
// 标记加载完成并记录
|
||
markLoadEnd: function(moduleId) {
|
||
if (loadStartTime && moduleId) {
|
||
const loadTime = performance.now() - loadStartTime;
|
||
this.recordLoadTime(moduleId, loadTime);
|
||
loadStartTime = null;
|
||
}
|
||
},
|
||
|
||
// 获取所有数据(面板用)
|
||
getAllData: function() {
|
||
return loadData();
|
||
},
|
||
|
||
// 获取最近7天趋势
|
||
getWeeklyTrend: function() {
|
||
const data = loadData();
|
||
const trend = [];
|
||
for (let i = 6; i >= 0; i--) {
|
||
const d = new Date();
|
||
d.setDate(d.getDate() - i);
|
||
const dateStr = d.toISOString().split('T')[0];
|
||
trend.push({
|
||
date: dateStr,
|
||
visits: data.globalDaily[dateStr] || 0
|
||
});
|
||
}
|
||
return trend;
|
||
},
|
||
|
||
// 清除所有数据(调试用)
|
||
clearAll: function() {
|
||
localStorage.removeItem(STORAGE_KEY);
|
||
console.log('🗑️ 所有分析数据已清除');
|
||
}
|
||
};
|
||
})();
|