controller.dart 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016
  1. import 'dart:async';
  2. import 'package:fis_common/helpers/encrypt.dart';
  3. import 'package:fis_common/index.dart';
  4. import 'package:fis_common/logger/logger.dart';
  5. import 'package:fis_i18n/i18n.dart';
  6. import 'package:fis_jsonrpc/rpc.dart';
  7. import 'package:fis_ui/index.dart';
  8. import 'package:fis_ui/interface/interactive_container.dart';
  9. import 'package:flutter/foundation.dart';
  10. import 'package:flutter/material.dart';
  11. import 'package:get/get.dart';
  12. import 'package:vitalapp/architecture/utils/prompt_box.dart';
  13. import 'package:vitalapp/architecture/values/features.dart';
  14. import 'package:vitalapp/managers/interfaces/language.dart';
  15. import 'package:vitalapp/managers/interfaces/models/consultations_record_data.dart';
  16. import 'package:vitalapp/managers/interfaces/models/image_report_list_params.dart';
  17. import 'package:vitalapp/managers/interfaces/models/role_type.dart';
  18. import 'package:vitalapp/managers/interfaces/models/selected_model.dart';
  19. import 'package:vitalapp/managers/interfaces/remedical.dart';
  20. import 'package:vitalapp/managers/interfaces/report.dart';
  21. import 'package:vitalapp/pages/image_report_inner_view/controller.dart';
  22. import 'package:vitalapp/pages/patient/create/widgets/patient_info.dart';
  23. import 'package:vitalapp/rpc.dart';
  24. import 'package:vitalapp/store/store.dart';
  25. import 'controllers/capture_live_controller.dart';
  26. import 'controllers/check_controller.dart';
  27. import 'controllers/remedical_controller.dart';
  28. import 'state.dart';
  29. import 'widgets/inspection_details_dialog.dart';
  30. class ConsultationRecordViewController extends GetxController
  31. with GetSingleTickerProviderStateMixin {
  32. late final RemedicalController remedicalController;
  33. late final CheckController checkController;
  34. late final CaptureLiveController captureLiveController;
  35. final languageConfigManager = Get.find<ILanguageConfigManager>();
  36. final remedicalManager = Get.find<IRemedicalManager>();
  37. final searchInputFocusNode = FocusNode();
  38. final searchSelectPatientFocusNode = FocusNode();
  39. final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
  40. List<ConsultationsRecordData> consultationsRecordDataList = [];
  41. ///医院筛选框
  42. final orgFilterController = TextEditingController();
  43. ///设备筛选框
  44. final deviceFilterController = TextEditingController();
  45. ConsultationRecordViewController() {
  46. remedicalController = RemedicalController(this);
  47. checkController = CheckController(this);
  48. captureLiveController = CaptureLiveController(this);
  49. }
  50. final state = ConsultationRecordViewState();
  51. final reportManager = Get.find<IReportManager>();
  52. ///是否抽屉显示历史检查
  53. bool isDrawerOpen = false;
  54. /// FisBuilder 中用到的 UI 数据
  55. // **表格数据**
  56. bool isTableLoading = false;
  57. ///当前检查详情
  58. QueryRecordResult? checkInfo;
  59. ConsultationsRecordData? get currentRecordData =>
  60. selectedIndex > -1 ? consultationsRecordDataList[selectedIndex] : null;
  61. ///转诊状态0-普通,1-转入,2-转出
  62. ReferralTypeEnum? get referralType => currentRecordData?.referralType;
  63. ///是否转诊
  64. bool get isReferral => referralType != null && referralType!.index > 0;
  65. String get desktopListSelectedRecordCode =>
  66. currentRecordData?.recordCode ?? '';
  67. String get deviceCode => currentRecordData?.deviceCode ?? '';
  68. String get patientCode => currentRecordData?.patientCode ?? '';
  69. String get patientName => currentRecordData?.patientName ?? '';
  70. RecordStatusEnum? get recordStatus => currentRecordData?.recordStatus;
  71. bool get canCollcetImg => currentRecordData?.canCollcetImg ?? false;
  72. ///是否能本地采图
  73. bool get canScreenshot => currentRecordData?.canScreenshot ?? false;
  74. bool get isCanTransfer => false;
  75. bool get isCanShowTransferHisHistory => [
  76. ReferralTypeEnum.ReferralIn,
  77. ReferralTypeEnum.ReferralOut
  78. ].contains(currentRecordData?.referralType); // 是否可以显示转诊历史
  79. /// 是否拥有删除的权限
  80. bool get isCanDelete => Store.user.hasFeature(FeatureKeys.DeleteRecord);
  81. /// **分页器**
  82. int totalDataCount = 0;
  83. int pageIndex = 1;
  84. // **操作栏**
  85. bool isShowOperationButtonsRow = false;
  86. // **筛选**
  87. RecordProcessStateEnum typeFilter = RecordProcessStateEnum.Wait;
  88. bool isFilterOptionsExpanded = false;
  89. // 筛选条件中的机构列表
  90. List<FMutiSelectModel> organizationLocatedList = [];
  91. // 所有机构列表
  92. List<FMutiSelectModel> allOrganizationLocatedList = [];
  93. ///机构总数量
  94. int organizationsCount = 0;
  95. // 所属机构
  96. List<String> get selectedOrganizationLocated =>
  97. organizationLocatedList.map((e) => e.code).toList();
  98. //筛选条件中的设备列表
  99. List<FMutiSelectModel> personDeviceList = [];
  100. //所有设备列表
  101. List<FMutiSelectModel> allPersonDeviceList = [];
  102. ///设备总数量
  103. int personDeviceCount = 0;
  104. ///设备编码集合
  105. List<String> get selectedpersonDevice =>
  106. personDeviceList.map((e) => e.code).toList(); // 当前选择设备
  107. ///是否全选组织
  108. bool isSelectAllOrg = true;
  109. ///是否全选设备
  110. bool isSelectAllDevice = true;
  111. List<FSelectOptionModel> recordStatusList = [
  112. FSelectOptionModel(
  113. title: i18nBook.common.all.t,
  114. value: RecordQueryStateEnum.All,
  115. ),
  116. FSelectOptionModel(
  117. title: i18nBook.remedical.toScan4Label.t,
  118. value: RecordQueryStateEnum.NotScanned,
  119. ),
  120. FSelectOptionModel(
  121. title: i18nBook.remedical.imageUploaded4Label.t,
  122. value: RecordQueryStateEnum.Uploaded,
  123. ),
  124. FSelectOptionModel(
  125. title: i18nBook.remedical.scanned4Label.t,
  126. value: RecordQueryStateEnum.NotReport,
  127. ),
  128. FSelectOptionModel(
  129. title: i18nBook.remedical.reported4Label.t,
  130. value: RecordQueryStateEnum.Completed,
  131. ),
  132. ]; // 状态列表
  133. RecordQueryStateEnum selectRecordStatus = RecordQueryStateEnum.All;
  134. int selectedIndex = -1;
  135. String keyWord = '';
  136. String organizationName = '';
  137. OrganizationPatientTypeEnum organizationPatientType =
  138. OrganizationPatientTypeEnum.Person;
  139. bool _isHasFocus = false;
  140. bool isSelectPatientHasFocus = false;
  141. DateTime startDateTime = DateTime.now().subtract(Duration(days: 365 * 3));
  142. DateTime endDateTime = DateTime.now();
  143. late AnimationController animationController;
  144. late Animation<double> animation;
  145. /// 是否展示结束扫查
  146. late bool isShowEndScan = false;
  147. /// 移动端详情页展示的记录 code
  148. String mobileDetailPageRecordCode = '';
  149. // **转诊**
  150. List<FSelectOptionModel<String>> referOrg = []; // 可转诊机构
  151. String? referralOrganizationCode; // 转诊机构code
  152. List<FSelectOptionModel> userRoleList = []; // 角色列表
  153. List<UserDoctorModel> referUserList = []; // 转诊医师列表
  154. String? referralUserCode; // 转诊医师code
  155. String subjectMatter = ''; // 拒绝原因
  156. List<ReferralHistoryDetailData> referralHistoryDetailList = []; // 转诊历史列表
  157. late PatientInfo currSelectPatientInfo;
  158. // **历史记录*
  159. bool isShowHistory = false; // 是否显示历史记录
  160. String histroyPatientCode = ''; // 历史记录病人的code
  161. ///选择病人弹窗,当前选中的病人
  162. String currentSelectPatientCode = '';
  163. @override
  164. void onEnterPressed() {
  165. if (_isHasFocus) {
  166. searchFindRecordPages();
  167. }
  168. if (isSelectPatientHasFocus) {
  169. checkController.searchPatient();
  170. }
  171. }
  172. void _listenSearchFocusNode() {
  173. searchInputFocusNode.addListener(() {
  174. if (searchInputFocusNode.hasFocus) {
  175. _isHasFocus = true;
  176. } else {
  177. Future.delayed(
  178. const Duration(milliseconds: 10),
  179. () {
  180. _isHasFocus = false;
  181. },
  182. );
  183. }
  184. });
  185. }
  186. /// 点击了某一行
  187. Future<void> onTableRowTap(int index) async {
  188. print("onTableRowTap: $index");
  189. selectedIndex = index;
  190. checkInfo = await remedicalManager
  191. .queryRecordInfoAsync(desktopListSelectedRecordCode);
  192. isShowOperationButtonsRow = true;
  193. /// 结束扫查的逻辑
  194. /// (待扫查 || 已传图) && (不可开始采图)
  195. isShowEndScan = [RecordStatusEnum.Uploaded, RecordStatusEnum.NotScanned]
  196. .contains(recordStatus) &&
  197. !canCollcetImg;
  198. Get.find<ImagereportinnerviewController>().changeRecord(
  199. ImageReportListParams(
  200. recordCode: desktopListSelectedRecordCode,
  201. ),
  202. );
  203. update(["operation_buttons_row"]);
  204. }
  205. /// 分页器翻页
  206. Future<void> onChangePage(int pageIndex, int listLength,
  207. {bool isLoadMore = false}) async {
  208. print("onChangePage: $pageIndex, $listLength");
  209. this.pageIndex = pageIndex;
  210. isShowOperationButtonsRow = false;
  211. if (isShowHistory) {
  212. await queryRecordByCurrentPatient(histroyPatientCode);
  213. } else {
  214. await findRecordPagesAsync(
  215. isLoadMore: isLoadMore,
  216. );
  217. }
  218. state.measureImages = [];
  219. state.aiImages = [];
  220. state.reports = [];
  221. state.remedicalListResult = RemedicalListResult();
  222. update(["operation_buttons_row"]);
  223. update(["record_table_pagination", "record_data_table"]);
  224. }
  225. /// 加载角色集合
  226. Future<void> loadRoles() async {
  227. final roles = await rpc.role.findAuthenticationRolesAsync(
  228. FindAuthenticationRolesRequest(
  229. token: Store.user.token,
  230. language: i18nBook.locale.toCodeString('-'),
  231. ),
  232. );
  233. List<FSelectOptionModel> _userRoleList = [];
  234. roles.forEach(
  235. (e) => _userRoleList.add(
  236. FSelectOptionModel(
  237. value: e.roleCode ?? '',
  238. title: e.roleName ?? '',
  239. ),
  240. ),
  241. );
  242. userRoleList = _userRoleList;
  243. }
  244. /// 获取转入机构下面的医生用户
  245. Future<void> getUserListAsync(String organizationCode) async {
  246. final result = await rpc.user.getUserListAsync(
  247. GetUserListRequest(
  248. token: Store.user.token,
  249. language: i18nBook.locale.toCodeString('-'),
  250. organizationCode: organizationCode,
  251. // 全部和待分配的枚举
  252. organizationQueryType: OrganizationQueryTypeEnum.All,
  253. roleCodes: [RoleType.certifiedPhysician, RoleType.certifiedExpert],
  254. ),
  255. );
  256. final List<UserDoctorModel> _referUserList = [];
  257. result.forEach(
  258. (element) {
  259. final referUserName = element.displayName!;
  260. _referUserList.add(
  261. UserDoctorModel(
  262. name: referUserName,
  263. code: element.userCode ?? '',
  264. roleCodes: element.roleCodes ?? [],
  265. roleName: element.roleName,
  266. fieldList: element.fieldList ?? [],
  267. headImageUrl: element.headImageUrl ?? '',
  268. ),
  269. );
  270. },
  271. );
  272. referUserList = _referUserList;
  273. update(['transfer_doctor']);
  274. }
  275. Future<void> findReferralHistoryAsync([
  276. String? mobileRecordCode,
  277. ]) async {
  278. try {
  279. String currentRecordCode = desktopListSelectedRecordCode;
  280. if (mobileRecordCode != null && mobileRecordCode.isNotEmpty) {
  281. currentRecordCode = mobileRecordCode;
  282. }
  283. final result = await rpc.recordInfo.findReferralHistoryAsync(
  284. FindReferralHistoryRequest(
  285. token: Store.user.token,
  286. recordCode: currentRecordCode,
  287. ),
  288. );
  289. List<ReferralHistoryDetailData> _referralHistoryDetailList = [];
  290. for (ReferralHistoryDetail i in result) {
  291. _referralHistoryDetailList
  292. .add(ReferralHistoryDetailData.fromJson(i.toJson()));
  293. }
  294. referralHistoryDetailList = _referralHistoryDetailList;
  295. } catch (e) {
  296. printError(
  297. info: "queryReferralOrganizationsAsync exception:" + e.toString());
  298. logger.e("queryReferralOrganizationsAsync exception:", e);
  299. }
  300. }
  301. /// 转诊提交
  302. Future<void> submitRefer(
  303. String patientCode, [
  304. String? mobileRecordCode,
  305. ]) async {
  306. try {
  307. if (subjectMatter.isNullOrWhiteSpace ||
  308. referralUserCode == '' ||
  309. referralUserCode == null ||
  310. referralOrganizationCode == '') {
  311. PromptBox.toast(i18nBook.user.requiredFieldsCannotBeEmpty.t);
  312. } else {
  313. String currentRecordCode = desktopListSelectedRecordCode;
  314. if (mobileRecordCode != null && mobileRecordCode.isNotEmpty) {
  315. currentRecordCode = mobileRecordCode;
  316. }
  317. /// 创建转诊
  318. final applyReferralRecord =
  319. await rpc.recordInfo.applyReferralForRecordInfoListAsync(
  320. CreateReferralRecordNewRequest(
  321. recordCode: currentRecordCode,
  322. token: Store.user.token,
  323. subjectMatter: subjectMatter,
  324. referralOrganizationCode: referralOrganizationCode,
  325. referralUserCode: referralUserCode,
  326. ),
  327. );
  328. // 转诊成功
  329. if (applyReferralRecord) {
  330. initReferStatus();
  331. await searchFindRecordPages();
  332. PromptBox.toast(i18nBook.remedical.submitSuccessToTransferList.t);
  333. }
  334. }
  335. } catch (e) {
  336. printError(
  337. info:
  338. "applyReferralForRecordInfoListAsync exception:" + e.toString());
  339. logger.e("applyReferralForRecordInfoListAsync exception:", e);
  340. }
  341. }
  342. void initReferStatus() {
  343. Get.back();
  344. subjectMatter = '';
  345. referralOrganizationCode = null;
  346. referralUserCode = null;
  347. }
  348. //**操作栏按钮 */
  349. // 查看病人信息
  350. Future<void> showPatientInfoDialog() async {
  351. // consultationController =
  352. // Get.put<ConsultationController>(ConsultationController());
  353. // consultationController?.state.checkLists = [];
  354. // consultationController?.changePatientInfo(patientCode);
  355. isDrawerOpen = true;
  356. update(['record_body']);
  357. }
  358. ///关闭病人信息
  359. void closePatientInfoDialog() {
  360. //Get.delete<ConsultationController>();
  361. isDrawerOpen = false;
  362. update(['record_body']);
  363. }
  364. // 查看检查详情
  365. Future<void> showInspectionDetailsDialog() async {
  366. checkInfo = await remedicalManager
  367. .queryRecordInfoAsync(desktopListSelectedRecordCode);
  368. var createTime = checkInfo!.createTime?.toLocal();
  369. var defaultTime = DateTime.utc(0001, 01, 01, 00, 00, 00, 00);
  370. if (checkInfo?.examTime != null && checkInfo?.examTime != defaultTime) {
  371. createTime = checkInfo?.examTime!.toLocal();
  372. }
  373. ClientPatientInfoDTO patientInfoDto =
  374. await remedicalManager.findPatientByCode(patientCode);
  375. Get.dialog(
  376. InspectionDetailsDiaLog(
  377. recordCode: desktopListSelectedRecordCode,
  378. checkInfo: GetRecordsPageDTO(
  379. createTime: createTime,
  380. creatorName: checkInfo!.creatorName,
  381. deptName: checkInfo!.deptName,
  382. displayName: checkInfo!.displayName,
  383. ),
  384. patientInfoExts: checkInfo?.patientInfoExtList ?? [],
  385. patientInfo: patientInfoDto,
  386. patientType: state.patientType,
  387. ),
  388. );
  389. }
  390. /// 获取组织信息
  391. Future<void> getOrgType() async {
  392. try {
  393. final result = await rpc.user.getUserInfoAsync(
  394. GetUserInfoRequest(token: Store.user.token),
  395. );
  396. final org = await rpc.organization.getOrganizationByCodeAsync(
  397. GetOrganizationByCodeRequest(
  398. organizationCode: result.rootOrganizationCode,
  399. token: Store.user.token,
  400. ),
  401. );
  402. state.patientType = org.patientType;
  403. } catch (e) {
  404. printError(info: "getOrgType exception:" + e.toString());
  405. logger.e("getOrgType exception:", e);
  406. }
  407. }
  408. /// 开始扫查
  409. ///
  410. /// [desktopListSelectedRecordCode] 设备code
  411. Future<bool> startScan(
  412. FInteractiveContainer businessParent,
  413. ) async {
  414. try {
  415. bool checkSuccess = await rpc.recordInfo
  416. .checkCollectingImgAsync(CheckCollectingImgRequest(
  417. deviceCode: deviceCode,
  418. token: Store.user.token,
  419. ));
  420. var startSuccess = false;
  421. if (checkSuccess) {
  422. startSuccess = await rpc.recordInfo
  423. .startCollectingImgAsync(StartCollectingImgRequest(
  424. recordCode: desktopListSelectedRecordCode,
  425. token: Store.user.token,
  426. ));
  427. if (startSuccess) {
  428. PromptBox.toast(i18nBook.remedical.startScanSuccess.t);
  429. }
  430. await findRecordPages();
  431. } else {
  432. FConfirmAlert.show(
  433. businessParent: businessParent,
  434. context: Get.context!,
  435. title: i18nBook.common.tip.t,
  436. subTitle: i18nBook.remedical.scanOcuppiedDetailTip.t,
  437. cancelLabel: i18nBook.common.cancel.t,
  438. confrimLabel: i18nBook.common.confirm.t,
  439. onCancel: () async {
  440. return;
  441. },
  442. onConfirm: () async {
  443. startSuccess = await rpc.recordInfo
  444. .startCollectingImgAsync(StartCollectingImgRequest(
  445. recordCode: desktopListSelectedRecordCode,
  446. token: Store.user.token,
  447. ));
  448. if (startSuccess) {
  449. PromptBox.toast(i18nBook.remedical.startScanSuccess.t);
  450. }
  451. await findRecordPages();
  452. },
  453. );
  454. }
  455. } catch (e) {
  456. printError(info: "StartScan:" + e.toString());
  457. logger.e("StartScan exception:", e);
  458. }
  459. return false;
  460. }
  461. // 当前页数不变
  462. Future<void> findRecordPages() async {
  463. await findRecordPagesAsync();
  464. isShowOperationButtonsRow = false;
  465. update(["operation_buttons_row"]);
  466. update(["record_table_pagination", "record_data_table"]);
  467. }
  468. // 编辑报告
  469. void editReport() {
  470. reportManager.openReportEdit(
  471. patientCode,
  472. recordCode: desktopListSelectedRecordCode,
  473. referralRecordCode: isReferral ? desktopListSelectedRecordCode : "",
  474. );
  475. }
  476. // 转诊
  477. Future<void> transfer() async {
  478. // await Get.dialog(RecordReferDoctorDiaLog(
  479. // patientName: patientName,
  480. // );
  481. subjectMatter = '';
  482. referUserList = [];
  483. referralOrganizationCode = null;
  484. referralUserCode = null;
  485. }
  486. // 撤销转诊
  487. Future<void> revokefer([
  488. String? mobileRecordCode,
  489. ]) async {
  490. try {
  491. String currentRecordCode = desktopListSelectedRecordCode;
  492. if (mobileRecordCode != null && mobileRecordCode.isNotEmpty) {
  493. currentRecordCode = mobileRecordCode;
  494. }
  495. final result =
  496. await rpc.recordInfo.withdrawReferralForRecordInfoListAsync(
  497. WithdrawReferralForRecordListRequest(
  498. token: Store.user.token,
  499. recordCode: currentRecordCode,
  500. ),
  501. );
  502. if (result) {
  503. Future.delayed(Duration(milliseconds: 500), () {
  504. PromptBox.toast(i18nBook.realTimeConsultation.withdrawalSucceeded.t);
  505. });
  506. Get.back();
  507. }
  508. searchFindRecordPages();
  509. } catch (e) {
  510. printError(info: "getOrgType exception:" + e.toString());
  511. logger.e("getOrgType exception:", e);
  512. }
  513. }
  514. // 查看历史记录
  515. Future<void> showReferralHistory([
  516. String? mobileRecordCode,
  517. ]) async {
  518. await findReferralHistoryAsync(mobileRecordCode);
  519. update(['record_refer_history_table']);
  520. print('showTransferHistory');
  521. }
  522. void showHistory() async {
  523. isShowHistory = true;
  524. pageIndex = 1;
  525. isShowOperationButtonsRow = false;
  526. histroyPatientCode = patientCode;
  527. await queryRecordByCurrentPatient(histroyPatientCode);
  528. update([
  529. "record_data_table_header",
  530. "record_data_table",
  531. "record_table_pagination",
  532. 'operation_buttons_row'
  533. ]);
  534. }
  535. // 离开历史记录模式
  536. void exitHistoryMode() async {
  537. isShowHistory = false;
  538. pageIndex = 1;
  539. isShowOperationButtonsRow = false;
  540. await searchFindRecordPages();
  541. update([
  542. "record_data_table_header",
  543. "record_data_table",
  544. "record_table_pagination",
  545. 'operation_buttons_row'
  546. ]);
  547. }
  548. /// 查询根据病人code查询
  549. Future<void> queryRecordByCurrentPatient(String patientCode) async {
  550. try {
  551. if (startDateTime.isAfter(endDateTime)) {
  552. PromptBox.toast(i18nBook.errorCodes.errorCode4022.t);
  553. return;
  554. }
  555. //busy = true;
  556. final result = await remedicalManager.findRecordPages(
  557. pageIndex: pageIndex,
  558. organizationCodes: selectedOrganizationLocated,
  559. deviceCodes: selectedpersonDevice,
  560. recordQueryState: selectRecordStatus,
  561. recordProcessState: typeFilter,
  562. patientCode: patientCode,
  563. startTime: startDateTime,
  564. endTime: endDateTime,
  565. );
  566. totalDataCount = result.totalCount;
  567. List<ConsultationsRecordData> _consultationsRecordDataList = [];
  568. for (SimpleRecordInfoDTO i in result.pageData ?? []) {
  569. i.patientName = FEncryptHelper.decryptBase64(i.patientName ?? '');
  570. var consultationsRecordData = ConsultationsRecordData.fromJson(
  571. i.toJson(),
  572. );
  573. consultationsRecordData.diagnosisInfos = i.diagnosisInfos ?? [];
  574. _consultationsRecordDataList.add(consultationsRecordData);
  575. }
  576. consultationsRecordDataList = _consultationsRecordDataList;
  577. //busy = false;
  578. } catch (e) {
  579. printError(info: "findRecordPagesAsync exception:" + e.toString());
  580. logger.e("findRecordPagesAsync exception:", e);
  581. //busy = false;
  582. }
  583. }
  584. // 切换筛选表格类型
  585. Future<void> changeTypeFilter(RecordProcessStateEnum value) async {
  586. remedicalController.clear();
  587. typeFilter = value;
  588. if (value == RecordProcessStateEnum.Done) {
  589. state.selectedTabIndex = 2;
  590. } else {
  591. state.selectedTabIndex = 0;
  592. }
  593. await searchFindRecordPages();
  594. isDrawerOpen = false;
  595. update(['record_body']);
  596. update(["record_filter_tab"]);
  597. update(["operation_buttons_row"]);
  598. update(["record_table_pagination", "record_data_table"]);
  599. }
  600. // 打开更多筛选项
  601. void openOrCloseMoreFilter() {
  602. isDrawerOpen = false;
  603. update(['record_body']);
  604. }
  605. Future<void> changeSelectedOrganizationLocated(List<String> value) async {
  606. await getPersonDeviceDropdownPageAsync();
  607. update(["record_more_filter"]);
  608. }
  609. /// 在 widget 内存中分配后立即调用。
  610. @override
  611. void onInit() async {
  612. super.onInit();
  613. reportManager.initFluwx();
  614. // userInfoManager
  615. // .getUserInfoAsync()
  616. // .then((value) => update(["record_data_table_header"]));
  617. _listenSearchFocusNode();
  618. _initListener();
  619. animationController = AnimationController(
  620. duration: Duration(milliseconds: 300),
  621. vsync: this,
  622. );
  623. animation = CurvedAnimation(
  624. parent: animationController,
  625. curve: Curves.easeInOut,
  626. );
  627. await getOrganizationByUserAndDevicesAsync(); // 筛选所有的机构
  628. allOrganizationLocatedList.addAll(organizationLocatedList);
  629. await getPersonDeviceDropdownPageAsync(); // 筛选所有的设备
  630. allPersonDeviceList.addAll(personDeviceList);
  631. await searchFindRecordPages(); // 查询列表
  632. }
  633. /// 获取机构列表
  634. Future<void> findRecordPagesAsync({
  635. bool isLoadMore = false,
  636. }) async {
  637. try {
  638. //busy = true;
  639. List<ConsultationsRecordData> _consultationsRecordDataList = [];
  640. if (startDateTime.isAfter(endDateTime)) {
  641. PromptBox.toast(i18nBook.errorCodes.errorCode4022.t);
  642. return;
  643. }
  644. final result = await remedicalManager.findRecordPages(
  645. pageIndex: pageIndex,
  646. organizationCodes: null,
  647. deviceCodes: null,
  648. recordQueryState: selectRecordStatus,
  649. recordProcessState: typeFilter,
  650. keyWord: keyWord,
  651. startTime: startDateTime,
  652. endTime: endDateTime,
  653. );
  654. totalDataCount = result.totalCount;
  655. for (SimpleRecordInfoDTO i in result.pageData ?? []) {
  656. // i.patientName = FEncryptHelper.decryptBase64(i.patientName ?? '');
  657. var consultationsRecordData = ConsultationsRecordData.fromJson(
  658. i.toJson(),
  659. );
  660. consultationsRecordData.diagnosisInfos = i.diagnosisInfos ?? [];
  661. _consultationsRecordDataList.add(consultationsRecordData);
  662. }
  663. if (isLoadMore) {
  664. consultationsRecordDataList.addAll(_consultationsRecordDataList);
  665. } else {
  666. consultationsRecordDataList = _consultationsRecordDataList;
  667. }
  668. //busy = false;
  669. } catch (e) {
  670. printError(info: "findRecordPagesAsync exception:" + e.toString());
  671. logger.e("findRecordPagesAsync exception:", e);
  672. //busy = false;
  673. }
  674. //if (busy) busy = false;
  675. }
  676. // 搜索
  677. Future<void> searchFindRecordPages() async {
  678. pageIndex = 1;
  679. await findRecordPagesAsync();
  680. openOrCloseMoreFilter();
  681. scaffoldKey.currentState?.closeEndDrawer();
  682. isShowOperationButtonsRow = false;
  683. isDrawerOpen = false;
  684. update(['record_body']);
  685. update(["operation_buttons_row"]);
  686. update(["record_table_pagination", "record_data_table"]);
  687. }
  688. // 重置
  689. Future<void> resetFilter() async {
  690. isSelectAllDevice = true;
  691. isSelectAllOrg = true;
  692. await getOrganizationByUserAndDevicesAsync();
  693. allOrganizationLocatedList.clear();
  694. allOrganizationLocatedList.addAll(organizationLocatedList);
  695. await getPersonDeviceDropdownPageAsync();
  696. allPersonDeviceList.clear();
  697. allPersonDeviceList.addAll(personDeviceList);
  698. selectRecordStatus = RecordQueryStateEnum.All;
  699. keyWord = '';
  700. startDateTime = DateTime.now().subtract(Duration(days: 365 * 3));
  701. endDateTime = DateTime.now();
  702. update(["record_time_filter"]);
  703. await searchFindRecordPages();
  704. }
  705. Future<void> refreshData() async {
  706. ///置空右侧的图像列表和报告列表
  707. selectedIndex = -1;
  708. state.selectedTabIndex = 0;
  709. state.measureImages = [];
  710. state.aiImages = [];
  711. state.reports = [];
  712. state.remedicalListResult = RemedicalListResult();
  713. await searchFindRecordPages();
  714. }
  715. /// 获取机构列表
  716. Future<void> getOrganizationByUserAndDevicesAsync() async {
  717. try {
  718. //busy = true;
  719. // var result = await userInfoManager.getOrganizationByUserAndDevices(
  720. // pageIndex: 1,
  721. // pageSize: 50,
  722. // );
  723. // organizationsCount = result.dataCount;
  724. // organizationLocatedList = result.pageData
  725. // ?.map((e) => FMutiSelectModel(
  726. // name: e.organizationName!, code: e.organizationCode!))
  727. // .toList() ??
  728. // [];
  729. // orgFilterController.text =
  730. // organizationLocatedList.map((element) => element.name).join('、');
  731. // busy = false;
  732. } catch (e) {
  733. printError(
  734. info:
  735. "getOrganizationByUserAndDevicesAsync exception:" + e.toString());
  736. logger.e("getOrganizationByUserAndDevicesAsync exception:", e);
  737. //busy = false;
  738. }
  739. }
  740. /// 结束扫查
  741. ///
  742. /// [desktopListSelectedRecordCode] 检查code
  743. Future<void> endScan(
  744. FInteractiveContainer businessParent,
  745. ) async {
  746. try {
  747. FConfirmAlert.show(
  748. businessParent: businessParent,
  749. context: Get.context!,
  750. title: i18nBook.common.tip.t,
  751. subTitle: i18nBook.remedical.finishScan.t,
  752. cancelLabel: i18nBook.common.cancel.t,
  753. confrimLabel: i18nBook.common.confirm.t,
  754. onCancel: () async {
  755. // await busyHandle(
  756. // () async {},
  757. // text: i18nBook.remedical.finishing.t,
  758. // );
  759. },
  760. onConfirm: () async {
  761. // await busyHandle(
  762. // () async {
  763. // final finishRecordAsync = await rpc.recordInfo.finishRecordAsync(
  764. // FinishRecordRequest(
  765. // recordCode: desktopListSelectedRecordCode,
  766. // token: Store.user.token,
  767. // ),
  768. // );
  769. // if (finishRecordAsync) {
  770. // PromptBox.toast(i18nBook.user.operationSuccess.t);
  771. // await findRecordPages();
  772. // } else {
  773. // PromptBox.toast(i18nBook.user.operationFailed.t);
  774. // }
  775. // },
  776. // text: i18nBook.remedical.finishing.t,
  777. // );
  778. },
  779. );
  780. } catch (e) {
  781. printError(info: "setVaildPatient exception:" + e.toString());
  782. logger.e("setVaildPatient exception:", e);
  783. }
  784. }
  785. /// 删除检查
  786. ///
  787. /// [desktopListSelectedRecordCode] 检查code
  788. Future<bool> deleteRecord(
  789. String recordCode,
  790. FInteractiveContainer businessParent,
  791. ) async {
  792. Completer deleteCompleter = Completer<bool>();
  793. FConfirmAlert.show(
  794. businessParent: businessParent,
  795. context: Get.context!,
  796. title: i18nBook.common.tip.t,
  797. subTitle: i18nBook.setting.confirmDeletion.t,
  798. cancelLabel: i18nBook.common.cancel.t,
  799. confrimLabel: i18nBook.common.confirm.t,
  800. onCancel: () {
  801. deleteCompleter.complete(false);
  802. },
  803. onConfirm: () async {
  804. try {
  805. final result = await rpc.recordInfo.deleteRecordAsync(
  806. DeleteRecordRequest(
  807. recordCode: recordCode,
  808. token: Store.user.token,
  809. ),
  810. );
  811. if (result) {
  812. Get.find<ImagereportinnerviewController>().clear();
  813. /// 下一帧执行
  814. await findRecordPages();
  815. await Future.delayed(Duration(milliseconds: 200));
  816. PromptBox.toast(i18nBook.measure.annotationDeleted.translate([""]));
  817. deleteCompleter.complete(true);
  818. } else {
  819. PromptBox.toast(i18nBook.user.deleteFailed.t);
  820. deleteCompleter.complete(false);
  821. }
  822. } catch (e) {
  823. deleteCompleter.complete(false);
  824. if (e is JsonRpcException) {
  825. if (e.data.code == 4068) {
  826. PromptBox.toast(i18nBook.errorCodes.errorCode4001.t);
  827. }
  828. }
  829. }
  830. },
  831. );
  832. bool success = await deleteCompleter.future;
  833. return success;
  834. }
  835. /// 获取设备列表
  836. Future<void> getPersonDeviceDropdownPageAsync() async {
  837. try {
  838. if (organizationLocatedList.isEmpty) {
  839. personDeviceList = [];
  840. personDeviceCount = 0;
  841. isSelectAllDevice = false;
  842. } else {
  843. // var result = await userInfoManager.getPersonDeviceDropdownPage(
  844. // index: 1,
  845. // pageSize: 50,
  846. // restrictOrgCodes: selectedOrganizationLocated,
  847. // isIncloudReferral: true,
  848. // );
  849. // personDeviceList = result.pageData
  850. // ?.map((e) =>
  851. // FMutiSelectModel(code: e.key ?? '', name: e.value ?? ''))
  852. // .toList() ??
  853. // [];
  854. // personDeviceCount = result.dataCount;
  855. }
  856. deviceFilterController.text =
  857. personDeviceList.map((e) => e.name).join('、');
  858. } catch (e) {
  859. printError(
  860. info: "getPersonDeviceDropdownPageAsync exception:" + e.toString());
  861. logger.e("getPersonDeviceDropdownPageAsync exception:", e);
  862. }
  863. }
  864. // 移动端查看检查详情
  865. void openRecordDetailPage(
  866. String recordCode, String patientCode, String devicePatientID) async {
  867. print('openRecordDetailPage $recordCode');
  868. QueryRecordResult? newCheckInfo =
  869. await remedicalManager.queryRecordInfoAsync(recordCode);
  870. ClientPatientInfoDTO patientInfoDto =
  871. await remedicalManager.findPatientByCode(patientCode);
  872. PatientInfo patientInfo =
  873. remedicalManager.dtoConvertToPatientInfo(patientInfoDto);
  874. // 数据载入
  875. if (newCheckInfo != null) {
  876. checkInfo = newCheckInfo;
  877. currSelectPatientInfo = patientInfo;
  878. mobileDetailPageRecordCode = recordCode;
  879. // await Get.to(
  880. // MobileRouteNames.Remedical.RecordDetail,
  881. // parameters: {
  882. // "devicePatientID": devicePatientID,
  883. // },
  884. // );
  885. }
  886. }
  887. /// 翻译
  888. String getValues(String code) {
  889. try {
  890. return languageConfigManager.getExamLanguageValue(code);
  891. } catch (e) {
  892. print(e);
  893. }
  894. return code;
  895. }
  896. @override
  897. void onReady() {
  898. super.onReady();
  899. }
  900. /// 在 [onDelete] 方法之前调用。
  901. @override
  902. void onClose() {
  903. super.onClose();
  904. }
  905. /// dispose 释放内存
  906. @override
  907. void dispose() {
  908. reportManager.onSubmitReport
  909. .removeListener(remedicalController.onSubmitReport);
  910. remedicalController.dispose();
  911. super.dispose();
  912. animationController.dispose();
  913. }
  914. void showImagePool() {
  915. // router.to(
  916. // RouteNames.Remedical.ImagePool,
  917. // id: NavIds.HOME,
  918. // parameters: {
  919. // "recordCode": desktopListSelectedRecordCode,
  920. // "patientCode": patientCode,
  921. // },
  922. // );
  923. }
  924. void _initListener() {
  925. reportManager.onSubmitReport
  926. .addListener(remedicalController.onSubmitReport);
  927. }
  928. }