WXL
4 天以前 c4599aa279fd2f90b741608392e056fbae2282d5
src/views/business/course/components/DonationConfirmStage.vue
@@ -1,217 +1,865 @@
<template>
  <base-stage :stage-data="stageData" :case-info="caseInfo">
    <template #header>
      <el-alert
        :title="`捐献确认 - ${getStatusText()}`"
        :type="getAlertType()"
        :description="getAlertDescription()"
        show-icon
        :closable="false"
      />
    </template>
  <div class="confirmation-detail">
    <!-- <case-basic-info :case-id="caseId" :show-attachment="true":column="3" /> -->
    <el-row :gutter="20" style="margin-top: 20px;">
      <el-col :span="8">
        <el-card>
          <div slot="header" class="card-header">
            <span>确认信息概览</span>
          </div>
          <div class="confirm-overview">
            <div class="overview-item">
              <span class="label">确认状态:</span>
              <el-tag :type="getStatusTag(confirmationDetails.status)">
                {{ getStatusText(confirmationDetails.status) }}
              </el-tag>
            </div>
            <div class="overview-item">
              <span class="label">确认时间:</span>
              <span>{{ formatTime(confirmationDetails.confirmTime) }}</span>
            </div>
            <div class="overview-item">
              <span class="label">确认方式:</span>
              <span>{{ confirmationDetails.method }}</span>
            </div>
            <div class="overview-item">
              <span class="label">协调员:</span>
              <span>{{ confirmationDetails.coordinator }}</span>
            </div>
          </div>
        </el-card>
      </el-col>
      <el-col :span="8">
        <el-card>
          <div slot="header" class="card-header">
            <span>家属同意情况</span>
          </div>
          <el-descriptions :column="1" size="small">
            <el-descriptions-item label="主要家属">
              {{ familyConsent.mainRelative }}
            </el-descriptions-item>
            <el-descriptions-item label="同意状态">
              <el-tag :type="familyConsent.consented ? 'success' : 'warning'">
                {{ familyConsent.consented ? '已同意' : '待确认' }}
              </el-tag>
            </el-descriptions-item>
            <el-descriptions-item label="签字时间">
              {{ formatTime(familyConsent.signTime) }}
            </el-descriptions-item>
            <el-descriptions-item label="关系证明">
              {{ familyConsent.relationshipProof }}
            </el-descriptions-item>
          </el-descriptions>
        </el-card>
      </el-col>
      <el-col :span="8">
        <el-card>
          <div slot="header" class="card-header">
            <span>法律文件</span>
          </div>
          <div class="document-list">
            <div v-for="doc in legalDocuments" :key="doc.name" class="document-item">
              <div class="doc-info">
                <i :class="doc.icon" style="color: #409EFF; margin-right: 8px;"></i>
                <span>{{ doc.name }}</span>
              </div>
              <el-tag :type="doc.status === 'completed' ? 'success' : 'warning'" size="small">
                {{ doc.status === 'completed' ? '已签署' : '待签署' }}
              </el-tag>
            </div>
          </div>
        </el-card>
      </el-col>
    </el-row>
    <el-card style="margin-top: 20px;">
      <div slot="header" class="card-header">
        <span>捐献意愿确认书</span>
    <el-card class="detail-card">
      <div slot="header" class="clearfix">
        <span class="detail-title">捐献确认信息</span>
      </div>
      <div class="consent-content">
        <p>本人/家属确认,在充分了解器官捐献的相关信息后,自愿同意进行器官捐献。</p>
        <el-divider />
        <el-descriptions :column="2" border>
          <el-descriptions-item label="捐献者姓名">{{ caseInfo.donorName }}</el-descriptions-item>
          <el-descriptions-item label="捐献者身份证号">{{ confirmationDetails.idNumber }}</el-descriptions-item>
          <el-descriptions-item label="捐献器官类型">{{ confirmationDetails.organs }}</el-descriptions-item>
          <el-descriptions-item label="捐献用途">{{ confirmationDetails.purpose }}</el-descriptions-item>
          <el-descriptions-item label="签字人">{{ familyConsent.mainRelative }}</el-descriptions-item>
          <el-descriptions-item label="签字日期">{{ formatTime(familyConsent.signTime) }}</el-descriptions-item>
        </el-descriptions>
      </div>
      <el-descriptions title="协调员信息" :column="descriptionColumn" border size="small">
        <el-descriptions-item label="协调员1">{{ form.coordinatedusernameo || '-' }}</el-descriptions-item>
        <el-descriptions-item label="协调员2">{{ form.coordinatedusernamet || '-' }}</el-descriptions-item>
      </el-descriptions>
      <el-descriptions title="捐献决定" :column="descriptionColumn" border size="small" style="margin-top: 16px;">
        <el-descriptions-item label="捐献决定">
          <template v-if="organdecision && organdecision.length">
            <el-tag v-for="(item, i) in organdecision" :key="i" size="small" style="margin-right: 8px;">{{ item }}</el-tag>
          </template>
          <template v-else>-</template>
        </el-descriptions-item>
        <el-descriptions-item v-if="organdecision && organdecision.includes('其他')" label="其他捐献决定">
          {{ organdecisionOther || '-' }}
        </el-descriptions-item>
      </el-descriptions>
      <el-descriptions title="家属意见备注" :column="1" border size="small" style="margin-top: 16px;">
        <el-descriptions-item label="家属意见备注">{{ form.relativeRemark || '-' }}</el-descriptions-item>
      </el-descriptions>
    </el-card>
  </base-stage>
    <!-- 亲属确认信息 -->
    <el-card class="detail-card">
      <div slot="header" class="clearfix">
        <span class="detail-title">亲属确认信息</span>
      </div>
      <el-table :data="familyMemberList" size="small" border>
        <el-table-column label="序号" width="60" align="center">
          <template slot-scope="scope">
            {{ scope.$index + 1 }}
          </template>
        </el-table-column>
        <el-table-column label="姓名" prop="name" min-width="120">
          <template slot-scope="scope">
            <span :class="{ 'main-family': scope.$index === 0 }">{{
              scope.row.name
            }}</span>
          </template>
        </el-table-column>
        <el-table-column label="与捐赠者关系" prop="relation" min-width="140">
          <template slot-scope="scope">
            <dict-tag
              :options="dict.type.sys_FamilyRelation"
              :value="scope.row.relation"
            />
          </template>
        </el-table-column>
        <el-table-column label="身份证号" prop="idcard" min-width="180">
          <template slot-scope="scope">
            <span v-if="scope.$index === 0">{{ scope.row.idcard }}</span>
            <span v-else style="color: #909399;">-</span>
          </template>
        </el-table-column>
        <el-table-column label="联系电话" prop="phone" min-width="130">
          <template slot-scope="scope">
            <span v-if="scope.$index === 0">{{ scope.row.phone }}</span>
            <span v-else style="color: #909399;">-</span>
          </template>
        </el-table-column>
        <el-table-column label="类型" width="70" align="center">
          <template slot-scope="scope">
            <el-tag v-if="scope.$index === 0" type="warning" size="small"
              >主要</el-tag
            >
            <el-tag v-else type="info" size="small">其他</el-tag>
          </template>
        </el-table-column>
      </el-table>
    </el-card>
    <!-- 附件信息 - 按类型分类 -->
    <el-card class="attachment-card">
      <div slot="header" class="clearfix">
        <span class="detail-title">相关附件</span>
      </div>
      <el-tabs v-model="activeAttachmentType" type="card">
        <el-tab-pane
          v-for="type in attachmentTypes"
          :key="type.value"
          :label="type.label"
          :name="type.value"
        >
          <div class="attachment-section">
            <div class="attachment-list">
              <el-table
                :data="getAttachmentsByType(type.value)"
                size="small"
                v-loading="attachmentLoading"
                style="width: 100%;"
              >
                <el-table-column label="文件名" min-width="200">
                  <template slot-scope="scope">
                    <i
                      class="el-icon-document"
                      style="color: #409EFF; margin-right: 8px;"
                    ></i>
                    <span class="file-name">{{ scope.row.fileName }}</span>
                  </template>
                </el-table-column>
                <el-table-column label="文件类型" width="90" align="center">
                  <template slot-scope="scope">
                    <el-tag size="small">{{
                      getFileType(scope.row.fileName)
                    }}</el-tag>
                  </template>
                </el-table-column>
                <el-table-column label="文件大小" width="90" align="center">
                  <template slot-scope="scope">
                    <span>{{ formatFileSize(scope.row.fileSize) }}</span>
                  </template>
                </el-table-column>
                <el-table-column label="上传时间" width="155" align="center">
                  <template slot-scope="scope">
                    <span>{{ formatDateTime(scope.row.uploadTime) }}</span>
                  </template>
                </el-table-column>
                <el-table-column label="操作" width="80" align="center">
                  <template slot-scope="scope">
                    <el-button
                      size="mini"
                      type="primary"
                      @click="handlePreview(scope.row)"
                    >
                      预览
                    </el-button>
                  </template>
                </el-table-column>
              </el-table>
              <div
                v-if="getAttachmentsByType(type.value).length === 0"
                class="empty-attachment"
              >
                <el-empty
                  :description="`暂无${type.label}附件`"
                  :image-size="80"
                ></el-empty>
              </div>
            </div>
          </div>
        </el-tab-pane>
      </el-tabs>
    </el-card>
    <!-- 文件预览弹窗 -->
    <FilePreviewDialog
      :visible="previewVisible"
      :file="currentPreviewFile"
      @close="previewVisible = false"
      @download="handleDownload"
    />
  </div>
</template>
<script>
import BaseStage from './BaseStage.vue';
import { relativesList, relativesEdit, relativesAdd } from "@/api/businessApi";
import FilePreviewDialog from "@/components/FilePreviewDialog";
import CaseBasicInfo from "@/components/CaseBasicInfo";
import { getToken } from "@/utils/auth";
import readonlyDescriptionsMixin from "./readonlyDescriptionsMixin";
export default {
  name: 'DonationConfirmStage',
  components: { BaseStage },
  props: {
    stageData: {
      type: Object,
      default: () => ({})
    },
    caseInfo: {
      type: Object,
      default: () => ({})
  name: "ConfirmationDetail",
  components: {
    FilePreviewDialog,
    CaseBasicInfo
  },
  mixins: [readonlyDescriptionsMixin],
  dicts: ["sys_FamilyRelation"],
   props: {
    infoid: {
      type: String,
      default: true
    }
  },
  data() {
    return {
      confirmationDetails: {
        status: 'completed',
        confirmTime: '2023-12-03 11:00:00',
        method: '家属书面同意',
        coordinator: '赵协调员',
        idNumber: '110101199001011234',
        organs: '心脏、肝脏、肾脏、角膜',
        purpose: '临床移植'
      caseId: null,
      isEdit: false,
      form: {
        id: undefined,
        infoid: undefined,
        caseNo: "",
        name: "",
        sex: "",
        age: "",
        diagnosisname: "",
        treatmenthospitalname: "",
        coordinatedusernameo: "",
        coordinatedusernamet: "",
        responsibleusername: "",
        relativeconfirmationsign: "0",
        signdate: "",
        relativeconfirmationsignname: "",
        signfamilyrelations: "",
        relativeidcardno: "",
        relativephone: "",
        relativeRemark: "",
        assessannex: "",
        otherFamilyMembers: ""
      },
      familyConsent: {
        mainRelative: '张三父亲',
        consented: true,
        signTime: '2023-12-03 10:45:00',
        relationshipProof: '户口本关系证明'
      // 统一亲属列表(第一条为主要亲属,其余为其他亲属)
      familyMemberList: [],
      // 当前编辑的家属(弹窗用)
      currentFamilyMember: {
        name: "",
        relation: "",
        phone: "",
        idcard: "",
        isMain: false
      },
      legalDocuments: [
        { name: '器官捐献同意书', icon: 'el-icon-document', status: 'completed' },
        { name: '家属关系证明', icon: 'el-icon-document', status: 'completed' },
        { name: '医疗免责声明', icon: 'el-icon-document', status: 'completed' },
        { name: '隐私保护协议', icon: 'el-icon-document', status: 'completed' }
      ]
      isEditFamilyMember: false,
      editFamilyMemberIndex: -1,
      familyDialogVisible: false,
      familyDialogTitle: "添加家属",
      uploadAction: process.env.VUE_APP_BASE_API + "/common/upload",
      headers: {
        Authorization: "Bearer " + getToken()
      },
      organdecision: [],
      organdecisionOther: "",
      organselection: [
        "肝脏",
        "肾脏",
        "心脏",
        "肺脏",
        "胰腺",
        "小肠",
        "眼角膜",
        "其他"
      ],
      loading: false,
      saveLoading: false,
      activeAttachmentType: "1",
      attachmentLoading: false,
      uploadDialogVisible: false,
      uploadLoading: false,
      tempFileList: [],
      currentUploadType: "",
      previewVisible: false,
      currentPreviewFile: null,
      attachmentTypes: [
        { value: "1", label: "人体器官潜在捐献者登记表" },
        { value: "2", label: "人体器官捐献亲属确认登记表" },
        { value: "3", label: "捐献者及直系亲属身份证、户口簿相关证明" },
        { value: "4", label: "公民身故后人体器官(角膜)遗体捐献告知书" },
        { value: "5", label: "脑死亡判定知情同意书" },
        { value: "6", label: "心死亡判定知情同意书" }
      ],
      attachmentData: {
        "1": [],
        "2": [],
        "3": [],
        "4": [],
        "5": [],
        "6": []
      }
    };
  },
  computed: {
    getCurrentTypeLabel() {
      const type = this.attachmentTypes.find(
        t => t.value === this.currentUploadType
      );
      return type ? type.label : "";
    }
  },
  created() {
    this.infoid = this.infoid;
    this.caseId = this.infoid;
    if (this.infoid) {
      this.getDetail(this.infoid);
    }
  },
  methods: {
    getStatusText() {
      const status = this.stageData.status;
      return status === 'completed' ? '已完成' :
             status === 'in_progress' ? '进行中' : '未开始';
    async getDetail(infoid) {
      this.loading = true;
      try {
        const response = await relativesList({ infoid });
        if (response.code === 200) {
          this.handleDetailData(response);
        } else {
          this.$message.error("获取详情失败:" + (response.msg || "未知错误"));
        }
      } catch (error) {
        console.error("获取捐献确认详情失败:", error);
        this.$message.error("获取详情失败");
      } finally {
        this.loading = false;
      }
    },
    getAlertType() {
      const status = this.stageData.status;
      return status === 'completed' ? 'success' :
             status === 'in_progress' ? 'warning' : 'info';
    },
    getAlertDescription() {
      const status = this.stageData.status;
      return status === 'completed' ? '捐献确认流程已完成,所有法律文件已签署' :
             status === 'in_progress' ? '捐献确认流程正在进行中' : '等待开始捐献确认流程';
    },
    getStatusTag(status) {
      const map = {
        'completed': 'success',
        'in_progress': 'warning',
        'pending': 'info'
    handleDetailData(response) {
      let detailData = null;
      if (response.data) {
        if (Array.isArray(response.data)) {
          detailData = response.data[0] || {};
        } else if (response.data.rows && Array.isArray(response.data.rows)) {
          detailData = response.data.rows[0] || {};
        } else if (Array.isArray(response.data.list)) {
          detailData = response.data.list[0] || {};
        } else {
          detailData = response.data;
        }
      } else {
        detailData = response;
      }
      this.form = {
        ...this.form,
        id: detailData.id || this.$route.query.id,
        infoid: detailData.infoid || this.infoid,
        caseNo: detailData.caseNo || "",
        name: detailData.name || "",
        sex: detailData.sex || "",
        age: detailData.age || "",
        diagnosisname: detailData.diagnosisname || "",
        treatmenthospitalname: detailData.treatmenthospitalname || "",
        coordinatedusernameo: detailData.coordinatedusernameo || "",
        coordinatedusernamet: detailData.coordinatedusernamet || "",
        responsibleusername: detailData.responsibleusername || "",
        relativeconfirmationsign: detailData.relativeconfirmationsign || "0",
        signdate: detailData.signdate,
        relativeconfirmationsignname:
          detailData.relativeconfirmationsignname || "",
        signfamilyrelations: detailData.signfamilyrelations || "",
        relativeidcardno: detailData.relativeidcardno || "",
        relativephone: detailData.relativephone || "",
        relativeRemark: detailData.relativeRemark || "",
        assessannex: detailData.assessannex || ""
      };
      return map[status] || 'info';
      // 初始化家属列表
      this.familyMemberList = [];
      if (detailData.relativeconfirmationsignname) {
        this.familyMemberList.push({
          name: detailData.relativeconfirmationsignname,
          relation: detailData.signfamilyrelations || "",
          phone: detailData.relativephone || "",
          idcard: detailData.relativeidcardno || ""
        });
      }
      if (detailData.otherFamilyMembers) {
        try {
          const otherMembers =
            typeof detailData.otherFamilyMembers === "string"
              ? JSON.parse(detailData.otherFamilyMembers)
              : detailData.otherFamilyMembers || [];
          otherMembers.forEach(member => {
            this.familyMemberList.push({
              name: member.name,
              relation: member.relation,
              phone: member.phone || "",
              idcard: member.idcard || ""
            });
          });
        } catch (e) {
          console.warn("解析其他家属数据失败:", e);
        }
      }
      if (detailData.organdecision) {
        this.organdecision = Array.isArray(detailData.organdecision)
          ? detailData.organdecision
          : detailData.organdecision.split(",");
      }
      this.processAssessannexData();
    },
    processAssessannexData() {
      if (this.form.assessannex) {
        try {
          const annexData =
            typeof this.form.assessannex === "string"
              ? JSON.parse(this.form.assessannex)
              : this.form.assessannex;
          Object.keys(this.attachmentData).forEach(key => {
            this.attachmentData[key] = [];
          });
          if (Array.isArray(annexData)) {
            annexData.forEach(attachment => {
              const type = attachment.type || "1";
              if (this.attachmentData[type]) {
                this.attachmentData[type].push(attachment);
              }
            });
          }
        } catch (error) {
          console.warn("assessannex数据解析失败:", error);
        }
      }
    },
    getAttachmentsByType(type) {
      console.log(type);
      console.log(this.attachmentData[type]);
      return this.attachmentData[type] || [];
    },
    openUploadDialog(type) {
      this.currentUploadType = type;
      this.tempFileList = [];
      this.uploadDialogVisible = true;
      this.$nextTick(() => {
        if (this.$refs.uploadRef) {
          this.$refs.uploadRef.clearFiles();
        }
      });
    },
    beforeUpload(file) {
      const allowedTypes = [
        "application/pdf",
        "image/jpeg",
        "image/png",
        "application/msword",
        "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
      ];
      const maxSize = 10 * 1024 * 1024;
      const isTypeOk =
        allowedTypes.includes(file.type) ||
        file.name.endsWith(".pdf") ||
        file.name.endsWith(".jpg") ||
        file.name.endsWith(".jpeg") ||
        file.name.endsWith(".png") ||
        file.name.endsWith(".doc") ||
        file.name.endsWith(".docx");
      if (!isTypeOk) {
        this.$message.error(
          "文件格式不支持,请上传pdf、jpg、png、doc或docx格式文件"
        );
        return false;
      }
      if (file.size > maxSize) {
        this.$message.error("文件大小不能超过10MB");
        return false;
      }
      return true;
    },
    handleFileChange(file, fileList) {
      this.tempFileList = fileList;
    },
    handleTempRemove(file, fileList) {
      this.tempFileList = fileList;
    },
    handleUploadSuccess(response, file) {
      if (response.code !== 200) {
        this.$message.error(response.msg || "上传失败");
        return;
      }
      const newAttachment = {
        id: Date.now(),
        fileName: file.name,
        fileUrl: response.url,
        fileSize: file.size,
        fileType: this.getFileExtension(file.name),
        type: this.currentUploadType,
        uploadTime: this.getCurrentTime(),
        uploader: "当前用户"
      };
      this.attachmentData[this.currentUploadType].push(newAttachment);
      console.log(this.attachmentData,'this.attachmentData');
      this.updateAssessannexField();
      this.$message.success("上传成功");
      this.uploadLoading = false;
      this.uploadDialogVisible = false;
      this.tempFileList = [];
    },
    submitUpload() {
      if (this.tempFileList.length === 0) {
        this.$message.warning("请先选择要上传的文件");
        return;
      }
      this.uploadLoading = true;
      this.$refs.uploadRef.submit();
    },
    handleRemoveAttachment(type, index) {
      this.$confirm("确定要删除这个附件吗?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      })
        .then(() => {
          if (this.attachmentData[type] && this.attachmentData[type][index]) {
            this.attachmentData[type].splice(index, 1);
            this.$message.success("附件删除成功");
            this.updateAssessannexField();
          }
        })
        .catch(() => {});
    },
    // 家属操作方法
    openFamilyDialog(isMain) {
      this.isEditFamilyMember = false;
      this.editFamilyMemberIndex = -1;
      this.familyDialogTitle = "添加其他家属";
      // 如果还没有任何家属,则添加主要亲属
      if (this.familyMemberList.length === 0) {
        this.currentFamilyMember = {
          name: "",
          relation: "",
          phone: "",
          idcard: "",
          isMain: true
        };
        this.familyDialogTitle = "添加主要亲属";
      } else {
        this.currentFamilyMember = {
          name: "",
          relation: "",
          phone: "",
          idcard: "",
          isMain: false
        };
      }
      this.familyDialogVisible = true;
    },
    editFamilyMember(index) {
      this.isEditFamilyMember = true;
      this.editFamilyMemberIndex = index;
      const member = this.familyMemberList[index];
      this.currentFamilyMember = {
        name: member.name,
        relation: member.relation,
        phone: member.phone || "",
        idcard: member.idcard || "",
        isMain: index === 0
      };
      this.familyDialogTitle = index === 0 ? "编辑主要亲属" : "编辑其他家属";
      this.familyDialogVisible = true;
    },
    deleteFamilyMember(index) {
      if (index === 0) {
        this.$message.warning("主要亲属不可删除");
        return;
      }
      this.$confirm("确认删除该家属?", "提示", { type: "warning" })
        .then(() => {
          this.familyMemberList.splice(index, 1);
          this.updateFamilyMemberField();
        })
        .catch(() => {});
    },
    saveFamilyMember() {
      if (!this.currentFamilyMember.name) {
        this.$message.warning("请输入姓名");
        return;
      }
      if (!this.currentFamilyMember.relation) {
        this.$message.warning("请选择与捐赠者关系");
        return;
      }
      // 如果是主要亲属,验证身份证和电话
      if (this.currentFamilyMember.isMain) {
        if (!this.currentFamilyMember.idcard) {
          this.$message.warning("请输入主要亲属的身份证号");
          return;
        }
        if (
          !/^(\d{15}|\d{18}|\d{17}(\d|X|x))$/.test(
            this.currentFamilyMember.idcard
          )
        ) {
          this.$message.warning("请输入正确的身份证号");
          return;
        }
        if (!this.currentFamilyMember.phone) {
          this.$message.warning("请输入主要亲属的联系电话");
          return;
        }
        if (!/^1[3-9]\d{9}$/.test(this.currentFamilyMember.phone)) {
          this.$message.warning("请输入正确的手机号");
          return;
        }
      }
      const memberData = {
        name: this.currentFamilyMember.name,
        relation: this.currentFamilyMember.relation,
        phone: this.currentFamilyMember.isMain
          ? this.currentFamilyMember.phone
          : "",
        idcard: this.currentFamilyMember.isMain
          ? this.currentFamilyMember.idcard
          : ""
      };
      if (this.isEditFamilyMember) {
        this.familyMemberList.splice(this.editFamilyMemberIndex, 1, memberData);
      } else {
        this.familyMemberList.push(memberData);
      }
      this.updateFamilyMemberField();
      this.familyDialogVisible = false;
      this.$message.success(this.isEditFamilyMember ? "编辑成功" : "添加成功");
    },
    updateFamilyMemberField() {
      if (this.familyMemberList.length > 0) {
        const mainMember = this.familyMemberList[0];
        this.form.relativeconfirmationsignname = mainMember.name;
        this.form.signfamilyrelations = mainMember.relation;
        this.form.relativeidcardno = mainMember.idcard || "";
        this.form.relativephone = mainMember.phone || "";
        const otherMembers = this.familyMemberList.slice(1).map(member => ({
          name: member.name,
          relation: member.relation,
          phone: member.phone || "",
          idcard: member.idcard || ""
        }));
        this.form.otherFamilyMembers = JSON.stringify(otherMembers);
      } else {
        this.form.relativeconfirmationsignname = "";
        this.form.signfamilyrelations = "";
        this.form.relativeidcardno = "";
        this.form.relativephone = "";
        this.form.otherFamilyMembers = "[]";
      }
    },
    updateAssessannexField() {
      const allAttachments = [];
      Object.values(this.attachmentData).forEach(attachments => {
        allAttachments.push(...attachments);
      });
      this.form.assessannex = JSON.stringify(allAttachments);
    },
    handlePreview(file) {
      this.currentPreviewFile = {
        fileName: file.fileName,
        fileUrl: file.fileUrl,
        fileType: this.getFileType(file.fileName)
      };
      this.previewVisible = true;
    },
    handleDownload(file) {
      const fileUrl = file.fileUrl;
      const fileName = file.fileName;
      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("文件路径不存在,无法下载");
      }
    },
    getFileType(fileName) {
      if (!fileName) return "other";
      const extension = this.getFileExtension(fileName);
      const imageTypes = ["jpg", "jpeg", "png"];
      const pdfTypes = ["pdf"];
      const officeTypes = ["doc", "docx"];
      if (imageTypes.includes(extension)) return "image";
      if (pdfTypes.includes(extension)) return "pdf";
      if (officeTypes.includes(extension)) return "office";
      return "other";
    },
    getFileExtension(filename) {
      return filename
        .split(".")
        .pop()
        .toLowerCase();
    },
    formatFileSize(size) {
      if (!size) return "0 B";
      const k = 1024;
      const sizes = ["B", "KB", "MB", "GB"];
      const i = Math.floor(Math.log(size) / Math.log(k));
      return parseFloat((size / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
    },
    formatDateTime(dateTime) {
      if (!dateTime) return "";
      try {
        const date = new Date(dateTime);
        if (isNaN(date.getTime())) return dateTime;
        const year = date.getFullYear();
        const month = String(date.getMonth() + 1).padStart(2, "0");
        const day = String(date.getDate()).padStart(2, "0");
        const hours = String(date.getHours()).padStart(2, "0");
        const minutes = String(date.getMinutes()).padStart(2, "0");
        return `${year}-${month}-${day} ${hours}:${minutes}`;
      } catch (error) {
        return dateTime;
      }
    },
    getCurrentTime() {
      const now = new Date();
      return `${now.getFullYear()}-${(now.getMonth() + 1)
        .toString()
        .padStart(2, "0")}-${now
        .getDate()
        .toString()
        .padStart(2, "0")} ${now
        .getHours()
        .toString()
        .padStart(2, "0")}:${now
        .getMinutes()
        .toString()
        .padStart(2, "0")}:${now
        .getSeconds()
        .toString()
        .padStart(2, "0")}`;
    },
    accomplish() {
      this.$confirm("是否完成该案例捐献确认步骤?", "提醒", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      })
        .then(() => {
          this.form.state = 3;
          this.handleSave();
        })
        .catch(() => {});
    },
    async handleSave() {
      try {
        await this.$refs.form.validate();
        this.saveLoading = true;
        this.updateFamilyMemberField();
        this.updateAssessannexField();
        const saveData = {
          ...this.form,
          infoid: this.infoid,
          organdecision: this.organdecision.join(","),
          organdecisionOther: this.organdecisionOther
        };
        if (saveData.state == 1 || !saveData.state) {
          saveData.state = 2;
        }
        let response = null;
        if (saveData.id) {
          response = await relativesEdit(saveData);
        } else {
          response = await relativesAdd(saveData);
        }
        if (response.code === 200) {
          this.$message.success("保存成功");
          this.$router.push("/case/affirm");
        } else {
          this.$message.error("保存失败:" + (response.msg || "未知错误"));
        }
      } catch (error) {
        if (error !== "cancel") {
          console.error("保存失败:", error);
          this.$message.error("保存失败");
        }
      } finally {
        this.saveLoading = false;
      }
    }
  }
};
</script>
<style scoped>
.confirm-overview {
  padding: 10px 0;
.confirmation-detail {
  padding: 20px;
}
.overview-item {
.detail-card {
  margin-bottom: 20px;
}
.main-family {
  font-weight: bold;
  color: #e6a23c;
}
.attachment-card {
  margin-bottom: 20px;
}
.detail-title {
  font-size: 16px;
  font-weight: bold;
  margin-right: 20px;
}
.attachment-section {
  padding: 15px;
}
.attachment-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 15px;
  padding: 8px 0;
  border-bottom: 1px solid #f0f0f0;
  padding-bottom: 10px;
  border-bottom: 1px solid #ebeef5;
}
.overview-item .label {
.upload-title {
  font-size: 14px;
  font-weight: 600;
  color: #303133;
}
.attachment-list {
  margin-top: 15px;
}
.empty-attachment {
  text-align: center;
  padding: 30px 0;
  color: #909399;
}
.file-name {
  font-size: 13px;
  color: #606266;
  font-weight: 500;
}
.document-list {
  padding: 10px 0;
}
.document-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
  padding: 8px 12px;
  border: 1px solid #e4e7ed;
  border-radius: 4px;
}
.doc-info {
  display: flex;
  align-items: center;
}
.consent-content {
  padding: 20px;
  line-height: 1.6;
}
</style>