fix: 修复剩余MEDIUM/LOW问题

This commit is contained in:
2026-06-18 21:34:03 +08:00
parent ea0c3b80c3
commit 29c0fcda9f
7 changed files with 135 additions and 12 deletions

View File

@@ -110,7 +110,63 @@ public class CdssAppServiceImpl implements ICdssAppService {
}
private boolean evaluateCondition(String conditionExpr, Long encounterId, Long patientId) {
return conditionExpr.contains("encounterId") || conditionExpr.contains("patientId");
String expr = conditionExpr.trim();
if (expr.isEmpty()) return false;
if (expr.contains(" OR ")) {
for (String part : expr.split("(?i)\\s+OR\\s+")) {
if (evaluateCondition(part.trim(), encounterId, patientId)) return true;
}
return false;
}
if (expr.contains(" AND ")) {
for (String part : expr.split("(?i)\\s+AND\\s+")) {
if (!evaluateCondition(part.trim(), encounterId, patientId)) return false;
}
return true;
}
String[] ops = {">=", "<=", "!=", "=", ">", "<"};
for (String op : ops) {
int idx = expr.indexOf(op);
if (idx > 0) {
String left = expr.substring(0, idx).trim();
String right = expr.substring(idx + op.length()).trim();
Object leftVal = resolveParam(left, encounterId, patientId);
if (leftVal == null) return false;
int cmp = compareValues(leftVal.toString(), right);
return switch (op) {
case ">=" -> cmp >= 0;
case "<=" -> cmp <= 0;
case "!=" -> cmp != 0;
case "=" -> cmp == 0;
case ">" -> cmp > 0;
case "<" -> cmp < 0;
default -> false;
};
}
}
return !"0".equals(expr) && !"false".equalsIgnoreCase(expr) && !"null".equalsIgnoreCase(expr);
}
private Object resolveParam(String name, Long encounterId, Long patientId) {
return switch (name.trim().toLowerCase()) {
case "encounterid" -> encounterId;
case "patientid" -> patientId;
default -> {
try { yield Long.parseLong(name); }
catch (NumberFormatException e) { yield name; }
}
};
}
private int compareValues(String left, String right) {
try {
return Long.compare(Long.parseLong(left), Long.parseLong(right));
} catch (NumberFormatException e) {
return left.compareTo(right);
}
}
private CdssAlert buildAlert(CdssRule rule, Long encounterId, Long patientId) {

View File

@@ -1,6 +1,8 @@
package com.healthlink.his.web.esbmanage.appservice.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.healthlink.his.administration.domain.Encounter;
import com.healthlink.his.administration.service.IEncounterService;
import com.healthlink.his.esb.domain.EsbServiceRegistry;
import com.healthlink.his.esb.domain.RegionalShareRecord;
import com.healthlink.his.esb.service.IEsbServiceRegistryService;
@@ -21,6 +23,7 @@ public class RegionalShareAppServiceImpl implements IRegionalShareAppService {
private final IRegionalShareRecordService shareRecordService;
private final IEsbServiceRegistryService registryService;
private final IEncounterService encounterService;
@Override
public RegionalShareRecord sharePatientData(Long encounterId, String targetSystem) {
@@ -34,7 +37,8 @@ public class RegionalShareAppServiceImpl implements IRegionalShareAppService {
RegionalShareRecord record = new RegionalShareRecord();
record.setEncounterId(encounterId);
record.setPatientId(0L);
Encounter encounter = encounterService.getById(encounterId);
record.setPatientId(encounter != null ? encounter.getPatientId() : 0L);
record.setShareType("PATIENT_DATA");
record.setTargetSystem(targetSystem);
record.setShareStatus("PENDING");

View File

@@ -169,7 +169,7 @@ public class InfectionEnhancedAppServiceImpl implements IInfectionEnhancedAppSer
private Date parseDate(String s) {
try { return new java.text.SimpleDateFormat("yyyy-MM-dd").parse(s); }
catch (Exception e) { return null; }
catch (Exception e) { log.warn("日期解析失败: {}", s); return null; }
}
private int parseInt(Object val, int defaultVal) {

View File

@@ -108,7 +108,7 @@ public class InfectionScreeningAppServiceImpl implements IInfectionScreeningAppS
return true;
}
}
} catch (NumberFormatException ignored) {}
} catch (NumberFormatException e) { log.warn("minDays解析失败: {}", params.get("minDays")); }
}
return false;
}

View File

@@ -99,7 +99,7 @@ public class TargetedSurveillanceAppServiceImpl implements ITargetedSurveillance
try {
java.time.LocalDate ld = java.time.LocalDate.parse(s, java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd"));
return java.util.Date.from(ld.atStartOfDay(java.time.ZoneId.systemDefault()).toInstant());
} catch (Exception e) { return null; }
} catch (Exception e) { log.warn("日期解析失败: {}", s); return null; }
}
private int parseInt(Object val, int defaultVal) {

View File

@@ -32,9 +32,22 @@ public class EmrQualityAppServiceImpl implements IEmrQualityAppService {
List<Map<String, Object>> checks = new ArrayList<>();
String[] items = {"入院记录24h完成", "首次病程8h完成", "日常病程及时", "出院记录完整", "签名完整"};
int pass = 0;
List<EmrDefect> defects = defectMapper.selectList(new LambdaQueryWrapper<EmrDefect>()
.eq(EmrDefect::getEncounterId, encounterId).eq(EmrDefect::getDelFlag, "0"));
Set<String> defectTypes = new HashSet<>();
for (EmrDefect d : defects) {
if (d.getDefectType() != null) defectTypes.add(d.getDefectType());
}
for (String item : items) {
Map<String, Object> check = new HashMap<>();
check.put("item", item); check.put("result", "PASS"); checks.add(check); pass++;
boolean passed = true;
if ("入院记录24h完成".equals(item) && defectTypes.contains("TIMELY")) passed = false;
if ("首次病程8h完成".equals(item) && defectTypes.contains("TIMELY")) passed = false;
if ("日常病程及时".equals(item) && defectTypes.contains("TIMELY")) passed = false;
if ("出院记录完整".equals(item) && defectTypes.contains("COMPLETENESS")) passed = false;
if ("签名完整".equals(item) && defectTypes.contains("SIGNATURE")) passed = false;
check.put("item", item); check.put("result", passed ? "PASS" : "FAIL"); checks.add(check);
if (passed) pass++;
}
result.put("encounterId", encounterId); result.put("checks", checks);
result.put("totalItems", items.length); result.put("passItems", pass);
@@ -78,8 +91,41 @@ public class EmrQualityAppServiceImpl implements IEmrQualityAppService {
}
@Override
public Map<String, Object> getCompletionRate(String startDate, String endDate) {
LambdaQueryWrapper<EmrDefect> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(EmrDefect::getDelFlag, "0");
if (startDate != null && !startDate.isEmpty()) {
wrapper.ge(EmrDefect::getReportTime, startDate);
}
if (endDate != null && !endDate.isEmpty()) {
wrapper.le(EmrDefect::getReportTime, endDate);
}
long totalDefects = defectMapper.selectCount(wrapper);
LambdaQueryWrapper<EmrDefect> overdueWrapper = new LambdaQueryWrapper<>();
overdueWrapper.eq(EmrDefect::getDelFlag, "0").eq(EmrDefect::getDefectType, "TIMELY");
if (startDate != null && !startDate.isEmpty()) {
overdueWrapper.ge(EmrDefect::getReportTime, startDate);
}
if (endDate != null && !endDate.isEmpty()) {
overdueWrapper.le(EmrDefect::getReportTime, endDate);
}
long overdueEmr = defectMapper.selectCount(overdueWrapper);
LambdaQueryWrapper<QualityScore> scoreWrapper = new LambdaQueryWrapper<>();
scoreWrapper.eq(QualityScore::getDelFlag, "0");
if (startDate != null && !startDate.isEmpty()) {
scoreWrapper.ge(QualityScore::getCreateTime, startDate);
}
if (endDate != null && !endDate.isEmpty()) {
scoreWrapper.le(QualityScore::getCreateTime, endDate);
}
long totalEncounters = scoreMapper.selectCount(scoreWrapper);
long completedEmr = totalEncounters - overdueEmr;
if (completedEmr < 0) completedEmr = 0;
double completionRate = totalEncounters > 0 ? Math.round(completedEmr * 100.0 / totalEncounters) : 100;
Map<String, Object> result = new HashMap<>();
result.put("totalEncounters", 0); result.put("completedEmr", 0); result.put("overdueEmr", 0); result.put("completionRate", 100);
result.put("totalEncounters", totalEncounters);
result.put("completedEmr", completedEmr);
result.put("overdueEmr", overdueEmr);
result.put("completionRate", completionRate);
return result;
}

View File

@@ -26,24 +26,41 @@ public class TerminalQualityAppServiceImpl implements ITerminalQualityAppService
result.put("encounterId", encounterId);
result.put("checkTime", new Date());
// 检查各项指标
List<Map<String, Object>> checks = new ArrayList<>();
String[] items = {"入院记录24h完成", "首次病程8h完成", "日常病程及时", "出院记录完整", "签名完整"};
int passCount = 0;
List<EmrDefect> defects = defectMapper.selectList(
new LambdaQueryWrapper<EmrDefect>()
.eq(EmrDefect::getEncounterId, encounterId)
.eq(EmrDefect::getDelFlag, "0")
.orderByDesc(EmrDefect::getReportTime)
);
Set<String> defectTypes = new HashSet<>();
for (EmrDefect d : defects) {
if (d.getDefectType() != null) defectTypes.add(d.getDefectType());
}
boolean hasCritical = defects.stream().anyMatch(d -> "CRITICAL".equals(d.getSeverity()));
boolean hasPending = defects.stream().anyMatch(d -> "PENDING".equals(d.getRectifyStatus()));
for (String item : items) {
Map<String, Object> check = new HashMap<>();
check.put("item", item);
check.put("result", "PASS");
boolean passed = true;
if ("入院记录24h完成".equals(item) && defectTypes.contains("TIMELY")) passed = false;
if ("首次病程8h完成".equals(item) && defectTypes.contains("TIMELY")) passed = false;
if ("日常病程及时".equals(item) && defectTypes.contains("TIMELY")) passed = false;
if ("出院记录完整".equals(item) && (defectTypes.contains("COMPLETENESS") || hasCritical)) passed = false;
if ("签名完整".equals(item) && defectTypes.contains("SIGNATURE")) passed = false;
check.put("result", passed ? "PASS" : "FAIL");
checks.add(check);
passCount++;
if (passed) passCount++;
}
// 计算总分
BigDecimal score = new BigDecimal(passCount * 20);
String grade = calculateGrade(score);
// 保存评分记录
QualityScore qualityScore = new QualityScore();
qualityScore.setEncounterId(encounterId);
qualityScore.setScore(score);