Browse Source

excel 数据导入支持

loki.wu 11 months ago
parent
commit
5c0f441cde

+ 65 - 2
lib/managers/csvDataManager.dart

@@ -1,9 +1,12 @@
 import 'dart:convert';
 
 import 'package:fis_common/logger/logger.dart';
+import 'package:fis_jsonrpc/rpc.dart';
 import 'package:flutter/services.dart';
 import 'package:get/get.dart';
-
+import 'package:excel/excel.dart';
+import 'package:vitalapp/rpc.dart';
+import 'package:vitalapp/store/store.dart';
 import 'interfaces/csvData.dart';
 import 'interfaces/models/csv_data.dart';
 import 'interfaces/template.dart';
@@ -11,7 +14,8 @@ import 'interfaces/template.dart';
 class CsvDataManager implements ICsvDataManager {
   ///将csv中的数据解析成结构化数据
   @override
-  Future<List<CsvRevord>> CsvDataConvert(List<List<dynamic>> datas) async {
+  Future<List<CsvRevord>> CsvDataConvert(
+      List<List<dynamic>> datas, String key) async {
     var json = await Get.find<ITemplateManager>()
         .getTemplateByKey("BiochemicalValues");
     List<CsvRevord> csvRevords = [];
@@ -58,6 +62,65 @@ class CsvDataManager implements ICsvDataManager {
     return csvRevords;
   }
 
+  @override
+  Future<List<CsvRevord>> ExcelDataConvert(
+      List<List<Data?>> rows, String key) async {
+    ///首行是标题
+    rows.removeAt(0);
+    List<CsvRevord> records = [];
+    var json = await Get.find<ITemplateManager>()
+        .getTemplateByKey("BiochemicalValues_HT");
+    List<dynamic> items = jsonDecode(json);
+    for (List<Data?> rowData in rows) {
+      List<CsvData> csvDatas = [];
+      for (var item in items) {
+        try {
+          if (item is Map) {
+            int column = item["column"];
+            String key = item["key"];
+            String des = item["des"];
+            String unit = item["unit"];
+            String identifier = item["identifier"];
+            String referenceRange = item["referenceRange"];
+            String value = "";
+            if (key == "sampleBarcode") {
+              print("sampleBarcode");
+            }
+            if (rowData.length >= column + 1) {
+              Data? data = rowData[column];
+              if (data == null) {
+                continue;
+              } else {
+                value = data.value.toString();
+              }
+              csvDatas.add(CsvData(
+                key: key,
+                value: value,
+                des: des,
+                unit: unit,
+                identifier: identifier,
+                referenceRange: referenceRange,
+              ));
+            }
+          }
+        } catch (e) {
+          logger.e("CsvDataManager ExcelDataConvert ex:", e);
+        }
+      }
+      records.add(CsvRevord(csvDatas));
+    }
+    return records;
+  }
+
+  Future<void> uploadDatas(List<CsvRevord> datas, String templateKey) async {
+    List<AddExamDTO> examInfos = [];
+
+    await rpc.vitalExam.batchAddExamAsync(BatchAddExamRequest(
+      examInfos: [],
+      token: Store.user.token,
+    ));
+  }
+
   List<List<List<dynamic>>> _splitIntoChunks(List<List<dynamic>> datas) {
     List<List<List<dynamic>>> records = [];
     List<List<dynamic>> currentRecord = [];

+ 4 - 1
lib/managers/interfaces/csvData.dart

@@ -1,6 +1,9 @@
 import 'base.dart';
 import 'models/csv_data.dart';
+import 'package:excel/excel.dart';
 
 abstract class ICsvDataManager implements IManager {
-  Future<List<CsvRevord>> CsvDataConvert(List<List<dynamic>> datas);
+  Future<List<CsvRevord>> CsvDataConvert(List<List<dynamic>> datas, String key);
+
+  Future<List<CsvRevord>> ExcelDataConvert(List<List<Data?>> rows, String key);
 }

+ 30 - 0
lib/managers/template.dart

@@ -69,6 +69,36 @@ class TemplateManager implements ITemplateManager {
             "TemplateManager saveTemplate  template Code:${i.code} , key:${i.key}.");
       }
 
+      ///Excel生化模板
+      if (syncSettingsDTO?.biochemicalTemplate?.code.isNotNullOrEmpty ??
+          false) {
+        var code = syncSettingsDTO!.biochemicalTemplate!.code!;
+        TextStorage template = TextStorage(
+          fileName: code,
+          directory: "template/$code",
+        );
+        var key = syncSettingsDTO.biochemicalTemplate!.key!;
+        currentTemplateIndex[key] = code;
+        await template.save(jsonEncode(syncSettingsDTO.biochemicalTemplate));
+        logger
+            .i("TemplateManager saveTemplate  template Code:$code , key:$key.");
+      }
+
+      ///Excel血常规模板
+      if (syncSettingsDTO?.bloodRoutineTemplate?.code.isNotNullOrEmpty ??
+          false) {
+        var code = syncSettingsDTO!.bloodRoutineTemplate!.code!;
+        TextStorage template = TextStorage(
+          fileName: code,
+          directory: "template/$code",
+        );
+        var key = syncSettingsDTO.bloodRoutineTemplate!.key!;
+        currentTemplateIndex[key] = code;
+        await template.save(jsonEncode(syncSettingsDTO.bloodRoutineTemplate));
+        logger
+            .i("TemplateManager saveTemplate  template Code:$code , key:$key.");
+      }
+
       /// 模板索引
       TextStorage templateRelation = TextStorage(
         fileName: "templateRelation",

+ 6 - 2
lib/pages/patient/csv_datas/csv_datas_view.dart

@@ -161,7 +161,11 @@ class CSVDatasViewState extends State<CSVDatasView> {
         SizedBox(
           width: 3,
         ),
-        Text(value),
+        Text(
+          value,
+          maxLines: 2,
+          style: TextStyle(fontSize: value.length > 40 ? 13 : 14),
+        ),
         SizedBox(
           width: 15,
         ),
@@ -296,7 +300,7 @@ class CSVDatasViewState extends State<CSVDatasView> {
         });
       },
       child: Text(
-        _isShowErrorData ? "切换至校验通过数据" : "切换至校验不通过数据",
+        _isShowErrorData ? "查看校验通过数据" : "查看校验不通过数据",
       ),
     );
   }

+ 55 - 7
lib/pages/patient/csv_datas/import_datas_view.dart

@@ -1,6 +1,6 @@
 import 'dart:async';
 import 'dart:convert';
-
+import 'package:excel/excel.dart';
 import 'package:flutter/foundation.dart';
 import 'package:flutter/material.dart';
 import 'package:get/get.dart';
@@ -16,7 +16,7 @@ class ImportDataView extends StatelessWidget {
   @override
   Widget build(BuildContext context) {
     return GridView.count(
-      crossAxisCount: 7, // 每行显示的子组件数量
+      crossAxisCount: 6, // 每行显示的子组件数量
       crossAxisSpacing: 4.0, // 子组件之间的水平间距
       mainAxisSpacing: 4.0, // 子组件之间的垂直间距
       childAspectRatio: 1.0, // 子组件的宽高比
@@ -27,13 +27,35 @@ class ImportDataView extends StatelessWidget {
             Icons.abc,
             size: 40,
           ),
-          onTap: _csvImportClick,
+          onTap: () {
+            _importClick("BiochemicalValues_CQZY");
+          },
+        ),
+        FunctionButton(
+          label: "黑台生化",
+          icon: Icon(
+            Icons.abc,
+            size: 40,
+          ),
+          onTap: () {
+            _importClick("BiochemicalValues_HT");
+          },
+        ),
+        FunctionButton(
+          label: "黑台血常规",
+          icon: Icon(
+            Icons.abc,
+            size: 40,
+          ),
+          onTap: () {
+            _importClick("BloodRoutine_HT");
+          },
         ),
       ],
     );
   }
 
-  Future<void> _csvImportClick() async {
+  Future<void> _importClick(String key) async {
     final html.FileUploadInputElement uploadInput =
         html.FileUploadInputElement();
     uploadInput.accept = '.xls,.xlsx,.csv'; // 设置接受的文件类型
@@ -43,19 +65,45 @@ class ImportDataView extends StatelessWidget {
 
     html.File? file = uploadInput.files?.first;
     String extension = file?.name.split('.').last.toLowerCase() ?? "";
+    Store.app.busy = true;
     if (extension == "csv") {
-      Store.app.busy = true;
       try {
         List<List<dynamic>> csvData = await readCSVFile(file!);
-        var records = await Get.find<ICsvDataManager>().CsvDataConvert(csvData);
+        var records =
+            await Get.find<ICsvDataManager>().CsvDataConvert(csvData, key);
         if (records.isNotEmpty) {
           Get.to(CSVDatasView(records));
         } else {
           PromptBox.toast('无可上传数据');
         }
       } catch (e) {}
-      Store.app.busy = false;
+    } else if (extension == "xlsx") {
+      final reader = html.FileReader();
+      reader.onLoadEnd.listen((e) async {
+        var bytes = reader.result as List<int>;
+        var excel = Excel.decodeBytes(bytes);
+
+        // Assuming the first sheet is what you want to read
+        for (var table in excel.tables.keys) {
+          print(table); // sheet name
+          print(excel.tables[table]?.maxColumns);
+          print(excel.tables[table]?.maxRows);
+          var records = await Get.find<ICsvDataManager>()
+              .ExcelDataConvert(excel.tables[table]!.rows, key);
+          if (records.isNotEmpty) {
+            Get.to(CSVDatasView(records));
+          } else {
+            PromptBox.toast('无可上传数据');
+          }
+        }
+        var content = excel.tables.keys.first;
+      });
+      reader.onError.listen((fileEvent) {
+        print("Some Error occured while reading the file");
+      });
+      reader.readAsArrayBuffer(file!);
     }
+    Store.app.busy = false;
   }
 
   Future<List<List<dynamic>>> readCSVFile(html.File file) async {

+ 18 - 2
pubspec.lock

@@ -21,10 +21,10 @@ packages:
     dependency: transitive
     description:
       name: archive
-      sha256: "22600aa1e926be775fa5fe7e6894e7fb3df9efda8891c73f70fb3262399a432d"
+      sha256: "7b875fd4a20b165a3084bd2d210439b22ebc653f21cea4842729c0c30c82596b"
       url: "https://pub.flutter-io.cn"
     source: hosted
-    version: "3.4.10"
+    version: "3.4.9"
   args:
     dependency: transitive
     description:
@@ -329,6 +329,14 @@ packages:
       url: "https://pub.flutter-io.cn"
     source: hosted
     version: "5.0.1"
+  equatable:
+    dependency: transitive
+    description:
+      name: equatable
+      sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2
+      url: "https://pub.flutter-io.cn"
+    source: hosted
+    version: "2.0.5"
   esc_utils:
     dependency: "direct main"
     description:
@@ -337,6 +345,14 @@ packages:
       url: "https://pub.flutter-io.cn"
     source: hosted
     version: "0.0.1"
+  excel:
+    dependency: "direct overridden"
+    description:
+      name: excel
+      sha256: f7cde34ffdbb397edeb4566621433bb820517cc0d8676c20d6122a85f749ee49
+      url: "https://pub.flutter-io.cn"
+    source: hosted
+    version: "3.0.0"
   fake_async:
     dependency: transitive
     description:

+ 1 - 0
pubspec.yaml

@@ -147,6 +147,7 @@ dependency_overrides:
   audio_session: 0.1.6
   flutter_sound: 9.2.13
   csv: 6.0.0
+  excel: 3.0.0
   flutter_sound_platform_interface: 9.2.13
   universal_html: 2.0.8