You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
169 lines
4.8 KiB
169 lines
4.8 KiB
import 'package:dio/dio.dart';
|
|
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
|
import 'package:get/get.dart' hide Response;
|
|
import 'package:get_storage/get_storage.dart';
|
|
|
|
import '../config/env_config.dart';
|
|
import '../pages/mine/login_page.dart';
|
|
|
|
/// API类型枚举,用于区分不同的baseUrl
|
|
enum ApiType {
|
|
main, // 主API
|
|
file, // 文件上传下载API
|
|
}
|
|
|
|
/// 网络请求配置类
|
|
class NetworkConfig {
|
|
static const int connectTimeout = 30000;
|
|
static const int receiveTimeout = 30000;
|
|
|
|
/// 根据API类型创建不同的Dio实例
|
|
static Dio createDio({ApiType type = ApiType.main}) {
|
|
// 根据类型选择对应的baseUrl
|
|
String currentBaseUrl;
|
|
switch (type) {
|
|
case ApiType.main:
|
|
currentBaseUrl = EnvConfig.mainBaseUrl;
|
|
break;
|
|
case ApiType.file:
|
|
currentBaseUrl = EnvConfig.fileBaseUrl;
|
|
break;
|
|
}
|
|
|
|
final dio = Dio(
|
|
BaseOptions(
|
|
baseUrl: currentBaseUrl,
|
|
connectTimeout: Duration(milliseconds: connectTimeout),
|
|
receiveTimeout: Duration(milliseconds: receiveTimeout),
|
|
contentType: 'application/json',
|
|
responseType: ResponseType.json,
|
|
),
|
|
);
|
|
|
|
// 添加请求拦截器
|
|
dio.interceptors.add(AuthInterceptor());
|
|
|
|
// 添加响应拦截器
|
|
dio.interceptors.add(ResponseInterceptor());
|
|
|
|
// 添加日志拦截器
|
|
dio.interceptors.add(LogInterceptor(
|
|
requestBody: true,
|
|
responseBody: true,
|
|
error: true,
|
|
));
|
|
|
|
return dio;
|
|
}
|
|
}
|
|
|
|
/// 请求拦截器
|
|
class AuthInterceptor extends Interceptor {
|
|
@override
|
|
void onRequest(
|
|
RequestOptions options,
|
|
RequestInterceptorHandler handler,
|
|
) async {
|
|
// 添加token等认证信息
|
|
final token = _getToken();
|
|
if (token != null && token.isNotEmpty) {
|
|
options.headers['Authorization'] = 'Bearer $token';
|
|
}
|
|
|
|
// 添加其他通用请求头
|
|
options.headers['X-APP-ID'] = '50325897884795885';
|
|
|
|
handler.next(options);
|
|
}
|
|
|
|
String? _getToken() {
|
|
// 从本地存储获取token
|
|
// 这里可以使用get_storage或其他存储方式
|
|
return GetStorage().read('token');
|
|
}
|
|
}
|
|
|
|
/// 响应拦截器
|
|
class ResponseInterceptor extends Interceptor {
|
|
@override
|
|
void onResponse(
|
|
Response response,
|
|
ResponseInterceptorHandler handler,
|
|
) {
|
|
// 统一处理响应数据
|
|
final data = response.data;
|
|
|
|
// 检查响应状态码
|
|
if (response.statusCode == 200) {
|
|
// 假设后端返回的数据格式为 {"code": 0, "message": "success", "data": {...}}
|
|
if (data is Map<String, dynamic>) {
|
|
final code = data['code'] ?? 0;
|
|
if (code == 0) {
|
|
// 请求成功
|
|
handler.next(response);
|
|
} else {
|
|
// 业务错误
|
|
final message = data['message'] ?? '请求失败';
|
|
_showError(message);
|
|
handler.reject(DioException(
|
|
requestOptions: response.requestOptions,
|
|
error: message,
|
|
type: DioExceptionType.badResponse,
|
|
));
|
|
}
|
|
} else {
|
|
handler.next(response);
|
|
}
|
|
} else {
|
|
handler.next(response);
|
|
}
|
|
}
|
|
|
|
@override
|
|
void onError(DioException err, ErrorInterceptorHandler handler) {
|
|
// 统一处理错误
|
|
String errorMessage = '网络请求失败';
|
|
print('DioError: ${err.message}');
|
|
switch (err.type) {
|
|
case DioExceptionType.connectionTimeout:
|
|
case DioExceptionType.sendTimeout:
|
|
case DioExceptionType.receiveTimeout:
|
|
errorMessage = '网络连接超时,请检查网络';
|
|
break;
|
|
case DioExceptionType.badResponse:
|
|
if (err.response?.statusCode == 401) {
|
|
errorMessage = '登录已过期,请重新登录';
|
|
_handleTokenExpired();
|
|
} else if (err.response?.statusCode == 403) {
|
|
errorMessage = '没有权限访问该资源';
|
|
} else if (err.response?.statusCode == 404) {
|
|
errorMessage = '请求的资源不存在';
|
|
} else if (err.response?.statusCode == 500) {
|
|
errorMessage = '服务器内部错误';
|
|
} else {
|
|
errorMessage = '请求失败,状态码:${err.response?.statusCode}';
|
|
}
|
|
break;
|
|
case DioExceptionType.cancel:
|
|
errorMessage = '请求已取消';
|
|
break;
|
|
default:
|
|
errorMessage = err.message ?? '未知错误';
|
|
}
|
|
|
|
_showError(errorMessage);
|
|
handler.reject(err);
|
|
}
|
|
|
|
void _showError(String message) {
|
|
// 使用FlutterSmartDialog显示错误信息
|
|
SmartDialog.showToast(message, displayTime: const Duration(seconds: 2));
|
|
}
|
|
|
|
void _handleTokenExpired() {
|
|
// 处理token过期逻辑,如清除本地数据、跳转登录页等
|
|
// 这里可以使用Get.offAllNamed('/login')等方式跳转
|
|
GetStorage().remove('token');
|
|
Get.offAll(() => LoginPage());
|
|
}
|
|
}
|