<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="6">
|
<el-card>
|
<div slot="header" class="card-header">
|
<span>利用概况</span>
|
</div>
|
<div class="utilization-overview">
|
<div class="overview-item">
|
<div class="overview-icon" style="color: #67C23A;">
|
<i class="el-icon-success"></i>
|
</div>
|
<div class="overview-content">
|
<div class="value">{{ utilizationStats.transplanted }}</div>
|
<div class="label">已移植器官</div>
|
</div>
|
</div>
|
<div class="overview-item">
|
<div class="overview-icon" style="color: #E6A23C;">
|
<i class="el-icon-time"></i>
|
</div>
|
<div class="overview-content">
|
<div class="value">{{ utilizationStats.inProgress }}</div>
|
<div class="label">移植中</div>
|
</div>
|
</div>
|
<div class="overview-item">
|
<div class="overview-icon" style="color: #F56C6C;">
|
<i class="el-icon-warning"></i>
|
</div>
|
<div class="overview-content">
|
<div class="value">{{ utilizationStats.failed }}</div>
|
<div class="label">移植失败</div>
|
</div>
|
</div>
|
</div>
|
</el-card>
|
</el-col>
|
|
<el-col :span="6">
|
<el-card>
|
<div slot="header" class="card-header">
|
<span>成功率统计</span>
|
</div>
|
<div class="success-stats">
|
<div class="success-item">
|
<span class="label">移植成功率:</span>
|
<el-progress
|
:percentage="utilizationStats.successRate"
|
:status="utilizationStats.successRate > 85 ? 'success' : 'warning'"
|
/>
|
</div>
|
<div class="success-item">
|
<span class="label">器官利用率:</span>
|
<el-progress
|
:percentage="utilizationStats.utilizationRate"
|
status="success"
|
/>
|
</div>
|
<div class="success-item">
|
<span class="label">患者存活率:</span>
|
<el-progress
|
:percentage="utilizationStats.survivalRate"
|
status="success"
|
/>
|
</div>
|
</div>
|
</el-card>
|
</el-col>
|
|
<el-col :span="6">
|
<el-card>
|
<div slot="header" class="card-header">
|
<span>时间跟踪</span>
|
</div>
|
<div class="time-tracking">
|
<div class="time-item">
|
<span class="label">获取到移植:</span>
|
<span class="value">{{ timeTracking.procurementToTransplant }}</span>
|
</div>
|
<div class="time-item">
|
<span class="label">冷缺血时间:</span>
|
<span class="value">{{ timeTracking.coldIschemiaTime }}</span>
|
</div>
|
<div class="time-item">
|
<span class="label">手术时长:</span>
|
<span class="value">{{ timeTracking.surgeryDuration }}</span>
|
</div>
|
<div class="time-item">
|
<span class="label">ICU停留:</span>
|
<span class="value">{{ timeTracking.icuStay }}</span>
|
</div>
|
</div>
|
</el-card>
|
</el-col>
|
|
<el-col :span="6">
|
<el-card>
|
<div slot="header" class="card-header">
|
<span>质量评估</span>
|
</div>
|
<div class="quality-assessment">
|
<div class="quality-item">
|
<span class="label">器官质量评分:</span>
|
<el-rate
|
v-model="qualityStats.organQuality"
|
disabled
|
show-score
|
text-color="#ff9900"
|
score-template="{value}"
|
/>
|
</div>
|
<div class="quality-item">
|
<span class="label">手术质量:</span>
|
<el-rate
|
v-model="qualityStats.surgeryQuality"
|
disabled
|
show-score
|
text-color="#ff9900"
|
score-template="{value}"
|
/>
|
</div>
|
<div class="quality-item">
|
<span class="label">随访完成率:</span>
|
<el-progress
|
:percentage="qualityStats.followupCompletionRate"
|
status="success"
|
/>
|
</div>
|
</div>
|
</el-card>
|
</el-col>
|
</el-row>
|
|
<!-- 数据可视化部分 -->
|
<el-row :gutter="20" style="margin-top: 20px;">
|
<!-- 器官利用分布图 -->
|
<el-col :span="12">
|
<el-card>
|
<div slot="header" class="card-header">
|
<span>器官利用分布</span>
|
<el-radio-group v-model="chartView" size="small" @change="updateCharts">
|
<el-radio-button label="bar">柱状图</el-radio-button>
|
<el-radio-button label="pie">饼图</el-radio-button>
|
</el-radio-group>
|
</div>
|
<div class="chart-container">
|
<div ref="organDistributionChart" style="width: 100%; height: 300px;"></div>
|
</div>
|
</el-card>
|
</el-col>
|
|
<!-- 成功率趋势图 -->
|
<el-col :span="12">
|
<el-card>
|
<div slot="header" class="card-header">
|
<span>移植成功率趋势</span>
|
</div>
|
<div class="chart-container">
|
<div ref="successTrendChart" style="width: 100%; height: 300px;"></div>
|
</div>
|
</el-card>
|
</el-col>
|
</el-row>
|
|
<el-row :gutter="20" style="margin-top: 20px;">
|
<!-- 随访数据统计 -->
|
<el-col :span="12">
|
<el-card>
|
<div slot="header" class="card-header">
|
<span>随访数据统计</span>
|
</div>
|
<div class="chart-container">
|
<div ref="followupStatsChart" style="width: 100%; height: 300px;"></div>
|
</div>
|
</el-card>
|
</el-col>
|
|
<!-- 并发症分析 -->
|
<el-col :span="12">
|
<el-card>
|
<div slot="header" class="card-header">
|
<span>并发症分析</span>
|
</div>
|
<div class="chart-container">
|
<div ref="complicationChart" style="width: 100%; height: 300px;"></div>
|
</div>
|
</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="exportData">
|
导出数据
|
</el-button>
|
</div>
|
|
<el-table :data="organUtilizationData" v-loading="loading" 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="getTransplantStatusTag(scope.row.status)">
|
{{ scope.row.status }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column label="受体信息" width="150">
|
<template slot-scope="scope">
|
<div>{{ scope.row.recipientName }}</div>
|
<div style="font-size: 12px; color: #909399;">{{ scope.row.recipientAge }}岁/{{ scope.row.recipientGender }}</div>
|
</template>
|
</el-table-column>
|
<el-table-column label="移植医院" prop="hospital" min-width="180" />
|
<el-table-column label="移植时间" width="160" align="center">
|
<template slot-scope="scope">
|
{{ formatTime(scope.row.transplantTime) }}
|
</template>
|
</el-table-column>
|
<el-table-column label="随访次数" width="100" align="center">
|
<template slot-scope="scope">
|
<el-tag :type="scope.row.followupCount > 0 ? 'success' : 'info'">
|
{{ scope.row.followupCount }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column label="当前状态" width="120" align="center">
|
<template slot-scope="scope">
|
<el-tag :type="getRecipientStatusTag(scope.row.recipientStatus)">
|
{{ scope.row.recipientStatus }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column label="操作" width="150" align="center">
|
<template slot-scope="scope">
|
<el-button type="text" size="small" @click="handleViewDetails(scope.row)">
|
查看详情
|
</el-button>
|
<el-button type="text" size="small" @click="handleAddFollowup(scope.row)">
|
添加随访
|
</el-button>
|
</template>
|
</el-table-column>
|
</el-table>
|
</el-card>
|
|
<!-- 行动按钮 -->
|
<template #footer>
|
<div class="action-buttons" style="margin-top: 20px; text-align: center;">
|
<el-button type="primary" @click="handleGenerateReport">
|
生成利用报告
|
</el-button>
|
<el-button type="success" @click="handleCompleteUtilization">
|
完成器官利用
|
</el-button>
|
<el-button type="warning" @click="handleStatistics">
|
统计数据分析
|
</el-button>
|
</div>
|
</template>
|
</base-stage>
|
</template>
|
|
<script>
|
import BaseStage from './BaseStage.vue';
|
import * as echarts from 'echarts';
|
|
export default {
|
name: 'OrganUtilizationStage',
|
components: { BaseStage },
|
props: {
|
stageData: {
|
type: Object,
|
default: () => ({})
|
},
|
caseInfo: {
|
type: Object,
|
default: () => ({})
|
}
|
},
|
data() {
|
return {
|
chartView: 'bar',
|
loading: false,
|
utilizationStats: {
|
transplanted: 3,
|
inProgress: 0,
|
failed: 0,
|
successRate: 95,
|
utilizationRate: 100,
|
survivalRate: 92
|
},
|
timeTracking: {
|
procurementToTransplant: '4.5小时',
|
coldIschemiaTime: '肝脏:6h,肾脏:8h,心脏:3h',
|
surgeryDuration: '肝脏:4h,肾脏:3h,心脏:5h',
|
icuStay: '肝脏:3天,肾脏:2天,心脏:5天'
|
},
|
qualityStats: {
|
organQuality: 4.5,
|
surgeryQuality: 4.8,
|
followupCompletionRate: 85
|
},
|
organUtilizationData: [
|
{
|
organName: '肝脏',
|
status: '移植成功',
|
recipientName: '王先生',
|
recipientAge: 45,
|
recipientGender: '男',
|
hospital: '北京协和医院移植中心',
|
transplantTime: '2025-12-04 16:00:00',
|
followupCount: 3,
|
recipientStatus: '恢复良好'
|
},
|
{
|
organName: '肾脏',
|
status: '移植成功',
|
recipientName: '李女士',
|
recipientAge: 38,
|
recipientGender: '女',
|
hospital: '上海瑞金医院移植中心',
|
transplantTime: '2025-12-04 17:30:00',
|
followupCount: 2,
|
recipientStatus: '稳定恢复'
|
},
|
{
|
organName: '心脏',
|
status: '移植成功',
|
recipientName: '陈先生',
|
recipientAge: 52,
|
recipientGender: '男',
|
hospital: '广州中山医院心脏中心',
|
transplantTime: '2025-12-04 18:15:00',
|
followupCount: 1,
|
recipientStatus: '密切观察'
|
}
|
],
|
// 图表实例
|
organDistributionChart: null,
|
successTrendChart: null,
|
followupStatsChart: null,
|
complicationChart: null
|
};
|
},
|
mounted() {
|
this.$nextTick(() => {
|
this.initCharts();
|
});
|
},
|
beforeDestroy() {
|
// 销毁图表实例
|
if (this.organDistributionChart) {
|
this.organDistributionChart.dispose();
|
}
|
if (this.successTrendChart) {
|
this.successTrendChart.dispose();
|
}
|
if (this.followupStatsChart) {
|
this.followupStatsChart.dispose();
|
}
|
if (this.complicationChart) {
|
this.complicationChart.dispose();
|
}
|
},
|
methods: {
|
// 初始化图表
|
initCharts() {
|
this.initOrganDistributionChart();
|
this.initSuccessTrendChart();
|
this.initFollowupStatsChart();
|
this.initComplicationChart();
|
},
|
|
// 初始化器官分布图表
|
initOrganDistributionChart() {
|
this.organDistributionChart = echarts.init(this.$refs.organDistributionChart);
|
const option = {
|
tooltip: {
|
trigger: 'item',
|
formatter: '{a} <br/>{b}: {c} ({d}%)'
|
},
|
legend: {
|
orient: 'vertical',
|
right: 10,
|
top: 'center',
|
data: ['肝脏', '肾脏', '心脏', '肺脏', '角膜', '其他']
|
},
|
series: [
|
{
|
name: '器官利用',
|
type: 'pie',
|
radius: ['50%', '70%'],
|
avoidLabelOverlap: false,
|
label: {
|
show: false,
|
position: 'center'
|
},
|
emphasis: {
|
label: {
|
show: true,
|
fontSize: '18',
|
fontWeight: 'bold'
|
}
|
},
|
labelLine: {
|
show: false
|
},
|
data: [
|
{ value: 35, name: '肝脏' },
|
{ value: 30, name: '肾脏' },
|
{ value: 15, name: '心脏' },
|
{ value: 10, name: '肺脏' },
|
{ value: 8, name: '角膜' },
|
{ value: 2, name: '其他' }
|
]
|
}
|
]
|
};
|
this.organDistributionChart.setOption(option);
|
},
|
|
// 初始化成功率趋势图表
|
initSuccessTrendChart() {
|
this.successTrendChart = echarts.init(this.$refs.successTrendChart);
|
const option = {
|
tooltip: {
|
trigger: 'axis'
|
},
|
legend: {
|
data: ['肝脏移植', '肾脏移植', '心脏移植', '平均成功率']
|
},
|
grid: {
|
left: '3%',
|
right: '4%',
|
bottom: '3%',
|
containLabel: true
|
},
|
xAxis: {
|
type: 'category',
|
boundaryGap: false,
|
data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月']
|
},
|
yAxis: {
|
type: 'value',
|
min: 80,
|
max: 100
|
},
|
series: [
|
{
|
name: '肝脏移植',
|
type: 'line',
|
smooth: true,
|
data: [92, 93, 94, 95, 96, 95, 96]
|
},
|
{
|
name: '肾脏移植',
|
type: 'line',
|
smooth: true,
|
data: [94, 95, 95, 96, 95, 96, 97]
|
},
|
{
|
name: '心脏移植',
|
type: 'line',
|
smooth: true,
|
data: [88, 89, 90, 91, 92, 91, 92]
|
},
|
{
|
name: '平均成功率',
|
type: 'line',
|
smooth: true,
|
lineStyle: {
|
type: 'dashed'
|
},
|
data: [91.3, 92.3, 93, 94, 94.3, 94, 95]
|
}
|
]
|
};
|
this.successTrendChart.setOption(option);
|
},
|
|
// 初始化随访统计图表
|
initFollowupStatsChart() {
|
this.followupStatsChart = echarts.init(this.$refs.followupStatsChart);
|
const option = {
|
tooltip: {
|
trigger: 'axis',
|
axisPointer: {
|
type: 'shadow'
|
}
|
},
|
legend: {
|
data: ['计划随访', '已完成', '逾期未完成']
|
},
|
grid: {
|
left: '3%',
|
right: '4%',
|
bottom: '3%',
|
containLabel: true
|
},
|
xAxis: {
|
type: 'value'
|
},
|
yAxis: {
|
type: 'category',
|
data: ['1个月', '3个月', '6个月', '1年', '2年', '5年']
|
},
|
series: [
|
{
|
name: '计划随访',
|
type: 'bar',
|
stack: 'total',
|
label: {
|
show: true
|
},
|
emphasis: {
|
focus: 'series'
|
},
|
data: [120, 132, 101, 134, 90, 60]
|
},
|
{
|
name: '已完成',
|
type: 'bar',
|
stack: 'total',
|
label: {
|
show: true
|
},
|
emphasis: {
|
focus: 'series'
|
},
|
data: [115, 125, 95, 120, 85, 55]
|
},
|
{
|
name: '逾期未完成',
|
type: 'bar',
|
stack: 'total',
|
label: {
|
show: true
|
},
|
emphasis: {
|
focus: 'series'
|
},
|
data: [5, 7, 6, 14, 5, 5]
|
}
|
]
|
};
|
this.followupStatsChart.setOption(option);
|
},
|
|
// 初始化并发症分析图表
|
initComplicationChart() {
|
this.complicationChart = echarts.init(this.$refs.complicationChart);
|
const option = {
|
tooltip: {
|
trigger: 'axis',
|
axisPointer: {
|
type: 'shadow'
|
}
|
},
|
radar: {
|
indicator: [
|
{ name: '感染风险', max: 100 },
|
{ name: '排斥反应', max: 100 },
|
{ name: '血管并发症', max: 100 },
|
{ name: '胆道并发症', max: 100 },
|
{ name: '代谢异常', max: 100 },
|
{ name: '其他并发症', max: 100 }
|
]
|
},
|
series: [
|
{
|
type: 'radar',
|
data: [
|
{
|
value: [85, 90, 78, 82, 75, 70],
|
name: '肝脏移植',
|
areaStyle: {}
|
},
|
{
|
value: [78, 85, 72, 65, 80, 68],
|
name: '肾脏移植',
|
areaStyle: {}
|
},
|
{
|
value: [90, 88, 85, 60, 82, 75],
|
name: '心脏移植',
|
areaStyle: {}
|
}
|
]
|
}
|
]
|
};
|
this.complicationChart.setOption(option);
|
},
|
|
// 更新图表视图
|
updateCharts() {
|
if (this.chartView === 'bar') {
|
this.updateToBarChart();
|
} else {
|
this.initOrganDistributionChart(); // 切回饼图
|
}
|
},
|
|
// 更新为柱状图
|
updateToBarChart() {
|
const option = {
|
tooltip: {
|
trigger: 'axis',
|
axisPointer: {
|
type: 'shadow'
|
}
|
},
|
grid: {
|
left: '3%',
|
right: '4%',
|
bottom: '3%',
|
containLabel: true
|
},
|
xAxis: {
|
type: 'category',
|
data: ['肝脏', '肾脏', '心脏', '肺脏', '角膜', '其他']
|
},
|
yAxis: {
|
type: 'value',
|
name: '数量'
|
},
|
series: [
|
{
|
name: '器官利用数量',
|
type: 'bar',
|
data: [35, 30, 15, 10, 8, 2],
|
itemStyle: {
|
color: function(params) {
|
const colorList = ['#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de', '#3ba272'];
|
return colorList[params.dataIndex];
|
}
|
}
|
}
|
]
|
};
|
this.organDistributionChart.setOption(option);
|
},
|
|
// 获取状态文本
|
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 '等待开始器官利用流程';
|
},
|
|
// 获取移植状态标签
|
getTransplantStatusTag(status) {
|
const map = {
|
'移植成功': 'success',
|
'移植中': 'warning',
|
'移植失败': 'danger'
|
};
|
return map[status] || 'info';
|
},
|
|
// 获取受体状态标签
|
getRecipientStatusTag(status) {
|
const map = {
|
'恢复良好': 'success',
|
'稳定恢复': 'warning',
|
'密切观察': 'danger'
|
};
|
return map[status] || 'info';
|
},
|
|
// 查看详情
|
handleViewDetails(row) {
|
this.$message.info(`查看${row.organName}移植详情`);
|
},
|
|
// 添加随访
|
handleAddFollowup(row) {
|
this.$message.info(`为${row.recipientName}添加随访记录`);
|
},
|
|
// 生成报告
|
handleGenerateReport() {
|
this.$message.info('生成器官利用分析报告');
|
},
|
|
// 完成利用
|
handleCompleteUtilization() {
|
this.$confirm('确认完成器官利用阶段吗?', '提示', {
|
confirmButtonText: '确定',
|
cancelButtonText: '取消',
|
type: 'success'
|
}).then(() => {
|
this.$message.success('器官利用阶段已完成');
|
});
|
},
|
|
// 统计数据分析
|
handleStatistics() {
|
this.$message.info('打开统计分析面板');
|
},
|
|
// 导出数据
|
exportData() {
|
this.$message.info('导出器官利用数据');
|
}
|
}
|
};
|
</script>
|
|
<style scoped>
|
.utilization-overview {
|
padding: 10px 0;
|
}
|
|
.overview-item {
|
display: flex;
|
align-items: center;
|
margin-bottom: 15px;
|
padding: 8px 0;
|
border-bottom: 1px solid #f0f0f0;
|
}
|
|
.overview-icon {
|
font-size: 24px;
|
margin-right: 15px;
|
}
|
|
.overview-content .value {
|
font-size: 24px;
|
font-weight: bold;
|
color: #303133;
|
}
|
|
.overview-content .label {
|
font-size: 12px;
|
color: #909399;
|
}
|
|
.success-stats, .time-tracking, .quality-assessment {
|
padding: 10px 0;
|
}
|
|
.success-item, .time-item, .quality-item {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
margin-bottom: 15px;
|
}
|
|
.success-item .label, .time-item .label, .quality-item .label {
|
color: #606266;
|
font-size: 14px;
|
min-width: 80px;
|
}
|
|
.time-item .value {
|
font-weight: 600;
|
color: #409EFF;
|
}
|
|
.chart-container {
|
position: relative;
|
min-height: 300px;
|
}
|
|
.action-buttons {
|
display: flex;
|
justify-content: center;
|
gap: 15px;
|
margin-top: 20px;
|
}
|
|
.card-header {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
}
|
</style>
|