From 6bf54eb8499be5a2daca01fea4ac6395b0481f00 Mon Sep 17 00:00:00 2001 From: sion <450702724@qq.com> Date: Tue, 24 Mar 2026 18:54:01 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20Flutter=20Web=20?= =?UTF-8?q?=E7=99=BD=E5=B1=8F=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - main.dart: 添加全局错误处理和 FlutterError.onError - index.html: 添加加载指示器,vconsole 仅在开发环境启用 - dio_client.dart: 添加详细错误日志,优化超时配置 Co-Authored-By: Claude Opus 4.6 --- flutter_monisuo/build/web/.last_build_id | 2 +- .../build/web/flutter_bootstrap.js | 2 +- flutter_monisuo/build/web/index.html | 94 +++++++++++++++++-- .../lib/core/network/dio_client.dart | 67 +++++++++++-- flutter_monisuo/lib/main.dart | 33 ++++++- flutter_monisuo/web/index.html | 94 +++++++++++++++++-- 6 files changed, 263 insertions(+), 29 deletions(-) diff --git a/flutter_monisuo/build/web/.last_build_id b/flutter_monisuo/build/web/.last_build_id index 551ab64..bccbcbc 100644 --- a/flutter_monisuo/build/web/.last_build_id +++ b/flutter_monisuo/build/web/.last_build_id @@ -1 +1 @@ -2b1d2ed877ca1d041aef5d6561fbfcf5 \ No newline at end of file +cd059bcd8df9e9b2b7bfff5ee9fb7ba7 \ No newline at end of file diff --git a/flutter_monisuo/build/web/flutter_bootstrap.js b/flutter_monisuo/build/web/flutter_bootstrap.js index 7bda195..1b80bae 100644 --- a/flutter_monisuo/build/web/flutter_bootstrap.js +++ b/flutter_monisuo/build/web/flutter_bootstrap.js @@ -37,6 +37,6 @@ _flutter.buildConfig = {"engineRevision":"e4b8dca3f1b4ede4c30371002441c88c12187e _flutter.loader.load({ serviceWorkerSettings: { - serviceWorkerVersion: "2873482940" /* Flutter's service worker is deprecated and will be removed in a future Flutter release. */ + serviceWorkerVersion: "1409326861" /* Flutter's service worker is deprecated and will be removed in a future Flutter release. */ } }); diff --git a/flutter_monisuo/build/web/index.html b/flutter_monisuo/build/web/index.html index aacce91..b170147 100644 --- a/flutter_monisuo/build/web/index.html +++ b/flutter_monisuo/build/web/index.html @@ -18,21 +18,79 @@ - + - + - flutter_monisuo + Monisuo + + + +
+
+
Loading...
+
+ + + - - + + + + diff --git a/flutter_monisuo/lib/core/network/dio_client.dart b/flutter_monisuo/lib/core/network/dio_client.dart index 8fede32..283a0fc 100644 --- a/flutter_monisuo/lib/core/network/dio_client.dart +++ b/flutter_monisuo/lib/core/network/dio_client.dart @@ -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 _handleError(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 diff --git a/flutter_monisuo/lib/main.dart b/flutter_monisuo/lib/main.dart index 03ff639..52a9c94 100644 --- a/flutter_monisuo/lib/main.dart +++ b/flutter_monisuo/lib/main.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'package:flutter/material.dart'; import 'package:shadcn_ui/shadcn_ui.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; @@ -21,13 +22,37 @@ import 'ui/pages/auth/login_page.dart'; import 'ui/pages/main/main_page.dart'; void main() async { + // 确保 Flutter 绑定初始化 WidgetsFlutterBinding.ensureInitialized(); - Provider.debugCheckInvalidValueType = null; - await SharedPreferences.getInstance(); - await LocalStorage.init(); + // 全局错误处理 + FlutterError.onError = (FlutterErrorDetails details) { + FlutterError.presentError(details); + debugPrint('Flutter Error: ${details.exception}'); + debugPrint('Stack trace: ${details.stack}'); + }; - runApp(const MyApp()); + // 捕获异步错误 + runZonedGuarded>( + () async { + Provider.debugCheckInvalidValueType = null; + + try { + await SharedPreferences.getInstance(); + await LocalStorage.init(); + debugPrint('App initialized successfully'); + } catch (e, stack) { + debugPrint('Initialization error: $e'); + debugPrint('Stack: $stack'); + } + + runApp(const MyApp()); + }, + (error, stack) { + debugPrint('Uncaught error: $error'); + debugPrint('Stack: $stack'); + }, + ); } class MyApp extends StatelessWidget { diff --git a/flutter_monisuo/web/index.html b/flutter_monisuo/web/index.html index 44865a9..5f2b8fb 100644 --- a/flutter_monisuo/web/index.html +++ b/flutter_monisuo/web/index.html @@ -18,21 +18,79 @@ - + - + - flutter_monisuo + Monisuo + + + +
+
+
Loading...
+
+ + + - - + + + +