fix(common): 统一异常处理并迁移打印功能到hiprint

- 替换所有System.out.println和printStackTrace为slf4j日志记录
- 在BeanUtils、AuditFieldUtil、DateUtils、ServletUtils等工具类中添加Logger实例
- 在Flowable相关控制器和服务中统一错误日志记录格式
- 在代码生成器中添加日志记录功能
- 将前端打印组件从Lodop迁移到hiprint打印方案
- 更新体温单打印功能使用hiprint预览打印
- 移除调试用的console.log语句
- 修复打印模板中线条元素类型定义
This commit is contained in:
2026-03-06 22:32:56 +08:00
parent b65841c0cc
commit 8a3fe5461e
11 changed files with 1667 additions and 0 deletions

View File

@@ -0,0 +1,483 @@
<template>
<el-drawer
:model-value="visible"
:title="mode === 'audit' ? '审核报卡' : '查看报卡'"
direction="rtl"
size="700px"
:before-close="handleClose"
>
<div class="drawer-content">
<!-- 报卡表单 -->
<div class="card-form-section">
<h3 class="section-title">中华人民共和国传染病报告卡</h3>
<el-form :model="cardData" label-width="100px" class="card-form">
<!-- 卡片编号 -->
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="卡片编号">
<el-input v-model="cardData.cardNo" disabled />
</el-form-item>
</el-col>
</el-row>
<!-- 患者基本信息 -->
<div class="form-divider">患者基本信息</div>
<el-row :gutter="16">
<el-col :span="8">
<el-form-item label="患者姓名">
<el-input v-model="cardData.patName" disabled />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="家长姓名">
<el-input v-model="cardData.parentName" disabled />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="身份证号">
<el-input v-model="cardData.idNo" disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="8">
<el-form-item label="性别">
<el-input :value="getSexName(cardData.sex)" disabled />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="出生日期">
<el-input v-model="cardData.birthday" disabled />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="实足年龄">
<el-input :value="cardData.age + getAgeUnit(cardData.ageUnit)" disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="联系电话">
<el-input v-model="cardData.phone" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="紧急电话">
<el-input v-model="cardData.contactPhone" disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="24">
<el-form-item label="现住地址">
<el-input :value="getFullAddress(cardData)" disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="病人属于">
<el-input v-model="cardData.patientbelong" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="职业">
<el-input v-model="cardData.occupation" disabled />
</el-form-item>
</el-col>
</el-row>
<!-- 临床信息 -->
<div class="form-divider">临床信息</div>
<el-row :gutter="16">
<el-col :span="8">
<el-form-item label="病例分类">
<el-input :value="getCaseTypeName(cardData.diseaseType)" disabled />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="发病日期">
<el-input :value="formatDate(cardData.onsetDate)" disabled />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="诊断日期">
<el-input :value="formatDate(cardData.diagDate)" disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="疾病名称">
<el-input :value="cardData.diseaseName || cardData.diseaseCode" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="分型">
<el-input v-model="cardData.diseaseSubtype" disabled />
</el-form-item>
</el-col>
</el-row>
<!-- 上报信息 -->
<div class="form-divider">上报信息</div>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="报告单位">
<el-input v-model="cardData.reportOrg" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="报告医生">
<el-input v-model="cardData.reportDoc" disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="填卡日期">
<el-input :value="formatDate(cardData.reportDate)" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="登记来源">
<el-input :value="getSourceName(cardData.registrationSource)" disabled />
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
<!-- 审核记录 -->
<div class="audit-records-section" v-if="auditRecords.length > 0">
<h3 class="section-title">审核记录</h3>
<el-timeline>
<el-timeline-item
v-for="record in auditRecords"
:key="record.auditId"
:timestamp="record.auditTime"
placement="top"
:type="getAuditType(record.auditStatusTo)"
>
<el-card>
<div class="record-content">
<div class="record-header">
<span class="auditor">{{ record.auditorName }}</span>
<el-tag size="small" :type="getAuditType(record.auditStatusTo)">
{{ getAuditTypeName(record.auditType) }}
</el-tag>
</div>
<div class="record-detail">
<span v-if="record.auditOpinion">审核意见{{ record.auditOpinion }}</span>
<span v-if="record.reasonForReturn">退回原因{{ record.reasonForReturn }}</span>
</div>
<div class="record-status">
{{ getStatusName(record.auditStatusFrom) }} {{ getStatusName(record.auditStatusTo) }}
</div>
</div>
</el-card>
</el-timeline-item>
</el-timeline>
</div>
<!-- 审核操作区域 -->
<div class="audit-action-section" v-if="mode === 'audit'">
<h3 class="section-title">审核操作</h3>
<el-form :model="auditForm" label-width="100px">
<el-form-item label="审核意见" required>
<el-input
v-model="auditForm.auditOpinion"
type="textarea"
:rows="3"
placeholder="请填写审核意见"
/>
</el-form-item>
<el-form-item label="退回原因">
<el-input
v-model="auditForm.returnReason"
type="textarea"
:rows="3"
placeholder="如需退回,请填写退回原因"
/>
</el-form-item>
</el-form>
</div>
</div>
<template #footer>
<div class="drawer-footer">
<el-button @click="handleClose">关闭</el-button>
<template v-if="mode === 'audit'">
<el-button type="warning" @click="handleReturn" :disabled="!auditForm.returnReason">
退回修改
</el-button>
<el-button type="success" @click="handlePass" :disabled="!auditForm.auditOpinion">
审核通过
</el-button>
</template>
</div>
</template>
</el-drawer>
</template>
<script setup>
import { ref, watch } from 'vue';
import { ElMessage } from 'element-plus';
const props = defineProps({
visible: {
type: Boolean,
default: false,
},
mode: {
type: String,
default: 'view', // view | audit
},
cardData: {
type: Object,
default: () => ({}),
},
auditRecords: {
type: Array,
default: () => [],
},
});
const emit = defineEmits(['close', 'submit']);
const auditForm = ref({
auditOpinion: '',
returnReason: '',
});
// 状态映射
const statusMap = {
'0': '暂存',
'1': '待审核',
'2': '审核通过',
'3': '已上报',
'4': '失败',
'5': '审核失败',
};
// 审核类型映射
const auditTypeMap = {
'1': '批量审核',
'2': '审核通过',
'3': '批量退回',
'4': '退回修改',
'5': '其他',
};
// 病例分类映射
const caseTypeMap = {
'1': '疑似病例',
'2': '临床诊断病例',
'3': '确诊病例',
'4': '病原携带者',
'5': '阳性检测结果',
};
// 年龄单位映射
const ageUnitMap = {
'1': '岁',
'2': '月',
'3': '天',
};
// 来源映射
const sourceMap = {
1: '门诊',
2: '住院',
3: '急诊',
4: '体检',
};
// 获取状态名称
function getStatusName(status) {
return statusMap[status] || '未知';
}
// 获取审核类型名称
function getAuditTypeName(type) {
return auditTypeMap[type] || '未知';
}
// 获取审核类型样式
function getAuditType(status) {
if (status === '2') return 'success';
if (status === '5') return 'warning';
return 'primary';
}
// 获取性别名称
function getSexName(sex) {
if (sex === '1') return '男';
if (sex === '2') return '女';
return '未知';
}
// 获取年龄单位
function getAgeUnit(unit) {
return ageUnitMap[unit] || '岁';
}
// 获取病例分类名称
function getCaseTypeName(type) {
return caseTypeMap[type] || '-';
}
// 获取来源名称
function getSourceName(source) {
return sourceMap[source] || '-';
}
// 获取完整地址
function getFullAddress(data) {
const parts = [
data.addressProv,
data.addressCity,
data.addressCounty,
data.addressTown,
data.addressVillage,
data.addressHouse,
].filter(Boolean);
return parts.join('') || '-';
}
// 格式化日期
function formatDate(date) {
if (!date) return '-';
if (typeof date === 'string') return date.split('T')[0];
return new Date(date).toISOString().split('T')[0];
}
// 关闭抽屉
function handleClose() {
emit('close');
}
// 审核通过
function handlePass() {
if (!auditForm.value.auditOpinion) {
ElMessage.warning('请填写审核意见');
return;
}
emit('submit', {
type: 'pass',
cardNo: props.cardData.cardNo,
auditOpinion: auditForm.value.auditOpinion,
});
}
// 退回修改
function handleReturn() {
if (!auditForm.value.returnReason) {
ElMessage.warning('请填写退回原因');
return;
}
emit('submit', {
type: 'return',
cardNo: props.cardData.cardNo,
returnReason: auditForm.value.returnReason,
});
}
// 监听visible变化重置表单
watch(() => props.visible, (val) => {
if (val) {
auditForm.value = {
auditOpinion: '',
returnReason: '',
};
}
});
</script>
<style scoped>
.drawer-content {
padding: 0 20px;
}
.section-title {
font-size: 16px;
font-weight: bold;
color: #303133;
margin: 0 0 16px 0;
padding-bottom: 8px;
border-bottom: 2px solid #409eff;
}
.card-form-section {
margin-bottom: 24px;
}
.card-form {
padding: 16px;
background: #fafafa;
border-radius: 8px;
}
.form-divider {
font-size: 14px;
font-weight: bold;
color: #606266;
margin: 16px 0 12px 0;
padding-left: 8px;
border-left: 3px solid #409eff;
}
.audit-records-section {
margin-bottom: 24px;
}
.record-content {
padding: 8px 0;
}
.record-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
}
.auditor {
font-weight: bold;
color: #303133;
}
.record-detail {
font-size: 13px;
color: #606266;
margin-bottom: 8px;
}
.record-status {
font-size: 12px;
color: #909399;
}
.audit-action-section {
margin-bottom: 24px;
}
.audit-action-section .el-form {
padding: 16px;
background: #fafafa;
border-radius: 8px;
}
.drawer-footer {
display: flex;
justify-content: flex-end;
gap: 12px;
}
:deep(.el-drawer__footer) {
padding: 16px 20px;
border-top: 1px solid #ebeef5;
}
</style>