view.dart 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529
  1. import 'package:fis_jsonrpc/services/vitalFollowUp.m.dart';
  2. import 'package:flutter/material.dart';
  3. import 'package:get/get.dart';
  4. import 'package:intl/intl.dart';
  5. import 'package:vitalapp/architecture/utils/prompt_box.dart';
  6. import 'package:vitalapp/components/alert_dialog.dart';
  7. import 'package:vitalapp/components/appbar.dart';
  8. import 'package:vitalapp/components/button.dart';
  9. import 'package:vitalapp/components/no_data_view.dart';
  10. import 'package:vitalapp/components/qr_code_with_logo/qr_code_with_logo.dart';
  11. import 'package:vitalapp/consts/styles.dart';
  12. import 'package:vitalapp/database/entities/defines.dart';
  13. import 'package:vitalapp/managers/interfaces/follow_up.dart';
  14. import 'package:vitalapp/pages/check/prescription/pediatric_prescription_collection.dart';
  15. import 'package:vitalapp/pages/check/prescription/prescription_form_keys.dart';
  16. import 'package:vitalapp/pages/form/form_info.dart';
  17. import 'package:vitalapp/pages/patient/list/widgets/status.dart';
  18. import 'package:vitalapp/pages/widgets/record_common_item.dart';
  19. import 'forms/antenatal_visit.dart';
  20. import 'forms/checkup_42_days.dart';
  21. import 'forms/first_form.dart';
  22. import 'forms/postpartum_follow_up.dart';
  23. import 'widgets/delete_follow_up_record_button.dart';
  24. import 'widgets/form_select_dialog.dart';
  25. import 'controller.dart';
  26. class MaternalHealthManagement
  27. extends GetView<MaternalHealthManagementController> {
  28. MaternalHealthManagement({Key? key}) : super(key: key);
  29. final _followUpManager = Get.find<IFollowUpManager>();
  30. @override
  31. Widget build(BuildContext context) {
  32. return GetBuilder(
  33. init: MaternalHealthManagementController(),
  34. id: "SelfCareAbilityAssessmentRecord",
  35. builder: (_) {
  36. return Scaffold(
  37. backgroundColor: const Color.fromRGBO(238, 238, 238, 1),
  38. appBar: VAppBar(
  39. titleWidget: const Text("孕产妇健康管理"),
  40. actions: [
  41. IconButton(
  42. onPressed: () async {
  43. FormInfo.instance.formValue.clear();
  44. controller.isEdit = false;
  45. Get.dialog(FormSelectDialog(
  46. onConfirm: (time, mode, isAfter, isAfterFirst) {
  47. Get.back();
  48. controller.recordCode = "";
  49. controller.followUpMode = mode;
  50. if (isAfter) {
  51. if (isAfterFirst) {
  52. Get.to(PostpartumFormView(
  53. onClickPrescribe: (followUpCode) async {
  54. /// 因为孕产妇使用的是单例和处方是同个数据
  55. controller.maternalFormValue =
  56. FormInfo.instance.formValue;
  57. var result = await Get.to(
  58. PrescriptionCollection(
  59. controller.recordCode,
  60. isChild: false,
  61. createFollowUpOnly: () async {
  62. await controller.save(
  63. "PostnatalVisitRecord", followUpCode);
  64. var recordCode = controller.recordCode;
  65. if (recordCode.isNotEmpty) {
  66. controller.isEdit = true;
  67. }
  68. return recordCode;
  69. },
  70. ),
  71. );
  72. FormInfo.instance.formValue =
  73. controller.maternalFormValue;
  74. return result;
  75. },
  76. ));
  77. } else {
  78. Get.to(PostpartumHealthCheckup42DaysForm(
  79. onClickPrescribe: (followUpCode) async {
  80. controller.maternalFormValue =
  81. FormInfo.instance.formValue;
  82. var result = await Get.to(
  83. PrescriptionCollection(
  84. controller.recordCode,
  85. isChild: false,
  86. createFollowUpOnly: () async {
  87. await controller.save(
  88. "PostpartumHealthCheckup42Days",
  89. followUpCode);
  90. var recordCode = controller.recordCode;
  91. if (recordCode.isNotEmpty) {
  92. controller.isEdit = true;
  93. }
  94. return recordCode;
  95. },
  96. ),
  97. );
  98. FormInfo.instance.formValue =
  99. controller.maternalFormValue;
  100. return result;
  101. },
  102. ));
  103. }
  104. return;
  105. }
  106. if (time == 1) {
  107. Get.to(FirstMaternalHealthManagementForm(
  108. onClickPrescribe: (followUpCode) async {
  109. controller.maternalFormValue =
  110. FormInfo.instance.formValue;
  111. var result = await Get.to(
  112. PrescriptionCollection(
  113. controller.recordCode,
  114. isChild: false,
  115. createFollowUpOnly: () async {
  116. await controller.save(
  117. "MaternalHealthManagement", followUpCode);
  118. var recordCode = controller.recordCode;
  119. if (recordCode.isNotEmpty) {
  120. controller.isEdit = true;
  121. }
  122. return recordCode;
  123. },
  124. ),
  125. );
  126. FormInfo.instance.formValue =
  127. controller.maternalFormValue;
  128. return result;
  129. },
  130. ));
  131. } else if (time >= 2 && time <= 5) {
  132. Get.to(
  133. AntenatalVisitForm(
  134. time,
  135. onClickPrescribe: (followUpCode) async {
  136. controller.maternalFormValue =
  137. FormInfo.instance.formValue;
  138. var result = await Get.to(
  139. PrescriptionCollection(
  140. controller.recordCode,
  141. isChild: false,
  142. createFollowUpOnly: () async {
  143. await controller.save(
  144. "PrenatalFollowupServiceRecord",
  145. followUpCode);
  146. var recordCode = controller.recordCode;
  147. if (recordCode.isNotEmpty) {
  148. controller.isEdit = true;
  149. }
  150. return recordCode;
  151. },
  152. ),
  153. );
  154. FormInfo.instance.formValue =
  155. controller.maternalFormValue;
  156. return result;
  157. },
  158. ),
  159. );
  160. }
  161. },
  162. ));
  163. },
  164. icon: Icon(Icons.add, size: 40),
  165. ),
  166. ],
  167. ),
  168. body: Stack(
  169. children: [
  170. Row(
  171. mainAxisAlignment: MainAxisAlignment.start,
  172. crossAxisAlignment: CrossAxisAlignment.start,
  173. children: [
  174. _buildDiagram(),
  175. _buildListView(),
  176. ],
  177. )
  178. ],
  179. ),
  180. );
  181. },
  182. );
  183. }
  184. Widget _buildDiagram() {
  185. return Expanded(
  186. flex: 1,
  187. child: Padding(
  188. padding: const EdgeInsets.all(16.0).copyWith(right: 0),
  189. child: Container(
  190. // color: Colors.white,
  191. padding: const EdgeInsets.all(16),
  192. decoration: BoxDecoration(
  193. color: Colors.white,
  194. border: Border.all(
  195. color: Colors.white,
  196. ),
  197. borderRadius: GlobalStyles.borderRadius,
  198. ),
  199. child: Image.asset(
  200. 'assets/images/exam/normalMeasurementChart.png',
  201. height: double.infinity,
  202. fit: BoxFit.fitWidth,
  203. ),
  204. ),
  205. ),
  206. );
  207. }
  208. Widget _buildListView() {
  209. return Expanded(
  210. flex: 2,
  211. child: Padding(
  212. padding: const EdgeInsets.all(16),
  213. child: RefreshIndicator(child: Obx(
  214. () {
  215. final list = controller.state.followUpDTOList;
  216. final children = <Widget>[];
  217. for (var i = 0; i < list.length; i++) {
  218. final dto = list[i];
  219. final records = dto.followUpRecordDatas;
  220. if (records == null) {
  221. continue;
  222. }
  223. for (var j = 0; j < records.length; j++) {
  224. final data = records[j];
  225. OfflineDataSyncState? offlineSyncState;
  226. offlineSyncState = null;
  227. children.add(
  228. followUpRecordCard(
  229. index: j,
  230. dto: dto,
  231. dataDto: data,
  232. syncState: offlineSyncState,
  233. ),
  234. );
  235. }
  236. }
  237. return list.isEmpty
  238. ? VNoDataView()
  239. : GridView(
  240. gridDelegate:
  241. const SliverGridDelegateWithFixedCrossAxisCount(
  242. crossAxisCount: 1,
  243. mainAxisSpacing: 16,
  244. crossAxisSpacing: 20,
  245. childAspectRatio: 900 / 180,
  246. ),
  247. children: children,
  248. );
  249. },
  250. ), onRefresh: () async {
  251. controller.getFollowUpRecordList();
  252. }),
  253. ),
  254. );
  255. }
  256. Widget followUpRecordCard({
  257. required int index,
  258. required FollowUpRecordDTO dto,
  259. required FollowUpRecordDataDTO dataDto,
  260. OfflineDataSyncState? syncState,
  261. }) {
  262. final body = Stack(
  263. children: [
  264. Row(
  265. children: [
  266. Expanded(
  267. flex: 10,
  268. child: Container(
  269. padding: const EdgeInsets.symmetric(
  270. horizontal: 30,
  271. vertical: 12,
  272. ),
  273. child: Column(
  274. crossAxisAlignment: CrossAxisAlignment.start,
  275. children: [
  276. const SizedBox(
  277. height: 8,
  278. ),
  279. LayoutBuilder(builder: (context, c) {
  280. final width = c.maxWidth - 100;
  281. return SizedBox(
  282. width: width,
  283. child: _buildBaseInfoRow(dataDto),
  284. );
  285. }),
  286. const SizedBox(
  287. height: 20,
  288. ),
  289. Wrap(
  290. alignment: WrapAlignment.start,
  291. spacing: 20,
  292. runSpacing: 8,
  293. children: [
  294. _buildName(dto.patientName ?? ''),
  295. _buildFollowUpMode(dataDto.followUpMode),
  296. ],
  297. ),
  298. const SizedBox(
  299. height: 20,
  300. ),
  301. Wrap(
  302. alignment: WrapAlignment.start,
  303. spacing: 20,
  304. runSpacing: 8,
  305. children: [
  306. _buildFollowUpDoctor(dataDto.followUpDoctor ?? ""),
  307. _buildFollowUpTime(dataDto.followUpTime),
  308. ],
  309. )
  310. ],
  311. ),
  312. ),
  313. ),
  314. // Expanded(
  315. // child: IconButton(
  316. // onPressed: () {
  317. // controller.toCheckPage(dataDto, isCreateFromOldDto: true);
  318. // },
  319. // icon: Column(
  320. // mainAxisAlignment: MainAxisAlignment.center,
  321. // crossAxisAlignment: CrossAxisAlignment.center,
  322. // children: [
  323. // Icon(
  324. // Icons.add,
  325. // size: 42,
  326. // color: Colors.grey.shade400,
  327. // ),
  328. // Text("复制新增")
  329. // ],
  330. // ),
  331. // ),
  332. // )
  333. ],
  334. ),
  335. Positioned(
  336. top: 16,
  337. right: 0,
  338. child: _FollowUpRecordSignStatusTag(
  339. dataDto: dataDto,
  340. ),
  341. ),
  342. Positioned(
  343. bottom: 16,
  344. right: 160,
  345. child: _buildShareButton(dataDto),
  346. ),
  347. Positioned(
  348. bottom: 16,
  349. right: 40,
  350. child: _buildCopyAddButton(dataDto),
  351. ),
  352. // if(dataDto)
  353. Positioned(
  354. top: 16,
  355. right: 100,
  356. child: _OfflineSyncTag(syncState: syncState),
  357. ),
  358. Positioned(
  359. bottom: 0,
  360. right: 0,
  361. child: DeleteFollowUpRecordButton(dataDto.code!, dataDto.key!, () {
  362. controller.getFollowUpRecordList();
  363. }),
  364. ),
  365. ],
  366. );
  367. return Material(
  368. borderRadius: GlobalStyles.borderRadius,
  369. child: Ink(
  370. decoration: BoxDecoration(
  371. color: Colors.white,
  372. borderRadius: GlobalStyles.borderRadius,
  373. ),
  374. child: InkWell(
  375. borderRadius: GlobalStyles.borderRadius,
  376. onTap: () {
  377. controller.isEdit = true;
  378. controller.recordCode = dataDto.code ?? '';
  379. controller.toCheckPage(dataDto); //跳转到随访页面
  380. },
  381. child: body,
  382. ),
  383. ),
  384. );
  385. }
  386. Widget _buildBaseInfoRow(FollowUpRecordDataDTO dto) {
  387. return SizedBox(
  388. child: RecordCommonItem(
  389. itemName: '随访病症',
  390. itemValue: controller.getFollowUpValueByKey(dto),
  391. fontSize: 20,
  392. ),
  393. );
  394. }
  395. Widget _FollowUpRecordSignStatusTag(
  396. {required FollowUpRecordDataDTO dataDto}) {
  397. return Container(
  398. alignment: Alignment.centerRight,
  399. width: 120,
  400. child: StatusLabel(
  401. title: _followUpManager.followUpStateTransition(dataDto.followUpState),
  402. color: _followUpManager.followUpStateColors(dataDto.followUpState),
  403. ),
  404. );
  405. }
  406. Widget _OfflineSyncTag({OfflineDataSyncState? syncState}) {
  407. return SizedBox();
  408. }
  409. Widget _buildName(String name) {
  410. return SizedBox(
  411. width: 300,
  412. child: RecordCommonItem(
  413. itemName: '姓名',
  414. itemValue: name,
  415. fontSize: 18,
  416. ),
  417. );
  418. }
  419. Widget _buildFollowUpMode(FollowUpModeEnum? followUpMode) {
  420. return RecordCommonItem(
  421. itemName: '随访类型',
  422. itemValue: _followUpManager.getFollowUpMode(followUpMode),
  423. fontSize: 18,
  424. );
  425. }
  426. Widget _buildFollowUpDoctor(String followUpDoctor) {
  427. return SizedBox(
  428. width: 300,
  429. child: RecordCommonItem(
  430. itemName: '随访医生',
  431. itemValue: followUpDoctor,
  432. fontSize: 18,
  433. ),
  434. );
  435. }
  436. Widget _buildFollowUpTime(DateTime? followUpTime) {
  437. return RecordCommonItem(
  438. itemName: '随访时间',
  439. itemValue: followUpTime != null
  440. ? DateFormat("yyyy-MM-dd").format(followUpTime.toLocal())
  441. : "",
  442. fontSize: 18,
  443. );
  444. }
  445. Widget _buildShareButton(FollowUpRecordDataDTO dataDto) {
  446. return Container(
  447. width: 100,
  448. height: 50,
  449. alignment: Alignment.bottomRight,
  450. child: VButton(
  451. onTap: () async {
  452. List<Map<String, dynamic>> previewList =
  453. await controller.sharePrescription(dataDto);
  454. if (previewList.length == 0) {
  455. PromptBox.toast("暂无处方");
  456. return;
  457. }
  458. const designWidth = 1280.0; // 设计尺寸宽度:1280
  459. final width = Get.width;
  460. final scale = width / designWidth; // 计算缩放比例
  461. Get.dialog(
  462. VAlertDialog(
  463. title: "分享处方",
  464. width: width * 0.8 / scale,
  465. content: _buildQrcode(previewList),
  466. ),
  467. );
  468. },
  469. label: "分享",
  470. ),
  471. );
  472. }
  473. Widget _buildCopyAddButton(FollowUpRecordDataDTO dataDto) {
  474. return Container(
  475. width: 100,
  476. height: 50,
  477. alignment: Alignment.bottomRight,
  478. child: VButton(
  479. onTap: () {
  480. controller.toCheckPage(dataDto, isCreateFromOldDto: true);
  481. },
  482. label: "复制新增",
  483. ),
  484. );
  485. }
  486. ///二维码
  487. Widget _buildQrcode(List<Map<String, dynamic>> qrCodes) {
  488. return SingleChildScrollView(
  489. child: Align(
  490. alignment: Alignment.center,
  491. child: Wrap(
  492. spacing: 80,
  493. runSpacing: 5,
  494. children: qrCodes
  495. .map(
  496. (e) => VQRCodeWithLogo(
  497. e["previewUrl"],
  498. codeStatement:
  499. PrescriptionFormKeys.AllPregnantWomenFormKeys[e["key"]],
  500. operationStatement: "复制链接",
  501. size: 260,
  502. titleWidth: 270,
  503. operationSuccessCallback: () {
  504. PromptBox.toast("复制成功");
  505. },
  506. ),
  507. )
  508. .toList(),
  509. ),
  510. ),
  511. );
  512. }
  513. }