Browse Source

fix : 登录认证提示未知错误

dev
徐振升 2 weeks ago
parent
commit
faa42e07e1
  1. 122
      lib/data/providers/http_provider.dart
  2. 59
      lib/data/repositories/auth_repository.dart
  3. 11
      lib/modules/auth/controllers/login_controller.dart
  4. 28
      lib/modules/my/controllers/my_controller.dart
  5. 48
      lib/modules/my/views/my_page.dart

122
lib/data/providers/http_provider.dart

@ -1,13 +1,15 @@
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart' hide Response;
import 'package:pretty_dio_logger/pretty_dio_logger.dart';
import 'package:problem_check_system/app/routes/app_routes.dart';
import 'package:problem_check_system/data/repositories/auth_repository.dart';
// DioProvider GetxService
// Dio
class HttpProvider extends GetxService {
static const String _baseUrl = 'https://xh.anxincloud.cn';
static const String _baseUrl = 'https://xhdev.anxincloud.cn';
late final Dio _dio;
@ -40,72 +42,7 @@ class HttpProvider extends GetxService {
}
List<Interceptor> _getInterceptors() {
return [
_getAuthInterceptor(),
_getErrorInterceptor(),
if (kDebugMode) _getLoggerInterceptor(),
];
}
/// token 401
Interceptor _getAuthInterceptor() {
return InterceptorsWrapper(
//
onRequest: (options, handler) async {
try {
// AuthRepository token
final authRepository = Get.find<AuthRepository>();
final token = authRepository.getToken();
if (token != null && token.isNotEmpty) {
options.headers['Authorization'] = 'Bearer $token';
}
} catch (e) {
// AuthRepository
debugPrint('AuthRepository 未找到。跳过认证头。');
}
return handler.next(options);
},
//
onError: (error, handler) async {
// 401 Unauthorized
if (error.response?.statusCode == 401) {
try {
final authRepository = Get.find<AuthRepository>();
// token
await authRepository.refreshToken();
//
final newOptions = Options(
method: error.requestOptions.method,
headers: error.requestOptions.headers
..['Authorization'] = 'Bearer ${authRepository.getToken()}',
);
final response = await _dio.request(
error.requestOptions.path,
data: error.requestOptions.data,
queryParameters: error.requestOptions.queryParameters,
options: newOptions,
);
// 使 handler.resolve()
return handler.resolve(response);
} on Exception catch (e) {
debugPrint('刷新 token 失败: $e');
// token
final authRepository = Get.find<AuthRepository>();
authRepository.clearAuthData();
if (Get.currentRoute != '/login') {
Get.offAllNamed('/login');
}
//
return handler.next(error);
}
}
// 401
return handler.next(error);
},
);
return [_getErrorInterceptor(), if (kDebugMode) _getLoggerInterceptor()];
}
///
@ -124,20 +61,59 @@ class HttpProvider extends GetxService {
/// Snackbar
Interceptor _getErrorInterceptor() {
return InterceptorsWrapper(
//
onRequest: (options, handler) async {
try {
// AuthRepository token
final authRepository = Get.find<AuthRepository>();
final token = authRepository.getToken();
if (token != null && token.isNotEmpty) {
options.headers['Authorization'] = 'Bearer $token';
}
} catch (e) {
// AuthRepository
Get.snackbar(
'认证过期',
'请重新手动登录',
colorText: Colors.white,
backgroundColor: Colors.red,
snackPosition: SnackPosition.TOP,
);
}
return handler.next(options);
},
onError: (error, handler) {
//
if (error.type == DioExceptionType.connectionTimeout ||
error.type == DioExceptionType.receiveTimeout ||
error.type == DioExceptionType.sendTimeout) {
Get.snackbar('网络超时', '请检查网络连接后重试');
Get.snackbar(
'网络超时',
'请检查网络连接后重试',
colorText: Colors.white,
backgroundColor: Colors.red,
snackPosition: SnackPosition.TOP,
);
} else if (error.type == DioExceptionType.unknown) {
Get.snackbar('网络异常', '请检查网络连接后重试');
Get.snackbar(
'网络异常',
'请检查网络连接后重试',
colorText: Colors.white,
backgroundColor: Colors.red,
snackPosition: SnackPosition.TOP,
);
}
// AuthInterceptor 401
if (error.response != null) {
final message = _handleStatusCode(error.response!);
Get.snackbar('请求错误', message);
Get.snackbar(
'请求错误',
message,
colorText: Colors.white,
backgroundColor: Colors.red,
snackPosition: SnackPosition.TOP,
);
}
return handler.next(error);
@ -151,8 +127,10 @@ class HttpProvider extends GetxService {
case 400:
return response.data?['detail'] ?? '请求参数错误';
case 401:
return response.data?['detail'] ??
'未授权,请重新登录'; // 401
final authRepository = Get.find<AuthRepository>();
authRepository.clearAuthData();
Get.offAllNamed(AppRoutes.login);
return '未授权,请重新登录';
case 403:
return response.data?['detail'] ?? '访问被拒绝';
case 404:

59
lib/data/repositories/auth_repository.dart

@ -1,4 +1,3 @@
import 'package:dio/dio.dart';
import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';
import 'package:problem_check_system/data/models/auth_model.dart';
@ -86,56 +85,36 @@ class AuthRepository extends GetxService {
/// Handles the user login process by calling the API and saving the response.
Future<LoginResponse> login(LoginRequest request) async {
try {
final response = await httpProvider.post(
'/api/Accounts/SignIn',
data: request.toJson(),
);
final loginResponse = LoginResponse.fromJson(response.data);
return loginResponse;
} catch (e) {
throw Exception(e);
}
final response = await httpProvider.post(
'/api/Accounts/SignIn',
data: request.toJson(),
);
final loginResponse = LoginResponse.fromJson(response.data);
return loginResponse;
}
/// API
Future<User> getUserProfile() async {
try {
final response = await httpProvider.get('/api/Accounts/Profile');
// JSON Profile
return User.fromJson(response.data);
} on DioException catch (e) {
//
// DioException
throw Exception('Network error: ${e.message}');
} catch (e) {
//
rethrow; //
}
final response = await httpProvider.get('/api/Accounts/Profile');
// JSON Profile
return User.fromJson(response.data);
}
/// Refreshes the authentication token using the refresh token.
Future<LoginResponse> refreshToken() async {
final refreshToken = getRefreshToken();
if (refreshToken == null || refreshToken.isEmpty) {
throw Exception('没有可用的刷新token');
}
try {
final response = await httpProvider.post(
'/auth/refresh',
data: {'refresh_token': refreshToken},
);
final response = await httpProvider.post(
'/auth/refresh',
data: {'refresh_token': refreshToken},
);
final authResponse = LoginResponse.fromJson(response.data);
saveToken(authResponse.token);
saveRefreshToken(authResponse.refreshToken);
final authResponse = LoginResponse.fromJson(response.data);
saveToken(authResponse.token);
saveRefreshToken(authResponse.refreshToken);
return authResponse;
} catch (e) {
throw Exception(e);
}
return authResponse;
}
}

11
lib/modules/auth/controllers/login_controller.dart

@ -1,3 +1,4 @@
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:problem_check_system/data/models/auth_model.dart';
@ -59,6 +60,7 @@ class LoginController extends GetxController {
/// 线
Future<void> _onlineLogin(LoginRequest loginRequest) async {
try {
// post
var loginResponse = await _authRepository.login(loginRequest);
//
_authRepository.saveToken(loginResponse.token);
@ -71,8 +73,15 @@ class LoginController extends GetxController {
_authRepository.removeLoginKey();
}
Get.offAllNamed(AppRoutes.home);
//
debugPrint('登录成功: $loginResponse');
} on DioException catch (e) {
// DioException
// Snackbar
debugPrint('登录失败,由DioException捕获: ${e.message}');
} catch (e) {
throw Exception(e);
// DioException
debugPrint('发生未知错误: $e');
}
}

28
lib/modules/my/controllers/my_controller.dart

@ -1,3 +1,4 @@
import 'package:dio/dio.dart';
import 'package:get/get.dart';
import 'package:problem_check_system/app/routes/app_routes.dart';
import 'package:problem_check_system/data/repositories/auth_repository.dart';
@ -18,12 +19,29 @@ class MyController extends GetxController {
_loadUserInfo();
}
// API加载用户信息
// GetxController
RxBool isLoading = false.obs;
/// API加载用户信息
Future<void> _loadUserInfo() async {
var userProfile = await authRepository.getUserProfile();
userName.value = userProfile.name ?? "";
userPhone.value = userProfile.email ?? '138****8547';
userImage.value = userProfile.signatureImage.toString();
// true
isLoading.value = true;
try {
//
final userProfile = await authRepository.getUserProfile();
// null使
userName.value = userProfile.name ?? "";
userPhone.value = userProfile.email ?? '138****8547';
userImage.value = userProfile.signatureImage.toString();
} on DioException catch (e) {
// DioException
// Snackbar
} catch (e) {
// DioException
} finally {
isLoading.value = false;
}
}
void logout() {

48
lib/modules/my/views/my_page.dart

@ -3,26 +3,39 @@ import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:problem_check_system/modules/my/controllers/my_controller.dart';
import '../../../app/routes/app_routes.dart';
import 'package:problem_check_system/app/routes/app_routes.dart';
class MyPage extends GetView<MyController> {
const MyPage({super.key});
@override
Widget build(BuildContext context) {
// MyController
final MyController controller = Get.find<MyController>();
return Scaffold(
body: Stack(
children: [
//
_buildBackground(),
//
_buildContent(controller),
],
),
);
// Obx listens to changes in the controller's observable state,
// such as an isLoading flag, and rebuilds the widget accordingly.
return Obx(() {
// Check if the controller is in a loading state.
// Assuming MyController has a `isLoading` RxBool variable.
if (controller.isLoading.value) {
return const Scaffold(
body: Center(
// Display a CircularProgressIndicator while loading.
child: CircularProgressIndicator(),
),
);
} else {
// If not loading, show the main content.
return Scaffold(
body: Stack(
children: [
//
_buildBackground(),
//
_buildContent(),
],
),
);
}
});
}
///
@ -45,7 +58,7 @@ class MyPage extends GetView<MyController> {
}
///
Widget _buildContent(MyController controller) {
Widget _buildContent() {
return Positioned(
top: 100.h,
left: 20.w,
@ -94,11 +107,6 @@ class MyPage extends GetView<MyController> {
width: 1.w,
),
),
// child: const Icon(
// Icons.person,
// size: 40,
// color: Color(0xFFC8E0FF),
// ),
child: Image.network(
controller.userImage.value,
// Show a CircularProgressIndicator while the image is loading

Loading…
Cancel
Save