feat(kg): 关系管理+知识图谱可视化

This commit is contained in:
2026-06-19 08:06:38 +08:00
parent deafee0621
commit be90a13cd6
23 changed files with 508 additions and 10 deletions

View File

@@ -0,0 +1,18 @@
package com.healthlink.his.web.clinical.appservice;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.healthlink.his.clinical.domain.KgClinicalPathway;
import com.healthlink.his.clinical.domain.KgEntityRelation;
import com.healthlink.his.clinical.domain.KgPathwayStep;
import java.util.List;
import java.util.Map;
public interface IKgRelationAppService {
void createRelation(KgEntityRelation relation);
IPage<KgEntityRelation> pageRelations(String sourceType, String targetType, String relationType, Integer pageNo, Integer pageSize);
Map<String, Object> getRelationGraph(String entityType, String entityId);
void createPathway(KgClinicalPathway pathway, List<KgPathwayStep> steps);
IPage<KgClinicalPathway> pagePathways(String keyword, Integer pageNo, Integer pageSize);
List<KgPathwayStep> getPathwaySteps(Long pathwayId);
}

View File

@@ -0,0 +1,146 @@
package com.healthlink.his.web.clinical.appservice.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.healthlink.his.clinical.domain.KgClinicalPathway;
import com.healthlink.his.clinical.domain.KgEntityRelation;
import com.healthlink.his.clinical.domain.KgPathwayStep;
import com.healthlink.his.clinical.service.IKgClinicalPathwayService;
import com.healthlink.his.clinical.service.IKgEntityRelationService;
import com.healthlink.his.clinical.service.IKgPathwayStepService;
import com.healthlink.his.web.clinical.appservice.IKgRelationAppService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
@Service
public class KgRelationAppServiceImpl implements IKgRelationAppService {
@Autowired
private IKgEntityRelationService relationService;
@Autowired
private IKgClinicalPathwayService pathwayService;
@Autowired
private IKgPathwayStepService stepService;
@Override
@Transactional(rollbackFor = Exception.class)
public void createRelation(KgEntityRelation relation) {
if (relation.getRelationStrength() == null) {
relation.setRelationStrength(BigDecimal.ONE);
}
relation.setCreateTime(new Date());
relationService.save(relation);
}
@Override
public IPage<KgEntityRelation> pageRelations(String sourceType, String targetType, String relationType, Integer pageNo, Integer pageSize) {
LambdaQueryWrapper<KgEntityRelation> w = new LambdaQueryWrapper<>();
w.eq(StringUtils.hasText(sourceType), KgEntityRelation::getSourceType, sourceType)
.eq(StringUtils.hasText(targetType), KgEntityRelation::getTargetType, targetType)
.eq(StringUtils.hasText(relationType), KgEntityRelation::getRelationType, relationType)
.orderByDesc(KgEntityRelation::getCreateTime);
return relationService.page(new Page<>(pageNo, pageSize), w);
}
@Override
public Map<String, Object> getRelationGraph(String entityType, String entityId) {
Set<String> nodeKeys = new LinkedHashSet<>();
List<Map<String, Object>> nodes = new ArrayList<>();
List<Map<String, Object>> edges = new ArrayList<>();
// Find all relations where this entity is source or target
LambdaQueryWrapper<KgEntityRelation> w1 = new LambdaQueryWrapper<>();
w1.eq(KgEntityRelation::getSourceType, entityType)
.eq(KgEntityRelation::getSourceId, entityId);
List<KgEntityRelation> outgoing = relationService.list(w1);
LambdaQueryWrapper<KgEntityRelation> w2 = new LambdaQueryWrapper<>();
w2.eq(KgEntityRelation::getTargetType, entityType)
.eq(KgEntityRelation::getTargetId, entityId);
List<KgEntityRelation> incoming = relationService.list(w2);
List<KgEntityRelation> all = new ArrayList<>();
all.addAll(outgoing);
all.addAll(incoming);
for (KgEntityRelation rel : all) {
String srcKey = rel.getSourceType() + ":" + rel.getSourceId();
String tgtKey = rel.getTargetType() + ":" + rel.getTargetId();
if (nodeKeys.add(srcKey)) {
nodes.add(buildNode(srcKey, rel.getSourceType(), rel.getSourceId()));
}
if (nodeKeys.add(tgtKey)) {
nodes.add(buildNode(tgtKey, rel.getTargetType(), rel.getTargetId()));
}
Map<String, Object> edge = new LinkedHashMap<>();
edge.put("source", srcKey);
edge.put("target", tgtKey);
edge.put("relationType", rel.getRelationType());
edge.put("relationStrength", rel.getRelationStrength());
edge.put("description", rel.getDescription());
edges.add(edge);
}
Map<String, Object> result = new LinkedHashMap<>();
result.put("nodes", nodes);
result.put("edges", edges);
return result;
}
private Map<String, Object> buildNode(String key, String type, String id) {
Map<String, Object> node = new LinkedHashMap<>();
node.put("id", key);
node.put("entityType", type);
node.put("entityId", id);
return node;
}
@Override
@Transactional(rollbackFor = Exception.class)
public void createPathway(KgClinicalPathway pathway, List<KgPathwayStep> steps) {
pathway.setStatus("ACTIVE");
pathway.setCreateTime(new Date());
pathwayService.save(pathway);
if (steps != null) {
for (int i = 0; i < steps.size(); i++) {
KgPathwayStep step = steps.get(i);
step.setPathwayId(pathway.getId());
step.setStepOrder(i + 1);
step.setCreateTime(new Date());
}
stepService.saveBatch(steps);
}
}
@Override
public IPage<KgClinicalPathway> pagePathways(String keyword, Integer pageNo, Integer pageSize) {
LambdaQueryWrapper<KgClinicalPathway> w = new LambdaQueryWrapper<>();
w.eq(KgClinicalPathway::getStatus, "ACTIVE")
.and(StringUtils.hasText(keyword), q -> q
.like(KgClinicalPathway::getPathwayName, keyword)
.or().like(KgClinicalPathway::getDiseaseName, keyword)
.or().like(KgClinicalPathway::getPathwayCode, keyword))
.orderByDesc(KgClinicalPathway::getCreateTime);
return pathwayService.page(new Page<>(pageNo, pageSize), w);
}
@Override
public List<KgPathwayStep> getPathwaySteps(Long pathwayId) {
LambdaQueryWrapper<KgPathwayStep> w = new LambdaQueryWrapper<>();
w.eq(KgPathwayStep::getPathwayId, pathwayId)
.orderByAsc(KgPathwayStep::getStepOrder);
return stepService.list(w);
}
}

View File

@@ -0,0 +1,79 @@
package com.healthlink.his.web.clinical.controller;
import com.core.common.core.domain.AjaxResult;
import com.core.common.core.domain.R;
import com.healthlink.his.clinical.domain.KgClinicalPathway;
import com.healthlink.his.clinical.domain.KgEntityRelation;
import com.healthlink.his.clinical.domain.KgPathwayStep;
import com.healthlink.his.web.clinical.appservice.IKgRelationAppService;
import com.healthlink.his.web.clinical.dto.KgPathwayDto;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Tag(name = "知识图谱管理")
@RestController
@RequestMapping("/knowledgegraph")
@Slf4j
@AllArgsConstructor
public class KgRelationController {
private final IKgRelationAppService kgRelationAppService;
@Operation(summary = "创建关系")
@PreAuthorize("@ss.hasPermi('system:knowledgegraph:edit')")
@PostMapping("/relation")
public AjaxResult createRelation(@RequestBody KgEntityRelation relation) {
kgRelationAppService.createRelation(relation);
return AjaxResult.success();
}
@Operation(summary = "关系分页查询")
@PreAuthorize("@ss.hasPermi('system:knowledgegraph:list')")
@GetMapping("/relation/page")
public R<?> pageRelations(
@RequestParam(value = "sourceType", required = false) String sourceType,
@RequestParam(value = "targetType", required = false) String targetType,
@RequestParam(value = "relationType", required = false) String relationType,
@RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(value = "pageSize", defaultValue = "20") Integer pageSize) {
return R.ok(kgRelationAppService.pageRelations(sourceType, targetType, relationType, pageNo, pageSize));
}
@Operation(summary = "查询实体关系图")
@PreAuthorize("@ss.hasPermi('system:knowledgegraph:list')")
@GetMapping("/relation/graph/{entityType}/{entityId}")
public R<?> getRelationGraph(@PathVariable String entityType, @PathVariable String entityId) {
return R.ok(kgRelationAppService.getRelationGraph(entityType, entityId));
}
@Operation(summary = "创建临床路径")
@PreAuthorize("@ss.hasPermi('system:knowledgegraph:edit')")
@PostMapping("/pathway")
public AjaxResult createPathway(@RequestBody KgPathwayDto dto) {
kgRelationAppService.createPathway(dto.getPathway(), dto.getSteps());
return AjaxResult.success();
}
@Operation(summary = "路径分页查询")
@PreAuthorize("@ss.hasPermi('system:knowledgegraph:list')")
@GetMapping("/pathway/page")
public R<?> pagePathways(
@RequestParam(value = "keyword", required = false) String keyword,
@RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(value = "pageSize", defaultValue = "20") Integer pageSize) {
return R.ok(kgRelationAppService.pagePathways(keyword, pageNo, pageSize));
}
@Operation(summary = "查询路径步骤")
@PreAuthorize("@ss.hasPermi('system:knowledgegraph:list')")
@GetMapping("/pathway/{id}/steps")
public R<?> getPathwaySteps(@PathVariable Long id) {
return R.ok(kgRelationAppService.getPathwaySteps(id));
}
}

View File

@@ -0,0 +1,13 @@
package com.healthlink.his.web.clinical.dto;
import com.healthlink.his.clinical.domain.KgClinicalPathway;
import com.healthlink.his.clinical.domain.KgPathwayStep;
import lombok.Data;
import java.util.List;
@Data
public class KgPathwayDto {
private KgClinicalPathway pathway;
private List<KgPathwayStep> steps;
}

View File

@@ -0,0 +1,28 @@
package com.healthlink.his.common.enums;
import com.baomidou.mybatisplus.annotation.EnumValue;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public enum KgEntityType implements HisEnumInterface {
DISEASE(1, "disease", "疾病"),
SYMPTOM(2, "symptom", "症状"),
DRUG(3, "drug", "药物"),
EXAM(4, "exam", "检查");
@EnumValue
private final Integer value;
private final String code;
private final String info;
public static KgEntityType getByCode(String code) {
if (code == null) return null;
for (KgEntityType e : values()) {
if (e.getCode().equals(code)) return e;
}
return null;
}
}

View File

@@ -0,0 +1,32 @@
package com.healthlink.his.common.enums;
import com.baomidou.mybatisplus.annotation.EnumValue;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public enum KgRelationType implements HisEnumInterface {
CAUSES(1, "CAUSES", "导致"),
TREATS(2, "TREATS", "治疗"),
CONTRAINDICATES(3, "CONTRAINDICATES", "禁忌"),
INTERACTS_WITH(4, "INTERACTS_WITH", "相互作用"),
REQUIRES_EXAM(5, "REQUIRES_EXAM", "需要检查"),
HAS_SYMPTOM(6, "HAS_SYMPTOM", "具有症状"),
SIDE_EFFECT(7, "SIDE_EFFECT", "副作用"),
ALTERNATIVE(8, "ALTERNATIVE", "替代");
@EnumValue
private final Integer value;
private final String code;
private final String info;
public static KgRelationType getByCode(String code) {
if (code == null) return null;
for (KgRelationType e : values()) {
if (e.getCode().equals(code)) return e;
}
return null;
}
}

View File

@@ -0,0 +1,22 @@
package com.healthlink.his.clinical.domain;
import com.baomidou.mybatisplus.annotation.*;
import com.core.common.core.domain.HisBaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("kg_clinical_pathway")
public class KgClinicalPathway extends HisBaseEntity {
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
@TableField("pathway_code") private String pathwayCode;
@TableField("pathway_name") private String pathwayName;
@TableField("disease_code") private String diseaseCode;
@TableField("disease_name") private String diseaseName;
@TableField("department") private String department;
@TableField("standard_days") private Integer standardDays;
@TableField("description") private String description;
@TableField("status") private String status;
}

View File

@@ -0,0 +1,24 @@
package com.healthlink.his.clinical.domain;
import com.baomidou.mybatisplus.annotation.*;
import com.core.common.core.domain.HisBaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.math.BigDecimal;
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("kg_entity_relation")
public class KgEntityRelation extends HisBaseEntity {
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
@TableField("source_type") private String sourceType;
@TableField("source_id") private String sourceId;
@TableField("target_type") private String targetType;
@TableField("target_id") private String targetId;
@TableField("relation_type") private String relationType;
@TableField("relation_strength") private BigDecimal relationStrength;
@TableField("description") private String description;
@TableField("evidence_source") private String evidenceSource;
}

View File

@@ -0,0 +1,20 @@
package com.healthlink.his.clinical.domain;
import com.baomidou.mybatisplus.annotation.*;
import com.core.common.core.domain.HisBaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("kg_pathway_step")
public class KgPathwayStep extends HisBaseEntity {
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
@TableField("pathway_id") private Long pathwayId;
@TableField("step_order") private Integer stepOrder;
@TableField("day_number") private Integer dayNumber;
@TableField("step_type") private String stepType;
@TableField("step_content") private String stepContent;
@TableField("required") private String required;
}

View File

@@ -0,0 +1,9 @@
package com.healthlink.his.clinical.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.healthlink.his.clinical.domain.KgClinicalPathway;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface KgClinicalPathwayMapper extends BaseMapper<KgClinicalPathway> {
}

View File

@@ -0,0 +1,9 @@
package com.healthlink.his.clinical.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.healthlink.his.clinical.domain.KgEntityRelation;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface KgEntityRelationMapper extends BaseMapper<KgEntityRelation> {
}

View File

@@ -0,0 +1,9 @@
package com.healthlink.his.clinical.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.healthlink.his.clinical.domain.KgPathwayStep;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface KgPathwayStepMapper extends BaseMapper<KgPathwayStep> {
}

View File

@@ -0,0 +1,7 @@
package com.healthlink.his.clinical.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.healthlink.his.clinical.domain.KgClinicalPathway;
public interface IKgClinicalPathwayService extends IService<KgClinicalPathway> {
}

View File

@@ -0,0 +1,7 @@
package com.healthlink.his.clinical.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.healthlink.his.clinical.domain.KgEntityRelation;
public interface IKgEntityRelationService extends IService<KgEntityRelation> {
}

View File

@@ -0,0 +1,7 @@
package com.healthlink.his.clinical.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.healthlink.his.clinical.domain.KgPathwayStep;
public interface IKgPathwayStepService extends IService<KgPathwayStep> {
}

View File

@@ -0,0 +1,11 @@
package com.healthlink.his.clinical.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.healthlink.his.clinical.domain.KgClinicalPathway;
import com.healthlink.his.clinical.mapper.KgClinicalPathwayMapper;
import com.healthlink.his.clinical.service.IKgClinicalPathwayService;
import org.springframework.stereotype.Service;
@Service
public class KgClinicalPathwayServiceImpl extends ServiceImpl<KgClinicalPathwayMapper, KgClinicalPathway> implements IKgClinicalPathwayService {
}

View File

@@ -0,0 +1,11 @@
package com.healthlink.his.clinical.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.healthlink.his.clinical.domain.KgEntityRelation;
import com.healthlink.his.clinical.mapper.KgEntityRelationMapper;
import com.healthlink.his.clinical.service.IKgEntityRelationService;
import org.springframework.stereotype.Service;
@Service
public class KgEntityRelationServiceImpl extends ServiceImpl<KgEntityRelationMapper, KgEntityRelation> implements IKgEntityRelationService {
}

View File

@@ -0,0 +1,11 @@
package com.healthlink.his.clinical.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.healthlink.his.clinical.domain.KgPathwayStep;
import com.healthlink.his.clinical.mapper.KgPathwayStepMapper;
import com.healthlink.his.clinical.service.IKgPathwayStepService;
import org.springframework.stereotype.Service;
@Service
public class KgPathwayStepServiceImpl extends ServiceImpl<KgPathwayStepMapper, KgPathwayStep> implements IKgPathwayStepService {
}

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.healthlink.his.clinical.mapper.KgClinicalPathwayMapper">
</mapper>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.healthlink.his.clinical.mapper.KgEntityRelationMapper">
</mapper>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.healthlink.his.clinical.mapper.KgPathwayStepMapper">
</mapper>

View File

@@ -1,5 +1,5 @@
<template>
<el-dialog v-model="visible" title="新增临床路径" width="750px" append-to-body @close="handleClose">
<el-dialog v-model="dialogVisible" title="新增临床路径" width="750px" append-to-body @close="handleClose">
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
<el-form-item label="路径编码" prop="pathwayCode">
<el-input v-model="form.pathwayCode" placeholder="如: CP-DM-001" />
@@ -13,6 +13,9 @@
<el-form-item label="疾病名称">
<el-input v-model="form.diseaseName" placeholder="疾病名称" />
</el-form-item>
<el-form-item label="所属科室">
<el-input v-model="form.department" placeholder="请输入所属科室" />
</el-form-item>
<el-form-item label="标准天数">
<el-input-number v-model="form.standardDays" :min="1" :max="365" />
</el-form-item>
@@ -37,7 +40,7 @@
<span style="color:#999;cursor:grab;width:20px;text-align:center"></span>
<el-tag size="small" type="info">{{ idx + 1 }}</el-tag>
<el-select v-model="step.dayNumber" placeholder="天" style="width:80px" size="small">
<el-option v-for="d in 30" :key="d" :label="`第${d}天`" :value="d" />
<el-option v-for="d in 30" :key="d" :label="'第'+d+'天'" :value="d" />
</el-select>
<el-select v-model="step.stepType" placeholder="类型" style="width:100px" size="small">
<el-option label="检查" value="exam" />
@@ -46,6 +49,7 @@
<el-option label="用药" value="medication" />
</el-select>
<el-input v-model="step.stepContent" placeholder="步骤内容" size="small" style="flex:1" />
<el-switch v-model="step.required" active-value="1" inactive-value="0" size="small" active-text="必选" inactive-text="可选" style="margin-left:4px" />
<el-button link type="danger" @click="removeStep(idx)" size="small">删除</el-button>
</div>
<el-empty v-if="!steps.length" description="点击上方添加步骤" :image-size="60" />
@@ -66,14 +70,18 @@ import { createPathway } from '@/api/knowledgegraph/api'
const props = defineProps({ visible: Boolean })
const emit = defineEmits(['update:visible', 'success'])
const dialogVisible = ref(false)
const formRef = ref(null)
const submitting = ref(false)
const steps = ref([])
let dragIdx = -1
watch(() => props.visible, (v) => { dialogVisible.value = v })
watch(dialogVisible, (v) => { emit('update:visible', v) })
const defaultForm = () => ({
pathwayCode: '', pathwayName: '', diseaseCode: '',
diseaseName: '', standardDays: 7, description: ''
diseaseName: '', department: '', standardDays: 7, description: ''
})
const form = ref(defaultForm())
@@ -86,10 +94,12 @@ watch(() => props.visible, (v) => {
if (v) { form.value = defaultForm(); steps.value = [] }
})
function handleClose() { emit('update:visible', false) }
function handleClose() {
dialogVisible.value = false
}
function addStep() {
steps.value.push({ dayNumber: 1, stepType: 'exam', stepContent: '' })
steps.value.push({ dayNumber: 1, stepType: 'exam', stepContent: '', required: '1' })
}
function removeStep(idx) {
@@ -111,7 +121,7 @@ async function handleSubmit() {
try {
await createPathway({ pathway: form.value, steps: steps.value })
ElMessage.success('创建成功')
emit('update:visible', false)
handleClose()
emit('success')
} finally {
submitting.value = false

View File

@@ -1,5 +1,5 @@
<template>
<el-dialog v-model="visible" title="新增实体关系" width="600px" append-to-body @close="handleClose">
<el-dialog v-model="dialogVisible" title="新增实体关系" width="600px" append-to-body @close="handleClose">
<el-form ref="formRef" :model="form" :rules="rules" label-width="110px">
<el-form-item label="源实体类型" prop="sourceType">
<el-select v-model="form.sourceType" placeholder="请选择" style="width:100%">
@@ -28,6 +28,9 @@
<el-form-item label="描述">
<el-input v-model="form.description" type="textarea" :rows="3" placeholder="关系描述" />
</el-form-item>
<el-form-item label="证据来源">
<el-input v-model="form.evidenceSource" placeholder="证据来源" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="handleClose">取消</el-button>
@@ -44,9 +47,13 @@ import { createRelation } from '@/api/knowledgegraph/api'
const props = defineProps({ visible: Boolean })
const emit = defineEmits(['update:visible', 'success'])
const dialogVisible = ref(false)
const formRef = ref(null)
const submitting = ref(false)
watch(() => props.visible, (v) => { dialogVisible.value = v })
watch(dialogVisible, (v) => { emit('update:visible', v) })
const entityTypes = [
{ code: 'disease', name: '疾病' },
{ code: 'symptom', name: '症状' },
@@ -67,7 +74,7 @@ const relationTypes = [
const defaultForm = () => ({
sourceType: '', sourceId: '', targetType: '', targetId: '',
relationType: '', relationStrength: 1.0, description: ''
relationType: '', relationStrength: 1.0, description: '', evidenceSource: ''
})
const form = ref(defaultForm())
@@ -84,7 +91,7 @@ watch(() => props.visible, (v) => {
})
function handleClose() {
emit('update:visible', false)
dialogVisible.value = false
}
async function handleSubmit() {
@@ -93,7 +100,7 @@ async function handleSubmit() {
try {
await createRelation(form.value)
ElMessage.success('创建成功')
emit('update:visible', false)
handleClose()
emit('success')
} finally {
submitting.value = false