- 将主要蓝色从 #409eff 替换为 #3B82F6 - 将成功绿色从 #67c23a 替换为 #10B981 - 将警告橙色从 #e6a23c 替换为 #F59E0B - 将危险红色从 #f56c6c 替换为 #EF4444 - 将信息灰色从 #909399 替换为 #64748B - 更新所有组件中的相关颜色配置 - 调整菜单主题为更深邃的午夜蓝风格 - 移除SCSS变量导出的注释标记
416 lines
9.9 KiB
Vue
Executable File
416 lines
9.9 KiB
Vue
Executable File
<!--
|
|
* @Author: sjjh
|
|
* @Date: 2025-09-05 21:16:06
|
|
* @Description: 输血申请详情
|
|
-->
|
|
<template>
|
|
<div class="report-container">
|
|
<div class="report-section">
|
|
<div class="report-title">
|
|
<span>输血申请</span>
|
|
<el-icon
|
|
class="report-refresh-icon"
|
|
:class="{ 'is-loading': loading }"
|
|
@click="handleRefresh"
|
|
>
|
|
<Refresh />
|
|
</el-icon>
|
|
</div>
|
|
<div class="report-table-wrapper">
|
|
<el-table
|
|
v-loading="loading"
|
|
:data="tableData"
|
|
border
|
|
size="small"
|
|
height="100%"
|
|
style="width: 100%"
|
|
>
|
|
<el-table-column
|
|
type="index"
|
|
label="序号"
|
|
width="60"
|
|
align="center"
|
|
/>
|
|
<el-table-column
|
|
prop="patientName"
|
|
label="患者姓名"
|
|
width="120"
|
|
/>
|
|
<el-table-column
|
|
prop="name"
|
|
label="申请单名称"
|
|
width="140"
|
|
/>
|
|
<el-table-column
|
|
prop="createTime"
|
|
label="创建时间"
|
|
width="160"
|
|
/>
|
|
<el-table-column
|
|
prop="prescriptionNo"
|
|
label="处方号"
|
|
width="140"
|
|
/>
|
|
<el-table-column
|
|
prop="requesterId_dictText"
|
|
label="申请者"
|
|
width="120"
|
|
/>
|
|
<el-table-column
|
|
label="操作"
|
|
align="center"
|
|
fixed="right"
|
|
>
|
|
<template #default="scope">
|
|
<el-button
|
|
link
|
|
type="primary"
|
|
@click="handleViewDetail(scope.row)"
|
|
>
|
|
详情
|
|
</el-button>
|
|
</template>
|
|
</el-table-column>
|
|
</el-table>
|
|
</div>
|
|
</div>
|
|
<!-- 详情弹窗 -->
|
|
<el-dialog
|
|
v-model="detailDialogVisible"
|
|
title="输血申请详情"
|
|
width="800px"
|
|
destroy-on-close
|
|
top="5vh"
|
|
:close-on-click-modal="false"
|
|
>
|
|
<div
|
|
v-if="currentDetail"
|
|
class="applicationShow-container"
|
|
>
|
|
<div class="applicationShow-container-content">
|
|
<el-descriptions
|
|
title="基本信息"
|
|
:column="2"
|
|
>
|
|
<el-descriptions-item label="患者姓名">
|
|
{{
|
|
currentDetail.patientName || '-'
|
|
}}
|
|
</el-descriptions-item>
|
|
<el-descriptions-item label="申请单名称">
|
|
{{
|
|
currentDetail.name || '-'
|
|
}}
|
|
</el-descriptions-item>
|
|
<el-descriptions-item label="创建时间">
|
|
{{
|
|
currentDetail.createTime || '-'
|
|
}}
|
|
</el-descriptions-item>
|
|
<el-descriptions-item label="处方号">
|
|
{{
|
|
currentDetail.prescriptionNo || '-'
|
|
}}
|
|
</el-descriptions-item>
|
|
<el-descriptions-item label="申请者">
|
|
{{
|
|
currentDetail.requesterId_dictText || '-'
|
|
}}
|
|
</el-descriptions-item>
|
|
<el-descriptions-item label="就诊ID">
|
|
{{
|
|
currentDetail.encounterId || '-'
|
|
}}
|
|
</el-descriptions-item>
|
|
<el-descriptions-item label="申请单ID">
|
|
{{
|
|
currentDetail.requestFormId || '-'
|
|
}}
|
|
</el-descriptions-item>
|
|
</el-descriptions>
|
|
</div>
|
|
|
|
<div
|
|
v-if="descJsonData && hasMatchedFields"
|
|
class="applicationShow-container-content"
|
|
>
|
|
<el-descriptions
|
|
title="申请单描述"
|
|
:column="2"
|
|
>
|
|
<template
|
|
v-for="(value, key) in descJsonData"
|
|
:key="key"
|
|
>
|
|
<el-descriptions-item
|
|
v-if="isFieldMatched(key)"
|
|
:label="getFieldLabel(key)"
|
|
>
|
|
{{ value || '-' }}
|
|
</el-descriptions-item>
|
|
</template>
|
|
</el-descriptions>
|
|
</div>
|
|
|
|
<div
|
|
v-if="currentDetail.requestFormDetailList && currentDetail.requestFormDetailList.length"
|
|
class="applicationShow-container-table"
|
|
>
|
|
<el-table
|
|
:data="currentDetail.requestFormDetailList"
|
|
border
|
|
>
|
|
<el-table-column
|
|
type="index"
|
|
label="序号"
|
|
width="60"
|
|
align="center"
|
|
/>
|
|
<el-table-column
|
|
prop="adviceName"
|
|
label="医嘱名称"
|
|
/>
|
|
<el-table-column
|
|
prop="quantity"
|
|
label="数量"
|
|
width="80"
|
|
align="center"
|
|
/>
|
|
<el-table-column
|
|
prop="unitCode_dictText"
|
|
label="单位"
|
|
width="100"
|
|
/>
|
|
<el-table-column
|
|
prop="totalPrice"
|
|
label="总价"
|
|
width="100"
|
|
align="right"
|
|
/>
|
|
</el-table>
|
|
</div>
|
|
</div>
|
|
<template #footer>
|
|
<el-button @click="detailDialogVisible = false">
|
|
关闭
|
|
</el-button>
|
|
</template>
|
|
</el-dialog>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import {computed, getCurrentInstance, ref, watch} from 'vue';
|
|
import {Refresh} from '@element-plus/icons-vue';
|
|
import {patientInfo} from '../../store/patient.js';
|
|
import {getBloodTransfusion} from './api';
|
|
import {getOrgList} from '@/views/doctorstation/components/api.js';
|
|
|
|
const { proxy } = getCurrentInstance();
|
|
|
|
const tableData = ref([]);
|
|
const loading = ref(false);
|
|
const detailDialogVisible = ref(false);
|
|
const currentDetail = ref(null);
|
|
const descJsonData = ref(null);
|
|
const orgOptions = ref([]);
|
|
|
|
const fetchData = async () => {
|
|
if (!patientInfo.value?.encounterId) {
|
|
tableData.value = [];
|
|
loading.value = false;
|
|
return;
|
|
}
|
|
loading.value = true;
|
|
try {
|
|
const res = await getBloodTransfusion({ encounterId: patientInfo.value.encounterId });
|
|
if (res.code === 200 && res.data) {
|
|
const raw = res.data?.records || res.data;
|
|
const list = Array.isArray(raw) ? raw : [raw];
|
|
tableData.value = list.filter(Boolean);
|
|
} else {
|
|
tableData.value = [];
|
|
}
|
|
} catch (e) {
|
|
proxy.$modal?.msgError?.(e.message || '查询输血申请失败');
|
|
tableData.value = [];
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
};
|
|
|
|
const handleRefresh = async () => {
|
|
if (loading.value || !patientInfo.value?.encounterId) return;
|
|
await fetchData();
|
|
};
|
|
|
|
const labelMap = {
|
|
categoryType: '项目类别',
|
|
targetDepartment: '发往科室',
|
|
symptom: '症状',
|
|
sign: '体征',
|
|
clinicalDiagnosis: '临床诊断',
|
|
otherDiagnosis: '其他诊断',
|
|
relatedResult: '相关结果',
|
|
attention: '注意事项',
|
|
};
|
|
|
|
const isFieldMatched = (key) => {
|
|
return key in labelMap;
|
|
};
|
|
|
|
const getFieldLabel = (key) => {
|
|
return labelMap[key] || key;
|
|
};
|
|
|
|
const hasMatchedFields = computed(() => {
|
|
if (!descJsonData.value) return false;
|
|
return Object.keys(descJsonData.value).some((key) => isFieldMatched(key));
|
|
});
|
|
|
|
/** 查询科室 */
|
|
const getLocationInfo = async () => {
|
|
const res = await getOrgList();
|
|
orgOptions.value = res.data.records;
|
|
};
|
|
|
|
const recursionFun = (targetDepartment) => {
|
|
let name = '';
|
|
for (let index = 0; index < orgOptions.value.length; index++) {
|
|
const obj = orgOptions.value[index];
|
|
if (obj.id == targetDepartment) {
|
|
name = obj.name;
|
|
}
|
|
const subObjArray = obj['children'];
|
|
for (let index = 0; index < subObjArray.length; index++) {
|
|
const item = subObjArray[index];
|
|
if (item.id == targetDepartment) {
|
|
name = item.name;
|
|
}
|
|
}
|
|
}
|
|
return name;
|
|
};
|
|
|
|
const handleViewDetail = async (row) => {
|
|
// 确保科室数据已加载,以便将 ID 解析为名称
|
|
if (!orgOptions.value || orgOptions.value.length === 0) {
|
|
await getLocationInfo();
|
|
}
|
|
|
|
currentDetail.value = row;
|
|
// 解析 descJson
|
|
if (row.descJson) {
|
|
try {
|
|
// descJsonData.value = JSON.parse(row.descJson);
|
|
const obj = JSON.parse(row.descJson);
|
|
obj.targetDepartment = recursionFun(obj.targetDepartment);
|
|
descJsonData.value = obj;
|
|
} catch (e) {
|
|
console.error('解析 descJson 失败:', e);
|
|
descJsonData.value = null;
|
|
}
|
|
} else {
|
|
descJsonData.value = null;
|
|
}
|
|
detailDialogVisible.value = true;
|
|
};
|
|
|
|
watch(
|
|
() => patientInfo.value?.encounterId,
|
|
async (val) => {
|
|
if (val) {
|
|
await Promise.all([fetchData(), getLocationInfo()]);
|
|
} else {
|
|
tableData.value = [];
|
|
}
|
|
},
|
|
{ immediate: true }
|
|
);
|
|
|
|
defineExpose({
|
|
refresh: fetchData,
|
|
});
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
.report-container {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 12px;
|
|
padding: 8px 0;
|
|
height: 100%;
|
|
}
|
|
|
|
.report-section {
|
|
background: #fff;
|
|
flex: 1;
|
|
min-height: 0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.report-title {
|
|
font-weight: 600;
|
|
margin-bottom: 8px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 0 8px;
|
|
}
|
|
|
|
.report-table-wrapper {
|
|
flex: 1;
|
|
min-height: 0;
|
|
overflow: auto;
|
|
padding: 0 8px;
|
|
}
|
|
|
|
.report-refresh-icon {
|
|
cursor: pointer;
|
|
color: #64748B;
|
|
transition: color 0.2s;
|
|
font-size: 18px;
|
|
}
|
|
|
|
.report-refresh-icon:hover {
|
|
color: #3B82F6;
|
|
}
|
|
|
|
.report-refresh-icon.is-loading {
|
|
animation: rotating 2s linear infinite;
|
|
}
|
|
|
|
@keyframes rotating {
|
|
0% {
|
|
transform: rotate(0deg);
|
|
}
|
|
100% {
|
|
transform: rotate(360deg);
|
|
}
|
|
}
|
|
|
|
:deep(.el-dialog__body) {
|
|
padding-top: 0 !important;
|
|
}
|
|
|
|
.applicationShow-container {
|
|
display: flex;
|
|
flex-direction: column;
|
|
max-height: 70vh;
|
|
width: 100%;
|
|
overflow-y: auto;
|
|
|
|
.applicationShow-container-content {
|
|
flex-shrink: 0;
|
|
margin-bottom: 0px;
|
|
}
|
|
|
|
.applicationShow-container-table {
|
|
flex-shrink: 0;
|
|
max-height: 300px;
|
|
overflow: auto;
|
|
}
|
|
}
|
|
</style>
|