fix: 修复 Flutter Web 白屏问题
- main.dart: 添加全局错误处理和 FlutterError.onError - index.html: 添加加载指示器,vconsole 仅在开发环境启用 - dio_client.dart: 添加详细错误日志,优化超时配置 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import '../constants/api_endpoints.dart';
|
||||
import '../storage/local_storage.dart';
|
||||
import 'api_exception.dart';
|
||||
@@ -7,8 +8,9 @@ import 'api_response.dart';
|
||||
/// 网络配置常量
|
||||
class NetworkConfig {
|
||||
static const String baseUrl = ApiEndpoints.baseUrl;
|
||||
static const Duration connectTimeout = Duration(seconds: 30);
|
||||
static const Duration receiveTimeout = Duration(seconds: 30);
|
||||
static const Duration connectTimeout = Duration(seconds: 15);
|
||||
static const Duration receiveTimeout = Duration(seconds: 15);
|
||||
static const Duration sendTimeout = Duration(seconds: 15);
|
||||
}
|
||||
|
||||
/// Dio 网络客户端
|
||||
@@ -18,6 +20,7 @@ class DioClient {
|
||||
DioClient() {
|
||||
_dio = _createDio();
|
||||
_setupInterceptors();
|
||||
debugPrint('DioClient initialized with baseUrl: ${NetworkConfig.baseUrl}');
|
||||
}
|
||||
|
||||
Dio _createDio() {
|
||||
@@ -25,6 +28,7 @@ class DioClient {
|
||||
baseUrl: NetworkConfig.baseUrl,
|
||||
connectTimeout: NetworkConfig.connectTimeout,
|
||||
receiveTimeout: NetworkConfig.receiveTimeout,
|
||||
sendTimeout: NetworkConfig.sendTimeout,
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
));
|
||||
}
|
||||
@@ -32,11 +36,7 @@ class DioClient {
|
||||
void _setupInterceptors() {
|
||||
_dio.interceptors.addAll([
|
||||
_AuthInterceptor(),
|
||||
LogInterceptor(
|
||||
requestHeader: false,
|
||||
responseHeader: false,
|
||||
error: true,
|
||||
),
|
||||
_LoggingInterceptor(),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -80,6 +80,15 @@ class DioClient {
|
||||
}
|
||||
|
||||
ApiResponse<T> _handleError<T>(DioException e) {
|
||||
// 详细错误日志
|
||||
debugPrint('=== Network Error ===');
|
||||
debugPrint('Type: ${e.type}');
|
||||
debugPrint('Message: ${e.message}');
|
||||
debugPrint('URL: ${e.requestOptions.uri}');
|
||||
debugPrint('StatusCode: ${e.response?.statusCode}');
|
||||
debugPrint('ResponseData: ${e.response?.data}');
|
||||
debugPrint('====================');
|
||||
|
||||
if (_isUnauthorized(e)) {
|
||||
_clearUserData();
|
||||
return ApiResponse.unauthorized('登录已过期,请重新登录');
|
||||
@@ -106,15 +115,55 @@ class DioClient {
|
||||
case DioExceptionType.receiveTimeout:
|
||||
return '响应超时,请重试';
|
||||
case DioExceptionType.connectionError:
|
||||
return '网络连接失败';
|
||||
return '网络连接失败,请检查网络设置';
|
||||
case DioExceptionType.badResponse:
|
||||
return '服务器错误 (${e.response?.statusCode})';
|
||||
final statusCode = e.response?.statusCode;
|
||||
if (statusCode == 500) {
|
||||
return '服务器内部错误';
|
||||
} else if (statusCode == 502 || statusCode == 503) {
|
||||
return '服务暂时不可用';
|
||||
}
|
||||
return '服务器错误 ($statusCode)';
|
||||
default:
|
||||
return e.message ?? '网络请求失败';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 日志拦截器
|
||||
class _LoggingInterceptor extends Interceptor {
|
||||
@override
|
||||
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
|
||||
debugPrint('┌──────────────────────────────────────────────────────────');
|
||||
debugPrint('│ REQUEST: ${options.method} ${options.uri}');
|
||||
debugPrint('│ Headers: ${options.headers}');
|
||||
if (options.data != null) {
|
||||
debugPrint('│ Data: ${options.data}');
|
||||
}
|
||||
debugPrint('└──────────────────────────────────────────────────────────');
|
||||
super.onRequest(options, handler);
|
||||
}
|
||||
|
||||
@override
|
||||
void onResponse(Response response, ResponseInterceptorHandler handler) {
|
||||
debugPrint('┌──────────────────────────────────────────────────────────');
|
||||
debugPrint('│ RESPONSE: ${response.statusCode} ${response.requestOptions.uri}');
|
||||
debugPrint('│ Data: ${response.data}');
|
||||
debugPrint('└──────────────────────────────────────────────────────────');
|
||||
super.onResponse(response, handler);
|
||||
}
|
||||
|
||||
@override
|
||||
void onError(DioException err, ErrorInterceptorHandler handler) {
|
||||
debugPrint('┌──────────────────────────────────────────────────────────');
|
||||
debugPrint('│ ERROR: ${err.type} ${err.requestOptions.uri}');
|
||||
debugPrint('│ Message: ${err.message}');
|
||||
debugPrint('│ StatusCode: ${err.response?.statusCode}');
|
||||
debugPrint('└──────────────────────────────────────────────────────────');
|
||||
super.onError(err, handler);
|
||||
}
|
||||
}
|
||||
|
||||
/// 认证拦截器
|
||||
class _AuthInterceptor extends Interceptor {
|
||||
@override
|
||||
|
||||
Reference in New Issue
Block a user