Эх сурвалжийг харах

1、诊疗展示、设备连接方式变更

guanxinyi 1 жил өмнө
parent
commit
bc71b3410d

+ 12 - 0
lib/managers/index.dart

@@ -1,5 +1,15 @@
+/*
+ * @Descripttion: 
+ * @version: 
+ * @Author: guanxiaoxin
+ * @Date: 2023-10-18 17:29:35
+ * @LastEditors: guanxiaoxin
+ * @LastEditTime: 2023-10-21 15:46:21
+ * @FilePath: \VNoteApp\lib\managers\index.dart
+ */
 import 'package:get/get.dart';
 import 'package:vnoteapp/managers/account.dart';
+import 'package:vnoteapp/managers/cachedRecord.dart';
 import 'package:vnoteapp/managers/contract.dart';
 import 'package:vnoteapp/managers/contract_template.dart';
 import 'package:vnoteapp/managers/diagnosis.dart';
@@ -8,6 +18,7 @@ import 'package:vnoteapp/managers/exam.dart';
 import 'package:vnoteapp/managers/follow_up.dart';
 import 'package:vnoteapp/managers/health_check_record.dart';
 import 'package:vnoteapp/managers/interfaces/account.dart';
+import 'package:vnoteapp/managers/interfaces/cachedRecord.dart';
 import 'package:vnoteapp/managers/interfaces/contract.dart';
 import 'package:vnoteapp/managers/interfaces/diagnosis.dart';
 import 'package:vnoteapp/managers/interfaces/doctor.dart';
@@ -41,6 +52,7 @@ abstract class ManagerCenter {
     Get.put<ITemplateManager>(TemplateManager());
     Get.put<IHealthCehckRecordManager>(HealthCheckRecordManager());
     Get.put<IPermissionManager>(PermissionManager());
+    Get.put<ICachedRecordManager>(CachedRecordManager());
     Get.put<IDiagnosisManager>(DiagnosisManager());
   }
 

+ 2 - 1
lib/pages/check/widgets/configurable_card.dart

@@ -4,7 +4,7 @@
  * @Author: guanxiaoxin
  * @Date: 2023-10-16 20:14:45
  * @LastEditors: guanxiaoxin
- * @LastEditTime: 2023-10-20 15:47:23
+ * @LastEditTime: 2023-10-21 15:06:15
  * @FilePath: \VNoteApp\lib\pages\check\widgets\configurable_card.dart
  */
 import 'dart:convert';
@@ -82,6 +82,7 @@ class _ConfigurableFormState extends State<ConfigurableCard> {
     super.dispose();
   }
 
+  /// TODO BAKA 替换manager
   Future<void> fetchTemplateIndex() async {
     try {
       /// 获取模板的键值对

+ 10 - 18
lib/pages/check/widgets/exam_configurable/exam_card.dart

@@ -1,12 +1,3 @@
-/*
- * @Descripttion: 
- * @version: 
- * @Author: guanxiaoxin
- * @Date: 2023-09-28 09:37:17
- * @LastEditors: guanxiaoxin
- * @LastEditTime: 2023-10-20 10:56:23
- * @FilePath: \VNoteApp\lib\pages\check\widgets\exam_configurable\exam_card.dart
- */
 import 'package:flutter/material.dart';
 import 'package:vnoteapp/consts/styles.dart';
 
@@ -40,14 +31,7 @@ class ExamCard extends StatelessWidget {
             crossAxisAlignment: CrossAxisAlignment.start,
             mainAxisAlignment: MainAxisAlignment.center,
             children: [
-              Container(
-                padding: const EdgeInsets.only(
-                  top: 20,
-                  left: 30,
-                  bottom: 15,
-                ),
-                child: _buildTitle(),
-              ),
+              _buildTitle(),
               content,
               const SizedBox(
                 height: 30,
@@ -67,6 +51,14 @@ class ExamCard extends StatelessWidget {
         style: const TextStyle(fontSize: 25),
       );
     }
-    return titleText ?? titleContent;
+    return titleText ??
+        Container(
+          padding: const EdgeInsets.only(
+            top: 20,
+            left: 30,
+            bottom: 15,
+          ),
+          child: titleContent,
+        );
   }
 }

+ 37 - 12
lib/pages/check/widgets/exam_device_connect_status/connect_disconnected.dart

@@ -4,35 +4,60 @@ import 'package:vnoteapp/components/button.dart';
 class DeviceConnectDisconnected extends StatelessWidget {
   const DeviceConnectDisconnected({
     super.key,
-    required this.connect,
+    this.connect,
   });
-  final Function connect;
+  final Function? connect;
 
   @override
   Widget build(BuildContext context) {
     return Positioned(
       right: 16,
       top: 16,
-      child: Row(
+      child: _buildContent(),
+    );
+  }
+
+  Widget _buildTitle(String title) {
+    return FittedBox(
+      child: Text(
+        title,
+        style: const TextStyle(color: Colors.red, fontSize: 24),
+      ),
+    );
+  }
+
+  Widget _buildContent() {
+    if (connect == null) {
+      return Row(
         children: [
-          const Text(
-            '设备连接中断,请重连',
-            style: TextStyle(color: Colors.red, fontSize: 24),
-          ),
+          _buildTitle('设备断开连接,重连中'),
           const SizedBox(
-            width: 32,
+            width: 16,
+          )
+        ],
+      );
+    } else {
+      return Row(
+        children: [
+          _buildTitle('设备连接失败'),
+          const SizedBox(
+            width: 16,
           ),
           SizedBox(
             width: 150,
             child: VButton(
-              child: Container(child: const Text('重连')),
+              child: Container(
+                  child: const Text(
+                '重连',
+                style: TextStyle(fontSize: 20),
+              )),
               onTap: () {
-                connect.call();
+                connect!.call();
               },
             ),
           )
         ],
-      ),
-    );
+      );
+    }
   }
 }

+ 31 - 12
lib/pages/check/widgets/exam_device_connect_status/connect_fail.dart

@@ -4,23 +4,42 @@ import 'package:vnoteapp/components/button.dart';
 class DeviceConnectFail extends StatelessWidget {
   const DeviceConnectFail({
     super.key,
-    required this.connect,
+    this.connect,
   });
-  final Function connect;
+  final Function? connect;
 
   @override
   Widget build(BuildContext context) {
     return Positioned(
       right: 16,
       top: 16,
-      child: Row(
+      child: _buildContent(),
+    );
+  }
+
+  Widget _buildTitle(String title) {
+    return FittedBox(
+      child: Text(
+        title,
+        style: const TextStyle(color: Colors.red, fontSize: 24),
+      ),
+    );
+  }
+
+  Widget _buildContent() {
+    if (connect == null) {
+      return Row(
         children: [
-          const FittedBox(
-            child: Text(
-              '设备连接失败',
-              style: TextStyle(color: Colors.red, fontSize: 24),
-            ),
-          ),
+          _buildTitle('设备连接失败,重连中'),
+          const SizedBox(
+            width: 16,
+          )
+        ],
+      );
+    } else {
+      return Row(
+        children: [
+          _buildTitle('设备连接失败'),
           const SizedBox(
             width: 16,
           ),
@@ -33,12 +52,12 @@ class DeviceConnectFail extends StatelessWidget {
                 style: TextStyle(fontSize: 20),
               )),
               onTap: () {
-                connect.call();
+                connect!.call();
               },
             ),
           )
         ],
-      ),
-    );
+      );
+    }
   }
 }

+ 100 - 15
lib/pages/medical/controller.dart

@@ -2,38 +2,123 @@ import 'dart:convert';
 
 import 'package:fis_jsonrpc/rpc.dart';
 import 'package:get/get.dart';
+import 'package:vnote_device_plugin/devices/temp.dart';
 import 'package:vnoteapp/architecture/defines.dart';
+import 'package:vnoteapp/architecture/utils/prompt_box.dart';
+import 'package:vnoteapp/managers/interfaces/cachedRecord.dart';
 import 'package:vnoteapp/managers/interfaces/diagnosis.dart';
-import 'package:vnoteapp/pages/medical/models/menu.dart';
+import 'package:vnoteapp/managers/interfaces/permission.dart';
+import 'package:vnoteapp/pages/medical/devices/controllers/sugar.dart';
+import 'package:vnoteapp/pages/medical/devices/controllers/temp.dart';
 import 'package:vnoteapp/pages/medical/state.dart';
 
 class MedicalController extends FControllerBase {
   final state = MedicalState();
   final _diagnosisManager = Get.find<IDiagnosisManager>();
+  final _cachedRecordManager = Get.find<ICachedRecordManager>();
+  var permissionManager = Get.find<IPermissionManager>();
+  final TempDeviceWorker tempDeviceWorker = TempDeviceWorker(
+    mac: 'D0:05:00:00:00:67',
+    model: 'YHW-6',
+  );
+
   String patientCode = '';
-  List<MedicalMenu> medicalMenuList = [
-    MedicalMenu(key: 'Temp', title: '体温'),
-    MedicalMenu(key: 'GLU', title: '血糖'),
-    MedicalMenu(key: 'NIBP', title: '血压'),
-    MedicalMenu(key: 'SpO2', title: '血氧'),
-    MedicalMenu(key: 'BMI', title: 'BMI'),
-  ];
+  String appDataId = '1008611';
+  // List<MedicalItem> medicalMenuList = [
+  //   MedicalItem(key: 'Temp', diagnosticItem: '体温'),
+  //   MedicalItem(key: 'GLU', diagnosticItem: '血糖'),
+  //   MedicalItem(key: 'NIBP', diagnosticItem: '血压'),
+  //   MedicalItem(key: 'SpO2', diagnosticItem: '血氧'),
+  //   MedicalItem(key: 'BMI', diagnosticItem: 'BMI'),
+  // ];
+  Map<String, dynamic> diagnosisDataValue = {};
 
   @override
   Future<void> onLoad() {
     final p = Get.parameters;
     patientCode = p["patientCode"]!;
+    getPermission();
+    initDeviceController();
     return super.onLoad();
   }
 
+  void initDeviceController() {
+    for (var i = 0; i < state.medicalMenuList.length; i++) {
+      var element = state.medicalMenuList[i];
+      switch (element.key) {
+        case 'Temp':
+          Get.put(
+            TempController(
+              medicalItem: element,
+              deviceChange: (value) {
+                state.medicalMenuList[i] = value;
+              },
+            ),
+          );
+        case 'GLU':
+          Get.put(
+            SugarController(
+              medicalItem: element,
+              deviceChange: (value) {
+                state.medicalMenuList[i] = value;
+              },
+            ),
+          );
+      }
+    }
+  }
+
+  Future<void> getPermission() async {
+    await permissionManager.requestLocationPermission();
+    await permissionManager.requestBluetoothConnectPermission();
+    await permissionManager.requestBluetoothAdvertisePermission();
+    await permissionManager.requestBluetoothScanPermission();
+  }
+
+  Future<void> readCachedRecord() async {
+    String? value = await _cachedRecordManager.readCachedRecord(
+      state.currentTab,
+      patientCode,
+      'ZLZS',
+      jsonEncode(
+        diagnosisDataValue[state.currentTab],
+      ),
+    );
+    diagnosisDataValue[state.currentTab] = jsonDecode(value ?? '');
+  }
+
+  Future<void> saveCachedRecord() async {
+    await _cachedRecordManager.saveCachedRecord(
+      state.currentTab,
+      patientCode,
+      'ZLZS',
+      jsonEncode(
+        diagnosisDataValue[state.currentTab],
+      ),
+    );
+    print(diagnosisDataValue['BMI']);
+  }
+
   Future<void> createDiagnosis() async {
     CreateDiagnosisRequest diagnosisRequest = CreateDiagnosisRequest(
-        patientCode: patientCode,
-        appDataId: '1',
-        diagnosisTime: DateTime.now(),
-        diagnosisData: jsonEncode({'Weight': '72'}),
-        key: 'Weight');
-    final a = await _diagnosisManager.createDiagnosisAsync(diagnosisRequest);
-    print(a);
+      patientCode: patientCode,
+      appDataId: appDataId,
+      diagnosisTime: DateTime.now(),
+      diagnosisData: jsonEncode(diagnosisDataValue[state.currentTab]),
+      key: state.currentTab,
+    );
+    saveCachedRecord();
+    final result =
+        await _diagnosisManager.createDiagnosisAsync(diagnosisRequest);
+    if (result.isNotEmpty) {
+      PromptBox.toast('保存成功');
+      final index = state.medicalMenuList
+          .indexWhere((element) => element.key == state.currentTab);
+      if (index < 4) {
+        state.currentTab = state.medicalMenuList[index + 1].key;
+      } else {
+        Get.back();
+      }
+    }
   }
 }

+ 80 - 0
lib/pages/medical/devices/controllers/sugar.dart

@@ -0,0 +1,80 @@
+/*
+ * @Descripttion: 
+ * @version: 
+ * @Author: guanxiaoxin
+ * @Date: 2023-10-23 13:38:34
+ * @LastEditors: guanxiaoxin
+ * @LastEditTime: 2023-10-23 17:47:15
+ * @FilePath: \VNoteApp\lib\pages\medical\devices\controllers\sugar.dart
+ */
+import 'dart:convert';
+
+import 'package:flutter/material.dart';
+import 'package:get/get.dart';
+import 'package:vnote_device_plugin/devices/sugar.dart';
+import 'package:vnote_device_plugin/models/exams/sugar.dart';
+import 'package:vnoteapp/pages/medical/devices/interfaces/device_controller.dart';
+import 'package:vnoteapp/pages/medical/models/item.dart';
+import 'package:vnoteapp/pages/medical/models/worker.dart';
+
+class SugarController extends GetxController implements IDeviceController {
+  SugarController({
+    required this.medicalItem,
+    required this.deviceChange,
+  });
+  final SugarDeviceWorker worker = SugarDeviceWorker(
+    mac: '60:98:66:C4:0E:51',
+    model: 'i-sens630',
+  );
+  MedicalItem medicalItem;
+  ValueChanged deviceChange;
+
+  /// 连接设备
+  @override
+  Future<void> connectDevice() async {
+    await worker.connect();
+  }
+
+  @override
+  void workerAddListener() async {
+    worker.successEvent.addListener(_onSuccess);
+    worker.connectErrorEvent.addListener(_onConnectFail);
+    worker.connectedEvent.addListener(_onConnectSuccess);
+    worker.disconnectedEvent.addListener(_onDisconnected);
+  }
+
+  @override
+  void onInit() {
+    connectDevice();
+    workerAddListener();
+    super.onInit();
+  }
+
+  @override
+  void dispose() {
+    disConnectDevice();
+    super.dispose();
+  }
+
+  void _onSuccess(_, SugarExamData e) {
+    print(e);
+    medicalItem.diagnosisWorkerStatus = WorkerStatus.connected;
+    medicalItem.diagnosisData = jsonEncode({'sugar': e.sugar.toString()});
+    deviceChange.call(medicalItem);
+  }
+
+  void _onConnectFail(sender, e) {}
+
+  void _onConnectSuccess(sender, e) {}
+
+  void _onDisconnected(sender, e) {}
+
+  @override
+  Future<void> disConnectDevice() async {
+    worker.connectErrorEvent.removeListener(_onConnectFail);
+    worker.connectedEvent.removeListener(_onConnectSuccess);
+    worker.successEvent.removeListener(_onSuccess);
+    worker.disconnectedEvent.removeListener(_onDisconnected);
+    await worker.disconnect();
+  }
+}

+ 86 - 0
lib/pages/medical/devices/controllers/temp.dart

@@ -0,0 +1,86 @@
+/*
+ * @Descripttion: 
+ * @version: 
+ * @Author: guanxiaoxin
+ * @Date: 2023-10-23 13:19:37
+ * @LastEditors: guanxiaoxin
+ * @LastEditTime: 2023-10-23 17:58:26
+ * @FilePath: \VNoteApp\lib\pages\medical\devices\controllers\temp.dart
+ */
+import 'dart:convert';
+
+import 'package:flutter/material.dart';
+import 'package:get/get.dart';
+import 'package:vnote_device_plugin/devices/temp.dart';
+import 'package:vnoteapp/pages/medical/devices/interfaces/device_controller.dart';
+import 'package:vnoteapp/pages/medical/models/item.dart';
+import 'package:vnoteapp/pages/medical/models/worker.dart';
+
+class TempController extends GetxController implements IDeviceController {
+  TempController({
+    required this.medicalItem,
+    required this.deviceChange,
+  });
+  MedicalItem medicalItem;
+  ValueChanged deviceChange;
+  final TempDeviceWorker worker = TempDeviceWorker(
+    mac: 'D0:05:00:00:00:67',
+    model: 'YHW-6',
+  );
+
+  /// 连接设备
+  @override
+  Future<void> connectDevice() async {
+    await worker.connect();
+  }
+
+  @override
+  void workerAddListener() async {
+    worker.successEvent.addListener(_onSuccess);
+    worker.connectErrorEvent.addListener(_onConnectFail);
+    worker.connectedEvent.addListener(_onConnectSuccess);
+    worker.disconnectedEvent.addListener(_onDisconnected);
+  }
+
+  @override
+  void onInit() {
+    connectDevice();
+    workerAddListener();
+    super.onInit();
+  }
+
+  @override
+  void dispose() {
+    disConnectDevice();
+    super.dispose();
+  }
+
+  void _onSuccess(_, double e) {
+    medicalItem.diagnosisWorkerStatus = WorkerStatus.connected;
+    medicalItem.diagnosisData = jsonEncode({'Temperature': e});
+    deviceChange.call(medicalItem);
+  }
+
+  void _onConnectFail(sender, e) {
+    medicalItem.diagnosisWorkerStatus = WorkerStatus.connectionFailed;
+    deviceChange.call(medicalItem);
+    connectDevice();
+  }
+
+  void _onConnectSuccess(sender, e) {}
+
+  void _onDisconnected(sender, e) {
+    medicalItem.diagnosisWorkerStatus = WorkerStatus.disconnected;
+    deviceChange.call(medicalItem);
+    connectDevice();
+  }
+
+  @override
+  Future<void> disConnectDevice() async {
+    worker.connectErrorEvent.removeListener(_onConnectFail);
+    worker.connectedEvent.removeListener(_onConnectSuccess);
+    worker.successEvent.removeListener(_onSuccess);
+    worker.disconnectedEvent.removeListener(_onDisconnected);
+    await worker.disconnect();
+  }
+}

+ 12 - 0
lib/pages/medical/devices/interfaces/device_controller.dart

@@ -0,0 +1,12 @@
+abstract class IDeviceController {
+  IDeviceController();
+
+  /// 连接设备
+  Future<void> connectDevice();
+
+  /// 设备监听
+  void workerAddListener();
+
+  /// 断开设备
+  Future<void> disConnectDevice();
+}

+ 22 - 0
lib/pages/medical/models/item.dart

@@ -0,0 +1,22 @@
+import 'package:vnoteapp/pages/medical/models/worker.dart';
+
+class MedicalItem {
+  MedicalItem({
+    required this.diagnosticItem,
+    required this.key,
+    this.diagnosisData,
+    this.diagnosisWorkerStatus = WorkerStatus.connecting,
+  });
+
+  /// 诊疗项目
+  final String diagnosticItem;
+
+  /// 诊疗key
+  final String key;
+
+  /// 诊疗数据
+  String? diagnosisData;
+
+  /// 诊疗仪器状态
+  WorkerStatus diagnosisWorkerStatus;
+}

+ 0 - 11
lib/pages/medical/models/menu.dart

@@ -1,11 +0,0 @@
-class MedicalMenu {
-  MedicalMenu({
-    required this.title,
-    required this.key,
-    this.diagnosisData,
-  });
-
-  final String title;
-  final String key;
-  final String? diagnosisData;
-}

+ 9 - 0
lib/pages/medical/models/worker.dart

@@ -0,0 +1,9 @@
+enum WorkerStatus {
+  connecting, // 连接中
+
+  connected, // 已连接
+
+  connectionFailed, // 连接失败
+
+  disconnected, // 已断开
+}

+ 17 - 0
lib/pages/medical/state.dart

@@ -1,8 +1,25 @@
 import 'package:get/get.dart';
+import 'package:vnoteapp/pages/medical/models/item.dart';
 
 class MedicalState {
   final RxString _currentTab = RxString('Temp');
+  final RxList<MedicalItem> _medicalMenuList = RxList<MedicalItem>([
+    MedicalItem(key: 'Temp', diagnosticItem: '体温'),
+    MedicalItem(key: 'GLU', diagnosticItem: '血糖'),
+    MedicalItem(key: 'NIBP', diagnosticItem: '血压'),
+    MedicalItem(key: 'SpO2', diagnosticItem: '血氧'),
+    MedicalItem(key: 'BMI', diagnosticItem: 'BMI'),
+  ]);
+
+  // final Rx<Map<String, dynamic>> _diagnosisDataValue = Rx({});
 
   String get currentTab => _currentTab.value;
   set currentTab(String val) => _currentTab(val);
+
+  /// 诊疗展示列表
+  set medicalMenuList(List<MedicalItem> value) => _medicalMenuList(value);
+  List<MedicalItem> get medicalMenuList => _medicalMenuList;
+
+  // Map<String, dynamic> get diagnosisDataValue => _diagnosisDataValue.value;
+  // set diagnosisDataValue(Map<String, dynamic> val) => _diagnosisDataValue(val);
 }

+ 9 - 7
lib/pages/medical/view.dart

@@ -6,7 +6,7 @@ import 'package:vnoteapp/pages/medical/controller.dart';
 import 'package:vnoteapp/pages/medical/widgets/blood_pressure.dart';
 import 'package:vnoteapp/pages/medical/widgets/blood_sugar.dart';
 import 'package:vnoteapp/pages/medical/widgets/body_temperature.dart';
-import 'package:vnoteapp/pages/medical/widgets/body_weight.dart';
+import 'package:vnoteapp/pages/medical/widgets/body_bmi.dart';
 import 'package:vnoteapp/pages/medical/widgets/bool_oxygen.dart';
 
 class MedicalPage extends GetView<MedicalController> {
@@ -26,7 +26,7 @@ class MedicalPage extends GetView<MedicalController> {
         children: [
           Column(
             mainAxisAlignment: MainAxisAlignment.center,
-            children: controller.medicalMenuList
+            children: controller.state.medicalMenuList
                 .map(
                   (e) => Material(
                     borderRadius: const BorderRadius.only(
@@ -50,7 +50,7 @@ class MedicalPage extends GetView<MedicalController> {
                           },
                           child: Obx(
                             () => _SideBar(
-                              title: e.title,
+                              title: e.diagnosticItem,
                               isActive: controller.state.currentTab == e.key,
                             ),
                           )),
@@ -80,11 +80,14 @@ class MedicalPage extends GetView<MedicalController> {
                   ),
                 ),
                 Positioned(
-                    bottom: 16,
+                    bottom: 100,
                     right: 16,
                     child: VButton(
-                      child: const Text('保存'),
-                      onTap: () => {},
+                      onTap: controller.createDiagnosis,
+                      child: const Text(
+                        '保存',
+                        style: TextStyle(fontSize: 26),
+                      ),
                     ))
               ],
             ),
@@ -105,7 +108,6 @@ class MedicalPage extends GetView<MedicalController> {
           return const BloodPressure();
         case 'SpO2':
           return const BloodOxygen();
-
         case 'BMI':
           return const BodyWeight();
         default:

+ 16 - 19
lib/pages/medical/widgets/blood_pressure.dart

@@ -13,7 +13,9 @@ import 'package:vnoteapp/pages/check/widgets/exam_device_connect_status/connect.
 import 'package:vnoteapp/pages/check/widgets/exam_device_connect_status/connect_disconnected.dart';
 import 'package:vnoteapp/pages/check/widgets/exam_device_connect_status/connect_fail.dart';
 import 'package:vnoteapp/pages/check/widgets/exam_device_connect_status/connect_success.dart';
+import 'package:vnoteapp/pages/medical/controller.dart';
 
+/// TODO 需要优化
 /// 小弹窗输入
 class VDialogBloodPressure extends StatelessWidget {
   /// 标题
@@ -177,16 +179,21 @@ class BloodPressure extends StatefulWidget {
 
 class _ExamBloodPressureState extends State<BloodPressure> {
   var permissionManager = Get.find<IPermissionManager>();
+  var controller = Get.find<MedicalController>();
 
   late final NibpDeviceWorker worker = NibpDeviceWorker(
     mac: 'A4:C1:38:33:84:F8',
     model: 'AOJ-30B',
   );
   late int liveValue = 0;
-  NibpExamValue? value;
-  // late String spO2 = widget.currentValue['Spo2'];
-  bool _connectFailStatus = false;
+  late NibpExamValue? value = NibpExamValue(
+    diastolicPressure: controller.diagnosisDataValue['NIBP']?['Sbp'] ?? 0,
+    systolicPressure: controller.diagnosisDataValue['NIBP']?['Dbp'] ?? 0,
+    pulse: controller.diagnosisDataValue['NIBP']?['Pulse_Beat'] ?? 0,
+  );
+
   bool _connectSuccessStatus = false;
+  bool _connectFailStatus = false;
   bool _isConnect = false;
 
   /// 设备连接中断的状态
@@ -236,6 +243,11 @@ class _ExamBloodPressureState extends State<BloodPressure> {
   void _onSuccess(_, NibpExamValue e) {
     setState(() {
       value = e;
+      controller.diagnosisDataValue['NIBP'] = {
+        'Sbp': value?.diastolicPressure ?? '0',
+        'Dbp': value?.systolicPressure ?? '0',
+        'Pulse_Beat': value?.pulse
+      };
     });
   }
 
@@ -273,7 +285,7 @@ class _ExamBloodPressureState extends State<BloodPressure> {
   }
 
   Widget _buildValue() {
-    if (value != null) {
+    if (value?.pulse != 0) {
       return _buildResultWidget();
     }
     return _buildLiveWidget();
@@ -384,21 +396,6 @@ class _SideBar extends StatelessWidget {
               crossAxisAlignment: CrossAxisAlignment.end,
               children: [
                 value,
-                // RichText(
-                //   text: TextSpan(
-                //     text: value,
-                //     style: const TextStyle(
-                //       fontSize: 80,
-                //       color: Colors.black,
-                //     ),
-                //     children: [
-                //       TextSpan(
-                //         text: unit,
-                //         style: const TextStyle(fontSize: 25),
-                //       )
-                //     ],
-                //   ),
-                // ),
               ],
             ),
           ),

+ 250 - 139
lib/pages/medical/widgets/blood_sugar.dart

@@ -1,8 +1,7 @@
+import 'dart:convert';
+
 import 'package:flutter/material.dart';
 import 'package:get/get.dart';
-import 'package:vnote_device_plugin/devices/sugar.dart';
-import 'package:vnote_device_plugin/models/exams/sugar.dart';
-import 'package:vnoteapp/managers/interfaces/permission.dart';
 import 'package:vnoteapp/pages/check/widgets/exam_configurable/exam_card.dart';
 
 import 'package:vnoteapp/components/dialog_number.dart';
@@ -10,130 +9,24 @@ import 'package:vnoteapp/pages/check/widgets/exam_device_connect_status/connect.
 import 'package:vnoteapp/pages/check/widgets/exam_device_connect_status/connect_disconnected.dart';
 import 'package:vnoteapp/pages/check/widgets/exam_device_connect_status/connect_fail.dart';
 import 'package:vnoteapp/pages/check/widgets/exam_device_connect_status/connect_success.dart';
+import 'package:vnoteapp/pages/medical/controller.dart';
+import 'package:vnoteapp/pages/medical/models/worker.dart';
 
-// ignore: must_be_immutable
-class BloodSugar extends StatefulWidget {
-  const BloodSugar({
-    super.key,
-  });
-
-  @override
-  State<BloodSugar> createState() => _ExamBloodSugarState();
-}
-
-class _ExamBloodSugarState extends State<BloodSugar> {
-  var permissionManager = Get.find<IPermissionManager>();
-  late final SugarDeviceWorker worker = SugarDeviceWorker(
-    mac: '60:98:66:C4:0E:51',
-    model: 'i-sens630',
-  );
-
-  /// 设备连接失败的状态
-  bool _connectFailStatus = false;
-
-  /// 设备连接中断的状态
-  bool _connectDisconnectedStatus = false;
-
-  /// 设备连接成功的状态
-  bool _connectSuccessStatus = false;
-
-  /// 设备是否连接中
-  bool _isConnect = false;
-
-  String _value = '';
-  @override
-  void initState() {
-    getPermission();
-    worker.successEvent.addListener(_onSuccess);
-    worker.connectErrorEvent.addListener(_onConnectFail);
-    worker.connectedEvent.addListener(_onConnectSuccess);
-    worker.disconnectedEvent.addListener(_onDisconnected);
-
-    connect();
-    super.initState();
-  }
-
-  Future<void> connect() async {
-    _connectFailStatus = false;
-    _isConnect = true;
-    _connectSuccessStatus = false;
-    _connectDisconnectedStatus = false;
-    setState(() {});
-    await worker.connect();
-  }
-
-  Future<void> disconnect() async {
-    worker.connectErrorEvent.removeListener(_onConnectFail);
-    worker.connectedEvent.removeListener(_onConnectSuccess);
-    worker.successEvent.removeListener(_onSuccess);
-    worker.disconnectedEvent.removeListener(_onDisconnected);
-    await worker.disconnect();
-  }
-
-  @override
-  void dispose() {
-    disconnect();
-    super.dispose();
-  }
-
-  void _onSuccess(_, SugarExamData e) {
-    setState(() {
-      _value = e.sugar.toString();
-
-      _isConnect = false;
-    });
-  }
-
-  void _onConnectFail(sender, e) {
-    print('连接设备失败');
-    _connectFailStatus = true;
-    _connectSuccessStatus = false;
-    _connectDisconnectedStatus = false;
-    _isConnect = false;
-    setState(() {});
-  }
-
-  void _onConnectSuccess(sender, e) {
-    _connectSuccessStatus = true;
-    _isConnect = false;
-    _connectFailStatus = false;
-    _connectDisconnectedStatus = false;
-    setState(() {});
-  }
-
-  void _onDisconnected(sender, e) {
-    print('设备连接中断');
-    _connectDisconnectedStatus = true;
-    _connectSuccessStatus = false;
-    _connectFailStatus = false;
-    _isConnect = false;
-    setState(() {});
-  }
-
-  Future<void> getPermission() async {
-    await permissionManager.requestLocationPermission();
-    await permissionManager.requestBluetoothConnectPermission();
-    await permissionManager.requestBluetoothAdvertisePermission();
-    await permissionManager.requestBluetoothScanPermission();
-  }
+class BloodSugar extends GetView<MedicalController> {
+  const BloodSugar({super.key});
 
   @override
   Widget build(BuildContext context) {
-    return Stack(
-      children: [
-        _buildTemperature(),
-        if (_connectFailStatus)
-          DeviceConnectFail(
-            connect: () => connect(),
-          ),
-        if (_connectSuccessStatus) const DeviceConnectSuccess(),
-        if (_isConnect) const DeviceConnect(),
-        if (_connectDisconnectedStatus)
-          DeviceConnectDisconnected(
-            connect: () => connect(),
-          ),
-      ],
-    );
+    return Obx(() {
+      var element = controller.state.medicalMenuList
+          .firstWhere((element) => element.key == 'GLU');
+      return Stack(
+        children: [
+          _buildTemperature(),
+          _buildStutas(element.diagnosisWorkerStatus),
+        ],
+      );
+    });
   }
 
   Widget _buildTemperature() {
@@ -155,21 +48,28 @@ class _ExamBloodSugarState extends State<BloodSugar> {
             mainAxisAlignment: MainAxisAlignment.end,
             crossAxisAlignment: CrossAxisAlignment.end,
             children: [
-              RichText(
-                text: TextSpan(
-                  text: _value,
-                  style: const TextStyle(
-                    fontSize: 80,
-                    color: Colors.black,
+              Obx(() {
+                var element = controller.state.medicalMenuList
+                    .firstWhere((element) => element.key == 'GLU');
+                String? value = element.diagnosisData;
+                String text =
+                    value != null ? jsonDecode(value)['sugar'].toString() : '';
+                return RichText(
+                  text: TextSpan(
+                    text: text,
+                    style: const TextStyle(
+                      fontSize: 80,
+                      color: Colors.black,
+                    ),
+                    children: const [
+                      TextSpan(
+                        text: 'mmol/L',
+                        style: TextStyle(fontSize: 25),
+                      )
+                    ],
                   ),
-                  children: const [
-                    TextSpan(
-                      text: 'mmol/L',
-                      style: TextStyle(fontSize: 25),
-                    )
-                  ],
-                ),
-              ),
+                );
+              })
             ],
           ),
         ),
@@ -180,10 +80,221 @@ class _ExamBloodSugarState extends State<BloodSugar> {
   Future<void> _inputTemperature() async {
     String? result = await VDialogNumber(
       title: '血糖',
-      initialValue: _value,
+      initialValue: jsonDecode(
+          controller.state.medicalMenuList.first.diagnosisData ?? '')['sugar'],
     ).show();
     if (result?.isNotEmpty ?? false) {
-      _value = result ?? '';
+      jsonDecode(controller.state.medicalMenuList.first.diagnosisData ?? '')[
+          'sugar'] = result ?? '';
+    }
+  }
+
+  Widget _buildStutas(diagnosisWorkerStatus) {
+    switch (diagnosisWorkerStatus) {
+      case WorkerStatus.connectionFailed:
+        return const DeviceConnectFail();
+      case WorkerStatus.connected:
+        return const DeviceConnectSuccess();
+      case WorkerStatus.connecting:
+        return const DeviceConnect();
+      case WorkerStatus.disconnected:
+        return const DeviceConnectDisconnected();
+      default:
+        return const SizedBox();
     }
   }
 }
+
+
+// // ignore: must_be_immutable
+// class BloodSugar extends StatefulWidget {
+//   const BloodSugar({
+//     super.key,
+//   });
+
+//   @override
+//   State<BloodSugar> createState() => _ExamBloodSugarState();
+// }
+
+// class _ExamBloodSugarState extends State<BloodSugar> {
+//   var permissionManager = Get.find<IPermissionManager>();
+//   var controller = Get.find<MedicalController>();
+
+//   late final SugarDeviceWorker worker = SugarDeviceWorker(
+//     mac: '60:98:66:C4:0E:51',
+//     model: 'i-sens630',
+//   );
+
+//   /// 设备连接失败的状态
+//   bool _connectFailStatus = false;
+
+//   /// 设备连接中断的状态
+//   bool _connectDisconnectedStatus = false;
+
+//   /// 设备连接成功的状态
+//   bool _connectSuccessStatus = false;
+
+//   /// 设备是否连接中
+//   bool _isConnect = false;
+
+//   late String _value = controller.diagnosisDataValue['GLU']?['sugar'] ?? '';
+//   @override
+//   void initState() {
+//     initSugar();
+//     super.initState();
+//   }
+
+//   void workerAddListener() {
+//     worker.successEvent.addListener(_onSuccess);
+//     worker.connectErrorEvent.addListener(_onConnectFail);
+//     worker.connectedEvent.addListener(_onConnectSuccess);
+//     worker.disconnectedEvent.addListener(_onDisconnected);
+//   }
+
+//   Future<void> initSugar() async {
+//     getPermission();
+//     workerAddListener();
+//     await connect();
+//     await initData();
+//   }
+
+//   Future<void> initData() async {
+//     await controller.readCachedRecord();
+//     _value = controller.diagnosisDataValue['GLU']?['sugar'] ?? '';
+//     setState(() {});
+//   }
+
+//   Future<void> connect() async {
+//     _connectFailStatus = false;
+//     _isConnect = true;
+//     _connectSuccessStatus = false;
+//     _connectDisconnectedStatus = false;
+//     setState(() {});
+//     await worker.connect();
+//   }
+
+//   Future<void> disconnect() async {
+//     worker.connectErrorEvent.removeListener(_onConnectFail);
+//     worker.connectedEvent.removeListener(_onConnectSuccess);
+//     worker.successEvent.removeListener(_onSuccess);
+//     worker.disconnectedEvent.removeListener(_onDisconnected);
+//     await worker.disconnect();
+//   }
+
+//   @override
+//   void dispose() {
+//     disconnect();
+//     super.dispose();
+//   }
+
+//   void _onSuccess(_, SugarExamData e) {
+//     setState(() {
+//       _value = e.sugar.toString();
+//       controller.diagnosisDataValue['GLU'] = {'sugar': _value};
+//       _isConnect = false;
+//     });
+//   }
+
+//   void _onConnectFail(sender, e) {
+//     print('连接设备失败');
+//     _connectFailStatus = true;
+//     _connectSuccessStatus = false;
+//     _connectDisconnectedStatus = false;
+//     _isConnect = false;
+//     setState(() {});
+//   }
+
+//   void _onConnectSuccess(sender, e) {
+//     _connectSuccessStatus = true;
+//     _isConnect = false;
+//     _connectFailStatus = false;
+//     _connectDisconnectedStatus = false;
+//     setState(() {});
+//   }
+
+//   void _onDisconnected(sender, e) {
+//     print('设备连接中断');
+//     _connectDisconnectedStatus = true;
+//     _connectSuccessStatus = false;
+//     _connectFailStatus = false;
+//     _isConnect = false;
+//     setState(() {});
+//   }
+
+//   Future<void> getPermission() async {
+//     await permissionManager.requestLocationPermission();
+//     await permissionManager.requestBluetoothConnectPermission();
+//     await permissionManager.requestBluetoothAdvertisePermission();
+//     await permissionManager.requestBluetoothScanPermission();
+//   }
+
+//   @override
+//   Widget build(BuildContext context) {
+//     return Stack(
+//       children: [
+//         _buildTemperature(),
+//         if (_connectFailStatus)
+//           DeviceConnectFail(
+//             connect: () => connect(),
+//           ),
+//         if (_connectSuccessStatus) const DeviceConnectSuccess(),
+//         if (_isConnect) const DeviceConnect(),
+//         if (_connectDisconnectedStatus)
+//           DeviceConnectDisconnected(
+//             connect: () => connect(),
+//           ),
+//       ],
+//     );
+//   }
+
+//   Widget _buildTemperature() {
+//     return ExamCard(
+//       title: '血糖',
+//       clickCard: () {
+//         _inputTemperature();
+//       },
+//       content: Container(
+//         alignment: Alignment.bottomRight,
+//         padding: const EdgeInsets.only(
+//           bottom: 20,
+//           right: 30,
+//           left: 40,
+//         ),
+//         constraints: const BoxConstraints(minHeight: 150),
+//         child: FittedBox(
+//           child: Row(
+//             mainAxisAlignment: MainAxisAlignment.end,
+//             crossAxisAlignment: CrossAxisAlignment.end,
+//             children: [
+//               RichText(
+//                 text: TextSpan(
+//                   text: _value,
+//                   style: const TextStyle(
+//                     fontSize: 80,
+//                     color: Colors.black,
+//                   ),
+//                   children: const [
+//                     TextSpan(
+//                       text: 'mmol/L',
+//                       style: TextStyle(fontSize: 25),
+//                     )
+//                   ],
+//                 ),
+//               ),
+//             ],
+//           ),
+//         ),
+//       ),
+//     );
+//   }
+
+//   Future<void> _inputTemperature() async {
+//     String? result = await VDialogNumber(
+//       title: '血糖',
+//       initialValue: _value,
+//     ).show();
+//     if (result?.isNotEmpty ?? false) {
+//       _value = result ?? '';
+//     }
+//   }
+// }

+ 225 - 0
lib/pages/medical/widgets/body_bmi.dart

@@ -0,0 +1,225 @@
+import 'package:flutter/material.dart';
+import 'package:get/get.dart';
+import 'package:vnote_device_plugin/devices/weight.dart';
+import 'package:vnoteapp/managers/interfaces/permission.dart';
+import 'package:vnoteapp/pages/check/widgets/exam_configurable/exam_card.dart';
+
+import 'package:vnoteapp/components/dialog_number.dart';
+import 'package:vnoteapp/pages/check/widgets/exam_device_connect_status/connect.dart';
+import 'package:vnoteapp/pages/check/widgets/exam_device_connect_status/connect_disconnected.dart';
+import 'package:vnoteapp/pages/check/widgets/exam_device_connect_status/connect_fail.dart';
+import 'package:vnoteapp/pages/check/widgets/exam_device_connect_status/connect_success.dart';
+import 'package:vnoteapp/pages/medical/controller.dart';
+import 'package:vnoteapp/pages/medical/widgets/side_bar.dart';
+
+// ignore: must_be_immutable
+class BodyWeight extends StatefulWidget {
+  const BodyWeight({
+    super.key,
+  });
+
+  @override
+  State<BodyWeight> createState() => _ExamBodyWeightState();
+}
+
+class _ExamBodyWeightState extends State<BodyWeight> {
+  var permissionManager = Get.find<IPermissionManager>();
+  var controller = Get.find<MedicalController>();
+
+  late final WeightDeviceWorker worker = WeightDeviceWorker(
+    mac: 'CF:E4:2C:22:01:39',
+    model: 'CF398BLE',
+  );
+
+  /// 设备连接失败的状态
+  bool _connectFailStatus = false;
+
+  /// 设备连接中断的状态
+  bool _connectDisconnectedStatus = false;
+
+  /// 设备连接成功的状态
+  bool _connectSuccessStatus = false;
+
+  /// 设备是否连接中
+  bool _isConnect = false;
+  late String _weight = controller.diagnosisDataValue['BMI']?['Weight'] ?? '';
+  late String _height = controller.diagnosisDataValue['BMI']?['Height'] ?? '';
+  late String _bmi = controller.diagnosisDataValue['BMI']?['Bmi'] ?? '';
+
+  @override
+  void initState() {
+    initBmi();
+    super.initState();
+  }
+
+  Future<void> connect() async {
+    _connectFailStatus = false;
+    _isConnect = true;
+    _connectSuccessStatus = false;
+    _connectDisconnectedStatus = false;
+    setState(() {});
+    await worker.connect();
+  }
+
+  Future<void> disconnect() async {
+    worker.connectErrorEvent.removeListener(_onConnectFail);
+    worker.connectedEvent.removeListener(_onConnectSuccess);
+    worker.successEvent.removeListener(_onSuccess);
+    worker.disconnectedEvent.removeListener(_onDisconnected);
+    await worker.disconnect();
+  }
+
+  @override
+  void dispose() {
+    disconnect();
+    super.dispose();
+  }
+
+  void workerAddListener() {
+    worker.successEvent.addListener(_onSuccess);
+    worker.connectErrorEvent.addListener(_onConnectFail);
+    worker.connectedEvent.addListener(_onConnectSuccess);
+    worker.disconnectedEvent.addListener(_onDisconnected);
+  }
+
+  Future<void> initBmi() async {
+    getPermission();
+    workerAddListener();
+    await connect();
+    await initData();
+  }
+
+  Future<void> initData() async {
+    await controller.readCachedRecord();
+    if (controller.diagnosisDataValue['BMI'] == null) {
+      controller.diagnosisDataValue['BMI'] = {};
+    }
+    _weight = controller.diagnosisDataValue['BMI']?['Weight'] ?? '';
+    _height = controller.diagnosisDataValue['BMI']?['Height'] ?? '';
+    _bmi = controller.diagnosisDataValue['BMI']?['Bmi'] ?? '';
+    setState(() {});
+  }
+
+  void _onSuccess(_, double e) {
+    setState(() {
+      _weight = e.toString();
+      _isConnect = false;
+    });
+  }
+
+  void _onConnectFail(sender, e) {
+    print('连接设备失败');
+    _connectFailStatus = true;
+    _connectSuccessStatus = false;
+    _connectDisconnectedStatus = false;
+    _isConnect = false;
+    setState(() {});
+  }
+
+  void _onConnectSuccess(sender, e) {
+    _connectSuccessStatus = true;
+    _isConnect = false;
+    _connectFailStatus = false;
+    _connectDisconnectedStatus = false;
+    setState(() {});
+  }
+
+  void _onDisconnected(sender, e) {
+    print('设备连接中断');
+    _connectDisconnectedStatus = true;
+    _connectSuccessStatus = false;
+    _connectFailStatus = false;
+    _isConnect = false;
+    setState(() {});
+  }
+
+  Future<void> getPermission() async {
+    await permissionManager.requestLocationPermission();
+    await permissionManager.requestBluetoothConnectPermission();
+    await permissionManager.requestBluetoothAdvertisePermission();
+    await permissionManager.requestBluetoothScanPermission();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return ExamCard(
+        titleText: const SizedBox(),
+        // clickCard: () {},
+        content: Column(
+          mainAxisAlignment: MainAxisAlignment.start,
+          children: [
+            SideBar(
+              title: '身高',
+              value: _height,
+              unit: 'cm',
+              onTap: _inputHeight,
+            ),
+            const Divider(indent: 30),
+            Stack(
+              children: [
+                SideBar(
+                  title: '体重',
+                  value: _weight,
+                  hasDevice: true,
+                  unit: 'kg',
+                  onTap: _inputWeight,
+                ),
+                if (_connectFailStatus)
+                  DeviceConnectFail(
+                    connect: () => connect(),
+                  ),
+                if (_connectSuccessStatus) const DeviceConnectSuccess(),
+                if (_isConnect) const DeviceConnect(),
+                if (_connectDisconnectedStatus)
+                  DeviceConnectDisconnected(
+                    connect: () => connect(),
+                  ),
+              ],
+            ),
+            const Divider(indent: 30),
+            SideBar(
+              title: 'BMI',
+              value: _bmi,
+              unit: 'kg/m²',
+            ),
+          ],
+        ));
+  }
+
+  Future<void> _inputWeight() async {
+    String? result = await VDialogNumber(
+      title: '体重',
+      initialValue: _weight,
+    ).show();
+    if (result?.isNotEmpty ?? false) {
+      _weight = result ?? '';
+      getBmi();
+      controller.diagnosisDataValue['BMI']?['Weight'] = _weight;
+      controller.diagnosisDataValue['BMI']?['Bmi'] = _bmi;
+    }
+    setState(() {});
+  }
+
+  void getBmi() {
+    if (_weight.isNotEmpty && _height.isNotEmpty) {
+      _bmi = (double.parse(_weight) /
+              ((double.parse(_height) / 100) * (double.parse(_height) / 100)))
+          .toStringAsFixed(2);
+    }
+  }
+
+  Future<void> _inputHeight() async {
+    String? result = await VDialogNumber(
+      title: '身高',
+      initialValue: _height,
+    ).show();
+    if (result?.isNotEmpty ?? false) {
+      _height = result ?? '';
+
+      getBmi();
+      controller.diagnosisDataValue['BMI']?['Height'] = _height;
+      controller.diagnosisDataValue['BMI']?['Bmi'] = _bmi;
+    }
+    setState(() {});
+  }
+}

+ 250 - 136
lib/pages/medical/widgets/body_temperature.dart

@@ -1,135 +1,31 @@
+import 'dart:convert';
+
 import 'package:flutter/material.dart';
 import 'package:get/get.dart';
-import 'package:vnote_device_plugin/devices/temp.dart';
 import 'package:vnoteapp/components/dialog_number.dart';
-import 'package:vnoteapp/managers/interfaces/permission.dart';
 import 'package:vnoteapp/pages/check/widgets/exam_configurable/exam_card.dart';
 import 'package:vnoteapp/pages/check/widgets/exam_device_connect_status/connect.dart';
 import 'package:vnoteapp/pages/check/widgets/exam_device_connect_status/connect_disconnected.dart';
 import 'package:vnoteapp/pages/check/widgets/exam_device_connect_status/connect_fail.dart';
 import 'package:vnoteapp/pages/check/widgets/exam_device_connect_status/connect_success.dart';
+import 'package:vnoteapp/pages/medical/controller.dart';
+import 'package:vnoteapp/pages/medical/models/worker.dart';
 
-// ignore: must_be_immutable
-class BodyTemperature extends StatefulWidget {
-  const BodyTemperature({
-    super.key,
-  });
-
-  @override
-  State<BodyTemperature> createState() => _ExamBodyTemperatureState();
-}
-
-class _ExamBodyTemperatureState extends State<BodyTemperature> {
-  var permissionManager = Get.find<IPermissionManager>();
-  late final TempDeviceWorker worker = TempDeviceWorker(
-    mac: 'D0:05:00:00:00:67',
-    model: 'YHW-6',
-  );
-
-  /// 设备连接失败的状态
-  bool _connectFailStatus = false;
-
-  /// 设备连接中断的状态
-  bool _connectDisconnectedStatus = false;
-
-  /// 设备连接成功的状态
-  bool _connectSuccessStatus = false;
-
-  /// 设备是否连接中
-  bool _isConnect = false;
-  String _value = '';
-  @override
-  void initState() {
-    getPermission();
-    worker.successEvent.addListener(_onSuccess);
-    worker.connectErrorEvent.addListener(_onConnectFail);
-    worker.connectedEvent.addListener(_onConnectSuccess);
-    worker.disconnectedEvent.addListener(_onDisconnected);
-
-    connect();
-    super.initState();
-  }
-
-  Future<void> connect() async {
-    _connectFailStatus = false;
-    _isConnect = true;
-    _connectSuccessStatus = false;
-    _connectDisconnectedStatus = false;
-    setState(() {});
-    await worker.connect();
-  }
-
-  Future<void> disconnect() async {
-    worker.connectErrorEvent.removeListener(_onConnectFail);
-    worker.connectedEvent.removeListener(_onConnectSuccess);
-    worker.successEvent.removeListener(_onSuccess);
-    worker.disconnectedEvent.removeListener(_onDisconnected);
-    await worker.disconnect();
-  }
-
-  @override
-  void dispose() {
-    disconnect();
-    super.dispose();
-  }
-
-  void _onSuccess(_, double e) {
-    setState(() {
-      _value = e.toString();
-      _isConnect = false;
-    });
-  }
-
-  void _onConnectFail(sender, e) {
-    print('连接设备失败');
-    _connectFailStatus = true;
-    _connectSuccessStatus = false;
-    _connectDisconnectedStatus = false;
-    _isConnect = false;
-    setState(() {});
-  }
-
-  void _onConnectSuccess(sender, e) {
-    _connectSuccessStatus = true;
-    _isConnect = false;
-    _connectFailStatus = false;
-    _connectDisconnectedStatus = false;
-    setState(() {});
-  }
-
-  void _onDisconnected(sender, e) {
-    print('设备连接中断');
-    _connectDisconnectedStatus = true;
-    _connectSuccessStatus = false;
-    _connectFailStatus = false;
-    _isConnect = false;
-    setState(() {});
-  }
-
-  Future<void> getPermission() async {
-    await permissionManager.requestLocationPermission();
-    await permissionManager.requestBluetoothConnectPermission();
-    await permissionManager.requestBluetoothAdvertisePermission();
-    await permissionManager.requestBluetoothScanPermission();
-  }
+class BodyTemperature extends GetView<MedicalController> {
+  const BodyTemperature({super.key});
 
   @override
   Widget build(BuildContext context) {
-    return Stack(
-      children: [
-        _buildTemperature(),
-        if (_connectFailStatus)
-          DeviceConnectFail(
-            connect: () => connect(),
-          ),
-        if (_connectSuccessStatus) const DeviceConnectSuccess(),
-        if (_isConnect) const DeviceConnect(),
-        if (_connectDisconnectedStatus)
-          DeviceConnectDisconnected(
-            connect: () => connect(),
-          ),
-      ],
-    );
+    return Obx(() {
+      var element = controller.state.medicalMenuList
+          .firstWhere((element) => element.key == 'Temp');
+      return Stack(
+        children: [
+          _buildTemperature(),
+          _buildStutas(element.diagnosisWorkerStatus),
+        ],
+      );
+    });
   }
 
   Widget _buildTemperature() {
@@ -151,21 +47,28 @@ class _ExamBodyTemperatureState extends State<BodyTemperature> {
             mainAxisAlignment: MainAxisAlignment.end,
             crossAxisAlignment: CrossAxisAlignment.end,
             children: [
-              RichText(
-                text: TextSpan(
-                  text: _value,
-                  style: const TextStyle(
-                    fontSize: 80,
-                    color: Colors.black,
+              Obx(() {
+                String? value =
+                    controller.state.medicalMenuList.first.diagnosisData;
+                String text = value != null
+                    ? jsonDecode(value)['Temperature'].toString()
+                    : '';
+                return RichText(
+                  text: TextSpan(
+                    text: text,
+                    style: const TextStyle(
+                      fontSize: 80,
+                      color: Colors.black,
+                    ),
+                    children: const [
+                      TextSpan(
+                        text: '°C',
+                        style: TextStyle(fontSize: 25),
+                      )
+                    ],
                   ),
-                  children: const [
-                    TextSpan(
-                      text: '°C',
-                      style: TextStyle(fontSize: 25),
-                    )
-                  ],
-                ),
-              ),
+                );
+              })
             ],
           ),
         ),
@@ -176,10 +79,221 @@ class _ExamBodyTemperatureState extends State<BodyTemperature> {
   Future<void> _inputTemperature() async {
     String? result = await VDialogNumber(
       title: '体温',
-      initialValue: _value,
+      initialValue: jsonDecode(
+          controller.state.medicalMenuList.first.diagnosisData ??
+              '')['Temperature'],
     ).show();
     if (result?.isNotEmpty ?? false) {
-      _value = result ?? '';
+      jsonDecode(controller.state.medicalMenuList.first.diagnosisData ?? '')[
+          'Temperature'] = result ?? '';
+    }
+  }
+
+  Widget _buildStutas(diagnosisWorkerStatus) {
+    switch (diagnosisWorkerStatus) {
+      case WorkerStatus.connectionFailed:
+        return const DeviceConnectFail();
+      case WorkerStatus.connected:
+        return const DeviceConnectSuccess();
+      case WorkerStatus.connecting:
+        return const DeviceConnect();
+      case WorkerStatus.disconnected:
+        return const DeviceConnectDisconnected();
+      default:
+        return const SizedBox();
     }
   }
 }
+
+// class BodyTemperature extends StatefulWidget {
+//   const BodyTemperature({
+//     super.key,
+//   });
+
+//   @override
+//   State<BodyTemperature> createState() => _ExamBodyTemperatureState();
+// }
+
+// class _ExamBodyTemperatureState extends State<BodyTemperature> {
+//   var permissionManager = Get.find<IPermissionManager>();
+//   var controller = Get.find<MedicalController>();
+
+//   late final TempDeviceWorker worker = TempDeviceWorker(
+//     mac: 'D0:05:00:00:00:67',
+//     model: 'YHW-6',
+//   );
+
+//   /// 设备连接失败的状态
+//   bool _connectFailStatus = false;
+
+//   /// 设备连接中断的状态
+//   bool _connectDisconnectedStatus = false;
+
+//   /// 设备连接成功的状态
+//   bool _connectSuccessStatus = false;
+
+//   /// 设备是否连接中
+//   bool _isConnect = false;
+//   late String _value =
+//       controller.diagnosisDataValue['Temp']?['Temperature'] ?? '';
+//   @override
+//   void initState() {
+//     initTemperature();
+//     super.initState();
+//   }
+
+//   Future<void> initTemperature() async {
+//     getPermission();
+//     workerAddListener();
+//     await connect();
+//     await initData();
+//   }
+
+//   void workerAddListener() {
+//     worker.successEvent.addListener(_onSuccess);
+//     worker.connectErrorEvent.addListener(_onConnectFail);
+//     worker.connectedEvent.addListener(_onConnectSuccess);
+//     worker.disconnectedEvent.addListener(_onDisconnected);
+//   }
+
+//   Future<void> initData() async {
+//     await controller.readCachedRecord();
+//     _value = controller.diagnosisDataValue['Temp']?['Temperature'] ?? '';
+//     setState(() {});
+//   }
+
+//   Future<void> connect() async {
+//     _connectFailStatus = false;
+//     _isConnect = true;
+//     _connectSuccessStatus = false;
+//     _connectDisconnectedStatus = false;
+//     await worker.connect();
+
+//     setState(() {});
+//   }
+
+//   Future<void> disconnect() async {
+//     worker.connectErrorEvent.removeListener(_onConnectFail);
+//     worker.connectedEvent.removeListener(_onConnectSuccess);
+//     worker.successEvent.removeListener(_onSuccess);
+//     worker.disconnectedEvent.removeListener(_onDisconnected);
+//     await worker.disconnect();
+//   }
+
+//   @override
+//   void dispose() {
+//     disconnect();
+//     super.dispose();
+//   }
+
+//   void _onSuccess(_, double e) {
+//     setState(() {
+//       _value = e.toString();
+//       controller.diagnosisDataValue['Temp'] = {'Temperature': _value};
+//       _isConnect = false;
+//     });
+//   }
+
+//   void _onConnectFail(sender, e) {
+//     print('连接设备失败');
+//     _connectFailStatus = true;
+//     _connectSuccessStatus = false;
+//     _connectDisconnectedStatus = false;
+//     _isConnect = false;
+//     setState(() {});
+//   }
+
+//   void _onConnectSuccess(sender, e) {
+//     _connectSuccessStatus = true;
+//     _isConnect = false;
+//     _connectFailStatus = false;
+//     _connectDisconnectedStatus = false;
+//     setState(() {});
+//   }
+
+//   void _onDisconnected(sender, e) {
+//     print('设备连接中断');
+//     _connectDisconnectedStatus = true;
+//     _connectSuccessStatus = false;
+//     _connectFailStatus = false;
+//     _isConnect = false;
+//     setState(() {});
+//   }
+
+//   Future<void> getPermission() async {
+//     await permissionManager.requestLocationPermission();
+//     await permissionManager.requestBluetoothConnectPermission();
+//     await permissionManager.requestBluetoothAdvertisePermission();
+//     await permissionManager.requestBluetoothScanPermission();
+//   }
+
+//   @override
+//   Widget build(BuildContext context) {
+    // return Stack(
+    //   children: [
+    //     _buildTemperature(),
+    //     if (_connectFailStatus)
+    //       DeviceConnectFail(
+    //         connect: () => connect(),
+    //       ),
+    //     if (_connectSuccessStatus) const DeviceConnectSuccess(),
+    //     if (_isConnect) const DeviceConnect(),
+    //     if (_connectDisconnectedStatus)
+    //       DeviceConnectDisconnected(
+    //         connect: () => connect(),
+    //       ),
+    //   ],
+    // );
+//   }
+
+//   Widget _buildTemperature() {
+//     return ExamCard(
+//       title: '体温',
+//       clickCard: () {
+//         _inputTemperature();
+//       },
+//       content: Container(
+//         alignment: Alignment.bottomRight,
+//         padding: const EdgeInsets.only(
+//           bottom: 20,
+//           right: 30,
+//           left: 40,
+//         ),
+//         constraints: const BoxConstraints(minHeight: 150),
+//         child: FittedBox(
+//           child: Row(
+//             mainAxisAlignment: MainAxisAlignment.end,
+//             crossAxisAlignment: CrossAxisAlignment.end,
+//             children: [
+//               RichText(
+//                 text: TextSpan(
+//                   text: _value,
+//                   style: const TextStyle(
+//                     fontSize: 80,
+//                     color: Colors.black,
+//                   ),
+//                   children: const [
+//                     TextSpan(
+//                       text: '°C',
+//                       style: TextStyle(fontSize: 25),
+//                     )
+//                   ],
+//                 ),
+//               ),
+//             ],
+//           ),
+//         ),
+//       ),
+//     );
+//   }
+
+//   Future<void> _inputTemperature() async {
+//     String? result = await VDialogNumber(
+//       title: '体温',
+//       initialValue: _value,
+//     ).show();
+//     if (result?.isNotEmpty ?? false) {
+//       _value = result ?? '';
+//     }
+//   }
+// }

+ 0 - 507
lib/pages/medical/widgets/body_weight.dart

@@ -1,507 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:get/get.dart';
-import 'package:vnote_device_plugin/devices/weight.dart';
-import 'package:vnoteapp/managers/interfaces/permission.dart';
-import 'package:vnoteapp/pages/check/models/form.dart';
-import 'package:vnoteapp/pages/check/widgets/exam_configurable/exam_card.dart';
-
-import 'package:vnoteapp/components/dialog_number.dart';
-import 'package:vnoteapp/pages/check/widgets/exam_device_connect_status/connect.dart';
-import 'package:vnoteapp/pages/check/widgets/exam_device_connect_status/connect_disconnected.dart';
-import 'package:vnoteapp/pages/check/widgets/exam_device_connect_status/connect_fail.dart';
-import 'package:vnoteapp/pages/check/widgets/exam_device_connect_status/connect_success.dart';
-
-// ignore: must_be_immutable
-class BodyWeight extends StatefulWidget {
-  const BodyWeight({
-    super.key,
-  });
-
-  @override
-  State<BodyWeight> createState() => _ExamBodyWeightState();
-}
-
-class _ExamBodyWeightState extends State<BodyWeight> {
-  var permissionManager = Get.find<IPermissionManager>();
-  late final WeightDeviceWorker worker = WeightDeviceWorker(
-    mac: 'CF:E4:2C:22:01:39',
-    model: 'CF398BLE',
-  );
-
-  /// 设备连接失败的状态
-  bool _connectFailStatus = false;
-
-  /// 设备连接中断的状态
-  bool _connectDisconnectedStatus = false;
-
-  /// 设备连接成功的状态
-  bool _connectSuccessStatus = false;
-
-  /// 设备是否连接中
-  bool _isConnect = false;
-  String _value = '';
-  @override
-  void initState() {
-    getPermission();
-    worker.successEvent.addListener(_onSuccess);
-    worker.connectErrorEvent.addListener(_onConnectFail);
-    worker.connectedEvent.addListener(_onConnectSuccess);
-    worker.disconnectedEvent.addListener(_onDisconnected);
-
-    connect();
-    super.initState();
-  }
-
-  Future<void> connect() async {
-    _connectFailStatus = false;
-    _isConnect = true;
-    _connectSuccessStatus = false;
-    _connectDisconnectedStatus = false;
-    setState(() {});
-    await worker.connect();
-  }
-
-  Future<void> disconnect() async {
-    worker.connectErrorEvent.removeListener(_onConnectFail);
-    worker.connectedEvent.removeListener(_onConnectSuccess);
-    worker.successEvent.removeListener(_onSuccess);
-    worker.disconnectedEvent.removeListener(_onDisconnected);
-    await worker.disconnect();
-  }
-
-  @override
-  void dispose() {
-    disconnect();
-    super.dispose();
-  }
-
-  void _onSuccess(_, double e) {
-    setState(() {
-      _value = e.toString();
-      _isConnect = false;
-    });
-  }
-
-  void _onConnectFail(sender, e) {
-    print('连接设备失败');
-    _connectFailStatus = true;
-    _connectSuccessStatus = false;
-    _connectDisconnectedStatus = false;
-    _isConnect = false;
-    setState(() {});
-  }
-
-  void _onConnectSuccess(sender, e) {
-    _connectSuccessStatus = true;
-    _isConnect = false;
-    _connectFailStatus = false;
-    _connectDisconnectedStatus = false;
-    setState(() {});
-  }
-
-  void _onDisconnected(sender, e) {
-    print('设备连接中断');
-    _connectDisconnectedStatus = true;
-    _connectSuccessStatus = false;
-    _connectFailStatus = false;
-    _isConnect = false;
-    setState(() {});
-  }
-
-  Future<void> getPermission() async {
-    await permissionManager.requestLocationPermission();
-    await permissionManager.requestBluetoothConnectPermission();
-    await permissionManager.requestBluetoothAdvertisePermission();
-    await permissionManager.requestBluetoothScanPermission();
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    return Stack(
-      children: [
-        _buildTemperature(),
-        if (_connectFailStatus)
-          DeviceConnectFail(
-            connect: () => connect(),
-          ),
-        if (_connectSuccessStatus) const DeviceConnectSuccess(),
-        if (_isConnect) const DeviceConnect(),
-        if (_connectDisconnectedStatus)
-          DeviceConnectDisconnected(
-            connect: () => connect(),
-          ),
-      ],
-    );
-  }
-
-  Widget _buildTemperature() {
-    return ExamCard(
-      title: '体重',
-      clickCard: () {
-        _inputTemperature();
-      },
-      content: Container(
-        alignment: Alignment.bottomRight,
-        padding: const EdgeInsets.only(
-          bottom: 20,
-          right: 30,
-          left: 40,
-        ),
-        constraints: const BoxConstraints(minHeight: 150),
-        child: FittedBox(
-          child: Row(
-            mainAxisAlignment: MainAxisAlignment.end,
-            crossAxisAlignment: CrossAxisAlignment.end,
-            children: [
-              RichText(
-                text: TextSpan(
-                  text: _value,
-                  style: const TextStyle(
-                    fontSize: 80,
-                    color: Colors.black,
-                  ),
-                  children: const [
-                    TextSpan(
-                      text: 'kg',
-                      style: TextStyle(fontSize: 25),
-                    )
-                  ],
-                ),
-              ),
-            ],
-          ),
-        ),
-      ),
-    );
-  }
-
-  Future<void> _inputTemperature() async {
-    String? result = await VDialogNumber(
-      title: '体重',
-      initialValue: _value,
-    ).show();
-    if (result?.isNotEmpty ?? false) {
-      _value = result ?? '';
-    }
-  }
-}
-
-
-
-// class BodyWeight extends StatefulWidget {
-//   const BodyWeight({
-//     super.key,
-//     required this.currentFormObject,
-//     required this.currentInputValue,
-//     this.specialInput,
-//   });
-//   final FormObject currentFormObject;
-//   final String currentInputValue;
-//   final Function(String value)? specialInput;
-
-//   @override
-//   State<ExamBodyWeight> createState() => _ExamBodyWeightState();
-// }
-
-// class _ExamBodyWeightState extends State<ExamBodyWeight> {
-//   var permissionManager = Get.find<IPermissionManager>();
-//   @override
-//   void initState() {
-//     getPermission();
-//     super.initState();
-//   }
-
-//   Future<void> getPermission() async {
-//     await permissionManager.requestLocationPermission();
-//     await permissionManager.requestBluetoothConnectPermission();
-//     await permissionManager.requestBluetoothAdvertisePermission();
-//     await permissionManager.requestBluetoothScanPermission();
-//   }
-
-//   @override
-//   Widget build(BuildContext context) {
-//     return ExamCard(
-//       title: widget.currentFormObject.label ?? '',
-//       clickCard: () {
-//         _buildTempertureInput(widget.currentFormObject);
-//       },
-//       content: Container(
-//         alignment: Alignment.bottomRight,
-//         padding: const EdgeInsets.only(
-//           bottom: 20,
-//           right: 30,
-//           left: 40,
-//         ),
-//         constraints: const BoxConstraints(minHeight: 150),
-//         child: FittedBox(
-//           child: Row(
-//             mainAxisAlignment: MainAxisAlignment.end,
-//             crossAxisAlignment: CrossAxisAlignment.end,
-//             children: [
-//               RichText(
-//                 text: TextSpan(
-//                   text: widget.currentInputValue,
-//                   style: const TextStyle(
-//                     fontSize: 80,
-//                     color: Colors.black,
-//                   ),
-//                   children: [
-//                     TextSpan(
-//                       text: widget.currentFormObject.append ?? '',
-//                       style: const TextStyle(fontSize: 25),
-//                     )
-//                   ],
-//                 ),
-//               ),
-//             ],
-//           ),
-//         ),
-//       ),
-//     );
-//   }
-
-//   Future<void> _buildTempertureInput(FormObject currentFormObject) async {
-//     // Future.delayed(const Duration(milliseconds: 3000), () {
-//     //   specialInputController.text = generateRandomNumber().toString();
-//     //   widget.specialInput?.call(specialInputController.text);
-//     //   setState(() {});
-//     // });
-
-//     final result = await Get.dialog(
-//       Weight(
-//         currentFormObject: widget.currentFormObject,
-//         weight: widget.currentInputValue,
-//       ),
-//       barrierDismissible: false,
-//     );
-//     widget.specialInput?.call(result);
-//     print('object');
-//     print(result);
-//     print('object');
-//   }
-// }
-
-// class Weight extends StatefulWidget {
-//   const Weight({
-//     super.key,
-//     required this.currentFormObject,
-//     this.weight,
-//   });
-//   final FormObject currentFormObject;
-//   final String? weight;
-
-//   @override
-//   State<Weight> createState() => _WeightState();
-// }
-
-// class _WeightState extends State<Weight> {
-//   late final WeightDeviceWorker worker = WeightDeviceWorker(
-//     mac: 'CF:E4:2C:22:01:39',
-//     model: 'CF398BLE',
-//   );
-//   late TextEditingController specialInputController =
-//       TextEditingController(text: widget.weight ?? '00.0');
-//   bool connectFailState = false;
-//   bool connectSuccessState = false;
-//   bool isConnect = false;
-
-//   @override
-//   void initState() {
-//     connect();
-
-//     worker.successEvent.addListener(_onSuccess);
-//     worker.connectErrorEvent.addListener(_onConnectFail);
-//     worker.connectedEvent.addListener(_onConnectSuccess);
-
-//     super.initState();
-//   }
-
-//   Future<void> connect() async {
-//     connectFailState = false;
-//     isConnect = true;
-//     connectSuccessState = false;
-//     setState(() {});
-//     await worker.connect();
-//   }
-
-//   Future<void> disconnect() async {
-//     worker.connectErrorEvent.removeListener(_onConnectFail);
-//     worker.connectedEvent.removeListener(_onConnectSuccess);
-//     worker.successEvent.removeListener(_onSuccess);
-//     await worker.disconnect();
-//   }
-
-//   @override
-//   void dispose() {
-//     super.dispose();
-//   }
-
-//   void _onSuccess(_, double e) {
-//     setState(() {
-//       specialInputController.text = e.toString();
-//       // connectFailState = false;
-//       // connectSuccessState = false;
-//       isConnect = false;
-//       // disconnect();
-//     });
-//   }
-
-//   void _onConnectFail(sender, e) {
-//     print('连接设备失败');
-//     connectFailState = true;
-//     connectSuccessState = false;
-//     isConnect = false;
-//     disconnect();
-//     setState(() {});
-//   }
-
-//   void _onConnectSuccess(sender, e) {
-//     connectSuccessState = true;
-//     connectFailState = false;
-//     isConnect = false;
-//     setState(() {});
-//   }
-
-//   @override
-//   Widget build(BuildContext context) {
-//     return VAlertDialog(
-//       title: widget.currentFormObject.label ?? '',
-//       width: 600,
-//       contentPadding: const EdgeInsets.symmetric(vertical: 12, horizontal: 24),
-//       content: buildMainWidget(),
-//       showCancel: true,
-//       onConfirm: () {
-//         disconnect();
-//         Get.back(result: specialInputController.text);
-//       },
-//       onCanceled: () {
-//         disconnect();
-//       },
-//     );
-//   }
-
-//   Widget buildInputField() {
-//     return Container(
-//       width: 350,
-//       padding: const EdgeInsets.only(left: 15),
-//       child: TextFormField(
-//         keyboardType: TextInputType.number,
-//         style: const TextStyle(
-//           fontSize: 100,
-//         ),
-//         showCursor: false,
-//         controller: specialInputController,
-//         decoration: const InputDecoration(
-//           labelStyle: TextStyle(
-//             fontSize: 100,
-//           ),
-//         ),
-//       ),
-//     );
-//   }
-
-//   Widget buildConnectFailText() {
-//     return const Text(
-//       '设备连接失败',
-//       style: TextStyle(
-//         color: Colors.red,
-//         fontSize: 25,
-//       ),
-//       textAlign: TextAlign.left,
-//     );
-//   }
-
-//   Widget buildConnectSuccessText() {
-//     return const Text(
-//       '设备连接成功',
-//       style: TextStyle(
-//         color: Colors.green,
-//         fontSize: 25,
-//       ),
-//       textAlign: TextAlign.left,
-//     );
-//   }
-
-//   Widget buildConnectingText() {
-//     return const Row(
-//       children: [
-//         Expanded(
-//           child: Text(
-//             '设备连接中',
-//             style: TextStyle(
-//               fontSize: 40,
-//               color: Colors.blue,
-//             ),
-//           ),
-//         ),
-//         CircularProgressIndicator(
-//           valueColor: AlwaysStoppedAnimation(
-//             Colors.blue,
-//           ),
-//         ),
-//         SizedBox(
-//           width: 20,
-//         ),
-//       ],
-//     );
-//   }
-
-//   Widget buildReconnectButton() {
-//     return Container(
-//       margin: const EdgeInsets.only(top: 4),
-//       width: 134,
-//       child: VButton(
-//         onTap: () async {
-//           /// TODO
-//           await connect();
-//           worker.connectErrorEvent.addListener(_onConnectFail);
-//           worker.connectedEvent.addListener(_onConnectSuccess);
-
-//           /// TODO 后面需要改,这边暂时演示用
-//           Future.delayed(const Duration(milliseconds: 8000), () {
-//             if (!connectSuccessState) {
-//               connectFailState = true;
-//             }
-//           });
-//         },
-//         child: const Row(
-//           mainAxisAlignment: MainAxisAlignment.center,
-//           children: [
-//             Icon(Icons.connected_tv_rounded, size: 24),
-//             SizedBox(
-//               width: 8,
-//             ),
-//             Text("重连", style: TextStyle(fontSize: 20)),
-//           ],
-//         ),
-//       ),
-//     );
-//   }
-
-//   Widget buildConnectStateWidgets() {
-//     return Column(
-//       children: [
-//         if (connectFailState) buildConnectFailText(),
-//         if (connectSuccessState) buildConnectSuccessText(),
-//         if (isConnect)
-//           buildConnectingText()
-//         else if (connectFailState)
-//           buildReconnectButton(),
-//       ],
-//     );
-//   }
-
-//   Widget buildMainWidget() {
-//     return SizedBox(
-//       height: 100,
-//       child: Row(
-//         children: [
-//           buildInputField(),
-//           Expanded(
-//             child: buildConnectStateWidgets(),
-//           ),
-//         ],
-//       ),
-//     );
-//   }
-// }

+ 31 - 87
lib/pages/medical/widgets/bool_oxygen.dart

@@ -8,6 +8,8 @@ import 'package:vnoteapp/pages/check/widgets/exam_device_connect_status/connect.
 import 'package:vnoteapp/pages/check/widgets/exam_device_connect_status/connect_disconnected.dart';
 import 'package:vnoteapp/pages/check/widgets/exam_device_connect_status/connect_fail.dart';
 import 'package:vnoteapp/pages/check/widgets/exam_device_connect_status/connect_success.dart';
+import 'package:vnoteapp/pages/medical/controller.dart';
+import 'package:vnoteapp/pages/medical/widgets/side_bar.dart';
 
 // ignore: must_be_immutable
 class BloodOxygen extends StatefulWidget {
@@ -21,14 +23,16 @@ class BloodOxygen extends StatefulWidget {
 
 class _ExamBloodOxygenState extends State<BloodOxygen> {
   var permissionManager = Get.find<IPermissionManager>();
+  var controller = Get.find<MedicalController>();
 
   late final SpO2DeviceWorker worker = SpO2DeviceWorker(
     mac: 'A4:C1:38:0B:CC:60',
     model: 'AOJ-70B',
   );
-  Map currentValue = {};
-  late String pulse = currentValue['Pulse_Frequency'] ?? '0';
-  late String spO2 = currentValue['Spo2'] ?? '0';
+
+  late String pulse =
+      controller.diagnosisDataValue['SpO2']?['Pulse_Frequency'] ?? '0';
+  late String spO2 = controller.diagnosisDataValue['SpO2']?['Spo2'] ?? '0';
   bool _connectFailStatus = false;
   bool _connectSuccessStatus = false;
   bool _isConnect = false;
@@ -37,14 +41,29 @@ class _ExamBloodOxygenState extends State<BloodOxygen> {
   bool _connectDisconnectedStatus = false;
   @override
   void initState() {
-    getPermission();
+    initOxygen();
+
+    super.initState();
+  }
+
+  void workerAddListener() {
     worker.valueUpdateEvent.addListener(_onSuccess);
     worker.connectErrorEvent.addListener(_onConnectFail);
     worker.connectedEvent.addListener(_onConnectSuccess);
+  }
 
-    connect();
+  Future<void> initOxygen() async {
+    getPermission();
+    workerAddListener();
+    await connect();
+    await initData();
+  }
 
-    super.initState();
+  Future<void> initData() async {
+    await controller.readCachedRecord();
+    pulse = controller.diagnosisDataValue['SpO2']?['Pulse_Frequency'];
+    spO2 = controller.diagnosisDataValue['SpO2']?['Spo2'];
+    setState(() {});
   }
 
   Future<void> connect() async {
@@ -73,18 +92,11 @@ class _ExamBloodOxygenState extends State<BloodOxygen> {
     setState(() {
       pulse = e.pulse.toString();
       spO2 = e.spO2.toString();
-      // connectFailState = false;
-      // connectSuccessState = false;
-      // widget.bloodOxygenInput.call({
-      //   'Spo2': spO2,
-      //   'Pulse_Frequency': pulse,
-      // });
-      // widget.currentValue = {
-      //   'Spo2': spO2,
-      //   'Pulse_Frequency': pulse,
-      // };
+      controller.diagnosisDataValue['SpO2'] = {
+        'Pulse_Frequency': pulse,
+        'Spo2': spO2
+      };
       _isConnect = false;
-      // disconnect();
     });
   }
 
@@ -130,19 +142,13 @@ class _ExamBloodOxygenState extends State<BloodOxygen> {
             content: Column(
           mainAxisAlignment: MainAxisAlignment.start,
           children: [
-            const SizedBox(
-              height: 46,
-            ),
-            _SideBar(
+            SideBar(
               title: '血氧饱和度',
               value: spO2,
               unit: '%',
             ),
             const Divider(indent: 30),
-            const SizedBox(
-              height: 32,
-            ),
-            _SideBar(
+            SideBar(
               title: '脉率',
               value: pulse,
               unit: 'bpm',
@@ -163,65 +169,3 @@ class _ExamBloodOxygenState extends State<BloodOxygen> {
     );
   }
 }
-
-class _SideBar extends StatelessWidget {
-  final String title;
-  final String value;
-  final String unit;
-
-  const _SideBar({
-    required this.title,
-    required this.value,
-    required this.unit,
-  });
-
-  @override
-  Widget build(BuildContext context) {
-    return Row(
-      mainAxisAlignment: MainAxisAlignment.spaceBetween,
-      crossAxisAlignment: CrossAxisAlignment.start,
-      children: [
-        Container(
-          padding: const EdgeInsets.symmetric(horizontal: 30),
-          child: Text(
-            title,
-            style: const TextStyle(
-              fontSize: 25,
-            ),
-          ),
-        ),
-        Container(
-          alignment: Alignment.bottomRight,
-          padding: const EdgeInsets.only(
-            bottom: 20,
-            right: 30,
-            left: 40,
-          ),
-          child: FittedBox(
-            child: Row(
-              mainAxisAlignment: MainAxisAlignment.end,
-              crossAxisAlignment: CrossAxisAlignment.end,
-              children: [
-                RichText(
-                  text: TextSpan(
-                    text: value,
-                    style: const TextStyle(
-                      fontSize: 80,
-                      color: Colors.black,
-                    ),
-                    children: [
-                      TextSpan(
-                        text: unit,
-                        style: const TextStyle(fontSize: 25),
-                      )
-                    ],
-                  ),
-                ),
-              ],
-            ),
-          ),
-        ),
-      ],
-    );
-  }
-}

+ 82 - 0
lib/pages/medical/widgets/side_bar.dart

@@ -0,0 +1,82 @@
+import 'package:flutter/material.dart';
+
+class SideBar extends StatelessWidget {
+  final String title;
+  final String value;
+  final String unit;
+  final Function? onTap;
+  final bool? hasDevice;
+
+  const SideBar({
+    super.key,
+    required this.title,
+    required this.value,
+    required this.unit,
+    this.onTap,
+    this.hasDevice = false,
+  });
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      margin: hasDevice!
+          ? const EdgeInsets.only(top: 60)
+          : const EdgeInsets.only(top: 10),
+      child: InkWell(
+        onTap: () => onTap?.call(),
+        child: Container(
+          margin: const EdgeInsets.only(top: 10),
+          padding: const EdgeInsets.symmetric(vertical: 20),
+          child: Row(
+            mainAxisAlignment: MainAxisAlignment.spaceBetween,
+            crossAxisAlignment: CrossAxisAlignment.start,
+            children: [
+              Container(
+                padding: const EdgeInsets.symmetric(
+                  horizontal: 30,
+                ),
+                child: Text(
+                  title,
+                  style: const TextStyle(
+                    fontSize: 25,
+                  ),
+                ),
+              ),
+              Container(
+                alignment: Alignment.bottomRight,
+                padding: const EdgeInsets.only(
+                  bottom: 20,
+                  right: 30,
+                  left: 40,
+                ),
+                child: FittedBox(
+                  child: Row(
+                    mainAxisAlignment: MainAxisAlignment.end,
+                    crossAxisAlignment: CrossAxisAlignment.end,
+                    children: [
+                      RichText(
+                        text: TextSpan(
+                          text: value,
+                          style: const TextStyle(
+                            fontSize: 60,
+                            color: Colors.black,
+                          ),
+                          children: [
+                            TextSpan(
+                              text: unit,
+                              style: const TextStyle(fontSize: 25),
+                            )
+                          ],
+                        ),
+                      ),
+                    ],
+                  ),
+                ),
+              ),
+            ],
+          ),
+        ),
+      ),
+    );
+  }
+}

+ 1 - 1
pubspec.yaml

@@ -49,7 +49,7 @@ dependencies:
   vnote_device_plugin:
     git:
       url: http://git.ius.plus:88/Project-VNOTE/FlutterDevicePlugin.git
-      ref: 06a14468
+      ref: 782523a8
     # path: ..\FlutterDevicePlugin
   particles_flutter: 0.1.4
   cool_dropdown: 2.1.0