measure_tool.dart 13 KB

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