|
|
@@ -1,6 +1,5 @@
|
|
|
import 'package:chicken_farm/core/api/api_option.dart';
|
|
|
import 'package:chicken_farm/core/services/navigation_service.dart';
|
|
|
-import 'package:chicken_farm/core/services/sync_service.dart';
|
|
|
import 'package:chicken_farm/core/utils/logger.dart';
|
|
|
import 'package:chicken_farm/core/utils/toast.dart';
|
|
|
import 'package:chicken_farm/routes/app_routes.dart';
|
|
|
@@ -105,7 +104,7 @@ class ApiService {
|
|
|
}
|
|
|
|
|
|
// 新增支持离线操作的POST方法
|
|
|
- Future<dynamic> postWithOfflineSupport(
|
|
|
+ Future<ApiOfflineModel> postWithOfflineSupport(
|
|
|
String path, {
|
|
|
dynamic data,
|
|
|
Map<String, dynamic>? queryParameters,
|
|
|
@@ -116,17 +115,12 @@ class ApiService {
|
|
|
// 先检查是否有待上传的数据,如果有则直接保存到离线队列
|
|
|
final pendingOps = await OfflineStorageService().getPendingOperations();
|
|
|
if (pendingOps.isNotEmpty) {
|
|
|
- // 有待上传数据,直接保存到队列
|
|
|
final result = await _saveOfflineOperation(path, 'POST', data);
|
|
|
- // 触发同步流程
|
|
|
- _triggerSync();
|
|
|
- // 返回特殊标识表示已保存到离线队列
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
- // 没有待上传数据,尝试直接发送请求
|
|
|
try {
|
|
|
- return await post(
|
|
|
+ final result = await post(
|
|
|
path,
|
|
|
data: data,
|
|
|
queryParameters: queryParameters,
|
|
|
@@ -134,20 +128,21 @@ class ApiService {
|
|
|
options: options,
|
|
|
cancelToken: cancelToken,
|
|
|
);
|
|
|
+ return ApiOfflineModel.onLine(result);
|
|
|
} catch (e) {
|
|
|
// 如果是网络错误,保存到离线队列
|
|
|
+ logger.e('请求错误: $e');
|
|
|
if (_isNetworkError(e)) {
|
|
|
final result = await _saveOfflineOperation(path, 'POST', data);
|
|
|
-
|
|
|
- // 返回特殊标识表示已保存到离线队列
|
|
|
return result;
|
|
|
+ } else {
|
|
|
+ rethrow;
|
|
|
}
|
|
|
- rethrow;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 新增支持离线操作的PUT方法
|
|
|
- Future<dynamic> putWithOfflineSupport(
|
|
|
+ Future<ApiOfflineModel> putWithOfflineSupport(
|
|
|
String path, {
|
|
|
dynamic data,
|
|
|
Map<String, dynamic>? queryParameters,
|
|
|
@@ -160,15 +155,13 @@ class ApiService {
|
|
|
if (pendingOps.isNotEmpty) {
|
|
|
// 有待上传数据,直接保存到队列
|
|
|
final result = await _saveOfflineOperation(path, 'PUT', data);
|
|
|
- // 触发同步流程
|
|
|
- _triggerSync();
|
|
|
// 返回特殊标识表示已保存到离线队列
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
// 没有待上传数据,尝试直接发送请求
|
|
|
try {
|
|
|
- return await put(
|
|
|
+ final result = put(
|
|
|
path,
|
|
|
data: data,
|
|
|
queryParameters: queryParameters,
|
|
|
@@ -176,20 +169,22 @@ class ApiService {
|
|
|
options: options,
|
|
|
cancelToken: cancelToken,
|
|
|
);
|
|
|
+ return ApiOfflineModel.onLine(result);
|
|
|
} catch (e) {
|
|
|
// 如果是网络错误,保存到离线队列
|
|
|
+ logger.e('请求错误: $e');
|
|
|
if (_isNetworkError(e)) {
|
|
|
final result = await _saveOfflineOperation(path, 'PUT', data);
|
|
|
-
|
|
|
// 返回特殊标识表示已保存到离线队列
|
|
|
return result;
|
|
|
+ } else {
|
|
|
+ rethrow;
|
|
|
}
|
|
|
- rethrow;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// 创建并保存离线操作的通用方法
|
|
|
- Future<Map<String, dynamic>> _saveOfflineOperation(
|
|
|
+ Future<ApiOfflineModel> _saveOfflineOperation(
|
|
|
String endpoint,
|
|
|
String method,
|
|
|
dynamic data,
|
|
|
@@ -204,14 +199,15 @@ class ApiService {
|
|
|
|
|
|
final storageService = OfflineStorageService();
|
|
|
await storageService.saveOperation(offlineOp);
|
|
|
-
|
|
|
- return {'offline_saved': true, 'operation_id': offlineOp.id};
|
|
|
+ logger.d('离线保存: ${offlineOp.id}');
|
|
|
+ return ApiOfflineModel();
|
|
|
}
|
|
|
|
|
|
bool _isNetworkError(dynamic error) {
|
|
|
// 根据实际的错误类型判断是否为网络错误
|
|
|
final errorString = error.toString().toLowerCase();
|
|
|
- return errorString.contains('network') ||
|
|
|
+ return errorString.contains('网络连接错误') ||
|
|
|
+ errorString.contains('network') ||
|
|
|
errorString.contains('connection') ||
|
|
|
errorString.contains('timeout') ||
|
|
|
errorString.contains('socket') ||
|
|
|
@@ -222,26 +218,15 @@ class ApiService {
|
|
|
error.type == DioExceptionType.connectionError));
|
|
|
}
|
|
|
|
|
|
- void _triggerSync() {
|
|
|
- // 触发离线操作同步流程
|
|
|
- // 使用 SyncService 来处理同步逻辑,避免重复代码
|
|
|
- Future.microtask(() async {
|
|
|
- try {
|
|
|
- final syncService = SyncService();
|
|
|
- await syncService.syncPendingOperations();
|
|
|
- } catch (e) {
|
|
|
- logger.e('同步离线操作时出错: $e');
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
dynamic _handleResponse(Response response, ApiOption apiOption) {
|
|
|
try {
|
|
|
if (response.statusCode == 200 || response.statusCode == 201) {
|
|
|
// 假设后端返回的数据结构是 { "code": 200, "msg": "success", "data": ... }
|
|
|
final data = response.data;
|
|
|
final code = data is Map && data.containsKey('code') ? data['code'] : 0;
|
|
|
- final msg = data is Map && data.containsKey('msg') ? data['msg'] : null;
|
|
|
+ String? msg = data is Map && data.containsKey('msg')
|
|
|
+ ? data['msg']
|
|
|
+ : null;
|
|
|
if (code == 200) {
|
|
|
final rData = (data is Map && data.containsKey('data'))
|
|
|
? data['data']
|
|
|
@@ -258,29 +243,49 @@ class ApiService {
|
|
|
AppRouteNames.login,
|
|
|
);
|
|
|
return null;
|
|
|
- } else if (code == 403) {
|
|
|
- if (apiOption.alert) {
|
|
|
- ToastUtil.errorAlert(msg ?? '没有权限!');
|
|
|
- }
|
|
|
- return null;
|
|
|
} else {
|
|
|
+ final msg1 = code == 403 ? "没有权限!" : data['msg'] ?? "操作失败";
|
|
|
if (apiOption.alert) {
|
|
|
- ToastUtil.errorAlert(data['msg'] ?? '操作失败');
|
|
|
+ ToastUtil.errorAlert(msg1);
|
|
|
+ } else {
|
|
|
+ throw Exception(msg1);
|
|
|
}
|
|
|
return null;
|
|
|
}
|
|
|
} else {
|
|
|
+ final msg2 = response.statusMessage ?? '请求失败';
|
|
|
if (apiOption.alert) {
|
|
|
- ToastUtil.errorAlert(response.statusMessage ?? '请求失败');
|
|
|
+ ToastUtil.errorAlert(msg2);
|
|
|
+ } else {
|
|
|
+ throw Exception(msg2);
|
|
|
}
|
|
|
return null;
|
|
|
}
|
|
|
} catch (e) {
|
|
|
logger.e("数据解析失败:$e");
|
|
|
+ final msg = "数据解析失败";
|
|
|
if (apiOption.alert) {
|
|
|
- ToastUtil.error('数据解析失败');
|
|
|
+ ToastUtil.errorAlert(msg);
|
|
|
+ } else {
|
|
|
+ throw Exception(msg);
|
|
|
}
|
|
|
return null;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+class ApiOfflineModel {
|
|
|
+ bool isOffline;
|
|
|
+ dynamic data;
|
|
|
+ ApiOfflineModel({this.isOffline = true, this.data});
|
|
|
+ ApiOfflineModel.onLine(this.data, {this.isOffline = false});
|
|
|
+
|
|
|
+ dynamic check() {
|
|
|
+ if (isOffline) {
|
|
|
+ ToastUtil.success("离线保存成功");
|
|
|
+ return null;
|
|
|
+ } else {
|
|
|
+ return data;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|