- 在header.php中添加用户角色检测,传递给前端JavaScript - 更新Open Sans字体CSS文件,支持本地woff2字体文件备用 - 修改footer.php中MathJax 3/2和KaTeX加载机制,添加onerror备用处理 - 优化resource-loader.js日志系统,使用ArgonLogger替代console.log - 仅管理员用户显示控制台日志,普通用户和游客不显示调试信息 - 完善资源加载错误处理,统一使用ArgonLogger记录警告信息
266 lines
8.7 KiB
JavaScript
266 lines
8.7 KiB
JavaScript
/* Argon 内部日志系统 - 仅管理员可见 */
|
||
(function() {
|
||
'use strict';
|
||
|
||
window.ArgonLogger = {
|
||
// 配置
|
||
config: {
|
||
maxLogs: 1000,
|
||
enableConsole: false, // 默认关闭控制台输出
|
||
enableStorage: true,
|
||
storageKey: 'argon_internal_logs'
|
||
},
|
||
|
||
// 日志级别
|
||
levels: {
|
||
DEBUG: 0,
|
||
INFO: 1,
|
||
WARN: 2,
|
||
ERROR: 3,
|
||
CRITICAL: 4
|
||
},
|
||
|
||
// 内部日志存储
|
||
logs: [],
|
||
|
||
// 初始化
|
||
init: function() {
|
||
this.checkAdminStatus();
|
||
this.loadStoredLogs();
|
||
this.bindEvents();
|
||
},
|
||
|
||
// 检查管理员状态
|
||
checkAdminStatus: function() {
|
||
// 检查是否为管理员(通过PHP传递的全局变量)
|
||
if (typeof window.argonUserRole !== 'undefined' && window.argonUserRole === 'administrator') {
|
||
this.config.enableConsole = true;
|
||
this.log('管理员模式:控制台日志已启用', 'INFO');
|
||
} else {
|
||
this.config.enableConsole = false;
|
||
}
|
||
},
|
||
|
||
// 加载存储的日志
|
||
loadStoredLogs: function() {
|
||
if (this.config.enableStorage && localStorage) {
|
||
try {
|
||
var stored = localStorage.getItem(this.config.storageKey);
|
||
if (stored) {
|
||
this.logs = JSON.parse(stored);
|
||
}
|
||
} catch (e) {
|
||
// 静默处理存储错误
|
||
}
|
||
}
|
||
},
|
||
|
||
// 保存日志到存储
|
||
saveLogsToStorage: function() {
|
||
if (this.config.enableStorage && localStorage) {
|
||
try {
|
||
// 只保留最新的日志
|
||
var logsToSave = this.logs.slice(-this.config.maxLogs);
|
||
localStorage.setItem(this.config.storageKey, JSON.stringify(logsToSave));
|
||
} catch (e) {
|
||
// 静默处理存储错误
|
||
}
|
||
}
|
||
},
|
||
|
||
// 记录日志
|
||
log: function(message, level, data) {
|
||
level = level || 'INFO';
|
||
var timestamp = new Date().toISOString();
|
||
var logEntry = {
|
||
timestamp: timestamp,
|
||
level: level,
|
||
message: message,
|
||
data: data || null,
|
||
url: window.location.href,
|
||
userAgent: navigator.userAgent.substring(0, 100) // 截取前100字符
|
||
};
|
||
|
||
// 添加到内部日志
|
||
this.logs.push(logEntry);
|
||
|
||
// 限制日志数量
|
||
if (this.logs.length > this.config.maxLogs) {
|
||
this.logs = this.logs.slice(-this.config.maxLogs);
|
||
}
|
||
|
||
// 保存到存储
|
||
this.saveLogsToStorage();
|
||
|
||
// 仅管理员显示控制台日志
|
||
if (this.config.enableConsole) {
|
||
var consoleMethod = this.getConsoleMethod(level);
|
||
consoleMethod('[Argon] ' + message, data || '');
|
||
}
|
||
|
||
// 关键错误需要特殊处理
|
||
if (level === 'CRITICAL') {
|
||
this.handleCriticalError(logEntry);
|
||
}
|
||
},
|
||
|
||
// 获取对应的控制台方法
|
||
getConsoleMethod: function(level) {
|
||
switch (level) {
|
||
case 'DEBUG':
|
||
return console.debug || console.log;
|
||
case 'INFO':
|
||
return console.info || console.log;
|
||
case 'WARN':
|
||
return console.warn || console.log;
|
||
case 'ERROR':
|
||
case 'CRITICAL':
|
||
return console.error || console.log;
|
||
default:
|
||
return console.log;
|
||
}
|
||
},
|
||
|
||
// 处理关键错误
|
||
handleCriticalError: function(logEntry) {
|
||
// 关键错误需要通知用户联系站长
|
||
if (this.config.enableConsole) {
|
||
console.error('发生关键错误,请联系站长处理:', logEntry.message);
|
||
}
|
||
|
||
// 可以在这里添加错误上报逻辑
|
||
this.reportCriticalError(logEntry);
|
||
},
|
||
|
||
// 上报关键错误
|
||
reportCriticalError: function(logEntry) {
|
||
// 这里可以实现错误上报到服务器的逻辑
|
||
// 暂时只记录到本地存储
|
||
try {
|
||
var criticalLogs = JSON.parse(localStorage.getItem('argon_critical_errors') || '[]');
|
||
criticalLogs.push(logEntry);
|
||
localStorage.setItem('argon_critical_errors', JSON.stringify(criticalLogs.slice(-50)));
|
||
} catch (e) {
|
||
// 静默处理
|
||
}
|
||
},
|
||
|
||
// 获取日志(仅管理员)
|
||
getLogs: function(level, limit) {
|
||
if (!this.config.enableConsole) {
|
||
return []; // 非管理员返回空数组
|
||
}
|
||
|
||
var filteredLogs = this.logs;
|
||
|
||
if (level) {
|
||
filteredLogs = this.logs.filter(function(log) {
|
||
return log.level === level;
|
||
});
|
||
}
|
||
|
||
if (limit) {
|
||
filteredLogs = filteredLogs.slice(-limit);
|
||
}
|
||
|
||
return filteredLogs;
|
||
},
|
||
|
||
// 清除日志(仅管理员)
|
||
clearLogs: function() {
|
||
if (!this.config.enableConsole) {
|
||
return false;
|
||
}
|
||
|
||
this.logs = [];
|
||
if (localStorage) {
|
||
localStorage.removeItem(this.config.storageKey);
|
||
localStorage.removeItem('argon_critical_errors');
|
||
}
|
||
return true;
|
||
},
|
||
|
||
// 导出日志(仅管理员)
|
||
exportLogs: function() {
|
||
if (!this.config.enableConsole) {
|
||
return null;
|
||
}
|
||
|
||
var exportData = {
|
||
timestamp: new Date().toISOString(),
|
||
site: window.location.origin,
|
||
logs: this.logs,
|
||
criticalErrors: JSON.parse(localStorage.getItem('argon_critical_errors') || '[]')
|
||
};
|
||
|
||
return JSON.stringify(exportData, null, 2);
|
||
},
|
||
|
||
// 绑定事件
|
||
bindEvents: function() {
|
||
var self = this;
|
||
|
||
// 监听页面错误
|
||
window.addEventListener('error', function(e) {
|
||
self.log('JavaScript错误: ' + e.message, 'ERROR', {
|
||
filename: e.filename,
|
||
lineno: e.lineno,
|
||
colno: e.colno,
|
||
stack: e.error ? e.error.stack : null
|
||
});
|
||
});
|
||
|
||
// 监听未处理的Promise拒绝
|
||
window.addEventListener('unhandledrejection', function(e) {
|
||
self.log('未处理的Promise拒绝: ' + e.reason, 'ERROR', {
|
||
reason: e.reason,
|
||
promise: e.promise
|
||
});
|
||
});
|
||
|
||
// 监听资源加载错误
|
||
window.addEventListener('error', function(e) {
|
||
if (e.target && e.target !== window) {
|
||
var resourceType = e.target.tagName || 'unknown';
|
||
var resourceUrl = e.target.src || e.target.href || 'unknown';
|
||
self.log('资源加载失败: ' + resourceType + ' - ' + resourceUrl, 'WARN');
|
||
}
|
||
}, true);
|
||
},
|
||
|
||
// 便捷方法
|
||
debug: function(message, data) {
|
||
this.log(message, 'DEBUG', data);
|
||
},
|
||
|
||
info: function(message, data) {
|
||
this.log(message, 'INFO', data);
|
||
},
|
||
|
||
warn: function(message, data) {
|
||
this.log(message, 'WARN', data);
|
||
},
|
||
|
||
error: function(message, data) {
|
||
this.log(message, 'ERROR', data);
|
||
},
|
||
|
||
critical: function(message, data) {
|
||
this.log(message, 'CRITICAL', data);
|
||
}
|
||
};
|
||
|
||
// 自动初始化
|
||
if (document.readyState === 'loading') {
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
ArgonLogger.init();
|
||
});
|
||
} else {
|
||
ArgonLogger.init();
|
||
}
|
||
|
||
// 为管理员提供全局访问
|
||
if (typeof window.argonUserRole !== 'undefined' && window.argonUserRole === 'administrator') {
|
||
window.ArgonLogs = ArgonLogger;
|
||
}
|
||
})(); |