This commit is contained in:
ChuXun
2025-10-19 20:28:31 +08:00
parent c81f8a8b03
commit eaab9a762a
100 changed files with 23416 additions and 0 deletions

310
utils/logger.js Normal file
View File

@@ -0,0 +1,310 @@
/**
* 日志管理系统
* 提供分级日志记录、错误追踪、性能监控
*/
class Logger {
constructor() {
this.logs = []
this.maxLogs = 1000 // 最多保存1000条日志
this.level = 'info' // debug, info, warn, error
this.enableConsole = true
this.enableStorage = true
}
/**
* 日志级别枚举
*/
static LEVELS = {
DEBUG: 0,
INFO: 1,
WARN: 2,
ERROR: 3
}
/**
* 记录调试信息
*/
debug(message, data = {}) {
this._log('DEBUG', message, data)
}
/**
* 记录普通信息
*/
info(message, data = {}) {
this._log('INFO', message, data)
}
/**
* 记录警告信息
*/
warn(message, data = {}) {
this._log('WARN', message, data)
}
/**
* 记录错误信息
*/
error(message, data = {}) {
this._log('ERROR', message, data)
}
/**
* 核心日志方法
*/
_log(level, message, data) {
const log = {
level,
message,
data,
timestamp: new Date().toISOString(),
page: getCurrentPages().length > 0 ? getCurrentPages()[getCurrentPages().length - 1].route : 'unknown'
}
// 添加到内存
this.logs.push(log)
if (this.logs.length > this.maxLogs) {
this.logs.shift()
}
// 输出到控制台
if (this.enableConsole) {
const consoleMethod = level.toLowerCase()
console[consoleMethod](`[${level}] ${message}`, data)
}
// 保存到本地存储
if (this.enableStorage && level === 'ERROR') {
this._persistErrorLog(log)
}
// 上报严重错误
if (level === 'ERROR') {
this._reportError(log)
}
}
/**
* 持久化错误日志
*/
_persistErrorLog(log) {
try {
const errorLogs = wx.getStorageSync('errorLogs') || []
errorLogs.push(log)
// 只保留最近100条错误
if (errorLogs.length > 100) {
errorLogs.shift()
}
wx.setStorageSync('errorLogs', errorLogs)
} catch (e) {
console.error('日志持久化失败:', e)
}
}
/**
* 上报错误
*/
_reportError(log) {
// TODO: 接入错误监控平台(如 Sentry
console.log('错误上报:', log)
}
/**
* 获取日志
*/
getLogs(filter = {}) {
let logs = this.logs
if (filter.level) {
logs = logs.filter(log => log.level === filter.level)
}
if (filter.page) {
logs = logs.filter(log => log.page === filter.page)
}
if (filter.startTime) {
logs = logs.filter(log => new Date(log.timestamp) >= new Date(filter.startTime))
}
return logs
}
/**
* 清空日志
*/
clearLogs() {
this.logs = []
wx.removeStorageSync('errorLogs')
}
/**
* 导出日志
*/
exportLogs() {
return {
logs: this.logs,
exportTime: new Date().toISOString(),
systemInfo: wx.getSystemInfoSync()
}
}
}
/**
* 错误处理器
*/
class ErrorHandler {
constructor() {
this.logger = new Logger()
this.setupGlobalErrorHandler()
}
/**
* 设置全局错误捕获
*/
setupGlobalErrorHandler() {
// 捕获未处理的Promise错误
wx.onUnhandledRejection((res) => {
this.handleError('UnhandledRejection', res.reason)
})
// 捕获小程序错误
wx.onError((error) => {
this.handleError('AppError', error)
})
}
/**
* 处理错误
*/
handleError(type, error, context = {}) {
const errorInfo = {
type,
message: error.message || error,
stack: error.stack || '',
context,
userAgent: wx.getSystemInfoSync(),
timestamp: Date.now()
}
this.logger.error(`${type}: ${errorInfo.message}`, errorInfo)
// 显示用户友好的错误提示
this.showUserFriendlyError(type, error)
return errorInfo
}
/**
* 显示用户友好的错误提示
*/
showUserFriendlyError(type, error) {
const errorMessages = {
'NetworkError': '网络连接失败,请检查网络设置',
'StorageError': '存储空间不足,请清理缓存',
'UnhandledRejection': '操作失败,请重试',
'AppError': '应用出现异常,请重启小程序'
}
const message = errorMessages[type] || '操作失败,请稍后重试'
wx.showToast({
title: message,
icon: 'none',
duration: 3000
})
}
/**
* 性能监控
*/
monitorPerformance(name, startTime) {
const duration = Date.now() - startTime
if (duration > 1000) {
this.logger.warn(`性能警告: ${name} 耗时 ${duration}ms`)
}
return duration
}
/**
* 获取错误统计
*/
getErrorStats() {
const errorLogs = wx.getStorageSync('errorLogs') || []
const stats = {
total: errorLogs.length,
byType: {},
byPage: {},
recent: errorLogs.slice(-10)
}
errorLogs.forEach(log => {
stats.byType[log.data.type] = (stats.byType[log.data.type] || 0) + 1
stats.byPage[log.page] = (stats.byPage[log.page] || 0) + 1
})
return stats
}
}
// 创建全局实例
const logger = new Logger()
const errorHandler = new ErrorHandler()
/**
* 用户反馈系统
*/
class FeedbackSystem {
/**
* 提交反馈
*/
static submit(feedback) {
const feedbackData = {
...feedback,
timestamp: Date.now(),
systemInfo: wx.getSystemInfoSync(),
logs: logger.getLogs({ level: 'ERROR' }).slice(-20)
}
logger.info('用户反馈', feedbackData)
// TODO: 上传到服务器
this._saveLocal(feedbackData)
return feedbackData
}
/**
* 保存到本地
*/
static _saveLocal(feedback) {
try {
const feedbacks = wx.getStorageSync('userFeedbacks') || []
feedbacks.push(feedback)
wx.setStorageSync('userFeedbacks', feedbacks)
} catch (e) {
console.error('反馈保存失败:', e)
}
}
/**
* 获取反馈列表
*/
static getList() {
return wx.getStorageSync('userFeedbacks') || []
}
}
module.exports = {
logger,
errorHandler,
Logger,
ErrorHandler,
FeedbackSystem
}