Pārlūkot izejas kodu

国康在线问诊功能对接

gjh 2 nedēļas atpakaļ
vecāks
revīzija
c04fb8c2b8

+ 116 - 0
docs/国康在线问诊H5对接文档.md

@@ -0,0 +1,116 @@
1
+# 在线问诊H5对接文档
2
+
3
+## 通信方式
4
+
5
+使用JsBridge的方式进行通信
6
+
7
+H5大致实现逻辑
8
+1.window监听flutterInAppWebViewPlatformReady事件
9
+2.使用window.flutter_inappwebview.callHandler方法调用app端方法,callHandler会返回一个Promise
10
+3.app直接调用js方法(暂无)
11
+
12
+具体实现方式参考文档JavaScript Handlers部分中js相关部分:https://inappwebview.dev/docs/webview/javascript/communication#javascript-handlers
13
+
14
+# 接口
15
+
16
+## H5调用app端
17
+
18
+### 关闭当前页面
19
+
20
+| 方法名    | 参数 | 返回值 |
21
+| :-------- | :--- | :----- |
22
+| closePage | 无   | 无     |
23
+
24
+### 打开URL
25
+
26
+| 方法名  | 参数1              | 参数2                             | 返回值 |
27
+| :------ | :----------------- | :-------------------------------- | :----- |
28
+| openUrl | 类型字符串,url地址 | 类型整数,是否在新页面打开,0否,1是 | 无     |
29
+
30
+### 选择照片
31
+
32
+| 方法名      | 参数1                                | 返回值                                                                                       |
33
+| :---------- | :----------------------------------- | :------------------------------------------------------------------------------------------- |
34
+| selectPhoto | 类型整数,最多选择数量,0单选,其他多选 | base64字符串数组,长度0表示用户没有选择照片,其中base64字符串不包含"data:image/jpeg;base64,"头 |
35
+
36
+### 查看图片
37
+
38
+| 方法名    | 参数1              | 返回值 |
39
+| :-------- | :----------------- | :----- |
40
+| viewPhoto | 类型字符串,图片url | 无     |
41
+
42
+# 测试代码
43
+
44
+``` html
45
+<!DOCTYPE html>
46
+<html>
47
+<head>
48
+    <meta charset="UTF-8">
49
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
50
+    <script>
51
+        //环境是否准备好
52
+        var isFlutterInAppWebViewReady = false;
53
+        //监听环境准备完毕事件
54
+        window.addEventListener("flutterInAppWebViewPlatformReady", function(event) {
55
+            isFlutterInAppWebViewReady = true;
56
+        });
57
+        window.onload = function() {
58
+            //打开URL
59
+            var button = document.getElementById('openUrl');
60
+            button.addEventListener('click', function() {
61
+                if(isFlutterInAppWebViewReady)
62
+                {
63
+                    window.flutter_inappwebview.callHandler('openUrl', "http://www.baidu.com");
64
+                }
65
+            });
66
+
67
+            //关闭页面
68
+            button = document.getElementById('closePage');
69
+            button.addEventListener('click', function() {
70
+                if(isFlutterInAppWebViewReady)
71
+                {
72
+                    window.flutter_inappwebview.callHandler('closePage');
73
+                }
74
+            });
75
+
76
+            //选择照片
77
+            button = document.getElementById('selectPhoto');
78
+            button.addEventListener('click', function() {
79
+                if(isFlutterInAppWebViewReady)
80
+                {
81
+                    window.flutter_inappwebview.callHandler('selectPhoto',3)
82
+                    .then(function(args){
83
+                        for(var i=0;i<args.length;i++)
84
+                        {
85
+                            var img = document.createElement('img');
86
+                            img.src = "data:image/jpeg;base64,"+args[i];
87
+                            img.width = 200;
88
+                            img.height = 150;
89
+
90
+                            var body = document.body;
91
+                            body.appendChild(img);
92
+                        }
93
+
94
+                    });
95
+                }
96
+            });
97
+
98
+            //查看图片
99
+            button = document.getElementById('viewPhoto');
100
+            button.addEventListener('click', function() {
101
+                if(isFlutterInAppWebViewReady)
102
+                {
103
+                    window.flutter_inappwebview.callHandler('viewPhoto', "https://inews.gtimg.com/om_bt/O0e2a37GGF5CDfNgK8GU29rF_2eJlHLDsa17LABXns7V4AA/641");
104
+                }
105
+            });
106
+        };
107
+    </script>
108
+</head>
109
+<body>
110
+<button id="openUrl">打开Url</button>
111
+<button id="closePage">关闭页面</button>
112
+<button id="selectPhoto">选择照片</button>
113
+<button id="viewPhoto">查看图片</button>
114
+</body>
115
+</html>
116
+```

+ 2 - 0
lib/app_router.dart

@@ -26,5 +26,7 @@ class AppRouter extends RootStackRouter {
26 26
         AutoRoute(page: PhotoPreviewRoute.page),
27 27
         AutoRoute(page: VideoPreviewRoute.page),
28 28
         AutoRoute(page: SelectHistoryRoute.page),
29
+        AutoRoute(page: OnlineConsultationRoute.page),
30
+        AutoRoute(page: OnlinePictureViewRoute.page),
29 31
       ];
30 32
 }

+ 240 - 136
lib/app_router.gr.dart

@@ -8,50 +8,54 @@
8 8
 // coverage:ignore-file
9 9
 
10 10
 // ignore_for_file: no_leading_underscores_for_library_prefixes
11
-import 'dart:async' as _i25;
11
+import 'dart:async' as _i27;
12 12
 
13
-import 'package:auto_route/auto_route.dart' as _i19;
14
-import 'package:eitc_erm_dental_flutter/entity/clinic_info.dart' as _i24;
13
+import 'package:auto_route/auto_route.dart' as _i21;
14
+import 'package:eitc_erm_dental_flutter/entity/clinic_info.dart' as _i26;
15 15
 import 'package:eitc_erm_dental_flutter/entity/db/local_patient_info.dart'
16
-    as _i22;
17
-import 'package:eitc_erm_dental_flutter/entity/history_item_info.dart' as _i23;
16
+    as _i24;
17
+import 'package:eitc_erm_dental_flutter/entity/history_item_info.dart' as _i25;
18
+import 'package:eitc_erm_dental_flutter/pages/consultation/online_consultation_page.dart'
19
+    as _i7;
18 20
 import 'package:eitc_erm_dental_flutter/pages/history/history_page.dart' as _i4;
19 21
 import 'package:eitc_erm_dental_flutter/pages/history/photo_view_page.dart'
20
-    as _i9;
22
+    as _i11;
21 23
 import 'package:eitc_erm_dental_flutter/pages/history/select_history_page.dart'
22
-    as _i10;
24
+    as _i12;
23 25
 import 'package:eitc_erm_dental_flutter/pages/history/video_player_page.dart'
24
-    as _i15;
26
+    as _i17;
25 27
 import 'package:eitc_erm_dental_flutter/pages/login/login_page.dart' as _i5;
26 28
 import 'package:eitc_erm_dental_flutter/pages/main/main_page.dart' as _i6;
27 29
 import 'package:eitc_erm_dental_flutter/pages/patient/add_patient_page.dart'
28 30
     as _i1;
29 31
 import 'package:eitc_erm_dental_flutter/pages/patient/patient_list_page.dart'
30
-    as _i7;
32
+    as _i9;
31 33
 import 'package:eitc_erm_dental_flutter/pages/settings/delay_shot_settings_page.dart'
32 34
     as _i2;
33 35
 import 'package:eitc_erm_dental_flutter/pages/settings/faqs_page.dart' as _i3;
34 36
 import 'package:eitc_erm_dental_flutter/pages/settings/settings_page.dart'
35
-    as _i11;
36
-import 'package:eitc_erm_dental_flutter/pages/splash/splash_page.dart' as _i12;
37
-import 'package:eitc_erm_dental_flutter/pages/upload/upload_page.dart' as _i13;
37
+    as _i13;
38
+import 'package:eitc_erm_dental_flutter/pages/splash/splash_page.dart' as _i14;
39
+import 'package:eitc_erm_dental_flutter/pages/upload/upload_page.dart' as _i15;
38 40
 import 'package:eitc_erm_dental_flutter/pages/upload/upload_select_clinic_page.dart'
39
-    as _i14;
40
-import 'package:eitc_erm_dental_flutter/pages/view/photo_preview_page.dart'
41
+    as _i16;
42
+import 'package:eitc_erm_dental_flutter/pages/view/online_picture_view_page.dart'
41 43
     as _i8;
44
+import 'package:eitc_erm_dental_flutter/pages/view/photo_preview_page.dart'
45
+    as _i10;
42 46
 import 'package:eitc_erm_dental_flutter/pages/view/video_preview_page.dart'
43
-    as _i16;
47
+    as _i18;
44 48
 import 'package:eitc_erm_dental_flutter/pages/view/video_view_page.dart'
45
-    as _i17;
46
-import 'package:eitc_erm_dental_flutter/pages/web/webview_page.dart' as _i18;
47
-import 'package:flutter/foundation.dart' as _i20;
48
-import 'package:flutter/material.dart' as _i21;
49
-import 'package:retrofit/dio.dart' as _i26;
49
+    as _i19;
50
+import 'package:eitc_erm_dental_flutter/pages/web/webview_page.dart' as _i20;
51
+import 'package:flutter/foundation.dart' as _i22;
52
+import 'package:flutter/material.dart' as _i23;
53
+import 'package:retrofit/dio.dart' as _i28;
50 54
 
51 55
 /// generated route for
52 56
 /// [_i1.AddPatientPage]
53
-class AddPatientRoute extends _i19.PageRouteInfo<void> {
54
-  const AddPatientRoute({List<_i19.PageRouteInfo>? children})
57
+class AddPatientRoute extends _i21.PageRouteInfo<void> {
58
+  const AddPatientRoute({List<_i21.PageRouteInfo>? children})
55 59
       : super(
56 60
           AddPatientRoute.name,
57 61
           initialChildren: children,
@@ -59,7 +63,7 @@ class AddPatientRoute extends _i19.PageRouteInfo<void> {
59 63
 
60 64
   static const String name = 'AddPatientRoute';
61 65
 
62
-  static _i19.PageInfo page = _i19.PageInfo(
66
+  static _i21.PageInfo page = _i21.PageInfo(
63 67
     name,
64 68
     builder: (data) {
65 69
       return const _i1.AddPatientPage();
@@ -69,8 +73,8 @@ class AddPatientRoute extends _i19.PageRouteInfo<void> {
69 73
 
70 74
 /// generated route for
71 75
 /// [_i2.DelayShotSettingsPage]
72
-class DelayShotSettingsRoute extends _i19.PageRouteInfo<void> {
73
-  const DelayShotSettingsRoute({List<_i19.PageRouteInfo>? children})
76
+class DelayShotSettingsRoute extends _i21.PageRouteInfo<void> {
77
+  const DelayShotSettingsRoute({List<_i21.PageRouteInfo>? children})
74 78
       : super(
75 79
           DelayShotSettingsRoute.name,
76 80
           initialChildren: children,
@@ -78,7 +82,7 @@ class DelayShotSettingsRoute extends _i19.PageRouteInfo<void> {
78 82
 
79 83
   static const String name = 'DelayShotSettingsRoute';
80 84
 
81
-  static _i19.PageInfo page = _i19.PageInfo(
85
+  static _i21.PageInfo page = _i21.PageInfo(
82 86
     name,
83 87
     builder: (data) {
84 88
       return const _i2.DelayShotSettingsPage();
@@ -88,8 +92,8 @@ class DelayShotSettingsRoute extends _i19.PageRouteInfo<void> {
88 92
 
89 93
 /// generated route for
90 94
 /// [_i3.FaqsPage]
91
-class FaqsRoute extends _i19.PageRouteInfo<void> {
92
-  const FaqsRoute({List<_i19.PageRouteInfo>? children})
95
+class FaqsRoute extends _i21.PageRouteInfo<void> {
96
+  const FaqsRoute({List<_i21.PageRouteInfo>? children})
93 97
       : super(
94 98
           FaqsRoute.name,
95 99
           initialChildren: children,
@@ -97,7 +101,7 @@ class FaqsRoute extends _i19.PageRouteInfo<void> {
97 101
 
98 102
   static const String name = 'FaqsRoute';
99 103
 
100
-  static _i19.PageInfo page = _i19.PageInfo(
104
+  static _i21.PageInfo page = _i21.PageInfo(
101 105
     name,
102 106
     builder: (data) {
103 107
       return const _i3.FaqsPage();
@@ -107,8 +111,8 @@ class FaqsRoute extends _i19.PageRouteInfo<void> {
107 111
 
108 112
 /// generated route for
109 113
 /// [_i4.HistoryPage]
110
-class HistoryRoute extends _i19.PageRouteInfo<void> {
111
-  const HistoryRoute({List<_i19.PageRouteInfo>? children})
114
+class HistoryRoute extends _i21.PageRouteInfo<void> {
115
+  const HistoryRoute({List<_i21.PageRouteInfo>? children})
112 116
       : super(
113 117
           HistoryRoute.name,
114 118
           initialChildren: children,
@@ -116,7 +120,7 @@ class HistoryRoute extends _i19.PageRouteInfo<void> {
116 120
 
117 121
   static const String name = 'HistoryRoute';
118 122
 
119
-  static _i19.PageInfo page = _i19.PageInfo(
123
+  static _i21.PageInfo page = _i21.PageInfo(
120 124
     name,
121 125
     builder: (data) {
122 126
       return const _i4.HistoryPage();
@@ -126,11 +130,11 @@ class HistoryRoute extends _i19.PageRouteInfo<void> {
126 130
 
127 131
 /// generated route for
128 132
 /// [_i5.LoginPage]
129
-class LoginRoute extends _i19.PageRouteInfo<LoginRouteArgs> {
133
+class LoginRoute extends _i21.PageRouteInfo<LoginRouteArgs> {
130 134
   LoginRoute({
131
-    _i20.Key? key,
135
+    _i22.Key? key,
132 136
     required bool cancelable,
133
-    List<_i19.PageRouteInfo>? children,
137
+    List<_i21.PageRouteInfo>? children,
134 138
   }) : super(
135 139
           LoginRoute.name,
136 140
           args: LoginRouteArgs(
@@ -142,7 +146,7 @@ class LoginRoute extends _i19.PageRouteInfo<LoginRouteArgs> {
142 146
 
143 147
   static const String name = 'LoginRoute';
144 148
 
145
-  static _i19.PageInfo page = _i19.PageInfo(
149
+  static _i21.PageInfo page = _i21.PageInfo(
146 150
     name,
147 151
     builder: (data) {
148 152
       final args = data.argsAs<LoginRouteArgs>();
@@ -160,7 +164,7 @@ class LoginRouteArgs {
160 164
     required this.cancelable,
161 165
   });
162 166
 
163
-  final _i20.Key? key;
167
+  final _i22.Key? key;
164 168
 
165 169
   final bool cancelable;
166 170
 
@@ -172,8 +176,8 @@ class LoginRouteArgs {
172 176
 
173 177
 /// generated route for
174 178
 /// [_i6.MainPage]
175
-class MainRoute extends _i19.PageRouteInfo<void> {
176
-  const MainRoute({List<_i19.PageRouteInfo>? children})
179
+class MainRoute extends _i21.PageRouteInfo<void> {
180
+  const MainRoute({List<_i21.PageRouteInfo>? children})
177 181
       : super(
178 182
           MainRoute.name,
179 183
           initialChildren: children,
@@ -181,7 +185,7 @@ class MainRoute extends _i19.PageRouteInfo<void> {
181 185
 
182 186
   static const String name = 'MainRoute';
183 187
 
184
-  static _i19.PageInfo page = _i19.PageInfo(
188
+  static _i21.PageInfo page = _i21.PageInfo(
185 189
     name,
186 190
     builder: (data) {
187 191
       return const _i6.MainPage();
@@ -190,12 +194,112 @@ class MainRoute extends _i19.PageRouteInfo<void> {
190 194
 }
191 195
 
192 196
 /// generated route for
193
-/// [_i7.PatientListPage]
194
-class PatientListRoute extends _i19.PageRouteInfo<PatientListRouteArgs> {
197
+/// [_i7.OnlineConsultationPage]
198
+class OnlineConsultationRoute
199
+    extends _i21.PageRouteInfo<OnlineConsultationRouteArgs> {
200
+  OnlineConsultationRoute({
201
+    _i22.Key? key,
202
+    required String url,
203
+    bool backAlert = false,
204
+    List<_i21.PageRouteInfo>? children,
205
+  }) : super(
206
+          OnlineConsultationRoute.name,
207
+          args: OnlineConsultationRouteArgs(
208
+            key: key,
209
+            url: url,
210
+            backAlert: backAlert,
211
+          ),
212
+          initialChildren: children,
213
+        );
214
+
215
+  static const String name = 'OnlineConsultationRoute';
216
+
217
+  static _i21.PageInfo page = _i21.PageInfo(
218
+    name,
219
+    builder: (data) {
220
+      final args = data.argsAs<OnlineConsultationRouteArgs>();
221
+      return _i7.OnlineConsultationPage(
222
+        key: args.key,
223
+        url: args.url,
224
+        backAlert: args.backAlert,
225
+      );
226
+    },
227
+  );
228
+}
229
+
230
+class OnlineConsultationRouteArgs {
231
+  const OnlineConsultationRouteArgs({
232
+    this.key,
233
+    required this.url,
234
+    this.backAlert = false,
235
+  });
236
+
237
+  final _i22.Key? key;
238
+
239
+  final String url;
240
+
241
+  final bool backAlert;
242
+
243
+  @override
244
+  String toString() {
245
+    return 'OnlineConsultationRouteArgs{key: $key, url: $url, backAlert: $backAlert}';
246
+  }
247
+}
248
+
249
+/// generated route for
250
+/// [_i8.OnlinePictureViewPage]
251
+class OnlinePictureViewRoute
252
+    extends _i21.PageRouteInfo<OnlinePictureViewRouteArgs> {
253
+  OnlinePictureViewRoute({
254
+    _i23.Key? key,
255
+    required String url,
256
+    List<_i21.PageRouteInfo>? children,
257
+  }) : super(
258
+          OnlinePictureViewRoute.name,
259
+          args: OnlinePictureViewRouteArgs(
260
+            key: key,
261
+            url: url,
262
+          ),
263
+          initialChildren: children,
264
+        );
265
+
266
+  static const String name = 'OnlinePictureViewRoute';
267
+
268
+  static _i21.PageInfo page = _i21.PageInfo(
269
+    name,
270
+    builder: (data) {
271
+      final args = data.argsAs<OnlinePictureViewRouteArgs>();
272
+      return _i8.OnlinePictureViewPage(
273
+        key: args.key,
274
+        url: args.url,
275
+      );
276
+    },
277
+  );
278
+}
279
+
280
+class OnlinePictureViewRouteArgs {
281
+  const OnlinePictureViewRouteArgs({
282
+    this.key,
283
+    required this.url,
284
+  });
285
+
286
+  final _i23.Key? key;
287
+
288
+  final String url;
289
+
290
+  @override
291
+  String toString() {
292
+    return 'OnlinePictureViewRouteArgs{key: $key, url: $url}';
293
+  }
294
+}
295
+
296
+/// generated route for
297
+/// [_i9.PatientListPage]
298
+class PatientListRoute extends _i21.PageRouteInfo<PatientListRouteArgs> {
195 299
   PatientListRoute({
196
-    _i21.Key? key,
300
+    _i23.Key? key,
197 301
     bool selectable = true,
198
-    List<_i19.PageRouteInfo>? children,
302
+    List<_i21.PageRouteInfo>? children,
199 303
   }) : super(
200 304
           PatientListRoute.name,
201 305
           args: PatientListRouteArgs(
@@ -207,12 +311,12 @@ class PatientListRoute extends _i19.PageRouteInfo<PatientListRouteArgs> {
207 311
 
208 312
   static const String name = 'PatientListRoute';
209 313
 
210
-  static _i19.PageInfo page = _i19.PageInfo(
314
+  static _i21.PageInfo page = _i21.PageInfo(
211 315
     name,
212 316
     builder: (data) {
213 317
       final args = data.argsAs<PatientListRouteArgs>(
214 318
           orElse: () => const PatientListRouteArgs());
215
-      return _i7.PatientListPage(
319
+      return _i9.PatientListPage(
216 320
         key: args.key,
217 321
         selectable: args.selectable,
218 322
       );
@@ -226,7 +330,7 @@ class PatientListRouteArgs {
226 330
     this.selectable = true,
227 331
   });
228 332
 
229
-  final _i21.Key? key;
333
+  final _i23.Key? key;
230 334
 
231 335
   final bool selectable;
232 336
 
@@ -237,18 +341,18 @@ class PatientListRouteArgs {
237 341
 }
238 342
 
239 343
 /// generated route for
240
-/// [_i8.PhotoPreviewPage]
241
-class PhotoPreviewRoute extends _i19.PageRouteInfo<PhotoPreviewRouteArgs> {
344
+/// [_i10.PhotoPreviewPage]
345
+class PhotoPreviewRoute extends _i21.PageRouteInfo<PhotoPreviewRouteArgs> {
242 346
   PhotoPreviewRoute({
243
-    _i21.Key? key,
244
-    required _i22.LocalPatientInfo info,
347
+    _i23.Key? key,
348
+    required _i24.LocalPatientInfo info,
245 349
     required String path,
246 350
     required String area,
247 351
     required DateTime time,
248 352
     required String mobile,
249 353
     required String deviceModel,
250 354
     required String wifi,
251
-    List<_i19.PageRouteInfo>? children,
355
+    List<_i21.PageRouteInfo>? children,
252 356
   }) : super(
253 357
           PhotoPreviewRoute.name,
254 358
           args: PhotoPreviewRouteArgs(
@@ -266,11 +370,11 @@ class PhotoPreviewRoute extends _i19.PageRouteInfo<PhotoPreviewRouteArgs> {
266 370
 
267 371
   static const String name = 'PhotoPreviewRoute';
268 372
 
269
-  static _i19.PageInfo page = _i19.PageInfo(
373
+  static _i21.PageInfo page = _i21.PageInfo(
270 374
     name,
271 375
     builder: (data) {
272 376
       final args = data.argsAs<PhotoPreviewRouteArgs>();
273
-      return _i8.PhotoPreviewPage(
377
+      return _i10.PhotoPreviewPage(
274 378
         key: args.key,
275 379
         info: args.info,
276 380
         path: args.path,
@@ -296,9 +400,9 @@ class PhotoPreviewRouteArgs {
296 400
     required this.wifi,
297 401
   });
298 402
 
299
-  final _i21.Key? key;
403
+  final _i23.Key? key;
300 404
 
301
-  final _i22.LocalPatientInfo info;
405
+  final _i24.LocalPatientInfo info;
302 406
 
303 407
   final String path;
304 408
 
@@ -319,12 +423,12 @@ class PhotoPreviewRouteArgs {
319 423
 }
320 424
 
321 425
 /// generated route for
322
-/// [_i9.PhotoViewPage]
323
-class PhotoViewRoute extends _i19.PageRouteInfo<PhotoViewRouteArgs> {
426
+/// [_i11.PhotoViewPage]
427
+class PhotoViewRoute extends _i21.PageRouteInfo<PhotoViewRouteArgs> {
324 428
   PhotoViewRoute({
325
-    _i21.Key? key,
326
-    required _i23.HistoryItemInfo? info,
327
-    List<_i19.PageRouteInfo>? children,
429
+    _i23.Key? key,
430
+    required _i25.HistoryItemInfo? info,
431
+    List<_i21.PageRouteInfo>? children,
328 432
   }) : super(
329 433
           PhotoViewRoute.name,
330 434
           args: PhotoViewRouteArgs(
@@ -336,11 +440,11 @@ class PhotoViewRoute extends _i19.PageRouteInfo<PhotoViewRouteArgs> {
336 440
 
337 441
   static const String name = 'PhotoViewRoute';
338 442
 
339
-  static _i19.PageInfo page = _i19.PageInfo(
443
+  static _i21.PageInfo page = _i21.PageInfo(
340 444
     name,
341 445
     builder: (data) {
342 446
       final args = data.argsAs<PhotoViewRouteArgs>();
343
-      return _i9.PhotoViewPage(
447
+      return _i11.PhotoViewPage(
344 448
         key: args.key,
345 449
         info: args.info,
346 450
       );
@@ -354,9 +458,9 @@ class PhotoViewRouteArgs {
354 458
     required this.info,
355 459
   });
356 460
 
357
-  final _i21.Key? key;
461
+  final _i23.Key? key;
358 462
 
359
-  final _i23.HistoryItemInfo? info;
463
+  final _i25.HistoryItemInfo? info;
360 464
 
361 465
   @override
362 466
   String toString() {
@@ -365,15 +469,15 @@ class PhotoViewRouteArgs {
365 469
 }
366 470
 
367 471
 /// generated route for
368
-/// [_i10.SelectHistoryPage]
369
-class SelectHistoryRoute extends _i19.PageRouteInfo<SelectHistoryRouteArgs> {
472
+/// [_i12.SelectHistoryPage]
473
+class SelectHistoryRoute extends _i21.PageRouteInfo<SelectHistoryRouteArgs> {
370 474
   SelectHistoryRoute({
371
-    _i21.Key? key,
372
-    required _i10.SelectHistoryType selectType,
475
+    _i23.Key? key,
476
+    required _i12.SelectHistoryType selectType,
373 477
     required bool isFillterPatient,
374 478
     bool isMultiSelect = false,
375 479
     int maxCount = 0,
376
-    List<_i19.PageRouteInfo>? children,
480
+    List<_i21.PageRouteInfo>? children,
377 481
   }) : super(
378 482
           SelectHistoryRoute.name,
379 483
           args: SelectHistoryRouteArgs(
@@ -388,11 +492,11 @@ class SelectHistoryRoute extends _i19.PageRouteInfo<SelectHistoryRouteArgs> {
388 492
 
389 493
   static const String name = 'SelectHistoryRoute';
390 494
 
391
-  static _i19.PageInfo page = _i19.PageInfo(
495
+  static _i21.PageInfo page = _i21.PageInfo(
392 496
     name,
393 497
     builder: (data) {
394 498
       final args = data.argsAs<SelectHistoryRouteArgs>();
395
-      return _i10.SelectHistoryPage(
499
+      return _i12.SelectHistoryPage(
396 500
         key: args.key,
397 501
         selectType: args.selectType,
398 502
         isFillterPatient: args.isFillterPatient,
@@ -412,9 +516,9 @@ class SelectHistoryRouteArgs {
412 516
     this.maxCount = 0,
413 517
   });
414 518
 
415
-  final _i21.Key? key;
519
+  final _i23.Key? key;
416 520
 
417
-  final _i10.SelectHistoryType selectType;
521
+  final _i12.SelectHistoryType selectType;
418 522
 
419 523
   final bool isFillterPatient;
420 524
 
@@ -429,9 +533,9 @@ class SelectHistoryRouteArgs {
429 533
 }
430 534
 
431 535
 /// generated route for
432
-/// [_i11.SettingsPage]
433
-class SettingsRoute extends _i19.PageRouteInfo<void> {
434
-  const SettingsRoute({List<_i19.PageRouteInfo>? children})
536
+/// [_i13.SettingsPage]
537
+class SettingsRoute extends _i21.PageRouteInfo<void> {
538
+  const SettingsRoute({List<_i21.PageRouteInfo>? children})
435 539
       : super(
436 540
           SettingsRoute.name,
437 541
           initialChildren: children,
@@ -439,18 +543,18 @@ class SettingsRoute extends _i19.PageRouteInfo<void> {
439 543
 
440 544
   static const String name = 'SettingsRoute';
441 545
 
442
-  static _i19.PageInfo page = _i19.PageInfo(
546
+  static _i21.PageInfo page = _i21.PageInfo(
443 547
     name,
444 548
     builder: (data) {
445
-      return const _i11.SettingsPage();
549
+      return const _i13.SettingsPage();
446 550
     },
447 551
   );
448 552
 }
449 553
 
450 554
 /// generated route for
451
-/// [_i12.SplashPage]
452
-class SplashRoute extends _i19.PageRouteInfo<void> {
453
-  const SplashRoute({List<_i19.PageRouteInfo>? children})
555
+/// [_i14.SplashPage]
556
+class SplashRoute extends _i21.PageRouteInfo<void> {
557
+  const SplashRoute({List<_i21.PageRouteInfo>? children})
454 558
       : super(
455 559
           SplashRoute.name,
456 560
           initialChildren: children,
@@ -458,23 +562,23 @@ class SplashRoute extends _i19.PageRouteInfo<void> {
458 562
 
459 563
   static const String name = 'SplashRoute';
460 564
 
461
-  static _i19.PageInfo page = _i19.PageInfo(
565
+  static _i21.PageInfo page = _i21.PageInfo(
462 566
     name,
463 567
     builder: (data) {
464
-      return const _i12.SplashPage();
568
+      return const _i14.SplashPage();
465 569
     },
466 570
   );
467 571
 }
468 572
 
469 573
 /// generated route for
470
-/// [_i13.UploadPage]
471
-class UploadRoute extends _i19.PageRouteInfo<UploadRouteArgs> {
574
+/// [_i15.UploadPage]
575
+class UploadRoute extends _i21.PageRouteInfo<UploadRouteArgs> {
472 576
   UploadRoute({
473
-    _i21.Key? key,
474
-    required List<_i23.HistoryItemInfo> uploadList,
475
-    required _i24.ClinicInfo clinicInfo,
577
+    _i23.Key? key,
578
+    required List<_i25.HistoryItemInfo> uploadList,
579
+    required _i26.ClinicInfo clinicInfo,
476 580
     required bool isFromView,
477
-    List<_i19.PageRouteInfo>? children,
581
+    List<_i21.PageRouteInfo>? children,
478 582
   }) : super(
479 583
           UploadRoute.name,
480 584
           args: UploadRouteArgs(
@@ -488,11 +592,11 @@ class UploadRoute extends _i19.PageRouteInfo<UploadRouteArgs> {
488 592
 
489 593
   static const String name = 'UploadRoute';
490 594
 
491
-  static _i19.PageInfo page = _i19.PageInfo(
595
+  static _i21.PageInfo page = _i21.PageInfo(
492 596
     name,
493 597
     builder: (data) {
494 598
       final args = data.argsAs<UploadRouteArgs>();
495
-      return _i13.UploadPage(
599
+      return _i15.UploadPage(
496 600
         key: args.key,
497 601
         uploadList: args.uploadList,
498 602
         clinicInfo: args.clinicInfo,
@@ -510,11 +614,11 @@ class UploadRouteArgs {
510 614
     required this.isFromView,
511 615
   });
512 616
 
513
-  final _i21.Key? key;
617
+  final _i23.Key? key;
514 618
 
515
-  final List<_i23.HistoryItemInfo> uploadList;
619
+  final List<_i25.HistoryItemInfo> uploadList;
516 620
 
517
-  final _i24.ClinicInfo clinicInfo;
621
+  final _i26.ClinicInfo clinicInfo;
518 622
 
519 623
   final bool isFromView;
520 624
 
@@ -525,14 +629,14 @@ class UploadRouteArgs {
525 629
 }
526 630
 
527 631
 /// generated route for
528
-/// [_i14.UploadSelectClinicPage]
632
+/// [_i16.UploadSelectClinicPage]
529 633
 class UploadSelectClinicRoute
530
-    extends _i19.PageRouteInfo<UploadSelectClinicRouteArgs> {
634
+    extends _i21.PageRouteInfo<UploadSelectClinicRouteArgs> {
531 635
   UploadSelectClinicRoute({
532
-    _i21.Key? key,
533
-    required List<_i23.HistoryItemInfo> uploadList,
636
+    _i23.Key? key,
637
+    required List<_i25.HistoryItemInfo> uploadList,
534 638
     required bool isFromView,
535
-    List<_i19.PageRouteInfo>? children,
639
+    List<_i21.PageRouteInfo>? children,
536 640
   }) : super(
537 641
           UploadSelectClinicRoute.name,
538 642
           args: UploadSelectClinicRouteArgs(
@@ -545,11 +649,11 @@ class UploadSelectClinicRoute
545 649
 
546 650
   static const String name = 'UploadSelectClinicRoute';
547 651
 
548
-  static _i19.PageInfo page = _i19.PageInfo(
652
+  static _i21.PageInfo page = _i21.PageInfo(
549 653
     name,
550 654
     builder: (data) {
551 655
       final args = data.argsAs<UploadSelectClinicRouteArgs>();
552
-      return _i14.UploadSelectClinicPage(
656
+      return _i16.UploadSelectClinicPage(
553 657
         key: args.key,
554 658
         uploadList: args.uploadList,
555 659
         isFromView: args.isFromView,
@@ -565,9 +669,9 @@ class UploadSelectClinicRouteArgs {
565 669
     required this.isFromView,
566 670
   });
567 671
 
568
-  final _i21.Key? key;
672
+  final _i23.Key? key;
569 673
 
570
-  final List<_i23.HistoryItemInfo> uploadList;
674
+  final List<_i25.HistoryItemInfo> uploadList;
571 675
 
572 676
   final bool isFromView;
573 677
 
@@ -578,12 +682,12 @@ class UploadSelectClinicRouteArgs {
578 682
 }
579 683
 
580 684
 /// generated route for
581
-/// [_i15.VideoPlayerPage]
582
-class VideoPlayerRoute extends _i19.PageRouteInfo<VideoPlayerRouteArgs> {
685
+/// [_i17.VideoPlayerPage]
686
+class VideoPlayerRoute extends _i21.PageRouteInfo<VideoPlayerRouteArgs> {
583 687
   VideoPlayerRoute({
584
-    _i21.Key? key,
585
-    required _i23.HistoryItemInfo? info,
586
-    List<_i19.PageRouteInfo>? children,
688
+    _i23.Key? key,
689
+    required _i25.HistoryItemInfo? info,
690
+    List<_i21.PageRouteInfo>? children,
587 691
   }) : super(
588 692
           VideoPlayerRoute.name,
589 693
           args: VideoPlayerRouteArgs(
@@ -595,11 +699,11 @@ class VideoPlayerRoute extends _i19.PageRouteInfo<VideoPlayerRouteArgs> {
595 699
 
596 700
   static const String name = 'VideoPlayerRoute';
597 701
 
598
-  static _i19.PageInfo page = _i19.PageInfo(
702
+  static _i21.PageInfo page = _i21.PageInfo(
599 703
     name,
600 704
     builder: (data) {
601 705
       final args = data.argsAs<VideoPlayerRouteArgs>();
602
-      return _i15.VideoPlayerPage(
706
+      return _i17.VideoPlayerPage(
603 707
         key: args.key,
604 708
         info: args.info,
605 709
       );
@@ -613,9 +717,9 @@ class VideoPlayerRouteArgs {
613 717
     required this.info,
614 718
   });
615 719
 
616
-  final _i21.Key? key;
720
+  final _i23.Key? key;
617 721
 
618
-  final _i23.HistoryItemInfo? info;
722
+  final _i25.HistoryItemInfo? info;
619 723
 
620 724
   @override
621 725
   String toString() {
@@ -624,18 +728,18 @@ class VideoPlayerRouteArgs {
624 728
 }
625 729
 
626 730
 /// generated route for
627
-/// [_i16.VideoPreviewPage]
628
-class VideoPreviewRoute extends _i19.PageRouteInfo<VideoPreviewRouteArgs> {
731
+/// [_i18.VideoPreviewPage]
732
+class VideoPreviewRoute extends _i21.PageRouteInfo<VideoPreviewRouteArgs> {
629 733
   VideoPreviewRoute({
630
-    _i21.Key? key,
631
-    required _i22.LocalPatientInfo info,
734
+    _i23.Key? key,
735
+    required _i24.LocalPatientInfo info,
632 736
     required String path,
633 737
     required String area,
634 738
     required DateTime time,
635 739
     required String mobile,
636 740
     required String wifi,
637 741
     required String deviceModel,
638
-    List<_i19.PageRouteInfo>? children,
742
+    List<_i21.PageRouteInfo>? children,
639 743
   }) : super(
640 744
           VideoPreviewRoute.name,
641 745
           args: VideoPreviewRouteArgs(
@@ -653,11 +757,11 @@ class VideoPreviewRoute extends _i19.PageRouteInfo<VideoPreviewRouteArgs> {
653 757
 
654 758
   static const String name = 'VideoPreviewRoute';
655 759
 
656
-  static _i19.PageInfo page = _i19.PageInfo(
760
+  static _i21.PageInfo page = _i21.PageInfo(
657 761
     name,
658 762
     builder: (data) {
659 763
       final args = data.argsAs<VideoPreviewRouteArgs>();
660
-      return _i16.VideoPreviewPage(
764
+      return _i18.VideoPreviewPage(
661 765
         key: args.key,
662 766
         info: args.info,
663 767
         path: args.path,
@@ -683,9 +787,9 @@ class VideoPreviewRouteArgs {
683 787
     required this.deviceModel,
684 788
   });
685 789
 
686
-  final _i21.Key? key;
790
+  final _i23.Key? key;
687 791
 
688
-  final _i22.LocalPatientInfo info;
792
+  final _i24.LocalPatientInfo info;
689 793
 
690 794
   final String path;
691 795
 
@@ -706,9 +810,9 @@ class VideoPreviewRouteArgs {
706 810
 }
707 811
 
708 812
 /// generated route for
709
-/// [_i17.VideoViewPage]
710
-class VideoViewRoute extends _i19.PageRouteInfo<void> {
711
-  const VideoViewRoute({List<_i19.PageRouteInfo>? children})
813
+/// [_i19.VideoViewPage]
814
+class VideoViewRoute extends _i21.PageRouteInfo<void> {
815
+  const VideoViewRoute({List<_i21.PageRouteInfo>? children})
712 816
       : super(
713 817
           VideoViewRoute.name,
714 818
           initialChildren: children,
@@ -716,23 +820,23 @@ class VideoViewRoute extends _i19.PageRouteInfo<void> {
716 820
 
717 821
   static const String name = 'VideoViewRoute';
718 822
 
719
-  static _i19.PageInfo page = _i19.PageInfo(
823
+  static _i21.PageInfo page = _i21.PageInfo(
720 824
     name,
721 825
     builder: (data) {
722
-      return const _i17.VideoViewPage();
826
+      return const _i19.VideoViewPage();
723 827
     },
724 828
   );
725 829
 }
726 830
 
727 831
 /// generated route for
728
-/// [_i18.WebviewPage]
729
-class WebviewRoute extends _i19.PageRouteInfo<WebviewRouteArgs> {
832
+/// [_i20.WebviewPage]
833
+class WebviewRoute extends _i21.PageRouteInfo<WebviewRouteArgs> {
730 834
   WebviewRoute({
731
-    _i20.Key? key,
835
+    _i22.Key? key,
732 836
     required String url,
733 837
     String? title,
734
-    _i25.Future<_i26.HttpResponse<String>>? htmlFuture,
735
-    List<_i19.PageRouteInfo>? children,
838
+    _i27.Future<_i28.HttpResponse<String>>? htmlFuture,
839
+    List<_i21.PageRouteInfo>? children,
736 840
   }) : super(
737 841
           WebviewRoute.name,
738 842
           args: WebviewRouteArgs(
@@ -746,11 +850,11 @@ class WebviewRoute extends _i19.PageRouteInfo<WebviewRouteArgs> {
746 850
 
747 851
   static const String name = 'WebviewRoute';
748 852
 
749
-  static _i19.PageInfo page = _i19.PageInfo(
853
+  static _i21.PageInfo page = _i21.PageInfo(
750 854
     name,
751 855
     builder: (data) {
752 856
       final args = data.argsAs<WebviewRouteArgs>();
753
-      return _i18.WebviewPage(
857
+      return _i20.WebviewPage(
754 858
         key: args.key,
755 859
         url: args.url,
756 860
         title: args.title,
@@ -768,13 +872,13 @@ class WebviewRouteArgs {
768 872
     this.htmlFuture,
769 873
   });
770 874
 
771
-  final _i20.Key? key;
875
+  final _i22.Key? key;
772 876
 
773 877
   final String url;
774 878
 
775 879
   final String? title;
776 880
 
777
-  final _i25.Future<_i26.HttpResponse<String>>? htmlFuture;
881
+  final _i27.Future<_i28.HttpResponse<String>>? htmlFuture;
778 882
 
779 883
   @override
780 884
   String toString() {

+ 29 - 0
lib/funcs.dart

@@ -742,3 +742,32 @@ void exitApp() async {
742 742
   await SystemNavigator.pop();
743 743
   //exit(0);
744 744
 }
745
+
746
+///前往国康在线问诊
747
+void gotoGkOnlineConsultation(BuildContext context) async {
748
+  if (!await checkInternetWifi(true)) {
749
+    logd("前往国康在线问诊,没连接外网");
750
+    return;
751
+  }
752
+  if (!context.mounted) {
753
+    return;
754
+  }
755
+  if (!checkLogin(context)) {
756
+    logd("前往国康在线问诊,未登录");
757
+    return;
758
+  }
759
+  String baseUrl = kDebugMode
760
+      ? urlGkOnlineConsultationBaseUrlTest
761
+      : urlGkOnlineConsultationBaseUrl;
762
+  Map<String, dynamic> map = {
763
+    "uid": await SpUtil.getUserId(),
764
+    "accessTime": DateTime.now().yyyyMMddHHmmss
765
+  };
766
+  String rsa = rsaEncrypt(gkOnlineConsultationRsaPublicKey, jsonEncode(map));
767
+  String url = "$baseUrl?appId=$gkOnlineConsultationAppId&data=$rsa";
768
+  logd("前往国康在线问诊,data=$map,url=$url");
769
+  if (!context.mounted) {
770
+    return;
771
+  }
772
+  context.pushRoute(OnlineConsultationRoute(url: url, backAlert: true));
773
+}

+ 3 - 0
lib/generated/intl/messages_en.dart

@@ -77,6 +77,8 @@ class MessageLookup extends MessageLookupByLibrary {
77 77
             MessageLookupByLibrary.simpleMessage("Detect the version"),
78 78
         "clickToConnect": MessageLookupByLibrary.simpleMessage("Click Connect"),
79 79
         "close": MessageLookupByLibrary.simpleMessage("Close"),
80
+        "closeCurrentPageHint": MessageLookupByLibrary.simpleMessage(
81
+            "Do you want to close the current page?"),
80 82
         "confirm": MessageLookupByLibrary.simpleMessage("Confirm"),
81 83
         "connect": MessageLookupByLibrary.simpleMessage("Connect"),
82 84
         "connectError":
@@ -319,6 +321,7 @@ class MessageLookup extends MessageLookupByLibrary {
319 321
         "userAgreementBookTitle":
320 322
             MessageLookupByLibrary.simpleMessage("\"User Agreement\""),
321 323
         "video": MessageLookupByLibrary.simpleMessage("Video"),
324
+        "viewPicture": MessageLookupByLibrary.simpleMessage("View picture"),
322 325
         "waitingConnectDevice": MessageLookupByLibrary.simpleMessage(
323 326
             "Waiting for the device to connect"),
324 327
         "xxAge": m6,

+ 3 - 0
lib/generated/intl/messages_zh.dart

@@ -67,6 +67,8 @@ class MessageLookup extends MessageLookupByLibrary {
67 67
         "checkVersion": MessageLookupByLibrary.simpleMessage("检测版本"),
68 68
         "clickToConnect": MessageLookupByLibrary.simpleMessage("点击连接"),
69 69
         "close": MessageLookupByLibrary.simpleMessage("关闭"),
70
+        "closeCurrentPageHint":
71
+            MessageLookupByLibrary.simpleMessage("是否关闭当前页面?"),
70 72
         "confirm": MessageLookupByLibrary.simpleMessage("确定"),
71 73
         "connect": MessageLookupByLibrary.simpleMessage("连接"),
72 74
         "connectError": MessageLookupByLibrary.simpleMessage("连接错误"),
@@ -249,6 +251,7 @@ class MessageLookup extends MessageLookupByLibrary {
249 251
         "userAgreementBookTitle":
250 252
             MessageLookupByLibrary.simpleMessage("《用户协议》"),
251 253
         "video": MessageLookupByLibrary.simpleMessage("视频"),
254
+        "viewPicture": MessageLookupByLibrary.simpleMessage("查看图片"),
252 255
         "waitingConnectDevice":
253 256
             MessageLookupByLibrary.simpleMessage("正在等待设备连接"),
254 257
         "xxAge": m6,

+ 20 - 0
lib/generated/l10n.dart

@@ -1839,6 +1839,26 @@ class S {
1839 1839
       args: [],
1840 1840
     );
1841 1841
   }
1842
+
1843
+  /// `Do you want to close the current page?`
1844
+  String get closeCurrentPageHint {
1845
+    return Intl.message(
1846
+      'Do you want to close the current page?',
1847
+      name: 'closeCurrentPageHint',
1848
+      desc: '',
1849
+      args: [],
1850
+    );
1851
+  }
1852
+
1853
+  /// `View picture`
1854
+  String get viewPicture {
1855
+    return Intl.message(
1856
+      'View picture',
1857
+      name: 'viewPicture',
1858
+      desc: '',
1859
+      args: [],
1860
+    );
1861
+  }
1842 1862
 }
1843 1863
 
1844 1864
 class AppLocalizationDelegate extends LocalizationsDelegate<S> {

+ 15 - 4
lib/global.dart

@@ -67,13 +67,24 @@ final MethodChannel videoChannel = const MethodChannel(_videoChannelName);
67 67
 ///文件channel
68 68
 final MethodChannel fileChannel = const MethodChannel(_fileChannelName);
69 69
 
70
-///国康RSA加密公钥
71
-final String gkRsaPublicKey = """
70
+///国康RSA加密密钥长度
71
+final int gkRsaKeyBitLength = 512;
72
+
73
+///国康在线问诊RSA加密公钥
74
+final String gkOnlineConsultationRsaPublicKey = """
72 75
 -----BEGIN PUBLIC KEY-----
73 76
 MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALltnyc4QcGMQ7/ZT+xmV6x/OXdJ2k5ftatsES9XlScM
74 77
 fPgs/mANKCixDwNFOIAFvTnKUvGgxVhBXpFL8Ma/J0cCAwEAAQ==
75 78
 -----END PUBLIC KEY-----
76 79
     """;
77 80
 
78
-///国康RSA加密密钥长度
79
-final int gkRsaKeyBitLength = 512;
81
+///国康在线问诊appID
82
+final String gkOnlineConsultationAppId = "AqC4SNnS3dvYKBYn";
83
+
84
+///国康在线问诊baseUrl测试环境
85
+final String urlGkOnlineConsultationBaseUrlTest =
86
+    "https://app.hchina.com/test/gzkj/web/authentication/";
87
+
88
+///国康在线问诊baseUrl生产环境
89
+final String urlGkOnlineConsultationBaseUrl =
90
+    "https://app.hchina.com/gzkj/web/authentication/";

+ 3 - 1
lib/l10n/intl_en.arb

@@ -177,5 +177,7 @@
177 177
   "selectRecord": "Select Recording",
178 178
   "selectPhotoAndRecord": "Select Photo & Video Recording",
179 179
   "maxSelectCountXx": "You can choose up to {count}",
180
-  "pleaseSelectAtLastOne": "Please select at least one"
180
+  "pleaseSelectAtLastOne": "Please select at least one",
181
+  "closeCurrentPageHint": "Do you want to close the current page?",
182
+  "viewPicture": "View picture"
181 183
 }

+ 3 - 1
lib/l10n/intl_zh.arb

@@ -177,5 +177,7 @@
177 177
   "selectRecord": "选择录像",
178 178
   "selectPhotoAndRecord": "选择照片和录像",
179 179
   "maxSelectCountXx": "最多可以选择{count}项",
180
-  "pleaseSelectAtLastOne": "请至少选择一项"
180
+  "pleaseSelectAtLastOne": "请至少选择一项",
181
+  "closeCurrentPageHint": "是否关闭当前页面?",
182
+  "viewPicture": "查看图片"
181 183
 }

+ 218 - 0
lib/pages/consultation/online_consultation_page.dart

@@ -0,0 +1,218 @@
1
+import 'dart:convert';
2
+import 'dart:io';
3
+
4
+import 'package:auto_route/auto_route.dart';
5
+import 'package:eitc_erm_dental_flutter/app_router.gr.dart';
6
+import 'package:eitc_erm_dental_flutter/entity/history_item_info.dart';
7
+import 'package:eitc_erm_dental_flutter/funcs.dart';
8
+import 'package:flutter/foundation.dart';
9
+import 'package:flutter/material.dart';
10
+import 'package:flutter_inappwebview/flutter_inappwebview.dart';
11
+import 'package:flutter_screenutil/flutter_screenutil.dart';
12
+
13
+import '../../widget/webview_progress_bar.dart';
14
+import '../history/select_history_page.dart';
15
+
16
+///在线问诊页面
17
+@RoutePage(name: "onlineConsultationRoute")
18
+class OnlineConsultationPage extends StatefulWidget {
19
+  final String url;
20
+  final bool backAlert;
21
+
22
+  const OnlineConsultationPage(
23
+      {super.key, required this.url, this.backAlert = false});
24
+
25
+  @override
26
+  State<OnlineConsultationPage> createState() => _OnlineConsultationPageState();
27
+}
28
+
29
+class _OnlineConsultationPageState extends State<OnlineConsultationPage> {
30
+  final GlobalKey _webViewKey = GlobalKey();
31
+
32
+  InAppWebViewController? _webViewController;
33
+  final InAppWebViewSettings _settings = InAppWebViewSettings(
34
+      isInspectable: kDebugMode,
35
+      mediaPlaybackRequiresUserGesture: true,
36
+      allowsInlineMediaPlayback: true,
37
+      iframeAllowFullscreen: true,
38
+      javaScriptEnabled: true,
39
+      allowFileAccess: true,
40
+      allowFileAccessFromFileURLs: true);
41
+
42
+  final WebviewProgressBarController _progressBarController =
43
+      WebviewProgressBarController();
44
+
45
+  @override
46
+  void initState() {
47
+    super.initState();
48
+  }
49
+
50
+  @override
51
+  void dispose() {
52
+    super.dispose();
53
+    _progressBarController.dispose();
54
+  }
55
+
56
+  @override
57
+  Widget build(BuildContext context) {
58
+    return PopScope(
59
+        canPop: !widget.backAlert,
60
+        onPopInvokedWithResult: _onPop,
61
+        child: Scaffold(
62
+          body: SafeArea(
63
+              child: Stack(
64
+            children: [
65
+              InAppWebView(
66
+                key: _webViewKey,
67
+                initialSettings: _settings,
68
+                onWebViewCreated: (controller) {
69
+                  _webViewController = controller;
70
+                  _load();
71
+                  _initHandler();
72
+                },
73
+                onLoadStart: (controller, url) {
74
+                  logd("onLoadStart,url=$url");
75
+                },
76
+                onPermissionRequest: (controller, request) async {
77
+                  return PermissionResponse(
78
+                      resources: request.resources,
79
+                      action: PermissionResponseAction.GRANT);
80
+                },
81
+                onLoadStop: (controller, url) async {
82
+                  logd("onLoadStop,url=$url");
83
+                },
84
+                onReceivedError: (controller, request, error) {
85
+                  loge("onReceivedError", error: error);
86
+                },
87
+                onProgressChanged: (controller, progress) {
88
+                  logd("onProgressChanged,progress=$progress");
89
+                  _progressBarController.setProgress(progress);
90
+                },
91
+                onConsoleMessage: (controller, consoleMessage) {
92
+                  if (kDebugMode) {
93
+                    logd(consoleMessage);
94
+                  }
95
+                },
96
+              ),
97
+              Align(
98
+                alignment: Alignment.topLeft,
99
+                child: WebviewProgressBar(controller: _progressBarController),
100
+              )
101
+            ],
102
+          )),
103
+        ));
104
+  }
105
+
106
+  void _onPop(bool didPop, dynamic result) async {
107
+    if (didPop) {
108
+      return;
109
+    }
110
+    bool? bo = await showDialog(
111
+        context: context,
112
+        builder: (ctx) {
113
+          return AlertDialog(
114
+            title: Text(getS().hint),
115
+            content: Text(getS().closeCurrentPageHint),
116
+            actions: [
117
+              TextButton(
118
+                  onPressed: () => Navigator.pop(ctx, false),
119
+                  child: Text(getS().cancel)),
120
+              TextButton(
121
+                  onPressed: () => Navigator.pop(ctx, true),
122
+                  child: Text(getS().confirm)),
123
+            ],
124
+            shape: RoundedRectangleBorder(
125
+                borderRadius: BorderRadius.circular(15.r)),
126
+          );
127
+        });
128
+    if (bo ?? false) {
129
+      if (mounted) {
130
+        Navigator.pop(context);
131
+      }
132
+    }
133
+  }
134
+
135
+  ///加载
136
+  void _load() {
137
+    if (widget.url.isEmpty) {
138
+      return;
139
+    }
140
+    _webViewController?.loadUrl(
141
+        urlRequest: URLRequest(url: WebUri(widget.url)));
142
+  }
143
+
144
+  void _initHandler() {
145
+    _webViewController?.addJavaScriptHandler(
146
+        handlerName: "closePage", callback: _onClosePage);
147
+    _webViewController?.addJavaScriptHandler(
148
+        handlerName: "openUrl", callback: _onOpenUrl);
149
+    _webViewController?.addJavaScriptHandler(
150
+        handlerName: "selectPhoto", callback: _onSelectPhoto);
151
+    _webViewController?.addJavaScriptHandler(
152
+        handlerName: "viewPhoto", callback: _onViewPhoto);
153
+  }
154
+
155
+  ///关闭页面
156
+  void _onClosePage(List<dynamic> args) {
157
+    Navigator.pop(context);
158
+  }
159
+
160
+  ///打开连接
161
+  void _onOpenUrl(List<dynamic> args) {
162
+    if (args.isEmpty) {
163
+      return;
164
+    }
165
+    String url = args[0];
166
+    bool isBlank = false;
167
+    if (args.length > 1) {
168
+      isBlank = args[0] == 1;
169
+    }
170
+    logd("H5打开新URL,url=$url,isBlank=$isBlank");
171
+    if (isBlank) {
172
+      _webViewController?.loadUrl(urlRequest: URLRequest(url: WebUri(url)));
173
+    } else {
174
+      context.pushRoute(OnlineConsultationRoute(url: url, backAlert: true));
175
+    }
176
+  }
177
+
178
+  ///选择照片
179
+  Future<List<String>> _onSelectPhoto(List<dynamic> args) async {
180
+    int maxCount = 0;
181
+    if (args.isNotEmpty) {
182
+      maxCount = args[0];
183
+    }
184
+    logd("H5选择照片,最大数量=$maxCount");
185
+    List<HistoryItemInfo>? list =
186
+        await context.pushRoute<List<HistoryItemInfo>>(SelectHistoryRoute(
187
+            selectType: SelectHistoryType.photo,
188
+            isFillterPatient: false,
189
+            isMultiSelect: maxCount > 0,
190
+            maxCount: maxCount));
191
+    if (list == null) {
192
+      logd("没有选择照片");
193
+      return [];
194
+    }
195
+    //把图片转成base64编码,直接给文件路径H5没法使用
196
+    List<String> datas = [];
197
+    Stream<HistoryItemInfo> stream = Stream.fromIterable(list);
198
+    await for (HistoryItemInfo info in stream) {
199
+      try {
200
+        File file = File(info.fileUri!.toFilePath());
201
+        Uint8List data = await file.readAsBytes();
202
+        String base64 = base64Encode(data);
203
+        datas.add(base64);
204
+      } catch (e) {
205
+        loge("H5选择图片,转为base64异常", error: e);
206
+      }
207
+    }
208
+    return datas;
209
+  }
210
+
211
+  ///查看图片
212
+  void _onViewPhoto(List<dynamic> args) async {
213
+    if (args.isEmpty) {
214
+      return;
215
+    }
216
+    context.pushRoute(OnlinePictureViewRoute(url: args[0]));
217
+  }
218
+}

+ 41 - 0
lib/pages/view/online_picture_view_page.dart

@@ -0,0 +1,41 @@
1
+import 'package:auto_route/annotations.dart';
2
+import 'package:cached_network_image/cached_network_image.dart';
3
+import 'package:eitc_erm_dental_flutter/funcs.dart';
4
+import 'package:flutter/material.dart';
5
+import 'package:flutter_screenutil/flutter_screenutil.dart';
6
+import 'package:photo_view/photo_view.dart';
7
+
8
+///在线图片查看页面
9
+@RoutePage(name: "onlinePictureViewRoute")
10
+class OnlinePictureViewPage extends StatelessWidget {
11
+  final String url;
12
+
13
+  const OnlinePictureViewPage({super.key, required this.url});
14
+
15
+  @override
16
+  Widget build(BuildContext context) {
17
+    return Scaffold(
18
+      appBar: AppBar(
19
+        title: Text(getS().viewPicture),
20
+        centerTitle: true,
21
+      ),
22
+      body: SafeArea(
23
+          child: Container(
24
+        color: Colors.black,
25
+        child: PhotoView(
26
+          imageProvider: CachedNetworkImageProvider(url),
27
+          errorBuilder: (ctx, obj, stacktrack) {
28
+            logd("在线查看图片,图片加载异常", error: obj, stackTrace: stacktrack);
29
+            return Center(
30
+              child: Icon(
31
+                size: 100.r,
32
+                Icons.image_not_supported_outlined,
33
+                color: Colors.white,
34
+              ),
35
+            );
36
+          },
37
+        ),
38
+      )),
39
+    );
40
+  }
41
+}

+ 88 - 0
pubspec.lock

@@ -190,6 +190,30 @@ packages:
190 190
       url: "https://pub.flutter-io.cn"
191 191
     source: hosted
192 192
     version: "8.9.2"
193
+  cached_network_image:
194
+    dependency: "direct main"
195
+    description:
196
+      name: cached_network_image
197
+      sha256: "7c1183e361e5c8b0a0f21a28401eecdbde252441106a9816400dd4c2b2424916"
198
+      url: "https://pub.flutter-io.cn"
199
+    source: hosted
200
+    version: "3.4.1"
201
+  cached_network_image_platform_interface:
202
+    dependency: transitive
203
+    description:
204
+      name: cached_network_image_platform_interface
205
+      sha256: "35814b016e37fbdc91f7ae18c8caf49ba5c88501813f73ce8a07027a395e2829"
206
+      url: "https://pub.flutter-io.cn"
207
+    source: hosted
208
+    version: "4.1.1"
209
+  cached_network_image_web:
210
+    dependency: transitive
211
+    description:
212
+      name: cached_network_image_web
213
+      sha256: "980842f4e8e2535b8dbd3d5ca0b1f0ba66bf61d14cc3a17a9b4788a3685ba062"
214
+      url: "https://pub.flutter-io.cn"
215
+    source: hosted
216
+    version: "1.3.1"
193 217
   characters:
194 218
     dependency: transitive
195 219
     description:
@@ -395,6 +419,14 @@ packages:
395 419
     description: flutter
396 420
     source: sdk
397 421
     version: "0.0.0"
422
+  flutter_cache_manager:
423
+    dependency: transitive
424
+    description:
425
+      name: flutter_cache_manager
426
+      sha256: "400b6592f16a4409a7f2bb929a9a7e38c72cceb8ffb99ee57bbf2cb2cecf8386"
427
+      url: "https://pub.flutter-io.cn"
428
+    source: hosted
429
+    version: "3.4.1"
398 430
   flutter_inappwebview:
399 431
     dependency: "direct main"
400 432
     description:
@@ -786,6 +818,14 @@ packages:
786 818
       url: "https://pub.flutter-io.cn"
787 819
     source: hosted
788 820
     version: "0.5.0"
821
+  octo_image:
822
+    dependency: transitive
823
+    description:
824
+      name: octo_image
825
+      sha256: "34faa6639a78c7e3cbe79be6f9f96535867e879748ade7d17c9b1ae7536293bd"
826
+      url: "https://pub.flutter-io.cn"
827
+    source: hosted
828
+    version: "2.1.0"
789 829
   package_config:
790 830
     dependency: transitive
791 831
     description:
@@ -1175,6 +1215,46 @@ packages:
1175 1215
       url: "https://pub.flutter-io.cn"
1176 1216
     source: hosted
1177 1217
     version: "7.0.0"
1218
+  sqflite:
1219
+    dependency: transitive
1220
+    description:
1221
+      name: sqflite
1222
+      sha256: "79a297dc3cc137e758c6a4baf83342b039e5a6d2436fcdf3f96a00adaaf2ad62"
1223
+      url: "https://pub.flutter-io.cn"
1224
+    source: hosted
1225
+    version: "2.4.0"
1226
+  sqflite_android:
1227
+    dependency: transitive
1228
+    description:
1229
+      name: sqflite_android
1230
+      sha256: "78f489aab276260cdd26676d2169446c7ecd3484bbd5fead4ca14f3ed4dd9ee3"
1231
+      url: "https://pub.flutter-io.cn"
1232
+    source: hosted
1233
+    version: "2.4.0"
1234
+  sqflite_common:
1235
+    dependency: transitive
1236
+    description:
1237
+      name: sqflite_common
1238
+      sha256: "4468b24876d673418a7b7147e5a08a715b4998a7ae69227acafaab762e0e5490"
1239
+      url: "https://pub.flutter-io.cn"
1240
+    source: hosted
1241
+    version: "2.5.4+5"
1242
+  sqflite_darwin:
1243
+    dependency: transitive
1244
+    description:
1245
+      name: sqflite_darwin
1246
+      sha256: "769733dddf94622d5541c73e4ddc6aa7b252d865285914b6fcd54a63c4b4f027"
1247
+      url: "https://pub.flutter-io.cn"
1248
+    source: hosted
1249
+    version: "2.4.1-1"
1250
+  sqflite_platform_interface:
1251
+    dependency: transitive
1252
+    description:
1253
+      name: sqflite_platform_interface
1254
+      sha256: "8dd4515c7bdcae0a785b0062859336de775e8c65db81ae33dd5445f35be61920"
1255
+      url: "https://pub.flutter-io.cn"
1256
+    source: hosted
1257
+    version: "2.4.0"
1178 1258
   stack_trace:
1179 1259
     dependency: transitive
1180 1260
     description:
@@ -1215,6 +1295,14 @@ packages:
1215 1295
       url: "https://pub.flutter-io.cn"
1216 1296
     source: hosted
1217 1297
     version: "1.2.0"
1298
+  synchronized:
1299
+    dependency: transitive
1300
+    description:
1301
+      name: synchronized
1302
+      sha256: "69fe30f3a8b04a0be0c15ae6490fc859a78ef4c43ae2dd5e8a623d45bfcf9225"
1303
+      url: "https://pub.flutter-io.cn"
1304
+    source: hosted
1305
+    version: "3.3.0+3"
1218 1306
   term_glyph:
1219 1307
     dependency: transitive
1220 1308
     description:

+ 2 - 0
pubspec.yaml

@@ -97,6 +97,8 @@ dependencies:
97 97
   retrofit: ^4.4.1
98 98
   json_annotation: ^4.9.0
99 99
 
100
+  cached_network_image: ^3.4.1
101
+
100 102
   flutter_localizations:
101 103
     sdk: flutter
102 104