excel_data_manager.dart 9.4 KB

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