| | |
| | | <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;" |
| | |
| | | <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> |
| | | |
| | |
| | | <!-- 评估汇总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=" |
| | |
| | | ? 'success' |
| | | : 'info' |
| | | " |
| | | size="small" |
| | | > |
| | | {{ scope.row.isbiopsybefore === "1" ? "是" : "否" }} |
| | | </el-tag> |
| | |
| | | ? 'success' |
| | | : 'info' |
| | | " |
| | | size="small" |
| | | > |
| | | {{ scope.row.isbiopsyafter === "1" ? "是" : "否" }} |
| | | </el-tag> |
| | |
| | | ? 'warning' |
| | | : 'info' |
| | | " |
| | | size="small" |
| | | > |
| | | {{ |
| | | scope.row.ismarginalorgan === "1" ? "是" : "否" |
| | |
| | | ? 'danger' |
| | | : 'info' |
| | | " |
| | | size="small" |
| | | > |
| | | {{ |
| | | scope.row.ispathogenpositive === "1" ? "是" : "否" |
| | |
| | | </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" /> |
| | | |
| | |
| | | |
| | | <!-- 动态显示评估状态列 --> |
| | | <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> |
| | |
| | | |
| | | <!-- 整体保存按钮 --> |
| | | <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> |
| | | |
| | |
| | | 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: { |
| | |
| | | }, |
| | | // 根据捐献决定过滤后的器官列表 |
| | | 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); |
| | | }, |
| | |
| | | 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, |
| | |
| | | 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, |
| | |
| | | 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; |
| | | } |
| | |
| | | }, |
| | | |
| | | // 捐献决定变更处理 |
| | | 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 = []; |
| | | } |
| | |
| | | |
| | | // 自动处理决定变更逻辑 |
| | | 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")) { |
| | | // 可以设置只保留遗体捐献,或者根据业务需求处理 |
| | | } |
| | | }, |
| | |
| | | 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]; |
| | |
| | | handleResponseData(response) { |
| | | let detailData = null; |
| | | |
| | | // 根据接口实际返回的数据结构进行调整 |
| | | if (response.data) { |
| | | if (Array.isArray(response.data)) { |
| | | detailData = response.data[0] || {}; |
| | |
| | | detailData = response; |
| | | } |
| | | |
| | | // 映射字段到评估数据 |
| | | this.assessmentData = { |
| | | id: detailData.id || this.assessmentId, |
| | | infoid: detailData.infoid || this.infoid, |
| | |
| | | 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); |
| | | }, |
| | | |
| | |
| | | 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" |
| | | }; |
| | | }); |
| | | }, |
| | |
| | | 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" |
| | | ); |
| | | |
| | |
| | | |
| | | // 添加新评估 |
| | | 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( |
| | |
| | | |
| | | // 检查评估权限 |
| | | canAssessOrgan(organ) { |
| | | console.log(organ,'organ'); |
| | | |
| | | if (this.isCoordinator) return true; |
| | | if (!this.isEdit) return false; |
| | | return ( |
| | |
| | | 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; |
| | | |
| | |
| | | } |
| | | ); |
| | | |
| | | // 更新评估状态为已完成 |
| | | const updateData = { |
| | | ...this.assessmentData, |
| | | assessState: "3", |
| | |
| | | .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> |