361 lines
10 KiB
Vue
361 lines
10 KiB
Vue
<template>
|
||
<div style="margin-bottom: 15px">
|
||
<el-button type="primary" @click="addEmr()">保存</el-button>
|
||
<el-button type="primary" plain @click="handleEmrTemplate()" style="margin-left: 20px">
|
||
模板
|
||
</el-button>
|
||
<el-button type="primary" plain @click="handleSaveTemplate()" style="margin-left: 20px">
|
||
另存模板
|
||
</el-button>
|
||
<el-button type="primary" plain @click="handleEmrHistory()" style="margin-left: 20px">
|
||
历史病历
|
||
</el-button>
|
||
<!-- 可选:添加打印按钮 -->
|
||
<!-- <el-button type="primary" plain @click="printEmr" style="margin-left: 20px">
|
||
打印病历
|
||
</el-button> -->
|
||
</div>
|
||
|
||
<div
|
||
ref="printArea"
|
||
style="max-height: 650px; overflow-y: auto; overflow-x: hidden; font-family: 'SimSun', '宋体', sans-serif;"
|
||
>
|
||
<!-- 标题 -->
|
||
<div style="text-align: center; font-size: 18px; font-weight: bold; margin-bottom: 10px;">
|
||
{{ visitType === 'FIRST' ? '门诊初诊病历' : '门诊复诊病历' }}
|
||
</div>
|
||
|
||
<!-- 患者基本信息 -->
|
||
<div style="display: flex; flex-wrap: wrap; gap: 10px; padding: 10px 0; border-bottom: 1px solid #ebeef5;">
|
||
<div style="flex: 1; min-width: 120px; font-size: 14px; line-height: 24px;">
|
||
<strong>就诊卡号:</strong> {{ patientInfo.patientId || '' }}
|
||
</div>
|
||
<div style="flex: 1; min-width: 120px; font-size: 14px; line-height: 24px;">
|
||
<strong>姓名:</strong> {{ patientInfo.patientName || '' }}
|
||
</div>
|
||
<div style="flex: 1; min-width: 120px; font-size: 14px; line-height: 24px;">
|
||
<strong>性别:</strong> {{ patientInfo.genderEnum_enumText || '' }}
|
||
</div>
|
||
<div style="flex: 1; min-width: 120px; font-size: 14px; line-height: 24px;">
|
||
<strong>年龄:</strong> {{ patientInfo.age || '' }}
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 就诊信息 -->
|
||
<div style="display: flex; flex-wrap: wrap; gap: 10px; padding: 10px 0; border-bottom: 1px solid #ebeef5;">
|
||
<div style="flex: 1; min-width: 200px; font-size: 14px; line-height: 24px;">
|
||
<strong>就诊日期:</strong> {{ currentVisitDate }}
|
||
</div>
|
||
<div style="flex: 1; min-width: 200px; font-size: 14px; line-height: 24px;">
|
||
<strong>就诊科室:</strong> {{ patientInfo.organizationName || '' }}
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 生命体征 -->
|
||
<div style="display: flex; flex-wrap: wrap; gap: 10px; padding: 10px 0; border-bottom: 1px solid #ebeef5;">
|
||
<div style="flex: 1; min-width: 120px; font-size: 14px; line-height: 24px;">
|
||
<strong>身高:</strong>
|
||
<el-input
|
||
v-model="form.height"
|
||
style="width: 80px; margin-left: 5px;"
|
||
/> cm
|
||
</div>
|
||
<div style="flex: 1; min-width: 120px; font-size: 14px; line-height: 24px;">
|
||
<strong>体重:</strong>
|
||
<el-input
|
||
v-model="form.weight"
|
||
style="width: 80px; margin-left: 5px;"
|
||
/> kg
|
||
</div>
|
||
<div style="flex: 1; min-width: 120px; font-size: 14px; line-height: 24px;">
|
||
<strong>体温:</strong>
|
||
<el-input
|
||
v-model="form.temperature"
|
||
style="width: 80px; margin-left: 5px;"
|
||
:step="0.1"
|
||
/> ℃
|
||
</div>
|
||
<div style="flex: 1; min-width: 120px; font-size: 14px; line-height: 24px;">
|
||
<strong>脉搏:</strong>
|
||
<el-input
|
||
v-model="form.pulse"
|
||
style="width: 80px; margin-left: 5px;"
|
||
/> 次/分
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 主诉 + 发病日期 -->
|
||
<div style="display: flex; flex-wrap: wrap; gap: 10px; padding: 10px 0; border-bottom: 1px solid #ebeef5;">
|
||
<div style="flex: 1; min-width: 300px; font-size: 14px; line-height: 24px;">
|
||
<strong>主诉:</strong>
|
||
<el-input
|
||
v-model="form.chiefComplaint"
|
||
style="width: calc(100% - 50px); margin-left: 5px;"
|
||
/>
|
||
</div>
|
||
<div style="flex: 1; min-width: 120px; font-size: 14px; line-height: 24px;">
|
||
<strong>发病日期:</strong>
|
||
<el-date-picker
|
||
v-model="form.onsetDate"
|
||
type="date"
|
||
style="width: calc(100% - 80px); margin-left: 5px;"
|
||
value-format="YYYY-MM-DD"
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 多行文本字段 -->
|
||
<div v-for="field in textFieldList" :key="field.key" style="padding: 10px 0;">
|
||
<div style="font-size: 14px; margin-bottom: 5px;">
|
||
<strong>{{ field.label }}:</strong>
|
||
</div>
|
||
<el-input
|
||
v-model="form[field.key]"
|
||
type="textarea"
|
||
:rows="4"
|
||
style="width: 100%; font-size: 14px; line-height: 1.5;"
|
||
/>
|
||
</div>
|
||
|
||
<!-- 弹窗 -->
|
||
<el-dialog
|
||
:title="emrTitle"
|
||
v-model="openEmrTemplate"
|
||
:width="showDialog === 'emrHistory' ? '800px' : '600px'"
|
||
append-to-body
|
||
destroy-on-close
|
||
>
|
||
<emrTemplate v-if="showDialog === 'emrTemplate'" @selectRow="templateSelect" />
|
||
<emrhistory v-if="showDialog === 'emrHistory'" @selectRow="emrHistorySelect" />
|
||
<div v-if="showDialog === 'saveTemplate'">
|
||
<span>模板名称:</span>
|
||
<el-input
|
||
v-model="templateName"
|
||
style="width: 260px; margin-top: 10px; margin-right: 20px"
|
||
/>
|
||
<el-radio-group v-model="radio">
|
||
<el-radio-button :label="1">个人</el-radio-button>
|
||
<el-radio-button :label="2">科室</el-radio-button>
|
||
<el-radio-button :label="3">全院</el-radio-button>
|
||
</el-radio-group>
|
||
</div>
|
||
<template #footer>
|
||
<div class="dialog-footer">
|
||
<el-button type="primary" @click="submit">确 定</el-button>
|
||
<el-button @click="cancel">取 消</el-button>
|
||
</div>
|
||
</template>
|
||
</el-dialog>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { saveEmr, getEmrDetail, saveEmrTemplate } from '../api';
|
||
import emrTemplate from '../emr/emrtemplate.vue';
|
||
import emrhistory from '../emr/emrhistory.vue';
|
||
|
||
import { ref, computed, watch, getCurrentInstance } from 'vue';
|
||
import { formatDate as formatDateUtil } from '@/utils/index';
|
||
|
||
// Props
|
||
const props = defineProps({
|
||
patientInfo: {
|
||
type: Object,
|
||
required: true,
|
||
},
|
||
visitType: {
|
||
type: String,
|
||
default: '',
|
||
},
|
||
firstVisitDate: {
|
||
type: String,
|
||
default: '',
|
||
},
|
||
});
|
||
|
||
// Computed: 当前就诊日期
|
||
const currentVisitDate = computed(() => {
|
||
if (props.visitType === 'FOLLOW_UP' && props.firstVisitDate) {
|
||
return props.firstVisitDate;
|
||
}
|
||
return formatDateUtil(props.patientInfo?.registerTime || new Date());
|
||
});
|
||
|
||
// 表单数据
|
||
const form = ref({
|
||
height: '',
|
||
weight: '',
|
||
temperature: '',
|
||
pulse: '',
|
||
chiefComplaint: '',
|
||
onsetDate: '',
|
||
currentIllnessHistory: '',
|
||
pastMedicalHistory: '',
|
||
menstrualHistory: '',
|
||
allergyHistory: '',
|
||
physicalExamination: '',
|
||
treatment: '',
|
||
auxiliaryExamination: '',
|
||
});
|
||
|
||
// 文本字段配置(用于循环渲染)
|
||
const textFieldList = [
|
||
{ key: 'currentIllnessHistory', label: '现病史' },
|
||
{ key: 'pastMedicalHistory', label: '既往史' },
|
||
{ key: 'menstrualHistory', label: '个人史' },
|
||
{ key: 'allergyHistory', label: '过敏史' },
|
||
{ key: 'physicalExamination', label: '查体' },
|
||
{ key: 'treatment', label: '处理' },
|
||
{ key: 'auxiliaryExamination', label: '辅助检查' },
|
||
];
|
||
|
||
// 弹窗控制
|
||
const emrTitle = ref('');
|
||
const radio = ref(1);
|
||
const showDialog = ref('');
|
||
const openEmrTemplate = ref(false);
|
||
const templateName = ref('');
|
||
|
||
// 事件
|
||
const emits = defineEmits(['save']);
|
||
const { proxy } = getCurrentInstance();
|
||
|
||
// 监听表单变化
|
||
watch(
|
||
() => form.value,
|
||
() => {
|
||
emits('save', false);
|
||
},
|
||
{ deep: true }
|
||
);
|
||
|
||
// 格式化日期(用于 onsetDate)
|
||
function formatDate(date) {
|
||
if (!date) return '';
|
||
return formatDateUtil(date);
|
||
}
|
||
|
||
// 保存病历
|
||
function addEmr() {
|
||
// 简单校验主诉
|
||
if (!form.value.chiefComplaint) {
|
||
proxy.$message.warning('请输入主诉');
|
||
return;
|
||
}
|
||
saveEmr({
|
||
patientId: props.patientInfo.patientId,
|
||
encounterId: props.patientInfo.encounterId,
|
||
contextJson: form.value,
|
||
}).then((res) => {
|
||
if (res.code === 200) {
|
||
proxy.$modal.msgSuccess('病历已保存');
|
||
emits('save', true);
|
||
}
|
||
});
|
||
}
|
||
|
||
// 打开模板
|
||
function handleEmrTemplate() {
|
||
emrTitle.value = '病历模板';
|
||
showDialog.value = 'emrTemplate';
|
||
openEmrTemplate.value = true;
|
||
}
|
||
|
||
// 打开历史
|
||
function handleEmrHistory() {
|
||
emrTitle.value = '历史病历';
|
||
showDialog.value = 'emrHistory';
|
||
openEmrTemplate.value = true;
|
||
sessionStorage.setItem('patientId', props.patientInfo.patientId);
|
||
}
|
||
|
||
// 保存为模板
|
||
function handleSaveTemplate() {
|
||
emrTitle.value = '保存模板';
|
||
showDialog.value = 'saveTemplate';
|
||
openEmrTemplate.value = true;
|
||
}
|
||
|
||
// 选择模板/历史
|
||
function templateSelect(row) {
|
||
form.value = { ...row };
|
||
openEmrTemplate.value = false;
|
||
}
|
||
function emrHistorySelect(row) {
|
||
form.value = { ...row };
|
||
openEmrTemplate.value = false;
|
||
}
|
||
|
||
// 弹窗确认
|
||
function submit() {
|
||
if (showDialog.value === 'saveTemplate') {
|
||
if (!templateName.value.trim()) {
|
||
proxy.$message.warning('请输入模板名称');
|
||
return;
|
||
}
|
||
saveEmrTemplate({
|
||
templateName: templateName.value,
|
||
useScopeCode: radio.value,
|
||
contextJson: form.value,
|
||
}).then((res) => {
|
||
if (res.code === 200) {
|
||
openEmrTemplate.value = false;
|
||
proxy.$modal.msgSuccess('保存成功');
|
||
}
|
||
});
|
||
} else {
|
||
openEmrTemplate.value = false;
|
||
}
|
||
}
|
||
|
||
function cancel() {
|
||
openEmrTemplate.value = false;
|
||
}
|
||
|
||
// 可选:打印功能
|
||
// function printEmr() {
|
||
// const printContent = proxy.$refs.printArea.innerHTML;
|
||
// const originalContent = document.body.innerHTML;
|
||
// document.body.innerHTML = printContent;
|
||
// window.print();
|
||
// document.body.innerHTML = originalContent;
|
||
// window.location.reload(); // 恢复组件状态
|
||
// }
|
||
|
||
// 暴露方法给父组件
|
||
defineExpose({
|
||
getDetail(encounterId) {
|
||
getEmrDetail(encounterId).then((res) => {
|
||
if (res.data) {
|
||
try {
|
||
form.value = JSON.parse(res.data.contextJson) || {};
|
||
} catch (e) {
|
||
form.value = {};
|
||
}
|
||
emits('save', true);
|
||
} else {
|
||
form.value = {};
|
||
}
|
||
});
|
||
},
|
||
addEmr
|
||
});
|
||
</script>
|
||
|
||
<style scoped>
|
||
/* 可选:增强打印样式 */
|
||
@media print {
|
||
body * {
|
||
visibility: hidden;
|
||
}
|
||
#printArea, #printArea * {
|
||
visibility: visible;
|
||
}
|
||
#printArea {
|
||
position: absolute;
|
||
left: 0;
|
||
top: 0;
|
||
width: 100%;
|
||
}
|
||
}
|
||
</style> |