<template>
|
<div class="transport-detail-container">
|
<!-- 基础信息模块 -->
|
<el-card class="detail-section">
|
<div slot="header" class="section-header">
|
<i
|
class="el-icon-document"
|
style="color: #409EFF; margin-right: 8px;"
|
></i>
|
<span class="section-title">基础信息</span>
|
</div>
|
<el-descriptions :column="2" border>
|
<el-descriptions-item label="转运单号">{{
|
transportData.reportId || transportData.id
|
}}</el-descriptions-item>
|
<el-descriptions-item label="案例编号">{{
|
transportData.caseNo
|
}}</el-descriptions-item>
|
<el-descriptions-item label="患者姓名">{{
|
transportData.patName
|
}}</el-descriptions-item>
|
<el-descriptions-item label="性别">
|
<dict-tag
|
:options="dict.type.sys_user_sex"
|
:value="parseInt(transportData.sex)"
|
/>
|
</el-descriptions-item>
|
<el-descriptions-item label="年龄"
|
>{{ transportData.age }}岁</el-descriptions-item
|
>
|
<el-descriptions-item label="疾病诊断">{{
|
transportData.diagnosisname
|
}}</el-descriptions-item>
|
<el-descriptions-item label="治疗医院">{{
|
transportData.treatmentHospitalName
|
}}</el-descriptions-item>
|
<el-descriptions-item label="治疗科室">{{
|
transportData.treatmentDeptName
|
}}</el-descriptions-item>
|
<el-descriptions-item label="出发地点">{{
|
transportData.transportStartPlace
|
}}</el-descriptions-item>
|
<el-descriptions-item label="计划转运时间">{{
|
transportData.transportStartTime
|
}}</el-descriptions-item>
|
<el-descriptions-item label="负责协调员">{{
|
transportData.contactPerson
|
}}</el-descriptions-item>
|
<el-descriptions-item label="转运状态">
|
<el-tag :type="getStatusTagType(transportData.transitStatus)">
|
{{ getStatusText(transportData.transitStatus) }}
|
</el-tag>
|
</el-descriptions-item>
|
<el-descriptions-item label="创建时间">{{
|
transportData.createTime
|
}}</el-descriptions-item>
|
<el-descriptions-item label="更新时间">{{
|
transportData.updateTime
|
}}</el-descriptions-item>
|
</el-descriptions>
|
</el-card>
|
|
<!-- 转运详情模块 -->
|
<el-card class="detail-section">
|
<div slot="header" class="section-header">
|
<i
|
class="el-icon-location-information"
|
style="color: #67C23A; margin-right: 8px;"
|
></i>
|
<span class="section-title">转运详情</span>
|
</div>
|
<el-descriptions :column="2" border>
|
<el-descriptions-item label="出发地点">{{
|
transportData.transportStartPlace
|
}}</el-descriptions-item>
|
<el-descriptions-item label="目的医院">{{
|
transportData.treatmentHospitalName
|
}}</el-descriptions-item>
|
<el-descriptions-item label="治疗科室">{{
|
transportData.treatmentDeptName
|
}}</el-descriptions-item>
|
<el-descriptions-item label="出发时间">{{
|
transportData.transportStartTime
|
}}</el-descriptions-item>
|
<el-descriptions-item label="转运状态">
|
<el-tag :type="getStatusTagType(transportData.transitStatus)">
|
{{ getStatusText(transportData.transitStatus) }}
|
</el-tag>
|
</el-descriptions-item>
|
</el-descriptions>
|
</el-card>
|
|
<!-- 医护人员信息模块 -->
|
<el-card class="detail-section">
|
<div slot="header" class="section-header">
|
<i class="el-icon-user" style="color: #E6A23C; margin-right: 8px;"></i>
|
<span class="section-title">医护人员信息</span>
|
</div>
|
<el-descriptions :column="2" border>
|
<el-descriptions-item label="协调员">{{
|
transportData.contactPerson
|
}}</el-descriptions-item>
|
<el-descriptions-item label="协调员电话">{{
|
transportData.contactPhone || "未填写"
|
}}</el-descriptions-item>
|
<el-descriptions-item label="急诊科医生">{{
|
transportData.doctor
|
}}</el-descriptions-item>
|
<el-descriptions-item label="急诊医生电话">{{
|
transportData.doctorPhone
|
}}</el-descriptions-item>
|
<el-descriptions-item label="护士">{{
|
transportData.nurse
|
}}</el-descriptions-item>
|
<el-descriptions-item label="护士电话">{{
|
transportData.nursePhone
|
}}</el-descriptions-item>
|
<el-descriptions-item label="驾驶员">{{
|
transportData.driver
|
}}</el-descriptions-item>
|
<el-descriptions-item label="驾驶员电话">{{
|
transportData.driverPhone
|
}}</el-descriptions-item>
|
<el-descriptions-item label="ICU评估医生">{{
|
transportData.icuDoctor
|
}}</el-descriptions-item>
|
<el-descriptions-item label="ICU医生电话">{{
|
transportData.icuDoctorPhone
|
}}</el-descriptions-item>
|
</el-descriptions>
|
</el-card>
|
|
<!-- 附件信息模块 -->
|
<el-card
|
class="detail-section"
|
v-if="
|
transportData.annexfilesList && transportData.annexfilesList.length > 0
|
"
|
>
|
<div slot="header" class="section-header">
|
<i
|
class="el-icon-folder"
|
style="color: #F56C6C; margin-right: 8px;"
|
></i>
|
<span class="section-title">附件信息</span>
|
</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.type }}</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column label="文件地址" min-width="200" show-overflow-tooltip>
|
<template slot-scope="scope">
|
<span>{{ scope.row.path }}</span>
|
</template>
|
</el-table-column>
|
<el-table-column label="操作" width="200">
|
<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
|
>
|
</template>
|
</el-table-column>
|
</el-table>
|
</el-card>
|
|
<!-- 备注信息模块 -->
|
<el-card class="detail-section" v-if="transportData.remark">
|
<div slot="header" class="section-header">
|
<i class="el-icon-edit" style="color: #909399; margin-right: 8px;"></i>
|
<span class="section-title">备注信息</span>
|
</div>
|
<div class="remarks-content">
|
{{ transportData.remark }}
|
</div>
|
</el-card>
|
|
<!-- 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">
|
<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>
|
|
<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";
|
import UploadAttachment from "@/components/UploadAttachment";
|
|
export default {
|
name: "TransportDetail",
|
components: {
|
pdf
|
},
|
components: {
|
UploadAttachment
|
},
|
dicts: ["sys_user_sex"],
|
props: {
|
transportData: {
|
type: Object,
|
default: () => ({})
|
}
|
},
|
data() {
|
return {
|
// 附件相关数据
|
attachmentList: [],
|
// PDF预览相关数据
|
pdfPreviewVisible: false,
|
pdfLoading: false,
|
pdfUrl: "",
|
currentPage: 1,
|
pageCount: 0,
|
scale: 100,
|
pageRotate: 0,
|
// 图片预览相关
|
imagePreviewVisible: false,
|
// 不支持预览相关
|
unsupportedPreviewVisible: false,
|
// 通用预览数据
|
previewTitle: "",
|
previewUrl: "",
|
currentFile: null
|
};
|
},
|
watch: {
|
transportData: {
|
handler(newVal) {
|
this.transformAttachmentData(newVal.annexfilesList);
|
},
|
immediate: true,
|
deep: true
|
}
|
},
|
methods: {
|
/** 转换附件数据 */
|
transformAttachmentData(annexfilesList) {
|
if (!annexfilesList || !Array.isArray(annexfilesList)) {
|
this.attachmentList = [];
|
return;
|
}
|
|
this.attachmentList = annexfilesList;
|
// this.attachmentList = annexfilesList.map((fileUrl, index) => {
|
// const fileName = this.getFileNameFromUrl(fileUrl);
|
// return {
|
// id: index + 1,
|
// fileName: fileName,
|
// fileType: this.getFileType(fileName),
|
// fileUrl: fileUrl
|
// };
|
// });
|
},
|
|
/** 从URL中提取文件名 */
|
getFileNameFromUrl(url) {
|
if (!url) return "未知文件";
|
return url.split("/").pop() || "未知文件";
|
},
|
|
/** 获取状态标签类型 */
|
getStatusTagType(transitStatus) {
|
const statusMap = {
|
1: "warning", // 待转运
|
2: "primary", // 转运中
|
3: "success", // 转运完成
|
4: "danger", // 转运取消
|
5: "info" // 暂存
|
};
|
return statusMap[transitStatus] || "info";
|
},
|
|
/** 获取状态文本 */
|
getStatusText(transitStatus) {
|
const statusMap = {
|
1: "待转运",
|
2: "转运中",
|
3: "转运完成",
|
4: "转运取消",
|
5: "暂存"
|
};
|
return statusMap[transitStatus] || "未知状态";
|
},
|
|
// 关闭弹框
|
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.path;
|
const fileType = this.getFileType(file.fileName);
|
console.log(this.previewUrl, "this.previewUrl");
|
|
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.path;
|
},
|
|
// 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.path;
|
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);
|
},
|
|
formatFileSize(bytes) {
|
if (!bytes) return "未知大小";
|
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>
|
.transport-detail-container {
|
max-height: 70vh;
|
overflow-y: auto;
|
padding: 0 10px;
|
}
|
|
.detail-section {
|
margin-bottom: 16px;
|
}
|
|
.section-header {
|
display: flex;
|
align-items: center;
|
}
|
|
.section-title {
|
font-size: 16px;
|
font-weight: bold;
|
color: #303133;
|
}
|
|
.remarks-content {
|
padding: 15px;
|
line-height: 1.6;
|
color: #606266;
|
white-space: pre-line;
|
}
|
|
/* 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-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-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);
|
}
|
|
.detail-footer {
|
text-align: center;
|
margin-top: 20px;
|
padding-top: 20px;
|
border-top: 1px solid #ebeef5;
|
}
|
|
/* 响应式设计 */
|
@media (max-width: 768px) {
|
.transport-detail-container {
|
padding: 0 5px;
|
}
|
|
.pdf-toolbar {
|
flex-direction: column;
|
gap: 10px;
|
}
|
|
.zoom-controls {
|
margin: 10px 0;
|
}
|
}
|
|
::v-deep .el-descriptions__label {
|
width: 120px;
|
background-color: #f5f7fa;
|
font-weight: bold;
|
}
|
</style>
|