list.dart 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  1. import 'package:fis_common/event/event_type.dart';
  2. import 'package:fis_jsonrpc/rpc.dart';
  3. import 'package:flutter/foundation.dart';
  4. import 'package:flutter/material.dart';
  5. import 'package:get/get.dart';
  6. import 'package:vitalapp/architecture/utils/datetime.dart';
  7. import 'package:vitalapp/architecture/utils/prompt_box.dart';
  8. import 'package:vitalapp/components/appbar.dart';
  9. import 'package:vitalapp/components/table/table_column.dart';
  10. import 'package:vitalapp/managers/interfaces/registration.dart';
  11. import 'package:vitalapp/pages/check/examination/controller.dart';
  12. import 'package:vitalapp/pages/check/examination/view.dart';
  13. import 'package:vitalapp/pages/medical_checkup_station/registration/controller.dart';
  14. import 'package:vitalapp/pages/medical_checkup_station/registration/state/list.dart';
  15. import 'package:vitalapp/pages/medical_checkup_station/registration/widgets/form/index.dart';
  16. import 'package:vitalapp/pages/medical_checkup_station/registration/widgets/report/report_preview.dart';
  17. import 'package:vitalapp/pages/medical_checkup_station/usb_print/module/printer_info.dart';
  18. import 'package:vitalapp/pages/medical_checkup_station/usb_print/page/temp/print_preview.dart';
  19. class RegistrationListController {
  20. late RegistrationController registrationController;
  21. RegistrationListController(RegistrationController controller) {
  22. registrationController = controller;
  23. }
  24. final state = ListState();
  25. final _registrationManager = Get.find<IRegistrationManager>();
  26. ResidentModel currentResident = ResidentModel(idNumber: "");
  27. List<String> _allExam = [
  28. "HEIBasic",
  29. "HEIUrinalysis",
  30. "HEIUltrasonic",
  31. "HEIBiochemical",
  32. "HEIBloodRoutine",
  33. "HEIECG",
  34. "HEITCMC"
  35. ];
  36. List<String> examList() {
  37. List<String> missingData = _allExam
  38. .where((element) =>
  39. !(currentResident.finishedExamKeys ?? []).contains(element))
  40. .toList();
  41. return missingData;
  42. }
  43. Future<void> getRegisterInfoPage({
  44. int? pageSize = 10,
  45. int? pageIndex = 1,
  46. String? keyword = "",
  47. DateTime? startTime,
  48. DateTime? endTime,
  49. }) async {
  50. registrationController.tableLoading = true;
  51. registrationController.currPageIndex = pageIndex!;
  52. var result = await registrationController.registrationManager
  53. .getRegisterInfoPageAsync(
  54. pageSize: pageSize,
  55. pageIndex: pageIndex,
  56. keyword: keyword,
  57. startTime: startTime,
  58. endTime: endTime,
  59. );
  60. List<ResidentModel> _residentList = [];
  61. if (result?.pageData != null) {
  62. for (RegisterInfoDTO i in result!.pageData!) {
  63. String statusStr = '';
  64. ExamStateEnum status = i.state;
  65. switch (status) {
  66. case ExamStateEnum.Unchecked:
  67. statusStr = "未体检";
  68. break;
  69. case ExamStateEnum.Invalid:
  70. statusStr = "已作废";
  71. break;
  72. case ExamStateEnum.Inspected:
  73. statusStr = "已体检";
  74. break;
  75. case ExamStateEnum.Reported:
  76. statusStr = "已报告";
  77. break;
  78. }
  79. _residentList.add(
  80. ResidentModel(
  81. name: i.name ?? '',
  82. idNumber: i.iDCardNo ?? '',
  83. code: i.code ?? '',
  84. homeAddress: i.adress,
  85. age: getAgeOfIdNumber(i.iDCardNo ?? ''),
  86. physicalExamNumber: i.physicalExamNumber,
  87. phone: i.phone,
  88. finishedExamKeys: i.finishedExamKeys,
  89. physicalExamStatus: statusStr,
  90. birthDay: i.birthday,
  91. sex: i.sex,
  92. batchNumber: i.batchNumber,
  93. ),
  94. );
  95. }
  96. registrationController.appointmentModelListLength = result.totalCount;
  97. }
  98. registrationController.residentList = _residentList;
  99. registrationController.tableLoading = false;
  100. registrationController.update(["registration_table"]);
  101. registrationController.update(["registration_table_pagination"]);
  102. }
  103. String getAgeOfIdNumber(String idNumber) {
  104. if (idNumber.isEmpty) return '';
  105. final idCardRegex = RegExp(r'^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})(\d|X)$');
  106. final match = idCardRegex.firstMatch(idNumber);
  107. if (match != null) {
  108. final year = int.parse(match.group(2)!);
  109. final month = int.parse(match.group(3)!);
  110. final day = int.parse(match.group(4)!);
  111. final birthDate = DateTime(year, month, day);
  112. String age = DataTimeUtils.calculateAge(birthDate);
  113. return age;
  114. }
  115. return ''; // 返回一个默认值
  116. }
  117. /// 登记列表表头
  118. List<TableColumn<ResidentModel>> buildTableColumns(BuildContext context) {
  119. var textStyle = TextStyle(
  120. fontSize: 18,
  121. overflow: TextOverflow.ellipsis,
  122. );
  123. return <TableColumn<ResidentModel>>[
  124. TableColumn<ResidentModel>(
  125. headerText: "体检号",
  126. maxWidth: 150,
  127. render: (rowData, index) => Container(
  128. padding: const EdgeInsets.symmetric(vertical: 16),
  129. child: Text(
  130. rowData.physicalExamNumber ?? '',
  131. style: textStyle,
  132. ),
  133. ),
  134. ),
  135. TableColumn<ResidentModel>(
  136. headerText: "姓名",
  137. maxWidth: 100,
  138. render: (rowData, index) => Text(
  139. rowData.name ?? '',
  140. style: textStyle,
  141. ),
  142. ),
  143. TableColumn<ResidentModel>(
  144. headerText: "年龄",
  145. maxWidth: 80,
  146. render: (rowData, index) => Text(
  147. rowData.age != null ? rowData.age.toString() : "",
  148. style: textStyle,
  149. ),
  150. ),
  151. TableColumn<ResidentModel>(
  152. headerText: "身份证号",
  153. // maxWidth: 200,
  154. render: (rowData, index) => Center(
  155. child: Text(
  156. rowData.idNumber,
  157. style: textStyle,
  158. ),
  159. ),
  160. ),
  161. TableColumn<ResidentModel>(
  162. headerText: "手机号",
  163. maxWidth: 120,
  164. render: (rowData, index) => Center(
  165. child: Text(
  166. rowData.phone ?? '',
  167. style: textStyle,
  168. ),
  169. ),
  170. ),
  171. TableColumn<ResidentModel>(
  172. headerText: "体检状态",
  173. maxWidth: 120,
  174. render: (rowData, index) => Center(
  175. child: Text(
  176. rowData.physicalExamStatus ?? "",
  177. style: textStyle,
  178. ),
  179. ),
  180. ),
  181. TableColumn<ResidentModel>(
  182. headerText: "操作",
  183. maxWidth: 360,
  184. width: 200,
  185. render: (rowData, index) => FittedBox(
  186. child: Row(
  187. mainAxisAlignment: MainAxisAlignment.center,
  188. children: [
  189. _buildPrint(context, rowData),
  190. _buildEditRegistration(rowData),
  191. if (kIsWeb) _buildEditingExcepting(rowData),
  192. if (kIsWeb) _buildShowReport(rowData),
  193. _buildHealthCheck(rowData),
  194. ],
  195. ),
  196. ),
  197. ),
  198. ];
  199. }
  200. /// 打印按钮
  201. Widget _buildPrint(BuildContext context, ResidentModel rowData) {
  202. return TextButton(
  203. onPressed: () async {
  204. // if (registrationController.printInfo == null) {
  205. // PromptBox.toast("打印出错");
  206. // return;
  207. // }
  208. // if (kIsWeb) {
  209. await registrationController.getExamLabelsByExamNoAsync(rowData);
  210. // } else {
  211. Get.dialog(
  212. Center(
  213. child: Container(
  214. width: MediaQuery.of(context).size.width * 0.7,
  215. height: MediaQuery.of(context).size.height,
  216. child: Center(
  217. child: PrintPreview(
  218. imageList: registrationController.barCodeList,
  219. printInfo: registrationController.printInfo ?? PrinterInfo(),
  220. ),
  221. ),
  222. ),
  223. ),
  224. );
  225. // }
  226. },
  227. child: const Text(
  228. "打印标签",
  229. style: TextStyle(fontSize: 18),
  230. ),
  231. );
  232. }
  233. /// 编辑按钮
  234. Widget _buildEditRegistration(ResidentModel rowData) {
  235. return TextButton(
  236. onPressed: () async {
  237. final PatientDTO? patient = PatientDTO(
  238. patientName: rowData.name,
  239. phone: rowData.phone,
  240. patientAddress: rowData.homeAddress,
  241. cardNo: rowData.idNumber,
  242. code: rowData.code,
  243. birthday: rowData.birthDay,
  244. patientGender: rowData.sex == "男"
  245. ? GenderEnum.Male
  246. : rowData.sex == "女"
  247. ? GenderEnum.Female
  248. : GenderEnum.Unknown,
  249. );
  250. final PatientDTO? result = await Get.dialog<PatientDTO>(
  251. RegistrationFormDialog(
  252. patient: patient,
  253. isEdit: true,
  254. ),
  255. barrierDismissible: false,
  256. );
  257. registrationController.formController.editResident(result);
  258. print(result);
  259. },
  260. child: const Text(
  261. "编辑",
  262. style: TextStyle(fontSize: 18),
  263. ),
  264. );
  265. }
  266. /// 健康指导
  267. Widget _buildEditingExcepting(ResidentModel rowData) {
  268. return TextButton(
  269. onPressed: () {
  270. Get.dialog(
  271. Dialog(
  272. backgroundColor: Colors.white, // 设置对话框背景颜色为白色
  273. child: Container(
  274. padding: EdgeInsets.all(16.0),
  275. child: Stack(
  276. children: [
  277. Column(
  278. children: [
  279. SizedBox(
  280. height: 20,
  281. ),
  282. Expanded(
  283. child: TextField(
  284. expands: true,
  285. maxLines: null,
  286. decoration: InputDecoration(
  287. hintText: '请输入健康指导信息...',
  288. border: InputBorder.none,
  289. ),
  290. onChanged: (value) {
  291. state.resultsAndSuggestions = value;
  292. },
  293. ),
  294. ),
  295. ElevatedButton(
  296. onPressed: () async {
  297. await _registrationManager
  298. .updateResultsAndSuggestionsAsync(
  299. rowData.code ?? "",
  300. state.resultsAndSuggestions ?? '');
  301. Get.back(); // Close the dialog
  302. },
  303. child: Text(
  304. '提交',
  305. style: TextStyle(fontSize: 18),
  306. ),
  307. ),
  308. ],
  309. ),
  310. Positioned(
  311. top: 1.0,
  312. right: 1.0,
  313. child: IconButton(
  314. icon: Icon(Icons.close),
  315. onPressed: () {
  316. Get.back();
  317. },
  318. ),
  319. ),
  320. ],
  321. ),
  322. ),
  323. ),
  324. barrierDismissible:
  325. false, // Prevent dialog from closing on outside tap
  326. );
  327. },
  328. child: const Text(
  329. "健康指导",
  330. style: TextStyle(fontSize: 18),
  331. ));
  332. }
  333. /// 查看报告
  334. Widget _buildShowReport(ResidentModel rowData) {
  335. return TextButton(
  336. onPressed: () async {
  337. List<ReportDTO2>? reportList = await registrationController
  338. .registrationManager
  339. .getVitalReportInfoAsync(
  340. physicalExamNumber: rowData.physicalExamNumber ?? '',
  341. );
  342. ReportDTO2? report =
  343. reportList?.firstWhereOrNull((element) => element.key == "Part");
  344. if (report != null) {
  345. Get.dialog(
  346. ReportPreview(
  347. pdfUrl: report.previewInfo?.fileToken ?? "",
  348. ),
  349. );
  350. } else {
  351. PromptBox.toast("暂无报告");
  352. }
  353. },
  354. child: const Text(
  355. "查看报告",
  356. style: TextStyle(fontSize: 18),
  357. ),
  358. );
  359. }
  360. /// 体检
  361. Widget _buildHealthCheck(ResidentModel rowData) {
  362. return TextButton(
  363. onPressed: () async {
  364. Get.lazyPut(
  365. () => ExaminationController(
  366. patientCode: rowData.idNumber,
  367. batchNumber: rowData.batchNumber ?? '',
  368. ),
  369. );
  370. final FEventHandler<bool> onSubmitEvent = FEventHandler<bool>();
  371. Get.dialog(
  372. Scaffold(
  373. body: ExaminationPage(
  374. idCard: rowData.idNumber,
  375. onSubmitEvent: onSubmitEvent,
  376. ),
  377. appBar: VAppBar(
  378. titleText: "体检",
  379. actions: [
  380. Container(
  381. margin: EdgeInsets.only(right: 10),
  382. child: ElevatedButton(
  383. onPressed: () async {
  384. onSubmitEvent.emit(this, true);
  385. },
  386. child: Text('保存'),
  387. ),
  388. ),
  389. // Container(
  390. // margin: EdgeInsets.only(right: 10),
  391. // child: ElevatedButton(
  392. // onPressed: () async {
  393. // final controller = Get.find<ExaminationController>();
  394. // // onCloseEvent.emit(this, true);
  395. // final isExamEmpty = await controller.checkExamEmpty();
  396. // if (isExamEmpty) {
  397. // PromptBox.toast("不能提交空数据");
  398. // } else {
  399. // Get.dialog(VAlertDialog(
  400. // title: '提示',
  401. // content: Container(
  402. // margin: const EdgeInsets.only(bottom: 20),
  403. // child: const Text(
  404. // '确定结束本次体检?',
  405. // style: TextStyle(fontSize: 20),
  406. // textAlign: TextAlign.center,
  407. // ),
  408. // ),
  409. // showCancel: true,
  410. // onConfirm: () {
  411. // controller.deleteCached();
  412. // Get.back();
  413. // },
  414. // ));
  415. // }
  416. // },
  417. // child: Text('结束本轮体检'),
  418. // ),
  419. // ),
  420. ],
  421. iconBack: () {
  422. onSubmitEvent.emit(this, true);
  423. },
  424. ),
  425. ),
  426. );
  427. },
  428. child: const Text(
  429. "体检",
  430. style: TextStyle(fontSize: 18),
  431. ),
  432. );
  433. }
  434. }