fix(wms): 优化 WMS 首页卡片样式和区块间距

pull/345/head
YunaiV 2026-05-19 14:46:05 +08:00
parent 9d54f60b10
commit 0bc1981675
12 changed files with 124 additions and 70 deletions

View File

@ -4,7 +4,7 @@ import { onMounted, ref } from 'vue';
import { DocAlert, Page } from '@vben/common-ui';
import { formatDateTime } from '@vben/utils';
import { Button } from 'ant-design-vue';
import { Button, Card } from 'ant-design-vue';
import { WmsWarehouseSelect } from '#/views/wms/md/warehouse/components';
@ -45,26 +45,28 @@ onMounted(() => {
<template #doc>
<DocAlert title="WMS 手册(功能开启)" url="https://doc.iocoder.cn/wms/build/" />
</template>
<div>
<div class="mb-4 flex flex-wrap items-center justify-between gap-4 rounded border bg-card p-4">
<div>
<div class="text-xl font-semibold">WMS 首页</div>
<div class="text-sm text-muted-foreground">单据工作台 / 库存概览</div>
<div class="flex flex-col gap-2">
<Card :body-style="{ padding: '16px' }">
<div class="flex flex-wrap items-center justify-between gap-4">
<div>
<div class="text-xl font-semibold">WMS 首页</div>
<div class="text-sm text-muted-foreground">单据工作台 / 库存概览</div>
</div>
<div class="flex items-center gap-2">
<WmsWarehouseSelect
v-model="warehouseId"
class="!w-[220px]"
placeholder="全部仓库"
@change="refresh"
/>
<Button :loading="loading" @click="refresh"></Button>
</div>
</div>
<div class="flex items-center gap-2">
<WmsWarehouseSelect
v-model="warehouseId"
class="!w-[220px]"
placeholder="全部仓库"
@change="refresh"
/>
<Button :loading="loading" @click="refresh"></Button>
</div>
</div>
</Card>
<WmsHomeOrderSummaryCards ref="orderSummaryCardsRef" />
<WmsHomeOrderTrendChart ref="orderTrendChartRef" />
<WmsHomeInventoryCharts ref="inventoryChartsRef" />
<div class="mt-3 text-center text-sm text-muted-foreground">
<div class="text-center text-sm text-muted-foreground">
统计时间{{ statTime }}
</div>
</div>

View File

@ -1,7 +1,13 @@
import type { useEcharts } from '@vben/plugins/echarts';
import type { WmsHomeStatisticsApi } from '#/api/wms/home';
import { formatQuantity } from '#/views/wms/utils/format';
type WmsHomeChartOption = Parameters<
ReturnType<typeof useEcharts>['renderEcharts']
>[0];
export interface InventoryChartItem {
name: string;
value: number;
@ -36,7 +42,9 @@ function formatGoodsLegend(name: string, goodsShareList: InventoryChartItem[]) {
}
/** 货物占比图表配置 */
export function getGoodsShareChartOptions(goodsShareList: InventoryChartItem[]): any {
export function getGoodsShareChartOptions(
goodsShareList: InventoryChartItem[],
): WmsHomeChartOption {
return {
color: ['#2f7df6', '#18a058', '#f59e0b', '#7c3aed', '#14b8a6'],
legend: {
@ -70,7 +78,7 @@ export function getGoodsShareChartOptions(goodsShareList: InventoryChartItem[]):
/** 库存分布图表配置 */
export function getWarehouseDistributionChartOptions(
warehouseDistributionList: InventoryChartItem[],
): any {
): WmsHomeChartOption {
const sortedList = warehouseDistributionList.toReversed();
return {
color: ['#2f7df6'],
@ -80,7 +88,7 @@ export function getWarehouseDistributionChartOptions(
barMaxWidth: 16,
data: sortedList.map((item) => item.value),
label: {
formatter: ({ value }: { value?: number }) => formatQuantityText(Number(value || 0)),
formatter: ({ value }) => formatQuantityText(Number(value || 0)),
position: 'right',
show: true,
},

View File

@ -5,6 +5,8 @@ import { nextTick, ref } from 'vue';
import { EchartsUI, useEcharts } from '@vben/plugins/echarts';
import { Card } from 'ant-design-vue';
import { getInventorySummary } from '#/api/wms/home';
import {
@ -68,7 +70,7 @@ defineExpose({ load });
<template>
<div class="grid grid-cols-2 gap-4 max-lg:grid-cols-1">
<div class="rounded border bg-card p-4 shadow-sm">
<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>
@ -82,8 +84,8 @@ defineExpose({ load });
加载中
</div>
</div>
</div>
<div class="rounded border bg-card p-4 shadow-sm">
</Card>
<Card :body-style="{ padding: '12px 16px 16px' }">
<div class="mb-3 flex justify-between">
<div>
<div class="font-semibold">库存分布</div>
@ -100,6 +102,6 @@ defineExpose({ load });
加载中
</div>
</div>
</div>
</Card>
</div>
</template>

View File

@ -120,11 +120,11 @@ defineExpose({ load });
</script>
<template>
<div class="mb-4 grid grid-cols-4 gap-4 max-xl:grid-cols-2 max-sm:grid-cols-1">
<div class="grid grid-cols-4 gap-4 max-xl:grid-cols-2 max-sm:grid-cols-1">
<Card
v-for="item in summaryList"
:key="item.type"
:body-style="{ padding: '16px' }"
:body-style="{ padding: '12px 16px 16px' }"
class="h-full shadow-sm"
:loading="loading"
:style="{ borderTop: `3px solid ${item.color}` }"

View File

@ -1,3 +1,5 @@
import type { useEcharts } from '@vben/plugins/echarts';
import type { WmsHomeStatisticsApi } from '#/api/wms/home';
import { DICT_TYPE } from '@vben/constants';
@ -6,6 +8,10 @@ import { formatDate } from '@vben/utils';
import { OrderTypeEnum } from '#/views/wms/utils/constants';
type WmsHomeChartOption = Parameters<
ReturnType<typeof useEcharts>['renderEcharts']
>[0];
interface OrderDefinition {
color: string;
title: string;
@ -50,7 +56,9 @@ function formatTrendTime(time: number | string) {
}
/** 单据趋势图表配置 */
export function getOrderTrendChartOptions(list: WmsHomeStatisticsApi.OrderTrend[]): any {
export function getOrderTrendChartOptions(
list: WmsHomeStatisticsApi.OrderTrend[],
): WmsHomeChartOption {
const labels = list.map((item) => formatTrendTime(item.time));
return {
color: orderDefinitions.map((item) => item.color),

View File

@ -5,6 +5,8 @@ import { nextTick, ref } from 'vue';
import { EchartsUI, useEcharts } from '@vben/plugins/echarts';
import { Card, Segmented } from 'ant-design-vue';
import { getOrderTrend, type WmsHomeStatisticsApi } from '#/api/wms/home';
import { getOrderTrendChartOptions } from './wms-home-order-trend-chart-options';
@ -17,6 +19,10 @@ const trendDays = ref(7);
const trendList = ref<WmsHomeStatisticsApi.OrderTrend[]>([]);
const chartRef = ref<EchartsUIType>();
const { renderEcharts } = useEcharts(chartRef);
const trendDayOptions = [
{ label: '近7天', value: 7 },
{ label: '近30天', value: 30 },
];
/** 使用最新趋势数据渲染单据趋势图 */
async function renderChart() {
@ -40,8 +46,8 @@ async function load(selectedWarehouseId?: number) {
}
/** 切换趋势统计时间范围并刷新图表 */
async function setTrendDays(days: number) {
trendDays.value = days;
async function handleTrendDaysChange(value: number | string) {
trendDays.value = Number(value);
await load(warehouseId.value);
}
@ -49,16 +55,17 @@ defineExpose({ load });
</script>
<template>
<div class="mb-4 rounded border bg-card p-4 shadow-sm">
<Card :body-style="{ padding: '12px 16px 16px' }">
<div class="mb-3 flex items-center justify-between">
<div>
<div class="font-semibold">单据趋势</div>
<div class="text-sm text-muted-foreground">入库出库移库盘库单据数量</div>
</div>
<div class="flex gap-2">
<button class="rounded border px-3 py-1" :class="{ 'bg-primary text-white': trendDays === 7 }" @click="setTrendDays(7)">7</button>
<button class="rounded border px-3 py-1" :class="{ 'bg-primary text-white': trendDays === 30 }" @click="setTrendDays(30)">30</button>
</div>
<Segmented
:options="trendDayOptions"
:value="trendDays"
@change="handleTrendDaysChange"
/>
</div>
<div class="relative min-h-[330px]">
<EchartsUI ref="chartRef" height="330px" />
@ -69,5 +76,5 @@ defineExpose({ load });
加载中
</div>
</div>
</div>
</Card>
</template>

View File

@ -4,7 +4,7 @@ import { onMounted, ref } from 'vue';
import { DocAlert, Page } from '@vben/common-ui';
import { formatDateTime } from '@vben/utils';
import { ElButton } from 'element-plus';
import { ElButton, ElCard } from 'element-plus';
import { WmsWarehouseSelect } from '#/views/wms/md/warehouse/components';
@ -45,26 +45,28 @@ onMounted(() => {
<template #doc>
<DocAlert title="WMS 手册(功能开启)" url="https://doc.iocoder.cn/wms/build/" />
</template>
<div>
<div class="mb-4 flex flex-wrap items-center justify-between gap-4 rounded border bg-card p-4">
<div>
<div class="text-xl font-semibold">WMS 首页</div>
<div class="text-sm text-muted-foreground">单据工作台 / 库存概览</div>
<div class="flex flex-col gap-2">
<ElCard :body-style="{ padding: '16px' }">
<div class="flex flex-wrap items-center justify-between gap-4">
<div>
<div class="text-xl font-semibold">WMS 首页</div>
<div class="text-sm text-muted-foreground">单据工作台 / 库存概览</div>
</div>
<div class="flex items-center gap-2">
<WmsWarehouseSelect
v-model="warehouseId"
class="!w-[220px]"
placeholder="全部仓库"
@change="refresh"
/>
<ElButton :loading="loading" @click="refresh"></ElButton>
</div>
</div>
<div class="flex items-center gap-2">
<WmsWarehouseSelect
v-model="warehouseId"
class="!w-[220px]"
placeholder="全部仓库"
@change="refresh"
/>
<ElButton :loading="loading" @click="refresh"></ElButton>
</div>
</div>
</ElCard>
<WmsHomeOrderSummaryCards ref="orderSummaryCardsRef" />
<WmsHomeOrderTrendChart ref="orderTrendChartRef" />
<WmsHomeInventoryCharts ref="inventoryChartsRef" />
<div class="mt-3 text-center text-sm text-muted-foreground">
<div class="text-center text-sm text-muted-foreground">
统计时间{{ statTime }}
</div>
</div>

View File

@ -1,7 +1,13 @@
import type { useEcharts } from '@vben/plugins/echarts';
import type { WmsHomeStatisticsApi } from '#/api/wms/home';
import { formatQuantity } from '#/views/wms/utils/format';
type WmsHomeChartOption = Parameters<
ReturnType<typeof useEcharts>['renderEcharts']
>[0];
export interface InventoryChartItem {
name: string;
value: number;
@ -36,7 +42,9 @@ function formatGoodsLegend(name: string, goodsShareList: InventoryChartItem[]) {
}
/** 货物占比图表配置 */
export function getGoodsShareChartOptions(goodsShareList: InventoryChartItem[]): any {
export function getGoodsShareChartOptions(
goodsShareList: InventoryChartItem[],
): WmsHomeChartOption {
return {
color: ['#2f7df6', '#18a058', '#f59e0b', '#7c3aed', '#14b8a6'],
legend: {
@ -70,7 +78,7 @@ export function getGoodsShareChartOptions(goodsShareList: InventoryChartItem[]):
/** 库存分布图表配置 */
export function getWarehouseDistributionChartOptions(
warehouseDistributionList: InventoryChartItem[],
): any {
): WmsHomeChartOption {
const sortedList = warehouseDistributionList.toReversed();
return {
color: ['#2f7df6'],
@ -80,7 +88,7 @@ export function getWarehouseDistributionChartOptions(
barMaxWidth: 16,
data: sortedList.map((item) => item.value),
label: {
formatter: ({ value }: { value?: number }) => formatQuantityText(Number(value || 0)),
formatter: ({ value }) => formatQuantityText(Number(value || 0)),
position: 'right',
show: true,
},

View File

@ -5,6 +5,8 @@ import { nextTick, ref } from 'vue';
import { EchartsUI, useEcharts } from '@vben/plugins/echarts';
import { ElCard } from 'element-plus';
import { getInventorySummary } from '#/api/wms/home';
import {
@ -68,7 +70,7 @@ defineExpose({ load });
<template>
<div class="grid grid-cols-2 gap-4 max-lg:grid-cols-1">
<div class="rounded border bg-card p-4 shadow-sm">
<ElCard :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>
@ -82,8 +84,8 @@ defineExpose({ load });
加载中
</div>
</div>
</div>
<div class="rounded border bg-card p-4 shadow-sm">
</ElCard>
<ElCard :body-style="{ padding: '12px 16px 16px' }">
<div class="mb-3 flex justify-between">
<div>
<div class="font-semibold">库存分布</div>
@ -100,6 +102,6 @@ defineExpose({ load });
加载中
</div>
</div>
</div>
</ElCard>
</div>
</template>

View File

@ -120,11 +120,11 @@ defineExpose({ load });
</script>
<template>
<div class="mb-4 grid grid-cols-4 gap-4 max-xl:grid-cols-2 max-sm:grid-cols-1">
<div class="grid grid-cols-4 gap-4 max-xl:grid-cols-2 max-sm:grid-cols-1">
<ElCard
v-for="item in summaryList"
:key="item.type"
:body-style="{ padding: '16px' }"
:body-style="{ padding: '12px 16px 16px' }"
class="h-full"
shadow="never"
:style="{ borderTop: `3px solid ${item.color}` }"

View File

@ -1,3 +1,5 @@
import type { useEcharts } from '@vben/plugins/echarts';
import type { WmsHomeStatisticsApi } from '#/api/wms/home';
import { DICT_TYPE } from '@vben/constants';
@ -6,6 +8,10 @@ import { formatDate } from '@vben/utils';
import { OrderTypeEnum } from '#/views/wms/utils/constants';
type WmsHomeChartOption = Parameters<
ReturnType<typeof useEcharts>['renderEcharts']
>[0];
interface OrderDefinition {
color: string;
title: string;
@ -50,7 +56,9 @@ function formatTrendTime(time: number | string) {
}
/** 单据趋势图表配置 */
export function getOrderTrendChartOptions(list: WmsHomeStatisticsApi.OrderTrend[]): any {
export function getOrderTrendChartOptions(
list: WmsHomeStatisticsApi.OrderTrend[],
): WmsHomeChartOption {
const labels = list.map((item) => formatTrendTime(item.time));
return {
color: orderDefinitions.map((item) => item.color),

View File

@ -5,6 +5,8 @@ import { nextTick, ref } from 'vue';
import { EchartsUI, useEcharts } from '@vben/plugins/echarts';
import { ElCard, ElSegmented } from 'element-plus';
import { getOrderTrend, type WmsHomeStatisticsApi } from '#/api/wms/home';
import { getOrderTrendChartOptions } from './wms-home-order-trend-chart-options';
@ -17,6 +19,10 @@ const trendDays = ref(7);
const trendList = ref<WmsHomeStatisticsApi.OrderTrend[]>([]);
const chartRef = ref<EchartsUIType>();
const { renderEcharts } = useEcharts(chartRef);
const trendDayOptions = [
{ label: '近7天', value: 7 },
{ label: '近30天', value: 30 },
];
/** 使用最新趋势数据渲染单据趋势图 */
async function renderChart() {
@ -40,8 +46,8 @@ async function load(selectedWarehouseId?: number) {
}
/** 切换趋势统计时间范围并刷新图表 */
async function setTrendDays(days: number) {
trendDays.value = days;
async function handleTrendDaysChange(value: number | string) {
trendDays.value = Number(value);
await load(warehouseId.value);
}
@ -49,16 +55,17 @@ defineExpose({ load });
</script>
<template>
<div class="mb-4 rounded border bg-card p-4 shadow-sm">
<ElCard :body-style="{ padding: '12px 16px 16px' }">
<div class="mb-3 flex items-center justify-between">
<div>
<div class="font-semibold">单据趋势</div>
<div class="text-sm text-muted-foreground">入库出库移库盘库单据数量</div>
</div>
<div class="flex gap-2">
<button class="rounded border px-3 py-1" :class="{ 'bg-primary text-white': trendDays === 7 }" @click="setTrendDays(7)">7</button>
<button class="rounded border px-3 py-1" :class="{ 'bg-primary text-white': trendDays === 30 }" @click="setTrendDays(30)">30</button>
</div>
<ElSegmented
:model-value="trendDays"
:options="trendDayOptions"
@change="handleTrendDaysChange"
/>
</div>
<div class="relative min-h-[330px]">
<EchartsUI ref="chartRef" height="330px" />
@ -69,5 +76,5 @@ defineExpose({ load });
加载中
</div>
</div>
</div>
</ElCard>
</template>