Ver código fonte

Merge branch 'master' of http://git.ius.plus/Project-Vital/VitalApp

Melon 1 ano atrás
pai
commit
a3131f4e1c

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 - 152
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);
@@ -333,27 +351,6 @@ class _HeartRateState extends State<TwelveHeartRate> {
     ecgViewController.updateTwelveEcgView();
   }
 
-  /// 需要封装一下
-  Widget _buildErrorButton() {
-    return DeviceStatusPosition(
-      deviceStatus: Row(
-        children: [
-          const Text(
-            '请确认设备是否启动',
-            style: TextStyle(fontSize: 24, color: Colors.red),
-          ),
-          IconButton(
-            onPressed: () {
-              tryReconnect();
-            },
-            icon: const Icon(Icons.refresh),
-            iconSize: 32,
-          ),
-        ],
-      ),
-    );
-  }
-
   void _onConnectFail(sender, e) async {
     logger.i("设备连接失败:${worker.mac}");
     connectStatus = WorkerStatus.connectionFailed;
@@ -370,7 +367,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 +375,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 +398,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();
     }

+ 18 - 3
lib/pages/medical/widgets/twelve_ecg_view/widgets/ecg_painter_for_all.dart

@@ -10,7 +10,7 @@ class EcgPainterForAll extends CustomPainter {
   final int yGridNumsPerMv; // 多少格是一毫伏特
 
   /// 纵坐标最大值
-  final List<double> yMaxList;
+  List<double> yMaxList;
 
   EcgPainterForAll({
     required this.allPoints,
@@ -29,12 +29,27 @@ class EcgPainterForAll extends CustomPainter {
 
   @override
   void paint(Canvas canvas, Size size) {
+    yMaxList = [
+      1500,
+      7500,
+      3000,
+      8000,
+      4000,
+      12000,
+      18000,
+      18000,
+      18000,
+      18000,
+      18000,
+      18000,
+    ];
     if (allPoints.isNotEmpty) {
       List<List<int>> ecgList = separateLines(allPoints);
       for (int i = 0; i < 12; i++) {
         double y = (size.height / 6 * (i + 0.5));
 
         Size currentSize = Size(size.width, y);
+        print("当前:$i : ${yMaxList[i]}");
         drawPoints(
           canvas,
           currentSize,
@@ -48,7 +63,7 @@ class EcgPainterForAll extends CustomPainter {
       final paint = Paint()
         ..color = Colors.green
         ..style = PaintingStyle.stroke
-        ..strokeWidth = 3.0;
+        ..strokeWidth = 2.0;
       final double xGridSize = size.width / xDataCount;
       final startX = allPoints.length * xGridSize;
       final startY = size.height / 2;
@@ -69,7 +84,7 @@ class EcgPainterForAll extends CustomPainter {
       ..color = Colors.green
       ..style = PaintingStyle.stroke
       ..strokeWidth = 2.0;
-
+    print("11111:$yMax");
     final double xGridSize = size.width / xDataCount;
     final double yScale = size.height / 2 / yMax;
 

+ 1 - 1
lib/pages/medical/widgets/twelve_ecg_view/widgets/full_screen_ecg_data_dialog.dart

@@ -48,7 +48,7 @@ class FullScreenEcgDataDialog extends GetView<TwelveEcgViewController> {
                       yMaxList: controller.yMaxList,
                     ),
                     painter: GridBackgroundPainterForAll(),
-                    size: const Size(5000, 200),
+                    size: const Size(3000, 200),
                   ),
                 ),
               ),

+ 0 - 43
lib/pages/medical/widgets/twelve_ecg_view/widgets/grid_background_painter_for_all.dart

@@ -137,49 +137,6 @@ class GridBackgroundPainterForAll extends CustomPainter {
         );
       }
     }
-
-    /// 绘制电势差标识
-    const tagStartGridX = 5;
-    const tagStartGridY = -30;
-    final tagPointA =
-        Offset(xGridSize * tagStartGridX, centerY + yGridSize * tagStartGridY);
-    final tagPointB = Offset(
-        xGridSize * (tagStartGridX + 1), centerY + yGridSize * tagStartGridY);
-    final tagPointC = Offset(xGridSize * (tagStartGridX + 1),
-        centerY + yGridSize * (tagStartGridY - 5));
-    final tagPointD = Offset(xGridSize * (tagStartGridX + 3),
-        centerY + yGridSize * (tagStartGridY - 5));
-    final tagPointE = Offset(
-        xGridSize * (tagStartGridX + 3), centerY + yGridSize * tagStartGridY);
-    final tagPointF = Offset(
-        xGridSize * (tagStartGridX + 4), centerY + yGridSize * tagStartGridY);
-
-    final tagPaint = Paint()
-      ..color = const Color.fromARGB(255, 99, 99, 99)
-      ..style = PaintingStyle.stroke
-      ..strokeWidth = 1.0;
-    canvas.drawLine(tagPointA, tagPointB, tagPaint);
-    canvas.drawLine(tagPointB, tagPointC, tagPaint);
-    canvas.drawLine(tagPointC, tagPointD, tagPaint);
-    canvas.drawLine(tagPointD, tagPointE, tagPaint);
-    canvas.drawLine(tagPointE, tagPointF, tagPaint);
-    final textPainter = TextPainter(
-      text: TextSpan(
-        text: '1mV',
-        style: TextStyle(
-          height: 1,
-          color: const Color.fromARGB(255, 99, 99, 99),
-          fontSize: 20,
-          background: Paint()..color = Colors.white.withOpacity(0.5),
-        ),
-      ),
-      textDirection: TextDirection.ltr,
-    );
-    textPainter.layout();
-    textPainter.paint(
-      canvas,
-      Offset(tagPointA.dx - 8, tagPointA.dy + 10),
-    );
   }
 
   @override

+ 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: