feat(emr): 打通EMR管理模块与门诊/住院病历集成

- 修复revision-history API路径与后端对齐
- EMR管理页面支持URL参数自动加载
- 医生工作站添加修订历史/完整性检查入口
- 住院医生工作站添加修订历史/完整性检查入口
This commit is contained in:
2026-06-21 06:17:50 +08:00
parent b965d80b12
commit f4493cf74b
8 changed files with 142 additions and 11 deletions

View File

@@ -30,6 +30,22 @@
>
历史病历
</el-button>
<el-button
type="info"
plain
style="margin-left: 20px"
@click="viewRevisionHistory()"
>
修订历史
</el-button>
<el-button
type="info"
plain
style="margin-left: 20px"
@click="checkCompleteness()"
>
完整性检查
</el-button>
<!-- 可选添加打印按钮 -->
<!-- <el-button type="primary" plain @click="printEmr" style="margin-left: 20px">
打印病历
@@ -196,10 +212,13 @@
import {getEmrDetail, saveEmr, saveEmrTemplate} from '../api';
import emrTemplate from '../emr/emrtemplate.vue';
import emrhistory from '../emr/emrhistory.vue';
import {checkCompleteness as checkEmrCompleteness} from '@/api/emr';
import {useRouter} from 'vue-router';
import {computed, getCurrentInstance, ref, watch} from 'vue';
import {formatDate as formatDateUtil} from '@/utils/index';
const router = useRouter();
// Props
const props = defineProps({
patientInfo: {
@@ -320,6 +339,37 @@ function handleSaveTemplate() {
openEmrTemplate.value = true;
}
// 查看修订历史
function viewRevisionHistory() {
if (!props.patientInfo?.encounterId) {
proxy.$message.warning('请先选择患者');
return;
}
router.push({
path: '/emr/revision-history',
query: { emrId: props.patientInfo.encounterId }
});
}
// 完整性检查
async function checkCompleteness() {
if (!props.patientInfo?.encounterId) {
proxy.$message.warning('请先选择患者');
return;
}
try {
const res = await checkEmrCompleteness(props.patientInfo.encounterId, props.patientInfo.encounterId);
const data = res.data || res;
if (data.isComplete) {
proxy.$modal.msgSuccess('病历完整性检查通过');
} else {
proxy.$message.warning(`病历完整性检查未通过,${data.requiredFailed}项必填项未填写`);
}
} catch (e) {
proxy.$message.error('检查失败');
}
}
// 选择模板/历史
function templateSelect(row) {
form.value = { ...row };

View File

@@ -226,13 +226,19 @@
</template>
<script setup>
import {ref,onMounted} from 'vue'
import {useRoute} from 'vue-router'
import {ElMessage,ElMessageBox} from 'element-plus'
import {getArchivePage,archive,reprint,getArchiveStats} from './api'
const route=useRoute()
const tableData=ref([]);const total=ref(0);const stats=ref({})
const q=ref({pageNo:1,pageSize:20,patientName:'',archiveStatus:''})
const loadData=async()=>{const r=await getArchivePage(q.value);tableData.value=r.data?.records||[];total.value=r.data?.total||0}
const loadStats=async()=>{const r=await getArchiveStats();stats.value=r.data||{}}
const doArchive=async(row)=>{const {value}=await ElMessageBox.prompt('归档人','确认归档');if(value){await archive(row.id,value);ElMessage.success('已归档');loadData();loadStats()}}
const doReprint=async(row)=>{await reprint(row.id);ElMessage.success('补打记录已添加');loadData()}
onMounted(()=>{loadData();loadStats()})
onMounted(()=>{
if(route.query.encounterId){q.value.encounterId=route.query.encounterId}
if(route.query.patientName){q.value.patientName=route.query.patientName}
loadData();loadStats()
})
</script>

View File

@@ -90,10 +90,12 @@
</template>
<script setup>
import { ref, reactive, computed } from 'vue'
import { ref, reactive, computed, onMounted } from 'vue'
import { useRoute } from 'vue-router'
import { checkCompleteness, getCompletenessResults } from '@/api/emr'
import { ElMessage } from 'element-plus'
const route = useRoute()
const checkLoading = ref(false)
const resultLoading = ref(false)
const checkResult = ref(null)
@@ -148,6 +150,12 @@ const loadResults = async () => {
resultLoading.value = false
}
}
onMounted(() => {
if (route.query.emrId) { checkForm.emrId = route.query.emrId }
if (route.query.encounterId) { checkForm.encounterId = route.query.encounterId }
if (checkForm.emrId && checkForm.encounterId) { handleCheck() }
})
</script>
<style scoped>

View File

@@ -1,5 +1,5 @@
import request from '@/utils/request'
export function getRevisionPage(p){return request({url:'/emr-revision/page',method:'get',params:p})}
export function getRevisionList(p){return request({url:'/emr-revision/list',method:'get',params:p})}
export function recordRevision(d){return request({url:'/emr-revision/record',method:'post',data:d})}
export function compareRevisions(id1,id2){return request({url:'/emr-revision/compare',method:'get',params:{revisionId1:id1,revisionId2:id2}})}
export function getRevisionPage(p){return request({url:'/emr/revision/page',method:'get',params:p})}
export function getRevisionList(emrId){return request({url:'/emr/revision/list/'+emrId,method:'get'})}
export function recordRevision(d){return request({url:'/emr/revision/record',method:'post',data:d})}
export function compareRevisions(id1,id2){return request({url:'/emr/revision/compare',method:'get',params:{revisionId1:id1,revisionId2:id2}})}

View File

@@ -129,11 +129,16 @@
</template>
<script setup>
import {ref,onMounted} from 'vue'
import {useRoute} from 'vue-router'
import {getRevisionPage} from './api'
const route=useRoute()
const tableData=ref([]);const total=ref(0)
const q=ref({pageNo:1,pageSize:20,emrId:'',operatorName:''})
const detailVisible=ref(false);const detail=ref({})
const loadData=async()=>{const r=await getRevisionPage(q.value);tableData.value=r.data?.records||[];total.value=r.data?.total||0}
const viewDetail=(row)=>{detail.value=row;detailVisible.value=true}
onMounted(()=>loadData())
onMounted(()=>{
if(route.query.emrId){q.value.emrId=route.query.emrId}
loadData()
})
</script>

View File

@@ -132,14 +132,20 @@
<script setup>
import { ref, reactive, onMounted } from 'vue'
import { useRoute } from 'vue-router'
import { getTimelinessByEncounter, getOverdueList, getTimelinessStatistics } from '@/api/emr'
const route = useRoute()
const loading = ref(false)
const dataList = ref([])
const stats = reactive({ pending: 0, completed: 0, overdue: 0, rate: 0 })
const queryParams = reactive({ departmentName: '', emrType: '' })
const queryParams = reactive({ departmentName: '', emrType: '', encounterId: '' })
const emrTypeMap = { ADMISSION: '入院记录', FIRST_COURSE: '首次病程', DAILY_COURSE: '日常病程', DISCHARGE: '出院记录' }
const statusMap = { PENDING: { label: '待完成', type: 'info' }, COMPLETED: { label: '已完成', type: 'success' }, OVERDUE: { label: '超时', type: 'danger' } }
const getList = async () => { loading.value = true; const res = await getOverdueList(); dataList.value = res.data || res.rows || []; loading.value = false }
const handleQuery = () => getList()
onMounted(() => { getList() })
onMounted(() => {
if (route.query.encounterId) { queryParams.encounterId = route.query.encounterId }
if (route.query.departmentName) { queryParams.departmentName = route.query.departmentName }
getList()
})
</script>

View File

@@ -120,8 +120,10 @@
<script setup>
import {ref,reactive,onMounted} from 'vue'
import {useRoute} from 'vue-router'
import {searchEmr} from './api'
const route=useRoute()
const loading=ref(false)
const searchData=ref([])
const total=ref(0)
@@ -132,5 +134,10 @@ const handleSearch=async()=>{
try{const r=await searchEmr(queryParams);searchData.value=r.data?.records||[];total.value=r.data?.total||0}finally{loading.value=false}
}
const resetQuery=()=>{Object.assign(queryParams,{keyword:'',patientName:'',emrType:'',doctorName:'',pageNo:1});handleSearch()}
onMounted(()=>handleSearch())
onMounted(()=>{
if(route.query.patientName){queryParams.patientName=route.query.patientName}
if(route.query.emrType){queryParams.emrType=route.query.emrType}
if(route.query.keyword){queryParams.keyword=route.query.keyword}
handleSearch()
})
</script>

View File

@@ -78,6 +78,20 @@
>
打印表单
</el-button>
<el-button
type="info"
plain
@click="viewRevisionHistory"
>
修订历史
</el-button>
<el-button
type="info"
plain
@click="checkCompleteness"
>
完整性检查
</el-button>
<!-- <el-button type="primary" @click="" disabled>病案上传</el-button>
<el-button type="primary" @click="">结算上传</el-button> -->
<!-- <el-button type="primary" @click="onNursingStatus">护理状态</el-button> -->
@@ -923,6 +937,41 @@ const onPrint = () => {
}
};
// 查看修订历史
import {useRouter} from 'vue-router';
import {checkCompleteness as checkEmrCompleteness} from '@/api/emr';
const router = useRouter();
const viewRevisionHistory = () => {
if (!patientInfo.value?.encounterId) {
ElMessage.warning('请先选择患者');
return;
}
router.push({
path: '/emr/revision-history',
query: { emrId: patientInfo.value.encounterId }
});
};
// 完整性检查
const checkCompleteness = async () => {
if (!patientInfo.value?.encounterId) {
ElMessage.warning('请先选择患者');
return;
}
try {
const res = await checkEmrCompleteness(patientInfo.value.encounterId, patientInfo.value.encounterId);
const data = res.data || res;
if (data.isComplete) {
ElMessage.success('病历完整性检查通过');
} else {
ElMessage.warning(`病历完整性检查未通过,${data.requiredFailed}项必填项未填写`);
}
} catch (e) {
ElMessage.error('检查失败');
}
};
// 添加一个方法供父组件调用,处理患者切换
const handlePatientChange = (patient) => {
// 更新患者信息