controller.dart 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. import 'dart:convert';
  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:uuid/uuid.dart';
  7. import 'package:vitalapp/architecture/storage/storage.dart';
  8. import 'package:vitalapp/architecture/utils/prompt_box.dart';
  9. import 'package:vitalapp/architecture/utils/upload.dart';
  10. import 'package:vitalapp/components/alert_dialog.dart';
  11. import 'package:vitalapp/managers/interfaces/record_data_cache.dart';
  12. import 'package:vitalapp/rpc.dart';
  13. import 'package:vnote_device_plugin/consts/types.dart';
  14. import 'package:vitalapp/architecture/defines.dart';
  15. import 'package:vitalapp/architecture/storage/text_storage.dart';
  16. import 'package:vitalapp/managers/interfaces/cachedRecord.dart';
  17. import 'package:vitalapp/managers/interfaces/device.dart';
  18. import 'package:vitalapp/managers/interfaces/diagnosis.dart';
  19. import 'package:vitalapp/managers/interfaces/models/device.dart';
  20. import 'package:vitalapp/pages/medical/models/item.dart';
  21. import 'package:vitalapp/pages/medical/state.dart';
  22. import 'package:vitalapp/store/store.dart';
  23. import 'package:vnote_device_plugin/events/event_type.dart';
  24. class MedicalController extends FControllerBase {
  25. String patientCode = '';
  26. Map<String, dynamic> diagnosisDataValue = {};
  27. String appDataId = "";
  28. final state = MedicalState();
  29. final recordDataCacheManager = Get.find<IRecordDataCacheManager>();
  30. static final typeConvertMap = <String, String>{
  31. DeviceTypes.TEMP: "Temp",
  32. DeviceTypes.WEIGHT: "BMI",
  33. DeviceTypes.SPO2: "SpO2",
  34. DeviceTypes.NIBP: "NIBP",
  35. DeviceTypes.SUGAR: "GLU",
  36. DeviceTypes.URINE: "Urine",
  37. DeviceTypes.IC_READER: "ICReader",
  38. DeviceTypes.HEART: "HEART",
  39. };
  40. final changePatient = FEventHandler<String>();
  41. final _diagnosisManager = Get.find<IDiagnosisManager>();
  42. final _cachedRecordManager = Get.find<ICachedRecordManager>();
  43. final _deviceManager = Get.find<IDeviceManager>();
  44. final _medicalMenus = [
  45. MedicalItem(key: DeviceTypes.TEMP, diagnosticItem: '体温'),
  46. MedicalItem(key: DeviceTypes.SUGAR, diagnosticItem: '血糖'),
  47. MedicalItem(key: DeviceTypes.NIBP, diagnosticItem: '血压'),
  48. MedicalItem(key: DeviceTypes.SPO2, diagnosticItem: '血氧'),
  49. MedicalItem(key: DeviceTypes.WEIGHT, diagnosticItem: 'BMI'),
  50. MedicalItem(key: DeviceTypes.URINE, diagnosticItem: '尿常规'),
  51. MedicalItem(key: DeviceTypes.HEART, diagnosticItem: '心电'),
  52. ];
  53. @override
  54. void onReady() {
  55. initData();
  56. getAccessTypes();
  57. super.onReady();
  58. }
  59. Future<void> initData() async {
  60. patientCode = Store.user.currentSelectPatientInfo?.code ?? '';
  61. if (patientCode.isNotEmpty) {
  62. var cachedAppDataId = await readCachedAppDataId();
  63. if (cachedAppDataId != null) {
  64. appDataId = cachedAppDataId;
  65. } else {
  66. await saveCachedAppDataId();
  67. }
  68. await initReadCached();
  69. }
  70. }
  71. Future<void> getAccessTypes() async {
  72. List<MedicalItem> medicalItemList = [];
  73. List<String> accessTypes = await _deviceManager.getAccessTypes();
  74. for (var element in _medicalMenus) {
  75. if (accessTypes.contains(element.key)) {
  76. medicalItemList.add(element);
  77. }
  78. }
  79. state.medicalMenuList = medicalItemList;
  80. }
  81. Future<DeviceModel?> getDevice(String type) async {
  82. List<DeviceModel> devices = await _deviceManager.getDeviceList();
  83. return devices.firstWhereOrNull((element) => element.type == type);
  84. }
  85. Future<void> initReadCached() async {
  86. if (patientCode.isNotEmpty) {
  87. TextStorage cachedRecord = TextStorage(
  88. fileName: 'JKJC',
  89. directory: "patient/$patientCode",
  90. );
  91. String? value = await cachedRecord.read();
  92. if (value == null) {
  93. diagnosisDataValue = {};
  94. Store.resident.handleSaveMedicalData(jsonEncode(diagnosisDataValue));
  95. return;
  96. }
  97. Store.resident.handleSaveMedicalData(value);
  98. diagnosisDataValue = jsonDecode(value);
  99. }
  100. }
  101. Future<void> readCachedRecord() async {
  102. if (patientCode.isNotEmpty) {
  103. // TextStorage cachedRecord = TextStorage(
  104. // fileName: 'JKJC',
  105. // directory: "patient/$patientCode",
  106. // );
  107. String? value = Store.resident.residentMedicalData;
  108. print('🍖');
  109. print(value);
  110. print('🍖');
  111. if (value == null) {
  112. diagnosisDataValue = {};
  113. return;
  114. }
  115. diagnosisDataValue = jsonDecode(value);
  116. }
  117. }
  118. Future<bool?> saveCachedAppDataId() async {
  119. appDataId = const Uuid().v4().replaceAll('-', '');
  120. TextStorage cachedRecord = TextStorage(
  121. fileName: 'appDataId',
  122. directory: "patient/$patientCode",
  123. );
  124. Get.back();
  125. return cachedRecord.save(appDataId);
  126. }
  127. Future<String?> readCachedAppDataId() async {
  128. TextStorage cachedRecord = TextStorage(
  129. fileName: 'appDataId',
  130. directory: "patient/$patientCode",
  131. );
  132. return cachedRecord.read();
  133. }
  134. Future<bool?> saveCachedRecord() async {
  135. try {
  136. return await recordDataCacheManager.saveRecordData(
  137. appDataId,
  138. patientCode,
  139. diagnosisDataValue,
  140. );
  141. } catch (e) {
  142. print(e);
  143. return false;
  144. }
  145. }
  146. Future<bool?> deleteDirectory() async {
  147. TextStorage cachedRecord = TextStorage(
  148. fileName: 'JKJC',
  149. directory: "patient/$patientCode",
  150. );
  151. return cachedRecord.deleteDirectory();
  152. }
  153. Future<void> submitDiagnosis(List<DiagnosisItem> diagnosisItems) async {
  154. state.currentTab = '-1';
  155. SubmitDiagnosisRequest submitDiagnosisRequest = SubmitDiagnosisRequest(
  156. appDataId: appDataId,
  157. patientCode: patientCode,
  158. diagnosisItems: diagnosisItems,
  159. diagnosisTime: DateTime.now().toUtc(),
  160. );
  161. print(submitDiagnosisRequest.toJson());
  162. final result =
  163. await _diagnosisManager.submitDiagnosisAsync(submitDiagnosisRequest);
  164. if (result) {
  165. PromptBox.toast('提交成功');
  166. await saveCachedAppDataId();
  167. await deleteDirectory();
  168. await readCachedRecord();
  169. Future.delayed(const Duration(milliseconds: 10), () {
  170. state.currentTab = state.medicalMenuList[0].key;
  171. });
  172. } else {
  173. PromptBox.toast('提交失败');
  174. }
  175. }
  176. Future<void> createDiagnosis() async {
  177. if (Store.user.teamName.isEmpty) {
  178. PromptBox.toast('未设置团队无法提交检测数据');
  179. return;
  180. }
  181. if (patientCode.isEmpty ||
  182. patientCode != Store.user.currentSelectPatientInfo?.code) {
  183. initData();
  184. }
  185. List<DiagnosisItem> diagnosisItems = [];
  186. for (var entry in diagnosisDataValue.entries) {
  187. var key = entry.key;
  188. var value = entry.value;
  189. if (value != null) {
  190. if (key == 'Heart' && value is Map) {
  191. if (value.isEmpty) {
  192. return;
  193. }
  194. String allPoint = value['ECG_POINT'];
  195. String imageBase64 = value['ECG'];
  196. /// 点集地址
  197. Uint8List bytes =
  198. Uint8List.fromList(jsonDecode(allPoint).cast<int>());
  199. final ecgPointBase64 = base64Encode(bytes);
  200. final ecgPointFile = UploadUtils.convertBase64ToXFile(ecgPointBase64);
  201. String? ecgPointUrl = await rpc.storage.upload(ecgPointFile!);
  202. /// 图片地址
  203. final imageFile = UploadUtils.convertBase64ToXFile(imageBase64);
  204. String? imageUrl = await rpc.storage.upload(imageFile!);
  205. value['ECG_POINT'] = ecgPointUrl ?? '';
  206. value['ECG'] = imageUrl ?? '';
  207. }
  208. diagnosisItems.add(
  209. DiagnosisItem(
  210. key: key,
  211. diagnosisData: jsonEncode(value),
  212. ),
  213. );
  214. }
  215. print('$key: $value');
  216. }
  217. if (diagnosisItems.isEmpty) {
  218. PromptBox.toast('不能提交空数据');
  219. return;
  220. }
  221. if (state.medicalMenuList.length > diagnosisDataValue.length) {
  222. Get.dialog(
  223. VAlertDialog(
  224. title: '提示',
  225. content: Container(
  226. margin: const EdgeInsets.only(bottom: 20),
  227. child: const Text(
  228. '当前检测项目未完成,请确定是否提交本次检测',
  229. style: TextStyle(fontSize: 20),
  230. textAlign: TextAlign.center,
  231. ),
  232. ),
  233. showCancel: true,
  234. onConfirm: () {
  235. submitDiagnosis(diagnosisItems);
  236. },
  237. onCanceled: () {},
  238. ),
  239. );
  240. return;
  241. }
  242. }
  243. @override
  244. void dispose() {
  245. print('MedicalController dispose');
  246. super.dispose();
  247. }
  248. }