measure_configuation_page.dart 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. import 'dart:convert';
  2. import 'package:fis_i18n/i18n.dart';
  3. import 'package:fis_jsonrpc/rpc.dart';
  4. import 'package:fis_measure/define.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/measure_config/widgets/has_selected_setting_dialog.dart';
  12. import 'package:fis_measure/view/measure/measure_config/widgets/measure_configuration_style.dart';
  13. import 'package:fis_measure/view/measure/measure_config/widgets/measure_configuration_unit.dart';
  14. import 'package:fis_measure/view/measure/measure_config/widgets/measurement_tool_selection.dart';
  15. import 'package:fis_measure/view/measure/measure_view_controller.dart';
  16. import 'package:fis_measure/view/player/controller.dart';
  17. import 'package:fis_theme/theme.dart';
  18. import 'package:fis_ui/index.dart';
  19. import 'package:fis_ui/interface/interactive_container.dart';
  20. import 'package:flutter/material.dart';
  21. import 'package:get/get.dart';
  22. import '../../gesture/positioned_cursor.dart';
  23. ///条目元数据组
  24. class ItemMetaGroup {
  25. ItemMetaGroup(
  26. this.itemMetaGroupTitle,
  27. this.itemMeta,
  28. this.isExpend,
  29. );
  30. /// 当前测量组的名称
  31. final String itemMetaGroupTitle;
  32. /// 当前测量组的测量数组
  33. final List<ItemMetaDTO> itemMeta;
  34. /// 是否展开
  35. bool? isExpend;
  36. }
  37. /// 测量工具配置
  38. class MeasureConfigurationPage extends StatefulWidget
  39. implements FWidget, FInteractiveContainer {
  40. @override
  41. final String pageName = 'MeasureConfigurationDialog';
  42. const MeasureConfigurationPage({
  43. Key? key,
  44. required this.ifHideConfig,
  45. }) : super(key: key);
  46. final bool ifHideConfig;
  47. @override
  48. State<MeasureConfigurationPage> createState() =>
  49. MeasureConfigurationPageState();
  50. }
  51. class MeasureConfigurationPageState extends State<MeasureConfigurationPage> {
  52. int measureToolsTab = 0;
  53. /// 切换标签栏
  54. void changeTab(int index) {
  55. measureToolsTab = index;
  56. setState(() {});
  57. }
  58. late final application = Get.find<IApplication>();
  59. late final measureHandler = Get.find<MeasureHandler>();
  60. final playerController = Get.find<IPlayerController>() as VidPlayerController;
  61. /// 数据
  62. final measureData = Get.find<MeasureDataController>();
  63. final mouseState = Get.find<IMouseState>();
  64. /// 测量项控制器
  65. final measureMetaController = Get.find<MeasureMetaController>();
  66. /// 之前保存的的测量项
  67. List<String> savedMeasureList = [];
  68. /// 选中的测量项
  69. List<String> chooseMeasureList = [];
  70. List<ItemMetaGroup> itemMetaListGroup = [];
  71. String activeName = '';
  72. List<MeasureModeDTO> measureMode = [];
  73. Future<void> getName() async {
  74. List<String> getModes = [];
  75. for (var element in playerController.currentFrame?.visuals[0].modes ?? []) {
  76. getModes.add(element.type.toString().split('.')[1]);
  77. }
  78. var measureModeSelection = MeasureModeSelection(
  79. application.applicationName,
  80. application.categoryName,
  81. application.isThirdPart ? ['TPPTissue'] : getModes,
  82. );
  83. measureHandler.measureModeChanged = measureModeSelection;
  84. measureData.getMeasureApplicationList = [];
  85. var measureApplicationDTO =
  86. await measureData.getMeasureApplication.call(measureModeSelection);
  87. if (measureApplicationDTO != null) {
  88. /// 模式版本
  89. measureData.measureApplicationVersion =
  90. measureApplicationDTO.version ?? '';
  91. measureData.availableModes = measureApplicationDTO.availableModes ?? [];
  92. measureMetaController.setAvailableModes(measureData.currentMode);
  93. activeName = measureData.curItemMetaList[0].name;
  94. }
  95. }
  96. void onSubmit() async {
  97. /// 判断两个数组是否相同
  98. if (savedMeasureList.toString() != chooseMeasureList.toString() ||
  99. measureData.itemMetaListConfig.isNotEmpty) {
  100. var measureModeSubmitChanged = MeasureModeSubmit(
  101. measureData.measureApplicationVersion,
  102. application.applicationName,
  103. application.categoryName,
  104. UserDefinedMeasureModeDTO(
  105. modeName: measureData.currentMode,
  106. workingGroups: [
  107. UserDefinedMeasureGroupDTO(
  108. name: 'General',
  109. folders: [
  110. UserDefinedMeasureFolderDTO(
  111. name: 'General',
  112. workingItemNames: chooseMeasureList,
  113. itemMetas: measureData.itemMetaListConfig,
  114. ),
  115. ],
  116. ),
  117. ],
  118. ),
  119. );
  120. measureHandler.measureModeSubmitChanged = measureModeSubmitChanged;
  121. await measureData.saveUserDefinedMeasureApplicationAsync
  122. .call(measureModeSubmitChanged);
  123. getName();
  124. measureMetaController.setAvailableModes(measureData.currentMode);
  125. }
  126. saveMeasureSystemSettingAsync();
  127. }
  128. void onCancel() async {
  129. // TODO 关闭时校验【measureSystemSetting】是否发生变更
  130. print('TODO 关闭时校验【measureSystemSetting】是否发生变更,如果发生变化需要询问用户是否保存');
  131. }
  132. // 保存修改测量样式
  133. Future<void> saveMeasureSystemSettingAsync() async {
  134. measureData.measureSystemSettingChanged
  135. .emit(this, measureData.measureSystemSetting);
  136. await measureData
  137. .saveMeasureSystemSettingAsync(measureData.measureSystemSetting);
  138. mouseState.cursorType = getMeasureSystemSettingCursorType(
  139. measureData.measureSystemSetting.cursorType);
  140. mouseState.cursorSize =
  141. measureData.measureSystemSetting.cursorSize as double;
  142. }
  143. @override
  144. void initState() {
  145. super.initState();
  146. List<String> chooseMeasure = [];
  147. if (widget.ifHideConfig) {
  148. measureToolsTab = 2;
  149. }
  150. measureMetaController.measureConfig();
  151. itemMetaListGroup = measureData.itemMetaListGroup;
  152. chooseMeasure = measureData.getMeasureApplicationList
  153. .where((element) => !MeasureUnsupportedTerms.items.contains(element))
  154. .toList();
  155. // 将原始列表转换为JSON字符串
  156. String jsonString = jsonEncode(measureData.availableModes);
  157. // 将JSON字符串转换回对象列表
  158. List<dynamic> jsonList = jsonDecode(jsonString);
  159. measureMode =
  160. jsonList.map((json) => MeasureModeDTO.fromJson(json)).toList();
  161. savedMeasureList = chooseMeasure.toSet().toList();
  162. chooseMeasureList = chooseMeasure.toSet().toList();
  163. /// TODO 打开时缓存当前的用户测量配置 【measureSystemSetting】,关闭时校验是否发生变更
  164. }
  165. @override
  166. void dispose() {
  167. super.dispose();
  168. }
  169. @override
  170. FWidget build(BuildContext context) {
  171. return FStack(
  172. children: [
  173. QuickFWidget(
  174. ModalBarrier(
  175. color: Colors.black.withOpacity(0.5),
  176. onDismiss: () {
  177. onCancel();
  178. },
  179. ),
  180. ),
  181. FSimpleDialog(
  182. title: FText(
  183. i18nBook.user.setting.t,
  184. style: const TextStyle(
  185. color: Colors.white,
  186. fontSize: 18,
  187. ),
  188. ),
  189. cancelString: i18nBook.common.cancel.t,
  190. okString: i18nBook.common.confirm.t,
  191. isDefault: true,
  192. onOk: () {
  193. onSubmit();
  194. Get.back();
  195. },
  196. onCancel: () {
  197. chooseMeasureList = measureData.getMeasureApplicationList;
  198. measureData.availableModes = measureMode;
  199. measureMetaController.setMeasureConfigItemMetaList();
  200. onCancel();
  201. Get.back();
  202. setState(() {});
  203. },
  204. children: [
  205. FContainer(
  206. width: 830,
  207. height: 500,
  208. child: _buildMeasureconfiguration(),
  209. ),
  210. ],
  211. ),
  212. ],
  213. );
  214. }
  215. FWidget _buildMeasureconfiguration() {
  216. return FContainer(
  217. padding: const EdgeInsets.symmetric(horizontal: 15),
  218. child: FRow(
  219. crossAxisAlignment: CrossAxisAlignment.start,
  220. children: [
  221. FContainer(
  222. width: 170,
  223. decoration: const BoxDecoration(
  224. border: Border(
  225. right: BorderSide(
  226. color: Color.fromRGBO(235, 235, 235, 1),
  227. width: 1,
  228. ),
  229. ),
  230. ),
  231. child: FColumn(
  232. crossAxisAlignment: CrossAxisAlignment.end,
  233. children: [
  234. const FSizedBox(
  235. height: 10,
  236. ),
  237. if (!widget.ifHideConfig)
  238. _buildTabButton(0, i18nBook.measure.measureToolSelect.t),
  239. if (!widget.ifHideConfig)
  240. _buildTabButton(1, i18nBook.measure.selectedMeasureTool.t),
  241. _buildTabButton(2, i18nBook.measure.measureStyleConfig.t),
  242. _buildTabButton(3, i18nBook.measure.measureUnitConfig.t),
  243. ],
  244. ),
  245. ),
  246. FExpanded(
  247. child: FStack(
  248. fit: StackFit.passthrough,
  249. children: [
  250. FOffstage(
  251. offstage: measureToolsTab != 0,
  252. child: FSingleChildScrollView(
  253. child: SelectModulePage(
  254. itemMetaListGroup: itemMetaListGroup,
  255. chooseMeasureList: chooseMeasureList,
  256. ),
  257. ),
  258. ),
  259. FOffstage(
  260. offstage: measureToolsTab != 1,
  261. child: _HasSelectedModulePage(
  262. chooseMeasureList: chooseMeasureList,
  263. ),
  264. ),
  265. FOffstage(
  266. offstage: measureToolsTab != 2,
  267. child: StyleConfigPage(
  268. businessParent: widget,
  269. ),
  270. ),
  271. FOffstage(
  272. offstage: measureToolsTab != 3,
  273. child: UnitConfigPage(
  274. businessParent: widget,
  275. ),
  276. ),
  277. ],
  278. )),
  279. ],
  280. ),
  281. );
  282. }
  283. FWidget _buildTabButton(int index, String title) {
  284. return FContainer(
  285. width: 160,
  286. child: FInkWell(
  287. onTap: () {
  288. changeTab(index);
  289. },
  290. child: FContainer(
  291. padding: const EdgeInsets.symmetric(
  292. vertical: 10,
  293. horizontal: 5,
  294. ),
  295. child: FText(
  296. title,
  297. style: measureToolsTab == index
  298. ? TextStyle(
  299. color: FTheme.ins.colorScheme.primary,
  300. )
  301. : const TextStyle(),
  302. textAlign: TextAlign.end,
  303. ),
  304. ),
  305. ),
  306. );
  307. }
  308. }
  309. class _HasSelectedModulePage extends StatelessWidget implements FWidget {
  310. final List<String> chooseMeasureList;
  311. /// 数据
  312. final measureData = Get.find<MeasureDataController>();
  313. /// 测量项控制器
  314. final measureMetaController = Get.find<MeasureMetaController>();
  315. /// 测量语言包
  316. final measureLanguage = MeasureLanguage();
  317. _HasSelectedModulePage({
  318. required this.chooseMeasureList,
  319. });
  320. /// 打开已选测量工具设置
  321. ///
  322. /// [itemMeta] 测量的对象
  323. void openHasSelectedSettingDialog(ItemMetaDTO itemMeta) {
  324. Get.dialog(HasSelectedSettingDialog(itemMeta: itemMeta));
  325. }
  326. @override
  327. FWidget build(BuildContext context) {
  328. return FListView(
  329. shrinkWrap: true,
  330. children: [
  331. FColumn(
  332. crossAxisAlignment: CrossAxisAlignment.start,
  333. children: [
  334. FContainer(
  335. padding: const EdgeInsets.only(left: 15, top: 15, bottom: 15),
  336. child: FWrap(
  337. spacing: 16.0, // 主轴(水平)方向间距
  338. runSpacing: 8.0, // 纵轴(垂直)方向间距
  339. direction: Axis.horizontal,
  340. crossAlignment: WrapCrossAlignment.center,
  341. alignment: WrapAlignment.start,
  342. children: List<FWidget>.generate(
  343. chooseMeasureList.length,
  344. (index) {
  345. return FInkWell(
  346. onTap: () {
  347. var item = measureMetaController
  348. .setMeasureConfigItemMetaList()
  349. .firstWhere((element) =>
  350. element.description ==
  351. chooseMeasureList[index]);
  352. openHasSelectedSettingDialog(item);
  353. },
  354. child: FContainer(
  355. width: 180,
  356. height: 60,
  357. decoration: BoxDecoration(
  358. border: Border.all(
  359. width: 0.5,
  360. color: FTheme.ins.colorScheme.primary,
  361. ),
  362. ),
  363. child: FColumn(
  364. mainAxisAlignment: MainAxisAlignment.center,
  365. children: [
  366. if (!i18nBook.isCurrentEnglish)
  367. FText(
  368. measureLanguage.t(
  369. 'measure',
  370. chooseMeasureList[index].toString(),
  371. ),
  372. style: const TextStyle(
  373. color: Colors.black,
  374. ),
  375. ),
  376. FText(
  377. chooseMeasureList[index].toString(),
  378. style: const TextStyle(
  379. color: Colors.black,
  380. ),
  381. ),
  382. ],
  383. ),
  384. // ),
  385. ),
  386. );
  387. },
  388. ),
  389. ),
  390. ),
  391. ],
  392. ),
  393. ],
  394. );
  395. }
  396. }