WXL
2026-03-13 45680b99ccdfb0d323088c57c237e0bc714a8e0b
青岛opo维护
已删除1个文件
已修改9个文件
3078 ■■■■ 文件已修改
src/views/business/affirm/affirmInfo.vue 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/assess/assessInfo copy.vue 1306 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/assess/components/OrganAssessmentForm.vue 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/maintain/components/BloodRoutinePanel.vue 324 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/maintain/components/LiverKidneyPanel.vue 362 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/maintain/components/UrineRoutinePanel.vue 324 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/maintain/maintainInfo.vue 374 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/project/DonationProcess/index.vue 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/project/donatebaseinfo/EditCaseModal.vue 362 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/project/donatebaseinfo/index.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/affirm/affirmInfo.vue
@@ -125,9 +125,9 @@
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="与捐赠者关系" prop="familyrelations">
            <el-form-item label="与捐赠者关系" prop="signfamilyrelations">
              <el-select
                v-model="form.familyrelations"
                v-model="form.signfamilyrelations"
                placeholder="请选择与捐赠者关系"
              >
                <el-option
@@ -370,7 +370,7 @@
        relativeconfirmationsign: "0",
        signdate: "",
        relativeconfirmationsignname: "",
        familyrelations: "",
        signfamilyrelations: "",
        relativeidcardno: "",
        relativephone: "",
        relativeRemark: "",
@@ -498,7 +498,7 @@
        signdate: detailData.signdate,
        relativeconfirmationsignname:
          detailData.relativeconfirmationsignname || "",
        familyrelations: detailData.familyrelations || "",
        signfamilyrelations: detailData.signfamilyrelations || "",
        relativeidcardno: detailData.relativeidcardno || "",
        relativephone: detailData.relativephone || "",
        relativeRemark: detailData.relativeRemark || "",
@@ -511,6 +511,8 @@
          ? detailData.organdecision
          : detailData.organdecision.split(",");
      }
      console.log(this.organdecision,'this.organdecision');
      // å¤„理附件数据 - ä»Žassessannex字段解析JSON并按类型分类
      this.processAssessannexData();
src/views/business/assess/assessInfo copy.vue
ÎļþÒÑɾ³ý
src/views/business/assess/components/OrganAssessmentForm.vue
@@ -369,6 +369,8 @@
    /** ä¸Šä¼ æˆåŠŸå¤„ç† */
    handleUploadSuccess({ file, fileList, response }) {
      console.log(response,'response');
      if (response.code === 200) {
        console.log(response, "上传数据");
src/views/business/maintain/components/BloodRoutinePanel.vue
@@ -129,12 +129,80 @@
        <span class="attachment-title">附件上传</span>
        <span class="attachment-tip">支持上传检验报告单等文件 (最多10个)</span>
      </div>
      <upload-attachment
        :file-list="attachments"
      <!-- ä½¿ç”¨ UploadAttachment ç»„ä»¶ -->
      <UploadAttachment
        ref="uploadAttachment"
        :file-list="attachmentFileList"
        :limit="attachmentLimit"
        :accept="attachmentAccept"
        :multiple="true"
        @change="handleAttachmentChange"
        :limit="10"
        :accept="'.pdf,.jpg,.jpeg,.png,.doc,.docx'"
        @upload-success="handleUploadSuccess"
        @upload-error="handleUploadError"
        @remove="handleAttachmentRemove"
      />
      <!-- é™„件列表展示 -->
      <div class="attachment-list" v-if="attachments && attachments.length > 0">
        <div class="list-title">已上传附件 ({{ attachments.length }})</div>
        <el-table :data="attachments" style="width: 100%" size="small">
          <el-table-column label="文件名" min-width="200">
            <template slot-scope="scope">
              <i
                class="el-icon-document"
                :style="{ color: getFileIconColor(scope.row.fileName) }"
              ></i>
              <span class="file-name">{{ scope.row.fileName }}</span>
            </template>
          </el-table-column>
          <el-table-column label="文件类型" width="100">
            <template slot-scope="scope">
              <el-tag :type="getFileTagType(scope.row.fileName)" size="small">
                {{ getFileTypeText(scope.row.fileName) }}
              </el-tag>
            </template>
          </el-table-column>
          <el-table-column label="上传时间" width="160">
            <template slot-scope="scope">
              <span>{{ formatDateTime(scope.row.uploadTime) }}</span>
            </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="266" fixed="right">
            <template slot-scope="scope">
              <el-button
                size="mini"
                type="primary"
                @click="handlePreview(scope.row)"
                :disabled="!isPreviewable(scope.row.fileName)"
              >
                é¢„览
              </el-button>
              <el-button
                v-if="isEditing"
                size="mini"
                type="success"
                @click="handleDownload(scope.row)"
              >
                ä¸‹è½½
              </el-button>
              <el-button
                v-if="isEditing"
                size="mini"
                type="danger"
                @click="handleRemoveAttachment(scope.$index)"
              >
                åˆ é™¤
              </el-button>
            </template>
          </el-table-column>
        </el-table>
      </div>
    </div>
    <!-- åˆ—编辑对话框 -->
@@ -197,23 +265,33 @@
        </el-button>
      </span>
    </el-dialog>
    <!-- æ–‡ä»¶é¢„览弹窗 -->
    <FilePreviewDialog
      :visible="previewVisible"
      :file="currentPreviewFile"
      @close="previewVisible = false"
      @download="handleDownload"
    />
  </div>
</template>
<script>
import UploadAttachment from "@/components/UploadAttachment";
import FilePreviewDialog from "@/components/FilePreviewDialog";
import dayjs from "dayjs";
export default {
  name: "BloodRoutinePanel",
  components: {
    UploadAttachment
    UploadAttachment,
    FilePreviewDialog
  },
  props: {
    isEditing: {
      type: Boolean,
      default: false
    },
    // ä¿®æ”¹ä¸º Object ç±»åž‹ï¼Œæ”¯æŒå¤æ‚数据结构
    initialData: {
      type: Object,
      default: () => ({})
@@ -238,12 +316,21 @@
      tableKey: 0,
      tableLoading: false,
      saveLoading: false,
      // å†…部数据状态
      internalData: {},
      columnRules: {
        date: [{ required: true, message: "请选择日期", trigger: "change" }],
        time: [{ required: true, message: "请选择时间", trigger: "change" }]
      }
      },
      // é¢„览相关
      previewVisible: false,
      currentPreviewFile: null,
      // é™„件相关配置
      attachmentLimit: 10,
      attachmentAccept:
        ".pdf,.jpg,.jpeg,.png,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.txt",
      attachmentFileList: []
    };
  },
  computed: {
@@ -264,7 +351,6 @@
    }
  },
  watch: {
    // ç›‘听 initialData å˜åŒ–,确保数据正确接收
    initialData: {
      handler(newData) {
        if (newData && Object.keys(newData).length > 0) {
@@ -291,6 +377,20 @@
      },
      deep: true,
      immediate: true
    },
    // ç›‘听附件数据变化
    attachments: {
      handler(newAttachments) {
        this.attachmentFileList = newAttachments.map(item => ({
          uid: item.id || Math.random(),
          name: item.fileName,
          fileSize: item.fileSize,
          url: item.path || item.fileUrl,
          uploadTime: item.uploadTime,
          status: "success"
        }));
      },
      deep: true
    }
  },
  methods: {
@@ -304,7 +404,6 @@
        }));
        this.dynamicColumns = [...this.internalData.columns];
      } else {
        // å¦‚果没有外部数据,使用组件默认初始化
        this.initTableData();
      }
@@ -318,7 +417,6 @@
    initTableData() {
      const medicalItems = this.getMedicalItems();
      // å¦‚果没有动态列,初始化默认列
      if (this.dynamicColumns.length === 0) {
        this.dynamicColumns = [
          {
@@ -387,7 +485,6 @@
        columns: this.dynamicColumns,
        attachments: this.attachments
      };
      this.$emit("data-change", dataToEmit);
    },
@@ -435,7 +532,6 @@
        this.saveLoading = true;
        if (this.editingColumnIndex !== null) {
          // ç¼–辑现有列
          const column = this.dynamicColumns[this.editingColumnIndex];
          column.label = `${this.columnForm.date}\n${this.columnForm.time}`;
          column.date = this.columnForm.date;
@@ -443,7 +539,6 @@
          column.remark = this.columnForm.remark;
          this.$message.success("时间点修改成功");
        } else {
          // æ–°å¢žåˆ—
          const newColumn = {
            label: `${this.columnForm.date}\n${this.columnForm.time}`,
            key: `time${Date.now()}`,
@@ -451,8 +546,8 @@
            time: this.columnForm.time,
            remark: this.columnForm.remark
          };
          this.internalData.columns.push(newColumn);
          this.dynamicColumns.push(newColumn);
          this.tableData.forEach(row => {
            if (!row.values) row.values = [];
@@ -464,6 +559,7 @@
        this.columnDialogVisible = false;
        this.saveLoading = false;
        this.tableKey += 1;
        this.saveData();
      });
    },
@@ -480,6 +576,7 @@
          });
          this.columnDialogVisible = false;
          this.tableKey += 1;
          this.saveData();
          this.$message.success("时间点删除成功");
        });
      }
@@ -503,12 +600,181 @@
      this.saveData();
    },
    /** é™„件变化处理 */
    handleAttachmentChange(fileList) {
      this.attachments = fileList;
      this.$emit("attachment-change", {
        type: "blood_routine",
        attachments: fileList
      });
      this.attachmentFileList = fileList;
    },
    /** é™„件移除处理 */
    handleAttachmentRemove(file) {
      if (file.url) {
        const index = this.attachments.findIndex(
          item => item.path === file.url || item.fileUrl === file.url
        );
        if (index > -1) {
          this.attachments.splice(index, 1);
          this.saveData();
          this.$message.success("附件删除成功");
        }
      }
    },
    /** ä¸Šä¼ æˆåŠŸå¤„ç† */
    handleUploadSuccess({ file, fileList, response }) {
      if (response.code === 200) {
        const attachmentObj = {
          fileName: file.name,
          path: response.fileUrl || file.url,
          fileUrl: response.fileUrl || file.url,
          fileType: this.getFileExtension(file.name),
          fileSize: file.size,
          uploadTime: dayjs().format("YYYY-MM-DD HH:mm:ss")
        };
        if (!Array.isArray(this.attachments)) {
          this.attachments = [];
        }
        this.attachments.push(attachmentObj);
        this.attachmentFileList = fileList;
        this.saveData();
        this.$message.success("文件上传成功");
      }
    },
    /** ä¸Šä¼ é”™è¯¯å¤„理 */
    handleUploadError({ file, fileList, error }) {
      console.error("附件上传失败:", error);
      this.$message.error("文件上传失败,请重试");
    },
    /** æ‰‹åŠ¨åˆ é™¤é™„ä»¶ */
    handleRemoveAttachment(index) {
      this.attachments.splice(index, 1);
      this.attachmentFileList.splice(index, 1);
      this.saveData();
      this.$message.success("附件删除成功");
    },
    /** æ–‡ä»¶é¢„览 */
    handlePreview(file) {
      this.currentPreviewFile = {
        fileName: file.fileName,
        fileUrl: file.path || file.fileUrl,
        fileType: this.getFileType(file.fileName)
      };
      this.previewVisible = true;
    },
    /** æ–‡ä»¶ä¸‹è½½ */
    handleDownload(file) {
      const fileUrl = file.path || 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 = fileName
        .split(".")
        .pop()
        .toLowerCase();
      const imageTypes = ["jpg", "jpeg", "png", "gif", "bmp", "webp"];
      const pdfTypes = ["pdf"];
      const officeTypes = ["doc", "docx", "xls", "xlsx", "ppt", "pptx"];
      if (imageTypes.includes(extension)) return "image";
      if (pdfTypes.includes(extension)) return "pdf";
      if (officeTypes.includes(extension)) return "office";
      return "other";
    },
    /** èŽ·å–æ–‡ä»¶å›¾æ ‡é¢œè‰² */
    getFileIconColor(fileName) {
      const type = this.getFileType(fileName);
      const colorMap = {
        image: "#67C23A",
        pdf: "#F56C6C",
        office: "#409EFF",
        other: "#909399"
      };
      return colorMap[type] || "#909399";
    },
    /** èŽ·å–æ–‡ä»¶æ ‡ç­¾ç±»åž‹ */
    getFileTagType(fileName) {
      const type = this.getFileType(fileName);
      const typeMap = {
        image: "success",
        pdf: "danger",
        office: "primary",
        other: "info"
      };
      return typeMap[type] || "info";
    },
    /** èŽ·å–æ–‡ä»¶ç±»åž‹æ–‡æœ¬ */
    getFileTypeText(fileName) {
      const type = this.getFileType(fileName);
      const textMap = {
        image: "图片",
        pdf: "PDF",
        office: "文档",
        other: "其他"
      };
      return textMap[type] || "未知";
    },
    /** æ£€æŸ¥æ˜¯å¦å¯é¢„览 */
    isPreviewable(fileName) {
      const type = this.getFileType(fileName);
      return ["image", "pdf"].includes(type);
    },
    /** èŽ·å–æ–‡ä»¶æ‰©å±•å */
    getFileExtension(filename) {
      return filename
        .split(".")
        .pop()
        .toLowerCase();
    },
    /** æ ¼å¼åŒ–文件大小 */
    formatFileSize(bytes) {
      if (!bytes || 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];
    },
    /** æ—¥æœŸæ—¶é—´æ ¼å¼åŒ– */
    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;
      }
    },
    forceTableLayout() {
@@ -539,7 +805,6 @@
    }
  },
  mounted() {
    // ç¡®ä¿ç»„件正确挂载后初始化数据
    this.$nextTick(() => {
      if (Object.keys(this.internalData).length === 0) {
        this.initTableData();
@@ -678,6 +943,7 @@
  font-size: 14px;
}
/* é™„件上传区域样式优化 */
.attachment-section {
  margin-top: 24px;
  padding: 20px;
@@ -703,6 +969,22 @@
  color: #909399;
}
.attachment-list {
  margin-top: 16px;
}
.list-title {
  font-weight: bold;
  margin-bottom: 12px;
  color: #303133;
  font-size: 14px;
}
.file-name {
  font-size: 13px;
  margin-left: 8px;
}
/* å“åº”式设计 */
@media (max-width: 768px) {
  .medical-panel {
src/views/business/maintain/components/LiverKidneyPanel.vue
@@ -70,19 +70,89 @@
      </el-table-column>
    </el-table>
    <!-- é™„件上传区域 -->
    <!-- é™„件上传区域优化 -->
    <div class="attachment-section">
      <div class="attachment-title">
      <div class="attachment-header">
        <i class="el-icon-paperclip"></i>
        é™„件上传
        <span class="attachment-tip">支持上传检验报告单等文件</span>
        <span class="attachment-title">附件上传</span>
        <span class="attachment-tip"
          >支持上传检验报告单等文件 (最多{{ attachmentLimit }}个)</span
        >
      </div>
      <upload-attachment
        :file-list="attachments"
      <!-- ä½¿ç”¨ UploadAttachment ç»„ä»¶ -->
      <UploadAttachment
        ref="uploadAttachment"
        :file-list="attachmentFileList"
        :limit="attachmentLimit"
        :accept="attachmentAccept"
        :multiple="true"
        @change="handleAttachmentChange"
        :limit="10"
        :accept="'.pdf,.jpg,.jpeg,.png,.doc,.docx'"
        @upload-success="handleUploadSuccess"
        @upload-error="handleUploadError"
        @remove="handleAttachmentRemove"
      />
      <!-- é™„件列表展示 -->
      <div class="attachment-list" v-if="attachments && attachments.length > 0">
        <div class="list-title">已上传附件 ({{ attachments.length }})</div>
        <el-table :data="attachments" style="width: 100%" size="small">
          <el-table-column label="文件名" min-width="200">
            <template slot-scope="scope">
              <i
                class="el-icon-document"
                :style="{ color: getFileIconColor(scope.row.fileName) }"
              ></i>
              <span class="file-name">{{ scope.row.fileName }}</span>
            </template>
          </el-table-column>
          <el-table-column label="文件类型" width="100">
            <template slot-scope="scope">
              <el-tag :type="getFileTagType(scope.row.fileName)" size="small">
                {{ getFileTypeText(scope.row.fileName) }}
              </el-tag>
            </template>
          </el-table-column>
          <el-table-column label="上传时间" width="160">
            <template slot-scope="scope">
              <span>{{ formatDateTime(scope.row.uploadTime) }}</span>
            </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="266" fixed="right">
            <template slot-scope="scope">
              <el-button
                size="mini"
                type="primary"
                @click="handlePreview(scope.row)"
                :disabled="!isPreviewable(scope.row.fileName)"
              >
                é¢„览
              </el-button>
              <el-button
                v-if="isEditing"
                size="mini"
                type="success"
                @click="handleDownload(scope.row)"
              >
                ä¸‹è½½
              </el-button>
              <el-button
                v-if="isEditing"
                size="mini"
                type="danger"
                @click="handleRemoveAttachment(scope.$index)"
              >
                åˆ é™¤
              </el-button>
            </template>
          </el-table-column>
        </el-table>
      </div>
    </div>
    <!-- åˆ—编辑对话框 -->
@@ -128,23 +198,33 @@
        <el-button type="primary" @click="confirmAddColumn">确定</el-button>
      </span>
    </el-dialog>
    <!-- æ–‡ä»¶é¢„览弹窗 -->
    <FilePreviewDialog
      :visible="previewVisible"
      :file="currentPreviewFile"
      @close="previewVisible = false"
      @download="handleDownload"
    />
  </div>
</template>
<script>
import UploadAttachment from "@/components/UploadAttachment";
import FilePreviewDialog from "@/components/FilePreviewDialog";
import dayjs from "dayjs";
export default {
  name: "LiverKidneyPanel",
  components: {
    UploadAttachment
    UploadAttachment,
    FilePreviewDialog
  },
  props: {
    isEditing: {
      type: Boolean,
      default: false
    },
    // ä¿®æ”¹ prop å®šä¹‰ï¼Œæ”¯æŒå¯¹è±¡æ ¼å¼çš„初始数据
    initialData: {
      type: Object,
      default: () => ({})
@@ -161,12 +241,20 @@
        time: ""
      },
      tableKey: 0,
      // å†…部数据状态
      internalData: {}
      internalData: {},
      // é¢„览相关
      previewVisible: false,
      currentPreviewFile: null,
      // é™„件相关配置
      attachmentLimit: 10,
      attachmentAccept:
        ".pdf,.jpg,.jpeg,.png,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.txt",
      attachmentFileList: []
    };
  },
  watch: {
    // ç›‘听 initialData å˜åŒ–,确保数据正确接收 [5](@ref)
    initialData: {
      handler(newData) {
        if (newData && Object.keys(newData).length > 0) {
@@ -192,13 +280,26 @@
        });
      },
      deep: true
    },
    // ç›‘听附件数据变化
    attachments: {
      handler(newAttachments) {
        this.attachmentFileList = newAttachments.map(item => ({
          uid: item.id || Math.random(),
          name: item.fileName,
          fileSize: item.fileSize,
          url: item.path || item.fileUrl,
          uploadTime: item.uploadTime,
          status: "success"
        }));
      },
      deep: true
    }
  },
  methods: {
    // ä»Žå¤–部数据初始化组件 [9](@ref)
    // ä»Žå¤–部数据初始化组件
    initFromExternalData() {
      if (this.internalData.data && this.internalData.columns) {
        // ä½¿ç”¨å¤–部数据初始化表格
        this.tableData = this.internalData.data.map(item => ({
          ...item,
          values:
@@ -206,7 +307,6 @@
        }));
        this.dynamicColumns = [...this.internalData.columns];
      } else {
        // å¦‚果没有外部数据,使用默认初始化
        this.initTableData();
      }
@@ -247,7 +347,6 @@
        { itemName: "INR", unit: "", required: true, reference: "0.85-1.15" }
      ];
      // å¦‚果没有动态列,初始化默认列
      if (this.dynamicColumns.length === 0) {
        this.dynamicColumns = [
          {
@@ -265,7 +364,7 @@
      }));
    },
    // ä¿å­˜æ•°æ®åˆ°çˆ¶ç»„ä»¶ [2](@ref)
    // ä¿å­˜æ•°æ®åˆ°çˆ¶ç»„ä»¶
    saveData() {
      const dataToEmit = {
        type: "liver_kidney",
@@ -298,7 +397,6 @@
          date: this.columnForm.date,
          time: this.columnForm.time
        };
        this.internalData.columns.push(newColumn);
        this.dynamicColumns.push(newColumn);
@@ -313,14 +411,12 @@
        this.columnDialogVisible = false;
        this.$message.success("时间点添加成功");
        this.tableKey += 1;
        this.saveData();
      });
    },
    handleDialogClosed() {
      this.columnForm = {
        date: "",
        time: ""
      };
      this.columnForm = { date: "", time: "" };
      this.$refs.columnForm && this.$refs.columnForm.clearValidate();
    },
@@ -328,12 +424,182 @@
      this.saveData();
    },
    /** é™„件变化处理 */
    handleAttachmentChange(fileList) {
      this.attachments = fileList;
      this.$emit("attachment-change", {
        type: "liver_kidney",
        attachments: fileList
      });
      this.attachmentFileList = fileList;
    },
    /** é™„件移除处理 */
    handleAttachmentRemove(file) {
      if (file.url) {
        const index = this.attachments.findIndex(
          item => item.path === file.url || item.fileUrl === file.url
        );
        if (index > -1) {
          this.attachments.splice(index, 1);
          this.saveData();
          this.$message.success("附件删除成功");
        }
      }
    },
    /** ä¸Šä¼ æˆåŠŸå¤„ç† */
    handleUploadSuccess({ file, fileList, response }) {
      if (response.code === 200) {
        const attachmentObj = {
          fileName: file.name,
          path: response.fileUrl || file.url,
          fileUrl: response.fileUrl || file.url,
          fileType: this.getFileExtension(file.name),
          fileSize: file.size,
          uploadTime: dayjs().format("YYYY-MM-DD HH:mm:ss")
        };
        // ç¡®ä¿ attachments æ˜¯æ•°ç»„
        if (!Array.isArray(this.attachments)) {
          this.attachments = [];
        }
        this.attachments.push(attachmentObj);
        this.attachmentFileList = fileList;
        this.saveData();
        this.$message.success("文件上传成功");
      }
    },
    /** ä¸Šä¼ é”™è¯¯å¤„理 */
    handleUploadError({ file, fileList, error }) {
      console.error("附件上传失败:", error);
      this.$message.error("文件上传失败,请重试");
    },
    /** æ‰‹åŠ¨åˆ é™¤é™„ä»¶ */
    handleRemoveAttachment(index) {
      this.attachments.splice(index, 1);
      this.attachmentFileList.splice(index, 1);
      this.saveData();
      this.$message.success("附件删除成功");
    },
    /** æ–‡ä»¶é¢„览 */
    handlePreview(file) {
      this.currentPreviewFile = {
        fileName: file.fileName,
        fileUrl: file.path || file.fileUrl,
        fileType: this.getFileType(file.fileName)
      };
      this.previewVisible = true;
    },
    /** æ–‡ä»¶ä¸‹è½½ */
    handleDownload(file) {
      const fileUrl = file.path || 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 = fileName
        .split(".")
        .pop()
        .toLowerCase();
      const imageTypes = ["jpg", "jpeg", "png", "gif", "bmp", "webp"];
      const pdfTypes = ["pdf"];
      const officeTypes = ["doc", "docx", "xls", "xlsx", "ppt", "pptx"];
      if (imageTypes.includes(extension)) return "image";
      if (pdfTypes.includes(extension)) return "pdf";
      if (officeTypes.includes(extension)) return "office";
      return "other";
    },
    /** èŽ·å–æ–‡ä»¶å›¾æ ‡é¢œè‰² */
    getFileIconColor(fileName) {
      const type = this.getFileType(fileName);
      const colorMap = {
        image: "#67C23A",
        pdf: "#F56C6C",
        office: "#409EFF",
        other: "#909399"
      };
      return colorMap[type] || "#909399";
    },
    /** èŽ·å–æ–‡ä»¶æ ‡ç­¾ç±»åž‹ */
    getFileTagType(fileName) {
      const type = this.getFileType(fileName);
      const typeMap = {
        image: "success",
        pdf: "danger",
        office: "primary",
        other: "info"
      };
      return typeMap[type] || "info";
    },
    /** èŽ·å–æ–‡ä»¶ç±»åž‹æ–‡æœ¬ */
    getFileTypeText(fileName) {
      const type = this.getFileType(fileName);
      const textMap = {
        image: "图片",
        pdf: "PDF",
        office: "文档",
        other: "其他"
      };
      return textMap[type] || "未知";
    },
    /** æ£€æŸ¥æ˜¯å¦å¯é¢„览 */
    isPreviewable(fileName) {
      const type = this.getFileType(fileName);
      return ["image", "pdf"].includes(type);
    },
    /** èŽ·å–æ–‡ä»¶æ‰©å±•å */
    getFileExtension(filename) {
      return filename
        .split(".")
        .pop()
        .toLowerCase();
    },
    /** æ ¼å¼åŒ–文件大小 */
    formatFileSize(bytes) {
      if (!bytes || 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];
    },
    /** æ—¥æœŸæ—¶é—´æ ¼å¼åŒ– */
    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;
      }
    },
    forceTableLayout() {
@@ -362,7 +628,6 @@
    }
  },
  mounted() {
    // ç¡®ä¿ç»„件正确挂载后初始化数据 [1](@ref)
    this.$nextTick(() => {
      if (Object.keys(this.internalData).length === 0) {
        this.initTableData();
@@ -442,6 +707,7 @@
  margin-right: 4px;
}
/* é™„件上传区域样式优化 */
.attachment-section {
  margin-top: 30px;
  padding: 20px;
@@ -450,21 +716,43 @@
  background: #fafafa;
}
.attachment-title {
  font-weight: bold;
  margin-bottom: 15px;
  color: #409eff;
.attachment-header {
  display: flex;
  align-items: center;
  margin-bottom: 16px;
  padding-bottom: 8px;
  border-bottom: 1px solid #ebeef5;
}
.attachment-title {
  font-weight: bold;
  margin: 0 8px;
  color: #303133;
}
.attachment-tip {
  font-size: 12px;
  color: #909399;
  margin-left: 10px;
  font-weight: normal;
  margin-left: auto;
}
.attachment-list {
  margin-top: 16px;
}
.list-title {
  font-weight: bold;
  margin-bottom: 12px;
  color: #303133;
  font-size: 14px;
}
.file-name {
  font-size: 13px;
  margin-left: 8px;
}
/* å“åº”式调整 */
@media (max-width: 768px) {
  .medical-panel {
    padding: 10px;
@@ -488,5 +776,9 @@
    margin-left: 0;
    margin-top: 4px;
  }
  .attachment-section {
    padding: 10px;
  }
}
</style>
src/views/business/maintain/components/UrineRoutinePanel.vue
@@ -144,12 +144,80 @@
          >支持上传尿常规检验报告单等文件 (最多10个)</span
        >
      </div>
      <upload-attachment
        :file-list="attachments"
      <!-- ä½¿ç”¨ UploadAttachment ç»„ä»¶ -->
      <UploadAttachment
        ref="uploadAttachment"
        :file-list="attachmentFileList"
        :limit="attachmentLimit"
        :accept="attachmentAccept"
        :multiple="true"
        @change="handleAttachmentChange"
        :limit="10"
        :accept="'.pdf,.jpg,.jpeg,.png,.doc,.docx'"
        @upload-success="handleUploadSuccess"
        @upload-error="handleUploadError"
        @remove="handleAttachmentRemove"
      />
      <!-- é™„件列表展示 -->
      <div class="attachment-list" v-if="attachments && attachments.length > 0">
        <div class="list-title">已上传附件 ({{ attachments.length }})</div>
        <el-table :data="attachments" style="width: 100%" size="small">
          <el-table-column label="文件名" min-width="200">
            <template slot-scope="scope">
              <i
                class="el-icon-document"
                :style="{ color: getFileIconColor(scope.row.fileName) }"
              ></i>
              <span class="file-name">{{ scope.row.fileName }}</span>
            </template>
          </el-table-column>
          <el-table-column label="文件类型" width="100">
            <template slot-scope="scope">
              <el-tag :type="getFileTagType(scope.row.fileName)" size="small">
                {{ getFileTypeText(scope.row.fileName) }}
              </el-tag>
            </template>
          </el-table-column>
          <el-table-column label="上传时间" width="160">
            <template slot-scope="scope">
              <span>{{ formatDateTime(scope.row.uploadTime) }}</span>
            </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="266" fixed="right">
            <template slot-scope="scope">
              <el-button
                size="mini"
                type="primary"
                @click="handlePreview(scope.row)"
                :disabled="!isPreviewable(scope.row.fileName)"
              >
                é¢„览
              </el-button>
              <el-button
                v-if="isEditing"
                size="mini"
                type="success"
                @click="handleDownload(scope.row)"
              >
                ä¸‹è½½
              </el-button>
              <el-button
                v-if="isEditing"
                size="mini"
                type="danger"
                @click="handleRemoveAttachment(scope.$index)"
              >
                åˆ é™¤
              </el-button>
            </template>
          </el-table-column>
        </el-table>
      </div>
    </div>
    <!-- åˆ—编辑对话框 -->
@@ -212,23 +280,33 @@
        </el-button>
      </span>
    </el-dialog>
    <!-- æ–‡ä»¶é¢„览弹窗 -->
    <FilePreviewDialog
      :visible="previewVisible"
      :file="currentPreviewFile"
      @close="previewVisible = false"
      @download="handleDownload"
    />
  </div>
</template>
<script>
import UploadAttachment from "@/components/UploadAttachment";
import FilePreviewDialog from "@/components/FilePreviewDialog";
import dayjs from "dayjs";
export default {
  name: "UrineRoutinePanel",
  components: {
    UploadAttachment
    UploadAttachment,
    FilePreviewDialog
  },
  props: {
    isEditing: {
      type: Boolean,
      default: false
    },
    // ä¿®æ”¹ä¸º Object ç±»åž‹ï¼Œæ”¯æŒå¤æ‚数据结构
    initialData: {
      type: Object,
      default: () => ({})
@@ -253,12 +331,21 @@
      tableKey: 0,
      tableLoading: false,
      saveLoading: false,
      // å†…部数据状态
      internalData: {},
      columnRules: {
        date: [{ required: true, message: "请选择日期", trigger: "change" }],
        time: [{ required: true, message: "请选择时间", trigger: "change" }]
      }
      },
      // é¢„览相关
      previewVisible: false,
      currentPreviewFile: null,
      // é™„件相关配置
      attachmentLimit: 10,
      attachmentAccept:
        ".pdf,.jpg,.jpeg,.png,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.txt",
      attachmentFileList: []
    };
  },
  computed: {
@@ -279,11 +366,9 @@
    }
  },
  watch: {
    // ç›‘听 initialData å˜åŒ–,确保数据正确接收
    initialData: {
      handler(newData) {
        console.log(newData);
        if (newData && Object.keys(newData).length > 0) {
          this.internalData = { ...newData };
          this.initFromExternalData();
@@ -308,12 +393,26 @@
      },
      deep: true,
      immediate: true
    },
    // ç›‘听附件数据变化
    attachments: {
      handler(newAttachments) {
        this.attachmentFileList = newAttachments.map(item => ({
          uid: item.id || Math.random(),
          name: item.fileName,
          fileSize: item.fileSize,
          url: item.path || item.fileUrl,
          uploadTime: item.uploadTime,
          status: "success"
        }));
      },
      deep: true
    }
  },
  methods: {
    // ä»Žå¤–部数据初始化组件
    initFromExternalData() {
      console.log(this.internalData,'this.internalData');
      console.log(this.internalData, "this.internalData");
      if (this.internalData.data && this.internalData.columns) {
        this.tableData = this.internalData.data.map(item => ({
@@ -323,7 +422,6 @@
        }));
        this.dynamicColumns = [...this.internalData.columns];
      } else {
        // å¦‚果没有外部数据,使用组件默认初始化
        this.initTableData();
      }
@@ -337,7 +435,6 @@
    initTableData() {
      const medicalItems = this.getMedicalItems();
      // å¦‚果没有动态列,初始化默认列
      if (this.dynamicColumns.length === 0) {
        this.dynamicColumns = [
          {
@@ -501,7 +598,6 @@
        this.saveLoading = true;
        if (this.editingColumnIndex !== null) {
          // ç¼–辑现有列
          const column = this.dynamicColumns[this.editingColumnIndex];
          column.label = `${this.columnForm.date}\n${this.columnForm.time}`;
          column.date = this.columnForm.date;
@@ -509,7 +605,6 @@
          column.remark = this.columnForm.remark;
          this.$message.success("时间点修改成功");
        } else {
          // æ–°å¢žåˆ—
          const newColumn = {
            label: `${this.columnForm.date}\n${this.columnForm.time}`,
            key: `time${Date.now()}`,
@@ -530,6 +625,7 @@
        this.columnDialogVisible = false;
        this.saveLoading = false;
        this.tableKey += 1;
        this.saveData();
      });
    },
@@ -546,6 +642,7 @@
          });
          this.columnDialogVisible = false;
          this.tableKey += 1;
          this.saveData();
          this.$message.success("时间点删除成功");
        });
      }
@@ -569,12 +666,181 @@
      this.saveData();
    },
    /** é™„件变化处理 */
    handleAttachmentChange(fileList) {
      this.attachments = fileList;
      this.$emit("attachment-change", {
        type: "urine_routine",
        attachments: fileList
      });
      this.attachmentFileList = fileList;
    },
    /** é™„件移除处理 */
    handleAttachmentRemove(file) {
      if (file.url) {
        const index = this.attachments.findIndex(
          item => item.path === file.url || item.fileUrl === file.url
        );
        if (index > -1) {
          this.attachments.splice(index, 1);
          this.saveData();
          this.$message.success("附件删除成功");
        }
      }
    },
    /** ä¸Šä¼ æˆåŠŸå¤„ç† */
    handleUploadSuccess({ file, fileList, response }) {
      if (response.code === 200) {
        const attachmentObj = {
          fileName: file.name,
          path: response.fileUrl || file.url,
          fileUrl: response.fileUrl || file.url,
          fileType: this.getFileExtension(file.name),
          fileSize: file.size,
          uploadTime: dayjs().format("YYYY-MM-DD HH:mm:ss")
        };
        if (!Array.isArray(this.attachments)) {
          this.attachments = [];
        }
        this.attachments.push(attachmentObj);
        this.attachmentFileList = fileList;
        this.saveData();
        this.$message.success("文件上传成功");
      }
    },
    /** ä¸Šä¼ é”™è¯¯å¤„理 */
    handleUploadError({ file, fileList, error }) {
      console.error("附件上传失败:", error);
      this.$message.error("文件上传失败,请重试");
    },
    /** æ‰‹åŠ¨åˆ é™¤é™„ä»¶ */
    handleRemoveAttachment(index) {
      this.attachments.splice(index, 1);
      this.attachmentFileList.splice(index, 1);
      this.saveData();
      this.$message.success("附件删除成功");
    },
    /** æ–‡ä»¶é¢„览 */
    handlePreview(file) {
      this.currentPreviewFile = {
        fileName: file.fileName,
        fileUrl: file.path || file.fileUrl,
        fileType: this.getFileType(file.fileName)
      };
      this.previewVisible = true;
    },
    /** æ–‡ä»¶ä¸‹è½½ */
    handleDownload(file) {
      const fileUrl = file.path || 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 = fileName
        .split(".")
        .pop()
        .toLowerCase();
      const imageTypes = ["jpg", "jpeg", "png", "gif", "bmp", "webp"];
      const pdfTypes = ["pdf"];
      const officeTypes = ["doc", "docx", "xls", "xlsx", "ppt", "pptx"];
      if (imageTypes.includes(extension)) return "image";
      if (pdfTypes.includes(extension)) return "pdf";
      if (officeTypes.includes(extension)) return "office";
      return "other";
    },
    /** èŽ·å–æ–‡ä»¶å›¾æ ‡é¢œè‰² */
    getFileIconColor(fileName) {
      const type = this.getFileType(fileName);
      const colorMap = {
        image: "#67C23A",
        pdf: "#F56C6C",
        office: "#409EFF",
        other: "#909399"
      };
      return colorMap[type] || "#909399";
    },
    /** èŽ·å–æ–‡ä»¶æ ‡ç­¾ç±»åž‹ */
    getFileTagType(fileName) {
      const type = this.getFileType(fileName);
      const typeMap = {
        image: "success",
        pdf: "danger",
        office: "primary",
        other: "info"
      };
      return typeMap[type] || "info";
    },
    /** èŽ·å–æ–‡ä»¶ç±»åž‹æ–‡æœ¬ */
    getFileTypeText(fileName) {
      const type = this.getFileType(fileName);
      const textMap = {
        image: "图片",
        pdf: "PDF",
        office: "文档",
        other: "其他"
      };
      return textMap[type] || "未知";
    },
    /** æ£€æŸ¥æ˜¯å¦å¯é¢„览 */
    isPreviewable(fileName) {
      const type = this.getFileType(fileName);
      return ["image", "pdf"].includes(type);
    },
    /** èŽ·å–æ–‡ä»¶æ‰©å±•å */
    getFileExtension(filename) {
      return filename
        .split(".")
        .pop()
        .toLowerCase();
    },
    /** æ ¼å¼åŒ–文件大小 */
    formatFileSize(bytes) {
      if (!bytes || 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];
    },
    /** æ—¥æœŸæ—¶é—´æ ¼å¼åŒ– */
    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;
      }
    },
    forceTableLayout() {
@@ -605,7 +871,6 @@
    }
  },
  mounted() {
    // ç¡®ä¿ç»„件正确挂载后初始化数据
    this.$nextTick(() => {
      if (Object.keys(this.internalData).length === 0) {
        this.initTableData();
@@ -744,6 +1009,7 @@
  font-size: 14px;
}
/* é™„件上传区域样式优化 */
.attachment-section {
  margin-top: 24px;
  padding: 20px;
@@ -769,6 +1035,22 @@
  color: #909399;
}
.attachment-list {
  margin-top: 16px;
}
.list-title {
  font-weight: bold;
  margin-bottom: 12px;
  color: #303133;
  font-size: 14px;
}
.file-name {
  font-size: 13px;
  margin-left: 8px;
}
/* å“åº”式设计 */
@media (max-width: 768px) {
  .medical-panel {
src/views/business/maintain/maintainInfo.vue
@@ -53,11 +53,6 @@
          <el-col :span="8">
            <el-form-item label="患者状态" prop="recordstate">
              <el-select v-model="form.recordstate" style="width: 100%">
                <!-- <el-option label="DCD" value="1" />
                <el-option label="DBD" value="2" />
                <el-option label="DBCD" value="3" />
                <el-option label="已完成捐献" value="4" />
                <el-option label="未完成捐献" value="5" /> -->
                <el-option
                  v-for="dict in dict.type.sys_DonationCategory || []"
                  :key="dict.value"
@@ -66,20 +61,6 @@
                ></el-option>
              </el-select>
            </el-form-item>
            <!-- <el-form-item
              align="left"
              label="患者捐献状态"
              prop="donationcategory"
            >
              <el-radio-group v-model="form.recordstate">
                <el-radio
                  v-for="dict in dict.type.sys_DonationCategory || []"
                  :key="dict.value"
                  :label="dict.value"
                  >{{ dict.label }}</el-radio
                >
              </el-radio-group>
            </el-form-item> -->
          </el-col>
          <el-col :span="8">
            <el-form-item
@@ -127,10 +108,6 @@
          <el-col :span="8">
            <el-form-item label="血型" prop="bloodtype">
              <el-select v-model="form.bloodtype" style="width: 100%">
                <!-- <el-option label="A型" value="A" />
                <el-option label="B型" value="B" />
                <el-option label="O型" value="O" />
                <el-option label="AB型" value="AB" /> -->
                <el-option
                  v-for="dict in dict.type.sys_BloodType"
                  :key="dict.value"
@@ -423,9 +400,16 @@
        </el-row>
        <el-form-item label="附件">
          <upload-attachment
            :file-list="cultureForm.attachments"
          <UploadAttachment
            ref="cultureUploadAttachment"
            :file-list="cultureFileList"
            :limit="10"
            :accept="attachmentAccept"
            :multiple="true"
            @change="handleCultureAttachmentChange"
            @upload-success="handleCultureUploadSuccess"
            @upload-error="handleCultureUploadError"
            @remove="handleCultureAttachmentRemove"
          />
        </el-form-item>
      </el-form>
@@ -486,9 +470,16 @@
        </el-form-item>
        <el-form-item label="附件">
          <upload-attachment
            :file-list="recordForm.attachments"
          <UploadAttachment
            ref="recordUploadAttachment"
            :file-list="recordFileList"
            :limit="10"
            :accept="attachmentAccept"
            :multiple="true"
            @change="handleRecordAttachmentChange"
            @upload-success="handleRecordUploadSuccess"
            @upload-error="handleRecordUploadError"
            @remove="handleRecordAttachmentRemove"
          />
        </el-form-item>
      </el-form>
@@ -505,11 +496,67 @@
    </el-dialog>
    <!-- é™„件预览对话框 -->
    <attachment-preview
      :visible="attachmentPreviewVisible"
      :file-list="currentAttachmentList"
    <el-dialog
      :title="attachmentPreviewTitle"
      @close="attachmentPreviewVisible = false"
      :visible.sync="attachmentPreviewVisible"
      width="900px"
      @close="handleAttachmentPreviewClose"
    >
      <el-table :data="currentAttachmentList" style="width: 100%" size="small">
        <el-table-column label="文件名" min-width="200">
          <template slot-scope="scope">
            <i
              class="el-icon-document"
              :style="{ color: getFileIconColor(scope.row.fileName) }"
            ></i>
            <span class="file-name">{{ scope.row.fileName }}</span>
          </template>
        </el-table-column>
        <el-table-column label="文件类型" width="100">
          <template slot-scope="scope">
            <el-tag :type="getFileTagType(scope.row.fileName)" size="small">
              {{ getFileTypeText(scope.row.fileName) }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="上传时间" width="160">
          <template slot-scope="scope">
            <span>{{ formatDateTime(scope.row.uploadTime) }}</span>
          </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="150" fixed="right">
          <template slot-scope="scope">
            <el-button
              size="mini"
              type="primary"
              @click="handlePreviewAttachment(scope.row)"
              :disabled="!isPreviewable(scope.row.fileName)"
            >
              é¢„览
            </el-button>
            <el-button
              size="mini"
              type="success"
              @click="handleDownloadAttachment(scope.row)"
            >
              ä¸‹è½½
            </el-button>
          </template>
        </el-table-column>
      </el-table>
    </el-dialog>
    <!-- æ–‡ä»¶é¢„览弹窗 -->
    <FilePreviewDialog
      :visible="filePreviewVisible"
      :file="currentPreviewFile"
      @close="filePreviewVisible = false"
      @download="handleDownloadAttachment"
    />
  </div>
</template>
@@ -518,17 +565,18 @@
import { maintainList, maintainedit, maintainAdd } from "@/api/businessApi";
import Pagination from "@/components/Pagination";
import UploadAttachment from "@/components/UploadAttachment";
import AttachmentPreview from "@/components/AttachmentPreview";
import FilePreviewDialog from "@/components/FilePreviewDialog";
import LiverKidneyPanel from "./components/LiverKidneyPanel.vue";
import BloodRoutinePanel from "./components/BloodRoutinePanel.vue";
import UrineRoutinePanel from "./components/UrineRoutinePanel.vue";
import dayjs from "dayjs";
export default {
  name: "MaintenanceDetail",
  components: {
    Pagination,
    UploadAttachment,
    AttachmentPreview,
    FilePreviewDialog,
    LiverKidneyPanel,
    BloodRoutinePanel,
    UrineRoutinePanel
@@ -565,10 +613,8 @@
        incompleteReason: ""
      },
      activeTab: "culture",
      liverKidneyData: {}, // ä»Ž maintainList æŽ¥å£èŽ·å–çš„æ•°æ®
      bloodRoutineData: {}, // ä»Ž maintainList æŽ¥å£èŽ·å–çš„æ•°æ®
      liverKidneyData: {}, // ä»Ž maintainList æŽ¥å£èŽ·å–çš„æ•°æ®
      extracontentinfo: {},
      // åŸ¹å…»ç»“果相关数据
      cultureList: [],
      cultureLoading: false,
@@ -582,6 +628,7 @@
        result: "阴性",
        attachments: []
      },
      cultureFileList: [],
      cultureRules: {
        cultureType: [
          { required: true, message: "请选择培养类型", trigger: "change" }
@@ -615,6 +662,7 @@
        checkRecord: "",
        attachments: []
      },
      recordFileList: [],
      recordRules: {
        recordTime: [
          { required: true, message: "请选择核查时间", trigger: "change" }
@@ -631,6 +679,14 @@
      attachmentPreviewVisible: false,
      currentAttachmentList: [],
      attachmentPreviewTitle: "",
      // æ–‡ä»¶é¢„览相关
      filePreviewVisible: false,
      currentPreviewFile: null,
      // é™„件相关配置
      attachmentLimit: 10,
      attachmentAccept: ".pdf,.jpg,.jpeg,.png,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.txt",
      // è¯„估数据存储
      assessmentData: {
@@ -651,7 +707,7 @@
    }
  },
  methods: {
    // åŠ è½½ç»´æŠ¤æ•°æ®[1,3](@ref)
    // åŠ è½½ç»´æŠ¤æ•°æ®
    async loadMaintenanceData() {
      try {
        this.cultureLoading = true;
@@ -661,7 +717,7 @@
        const queryParams = {};
        if (id) {
          queryParams.id = id;
          queryParams.infoid = infoid;
          this.currentMaintenanceId = id;
          this.isEditMode = true;
        } else if (infoid) {
@@ -672,30 +728,27 @@
          this.$message.error("缺少必要的路由参数");
          return;
        }
        queryParams.infoid = infoid;
        const response = await maintainList(queryParams);
        if (response.code === 200) {
          let maintenanceData = response.data[0];
          // å¤„理数组响应
          if (Array.isArray(maintenanceData)) {
            maintenanceData = maintenanceData[0] || {};
          }
          if (maintenanceData.extracontent) {
             this.extracontentinfo = JSON.parse(maintenanceData.extracontent);
            if (this.extracontentinfo.specialMedicalHistory) {
              this.form.specialMedicalHistory =
                this.extracontentinfo.specialMedicalHistory;
              this.form.specialMedicalHistory = this.extracontentinfo.specialMedicalHistory;
            }
          }
          // è§£æžitemDesc字段中的JSON数据[6,8](@ref)
          if (maintenanceData.itemDesc) {
            try {
              const itemDescData = maintenanceData.itemDesc;
              this.assessmentData = { ...this.assessmentData, ...itemDescData };
              // å¡«å……各个模块的数据
              if (itemDescData.cultureResults) {
                this.cultureList = itemDescData.cultureResults;
              }
@@ -716,7 +769,6 @@
            }
          }
          // å¡«å……基础表单数据
          this.form = { ...this.form, ...maintenanceData };
          this.$message.success("数据加载成功");
        } else {
@@ -731,10 +783,9 @@
      }
    },
    // ä¿å­˜æ‰€æœ‰æ•°æ®[1,2](@ref)
    // ä¿å­˜æ‰€æœ‰æ•°æ®
    async handleSave() {
      try {
        // æž„建保存数据
        const saveData = {
          ...this.form,
          itemDesc: {
@@ -748,11 +799,9 @@
        this.extracontentinfo.specialMedicalHistory = this.form.specialMedicalHistory;
        let response;
        if (this.isEditMode && this.currentMaintenanceId) {
          // ç¼–辑模式,调用maintainedit接口[1](@ref)
          saveData.id = this.currentMaintenanceId;
          response = await maintainedit(saveData);
        } else {
          // æ–°å¢žæ¨¡å¼ï¼Œè°ƒç”¨maintainAdd接口[2](@ref)
          response = await maintainAdd(saveData);
        }
@@ -763,7 +812,6 @@
            id: this.$route.query.infoid,
            extracontent: JSON.stringify(this.extracontentinfo)
          });
          // å¦‚果是新增保存,更新当前ID
          if (!this.isEditMode && response.data && response.data.id) {
            this.currentMaintenanceId = response.data.id;
            this.isEditMode = true;
@@ -795,6 +843,7 @@
        result: "阴性",
        attachments: []
      };
      this.cultureFileList = [];
      this.cultureDialogVisible = true;
      this.$nextTick(() => {
        this.$refs.cultureForm && this.$refs.cultureForm.clearValidate();
@@ -804,6 +853,14 @@
    handleEditCulture(row) {
      this.cultureDialogTitle = "编辑培养记录";
      this.cultureForm = { ...row };
      this.cultureFileList = row.attachments ? row.attachments.map(item => ({
        uid: item.id || Math.random(),
        name: item.fileName,
        fileSize: item.fileSize,
        url: item.path || item.fileUrl,
        uploadTime: item.uploadTime,
        status: "success"
      })) : [];
      this.cultureDialogVisible = true;
      this.$nextTick(() => {
        this.$refs.cultureForm && this.$refs.cultureForm.clearValidate();
@@ -816,7 +873,6 @@
          this.cultureSaveLoading = true;
          if (this.cultureForm.id) {
            // ç¼–辑现有记录
            const index = this.cultureList.findIndex(
              item => item.id === this.cultureForm.id
            );
@@ -824,7 +880,6 @@
              this.cultureList.splice(index, 1, { ...this.cultureForm });
            }
          } else {
            // æ–°å¢žè®°å½•
            this.cultureForm.id = Date.now();
            this.cultureList.push({ ...this.cultureForm });
          }
@@ -864,6 +919,7 @@
        checkRecord: "",
        attachments: []
      };
      this.recordFileList = [];
      this.recordDialogVisible = true;
      this.$nextTick(() => {
        this.$refs.recordForm && this.$refs.recordForm.clearValidate();
@@ -873,6 +929,14 @@
    handleEditRecord(row) {
      this.recordDialogTitle = "编辑护理核查记录";
      this.recordForm = { ...row };
      this.recordFileList = row.attachments ? row.attachments.map(item => ({
        uid: item.id || Math.random(),
        name: item.fileName,
        fileSize: item.fileSize,
        url: item.path || item.fileUrl,
        uploadTime: item.uploadTime,
        status: "success"
      })) : [];
      this.recordDialogVisible = true;
      this.$nextTick(() => {
        this.$refs.recordForm && this.$refs.recordForm.clearValidate();
@@ -885,7 +949,6 @@
          this.recordSaveLoading = true;
          if (this.recordForm.id) {
            // ç¼–辑现有记录
            const index = this.recordList.findIndex(
              item => item.id === this.recordForm.id
            );
@@ -893,7 +956,6 @@
              this.recordList.splice(index, 1, { ...this.recordForm });
            }
          } else {
            // æ–°å¢žè®°å½•
            this.recordForm.id = Date.now();
            this.recordList.push({ ...this.recordForm });
          }
@@ -918,13 +980,90 @@
        .catch(() => {});
    },
    // é™„件相关方法
    // åŸ¹å…»è®°å½•附件相关方法
    handleCultureAttachmentChange(fileList) {
      this.cultureForm.attachments = fileList;
      this.cultureFileList = fileList;
    },
    handleCultureUploadSuccess({ file, fileList, response }) {
      if (response.code === 200) {
        const attachmentObj = {
          fileName: file.name,
          path: response.fileUrl || file.url,
          fileUrl: response.fileUrl || file.url,
          fileType: this.getFileExtension(file.name),
          fileSize: file.size,
          uploadTime: dayjs().format("YYYY-MM-DD HH:mm:ss")
        };
        if (!Array.isArray(this.cultureForm.attachments)) {
          this.cultureForm.attachments = [];
        }
        this.cultureForm.attachments.push(attachmentObj);
        this.cultureFileList = fileList;
        this.$message.success("文件上传成功");
      }
    },
    handleCultureUploadError({ file, fileList, error }) {
      console.error("培养记录附件上传失败:", error);
      this.$message.error("文件上传失败,请重试");
    },
    handleCultureAttachmentRemove(file) {
      if (file.url) {
        const index = this.cultureForm.attachments.findIndex(
          item => item.path === file.url || item.fileUrl === file.url
        );
        if (index > -1) {
          this.cultureForm.attachments.splice(index, 1);
          this.$message.success("附件删除成功");
        }
      }
    },
    // æŠ¤ç†è®°å½•附件相关方法
    handleRecordAttachmentChange(fileList) {
      this.recordForm.attachments = fileList;
      this.recordFileList = fileList;
    },
    handleRecordUploadSuccess({ file, fileList, response }) {
      if (response.code === 200) {
        const attachmentObj = {
          fileName: file.name,
          path: response.fileUrl || file.url,
          fileUrl: response.fileUrl || file.url,
          fileType: this.getFileExtension(file.name),
          fileSize: file.size,
          uploadTime: dayjs().format("YYYY-MM-DD HH:mm:ss")
        };
        if (!Array.isArray(this.recordForm.attachments)) {
          this.recordForm.attachments = [];
        }
        this.recordForm.attachments.push(attachmentObj);
        this.recordFileList = fileList;
        this.$message.success("文件上传成功");
      }
    },
    handleRecordUploadError({ file, fileList, error }) {
      console.error("护理记录附件上传失败:", error);
      this.$message.error("文件上传失败,请重试");
    },
    handleRecordAttachmentRemove(file) {
      if (file.url) {
        const index = this.recordForm.attachments.findIndex(
          item => item.path === file.url || item.fileUrl === file.url
        );
        if (index > -1) {
          this.recordForm.attachments.splice(index, 1);
          this.$message.success("附件删除成功");
        }
      }
    },
    handleViewCultureAttachments(row) {
@@ -937,6 +1076,124 @@
      this.currentAttachmentList = row.attachments || [];
      this.attachmentPreviewTitle = `护理核查记录附件 - ${row.recorder}`;
      this.attachmentPreviewVisible = true;
    },
    handleAttachmentPreviewClose() {
      this.currentAttachmentList = [];
      this.attachmentPreviewTitle = "";
    },
    handlePreviewAttachment(file) {
      this.currentPreviewFile = {
        fileName: file.fileName,
        fileUrl: file.path || file.fileUrl,
        fileType: this.getFileType(file.fileName)
      };
      this.filePreviewVisible = true;
    },
    handleDownloadAttachment(file) {
      const fileUrl = file.path || 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 = fileName.split(".").pop().toLowerCase();
      const imageTypes = ["jpg", "jpeg", "png", "gif", "bmp", "webp"];
      const pdfTypes = ["pdf"];
      const officeTypes = ["doc", "docx", "xls", "xlsx", "ppt", "pptx"];
      if (imageTypes.includes(extension)) return "image";
      if (pdfTypes.includes(extension)) return "pdf";
      if (officeTypes.includes(extension)) return "office";
      return "other";
    },
    /** èŽ·å–æ–‡ä»¶å›¾æ ‡é¢œè‰² */
    getFileIconColor(fileName) {
      const type = this.getFileType(fileName);
      const colorMap = {
        image: "#67C23A",
        pdf: "#F56C6C",
        office: "#409EFF",
        other: "#909399"
      };
      return colorMap[type] || "#909399";
    },
    /** èŽ·å–æ–‡ä»¶æ ‡ç­¾ç±»åž‹ */
    getFileTagType(fileName) {
      const type = this.getFileType(fileName);
      const typeMap = {
        image: "success",
        pdf: "danger",
        office: "primary",
        other: "info"
      };
      return typeMap[type] || "info";
    },
    /** èŽ·å–æ–‡ä»¶ç±»åž‹æ–‡æœ¬ */
    getFileTypeText(fileName) {
      const type = this.getFileType(fileName);
      const textMap = {
        image: "图片",
        pdf: "PDF",
        office: "文档",
        other: "其他"
      };
      return textMap[type] || "未知";
    },
    /** æ£€æŸ¥æ˜¯å¦å¯é¢„览 */
    isPreviewable(fileName) {
      const type = this.getFileType(fileName);
      return ["image", "pdf"].includes(type);
    },
    /** èŽ·å–æ–‡ä»¶æ‰©å±•å */
    getFileExtension(filename) {
      return filename.split(".").pop().toLowerCase();
    },
    /** æ ¼å¼åŒ–文件大小 */
    formatFileSize(bytes) {
      if (!bytes || 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];
    },
    /** æ—¥æœŸæ—¶é—´æ ¼å¼åŒ– */
    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;
      }
    },
    // è¯„估数据变更处理
@@ -1002,4 +1259,9 @@
.fixed-width .el-button {
  margin: 0 2px;
}
.file-name {
  font-size: 13px;
  margin-left: 8px;
}
</style>
src/views/project/DonationProcess/index.vue
@@ -396,7 +396,12 @@
  components: {
    TerminateRestoreModal
  },
  dicts: ["sys_donornode",'sys_BloodType', "sys_EthicalReview", "sys_BaseAssessConclusion"],
  dicts: [
    "sys_donornode",
    "sys_BloodType",
    "sys_EthicalReview",
    "sys_BaseAssessConclusion"
  ],
  data() {
    return {
      loading: false,
@@ -593,8 +598,10 @@
    /** æŸ¥çœ‹è¯¦æƒ… */
    handleDetail(row) {
      this.currentRecord = { ...row };
      this.detailVisible = true;
      this.$router.push({
        path: "/case/course",
        query: { id: row.id, organType: "edit" }
      });
    },
    /** ç»ˆæ­¢æ“ä½œ */
src/views/project/donatebaseinfo/EditCaseModal.vue
@@ -45,9 +45,12 @@
            <el-col :span="6">
              <el-form-item label="性别" prop="sex">
                <el-select v-model="formData.sex" placeholder="请选择性别">
                  <el-option label="未知" value="0" />
                  <el-option label="男" value="1" />
                  <el-option label="女" value="2" />
                  <el-option
                    v-for="dict in dict.type.sys_user_sex || []"
                    :key="dict.value"
                    :label="dict.label"
                    :value="parseInt(dict.value)"
                  />
                </el-select>
              </el-form-item>
            </el-col>
@@ -57,9 +60,12 @@
                  v-model="formData.idcardtype"
                  placeholder="请选择证件类型"
                >
                  <el-option label="身份证" :value="1" />
                  <el-option label="军人证" :value="2" />
                  <el-option label="护照" :value="3" />
                  <el-option
                    v-for="dict in dict.type.sys_IDType || []"
                    :key="dict.value"
                    :label="dict.label"
                    :value="parseInt(dict.value)"
                  />
                </el-select>
              </el-form-item>
            </el-col>
@@ -96,7 +102,7 @@
              <el-form-item label="民族" prop="nation">
                <el-select v-model="formData.nation" placeholder="请选择民族">
                  <el-option
                    v-for="dict in dictOptions.sys_nation"
                    v-for="dict in dict.type.sys_nation || []"
                    :key="dict.value"
                    :label="dict.label"
                    :value="dict.value"
@@ -130,7 +136,7 @@
                  placeholder="请选择学历"
                >
                  <el-option
                    v-for="dict in dictOptions.sys_education"
                    v-for="dict in dict.type.sys_education || []"
                    :key="dict.value"
                    :label="dict.label"
                    :value="dict.value"
@@ -145,7 +151,7 @@
                  placeholder="请选择职业"
                >
                  <el-option
                    v-for="dict in dictOptions.sys_occupation"
                    v-for="dict in dict.type.sys_occupation || []"
                    :key="dict.value"
                    :label="dict.label"
                    :value="dict.value"
@@ -204,14 +210,17 @@
              </el-form-item>
            </el-col>
          </el-row>
          <el-row :gutter="20">
            <el-col :span="12">
              <el-form-item label="血型" prop="bloodtype">
                <el-radio-group v-model="formData.bloodtype">
                  <el-radio label="1">A型</el-radio>
                  <el-radio label="2">B型</el-radio>
                  <el-radio label="3">O型</el-radio>
                  <el-radio label="4">AB型</el-radio>
                  <el-radio
                    v-for="dict in dict.type.sys_BloodType || []"
                    :key="dict.value"
                    :label="dict.value"
                    >{{ dict.label }}</el-radio
                  >
                </el-radio-group>
              </el-form-item>
            </el-col>
@@ -222,8 +231,85 @@
                    v-for="dict in dict.type.sys_bloodtype_rhd || []"
                    :key="dict.value"
                    :label="dict.value"
                  >{{ dict.label }}</el-radio>
                    >{{ dict.label }}</el-radio
                  >
                </el-radio-group>
              </el-form-item>
            </el-col>
          </el-row>
          <!-- ç–¾ç—…类型 -->
          <el-row>
            <el-form-item label="疾病类型" align="left">
              <el-checkbox-group v-model="formData.diseasetype">
                <el-checkbox
                  v-for="dict in dict.type.sys_DiseaseType || []"
                  :key="dict.value"
                  :label="dict.value"
                >
                  {{ dict.label }}
                </el-checkbox>
              </el-checkbox-group>
            </el-form-item>
            <el-form-item label="其他" prop="diseasetypeOther">
              <el-input
                v-model="formData.diseasetypeOther"
                placeholder="请输入其他"
              />
            </el-form-item>
          </el-row>
          <!-- ä¼ æŸ“ç—… -->
          <el-row>
            <el-col :span="12">
              <el-form-item align="left" label="传染病">
                <el-checkbox-group v-model="formData.infectious">
                  <el-checkbox
                    v-for="dict in dict.type.sys_Infectious || []"
                    :key="dict.value"
                    :label="dict.value"
                  >
                    {{ dict.label }}
                  </el-checkbox>
                </el-checkbox-group>
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item align="left" label="其他" prop="infectiousOther">
                <el-input
                  v-model="formData.infectiousOther"
                  placeholder="请输入其他"
                />
              </el-form-item>
            </el-col>
          </el-row>
          <!-- ç—…人状况和其他情况 -->
          <el-row>
            <el-col :span="9">
              <el-form-item align="left" label="病人状况">
                <el-checkbox-group v-model="formData.patientstate">
                  <el-checkbox
                    v-for="dict in dict.type.sys_patientstate || []"
                    :key="dict.value"
                    :label="dict.value"
                  >
                    {{ dict.label }}
                  </el-checkbox>
                </el-checkbox-group>
              </el-form-item>
            </el-col>
            <el-col :span="15" align="left">
              <el-form-item label="其他情况">
                <el-checkbox-group v-model="formData.othercases">
                  <el-checkbox
                    v-for="dict in dict.type.sys_OtherCases || []"
                    :key="dict.value"
                    :label="dict.value"
                  >
                    {{ dict.label }}
                  </el-checkbox>
                </el-checkbox-group>
              </el-form-item>
            </el-col>
          </el-row>
@@ -344,6 +430,128 @@
          </el-row>
        </el-card>
        <!-- æ„æ„¿å’Œäº²å±žä¿¡æ¯éƒ¨åˆ† -->
        <el-card header="意愿和亲属信息" class="form-section">
          <!-- æœ¬äººæ„æ„¿ -->
          <el-row>
            <el-col :span="24">
              <el-form-item align="left" label="本人意愿 ">
                <el-checkbox-group v-model="formData.selfwill">
                  <el-checkbox
                    v-for="dict in dict.type.sys_SelfWill || []"
                    :key="dict.value"
                    :label="dict.value"
                  >
                    {{ dict.label }}
                  </el-checkbox>
                </el-checkbox-group>
              </el-form-item>
            </el-col>
          </el-row>
          <!-- äº²å±žçж况 -->
          <el-row>
            <el-col :span="12">
              <el-form-item
                label="亲属状况"
                prop="kinship"
                class="relation"
                align="left"
              >
                <el-checkbox-group v-model="formData.kinship">
                  <el-checkbox
                    v-for="dict in dict.type.sys_Kinship || []"
                    :key="dict.value"
                    :label="dict.value"
                  >
                    {{ dict.label }}
                  </el-checkbox>
                </el-checkbox-group>
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="其他" prop="kinshipOther">
                <el-input
                  v-model="formData.kinshipOther"
                  placeholder="请输入其他"
                />
              </el-form-item>
            </el-col>
          </el-row>
          <!-- ä¸»è¦äº²å±ž -->
          <el-row>
            <el-col :span="12">
              <el-form-item label="主要亲属" prop="majorrelatives">
                <el-input
                  v-model="formData.majorrelatives"
                  placeholder="请输入主要亲属"
                />
              </el-form-item>
            </el-col>
            <el-col :span="8">
              <el-form-item label="与捐赠者关系" prop="familyrelations">
                <el-select
                  v-model="formData.familyrelations"
                  placeholder="请选择与捐赠者关系"
                >
                  <el-option
                    v-for="dict in dict.type.sys_FamilyRelation || []"
                    :key="dict.value"
                    :label="dict.label"
                    :value="dict.value"
                  />
                </el-select>
              </el-form-item>
            </el-col>
          </el-row>
          <!-- ä¿¡æ¯æ¥æº -->
          <el-row>
            <el-col :span="12">
              <el-form-item align="left" label="信息来源">
                <el-checkbox-group v-model="formData.infosources">
                  <el-checkbox
                    v-for="dict in dict.type.sys_InfoSources || []"
                    :key="dict.value"
                    :label="dict.value"
                  >
                    {{ dict.label }}
                  </el-checkbox>
                </el-checkbox-group>
              </el-form-item>
            </el-col>
            <el-col :span="8">
              <el-form-item label="其他" prop="infosourcesOther">
                <el-input
                  v-model="formData.infosourcesOther"
                  placeholder="请输入信息来源其他"
                />
              </el-form-item>
            </el-col>
          </el-row>
          <!-- ä¿¡æ¯å‘˜ -->
          <el-row>
            <el-col :span="8">
              <el-form-item label="信息员" prop="infoname">
                <el-input
                  v-model="formData.infoname"
                  placeholder="请输入信息员"
                />
              </el-form-item>
            </el-col>
            <el-col :span="8">
              <el-form-item label="联系电话" prop="infophone">
                <el-input
                  v-model="formData.infophone"
                  placeholder="请输入信息员联系电话"
                />
              </el-form-item>
            </el-col>
          </el-row>
        </el-card>
        <!-- æçŒ®ä¿¡æ¯éƒ¨åˆ† -->
        <el-card header="捐献信息" class="form-section">
          <el-row :gutter="20">
@@ -354,7 +562,7 @@
                  placeholder="请选择捐献类别"
                >
                  <el-option
                    v-for="dict in dictOptions.sys_DonationCategory"
                    v-for="dict in dict.type.sys_DonationCategory || []"
                    :key="dict.value"
                    :label="dict.label"
                    :value="dict.value"
@@ -400,6 +608,38 @@
                <el-input
                  v-model="formData.acquisitiontissuename"
                  placeholder="请输入获取组织名称"
                />
              </el-form-item>
            </el-col>
          </el-row>
          <!-- çº¢åå­—会和联系人 -->
          <el-row>
            <el-col :span="8">
              <el-form-item align="left" label="红十字会" prop="redorganno">
                <org-selecter
                  ref="addCrossOrgSelect"
                  :org-type="'2'"
                  v-model="formData.redorganno"
                />
              </el-form-item>
            </el-col>
            <el-col :span="8">
              <el-form-item label="联系人" prop="contactperson">
                <el-input
                  v-model="formData.contactperson"
                  placeholder="请输入联系人"
                />
              </el-form-item>
            </el-col>
            <el-col :span="8">
              <el-form-item label="联系时间" prop="contacttime">
                <el-date-picker
                  v-model="formData.contacttime"
                  type="datetime"
                  value-format="yyyy-MM-dd HH:mm:ss"
                  placeholder="选择报告时间"
                  style="width: 100%"
                />
              </el-form-item>
            </el-col>
@@ -496,7 +736,25 @@
    LiAreaSelect
  },
  dicts: ["sys_bloodtype_rhd", "sys_BloodType"],
  // æ·»åŠ æ‰€æœ‰éœ€è¦çš„å­—å…¸ç±»åž‹
  dicts: [
    "sys_bloodtype_rhd",
    "sys_BloodType",
    "sys_user_sex",
    "sys_IDType",
    "sys_nation",
    "sys_education",
    "sys_occupation",
    "sys_DiseaseType",
    "sys_Infectious",
    "sys_patientstate",
    "sys_OtherCases",
    "sys_SelfWill",
    "sys_Kinship",
    "sys_FamilyRelation",
    "sys_InfoSources",
    "sys_DonationCategory"
  ],
  props: {
    visible: {
@@ -564,7 +822,7 @@
        return this.visible;
      },
      set(value) {
        this.$emit('update:visible', value);
        this.$emit("update:visible", value);
        if (!value) {
          this.handleClose();
        }
@@ -592,15 +850,15 @@
    }
  },
  created() {
    console.log('EditCaseModal created');
    console.log('visible:', this.visible);
    console.log('editData:', this.editData);
    console.log("EditCaseModal created");
    console.log("visible:", this.visible);
    console.log("editData:", this.editData);
  },
  mounted() {
    console.log('EditCaseModal mounted');
    console.log('visible:', this.visible);
    console.log('editData:', this.editData);
    console.log('isEdit:', this.isEdit);
    console.log("EditCaseModal mounted");
    console.log("visible:", this.visible);
    console.log("editData:", this.editData);
    console.log("isEdit:", this.isEdit);
  },
  methods: {
    getDefaultFormData() {
@@ -642,14 +900,32 @@
        illnessoverview: null,
        coordinatorNo: null,
        coordinatorName: null,
        diseasetype: [],
        infectious: [],
        patientstate: [],
        othercases: [],
        // åœ°å€ä¿¡æ¯
        residenceaddress: null,
        residenceprovince: null,
        residencecity: null,
        residencetown: null,
        registeraddress: null,
        registerprovince: null,
        registercity: null,
        registertown: null,
        // æ„æ„¿å’Œäº²å±žä¿¡æ¯
        selfwill: [],
        kinship: [],
        majorrelatives: null,
        familyrelations: null,
        infosources: [],
        infoname: null,
        infophone: null,
        redorganno: null,
        contactperson: null,
        contacttime: null,
        // æçŒ®ä¿¡æ¯
        donationcategory: null,
@@ -665,25 +941,22 @@
        reporttime: null,
        deptid: null,
        // æ•°ç»„字段
        diseasetype: [],
        infectious: [],
        selfwill: [],
        othercases: [],
        infosources: [],
        kinship: [],
        patientstate: []
        // å…¶ä»–字段
        diseasetypeOther: null,
        infectiousOther: null,
        kinshipOther: null,
        infosourcesOther: null
      };
    },
    async initForm() {
      console.log('初始化表单,isEdit:', this.isEdit);
      console.log("初始化表单,isEdit:", this.isEdit);
      try {
        if (this.isEdit && this.editData && this.editData.id) {
          console.log('加载编辑数据,id:', this.editData.id);
          console.log("加载编辑数据,id:", this.editData.id);
          await this.loadEditData();
        } else {
          console.log('新增模式,初始化表单');
          console.log("新增模式,初始化表单");
          this.formData = this.getDefaultFormData();
          this.formData.nationality = "中国";
          this.formData.bloodtype = "0";
@@ -708,7 +981,7 @@
      try {
        const response = await getDonatebaseinfo(this.editData.id);
        const data = response.data;
        console.log('加载到的数据:', data);
        console.log("加载到的数据:", data);
        // å¤„理数组字段
        const arrayFields = [
@@ -721,15 +994,15 @@
          "patientstate"
        ];
        arrayFields.forEach(field => {
          if (data[field]) {
          if (data[field] && typeof data[field] === "string") {
            data[field] = data[field].split(",");
          } else {
          } else if (!data[field]) {
            data[field] = [];
          }
        });
        this.formData = { ...this.getDefaultFormData(), ...data };
        console.log('合并后的formData:', this.formData);
        console.log("合并后的formData:", this.formData);
        // è®¾ç½®åœ°å€ä¿¡æ¯
        if (data.residenceprovince) {
@@ -864,7 +1137,7 @@
    },
    handleClose() {
      console.log('关闭弹框');
      console.log("关闭弹框");
      this.isEdit = false;
      this.submitLoading = false;
      this.formData = this.getDefaultFormData();
@@ -880,12 +1153,14 @@
      this.submitLoading = true;
      try {
        const submitData = this.processSubmitData();
        console.log('提交数据:', submitData);
        console.log("提交数据:", submitData);
        const result = await updateDonatebaseinfo(submitData);
        if (result.code === 200) {
          this.$message.success(this.isEdit ? "更新成功" : "新增成功");
          this.$emit("success", result.data);
          console.log(1122);
          this.handleClose();
        } else {
          this.$message.error(result.msg || "操作失败");
@@ -935,6 +1210,11 @@
          "YYYY-MM-DD HH:mm:ss"
        );
      }
      if (data.contacttime) {
        data.contacttime = this.$moment(data.contacttime).format(
          "YYYY-MM-DD HH:mm:ss"
        );
      }
      // è®¾ç½®é»˜è®¤å€¼
      if (!data.recordstate) {
src/views/project/donatebaseinfo/index.vue
@@ -553,6 +553,7 @@
    /** å¤„理编辑弹窗关闭 */
    handleEditClosed() {
      this.currentEditData = {};
      this.editModalVisible = false;
    },
    handleModalVisibleChange(newVisible) {