<template>
|
<div class="donation-process-detail">
|
<el-card class="process-card">
|
<div class="process-container">
|
<!-- 左侧时间线 -->
|
<div class="timeline-section">
|
<div class="section-header">
|
<h3>捐献进程时间线</h3>
|
<el-tag :type="getOverallStatusTag(caseInfo.status)">
|
{{ getStatusText(caseInfo.status) }}
|
</el-tag>
|
</div>
|
|
<div class="timeline-container">
|
<div
|
v-for="stage in processStages"
|
:key="stage.key"
|
class="timeline-item"
|
:class="{
|
'active': activeStage === stage.key,
|
'completed': stage.status === 'completed',
|
'in-progress': stage.status === 'in_progress',
|
'pending': stage.status === 'pending'
|
}"
|
@click="handleStageClick(stage)"
|
>
|
<div class="timeline-marker">
|
<i v-if="stage.status === 'completed'" class="el-icon-check"></i>
|
<i v-else-if="stage.status === 'in_progress'" class="el-icon-loading"></i>
|
<i v-else class="el-icon-time"></i>
|
</div>
|
|
<div class="timeline-content">
|
<div class="stage-header">
|
<span class="stage-name">{{ stage.name }}</span>
|
<el-tag
|
size="small"
|
:type="getStageStatusTag(stage.status)"
|
>
|
{{ getStageStatusText(stage.status) }}
|
</el-tag>
|
</div>
|
|
<div class="stage-info">
|
<div v-if="stage.completeTime" class="time-info">
|
<span>完成时间: {{ formatTime(stage.completeTime) }}</span>
|
</div>
|
<div v-if="stage.updateTime" class="time-info">
|
<span>最近更新: {{ formatTime(stage.updateTime) }}</span>
|
</div>
|
<div v-if="stage.operator" class="operator-info">
|
<span>负责人: {{ stage.operator }}</span>
|
</div>
|
</div>
|
</div>
|
</div>
|
</div>
|
</div>
|
|
<!-- 右侧内容区域 -->
|
<div class="content-section">
|
<!-- 案例基本信息 -->
|
<div class="basic-info-section">
|
<div class="section-header">
|
<h3>案例基本信息</h3>
|
<el-button
|
type="primary"
|
size="small"
|
@click="handleEditBasicInfo"
|
>
|
编辑信息
|
</el-button>
|
</div>
|
|
<el-descriptions :column="2" border>
|
<el-descriptions-item label="住院号">
|
{{ caseInfo.caseNo }}
|
</el-descriptions-item>
|
<el-descriptions-item label="住院号">
|
{{ caseInfo.hospitalNo }}
|
</el-descriptions-item>
|
<el-descriptions-item label="捐献者姓名">
|
{{ caseInfo.donorName }}
|
</el-descriptions-item>
|
<el-descriptions-item label="性别">
|
<dict-tag
|
:options="dict.type.sys_user_sex"
|
:value="parseInt(caseInfo.gender)"
|
/>
|
</el-descriptions-item>
|
<el-descriptions-item label="年龄">
|
{{ caseInfo.age }} 岁
|
</el-descriptions-item>
|
<el-descriptions-item label="血型">
|
<dict-tag
|
:options="dict.type.sys_BloodType"
|
:value="caseInfo.bloodType"
|
/>
|
</el-descriptions-item>
|
<el-descriptions-item label="疾病诊断">
|
{{ caseInfo.diagnosis }}
|
</el-descriptions-item>
|
<el-descriptions-item label="案例状态">
|
<el-tag :type="getOverallStatusTag(caseInfo.status)">
|
{{ getStatusText(caseInfo.status) }}
|
</el-tag>
|
</el-descriptions-item>
|
<el-descriptions-item label="创建时间">
|
{{ formatTime(caseInfo.createTime) }}
|
</el-descriptions-item>
|
<el-descriptions-item label="登记人">
|
{{ caseInfo.registrant }}
|
</el-descriptions-item>
|
<el-descriptions-item label="当前阶段">
|
{{ getCurrentStageName() }}
|
</el-descriptions-item>
|
</el-descriptions>
|
</div>
|
|
<!-- 阶段详情内容 -->
|
<div class="stage-detail-section">
|
<div class="section-header">
|
<h3>{{ activeStageName }} - 阶段详情</h3>
|
<div class="stage-actions">
|
<!-- <el-button
|
v-if="activeStageData.status !== 'completed'"
|
type="success"
|
size="small"
|
@click="handleCompleteStage"
|
>
|
完成阶段
|
</el-button>
|
<el-button
|
type="primary"
|
size="small"
|
@click="handleViewDetail"
|
>
|
查看详情
|
</el-button>
|
<el-button
|
v-if="activeStageData.status === 'completed'"
|
type="warning"
|
size="small"
|
@click="handleModifyStage"
|
>
|
修改信息
|
</el-button> -->
|
</div>
|
</div>
|
|
<!-- 动态阶段内容 -->
|
<div class="stage-content">
|
<component
|
:is="getStageComponent()"
|
:stageData="activeStageData"
|
:caseInfo="caseInfo"
|
/>
|
</div>
|
</div>
|
</div>
|
</div>
|
</el-card>
|
</div>
|
</template>
|
|
<script>
|
import { getDonationProcessDetail } from './donationProcess';
|
import DonorMaintenanceStage from './components/DonorMaintenanceStage';
|
import MedicalAssessmentStage from './components/MedicalAssessmentStage';
|
import DeathJudgmentStage from './components/DeathJudgmentStage';
|
import DonationConfirmStage from './components/DonationConfirmStage';
|
import EthicalReviewStage from './components/EthicalReviewStage';
|
import OrganAllocationStage from './components/OrganAllocationStage';
|
import OrganProcurementStage from './components/OrganProcurementStage';
|
import OrganUtilizationStage from './components/OrganUtilizationStage';
|
import dayjs from "dayjs";
|
|
export default {
|
name: 'DonationProcessDetail',
|
components: {
|
DonorMaintenanceStage,
|
MedicalAssessmentStage,
|
DeathJudgmentStage,
|
DonationConfirmStage,
|
EthicalReviewStage,
|
OrganAllocationStage,
|
OrganProcurementStage,
|
OrganUtilizationStage
|
},
|
dicts: ['sys_user_sex', 'sys_BloodType', 'sys_0_1'],
|
data() {
|
return {
|
caseId: null,
|
caseInfo: {
|
id: '',
|
caseNo: '',
|
hospitalNo: '',
|
donorName: '',
|
gender: '',
|
age: '',
|
bloodType: '',
|
diagnosis: '',
|
status: 'in_progress',
|
createTime: '',
|
registrant: '',
|
currentStage: 'donor_maintenance'
|
},
|
processStages: [
|
{
|
key: 'donor_maintenance',
|
name: '供者维护',
|
status: 'completed',
|
completeTime: '2025-12-01 10:00:00',
|
updateTime: '2025-12-01 10:00:00',
|
operator: '张医生'
|
},
|
{
|
key: 'medical_assessment',
|
name: '医学评估',
|
status: 'completed',
|
completeTime: '2025-12-02 14:30:00',
|
updateTime: '2025-12-02 14:30:00',
|
operator: '李主任'
|
},
|
{
|
key: 'death_judgment',
|
name: '死亡判定',
|
status: 'completed',
|
completeTime: '2025-12-03 09:15:00',
|
updateTime: '2025-12-03 09:15:00',
|
operator: '王医生'
|
},
|
{
|
key: 'donation_confirm',
|
name: '捐献确认',
|
status: 'completed',
|
completeTime: '2025-12-03 11:00:00',
|
updateTime: '2025-12-03 11:00:00',
|
operator: '赵协调员'
|
},
|
{
|
key: 'ethical_review',
|
name: '伦理审查',
|
status: 'completed',
|
completeTime: '2025-12-03 15:20:00',
|
updateTime: '2025-12-03 15:20:00',
|
operator: '伦理委员会'
|
},
|
{
|
key: 'organ_allocation',
|
name: '器官分配',
|
status: 'in_progress',
|
updateTime: '2025-12-04 10:00:00',
|
operator: '分配系统'
|
},
|
{
|
key: 'organ_procurement',
|
name: '器官获取',
|
status: 'pending',
|
operator: '待分配'
|
},
|
{
|
key: 'organ_utilization',
|
name: '器官利用',
|
status: 'pending',
|
operator: '待分配'
|
}
|
],
|
activeStage: 'organ_allocation',
|
activeStageName: '器官分配',
|
activeStageData: {},
|
loading: false
|
};
|
},
|
computed: {
|
|
},
|
created() {
|
this.caseId = this.$route.query.id;
|
if (this.caseId) {
|
this.getDetail();
|
} else {
|
this.generateMockData();
|
}
|
this.setActiveStage(this.activeStage);
|
},
|
methods: {
|
getStageComponent() {
|
const componentMap = {
|
'donor_maintenance': 'DonorMaintenanceStage',
|
'medical_assessment': 'MedicalAssessmentStage',
|
'death_judgment': 'DeathJudgmentStage',
|
'donation_confirm': 'DonationConfirmStage',
|
'ethical_review': 'EthicalReviewStage',
|
'organ_allocation': 'OrganAllocationStage',
|
'organ_procurement': 'OrganProcurementStage',
|
'organ_utilization': 'OrganUtilizationStage'
|
};
|
return componentMap[this.activeStage];
|
},
|
// 获取详情数据
|
async getDetail() {
|
this.loading = true;
|
try {
|
const response = await getDonationProcessDetail(this.caseId);
|
if (response.code === 200) {
|
this.caseInfo = response.data.caseInfo;
|
this.processStages = response.data.processStages;
|
this.setActiveStage(response.data.currentStage);
|
}
|
} catch (error) {
|
console.error('获取捐献进程详情失败:', error);
|
this.$message.error('获取详情失败');
|
} finally {
|
this.loading = false;
|
}
|
},
|
// 生成模拟数据
|
generateMockData() {
|
this.caseInfo = {
|
id: '202512001',
|
caseNo: 'C202512001',
|
hospitalNo: 'D202512001',
|
donorName: '张三',
|
gender: '0',
|
age: 45,
|
bloodType: 'A',
|
diagnosis: '脑外伤',
|
status: 'in_progress',
|
createTime: '2025-12-01 08:00:00',
|
registrant: '李协调员',
|
currentStage: 'organ_allocation'
|
};
|
},
|
// 设置当前激活阶段
|
setActiveStage(stageKey) {
|
this.activeStage = stageKey;
|
const stage = this.processStages.find(s => s.key === stageKey);
|
if (stage) {
|
this.activeStageName = stage.name;
|
this.activeStageData = stage;
|
}
|
},
|
// 处理阶段点击
|
handleStageClick(stage) {
|
if (stage.status !== 'pending') {
|
this.setActiveStage(stage.key);
|
} else {
|
this.$message.warning('该阶段尚未开始,无法查看详情');
|
}
|
},
|
// 获取阶段状态标签类型
|
getStageStatusTag(status) {
|
const map = {
|
'completed': 'success',
|
'in_progress': 'warning',
|
'pending': 'info'
|
};
|
return map[status] || 'info';
|
},
|
// 获取阶段状态文本
|
getStageStatusText(status) {
|
const map = {
|
'completed': '已完成',
|
'in_progress': '进行中',
|
'pending': '未开始'
|
};
|
return map[status] || '未知';
|
},
|
// 获取整体状态标签类型
|
getOverallStatusTag(status) {
|
const map = {
|
'completed': 'success',
|
'in_progress': 'warning',
|
'pending': 'info',
|
'terminated': 'danger'
|
};
|
return map[status] || 'info';
|
},
|
// 获取整体状态文本
|
getStatusText(status) {
|
const map = {
|
'completed': '已完成',
|
'in_progress': '进行中',
|
'pending': '未开始',
|
'terminated': '已终止'
|
};
|
return map[status] || '未知';
|
},
|
// 时间格式化
|
formatTime(time) {
|
if (!time) return '-';
|
return dayjs(time).format('YYYY-MM-DD HH:mm');
|
},
|
|
// 获取当前阶段名称
|
getCurrentStageName() {
|
const currentStage = this.processStages.find(
|
stage => stage.status === 'in_progress'
|
);
|
return currentStage ? currentStage.name : '已完成';
|
},
|
// 编辑基本信息
|
handleEditBasicInfo() {
|
this.$message.info('编辑基本信息功能');
|
},
|
// 完成阶段
|
handleCompleteStage() {
|
this.$confirm(`确定要完成【${this.activeStageName}】阶段吗?`, '提示', {
|
confirmButtonText: '确定',
|
cancelButtonText: '取消',
|
type: 'warning'
|
}).then(() => {
|
// 更新当前阶段状态
|
const currentIndex = this.processStages.findIndex(
|
stage => stage.key === this.activeStage
|
);
|
|
if (currentIndex !== -1) {
|
this.processStages[currentIndex].status = 'completed';
|
this.processStages[currentIndex].completeTime = new Date().toISOString();
|
|
// 激活下一个阶段
|
if (currentIndex < this.processStages.length - 1) {
|
this.processStages[currentIndex + 1].status = 'in_progress';
|
this.setActiveStage(this.processStages[currentIndex + 1].key);
|
} else {
|
this.caseInfo.status = 'completed';
|
}
|
|
this.$message.success('阶段已完成');
|
}
|
});
|
},
|
// 查看详情
|
handleViewDetail() {
|
const routeMap = {
|
'donor_maintenance': '/case/donorMaintenance/detail',
|
'medical_assessment': '/case/medicalAssessment/detail',
|
'death_judgment': '/case/deathJudgment/detail',
|
'donation_confirm': '/case/donationConfirm/detail',
|
'ethical_review': '/case/ethicalReview/detail',
|
'organ_allocation': '/case/organAllocation/detail',
|
'organ_procurement': '/case/organProcurement/detail',
|
'organ_utilization': '/case/organUtilization/detail'
|
};
|
|
const route = routeMap[this.activeStage];
|
if (route) {
|
this.$router.push({
|
path: route,
|
query: { id: this.caseId }
|
});
|
}
|
},
|
// 修改阶段信息
|
handleModifyStage() {
|
this.$message.info(`修改${this.activeStageName}信息功能`);
|
}
|
}
|
};
|
</script>
|
|
<style scoped>
|
.donation-process-detail {
|
padding: 20px;
|
background-color: #f5f7fa;
|
min-height: 100vh;
|
}
|
|
.process-card {
|
border-radius: 8px;
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
}
|
|
.process-container {
|
display: flex;
|
min-height: 800px;
|
gap: 20px;
|
}
|
|
/* 左侧时间线样式 */
|
.timeline-section {
|
flex: 0 0 300px;
|
background: white;
|
border-radius: 6px;
|
padding: 20px;
|
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
|
}
|
|
.section-header {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
margin-bottom: 20px;
|
padding-bottom: 15px;
|
border-bottom: 1px solid #e4e7ed;
|
}
|
|
.section-header h3 {
|
margin: 0;
|
color: #303133;
|
font-size: 16px;
|
}
|
|
.timeline-container {
|
display: flex;
|
flex-direction: column;
|
gap: 15px;
|
}
|
|
.timeline-item {
|
display: flex;
|
align-items: flex-start;
|
padding: 15px;
|
border-radius: 6px;
|
cursor: pointer;
|
transition: all 0.3s ease;
|
border: 1px solid #e4e7ed;
|
}
|
|
.timeline-item:hover {
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
transform: translateY(-1px);
|
}
|
|
.timeline-item.active {
|
border-color: #409EFF;
|
background-color: #f0f9ff;
|
}
|
|
.timeline-item.completed {
|
border-color: #67C23A;
|
background-color: #f0f9e8;
|
}
|
|
.timeline-item.in-progress {
|
border-color: #E6A23C;
|
background-color: #fdf6ec;
|
}
|
|
.timeline-item.pending {
|
border-color: #909399;
|
background-color: #f4f4f5;
|
}
|
|
.timeline-marker {
|
flex: 0 0 40px;
|
height: 40px;
|
border-radius: 50%;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
margin-right: 15px;
|
font-size: 18px;
|
color: white;
|
}
|
|
.timeline-item.completed .timeline-marker {
|
background-color: #67C23A;
|
}
|
|
.timeline-item.in-progress .timeline-marker {
|
background-color: #E6A23C;
|
}
|
|
.timeline-item.pending .timeline-marker {
|
background-color: #909399;
|
}
|
|
.timeline-content {
|
flex: 1;
|
}
|
|
.stage-header {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
margin-bottom: 8px;
|
}
|
|
.stage-name {
|
font-weight: 600;
|
color: #303133;
|
font-size: 14px;
|
}
|
|
.stage-info {
|
font-size: 12px;
|
color: #606266;
|
}
|
|
.time-info, .operator-info {
|
margin-bottom: 4px;
|
}
|
|
/* 右侧内容区域样式 */
|
.content-section {
|
flex: 1;
|
display: flex;
|
flex-direction: column;
|
gap: 20px;
|
}
|
|
.basic-info-section,
|
.stage-detail-section {
|
background: white;
|
border-radius: 6px;
|
padding: 20px;
|
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
|
}
|
|
.stage-actions {
|
display: flex;
|
gap: 10px;
|
}
|
|
.stage-content {
|
margin-top: 20px;
|
}
|
|
/* 响应式设计 */
|
@media (max-width: 1200px) {
|
.process-container {
|
flex-direction: column;
|
}
|
|
.timeline-section {
|
flex: none;
|
margin-bottom: 20px;
|
}
|
}
|
|
@media (max-width: 768px) {
|
.donation-process-detail {
|
padding: 10px;
|
}
|
|
.process-container {
|
gap: 15px;
|
}
|
|
.timeline-section,
|
.basic-info-section,
|
.stage-detail-section {
|
padding: 15px;
|
}
|
|
.section-header {
|
flex-direction: column;
|
align-items: flex-start;
|
gap: 10px;
|
}
|
|
.stage-actions {
|
flex-wrap: wrap;
|
}
|
}
|
|
/* 动画效果 */
|
.timeline-item {
|
transition: all 0.3s ease;
|
}
|
|
.timeline-item:hover {
|
transform: translateY(-2px);
|
}
|
|
/* 进度条样式优化 */
|
:deep(.el-progress-bar) {
|
padding-right: 0;
|
}
|
|
:deep(.el-progress__text) {
|
font-size: 12px;
|
}
|
</style>
|