feat:库存总览-模块对接接口

main
黄伟杰 1 week ago
parent c0c701b79f
commit d74f8cf045

@ -1,6 +1,49 @@
import request from '@/config/axios'
// ERP 产品库存 VO
export interface StockUnitStockVO {
unitId?: number
unitName?: string
count?: number
stockDisplay?: string
}
export interface ProductStockCardVO {
skuCount?: number
stockDisplay?: string
todayFinishedInDisplay?: string
}
export interface UnitGroupedStockCardVO {
skuCount?: number
stockDisplay?: string
unitStocks?: StockUnitStockVO[]
}
export interface TodayInCardVO {
orderCount?: number
itemCount?: number
productDisplay?: string
materialDisplay?: string
sparePartDisplay?: string
}
export interface TodayOutCardVO {
orderCount?: number
itemCount?: number
materialDisplay?: string
sparePartDisplay?: string
productDisplay?: string
}
export interface StockStatisticsCardsRespVO {
productStock?: ProductStockCardVO
materialStock?: UnitGroupedStockCardVO
sparePartStock?: UnitGroupedStockCardVO
todayIn?: TodayInCardVO
todayOut?: TodayOutCardVO
}
export interface StockVO {
// 编号
id: number
@ -49,6 +92,11 @@ export interface StockVO {
// ERP 产品库存 API
export const StockApi = {
// 查询库存统计卡片
getStockStatisticsCards: async () => {
return await request.get<StockStatisticsCardsRespVO>({ url: `/erp/stock/statistics-cards` })
},
// 查询产品库存分页
getStockPage: async (params: any) => {
return await request.get({ url: `/erp/stock/page`, params })

@ -416,6 +416,22 @@ export default {
latestChangeTime: 'Latest Change Time',
stockIn: 'Inbound',
stockOut: 'Outbound',
cardLabels: {
sku: 'SKU',
stockSummary: 'Stock Summary',
todayFinishedIn: 'Completed Inbound Today',
materialSku: 'Materials',
sparePartSku: 'Spare Parts',
inboundOrders: 'Inbound Orders',
outboundOrders: 'Outbound Orders',
detailLines: 'Detail Lines',
productIn: 'Finished Goods',
materialIn: 'Raw Materials',
sparePartIn: 'Spare Parts',
materialOut: 'Raw Material Issue',
sparePartOut: 'Spare Parts Issue',
productOut: 'Finished Goods Shipment'
},
cards: {
finishedGoods: {
title: 'Finished Goods Stock',

@ -416,6 +416,22 @@ export default {
latestChangeTime: '最近变动时间',
stockIn: '入库',
stockOut: '出库',
cardLabels: {
sku: 'SKU',
stockSummary: '库存摘要',
todayFinishedIn: '今日完工入库',
materialSku: '物料',
sparePartSku: '备件',
inboundOrders: '入库单',
outboundOrders: '出库单',
detailLines: '明细行',
productIn: '产成品',
materialIn: '原材料',
sparePartIn: '备件',
materialOut: '原材料领用',
sparePartOut: '备件领用',
productOut: '产成品发货'
},
cards: {
finishedGoods: {
title: '产成品库存',

@ -38,7 +38,7 @@
</el-form>
</ContentWrap>
<div class="stock-overview__cards">
<div v-loading="cardsLoading" class="stock-overview__cards">
<ContentWrap v-for="item in summaryCards" :key="item.title" class="stock-overview__card-wrap"
:body-style="{ padding: '22px 24px' }">
<div class="stock-overview__card">
@ -177,7 +177,7 @@
import { DICT_TYPE, getDictObj, getIntDictOptions } from '@/utils/dict'
import { isHexColor } from '@/utils/color'
import { formatDate } from '@/utils/formatTime'
import { StockApi, StockVO } from '@/api/erp/stock/stock'
import { StockApi, type StockStatisticsCardsRespVO, type StockVO } from '@/api/erp/stock/stock'
import { StockRecordApi, StockRecordVO } from '@/api/erp/stock/record'
import { WarehouseApi, WarehouseVO } from '@/api/erp/stock/warehouse'
import { useDictStoreWithOut } from '@/store/modules/dict'
@ -204,10 +204,12 @@ const queryParams = reactive<{
dateRange: []
})
const cardsLoading = ref(false)
const stockLoading = ref(false)
const recordLoading = ref(false)
const stockList = ref<StockVO[]>([])
const recordList = ref<StockRecordVO[]>([])
const statisticsCards = ref<StockStatisticsCardsRespVO>()
const stockTotal = ref(0)
const stockQuery = reactive({
pageNo: 1,
@ -218,79 +220,78 @@ const recordQuery = reactive({
pageSize: 9
})
const summaryCards = computed(() => [
{
title: t('ErpStock.Overview.cards.finishedGoods.title'),
icon: 'ep:box',
color: 'blue',
lines: [
t('ErpStock.Overview.cards.finishedGoods.line1'),
t('ErpStock.Overview.cards.finishedGoods.line2'),
t('ErpStock.Overview.cards.finishedGoods.line3')
],
tip: t('ErpStock.Overview.cards.finishedGoods.tip')
},
{
title: t('ErpStock.Overview.cards.rawMaterial.title'),
icon: 'ep:collection',
color: 'green',
lines: [
t('ErpStock.Overview.cards.rawMaterial.line1'),
t('ErpStock.Overview.cards.rawMaterial.line2'),
t('ErpStock.Overview.cards.rawMaterial.line3'),
t('ErpStock.Overview.cards.rawMaterial.line4')
],
tip: t('ErpStock.Overview.cards.rawMaterial.tip')
},
{
title: t('ErpStock.Overview.cards.sparePart.title'),
icon: 'ep:setting',
color: 'orange',
lines: [
t('ErpStock.Overview.cards.sparePart.line1'),
t('ErpStock.Overview.cards.sparePart.line2'),
t('ErpStock.Overview.cards.sparePart.line3'),
t('ErpStock.Overview.cards.sparePart.line4')
],
tip: t('ErpStock.Overview.cards.sparePart.tip')
},
{
title: t('ErpStock.Overview.cards.todayIn.title'),
icon: 'ep:download',
color: 'blue',
lines: [
t('ErpStock.Overview.cards.todayIn.line1'),
t('ErpStock.Overview.cards.todayIn.line2'),
t('ErpStock.Overview.cards.todayIn.line3'),
t('ErpStock.Overview.cards.todayIn.line4'),
t('ErpStock.Overview.cards.todayIn.line5')
]
},
{
title: t('ErpStock.Overview.cards.todayOut.title'),
icon: 'ep:upload',
color: 'green',
lines: [
t('ErpStock.Overview.cards.todayOut.line1'),
t('ErpStock.Overview.cards.todayOut.line2'),
t('ErpStock.Overview.cards.todayOut.line3'),
t('ErpStock.Overview.cards.todayOut.line4'),
t('ErpStock.Overview.cards.todayOut.line5')
]
},
{
title: t('ErpStock.Overview.cards.warning.title'),
icon: 'ep:warning-filled',
color: 'red',
lines: [
t('ErpStock.Overview.cards.warning.line1'),
t('ErpStock.Overview.cards.warning.line2'),
t('ErpStock.Overview.cards.warning.line3'),
t('ErpStock.Overview.cards.warning.line4')
]
}
])
const displayValue = (value: unknown) => {
return value === undefined || value === null || value === '' ? '-' : value
}
const formatCardLine = (label: string, value: unknown) => `${label}: ${displayValue(value)}`
const summaryCards = computed(() => {
const data: StockStatisticsCardsRespVO = statisticsCards.value || {}
const productStock = data.productStock || {}
const materialStock = data.materialStock || {}
const sparePartStock = data.sparePartStock || {}
const todayIn = data.todayIn || {}
const todayOut = data.todayOut || {}
return [
{
title: t('ErpStock.Overview.cards.finishedGoods.title'),
icon: 'ep:box',
color: 'blue',
lines: [
formatCardLine(t('ErpStock.Overview.cardLabels.sku'), productStock.skuCount),
formatCardLine(t('ErpStock.Overview.cardLabels.stockSummary'), productStock.stockDisplay),
formatCardLine(t('ErpStock.Overview.cardLabels.todayFinishedIn'), productStock.todayFinishedInDisplay)
],
tip: t('ErpStock.Overview.cards.finishedGoods.tip')
},
{
title: t('ErpStock.Overview.cards.rawMaterial.title'),
icon: 'ep:collection',
color: 'green',
lines: [
formatCardLine(t('ErpStock.Overview.cardLabels.materialSku'), materialStock.skuCount),
formatCardLine(t('ErpStock.Overview.cardLabels.stockSummary'), materialStock.stockDisplay)
],
tip: t('ErpStock.Overview.cards.rawMaterial.tip')
},
{
title: t('ErpStock.Overview.cards.sparePart.title'),
icon: 'ep:setting',
color: 'orange',
lines: [
formatCardLine(t('ErpStock.Overview.cardLabels.sparePartSku'), sparePartStock.skuCount),
formatCardLine(t('ErpStock.Overview.cardLabels.stockSummary'), sparePartStock.stockDisplay)
],
tip: t('ErpStock.Overview.cards.sparePart.tip')
},
{
title: t('ErpStock.Overview.cards.todayIn.title'),
icon: 'ep:download',
color: 'blue',
lines: [
formatCardLine(t('ErpStock.Overview.cardLabels.inboundOrders'), todayIn.orderCount),
formatCardLine(t('ErpStock.Overview.cardLabels.detailLines'), todayIn.itemCount),
formatCardLine(t('ErpStock.Overview.cardLabels.productIn'), todayIn.productDisplay),
formatCardLine(t('ErpStock.Overview.cardLabels.materialIn'), todayIn.materialDisplay),
formatCardLine(t('ErpStock.Overview.cardLabels.sparePartIn'), todayIn.sparePartDisplay)
]
},
{
title: t('ErpStock.Overview.cards.todayOut.title'),
icon: 'ep:upload',
color: 'green',
lines: [
formatCardLine(t('ErpStock.Overview.cardLabels.outboundOrders'), todayOut.orderCount),
formatCardLine(t('ErpStock.Overview.cardLabels.detailLines'), todayOut.itemCount),
formatCardLine(t('ErpStock.Overview.cardLabels.materialOut'), todayOut.materialDisplay),
formatCardLine(t('ErpStock.Overview.cardLabels.sparePartOut'), todayOut.sparePartDisplay),
formatCardLine(t('ErpStock.Overview.cardLabels.productOut'), todayOut.productDisplay)
]
}
]
})
const areaOptions = computed(() => {
const areaMap = new Map<number, { id: number; areaName: string }>()
warehouseList.value.forEach((warehouse) => {
@ -323,6 +324,14 @@ const buildBaseQueryParams = () => {
})
}
const getStatisticsCards = async () => {
cardsLoading.value = true
try {
statisticsCards.value = await StockApi.getStockStatisticsCards()
} finally {
cardsLoading.value = false
}
}
const getStockList = async () => {
stockLoading.value = true
try {
@ -357,7 +366,7 @@ const getRecordList = async () => {
}
const getList = async () => {
await Promise.all([getStockList(), getRecordList()])
await Promise.all([getStatisticsCards(), getStockList(), getRecordList()])
}
const handleQuery = () => {
@ -476,7 +485,7 @@ onMounted(async () => {
.stock-overview__cards {
display: grid;
grid-template-columns: repeat(6, minmax(0, 1fr));
grid-template-columns: repeat(5, minmax(0, 1fr));
gap: 14px;
margin-bottom: 15px;
}

Loading…
Cancel
Save