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:dio/dio.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart' hide Response; import 'package:get/get.dart' hide Response;
import 'package:pretty_dio_logger/pretty_dio_logger.dart'; 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'; import 'package:problem_check_system/data/repositories/auth_repository.dart';
// DioProvider GetxService // DioProvider GetxService
// Dio // Dio
class HttpProvider extends GetxService { class HttpProvider extends GetxService {
static const String _baseUrl = 'https://xh.anxincloud.cn'; static const String _baseUrl = 'https://xhdev.anxincloud.cn';
late final Dio _dio; late final Dio _dio;
@ -40,72 +42,7 @@ class HttpProvider extends GetxService {
} }
List<Interceptor> _getInterceptors() { List<Interceptor> _getInterceptors() {
return [ return [_getErrorInterceptor(), if (kDebugMode) _getLoggerInterceptor()];
_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);
},
);
} }
/// ///
@ -124,20 +61,59 @@ class HttpProvider extends GetxService {
/// Snackbar /// Snackbar
Interceptor _getErrorInterceptor() { Interceptor _getErrorInterceptor() {
return InterceptorsWrapper( 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) { onError: (error, handler) {
// //
if (error.type == DioExceptionType.connectionTimeout || if (error.type == DioExceptionType.connectionTimeout ||
error.type == DioExceptionType.receiveTimeout || error.type == DioExceptionType.receiveTimeout ||
error.type == DioExceptionType.sendTimeout) { error.type == DioExceptionType.sendTimeout) {
Get.snackbar('网络超时', '请检查网络连接后重试'); Get.snackbar(
'网络超时',
'请检查网络连接后重试',
colorText: Colors.white,
backgroundColor: Colors.red,
snackPosition: SnackPosition.TOP,
);
} else if (error.type == DioExceptionType.unknown) { } else if (error.type == DioExceptionType.unknown) {
Get.snackbar('网络异常', '请检查网络连接后重试'); Get.snackbar(
'网络异常',
'请检查网络连接后重试',
colorText: Colors.white,
backgroundColor: Colors.red,
snackPosition: SnackPosition.TOP,
);
} }
// AuthInterceptor 401 // AuthInterceptor 401
if (error.response != null) { if (error.response != null) {
final message = _handleStatusCode(error.response!); final message = _handleStatusCode(error.response!);
Get.snackbar('请求错误', message); Get.snackbar(
'请求错误',
message,
colorText: Colors.white,
backgroundColor: Colors.red,
snackPosition: SnackPosition.TOP,
);
} }
return handler.next(error); return handler.next(error);
@ -151,8 +127,10 @@ class HttpProvider extends GetxService {
case 400: case 400:
return response.data?['detail'] ?? '请求参数错误'; return response.data?['detail'] ?? '请求参数错误';
case 401: case 401:
return response.data?['detail'] ?? final authRepository = Get.find<AuthRepository>();
'未授权,请重新登录'; // 401 authRepository.clearAuthData();
Get.offAllNamed(AppRoutes.login);
return '未授权,请重新登录';
case 403: case 403:
return response.data?['detail'] ?? '访问被拒绝'; return response.data?['detail'] ?? '访问被拒绝';
case 404: 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/get.dart';
import 'package:get_storage/get_storage.dart'; import 'package:get_storage/get_storage.dart';
import 'package:problem_check_system/data/models/auth_model.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. /// Handles the user login process by calling the API and saving the response.
Future<LoginResponse> login(LoginRequest request) async { Future<LoginResponse> login(LoginRequest request) async {
try { final response = await httpProvider.post(
final response = await httpProvider.post( '/api/Accounts/SignIn',
'/api/Accounts/SignIn', data: request.toJson(),
data: request.toJson(), );
);
final loginResponse = LoginResponse.fromJson(response.data);
final loginResponse = LoginResponse.fromJson(response.data); return loginResponse;
return loginResponse;
} catch (e) {
throw Exception(e);
}
} }
/// API /// API
Future<User> getUserProfile() async { Future<User> getUserProfile() async {
try { final response = await httpProvider.get('/api/Accounts/Profile');
final response = await httpProvider.get('/api/Accounts/Profile');
// JSON Profile
// JSON Profile return User.fromJson(response.data);
return User.fromJson(response.data);
} on DioException catch (e) {
//
// DioException
throw Exception('Network error: ${e.message}');
} catch (e) {
//
rethrow; //
}
} }
/// Refreshes the authentication token using the refresh token. /// Refreshes the authentication token using the refresh token.
Future<LoginResponse> refreshToken() async { Future<LoginResponse> refreshToken() async {
final refreshToken = getRefreshToken(); final refreshToken = getRefreshToken();
if (refreshToken == null || refreshToken.isEmpty) {
throw Exception('没有可用的刷新token');
}
try { final response = await httpProvider.post(
final response = await httpProvider.post( '/auth/refresh',
'/auth/refresh', data: {'refresh_token': refreshToken},
data: {'refresh_token': refreshToken}, );
);
final authResponse = LoginResponse.fromJson(response.data); final authResponse = LoginResponse.fromJson(response.data);
saveToken(authResponse.token); saveToken(authResponse.token);
saveRefreshToken(authResponse.refreshToken); saveRefreshToken(authResponse.refreshToken);
return authResponse; return authResponse;
} catch (e) {
throw Exception(e);
}
} }
} }

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

@ -1,3 +1,4 @@
import 'package:dio/dio.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:problem_check_system/data/models/auth_model.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 { Future<void> _onlineLogin(LoginRequest loginRequest) async {
try { try {
// post
var loginResponse = await _authRepository.login(loginRequest); var loginResponse = await _authRepository.login(loginRequest);
// //
_authRepository.saveToken(loginResponse.token); _authRepository.saveToken(loginResponse.token);
@ -71,8 +73,15 @@ class LoginController extends GetxController {
_authRepository.removeLoginKey(); _authRepository.removeLoginKey();
} }
Get.offAllNamed(AppRoutes.home); Get.offAllNamed(AppRoutes.home);
//
debugPrint('登录成功: $loginResponse');
} on DioException catch (e) {
// DioException
// Snackbar
debugPrint('登录失败,由DioException捕获: ${e.message}');
} catch (e) { } 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:get/get.dart';
import 'package:problem_check_system/app/routes/app_routes.dart'; import 'package:problem_check_system/app/routes/app_routes.dart';
import 'package:problem_check_system/data/repositories/auth_repository.dart'; import 'package:problem_check_system/data/repositories/auth_repository.dart';
@ -18,12 +19,29 @@ class MyController extends GetxController {
_loadUserInfo(); _loadUserInfo();
} }
// API加载用户信息 // GetxController
RxBool isLoading = false.obs;
/// API加载用户信息
Future<void> _loadUserInfo() async { Future<void> _loadUserInfo() async {
var userProfile = await authRepository.getUserProfile(); // true
userName.value = userProfile.name ?? ""; isLoading.value = true;
userPhone.value = userProfile.email ?? '138****8547'; try {
userImage.value = userProfile.signatureImage.toString(); //
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() { 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:get/get.dart';
import 'package:problem_check_system/modules/my/controllers/my_controller.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> { class MyPage extends GetView<MyController> {
const MyPage({super.key}); const MyPage({super.key});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
// MyController // Obx listens to changes in the controller's observable state,
final MyController controller = Get.find<MyController>(); // such as an isLoading flag, and rebuilds the widget accordingly.
return Obx(() {
return Scaffold( // Check if the controller is in a loading state.
body: Stack( // Assuming MyController has a `isLoading` RxBool variable.
children: [ if (controller.isLoading.value) {
// return const Scaffold(
_buildBackground(), body: Center(
// // Display a CircularProgressIndicator while loading.
_buildContent(controller), 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( return Positioned(
top: 100.h, top: 100.h,
left: 20.w, left: 20.w,
@ -94,11 +107,6 @@ class MyPage extends GetView<MyController> {
width: 1.w, width: 1.w,
), ),
), ),
// child: const Icon(
// Icons.person,
// size: 40,
// color: Color(0xFFC8E0FF),
// ),
child: Image.network( child: Image.network(
controller.userImage.value, controller.userImage.value,
// Show a CircularProgressIndicator while the image is loading // Show a CircularProgressIndicator while the image is loading

Loading…
Cancel
Save