Explorar o código

拦截器设置更新。

PC\19500 hai 3 semanas
pai
achega
7a60f0a6d5

+ 35 - 28
lib/core/network/dio_client.dart

@@ -3,42 +3,49 @@ import 'package:sino_med_cloud/core/constants/api_constants.dart';
 import 'package:sino_med_cloud/core/network/interceptors/auth_interceptor.dart';
 import 'package:sino_med_cloud/core/network/interceptors/error_interceptor.dart';
 import 'package:sino_med_cloud/core/network/interceptors/log_interceptor.dart';
+import 'package:sino_med_cloud/core/utils/logger.dart';
 
 /// Dio 客户端 - 统一网络请求管理
 class DioClient {
-  static final Dio _dio = Dio(
-    BaseOptions(
-      baseUrl: ApiConstants.baseUrl,
-      connectTimeout: Duration(seconds: ApiConstants.connectTimeout),
-      receiveTimeout: Duration(seconds: ApiConstants.receiveTimeout),
-      sendTimeout: Duration(seconds: ApiConstants.sendTimeout),
-      headers: {
-        ApiConstants.contentType: ApiConstants.applicationJson,
-      },
-    ),
-  );
-
-  static Dio get dio {
-    // 确保拦截器只添加一次
-    // 拦截器执行顺序:按添加顺序执行
-    // 1. AuthInterceptor - 在请求前添加 Token
-    // 2. LogInterceptor - 记录请求和响应日志
-    // 3. ErrorInterceptor - 统一处理错误
-    if (_dio.interceptors.isEmpty) {
-      _dio.interceptors.addAll([
-        AuthInterceptor(), // 认证拦截器(自动添加 Token)
-        LogInterceptor(), // 日志拦截器(使用 AppLogger 记录日志)
-        ErrorInterceptor(), // 错误拦截器(统一错误处理)
-      ]);
-      // 调试:确认拦截器已添加
-      assert(_dio.interceptors.length == 3, '拦截器应该添加3个');
-    }
-    return _dio;
+  // 使用一个内部方法来创建和配置 Dio 实例
+  static final Dio _dio = _createDio();
+
+  static Dio _createDio() {
+    AppLogger.d('DioClient - 开始创建 Dio 实例并配置拦截器');
+    final dio = Dio(
+      BaseOptions(
+        baseUrl: ApiConstants.baseUrl,
+        connectTimeout: Duration(seconds: ApiConstants.connectTimeout),
+        receiveTimeout: Duration(seconds: ApiConstants.receiveTimeout),
+        sendTimeout: Duration(seconds: ApiConstants.sendTimeout),
+        headers: {
+          ApiConstants.contentType: ApiConstants.applicationJson,
+        },
+      ),
+    );
+
+    // 立即添加拦截器
+    dio.interceptors.addAll([
+      AuthInterceptor(), // 认证拦截器
+      LogInterceptor(), // 日志拦截器
+      ErrorInterceptor(), // 错误拦截器
+    ]);
+
+    AppLogger.d('DioClient - Dio 实例初始化完成,拦截器数量: ${dio.interceptors.length}');
+    return dio;
   }
 
+  // 暴露 dio 实例
+  static Dio get dio => _dio;
+
   /// 重置 Dio 实例(用于重新配置)
   static void reset() {
     _dio.interceptors.clear();
+    _dio.interceptors.addAll([
+      AuthInterceptor(),
+      LogInterceptor(),
+      ErrorInterceptor(),
+    ]);
   }
 
   // ==================== GET 请求 ====================

+ 34 - 16
lib/core/network/interceptors/auth_interceptor.dart

@@ -1,26 +1,44 @@
 import 'package:dio/dio.dart';
 import 'package:sino_med_cloud/core/constants/api_constants.dart';
 import 'package:sino_med_cloud/core/storage/local_storage.dart';
+import 'package:sino_med_cloud/core/utils/logger.dart';
 
 /// 认证拦截器 - 自动添加 Token
 class AuthInterceptor extends Interceptor {
+  AuthInterceptor() {
+    AppLogger.d('AuthInterceptor - 构造函数被调用');
+  }
+  
   @override
-  void onRequest(RequestOptions options, RequestInterceptorHandler handler) async {
-    // 获取 Token(异步,会自动初始化)
-    final token = await LocalStorage.getToken();
-    
-    // 如果存在 Token,添加到请求头
-    if (token != null && token.isNotEmpty) {
-      options.headers[ApiConstants.tokenHeader] = 
-          '${ApiConstants.tokenPrefix} $token';
-    }
-    
-    // 设置 Content-Type
-    if (!options.headers.containsKey(ApiConstants.contentType)) {
-      options.headers[ApiConstants.contentType] = ApiConstants.applicationJson;
-    }
-    
-    super.onRequest(options, handler);
+  void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
+    AppLogger.d('AuthInterceptor.onRequest - 被调用,URL: ${options.uri}');
+    // 使用 Future 处理异步操作
+    LocalStorage.getToken().then((token) {
+      AppLogger.d('AuthInterceptor - 开始处理请求,URL: ${options.uri}');
+      
+      // 如果存在 Token,添加到请求头
+      if (token != null && token.isNotEmpty) {
+        options.headers[ApiConstants.tokenHeader] = 
+            '${ApiConstants.tokenPrefix} $token';
+        AppLogger.d('AuthInterceptor - Token 已添加到请求头: ${ApiConstants.tokenPrefix} $token');
+      } else {
+        AppLogger.w('AuthInterceptor - Token 为空,未添加到请求头');
+      }
+      
+      // 设置 Content-Type
+      if (!options.headers.containsKey(ApiConstants.contentType)) {
+        options.headers[ApiConstants.contentType] = ApiConstants.applicationJson;
+      }
+      
+      // 打印最终的请求头
+      AppLogger.d('AuthInterceptor - 最终请求头: ${options.headers}');
+      
+      // 继续请求
+      handler.next(options);
+    }).catchError((error) {
+      AppLogger.e('AuthInterceptor - 获取 Token 错误', error);
+      handler.next(options);
+    });
   }
 
   @override

+ 30 - 0
lib/features/MinePage/data/quit_model.dart

@@ -0,0 +1,30 @@
+
+class QuitModel {
+  final int code;
+  final bool success;
+  final String msg;
+
+  QuitModel({
+    required this.code,
+    required this.success,
+    required this.msg
+  });
+
+  /// 从 JSON 创建 QuitModel
+  factory QuitModel.fromJson(Map<String, dynamic> json) {
+    return QuitModel(
+      code: json['code'] as int,
+      success: json['success'] as bool,
+      msg: json['msg'] as String,
+    );
+  }
+
+  /// 转换为 JSON
+  Map<String, dynamic> toJson() {
+    return {
+      'code': code,
+      'success': success,
+      'msg': msg,
+    };
+  }
+}

+ 48 - 0
lib/features/MinePage/domain/mine_service.dart

@@ -0,0 +1,48 @@
+import 'package:path/path.dart' as path;
+import '../../../core/constants/api_constants.dart';
+import '../../../core/network/dio_client.dart';
+import '../../../core/storage/local_storage.dart';
+import '../../../core/utils/logger.dart';
+import '../data/quit_model.dart';
+
+class MineService {
+  static Future<QuitModel> logout({
+    required String loginSystem
+  }) async {
+    try {
+      // 在请求之前获取并打印 Token
+      final token = await LocalStorage.getToken();
+      AppLogger.d('退出登录 - 本地存储的 Token: $token');
+      
+      final parame = {
+        "login_system": loginSystem
+      };
+      AppLogger.d('退出登录请求参数: $parame');
+      final response = await DioClient.post<Map<String, dynamic>>(
+        path.join(ApiConstants.baseUrl, ApiConstants.logout),
+        data: parame,
+      );
+
+      if (response.statusCode == 200) {
+        final data = response.data;
+        if (data != null && data['code'] == 20000) {
+          AppLogger.d('退出登录成功: $data');
+          // 解析为 QuitModel
+          final authModel = QuitModel.fromJson(data);
+          return authModel;
+        } else {
+          final errorMsg = data?['message'] ?? '退出登录失败';
+          AppLogger.d('退出登录失败: $errorMsg');
+          throw Exception(errorMsg);
+        }
+      } else {
+        AppLogger.d('退出登录请求错误: ${response.statusCode}, ${response.statusMessage}');
+        throw Exception('请求失败: ${response.statusCode}');
+      }
+    } catch (e) {
+      AppLogger.e('退出登录错误', e);
+      rethrow;
+    }
+
+  }
+}

+ 3 - 1
lib/features/MinePage/presentation/mine_page.dart

@@ -4,6 +4,7 @@ import 'package:go_router/go_router.dart';
 import 'package:sino_med_cloud/l10n/app_localizations.dart';
 
 import '../../main_tab_provider.dart';
+import '../domain/mine_service.dart';
 
 class MinePage extends ConsumerStatefulWidget {
   const MinePage({super.key});
@@ -30,7 +31,8 @@ class _MinePageState extends ConsumerState<MinePage>
   }
 
   // 退出登录
-  void _handleLogout() {
+  void _handleLogout() async {
+    await MineService.logout(loginSystem: "YUN_HIS_PC_WEB");
     ref.read(currentTabIndexProvider.notifier).state = 0;
     Future.microtask(() {
       if (mounted) {

+ 24 - 3
lib/features/auth/presentation/login_page.dart

@@ -36,6 +36,9 @@ class _LoginPageState extends ConsumerState<LoginPage>
   final _phoneSmsController = TextEditingController();
   final _smsCodeController = TextEditingController();
   Timer? _countdownTimer;
+  
+  // 防止循环更新的标志
+  bool _isSyncingPhone = false;
 
   @override
   void initState() {
@@ -52,15 +55,33 @@ class _LoginPageState extends ConsumerState<LoginPage>
     });
     // 同步初始 tab 索引
     ref.read(loginTabIndexProvider.notifier).state = _tabController.index;
-    // 监听输入框变化,同步到 Provider
+    // 监听输入框变化,同步到 Provider 和另一个输入框
     _phoneController.addListener(() {
-      ref.read(passwordLoginPhoneProvider.notifier).state = _phoneController.text;
+      final text = _phoneController.text;
+      ref.read(passwordLoginPhoneProvider.notifier).state = text;
+      
+      // 同步到验证码登录的手机号输入框
+      if (!_isSyncingPhone && _phoneSmsController.text != text) {
+        _isSyncingPhone = true;
+        _phoneSmsController.text = text;
+        ref.read(smsLoginPhoneProvider.notifier).state = text;
+        _isSyncingPhone = false;
+      }
     });
     _passwordController.addListener(() {
       ref.read(passwordLoginPasswordProvider.notifier).state = _passwordController.text;
     });
     _phoneSmsController.addListener(() {
-      ref.read(smsLoginPhoneProvider.notifier).state = _phoneSmsController.text;
+      final text = _phoneSmsController.text;
+      ref.read(smsLoginPhoneProvider.notifier).state = text;
+      
+      // 同步到密码登录的手机号输入框
+      if (!_isSyncingPhone && _phoneController.text != text) {
+        _isSyncingPhone = true;
+        _phoneController.text = text;
+        ref.read(passwordLoginPhoneProvider.notifier).state = text;
+        _isSyncingPhone = false;
+      }
     });
     _smsCodeController.addListener(() {
       ref.read(smsLoginCodeProvider.notifier).state = _smsCodeController.text;