- 上游: github.com/OpenIMSDK/openim-flutter-demo tag 3.8.3-patch.3 commit b3dfdb1e8aaeaaf6f0793e10cadd20d5c184a31f - 并行目录 mobile-next/ 原样导入(含 LICENSE),不覆盖现网 mobile/ - 锁定 Flutter 3.24.5 / Dart 3.5.4 / JDK 17 / Gradle 7.6.3 / AGP 7.3.1 - 实测 Android debug 与 release 构建均成功(见 docs/mobile-next-baseline-import.md) - 本提交可单独回退:git revert 1db1229(重写前) Co-authored-by: multica-agent <github@multica.ai>
162 lines
4.0 KiB
Dart
162 lines
4.0 KiB
Dart
import 'dart:convert';
|
|
|
|
import 'package:dio/dio.dart';
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:openim_common/openim_common.dart';
|
|
import 'package:talker_dio_logger/talker_dio_logger.dart';
|
|
|
|
class ApiService {
|
|
static final _instance = ApiService._internal();
|
|
|
|
factory ApiService() {
|
|
return _instance;
|
|
}
|
|
|
|
final Dio dio = Dio();
|
|
|
|
ApiService._internal() {
|
|
final talkerDioLogger = TalkerDioLogger(
|
|
settings: const TalkerDioLoggerSettings(
|
|
printRequestHeaders: kDebugMode,
|
|
printRequestData: kDebugMode,
|
|
printResponseMessage: kDebugMode,
|
|
printResponseData: kDebugMode,
|
|
printResponseHeaders: false,
|
|
),
|
|
);
|
|
|
|
dio.options
|
|
..connectTimeout = const Duration(seconds: 30)
|
|
..receiveTimeout = const Duration(seconds: 30);
|
|
|
|
dio.interceptors
|
|
..add(talkerDioLogger)
|
|
..add(
|
|
InterceptorsWrapper(
|
|
onRequest: (options, handler) {
|
|
return handler.next(options); //continue
|
|
},
|
|
onResponse: (response, handler) {
|
|
return handler.next(response); // continue
|
|
},
|
|
onError: (DioException e, handler) {
|
|
return handler.next(e); //continue
|
|
},
|
|
),
|
|
);
|
|
|
|
dio.options.connectTimeout = const Duration(seconds: 30);
|
|
dio.options.receiveTimeout = const Duration(seconds: 30);
|
|
}
|
|
|
|
void setBaseUrl(String baseUrl) {
|
|
dio.options.baseUrl = baseUrl;
|
|
}
|
|
|
|
void setToken(String token) {
|
|
dio.options.headers['token'] = token;
|
|
}
|
|
|
|
Future get(String path, {Map<String, dynamic>? queryParams}) async {
|
|
try {
|
|
dio.options.headers['operationID'] = DateTime.now().millisecondsSinceEpoch.toString();
|
|
|
|
final response = await dio.get(path, queryParameters: queryParams);
|
|
|
|
if (response.statusCode == 200) {
|
|
final result = ApiResponse.fromJson(response.data as Map<String, dynamic>);
|
|
|
|
if (result.errCode == 0) {
|
|
return result.data;
|
|
} else {
|
|
return Future.error(result.errMsg);
|
|
}
|
|
}
|
|
|
|
return Future.error(response.data);
|
|
} on DioException catch (e) {
|
|
_handleError(e);
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
Future post(String path, {Map<String, dynamic>? data, String? token}) async {
|
|
try {
|
|
final operationID = DateTime.now().millisecondsSinceEpoch.toString();
|
|
dio.options.headers['operationID'] = operationID;
|
|
|
|
final response = await dio.post(path, data: data);
|
|
|
|
if (response.statusCode == 200) {
|
|
final result = ApiResponse.fromJson(response.data as Map<String, dynamic>);
|
|
|
|
if (result.errCode == 0) {
|
|
return result.data;
|
|
} else {
|
|
final exception = ApiException(code: result.errCode, message: result.errMsg, operationID: operationID);
|
|
|
|
return Future.error(exception);
|
|
}
|
|
}
|
|
|
|
return Future.error(response.data);
|
|
} on DioException catch (e) {
|
|
_handleError(e);
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
Future download(
|
|
String url, {
|
|
required String cachePath,
|
|
CancelToken? cancelToken,
|
|
Function(int count, int total)? onProgress,
|
|
}) {
|
|
return dio.download(
|
|
url,
|
|
cachePath,
|
|
cancelToken: cancelToken,
|
|
onReceiveProgress: onProgress,
|
|
);
|
|
}
|
|
|
|
void _handleError(DioException error) {
|
|
Logger.print('DioError: ${error.message}', isError: true);
|
|
}
|
|
}
|
|
|
|
class ApiResponse {
|
|
int errCode;
|
|
String errMsg;
|
|
String errDlt;
|
|
dynamic data;
|
|
|
|
ApiResponse.fromJson(Map<String, dynamic> map)
|
|
: errCode = map["errCode"] ?? -1,
|
|
errMsg = map["errMsg"] ?? '',
|
|
errDlt = map["errDlt"] ?? '',
|
|
data = map["data"];
|
|
|
|
Map<String, dynamic> toJson() {
|
|
final data = <String, dynamic>{};
|
|
data['errCode'] = errCode;
|
|
data['errMsg'] = errMsg;
|
|
data['errDlt'] = errDlt;
|
|
data['data'] = data;
|
|
return data;
|
|
}
|
|
|
|
@override
|
|
String toString() {
|
|
return jsonEncode(this);
|
|
}
|
|
}
|
|
|
|
class ApiException implements Exception {
|
|
final int code;
|
|
final String? message;
|
|
final String? operationID;
|
|
|
|
ApiException({required this.code, this.message, this.operationID});
|
|
}
|