measure_configuation_page.dart 16 KB

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