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
129
130
131
132
133
134
135
<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 flex items-center justify-center gap-1 text-gray-500">
            节约金额(元)
            <a-tooltip title="节约金额 = 招标总金额(预算金额) − 定标总金额(中标金额)">
              <span
                class="inline-flex h-3.5 w-3.5 cursor-help items-center justify-center rounded-full bg-gray-400 text-[10px] leading-none text-white"
              >?</span>
            </a-tooltip>
          </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>