gaoluyang
16 小时以前 844dfdc256bfc567f9eaa007a7bc37dc120bffa8
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
<script lang="ts" setup>
import type { EchartsUIType } from '@vben/plugins/echarts';
import type { SrmStatisticsApi } from '#/api/srm/statistics';
 
import { onMounted, ref, watch } from 'vue';
 
import { Page } from '@vben/common-ui';
 
import { EchartsUI, useEcharts } from '@vben/plugins/echarts';
 
import { getTenderStatistics } from '#/api/srm/statistics';
import { getSupplierSimpleList } from '#/api/srm/supplier';
 
defineOptions({ name: 'SrmStatistics' });
 
const year = ref(new Date().getFullYear().toString());
const stats = ref<SrmStatisticsApi.TenderStatisticsVO>({});
const supplierCount = ref(0);
 
async function loadStats() {
  stats.value = await getTenderStatistics(year.value);
}
async function loadSupplierCount() {
  const list = await getSupplierSimpleList();
  supplierCount.value = list?.length ?? 0;
}
 
// 图表
const pieChartRef = ref<EchartsUIType>();
const barChartRef = ref<EchartsUIType>();
const { renderEcharts: renderPie } = useEcharts(pieChartRef);
const { renderEcharts: renderBar } = useEcharts(barChartRef);
 
async function renderCharts() {
  // 饼图:供应商状态分布
  await renderPie({
    title: { text: '供应商状态分布', left: 'center' },
    tooltip: { trigger: 'item' },
    legend: { bottom: 0 },
    series: [{
      type: 'pie',
      radius: ['40%', '70%'],
      data: [
        { value: supplierCount.value, name: '已启用' },
        { value: 0, name: '已禁用' },
      ],
    }],
  });
 
  // 柱状图:招标统计概览
  await renderBar({
    title: { text: `${year.value} 年招标统计概览`, left: 'center' },
    tooltip: { trigger: 'axis' },
    xAxis: { type: 'category', data: ['招标总数', '参与供应商', '定标金额(万)', '节约金额(万)'] },
    yAxis: { type: 'value' },
    series: [{
      type: 'bar',
      data: [
        stats.value.totalTenderCount ?? 0,
        stats.value.supplierCount ?? 0,
        +(((stats.value.totalAwardAmount ?? 0) / 10000).toFixed(2)),
        +(((stats.value.savedAmount ?? 0) / 10000).toFixed(2)),
      ],
      itemStyle: {
        color: (params: any) => ['#3b82f6', '#ec4899', '#f97316', '#8b5cf6'][params.dataIndex],
      },
    }],
  });
}
 
watch([stats, supplierCount], () => renderCharts());
onMounted(() => { loadStats(); loadSupplierCount(); });
</script>
 
<template>
  <Page auto-content-height>
    <div class="p-4">
      <div class="mb-6 flex items-center gap-4">
        <span class="text-lg font-medium">SRM 统计看板</span>
        <a-input v-model:value="year" placeholder="年份" style="width: 120px" @change="loadStats" />
      </div>
 
      <!-- 6 个统计卡片 -->
      <div class="mb-6 grid grid-cols-3 gap-4">
        <div class="rounded-lg bg-blue-50 p-6 text-center shadow-sm">
          <div class="text-3xl font-bold text-blue-600">{{ stats.totalTenderCount ?? 0 }}</div>
          <div class="mt-2 text-gray-500">招标总数</div>
        </div>
        <div class="rounded-lg bg-green-50 p-6 text-center shadow-sm">
          <div class="text-3xl font-bold text-green-600">{{ stats.totalTenderAmount?.toLocaleString() ?? 0 }}</div>
          <div class="mt-2 text-gray-500">招标总金额(元)</div>
        </div>
        <div class="rounded-lg bg-orange-50 p-6 text-center shadow-sm">
          <div class="text-3xl font-bold text-orange-600">{{ stats.totalAwardAmount?.toLocaleString() ?? 0 }}</div>
          <div class="mt-2 text-gray-500">定标总金额(元)</div>
        </div>
        <div class="rounded-lg bg-purple-50 p-6 text-center shadow-sm">
          <div class="text-3xl font-bold text-purple-600">{{ stats.savedAmount?.toLocaleString() ?? 0 }}</div>
          <div class="mt-2 text-gray-500">节约金额(元)</div>
        </div>
        <div class="rounded-lg bg-teal-50 p-6 text-center shadow-sm">
          <div class="text-3xl font-bold text-teal-600">{{ stats.winRate ?? 0 }}%</div>
          <div class="mt-2 text-gray-500">中标率</div>
        </div>
        <div class="rounded-lg bg-rose-50 p-6 text-center shadow-sm">
          <div class="text-3xl font-bold text-rose-600">{{ stats.supplierCount ?? 0 }}</div>
          <div class="mt-2 text-gray-500">参与招标供应商</div>
        </div>
      </div>
 
      <!-- 图表区域 -->
      <div class="mb-6 grid grid-cols-2 gap-4">
        <div class="rounded-lg bg-white p-4 shadow-sm">
          <EchartsUI ref="pieChartRef" class="h-[350px] w-full" />
        </div>
        <div class="rounded-lg bg-white p-4 shadow-sm">
          <EchartsUI ref="barChartRef" class="h-[350px] w-full" />
        </div>
      </div>
 
      <!-- 底部信息 -->
      <div class="rounded-lg bg-white p-4 shadow-sm">
        <h3 class="mb-3 text-base font-medium">供应商总数: {{ supplierCount }} 家</h3>
        <a-empty v-if="supplierCount === 0" description="暂无供应商数据" />
      </div>
    </div>
  </Page>
</template>