|
@@ -12,6 +12,12 @@ import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
import org.slf4j.LoggerFactory;
|
|
|
import work.baiyun.chronicdiseaseapp.mapper.CriticalValueMapper;
|
|
import work.baiyun.chronicdiseaseapp.mapper.CriticalValueMapper;
|
|
|
import work.baiyun.chronicdiseaseapp.model.po.CriticalValue;
|
|
import work.baiyun.chronicdiseaseapp.model.po.CriticalValue;
|
|
|
|
|
+import work.baiyun.chronicdiseaseapp.model.vo.SystemAnomalySendRequest;
|
|
|
|
|
+import work.baiyun.chronicdiseaseapp.enums.MessageType;
|
|
|
|
|
+import work.baiyun.chronicdiseaseapp.service.MessageService;
|
|
|
|
|
+import work.baiyun.chronicdiseaseapp.service.UserBindingService;
|
|
|
|
|
+import work.baiyun.chronicdiseaseapp.model.vo.BaseQueryRequest;
|
|
|
|
|
+import work.baiyun.chronicdiseaseapp.model.vo.UserBindingResponse;
|
|
|
import work.baiyun.chronicdiseaseapp.util.SecurityUtils;
|
|
import work.baiyun.chronicdiseaseapp.util.SecurityUtils;
|
|
|
|
|
|
|
|
import java.lang.reflect.Field;
|
|
import java.lang.reflect.Field;
|
|
@@ -33,6 +39,12 @@ public class HealthDataCriticalAlertAspect {
|
|
|
@Autowired
|
|
@Autowired
|
|
|
private CriticalValueMapper criticalValueMapper;
|
|
private CriticalValueMapper criticalValueMapper;
|
|
|
|
|
|
|
|
|
|
+ @Autowired
|
|
|
|
|
+ private MessageService messageService;
|
|
|
|
|
+
|
|
|
|
|
+ @Autowired
|
|
|
|
|
+ private UserBindingService userBindingService;
|
|
|
|
|
+
|
|
|
@Pointcut("execution(* work.baiyun.chronicdiseaseapp.controller..*(..)) && (execution(* *..add*(..)) || execution(* *..upload*(..)) || execution(* *..create*(..)))")
|
|
@Pointcut("execution(* work.baiyun.chronicdiseaseapp.controller..*(..)) && (execution(* *..add*(..)) || execution(* *..upload*(..)) || execution(* *..create*(..)))")
|
|
|
public void uploadMethods() {}
|
|
public void uploadMethods() {}
|
|
|
|
|
|
|
@@ -105,6 +117,9 @@ public class HealthDataCriticalAlertAspect {
|
|
|
mapKeyToCode.put("rate", "heartRate");
|
|
mapKeyToCode.put("rate", "heartRate");
|
|
|
mapKeyToCode.put("hr", "heartRate");
|
|
mapKeyToCode.put("hr", "heartRate");
|
|
|
|
|
|
|
|
|
|
+ // collect warnings per measurement, we'll aggregate and send one system-anomaly message if any
|
|
|
|
|
+ Map<String, Map<String, Object>> warnings = new HashMap<>();
|
|
|
|
|
+
|
|
|
// For each measurement, load threshold and compare
|
|
// For each measurement, load threshold and compare
|
|
|
for (Map.Entry<String, BigDecimal> e : measurements.entrySet()) {
|
|
for (Map.Entry<String, BigDecimal> e : measurements.entrySet()) {
|
|
|
String key = e.getKey();
|
|
String key = e.getKey();
|
|
@@ -127,9 +142,91 @@ public class HealthDataCriticalAlertAspect {
|
|
|
if (warn) {
|
|
if (warn) {
|
|
|
logger.warn("危急值警告: userId={} type={} measured={} below={} above={} controllerMethod={}",
|
|
logger.warn("危急值警告: userId={} type={} measured={} below={} above={} controllerMethod={}",
|
|
|
userId, code, measured, low, high, pjp.getSignature().toShortString());
|
|
userId, code, measured, low, high, pjp.getSignature().toShortString());
|
|
|
|
|
+ // add to aggregated anomaly data
|
|
|
|
|
+ Map<String, Object> info = new HashMap<>();
|
|
|
|
|
+ info.put("measured", measured);
|
|
|
|
|
+ info.put("below", low);
|
|
|
|
|
+ info.put("above", high);
|
|
|
|
|
+ info.put("detectedBy", pjp.getSignature().toShortString());
|
|
|
|
|
+ warnings.put(code, info);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ // If any warnings collected, send a single system anomaly message
|
|
|
|
|
+ if (!warnings.isEmpty()) {
|
|
|
|
|
+ // Build a richer anomaly payload containing original patient id and detected anomalies
|
|
|
|
|
+ Map<String, Object> anomalyPayload = new HashMap<>();
|
|
|
|
|
+ anomalyPayload.put("patientId", userId);
|
|
|
|
|
+ anomalyPayload.put("anomalies", warnings);
|
|
|
|
|
+ anomalyPayload.put("detectedAt", java.time.LocalDateTime.now().toString());
|
|
|
|
|
+
|
|
|
|
|
+ // prepare base request
|
|
|
|
|
+ SystemAnomalySendRequest baseReq = new SystemAnomalySendRequest();
|
|
|
|
|
+ baseReq.setAnomalyData(anomalyPayload);
|
|
|
|
|
+ baseReq.setType(MessageType.SYSTEM_ANOMALY);
|
|
|
|
|
|
|
|
|
|
+ // Collect recipients: patient, bound family, bound doctors
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 1) send to patient (uploader)
|
|
|
|
|
+ try {
|
|
|
|
|
+ SystemAnomalySendRequest reqPatient = new SystemAnomalySendRequest();
|
|
|
|
|
+ reqPatient.setPatientId(userId);
|
|
|
|
|
+ reqPatient.setAnomalyData(anomalyPayload);
|
|
|
|
|
+ reqPatient.setType(MessageType.SYSTEM_ANOMALY);
|
|
|
|
|
+ String msgId = messageService.sendSystemAnomalyMessage(reqPatient);
|
|
|
|
|
+ logger.info("Sent system anomaly message id={} to patientId={} anomalies={}", msgId, userId, warnings.keySet());
|
|
|
|
|
+ } catch (Exception ex) {
|
|
|
|
|
+ logger.error("Failed to send system anomaly message to patient {}", userId, ex);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 2) send to bound family
|
|
|
|
|
+ try {
|
|
|
|
|
+ java.util.List<Long> familyIds = userBindingService.getBoundFamilyIds(userId);
|
|
|
|
|
+ if (familyIds != null) {
|
|
|
|
|
+ for (Long famId : familyIds) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ SystemAnomalySendRequest reqFam = new SystemAnomalySendRequest();
|
|
|
|
|
+ reqFam.setPatientId(famId);
|
|
|
|
|
+ reqFam.setAnomalyData(anomalyPayload);
|
|
|
|
|
+ reqFam.setType(MessageType.SYSTEM_ANOMALY);
|
|
|
|
|
+ String msgIdFam = messageService.sendSystemAnomalyMessage(reqFam);
|
|
|
|
|
+ logger.info("Sent system anomaly message id={} to familyId={} for patient={} anomalies={}", msgIdFam, famId, userId, warnings.keySet());
|
|
|
|
|
+ } catch (Exception ex) {
|
|
|
|
|
+ logger.error("Failed to send system anomaly message to family {}", famId, ex);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (Exception ex) {
|
|
|
|
|
+ logger.warn("Failed to fetch bound family ids for user {}", userId, ex);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 3) send to bound doctors (use listBindingsByPatient to find DOCTOR bindings)
|
|
|
|
|
+ try {
|
|
|
|
|
+ BaseQueryRequest bqr = new BaseQueryRequest();
|
|
|
|
|
+ // call service to get bindings (we only need the first page)
|
|
|
|
|
+ com.baomidou.mybatisplus.extension.plugins.pagination.Page<UserBindingResponse> page = userBindingService.listBindingsByPatient(userId, "DOCTOR", bqr);
|
|
|
|
|
+ if (page != null && page.getRecords() != null) {
|
|
|
|
|
+ for (UserBindingResponse ub : page.getRecords()) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ Long docId = Long.valueOf(ub.getBoundUserId());
|
|
|
|
|
+ SystemAnomalySendRequest reqDoc = new SystemAnomalySendRequest();
|
|
|
|
|
+ reqDoc.setPatientId(docId);
|
|
|
|
|
+ reqDoc.setAnomalyData(anomalyPayload);
|
|
|
|
|
+ reqDoc.setType(MessageType.SYSTEM_ANOMALY);
|
|
|
|
|
+ String msgIdDoc = messageService.sendSystemAnomalyMessage(reqDoc);
|
|
|
|
|
+ logger.info("Sent system anomaly message id={} to doctorId={} for patient={} anomalies={}", msgIdDoc, docId, userId, warnings.keySet());
|
|
|
|
|
+ } catch (Exception ex) {
|
|
|
|
|
+ logger.error("Failed to send system anomaly message to a bound doctor record {}", ub, ex);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (Exception ex) {
|
|
|
|
|
+ logger.warn("Failed to fetch bound doctor bindings for user {}", userId, ex);
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (Exception ex) {
|
|
|
|
|
+ logger.error("Failed to send aggregated system anomaly messages", ex);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
} catch (Exception ex) {
|
|
} catch (Exception ex) {
|
|
|
logger.error("HealthDataCriticalAlertAspect failed to check critical values", ex);
|
|
logger.error("HealthDataCriticalAlertAspect failed to check critical values", ex);
|
|
|
}
|
|
}
|