WXL
12 小时以前 0c03027d7f238bf5beb98e85463f53f0bd92bbaa
src/views/business/appear/caseDetail.vue
@@ -1,235 +1,403 @@
<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-card class="detail-section">
      <div slot="header" class="section-header">
        <span class="section-title">基本信息</span>
      </div>
      <el-descriptions :column="2" border>
        <el-descriptions-item label="案例编号">{{
          caseData.caseNo || "-"
        }}</el-descriptions-item>
        <el-descriptions-item label="捐献者姓名">{{
          caseData.name || "-"
        }}</el-descriptions-item>
        <el-descriptions-item label="性别">
          <dict-tag :options="dict.type.sys_user_sex" :value="caseData.sex" />
        </el-descriptions-item>
        <el-descriptions-item label="年龄">
          {{ caseData.age || "-"
          }}{{
            caseData.ageunit ? `(${getAgeUnitText(caseData.ageunit)})` : ""
          }}
        </el-descriptions-item>
        <el-descriptions-item label="血型">
          <dict-tag
            :options="dict.type.sys_BloodType"
            :value="caseData.bloodType"
          />
        </el-descriptions-item>
        <el-descriptions-item label="Rh阴性">
          {{
            caseData.rhYin === "1" ? "是" : caseData.rhYin === "0" ? "否" : "-"
          }}
        </el-descriptions-item>
        <el-descriptions-item label="证件类型">
          {{ getIdCardTypeText(caseData.idcardtype) }}
        </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.nationality || "-"
        }}</el-descriptions-item>
        <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="出生日期">{{
          formatDate(caseData.birthday)
        }}</el-descriptions-item>
        <el-descriptions-item label="联系电话">{{
          caseData.phone || "-"
        }}</el-descriptions-item>
      </el-descriptions>
    </el-card>
      <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-card class="detail-section">
      <div slot="header" class="section-header">
        <span class="section-title">地址信息</span>
      </div>
      <el-descriptions :column="1" border>
        <el-descriptions-item label="户籍地址">
          {{ getFullRegisterAddress() }}
        </el-descriptions-item>
        <el-descriptions-item label="现住地址">
          {{ getFullResidenceAddress() }}
        </el-descriptions-item>
      </el-descriptions>
    </el-card>
      <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-card class="detail-section">
      <div slot="header" class="section-header">
        <span class="section-title">医疗信息</span>
      </div>
      <el-descriptions :column="1" border>
        <el-descriptions-item label="疾病诊断名称">{{
          caseData.diagnosisname || "-"
        }}</el-descriptions-item>
        <el-descriptions-item label="病情概况">{{
          caseData.illnessoverview || "-"
        }}</el-descriptions-item>
        <el-descriptions-item label="病人状况">{{
          caseData.patientstate || "-"
        }}</el-descriptions-item>
        <el-descriptions-item label="GCS评分">{{
          caseData.gcsScore || "-"
        }}</el-descriptions-item>
        <el-descriptions-item label="传染病情况">{{
          caseData.infectious || "无"
        }}</el-descriptions-item>
        <el-descriptions-item
          label="传染病其他说明"
          v-if="caseData.infectiousOther"
          >{{ caseData.infectiousOther }}</el-descriptions-item
        >
        <el-descriptions-item label="是否需要转运">
          {{ caseData.isTransport === "2" ? "需要" : "不需要" }}
        </el-descriptions-item>
      </el-descriptions>
    </el-card>
      <!-- 新增附件信息标签页 -->
      <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-card class="detail-section">
      <div slot="header" class="section-header">
        <span class="section-title">医院信息</span>
      </div>
      <el-descriptions :column="2" border>
        <el-descriptions-item label="治疗医院名称">{{
          caseData.treatmenthospitalname || "-"
        }}</el-descriptions-item>
        <el-descriptions-item label="治疗科室名称">{{
          caseData.treatmentdeptname || "-"
        }}</el-descriptions-item>
        <el-descriptions-item label="住院号">{{
          caseData.inpatientno || "-"
        }}</el-descriptions-item>
        <el-descriptions-item label="部门名称">{{
          caseData.deptName || "-"
        }}</el-descriptions-item>
        <el-descriptions-item label="部门编号">{{
          caseData.deptNo || "-"
        }}</el-descriptions-item>
        <el-descriptions-item label="上报医院">{{
          caseData.toHospital || "-"
        }}</el-descriptions-item>
      </el-descriptions>
    </el-card>
          <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-card class="detail-section">
      <div slot="header" class="section-header">
        <span class="section-title">上报信息</span>
      </div>
      <el-descriptions :column="2" border>
        <el-descriptions-item label="报告者姓名">{{
          caseData.infoName || "-"
        }}</el-descriptions-item>
        <el-descriptions-item label="报告者编号">{{
          caseData.infoNo || "-"
        }}</el-descriptions-item>
        <el-descriptions-item label="报告者联系电话">{{
          caseData.reporterphone || "-"
        }}</el-descriptions-item>
        <el-descriptions-item label="协调员姓名">{{
          caseData.coordinatorName || "-"
        }}</el-descriptions-item>
        <el-descriptions-item label="协调员编号">{{
          caseData.coordinatorNo || "-"
        }}</el-descriptions-item>
        <el-descriptions-item label="上报状态">
          <el-tag :type="getStatusType(caseData.reportStatus)">
            {{ getStatusText(caseData.reportStatus) }}
          </el-tag>
        </el-descriptions-item>
        <el-descriptions-item label="报告时间">{{
          formatDateTime(caseData.createTime)
        }}</el-descriptions-item>
        <el-descriptions-item label="是否终止案例">
          {{ caseData.terminationCase === "1" ? "已终止" : "进行中" }}
        </el-descriptions-item>
      </el-descriptions>
    </el-card>
      <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"
    <!-- 附件信息模块 -->
    <el-card
      class="detail-section"
      v-if="caseData.annexfilesList && caseData.annexfilesList.length > 0"
    >
      <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"
      <div slot="header" class="section-header">
        <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"
          >
            下载
          </el-button>
        </div>
            <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>
        <!-- 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>
            <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>
    </el-dialog>
    </el-card>
    <!-- 图片预览弹窗 -->
    <el-dialog
      :append-to-body="true"
      :title="previewTitle"
      :visible.sync="imagePreviewVisible"
      width="60%"
      top="10vh"
      :close-on-click-modal="true"
    <!-- 备注信息 -->
    <el-card class="detail-section" v-if="caseData.remark">
      <div slot="header" class="section-header">
        <span class="section-title">备注信息</span>
      </div>
      <div class="remark-content">
        {{ caseData.remark }}
      </div>
    </el-card>
    <!-- 审批信息模块(状态为已同意或已驳回时显示) -->
    <el-card
      class="detail-section"
      v-if="caseData.reportStatus === '3' || caseData.reportStatus === '4'"
    >
      <div class="image-preview-container">
        <img :src="previewUrl" alt="预览图片" class="preview-image" />
      <div slot="header" class="section-header">
        <span class="section-title">审批信息</span>
      </div>
    </el-dialog>
    <!-- 不支持预览的文件类型 -->
    <el-dialog
      :title="previewTitle"
      :visible.sync="unsupportedPreviewVisible"
      width="400px"
      :close-on-click-modal="true"
      <el-descriptions :column="1" border>
        <el-descriptions-item label="审批结果">
          <el-tag :type="caseData.reportStatus === '3' ? 'success' : 'danger'">
            {{ caseData.reportStatus === "3" ? "已同意" : "已驳回" }}
          </el-tag>
        </el-descriptions-item>
        <el-descriptions-item label="审批人">{{
          caseData.updateBy || "-"
        }}</el-descriptions-item>
        <el-descriptions-item label="审批时间">{{
          formatDateTime(caseData.updateTime)
        }}</el-descriptions-item>
        <el-descriptions-item label="审批意见">{{
          caseData.remark || "无"
        }}</el-descriptions-item>
      </el-descriptions>
    </el-card>
    <el-card
      class="detail-section"
      v-if="
        caseData.isTransport == '2' &&
          caseData.serviceTransport &&
          caseData.serviceTransport.length > 0
      "
    >
      <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 slot="header" class="section-header">
        <span class="section-title">转运信息</span>
        <el-button
          v-if="caseData.reportStatus === '3'"
          type="primary"
          size="small"
          icon="el-icon-truck"
          @click="handleViewTransport"
        >
          查看转运详情
        </el-button>
      </div>
    </el-dialog>
    <div class="detail-footer">
      <el-descriptions :column="2" border>
        <el-descriptions-item
          v-for="transport in caseData.serviceTransport"
          :key="transport.id"
        >
          <!-- 转运单列表 -->
          <div class="transport-info">
            <div class="transport-item">
              <strong>转运单号:</strong> {{ transport.reportId || "-" }}
            </div>
            <div class="transport-item">
              <strong>患者姓名:</strong> {{ transport.patName || "-" }}
            </div>
            <div class="transport-item">
              <strong>出发地点:</strong>
              {{ transport.transportStartPlace || "-" }}
            </div>
            <div class="transport-item">
              <strong>出发时间:</strong>
              {{ formatDateTime(transport.transportStartTime) }}
            </div>
            <div class="transport-item">
              <strong>转运状态:</strong>
              <el-tag :type="getTransportStatusTag(transport)" size="small">
                {{ getTransportStatusText(transport) }}
              </el-tag>
            </div>
            <div class="transport-item">
              <strong>负责协调员:</strong> {{ transport.contactPerson || "-" }}
            </div>
            <div class="transport-item" v-if="transport.remark">
              <strong>备注:</strong> {{ transport.remark }}
            </div>
          </div>
        </el-descriptions-item>
      </el-descriptions>
    </el-card>
    <!-- 无转运信息但需要转运的提示 -->
    <el-card
      class="detail-section"
      v-else-if="caseData.isTransport === '2' && caseData.reportStatus === '3'"
    >
      <div slot="header" class="section-header">
        <span class="section-title">转运信息</span>
        <el-button
          type="primary"
          size="small"
          icon="el-icon-truck"
          @click="handleCreateTransport"
        >
          创建转运单
        </el-button>
      </div>
      <el-alert
        title="该案例需要转运,但尚未创建转运单"
        type="warning"
        description="请点击上方按钮创建转运单"
        show-icon
        :closable="false"
      />
    </el-card>
    <!-- 文件预览弹窗 -->
    <FilePreviewDialog
      :visible="previewVisible"
      :file="currentPreviewFile"
      @close="previewVisible = false"
      @download="handleDownload"
    />
    <div class="detail-footer" v-if="showtitle">
      <el-button @click="handleClose">关闭</el-button>
    </div>
  </div>
@@ -237,247 +405,336 @@
<script>
import pdf from "vue-pdf";
import FilePreviewDialog from "@/components/FilePreviewDialog";
export default {
  name: "CaseDetail",
  components: {
    pdf
    pdf,
    FilePreviewDialog
  },
  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];
    showtitle: {
      type: Boolean,
      default: true
    }
  },
  dicts: ["sys_user_sex", "sys_BloodType"],
  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,
      // 预览相关
      previewVisible: false,
      currentPreviewFile: null,
      // 图片预览相关
      imagePreviewVisible: false,
      // 不支持预览相关
      unsupportedPreviewVisible: false,
      // 通用预览数据
      previewTitle: "",
      previewUrl: "",
      currentFile: null
      imagePreviewUrls: []
    };
  },
  computed: {
    // 收集所有图片URL用于预览
    allImageUrls() {
      if (
        !this.caseData.annexfilesList ||
        !Array.isArray(this.caseData.annexfilesList)
      ) {
        return [];
      }
      return this.caseData.annexfilesList
        .filter(file => this.isImageFile(file.fileName || file.path))
        .map(file => this.getFileUrl(file))
        .filter(url => url);
    }
  },
  methods: {
    handleClose() {
      this.$emit('close');
      this.$emit("close");
    },
    // 获取文件类型
    // 格式化日期时间
    formatDateTime(dateTime) {
      if (!dateTime) return "-";
      return dateTime.replace("T", " ").substring(0, 19);
    },
    // 格式化日期
    formatDate(dateString) {
      if (!dateString) return "-";
      return dateString.split("T")[0];
    },
    getTransportStatusTag(transport) {
      if (!transport.transitStatus) return "info";
      switch (transport.transitStatus.toString()) {
        case "1":
          return "warning"; // 待转运
        case "2":
          return "primary"; // 转运中
        case "3":
          return "success"; // 转运完成
        case "4":
          return "danger"; // 转运取消
        case "5":
          return "info"; // 暂存
        default:
          return "info";
      }
    },
    /** 获取转运状态文本 */
    getTransportStatusText(transport) {
      if (!transport.transitStatus) return "未知";
      switch (transport.transitStatus.toString()) {
        case "1":
          return "待转运";
        case "2":
          return "转运中";
        case "3":
          return "转运完成";
        case "4":
          return "转运取消";
        case "5":
          return "暂存";
        default:
          return "未知";
      }
    },
    /** 查看转运详情 */
    handleViewTransport() {
      if (
        this.caseData.serviceTransport &&
        this.caseData.serviceTransport.length > 0
      ) {
        const transport = this.caseData.serviceTransport[0];
        this.$router.push({
          path: "/business/transport/detail",
          query: {
            id: transport.id,
            caseNo: this.caseData.caseNo
          }
        });
      }
    },
    /** 创建转运单 */
    handleCreateTransport() {
      this.$router.push({
        path: "/business/transport/create",
        query: {
          caseId: this.caseData.id,
          caseNo: this.caseData.caseNo,
          patName: this.caseData.name,
          age: this.caseData.age,
          sex: this.caseData.sex,
          diagnosisname: this.caseData.diagnosisname,
          treatmentHospitalName: this.caseData.treatmenthospitalname
        }
      });
    },
    // 获取完整户籍地址
    getFullRegisterAddress() {
      const {
        registerprovincename,
        registercityname,
        registertownname,
        registercommunityname,
        registeraddress
      } = this.caseData;
      const addressParts = [
        registerprovincename,
        registercityname,
        registertownname,
        registercommunityname,
        registeraddress
      ];
      return addressParts.filter(part => part).join("") || "-";
    },
    // 获取完整现住地址
    getFullResidenceAddress() {
      const {
        residenceprovincename,
        residencecountyname,
        residencetownname,
        residencecommunityname,
        residenceaddress
      } = this.caseData;
      const addressParts = [
        residenceprovincename,
        residencecountyname,
        residencetownname,
        residencecommunityname,
        residenceaddress
      ];
      return addressParts.filter(part => part).join("") || "-";
    },
    // 获取状态文本
    getStatusText(status) {
      const statusMap = {
        "1": "已上报",
        "2": "已阅读",
        "3": "已同意",
        "4": "已驳回"
      };
      return statusMap[status] || "未知状态";
    },
    // 获取状态类型
    getStatusType(status) {
      const statusMap = {
        "1": "info",
        "2": "warning",
        "3": "success",
        "4": "danger"
      };
      return statusMap[status] || "info";
    },
    // 获取年龄单位文本
    getAgeUnitText(unit) {
      const unitMap = {
        year: "岁",
        month: "月",
        day: "天"
      };
      return unitMap[unit] || unit;
    },
    // 获取证件类型文本
    getIdCardTypeText(type) {
      const typeMap = {
        "1": "身份证",
        "2": "护照",
        "3": "军官证"
      };
      return typeMap[type] || type || "-";
    },
    // 文件处理相关方法
    isImageFile(fileName) {
      if (!fileName) return false;
      const imageExtensions = [
        "jpg",
        "jpeg",
        "png",
        "gif",
        "bmp",
        "webp",
        "svg"
      ];
      const extension = fileName
        .split(".")
        .pop()
        .toLowerCase();
      return imageExtensions.includes(extension);
    },
    getFileUrl(file) {
      return file.path || file.fileUrl || "";
    },
    getImagePreviewList(file) {
      // 返回所有图片的URL列表,实现点击任意图片查看所有图片
      return this.allImageUrls;
    },
    getFileIcon(fileName) {
      if (!fileName) return "el-icon-document";
      const ext = fileName
        .split(".")
        .pop()
        .toLowerCase();
      const iconMap = {
        pdf: "el-icon-document",
        doc: "el-icon-document",
        docx: "el-icon-document",
        xls: "el-icon-document",
        xlsx: "el-icon-document",
        jpg: "el-icon-picture",
        jpeg: "el-icon-picture",
        png: "el-icon-picture",
        gif: "el-icon-picture"
      };
      return iconMap[ext] || "el-icon-document";
    },
    getFileTypeText(fileName) {
      if (!fileName) return "文件";
      const ext = fileName
        .split(".")
        .pop()
        .toLowerCase();
      const typeMap = {
        pdf: "PDF文档",
        doc: "Word文档",
        docx: "Word文档",
        xls: "Excel表格",
        xlsx: "Excel表格",
        jpg: "图片",
        jpeg: "图片",
        png: "图片",
        gif: "图片"
      };
      return typeMap[ext] || "文件";
    },
    canPreview(fileName) {
      if (!fileName) return false;
      const previewableExtensions = ["pdf", "jpg", "jpeg", "png", "gif"];
      const extension = fileName
        .split(".")
        .pop()
        .toLowerCase();
      return previewableExtensions.includes(extension);
    },
    // 文件预览
    handlePreview(file) {
      this.currentPreviewFile = {
        fileName: file.fileName,
        fileUrl: this.getFileUrl(file),
        fileType: this.getFileType(file.fileName)
      };
      this.previewVisible = true;
    },
    getFileType(fileName) {
      const extension = fileName.split('.').pop().toLowerCase();
      if (!fileName) return "other";
      const extension = fileName
        .split(".")
        .pop()
        .toLowerCase();
      const imageTypes = ["jpg", "jpeg", "png", "gif", "bmp", "webp"];
      const pdfTypes = ["pdf"];
      const officeTypes = ["doc", "docx", "xls", "xlsx"];
      if (imageTypes.includes(extension)) return "image";
      if (pdfTypes.includes(extension)) return "pdf";
      if (officeTypes.includes(extension)) return "office";
      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("开始下载文件");
    },
      const fileUrl = this.getFileUrl(file);
      const fileName = file.fileName;
    // 专用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];
      if (fileUrl) {
        const link = document.createElement("a");
        link.href = fileUrl;
        link.download = fileName;
        link.style.display = "none";
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
        this.$message.success("开始下载文件");
      } else {
        this.$message.warning("文件路径不存在,无法下载");
      }
    }
  }
};
@@ -488,83 +745,144 @@
  padding: 0 20px;
}
/* PDF预览对话框样式 */
.pdf-preview-dialog {
  margin-top: 5vh !important;
.detail-section {
  margin-bottom: 16px;
}
.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;
.section-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
}
.zoom-controls {
  margin: 0 15px;
.section-title {
  font-size: 16px;
  font-weight: bold;
  color: #303133;
}
/* PDF视图区域样式 */
.pdf-viewport {
  flex: 1;
  overflow: auto;
  padding: 20px;
  background: #f8f9fa;
/* 附件样式 */
.detail-attachments {
  padding: 10px 0;
}
.attachment-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 16px;
}
.attachment-card {
  display: flex;
  flex-direction: column;
  align-items: center;
}
/* 图片附件样式 */
.image-attachment {
  border-radius: 4px;
  border: 1px solid #ebeef5;
  cursor: pointer;
  transition: all 0.3s;
  margin-bottom: 8px;
}
.image-attachment:hover {
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
  transform: translateY(-2px);
}
.image-info {
  text-align: center;
  width: 100%;
}
.image-info .file-name {
  font-size: 12px;
  color: #606266;
  margin-bottom: 4px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 120px;
}
.image-info .file-actions {
  display: flex;
  justify-content: center;
  align-items: flex-start;
  gap: 8px;
}
/* 图片预览样式 */
.image-preview-container {
.image-loading,
.image-error {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  height: 100%;
  color: #909399;
  font-size: 12px;
}
.image-loading i,
.image-error i {
  font-size: 20px;
  margin-bottom: 4px;
}
/* 文件卡片样式 */
.file-card {
  width: 100%;
  min-height: 60px;
  margin-bottom: 8px;
}
.file-content {
  display: flex;
  align-items: center;
  padding: 8px;
}
.file-icon {
  font-size: 24px;
  margin-right: 12px;
  color: #409eff;
  flex-shrink: 0;
}
.file-info {
  flex: 1;
  min-width: 0;
}
.file-name {
  font-size: 13px;
  font-weight: 500;
  margin-bottom: 4px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.file-meta {
  display: flex;
  justify-content: space-between;
  font-size: 12px;
  color: #909399;
}
.file-actions {
  text-align: center;
  padding: 20px;
  padding: 8px;
  border-top: 1px solid #f0f0f0;
}
.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;
  }
/* 备注样式 */
.remark-content {
  padding: 12px;
  line-height: 1.6;
  color: #606266;
  white-space: pre-line;
}
.detail-footer {
@@ -579,4 +897,19 @@
  background-color: #f5f7fa;
  font-weight: bold;
}
/* 转运信息样式 */
.transport-info {
  padding: 10px;
}
.transport-item {
  margin-bottom: 8px;
  line-height: 1.6;
}
.transport-item strong {
  display: inline-block;
  width: 100px;
  color: #606266;
}
</style>