123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506 |
- import 'package:flutter/material.dart';
- import 'package:flyinsono/architecture/router/desktop/names.dart';
- import 'package:flyinsono/architecture/services/modules/config_language.dart';
- import 'package:flyinsono/architecture/utils/common_util.dart';
- import 'package:flyinsono/architecture/utils/prompt_box.dart';
- import 'package:flyinsono/lab/color/lab_colors.dart';
- import 'package:flyinsono/lab/components/classify_data_selector/classify_data_selector.dart';
- import 'package:flyinsono/lab/components/lab_dialog.dart';
- import 'package:flyinsono/lab/manager/interfaces/project.dart';
- import 'package:flyinsono/lab/manager/page_manager.dart';
- import 'package:flyinsono/lab/mixin/tab_hook_mixin.dart';
- import 'package:flyinsono/lab/mock_data/mock_rpc.dart';
- import 'package:flyinsono/lab/pages/lab_batch_analysis/controller.dart';
- import 'package:flyinsono/lab/pages/lab_image/index.dart';
- import 'package:flyinsono/lab/router/lab_route_names.dart';
- import 'package:fis_jsonrpc/services/index.dart';
- import 'package:flyinsono/managers/interfaces/language.dart';
- import 'package:get/get.dart';
- import 'package:fis_measure/configs/patient.dart';
- import 'package:fis_measure/interfaces/enums/species.dart';
- import 'package:fis_common/helpers/encrypt.dart';
- import 'index.dart';
- class LabDataController extends GetxController with TabHookMixin {
- LabDataController({
- required this.tabHashCode,
- });
- @override
- final int tabHashCode;
- final state = LabDataState();
- /// 数据页分为以下五个部分
- static const dataSourceSelectorId = "data_source_selector"; // 数据源选择器
- static const patientListId = "patient_list"; // 病人/样本列表
- static const recordListId = "record_list"; // 检查记录列表
- static const imageListId = "image_list"; // 图片列表
- /// 数据源
- List<ProjectModel> dataSourceList = [];
- String selectedDataSourceId = "";
- /// 数据源搜索栏输入控制器
- final dataSourceSearchInputController = TextEditingController();
- /// 病人列表
- List<ClassifyData<PatientModel>> patientClassifyData = [];
- final languageConfigManager = Get.find<ILanguageConfigManager>();
- int selectedClassifyIndex = 0;
- int selectedPatientIndex = 0;
- bool isPatientListLoading = false;
- /// 检查记录列表
- List<RecordModel> recordList = [];
- bool isRecordListLoading = false;
- /// 图片列表
- List<ImageModel> imageList = [];
- bool isImageListLoading = false;
- /// 当前项目的病人类型
- OrganizationPatientTypeEnum patientType = OrganizationPatientTypeEnum.Person;
- List<PatientModel> get selectedPatientList =>
- [patientClassifyData[selectedClassifyIndex].data[selectedPatientIndex]];
- // 获取当前选中的病人
- PatientModel get selectedPatient =>
- patientClassifyData[selectedClassifyIndex].data[selectedPatientIndex];
- // 获取当前选中的检查记录
- RecordModel get selectedRecord => recordList[state.selectedRecordIndex];
- /// 当前无数据
- // bool get isNoData => dataSourceList.length == 0;
- /// 项目接口
- final projectService = Get.find<IProjectManager>();
- /// 语言服务
- final languageService = Get.find<LanguageService>();
- // 查看/编辑
- void editRecord() {
- print("查看/编辑 $selectedRecord");
- PageManager.ins.openNewTab(
- LabRouteNames.RecordInfo,
- "查看/编辑",
- multiple: false,
- args: selectedRecord,
- );
- }
- // 删除选中的检查记录
- void deleteRecord() async {
- dynamic result = await Get.dialog(
- LabDialog(
- title: "删除检查",
- content: "确定要删除当前所选检查?",
- ),
- barrierColor: LabColors.base100.withOpacity(0.1),
- );
- if (result is bool && result) {
- bool? deleteRecord = await projectService.deleteRecordAsync(
- recordCode: selectedRecord.id,
- projectCode: selectedDataSourceId,
- );
- if (deleteRecord ?? false) {
- await updatePatientList(selectedDataSourceId);
- PromptBox.toast('删除完成');
- print("删除检查记录 $selectedRecord");
- }
- }
- }
- void clickRecordItem(int index) {
- state.selectedRecordIndex = index;
- updateImageList(recordList[index].images);
- }
- void clickPatientItem(int classifyIndex, int index) {
- selectedClassifyIndex = classifyIndex;
- selectedPatientIndex = index;
- updateRecordList(patientClassifyData[classifyIndex].data[index].code);
- update([patientListId]);
- }
- ///删除病人
- Future<void> deleteCurrentPatient() async {
- String patientCode = patientClassifyData[selectedClassifyIndex]
- .data[selectedPatientIndex]
- .code;
- dynamic result = await Get.dialog(
- LabDialog(
- title: "删除样本",
- content: "确定要删除当前所选样本?",
- ),
- barrierColor: LabColors.base100.withOpacity(0.1),
- );
- if (result is bool && result) {
- bool deleteRecord =
- await projectService.deleteSample(selectedDataSourceId, patientCode);
- if (deleteRecord) {
- await updatePatientList(selectedDataSourceId);
- PromptBox.toast('删除完成');
- }
- }
- }
- // 根据病人 Id 选中病人
- void selectPatientByCode(String patientCode) {
- bool isExist = false;
- for (int i = 0; i < patientClassifyData.length; i++) {
- for (int j = 0; j < patientClassifyData[i].data.length; j++) {
- if (patientClassifyData[i].data[j].code == patientCode) {
- selectedClassifyIndex = i;
- selectedPatientIndex = j;
- isExist = true;
- break;
- }
- }
- if (isExist) break;
- }
- if (!isExist) return;
- updateRecordList(patientCode);
- update([patientListId]);
- }
- void clickImage(int index) {
- var currentProject = dataSourceList
- .firstWhereOrNull((element) => element.id == selectedDataSourceId);
- PageManager.ins.openTab(
- LabRouteNames.Image,
- args: LabImageActiveArguments(
- patient: selectedPatient,
- record: selectedRecord,
- images: imageList,
- selectedImageIndex: index,
- patientType: patientType,
- projectCode: currentProject?.id,
- ),
- );
- }
- /// 空图像测试入口
- void debugForEmptyImageList() async {
- final images = await MockRPC.getImageListByRecordId("");
- PageManager.ins.openTab(
- LabRouteNames.Image,
- args: LabImageActiveArguments(
- patient: selectedPatient,
- record: selectedRecord,
- images: images,
- selectedImageIndex: 0,
- ),
- );
- }
- /// 进入批量分析页面
- void enterBatchAnalysis() {
- PageManager.ins.openNewTab(
- LabRouteNames.BatchAnalysis,
- "批量分析",
- args: LabBatchAnalysisInitArguments(
- patient: selectedPatient,
- record: selectedRecord,
- images: imageList,
- projectCode: selectedDataSourceId,
- ),
- );
- }
- /// 初始化数据源列表
- void initDataSourceList() async {
- List<ResearchProjectBaseDTO>? researchProjectList =
- await projectService.getResearchProjectListAsync(
- keyWord: "",
- searchType: ResearchProjectSearchTypeEnum.Undefined,
- );
- List<ProjectModel> projects = [];
- researchProjectList?.forEach((element) {
- projects.add(ProjectModel(
- id: element.code ?? '',
- name: element.name ?? '',
- type: ProjectType.created,
- projectIntroduction: element.introduction ?? '',
- organizationPatientType: element.patientType,
- ));
- });
- dataSourceList = projects;
- selectedDataSourceId = dataSourceList[0].id;
- await updatePatientList(selectedDataSourceId);
- update([dataSourceSelectorId]);
- }
- /// 更新数据源列表
- void updateDataSourceList() async {
- List<ResearchProjectBaseDTO>? researchProjectList =
- await projectService.getResearchProjectListAsync(
- keyWord: "",
- searchType: ResearchProjectSearchTypeEnum.Undefined,
- );
- List<ProjectModel> projects = [];
- researchProjectList?.forEach((element) {
- projects.add(ProjectModel(
- id: element.code ?? '',
- name: element.name ?? '',
- type: ProjectType.created,
- projectIntroduction: element.introduction ?? '',
- organizationPatientType: element.patientType,
- ));
- });
- dataSourceList = projects;
- state.noData = dataSourceList.length == 0;
- if (!dataSourceList.map((e) => e.id).contains(selectedDataSourceId)) {
- if (dataSourceList.length > 0) {
- selectedDataSourceId = dataSourceList.first.id;
- } else {
- selectedDataSourceId = '';
- }
- await updatePatientList(selectedDataSourceId);
- }
- update([dataSourceSelectorId]);
- }
- // 选择数据源
- Future<void> selectDataSource(String? projectId) async {
- if (projectId == null) return;
- selectedDataSourceId = projectId;
- await updatePatientList(projectId);
- update([dataSourceSelectorId]);
- }
- /// 获取项目详情
- Future<void> getResearchProjectDetailAsync(String? projectId) async {
- if (projectId == null) return;
- ResearchProjectDTO? detail = await projectService.getResearchProjectDetail(
- projectCode: projectId,
- );
- patientType = detail?.patientType ?? OrganizationPatientTypeEnum.Person;
- await getResearchProjectData(projectId);
- }
- Future<void> getResearchProjectData(
- String projectId,
- ) async {
- PageCollection<ResearchProjectDataDTO>? result =
- await projectService.getResearchProjectDataPagesAsync(
- projectCode: projectId,
- keyWord: dataSourceSearchInputController.text,
- pageIndex: 1,
- pageSize: 1000,
- sort: 0,
- );
- List<PatientModel> patients = [];
- result?.pageData?.forEach((element) {
- String patientName =
- FEncryptHelper.decryptBase64(element.patientName ?? '');
- if (patientName.isEmpty) {
- patientName = "未命名";
- }
- patients.add(PatientModel(
- id: element.devicePatientId ?? '',
- code: element.patientCode ?? '',
- name: patientName,
- isExistUrmData: element.isUrm,
- fileSize: CommonUtil.convertBytesToMegabytesOrGigabytes(
- int.parse(
- element.fileSize ?? '0',
- ),
- ),
- ));
- });
- if (result?.pageData?.isEmpty ?? true) {
- patientClassifyData = [];
- isPatientListLoading = false;
- state.noPatient = true;
- update([patientListId]);
- return;
- } else {
- patientClassifyData = [
- ClassifyData(
- classifyName: patientType == OrganizationPatientTypeEnum.Person
- ? "实验样本"
- : "实验样本",
- data: patients,
- showActionButton: true,
- showItemActionButton: true,
- ),
- ];
- state.noPatient = false;
- }
- if (patients.length > 0) updateRecordList(selectedPatient.code);
- isPatientListLoading = false;
- update([patientListId]);
- }
- // 根据数据源更新样本列表(病人列表)
- Future<void> updatePatientList(String projectId) async {
- isPatientListLoading = true;
- isRecordListLoading = true;
- isImageListLoading = true;
- update([patientListId, recordListId, imageListId]);
- if (projectId.isEmpty) {
- return;
- }
- await getResearchProjectDetailAsync(projectId);
- isPatientListLoading = false;
- update([patientListId, imageListId]);
- }
- // 根据病人 code 更新检查记录列表
- void updateRecordList(String patientCode) async {
- isRecordListLoading = true;
- isImageListLoading = true;
- update([recordListId, imageListId]);
- List<RecordModel> result = await projectService.getRecordDetail(
- patientCode: patientCode,
- patientType: patientType,
- selectedPatient: selectedPatient,
- );
- recordList = result;
- if (result.isEmpty) {
- state.noRecord = true;
- return;
- } else {
- state.selectedRecordIndex = 0;
- updateImageList(result.first.images);
- state.noRecord = false;
- }
- isRecordListLoading = false;
- update([recordListId]);
- }
- /// 切换测量公式
- void changeMeasureCalcuators() {
- List<DataItemDTO> patientInfo = selectedRecord.patientInfo;
- if (patientInfo.isNotEmpty) {
- DataItemDTO? dataItem = patientInfo.firstWhereOrNull((element) =>
- element.key == "Species" &&
- (element.value == "Mouse" || element.value == "Rat"));
- if (dataItem != null) {
- GlobalPatientConfig.switchSpecies(SpeciesType.mouse);
- } else {
- GlobalPatientConfig.switchSpecies(SpeciesType.animals);
- }
- }
- }
- // 根据检查记录 Id 更新图片列表
- void updateImageList(List<ImageModel> resultImage) {
- changeMeasureCalcuators();
- isImageListLoading = true;
- update([imageListId]);
- imageList = resultImage;
- isImageListLoading = false;
- update([imageListId]);
- }
- // 更新当前选中的检查下的图像列表
- void updateImageListByCurrRecord() async {
- // 判断当前是否选中了检查记录,如果有则获取检查下的图像列表
- if (recordList.isNotEmpty) {
- // 取当前选中的检查code,获取详情数据
- List<RecordModel> result = await projectService.getRecordDetail(
- patientCode: selectedPatient.code,
- patientType: patientType,
- selectedPatient: selectedPatient,
- );
- recordList = result;
- if (result.isEmpty) {
- state.noRecord = true;
- return;
- } else {
- if (result.length > state.selectedRecordIndex) {
- updateImageList(result[state.selectedRecordIndex].images);
- }
- state.noRecord = false;
- }
- }
- }
- void updateByLabDataActiveArguments(LabDataActiveArguments arguments) async {
- if (selectedDataSourceId != arguments.projectCode) {
- // selectedClassifyIndex = 0;
- selectedPatientIndex = 0;
- }
- print("🥓🥓🥓🥓🥓");
- print(arguments.projectCode);
- print(arguments.patientCode);
- print("🥓🥓🥓🥓🥓");
- await selectDataSource(arguments.projectCode);
- selectPatientByCode(arguments.patientCode);
- }
- @override
- void onSleep() {
- // cancelTimer();
- print("Lab Data onSleep: $tabHashCode");
- }
- @override
- void onActive(arguments) {
- updateDataSourceList();
- print("Lab Data onActive: $tabHashCode arguments: $arguments");
- if (arguments is LabDataActiveArguments) {
- updateByLabDataActiveArguments(arguments);
- } else {
- try {
- updateImageListByCurrRecord();
- } catch (e) {
- print(e);
- }
- }
- }
- /// 在 widget 内存中分配后立即调用。
- @override
- void onInit() {
- super.onInit();
- initDataSourceList();
- /// 初始化语言包
- languageService.init();
- }
- /// 在 onInit() 之后调用 1 帧。这是进入的理想场所
- @override
- void onReady() {
- super.onReady();
- }
- /// 在 [onDelete] 方法之前调用。
- @override
- void onClose() {
- super.onClose();
- }
- /// dispose 释放内存
- @override
- void dispose() {
- super.dispose();
- }
- void debugForHomePage() {
- Get.offNamed(RouteNames.Lab.Login);
- }
- }
- class LabDataActiveArguments {
- LabDataActiveArguments({
- required this.projectCode,
- required this.patientCode,
- });
- final String projectCode;
- final String patientCode;
- }
|