<!-- src/views/statistics/utilization.vue -->
|
<template>
|
<div class="statistics-page">
|
<!-- 筛选面板 -->
|
<FilterPanel
|
:fields="filterFields"
|
:default-value="query"
|
@search="handleSearch"
|
@reset="handleReset"
|
>
|
<template #extra-actions>
|
<el-button type="success" icon="el-icon-download" @click="handleExport">导出</el-button>
|
</template>
|
</FilterPanel>
|
|
<!-- 第一部分:器官获取/移植统计 -->
|
<el-card style="margin-bottom: 20px;">
|
<div slot="header" class="clearfix">
|
<h3>1. 器官获取/移植数量统计</h3>
|
</div>
|
<EChartsWrapper
|
:id="'acquisition-transplant-chart'"
|
:options="acquisitionChartOptions"
|
height="500px"
|
/>
|
</el-card>
|
|
<!-- 第二部分:器官弃用原因分析 -->
|
<el-card style="margin-bottom: 20px;">
|
<div slot="header" class="clearfix">
|
<h3>2. 器官弃用原因分析</h3>
|
</div>
|
<EChartsWrapper
|
v-if="useMock"
|
:id="'abandon-analysis-chart'"
|
:options="abandonChartOptions"
|
height="400px"
|
/>
|
<el-empty v-else description="后端暂未提供器官弃用原因统计接口"></el-empty>
|
</el-card>
|
|
<!-- 第三部分:每供体器官获取数量 -->
|
<el-card>
|
<div slot="header" class="clearfix">
|
<h3>3. 每供体器官获取数量</h3>
|
</div>
|
|
<template v-if="useMock">
|
<el-table
|
v-loading="loading"
|
:data="perDonorTable"
|
style="width: 100%"
|
border
|
stripe
|
>
|
<el-table-column label="年份" prop="year" align="center" />
|
<el-table-column label="供体姓名" prop="donorName" align="center" />
|
<el-table-column label="获取数量" prop="acquisitionCount" align="center">
|
<template slot-scope="{ row }">
|
<el-tag :type="getCountTag(row.acquisitionCount)" size="small">
|
{{ row.acquisitionCount }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column label="全肝" prop="liver" align="center" />
|
<el-table-column label="左半肝" prop="leftLiver" align="center" />
|
<el-table-column label="右半肝" prop="rightLiver" align="center" />
|
<el-table-column label="心脏" prop="heart" align="center" />
|
<el-table-column label="小肠" prop="intestine" align="center" />
|
<el-table-column label="胰腺" prop="pancreas" align="center" />
|
<el-table-column label="左肾" prop="leftKidney" align="center" />
|
<el-table-column label="右肾" prop="rightKidney" align="center" />
|
<el-table-column label="全肺" prop="fullLung" align="center" />
|
<el-table-column label="左肺" prop="leftLung" align="center" />
|
<el-table-column label="右肺" prop="rightLung" align="center" />
|
<el-table-column label="左眼角膜" prop="leftCornea" align="center" />
|
<el-table-column label="右眼角膜" prop="rightCornea" align="center" />
|
<el-table-column label="地区" prop="region" align="center" />
|
</el-table>
|
</template>
|
<el-empty v-else description="后端暂未提供每供体器官获取明细接口"></el-empty>
|
</el-card>
|
</div>
|
</template>
|
|
<script>
|
import FilterPanel from '@/components/charts/FilterPanel.vue';
|
import EChartsWrapper from '@/components/charts/EChartsWrapper.vue';
|
import { organType } from '@/api/businessApi';
|
import { toTotalsList, toNum } from '@/utils/totals';
|
import statisticsMode, { isStatisticsMock } from '@/utils/statisticsMode';
|
import { COLORS, axisTooltip, grid, xAxis, yAxis, legend, barSeries } from '@/utils/chartStyle';
|
|
export default {
|
name: 'OrganUtilization',
|
components: {
|
FilterPanel,
|
EChartsWrapper
|
},
|
data() {
|
return {
|
// 查询参数
|
query: {
|
region: [],
|
monthRange: [],
|
organType: null,
|
page: 1,
|
limit: 10
|
},
|
|
// 筛选字段配置
|
filterFields: [
|
{
|
label: '地区',
|
prop: 'region',
|
type: 'select',
|
multiple: true,
|
options: [
|
{ label: '青岛地区', value: '青岛地区' },
|
{ label: '日照地区', value: '日照地区' },
|
{ label: '济南地区', value: '济南地区' },
|
{ label: '烟台地区', value: '烟台地区' },
|
{ label: '威海地区', value: '威海地区' },
|
{ label: '潍坊地区', value: '潍坊地区' },
|
{ label: '临沂地区', value: '临沂地区' }
|
],
|
width: '300px'
|
},
|
{
|
label: '月份范围',
|
prop: 'monthRange',
|
type: 'daterange',
|
dateType: 'monthrange',
|
startPlaceholder: '开始月份',
|
endPlaceholder: '结束月份',
|
valueFormat: 'yyyy-MM',
|
width: '300px'
|
},
|
{
|
label: '器官类型',
|
prop: 'organType',
|
type: 'select',
|
options: [
|
{ label: '全肝', value: '全肝' },
|
{ label: '肾脏', value: '肾脏' },
|
{ label: '心脏', value: '心脏' },
|
{ label: '肺', value: '肺' },
|
{ label: '胰腺', value: '胰腺' },
|
{ label: '眼角膜', value: '眼角膜' }
|
],
|
width: '200px'
|
}
|
],
|
|
// 加载状态
|
loading: false,
|
|
// 图表配置
|
acquisitionChartOptions: {},
|
|
// 器官类型分布数据
|
organData: [],
|
|
// 无接口部分的模拟数据(仅 mock 模式展示)
|
abandonReasons: [
|
{ name: '器官质量不合格', value: 45 },
|
{ name: '供体疾病', value: 25 },
|
{ name: '运输问题', value: 15 },
|
{ name: '受体匹配问题', value: 10 },
|
{ name: '其他原因', value: 5 }
|
],
|
perDonorTable: [
|
{ id: 1, year: '2024', donorName: '张三', acquisitionCount: 5, liver: 1, leftLiver: 0, rightLiver: 0, heart: 0, intestine: 0, pancreas: 0, leftKidney: 1, rightKidney: 1, fullLung: 0, leftLung: 0, rightLung: 0, leftCornea: 1, rightCornea: 1, region: '青岛地区' },
|
{ id: 2, year: '2024', donorName: '李四', acquisitionCount: 3, liver: 0, leftLiver: 0, rightLiver: 0, heart: 1, intestine: 0, pancreas: 0, leftKidney: 0, rightKidney: 0, fullLung: 0, leftLung: 1, rightLung: 1, leftCornea: 0, rightCornea: 0, region: '青岛地区' },
|
{ id: 3, year: '2024', donorName: '王五', acquisitionCount: 6, liver: 1, leftLiver: 0, rightLiver: 0, heart: 0, intestine: 0, pancreas: 1, leftKidney: 1, rightKidney: 1, fullLung: 0, leftLung: 0, rightLung: 0, leftCornea: 1, rightCornea: 1, region: '日照地区' },
|
{ id: 4, year: '2024', donorName: '赵六', acquisitionCount: 4, liver: 0, leftLiver: 0, rightLiver: 0, heart: 0, intestine: 0, pancreas: 0, leftKidney: 1, rightKidney: 1, fullLung: 0, leftLung: 0, rightLung: 0, leftCornea: 1, rightCornea: 1, region: '济南地区' },
|
{ id: 5, year: '2023', donorName: '钱七', acquisitionCount: 3, liver: 0, leftLiver: 0, rightLiver: 0, heart: 1, intestine: 0, pancreas: 0, leftKidney: 0, rightKidney: 0, fullLung: 1, leftLung: 0, rightLung: 1, leftCornea: 0, rightCornea: 0, region: '烟台地区' }
|
]
|
};
|
},
|
computed: {
|
useMock() {
|
return isStatisticsMock();
|
},
|
abandonChartOptions() {
|
return {
|
tooltip: {
|
trigger: 'item',
|
formatter: '{a} <br/>{b} : {c} ({d}%)'
|
},
|
legend: {
|
orient: 'vertical',
|
left: 'left',
|
data: this.abandonReasons.map(item => item.name)
|
},
|
series: [
|
{
|
name: '弃用原因',
|
type: 'pie',
|
radius: '55%',
|
center: ['50%', '60%'],
|
data: this.abandonReasons,
|
emphasis: {
|
itemStyle: {
|
shadowBlur: 10,
|
shadowOffsetX: 0,
|
shadowColor: 'rgba(0, 0, 0, 0.5)'
|
}
|
}
|
}
|
]
|
};
|
}
|
},
|
created() {
|
this.loadData();
|
// 数据源(mock/真实接口)切换时重新加载
|
this.$watch(() => statisticsMode.useMock, () => this.loadData());
|
},
|
methods: {
|
// 组装查询条件
|
buildQuery() {
|
const q = {};
|
if (this.query.region && this.query.region.length) {
|
q.area = this.query.region.join(',');
|
}
|
if (this.query.monthRange && this.query.monthRange.length === 2) {
|
q.startTime = this.query.monthRange[0];
|
q.endTime = this.query.monthRange[1];
|
}
|
if (this.query.organType) {
|
q.organName = this.query.organType;
|
}
|
return q;
|
},
|
|
// 加载数据
|
async loadData() {
|
this.loading = true;
|
try {
|
const q = this.buildQuery();
|
const typeRes = await organType(q);
|
|
this.organData = toTotalsList(typeRes).map(item => ({
|
name: item.organName || '未知',
|
acquisition: toNum(item.getCount),
|
transplant: toNum(item.useCount)
|
}));
|
|
this.updateCharts();
|
} catch (error) {
|
console.error('加载数据失败:', error);
|
this.$message.error('数据加载失败');
|
} finally {
|
this.loading = false;
|
}
|
},
|
|
// 更新图表
|
updateCharts() {
|
this.acquisitionChartOptions = {
|
tooltip: axisTooltip(),
|
legend: legend(['获取数量', '移植数量']),
|
grid: grid(),
|
xAxis: xAxis(this.organData.map(item => item.name)),
|
yAxis: yAxis('数量(个)'),
|
series: [
|
barSeries('获取数量', this.organData.map(item => item.acquisition), COLORS.blue),
|
barSeries('移植数量', this.organData.map(item => item.transplant), COLORS.green)
|
]
|
};
|
},
|
|
// 获取数量标签
|
getCountTag(count) {
|
if (count >= 5) return 'success';
|
if (count >= 3) return 'warning';
|
return 'danger';
|
},
|
|
// 处理查询
|
handleSearch(formData) {
|
this.query = { ...this.query, ...formData, page: 1 };
|
this.loadData();
|
},
|
|
// 处理重置
|
handleReset() {
|
this.query = {
|
region: [],
|
monthRange: [],
|
organType: null,
|
page: 1,
|
limit: 10
|
};
|
this.loadData();
|
},
|
|
// 处理导出
|
handleExport() {
|
this.$message.info('导出功能开发中...');
|
}
|
}
|
};
|
</script>
|
|
<style scoped>
|
.statistics-page {
|
padding: 20px;
|
}
|
</style>
|