youhua
This commit is contained in:
74
flutter_monisuo/lib/core/network/api_response.dart
Normal file
74
flutter_monisuo/lib/core/network/api_response.dart
Normal file
@@ -0,0 +1,74 @@
|
||||
/// API 响应状态码
|
||||
class ResponseCode {
|
||||
static const String success = '0000';
|
||||
static const String unauthorized = '0002';
|
||||
}
|
||||
|
||||
/// API 响应模型
|
||||
class ApiResponse<T> {
|
||||
final bool success;
|
||||
final String? message;
|
||||
final T? data;
|
||||
final String? code;
|
||||
|
||||
ApiResponse({
|
||||
required this.success,
|
||||
this.message,
|
||||
this.data,
|
||||
this.code,
|
||||
});
|
||||
|
||||
factory ApiResponse.success(T data, [String? message]) {
|
||||
return ApiResponse(
|
||||
success: true,
|
||||
data: data,
|
||||
message: message,
|
||||
code: ResponseCode.success,
|
||||
);
|
||||
}
|
||||
|
||||
factory ApiResponse.fail(String message, [String? code]) {
|
||||
return ApiResponse(
|
||||
success: false,
|
||||
message: message,
|
||||
code: code,
|
||||
);
|
||||
}
|
||||
|
||||
factory ApiResponse.unauthorized(String message) {
|
||||
return ApiResponse(
|
||||
success: false,
|
||||
message: message,
|
||||
code: ResponseCode.unauthorized,
|
||||
);
|
||||
}
|
||||
|
||||
factory ApiResponse.fromJson(
|
||||
Map<String, dynamic> json,
|
||||
T Function(dynamic)? fromJsonT,
|
||||
) {
|
||||
final code = json['code'] as String? ?? '';
|
||||
final msg = json['msg'] as String? ?? '';
|
||||
|
||||
return switch (code) {
|
||||
ResponseCode.success => _parseSuccess(json, msg, fromJsonT),
|
||||
ResponseCode.unauthorized => ApiResponse.unauthorized(msg),
|
||||
_ => ApiResponse.fail(msg, code),
|
||||
};
|
||||
}
|
||||
|
||||
static ApiResponse<T> _parseSuccess<T>(
|
||||
Map<String, dynamic> json,
|
||||
String msg,
|
||||
T Function(dynamic)? fromJsonT,
|
||||
) {
|
||||
final data = json['data'];
|
||||
if (fromJsonT != null && data != null) {
|
||||
return ApiResponse.success(fromJsonT(data), msg);
|
||||
}
|
||||
return ApiResponse.success(data as T, msg);
|
||||
}
|
||||
|
||||
bool get isSuccess => success;
|
||||
bool get isUnauthorized => code == ResponseCode.unauthorized;
|
||||
}
|
||||
@@ -1,65 +1,13 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import '../storage/local_storage.dart';
|
||||
import 'api_exception.dart';
|
||||
import 'api_response.dart';
|
||||
|
||||
/// API 响应模型
|
||||
class ApiResponse<T> {
|
||||
final bool success;
|
||||
final String? message;
|
||||
final T? data;
|
||||
final String? code;
|
||||
|
||||
ApiResponse({
|
||||
required this.success,
|
||||
this.message,
|
||||
this.data,
|
||||
this.code,
|
||||
});
|
||||
|
||||
factory ApiResponse.success(T data, [String? message]) {
|
||||
return ApiResponse(
|
||||
success: true,
|
||||
data: data,
|
||||
message: message,
|
||||
code: '0000',
|
||||
);
|
||||
}
|
||||
|
||||
factory ApiResponse.fail(String message, [String? code]) {
|
||||
return ApiResponse(
|
||||
success: false,
|
||||
message: message,
|
||||
code: code,
|
||||
);
|
||||
}
|
||||
|
||||
factory ApiResponse.unauthorized(String message) {
|
||||
return ApiResponse(
|
||||
success: false,
|
||||
message: message,
|
||||
code: '0002',
|
||||
);
|
||||
}
|
||||
|
||||
factory ApiResponse.fromJson(
|
||||
Map<String, dynamic> json,
|
||||
T Function(dynamic)? fromJsonT,
|
||||
) {
|
||||
final code = json['code'] as String? ?? '';
|
||||
final msg = json['msg'] as String? ?? '';
|
||||
|
||||
if (code == '0000') {
|
||||
final data = json['data'];
|
||||
if (fromJsonT != null && data != null) {
|
||||
return ApiResponse.success(fromJsonT(data), msg);
|
||||
}
|
||||
return ApiResponse.success(data as T, msg);
|
||||
} else if (code == '0002') {
|
||||
return ApiResponse.unauthorized(msg);
|
||||
} else {
|
||||
return ApiResponse.fail(msg, code);
|
||||
}
|
||||
}
|
||||
/// 网络配置常量
|
||||
class NetworkConfig {
|
||||
static const String baseUrl = 'http://localhost:5010';
|
||||
static const Duration connectTimeout = Duration(seconds: 30);
|
||||
static const Duration receiveTimeout = Duration(seconds: 30);
|
||||
}
|
||||
|
||||
/// Dio 网络客户端
|
||||
@@ -67,23 +15,30 @@ class DioClient {
|
||||
late final Dio _dio;
|
||||
|
||||
DioClient() {
|
||||
_dio = Dio(BaseOptions(
|
||||
baseUrl: 'http://localhost:5010',
|
||||
connectTimeout: const Duration(seconds: 30),
|
||||
receiveTimeout: const Duration(seconds: 30),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
));
|
||||
_dio = _createDio();
|
||||
_setupInterceptors();
|
||||
}
|
||||
|
||||
_dio.interceptors.add(_AuthInterceptor());
|
||||
_dio.interceptors.add(LogInterceptor(
|
||||
requestHeader: false,
|
||||
responseHeader: false,
|
||||
error: true,
|
||||
Dio _createDio() {
|
||||
return Dio(BaseOptions(
|
||||
baseUrl: NetworkConfig.baseUrl,
|
||||
connectTimeout: NetworkConfig.connectTimeout,
|
||||
receiveTimeout: NetworkConfig.receiveTimeout,
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
));
|
||||
}
|
||||
|
||||
void _setupInterceptors() {
|
||||
_dio.interceptors.addAll([
|
||||
_AuthInterceptor(),
|
||||
LogInterceptor(
|
||||
requestHeader: false,
|
||||
responseHeader: false,
|
||||
error: true,
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
/// GET 请求
|
||||
Future<ApiResponse<T>> get<T>(
|
||||
String path, {
|
||||
@@ -112,7 +67,6 @@ class DioClient {
|
||||
}
|
||||
}
|
||||
|
||||
/// 处理响应
|
||||
ApiResponse<T> _handleResponse<T>(
|
||||
Response response,
|
||||
T Function(dynamic)? fromJson,
|
||||
@@ -124,13 +78,39 @@ class DioClient {
|
||||
return ApiResponse.fail('响应数据格式错误');
|
||||
}
|
||||
|
||||
/// 处理错误
|
||||
ApiResponse<T> _handleError<T>(DioException e) {
|
||||
if (e.response?.statusCode == 401) {
|
||||
LocalStorage.clearUserData();
|
||||
if (_isUnauthorized(e)) {
|
||||
_clearUserData();
|
||||
return ApiResponse.unauthorized('登录已过期,请重新登录');
|
||||
}
|
||||
return ApiResponse.fail(e.message ?? '网络请求失败');
|
||||
|
||||
final message = _getErrorMessage(e);
|
||||
return ApiResponse.fail(message);
|
||||
}
|
||||
|
||||
bool _isUnauthorized(DioException e) {
|
||||
return e.response?.statusCode == 401;
|
||||
}
|
||||
|
||||
void _clearUserData() {
|
||||
LocalStorage.clearUserData();
|
||||
}
|
||||
|
||||
String _getErrorMessage(DioException e) {
|
||||
switch (e.type) {
|
||||
case DioExceptionType.connectionTimeout:
|
||||
return '连接超时,请检查网络';
|
||||
case DioExceptionType.sendTimeout:
|
||||
return '发送超时,请重试';
|
||||
case DioExceptionType.receiveTimeout:
|
||||
return '响应超时,请重试';
|
||||
case DioExceptionType.connectionError:
|
||||
return '网络连接失败';
|
||||
case DioExceptionType.badResponse:
|
||||
return '服务器错误 (${e.response?.statusCode})';
|
||||
default:
|
||||
return e.message ?? '网络请求失败';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,7 +119,7 @@ class _AuthInterceptor extends Interceptor {
|
||||
@override
|
||||
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
|
||||
final token = LocalStorage.getToken();
|
||||
if (token != null && token.isNotEmpty) {
|
||||
if (token?.isNotEmpty == true) {
|
||||
options.headers['Authorization'] = 'Bearer $token';
|
||||
}
|
||||
super.onRequest(options, handler);
|
||||
|
||||
Reference in New Issue
Block a user