Browse Source

Merge remote-tracking branch 'origin/master' into feature/gavin_webview_0817

# Conflicts:
#	lib/view/measure/measure_main_view.dart
gavin.chen 2 năm trước cách đây
mục cha
commit
4ec222dd66

+ 0 - 1
lib/process/workspace/measure_controller.dart

@@ -14,7 +14,6 @@ import 'package:fis_common/event/event_type.dart';
 import 'package:flutter/foundation.dart';
 import 'package:get/get.dart';
 import 'package:vid/us/vid_us_image.dart';
-import 'package:fis_vid_ext/vid_extended_data.dart';
 
 typedef MeasureImagesFetchFunc = Future<List<ExamImageInfo>> Function(
     String code);

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

@@ -69,6 +69,11 @@ abstract class IMeasureHandler {
   /// 注释箭头还是标签
   late FEventHandler<AnnotationType> onChangedAnnotationType;
 
+  /// 图片加载loadding
+  late FEventHandler<bool> onChangeImageLoaded;
+
+  late FEventHandler<bool> onChangeFullScreenState;
+
   /// 切换图像传递数据
   ChangeImageInfo get imageChanged;
   set imageChanged(ChangeImageInfo value);
@@ -88,6 +93,14 @@ abstract class IMeasureHandler {
   /// 切换注释
   AnnotationType get changedAnnotationType;
   set changedAnnotationType(AnnotationType value);
+
+  /// 切换图片
+  bool get changeImageLoaded;
+  set changeImageLoaded(bool value);
+
+  /// 全屏状态
+  bool get fullScreenState;
+  set fullScreenState(bool value);
 }
 
 class MeasureHandler implements IMeasureHandler {
@@ -100,6 +113,10 @@ class MeasureHandler implements IMeasureHandler {
 
   TagEnum _changedTab = TagEnum.MeasureTool;
 
+  bool _changeImageLoaded = true;
+
+  bool _fullScreenState = false;
+
   AnnotationType _changedAnnotationType = AnnotationType.label;
   @override
   var onImageChanged = FEventHandler<ChangeImageInfo>();
@@ -114,6 +131,11 @@ class MeasureHandler implements IMeasureHandler {
 
   @override
   var onChangedAnnotationType = FEventHandler<AnnotationType>();
+  @override
+  FEventHandler<bool> onChangeImageLoaded = FEventHandler<bool>();
+
+  @override
+  FEventHandler<bool> onChangeFullScreenState = FEventHandler<bool>();
 
   @override
   ChangeImageInfo get imageChanged => _imageChanged;
@@ -129,6 +151,28 @@ class MeasureHandler implements IMeasureHandler {
 
   @override
   AnnotationType get changedAnnotationType => _changedAnnotationType;
+
+  @override
+  bool get changeImageLoaded => _changeImageLoaded;
+
+  @override
+  bool get fullScreenState => _fullScreenState;
+  @override
+  set fullScreenState(bool value) {
+    if (value != _fullScreenState) {
+      _fullScreenState = value;
+      _onChangeFullScreenState();
+    }
+  }
+
+  @override
+  set changeImageLoaded(bool value) {
+    if (value != _changeImageLoaded) {
+      _changeImageLoaded = value;
+      _onChangeImageLoaded();
+    }
+  }
+
   @override
   set changedTab(TagEnum value) {
     if (value != _changedTab) {
@@ -185,6 +229,14 @@ class MeasureHandler implements IMeasureHandler {
     onChangedTab.emit(this, changedTab);
   }
 
+  void _onChangeImageLoaded() {
+    onChangeImageLoaded.emit(this, changeImageLoaded);
+  }
+
+  void _onChangeFullScreenState() {
+    onChangeFullScreenState.emit(this, fullScreenState);
+  }
+
   void _onChangedAnnotation() {
     onChangedAnnotationType.emit(this, changedAnnotationType);
   }

+ 80 - 46
lib/view/button_group/button_group.dart

@@ -1,4 +1,6 @@
+import 'package:fis_measure/interfaces/process/standard_line/calibration.dart';
 import 'package:fis_measure/interfaces/process/workspace/application.dart';
+import 'package:fis_measure/process/workspace/measure_handler.dart';
 import 'package:fis_ui/index.dart';
 import 'package:flutter/material.dart';
 import 'package:get/get.dart';
@@ -19,7 +21,7 @@ class _ButtonGroupState extends State<ButtonGroup> {
   bool _isExpanded = false;
   final _key = GlobalKey();
   final application = Get.find<IApplication>();
-
+  late final measureHandler = Get.find<MeasureHandler>();
   Future<bool> _showList() async {
     await Future.delayed(const Duration(milliseconds: 300));
     return true;
@@ -31,59 +33,92 @@ class _ButtonGroupState extends State<ButtonGroup> {
     return Row(
       mainAxisAlignment: MainAxisAlignment.end,
       children: [
-        AnimatedContainer(
-          duration: const Duration(milliseconds: 300),
-          padding: const EdgeInsets.only(
-            top: 5,
-            bottom: 5,
-            left: 15,
-          ),
-          decoration: BoxDecoration(
-            borderRadius: const BorderRadius.only(
-              topLeft: Radius.circular(4),
-              bottomLeft: Radius.circular(4),
+        InkWell(
+          onTap: () {},
+          onHover: (isHover) {
+            if (!isHover) {
+              setState(() {
+                _width = 0;
+                _isExpanded = isHover;
+              });
+            } else {
+              setState(() {
+                application.isThirdPart ? _width = 270 : _width = 220;
+                _isExpanded = isHover;
+              });
+            }
+          },
+          child: AnimatedContainer(
+            duration: const Duration(milliseconds: 300),
+            padding: const EdgeInsets.only(
+              top: 5,
+              bottom: 5,
+              left: 15,
             ),
-            color: Colors.grey.withOpacity(0.6),
+            decoration: BoxDecoration(
+              borderRadius: const BorderRadius.only(
+                topLeft: Radius.circular(4),
+                bottomLeft: Radius.circular(4),
+              ),
+              color: Colors.grey.withOpacity(0.6),
+            ),
+            width: _width,
+            height: 60,
+            child: _isExpanded
+                ? FutureBuilder(
+                    future: _showList(),
+                    builder: (context, snapshot) {
+                      if (!snapshot.hasData) {
+                        return const SizedBox();
+                      }
+                      return Row(
+                        children: [
+                          _buildTitleButton(FIcons.fis_quash, '撤销',
+                              () => application.undoRecord()),
+                          _buildTitleButton(FIcons.fis_purge, '清除',
+                              () => application.clearRecords()),
+                          _buildTitleButton(FIcons.fis_full_screen, '全屏', () {
+                            measureHandler.fullScreenState =
+                                !measureHandler.fullScreenState;
+                          }),
+                          _buildTitleButton(
+                              FIcons.fis_save, '保存', widget.capturePng),
+                          _buildTitleButton(
+                            FIcons.fis_share,
+                            '分享',
+                            () {
+                              print('分享');
+                            },
+                          ),
+                          application.isThirdPart
+                              ? _buildTitleButton(
+                                  FIcons.device,
+                                  '校准线',
+                                  () {
+                                    Get.find<
+                                            IStandardLineCalibrationController>()
+                                        .enterEditMode();
+                                  },
+                                )
+                              : const SizedBox(),
+                        ],
+                      );
+                    })
+                : const SizedBox(),
           ),
-          width: _width,
-          height: 60,
-          child: _isExpanded
-              ? FutureBuilder(
-                  future: _showList(),
-                  builder: (context, snapshot) {
-                    if (!snapshot.hasData) {
-                      return const SizedBox();
-                    }
-                    return Row(
-                      children: [
-                        _buildTitleButton(FIcons.fis_quash, '撤销',
-                            () => application.undoRecord()),
-                        _buildTitleButton(FIcons.fis_purge, '清除',
-                            () => application.clearRecords()),
-                        _buildTitleButton(FIcons.fis_full_screen, '全屏', () {
-                          print('全屏');
-                        }),
-                        _buildTitleButton(
-                            FIcons.fis_save, '保存', widget.capturePng),
-                        _buildTitleButton(FIcons.fis_share, '分享', () {
-                          print('分享');
-                        }),
-                      ],
-                    );
-                  })
-              : const SizedBox(),
         ),
         InkWell(
-          onTap: () {
-            if (!_isExpanded) {
+          onTap: () {},
+          onHover: (isHover) {
+            if (isHover) {
               setState(() {
-                _width = 220;
-                _isExpanded = true;
+                application.isThirdPart ? _width = 270 : _width = 220;
+                _isExpanded = isHover;
               });
             } else {
               setState(() {
                 _width = 0;
-                _isExpanded = false;
+                _isExpanded = isHover;
               });
             }
           },
@@ -96,7 +131,6 @@ class _ButtonGroupState extends State<ButtonGroup> {
           ),
         ),
       ],
-      // ),
     );
   }
 

+ 86 - 24
lib/view/measure/measure_main_view.dart

@@ -1,4 +1,3 @@
-import 'dart:convert';
 import 'dart:ui';
 
 import 'package:fis_jsonrpc/rpc.dart';
@@ -10,6 +9,7 @@ import 'package:fis_measure/interfaces/process/workspace/application.dart';
 import 'package:fis_measure/interfaces/process/workspace/measure_3d_view_controller.dart';
 import 'package:fis_measure/process/workspace/measure_3d_view_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/third_part/application.dart';
 import 'package:fis_measure/process/workspace/third_part/calibration_controller.dart';
 import 'package:fis_measure/utils/canvas.dart';
@@ -23,7 +23,7 @@ import 'package:fis_measure/view/paint/ai_patint_result.dart';
 import 'package:fis_measure/view/result/results_panel.dart';
 import 'package:fis_measure/view/standard_line/calibration_canvas.dart';
 import 'package:fis_measure/view/standard_line/calibration_gesture.dart';
-import 'package:fis_ui/define.dart';
+import 'package:fis_ui/index.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/rendering.dart';
 import 'package:get/get.dart';
@@ -48,6 +48,7 @@ class _MeasureMainViewState extends State<MeasureMainView> {
 
   late final playerController = Get.find<IPlayerController>();
   late final measure3DViewController = Get.find<Measure3DViewController>();
+  late final measureHandler = Get.find<MeasureHandler>();
 
   /// 测量数据
   final measureData = Get.find<MeasureDataController>();
@@ -56,6 +57,7 @@ class _MeasureMainViewState extends State<MeasureMainView> {
 
   late bool enableCarotid2DMeasure = false;
   bool isCaptureState = false;
+  late double calibrationLine = 4;
 
   /// 是否显示进度条
   bool ifShowProgressBar = true;
@@ -148,9 +150,9 @@ class _MeasureMainViewState extends State<MeasureMainView> {
     }
   }
 
+  /// 保存图片
   void capturePng() async {
     isCaptureState = true;
-
     setState(() {});
     await Future.delayed(const Duration(milliseconds: 10), () async {
       final RenderRepaintBoundary? boundary =
@@ -160,36 +162,28 @@ class _MeasureMainViewState extends State<MeasureMainView> {
         final image = await boundary.toImage();
         final byteData = await image.toByteData(format: ImageByteFormat.png);
         final pngBytes = byteData!.buffer.asUint8List();
-        final base64 = base64Encode(pngBytes);
+        Get.dialog(
+          CaptureImage(
+            bytes: pngBytes,
+          ),
+          transitionCurve: Curves.bounceInOut,
+        );
         await measureData.saveImage.call(
           pngBytes,
           measureData.measureImageData.patientCode ?? '',
           measureData.measureImageData.recordCode ?? '',
           measureData.measureImageData.remedicalCode ?? '',
         );
-        print('data:image/png;base64,' + base64);
         isCaptureState = false;
-        Get.dialog(
-          CaptureImage(
-            bytes: pngBytes,
-          ),
-          transitionDuration: const Duration(milliseconds: 600),
-          transitionCurve: Curves.bounceInOut,
-        );
         Future.delayed(
           const Duration(
-            milliseconds: 1600,
+            milliseconds: 600,
           ),
           () {
             Get.back();
           },
         );
         setState(() {});
-        ScaffoldMessenger.of(context).showSnackBar(
-          const SnackBar(
-            content: Text("Success! See console."),
-          ),
-        );
       }
     });
   }
@@ -210,15 +204,83 @@ class _MeasureMainViewState extends State<MeasureMainView> {
       Object sender, StandardLineCalibrationEditState e) {
     setState(() {
       if (e == StandardLineCalibrationEditState.drawn) {
-        //TODO: 弹窗输入
-        Future.delayed(const Duration(seconds: 1), () {
-          standardLineCalibrationController!.confirmEdit(4);
-          // standardLineCalibrationController!.cancelEdit();
-        });
+        Get.dialog(buildCalibrationLine());
       }
     });
   }
 
+  /// TODO 翻译
+  FWidget buildCalibrationLine() {
+    return FSimpleDialog(
+      title: const FText(
+        '参考线校准',
+        style: TextStyle(
+          color: Colors.white,
+          fontSize: 18,
+        ),
+      ),
+      isDefault: true,
+      onOk: () {
+        standardLineCalibrationController!.confirmEdit(calibrationLine);
+        Get.back();
+      },
+      onCancel: () {
+        standardLineCalibrationController!.cancelEdit();
+        Get.back();
+      },
+      children: [
+        buildCalibrationLineItem(
+          '长度',
+          FTextField(
+            decoration: InputDecoration(
+              hintText: '请输入',
+              hintStyle: const TextStyle(
+                fontSize: 16,
+              ),
+              enabledBorder: OutlineInputBorder(
+                borderSide: BorderSide(
+                  color: Colors.white.withOpacity(0.5),
+                  width: 0.5,
+                  style: BorderStyle.solid,
+                ),
+              ),
+              focusedBorder: const OutlineInputBorder(
+                borderSide: BorderSide(
+                  color: Colors.blue,
+                  width: 0.5,
+                  style: BorderStyle.solid,
+                ),
+              ),
+              filled: true,
+            ),
+            onChanged: (val) => calibrationLine = double.parse(val),
+          ),
+        ),
+        buildCalibrationLineItem(
+          '单位',
+          const FText('cm'),
+        ),
+      ],
+    );
+  }
+
+  FWidget buildCalibrationLineItem(String name, FWidget itemWidget) {
+    return FContainer(
+      padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 25),
+      child: FRow(
+        children: [
+          FContainer(
+            width: 60,
+            child: FText(name),
+          ),
+          FExpanded(
+            child: itemWidget,
+          ),
+        ],
+      ),
+    );
+  }
+
   @override
   Widget build(BuildContext context) {
     MeasureCanvasExt.setFontFamily(
@@ -301,7 +363,7 @@ class _MeasureMainViewState extends State<MeasureMainView> {
                       ),
                     ),
                   ),
-                  if (canShowAI) ...[
+                  if (canShowAI && !measureHandler.fullScreenState) ...[
                     SizedBox(
                       width: 200,
                       child: AIPaintInfoReslut(

+ 1 - 39
lib/view/measure/measure_tool.dart

@@ -88,51 +88,13 @@ class LeftSiderSelectMeasureState extends FState<LeftSiderSelectMeasure> {
     setState(() {});
   }
 
-  Future<void> getName() async {
-    var measureModeSelection = MeasureModeSelection(
-      application.applicationName,
-      application.categoryName,
-      application.isThirdPart ? ['TPPTissue'] : [activeMode],
-    );
-    measureHandler.measureModeChanged = measureModeSelection;
-    measureData.getMeasureApplicationList = [];
-    var measureApplicationDTO =
-        await measureData.getMeasureApplication.call(measureModeSelection);
-    if (measureApplicationDTO != null) {
-      /// 模式版本
-      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!.toList();
-            }
-            if (measureData.getMeasureApplicationList.isNotEmpty) {
-              changeItem(measureData.getMeasureApplicationList[0]);
-            }
-          }
-        }
-      }
-    }
-  }
-
   @override
   void initState() {
     application.visualsLoaded.addListener(visualsLoaded);
+
     measureData.itemMetaListChanged.addListener(itemMetaList);
     measureData.getMeasureApplicationChanged
         .addListener(getMeasureApplicationChanged);
-    // getName();
     super.initState();
   }
 

+ 44 - 13
lib/view/measure/measure_view.dart

@@ -1,5 +1,4 @@
 import 'package:fis_jsonrpc/rpc.dart';
-import 'package:fis_measure/index.dart';
 import 'package:fis_measure/interfaces/enums/annotation.dart';
 import 'package:fis_measure/interfaces/process/player/play_controller.dart';
 import 'package:fis_measure/interfaces/process/workspace/application.dart';
@@ -46,9 +45,17 @@ class _MeasureMainPageState extends State<MeasureMainPage> {
   final measure3DViewController = Get.find<Measure3DViewController>();
   late final application = Get.find<IApplication>();
 
+  /// 页面loadding
+  bool loaded = false;
+
+  // /// 图片loadding
+  late bool imageLoaded = false;
+
   ///检查图片信息表
   List<ExamImageInfo> examImageInfoList = [];
 
+  late final measureHandler = Get.find<MeasureHandler>();
+
   /// 测量控制器
   late MeasureController measureController = Get.put(MeasureController(
     "",
@@ -56,7 +63,6 @@ class _MeasureMainPageState extends State<MeasureMainPage> {
       return examImageInfoList;
     },
   ));
-  bool loaded = false;
 
   /// 获取测量图片所需的图片组 并且写入控制器中 加载
   void getExamImageInfoList(List<RemedicalInfoDTO> remedicals) async {
@@ -88,10 +94,21 @@ class _MeasureMainPageState extends State<MeasureMainPage> {
     }
   }
 
+  void changeImage(sender, e) {
+    imageLoaded = e;
+    setState(() {});
+  }
+
+  void changeFullScreenState(sender, e) {
+    setState(() {});
+  }
+
   @override
   void initState() {
     loadLayoutConfig();
     getImageInfo();
+    measureHandler.onChangeImageLoaded.addListener(changeImage);
+    measureHandler.onChangeFullScreenState.addListener(changeFullScreenState);
     super.initState();
   }
 
@@ -113,16 +130,16 @@ class _MeasureMainPageState extends State<MeasureMainPage> {
   }
 
   void onImageLoaded(Object sender, ExamImageInfo? e) async {
+    measureHandler.changeImageLoaded = true;
     if (!mounted) return;
-    setState(() {
-      loaded = true;
-    });
     final currentImage = measureData.remedicalList.firstWhereOrNull(
         (element) => element.terminalImages!.imageUrl == e!.url);
     if (currentImage != null) {
-      loaded = false;
+      /// 获取图片详细信息
       var remedicalInfo = await measureData.getImageInfo(
-          currentImage.remedicalCode ?? '', widget.token);
+        currentImage.remedicalCode ?? '',
+        widget.token,
+      );
       if (remedicalInfo != null) {
         measureData.aiResults = remedicalInfo.diagnosisResult ?? '';
         measure3DViewController.initParams();
@@ -147,11 +164,13 @@ class _MeasureMainPageState extends State<MeasureMainPage> {
             });
             setState(() {
               loaded = true;
+              measureHandler.changeImageLoaded = false;
             });
           }
         } catch (error) {
           setState(() {
             loaded = true;
+            measureHandler.changeImageLoaded = false;
           });
         }
       }
@@ -160,6 +179,9 @@ class _MeasureMainPageState extends State<MeasureMainPage> {
 
   @override
   void dispose() {
+    measureHandler.onChangeImageLoaded.removeListener(changeImage);
+    measureHandler.onChangeFullScreenState
+        .removeListener(changeFullScreenState);
     super.dispose();
   }
 
@@ -178,18 +200,26 @@ class _MeasureMainPageState extends State<MeasureMainPage> {
     } else {
       body = FRow(
         children: [
-          _MeasureLeftBoard(),
+          if (!measureHandler.fullScreenState) _MeasureLeftBoard(),
           const FVerticalDivider(),
           FExpanded(
             child: FColumn(
               mainAxisSize: MainAxisSize.max,
               children: [
                 FExpanded(
-                  child: MeasureRightBoard(
-                    key: ValueKey(measureData.itemCurrentImage),
-                  ),
-                ),
-                const MeasureImagesBar(),
+                    child: FStack(
+                  children: [
+                    if (!imageLoaded)
+                      MeasureRightBoard(
+                        key: ValueKey(measureData.itemCurrentImage),
+                      ),
+                    if (imageLoaded)
+                      const FCenter(
+                        child: FCircularProgressIndicator(),
+                      ),
+                  ],
+                )),
+                if (!measureHandler.fullScreenState) const MeasureImagesBar(),
               ],
             ),
           ),
@@ -209,6 +239,7 @@ class _MeasureMainPageState extends State<MeasureMainPage> {
     List<RemedicalInfoDTO> remedicals = [];
     List<Ultra3DResourceInfo> ultra3DResourceInfos = [];
     loaded = false;
+
     var value = await measureData.getRemedicalList
         .call(widget.patientCode, widget.recordCode, widget.token);
     for (var remedicalItemList in value) {

+ 5 - 0
lib/view/measure/tool_chest_title.dart

@@ -228,6 +228,11 @@ class _LeftMeasureToolsState extends State<_LeftMeasureTools> {
   void initState() {
     super.initState();
     application.visualsLoaded.addListener(visualsLoaded);
+    application.visualAreaChanged.addListener((sender, e) {
+      print(e.mode.modeType.toString().split('.')[1]);
+      getName(e.mode.modeType.toString().split('.')[1]);
+      // application.switchMode(e.mode.modeType.toString().split('.')[1]);
+    });
   }
 
   @override

+ 9 - 1
lib/view/paint/ai_patint.dart

@@ -34,6 +34,7 @@ class _AIPaintInfoState extends State<AIPaintInfo> {
       widget.controller,
     ),
   );
+  late bool isShowAiResult;
 
   /// 播放控制器
   final playerController = Get.find<IPlayerController>();
@@ -108,7 +109,14 @@ class _AIPaintInfoState extends State<AIPaintInfo> {
               late final frameDataWidth =
                   aiPatintController.application.frameData?.width;
               late final widthScale = (canvasWidth / frameDataWidth!);
-              if (!aiPatintController.onGetAIResultsInfo(widthScale)) {
+              try {
+                isShowAiResult =
+                    aiPatintController.onGetAIResultsInfo(widthScale);
+              } catch (e) {
+                isShowAiResult = true;
+              }
+
+              if (!isShowAiResult) {
                 return const SizedBox();
               } else {
                 return CustomMultiChildLayout(

+ 13 - 8
lib/view/paint/ai_patint_controller.dart

@@ -176,16 +176,17 @@ class AiPatintController extends GetxController {
           detectedObjects,
           widthScale,
         );
+        return true;
       } else {
         return false;
       }
-      return true;
     } else {
       updateFeatures();
-      final diagResultsForEachOrgan = state.aiResult[state.frameIndex!]
-          .diagResultsForEachOrgan![state.aiResultIndex];
-      diagnosisOrgan = diagResultsForEachOrgan.organ;
-      final detectedObjects = diagResultsForEachOrgan.detectedObjects;
+      final diagResultsForEachOrgan = state.aiResult[state.frameIndex]
+          .diagResultsForEachOrgan?[state.aiResultIndex];
+      diagnosisOrgan =
+          diagResultsForEachOrgan?.organ ?? DiagnosisOrganEnum.Null;
+      final detectedObjects = diagResultsForEachOrgan?.detectedObjects;
       if (state.vidStatus == VidPlayStatus.pause) {
         if (detectedObjects!.isNotEmpty) {
           onSingleFrameImage(
@@ -193,9 +194,10 @@ class AiPatintController extends GetxController {
             widthScale,
           );
         }
+        return true;
       } else if (state.vidStatus == VidPlayStatus.play) {
-        if (detectedObjects!.isNotEmpty) {
-          for (int m = 0; m < detectedObjects.length; m++) {
+        if (detectedObjects?.isNotEmpty ?? false) {
+          for (int m = 0; m < detectedObjects!.length; m++) {
             final organBoundBox =
                 detectedObjects[m].boundingBox ?? AIDiagnosisRect();
 
@@ -204,9 +206,12 @@ class AiPatintController extends GetxController {
             width = organBoundBox.width * widthScale;
             height = organBoundBox.height * widthScale;
           }
+          return true;
+        } else {
+          return false;
         }
       }
-      return true;
+      return false;
     }
   }
 

+ 10 - 3
lib/view/paint/ai_patint_result.dart

@@ -1,3 +1,4 @@
+import 'package:fis_jsonrpc/rpc.dart';
 import 'package:fis_measure/view/paint/ai_patint_controller.dart';
 import 'package:fis_measure/view/paint/parts/ai_result.dart';
 import 'package:fis_measure/view/player/controller.dart';
@@ -29,6 +30,7 @@ class _AIPaintInfoState extends State<AIPaintInfoReslut> {
       widget.controller,
     ),
   );
+  late bool isShowAiResult;
 
   void onControllerEvent(Object sender, VidPlayerEvent e) {
     if (e is VidPlayerStatusChangeEvent) {
@@ -81,17 +83,22 @@ class _AIPaintInfoState extends State<AIPaintInfoReslut> {
   @override
   Widget build(BuildContext context) {
     Widget? child;
-
     if (widget.controller.status == VidPlayStatus.pause) {
       child = LayoutBuilder(builder: (context, constraints) {
         final canvasWidth = constraints.maxWidth;
         late final frameDataWidth =
             aiPatintController.application.frameData?.width;
         late final widthScale = (canvasWidth / frameDataWidth!);
-        if (!aiPatintController.onGetAIResultsInfo(widthScale)) {
+        try {
+          isShowAiResult = aiPatintController.onGetAIResultsInfo(widthScale);
+        } catch (e) {
+          isShowAiResult = true;
+        }
+        if (!isShowAiResult) {
           return const SizedBox();
         } else {
-          if (aiPatintController.aiDetectedObject.isNotEmpty) {
+          if (isShowAiResult &&
+              aiPatintController.diagnosisOrgan != DiagnosisOrganEnum.Null) {
             return AIResultPanel(
               aiPatintController.aiDetectedObject,
               aiPatintController.diagnosisOrgan,

+ 2 - 2
lib/view/paint/ai_patint_state.dart

@@ -17,8 +17,8 @@ class AiPatintState {
   get frameIndex => _frameIndex.value;
 
   /// 当前ai帧数
-  set aiResultIndex(value) => _aiResultIndex.value = value;
-  get aiResultIndex => _aiResultIndex.value;
+  set aiResultIndex(int value) => _aiResultIndex.value = value;
+  int get aiResultIndex => _aiResultIndex.value;
 
   /// ai结果集合
   set aiResult(List<AIDiagnosisPerImageDTO> value) => _aiResult(value);

+ 5 - 2
lib/view/paint/parts/feature_analysis.dart

@@ -1,14 +1,17 @@
 import 'dart:convert';
 
 import 'package:fis_i18n/i18n.dart';
+import 'package:fis_measure/view/paint/ai_patint_controller.dart';
 import 'package:fis_measure/view/paint/date_structure.dart';
 import 'package:flutter/material.dart';
+import 'package:get/get.dart';
 
 /// 特征分析
 class FeatureAnalysis extends StatelessWidget {
-  const FeatureAnalysis(this.descriptions, {Key? key}) : super(key: key);
+  FeatureAnalysis(this.descriptions, {Key? key}) : super(key: key);
 
   final List<AIDiagnosisDescription>? descriptions;
+  late final aiPatintController = Get.find<AiPatintController>();
   @override
   Widget build(BuildContext context) {
     return Container(
@@ -107,7 +110,7 @@ class FeatureAnalysis extends StatelessWidget {
       case DiagnosisDescriptionEnum.Calcification:
         return i18nBook.measure.calcification.t;
 
-      /// 纵横比
+      /// TODO 翻译 纵横比
       case DiagnosisDescriptionEnum.LesionSize:
         return '横纵比';
       default: