controller.dart 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. import 'dart:convert';
  2. import 'package:fis_common/index.dart';
  3. import 'package:fis_jsonrpc/rpc.dart';
  4. import 'package:flutter/foundation.dart';
  5. import 'package:flutter/material.dart';
  6. import 'package:flutter/services.dart';
  7. import 'package:flutter_inappwebview/flutter_inappwebview.dart';
  8. import 'package:get/get.dart';
  9. import 'package:intl/intl.dart';
  10. import 'package:vitalapp/architecture/defines.dart';
  11. import 'package:vitalapp/architecture/utils/prompt_box.dart';
  12. import 'package:vitalapp/database/db.dart';
  13. import 'package:vitalapp/global.dart';
  14. import 'package:vitalapp/managers/interfaces/follow_up.dart';
  15. import 'package:vitalapp/managers/interfaces/prescription.dart';
  16. import 'package:vitalapp/pages/check/follow_up/controller.dart';
  17. import 'package:vitalapp/pages/check/follow_up/widgets/follow_up_from.dart';
  18. import 'package:vitalapp/pages/check/follow_up_record/state.dart';
  19. import 'package:vitalapp/pages/check/widgets/configurable_card.dart';
  20. import 'package:vitalapp/pages/form/form_info.dart';
  21. import 'package:vitalapp/pages/medical/controller.dart';
  22. import 'package:vitalapp/store/store.dart';
  23. class FollowUpRecordController extends FControllerBase {
  24. FollowUpRecordController({
  25. required this.followUpType,
  26. });
  27. final String followUpType;
  28. final state = FollowUpRecordState();
  29. final _followUpManager = Get.find<IFollowUpManager>();
  30. final followUpController = Get.put(FollowUpController());
  31. final _prescriptionManager = Get.find<IPrescriptionManager>();
  32. late String patientCode;
  33. late String patientName;
  34. late FollowUpController _followUpController;
  35. List<List> offlineSyncTemp = [];
  36. String prescriptionCode = "";
  37. @override
  38. void onReady() {
  39. super.onReady();
  40. _initData();
  41. }
  42. _initData() async {
  43. update(["contract_records"]);
  44. patientCode = Store.user.currentSelectPatientInfo?.code ?? '';
  45. patientName = Store.user.currentSelectPatientInfo?.patientName ?? '';
  46. await getFollowUpRecordList();
  47. _followUpController = Get.put(FollowUpController());
  48. }
  49. Future<void> getFollowUpRecordList() async {
  50. try {
  51. var keys = [followUpType];
  52. if (followUpType == "FollowUpTuberculosisFirstRecord") {
  53. keys = [
  54. "FollowUpTuberculosisFirstRecord",
  55. "FollowUpTuberculosisRecord",
  56. "FollowUpTuberculosisResultRecord"
  57. ];
  58. }
  59. var result = await _followUpManager.getFollowUpRecordList(
  60. keys,
  61. patientCode,
  62. );
  63. List<FollowUpRecordDTO> followUpDTOList = [];
  64. // 如果是web端并且是离线模式,则从本地获取数据
  65. if (!kIsWeb && kIsOnline) {
  66. List<FollowUpRecordDTO> offlineFollowUpList = await _followUpManager
  67. .getPatientNotUploadedRecordList(patientCode, followUpType);
  68. followUpDTOList = offlineFollowUpList;
  69. }
  70. /// TODO 后面需要优化,去重
  71. followUpDTOList.addAll(result ?? []);
  72. if (kIsOnline) {
  73. offlineSyncTemp = await _loadUnsyncIndexs(followUpDTOList);
  74. } else {
  75. offlineSyncTemp = await _loadUnsyncIndexs(result ?? []);
  76. }
  77. state.followUpDTOList = followUpDTOList;
  78. } catch (e) {
  79. return;
  80. }
  81. }
  82. Future<List<List>> _loadUnsyncIndexs(List<FollowUpRecordDTO> dtos) async {
  83. List<List> _offlineSyncTemp = [];
  84. /// web 端没有本地数据库
  85. if (!kIsWeb) {
  86. // TODO 临时打个补丁,后续再优化
  87. final entities = await db.repositories.followUp.queryAllListByPatient(
  88. patientCode,
  89. Store.user.userCode!,
  90. followUpType,
  91. );
  92. for (var i = 0; i < dtos.length; i++) {
  93. _offlineSyncTemp.add([]);
  94. final records = dtos[i].followUpRecordDatas;
  95. if (records == null) {
  96. continue;
  97. }
  98. for (var j = 0; j < records.length; j++) {
  99. final data = records[j];
  100. final entity = entities.firstWhereOrNull((e) => e.code == data.code);
  101. if (entity != null) {
  102. _offlineSyncTemp[i].add(entity.syncState);
  103. } else {
  104. _offlineSyncTemp[i].add(null);
  105. }
  106. }
  107. }
  108. } else {
  109. for (var i = 0; i < dtos.length; i++) {
  110. _offlineSyncTemp.add([]);
  111. final records = dtos[i].followUpRecordDatas;
  112. if (records == null) {
  113. continue;
  114. }
  115. for (var j = 0; j < records.length; j++) {
  116. final data = records[j];
  117. _offlineSyncTemp[i].add(data);
  118. }
  119. }
  120. }
  121. return _offlineSyncTemp;
  122. }
  123. Future<void> updateFollowUp(key, code, data) async {
  124. List<String> followUpPhotos = [];
  125. if (_followUpController.state.followUpPhoto?.isNotEmpty ?? false) {
  126. followUpPhotos = [_followUpController.state.followUpPhoto!];
  127. }
  128. final result = await _followUpManager.updateFollowUp(
  129. UpdateFollowUpRequest(
  130. key: key,
  131. followUpData: data,
  132. followUpTime: _followUpController.state.followUpTime,
  133. nextFollowUpTime: _followUpController.state.nextFollowUpTime,
  134. followUpMode: _followUpController.state.followUpMode ??
  135. FollowUpModeEnum.Outpatient,
  136. code: code,
  137. followUpPhotos: followUpPhotos,
  138. ),
  139. );
  140. if (result ?? false) {
  141. PromptBox.toast('保存成功');
  142. } else {
  143. PromptBox.toast('保存失败');
  144. }
  145. }
  146. ///读取静态Html
  147. Future<String> loadingLocalAsset(String key) async {
  148. String tableName = "";
  149. if (key == 'GXY') {
  150. tableName = 'assets/docs/highBloodPressureTable.html';
  151. } else if (key == 'TNB') {
  152. tableName = 'assets/docs/diabetesTable.html';
  153. }
  154. ///加载
  155. String htmlData = await rootBundle.loadString(tableName);
  156. print("加载数据完成 $htmlData");
  157. return htmlData;
  158. }
  159. Future<List> getFollowUpTableData(FollowUpRecordDTO dto, int index) async {
  160. var currentFollowUp = dto.followUpRecordDatas?[index];
  161. var followUpTableData = await _followUpManager
  162. .getFollowUpRecordListByYearAsync(GetFollowUpRecordListByYearRequest(
  163. year: (currentFollowUp?.followUpTime?.year ?? DateTime.now().year)
  164. .toString(),
  165. keys: [currentFollowUp?.key ?? ''],
  166. patientCode: patientCode,
  167. ));
  168. List tableData = [];
  169. followUpTableData?.first.followUpRecordDatas?.forEach((element) {
  170. Map followUp = {
  171. "Follow_Time": element.followUpTime != null
  172. ? DateFormat("yyyy-MM-dd").format(element.followUpTime!.toLocal())
  173. : "",
  174. "Follow_Type": '${(element.followUpMode?.index ?? 0) + 1} ',
  175. "Next_Follow_Up_Time": element.nextFollowUpTime != null
  176. ? DateFormat("yyyy-MM-dd")
  177. .format(element.nextFollowUpTime!.toLocal())
  178. : "",
  179. };
  180. followUp.addAll(jsonDecode(element.followUpData ?? ''));
  181. tableData.add(followUp);
  182. });
  183. return tableData;
  184. }
  185. Future<String> loadLocalAsset(String key) async {
  186. String tableName = "";
  187. if (key == 'GXY') {
  188. tableName = 'assets/docs/highBloodPressureTable.html';
  189. } else if (key == 'TNB') {
  190. tableName = 'assets/docs/diabetesTable.html';
  191. }
  192. ///加载
  193. String htmlData = await rootBundle.loadString(tableName);
  194. print("加载数据完成 $htmlData");
  195. return htmlData;
  196. }
  197. Future<void> showDialogBox(String initialData, String jsonData) async {
  198. Get.dialog(Column(
  199. children: [
  200. Container(
  201. width: 900,
  202. alignment: Alignment.centerRight,
  203. padding: const EdgeInsets.only(right: 20, top: 10),
  204. color: Colors.white,
  205. child: IconButton(
  206. onPressed: () {
  207. Get.back();
  208. },
  209. icon: const Icon(
  210. Icons.close,
  211. ),
  212. ),
  213. ),
  214. Expanded(
  215. child: SizedBox(
  216. width: 900,
  217. child: InAppWebView(
  218. initialData: InAppWebViewInitialData(
  219. data: '<body style="padding:30px 100px;">$initialData </body>',
  220. mimeType: 'text/html',
  221. encoding: 'utf-8',
  222. ),
  223. onWebViewCreated: (controller) {
  224. controller.evaluateJavascript(
  225. source: "window.tableData = $jsonData;");
  226. },
  227. onConsoleMessage: (controller, consoleMessage) {
  228. // print(consoleMessage);
  229. },
  230. ),
  231. ),
  232. ),
  233. ],
  234. ));
  235. }
  236. Future<void> toFollowUpDetailPage(int index, FollowUpRecordDTO dto) async {
  237. var tableData = await getFollowUpTableData(dto, index);
  238. var initialData =
  239. await loadLocalAsset(dto.followUpRecordDatas?[index].key ?? '');
  240. var jsonData = jsonEncode(tableData);
  241. showDialogBox(initialData, jsonData);
  242. }
  243. /// 获取处方详情
  244. Future<PrescriptionDTO?> getPrescriptionDetailByFollowAnPatient(
  245. String followUpCode) async {
  246. return await _prescriptionManager.getPrescriptionDetailByFollowAnPatient(
  247. patientCode: patientCode,
  248. followUpCode: followUpCode,
  249. );
  250. }
  251. Future<Map<String, dynamic>> sharePrescription(
  252. FollowUpRecordDataDTO dataDTO,
  253. ) async {
  254. PrescriptionDTO? prescription =
  255. await getPrescriptionDetailByFollowAnPatient(dataDTO.code!);
  256. if (prescription == null) {
  257. return {};
  258. }
  259. return {
  260. "previewUrl": prescription.previewUrl ?? "",
  261. "key": prescription.prescriptionTemplateKey ?? "",
  262. };
  263. }
  264. toCheckPage(
  265. FollowUpRecordDataDTO dataDTO, {
  266. bool isCreateFromOldDto = false,
  267. }) async {
  268. await Get.put(MedicalController());
  269. _followUpController.state.followUpTime = dataDTO.followUpTime;
  270. _followUpController.state.nextFollowUpTime = dataDTO.nextFollowUpTime;
  271. _followUpController.state.followUpMode = dataDTO.followUpMode;
  272. if (dataDTO.followUpPhotos?.isNotEmpty ?? false) {
  273. _followUpController.state.followUpPhoto = dataDTO.followUpPhotos?.first;
  274. } else {
  275. _followUpController.state.followUpPhoto = "";
  276. }
  277. PrescriptionDTO? prescription =
  278. await getPrescriptionDetailByFollowAnPatient(dataDTO.code!);
  279. if (prescription != null && prescription.prescriptionData!.isNotEmpty) {
  280. FormInfo.instance.formValue = jsonDecode(prescription.prescriptionData!);
  281. }
  282. await Get.to(
  283. ConfigurableCard(
  284. cardKey: dataDTO.key!,
  285. examData: dataDTO.followUpData,
  286. followUpWidget: FollowUpFrom(cardKey: dataDTO.key!, dataDTO: dataDTO),
  287. patientCode: patientCode,
  288. callBack: (key, code, data, prescriptionKey) async {
  289. if (isCreateFromOldDto) {
  290. await createFollowUpFromOldDto(
  291. key,
  292. dataDTO.code,
  293. data,
  294. prescriptionKey,
  295. );
  296. } else {
  297. await initPrescription(dataDTO.code!, prescriptionKey ?? '');
  298. await updateFollowUp(key, dataDTO.code, data);
  299. if (prescriptionCode.isNullOrEmpty) {
  300. await createPrescription(dataDTO.code!, prescriptionKey ?? '');
  301. } else {
  302. await updatePrescription(dataDTO.code!, prescriptionKey ?? '');
  303. }
  304. }
  305. await getFollowUpRecordList();
  306. return true;
  307. },
  308. ),
  309. transition: Transition.rightToLeft,
  310. );
  311. await Get.find<MedicalController>().initRecordDataState();
  312. await Get.delete<MedicalController>();
  313. }
  314. final Map<String, String> followUpKeyValue = {
  315. 'FJHSFFW': "肺结核随访服务",
  316. 'FJHRHSF': "肺结核入户随访",
  317. 'GXB': "冠心病",
  318. 'NCZ': "脑卒中",
  319. 'YZJSZASFFW': "严重精神障碍随访服务",
  320. 'YZJSZAGRXXBC': "严重精神障碍个人信息补充",
  321. 'TNB': "2型糖尿病",
  322. 'GXY': "高血压",
  323. // 'LNRZYYJKGLFWJL': "老年人中医药健康管理服务记录表",
  324. 'LNRSHZLNLPGB': "老年人生活自理能力评估表",
  325. 'YCF_CH42TJKJCLB': "产后42天健康检查列表",
  326. 'YCF_CHFSLB': "产后访视列表",
  327. 'YCF_2_5CCQSFLB': "2~5次产前随访列表",
  328. 'YCF_DYCCQJCLB': "第一次产前检查列表",
  329. 'YCF_JBXX': "基本信息",
  330. 'ET_ZYYJKGLLB': "儿童中医药健康管理列表",
  331. 'ET_1MSETJKJCLB': "满月儿童健康检查",
  332. 'ET_3MSETJKJCLB': "3月龄儿童健康检查",
  333. 'ET_6MSETJKJCLB': "6月龄儿童健康检查",
  334. 'ET_8MSETJKJCLB': "8月龄儿童健康检查",
  335. 'ET_12MSETJKJCLB': "12月儿童健康检查",
  336. 'ET_18MSETJKJCLB': "18月儿童健康检查",
  337. 'ET_24MSETJKJCLB': "24月儿童健康检查",
  338. 'ET_30MSETJKJCLB': "30月儿童健康检查",
  339. 'ET_3SETJKJCLB': "3岁儿童健康检查列表",
  340. 'ET_4SETJKJCLB': "4岁儿童健康检查",
  341. 'ET_5SETJKJCLB': "5岁儿童健康检查",
  342. 'ET_6SETJKJCLB': "6岁儿童健康检查",
  343. 'ET_1_2SETJKJCLB': "1~2岁儿童健康检查列表",
  344. 'ET_1SNETJKJCLB': "1岁内儿童健康检查列表",
  345. 'ET_FamilyVisitRecord': "新生儿访视列表",
  346. 'FollowUpTuberculosisFirstRecord': "肺结核患者第一次入户随访记录表",
  347. 'FollowUpTuberculosisRecord': "肺结核患者随访服务记录表",
  348. 'FollowUpTuberculosisResultRecord': "肺结核患者结论表",
  349. };
  350. String getFollowUpValueByKey(String key) {
  351. if (followUpKeyValue[key] != null) {
  352. return followUpKeyValue[key]!;
  353. } else {
  354. return "";
  355. }
  356. }
  357. String followUpStateTransition(FollowUpStateEnum state) {
  358. switch (state) {
  359. case FollowUpStateEnum.NoFollowUp:
  360. return "未随访";
  361. case FollowUpStateEnum.FollowUpVisit:
  362. return "已随访";
  363. case FollowUpStateEnum.Cancelled:
  364. return "已作废";
  365. default:
  366. return "";
  367. }
  368. }
  369. MaterialColor followUpStateColors(FollowUpStateEnum state) {
  370. switch (state) {
  371. case FollowUpStateEnum.NoFollowUp:
  372. return Colors.grey;
  373. case FollowUpStateEnum.Cancelled:
  374. return Colors.red;
  375. case FollowUpStateEnum.FollowUpVisit:
  376. return Colors.green;
  377. default:
  378. return Colors.blue;
  379. }
  380. }
  381. String getFollowUpMode(FollowUpModeEnum? modeEnum) {
  382. switch (modeEnum) {
  383. case FollowUpModeEnum.Outpatient:
  384. return "门诊";
  385. case FollowUpModeEnum.Phone:
  386. return "电话";
  387. case FollowUpModeEnum.Visit:
  388. return "家庭";
  389. default:
  390. return "";
  391. }
  392. }
  393. Future<bool> createFollowUpFromOldDto(
  394. String key,
  395. String? code,
  396. data,
  397. prescriptionKey,
  398. ) async {
  399. return await _followUpController.createFollowUp(
  400. key,
  401. code,
  402. data,
  403. prescriptionKey,
  404. );
  405. }
  406. Future<void> initPrescription(
  407. String followUpCode, String prescriptionKey) async {
  408. // 获取处方列表
  409. List<PrescriptionDTO>? prescriptionList =
  410. await _prescriptionManager.getPrescriptionPage(
  411. patientCode: patientCode,
  412. followUpCode: followUpCode,
  413. );
  414. prescriptionCode = prescriptionList
  415. ?.firstWhereOrNull(
  416. (element) => element.prescriptionTemplateKey == prescriptionKey)
  417. ?.code ??
  418. "";
  419. }
  420. Future<bool?> updatePrescription(
  421. String followUpCode,
  422. String prescriptionKey,
  423. ) async {
  424. if (FormInfo.instance.formValue.isEmpty) {
  425. return null;
  426. }
  427. /// 创建处方
  428. bool? result = await _prescriptionManager.updatePrescription(
  429. patientCode: patientCode,
  430. followUpCode: followUpCode,
  431. prescriptionCode: prescriptionCode,
  432. prescriptionData: jsonEncode(FormInfo.instance.formValue),
  433. prescriptionKey: prescriptionKey,
  434. );
  435. if (result != null && result) {
  436. FormInfo.instance.formValue.clear();
  437. } else {
  438. PromptBox.toast("更新失败");
  439. }
  440. return result;
  441. }
  442. Future<String?> createPrescription(
  443. String followUpCode, String prescriptionKey) async {
  444. if (FormInfo.instance.formValue.isEmpty) {
  445. return null;
  446. }
  447. /// 创建处方
  448. String? prescriptionCode = await _prescriptionManager.createPrescription(
  449. patientCode: patientCode,
  450. followUpCode: followUpCode,
  451. prescriptionKey: prescriptionKey,
  452. prescriptionData: jsonEncode(FormInfo.instance.formValue),
  453. );
  454. FormInfo.instance.formValue.clear();
  455. return prescriptionCode;
  456. }
  457. }