|
|
|
@ -1,5 +1,7 @@
|
|
|
|
|
package com.supervision.service.impl;
|
|
|
|
|
|
|
|
|
|
import cn.hutool.core.bean.BeanUtil;
|
|
|
|
|
import cn.hutool.core.collection.CollUtil;
|
|
|
|
|
import cn.hutool.core.date.DateUtil;
|
|
|
|
|
import cn.hutool.core.lang.Assert;
|
|
|
|
|
import cn.hutool.core.util.NumberUtil;
|
|
|
|
@ -7,20 +9,26 @@ import cn.hutool.core.util.ObjectUtil;
|
|
|
|
|
import cn.hutool.core.util.StrUtil;
|
|
|
|
|
import com.supervision.dao.*;
|
|
|
|
|
import com.supervision.domain.*;
|
|
|
|
|
import com.supervision.enums.TagEnum;
|
|
|
|
|
import com.supervision.exception.BusinessException;
|
|
|
|
|
import com.supervision.model.Process;
|
|
|
|
|
import com.supervision.model.*;
|
|
|
|
|
import com.supervision.service.*;
|
|
|
|
|
import com.supervision.vo.EdgeVO;
|
|
|
|
|
import com.supervision.vo.GraphVO;
|
|
|
|
|
import com.supervision.vo.NodeVO;
|
|
|
|
|
import com.supervision.vo.TreeNodeVO;
|
|
|
|
|
import lombok.RequiredArgsConstructor;
|
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
import org.nebula.contrib.ngbatis.models.data.NgEdge;
|
|
|
|
|
import org.nebula.contrib.ngbatis.models.data.NgSubgraph;
|
|
|
|
|
import org.nebula.contrib.ngbatis.models.data.NgVertex;
|
|
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
|
|
|
|
import javax.annotation.Resource;
|
|
|
|
|
import java.util.HashMap;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
import java.util.Optional;
|
|
|
|
|
import java.util.*;
|
|
|
|
|
import java.util.function.Function;
|
|
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
|
|
@Slf4j
|
|
|
|
|
@Service
|
|
|
|
@ -78,21 +86,21 @@ public class GraphNebulaServiceImpl implements GraphNebulaService {
|
|
|
|
|
|
|
|
|
|
// 首先创建一个病历
|
|
|
|
|
MedicalRecVertex medicalRecVertex = new MedicalRecVertex();
|
|
|
|
|
medicalRecVertex.setName((disposalMethod == 0 ? "门诊" : "住院") + "(" + DateUtil.format(process.getCreateTime(), "yyyy-MM-dd") + ")");
|
|
|
|
|
medicalRecVertex.setNodeValue((disposalMethod == 0 ? "门诊" : "住院") + "(" + DateUtil.format(process.getCreateTime(), "yyyy-MM-dd") + ")");
|
|
|
|
|
medicalRecDao.insert(medicalRecVertex);
|
|
|
|
|
log.info("病历图谱ID:{}", medicalRecVertex.getId());
|
|
|
|
|
// 根据processId找到电子病历
|
|
|
|
|
ProcessMedical processMedical = processMedicalService.lambdaQuery().eq(ProcessMedical::getProcessId, processId).oneOpt().orElseThrow(() -> new BusinessException("未找到电子病历"));
|
|
|
|
|
|
|
|
|
|
ProcessMedicalVertex processMedicalVertex = new ProcessMedicalVertex();
|
|
|
|
|
processMedicalVertex.setName("病历(" + DateUtil.format(processMedical.getCreateTime(), "yyyy-MM-dd") + ")");
|
|
|
|
|
processMedicalVertex.setNodeValue("病历(" + DateUtil.format(processMedical.getCreateTime(), "yyyy-MM-dd") + ")");
|
|
|
|
|
processMedicalDao.insert(processMedicalVertex);
|
|
|
|
|
|
|
|
|
|
medicalRecDao.insertEdge(medicalRecVertex, new NoPropertyEdge(), processMedicalVertex);
|
|
|
|
|
// 创建主诉节点
|
|
|
|
|
if (StrUtil.isNotBlank(processMedical.getPatientSelfDesc())) {
|
|
|
|
|
SelfDescVertex selfDescVertex = new SelfDescVertex();
|
|
|
|
|
selfDescVertex.setName("主诉:" + processMedical.getPatientSelfDesc());
|
|
|
|
|
selfDescVertex.setNodeValue(processMedical.getPatientSelfDesc());
|
|
|
|
|
selfDescDao.insert(selfDescVertex);
|
|
|
|
|
// 保存节点之间的关系
|
|
|
|
|
processMedicalDao.insertEdge(processMedicalVertex, new NoPropertyEdge(), selfDescVertex);
|
|
|
|
@ -100,7 +108,7 @@ public class GraphNebulaServiceImpl implements GraphNebulaService {
|
|
|
|
|
// 创建现病史节点
|
|
|
|
|
if (StrUtil.isNotBlank(processMedical.getIllnessHistory())) {
|
|
|
|
|
IllnessHistoryVertex illnessHistoryVertex = new IllnessHistoryVertex();
|
|
|
|
|
illnessHistoryVertex.setName("现病史:" + processMedical.getIllnessHistory());
|
|
|
|
|
illnessHistoryVertex.setNodeValue(processMedical.getIllnessHistory());
|
|
|
|
|
illnessHistoryDao.insert(illnessHistoryVertex);
|
|
|
|
|
// 保存节点之间的关系
|
|
|
|
|
processMedicalDao.insertEdge(processMedicalVertex, new NoPropertyEdge(), illnessHistoryVertex);
|
|
|
|
@ -108,7 +116,7 @@ public class GraphNebulaServiceImpl implements GraphNebulaService {
|
|
|
|
|
// 创建个人史节点
|
|
|
|
|
if (StrUtil.isNotBlank(processMedical.getPersonalHistory())) {
|
|
|
|
|
PersonalHistoryVertex personalHistoryVertex = new PersonalHistoryVertex();
|
|
|
|
|
personalHistoryVertex.setName("个人史:" + processMedical.getPersonalHistory());
|
|
|
|
|
personalHistoryVertex.setNodeValue(processMedical.getPersonalHistory());
|
|
|
|
|
personalHistoryDao.insert(personalHistoryVertex);
|
|
|
|
|
// 保存节点之间的关系
|
|
|
|
|
processMedicalDao.insertEdge(processMedicalVertex, new NoPropertyEdge(), personalHistoryVertex);
|
|
|
|
@ -116,7 +124,7 @@ public class GraphNebulaServiceImpl implements GraphNebulaService {
|
|
|
|
|
// 创建过敏史节点
|
|
|
|
|
if (ObjectUtil.isNotEmpty(processMedical.getAllergyHistoryFlag()) && 1 == processMedical.getAllergyHistoryFlag() && StrUtil.isNotBlank(processMedical.getAllergyHistory())) {
|
|
|
|
|
AllergyHistoryVertex allergyHistoryVertex = new AllergyHistoryVertex();
|
|
|
|
|
allergyHistoryVertex.setName("过敏史:" + processMedical.getAllergyHistory());
|
|
|
|
|
allergyHistoryVertex.setNodeValue(processMedical.getAllergyHistory());
|
|
|
|
|
allergyHistoryDao.insert(allergyHistoryVertex);
|
|
|
|
|
// 保存节点之间的关系
|
|
|
|
|
processMedicalDao.insertEdge(processMedicalVertex, new NoPropertyEdge(), allergyHistoryVertex);
|
|
|
|
@ -124,7 +132,7 @@ public class GraphNebulaServiceImpl implements GraphNebulaService {
|
|
|
|
|
// 创建既往史节点
|
|
|
|
|
if (ObjectUtil.isNotEmpty(processMedical.getPreviousHistoryFlag()) && 1 == processMedical.getPreviousHistoryFlag() && StrUtil.isNotBlank(processMedical.getPreviousHistory())) {
|
|
|
|
|
PreviousHistoryVertex previousHistoryVertex = new PreviousHistoryVertex();
|
|
|
|
|
previousHistoryVertex.setName("既往史:" + processMedical.getPreviousHistory());
|
|
|
|
|
previousHistoryVertex.setNodeValue(processMedical.getPreviousHistory());
|
|
|
|
|
previousHistoryDao.insert(previousHistoryVertex);
|
|
|
|
|
// 保存节点之间的关系
|
|
|
|
|
processMedicalDao.insertEdge(processMedicalVertex, new NoPropertyEdge(), previousHistoryVertex);
|
|
|
|
@ -132,7 +140,7 @@ public class GraphNebulaServiceImpl implements GraphNebulaService {
|
|
|
|
|
// 创建家族史节点
|
|
|
|
|
if (ObjectUtil.isNotEmpty(processMedical.getFamilyHistoryFlag()) && 1 == processMedical.getFamilyHistoryFlag() && StrUtil.isNotBlank(processMedical.getFamilyHistory())) {
|
|
|
|
|
FamilyHistoryVertex familyHistoryVertex = new FamilyHistoryVertex();
|
|
|
|
|
familyHistoryVertex.setName("家族史:" + processMedical.getFamilyHistory());
|
|
|
|
|
familyHistoryVertex.setNodeValue(processMedical.getFamilyHistory());
|
|
|
|
|
familyHistoryDao.insert(familyHistoryVertex);
|
|
|
|
|
// 保存节点之间的关系
|
|
|
|
|
processMedicalDao.insertEdge(processMedicalVertex, new NoPropertyEdge(), familyHistoryVertex);
|
|
|
|
@ -140,7 +148,7 @@ public class GraphNebulaServiceImpl implements GraphNebulaService {
|
|
|
|
|
// 创建手术史节点
|
|
|
|
|
if (ObjectUtil.isNotEmpty(processMedical.getOperationHistory()) && 1 == processMedical.getOperationHistoryFlag() && StrUtil.isNotBlank(processMedical.getOperationHistory())) {
|
|
|
|
|
OperationHistoryVertex operationHistoryVertex = new OperationHistoryVertex();
|
|
|
|
|
operationHistoryVertex.setName("手术史:" + processMedical.getOperationHistory());
|
|
|
|
|
operationHistoryVertex.setNodeValue(processMedical.getOperationHistory());
|
|
|
|
|
operationHistoryDao.insert(operationHistoryVertex);
|
|
|
|
|
// 保存节点之间的关系
|
|
|
|
|
processMedicalDao.insertEdge(processMedicalVertex, new NoPropertyEdge(), operationHistoryVertex);
|
|
|
|
@ -148,7 +156,7 @@ public class GraphNebulaServiceImpl implements GraphNebulaService {
|
|
|
|
|
// 创建患者节点
|
|
|
|
|
MedicalRec medicalRec = Optional.ofNullable(medicalRecService.getById(process.getMedicalRecId())).orElseThrow(() -> new BusinessException("未找到病历"));
|
|
|
|
|
PatientVertex patientVertex = new PatientVertex();
|
|
|
|
|
patientVertex.setName("患者:" + medicalRec.getPatientName());
|
|
|
|
|
patientVertex.setNodeValue(medicalRec.getPatientName());
|
|
|
|
|
patientDao.insert(patientVertex);
|
|
|
|
|
processMedicalDao.insertEdge(medicalRecVertex, new NoPropertyEdge(), patientVertex);
|
|
|
|
|
|
|
|
|
@ -165,7 +173,7 @@ public class GraphNebulaServiceImpl implements GraphNebulaService {
|
|
|
|
|
}
|
|
|
|
|
if (ObjectUtil.isNotEmpty(tool)) {
|
|
|
|
|
PhysicalVertex physicalVertex = new PhysicalVertex();
|
|
|
|
|
physicalVertex.setName("体格检查:" + tool.getToolName() + (location != null ? ("-" + location.getLocationName()) : ""));
|
|
|
|
|
physicalVertex.setNodeValue(tool.getToolName() + (location != null ? ("-" + location.getLocationName()) : ""));
|
|
|
|
|
physicalDao.insert(physicalVertex);
|
|
|
|
|
processMedicalDao.insertEdge(medicalRecVertex, new NoPropertyEdge(), physicalVertex);
|
|
|
|
|
// 如果是证实诊断依据,添加到证实诊断依据里面去
|
|
|
|
@ -183,13 +191,13 @@ public class GraphNebulaServiceImpl implements GraphNebulaService {
|
|
|
|
|
ConfigAncillaryItem configAncillaryItem = configAncillaryItemService.getById(diagnosisAncillaryRecord.getItemId());
|
|
|
|
|
if (ObjectUtil.isNotEmpty(configAncillaryItem)) {
|
|
|
|
|
AncillaryVertex ancillaryVertex = new AncillaryVertex();
|
|
|
|
|
ancillaryVertex.setName("辅助检查:" + configAncillaryItem.getItemName());
|
|
|
|
|
ancillaryVertex.setNodeValue(configAncillaryItem.getItemName());
|
|
|
|
|
ancillaryDao.insert(ancillaryVertex);
|
|
|
|
|
// 保存病历和辅助检查连线
|
|
|
|
|
medicalRecDao.insertEdge(medicalRecVertex, new NoPropertyEdge(), ancillaryVertex);
|
|
|
|
|
// 结果节点
|
|
|
|
|
AncillaryResultVertex ancillaryResultVertex = new AncillaryResultVertex();
|
|
|
|
|
ancillaryResultVertex.setName(diagnosisAncillaryRecord.getResult());
|
|
|
|
|
ancillaryResultVertex.setNodeValue(diagnosisAncillaryRecord.getResult());
|
|
|
|
|
ancillaryResultDao.insert(ancillaryResultVertex);
|
|
|
|
|
// 保存检查结果连线
|
|
|
|
|
ancillaryDao.insertEdge(ancillaryVertex, new SinglePropertyEdge("结果"), ancillaryResultVertex);
|
|
|
|
@ -207,7 +215,7 @@ public class GraphNebulaServiceImpl implements GraphNebulaService {
|
|
|
|
|
Disease disease = diseaseService.getById(diagnosisPrimary.getPrimaryDiagnosisId());
|
|
|
|
|
if (ObjectUtil.isNotEmpty(disease)) {
|
|
|
|
|
DiagnosisVertex diagnosisVertex = new DiagnosisVertex();
|
|
|
|
|
diagnosisVertex.setName("诊断:" + disease.getDiseaseNameAlias());
|
|
|
|
|
diagnosisVertex.setNodeValue(disease.getDiseaseNameAlias());
|
|
|
|
|
diagnosisDao.insert(diagnosisVertex);
|
|
|
|
|
diagnosisDao.insertEdge(medicalRecVertex, new SinglePropertyEdge("诊断"), diagnosisVertex);
|
|
|
|
|
diagnosisMap.put(diagnosisPrimary.getId(), diagnosisVertex);
|
|
|
|
@ -237,10 +245,96 @@ public class GraphNebulaServiceImpl implements GraphNebulaService {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public List<NgSubgraph<String>> queryGraph(String processId) {
|
|
|
|
|
public GraphVO queryGraph(String processId) {
|
|
|
|
|
Process process = Optional.ofNullable(processService.getById(processId)).orElseThrow(() -> new BusinessException("未找到对应的问诊流程"));
|
|
|
|
|
return medicalRecDao.selectSubgraph(process.getGraphId());
|
|
|
|
|
List<NgSubgraph<String>> subgraphList = medicalRecDao.selectSubgraph(process.getGraphId());
|
|
|
|
|
|
|
|
|
|
List<NodeVO> nodeList = new ArrayList<>();
|
|
|
|
|
List<EdgeVO> edgeList = new ArrayList<>();
|
|
|
|
|
for (NgSubgraph<String> subgraph : subgraphList) {
|
|
|
|
|
// 首先构建点
|
|
|
|
|
List<NgVertex<String>> vertexes = subgraph.getVertexes();
|
|
|
|
|
for (NgVertex<String> vertex : vertexes) {
|
|
|
|
|
NodeVO nodeVO = new NodeVO();
|
|
|
|
|
String vid = vertex.getVid();
|
|
|
|
|
nodeVO.setId(vid);
|
|
|
|
|
Map<String, Object> properties = vertex.getProperties();
|
|
|
|
|
for (Map.Entry<String, Object> entry : properties.entrySet()) {
|
|
|
|
|
String key = entry.getKey();
|
|
|
|
|
TagEnum tagEnum = TagEnum.valueOf(key);
|
|
|
|
|
if (ObjectUtil.isNotEmpty(tagEnum)) {
|
|
|
|
|
nodeVO.setNodeType(tagEnum.name());
|
|
|
|
|
nodeVO.setNodeDesc(tagEnum.getType());
|
|
|
|
|
nodeVO.setNodeColour(tagEnum.getColour());
|
|
|
|
|
nodeVO.setNodeLevel(tagEnum.getLevel());
|
|
|
|
|
}
|
|
|
|
|
Object value = entry.getValue();
|
|
|
|
|
if (value instanceof Map) {
|
|
|
|
|
Map<?, ?> map = (Map<?, ?>) value;
|
|
|
|
|
Object nodeValue = map.get("nodeValue");
|
|
|
|
|
if (ObjectUtil.isNotEmpty(nodeValue)) {
|
|
|
|
|
nodeVO.setNodeValue(String.valueOf(nodeValue));
|
|
|
|
|
}
|
|
|
|
|
map.forEach((k, v) -> {
|
|
|
|
|
if (ObjectUtil.isNotEmpty(k)) {
|
|
|
|
|
nodeVO.getParams().put(String.valueOf(k), v);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
nodeList.add(nodeVO);
|
|
|
|
|
}
|
|
|
|
|
// 构建边
|
|
|
|
|
List<NgEdge<String>> edges = subgraph.getEdges();
|
|
|
|
|
for (NgEdge<String> edge : edges) {
|
|
|
|
|
EdgeVO edgeVO = new EdgeVO();
|
|
|
|
|
edgeVO.setSource(edge.getSrcID());
|
|
|
|
|
edgeVO.setTarget(edge.getDstID());
|
|
|
|
|
Map<String, Object> properties = edge.getProperties();
|
|
|
|
|
Object nameObject = properties.get("edgeValue");
|
|
|
|
|
if (ObjectUtil.isNotEmpty(nameObject)) {
|
|
|
|
|
edgeVO.setName(String.valueOf(nameObject));
|
|
|
|
|
}
|
|
|
|
|
edgeVO.setParams(properties);
|
|
|
|
|
edgeList.add(edgeVO);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return new GraphVO(nodeList, edgeList);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public List<TreeNodeVO> queryTreeGraph(String processId) {
|
|
|
|
|
GraphVO graphVO = queryGraph(processId);
|
|
|
|
|
List<TreeNodeVO> treeNodeList = graphVO.getNodes().stream().map(node -> BeanUtil.toBean(node, TreeNodeVO.class)).collect(Collectors.toList());
|
|
|
|
|
// 首先找到第一级节点
|
|
|
|
|
List<TreeNodeVO> firstNodeList = treeNodeList.stream().filter(node -> node.getNodeLevel() == 1).collect(Collectors.toList());
|
|
|
|
|
if (CollUtil.isEmpty(firstNodeList)) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
// treeNodeList转换为map,key为节点ID,value为节点对象
|
|
|
|
|
Map<String, TreeNodeVO> treeNodeMap = treeNodeList.stream().collect(Collectors.toMap(TreeNodeVO::getId, Function.identity()));
|
|
|
|
|
for (TreeNodeVO nodeVO : firstNodeList) {
|
|
|
|
|
recursionBuildTree(nodeVO, treeNodeMap, graphVO.getEdges());
|
|
|
|
|
}
|
|
|
|
|
return firstNodeList;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void recursionBuildTree(TreeNodeVO preNode, Map<String, TreeNodeVO> treeNodeMap, List<EdgeVO> edgeList) {
|
|
|
|
|
// 通过preNode的ID找到所有的子节点
|
|
|
|
|
List<TreeNodeVO> childNode = new ArrayList<>();
|
|
|
|
|
for (EdgeVO edgeVO : edgeList) {
|
|
|
|
|
if (StrUtil.equals(edgeVO.getSource(), preNode.getId())) {
|
|
|
|
|
TreeNodeVO treeNodeVO = treeNodeMap.get(edgeVO.getTarget());
|
|
|
|
|
if (ObjectUtil.isNotEmpty(treeNodeVO)) {
|
|
|
|
|
childNode.add(treeNodeVO);
|
|
|
|
|
}
|
|
|
|
|
;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
preNode.setChildNodeList(childNode);
|
|
|
|
|
for (TreeNodeVO treeNodeVO : childNode) {
|
|
|
|
|
recursionBuildTree(treeNodeVO, treeNodeMap, edgeList);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|