| | |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="Rh阴性"> |
| | | {{ |
| | | caseData.rhYin === "1" ? "是" : caseData.rhYin === "0" ? "否" : "-" |
| | | caseData.rhYin == "1" ? "是" : caseData.rhYin == "0" ? "否" : "-" |
| | | }} |
| | | </el-descriptions-item> |
| | | |
| | | <el-descriptions-item label="证件类型"> |
| | | {{ getIdCardTypeText(caseData.idcardtype) }} |
| | | <dict-tag |
| | | :options="dict.type.sys_IDType" |
| | | :value="caseData.idcardtype" |
| | | /> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="证件号码">{{ |
| | | caseData.idcardno || "-" |
| | |
| | | <el-descriptions-item label="籍贯">{{ |
| | | caseData.nativeplace || "-" |
| | | }}</el-descriptions-item> |
| | | <el-descriptions-item label="学历">{{ |
| | | caseData.education || "-" |
| | | }}</el-descriptions-item> |
| | | <el-descriptions-item label="职业">{{ |
| | | caseData.occupation || "-" |
| | | }}</el-descriptions-item> |
| | | <el-descriptions-item label="学历"> |
| | | <dict-tag |
| | | :options="dict.type.sys_education" |
| | | :value="String(caseData.education)" |
| | | /></el-descriptions-item> |
| | | <el-descriptions-item label="职业"> |
| | | <dict-tag |
| | | :options="dict.type.sys_occupation" |
| | | :value="caseData.occupation" |
| | | /></el-descriptions-item> |
| | | <el-descriptions-item label="出生日期">{{ |
| | | formatDate(caseData.birthday) |
| | | }}</el-descriptions-item> |
| | |
| | | </el-card> |
| | | |
| | | <!-- 地址信息模块 --> |
| | | <!-- <el-card class="detail-section"> |
| | | <el-card class="detail-section"> |
| | | <div slot="header" class="section-header"> |
| | | <span class="section-title">地址信息</span> |
| | | </div> |
| | |
| | | {{ getFullResidenceAddress() }} |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | </el-card> --> |
| | | </el-card> |
| | | |
| | | <!-- 医疗信息模块 --> |
| | | <el-card class="detail-section"> |
| | |
| | | >{{ caseData.infectiousOther }}</el-descriptions-item |
| | | > |
| | | <el-descriptions-item label="是否需要转运"> |
| | | {{ caseData.isTransport === "2" ? "需要" : "不需要" }} |
| | | {{ |
| | | caseData.isTransport == "1" |
| | | ? "不需要" |
| | | : caseData.isTransport == "2" |
| | | ? "需要" |
| | | : "待定" |
| | | }} |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | </el-card> |
| | |
| | | <span class="section-title">医院信息</span> |
| | | </div> |
| | | <el-descriptions :column="2" border> |
| | | <el-descriptions-item label="治疗医院名称">{{ |
| | | <el-descriptions-item label="ICU评估医生">{{ |
| | | caseData.icuDoctor || "-" |
| | | }}</el-descriptions-item> |
| | | <el-descriptions-item label="ICU医生电话">{{ |
| | | caseData.icuDoctorPhone || "-" |
| | | }}</el-descriptions-item |
| | | ><el-descriptions-item label="治疗医院名称">{{ |
| | | caseData.treatmenthospitalname || "-" |
| | | }}</el-descriptions-item> |
| | | <!-- <el-descriptions-item label="治疗科室名称">{{ |
| | |
| | | formatDateTime(caseData.createTime) |
| | | }}</el-descriptions-item> |
| | | <el-descriptions-item label="是否终止案例"> |
| | | {{ caseData.terminationCase === "1" ? "已终止" : "进行中" }} |
| | | {{ caseData.terminationCase == "1" ? "已终止" : "进行中" }} |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | </el-card> |
| | |
| | | <span class="section-title">附件信息</span> |
| | | </div> |
| | | <div class="detail-attachments"> |
| | | <div class="attachment-grid"> |
| | | <div |
| | | v-for="file in caseData.annexfilesList" |
| | | :key="file.id || file.fileName" |
| | | class="attachment-card" |
| | | > |
| | | <template v-if="isImageFile(file.fileName || file.path)"> |
| | | <!-- 图片使用 el-image 预览 --> |
| | | <el-image |
| | | class="image-attachment" |
| | | :src="getFileUrl(file)" |
| | | :preview-src-list="getImagePreviewList(file)" |
| | | fit="cover" |
| | | :style="{ width: '120px', height: '120px' }" |
| | | lazy |
| | | > |
| | | <div slot="error" class="image-error"> |
| | | <i class="el-icon-picture-outline"></i> |
| | | <span>加载失败</span> |
| | | </div> |
| | | <div slot="placeholder" class="image-loading"> |
| | | <i class="el-icon-loading"></i> |
| | | </div> |
| | | </el-image> |
| | | <div class="image-info"> |
| | | <div class="file-name" :title="file.fileName"> |
| | | {{ file.fileName }} |
| | | </div> |
| | | <div class="file-actions"> |
| | | <el-button |
| | | type="text" |
| | | size="mini" |
| | | @click="handleDownload(file)" |
| | | icon="el-icon-download" |
| | | title="下载" |
| | | /> |
| | | <el-button |
| | | type="text" |
| | | size="mini" |
| | | @click="handlePreview(file)" |
| | | icon="el-icon-view" |
| | | title="预览" |
| | | /> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <template v-else> |
| | | <!-- 非图片文件使用卡片样式 --> |
| | | <el-card shadow="hover" class="file-card"> |
| | | <div class="file-content"> |
| | | <i :class="getFileIcon(file.fileName)" class="file-icon"></i> |
| | | <div class="file-info"> |
| | | <div class="file-name" :title="file.fileName"> |
| | | {{ file.fileName }} |
| | | </div> |
| | | <div class="file-meta"> |
| | | <span class="file-type">{{ |
| | | getFileTypeText(file.fileName) |
| | | }}</span> |
| | | <span v-if="file.createTime" class="file-time"> |
| | | {{ formatDateTime(file.createTime) }} |
| | | </span> |
| | | </div> |
| | | <div |
| | | v-for="group in attachmentGroups" |
| | | :key="group.label" |
| | | class="attachment-group" |
| | | > |
| | | <div class="attachment-group-title">{{ group.label }}</div> |
| | | <div class="attachment-grid"> |
| | | <div |
| | | v-for="file in group.files" |
| | | :key="file.id || file.fileName" |
| | | class="attachment-card" |
| | | > |
| | | <template v-if="isImageFile(file.fileName || file.path)"> |
| | | <!-- 图片使用 el-image 预览 --> |
| | | <el-image |
| | | class="image-attachment" |
| | | :src="getFileUrl(file)" |
| | | :preview-src-list="getImagePreviewList(file)" |
| | | fit="cover" |
| | | :style="{ width: '120px', height: '120px' }" |
| | | lazy |
| | | > |
| | | <div slot="error" class="image-error"> |
| | | <i class="el-icon-picture-outline"></i> |
| | | <span>加载失败</span> |
| | | </div> |
| | | <div slot="placeholder" class="image-loading"> |
| | | <i class="el-icon-loading"></i> |
| | | </div> |
| | | </el-image> |
| | | <div class="image-info"> |
| | | <div class="file-name" :title="file.fileName"> |
| | | {{ file.fileName }} |
| | | </div> |
| | | <div class="file-actions"> |
| | | <el-button |
| | | type="text" |
| | | size="mini" |
| | | @click="handleDownload(file)" |
| | | icon="el-icon-download" |
| | | title="下载" |
| | | /> |
| | | <el-button |
| | | type="text" |
| | | size="mini" |
| | | @click="handlePreview(file)" |
| | | icon="el-icon-view" |
| | | title="预览" |
| | | /> |
| | | </div> |
| | | </div> |
| | | <div class="file-actions"> |
| | | <el-button |
| | | type="text" |
| | | size="mini" |
| | | @click="handleDownload(file)" |
| | | > |
| | | 下载 |
| | | </el-button> |
| | | <el-button |
| | | v-if="canPreview(file.fileName)" |
| | | type="text" |
| | | size="mini" |
| | | @click="handlePreview(file)" |
| | | > |
| | | 预览 |
| | | </el-button> |
| | | </div> |
| | | </el-card> |
| | | </template> |
| | | </template> |
| | | |
| | | <template v-else> |
| | | <!-- 非图片文件使用卡片样式 --> |
| | | <el-card shadow="hover" class="file-card"> |
| | | <div class="file-content"> |
| | | <i :class="getFileIcon(file.fileName)" class="file-icon"></i> |
| | | <div class="file-info"> |
| | | <div class="file-name" :title="file.fileName"> |
| | | {{ file.fileName }} |
| | | </div> |
| | | <div class="file-meta"> |
| | | <span class="file-type">{{ |
| | | getFileTypeText(file.fileName) |
| | | }}</span> |
| | | <span v-if="file.createTime" class="file-time"> |
| | | {{ formatDateTime(file.createTime) }} |
| | | </span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="file-actions"> |
| | | <el-button |
| | | type="text" |
| | | size="mini" |
| | | @click="handleDownload(file)" |
| | | > |
| | | 下载 |
| | | </el-button> |
| | | <el-button |
| | | v-if="canPreview(file.fileName)" |
| | | type="text" |
| | | size="mini" |
| | | @click="handlePreview(file)" |
| | | > |
| | | 预览 |
| | | </el-button> |
| | | </div> |
| | | </el-card> |
| | | </template> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | <!-- 审批信息模块(状态为已同意或已驳回时显示) --> |
| | | <el-card |
| | | class="detail-section" |
| | | v-if="caseData.reportStatus === '3' || caseData.reportStatus === '4'" |
| | | v-if="caseData.reportStatus == '3' || caseData.reportStatus == '4'" |
| | | > |
| | | <div slot="header" class="section-header"> |
| | | <span class="section-title">审批信息</span> |
| | | </div> |
| | | <el-descriptions :column="1" border> |
| | | <el-descriptions-item label="审批结果"> |
| | | <el-tag :type="caseData.reportStatus === '3' ? 'success' : 'danger'"> |
| | | {{ caseData.reportStatus === "3" ? "已同意" : "已驳回" }} |
| | | <el-tag :type="caseData.reportStatus == '3' ? 'success' : 'danger'"> |
| | | {{ caseData.reportStatus == "3" ? "已同意" : "已驳回" }} |
| | | </el-tag> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item |
| | |
| | | <div slot="header" class="section-header"> |
| | | <span class="section-title">转运信息</span> |
| | | <el-button |
| | | v-if="caseData.reportStatus === '3'" |
| | | v-if="caseData.reportStatus == '3'" |
| | | type="primary" |
| | | size="small" |
| | | icon="el-icon-truck" |
| | |
| | | <!-- 无转运信息但需要转运的提示 --> |
| | | <el-card |
| | | class="detail-section" |
| | | v-else-if="caseData.isTransport === '2' && caseData.reportStatus === '3'" |
| | | v-else-if="caseData.isTransport == '2' && caseData.reportStatus == '3'" |
| | | > |
| | | <div slot="header" class="section-header"> |
| | | <span class="section-title">转运信息</span> |
| | |
| | | pdf, |
| | | FilePreviewDialog |
| | | }, |
| | | dicts: [ |
| | | "sys_user_sex", |
| | | "sys_BloodType", |
| | | "sys_Infectious", |
| | | "sys_IDType", |
| | | "sys_education", |
| | | "sys_occupation", |
| | | "reject_type" |
| | | ], |
| | | props: { |
| | | caseData: { |
| | | type: Object, |
| | |
| | | default: true |
| | | } |
| | | }, |
| | | dicts: ["sys_user_sex", "sys_BloodType", "sys_Infectious", "reject_type"], |
| | | data() { |
| | | return { |
| | | // 预览相关 |
| | | previewVisible: false, |
| | | currentPreviewFile: null, |
| | | |
| | | // 动态计算的 baseUrlHt |
| | | baseUrlHt: "", |
| | | // 图片预览相关 |
| | | imagePreviewUrls: [], |
| | | rejectOptions: [ |
| | |
| | | .filter(file => this.isImageFile(file.fileName || file.path)) |
| | | .map(file => this.getFileUrl(file)) |
| | | .filter(url => url); |
| | | }, |
| | | // 按分类分组附件(捐献者登记阶段:登记表附件/证件照/疾病诊断治疗) |
| | | attachmentGroups() { |
| | | const list = this.caseData.annexfilesList; |
| | | if (!Array.isArray(list) || list.length === 0) return []; |
| | | const categories = [ |
| | | { value: "登记表附件", label: "人体器官潜在捐献者登记表附件" }, |
| | | { value: "证件照", label: "证件照" }, |
| | | { value: "疾病诊断治疗", label: "疾病诊断治疗" } |
| | | ]; |
| | | const groups = categories |
| | | .map(cat => ({ |
| | | label: cat.label, |
| | | files: list.filter(f => (f.fileType || "").trim() === cat.value) |
| | | })) |
| | | .filter(group => group.files.length > 0); |
| | | // 未分类附件兜底,避免丢失旧数据 |
| | | const classifiedValues = categories.map(c => c.value); |
| | | const unclassified = list.filter(f => { |
| | | const t = (f.fileType || "").trim(); |
| | | return !t || !classifiedValues.includes(t); |
| | | }); |
| | | if (unclassified.length > 0) { |
| | | groups.push({ label: "未分类", files: unclassified }); |
| | | } |
| | | return groups; |
| | | } |
| | | }, |
| | | created() { |
| | | this.calculateBaseUrl(); |
| | | }, |
| | | methods: { |
| | | handleClose() { |
| | | this.$emit("close"); |
| | | }, |
| | | /** 计算 baseUrlHt */ |
| | | calculateBaseUrl() { |
| | | const currentUrl = window.location.href; |
| | | |
| | | try { |
| | | const urlObj = new URL(currentUrl); |
| | | const hostname = urlObj.hostname; |
| | | this.baseUrlHt = `http://${hostname}:9095`; |
| | | } catch (error) { |
| | | console.error("解析URL失败:", error); |
| | | const match = currentUrl.match(/https?:\/\/([^:\/]+)/); |
| | | if (match) { |
| | | this.baseUrlHt = `http://${match[1]}:9095`; |
| | | } else { |
| | | this.baseUrlHt = "http://localhost:9095"; |
| | | } |
| | | } |
| | | }, |
| | | // 格式化日期时间 |
| | | formatDateTime(dateTime) { |
| | | if (!dateTime) return "-"; |
| | |
| | | }, |
| | | |
| | | getFileUrl(file) { |
| | | return file.path || file.fileUrl || ""; |
| | | if (!file) return ""; |
| | | const url = file.path || file.fileUrl || file.url || ""; |
| | | return this.processFileUrl(url); |
| | | }, |
| | | // URL处理函数 - 将完整URL替换为baseUrlHt |
| | | processFileUrl(url) { |
| | | if (!url) return ""; |
| | | |
| | | // 如果已经是完整的http或https链接 |
| | | if (url.startsWith("http://") || url.startsWith("https://")) { |
| | | // 找到第三个斜杠后的位置,提取路径部分 |
| | | const thirdSlashIndex = url.indexOf("/", 8); |
| | | if (thirdSlashIndex !== -1) { |
| | | return `${this.baseUrlHt}${url.substring(thirdSlashIndex)}`; |
| | | } |
| | | return this.baseUrlHt; |
| | | } |
| | | |
| | | // 相对路径处理 |
| | | if (url.startsWith("/")) { |
| | | return `${this.baseUrlHt}${url}`; |
| | | } |
| | | |
| | | return `${this.baseUrlHt}/${url}`; |
| | | }, |
| | | |
| | | getImagePreviewList(file) { |
| | |
| | | handlePreview(file) { |
| | | this.currentPreviewFile = { |
| | | fileName: file.fileName, |
| | | fileUrl: this.getFileUrl(file), |
| | | fileUrl: this.getFileUrl(file), // 已经处理过URL |
| | | fileType: this.getFileType(file.fileName) |
| | | }; |
| | | this.previewVisible = true; |
| | |
| | | |
| | | // 文件下载 |
| | | handleDownload(file) { |
| | | const fileUrl = this.getFileUrl(file); |
| | | const fileUrl = this.getFileUrl(file); // 使用处理过的URL |
| | | const fileName = file.fileName; |
| | | |
| | | if (fileUrl) { |
| | |
| | | padding: 10px 0; |
| | | } |
| | | |
| | | .attachment-group { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .attachment-group-title { |
| | | font-size: 14px; |
| | | font-weight: bold; |
| | | color: #409eff; |
| | | margin-bottom: 12px; |
| | | padding-left: 10px; |
| | | border-left: 3px solid #409eff; |
| | | } |
| | | |
| | | .attachment-grid { |
| | | display: grid; |
| | | grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); |