Files
template-10579/src/utils/errorHandler.ts
赵忠林 ec252beb4b feat(pages): 添加管理页面功能和配置
- 创建 .editorconfig 文件统一代码风格配置
- 配置 .eslintrc 使用 taro/react 规则集
- 完善 .gitignore 忽略编译产物和敏感文件
- 添加 admin/article/add 页面实现文章管理功能
- 添加 dealer/apply/add 页面实现经销商申请功能
- 添加 dealer/bank/add 页面实现银行卡管理功能
- 添加 dealer/customer/add 页面实现客户管理功能
- 添加 user/address/add 页面实现用户地址管理功能
- 添加 user/chat/message/add 页面实现消息功能
- 添加 user/gift/add 页面实现礼品管理功能
- 配置各页面导航栏标题和样式
- 实现表单验证和数据提交功能
- 集成图片上传和头像选择功能
- 添加日期选择和数据校验逻辑
- 实现编辑和新增模式切换
- 集成用户权限和角色管理功能
2026-02-08 12:15:31 +08:00

303 lines
7.2 KiB
TypeScript
Raw 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.

import Taro from '@tarojs/taro';
// 定义本地的RequestError类避免循环依赖
export class RequestError extends Error {
public type: string;
public code?: number;
public data?: any;
constructor(message: string, type: string, code?: number, data?: any) {
super(message);
this.name = 'RequestError';
this.type = type;
this.code = code;
this.data = data;
}
}
// 错误类型枚举
export enum ErrorType {
NETWORK_ERROR = 'NETWORK_ERROR',
TIMEOUT_ERROR = 'TIMEOUT_ERROR',
BUSINESS_ERROR = 'BUSINESS_ERROR',
AUTH_ERROR = 'AUTH_ERROR',
UNKNOWN_ERROR = 'UNKNOWN_ERROR'
}
// 错误级别枚举
export enum ErrorLevel {
INFO = 'info',
WARNING = 'warning',
ERROR = 'error',
FATAL = 'fatal'
}
// 错误信息接口
export interface ErrorInfo {
message: string;
level: ErrorLevel;
type: string;
stack?: string;
extra?: any;
timestamp: number;
userId?: string;
page?: string;
}
/**
* 全局错误处理器
*/
class GlobalErrorHandler {
private static instance: GlobalErrorHandler;
private errorQueue: ErrorInfo[] = [];
private maxQueueSize = 50;
private constructor() {
this.setupGlobalErrorHandlers();
}
public static getInstance(): GlobalErrorHandler {
if (!GlobalErrorHandler.instance) {
GlobalErrorHandler.instance = new GlobalErrorHandler();
}
return GlobalErrorHandler.instance;
}
/**
* 设置全局错误处理器
*/
private setupGlobalErrorHandlers() {
// 捕获未处理的Promise rejection
if (typeof window !== 'undefined') {
window.addEventListener('unhandledrejection', (event) => {
this.handleError(event.reason, ErrorLevel.ERROR, 'UnhandledPromiseRejection');
event.preventDefault();
});
}
}
/**
* 处理错误
*/
public handleError(
error: any,
level: ErrorLevel = ErrorLevel.ERROR,
type: string = 'Unknown',
extra?: any
) {
const errorInfo = this.createErrorInfo(error, level, type, extra);
// 添加到错误队列
this.addToQueue(errorInfo);
// 根据错误级别决定处理方式
switch (level) {
case ErrorLevel.FATAL:
this.handleFatalError(errorInfo);
break;
case ErrorLevel.ERROR:
this.handleNormalError(errorInfo);
break;
case ErrorLevel.WARNING:
this.handleWarning(errorInfo);
break;
case ErrorLevel.INFO:
this.handleInfo(errorInfo);
break;
}
// 上报错误
this.reportError(errorInfo);
}
/**
* 创建错误信息对象
*/
private createErrorInfo(
error: any,
level: ErrorLevel,
type: string,
extra?: any
): ErrorInfo {
let message = '未知错误';
let stack: string | undefined;
if (error instanceof Error) {
message = error.message;
stack = error.stack;
} else if (error instanceof RequestError) {
message = error.message;
type = error.type;
extra = { ...extra, code: error.code, data: error.data };
} else if (typeof error === 'string') {
message = error;
} else if (error && typeof error === 'object') {
message = error.message || error.errMsg || JSON.stringify(error);
}
return {
message,
level,
type,
stack,
extra,
timestamp: Date.now(),
userId: Taro.getStorageSync('UserId') || undefined,
page: this.getCurrentPage()
};
}
/**
* 获取当前页面路径
*/
private getCurrentPage(): string {
try {
const pages = Taro.getCurrentPages();
const currentPage = pages[pages.length - 1];
return currentPage?.route || 'unknown';
} catch {
return 'unknown';
}
}
/**
* 添加到错误队列
*/
private addToQueue(errorInfo: ErrorInfo) {
this.errorQueue.push(errorInfo);
// 保持队列大小
if (this.errorQueue.length > this.maxQueueSize) {
this.errorQueue.shift();
}
}
/**
* 处理致命错误
*/
private handleFatalError(errorInfo: ErrorInfo) {
console.error('Fatal Error:', errorInfo);
Taro.showModal({
title: '严重错误',
content: '应用遇到严重错误,需要重启',
showCancel: false,
confirmText: '重启应用',
success: () => {
Taro.reLaunch({ url: '/pages/index/index' });
}
});
}
/**
* 处理普通错误
*/
private handleNormalError(errorInfo: ErrorInfo) {
console.error('Error:', errorInfo);
// 根据错误类型显示不同的提示
let title = '操作失败';
if (errorInfo.type === ErrorType.NETWORK_ERROR) {
title = '网络连接失败';
} else if (errorInfo.type === ErrorType.TIMEOUT_ERROR) {
title = '请求超时';
} else if (errorInfo.type === ErrorType.AUTH_ERROR) {
title = '认证失败';
}
Taro.showToast({
title: errorInfo.message || title,
icon: 'error',
duration: 2000
});
}
/**
* 处理警告
*/
private handleWarning(errorInfo: ErrorInfo) {
console.warn('Warning:', errorInfo);
// 警告通常不需要用户交互,只记录日志
}
/**
* 处理信息
*/
private handleInfo(errorInfo: ErrorInfo) {
console.info('Info:', errorInfo);
}
/**
* 上报错误到服务器
*/
private reportError(errorInfo: ErrorInfo) {
try {
// 这里可以实现错误上报逻辑
// 例如发送到后端日志系统、第三方监控服务等
// 示例:发送到后端
// request.post('/api/error/report', errorInfo).catch(() => {
// // 上报失败也不要影响用户体验
// });
// 开发环境下打印详细信息
if (process.env.NODE_ENV === 'development') {
console.group('🚨 Error Report');
console.log('Message:', errorInfo.message);
console.log('Level:', errorInfo.level);
console.log('Type:', errorInfo.type);
console.log('Page:', errorInfo.page);
console.log('UserId:', errorInfo.userId);
console.log('Timestamp:', new Date(errorInfo.timestamp).toLocaleString());
if (errorInfo.stack) {
console.log('Stack:', errorInfo.stack);
}
if (errorInfo.extra) {
console.log('Extra:', errorInfo.extra);
}
console.groupEnd();
}
} catch (reportError) {
console.error('Failed to report error:', reportError);
}
}
/**
* 获取错误队列
*/
public getErrorQueue(): ErrorInfo[] {
return [...this.errorQueue];
}
/**
* 清空错误队列
*/
public clearErrorQueue() {
this.errorQueue = [];
}
}
// 导出单例实例
export const errorHandler = GlobalErrorHandler.getInstance();
// 便捷方法
export const handleError = (error: any, level?: ErrorLevel, type?: string, extra?: any) => {
errorHandler.handleError(error, level, type, extra);
};
export const handleFatalError = (error: any, extra?: any) => {
errorHandler.handleError(error, ErrorLevel.FATAL, 'FatalError', extra);
};
export const handleWarning = (error: any, extra?: any) => {
errorHandler.handleError(error, ErrorLevel.WARNING, 'Warning', extra);
};
export const handleInfo = (message: string, extra?: any) => {
errorHandler.handleError(message, ErrorLevel.INFO, 'Info', extra);
};
export default errorHandler;