<!-- src/views/statistics/organ.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-row :gutter="20" class="overview-row">
|
<el-col :span="6" v-for="item in overviewData" :key="item.title">
|
<el-card class="overview-card">
|
<div class="overview-content">
|
<div class="overview-icon" :style="{ backgroundColor: item.color }">
|
<i :class="item.icon"></i>
|
</div>
|
<div class="overview-info">
|
<div class="overview-title">{{ item.title }}</div>
|
<div class="overview-value">{{ item.value }}</div>
|
<div class="overview-desc">{{ item.desc }}</div>
|
</div>
|
</div>
|
</el-card>
|
</el-col>
|
</el-row>
|
|
<!-- 图表区域 -->
|
<el-row :gutter="20" class="chart-row">
|
<el-col :span="12">
|
<el-card>
|
<div slot="header" class="clearfix">
|
<span>器官获取/移植趋势</span>
|
</div>
|
<EChartsWrapper
|
:id="'organ-trend-chart'"
|
:options="trendChartOptions"
|
height="400px"
|
/>
|
</el-card>
|
</el-col>
|
|
<el-col :span="12">
|
<el-card>
|
<div slot="header" class="clearfix">
|
<span>器官类型分布</span>
|
</div>
|
<EChartsWrapper
|
:id="'organ-distribution-chart'"
|
:options="distributionChartOptions"
|
height="400px"
|
/>
|
</el-card>
|
</el-col>
|
</el-row>
|
|
<!-- 数据表格 -->
|
<el-card>
|
<div slot="header" class="clearfix">
|
<span>捐献器官统计明细</span>
|
<el-button
|
style="float: right; margin-left: 10px;"
|
type="primary"
|
icon="el-icon-zoom-in"
|
@click="showOrganDetail = true"
|
>
|
查看器官明细
|
</el-button>
|
</div>
|
|
<el-table
|
v-loading="loading"
|
:data="tableData"
|
style="width: 100%"
|
border
|
stripe
|
>
|
<el-table-column label="年份" prop="year" align="center" />
|
<el-table-column label="器官名称" prop="organName" align="center" />
|
<el-table-column label="获取数量" prop="acquisitionCount" align="center" />
|
<el-table-column label="移植数量" prop="transplantCount" align="center" />
|
<el-table-column label="移植率" prop="transplantRate" align="center" >
|
<template slot-scope="{ row }">
|
<el-tag :type="getRateTag(row.transplantRate)" size="small">
|
{{ row.transplantRate }}%
|
</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column label="弃用数量" prop="abandonCount" align="center" />
|
<el-table-column label="地区" prop="region" align="center" />
|
<el-table-column label="操作" align="center" fixed="right">
|
<template slot-scope="{ row }">
|
<el-button
|
type="text"
|
size="mini"
|
@click="viewOrganDetail(row)"
|
>
|
详情
|
</el-button>
|
</template>
|
</el-table-column>
|
</el-table>
|
|
<el-pagination
|
v-show="total > 0"
|
:total="total"
|
:page.sync="query.page"
|
:limit.sync="query.limit"
|
@current-change="handlePagination"
|
@size-change="handlePageSizeChange"
|
style="margin-top: 20px;"
|
layout="total, sizes, prev, pager, next, jumper"
|
:page-sizes="[10, 20, 50, 100]"
|
/>
|
</el-card>
|
|
<!-- 器官明细弹窗 -->
|
<el-dialog
|
title="器官明细"
|
:visible.sync="showOrganDetail"
|
width="80%"
|
append-to-body
|
>
|
<OrganDetail
|
:query="detailQuery"
|
@close="showOrganDetail = false"
|
/>
|
</el-dialog>
|
</div>
|
</template>
|
|
<script>
|
import FilterPanel from '@/components/charts/FilterPanel.vue';
|
import EChartsWrapper from '@/components/charts/EChartsWrapper.vue';
|
import OrganDetail from './components/OrganDetail.vue';
|
|
export default {
|
name: 'OrganStatistics',
|
components: {
|
FilterPanel,
|
EChartsWrapper,
|
OrganDetail
|
},
|
data() {
|
return {
|
// 查询参数
|
query: {
|
region: [],
|
yearRange: [],
|
organType: null,
|
page: 1,
|
limit: 10
|
},
|
|
// 筛选字段配置
|
filterFields: [
|
{
|
label: '地区',
|
prop: 'region',
|
type: 'select',
|
multiple: true,
|
options: [
|
{ label: '青岛地区', value: 'qingdao' },
|
{ label: '日照地区', value: 'rizhao' },
|
{ label: '济南地区', value: 'jinan' },
|
{ label: '烟台地区', value: 'yantai' },
|
{ label: '威海地区', value: 'weihai' },
|
{ label: '潍坊地区', value: 'weifang' },
|
{ label: '临沂地区', value: 'linyi' }
|
],
|
width: '300px'
|
},
|
{
|
label: '年份范围',
|
prop: 'yearRange',
|
type: 'daterange',
|
dateType: 'yearrange',
|
startPlaceholder: '开始年份',
|
endPlaceholder: '结束年份',
|
valueFormat: 'yyyy',
|
width: '300px'
|
},
|
{
|
label: '器官类型',
|
prop: 'organType',
|
type: 'select',
|
options: [
|
{ label: '全肝', value: 'liver' },
|
{ label: '肾脏', value: 'kidney' },
|
{ label: '心脏', value: 'heart' },
|
{ label: '肺', value: 'lung' },
|
{ label: '胰腺', value: 'pancreas' },
|
{ label: '眼角膜', value: 'cornea' }
|
],
|
width: '200px'
|
}
|
],
|
|
// 加载状态
|
loading: false,
|
|
// 表格数据
|
tableData: [],
|
total: 0,
|
|
// 概览数据
|
overviewData: [
|
{ title: '总获取数量', value: 0, desc: '统计周期内', icon: 'el-icon-s-claim', color: '#409EFF' },
|
{ title: '总移植数量', value: 0, desc: '统计周期内', icon: 'el-icon-success', color: '#67C23A' },
|
{ title: '总移植率', value: '0%', desc: '统计周期内', icon: 'el-icon-s-data', color: '#E6A23C' },
|
{ title: '总弃用数量', value: 0, desc: '统计周期内', icon: 'el-icon-warning', color: '#F56C6C' }
|
],
|
|
// 图表配置
|
trendChartOptions: {},
|
distributionChartOptions: {},
|
|
// 弹窗控制
|
showOrganDetail: false,
|
detailQuery: {},
|
|
// 模拟数据
|
mockData: {
|
table: [
|
{ id: 1, year: '2024', organName: '全肝', acquisitionCount: 15, transplantCount: 12, transplantRate: 80.0, abandonCount: 3, region: '青岛地区' },
|
{ id: 2, year: '2024', organName: '肾脏', acquisitionCount: 20, transplantCount: 18, transplantRate: 90.0, abandonCount: 2, region: '青岛地区' },
|
{ id: 3, year: '2024', organName: '全肝', acquisitionCount: 8, transplantCount: 6, transplantRate: 75.0, abandonCount: 2, region: '日照地区' },
|
{ id: 4, year: '2024', organName: '心脏', acquisitionCount: 5, transplantCount: 4, transplantRate: 80.0, abandonCount: 1, region: '青岛地区' },
|
{ id: 5, year: '2023', organName: '全肝', acquisitionCount: 12, transplantCount: 10, transplantRate: 83.3, abandonCount: 2, region: '青岛地区' },
|
{ id: 6, year: '2023', organName: '眼角膜', acquisitionCount: 25, transplantCount: 22, transplantRate: 88.0, abandonCount: 3, region: '济南地区' }
|
],
|
trend: [
|
{ year: '2020', acquisition: 120, transplant: 100 },
|
{ year: '2021', acquisition: 150, transplant: 130 },
|
{ year: '2022', acquisition: 180, transplant: 160 },
|
{ year: '2023', acquisition: 220, transplant: 200 },
|
{ year: '2024', acquisition: 250, transplant: 230 }
|
],
|
distribution: [
|
{ name: '全肝', value: 85 },
|
{ name: '肾脏', value: 120 },
|
{ name: '心脏', value: 45 },
|
{ name: '肺', value: 60 },
|
{ name: '胰腺', value: 30 },
|
{ name: '眼角膜', value: 200 }
|
]
|
}
|
};
|
},
|
created() {
|
this.loadData();
|
},
|
methods: {
|
// 加载数据
|
async loadData() {
|
this.loading = true;
|
try {
|
await new Promise(resolve => setTimeout(resolve, 500));
|
|
// 处理表格数据
|
let filteredData = [...this.mockData.table];
|
|
if (this.query.region.length > 0) {
|
filteredData = filteredData.filter(item =>
|
this.query.region.includes(item.region.replace('地区', '').toLowerCase())
|
);
|
}
|
|
if (this.query.yearRange && this.query.yearRange.length === 2) {
|
const [start, end] = this.query.yearRange;
|
filteredData = filteredData.filter(item =>
|
parseInt(item.year) >= parseInt(start) && parseInt(item.year) <= parseInt(end)
|
);
|
}
|
|
if (this.query.organType) {
|
const organMap = { liver: '肝', kidney: '肾', heart: '心脏', lung: '肺', pancreas: '胰腺', cornea: '眼角膜' };
|
const organName = organMap[this.query.organType];
|
if (organName) {
|
filteredData = filteredData.filter(item => item.organName.includes(organName));
|
}
|
}
|
|
// 分页
|
const start = (this.query.page - 1) * this.query.limit;
|
this.tableData = filteredData.slice(start, start + this.query.limit);
|
this.total = filteredData.length;
|
|
// 更新概览数据
|
this.updateOverviewData(filteredData);
|
|
// 更新图表
|
this.updateCharts();
|
|
} catch (error) {
|
console.error('加载数据失败:', error);
|
this.$message.error('数据加载失败');
|
} finally {
|
this.loading = false;
|
}
|
},
|
|
// 更新概览数据
|
updateOverviewData(data) {
|
if (data.length === 0) return;
|
|
const totalAcquisition = data.reduce((sum, item) => sum + item.acquisitionCount, 0);
|
const totalTransplant = data.reduce((sum, item) => sum + item.transplantCount, 0);
|
const totalAbandon = data.reduce((sum, item) => sum + item.abandonCount, 0);
|
const transplantRate = totalAcquisition > 0 ? (totalTransplant / totalAcquisition * 100).toFixed(1) : 0;
|
|
this.overviewData[0].value = totalAcquisition;
|
this.overviewData[1].value = totalTransplant;
|
this.overviewData[2].value = `${transplantRate}%`;
|
this.overviewData[3].value = totalAbandon;
|
},
|
|
// 更新图表
|
updateCharts() {
|
// 趋势图
|
this.trendChartOptions = {
|
tooltip: {
|
trigger: 'axis',
|
axisPointer: {
|
type: 'shadow'
|
}
|
},
|
legend: {
|
data: ['获取数量', '移植数量']
|
},
|
grid: {
|
left: '3%',
|
right: '4%',
|
bottom: '3%',
|
containLabel: true
|
},
|
xAxis: {
|
type: 'category',
|
data: this.mockData.trend.map(item => item.year + '年')
|
},
|
yAxis: {
|
type: 'value',
|
name: '数量(个)'
|
},
|
series: [
|
{
|
name: '获取数量',
|
type: 'bar',
|
data: this.mockData.trend.map(item => item.acquisition),
|
itemStyle: { color: '#409EFF' }
|
},
|
{
|
name: '移植数量',
|
type: 'bar',
|
data: this.mockData.trend.map(item => item.transplant),
|
itemStyle: { color: '#67C23A' }
|
}
|
]
|
};
|
|
// 分布图
|
this.distributionChartOptions = {
|
tooltip: {
|
trigger: 'item',
|
formatter: '{a} <br/>{b} : {c} ({d}%)'
|
},
|
legend: {
|
orient: 'vertical',
|
left: 'left',
|
data: this.mockData.distribution.map(item => item.name)
|
},
|
series: [
|
{
|
name: '器官分布',
|
type: 'pie',
|
radius: '55%',
|
center: ['50%', '60%'],
|
data: this.mockData.distribution,
|
emphasis: {
|
itemStyle: {
|
shadowBlur: 10,
|
shadowOffsetX: 0,
|
shadowColor: 'rgba(0, 0, 0, 0.5)'
|
}
|
}
|
}
|
]
|
};
|
},
|
|
// 获取移植率标签类型
|
getRateTag(rate) {
|
if (rate >= 85) return 'success';
|
if (rate >= 75) return 'warning';
|
return 'danger';
|
},
|
|
// 处理查询
|
handleSearch(formData) {
|
this.query = { ...this.query, ...formData, page: 1 };
|
this.loadData();
|
},
|
|
// 处理重置
|
handleReset() {
|
this.query = {
|
region: [],
|
yearRange: [],
|
organType: null,
|
page: 1,
|
limit: 10
|
};
|
this.loadData();
|
},
|
|
// 处理分页
|
handlePagination(page) {
|
this.query.page = page;
|
this.loadData();
|
},
|
|
// 处理分页大小变化
|
handlePageSizeChange(size) {
|
this.query.limit = size;
|
this.query.page = 1;
|
this.loadData();
|
},
|
|
// 处理导出
|
handleExport() {
|
this.$message.info('导出功能开发中...');
|
},
|
|
// 查看器官详情
|
viewOrganDetail(row) {
|
this.detailQuery = {
|
year: row.year,
|
organType: row.organName,
|
region: row.region
|
};
|
this.showOrganDetail = true;
|
}
|
}
|
};
|
</script>
|
|
<style scoped>
|
.statistics-page {
|
padding: 20px;
|
}
|
|
.filter-card {
|
margin-bottom: 20px;
|
}
|
|
.filter-form {
|
margin-bottom: 0;
|
}
|
|
.overview-row {
|
margin-bottom: 20px;
|
}
|
|
.overview-card {
|
height: 100%;
|
}
|
|
.overview-content {
|
display: flex;
|
align-items: center;
|
}
|
|
.overview-icon {
|
width: 50px;
|
height: 50px;
|
border-radius: 8px;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
margin-right: 15px;
|
}
|
|
.overview-icon i {
|
font-size: 24px;
|
color: white;
|
}
|
|
.overview-info {
|
flex: 1;
|
}
|
|
.overview-title {
|
font-size: 14px;
|
color: #909399;
|
margin-bottom: 4px;
|
}
|
|
.overview-value {
|
font-size: 24px;
|
font-weight: bold;
|
color: #303133;
|
margin-bottom: 4px;
|
}
|
|
.overview-desc {
|
font-size: 12px;
|
color: #C0C4CC;
|
}
|
|
.chart-row {
|
margin-bottom: 20px;
|
}
|
</style>
|