2026-07-01 18:25:58 +08:00

300 lines
9.5 KiB
Dart

// api.dart
import 'dart:convert';
import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:aslan/chatvibe_ui/components/at_tts.dart';
import 'package:aslan/chatvibe_core/utilities/at_room_utils.dart';
import 'package:aslan/chatvibe_data/sources/local/user_manager.dart';
import 'package:aslan/chatvibe_features/family/family_route.dart';
import 'package:aslan/chatvibe_features/auth/login_route.dart';
import 'package:aslan/chatvibe_managers/user_profile_manager.dart';
import 'package:aslan/chatvibe_ui/widgets/room/pwd/input_room_pwd_page.dart';
import 'package:provider/provider.dart';
import 'package:aslan/chatvibe_core/routes/at_fluro_navigator.dart';
import 'package:aslan/chatvibe_core/utilities/at_loading_manager.dart';
import 'package:aslan/main.dart';
import 'package:aslan/chatvibe_ui/widgets/room/redpack/room_redenvelope_rec_record_page.dart';
import 'package:aslan/chatvibe_data/sources/remote/net/network_client.dart';
import '../../../models/enum/at_erro_code.dart';
export 'package:dio/dio.dart';
_parseAndDecode(String response) => jsonDecode(response);
parseJson(String text) => compute(_parseAndDecode, text);
class BaseNetworkClient {
final Dio dio;
BaseNetworkClient() : dio = Dio() {
_configureDio();
init();
}
void _configureDio() {
dio.transformer = BackgroundTransformer()..jsonDecodeCallback = parseJson;
dio.options = BaseOptions(
connectTimeout: const Duration(seconds: 12),
receiveTimeout: const Duration(seconds: 15),
contentType: 'application/json; charset=UTF-8',
);
}
void init() {}
// 通用 GET 请求
Future<T> get<T>(
String path, {
Map<String, dynamic>? queryParams,
required T Function(dynamic) fromJson,
CancelToken? cancelToken,
ProgressCallback? onSendProgress,
ProgressCallback? onReceiveProgress,
}) async {
return _request<T>(
path,
method: 'GET',
queryParams: queryParams,
fromJson: fromJson,
cancelToken: cancelToken,
onSendProgress: onSendProgress,
onReceiveProgress: onReceiveProgress,
);
}
// 通用 put 请求
Future<T> put<T>(
String path, {
dynamic data,
Map<String, dynamic>? queryParams,
required T Function(dynamic) fromJson,
CancelToken? cancelToken,
ProgressCallback? onSendProgress,
ProgressCallback? onReceiveProgress,
}) async {
return _request<T>(
path,
method: 'PUT',
data: data,
queryParams: queryParams,
fromJson: fromJson,
cancelToken: cancelToken,
onSendProgress: onSendProgress,
onReceiveProgress: onReceiveProgress,
);
}
// 通用 POST 请求
Future<T> post<T>(
String path, {
dynamic data,
Map<String, dynamic>? queryParams,
required T Function(dynamic) fromJson,
CancelToken? cancelToken,
ProgressCallback? onSendProgress,
ProgressCallback? onReceiveProgress,
}) async {
return _request<T>(
path,
method: 'POST',
data: data,
queryParams: queryParams,
fromJson: fromJson,
cancelToken: cancelToken,
onSendProgress: onSendProgress,
onReceiveProgress: onReceiveProgress,
);
}
// 通用 POST 请求
Future<T> delete<T>(
String path, {
dynamic data,
Map<String, dynamic>? queryParams,
required T Function(dynamic) fromJson,
CancelToken? cancelToken,
ProgressCallback? onSendProgress,
ProgressCallback? onReceiveProgress,
}) async {
return _request<T>(
path,
method: 'DELETE',
data: data,
queryParams: queryParams,
fromJson: fromJson,
cancelToken: cancelToken,
onSendProgress: onSendProgress,
onReceiveProgress: onReceiveProgress,
);
}
// 核心请求方法
Future<T> _request<T>(
String path, {
required String method,
dynamic data,
Map<String, dynamic>? queryParams,
CancelToken? cancelToken,
ProgressCallback? onSendProgress,
ProgressCallback? onReceiveProgress,
required T Function(dynamic) fromJson,
}) async {
try {
final response = await dio.request(
path,
data: data,
queryParameters: queryParams,
options: Options(method: method),
cancelToken: cancelToken,
onSendProgress: onSendProgress,
onReceiveProgress: onReceiveProgress,
);
// 处理基础响应
final baseResponse = ResponseData.fromJson(
response.data as Map<String, dynamic>,
fromJsonT: fromJson,
);
// 业务逻辑成功判断
if (baseResponse.success) {
if (baseResponse.body != null) {
return baseResponse.body!;
} else {
if (T == bool) return false as T;
if (T == int) return 0 as T;
if (T == String) return "" as T;
ATLoadingManager.veilRoutine();
throw Exception('Response data is null');
}
} else {
// 业务逻辑错误
ATLoadingManager.veilRoutine();
throw DioException(
requestOptions: response.requestOptions,
response: response,
error: '业务错误: ${baseResponse.errorMsg}',
);
}
} on DioException catch (e) {
// 网络错误处理
throw _handleDioError(e);
} catch (e) {
ATLoadingManager.veilRoutine();
throw Exception('未知错误: $e');
}
}
// 错误处理
DioException _handleDioError(DioException e) {
ATLoadingManager.veilRoutine();
switch (e.type) {
case DioExceptionType.connectionTimeout:
return DioException(requestOptions: e.requestOptions, error: '连接超时');
case DioExceptionType.sendTimeout:
return DioException(requestOptions: e.requestOptions, error: '发送超时');
case DioExceptionType.receiveTimeout:
return DioException(requestOptions: e.requestOptions, error: '接收超时');
case DioExceptionType.badResponse:
var errorCode = e.response?.data["errorCode"];
var errorMsg = e.response?.data["errorMsg"];
if (errorCode == ATErroCode.userNotRegistered.code) {
//用户还没有注册
ATTts.show("Please register an account first.");
BuildContext? context = navigatorKey.currentContext;
if (context != null) {
ATNavigatorUtils.push(
context,
LoginRouter.editProfile,
replace: false,
);
}
} else if (errorCode == ATErroCode.authUnauthorized.code) {
//token过期
BuildContext? context = navigatorKey.currentContext;
if (context != null) {
if (!inLoginPage) {
AccountStorage().logout(context);
inLoginPage = true;
}
}
} else if (errorCode == ATErroCode.passwordNotTrue.code) {
//需要输入房间密码
String roomId = e.requestOptions.data["roomId"];
bool needOpenRedenvelope =
e.requestOptions.data["needOpenRedenvelope"];
String redPackId = e.requestOptions.data["redPackId"];
SmartDialog.dismiss(tag: "showInputRoomPwd");
SmartDialog.show(
tag: "showInputRoomPwd",
alignment: Alignment.bottomCenter,
animationType: SmartAnimationType.fade,
builder: (_) {
return InputRoomPwdPage(
roomId,
needOpenRedenvelope: needOpenRedenvelope,
redPackId: redPackId,
);
},
);
} else if (errorCode == ATErroCode.redPacketFinished.code) {
//红包领完了直接跳到红包详情页面
String packetId = e.requestOptions.data["packetId"];
SmartDialog.dismiss(tag: "showRoomRedenvelopeList");
SmartDialog.show(
tag: "showRoomRedenvelopeRec",
alignment: Alignment.center,
animationType: SmartAnimationType.fade,
builder: (_) {
return RoomRedenvelopeRecRecordPage(packetId);
},
);
} else if (errorCode == ATErroCode.userJoinedFamily.code) {
BuildContext? context = navigatorKey.currentContext;
Provider.of<ChatVibeUserProfileManager>(
context!,
listen: false,
).getMyUserInfo(needRefreshFamily: true).then((res) {
navigatorKey.currentState?.popUntil(
ModalRoute.withName(FamilyRoute.reqRecordFamily),
);
});
} else {
if (errorMsg.toString().endsWith("balance not made")) {
BuildContext? context = navigatorKey.currentContext;
if (context != null) {
ATRoomUtils.goRechargeOperation(context);
}
} else {
ATTts.show(errorMsg);
}
}
return DioException(
requestOptions: e.requestOptions,
response: e.response,
error: '服务器错误: ${e.response?.data["errorCode"]}',
);
case DioExceptionType.cancel:
return DioException(requestOptions: e.requestOptions, error: 'Cancel');
default:
return DioException(
requestOptions: e.requestOptions,
error: 'Net fail',
);
}
}
}
class NotSuccessException implements Exception {
final String message;
NotSuccessException(this.message);
factory NotSuccessException.fromRespData(ResponseData respData) {
return NotSuccessException(respData.errorMsg ?? "操作失败");
}
}