fix(wms): 优化 WMS 首页卡片样式和区块间距
parent
9d54f60b10
commit
0bc1981675
|
|
@ -4,7 +4,7 @@ import { onMounted, ref } from 'vue';
|
||||||
import { DocAlert, Page } from '@vben/common-ui';
|
import { DocAlert, Page } from '@vben/common-ui';
|
||||||
import { formatDateTime } from '@vben/utils';
|
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';
|
import { WmsWarehouseSelect } from '#/views/wms/md/warehouse/components';
|
||||||
|
|
||||||
|
|
@ -45,26 +45,28 @@ onMounted(() => {
|
||||||
<template #doc>
|
<template #doc>
|
||||||
<DocAlert title="WMS 手册(功能开启)" url="https://doc.iocoder.cn/wms/build/" />
|
<DocAlert title="WMS 手册(功能开启)" url="https://doc.iocoder.cn/wms/build/" />
|
||||||
</template>
|
</template>
|
||||||
<div>
|
<div class="flex flex-col gap-2">
|
||||||
<div class="mb-4 flex flex-wrap items-center justify-between gap-4 rounded border bg-card p-4">
|
<Card :body-style="{ padding: '16px' }">
|
||||||
<div>
|
<div class="flex flex-wrap items-center justify-between gap-4">
|
||||||
<div class="text-xl font-semibold">WMS 首页</div>
|
<div>
|
||||||
<div class="text-sm text-muted-foreground">单据工作台 / 库存概览</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>
|
||||||
<div class="flex items-center gap-2">
|
</Card>
|
||||||
<WmsWarehouseSelect
|
|
||||||
v-model="warehouseId"
|
|
||||||
class="!w-[220px]"
|
|
||||||
placeholder="全部仓库"
|
|
||||||
@change="refresh"
|
|
||||||
/>
|
|
||||||
<Button :loading="loading" @click="refresh">刷新</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<WmsHomeOrderSummaryCards ref="orderSummaryCardsRef" />
|
<WmsHomeOrderSummaryCards ref="orderSummaryCardsRef" />
|
||||||
<WmsHomeOrderTrendChart ref="orderTrendChartRef" />
|
<WmsHomeOrderTrendChart ref="orderTrendChartRef" />
|
||||||
<WmsHomeInventoryCharts ref="inventoryChartsRef" />
|
<WmsHomeInventoryCharts ref="inventoryChartsRef" />
|
||||||
<div class="mt-3 text-center text-sm text-muted-foreground">
|
<div class="text-center text-sm text-muted-foreground">
|
||||||
统计时间:{{ statTime }}
|
统计时间:{{ statTime }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,13 @@
|
||||||
|
import type { useEcharts } from '@vben/plugins/echarts';
|
||||||
|
|
||||||
import type { WmsHomeStatisticsApi } from '#/api/wms/home';
|
import type { WmsHomeStatisticsApi } from '#/api/wms/home';
|
||||||
|
|
||||||
import { formatQuantity } from '#/views/wms/utils/format';
|
import { formatQuantity } from '#/views/wms/utils/format';
|
||||||
|
|
||||||
|
type WmsHomeChartOption = Parameters<
|
||||||
|
ReturnType<typeof useEcharts>['renderEcharts']
|
||||||
|
>[0];
|
||||||
|
|
||||||
export interface InventoryChartItem {
|
export interface InventoryChartItem {
|
||||||
name: string;
|
name: string;
|
||||||
value: number;
|
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 {
|
return {
|
||||||
color: ['#2f7df6', '#18a058', '#f59e0b', '#7c3aed', '#14b8a6'],
|
color: ['#2f7df6', '#18a058', '#f59e0b', '#7c3aed', '#14b8a6'],
|
||||||
legend: {
|
legend: {
|
||||||
|
|
@ -70,7 +78,7 @@ export function getGoodsShareChartOptions(goodsShareList: InventoryChartItem[]):
|
||||||
/** 库存分布图表配置 */
|
/** 库存分布图表配置 */
|
||||||
export function getWarehouseDistributionChartOptions(
|
export function getWarehouseDistributionChartOptions(
|
||||||
warehouseDistributionList: InventoryChartItem[],
|
warehouseDistributionList: InventoryChartItem[],
|
||||||
): any {
|
): WmsHomeChartOption {
|
||||||
const sortedList = warehouseDistributionList.toReversed();
|
const sortedList = warehouseDistributionList.toReversed();
|
||||||
return {
|
return {
|
||||||
color: ['#2f7df6'],
|
color: ['#2f7df6'],
|
||||||
|
|
@ -80,7 +88,7 @@ export function getWarehouseDistributionChartOptions(
|
||||||
barMaxWidth: 16,
|
barMaxWidth: 16,
|
||||||
data: sortedList.map((item) => item.value),
|
data: sortedList.map((item) => item.value),
|
||||||
label: {
|
label: {
|
||||||
formatter: ({ value }: { value?: number }) => formatQuantityText(Number(value || 0)),
|
formatter: ({ value }) => formatQuantityText(Number(value || 0)),
|
||||||
position: 'right',
|
position: 'right',
|
||||||
show: true,
|
show: true,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ import { nextTick, ref } from 'vue';
|
||||||
|
|
||||||
import { EchartsUI, useEcharts } from '@vben/plugins/echarts';
|
import { EchartsUI, useEcharts } from '@vben/plugins/echarts';
|
||||||
|
|
||||||
|
import { Card } from 'ant-design-vue';
|
||||||
|
|
||||||
import { getInventorySummary } from '#/api/wms/home';
|
import { getInventorySummary } from '#/api/wms/home';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
|
@ -68,7 +70,7 @@ defineExpose({ load });
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="grid grid-cols-2 gap-4 max-lg:grid-cols-1">
|
<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="mb-3">
|
||||||
<div class="font-semibold">货物占比</div>
|
<div class="font-semibold">货物占比</div>
|
||||||
<div class="text-sm text-muted-foreground">按商品库存数量汇总 Top 5</div>
|
<div class="text-sm text-muted-foreground">按商品库存数量汇总 Top 5</div>
|
||||||
|
|
@ -82,8 +84,8 @@ defineExpose({ load });
|
||||||
加载中
|
加载中
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Card>
|
||||||
<div class="rounded border bg-card p-4 shadow-sm">
|
<Card :body-style="{ padding: '12px 16px 16px' }">
|
||||||
<div class="mb-3 flex justify-between">
|
<div class="mb-3 flex justify-between">
|
||||||
<div>
|
<div>
|
||||||
<div class="font-semibold">库存分布</div>
|
<div class="font-semibold">库存分布</div>
|
||||||
|
|
@ -100,6 +102,6 @@ defineExpose({ load });
|
||||||
加载中
|
加载中
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -120,11 +120,11 @@ defineExpose({ load });
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<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
|
<Card
|
||||||
v-for="item in summaryList"
|
v-for="item in summaryList"
|
||||||
:key="item.type"
|
:key="item.type"
|
||||||
:body-style="{ padding: '16px' }"
|
:body-style="{ padding: '12px 16px 16px' }"
|
||||||
class="h-full shadow-sm"
|
class="h-full shadow-sm"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
:style="{ borderTop: `3px solid ${item.color}` }"
|
: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 type { WmsHomeStatisticsApi } from '#/api/wms/home';
|
||||||
|
|
||||||
import { DICT_TYPE } from '@vben/constants';
|
import { DICT_TYPE } from '@vben/constants';
|
||||||
|
|
@ -6,6 +8,10 @@ import { formatDate } from '@vben/utils';
|
||||||
|
|
||||||
import { OrderTypeEnum } from '#/views/wms/utils/constants';
|
import { OrderTypeEnum } from '#/views/wms/utils/constants';
|
||||||
|
|
||||||
|
type WmsHomeChartOption = Parameters<
|
||||||
|
ReturnType<typeof useEcharts>['renderEcharts']
|
||||||
|
>[0];
|
||||||
|
|
||||||
interface OrderDefinition {
|
interface OrderDefinition {
|
||||||
color: string;
|
color: string;
|
||||||
title: 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));
|
const labels = list.map((item) => formatTrendTime(item.time));
|
||||||
return {
|
return {
|
||||||
color: orderDefinitions.map((item) => item.color),
|
color: orderDefinitions.map((item) => item.color),
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ import { nextTick, ref } from 'vue';
|
||||||
|
|
||||||
import { EchartsUI, useEcharts } from '@vben/plugins/echarts';
|
import { EchartsUI, useEcharts } from '@vben/plugins/echarts';
|
||||||
|
|
||||||
|
import { Card, Segmented } from 'ant-design-vue';
|
||||||
|
|
||||||
import { getOrderTrend, type WmsHomeStatisticsApi } from '#/api/wms/home';
|
import { getOrderTrend, type WmsHomeStatisticsApi } from '#/api/wms/home';
|
||||||
|
|
||||||
import { getOrderTrendChartOptions } from './wms-home-order-trend-chart-options';
|
import { getOrderTrendChartOptions } from './wms-home-order-trend-chart-options';
|
||||||
|
|
@ -17,6 +19,10 @@ const trendDays = ref(7);
|
||||||
const trendList = ref<WmsHomeStatisticsApi.OrderTrend[]>([]);
|
const trendList = ref<WmsHomeStatisticsApi.OrderTrend[]>([]);
|
||||||
const chartRef = ref<EchartsUIType>();
|
const chartRef = ref<EchartsUIType>();
|
||||||
const { renderEcharts } = useEcharts(chartRef);
|
const { renderEcharts } = useEcharts(chartRef);
|
||||||
|
const trendDayOptions = [
|
||||||
|
{ label: '近7天', value: 7 },
|
||||||
|
{ label: '近30天', value: 30 },
|
||||||
|
];
|
||||||
|
|
||||||
/** 使用最新趋势数据渲染单据趋势图 */
|
/** 使用最新趋势数据渲染单据趋势图 */
|
||||||
async function renderChart() {
|
async function renderChart() {
|
||||||
|
|
@ -40,8 +46,8 @@ async function load(selectedWarehouseId?: number) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 切换趋势统计时间范围并刷新图表 */
|
/** 切换趋势统计时间范围并刷新图表 */
|
||||||
async function setTrendDays(days: number) {
|
async function handleTrendDaysChange(value: number | string) {
|
||||||
trendDays.value = days;
|
trendDays.value = Number(value);
|
||||||
await load(warehouseId.value);
|
await load(warehouseId.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -49,16 +55,17 @@ defineExpose({ load });
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<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 class="mb-3 flex items-center justify-between">
|
||||||
<div>
|
<div>
|
||||||
<div class="font-semibold">单据趋势</div>
|
<div class="font-semibold">单据趋势</div>
|
||||||
<div class="text-sm text-muted-foreground">入库、出库、移库、盘库单据数量</div>
|
<div class="text-sm text-muted-foreground">入库、出库、移库、盘库单据数量</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex gap-2">
|
<Segmented
|
||||||
<button class="rounded border px-3 py-1" :class="{ 'bg-primary text-white': trendDays === 7 }" @click="setTrendDays(7)">近7天</button>
|
:options="trendDayOptions"
|
||||||
<button class="rounded border px-3 py-1" :class="{ 'bg-primary text-white': trendDays === 30 }" @click="setTrendDays(30)">近30天</button>
|
:value="trendDays"
|
||||||
</div>
|
@change="handleTrendDaysChange"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="relative min-h-[330px]">
|
<div class="relative min-h-[330px]">
|
||||||
<EchartsUI ref="chartRef" height="330px" />
|
<EchartsUI ref="chartRef" height="330px" />
|
||||||
|
|
@ -69,5 +76,5 @@ defineExpose({ load });
|
||||||
加载中
|
加载中
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Card>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { onMounted, ref } from 'vue';
|
||||||
import { DocAlert, Page } from '@vben/common-ui';
|
import { DocAlert, Page } from '@vben/common-ui';
|
||||||
import { formatDateTime } from '@vben/utils';
|
import { formatDateTime } from '@vben/utils';
|
||||||
|
|
||||||
import { ElButton } from 'element-plus';
|
import { ElButton, ElCard } from 'element-plus';
|
||||||
|
|
||||||
import { WmsWarehouseSelect } from '#/views/wms/md/warehouse/components';
|
import { WmsWarehouseSelect } from '#/views/wms/md/warehouse/components';
|
||||||
|
|
||||||
|
|
@ -45,26 +45,28 @@ onMounted(() => {
|
||||||
<template #doc>
|
<template #doc>
|
||||||
<DocAlert title="WMS 手册(功能开启)" url="https://doc.iocoder.cn/wms/build/" />
|
<DocAlert title="WMS 手册(功能开启)" url="https://doc.iocoder.cn/wms/build/" />
|
||||||
</template>
|
</template>
|
||||||
<div>
|
<div class="flex flex-col gap-2">
|
||||||
<div class="mb-4 flex flex-wrap items-center justify-between gap-4 rounded border bg-card p-4">
|
<ElCard :body-style="{ padding: '16px' }">
|
||||||
<div>
|
<div class="flex flex-wrap items-center justify-between gap-4">
|
||||||
<div class="text-xl font-semibold">WMS 首页</div>
|
<div>
|
||||||
<div class="text-sm text-muted-foreground">单据工作台 / 库存概览</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>
|
||||||
<div class="flex items-center gap-2">
|
</ElCard>
|
||||||
<WmsWarehouseSelect
|
|
||||||
v-model="warehouseId"
|
|
||||||
class="!w-[220px]"
|
|
||||||
placeholder="全部仓库"
|
|
||||||
@change="refresh"
|
|
||||||
/>
|
|
||||||
<ElButton :loading="loading" @click="refresh">刷新</ElButton>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<WmsHomeOrderSummaryCards ref="orderSummaryCardsRef" />
|
<WmsHomeOrderSummaryCards ref="orderSummaryCardsRef" />
|
||||||
<WmsHomeOrderTrendChart ref="orderTrendChartRef" />
|
<WmsHomeOrderTrendChart ref="orderTrendChartRef" />
|
||||||
<WmsHomeInventoryCharts ref="inventoryChartsRef" />
|
<WmsHomeInventoryCharts ref="inventoryChartsRef" />
|
||||||
<div class="mt-3 text-center text-sm text-muted-foreground">
|
<div class="text-center text-sm text-muted-foreground">
|
||||||
统计时间:{{ statTime }}
|
统计时间:{{ statTime }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,13 @@
|
||||||
|
import type { useEcharts } from '@vben/plugins/echarts';
|
||||||
|
|
||||||
import type { WmsHomeStatisticsApi } from '#/api/wms/home';
|
import type { WmsHomeStatisticsApi } from '#/api/wms/home';
|
||||||
|
|
||||||
import { formatQuantity } from '#/views/wms/utils/format';
|
import { formatQuantity } from '#/views/wms/utils/format';
|
||||||
|
|
||||||
|
type WmsHomeChartOption = Parameters<
|
||||||
|
ReturnType<typeof useEcharts>['renderEcharts']
|
||||||
|
>[0];
|
||||||
|
|
||||||
export interface InventoryChartItem {
|
export interface InventoryChartItem {
|
||||||
name: string;
|
name: string;
|
||||||
value: number;
|
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 {
|
return {
|
||||||
color: ['#2f7df6', '#18a058', '#f59e0b', '#7c3aed', '#14b8a6'],
|
color: ['#2f7df6', '#18a058', '#f59e0b', '#7c3aed', '#14b8a6'],
|
||||||
legend: {
|
legend: {
|
||||||
|
|
@ -70,7 +78,7 @@ export function getGoodsShareChartOptions(goodsShareList: InventoryChartItem[]):
|
||||||
/** 库存分布图表配置 */
|
/** 库存分布图表配置 */
|
||||||
export function getWarehouseDistributionChartOptions(
|
export function getWarehouseDistributionChartOptions(
|
||||||
warehouseDistributionList: InventoryChartItem[],
|
warehouseDistributionList: InventoryChartItem[],
|
||||||
): any {
|
): WmsHomeChartOption {
|
||||||
const sortedList = warehouseDistributionList.toReversed();
|
const sortedList = warehouseDistributionList.toReversed();
|
||||||
return {
|
return {
|
||||||
color: ['#2f7df6'],
|
color: ['#2f7df6'],
|
||||||
|
|
@ -80,7 +88,7 @@ export function getWarehouseDistributionChartOptions(
|
||||||
barMaxWidth: 16,
|
barMaxWidth: 16,
|
||||||
data: sortedList.map((item) => item.value),
|
data: sortedList.map((item) => item.value),
|
||||||
label: {
|
label: {
|
||||||
formatter: ({ value }: { value?: number }) => formatQuantityText(Number(value || 0)),
|
formatter: ({ value }) => formatQuantityText(Number(value || 0)),
|
||||||
position: 'right',
|
position: 'right',
|
||||||
show: true,
|
show: true,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ import { nextTick, ref } from 'vue';
|
||||||
|
|
||||||
import { EchartsUI, useEcharts } from '@vben/plugins/echarts';
|
import { EchartsUI, useEcharts } from '@vben/plugins/echarts';
|
||||||
|
|
||||||
|
import { ElCard } from 'element-plus';
|
||||||
|
|
||||||
import { getInventorySummary } from '#/api/wms/home';
|
import { getInventorySummary } from '#/api/wms/home';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
|
@ -68,7 +70,7 @@ defineExpose({ load });
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="grid grid-cols-2 gap-4 max-lg:grid-cols-1">
|
<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="mb-3">
|
||||||
<div class="font-semibold">货物占比</div>
|
<div class="font-semibold">货物占比</div>
|
||||||
<div class="text-sm text-muted-foreground">按商品库存数量汇总 Top 5</div>
|
<div class="text-sm text-muted-foreground">按商品库存数量汇总 Top 5</div>
|
||||||
|
|
@ -82,8 +84,8 @@ defineExpose({ load });
|
||||||
加载中
|
加载中
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</ElCard>
|
||||||
<div class="rounded border bg-card p-4 shadow-sm">
|
<ElCard :body-style="{ padding: '12px 16px 16px' }">
|
||||||
<div class="mb-3 flex justify-between">
|
<div class="mb-3 flex justify-between">
|
||||||
<div>
|
<div>
|
||||||
<div class="font-semibold">库存分布</div>
|
<div class="font-semibold">库存分布</div>
|
||||||
|
|
@ -100,6 +102,6 @@ defineExpose({ load });
|
||||||
加载中
|
加载中
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</ElCard>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -120,11 +120,11 @@ defineExpose({ load });
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<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
|
<ElCard
|
||||||
v-for="item in summaryList"
|
v-for="item in summaryList"
|
||||||
:key="item.type"
|
:key="item.type"
|
||||||
:body-style="{ padding: '16px' }"
|
:body-style="{ padding: '12px 16px 16px' }"
|
||||||
class="h-full"
|
class="h-full"
|
||||||
shadow="never"
|
shadow="never"
|
||||||
:style="{ borderTop: `3px solid ${item.color}` }"
|
: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 type { WmsHomeStatisticsApi } from '#/api/wms/home';
|
||||||
|
|
||||||
import { DICT_TYPE } from '@vben/constants';
|
import { DICT_TYPE } from '@vben/constants';
|
||||||
|
|
@ -6,6 +8,10 @@ import { formatDate } from '@vben/utils';
|
||||||
|
|
||||||
import { OrderTypeEnum } from '#/views/wms/utils/constants';
|
import { OrderTypeEnum } from '#/views/wms/utils/constants';
|
||||||
|
|
||||||
|
type WmsHomeChartOption = Parameters<
|
||||||
|
ReturnType<typeof useEcharts>['renderEcharts']
|
||||||
|
>[0];
|
||||||
|
|
||||||
interface OrderDefinition {
|
interface OrderDefinition {
|
||||||
color: string;
|
color: string;
|
||||||
title: 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));
|
const labels = list.map((item) => formatTrendTime(item.time));
|
||||||
return {
|
return {
|
||||||
color: orderDefinitions.map((item) => item.color),
|
color: orderDefinitions.map((item) => item.color),
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ import { nextTick, ref } from 'vue';
|
||||||
|
|
||||||
import { EchartsUI, useEcharts } from '@vben/plugins/echarts';
|
import { EchartsUI, useEcharts } from '@vben/plugins/echarts';
|
||||||
|
|
||||||
|
import { ElCard, ElSegmented } from 'element-plus';
|
||||||
|
|
||||||
import { getOrderTrend, type WmsHomeStatisticsApi } from '#/api/wms/home';
|
import { getOrderTrend, type WmsHomeStatisticsApi } from '#/api/wms/home';
|
||||||
|
|
||||||
import { getOrderTrendChartOptions } from './wms-home-order-trend-chart-options';
|
import { getOrderTrendChartOptions } from './wms-home-order-trend-chart-options';
|
||||||
|
|
@ -17,6 +19,10 @@ const trendDays = ref(7);
|
||||||
const trendList = ref<WmsHomeStatisticsApi.OrderTrend[]>([]);
|
const trendList = ref<WmsHomeStatisticsApi.OrderTrend[]>([]);
|
||||||
const chartRef = ref<EchartsUIType>();
|
const chartRef = ref<EchartsUIType>();
|
||||||
const { renderEcharts } = useEcharts(chartRef);
|
const { renderEcharts } = useEcharts(chartRef);
|
||||||
|
const trendDayOptions = [
|
||||||
|
{ label: '近7天', value: 7 },
|
||||||
|
{ label: '近30天', value: 30 },
|
||||||
|
];
|
||||||
|
|
||||||
/** 使用最新趋势数据渲染单据趋势图 */
|
/** 使用最新趋势数据渲染单据趋势图 */
|
||||||
async function renderChart() {
|
async function renderChart() {
|
||||||
|
|
@ -40,8 +46,8 @@ async function load(selectedWarehouseId?: number) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 切换趋势统计时间范围并刷新图表 */
|
/** 切换趋势统计时间范围并刷新图表 */
|
||||||
async function setTrendDays(days: number) {
|
async function handleTrendDaysChange(value: number | string) {
|
||||||
trendDays.value = days;
|
trendDays.value = Number(value);
|
||||||
await load(warehouseId.value);
|
await load(warehouseId.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -49,16 +55,17 @@ defineExpose({ load });
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<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 class="mb-3 flex items-center justify-between">
|
||||||
<div>
|
<div>
|
||||||
<div class="font-semibold">单据趋势</div>
|
<div class="font-semibold">单据趋势</div>
|
||||||
<div class="text-sm text-muted-foreground">入库、出库、移库、盘库单据数量</div>
|
<div class="text-sm text-muted-foreground">入库、出库、移库、盘库单据数量</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex gap-2">
|
<ElSegmented
|
||||||
<button class="rounded border px-3 py-1" :class="{ 'bg-primary text-white': trendDays === 7 }" @click="setTrendDays(7)">近7天</button>
|
:model-value="trendDays"
|
||||||
<button class="rounded border px-3 py-1" :class="{ 'bg-primary text-white': trendDays === 30 }" @click="setTrendDays(30)">近30天</button>
|
:options="trendDayOptions"
|
||||||
</div>
|
@change="handleTrendDaysChange"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="relative min-h-[330px]">
|
<div class="relative min-h-[330px]">
|
||||||
<EchartsUI ref="chartRef" height="330px" />
|
<EchartsUI ref="chartRef" height="330px" />
|
||||||
|
|
@ -69,5 +76,5 @@ defineExpose({ load });
|
||||||
加载中
|
加载中
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</ElCard>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue