excel_data_manager.dart 8.1 KB

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