Browse Source

update test tools

arthur.wu 2 years ago
parent
commit
d166ca3bcf

+ 384 - 0
Tools/TestTools/client/lib/ApplyConsultationScreen.dart

@@ -0,0 +1,384 @@
+import 'package:flutter/material.dart';
+import 'package:get_it/get_it.dart';
+import 'package:ustest/Services/ConsultationService.dart';
+import 'package:ustest/Services/UserService.dart';
+import 'package:flutter_datetime_picker/flutter_datetime_picker.dart';
+import 'package:autocomplete_textfield/autocomplete_textfield.dart';
+
+class CustomPicker extends CommonPickerModel {
+  String digits(int value, int length) {
+    return '$value'.padLeft(length, "0");
+  }
+
+  CustomPicker({DateTime? currentTime, LocaleType? locale})
+      : super(locale: locale) {
+    this.currentTime = currentTime ?? DateTime.now();
+    this.setLeftIndex(this.currentTime.hour);
+    this.setMiddleIndex(this.currentTime.minute);
+    this.setRightIndex(this.currentTime.second);
+  }
+
+  @override
+  String? leftStringAtIndex(int index) {
+    if (index >= 0 && index < 24) {
+      return this.digits(index, 2);
+    } else {
+      return null;
+    }
+  }
+
+  @override
+  String? middleStringAtIndex(int index) {
+    if (index >= 0 && index < 60) {
+      return this.digits(index, 2);
+    } else {
+      return null;
+    }
+  }
+
+  @override
+  String? rightStringAtIndex(int index) {
+    if (index >= 0 && index < 60) {
+      return this.digits(index, 2);
+    } else {
+      return null;
+    }
+  }
+
+  @override
+  String leftDivider() {
+    return "|";
+  }
+
+  @override
+  String rightDivider() {
+    return "|";
+  }
+
+  @override
+  List<int> layoutProportions() {
+    return [1, 2, 1];
+  }
+
+  @override
+  DateTime finalTime() {
+    return currentTime.isUtc
+        ? DateTime.utc(
+            currentTime.year,
+            currentTime.month,
+            currentTime.day,
+            this.currentLeftIndex(),
+            this.currentMiddleIndex(),
+            this.currentRightIndex())
+        : DateTime(
+            currentTime.year,
+            currentTime.month,
+            currentTime.day,
+            this.currentLeftIndex(),
+            this.currentMiddleIndex(),
+            this.currentRightIndex());
+  }
+}
+
+class ApplyConsultationScreen extends StatelessWidget {
+  const ApplyConsultationScreen();
+
+  @override
+  Widget build(BuildContext context) {
+    return Scaffold(
+      backgroundColor: Colors.grey[200],
+      body: const Center(
+        child: SizedBox(
+          width: 400,
+          child: Card(
+            child: ApplyConsultationForm(),
+          ),
+        ),
+      ),
+    );
+  }
+}
+
+class ApplyConsultationForm extends StatefulWidget {
+  const ApplyConsultationForm();
+  @override
+  _ApplyConsultationFormState createState() => _ApplyConsultationFormState();
+}
+
+class _ApplyConsultationFormState extends State<ApplyConsultationForm> {
+  final expertCodeController = TextEditingController();
+  final deviceCodeController = TextEditingController();
+  final scanPositionController = TextEditingController();
+  final timeController = TextEditingController(text: DateTime.now().toString());
+  final patientCodeController = TextEditingController();
+
+  GlobalKey<AutoCompleteTextFieldState<String>> exportKey = GlobalKey();
+  double _formProgress = 0;
+
+  @override
+  Widget build(BuildContext context) {
+    return Form(
+      child: Column(
+        mainAxisSize: MainAxisSize.min,
+        children: [
+          LinearProgressIndicator(value: _formProgress),
+          Text('Apply', style: Theme.of(context).textTheme.headline4),
+          Padding(
+            padding: const EdgeInsets.all(8.0),
+            child: FutureBuilder<List<String>>(
+                future: fetchExperts(),
+                builder: (context, snapshot) {
+                  if (snapshot.hasError) {
+                    return const Center(
+                      child: Text('An error has occurred!'),
+                    );
+                  } else if (snapshot.hasData) {
+                    return SimpleAutoCompleteTextField(
+                      key: exportKey,
+                      suggestions: snapshot.data!,
+                      controller: expertCodeController,
+                      decoration: const InputDecoration(hintText: 'export'),
+                    );
+                  } else {
+                    return const Center(
+                      child: CircularProgressIndicator(),
+                    );
+                  }
+                }),
+          ),
+          Padding(
+            padding: const EdgeInsets.all(8.0),
+            child: TextFormField(
+              controller: deviceCodeController,
+              decoration: const InputDecoration(hintText: 'device'),
+            ),
+          ),
+          Padding(
+            padding: const EdgeInsets.all(8.0),
+            child: TextFormField(
+              controller: scanPositionController,
+              decoration: const InputDecoration(hintText: 'scan position'),
+            ),
+          ),
+          Padding(
+            padding: const EdgeInsets.all(8.0),
+            child: Row(
+              children: [
+                Expanded(
+                    child: TextFormField(
+                  controller: timeController,
+                  decoration: const InputDecoration(hintText: 'time'),
+                )),
+                TextButton(
+                    onPressed: () {
+                      DatePicker.showDatePicker(context,
+                          showTitleActions: true,
+                          minTime: DateTime(2022, 3, 5),
+                          maxTime: DateTime(2024, 6, 7),
+                          theme: DatePickerTheme(
+                              headerColor: Colors.orange,
+                              backgroundColor: Colors.blue,
+                              itemStyle: TextStyle(
+                                  color: Colors.white,
+                                  fontWeight: FontWeight.bold,
+                                  fontSize: 18),
+                              doneStyle:
+                                  TextStyle(color: Colors.white, fontSize: 16)),
+                          onChanged: (date) {
+                        print('change $date in time zone ' +
+                            date.timeZoneOffset.inHours.toString());
+                      }, onConfirm: (date) {
+                        print('confirm $date');
+                      }, currentTime: DateTime.now(), locale: LocaleType.en);
+                    },
+                    child: Text(
+                      'date',
+                      style: TextStyle(color: Colors.blue),
+                    )),
+                TextButton(
+                    onPressed: () {
+                      DatePicker.showTimePicker(context, showTitleActions: true,
+                          onChanged: (date) {
+                        print('change $date in time zone ' +
+                            date.timeZoneOffset.inHours.toString());
+                      }, onConfirm: (date) {
+                        print('confirm $date');
+                      }, currentTime: DateTime.now());
+                    },
+                    child: Text(
+                      'time',
+                      style: TextStyle(color: Colors.blue),
+                    )),
+              ],
+            ),
+          ),
+          Padding(
+              padding: const EdgeInsets.all(8.0),
+              child: Row(
+                mainAxisAlignment: MainAxisAlignment.center,
+                children: [
+                  TextButton(
+                    style: ButtonStyle(
+                      foregroundColor: MaterialStateProperty.resolveWith(
+                          (Set<MaterialState> states) {
+                        return states.contains(MaterialState.disabled)
+                            ? null
+                            : Colors.white;
+                      }),
+                      backgroundColor: MaterialStateProperty.resolveWith(
+                          (Set<MaterialState> states) {
+                        return states.contains(MaterialState.disabled)
+                            ? null
+                            : Colors.blue;
+                      }),
+                    ),
+                    onPressed: _showWelcomeScreen,
+                    child: const Text('Submit'),
+                  ),
+                  Padding(
+                    padding: const EdgeInsets.all(8.0),
+                    child: TextButton(
+                      style: ButtonStyle(
+                        foregroundColor: MaterialStateProperty.resolveWith(
+                            (Set<MaterialState> states) {
+                          return states.contains(MaterialState.disabled)
+                              ? null
+                              : Colors.white;
+                        }),
+                        backgroundColor: MaterialStateProperty.resolveWith(
+                            (Set<MaterialState> states) {
+                          return states.contains(MaterialState.disabled)
+                              ? null
+                              : Colors.blue;
+                        }),
+                      ),
+                      onPressed: () => {Navigator.of(context).pop()},
+                      child: const Text('Cancel'),
+                    ),
+                  ),
+                ],
+              )),
+        ],
+      ),
+    );
+  }
+
+  void _showWelcomeScreen() async {
+    try {
+      ApplyConsultationRequest _model = new ApplyConsultationRequest(
+          "expertusercode", "d", "s", DateTime.now(), List.empty(), "", "");
+      var service = GetIt.instance.get<UserService>();
+      var userName = expertCodeController.text;
+      var password = deviceCodeController.text;
+      var host = scanPositionController.text;
+      var result = await service.signInAsync(host, userName, password);
+      if (result != null) {
+        Navigator.of(context).pushNamed('/');
+      }
+    } catch (e) {
+      print('signInAsync ex: $e');
+    }
+  }
+
+  fetchExperts() {}
+}
+
+class ExportInfo {
+  final String id;
+  final String name;
+
+  ExportInfo({required this.id, required this.name});
+
+  factory ExportInfo.fromJson(Map<String, dynamic> json) {
+    var item = ExportInfo(
+      id: json['id'] as String,
+      name: json['name'] as String,
+    );
+
+    return item;
+  }
+
+  Map<String, dynamic> toMap() {
+    return {
+      'id': id,
+      'name': name,
+    };
+  }
+
+  @override
+  String toString() {
+    return 'ExportInfo{id: $id}, {name: $name}';
+  }
+}
+
+enum NotificationTypeEnum {
+  Daiding,
+
+  /// <summary>
+  /// ChatMsgNotification|1| 聊天通知
+  /// </summary>
+  ChatMsgNotification,
+
+  /// <summary>
+  /// UpgradeVersionNotification|2| 版本更新通知
+  /// </summary>
+  UpgradeVersionNotification,
+
+  /// <summary>
+  /// LogoffNotification|3| 登出通知
+  /// </summary>
+  LogoffNotification,
+
+  /// <summary>
+  /// DisconnectNotification| 4|与服务器断开连接通知
+  /// </summary>
+  DisconnectNotification,
+
+  /// <summary>
+  /// ConnectionNotification| 5|	与服务器已连接通知
+  /// </summary>
+  ConnectionNotification,
+
+  /// <summary>
+  ///FinishNotifyRecordsMessage| 6 | 检查记录完成消息类型
+  /// </summary>
+  FinishNotifyRecordsMessage,
+
+  /// <summary>
+  ///InvitedEnterRoomNotification| 7 | 邀请用户加入房间通知
+  /// </summary>
+  InvitedEnterRoomNotification,
+
+  /// <summary>
+  ///CancelInvitedEnterRoomNotification| 8 |取消邀请用户通知
+  /// </summary>
+  CancelInvitedEnterRoomNotification,
+}
+
+class ConnectionNotification {
+  NotificationTypeEnum notificationType;
+  ConnectionNotification({
+    this.notificationType = NotificationTypeEnum.Daiding,
+  });
+  factory ConnectionNotification.fromJson(Map<String, dynamic> map) {
+    return ConnectionNotification(
+      notificationType: NotificationTypeEnum.values
+          .firstWhere((e) => e.index == map['NotificationType']),
+    );
+  }
+}
+
+class DisconnectNotification {
+  NotificationTypeEnum notificationType;
+  DisconnectNotification({
+    this.notificationType = NotificationTypeEnum.Daiding,
+  });
+  factory DisconnectNotification.fromJson(Map<String, dynamic> map) {
+    return DisconnectNotification(
+      notificationType: NotificationTypeEnum.values
+          .firstWhere((e) => e.index == map['NotificationType']),
+    );
+  }
+}
+
+class FinishNotifyRecordsMessage {}

+ 134 - 0
Tools/TestTools/client/lib/ConsultationList.dart

@@ -0,0 +1,134 @@
+import 'dart:convert';
+
+import 'package:flutter/material.dart';
+import 'package:flutter/widgets.dart';
+import 'package:get_it/get_it.dart';
+import 'package:sprintf/sprintf.dart';
+import 'package:http/http.dart' as http;
+
+class ConsultationList extends StatefulWidget {
+  ConsultationList({Key? key, required this.token, required this.patients})
+      : super();
+  final String token;
+  final List<Consultation> patients;
+
+  @override
+  _ConsultationListState createState() => _ConsultationListState();
+}
+
+class _ConsultationListState extends State<ConsultationList> {
+  @override
+  Widget build(BuildContext context) {
+    return Scaffold(
+        body: Container(
+      height: 600,
+      child: Row(
+        children: [
+          Container(
+            height: 500,
+            width: 400,
+            child: ListView(
+              restorationId: 'list_demo_list_view',
+              padding: const EdgeInsets.symmetric(vertical: 0),
+              children: [
+                for (int index = 0; index < widget.patients.length; index++)
+                  Row(
+                    children: [
+                      Expanded(
+                          child: Container(
+                        child: ListTile(
+                          leading: ExcludeSemantics(
+                            child: Icon(Icons.person),
+                          ),
+                          title: Text(widget.patients[index].id),
+                          subtitle: Text("patients[index].subtitle"),
+                          onTap: (() =>
+                              onTabPatient(widget.patients[index].id)),
+                        ),
+                      )),
+                      Container(
+                          alignment: Alignment.topRight,
+                          child: Container(
+                            child: Column(
+                              children: [
+                                ClipRRect(
+                                    borderRadius: BorderRadius.circular(2),
+                                    child: Container(
+                                        color: Colors.amber[50],
+                                        child: Row(children: [
+                                          Icon(
+                                            Icons.star,
+                                            color: Colors.amber[500],
+                                            size: 12,
+                                          ),
+                                          Text(
+                                            "5.0",
+                                            style: TextStyle(
+                                                color: Colors.amber[900],
+                                                fontSize: 9),
+                                          ),
+                                        ]))),
+                                Container(child: Text("a"))
+                              ],
+                            ),
+                          )),
+                    ],
+                  ),
+              ],
+            ),
+          ),
+        ],
+      ),
+    ));
+  }
+
+  void onTabPatient(String id) async {
+    try {
+      var client = http.Client();
+
+      var body = sprintf(
+          '{"jsonrpc": "2.0", "method": "GetRecordInfoPagesAsync", "params": [{"Token": "%s",  "PageIndex": 1, "PageSize": 10, "PatientCode": "%s"}], "id": 1 }',
+          [widget.token, id]);
+      print('GetRecordInfoPagesAsync http.Client()' + body);
+      final response = await client.post(
+          Uri.parse('http://192.168.6.80:8303/IRecordInfoService'),
+          body: body);
+      print('GetRecordInfoPagesAsync response.body' + response.body);
+      final parsed = jsonDecode(response.body);
+      var datas = parsed['result']['PageData'];
+
+      setState(() {});
+      //client.close();
+
+    } catch (ex) {
+      print('GetRecordInfoPagesAsync.to ex' + ex.toString());
+    }
+  }
+}
+
+class Consultation {
+  final String id;
+
+  Consultation({
+    required this.id,
+  });
+
+  factory Consultation.fromJson(Map<String, dynamic> json) {
+    var item = Consultation(
+      id: json['PatientCode'] as String,
+    );
+
+    return item;
+  }
+
+  Map<String, dynamic> toMap() {
+    return {
+      'PatientCode': id,
+    };
+  }
+
+  @override
+  String toString() {
+    return 'Patient{id: $id}';
+  }
+}

+ 0 - 261
Tools/TestTools/client/lib/PatientList.dart

@@ -1,261 +0,0 @@
-import 'dart:convert';
-
-import 'package:flutter/material.dart';
-import 'package:flutter/widgets.dart';
-import 'package:get_it/get_it.dart';
-import 'package:sprintf/sprintf.dart';
-import 'package:http/http.dart' as http;
-
-class PatientList extends StatefulWidget {
-  PatientList({Key? key, required this.token, required this.patients})
-      : super(key: key);
-  final String token;
-  final List<Patient> patients;
-  late List<ExamRecord> examRecords = [];
-  late List<ImageData> datas = [];
-  @override
-  _PatientListState createState() => _PatientListState();
-}
-
-class _PatientListState extends State<PatientList> {
-  @override
-  Widget build(BuildContext context) {
-    return Scaffold(
-        body: Container(
-      height: 600,
-      child: Row(
-        children: [
-          Container(
-            height: 500,
-            width: 400,
-            child: ListView(
-              restorationId: 'list_demo_list_view',
-              padding: const EdgeInsets.symmetric(vertical: 0),
-              children: [
-                for (int index = 0; index < widget.patients.length; index++)
-                  Row(
-                    children: [
-                      Expanded(
-                          child: Container(
-                        child: ListTile(
-                          leading: ExcludeSemantics(
-                            child: Icon(Icons.person),
-                          ),
-                          title: Text(widget.patients[index].id),
-                          subtitle: Text("patients[index].subtitle"),
-                          onTap: (() =>
-                              onTabPatient(widget.patients[index].id)),
-                        ),
-                      )),
-                      Container(
-                          alignment: Alignment.topRight,
-                          child: Container(
-                            child: Column(
-                              children: [
-                                ClipRRect(
-                                    borderRadius: BorderRadius.circular(2),
-                                    child: Container(
-                                        color: Colors.amber[50],
-                                        child: Row(children: [
-                                          Icon(
-                                            Icons.star,
-                                            color: Colors.amber[500],
-                                            size: 12,
-                                          ),
-                                          Text(
-                                            "5.0",
-                                            style: TextStyle(
-                                                color: Colors.amber[900],
-                                                fontSize: 9),
-                                          ),
-                                        ]))),
-                                Container(child: Text("a"))
-                              ],
-                            ),
-                          )),
-                    ],
-                  ),
-              ],
-            ),
-          ),
-          Wrap(
-            children: [
-              for (int index = 0; index < widget.examRecords.length; index++)
-                Row(
-                  children: [
-                    TextButton(
-                        onPressed: (() =>
-                            onTabExamRecord(widget.examRecords[index].id)),
-                        child: Text(widget.examRecords[index].id))
-                  ],
-                )
-            ],
-          ),
-          Wrap(
-            children: [
-              for (int index = 0; index < widget.datas.length; index++)
-                Container(
-                    child: Image.network(widget.datas[index].url),
-                    padding: EdgeInsets.all(16),
-                    margin: EdgeInsets.all(8),
-                    decoration: BoxDecoration(
-                        color: Colors.black,
-                        border: Border(
-                            top: BorderSide(
-                                color: Colors.amber,
-                                width: 3,
-                                style: BorderStyle.solid))))
-            ],
-          ),
-        ],
-      ),
-    ));
-  }
-
-  void onTabPatient(String id) async {
-    try {
-      var client = http.Client();
-
-      var body = sprintf(
-          '{"jsonrpc": "2.0", "method": "GetRecordInfoPagesAsync", "params": [{"Token": "%s",  "PageIndex": 1, "PageSize": 10, "PatientCode": "%s"}], "id": 1 }',
-          [widget.token, id]);
-      print('GetRecordInfoPagesAsync http.Client()' + body);
-      final response = await client.post(
-          Uri.parse('http://192.168.6.80:8303/IRecordInfoService'),
-          body: body);
-      print('GetRecordInfoPagesAsync response.body' + response.body);
-      final parsed = jsonDecode(response.body);
-      var datas = parsed['result']['PageData'];
-      var list =
-          datas.map<ExamRecord>((json) => ExamRecord.fromJson(json)).toList();
-
-      setState(() {
-        widget.examRecords = list;
-      });
-      //client.close();
-
-    } catch (ex) {
-      print('GetRecordInfoPagesAsync.to ex' + ex.toString());
-    }
-  }
-
-  void onTabExamRecord(String id) async {
-    try {
-      var client = http.Client();
-
-      var body = sprintf(
-          '{"jsonrpc": "2.0", "method": "GetRemedicalListByRecordInfoAsync", "params": [{"Token": "%s",  "RecordCode": "%s" }], "id": 1 }',
-          [widget.token, id]);
-      print('GetRemedicalListByRecordInfoAsync http.Client()' + body);
-      final response = await client.post(
-          Uri.parse('http://192.168.6.175:80/IRemedicalService'),
-          body: body);
-      print('GetRemedicalListByRecordInfoAsync response.body' + response.body);
-      final parsed = jsonDecode(response.body);
-      var datas = parsed['result']['RemedicalItemList'][0]['RemedicalList'];
-      print("data list len is" + datas.toString());
-      var list = datas
-          .map<ImageData>((json) => ImageData.fromJson(json))
-          .toList() as List<ImageData>;
-
-      for (var i = 0; i < list.length; i++) {
-        print("data list len is" + list[i].url);
-      }
-
-      setState(() {
-        widget.datas = list;
-      });
-      //client.close();
-
-    } catch (ex) {
-      print('GetRemedicalListByRecordInfoAsync.to ex' + ex.toString());
-    }
-  }
-}
-
-class Patient {
-  final String id;
-
-  Patient({
-    required this.id,
-  });
-
-  factory Patient.fromJson(Map<String, dynamic> json) {
-    var item = Patient(
-      id: json['PatientCode'] as String,
-    );
-
-    return item;
-  }
-
-  Map<String, dynamic> toMap() {
-    return {
-      'PatientCode': id,
-    };
-  }
-
-  @override
-  String toString() {
-    return 'Patient{id: $id}';
-  }
-}
-
-class ExamRecord {
-  final String id;
-  final String deviceName;
-
-  ExamRecord({
-    required this.id,
-    required this.deviceName,
-  });
-
-  factory ExamRecord.fromJson(Map<String, dynamic> json) {
-    var item = ExamRecord(
-      id: json['RecordCode'] as String,
-      deviceName: json['DeviceName'] as String,
-    );
-    return item;
-  }
-
-  Map<String, dynamic> toMap() {
-    return {
-      'RecordCode': id,
-      'DeviceName': deviceName,
-    };
-  }
-
-  @override
-  String toString() {
-    return 'ExamRecord{id: $id, url:$deviceName}';
-  }
-}
-
-class ImageData {
-  final String id;
-  final String url;
-
-  ImageData({
-    required this.id,
-    required this.url,
-  });
-
-  factory ImageData.fromJson(Map<String, dynamic> json) {
-    var item = ImageData(
-      id: json['RemedicalCode'] as String,
-      url: json['TerminalImages']['PreviewUrl'] as String,
-    );
-    return item;
-  }
-
-  Map<String, dynamic> toMap() {
-    return {
-      'RemedicalCode': id,
-      'PreviewUrl': url,
-    };
-  }
-
-  @override
-  String toString() {
-    return 'ImageData{id: $id, url:$url}';
-  }
-}

+ 46 - 10
Tools/TestTools/client/lib/Services/UserService.dart

@@ -34,23 +34,53 @@ class UserService {
     this.storage.deleteItem(UserStroageKey);
   }
 
-  Future<User> signInAsync(
+  Future<bool> signInAsync(
       String host, String userName, String password) async {
     _host = host;
     var client = http.Client();
     var body = sprintf(
         '{"jsonrpc": "2.0", "method": "CommonLoginAsync", "params": [{"AnyAccount": "%s", "AnyCode": "", "Password": "%s" }], "id": 1 }',
         [userName, password]);
-    final response =
+    var response =
         await client.post(Uri.parse(_host + '/ILoginService'), body: body);
     print('response.body' + response.body);
-    final parsed = jsonDecode(response.body);
-    var user =
-        new User(userName: userName, accessToken: parsed['result']['Token']);
-    var jsonUser = user.toJson();
-    print('jsonUser:' + jsonUser.toString());
-    this.storage.setItem(UserStroageKey, jsonUser);
-    return user;
+    var parsed = jsonDecode(response.body);
+    var token = parsed['result']['Token'];
+    if (token != null) {
+      body = sprintf(
+          '{"jsonrpc": "2.0", "method": "GetUserInfoAsync", "params": [{"Token": "%s" }], "id": 1 }',
+          [token]);
+      response =
+          await client.post(Uri.parse(_host + '/IUserService'), body: body);
+      print('GetUserInfoAsync response.body' + response.body);
+      var parsed = jsonDecode(response.body);
+      if (parsed != null) {
+        var organizationCode = parsed['result']['OrganizationCode'];
+        var user = new User(
+            userName: userName,
+            accessToken: token,
+            organizationCode: organizationCode);
+        var jsonUser = user.toJson();
+
+        this.storage.setItem(UserStroageKey, jsonUser);
+        print('jsonUser:' + jsonUser.toString());
+
+        return true;
+      }
+    }
+
+    return false;
+  }
+
+  dynamic post(
+      http.Client client, String interface, String method, String args) async {
+    final body = sprintf(
+        '{"jsonrpc": "2.0", "method": "GetUserInfoAsync", "params": %s, "id": 1 }',
+        args);
+    final response =
+        await client.post(Uri.parse(_host + '/$interface'), body: body);
+    print('GetUserInfoAsync response.body' + response.body);
+    var parsed = jsonDecode(response.body);
   }
 }
 
@@ -59,17 +89,23 @@ class JsonRpcResult {}
 class User {
   final String userName;
   final String accessToken;
+  final String organizationCode;
 
-  User({required this.userName, required this.accessToken});
+  User(
+      {required this.userName,
+      required this.accessToken,
+      required this.organizationCode});
   factory User.fromJson(Map<String, dynamic> json) {
     return User(
       userName: json['userName'] as String,
       accessToken: json['accessToken'] as String,
+      organizationCode: json['organizationCode'] as String,
     );
   }
 
   Map<String, dynamic> toJson() => {
         "userName": userName,
         "accessToken": accessToken,
+        "organizationCode": organizationCode,
       };
 }

+ 11 - 15
Tools/TestTools/client/lib/SignInScreen.dart

@@ -119,27 +119,23 @@ class _SignInFormState extends State<SignInForm> {
                   ),
                 ],
               )),
-          TextButton(
-            child: const Text("Sign up"),
-            onPressed: _showSignUpScreen,
-          )
         ],
       ),
     );
   }
 
-  void _showSignUpScreen() {
-    Navigator.of(context).pushNamed('/signup');
-  }
-
   void _showWelcomeScreen() async {
-    var service = GetIt.instance.get<UserService>();
-    var userName = _userNameTextController.text;
-    var password = _userPasswordTextController.text;
-    var host = _serverUrlTextController.text;
-    var result = await service.signInAsync(host, userName, password);
-    if (result != null) {
-      Navigator.of(context).pushNamed('/');
+    try {
+      var service = GetIt.instance.get<UserService>();
+      var userName = _userNameTextController.text;
+      var password = _userPasswordTextController.text;
+      var host = _serverUrlTextController.text;
+      var result = await service.signInAsync(host, userName, password);
+      if (result != null) {
+        Navigator.of(context).pushNamed('/');
+      }
+    } catch (e) {
+      print('signInAsync ex: $e');
     }
   }
 }

+ 0 - 91
Tools/TestTools/client/lib/SignUpScreen.dart

@@ -1,91 +0,0 @@
-import 'package:flutter/material.dart';
-
-class SignUpScreen extends StatelessWidget {
-  const SignUpScreen();
-
-  @override
-  Widget build(BuildContext context) {
-    return Scaffold(
-      backgroundColor: Colors.grey[200],
-      body: const Center(
-        child: SizedBox(
-          width: 400,
-          child: Card(
-            child: SignUpForm(),
-          ),
-        ),
-      ),
-    );
-  }
-}
-
-class SignUpForm extends StatefulWidget {
-  const SignUpForm();
-
-  @override
-  _SignUpFormState createState() => _SignUpFormState();
-}
-
-class _SignUpFormState extends State<SignUpForm> {
-  final _firstNameTextController = TextEditingController();
-  final _lastNameTextController = TextEditingController();
-  final _usernameTextController = TextEditingController();
-
-  double _formProgress = 0;
-
-  @override
-  Widget build(BuildContext context) {
-    return Form(
-      child: Column(
-        mainAxisSize: MainAxisSize.min,
-        children: [
-          LinearProgressIndicator(value: _formProgress),
-          Text('Sign up', style: Theme.of(context).textTheme.headline4),
-          Padding(
-            padding: const EdgeInsets.all(8.0),
-            child: TextFormField(
-              controller: _firstNameTextController,
-              decoration: const InputDecoration(hintText: 'Device ID'),
-            ),
-          ),
-          Padding(
-            padding: const EdgeInsets.all(8.0),
-            child: TextFormField(
-              controller: _lastNameTextController,
-              decoration: const InputDecoration(hintText: 'Model Number'),
-            ),
-          ),
-          Padding(
-            padding: const EdgeInsets.all(8.0),
-            child: TextFormField(
-              controller: _usernameTextController,
-              decoration: const InputDecoration(hintText: 'Cpu'),
-            ),
-          ),
-          TextButton(
-            style: ButtonStyle(
-              foregroundColor: MaterialStateProperty.resolveWith(
-                  (Set<MaterialState> states) {
-                return states.contains(MaterialState.disabled)
-                    ? null
-                    : Colors.white;
-              }),
-              backgroundColor: MaterialStateProperty.resolveWith(
-                  (Set<MaterialState> states) {
-                return states.contains(MaterialState.disabled)
-                    ? null
-                    : Colors.blue;
-              }),
-            ),
-            onPressed: _showWelcomeScreen,
-            child: const Text('Sign up'),
-          ),
-        ],
-      ),
-    );
-  }
-
-  void _showWelcomeScreen() {
-    Navigator.of(context).pushNamed('/welcome');
-  }
-}

+ 1 - 0
Tools/TestTools/client/lib/TestCaseView.dart

@@ -66,6 +66,7 @@ class TestCaseView extends StatelessWidget {
 
   List<TestCase> fetchTestCases() {
     try {
+      return <TestCase>[];
       var testCases = <TestCase>[];
       testCases.add(new TestCase(
           id: "1",

+ 30 - 14
Tools/TestTools/client/lib/UserView.dart

@@ -5,7 +5,7 @@ import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
 import 'package:get_it/get_it.dart';
 import 'package:sprintf/sprintf.dart';
-import 'package:ustest/PatientList.dart';
+import 'package:ustest/ConsultationList.dart';
 import 'package:ustest/Services/UserService.dart';
 import 'package:http/http.dart' as http;
 
@@ -15,9 +15,11 @@ class UserView extends StatelessWidget {
   @override
   Widget build(BuildContext context) {
     var service = GetIt.instance.get<UserService>();
-    print("service:${service}");
     var user = service.getCurrentUser();
-    //var user = null;
+    if (user == null) {
+      print("user is null");
+      _showSignInScreen(context);
+    }
     var userName = user == null ? "" : user.userName;
     var accessToken = user == null ? "" : user.accessToken;
     return Scaffold(
@@ -32,22 +34,26 @@ class UserView extends StatelessWidget {
                       ? TextButton(
                           child: const Text("Sign in"),
                           onPressed: () => _showSignInScreen(context))
-                      : Text(
-                          sprintf('Name:%s, Token:%s', [userName, accessToken]))
+                      : Text(sprintf(
+                          'Name:%s, Token:%s', [userName, accessToken])),
+                  TextButton.icon(
+                      onPressed: () => onLogout(context),
+                      icon: Icon(Icons.logout),
+                      label: Text("注銷"))
                 ],
               ),
             ),
             Row(
               children: [
                 TextButton.icon(
-                    onPressed: onQueryExamPressed,
+                    onPressed: () => onApplyConsultation(context),
                     icon: Icon(Icons.add),
-                    label: Text("注銷")),
+                    label: Text("Apply")),
               ],
             ),
             Expanded(
                 child: Center(
-              child: FutureBuilder<List<Patient>>(
+              child: FutureBuilder<List<Consultation>>(
                 future: fetchPatients(),
                 builder: (context, snapshot) {
                   if (snapshot.hasError) {
@@ -55,7 +61,7 @@ class UserView extends StatelessWidget {
                       child: Text('An error has occurred!'),
                     );
                   } else if (snapshot.hasData) {
-                    return PatientList(
+                    return ConsultationList(
                         token: accessToken, patients: snapshot.data!);
                   } else {
                     return const Center(
@@ -118,11 +124,13 @@ class UserView extends StatelessWidget {
   }
 
   void _showSignInScreen(BuildContext context) {
-    Navigator.of(context).pushNamed('/signin');
+    Future.delayed(Duration.zero, () {
+      Navigator.of(context).pushNamed('/signin');
+    });
   }
 
-  Future<List<Patient>> fetchPatients() async {
-    var list = <Patient>[];
+  Future<List<Consultation>> fetchPatients() async {
+    var list = <Consultation>[];
     try {
       var service = GetIt.instance.get<UserService>();
       var user = service.getCurrentUser() as User;
@@ -139,7 +147,9 @@ class UserView extends StatelessWidget {
       final parsed = jsonDecode(response.body);
       var datas = parsed['result']['PageData'];
 
-      var list = datas.map<Patient>((json) => Patient.fromJson(json)).toList();
+      var list = datas
+          .map<Consultation>((json) => Consultation.fromJson(json))
+          .toList();
       return list;
     } catch (ex) {
       print('QueryExam.to ex' + ex.toString());
@@ -147,9 +157,15 @@ class UserView extends StatelessWidget {
     }
   }
 
-  void onQueryExamPressed() {
+  void onLogout(context) {
     var service = GetIt.instance.get<UserService>();
     service.logout();
+    Navigator.of(context).pushNamed('/signin');
+  }
+
+  void onApplyConsultation(context) {
+    print("onApplyConsultation click");
+    Navigator.of(context).pushNamed('/applyconsultation');
   }
 }
 

+ 2 - 2
Tools/TestTools/client/lib/main.dart

@@ -1,9 +1,9 @@
 import 'package:flutter/material.dart';
+import 'package:ustest/ApplyConsultationScreen.dart';
 import 'package:ustest/Services/LocalStorageService.dart';
 import 'package:ustest/Services/UserService.dart';
 import 'package:ustest/Services/ApiTestService.dart';
 import 'package:ustest/SignInScreen.dart';
-import 'package:ustest/SignUpScreen.dart';
 import 'package:ustest/MainScreen.dart';
 import 'package:get_it/get_it.dart';
 import 'package:colorize_logger/colorize_logger.dart';
@@ -33,7 +33,7 @@ class MyApp extends StatelessWidget {
       routes: {
         '/': (context) => MainScreen(),
         '/signin': (context) => const SignInScreen(),
-        '/signup': (context) => const SignUpScreen(),
+        '/applyconsultation': (context) => const ApplyConsultationScreen(),
       },
     );
   }

+ 82 - 75
Tools/TestTools/client/pubspec.lock

@@ -5,84 +5,91 @@ packages:
     dependency: transitive
     description:
       name: ansicolor
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "2.0.1"
   async:
     dependency: transitive
     description:
       name: async
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "2.9.0"
+  autocomplete_textfield:
+    dependency: "direct main"
+    description:
+      name: autocomplete_textfield
+      url: "https://pub.flutter-io.cn"
+    source: hosted
+    version: "2.0.1"
   boolean_selector:
     dependency: transitive
     description:
       name: boolean_selector
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "2.1.0"
   characters:
     dependency: transitive
     description:
       name: characters
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "1.2.1"
   clock:
     dependency: transitive
     description:
       name: clock
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "1.1.1"
   collection:
     dependency: transitive
     description:
       name: collection
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "1.16.0"
   colorize_logger:
     dependency: "direct main"
     description:
       name: colorize_logger
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "1.1.0"
   crypto:
     dependency: transitive
     description:
       name: crypto
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "3.0.2"
+    version: "3.0.1"
   cupertino_icons:
     dependency: "direct main"
     description:
       name: cupertino_icons
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "1.0.5"
   fake_async:
     dependency: transitive
     description:
       name: fake_async
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "1.3.1"
   ffi:
     dependency: transitive
     description:
       name: ffi
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "2.0.1"
+    version: "1.2.1"
   file:
     dependency: transitive
     description:
       name: file
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "6.1.4"
   flutter:
@@ -90,6 +97,13 @@ packages:
     description: flutter
     source: sdk
     version: "0.0.0"
+  flutter_datetime_picker:
+    dependency: "direct main"
+    description:
+      name: flutter_datetime_picker
+      url: "https://pub.flutter-io.cn"
+    source: hosted
+    version: "1.5.1"
   flutter_test:
     dependency: "direct dev"
     description: flutter
@@ -104,147 +118,140 @@ packages:
     dependency: "direct main"
     description:
       name: fluttertoast
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "8.0.9"
+    version: "8.1.1"
   get_it:
     dependency: "direct main"
     description:
       name: get_it
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "7.2.0"
+    version: "7.1.3"
   http:
     dependency: "direct main"
     description:
       name: http
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "0.13.5"
+    version: "0.13.3"
   http_parser:
     dependency: transitive
     description:
       name: http_parser
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "4.0.1"
+    version: "4.0.2"
   js:
     dependency: transitive
     description:
       name: js
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "0.6.4"
   localstorage:
     dependency: "direct main"
     description:
       name: localstorage
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "4.0.0+1"
   matcher:
     dependency: transitive
     description:
       name: matcher
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "0.12.12"
   material_color_utilities:
     dependency: transitive
     description:
       name: material_color_utilities
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "0.1.5"
   meta:
     dependency: transitive
     description:
       name: meta
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "1.8.0"
   path:
     dependency: transitive
     description:
       name: path
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "1.8.2"
   path_provider:
     dependency: transitive
     description:
       name: path_provider
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "2.0.11"
-  path_provider_android:
-    dependency: transitive
-    description:
-      name: path_provider_android
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "2.0.20"
-  path_provider_ios:
-    dependency: transitive
-    description:
-      name: path_provider_ios
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "2.0.11"
+    version: "2.0.4"
   path_provider_linux:
     dependency: transitive
     description:
       name: path_provider_linux
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "2.1.7"
+    version: "2.1.6"
   path_provider_macos:
     dependency: transitive
     description:
       name: path_provider_macos
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "2.0.6"
   path_provider_platform_interface:
     dependency: transitive
     description:
       name: path_provider_platform_interface
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "2.0.5"
+    version: "2.0.4"
   path_provider_windows:
     dependency: transitive
     description:
       name: path_provider_windows
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "2.1.3"
+    version: "2.0.6"
+  pedantic:
+    dependency: transitive
+    description:
+      name: pedantic
+      url: "https://pub.flutter-io.cn"
+    source: hosted
+    version: "1.11.1"
   platform:
     dependency: transitive
     description:
       name: platform
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "3.1.0"
   plugin_platform_interface:
     dependency: transitive
     description:
       name: plugin_platform_interface
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "2.1.3"
   process:
     dependency: transitive
     description:
       name: process
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "4.2.4"
+    version: "4.2.3"
   sentry:
     dependency: transitive
     description:
       name: sentry
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "5.1.0"
   sky_engine:
@@ -256,100 +263,100 @@ packages:
     dependency: transitive
     description:
       name: source_span
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "1.9.0"
   sprintf:
     dependency: "direct main"
     description:
       name: sprintf
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "6.0.2"
   stack_trace:
     dependency: transitive
     description:
       name: stack_trace
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "1.10.0"
   stream_channel:
     dependency: transitive
     description:
       name: stream_channel
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "2.1.0"
   string_scanner:
     dependency: transitive
     description:
       name: string_scanner
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "1.1.1"
   synchronized:
     dependency: transitive
     description:
       name: synchronized
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "3.0.0+3"
+    version: "3.0.0"
   term_glyph:
     dependency: transitive
     description:
       name: term_glyph
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "1.2.1"
   test_api:
     dependency: transitive
     description:
       name: test_api
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "0.4.12"
   typed_data:
     dependency: transitive
     description:
       name: typed_data
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "1.3.1"
+    version: "1.3.0"
   uuid:
     dependency: transitive
     description:
       name: uuid
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "3.0.6"
   vector_math:
     dependency: transitive
     description:
       name: vector_math
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "2.1.2"
   web_socket_channel:
     dependency: "direct main"
     description:
       name: web_socket_channel
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "2.2.0"
   win32:
     dependency: transitive
     description:
       name: win32
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "3.0.0"
+    version: "2.0.5"
   xdg_directories:
     dependency: transitive
     description:
       name: xdg_directories
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "0.2.0+2"
 sdks:
-  dart: ">=2.17.0 <3.0.0"
-  flutter: ">=3.0.0"
+  dart: ">=2.17.0-0 <3.0.0"
+  flutter: ">=2.0.0"

+ 2 - 0
Tools/TestTools/client/pubspec.yaml

@@ -34,6 +34,8 @@ dependencies:
   colorize_logger: ^1.1.0
   web_socket_channel: ^2.2.0
   fluttertoast: ^8.0.9
+  flutter_datetime_picker: ^1.5.1
+  autocomplete_textfield: ^2.0.1
   
 
 dev_dependencies:

+ 88 - 95
Tools/TestTools/ustest/pubspec.lock

@@ -5,84 +5,91 @@ packages:
     dependency: transitive
     description:
       name: ansicolor
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "2.0.1"
   async:
     dependency: transitive
     description:
       name: async
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "2.9.0"
+    version: "2.5.0"
   boolean_selector:
     dependency: transitive
     description:
       name: boolean_selector
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "2.1.0"
   characters:
     dependency: transitive
     description:
       name: characters
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "1.2.1"
+    version: "1.1.0"
+  charcode:
+    dependency: transitive
+    description:
+      name: charcode
+      url: "https://pub.flutter-io.cn"
+    source: hosted
+    version: "1.2.0"
   clock:
     dependency: transitive
     description:
       name: clock
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "1.1.1"
+    version: "1.1.0"
   collection:
     dependency: transitive
     description:
       name: collection
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "1.16.0"
+    version: "1.15.0"
   colorize_logger:
     dependency: "direct main"
     description:
       name: colorize_logger
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "1.1.0"
   crypto:
     dependency: transitive
     description:
       name: crypto
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "3.0.2"
+    version: "3.0.1"
   cupertino_icons:
     dependency: "direct main"
     description:
       name: cupertino_icons
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "1.0.5"
   fake_async:
     dependency: transitive
     description:
       name: fake_async
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "1.3.1"
+    version: "1.2.0"
   ffi:
     dependency: transitive
     description:
       name: ffi
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "2.0.1"
+    version: "1.2.1"
   file:
     dependency: transitive
     description:
       name: file
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "6.1.4"
   flutter:
@@ -104,147 +111,133 @@ packages:
     dependency: "direct main"
     description:
       name: fluttertoast
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "8.0.9"
+    version: "8.1.1"
   get_it:
     dependency: "direct main"
     description:
       name: get_it
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "7.2.0"
+    version: "7.1.3"
   http:
     dependency: "direct main"
     description:
       name: http
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "0.13.5"
+    version: "0.13.3"
   http_parser:
     dependency: transitive
     description:
       name: http_parser
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "4.0.1"
+    version: "4.0.2"
   js:
     dependency: transitive
     description:
       name: js
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "0.6.4"
+    version: "0.6.3"
   localstorage:
     dependency: "direct main"
     description:
       name: localstorage
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "4.0.0+1"
   matcher:
     dependency: transitive
     description:
       name: matcher
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "0.12.12"
-  material_color_utilities:
-    dependency: transitive
-    description:
-      name: material_color_utilities
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "0.1.5"
+    version: "0.12.10"
   meta:
     dependency: transitive
     description:
       name: meta
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "1.8.0"
+    version: "1.3.0"
   path:
     dependency: transitive
     description:
       name: path
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "1.8.2"
+    version: "1.8.0"
   path_provider:
     dependency: transitive
     description:
       name: path_provider
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "2.0.11"
-  path_provider_android:
-    dependency: transitive
-    description:
-      name: path_provider_android
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "2.0.20"
-  path_provider_ios:
-    dependency: transitive
-    description:
-      name: path_provider_ios
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "2.0.11"
+    version: "2.0.4"
   path_provider_linux:
     dependency: transitive
     description:
       name: path_provider_linux
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "2.1.7"
+    version: "2.1.6"
   path_provider_macos:
     dependency: transitive
     description:
       name: path_provider_macos
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "2.0.6"
   path_provider_platform_interface:
     dependency: transitive
     description:
       name: path_provider_platform_interface
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "2.0.5"
+    version: "2.0.4"
   path_provider_windows:
     dependency: transitive
     description:
       name: path_provider_windows
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "2.1.3"
+    version: "2.0.6"
+  pedantic:
+    dependency: transitive
+    description:
+      name: pedantic
+      url: "https://pub.flutter-io.cn"
+    source: hosted
+    version: "1.11.1"
   platform:
     dependency: transitive
     description:
       name: platform
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "3.1.0"
   plugin_platform_interface:
     dependency: transitive
     description:
       name: plugin_platform_interface
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "2.1.3"
   process:
     dependency: transitive
     description:
       name: process
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "4.2.4"
+    version: "4.2.3"
   sentry:
     dependency: transitive
     description:
       name: sentry
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "5.1.0"
   sky_engine:
@@ -256,100 +249,100 @@ packages:
     dependency: transitive
     description:
       name: source_span
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "1.9.0"
+    version: "1.8.0"
   sprintf:
     dependency: "direct main"
     description:
       name: sprintf
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "6.0.2"
   stack_trace:
     dependency: transitive
     description:
       name: stack_trace
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "1.10.0"
   stream_channel:
     dependency: transitive
     description:
       name: stream_channel
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "2.1.0"
   string_scanner:
     dependency: transitive
     description:
       name: string_scanner
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "1.1.1"
+    version: "1.1.0"
   synchronized:
     dependency: transitive
     description:
       name: synchronized
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "3.0.0+3"
+    version: "3.0.0"
   term_glyph:
     dependency: transitive
     description:
       name: term_glyph
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "1.2.1"
+    version: "1.2.0"
   test_api:
     dependency: transitive
     description:
       name: test_api
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "0.4.12"
+    version: "0.2.19"
   typed_data:
     dependency: transitive
     description:
       name: typed_data
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "1.3.1"
+    version: "1.3.0"
   uuid:
     dependency: transitive
     description:
       name: uuid
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "3.0.6"
   vector_math:
     dependency: transitive
     description:
       name: vector_math
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "2.1.2"
+    version: "2.1.0"
   web_socket_channel:
     dependency: "direct main"
     description:
       name: web_socket_channel
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "2.2.0"
   win32:
     dependency: transitive
     description:
       name: win32
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "3.0.0"
+    version: "2.0.5"
   xdg_directories:
     dependency: transitive
     description:
       name: xdg_directories
-      url: "https://pub.dartlang.org"
+      url: "https://pub.flutter-io.cn"
     source: hosted
     version: "0.2.0+2"
 sdks:
-  dart: ">=2.17.0 <3.0.0"
-  flutter: ">=3.0.0"
+  dart: ">=2.12.0 <3.0.0"
+  flutter: ">=2.0.0"