feat(kg): 推理引擎+CDSS集成

This commit is contained in:
2026-06-19 10:34:43 +08:00
parent ed1dd56ad4
commit 179d8c9c97
8 changed files with 247 additions and 0 deletions

View File

@@ -0,0 +1,15 @@
package com.healthlink.his.web.knowledgegraph.dto;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class DiagnosisResultDto {
private String diseaseCode;
private String diseaseName;
private String category;
private String department;
private BigDecimal score;
private String matchedSymptoms;
}

View File

@@ -0,0 +1,13 @@
package com.healthlink.his.web.knowledgegraph.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import java.util.List;
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class DiagnosisSuggestDto {
private List<String> symptoms;
private Integer topN = 5;
}

View File

@@ -0,0 +1,12 @@
package com.healthlink.his.web.knowledgegraph.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import java.util.List;
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class DrugInteractionDto {
private List<String> drugCodes;
}

View File

@@ -0,0 +1,14 @@
package com.healthlink.his.web.knowledgegraph.dto;
import lombok.Data;
@Data
public class DrugInteractionResultDto {
private String drugCodeA;
private String drugNameA;
private String drugCodeB;
private String drugNameB;
private String interactionType;
private String description;
private String severity;
}

View File

@@ -0,0 +1,14 @@
package com.healthlink.his.web.knowledgegraph.dto;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class ExaminationResultDto {
private String examCode;
private String examName;
private String examType;
private String clinicalSignificance;
private BigDecimal score;
}

View File

@@ -0,0 +1,11 @@
package com.healthlink.his.web.knowledgegraph.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class ExaminationSuggestDto {
private String diseaseCode;
private Integer topN = 10;
}

View File

@@ -0,0 +1,84 @@
<template>
<div class="app-container">
<el-card shadow="never">
<template #header>
<span>诊断推荐</span>
</template>
<el-form :model="form" label-width="80px">
<el-form-item label="症状">
<el-select v-model="form.symptoms" multiple filterable allow-create default-first-option placeholder="输入症状后回车" style="width: 100%">
<el-option v-for="item in symptomOptions" :key="item" :label="item" :value="item" />
</el-select>
</el-form-item>
<el-form-item label="推荐数量">
<el-input-number v-model="form.topN" :min="1" :max="20" />
</el-form-item>
<el-form-item>
<el-button type="primary" :loading="loading" @click="handleSuggest">查询推荐</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card shadow="never" class="mt16" v-if="results.length > 0">
<template #header>
<span>推荐结果 {{ results.length }} </span>
</template>
<el-table :data="results" border stripe>
<el-table-column type="index" label="排名" width="60" align="center" />
<el-table-column prop="diseaseCode" label="疾病编码" width="140" show-overflow-tooltip />
<el-table-column prop="diseaseName" label="疾病名称" min-width="160" show-overflow-tooltip />
<el-table-column prop="category" label="分类" width="120" show-overflow-tooltip />
<el-table-column prop="department" label="科室" width="120" show-overflow-tooltip />
<el-table-column prop="score" label="匹配度" width="100" align="center">
<template #default="{ row }">
<el-tag :type="row.score >= 2 ? 'danger' : row.score >= 1 ? 'warning' : 'info'">
{{ row.score }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="matchedSymptoms" label="匹配症状" min-width="200" show-overflow-tooltip />
</el-table>
</el-card>
</div>
</template>
<script setup name="DiagnosisSuggest">
import { ref, reactive } from 'vue'
import { suggestDiagnosis } from '@/api/knowledgegraph/api'
import { ElMessage } from 'element-plus'
const loading = ref(false)
const results = ref([])
const form = reactive({
symptoms: [],
topN: 5
})
const symptomOptions = ref([])
async function handleSuggest() {
if (form.symptoms.length === 0) {
ElMessage.warning('请输入至少一个症状')
return
}
loading.value = true
try {
const res = await suggestDiagnosis(form)
if (res.code === 200) {
results.value = res.data || []
if (results.value.length === 0) {
ElMessage.info('未找到匹配的诊断')
}
} else {
ElMessage.error(res.msg || '查询失败')
}
} finally {
loading.value = false
}
}
</script>
<style scoped>
.mt16 { margin-top: 16px; }
</style>

View File

@@ -0,0 +1,84 @@
<template>
<div class="app-container">
<el-card shadow="never">
<template #header>
<span>药物相互作用检查</span>
</template>
<el-form :model="form" label-width="80px">
<el-form-item label="药物">
<el-select v-model="form.drugCodes" multiple filterable allow-create default-first-option placeholder="输入药物编码后回车" style="width: 100%">
<el-option v-for="item in drugOptions" :key="item" :label="item" :value="item" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" :loading="loading" @click="handleCheck">检查相互作用</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card shadow="never" class="mt16" v-if="results.length > 0">
<template #header>
<span>检查结果发现 {{ results.length }} 个相互作用</span>
</template>
<el-table :data="results" border stripe>
<el-table-column prop="drugNameA" label="药物A" min-width="140" show-overflow-tooltip />
<el-table-column prop="drugCodeA" label="编码A" width="120" show-overflow-tooltip />
<el-table-column prop="drugNameB" label="药物B" min-width="140" show-overflow-tooltip />
<el-table-column prop="drugCodeB" label="编码B" width="120" show-overflow-tooltip />
<el-table-column prop="interactionType" label="相互作用类型" width="140" show-overflow-tooltip />
<el-table-column prop="severity" label="严重程度" width="100" align="center">
<template #default="{ row }">
<el-tag :type="row.severity === '严重' ? 'danger' : 'warning'">
{{ row.severity }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="description" label="描述" min-width="200" show-overflow-tooltip />
</el-table>
</el-card>
<el-card shadow="never" class="mt16" v-if="checked && results.length === 0">
<el-empty description="未发现药物相互作用" />
</el-card>
</div>
</template>
<script setup name="DrugInteractionCheck">
import { ref, reactive } from 'vue'
import { checkDrugInteractions } from '@/api/knowledgegraph/api'
import { ElMessage } from 'element-plus'
const loading = ref(false)
const results = ref([])
const checked = ref(false)
const form = reactive({
drugCodes: []
})
const drugOptions = ref([])
async function handleCheck() {
if (form.drugCodes.length < 2) {
ElMessage.warning('请至少输入两种药物')
return
}
loading.value = true
checked.value = false
try {
const res = await checkDrugInteractions(form)
if (res.code === 200) {
results.value = res.data || []
checked.value = true
} else {
ElMessage.error(res.msg || '检查失败')
}
} finally {
loading.value = false
}
}
</script>
<style scoped>
.mt16 { margin-top: 16px; }
</style>