WXL
2026-03-11 c441e5f3cb734b5db5e893536f267b13814796f5
青岛推送
已修改20个文件
已添加1个文件
3462 ■■■■ 文件已修改
src/api/businessApi/allocation.js 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/businessApi/ethicalReview.js 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main.js 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/ruoyi.js 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/GetWitness/index.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/OrganUtilization/index.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/affirm/affirmInfo.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/affirm/index.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/allocation/index.vue 154 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/appear/index.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/assess/assessInfo copy.vue 1306 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/assess/assessInfo.vue 939 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/assess/components/OrganAssessmentForm.vue 243 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/assess/index.vue 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/decide/DecideInfo.vue 268 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/decide/index.vue 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/ethicalReview/index.vue 305 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/maintain/index.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/maintain/maintainInfo.vue 23 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/transfer/index.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/login.vue 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/businessApi/allocation.js
@@ -0,0 +1,34 @@
import request from '@/utils/request'
// æ¡ˆä¾‹åˆ—表及详情
export function allocationList(data) {
  return request({
    url: '/project/donateorganBase/getDonateorganBaseInfoList',
    method: 'post',
    data: data
  })
}
// æ­»äº¡ä¿¡æ¯ä¿®æ”¹
export function allocationadd(data) {
  return request({
    url: '/project/donateorganBase/add',
    method: 'post',
    data: data
  })
}
// æ­»äº¡ä¿¡æ¯ä¿®æ”¹
export function allocationedit(data) {
  return request({
    url: '/project/donateorganBase/edit',
    method: 'post',
    data: data
  })
}
// æ­»äº¡ä¿¡æ¯è¯¦æƒ…
export function donateorganBaseinfoInfo(id) {
  return request({
    url: '/project/donateorganBase/getInfo/' + id,
    method: 'get'
  })
}
src/api/businessApi/ethicalReview.js
@@ -0,0 +1,34 @@
import request from '@/utils/request'
// æ¡ˆä¾‹åˆ—表及详情
export function reviewinitiateBaseInfoList(data) {
  return request({
    url: '/project/ethicalreviewinitiate/reviewinitiateBaseInfoList',
    method: 'post',
    data: data
  })
}
// æ­»äº¡ä¿¡æ¯ä¿®æ”¹
export function ethicalreviewadd(data) {
  return request({
    url: '/project/ethicalreviewinitiate/add',
    method: 'post',
    data: data
  })
}
// æ­»äº¡ä¿¡æ¯ä¿®æ”¹
export function ethicalreviewedit(data) {
  return request({
    url: '/project/ethicalreviewinitiate/edit',
    method: 'post',
    data: data
  })
}
// æ­»äº¡ä¿¡æ¯è¯¦æƒ…
export function ethicalinfoInfo(id) {
  return request({
    url: '/project/deathinfo/getInfo/' + id,
    method: 'get'
  })
}
src/main.js
@@ -25,7 +25,7 @@
import './permission' // permission control
import { getDicts } from "@/api/system/dict/data";
import { getConfigKey } from "@/api/system/config";
import { parseTime, resetForm, addDateRange, selectDictLabel, selectDictLabels, handleTree } from "@/utils/ruoyi";
import { parseTime, resetForm, addDateRange, selectDictLabel, selectDictLabels,donatebaseinfoEdit, handleTree } from "@/utils/ruoyi";
import { formatTime } from "@/utils/index";
import dataV from '@jiaminghi/data-view';//dataV
// åˆ†é¡µç»„ä»¶
@@ -66,6 +66,7 @@
Vue.prototype.getDicts = getDicts
Vue.prototype.getConfigKey = getConfigKey
Vue.prototype.parseTime = parseTime
Vue.prototype.donatebaseinfoEdit = donatebaseinfoEdit
Vue.prototype.formatTime = formatTime
Vue.prototype.resetForm = resetForm
Vue.prototype.addDateRange = addDateRange
src/utils/ruoyi.js
@@ -1,3 +1,5 @@
import { updateDonatebaseinfo } from "@/api/project/donatebaseinfo";
/**
 * é€šç”¨js方法封装处理
 * Copyright (c) 2019 ruoyi
@@ -6,22 +8,25 @@
// æ—¥æœŸæ ¼å¼åŒ–
export function parseTime(time, pattern) {
    if (arguments.length === 0 || !time) {
        return null
    return null;
    }
    const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}'
    let date
    if (typeof time === 'object') {
        date = time
  const format = pattern || "{y}-{m}-{d} {h}:{i}:{s}";
  let date;
  if (typeof time === "object") {
    date = time;
    } else {
        if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
            time = parseInt(time)
        } else if (typeof time === 'string') {
            time = time.replace(new RegExp(/-/gm), '/').replace('T', ' ').replace(new RegExp(/\.[\d]{3}/gm),'');
    if (typeof time === "string" && /^[0-9]+$/.test(time)) {
      time = parseInt(time);
    } else if (typeof time === "string") {
      time = time
        .replace(new RegExp(/-/gm), "/")
        .replace("T", " ")
        .replace(new RegExp(/\.[\d]{3}/gm), "");
        }
        if ((typeof time === 'number') && (time.toString().length === 10)) {
            time = time * 1000
    if (typeof time === "number" && time.toString().length === 10) {
      time = time * 1000;
        }
        date = new Date(time)
    date = new Date(time);
    }
    const formatObj = {
        y: date.getFullYear(),
@@ -31,19 +36,23 @@
        i: date.getMinutes(),
        s: date.getSeconds(),
        a: date.getDay()
    }
  };
    const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
        let value = formatObj[key]
    let value = formatObj[key];
        // Note: getDay() returns 0 on Sunday
        if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value] }
    if (key === "a") {
      return ["日", "一", "二", "三", "四", "五", "六"][value];
    }
        if (result.length > 0 && value < 10) {
            value = '0' + value
      value = "0" + value;
        }
        return value || 0
    })
    return time_str
    return value || 0;
  });
  return time_str;
}
export function donatebaseinfoEdit(data) {
  updateDonatebaseinfo(data);
}
// è¡¨å•重置
export function resetForm(refName) {
    if (this.$refs[refName]) {
@@ -54,14 +63,19 @@
// æ·»åŠ æ—¥æœŸèŒƒå›´
export function addDateRange(params, dateRange, propName) {
    let search = params;
    search.params = typeof (search.params) === 'object' && search.params !== null && !Array.isArray(search.params) ? search.params : {};
  search.params =
    typeof search.params === "object" &&
    search.params !== null &&
    !Array.isArray(search.params)
      ? search.params
      : {};
    dateRange = Array.isArray(dateRange) ? dateRange : [];
    if (typeof (propName) === 'undefined') {
        search.params['beginTime'] = dateRange[0];
        search.params['endTime'] = dateRange[1];
  if (typeof propName === "undefined") {
    search.params["beginTime"] = dateRange[0];
    search.params["endTime"] = dateRange[1];
    } else {
        search.params['begin' + propName] = dateRange[0];
        search.params['end' + propName] = dateRange[1];
    search.params["begin" + propName] = dateRange[0];
    search.params["end" + propName] = dateRange[1];
    }
    return search;
}
@@ -69,13 +83,13 @@
// å›žæ˜¾æ•°æ®å­—å…¸
export function selectDictLabel(datas, value) {
    var actions = [];
    Object.keys(datas).some((key) => {
        if (datas[key].value == ('' + value)) {
  Object.keys(datas).some(key => {
    if (datas[key].value == "" + value) {
            actions.push(datas[key].label);
            return true;
        }
    })
    return actions.join('');
  });
  return actions.join("");
}
// å›žæ˜¾æ•°æ®å­—典(字符串数组)
@@ -83,28 +97,30 @@
    var actions = [];
    var currentSeparator = undefined === separator ? "," : separator;
    var temp = value.split(currentSeparator);
    Object.keys(value.split(currentSeparator)).some((val) => {
        Object.keys(datas).some((key) => {
            if (datas[key].dictValue == ('' + temp[val])) {
  Object.keys(value.split(currentSeparator)).some(val => {
    Object.keys(datas).some(key => {
      if (datas[key].dictValue == "" + temp[val]) {
                actions.push(datas[key].dictLabel + currentSeparator);
            }
        })
    })
    return actions.join('').substring(0, actions.join('').length - 1);
    });
  });
  return actions.join("").substring(0, actions.join("").length - 1);
}
// å­—符串格式化(%s )
export function sprintf(str) {
    var args = arguments, flag = true, i = 1;
  var args = arguments,
    flag = true,
    i = 1;
    str = str.replace(/%s/g, function () {
        var arg = args[i++];
        if (typeof arg === 'undefined') {
    if (typeof arg === "undefined") {
            flag = false;
            return '';
      return "";
        }
        return arg;
    });
    return flag ? str : '';
  return flag ? str : "";
}
// è½¬æ¢å­—符串,undefined,null等转化为""
@@ -129,7 +145,7 @@
        }
    }
    return source;
};
}
/**
 * æž„造树型结构数据
@@ -140,9 +156,9 @@
 */
export function handleTree(data, id, parentId, children) {
    let config = {
        id: id || 'id',
        parentId: parentId || 'parentId',
        childrenList: children || 'children'
    id: id || "id",
    parentId: parentId || "parentId",
    childrenList: children || "children"
    };
    var childrenListMap = {};
src/views/business/GetWitness/index.vue
@@ -162,6 +162,7 @@
          label="操作"
          align="center"
          width="210"
          fixed="right"
          class-name="small-padding fixed-width"
        >
          <template slot-scope="scope">
src/views/business/OrganUtilization/index.vue
@@ -147,6 +147,7 @@
        </el-table-column>
        <el-table-column
          label="操作"
          fixed="right"
          align="center"
          width="210"
          class-name="small-padding fixed-width"
src/views/business/affirm/affirmInfo.vue
@@ -809,7 +809,7 @@
        if (response.code === 200) {
          this.$message.success("保存成功");
          this.$router.push("/case/confirmation");
          this.$router.push("/case/affirm");
        } else {
          this.$message.error("保存失败:" + (response.msg || "未知错误"));
        }
src/views/business/affirm/index.vue
@@ -203,6 +203,7 @@
          label="操作"
          align="center"
          width="120"
          fixed="right"
          class-name="small-padding fixed-width"
        >
          <template slot-scope="scope">
src/views/business/allocation/index.vue
@@ -8,19 +8,28 @@
        :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="caseNo">
          <el-input
            v-model="queryParams.caseNo"
            placeholder="请输入案例编号"
            clearable
            style="width: 200px"
            @keyup.enter.native="handleQuery"
@@ -33,9 +42,25 @@
            clearable
            style="width: 200px"
          >
            <el-option label="已分配" value="allocated" />
            <el-option label="待分配" value="pending" />
            <el-option label="全部" value="" />
            <el-option
              v-for="dict in dict.type.allocation_Status"
              :key="dict.value"
              :label="dict.label"
              :value="dict.value"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="分配时间范围" prop="allocationTimeRange">
          <el-date-picker
            v-model="queryParams.allocationTimeRange"
            type="daterange"
            range-separator="至"
            start-placeholder="开始日期"
            end-placeholder="结束日期"
            value-format="yyyy-MM-dd"
            style="width: 240px"
          />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" icon="el-icon-search" @click="handleQuery"
@@ -60,13 +85,13 @@
            @click="handleUpdate"
            >修改</el-button
          >
          <el-button
          <!-- <el-button
            type="danger"
            icon="el-icon-delete"
            :disabled="multiple"
            :disabled="single"
            @click="handleDelete"
            >删除</el-button
          >
          > -->
        </el-col>
        <el-col :span="8" style="text-align: right">
          <el-tooltip content="刷新" placement="top">
@@ -85,31 +110,62 @@
      >
        <el-table-column type="selection" width="55" align="center" />
        <el-table-column
          label="住院号"
          label="案例编号"
          align="center"
          prop="hospitalNo"
          prop="caseNo"
          width="120"
        />
        <el-table-column
          label="捐献者姓名"
          label="捐献者编号"
          align="center"
          prop="donorName"
          prop="donorno"
          width="120"
        />
        <el-table-column label="性别" align="center" prop="gender" width="80">
        <el-table-column
          label="姓名"
          align="center"
          prop="name"
          width="100"
        />
        <el-table-column
          label="住院号"
          align="center"
          prop="inpatientno"
          width="120"
        />
        <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="bloodtype"
          width="80"
        />
        <el-table-column
          label="证件号码"
          align="center"
          prop="idcardno"
          width="180"
        />
        <el-table-column
          label="疾病诊断"
          align="center"
          prop="diagnosis"
          prop="diagnosisname"
          min-width="180"
          show-overflow-tooltip
        />
        <el-table-column
          label="医疗机构"
          align="center"
          prop="treatmenthospitalname"
          min-width="150"
          show-overflow-tooltip
        />
        <el-table-column
@@ -119,9 +175,10 @@
          width="100"
        >
          <template slot-scope="scope">
            <el-tag :type="scope.row.allocationStatus === 'allocated' ? 'success' : 'warning'">
              {{ scope.row.allocationStatus === 'allocated' ? '已分配' : '待分配' }}
            </el-tag>
            <dict-tag
              :options="dict.type.allocation_Status"
              :value="scope.row.allocationStatus"
            />
          </template>
        </el-table-column>
        <el-table-column
@@ -141,7 +198,7 @@
        <el-table-column
          label="登记人"
          align="center"
          prop="registrant"
          prop="registrationName"
          width="100"
        />
        <el-table-column
@@ -162,6 +219,7 @@
          label="操作"
          align="center"
          width="210"
          fixed="right"
          class-name="small-padding fixed-width"
        >
          <template slot-scope="scope">
@@ -185,6 +243,7 @@
              icon="el-icon-delete"
              style="color: #F56C6C"
              @click="handleDelete(scope.row)"
              :disabled="scope.row.allocationStatus === '2'"
              >删除</el-button
            >
          </template>
@@ -204,19 +263,21 @@
</template>
<script>
import { listOrganAllocation, delOrganAllocation } from "./organAllocation";
import { allocationList,  } from "@/api/businessApi";
import Pagination from "@/components/Pagination";
export default {
  name: "OrganAllocationList",
  components: { Pagination },
  dicts: ["sys_user_sex"],
  dicts: ["sys_user_sex", "allocation_Status"],
  data() {
    return {
      // é®ç½©å±‚
      loading: true,
      // é€‰ä¸­æ•°ç»„
      ids: [],
      // é€‰ä¸­çš„行数据
      selectedRows: [],
      // éžå•个禁用
      single: true,
      // éžå¤šä¸ªç¦ç”¨
@@ -229,9 +290,11 @@
      queryParams: {
        pageNum: 1,
        pageSize: 10,
        hospitalNo: undefined,
        donorName: undefined,
        allocationStatus: undefined
        inpatientno: undefined,
        name: undefined,
        caseNo: undefined,
        allocationStatus: undefined,
        allocationTimeRange: []
      }
    };
  },
@@ -242,13 +305,28 @@
    // æŸ¥è¯¢å™¨å®˜åˆ†é…åˆ—表
    getList() {
      this.loading = true;
      listOrganAllocation(this.queryParams)
      // å¤„理查询参数
      const params = {
        ...this.queryParams
      };
      // ç§»é™¤åˆ†é¡µå‚数以外的额外参数
      delete params.allocationTimeRange;
      // å¦‚果有时间范围参数
      if (this.queryParams.allocationTimeRange && this.queryParams.allocationTimeRange.length === 2) {
        params.allocationTimeStart = this.queryParams.allocationTimeRange[0] + ' 00:00:00';
        params.allocationTimeEnd = this.queryParams.allocationTimeRange[1] + ' 23:59:59';
      }
      allocationList(params)
        .then(response => {
          if (response.code === 200) {
            this.organAllocationList = response.data.rows;
            this.total = response.data.total;
            this.organAllocationList = response.data || [];
            this.total = response.total || 0;
          } else {
            this.$message.error("获取数据失败");
            this.$message.error(response.msg || "获取数据失败");
          }
          this.loading = false;
        })
@@ -270,7 +348,8 @@
    },
    // å¤šé€‰æ¡†é€‰ä¸­æ•°æ®
    handleSelectionChange(selection) {
      this.ids = selection.map(item => item.id);
      this.ids = selection.map(item => item.infoid);
      this.selectedRows = selection;
      this.single = selection.length !== 1;
      this.multiple = !selection.length;
    },
@@ -278,7 +357,7 @@
    handleView(row) {
      this.$router.push({
        path: "/case/allocationInfo",
        query: { id: row.id }
        query: { id: row.infoid }
      });
    },
    // æ–°å¢žæŒ‰é’®æ“ä½œ
@@ -287,7 +366,7 @@
    },
    // ä¿®æ”¹æŒ‰é’®æ“ä½œ
    handleUpdate(row) {
      const id = row.id || this.ids[0];
      const id = row.infoid || this.ids[0];
      this.$router.push({
        path: "/case/allocationInfo",
        query: { id: id }
@@ -295,19 +374,26 @@
    },
    // åˆ é™¤æŒ‰é’®æ“ä½œ
    handleDelete(row) {
      const ids = row.id ? [row.id] : this.ids;
      const selectedRow = row || (this.selectedRows.length === 1 ? this.selectedRows[0] : null);
      if (!selectedRow) {
        this.$message.warning("请选择一条记录");
        return;
      }
      this.$confirm("是否确认删除选中的数据项?", "警告", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      })
        .then(() => {
          return delOrganAllocation(ids);
          // return allocationdelete([selectedRow.infoid]);
        })
        .then(response => {
          if (response.code === 200) {
            this.$message.success("删除成功");
            this.getList();
          } else {
            this.$message.error(response.msg || "删除失败");
          }
        })
        .catch(() => {});
src/views/business/appear/index.vue
@@ -139,6 +139,7 @@
      <el-table-column
        label="操作"
        align="center"
        fixed="right"
        class-name="small-padding fixed-width"
        width="200"
      >
src/views/business/assess/assessInfo copy.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,1306 @@
<template>
  <div class="assessment-detail">
    <el-card class="basic-info-card">
      <div slot="header" class="clearfix">
        <span>案例基本信息</span>
        <el-button
          style="float: right; padding: 3px 0"
          type="text"
          @click="handleAttachmentPreview"
        >
          <i class="el-icon-folder-opened"></i> æŸ¥çœ‹é™„ä»¶
        </el-button>
      </div>
      <el-descriptions :column="2" border>
        <el-descriptions-item label="住院号">{{
          assessmentData.caseNo
        }}</el-descriptions-item>
        <el-descriptions-item label="潜在捐献者姓名">{{
          assessmentData.name || assessmentData.donorName
        }}</el-descriptions-item>
        <el-descriptions-item label="性别">
          <dict-tag
            :options="dict.type.sys_user_sex"
            :value="assessmentData.sex"
          />
        </el-descriptions-item>
        <el-descriptions-item label="年龄"
          >{{ assessmentData.age }}岁</el-descriptions-item
        >
        <el-descriptions-item label="血型">
          {{ assessmentData.bloodtype }}
        </el-descriptions-item>
        <el-descriptions-item label="证件号码">{{
          assessmentData.idcardno
        }}</el-descriptions-item>
        <el-descriptions-item label="疾病诊断">{{
          assessmentData.diagnosisname
        }}</el-descriptions-item>
        <el-descriptions-item label="所在医疗机构">{{
          assessmentData.treatmenthospitalname
        }}</el-descriptions-item>
        <el-descriptions-item label="协调员">{{
          assessmentData.coordinatorName
        }}</el-descriptions-item>
        <el-descriptions-item label="评估时间">{{
          assessmentData.assessTime
        }}</el-descriptions-item>
        <el-descriptions-item label="评估状态">
          <el-tag :type="statusFilter(assessmentData.assessState)">
            {{ statusTextFilter(assessmentData.assessState) }}
          </el-tag>
        </el-descriptions-item>
      </el-descriptions>
    </el-card>
    <el-card class="organ-assessment-card">
      <div slot="header" class="clearfix">
        <span>器官评估表</span>
        <el-button
          v-if="isCoordinator && allOrgansAssessed"
          style="float: right; margin-left: 10px"
          type="primary"
          size="mini"
          @click="handleCompleteAssessment"
          :loading="saveLoading"
        >
          ç¡®è®¤å®Œæˆè¯„ä¼°
        </el-button>
        <span v-if="!isCoordinator" class="jstitle">
          å½“前角色:{{ currentDepartment }}评估人员
        </span>
      </div>
      <!-- æçŒ®å†³å®šè¡¨å• -->
      <el-form>
        <el-form-item label-width="100px" label="捐献决定">
          <el-checkbox-group
            v-model="organdecisionValues"
            @change="handleOrganDecisionChange"
            :disabled="!isEdit"
          >
            <el-checkbox
              v-for="dict in dict.type.sys_Organ"
              :key="dict.value"
              :label="dict.value"
              >{{ dict.label }}
            </el-checkbox>
          </el-checkbox-group>
          <el-input
            v-if="showOtherInput"
            v-model="organdecisionOther"
            placeholder="请输入其他捐献决定的具体内容"
            style="margin-top: 10px; width: 300px;"
            :readonly="!isEdit"
            @input="handleOtherDecisionInput"
          ></el-input>
        </el-form-item>
      </el-form>
      <!-- å™¨å®˜è¯„估表格 -->
      <el-table
        :data="filteredOrganAssessmentList"
        v-loading="assessmentLoading"
        style="width: 100%"
        :row-class-name="getRowClassName"
        :expand-row-keys="expandedRowKeys"
        @expand-change="handleExpandChange"
        row-key="organno"
        empty-text="当前捐献决定下暂无需要评估的器官"
      >
        <el-table-column type="expand">
          <template slot-scope="scope">
            <div class="organ-expand-content" v-if="scope.row.expanded">
              <el-tabs
                v-model="scope.row.activeTab"
                type="card"
                class="organ-detail-tabs"
                @tab-click="handleTabClick(scope.row, $event)"
              >
                <!-- åŠ¨æ€ç”Ÿæˆè¯„ä¼°Tab -->
                <el-tab-pane
                  v-for="(assessment, index) in scope.row.assessments"
                  :key="`${scope.row.organno}_${index}`"
                  :label="`第${index + 1}次评估`"
                  :name="`assessment_${index}`"
                >
                  <organ-assessment-form
                    :organ-data="scope.row"
                    :assessment-data="assessment"
                    :assessment-index="index"
                    :readonly="!canAssessOrgan(scope.row)"
                    @update-assessment="handleUpdateAssessment"
                    @delete-assessment="handleDeleteAssessment"
                  />
                </el-tab-pane>
                <!-- æ·»åŠ è¯„ä¼°æŒ‰é’® -->
                <el-tab-pane
                  name="add"
                  v-if="canAssessOrgan(scope.row) && isEdit"
                >
                  <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="器官类型">{{
                        getOrganLabel(scope.row.organno)
                      }}</el-descriptions-item>
                      <el-descriptions-item label="获取机构">{{
                        scope.row.gainhospitalname
                      }}</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-descriptions :column="1" border>
                        <el-descriptions-item label="获取前活检">
                          <el-tag
                            :type="
                              scope.row.isbiopsybefore === '1'
                                ? 'success'
                                : 'info'
                            "
                          >
                            {{ scope.row.isbiopsybefore === "1" ? "是" : "否" }}
                          </el-tag>
                        </el-descriptions-item>
                        <el-descriptions-item label="获取后活检">
                          <el-tag
                            :type="
                              scope.row.isbiopsyafter === '1'
                                ? 'success'
                                : 'info'
                            "
                          >
                            {{ scope.row.isbiopsyafter === "1" ? "是" : "否" }}
                          </el-tag>
                        </el-descriptions-item>
                        <el-descriptions-item label="边缘器官">
                          <el-tag
                            :type="
                              scope.row.ismarginalorgan === '1'
                                ? 'warning'
                                : 'info'
                            "
                          >
                            {{
                              scope.row.ismarginalorgan === "1" ? "是" : "否"
                            }}
                          </el-tag>
                        </el-descriptions-item>
                        <el-descriptions-item label="病原菌阳性">
                          <el-tag
                            :type="
                              scope.row.ispathogenpositive === '1'
                                ? 'danger'
                                : 'info'
                            "
                          >
                            {{
                              scope.row.ispathogenpositive === "1" ? "是" : "否"
                            }}
                          </el-tag>
                        </el-descriptions-item>
                      </el-descriptions>
                    </el-card>
                  </div>
                </el-tab-pane>
              </el-tabs>
            </div>
          </template>
        </el-table-column>
        <el-table-column label="器官类型" align="center" prop="organname">
          <template slot-scope="scope">
            {{ getOrganLabel(scope.row.organno) }}
          </template>
        </el-table-column>
        <el-table-column label="器官编号" align="center" prop="organnumber" />
        <el-table-column
          label="获取机构"
          align="center"
          prop="gainhospitalname"
          show-overflow-tooltip
        />
        <!-- åŠ¨æ€æ˜¾ç¤ºè¯„ä¼°çŠ¶æ€åˆ— -->
        <el-table-column
          v-for="(assessment, index) in getMaxAssessmentCount()"
          :key="index"
          :label="`第${index + 1}次评估`"
          align="center"
          width="120"
        >
          <template slot-scope="scope">
            <el-tag
              v-if="scope.row.assessments[index]"
              :type="getAssessmentTagType(scope.row.assessments[index].status)"
              size="small"
            >
              {{ 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="
                getOrganOverallStatus(scope.row) === 'completed'
                  ? 'success'
                  : getOrganOverallStatus(scope.row) === 'assessing'
                  ? 'primary'
                  : 'warning'
              "
              size="small"
            >
              {{ getOrganOverallStatusText(scope.row) }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column
          label="操作"
          align="center"
          width="150"
          class-name="small-padding fixed-width"
        >
          <template slot-scope="scope">
            <el-button
              v-if="canAssessOrgan(scope.row) && isEdit"
              size="mini"
              type="text"
              @click="handleToggleExpand(scope.row)"
            >
              {{
                expandedRowKeys.includes(scope.row.organno) ? "收起" : "详情"
              }}
            </el-button>
            <el-button
              v-else-if="!isEdit"
              size="mini"
              type="text"
              @click="handleToggleExpand(scope.row)"
            >
              {{
                expandedRowKeys.includes(scope.row.organno) ? "收起" : "查看"
              }}
            </el-button>
            <el-button v-else size="mini" type="text" disabled
              >无权限</el-button
            >
          </template>
        </el-table-column>
      </el-table>
    </el-card>
    <!-- æ•´ä½“保存按钮 -->
    <div class="footer-actions" v-if="isEdit">
      <el-button type="primary" @click="handleSaveAll" :loading="saveLoading"
        >保存评估表</el-button
      >
      <el-button @click="handleCancel">取消</el-button>
    </div>
    <!-- æ–‡ä»¶é¢„览弹窗 -->
    <FilePreviewDialog
      :visible="attachmentVisible"
      :file="currentPreviewFile"
      @close="attachmentVisible = false"
    />
  </div>
</template>
<script>
import {
  evaluateBaseInfolist,
  assessedit,
  assessAdd
} from "@/api/businessApi/index";
import FilePreviewDialog from "@/components/FilePreviewDialog";
import OrganAssessmentForm from "./components/OrganAssessmentForm.vue";
export default {
  name: "AssessmentDetail",
  components: { OrganAssessmentForm, FilePreviewDialog },
  dicts: ["sys_user_sex", "sys_Organ", "sys_0_1"],
  data() {
    return {
      // æ˜¯å¦ç¼–辑模式
      isEdit: false,
      // åŠ è½½çŠ¶æ€
      assessmentLoading: false,
      saveLoading: false,
      // æ•°æ®ID
      infoid: undefined,
      assessmentId: undefined,
      // ä¸»è¦æ•°æ®
      assessmentData: {},
      organAssessmentList: [], // æ‰€æœ‰å™¨å®˜æ•°æ®
      // å±•开行相关
      expandedRowKeys: [],
      // é™„件相关
      currentPreviewFile: null,
      attachmentVisible: false,
      // æçŒ®å†³å®šç›¸å…³
      organdecisionValues: [], // å­˜å‚¨å­—å…¸value
      organdecisionOther: "",
      // è®°å½•捐献决定变化前的值
      prevOrgandecisionValues: [],
      // å™¨å®˜ç±»åž‹æ˜ å°„关系
      organDecisionMapping: {
        // ä½¿ç”¨å­—å…¸value作为key
        C38: ["C38"], // å¿ƒè„ -> å¿ƒè„
        C22: ["C22"], // å…¨è‚ -> å…¨è‚
        C22L: ["C22L"], // å·¦åŠè‚ -> å·¦åŠè‚
        C22L0: ["C22L0"], // å·¦å¤–叶 -> å·¦å¤–叶
        C22R: ["C22R"], // å³åŠè‚ -> å³åŠè‚
        C22R0: ["C22R0"], // å³ä¸‰å¶ -> å³ä¸‰å¶
        C64: ["C64L", "C64R"], // åŒè‚¾ -> å·¦è‚¾, å³è‚¾
        C64L: ["C64L"], // å·¦è‚¾ -> å·¦è‚¾
        C64R: ["C64R"], // å³è‚¾ -> å³è‚¾
        C34: ["C34L", "C34R"], // å…¨è‚º -> å·¦è‚º, å³è‚º
        C34L: ["C34L"], // å·¦è‚º -> å·¦è‚º
        C34R: ["C34R"], // å³è‚º -> å³è‚º
        C17: ["C17"], // å°è‚  -> å°è‚ 
        C25: ["C25"], // èƒ°è…º -> èƒ°è…º
        C00: [], // é—体 -> ä¸æ˜ å°„具体器官(遗体是整体)
        C69L: ["C69L"], // å·¦çœ¼è§’膜 -> å·¦çœ¼è§’膜
        C69R: ["C69R"], // å³çœ¼è§’膜 -> å³çœ¼è§’膜
        C01: [] // å…¶ä»– -> ä¸æ˜ å°„具体器官
      },
      // ç”¨æˆ·ä¿¡æ¯
      currentUser: {
        id: "001",
        name: "张医生",
        department: "心脏科",
        role: "coordinator" // coordinator, doctor
      },
      // è®°å½•被删除的器官评估
      deletedOrganAssessments: [],
      // ç”¨äºŽè¿½è¸ªtab激活状态
      activeTabMap: new Map()
    };
  },
  computed: {
    isCoordinator() {
      return this.currentUser.role === "coordinator";
    },
    currentDepartment() {
      return this.currentUser.department;
    },
    // æ ¹æ®æçŒ®å†³å®šè¿‡æ»¤åŽçš„器官列表
    filteredOrganAssessmentList() {
      if (!this.organdecisionValues || this.organdecisionValues.length === 0) {
        return [];
      }
      // èŽ·å–æ‰€æœ‰é€‰ä¸­çš„å™¨å®˜ç±»åž‹
      const selectedOrgans = new Set();
      this.organdecisionValues.forEach(decision => {
        const organs = this.organDecisionMapping[decision] || [];
        organs.forEach(organ => selectedOrgans.add(organ));
      });
      // è¿‡æ»¤å™¨å®˜è¯„估列表,排除被删除的器官评估
      return this.organAssessmentList.filter(
        organ =>
          selectedOrgans.has(organ.organno) &&
          organ.delFlag !== "1" &&
          !this.deletedOrganAssessments.includes(organ.organno)
      );
    },
    // æ£€æŸ¥æ‰€æœ‰è¿‡æ»¤åŽçš„器官是否都已评估
    allOrgansAssessed() {
      return this.filteredOrganAssessmentList.every(
        organ =>
          organ.assessments &&
          organ.assessments.length > 0 &&
          organ.assessments.every(
            assessment => assessment.status === "assessed"
          )
      );
    },
    // èŽ·å–å™¨å®˜å­—å…¸
    organDict() {
      return this.dict.type.sys_Organ || [];
    },
    // åˆ¤æ–­æ˜¯å¦éœ€è¦æ˜¾ç¤ºå…¶ä»–输入框
    showOtherInput() {
      return this.organdecisionValues.includes("C01"); // å­—典中其他的value
    }
  },
  watch: {
    // ç›‘听捐献决定变化,用于复杂逻辑处理
    organdecisionValues: {
      handler(newVal, oldVal) {
        this.handleComplexDecisionChange(newVal, oldVal);
      },
      deep: true
    }
  },
  created() {
    this.infoid = this.$route.query.infoid;
    this.assessmentId = this.$route.query.id;
    this.isEdit = this.$route.query.assess === "true";
    this.getAssessmentDetail();
  },
  methods: {
    // æ ¹æ®å­—å…¸value获取label
    getOrganLabel(organValue) {
      const dictItem = this.organDict.find(item => item.value === organValue);
      return dictItem ? dictItem.label : organValue;
    },
    // Tab点击事件
    handleTabClick(organ, tab) {
      if (tab.name !== "add") {
        this.activeTabMap.set(organ.organno, tab.name);
      }
    },
    // å¤„理评估更新
    handleUpdateAssessment(data) {
      const { organData, assessmentData, assessmentIndex } = data;
      if (organData.assessments[assessmentIndex]) {
        this.$set(organData.assessments, assessmentIndex, {
          ...organData.assessments[assessmentIndex],
          ...assessmentData
        });
      }
    },
    // æ•´ä½“保存方法
    async handleSaveAll() {
      this.saveLoading = true;
      try {
        // 1. å‡†å¤‡ä¸»è¯„估表数据
        const saveData = {
          // æ ¹æ® id æ˜¯å¦å­˜åœ¨å†³å®šæ˜¯æ›´æ–°è¿˜æ˜¯æ–°å¢ž
          id: this.assessmentData.id || undefined,
          infoid: this.infoid,
          caseNo: this.assessmentData.caseNo,
          donorno: this.assessmentData.donorno,
          treatmenthospitalname: this.assessmentData.treatmenthospitalname,
          treatmenthospitalno: this.assessmentData.treatmenthospitalno,
          sex: this.assessmentData.sex,
          age: this.assessmentData.age,
          bloodtype: this.assessmentData.bloodtype,
          idcardno: this.assessmentData.idcardno,
          diagnosisname: this.assessmentData.diagnosisname,
          coordinatorName: this.assessmentData.coordinatorName,
          assessTime:
            this.assessmentData.assessTime || new Date().toISOString(),
          assessState: this.assessmentData.assessState,
          assessannex: this.assessmentData.assessannex,
          // æçŒ®å†³å®šä¿¡æ¯
          organdecision: this.organdecisionValues.join(","),
          organdecisionOther: this.organdecisionOther,
          // å™¨å®˜è¯„估列表
          serviceMedicalevaluationorganList: this.organAssessmentList.map(
            organ => ({
              id: organ.id,
              infoid: organ.infoid,
              donorno: organ.donorno,
              organno: organ.organno,
              organname: this.getOrganLabel(organ.organno), // ä¿å­˜label
              organnumber: organ.organnumber,
              gainhospitalno: organ.gainhospitalno,
              gainhospitalname: organ.gainhospitalname,
              isbiopsybefore: organ.isbiopsybefore,
              isbiopsyafter: organ.isbiopsyafter,
              ismarginalorgan: organ.ismarginalorgan,
              ispathogenpositive: organ.ispathogenpositive,
              ispnf: organ.ispnf,
              isdgf: organ.isdgf,
              delFlag: organ.delFlag || "0", // ä¿å­˜åˆ é™¤æ ‡å¿—
              // å°† assessments æ•°ç»„序列化到 assesscontent å­—段
              assesscontent: JSON.stringify(organ.assessments)
            })
          )
        };
        // 2. æ ¹æ® id åˆ¤æ–­è°ƒç”¨å“ªä¸ª API
        const saveMethod = this.assessmentData.id ? assessedit : assessAdd;
        const response = await saveMethod(saveData);
        if (response.code === 200) {
          this.$message.success("评估表保存成功!");
          // ä¿å­˜æˆåŠŸåŽï¼Œæ›´æ–°æœ¬åœ°çš„ assessmentData.id(对于新增情况)
          if (!this.assessmentData.id && response.data && response.data.id) {
            this.assessmentData.id = response.data.id;
          }
        } else {
          this.$message.error("保存失败:" + (response.msg || "未知错误"));
        }
      } catch (error) {
        console.error("保存评估表失败:", error);
        this.$message.error("保存失败,请重试");
      } finally {
        this.saveLoading = false;
      }
    },
    // å–消按钮事件
    handleCancel() {
      this.$router.go(-1);
    },
    // æçŒ®å†³å®šå˜æ›´å¤„理
    async handleOrganDecisionChange(newDecision) {
      // è®°å½•变更前的值
      const oldDecision = [...this.prevOrgandecisionValues];
      // è‡ªåŠ¨å¤„ç†ç›¸å…³é€»è¾‘
      this.autoHandleDecisionChange(newDecision);
      // å¤„理移除的决策
      const removedDecisions = oldDecision.filter(
        item => !newDecision.includes(item)
      );
      // å¯¹æ¯ä¸ªç§»é™¤çš„决定处理相关器官删除
      for (const decision of removedDecisions) {
        await this.handleRemovedDecision(decision);
      }
      // æ›´æ–°å˜æ›´å‰çš„记录
      this.prevOrgandecisionValues = [...newDecision];
      // å¼ºåˆ¶é‡æ–°æ¸²æŸ“
      this.$forceUpdate();
      // å¦‚果从有选择变为无选择,清空展开状态
      if (newDecision.length === 0) {
        this.expandedRowKeys = [];
      }
    },
    // å…¶ä»–捐献决定输入处理
    handleOtherDecisionInput(value) {
      // è¾“入时不做单独保存,等待整体保存
    },
    // è‡ªåŠ¨å¤„ç†å†³å®šå˜æ›´é€»è¾‘
    autoHandleDecisionChange(newDecision) {
      // å¦‚果选择了"双肾"(value: C64),自动取消单独的"左肾"(value: C64L)和"右肾"(value: C64R)选择
      if (newDecision.includes("C64")) {
        this.organdecisionValues = newDecision.filter(
          item => item !== "C64L" && item !== "C64R"
        );
      }
      // å¦‚果选择了"左肾"或"右肾",取消"双肾"选择
      else if (newDecision.includes("C64L") || newDecision.includes("C64R")) {
        this.organdecisionValues = newDecision.filter(item => item !== "C64");
      }
      // å¦‚果选择了"全肺"(value: C34),自动取消单独的"左肺"(value: C34L)和"右肺"(value: C34R)选择
      if (newDecision.includes("C34")) {
        this.organdecisionValues = newDecision.filter(
          item => item !== "C34L" && item !== "C34R"
        );
      }
      // å¦‚果选择了"左肺"或"右肺",取消"全肺"选择
      else if (newDecision.includes("C34L") || newDecision.includes("C34R")) {
        this.organdecisionValues = newDecision.filter(item => item !== "C34");
      }
      // å¤„理其他互斥逻辑
      this.handleExclusiveDecisions();
    },
    // å¤„理互斥的捐献决定
    handleExclusiveDecisions() {
      // é—体捐献(value: 10)与其他器官捐献互斥(根据业务需求调整)
      if (this.organdecisionValues.includes("10")) {
        // å¯ä»¥è®¾ç½®åªä¿ç•™é—体捐献,或者根据业务需求处理
      }
    },
    // å¤æ‚决策变化处理
    handleComplexDecisionChange(newVal, oldVal) {
      // å¤„理新增的选择
      const addedDecisions = newVal.filter(item => !oldVal.includes(item));
      // å¯¹æ–°å¢žåŠ çš„é€‰æ‹©è¿›è¡Œç‰¹æ®Šå¤„ç†
      addedDecisions.forEach(decision => {
        this.handleNewDecision(decision);
      });
    },
    // å¤„理新增的捐献决定
    handleNewDecision(decision) {
      // æ ¹æ®æ˜ å°„关系自动创建对应的器官评估项
      this.autoCreateOrganAssessments(decision);
    },
    // è‡ªåŠ¨åˆ›å»ºå™¨å®˜è¯„ä¼°é¡¹
    autoCreateOrganAssessments(decision) {
      const organsToCreate = this.organDecisionMapping[decision];
      if (organsToCreate && organsToCreate.length > 0) {
        organsToCreate.forEach(organValue => {
          this.ensureOrganExists(organValue);
        });
        // æ˜¾ç¤ºåˆ›å»ºæç¤º
        if (organsToCreate.length > 0) {
          this.$message.success(
            `已为【${this.getOrganLabel(decision)}】创建${
              organsToCreate.length
            }个评估项`
          );
        }
      } else {
        console.warn(
          `捐献决定【${this.getOrganLabel(decision)}】没有配置器官映射关系`
        );
      }
    },
    // å¤„理移除的捐献决定
    async handleRemovedDecision(decision) {
      const relatedOrgans = this.organDecisionMapping[decision] || [];
      for (const organValue of relatedOrgans) {
        // æŸ¥æ‰¾å¯¹åº”的器官评估项
        const organIndex = this.organAssessmentList.findIndex(
          organ => organ.organno === organValue && organ.delFlag !== "1"
        );
        if (organIndex !== -1) {
          const organ = this.organAssessmentList[organIndex];
          const organLabel = this.getOrganLabel(organValue);
          try {
            await this.$confirm(
              `捐献决定"${this.getOrganLabel(
                decision
              )}"已取消,是否删除对应的${organLabel}评估记录?`,
              "确认删除",
              {
                confirmButtonText: "确定",
                cancelButtonText: "取消",
                type: "warning"
              }
            );
            // æ ‡è®°ä¸ºåˆ é™¤
            this.$set(this.organAssessmentList[organIndex], "delFlag", "1");
            this.deletedOrganAssessments.push(organValue);
            // ä»Žå±•开行中移除
            const keyIndex = this.expandedRowKeys.indexOf(organValue);
            if (keyIndex > -1) {
              this.expandedRowKeys.splice(keyIndex, 1);
            }
            this.$message.success(`${organLabel}评估记录已标记删除`);
          } catch (cancelError) {
            // ç”¨æˆ·å–消删除,恢复选择
            if (!this.organdecisionValues.includes(decision)) {
              this.organdecisionValues.push(decision);
            }
            this.$message.info(`已取消删除${organLabel}评估记录`);
          }
        }
      }
    },
    // ç¡®ä¿å™¨å®˜å­˜åœ¨ï¼ˆå¸¦é‡å¤æ£€æŸ¥ï¼‰
    ensureOrganExists(organValue) {
      // æ£€æŸ¥æ˜¯å¦å·²å­˜åœ¨åŒç¼–号的器官评估项
      const exists = this.organAssessmentList.some(
        organ => organ.organno === organValue && organ.delFlag !== "1"
      );
      if (!exists) {
        // åˆ›å»ºæ–°çš„器官评估项
        const newOrgan = {
          id: null,
          organno: organValue, // ä½¿ç”¨å­—å…¸value
          organname: this.getOrganLabel(organValue), // ä½¿ç”¨å­—å…¸label
          gainhospitalname: "待分配机构",
          isbiopsybefore: "0",
          isbiopsyafter: "0",
          ismarginalorgan: "0",
          ispathogenpositive: "0",
          assessments: [this.getDefaultAssessment(0)],
          activeTab: "assessment_0", // ç»Ÿä¸€ä½¿ç”¨activeTab
          expanded: false,
          createTime: new Date().toISOString(),
          delFlag: "0"
        };
        this.organAssessmentList = [...this.organAssessmentList, newOrgan];
        return true;
      }
      return false;
    },
    // èŽ·å–è¯„ä¼°è¯¦æƒ…
    async getAssessmentDetail() {
      this.assessmentLoading = true;
      try {
        const response = await evaluateBaseInfolist({ infoid: this.infoid });
        if (response.code === 200) {
          this.handleResponseData(response);
        } else {
          this.$message.error("获取详情失败:" + (response.msg || "未知错误"));
        }
      } catch (error) {
        console.error("获取评估详情失败:", error);
        this.$message.error("获取详情失败");
      } finally {
        this.assessmentLoading = false;
      }
    },
    // å¤„理接口响应数据
    handleResponseData(response) {
      let detailData = null;
      // æ ¹æ®æŽ¥å£å®žé™…返回的数据结构进行调整
      if (response.data) {
        if (Array.isArray(response.data)) {
          detailData = response.data[0] || {};
        } else if (response.data.rows && Array.isArray(response.data.rows)) {
          detailData = response.data.rows[0] || {};
        } else if (Array.isArray(response.data.list)) {
          detailData = response.data.list[0] || {};
        } else {
          detailData = response.data;
        }
      } else {
        detailData = response;
      }
      // æ˜ å°„字段到评估数据
      this.assessmentData = {
        id: detailData.id || this.assessmentId,
        infoid: detailData.infoid || this.infoid,
        caseNo: detailData.caseNo || "",
        name: detailData.name || detailData.donorName || "",
        sex: detailData.sex || "",
        age: detailData.age || "",
        bloodtype: detailData.bloodtype || "",
        idcardno: detailData.idcardno || "",
        diagnosisname: detailData.diagnosisname || "",
        treatmenthospitalname: detailData.treatmenthospitalname || "",
        coordinatorName: detailData.coordinatorName || "",
        assessTime: detailData.assessTime || "",
        assessState: detailData.assessState || "1",
        assessannex: detailData.assessannex || ""
      };
      // å¤„理捐献决定数据
      if (detailData.organdecision) {
        const decisionArray = Array.isArray(detailData.organdecision)
          ? detailData.organdecision
          : (detailData.organdecision || "").split(",").filter(item => item);
        this.organdecisionValues = decisionArray;
        this.prevOrgandecisionValues = [...decisionArray]; // åˆå§‹åŒ–prevOrgandecisionValues
        this.organdecisionOther = detailData.organdecisionOther || "";
      }
      // å¤„理器官评估数据
      this.processOrganAssessmentData(detailData);
    },
    // å¤„理器官评估数据
    processOrganAssessmentData(detailData) {
      let organList = [];
      // ä»ŽæŽ¥å£æ•°æ®ä¸­èŽ·å–å™¨å®˜è¯„ä¼°åˆ—è¡¨
      if (detailData.serviceMedicalevaluationorganList) {
        if (Array.isArray(detailData.serviceMedicalevaluationorganList)) {
          organList = detailData.serviceMedicalevaluationorganList;
        }
      }
      // è½¬æ¢å™¨å®˜æ•°æ®æ ¼å¼ï¼Œæ”¯æŒå¤šæ¬¡è¯„ä¼°
      this.organAssessmentList = organList.map(organ => {
        let assessments = [];
        // è§£æžassesscontent字段中的多次评估数据
        if (organ.assesscontent) {
          try {
            const assessData =
              typeof organ.assesscontent === "string"
                ? JSON.parse(organ.assesscontent)
                : organ.assesscontent;
            console.log(assessData, "assessData");
            if (Array.isArray(assessData)) {
              // è¿‡æ»¤æŽ‰å·²åˆ é™¤çš„评估
              const validAssessments = assessData.filter(
                item => item.delFlag !== "1"
              );
              console.log(validAssessments,'validAssessments');
              // assessments.push(
              //   ...validAssessments.map((item, index) => ({
              //     ...item,
              //     index: index,
              //     status: item.status || "assessed",
              //     delFlag: item.delFlag || "0"
              //   }))
              // );
              assessments = validAssessments;
            }
          } catch (error) {
            console.warn("解析评估内容失败:", error);
            assessments.push(this.getDefaultAssessment(0));
          }
        } else {
          assessments.push(this.getDefaultAssessment(0));
        }
        const organno = organ.organno;
        const activeTab = this.activeTabMap.has(organno)
          ? this.activeTabMap.get(organno)
          : assessments.length > 0
          ? "assessment_0"
          : "summary";
        return {
          ...organ,
          // ç¡®ä¿organname使用字典label
          organname: this.getOrganLabel(organ.organno) || organ.organname,
          assessments: assessments,
          activeTab: activeTab,
          expanded: false,
          delFlag: organ.delFlag || "0"
        };
      });
      console.log(this.organAssessmentList, "this.organAssessmentList");
    },
    // èŽ·å–é»˜è®¤è¯„ä¼°æ•°æ®ç»“æž„
    getDefaultAssessment(index) {
      return {
        index: index,
        status: "pending",
        assessmentTime: "",
        assessor: "",
        functionStatus: "",
        assessmentOpinion: "",
        clinicalData: {},
        labResults: {},
        createTime: new Date().toISOString(),
        delFlag: "0"
      };
    },
    // è®¡ç®—最大评估次数
    getMaxAssessmentCount() {
      const maxCount = Math.max(
        ...this.organAssessmentList
          .filter(organ => organ.delFlag !== "1")
          .map(organ => (organ.assessments ? organ.assessments.length : 0))
      );
      return Math.max(maxCount, 1);
    },
    // èŽ·å–å™¨å®˜æ•´ä½“çŠ¶æ€
    getOrganOverallStatus(organ) {
      if (!organ.assessments || organ.assessments.length === 0) {
        return "pending";
      }
      const validAssessments = organ.assessments.filter(a => a.delFlag !== "1");
      if (validAssessments.length === 0) {
        return "pending";
      }
      const allAssessed = validAssessments.every(
        assessment => assessment.status === "assessed"
      );
      const someAssessed = validAssessments.some(
        assessment => assessment.status === "assessed"
      );
      if (allAssessed) return "completed";
      if (someAssessed) return "assessing";
      return "pending";
    },
    getOrganOverallStatusText(organ) {
      const status = this.getOrganOverallStatus(organ);
      const statusMap = {
        pending: "待评估",
        assessing: "评估中",
        completed: "已完成"
      };
      return statusMap[status] || "未知";
    },
    // åˆ‡æ¢å±•开行
    handleToggleExpand(row) {
      const key = row.organno;
      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.organno === key;
        });
      }
    },
    // å±•开行变化
    handleExpandChange(row, expandedRows) {
      this.expandedRowKeys = expandedRows.map(item => item.organno);
      this.organAssessmentList.forEach(item => {
        item.expanded = this.expandedRowKeys.includes(item.organno);
      });
    },
    // æ·»åŠ æ–°è¯„ä¼°
    handleAddNewAssessment(organ) {
      const newAssessment = {
        ...this.getDefaultAssessment(organ.assessments.length),
        assessor: this.currentUser.name
      };
      organ.assessments.push(newAssessment);
      // åˆ‡æ¢åˆ°æ–°æ·»åŠ çš„è¯„ä¼°tab
      organ.activeTab = `assessment_${organ.assessments.length - 1}`;
      this.activeTabMap.set(organ.organno, organ.activeTab);
      this.$message.success("已添加新的评估");
    },
    // å¤„理评估更新事件
    handleUpdateAssessment(data) {
      const { organData, assessmentData, assessmentIndex } = data;
      if (organData.assessments[assessmentIndex]) {
        this.$set(organData.assessments, assessmentIndex, {
          ...organData.assessments[assessmentIndex],
          ...assessmentData
        });
      }
    },
    // å¤„理删除评估事件
    handleDeleteAssessment(data) {
      const { organData, assessmentIndex } = data;
      this.deleteOrganAssessment(organData, assessmentIndex);
    },
    // åˆ é™¤å™¨å®˜è¯„ä¼°
    async deleteOrganAssessment(organ, assessmentIndex) {
      try {
        await this.$confirm(
          `确认删除第${assessmentIndex + 1}次评估记录吗?`,
          "确认删除",
          {
            confirmButtonText: "确定",
            cancelButtonText: "取消",
            type: "warning"
          }
        );
        // æ ‡è®°è¯„估为删除
        if (organ.assessments[assessmentIndex]) {
          this.$set(organ.assessments[assessmentIndex], "delFlag", "1");
          // è¿‡æ»¤æŽ‰å·²åˆ é™¤çš„评估
          organ.assessments = organ.assessments.filter(
            item => item.delFlag !== "1"
          );
          // é‡æ–°è®¡ç®—评估索引
          organ.assessments.forEach((assessment, index) => {
            assessment.index = index;
          });
          // å¦‚果删除后没有评估了,显示汇总页
          if (organ.assessments.length === 0) {
            organ.activeTab = "summary";
            this.activeTabMap.set(organ.organno, "summary");
          } else if (organ.activeTab === `assessment_${assessmentIndex}`) {
            // å¦‚果当前激活的就是被删除的tab,切换到前一个
            const newIndex = Math.max(0, assessmentIndex - 1);
            organ.activeTab = `assessment_${newIndex}`;
            this.activeTabMap.set(organ.organno, `assessment_${newIndex}`);
          } else if (organ.activeTab === "summary") {
            this.activeTabMap.set(organ.organno, "summary");
          }
          this.$message.success("评估记录已删除");
        }
      } catch (cancelError) {
        // ç”¨æˆ·å–消删除
        this.$message.info("已取消删除");
      }
    },
    // èŽ·å–æœ€æ–°è¯„ä¼°æ—¶é—´
    getLatestAssessmentTime(organ) {
      if (!organ.assessments || organ.assessments.length === 0) return null;
      const assessed = organ.assessments.filter(
        a => a.assessmentTime && a.delFlag !== "1"
      );
      if (assessed.length === 0) return null;
      return assessed.sort(
        (a, b) => new Date(b.assessmentTime) - new Date(a.assessmentTime)
      )[0].assessmentTime;
    },
    // èŽ·å–è¯„ä¼°çŠ¶æ€æ ‡ç­¾ç±»åž‹
    getAssessmentTagType(status) {
      const typeMap = {
        pending: "warning",
        assessing: "primary",
        assessed: "success"
      };
      return typeMap[status] || "info";
    },
    // èŽ·å–è¯„ä¼°çŠ¶æ€æ–‡æœ¬
    getAssessmentStatusText(status) {
      const textMap = {
        pending: "待评估",
        assessing: "评估中",
        assessed: "已评估"
      };
      return textMap[status] || "未知";
    },
    // æ£€æŸ¥è¯„估权限
    canAssessOrgan(organ) {
      if (this.isCoordinator) return true;
      if (!this.isEdit) return false;
      return (
        organ.gainhospitalname &&
        organ.gainhospitalname.includes(this.currentDepartment)
      );
    },
    // èŽ·å–è¡Œç±»å
    getRowClassName({ row }) {
      return this.canAssessOrgan(row) ? "assessable-row" : "non-assessable-row";
    },
    // çŠ¶æ€è¿‡æ»¤å™¨
    statusFilter(status) {
      const statusMap = {
        "1": "warning",
        "2": "primary",
        "3": "success"
      };
      return statusMap[status] || "info";
    },
    statusTextFilter(status) {
      const statusMap = {
        "1": "待评估",
        "2": "评估中",
        "3": "已完成"
      };
      return statusMap[status] || "未知";
    },
    // æŸ¥çœ‹é™„ä»¶
    handleAttachmentPreview() {
      if (this.assessmentData.assessannex) {
        try {
          const annexData =
            typeof this.assessmentData.assessannex === "string"
              ? JSON.parse(this.assessmentData.assessannex)
              : this.assessmentData.assessannex;
          if (Array.isArray(annexData) && annexData.length > 0) {
            this.currentPreviewFile = annexData[0];
            this.attachmentVisible = true;
          } else {
            this.$message.info("暂无附件可预览");
          }
        } catch (error) {
          this.$message.info("附件数据格式错误");
        }
      } else {
        this.$message.info("暂无附件");
      }
    },
    // å®Œæˆè¯„ä¼°
    async handleCompleteAssessment() {
      try {
        await this.$confirm(
          "确认完成所有器官评估吗?完成后将无法修改",
          "确认操作",
          {
            confirmButtonText: "确定",
            cancelButtonText: "取消",
            type: "warning"
          }
        );
        // æ›´æ–°è¯„估状态为已完成
        const updateData = {
          ...this.assessmentData,
          assessState: "3",
          assessTime: new Date().toISOString()
        };
        const response = await assessedit(updateData);
        if (response.code === 200) {
          this.$message.success("评估完成确认成功");
          this.assessmentData.assessState = "3";
          this.isEdit = false;
        } else {
          this.$message.error("操作失败:" + (response.msg || "未知错误"));
        }
      } catch (error) {
        if (error !== "cancel") {
          console.error("完成评估失败:", error);
          this.$message.error("操作失败");
        }
      }
    }
  }
};
</script>
<style scoped>
.assessment-detail {
  padding: 20px;
}
.basic-info-card {
  margin-bottom: 20px;
}
.organ-assessment-card {
  margin-bottom: 20px;
}
/* å±•开行样式 */
.organ-expand-content {
  padding: 20px;
  background: #fafafa;
  border-radius: 4px;
  margin: 10px 0;
}
.organ-detail-tabs {
  background: white;
  border-radius: 4px;
  padding: 20px;
}
.add-assessment-prompt {
  text-align: center;
  padding: 40px 0;
}
.assessment-summary {
  padding: 10px;
}
/* åº•部保存按钮样式 */
.footer-actions {
  margin-top: 20px;
  text-align: center;
  padding: 20px;
  border-top: 1px solid #eaeaea;
}
/* å“åº”式设计 */
@media (max-width: 768px) {
  .assessment-detail {
    padding: 10px;
  }
  .organ-expand-content {
    padding: 10px;
  }
}
::v-deep .assessable-row {
  background-color: #f0f9ff;
}
::v-deep .non-assessable-row {
  background-color: #fafafa;
}
.jstitle {
  float: right;
  font-size: 18px !important;
  font-weight: 600;
  color: #2645f7;
  font-size: 12px;
}
/* è¡¨æ ¼å±•开图标样式 */
::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;
}
.fixed-width .el-button {
  margin: 0 2px;
}
/* æçŒ®å†³å®šæ ·å¼ä¼˜åŒ– */
.organ-decision-info {
  margin: 10px 0;
  padding: 10px;
  background-color: #f8f9fa;
  border-radius: 4px;
  border-left: 4px solid #409eff;
}
.decision-tag {
  margin: 2px 5px;
}
</style>
src/views/business/assess/assessInfo.vue
@@ -76,19 +76,19 @@
      <el-form>
        <el-form-item label-width="100px" label="捐献决定">
          <el-checkbox-group
            v-model="organdecision"
            v-model="organdecisionValues"
            @change="handleOrganDecisionChange"
            :disabled="!isEdit"
          >
            <el-checkbox
              v-for="item in organselection"
              :key="item"
              :label="item"
              >{{ item }}
              v-for="dict in dict.type.sys_Organ"
              :key="dict.value"
              :label="dict.value"
              >{{ dict.label }}
            </el-checkbox>
          </el-checkbox-group>
          <el-input
            v-if="organdecision.includes('其他')"
            v-if="showOtherInput"
            v-model="organdecisionOther"
            placeholder="请输入其他捐献决定的具体内容"
            style="margin-top: 10px; width: 300px;"
@@ -113,23 +113,26 @@
          <template slot-scope="scope">
            <div class="organ-expand-content" v-if="scope.row.expanded">
              <el-tabs
                v-model="scope.row.activeAssessmentTab"
                v-model="scope.row.activeTab"
                type="card"
                class="organ-detail-tabs"
                @tab-click="handleTabClick(scope.row, $event)"
              >
                <!-- åŠ¨æ€ç”Ÿæˆè¯„ä¼°Tab -->
                <el-tab-pane
                  v-for="(assessment, index) in scope.row.assessments"
                  :key="index"
                  v-for="(assessment, index) in getOrganAssessments(scope.row)"
                  :key="`${scope.row.organno}_${index}`"
                  :label="`第${index + 1}次评估`"
                  :name="`assessment_${index}`"
                  :name="index"
                >
                  <organ-assessment-form
                    :organ-data="scope.row"
                    :assessment-data="assessment"
                    :assessment-index="index"
                    :readonly="!canAssessOrgan(scope.row)"
                    @add-assessment="handleAddAssessment"
                    :current-user="currentUser"
                    @update-assessment="handleUpdateAssessment"
                    @delete-assessment="handleDeleteAssessment"
                    @save-assessment="handleSaveAssessment"
                  />
                </el-tab-pane>
@@ -156,26 +159,95 @@
                <!-- è¯„估汇总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.gainhospitalname
                      }}</el-descriptions-item>
    <!-- åŸºæœ¬ä¿¡æ¯æ±‡æ€» -->
    <el-descriptions title="基本信息汇总" :column="2" border>
      <el-descriptions-item label="器官类型">
        <span class="summary-item">{{ getOrganLabel(scope.row.organno) }}</span>
      </el-descriptions-item>
      <el-descriptions-item label="获取机构">
        <span class="summary-item">{{ scope.row.gainhospitalname }}</span>
      </el-descriptions-item>
                      <el-descriptions-item label="评估次数" :span="2">
                        <el-tag type="info"
                          >{{ scope.row.assessments.length }}次</el-tag
                        >
        <el-tag type="info" size="medium">
          {{ getAssessmentCount(scope.row) }}次
        </el-tag>
                      </el-descriptions-item>
                      <el-descriptions-item label="最新评估时间" :span="2">
                        {{ getLatestAssessmentTime(scope.row) || "-" }}
        <span class="highlight-text">{{ getLatestAssessmentTime(scope.row) || "-" }}</span>
                      </el-descriptions-item>
                    </el-descriptions>
                    <!-- è¯„估详情汇总 -->
                    <el-card header="评估详情" style="margin-top: 20px;">
                      <el-descriptions :column="1" border>
    <el-card header="评估详情列表" style="margin-top: 20px;" class="assessment-detail-card">
      <div v-if="getOrganAssessments(scope.row).length === 0" class="no-assessment">
        <el-empty description="暂无评估记录"></el-empty>
      </div>
      <div v-else>
        <!-- æ¯æ¬¡è¯„估详情 -->
        <div v-for="(assessment, index) in getOrganAssessments(scope.row)"
             :key="index"
             class="assessment-item">
          <el-card shadow="hover" class="assessment-card">
            <div slot="header" class="clearfix">
              <span class="assessment-title">第{{ index + 1 }}次评估</span>
              <el-tag
                :type="getAssessmentTagType(assessment.status)"
                size="small"
                class="status-tag"
              >
                {{ getAssessmentStatusText(assessment.status) }}
              </el-tag>
            </div>
            <el-descriptions :column="2" border class="detail-descriptions">
              <el-descriptions-item label="评估时间" :span="2">
                <span class="time-text">{{ assessment.assessmentTime || "-" }}</span>
              </el-descriptions-item>
              <el-descriptions-item label="评估人">
                <el-tag type="info" size="small">
                  {{ assessment.assessor || "未填写" }}
                </el-tag>
              </el-descriptions-item>
              <el-descriptions-item label="功能状态">
                <el-tag
                  :type="getFunctionStatusTagType(assessment.functionStatus)"
                  size="small"
                >
                  {{ getFunctionStatusText(assessment.functionStatus) }}
                </el-tag>
              </el-descriptions-item>
              <el-descriptions-item label="评估意见" :span="2">
                <div class="opinion-content">
                  {{ assessment.assessmentOpinion || "暂无评估意见" }}
                </div>
              </el-descriptions-item>
              <el-descriptions-item label="附件数量" :span="2" v-if="assessment.attachments && assessment.attachments.length > 0">
                <el-tag type="success" size="small">
                  {{ assessment.attachments.length }}个
                </el-tag>
                <el-button
                  type="text"
                  size="mini"
                  @click="showAttachmentList(assessment.attachments, index + 1)"
                  style="margin-left: 10px;"
                >
                  æŸ¥çœ‹é™„件列表
                </el-button>
              </el-descriptions-item>
            </el-descriptions>
          </el-card>
        </div>
      </div>
    </el-card>
    <!-- å™¨å®˜åŸºæœ¬ä¿¡æ¯å¡ç‰‡ -->
    <el-card header="器官信息" style="margin-top: 20px;" class="organ-info-card">
      <el-descriptions :column="2" border>
                        <el-descriptions-item label="获取前活检">
                          <el-tag
                            :type="
@@ -183,6 +255,7 @@
                                ? 'success'
                                : 'info'
                            "
            size="small"
                          >
                            {{ scope.row.isbiopsybefore === "1" ? "是" : "否" }}
                          </el-tag>
@@ -194,6 +267,7 @@
                                ? 'success'
                                : 'info'
                            "
            size="small"
                          >
                            {{ scope.row.isbiopsyafter === "1" ? "是" : "否" }}
                          </el-tag>
@@ -205,6 +279,7 @@
                                ? 'warning'
                                : 'info'
                            "
            size="small"
                          >
                            {{
                              scope.row.ismarginalorgan === "1" ? "是" : "否"
@@ -218,6 +293,7 @@
                                ? 'danger'
                                : 'info'
                            "
            size="small"
                          >
                            {{
                              scope.row.ispathogenpositive === "1" ? "是" : "否"
@@ -233,7 +309,11 @@
          </template>
        </el-table-column>
        <el-table-column label="器官类型" align="center" prop="organname" />
        <el-table-column label="器官类型" align="center" prop="organname">
          <template slot-scope="scope">
            {{ getOrganLabel(scope.row.organno) }}
          </template>
        </el-table-column>
        <el-table-column label="器官编号" align="center" prop="organnumber" />
@@ -246,19 +326,27 @@
        <!-- åŠ¨æ€æ˜¾ç¤ºè¯„ä¼°çŠ¶æ€åˆ— -->
        <el-table-column
          v-for="(assessment, index) in getMaxAssessmentCount()"
          v-for="index in getMaxAssessmentCount()"
          :key="index"
          :label="`第${index + 1}次评估`"
          :label="`第${index}次评估`"
          align="center"
          width="120"
        >
          <template slot-scope="scope">
            <el-tag
              v-if="scope.row.assessments[index]"
              :type="getAssessmentTagType(scope.row.assessments[index].status)"
              v-if="getOrganAssessments(scope.row)[index - 1]"
              :type="
                getAssessmentTagType(
                  getOrganAssessments(scope.row)[index - 1].status
                )
              "
              size="small"
            >
              {{ getAssessmentStatusText(scope.row.assessments[index].status) }}
              {{
                getAssessmentStatusText(
                  getOrganAssessments(scope.row)[index - 1].status
                )
              }}
            </el-tag>
            <el-tag v-else type="info" size="small">未评估</el-tag>
          </template>
@@ -318,7 +406,9 @@
    <!-- æ•´ä½“保存按钮 -->
    <div class="footer-actions" v-if="isEdit">
      <el-button type="primary" @click="handleSaveAll" :loading="saveLoading">保存评估表</el-button>
      <el-button type="primary" @click="handleSaveAll" :loading="saveLoading"
        >保存评估表</el-button
      >
      <el-button @click="handleCancel">取消</el-button>
    </div>
@@ -363,42 +453,44 @@
      currentPreviewFile: null,
      attachmentVisible: false,
      // æçŒ®å†³å®šç›¸å…³
      organdecision: [],
      organdecisionValues: [], // å­˜å‚¨å­—å…¸value
      organdecisionOther: "",
      organselection: [
        "肝脏",
        "双肾",
        "左肾",
        "右肾",
        "心脏",
        "肺脏",
        "胰腺",
        "小肠",
        "双眼组织",
        "遗体",
        "其他"
      ],
      // è®°å½•捐献决定变化前的值
      prevOrgandecisionValues: [],
      // å™¨å®˜ç±»åž‹æ˜ å°„关系
      organDecisionMapping: {
        è‚è„: ["肝脏"],
        åŒè‚¾: ["左肾", "右肾"],
        å·¦è‚¾: ["左肾"],
        å³è‚¾: ["右肾"],
        å¿ƒè„: ["心脏"],
        è‚ºè„: ["肺脏"],
        èƒ°è…º: ["胰腺"],
        å°è‚ : ["小肠"],
        åŒçœ¼ç»„织: ["角膜"],
        é—体: ["皮肤", "骨骼", "其他组织"],
        å…¶ä»–: [] // å…¶ä»–类型不映射具体器官
        C38: ["C38"], // å¿ƒè„ -> å¿ƒè„
        C22: ["C22"], // å…¨è‚ -> å…¨è‚
        C22L: ["C22L"], // å·¦åŠè‚ -> å·¦åŠè‚
        C22L0: ["C22L0"], // å·¦å¤–叶 -> å·¦å¤–叶
        C22R: ["C22R"], // å³åŠè‚ -> å³åŠè‚
        C22R0: ["C22R0"], // å³ä¸‰å¶ -> å³ä¸‰å¶
        C64: ["C64L", "C64R"], // åŒè‚¾ -> å·¦è‚¾, å³è‚¾
        C64L: ["C64L"], // å·¦è‚¾ -> å·¦è‚¾
        C64R: ["C64R"], // å³è‚¾ -> å³è‚¾
        C34: ["C34L", "C34R"], // å…¨è‚º -> å·¦è‚º, å³è‚º
        C34L: ["C34L"], // å·¦è‚º -> å·¦è‚º
        C34R: ["C34R"], // å³è‚º -> å³è‚º
        C17: ["C17"], // å°è‚  -> å°è‚ 
        C25: ["C25"], // èƒ°è…º -> èƒ°è…º
        C00: [], // é—体 -> ä¸æ˜ å°„具体器官(遗体是整体)
        C69L: ["C69L"], // å·¦çœ¼è§’膜 -> å·¦çœ¼è§’膜
        C69R: ["C69R"], // å³çœ¼è§’膜 -> å³çœ¼è§’膜
        C01: [] // å…¶ä»– -> ä¸æ˜ å°„具体器官
      },
      // ç”¨æˆ·ä¿¡æ¯
      currentUser: {
        id: "001",
        name: "张医生",
        department: "心脏科",
        role: "doctor" // coordinator, doctor
      }
        role: "coordinator"
      },
      // è®°å½•被删除的器官评估
      deletedOrganAssessments: [],
      // ç”¨äºŽè¿½è¸ªtab激活状态
      activeTabMap: new Map(),
      // åˆ·æ–°key
      refreshKey: 0
    };
  },
  computed: {
@@ -410,37 +502,46 @@
    },
    // æ ¹æ®æçŒ®å†³å®šè¿‡æ»¤åŽçš„器官列表
    filteredOrganAssessmentList() {
      if (!this.organdecision || this.organdecision.length === 0) {
      if (!this.organdecisionValues || this.organdecisionValues.length === 0) {
        return [];
      }
      // èŽ·å–æ‰€æœ‰é€‰ä¸­çš„å™¨å®˜ç±»åž‹
      const selectedOrgans = new Set();
      this.organdecision.forEach(decision => {
      this.organdecisionValues.forEach(decision => {
        const organs = this.organDecisionMapping[decision] || [];
        organs.forEach(organ => selectedOrgans.add(organ));
      });
      // è¿‡æ»¤å™¨å®˜è¯„估列表
      return this.organAssessmentList.filter(organ =>
        selectedOrgans.has(organ.organname)
      return this.organAssessmentList.filter(
        organ =>
          selectedOrgans.has(organ.organno) &&
          organ.delFlag !== "1" &&
          !this.deletedOrganAssessments.includes(organ.organno)
      );
    },
    // æ£€æŸ¥æ‰€æœ‰è¿‡æ»¤åŽçš„器官是否都已评估
    allOrgansAssessed() {
      return this.filteredOrganAssessmentList.every(
        organ =>
          organ.assessments &&
          organ.assessments.length > 0 &&
          organ.assessments.every(
            assessment => assessment.status === "assessed"
          )
      return this.filteredOrganAssessmentList.every(organ => {
        const assessments = this.getOrganAssessments(organ);
        return (
          assessments &&
          assessments.length > 0 &&
          assessments.every(assessment => assessment.status === "assessed")
      );
      });
    },
    // èŽ·å–å™¨å®˜å­—å…¸
    organDict() {
      return this.dict.type.sys_Organ || [];
    },
    // åˆ¤æ–­æ˜¯å¦éœ€è¦æ˜¾ç¤ºå…¶ä»–输入框
    showOtherInput() {
      return this.organdecisionValues.includes("C01");
    }
  },
  watch: {
    // ç›‘听捐献决定变化,用于复杂逻辑处理
    organdecision: {
    organdecisionValues: {
      handler(newVal, oldVal) {
        this.handleComplexDecisionChange(newVal, oldVal);
      },
@@ -454,13 +555,124 @@
    this.getAssessmentDetail();
  },
  methods: {
    // æ ¹æ®å­—å…¸value获取label
    getOrganLabel(organValue) {
      const dictItem = this.organDict.find(item => item.value === organValue);
      return dictItem ? dictItem.label : organValue;
    },
    // Tab点击事件
    handleTabClick(organ, tab) {
      if (tab.name !== "add") {
        this.activeTabMap.set(organ.organno, tab.name);
      }
    },
// èŽ·å–åŠŸèƒ½çŠ¶æ€æ ‡ç­¾ç±»åž‹
  getFunctionStatusTagType(status) {
    const typeMap = {
      "1": "success",  // æ­£å¸¸
      "2": "warning",  // è½»åº¦å¼‚常
      "3": "danger",   // é‡åº¦å¼‚常
      "4": "info"      // æ— æ³•评估
    };
    return typeMap[status] || "info";
  },
  // èŽ·å–åŠŸèƒ½çŠ¶æ€æ–‡æœ¬
  getFunctionStatusText(status) {
    const textMap = {
      "1": "正常",
      "2": "轻度异常",
      "3": "重度异常",
      "4": "无法评估"
    };
    return textMap[status] || "未评估";
  },
  // æ˜¾ç¤ºé™„件列表
  showAttachmentList(attachments, assessmentNumber) {
    if (!attachments || attachments.length === 0) {
      this.$message.info(`第${assessmentNumber}次评估暂无附件`);
      return;
    }
    this.$alert(
      `<div>
        <h4>第${assessmentNumber}次评估附件列表</h4>
        <ul style="list-style: none; padding-left: 0;">
          ${attachments.map((item, index) => `
            <li style="margin: 5px 0; padding: 5px; background: #f5f7fa; border-radius: 4px;">
              <i class="el-icon-document"></i>
              <span style="margin-left: 8px;">${item.fileName}</span>
              <el-button
                type="text"
                size="mini"
                onclick="window.open('${item.path || item.fileUrl}')"
                style="margin-left: 10px;"
              >
                ä¸‹è½½
              </el-button>
            </li>
          `).join('')}
        </ul>
      </div>`,
      '附件列表',
      {
        dangerouslyUseHTMLString: true,
        showConfirmButton: false,
        showCancelButton: true,
        cancelButtonText: '关闭'
      }
    );
  },
    // èŽ·å–å™¨å®˜çš„è¯„ä¼°åˆ—è¡¨
    getOrganAssessments(organ) {
      if (!organ.assesscontent) return [];
      try {
        const assessData =
          typeof organ.assesscontent === "string"
            ? JSON.parse(organ.assesscontent)
            : organ.assesscontent;
        if (Array.isArray(assessData)) {
          return assessData.filter(item => item.delFlag !== "1");
        }
        return [];
      } catch (error) {
        console.warn("解析评估内容失败:", error);
        return [];
      }
    },
    // èŽ·å–è¯„ä¼°æ•°é‡
    getAssessmentCount(organ) {
      return this.getOrganAssessments(organ).length;
    },
    // å¤„理评估更新
    handleUpdateAssessment(data) {
      const { organData, assessmentData, assessmentIndex } = data;
      const assessments = this.getOrganAssessments(organData);
      if (assessments[assessmentIndex]) {
        // åˆ›å»ºæ–°çš„评估数组
        const newAssessments = [...assessments];
        newAssessments[assessmentIndex] = {
          ...assessments[assessmentIndex],
          ...assessmentData
        };
        // æ›´æ–° assesscontent
        this.$set(organData, "assesscontent", JSON.stringify(newAssessments));
        this.$forceUpdate();
      }
    },
    // æ•´ä½“保存方法
    async handleSaveAll() {
      this.saveLoading = true;
      try {
        // 1. å‡†å¤‡ä¸»è¯„估表数据
        const saveData = {
          // æ ¹æ® id æ˜¯å¦å­˜åœ¨å†³å®šæ˜¯æ›´æ–°è¿˜æ˜¯æ–°å¢ž
          id: this.assessmentData.id || undefined,
          infoid: this.infoid,
          caseNo: this.assessmentData.caseNo,
@@ -473,19 +685,19 @@
          idcardno: this.assessmentData.idcardno,
          diagnosisname: this.assessmentData.diagnosisname,
          coordinatorName: this.assessmentData.coordinatorName,
          assessTime: this.assessmentData.assessTime || new Date().toISOString(),
          assessTime:
            this.assessmentData.assessTime || new Date().toISOString(),
          assessState: this.assessmentData.assessState,
          assessannex: this.assessmentData.assessannex,
          // æçŒ®å†³å®šä¿¡æ¯
          organdecision: this.organdecision.join(','),
          organdecision: this.organdecisionValues.join(","),
          organdecisionOther: this.organdecisionOther,
          // å™¨å®˜è¯„估列表
          serviceMedicalevaluationorgans: this.organAssessmentList.map(organ => ({
          serviceMedicalevaluationorganList: this.organAssessmentList.map(
            organ => ({
            id: organ.id,
            infoid: organ.infoid,
            donorno: organ.donorno,
            organno: organ.organno,
            organname: organ.organname,
              organname: this.getOrganLabel(organ.organno),
            organnumber: organ.organnumber,
            gainhospitalno: organ.gainhospitalno,
            gainhospitalname: organ.gainhospitalname,
@@ -495,27 +707,27 @@
            ispathogenpositive: organ.ispathogenpositive,
            ispnf: organ.ispnf,
            isdgf: organ.isdgf,
            // å°† assessments æ•°ç»„序列化到 assesscontent å­—段
            assesscontent: JSON.stringify(organ.assessments)
          }))
              delFlag: organ.delFlag || "0",
              assesscontent: organ.assesscontent || "[]"
            })
          )
        };
        // 2. æ ¹æ® id åˆ¤æ–­è°ƒç”¨å“ªä¸ª API
        const saveMethod = this.assessmentData.id ? assessedit : assessAdd;
        const response = await saveMethod(saveData);
        if (response.code === 200) {
          this.$message.success('评估表保存成功!');
          // ä¿å­˜æˆåŠŸåŽï¼Œæ›´æ–°æœ¬åœ°çš„ assessmentData.id(对于新增情况)
          this.$message.success("评估表保存成功!");
          if (!this.assessmentData.id && response.data && response.data.id) {
            this.assessmentData.id = response.data.id;
          }
          this.refreshKey += 1; // è§¦å‘重新渲染
        } else {
          this.$message.error('保存失败:' + (response.msg || '未知错误'));
          this.$message.error("保存失败:" + (response.msg || "未知错误"));
        }
      } catch (error) {
        console.error('保存评估表失败:', error);
        this.$message.error('保存失败,请重试');
        console.error("保存评估表失败:", error);
        this.$message.error("保存失败,请重试");
      } finally {
        this.saveLoading = false;
      }
@@ -527,12 +739,21 @@
    },
    // æçŒ®å†³å®šå˜æ›´å¤„理
    handleOrganDecisionChange(newDecision) {
      // è‡ªåŠ¨å¤„ç†ç›¸å…³é€»è¾‘
    async handleOrganDecisionChange(newDecision) {
      const oldDecision = [...this.prevOrgandecisionValues];
      this.autoHandleDecisionChange(newDecision);
      // å¼ºåˆ¶é‡æ–°æ¸²æŸ“
      const removedDecisions = oldDecision.filter(
        item => !newDecision.includes(item)
      );
      for (const decision of removedDecisions) {
        await this.handleRemovedDecision(decision);
      }
      this.prevOrgandecisionValues = [...newDecision];
      this.$forceUpdate();
      // å¦‚果从有选择变为无选择,清空展开状态
      if (newDecision.length === 0) {
        this.expandedRowKeys = [];
      }
@@ -545,25 +766,36 @@
    // è‡ªåŠ¨å¤„ç†å†³å®šå˜æ›´é€»è¾‘
    autoHandleDecisionChange(newDecision) {
      // å¦‚果选择了"双肾",自动取消单独的"左肾"和"右肾"选择
      if (newDecision.includes("双肾")) {
        this.organdecision = newDecision.filter(
          item => item !== "左肾" && item !== "右肾"
      // å¦‚果选择了"双肾"(value: C64),自动取消单独的"左肾"(value: C64L)和"右肾"(value: C64R)选择
      if (newDecision.includes("C64")) {
        this.organdecisionValues = newDecision.filter(
          item => item !== "C64L" && item !== "C64R"
        );
      }
      // å¦‚果选择了"左肾"或"右肾",取消"双肾"选择
      else if (newDecision.includes("左肾") || newDecision.includes("右肾")) {
        this.organdecision = newDecision.filter(item => item !== "双肾");
      else if (newDecision.includes("C64L") || newDecision.includes("C64R")) {
        this.organdecisionValues = newDecision.filter(item => item !== "C64");
      }
      // å¤„理互斥逻辑
      // å¦‚果选择了"全肺"(value: C34),自动取消单独的"左肺"(value: C34L)和"右肺"(value: C34R)选择
      if (newDecision.includes("C34")) {
        this.organdecisionValues = newDecision.filter(
          item => item !== "C34L" && item !== "C34R"
        );
      }
      // å¦‚果选择了"左肺"或"右肺",取消"全肺"选择
      else if (newDecision.includes("C34L") || newDecision.includes("C34R")) {
        this.organdecisionValues = newDecision.filter(item => item !== "C34");
      }
      // å¤„理其他互斥逻辑
      this.handleExclusiveDecisions();
    },
    // å¤„理互斥的捐献决定
    handleExclusiveDecisions() {
      // é—体捐献与其他器官捐献互斥(根据业务需求调整)
      if (this.organdecision.includes("遗体")) {
      // é—体捐献(value: 10)与其他器官捐献互斥(根据业务需求调整)
      if (this.organdecisionValues.includes("10")) {
        // å¯ä»¥è®¾ç½®åªä¿ç•™é—体捐献,或者根据业务需求处理
      }
    },
@@ -596,52 +828,91 @@
      const organsToCreate = this.organDecisionMapping[decision];
      if (organsToCreate && organsToCreate.length > 0) {
        organsToCreate.forEach(organName => {
          this.ensureOrganExists(organName);
        organsToCreate.forEach(organValue => {
          this.ensureOrganExists(organValue);
        });
        // æ˜¾ç¤ºåˆ›å»ºæç¤º
        if (organsToCreate.length > 0) {
          this.$message.success(
            `已为【${decision}】创建${organsToCreate.length}个评估项`
            `已为【${this.getOrganLabel(decision)}】创建${
              organsToCreate.length
            }个评估项`
          );
        }
      } else {
        console.warn(`捐献决定【${decision}】没有配置器官映射关系`);
        console.warn(
          `捐献决定【${this.getOrganLabel(decision)}】没有配置器官映射关系`
        );
      }
    },
    // å¤„理移除的捐献决定
    handleRemovedDecision(decision) {
      // æ ¹æ®ä¸šåŠ¡éœ€æ±‚æ·»åŠ æ¸…ç†é€»è¾‘
    async handleRemovedDecision(decision) {
      const relatedOrgans = this.organDecisionMapping[decision] || [];
      relatedOrgans.forEach(organ => {
        // å¯ä»¥åœ¨è¿™é‡Œæ·»åŠ æ¸…ç†ç›¸å…³å™¨å®˜è¯„ä¼°çš„é€»è¾‘
      });
      for (const organValue of relatedOrgans) {
        const organIndex = this.organAssessmentList.findIndex(
          organ => organ.organno === organValue && organ.delFlag !== "1"
        );
        if (organIndex !== -1) {
          const organ = this.organAssessmentList[organIndex];
          const organLabel = this.getOrganLabel(organValue);
          try {
            await this.$confirm(
              `捐献决定"${this.getOrganLabel(
                decision
              )}"已取消,是否删除对应的${organLabel}评估记录?`,
              "确认删除",
              {
                confirmButtonText: "确定",
                cancelButtonText: "取消",
                type: "warning"
              }
            );
            this.$set(this.organAssessmentList[organIndex], "delFlag", "1");
            this.deletedOrganAssessments.push(organValue);
            const keyIndex = this.expandedRowKeys.indexOf(organValue);
            if (keyIndex > -1) {
              this.expandedRowKeys.splice(keyIndex, 1);
            }
            this.$message.success(`${organLabel}评估记录已标记删除`);
          } catch (cancelError) {
            if (!this.organdecisionValues.includes(decision)) {
              this.organdecisionValues.push(decision);
            }
            this.$message.info(`已取消删除${organLabel}评估记录`);
          }
        }
      }
    },
    // ç¡®ä¿å™¨å®˜å­˜åœ¨ï¼ˆå¸¦é‡å¤æ£€æŸ¥ï¼‰
    ensureOrganExists(organName) {
      // æ£€æŸ¥æ˜¯å¦å·²å­˜åœ¨åŒåå™¨å®˜è¯„估项
    // ç¡®ä¿å™¨å®˜å­˜åœ¨
    ensureOrganExists(organValue) {
      const exists = this.organAssessmentList.some(
        organ => organ.organname === organName
        organ => organ.organno === organValue && organ.delFlag !== "1"
      );
      if (!exists) {
        // åˆ›å»ºæ–°çš„器官评估项
        const newOrgan = {
          id: `organ_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
          organno: `ORG${Date.now()}`,
          organname: organName,
          id: null,
          organno: organValue,
          organname: this.getOrganLabel(organValue),
          gainhospitalname: "待分配机构",
          isbiopsybefore: "0",
          isbiopsyafter: "0",
          ismarginalorgan: "0",
          ispathogenpositive: "0",
          assessments: [this.getDefaultAssessment(0)],
          activeAssessmentTab: "assessment_0",
          assesscontent: JSON.stringify([this.getDefaultAssessment(0)]),
          activeTab: 0,
          expanded: false,
          createTime: new Date().toISOString()
          createTime: new Date().toISOString(),
          delFlag: "0"
        };
        this.organAssessmentList = [...this.organAssessmentList, newOrgan];
@@ -673,7 +944,6 @@
    handleResponseData(response) {
      let detailData = null;
      // æ ¹æ®æŽ¥å£å®žé™…返回的数据结构进行调整
      if (response.data) {
        if (Array.isArray(response.data)) {
          detailData = response.data[0] || {};
@@ -688,7 +958,6 @@
        detailData = response;
      }
      // æ˜ å°„字段到评估数据
      this.assessmentData = {
        id: detailData.id || this.assessmentId,
        infoid: detailData.infoid || this.infoid,
@@ -706,15 +975,16 @@
        assessannex: detailData.assessannex || ""
      };
      // å¤„理捐献决定数据
      if (detailData.organdecision) {
        this.organdecision = Array.isArray(detailData.organdecision)
        const decisionArray = Array.isArray(detailData.organdecision)
          ? detailData.organdecision
          : (detailData.organdecision || "").split(",");
          : (detailData.organdecision || "").split(",").filter(item => item);
        this.organdecisionValues = decisionArray;
        this.prevOrgandecisionValues = [...decisionArray];
        this.organdecisionOther = detailData.organdecisionOther || "";
      }
      // å¤„理器官评估数据
      this.processOrganAssessmentData(detailData);
    },
@@ -722,46 +992,43 @@
    processOrganAssessmentData(detailData) {
      let organList = [];
      // ä»ŽæŽ¥å£æ•°æ®ä¸­èŽ·å–å™¨å®˜è¯„ä¼°åˆ—è¡¨
      if (detailData.serviceMedicalevaluationorgans) {
        if (Array.isArray(detailData.serviceMedicalevaluationorgans)) {
          organList = detailData.serviceMedicalevaluationorgans;
      if (detailData.serviceMedicalevaluationorganList) {
        if (Array.isArray(detailData.serviceMedicalevaluationorganList)) {
          organList = detailData.serviceMedicalevaluationorganList;
        }
      }
      // è½¬æ¢å™¨å®˜æ•°æ®æ ¼å¼ï¼Œæ”¯æŒå¤šæ¬¡è¯„ä¼°
      this.organAssessmentList = organList.map(organ => {
        const assessments = [];
        const organno = organ.organno;
        // è§£æžassesscontent字段中的多次评估数据
        if (organ.assesscontent) {
        // å¦‚æžœ assesscontent æ˜¯å­—符串,确保它是有效的 JSON
        if (organ.assesscontent && typeof organ.assesscontent === "string") {
          try {
            const assessData = typeof organ.assesscontent === "string"
              ? JSON.parse(organ.assesscontent)
              : organ.assesscontent;
            if (Array.isArray(assessData)) {
              assessments.push(
                ...assessData.map((item, index) => ({
                  ...item,
                  index: index,
                  status: item.status || "assessed"
                }))
              );
            }
            JSON.parse(organ.assesscontent);
          } catch (error) {
            console.warn("解析评估内容失败:", error);
            assessments.push(this.getDefaultAssessment(0));
            console.warn(
              "无效的 assesscontent,重置为空数组:",
              organ.assesscontent
            );
            organ.assesscontent = "[]";
          }
        } else {
          assessments.push(this.getDefaultAssessment(0));
        } else if (!organ.assesscontent) {
          organ.assesscontent = "[]";
        }
        const assessments = this.getOrganAssessments(organ);
        const activeTab = this.activeTabMap.has(organno)
          ? this.activeTabMap.get(organno)
          : assessments.length > 0
          ? 0
          : "summary";
        return {
          ...organ,
          assessments: assessments,
          activeAssessmentTab: assessments.length > 0 ? "assessment_0" : "summary",
          expanded: false
          organname: this.getOrganLabel(organ.organno) || organ.organname,
          activeTab: activeTab,
          expanded: false,
          delFlag: organ.delFlag || "0"
        };
      });
    },
@@ -777,30 +1044,37 @@
        assessmentOpinion: "",
        clinicalData: {},
        labResults: {},
        createTime: new Date().toISOString()
        createTime: new Date().toISOString(),
        delFlag: "0"
      };
    },
    // è®¡ç®—最大评估次数
    getMaxAssessmentCount() {
      const maxCount = Math.max(
        ...this.organAssessmentList.map(organ =>
          organ.assessments ? organ.assessments.length : 0
        )
        ...this.organAssessmentList
          .filter(organ => organ.delFlag !== "1")
          .map(organ => this.getAssessmentCount(organ))
      );
      return Math.max(maxCount, 1);
    },
    // èŽ·å–å™¨å®˜æ•´ä½“çŠ¶æ€
    getOrganOverallStatus(organ) {
      if (!organ.assessments || organ.assessments.length === 0) {
      const assessments = this.getOrganAssessments(organ);
      if (assessments.length === 0) {
        return "pending";
      }
      const allAssessed = organ.assessments.every(
      const validAssessments = assessments.filter(a => a.delFlag !== "1");
      if (validAssessments.length === 0) {
        return "pending";
      }
      const allAssessed = validAssessments.every(
        assessment => assessment.status === "assessed"
      );
      const someAssessed = organ.assessments.some(
      const someAssessed = validAssessments.some(
        assessment => assessment.status === "assessed"
      );
@@ -845,28 +1119,130 @@
    // æ·»åŠ æ–°è¯„ä¼°
    handleAddNewAssessment(organ) {
      const assessments = this.getOrganAssessments(organ);
      const newAssessment = {
        ...this.getDefaultAssessment(organ.assessments.length),
        ...this.getDefaultAssessment(assessments.length),
        assessor: this.currentUser.name
      };
      organ.assessments.push(newAssessment);
      organ.activeAssessmentTab = `assessment_${organ.assessments.length - 1}`;
      const newAssessments = [...assessments, newAssessment];
      this.$set(organ, "assesscontent", JSON.stringify(newAssessments));
      organ.activeTab = assessments.length;
      this.activeTabMap.set(organ.organno, assessments.length);
      this.$message.success("已添加新的评估");
    },
    // å¤„理添加评估事件
    handleAddAssessment(data) {
      const { organData } = data;
      this.handleAddNewAssessment(organData);
    // å¤„理删除评估事件
    handleDeleteAssessment(data) {
      const { organData, assessmentIndex } = data;
      this.deleteOrganAssessment(organData, assessmentIndex);
    },
    // å¤„理评估保存
    handleSaveAssessment(data) {
      const { organData, assessmentData, assessmentIndex } = data;
      const assessments = this.getOrganAssessments(organData);
      console.log("保存评估数据:", data);
      if (assessments[assessmentIndex]) {
        // åˆ›å»ºæ–°çš„评估数组
        const newAssessments = [...assessments];
        newAssessments[assessmentIndex] = {
          ...assessments[assessmentIndex],
          ...assessmentData,
          status: "assessed", // æ ‡è®°ä¸ºå·²è¯„ä¼°
          assessmentTime: new Date().toISOString(), // è®¾ç½®è¯„ä¼°æ—¶é—´
          delFlag: "0" // ç¡®ä¿åˆ é™¤æ ‡å¿—
        };
        // æ›´æ–° assesscontent
        this.$set(organData, "assesscontent", JSON.stringify(newAssessments));
        // å¼ºåˆ¶é‡æ–°æ¸²æŸ“
        this.$forceUpdate();
        this.$message.success("评估保存成功");
        // æ£€æŸ¥æ˜¯å¦éœ€è¦è‡ªåŠ¨åˆ‡æ¢åˆ°ä¸‹ä¸€ä¸ªè¯„ä¼°
        this.checkAndSwitchTab(organData, assessmentIndex);
      }
    },
    // æ£€æŸ¥å¹¶è‡ªåŠ¨åˆ‡æ¢tab
    checkAndSwitchTab(organData, currentIndex) {
      const assessments = this.getOrganAssessments(organData);
      if (currentIndex < assessments.length - 1) {
        // å¦‚果还有下一个评估,自动切换到下一个
        organData.activeTab = currentIndex + 1;
        this.activeTabMap.set(organData.organno, currentIndex + 1);
      } else {
        // å¦‚果没有下一个评估,切换到汇总页
        organData.activeTab = "summary";
        this.activeTabMap.set(organData.organno, "summary");
      }
    },
    // åˆ é™¤å™¨å®˜è¯„ä¼°
    async deleteOrganAssessment(organ, assessmentIndex) {
      try {
        await this.$confirm(
          `确认删除第${assessmentIndex + 1}次评估记录吗?`,
          "确认删除",
          {
            confirmButtonText: "确定",
            cancelButtonText: "取消",
            type: "warning"
          }
        );
        const assessments = this.getOrganAssessments(organ);
        if (assessments[assessmentIndex]) {
          // æ ‡è®°ä¸ºåˆ é™¤
          assessments[assessmentIndex].delFlag = "1";
          // è¿‡æ»¤æŽ‰å·²åˆ é™¤çš„评估
          const newAssessments = assessments.filter(
            item => item.delFlag !== "1"
          );
          // é‡æ–°è®¡ç®—评估索引
          newAssessments.forEach((assessment, index) => {
            assessment.index = index;
          });
          // æ›´æ–° assesscontent
          this.$set(organ, "assesscontent", JSON.stringify(newAssessments));
          // å¤„理tab切换
          if (newAssessments.length === 0) {
            organ.activeTab = "summary";
            this.activeTabMap.set(organ.organno, "summary");
          } else if (organ.activeTab === assessmentIndex) {
            const newIndex = Math.max(0, assessmentIndex - 1);
            organ.activeTab = newIndex;
            this.activeTabMap.set(organ.organno, newIndex);
          } else if (organ.activeTab === "summary") {
            this.activeTabMap.set(organ.organno, "summary");
          }
          this.$message.success("评估记录已删除");
          this.$forceUpdate();
        }
      } catch (cancelError) {
        this.$message.info("已取消删除");
      }
    },
    // èŽ·å–æœ€æ–°è¯„ä¼°æ—¶é—´
    getLatestAssessmentTime(organ) {
      if (!organ.assessments || organ.assessments.length === 0) return null;
      const assessments = this.getOrganAssessments(organ);
      if (assessments.length === 0) return null;
      const assessed = organ.assessments.filter(a => a.assessmentTime);
      const assessed = assessments.filter(
        a => a.assessmentTime && a.delFlag !== "1"
      );
      if (assessed.length === 0) return null;
      return assessed.sort(
@@ -896,8 +1272,6 @@
    // æ£€æŸ¥è¯„估权限
    canAssessOrgan(organ) {
      console.log(organ,'organ');
      if (this.isCoordinator) return true;
      if (!this.isEdit) return false;
      return (
@@ -934,7 +1308,8 @@
    handleAttachmentPreview() {
      if (this.assessmentData.assessannex) {
        try {
          const annexData = typeof this.assessmentData.assessannex === "string"
          const annexData =
            typeof this.assessmentData.assessannex === "string"
            ? JSON.parse(this.assessmentData.assessannex)
            : this.assessmentData.assessannex;
@@ -965,7 +1340,6 @@
          }
        );
        // æ›´æ–°è¯„估状态为已完成
        const updateData = {
          ...this.assessmentData,
          assessState: "3",
@@ -1082,17 +1456,210 @@
.fixed-width .el-button {
  margin: 0 2px;
}
/* æçŒ®å†³å®šæ ·å¼ä¼˜åŒ– */
.organ-decision-info {
  margin: 10px 0;
/* æ±‡æ€»é¡µé¢æ ·å¼ */
.assessment-summary {
  padding: 10px;
  background-color: #f8f9fa;
  border-radius: 4px;
  border-left: 4px solid #409eff;
}
.decision-tag {
  margin: 2px 5px;
.summary-item {
  font-weight: 500;
  color: #303133;
}
.highlight-text {
  color: #409EFF;
  font-weight: 500;
}
.assessment-detail-card {
  border: 1px solid #e6ebf5;
}
.organ-info-card {
  border: 1px solid #e6ebf5;
  background-color: #fafafa;
}
.no-assessment {
  text-align: center;
  padding: 40px 0;
  color: #909399;
}
.assessment-item {
  margin-bottom: 20px;
}
.assessment-item:last-child {
  margin-bottom: 0;
}
.assessment-card {
  border: 1px solid #dcdfe6;
  border-radius: 8px;
  transition: all 0.3s;
}
.assessment-card:hover {
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  border-color: #409EFF;
}
.assessment-title {
  font-size: 16px;
  font-weight: 600;
  color: #303133;
}
.status-tag {
  float: right;
  margin-right: 0;
}
.time-text {
  color: #67C23A;
  font-weight: 500;
}
.opinion-content {
  padding: 8px 12px;
  background: #f5f7fa;
  border-radius: 4px;
  line-height: 1.5;
  color: #606266;
  white-space: pre-wrap;
  word-break: break-word;
}
.detail-descriptions {
  background: #fff;
}
/* ä¼˜åŒ–表格样式 */
::v-deep .el-table {
  color: #303133;
  font-size: 14px;
}
::v-deep .el-table th {
  background-color: #f5f7fa;
  color: #303133;
  font-weight: 600;
  padding: 12px 0;
}
::v-deep .el-table tr {
  background-color: #fff;
}
::v-deep .el-table tr:hover {
  background-color: #f5f7fa;
}
::v-deep .el-table .cell {
  padding: 12px 10px;
  line-height: 1.5;
}
::v-deep .el-table--striped .el-table__body tr.el-table__row--striped td {
  background-color: #fafafa;
}
::v-deep .el-table--enable-row-hover .el-table__body tr:hover>td {
  background-color: #ecf5ff;
}
/* å¯è¯„估行样式 */
::v-deep .assessable-row {
  background-color: #f0f9ff !important;
}
::v-deep .assessable-row:hover {
  background-color: #d9ecff !important;
}
::v-deep .non-assessable-row {
  background-color: #fafafa !important;
}
/* æè¿°åˆ—表样式优化 */
::v-deep .el-descriptions__label {
  width: 120px;
  background-color: #f5f7fa;
  font-weight: 600;
  color: #303133;
}
::v-deep .el-descriptions__content {
  background-color: #fff;
  color: #606266;
}
::v-deep .el-descriptions__body {
  background-color: #fff;
}
/* å¡ç‰‡æ ·å¼ä¼˜åŒ– */
::v-deep .el-card__header {
  background-color: #f5f7fa;
  border-bottom: 1px solid #e6ebf5;
  padding: 12px 20px;
  font-weight: 600;
  color: #303133;
}
::v-deep .el-card__body {
  padding: 20px;
}
/* æ ‡ç­¾æ ·å¼ä¼˜åŒ– */
::v-deep .el-tag {
  font-weight: 500;
  border-radius: 12px;
  padding: 0 10px;
  height: 24px;
  line-height: 22px;
}
/* æŒ‰é’®æ ·å¼ä¼˜åŒ– */
::v-deep .el-button--mini {
  padding: 7px 12px;
  font-size: 12px;
  border-radius: 4px;
}
/* Tab样式优化 */
::v-deep .el-tabs__item {
  font-weight: 500;
  color: #606266;
}
::v-deep .el-tabs__item.is-active {
  color: #409EFF;
  font-weight: 600;
}
::v-deep .el-tabs__nav-wrap::after {
  background-color: #e4e7ed;
}
::v-deep .el-tabs--card>.el-tabs__header .el-tabs__item.is-active {
  background-color: #fff;
  border-bottom-color: #fff;
}
/* å“åº”式设计 */
@media (max-width: 768px) {
  .assessment-summary {
    padding: 5px;
  }
  ::v-deep .el-table .cell {
    padding: 8px 5px;
  }
  .assessment-card {
    margin-bottom: 10px;
  }
}
</style>
src/views/business/assess/components/OrganAssessmentForm.vue
@@ -1,8 +1,8 @@
<template>
  <div class="organ-assessment-form">
    <el-form :model="assessmentData" label-width="120px">
    <el-form :model="formData" label-width="120px">
      <el-form-item label="功能状态">
        <el-select v-model="assessmentData.functionStatus">
        <el-select v-model="formData.functionStatus">
          <el-option label="正常" value="1" />
          <el-option label="轻度异常" value="2" />
          <el-option label="重度异常" value="3" />
@@ -13,7 +13,7 @@
      <el-form-item label="评估意见">
        <el-input
          type="textarea"
          v-model="assessmentData.assessmentOpinion"
          v-model="formData.assessmentOpinion"
          :rows="4"
          placeholder="请输入评估意见"
        />
@@ -46,16 +46,13 @@
          <!-- é™„件列表 -->
          <div
            class="attachment-list"
            v-if="
              assessmentData.attachments &&
                assessmentData.attachments.length > 0
            "
            v-if="formData.attachments && formData.attachments.length > 0"
          >
            <div class="list-title">
              å·²ä¸Šä¼ é™„ä»¶ ({{ assessmentData.attachments.length }})
              å·²ä¸Šä¼ é™„ä»¶ ({{ formData.attachments.length }})
            </div>
            <el-table
              :data="assessmentData.attachments"
              :data="formData.attachments"
              style="width: 100%"
              size="small"
            >
@@ -121,14 +118,15 @@
      </el-form-item>
      <el-form-item v-if="!readonly">
        <el-button type="primary" @click="handleSave">保存评估</el-button>
        <el-button type="primary" @click="handleSave">评估完成</el-button>
        <el-button @click="handleCancel">取消</el-button>
        <el-button
          type="success"
          @click="handleAddAssessment"
          icon="el-icon-plus"
          type="danger"
          size="small"
          @click="handleDelete"
          icon="el-icon-delete"
        >
          æ–°å¢žè¯„估记录
          åˆ é™¤æ­¤è¯„ä¼°
        </el-button>
      </el-form-item>
    </el-form>
@@ -159,14 +157,6 @@
      type: Object,
      default: () => ({})
    },
    assessmentData: {
      type: Object,
      default: () => ({
        functionStatus: "",
        assessmentOpinion: "",
        attachments: []
      })
    },
    assessmentIndex: {
      type: Number,
      default: 0
@@ -174,73 +164,184 @@
    readonly: {
      type: Boolean,
      default: false
    },
    // æ·»åŠ ç”¨æˆ·ä¿¡æ¯props
    currentUser: {
      type: Object,
      default: () => ({
        name: "评估员"
      })
    }
  },
  data() {
    return {
      // è¡¨å•数据
      formData: {
        functionStatus: "",
        assessmentOpinion: "",
        attachments: []
      },
      // é¢„览相关
      previewVisible: false,
      currentPreviewFile: null,
      // é™„件相关配置
      attachmentLimit: 10,
      attachmentAccept:
        ".pdf,.jpg,.jpeg,.png,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.txt",
      attachmentFileList: []
      attachmentFileList: [],
      // åŽŸå§‹è¯„ä¼°æ•°æ®
      currentAssessment: null
    };
  },
  watch: {
    organData: {
      handler(newVal, oldVal) {
        // åªæœ‰å½“附件数据真正发生变化时才初始化
        if (
          !oldVal ||
          !oldVal.attachments ||
          JSON.stringify(newVal.attachments) !==
            JSON.stringify(oldVal.attachments)
        ) {
          this.initAttachmentList();
        }
      handler() {
        this.initData();
      },
      immediate: true,
      deep: true,
      immediate: true
    },
    // æ·±åº¦ç›‘听表单数据变化
    formData: {
      handler(newVal) {
        this.$emit("update-assessment", {
          organData: this.organData,
          assessmentData: newVal,
          assessmentIndex: this.assessmentIndex
        });
      },
      deep: true
    }
  },
  created() {
    this.initData();
  },
  methods: {
    /** åˆå§‹åŒ–附件列表 */
    initAttachmentList() {
      if (this.organData.attachments && this.organData.attachments.length > 0) {
        this.assessmentData.attachments = [...this.organData.attachments];
        this.attachmentFileList = this.organData.attachments.map(item => ({
    // åˆå§‹åŒ–数据
    initData() {
      if (!this.organData || !this.organData.assesscontent) {
        this.formData = {
          functionStatus: "",
          assessmentOpinion: "",
          attachments: []
        };
        this.attachmentFileList = [];
        return;
      }
      try {
        const assessData =
          typeof this.organData.assesscontent === "string"
            ? JSON.parse(this.organData.assesscontent)
            : this.organData.assesscontent;
        if (
          Array.isArray(assessData) &&
          assessData.length > this.assessmentIndex
        ) {
          this.currentAssessment = assessData[this.assessmentIndex];
          // æ·±æ‹·è´æ•°æ®ï¼Œé¿å…ä¿®æ”¹åŽŸå§‹æ•°æ®
          const assessmentCopy = JSON.parse(
            JSON.stringify(this.currentAssessment)
          );
          this.formData = {
            functionStatus: assessmentCopy.functionStatus || "",
            assessmentOpinion: assessmentCopy.assessmentOpinion || "",
            attachments: Array.isArray(assessmentCopy.attachments)
              ? [...assessmentCopy.attachments]
              : []
          };
          // åˆå§‹åŒ–附件文件列表
          this.attachmentFileList = this.formData.attachments.map(item => ({
          uid: item.id || Math.random(),
          name: item.fileName,
            fileSize: item.fileSize,
          url: item.path || item.fileUrl,
            uploadTime: item.uploadTime,
          status: "success"
        }));
      } else {
        this.assessmentData.attachments = [];
        this.attachmentFileList = [];
          console.log("评估索引超出范围或数据为空");
          this.resetForm();
        }
      } catch (error) {
        console.error("初始化数据失败:", error);
        this.resetForm();
      }
    },
    handleSave() {
      const saveData = {
        organData: this.organData,
        assessmentData: this.assessmentData,
        assessmentIndex: this.assessmentIndex
    // é‡ç½®è¡¨å•
    resetForm() {
      this.formData = {
        functionStatus: "",
        assessmentOpinion: "",
        attachments: []
      };
      this.$emit("save", saveData);
      this.attachmentFileList = [];
    },
    // ä¿å­˜è¯„ä¼°
    handleSave() {
      // éªŒè¯å¿…要字段
      if (!this.formData.functionStatus) {
        this.$message.warning("请选择功能状态");
        return;
      }
      if (!this.formData.assessmentOpinion) {
        this.$message.warning("请输入评估意见");
        return;
      }
      // å‡†å¤‡ä¿å­˜çš„æ•°æ®
      const saveData = {
        functionStatus: this.formData.functionStatus,
        assessmentOpinion: this.formData.assessmentOpinion,
        attachments: Array.isArray(this.formData.attachments)
          ? [...this.formData.attachments]
          : []
      };
      // æ·»åŠ è¯„ä¼°è€…å’Œè¯„ä¼°æ—¶é—´
      const assessmentData = {
        ...saveData,
        assessor: this.currentUser.name,
        assessmentTime: new Date().toISOString()
      };
      console.log("发送保存请求:", assessmentData);
      this.$emit("save-assessment", {
        organData: this.organData,
        assessmentData: assessmentData,
        assessmentIndex: this.assessmentIndex
      });
    },
    handleCancel() {
      this.$emit("cancel");
    },
    handleAddAssessment() {
      this.$emit("add-assessment", {
    handleDelete() {
      this.$confirm("确认删除此评估记录吗?", "确认删除", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      })
        .then(() => {
          this.$emit("delete-assessment", {
        organData: this.organData,
        currentIndex: this.assessmentIndex
            assessmentIndex: this.assessmentIndex
          });
        })
        .catch(() => {
          this.$message.info("已取消删除");
      });
    },
    /** é™„件变化处理 */
    handleAttachmentChange(fileList) {
      this.attachmentFileList = fileList;
@@ -249,47 +350,49 @@
    /** é™„件移除处理 */
    handleAttachmentRemove(file) {
      if (file.url) {
        const index = this.assessmentData.attachments.findIndex(
        const index = this.formData.attachments.findIndex(
          item => item.path === file.url || item.fileUrl === file.url
        );
        if (index > -1) {
          this.assessmentData.attachments.splice(index, 1);
          this.formData.attachments.splice(index, 1);
          this.$message.success("附件删除成功");
        }
      }
    },
    /** æ‰‹åŠ¨åˆ é™¤é™„ä»¶ */
    handleRemoveAttachment(index) {
      this.assessmentData.attachments.splice(index, 1);
      this.formData.attachments.splice(index, 1);
      this.attachmentFileList.splice(index, 1);
      this.$message.success("附件删除成功");
    },
    /** ä¸Šä¼ æˆåŠŸå¤„ç† */
    handleUploadSuccess({ file, fileList, response }) {
      console.log(response);
      if (response.code == 200) {
        console.log(1);
      if (response.code === 200) {
        console.log(response, "上传数据");
        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,
          path: response.fileUrl || file.url,
          fileUrl: response.fileUrl || file.url,
          fileType: this.getFileExtension(file.name),
          fileSize: file.size,
          uploadTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
          assessmentType: this.assessmentType,
          organType: this.organData.organType
          uploadTime: dayjs().format("YYYY-MM-DD HH:mm:ss")
        };
        console.log(2,attachmentObj);
        this.assessmentData.attachments.push(attachmentObj);
        console.log("添加上传的附件:", attachmentObj);
        // ç¡®ä¿ attachments æ˜¯æ•°ç»„
        if (!Array.isArray(this.formData.attachments)) {
          this.formData.attachments = [];
        }
        this.formData.attachments.push(attachmentObj);
        // æ›´æ–°æ–‡ä»¶åˆ—表
        this.attachmentFileList = fileList;
        this.$message.success("文件上传成功");
      }
    },
src/views/business/assess/index.vue
@@ -83,10 +83,10 @@
    <el-card class="tool-card">
      <el-row :gutter="10">
        <el-col :span="16">
          <el-button type="primary" icon="el-icon-plus" @click="handleCreate"
          <!-- <el-button type="primary" icon="el-icon-plus" @click="handleCreate"
            >新增评估</el-button
          >
          <el-button
          > -->
          <!-- <el-button
            type="success"
            icon="el-icon-edit"
            :disabled="single"
@@ -99,7 +99,7 @@
            :disabled="multiple"
            @click="handleDelete"
            >删除</el-button
          >
          > -->
          <el-button
            type="warning"
            icon="el-icon-download"
@@ -205,6 +205,7 @@
          label="操作"
          align="center"
          width="200"
          fixed="right"
          class-name="small-padding fixed-width"
        >
          <template slot-scope="scope">
@@ -217,8 +218,8 @@
            >
            <el-button
              v-if="
                scope.row.assessState === '1' ||
                  scope.row.assessState === '2'
                scope.row.assessState != '3' ||
                  scope.row.assessState != '4'
              "
              size="mini"
              type="text"
@@ -226,14 +227,14 @@
              @click.stop="handleAssess(scope.row)"
              >评估</el-button
            >
            <el-button
            <!-- <el-button
              v-if="scope.row.assessState === '3'"
              size="mini"
              type="text"
              icon="el-icon-check"
              @click.stop="handleConfirm(scope.row)"
              >确认</el-button
            >
            > -->
          </template>
        </el-table-column>
      </el-table>
src/views/business/decide/DecideInfo.vue
@@ -6,8 +6,8 @@
        <span class="detail-title">死亡判定基本信息</span>
        <el-button
          v-if="isEdit"
          type="primary"
          style="float: right; padding: 3px 0"
          type="success"
          style="float: right"
          @click="handleSave"
          :loading="saveLoading"
        >
@@ -16,7 +16,7 @@
        <el-button
          v-else
          type="primary"
          style="float: right; padding: 3px 0"
          style="float: right"
          @click="handleEdit"
        >
          ç¼–辑信息
@@ -138,7 +138,10 @@
        <el-row :gutter="20">
          <el-col :span="8">
            <el-form-item label="负责人" prop="responsibleusername">
              <el-input v-model="form.responsibleusername" :readonly="!isEdit" />
              <el-input
                v-model="form.responsibleusername"
                :readonly="!isEdit"
              />
            </el-form-item>
          </el-col>
          <el-col :span="8">
@@ -166,7 +169,7 @@
    <el-card class="attachment-card">
      <div slot="header" class="clearfix">
        <span class="detail-title">死亡判定评估表附件</span>
        <el-button
        <!-- <el-button
          v-if="isEdit"
          type="primary"
          size="mini"
@@ -174,7 +177,7 @@
          :loading="uploadLoading"
        >
          ä¸Šä¼ é™„ä»¶
        </el-button>
        </el-button> -->
      </div>
      <!-- é™„件类型选项卡 -->
@@ -221,7 +224,9 @@
              <el-table-column label="文件类型" width="100" align="center">
                <template slot-scope="scope">
                  <el-tag size="small">{{ getFileType(scope.row.fileName) }}</el-tag>
                  <el-tag size="small">{{
                    getFileType(scope.row.fileName)
                  }}</el-tag>
                </template>
              </el-table-column>
@@ -243,11 +248,7 @@
                </template>
              </el-table-column>
              <el-table-column
                label="操作"
                width="180"
                align="center"
              >
              <el-table-column label="操作" width="180" align="center">
                <template slot-scope="scope">
                  <el-button
                    size="mini"
@@ -280,7 +281,10 @@
              v-if="getAttachmentsByType(type.value).length === 0"
              class="empty-attachment"
            >
              <el-empty description="暂无评估表附件" :image-size="80"></el-empty>
              <el-empty
                description="暂无评估表附件"
                :image-size="80"
              ></el-empty>
            </div>
          </div>
        </el-tab-pane>
@@ -298,16 +302,20 @@
        ref="uploadRef"
        class="upload-demo"
        drag
        action="#"
        :action="uploadAction"
        :headers="headers"
        multiple
        :file-list="tempFileList"
        :before-upload="beforeUpload"
        :on-change="handleFileChange"
        :on-remove="handleTempRemove"
        :on-success="handleUploadSuccess"
        :auto-upload="false"
      >
        <i class="el-icon-upload"></i>
        <div class="el-upload__text">将评估表文件拖到此处,或<em>点击上传</em></div>
        <div class="el-upload__text">
          å°†è¯„估表文件拖到此处,或<em>点击上传</em>
        </div>
        <div class="el-upload__tip" slot="tip">
          æ”¯æŒä¸Šä¼ pdf、jpg、png、doc、docx、xls、xlsx格式文件,单个文件不超过10MB
        </div>
@@ -330,6 +338,7 @@
<script>
import { deathinfoedit, deathinfoInfo } from "@/api/businessApi";
import { getToken } from "@/utils/auth";
export default {
  name: "DeathJudgmentDetail",
@@ -384,7 +393,10 @@
      uploadLoading: false,
      tempFileList: [],
      currentUploadType: "",
      uploadAction: process.env.VUE_APP_BASE_API + "/common/upload",
      headers: {
        Authorization: "Bearer " + getToken()
      },
      // è¯„估表类型定义
      attachmentTypes: [
        { value: "1", label: "脑死亡判定表" },
@@ -410,10 +422,10 @@
  },
  created() {
    const id = this.$route.query.id;
    this.isEdit = this.$route.path.includes('/edit') || this.$route.path.includes('/add');
    if (id && !this.$route.path.includes('/add')) {
    this.isEdit = this.$route.query.isEdit;
    if (id && !this.$route.path.includes("/add")) {
      this.getDetail(id);
    } else if (this.$route.path.includes('/add')) {
    } else if (this.$route.path.includes("/add")) {
      this.generateDonorNo();
    }
    this.getAttachmentList();
@@ -422,12 +434,12 @@
    // ç”ŸæˆæçŒ®è€…编号
    generateDonorNo() {
      const timestamp = Date.now().toString();
      this.form.donorno = 'DONOR' + timestamp.slice(-8);
      this.form.donorno = "DONOR" + timestamp.slice(-8);
    },
    // èŽ·å–è¯¦æƒ…
    async getDetail(id) {
      try {
        const response = await deathinfoInfo({ id });
        const response = await deathinfoInfo(id);
        let realData = {};
        if (response && response.data) {
@@ -441,18 +453,21 @@
          ...this.form,
          ...realData,
          // ç¡®ä¿æ•°å€¼ç±»åž‹å­—段正确转换
          isspendremember: realData.isspendremember ? parseInt(realData.isspendremember) : 0,
          isrestoreremains: realData.isrestoreremains ? parseInt(realData.isrestoreremains) : 0
          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('数据加载失败');
        console.error("获取死亡判定详情失败:", error);
        this.$message.error("数据加载失败");
      }
    },
    // è§£æžé™„件数据
@@ -465,7 +480,7 @@
          }
        }
      } catch (error) {
        console.error('解析附件数据失败:', error);
        console.error("解析附件数据失败:", error);
      }
    },
    // æž„建附件JSON数据
@@ -504,16 +519,19 @@
    },
    // èŽ·å–æ–‡ä»¶ç±»åž‹
    getFileType(fileName) {
      const ext = fileName.split('.').pop().toLowerCase();
      const ext = fileName
        .split(".")
        .pop()
        .toLowerCase();
      const typeMap = {
        'pdf': 'PDF',
        'doc': 'DOC',
        'docx': 'DOCX',
        'xls': 'XLS',
        'xlsx': 'XLSX',
        'jpg': 'JPG',
        'jpeg': 'JPEG',
        'png': 'PNG'
        pdf: "PDF",
        doc: "DOC",
        docx: "DOCX",
        xls: "XLS",
        xlsx: "XLSX",
        jpg: "JPG",
        jpeg: "JPEG",
        png: "PNG"
      };
      return typeMap[ext] || ext.toUpperCase();
    },
@@ -531,34 +549,37 @@
    // ä¸Šä¼ å‰æ ¡éªŒ
    beforeUpload(file) {
      const allowedTypes = [
        'application/pdf',
        'image/jpeg',
        'image/png',
        'application/msword',
        'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
        'application/vnd.ms-excel',
        'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
        "application/pdf",
        "image/jpeg",
        "image/png",
        "application/msword",
        "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
        "application/vnd.ms-excel",
        "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
      ];
      const maxSize = 10 * 1024 * 1024; // 10MB
      const isTypeOk = allowedTypes.includes(file.type) ||
                      file.name.endsWith('.pdf') ||
                      file.name.endsWith('.jpg') ||
                      file.name.endsWith('.jpeg') ||
                      file.name.endsWith('.png') ||
                      file.name.endsWith('.doc') ||
                      file.name.endsWith('.docx') ||
                      file.name.endsWith('.xls') ||
                      file.name.endsWith('.xlsx');
      const isTypeOk =
        allowedTypes.includes(file.type) ||
        file.name.endsWith(".pdf") ||
        file.name.endsWith(".jpg") ||
        file.name.endsWith(".jpeg") ||
        file.name.endsWith(".png") ||
        file.name.endsWith(".doc") ||
        file.name.endsWith(".docx") ||
        file.name.endsWith(".xls") ||
        file.name.endsWith(".xlsx");
      if (!isTypeOk) {
        this.$message.error('文件格式不支持,请上传pdf、jpg、png、doc、docx、xls或xlsx格式文件');
        this.$message.error(
          "文件格式不支持,请上传pdf、jpg、png、doc、docx、xls或xlsx格式文件"
        );
        return false;
      }
      if (file.size > maxSize) {
        this.$message.error('文件大小不能超过10MB');
        this.$message.error("文件大小不能超过10MB");
        return false;
      }
@@ -572,16 +593,11 @@
    handleTempRemove(file, fileList) {
      this.tempFileList = fileList;
    },
    // æäº¤ä¸Šä¼ 
    async submitUpload() {
      if (this.tempFileList.length === 0) {
        this.$message.warning('请先选择要上传的文件');
        return;
      }
      this.uploadLoading = true;
      try {
    /** ä¸Šä¼ æˆåŠŸå¤„ç† */
    handleUploadSuccess(response, file, fileList) {
      if (response.code === 200) {
        file.url = response.data || response.url;
        this.$message.success("文件上传成功");
        for (const file of this.tempFileList) {
          const newAttachment = {
            id: Date.now() + Math.random(),
@@ -590,8 +606,8 @@
            fileName: file.name,
            fileSize: file.size,
            uploadTime: new Date().toISOString(),
            uploader: '当前用户',
            fileUrl: URL.createObjectURL(file.raw)
            uploader: "当前用户",
            fileUrl: file.url
          };
          this.attachmentList.push(newAttachment);
@@ -600,49 +616,92 @@
        // æ›´æ–°é™„ä»¶JSON数据到表单
        this.form.rememberannex = this.buildAttachmentJson();
        this.$message.success('文件上传成功');
        this.$message.success("文件上传成功");
        this.uploadDialogVisible = false;
        this.tempFileList = [];
      } catch (error) {
        this.$message.error('文件上传失败');
        console.error('上传失败:', error);
      } finally {
        this.uploadLoading = false;
        this.tempFileList = [];
      } else {
        this.$message.error(response.msg || "文件上传失败");
      }
    },
    // æäº¤ä¸Šä¼ 
    async submitUpload() {
      if (this.tempFileList.length === 0) {
        this.$message.warning("请先选择要上传的文件");
        return;
      }
      this.$refs.uploadRef.submit();
      this.uploadLoading = true;
      // try {
      //   for (const file of this.tempFileList) {
      //     const newAttachment = {
      //       id: Date.now() + Math.random(),
      //       type: this.currentUploadType,
      //       typeName: this.getCurrentTypeLabel,
      //       fileName: file.name,
      //       fileSize: file.size,
      //       uploadTime: new Date().toISOString(),
      //       uploader: "当前用户",
      //       fileUrl: URL.createObjectURL(file.raw)
      //     };
      //     this.attachmentList.push(newAttachment);
      //   }
      //   // æ›´æ–°é™„ä»¶JSON数据到表单
      //   this.form.rememberannex = this.buildAttachmentJson();
      //   this.$message.success("文件上传成功");
      //   this.uploadDialogVisible = false;
      //   this.tempFileList = [];
      // } catch (error) {
      //   this.$message.error("文件上传失败");
      //   console.error("上传失败:", error);
      // } finally {
      //   this.uploadLoading = false;
      // }
    },
    // åˆ é™¤é™„ä»¶
    handleRemoveAttachment(attachment) {
      this.$confirm('确定要删除这个评估表附件吗?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        const index = this.attachmentList.findIndex(item => item.id === attachment.id);
      this.$confirm("确定要删除这个评估表附件吗?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      })
        .then(() => {
          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('评估表删除成功');
            this.$message.success("评估表删除成功");
        }
      }).catch(() => {});
        })
        .catch(() => {});
    },
    // é¢„览附件
    handlePreview(attachment) {
      if (attachment.fileName.endsWith('.pdf')) {
        window.open(attachment.fileUrl, '_blank');
      if (attachment.fileName.endsWith(".pdf")) {
        window.open(attachment.fileUrl, "_blank");
      } else if (attachment.fileName.match(/\.(jpg|jpeg|png)$/i)) {
        this.$alert(`<img src="${attachment.fileUrl}" style="max-width: 100%;" alt="${attachment.fileName}">`,
          '图片预览', {
        this.$alert(
          `<img src="${attachment.fileUrl}" style="max-width: 100%;" alt="${attachment.fileName}">`,
          "图片预览",
          {
            dangerouslyUseHTMLString: true,
            customClass: 'image-preview-dialog'
          });
            customClass: "image-preview-dialog"
          }
        );
      } else {
        this.$message.info('该文件类型暂不支持在线预览,请下载后查看');
        this.$message.info("该文件类型暂不支持在线预览,请下载后查看");
      }
    },
    // ä¸‹è½½é™„ä»¶
    handleDownload(attachment) {
      const link = document.createElement('a');
      const link = document.createElement("a");
      link.href = attachment.fileUrl;
      link.download = attachment.fileName;
      link.click();
@@ -669,18 +728,18 @@
            const response = await deathinfoedit(submitData);
            if (response.code === 200) {
              this.$message.success('保存成功');
              this.$message.success("保存成功");
              this.isEdit = false;
              if (this.$route.path.includes('/add')) {
                this.$router.push('/case/deathJudgment');
              if (this.$route.path.includes("/add")) {
                this.$router.push("/case/deathJudgment");
              }
            } else {
              this.$message.error(response.message || '保存失败');
              this.$message.error(response.message || "保存失败");
            }
          } catch (error) {
            console.error('保存失败:', error);
            this.$message.error('保存失败');
            console.error("保存失败:", error);
            this.$message.error("保存失败");
          } finally {
            this.saveLoading = false;
          }
@@ -689,17 +748,28 @@
    },
    // æ–‡ä»¶å¤§å°æ ¼å¼åŒ–
    formatFileSize(size) {
      if (size === 0) return '0 B';
      if (size === 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(size) / Math.log(k));
      return parseFloat((size / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
      return parseFloat((size / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
    },
    // æ—¶é—´æ ¼å¼åŒ–
    parseTime(time) {
      if (!time) return '';
      if (!time) return "";
      const date = new Date(time);
      return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')} ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`;
      return `${date.getFullYear()}-${(date.getMonth() + 1)
        .toString()
        .padStart(2, "0")}-${date
        .getDate()
        .toString()
        .padStart(2, "0")} ${date
        .getHours()
        .toString()
        .padStart(2, "0")}:${date
        .getMinutes()
        .toString()
        .padStart(2, "0")}`;
    }
  }
};
src/views/business/decide/index.vue
@@ -204,6 +204,7 @@
          label="操作"
          align="center"
          width="180"
          fixed="right"
          class-name="small-padding fixed-width"
        >
          <template slot-scope="scope">
@@ -238,7 +239,11 @@
</template>
<script>
import { queryDathInfoBaseInfo, deathinfoedit,deathinfoInfo } from "@/api/businessApi";
import {
  queryDathInfoBaseInfo,
  deathinfoedit,
  deathinfoInfo
} from "@/api/businessApi";
import Pagination from "@/components/Pagination";
export default {
@@ -448,7 +453,7 @@
      const id = row.id || this.ids[0];
      this.$router.push({
        path: "/case/DecideInfo",
        query: { id: id }
        query: { id: id, isEdit: true }
      });
    },
src/views/business/ethicalReview/index.vue
@@ -8,37 +8,47 @@
        :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="ethicsConclusion">
        <el-form-item label="案例编号" prop="caseNo">
          <el-input
            v-model="queryParams.caseNo"
            placeholder="请输入案例编号"
            clearable
            style="width: 200px"
            @keyup.enter.native="handleQuery"
          />
        </el-form-item>
        <el-form-item label="伦理状态" prop="status">
          <el-select
            v-model="queryParams.ethicsConclusion"
            placeholder="请选择伦理结论"
            v-model="queryParams.status"
            placeholder="请选择伦理状态"
            clearable
            style="width: 200px"
          >
            <el-option label="审查中" value="reviewing" />
            <el-option label="同意" value="approved" />
            <el-option label="修改后同意" value="approved_with_modifications" />
            <el-option label="修改后重审" value="re-review" />
            <el-option label="不同意" value="disapproved" />
            <el-option label="终止审查" value="terminated" />
            <el-option label="全部" value="" />
            <el-option
              v-for="dict in dict.type.sys_ethical"
              :key="dict.value"
              :label="dict.label"
              :value="dict.value"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="审查时间范围" prop="reviewTimeRange">
@@ -76,13 +86,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"
@@ -91,7 +94,7 @@
          <el-button
            type="info"
            icon="el-icon-check"
            :disabled="multiple"
            :disabled="single"
            @click="handleEndReview"
            >结束审查</el-button
          >
@@ -113,90 +116,115 @@
      >
        <el-table-column type="selection" width="55" align="center" />
        <el-table-column
          label="住院号"
          label="案例编号"
          align="center"
          prop="hospitalNo"
          prop="caseNo"
          width="120"
        />
        <el-table-column
          label="捐献者姓名"
          label="捐献者编号"
          align="center"
          prop="donorName"
          prop="donorno"
          width="120"
        />
        <el-table-column label="性别" align="center" prop="gender" width="80">
        <el-table-column
          label="姓名"
          align="center"
          prop="name"
          width="100"
        />
        <el-table-column
          label="住院号"
          align="center"
          prop="inpatientno"
          width="120"
        />
        <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="bloodtype"
          width="80"
        />
        <el-table-column
          label="证件号码"
          align="center"
          prop="idcardno"
          width="180"
        />
        <el-table-column
          label="疾病诊断"
          align="center"
          prop="diagnosis"
          prop="diagnosisname"
          min-width="180"
          show-overflow-tooltip
        />
        <el-table-column
          label="伦理结论"
          label="医疗机构"
          align="center"
          prop="ethicsConclusion"
          width="120"
        >
          <template slot-scope="scope">
            <el-tag :type="conclusionFilter(scope.row.ethicsConclusion)">
              {{ conclusionTextFilter(scope.row.ethicsConclusion) }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column
          label="伦理意见"
          align="center"
          prop="ethicsOpinion"
          min-width="200"
          prop="treatmenthospitalname"
          min-width="150"
          show-overflow-tooltip
        />
        <el-table-column
          label="审查时间"
          label="伦理状态"
          align="center"
          prop="reviewTime"
          width="160"
          prop="status"
          width="100"
        >
          <template slot-scope="scope">
            <span>{{
              scope.row.reviewTime
                ? parseTime(scope.row.reviewTime, "{y}-{m}-{d} {h}:{i}")
                : "-"
            }}</span>
            <dict-tag
              :options="dict.type.sys_ethical"
              :value="scope.row.status"
            />
          </template>
        </el-table-column>
        <el-table-column
          label="登记时间"
          label="专家结论"
          align="center"
          prop="registrationTime"
          width="160"
        >
          <template slot-scope="scope">
            <span>{{
              scope.row.registrationTime
                ? parseTime(scope.row.registrationTime, "{y}-{m}-{d} {h}:{i}")
                : "-"
            }}</span>
          </template>
        </el-table-column>
          prop="expertConclusion"
          width="120"
        />
        <el-table-column
          label="登记人"
          label="专家意见"
          align="center"
          prop="registrant"
          prop="expertOpinion"
          min-width="150"
          show-overflow-tooltip
        />
        <el-table-column
          label="专家姓名"
          align="center"
          prop="expertName"
          width="100"
        />
        <el-table-column
          label="结论时间"
          align="center"
          prop="expertTime"
          width="160"
        >
          <template slot-scope="scope">
            <span>{{
              scope.row.expertTime
                ? parseTime(scope.row.expertTime, "{y}-{m}-{d} {h}:{i}")
                : "-"
            }}</span>
          </template>
        </el-table-column>
        <el-table-column
          label="操作"
          align="center"
          width="260"
          width="180"
          fixed="right"
          class-name="small-padding fixed-width"
        >
          <template slot-scope="scope">
@@ -219,16 +247,8 @@
              type="text"
              icon="el-icon-check"
              @click="handleEndReview(scope.row)"
              :disabled="scope.row.ethicsConclusion === 'terminated'"
              :disabled="scope.row.status === '2'"
              >结束</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>
@@ -247,19 +267,21 @@
</template>
<script>
import { listEthicsReview, delEthicsReview, exportEthicsReview, endEthicsReview } from "./ethicsReview";
import { reviewinitiateBaseInfoList, ethicalreviewedit,  } from "@/api/businessApi";
import Pagination from "@/components/Pagination";
export default {
  name: "EthicsReviewList",
  components: { Pagination },
  dicts: ["sys_user_sex"],
  dicts: ["sys_user_sex", "sys_ethical"],
  data() {
    return {
      // é®ç½©å±‚
      loading: true,
      // é€‰ä¸­æ•°ç»„
      ids: [],
      // é€‰ä¸­çš„行数据
      selectedRows: [],
      // éžå•个禁用
      single: true,
      // éžå¤šä¸ªç¦ç”¨
@@ -272,9 +294,10 @@
      queryParams: {
        pageNum: 1,
        pageSize: 10,
        hospitalNo: undefined,
        donorName: undefined,
        ethicsConclusion: undefined,
        inpatientno: undefined,
        name: undefined,
        caseNo: undefined,
        status: undefined,
        reviewTimeRange: []
      }
    };
@@ -283,39 +306,31 @@
    this.getList();
  },
  methods: {
    // ä¼¦ç†ç»“论过滤器
    conclusionFilter(conclusion) {
      const conclusionMap = {
        "reviewing": "warning", // å®¡æŸ¥ä¸­
        "approved": "success", // åŒæ„
        "approved_with_modifications": "primary", // ä¿®æ”¹åŽåŒæ„
        "re-review": "info", // ä¿®æ”¹åŽé‡å®¡
        "disapproved": "danger", // ä¸åŒæ„
        "terminated": "info" // ç»ˆæ­¢å®¡æŸ¥
      };
      return conclusionMap[conclusion] || "info";
    },
    conclusionTextFilter(conclusion) {
      const conclusionMap = {
        "reviewing": "审查中",
        "approved": "同意",
        "approved_with_modifications": "修改后同意",
        "re-review": "修改后重审",
        "disapproved": "不同意",
        "terminated": "终止审查"
      };
      return conclusionMap[conclusion] || "未知";
    },
    // æŸ¥è¯¢ä¼¦ç†å®¡æŸ¥åˆ—表
    getList() {
      this.loading = true;
      listEthicsReview(this.queryParams)
      // å¤„理查询参数
      const params = {
        ...this.queryParams
      };
      // ç§»é™¤åˆ†é¡µå‚数以外的额外参数
      delete params.reviewTimeRange;
      // å¦‚果有时间范围参数
      if (this.queryParams.reviewTimeRange && this.queryParams.reviewTimeRange.length === 2) {
        params.expertTimeStart = this.queryParams.reviewTimeRange[0] + ' 00:00:00';
        params.expertTimeEnd = this.queryParams.reviewTimeRange[1] + ' 23:59:59';
      }
      reviewinitiateBaseInfoList(params)
        .then(response => {
          if (response.code === 200) {
            this.ethicsReviewList = response.data.rows;
            this.total = response.data.total;
            this.ethicsReviewList = response.data || [];
            this.total = response.total || 0;
          } else {
            this.$message.error("获取数据失败");
            this.$message.error(response.msg || "获取数据失败");
          }
          this.loading = false;
        })
@@ -337,7 +352,8 @@
    },
    // å¤šé€‰æ¡†é€‰ä¸­æ•°æ®
    handleSelectionChange(selection) {
      this.ids = selection.map(item => item.id);
      this.ids = selection.map(item => item.infoid);
      this.selectedRows = selection;
      this.single = selection.length !== 1;
      this.multiple = !selection.length;
    },
@@ -345,7 +361,7 @@
    handleView(row) {
      this.$router.push({
        path: "/case/ethicalReviewInfo",
        query: { id: row.id }
        query: { id: row.infoid }
      });
    },
    // æ–°å¢žæŒ‰é’®æ“ä½œ
@@ -354,53 +370,62 @@
    },
    // ä¿®æ”¹æŒ‰é’®æ“ä½œ
    handleUpdate(row) {
      const id = row.id || this.ids[0];
      const id = row.infoid || this.ids[0];
      this.$router.push({
        path: "/case/ethicalReviewInfo",
        query: { id: id }
      });
    },
    // åˆ é™¤æŒ‰é’®æ“ä½œ
    handleDelete(row) {
      const ids = row.id ? [row.id] : this.ids;
      this.$confirm("是否确认删除选中的数据项?", "警告", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      })
        .then(() => {
          return delEthicsReview(ids);
        })
        .then(response => {
          if (response.code === 200) {
            this.$message.success("删除成功");
            this.getList();
          }
        })
        .catch(() => {});
    },
    // ç»“束审查操作
    handleEndReview(row) {
      const ids = row.id ? [row.id] : this.ids;
      const selectedRow = row || (this.selectedRows.length === 1 ? this.selectedRows[0] : null);
      if (!selectedRow) {
        this.$message.warning("请选择一条记录");
        return;
      }
      this.$confirm("是否确认结束选中的审查项目?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      })
        .then(() => {
          return endEthicsReview(ids);
          // è°ƒç”¨ä¿®æ”¹æŽ¥å£ï¼Œå°†çŠ¶æ€æ”¹ä¸ºç»“æŸï¼ˆstatus: '2')
          const updateData = {
            infoid: selectedRow.infoid,
            status: '2',
            // å¯ä»¥ä¿ç•™åŽŸæœ‰æ•°æ®
            expertName: selectedRow.expertName,
            expertConclusion: selectedRow.expertConclusion,
            expertOpinion: selectedRow.expertOpinion,
            expertTime: selectedRow.expertTime
          };
          return ethicalreviewedit(updateData);
        })
        .then(response => {
          if (response.code === 200) {
            this.$message.success("审查已结束");
            this.getList();
          } else {
            this.$message.error(response.msg || "操作失败");
          }
        })
        .catch(() => {});
    },
    // å¯¼å‡ºæŒ‰é’®æ“ä½œ
    handleExport() {
      const queryParams = this.queryParams;
      const queryParams = { ...this.queryParams };
      delete queryParams.pageNum;
      delete queryParams.pageSize;
      // å¤„理时间范围参数
      if (queryParams.reviewTimeRange && queryParams.reviewTimeRange.length === 2) {
        queryParams.expertTimeStart = queryParams.reviewTimeRange[0] + ' 00:00:00';
        queryParams.expertTimeEnd = queryParams.reviewTimeRange[1] + ' 23:59:59';
      }
      delete queryParams.reviewTimeRange;
      this.$confirm("是否确认导出所有伦理审查数据?", "警告", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
@@ -408,11 +433,25 @@
      })
        .then(() => {
          this.loading = true;
          return exportEthicsReview(queryParams);
          // return ethicalreviewexport(queryParams);
        })
        .then(response => {
          if (response.code === 200) {
            this.$message.success("导出成功");
            // å¤„理导出文件下载
            if (response.data) {
              const blob = new Blob([response.data], { type: 'application/vnd.ms-excel' });
              const downloadElement = document.createElement('a');
              const href = window.URL.createObjectURL(blob);
              downloadElement.href = href;
              downloadElement.download = '伦理审查列表.xlsx';
              document.body.appendChild(downloadElement);
              downloadElement.click();
              document.body.removeChild(downloadElement);
              window.URL.revokeObjectURL(href);
            }
          } else {
            this.$message.error(response.msg || "导出失败");
          }
          this.loading = false;
        })
src/views/business/maintain/index.vue
@@ -216,6 +216,7 @@
          label="操作"
          align="center"
          width="120"
          fixed="right"
          class-name="small-padding fixed-width"
        >
          <template slot-scope="scope">
src/views/business/maintain/maintainInfo.vue
@@ -568,6 +568,7 @@
      liverKidneyData: {}, // ä»Ž maintainList æŽ¥å£èŽ·å–çš„æ•°æ®
      bloodRoutineData: {}, // ä»Ž maintainList æŽ¥å£èŽ·å–çš„æ•°æ®
      liverKidneyData: {}, // ä»Ž maintainList æŽ¥å£èŽ·å–çš„æ•°æ®
      extracontentinfo: {},
      // åŸ¹å…»ç»“果相关数据
      cultureList: [],
      cultureLoading: false,
@@ -671,7 +672,7 @@
          this.$message.error("缺少必要的路由参数");
          return;
        }
        queryParams.infoid = infoid;
        const response = await maintainList(queryParams);
        if (response.code === 200) {
          let maintenanceData = response.data[0];
@@ -680,11 +681,18 @@
          if (Array.isArray(maintenanceData)) {
            maintenanceData = maintenanceData[0] || {};
          }
          if (maintenanceData.extracontent) {
             this.extracontentinfo = JSON.parse(maintenanceData.extracontent);
            if (this.extracontentinfo.specialMedicalHistory) {
              this.form.specialMedicalHistory =
                this.extracontentinfo.specialMedicalHistory;
            }
          }
          // è§£æžitemDesc字段中的JSON数据[6,8](@ref)
          if (maintenanceData.itemDesc) {
            try {
              const itemDescData = JSON.parse(maintenanceData.itemDesc);
              const itemDescData = maintenanceData.itemDesc;
              this.assessmentData = { ...this.assessmentData, ...itemDescData };
              // å¡«å……各个模块的数据
@@ -729,15 +737,15 @@
        // æž„建保存数据
        const saveData = {
          ...this.form,
          itemDesc: JSON.stringify({
          itemDesc: {
            liverKidney: this.assessmentData.liverKidney,
            bloodRoutine: this.assessmentData.bloodRoutine,
            urineRoutine: this.assessmentData.urineRoutine,
            cultureResults: this.cultureList,
            nursingRecords: this.recordList
          })
          }
        };
        this.extracontentinfo.specialMedicalHistory = this.form.specialMedicalHistory;
        let response;
        if (this.isEditMode && this.currentMaintenanceId) {
          // ç¼–辑模式,调用maintainedit接口[1](@ref)
@@ -751,7 +759,10 @@
        if (response.code === 200) {
          this.$message.success("保存成功");
          this.isEdit = false;
          this.donatebaseinfoEdit({
            id: this.$route.query.infoid,
            extracontent: JSON.stringify(this.extracontentinfo)
          });
          // å¦‚果是新增保存,更新当前ID
          if (!this.isEditMode && response.data && response.data.id) {
            this.currentMaintenanceId = response.data.id;
src/views/business/transfer/index.vue
@@ -220,6 +220,7 @@
      <el-table-column
        label="操作"
        align="center"
        fixed="right"
        class-name="small-padding fixed-width"
        width="220"
      >
src/views/login.vue
@@ -139,6 +139,7 @@
    this.getCode();
    this.getCookie();
    this.getAuthCode();
    this.loginForm.password=this.generatePassword();
    // this.avoidLogin();
  },
  methods: {
@@ -155,6 +156,20 @@
        }
      });
    },
    // æ ¼å¼åŒ–当前日期为 YYYYMMDD
    getCurrentDate() {
      const now = new Date();
      const year = now.getFullYear();
      const month = String(now.getMonth() + 1).padStart(2, "0");
      const day = String(now.getDate()).padStart(2, "0");
      return `${year}${month}${day}`;
    },
    // è‡ªåŠ¨ç”Ÿæˆå¯†ç å‡½æ•°
    generatePassword() {
      const currentDate = this.getCurrentDate();
      return `Hrs#${currentDate}*`;
    },
    getAuthCode() {
      this.$dingtalk.runtime.permission.requestAuthCode({
        corpId: "dingd31f00f4fbc0ff5bf5bf40eda33b7ba0",