measure_tool.dart 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. import 'package:fis_common/logger/logger.dart';
  2. import 'package:fis_jsonrpc/rpc.dart';
  3. import 'package:fis_measure/interfaces/process/items/item.dart';
  4. import 'package:fis_measure/interfaces/process/items/item_metas.dart';
  5. import 'package:fis_measure/interfaces/process/player/play_controller.dart';
  6. import 'package:fis_measure/interfaces/process/workspace/application.dart';
  7. import 'package:fis_measure/process/workspace/measure_data_controller.dart';
  8. import 'package:fis_measure/process/workspace/measure_handler.dart';
  9. import 'package:fis_measure/view/player/controller.dart';
  10. import 'package:fis_ui/index.dart';
  11. import 'package:flutter/material.dart';
  12. import 'package:get/get.dart';
  13. import 'package:vid/us/vid_us_image.dart';
  14. import 'package:vid/us/vid_us_unit.dart';
  15. /// 测量项页面
  16. class LeftSiderSelectMeasure extends FStatefulWidget {
  17. const LeftSiderSelectMeasure({Key? key}) : super(key: key);
  18. @override
  19. FState<LeftSiderSelectMeasure> createState() => LeftSiderSelectMeasureState();
  20. }
  21. class LeftSiderSelectMeasureState extends FState<LeftSiderSelectMeasure> {
  22. final ScrollController scrollController = ScrollController();
  23. late final application = Get.find<IApplication>();
  24. late final measureHandler = Get.find<MeasureHandler>();
  25. /// 数据
  26. late final measureData = Get.find<MeasureDataController>();
  27. final playerController = Get.find<IPlayerController>() as VidPlayerController;
  28. // final topMeasureItem = Get.put<ITopMeasureItem>();
  29. /// 当前选中的测量项目
  30. String activeName = '';
  31. /// 当前组合测量项
  32. ItemMeta? comboItemMeta;
  33. int? comboItemMetaActivedIndex;
  34. /// 是否展开组合测量项
  35. bool isCombo = false;
  36. void workingChildChanged(sender, int e) {
  37. comboItemMetaActivedIndex = e;
  38. setState(() {});
  39. }
  40. /// 切换测量项
  41. void changeItem(ItemMeta itemMeta) {
  42. activeName = itemMeta.name;
  43. try {
  44. application.switchItem(itemMeta);
  45. final item = application.activeMeasureItem!;
  46. if (item is ITopMeasureItem) {
  47. item.switchChild(0);
  48. item.workingChildChanged.addListener(workingChildChanged);
  49. }
  50. } catch (e) {
  51. logger.e("changeItem failed", e);
  52. }
  53. if (mounted) {
  54. setState(() {});
  55. }
  56. }
  57. /// 当前测量数据源变更
  58. void itemMetaList(Object s, dynamic e) {
  59. try {
  60. if (e != null) {
  61. setState(() {});
  62. }
  63. } catch (e) {
  64. debugPrint("callmethod fail " + e.toString());
  65. }
  66. }
  67. /// 获取组合测量项
  68. void comboList() {
  69. /// 格式化数据
  70. List<ItemMeta> itemMetaList = [];
  71. for (var element in measureData.itemMetaList) {
  72. if (measureData.getMeasureApplicationList.contains(element.name)) {
  73. List<ItemOutputMeta> itemOutputMeta = [];
  74. String? multiMethod;
  75. List<OutputItemMetaDTO> availableOutputs =
  76. element.calculator?.availableOutputs ?? [];
  77. for (var element in availableOutputs) {
  78. itemOutputMeta.add(
  79. ItemOutputMeta(
  80. element.name ?? '',
  81. element.description ?? '',
  82. VidUsUnitMap.getUnit(element.unit),
  83. ),
  84. );
  85. }
  86. List<ItemMeta> childItemMetas = [];
  87. if (element.multiMethodItems?.isNotEmpty ?? false) {
  88. ChildItemMetaDTO? itemMeta = element.multiMethodItems!
  89. .firstWhereOrNull((element) => element.isWorking == true);
  90. multiMethod = itemMeta?.name ?? '';
  91. List<ChildItemMetaDTO> childItems = itemMeta?.childItems ?? [];
  92. /// 组合测量项部分
  93. for (var element in childItems) {
  94. childItemMetas.add(
  95. ItemMeta(
  96. element.name ?? '',
  97. measureType: element.measureTypeName!,
  98. description: element.description ?? '',
  99. outputs: itemOutputMeta,
  100. childItems: childItemMetas,
  101. ),
  102. );
  103. }
  104. }
  105. itemMetaList.add(
  106. ItemMeta(
  107. element.name ?? '',
  108. measureType: element.measureTypeName!,
  109. description: element.description ?? '',
  110. outputs: itemOutputMeta,
  111. childItems: childItemMetas,
  112. ),
  113. );
  114. }
  115. }
  116. measureData.getItemMetaList = itemMetaList;
  117. measureData.getTopItemMetaList = measureData.getItemMetaList;
  118. }
  119. /// 获取当前图像的测量项,从第一帧取
  120. void currentFrameHandler(Object sender, VidUsImage e) async {
  121. List<String> getModes = [];
  122. for (var element in e.visuals[0].modes) {
  123. getModes.add(element.type.toString().split('.')[1]);
  124. }
  125. measureData.applicationModes = e.visuals[0].modes;
  126. measureData.currentMode = e.visuals[0].modes.first.type.name;
  127. var measureModeSelection = MeasureModeSelection(
  128. application.applicationName,
  129. application.categoryName,
  130. application.isThirdPart ? ['TPPTissue'] : getModes,
  131. );
  132. measureHandler.measureModeChanged = measureModeSelection;
  133. var measureApplicationDTO =
  134. await measureData.getMeasureApplication.call(measureModeSelection);
  135. if (measureApplicationDTO != null) {
  136. /// 模式版本
  137. measureData.measureApplicationVersion =
  138. measureApplicationDTO.version ?? '';
  139. measureData.availableModes = measureApplicationDTO.availableModes ?? [];
  140. ///模式列表
  141. var models = measureApplicationDTO.availableModes;
  142. if (models != null && models.isNotEmpty) {
  143. ///群组列表
  144. var groups = models[0].availableGroups;
  145. if (groups != null && groups.isNotEmpty) {
  146. ///项目列表
  147. var folders = groups[0].availableFolders;
  148. if (folders != null && folders.isNotEmpty) {
  149. measureData.getMeasureApplicationList =
  150. folders[0].workingItemNames ?? [];
  151. if (folders[0].availableItems != null) {
  152. measureData.itemMetaList = folders[0].availableItems!.toList();
  153. comboList();
  154. }
  155. print('测量方法集: ${measureData.getMeasureApplicationList.toString()}');
  156. if (measureData.getMeasureApplicationList.isNotEmpty) {
  157. changeItem(measureData.getItemMetaList[0]);
  158. }
  159. }
  160. }
  161. }
  162. }
  163. getNoteCommentsList();
  164. }
  165. /// 注释获取
  166. void getNoteCommentsList() async {
  167. List<String> commentsList = [];
  168. var measureCommentItemResult =
  169. await measureData.getCommentsByApplicationAsync(
  170. application.applicationName,
  171. application.categoryName,
  172. );
  173. measureData.measureCommentItemResult =
  174. measureCommentItemResult?.commentItems ?? [];
  175. measureCommentItemResult?.commentItems?.forEach((element) {
  176. commentsList.add(element.text ?? '');
  177. });
  178. measureData.getCommentsList = commentsList;
  179. }
  180. void getItemMetaListChanged(sender, e) {
  181. measureData.getTopItemMetaList = measureData.getItemMetaList;
  182. setState(() {});
  183. }
  184. @override
  185. void initState() {
  186. playerController.currentFrameHandler.addListener(
  187. (currentFrameHandler),
  188. );
  189. measureData.getItemMetaListChanged.addListener(getItemMetaListChanged);
  190. measureData.itemMetaListChanged.addListener(itemMetaList);
  191. super.initState();
  192. }
  193. @override
  194. dispose() {
  195. super.dispose();
  196. playerController.currentFrameHandler.removeListener(
  197. (currentFrameHandler),
  198. );
  199. measureData.getItemMetaListChanged.removeListener(getItemMetaListChanged);
  200. measureData.itemMetaListChanged.removeListener(itemMetaList);
  201. final item = application.activeMeasureItem!;
  202. if (item is ITopMeasureItem) {
  203. item.workingChildChanged.removeListener(workingChildChanged);
  204. }
  205. }
  206. @override
  207. FWidget build(BuildContext context) {
  208. return FSingleChildScrollView(
  209. controller: ScrollController(),
  210. child: FScrollbar(
  211. isAlwaysShown: true,
  212. child: FColumn(
  213. children: [
  214. _buildFGridView(measureData.getTopItemMetaList),
  215. if (isCombo) _buildCombo(),
  216. _buildFGridView(measureData.getBottomItemMetaList),
  217. ],
  218. ),
  219. ),
  220. );
  221. }
  222. /// 未选中的普通测量项 选中事件
  223. void chooseMeasure(ItemMeta itemMeta) {
  224. isCombo = false;
  225. changeItem(itemMeta);
  226. measureData.getTopItemMetaList = measureData.getItemMetaList;
  227. measureData.getBottomItemMetaList = [];
  228. }
  229. void chooseComboMeasure(ItemMeta itemMeta) {
  230. isCombo = true;
  231. changeItem(itemMeta);
  232. List<ItemMeta> top = [];
  233. List<ItemMeta> bottom = [];
  234. List<ItemMeta> getItemMetaList = measureData.getItemMetaList;
  235. for (int i = 0; i < getItemMetaList.length; i++) {
  236. if (i <= getItemMetaList.indexOf(itemMeta)) {
  237. top.add(getItemMetaList[i]);
  238. } else {
  239. bottom.add(getItemMetaList[i]);
  240. }
  241. measureData.getTopItemMetaList = top;
  242. measureData.getBottomItemMetaList = bottom;
  243. if (i == getItemMetaList.indexOf(itemMeta)) {
  244. comboItemMeta = getItemMetaList[i];
  245. comboItemMetaActivedIndex = 0;
  246. }
  247. }
  248. }
  249. FWidget _buildComboItem(ItemMeta itemMeta, int index) {
  250. FWidget child;
  251. if (comboItemMetaActivedIndex == index) {
  252. child = FElevatedButton(
  253. onPressed: () {
  254. final item = application.activeMeasureItem!;
  255. if (item is ITopMeasureItem) {
  256. item.switchChild(index);
  257. comboItemMetaActivedIndex = index;
  258. }
  259. setState(() {});
  260. },
  261. child: FText(
  262. itemMeta.name,
  263. style: const TextStyle(
  264. color: Colors.white,
  265. ),
  266. ),
  267. );
  268. } else {
  269. child = FOutlinedButton(
  270. onPressed: () {
  271. final item = application.activeMeasureItem!;
  272. if (item is ITopMeasureItem) {
  273. item.switchChild(index);
  274. comboItemMetaActivedIndex = index;
  275. }
  276. setState(() {});
  277. },
  278. style: OutlinedButton.styleFrom(
  279. side: const BorderSide(
  280. color: Color.fromRGBO(124, 124, 124, 1),
  281. ),
  282. ),
  283. child: FText(
  284. itemMeta.name,
  285. style: const TextStyle(
  286. color: Colors.white,
  287. ),
  288. ),
  289. );
  290. }
  291. return child;
  292. }
  293. /// 组合测量项打开的ui
  294. FWidget _buildCombo() {
  295. return FColumn(
  296. mainAxisSize: MainAxisSize.max,
  297. children: [
  298. FContainer(
  299. padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 5),
  300. color: const Color.fromRGBO(70, 70, 70, 1),
  301. child: FColumn(
  302. children: (comboItemMeta?.childItems ?? [])
  303. .asMap()
  304. .entries
  305. .map(
  306. (e) => FContainer(
  307. width: double.infinity,
  308. padding: const EdgeInsets.symmetric(
  309. vertical: 2,
  310. ),
  311. child: _buildComboItem(
  312. e.value,
  313. e.key,
  314. ),
  315. ),
  316. )
  317. .toList(),
  318. ),
  319. ),
  320. ],
  321. );
  322. }
  323. FWidget _buildFGridView(List<ItemMeta> itemMeta) {
  324. return FGridView.count(
  325. shrinkWrap: true,
  326. crossAxisCount: 2,
  327. childAspectRatio: 3,
  328. controller: ScrollController(),
  329. children: itemMeta.map((e) {
  330. if (e.name == activeName) {
  331. // 选中的测量项
  332. return _buildItemMetaContainer(e, () {});
  333. } else {
  334. if (e.childItems.isEmpty) {
  335. return _buildItemMetaContainer(
  336. e,
  337. () => chooseMeasure(e),
  338. );
  339. } else {
  340. return _buildItemMetaContainer(
  341. e,
  342. () => chooseComboMeasure(e),
  343. );
  344. }
  345. }
  346. }).toList(),
  347. );
  348. }
  349. FWidget _buildItemMetaContainer(ItemMeta e, Function onTap) {
  350. FWidget measure;
  351. if (e.name == activeName) {
  352. measure = FElevatedButton(
  353. onPressed: () => onTap.call(),
  354. child: FText(e.name),
  355. style: ElevatedButton.styleFrom(
  356. fixedSize: const Size.fromHeight(
  357. 40,
  358. ),
  359. ),
  360. );
  361. } else {
  362. measure = FOutlinedButton(
  363. onPressed: () => onTap.call(),
  364. child: FText(
  365. e.name,
  366. style: const TextStyle(
  367. color: Colors.white,
  368. ),
  369. ),
  370. style: OutlinedButton.styleFrom(
  371. fixedSize: const Size.fromHeight(
  372. 40,
  373. ),
  374. side: const BorderSide(
  375. color: Color.fromRGBO(124, 124, 124, 1),
  376. ),
  377. textStyle: const TextStyle(
  378. color: Colors.white,
  379. ),
  380. ),
  381. );
  382. }
  383. return FRow(
  384. children: [
  385. const FSizedBox(
  386. width: 12,
  387. ),
  388. FExpanded(
  389. child: measure,
  390. ),
  391. const FSizedBox(
  392. width: 12,
  393. ),
  394. ],
  395. );
  396. }
  397. }