当手术计费弹窗中点击"签发"耗材时,因耗材的locationId(发放库房)为空导致后端异常。 在DoctorStationAdviceAppServiceImpl.handDevice方法中,当locationId为null时,使用登录用户的科室ID作为默认值, 与NurseBillingAppService中的处理方式保持一致。
484 lines
12 KiB
Vue
Executable File
484 lines
12 KiB
Vue
Executable File
<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>
|