Browse Source

1、新增12导心电的配对流程

guanxinyi 1 năm trước cách đây
mục cha
commit
962c57b7a5

BIN
android/app/libs/device_sdk.aar


+ 20 - 0
lib/pages/check/widgets/exam_device_connect_status/bound_fail.dart

@@ -0,0 +1,20 @@
+import 'package:flutter/material.dart';
+
+class BoundFail extends StatelessWidget {
+  const BoundFail({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return Row(
+      children: const [
+        Text(
+          '设备配对失败',
+          style: TextStyle(color: Colors.red, fontSize: 24),
+        ),
+        SizedBox(
+          width: 32,
+        ),
+      ],
+    );
+  }
+}

+ 41 - 0
lib/pages/check/widgets/exam_device_connect_status/bounding.dart

@@ -0,0 +1,41 @@
+import 'package:flutter/material.dart';
+
+class BoundingDevice extends StatelessWidget {
+  const BoundingDevice({
+    super.key,
+    this.connect,
+  });
+  final Function? connect;
+
+  @override
+  Widget build(BuildContext context) {
+    return _buildContent(context);
+  }
+
+  Widget _buildContent(BuildContext context) {
+    return Row(
+      children: [
+        Text(
+          '设备配对中',
+          style: TextStyle(color: Theme.of(context).primaryColor, fontSize: 24),
+        ),
+        const SizedBox(
+          width: 16,
+        ),
+        const SizedBox(
+          // width: 150,
+          height: 20,
+          width: 20,
+          child: CircularProgressIndicator(
+            valueColor: AlwaysStoppedAnimation(
+              Colors.blue,
+            ),
+          ),
+        ),
+        const SizedBox(
+          width: 16,
+        ),
+      ],
+    );
+  }
+}

+ 5 - 0
lib/pages/medical/models/twelve_ecg.dart

@@ -1,5 +1,10 @@
 enum TwelveEcgStatus {
+  /// 未采样
   noSampling,
+
+  /// 采样不稳定
   unstableSampling,
+
+  /// 采样已稳定
   stableSampling,
 }

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

@@ -8,4 +8,10 @@ enum WorkerStatus {
   disconnected, // 已断开
 
   unboundDevice, // 未绑定设备
+
+  boundingDevice, // 绑定设备中
+
+  boundDeviceSuccess, // 绑定设备成功
+
+  boundDeviceFail, // 绑定设备成功
 }

+ 163 - 131
lib/pages/medical/widgets/twelve_ecg.dart

@@ -61,146 +61,158 @@ class _HeartRateState extends State<TwelveHeartRate> {
   Widget build(BuildContext context) {
     return Stack(
       children: [
-        ExamCard(
-          titleText: const SizedBox(),
-          content: SizedBox(
-            height: 620,
-            // margin: const EdgeInsets.only(bottom: 10),
-            child: Column(
-              children: [
-                Row(
-                  mainAxisAlignment: MainAxisAlignment.end,
-                  children: [
-                    const Expanded(child: SizedBox()),
-                    const Text(
-                      "心率",
-                      style: TextStyle(
-                        fontSize: 24,
-                        color: Colors.black,
-                      ),
-                    ),
-                    const SizedBox(
-                      width: 10,
-                    ),
-                    Text(
-                      _heart.isEmpty ? '--' : _heart,
-                      style: const TextStyle(
-                        fontSize: 60,
-                        color: Colors.black,
-                      ),
-                    ),
-                    const Text(
-                      "  bpm",
-                      style: TextStyle(fontSize: 25),
-                    ),
-                    const SizedBox(
-                      width: 250,
-                    )
-                  ],
-                ),
-                Expanded(
-                  child: ListView(
-                    shrinkWrap: true,
-                    children: [
-                      SizedBox(
-                        height: 520,
-                        child: LayoutBuilder(builder: (context, constraints) {
-                          if (initEcgData == null) {
-                            return Container();
-                          } else {
-                            return TwelveEcgView(
-                              width: constraints.maxWidth,
-                              height: constraints.maxHeight,
-                              initData: initEcgData!,
-                              currentIndex: 0,
-                              isConclusion: _assess.isNotEmpty,
-                            );
-                          }
-                        }),
-                      ),
-                    ],
-                  ),
-                ),
-              ],
-            ),
+        _buildEcgView(),
+        DeviceStatusPosition(
+          currentTop: 24,
+          deviceStatus: EcgDeviceStatus(
+            connectStatus: connectStatus,
           ),
         ),
-        if (!isConnectFail)
-          DeviceStatusPosition(
-            currentTop: 24,
-            deviceStatus: EcgDeviceStatus(
-              connectStatus: connectStatus,
-              connectEcg: tryReconnect,
-            ),
-          )
-        else
-          _buildErrorButton(),
         if (twelveEcgStatus == TwelveEcgStatus.unstableSampling)
-          const Positioned(
-            left: 20,
-            top: 24,
-            child: Text(
-              '波形正在稳定中',
-              style: TextStyle(fontSize: 24, color: Colors.blue),
-            ),
-          ),
+          _buildUnstableSampling(),
         if (twelveEcgStatus == TwelveEcgStatus.stableSampling)
-          Positioned(
-            left: 20,
-            top: 24,
-            child: Row(
-              children: const [
-                CountdownPage(
-                  seconds: 30,
+          _buildCountdownPage(),
+        _buildOperateButton(),
+      ],
+    );
+  }
+
+  Widget _buildEcgView() {
+    return ExamCard(
+      titleText: const SizedBox(),
+      content: SizedBox(
+        height: 620,
+        // margin: const EdgeInsets.only(bottom: 10),
+        child: Column(
+          children: [
+            Row(
+              mainAxisAlignment: MainAxisAlignment.end,
+              children: [
+                const Expanded(child: SizedBox()),
+                const Text(
+                  "心率",
+                  style: TextStyle(
+                    fontSize: 24,
+                    color: Colors.black,
+                  ),
                 ),
+                const SizedBox(
+                  width: 10,
+                ),
+                Text(
+                  _heart.isEmpty ? '--' : _heart,
+                  style: const TextStyle(
+                    fontSize: 60,
+                    color: Colors.black,
+                  ),
+                ),
+                const Text(
+                  "  bpm",
+                  style: TextStyle(fontSize: 25),
+                ),
+                const SizedBox(
+                  width: 250,
+                )
               ],
             ),
+            Expanded(
+              child: ListView(
+                shrinkWrap: true,
+                children: [
+                  SizedBox(
+                    height: 520,
+                    child: LayoutBuilder(builder: (context, constraints) {
+                      if (initEcgData == null) {
+                        return Container();
+                      } else {
+                        return TwelveEcgView(
+                          width: constraints.maxWidth,
+                          height: constraints.maxHeight,
+                          initData: initEcgData!,
+                          currentIndex: 0,
+                          isConclusion: _assess.isNotEmpty,
+                        );
+                      }
+                    }),
+                  ),
+                ],
+              ),
+            ),
+          ],
+        ),
+      ),
+    );
+  }
+
+  Widget _buildUnstableSampling() {
+    return const Positioned(
+      left: 20,
+      top: 24,
+      child: Text(
+        '波形正在稳定中',
+        style: TextStyle(fontSize: 24, color: Colors.blue),
+      ),
+    );
+  }
+
+  Widget _buildCountdownPage() {
+    return Positioned(
+      left: 20,
+      top: 24,
+      child: Row(
+        children: const [
+          CountdownPage(
+            seconds: 30,
           ),
-        Positioned(
-          left: 24,
-          top: 24,
-          child: Row(
-            children: [
-              if (twelveEcgStatus == TwelveEcgStatus.noSampling &&
-                  (connectStatus == WorkerStatus.connectionFailed ||
-                      connectStatus == WorkerStatus.disconnected)) ...[
-                SizedBox(
-                  width: 150,
-                  height: 50,
-                  child: VButton(
-                    onTap: () => connectStatus == WorkerStatus.connecting
-                        ? null
-                        : connect(),
-                    child: const Center(
-                      child: Text(
-                        "采样",
-                        style: TextStyle(fontSize: 24),
-                      ),
-                    ),
+        ],
+      ),
+    );
+  }
+
+  Widget _buildOperateButton() {
+    return Positioned(
+      left: 24,
+      top: 24,
+      child: Row(
+        children: [
+          if (twelveEcgStatus == TwelveEcgStatus.noSampling &&
+              (connectStatus == WorkerStatus.connectionFailed ||
+                  connectStatus == WorkerStatus.disconnected ||
+                  connectStatus == WorkerStatus.boundDeviceFail)) ...[
+            SizedBox(
+              width: 150,
+              height: 50,
+              child: VButton(
+                onTap: () =>
+                    connectStatus == WorkerStatus.connecting ? null : connect(),
+                child: const Center(
+                  child: Text(
+                    "采样",
+                    style: TextStyle(fontSize: 24),
                   ),
                 ),
-                const SizedBox(
-                  width: 20,
-                ),
-              ],
-              if (_assess.isNotEmpty)
-                SizedBox(
-                  width: 150,
-                  height: 50,
-                  child: VButton(
-                    onTap: () => _openConclusion(),
-                    child: const Center(
-                      child: Text(
-                        "查看结果",
-                        style: TextStyle(fontSize: 24),
-                      ),
-                    ),
+              ),
+            ),
+            const SizedBox(
+              width: 20,
+            ),
+          ],
+          if (_assess.isNotEmpty)
+            SizedBox(
+              width: 150,
+              height: 50,
+              child: VButton(
+                onTap: () => _openConclusion(),
+                child: const Center(
+                  child: Text(
+                    "查看结果",
+                    style: TextStyle(fontSize: 24),
                   ),
                 ),
-            ],
-          ),
-        ),
-      ],
+              ),
+            ),
+        ],
+      ),
     );
   }
 
@@ -236,9 +248,9 @@ class _HeartRateState extends State<TwelveHeartRate> {
   }
 
   Future<void> connect() async {
-    await worker.connect();
     connectStatus = WorkerStatus.connecting;
     isConnectFail = false;
+    await worker.connect();
     setState(() {});
   }
 
@@ -302,6 +314,9 @@ class _HeartRateState extends State<TwelveHeartRate> {
   }
 
   void loadListeners() {
+    worker.boundingEvent.addListener(_onBounding);
+    worker.boundSuccessEvent.addListener(_onBoundSuccess);
+    worker.boundFailEvent.addListener(_onBoundFail);
     worker.connectErrorEvent.addListener(_onConnectFail);
     worker.connectedEvent.addListener(_onConnectSuccess);
     worker.disconnectedEvent.addListener(_onDisconnected);
@@ -312,6 +327,9 @@ class _HeartRateState extends State<TwelveHeartRate> {
   }
 
   void releaseListeners() {
+    worker.boundingEvent.removeListener(_onBounding);
+    worker.boundSuccessEvent.removeListener(_onBoundSuccess);
+    worker.boundFailEvent.removeListener(_onBoundFail);
     worker.connectErrorEvent.removeListener(_onConnectFail);
     worker.connectedEvent.removeListener(_onConnectSuccess);
     worker.disconnectedEvent.removeListener(_onDisconnected);
@@ -370,7 +388,7 @@ class _HeartRateState extends State<TwelveHeartRate> {
     setState(() {});
   }
 
-  void _onSaveSuccess(semder, e) async {
+  void _onSaveSuccess(sender, e) async {
     if (e) {
       PromptBox.toast("采样结束");
       twelveEcgStatus = TwelveEcgStatus.noSampling;
@@ -378,6 +396,21 @@ class _HeartRateState extends State<TwelveHeartRate> {
     setState(() {});
   }
 
+  void _onBounding(sender, e) {
+    connectStatus = WorkerStatus.boundingDevice;
+    setState(() {});
+  }
+
+  void _onBoundSuccess(sender, e) {
+    tryReconnect();
+    setState(() {});
+  }
+
+  void _onBoundFail(sender, e) {
+    connectStatus = WorkerStatus.boundDeviceFail;
+    setState(() {});
+  }
+
   void _onConnectSuccess(sender, e) {
     logger.i('_HeartRateState ${worker.mac}, 设备连接成功');
     twelveEcgStatus = TwelveEcgStatus.unstableSampling;
@@ -386,7 +419,6 @@ class _HeartRateState extends State<TwelveHeartRate> {
     connectStatus = WorkerStatus.connected;
     resetEcgView();
     _assess = "";
-
     setState(() {});
   }
 

+ 14 - 2
lib/pages/medical/widgets/twelve_ecg_view/widgets/ecg_device_status.dart

@@ -1,4 +1,6 @@
 import 'package:flutter/material.dart';
+import 'package:vitalapp/pages/check/widgets/exam_device_connect_status/bound_fail.dart';
+import 'package:vitalapp/pages/check/widgets/exam_device_connect_status/bounding.dart';
 import 'package:vitalapp/pages/check/widgets/exam_device_connect_status/connect.dart';
 import 'package:vitalapp/pages/check/widgets/exam_device_connect_status/connect_success.dart';
 import 'package:vitalapp/pages/check/widgets/exam_device_connect_status/connect_unbound_device.dart';
@@ -9,10 +11,8 @@ class EcgDeviceStatus extends StatefulWidget {
   const EcgDeviceStatus({
     super.key,
     required this.connectStatus,
-    this.connectEcg,
   });
   final WorkerStatus connectStatus;
-  final Function? connectEcg;
   @override
   State<StatefulWidget> createState() {
     return _EcgDeviceStatusState();
@@ -72,6 +72,18 @@ class _EcgDeviceStatusState extends State<EcgDeviceStatus> {
         return _buildColumn(
           const UnboundDevice(),
         );
+      case WorkerStatus.boundingDevice:
+        return _buildColumn(
+          const BoundingDevice(),
+        );
+      case WorkerStatus.boundDeviceSuccess:
+        return _buildColumn(
+          const UnboundDevice(),
+        );
+      case WorkerStatus.boundDeviceFail:
+        return _buildColumn(
+          const BoundFail(),
+        );
       default:
         return const SizedBox();
     }

+ 1 - 1
pubspec.yaml

@@ -51,7 +51,7 @@ dependencies:
   vnote_device_plugin:
     git:
       url: http://git.ius.plus/Project-Vital/FlutterDevicePlugin.git
-      ref: e20aef0
+      ref: "8c9e3fd"
     # path: ..\VitalFlutterDevicePlugin
     # path: ..\FlutterDevicePlugin
   vital_local_database: