100 lines
3.0 KiB
Dart
100 lines
3.0 KiB
Dart
|
import 'package:dio/dio.dart';
|
||
|
|
||
|
/// 统一接口异常
|
||
|
class ApiException implements Exception {
|
||
|
final String result;
|
||
|
final String message;
|
||
|
ApiException(this.result, this.message);
|
||
|
@override
|
||
|
String toString() => 'ApiException($result): $message';
|
||
|
}
|
||
|
|
||
|
/// HTTP 方法枚举
|
||
|
enum Method { get, post, put, delete }
|
||
|
|
||
|
class HttpManager {
|
||
|
HttpManager._internal() {
|
||
|
_dio = Dio(BaseOptions(
|
||
|
connectTimeout: const Duration(milliseconds: 10000),
|
||
|
receiveTimeout: const Duration(milliseconds: 10000),
|
||
|
headers: {
|
||
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||
|
},
|
||
|
));
|
||
|
_initInterceptors();
|
||
|
}
|
||
|
|
||
|
static final HttpManager _instance = HttpManager._internal();
|
||
|
factory HttpManager() => _instance;
|
||
|
late final Dio _dio;
|
||
|
|
||
|
void _initInterceptors() {
|
||
|
_dio.interceptors
|
||
|
..add(LogInterceptor(request: true, responseBody: true, error: true))
|
||
|
..add(InterceptorsWrapper(onError: (err, handler) {
|
||
|
// 全局错误处理,可根据 err.response?.statusCode 或 err.type 操作
|
||
|
handler.next(err);
|
||
|
}));
|
||
|
}
|
||
|
|
||
|
/// 通用 request 方法,返回完整后台 JSON
|
||
|
/// baseUrl: 基础路径,如 basePath
|
||
|
/// path: 接口路径,如 '/admin/check'
|
||
|
/// method: HTTP 方法,默认 POST
|
||
|
/// data: Form 表单参数
|
||
|
/// params: URL 查询参数
|
||
|
Future<Map<String, dynamic>> request(
|
||
|
String baseUrl,
|
||
|
String path, {
|
||
|
Method method = Method.post,
|
||
|
Map<String, dynamic>? data,
|
||
|
Map<String, dynamic>? params,
|
||
|
CancelToken? cancelToken,
|
||
|
}) async {
|
||
|
Response resp;
|
||
|
final url = baseUrl + path;
|
||
|
final options = Options(
|
||
|
method: method.name.toUpperCase(),
|
||
|
contentType: Headers.formUrlEncodedContentType,
|
||
|
);
|
||
|
try {
|
||
|
switch (method) {
|
||
|
case Method.get:
|
||
|
resp = await _dio.get(url,
|
||
|
queryParameters: params, cancelToken: cancelToken, options: options);
|
||
|
break;
|
||
|
case Method.put:
|
||
|
resp = await _dio.put(url,
|
||
|
data: data, queryParameters: params, cancelToken: cancelToken, options: options);
|
||
|
break;
|
||
|
case Method.delete:
|
||
|
resp = await _dio.delete(url,
|
||
|
queryParameters: params, cancelToken: cancelToken, options: options);
|
||
|
break;
|
||
|
case Method.post:
|
||
|
default:
|
||
|
resp = await _dio.post(url,
|
||
|
data: data, queryParameters: params, cancelToken: cancelToken, options: options);
|
||
|
}
|
||
|
} on DioError catch (e) {
|
||
|
// 网络或服务器错误
|
||
|
throw ApiException('network_error', e.message ?? "");
|
||
|
}
|
||
|
|
||
|
// 解析返回 JSON
|
||
|
final json = resp.data is Map<String, dynamic>
|
||
|
? resp.data as Map<String, dynamic>
|
||
|
: <String, dynamic>{};
|
||
|
final result = json['result'] as String?;
|
||
|
final msg = json['msg'] as String? ?? json['message'] as String? ?? '';
|
||
|
if (result != 'success') {
|
||
|
// 非 success 都抛异常
|
||
|
throw ApiException(result ?? 'unknown', msg);
|
||
|
}
|
||
|
// 返回完整数据,包括 msg、USER_ID 等
|
||
|
return json;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|