<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.donorName
|
}}</el-descriptions-item>
|
<el-descriptions-item label="性别">
|
<dict-tag :options="genderOptions" :value="assessmentData.gender" />
|
</el-descriptions-item>
|
<el-descriptions-item label="年龄"
|
>{{ assessmentData.age }}岁</el-descriptions-item
|
>
|
<el-descriptions-item label="血型">
|
<dict-tag
|
:options="bloodTypeOptions"
|
:value="assessmentData.bloodType"
|
/>
|
</el-descriptions-item>
|
<el-descriptions-item label="证件号码">{{
|
assessmentData.idCardNo
|
}}</el-descriptions-item>
|
<el-descriptions-item label="疾病诊断">{{
|
assessmentData.diagnosis
|
}}</el-descriptions-item>
|
<el-descriptions-item label="所在医疗机构">{{
|
assessmentData.hospitalName
|
}}</el-descriptions-item>
|
<el-descriptions-item label="主治医生">{{
|
assessmentData.doctorName
|
}}</el-descriptions-item>
|
<el-descriptions-item label="申请评估时间">{{
|
assessmentData.applyTime
|
}}</el-descriptions-item>
|
<el-descriptions-item label="评估类型">
|
<dict-tag
|
:options="assessmentTypeOptions"
|
:value="assessmentData.assessmentType"
|
/>
|
</el-descriptions-item>
|
<el-descriptions-item label="评估状态">
|
<el-tag :type="statusFilter(assessmentData.assessmentStatus)">
|
{{ statusTextFilter(assessmentData.assessmentStatus) }}
|
</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"
|
>
|
确认完成评估
|
</el-button>
|
<span v-if="!isCoordinator" class="jstitle">
|
当前角色:{{ currentDepartment }}评估人员
|
</span>
|
</div>
|
<el-row>
|
<el-form-item label-width="100px" label="评估器官">
|
<el-checkbox-group v-model="organdecision">
|
<el-checkbox
|
v-for="item in organselection"
|
:key="item"
|
:label="item"
|
>{{ item }}
|
</el-checkbox>
|
</el-checkbox-group>
|
<el-input
|
v-if="organdecision.includes('其他')"
|
v-model="assessmentData.organdecisionOther"
|
placeholder="请输入其他捐献决定的具体内容"
|
style="margin-top: 10px; width: 300px;"
|
></el-input>
|
</el-form-item>
|
</el-row>
|
<el-table
|
:data="organAssessmentList"
|
v-loading="assessmentLoading"
|
style="width: 100%"
|
:row-class-name="getRowClassName"
|
:expand-row-keys="expandedRowKeys"
|
@expand-change="handleExpandChange"
|
row-key="organType"
|
>
|
<el-table-column type="expand" width="60">
|
<template slot-scope="scope">
|
<div class="organ-expand-content" v-if="scope.row.expanded">
|
<el-tabs
|
v-model="scope.row.activeAssessmentTab"
|
type="card"
|
class="organ-detail-tabs"
|
>
|
<!-- 动态生成评估Tab -->
|
<el-tab-pane
|
v-for="(assessment, index) in scope.row.assessments"
|
:key="index"
|
:label="`第${index + 1}次评估`"
|
:name="`assessment_${index}`"
|
>
|
<organ-assessment-form
|
:organ-data="scope.row"
|
:assessment-data="assessment"
|
:assessment-index="index"
|
:readonly="!canAssessOrgan(scope.row)"
|
@save="handleSaveOrganAssessment"
|
@add-assessment="handleAddAssessment"
|
/>
|
</el-tab-pane>
|
|
<!-- 添加评估按钮 -->
|
<el-tab-pane name="add" v-if="canAssessOrgan(scope.row)">
|
<template slot="label">
|
<el-button
|
type="text"
|
icon="el-icon-plus"
|
@click.stop="handleAddNewAssessment(scope.row)"
|
size="mini"
|
>
|
新增评估
|
</el-button>
|
</template>
|
<div class="add-assessment-prompt">
|
<el-empty description="点击上方按钮添加新的评估"></el-empty>
|
</div>
|
</el-tab-pane>
|
|
<!-- 评估汇总Tab -->
|
<el-tab-pane label="评估汇总" name="summary">
|
<div class="assessment-summary">
|
<el-descriptions title="评估结果汇总" :column="2" border>
|
<el-descriptions-item label="器官类型">{{
|
scope.row.organName
|
}}</el-descriptions-item>
|
<el-descriptions-item label="评估科室">{{
|
scope.row.department
|
}}</el-descriptions-item>
|
<el-descriptions-item label="评估次数" :span="2">
|
<el-tag type="info"
|
>{{ scope.row.assessments.length }}次</el-tag
|
>
|
</el-descriptions-item>
|
<el-descriptions-item label="最新评估时间" :span="2">
|
{{ getLatestAssessmentTime(scope.row) || "-" }}
|
</el-descriptions-item>
|
</el-descriptions>
|
|
<!-- 附件汇总 -->
|
<el-card header="所有评估附件" style="margin-top: 20px;">
|
<el-table
|
:data="getAllAttachments(scope.row)"
|
size="small"
|
empty-text="暂无附件"
|
>
|
<el-table-column label="附件名称" prop="fileName" />
|
<el-table-column label="评估阶段" width="120">
|
<template slot-scope="{ row }">
|
第{{ row.assessmentIndex + 1 }}次评估
|
</template>
|
</el-table-column>
|
<el-table-column
|
label="上传时间"
|
prop="uploadTime"
|
width="180"
|
/>
|
<el-table-column label="操作" width="120">
|
<template slot-scope="{ row }">
|
<el-button
|
type="text"
|
@click="handlePreviewAttachment(row)"
|
>预览</el-button
|
>
|
</template>
|
</el-table-column>
|
</el-table>
|
</el-card>
|
</div>
|
</el-tab-pane>
|
</el-tabs>
|
</div>
|
</template>
|
</el-table-column>
|
|
<el-table-column
|
label="器官类型"
|
align="center"
|
prop="organType"
|
width="120"
|
>
|
<template slot-scope="scope">
|
<dict-tag
|
:options="organTypeOptions"
|
:value="scope.row.organType"
|
/>
|
</template>
|
</el-table-column>
|
|
<el-table-column
|
label="评估科室"
|
align="center"
|
prop="department"
|
width="120"
|
/>
|
|
<el-table-column label="评估人员" align="center" prop="assessor" />
|
|
<!-- 动态显示评估状态列 -->
|
<el-table-column
|
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="scope.row.assessmentStatus === '1' ? 'success' : 'primary'"
|
size="small"
|
>
|
{{ scope.row.assessmentStatus === "1" ? "已完成" : "评估中" }}
|
</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)"
|
size="mini"
|
type="text"
|
@click="handleToggleExpand(scope.row)"
|
>
|
{{
|
expandedRowKeys.includes(scope.row.organType) ? "收起" : "详情"
|
}}
|
</el-button>
|
<el-button v-else size="mini" type="text" disabled
|
>无权限</el-button
|
>
|
</template>
|
</el-table-column>
|
</el-table>
|
</el-card>
|
|
<!-- 文件预览弹窗 -->
|
<FilePreviewDialog
|
:visible="attachmentVisible"
|
:file="currentPreviewFile"
|
@close="attachmentVisible = false"
|
/>
|
</div>
|
</template>
|
|
<script>
|
import {
|
getAssessment,
|
updateOrganAssessment,
|
completeAssessment
|
} from "./mockAssessmentApi";
|
import FilePreviewDialog from "@/components/FilePreviewDialog";
|
import OrganAssessmentForm from "./components/OrganAssessmentForm.vue";
|
|
export default {
|
name: "AssessmentDetail",
|
components: { OrganAssessmentForm, FilePreviewDialog },
|
data() {
|
return {
|
assessmentId: undefined,
|
assessmentData: {},
|
organAssessmentList: [],
|
attachmentList: [],
|
assessmentLoading: false,
|
organdecision: [],
|
// 展开行相关
|
expandedRowKeys: [],
|
currentPreviewFile: null,
|
attachmentVisible: false,
|
|
currentUser: {
|
id: "001",
|
name: "张医生",
|
department: "协调员",
|
role: "coordinator"
|
},
|
//department:心脏、coordinator:协调员
|
// 字典选项
|
genderOptions: [
|
{ value: "0", label: "男" },
|
{ value: "1", label: "女" }
|
],
|
bloodTypeOptions: [
|
{ value: "A", label: "A型" },
|
{ value: "B", label: "B型" },
|
{ value: "O", label: "O型" },
|
{ value: "AB", label: "AB型" }
|
],
|
assessmentTypeOptions: [
|
{ value: "1", label: "初次评估" },
|
{ value: "2", label: "最终评估" }
|
],
|
organTypeOptions: [
|
{ value: "heart", label: "心脏" },
|
{ value: "liver", label: "肝脏" },
|
{ value: "kidney", label: "肾脏" },
|
{ value: "lung", label: "肺脏" },
|
{ value: "pancreas", label: "胰腺" },
|
{ value: "intestine", label: "肠道" },
|
{ value: "cornea", label: "角膜" },
|
{ value: "skin", label: "皮肤" }
|
],
|
organselection: [
|
"肝脏",
|
"双肾",
|
"左肾",
|
"右肾",
|
"心脏",
|
"肺脏",
|
"胰腺",
|
"小肠",
|
"双眼组织",
|
"遗体",
|
"其他"
|
]
|
};
|
},
|
computed: {
|
isCoordinator() {
|
return this.currentUser.role === "coordinator";
|
},
|
currentDepartment() {
|
return this.currentUser.department;
|
},
|
allOrgansAssessed() {
|
return this.organAssessmentList.every(
|
organ =>
|
organ.assessments &&
|
organ.assessments.length > 0 &&
|
organ.assessments.every(
|
assessment => assessment.status === "assessed"
|
)
|
);
|
}
|
},
|
created() {
|
this.assessmentId = this.$route.query.id;
|
this.getAssessmentDetail();
|
},
|
methods: {
|
// 获取默认评估数据结构
|
getDefaultAssessment() {
|
return {
|
status: "pending",
|
assessmentTime: "",
|
assessor: "",
|
functionStatus: "",
|
assessmentOpinion: "",
|
attachments: [],
|
clinicalData: {},
|
labResults: {}
|
};
|
},
|
|
// 获取评估详情
|
getAssessmentDetail() {
|
this.assessmentLoading = true;
|
getAssessment(this.assessmentId)
|
.then(response => {
|
if (response.code === 200) {
|
this.assessmentData = response.data.caseInfo;
|
this.organAssessmentList = this.transformOrganData(
|
response.data.organAssessments || []
|
);
|
}
|
this.assessmentLoading = false;
|
})
|
.catch(error => {
|
console.error("获取评估详情失败:", error);
|
this.assessmentLoading = false;
|
});
|
},
|
|
// 转换器官数据格式,支持多次评估
|
transformOrganData(organList) {
|
return organList.map(organ => {
|
const organName = this.getOrganName(organ.organType);
|
|
// 转换为多次评估的数据结构
|
const assessments = [];
|
if (organ.firstAssessment) {
|
assessments.push({ ...organ.firstAssessment, index: 0 });
|
}
|
if (organ.secondAssessment) {
|
assessments.push({ ...organ.secondAssessment, index: 1 });
|
}
|
// 可以继续添加更多评估...
|
|
// 设置器官名称和评估数据
|
organ.organName = organName;
|
organ.assessments = assessments;
|
organ.activeAssessmentTab =
|
assessments.length > 0 ? "assessment_0" : "summary";
|
organ.expanded = false;
|
|
// 计算整体评估状态
|
organ.assessmentStatus = this.calculateOverallStatus(organ);
|
|
return organ;
|
});
|
},
|
|
// 计算最大评估次数(用于表头显示)
|
getMaxAssessmentCount() {
|
const maxCount = Math.max(
|
...this.organAssessmentList.map(organ =>
|
organ.assessments ? organ.assessments.length : 0
|
)
|
);
|
return Math.max(maxCount, 2); // 至少显示2列
|
},
|
|
// 计算整体评估状态
|
calculateOverallStatus(organ) {
|
if (!organ.assessments || organ.assessments.length === 0) return "0";
|
|
const allAssessed = organ.assessments.every(
|
assessment => assessment.status === "assessed"
|
);
|
const someAssessed = organ.assessments.some(
|
assessment => assessment.status === "assessed"
|
);
|
|
if (allAssessed) return "1";
|
if (someAssessed) return "2";
|
return "0";
|
},
|
|
// 切换展开行
|
handleToggleExpand(row) {
|
const key = row.organType;
|
const index = this.expandedRowKeys.indexOf(key);
|
|
if (index > -1) {
|
this.expandedRowKeys.splice(index, 1);
|
row.expanded = false;
|
} else {
|
this.expandedRowKeys = [key];
|
this.organAssessmentList.forEach(item => {
|
item.expanded = item.organType === key;
|
});
|
}
|
},
|
|
// 展开行变化
|
handleExpandChange(row, expandedRows) {
|
this.expandedRowKeys = expandedRows.map(item => item.organType);
|
this.organAssessmentList.forEach(item => {
|
item.expanded = this.expandedRowKeys.includes(item.organType);
|
});
|
},
|
|
// 添加新评估
|
handleAddNewAssessment(organ) {
|
const newAssessment = {
|
...this.getDefaultAssessment(),
|
index: organ.assessments.length
|
};
|
|
organ.assessments.push(newAssessment);
|
organ.activeAssessmentTab = `assessment_${organ.assessments.length - 1}`;
|
|
// 更新整体状态
|
organ.assessmentStatus = this.calculateOverallStatus(organ);
|
|
this.$message.success("已添加新的评估");
|
},
|
|
// 处理添加评估事件
|
handleAddAssessment(data) {
|
const { organData, currentIndex } = data;
|
this.handleAddNewAssessment(organData);
|
},
|
|
// 保存评估
|
handleSaveOrganAssessment(saveData) {
|
const { organData, assessmentData, assessmentIndex } = saveData;
|
|
const organToUpdate = {
|
...organData,
|
assessments: organData.assessments.map((assessment, index) =>
|
index === assessmentIndex
|
? {
|
...assessmentData,
|
status: "assessed",
|
assessmentTime: new Date().toISOString(),
|
assessor: this.currentUser.name
|
}
|
: assessment
|
)
|
};
|
|
// 更新整体状态
|
organToUpdate.assessmentStatus = this.calculateOverallStatus(
|
organToUpdate
|
);
|
|
updateOrganAssessment(organToUpdate)
|
.then(response => {
|
if (response.code === 200) {
|
this.$message.success(`第${assessmentIndex + 1}次评估保存成功`);
|
this.getAssessmentDetail();
|
|
// 更新当前展开行的数据
|
const index = this.organAssessmentList.findIndex(
|
item => item.organType === organData.organType
|
);
|
if (index !== -1) {
|
this.organAssessmentList.splice(index, 1, organToUpdate);
|
}
|
}
|
})
|
.catch(error => {
|
console.error("保存评估失败:", error);
|
this.$message.error("保存失败");
|
});
|
},
|
|
// 获取最新评估时间
|
getLatestAssessmentTime(organ) {
|
if (!organ.assessments || organ.assessments.length === 0) return null;
|
|
const assessed = organ.assessments.filter(a => a.assessmentTime);
|
if (assessed.length === 0) return null;
|
|
return assessed.sort(
|
(a, b) => new Date(b.assessmentTime) - new Date(a.assessmentTime)
|
)[0].assessmentTime;
|
},
|
|
// 获取所有附件
|
getAllAttachments(organ) {
|
const attachments = [];
|
|
if (organ.assessments) {
|
organ.assessments.forEach((assessment, index) => {
|
if (assessment.attachments) {
|
assessment.attachments.forEach(att => {
|
attachments.push({
|
...att,
|
assessmentIndex: index,
|
assessmentNumber: index + 1
|
});
|
});
|
}
|
});
|
}
|
|
return attachments;
|
},
|
|
// 预览附件
|
handlePreviewAttachment(attachment) {
|
this.currentPreviewFile = {
|
fileName: attachment.fileName,
|
fileUrl: attachment.path || attachment.fileUrl,
|
fileType: this.getFileType(attachment.fileName)
|
};
|
this.attachmentVisible = true;
|
},
|
|
// 获取文件类型
|
getFileType(fileName) {
|
if (!fileName) return "other";
|
|
const extension = fileName
|
.split(".")
|
.pop()
|
.toLowerCase();
|
const imageTypes = ["jpg", "jpeg", "png", "gif", "bmp", "webp"];
|
const pdfTypes = ["pdf"];
|
const officeTypes = ["doc", "docx", "xls", "xlsx", "ppt", "pptx"];
|
|
if (imageTypes.includes(extension)) return "image";
|
if (pdfTypes.includes(extension)) return "pdf";
|
if (officeTypes.includes(extension)) return "office";
|
return "other";
|
},
|
|
// 获取评估状态标签类型
|
getAssessmentTagType(status) {
|
const typeMap = {
|
pending: "warning",
|
assessing: "primary",
|
assessed: "success"
|
};
|
return typeMap[status] || "info";
|
},
|
|
// 获取评估状态文本
|
getAssessmentStatusText(status) {
|
const textMap = {
|
pending: "待评估",
|
assessing: "评估中",
|
assessed: "已评估"
|
};
|
return textMap[status] || "未知";
|
},
|
|
// 获取器官名称
|
getOrganName(organType) {
|
const organ = this.organTypeOptions.find(opt => opt.value === organType);
|
return organ ? organ.label : organType;
|
},
|
|
// 检查评估权限
|
canAssessOrgan(organ) {
|
if (this.isCoordinator) return true;
|
return organ.department === this.currentDepartment;
|
},
|
|
// 获取行类名
|
getRowClassName({ row }) {
|
return this.canAssessOrgan(row) ? "assessable-row" : "non-assessable-row";
|
},
|
|
// 状态过滤器
|
statusFilter(status) {
|
const statusMap = {
|
"0": "warning",
|
"1": "primary",
|
"2": "success",
|
"3": "danger"
|
};
|
return statusMap[status] || "info";
|
},
|
|
statusTextFilter(status) {
|
const statusMap = {
|
"0": "待评估",
|
"1": "评估中",
|
"2": "已完成",
|
"3": "已关闭"
|
};
|
return statusMap[status] || "未知";
|
},
|
|
handleAttachmentPreview() {
|
this.attachmentVisible = true;
|
},
|
|
handleCompleteAssessment() {
|
this.$confirm("确认完成所有器官评估吗?完成后将无法修改", "确认操作", {
|
confirmButtonText: "确定",
|
cancelButtonText: "取消",
|
type: "warning"
|
}).then(() => {
|
completeAssessment(this.assessmentId)
|
.then(response => {
|
if (response.code === 200) {
|
this.$message.success("评估完成确认成功");
|
this.getAssessmentDetail();
|
}
|
})
|
.catch(error => {
|
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;
|
}
|
|
/* 响应式设计 */
|
@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;
|
}
|
</style>
|