WXL
2026-05-08 6623e51d0b1edb191ca50201c0130cb5ed1beda8
青岛推送
已修改5个文件
已添加3个文件
4886 ■■■■ 文件已修改
src/api/businessApi/followup.js 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/GetWitness/GetWitnessInfo.vue 312 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/GetWitness/index.vue 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/OrganUtilization/OrganUtilizationInfo.vue 2330 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/allocation/allocationInfo.vue 76 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/followupVisit/index.vue 1349 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/followupVisit/info.vue 743 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/project/components/orgselect/index.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/businessApi/followup.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,48 @@
import request from '@/utils/request'
// æ¡ˆä¾‹åˆ—表及详情
export function listFollowup(data) {
  return request({
    url: '/project/donatefollowup/list',
    method: 'post',
    data: data
  })
}
// å—者随访修改
export function addFollowup(data) {
  return request({
    url: '/project/donatefollowup/add',
    method: 'post',
    data: data
  })
}
// å—者随访修改
export function updateFollowup(data) {
  return request({
    url: '/project/donatefollowup/edit',
    method: 'post',
    data: data
  })
}
// å—者随访详情
export function getFollowup(id) {
  return request({
    url: '/project/donatefollowup/' + id,
    method: 'get'
  })
}
// åˆ é™¤
export function delFollowup(id) {
  return request({
    url: '/project/donatefollowup/remove/' + id,
    method: 'get'
  })
}
// å¯¼å‡ºå—者随访
export function exportFollowup(query) {
  return request({
    url: '/project/donatefollowup/export',
    method: 'get',
    params: query
  })
}
src/views/business/GetWitness/GetWitnessInfo.vue
@@ -13,7 +13,6 @@
          <el-button
            type="success"
            @click="handleProcure"
            :disabled="form.recordstate === 'completed'"
            :loading="confirmLoading"
          >
            ç¡®è®¤èŽ·å–
@@ -22,7 +21,6 @@
      </div>
      <el-form :model="form" ref="form" :rules="rules" label-width="120px">
        <!-- æ‰‹æœ¯ç›¸å…³ä¿¡æ¯ -->
        <el-divider content-position="left">手术信息</el-divider>
@@ -39,7 +37,6 @@
                type="datetime"
                value-format="yyyy-MM-dd HH:mm:ss"
                style="width: 100%"
                :disabled="form.recordstate === 'completed'"
              />
            </el-form-item>
          </el-col>
@@ -50,7 +47,6 @@
                type="datetime"
                value-format="yyyy-MM-dd HH:mm:ss"
                style="width: 100%"
                :disabled="form.recordstate === 'completed'"
              />
            </el-form-item>
          </el-col>
@@ -67,7 +63,6 @@
                type="datetime"
                value-format="yyyy-MM-dd HH:mm:ss"
                style="width: 100%"
                :disabled="form.recordstate === 'completed'"
              />
            </el-form-item>
          </el-col>
@@ -81,7 +76,6 @@
                type="datetime"
                value-format="yyyy-MM-dd HH:mm:ss"
                style="width: 100%"
                :disabled="form.recordstate === 'completed'"
              />
            </el-form-item>
          </el-col>
@@ -89,30 +83,22 @@
        <el-row :gutter="20">
          <el-col :span="8">
            <el-form-item
              label="门静脉插管时间"
              prop="portalveincannulatime"
            >
            <el-form-item label="门静脉插管时间" prop="portalveincannulatime">
              <el-date-picker
                v-model="form.portalveincannulatime"
                type="datetime"
                value-format="yyyy-MM-dd HH:mm:ss"
                style="width: 100%"
                :disabled="form.recordstate === 'completed'"
              />
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item
              label="门静脉灌注时间"
              prop="portalveinperfusiontime"
            >
            <el-form-item label="门静脉灌注时间" prop="portalveinperfusiontime">
              <el-date-picker
                v-model="form.portalveinperfusiontime"
                type="datetime"
                value-format="yyyy-MM-dd HH:mm:ss"
                style="width: 100%"
                :disabled="form.recordstate === 'completed'"
              />
            </el-form-item>
          </el-col>
@@ -122,11 +108,11 @@
        <el-divider content-position="left">协调员信息</el-divider>
        <el-row :gutter="20">
          <el-col :span="8">
          <!-- <el-col :span="8">
            <el-form-item label="协调员姓名" prop="coordinatorName">
              <el-input v-model="form.coordinatorName" />
            </el-form-item>
          </el-col>
          </el-col> -->
          <el-col :span="8">
            <el-form-item label="进手术室时间" prop="coordinatorInOperating">
              <el-date-picker
@@ -134,7 +120,6 @@
                type="datetime"
                value-format="yyyy-MM-dd HH:mm:ss"
                style="width: 100%"
                :disabled="form.recordstate === 'completed'"
              />
            </el-form-item>
          </el-col>
@@ -145,7 +130,6 @@
                type="datetime"
                value-format="yyyy-MM-dd HH:mm:ss"
                style="width: 100%"
                :disabled="form.recordstate === 'completed'"
              />
            </el-form-item>
          </el-col>
@@ -164,7 +148,6 @@
                type="datetime"
                value-format="yyyy-MM-dd HH:mm:ss"
                style="width: 100%"
                :disabled="form.recordstate === 'completed'"
              />
            </el-form-item>
          </el-col>
@@ -212,33 +195,6 @@
            </el-form-item>
          </el-col>
        </el-row>
        <!-- è®°å½•信息 -->
        <el-divider content-position="left">记录信息</el-divider>
        <el-row :gutter="20">
          <el-col :span="8">
            <el-form-item label="住院号" prop="donorno">
              <el-input v-model="form.donorno" readonly />
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="所在医疗机构" prop="treatmenthospitalname">
              <el-input
                v-model="form.treatmenthospitalname"
                placeholder="请输入医疗机构名称"
              />
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="医疗机构编码" prop="treatmenthospitalno">
              <el-input
                v-model="form.treatmenthospitalno"
                placeholder="请输入医疗机构编码"
              />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
    </el-card>
@@ -247,13 +203,15 @@
      <div slot="header" class="clearfix">
        <span class="detail-title">器官获取记录</span>
        <div style="float: right;">
          <el-tag
            :type="
              form.recordstate === 'completed' ? 'success' : 'warning'
            "
          <!-- <el-tag
            :type="form.witnessState === 'completed' ? 'success' : 'warning'"
          >
            {{ form.recordstate === "completed" ? "已完成" : "进行中" }}
          </el-tag>
            {{ form.witnessState === "completed" ? "已完成" : "进行中" }}
          </el-tag> -->
          <dict-tag
            :options="dict.type.sys_user_sex"
            :value="form.witnessState"
          />
        </div>
      </div>
@@ -274,7 +232,6 @@
                  v-for="dict in dict.type.sys_Organ || []"
                  :key="dict.value"
                  :label="dict.value"
                  :disabled="form.recordstate === 'completed'"
                >
                  {{ dict.label }}
                </el-checkbox>
@@ -323,7 +280,6 @@
                      type="datetime"
                      value-format="yyyy-MM-dd HH:mm:ss"
                      placeholder="选择获取开始时间"
                      :disabled="form.recordstate === 'completed'"
                    />
                  </template>
                </el-table-column>
@@ -332,18 +288,17 @@
                  label="器官离体时间"
                  align="center"
                  width="180"
                  prop="organGetTime"
                  prop="organgettime"
                >
                  <template slot-scope="scope">
                    <el-date-picker
                      clearable
                      size="small"
                      style="width: 100%"
                      v-model="scope.row.organGetTime"
                      v-model="scope.row.organgettime"
                      type="datetime"
                      value-format="yyyy-MM-dd HH:mm:ss"
                      placeholder="选择器官离体时间"
                      :disabled="form.recordstate === 'completed'"
                    />
                  </template>
                </el-table-column>
@@ -352,14 +307,13 @@
                  label="获取医院"
                  align="center"
                  width="200"
                  prop="gainHospitalNo"
                  prop="gainhospitalno"
                >
                  <template slot-scope="scope">
                    <el-select
                      v-model="scope.row.gainHospitalNo"
                      v-model="scope.row.gainhospitalno"
                      placeholder="请选择获取医院"
                      style="width: 100%"
                      :disabled="form.recordstate === 'completed'"
                      @change="handleHospitalChange(scope.row, $event)"
                    >
                      <el-option
@@ -376,18 +330,17 @@
                  label="获取医师"
                  align="center"
                  width="120"
                  prop="organGetDoctor"
                  prop="organgetdoct"
                >
                  <template slot-scope="scope">
                    <el-input
                      v-model="scope.row.organGetDoctor"
                      v-model="scope.row.organgetdoct"
                      placeholder="获取医师"
                      :disabled="form.recordstate === 'completed'"
                    />
                  </template>
                </el-table-column>
                <el-table-column
                <!-- <el-table-column
                  label="助手"
                  align="center"
                  width="120"
@@ -397,12 +350,12 @@
                    <el-input
                      v-model="scope.row.assistant"
                      placeholder="助手"
                      :disabled="form.recordstate === 'completed'"
                    />
                  </template>
                </el-table-column>
                </el-table-column> -->
                <el-table-column
                <!-- <el-table-column
                  label="获取护士"
                  align="center"
                  width="120"
@@ -412,7 +365,7 @@
                    <el-input
                      v-model="scope.row.procurementNurse"
                      placeholder="获取护士"
                      :disabled="form.recordstate === 'completed'"
                    />
                  </template>
                </el-table-column>
@@ -427,41 +380,25 @@
                    <el-input
                      v-model="scope.row.operatingRoomNurse"
                      placeholder="手术室护士"
                      :disabled="form.recordstate === 'completed'"
                    />
                  </template>
                </el-table-column>
                <el-table-column
                  label="麻醉医生"
                  align="center"
                  width="120"
                  prop="anesthesiologist"
                >
                  <template slot-scope="scope">
                    <el-input
                      v-model="scope.row.anesthesiologist"
                      placeholder="麻醉医生"
                      :disabled="form.recordstate === 'completed'"
                    />
                  </template>
                </el-table-column>
                </el-table-column> -->
                <el-table-column
                  label="获取状态"
                  align="center"
                  width="120"
                  prop="organState"
                  prop="organstate"
                >
                  <template slot-scope="scope">
                    <el-select
                      v-model="scope.row.organState"
                      v-model="scope.row.organstate"
                      placeholder="请选择获取状态"
                      style="width: 100%"
                      :disabled="form.recordstate === 'completed'"
                    >
                      <el-option
                        v-for="dict in organStateList"
                        v-for="dict in dict.type.Obtain_status"
                        :key="dict.value"
                        :label="dict.label"
                        :value="dict.value"
@@ -473,16 +410,15 @@
                <el-table-column
                  label="说明"
                  align="center"
                  prop="notGetReason"
                  prop="notgetreason"
                  min-width="200"
                >
                  <template slot-scope="scope">
                    <el-input
                      type="textarea"
                      clearable
                      v-model="scope.row.notGetReason"
                      v-model="scope.row.notgetreason"
                      placeholder="请输入未获取说明"
                      :disabled="form.recordstate === 'completed'"
                    />
                  </template>
                </el-table-column>
@@ -492,7 +428,6 @@
                  align="center"
                  width="120"
                  class-name="small-padding fixed-width"
                  v-if="form.recordstate !== 'completed'"
                >
                  <template slot-scope="scope">
                    <el-button
@@ -511,16 +446,22 @@
        </el-row>
        <!-- èŽ·å–ç»Ÿè®¡ä¿¡æ¯ -->
        <div
        <!-- <div
          class="procurement-stats"
          v-if="procurementData.serviceDonationwitnessorgans && procurementData.serviceDonationwitnessorgans.length > 0"
          v-if="
            procurementData.serviceDonationwitnessorgans &&
              procurementData.serviceDonationwitnessorgans.length > 0
          "
        >
          <el-row :gutter="20">
            <el-col :span="6">
              <div class="stat-item">
                <span class="stat-label">已获取器官:</span>
                <span class="stat-value"
                  >{{ procurementData.serviceDonationwitnessorgans.length }} ä¸ª</span
                  >{{
                    procurementData.serviceDonationwitnessorgans.length
                  }}
                  ä¸ª</span
                >
              </div>
            </el-col>
@@ -542,48 +483,26 @@
                <span class="stat-value">
                  <el-tag
                    :type="
                      form.recordstate === 'completed'
                        ? 'success'
                        : 'warning'
                      form.witnessState === 'completed' ? 'success' : 'warning'
                    "
                  >
                    {{
                      form.recordstate === "completed"
                        ? "已完成"
                        : "进行中"
                    }}
                    {{ form.witnessState === "completed" ? "已完成" : "进行中" }}
                  </el-tag>
                </span>
              </div>
            </el-col>
          </el-row>
        </div>
        </div> -->
        <div v-else class="empty-procurement">
        <div
          v-if="!procurementData.serviceDonationwitnessorgans"
          class="empty-procurement"
        >
          <el-empty description="暂无获取记录" :image-size="80">
            <span>请先选择要获取的器官</span>
          </el-empty>
        </div>
      </el-form>
      <div class="dialog-footer" v-if="form.recordstate !== 'completed'">
        <el-button
          type="primary"
          @click="handleSaveProcurement"
          :loading="saveLoading"
          :disabled="!procurementData.serviceDonationwitnessorgans || procurementData.serviceDonationwitnessorgans.length === 0"
        >
          ä¿å­˜èŽ·å–è®°å½•
        </el-button>
        <el-button
          type="success"
          @click="handleConfirmProcurement"
          :loading="confirmLoading"
          :disabled="incompleteRecords > 0"
        >
          ç¡®è®¤å®ŒæˆèŽ·å–
        </el-button>
      </div>
    </el-card>
    <!-- é™„件管理部分优化 -->
@@ -610,10 +529,7 @@
      />
      <!-- é™„件列表展示 -->
      <div
        class="attachment-list"
        v-if="attachments && attachments.length > 0"
      >
      <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">
@@ -687,9 +603,9 @@
          </el-col>
          <el-col :span="12">
            <el-form-item label="获取状态">
              <el-select v-model="currentRecord.organState" style="width: 100%">
              <el-select v-model="currentRecord.organstate" style="width: 100%">
                <el-option
                  v-for="dict in organStateList"
                  v-for="dict in dict.type.Obtain_status"
                  :key="dict.value"
                  :label="dict.label"
                  :value="dict.value"
@@ -703,7 +619,7 @@
          <el-col :span="12">
            <el-form-item label="获取医师">
              <el-input
                v-model="currentRecord.organGetDoctor"
                v-model="currentRecord.organgetdoct"
                placeholder="请输入获取医师"
              />
            </el-form-item>
@@ -746,12 +662,12 @@
        <el-form-item
          label="未获取说明"
          v-if="currentRecord.organState === '0'"
          v-if="currentRecord.organstate === '0'"
        >
          <el-input
            type="textarea"
            :rows="3"
            v-model="currentRecord.notGetReason"
            v-model="currentRecord.notgetreason"
            placeholder="请输入未获取的原因说明"
          />
        </el-form-item>
@@ -772,10 +688,17 @@
    >
      <div v-if="currentPreviewFile">
        <div v-if="currentPreviewFile.fileType === 'image'">
          <img :src="currentPreviewFile.fileUrl" style="max-width: 100%; max-height: 500px;" />
          <img
            :src="currentPreviewFile.fileUrl"
            style="max-width: 100%; max-height: 500px;"
          />
        </div>
        <div v-else-if="currentPreviewFile.fileType === 'pdf'">
          <iframe :src="currentPreviewFile.fileUrl" width="100%" height="500px"></iframe>
          <iframe
            :src="currentPreviewFile.fileUrl"
            width="100%"
            height="500px"
          ></iframe>
        </div>
        <div v-else>
          <p>不支持预览此文件类型,请下载查看</p>
@@ -786,7 +709,7 @@
</template>
<script>
import { witnessList, witnessadd, witnessedit, } from "@/api/businessApi";
import { witnessList, witnessadd, witnessedit } from "@/api/businessApi";
import UploadAttachment from "@/components/UploadAttachment";
import CaseBasicInfo from "@/components/CaseBasicInfo";
import dayjs from "dayjs";
@@ -794,9 +717,15 @@
export default {
  name: "OrganProcurementDetail",
  components: {
    UploadAttachment,CaseBasicInfo
    UploadAttachment,
    CaseBasicInfo
  },
  dicts: ["sys_BloodType", "sys_DonationCategory", "sys_Organ"],
  dicts: [
    "sys_BloodType",
    "sys_DonationCategory",
    "sys_Organ",
    "Obtain_status"
  ],
  data() {
    return {
      caseId: null,
@@ -806,7 +735,7 @@
        infoid: undefined,
        name: "",
        inpatientno: "",
        recordstate: "pending",
        witnessState: "2",
        caseNo: "",
        donorno: "",
        treatmenthospitalname: "",
@@ -879,12 +808,6 @@
      selectedOrgans: [],
      // åŒ»é™¢åˆ—表
      hospitalList: [],
      // å™¨å®˜çŠ¶æ€åˆ—è¡¨
      organStateList: [
        { value: "1", label: "已获取" },
        { value: "0", label: "未获取" },
        { value: "2", label: "部分获取" }
      ],
      // èŽ·å–è®°å½•æ•°æ®
      procurementData: {
        serviceDonationwitnessorgans: []
@@ -894,7 +817,8 @@
      attachmentFileList: [],
      // é™„件相关配置
      attachmentLimit: 10,
      attachmentAccept: ".pdf,.jpg,.jpeg,.png,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.txt",
      attachmentAccept:
        ".pdf,.jpg,.jpeg,.png,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.txt",
      // ç¼–辑对话框
      editDialogVisible: false,
      currentRecord: {},
@@ -916,16 +840,16 @@
      return this.procurementData.serviceDonationwitnessorgans.filter(
        record =>
          !record.organStartTime ||
          !record.organGetTime ||
          !record.gainHospitalNo ||
          !record.organGetDoctor
          !record.organgettime ||
          !record.gainhospitalno ||
          !record.organgetdoct
      ).length;
    },
    // å”¯ä¸€åŒ»é™¢æ•°é‡
    uniqueHospitals() {
      if (!this.procurementData.serviceDonationwitnessorgans) return 0;
      const hospitals = this.procurementData.serviceDonationwitnessorgans
        .map(record => record.gainHospitalNo)
        .map(record => record.gainhospitalno)
        .filter(Boolean);
      return new Set(hospitals).size;
    },
@@ -973,7 +897,7 @@
      }
      this.form.infoid = infoid;
      this.generateDonorNo();
      // this.generateDonorNo();
      if (infoid) {
        this.getDetail(infoid);
@@ -982,12 +906,12 @@
      this.getHospitalData();
    },
    // ç”ŸæˆæçŒ®è€…编号
    generateDonorNo() {
      const timestamp = Date.now().toString();
      this.form.donorno = "D" + timestamp.slice(-8);
      this.form.caseNo = "CASE" + timestamp.slice(-6);
      this.form.inpatientno = "IP" + timestamp.slice(-6);
    },
    // generateDonorNo() {
    //   const timestamp = Date.now().toString();
    //   this.form.donorno = "D" + timestamp.slice(-8);
    //   this.form.caseNo = "CASE" + timestamp.slice(-6);
    //   this.form.inpatientno = "IP" + timestamp.slice(-6);
    // },
    // èŽ·å–è¯¦æƒ…
    async getDetail(infoid) {
      this.loading = true;
@@ -999,12 +923,16 @@
          response.data.length > 0
        ) {
          const data = response.data[0];
          if (!data.witnessState || data.witnessState == 1) {
            data.witnessState = "2";
          }
          // å¡«å……表单数据
          Object.assign(this.form, data);
          // åˆå§‹åŒ–附件
          if (this.form.attachments) {
          if (this.form.deathjudgeannex) {
            this.form.attachments = JSON.parse(this.form.deathjudgeannex);
            this.attachments = Array.isArray(this.form.attachments)
              ? [...this.form.attachments]
              : [];
@@ -1122,7 +1050,10 @@
        );
      }
      // å¦‚果选择了"左肾"或"右肾",取消"双肾"选择
      else if (selectedValues.includes("C64L") || selectedValues.includes("C64R")) {
      else if (
        selectedValues.includes("C64L") ||
        selectedValues.includes("C64R")
      ) {
        this.selectedOrgans = selectedValues.filter(item => item !== "C64");
      }
@@ -1133,7 +1064,10 @@
        );
      }
      // å¦‚果选择了"左肺"或"右肺",取消"全肺"选择
      else if (selectedValues.includes("C34L") || selectedValues.includes("C34R")) {
      else if (
        selectedValues.includes("C34L") ||
        selectedValues.includes("C34R")
      ) {
        this.selectedOrgans = selectedValues.filter(item => item !== "C34");
      }
    },
@@ -1147,16 +1081,16 @@
        organname: organName,
        organno: organValue,
        organStartTime: "",
        organGetTime: "",
        gainHospitalNo: "",
        gainHospitalName: "",
        organGetDoctor: "",
        organgettime: "",
        gainhospitalno: "",
        gainhospitalname: "",
        organgetdoct: "",
        assistant: "",
        procurementNurse: "",
        operatingRoomNurse: "",
        anesthesiologist: "",
        organState: "1",
        notGetReason: ""
        organstate: "1",
        notgetreason: ""
      });
    },
@@ -1166,7 +1100,7 @@
        item => item.hospitalNo === hospitalNo
      );
      if (hospital) {
        row.gainHospitalName = hospital.hospitalName;
        row.gainhospitalname = hospital.hospitalName;
      }
    },
    // ç¼–辑获取记录
@@ -1183,7 +1117,9 @@
    // ç¡®è®¤ç¼–辑
    handleEditConfirm() {
      if (this.currentEditIndex !== -1) {
        this.procurementData.serviceDonationwitnessorgans[this.currentEditIndex] = {
        this.procurementData.serviceDonationwitnessorgans[
          this.currentEditIndex
        ] = {
          ...this.currentRecord
        };
        this.$message.success("获取记录更新成功");
@@ -1194,9 +1130,9 @@
    getOrganRowClassName({ row }) {
      if (
        !row.organStartTime ||
        !row.organGetTime ||
        !row.gainHospitalNo ||
        !row.organGetDoctor
        !row.organgettime ||
        !row.gainhospitalno ||
        !row.organgetdoct
      ) {
        return "warning-row";
      }
@@ -1210,9 +1146,9 @@
          try {
            const saveData = {
              ...this.form,
              attachments: this.attachments,
              deathjudgeannex: JSON.stringify(this.attachments),
              organdonation: this.selectedOrgans.join(","),
              serviceDonationwitnessorgans:
              serviceDonationwitnessorganList:
                this.procurementData.serviceDonationwitnessorgans || []
            };
@@ -1286,11 +1222,13 @@
      })
        .then(async () => {
          this.confirmLoading = true;
          this.form.recordstate = "completed";
          this.form.operationendtime = this.form.operationendtime || new Date()
            .toISOString()
            .replace("T", " ")
            .substring(0, 19);
          this.form.witnessState = "3";
          this.form.operationendtime =
            this.form.operationendtime ||
            new Date()
              .toISOString()
              .replace("T", " ")
              .substring(0, 19);
          try {
            const saveData = {
@@ -1309,13 +1247,13 @@
              this.$message.error(
                "确认获取失败:" + (response.msg || "未知错误")
              );
              this.form.recordstate = "pending";
              this.form.witnessState = "2";
              this.form.operationendtime = "";
            }
          } catch (error) {
            console.error("确认获取失败:", error);
            this.$message.error("确认获取失败");
            this.form.recordstate = "pending";
            this.form.witnessState = "2";
            this.form.operationendtime = "";
          } finally {
            this.confirmLoading = false;
@@ -1415,7 +1353,10 @@
    /** èŽ·å–æ–‡ä»¶ç±»åž‹ */
    getFileType(fileName) {
      if (!fileName) return "other";
      const extension = fileName.split(".").pop().toLowerCase();
      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"];
@@ -1469,7 +1410,10 @@
    /** èŽ·å–æ–‡ä»¶æ‰©å±•å */
    getFileExtension(filename) {
      return filename.split(".").pop().toLowerCase();
      return filename
        .split(".")
        .pop()
        .toLowerCase();
    },
    /** æ ¼å¼åŒ–文件大小 */
src/views/business/GetWitness/index.vue
@@ -26,15 +26,19 @@
            @keyup.enter.native="handleQuery"
          />
        </el-form-item>
        <el-form-item label="获取状态" prop="recordstate">
        <el-form-item label="获取状态" prop="witnessState">
          <el-select
            v-model="queryParams.recordstate"
            v-model="queryParams.witnessState"
            placeholder="请选择获取状态"
            clearable
            style="width: 200px"
          >
            <el-option label="已获取" value="1" />
            <el-option label="待获取" value="0" />
          <el-option
            v-for="dict in dict.type.Obtain_status"
            :key="dict.value"
            :label="dict.label"
            :value="dict.value"
          />
          </el-select>
        </el-form-item>
        <el-form-item>
@@ -108,15 +112,14 @@
        <el-table-column
          label="获取状态"
          align="center"
          prop="recordstate"
          prop="witnessState"
          width="100"
        >
          <template slot-scope="scope">
            <el-tag
              :type="scope.row.recordstate === '1' ? 'success' : 'warning'"
            >
              {{ scope.row.recordstate === "1" ? "已获取" : "待获取" }}
            </el-tag>
              <dict-tag
              :options="dict.type.Obtain_status"
              :value="scope.row.witnessState"
            />
          </template>
        </el-table-column>
        <el-table-column
@@ -191,7 +194,7 @@
export default {
  name: "OrganProcurementList",
  components: { Pagination },
  dicts: ["sys_user_sex"],
  dicts: ["sys_user_sex",'Obtain_status'],
  data() {
    return {
      // é®ç½©å±‚
@@ -212,7 +215,7 @@
        pageSize: 10,
        inpatientno: undefined,
        name: undefined,
        recordstate: undefined
        witnessState: undefined
      }
    };
  },
src/views/business/OrganUtilization/OrganUtilizationInfo.vue
@@ -1,5 +1,7 @@
<template>
  <div class="organ-utilization-detail">
    <case-basic-info :case-id="caseId" :show-attachment="true" />
    <!-- åŸºæœ¬ä¿¡æ¯ -->
    <el-card class="detail-card">
      <div slot="header" class="clearfix">
@@ -11,7 +13,8 @@
          <el-button
            type="success"
            @click="handleComplete"
            :disabled="form.utilizationStatus === 'completed'"
            :disabled="form.recordstate === 'completed'"
            :loading="confirmLoading"
          >
            å®Œæˆåˆ©ç”¨
          </el-button>
@@ -20,76 +23,9 @@
      <el-form :model="form" ref="form" :rules="rules" label-width="120px">
        <el-row :gutter="20">
          <el-col :span="8">
            <el-form-item label="住院号" prop="hospitalNo">
              <el-input v-model="form.hospitalNo" readonly />
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="住院号" prop="caseNo">
              <el-input v-model="form.caseNo" readonly />
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="捐献者姓名" prop="donorName">
              <el-input v-model="form.donorName" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="8">
            <el-form-item label="性别" prop="gender">
              <el-select v-model="form.gender" style="width: 100%">
                <el-option label="男" value="0" />
                <el-option label="女" value="1" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="年龄" prop="age">
              <el-input v-model="form.age" />
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="出生日期" prop="birthDate">
              <el-date-picker
                v-model="form.birthDate"
                type="date"
                value-format="yyyy-MM-dd"
                style="width: 100%"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="疾病诊断" prop="diagnosis">
              <el-input
                type="textarea"
                :rows="2"
                v-model="form.diagnosis"
                placeholder="请输入疾病诊断信息"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="分配时间" prop="allocationTime">
              <el-date-picker
                v-model="form.allocationTime"
                type="datetime"
                value-format="yyyy-MM-dd HH:mm:ss"
                style="width: 100%"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="6">
            <el-form-item align="left" label="遗体捐献" prop="isBodyDonation">
              <el-radio-group v-model="form.isBodyDonation">
            <el-form-item align="left" label="遗体捐献" prop="isbodydonation">
              <el-radio-group v-model="form.isbodydonation">
                <el-radio
                  v-for="dict in dict.type.sys_0_1 || []"
                  :key="dict.value"
@@ -100,11 +36,11 @@
            </el-form-item>
          </el-col>
          <el-col :span="18">
            <el-form-item align="left" label="接收单位" prop="receivingUnit">
            <el-form-item align="left" label="接收单位" prop="receivingunit">
              <el-input
                v-model="form.receivingUnit"
                v-model="form.receivingunit"
                placeholder="请输入接收单位"
                :disabled="form.isBodyDonation !== '1'"
                :disabled="form.isbodydonation !== '1'"
              />
            </el-form-item>
          </el-col>
@@ -112,61 +48,37 @@
        <el-row :gutter="20">
          <el-col :span="6">
            <el-form-item label="负责人" prop="responsibleUserId">
              <el-select
                v-model="form.responsibleUserId"
                placeholder="请选择负责人"
                style="width: 100%"
              >
                <el-option
                  v-for="item in leaderList"
                  :key="item.reportNo"
                  :label="item.reportName"
                  :value="item.reportNo"
                />
              </el-select>
            <el-form-item label="负责人" prop="responsibleusername">
              <el-input
                v-model="form.responsibleusername"
                placeholder="请输入负责人姓名"
              />
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="协调员一" prop="coordinatedUserId1">
              <el-select
                v-model="form.coordinatedUserId1"
                placeholder="请选择协调员"
                style="width: 100%"
              >
                <el-option
                  v-for="item in coordinatorList"
                  :key="item.reportNo"
                  :label="item.reportName"
                  :value="item.reportNo"
                />
              </el-select>
            <el-form-item label="协调员一" prop="coordinatedusernameo">
              <el-input
                v-model="form.coordinatedusernameo"
                placeholder="请输入协调员一姓名"
              />
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="协调员二" prop="coordinatedUserId2">
              <el-select
                v-model="form.coordinatedUserId2"
                placeholder="请选择协调员"
                style="width: 100%"
              >
                <el-option
                  v-for="item in coordinatorList"
                  :key="item.reportNo"
                  :label="item.reportName"
                  :value="item.reportNo"
                />
              </el-select>
            <el-form-item label="协调员二" prop="coordinatedusernamet">
              <el-input
                v-model="form.coordinatedusernamet"
                placeholder="请输入协调员二姓名"
              />
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="完成时间" prop="completionTime">
            <el-form-item label="完成时间" prop="completetime">
              <el-date-picker
                v-model="form.completionTime"
                v-model="form.completetime"
                type="datetime"
                value-format="yyyy-MM-dd HH:mm:ss"
                style="width: 100%"
                :disabled="form.utilizationStatus !== 'completed'"
                :disabled="form.recordstate === 'completed'"
              />
            </el-form-item>
          </el-col>
@@ -174,14 +86,14 @@
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="登记人" prop="registrant">
              <el-input v-model="form.registrant" />
            <el-form-item label="登记人" prop="createBy">
              <el-input v-model="form.createBy" readonly />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="登记时间" prop="registrationTime">
            <el-form-item label="登记时间" prop="createTime">
              <el-date-picker
                v-model="form.registrationTime"
                v-model="form.createTime"
                type="datetime"
                value-format="yyyy-MM-dd HH:mm:ss"
                style="width: 100%"
@@ -193,13 +105,13 @@
      </el-form>
    </el-card>
    <!-- å™¨å®˜åˆ©ç”¨è®°å½•部分 -->
    <!-- å™¨å®˜åˆ©ç”¨è®°å½•部分 - æ•´åˆå—者详情 -->
    <el-card class="utilization-card">
      <div slot="header" class="clearfix">
        <span class="detail-title">器官利用记录</span>
        <div style="float: right;">
          <el-tag :type="getStatusTagType(form.utilizationStatus)">
            {{ getStatusText(form.utilizationStatus) }}
          <el-tag :type="getStatusTagType(form.recordstate)">
            {{ getStatusText(form.recordstate) }}
          </el-tag>
        </div>
      </div>
@@ -213,12 +125,15 @@
        <el-row>
          <el-col>
            <el-form-item label-width="100px" label="移植器官">
              <el-checkbox-group v-model="selectedOrgans" @change="handleOrganSelectionChange">
              <el-checkbox-group
                v-model="selectedOrgans"
                @change="handleOrganSelectionChange"
              >
                <el-checkbox
                  v-for="dict in dict.type.sys_Organ || []"
                  :key="dict.value"
                  :label="dict.value"
                  :disabled="form.utilizationStatus === 'completed'"
                  :disabled="form.recordstate === 'completed'"
                >
                  {{ dict.label }}
                </el-checkbox>
@@ -231,38 +146,236 @@
          <el-col>
            <el-form-item>
              <el-table
                :data="utilizationData.records"
                :data="utilizationData.serviceDonatecomporganList"
                v-loading="loading"
                border
                style="width: 100%"
                :row-class-name="getOrganRowClassName"
                :expand-row-keys="expandedRows"
                @expand-change="handleExpandChange"
                row-key="organno"
              >
                <el-table-column type="expand" width="60">
                  <template slot-scope="scope">
                    <!-- å±•开行内容 - å—者详细信息 -->
                    <div class="recipient-detail-expand">
                      <div class="recipient-header">
                        <span class="recipient-title">受者详细信息</span>
                        <el-tag
                          v-if="scope.row.transplantstate === '1'"
                          type="success"
                          size="small"
                        >
                          å·²ç§»æ¤
                        </el-tag>
                        <el-tag
                          v-else-if="scope.row.transplantstate === '0'"
                          type="warning"
                          size="small"
                        >
                          æœªç§»æ¤
                        </el-tag>
                        <el-tag v-else type="info" size="small">
                          ç§»æ¤ä¸­
                        </el-tag>
                      </div>
                      <el-form
                        :model="scope.row"
                        label-width="140px"
                        class="recipient-form"
                      >
                        <!-- åŸºæœ¬ä¿¡æ¯éƒ¨åˆ† -->
                        <div class="form-section">
                          <h4 class="section-title">基本信息</h4>
                          <el-row :gutter="20">
                            <el-col :span="8">
                              <el-form-item label="受者姓名">
                                <el-input
                                  v-model="scope.row.name"
                                  placeholder="请输入受者姓名"
                                  :disabled="form.recordstate === 'completed'"
                                />
                              </el-form-item>
                            </el-col>
                            <el-col :span="8">
                              <el-form-item label="出生日期">
                                <el-date-picker
                                  v-model="scope.row.birthday"
                                  type="date"
                                  value-format="yyyy-MM-dd"
                                  placeholder="选择出生日期"
                                  style="width: 100%"
                                  :disabled="form.recordstate === 'completed'"
                                />
                              </el-form-item>
                            </el-col>
                            <el-col :span="8">
                              <el-form-item label="性别">
                                <el-select
                                  v-model="scope.row.sex"
                                  placeholder="请选择性别"
                                  style="width: 100%"
                                  :disabled="form.recordstate === 'completed'"
                                >
                                  <el-option label="男" value="0" />
                                  <el-option label="女" value="1" />
                                </el-select>
                              </el-form-item>
                            </el-col>
                          </el-row>
                          <el-row :gutter="20">
                            <el-col :span="8">
                              <el-form-item label="年龄">
                                <el-input
                                  v-model="scope.row.age"
                                  placeholder="年龄"
                                  :disabled="form.recordstate === 'completed'"
                                />
                              </el-form-item>
                            </el-col>
                            <el-col :span="8">
                              <el-form-item label="证件类型">
                                <el-select
                                  v-model="scope.row.idcardtype"
                                  placeholder="请选择证件类型"
                                  style="width: 100%"
                                  :disabled="form.recordstate === 'completed'"
                                >
                                  <el-option label="身份证" value="1" />
                                  <el-option label="护照" value="2" />
                                  <el-option label="军官证" value="3" />
                                  <el-option label="其他" value="4" />
                                </el-select>
                              </el-form-item>
                            </el-col>
                            <el-col :span="8">
                              <el-form-item label="证件号码">
                                <el-input
                                  v-model="scope.row.idcardno"
                                  placeholder="证件号码"
                                  :disabled="form.recordstate === 'completed'"
                                />
                              </el-form-item>
                            </el-col>
                          </el-row>
                        </div>
                        <!-- è”系信息部分 -->
                        <div class="form-section">
                          <h4 class="section-title">联系信息</h4>
                          <el-row :gutter="20">
                            <el-col :span="12">
                              <el-form-item label="移植中心名称">
                                <el-input
                                  v-model="scope.row.hospitalname"
                                  placeholder="请输入移植中心名称"
                                  :disabled="form.recordstate === 'completed'"
                                />
                              </el-form-item>
                            </el-col>
                            <el-col :span="12">
                              <el-form-item label="联系电话">
                                <el-input
                                  v-model="scope.row.phone"
                                  placeholder="联系电话"
                                  :disabled="form.recordstate === 'completed'"
                                />
                              </el-form-item>
                            </el-col>
                          </el-row>
                          <el-row :gutter="20">
                            <el-col :span="24">
                              <el-form-item label="现住地址">
                                <el-input
                                  type="textarea"
                                  :rows="2"
                                  v-model="scope.row.residenceaddress"
                                  placeholder="请输入详细地址"
                                  :disabled="form.recordstate === 'completed'"
                                />
                              </el-form-item>
                            </el-col>
                          </el-row>
                        </div>
                        <!-- ç§»æ¤ä¿¡æ¯éƒ¨åˆ† -->
                        <div
                          class="form-section"
                          v-if="scope.row.transplantstate === '1'"
                        >
                          <h4 class="section-title">移植信息</h4>
                          <el-row :gutter="20">
                            <el-col :span="12">
                              <el-form-item label="移植时间">
                                <el-date-picker
                                  v-model="scope.row.transplanttime"
                                  type="datetime"
                                  value-format="YYYY-MM-DD HH:mm:ss"
                                  placeholder="选择移植日期"
                                  style="width: 100%"
                                  :disabled="form.recordstate === 'completed'"
                                />
                              </el-form-item>
                            </el-col>
                            <el-col :span="12">
                              <el-form-item label="移植医生">
                                <el-input
                                  v-model="scope.row.transplantdoct"
                                  placeholder="请输入移植医生"
                                  :disabled="form.recordstate === 'completed'"
                                />
                              </el-form-item>
                            </el-col>
                          </el-row>
                        </div>
                        <!-- æœªç§»æ¤åŽŸå›  -->
                        <div
                          class="form-section"
                          v-if="scope.row.transplantstate === '0'"
                        >
                          <h4 class="section-title">未移植信息</h4>
                          <el-row :gutter="20">
                            <el-col :span="24">
                              <el-form-item label="未移植原因">
                                <el-input
                                  type="textarea"
                                  :rows="3"
                                  v-model="scope.row.abandonreason"
                                  placeholder="请输入未移植原因"
                                  :disabled="form.recordstate === 'completed'"
                                />
                              </el-form-item>
                            </el-col>
                          </el-row>
                        </div>
                      </el-form>
                    </div>
                  </template>
                </el-table-column>
                <el-table-column
                  label="器官名称"
                  align="center"
                  width="120"
                  prop="organName"
                  prop="organname"
                >
                  <template slot-scope="scope">
                    <el-input
                      v-model="scope.row.organName"
                      v-model="scope.row.organname"
                      placeholder="器官名称"
                      :disabled="true"
                    />
                  </template>
                </el-table-column>
                <el-table-column
                  label="系统编号"
                  align="center"
                  width="120"
                  prop="caseNo"
                >
                <el-table-column label="系统编号" align="center" prop="caseNo">
                  <template slot-scope="scope">
                    <el-input
                      v-model="scope.row.caseNo"
                      placeholder="系统编号"
                      :disabled="form.utilizationStatus === 'completed'"
                    />
                  </template>
                </el-table-column>
@@ -270,15 +383,14 @@
                <el-table-column
                  label="移植医院"
                  align="center"
                  width="200"
                  prop="hospitalNo"
                  width="260"
                  prop="hospitalno"
                >
                  <template slot-scope="scope">
                    <el-select
                      v-model="scope.row.hospitalNo"
                      v-model="scope.row.hospitalno"
                      placeholder="请选择移植医院"
                      style="width: 100%"
                      :disabled="form.utilizationStatus === 'completed'"
                      @change="handleHospitalChange(scope.row, $event)"
                    >
                      <el-option
@@ -292,67 +404,16 @@
                </el-table-column>
                <el-table-column
                  label="受体姓氏"
                  align="center"
                  width="120"
                  prop="recipientName"
                >
                  <template slot-scope="scope">
                    <el-input
                      v-model="scope.row.recipientName"
                      placeholder="受体姓氏"
                      :disabled="form.utilizationStatus === 'completed'"
                    />
                  </template>
                </el-table-column>
                <el-table-column
                  label="移植负责人"
                  align="center"
                  width="120"
                  prop="transplantDoctor"
                >
                  <template slot-scope="scope">
                    <el-input
                      v-model="scope.row.transplantDoctor"
                      placeholder="医师姓名"
                      :disabled="form.utilizationStatus === 'completed'"
                    />
                  </template>
                </el-table-column>
                <el-table-column
                  label="移植时间"
                  align="center"
                  width="150"
                  prop="transplantTime"
                >
                  <template slot-scope="scope">
                    <el-date-picker
                      clearable
                      size="small"
                      style="width: 100%"
                      v-model="scope.row.transplantTime"
                      type="date"
                      value-format="yyyy-MM-dd"
                      placeholder="选择移植时间"
                      :disabled="form.utilizationStatus === 'completed'"
                    />
                  </template>
                </el-table-column>
                <el-table-column
                  label="移植状态"
                  align="center"
                  width="120"
                  prop="transplantStatus"
                  prop="transplantstate"
                >
                  <template slot-scope="scope">
                    <el-select
                      v-model="scope.row.transplantStatus"
                      v-model="scope.row.transplantstate"
                      placeholder="请选择移植状态"
                      style="width: 100%"
                      :disabled="form.utilizationStatus === 'completed'"
                      @change="handleTransplantStatusChange(scope.row, $event)"
                    >
                      <el-option
                        v-for="dict in transplantStatusList"
@@ -365,18 +426,43 @@
                </el-table-column>
                <el-table-column
                  label="说明"
                  label="移植时间"
                  align="center"
                  prop="abandonReason"
                  min-width="200"
                  width="220"
                  prop="transplanttime"
                >
                  <template slot-scope="scope">
                    <el-date-picker
                      clearable
                      size="small"
                      style="width: 100%"
                      v-model="scope.row.transplanttime"
                      type="datetime"
                      value-format="YYYY-MM-DD HH:mm:ss"
                      placeholder="选择移植时间"
                    />
                  </template>
                </el-table-column>
                <el-table-column
                  label="移植医生"
                  align="center"
                  prop="transplantdoct"
                >
                  <template slot-scope="scope">
                    <el-input
                      type="textarea"
                      clearable
                      v-model="scope.row.abandonReason"
                      placeholder="请输入弃用说明"
                      :disabled="form.utilizationStatus === 'completed'"
                      v-model="scope.row.transplantdoct"
                      placeholder="医师姓名"
                    />
                  </template>
                </el-table-column>
                <el-table-column label="受者姓名" align="center" prop="name">
                  <template slot-scope="scope">
                    <el-input
                      v-model="scope.row.name"
                      placeholder="受者姓名"
                      :disabled="form.recordstate === 'completed'"
                    />
                  </template>
                </el-table-column>
@@ -384,9 +470,8 @@
                <el-table-column
                  label="操作"
                  align="center"
                  width="120"
                  class-name="small-padding fixed-width"
                  v-if="form.utilizationStatus !== 'completed'"
                  v-if="form.recordstate !== 'completed'"
                >
                  <template slot-scope="scope">
                    <el-button
@@ -397,6 +482,16 @@
                    >
                      ç¼–辑
                    </el-button>
                    <el-button
                      size="mini"
                      type="text"
                      icon="el-icon-delete"
                      style="color: #F56C6C;"
                      @click="handleRemoveOrgan(scope.$index)"
                      v-if="!scope.row.id"
                    >
                      åˆ é™¤
                    </el-button>
                  </template>
                </el-table-column>
              </el-table>
@@ -404,279 +499,100 @@
          </el-col>
        </el-row>
        <!-- åˆ©ç”¨ç»Ÿè®¡ä¿¡æ¯ -->
        <div class="utilization-stats" v-if="utilizationData.records.length > 0">
          <el-row :gutter="20">
            <el-col :span="6">
              <div class="stat-item">
                <span class="stat-label">已利用器官:</span>
                <span class="stat-value">{{ utilizationData.records.length }} ä¸ª</span>
              </div>
            </el-col>
            <el-col :span="6">
              <div class="stat-item">
                <span class="stat-label">待完善信息:</span>
                <span class="stat-value">{{ incompleteRecords }} ä¸ª</span>
              </div>
            </el-col>
            <el-col :span="6">
              <div class="stat-item">
                <span class="stat-label">涉及医院:</span>
                <span class="stat-value">{{ uniqueHospitals }} å®¶</span>
              </div>
            </el-col>
            <el-col :span="6">
              <div class="stat-item">
                <span class="stat-label">利用状态:</span>
                <span class="stat-value">
                  <el-tag :type="getStatusTagType(form.utilizationStatus)">
                    {{ getStatusText(form.utilizationStatus) }}
                  </el-tag>
                </span>
              </div>
            </el-col>
          </el-row>
        </div>
        <!-- ç»Ÿè®¡ä¿¡æ¯ -->
        <div v-else class="empty-utilization">
        <div
          v-if="
            !utilizationData.serviceDonatecomporganList ||
              utilizationData.serviceDonatecomporganList.length == 0
          "
          class="empty-utilization"
        >
          <el-empty description="暂无利用记录" :image-size="80">
            <span>请先选择要利用的器官</span>
          </el-empty>
        </div>
      </el-form>
      <div class="dialog-footer" v-if="form.utilizationStatus !== 'completed'">
        <el-button
          type="primary"
          @click="handleSaveUtilization"
          :loading="saveLoading"
          :disabled="utilizationData.records.length === 0"
        >
          ä¿å­˜åˆ©ç”¨è®°å½•
        </el-button>
        <el-button
          type="success"
          @click="handleConfirmUtilization"
          :loading="confirmLoading"
          :disabled="incompleteRecords > 0"
        >
          ç¡®è®¤å®Œæˆåˆ©ç”¨
        </el-button>
      </div>
    </el-card>
    <!-- å—者详细信息部分 -->
    <el-card class="recipient-card" v-if="utilizationData.records.length > 0">
      <div slot="header" class="clearfix">
        <span class="detail-title">受者详细信息</span>
      </div>
      <el-tabs v-model="activeRecipientTab" type="card">
        <el-tab-pane
          v-for="record in utilizationData.records"
          :key="record.organNo"
          :label="record.organName"
          :name="record.organNo"
        >
          <el-form :model="record" label-width="140px">
            <el-row :gutter="20">
              <el-col :span="8">
                <el-form-item label="受者姓名">
                  <el-input v-model="record.recipientName" placeholder="请输入受者姓名" />
                </el-form-item>
              </el-col>
              <el-col :span="8">
                <el-form-item label="出生年月">
                  <el-date-picker
                    v-model="record.recipientBirthDate"
                    type="month"
                    value-format="yyyy-MM"
                    placeholder="选择出生年月"
                    style="width: 100%"
                  />
                </el-form-item>
              </el-col>
              <el-col :span="8">
                <el-form-item label="性别">
                  <el-select v-model="record.recipientGender" placeholder="请选择性别" style="width: 100%">
                    <el-option label="男" value="0" />
                    <el-option label="女" value="1" />
                  </el-select>
                </el-form-item>
              </el-col>
            </el-row>
            <el-row :gutter="20">
              <el-col :span="12">
                <el-form-item label="移植中心名称">
                  <el-input v-model="record.transplantCenter" placeholder="请输入移植中心名称" />
                </el-form-item>
              </el-col>
              <el-col :span="12">
                <el-form-item label="所在地">
                  <el-input v-model="record.location" placeholder="请输入所在地" />
                </el-form-item>
              </el-col>
            </el-row>
            <el-row :gutter="20">
              <el-col :span="12">
                <el-form-item label="移植日期">
                  <el-date-picker
                    v-model="record.transplantTime"
                    type="date"
                    value-format="yyyy-MM-dd"
                    placeholder="选择移植日期"
                    style="width: 100%"
                  />
                </el-form-item>
              </el-col>
              <el-col :span="12">
                <el-form-item label="原发病">
                  <el-input v-model="record.originalDisease" placeholder="请输入原发病" />
                </el-form-item>
              </el-col>
            </el-row>
            <el-row :gutter="20">
              <el-col :span="24">
                <el-form-item label="检测指标">
                  <el-input
                    type="textarea"
                    :rows="3"
                    v-model="record.testIndicators"
                    placeholder="请输入各类必要的检测指标"
                  />
                </el-form-item>
              </el-col>
            </el-row>
          </el-form>
        </el-tab-pane>
      </el-tabs>
    </el-card>
    <!-- éšè®¿è®°å½•部分 -->
    <el-card class="followup-card">
      <div slot="header" class="clearfix">
        <span class="detail-title">随访记录</span>
        <el-button
          type="primary"
          size="mini"
          icon="el-icon-plus"
          @click="handleAddFollowup"
          style="float: right;"
        >
          æ–°å¢žéšè®¿
        </el-button>
      </div>
      <el-table :data="followupData.records" v-loading="loading" border>
        <el-table-column label="器官名称" align="center" width="120" prop="organName" />
        <el-table-column label="随访时间" align="center" width="160" prop="followupTime">
          <template slot-scope="scope">
            <span>{{ parseTime(scope.row.followupTime) }}</span>
          </template>
        </el-table-column>
        <el-table-column label="随访类型" align="center" width="100" prop="followupType">
          <template slot-scope="scope">
            <el-tag :type="getFollowupTypeTag(scope.row.followupType)">
              {{ getFollowupTypeText(scope.row.followupType) }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="受者情况" align="center" prop="recipientCondition" min-width="200" show-overflow-tooltip />
        <el-table-column label="随访医生" align="center" width="120" prop="followupDoctor" />
        <el-table-column label="下次随访时间" align="center" width="160" prop="nextFollowupTime">
          <template slot-scope="scope">
            <span>{{ scope.row.nextFollowupTime || '-' }}</span>
          </template>
        </el-table-column>
        <el-table-column label="操作" align="center" width="150">
          <template slot-scope="scope">
            <el-button
              size="mini"
              type="text"
              icon="el-icon-view"
              @click="handleViewFollowup(scope.row)"
            >查看</el-button>
            <el-button
              size="mini"
              type="text"
              icon="el-icon-edit"
              @click="handleEditFollowup(scope.row)"
            >编辑</el-button>
            <el-button
              size="mini"
              type="text"
              icon="el-icon-delete"
              style="color: #F56C6C;"
              @click="handleDeleteFollowup(scope.row)"
            >删除</el-button>
          </template>
        </el-table-column>
      </el-table>
    </el-card>
    <!-- é™„件管理部分 -->
    <!-- é™„件管理部分 - ä¼˜åŒ–为完整功能 -->
    <el-card class="attachment-card">
      <div slot="header" class="clearfix">
        <span class="detail-title">相关附件</span>
        <el-button
          type="primary"
          size="mini"
          icon="el-icon-upload"
          @click="handleUploadAttachment"
      <div class="attachment-header">
        <i class="el-icon-paperclip"></i>
        <span class="attachment-title">相关附件</span>
        <span class="attachment-tip"
          >支持上传器官利用相关文件 (最多{{ attachmentLimit }}个)</span
        >
          ä¸Šä¼ é™„ä»¶
        </el-button>
      </div>
      <div class="attachment-list">
        <el-table :data="attachments" style="width: 100%">
          <el-table-column label="文件名称" min-width="200">
      <!-- ä½¿ç”¨ UploadAttachment ç»„ä»¶ -->
      <UploadAttachment
        ref="uploadAttachment"
        :file-list="attachmentFileList"
        :limit="attachmentLimit"
        :accept="attachmentAccept"
        :multiple="true"
        @change="handleAttachmentChange"
        @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">
              <div class="file-info">
                <i :class="getFileIcon(scope.row.fileName)" style="margin-right: 8px; color: #409EFF;"></i>
                <span>{{ scope.row.fileName }}</span>
              </div>
              <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" align="center">
          <el-table-column label="文件类型" width="100">
            <template slot-scope="scope">
              <el-tag size="small">{{ getFileType(scope.row.fileName) }}</el-tag>
              <el-tag :type="getFileTagType(scope.row.fileName)" size="small">
                {{ getFileTypeText(scope.row.fileName) }}
              </el-tag>
            </template>
          </el-table-column>
          <el-table-column label="文件大小" width="100" align="center">
          <el-table-column label="上传时间" width="200">
            <template slot-scope="scope">
              <span>{{ formatDateTime(scope.row.uploadTime) }}</span>
            </template>
          </el-table-column>
          <el-table-column label="文件大小" width="180">
            <template slot-scope="scope">
              <span>{{ formatFileSize(scope.row.fileSize) }}</span>
            </template>
          </el-table-column>
          <el-table-column label="上传时间" width="160" align="center">
            <template slot-scope="scope">
              <span>{{ parseTime(scope.row.uploadTime) }}</span>
            </template>
          </el-table-column>
          <el-table-column label="操作" width="150" align="center">
          <el-table-column label="操作" width="260" fixed="right">
            <template slot-scope="scope">
              <el-button
                size="mini"
                type="text"
                icon="el-icon-view"
                @click="handlePreviewAttachment(scope.row)"
              >预览</el-button>
                type="primary"
                @click="handlePreview(scope.row)"
                :disabled="!isPreviewable(scope.row.fileName)"
              >
                é¢„览
              </el-button>
              <el-button
                size="mini"
                type="text"
                icon="el-icon-download"
                type="success"
                @click="handleDownloadAttachment(scope.row)"
              >下载</el-button>
              >
                ä¸‹è½½
              </el-button>
              <el-button
                size="mini"
                type="text"
                icon="el-icon-delete"
                style="color: #F56C6C;"
                @click="handleRemoveAttachment(scope.row)"
              >删除</el-button>
                type="danger"
                @click="handleRemoveAttachment(scope.$index)"
              >
                åˆ é™¤
              </el-button>
            </template>
          </el-table-column>
        </el-table>
@@ -693,12 +609,15 @@
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="器官名称">
              <el-input v-model="currentRecord.organName" readonly />
              <el-input v-model="currentRecord.organname" readonly />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="移植状态">
              <el-select v-model="currentRecord.transplantStatus" style="width: 100%">
              <el-select
                v-model="currentRecord.transplantstate"
                style="width: 100%"
              >
                <el-option
                  v-for="dict in transplantStatusList"
                  :key="dict.value"
@@ -709,13 +628,39 @@
            </el-form-item>
          </el-col>
        </el-row>
        <el-form-item label="弃用说明" v-if="currentRecord.transplantStatus === '0'">
        <el-form-item
          label="未移植原因"
          v-if="currentRecord.transplantstate === '0'"
        >
          <el-input
            type="textarea"
            :rows="3"
            v-model="currentRecord.abandonReason"
            placeholder="请输入弃用的原因说明"
            v-model="currentRecord.abandonreason"
            placeholder="请输入未移植原因"
          />
        </el-form-item>
        <el-form-item
          label="移植医院"
          v-if="currentRecord.transplantstate === '1'"
        >
          <el-select
            v-model="currentRecord.hospitalno"
            placeholder="请选择移植医院"
            style="width: 100%"
          >
            <el-option
              v-for="hospital in hospitalList"
              :key="hospital.hospitalNo"
              :label="hospital.hospitalName"
              :value="hospital.hospitalNo"
            />
          </el-select>
        </el-form-item>
        <el-form-item
          label="受者姓名"
          v-if="currentRecord.transplantstate === '1'"
        >
          <el-input v-model="currentRecord.name" placeholder="请输入受者姓名" />
        </el-form-item>
      </el-form>
      <div slot="footer">
@@ -724,139 +669,82 @@
      </div>
    </el-dialog>
    <!-- éšè®¿è®°å½•对话框 -->
    <el-dialog
      :title="followupDialogTitle"
      :visible.sync="followupDialogVisible"
      width="700px"
    >
      <el-form :model="currentFollowup" label-width="120px">
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="器官名称">
              <el-select v-model="currentFollowup.organNo" style="width: 100%">
                <el-option
                  v-for="organ in utilizationData.records"
                  :key="organ.organNo"
                  :label="organ.organName"
                  :value="organ.organNo"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="随访类型">
              <el-select v-model="currentFollowup.followupType" style="width: 100%">
                <el-option label="常规随访" value="routine" />
                <el-option label="紧急随访" value="emergency" />
                <el-option label="特殊随访" value="special" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="随访时间">
              <el-date-picker
                v-model="currentFollowup.followupTime"
                type="datetime"
                value-format="yyyy-MM-dd HH:mm:ss"
                style="width: 100%"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="随访医生">
              <el-input v-model="currentFollowup.followupDoctor" placeholder="请输入随访医生" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-form-item label="受者情况">
          <el-input
            type="textarea"
            :rows="3"
            v-model="currentFollowup.recipientCondition"
            placeholder="请输入受者当前情况"
          />
        </el-form-item>
        <el-form-item label="用药情况">
          <el-input
            type="textarea"
            :rows="2"
            v-model="currentFollowup.medicationSituation"
            placeholder="请输入用药情况"
          />
        </el-form-item>
        <el-form-item label="检查结果">
          <el-input
            type="textarea"
            :rows="2"
            v-model="currentFollowup.testResults"
            placeholder="请输入检查结果"
          />
        </el-form-item>
        <el-form-item label="下次随访时间">
          <el-date-picker
            v-model="currentFollowup.nextFollowupTime"
            type="date"
            value-format="yyyy-MM-dd"
            style="width: 100%"
          />
        </el-form-item>
      </el-form>
      <div slot="footer">
        <el-button @click="followupDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="handleSaveFollowup">保存</el-button>
      </div>
    </el-dialog>
    <!-- æ–‡ä»¶é¢„览对话框 -->
    <FilePreviewDialog
      :visible="filePreviewVisible"
      :file="currentPreviewFile"
      @close="filePreviewVisible = false"
      @download="handleDownloadAttachment"
    />
  </div>
</template>
<script>
import {
  getOrganUtilizationDetail,
  updateOrganUtilization,
  addOrganUtilization,
  saveUtilizationRecords,
  saveFollowupRecord,
  getHospitalList,
  getLeaderList,
  getCoordinatorList
} from "./organUtilization";
  completionList,
  completionadd,
  completionedit
} from "@/api/businessApi";
import UploadAttachment from "@/components/UploadAttachment"; // æ–°å¢žå¯¼å…¥
import FilePreviewDialog from "@/components/FilePreviewDialog"; // æ–°å¢žå¯¼å…¥
import CaseBasicInfo from "@/components/CaseBasicInfo";
import dayjs from "dayjs"; // æ–°å¢žå¯¼å…¥ï¼Œç”¨äºŽæ—¶é—´å¤„理
export default {
  name: "OrganUtilizationDetail",
  dicts: ["sys_user_sex", "sys_Organ", "sys_0_1"],
  components: {
    UploadAttachment,
    FilePreviewDialog,
    CaseBasicInfo
  },
  dicts: ["sys_BloodType", "sys_Organ", "sys_0_1"],
  data() {
    return {
      // è¡¨å•数据
      caseId: null,
      // è¡¨å•数据 - æ ¹æ®æŽ¥å£å‚数调整
      form: {
        id: undefined,
        hospitalNo: "",
        infoid: undefined,
        inpatientno: "",
        recordstate: "pending",
        caseNo: "",
        donorName: "",
        gender: "",
        donorno: "",
        treatmenthospitalname: "",
        treatmenthospitalno: "",
        sex: "",
        name: "",
        age: "",
        birthDate: "",
        diagnosis: "",
        utilizationStatus: "pending",
        allocationTime: "",
        registrant: "",
        registrationTime: "",
        isBodyDonation: "0",
        receivingUnit: "",
        responsibleUserId: "",
        coordinatedUserId1: "",
        coordinatedUserId2: "",
        completionTime: ""
        bloodtype: "",
        idcardno: "",
        diagnosisname: "",
        completetime: "",
        responsibleuserid: "",
        responsibleusername: "",
        coordinateduserido: "",
        coordinatedusernameo: "",
        coordinateduseridt: "",
        coordinatedusernamet: "",
        assessannex: "",
        donateorgan: "",
        isbodydonation: "0",
        receivingunit: "",
        createBy: "",
        createTime: "",
        updateBy: "",
        updateTime: "",
        attachments: []
      },
      // è¡¨å•验证规则
      rules: {
        donorName: [
        name: [
          { required: true, message: "捐献者姓名不能为空", trigger: "blur" }
        ],
        diagnosis: [
        diagnosisname: [
          { required: true, message: "疾病诊断不能为空", trigger: "blur" }
        ],
        donorno: [
          { required: true, message: "捐献者编号不能为空", trigger: "blur" }
        ]
      },
      // åˆ©ç”¨è®°å½•验证规则
@@ -870,10 +758,6 @@
      selectedOrgans: [],
      // åŒ»é™¢åˆ—表
      hospitalList: [],
      // è´Ÿè´£äººåˆ—表
      leaderList: [],
      // åè°ƒå‘˜åˆ—表
      coordinatorList: [],
      // ç§»æ¤çŠ¶æ€åˆ—è¡¨
      transplantStatusList: [
        { value: "1", label: "已移植" },
@@ -882,7 +766,7 @@
      ],
      // åˆ©ç”¨è®°å½•数据
      utilizationData: {
        records: []
        serviceDonatecomporganList: []
      },
      // éšè®¿è®°å½•数据
      followupData: {
@@ -890,15 +774,21 @@
      },
      // é™„件数据
      attachments: [],
      // å½“前激活的受者标签
      activeRecipientTab: "",
      // å±•开的行keys
      expandedRows: [],
      // ç¼–辑对话框
      editDialogVisible: false,
      currentRecord: {},
      currentEditIndex: -1,
      // éšè®¿å¯¹è¯æ¡†
      followupDialogVisible: false,
      followupDialogTitle: "新增随访记录",
      // é™„件相关配置 - æ–°å¢ž
      attachmentFileList: [],
      attachmentLimit: 10,
      attachmentAccept:
        ".pdf,.jpg,.jpeg,.png,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.txt",
      // æ–‡ä»¶é¢„览相关 - æ–°å¢ž
      filePreviewVisible: false,
      currentPreviewFile: null,
      currentFollowup: {},
      isEditingFollowup: false
    };
@@ -908,140 +798,179 @@
    currentUser() {
      return JSON.parse(sessionStorage.getItem("user") || "{}");
    },
    // ä¸å®Œæ•´çš„记录数量
    incompleteRecords() {
      return this.utilizationData.records.filter(
        record =>
          !record.caseNo ||
          !record.hospitalNo ||
          !record.recipientName ||
          !record.transplantTime
    // å·²ç§»æ¤æ•°é‡
    transplantedCount() {
      if (!this.utilizationData.serviceDonatecomporganList) return 0;
      return this.utilizationData.serviceDonatecomporganList.filter(
        record => record.transplantstate === "1"
      ).length;
    },
    // å”¯ä¸€åŒ»é™¢æ•°é‡
    uniqueHospitals() {
      const hospitals = this.utilizationData.records
        .map(record => record.hospitalNo)
      if (!this.utilizationData.serviceDonatecomporganList) return 0;
      const hospitals = this.utilizationData.serviceDonatecomporganList
        .map(record => record.hospitalno)
        .filter(Boolean);
      return new Set(hospitals).size;
    },
    // èŽ·å–å™¨å®˜å­—å…¸
    organDict() {
      return this.dict.type.sys_Organ || [];
    }
  },
  created() {
    const id = this.$route.query.id;
    if (id) {
      this.getDetail(id);
    } else {
      this.generateCaseNo();
      this.form.registrant = this.currentUser.username || "当前用户";
      this.form.registrationTime = new Date()
    this.initData();
  },
  watch: {
    // ç›‘听附件数据变化 - æ–°å¢ž
    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: {
    // åˆå§‹åŒ–数据
    initData() {
      this.caseId = this.$route.query.infoid;
      if (!this.caseId) {
        this.$message.error("缺少必要的路由参数 infoid");
        this.$router.back();
        return;
      }
      this.form.infoid = this.caseId;
      this.form.createBy =
        this.currentUser.username || this.currentUser.name || "当前用户";
      this.form.createTime = new Date()
        .toISOString()
        .replace("T", " ")
        .substring(0, 19);
    }
    this.getHospitalData();
    this.getLeaderData();
    this.getCoordinatorData();
  },
  methods: {
    // ç”Ÿæˆä½é™¢å·
    generateCaseNo() {
      this.generateDonorNo();
      this.getDetail();
      this.getHospitalData();
    },
    // ç”ŸæˆæçŒ®è€…编号
    generateDonorNo() {
      const timestamp = Date.now().toString();
      this.form.hospitalNo = "D" + timestamp.slice(-6);
      this.form.caseNo = "C" + timestamp.slice(-6);
      this.form.donorno = "D" + timestamp.slice(-8);
      this.form.caseNo = "CASE" + timestamp.slice(-6);
      this.form.inpatientno = "IP" + timestamp.slice(-6);
    },
    // èŽ·å–è¯¦æƒ…
    getDetail(id) {
    async getDetail() {
      this.loading = true;
      getOrganUtilizationDetail(id)
        .then(response => {
          if (response.code === 200) {
            this.form = response.data;
            if (response.data.utilizationRecords) {
              this.utilizationData.records = response.data.utilizationRecords;
              this.selectedOrgans = response.data.utilizationRecords.map(
                item => item.organNo
              );
              if (this.utilizationData.records.length > 0) {
                this.activeRecipientTab = this.utilizationData.records[0].organNo;
              }
            }
            if (response.data.followupRecords) {
              this.followupData.records = response.data.followupRecords;
            }
      try {
        const response = await completionList({ infoid: this.caseId });
        if (
          response.code === 200 &&
          response.data &&
          response.data.length > 0
        ) {
          const data = response.data[0];
          // å¡«å……表单数据
          Object.assign(this.form, data);
          // å¤„理捐献器官字段
          if (data.donateorgan) {
            const organArray = Array.isArray(data.donateorgan)
              ? data.donateorgan
              : (data.donateorgan || "").split(",").filter(item => item);
            this.selectedOrgans = organArray;
          }
          this.loading = false;
        })
        .catch(error => {
          console.error("获取器官利用详情失败:", error);
          this.loading = false;
          this.$message.error("获取详情失败");
        });
          // å¤„理器官利用记录
          if (data.serviceDonatecomporganList) {
            this.utilizationData.serviceDonatecomporganList = Array.isArray(
              data.serviceDonatecomporganList
            )
              ? data.serviceDonatecomporganList.map(record => ({
                  ...record,
                  transplantstate: record.transplantstate
                    ? record.transplantstate.toString()
                    : "1"
                }))
              : [];
          }
          // åˆå§‹åŒ–附件
          if (this.form.assessannex) {
            this.form.attachments = JSON.parse(this.form.assessannex);
            this.attachments = Array.isArray(this.form.attachments)
              ? [...this.form.attachments]
              : [];
          }
          this.$message.success("数据加载成功");
        } else {
          this.$message.warning("未找到对应的器官利用数据");
        }
      } catch (error) {
        console.error("获取器官利用详情失败:", error);
        this.$message.error("获取详情失败");
      } finally {
        this.loading = false;
      }
    },
    // èŽ·å–åŒ»é™¢æ•°æ®
    getHospitalData() {
      getHospitalList().then(response => {
        if (response.code === 200) {
          this.hospitalList = response.data;
        }
      });
    async getHospitalData() {
      try {
        // TODO: æ›¿æ¢ä¸ºå®žé™…的医院列表接口
        // æš‚时使用模拟数据
        this.hospitalList = [
          { hospitalNo: "H001", hospitalName: "北京协和医院" },
          { hospitalNo: "H002", hospitalName: "上海华山医院" },
          { hospitalNo: "H003", hospitalName: "上海瑞金医院" },
          { hospitalNo: "H004", hospitalName: "广州中山医院" },
          { hospitalNo: "H005", hospitalName: "武汉同济医院" },
          { hospitalNo: "H006", hospitalName: "成都华西医院" }
        ];
      } catch (error) {
        console.error("获取医院数据失败:", error);
        this.$message.error("获取医院数据失败");
      }
    },
    // èŽ·å–è´Ÿè´£äººæ•°æ®
    getLeaderData() {
      getLeaderList().then(response => {
        if (response.code === 200) {
          this.leaderList = response.data;
        }
      });
    },
    // èŽ·å–åè°ƒå‘˜æ•°æ®
    getCoordinatorData() {
      getCoordinatorList().then(response => {
        if (response.code === 200) {
          this.coordinatorList = response.data;
        }
      });
    },
    // å™¨å®˜é€‰æ‹©çŠ¶æ€å˜åŒ–
    handleOrganSelectionChange(selectedValues) {
      const currentOrganNos = this.utilizationData.records.map(
        item => item.organNo
      if (!this.utilizationData.serviceDonatecomporganList) {
        this.utilizationData.serviceDonatecomporganList = [];
      }
      const currentOrganValues = this.utilizationData.serviceDonatecomporganList.map(
        item => item.organno
      );
      // å¤„理互斥逻辑
      this.handleExclusiveSelections(selectedValues);
      // æ›´æ–°æçŒ®å™¨å®˜å­—段
      this.form.donateorgan = selectedValues.join(",");
      // æ–°å¢žé€‰æ‹©çš„器官
      selectedValues.forEach(organValue => {
        if (!currentOrganNos.includes(organValue)) {
          const organInfo = this.dict.type.sys_Organ.find(
            item => item.value === organValue
          );
          if (organInfo) {
            this.utilizationData.records.push({
              organName: organInfo.label,
              organNo: organValue,
              id: null,
              utilizationId: this.form.id,
              caseNo: "",
              hospitalNo: "",
              hospitalName: "",
              recipientName: "",
              transplantDoctor: "",
              transplantTime: "",
              transplantStatus: "1",
              abandonReason: "",
              recipientBirthDate: "",
              recipientGender: "",
              transplantCenter: "",
              location: "",
              originalDisease: "",
              testIndicators: ""
            });
          }
        if (!currentOrganValues.includes(organValue)) {
          this.createOrganRecord(organValue);
        }
      });
      // ç§»é™¤å–消选择的器官
      this.utilizationData.records = this.utilizationData.records.filter(
      this.utilizationData.serviceDonatecomporganList = this.utilizationData.serviceDonatecomporganList.filter(
        record => {
          if (selectedValues.includes(record.organNo)) {
          if (selectedValues.includes(record.organno)) {
            return true;
          } else {
            if (record.id) {
@@ -1055,13 +984,13 @@
                }
              )
                .then(() => {
                  this.utilizationData.records = this.utilizationData.records.filter(
                    r => r.organNo !== record.organNo
                  this.utilizationData.serviceDonatecomporganList = this.utilizationData.serviceDonatecomporganList.filter(
                    r => r.organno !== record.organno
                  );
                  this.$message.success("删除成功");
                })
                .catch(() => {
                  this.selectedOrgans.push(record.organNo);
                  this.selectedOrgans.push(record.organno);
                });
              return true;
            } else {
@@ -1071,19 +1000,115 @@
        }
      );
    },
    // å¤„理互斥选择
    handleExclusiveSelections(selectedValues) {
      // å¦‚果选择了"双肾"(假设字典值为C64),自动取消单独的"左肾"(C64L)和"右肾"(C64R)选择
      if (selectedValues.includes("C64")) {
        this.selectedOrgans = selectedValues.filter(
          item => item !== "C64L" && item !== "C64R"
        );
      }
      // å¦‚果选择了"左肾"或"右肾",取消"双肾"选择
      else if (
        selectedValues.includes("C64L") ||
        selectedValues.includes("C64R")
      ) {
        this.selectedOrgans = selectedValues.filter(item => item !== "C64");
      }
      // å¦‚果选择了"全肺"(假设字典值为C34),自动取消单独的"左肺"(C34L)和"右肺"(C34R)选择
      if (selectedValues.includes("C34")) {
        this.selectedOrgans = selectedValues.filter(
          item => item !== "C34L" && item !== "C34R"
        );
      }
      // å¦‚果选择了"左肺"或"右肺",取消"全肺"选择
      else if (
        selectedValues.includes("C34L") ||
        selectedValues.includes("C34R")
      ) {
        this.selectedOrgans = selectedValues.filter(item => item !== "C34");
      }
    },
    // åˆ›å»ºå™¨å®˜è®°å½•
    createOrganRecord(organValue) {
      const organName = this.getOrganLabel(organValue);
      this.utilizationData.serviceDonatecomporganList.push({
        organname: organName,
        organno: organValue,
        caseNo: "",
        hospitalno: "",
        hospitalname: "",
        name: "",
        transplantdoct: "",
        transplanttime: "",
        transplantstate: "1",
        abandonreason: "",
        sex: "",
        age: "",
        birthday: "",
        phone: "",
        residenceaddress: "",
        residenceprovince: "",
        residenceprovincename: "",
        residencecity: "",
        residencecityname: "",
        residencetown: "",
        residencetownname: "",
        residencecommunity: "",
        residencecommunityname: "",
        residencecountycode: "",
        residencecountyname: "",
        idcardtype: "",
        idcardno: "",
        ageunit: ""
      });
    },
    // æ ¹æ®å­—å…¸value获取label
    getOrganLabel(organValue) {
      const dictItem = this.organDict.find(item => item.value === organValue);
      return dictItem ? dictItem.label : organValue;
    },
    // åŒ»é™¢é€‰æ‹©å˜åŒ–
    handleHospitalChange(row, hospitalNo) {
      const hospital = this.hospitalList.find(
        item => item.hospitalNo === hospitalNo
      );
      if (hospital) {
        row.hospitalName = hospital.hospitalName;
        row.hospitalname = hospital.hospitalName;
      }
    },
    // ç§»æ¤çŠ¶æ€å˜åŒ–å¤„ç†
    handleTransplantStatusChange(row, status) {
      if (status === "0") {
        // å¦‚果状态为未移植,清除相关字段
        // row.transplanttime = "";
        // row.transplantdoct = "";
        // row.hospitalno = "";
        // row.hospitalname = "";
      } else if (status === "1") {
        // å¦‚果状态为已移植,自动设置移植时间为当前时间
        if (!row.transplanttime) {
          row.transplanttime = new Date().toISOString().split("T")[0];
        }
      }
    },
    // è¡Œå±•开事件
    handleExpandChange(row, expandedRows) {
      this.expandedRows = expandedRows.map(item => item.organno);
    },
    // ç¼–辑利用记录
    handleEditUtilization(row) {
      const index = this.utilizationData.records.findIndex(
        item => item.organNo === row.organNo
      const index = this.utilizationData.serviceDonatecomporganList.findIndex(
        item => item.organno === row.organno
      );
      if (index !== -1) {
        this.currentRecord = { ...row };
@@ -1091,46 +1116,77 @@
        this.editDialogVisible = true;
      }
    },
    // ç¡®è®¤ç¼–辑
    handleEditConfirm() {
      if (this.currentEditIndex !== -1) {
        this.utilizationData.records[this.currentEditIndex] = {
        this.utilizationData.serviceDonatecomporganList[
          this.currentEditIndex
        ] = {
          ...this.currentRecord
        };
        this.$message.success("利用记录更新成功");
        this.editDialogVisible = false;
      }
    },
    // åˆ é™¤å™¨å®˜è®°å½•
    handleRemoveOrgan(index) {
      this.$confirm("确认删除这条器官记录吗?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      })
        .then(() => {
          const organno = this.utilizationData.serviceDonatecomporganList[index]
            .organno;
          this.utilizationData.serviceDonatecomporganList.splice(index, 1);
          // ä»Žé€‰ä¸­çš„器官中移除
          const idx = this.selectedOrgans.indexOf(organno);
          if (idx > -1) {
            this.selectedOrgans.splice(idx, 1);
          }
          this.$message.success("器官记录删除成功");
        })
        .catch(() => {});
    },
    // å™¨å®˜è¡Œæ ·å¼
    getOrganRowClassName({ row }) {
      if (
        !row.caseNo ||
        !row.hospitalNo ||
        !row.recipientName ||
        !row.transplantTime
        row.transplantstate === "1" &&
        (!row.caseNo || !row.hospitalno || !row.name || !row.transplanttime)
      ) {
        return "warning-row";
      }
      if (row.transplantstate === "0" && !row.abandonreason) {
        return "warning-row";
      }
      return "";
    },
    // èŽ·å–çŠ¶æ€æ ‡ç­¾ç±»åž‹
    getStatusTagType(status) {
      const typeMap = {
        completed: "success",
        in_progress: "warning",
        processing: "warning",
        pending: "info"
      };
      return typeMap[status] || "info";
    },
    // èŽ·å–çŠ¶æ€æ–‡æœ¬
    getStatusText(status) {
      const textMap = {
        completed: "已完成",
        in_progress: "进行中",
        processing: "进行中",
        pending: "待处理"
      };
      return textMap[status] || "未知";
    },
    // èŽ·å–éšè®¿ç±»åž‹æ ‡ç­¾
    getFollowupTypeTag(type) {
      const typeMap = {
@@ -1140,6 +1196,7 @@
      };
      return typeMap[type] || "info";
    },
    // èŽ·å–éšè®¿ç±»åž‹æ–‡æœ¬
    getFollowupTypeText(type) {
      const textMap = {
@@ -1149,62 +1206,102 @@
      };
      return textMap[type] || "未知";
    },
    // ä¿å­˜åŸºæœ¬ä¿¡æ¯
    handleSave() {
      this.$refs.form.validate(valid => {
    async handleSave() {
      this.$refs.form.validate(async valid => {
        if (valid) {
          this.saveLoading = true;
          const apiMethod = this.form.id
            ? updateOrganUtilization
            : addOrganUtilization;
          try {
            const saveData = {
              ...this.form,
              assessannex: JSON.stringify(this.attachments),
              donateorgan: this.selectedOrgans.join(","),
              serviceDonatecomporganList:
                this.utilizationData.serviceDonatecomporganList || []
            };
          apiMethod(this.form)
            .then(response => {
              if (response.code === 200) {
                this.$message.success("保存成功");
                if (!this.form.id) {
                  this.form.id = response.data.id;
                  this.$router.replace({
                    query: { ...this.$route.query, id: this.form.id }
                  });
                }
            const apiMethod = this.form.id ? completionedit : completionadd;
            const response = await apiMethod(saveData);
            if (response.code === 200) {
              this.$message.success("保存成功");
              if (!this.form.id && response.data && response.data.id) {
                this.form.id = response.data.id;
                this.$router.replace({
                  query: { ...this.$route.query, id: this.form.id }
                });
              }
            })
            .catch(error => {
              console.error("保存失败:", error);
              this.$message.error("保存失败");
            })
            .finally(() => {
              this.saveLoading = false;
            });
            } else {
              this.$message.error("保存失败:" + (response.msg || "未知错误"));
            }
          } catch (error) {
            console.error("保存失败:", error);
            this.$message.error("保存失败");
          } finally {
            this.saveLoading = false;
          }
        }
      });
    },
    // ä¿å­˜åˆ©ç”¨è®°å½•
    handleSaveUtilization() {
      if (!this.form.id) {
        this.$message.warning("请先保存基本信息");
    async handleSaveUtilization() {
      if (
        !this.utilizationData.serviceDonatecomporganList ||
        this.utilizationData.serviceDonatecomporganList.length === 0
      ) {
        this.$message.warning("请先添加利用记录");
        return;
      }
      this.saveLoading = true;
      saveUtilizationRecords(this.form.id, this.utilizationData.records)
        .then(response => {
          if (response.code === 200) {
            this.$message.success("利用记录保存成功");
          }
        })
        .catch(error => {
          console.error("保存利用记录失败:", error);
          this.$message.error("保存利用记录失败");
        })
        .finally(() => {
          this.saveLoading = false;
        });
      try {
        const saveData = {
          ...this.form,
          attachments: this.attachments,
          donateorgan: this.selectedOrgans.join(","),
          serviceDonatecomporganList:
            this.utilizationData.serviceDonatecomporganList || []
        };
        const response = await completionedit(saveData);
        if (response.code === 200) {
          this.$message.success("利用记录保存成功");
        } else {
          this.$message.error(
            "保存利用记录失败:" + (response.msg || "未知错误")
          );
        }
      } catch (error) {
        console.error("保存利用记录失败:", error);
        this.$message.error("保存利用记录失败");
      } finally {
        this.saveLoading = false;
      }
    },
    // ç¡®è®¤å®Œæˆåˆ©ç”¨
    handleConfirmUtilization() {
      if (this.incompleteRecords > 0) {
    async handleConfirmUtilization() {
      // æ£€æŸ¥åˆ©ç”¨è®°å½•是否完整
      const incompleteRecords = this.utilizationData.serviceDonatecomporganList.filter(
        record => {
          if (record.transplantstate === "1") {
            return (
              !record.caseNo ||
              !record.hospitalno ||
              !record.name ||
              !record.transplanttime
            );
          } else if (record.transplantstate === "0") {
            return !record.abandonreason;
          }
          return false;
        }
      );
      if (incompleteRecords.length > 0) {
        this.$message.warning("请先完善所有利用记录的信息");
        return;
      }
@@ -1214,81 +1311,53 @@
        cancelButtonText: "取消",
        type: "warning"
      })
        .then(() => {
        .then(async () => {
          this.confirmLoading = true;
          this.form.utilizationStatus = "completed";
          this.form.completionTime = new Date()
            .toISOString()
            .replace("T", " ")
            .substring(0, 19);
          this.form.recordstate = "completed";
          this.form.completetime =
            this.form.completetime ||
            new Date()
              .toISOString()
              .replace("T", " ")
              .substring(0, 19);
          updateOrganUtilization(this.form)
            .then(response => {
              if (response.code === 200) {
                this.$message.success("器官利用已完成");
              }
            })
            .catch(error => {
              console.error("确认利用失败:", error);
              this.$message.error("确认利用失败");
            })
            .finally(() => {
              this.confirmLoading = false;
            });
        })
        .catch(() => {});
    },
    // å®Œæˆåˆ©ç”¨
    handleComplete() {
      this.handleConfirmUtilization();
    },
    // æ–°å¢žéšè®¿è®°å½•
    handleAddFollowup() {
      this.followupDialogTitle = "新增随访记录";
      this.isEditingFollowup = false;
      this.currentFollowup = {
        organNo: this.utilizationData.records.length > 0 ? this.utilizationData.records[0].organNo : "",
        followupTime: new Date().toISOString().replace("T", " ").substring(0, 19),
        followupType: "routine",
        recipientCondition: "",
        medicationSituation: "",
        testResults: "",
        nextFollowupTime: "",
        followupDoctor: ""
      };
      this.followupDialogVisible = true;
    },
    // æŸ¥çœ‹éšè®¿è®°å½•
    handleViewFollowup(record) {
      this.currentFollowup = { ...record };
      this.followupDialogTitle = "查看随访记录";
      this.followupDialogVisible = true;
    },
    // ç¼–辑随访记录
    handleEditFollowup(record) {
      this.followupDialogTitle = "编辑随访记录";
      this.isEditingFollowup = true;
      this.currentFollowup = { ...record };
      this.followupDialogVisible = true;
    },
    // åˆ é™¤éšè®¿è®°å½•
    handleDeleteFollowup(record) {
      this.$confirm("确定要删除这条随访记录吗?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      })
        .then(() => {
          const index = this.followupData.records.findIndex(
            item => item.id === record.id
          );
          if (index !== -1) {
            this.followupData.records.splice(index, 1);
            this.$message.success("随访记录删除成功");
          try {
            const saveData = {
              ...this.form,
              attachments: this.attachments,
              donateorgan: this.selectedOrgans.join(","),
              serviceDonatecomporganList:
                this.utilizationData.serviceDonatecomporganList || []
            };
            const response = await completionedit(saveData);
            if (response.code === 200) {
              this.$message.success("器官利用已完成");
            } else {
              this.$message.error(
                "确认利用失败:" + (response.msg || "未知错误")
              );
              this.form.recordstate = "pending";
              this.form.completetime = "";
            }
          } catch (error) {
            console.error("确认利用失败:", error);
            this.$message.error("确认利用失败");
            this.form.recordstate = "pending";
            this.form.completetime = "";
          } finally {
            this.confirmLoading = false;
          }
        })
        .catch(() => {});
    },
    // å®Œæˆåˆ©ç”¨
    handleComplete() {
      this.handleConfirmUtilization();
    },
    // ä¿å­˜éšè®¿è®°å½•
    handleSaveFollowup() {
      if (!this.currentFollowup.organNo) {
@@ -1304,10 +1373,10 @@
      this.saveLoading = true;
      // èŽ·å–å™¨å®˜åç§°
      const organRecord = this.utilizationData.records.find(
        item => item.organNo === this.currentFollowup.organNo
      const organRecord = this.utilizationData.serviceDonatecomporganList.find(
        item => item.organno === this.currentFollowup.organNo
      );
      const organName = organRecord ? organRecord.organName : "";
      const organName = organRecord ? organRecord.organname : "";
      const followupData = {
        ...this.currentFollowup,
@@ -1315,165 +1384,198 @@
        utilizationId: this.form.id
      };
      saveFollowupRecord(followupData)
        .then(response => {
          if (response.code === 200) {
            if (this.isEditingFollowup) {
              // æ›´æ–°çŽ°æœ‰è®°å½•
              const index = this.followupData.records.findIndex(
                item => item.id === this.currentFollowup.id
              );
              if (index !== -1) {
                this.followupData.records[index] = response.data;
              }
            } else {
              // æ·»åŠ æ–°è®°å½•
              this.followupData.records.push(response.data);
            }
            this.$message.success("随访记录保存成功");
            this.followupDialogVisible = false;
      // TODO: æ›¿æ¢ä¸ºå®žé™…的随访记录保存接口
      setTimeout(() => {
        if (this.isEditingFollowup) {
          // æ›´æ–°çŽ°æœ‰è®°å½•
          const index = this.followupData.records.findIndex(
            item => item.id === this.currentFollowup.id
          );
          if (index !== -1) {
            this.followupData.records[index] = {
              ...followupData,
              id: this.currentFollowup.id
            };
          }
        })
        .catch(error => {
          console.error("保存随访记录失败:", error);
          this.$message.error("保存随访记录失败");
        })
        .finally(() => {
          this.saveLoading = false;
        });
        } else {
          // æ·»åŠ æ–°è®°å½•
          this.followupData.records.push({ ...followupData, id: Date.now() });
        }
        this.$message.success("随访记录保存成功");
        this.followupDialogVisible = false;
        this.saveLoading = false;
      }, 1000);
    },
    // ä¸Šä¼ é™„ä»¶
    handleUploadAttachment() {
      this.$message.info("附件上传功能");
    /** é™„件变化处理 */
    handleAttachmentChange(fileList) {
      this.attachmentFileList = fileList;
    },
    // é¢„览附件
    handlePreviewAttachment(attachment) {
      this.$message.info("附件预览功能");
    },
    // ä¸‹è½½é™„ä»¶
    handleDownloadAttachment(attachment) {
      this.$message.info("附件下载功能");
    },
    // åˆ é™¤é™„ä»¶
    handleRemoveAttachment(attachment) {
      this.$confirm("确定要删除这个附件吗?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      })
        .then(() => {
    /** é™„件移除处理 */
    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.$message.success("附件删除成功");
        })
        .catch(() => {});
        }
      }
    },
    // èŽ·å–æ–‡ä»¶å›¾æ ‡
    getFileIcon(fileName) {
      const ext = fileName
        .split(".")
        .pop()
        .toLowerCase();
      const iconMap = {
        pdf: "el-icon-document",
        doc: "el-icon-document",
        docx: "el-icon-document",
        xls: "el-icon-document",
        xlsx: "el-icon-document",
        jpg: "el-icon-picture",
        jpeg: "el-icon-picture",
        png: "el-icon-picture"
    /** ä¸Šä¼ æˆåŠŸå¤„ç† */
    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.$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.$message.success("附件删除成功");
    },
    /** æ–‡ä»¶é¢„览 */
    handlePreview(file) {
      this.currentPreviewFile = {
        fileName: file.fileName,
        fileUrl: file.path || file.fileUrl,
        fileType: this.getFileType(file.fileName)
      };
      return iconMap[ext] || "el-icon-document";
      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) {
      const ext = fileName
      if (!fileName) return "other";
      const extension = fileName
        .split(".")
        .pop()
        .toLowerCase();
      const typeMap = {
        pdf: "PDF",
        doc: "DOC",
        docx: "DOCX",
        xls: "XLS",
        xlsx: "XLSX",
        jpg: "JPG",
        jpeg: "JPEG",
        png: "PNG"
      };
      return typeMap[ext] || ext.toUpperCase();
      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";
    },
    // æ–‡ä»¶å¤§å°æ ¼å¼åŒ–
    formatFileSize(size) {
      if (size === 0) return "0 B";
    /** èŽ·å–æ–‡ä»¶å›¾æ ‡é¢œè‰² */
    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(size) / Math.log(k));
      return parseFloat((size / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
      const i = Math.floor(Math.log(bytes) / Math.log(k));
      return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
    },
    // æ—¶é—´æ ¼å¼åŒ–
    parseTime(time) {
      if (!time) return "";
      const date = new Date(time);
      return `${date.getFullYear()}-${(date.getMonth() + 1)
        .toString()
        .padStart(2, "0")}-${date
        .getDate()
        .toString()
        .padStart(2, "0")} ${date
        .getHours()
        .toString()
        .padStart(2, "0")}:${date
        .getMinutes()
        .toString()
        .padStart(2, "0")}`;
    },
    // æäº¤å½’æ¡£
    handleSubmitArchive() {
      this.$confirm("确认提交归档吗?归档后将无法修改数据。", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      })
        .then(() => {
          this.$message.success("提交归档成功");
        })
        .catch(() => {});
    },
    // æ’¤é”€å½’æ¡£
    handleRevokeArchive() {
      this.$confirm("确认撤销归档吗?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      })
        .then(() => {
          this.$message.success("撤销归档成功");
        })
        .catch(() => {});
    },
    // ç»ˆæ­¢æ¡ˆä¾‹
    handleTerminateCase() {
      this.$confirm("确认终止案例吗?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      })
        .then(() => {
          this.$message.success("案例已终止");
        })
        .catch(() => {});
    },
    // æ¢å¤æ¡ˆä¾‹
    handleRestoreCase() {
      this.$confirm("确认恢复案例吗?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      })
        .then(() => {
          this.$message.success("案例已恢复");
        })
        .catch(() => {});
    /** æ—¥æœŸæ—¶é—´æ ¼å¼åŒ– */
    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;
      }
    }
  }
};
@@ -1486,29 +1588,81 @@
  min-height: 100vh;
}
.detail-card, .utilization-card, .recipient-card, .followup-card, .attachment-card {
.detail-card,
.utilization-card,
.followup-card,
.attachment-card {
  margin-bottom: 20px;
  border-radius: 8px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  border: 1px solid #e4e7ed;
}
/* æ–°å¢žé™„件头部样式 */
.attachment-header {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 16px;
  padding-bottom: 8px;
  border-bottom: 1px solid #ebeef5;
}
.attachment-title {
  font-weight: 600;
  color: #303133;
  font-size: 16px;
}
.attachment-tip {
  font-size: 12px;
  color: #909399;
  margin-left: auto;
}
.attachment-list {
  margin-top: 20px;
}
.list-title {
  font-weight: bold;
  margin-bottom: 12px;
  color: #303133;
  font-size: 14px;
}
.file-name {
  font-size: 13px;
  margin-left: 8px;
  color: #606266;
}
/* æ–‡ä»¶å›¾æ ‡æ ·å¼ */
.el-icon-document {
  font-size: 16px;
  vertical-align: middle;
}
/* ä¿æŒåŽŸæœ‰æ ·å¼ */
.detail-title {
  font-size: 18px;
  font-weight: 600;
  color: #303133;
  line-height: 1.4;
}
/* è¡¨æ ¼æ•´ä½“样式 */
:deep(.el-table) {
  border-radius: 8px;
  overflow: hidden;
}
:deep(.el-table th) {
  background-color: #f5f7fa;
  color: #606266;
  font-weight: 600;
}
:deep(.el-table .cell) {
  padding: 12px 8px;
  line-height: 1.5;
@@ -1518,6 +1672,7 @@
:deep(.el-table__row.warning-row) {
  background-color: #fdf6ec;
}
:deep(.el-table__row.default-row) {
  background-color: #f0f9ff;
}
@@ -1535,6 +1690,7 @@
  border-radius: 8px;
  color: white;
}
.stat-item {
  display: flex;
  flex-direction: column;
@@ -1542,84 +1698,238 @@
  padding: 10px;
  text-align: center;
}
.stat-label {
  font-size: 18px;
  font-size: 12px;
  opacity: 0.9;
  margin-bottom: 5px;
  color: rgba(255, 255, 255, 0.9);
}
.stat-value {
  font-size: 20px;
  font-size: 18px;
  font-weight: bold;
  color: white;
}
/* å±•开行样式 */
.recipient-detail-expand {
  padding: 20px;
  background: #fafafa;
  border-radius: 8px;
  margin: 10px 0;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.recipient-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 20px;
  padding-bottom: 15px;
  border-bottom: 2px solid #e4e7ed;
}
.recipient-title {
  font-size: 16px;
  font-weight: 600;
  color: #303133;
}
/* è¡¨å•部分样式 */
.recipient-form {
  background: white;
  padding: 20px;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
}
/* è¡¨å•部分标题 */
.form-section {
  margin-bottom: 25px;
  padding-bottom: 20px;
  border-bottom: 1px solid #f0f0f0;
  &:last-child {
    margin-bottom: 0;
    padding-bottom: 0;
    border-bottom: none;
  }
}
.section-title {
  font-size: 15px;
  font-weight: 600;
  color: #409eff;
  margin: 0 0 15px 0;
  padding-left: 10px;
  border-left: 4px solid #409eff;
  line-height: 1.2;
}
/* è¡¨å•行间距 */
:deep(.el-form-item) {
  margin-bottom: 20px;
  .el-form-item__label {
    font-weight: 500;
    color: #606266;
    padding-right: 10px;
  }
  .el-form-item__content {
    line-height: 1.5;
  }
}
/* è¡¨å•输入框样式 */
:deep(.el-input__inner) {
  height: 36px;
  line-height: 36px;
  border-radius: 4px;
  transition: all 0.3s ease;
  &:focus {
    border-color: #409eff;
    box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
  }
  &:disabled {
    background-color: #f5f7fa;
    border-color: #e4e7ed;
    color: #c0c4cc;
    cursor: not-allowed;
  }
}
/* æ–‡æœ¬åŸŸæ ·å¼ */
:deep(.el-textarea__inner) {
  min-height: 80px;
  border-radius: 4px;
  transition: all 0.3s ease;
  &:focus {
    border-color: #409eff;
    box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
  }
  &:disabled {
    background-color: #f5f7fa;
    border-color: #e4e7ed;
    color: #c0c4cc;
    cursor: not-allowed;
  }
}
/* é€‰æ‹©æ¡†æ ·å¼ */
:deep(.el-select) {
  width: 100%;
  .el-input__inner {
    border-radius: 4px;
  }
  &.is-disabled {
    .el-input__inner {
      background-color: #f5f7fa;
      border-color: #e4e7ed;
      color: #c0c4cc;
    }
  }
}
/* æ—¥æœŸé€‰æ‹©å™¨æ ·å¼ */
:deep(.el-date-editor) {
  width: 100%;
  &.el-input__inner {
    border-radius: 4px;
  }
  &.is-disabled {
    .el-input__inner {
      background-color: #f5f7fa;
      border-color: #e4e7ed;
      color: #c0c4cc;
    }
  }
}
/* å“åº”式调整 */
@media (max-width: 768px) {
  .recipient-detail-expand {
    padding: 15px;
  }
  .recipient-form {
    padding: 15px;
  }
  .attachment-header {
    flex-wrap: wrap;
  }
  .attachment-tip {
    width: 100%;
    margin-top: 8px;
    margin-left: 0;
  }
  .form-section {
    margin-bottom: 20px;
    padding-bottom: 15px;
  }
  :deep(.el-form-item) {
    margin-bottom: 15px;
  }
  .section-title {
    font-size: 14px;
    margin-bottom: 12px;
  }
}
:deep(.el-divider) {
  margin: 20px 0;
  background-color: #e4e7ed;
}
/* è¡¨å•标签和输入框样式 */
:deep(.el-form-item__label) {
  font-weight: 500;
  color: #606266;
}
:deep(.el-input__inner) {
  border-radius: 4px;
  transition: border-color 0.3s ease;
}
:deep(.el-input__inner:focus) {
  border-color: #409EFF;
  border-color: #409eff;
  box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
}
/* æŒ‰é’®æ ·å¼ä¼˜åŒ– */
:deep(.el-button--primary) {
  background: linear-gradient(135deg, #409EFF 0%, #3375e0 100%);
  background: linear-gradient(135deg, #409eff 0%, #3375e0 100%);
  border: none;
  border-radius: 4px;
  transition: all 0.3s ease;
}
:deep(.el-button--primary:hover) {
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(64, 158, 255, 0.4);
}
/* æ ‡ç­¾é¡µæ ·å¼ */
:deep(.el-tabs__item) {
  font-weight: 500;
}
:deep(.el-tabs__active-bar) {
  background: linear-gradient(135deg, #409EFF 0%, #3375e0 100%);
}
/* å¹³æ¿è®¾å¤‡é€‚配 */
@media (max-width: 1024px) {
  .organ-utilization-detail {
    padding: 15px;
  }
  :deep(.el-col) {
    margin-bottom: 10px;
  }
/* åº•部操作按钮 */
.dialog-footer {
  margin-top: 20px;
  text-align: center;
  padding-top: 20px;
  border-top: 1px solid #e4e7ed;
}
/* æ‰‹æœºè®¾å¤‡é€‚配 */
@media (max-width: 768px) {
  .organ-utilization-detail {
    padding: 10px;
  }
  .detail-title {
    font-size: 16px;
  }
  :deep(.el-table .cell) {
    padding: 8px 4px;
    font-size: 12px;
  }
  :deep(.el-form-item__label) {
    font-size: 12px;
  }
.dialog-footer .el-button {
  margin: 0 10px;
  min-width: 120px;
}
/* è¶…小屏幕设备 */
@media (max-width: 480px) {
  .organ-utilization-detail {
    padding: 5px;
  }
  :deep(.el-card__header) {
    padding: 10px 15px;
  }
}
/* ç©ºçŠ¶æ€æ ·å¼ */
.empty-utilization {
  text-align: center;
@@ -1630,27 +1940,39 @@
  margin: 20px 0;
}
/* åŠ è½½çŠ¶æ€ */
:deep(.el-loading-mask) {
  border-radius: 4px;
}
/* æ–‡ä»¶ä¿¡æ¯æ ·å¼ */
.file-info {
  display: flex;
  align-items: center;
  padding: 5px 0;
}
.file-info i {
  font-size: 18px;
  margin-right: 10px;
}
/* åŠ¨ç”»æ•ˆæžœ */
.fade-enter-active, .fade-leave-active {
  transition: opacity 0.3s ease;
/* å¹³æ¿è®¾å¤‡é€‚配 */
@media (max-width: 1024px) {
  .organ-utilization-detail {
    padding: 15px;
  }
  :deep(.el-col) {
    margin-bottom: 10px;
  }
}
.fade-enter, .fade-leave-to {
  opacity: 0;
/* æ‰‹æœºè®¾å¤‡é€‚配 */
/* è¶…小屏幕设备 */
@media (max-width: 480px) {
  .organ-utilization-detail {
    padding: 5px;
  }
  :deep(.el-card__header) {
    padding: 10px 15px;
  }
}
</style>
src/views/business/allocation/allocationInfo.vue
@@ -12,7 +12,7 @@
          <el-button
            type="success"
            @click="handleConfirmAllocation"
            :disabled="form.allocationStatus === '1'"
            :disabled="form.allocationStatus == '1'"
            :loading="confirmLoading"
          >
            ç¡®è®¤åˆ†é…
@@ -44,7 +44,7 @@
                type="datetime"
                value-format="yyyy-MM-dd HH:mm:ss"
                style="width: 100%"
                :disabled="form.allocationStatus === '1'"
                :disabled="form.allocationStatus == '1'"
              />
            </el-form-item>
          </el-col>
@@ -77,17 +77,17 @@
        <div style="float: right;">
          <el-tag
            :type="
              form.allocationStatus === '1'
              form.allocationStatus == '1'
                ? 'success'
                : form.allocationStatus === '2'
                : form.allocationStatus == '2'
                ? 'danger'
                : 'warning'
            "
          >
            {{
              form.allocationStatus === "1"
              form.allocationStatus == "1"
                ? "已分配"
                : form.allocationStatus === "2"
                : form.allocationStatus == "2"
                ? "作废"
                : "未分配"
            }}
@@ -112,7 +112,7 @@
                  v-for="dict in dict.type.sys_Organ || []"
                  :key="dict.value"
                  :label="dict.value"
                  :disabled="form.allocationStatus === '1'"
                  :disabled="form.allocationStatus == '1'"
                >
                  {{ dict.label }}
                </el-checkbox>
@@ -162,7 +162,7 @@
                    <el-input
                      v-model="scope.row.caseno"
                      placeholder="分配系统编号"
                      :disabled="form.allocationStatus === '1'"
                      :disabled="form.allocationStatus == '1'"
                    />
                  </template>
                </el-table-column>
@@ -182,7 +182,7 @@
                      type="datetime"
                      value-format="yyyy-MM-dd HH:mm:ss"
                      placeholder="选择分配接收时间"
                      :disabled="form.allocationStatus === '1'"
                      :disabled="form.allocationStatus == '1'"
                    />
                  </template>
                </el-table-column>
@@ -197,7 +197,7 @@
                    <el-input
                      v-model="scope.row.name"
                      placeholder="受体姓氏"
                      :disabled="form.allocationStatus === '1'"
                      :disabled="form.allocationStatus == '1'"
                    />
                  </template>
                </el-table-column>
@@ -233,7 +233,7 @@
                      clearable
                      v-model="scope.row.reallocationreason"
                      placeholder="请输入说明"
                      :disabled="form.allocationStatus === '1'"
                      :disabled="form.allocationStatus == '1'"
                    />
                  </template>
                </el-table-column>
@@ -297,17 +297,17 @@
                <span class="stat-value">
                  <el-tag
                    :type="
                      form.allocationStatus === '1'
                      form.allocationStatus == '1'
                        ? 'success'
                        : form.allocationStatus === '2'
                        : form.allocationStatus == '2'
                        ? 'danger'
                        : 'warning'
                    "
                  >
                    {{
                      form.allocationStatus === "1"
                      form.allocationStatus == "1"
                        ? "已分配"
                        : form.allocationStatus === "2"
                        : form.allocationStatus == "2"
                        ? "作废"
                        : "未分配"
                    }}
@@ -332,7 +332,7 @@
          :loading="saveLoading"
          :disabled="
            !allocationData.serviceDonateorganList ||
              allocationData.serviceDonateorganList.length === 0
              allocationData.serviceDonateorganList.length == 0
          "
        >
          ä¿å­˜åˆ†é…è®°å½•
@@ -645,7 +645,7 @@
  methods: {
    // æ ¹æ®å­—å…¸value获取label
    getOrganLabel(organValue) {
      const dictItem = this.organDict.find(item => item.value === organValue);
      const dictItem = this.organDict.find(item => item.value == organValue);
      return dictItem ? dictItem.label : organValue;
    },
@@ -702,17 +702,14 @@
      donateorganBaseinfoInfo(id);
      try {
        const response = await allocationList({ infoid });
        if (
          response.code === 200 &&
          response.data &&
          response.data.length > 0
        ) {
        if (response.code == 200 && response.data && response.data.length > 0) {
          const data = response.data[0];
          data.allocationStatus = JSON.stringify(data.allocationStatus);
          // å¡«å……表单数据
          Object.assign(this.form, data);
          // è½¬æ¢é™„件为集合
            this.parseFilePatch(this.form.fileName);
          this.parseFilePatch(this.form.fileName);
          // åˆå§‹åŒ–附件
          if (this.form.attachments) {
@@ -741,7 +738,7 @@
                if (item.organname) {
                  const dictItem = this.organDict.find(
                    org =>
                      org.label === item.organname ||
                      org.label == item.organname ||
                      (item.organname && item.organname.includes(org.label))
                  );
                  return dictItem ? dictItem.value : null;
@@ -881,7 +878,7 @@
      let organName = this.getOrganLabel(organValue);
      // å¦‚果是"其他"器官且有输入值
      if (organValue === "C01" && this.otherOrganInput) {
      if (organValue == "C01" && this.otherOrganInput) {
        organName = `其他(${this.otherOrganInput})`;
      }
@@ -902,7 +899,7 @@
    // åŒ»é™¢é€‰æ‹©å˜åŒ–
    handleHospitalChange(row, hospitalNo) {
      const hospital = this.hospitalList.find(
        item => item.hospitalNo === hospitalNo
        item => item.hospitalNo == hospitalNo
      );
      if (hospital) {
        row.transplantHospitalName = hospital.hospitalName;
@@ -942,7 +939,7 @@
    },
    // æž„建 filePatch å­—段
    buildFilePatch() {
      if (!this.attachments || this.attachments.length === 0) {
      if (!this.attachments || this.attachments.length == 0) {
        return "";
      }
      return JSON.stringify(this.attachments);
@@ -962,23 +959,22 @@
            serviceDonateorganList:
              this.allocationData.serviceDonateorganList || []
          };
          saveData.fileName=this.buildFilePatch();
          saveData.fileName = this.buildFilePatch();
          saveData.serviceDonateorganList.forEach(item => {
            item.baseid = this.form.id;
            item.infoid = this.form.infoid;
          });
          console.log(this.form.recordstate);
          this.form.recordstate = 1;
          const apiMethod = this.form.id ? allocationedit : allocationadd;
          const response = await apiMethod(saveData);
          if (response.code === 200) {
          if (response.code == 200) {
            this.$message.success("保存成功");
            if (!this.form.id && response.data && response.data.id) {
              this.form.id = response.data.id;
              this.$router.replace({
                query: { ...this.$route.query, id: this.form.id }
              });
            if (!this.form.id && response.data) {
              this.form.id = response.data;
              // this.$router.replace({
              //   query: { ...this.$route.query, id: this.form.id }
              // });
            }
          } else {
            this.$message.error("保存失败:" + (response.msg || "未知错误"));
@@ -1009,7 +1005,7 @@
        const response = await allocationedit(saveData);
        if (response.code === 200) {
        if (response.code == 200) {
          this.$message.success("分配记录保存成功");
        } else {
          this.$message.error(
@@ -1053,7 +1049,7 @@
            const response = await allocationedit(saveData);
            if (response.code === 200) {
            if (response.code == 200) {
              this.$message.success("器官分配已完成");
            } else {
              this.$message.error(
@@ -1084,7 +1080,7 @@
    handleAttachmentRemove(file) {
      if (file.url) {
        const index = this.attachments.findIndex(
          item => item.path === file.url || item.fileUrl === file.url
          item => item.path == file.url || item.fileUrl == file.url
        );
        if (index > -1) {
          this.attachments.splice(index, 1);
@@ -1095,7 +1091,7 @@
    /** ä¸Šä¼ æˆåŠŸå¤„ç† */
    handleUploadSuccess({ file, fileList, response }) {
      if (response.code === 200) {
      if (response.code == 200) {
        const attachmentObj = {
          fileName: file.name,
          path: response.fileUrl || file.url,
@@ -1224,7 +1220,7 @@
    /** æ ¼å¼åŒ–文件大小 */
    formatFileSize(bytes) {
      if (!bytes || bytes === 0) return "0 B";
      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));
src/views/business/followupVisit/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,1349 @@
<template>
  <div class="followup-list">
    <!-- æŸ¥è¯¢æ¡ä»¶ -->
    <el-card class="search-card">
      <el-form
        :model="queryParams"
        ref="queryForm"
        :inline="true"
        label-width="100px"
      >
        <el-form-item label="器官受体者姓名" prop="recipientname">
          <el-input
            v-model="queryParams.recipientname"
            placeholder="请输入器官受体者姓名"
            clearable
            style="width: 200px"
            @keyup.enter.native="handleQuery"
          />
        </el-form-item>
        <el-form-item label="移植医院" prop="hospitalname">
          <el-input
            v-model="queryParams.hospitalname"
            placeholder="请输入移植医院名称"
            clearable
            style="width: 200px"
            @keyup.enter.native="handleQuery"
          />
        </el-form-item>
        <el-form-item label="随访者" prop="followupno">
          <el-input
            v-model="queryParams.followupno"
            placeholder="请输入随访者"
            clearable
            style="width: 180px"
            @keyup.enter.native="handleQuery"
          />
        </el-form-item>
        <el-form-item label="捐献结果" prop="donateresult">
          <el-select
            v-model="queryParams.donateresult"
            placeholder="请选择捐献结果"
            clearable
            style="width: 180px"
          >
            <el-option label="成功" value="1" />
            <el-option label="失败" value="0" />
            <el-option label="进行中" value="2" />
          </el-select>
        </el-form-item>
        <el-form-item label="随访时间" prop="followupTimeRange">
          <el-date-picker
            v-model="queryParams.followupTimeRange"
            type="daterange"
            range-separator="至"
            start-placeholder="开始日期"
            end-placeholder="结束日期"
            value-format="yyyy-MM-dd"
            style="width: 240px"
          />
        </el-form-item>
        <el-form-item label="创建时间" prop="createTimeRange">
          <el-date-picker
            v-model="queryParams.createTimeRange"
            type="daterange"
            range-separator="至"
            start-placeholder="开始日期"
            end-placeholder="结束日期"
            value-format="yyyy-MM-dd"
            style="width: 240px"
          />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" icon="el-icon-search" @click="handleQuery"
            >搜索</el-button
          >
          <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
        </el-form-item>
      </el-form>
    </el-card>
    <!-- æ“ä½œæŒ‰é’® -->
    <el-card class="tool-card">
      <el-row :gutter="10">
        <el-col :span="16">
          <el-button
            type="primary"
            icon="el-icon-plus"
            @click="handleCreate"
            v-hasPermi="['system:followup:add']"
            >新增随访</el-button
          >
          <el-button
            type="success"
            icon="el-icon-edit"
            :disabled="single"
            @click="handleUpdate"
            v-hasPermi="['system:followup:edit']"
            >修改</el-button
          >
          <el-button
            type="danger"
            icon="el-icon-delete"
            :disabled="multiple"
            @click="handleDelete"
            v-hasPermi="['system:followup:remove']"
            >删除</el-button
          >
          <el-button
            type="warning"
            icon="el-icon-download"
            @click="handleExport"
            v-hasPermi="['system:followup:export']"
            >导出</el-button
          >
        </el-col>
        <el-col :span="8" style="text-align: right">
          <el-tooltip content="刷新" placement="top">
            <el-button icon="el-icon-refresh" circle @click="getList" />
          </el-tooltip>
        </el-col>
      </el-row>
    </el-card>
    <!-- æ•°æ®è¡¨æ ¼ -->
    <el-card>
      <el-table
        v-loading="loading"
        :data="followupList"
        @selection-change="handleSelectionChange"
        border
        :default-sort="{ prop: 'followuptime', order: 'descending' }"
      >
        <el-table-column type="selection" width="55" align="center" />
        <el-table-column
          label="随访序号"
          align="center"
          prop="seqno"
          width="100"
        >
          <template slot-scope="scope">
            <span>第{{ scope.row.seqno || 1 }}次</span>
          </template>
        </el-table-column>
        <el-table-column
          label="随访时间"
          align="center"
          prop="followuptime"
          width="120"
        >
          <template slot-scope="scope">
            <span>{{ parseTime(scope.row.followuptime, "{y}-{m}-{d}") }}</span>
          </template>
        </el-table-column>
        <el-table-column
          label="器官受体者姓名"
          align="center"
          prop="recipientname"
          width="120"
        />
        <el-table-column
          label="移植医院"
          align="center"
          prop="hospitalname"
          width="150"
          show-overflow-tooltip
        />
        <el-table-column
          label="移植科室"
          align="center"
          prop="hospitaldept"
          width="120"
        />
        <el-table-column
          label="随访医生"
          align="center"
          prop="doctorname"
          width="120"
        />
        <el-table-column
          label="医生电话"
          align="center"
          prop="doctorphone"
          width="120"
        />
        <el-table-column
          label="捐献结果"
          align="center"
          prop="donateresult"
          width="100"
        >
          <template slot-scope="scope">
            <el-tag :type="resultTypeFilter(scope.row.donateresult)">
              {{ resultTextFilter(scope.row.donateresult) }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column
          label="随访者"
          align="center"
          prop="followupno"
          width="100"
        />
        <el-table-column
          label="随访描述"
          align="center"
          prop="followupdescribe"
          min-width="200"
          show-overflow-tooltip
        />
        <el-table-column
          label="创建时间"
          align="center"
          prop="createTime"
          width="120"
        >
          <template slot-scope="scope">
            <span>{{ parseTime(scope.row.createTime, "{y}-{m}-{d}") }}</span>
          </template>
        </el-table-column>
        <el-table-column
          label="操作"
          align="center"
          width="150"
          fixed="right"
          class-name="small-padding fixed-width"
        >
          <template slot-scope="scope">
            <el-button
              size="mini"
              type="text"
              icon="el-icon-view"
              @click="handleView(scope.row)"
              v-hasPermi="['system:followup:query']"
              >详情</el-button
            >
            <!-- <el-button
              size="mini"
              type="text"
              icon="el-icon-edit"
              @click="handleUpdate(scope.row)"
              v-hasPermi="['system:followup:edit']"
              >修改</el-button
            > -->
            <el-button
              size="mini"
              type="text"
              icon="el-icon-delete"
              @click="handleDelete(scope.row)"
              v-hasPermi="['system:followup:remove']"
              >删除</el-button
            >
          </template>
        </el-table-column>
      </el-table>
      <!-- åˆ†é¡µç»„ä»¶ -->
      <pagination
        v-show="total > 0"
        :total="total"
        :page.sync="queryParams.pageNum"
        :limit.sync="queryParams.pageSize"
        @pagination="getList"
      />
    </el-card>
    <!-- é€‰æ‹©æ¡ˆä¾‹å¯¹è¯æ¡† - å‚照捐献案例列表页的完整功能 -->
    <el-dialog
      title="选择捐献案例"
      :visible.sync="selectCaseOpen"
      width="1200px"
      append-to-body
      :close-on-click-modal="false"
    >
      <!-- æœç´¢è¡¨å• -->
      <el-form
        :model="caseQueryParams"
        ref="caseQueryForm"
        :inline="true"
        label-width="88px"
      >
        <el-form-item label="捐献者姓名" prop="name">
          <el-input
            v-model="caseQueryParams.name"
            placeholder="请输入姓名"
            clearable
            size="small"
            @keyup.enter.native="searchCaseList"
          />
        </el-form-item>
        <el-form-item label="治疗医院" prop="treatmenthospitalname">
          <el-input
            v-model="caseQueryParams.treatmenthospitalname"
            placeholder="请输入治疗医院"
            clearable
            size="small"
            style="width: 150px"
          />
        </el-form-item>
        <el-form-item label="上报时间">
          <el-date-picker
            style="width: 100%"
            v-model="caseSelectTime"
            type="monthrange"
            range-separator="至"
            start-placeholder="开始月份"
            end-placeholder="结束月份"
            value-format="yyyy-MM-dd"
            @change="handleCaseTimeSelect"
            size="small"
          />
        </el-form-item>
        <el-row>
          <el-col :span="4">
            <el-form-item>
              <el-button
                type="primary"
                icon="el-icon-search"
                size="mini"
                @click="searchCaseList"
              >
                æœç´¢
              </el-button>
              <el-button
                icon="el-icon-refresh"
                size="mini"
                @click="resetCaseSearch"
              >
                é‡ç½®
              </el-button>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <!-- æ¡ˆä¾‹è¡¨æ ¼ -->
      <el-table
        v-loading="caseLoading"
        :data="availableCaseList"
        @row-click="handleCaseRowClick"
        highlight-current-row
        style="width: 100%; margin-top: 20px;"
      >
        <el-table-column
          label="案例时间"
          align="center"
          prop="donatetime"
          width="100"
        >
          <template slot-scope="scope">
            <span>{{ parseTime(scope.row.donatetime, "{y}-{m}-{d}") }}</span>
          </template>
        </el-table-column>
        <el-table-column
          label="案例编号"
          align="center"
          prop="caseNo"
          width="200"
        />
        <el-table-column
          label="捐献者姓名"
          align="center"
          prop="name"
          width="100"
        />
        <el-table-column label="性别" align="center" prop="sex" width="100">
          <template slot-scope="scope">
            <dict-tag
              :options="dict.type.sys_user_sex"
              :value="parseInt(scope.row.sex)"
            />
          </template>
        </el-table-column>
        <el-table-column label="年龄" align="center" prop="age" width="100">
          <template slot-scope="scope">
            {{
              `${
                scope.row.age && scope.row.age !== 0
                  ? `${scope.row.age}${scope.row.ageunit || ""}`
                  : ""
              } ${
                scope.row.age2 && scope.row.age2 !== 0
                  ? `${scope.row.age2}${scope.row.ageunit2}`
                  : ""
              }`.trim()
            }}
          </template>
        </el-table-column>
        <el-table-column
          label="治疗医院"
          align="center"
          prop="treatmenthospitalname"
          show-overflow-tooltip
        />
        <el-table-column
          label="GCS评分"
          align="center"
          prop="gcsScore"
          width="100"
        />
        <el-table-column
          label="血型"
          align="center"
          prop="bloodtype"
          width="100"
        >
          <template slot-scope="scope">
            <dict-tag
              :options="dict.type.sys_BloodType"
              :value="scope.row.bloodtype"
            />
          </template>
        </el-table-column>
        <el-table-column
          label="捐献类别"
          align="center"
          prop="donationcategory"
        >
          <template slot-scope="scope">
            <dict-tag
              :options="dict.type.sys_DonationCategory"
              :value="scope.row.donationcategory"
            />
          </template>
        </el-table-column>
        <el-table-column
          label="报告人"
          align="center"
          prop="reportername"
        />
        <el-table-column
          label="捐献进度"
          align="center"
          prop="workflow"
        >
          <template slot-scope="scope">
            <div v-if="!scope.row.terminationCase">
              <dict-tag
                :options="dict.type.sys_donornode"
                :value="scope.row.workflow"
              />
            </div>
            <div v-else>
              <el-button type="danger" plain>任务终止</el-button>
            </div>
          </template>
        </el-table-column>
        <el-table-column label="是否已有随访" width="100" align="center">
          <template slot-scope="scope">
            <el-tag
              :type="hasFollowup(scope.row) ? 'danger' : 'success'"
              size="small"
            >
              {{ hasFollowup(scope.row) ? "已有随访" : "可选择" }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="操作"  align="center">
          <template slot-scope="scope">
            <el-button
              type="text"
              size="mini"
              @click.stop="selectCase(scope.row)"
              :disabled="hasFollowup(scope.row) || scope.row.terminationCase"
            >
              é€‰æ‹©
            </el-button>
          </template>
        </el-table-column>
      </el-table>
      <!-- åˆ†é¡µ -->
      <pagination
        v-show="caseTotal > 0"
        :total="caseTotal"
        :page.sync="caseQueryParams.pageNum"
        :limit.sync="caseQueryParams.pageSize"
        @pagination="searchCaseList"
        style="padding: 10px 0; background: #fff; border-top: 1px solid #ebeef5;"
      />
      <div slot="footer" class="dialog-footer">
        <el-button @click="selectCaseOpen = false">取消</el-button>
        <el-button
          type="primary"
          @click="confirmCaseSelection"
          v-if="selectedCaseRow"
        >
          ç¡®è®¤é€‰æ‹©
        </el-button>
      </div>
    </el-dialog>
    <!-- æ–°å¢ž/修改对话框 -->
    <el-dialog
      :title="title"
      :visible.sync="open"
      width="800px"
      append-to-body
      :close-on-click-modal="false"
    >
      <el-form ref="form" :model="form" :rules="rules" label-width="120px">
        <el-form-item label="关联案例" prop="infoid">
          <el-input
            v-model="form.infoid"
            placeholder="请选择案例"
            :disabled="true"
            style="width: 300px"
          >
            <el-button
              slot="append"
              icon="el-icon-search"
              @click="openCaseDialog"
              v-if="!form.id"
              >选择案例</el-button
            >
          </el-input>
          <div v-if="selectedCase" style="margin-top: 8px; color: #666;">
            <span>案例编号: {{ selectedCase.caseNo }}</span>
            <span style="margin-left: 20px;"
              >捐献者: {{ selectedCase.name }}</span
            >
            <span style="margin-left: 20px; display: block; margin-top: 5px;">
              æ²»ç–—医院: {{ selectedCase.treatmenthospitalname }}
            </span>
            <span style="margin-left: 20px; display: block; margin-top: 5px;">
              è¯Šæ–­: {{ selectedCase.diagnosisname }}
            </span>
            <span style="margin-left: 20px; display: block; margin-top: 5px;">
              è¡€åž‹:
              <dict-tag
                :options="dict.type.sys_BloodType"
                :value="selectedCase.bloodtype"
              />
            </span>
          </div>
        </el-form-item>
        <el-row>
          <el-col :span="12">
            <el-form-item label="器官受体者姓名" prop="recipientname">
              <el-input
                v-model="form.recipientname"
                placeholder="请输入器官受体者姓名"
                maxlength="50"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="受体电话" prop="recipientphone">
              <el-input
                v-model="form.recipientphone"
                placeholder="请输入器官受体者电话"
                maxlength="20"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="移植医院名称" prop="hospitalname">
              <el-input
                v-model="form.hospitalname"
                placeholder="请输入移植医院名称"
                maxlength="100"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="移植科室" prop="hospitaldept">
              <el-input
                v-model="form.hospitaldept"
                placeholder="请输入移植医院科室"
                maxlength="50"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="随访医生姓名" prop="doctorname">
              <el-input
                v-model="form.doctorname"
                placeholder="请输入接受随访医生姓名"
                maxlength="50"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="医生电话" prop="doctorphone">
              <el-input
                v-model="form.doctorphone"
                placeholder="请输入接受随访医生电话"
                maxlength="20"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="捐献结果" prop="donateresult">
              <el-select
                v-model="form.donateresult"
                placeholder="请选择捐献结果"
                style="width: 100%"
              >
                <el-option label="成功" value="1" />
                <el-option label="失败" value="0" />
                <el-option label="进行中" value="2" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="随访时间" prop="followuptime">
              <el-date-picker
                v-model="form.followuptime"
                type="datetime"
                placeholder="选择随访时间"
                value-format="yyyy-MM-dd HH:mm:ss"
                style="width: 100%"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-form-item label="随访序号" prop="seqno">
          <el-input-number
            v-model="form.seqno"
            :min="1"
            :max="20"
            placeholder="请输入随访序号"
            style="width: 200px"
          />
          <span style="margin-left: 10px; color: #999;"
            >(第{{ form.seqno || 1 }}次随访)</span
          >
        </el-form-item>
        <el-form-item label="随访者" prop="followupno">
          <el-input
            v-model="form.followupno"
            placeholder="请输入随访者"
            maxlength="50"
            style="width: 300px"
          />
        </el-form-item>
        <el-form-item label="医生描述" prop="doctordescribe">
          <el-input
            v-model="form.doctordescribe"
            type="textarea"
            placeholder="请输入医生描述"
            maxlength="500"
            :rows="3"
            show-word-limit
          />
        </el-form-item>
        <el-form-item label="随访描述" prop="followupdescribe">
          <el-input
            v-model="form.followupdescribe"
            type="textarea"
            placeholder="请输入随访描述"
            maxlength="1000"
            :rows="4"
            show-word-limit
          />
        </el-form-item>
        <el-form-item label="受体者描述" prop="recipientdescribe">
          <el-input
            v-model="form.recipientdescribe"
            type="textarea"
            placeholder="请输入器官受体者描述"
            maxlength="500"
            :rows="3"
            show-word-limit
          />
        </el-form-item>
        <el-form-item label="备注" prop="remark">
          <el-input
            v-model="form.remark"
            type="textarea"
            placeholder="请输入备注"
            maxlength="500"
            :rows="3"
            show-word-limit
          />
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submitForm">ç¡® å®š</el-button>
        <el-button @click="cancel">取 æ¶ˆ</el-button>
      </div>
    </el-dialog>
  </div>
</template>
<script>
import {
  listFollowup,
  getFollowup,
  addFollowup,
  updateFollowup,
  delFollowup,
  exportFollowup
} from "@/api/businessApi/followup";
import { listDonatebaseinfo } from "@/api/project/donatebaseinfo";
import Pagination from "@/components/Pagination";
export default {
  name: "Followup",
  components: { Pagination },
  dicts: [
    "sys_user_sex",
    "sys_BloodType",
    "sys_DonationCategory",
    "sys_donornode"
  ],
  data() {
    return {
      // é®ç½©å±‚
      loading: true,
      caseLoading: false,
      exportLoading: false,
      // é€‰ä¸­æ•°ç»„
      ids: [],
      // éžå•个禁用
      single: true,
      // éžå¤šä¸ªç¦ç”¨
      multiple: true,
      // æ€»æ¡æ•°
      total: 0,
      caseTotal: 0,
      // éšè®¿è¡¨æ ¼æ•°æ®
      followupList: [],
      // å¼¹å‡ºå±‚标题
      title: "",
      // æ˜¯å¦æ˜¾ç¤ºå¼¹å‡ºå±‚
      open: false,
      // æ˜¯å¦æ˜¾ç¤ºé€‰æ‹©æ¡ˆä¾‹å¼¹å‡ºå±‚
      selectCaseOpen: false,
      // æ—¶é—´é€‰æ‹©
      caseSelectTime: [],
      // æŸ¥è¯¢å‚æ•°
      queryParams: {
        pageNum: 1,
        pageSize: 10,
        recipientname: undefined,
        hospitalname: undefined,
        followupno: undefined,
        donateresult: undefined,
        followupTimeRange: [],
        createTimeRange: []
      },
      // æ¡ˆä¾‹æŸ¥è¯¢å‚æ•°
      caseQueryParams: {
        pageNum: 1,
        pageSize: 10,
        name: undefined,
        treatmenthospitalname: undefined,
        starttime: undefined,
        endtime: undefined
      },
      // å¯é€‰æ‹©çš„æ¡ˆä¾‹åˆ—表
      availableCaseList: [],
      // å½“前选中的案例
      selectedCase: null,
      selectedCaseRow: null,
      // å·²æœ‰éšè®¿çš„æ¡ˆä¾‹ID缓存
      existingFollowupCases: new Set(),
      // è¡¨å•参数
      form: {
        id: undefined,
        infoid: undefined,
        organid: undefined,
        recipientname: "",
        recipientphone: "",
        recipientdescribe: "",
        hospitalname: "",
        hospitaldept: "",
        hospitalno: "",
        doctorname: "",
        doctorphone: "",
        doctordescribe: "",
        donateresult: "",
        followuptime: undefined,
        followupno: "",
        followupdescribe: "",
        seqno: 1,
        remark: ""
      },
      // è¡¨å•校验
      rules: {
        infoid: [
          { required: true, message: "请选择关联案例", trigger: "blur" }
        ],
        recipientname: [
          {
            required: true,
            message: "器官受体者姓名不能为空",
            trigger: "blur"
          },
          { max: 50, message: "长度不能超过50个字符", trigger: "blur" }
        ],
        hospitalname: [
          { required: true, message: "移植医院名称不能为空", trigger: "blur" },
          { max: 100, message: "长度不能超过100个字符", trigger: "blur" }
        ],
        followuptime: [
          { required: true, message: "随访时间不能为空", trigger: "change" }
        ],
        followupno: [
          { required: true, message: "随访者不能为空", trigger: "blur" },
          { max: 50, message: "长度不能超过50个字符", trigger: "blur" }
        ],
        donateresult: [
          { required: true, message: "捐献结果不能为空", trigger: "change" }
        ],
        seqno: [
          { required: true, message: "随访序号不能为空", trigger: "blur" },
          {
            type: "number",
            min: 1,
            max: 20,
            message: "随访序号范围为1-20",
            trigger: "blur"
          }
        ]
      }
    };
  },
  created() {
    this.getList();
  },
  methods: {
    // ç»“果类型过滤器
    resultTypeFilter(result) {
      const resultMap = {
        "1": "success", // æˆåŠŸ
        "0": "danger", // å¤±è´¥
        "2": "primary" // è¿›è¡Œä¸­
      };
      return resultMap[result] || "info";
    },
    resultTextFilter(result) {
      const resultMap = {
        "1": "成功",
        "0": "失败",
        "2": "进行中"
      };
      return resultMap[result] || "未知";
    },
    // æŸ¥è¯¢éšè®¿åˆ—表
    async getList() {
      this.loading = true;
      try {
        const requestParams = this.buildRequestParams();
        const response = await listFollowup(requestParams);
        if (response.code === 200) {
          this.handleResponseData(response);
          // åŠ è½½éšè®¿æ•°æ®åŽï¼Œæå–å·²æœ‰çš„æ¡ˆä¾‹ID
          this.extractExistingCaseIds();
        } else {
          this.$message.error("获取数据失败:" + (response.msg || "未知错误"));
          this.followupList = [];
          this.total = 0;
        }
      } catch (error) {
        console.error("获取随访列表失败:", error);
        this.$message.error("获取数据失败");
        this.followupList = [];
        this.total = 0;
      } finally {
        this.loading = false;
      }
    },
    // æž„建请求参数
    buildRequestParams() {
      const params = {
        pageNum: this.queryParams.pageNum,
        pageSize: this.queryParams.pageSize
      };
      if (this.queryParams.recipientname) {
        params.recipientname = this.queryParams.recipientname;
      }
      if (this.queryParams.hospitalname) {
        params.hospitalname = this.queryParams.hospitalname;
      }
      if (this.queryParams.followupno) {
        params.followupno = this.queryParams.followupno;
      }
      if (
        this.queryParams.donateresult !== undefined &&
        this.queryParams.donateresult !== ""
      ) {
        params.donateresult = this.queryParams.donateresult;
      }
      if (
        this.queryParams.followupTimeRange &&
        this.queryParams.followupTimeRange.length === 2
      ) {
        params.startFollowupTime = this.queryParams.followupTimeRange[0];
        params.endFollowupTime = this.queryParams.followupTimeRange[1];
      }
      if (
        this.queryParams.createTimeRange &&
        this.queryParams.createTimeRange.length === 2
      ) {
        params.startCreateTime = this.queryParams.createTimeRange[0];
        params.endCreateTime = this.queryParams.createTimeRange[1];
      }
      return params;
    },
    // å¤„理接口响应数据
    handleResponseData(response) {
      if (response.data) {
        if (Array.isArray(response.data)) {
          this.followupList = response.data;
          this.total = response.data.length;
        } else if (response.data.rows) {
          this.followupList = response.data.rows;
          this.total = response.data.total;
        } else if (Array.isArray(response.data.list)) {
          this.followupList = response.data.list;
          this.total = response.data.total || response.data.list.length;
        } else {
          this.followupList = response.data;
          this.total = response.total || response.data.length;
        }
      } else {
        if (Array.isArray(response.rows)) {
          this.followupList = response.rows;
          this.total = response.total;
        } else if (Array.isArray(response.list)) {
          this.followupList = response.list;
          this.total = response.total;
        } else {
          this.followupList = [];
          this.total = 0;
        }
      }
      if (!Array.isArray(this.followupList)) {
        this.followupList = [];
      }
    },
    // æå–已有随访的案例ID
    extractExistingCaseIds() {
      this.existingFollowupCases.clear();
      this.followupList.forEach(followup => {
        if (followup.infoid) {
          this.existingFollowupCases.add(followup.infoid);
        }
      });
    },
    // æœç´¢æŒ‰é’®æ“ä½œ
    handleQuery() {
      this.queryParams.pageNum = 1;
      this.getList();
    },
    // é‡ç½®æŒ‰é’®æ“ä½œ
    resetQuery() {
      this.$refs.queryForm.resetFields();
      this.queryParams.pageNum = 1;
      this.getList();
    },
    // å¤šé€‰æ¡†é€‰ä¸­æ•°æ®
    handleSelectionChange(selection) {
      this.ids = selection.map(item => item.id);
      this.single = selection.length !== 1;
      this.multiple = !selection.length;
    },
    // æŸ¥çœ‹è¯¦æƒ…
    async handleView(row) {
      this.$router.push({
        path: "/follow/followupVisitinfo",
        query: { id: row.id, infoid: row.infoid }
      });
    },
    // æ–°å¢žæŒ‰é’®æ“ä½œ
    handleCreate() {
      this.reset();
      this.open = true;
      this.title = "新增受者随访";
    },
    // ä¿®æ”¹æŒ‰é’®æ“ä½œ
    async handleUpdate(row) {
      const id = row.id || this.ids[0];
      if (!id) {
        this.$message.warning("请先选择要操作的数据");
        return;
      }
      try {
        this.loading = true;
        const response = await getFollowup(id);
        if (response.code === 200) {
          this.form = response.data;
          this.open = true;
          this.title = "修改受者随访";
          // å¦‚果是修改,尝试加载案例信息
          if (this.form.infoid) {
            this.loadSelectedCaseInfo(this.form.infoid);
          }
        } else {
          this.$message.error("获取数据失败:" + response.msg);
        }
      } catch (error) {
        console.error("获取随访详情失败:", error);
        this.$message.error("获取数据失败");
      } finally {
        this.loading = false;
      }
    },
    // åŠ è½½é€‰ä¸­çš„æ¡ˆä¾‹ä¿¡æ¯
    async loadSelectedCaseInfo(infoid) {
      try {
        const response = await listDonatebaseinfo({
          pageNum: 1,
          pageSize: 1,
          id: infoid
        });
        if (
          response.code === 200 &&
          response.data &&
          response.data.length > 0
        ) {
          this.selectedCase = response.data[0];
        }
      } catch (error) {
        console.error("加载案例信息失败:", error);
      }
    },
    // åˆ é™¤æŒ‰é’®æ“ä½œ
    async handleDelete(row) {
      const ids = row.id ? [row.id] : this.ids;
      if (ids.length === 0) {
        this.$message.warning("请先选择要删除的数据");
        return;
      }
      try {
        await this.$confirm("是否确认删除选中的数据项?", "警告", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
        });
        const response = await delFollowup(ids);
        if (response.code === 200) {
          this.$message.success("删除成功");
          this.getList();
        } else {
          this.$message.error("删除失败:" + response.msg);
        }
      } catch (error) {
        if (error !== "cancel") {
          console.error("删除失败:", error);
        }
      }
    },
    // å¯¼å‡ºæŒ‰é’®æ“ä½œ
    async handleExport() {
      try {
        await this.$confirm("是否确认导出所有随访数据?", "警告", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
        });
        this.exportLoading = true;
        const exportParams = this.buildRequestParams();
        const response = await exportFollowup(exportParams);
        if (response.code === 200) {
          this.download(response.msg || "随访数据.xlsx");
        } else {
          this.$message.error("导出失败:" + response.msg);
        }
      } catch (error) {
        if (error !== "cancel") {
          console.error("导出失败:", error);
          this.$message.error("导出失败");
        }
      } finally {
        this.exportLoading = false;
      }
    },
    // æ–‡ä»¶ä¸‹è½½å¤„理
    download(fileName) {
      // è¿™é‡Œå®žçŽ°æ–‡ä»¶ä¸‹è½½é€»è¾‘
      console.log("下载文件:", fileName);
      // æ ¹æ®æ‚¨çš„项目实际文件下载方式实现
    },
    // è¡¨å•重置
    reset() {
      this.form = {
        id: undefined,
        infoid: undefined,
        organid: undefined,
        recipientname: "",
        recipientphone: "",
        recipientdescribe: "",
        hospitalname: "",
        hospitaldept: "",
        hospitalno: "",
        doctorname: "",
        doctorphone: "",
        doctordescribe: "",
        donateresult: "",
        followuptime: undefined,
        followupno: "",
        followupdescribe: "",
        seqno: 1,
        remark: ""
      };
      this.selectedCase = null;
      this.selectedCaseRow = null;
      this.resetForm("form");
    },
    // å–消按钮
    cancel() {
      this.open = false;
      this.reset();
    },
    // æäº¤è¡¨å•
    submitForm() {
      this.$refs["form"].validate(async valid => {
        if (valid) {
          let response;
          if (this.form.id) {
            // ä¿®æ”¹
            response = await updateFollowup(this.form);
          } else {
            // æ–°å¢ž
            response = await addFollowup(this.form);
          }
          if (response.code === 200) {
            this.$message.success("操作成功");
            this.open = false;
            this.getList();
          } else {
            this.$message.error(response.msg || "操作失败");
          }
        }
      });
    },
    // æ‰“开选择案例对话框
    openCaseDialog() {
      this.selectCaseOpen = true;
      this.caseQueryParams.pageNum = 1;
      this.resetCaseSearch();
      this.searchCaseList();
    },
    // æœç´¢æ¡ˆä¾‹åˆ—表
    async searchCaseList() {
      this.caseLoading = true;
      try {
        const params = {
          pageNum: this.caseQueryParams.pageNum,
          pageSize: this.caseQueryParams.pageSize
        };
        if (this.caseQueryParams.name) {
          params.name = this.caseQueryParams.name;
        }
        if (this.caseQueryParams.treatmenthospitalname) {
          params.treatmenthospitalname = this.caseQueryParams.treatmenthospitalname;
        }
        if (this.caseQueryParams.starttime) {
          params.starttime = this.caseQueryParams.starttime;
        }
        if (this.caseQueryParams.endtime) {
          params.endtime = this.caseQueryParams.endtime;
        }
        const response = await listDonatebaseinfo(params);
        if (response.code === 200) {
          this.availableCaseList = response.data || [];
          this.caseTotal = response.total || this.availableCaseList.length;
        } else {
          this.$message.error("获取案例列表失败");
          this.availableCaseList = [];
          this.caseTotal = 0;
        }
      } catch (error) {
        console.error("搜索案例失败:", error);
        this.$message.error("获取案例列表失败");
        this.availableCaseList = [];
        this.caseTotal = 0;
      } finally {
        this.caseLoading = false;
      }
    },
    // é‡ç½®æ¡ˆä¾‹æœç´¢
    resetCaseSearch() {
      this.caseQueryParams = {
        pageNum: 1,
        pageSize: 10,
        name: undefined,
        treatmenthospitalname: undefined,
        starttime: undefined,
        endtime: undefined
      };
      this.caseSelectTime = [];
      this.handleCaseTimeSelect();
    },
    // å¤„理案例时间选择
    handleCaseTimeSelect(timeRange) {
      if (!timeRange) {
        this.caseQueryParams.starttime = undefined;
        this.caseQueryParams.endtime = undefined;
        return;
      }
      const [start, end] = timeRange;
      this.caseQueryParams.starttime = `${start} 00:00:00`;
      const monthNum = Number(end.slice(5, 7));
      const nextMonth = monthNum < 9 ? `0${monthNum + 1}` : monthNum + 1;
      this.caseQueryParams.endtime = `${end.slice(
        0,
        5
      )}${nextMonth}-01 00:00:00`;
    },
    // æ£€æŸ¥æ¡ˆä¾‹æ˜¯å¦å·²æœ‰éšè®¿è®°å½•
    hasFollowup(row) {
      return this.existingFollowupCases.has(row.id);
    },
    // æ¡ˆä¾‹è¡Œç‚¹å‡»äº‹ä»¶
    handleCaseRowClick(row) {
      this.selectedCaseRow = row;
    },
    // é€‰æ‹©æ¡ˆä¾‹
    selectCase(row) {
      this.selectedCaseRow = row;
    },
    // ç¡®è®¤é€‰æ‹©æ¡ˆä¾‹
    confirmCaseSelection() {
      if (this.selectedCaseRow) {
        this.selectedCase = this.selectedCaseRow;
        this.form.infoid = this.selectedCaseRow.id;
        this.form.organid = this.selectedCaseRow.organid;
        this.selectCaseOpen = false;
        // å¦‚果选择案例成功,自动填充一些默认值
        this.form.seqno = this.calculateNextSeqNo();
        this.form.followupno = this.$store.state.user.name || "";
      } else {
        this.$message.warning("请先选择一个案例");
      }
    },
    // è®¡ç®—下一个随访序号
    calculateNextSeqNo() {
      if (this.selectedCase) {
        const caseFollowups = this.followupList.filter(
          followup => followup.infoid === this.selectedCase.id
        );
        if (caseFollowups.length === 0) {
          return 1;
        }
        const maxSeqNo = Math.max(
          ...caseFollowups.map(item => Number(item.seqno) || 1)
        );
        return maxSeqNo + 1;
      }
      return 1;
    },
    // æ—¶é—´æ ¼å¼åŒ–
    parseTime(time, pattern) {
      if (!time) return "";
      const date = new Date(time);
      if (pattern) {
        if (pattern === "{y}-{m}-{d}") {
          return `${date.getFullYear()}-${(date.getMonth() + 1)
            .toString()
            .padStart(2, "0")}-${date
            .getDate()
            .toString()
            .padStart(2, "0")}`;
        }
      }
      return `${date.getFullYear()}-${(date.getMonth() + 1)
        .toString()
        .padStart(2, "0")}-${date
        .getDate()
        .toString()
        .padStart(2, "0")} ${date
        .getHours()
        .toString()
        .padStart(2, "0")}:${date
        .getMinutes()
        .toString()
        .padStart(2, "0")}:${date
        .getSeconds()
        .toString()
        .padStart(2, "0")}`;
    }
  }
};
</script>
<style scoped>
.followup-list {
  padding: 20px;
}
.search-card {
  margin-bottom: 20px;
}
.tool-card {
  margin-bottom: 20px;
}
.fixed-width .el-button {
  margin: 0 5px;
}
.case-select-container {
  max-height: 600px;
  overflow-y: auto;
}
.dialog-footer {
  text-align: right;
}
/* é¼ æ ‡æ‚¬åœè¡Œæ ·å¼ */
.el-table__row:hover {
  cursor: pointer;
  background-color: #f5f7fa;
}
</style>
src/views/business/followupVisit/info.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,743 @@
<template>
  <div class="followup-detail">
    <!-- æ¡ˆä¾‹åŸºæœ¬ä¿¡æ¯ç»„ä»¶ -->
    <case-basic-info
      :case-id="caseId"
      :show-attachment="true"
    />
    <!-- éšè®¿è®°å½•管理 -->
    <el-card>
      <div slot="header" class="clearfix">
        <span>随访记录管理</span>
        <el-button style="float: right; padding: 3px 0" type="text" @click="goBack">返回列表</el-button>
      </div>
      <!-- æ“ä½œæŒ‰é’®åŒºåŸŸ -->
      <div class="operation-bar">
        <el-button
          type="primary"
          icon="el-icon-plus"
          @click="handleAddFollowup"
          v-hasPermi="['system:followup:add']"
        >
          æ–°å¢žéšè®¿
        </el-button>
        <el-button
          type="danger"
          icon="el-icon-delete"
          :disabled="!selectedFollowup"
          @click="handleDeleteFollowup"
          v-hasPermi="['system:followup:remove']"
        >
          åˆ é™¤é€‰ä¸­
        </el-button>
        <el-button
          type="warning"
          icon="el-icon-refresh"
          @click="getFollowupList"
        >
          åˆ·æ–°åˆ—表
        </el-button>
      </div>
      <!-- éšè®¿è®°å½•列表 -->
      <el-table
        v-loading="loading"
        :data="followupList"
        highlight-current-row
        @row-click="handleRowClick"
        style="width: 100%; margin-top: 20px;"
        :default-sort="{prop: 'followuptime', order: 'descending'}"
      >
        <el-table-column
          label="随访序号"
          align="center"
          prop="seqno"
          width="120"
        >
          <template slot-scope="scope">
            <span>第{{ scope.row.seqno || 1 }}次</span>
          </template>
        </el-table-column>
        <el-table-column
          label="随访时间"
          align="center"
          prop="followuptime"
          sortable
        >
          <template slot-scope="scope">
            <span>{{ parseTime(scope.row.followuptime, "{y}-{m}-{d}") }}</span>
          </template>
        </el-table-column>
        <el-table-column
          label="器官受体者"
          align="center"
          prop="recipientname"
        />
        <el-table-column
          label="移植医院"
          align="center"
          prop="hospitalname"
          show-overflow-tooltip
        />
        <el-table-column
          label="随访医生"
          align="center"
          prop="doctorname"
        />
        <el-table-column
          label="捐献结果"
          align="center"
          prop="donateresult"
        >
          <template slot-scope="scope">
            <el-tag :type="resultTypeFilter(scope.row.donateresult)" size="small">
              {{ resultTextFilter(scope.row.donateresult) }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column
          label="随访者"
          align="center"
          prop="followupno"
        />
        <el-table-column
          label="创建时间"
          align="center"
          prop="createTime"
        >
          <template slot-scope="scope">
            <span>{{ parseTime(scope.row.createTime, "{y}-{m}-{d}") }}</span>
          </template>
        </el-table-column>
        <el-table-column
          label="操作"
          align="center"
          fixed="right"
        >
          <template slot-scope="scope">
            <el-button
              size="mini"
              type="text"
              icon="el-icon-delete"
              @click="handleDeleteSingle(scope.row)"
              v-hasPermi="['system:followup:remove']"
            >
              åˆ é™¤
            </el-button>
          </template>
        </el-table-column>
      </el-table>
      <!-- åˆ†é¡µç»„ä»¶ -->
      <pagination
        v-show="total > 0"
        :total="total"
        :page.sync="queryParams.pageNum"
        :limit.sync="queryParams.pageSize"
        @pagination="getFollowupList"
      />
    </el-card>
    <!-- ç¼–辑/新增区域 - å§‹ç»ˆæ˜¾ç¤º -->
    <el-card class="edit-area-card">
      <div slot="header" class="clearfix">
        <span>{{ editForm.id ? '编辑随访记录' : '新增随访记录' }}</span>
        <div style="float: right;">
          <el-button
            type="text"
            @click="handleReset"
            v-if="editForm.id"
          >
            é‡ç½®
          </el-button>
        </div>
      </div>
      <el-form
        ref="editFormRef"
        :model="editForm"
        :rules="editRules"
        label-width="120px"
      >
        <el-row>
          <el-col :span="12">
            <el-form-item label="随访序号" prop="seqno">
              <el-input-number
                v-model="editForm.seqno"
                :min="1"
                :max="20"
                placeholder="请输入随访序号"
                style="width: 200px"
              />
              <span style="margin-left: 10px; color: #999;">(第{{ editForm.seqno || 1 }}次随访)</span>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="随访时间" prop="followuptime">
              <el-date-picker
                v-model="editForm.followuptime"
                type="datetime"
                placeholder="选择随访时间"
                value-format="yyyy-MM-dd HH:mm:ss"
                style="width: 200px"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="器官受体者姓名" prop="recipientname">
              <el-input
                v-model="editForm.recipientname"
                placeholder="请输入器官受体者姓名"
                maxlength="50"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="受体电话" prop="recipientphone">
              <el-input
                v-model="editForm.recipientphone"
                placeholder="请输入器官受体者电话"
                maxlength="20"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="移植医院名称" prop="hospitalname">
              <el-input
                v-model="editForm.hospitalname"
                placeholder="请输入移植医院名称"
                maxlength="100"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="移植科室" prop="hospitaldept">
              <el-input
                v-model="editForm.hospitaldept"
                placeholder="请输入移植医院科室"
                maxlength="50"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="随访医生姓名" prop="doctorname">
              <el-input
                v-model="editForm.doctorname"
                placeholder="请输入接受随访医生姓名"
                maxlength="50"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="医生电话" prop="doctorphone">
              <el-input
                v-model="editForm.doctorphone"
                placeholder="请输入接受随访医生电话"
                maxlength="20"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="捐献结果" prop="donateresult">
              <el-select
                v-model="editForm.donateresult"
                placeholder="请选择捐献结果"
                style="width: 200px"
              >
                <el-option label="成功" value="1" />
                <el-option label="失败" value="0" />
                <el-option label="进行中" value="2" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="随访者" prop="followupno">
              <el-input
                v-model="editForm.followupno"
                placeholder="请输入随访者"
                maxlength="50"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-form-item label="随访描述" prop="followupdescribe">
          <el-input
            v-model="editForm.followupdescribe"
            type="textarea"
            placeholder="请输入随访描述"
            maxlength="1000"
            :rows="3"
            show-word-limit
          />
        </el-form-item>
        <el-form-item label="医生描述" prop="doctordescribe">
          <el-input
            v-model="editForm.doctordescribe"
            type="textarea"
            placeholder="请输入医生描述"
            maxlength="500"
            :rows="3"
            show-word-limit
          />
        </el-form-item>
        <el-form-item label="受体者描述" prop="recipientdescribe">
          <el-input
            v-model="editForm.recipientdescribe"
            type="textarea"
            placeholder="请输入器官受体者描述"
            maxlength="500"
            :rows="3"
            show-word-limit
          />
        </el-form-item>
        <el-form-item label="备注" prop="remark">
          <el-input
            v-model="editForm.remark"
            type="textarea"
            placeholder="请输入备注"
            maxlength="500"
            :rows="3"
            show-word-limit
          />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="submitEditForm">
            {{ editForm.id ? '保存修改' : '创建随访' }}
          </el-button>
          <el-button @click="resetEditForm">重置</el-button>
        </el-form-item>
      </el-form>
    </el-card>
  </div>
</template>
<script>
import {
  listFollowup,
  getFollowup,
  addFollowup,
  updateFollowup,
  delFollowup
} from "@/api/businessApi/followup";
import CaseBasicInfo from "@/components/CaseBasicInfo";
import Pagination from "@/components/Pagination";
export default {
  name: "FollowupDetail",
  components: {
    CaseBasicInfo,
    Pagination
  },
  data() {
    return {
      // æ¡ˆä¾‹ID
      caseId: null,
      // åŠ è½½çŠ¶æ€
      loading: false,
      // éšè®¿è®°å½•列表
      followupList: [],
      // æ€»æ¡æ•°
      total: 0,
      // æŸ¥è¯¢å‚æ•°
      queryParams: {
        pageNum: 1,
        pageSize: 10
      },
      // å½“前选中的随访记录
      selectedFollowup: null,
      // ç¼–辑表单
      editForm: {
        id: undefined,
        infoid: null,
        organid: undefined,
        recipientname: "",
        recipientphone: "",
        recipientdescribe: "",
        hospitalname: "",
        hospitaldept: "",
        hospitalno: "",
        doctorname: "",
        doctorphone: "",
        doctordescribe: "",
        donateresult: "",
        followuptime: undefined,
        followupno: "",
        followupdescribe: "",
        seqno: 1,
        remark: ""
      },
      // ç¼–辑表单校验规则
      editRules: {
        seqno: [
          { required: true, message: "随访序号不能为空", trigger: "blur" },
          { type: "number", min: 1, max: 20, message: "随访序号范围为1-20", trigger: "blur" }
        ],
        followuptime: [
          { required: true, message: "随访时间不能为空", trigger: "change" }
        ],
        recipientname: [
          { required: true, message: "器官受体者姓名不能为空", trigger: "blur" },
          { max: 50, message: "长度不能超过50个字符", trigger: "blur" }
        ],
        hospitalname: [
          { required: true, message: "移植医院名称不能为空", trigger: "blur" },
          { max: 100, message: "长度不能超过100个字符", trigger: "blur" }
        ],
        followupno: [
          { required: true, message: "随访者不能为空", trigger: "blur" },
          { max: 50, message: "长度不能超过50个字符", trigger: "blur" }
        ],
        donateresult: [
          { required: true, message: "捐献结果不能为空", trigger: "change" }
        ]
      }
    };
  },
  created() {
    this.caseId = this.$route.query.infoid;
    if (this.caseId) {
      this.getFollowupList();
    } else {
      this.$message.error("参数错误");
      this.goBack();
    }
  },
  methods: {
    // èŽ·å–å½“å‰æ¡ˆä¾‹ä¸‹çš„éšè®¿è®°å½•åˆ—è¡¨
    async getFollowupList() {
      this.loading = true;
      try {
        const params = {
          ...this.queryParams,
          infoid: this.caseId
        };
        const response = await listFollowup(params);
        if (response.code === 200) {
          this.handleResponseData(response);
          // å¦‚果有数据,默认选中第一条
          if (this.followupList.length > 0) {
            this.selectFirstRecord();
          } else {
            // æ²¡æœ‰æ•°æ®æ—¶ï¼Œè®¾ç½®æ–°å¢žçŠ¶æ€
            this.resetEditForm();
          }
        } else {
          this.$message.error("获取随访记录失败:" + (response.msg || "未知错误"));
          this.followupList = [];
          this.total = 0;
          this.resetEditForm();
        }
      } catch (error) {
        console.error("获取随访记录失败:", error);
        this.$message.error("获取数据失败");
        this.followupList = [];
        this.total = 0;
        this.resetEditForm();
      } finally {
        this.loading = false;
      }
    },
    // å¤„理接口响应数据
    handleResponseData(response) {
      if (response.data) {
        if (Array.isArray(response.data)) {
          this.followupList = response.data;
          this.total = response.data.length;
        } else if (response.data.rows) {
          this.followupList = response.data.rows;
          this.total = response.data.total;
        } else if (Array.isArray(response.data.list)) {
          this.followupList = response.data.list;
          this.total = response.data.total || response.data.list.length;
        } else {
          this.followupList = response.data;
          this.total = response.total || response.data.length;
        }
      } else {
        if (Array.isArray(response.rows)) {
          this.followupList = response.rows;
          this.total = response.total;
        } else if (Array.isArray(response.list)) {
          this.followupList = response.list;
          this.total = response.total;
        } else {
          this.followupList = [];
          this.total = 0;
        }
      }
    },
    // é€‰æ‹©ç¬¬ä¸€æ¡è®°å½•
    selectFirstRecord() {
      if (this.followupList.length > 0) {
        const firstRecord = this.followupList[0];
        this.selectedFollowup = firstRecord;
        this.loadFollowupData(firstRecord);
      }
    },
    // åŠ è½½éšè®¿æ•°æ®åˆ°ç¼–è¾‘è¡¨å•
    loadFollowupData(record) {
      this.editForm = { ...record };
      // ç¡®ä¿æ•°æ®ç±»åž‹æ­£ç¡®
      if (this.editForm.seqno) {
        this.editForm.seqno = Number(this.editForm.seqno);
      }
      // æ¸…空表单验证
      if (this.$refs.editFormRef) {
        this.$nextTick(() => {
          this.$refs.editFormRef.clearValidate();
        });
      }
    },
    // ç»“果类型过滤器
    resultTypeFilter(result) {
      const resultMap = {
        "1": "success",  // æˆåŠŸ
        "0": "danger",   // å¤±è´¥
        "2": "primary"  // è¿›è¡Œä¸­
      };
      return resultMap[result] || "info";
    },
    resultTextFilter(result) {
      const resultMap = {
        "1": "成功",
        "0": "失败",
        "2": "进行中"
      };
      return resultMap[result] || "未知";
    },
    // è¡Œç‚¹å‡»äº‹ä»¶
    handleRowClick(row) {
      this.selectedFollowup = row;
      this.loadFollowupData(row);
    },
    // æ–°å¢žéšè®¿
    handleAddFollowup() {
      this.resetEditForm();
      this.selectedFollowup = null;
    },
    // è®¡ç®—下一个随访序号
    calculateNextSeqNo() {
      if (this.followupList.length === 0) {
        return 1;
      }
      const maxSeqNo = Math.max(...this.followupList.map(item => Number(item.seqno) || 1));
      return maxSeqNo + 1;
    },
    // æäº¤ç¼–辑表单
    submitEditForm() {
      this.$refs.editFormRef.validate(async (valid) => {
        if (valid) {
          try {
            // ç¡®ä¿infoid正确
            this.editForm.infoid = this.caseId;
            let response;
            if (this.editForm.id) {
              // ä¿®æ”¹
              response = await updateFollowup(this.editForm);
            } else {
              // æ–°å¢ž
              response = await addFollowup(this.editForm);
            }
            if (response.code === 200) {
              this.$message.success(this.editForm.id ? "修改成功" : "新增成功");
              this.getFollowupList();
              // æ–°å¢žæˆåŠŸåŽï¼Œæ¸…ç©ºè¡¨å•
              if (!this.editForm.id) {
                this.resetEditForm();
              }
            } else {
              this.$message.error(response.msg || "操作失败");
            }
          } catch (error) {
            console.error("操作失败:", error);
            this.$message.error("操作失败");
          }
        }
      });
    },
    // é‡ç½®ç¼–辑表单
    resetEditForm() {
      this.editForm = {
        id: undefined,
        infoid: this.caseId,
        organid: undefined,
        recipientname: "",
        recipientphone: "",
        recipientdescribe: "",
        hospitalname: "",
        hospitaldept: "",
        hospitalno: "",
        doctorname: "",
        doctorphone: "",
        doctordescribe: "",
        donateresult: "",
        followuptime: undefined,
        followupno: "",
        followupdescribe: "",
        seqno: this.calculateNextSeqNo(),
        remark: ""
      };
      if (this.$refs.editFormRef) {
        this.$refs.editFormRef.clearValidate();
      }
    },
    // é‡ç½®
    handleReset() {
      if (this.selectedFollowup) {
        this.loadFollowupData(this.selectedFollowup);
      } else {
        this.resetEditForm();
      }
    },
    // åˆ é™¤é€‰ä¸­éšè®¿
    async handleDeleteFollowup() {
      if (!this.selectedFollowup) {
        this.$message.warning("请先选择要删除的随访记录");
        return;
      }
      await this.deleteFollowupRecord(this.selectedFollowup.id);
    },
    // åˆ é™¤å•条随访
    async handleDeleteSingle(row, event) {
      event.stopPropagation(); // é˜»æ­¢äº‹ä»¶å†’泡
      await this.deleteFollowupRecord(row.id);
    },
    // åˆ é™¤éšè®¿è®°å½•
    async deleteFollowupRecord(id) {
      try {
        await this.$confirm('确认删除该随访记录吗?', "警告", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
        });
        const response = await delFollowup([id]);
        if (response.code === 200) {
          this.$message.success("删除成功");
          // å¦‚果删除的是当前选中的记录
          if (this.selectedFollowup && this.selectedFollowup.id === id) {
            this.selectedFollowup = null;
            this.resetEditForm();
          }
          this.getFollowupList();
        } else {
          this.$message.error("删除失败:" + response.msg);
        }
      } catch (error) {
        if (error !== "cancel") {
          console.error("删除失败:", error);
        }
      }
    },
    // è¿”回列表页
    goBack() {
      this.$router.go(-1);
    },
    // æ—¶é—´æ ¼å¼åŒ–
    parseTime(time, pattern) {
      if (!time) return "";
      const date = new Date(time);
      if (pattern) {
        if (pattern === "{y}-{m}-{d}") {
          return `${date.getFullYear()}-${(date.getMonth() + 1)
            .toString()
            .padStart(2, "0")}-${date
            .getDate()
            .toString()
            .padStart(2, "0")}`;
        }
      }
      return `${date.getFullYear()}-${(date.getMonth() + 1)
        .toString()
        .padStart(2, "0")}-${date
        .getDate()
        .toString()
        .padStart(2, "0")} ${date
        .getHours()
        .toString()
        .padStart(2, "0")}:${date
        .getMinutes()
        .toString()
        .padStart(2, "0")}:${date
        .getSeconds()
        .toString()
        .padStart(2, "0")}`;
    }
  }
};
</script>
<style scoped>
.followup-detail {
  padding: 20px;
}
.operation-bar {
  margin-bottom: 20px;
  display: flex;
  gap: 10px;
  align-items: center;
}
.edit-area-card {
  margin-top: 20px;
  animation: fadeIn 0.5s;
}
@keyframes fadeIn {
  from {
    opacity: 0;
    transform: translateY(-20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
/* è¡¨æ ¼é€‰ä¸­è¡Œæ ·å¼ */
.el-table__row.current-row {
  background-color: #f0f9ff !important;
}
/* é¼ æ ‡æ‚¬åœè¡Œæ ·å¼ */
.el-table__row:hover {
  cursor: pointer;
  background-color: #f5f7fa;
}
</style>
src/views/project/components/orgselect/index.vue
@@ -154,7 +154,6 @@
          };
          this.dataList.unshift(all);
        }
        console.log(this.dataList,'this.dataList');
        this.tempList = this.dataList.map(item => item);
        this.focusEvents.loaded = true;