From 3df460667d74868d0a54fce12d5e881bbd6c0c1a Mon Sep 17 00:00:00 2001
From: WXL <wl_5969728@163.com>
Date: 星期四, 17 九月 2026 17:11:18 +0800
Subject: [PATCH] 青岛维护统计
---
src/views/statistics/organ.vue | 239 ++++++++++++++++++++++++++++-------------------------------
1 files changed, 113 insertions(+), 126 deletions(-)
diff --git a/src/views/statistics/organ.vue b/src/views/statistics/organ.vue
index bff9883..9c420ae 100644
--- a/src/views/statistics/organ.vue
+++ b/src/views/statistics/organ.vue
@@ -81,20 +81,20 @@
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" >
+ <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">
+ <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"
@@ -139,6 +139,10 @@
import FilterPanel from '@/components/charts/FilterPanel.vue';
import EChartsWrapper from '@/components/charts/EChartsWrapper.vue';
import OrganDetail from './components/OrganDetail.vue';
+import { organ, organMoon, organType } from '@/api/businessApi';
+import { toTotalsList, toMonth, toNum } from '@/utils/totals';
+import statisticsMode from '@/utils/statisticsMode';
+import { COLORS, PALETTE, axisTooltip, grid, xAxis, yAxis, legend, barSeries } from '@/utils/chartStyle';
export default {
name: 'OrganStatistics',
@@ -166,13 +170,13 @@
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' }
+ { label: '闈掑矝鍦板尯', value: '闈掑矝鍦板尯' },
+ { label: '鏃ョ収鍦板尯', value: '鏃ョ収鍦板尯' },
+ { label: '娴庡崡鍦板尯', value: '娴庡崡鍦板尯' },
+ { label: '鐑熷彴鍦板尯', value: '鐑熷彴鍦板尯' },
+ { label: '濞佹捣鍦板尯', value: '濞佹捣鍦板尯' },
+ { label: '娼嶅潑鍦板尯', value: '娼嶅潑鍦板尯' },
+ { label: '涓存矀鍦板尯', value: '涓存矀鍦板尯' }
],
width: '300px'
},
@@ -191,12 +195,12 @@
prop: 'organType',
type: 'select',
options: [
- { label: '鍏ㄨ倽', value: 'liver' },
- { label: '鑲捐剰', value: 'kidney' },
- { label: '蹇冭剰', value: 'heart' },
- { label: '鑲�', value: 'lung' },
- { label: '鑳拌吅', value: 'pancreas' },
- { label: '鐪艰鑶�', value: 'cornea' }
+ { label: '鍏ㄨ倽', value: '鍏ㄨ倽' },
+ { label: '鑲捐剰', value: '鑲捐剰' },
+ { label: '蹇冭剰', value: '蹇冭剰' },
+ { label: '鑲�', value: '鑲�' },
+ { label: '鑳拌吅', value: '鑳拌吅' },
+ { label: '鐪艰鑶�', value: '鐪艰鑶�' }
],
width: '200px'
}
@@ -211,93 +215,97 @@
// 姒傝鏁版嵁
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' }
+ { title: '鎬昏幏鍙栨暟閲�', value: 0, desc: '缁熻鍛ㄦ湡鍐�', icon: 'el-icon-s-claim', color: '#5B8FF9' },
+ { title: '鎬荤Щ妞嶆暟閲�', value: 0, desc: '缁熻鍛ㄦ湡鍐�', icon: 'el-icon-success', color: '#5AD8A6' },
+ { title: '鎬荤Щ妞嶇巼', value: '0%', desc: '缁熻鍛ㄦ湡鍐�', icon: 'el-icon-s-data', color: '#F6BD16' },
+ { title: '鎬诲純鐢ㄦ暟閲�', value: 0, desc: '缁熻鍛ㄦ湡鍐�', icon: 'el-icon-warning', color: '#E8684A' }
],
// 鍥捐〃閰嶇疆
trendChartOptions: {},
distributionChartOptions: {},
+ // 鍥捐〃鏁版嵁
+ chartData: {
+ trend: [],
+ distribution: []
+ },
+
// 寮圭獥鎺у埗
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 }
- ]
- }
+ detailQuery: {}
};
},
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.yearRange && this.query.yearRange.length === 2) {
+ q.startTime = this.query.yearRange[0];
+ q.endTime = this.query.yearRange[1];
+ }
+ if (this.query.organType) {
+ q.organName = this.query.organType;
+ }
+ return q;
+ },
+
// 鍔犺浇鏁版嵁
async loadData() {
this.loading = true;
try {
- await new Promise(resolve => setTimeout(resolve, 500));
+ const q = this.buildQuery();
+ const [moonRes, typeRes, organRes] = await Promise.all([
+ organMoon(q),
+ organType(q),
+ organ(q)
+ ]);
- // 澶勭悊琛ㄦ牸鏁版嵁
- let filteredData = [...this.mockData.table];
+ // 鑾峰彇/绉绘瓒嬪娍
+ this.chartData.trend = toTotalsList(moonRes).map(item => ({
+ time: toMonth(item.donateTime) || toMonth(item.month),
+ acquisition: toNum(item.getCount),
+ transplant: toNum(item.useCount)
+ }));
- if (this.query.region.length > 0) {
- filteredData = filteredData.filter(item =>
- this.query.region.includes(item.region.replace('鍦板尯', '').toLowerCase())
- );
- }
+ // 鍣ㄥ畼绫诲瀷鍒嗗竷
+ this.chartData.distribution = toTotalsList(typeRes).map(item => ({
+ name: item.organName || '',
+ value: toNum(item.getCount)
+ }));
- 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 all = toTotalsList(organRes).map(item => {
+ const get = toNum(item.getCount);
+ const use = toNum(item.useCount);
+ const rate = get > 0 ? Number(((use / get) * 100).toFixed(1)) : 0;
+ return {
+ year: String(item.donateTime || item.year || '').slice(0, 4),
+ organName: item.organName || '',
+ acquisitionCount: get,
+ transplantCount: use,
+ transplantRate: rate,
+ abandonCount: get - use,
+ region: item.area || item.region || ''
+ };
+ });
+ this.total = all.length;
const start = (this.query.page - 1) * this.query.limit;
- this.tableData = filteredData.slice(start, start + this.query.limit);
- this.total = filteredData.length;
+ this.tableData = all.slice(start, start + this.query.limit);
- // 鏇存柊姒傝鏁版嵁
- this.updateOverviewData(filteredData);
+ // 鏇存柊姒傝
+ this.updateOverviewData(all);
// 鏇存柊鍥捐〃
this.updateCharts();
-
} catch (error) {
console.error('鍔犺浇鏁版嵁澶辫触:', error);
this.$message.error('鏁版嵁鍔犺浇澶辫触');
@@ -308,12 +316,10 @@
// 鏇存柊姒傝鏁版嵁
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;
+ const totalAcquisition = data.reduce((sum, item) => sum + toNum(item.acquisitionCount), 0);
+ const totalTransplant = data.reduce((sum, item) => sum + toNum(item.transplantCount), 0);
+ const totalAbandon = data.reduce((sum, item) => sum + toNum(item.abandonCount), 0);
+ const transplantRate = totalAcquisition > 0 ? ((totalTransplant / totalAcquisition) * 100).toFixed(1) : 0;
this.overviewData[0].value = totalAcquisition;
this.overviewData[1].value = totalTransplant;
@@ -325,47 +331,20 @@
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: '鏁伴噺(涓�)'
- },
+ tooltip: axisTooltip(),
+ legend: legend(['鑾峰彇鏁伴噺', '绉绘鏁伴噺']),
+ grid: grid(),
+ xAxis: xAxis(this.chartData.trend.map(item => item.time)),
+ yAxis: yAxis(),
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' }
- }
+ barSeries('鑾峰彇鏁伴噺', this.chartData.trend.map(item => item.acquisition), COLORS.blue),
+ barSeries('绉绘鏁伴噺', this.chartData.trend.map(item => item.transplant), COLORS.green)
]
};
// 鍒嗗竷鍥�
this.distributionChartOptions = {
+ color: PALETTE,
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b} : {c} ({d}%)'
@@ -373,15 +352,23 @@
legend: {
orient: 'vertical',
left: 'left',
- data: this.mockData.distribution.map(item => item.name)
+ top: 'middle',
+ itemWidth: 10,
+ itemHeight: 10,
+ itemGap: 16,
+ textStyle: { fontSize: 14, color: '#606266' },
+ data: this.chartData.distribution.map(item => item.name)
},
series: [
{
name: '鍣ㄥ畼鍒嗗竷',
type: 'pie',
radius: '55%',
- center: ['50%', '60%'],
- data: this.mockData.distribution,
+ center: ['55%', '50%'],
+ itemStyle: { borderColor: '#fff', borderWidth: 2 },
+ label: { fontSize: 14, color: '#606266', formatter: '{b} {d}%' },
+ labelLine: { lineStyle: { color: '#c0c4cc' } },
+ data: this.chartData.distribution,
emphasis: {
itemStyle: {
shadowBlur: 10,
--
Gitblit v1.9.3