Prechádzať zdrojové kódy

update(measure): 子窗口新开测量页优化为【局部刷新】 #0009417 Review by baka

gavin.chen 2 rokov pred
rodič
commit
be186616ca

+ 5 - 1
lib/process/workspace/measure_data_controller.dart

@@ -34,6 +34,9 @@ abstract class IMeasureDataController {
   late FEventHandler<List<ItemMeta>> curItemMetaListChanged;
   late FEventHandler<List<String>> getCommentsListChanged;
 
+  /// 切换至另一个病人的图像集
+  late FEventHandler<Map<String, String>> curMeasureDataChanged;
+
   /// 该图像下面的应用
   List<ItemMeta> get itemMetaList;
   set itemMetaList(List<ItemMeta> value);
@@ -157,7 +160,8 @@ class MeasureDataController implements IMeasureDataController {
   var curItemMetaListChanged = FEventHandler<List<ItemMeta>>();
   @override
   var getCommentsListChanged = FEventHandler<List<String>>();
-
+  @override
+  var curMeasureDataChanged = FEventHandler<Map<String, String>>();
   @override
   List<ItemMeta> get curItemMetaList => _curItemMetaList;
 

+ 12 - 0
lib/process/workspace/measure_handler.dart

@@ -72,6 +72,12 @@ abstract class IMeasureHandler {
   /// 图片加载loadding
   late FEventHandler<bool> onChangeImageLoaded;
 
+  /// 通过 remedicalCode 切换图片
+  late FEventHandler<String> changeImageByRemedicalCode;
+
+  /// 更新图片列表
+  late FEventHandler<List<RemedicalInfoDTO>> changeImageList;
+
   late FEventHandler<bool> onChangeFullScreenState;
 
   late FEventHandler<void> commentsLoaded;
@@ -136,6 +142,12 @@ class MeasureHandler implements IMeasureHandler {
   @override
   FEventHandler<bool> onChangeImageLoaded = FEventHandler<bool>();
 
+  @override
+  FEventHandler<String> changeImageByRemedicalCode = FEventHandler<String>();
+  @override
+  FEventHandler<List<RemedicalInfoDTO>> changeImageList =
+      FEventHandler<List<RemedicalInfoDTO>>();
+
   @override
   FEventHandler<bool> onChangeFullScreenState = FEventHandler<bool>();
 

+ 43 - 8
lib/view/measure/measure_images_bar.dart

@@ -83,7 +83,7 @@ class _MeasureImagesBarState extends State<MeasureImagesBar> {
             onLeftMoveImage,
           ),
           FExpanded(
-            child: LeftSiderImageList(
+            child: ScrollableImageList(
               scrollController: scrollController,
               globalKey: globalKey,
               remedicalList: measureData.remedicalList,
@@ -168,9 +168,9 @@ class _MeasureImagesBarState extends State<MeasureImagesBar> {
   }
 }
 
-/// 当前测量组的所有图片
-class LeftSiderImageList extends StatefulWidget implements FWidget {
-  const LeftSiderImageList({
+/// 可滑动的图片组,显示当前测量组的所有图片
+class ScrollableImageList extends StatefulWidget implements FWidget {
+  const ScrollableImageList({
     required this.scrollController,
     required this.globalKey,
     required this.remedicalList,
@@ -184,19 +184,23 @@ class LeftSiderImageList extends StatefulWidget implements FWidget {
 
   final List<RemedicalInfoDTO> remedicalList;
   @override
-  State<LeftSiderImageList> createState() => _LeftSiderImageListState();
+  State<ScrollableImageList> createState() => _ScrollableImageListState();
 }
 
-class _LeftSiderImageListState extends State<LeftSiderImageList> {
+class _ScrollableImageListState extends State<ScrollableImageList> {
   /// 当前测量的图片
   // final measureCurrentImage = Get.put(MeasureGetCurrentImage());
 
   /// 测量AI数据
   final measureData = Get.find<MeasureDataController>();
 
-  late final measureController = Get.find<MeasureController>();
+  MeasureController measureController = Get.find<MeasureController>();
   late final measureHandler = Get.put(MeasureHandler());
 
+  /// 图像数据列表
+  List<RemedicalInfoDTO> remedicalList = [];
+
+  /// 当前选中的图像下标
   int selectedImageIndex = -1;
 
   /// 获取图片地址
@@ -222,13 +226,44 @@ class _LeftSiderImageListState extends State<LeftSiderImageList> {
     setState(() {});
   }
 
+  /// 获取图像Code来更新图像
+  void onChangeImageByRemedicalCode(_, e) {
+    onChangeImage(findImageUrlByRemedicalCode(e), e);
+  }
+
+  /// 更新图像集合
+  void onChangeImageList(_, e) {
+    measureController = Get.find<MeasureController>();
+    setState(() {
+      remedicalList = e;
+    });
+  }
+
+  String findImageUrlByRemedicalCode(String remedicalCode) {
+    String imageUrl = '';
+    for (var i = 0; i < measureController.examInfo.images.length; i++) {
+      if (remedicalList[i].remedicalCode! == remedicalCode) {
+        imageUrl = remedicalList[i].terminalImages!.imageUrl!;
+        break;
+      }
+    }
+    return imageUrl;
+  }
+
   @override
   void initState() {
+    remedicalList = widget.remedicalList;
+    measureHandler.changeImageByRemedicalCode
+        .addListener(onChangeImageByRemedicalCode);
+    measureHandler.changeImageList.addListener(onChangeImageList);
     super.initState();
   }
 
   @override
   void dispose() {
+    measureHandler.changeImageByRemedicalCode
+        .removeListener(onChangeImageByRemedicalCode);
+    measureHandler.changeImageList.removeListener(onChangeImageList);
     super.dispose();
   }
 
@@ -237,7 +272,7 @@ class _LeftSiderImageListState extends State<LeftSiderImageList> {
     return FContainer(
       key: ValueKey(measureData.itemCurrentImage),
       alignment: Alignment.topCenter,
-      child: _buildImageList(widget.remedicalList),
+      child: _buildImageList(remedicalList),
     );
   }
 

+ 209 - 163
lib/view/measure/measure_view.dart

@@ -11,7 +11,6 @@ import 'package:fis_measure/process/workspace/measure_controller.dart';
 import 'package:fis_measure/process/workspace/measure_data_controller.dart';
 import 'package:fis_measure/process/workspace/measure_handler.dart';
 import 'package:fis_measure/process/workspace/measure_3d_view_controller.dart';
-import 'package:fis_measure/view/cursor.dart';
 import 'package:fis_measure/view/gesture/positioned_cursor.dart';
 import 'package:fis_measure/view/measure/measure_config/widgets/measure_configuration_style.dart';
 import 'package:fis_measure/view/measure/measure_images_bar.dart';
@@ -49,6 +48,13 @@ class MeasureMainPage extends StatefulWidget implements FWidget {
 }
 
 class _MeasureMainPageState extends State<MeasureMainPage> {
+  /// 病人及图像信息
+  String _curToken = '';
+  String _curPatientCode = '';
+  String _curRemedicalCode = '';
+  String _curRecordCode = '';
+  bool? _curNeedRouterBack;
+
   /// 数据
   final measureData = Get.find<MeasureDataController>();
 
@@ -58,156 +64,119 @@ class _MeasureMainPageState extends State<MeasureMainPage> {
   /// 测量项控制器
   final measureMetaController = Get.put(MeasureMetaController());
 
-  /// 页面loadding
-  bool loaded = false;
+  /// 隐藏全屏loadding
+  bool _hideFullScreenLoading = false;
 
-  // /// 图片loadding
+  /// 图片loadding
   late bool imageLoaded = false;
 
-  ///检查图片信息表
-  List<ExamImageInfo> examImageInfoList = [];
-
   late final measureHandler = Get.find<MeasureHandler>();
 
   /// 测量控制器
-  late MeasureController measureController = Get.put(MeasureController(
-    "",
-    imagesFetchFunc: (code) async {
-      return examImageInfoList;
-    },
-  ));
-
-  /// 获取测量图片所需的图片组 并且写入控制器中 加载
-  void getExamImageInfoList(List<RemedicalInfoDTO> remedicals) async {
-    for (var element in remedicals) {
-      examImageInfoList.add(
-        ExamImageInfo(
-          element.terminalImages!.imageUrl!,
-          element.terminalImages!.previewUrl!,
-        ),
-      );
-    }
+  late MeasureController measureController;
 
-    measureController = Get.put(MeasureController(
-      "",
-      imagesFetchFunc: (code) async {
-        return examImageInfoList;
-      },
-    ));
-
-    await measureController.load();
-    int selectedImageIndex = -1;
-    if (examImageInfoList
-        .any((element) => element.url == measureData.itemCurrentImage)) {
-      ExamImageInfo selectedImage = examImageInfoList.firstWhere(
-        (element) => element.url == measureData.itemCurrentImage,
-      );
-      selectedImageIndex = examImageInfoList.indexOf(selectedImage);
-      measureController.examInfo.selectedImageIndex = selectedImageIndex;
-    }
-    MeasureLanguage.load(measureData.measureLanguage);
-  }
-
-  void changeImage(sender, e) {
+  /// 响应图片切换事件通知
+  void _onChangeImage(sender, e) {
     imageLoaded = e;
     setState(() {});
   }
 
-  void changeFullScreenState(sender, e) {
+  /// 响应全屏状态切换事件
+  void _onChangeFullScreenState(sender, e) {
     setState(() {});
   }
 
-  @override
-  void initState() {
-    loadLayoutConfig();
-    getImageInfo();
-    measureHandler.onChangeImageLoaded.addListener(changeImage);
-    measureHandler.onChangeFullScreenState.addListener(changeFullScreenState);
-    super.initState();
+  /// 在此处动态刷新测量窗口,而不是重置窗口
+  void _onUpdateState(sender, Map<String, String> parameters) async {
+    _curNeedRouterBack = false;
+    bool needUpdate = false;
+    if (_curPatientCode == (parameters['patientCode'] ?? '')) {
+      if (_curRemedicalCode == (parameters['remedicalCode'] ?? '')) {
+      } else {
+        measureHandler.changeImageByRemedicalCode
+            .emit(this, parameters['remedicalCode'] ?? '');
+      }
+    } else {
+      needUpdate = true;
+    }
+    _curToken = parameters['token'] ?? '';
+    _curPatientCode = parameters['patientCode'] ?? '';
+    _curRemedicalCode = parameters['remedicalCode'] ?? '';
+    _curRecordCode = parameters['recordCode'] ?? '';
+
+    if (needUpdate) {
+      await LayoutConfiguration.ins.loadData();
+      List<RemedicalInfoDTO> remedicals = await _getCurRemedicals();
+      _initMouseModuel();
+      _initCarotidModuel(remedicals);
+      measureData.remedicalList = remedicals;
+      var remedicalInfo =
+          await measureData.getImageInfo.call(_curRemedicalCode, _curToken);
+      if (remedicalInfo != null) {
+        measureData.aiResults = remedicalInfo.diagnosisResult ?? '';
+
+        if (remedicalInfo.terminalImages != null) {
+          _hideFullScreenLoading = true;
+          measureData.itemCurrentImage =
+              remedicalInfo.terminalImages!.imageUrl ?? '';
+          getExamImageInfoList(remedicals);
+          measureHandler.changeImageList.emit(this, remedicals);
+        }
+      }
+
+      measureController.imageLoaded.removeListener(_onImageLoaded);
+      measureController.imageLoaded.addListener(_onImageLoaded);
+    }
+    _setCurImageData();
   }
 
-  void getImageInfo() {
+  /// 将当前的图像信息同步到 measureData 中
+  void _setCurImageData() {
     measureData.measureImageData = MeasureImageData(
-      patientCode: widget.patientCode,
-      recordCode: widget.recordCode,
-      remedicalCode: widget.remedicalCode,
+      patientCode: _curPatientCode,
+      recordCode: _curRecordCode,
+      remedicalCode: _curRemedicalCode,
     );
   }
 
-  /// 加载图像布局配置
-  void loadLayoutConfig() async {
+  /// 加载图像布局配置,然后加载全局数据
+  void _loadLayoutConfig() async {
     await LayoutConfiguration.ins.loadData();
     setState(() {
-      // 加载图像数据
       _initData();
     });
   }
 
-  void onImageLoaded(Object sender, ExamImageInfo? e) async {
-    // measureHandler.changeImageLoaded = true;
-    if (!mounted) return;
-    final currentImage = measureData.remedicalList.firstWhereOrNull(
-      (element) => element.terminalImages!.imageUrl == e!.url,
-    );
-    if (currentImage != null) {
-      /// 获取图片详细信息
-      var remedicalInfo = await measureData.getImageInfo(
-        currentImage.remedicalCode ?? '',
-        widget.token,
-      );
-      if (remedicalInfo != null) {
-        measureData.aiResults = remedicalInfo.diagnosisResult ?? '';
-        measure3DViewController.initParams();
-
-        /// ai 良恶性 判断是否有ai
-        measureData.diagnosisConclusion = remedicalInfo.diagnosisConclusion;
-        if (remedicalInfo.carotidResult != null) {
-          /// [Carotid] ✅详情传入测量信息
-          measure3DViewController.carotidResult = remedicalInfo.carotidResult!;
-
-          /// [Carotid] ✅需要在此通知 controller 存在颈动脉信息
-          measure3DViewController.exist3DData = true;
-          measure3DViewController
-              .handleChangeCarotid2DImage(remedicalInfo.recordCode!);
-        } else {
-          measure3DViewController.exist3DData = false;
-        }
-        // [Carotid] ✅只要更换图片都要切换到Vid 2D模式
-        if (measure3DViewController.curMeasureMode != MeasureMode.vidMode) {
-          measure3DViewController.backToVidMode();
-        }
-        try {
-          if (e != null) {
-            Future.delayed(const Duration(milliseconds: 100), () {
-              measureController.playerController.play();
-            });
-            setState(() {
-              loaded = true;
-              measureHandler.changeImageLoaded = false;
-            });
-          }
-        } catch (error) {
-          setState(() {
-            loaded = true;
-            measureHandler.changeImageLoaded = false;
-          });
-        }
-      }
-    }
+  @override
+  void initState() {
+    _curToken = widget.token;
+    _curPatientCode = widget.patientCode;
+    _curRemedicalCode = widget.remedicalCode;
+    _curRecordCode = widget.recordCode;
+    _curNeedRouterBack = widget.needRouterBack;
+    _hideFullScreenLoading = false;
+    _loadLayoutConfig();
+    _setCurImageData();
+    measureData.curMeasureDataChanged.addListener(_onUpdateState);
+    measureHandler.onChangeImageLoaded.addListener(_onChangeImage);
+    measureHandler.onChangeFullScreenState
+        .addListener(_onChangeFullScreenState);
+    super.initState();
   }
 
   @override
   void dispose() {
-    measureHandler.onChangeImageLoaded.removeListener(changeImage);
+    measureData.curMeasureDataChanged.removeListener(_onUpdateState);
+    measureHandler.onChangeImageLoaded.removeListener(_onChangeImage);
     measureHandler.onChangeFullScreenState
-        .removeListener(changeFullScreenState);
+        .removeListener(_onChangeFullScreenState);
     super.dispose();
   }
 
   @override
   FWidget build(BuildContext context) {
     FWidget body;
-    if (!loaded) {
+    if (!_hideFullScreenLoading) {
       const loadingWidget = FCenter(child: FCircularProgressIndicator());
       body = FRow(
         children: const [
@@ -221,7 +190,7 @@ class _MeasureMainPageState extends State<MeasureMainPage> {
         children: [
           FOffstage(
               child: _MeasureLeftBoard(
-                needRouterBack: widget.needRouterBack,
+                needRouterBack: _curNeedRouterBack,
               ),
               offstage: measureHandler.fullScreenState),
           const FVerticalDivider(),
@@ -252,7 +221,6 @@ class _MeasureMainPageState extends State<MeasureMainPage> {
         ],
       );
     }
-
     return FCenter(
       child: FContainer(
         color: const Color.fromRGBO(70, 70, 70, 1),
@@ -261,79 +229,157 @@ class _MeasureMainPageState extends State<MeasureMainPage> {
     );
   }
 
-  MeasureCursorType _getMeasureSystemSettingCursorType(
-    CursorTypeEnum cursorType,
-  ) {
-    switch (cursorType) {
-      case CursorTypeEnum.CursorType1Icon:
-        return MeasureCursorType.cursor01;
-      case CursorTypeEnum.CursorType2Icon:
-        return MeasureCursorType.cursor02;
-      case CursorTypeEnum.CursorType3Icon:
-        return MeasureCursorType.cursor03;
-      case CursorTypeEnum.CursorType4Icon:
-        return MeasureCursorType.cursor04;
-      case CursorTypeEnum.CursorType5Icon:
-        return MeasureCursorType.cursor05;
-      default:
-        return MeasureCursorType.cursor01;
-    }
-  }
-
-  /// 初始化卡尺样式部分
-  Future<void> _getMeasureSystemSetting() async {
-    final mouseState = Get.put<IMouseState>(MouseState());
-    final result = await measureData.getMeasureSystemSettingAsync()
-        as MeasureSystemSettingDTO;
-    measureData.measureSystemSetting = result;
-    mouseState.cursorType =
-        getMeasureSystemSettingCursorType(result.cursorType);
-    mouseState.cursorSize = result.cursorSize.toDouble();
-  }
-
-  void _initData() async {
+  /// 获取当前状态下的图像集
+  Future<List<RemedicalInfoDTO>> _getCurRemedicals() async {
     List<RemedicalInfoDTO> remedicals = [];
-    List<Ultra3DResourceInfo> ultra3DResourceInfos = [];
-    loaded = false;
 
     var value = await measureData.getRemedicalList.call(
-      widget.patientCode,
-      widget.recordCode,
-      widget.token,
+      _curPatientCode,
+      _curRecordCode,
+      _curToken,
     );
 
     for (var remedicalItemList in value) {
       remedicals.addAll(remedicalItemList.remedicalList ?? []);
     }
 
-    /// 获取样式
-    _getMeasureSystemSetting();
+    return remedicals;
+  }
 
-    /// [Carotid] ✅遍历出颈动脉信息列表,传给壳子
+  /// 初始化颈动脉模块
+  /// [Carotid] ✅遍历出颈动脉信息列表,传给壳子
+  void _initCarotidModuel(List<RemedicalInfoDTO> remedicals) {
+    List<Ultra3DResourceInfo> ultra3DResourceInfos = [];
     for (var remedical in remedicals) {
       if (remedical.carotidResult != null) {
         ultra3DResourceInfos.add(Ultra3DResourceInfo(remedical.carotidResult!));
       }
     }
     measure3DViewController.ultra3DResourceInfoList = ultra3DResourceInfos;
-    measure3DViewController.recordId = widget.recordCode;
+    measure3DViewController.recordId = _curRecordCode;
     measure3DViewController.notifyShellLoadAllModel();
+  }
+
+  /// 初始化卡尺样式部分
+  Future<void> _initMouseModuel() async {
+    final mouseState = Get.put<IMouseState>(MouseState());
+    final result = await measureData.getMeasureSystemSettingAsync()
+        as MeasureSystemSettingDTO;
+    measureData.measureSystemSetting = result;
+    mouseState.cursorType =
+        getMeasureSystemSettingCursorType(result.cursorType);
+    mouseState.cursorSize = result.cursorSize.toDouble();
+  }
+
+  /// 测量页全局数据首次初始化
+  void _initData() async {
+    List<RemedicalInfoDTO> remedicals = await _getCurRemedicals();
+    _initMouseModuel();
+    _initCarotidModuel(remedicals);
     measureData.remedicalList = remedicals;
     var remedicalInfo =
-        await measureData.getImageInfo.call(widget.remedicalCode, widget.token);
+        await measureData.getImageInfo.call(_curRemedicalCode, _curToken);
     if (remedicalInfo != null) {
       measureData.aiResults = remedicalInfo.diagnosisResult ?? '';
 
       if (remedicalInfo.terminalImages != null) {
-        loaded = true;
+        _hideFullScreenLoading = true;
         measureData.itemCurrentImage =
             remedicalInfo.terminalImages!.imageUrl ?? '';
         getExamImageInfoList(remedicals);
       }
     }
 
-    measureController.imageLoaded.removeListener(onImageLoaded);
-    measureController.imageLoaded.addListener(onImageLoaded);
+    measureController.imageLoaded.removeListener(_onImageLoaded);
+    measureController.imageLoaded.addListener(_onImageLoaded);
+  }
+
+  /// 获取测量图片所需的图片组 并且写入控制器中 加载
+  void getExamImageInfoList(List<RemedicalInfoDTO> remedicals) async {
+    /// 检查中图片信息表
+    List<ExamImageInfo> examImageInfoList = [];
+    for (var element in remedicals) {
+      examImageInfoList.add(
+        ExamImageInfo(
+          element.terminalImages!.imageUrl!,
+          element.terminalImages!.previewUrl!,
+        ),
+      );
+    }
+
+    Get.delete<MeasureController>();
+    measureController = Get.put(MeasureController(
+      "",
+      imagesFetchFunc: (code) async {
+        return examImageInfoList;
+      },
+    ));
+
+    await measureController.load();
+    int selectedImageIndex = -1;
+    if (examImageInfoList
+        .any((element) => element.url == measureData.itemCurrentImage)) {
+      ExamImageInfo selectedImage = examImageInfoList.firstWhere(
+        (element) => element.url == measureData.itemCurrentImage,
+      );
+      selectedImageIndex = examImageInfoList.indexOf(selectedImage);
+      measureController.examInfo.selectedImageIndex = selectedImageIndex;
+    }
+    MeasureLanguage.load(measureData.measureLanguage);
+  }
+
+  /// vid 切换时会触发到这里
+  void _onImageLoaded(Object sender, ExamImageInfo? e) async {
+    // measureHandler.changeImageLoaded = true;
+    if (!mounted) return;
+    final currentImage = measureData.remedicalList.firstWhereOrNull(
+      (element) => element.terminalImages!.imageUrl == e!.url,
+    );
+    if (currentImage != null) {
+      /// 获取图片详细信息
+      var remedicalInfo = await measureData.getImageInfo(
+        currentImage.remedicalCode ?? '',
+        _curToken,
+      );
+      if (remedicalInfo != null) {
+        measureData.aiResults = remedicalInfo.diagnosisResult ?? '';
+        measure3DViewController.initParams();
+
+        /// ai 良恶性 判断是否有ai
+        measureData.diagnosisConclusion = remedicalInfo.diagnosisConclusion;
+        if (remedicalInfo.carotidResult != null) {
+          /// [Carotid] ✅详情传入测量信息
+          measure3DViewController.carotidResult = remedicalInfo.carotidResult!;
+
+          /// [Carotid] ✅需要在此通知 controller 存在颈动脉信息
+          measure3DViewController.exist3DData = true;
+          measure3DViewController
+              .handleChangeCarotid2DImage(remedicalInfo.recordCode!);
+        } else {
+          measure3DViewController.exist3DData = false;
+        }
+        // [Carotid] ✅只要更换图片都要切换到Vid 2D模式
+        if (measure3DViewController.curMeasureMode != MeasureMode.vidMode) {
+          measure3DViewController.backToVidMode();
+        }
+        try {
+          if (e != null) {
+            Future.delayed(const Duration(milliseconds: 100), () {
+              measureController.playerController.play();
+            });
+            setState(() {
+              _hideFullScreenLoading = true;
+              measureHandler.changeImageLoaded = false;
+            });
+          }
+        } catch (error) {
+          setState(() {
+            _hideFullScreenLoading = true;
+            measureHandler.changeImageLoaded = false;
+          });
+        }
+      }
+    }
   }
 }
 
@@ -384,7 +430,7 @@ class _MeasureLeftBoardState extends State<_MeasureLeftBoard> {
   }
 
   ///图像发生变化
-  void changeImage(sender, e) {
+  void _onChangeImage(sender, e) {
     setState(() {});
   }
 
@@ -393,7 +439,7 @@ class _MeasureLeftBoardState extends State<_MeasureLeftBoard> {
     measureHandler.onChangedTab.addListener(_onChangedTab);
     measure3DViewController.updatePlayerMode.addListener(_onModeChanged);
     measureData.curItemMetaListChanged.addListener(_onCurItemMetaListChanged);
-    measureHandler.onChangeImageLoaded.addListener(changeImage);
+    measureHandler.onChangeImageLoaded.addListener(_onChangeImage);
     super.initState();
   }
 
@@ -403,7 +449,7 @@ class _MeasureLeftBoardState extends State<_MeasureLeftBoard> {
     measure3DViewController.updatePlayerMode.removeListener(_onModeChanged);
     measureData.curItemMetaListChanged
         .removeListener(_onCurItemMetaListChanged);
-    measureHandler.onChangeImageLoaded.removeListener(changeImage);
+    measureHandler.onChangeImageLoaded.removeListener(_onChangeImage);
     super.dispose();
   }