<template>
|
<base-stage :stage-data="stageData" :case-info="caseInfo">
|
<template #header>
|
<el-alert
|
:title="`器官分配 - ${getStatusText()}`"
|
:type="getAlertType()"
|
:description="getAlertDescription()"
|
show-icon
|
:closable="false"
|
/>
|
</template>
|
|
<el-row :gutter="20" style="margin-top: 20px;">
|
<el-col :span="8">
|
<el-card>
|
<div slot="header" class="card-header">
|
<span>分配概况</span>
|
</div>
|
<div class="allocation-stats">
|
<div class="stat-item">
|
<span class="label">待分配器官:</span>
|
<span class="value">{{ allocationStats.totalOrgans }} 个</span>
|
</div>
|
<div class="stat-item">
|
<span class="label">已分配器官:</span>
|
<span class="value">{{ allocationStats.allocatedOrgans }} 个</span>
|
</div>
|
<div class="stat-item">
|
<span class="label">分配系统:</span>
|
<span class="value">{{ allocationStats.system }}</span>
|
</div>
|
<div class="stat-item">
|
<span class="label">匹配成功率:</span>
|
<el-progress
|
:percentage="allocationStats.matchRate"
|
:status="allocationStats.matchRate > 80 ? 'success' : 'warning'"
|
/>
|
</div>
|
</div>
|
</el-card>
|
</el-col>
|
|
<el-col :span="8">
|
<el-card>
|
<div slot="header" class="card-header">
|
<span>分配时间窗口</span>
|
</div>
|
<div class="time-window">
|
<div class="time-item">
|
<span class="label">分配开始:</span>
|
<span>{{ formatTime(allocationDetails.startTime) }}</span>
|
</div>
|
<div class="time-item">
|
<span class="label">预计完成:</span>
|
<span>{{ formatTime(allocationDetails.estimatedEndTime) }}</span>
|
</div>
|
<div class="time-item">
|
<span class="label">器官耐受时间:</span>
|
<span>{{ allocationDetails.toleranceTime }}</span>
|
</div>
|
<div class="time-item">
|
<span class="label">剩余时间:</span>
|
<el-tag :type="getTimeRemainingType()">
|
{{ allocationDetails.timeRemaining }}
|
</el-tag>
|
</div>
|
</div>
|
</el-card>
|
</el-col>
|
|
<el-col :span="8">
|
<el-card>
|
<div slot="header" class="card-header">
|
<span>分配优先级</span>
|
</div>
|
<el-steps direction="vertical" :active="prioritySteps.active">
|
<el-step
|
v-for="step in prioritySteps.steps"
|
:key="step.title"
|
:title="step.title"
|
:description="step.description"
|
:status="step.status"
|
/>
|
</el-steps>
|
</el-card>
|
</el-col>
|
</el-row>
|
|
<el-card style="margin-top: 20px;">
|
<div slot="header" class="card-header">
|
<span>器官分配详情</span>
|
<el-button type="primary" size="small" @click="handleStartAllocation">
|
启动自动分配
|
</el-button>
|
</div>
|
<el-table :data="organAllocationData" border>
|
<el-table-column label="器官名称" prop="organName" width="120" align="center" />
|
<el-table-column label="器官状态" width="100" align="center">
|
<template slot-scope="scope">
|
<el-tag :type="getOrganStatusTag(scope.row.status)" size="small">
|
{{ scope.row.status }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column label="匹配受体" prop="recipient" width="150" />
|
<el-table-column label="血型匹配" width="100" align="center">
|
<template slot-scope="scope">
|
<el-tag :type="scope.row.bloodMatch ? 'success' : 'warning'">
|
{{ scope.row.bloodMatch ? '匹配' : '待匹配' }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column label="组织配型" width="100" align="center">
|
<template slot-scope="scope">
|
<el-tag :type="scope.row.tissueMatch ? 'success' : 'warning'">
|
{{ scope.row.tissueMatch ? '合格' : '待检测' }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column label="移植医院" prop="hospital" min-width="200" />
|
<el-table-column label="分配时间" width="160" align="center">
|
<template slot-scope="scope">
|
{{ scope.row.allocationTime || '待分配' }}
|
</template>
|
</el-table-column>
|
<el-table-column label="操作" width="120" align="center">
|
<template slot-scope="scope">
|
<el-button type="text" size="small" @click="handleViewMatch(scope.row)">
|
查看匹配
|
</el-button>
|
</template>
|
</el-table-column>
|
</el-table>
|
</el-card>
|
|
<el-card style="margin-top: 20px;">
|
<div slot="header" class="card-header">
|
<span>分配算法结果</span>
|
</div>
|
<div class="algorithm-results">
|
<el-row :gutter="20">
|
<el-col :span="12">
|
<div class="result-item">
|
<h4>匹配评分排名</h4>
|
<el-table :data="matchRanking" border size="small">
|
<el-table-column label="排名" width="60" align="center">
|
<template slot-scope="scope">
|
{{ scope.$index + 1 }}
|
</template>
|
</el-table-column>
|
<el-table-column label="受体编号" prop="recipientNo" width="100" />
|
<el-table-column label="匹配分数" prop="matchScore" width="100">
|
<template slot-scope="scope">
|
<el-rate
|
v-model="scope.row.matchScore"
|
disabled
|
show-score
|
text-color="#ff9900"
|
score-template="{value} 分"
|
/>
|
</template>
|
</el-table-column>
|
<el-table-column label="推荐器官" prop="recommendedOrgan" />
|
</el-table>
|
</div>
|
</el-col>
|
<el-col :span="12">
|
<div class="result-item">
|
<h4>分配因素权重</h4>
|
<div class="weight-distribution">
|
<div v-for="factor in allocationFactors" :key="factor.name" class="factor-item">
|
<span class="factor-name">{{ factor.name }}</span>
|
<el-progress
|
:percentage="factor.weight"
|
:show-text="false"
|
:color="factor.color"
|
/>
|
<span class="factor-percent">{{ factor.weight }}%</span>
|
</div>
|
</div>
|
</div>
|
</el-col>
|
</el-row>
|
</div>
|
</el-card>
|
|
<template #footer>
|
<div class="action-buttons" style="margin-top: 20px; text-align: center;">
|
<el-button type="primary" @click="handleAutoAllocation">
|
智能分配
|
</el-button>
|
<el-button type="success" @click="handleConfirmAllocation">
|
确认分配结果
|
</el-button>
|
<el-button type="warning" @click="handleManualAdjust">
|
手动调整
|
</el-button>
|
</div>
|
</template>
|
</base-stage>
|
</template>
|
|
<script>
|
import BaseStage from './BaseStage.vue';
|
|
export default {
|
name: 'OrganAllocationStage',
|
components: { BaseStage },
|
props: {
|
stageData: {
|
type: Object,
|
default: () => ({})
|
},
|
caseInfo: {
|
type: Object,
|
default: () => ({})
|
}
|
},
|
data() {
|
return {
|
allocationStats: {
|
totalOrgans: 3,
|
allocatedOrgans: 0,
|
system: '中国人体器官分配与共享计算机系统',
|
matchRate: 0
|
},
|
allocationDetails: {
|
startTime: '2025-12-04 10:00:00',
|
estimatedEndTime: '2025-12-04 12:00:00',
|
toleranceTime: '肝脏:12小时,肾脏:24小时,心脏:8小时,肺脏:12小时',
|
timeRemaining: '2小时'
|
},
|
prioritySteps: {
|
active: 3,
|
steps: [
|
{
|
title: '病情危重优先',
|
description: '根据患者病情危重程度分配[1](@ref)',
|
status: 'finish'
|
},
|
{
|
title: '组织配型优先',
|
description: '组织配型匹配度高的患者优先',
|
status: 'finish'
|
},
|
{
|
title: '血型相同优先',
|
description: '血型匹配的患者优先考虑',
|
status: 'finish'
|
},
|
{
|
title: '儿童匹配优先',
|
description: '儿童患者享有优先分配权',
|
status: 'wait'
|
}
|
]
|
},
|
organAllocationData: [
|
{
|
organName: '肝脏',
|
status: '待分配',
|
recipient: '',
|
bloodMatch: false,
|
tissueMatch: false,
|
hospital: '',
|
allocationTime: ''
|
},
|
{
|
organName: '肾脏',
|
status: '待分配',
|
recipient: '',
|
bloodMatch: false,
|
tissueMatch: false,
|
hospital: '',
|
allocationTime: ''
|
},
|
{
|
organName: '心脏',
|
status: '待分配',
|
recipient: '',
|
bloodMatch: false,
|
tissueMatch: false,
|
hospital: '',
|
allocationTime: ''
|
}
|
],
|
matchRanking: [
|
{
|
recipientNo: 'R202512001',
|
matchScore: 4.8,
|
recommendedOrgan: '肝脏'
|
},
|
{
|
recipientNo: 'R202512002',
|
matchScore: 4.5,
|
recommendedOrgan: '肾脏'
|
},
|
{
|
recipientNo: 'R202512003',
|
matchScore: 4.3,
|
recommendedOrgan: '心脏'
|
}
|
],
|
allocationFactors: [
|
{ name: '病情危重程度', weight: 35, color: '#f56c6c' },
|
{ name: '组织配型匹配', weight: 25, color: '#e6a23c' },
|
{ name: '等待时间', weight: 15, color: '#5cb87a' },
|
{ name: '地理因素', weight: 10, color: '#6f7ad3' },
|
{ name: '年龄因素', weight: 15, color: '#8e44ad' }
|
]
|
};
|
},
|
methods: {
|
getStatusText() {
|
const status = this.stageData.status;
|
return status === 'completed' ? '已完成' :
|
status === 'in_progress' ? '进行中' : '未开始';
|
},
|
getAlertType() {
|
const status = this.stageData.status;
|
return status === 'completed' ? 'success' :
|
status === 'in_progress' ? 'warning' : 'info';
|
},
|
getAlertDescription() {
|
const status = this.stageData.status;
|
if (status === 'completed') {
|
return '器官分配已完成,所有器官均已成功匹配受体';
|
} else if (status === 'in_progress') {
|
return '器官分配进行中,系统正在自动匹配最佳受体';
|
}
|
return '等待开始器官分配流程';
|
},
|
getOrganStatusTag(status) {
|
const map = {
|
'已分配': 'success',
|
'分配中': 'warning',
|
'待分配': 'info'
|
};
|
return map[status] || 'info';
|
},
|
getTimeRemainingType() {
|
return this.allocationDetails.timeRemaining.includes('小时') ? 'success' : 'danger';
|
},
|
handleStartAllocation() {
|
this.$confirm('确认启动自动器官分配吗?', '提示', {
|
confirmButtonText: '确定',
|
cancelButtonText: '取消',
|
type: 'warning'
|
}).then(() => {
|
this.$message.success('已启动自动分配算法');
|
// 模拟分配过程
|
this.allocationStats.allocatedOrgans = 3;
|
this.allocationStats.matchRate = 95;
|
this.organAllocationData.forEach(organ => {
|
organ.status = '已分配';
|
organ.allocationTime = new Date().toISOString().replace('T', ' ').substring(0, 19);
|
});
|
});
|
},
|
handleAutoAllocation() {
|
this.$message.info('执行智能分配算法');
|
},
|
handleConfirmAllocation() {
|
this.$confirm('确认最终分配结果吗?', '提示', {
|
confirmButtonText: '确定',
|
cancelButtonText: '取消',
|
type: 'success'
|
}).then(() => {
|
this.$message.success('器官分配结果已确认');
|
});
|
},
|
handleManualAdjust() {
|
this.$message.info('进入手动调整模式');
|
},
|
handleViewMatch(row) {
|
this.$message.info(`查看${row.organName}的匹配详情`);
|
}
|
}
|
};
|
</script>
|
|
<style scoped>
|
.allocation-stats, .time-window {
|
padding: 10px 0;
|
}
|
|
.stat-item, .time-item {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
margin-bottom: 15px;
|
padding: 8px 0;
|
border-bottom: 1px solid #f0f0f0;
|
}
|
|
.stat-item .label, .time-item .label {
|
color: #606266;
|
font-weight: 500;
|
min-width: 100px;
|
}
|
|
.stat-item .value {
|
font-weight: 600;
|
color: #409EFF;
|
}
|
|
.algorithm-results {
|
padding: 15px 0;
|
}
|
|
.result-item {
|
margin-bottom: 20px;
|
}
|
|
.result-item h4 {
|
margin-bottom: 15px;
|
color: #303133;
|
}
|
|
.weight-distribution {
|
padding: 10px 0;
|
}
|
|
.factor-item {
|
display: flex;
|
align-items: center;
|
margin-bottom: 12px;
|
}
|
|
.factor-name {
|
width: 120px;
|
color: #606266;
|
font-size: 14px;
|
}
|
|
.factor-item .el-progress {
|
flex: 1;
|
margin: 0 15px;
|
}
|
|
.factor-percent {
|
width: 40px;
|
text-align: right;
|
color: #909399;
|
font-size: 12px;
|
}
|
</style>
|