ai_resul_info.dart 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. import 'dart:convert';
  2. import 'package:fis_i18n/i18n.dart';
  3. import 'package:fis_measure/interfaces/process/workspace/application.dart';
  4. import 'package:fis_measure/view/paint/ai_patint_controller.dart';
  5. import 'package:fis_measure/view/paint/date_structure.dart';
  6. import 'package:flutter/material.dart';
  7. import 'package:get/get.dart';
  8. /// AI诊断结果
  9. class ResultInfo extends StatefulWidget {
  10. final List<AIDetectedObject> aiDetectedObject;
  11. const ResultInfo(this.aiDetectedObject, {Key? key}) : super(key: key);
  12. @override
  13. State<ResultInfo> createState() => _ResultInfoState();
  14. }
  15. class _ResultInfoState extends State<ResultInfo> {
  16. late final aiPatintController = Get.find<AiPatintController>();
  17. late AIDetectedObject aiDetectedObjectItem;
  18. late double unitsPhysicalPixels;
  19. late final application = Get.find<IApplication>();
  20. @override
  21. void initState() {
  22. super.initState();
  23. }
  24. @override
  25. Widget build(BuildContext context) {
  26. final description = widget
  27. .aiDetectedObject[aiPatintController.state.aiResultIndex].descriptions;
  28. late final descriptions = (description?.length ?? 0) > 1
  29. ? jsonDecode(description?[description.length - 1].value ?? '')
  30. : '';
  31. unitsPhysicalPixels =
  32. (application.visuals[0].visualAreas[0].viewport?.region.width)! /
  33. (application.frameData!.width).toDouble();
  34. return Container(
  35. decoration: BoxDecoration(
  36. border: Border.all(
  37. color: Colors.grey,
  38. ),
  39. borderRadius: BorderRadius.circular(4),
  40. color: Colors.transparent,
  41. ),
  42. padding: const EdgeInsets.only(bottom: 10),
  43. child: Column(
  44. children: [
  45. Row(
  46. mainAxisSize: MainAxisSize.max,
  47. children: [
  48. Expanded(
  49. child: Container(
  50. decoration: const BoxDecoration(
  51. borderRadius: BorderRadius.only(
  52. topLeft: Radius.circular(4),
  53. topRight: Radius.circular(4),
  54. ),
  55. color: Color.fromRGBO(54, 169, 206, 1),
  56. ),
  57. padding: const EdgeInsets.only(
  58. top: 4,
  59. bottom: 10,
  60. left: 8,
  61. right: 8,
  62. ),
  63. child: const Text(
  64. 'AI诊断结果',
  65. style: TextStyle(
  66. color: Colors.white,
  67. ),
  68. ),
  69. ),
  70. )
  71. ],
  72. ),
  73. Row(
  74. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  75. children: [
  76. Container(
  77. padding: const EdgeInsets.only(
  78. left: 10,
  79. ),
  80. child: Column(
  81. crossAxisAlignment: CrossAxisAlignment.start,
  82. mainAxisAlignment: MainAxisAlignment.start,
  83. children: [
  84. _buildTitle(
  85. i18nBook.measure.diseaseLabels.t,
  86. _buildAITitle(),
  87. ),
  88. if (descriptions != '' && descriptions != null)
  89. _buildTitle(
  90. i18nBook.measure.isLesionSize.t,
  91. _buildLesionSize(
  92. descriptions?['HorizontalLengthInPixel'] ?? 0,
  93. descriptions?['VerticalLengthInPixel'] ?? 0,
  94. unitsPhysicalPixels,
  95. ),
  96. )
  97. ],
  98. ),
  99. ),
  100. Container(
  101. margin: const EdgeInsets.symmetric(
  102. vertical: 15,
  103. ),
  104. child: SizedBox(
  105. width: 70,
  106. height: 70,
  107. child: Stack(
  108. children: [
  109. SizedBox(
  110. width: 70,
  111. height: 70,
  112. child: Obx(() {
  113. final aiDetected = widget.aiDetectedObject[
  114. aiPatintController.state.aiResultIndex];
  115. return CircularProgressIndicator(
  116. valueColor: AlwaysStoppedAnimation(
  117. _buildAITextColor(
  118. aiDetected.label,
  119. ),
  120. ),
  121. backgroundColor: Colors.grey,
  122. value: aiDetected.confidence,
  123. );
  124. }),
  125. ),
  126. Center(
  127. child: SizedBox(
  128. width: 45,
  129. height: 45,
  130. child: Obx(() {
  131. final confidence = widget
  132. .aiDetectedObject[
  133. aiPatintController.state.aiResultIndex]
  134. .confidence;
  135. return Text(
  136. i18nBook.measure.possibility.t +
  137. '${(confidence * 100).toStringAsFixed(1)}%',
  138. style: const TextStyle(
  139. color: Colors.white,
  140. ),
  141. );
  142. }),
  143. ),
  144. ),
  145. ],
  146. ),
  147. ),
  148. ),
  149. ],
  150. ),
  151. ],
  152. ),
  153. );
  154. }
  155. Widget _buildLesionSize(
  156. int horizontalLengthInPixel,
  157. int verticalLengthInPixel,
  158. double unitsPhysicalPixels,
  159. ) {
  160. return Text(
  161. (horizontalLengthInPixel * unitsPhysicalPixels)
  162. .toStringAsFixed(2)
  163. .toString() +
  164. 'cm x' +
  165. (verticalLengthInPixel * unitsPhysicalPixels)
  166. .toStringAsFixed(2)
  167. .toString() +
  168. 'cm',
  169. style: const TextStyle(color: Colors.white),
  170. );
  171. }
  172. Widget _buildTitle(String label, Widget value) {
  173. return Column(
  174. mainAxisSize: MainAxisSize.max,
  175. crossAxisAlignment: CrossAxisAlignment.start,
  176. children: [
  177. Text(
  178. label,
  179. style: const TextStyle(
  180. color: Color.fromRGBO(54, 169, 206, 1),
  181. ),
  182. ),
  183. value,
  184. const SizedBox(
  185. height: 5,
  186. ),
  187. ],
  188. );
  189. }
  190. Color _buildAITextColor(int label) {
  191. switch (label) {
  192. case 0:
  193. return Colors.lightBlue;
  194. case 1:
  195. case 2:
  196. case 3:
  197. return Colors.greenAccent;
  198. default:
  199. return Colors.redAccent;
  200. }
  201. }
  202. Widget _buildAITitle() {
  203. switch (aiPatintController.diagnosisOrgan) {
  204. case DiagnosisOrganEnum.Breast:
  205. return Obx(() {
  206. aiDetectedObjectItem =
  207. widget.aiDetectedObject[aiPatintController.state.aiResultIndex];
  208. return _buildBreastDescription(aiDetectedObjectItem.label);
  209. });
  210. case DiagnosisOrganEnum.Liver:
  211. return Obx(() {
  212. aiDetectedObjectItem =
  213. widget.aiDetectedObject[aiPatintController.state.aiResultIndex];
  214. return _buildLiverDescription(aiDetectedObjectItem.label);
  215. });
  216. default:
  217. return const SizedBox();
  218. }
  219. }
  220. Widget _buildBreastDescription(int label) {
  221. switch (label) {
  222. case 0:
  223. return _buildDescription(
  224. i18nBook.measure.noSignificantAbnormalitiesWereSeen.t);
  225. case 1:
  226. return _buildDescription(i18nBook.measure.lipoma.t);
  227. case 2:
  228. return _buildDescription('BI-RADS 2');
  229. case 3:
  230. return _buildDescription('BI-RADS 3');
  231. case 4:
  232. return _buildDescription('BI-RADS 4a');
  233. case 5:
  234. return _buildDescription('BI-RADS 4b');
  235. case 6:
  236. return _buildDescription('BI-RADS 4c');
  237. case 7:
  238. return _buildDescription('BI-RADS 5');
  239. case 8:
  240. return _buildDescription(
  241. i18nBook.measure.noSignificantAbnormalitiesWereSeen.t);
  242. default:
  243. return _buildDescription(null);
  244. }
  245. }
  246. Widget _buildLiverDescription(int label) {
  247. switch (label) {
  248. case 0:
  249. return _buildDescription(
  250. i18nBook.measure.noSignificantAbnormalitiesWereSeen.t);
  251. case 1:
  252. return _buildDescription(i18nBook.measure.intrahepaticStrongEchoFoci.t);
  253. case 2:
  254. return _buildDescription(i18nBook.measure.hepaticHemangioma.t);
  255. case 3:
  256. return _buildDescription(i18nBook.measure.liverCysts.t);
  257. case 4:
  258. return _buildDescription(i18nBook.measure.liverCancerMayOccur.t);
  259. case 5:
  260. return _buildDescription(i18nBook.measure.fattyLiver.t);
  261. case 6:
  262. return _buildDescription(
  263. i18nBook.measure.panisodicChangesLiverDiffuseLesions.t);
  264. case 7:
  265. return _buildDescription(i18nBook.measure.cirrhosis.t);
  266. case 8:
  267. return _buildDescription(i18nBook.measure.polycysticLiver.t);
  268. default:
  269. return _buildDescription(null);
  270. }
  271. }
  272. Widget _buildDescription(
  273. String? title,
  274. ) {
  275. return Column(
  276. crossAxisAlignment: CrossAxisAlignment.start,
  277. children: [
  278. if (title != null) ...[
  279. const SizedBox(
  280. height: 5,
  281. ),
  282. Text(
  283. title,
  284. style: const TextStyle(color: Colors.white),
  285. ),
  286. ],
  287. ],
  288. );
  289. }
  290. }