list.dart 15 KB

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