feat(cdss): CDSS临床决策支持系统
This commit is contained in:
115
healthlink-his-ui/src/views/infection/cdss/CdssAlerts.vue
Normal file
115
healthlink-his-ui/src/views/infection/cdss/CdssAlerts.vue
Normal file
@@ -0,0 +1,115 @@
|
||||
<template>
|
||||
<div class="cdss-alerts-container">
|
||||
<div class="page-header">
|
||||
<span class="tab-title">CDSS告警列表</span>
|
||||
</div>
|
||||
|
||||
<el-card shadow="never" style="margin-bottom: 16px">
|
||||
<template #header>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center">
|
||||
<span>告警记录</span>
|
||||
<div style="display: flex; gap: 8px">
|
||||
<el-input v-model="encounterId" placeholder="就诊ID" style="width: 140px" />
|
||||
<el-button type="primary" @click="loadAlerts" :loading="loading">查询</el-button>
|
||||
<el-button type="warning" @click="handleEvaluate" :loading="evaluating">执行评估</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<el-table :data="alerts" v-loading="loading" border stripe style="width: 100%">
|
||||
<el-table-column prop="alertType" label="告警类型" width="120" />
|
||||
<el-table-column prop="severity" label="严重程度" width="100" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="severityType(row.severity)" size="small" effect="dark">
|
||||
{{ row.severity }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="alertMessage" label="告警信息" min-width="300" show-overflow-tooltip />
|
||||
<el-table-column prop="acknowledged" label="状态" width="90" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.acknowledged ? 'success' : 'danger'" size="small">
|
||||
{{ row.acknowledged ? '已确认' : '待确认' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="acknowledgedTime" label="确认时间" width="170" />
|
||||
<el-table-column prop="createTime" label="产生时间" width="170" />
|
||||
<el-table-column label="操作" width="100" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button v-if="!row.acknowledged" link type="primary" @click="handleAcknowledge(row)">
|
||||
确认
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { getAlerts, acknowledgeAlert, evaluateRules } from './api'
|
||||
|
||||
const loading = ref(false)
|
||||
const evaluating = ref(false)
|
||||
const alerts = ref([])
|
||||
const encounterId = ref('')
|
||||
|
||||
const severityType = (severity) => {
|
||||
const map = { CRITICAL: 'danger', HIGH: 'warning', MEDIUM: '', LOW: 'info', INFO: 'info' }
|
||||
return map[severity] || ''
|
||||
}
|
||||
|
||||
const loadAlerts = async () => {
|
||||
if (!encounterId.value) {
|
||||
ElMessage.warning('请输入就诊ID')
|
||||
return
|
||||
}
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await getAlerts(encounterId.value)
|
||||
alerts.value = res.data || []
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const handleEvaluate = async () => {
|
||||
if (!encounterId.value) {
|
||||
ElMessage.warning('请输入就诊ID')
|
||||
return
|
||||
}
|
||||
evaluating.value = true
|
||||
try {
|
||||
const res = await evaluateRules(encounterId.value)
|
||||
ElMessage.success('评估完成,生成 ' + (res.data?.newAlertCount || 0) + ' 条告警')
|
||||
loadAlerts()
|
||||
} catch (e) {
|
||||
ElMessage.error('评估失败: ' + (e.message || '未知错误'))
|
||||
} finally {
|
||||
evaluating.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const handleAcknowledge = async (row) => {
|
||||
try {
|
||||
await acknowledgeAlert(row.id)
|
||||
ElMessage.success('已确认')
|
||||
loadAlerts()
|
||||
} catch (e) {
|
||||
ElMessage.error('确认失败')
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (encounterId.value) loadAlerts()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.cdss-alerts-container { padding: 16px; }
|
||||
.page-header { margin-bottom: 16px; }
|
||||
.tab-title { font-size: 18px; font-weight: bold; }
|
||||
</style>
|
||||
97
healthlink-his-ui/src/views/infection/cdss/CdssRules.vue
Normal file
97
healthlink-his-ui/src/views/infection/cdss/CdssRules.vue
Normal file
@@ -0,0 +1,97 @@
|
||||
<template>
|
||||
<div class="cdss-rules-container">
|
||||
<div class="page-header">
|
||||
<span class="tab-title">CDSS规则管理</span>
|
||||
</div>
|
||||
|
||||
<el-card shadow="never">
|
||||
<template #header>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center">
|
||||
<span>规则列表</span>
|
||||
<div style="display: flex; gap: 8px">
|
||||
<el-select v-model="filterType" placeholder="规则类型" clearable style="width: 130px" @change="loadRules">
|
||||
<el-option label="药物审查" value="DRUG_REVIEW" />
|
||||
<el-option label="诊断提示" value="DIAGNOSIS" />
|
||||
<el-option label="检验预警" value="LAB_ALERT" />
|
||||
<el-option label="用药禁忌" value="CONTRAINDICATION" />
|
||||
</el-select>
|
||||
<el-select v-model="filterSeverity" placeholder="严重程度" clearable style="width: 120px" @change="loadRules">
|
||||
<el-option label="危急" value="CRITICAL" />
|
||||
<el-option label="高" value="HIGH" />
|
||||
<el-option label="中" value="MEDIUM" />
|
||||
<el-option label="低" value="LOW" />
|
||||
<el-option label="提示" value="INFO" />
|
||||
</el-select>
|
||||
<el-input v-model="filterKeyword" placeholder="搜索规则名称" clearable style="width: 180px" @keyup.enter="loadRules" />
|
||||
<el-button type="primary" @click="loadRules">查询</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<el-table :data="rules" v-loading="loading" border stripe style="width: 100%">
|
||||
<el-table-column prop="ruleCode" label="规则编码" width="120" />
|
||||
<el-table-column prop="ruleName" label="规则名称" min-width="180" show-overflow-tooltip />
|
||||
<el-table-column prop="ruleType" label="规则类型" width="110" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag size="small">{{ row.ruleType }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="severity" label="严重程度" width="90" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="severityType(row.severity)" size="small" effect="dark">
|
||||
{{ row.severity }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="conditionExpr" label="条件表达式" min-width="200" show-overflow-tooltip />
|
||||
<el-table-column prop="suggestion" label="建议" min-width="200" show-overflow-tooltip />
|
||||
<el-table-column prop="enabled" label="状态" width="80" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.enabled ? 'success' : 'info'" size="small">
|
||||
{{ row.enabled ? '启用' : '停用' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="createTime" label="创建时间" width="170" />
|
||||
</el-table>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { getRules } from './api'
|
||||
|
||||
const loading = ref(false)
|
||||
const rules = ref([])
|
||||
const filterType = ref('')
|
||||
const filterSeverity = ref('')
|
||||
const filterKeyword = ref('')
|
||||
|
||||
const severityType = (severity) => {
|
||||
const map = { CRITICAL: 'danger', HIGH: 'warning', MEDIUM: '', LOW: 'info', INFO: 'info' }
|
||||
return map[severity] || ''
|
||||
}
|
||||
|
||||
const loadRules = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const params = {}
|
||||
if (filterType.value) params.ruleType = filterType.value
|
||||
if (filterSeverity.value) params.severity = filterSeverity.value
|
||||
if (filterKeyword.value) params.keyword = filterKeyword.value
|
||||
const res = await getRules(params)
|
||||
rules.value = res.data || []
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => loadRules())
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.cdss-rules-container { padding: 16px; }
|
||||
.page-header { margin-bottom: 16px; }
|
||||
.tab-title { font-size: 18px; font-weight: bold; }
|
||||
</style>
|
||||
17
healthlink-his-ui/src/views/infection/cdss/api.js
Normal file
17
healthlink-his-ui/src/views/infection/cdss/api.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function evaluateRules(encounterId) {
|
||||
return request({ url: '/infection/cdss/evaluate', method: 'post', params: { encounterId } })
|
||||
}
|
||||
|
||||
export function getAlerts(encounterId) {
|
||||
return request({ url: '/infection/cdss/alerts/' + encounterId, method: 'get' })
|
||||
}
|
||||
|
||||
export function acknowledgeAlert(alertId) {
|
||||
return request({ url: '/infection/cdss/alerts/' + alertId + '/acknowledge', method: 'post' })
|
||||
}
|
||||
|
||||
export function getRules(params) {
|
||||
return request({ url: '/infection/cdss/rules', method: 'get', params })
|
||||
}
|
||||
Reference in New Issue
Block a user