import 'dart:convert'; import 'package:fis_jsonrpc/rpc.dart'; import 'package:flutter/foundation.dart'; import 'package:vital_local_database/core/interface/queryable.dart'; import 'package:vitalapp/database/db.dart'; import 'package:vitalapp/database/entities/defines.dart'; import 'package:vitalapp/database/entities/patient.dart'; import 'package:vitalapp/global.dart'; import 'package:vitalapp/managers/interfaces/models/patient_model_dto.dart'; import 'package:vitalapp/managers/interfaces/patient.dart'; import 'package:vitalapp/mock/services/patient.dart'; import 'package:vitalapp/pages/patient/info/widgets/ext_model.dart'; import 'package:vitalapp/rpc.dart'; import 'package:fis_common/logger/logger.dart'; import 'package:vitalapp/store/store.dart'; class PatientManager implements IPatientManager { String? get userCode => Store.user.userCode; @override Future create(CreatePatientRequest2 request) async { request.token = Store.user.token; request.code = request.cardNo; final result = await rpc.vitalPatient.createPatientAsync(request); return result; } @override Future?> getPagedOfflineList( String? keyword, DateTime? startTime, DateTime? endTime, ) async { final isKeywordQuery = keyword != null && keyword.isNotEmpty; var query = db.repositories.patient.queryable.where((x) { final List arr = []; arr.add(x.isValid.equals(true)); arr.add(x.orgCode.equals(Store.user.organizationCode)); arr.add(x.overallSyncState.notEquals(OfflineDataSyncState.success)); if (!isKeywordQuery) {} return arr; }); if (isKeywordQuery) { // 根据 姓名or身份证号 模糊查询 query = query.whereCustom( " AND ( name like '%$keyword%' OR code like '%$keyword%' ) "); } else { if (startTime != null) { query = query.and((x) => x.createTime.gte(startTime)); } if (endTime != null) { query = query.and((x) => x.createTime.lt(endTime)); } } final entities = await query.orderBy((x) => x.updateTime, DbOrderByType.desc).toList(); final dtos = entities.map((e) { var patientModel = PatientModelDTO.fromJson(jsonDecode(e.dataJson)); patientModel.isExistLocalData = true; return patientModel; }).toList(); return dtos; } @override Future getDetail(String code) async { final request = GetPatientRequest(code: code, token: Store.user.token); try { if (kIsOnline && !kIsWeb) { //在线状态,先查询是否存在本地未提交数据 final entity = await db.repositories.patient .singleByCodeWithUserCode(code, Store.user.userCode!); if (entity != null && entity.dataJson.isNotEmpty && entity.syncState != OfflineDataSyncState.success) { logger.i("PatientManager query patient detail location exist."); final jsonMap = jsonDecode(entity.dataJson); final dto = PatientDTO.fromJson(jsonMap); return dto; } else { logger.i("PatientManager query patient detail location not exist."); } } final result = await rpc.vitalPatient.getPatientDetailAsync(request); return result; } catch (e) { logger.e("PatientManager query patient detail error.", e); logger.i("GetPatientRequest: ${jsonEncode(request.toJson())}"); return null; } } @override Future?> getPagedList( PatientPageRequest request) async { PageCollection? listPatientDto = PageCollection(); try { request.token = Store.user.token; print(jsonEncode(request.toJson())); final result = await rpc.vitalPatient.getPatientPageAsync(request); listPatientDto.dataCount = result.dataCount; listPatientDto.pageData = []; for (var element in result.pageData!) { var patientModel = PatientModelDTO.fromJson(element.toJson()); if (!kIsWeb) { var isNotUploadedPatient = await db.repositories.patient.isNotUploadedPatient(element.code!); if (isNotUploadedPatient) { patientModel.isExistLocalData = true; } } listPatientDto.pageData?.add(patientModel); } return listPatientDto; } catch (e) { logger.e("PatientManager query patient paged list error.", e); return null; } } @override Future updatePatientAsync(UpdatePatientRequest2 request) async { try { if (kIsOnline) { await _updateLocationPatientAsync(request); } final result = await rpc.vitalPatient.updatePatientAsync(request); return result; } catch (e) { return false; } } ///在线编辑居民信息时,同步更改本地缓存 Future _updateLocationPatientAsync( UpdatePatientRequest2 request) async { final code = request.code!; final existEntity = await _checkPatientExist(code); PatientEntity entity; PatientDTO dto; if (existEntity == null) { entity = PatientEntity(); entity.code = request.code!; entity.isValid = true; entity.name = request.patientName!; entity.userCode = Store.user.userCode!; //添加用户code entity.syncState = OfflineDataSyncState.success; dto = PatientDTO(); ModelConverter.syncUpdate2Dto(dto, request); final dtoJson = dto.toJson(); entity.dataJson = jsonEncode(dtoJson); final id = await db.repositories.patient.insert(entity); return id > 0; } else { entity = existEntity; final jsonMap = jsonDecode(entity.dataJson); dto = PatientDTO.fromJson(jsonMap); ModelConverter.syncUpdate2Dto(dto, request); final dtoJson = dto.toJson(); entity.dataJson = jsonEncode(dtoJson); final rows = await db.repositories.patient.update(entity); return rows > 0; } } Future _checkPatientExist(String code) async { try { final entity = await db.repositories.patient .singleByCodeWithUserCode(code, Store.user.userCode!); return entity; } catch (e) { logger.e( "PatientServiceMock - Check patient exist error. Code: $code.", e); } return null; } @override Future setCrowdLabelsAsync( String patientCode, List crowLabels) async { try { final request = SetCrowdLabelsRequest( code: patientCode, crowdLabels: crowLabels, token: Store.user.token); final result = rpc.vitalPatient.setCrowdLabelsAsync(request); return result; } catch (e) { logger.e("PatientManager setCrowdLabelsAsync error.", e); return false; } } Future createPatientExtension( String patientCode, PatientHealthInfoModel healthInfo, PatientDetailInfoModel detailInfo, String healthCode) async { final jsonMap = {}; final detailJsonMap = detailInfo.toJson(); final healthJsonMap = healthInfo.toJson(); jsonMap.addAll(detailJsonMap); jsonMap.addAll(healthJsonMap); jsonMap.removeWhere((key, value) => value == null); if (!kIsOnline) { if (healthCode.startsWith("mock")) { healthCode = ""; // TODO:update from server } } if (healthCode.isNotEmpty) { var request = UpdatePatientExtensionRequest( code: healthCode, token: Store.user.token, patientCode: patientCode, key: "PatientHealthInfo", extensionData: jsonEncode(jsonMap), ); var result = await updatePatientExtensionAsync(request); if (result) {} } else { var request = CreatePatientExtensionRequest( token: Store.user.token, patientCode: patientCode, key: "PatientHealthInfo", extensionData: jsonEncode(jsonMap), ); var result = await createPatientExtensionAsync(request); if (result.isNotEmpty) { healthCode = result; } } ///更新 return healthCode; } @override Future createPatientExtensionAsync( CreatePatientExtensionRequest request) async { try { final result = await rpc.vitalPatientExtension.createPatientExtensionAsync(request); return result; } catch (e) { logger.e("PatientManager createPatientExtension error.", e); return ''; } } @override Future getPatientExtensionDetailByCodeAndKeyAsync( GetPatientExtensionByCodeAndKeyRequest request) async { try { final result = await rpc.vitalPatientExtension .getPatientExtensionDetailByCodeAndKeyAsync(request); return result; } catch (e) { return null; } } @override Future updatePatientExtensionAsync( UpdatePatientExtensionRequest request) async { try { final result = await rpc.vitalPatientExtension.updatePatientExtensionAsync(request); return result; } catch (e) { logger.e("PatientManager updatePatientExtension error.", e); return false; } } ///获取所有userCode为空的数据,并赋值 @override Future resettingUsercodeIsEmptyData() async { if (kIsWeb) return; var version = await db.database.getVersion(); if (version > 0) { final list = await db.repositories.patient.queryable.where((x) { final List arr = []; arr.add(x.isValid.equals(true)); arr.add(x.userCode.equals('')); return arr; }).toList(); logger.w( "PatientManager resettingUsercodeIsEmptyData list.count:${list.length}."); for (var element in list) { if (element.syncState == OfflineDataSyncState.success) { var result = await getDetail(element.code); if (result != null) { element.userCode = result.createdDoctor!; } } else { element.userCode = Store.user.userCode!; } await db.repositories.patient.update(element); } // 更新归属于该医生下的居民的组织Code final orgCode = Store.user.organizationCode; final userCode = Store.user.userCode; await db.database.execute( "UPDATE patients SET orgCode = '$orgCode' WHERE 1=1 AND isValid=1 AND orgCode='' AND userCode='$userCode';"); } } @override Future switchCurrentPatient(PatientDTO dto) async { try { if (!kIsWeb) { await _syncCloud2Offline(dto); } Store.user.currentSelectPatientInfo = dto; } catch (e) { logger.e("PatientManager switchCurrentPatient-${dto.code} error.", e); } } @override Future switchCurrentPatientByCode(String code) async { final dto = await getDetail(code); if (dto != null) { await switchCurrentPatient(dto); } } @override Future getRegisterPersonInfoByPhysicalExamNumberAsync({ required String physicalExamNumber, }) async { try { var request = GetRegisterPersonRequest(); request.physicalExamNumber = physicalExamNumber; final registerPersonInfo = await rpc.vitalHealthExamBooking .getRegisterPersonInfoByPhysicalExamNumberAsync( request, ); return registerPersonInfo; } catch (e) { logger.e( "PatientManager sync getRegisterPersonInfoByPhysicalExamNumberAsync error.", e); return null; } } @override Future removePatient(String code) async { bool result = false; try { final entity = await db.repositories.patient .singleByCodeWithUserCode(code, Store.user.userCode!); if (entity != null) { result = await db.repositories.patient.delete(entity.id); if (!result) { return false; } } if (kIsOnline) { try { // 先检查云端是否有数据 final dto = await rpc.vitalPatient.getPatientDetailAsync( GetPatientRequest(code: code, token: Store.user.token), ); // 然后再请求删除 result = await rpc.vitalPatient.removePatientAsync( RemovePatientRequest(code: code, token: Store.user.token), ); } catch (e) { logger.e("PatientManager remove cloud patient-$code error.", e); } } } catch (e) { logger.e("PatientManager remove patient-$code error.", e); result = false; } if (result) { if (Store.user.currentSelectPatientInfo?.code == code) { Store.user.currentSelectPatientInfo = null; } } return result; } @override Future getStatistic() async { try { if (!kIsOnline) { // TODO: offline statistic return PatientStatisticDTO(); } final result = await rpc.vitalPatient.getPatientStatisticAsync( GetPatientStatisticRequest(token: Store.user.token)); return result; } catch (e) { logger.e("PatientManager get patient statistic error.", e); return PatientStatisticDTO(); } } Future _syncCloud2Offline(PatientDTO dto) async { PatientEntity? entity = await db.repositories.patient .singleByCodeWithUserCode(dto.code!, Store.user.userCode!); if (entity == null) { entity = PatientEntity(); entity.isValid = true; entity.code = dto.code!; entity.userCode = userCode!; entity.orgCode = Store.user.organizationCode; // 从在线数据中刚获取的,不需要同步 entity.syncState = OfflineDataSyncState.success; entity.overallSyncState = OfflineDataSyncState.success; // 先创建,后面统一代码更新 final id = await db.repositories.patient.insert(entity); entity.id = id; } else { if (entity.syncState != OfflineDataSyncState.success) { // 本地档案有更新,已本地数据为准 return; } } entity.name = dto.patientName!; final dtoJsonMap = dto.toJson(); entity.dataJson = jsonEncode(dtoJsonMap); var extDto = await getPatientExtensionDetailByCodeAndKeyAsync( GetPatientExtensionByCodeAndKeyRequest( token: Store.user.token, patientCode: dto.code, key: "PatientHealthInfo", ), ); if (extDto != null && extDto.code != null) { entity.extJson = extDto.extensionData; entity.extCode = extDto.code; } await db.repositories.patient.update(entity); } }