dio_client.dart 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. import 'package:dio/dio.dart' hide LogInterceptor;
  2. import 'package:sino_med_cloud/core/constants/api_constants.dart';
  3. import 'package:sino_med_cloud/core/network/interceptors/auth_interceptor.dart';
  4. import 'package:sino_med_cloud/core/network/interceptors/error_interceptor.dart';
  5. import 'package:sino_med_cloud/core/network/interceptors/log_interceptor.dart';
  6. import 'package:sino_med_cloud/core/network/interceptors/network_interceptor.dart';
  7. import 'package:sino_med_cloud/core/utils/logger.dart';
  8. import 'package:sino_med_cloud/base/common_response.dart';
  9. import '../../base/list_response.dart';
  10. /// Dio 客户端 - 统一网络请求管理
  11. class DioClient {
  12. // 使用一个内部方法来创建和配置 Dio 实例
  13. static final Dio _dio = _createDio();
  14. static Dio _createDio() {
  15. AppLogger.d('DioClient - 开始创建 Dio 实例并配置拦截器');
  16. final dio = Dio(
  17. BaseOptions(
  18. baseUrl: ApiConstants.baseUrl,
  19. connectTimeout: Duration(seconds: ApiConstants.connectTimeout),
  20. receiveTimeout: Duration(seconds: ApiConstants.receiveTimeout),
  21. sendTimeout: Duration(seconds: ApiConstants.sendTimeout),
  22. headers: {
  23. ApiConstants.contentType: ApiConstants.applicationJson,
  24. },
  25. ),
  26. );
  27. // 立即添加拦截器
  28. dio.interceptors.addAll([
  29. AuthInterceptor(), // 认证拦截器
  30. LogInterceptor(), // 日志拦截器
  31. ErrorInterceptor(), // 错误拦截器
  32. NetworkInterceptor(), // 网络状态拦截器(在最后检查,确保异常能被 ErrorInterceptor 捕获)
  33. ]);
  34. AppLogger.d('DioClient - Dio 实例初始化完成,拦截器数量: ${dio.interceptors.length}');
  35. return dio;
  36. }
  37. // 暴露 dio 实例
  38. static Dio get dio => _dio;
  39. /// 重置 Dio 实例(用于重新配置)
  40. static void reset() {
  41. _dio.interceptors.clear();
  42. _dio.interceptors.addAll([
  43. AuthInterceptor(),
  44. LogInterceptor(),
  45. ErrorInterceptor(),
  46. NetworkInterceptor(),
  47. ]);
  48. }
  49. // ==================== GET 请求 ====================
  50. /// GET 请求
  51. ///
  52. /// [path] 请求路径(相对于 baseUrl)
  53. /// [fromJsonT] JSON 转换为 T 类型的函数
  54. /// [queryParameters] 查询参数
  55. /// [options] 请求选项
  56. ///
  57. /// 返回 [BaseCommonResponse] 对象
  58. static Future<BaseCommonResponse<T>> get<T>(
  59. String path, {
  60. required T Function(Object? json) fromJsonT,
  61. Map<String, dynamic>? queryParameters,
  62. Options? options,
  63. CancelToken? cancelToken,
  64. ProgressCallback? onReceiveProgress,
  65. }) async {
  66. try {
  67. final response = await dio.get(
  68. path,
  69. queryParameters: queryParameters,
  70. options: options,
  71. cancelToken: cancelToken,
  72. onReceiveProgress: onReceiveProgress,
  73. );
  74. return BaseCommonResponse<T>.fromJson(
  75. response.data as Map<String, dynamic>,
  76. fromJsonT,
  77. );
  78. } on DioException catch (e) {
  79. // 错误已由 ErrorInterceptor 处理,直接抛出
  80. rethrow;
  81. }
  82. }
  83. static Future<BaseListResponse<T>> getList<T>(
  84. String path, {
  85. required T Function(Object? json) fromJsonT,
  86. Map<String, dynamic>? queryParameters,
  87. Options? options,
  88. CancelToken? cancelToken,
  89. ProgressCallback? onReceiveProgress,
  90. }) async {
  91. try {
  92. final response = await dio.get(
  93. path,
  94. queryParameters: queryParameters,
  95. options: options,
  96. cancelToken: cancelToken,
  97. onReceiveProgress: onReceiveProgress,
  98. );
  99. return BaseListResponse<T>.fromJson(
  100. response.data as Map<String, dynamic>,
  101. fromJsonT,
  102. );
  103. } on DioException catch (e) {
  104. // 错误已由 ErrorInterceptor 处理,直接抛出
  105. rethrow;
  106. }
  107. }
  108. // ==================== POST 请求 ====================
  109. /// POST 请求
  110. ///
  111. /// [path] 请求路径(相对于 baseUrl)
  112. /// [fromJsonT] JSON 转换为 T 类型的函数
  113. /// [data] 请求体数据
  114. /// [queryParameters] 查询参数
  115. /// [options] 请求选项
  116. ///
  117. /// 返回 [BaseCommonResponse] 对象
  118. static Future<BaseCommonResponse<T>> post<T>(
  119. String path, {
  120. required T Function(Object? json) fromJsonT,
  121. dynamic data,
  122. Map<String, dynamic>? queryParameters,
  123. Options? options,
  124. CancelToken? cancelToken,
  125. ProgressCallback? onSendProgress,
  126. ProgressCallback? onReceiveProgress,
  127. }) async {
  128. try {
  129. final response = await dio.post(
  130. path,
  131. data: data,
  132. queryParameters: queryParameters,
  133. options: options,
  134. cancelToken: cancelToken,
  135. onSendProgress: onSendProgress,
  136. onReceiveProgress: onReceiveProgress,
  137. );
  138. return BaseCommonResponse<T>.fromJson(
  139. response.data as Map<String, dynamic>,
  140. fromJsonT,
  141. );
  142. } on DioException catch (e) {
  143. // 错误已由 ErrorInterceptor 处理,直接抛出
  144. rethrow;
  145. }
  146. }
  147. // ==================== DELETE 请求 ====================
  148. /// DELETE 请求
  149. ///
  150. /// [path] 请求路径(相对于 baseUrl)
  151. /// [fromJsonT] JSON 转换为 T 类型的函数
  152. /// [data] 请求体数据(可选)
  153. /// [queryParameters] 查询参数
  154. /// [options] 请求选项
  155. ///
  156. /// 返回 [BaseCommonResponse] 对象
  157. static Future<BaseCommonResponse<T>> delete<T>(
  158. String path, {
  159. required T Function(Object? json) fromJsonT,
  160. dynamic data,
  161. Map<String, dynamic>? queryParameters,
  162. Options? options,
  163. CancelToken? cancelToken,
  164. }) async {
  165. try {
  166. final response = await dio.delete(
  167. path,
  168. data: data,
  169. queryParameters: queryParameters,
  170. options: options,
  171. cancelToken: cancelToken,
  172. );
  173. return BaseCommonResponse<T>.fromJson(
  174. response.data as Map<String, dynamic>,
  175. fromJsonT,
  176. );
  177. } on DioException catch (e) {
  178. // 错误已由 ErrorInterceptor 处理,直接抛出
  179. rethrow;
  180. }
  181. }
  182. // ==================== PUT 请求 ====================
  183. /// PUT 请求
  184. ///
  185. /// [path] 请求路径(相对于 baseUrl)
  186. /// [fromJsonT] JSON 转换为 T 类型的函数
  187. /// [data] 请求体数据
  188. /// [queryParameters] 查询参数
  189. /// [options] 请求选项
  190. ///
  191. /// 返回 [BaseCommonResponse] 对象
  192. static Future<BaseCommonResponse<T>> put<T>(
  193. String path, {
  194. required T Function(Object? json) fromJsonT,
  195. dynamic data,
  196. Map<String, dynamic>? queryParameters,
  197. Options? options,
  198. CancelToken? cancelToken,
  199. ProgressCallback? onSendProgress,
  200. ProgressCallback? onReceiveProgress,
  201. }) async {
  202. try {
  203. final response = await dio.put(
  204. path,
  205. data: data,
  206. queryParameters: queryParameters,
  207. options: options,
  208. cancelToken: cancelToken,
  209. onSendProgress: onSendProgress,
  210. onReceiveProgress: onReceiveProgress,
  211. );
  212. return BaseCommonResponse<T>.fromJson(
  213. response.data as Map<String, dynamic>,
  214. fromJsonT,
  215. );
  216. } on DioException catch (e) {
  217. // 错误已由 ErrorInterceptor 处理,直接抛出
  218. rethrow;
  219. }
  220. }
  221. // ==================== PATCH 请求 ====================
  222. /// PATCH 请求
  223. ///
  224. /// [path] 请求路径(相对于 baseUrl)
  225. /// [fromJsonT] JSON 转换为 T 类型的函数
  226. /// [data] 请求体数据
  227. /// [queryParameters] 查询参数
  228. /// [options] 请求选项
  229. ///
  230. /// 返回 [BaseCommonResponse] 对象
  231. static Future<BaseCommonResponse<T>> patch<T>(
  232. String path, {
  233. required T Function(Object? json) fromJsonT,
  234. dynamic data,
  235. Map<String, dynamic>? queryParameters,
  236. Options? options,
  237. CancelToken? cancelToken,
  238. ProgressCallback? onSendProgress,
  239. ProgressCallback? onReceiveProgress,
  240. }) async {
  241. try {
  242. final response = await dio.patch(
  243. path,
  244. data: data,
  245. queryParameters: queryParameters,
  246. options: options,
  247. cancelToken: cancelToken,
  248. onSendProgress: onSendProgress,
  249. onReceiveProgress: onReceiveProgress,
  250. );
  251. return BaseCommonResponse<T>.fromJson(
  252. response.data as Map<String, dynamic>,
  253. fromJsonT,
  254. );
  255. } on DioException catch (e) {
  256. // 错误已由 ErrorInterceptor 处理,直接抛出
  257. rethrow;
  258. }
  259. }
  260. }