Browse Source

增加网络请求库、登录和个人中心接口联调。

maqiang 1 year ago
parent
commit
b9285b9566

+ 2 - 1
android/app/src/main/AndroidManifest.xml

@@ -11,7 +11,8 @@
11 11
             android:theme="@style/LaunchTheme"
12 12
             android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
13 13
             android:hardwareAccelerated="true"
14
-            android:windowSoftInputMode="adjustResize">
14
+            android:windowSoftInputMode="adjustResize"
15
+            android:networkSecurityConfig="@xml/network_security_config">
15 16
             <!-- Specifies an Android theme to apply to this Activity as soon as
16 17
                  the Android process has started. This theme is visible to the user
17 18
                  while the Flutter UI initializes. After that, this theme continues

+ 5 - 0
android/app/src/main/res/xml/network_security_config.xml

@@ -0,0 +1,5 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<network-security-config>
3
+    <!--  默认配置,是否开启Http流量允许-->
4
+    <base-config cleartextTrafficPermitted="true"/>
5
+</network-security-config>

+ 9 - 1
lib/main.dart

@@ -2,15 +2,23 @@ import 'package:flutter/material.dart';
2 2
 import 'package:flutter/services.dart';
3 3
 import 'package:flutter_localizations/flutter_localizations.dart';
4 4
 import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
5
+import 'package:logger/logger.dart';
6
+import 'package:lszlgl/network/base_dio.dart';
5 7
 import 'package:lszlgl/router/my_navigator.dart';
8
+import 'package:lszlgl/utils/sp_utils.dart';
6 9
 
7
-void main() {
10
+late Logger logger;
11
+
12
+void main() async {
8 13
   WidgetsFlutterBinding.ensureInitialized();
9 14
   SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.light.copyWith(statusBarColor: Colors.transparent));
10 15
   SystemChrome.setPreferredOrientations([
11 16
     DeviceOrientation.portraitUp,
12 17
     DeviceOrientation.portraitDown,
13 18
   ]);
19
+  BaseDio.get().init();
20
+  logger = Logger(printer: PrettyPrinter(methodCount: 0));
21
+  await SPUtils.getInstance().init();
14 22
   runApp(const MyApp());
15 23
 }
16 24
 

+ 25 - 0
lib/network/api.dart

@@ -0,0 +1,25 @@
1
+import 'package:dio/dio.dart';
2
+import 'package:lszlgl/network/base_dio.dart';
3
+import 'package:lszlgl/network/req/login_req.dart';
4
+import 'package:lszlgl/network/api_rsp.dart';
5
+import 'package:lszlgl/network/rsp/login_rsp.dart';
6
+import 'package:lszlgl/network/rsp/user_rsp.dart';
7
+import 'package:retrofit/retrofit.dart';
8
+
9
+part 'api.g.dart';
10
+
11
+@RestApi(baseUrl: 'http://121.36.17.6:9099')
12
+abstract class Api {
13
+  factory Api({Dio? dio, String? baseUrl}) {
14
+    dio ??= BaseDio.get().dio;
15
+    return _Api(dio, baseUrl: baseUrl);
16
+  }
17
+
18
+  /// 登录
19
+  @POST('/admin-api/system/auth/login')
20
+  Future<ApiRsp<LoginRsp>> login(@Body() LoginReq req);
21
+
22
+  /// 获取个人信息
23
+  @GET('/admin-api/system/user/profile/get')
24
+  Future<ApiRsp<UserRsp>> userProfile();
25
+}

+ 31 - 0
lib/network/api_rsp.dart

@@ -0,0 +1,31 @@
1
+import 'package:json_annotation/json_annotation.dart';
2
+
3
+part 'api_rsp.g.dart';
4
+
5
+@JsonSerializable(genericArgumentFactories: true)
6
+class ApiRsp<T> {
7
+  /*
8
+  "code": 0,
9
+  "data": ,
10
+  "msg": "string"
11
+   */
12
+
13
+  final num? code;
14
+  final T? data;
15
+  final String? string;
16
+
17
+  const ApiRsp({
18
+    this.code,
19
+    this.data,
20
+    this.string,
21
+  });
22
+
23
+  factory ApiRsp.fromJson(
24
+    Map<String, dynamic> json,
25
+    T Function(dynamic json) fromJsonT,
26
+  ) =>
27
+      _$ApiRspFromJson<T>(json, fromJsonT);
28
+
29
+  Map<String, dynamic> toJson(Object? Function(T value) toJsonT) => _$ApiRspToJson(this, toJsonT);
30
+
31
+}

+ 181 - 0
lib/network/base_dio.dart

@@ -0,0 +1,181 @@
1
+import 'dart:io';
2
+
3
+import 'package:connectivity_plus/connectivity_plus.dart';
4
+import 'package:dio/dio.dart';
5
+import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
6
+import 'package:lszlgl/main.dart';
7
+import 'package:lszlgl/service/user_service.dart';
8
+
9
+class BaseDio {
10
+  static BaseDio? _instance;
11
+
12
+  static BaseDio get() => _instance ??= BaseDio._();
13
+
14
+  BaseDio._() {
15
+    BaseOptions options = BaseOptions();
16
+
17
+    dio = Dio(options);
18
+
19
+    // 添加request拦截器
20
+    dio.interceptors.add(MyInterceptor());
21
+    // // 添加error拦截器
22
+    // dio.interceptors.add(ErrorInterceptor());
23
+    // // // 添加cache拦截器
24
+    // dio.interceptors.add(NetCacheInterceptor());
25
+    // // // 添加retry拦截器
26
+    // dio.interceptors.add(
27
+    //   RetryOnConnectionChangeInterceptor(
28
+    //     requestRetrier: DioConnectivityRequestRetrier(
29
+    //       dio: dio,
30
+    //       connectivity: Connectivity(),
31
+    //     ),
32
+    //   ),
33
+    // );
34
+  }
35
+
36
+  late final Dio dio;
37
+
38
+  /// 初始化公共属性
39
+  /// * [baseUrl] 前缀地址
40
+  /// * [receiveTimeout] 接收超出时间
41
+  /// * [connectTimeout] 连接超时时间
42
+  /// * [sendTimeout] 发送超时时间
43
+  void init({
44
+    String? baseUrl,
45
+    Duration? receiveTimeout = const Duration(seconds: 60),
46
+    Duration? connectTimeout = const Duration(seconds: 30),
47
+    Duration? sendTimeout = const Duration(seconds: 60),
48
+    Map<String, String>? headers,
49
+    List<Interceptor>? interceptors,
50
+  }) {
51
+    dio.options.copyWith(
52
+      connectTimeout: connectTimeout,
53
+      receiveTimeout: receiveTimeout,
54
+      sendTimeout: sendTimeout,
55
+      headers: headers,
56
+    );
57
+    if (interceptors != null && interceptors.isNotEmpty) {
58
+      dio.interceptors.addAll(interceptors);
59
+    }
60
+  }
61
+}
62
+
63
+/// 拦截器
64
+class MyInterceptor extends Interceptor {
65
+  @override
66
+  void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
67
+    // 请求
68
+    var login = UserService.get().getLogin();
69
+    if (login != null) {
70
+      // 已登录添加token
71
+      options.headers['Authorization'] = 'Bearer ${login.accessToken}';
72
+    }
73
+    Map<String, Object?> map = {};
74
+    map['url'] = options.uri;
75
+    map['method'] = options.method;
76
+    map['headers'] = options.headers;
77
+    map['data'] = options.data;
78
+    if (options.queryParameters.isNotEmpty) map['queryParameters'] = options.queryParameters;
79
+    if (options.extra.isNotEmpty) map['extra'] = options.extra;
80
+    logger.i('ApiRequest: $map');
81
+    super.onRequest(options, handler);
82
+  }
83
+
84
+  @override
85
+  void onResponse(Response response, ResponseInterceptorHandler handler) {
86
+    // 响应
87
+    Map<String, Object?> map = {};
88
+    map['url'] = response.requestOptions.uri;
89
+    map['statusCode'] = response.statusCode;
90
+    map['statusMessage'] = response.statusMessage;
91
+    map['data'] = response.data;
92
+    if (response.extra.isNotEmpty) map['extra'] = response.extra;
93
+    logger.i('ApiResponse: $map');
94
+    super.onResponse(response, handler);
95
+  }
96
+
97
+  // 是否有网
98
+  Future<bool> isConnected() async {
99
+    var connectivityResult = await (Connectivity().checkConnectivity());
100
+    return connectivityResult != ConnectivityResult.none;
101
+  }
102
+
103
+  @override
104
+  void onError(DioException err, ErrorInterceptorHandler handler) async {
105
+    if (err.error != null && err.error is SocketException) {
106
+      var error = err.error as SocketException;
107
+      String message = error.message;
108
+      // 增加网络检测
109
+      if (err.type == DioExceptionType.unknown) {
110
+        bool isConnectNetWork = await isConnected();
111
+        if (!isConnectNetWork) {
112
+          message = '当前网络不可用,请检查您的网络';
113
+        }
114
+      }
115
+      err.copyWith(
116
+        message: message,
117
+        error: SocketException(
118
+          message,
119
+          osError: error.osError,
120
+          address: error.address,
121
+          port: error.port,
122
+        ),
123
+      );
124
+    }
125
+    // error统一处理
126
+    AppException appException = AppException.create(err);
127
+    err.copyWith(error: appException);
128
+    // 响应
129
+    Map<String, Object?> map = {};
130
+    map['url'] = err.requestOptions.uri;
131
+    map['statusCode'] = err.response?.statusCode;
132
+    map['exceptionCode'] = appException.code;
133
+    map['message'] = appException.message;
134
+    if (err.response?.extra.isNotEmpty ?? false) map['extra'] = err.response?.extra;
135
+    logger.e('ApiError: $map');
136
+    SmartDialog.showToast(appException.message ?? '');
137
+    super.onError(err, handler);
138
+  }
139
+}
140
+
141
+/// 自定义异常
142
+class AppException implements Exception {
143
+  final String? message;
144
+  final int code;
145
+
146
+  AppException(
147
+    this.code,
148
+    this.message,
149
+  );
150
+
151
+  @override
152
+  String toString() {
153
+    return 'code:$code, message:$message';
154
+  }
155
+
156
+  factory AppException.create(DioException error) {
157
+    switch (error.type) {
158
+      case DioExceptionType.connectionTimeout:
159
+        return AppException(-1, '连接超时');
160
+      case DioExceptionType.sendTimeout:
161
+        return AppException(-1, '请求超时');
162
+      case DioExceptionType.receiveTimeout:
163
+        return AppException(-1, '响应超时');
164
+      case DioExceptionType.badCertificate:
165
+        return AppException(-1, '证书错误');
166
+      case DioExceptionType.badResponse:
167
+        try {
168
+          int? errCode = error.response!.statusCode;
169
+          return AppException(errCode!, error.response?.data ?? '');
170
+        } catch (_) {
171
+          return AppException(-1, "未知错误");
172
+        }
173
+      case DioExceptionType.cancel:
174
+        return AppException(-1, "请求取消");
175
+      case DioExceptionType.connectionError:
176
+        return AppException(-1, '连接超时');
177
+      case DioExceptionType.unknown:
178
+        return AppException(-1, error.message);
179
+    }
180
+  }
181
+}

+ 18 - 0
lib/network/req/login_req.dart

@@ -0,0 +1,18 @@
1
+import 'package:json_annotation/json_annotation.dart';
2
+
3
+part 'login_req.g.dart';
4
+
5
+@JsonSerializable(genericArgumentFactories: true)
6
+class LoginReq {
7
+  final String? username;
8
+  final String? password;
9
+
10
+  const LoginReq({
11
+    this.username,
12
+    this.password,
13
+  });
14
+
15
+  factory LoginReq.fromJson(Map<String, dynamic> json) => _$LoginReqFromJson(json);
16
+
17
+  Map<String, dynamic> toJson() => _$LoginReqToJson(this);
18
+}

+ 29 - 0
lib/network/rsp/login_rsp.dart

@@ -0,0 +1,29 @@
1
+import 'package:json_annotation/json_annotation.dart';
2
+
3
+part 'login_rsp.g.dart';
4
+
5
+@JsonSerializable(genericArgumentFactories: true)
6
+class LoginRsp {
7
+  /*
8
+    "userId": 1024,
9
+    "accessToken": "happy",
10
+    "refreshToken": "nice",
11
+    "expiresTime": 1708343953434
12
+   */
13
+
14
+  final num? userId;
15
+  final String? accessToken;
16
+  final String? refreshToken;
17
+  final num? expiresTime;
18
+
19
+  const LoginRsp({
20
+    this.userId,
21
+    this.accessToken,
22
+    this.refreshToken,
23
+    this.expiresTime,
24
+  });
25
+
26
+  factory LoginRsp.fromJson(Map<String, dynamic> json) => _$LoginRspFromJson(json);
27
+
28
+  Map<String, dynamic> toJson() => _$LoginRspToJson(this);
29
+}

+ 114 - 0
lib/network/rsp/user_rsp.dart

@@ -0,0 +1,114 @@
1
+import 'package:json_annotation/json_annotation.dart';
2
+
3
+part 'user_rsp.g.dart';
4
+
5
+@JsonSerializable(genericArgumentFactories: true)
6
+class UserRsp {
7
+  /*
8
+  {
9
+        "id": 1,
10
+        "username": "admin",
11
+        "nickname": "超级管理员",
12
+        "email": "aoteman@126.com",
13
+        "mobile": "15612345678",
14
+        "sex": 1,
15
+        "avatar": "http://127.0.0.1:48080/admin-api/infra/file/4/get/37e56010ecbee472cdd821ac4b608e151e62a74d9633f15d085aee026eedeb60.png",
16
+        "loginIp": "210.12.51.197",
17
+        "loginDate": 1708417207000,
18
+        "createTime": 1609837427000,
19
+        "roles": [
20
+            {
21
+                "id": 1,
22
+                "name": "超级管理员"
23
+            }
24
+        ],
25
+        "dept": {
26
+            "id": 3010,
27
+            "name": "国家局",
28
+            "parentId": 0,
29
+            "tyshxydm": null,
30
+            "isRoot": null
31
+        },
32
+        "posts": [
33
+            {
34
+                "id": 1,
35
+                "name": "董事长"
36
+            }
37
+        ],
38
+        "socialUsers": []
39
+    }
40
+   */
41
+
42
+  final num? id;
43
+  final String? username;
44
+  final String? nickname;
45
+  final String? email;
46
+  final String? mobile;
47
+  final num? sex;
48
+  final String? avatar;
49
+  final String? loginIp;
50
+  final num? loginDate;
51
+  final num? createTime;
52
+  final List<EnumRsp>? roles;
53
+  final DepartmentRsp? dept;
54
+  final List<EnumRsp>? posts;
55
+
56
+  const UserRsp({
57
+    this.id,
58
+    this.username,
59
+    this.nickname,
60
+    this.email,
61
+    this.mobile,
62
+    this.sex,
63
+    this.avatar,
64
+    this.loginIp,
65
+    this.loginDate,
66
+    this.createTime,
67
+    this.roles,
68
+    this.dept,
69
+    this.posts,
70
+  });
71
+
72
+  factory UserRsp.fromJson(Map<String, dynamic> json) => _$UserRspFromJson(json);
73
+
74
+  Map<String, dynamic> toJson() => _$UserRspToJson(this);
75
+
76
+  String? getMobile() {
77
+    if (mobile == null) return null;
78
+    var start = mobile!.substring(0, 3);
79
+    var end = mobile!.substring(mobile!.length - 3);
80
+    return '$start*****$end';
81
+  }
82
+}
83
+
84
+@JsonSerializable(genericArgumentFactories: true)
85
+class DepartmentRsp {
86
+  final num? id;
87
+  final String? name;
88
+  final num? parentId;
89
+
90
+  const DepartmentRsp({
91
+    this.id,
92
+    this.name,
93
+    this.parentId,
94
+  });
95
+
96
+  factory DepartmentRsp.fromJson(Map<String, dynamic> json) => _$DepartmentRspFromJson(json);
97
+
98
+  Map<String, dynamic> toJson() => _$DepartmentRspToJson(this);
99
+}
100
+
101
+@JsonSerializable(genericArgumentFactories: true)
102
+class EnumRsp {
103
+  final num? id;
104
+  final String? name;
105
+
106
+  const EnumRsp({
107
+    this.id,
108
+    this.name,
109
+  });
110
+
111
+  factory EnumRsp.fromJson(Map<String, dynamic> json) => _$EnumRspFromJson(json);
112
+
113
+  Map<String, dynamic> toJson() => _$EnumRspToJson(this);
114
+}

+ 34 - 22
lib/page/login/login_page.dart

@@ -1,12 +1,13 @@
1
-import 'package:flutter/cupertino.dart';
2 1
 import 'package:flutter/material.dart';
3 2
 import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart';
4 3
 import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
5
-import 'package:lszlgl/router/my_navigator.dart';
4
+import 'package:lszlgl/base/base_lifecycle_state.dart';
5
+import 'package:lszlgl/network/api.dart';
6
+import 'package:lszlgl/network/req/login_req.dart';
7
+import 'package:lszlgl/service/user_service.dart';
6 8
 import 'package:lszlgl/widget/button.dart';
7 9
 
8 10
 import '../../base/base_state.dart';
9
-import '../main_tab_page.dart';
10 11
 
11 12
 /// 登录页面
12 13
 class LoginPage extends StatefulWidget {
@@ -16,32 +17,56 @@ class LoginPage extends StatefulWidget {
16 17
   State<LoginPage> createState() => _LoginPageState();
17 18
 }
18 19
 
19
-class _LoginPageState extends BaseState<LoginPage> {
20
+class _LoginPageState extends BaseLifecycleState<LoginPage> {
20 21
   late TextEditingController accountCtrl;
21 22
   late TextEditingController pwdCtrl;
22 23
 
23
-  void onLogin() {
24
+  void onLogin() async {
24 25
     var account = accountCtrl.text;
25 26
     var pwd = pwdCtrl.text;
26 27
     if (account.isEmpty || pwd.isEmpty) {
27 28
       SmartDialog.showToast('请输入账号和密码');
28 29
       return;
29 30
     }
31
+    SmartDialog.showLoading();
32
+    try {
33
+      // 登录
34
+      var login = await Api().login(LoginReq(username: account, password: pwd));
35
+      await UserService.get().saveLogin(login.data);
36
+      // 用户信息
37
+      var user = await Api().userProfile();
38
+      await UserService.get().saveUser(user.data);
39
+      SmartDialog.dismiss();
40
+      // 进入主页
41
+      startHome();
42
+    } catch (_) {
43
+      SmartDialog.dismiss();
44
+    }
45
+  }
46
+
47
+  /// 进入主页
48
+  void startHome() {
30 49
     MyRouter.startMain(popAll: true);
31 50
   }
32 51
 
33 52
   @override
34
-  void initState() {
35
-    super.initState();
53
+  void onInit() {
36 54
     accountCtrl = TextEditingController();
37 55
     pwdCtrl = TextEditingController();
38 56
   }
39 57
 
40 58
   @override
41
-  void dispose() {
59
+  void onFirstShow(Duration timeStamp) {
60
+    // 已登录进入主页
61
+    if (UserService.get().getLogin() != null) {
62
+      startHome();
63
+    }
64
+  }
65
+
66
+  @override
67
+  void onDestroy() {
42 68
     accountCtrl.dispose();
43 69
     pwdCtrl.dispose();
44
-    super.dispose();
45 70
   }
46 71
 
47 72
   @override
@@ -49,7 +74,6 @@ class _LoginPageState extends BaseState<LoginPage> {
49 74
     return Scaffold(
50 75
       backgroundColor: const Color(0xFF49AAF2),
51 76
       body: KeyboardDismissOnTap(
52
-        dismissOnCapturedTaps: true,
53 77
         child: SingleChildScrollView(
54 78
           physics: const BouncingScrollPhysics(),
55 79
           child: Stack(
@@ -191,17 +215,5 @@ class _LoginPageState extends BaseState<LoginPage> {
191 215
       onTap: onLogin,
192 216
       gradient: const LinearGradient(colors: [Color(0xFF60B5F4), Color(0xFF62A4D6)]),
193 217
     );
194
-    return GestureDetector(
195
-      onTap: onLogin,
196
-      child: Container(
197
-        alignment: Alignment.center,
198
-        padding: const EdgeInsets.symmetric(vertical: 12),
199
-        decoration: const BoxDecoration(
200
-          gradient: LinearGradient(colors: [Color(0xFF60B5F4), Color(0xFF62A4D6)]),
201
-          borderRadius: BorderRadius.all(Radius.circular(100)),
202
-        ),
203
-        child: const Text('登录', style: TextStyle(fontSize: 16, color: Colors.white)),
204
-      ),
205
-    );
206 218
   }
207 219
 }

+ 2 - 2
lib/page/reap_step/reap_step_list_page.dart

@@ -57,7 +57,7 @@ class _ReapStepListPageState extends State<ReapStepListPage> {
57 57
       infoList = [
58 58
         {'采样品种': '玉米'},
59 59
         {'粮食品类': '粮食品类'},
60
-        {'任务类型': taskType},
60
+        {'监测类别': taskType},
61 61
         {'扦样数量(kg)': '10'},
62 62
         {'扦样人员': '李飞'},
63 63
         {'扦样时间': '2024-01-01'},
@@ -66,7 +66,7 @@ class _ReapStepListPageState extends State<ReapStepListPage> {
66 66
       infoList = [
67 67
         {'采样品种': '玉米'},
68 68
         {'报送截止时间': '2024-01-01'},
69
-        {'任务类型': taskType},
69
+        {'监测类别': taskType},
70 70
         {'扦样人员': '李飞'},
71 71
       ];
72 72
     }

+ 18 - 12
lib/page/user_center/account_manage_page.dart

@@ -1,9 +1,9 @@
1 1
 import 'package:cached_network_image/cached_network_image.dart';
2
-import 'package:flutter/cupertino.dart';
3 2
 import 'package:flutter/material.dart';
3
+import 'package:lszlgl/base/base_lifecycle_state.dart';
4 4
 import 'package:lszlgl/base/base_state.dart';
5
-import 'package:lszlgl/page/login/login_page.dart';
6
-import 'package:lszlgl/page/user_center/change_pwd_page.dart';
5
+import 'package:lszlgl/network/rsp/user_rsp.dart';
6
+import 'package:lszlgl/service/user_service.dart';
7 7
 import 'package:lszlgl/widget/button.dart';
8 8
 import 'package:lszlgl/widget/card_item.dart';
9 9
 
@@ -15,18 +15,24 @@ class AccountManagePage extends StatefulWidget {
15 15
   State<AccountManagePage> createState() => _AccountManagePageState();
16 16
 }
17 17
 
18
-class _AccountManagePageState extends BaseState<AccountManagePage> {
19
-  String userAvatar = 'https://gd-hbimg.huaban.com/4105629c1e4204e2296515d1784f407c903024e7b9ce-Gs4d6A_fw658webp';
18
+class _AccountManagePageState extends BaseLifecycleState<AccountManagePage> {
19
+  UserRsp? user;
20 20
 
21 21
   void startChangePwd() {
22 22
     MyRouter.startChangePwd();
23 23
   }
24 24
 
25 25
   void onLogout() {
26
+    UserService.get().logout();
26 27
     MyRouter.startLogin(popAll: true);
27 28
   }
28 29
 
29 30
   @override
31
+  void onInit() {
32
+    user = UserService.get().getUser();
33
+  }
34
+
35
+  @override
30 36
   Widget build(BuildContext context) {
31 37
     return myScaffold(child: buildBody());
32 38
   }
@@ -59,19 +65,19 @@ class _AccountManagePageState extends BaseState<AccountManagePage> {
59 65
             rightChild: buildAvatar(),
60 66
             bottomLine: true,
61 67
           ),
62
-          const CardItemWidget(
68
+          CardItemWidget(
63 69
             '单位名称',
64
-            rightText: '****',
70
+            rightText: user?.dept?.name ?? '',
65 71
             bottomLine: true,
66 72
           ),
67
-          const CardItemWidget(
73
+          CardItemWidget(
68 74
             '姓名',
69
-            rightText: '****',
75
+            rightText: user?.nickname ?? '',
70 76
             bottomLine: true,
71 77
           ),
72
-          const CardItemWidget(
78
+          CardItemWidget(
73 79
             '账号',
74
-            rightText: '手机号',
80
+            rightText: user?.getMobile() ?? '',
75 81
             bottomLine: true,
76 82
           ),
77 83
           const CardItemWidget(
@@ -97,7 +103,7 @@ class _AccountManagePageState extends BaseState<AccountManagePage> {
97 103
       decoration: const BoxDecoration(borderRadius: BorderRadius.all(Radius.circular(200))),
98 104
       child: CachedNetworkImage(
99 105
         fit: BoxFit.cover,
100
-        imageUrl: userAvatar,
106
+        imageUrl: user?.avatar ?? '',
101 107
         placeholder: (_, __) => const Center(child: CircularProgressIndicator()),
102 108
         errorWidget: (context, url, error) => const Center(child: Icon(Icons.error)),
103 109
       ),

+ 48 - 37
lib/page/user_center/user_center_page.dart

@@ -1,6 +1,9 @@
1 1
 import 'package:cached_network_image/cached_network_image.dart';
2 2
 import 'package:flutter/material.dart';
3
+import 'package:lszlgl/base/base_lifecycle_state.dart';
3 4
 import 'package:lszlgl/base/base_state.dart';
5
+import 'package:lszlgl/network/rsp/user_rsp.dart';
6
+import 'package:lszlgl/service/user_service.dart';
4 7
 import 'package:lszlgl/widget/card_item.dart';
5 8
 
6 9
 /// 用户中心
@@ -11,8 +14,8 @@ class UserCenterPage extends StatefulWidget {
11 14
   State<UserCenterPage> createState() => _UserCenterPageState();
12 15
 }
13 16
 
14
-class _UserCenterPageState extends BaseState<UserCenterPage> with AutomaticKeepAliveClientMixin {
15
-  String userAvatar = 'https://gd-hbimg.huaban.com/4105629c1e4204e2296515d1784f407c903024e7b9ce-Gs4d6A_fw658webp';
17
+class _UserCenterPageState extends BaseLifecycleState<UserCenterPage> with AutomaticKeepAliveClientMixin {
18
+  UserRsp? user;
16 19
 
17 20
   void startAccountManage() {
18 21
     MyRouter.startAccountManage();
@@ -23,6 +26,11 @@ class _UserCenterPageState extends BaseState<UserCenterPage> with AutomaticKeepA
23 26
   }
24 27
 
25 28
   @override
29
+  void onInit() {
30
+    user = UserService.get().getUser();
31
+  }
32
+
33
+  @override
26 34
   Widget build(BuildContext context) {
27 35
     super.build(context);
28 36
     return myScaffold(child: buildBody());
@@ -44,40 +52,43 @@ class _UserCenterPageState extends BaseState<UserCenterPage> with AutomaticKeepA
44 52
   }
45 53
 
46 54
   Widget buildUserInfo() {
47
-    return Container(
48
-      margin: const EdgeInsets.symmetric(horizontal: 12),
49
-      padding: const EdgeInsets.only(left: 8, right: 14, top: 14, bottom: 26),
50
-      clipBehavior: Clip.hardEdge,
51
-      decoration: BoxDecoration(
52
-        borderRadius: const BorderRadius.all(Radius.circular(12)),
53
-        boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.1), offset: const Offset(0, 5), blurRadius: 4)],
54
-        image: const DecorationImage(image: AssetImage(imgHomeListBg), fit: BoxFit.fill),
55
-      ),
56
-      child: Column(
57
-        children: [
58
-          buildUserText('****质检机构'),
59
-          Row(
60
-            children: [
61
-              buildUserAvatar(),
62
-              const SizedBox(width: 12),
63
-              const Column(
64
-                crossAxisAlignment: CrossAxisAlignment.start,
65
-                mainAxisSize: MainAxisSize.min,
66
-                children: [
67
-                  Text(
68
-                    '李某',
69
-                    style: TextStyle(fontSize: 17, color: Color(0xFF333333), fontWeight: FontWeight.w500),
70
-                  ),
71
-                  SizedBox(height: 14),
72
-                  Text(
73
-                    '178*****111',
74
-                    style: TextStyle(fontSize: 17, color: Color(0xFF333333), fontWeight: FontWeight.w500),
75
-                  ),
76
-                ],
77
-              ),
78
-            ],
79
-          ),
80
-        ],
55
+    return GestureDetector(
56
+      onTap: startAccountManage,
57
+      child: Container(
58
+        margin: const EdgeInsets.symmetric(horizontal: 12),
59
+        padding: const EdgeInsets.only(left: 8, right: 14, top: 14, bottom: 26),
60
+        clipBehavior: Clip.hardEdge,
61
+        decoration: BoxDecoration(
62
+          borderRadius: const BorderRadius.all(Radius.circular(12)),
63
+          boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.1), offset: const Offset(0, 5), blurRadius: 4)],
64
+          image: const DecorationImage(image: AssetImage(imgHomeListBg), fit: BoxFit.fill),
65
+        ),
66
+        child: Column(
67
+          children: [
68
+            buildUserText(user?.dept?.name ?? ''),
69
+            Row(
70
+              children: [
71
+                buildUserAvatar(),
72
+                const SizedBox(width: 12),
73
+                Column(
74
+                  crossAxisAlignment: CrossAxisAlignment.start,
75
+                  mainAxisSize: MainAxisSize.min,
76
+                  children: [
77
+                    Text(
78
+                      user?.nickname ?? '',
79
+                      style: const TextStyle(fontSize: 17, color: Color(0xFF333333), fontWeight: FontWeight.w500),
80
+                    ),
81
+                    const SizedBox(height: 14),
82
+                    Text(
83
+                      user?.getMobile() ?? '',
84
+                      style: const TextStyle(fontSize: 17, color: Color(0xFF333333), fontWeight: FontWeight.w500),
85
+                    ),
86
+                  ],
87
+                ),
88
+              ],
89
+            ),
90
+          ],
91
+        ),
81 92
       ),
82 93
     );
83 94
   }
@@ -94,7 +105,7 @@ class _UserCenterPageState extends BaseState<UserCenterPage> with AutomaticKeepA
94 105
       ),
95 106
       child: CachedNetworkImage(
96 107
         fit: BoxFit.cover,
97
-        imageUrl: userAvatar,
108
+        imageUrl: user?.avatar ?? '',
98 109
         placeholder: (_, __) => const Center(child: CircularProgressIndicator()),
99 110
         errorWidget: (context, url, error) => const Center(child: Icon(Icons.error)),
100 111
       ),

+ 54 - 0
lib/service/user_service.dart

@@ -0,0 +1,54 @@
1
+import 'dart:convert';
2
+
3
+import 'package:lszlgl/network/rsp/login_rsp.dart';
4
+import 'package:lszlgl/network/rsp/user_rsp.dart';
5
+import 'package:lszlgl/utils/sp_utils.dart';
6
+
7
+class UserService {
8
+  UserService._();
9
+
10
+  static UserService? _instance;
11
+
12
+  static UserService get() => _instance ??= UserService._();
13
+
14
+  LoginRsp? _login;
15
+  UserRsp? _user;
16
+
17
+  /// 存储登录信息
18
+  Future<void> saveLogin(LoginRsp? value) async {
19
+    if (value == null) return;
20
+    _login = value;
21
+    await SPUtils.getInstance().saveString('login', jsonEncode(value.toJson()));
22
+  }
23
+
24
+  /// 获取登录信息
25
+  LoginRsp? getLogin() {
26
+    if (_login != null) return _login;
27
+    String? login = SPUtils.getInstance().getString('login');
28
+    if (login == null) return null;
29
+    return LoginRsp.fromJson(jsonDecode(login));
30
+  }
31
+
32
+  /// 退出登录
33
+  Future<void> logout() async {
34
+    _login = null;
35
+    await SPUtils.getInstance().remove('login');
36
+    _user = null;
37
+    await SPUtils.getInstance().remove('user');
38
+  }
39
+
40
+  /// 存储用户信息
41
+  Future<void> saveUser(UserRsp? value) async {
42
+    if (value == null) return;
43
+    _user = value;
44
+    await SPUtils.getInstance().saveString('user', jsonEncode(value.toJson()));
45
+  }
46
+
47
+  /// 获取用户信息
48
+  UserRsp? getUser() {
49
+    if (_user != null) return _user;
50
+    String? user = SPUtils.getInstance().getString('user');
51
+    if (user == null) return null;
52
+    return UserRsp.fromJson(jsonDecode(user));
53
+  }
54
+}

+ 82 - 0
lib/utils/sp_utils.dart

@@ -0,0 +1,82 @@
1
+import 'package:shared_preferences/shared_preferences.dart';
2
+
3
+/// 持久化缓存类
4
+///
5
+/// 使用SharedPreferences共享参数存储
6
+class SPUtils {
7
+  SPUtils._();
8
+
9
+  static SPUtils? _instance;
10
+
11
+  static SPUtils getInstance() => _instance ??= SPUtils._();
12
+
13
+  late SharedPreferences _sp;
14
+
15
+  Future<void> init() async {
16
+    _sp = await SharedPreferences.getInstance();
17
+  }
18
+
19
+  /// 获取所有key
20
+  Set<String> getKeys() {
21
+    return _sp.getKeys();
22
+  }
23
+
24
+  /// 是否有key
25
+  bool containsKey(String key) {
26
+    return _sp.containsKey(key);
27
+  }
28
+
29
+  /// 以k,v形式 存储各种类型的值
30
+  ///
31
+  Future<bool> saveString(String key, String value) async {
32
+    return await _sp.setString(key, value);
33
+  }
34
+
35
+  Future<bool> saveInt(String key, int value) async {
36
+    return await _sp.setInt(key, value);
37
+  }
38
+
39
+  Future<bool> saveDouble(String key, double value) async {
40
+    return await _sp.setDouble(key, value);
41
+  }
42
+
43
+  Future<bool> saveBool(String key, bool value) async {
44
+    return await _sp.setBool(key, value);
45
+  }
46
+
47
+  Future<bool> saveStringList(String key, List<String> value) async {
48
+    return await _sp.setStringList(key, value);
49
+  }
50
+
51
+  /// 获取存储的数据
52
+  ///
53
+  String? getString(String key) {
54
+    return _sp.getString(key);
55
+  }
56
+
57
+  int? getInt(String key) {
58
+    return _sp.getInt(key);
59
+  }
60
+
61
+  double? getDouble(String key) {
62
+    return _sp.getDouble(key);
63
+  }
64
+
65
+  bool? getBool(String key) {
66
+    return _sp.getBool(key);
67
+  }
68
+
69
+  List<String>? getStringList(String key) {
70
+    return _sp.getStringList(key);
71
+  }
72
+
73
+  /// 移除存储的数据
74
+  ///
75
+  Future<bool> remove(String key) async {
76
+    return await _sp.remove(key);
77
+  }
78
+
79
+  Future<bool> clear() async {
80
+    return await _sp.clear();
81
+  }
82
+}

+ 4 - 0
macos/Flutter/GeneratedPluginRegistrant.swift

@@ -5,14 +5,18 @@
5 5
 import FlutterMacOS
6 6
 import Foundation
7 7
 
8
+import connectivity_plus
8 9
 import device_info_plus
9 10
 import package_info_plus
10 11
 import path_provider_foundation
12
+import shared_preferences_foundation
11 13
 import sqflite
12 14
 
13 15
 func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
16
+  ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin"))
14 17
   DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
15 18
   FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
16 19
   PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
20
+  SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
17 21
   SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
18 22
 }

+ 449 - 1
pubspec.lock

@@ -1,6 +1,30 @@
1 1
 # Generated by pub
2 2
 # See https://dart.dev/tools/pub/glossary#lockfile
3 3
 packages:
4
+  _fe_analyzer_shared:
5
+    dependency: transitive
6
+    description:
7
+      name: _fe_analyzer_shared
8
+      sha256: eb376e9acf6938204f90eb3b1f00b578640d3188b4c8a8ec054f9f479af8d051
9
+      url: "https://pub.dev"
10
+    source: hosted
11
+    version: "64.0.0"
12
+  analyzer:
13
+    dependency: transitive
14
+    description:
15
+      name: analyzer
16
+      sha256: "69f54f967773f6c26c7dcb13e93d7ccee8b17a641689da39e878d5cf13b06893"
17
+      url: "https://pub.dev"
18
+    source: hosted
19
+    version: "6.2.0"
20
+  args:
21
+    dependency: transitive
22
+    description:
23
+      name: args
24
+      sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596
25
+      url: "https://pub.dev"
26
+    source: hosted
27
+    version: "2.4.2"
4 28
   async:
5 29
     dependency: transitive
6 30
     description:
@@ -17,6 +41,70 @@ packages:
17 41
       url: "https://pub.dev"
18 42
     source: hosted
19 43
     version: "2.1.1"
44
+  build:
45
+    dependency: transitive
46
+    description:
47
+      name: build
48
+      sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0"
49
+      url: "https://pub.dev"
50
+    source: hosted
51
+    version: "2.4.1"
52
+  build_config:
53
+    dependency: transitive
54
+    description:
55
+      name: build_config
56
+      sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1
57
+      url: "https://pub.dev"
58
+    source: hosted
59
+    version: "1.1.1"
60
+  build_daemon:
61
+    dependency: transitive
62
+    description:
63
+      name: build_daemon
64
+      sha256: "0343061a33da9c5810b2d6cee51945127d8f4c060b7fbdd9d54917f0a3feaaa1"
65
+      url: "https://pub.dev"
66
+    source: hosted
67
+    version: "4.0.1"
68
+  build_resolvers:
69
+    dependency: transitive
70
+    description:
71
+      name: build_resolvers
72
+      sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a"
73
+      url: "https://pub.dev"
74
+    source: hosted
75
+    version: "2.4.2"
76
+  build_runner:
77
+    dependency: "direct dev"
78
+    description:
79
+      name: build_runner
80
+      sha256: "581bacf68f89ec8792f5e5a0b2c4decd1c948e97ce659dc783688c8a88fbec21"
81
+      url: "https://pub.dev"
82
+    source: hosted
83
+    version: "2.4.8"
84
+  build_runner_core:
85
+    dependency: transitive
86
+    description:
87
+      name: build_runner_core
88
+      sha256: "4ae8ffe5ac758da294ecf1802f2aff01558d8b1b00616aa7538ea9a8a5d50799"
89
+      url: "https://pub.dev"
90
+    source: hosted
91
+    version: "7.3.0"
92
+  built_collection:
93
+    dependency: transitive
94
+    description:
95
+      name: built_collection
96
+      sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100"
97
+      url: "https://pub.dev"
98
+    source: hosted
99
+    version: "5.1.1"
100
+  built_value:
101
+    dependency: transitive
102
+    description:
103
+      name: built_value
104
+      sha256: a3ec2e0f967bc47f69f95009bb93db936288d61d5343b9436e378b28a2f830c6
105
+      url: "https://pub.dev"
106
+    source: hosted
107
+    version: "8.9.0"
20 108
   cached_network_image:
21 109
     dependency: "direct main"
22 110
     description:
@@ -57,6 +145,14 @@ packages:
57 145
       url: "https://pub.dev"
58 146
     source: hosted
59 147
     version: "1.3.0"
148
+  checked_yaml:
149
+    dependency: transitive
150
+    description:
151
+      name: checked_yaml
152
+      sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff
153
+      url: "https://pub.dev"
154
+    source: hosted
155
+    version: "2.0.3"
60 156
   clock:
61 157
     dependency: transitive
62 158
     description:
@@ -65,6 +161,14 @@ packages:
65 161
       url: "https://pub.dev"
66 162
     source: hosted
67 163
     version: "1.1.1"
164
+  code_builder:
165
+    dependency: transitive
166
+    description:
167
+      name: code_builder
168
+      sha256: f692079e25e7869c14132d39f223f8eec9830eb76131925143b2129c4bb01b37
169
+      url: "https://pub.dev"
170
+    source: hosted
171
+    version: "4.10.0"
68 172
   collection:
69 173
     dependency: transitive
70 174
     description:
@@ -73,6 +177,30 @@ packages:
73 177
       url: "https://pub.dev"
74 178
     source: hosted
75 179
     version: "1.18.0"
180
+  connectivity_plus:
181
+    dependency: "direct main"
182
+    description:
183
+      name: connectivity_plus
184
+      sha256: "224a77051d52a11fbad53dd57827594d3bd24f945af28bd70bab376d68d437f0"
185
+      url: "https://pub.dev"
186
+    source: hosted
187
+    version: "5.0.2"
188
+  connectivity_plus_platform_interface:
189
+    dependency: transitive
190
+    description:
191
+      name: connectivity_plus_platform_interface
192
+      sha256: cf1d1c28f4416f8c654d7dc3cd638ec586076255d407cef3ddbdaf178272a71a
193
+      url: "https://pub.dev"
194
+    source: hosted
195
+    version: "1.2.4"
196
+  convert:
197
+    dependency: transitive
198
+    description:
199
+      name: convert
200
+      sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592"
201
+      url: "https://pub.dev"
202
+    source: hosted
203
+    version: "3.1.1"
76 204
   crypto:
77 205
     dependency: transitive
78 206
     description:
@@ -89,6 +217,14 @@ packages:
89 217
       url: "https://pub.dev"
90 218
     source: hosted
91 219
     version: "1.0.6"
220
+  dart_style:
221
+    dependency: transitive
222
+    description:
223
+      name: dart_style
224
+      sha256: "40ae61a5d43feea6d24bd22c0537a6629db858963b99b4bc1c3db80676f32368"
225
+      url: "https://pub.dev"
226
+    source: hosted
227
+    version: "2.3.4"
92 228
   date_format:
93 229
     dependency: "direct main"
94 230
     description:
@@ -97,6 +233,14 @@ packages:
97 233
       url: "https://pub.dev"
98 234
     source: hosted
99 235
     version: "2.0.7"
236
+  dbus:
237
+    dependency: transitive
238
+    description:
239
+      name: dbus
240
+      sha256: "365c771ac3b0e58845f39ec6deebc76e3276aa9922b0cc60840712094d9047ac"
241
+      url: "https://pub.dev"
242
+    source: hosted
243
+    version: "0.7.10"
100 244
   device_info_plus:
101 245
     dependency: "direct main"
102 246
     description:
@@ -113,6 +257,14 @@ packages:
113 257
       url: "https://pub.dev"
114 258
     source: hosted
115 259
     version: "7.0.0"
260
+  dio:
261
+    dependency: "direct main"
262
+    description:
263
+      name: dio
264
+      sha256: "49af28382aefc53562459104f64d16b9dfd1e8ef68c862d5af436cc8356ce5a8"
265
+      url: "https://pub.dev"
266
+    source: hosted
267
+    version: "5.4.1"
116 268
   fake_async:
117 269
     dependency: transitive
118 270
     description:
@@ -237,6 +389,30 @@ packages:
237 389
     description: flutter
238 390
     source: sdk
239 391
     version: "0.0.0"
392
+  frontend_server_client:
393
+    dependency: transitive
394
+    description:
395
+      name: frontend_server_client
396
+      sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612"
397
+      url: "https://pub.dev"
398
+    source: hosted
399
+    version: "3.2.0"
400
+  glob:
401
+    dependency: transitive
402
+    description:
403
+      name: glob
404
+      sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63"
405
+      url: "https://pub.dev"
406
+    source: hosted
407
+    version: "2.1.2"
408
+  graphs:
409
+    dependency: transitive
410
+    description:
411
+      name: graphs
412
+      sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19
413
+      url: "https://pub.dev"
414
+    source: hosted
415
+    version: "2.3.1"
240 416
   http:
241 417
     dependency: transitive
242 418
     description:
@@ -245,6 +421,14 @@ packages:
245 421
       url: "https://pub.dev"
246 422
     source: hosted
247 423
     version: "1.2.0"
424
+  http_multi_server:
425
+    dependency: transitive
426
+    description:
427
+      name: http_multi_server
428
+      sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b"
429
+      url: "https://pub.dev"
430
+    source: hosted
431
+    version: "3.2.1"
248 432
   http_parser:
249 433
     dependency: transitive
250 434
     description:
@@ -261,6 +445,38 @@ packages:
261 445
       url: "https://pub.dev"
262 446
     source: hosted
263 447
     version: "0.18.1"
448
+  io:
449
+    dependency: transitive
450
+    description:
451
+      name: io
452
+      sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e"
453
+      url: "https://pub.dev"
454
+    source: hosted
455
+    version: "1.0.4"
456
+  js:
457
+    dependency: transitive
458
+    description:
459
+      name: js
460
+      sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
461
+      url: "https://pub.dev"
462
+    source: hosted
463
+    version: "0.6.7"
464
+  json_annotation:
465
+    dependency: "direct main"
466
+    description:
467
+      name: json_annotation
468
+      sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467
469
+      url: "https://pub.dev"
470
+    source: hosted
471
+    version: "4.8.1"
472
+  json_serializable:
473
+    dependency: "direct dev"
474
+    description:
475
+      name: json_serializable
476
+      sha256: aa1f5a8912615733e0fdc7a02af03308933c93235bdc8d50d0b0c8a8ccb0b969
477
+      url: "https://pub.dev"
478
+    source: hosted
479
+    version: "6.7.1"
264 480
   lints:
265 481
     dependency: transitive
266 482
     description:
@@ -269,6 +485,22 @@ packages:
269 485
       url: "https://pub.dev"
270 486
     source: hosted
271 487
     version: "2.1.1"
488
+  logger:
489
+    dependency: "direct main"
490
+    description:
491
+      name: logger
492
+      sha256: "6bbb9d6f7056729537a4309bda2e74e18e5d9f14302489cc1e93f33b3fe32cac"
493
+      url: "https://pub.dev"
494
+    source: hosted
495
+    version: "2.0.2+1"
496
+  logging:
497
+    dependency: transitive
498
+    description:
499
+      name: logging
500
+      sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340"
501
+      url: "https://pub.dev"
502
+    source: hosted
503
+    version: "1.2.0"
272 504
   matcher:
273 505
     dependency: transitive
274 506
     description:
@@ -293,6 +525,22 @@ packages:
293 525
       url: "https://pub.dev"
294 526
     source: hosted
295 527
     version: "1.10.0"
528
+  mime:
529
+    dependency: transitive
530
+    description:
531
+      name: mime
532
+      sha256: "2e123074287cc9fd6c09de8336dae606d1ddb88d9ac47358826db698c176a1f2"
533
+      url: "https://pub.dev"
534
+    source: hosted
535
+    version: "1.0.5"
536
+  nm:
537
+    dependency: transitive
538
+    description:
539
+      name: nm
540
+      sha256: "2c9aae4127bdc8993206464fcc063611e0e36e72018696cd9631023a31b24254"
541
+      url: "https://pub.dev"
542
+    source: hosted
543
+    version: "0.5.0"
296 544
   octo_image:
297 545
     dependency: transitive
298 546
     description:
@@ -301,6 +549,14 @@ packages:
301 549
       url: "https://pub.dev"
302 550
     source: hosted
303 551
     version: "2.0.0"
552
+  package_config:
553
+    dependency: transitive
554
+    description:
555
+      name: package_config
556
+      sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd"
557
+      url: "https://pub.dev"
558
+    source: hosted
559
+    version: "2.1.0"
304 560
   package_info_plus:
305 561
     dependency: "direct main"
306 562
     description:
@@ -373,6 +629,14 @@ packages:
373 629
       url: "https://pub.dev"
374 630
     source: hosted
375 631
     version: "2.2.1"
632
+  petitparser:
633
+    dependency: transitive
634
+    description:
635
+      name: petitparser
636
+      sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27
637
+      url: "https://pub.dev"
638
+    source: hosted
639
+    version: "6.0.2"
376 640
   platform:
377 641
     dependency: transitive
378 642
     description:
@@ -389,6 +653,46 @@ packages:
389 653
       url: "https://pub.dev"
390 654
     source: hosted
391 655
     version: "2.1.8"
656
+  pool:
657
+    dependency: transitive
658
+    description:
659
+      name: pool
660
+      sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a"
661
+      url: "https://pub.dev"
662
+    source: hosted
663
+    version: "1.5.1"
664
+  pub_semver:
665
+    dependency: transitive
666
+    description:
667
+      name: pub_semver
668
+      sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c"
669
+      url: "https://pub.dev"
670
+    source: hosted
671
+    version: "2.1.4"
672
+  pubspec_parse:
673
+    dependency: transitive
674
+    description:
675
+      name: pubspec_parse
676
+      sha256: c63b2876e58e194e4b0828fcb080ad0e06d051cb607a6be51a9e084f47cb9367
677
+      url: "https://pub.dev"
678
+    source: hosted
679
+    version: "1.2.3"
680
+  retrofit:
681
+    dependency: "direct main"
682
+    description:
683
+      name: retrofit
684
+      sha256: "13a2865c0d97da580ea4e3c64d412d81f365fd5b26be2a18fca9582e021da37a"
685
+      url: "https://pub.dev"
686
+    source: hosted
687
+    version: "4.1.0"
688
+  retrofit_generator:
689
+    dependency: "direct dev"
690
+    description:
691
+      name: retrofit_generator
692
+      sha256: "9499eb46b3657a62192ddbc208ff7e6c6b768b19e83c1ee6f6b119c864b99690"
693
+      url: "https://pub.dev"
694
+    source: hosted
695
+    version: "7.0.8"
392 696
   rxdart:
393 697
     dependency: transitive
394 698
     description:
@@ -397,11 +701,99 @@ packages:
397 701
       url: "https://pub.dev"
398 702
     source: hosted
399 703
     version: "0.27.7"
704
+  shared_preferences:
705
+    dependency: "direct main"
706
+    description:
707
+      name: shared_preferences
708
+      sha256: "81429e4481e1ccfb51ede496e916348668fd0921627779233bd24cc3ff6abd02"
709
+      url: "https://pub.dev"
710
+    source: hosted
711
+    version: "2.2.2"
712
+  shared_preferences_android:
713
+    dependency: transitive
714
+    description:
715
+      name: shared_preferences_android
716
+      sha256: "8568a389334b6e83415b6aae55378e158fbc2314e074983362d20c562780fb06"
717
+      url: "https://pub.dev"
718
+    source: hosted
719
+    version: "2.2.1"
720
+  shared_preferences_foundation:
721
+    dependency: transitive
722
+    description:
723
+      name: shared_preferences_foundation
724
+      sha256: "7708d83064f38060c7b39db12aefe449cb8cdc031d6062280087bc4cdb988f5c"
725
+      url: "https://pub.dev"
726
+    source: hosted
727
+    version: "2.3.5"
728
+  shared_preferences_linux:
729
+    dependency: transitive
730
+    description:
731
+      name: shared_preferences_linux
732
+      sha256: "9f2cbcf46d4270ea8be39fa156d86379077c8a5228d9dfdb1164ae0bb93f1faa"
733
+      url: "https://pub.dev"
734
+    source: hosted
735
+    version: "2.3.2"
736
+  shared_preferences_platform_interface:
737
+    dependency: transitive
738
+    description:
739
+      name: shared_preferences_platform_interface
740
+      sha256: "22e2ecac9419b4246d7c22bfbbda589e3acf5c0351137d87dd2939d984d37c3b"
741
+      url: "https://pub.dev"
742
+    source: hosted
743
+    version: "2.3.2"
744
+  shared_preferences_web:
745
+    dependency: transitive
746
+    description:
747
+      name: shared_preferences_web
748
+      sha256: "7b15ffb9387ea3e237bb7a66b8a23d2147663d391cafc5c8f37b2e7b4bde5d21"
749
+      url: "https://pub.dev"
750
+    source: hosted
751
+    version: "2.2.2"
752
+  shared_preferences_windows:
753
+    dependency: transitive
754
+    description:
755
+      name: shared_preferences_windows
756
+      sha256: "841ad54f3c8381c480d0c9b508b89a34036f512482c407e6df7a9c4aa2ef8f59"
757
+      url: "https://pub.dev"
758
+    source: hosted
759
+    version: "2.3.2"
760
+  shelf:
761
+    dependency: transitive
762
+    description:
763
+      name: shelf
764
+      sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4
765
+      url: "https://pub.dev"
766
+    source: hosted
767
+    version: "1.4.1"
768
+  shelf_web_socket:
769
+    dependency: transitive
770
+    description:
771
+      name: shelf_web_socket
772
+      sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1"
773
+      url: "https://pub.dev"
774
+    source: hosted
775
+    version: "1.0.4"
400 776
   sky_engine:
401 777
     dependency: transitive
402 778
     description: flutter
403 779
     source: sdk
404 780
     version: "0.0.99"
781
+  source_gen:
782
+    dependency: transitive
783
+    description:
784
+      name: source_gen
785
+      sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832"
786
+      url: "https://pub.dev"
787
+    source: hosted
788
+    version: "1.5.0"
789
+  source_helper:
790
+    dependency: transitive
791
+    description:
792
+      name: source_helper
793
+      sha256: "6adebc0006c37dd63fe05bca0a929b99f06402fc95aa35bf36d67f5c06de01fd"
794
+      url: "https://pub.dev"
795
+    source: hosted
796
+    version: "1.3.4"
405 797
   source_span:
406 798
     dependency: transitive
407 799
     description:
@@ -450,6 +842,14 @@ packages:
450 842
       url: "https://pub.dev"
451 843
     source: hosted
452 844
     version: "2.1.2"
845
+  stream_transform:
846
+    dependency: transitive
847
+    description:
848
+      name: stream_transform
849
+      sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f"
850
+      url: "https://pub.dev"
851
+    source: hosted
852
+    version: "2.1.0"
453 853
   string_scanner:
454 854
     dependency: transitive
455 855
     description:
@@ -498,6 +898,22 @@ packages:
498 898
       url: "https://pub.dev"
499 899
     source: hosted
500 900
     version: "0.6.1"
901
+  timing:
902
+    dependency: transitive
903
+    description:
904
+      name: timing
905
+      sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32"
906
+      url: "https://pub.dev"
907
+    source: hosted
908
+    version: "1.0.1"
909
+  tuple:
910
+    dependency: transitive
911
+    description:
912
+      name: tuple
913
+      sha256: a97ce2013f240b2f3807bcbaf218765b6f301c3eff91092bcfa23a039e7dd151
914
+      url: "https://pub.dev"
915
+    source: hosted
916
+    version: "2.0.2"
501 917
   typed_data:
502 918
     dependency: transitive
503 919
     description:
@@ -522,6 +938,14 @@ packages:
522 938
       url: "https://pub.dev"
523 939
     source: hosted
524 940
     version: "2.1.4"
941
+  watcher:
942
+    dependency: transitive
943
+    description:
944
+      name: watcher
945
+      sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8"
946
+      url: "https://pub.dev"
947
+    source: hosted
948
+    version: "1.1.0"
525 949
   web:
526 950
     dependency: transitive
527 951
     description:
@@ -530,6 +954,14 @@ packages:
530 954
       url: "https://pub.dev"
531 955
     source: hosted
532 956
     version: "0.3.0"
957
+  web_socket_channel:
958
+    dependency: transitive
959
+    description:
960
+      name: web_socket_channel
961
+      sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b
962
+      url: "https://pub.dev"
963
+    source: hosted
964
+    version: "2.4.0"
533 965
   win32:
534 966
     dependency: transitive
535 967
     description:
@@ -554,6 +986,22 @@ packages:
554 986
       url: "https://pub.dev"
555 987
     source: hosted
556 988
     version: "1.0.4"
989
+  xml:
990
+    dependency: transitive
991
+    description:
992
+      name: xml
993
+      sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226
994
+      url: "https://pub.dev"
995
+    source: hosted
996
+    version: "6.5.0"
997
+  yaml:
998
+    dependency: transitive
999
+    description:
1000
+      name: yaml
1001
+      sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5"
1002
+      url: "https://pub.dev"
1003
+    source: hosted
1004
+    version: "3.1.2"
557 1005
 sdks:
558 1006
   dart: ">=3.2.0 <4.0.0"
559
-  flutter: ">=3.10.0"
1007
+  flutter: ">=3.16.0"

+ 17 - 0
pubspec.yaml

@@ -54,6 +54,18 @@ dependencies:
54 54
   date_format: ^2.0.7
55 55
   # 日期选择器
56 56
   syncfusion_flutter_datepicker: ^24.2.4
57
+  # 网络连接状态
58
+  connectivity_plus: ^5.0.2
59
+  # 网络请求
60
+  dio: ^5.4.1
61
+  # 网络请求
62
+  retrofit: '>=4.0.0 <5.0.0'
63
+  # log打印
64
+  logger: ^2.0.2+1
65
+  # json解析
66
+  json_annotation: ^4.8.1
67
+  # 共享参数
68
+  shared_preferences: ^2.2.2
57 69
 
58 70
 dev_dependencies:
59 71
   flutter_test:
@@ -66,6 +78,11 @@ dev_dependencies:
66 78
   # rules and activating additional ones.
67 79
   flutter_lints: ^2.0.0
68 80
 
81
+  retrofit_generator: '>=7.0.0 <8.0.0'
82
+  build_runner: '>=2.3.0 <4.0.0'
83
+  # JSON转实体类
84
+  json_serializable: ^6.6.2
85
+
69 86
 # For information on the generic Dart part of this file, see the
70 87
 # following page: https://dart.dev/tools/pub/pubspec
71 88
 

+ 3 - 0
windows/flutter/generated_plugin_registrant.cc

@@ -6,6 +6,9 @@
6 6
 
7 7
 #include "generated_plugin_registrant.h"
8 8
 
9
+#include <connectivity_plus/connectivity_plus_windows_plugin.h>
9 10
 
10 11
 void RegisterPlugins(flutter::PluginRegistry* registry) {
12
+  ConnectivityPlusWindowsPluginRegisterWithRegistrar(
13
+      registry->GetRegistrarForPlugin("ConnectivityPlusWindowsPlugin"));
11 14
 }

+ 1 - 0
windows/flutter/generated_plugins.cmake

@@ -3,6 +3,7 @@
3 3
 #
4 4
 
5 5
 list(APPEND FLUTTER_PLUGIN_LIST
6
+  connectivity_plus
6 7
 )
7 8
 
8 9
 list(APPEND FLUTTER_FFI_PLUGIN_LIST