feat(V39): 危急值管理增强 — 前端重构+DB修复+4/4 API通过
前端增强: - CriticalValue pending页面: Tab切换(待确认/超时列表) - 统计卡片: 待确认/已确认/已关闭/超时未确认 - 操作流程: 上报→确认接收→处理→关闭完整闭环 - API文件: 7个接口封装 数据库修复: - critical_value: 添加delete_flag/create_by/update_by/update_time列 - 放宽encounter_id/lab_result_id/patient_id NOT NULL约束 后端修复: - CriticalValue实体: 移除冗余delFlag,使用HisBaseEntity.deleteFlag - CriticalValueAppServiceImpl: delFlag→deleteFlag迁移 测试: 4/4 API全部通过(上报/待确认列表/统计/超时列表)
This commit is contained in:
@@ -13,7 +13,7 @@ public class CriticalValueAppServiceImpl implements ICriticalValueAppService {
|
||||
@Override
|
||||
public CriticalValue reportCriticalValue(CriticalValue cv) {
|
||||
cv.setStatus("PENDING");
|
||||
cv.setDelFlag("0");
|
||||
cv.setDeleteFlag("0");
|
||||
cv.setReportTime(new Date());
|
||||
criticalValueService.save(cv);
|
||||
return cv;
|
||||
@@ -47,7 +47,7 @@ public class CriticalValueAppServiceImpl implements ICriticalValueAppService {
|
||||
@Override
|
||||
public List<CriticalValue> getPendingList() {
|
||||
return criticalValueService.list(new LambdaQueryWrapper<CriticalValue>()
|
||||
.eq(CriticalValue::getStatus, "PENDING").eq(CriticalValue::getDelFlag, "0")
|
||||
.eq(CriticalValue::getStatus, "PENDING").eq(CriticalValue::getDeleteFlag, "0")
|
||||
.orderByDesc(CriticalValue::getReportTime));
|
||||
}
|
||||
@Override
|
||||
@@ -56,14 +56,14 @@ public class CriticalValueAppServiceImpl implements ICriticalValueAppService {
|
||||
return criticalValueService.list(new LambdaQueryWrapper<CriticalValue>()
|
||||
.in(CriticalValue::getStatus, "PENDING", "RECEIVED")
|
||||
.lt(CriticalValue::getReportTime, threshold)
|
||||
.eq(CriticalValue::getDelFlag, "0"));
|
||||
.eq(CriticalValue::getDeleteFlag, "0"));
|
||||
}
|
||||
@Override
|
||||
public Map<String, Object> getStatistics(String startDate, String endDate) {
|
||||
long total = criticalValueService.count(new LambdaQueryWrapper<CriticalValue>()
|
||||
.eq(CriticalValue::getDelFlag, "0"));
|
||||
.eq(CriticalValue::getDeleteFlag, "0"));
|
||||
long closed = criticalValueService.count(new LambdaQueryWrapper<CriticalValue>()
|
||||
.eq(CriticalValue::getStatus, "CLOSED").eq(CriticalValue::getDelFlag, "0"));
|
||||
.eq(CriticalValue::getStatus, "CLOSED").eq(CriticalValue::getDeleteFlag, "0"));
|
||||
long overdue = getOverdueList().size();
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("total", total);
|
||||
|
||||
@@ -35,5 +35,4 @@ public class CriticalValue extends HisBaseEntity {
|
||||
private String handleResult;
|
||||
private Date closeTime;
|
||||
private String status;
|
||||
private String delFlag;
|
||||
}
|
||||
|
||||
9
healthlink-his-ui/src/views/criticalvalue/api.js
Normal file
9
healthlink-his-ui/src/views/criticalvalue/api.js
Normal file
@@ -0,0 +1,9 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function reportCriticalValue(data) { return request({ url: '/healthlink-his/api/v1/critical-value/report', method: 'post', data }) }
|
||||
export function confirmCriticalValue(id, params) { return request({ url: '/healthlink-his/api/v1/critical-value/confirm/' + id, method: 'put', params }) }
|
||||
export function processCriticalValue(id, params) { return request({ url: '/healthlink-his/api/v1/critical-value/process/' + id, method: 'put', params }) }
|
||||
export function closeCriticalValue(id) { return request({ url: '/healthlink-his/api/v1/critical-value/close/' + id, method: 'put' }) }
|
||||
export function getPendingList() { return request({ url: '/healthlink-his/api/v1/critical-value/pending', method: 'get' }) }
|
||||
export function getOverdueList() { return request({ url: '/healthlink-his/api/v1/critical-value/overdue', method: 'get' }) }
|
||||
export function getStatistics(params) { return request({ url: '/healthlink-his/api/v1/critical-value/statistics', method: 'get', params }) }
|
||||
@@ -1,31 +1,84 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-row :gutter="20" class="mb8">
|
||||
<el-col :span="6"><el-card shadow="hover"><el-statistic title="待确认" :value="stats.total || 0" /></el-card></el-col>
|
||||
<el-col :span="6"><el-card shadow="hover"><el-statistic title="已关闭" :value="stats.closed || 0" /></el-card></el-col>
|
||||
<el-col :span="6"><el-card shadow="hover"><el-statistic title="超时" :value="stats.overdue || 0" /></el-card></el-col>
|
||||
<el-col :span="6"><el-card shadow="hover"><el-statistic title="确认率" :value="stats.confirmRate || 0" suffix="%" /></el-card></el-col>
|
||||
<el-col :span="6"><el-card shadow="hover"><el-statistic title="待确认" :value="stats.pendingCount || 0" /></el-card></el-col>
|
||||
<el-col :span="6"><el-card shadow="hover"><el-statistic title="已确认" :value="stats.confirmedCount || 0" /></el-card></el-col>
|
||||
<el-col :span="6"><el-card shadow="hover"><el-statistic title="已关闭" :value="stats.closedCount || 0" /></el-card></el-col>
|
||||
<el-col :span="6"><el-card shadow="hover"><el-statistic title="超时未确认" :value="stats.overdueCount || 0" /></el-card></el-col>
|
||||
</el-row>
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="患者" prop="patientName" width="100" />
|
||||
<el-table-column label="项目" prop="itemName" width="120" />
|
||||
<el-table-column label="结果" prop="resultValue" width="100" />
|
||||
<el-table-column label="参考范围" prop="referenceRange" width="100" />
|
||||
<el-table-column label="报告时间" prop="reportTime" width="170" />
|
||||
<el-table-column label="状态" prop="status" width="100">
|
||||
<template #default="s"><el-tag :type="s.row.status==='PENDING'?'danger':'success'">{{ {PENDING:'待确认',RECEIVED:'已确认',PROCESSING:'处理中',CLOSED:'已关闭'}[s.row.status] }}</el-tag></template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="120">
|
||||
<template #default="s"><el-button link type="primary" v-if="s.row.status==='PENDING'" @click="handleConfirm(s.row)">确认</el-button></template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-tabs v-model="activeTab" @tab-change="handleTabChange">
|
||||
<el-tab-pane label="待确认" name="pending">
|
||||
<el-table v-loading="loading" :data="pendingList">
|
||||
<el-table-column label="患者" prop="patientName" width="100" />
|
||||
<el-table-column label="检验项目" prop="itemName" width="120" />
|
||||
<el-table-column label="结果" prop="resultValue" width="100">
|
||||
<template #default="s"><el-text type="danger">{{ s.row.resultValue }}</el-text></template>
|
||||
</el-table-column>
|
||||
<el-table-column label="参考范围" prop="referenceRange" width="100" />
|
||||
<el-table-column label="报告时间" prop="reportTime" width="170" />
|
||||
<el-table-column label="上报人" prop="reporterName" width="100" />
|
||||
<el-table-column label="状态" prop="status" width="90">
|
||||
<template #default="s"><el-tag :type="statusType(s.row.status)">{{ statusText(s.row.status) }}</el-tag></template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="150" fixed="right">
|
||||
<template #default="s">
|
||||
<el-button link type="primary" v-if="s.row.status==='PENDING'" @click="handleConfirm(s.row)">确认接收</el-button>
|
||||
<el-button link type="warning" v-if="s.row.status==='RECEIVED'" @click="handleProcess(s.row)">处理</el-button>
|
||||
<el-button link type="success" v-if="s.row.status==='PROCESSING'" @click="handleClose(s.row)">关闭</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="超时列表" name="overdue">
|
||||
<el-table v-loading="loading" :data="overdueList">
|
||||
<el-table-column label="患者" prop="patientName" width="100" />
|
||||
<el-table-column label="检验项目" prop="itemName" width="120" />
|
||||
<el-table-column label="结果" prop="resultValue" width="100" />
|
||||
<el-table-column label="报告时间" prop="reportTime" width="170" />
|
||||
<el-table-column label="超时时长" prop="overdueHours" width="100">
|
||||
<template #default="s"><el-tag type="danger">{{ s.row.overdueHours }}h</el-tag></template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'; import { getPendingList, confirmValue, getStatistics } from '@/api/criticalvalue'; import { ElMessage } from 'element-plus'
|
||||
const loading = ref(false); const list = ref([]); const stats = ref({})
|
||||
const getList = async () => { loading.value = true; const r = await getPendingList(); list.value = r.data || []; loading.value = false }
|
||||
const loadStats = async () => { const r = await getStatistics(); stats.value = r.data || {} }
|
||||
const handleConfirm = async (row) => { await confirmValue(row.id, { receiverId: 1, receiverName: '当前用户' }); ElMessage.success('已确认'); getList(); loadStats() }
|
||||
onMounted(() => { getList(); loadStats() })
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { getPendingList, getOverdueList, confirmCriticalValue, processCriticalValue, closeCriticalValue, getStatistics } from '../api'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
|
||||
const activeTab = ref('pending')
|
||||
const loading = ref(false)
|
||||
const pendingList = ref([])
|
||||
const overdueList = ref([])
|
||||
const stats = ref({})
|
||||
|
||||
const statusType = (s) => ({ PENDING: 'danger', RECEIVED: 'warning', PROCESSING: 'primary', CLOSED: 'success' }[s] || 'info')
|
||||
const statusText = (s) => ({ PENDING: '待确认', RECEIVED: '已确认', PROCESSING: '处理中', CLOSED: '已关闭' }[s] || s)
|
||||
|
||||
const loadPending = async () => { loading.value = true; const res = await getPendingList(); pendingList.value = res.data || []; loading.value = false }
|
||||
const loadOverdue = async () => { loading.value = true; const res = await getOverdueList(); overdueList.value = res.data || []; loading.value = false }
|
||||
const loadStats = async () => { const res = await getStatistics(); stats.value = res.data || {} }
|
||||
const handleTabChange = () => { activeTab.value === 'pending' ? loadPending() : loadOverdue() }
|
||||
|
||||
const handleConfirm = async (row) => {
|
||||
await ElMessageBox.confirm('确认接收此危急值?', '确认', { type: 'warning' })
|
||||
await confirmCriticalValue(row.id, { receiverId: 1, receiverName: '当前用户' })
|
||||
ElMessage.success('已确认接收'); loadPending(); loadStats()
|
||||
}
|
||||
const handleProcess = async (row) => {
|
||||
await ElMessageBox.prompt('请输入处理结果', '处理危急值', { type: 'info' })
|
||||
.then(async ({ value }) => {
|
||||
await processCriticalValue(row.id, { handlerId: 1, handlerName: '当前用户', result: value || '已处理' })
|
||||
ElMessage.success('处理完成'); loadPending(); loadStats()
|
||||
})
|
||||
}
|
||||
const handleClose = async (row) => {
|
||||
await ElMessageBox.confirm('确认关闭此危急值?', '关闭', { type: 'success' })
|
||||
await closeCriticalValue(row.id); ElMessage.success('已关闭'); loadPending(); loadStats()
|
||||
}
|
||||
|
||||
onMounted(() => { loadPending(); loadStats() })
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user