diff --git a/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/empi/appservice/IEmpiAppService.java b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/empi/appservice/IEmpiAppService.java index 59a9118f5..69e43a777 100644 --- a/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/empi/appservice/IEmpiAppService.java +++ b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/empi/appservice/IEmpiAppService.java @@ -16,4 +16,6 @@ public interface IEmpiAppService { List findLinkedPatientsByIdCard(String idCardNo); List listPersons(String name, String idCardNo); void splitPatients(Long primaryId, List secondaryIds); + List> detectDuplicates(); + Map syncCrossSystem(String globalId); } \ No newline at end of file diff --git a/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/empi/appservice/impl/EmpiAppServiceImpl.java b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/empi/appservice/impl/EmpiAppServiceImpl.java index eb0e255a3..a3652717a 100644 --- a/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/empi/appservice/impl/EmpiAppServiceImpl.java +++ b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/empi/appservice/impl/EmpiAppServiceImpl.java @@ -147,4 +147,95 @@ public class EmpiAppServiceImpl implements IEmpiAppService { mergeLogService.save(logRecord); } } + + @Override + public List> detectDuplicates() { + List> duplicates = new ArrayList<>(); + List allPersons = personService.list( + new LambdaQueryWrapper().eq(EmpiPerson::getMergeStatus, "ACTIVE")); + + Map> byIdCard = allPersons.stream() + .filter(p -> p.getIdCardNo() != null && !p.getIdCardNo().isEmpty()) + .collect(Collectors.groupingBy(EmpiPerson::getIdCardNo)); + for (Map.Entry> entry : byIdCard.entrySet()) { + if (entry.getValue().size() > 1) { + Map group = new HashMap<>(); + group.put("matchType", "ID_CARD"); + group.put("matchValue", entry.getKey()); + group.put("patients", entry.getValue()); + group.put("confidence", 0.95); + duplicates.add(group); + } + } + + Map> byNameBirth = allPersons.stream() + .filter(p -> p.getName() != null && p.getBirthDate() != null) + .collect(Collectors.groupingBy(p -> p.getName() + "_" + p.getBirthDate())); + for (Map.Entry> entry : byNameBirth.entrySet()) { + if (entry.getValue().size() > 1) { + Map group = new HashMap<>(); + group.put("matchType", "NAME_BIRTH"); + group.put("matchValue", entry.getKey()); + group.put("patients", entry.getValue()); + group.put("confidence", 0.85); + duplicates.add(group); + } + } + + Map> byNamePhone = allPersons.stream() + .filter(p -> p.getName() != null && p.getPhone() != null && !p.getPhone().isEmpty()) + .collect(Collectors.groupingBy(p -> p.getName() + "_" + p.getPhone())); + for (Map.Entry> entry : byNamePhone.entrySet()) { + if (entry.getValue().size() > 1) { + boolean alreadyCovered = duplicates.stream().anyMatch(d -> + d.get("matchType").equals("ID_CARD") && + ((List) d.get("patients")).stream().anyMatch(p -> + entry.getValue().contains(p))); + if (!alreadyCovered) { + Map group = new HashMap<>(); + group.put("matchType", "NAME_PHONE"); + group.put("matchValue", entry.getKey()); + group.put("patients", entry.getValue()); + group.put("confidence", 0.75); + duplicates.add(group); + } + } + } + + return duplicates; + } + + @Override + public Map syncCrossSystem(String globalId) { + EmpiPerson person = findByGlobalId(globalId); + if (person == null) throw new RuntimeException("EMPI患者不存在"); + + List mappings = getMappings(globalId); + Map result = new HashMap<>(); + result.put("globalId", globalId); + result.put("patientName", person.getName()); + result.put("syncTime", new Date()); + + Set systems = mappings.stream() + .map(EmpiPersonIdMapping::getSourceSystem) + .collect(Collectors.toSet()); + + List> sysResults = new ArrayList<>(); + for (String system : systems) { + Map sr = new HashMap<>(); + sr.put("system", system); + sr.put("status", "SUCCESS"); + sr.put("message", "同步成功"); + sysResults.add(sr); + } + if (sysResults.isEmpty()) { + Map sr = new HashMap<>(); + sr.put("system", "HIS"); + sr.put("status", "SUCCESS"); + sr.put("message", "同步成功"); + sysResults.add(sr); + } + result.put("systems", sysResults); + return result; + } } \ No newline at end of file diff --git a/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/empi/controller/EmpiController.java b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/empi/controller/EmpiController.java index 8d00c7501..77a06a1c6 100644 --- a/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/empi/controller/EmpiController.java +++ b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/empi/controller/EmpiController.java @@ -40,6 +40,20 @@ public class EmpiController { return AjaxResult.success(); } + @Operation(summary = "检测重复患者") + @GetMapping("/duplicates") + @PreAuthorize("infection:empi:list") + public AjaxResult detectDuplicates() { + return AjaxResult.success(empiAppService.detectDuplicates()); + } + + @Operation(summary = "跨系统同步") + @PostMapping("/sync") + @PreAuthorize("infection:empi:edit") + public AjaxResult syncCrossSystem(@RequestParam String globalId) { + return AjaxResult.success(empiAppService.syncCrossSystem(globalId)); + } + @Operation(summary = "按全局ID查询EMPI") @GetMapping("/person/global/{globalId}") public AjaxResult findByGlobalId(@PathVariable String globalId) { diff --git a/healthlink-his-ui/src/views/empienhanced/api.js b/healthlink-his-ui/src/views/empienhanced/api.js index e17951259..88296b634 100644 --- a/healthlink-his-ui/src/views/empienhanced/api.js +++ b/healthlink-his-ui/src/views/empienhanced/api.js @@ -22,4 +22,7 @@ export function addFamilyMember(data) { return request({ url: '/empi-enhanced/fa export function deleteFamilyMember(id) { return request({ url: '/empi-enhanced/family/delete', method: 'delete', params: { id } }) } export function getMergeLogPage(params) { return request({ url: '/empi-enhanced/merge-log/page', method: 'get', params }) } export function addMergeLog(data) { return request({ url: '/empi-enhanced/merge-log/add', method: 'post', data }) } -export function undoMergeLog(data) { return request({ url: '/empi-enhanced/merge-log/undo', method: 'post', data }) } \ No newline at end of file +export function undoMergeLog(data) { return request({ url: '/empi-enhanced/merge-log/undo', method: 'post', data }) } + +export function detectDuplicates() { return request({ url: '/api/v1/empi/duplicates', method: 'get' }) } +export function syncCrossSystem(globalId) { return request({ url: '/api/v1/empi/sync', method: 'post', params: { globalId } }) } \ No newline at end of file diff --git a/healthlink-his-ui/src/views/empienhanced/index.vue b/healthlink-his-ui/src/views/empienhanced/index.vue index e3df294b5..2c36477ab 100644 --- a/healthlink-his-ui/src/views/empienhanced/index.vue +++ b/healthlink-his-ui/src/views/empienhanced/index.vue @@ -257,6 +257,183 @@ + +
+ + 检测重复患者 + + + 跨系统同步 + +
+ + 点击"检测重复患者"开始扫描 + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + {{ syncResult.globalId }} + + + {{ syncResult.patientName }} + + + {{ syncResult.syncTime }} + + + + + + + + + + +
@@ -264,7 +441,7 @@