Browse Source

1.0 完成网络请求封装

alroyso 1 year ago
parent
commit
909de4d0ac

+ 48 - 0
lib/app/common/SecureStorageUtil.dart

@@ -0,0 +1,48 @@
+import 'dart:convert';
+import 'package:flutter_secure_storage/flutter_secure_storage.dart';
+
+class SecureStorageUtil {
+  // 单例对象
+  static final SecureStorageUtil _singleton = SecureStorageUtil._internal();
+
+  // 私有构造函数
+  SecureStorageUtil._internal();
+
+  // 工厂构造函数返回单例对象
+  factory SecureStorageUtil() => _singleton;
+
+  // Secure Storage 实例
+  final _storage = const FlutterSecureStorage();
+
+  // 存储字符串
+  Future<void> setString(String key, String value) async {
+    await _storage.write(key: key, value: value);
+  }
+
+  // 读取字符串
+  Future<String?> getString(String key) async {
+    return await _storage.read(key: key);
+  }
+
+  // 存储JSON数组
+  Future<void> setJsonList(String key, List<Map<String, dynamic>> jsonList) async {
+    final jsonString = jsonEncode(jsonList);
+    await _storage.write(key: key, value: jsonString);
+  }
+
+  // 读取JSON数组
+  Future<List<Map<String, dynamic>>?> getJsonList(String key) async {
+    final jsonString = await _storage.read(key: key);
+    return jsonString != null ? List<Map<String, dynamic>>.from(jsonDecode(jsonString)) : null;
+  }
+
+  // 删除指定键的数据
+  Future<void> delete(String key) async {
+    await _storage.delete(key: key);
+  }
+
+  // 删除所有数据
+  Future<void> deleteAll() async {
+    await _storage.deleteAll();
+  }
+}

+ 56 - 0
lib/app/data/model/SysConfig.dart

@@ -0,0 +1,56 @@
+class SysConfig {
+  String? affurl;
+  String? userLoginUrl;
+  String? userLoginUrlKe;
+  String? userBuy;
+  String? userTicket;
+  String? userReg;
+  String? userReset;
+  String? userTutorial;
+  String? userRofile;
+  String? userDownload;
+  int? tag;
+
+  SysConfig(
+      {this.affurl,
+        this.userLoginUrl,
+        this.userLoginUrlKe,
+        this.userBuy,
+        this.userTicket,
+        this.userReg,
+        this.userReset,
+        this.userTutorial,
+        this.userRofile,
+        this.userDownload,
+        this.tag});
+
+  SysConfig.fromJson(Map<String, dynamic> json) {
+    affurl = json['affurl'];
+    userLoginUrl = json['user_login_url'];
+    userLoginUrlKe = json['user_login_url_ke'];
+    userBuy = json['user_buy'];
+    userTicket = json['user_ticket'];
+    userReg = json['user_reg'];
+    userReset = json['user_reset'];
+    userTutorial = json['user_tutorial'];
+    userRofile = json['user_rofile'];
+    userDownload = json['user_download'];
+    tag = json['tag'];
+  }
+
+  Map<String, dynamic> toJson() {
+    final Map<String, dynamic> data = new Map<String, dynamic>();
+    data['affurl'] = this.affurl;
+    data['user_login_url'] = this.userLoginUrl;
+    data['user_login_url_ke'] = this.userLoginUrlKe;
+    data['user_buy'] = this.userBuy;
+    data['user_ticket'] = this.userTicket;
+    data['user_reg'] = this.userReg;
+    data['user_reset'] = this.userReset;
+    data['user_tutorial'] = this.userTutorial;
+    data['user_rofile'] = this.userRofile;
+    data['user_download'] = this.userDownload;
+    data['tag'] = this.tag;
+    return data;
+  }
+}

+ 20 - 2
lib/app/modules/home/controllers/home_controller.dart

@@ -1,16 +1,34 @@
 import 'package:flutter/cupertino.dart';
 import 'package:get/get.dart';
 
+import '../../../data/model/SysConfig.dart';
+import '../../../network/api_service.dart';
+
 class HomeController extends GetxController {
   //TODO: Implement HomeController
 
+  var isLoading = true.obs;
+  var sysConfig = SysConfig().obs;
+  var errorMsg = ''.obs;
+
+  Future<void> fetchSysConfig() async {
+    try {
+      isLoading.value = true;
+      sysConfig.value = await ApiService().fetchSysConfig("/api/client/v3/getconfig");
+      print(sysConfig.value.affurl);
+    } catch (e) {
+      errorMsg.value = e.toString();
+    } finally {
+      isLoading.value = false;
+    }
+  }
+
   final count = 0.obs;
   @override
   void onInit() {
 
-
-
     super.onInit();
+    //fetchSysConfig();
   }
 
   @override

+ 1 - 0
lib/app/modules/home/views/home_view.dart

@@ -25,6 +25,7 @@ class HomeView extends GetView<HomeController> {
         appBar: const SysAppBar(title: Text("登录"),),
 
         body: LoginScreen(onLogin: (username,password) {
+          controller.fetchSysConfig();
           // 在这里处理登录逻辑,例如调用API
           print('Username: $username');
           print('Password: $password');

+ 37 - 0
lib/app/network/api_service.dart

@@ -0,0 +1,37 @@
+import '../data/model/SysConfig.dart';
+import 'dio_client.dart';
+
+class ApiService {
+  static final ApiService _instance = ApiService._internal();
+  final DioClient _dioClient = DioClient();
+
+  factory ApiService() => _instance;
+
+  ApiService._internal();
+
+
+  Future<SysConfig> fetchSysConfig(String path) async {
+    try {
+      final Map<String, dynamic> data = await _dioClient.get(path);
+      return SysConfig.fromJson(data);
+    } catch (e) {
+      throw Exception('Failed to fetch user: $e');
+    }
+  }
+
+  Future<Map<String, dynamic>> fetchData(String path, {Map<String, dynamic>? queryParameters}) async {
+    return await _dioClient.get(path, queryParameters: queryParameters);
+  }
+
+  Future<Map<String, dynamic>> createData(String path, {Map<String, dynamic>? data}) async {
+    return await _dioClient.post(path, data: data);
+  }
+
+  Future<Map<String, dynamic>> updateData(String path, {Map<String, dynamic>? data}) async {
+    return await _dioClient.put(path, data: data);
+  }
+
+  Future<void> downloadFile(String urlPath, String savePath) async {
+    await _dioClient.download(urlPath, savePath);
+  }
+}

+ 84 - 0
lib/app/core/dio_client.dart → lib/app/network/dio_client.dart

@@ -1,9 +1,12 @@
+import 'dart:convert';
 import 'dart:io';
 
 import 'package:connectivity_plus/connectivity_plus.dart';
 import 'package:dio/dio.dart';
 import 'package:flutter/cupertino.dart';
+import 'package:logger/logger.dart';
 
+import '../common/SecureStorageUtil.dart';
 //import 'custom_interceptors.dart';
 
 class DioClient {
@@ -11,6 +14,7 @@ class DioClient {
   late Dio _dio;
 
   factory DioClient() => _instance;
+  final Logger _logger = Logger();
 
   DioClient._internal() {
     _dio = Dio(BaseOptions(
@@ -19,12 +23,72 @@ class DioClient {
       receiveTimeout: 3000,
     ));
 
+    // 仅在调试模式下添加日志拦截器
+    assert(() {
+      _dio.interceptors.add(LogInterceptor(
+        request: true,
+        requestBody: true,
+        responseBody: true,
+        error: true,
+        logPrint: _logger.d, // 使用 Logger 插件打印日志
+      ));
+      return true;
+    }());
+
+    //token
+    _dio.interceptors.add(TokenInterceptor());
     // 添加拦截器
     _dio.interceptors.add(CustomInterceptors());
+
+    // 添加响应拦截器
+    _dio.interceptors.add(InterceptorsWrapper(
+      onResponse: (Response<dynamic> response, ResponseInterceptorHandler handler) {
+        final responseData = response.data as Map<String, dynamic>;
+        if (responseData['ret'] == 1) {
+          handler.next(
+            Response<dynamic>(
+              data: responseData['data'],
+              headers: response.headers,
+              requestOptions: response.requestOptions,
+              statusCode: response.statusCode,
+            ),
+          );
+        } else {
+          handler.reject(
+            DioError(
+              requestOptions: response.requestOptions,
+              error: AppException(message: responseData['msg'] ?? 'Unknown Error'),
+            ),
+          );
+        }
+      },
+    ));
+
+
   }
 
   Dio get dio => _dio;
 }
+
+class TokenInterceptor extends Interceptor {
+  // 这里假设您有一个方法来从安全存储中获取Token
+  Future<String?> getToken() async {
+    // 从您存储Token的地方获取Token,例如从SharedPreferences或SecureStorage
+    String? token = await SecureStorageUtil().getString("token");
+    return token;
+    //return "Your_Token";
+  }
+
+  @override
+  Future<void> onRequest(RequestOptions options, RequestInterceptorHandler handler) async {
+    final token = await getToken();
+    if (token != null) {
+      options.headers["Authorization"] = "Bearer $token";
+    }
+    return super.onRequest(options, handler);
+  }
+}
+
 class CustomInterceptors extends Interceptor {
   int _retryCount = 0;
   final List<String> _backupUrls = ['https://api.androidrj03.top', 'https://api.androidrj88.com'];
@@ -119,3 +183,23 @@ class AppException implements Exception {
     return message;
   }
 }
+extension DioClientExtension on DioClient {
+  Future<Map<String, dynamic>> get(String path, {Map<String, dynamic>? queryParameters}) async {
+    final response = await _dio.get(path, queryParameters: queryParameters);
+    return response.data as Map<String, dynamic>;
+  }
+
+  Future<Map<String, dynamic>> post(String path, {Map<String, dynamic>? data}) async {
+    final response = await _dio.post(path, data: data);
+    return response.data as Map<String, dynamic>;
+  }
+
+  Future<Map<String, dynamic>> put(String path, {Map<String, dynamic>? data}) async {
+    final response = await _dio.put(path, data: data);
+    return response.data as Map<String, dynamic>;
+  }
+
+  Future<void> download(String urlPath, String savePath) async {
+    await _dio.download(urlPath, savePath);
+  }
+}

+ 4 - 0
linux/flutter/generated_plugin_registrant.cc

@@ -6,10 +6,14 @@
 
 #include "generated_plugin_registrant.h"
 
+#include <flutter_secure_storage_linux/flutter_secure_storage_linux_plugin.h>
 #include <screen_retriever/screen_retriever_plugin.h>
 #include <window_manager/window_manager_plugin.h>
 
 void fl_register_plugins(FlPluginRegistry* registry) {
+  g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar =
+      fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin");
+  flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar);
   g_autoptr(FlPluginRegistrar) screen_retriever_registrar =
       fl_plugin_registry_get_registrar_for_plugin(registry, "ScreenRetrieverPlugin");
   screen_retriever_plugin_register_with_registrar(screen_retriever_registrar);

+ 1 - 0
linux/flutter/generated_plugins.cmake

@@ -3,6 +3,7 @@
 #
 
 list(APPEND FLUTTER_PLUGIN_LIST
+  flutter_secure_storage_linux
   screen_retriever
   window_manager
 )

+ 2 - 0
macos/Flutter/GeneratedPluginRegistrant.swift

@@ -6,11 +6,13 @@ import FlutterMacOS
 import Foundation
 
 import connectivity_plus_macos
+import flutter_secure_storage_macos
 import screen_retriever
 import window_manager
 
 func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
   ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin"))
+  FlutterSecureStorageMacosPlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStorageMacosPlugin"))
   ScreenRetrieverPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverPlugin"))
   WindowManagerPlugin.register(with: registry.registrar(forPlugin: "WindowManagerPlugin"))
 }

+ 7 - 1
macos/Podfile.lock

@@ -2,6 +2,8 @@ PODS:
   - connectivity_plus_macos (0.0.1):
     - FlutterMacOS
     - ReachabilitySwift
+  - flutter_secure_storage_macos (3.3.1):
+    - FlutterMacOS
   - FlutterMacOS (1.0.0)
   - ReachabilitySwift (5.0.0)
   - screen_retriever (0.0.1):
@@ -11,6 +13,7 @@ PODS:
 
 DEPENDENCIES:
   - connectivity_plus_macos (from `Flutter/ephemeral/.symlinks/plugins/connectivity_plus_macos/macos`)
+  - flutter_secure_storage_macos (from `Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos`)
   - FlutterMacOS (from `Flutter/ephemeral`)
   - screen_retriever (from `Flutter/ephemeral/.symlinks/plugins/screen_retriever/macos`)
   - window_manager (from `Flutter/ephemeral/.symlinks/plugins/window_manager/macos`)
@@ -22,6 +25,8 @@ SPEC REPOS:
 EXTERNAL SOURCES:
   connectivity_plus_macos:
     :path: Flutter/ephemeral/.symlinks/plugins/connectivity_plus_macos/macos
+  flutter_secure_storage_macos:
+    :path: Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos
   FlutterMacOS:
     :path: Flutter/ephemeral
   screen_retriever:
@@ -31,6 +36,7 @@ EXTERNAL SOURCES:
 
 SPEC CHECKSUMS:
   connectivity_plus_macos: f6e86fd000e971d361e54b5afcadc8c8fa773308
+  flutter_secure_storage_macos: 6ceee8fbc7f484553ad17f79361b556259df89aa
   FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
   ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
   screen_retriever: 59634572a57080243dd1bf715e55b6c54f241a38
@@ -38,4 +44,4 @@ SPEC CHECKSUMS:
 
 PODFILE CHECKSUM: 236401fc2c932af29a9fcf0e97baeeb2d750d367
 
-COCOAPODS: 1.13.0
+COCOAPODS: 1.12.1

+ 2 - 0
macos/Runner/DebugProfile.entitlements

@@ -8,5 +8,7 @@
 	<true/>
 	<key>com.apple.security.network.server</key>
 	<true/>
+	<key>com.apple.security.network.client</key>
+    <true/>
 </dict>
 </plist>

+ 2 - 0
macos/Runner/Release.entitlements

@@ -4,5 +4,7 @@
 <dict>
 	<key>com.apple.security.app-sandbox</key>
 	<true/>
+	<key>com.apple.security.network.client</key>
+    <true/>
 </dict>
 </plist>

+ 2 - 0
pubspec.yaml

@@ -17,6 +17,8 @@ dependencies:
     sdk: flutter
   dio: ^4.0.6
   connectivity_plus: ^2.3.6
+  flutter_secure_storage: ^5.0.2
+
 dev_dependencies: 
   flutter_lints: ^2.0.0
   flutter_test: 

+ 3 - 0
windows/flutter/generated_plugin_registrant.cc

@@ -7,12 +7,15 @@
 #include "generated_plugin_registrant.h"
 
 #include <connectivity_plus_windows/connectivity_plus_windows_plugin.h>
+#include <flutter_secure_storage_windows/flutter_secure_storage_windows_plugin.h>
 #include <screen_retriever/screen_retriever_plugin.h>
 #include <window_manager/window_manager_plugin.h>
 
 void RegisterPlugins(flutter::PluginRegistry* registry) {
   ConnectivityPlusWindowsPluginRegisterWithRegistrar(
       registry->GetRegistrarForPlugin("ConnectivityPlusWindowsPlugin"));
+  FlutterSecureStorageWindowsPluginRegisterWithRegistrar(
+      registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin"));
   ScreenRetrieverPluginRegisterWithRegistrar(
       registry->GetRegistrarForPlugin("ScreenRetrieverPlugin"));
   WindowManagerPluginRegisterWithRegistrar(

+ 1 - 0
windows/flutter/generated_plugins.cmake

@@ -4,6 +4,7 @@
 
 list(APPEND FLUTTER_PLUGIN_LIST
   connectivity_plus_windows
+  flutter_secure_storage_windows
   screen_retriever
   window_manager
 )