fix(wms): 优化 WMS 首页卡片样式和区块间距
parent
9d54f60b10
commit
0bc1981675
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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}` }"
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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}` }"
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
Loading…
Reference in New Issue