소스 검색

接入心电大列表仓库

loki.wu 9 달 전
부모
커밋
49d80f0e42

+ 46 - 0
lib/managers/ecg_manager.dart

@@ -0,0 +1,46 @@
+import 'package:fis_common/logger/logger.dart';
+import 'package:fis_jsonrpc/rpc.dart';
+import 'package:get/get.dart';
+import 'package:vitalapp/architecture/utils/prompt_box.dart';
+import 'package:vitalapp/pages/ecg/ecg_result_view.dart';
+import 'package:vitalapp/pages/medical/controller.dart';
+import 'package:vitalapp/rpc.dart';
+import 'package:vitalapp/store/store.dart';
+
+import 'interfaces/base_manager.dart';
+import 'interfaces/ecg.dart';
+
+class EcgManager extends BaseManager implements IEcgManager {
+  //编辑Ecg结果
+  @override
+  Future<void> editEcgResult(String code) async {
+    ElectrocardiogramRecord? recordInfo =
+        await getElectrocardiogramRecord(code);
+    if (recordInfo == null) {
+      PromptBox.toast('获取心电结果失败');
+      return;
+    }
+    if (!Get.isRegistered<MedicalController>()) {
+      Get.lazyPut(() => MedicalController());
+    }
+    Get.to(EcgResultView(recordInfo));
+  }
+
+  ///获取心电记录详情
+  @override
+  Future<ElectrocardiogramRecord?> getElectrocardiogramRecord(
+      String code) async {
+    ElectrocardiogramRecord? result;
+    try {
+      result = await rpc.vitalElectrocardiogram.getElectrocardiogramRecordAsync(
+        GetElectrocardiogramRecordRequest(
+          code: code,
+          token: Store.user.token,
+        ),
+      );
+    } catch (e) {
+      logger.e('EcgManager getElectrocardiogramRecord ex:', e);
+    }
+    return result;
+  }
+}

+ 3 - 0
lib/managers/index.dart

@@ -24,6 +24,7 @@ import 'package:vitalapp/managers/interfaces/device.dart';
 import 'package:vitalapp/managers/interfaces/diagnosis.dart';
 import 'package:vitalapp/managers/interfaces/dictionary.dart';
 import 'package:vitalapp/managers/interfaces/doctor.dart';
+import 'package:vitalapp/managers/interfaces/ecg.dart';
 import 'package:vitalapp/managers/interfaces/entry.dart';
 import 'package:vitalapp/managers/interfaces/exam.dart';
 import 'package:vitalapp/managers/interfaces/follow_up.dart';
@@ -54,6 +55,7 @@ import 'application.dart';
 import 'appointment.dart';
 import 'cache.dart';
 import 'data_convert.dart';
+import 'ecg_manager.dart';
 import 'interfaces/application.dart';
 import 'interfaces/appointment.dart';
 import 'interfaces/base.dart';
@@ -84,6 +86,7 @@ abstract class ManagerCenter {
     Get.put<IPatientManager>(PatientManager());
     Get.put<IRecordDataCacheManager>(RecordDataCacheManager());
     Get.put<IDoctorManager>(DoctorManager());
+    Get.put<IEcgManager>(EcgManager());
     Get.put<IServicePackManager>(ServicePackManager());
     Get.put<IContractTemplateManager>(ContractTemplateManager());
     Get.put<IContractManager>(ContractManager());

+ 9 - 0
lib/managers/interfaces/ecg.dart

@@ -0,0 +1,9 @@
+import 'package:fis_jsonrpc/rpc.dart';
+
+import 'base.dart';
+
+abstract class IEcgManager implements IManager {
+  void editEcgResult(String code);
+
+  Future<ElectrocardiogramRecord?> getElectrocardiogramRecord(String code);
+}

+ 324 - 0
lib/pages/ecg/ecg_result_view.dart

@@ -0,0 +1,324 @@
+import 'dart:convert';
+import 'package:ecg_list_view/ecg_list/widgets/conclusion_dialog.dart';
+import 'package:fis_common/index.dart';
+import 'package:http/http.dart' as http;
+import 'package:fis_jsonrpc/rpc.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:vitalapp/components/appbar.dart';
+import 'package:vitalapp/components/no_data_view.dart';
+import 'package:vitalapp/pages/medical/widgets/twelve_ecg_view/view.dart';
+import 'package:vnote_device_plugin/models/exams/twelve_heart.dart';
+
+class EcgResultView extends StatefulWidget {
+  final ElectrocardiogramRecord recordInfo;
+  EcgResultView(this.recordInfo);
+  @override
+  State<StatefulWidget> createState() {
+    return EcgResultViewState();
+  }
+}
+
+class EcgResultViewState extends State<EcgResultView> {
+  TwelveHeartResultEntity? resultConclusion;
+  final _promptWordsController = TextEditingController();
+  final _hrController = TextEditingController();
+  final _qRSAxisController = TextEditingController();
+  final _pRController = TextEditingController();
+  final _qTDurController = TextEditingController();
+  final _qTCDurController = TextEditingController();
+  final _pAxisController = TextEditingController();
+  final _qRSController = TextEditingController();
+  final _tAxisController = TextEditingController();
+  final _pDurController = TextEditingController();
+  final _tDurController = TextEditingController();
+
+  /// 初始时的心电初始数据
+  List<int> _initEcgDatas = [];
+
+  @override
+  void initState() {
+    String examData = widget.recordInfo.examData ?? '';
+    if (examData.isNotEmpty) {
+      Map<String, dynamic> examDatas = jsonDecode(examData);
+      if (examDatas.containsKey("ECG_POINT12")) {
+        String exgPoint12Url = examDatas["ECG_POINT12"].toString();
+        if (exgPoint12Url.startsWith('https://') ||
+            exgPoint12Url.startsWith("http://")) {
+          http.get(Uri.parse(exgPoint12Url)).then((value) {
+            var initEcgData = jsonDecode(value.body).cast<int>();
+            setState(() {
+              _initEcgDatas = initEcgData;
+            });
+          });
+        }
+      }
+      if (examDatas.containsKey("Analyse12")) {
+        String analyse12 = examDatas["Analyse12"].toString();
+        if (analyse12.isNotEmpty) {
+          resultConclusion =
+              TwelveHeartResultEntity.fromJson(jsonDecode(analyse12));
+          if (resultConclusion != null) {
+            _promptWordsController.text = resultConclusion!.advice;
+            _qRSAxisController.text = resultConclusion!.QRSAxis;
+            _pRController.text = resultConclusion!.PR;
+            _qTDurController.text = resultConclusion!.QTDur;
+            _qTCDurController.text = resultConclusion!.QTCDur;
+            _pAxisController.text = resultConclusion!.PAxis;
+            _qRSController.text = resultConclusion!.QRSDur;
+            _tAxisController.text = resultConclusion!.TAxis;
+            _pDurController.text = resultConclusion!.PDur;
+            _tDurController.text = resultConclusion!.TDur;
+          }
+        }
+      }
+    }
+    super.initState();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    final double ecgViewWidth = 950;
+    final double ecgViewHeight = 550;
+    return Scaffold(
+      resizeToAvoidBottomInset: false, // 防止内容自动调整以避免被键盘遮挡
+      appBar: VAppBar(
+        titleText: "体检心电",
+        actions: [
+          Container(
+            margin: EdgeInsets.only(right: 10),
+            child: Text(
+              widget.recordInfo.patientName ?? '',
+              style: TextStyle(color: Colors.white, fontSize: 24),
+            ),
+          ),
+        ],
+      ),
+      body: widget.recordInfo.examData.isNullOrEmpty
+          ? VNoDataView()
+          : Container(
+              color: Colors.white,
+              child: Row(
+                children: [
+                  SizedBox(width: 5),
+                  if (_initEcgDatas.isNotEmpty) ...[
+                    Expanded(
+                      flex: 8,
+                      child: Column(
+                        crossAxisAlignment: CrossAxisAlignment.start,
+                        children: [
+                          Expanded(
+                            child: _buildHeader(),
+                          ),
+                          TwelveEcgView(
+                            width: ecgViewWidth,
+                            height: ecgViewHeight,
+                            initData: _initEcgDatas,
+                            currentIndex: 0,
+                            isConclusion: true,
+                          ),
+                          Container(
+                            margin: EdgeInsets.only(left: 5),
+                            height: 25,
+                            child: Text("点击图像可放大查看"),
+                          ),
+                        ],
+                      ),
+                    ),
+                  ] else ...[
+                    SizedBox(
+                      width: ecgViewWidth,
+                    ),
+                  ],
+                  Expanded(
+                    flex: 3,
+                    child: _buildAnalysisResults(),
+                  ),
+                ],
+              ),
+            ),
+    );
+  }
+
+  Widget _buildHeader() {
+    String heartRate12 = "";
+    String examData = widget.recordInfo.examData ?? '';
+    if (examData.isNotEmpty) {
+      Map<String, dynamic> examDatas = jsonDecode(examData);
+      if (examDatas.containsKey("HEART12")) {
+        heartRate12 = examDatas["HEART12"].toString();
+        _hrController.text = heartRate12;
+      }
+    }
+    final gapHeight = 15.0;
+    return Row(
+      mainAxisAlignment: MainAxisAlignment.spaceBetween,
+      children: [
+        Container(
+          width: 650,
+          child: Column(
+            crossAxisAlignment: CrossAxisAlignment.start,
+            children: [
+              SizedBox(height: gapHeight),
+              Row(
+                children: [
+                  SizedBox(width: 15),
+                  _buildKeyValue("走速:", "25 mm/s"),
+                  SizedBox(width: 15),
+                  _buildKeyValue("增益:", "5 mm/mV"),
+                ],
+              ),
+              SizedBox(height: gapHeight),
+              Row(
+                children: [
+                  SizedBox(width: 15),
+                  _buildKeyValue("基线滤波:", "1.6-2.0 Hz"),
+                  SizedBox(width: 15),
+                  _buildKeyValue("肌电滤波:", "53 Hz"),
+                  SizedBox(width: 15),
+                  _buildKeyValue("AC", ""),
+                  SizedBox(width: 15),
+                  _buildKeyValue("工频滤波:", "50 Hz"),
+                  SizedBox(width: 15),
+                ],
+              ),
+              SizedBox(height: gapHeight),
+              Row(
+                children: [
+                  SizedBox(width: 15),
+                  _buildKeyValue(
+                      "RV5/SV1:", "${resultConclusion?.Rv5_Sv1_1} Hz"),
+                  SizedBox(width: 20),
+                  _buildKeyValue(
+                      "RV5+SV1:", "${resultConclusion?.Rv5_Sv1_2} Hz"),
+                  SizedBox(width: 15),
+                ],
+              ),
+            ],
+          ),
+        ),
+        //Expanded(child: SizedBox.shrink()),
+        Column(
+          crossAxisAlignment: CrossAxisAlignment.end,
+          children: [
+            Text(
+              "诊断提示:",
+              style: TextStyle(fontSize: 20),
+            ),
+            Expanded(child: SizedBox()),
+            ElevatedButton(
+              onPressed: () {},
+              child: Text("词条选择"),
+            ),
+            SizedBox(height: 10)
+          ],
+        ),
+      ],
+    );
+  }
+
+  Widget _buildKeyValue(String key, String value) {
+    return Row(
+      mainAxisAlignment: MainAxisAlignment.spaceBetween,
+      children: [
+        Text(
+          key,
+          style: TextStyle(fontSize: 20),
+        ),
+        Text(
+          value,
+          style: const TextStyle(fontSize: 20),
+        ),
+      ],
+    );
+  }
+
+  Widget _buildKeyInput(
+      String key, TextEditingController controller, String? unit) {
+    final textStyle = const TextStyle(fontSize: 20);
+    return Container(
+      margin: EdgeInsets.symmetric(vertical: 2),
+      child: Row(
+        mainAxisAlignment: MainAxisAlignment.spaceBetween,
+        children: [
+          SizedBox(
+            width: 110,
+            child: Text(
+              key,
+              style: textStyle,
+            ),
+          ),
+          Expanded(
+            child: TextField(
+              decoration: InputDecoration(
+                contentPadding: EdgeInsets.only(
+                    top: 2.0, bottom: 2.0, left: 10, right: 10), // 设置上下内边距
+                border: OutlineInputBorder(
+                  borderSide:
+                      BorderSide(color: Colors.black, width: 1.0), // 设置边框颜色和宽度
+                  borderRadius:
+                      BorderRadius.all(Radius.circular(8.0)), // 可选:设置边框圆角
+                ),
+              ),
+              controller: controller,
+              style: textStyle,
+            ),
+          ),
+          if (unit.isNotNullOrEmpty) ...[
+            SizedBox(
+              width: 50,
+              child: Text(
+                unit!,
+                style: textStyle,
+              ),
+            ),
+          ],
+        ],
+      ),
+    );
+  }
+
+  Widget _buildAnalysisResults() {
+    if (resultConclusion == null) {
+      return SizedBox();
+    }
+    return Container(
+      margin: EdgeInsets.symmetric(horizontal: 10),
+      child: Column(
+        children: [
+          SizedBox(
+            height: 5,
+          ),
+          Expanded(child: _buildPromptWords()),
+          _buildKeyInput("心率:", _hrController, " bpm"),
+          _buildKeyInput("P时限:", _pDurController, " ms"),
+          _buildKeyInput("QRS时限:", _qRSController, " ms"),
+          _buildKeyInput("T时限:", _tDurController, " ms"),
+          _buildKeyInput("PR间期:", _pRController, " ms"),
+          _buildKeyInput("QT间期:", _qTDurController, " ms"),
+          _buildKeyInput("QTc间期:", _qTCDurController, " ms"),
+          _buildKeyInput("P轴:", _pAxisController, " °"),
+          _buildKeyInput("QRS轴:", _qRSController, " °"),
+          _buildKeyInput("T轴:", _tAxisController, " °"),
+        ],
+      ),
+    );
+  }
+
+  Widget _buildPromptWords() {
+    return SizedBox(
+      child: TextField(
+        controller: _promptWordsController,
+        maxLines: 5,
+        decoration: InputDecoration(
+          hintText: '请输入提示词',
+          border: OutlineInputBorder(
+            borderSide:
+                BorderSide(color: Colors.black, width: 1.0), // 设置边框颜色和宽度
+            borderRadius: BorderRadius.all(Radius.circular(8.0)), // 可选:设置边框圆角
+          ),
+        ),
+      ),
+    );
+  }
+}

+ 0 - 5
lib/pages/image_report_inner_view/widgets/report_cards_view.dart

@@ -55,11 +55,6 @@ class FReportCardsViewState extends FState<FReportCardsView> {
         businessParent: widget,
         name: 'report preview',
         onDoubleTap: () {
-          // FIXME 没用到
-          // var reportUrls = report.reportPreviewList
-          //     ?.where((element) => element.fileType == UploadFileTypeEnum.JPG)
-          //     .map((e) => e.fileToken ?? '')
-          //     .toList();
           _reportManager.openReportPreviewPage(
             controller.recordCode,
             controller.isReferral ? controller.recordCode : "",

+ 0 - 2
lib/pages/splash/view.dart

@@ -88,9 +88,7 @@ class _ImageAnimationState extends State<ImageAnimation>
   }
 
   void checkForConnected() async {
-    // 这里替换成你的接口调用逻辑
     bool isCallSuccess = await callServer();
-
     if (isCallSuccess) {
       logger.i('call server success,times:${_callServerTimes}');
       // 如果接口调用成功,取消timer并且跳转到登录页面

+ 20 - 1
lib/routes/routes.dart

@@ -1,4 +1,7 @@
+import 'package:ecg_list_view/rpc/rpc_bridge.dart';
+import 'package:flutter/foundation.dart';
 import 'package:get/get.dart';
+import 'package:vitalapp/managers/interfaces/ecg.dart';
 import 'package:vitalapp/pages/admin/controller.dart';
 import 'package:vitalapp/pages/admin/view.dart';
 import 'package:vitalapp/pages/check/maternal_health_management/controller.dart';
@@ -88,6 +91,10 @@ import 'package:vitalapp/pages/patient/list/controller.dart';
 import 'package:vitalapp/pages/patient/list/view.dart';
 import 'package:vitalapp/pages/splash/controller.dart';
 import 'package:vitalapp/pages/splash/view.dart';
+import 'package:ecg_list_view/ecg_list/view.dart';
+import 'package:ecg_list_view/ecg_list/controller.dart';
+import 'package:vitalapp/rpc.dart';
+import 'package:vitalapp/store/store.dart';
 
 import '../pages/contract/contract_record_html/view.dart';
 
@@ -500,14 +507,26 @@ class Routes {
     ),
     VRouteSetting(
       '/electrocardiogram',
-      () => const HeartCheckNew(),
+      () => kIsWeb
+          ? HeartCheckNew()
+          : EcgListPage(
+              onEdit: (v) {
+                Get.find<IEcgManager>().editEcgResult(v);
+              },
+            ),
       binding: BindingsBuilder(
         () {
+          if (Get.isRegistered<RPCBridge>()) {
+            Get.delete<RPCBridge>();
+          }
+          Get.put(RPCBridge(rpc, Store.user.token ?? ''));
           if (!Get.isRegistered<MedicalController>()) {
             Get.lazyPut(() => MedicalController());
           }
+
           Get.put(PatientDetailController());
           Get.put(HealthCheckListController());
+          Get.put(EcgListController());
           Get.put(HeartCheckListController());
         },
       ),

+ 13 - 4
pubspec.lock

@@ -321,6 +321,15 @@ packages:
       url: "https://pub.flutter-io.cn"
     source: hosted
     version: "4.0.6"
+  ecg_list_view:
+    dependency: "direct main"
+    description:
+      path: "."
+      ref: "0b35ab63cab3f9b30d8d98503e01874843903917"
+      resolved-ref: "0b35ab63cab3f9b30d8d98503e01874843903917"
+      url: "http://git.ius.plus/loki.wu/ecg_list_view.git"
+    source: git
+    version: "1.0.0+1"
   encrypt:
     dependency: transitive
     description:
@@ -415,8 +424,8 @@ packages:
     dependency: "direct main"
     description:
       path: "."
-      ref: f72045636ceb7c5430003eb9401652d9c843acc8
-      resolved-ref: f72045636ceb7c5430003eb9401652d9c843acc8
+      ref: "8ca4c53e2c057ff5631163403f19a5491ddc16ec"
+      resolved-ref: "8ca4c53e2c057ff5631163403f19a5491ddc16ec"
       url: "http://git.ius.plus:88/Project-Wing/fis_lib_jsonrpc.git"
     source: git
     version: "0.0.1"
@@ -1607,8 +1616,8 @@ packages:
     dependency: "direct main"
     description:
       path: "."
-      ref: d0ac3d5
-      resolved-ref: d0ac3d59ccdb30b0657df7ed5c2e4d0073b2f105
+      ref: "5f6d47cb2b225042d3b25d85e5da2676c0df3737"
+      resolved-ref: "5f6d47cb2b225042d3b25d85e5da2676c0df3737"
       url: "http://git.ius.plus/Project-Vital/FlutterDevicePlugin.git"
     source: git
     version: "0.0.1"

+ 11 - 3
pubspec.yaml

@@ -52,7 +52,7 @@ dependencies:
   vnote_device_plugin:
     git:
       url: http://git.ius.plus/Project-Vital/FlutterDevicePlugin.git
-      ref: d0ac3d5
+      ref: 5f6d47cb2b225042d3b25d85e5da2676c0df3737
   vital_local_database:
     git:
       url: http://git.ius.plus:88/Project-Vital/FlutterLocalDB.git
@@ -87,6 +87,10 @@ dependencies:
     git:
       url: http://git.ius.plus:88/Project-Wing/fis_lib_business_components.git
       ref: f8f5092
+  ecg_list_view:
+    git:
+      url: http://git.ius.plus/loki.wu/ecg_list_view.git
+      ref: 8ac15b110f6d327461201d4b2e3489e4de7ed358
   #   path: ..\FlutterSmartScanPlugin
   # fis_ui:
   #   git:
@@ -163,7 +167,7 @@ dependency_overrides:
   fis_jsonrpc:
     git:
       url: http://git.ius.plus:88/Project-Wing/fis_lib_jsonrpc.git
-      ref: f72045636ceb7c5430003eb9401652d9c843acc8
+      ref: 8ca4c53e2c057ff5631163403f19a5491ddc16ec
     #path: ../fis_lib_jsonrpc
   fis_theme:
     git:
@@ -208,7 +212,11 @@ dependency_overrides:
     git:
       url: http://git.ius.plus/Project-Wing/fis_lib_print.git
       ref: d23341a
-
+  ecg_list_view:
+    git:
+      url: http://git.ius.plus/loki.wu/ecg_list_view.git
+      ref: 0b35ab63cab3f9b30d8d98503e01874843903917
+    #path: ../ecg_list_view
 dev_dependencies:
   flutter_test:
     sdk: flutter