excel_data_manager.dart 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. import 'dart:convert';
  2. import 'package:fis_common/index.dart';
  3. import 'package:fis_common/logger/logger.dart';
  4. import 'package:fis_jsonrpc/rpc.dart';
  5. import 'package:flutter/services.dart';
  6. import 'package:get/get.dart';
  7. import 'package:excel/excel.dart';
  8. import 'package:intl/intl.dart';
  9. import 'package:vitalapp/rpc.dart';
  10. import 'package:vitalapp/store/store.dart';
  11. import 'interfaces/excelData.dart';
  12. import 'interfaces/models/exce_keys.dart';
  13. import 'interfaces/models/excel_data.dart';
  14. import 'interfaces/template.dart';
  15. class ExcelDataManager implements IExcelDataManager {
  16. final List<String> _bloodRoutineKeys = [
  17. "Blood_Hgb",
  18. "Blood_Wbc",
  19. "ALC",
  20. "AMC",
  21. "ANC",
  22. "AEC",
  23. "Blood_NeutrophilRatio",
  24. "Blood_LymphocyteRatio",
  25. "Blood_MonocyteRatio",
  26. "EOS",
  27. "RBC",
  28. "Blood_Mchc",
  29. "Urea",
  30. "Blood_Hematocrit",
  31. "Blood_McV",
  32. "Blood_Mch",
  33. "Blood_Rlt",
  34. "Blood_MeanPlateletVolume",
  35. "Blood_PlateletDW",
  36. "Blood_PlateletPct"
  37. ];
  38. final List<String> _biochemicalKeys = [
  39. "Liver_Alt",
  40. "Liver_Ast",
  41. "Total_Protein",
  42. "Liver_Alb",
  43. "Liver_Tbil",
  44. "directBili",
  45. "GGT",
  46. "Renal_Cr",
  47. "UricAcid",
  48. "Urea",
  49. "BCH_Glu",
  50. "Lipid_Cho",
  51. "Lipid_Tg",
  52. "Lipid_Ldl",
  53. "Lipid_Hdl",
  54. "AGratio",
  55. "ALP",
  56. "UB",
  57. "Globulin",
  58. ];
  59. ///将csv中的数据解析成结构化数据
  60. @override
  61. Future<List<ExcelDataRecord>> CsvDataConvert(
  62. List<List<dynamic>> datas, String key) async {
  63. var json = await Get.find<ITemplateManager>()
  64. .getTemplateByKey("BiochemicalValues");
  65. List<ExcelDataRecord> csvRevords = [];
  66. List<dynamic> items = jsonDecode(json);
  67. List<List<List<dynamic>>> result = _splitIntoChunks(datas);
  68. for (List<List<dynamic>> chunkDatas in result) {
  69. List<ExcelDataItem> csvDatas = [];
  70. for (var item in items) {
  71. try {
  72. if (item is Map) {
  73. int row = item["row"];
  74. int column = item["column"];
  75. String key = item["key"];
  76. String des = item["des"];
  77. String identifier = item["identifier"];
  78. String referenceRange = item["referenceRange"];
  79. String unit = item["unit"];
  80. String value = "";
  81. if (chunkDatas.length >= row + 1) {
  82. var rowValue = chunkDatas[row];
  83. if (rowValue.length >= column + 1) {
  84. value = chunkDatas[row][column].toString().trim();
  85. } else {
  86. continue;
  87. }
  88. } else {
  89. continue;
  90. }
  91. csvDatas.add(ExcelDataItem(
  92. key: key,
  93. value: value,
  94. des: des,
  95. unit: unit,
  96. identifier: identifier,
  97. referenceRange: referenceRange,
  98. ));
  99. }
  100. } catch (e) {
  101. logger.e("CsvDataManager csvDataConvert ex:", e);
  102. }
  103. }
  104. csvRevords.add(ExcelDataRecord(csvDatas));
  105. }
  106. return csvRevords;
  107. }
  108. @override
  109. Future<List<ExcelDataRecord>> ExcelDataConvert(
  110. List<List<Data?>> rows, String templateKey) async {
  111. ///首行是标题
  112. rows.removeAt(0);
  113. List<ExcelDataRecord> records = [];
  114. var json = await Get.find<ITemplateManager>().getTemplateByKey(templateKey);
  115. List<dynamic> items = jsonDecode(json);
  116. List<String> keys = [];
  117. if (templateKey.contains("BloodRoutine")) {
  118. keys = _bloodRoutineKeys;
  119. } else if (templateKey.contains("Biochemical")) {
  120. keys = _biochemicalKeys;
  121. }
  122. for (List<Data?> rowData in rows) {
  123. List<ExcelDataItem> csvDatas = [];
  124. for (var item in items) {
  125. try {
  126. if (item is Map) {
  127. String key = item["key"];
  128. ///过滤不需要展示的数据
  129. if (keys.contains(key) ||
  130. key == "sampleBarcode" ||
  131. key == "patientName" ||
  132. key == "samplingTime") {
  133. int column = item["column"];
  134. String des = item["des"];
  135. String unit = item["unit"];
  136. String identifier = item["identifier"];
  137. String referenceRange = item["referenceRange"];
  138. String value = "";
  139. if (key == "Blood_Wbc") {
  140. print("sampleBarcode");
  141. }
  142. if (rowData.length >= column + 1) {
  143. Data? data = rowData[column];
  144. if (data == null) {
  145. continue;
  146. } else {
  147. value = data.value.toString();
  148. }
  149. csvDatas.add(ExcelDataItem(
  150. key: key,
  151. value: value,
  152. des: des,
  153. unit: unit,
  154. identifier: identifier,
  155. referenceRange: referenceRange,
  156. ));
  157. }
  158. }
  159. }
  160. } catch (e) {
  161. logger.e("CsvDataManager ExcelDataConvert ex:", e);
  162. }
  163. }
  164. records.add(ExcelDataRecord(csvDatas));
  165. }
  166. return records;
  167. }
  168. @override
  169. Future<bool> uploadDatas(
  170. List<ExcelDataRecord> datas, String templateKey) async {
  171. try {
  172. if (ExcelTemplateKeys.AllBiochemicalKeys.contains(templateKey)) {
  173. templateKey = "HEIBiochemical";
  174. } else if (ExcelTemplateKeys.AllBloodRoutineKeys.contains(templateKey)) {
  175. templateKey = "HEIBloodRoutine";
  176. }
  177. List<AddExamDTO> examInfos = [];
  178. for (ExcelDataRecord data in datas) {
  179. List<ExcelDataItem> items = data.excelDatas;
  180. var physicalExamNumber =
  181. items.firstWhere((element) => element.key == "sampleBarcode").value;
  182. String examTimeStr =
  183. items.firstWhere((element) => element.key == "samplingTime").value;
  184. List<String> keys = [];
  185. if (templateKey.contains("BloodRoutine")) {
  186. keys = _bloodRoutineKeys;
  187. } else if (templateKey.contains("Biochemical")) {
  188. keys = _biochemicalKeys;
  189. }
  190. // 使用DateFormat格式化日期,去除时间部分
  191. DateFormat dateOnlyFormat = DateFormat('yyyy-MM-dd');
  192. DateTime dateOnlyDateTime = dateOnlyFormat.parse(examTimeStr);
  193. var examDTO = AddExamDTO(
  194. key: templateKey,
  195. examNumber: physicalExamNumber,
  196. examTime: dateOnlyDateTime,
  197. examData: data.toJson(keys),
  198. );
  199. examInfos.add(examDTO);
  200. }
  201. if (examInfos.length <= 200) {
  202. await rpc.vitalExam.batchAddExamAsync(BatchAddExamRequest(
  203. examInfos: examInfos,
  204. token: Store.user.token,
  205. ));
  206. } else {
  207. // 计算需要拆分成多少个小组
  208. int groupCount = (examInfos.length / 200).ceil();
  209. // 遍历并拆分列表
  210. for (int i = 0; i < groupCount; i++) {
  211. // 计算当前小组的起始索引和结束索引
  212. int startIndex = i * 200;
  213. int endIndex = (i + 1) * 200;
  214. // 如果已经到达列表的末尾,设置结束索引为列表的长度
  215. if (endIndex > examInfos.length) {
  216. endIndex = examInfos.length;
  217. }
  218. // 使用 getRange 方法获取当前小组的数据
  219. List<AddExamDTO> group =
  220. examInfos.getRange(startIndex, endIndex).toList();
  221. await rpc.vitalExam.batchAddExamAsync(BatchAddExamRequest(
  222. examInfos: group,
  223. token: Store.user.token,
  224. ));
  225. }
  226. }
  227. } catch (e) {
  228. logger.e("ExcelDataManager uploadDatas ex:", e);
  229. return false;
  230. }
  231. return true;
  232. }
  233. List<List<List<dynamic>>> _splitIntoChunks(List<List<dynamic>> datas) {
  234. List<List<List<dynamic>>> records = [];
  235. List<List<dynamic>> currentRecord = [];
  236. for (int i = 0; i < datas.length; i++) {
  237. // Check if the current element and the next one are empty lists
  238. if ((datas[i].length == 1 && datas[i][0].isEmpty) &&
  239. i + 1 < datas.length &&
  240. (datas[i + 1].length == 1 && datas[i + 1][0].isEmpty)) {
  241. // Skip the next empty list as it is part of the separator
  242. i++;
  243. // Add the current record to records if it is not empty
  244. if (currentRecord.isNotEmpty) {
  245. records.add(List.from(currentRecord));
  246. currentRecord.clear();
  247. }
  248. } else {
  249. // Add the current data to the current record
  250. currentRecord.add(datas[i]);
  251. }
  252. }
  253. // Add the last record if it's not empty (case when no trailing empty lists)
  254. if (currentRecord.isNotEmpty) {
  255. records.add(currentRecord);
  256. }
  257. return records;
  258. }
  259. }