feat:库存报表模块

main
黄伟杰 1 month ago
parent 32acd2f31b
commit 4c1d95010d

@ -6,10 +6,30 @@ export interface StockVO {
id: number id: number
// 产品编号 // 产品编号
productId: number productId: number
name?: string
productName?: string
barCode?: string
categoryName?: string
unitName?: string
// 产品分类类型
categoryType?: number
// 仓库编号 // 仓库编号
warehouseId: number warehouseId: number
warehouseName?: string
areaId?: number
areaName?: string
// 库存数量 // 库存数量
count: number count: number
latestInTime?: number | string
lastInTime?: number | string
recentInTime?: number | string
latestStockInTime?: number | string
lastStockInTime?: number | string
latestOutTime?: number | string
lastOutTime?: number | string
recentOutTime?: number | string
latestStockOutTime?: number | string
lastStockOutTime?: number | string
} }
// ERP 产品库存 API // ERP 产品库存 API

@ -345,11 +345,14 @@ export default {
Stock: { Stock: {
product: 'Product', product: 'Product',
warehouse: 'Warehouse', warehouse: 'Warehouse',
code: 'Code', code: 'Material Code',
name: 'Name', name: 'Material Name',
category: 'Category', category: 'Material Category',
area: 'Area',
unit: 'Unit', unit: 'Unit',
count: 'Stock Quantity', count: 'Base Quantity',
latestInTime: 'Latest Inbound',
latestOutTime: 'Latest Outbound',
placeholderProduct: 'Please select product', placeholderProduct: 'Please select product',
placeholderWarehouse: 'Please select warehouse', placeholderWarehouse: 'Please select warehouse',
exportName: 'Product Stock.xls' exportName: 'Product Stock.xls'

@ -345,11 +345,14 @@ export default {
Stock: { Stock: {
product: '产品', product: '产品',
warehouse: '仓库', warehouse: '仓库',
code: '编码', code: '物料编码',
name: '名称', name: '物料名称',
category: '分类', category: '物料大类',
area: '库区',
unit: '单位', unit: '单位',
count: '库存量', count: '基本数量',
latestInTime: '最近入库',
latestOutTime: '最近出库',
placeholderProduct: '请选择产品', placeholderProduct: '请选择产品',
placeholderWarehouse: '请选择仓库', placeholderWarehouse: '请选择仓库',
exportName: '产品库存.xls' exportName: '产品库存.xls'

@ -69,22 +69,13 @@
<!-- 列表 --> <!-- 列表 -->
<ContentWrap> <ContentWrap>
<!-- <el-tabs v-model="activeName" @tab-click="handleTabClick">
<el-tab-pane label="产品" name="2" />
<el-tab-pane label="原料" name="1" />
<el-tab-pane label="备件" name="5" />
<el-tab-pane label="工具" name="3" />
<el-tab-pane label="耗材" name="4" />
<el-tab-pane label="其他" name="0" />
</el-tabs> -->
<el-tabs v-model="activeName" @tab-click="handleTabClick"> <el-tabs v-model="activeName" @tab-click="handleTabClick">
<!-- 使用 v-for 动态生成 el-tab-pane --> <el-tab-pane
<el-tab-pane v-for="item in categoryTabs"
v-for="item in parentList" :key="String(item.value)"
:key="item.id" :label="item.label"
:label="item.name" :name="String(item.value)"
:name="item.id.toString()" />
/>
</el-tabs> </el-tabs>
<el-table <el-table
v-loading="loading" v-loading="loading"
@ -95,19 +86,31 @@
@selection-change="handleSelectionChange" @selection-change="handleSelectionChange"
> >
<el-table-column width="30" :label="t('action.select')" type="selection" /> <el-table-column width="30" :label="t('action.select')" type="selection" />
<el-table-column :label="t('ErpStock.Stock.code')" align="left" sortable prop="barCode" /> <el-table-column :label="t('ErpStock.Stock.code')" align="center" sortable prop="barCode" min-width="160" />
<el-table-column :label="t('ErpStock.Stock.name')" align="left" sortable prop="productName" /> <el-table-column :label="t('ErpStock.Stock.name')" align="center" sortable prop="name" min-width="180">
<el-table-column :label="t('ErpStock.Stock.category')" align="center" prop="categoryName" sortable /> <template #default="{ row }">
<el-table-column :label="t('ErpStock.Stock.unit')" align="center" prop="unitName" sortable /> {{ row.name || row.productName || '-' }}
<el-table-column </template>
:label="t('ErpStock.Stock.count')" </el-table-column>
align="right" <el-table-column :label="t('ErpStock.Stock.category')" align="center" prop="categoryName" min-width="120" sortable />
sortable <el-table-column :label="t('ErpStock.Stock.warehouse')" align="center" prop="warehouseName" min-width="140" sortable />
prop="count" <el-table-column :label="t('ErpStock.Stock.area')" align="center" prop="areaName" min-width="120" sortable />
:formatter="erpCountTableColumnFormatter" <el-table-column :label="t('ErpStock.Stock.count')" align="center" sortable prop="count" min-width="120">
/> <template #default="{ row }">
{{ formatStockCount(row.count) }}
<el-table-column :label="t('ErpStock.Stock.warehouse')" align="center" prop="warehouseName" sortable /> </template>
</el-table-column>
<el-table-column :label="t('ErpStock.Stock.unit')" align="center" prop="unitName" min-width="90" sortable />
<el-table-column :label="t('ErpStock.Stock.latestInTime')" align="center" min-width="180">
<template #default="{ row }">
{{ formatStockTime(getLatestInTime(row)) }}
</template>
</el-table-column>
<el-table-column :label="t('ErpStock.Stock.latestOutTime')" align="center" min-width="180">
<template #default="{ row }">
{{ formatStockTime(getLatestOutTime(row)) }}
</template>
</el-table-column>
</el-table> </el-table>
<!-- 分页 --> <!-- 分页 -->
<Pagination <Pagination
@ -121,34 +124,58 @@
<script setup lang="ts"> <script setup lang="ts">
import download from '@/utils/download' import download from '@/utils/download'
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { StockApi, StockVO } from '@/api/erp/stock/stock' import { StockApi, StockVO } from '@/api/erp/stock/stock'
import { ProductApi, ProductVO } from '@/api/erp/product/product' import { ProductApi, ProductVO } from '@/api/erp/product/product'
import { WarehouseApi, WarehouseVO } from '@/api/erp/stock/warehouse' import { WarehouseApi, WarehouseVO } from '@/api/erp/stock/warehouse'
import { erpCountTableColumnFormatter } from '@/utils' import { useDictStoreWithOut } from '@/store/modules/dict'
import { ProductCategoryApi, ProductCategoryVO } from '@/api/erp/product/category' import { formatDate } from '@/utils/formatTime'
import { handleTree } from '@/utils/tree'
/** ERP 产品库存列表 */ /** ERP 产品库存列表 */
defineOptions({ name: 'ErpStock' }) defineOptions({ name: 'ErpStock' })
const message = useMessage() // const message = useMessage() //
const { t } = useI18n() // const { t } = useI18n() //
const dictStore = useDictStoreWithOut()
const loading = ref(true) // const loading = ref(true) //
const list = ref<StockVO[]>([]) // const list = ref<StockVO[]>([]) //
const total = ref(0) // const total = ref(0) //
const queryParams = reactive({ const queryParams = reactive<{
pageNo: number
pageSize: number
productId?: number
warehouseId?: number
categoryType?: number
}>({
pageNo: 1, pageNo: 1,
pageSize: 10, pageSize: 10,
productId: undefined, productId: undefined,
warehouseId: undefined, warehouseId: undefined,
categoryId: undefined categoryType: undefined
}) })
const queryFormRef = ref() // const queryFormRef = ref() //
const exportLoading = ref(false) // const exportLoading = ref(false) //
const productList = ref<ProductVO[]>([]) // const productList = ref<ProductVO[]>([]) //
const warehouseList = ref<WarehouseVO[]>([]) // const warehouseList = ref<WarehouseVO[]>([]) //
const categoryList = ref<ProductCategoryVO[]>([]) // const categoryTabs = computed(() => getIntDictOptions(DICT_TYPE.MATERIAL_CLASSIFICATION_TYPE))
const parentList = ref<ProductCategoryVO[]>([])
const formatStockCount = (value: number | string | undefined) => {
if (value === undefined || value === null || value === '') return '-'
const num = Number(value)
return Number.isFinite(num) ? num.toLocaleString() : String(value)
}
const formatStockTime = (value: any) => {
return value ? formatDate(value, 'YYYY-MM-DD HH:mm:ss') : '-'
}
const getLatestInTime = (row: any) => {
return row.latestInTime ?? row.lastInTime ?? row.recentInTime ?? row.latestStockInTime ?? row.lastStockInTime
}
const getLatestOutTime = (row: any) => {
return row.latestOutTime ?? row.lastOutTime ?? row.recentOutTime ?? row.latestStockOutTime ?? row.lastStockOutTime
}
/** 查询列表 */ /** 查询列表 */
const getList = async () => { const getList = async () => {
@ -221,28 +248,24 @@ const handleSelectionChange = (rows: StockVO[]) => {
/** 初始化 **/ /** 初始化 **/
onMounted(async () => { onMounted(async () => {
queryParams.categoryId = 2 await dictStore.setDictMap()
await loadCategoryTabs()
await getList() await getList()
// //
productList.value = await ProductApi.getProductSimpleList() productList.value = await ProductApi.getProductSimpleList()
warehouseList.value = await WarehouseApi.getWarehouseSimpleList() warehouseList.value = await WarehouseApi.getWarehouseSimpleList()
//
const categoryData = await ProductCategoryApi.getProductCategorySimpleList()
categoryList.value = handleTree(categoryData, 'id', 'parentId')
//
for (let i = 0; i < categoryData.length; i++) {
if (categoryData[i].parentId === 0) {
parentList.value.push(categoryData[i]);
}
}
//
parentList.value.sort((a, b) => a.sort - b.sort);
}) })
/** tab 切换 */ /** tab 切换 */
let activeName = '2' const activeName = ref('')
const handleTabClick = (tab: TabsPaneContext) => { const handleTabClick = (tab: TabsPaneContext) => {
queryParams.categoryId = tab.paneName queryParams.categoryType = tab.paneName ? Number(tab.paneName) : undefined
handleQuery() handleQuery()
} }
const loadCategoryTabs = async () => {
const defaultValue = categoryTabs.value[0]?.value
queryParams.categoryType = defaultValue !== undefined && defaultValue !== null ? Number(defaultValue) : undefined
activeName.value = defaultValue !== undefined && defaultValue !== null ? String(defaultValue) : ''
}
</script> </script>

Loading…
Cancel
Save