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

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());
}
}