WXL
2026-01-28 bcb9976e7680ce67fadb6fec7ab5fca36552cdbc
青岛维护
已修改11个文件
2465 ■■■■■ 文件已修改
src/api/businessApi/assess.js 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/businessApi/decide.js 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/businessApi/maintain.js 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/assess/assessInfo.vue 789 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/assess/components/OrganAssessmentForm.vue 554 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/assess/index.vue 42 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/decide/DecideInfo.vue 295 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/decide/index.vue 320 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/ethicalReview/ethicalReviewInfo.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/transfer/TransportEdit.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/project/DonationProcess/index.vue 347 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/businessApi/assess.js
@@ -0,0 +1,44 @@
import request from '@/utils/request'
// 上报案例新增
export function assessAdd(data) {
  return request({
    url: '/project/assessbaseinforeport/add',
    method: 'post',
    data: data
  })
}
// 案例列表及详情
export function evaluateBaseInfolist(data) {
  return request({
    url: '/project/medicalevaluation/evaluateBaseInfolist',
    method: 'post',
    data: data
  })
}
// 上报案例列表
export function assessList(data) {
  return request({
    url: '/project/assessbaseinforeport/list',
    method: 'post',
    data: data
  })
}
// 案例详情
export function assessInfo(id) {
  return request({
    url: '/project/assessbaseinforeport/getInfo/' + id,
    method: 'get'
  })
}
// 删除
export function assessDel(id) {
  return request({
    url: '/project/assessbaseinforeport/remove/' + id,
    method: 'get'
  })
}
src/api/businessApi/decide.js
@@ -0,0 +1,25 @@
import request from '@/utils/request'
// 案例列表及详情
export function queryDathInfoBaseInfo(data) {
  return request({
    url: '/project/deathinfo/queryDathInfoBaseInfo',
    method: 'post',
    data: data
  })
}
// 死亡信息修改
export function deathinfoedit(data) {
  return request({
    url: '/project/deathinfo/edit',
    method: 'post',
    data: data
  })
}
// 死亡信息详情
export function deathinfoInfo(id) {
  return request({
    url: '/project/deathinfo/getInfo/' + id,
    method: 'get'
  })
}
src/api/businessApi/maintain.js
@@ -0,0 +1,45 @@
import request from '@/utils/request'
// 供者维护新增
export function maintainAdd(data) {
  return request({
    url: '/project/donatemaintenance/add',
    method: 'post',
    data: data
  })
}
// 供者维护修改
export function maintainedit(data) {
  return request({
    url: '/project/donatemaintenance/edit',
    method: 'post',
    data: data
  })
}
// 供者维护列表
export function maintainList(data) {
  return request({
    url: '/project/donatemaintenance/maintenanceBaseInfoList',
    method: 'post',
    data: data
  })
}
// 案例详情
export function maintainInfo(id) {
  return request({
    url: '/project/donatemaintenance/getInfo/' + id,
    method: 'get'
  })
}
// 删除
export function maintainDel(id) {
  return request({
    url: '/project/donatemaintenance/remove/' + id,
    method: 'get'
  })
}
src/views/business/assess/assessInfo.vue
@@ -76,13 +76,131 @@
          当前角色:{{ currentDepartment }}评估人员
        </span>
      </div>
      <el-row>
        <el-form-item label-width="100px" label="评估器官">
          <el-checkbox-group v-model="organdecision">
            <el-checkbox
              v-for="item in organselection"
              :key="item"
              :label="item"
              >{{ item }}
            </el-checkbox>
          </el-checkbox-group>
          <el-input
            v-if="organdecision.includes('其他')"
            v-model="assessmentData.organdecisionOther"
            placeholder="请输入其他捐献决定的具体内容"
            style="margin-top: 10px; width: 300px;"
          ></el-input>
        </el-form-item>
      </el-row>
      <el-table
        :data="organAssessmentList"
        v-loading="assessmentLoading"
        style="width: 100%"
        :row-class-name="getRowClassName"
        :expand-row-keys="expandedRowKeys"
        @expand-change="handleExpandChange"
        row-key="organType"
      >
        <el-table-column type="expand" width="60">
          <template slot-scope="scope">
            <div class="organ-expand-content" v-if="scope.row.expanded">
              <el-tabs
                v-model="scope.row.activeAssessmentTab"
                type="card"
                class="organ-detail-tabs"
              >
                <!-- 动态生成评估Tab -->
                <el-tab-pane
                  v-for="(assessment, index) in scope.row.assessments"
                  :key="index"
                  :label="`第${index + 1}次评估`"
                  :name="`assessment_${index}`"
                >
                  <organ-assessment-form
                    :organ-data="scope.row"
                    :assessment-data="assessment"
                    :assessment-index="index"
                    :readonly="!canAssessOrgan(scope.row)"
                    @save="handleSaveOrganAssessment"
                    @add-assessment="handleAddAssessment"
                  />
                </el-tab-pane>
                <!-- 添加评估按钮 -->
                <el-tab-pane name="add" v-if="canAssessOrgan(scope.row)">
                  <template slot="label">
                    <el-button
                      type="text"
                      icon="el-icon-plus"
                      @click.stop="handleAddNewAssessment(scope.row)"
                      size="mini"
                    >
                      新增评估
                    </el-button>
                  </template>
                  <div class="add-assessment-prompt">
                    <el-empty description="点击上方按钮添加新的评估"></el-empty>
                  </div>
                </el-tab-pane>
                <!-- 评估汇总Tab -->
                <el-tab-pane label="评估汇总" name="summary">
                  <div class="assessment-summary">
                    <el-descriptions title="评估结果汇总" :column="2" border>
                      <el-descriptions-item label="器官类型">{{
                        scope.row.organName
                      }}</el-descriptions-item>
                      <el-descriptions-item label="评估科室">{{
                        scope.row.department
                      }}</el-descriptions-item>
                      <el-descriptions-item label="评估次数" :span="2">
                        <el-tag type="info"
                          >{{ scope.row.assessments.length }}次</el-tag
                        >
                      </el-descriptions-item>
                      <el-descriptions-item label="最新评估时间" :span="2">
                        {{ getLatestAssessmentTime(scope.row) || "-" }}
                      </el-descriptions-item>
                    </el-descriptions>
                    <!-- 附件汇总 -->
                    <el-card header="所有评估附件" style="margin-top: 20px;">
                      <el-table
                        :data="getAllAttachments(scope.row)"
                        size="small"
                        empty-text="暂无附件"
                      >
                        <el-table-column label="附件名称" prop="fileName" />
                        <el-table-column label="评估阶段" width="120">
                          <template slot-scope="{ row }">
                            第{{ row.assessmentIndex + 1 }}次评估
                          </template>
                        </el-table-column>
                        <el-table-column
                          label="上传时间"
                          prop="uploadTime"
                          width="180"
                        />
                        <el-table-column label="操作" width="120">
                          <template slot-scope="{ row }">
                            <el-button
                              type="text"
                              @click="handlePreviewAttachment(row)"
                              >预览</el-button
                            >
                          </template>
                        </el-table-column>
                      </el-table>
                    </el-card>
                  </div>
                </el-tab-pane>
              </el-tabs>
            </div>
          </template>
        </el-table-column>
        <el-table-column
          label="器官类型"
          align="center"
@@ -96,54 +214,51 @@
            />
          </template>
        </el-table-column>
        <el-table-column
          label="评估科室"
          align="center"
          prop="department"
          width="120"
        />
        <el-table-column
          label="评估人员"
          align="center"
          prop="assessor"
        />
        <!-- 新增:第一次评估状态 -->
        <el-table-column label="第一次评估" align="center" >
        <el-table-column label="评估人员" align="center" prop="assessor" />
        <!-- 动态显示评估状态列 -->
        <el-table-column
          v-for="(assessment, index) in getMaxAssessmentCount()"
          :key="index"
          :label="`第${index + 1}次评估`"
          align="center"
          width="120"
        >
          <template slot-scope="scope">
            <el-tag
              :type="getAssessmentTagType(scope.row.firstAssessment.status)"
              v-if="scope.row.assessments[index]"
              :type="getAssessmentTagType(scope.row.assessments[index].status)"
              size="small"
            >
              {{ getAssessmentStatusText(scope.row.firstAssessment.status) }}
              {{ getAssessmentStatusText(scope.row.assessments[index].status) }}
            </el-tag>
            <el-tag v-else type="info" size="small">未评估</el-tag>
          </template>
        </el-table-column>
        <el-table-column label="整体状态" align="center" width="100">
          <template slot-scope="scope">
            <el-tag
              :type="scope.row.assessmentStatus === '1' ? 'success' : 'primary'"
              size="small"
            >
              {{ scope.row.assessmentStatus === "1" ? "已完成" : "评估中" }}
            </el-tag>
          </template>
        </el-table-column>
        <!-- 新增:第二次评估状态 -->
        <el-table-column label="第二次评估" align="center" >
          <template slot-scope="scope">
            <el-tag
              :type="getAssessmentTagType(scope.row.secondAssessment.status)"
              size="small"
            >
              {{ getAssessmentStatusText(scope.row.secondAssessment.status) }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="整体状态" align="center" >
          <template slot-scope="scope">
            <el-tag
              :type="scope.row.assessmentStatus === '1' ? 'success' : 'warning'"
              size="small"
            >
              {{ scope.row.assessmentStatus === "1" ? "已评估" : "待评估" }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column
          label="操作"
          align="center"
          width="180"
          width="150"
          class-name="small-padding fixed-width"
        >
          <template slot-scope="scope">
@@ -151,133 +266,35 @@
              v-if="canAssessOrgan(scope.row)"
              size="mini"
              type="text"
              @click="handleOrganAssess(scope.row)"
              @click="handleToggleExpand(scope.row)"
            >
              评估
              {{
                expandedRowKeys.includes(scope.row.organType) ? "收起" : "详情"
              }}
            </el-button>
            <el-button v-else size="mini" type="text" disabled
              >无权限</el-button
            >
            <el-button
              size="mini"
              type="text"
              @click="handleViewOrganDetail(scope.row)"
            >
              详情
            </el-button>
          </template>
        </el-table-column>
      </el-table>
      <!-- 器官评估详情 - 改为Tab页形式 -->
      <el-dialog
        :title="`${currentOrgan.organName}评估详情`"
        :visible.sync="organDetailVisible"
        width="90%"
        top="5vh"
        class="organ-detail-dialog"
      >
        <el-tabs v-model="activeAssessmentTab" type="card">
          <!-- 第一次评估Tab -->
          <el-tab-pane label="第一次评估" name="first">
            <organ-assessment-form
              :organ-data="currentOrgan"
              :assessment-data="currentOrgan.firstAssessment"
              assessment-type="first"
              :readonly="!canAssessOrgan(currentOrgan)"
              @save="handleSaveOrganAssessment"
            />
          </el-tab-pane>
          <!-- 第二次评估Tab -->
          <el-tab-pane label="第二次评估" name="second">
            <organ-assessment-form
              :organ-data="currentOrgan"
              :assessment-data="currentOrgan.secondAssessment"
              assessment-type="second"
              :readonly="!canAssessOrgan(currentOrgan)"
              @save="handleSaveOrganAssessment"
            />
          </el-tab-pane>
          <!-- 评估汇总Tab -->
          <el-tab-pane label="评估汇总" name="summary">
            <div class="assessment-summary">
              <el-descriptions title="评估结果汇总" :column="2" border>
                <el-descriptions-item label="器官类型">
                  {{ currentOrgan.organName }}
                </el-descriptions-item>
                <el-descriptions-item label="评估科室">
                  {{ currentOrgan.department }}
                </el-descriptions-item>
                <el-descriptions-item label="第一次评估状态">
                  <el-tag :type="getAssessmentTagType(currentOrgan.firstAssessment.status)">
                    {{ getAssessmentStatusText(currentOrgan.firstAssessment.status) }}
                  </el-tag>
                </el-descriptions-item>
                <el-descriptions-item label="第二次评估状态">
                  <el-tag :type="getAssessmentTagType(currentOrgan.secondAssessment.status)">
                    {{ getAssessmentStatusText(currentOrgan.secondAssessment.status) }}
                  </el-tag>
                </el-descriptions-item>
                <el-descriptions-item label="第一次评估时间" :span="2">
                  {{ currentOrgan.firstAssessment.assessmentTime || '-' }}
                </el-descriptions-item>
                <el-descriptions-item label="第二次评估时间" :span="2">
                  {{ currentOrgan.secondAssessment.assessmentTime || '-' }}
                </el-descriptions-item>
              </el-descriptions>
              <!-- 附件汇总 -->
              <el-card header="评估附件" style="margin-top: 20px;">
                <el-table :data="getAllAttachments(currentOrgan)" size="small">
                  <el-table-column label="附件名称" prop="fileName" />
                  <el-table-column label="评估阶段" >
                    <template slot-scope="{row}">
                      {{ row.assessmentType === 'first' ? '第一次评估' : '第二次评估' }}
                    </template>
                  </el-table-column>
                  <el-table-column label="上传时间" prop="uploadTime" width="180" />
                  <el-table-column label="操作" width="120">
                    <template slot-scope="{row}">
                      <el-button type="text" @click="handlePreviewAttachment(row)">预览</el-button>
                    </template>
                  </el-table-column>
                </el-table>
              </el-card>
            </div>
          </el-tab-pane>
        </el-tabs>
        <div slot="footer" class="dialog-footer">
          <el-button @click="organDetailVisible = false">关闭</el-button>
          <el-button
            v-if="canAssessOrgan(currentOrgan)"
            type="primary"
            @click="handleSaveAllAssessments"
          >
            保存所有评估
          </el-button>
        </div>
      </el-dialog>
    </el-card>
    <!-- 附件预览弹窗 -->
    <!-- <attachment-preview
      :visible="attachmentVisible"
      :attachment-list="attachmentList"
      @close="attachmentVisible = false"
    /> -->
    <!-- 文件预览弹窗 -->
    <FilePreviewDialog
      :visible="attachmentVisible"
      :file="attachmentList"
      :file="currentPreviewFile"
      @close="attachmentVisible = false"
    />
  </div>
</template>
<script>
import { getAssessment, updateOrganAssessment, completeAssessment } from "./mockAssessmentApi";
import {
  getAssessment,
  updateOrganAssessment,
  completeAssessment
} from "./mockAssessmentApi";
import FilePreviewDialog from "@/components/FilePreviewDialog";
import OrganAssessmentForm from "./components/OrganAssessmentForm.vue";
@@ -291,27 +308,19 @@
      organAssessmentList: [],
      attachmentList: [],
      assessmentLoading: false,
      // 器官详情相关数据
      organDetailVisible: false,
      currentOrgan: {
        organType: '',
        organName: '',
        department: '',
        firstAssessment: this.getDefaultAssessment(),
        secondAssessment: this.getDefaultAssessment()
      },
      activeAssessmentTab: 'first',
      organdecision: [],
      // 展开行相关
      expandedRowKeys: [],
      currentPreviewFile: null,
      attachmentVisible: false,
      currentUser: {
        id: "001",
        name: "张医生",
        department: "心脏外科",
        role: "department"
        department: "协调员",
        role: "coordinator"
      },
      attachmentVisible: false,
      //department:心脏、coordinator:协调员
      // 字典选项
      genderOptions: [
        { value: "0", label: "男" },
@@ -336,6 +345,19 @@
        { value: "intestine", label: "肠道" },
        { value: "cornea", label: "角膜" },
        { value: "skin", label: "皮肤" }
      ],
      organselection: [
        "肝脏",
        "双肾",
        "左肾",
        "右肾",
        "心脏",
        "肺脏",
        "胰腺",
        "小肠",
        "双眼组织",
        "遗体",
        "其他"
      ]
    };
  },
@@ -347,9 +369,13 @@
      return this.currentUser.department;
    },
    allOrgansAssessed() {
      return this.organAssessmentList.every(organ =>
        organ.firstAssessment.status === 'assessed' &&
        organ.secondAssessment.status === 'assessed'
      return this.organAssessmentList.every(
        organ =>
          organ.assessments &&
          organ.assessments.length > 0 &&
          organ.assessments.every(
            assessment => assessment.status === "assessed"
          )
      );
    }
  },
@@ -361,11 +387,11 @@
    // 获取默认评估数据结构
    getDefaultAssessment() {
      return {
        status: 'pending', // pending, assessing, assessed
        assessmentTime: '',
        assessor: '',
        functionStatus: '',
        assessmentOpinion: '',
        status: "pending",
        assessmentTime: "",
        assessor: "",
        functionStatus: "",
        assessmentOpinion: "",
        attachments: [],
        clinicalData: {},
        labResults: {}
@@ -379,7 +405,9 @@
        .then(response => {
          if (response.code === 200) {
            this.assessmentData = response.data.caseInfo;
            this.organAssessmentList = this.transformOrganData(response.data.organAssessments || []);
            this.organAssessmentList = this.transformOrganData(
              response.data.organAssessments || []
            );
          }
          this.assessmentLoading = false;
        })
@@ -389,21 +417,27 @@
        });
    },
    // 转换器官数据格式,支持两次评估
    // 转换器官数据格式,支持多次评估
    transformOrganData(organList) {
      return organList.map(organ => {
        const organName = this.getOrganName(organ.organType);
        // 确保有两次评估的数据结构
        if (!organ.firstAssessment) {
          organ.firstAssessment = this.getDefaultAssessment();
        // 转换为多次评估的数据结构
        const assessments = [];
        if (organ.firstAssessment) {
          assessments.push({ ...organ.firstAssessment, index: 0 });
        }
        if (!organ.secondAssessment) {
          organ.secondAssessment = this.getDefaultAssessment();
        if (organ.secondAssessment) {
          assessments.push({ ...organ.secondAssessment, index: 1 });
        }
        // 可以继续添加更多评估...
        // 设置器官名称
        // 设置器官名称和评估数据
        organ.organName = organName;
        organ.assessments = assessments;
        organ.activeAssessmentTab =
          assessments.length > 0 ? "assessment_0" : "summary";
        organ.expanded = false;
        // 计算整体评估状态
        organ.assessmentStatus = this.calculateOverallStatus(organ);
@@ -412,54 +446,199 @@
      });
    },
    // 计算最大评估次数(用于表头显示)
    getMaxAssessmentCount() {
      const maxCount = Math.max(
        ...this.organAssessmentList.map(organ =>
          organ.assessments ? organ.assessments.length : 0
        )
      );
      return Math.max(maxCount, 2); // 至少显示2列
    },
    // 计算整体评估状态
    calculateOverallStatus(organ) {
      const firstDone = organ.firstAssessment.status === 'assessed';
      const secondDone = organ.secondAssessment.status === 'assessed';
      if (!organ.assessments || organ.assessments.length === 0) return "0";
      if (firstDone && secondDone) return '1'; // 已完成
      if (firstDone || secondDone) return '2'; // 部分完成
      return '0'; // 未开始
      const allAssessed = organ.assessments.every(
        assessment => assessment.status === "assessed"
      );
      const someAssessed = organ.assessments.some(
        assessment => assessment.status === "assessed"
      );
      if (allAssessed) return "1";
      if (someAssessed) return "2";
      return "0";
    },
    // 切换展开行
    handleToggleExpand(row) {
      const key = row.organType;
      const index = this.expandedRowKeys.indexOf(key);
      if (index > -1) {
        this.expandedRowKeys.splice(index, 1);
        row.expanded = false;
      } else {
        this.expandedRowKeys = [key];
        this.organAssessmentList.forEach(item => {
          item.expanded = item.organType === key;
        });
      }
    },
    // 展开行变化
    handleExpandChange(row, expandedRows) {
      this.expandedRowKeys = expandedRows.map(item => item.organType);
      this.organAssessmentList.forEach(item => {
        item.expanded = this.expandedRowKeys.includes(item.organType);
      });
    },
    // 添加新评估
    handleAddNewAssessment(organ) {
      const newAssessment = {
        ...this.getDefaultAssessment(),
        index: organ.assessments.length
      };
      organ.assessments.push(newAssessment);
      organ.activeAssessmentTab = `assessment_${organ.assessments.length - 1}`;
      // 更新整体状态
      organ.assessmentStatus = this.calculateOverallStatus(organ);
      this.$message.success("已添加新的评估");
    },
    // 处理添加评估事件
    handleAddAssessment(data) {
      const { organData, currentIndex } = data;
      this.handleAddNewAssessment(organData);
    },
    // 保存评估
    handleSaveOrganAssessment(saveData) {
      const { organData, assessmentData, assessmentIndex } = saveData;
      const organToUpdate = {
        ...organData,
        assessments: organData.assessments.map((assessment, index) =>
          index === assessmentIndex
            ? {
                ...assessmentData,
                status: "assessed",
                assessmentTime: new Date().toISOString(),
                assessor: this.currentUser.name
              }
            : assessment
        )
      };
      // 更新整体状态
      organToUpdate.assessmentStatus = this.calculateOverallStatus(
        organToUpdate
      );
      updateOrganAssessment(organToUpdate)
        .then(response => {
          if (response.code === 200) {
            this.$message.success(`第${assessmentIndex + 1}次评估保存成功`);
            this.getAssessmentDetail();
            // 更新当前展开行的数据
            const index = this.organAssessmentList.findIndex(
              item => item.organType === organData.organType
            );
            if (index !== -1) {
              this.organAssessmentList.splice(index, 1, organToUpdate);
            }
          }
        })
        .catch(error => {
          console.error("保存评估失败:", error);
          this.$message.error("保存失败");
        });
    },
    // 获取最新评估时间
    getLatestAssessmentTime(organ) {
      if (!organ.assessments || organ.assessments.length === 0) return null;
      const assessed = organ.assessments.filter(a => a.assessmentTime);
      if (assessed.length === 0) return null;
      return assessed.sort(
        (a, b) => new Date(b.assessmentTime) - new Date(a.assessmentTime)
      )[0].assessmentTime;
    },
    // 获取所有附件
    getAllAttachments(organ) {
      const attachments = [];
      if (organ.assessments) {
        organ.assessments.forEach((assessment, index) => {
          if (assessment.attachments) {
            assessment.attachments.forEach(att => {
              attachments.push({
                ...att,
                assessmentIndex: index,
                assessmentNumber: index + 1
              });
            });
          }
        });
      }
      return attachments;
    },
    // 预览附件
    handlePreviewAttachment(attachment) {
      this.currentPreviewFile = {
        fileName: attachment.fileName,
        fileUrl: attachment.path || attachment.fileUrl,
        fileType: this.getFileType(attachment.fileName)
      };
      this.attachmentVisible = true;
    },
    // 获取文件类型
    getFileType(fileName) {
      if (!fileName) return "other";
      const extension = fileName
        .split(".")
        .pop()
        .toLowerCase();
      const imageTypes = ["jpg", "jpeg", "png", "gif", "bmp", "webp"];
      const pdfTypes = ["pdf"];
      const officeTypes = ["doc", "docx", "xls", "xlsx", "ppt", "pptx"];
      if (imageTypes.includes(extension)) return "image";
      if (pdfTypes.includes(extension)) return "pdf";
      if (officeTypes.includes(extension)) return "office";
      return "other";
    },
    // 获取评估状态标签类型
    getAssessmentTagType(status) {
      const typeMap = {
        'pending': 'info',
        'assessing': 'warning',
        'assessed': 'success'
        pending: "warning",
        assessing: "primary",
        assessed: "success"
      };
      return typeMap[status] || 'info';
      return typeMap[status] || "info";
    },
    // 获取评估状态文本
    getAssessmentStatusText(status) {
      const textMap = {
        'pending': '待评估',
        'assessing': '评估中',
        'assessed': '已评估'
      };
      return textMap[status] || '未知';
    },
    // 获取功能状态类型
    getFunctionStatusType(status) {
      const typeMap = {
        "1": "success", // 正常
        "2": "warning", // 轻度异常
        "3": "danger", // 重度异常
        "4": "info" // 无法评估
      };
      return typeMap[status] || "info";
    },
    // 获取功能状态文本
    getFunctionStatusText(status) {
      const textMap = {
        "1": "正常",
        "2": "轻度异常",
        "3": "重度异常",
        "4": "无法评估"
        pending: "待评估",
        assessing: "评估中",
        assessed: "已评估"
      };
      return textMap[status] || "未知";
    },
@@ -479,125 +658,6 @@
    // 获取行类名
    getRowClassName({ row }) {
      return this.canAssessOrgan(row) ? "assessable-row" : "non-assessable-row";
    },
    // 格式化时间
    formatTime(time) {
      if (!time) return '';
      return new Date(time).toLocaleString();
    },
    // 查看器官详情
    handleViewOrganDetail(organ) {
      this.currentOrgan = JSON.parse(JSON.stringify(organ));
      this.activeAssessmentTab = 'first';
      this.organDetailVisible = true;
    },
    // 器官评估
    handleOrganAssess(organ) {
      this.currentOrgan = JSON.parse(JSON.stringify(organ));
      this.activeAssessmentTab = 'first';
      this.organDetailVisible = true;
    },
    // 保存单个评估
    handleSaveOrganAssessment(assessmentData, assessmentType) {
      const organToUpdate = {
        ...this.currentOrgan,
        [assessmentType === 'first' ? 'firstAssessment' : 'secondAssessment']: {
          ...assessmentData,
          status: 'assessed',
          assessmentTime: new Date().toISOString(),
          assessor: this.currentUser.name
        }
      };
      // 更新整体状态
      organToUpdate.assessmentStatus = this.calculateOverallStatus(organToUpdate);
      updateOrganAssessment(organToUpdate)
        .then(response => {
          if (response.code === 200) {
            this.$message.success(`${assessmentType === 'first' ? '第一次' : '第二次'}评估保存成功`);
            this.getAssessmentDetail();
            // 自动切换到下一个未完成的评估或汇总页
            this.autoSwitchTab(assessmentType);
          }
        })
        .catch(error => {
          console.error("保存评估失败:", error);
          this.$message.error("保存失败");
        });
    },
    // 自动切换Tab页
    autoSwitchTab(currentType) {
      if (currentType === 'first' && this.currentOrgan.secondAssessment.status === 'pending') {
        this.activeAssessmentTab = 'second';
      } else if (currentType === 'second' ||
                (currentType === 'first' && this.currentOrgan.secondAssessment.status === 'assessed')) {
        this.activeAssessmentTab = 'summary';
      }
    },
    // 保存所有评估
    handleSaveAllAssessments() {
      this.$confirm("确认保存所有评估数据吗?", "确认保存", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      }).then(() => {
        const organToUpdate = JSON.parse(JSON.stringify(this.currentOrgan));
        // 更新整体状态
        organToUpdate.assessmentStatus = this.calculateOverallStatus(organToUpdate);
        updateOrganAssessment(organToUpdate)
          .then(response => {
            if (response.code === 200) {
              this.$message.success("所有评估数据保存成功");
              this.getAssessmentDetail();
              this.organDetailVisible = false;
            }
          })
          .catch(error => {
            console.error("保存评估失败:", error);
            this.$message.error("保存失败");
          });
      });
    },
    // 获取所有附件
    getAllAttachments(organ) {
      const attachments = [];
      if (organ.firstAssessment.attachments) {
        organ.firstAssessment.attachments.forEach(att => {
          attachments.push({
            ...att,
            assessmentType: 'first'
          });
        });
      }
      if (organ.secondAssessment.attachments) {
        organ.secondAssessment.attachments.forEach(att => {
          attachments.push({
            ...att,
            assessmentType: 'second'
          });
        });
      }
      return attachments;
    },
    // 预览附件
    handlePreviewAttachment(attachment) {
      // 实现附件预览逻辑
      console.log('预览附件:', attachment);
      this.$message.info('附件预览功能待实现');
    },
    // 状态过滤器
@@ -661,41 +721,36 @@
  margin-bottom: 20px;
}
.assessment-time {
  font-size: 12px;
  color: #909399;
  margin-top: 4px;
}
/* Tab页样式优化 */
.organ-detail-dialog ::v-deep .el-dialog__body {
/* 展开行样式 */
.organ-expand-content {
  padding: 20px;
  max-height: 70vh;
  overflow-y: auto;
  background: #fafafa;
  border-radius: 4px;
  margin: 10px 0;
}
.organ-detail-dialog ::v-deep .el-tabs__content {
  padding: 20px 0;
  min-height: 400px;
.organ-detail-tabs {
  background: white;
  border-radius: 4px;
  padding: 20px;
}
.add-assessment-prompt {
  text-align: center;
  padding: 40px 0;
}
.assessment-summary {
  padding: 10px;
}
.dialog-footer {
  text-align: right;
  padding-top: 20px;
  border-top: 1px solid #ebeef5;
}
/* 响应式设计 */
@media (max-width: 768px) {
  .organ-detail-dialog {
    width: 95% !important;
  .assessment-detail {
    padding: 10px;
  }
  .assessment-detail {
  .organ-expand-content {
    padding: 10px;
  }
}
@@ -708,16 +763,6 @@
  background-color: #fafafa;
}
::v-deep .el-descriptions__label {
  width: 120px;
  background-color: #f5f7fa;
  font-weight: bold;
}
.fixed-width .el-button {
  margin: 0 2px;
}
.jstitle {
  float: right;
  font-size: 18px !important;
@@ -726,21 +771,23 @@
  font-size: 12px;
}
/* Tab页激活状态样式 */
::v-deep .el-tabs__item.is-active {
  color: #409EFF;
/* 表格展开图标样式 */
::v-deep .el-table__expand-icon {
  cursor: pointer;
}
::v-deep .el-table__expanded-cell {
  padding: 0 !important;
}
/* 确保描述列表标签宽度一致 */
::v-deep .el-descriptions__label {
  width: 120px;
  background-color: #f5f7fa;
  font-weight: bold;
}
/* 评估表单样式 */
.assessment-form-section {
  margin-bottom: 20px;
}
.assessment-form-section h3 {
  margin-bottom: 15px;
  color: #303133;
  border-left: 4px solid #409EFF;
  padding-left: 10px;
.fixed-width .el-button {
  margin: 0 2px;
}
</style>
src/views/business/assess/components/OrganAssessmentForm.vue
@@ -1,8 +1,8 @@
<template>
  <div class="organ-assessment-form">
    <el-form :model="organData" label-width="120px">
    <el-form :model="assessmentData" label-width="120px">
      <el-form-item label="功能状态">
        <el-select v-model="organData.functionStatus" :disabled="readonly">
        <el-select v-model="assessmentData.functionStatus" :disabled="readonly">
          <el-option label="正常" value="1" />
          <el-option label="轻度异常" value="2" />
          <el-option label="重度异常" value="3" />
@@ -13,59 +13,110 @@
      <el-form-item label="评估意见">
        <el-input
          type="textarea"
          v-model="organData.assessmentOpinion"
          v-model="assessmentData.assessmentOpinion"
          :rows="4"
          :disabled="readonly"
          placeholder="请输入评估意见"
        />
      </el-form-item>
      <!-- 器官级别附件管理 -->
      <!-- 附件上传区域 -->
      <el-form-item label="相关附件">
        <div class="attachment-section">
          <el-upload
            v-if="!readonly"
            class="attachment-upload"
            action="/api/attachment/upload"
            :headers="uploadHeaders"
            :on-success="handleUploadSuccess"
            :on-error="handleUploadError"
            :before-upload="beforeUpload"
            :show-file-list="false"
            :multiple="true"
          >
            <el-button size="small" type="primary" icon="el-icon-upload">
              上传附件
            </el-button>
            <div slot="tip" class="el-upload__tip">
              支持图片、文档等格式,单个文件不超过10MB
            </div>
          </el-upload>
          <!-- 附件列表 -->
          <div v-if="organData.attachments && organData.attachments.length > 0" class="attachment-list">
            <div v-for="file in organData.attachments" :key="file.id" class="attachment-item">
              <div class="file-info">
                <i :class="getFileIcon(file.fileType)" class="file-icon"></i>
                <span class="file-name" :title="file.fileName">{{ file.fileName }}</span>
                <span class="file-size">({{ formatFileSize(file.fileSize) }})</span>
              </div>
              <div class="file-actions">
                <el-button type="text" size="mini" @click="handlePreview(file)">预览</el-button>
                <el-button type="text" size="mini" @click="handleDownload(file)">下载</el-button>
                <el-button
                  v-if="!readonly"
                  type="text"
                  size="mini"
                  style="color: #F56C6C;"
                  @click="handleDeleteFile(file)"
                >删除</el-button>
              </div>
            </div>
          <div class="attachment-header">
            <i class="el-icon-paperclip"></i>
            <span class="attachment-title">附件上传</span>
            <span class="attachment-tip"
              >支持上传检验报告单等文件 (最多{{ attachmentLimit }}个)</span
            >
          </div>
          <div v-else class="no-attachment">
            <el-empty description="暂无附件" :image-size="50"></el-empty>
          <!-- 使用 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="
              assessmentData.attachments &&
                assessmentData.attachments.length > 0
            "
          >
            <div class="list-title">
              已上传附件 ({{ assessmentData.attachments.length }})
            </div>
            <el-table
              :data="assessmentData.attachments"
              style="width: 100%"
              size="small"
            >
              <el-table-column label="文件名" min-width="200">
                <template slot-scope="scope">
                  <i
                    class="el-icon-document"
                    :style="{ color: getFileIconColor(scope.row.fileName) }"
                  ></i>
                  <span class="file-name">{{ scope.row.fileName }}</span>
                </template>
              </el-table-column>
              <el-table-column label="文件类型" width="100">
                <template slot-scope="scope">
                  <el-tag
                    :type="getFileTagType(scope.row.fileName)"
                    size="small"
                  >
                    {{ getFileTypeText(scope.row.fileName) }}
                  </el-tag>
                </template>
              </el-table-column>
              <el-table-column label="上传时间" width="160">
                <template slot-scope="scope">
                  <span>{{ formatDateTime(scope.row.uploadTime) }}</span>
                </template>
              </el-table-column>
              <el-table-column label="文件大小" width="100">
                <template slot-scope="scope">
                  <span>{{ formatFileSize(scope.row.fileSize) }}</span>
                </template>
              </el-table-column>
              <el-table-column label="操作" width="266" fixed="right">
                <template slot-scope="scope">
                  <el-button
                    size="mini"
                    type="primary"
                    @click="handlePreview(scope.row)"
                    :disabled="!isPreviewable(scope.row.fileName)"
                  >
                    预览
                  </el-button>
                  <el-button
                    size="mini"
                    type="success"
                    @click="handleDownload(scope.row)"
                  >
                    下载
                  </el-button>
                  <el-button
                    v-if="!readonly"
                    size="mini"
                    type="danger"
                    @click="handleRemoveAttachment(scope.$index)"
                  >
                    删除
                  </el-button>
                </template>
              </el-table-column>
            </el-table>
          </div>
        </div>
      </el-form-item>
@@ -73,45 +124,53 @@
      <el-form-item v-if="!readonly">
        <el-button type="primary" @click="handleSave">保存评估</el-button>
        <el-button @click="handleCancel">取消</el-button>
        <el-button
          type="success"
          @click="handleAddAssessment"
          icon="el-icon-plus"
        >
          新增评估记录
        </el-button>
      </el-form-item>
    </el-form>
    <!-- 附件预览弹窗 -->
    <el-dialog
      :title="`附件预览 - ${currentFile.fileName}`"
      :visible.sync="previewVisible"
      width="60%"
    >
      <div v-if="isImage(currentFile.fileType)" class="image-preview">
        <img :src="currentFile.fileUrl" alt="预览图片" style="max-width: 100%;" />
      </div>
      <div v-else class="file-preview">
        <el-alert
          title="该文件格式不支持在线预览,请下载后查看"
          type="info"
          show-icon
        />
        <div style="text-align: center; margin-top: 20px;">
          <el-button type="primary" @click="handleDownload(currentFile)">
            <i class="el-icon-download"></i> 下载文件
          </el-button>
        </div>
      </div>
    </el-dialog>
    <!-- 文件预览弹窗 -->
    <FilePreviewDialog
      :visible="previewVisible"
      :file="currentPreviewFile"
      @close="previewVisible = false"
      @download="handleDownload"
    />
  </div>
</template>
<script>
import { getToken } from '@/utils/auth'
import UploadAttachment from "@/components/UploadAttachment";
import FilePreviewDialog from "@/components/FilePreviewDialog";
import dayjs from "dayjs";
export default {
  name: "OrganAssessmentForm",
  components: {
    UploadAttachment,
    FilePreviewDialog
  },
  props: {
    organData: {
      type: Object,
      default: () => ({})
    },
    assessmentData: {
      type: Object,
      default: () => ({
        attachments: [] // 确保有附件数组
        functionStatus: "",
        assessmentOpinion: "",
        attachments: []
      })
    },
    assessmentIndex: {
      type: Number,
      default: 0
    },
    readonly: {
      type: Boolean,
@@ -120,125 +179,250 @@
  },
  data() {
    return {
      // 预览相关
      previewVisible: false,
      currentFile: {},
      uploadHeaders: {
        Authorization: 'Bearer ' + getToken()
      }
      currentPreviewFile: null,
      // 附件相关配置
      attachmentLimit: 10,
      attachmentAccept:
        ".pdf,.jpg,.jpeg,.png,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.txt",
      attachmentFileList: []
    };
  },
  watch: {
    organData: {
      handler(newVal, oldVal) {
        // 只有当附件数据真正发生变化时才初始化
        if (
          !oldVal ||
          !oldVal.attachments ||
          JSON.stringify(newVal.attachments) !==
            JSON.stringify(oldVal.attachments)
        ) {
          this.initAttachmentList();
        }
      },
      immediate: true,
      deep: true
    }
  },
  methods: {
    /** 初始化附件列表 */
    initAttachmentList() {
      if (this.organData.attachments && this.organData.attachments.length > 0) {
        this.assessmentData.attachments = [...this.organData.attachments];
        this.attachmentFileList = this.organData.attachments.map(item => ({
          uid: item.id || Math.random(),
          name: item.fileName,
          url: item.path || item.fileUrl,
          status: "success"
        }));
      } else {
        this.assessmentData.attachments = [];
        this.attachmentFileList = [];
      }
    },
    handleSave() {
      this.$emit('save', {
        ...this.organData,
        assessmentTime: new Date().toISOString(),
        assessor: '当前用户'
      });
      const saveData = {
        organData: this.organData,
        assessmentData: this.assessmentData,
        assessmentIndex: this.assessmentIndex
      };
      this.$emit("save", saveData);
    },
    handleCancel() {
      this.$emit('cancel');
      this.$emit("cancel");
    },
    // 文件上传处理
    handleUploadSuccess(response, file) {
    handleAddAssessment() {
      this.$emit("add-assessment", {
        organData: this.organData,
        currentIndex: this.assessmentIndex
      });
    },
    /** 附件变化处理 */
    handleAttachmentChange(fileList) {
      this.attachmentFileList = fileList;
    },
    /** 附件移除处理 */
    handleAttachmentRemove(file) {
      if (file.url) {
        const index = this.assessmentData.attachments.findIndex(
          item => item.path === file.url || item.fileUrl === file.url
        );
        if (index > -1) {
          this.assessmentData.attachments.splice(index, 1);
        }
      }
    },
    /** 手动删除附件 */
    handleRemoveAttachment(index) {
      this.assessmentData.attachments.splice(index, 1);
      this.attachmentFileList.splice(index, 1);
      this.$message.success("附件删除成功");
    },
    /** 上传成功处理 */
    handleUploadSuccess({ file, fileList, response }) {
      if (response.code === 200) {
        // 将新文件添加到附件列表
        const newFile = {
          id: response.data.fileId,
        const attachmentObj = {
          id:
            response.data.fileId ||
            Math.random()
              .toString(36)
              .substr(2),
          fileName: file.name,
          path: response.data.fileUrl || file.url,
          fileUrl: response.data.fileUrl || file.url,
          fileType: this.getFileExtension(file.name),
          fileSize: file.size,
          fileUrl: response.data.fileUrl,
          uploadTime: new Date().toISOString()
          uploadTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
          assessmentType: this.assessmentType,
          organType: this.organData.organType
        };
        if (!this.organData.attachments) {
          this.organData.attachments = [];
        }
        this.organData.attachments.push(newFile);
        this.$message.success('文件上传成功');
        this.assessmentData.attachments.push(attachmentObj);
        this.$message.success("文件上传成功");
      }
    },
    handleUploadError(error) {
      console.error('文件上传失败:', error);
      this.$message.error('文件上传失败');
    /** 上传错误处理 */
    handleUploadError({ file, fileList, error }) {
      console.error("附件上传失败:", error);
      this.$message.error("文件上传失败,请重试");
    },
    beforeUpload(file) {
      const isLt10M = file.size / 1024 / 1024 < 10;
      if (!isLt10M) {
        this.$message.error('文件大小不能超过 10MB');
        return false;
      }
      return true;
    },
    // 文件操作
    /** 文件预览 */
    handlePreview(file) {
      this.currentFile = file;
      this.currentPreviewFile = {
        fileName: file.fileName,
        fileUrl: file.path || file.fileUrl,
        fileType: this.getFileType(file.fileName)
      };
      this.previewVisible = true;
    },
    /** 文件下载 */
    handleDownload(file) {
      // 模拟文件下载
      const link = document.createElement('a');
      link.href = file.fileUrl;
      link.download = file.fileName;
      link.click();
      this.$message.success('开始下载文件');
      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("文件路径不存在,无法下载");
      }
    },
    handleDeleteFile(file) {
      this.$confirm('确定要删除这个附件吗?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        const index = this.organData.attachments.findIndex(f => f.id === file.id);
        if (index !== -1) {
          this.organData.attachments.splice(index, 1);
          this.$message.success('删除成功');
        }
      });
    /** 获取文件类型 */
    getFileType(fileName) {
      if (!fileName) return "other";
      const extension = fileName
        .split(".")
        .pop()
        .toLowerCase();
      const imageTypes = ["jpg", "jpeg", "png", "gif", "bmp", "webp"];
      const pdfTypes = ["pdf"];
      const officeTypes = ["doc", "docx", "xls", "xlsx", "ppt", "pptx"];
      if (imageTypes.includes(extension)) return "image";
      if (pdfTypes.includes(extension)) return "pdf";
      if (officeTypes.includes(extension)) return "office";
      return "other";
    },
    // 工具方法
    getFileIcon(fileType) {
      const iconMap = {
        'pdf': 'el-icon-document',
        'doc': 'el-icon-document',
        'docx': 'el-icon-document',
        'xls': 'el-icon-document',
        'xlsx': 'el-icon-document',
        'jpg': 'el-icon-picture',
        'jpeg': 'el-icon-picture',
        'png': 'el-icon-picture',
        'gif': 'el-icon-picture'
    /** 获取文件图标颜色 */
    getFileIconColor(fileName) {
      const type = this.getFileType(fileName);
      const colorMap = {
        image: "#67C23A",
        pdf: "#F56C6C",
        office: "#409EFF",
        other: "#909399"
      };
      return iconMap[fileType] || 'el-icon-document';
      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();
      return filename
        .split(".")
        .pop()
        .toLowerCase();
    },
    /** 格式化文件大小 */
    formatFileSize(bytes) {
      if (bytes === 0) return '0 B';
      if (!bytes || bytes === 0) return "0 B";
      const k = 1024;
      const sizes = ['B', 'KB', 'MB', 'GB'];
      const sizes = ["B", "KB", "MB", "GB"];
      const i = Math.floor(Math.log(bytes) / Math.log(k));
      return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
      return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
    },
    isImage(fileType) {
      const imageTypes = ['jpg', 'jpeg', 'png', 'gif', 'bmp'];
      return imageTypes.includes(fileType);
    /** 日期时间格式化 */
    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;
      }
    }
  }
}
};
</script>
<style scoped>
@@ -250,61 +434,57 @@
  border: 1px solid #ebeef5;
  border-radius: 4px;
  padding: 15px;
  background: #fafafa;
}
.attachment-upload {
  margin-bottom: 15px;
.attachment-header {
  display: flex;
  align-items: center;
  margin-bottom: 16px;
  padding-bottom: 8px;
  border-bottom: 1px solid #ebeef5;
}
.attachment-title {
  font-weight: bold;
  margin: 0 8px;
  color: #303133;
}
.attachment-tip {
  font-size: 12px;
  color: #909399;
  margin-left: auto;
}
.attachment-list {
  max-height: 300px;
  overflow-y: auto;
  margin-top: 16px;
}
.attachment-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px 12px;
  border-bottom: 1px solid #f0f0f0;
}
.attachment-item:last-child {
  border-bottom: none;
}
.file-info {
  display: flex;
  align-items: center;
  flex: 1;
}
.file-icon {
  margin-right: 8px;
  font-size: 16px;
  color: #409EFF;
.list-title {
  font-weight: bold;
  margin-bottom: 12px;
  color: #303133;
  font-size: 14px;
}
.file-name {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  margin-right: 8px;
  font-size: 13px;
  margin-left: 8px;
}
.file-size {
  color: #909399;
::v-deep .el-upload__tip {
  font-size: 12px;
}
.file-actions {
  flex-shrink: 0;
}
.no-attachment {
  text-align: center;
  padding: 20px;
  color: #909399;
  margin-top: 8px;
}
::v-deep .el-table .cell {
  padding: 8px 12px;
}
::v-deep .el-button--mini {
  padding: 5px 10px;
  font-size: 12px;
}
</style>
src/views/business/assess/index.vue
@@ -26,18 +26,18 @@
            @keyup.enter.native="handleQuery"
          />
        </el-form-item>
        <el-form-item label="业务人员" prop="assignee">
        <el-form-item label="业务人员" prop="coordinatorName">
          <el-input
            v-model="queryParams.assignee"
            v-model="queryParams.coordinatorName"
            placeholder="请输入业务人员"
            clearable
            style="width: 200px"
            @keyup.enter.native="handleQuery"
          />
        </el-form-item>
        <el-form-item label="评估状态" prop="assessmentStatus">
        <el-form-item label="评估状态" prop="firstAssessState">
          <el-select
            v-model="queryParams.assessmentStatus"
            v-model="queryParams.firstAssessState"
            placeholder="请选择评估状态"
            clearable
            style="width: 200px"
@@ -50,7 +50,7 @@
        </el-form-item>
        <el-form-item label="申请时间" prop="applyTimeRange">
          <el-date-picker
            v-model="queryParams.applyTimeRange"
            v-model="applyTimeRange"
            type="daterange"
            range-separator="至"
            start-placeholder="开始日期"
@@ -61,7 +61,7 @@
        </el-form-item>
        <el-form-item label="评估时间" prop="assessmentTimeRange">
          <el-date-picker
            v-model="queryParams.assessmentTimeRange"
            v-model="assessmentTimeRange"
            type="daterange"
            range-separator="至"
            start-placeholder="开始日期"
@@ -187,22 +187,22 @@
        <el-table-column
          label="评估状态"
          align="center"
          prop="assessmentStatus"
          prop="firstAssessState"
          width="100"
        >
          <template slot-scope="scope">
            <el-tag :type="statusFilter(scope.row.assessmentStatus)">
              {{ statusTextFilter(scope.row.assessmentStatus) }}
            <el-tag :type="statusFilter(scope.row.firstAssessState)">
              {{ statusTextFilter(scope.row.firstAssessState) }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column
          label="业务人员"
          align="center"
          prop="assignee"
          prop="coordinatorName"
          width="100"
        />
        <el-table-column
        <!-- <el-table-column
          label="评估类型"
          align="center"
          prop="assessmentType"
@@ -214,7 +214,7 @@
              :value="parseInt(scope.row.assessmentType)"
            />
          </template>
        </el-table-column>
        </el-table-column> -->
        <el-table-column
          label="操作"
          align="center"
@@ -231,8 +231,8 @@
            >
            <el-button
              v-if="
                scope.row.assessmentStatus === '0' ||
                  scope.row.assessmentStatus === '1'
                scope.row.firstAssessState === '0' ||
                  scope.row.firstAssessState === '1'
              "
              size="mini"
              type="text"
@@ -241,7 +241,7 @@
              >评估</el-button
            >
            <el-button
              v-if="scope.row.assessmentStatus === '2'"
              v-if="scope.row.firstAssessState === '2'"
              size="mini"
              type="text"
              icon="el-icon-check"
@@ -271,7 +271,7 @@
  delAssessment,
  exportAssessment
} from "./mockAssessmentApi";
import { evaluateBaseInfolist } from "@/api/businessApi/index";
import Pagination from "@/components/Pagination";
export default {
@@ -298,11 +298,12 @@
        pageSize: 10,
        donorName: undefined,
        hospitalName: undefined,
        assignee: undefined,
        assessmentStatus: undefined,
        applyTimeRange: [],
        assessmentTimeRange: []
        coordinatorName: undefined,
        firstAssessState: undefined,
      },
      applyTimeRange: [],
        assessmentTimeRange: [],
      // 性别选项
      genderOptions: [
        { value: "0", label: "男" },
@@ -341,6 +342,7 @@
    // 查询评估列表
    getList() {
      this.loading = true;
      evaluateBaseInfolist(this.queryParams);
      listAssessment(this.queryParams)
        .then(response => {
          if (response.code === 200) {
src/views/business/decide/DecideInfo.vue
@@ -13,33 +13,41 @@
        >
          保存信息
        </el-button>
        <el-button
          v-else
          type="primary"
          style="float: right; padding: 3px 0"
          @click="handleEdit"
        >
          编辑信息
        </el-button>
      </div>
      <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-form-item label="捐献者编号" prop="donorno">
              <el-input
                v-model="form.hospitalNo"
                v-model="form.donorno"
                :readonly="!isEdit"
                placeholder="自动生成 D+数字"
                placeholder="自动生成捐献者编号"
              />
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="捐献者姓名" prop="donorName">
              <el-input v-model="form.donorName" :readonly="!isEdit" />
            <el-form-item label="捐献者姓名" prop="name">
              <el-input v-model="form.name" :readonly="!isEdit" />
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="性别" prop="gender">
            <el-form-item label="性别" prop="sex">
              <el-select
                v-model="form.gender"
                v-model="form.sex"
                :disabled="!isEdit"
                style="width: 100%"
              >
                <el-option label="男" value="0" />
                <el-option label="女" value="1" />
                <el-option label="男" value="1" />
                <el-option label="女" value="2" />
              </el-select>
            </el-form-item>
          </el-col>
@@ -52,14 +60,14 @@
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="疾病诊断" prop="diagnosis">
              <el-input v-model="form.diagnosis" :readonly="!isEdit" />
            <el-form-item label="疾病诊断" prop="diagnosisname">
              <el-input v-model="form.diagnosisname" :readonly="!isEdit" />
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="死亡原因" prop="deathReason">
            <el-form-item label="死亡原因" prop="deathreason">
              <el-select
                v-model="form.deathReason"
                v-model="form.deathreason"
                :disabled="!isEdit"
                style="width: 100%"
              >
@@ -73,9 +81,9 @@
        <el-row :gutter="20">
          <el-col :span="8">
            <el-form-item label="死亡时间" prop="deathTime">
            <el-form-item label="死亡时间" prop="deathtime">
              <el-date-picker
                v-model="form.deathTime"
                v-model="form.deathtime"
                type="datetime"
                value-format="yyyy-MM-dd HH:mm:ss"
                style="width: 100%"
@@ -83,21 +91,61 @@
              />
            </el-form-item>
          </el-col>
            <el-col :span="8">
            <el-form-item label="判定医生一" prop="judgmentDoctor">
              <el-input v-model="form.judgmentDoctorone" :readonly="!isEdit" />
          <el-col :span="8">
            <el-form-item label="判定医生一" prop="deathjudgedocto">
              <el-input v-model="form.deathjudgedocto" :readonly="!isEdit" />
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="判定医生二" prop="judgmentDoctor">
              <el-input v-model="form.judgmentDoctortwo" :readonly="!isEdit" />
            <el-form-item label="判定医生二" prop="deathjudgedoctt">
              <el-input v-model="form.deathjudgedoctt" :readonly="!isEdit" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
        <el-row :gutter="20">
          <el-col :span="8">
            <el-form-item label="登记人" prop="registrant">
              <el-input v-model="form.registrant" :readonly="!isEdit" />
            <el-form-item label="器官获取机构" prop="gainhospitalname">
              <el-input v-model="form.gainhospitalname" :readonly="!isEdit" />
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="是否默哀缅怀" prop="isspendremember">
              <el-select
                v-model="form.isspendremember"
                :disabled="!isEdit"
                style="width: 100%"
              >
                <el-option label="是" :value="1" />
                <el-option label="否" :value="0" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="是否恢复遗体仪容" prop="isrestoreremains">
              <el-select
                v-model="form.isrestoreremains"
                :disabled="!isEdit"
                style="width: 100%"
              >
                <el-option label="是" :value="1" />
                <el-option label="否" :value="0" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="8">
            <el-form-item label="负责人" prop="responsibleusername">
              <el-input v-model="form.responsibleusername" :readonly="!isEdit" />
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="记录状态" prop="recordstate">
              <el-tag :type="getStatusTag(form.recordstate)">
                {{ getStatusText(form.recordstate) }}
              </el-tag>
            </el-form-item>
          </el-col>
        </el-row>
@@ -281,7 +329,7 @@
</template>
<script>
import { getDeathJudgmentDetail, updateDeathJudgment } from "./mockDeathJudgmentApi";
import { deathinfoedit, deathinfoInfo } from "@/api/businessApi";
export default {
  name: "DeathJudgmentDetail",
@@ -294,31 +342,39 @@
      // 表单数据
      form: {
        id: undefined,
        hospitalNo: "",
        donorName: "",
        gender: "",
        infoid: undefined,
        donorno: "",
        name: "",
        sex: "",
        age: "",
        diagnosis: "",
        deathReason: "",
        deathTime: "",
        judgmentDoctor: "",
        judgmentDescription: "",
        registrant: "",
        registrationTime: ""
        diagnosisname: "",
        deathreason: "",
        deathtime: "",
        deathjudgedocto: "",
        deathjudgedoctt: "",
        gainhospitalno: "",
        gainhospitalname: "",
        isspendremember: 0,
        isrestoreremains: 0,
        rememberannex: "",
        responsibleuserid: "",
        responsibleusername: "",
        recordstate: "0",
        judgmentDescription: ""
      },
      // 表单验证规则
      rules: {
        donorName: [
        name: [
          { required: true, message: "捐献者姓名不能为空", trigger: "blur" }
        ],
        deathReason: [
        deathreason: [
          { required: true, message: "死亡原因不能为空", trigger: "change" }
        ],
        deathTime: [
        deathtime: [
          { required: true, message: "死亡时间不能为空", trigger: "change" }
        ],
        judgmentDoctor: [
          { required: true, message: "判定医生不能为空", trigger: "blur" }
        deathjudgedocto: [
          { required: true, message: "判定医生一不能为空", trigger: "blur" }
        ]
      },
      // 附件相关数据
@@ -358,52 +414,87 @@
    if (id && !this.$route.path.includes('/add')) {
      this.getDetail(id);
    } else if (this.$route.path.includes('/add')) {
      this.generateHospitalNo();
      this.generateDonorNo();
    }
    this.getAttachmentList();
  },
  methods: {
    // 生成住院号
    generateHospitalNo() {
      // 模拟生成住院号:D + 时间戳后6位
    // 生成捐献者编号
    generateDonorNo() {
      const timestamp = Date.now().toString();
      this.form.hospitalNo = 'D' + timestamp.slice(-6);
      this.form.donorno = 'DONOR' + timestamp.slice(-8);
    },
    // 获取详情
    getDetail(id) {
      getDeathJudgmentDetail(id).then(response => {
        if (response.code === 200) {
          this.form = response.data;
    async getDetail(id) {
      try {
        const response = await deathinfoInfo({ id });
        let realData = {};
        if (response && response.data) {
          realData = response.data;
        } else if (response) {
          realData = response;
        }
      });
        // 映射字段到表单
        this.form = {
          ...this.form,
          ...realData,
          // 确保数值类型字段正确转换
          isspendremember: realData.isspendremember ? parseInt(realData.isspendremember) : 0,
          isrestoreremains: realData.isrestoreremains ? parseInt(realData.isrestoreremains) : 0
        };
        // 解析附件信息
        if (realData.rememberannex) {
          this.parseAttachmentData(realData.rememberannex);
        }
      } catch (error) {
        console.error('获取死亡判定详情失败:', error);
        this.$message.error('数据加载失败');
      }
    },
    // 解析附件数据
    parseAttachmentData(attachmentJson) {
      try {
        if (attachmentJson) {
          const attachments = JSON.parse(attachmentJson);
          if (Array.isArray(attachments)) {
            this.attachmentList = attachments;
          }
        }
      } catch (error) {
        console.error('解析附件数据失败:', error);
      }
    },
    // 构建附件JSON数据
    buildAttachmentJson() {
      return JSON.stringify(this.attachmentList);
    },
    // 获取状态标签样式
    getStatusTag(status) {
      const statusMap = {
        "0": "warning", // 维护中
        "1": "success", // 已完成
        "99": "danger"  // 已终止
      };
      return statusMap[status] || "info";
    },
    // 获取状态文本
    getStatusText(status) {
      const textMap = {
        "0": "维护中",
        "1": "已完成",
        "99": "已终止"
      };
      return textMap[status] || "未知状态";
    },
    // 获取附件列表
    getAttachmentList() {
      this.attachmentLoading = true;
      // 模拟附件数据 - 实际项目中从接口获取
      // 实际项目中从接口获取附件数据
      setTimeout(() => {
        this.attachmentList = [
          {
            id: 1,
            type: "1",
            typeName: "脑死亡判定表",
            fileName: "脑死亡判定表_202512001.pdf",
            fileSize: 2548321,
            uploadTime: "2025-12-01 10:30:00",
            uploader: "张医生",
            fileUrl: "/attachments/brain_death_1.pdf"
          },
          {
            id: 2,
            type: "2",
            typeName: "脑电图评估表",
            fileName: "脑电图评估表_202512001.docx",
            fileSize: 512345,
            uploadTime: "2025-12-01 14:20:00",
            uploader: "李医生",
            fileUrl: "/attachments/eeg_1.docx"
          }
        ];
        this.attachmentLoading = false;
      }, 500);
    },
@@ -451,7 +542,6 @@
      const maxSize = 10 * 1024 * 1024; // 10MB
      // 校验文件类型
      const isTypeOk = allowedTypes.includes(file.type) ||
                      file.name.endsWith('.pdf') ||
                      file.name.endsWith('.jpg') ||
@@ -467,7 +557,6 @@
        return false;
      }
      // 校验文件大小
      if (file.size > maxSize) {
        this.$message.error('文件大小不能超过10MB');
        return false;
@@ -493,7 +582,6 @@
      this.uploadLoading = true;
      try {
        // 模拟上传过程 - 实际项目中调用上传接口
        for (const file of this.tempFileList) {
          const newAttachment = {
            id: Date.now() + Math.random(),
@@ -508,6 +596,9 @@
          this.attachmentList.push(newAttachment);
        }
        // 更新附件JSON数据到表单
        this.form.rememberannex = this.buildAttachmentJson();
        this.$message.success('文件上传成功');
        this.uploadDialogVisible = false;
@@ -529,6 +620,8 @@
        const index = this.attachmentList.findIndex(item => item.id === attachment.id);
        if (index !== -1) {
          this.attachmentList.splice(index, 1);
          // 更新附件JSON数据到表单
          this.form.rememberannex = this.buildAttachmentJson();
          this.$message.success('评估表删除成功');
        }
      }).catch(() => {});
@@ -549,38 +642,48 @@
    },
    // 下载附件
    handleDownload(attachment) {
      // 实际项目中调用下载接口
      const link = document.createElement('a');
      link.href = attachment.fileUrl;
      link.download = attachment.fileName;
      link.click();
      this.$message.success(`开始下载: ${attachment.fileName}`);
    },
    // 编辑信息
    handleEdit() {
      this.isEdit = true;
    },
    // 保存信息
    handleSave() {
      this.$refs.form.validate(valid => {
    async handleSave() {
      this.$refs.form.validate(async valid => {
        if (valid) {
          this.saveLoading = true;
          // 模拟保存过程
          updateDeathJudgment(this.form)
            .then(response => {
              if (response.code === 200) {
                this.$message.success('保存成功');
                if (this.$route.path.includes('/add')) {
                  this.$router.push('/case/deathJudgment');
                } else {
                  this.isEdit = false;
                }
          try {
            // 构建提交数据
            const submitData = {
              ...this.form,
              // 确保附件数据最新
              rememberannex: this.buildAttachmentJson()
            };
            const response = await deathinfoedit(submitData);
            if (response.code === 200) {
              this.$message.success('保存成功');
              this.isEdit = false;
              if (this.$route.path.includes('/add')) {
                this.$router.push('/case/deathJudgment');
              }
            })
            .catch(error => {
              console.error('保存失败:', error);
              this.$message.error('保存失败');
            })
            .finally(() => {
              this.saveLoading = false;
            });
            } else {
              this.$message.error(response.message || '保存失败');
            }
          } catch (error) {
            console.error('保存失败:', error);
            this.$message.error('保存失败');
          } finally {
            this.saveLoading = false;
          }
        }
      });
    },
src/views/business/decide/index.vue
@@ -8,27 +8,27 @@
        :inline="true"
        label-width="100px"
      >
        <el-form-item label="住院号" prop="hospitalNo">
        <el-form-item label="住院号" prop="inpatientno">
          <el-input
            v-model="queryParams.hospitalNo"
            v-model="queryParams.inpatientno"
            placeholder="请输入住院号"
            clearable
            style="width: 200px"
            @keyup.enter.native="handleQuery"
          />
        </el-form-item>
        <el-form-item label="捐献者姓名" prop="donorName">
        <el-form-item label="捐献者姓名" prop="name">
          <el-input
            v-model="queryParams.donorName"
            v-model="queryParams.name"
            placeholder="请输入捐献者姓名"
            clearable
            style="width: 200px"
            @keyup.enter.native="handleQuery"
          />
        </el-form-item>
        <el-form-item label="死亡原因" prop="deathReason">
        <el-form-item label="死亡原因" prop="deathreason">
          <el-select
            v-model="queryParams.deathReason"
            v-model="queryParams.deathreason"
            placeholder="请选择死亡原因"
            clearable
            style="width: 200px"
@@ -73,13 +73,6 @@
            >修改</el-button
          >
          <el-button
            type="danger"
            icon="el-icon-delete"
            :disabled="multiple"
            @click="handleDelete"
            >删除</el-button
          >
          <el-button
            type="warning"
            icon="el-icon-download"
            @click="handleExport"
@@ -103,95 +96,114 @@
      >
        <el-table-column type="selection" width="55" align="center" />
        <el-table-column
          label="案例编号"
          align="center"
          prop="caseNo"
          width="120"
        />
        <el-table-column
          label="住院号"
          align="center"
          prop="hospitalNo"
          prop="inpatientno"
          width="120"
        />
        <el-table-column
          label="捐献者姓名"
          align="center"
          prop="donorName"
          prop="name"
          width="120"
        />
        <el-table-column label="性别" align="center" prop="gender" width="80">
        <el-table-column label="性别" align="center" prop="sex" width="80">
          <template slot-scope="scope">
            <dict-tag
              :options="dict.type.sys_user_sex"
              :value="parseInt(scope.row.gender)"
              :value="scope.row.sex"
            />
          </template>
        </el-table-column>
        <el-table-column label="年龄" align="center" prop="age" width="80" />
        <el-table-column
          label="治疗医院"
          align="center"
          prop="treatmenthospitalname"
          width="180"
          show-overflow-tooltip
        />
        <el-table-column
          label="疾病诊断"
          align="center"
          prop="diagnosis"
          min-width="180"
          prop="diagnosisname"
          min-width="200"
          show-overflow-tooltip
        />
        <el-table-column
          label="死亡原因"
          align="center"
          prop="deathReason"
          prop="deathreason"
          width="120"
        >
          <template slot-scope="scope">
            <el-tag :type="reasonFilter(scope.row.deathReason)">
              {{ reasonTextFilter(scope.row.deathReason) }}
            <el-tag :type="reasonFilter(scope.row.deathreason)">
              {{ reasonTextFilter(scope.row.deathreason) }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column
          label="死亡时间"
          align="center"
          prop="deathTime"
          prop="deathtime"
          width="160"
        >
          <template slot-scope="scope">
            <span>{{
              scope.row.deathTime
                ? parseTime(scope.row.deathTime, "{y}-{m}-{d} {h}:{i}")
              scope.row.deathtime
                ? parseTime(scope.row.deathtime, "{y}-{m}-{d} {h}:{i}")
                : "-"
            }}</span>
          </template>
        </el-table-column>
        <el-table-column
          label="判定医生"
          label="判定医生一"
          align="center"
          prop="judgmentDoctor"
          prop="deathjudgedocto"
          width="120"
        />
          <el-table-column
        <el-table-column
          label="判定医生二"
          align="center"
          prop="judgmentDoctortwo"
          prop="deathjudgedoctt"
          width="120"
        />
        <el-table-column
          label="登记时间"
          label="记录状态"
          align="center"
          prop="registrationTime"
          prop="recordstate"
          width="100"
        >
          <template slot-scope="scope">
            <el-tag :type="statusFilter(scope.row.recordstate)">
              {{ statusTextFilter(scope.row.recordstate) }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column
          label="创建时间"
          align="center"
          prop="createTime"
          width="160"
        >
          <template slot-scope="scope">
            <span>{{
              scope.row.registrationTime
                ? parseTime(scope.row.registrationTime, "{y}-{m}-{d} {h}:{i}")
              scope.row.createTime
                ? parseTime(scope.row.createTime, "{y}-{m}-{d} {h}:{i}")
                : "-"
            }}</span>
          </template>
        </el-table-column>
        <el-table-column
          label="登记人"
          align="center"
          prop="registrant"
          width="100"
        />
        <el-table-column
          label="操作"
          align="center"
          width="210"
          width="180"
          class-name="small-padding fixed-width"
        >
          <template slot-scope="scope">
@@ -208,14 +220,6 @@
              icon="el-icon-edit"
              @click="handleUpdate(scope.row)"
              >修改</el-button
            >
            <el-button
              size="mini"
              type="text"
              icon="el-icon-delete"
              style="color: #F56C6C"
              @click="handleDelete(scope.row)"
              >删除</el-button
            >
          </template>
        </el-table-column>
@@ -234,7 +238,7 @@
</template>
<script>
import { listDeathJudgment, delDeathJudgment, exportDeathJudgment } from "./mockDeathJudgmentApi";
import { queryDathInfoBaseInfo, deathinfoedit,deathinfoInfo } from "@/api/businessApi";
import Pagination from "@/components/Pagination";
export default {
@@ -259,11 +263,13 @@
      queryParams: {
        pageNum: 1,
        pageSize: 10,
        hospitalNo: undefined,
        donorName: undefined,
        deathReason: undefined,
        inpatientno: undefined,
        name: undefined,
        deathreason: undefined,
        deathTimeRange: []
      }
      },
      // 所有数据(用于前端筛选)
      allTableData: []
    };
  },
  created() {
@@ -273,55 +279,157 @@
    // 死亡原因过滤器
    reasonFilter(reason) {
      const reasonMap = {
        "brain_death": "primary", // 脑死亡
        "heart_death": "danger", // 心死亡
        "other": "info" // 其他
        brain_death: "primary",
        heart_death: "danger",
        other: "info"
      };
      return reasonMap[reason] || "info";
    },
    reasonTextFilter(reason) {
      const reasonMap = {
        "brain_death": "脑死亡",
        "heart_death": "心死亡",
        "other": "其他"
        brain_death: "脑死亡",
        heart_death: "心死亡",
        other: "其他"
      };
      return reasonMap[reason] || "未知";
    },
    // 查询死亡判定列表
    getList() {
      this.loading = true;
      listDeathJudgment(this.queryParams)
        .then(response => {
          if (response.code === 200) {
            this.deathJudgmentList = response.data.rows;
            this.total = response.data.total;
          } else {
            this.$message.error("获取数据失败");
          }
          this.loading = false;
        })
        .catch(error => {
          console.error("获取死亡判定列表失败:", error);
          this.loading = false;
          this.$message.error("获取数据失败");
        });
    // 记录状态过滤器
    statusFilter(status) {
      const statusMap = {
        "0": "warning", // 维护中
        "1": "success", // 已完成
        "99": "danger" // 已终止
      };
      return statusMap[status] || "info";
    },
    statusTextFilter(status) {
      const statusMap = {
        "0": "维护中",
        "1": "已完成",
        "99": "已终止"
      };
      return statusMap[status] || "未知状态";
    },
    // 查询死亡判定列表
    async getList() {
      this.loading = true;
      try {
        const response = await queryDathInfoBaseInfo(this.queryParams);
        // 根据实际接口返回结构调整
        let realData = [];
        realData = response.data;
        this.total = response.total;
        // if (Array.isArray(response)) {
        //   realData = response;
        // } else if (response && response.data) {
        //   realData = response.data;
        // } else if (response && response.rows) {
        //   realData = response.rows;
        //   this.total = response.total || response.rows.length;
        // } else if (response && response.code === 200) {
        //   realData = response.data.rows || response.data;
        //   this.total = response.data.total || realData.length;
        // } else {
        //   realData = [];
        // }
        // 存储所有数据用于前端筛选
        this.allTableData = realData;
        // 应用前端筛选条件
        let filteredData = this.applyFrontendFilter(realData);
        // 前端分页处理(如果接口不支持后端分页)
        if (!response.total && !response.data) {
          const startIndex =
            (this.queryParams.pageNum - 1) * this.queryParams.pageSize;
          const endIndex = startIndex + this.queryParams.pageSize;
          this.deathJudgmentList = filteredData.slice(startIndex, endIndex);
          this.total = filteredData.length;
        } else {
          // 接口已分页,直接使用返回数据
          this.deathJudgmentList = filteredData;
        }
      } catch (error) {
        console.error("获取死亡判定数据失败:", error);
        this.$message.error("数据加载失败");
        this.deathJudgmentList = [];
        this.total = 0;
      } finally {
        this.loading = false;
      }
    },
    // 应用前端筛选
    applyFrontendFilter(data) {
      let filteredData = data;
      // 住院号筛选
      if (this.queryParams.inpatientno) {
        filteredData = filteredData.filter(
          item =>
            item.inpatientno &&
            item.inpatientno.includes(this.queryParams.inpatientno)
        );
      }
      // 姓名筛选
      if (this.queryParams.name) {
        filteredData = filteredData.filter(
          item => item.name && item.name.includes(this.queryParams.name)
        );
      }
      // 死亡原因筛选
      if (this.queryParams.deathreason) {
        filteredData = filteredData.filter(
          item => item.deathreason === this.queryParams.deathreason
        );
      }
      // 死亡时间范围筛选
      if (
        this.queryParams.deathTimeRange &&
        this.queryParams.deathTimeRange.length === 2
      ) {
        const [startDate, endDate] = this.queryParams.deathTimeRange;
        filteredData = filteredData.filter(item => {
          if (!item.deathtime) return false;
          const deathTime = new Date(item.deathtime).getTime();
          const startTime = new Date(startDate).getTime();
          const endTime = new Date(endDate + " 23:59:59").getTime();
          return deathTime >= startTime && deathTime <= endTime;
        });
      }
      return filteredData;
    },
    // 搜索按钮操作
    handleQuery() {
      this.queryParams.pageNum = 1;
      this.getList();
    },
    // 重置按钮操作
    resetQuery() {
      this.$refs.queryForm.resetFields();
      this.handleQuery();
      this.queryParams.pageNum = 1;
      this.getList();
    },
    // 多选框选中数据
    handleSelectionChange(selection) {
      this.ids = selection.map(item => item.id);
      this.single = selection.length !== 1;
      this.multiple = !selection.length;
    },
    // 查看详情
    handleView(row) {
      this.$router.push({
@@ -329,10 +437,12 @@
        query: { id: row.id }
      });
    },
    // 新增按钮操作
    handleCreate() {
      this.$router.push("/case/DecideInfo");
    },
    // 修改按钮操作
    handleUpdate(row) {
      const id = row.id || this.ids[0];
@@ -341,28 +451,9 @@
        query: { id: id }
      });
    },
    // 删除按钮操作
    handleDelete(row) {
      const ids = row.id ? [row.id] : this.ids;
      this.$confirm("是否确认删除选中的数据项?", "警告", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      })
        .then(() => {
          return delDeathJudgment(ids);
        })
        .then(response => {
          if (response.code === 200) {
            this.$message.success("删除成功");
            this.getList();
          }
        })
        .catch(() => {});
    },
    // 导出按钮操作
    // 导出按钮操作(模拟调用)
    handleExport() {
      const queryParams = this.queryParams;
      this.$confirm("是否确认导出所有死亡判定数据?", "警告", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
@@ -370,12 +461,19 @@
      })
        .then(() => {
          this.loading = true;
          return exportDeathJudgment(queryParams);
          // 模拟导出操作
          return new Promise(resolve => {
            setTimeout(() => {
              resolve({ code: 200 });
            }, 1000);
          });
        })
        .then(response => {
          if (response.code === 200) {
            this.$message.success("导出成功");
            // 实际项目中这里处理文件下载
            // 可以添加以下代码来触发文件下载
            // this.downloadFile();
          }
          this.loading = false;
        })
@@ -383,6 +481,18 @@
          this.loading = false;
        });
    },
    // 文件下载方法(预留)
    downloadFile() {
      // 实际项目中的文件下载逻辑
      const link = document.createElement("a");
      link.style.display = "none";
      link.href = "/api/export/death-judgment"; // 替换为实际导出接口
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
    },
    // 时间格式化
    parseTime(time, pattern) {
      if (!time) return "";
@@ -440,4 +550,14 @@
.fixed-width .el-button {
  margin: 0 5px;
}
/* 表格样式优化 */
::v-deep .el-table .cell {
  padding: 8px 4px;
}
::v-deep .el-table th {
  background-color: #f5f7fa;
  font-weight: bold;
}
</style>
src/views/business/ethicalReview/ethicalReviewInfo.vue
@@ -325,7 +325,7 @@
          </template>
        </el-table-column>
        <el-table-column label="操作" width="180" align="center" fixed="right">
        <el-table-column label="操作" width="280" align="center" fixed="right">
          <template slot-scope="scope">
            <el-button
              size="mini"
src/views/business/transfer/TransportEdit.vue
@@ -297,7 +297,7 @@
                <span>{{ formatDateTime(scope.row.createTime) }}</span>
              </template>
            </el-table-column>
            <el-table-column label="操作" width="180">
            <el-table-column label="操作" width="266">
              <template slot-scope="scope">
                <el-button
                  size="mini"
src/views/project/DonationProcess/index.vue
@@ -108,25 +108,25 @@
      v-loading="loading"
      :data="donatebaseinfoList"
      border
      :default-sort="{ prop: 'donatetime', order: 'descending' }"
      :default-sort="{ prop: 'reporttime', order: 'descending' }"
      style="width: 100%; margin-top: 20px;"
    >
      <el-table-column
        label="上报时间"
        align="center"
        prop="donatetime"
        prop="reporttime"
        width="110"
        fixed="left"
      >
        <template slot-scope="scope">
          <span>{{ parseTime(scope.row.donatetime, "{y}-{m}-{d}") }}</span>
          <span>{{ parseTime(scope.row.reporttime, "{y}-{m}-{d}") }}</span>
        </template>
      </el-table-column>
      <el-table-column
        label="进度"
        label="捐献状态"
        align="center"
        prop="coreteamassessconclusion"
        prop="recordstate"
        width="100"
        fixed="left"
      >
@@ -141,7 +141,7 @@
      <el-table-column label="性别" align="center" prop="sex" width="80">
        <template slot-scope="scope">
          <span>{{ scope.row.sex === 1 ? "男" : "女" }}</span>
          <span>{{ scope.row.sex === "1" ? "男" : "女" }}</span>
        </template>
      </el-table-column>
@@ -155,34 +155,37 @@
      />
      <el-table-column
        label="治疗医院"
        align="center"
        prop="treatmenthospitalname"
        width="150"
      />
      <el-table-column
        label="协调员"
        align="center"
        prop="reportername"
        prop="coordinatorName"
        width="100"
      />
      <el-table-column
        label="转为案例时间"
        label="案例编号"
        align="center"
        prop="donatetime"
        width="110"
      >
        <template slot-scope="scope">
          <span>{{ parseTime(scope.row.donatetime, "{y}-{m}-{d}") }}</span>
        </template>
      </el-table-column>
        prop="caseNo"
        width="120"
      />
      <!-- 第一次医学评估 -->
      <el-table-column
        label="第一次评估结论"
        align="center"
        prop="coreteamassessconclusion"
        prop="firstAssessState"
        width="120"
      >
        <template slot-scope="scope">
          <dict-tag
            :options="dict.type.sys_BaseAssessConclusion"
            :value="scope.row.coreteamassessconclusion"
            :value="scope.row.firstAssessState"
          />
        </template>
      </el-table-column>
@@ -190,13 +193,11 @@
      <el-table-column
        label="第一次评估时间"
        align="center"
        prop="coreteamassesstime"
        prop="assessFirstTime"
        width="110"
      >
        <template slot-scope="scope">
          <span>{{
            parseTime(scope.row.coreteamassesstime, "{y}-{m}-{d}")
          }}</span>
          <span>{{ parseTime(scope.row.assessFirstTime, "{y}-{m}-{d}") }}</span>
        </template>
      </el-table-column>
@@ -204,13 +205,13 @@
      <el-table-column
        label="第二次评估结论"
        align="center"
        prop="coreteamassessconclusion"
        prop="secondAssessState"
        width="120"
      >
        <template slot-scope="scope">
          <dict-tag
            :options="dict.type.sys_BaseAssessConclusion"
            :value="scope.row.coreteamassessconclusion"
            :value="scope.row.secondAssessState"
          />
        </template>
      </el-table-column>
@@ -218,12 +219,12 @@
      <el-table-column
        label="第二次评估时间"
        align="center"
        prop="coreteamassesstime"
        prop="assessSecondTime"
        width="110"
      >
        <template slot-scope="scope">
          <span>{{
            parseTime(scope.row.coreteamassesstime, "{y}-{m}-{d}")
            parseTime(scope.row.assessSecondTime, "{y}-{m}-{d}")
          }}</span>
        </template>
      </el-table-column>
@@ -231,24 +232,24 @@
      <el-table-column
        label="亲属确认时间"
        align="center"
        prop="signdate"
        prop="signDate"
        width="110"
      >
        <template slot-scope="scope">
          <span>{{ parseTime(scope.row.signdate, "{y}-{m}-{d}") }}</span>
          <span>{{ parseTime(scope.row.signDate, "{y}-{m}-{d}") }}</span>
        </template>
      </el-table-column>
      <el-table-column
        label="伦理审查结论"
        align="center"
        prop="expertconclusion"
        prop="expertConclusion"
        width="120"
      >
        <template slot-scope="scope">
          <dict-tag
            :options="dict.type.sys_EthicalReview"
            :value="scope.row.expertconclusion"
            :value="scope.row.expertConclusion"
          />
        </template>
      </el-table-column>
@@ -256,30 +257,30 @@
      <el-table-column
        label="伦理审查时间"
        align="center"
        prop="conclusiontime"
        prop="expertTime"
        width="110"
      >
        <template slot-scope="scope">
          <span>{{ parseTime(scope.row.conclusiontime, "{y}-{m}-{d}") }}</span>
          <span>{{ parseTime(scope.row.expertTime, "{y}-{m}-{d}") }}</span>
        </template>
      </el-table-column>
      <el-table-column
        label="器官分配数量"
        align="center"
        prop="organcount"
        prop="organCount"
        width="100"
      />
      <el-table-column
        label="获取见证时间"
        align="center"
        prop="operationbegtime"
        prop="operationBegTime"
        width="110"
      >
        <template slot-scope="scope">
          <span>{{
            parseTime(scope.row.operationbegtime, "{y}-{m}-{d}")
            parseTime(scope.row.operationBegTime, "{y}-{m}-{d}")
          }}</span>
        </template>
      </el-table-column>
@@ -287,26 +288,26 @@
      <el-table-column
        label="完成登记时间"
        align="center"
        prop="completetime"
        prop="completeTime"
        width="110"
      >
        <template slot-scope="scope">
          <span>{{ parseTime(scope.row.completetime, "{y}-{m}-{d}") }}</span>
          <span>{{ parseTime(scope.row.completeTime, "{y}-{m}-{d}") }}</span>
        </template>
      </el-table-column>
      <!-- 捐献进度列 -->
      <el-table-column
        label="捐献进度"
        align="center"
        prop="workflow"
        prop="recordstate"
        width="120"
        fixed="right"
      >
        <template slot-scope="scope">
          <div v-if="!scope.row.terminationCase">
          <div v-if="scope.row.terminationCase == 0">
            <dict-tag
              :options="dict.type.sys_donornode"
              :value="scope.row.workflow"
              :value="scope.row.recordstate"
            />
          </div>
          <div v-else>
@@ -315,23 +316,24 @@
        </template>
      </el-table-column>
      <!-- <el-table-column label="操作" align="center" width="120" fixed="right">
      <!-- 操作列:只保留终止和查看详情 -->
      <el-table-column label="操作" align="center" width="150" fixed="right">
        <template slot-scope="scope">
          <el-button size="mini" type="text" @click="handleDetail(scope.row)"
            >查看详情</el-button
          >
          <el-button
            size="mini"
            type="text"
            icon="el-icon-view"
            @click="handleDetail(scope.row)"
          >详情</el-button>
          <el-button
            v-if="scope.row.recordstate == 0"
            size="mini"
            type="text"
            icon="el-icon-check"
            @click="handleApprove(scope.row)"
          >审核</el-button>
            style="color: #f56c6c;"
            @click="handleTerminate(scope.row)"
            v-if="
              scope.row.terminationCase === 0 && scope.row.recordstate !== '99'
            "
            >终止</el-button
          >
        </template>
      </el-table-column> -->
      </el-table-column>
    </el-table>
    <pagination
@@ -344,7 +346,7 @@
    <!-- 详情弹框 -->
    <el-dialog
      :title="`捐献者详情 - ${currentRecord.name}`"
      :title="`捐献者详情 - ${currentRecord.name || ''}`"
      :visible.sync="detailVisible"
      width="1000px"
      append-to-body
@@ -352,41 +354,32 @@
      <donor-detail :donorData="currentRecord" @close="detailVisible = false" />
    </el-dialog>
    <!-- 审核弹框 -->
    <!-- 终止确认弹框 -->
    <el-dialog
      title="捐献者审核"
      :visible.sync="approveVisible"
      width="500px"
      title="终止确认"
      :visible.sync="terminateVisible"
      width="400px"
      append-to-body
    >
      <el-form ref="approveForm" :model="approveForm" label-width="100px">
        <el-form-item label="审核结果">
          <el-radio-group v-model="approveForm.approveResult">
            <el-radio label="1">通过</el-radio>
            <el-radio label="2">驳回</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="审核意见">
          <el-input
            type="textarea"
            v-model="approveForm.approveOpinion"
            placeholder="请输入审核意见"
            :rows="4"
          />
        </el-form-item>
      </el-form>
      <div style="margin-bottom: 20px;">
        <p>
          确定要终止捐献者
          <strong>{{ currentRecord.name }}</strong> 的捐献进程吗?
        </p>
        <p style="color: #f56c6c; font-size: 12px;">
          此操作不可逆,请谨慎操作!
        </p>
      </div>
      <div slot="footer">
        <el-button @click="approveVisible = false">取消</el-button>
        <el-button type="primary" @click="submitApprove">确定</el-button>
        <el-button @click="terminateVisible = false">取消</el-button>
        <el-button type="danger" @click="submitTerminate">确认终止</el-button>
      </div>
    </el-dialog>
  </div>
</template>
<script>
// 导入模拟数据生成工具
import Mock from "mockjs";
import { courselist } from "@/api/businessApi";
import { courselist, terminateDonor } from "@/api/businessApi";
export default {
  name: "Donatebaseinfo",
@@ -403,8 +396,8 @@
      donatebaseinfoList: [],
      // 详情弹框显示
      detailVisible: false,
      // 审核弹框显示
      approveVisible: false,
      // 终止确认弹框显示
      terminateVisible: false,
      // 当前操作记录
      currentRecord: {},
      // 统计数据
@@ -421,11 +414,6 @@
        name: undefined,
        idcardno: undefined,
        recordstate: undefined
      },
      // 审核表单
      approveForm: {
        approveResult: "1",
        approveOpinion: ""
      }
    };
  },
@@ -433,96 +421,96 @@
    this.getList();
  },
  methods: {
    /** 生成模拟数据 */
    generateMockData() {
      const mockTemplate = {
        "list|15-30": [
          {
            "id|+1": 1001,
            name: "@cname",
            "sex|1": [1, 2], // 1:男, 2:女
            "age|18-65": 1,
            idcardno: /^[1-9]\d{5}(19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dX]$/,
            reportername: "@cname",
            treatmenthospitalname: "@ctitle(3, 5)医院",
            donatetime: '@datetime("yyyy-MM-dd HH:mm:ss")',
            "coreteamassessconclusion|1": ["1", "2", "3"], // 评估结论
            coreteamassesstime: '@datetime("yyyy-MM-dd HH:mm:ss")',
            signdate: '@datetime("yyyy-MM-dd HH:mm:ss")',
            "expertconclusion|1": ["1", "2", "3"], // 伦理审查结论
            conclusiontime: '@datetime("yyyy-MM-dd HH:mm:ss")',
            "organcount|0-5": 1,
            operationbegtime: '@datetime("yyyy-MM-dd HH:mm:ss")',
            completetime: '@datetime("yyyy-MM-dd HH:mm:ss")',
            "workflow|1": ["1", "2", "3", "4", "5"], // 工作流状态
            "recordstate|1": ["0", "1", "99"], // 0:待审核, 1:已审核, 99:已终止
            "terminationCase|1": [true, false]
          }
        ]
      };
      return Mock.mock(mockTemplate).list;
    },
    /** 查询捐献基础列表 */
    async getList() {
      this.loading = true;
      const response = await courselist(this.queryParams);
      // 模拟API调用延迟
      setTimeout(() => {
        // 生成模拟数据
        const mockData = this.generateMockData();
      try {
        const response = await courselist(this.queryParams);
        // 应用筛选条件
        let filteredData = mockData;
        if (this.queryParams.name) {
          filteredData = filteredData.filter(item =>
            item.name.includes(this.queryParams.name)
          );
        }
        if (this.queryParams.idcardno) {
          filteredData = filteredData.filter(item =>
            item.idcardno.includes(this.queryParams.idcardno)
          );
        }
        if (this.queryParams.recordstate) {
          filteredData = filteredData.filter(
            item => item.recordstate === this.queryParams.recordstate
          );
        }
        // 根据实际接口返回结构调整
        let realData = [];
        realData = response.data.donatebaseinfoProgressDTOS;
        this.total = response.total;
        this.stats.pendingCount = response.data.terminationCase[0];
        this.stats.approvedCount = response.data.terminationCase[1];
        this.stats.terminatedCount = response.data.terminationCase[2];
        this.stats.totalCount = response.total;
        // 存储所有数据用于前端筛选和分页
        this.allTableData = realData;
        // 分页处理
        const startIndex =
          (this.queryParams.pageNum - 1) * this.queryParams.pageSize;
        const endIndex = startIndex + this.queryParams.pageSize;
        this.donatebaseinfoList = filteredData.slice(startIndex, endIndex);
        this.total = filteredData.length;
        // 应用前端筛选条件(如果接口不支持后端筛选)
        let filteredData = this.applyFrontendFilter(realData);
        // 前端分页处理(如果接口不支持后端分页)
        if (!response.total && !response.data) {
          const startIndex =
            (this.queryParams.pageNum - 1) * this.queryParams.pageSize;
          const endIndex = startIndex + this.queryParams.pageSize;
          this.donatebaseinfoList = filteredData.slice(startIndex, endIndex);
          this.total = filteredData.length;
        } else {
          // 接口已分页,直接使用返回数据
          this.donatebaseinfoList = filteredData;
        }
        // 更新统计数据
        this.updateStats(mockData);
        // this.updateStats(realData);
      } catch (error) {
        console.error("获取数据失败:", error);
        this.$message.error("数据加载失败");
        this.donatebaseinfoList = [];
        this.total = 0;
        // this.updateStats([]);
      } finally {
        this.loading = false;
      }, 500);
      }
    },
    /** 应用前端筛选 */
    applyFrontendFilter(data) {
      let filteredData = data;
      if (this.queryParams.name) {
        filteredData = filteredData.filter(
          item => item.name && item.name.includes(this.queryParams.name)
        );
      }
      if (this.queryParams.idcardno) {
        filteredData = filteredData.filter(
          item =>
            item.idcardno && item.idcardno.includes(this.queryParams.idcardno)
        );
      }
      if (this.queryParams.recordstate) {
        filteredData = filteredData.filter(
          item => item.recordstate === this.queryParams.recordstate
        );
      }
      return filteredData;
    },
    /** 更新统计数据 */
    updateStats(data) {
      this.stats.totalCount = data.length;
      this.stats.pendingCount = data.filter(
        item => item.recordstate === "0"
        item => item.recordstate === "0" || item.recordstate === 0
      ).length;
      this.stats.approvedCount = data.filter(
        item => item.recordstate === "1"
        item => item.recordstate === "1" || item.recordstate === 1
      ).length;
      this.stats.terminatedCount = data.filter(
        item => item.recordstate === "99"
        item => item.recordstate === "99" || item.recordstate === 99
      ).length;
    },
    /** 获取状态标签样式 */
    getStatusTag(status) {
      const statusMap = {
        "0": "warning", // 待审核
        "1": "success", // 已审核
        "0": "warning", // 维护中
        "1": "success", // 已完成
        "99": "danger" // 已终止
      };
      return statusMap[status] || "info";
@@ -541,7 +529,11 @@
    /** 时间格式化 */
    parseTime(time, format) {
      if (!time) return "-";
      // 处理时间戳和日期字符串
      const date = new Date(time);
      if (isNaN(date.getTime())) return time;
      const year = date.getFullYear();
      const month = (date.getMonth() + 1).toString().padStart(2, "0");
      const day = date
@@ -563,13 +555,8 @@
    /** 重置按钮操作 */
    resetQuery() {
      this.queryParams = {
        pageNum: 1,
        pageSize: 10,
        name: undefined,
        idcardno: undefined,
        recordstate: undefined
      };
      this.$refs.queryForm.resetFields();
      this.queryParams.pageNum = 1;
      this.getList();
    },
@@ -579,29 +566,28 @@
      this.detailVisible = true;
    },
    /** 审核操作 */
    handleApprove(row) {
    /** 终止操作 */
    handleTerminate(row) {
      this.currentRecord = { ...row };
      this.approveForm = {
        approveResult: "1",
        approveOpinion: ""
      };
      this.approveVisible = true;
      this.terminateVisible = true;
    },
    /** 提交审核 */
    submitApprove() {
      // 模拟审核提交
      const index = this.donatebaseinfoList.findIndex(
        item => item.id === this.currentRecord.id
      );
      if (index !== -1) {
        this.donatebaseinfoList[
          index
        ].recordstate = this.approveForm.approveResult;
        this.$message.success("审核成功");
        this.approveVisible = false;
        this.getList(); // 重新加载更新统计
    /** 提交终止 */
    async submitTerminate() {
      try {
        // 调用终止接口
        await terminateDonor({
          id: this.currentRecord.id,
          caseNo: this.currentRecord.caseNo,
          terminationReason: "管理员手动终止"
        });
        this.$message.success("终止成功");
        this.terminateVisible = false;
        this.getList(); // 重新加载更新数据
      } catch (error) {
        this.$message.error("终止失败");
        console.error("终止错误:", error);
      }
    }
  }
@@ -678,4 +664,9 @@
  background-color: #f5f7fa;
  font-weight: bold;
}
/* 操作按钮样式 */
::v-deep .el-button--text {
  padding: 4px 8px;
}
</style>