Files
ai_english/client/lib/shared/providers/error_provider.dart

382 lines
9.8 KiB
Dart
Raw Permalink Normal View History

2025-11-17 14:09:17 +08:00
import 'package:flutter/foundation.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
/// 错误类型枚举
enum ErrorType {
network,
authentication,
validation,
server,
unknown,
}
/// 错误严重程度枚举
enum ErrorSeverity {
info,
warning,
error,
critical,
}
/// 应用错误模型
class AppError {
final String id;
final String message;
final String? details;
final ErrorType type;
final ErrorSeverity severity;
final DateTime timestamp;
final String? stackTrace;
final Map<String, dynamic>? context;
const AppError({
required this.id,
required this.message,
this.details,
required this.type,
required this.severity,
required this.timestamp,
this.stackTrace,
this.context,
});
AppError copyWith({
String? id,
String? message,
String? details,
ErrorType? type,
ErrorSeverity? severity,
DateTime? timestamp,
String? stackTrace,
Map<String, dynamic>? context,
}) {
return AppError(
id: id ?? this.id,
message: message ?? this.message,
details: details ?? this.details,
type: type ?? this.type,
severity: severity ?? this.severity,
timestamp: timestamp ?? this.timestamp,
stackTrace: stackTrace ?? this.stackTrace,
context: context ?? this.context,
);
}
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is AppError &&
other.id == id &&
other.message == message &&
other.type == type &&
other.severity == severity;
}
@override
int get hashCode {
return id.hashCode ^
message.hashCode ^
type.hashCode ^
severity.hashCode;
}
@override
String toString() {
return 'AppError(id: $id, message: $message, type: $type, severity: $severity, timestamp: $timestamp)';
}
/// 创建网络错误
factory AppError.network(String message, {String? details, Map<String, dynamic>? context}) {
return AppError(
id: DateTime.now().millisecondsSinceEpoch.toString(),
message: message,
details: details,
type: ErrorType.network,
severity: ErrorSeverity.error,
timestamp: DateTime.now(),
context: context,
);
}
/// 创建认证错误
factory AppError.authentication(String message, {String? details, Map<String, dynamic>? context}) {
return AppError(
id: DateTime.now().millisecondsSinceEpoch.toString(),
message: message,
details: details,
type: ErrorType.authentication,
severity: ErrorSeverity.error,
timestamp: DateTime.now(),
context: context,
);
}
/// 创建验证错误
factory AppError.validation(String message, {String? details, Map<String, dynamic>? context}) {
return AppError(
id: DateTime.now().millisecondsSinceEpoch.toString(),
message: message,
details: details,
type: ErrorType.validation,
severity: ErrorSeverity.warning,
timestamp: DateTime.now(),
context: context,
);
}
/// 创建服务器错误
factory AppError.server(String message, {String? details, Map<String, dynamic>? context}) {
return AppError(
id: DateTime.now().millisecondsSinceEpoch.toString(),
message: message,
details: details,
type: ErrorType.server,
severity: ErrorSeverity.error,
timestamp: DateTime.now(),
context: context,
);
}
/// 创建未知错误
factory AppError.unknown(String message, {String? details, String? stackTrace, Map<String, dynamic>? context}) {
return AppError(
id: DateTime.now().millisecondsSinceEpoch.toString(),
message: message,
details: details,
type: ErrorType.unknown,
severity: ErrorSeverity.error,
timestamp: DateTime.now(),
stackTrace: stackTrace,
context: context,
);
}
}
/// 错误状态模型
class ErrorState {
final List<AppError> errors;
final AppError? currentError;
const ErrorState({
required this.errors,
this.currentError,
});
bool get hasErrors => errors.isNotEmpty;
ErrorState copyWith({
List<AppError>? errors,
AppError? currentError,
}) {
return ErrorState(
errors: errors ?? this.errors,
currentError: currentError,
);
}
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is ErrorState &&
other.errors.length == errors.length &&
other.currentError == currentError;
}
@override
int get hashCode {
return errors.hashCode ^ currentError.hashCode;
}
}
/// 错误管理Provider
class ErrorNotifier extends StateNotifier<ErrorState> {
static const int maxErrorCount = 50; // 最大错误数量
static const Duration errorRetentionDuration = Duration(hours: 24); // 错误保留时间
ErrorNotifier() : super(const ErrorState(errors: []));
/// 添加错误
void addError(AppError error) {
final updatedErrors = List<AppError>.from(state.errors);
updatedErrors.insert(0, error); // 新错误插入到列表开头
// 限制错误数量
if (updatedErrors.length > maxErrorCount) {
updatedErrors.removeRange(maxErrorCount, updatedErrors.length);
}
// 清理过期错误
_cleanExpiredErrors(updatedErrors);
state = state.copyWith(
errors: updatedErrors,
currentError: error,
);
// 在调试模式下打印错误
if (kDebugMode) {
print('Error added: ${error.toString()}');
if (error.stackTrace != null) {
print('Stack trace: ${error.stackTrace}');
}
}
}
/// 清除当前错误
void clearCurrentError() {
state = state.copyWith(currentError: null);
}
/// 清除指定错误
void removeError(String errorId) {
final updatedErrors = state.errors.where((error) => error.id != errorId).toList();
AppError? newCurrentError = state.currentError;
if (state.currentError?.id == errorId) {
newCurrentError = null;
}
state = state.copyWith(
errors: updatedErrors,
currentError: newCurrentError,
);
}
/// 清除所有错误
void clearAllErrors() {
state = const ErrorState(errors: []);
}
/// 清除指定类型的错误
void clearErrorsByType(ErrorType type) {
final updatedErrors = state.errors.where((error) => error.type != type).toList();
AppError? newCurrentError = state.currentError;
if (state.currentError?.type == type) {
newCurrentError = null;
}
state = state.copyWith(
errors: updatedErrors,
currentError: newCurrentError,
);
}
/// 清除指定严重程度的错误
void clearErrorsBySeverity(ErrorSeverity severity) {
final updatedErrors = state.errors.where((error) => error.severity != severity).toList();
AppError? newCurrentError = state.currentError;
if (state.currentError?.severity == severity) {
newCurrentError = null;
}
state = state.copyWith(
errors: updatedErrors,
currentError: newCurrentError,
);
}
/// 获取指定类型的错误
List<AppError> getErrorsByType(ErrorType type) {
return state.errors.where((error) => error.type == type).toList();
}
/// 获取指定严重程度的错误
List<AppError> getErrorsBySeverity(ErrorSeverity severity) {
return state.errors.where((error) => error.severity == severity).toList();
}
/// 获取最近的错误
List<AppError> getRecentErrors({int count = 10}) {
return state.errors.take(count).toList();
}
/// 检查是否有指定类型的错误
bool hasErrorOfType(ErrorType type) {
return state.errors.any((error) => error.type == type);
}
/// 检查是否有指定严重程度的错误
bool hasErrorOfSeverity(ErrorSeverity severity) {
return state.errors.any((error) => error.severity == severity);
}
/// 清理过期错误
void _cleanExpiredErrors(List<AppError> errors) {
final now = DateTime.now();
errors.removeWhere((error) =>
now.difference(error.timestamp) > errorRetentionDuration);
}
/// 处理异常并转换为AppError
void handleException(dynamic exception, {
String? message,
ErrorType? type,
ErrorSeverity? severity,
Map<String, dynamic>? context,
}) {
String errorMessage = message ?? exception.toString();
ErrorType errorType = type ?? ErrorType.unknown;
ErrorSeverity errorSeverity = severity ?? ErrorSeverity.error;
String? stackTrace;
if (exception is Error) {
stackTrace = exception.stackTrace?.toString();
}
final error = AppError(
id: DateTime.now().millisecondsSinceEpoch.toString(),
message: errorMessage,
details: exception.toString(),
type: errorType,
severity: errorSeverity,
timestamp: DateTime.now(),
stackTrace: stackTrace,
context: context,
);
addError(error);
}
}
/// 错误状态Provider
final errorProvider = StateNotifierProvider<ErrorNotifier, ErrorState>(
(ref) => ErrorNotifier(),
);
/// 当前错误Provider
final currentErrorProvider = Provider<AppError?>(
(ref) => ref.watch(errorProvider).currentError,
);
/// 是否有错误Provider
final hasErrorsProvider = Provider<bool>(
(ref) => ref.watch(errorProvider).hasErrors,
);
/// 错误数量Provider
final errorCountProvider = Provider<int>(
(ref) => ref.watch(errorProvider).errors.length,
);
/// 网络错误Provider
final networkErrorsProvider = Provider<List<AppError>>(
(ref) => ref.watch(errorProvider).errors
.where((error) => error.type == ErrorType.network)
.toList(),
);
/// 认证错误Provider
final authErrorsProvider = Provider<List<AppError>>(
(ref) => ref.watch(errorProvider).errors
.where((error) => error.type == ErrorType.authentication)
.toList(),
);
/// 严重错误Provider
final criticalErrorsProvider = Provider<List<AppError>>(
(ref) => ref.watch(errorProvider).errors
.where((error) => error.severity == ErrorSeverity.critical)
.toList(),
);