Files
his/openhis-ui-vue3/src/views/cardmanagement/components/AuditDrawer.vue
zhangfei 9c3e603b94 Fix Bug #443: 手术计费:点击签发耗材时异常报错
当手术计费弹窗中点击"签发"耗材时,因耗材的locationId(发放库房)为空导致后端异常。
在DoctorStationAdviceAppServiceImpl.handDevice方法中,当locationId为null时,使用登录用户的科室ID作为默认值,
与NurseBillingAppService中的处理方式保持一致。
2026-05-08 09:14:18 +08:00

484 lines
12 KiB
Vue
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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>