gaoluyang
2026-06-29 27cd042df9aca0383a49f3514bc21958dd890912
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
<script lang="ts" setup>
import type { EchartsUIType } from '../../../../packages/effects/plugins/src/echarts';
 
import type { InventoryChartItem } from './wms-home-inventory-chart-options';
 
import { nextTick, ref } from 'vue';
 
import { EchartsUI, useEcharts } from '../../../../packages/effects/plugins/src/echarts';
 
import { Card } from 'ant-design-vue';
 
import { getInventorySummary } from '#/api/wms/home';
 
import {
  buildInventoryChartItemList,
  formatQuantityText,
  getGoodsShareChartOptions,
  getWarehouseDistributionChartOptions,
} from './wms-home-inventory-chart-options';
 
defineOptions({ name: 'WmsHomeInventoryCharts' });
 
const GOODS_SHARE_LIMIT = 5;
const WAREHOUSE_DISTRIBUTION_LIMIT = 8;
 
const loading = ref(false);
const totalQuantity = ref(0);
const goodsShareList = ref<InventoryChartItem[]>([]);
const warehouseDistributionList = ref<InventoryChartItem[]>([]);
const goodsShareChartRef = ref<EchartsUIType>();
const warehouseDistributionChartRef = ref<EchartsUIType>();
const { renderEcharts: renderGoodsShareEcharts } =
  useEcharts(goodsShareChartRef);
const { renderEcharts: renderWarehouseDistributionEcharts } = useEcharts(
  warehouseDistributionChartRef,
);
 
/** 使用最新库存汇总数据渲染首页库存图表 */
async function renderCharts() {
  await nextTick();
  await Promise.all([
    renderGoodsShareEcharts(getGoodsShareChartOptions(goodsShareList.value)),
    renderWarehouseDistributionEcharts(
      getWarehouseDistributionChartOptions(warehouseDistributionList.value),
    ),
  ]);
}
 
/** 加载指定仓库的库存汇总和排行数据 */
async function load(warehouseId?: number) {
  loading.value = true;
  try {
    const data = await getInventorySummary({
      ...(warehouseId ? { warehouseId } : {}),
      goodsLimit: GOODS_SHARE_LIMIT,
      warehouseLimit: WAREHOUSE_DISTRIBUTION_LIMIT,
    });
    totalQuantity.value = Number(data.totalQuantity || 0);
    goodsShareList.value = buildInventoryChartItemList(
      data.goodsShareList,
      '未命名商品',
    );
    warehouseDistributionList.value = buildInventoryChartItemList(
      data.warehouseDistributionList,
      '未指定仓库',
    );
    await renderCharts();
  } finally {
    loading.value = false;
  }
}
 
defineExpose({ load });
</script>
 
<template>
  <div class="grid grid-cols-2 gap-4 max-lg:grid-cols-1">
    <Card :body-style="{ padding: '12px 16px 16px' }">
      <div class="mb-3">
        <div class="font-semibold">货物占比</div>
        <div class="text-sm text-muted-foreground">
          按商品库存数量汇总 Top 5
        </div>
      </div>
      <div class="relative min-h-[300px]">
        <EchartsUI ref="goodsShareChartRef" height="300px" />
        <div
          v-if="loading"
          class="absolute inset-0 flex items-center justify-center bg-card/70 text-sm text-muted-foreground"
        >
          加载中
        </div>
      </div>
    </Card>
    <Card :body-style="{ padding: '12px 16px 16px' }">
      <div class="mb-3 flex justify-between">
        <div>
          <div class="font-semibold">库存分布</div>
          <div class="text-sm text-muted-foreground">按仓库库存数量汇总</div>
        </div>
        <span class="font-semibold">
          总库存 {{ formatQuantityText(totalQuantity) }}
        </span>
      </div>
      <div class="relative min-h-[300px]">
        <EchartsUI ref="warehouseDistributionChartRef" height="300px" />
        <div
          v-if="loading"
          class="absolute inset-0 flex items-center justify-center bg-card/70 text-sm text-muted-foreground"
        >
          加载中
        </div>
      </div>
    </Card>
  </div>
</template>