feat(ui): Enhance error handling in postData method

* Added try-catch block to handle exceptions during data posting.
* Improved logging for successful and failed requests.
* Ensured robust error reporting for better debugging.
This commit is contained in:
qianlifeng 2025-06-08 22:14:02 +08:00
parent c1a87df75b
commit c1c6ced55d
No known key found for this signature in database
2 changed files with 117 additions and 67 deletions

View File

@ -1,3 +1,4 @@
import 'package:uuid/v4.dart';
import 'package:wox/entity/wox_ai.dart';
import 'package:wox/entity/wox_backup.dart';
import 'package:wox/entity/wox_image.dart';
@ -7,73 +8,117 @@ import 'package:wox/entity/wox_preview.dart';
import 'package:wox/entity/wox_setting.dart';
import 'package:wox/entity/wox_theme.dart';
import 'package:wox/models/doctor_check_result.dart';
import 'package:wox/utils/log.dart';
/// Factory function type for creating objects from JSON
typedef JsonFactory = dynamic Function(dynamic json);
class EntityFactory {
// Single object factories
static final Map<String, JsonFactory> _singleFactories = {
'WoxTheme': (json) => WoxTheme.fromJson(json),
'WoxSetting': (json) => WoxSetting.fromJson(json),
'WoxPreview': (json) => WoxPreview.fromJson(json),
'WoxImage': (json) => WoxImage.fromJson(json),
'WoxLang': (json) => WoxLang.fromJson(json),
'PluginDetail': (json) => PluginDetail.fromJson(json),
'AIModel': (json) => AIModel.fromJson(json),
'DoctorCheckResult': (json) => DoctorCheckResult.fromJson(json),
};
// List factories
static final Map<String, JsonFactory> _listFactories = {
'List<PluginDetail>': (json) => _createList<PluginDetail>(json, (e) => PluginDetail.fromJson(e)),
'List<WoxTheme>': (json) => _createList<WoxTheme>(json, (e) => WoxTheme.fromJson(e)),
'List<AIModel>': (json) => _createList<AIModel>(json, (e) => AIModel.fromJson(e)),
'List<WoxLang>': (json) => _createList<WoxLang>(json, (e) => WoxLang.fromJson(e)),
'List<WoxBackup>': (json) => _createList<WoxBackup>(json, (e) => WoxBackup.fromJson(e)),
'List<AIMCPTool>': (json) => _createList<AIMCPTool>(json, (e) => AIMCPTool.fromJson(e)),
'List<AIProviderInfo>': (json) => _createList<AIProviderInfo>(json, (e) => AIProviderInfo.fromJson(e)),
'List<AIAgent>': (json) => _createList<AIAgent>(json, (e) => AIAgent.fromJson(e)),
'List<DoctorCheckResult>': (json) => _createList<DoctorCheckResult>(json, (e) => DoctorCheckResult.fromJson(e)),
};
/// Helper method to create typed lists from JSON with robust error handling
static List<T> _createList<T>(dynamic json, T Function(dynamic) fromJson) {
if (json == null) return <T>[];
// Ensure json is actually a List
if (json is! List) {
final traceId = const UuidV4().generate();
Logger.instance.warn(traceId, 'EntityFactory: Expected List but got ${json.runtimeType}, returning empty list');
return <T>[];
}
final List<T> result = <T>[];
for (int i = 0; i < json.length; i++) {
try {
final item = fromJson(json[i]);
result.add(item);
} catch (e) {
// Log the error but continue processing other items
final traceId = const UuidV4().generate();
Logger.instance.warn(traceId, 'EntityFactory: Failed to parse item at index $i: $e');
// Skip this item and continue with the rest
}
}
return result;
}
/// Generate object from JSON based on type T with robust error handling
static T generateOBJ<T>(dynamic json) {
// Logger.instance.debug(const UuidV4().generate(), "try to unmarshal post data, datatype=${T.toString()}");
if (T.toString() == "WoxTheme") {
return WoxTheme.fromJson(json) as T;
} else if (T.toString() == "WoxSetting") {
return WoxSetting.fromJson(json) as T;
} else if (T.toString() == "WoxPreview") {
return WoxPreview.fromJson(json) as T;
} else if (T.toString() == "WoxImage") {
return WoxImage.fromJson(json) as T;
} else if (T.toString() == "WoxLang") {
return WoxLang.fromJson(json) as T;
} else if (T.toString() == "PluginDetail") {
return PluginDetail.fromJson(json) as T;
} else if (T.toString() == "AIModel") {
return AIModel.fromJson(json) as T;
} else if (T.toString() == "DoctorCheckResult") {
return DoctorCheckResult.fromJson(json) as T;
} else if (T.toString() == "List<PluginDetail>") {
if (json == null) {
return <PluginDetail>[] as T;
final typeName = T.toString();
try {
// Try single object factories first
final singleFactory = _singleFactories[typeName];
if (singleFactory != null) {
return singleFactory(json) as T;
}
return (json as List).map((e) => PluginDetail.fromJson(e)).toList() as T;
} else if (T.toString() == "List<WoxTheme>") {
if (json == null) {
return <WoxTheme>[] as T;
// Try list factories
final listFactory = _listFactories[typeName];
if (listFactory != null) {
return listFactory(json) as T;
}
return (json as List).map((e) => WoxTheme.fromJson(e)).toList() as T;
} else if (T.toString() == "List<AIModel>") {
if (json == null) {
return <AIModel>[] as T;
}
return (json as List).map((e) => AIModel.fromJson(e)).toList() as T;
} else if (T.toString() == "List<WoxLang>") {
if (json == null) {
return <WoxLang>[] as T;
}
return (json as List).map((e) => WoxLang.fromJson(e)).toList() as T;
} else if (T.toString() == "List<WoxBackup>") {
if (json == null) {
return <WoxBackup>[] as T;
}
return (json as List).map((e) => WoxBackup.fromJson(e)).toList() as T;
} else if (T.toString() == "List<AIMCPTool>") {
if (json == null) {
return <AIMCPTool>[] as T;
}
return (json as List).map((e) => AIMCPTool.fromJson(e)).toList() as T;
} else if (T.toString() == "List<AIProviderInfo>") {
if (json == null) {
return <AIProviderInfo>[] as T;
}
return (json as List).map((e) => AIProviderInfo.fromJson(e)).toList() as T;
} else if (T.toString() == "List<AIAgent>") {
if (json == null) {
return <AIAgent>[] as T;
}
return (json as List).map((e) => AIAgent.fromJson(e)).toList() as T;
} else if (T.toString() == "List<DoctorCheckResult>") {
if (json == null) {
return <DoctorCheckResult>[] as T;
}
return (json as List).map((e) => DoctorCheckResult.fromJson(e)).toList() as T;
} else {
// Fallback to direct casting for primitive types
return json as T;
} catch (e) {
final traceId = const UuidV4().generate();
Logger.instance.error(traceId, 'EntityFactory: Failed to generate object of type $typeName: $e');
// Return safe default values based on type
return _getSafeDefault<T>();
}
}
/// Get safe default value for type T
static T _getSafeDefault<T>() {
final typeName = T.toString();
// Handle list types
if (typeName.startsWith('List<')) {
return <dynamic>[] as T;
}
// Handle common primitive types
switch (typeName) {
case 'String':
return '' as T;
case 'int':
return 0 as T;
case 'double':
return 0.0 as T;
case 'bool':
return false as T;
case 'Map<String, dynamic>':
return <String, dynamic>{} as T;
default:
// For complex objects, return null and let the caller handle it
return null as T;
}
}
}

View File

@ -28,11 +28,16 @@ class WoxHttpUtil {
}
Future<T> postData<T>(String url, dynamic data) async {
final traceId = const UuidV4().generate();
Logger.instance.info(traceId, 'Posting data to $_baseUrl$url');
final response = await _dio.post(_baseUrl + url, data: data);
WoxResponse woxResponse = WoxResponse.fromJson(response.data);
if (woxResponse.success == false) throw Exception(woxResponse.message);
return EntityFactory.generateOBJ<T>(woxResponse.data);
try {
final traceId = const UuidV4().generate();
Logger.instance.info(traceId, 'Posting data to $_baseUrl$url');
final response = await _dio.post(_baseUrl + url, data: data);
WoxResponse woxResponse = WoxResponse.fromJson(response.data);
if (woxResponse.success == false) throw Exception(woxResponse.message);
return EntityFactory.generateOBJ<T>(woxResponse.data);
} catch (e) {
Logger.instance.error(const UuidV4().generate(), 'Failed to post data: $e');
rethrow;
}
}
}