list.dart 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824
  1. import 'dart:convert';
  2. import 'package:fis_common/event/event_type.dart';
  3. import 'package:fis_common/index.dart';
  4. import 'package:fis_common/logger/logger.dart';
  5. import 'package:fis_jsonrpc/rpc.dart';
  6. import 'package:flutter/foundation.dart';
  7. import 'package:flutter/material.dart';
  8. import 'package:flutter_easyloading/flutter_easyloading.dart';
  9. import 'package:get/get.dart';
  10. import 'package:vitalapp/architecture/utils/advance_debounce.dart';
  11. import 'package:vitalapp/architecture/utils/datetime.dart';
  12. import 'package:vitalapp/architecture/utils/prompt_box.dart';
  13. import 'package:vitalapp/components/alert_dialog.dart';
  14. import 'package:vitalapp/components/appbar.dart';
  15. import 'package:vitalapp/components/button.dart';
  16. import 'package:vitalapp/components/scroll_list.dart';
  17. import 'package:vitalapp/components/table/table_column.dart';
  18. import 'package:vitalapp/managers/interfaces/diagnosis.dart';
  19. import 'package:vitalapp/managers/interfaces/models/diagnosis_aggregation_record_model.dart';
  20. import 'package:vitalapp/managers/interfaces/patient.dart';
  21. import 'package:vitalapp/managers/interfaces/prescription.dart';
  22. import 'package:vitalapp/managers/interfaces/registration.dart';
  23. import 'package:vitalapp/pages/check/examination/controller.dart';
  24. import 'package:vitalapp/pages/check/examination/view.dart';
  25. import 'package:vitalapp/pages/check/prescription/examination_prescription.dart';
  26. import 'package:vitalapp/pages/check/prescription/prescription_form_keys.dart';
  27. import 'package:vitalapp/pages/medical/controller.dart';
  28. import 'package:vitalapp/pages/medical/views/exam_medical.dart';
  29. import 'package:vitalapp/pages/medical_checkup_station/registration/controller.dart';
  30. import 'package:vitalapp/pages/medical_checkup_station/registration/state/list.dart';
  31. import 'package:vitalapp/pages/medical_checkup_station/registration/widgets/form/index.dart';
  32. import 'package:vitalapp/pages/medical_checkup_station/registration/widgets/report/report_preview.dart';
  33. import 'package:vitalapp/pages/medical_checkup_station/usb_print/module/printer_info.dart';
  34. import 'package:vitalapp/pages/medical_checkup_station/usb_print/page/temp/print_preview.dart';
  35. import 'package:vitalapp/pages/widgets/overflow_tooltip_wrapper.dart';
  36. import 'package:vitalapp/store/store.dart';
  37. class RegistrationListController {
  38. late RegistrationController registrationController;
  39. RegistrationListController(RegistrationController controller) {
  40. registrationController = controller;
  41. }
  42. final state = ListState();
  43. final _registrationManager = Get.find<IRegistrationManager>();
  44. final _prescriptionManager = Get.find<IPrescriptionManager>();
  45. ResidentModel currentResident = ResidentModel(idNumber: "");
  46. List<String> _allExam = [
  47. "HEIBasic",
  48. "HEIUrinalysis",
  49. "HEIUltrasonic",
  50. "HEIBiochemical",
  51. "HEIBloodRoutine",
  52. "HEIECG",
  53. "HEITCMC"
  54. ];
  55. Map<String, dynamic> examData = {};
  56. List<String> noMedicalCheckUpList() {
  57. List<String> noCheckUpList = _allExam
  58. .where((element) =>
  59. !(currentResident.finishedExamKeys ?? []).contains(element))
  60. .toList();
  61. return noCheckUpList;
  62. }
  63. List<String> medicalCheckUpList() {
  64. List<String> checkUpList = _allExam
  65. .where((element) =>
  66. (currentResident.finishedExamKeys ?? []).contains(element))
  67. .toList();
  68. return checkUpList;
  69. }
  70. /// 是否有健康检测的页面权限
  71. bool _hasHealthMonitor() {
  72. bool hasAuth = false;
  73. Store.user.menuPermissionList?.forEach((element) {
  74. if (element.code == "JKJC") {
  75. hasAuth = true;
  76. }
  77. });
  78. return hasAuth;
  79. }
  80. Future<void> getRegisterInfoPage({
  81. int? pageSize = 10,
  82. int? pageIndex = 1,
  83. String? keyword = "",
  84. }) async {
  85. registrationController.tableLoading = true;
  86. registrationController.currPageIndex = pageIndex!;
  87. var result = await registrationController.registrationManager
  88. .getRegisterInfoPageAsync(
  89. pageSize: pageSize,
  90. pageIndex: pageIndex,
  91. keyword: keyword,
  92. startTime: state.startTime,
  93. endTime: state.endTime,
  94. );
  95. List<ResidentModel> _residentList = [];
  96. if (result?.pageData != null) {
  97. for (RegisterInfoDTO i in result!.pageData!) {
  98. String statusStr = '';
  99. ExamStateEnum status = i.state;
  100. switch (status) {
  101. case ExamStateEnum.Unchecked:
  102. statusStr = "未体检";
  103. break;
  104. case ExamStateEnum.Invalid:
  105. statusStr = "已作废";
  106. break;
  107. case ExamStateEnum.Inspected:
  108. statusStr = "体检中";
  109. break;
  110. case ExamStateEnum.Reported:
  111. statusStr = "已报告";
  112. break;
  113. }
  114. _residentList.add(
  115. ResidentModel(
  116. name: i.name ?? '',
  117. idNumber: i.iDCardNo ?? '',
  118. code: i.code ?? '',
  119. homeAddress: i.adress,
  120. age: getAgeOfIdNumber(i.iDCardNo ?? ''),
  121. physicalExamNumber: i.physicalExamNumber,
  122. phone: i.phone,
  123. finishedExamKeys: i.finishedExamKeys,
  124. physicalExamStatus: statusStr,
  125. birthDay: i.birthday?.toLocal(),
  126. sex: i.sex,
  127. batchNumber: i.batchNumber,
  128. resultsAndSuggestions: i.resultsAndSuggestions,
  129. createdDoctorName: i.createdDoctorName,
  130. physicalExamTime: i.updateTime,
  131. ),
  132. );
  133. }
  134. registrationController.appointmentModelListLength = result.totalCount;
  135. } else {
  136. registrationController.appointmentModelListLength = 0;
  137. }
  138. registrationController.residentList = _residentList;
  139. registrationController.tableLoading = false;
  140. registrationController.update(["registration_table"]);
  141. registrationController.update(["registration_table_pagination"]);
  142. }
  143. String getAgeOfIdNumber(String idNumber) {
  144. if (idNumber.isEmpty) return '';
  145. final idCardRegex = RegExp(r'^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})(\d|X)$');
  146. final match = idCardRegex.firstMatch(idNumber);
  147. if (match != null) {
  148. final year = int.parse(match.group(2)!);
  149. final month = int.parse(match.group(3)!);
  150. final day = int.parse(match.group(4)!);
  151. final birthDate = DateTime(year, month, day);
  152. String age = DataTimeUtils.calculateAge(birthDate);
  153. return age;
  154. }
  155. return ''; // 返回一个默认值
  156. }
  157. /// 登记列表表头
  158. List<TableColumn<ResidentModel>> buildTableColumns(
  159. BuildContext context,
  160. bool? isVital,
  161. ) {
  162. /// 是否是一体机
  163. bool isIntegralDesk = isVital ?? false;
  164. var textStyle = TextStyle(
  165. fontSize: 18,
  166. overflow: TextOverflow.ellipsis,
  167. fontFamily: "NotoSansSC",
  168. );
  169. return <TableColumn<ResidentModel>>[
  170. TableColumn<ResidentModel>(
  171. headerText: "体检号",
  172. flex: 5,
  173. render: (rowData, index) => Container(
  174. padding: const EdgeInsets.symmetric(vertical: kIsWeb ? 10 : 16),
  175. child: OverflowTooltipWrapper(
  176. child: Text(
  177. rowData.physicalExamNumber ?? '',
  178. style: textStyle,
  179. ),
  180. ),
  181. ),
  182. ),
  183. TableColumn<ResidentModel>(
  184. flex: 3,
  185. headerText: "姓名",
  186. render: (rowData, index) => Center(
  187. child: Text(
  188. rowData.name ?? '',
  189. style: textStyle,
  190. ),
  191. ),
  192. ),
  193. if (isIntegralDesk)
  194. TableColumn<ResidentModel>(
  195. headerText: "年龄",
  196. flex: 3,
  197. render: (rowData, index) => Center(
  198. child: Text(
  199. rowData.age != null ? rowData.age.toString() : "",
  200. style: textStyle,
  201. ),
  202. ),
  203. ),
  204. TableColumn<ResidentModel>(
  205. headerText: "身份证号",
  206. flex: 6,
  207. render: (rowData, index) => Center(
  208. child: Text(
  209. rowData.idNumber,
  210. style: textStyle,
  211. ),
  212. ),
  213. ),
  214. TableColumn<ResidentModel>(
  215. headerText: "手机号",
  216. flex: 4,
  217. render: (rowData, index) => Center(
  218. child: Text(
  219. rowData.phone == "" ? "-" : rowData.phone ?? '-',
  220. style: textStyle,
  221. ),
  222. ),
  223. ),
  224. TableColumn<ResidentModel>(
  225. headerRender: () {
  226. return Center(
  227. child: Padding(
  228. padding: EdgeInsets.only(right: 15),
  229. child: Text(
  230. "体检时间",
  231. style: TextStyle(
  232. fontSize: 20,
  233. ),
  234. ),
  235. ),
  236. );
  237. },
  238. flex: 3,
  239. render: (rowData, index) => Center(
  240. child: Text(
  241. rowData.physicalExamTime == null
  242. ? ""
  243. : DataTimeUtils.formatDateString(rowData.physicalExamTime!),
  244. style: textStyle,
  245. ),
  246. ),
  247. ),
  248. // if (isIntegralDesk)
  249. TableColumn<ResidentModel>(
  250. headerText: "责任医生",
  251. maxWidth: 120,
  252. flex: 4,
  253. render: (rowData, index) => Center(
  254. child: Text(
  255. rowData.createdDoctorName ?? "",
  256. style: textStyle,
  257. ),
  258. ),
  259. ),
  260. // if (!isIntegralDesk)
  261. // TableColumn<ResidentModel>(
  262. // headerRender: () {
  263. // return Center(
  264. // child: Padding(
  265. // padding: EdgeInsets.only(right: 15),
  266. // child: Text(
  267. // "体检状态",
  268. // style: TextStyle(
  269. // fontSize: 20,
  270. // ),
  271. // ),
  272. // ),
  273. // );
  274. // },
  275. // flex: 3,
  276. // render: (rowData, index) => Center(
  277. // child: Text(
  278. // rowData.physicalExamStatus ?? "",
  279. // style: textStyle,
  280. // ),
  281. // ),
  282. // ),
  283. TableColumn<ResidentModel>(
  284. headerText: "操作",
  285. flex: 7,
  286. render: (rowData, index) => FittedBox(
  287. child: Row(
  288. mainAxisAlignment: MainAxisAlignment.center,
  289. children: [
  290. if (!FPlatform.isPureWeb && !isIntegralDesk) ...[
  291. _buildPrint(context, rowData),
  292. ],
  293. _buildEditRegistration(rowData),
  294. _buildHealthCheck(rowData, isIntegralDesk),
  295. _buildEditingExcepting(rowData),
  296. _buildShowReport(rowData),
  297. ],
  298. ),
  299. ),
  300. ),
  301. ];
  302. }
  303. /// 打印按钮
  304. Widget _buildPrint(BuildContext context, ResidentModel rowData) {
  305. return TextButton(
  306. onPressed: () async {
  307. advanceDebounce(() async {
  308. Store.app.setBusy("加载中...");
  309. try {
  310. await registrationController.getExamLabelsByExamNoAsync(rowData);
  311. } catch (e) {
  312. print(e);
  313. }
  314. Store.app.busy = false;
  315. Get.dialog(
  316. Center(
  317. child: Container(
  318. width: MediaQuery.of(context).size.width * 0.7,
  319. height: MediaQuery.of(context).size.height,
  320. child: Center(
  321. child: PrintPreview(
  322. imageList: registrationController.barCodeList,
  323. printInfo:
  324. registrationController.printInfo ?? PrinterInfo(),
  325. ),
  326. ),
  327. ),
  328. ),
  329. );
  330. }, "print label", 3000);
  331. },
  332. child: const Text(
  333. "打印标签",
  334. style: TextStyle(fontSize: 18),
  335. ),
  336. );
  337. }
  338. /// 编辑按钮
  339. Widget _buildEditRegistration(ResidentModel rowData) {
  340. return TextButton(
  341. onPressed: () async {
  342. final RegistrationInfoModel? patient = RegistrationInfoModel(
  343. patientName: rowData.name,
  344. phone: rowData.phone,
  345. patientAddress: rowData.homeAddress,
  346. cardNo: rowData.idNumber,
  347. code: rowData.code,
  348. birthday: rowData.birthDay,
  349. patientGender: RegistrationInfoModel.getGenderEnum(rowData.sex),
  350. );
  351. final RegistrationInfoModel? result =
  352. await Get.dialog<RegistrationInfoModel>(
  353. RegistrationFormDialog(
  354. patient: patient,
  355. isEdit: true,
  356. ),
  357. barrierDismissible: false,
  358. );
  359. registrationController.formController.editResident(result);
  360. print(result);
  361. },
  362. child: const Text(
  363. "编辑",
  364. style: TextStyle(fontSize: 18),
  365. ),
  366. );
  367. }
  368. Future<List<PrescriptionDTO>?> getPrescriptionList(
  369. String patientCode,
  370. String physicalExamNumber,
  371. ) async {
  372. // 获取处方列表
  373. List<PrescriptionDTO>? prescriptionList =
  374. await _prescriptionManager.getPrescriptionPage(
  375. patientCode: patientCode,
  376. physicalExamNumber: physicalExamNumber,
  377. );
  378. return prescriptionList;
  379. }
  380. /// 健康指导
  381. Widget _buildEditingExcepting(ResidentModel rowData) {
  382. const designWidth = 1280.0; // 设计尺寸宽度:1280
  383. final width = Get.width;
  384. final scale = width / designWidth; // 计算缩放比例
  385. return TextButton(
  386. onPressed: () async {
  387. state.resultsAndSuggestions = rowData.resultsAndSuggestions;
  388. state.prescriptionList = await getPrescriptionList(
  389. rowData.idNumber,
  390. rowData.physicalExamNumber ?? '',
  391. ) ??
  392. [];
  393. Get.dialog(
  394. VAlertDialog(
  395. width: width / scale * 0.85,
  396. onConfirm: () async {
  397. final result =
  398. await _registrationManager.updateResultsAndSuggestionsAsync(
  399. rowData.code ?? "", state.resultsAndSuggestions ?? '');
  400. if (result) {
  401. rowData.resultsAndSuggestions =
  402. state.resultsAndSuggestions; // 内存更新
  403. Get.back(); // Close the dialog
  404. } else {
  405. PromptBox.toast("保存失败");
  406. }
  407. },
  408. confirmLabel: "提交",
  409. content: Container(
  410. padding: EdgeInsets.all(8.0),
  411. child: Stack(
  412. children: [
  413. Column(
  414. crossAxisAlignment: CrossAxisAlignment.start,
  415. children: [
  416. SizedBox(
  417. height: 20,
  418. ),
  419. Expanded(
  420. child: Container(
  421. padding: EdgeInsets.symmetric(horizontal: 32),
  422. child: TextField(
  423. expands: false,
  424. maxLines: 10,
  425. controller: TextEditingController(
  426. text: rowData.resultsAndSuggestions,
  427. ),
  428. decoration: InputDecoration(
  429. hintText: '请输入健康指导信息...',
  430. border: OutlineInputBorder(
  431. borderRadius: BorderRadius.all(
  432. Radius.circular(8.0),
  433. ), // 可以调整边框圆角度数
  434. ),
  435. contentPadding: EdgeInsets.all(16), // 调整文本内边距
  436. ),
  437. onChanged: (value) {
  438. state.resultsAndSuggestions = value;
  439. },
  440. ),
  441. ),
  442. ),
  443. SizedBox(
  444. height: 20,
  445. ),
  446. Container(
  447. padding: EdgeInsets.only(left: 30),
  448. width: 280,
  449. height: 54,
  450. alignment: Alignment.centerRight,
  451. child: VButton(
  452. onTap: () async {
  453. await Get.dialog(
  454. ExaminationPrescription(
  455. physicalExamNumber: rowData.physicalExamNumber,
  456. patientCode: rowData.idNumber,
  457. prescription: "",
  458. prescriptionTitle: "",
  459. ),
  460. );
  461. state.prescriptionList = await getPrescriptionList(
  462. rowData.idNumber,
  463. rowData.physicalExamNumber ?? '',
  464. ) ??
  465. [];
  466. },
  467. label: '开具健康教育处方',
  468. ),
  469. ),
  470. SizedBox(
  471. height: 10,
  472. ),
  473. _buildPrescriptionList(
  474. rowData.physicalExamNumber ?? '',
  475. rowData.idNumber,
  476. ),
  477. SizedBox(
  478. height: 20,
  479. ),
  480. ],
  481. ),
  482. ],
  483. ),
  484. ),
  485. ),
  486. barrierDismissible:
  487. false, // Prevent dialog from closing on outside tap
  488. );
  489. },
  490. child: const Text(
  491. "健康指导",
  492. style: TextStyle(fontSize: 18),
  493. ),
  494. );
  495. }
  496. Widget _buildPrescriptionList(
  497. String physicalExamNumber,
  498. String patientCode,
  499. ) {
  500. ScrollController _scrollController = ScrollController();
  501. return Obx(() {
  502. if (state.prescriptionList.isNotEmpty)
  503. return Container(
  504. alignment: Alignment.centerLeft,
  505. padding: EdgeInsets.only(left: 30),
  506. child: Column(
  507. crossAxisAlignment: CrossAxisAlignment.start,
  508. children: [
  509. SizedBox(width: 30),
  510. Container(
  511. margin: EdgeInsets.only(bottom: 8, top: 8),
  512. child: Text(
  513. '处方列表',
  514. style: TextStyle(
  515. fontSize: 26,
  516. fontWeight: FontWeight.bold,
  517. ),
  518. ),
  519. ),
  520. SizedBox(width: 16),
  521. Container(
  522. height: 95,
  523. child: AlwaysScrollListView(
  524. scrollController: _scrollController,
  525. child: Container(
  526. padding: EdgeInsets.only(bottom: 8),
  527. child: ListView(
  528. controller: _scrollController,
  529. shrinkWrap: true,
  530. scrollDirection: Axis.horizontal,
  531. children: [
  532. ...state.prescriptionList.map(
  533. (e) => InkWell(
  534. radius: 8,
  535. onTap: () async {
  536. await Get.dialog(
  537. ExaminationPrescription(
  538. physicalExamNumber: physicalExamNumber,
  539. patientCode: patientCode,
  540. prescription: e.prescriptionTemplateKey ?? '',
  541. prescriptionTitle:
  542. '${PrescriptionFormKeys.AllFormKeys[e.prescriptionTemplateKey ?? '']}',
  543. isEdit: true,
  544. ),
  545. );
  546. },
  547. child: Container(
  548. decoration: BoxDecoration(
  549. border: Border.all(
  550. color: Colors.black26,
  551. ),
  552. borderRadius: BorderRadius.all(
  553. Radius.circular(8),
  554. ),
  555. ),
  556. margin: EdgeInsets.all(8),
  557. padding:
  558. const EdgeInsets.all(8).copyWith(left: 30),
  559. child: Container(
  560. width: 380,
  561. child: Row(
  562. children: [
  563. Expanded(
  564. child: Text(
  565. '${PrescriptionFormKeys.AllFormKeys[e.prescriptionTemplateKey ?? '']}',
  566. style: TextStyle(
  567. fontSize: 24,
  568. fontWeight: FontWeight.bold,
  569. ),
  570. overflow: TextOverflow.ellipsis,
  571. ),
  572. ),
  573. Container(
  574. width: 60,
  575. padding: EdgeInsets.only(
  576. right: 8,
  577. ),
  578. child: IconButton(
  579. onPressed: () {
  580. Get.dialog(
  581. VAlertDialog(
  582. title: "提示",
  583. onConfirm: () async {
  584. bool? result =
  585. await _prescriptionManager
  586. .removePrescription(
  587. prescriptionCode:
  588. e.code ?? '',
  589. );
  590. if (result ?? false) {
  591. state.prescriptionList =
  592. await getPrescriptionList(
  593. patientCode,
  594. physicalExamNumber,
  595. ) ??
  596. [];
  597. Get.back();
  598. } else {
  599. PromptBox.toast("删除失败");
  600. }
  601. },
  602. content: Container(
  603. alignment: Alignment.center,
  604. height: 60,
  605. child: Text(
  606. "确认是否删除 ${PrescriptionFormKeys.AllFormKeys[e.prescriptionTemplateKey ?? '']}",
  607. style: TextStyle(
  608. fontSize: 24,
  609. ),
  610. ),
  611. ),
  612. ),
  613. );
  614. },
  615. icon: Icon(
  616. Icons.close,
  617. size: 40,
  618. ),
  619. ),
  620. )
  621. ],
  622. ),
  623. ),
  624. ),
  625. ),
  626. ),
  627. ],
  628. ),
  629. ),
  630. ),
  631. ),
  632. ],
  633. ),
  634. );
  635. return Container();
  636. });
  637. }
  638. /// 查看报告
  639. Widget _buildShowReport(ResidentModel rowData) {
  640. return TextButton(
  641. onPressed: () {
  642. Debouncer.run(
  643. () async {
  644. PromptBox.dismiss();
  645. Store.app.busy = true;
  646. List<ReportDTO2>? reportList = await registrationController
  647. .registrationManager
  648. .getVitalReportInfoAsync(
  649. physicalExamNumber: rowData.physicalExamNumber ?? '',
  650. );
  651. Store.app.busy = false;
  652. ReportDTO2? report = reportList
  653. ?.firstWhereOrNull((element) => element.key == "Part");
  654. if (report != null) {
  655. logger.i("show report:${report.code}");
  656. Get.dialog(
  657. ReportPreview(
  658. pdfUrl: report.previewInfo?.fileToken ?? "",
  659. ),
  660. );
  661. } else {
  662. PromptBox.showToast(
  663. '暂无报告',
  664. maskType: EasyLoadingMaskType.none, // 设置为none以允许用户操作其他控件
  665. );
  666. }
  667. },
  668. duration: Duration(milliseconds: 300),
  669. );
  670. },
  671. child: const Text(
  672. "查看报告",
  673. style: TextStyle(fontSize: 18),
  674. ),
  675. );
  676. }
  677. void _examDialog(ResidentModel rowData, bool isIntegralDesk) async {
  678. final FEventHandler<bool> onSubmitEvent = FEventHandler<bool>();
  679. /// 需要检测页面回调数据
  680. Get.put(MedicalController());
  681. Get.dialog(
  682. Scaffold(
  683. body: Stack(
  684. children: [
  685. ExaminationPage(
  686. idCard: rowData.idNumber,
  687. onSubmitEvent: onSubmitEvent,
  688. physicalExamNumber: rowData.physicalExamNumber ?? '',
  689. ),
  690. Positioned(
  691. left: 16,
  692. bottom: 16,
  693. child: _buildMedicalButton(rowData.idNumber),
  694. )
  695. ],
  696. ),
  697. appBar: VAppBar(
  698. titleText: "体检",
  699. actions: [
  700. TextButton.icon(
  701. onPressed: () async {
  702. onSubmitEvent.emit(this, true);
  703. },
  704. label: Text(
  705. '保存',
  706. style: TextStyle(fontSize: 20, color: Colors.white),
  707. ),
  708. icon: Icon(Icons.save, size: 32, color: Colors.white),
  709. ),
  710. const SizedBox(width: 8),
  711. ],
  712. iconBack: () {
  713. onSubmitEvent.emit(this, false);
  714. Get.delete<MedicalController>();
  715. },
  716. ),
  717. ),
  718. );
  719. }
  720. Widget _buildMedicalButton(String patientCode) {
  721. if (_hasHealthMonitor()) {
  722. return Container(
  723. width: 214,
  724. margin: EdgeInsets.only(right: 10),
  725. child: VButton(
  726. onTap: () async {
  727. var diagnosis = await Get.find<IDiagnosisManager>()
  728. .getDiagnosisAggregationPageAsync(patientCode, 1, 10);
  729. if (diagnosis?.pageData?.isNotEmpty ?? false) {
  730. try {
  731. Map<String, dynamic> diagnosisDataValue = {};
  732. for (DiagnosisAggregationRecordModel data
  733. in diagnosis!.pageData!) {
  734. if (data.diagnosisAggregationData?.isNotEmpty ?? false) {
  735. for (DiagnosisAggregationData diaData
  736. in data.diagnosisAggregationData!) {
  737. diagnosisDataValue[diaData.key ?? ''] =
  738. jsonDecode(diaData.diagnosisData ?? '');
  739. }
  740. break;
  741. }
  742. }
  743. var medicalController = Get.find<MedicalController>();
  744. medicalController.diagnosisDataValue = diagnosisDataValue;
  745. } catch (e) {}
  746. }
  747. Get.dialog<MedicalController>(
  748. Scaffold(
  749. body: ExamMedicalPage(
  750. isHealthCheck: true,
  751. ),
  752. appBar: VAppBar(
  753. titleText: "检测",
  754. ),
  755. ),
  756. );
  757. },
  758. child: Text(
  759. '检测',
  760. style: TextStyle(fontSize: 26),
  761. ),
  762. ),
  763. );
  764. }
  765. return SizedBox();
  766. }
  767. /// 体检
  768. Widget _buildHealthCheck(ResidentModel rowData, bool isIntegralDesk) {
  769. return TextButton(
  770. onPressed: () {
  771. advanceDebounce(
  772. () async {
  773. await Get.find<IPatientManager>()
  774. .switchCurrentPatientByCode(rowData.idNumber);
  775. if (Get.isRegistered<ExaminationController>()) {
  776. Get.delete<ExaminationController>();
  777. }
  778. Get.put(
  779. ExaminationController(
  780. patientCode: rowData.idNumber,
  781. batchNumber: rowData.batchNumber ?? '',
  782. ),
  783. );
  784. _examDialog(rowData, isIntegralDesk);
  785. },
  786. "HealthCheck",
  787. );
  788. },
  789. child: const Text(
  790. "填表",
  791. style: TextStyle(fontSize: 18),
  792. ),
  793. );
  794. }
  795. }