Ver código fonte

Merge branch 'master' of http://git.ius.plus/melon.yin/fis_lib_measure

melon.yin 2 anos atrás
pai
commit
802a536997

Diferenças do arquivo suprimidas por serem muito extensas
+ 640 - 66
assets/items.json


+ 2 - 21
lib/interfaces/process/items/terms.dart

@@ -5,34 +5,15 @@ class MeasureUnsupportedTerms {
     PSAD,
     AntPelvic_Rest,
     AntPelvic_Valsalva,
+    HR,
   ];
   static const PSAD = "PSAD";
   static const AntPelvic_Rest = "Ant. Pelvic(Rest)";
   static const AntPelvic_Valsalva = "Ant. Pelvic(Valsalva)";
+  static const HR = "HR";
 }
 
 class MeasureTerms {
-  MeasureTerms._();
-
-  /// M 模式(TissueTM)下的测量项
-  /// 见 Vinno.Modules.MeasureModule 内
-  /// ItemMetas\MeasureAppMetas.Config.cs
-  /// Line: 846-856
-  /// 距离 TODO: 因为当前使用的是 switchItemByName ,所以此处name先不与普通Distance重复
-  static const String MVerticalDistance = "M_Distance";
-
-  /// 心率
-  static const String Hr = "HR";
-
-  /// 狭窄率
-  static const String StenosisTwoVerticalDistance = "M_%Stenosis";
-
-  /// A/B比值 TODO ? See: Line: 858
-  // static const String CreateMAbRatio = "M_A/B Ratio";
-
-  /// 深度
-  static const String MDepth = "M_Depth";
-
   ///////////////////////////////////////////////////////////////////////////////////////////////////////
 
   /* AI [begin]*/

+ 6 - 7
lib/measure_page_test.dart

@@ -361,8 +361,11 @@ class _MeasureLeftBoardState extends State<_MeasureLeftBoard> {
   ];
   // ignore: non_constant_identifier_names
   static final C_SUPPORTED_M_ITEMS = <String>[
-    MeasureTerms.MVerticalDistance,
+    MeasureTerms.VerticalDistance,
     MeasureTerms.Timespan,
+    MeasureTerms.Depth,
+    MeasureTerms.Stenosis,
+    MeasureTerms.AbRatio,
     "Qp/Qs",
   ];
 
@@ -408,7 +411,8 @@ class _MeasureLeftBoardState extends State<_MeasureLeftBoard> {
   void _visualAreaChanged(sender, IVisualArea e) {
     if (mounted) {
       _setAvailableModes(e.mode.modeType.toString().split('.')[1]);
-      changeItemByMeta(0);
+      // changeItemByMeta(0); //暂时不要自动切测量项
+      setState(() {});
     }
   }
 
@@ -416,11 +420,6 @@ class _MeasureLeftBoardState extends State<_MeasureLeftBoard> {
     modeType = name;
     print("_setAvailableModes: $name");
     loadItems();
-    // setState(() {
-    //   /// TODO:当前先写死模式判断,debug用
-    //   curActiveItems =
-    //       name == "TissueTM" ? C_SUPPORTED_M_ITEMS : C_SUPPORTED_ITEMS;
-    // });
   }
 
   @override

+ 7 - 5
lib/process/calcuators/a_b_ratio.dart

@@ -1,20 +1,22 @@
 import 'package:fis_measure/interfaces/process/calculators/output.dart';
 import 'package:fis_measure/interfaces/process/calculators/values.dart';
 import 'package:fis_measure/process/calcuators/formulas/general.dart';
+import 'package:fis_measure/process/items/item.dart';
 import 'package:fis_measure/process/primitives/combos/two_area.dart';
+import 'package:fis_measure/process/primitives/combos/two_length.dart';
 import 'package:fis_measure/process/primitives/trace.dart';
 
 import 'calculator.dart';
 
-class ABRatioCal extends Calculator<TwoArea, double> {
-  ABRatioCal(TwoArea ref) : super(ref);
+class ABRatioCal extends Calculator<TwoLengthAbstract, double> {
+  ABRatioCal(TwoLengthAbstract ref) : super(ref);
 
   @override
   void calculate() {
     if (ref.feature == null) return;
 
-    final a1 = _pickChildValue(ref.a1);
-    final a2 = _pickChildValue(ref.a2);
+    final a1 = _pickChildValue(ref.child1);
+    final a2 = _pickChildValue(ref.child2);
 
     final feature = ref.feature!;
     final viewport = feature.hostVisualArea!.viewport!;
@@ -32,7 +34,7 @@ class ABRatioCal extends Calculator<TwoArea, double> {
     return d1 / d2;
   }
 
-  double? _pickChildValue(Trace item) {
+  double? _pickChildValue(MeasureItem item) {
     if (item.calculator == null) return null;
     ValueBase? value;
     if (item.measuredFeatures.isNotEmpty) {

+ 18 - 0
lib/process/calcuators/depth.dart

@@ -23,6 +23,24 @@ class TissueDepthCal extends Calculator<Location, double> {
   }
 }
 
+class MDepthCal extends Calculator<Location, double> {
+  MDepthCal(Location ref) : super(ref);
+
+  @override
+  void calculate() {
+    if (ref.feature == null) return;
+    final viewport = ref.feature!.hostVisualArea!.viewport!;
+    final layout = ref.feature!.hostVisualArea!.displayRegion;
+    final point = ref.feature!.point.clone();
+
+    point.addOffset(-layout.left, -layout.top);
+    // final physicalPoint = viewport.physical!.convert(point);
+    final physicalPoint = viewport.convert(point);
+    final value = physicalPoint.y;
+    updateFloatValue(value);
+  }
+}
+
 class TissueConvexDepthCal extends Calculator<Location, double> {
   TissueConvexDepthCal(Location ref) : super(ref);
 

+ 42 - 0
lib/process/calcuators/time_motion.dart

@@ -1,3 +1,8 @@
+import 'package:fis_measure/interfaces/process/calculators/values.dart';
+import 'package:fis_measure/process/calcuators/formulas/general.dart';
+import 'package:fis_measure/process/items/item.dart';
+import 'package:fis_measure/process/primitives/combos/two_length.dart';
+
 import '../primitives/straightline.dart';
 import 'calculator.dart';
 
@@ -38,3 +43,40 @@ class TimeSpanCal extends Calculator<StraightLine, double> {
     updateFloatValue(value);
   }
 }
+
+class StenosisCal extends Calculator<TwoLengthAbstract, double> {
+  StenosisCal(TwoLengthAbstract ref) : super(ref);
+
+  @override
+  void calculate() {
+    if (ref.feature == null) return;
+
+    final a1 = _pickChildValue(ref.child1);
+    final a2 = _pickChildValue(ref.child2);
+
+    final feature = ref.feature!;
+    final viewport = feature.hostVisualArea!.viewport!;
+
+    if (a1 != null && a2 != null) {
+      final value = GeneralFormulas.countStenosis(
+        a1,
+        a2,
+      );
+      updateFloatValue(value);
+    }
+  }
+
+  double? _pickChildValue(MeasureItem item) {
+    if (item.calculator == null) return null;
+    ValueBase? value;
+    if (item.measuredFeatures.isNotEmpty) {
+      value = item.measuredFeatures.first.value;
+    } else if (item.feature != null) {
+      value = item.feature!.value;
+    }
+    if (value != null) {
+      return (value as FloatValue).value ?? 0;
+    }
+    return null;
+  }
+}

+ 5 - 0
lib/process/items/factory.dart

@@ -101,6 +101,11 @@ class MeasureItemFactory {
     _singleton._register(
         MeasureTypes.VerticalDistance, StraightLine.createVerticalDistance);
     _singleton._register(MeasureTypes.TimeSpan, StraightLine.createTimeSpan);
+    _singleton._register(MeasureTypes.MDepth, Location.createTissueTMDepth);
+    _singleton._register(MeasureTypes.StenosisTwoVerticalDistance,
+        TwoStraightLine.createStenosisTwoVerticalDistance);
+    _singleton._register(MeasureTypes.AbRatioTwoVerticalDistance,
+        TwoStraightLine.createAbRatioTwoVerticalDistance);
 
     // Area Perimeter
     _singleton._register(

+ 26 - 3
lib/process/primitives/combos/two_straightline.dart

@@ -20,12 +20,19 @@ import 'two_length.dart';
 class TwoStraightLine extends TwoLengthAbstract<TwoStraightLineFeature> {
   late final StraightLine x;
   late final StraightLine y;
+  final bool ifVertical;
 
-  TwoStraightLine(ItemMeta meta) : super(meta) {
+  TwoStraightLine(ItemMeta meta, {this.ifVertical = false}) : super(meta) {
     final metaX = meta.childItems[0];
     final metaY = meta.childItems[1];
-    x = StraightLine.createDistance(metaX, this);
-    y = StraightLine.createDistance(metaY, this);
+
+    if (ifVertical) {
+      x = StraightLine.createDistance(metaX, this);
+      y = StraightLine.createDistance(metaY, this);
+    } else {
+      x = StraightLine.createVerticalDistance(metaX, this);
+      y = StraightLine.createVerticalDistance(metaY, this);
+    }
     childItems.add(x);
     childItems.add(y);
   }
@@ -83,6 +90,22 @@ class TwoStraightLine extends TwoLengthAbstract<TwoStraightLineFeature> {
 
     return twoStraightline;
   }
+
+  static TwoStraightLine createStenosisTwoVerticalDistance(ItemMeta meta,
+      [IMeasureItem? parent]) {
+    var twoStraightline = TwoStraightLine(meta, ifVertical: true);
+    twoStraightline.calculator = StenosisCal(twoStraightline);
+
+    return twoStraightline;
+  }
+
+  static TwoStraightLine createAbRatioTwoVerticalDistance(ItemMeta meta,
+      [IMeasureItem? parent]) {
+    var twoStraightline = TwoStraightLine(meta, ifVertical: true);
+    twoStraightline.calculator = ABRatioCal(twoStraightline);
+
+    return twoStraightline;
+  }
 }
 
 class TwoStraightLineFeature extends TopMeasureItemFeature {

+ 33 - 7
lib/process/primitives/location.dart

@@ -6,11 +6,14 @@ import 'package:fis_measure/interfaces/date_types/rect_region.dart';
 import 'package:fis_measure/interfaces/enums/items.dart';
 import 'package:fis_measure/interfaces/process/items/item.dart';
 import 'package:fis_measure/interfaces/process/items/item_metas.dart';
+import 'package:fis_measure/interfaces/process/items/types.dart';
 import 'package:fis_measure/interfaces/process/workspace/application.dart';
 import 'package:fis_measure/interfaces/process/workspace/point_info.dart';
 import 'package:fis_measure/process/visual/tissue_area.dart';
 import 'package:fis_measure/utils/canvas.dart';
 import 'package:get/get.dart';
+import 'package:vid/us/vid_us_mode.dart';
+import 'package:vid/us/vid_us_probe.dart';
 
 import '../calcuators/depth.dart';
 import '../items/item.dart';
@@ -49,19 +52,33 @@ class Location extends MeasureItem<LocationFeature> {
     // TODO: 判断是否当前area
     // 转换为Area逻辑位置
     final point = args.toAreaLogicPoint();
-    final isProbeConvex = (args.hostVisualArea! as TissueArea).isConvex;
-    if (isProbeConvex) {
-      feature = TissueConvexLocationFeature(this, point);
-    } else {
-      feature = LocationFeature(this, point);
-    }
-
+    print(args.hostVisualArea!.mode.modeType);
+    handleTissue(args, point);
+    handleTissueTM(args.hostVisualArea!.mode.modeType, point);
     if (args.hostVisualArea != null) {
       feature!.hostVisualArea = args.hostVisualArea;
     }
     state = ItemStates.running;
   }
 
+  void handleTissueTM(VidUsModeType mode, DPoint point) {
+    if (mode == VidUsModeType.TissueTM) {
+      ///TODO [Gavin] 写一个新的 feature 处理 M 模式
+      feature = LocationFeature(this, point);
+    }
+  }
+
+  void handleTissue(PointInfo args, DPoint point) {
+    if (args.hostVisualArea!.mode.modeType == VidUsModeType.Tissue) {
+      final isProbeConvex = (args.hostVisualArea! as TissueArea).isConvex;
+      if (isProbeConvex) {
+        feature = TissueConvexLocationFeature(this, point);
+      } else {
+        feature = LocationFeature(this, point);
+      }
+    }
+  }
+
   static Location createTissueConvexDepth(
     ItemMeta meta, [
     IMeasureItem? parent,
@@ -90,6 +107,15 @@ class Location extends MeasureItem<LocationFeature> {
     location.calculator = TissueDepthCal(location);
     return location;
   }
+
+  static Location createTissueTMDepth(
+    ItemMeta meta, [
+    IMeasureItem? parent,
+  ]) {
+    Location location = Location(meta, parent);
+    location.calculator = MDepthCal(location);
+    return location;
+  }
 }
 
 class TissueConvexLocationFeature extends LocationFeature {

+ 2 - 16
lib/process/workspace/application.dart

@@ -426,7 +426,7 @@ class Application implements IApplication {
     if (name == MeasureTypes.VerticalDistance) {
       activeMeasureItem = MeasureItemFactory.createItem(
         ItemMeta(
-          MeasureTerms.MVerticalDistance,
+          MeasureTerms.VerticalDistance,
           measureType: MeasureTypes.VerticalDistance,
           description: MeasureTypes.VerticalDistance,
           outputs: [
@@ -437,20 +437,6 @@ class Application implements IApplication {
       );
       return;
     }
-    if (name == MeasureTerms.Timespan) {
-      activeMeasureItem = MeasureItemFactory.createItem(
-        ItemMeta(
-          MeasureTerms.Timespan,
-          measureType: MeasureTypes.TimeSpan,
-          description: MeasureTerms.Timespan,
-          outputs: [
-            ItemOutputMeta(
-                MeasureTerms.Timespan, MeasureTerms.Timespan, VidUsUnit.s),
-          ],
-        ),
-      );
-      return;
-    }
     print("Unknown measure type: $name");
     activeMeasureItem = null;
   }
@@ -618,7 +604,7 @@ class Application implements IApplication {
       }
       area.isActive = true;
       print("切换到${area.mode.name}模式,TODO:切换区域自动切换测量项");
-      switchItemByName("---"); //TODO:切换区域自动切换测量项
+      // switchItemByName("---"); //TODO:切换区域自动切换测量项
       visualAreaChanged.emit(this, area);
       return true;
     }

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

@@ -4,6 +4,7 @@ import 'package:fis_common/event/event_type.dart';
 import 'package:fis_jsonrpc/rpc.dart';
 import 'package:fis_measure/interfaces/process/items/item_metas.dart';
 import 'package:fis_measure/process/workspace/measure_handler.dart';
+import 'package:fis_measure/view/measure/measure_config/measure_configuation_page.dart';
 import 'package:vid/us/vid_us_mode.dart';
 
 class MeasureImageData {
@@ -97,10 +98,13 @@ abstract class IMeasureDataController {
   List<VidUsMode> get applicationModes;
   set applicationModes(List<VidUsMode> value);
 
-  /// 测量图片当前所有模式下所有测量项数据
+  /// 测量图片当前模式下所有测量项数据
   List<MeasureModeDTO> get availableModes;
   set availableModes(List<MeasureModeDTO> value);
 
+  List<ItemMetaGroup> get itemMetaListGroup;
+  set itemMetaListGroup(List<ItemMetaGroup> itemMetaListGroup);
+
   String get currentMode;
   set currentMode(String value);
 }
@@ -125,6 +129,7 @@ class MeasureDataController implements IMeasureDataController {
   List<ItemMeta> _getBottomItemMetaList = [];
   List<String> _getCommentsList = [];
   List<CommentItemDTO> _measureCommentItemResult = [];
+  List<ItemMetaGroup> _itemMetaListGroup = [];
   @override
   var remedicalListResultChanged = FEventHandler<List<RemedicalInfoDTO>>();
 
@@ -270,6 +275,16 @@ class MeasureDataController implements IMeasureDataController {
     }
   }
 
+  @override
+  List<ItemMetaGroup> get itemMetaListGroup => _itemMetaListGroup;
+  @override
+  set itemMetaListGroup(List<ItemMetaGroup> value) {
+    if (value != _itemMetaListGroup) {
+      _itemMetaListGroup = value;
+      // _onItemMetaListChanged();
+    }
+  }
+
   @override
   String get itemCurrentImage => _itemCurrentImage;
   @override

+ 3 - 2
lib/view/gesture/mouse_gesture.dart

@@ -140,12 +140,13 @@ class _MeasureMouseGesturePanelState extends State<MeasureMouseGesturePanel> {
         if (area.visualAreaType == VidUsVisualAreaType.TissueTimeMotion) {
           ifContainerTissueTM = true;
 
-          ///TODO Left 好像不准?需要其他相关组进行调整
+          ///TODO 由于布局问题 Left 定位给不准,这里放宽到边界
           tissueTMPixelRegion = RectRegion.rect(DRect(
             // area.displayRegion.left * displaySize.width,
             0,
             area.displayRegion.top * displaySize.height,
-            area.displayRegion.width * displaySize.width,
+            // area.displayRegion.width * displaySize.width,
+            displaySize.width,
             area.displayRegion.height * displaySize.height,
           ));
         }

+ 26 - 71
lib/view/measure/measure_config/measure_configuation_page.dart

@@ -2,12 +2,13 @@ import 'dart:convert';
 
 import 'package:fis_i18n/i18n.dart';
 import 'package:fis_jsonrpc/rpc.dart';
-import 'package:fis_measure/interfaces/process/items/item_metas.dart';
+import 'package:fis_measure/interfaces/process/player/play_controller.dart';
 import 'package:fis_measure/interfaces/process/workspace/application.dart';
-import 'package:fis_measure/process/items/item_meta_convert.dart';
 import 'package:fis_measure/process/workspace/measure_data_controller.dart';
 import 'package:fis_measure/process/workspace/measure_handler.dart';
 import 'package:fis_measure/view/measure/measure_config/widgets/measurement_tool_selection.dart';
+import 'package:fis_measure/view/measure/measure_view_controller.dart';
+import 'package:fis_measure/view/player/controller.dart';
 import 'package:fis_theme/theme.dart';
 import 'package:fis_ui/index.dart';
 import 'package:flutter/material.dart';
@@ -25,7 +26,7 @@ class ItemMetaGroup {
   final String itemMetaGroupTitle;
 
   /// 当前测量组的测量数组
-  final List<ItemMeta> itemMeta;
+  final List<ItemMetaDTO> itemMeta;
 
   /// 是否展开
   bool? isExpend;
@@ -64,27 +65,19 @@ class _MeasureConfigurationDialogState
 
   late final application = Get.find<IApplication>();
   late final measureHandler = Get.find<MeasureHandler>();
+  final playerController = Get.find<IPlayerController>() as VidPlayerController;
 
   /// 数据
   final measureData = Get.find<MeasureDataController>();
 
+  /// 测量项控制器
+  final measureMetaController = Get.find<MeasureMetaController>();
+
   /// 选中的测量项
   List<String> chooseMeasureList = [];
   List<ItemMetaGroup> itemMetaListGroup = [];
   String activeName = '';
 
-  /// 跟超声机端保持一致,配置 项目写死
-  List<ItemMetaGroup> getMeasureConfigurationGroupName() {
-    return [
-      ItemMetaGroup('Common', [], true),
-      ItemMetaGroup('ABD', [], true),
-      ItemMetaGroup('CARD', [], true),
-      ItemMetaGroup('GYN', [], true),
-      ItemMetaGroup('OB', [], true),
-      ItemMetaGroup('VAS', [], true),
-    ];
-  }
-
   /// 打开已选测量工具设置
   ///
   /// [name] 测量的名字 后期改版后应该是一个测量对象
@@ -95,10 +88,14 @@ class _MeasureConfigurationDialogState
     // router.dialog(() => HasSelectedSettingDialog(name: name));
   }
   Future<void> getName() async {
+    List<String> getModes = [];
+    for (var element in playerController.currentFrame?.visuals[0].modes ?? []) {
+      getModes.add(element.type.toString().split('.')[1]);
+    }
     var measureModeSelection = MeasureModeSelection(
       application.applicationName,
       application.categoryName,
-      application.isThirdPart ? ['TPPTissue'] : ['Tissue'],
+      application.isThirdPart ? ['TPPTissue'] : getModes,
     );
     measureHandler.measureModeChanged = measureModeSelection;
     measureData.getMeasureApplicationList = [];
@@ -108,30 +105,9 @@ class _MeasureConfigurationDialogState
       /// 模式版本
       measureData.measureApplicationVersion =
           measureApplicationDTO.version ?? '';
-
-      ///模式列表
-      var models = measureApplicationDTO.availableModes;
-      if (models != null && models.isNotEmpty) {
-        ///群组列表
-        var groups = models[0].availableGroups;
-        if (groups != null && groups.isNotEmpty) {
-          ///项目列表
-          var folders = groups[0].availableFolders;
-          if (folders != null && folders.isNotEmpty) {
-            measureData.getMeasureApplicationList =
-                folders[0].workingItemNames ?? [];
-            if (folders[0].availableItems != null) {
-              measureData.itemMetaList =
-                  folders[0].availableItems!.map((element) {
-                return ItemMetaConverter(element).output();
-              }).toList();
-            }
-            if (measureData.getMeasureApplicationList.isNotEmpty) {
-              changeItem(measureData.getMeasureApplicationList[0]);
-            }
-          }
-        }
-      }
+      measureData.availableModes = measureApplicationDTO.availableModes ?? [];
+      measureMetaController.setAvailableModes(measureData.currentMode);
+      activeName = measureData.getItemMetaList[0].name;
     }
   }
 
@@ -149,7 +125,7 @@ class _MeasureConfigurationDialogState
       application.applicationName,
       application.categoryName,
       UserDefinedMeasureModeDTO(
-        modeName: 'Tissue',
+        modeName: measureData.currentMode,
         workingGroups: [
           UserDefinedMeasureGroupDTO(
             name: 'General',
@@ -164,41 +140,18 @@ class _MeasureConfigurationDialogState
       ),
     );
     measureHandler.measureModeSubmitChanged = measureModeSubmitChanged;
-    var saveUserDefinedMeasureApplication = await measureData
-        .saveUserDefinedMeasureApplicationAsync
+    await measureData.saveUserDefinedMeasureApplicationAsync
         .call(measureModeSubmitChanged);
     getName();
-    setState(() {});
+    measureMetaController.setAvailableModes(measureData.currentMode);
   }
 
   @override
   void initState() {
     super.initState();
-    List<ItemMetaGroup> _itemMetaConfigurationList = [];
     List<String> chooseMeasure = [];
-
-    Map<String, List<ItemMeta>> _group = {};
-    getMeasureConfigurationGroupName().forEach(
-      ((element) {
-        List<ItemMeta> itemMetaListGroupItem = [];
-        (measureData.itemMetaList).toList().forEach(
-          (e) {
-            // if (e.categories!.contains(element.itemMetaGroupTitle)) {
-            //   itemMetaListGroupItem.add(e);
-            // }
-            _group[element.itemMetaGroupTitle] = itemMetaListGroupItem;
-          },
-        );
-      }),
-    );
-    _group.forEach(
-      (key, value) {
-        _itemMetaConfigurationList.add(
-          ItemMetaGroup(key, value, true),
-        );
-      },
-    );
-    itemMetaListGroup = _itemMetaConfigurationList;
+    measureMetaController.measureConfig();
+    itemMetaListGroup = measureData.itemMetaListGroup;
     chooseMeasure = measureData.getMeasureApplicationList;
     chooseMeasureList = chooseMeasure.toSet().toList();
   }
@@ -310,9 +263,11 @@ class _MeasureConfigurationDialogState
           ),
           measureToolsTab == 0
               ? FExpanded(
-                  child: SelectModulePage(
-                    itemMetaListGroup: itemMetaListGroup,
-                    chooseMeasureList: chooseMeasureList,
+                  child: FSingleChildScrollView(
+                    child: SelectModulePage(
+                      itemMetaListGroup: itemMetaListGroup,
+                      chooseMeasureList: chooseMeasureList,
+                    ),
                   ),
                 )
               : FExpanded(

+ 169 - 81
lib/view/measure/measure_config/widgets/measurement_tool_selection.dart

@@ -59,8 +59,19 @@ class _SelectModulePageState extends FState<SelectModulePage> {
 
   @override
   FWidget build(BuildContext context) {
-    return FListView(
-      shrinkWrap: true,
+    return FColumn(
+      children: widget.itemMetaListGroup
+          .map(
+            (e) => FColumn(
+              crossAxisAlignment: CrossAxisAlignment.start,
+              children: _buildMeasureConfiguration(e),
+            ),
+          )
+          .toList(),
+    );
+
+    FListView(
+      // shrinkWrap: true,
       children: widget.itemMetaListGroup
           .map(
             (e) => FColumn(
@@ -126,90 +137,167 @@ class _SelectModulePageState extends FState<SelectModulePage> {
       padding: const EdgeInsets.only(left: 15),
       margin: const EdgeInsets.symmetric(vertical: 10),
       child: FWrap(
-        spacing: 16.0, // 主轴(水平)方向间距
-        runSpacing: 8.0, // 纵轴(垂直)方向间距
-        direction: Axis.horizontal,
-        crossAlignment: WrapCrossAlignment.center,
-        alignment: WrapAlignment.start,
-        children: List<FWidget>.generate(
-          e.itemMeta.length,
-          (index) {
-            return widget.chooseMeasureList.contains(
-              e.itemMeta[index].name,
-            )
-                ? FElevatedButton(
-                    onPressed: () {
-                      removeChooseMeasure(
-                        e.itemMeta[index].name,
-                      );
-                    },
-                    style: const ButtonStyle(),
-                    child: FContainer(
-                      width: 180,
-                      height: 60,
-                      child: FCenter(
-                        child: FColumn(
-                          mainAxisAlignment: MainAxisAlignment.center,
-                          children: [
-                            FText(
-                              getValues(
-                                e.itemMeta[index].name,
-                              ),
-                              style: const TextStyle(
-                                color: Colors.white,
-                              ),
+          spacing: 16.0, // 主轴(水平)方向间距
+          runSpacing: 8.0, // 纵轴(垂直)方向间距
+          direction: Axis.horizontal,
+          crossAlignment: WrapCrossAlignment.center,
+          alignment: WrapAlignment.start,
+          children: e.itemMeta
+              .map(
+                (e) => widget.chooseMeasureList.contains(
+                  e.name,
+                )
+                    ? FElevatedButton(
+                        onPressed: () {
+                          removeChooseMeasure(
+                            e.name ?? '',
+                          );
+                        },
+                        style: const ButtonStyle(),
+                        child: FContainer(
+                          width: 180,
+                          height: 60,
+                          child: FCenter(
+                            child: FColumn(
+                              mainAxisAlignment: MainAxisAlignment.center,
+                              children: [
+                                FText(
+                                  getValues(
+                                    e.name ?? '',
+                                  ),
+                                  style: const TextStyle(
+                                    color: Colors.white,
+                                  ),
+                                ),
+                                FText(
+                                  e.name ?? '',
+                                  style: const TextStyle(
+                                    color: Colors.white,
+                                  ),
+                                ),
+                              ],
                             ),
-                            FText(
-                              e.itemMeta[index].name,
-                              style: const TextStyle(
-                                color: Colors.white,
-                              ),
-                            ),
-                          ],
+                          ),
                         ),
-                      ),
-                    ),
-                  )
-                : FElevatedButton(
-                    onPressed: () {
-                      addChooseMeasure(
-                        e.itemMeta[index].name,
-                      );
-                    },
-                    style: ButtonStyle(
-                      backgroundColor: MaterialStateProperty.all(
-                        Colors.white,
-                      ),
-                    ),
-                    child: FContainer(
-                      width: 180,
-                      height: 60,
-                      child: FCenter(
-                        child: FColumn(
-                          mainAxisAlignment: MainAxisAlignment.center,
-                          children: [
-                            FText(
-                              getValues(
-                                e.itemMeta[index].name,
-                              ),
-                              style: const TextStyle(
-                                color: Colors.black,
-                              ),
-                            ),
-                            FText(
-                              e.itemMeta[index].name,
-                              style: const TextStyle(
-                                color: Colors.black,
-                              ),
+                      )
+                    : FElevatedButton(
+                        onPressed: () {
+                          addChooseMeasure(
+                            e.name ?? '',
+                          );
+                        },
+                        style: ButtonStyle(
+                          backgroundColor: MaterialStateProperty.all(
+                            Colors.white,
+                          ),
+                        ),
+                        child: FContainer(
+                          width: 180,
+                          height: 60,
+                          child: FCenter(
+                            child: FColumn(
+                              mainAxisAlignment: MainAxisAlignment.center,
+                              children: [
+                                FText(
+                                  getValues(
+                                    e.name ?? '',
+                                  ),
+                                  style: const TextStyle(
+                                    color: Colors.black,
+                                  ),
+                                ),
+                                FText(
+                                  e.name ?? '',
+                                  style: const TextStyle(
+                                    color: Colors.black,
+                                  ),
+                                ),
+                              ],
                             ),
-                          ],
+                          ),
                         ),
                       ),
-                    ),
-                  );
-          },
-        ),
-      ),
+              )
+              .toList()
+
+          // List<FWidget>.generate(
+          //   e.itemMeta.length,
+          //   (index) {
+          //     return widget.chooseMeasureList.contains(
+          //       e.itemMeta[index].name,
+          //     )
+          //         ? FElevatedButton(
+          //             onPressed: () {
+          //               removeChooseMeasure(
+          //                 e.itemMeta[index].name ?? '',
+          //               );
+          //             },
+          //             style: const ButtonStyle(),
+          //             child: FContainer(
+          //               width: 180,
+          //               height: 60,
+          //               child: FCenter(
+          //                 child: FColumn(
+          //                   mainAxisAlignment: MainAxisAlignment.center,
+          //                   children: [
+          //                     FText(
+          //                       getValues(
+          //                         e.itemMeta[index].name ?? '',
+          //                       ),
+          //                       style: const TextStyle(
+          //                         color: Colors.white,
+          //                       ),
+          //                     ),
+          //                     FText(
+          //                       e.itemMeta[index].name ?? '',
+          //                       style: const TextStyle(
+          //                         color: Colors.white,
+          //                       ),
+          //                     ),
+          //                   ],
+          //                 ),
+          //               ),
+          //             ),
+          //           )
+          //         : FElevatedButton(
+          //             onPressed: () {
+          //               addChooseMeasure(
+          //                 e.itemMeta[index].name ?? '',
+          //               );
+          //             },
+          //             style: ButtonStyle(
+          //               backgroundColor: MaterialStateProperty.all(
+          //                 Colors.white,
+          //               ),
+          //             ),
+          //             child: FContainer(
+          //               width: 180,
+          //               height: 60,
+          //               child: FCenter(
+          //                 child: FColumn(
+          //                   mainAxisAlignment: MainAxisAlignment.center,
+          //                   children: [
+          //                     FText(
+          //                       getValues(
+          //                         e.itemMeta[index].name ?? '',
+          //                       ),
+          //                       style: const TextStyle(
+          //                         color: Colors.black,
+          //                       ),
+          //                     ),
+          //                     FText(
+          //                       e.itemMeta[index].name ?? '',
+          //                       style: const TextStyle(
+          //                         color: Colors.black,
+          //                       ),
+          //                     ),
+          //                   ],
+          //                 ),
+          //               ),
+          //             ),
+          //           );
+          //   },
+          ),
     );
   }
 }

+ 26 - 46
lib/view/measure/measure_tool.dart

@@ -1,12 +1,11 @@
 import 'package:fis_common/logger/logger.dart';
 import 'package:fis_measure/interfaces/process/items/item.dart';
 import 'package:fis_measure/interfaces/process/items/item_metas.dart';
-import 'package:fis_measure/interfaces/process/items/terms.dart';
 import 'package:fis_measure/interfaces/process/player/play_controller.dart';
 import 'package:fis_measure/interfaces/process/workspace/application.dart';
-import 'package:fis_measure/process/items/item_meta_convert.dart';
 import 'package:fis_measure/process/workspace/measure_data_controller.dart';
 import 'package:fis_measure/process/workspace/measure_handler.dart';
+import 'package:fis_measure/view/measure/measure_view_controller.dart';
 import 'package:fis_measure/view/player/controller.dart';
 import 'package:fis_ui/index.dart';
 import 'package:flutter/material.dart';
@@ -30,6 +29,9 @@ class LeftSiderSelectMeasureState extends FState<LeftSiderSelectMeasure> {
   /// 数据
   late final measureData = Get.find<MeasureDataController>();
   final playerController = Get.find<IPlayerController>() as VidPlayerController;
+
+  /// 测量项控制器
+  final measureMetaController = Get.find<MeasureMetaController>();
   // final topMeasureItem = Get.put<ITopMeasureItem>();
 
   /// 当前选中的测量项目
@@ -112,46 +114,11 @@ class LeftSiderSelectMeasureState extends FState<LeftSiderSelectMeasure> {
           measureApplicationDTO.version ?? '';
       measureData.availableModes = measureApplicationDTO.availableModes ?? [];
 
-      ///模式列表
-      var models = measureApplicationDTO.availableModes;
-      if (models != null && models.isNotEmpty) {
-        ///群组列表
-        var groups = models[0].availableGroups;
-        if (groups != null && groups.isNotEmpty) {
-          ///项目列表
-          var folders = groups[0].availableFolders;
-          if (folders != null && folders.isNotEmpty) {
-            measureData.getMeasureApplicationList =
-                folders[0].workingItemNames ?? [];
-            if (folders[0].availableItems != null) {
-              measureData.itemMetaList = folders[0]
-                  .availableItems!
-                  // 排除不支持的测量项
-                  .where((element) =>
-                      !MeasureUnsupportedTerms.items.contains(element.name))
-                  .map((element) {
-                    try {
-                      return ItemMetaConverter(element).output();
-                    } catch (e) {
-                      logger.e(
-                        "Item meta -[${element.name}] convert error; JSON-Text: ${element.toJson()}",
-                        e,
-                      );
-                      return null;
-                    }
-                  })
-                  .where((element) => element != null)
-                  .map((e) => e!)
-                  .toList();
-              comboList();
-            }
-            print('测量方法集: ${measureData.getMeasureApplicationList.toString()}');
-            if (measureData.getMeasureApplicationList.isNotEmpty) {
-              changeItem(measureData.getItemMetaList[0]);
-            }
-          }
-        }
-      }
+      measureMetaController.setAvailableModes(measureData.currentMode);
+
+      activeName = measureData.getItemMetaList[0].name;
+      // measureMetaController.measureConfig();
+      setState(() {});
     }
     getNoteCommentsList();
   }
@@ -174,7 +141,13 @@ class LeftSiderSelectMeasureState extends FState<LeftSiderSelectMeasure> {
   }
 
   void getItemMetaListChanged(sender, e) {
+    print('getItemMetaList changed');
+    isCombo = false;
     measureData.getTopItemMetaList = measureData.getItemMetaList;
+    measureData.getBottomItemMetaList = [];
+    if (measureData.getItemMetaList.isNotEmpty) {
+      changeItem(measureData.getItemMetaList[0]);
+    }
     setState(() {});
   }
 
@@ -236,13 +209,20 @@ class LeftSiderSelectMeasureState extends FState<LeftSiderSelectMeasure> {
     List<ItemMeta> bottom = [];
     List<ItemMeta> getItemMetaList = measureData.getItemMetaList;
     for (int i = 0; i < getItemMetaList.length; i++) {
-      if (i <= getItemMetaList.indexOf(itemMeta)) {
+      int indexOfItemMeta = getItemMetaList.indexOf(itemMeta);
+      if (i <= indexOfItemMeta && indexOfItemMeta % 2 != 0) {
+        top.add(getItemMetaList[i]);
+      } else if (i > indexOfItemMeta && indexOfItemMeta % 2 != 0) {
+        bottom.add(getItemMetaList[i]);
+      }
+      if (indexOfItemMeta % 2 == 0 && i <= indexOfItemMeta + 1) {
         top.add(getItemMetaList[i]);
-      } else {
+      }
+      if (indexOfItemMeta % 2 == 0 && i > indexOfItemMeta + 1) {
         bottom.add(getItemMetaList[i]);
       }
-      measureData.getTopItemMetaList = top;
-      measureData.getBottomItemMetaList = bottom;
+      measureData.getTopItemMetaList = top.toSet().toList();
+      measureData.getBottomItemMetaList = bottom.toSet().toList();
       if (i == getItemMetaList.indexOf(itemMeta)) {
         comboItemMeta = getItemMetaList[i];
         comboItemMetaActivedIndex = 0;

+ 9 - 49
lib/view/measure/measure_tools_title.dart

@@ -1,9 +1,9 @@
 import 'package:fis_measure/interfaces/process/items/item_metas.dart';
 import 'package:fis_measure/interfaces/process/visuals/visual_area.dart';
 import 'package:fis_measure/interfaces/process/workspace/application.dart';
-import 'package:fis_measure/process/items/item_meta_convert.dart';
 import 'package:fis_measure/process/workspace/measure_data_controller.dart';
 import 'package:fis_measure/process/workspace/measure_handler.dart';
+import 'package:fis_measure/view/measure/measure_view_controller.dart';
 import 'package:fis_ui/index.dart';
 import 'package:flutter/material.dart';
 import 'package:get/get.dart';
@@ -25,6 +25,9 @@ class _LeftMeasureToolsState extends State<LeftMeasureTools> {
   /// 数据
   late final measureData = Get.find<MeasureDataController>();
 
+  /// 测量项控制器
+  final measureMetaController = Get.find<MeasureMetaController>();
+
   void changeItem(ItemMeta itemMeta) {
     application.switchItem(itemMeta);
     if (mounted) {
@@ -40,54 +43,10 @@ class _LeftMeasureToolsState extends State<LeftMeasureTools> {
 
   void visualAreaChanged(sender, IVisualArea e) {
     if (mounted) {
-      setAvailableModes(e.mode.modeType.toString().split('.')[1]);
-    }
-  }
-
-  /// 获取组合测量项
-  void comboList() {
-    /// 格式化数据
-    List<ItemMeta> itemMetaList = [];
-    for (var element in measureData.itemMetaList) {
-      if (measureData.getMeasureApplicationList.contains(element.name)) {
-        itemMetaList.add(element);
-      }
-    }
-    measureData.getItemMetaList = itemMetaList;
-  }
-
-  void setAvailableModes(String name) {
-    var models = measureData.availableModes;
-    measureData.currentMode = name;
-    if (models.isNotEmpty) {
-      ///群组列表
-      var groups = models
-          .firstWhereOrNull(
-              (element) => element.modeName == measureData.currentMode)
-          ?.availableGroups;
-
-      if (groups != null && groups.isNotEmpty) {
-        ///项目列表
-        var folders = groups[0].availableFolders;
-        if (folders != null && folders.isNotEmpty) {
-          measureData.getMeasureApplicationList =
-              folders[0].workingItemNames ?? [];
-          if (folders[0].availableItems != null) {
-            measureData.itemMetaList = folders[0]
-                .availableItems!
-                .where((element) => element.name != 'PSAD')
-                .map((element) {
-              return ItemMetaConverter(element).output();
-            }).toList();
-            comboList();
-          }
-          if (measureData.getMeasureApplicationList.isNotEmpty) {
-            changeItem(measureData.getItemMetaList[0]);
-          }
-        }
-      }
+      measureMetaController
+          .setAvailableModes(e.mode.modeType.toString().split('.')[1]);
+      setState(() {});
     }
-    setState(() {});
   }
 
   @override
@@ -123,7 +82,8 @@ class _LeftMeasureToolsState extends State<LeftMeasureTools> {
 
           return FInkWell(
             onTap: () {
-              setAvailableModes(e.value.type.name);
+              measureMetaController.setAvailableModes(e.value.type.name);
+              measureData.getTopItemMetaList = measureData.getItemMetaList;
               setState(() {});
             },
             child: FContainer(

+ 4 - 0
lib/view/measure/measure_view.dart

@@ -20,6 +20,7 @@ import 'package:fis_measure/view/measure/measure_search_input.dart';
 import 'package:fis_measure/view/measure/measure_tool.dart';
 import 'package:fis_measure/view/measure/carotid_measure_tool.dart';
 import 'package:fis_measure/view/measure/measure_tools_title.dart';
+import 'package:fis_measure/view/measure/measure_view_controller.dart';
 import 'package:fis_measure/view/measure/tool_chest_title.dart';
 import 'package:fis_measure/view/player/control_board/operate_bar.dart';
 import 'package:fis_ui/index.dart';
@@ -52,6 +53,9 @@ class _MeasureMainPageState extends State<MeasureMainPage> {
 
   final mouseState = Get.put<IMouseState>(MouseState());
 
+  /// 测量项控制器
+  final measureMetaController = Get.put(MeasureMetaController());
+
   /// 页面loadding
   bool loaded = false;
 

+ 154 - 0
lib/view/measure/measure_view_controller.dart

@@ -0,0 +1,154 @@
+import 'package:fis_common/logger/logger.dart';
+import 'package:fis_jsonrpc/rpc.dart';
+import 'package:fis_measure/interfaces/process/items/item_metas.dart';
+import 'package:fis_measure/interfaces/process/items/terms.dart';
+import 'package:fis_measure/interfaces/process/workspace/application.dart';
+import 'package:fis_measure/process/items/item_meta_convert.dart';
+import 'package:fis_measure/process/workspace/measure_data_controller.dart';
+import 'package:fis_measure/process/workspace/measure_handler.dart';
+import 'package:fis_measure/view/measure/measure_config/measure_configuation_page.dart';
+import 'package:get/get.dart';
+
+class MeasureMetaController extends GetxController {
+  /// 数据
+  late final measureData = Get.find<MeasureDataController>();
+  late final application = Get.find<IApplication>();
+  late final measureHandler = Get.find<MeasureHandler>();
+
+  /// 跟超声机端保持一致,配置 项目写死
+  List<ItemMetaGroup> getMeasureConfigurationGroupName() {
+    return [
+      ItemMetaGroup('Common', [], true),
+      ItemMetaGroup('ABD', [], true),
+      ItemMetaGroup('CARD', [], true),
+      ItemMetaGroup('GYN', [], true),
+      ItemMetaGroup('OB', [], true),
+      ItemMetaGroup('VAS', [], true),
+    ];
+  }
+
+  /// 获取组合测量项
+  void comboList() {
+    /// 格式化数据
+    List<ItemMeta> itemMetaList = [];
+    for (var element in measureData.itemMetaList) {
+      if (measureData.getMeasureApplicationList.contains(element.name)) {
+        itemMetaList.add(element);
+      }
+    }
+    measureData.getItemMetaList = itemMetaList;
+  }
+
+  void setAvailableModes(String name) {
+    print('切换模式到:' + name);
+    var models = measureData.availableModes;
+    measureData.currentMode = name;
+    if (models.isNotEmpty) {
+      ///群组列表
+      var groups = models
+          .firstWhereOrNull(
+              (element) => element.modeName == measureData.currentMode)
+          ?.availableGroups;
+
+      if (groups != null && groups.isNotEmpty) {
+        ///项目列表
+        var folders = groups[0].availableFolders;
+        if (folders != null && folders.isNotEmpty) {
+          measureData.getMeasureApplicationList =
+              folders[0].workingItemNames ?? [];
+          if (folders[0].availableItems != null) {
+            measureData.itemMetaList = folders[0]
+                .availableItems!
+                // 排除不支持的测量项
+                .where((element) =>
+                    !MeasureUnsupportedTerms.items.contains(element.name))
+                .map((element) {
+                  try {
+                    return ItemMetaConverter(element).output();
+                  } catch (e) {
+                    logger.e(
+                      "Item meta -[${element.name}] convert error; JSON-Text: ${element.toJson()}",
+                      e,
+                    );
+                    return null;
+                  }
+                })
+                .where((element) => element != null)
+                .map((e) => e!)
+                .toList();
+            comboList();
+          }
+          if (measureData.getMeasureApplicationList.isNotEmpty) {
+            changeItem(measureData.getItemMetaList[0]);
+          }
+        }
+      }
+    }
+  }
+
+  // /// 获取当前图像的测量项,从第一帧取
+  // void currentFrameHandler(Object sender, VidUsImage e) async {
+  //   List<String> getModes = [];
+  //   for (var element in e.visuals[0].modes) {
+  //     getModes.add(element.type.toString().split('.')[1]);
+  //   }
+  //   measureData.applicationModes = e.visuals[0].modes;
+  //   measureData.currentMode = e.visuals[0].modes.first.type.name;
+  //   var measureModeSelection = MeasureModeSelection(
+  //     application.applicationName,
+  //     application.categoryName,
+  //     application.isThirdPart ? ['TPPTissue'] : getModes,
+  //   );
+  //   measureHandler.measureModeChanged = measureModeSelection;
+  //   var measureApplicationDTO =
+  //       await measureData.getMeasureApplication.call(measureModeSelection);
+  //   if (measureApplicationDTO != null) {
+  //     /// 模式版本
+  //     measureData.measureApplicationVersion =
+  //         measureApplicationDTO.version ?? '';
+  //     measureData.availableModes = measureApplicationDTO.availableModes ?? [];
+
+  //     setAvailableModes(measureData.currentMode);
+
+  //     activeName = measureData.getItemMetaList[0].name;
+  //     measureConfig();
+  //   }
+  //   getNoteCommentsList();
+  // }
+
+  /// 测量项配置组
+  void measureConfig() {
+    List<ItemMetaGroup> _itemMetaConfigurationList = [];
+    Map<String, List<ItemMetaDTO>> _group = {};
+    getMeasureConfigurationGroupName().forEach(
+      ((element) {
+        List<ItemMetaDTO> itemMetaListGroupItem = [];
+        print(measureData.currentMode);
+        var groups = measureData.availableModes
+            .firstWhereOrNull(
+                (element) => element.modeName == measureData.currentMode)
+            ?.availableGroups;
+        (groups![0].availableFolders![0].availableItems)?.toList().forEach(
+          (e) {
+            if (e.categories!.toList().contains(element.itemMetaGroupTitle)) {
+              itemMetaListGroupItem.add(e);
+            }
+            _group[element.itemMetaGroupTitle] = itemMetaListGroupItem;
+          },
+        );
+      }),
+    );
+    _group.forEach(
+      (key, value) {
+        _itemMetaConfigurationList.add(
+          ItemMetaGroup(key, value, true),
+        );
+      },
+    );
+    measureData.itemMetaListGroup = _itemMetaConfigurationList;
+  }
+
+  void changeItem(ItemMeta itemMeta) {
+    application.switchItem(itemMeta);
+  }
+}

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff