guanghulab/modules/m-channel/channel-analytics.js
2026-05-10 13:12:44 +08:00

179 lines
5.9 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 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('🗑️ 所有分析数据已清除');
}
};
})();