<template>
|
<div class="case-detail">
|
<el-tabs v-model="activeTab">
|
<el-tab-pane label="基本信息" name="basic">
|
<el-descriptions :column="2" border>
|
<el-descriptions-item label="捐献编号">{{ caseData.donorNo }}</el-descriptions-item>
|
<el-descriptions-item label="捐献者姓名">{{ caseData.donorName }}</el-descriptions-item>
|
<el-descriptions-item label="性别">
|
<dict-tag :options="genderOptions" :value="caseData.gender"/>
|
</el-descriptions-item>
|
<el-descriptions-item label="年龄">{{ caseData.age }}岁</el-descriptions-item>
|
<el-descriptions-item label="血型">
|
<dict-tag :options="bloodTypeOptions" :value="caseData.bloodType"/>
|
</el-descriptions-item>
|
<el-descriptions-item label="证件号码">{{ caseData.idCardNo }}</el-descriptions-item>
|
<el-descriptions-item label="民族">{{ caseData.nation }}</el-descriptions-item>
|
<el-descriptions-item label="联系电话">{{ caseData.phone }}</el-descriptions-item>
|
<el-descriptions-item label="住址" :span="2">{{ caseData.address }}</el-descriptions-item>
|
</el-descriptions>
|
</el-tab-pane>
|
|
<el-tab-pane label="医疗信息" name="medical">
|
<el-descriptions :column="1" border>
|
<el-descriptions-item label="疾病诊断">{{ caseData.diagnosis }}</el-descriptions-item>
|
<el-descriptions-item label="住院号">{{ caseData.inpatientNo }}</el-descriptions-item>
|
<el-descriptions-item label="所在科室">{{ caseData.departmentName }}</el-descriptions-item>
|
<el-descriptions-item label="主治医生">{{ caseData.doctorName }}</el-descriptions-item>
|
<el-descriptions-item label="传染病情况">{{ caseData.infectiousDisease || '无' }}</el-descriptions-item>
|
<el-descriptions-item label="医疗记录">{{ caseData.medicalRecord }}</el-descriptions-item>
|
</el-descriptions>
|
</el-tab-pane>
|
|
<el-tab-pane label="医院信息" name="hospital">
|
<el-descriptions :column="2" border>
|
<el-descriptions-item label="医院名称">{{ caseData.hospitalName }}</el-descriptions-item>
|
<el-descriptions-item label="医院级别">{{ caseData.hospitalLevel }}</el-descriptions-item>
|
<el-descriptions-item label="联系人">{{ caseData.contactPerson }}</el-descriptions-item>
|
<el-descriptions-item label="联系电话">{{ caseData.contactPhone }}</el-descriptions-item>
|
<el-descriptions-item label="医院地址" :span="2">{{ caseData.hospitalAddress }}</el-descriptions-item>
|
</el-descriptions>
|
</el-tab-pane>
|
|
<!-- 新增附件信息标签页 -->
|
<el-tab-pane label="附件信息" name="attachments">
|
<el-card class="attachment-card">
|
<div slot="header" class="clearfix">
|
<span>附件列表</span>
|
<el-button
|
style="float: right; padding: 3px 0"
|
type="text"
|
@click="handleUpload"
|
>
|
上传附件
|
</el-button>
|
</div>
|
|
<el-table :data="attachmentList" style="width: 100%">
|
<el-table-column label="文件名" width="300">
|
<template slot-scope="scope">
|
<i class="el-icon-document" style="margin-right: 8px;"></i>
|
<span>{{ scope.row.fileName }}</span>
|
</template>
|
</el-table-column>
|
<el-table-column label="文件类型" width="120">
|
<template slot-scope="scope">
|
<el-tag size="small">{{ scope.row.fileType }}</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column label="大小" width="100">
|
<template slot-scope="scope">
|
<span>{{ formatFileSize(scope.row.fileSize) }}</span>
|
</template>
|
</el-table-column>
|
<el-table-column label="上传时间" width="180">
|
<template slot-scope="scope">
|
<span>{{ scope.row.uploadTime }}</span>
|
</template>
|
</el-table-column>
|
<el-table-column label="操作">
|
<template slot-scope="scope">
|
<el-button size="mini" @click="handlePreview(scope.row)"
|
>预览</el-button
|
>
|
<el-button
|
size="mini"
|
type="success"
|
@click="handleDownload(scope.row)"
|
>下载</el-button
|
>
|
<el-button
|
size="mini"
|
type="danger"
|
@click="handleDelete(scope.row)"
|
>删除</el-button
|
>
|
</template>
|
</el-table-column>
|
</el-table>
|
</el-card>
|
</el-tab-pane>
|
|
<el-tab-pane label="审批信息" name="approval" v-if="caseData.status !== '0'">
|
<el-descriptions :column="1" border>
|
<el-descriptions-item label="审批结果">
|
<el-tag :type="caseData.status | statusFilter">
|
{{ caseData.status | statusTextFilter }}
|
</el-tag>
|
</el-descriptions-item>
|
<el-descriptions-item label="审批时间">{{ caseData.approveTime }}</el-descriptions-item>
|
<el-descriptions-item label="审批人">{{ caseData.approverName }}</el-descriptions-item>
|
<el-descriptions-item label="审批意见">{{ caseData.approveOpinion }}</el-descriptions-item>
|
</el-descriptions>
|
</el-tab-pane>
|
</el-tabs>
|
|
<!-- PDF预览弹窗 -->
|
<el-dialog
|
:title="previewTitle"
|
:append-to-body="true"
|
:visible.sync="pdfPreviewVisible"
|
width="90%"
|
top="5vh"
|
:close-on-click-modal="true"
|
class="pdf-preview-dialog"
|
@close="handlePdfDialogClose"
|
>
|
<div class="pdf-preview-container" v-loading="pdfLoading">
|
<!-- PDF控制工具栏 -->
|
<div class="pdf-toolbar">
|
<el-button-group>
|
<el-button
|
size="mini"
|
@click="changePage(currentPage - 1)"
|
:disabled="currentPage <= 1"
|
icon="el-icon-arrow-left"
|
>
|
上一页
|
</el-button>
|
<el-button size="mini" disabled>
|
第 {{ currentPage }} 页 / 共 {{ pageCount }} 页
|
</el-button>
|
<el-button
|
size="mini"
|
@click="changePage(currentPage + 1)"
|
:disabled="currentPage >= pageCount"
|
icon="el-icon-arrow-right"
|
>
|
下一页
|
</el-button>
|
</el-button-group>
|
|
<el-button-group class="zoom-controls">
|
<el-button size="mini" @click="zoomOut" :disabled="scale <= 50">
|
<i class="el-icon-zoom-out"></i> 缩小
|
</el-button>
|
<el-button size="mini" disabled> {{ scale }}% </el-button>
|
<el-button size="mini" @click="zoomIn" :disabled="scale >= 200">
|
<i class="el-icon-zoom-in"></i> 放大
|
</el-button>
|
<el-button size="mini" @click="resetZoom">
|
<i class="el-icon-refresh-left"></i> 重置
|
</el-button>
|
</el-button-group>
|
|
<el-button
|
size="mini"
|
type="success"
|
@click="downloadPdf(currentFile)"
|
icon="el-icon-download"
|
>
|
下载
|
</el-button>
|
</div>
|
|
<!-- PDF渲染区域 -->
|
<div class="pdf-viewport">
|
<pdf
|
ref="pdf"
|
:src="pdfUrl"
|
:page="currentPage"
|
:rotate="pageRotate"
|
@num-pages="pageCount = $event"
|
@page-loaded="currentPage = $event"
|
@loaded="loadPdfHandler"
|
@error="pdfErrorHandler"
|
:style="{
|
width: scale + '%',
|
transform: 'scale(' + scale / 100 + ')',
|
transformOrigin: '0 0'
|
}"
|
></pdf>
|
</div>
|
</div>
|
</el-dialog>
|
|
<!-- 图片预览弹窗 -->
|
<el-dialog
|
:append-to-body="true"
|
:title="previewTitle"
|
:visible.sync="imagePreviewVisible"
|
width="60%"
|
top="10vh"
|
:close-on-click-modal="true"
|
>
|
<div class="image-preview-container">
|
<img :src="previewUrl" alt="预览图片" class="preview-image" />
|
</div>
|
</el-dialog>
|
|
<!-- 不支持预览的文件类型 -->
|
<el-dialog
|
:title="previewTitle"
|
:visible.sync="unsupportedPreviewVisible"
|
width="400px"
|
:close-on-click-modal="true"
|
>
|
<div class="unsupported-preview">
|
<el-alert
|
title="该文件格式不支持在线预览,请下载后查看"
|
type="warning"
|
show-icon
|
:closable="false"
|
/>
|
<div style="text-align: center; margin-top: 20px;">
|
<el-button type="primary" @click="handleDownload(currentFile)">
|
<i class="el-icon-download"></i> 下载文件
|
</el-button>
|
</div>
|
</div>
|
</el-dialog>
|
|
<div class="detail-footer">
|
<el-button @click="handleClose">关闭</el-button>
|
</div>
|
</div>
|
</template>
|
|
<script>
|
import pdf from "vue-pdf";
|
|
export default {
|
name: "CaseDetail",
|
components: {
|
pdf
|
},
|
props: {
|
caseData: {
|
type: Object,
|
default: () => ({})
|
}
|
},
|
filters: {
|
statusFilter(status) {
|
const statusMap = {
|
'0': 'warning',
|
'1': 'success',
|
'2': 'danger'
|
};
|
return statusMap[status];
|
},
|
statusTextFilter(status) {
|
const statusMap = {
|
'0': '待审批',
|
'1': '已通过',
|
'2': '已驳回'
|
};
|
return statusMap[status];
|
}
|
},
|
data() {
|
return {
|
activeTab: 'basic',
|
genderOptions: [
|
{ value: "0", label: "男" },
|
{ value: "1", label: "女" }
|
],
|
bloodTypeOptions: [
|
{ value: "A", label: "A型" },
|
{ value: "B", label: "B型" },
|
{ value: "O", label: "O型" },
|
{ value: "AB", label: "AB型" }
|
],
|
|
// 附件相关数据
|
attachmentList: [
|
{
|
id: 1,
|
fileName: "捐献者身份证.jpg",
|
fileType: "jpg",
|
fileSize: 1024000,
|
uploadTime: "2024-12-19 10:30:00",
|
fileUrl: "https://img95.699pic.com/photo/40142/8262.jpg_wh860.jpg"
|
},
|
{
|
id: 2,
|
fileName: "医疗诊断证明.pdf",
|
fileType: "pdf",
|
fileSize: 2048000,
|
uploadTime: "2024-12-19 11:20:00",
|
fileUrl:
|
"http://192.168.100.10:8080/profile/upload/2025/12/19/(吴龙8.7)每日工作总结1766131266142.pdf"
|
},
|
{
|
id: 3,
|
fileName: "检验报告单.jpg",
|
fileType: "docx",
|
fileSize: 512000,
|
uploadTime: "2024-12-19 14:15:00",
|
fileUrl: "https://img95.699pic.com/photo/40019/3490.jpg_wh860.jpg"
|
}
|
],
|
|
// PDF预览相关数据
|
pdfPreviewVisible: false,
|
pdfLoading: false,
|
pdfUrl: "",
|
currentPage: 1,
|
pageCount: 0,
|
scale: 100,
|
pageRotate: 0,
|
|
// 图片预览相关
|
imagePreviewVisible: false,
|
|
// 不支持预览相关
|
unsupportedPreviewVisible: false,
|
|
// 通用预览数据
|
previewTitle: "",
|
previewUrl: "",
|
currentFile: null
|
};
|
},
|
methods: {
|
handleClose() {
|
this.$emit('close');
|
},
|
|
// 获取文件类型
|
getFileType(fileName) {
|
const extension = fileName.split('.').pop().toLowerCase();
|
const imageTypes = ["jpg", "jpeg", "png", "gif", "bmp", "webp"];
|
const pdfTypes = ["pdf"];
|
|
if (imageTypes.includes(extension)) return "image";
|
if (pdfTypes.includes(extension)) return "pdf";
|
return "other";
|
},
|
|
// 文件预览主入口
|
handlePreview(file) {
|
this.currentFile = file;
|
this.previewTitle = `预览 - ${file.fileName}`;
|
this.previewUrl = file.fileUrl;
|
const fileType = this.getFileType(file.fileName);
|
|
switch (fileType) {
|
case "pdf":
|
this.previewPdf(file);
|
break;
|
case "image":
|
this.previewImage(file);
|
break;
|
default:
|
this.previewUnsupported(file);
|
break;
|
}
|
},
|
|
// PDF预览方法
|
previewPdf(file) {
|
this.pdfPreviewVisible = true;
|
this.pdfLoading = true;
|
this.currentPage = 1;
|
this.scale = 100;
|
this.pageRotate = 0;
|
this.pdfUrl = file.fileUrl;
|
},
|
|
// PDF加载完成回调
|
loadPdfHandler() {
|
this.pdfLoading = false;
|
this.currentPage = 1;
|
},
|
|
// PDF加载错误处理
|
pdfErrorHandler(error) {
|
console.error("PDF加载失败:", error);
|
this.pdfLoading = false;
|
this.$message.error("PDF文件加载失败,请尝试下载后查看");
|
this.pdfPreviewVisible = false;
|
},
|
|
// 翻页功能
|
changePage(newPage) {
|
if (newPage < 1 || newPage > this.pageCount) return;
|
this.currentPage = newPage;
|
},
|
|
// 缩放功能
|
zoomIn() {
|
if (this.scale >= 200) {
|
this.$message.info("已放大到最大比例");
|
return;
|
}
|
this.scale += 10;
|
},
|
|
zoomOut() {
|
if (this.scale <= 50) {
|
this.$message.info("已缩小到最小比例");
|
return;
|
}
|
this.scale -= 10;
|
},
|
|
resetZoom() {
|
this.scale = 100;
|
},
|
|
// 图片预览方法
|
previewImage(file) {
|
this.imagePreviewVisible = true;
|
},
|
|
// 不支持预览的文件类型
|
previewUnsupported(file) {
|
this.unsupportedPreviewVisible = true;
|
},
|
|
// PDF对话框关闭处理
|
handlePdfDialogClose() {
|
this.pdfUrl = "";
|
this.currentPage = 1;
|
this.pageCount = 0;
|
},
|
|
// 文件下载
|
handleDownload(file) {
|
const link = document.createElement("a");
|
link.href = file.fileUrl;
|
link.download = file.fileName;
|
link.style.display = "none";
|
document.body.appendChild(link);
|
link.click();
|
document.body.removeChild(link);
|
this.$message.success("开始下载文件");
|
},
|
|
// 专用PDF下载方法
|
downloadPdf(file) {
|
this.handleDownload(file);
|
},
|
|
// 文件删除
|
handleDelete(file) {
|
this.$confirm("确定要删除这个附件吗?", "提示", {
|
confirmButtonText: "确定",
|
cancelButtonText: "取消",
|
type: "warning"
|
}).then(() => {
|
this.attachmentList = this.attachmentList.filter(
|
item => item.id !== file.id
|
);
|
this.$message.success("删除成功");
|
});
|
},
|
|
// 上传附件
|
handleUpload() {
|
this.$message.info("上传功能待实现");
|
},
|
|
// 格式化文件大小
|
formatFileSize(bytes) {
|
if (bytes === 0) return "0 B";
|
const k = 1024;
|
const sizes = ["B", "KB", "MB", "GB"];
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
|
}
|
}
|
};
|
</script>
|
|
<style scoped>
|
.case-detail {
|
padding: 0 20px;
|
}
|
|
/* PDF预览对话框样式 */
|
.pdf-preview-dialog {
|
margin-top: 5vh !important;
|
}
|
|
.pdf-preview-dialog >>> .el-dialog {
|
min-height: 80vh;
|
display: flex;
|
flex-direction: column;
|
}
|
|
.pdf-preview-dialog >>> .el-dialog__body {
|
flex: 1;
|
padding: 0;
|
display: flex;
|
flex-direction: column;
|
}
|
|
.pdf-preview-container {
|
display: flex;
|
flex-direction: column;
|
height: 100%;
|
}
|
|
/* PDF工具栏样式 */
|
.pdf-toolbar {
|
padding: 15px 20px;
|
background: #f5f7fa;
|
border-bottom: 1px solid #ebeef5;
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
flex-wrap: wrap;
|
gap: 10px;
|
}
|
|
.zoom-controls {
|
margin: 0 15px;
|
}
|
|
/* PDF视图区域样式 */
|
.pdf-viewport {
|
flex: 1;
|
overflow: auto;
|
padding: 20px;
|
background: #f8f9fa;
|
display: flex;
|
justify-content: center;
|
align-items: flex-start;
|
}
|
|
/* 图片预览样式 */
|
.image-preview-container {
|
text-align: center;
|
padding: 20px;
|
}
|
|
.preview-image {
|
max-width: 100%;
|
max-height: 70vh;
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
}
|
|
/* 响应式设计 */
|
@media (max-width: 768px) {
|
.pdf-toolbar {
|
flex-direction: column;
|
gap: 10px;
|
}
|
|
.zoom-controls {
|
margin: 10px 0;
|
}
|
|
.pdf-preview-dialog {
|
width: 95% !important;
|
}
|
}
|
|
.detail-footer {
|
text-align: center;
|
margin-top: 20px;
|
padding-top: 20px;
|
border-top: 1px solid #ebeef5;
|
}
|
|
::v-deep .el-descriptions__label {
|
width: 120px;
|
background-color: #f5f7fa;
|
font-weight: bold;
|
}
|
</style>
|