diff --git a/src/api/erp/stock/record/index.ts b/src/api/erp/stock/record/index.ts index a758eb49..fbf04240 100644 --- a/src/api/erp/stock/record/index.ts +++ b/src/api/erp/stock/record/index.ts @@ -2,15 +2,28 @@ import request from '@/config/axios' // ERP 产品库存明细 VO export interface StockRecordVO { - id: number // 编号 - productId: number // 产品编号 - warehouseId: number // 仓库编号 - count: number // 出入库数量 - totalCount: number // 总库存量 - bizType: number // 业务类型 - bizId: number // 业务编号 - bizItemId: number // 业务项编号 - bizNo: string // 业务单号 + id: number + productId: number + bizDirection?: string + bizDocType?: number + categoryType?: number + warehouseId: number + areaId?: number + areaName?: string + count: number + totalCount: number + bizType: number + bizId: number + bizItemId: number + bizNo: string + createTime?: string + creator?: string + productName: string + categoryName: string + unitName: string + warehouseName: string + creatorName: string + recordTime?: string } // ERP 产品库存明细 API diff --git a/src/api/erp/stock/stock/index.ts b/src/api/erp/stock/stock/index.ts index 4de86fb1..a9dd22b4 100644 --- a/src/api/erp/stock/stock/index.ts +++ b/src/api/erp/stock/stock/index.ts @@ -6,10 +6,34 @@ export interface StockVO { id: number // 产品编号 productId: number + name?: string + productName?: string + barCode?: string + categoryName?: string + unitName?: string + // 产品分类类型 + categoryType?: number // 仓库编号 warehouseId: number + warehouseName?: string + areaId?: number + areaName?: string + // 包装/换算规则 + packagingRule?: string + // 库存展示 + stockDisplay?: string // 库存数量 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 @@ -25,8 +49,8 @@ export const StockApi = { }, // 查询产品库存详情 - getStock2: async (productId: number, warehouseId: number) => { - return await request.get({ url: `/erp/stock/get`, params: { productId, warehouseId } }) + getStock2: async (productId: number, warehouseId: number, areaId?: number) => { + return await request.get({ url: `/erp/stock/get`, params: { productId, warehouseId, areaId } }) }, // 获得产品库存数量 diff --git a/src/locales/en.ts b/src/locales/en.ts index bf2d5f15..7e6b3705 100644 --- a/src/locales/en.ts +++ b/src/locales/en.ts @@ -345,12 +345,19 @@ Stock: { product: 'Product', warehouse: 'Warehouse', - code: 'Code', - name: 'Name', - category: 'Category', + code: 'Material Code', + name: 'Material Name', + category: 'Material Category', + subCategory: 'Material Subcategory', + area: 'Area', + packagingRule: 'Packaging / Conversion Rule', + stockDisplay: 'Stock Display', unit: 'Unit', - count: 'Stock Quantity', + count: 'Base Quantity', + latestInTime: 'Latest Inbound', + latestOutTime: 'Latest Outbound', placeholderProduct: 'Please select product', + placeholderCategory: 'Please select material category', placeholderWarehouse: 'Please select warehouse', exportName: 'Product Stock.xls' }, @@ -487,8 +494,15 @@ inventoryUnit: 'Inventory Unit', purchaseUnit: 'Purchase Unit', purchaseUnitConvertQuantity: 'Purchase Convert Qty', + defaultSupplier: 'Supplier (Default)', + outboundPurpose: 'Outbound Purpose', + relatedOrder: 'Related Order', + relatedRepairOrder: 'Related Repair Order', + relatedMaintainRecord: 'Related Maintenance Record', + selectRelatedRepairOrder: 'Select Repair Order', + selectRelatedMaintainRecord: 'Select Maintenance Record', inputUnitType: 'Unit Input Type', - inputCount: 'Input Count', + inputCount: 'Purchase Unit Quantity', count: 'Quantity', price: 'Price', totalPrice: 'Total Price', @@ -503,13 +517,17 @@ placeholderArea: 'Please select area', placeholderProduct: 'Please select product', placeholderBarcode: 'Please select barcode', + placeholderOutboundPurpose: 'Please select outbound purpose', + placeholderRelatedRepairOrder: 'Please select related repair order', + placeholderRelatedMaintainRecord: 'Please select related maintenance record', placeholderInputUnitType: 'Please select', placeholderCode: 'Please enter code', placeholderName: 'Please enter name', validatorWarehouseRequired: 'Warehouse is required', validatorAreaRequired: 'Please select area', validatorProductRequired: 'Product is required', - validatorCountRequired: 'Quantity is required' + validatorCountRequired: 'Quantity is required', + stockCountExceededWarning: 'Quantity cannot exceed stock. It has been adjusted to stock quantity.' }, Check: { no: 'Check No', @@ -549,10 +567,20 @@ } }, Record: { + id: 'ID', product: 'Product', warehouse: 'Warehouse', bizType: 'Type', bizNo: 'Business No', + bizDirection: 'Direction', + categoryType: 'Business Type', + materialCategory: 'Material Category', + productId: 'Product ID', + warehouseId: 'Warehouse ID', + areaId: 'Area ID', + bizId: 'Business ID', + bizItemId: 'Business Item ID', + creator: 'Creator', categoryProduct: 'Product', categoryMaterial: 'Material', categorySpare: 'Spare Part', @@ -562,13 +590,15 @@ productName: 'Product Name', categoryName: 'Product Category', unitName: 'Unit', - warehouseName: 'Warehouse Code', + warehouseName: 'Warehouse Name', + areaName: 'Area Name', count: 'In/Out Quantity', totalCount: 'Stock Quantity', - recordTime: 'In/Out Date', + recordTime: 'Operation Time', createTime: 'Create Date', creatorName: 'Operator', placeholderProduct: 'Please select product', + placeholderMaterialCategory: 'Please select material category', placeholderWarehouse: 'Please select warehouse', placeholderBizType: 'Please select type', placeholderBizNo: 'Please input business no', @@ -2712,6 +2742,7 @@ tabInspection: 'Inspection Records', tabRepair: 'Repair Records', tabMaintain: 'Maintenance Records', + pressureNetRecord: 'Pressure Net Record', tabInstall: 'Installation Records', tabDrawings: 'Drawings', tabOperationManual: 'Operation Manual', @@ -2763,6 +2794,10 @@ createTime: 'Operation Time', noInstallRecords: 'No installation records', noRecords: 'No data', + moldBrandName: 'Mold Group Name', + subMoldName: 'Sub Mold Name', + pressureNetTime: 'Pressure Net Time', + placeholderPressureNetTime: 'Please select pressure net time', pending: 'Pending', pass: 'Pass', fail: 'Fail', diff --git a/src/locales/zh-CN.ts b/src/locales/zh-CN.ts index 4ae28bfc..8553a215 100644 --- a/src/locales/zh-CN.ts +++ b/src/locales/zh-CN.ts @@ -345,12 +345,19 @@ Stock: { product: '产品', warehouse: '仓库', - code: '编码', - name: '名称', - category: '分类', + code: '物料编码', + name: '物料名称', + category: '物料大类', + subCategory: '物料小类', + area: '库区', + packagingRule: '包装/换算规则', + stockDisplay: '库存展示', unit: '单位', - count: '库存量', + count: '基本数量', + latestInTime: '最近入库', + latestOutTime: '最近出库', placeholderProduct: '请选择产品', + placeholderCategory: '请选择物料大类', placeholderWarehouse: '请选择仓库', exportName: '产品库存.xls' }, @@ -487,8 +494,15 @@ inventoryUnit: '库存单位', purchaseUnit: '采购单位', purchaseUnitConvertQuantity: '采购换算数量', + defaultSupplier: '供应商(默认)', + outboundPurpose: '出库用途', + relatedOrder: '关联单据', + relatedRepairOrder: '关联维修单', + relatedMaintainRecord: '关联保养记录', + selectRelatedRepairOrder: '选择维修单', + selectRelatedMaintainRecord: '选择保养记录', inputUnitType: '单位输入方式', - inputCount: '录入数量', + inputCount: '采购单位数量', count: '数量', price: '产品单价', totalPrice: '合计金额', @@ -503,13 +517,17 @@ placeholderArea: '请选择库区', placeholderProduct: '请选择产品', placeholderBarcode: '请选择编码', + placeholderOutboundPurpose: '请选择出库用途', + placeholderRelatedRepairOrder: '请选择关联维修单', + placeholderRelatedMaintainRecord: '请选择关联保养记录', placeholderInputUnitType: '请选择', placeholderCode: '请输入编码', placeholderName: '请输入名称', validatorWarehouseRequired: '仓库不能为空', validatorAreaRequired: '请选择库区', validatorProductRequired: '产品不能为空', - validatorCountRequired: '产品数量不能为空' + validatorCountRequired: '产品数量不能为空', + stockCountExceededWarning: '数量不能超出库存,已自动调整为库存数量' }, Check: { no: '盘点单号', @@ -549,10 +567,20 @@ } }, Record: { + id: '编号', product: '产品', warehouse: '仓库', bizType: '类型', bizNo: '业务单号', + bizDirection: '方向', + categoryType: '业务类型', + materialCategory: '物料大类', + productId: '产品编号', + warehouseId: '仓库编号', + areaId: '库区编号', + bizId: '业务编号', + bizItemId: '业务项编号', + creator: '创建人', categoryProduct: '产品', categoryMaterial: '原料', categorySpare: '备件', @@ -562,13 +590,15 @@ productName: '产品名称', categoryName: '产品分类', unitName: '产品单位', - warehouseName: '仓库编号', + warehouseName: '仓库名称', + areaName: '库区名称', count: '出入库数量', totalCount: '库存量', - recordTime: '出入库日期', + recordTime: '操作时间', createTime: '创建日期', creatorName: '操作人', placeholderProduct: '请选择产品', + placeholderMaterialCategory: '请选择物料大类', placeholderWarehouse: '请选择仓库', placeholderBizType: '请选择类型', placeholderBizNo: '请输入业务单号', @@ -2191,6 +2221,7 @@ tabInspection: '点检记录', tabRepair: '维修记录', tabMaintain: '保养记录', + pressureNetRecord: '压网记录', tabInstall: '安装记录', tabDrawings: '图纸', tabOperationManual: '操作手册', @@ -2247,6 +2278,10 @@ createTime: '操作时间', noInstallRecords: '暂无安装记录', noRecords: '暂无数据', + moldBrandName: '模具组名称', + subMoldName: '子模具名称', + pressureNetTime: '压网时间', + placeholderPressureNetTime: '请选择压网时间', // 检测结果 pending: '待检测', pass: '通过', diff --git a/src/store/modules/dict.ts b/src/store/modules/dict.ts index e3fda4da..f16e64ea 100644 --- a/src/store/modules/dict.ts +++ b/src/store/modules/dict.ts @@ -22,6 +22,20 @@ export interface DictState { isSetDict: boolean } +const normalizeDictMap = (dictMap: Recordable = {}) => { + const normalizedDictMap: Recordable = {} + Object.keys(dictMap || {}).forEach((dictType) => { + const normalizedDictType = dictType.trim() + const dictList = dictMap[dictType] + if (Array.isArray(normalizedDictMap[normalizedDictType]) && Array.isArray(dictList)) { + normalizedDictMap[normalizedDictType].push(...dictList) + } else { + normalizedDictMap[normalizedDictType] = dictList + } + }) + return normalizedDictMap +} + export const useDictStore = defineStore('dict', { state: (): DictState => ({ dictMap: new Map(), @@ -31,7 +45,7 @@ export const useDictStore = defineStore('dict', { getDictMap(): Recordable { const dictMap = wsCache.get(CACHE_KEY.DICT_CACHE) if (dictMap) { - this.dictMap = dictMap + this.dictMap = normalizeDictMap(dictMap) } return this.dictMap }, @@ -43,13 +57,15 @@ export const useDictStore = defineStore('dict', { async setDictMap() { const dictMap = wsCache.get(CACHE_KEY.DICT_CACHE) if (dictMap) { - const dictTypes = Object.keys(dictMap || {}) + const normalizedDictMap = normalizeDictMap(dictMap) + const dictTypes = Object.keys(normalizedDictMap || {}) const firstDictType = dictTypes[0] - const firstList = firstDictType ? dictMap[firstDictType] : undefined + const firstList = firstDictType ? normalizedDictMap[firstDictType] : undefined const needsUpgrade = Array.isArray(firstList) && firstList.length > 0 && !('labelEn' in (firstList[0] || {})) if (!needsUpgrade) { - this.dictMap = dictMap + this.dictMap = normalizedDictMap + wsCache.set(CACHE_KEY.DICT_CACHE, normalizedDictMap, { exp: 60 }) this.isSetDict = true return } @@ -58,11 +74,12 @@ export const useDictStore = defineStore('dict', { const res = await getSimpleDictDataList() const dictDataMap = new Map() res.forEach((dictData: DictDataVO) => { - const enumValueObj = dictDataMap[dictData.dictType] + const dictType = dictData.dictType.trim() + const enumValueObj = dictDataMap[dictType] if (!enumValueObj) { - dictDataMap[dictData.dictType] = [] + dictDataMap[dictType] = [] } - dictDataMap[dictData.dictType].push({ + dictDataMap[dictType].push({ value: dictData.value, label: dictData.label, labelEn: (dictData as any).labelEn, @@ -91,11 +108,12 @@ export const useDictStore = defineStore('dict', { const res = await getSimpleDictDataList() const dictDataMap = new Map() res.forEach((dictData: DictDataVO) => { - const enumValueObj = dictDataMap[dictData.dictType] + const dictType = dictData.dictType.trim() + const enumValueObj = dictDataMap[dictType] if (!enumValueObj) { - dictDataMap[dictData.dictType] = [] + dictDataMap[dictType] = [] } - dictDataMap[dictData.dictType].push({ + dictDataMap[dictType].push({ value: dictData.value, label: dictData.label, labelEn: (dictData as any).labelEn, diff --git a/src/utils/dict.ts b/src/utils/dict.ts index d4ca95c3..427a7797 100644 --- a/src/utils/dict.ts +++ b/src/utils/dict.ts @@ -228,6 +228,11 @@ export enum DICT_TYPE { ERP_AUDIT_STATUS = 'erp_audit_status',// ERP 审批状态 ERP_STOCK_RECORD_BIZ_TYPE = 'erp_stock_record_biz_type',// 库存明细的业务类型 ERP_MOLD_STATUS = 'erp_mold_status',// ERP 模具状态 + WAREHOUSE_DOCUMENT_TYPES = 'warehouse_document_types', // 入库单据类型 + WAREHOUSE_DOCUMENT_OUT_TYPES = 'warehouse_document_out_types', // 出库单据类型 + WAREHOUSE_RECEIVING_STATUS = 'warehouse_receiving_status', // 入库状态 + WAREHOUSE_OUTBOUND_STATUS = 'Warehouse_outbound_status', // 出库状态 + WAREHOUSE_OUTBOUND_PURPOSE = 'warehouse_outbound_purpose', // 出库用途 SUBMOLD_TYPE = 'submold_type', // 子模具类型 ERP_MAINTAIN_TYPE = 'maintain_type',// ERP 保养类型 diff --git a/src/views/erp/mold/detail/brand.vue b/src/views/erp/mold/detail/brand.vue index 5c3510c4..d5a08226 100644 --- a/src/views/erp/mold/detail/brand.vue +++ b/src/views/erp/mold/detail/brand.vue @@ -252,6 +252,22 @@ class="device-ledger-history-item-label">{{ t('MoldManagement.MoldBrandDetail.maintainTime') }}{{ String(formatHistoryTime(item.taskTime)).split(' ')[0] }} +
{{ t('MoldManagement.MoldBrandDetail.images') }} +
+ +
+
-
+
{{ t('MoldManagement.MoldBrandDetail.remark') }}{{ item.remark ?? '-' }}
@@ -263,6 +279,44 @@ + +
+ + + + + + {{ t('MoldManagement.MoldBrandDetail.query') }} + {{ t('MoldManagement.MoldBrandDetail.reset') }} + + + + + + + + + + + + + + + + + +
+
@@ -374,10 +428,15 @@ const maintainHistory = ref([]) const repairList = ref([]) const repairQueryCode = ref() const repairQueryStatus = ref() +const pressureNetRecordList = ref([]) const installRecords = ref([]) const installTotal = ref(0) const installPageNo = ref(1) const installPageSize = ref(10) +const pressureNetTotal = ref(0) +const pressureNetPageNo = ref(1) +const pressureNetPageSize = ref(10) +const pressureNetTime = ref() const installMoldId = ref() const installRemark = ref() const installDateRange = ref() @@ -393,6 +452,7 @@ const repairExportLoading = ref(false) const inspectionLoading = ref(false) const repairLoading = ref(false) const maintainLoading = ref(false) +const pressureNetLoading = ref(false) const installLoading = ref(false) const imageList = computed(() => parseImages(detailData.value?.images)) @@ -727,6 +787,38 @@ const fetchRepairHistory = async () => { } } +const fetchPressureNetRecords = async () => { + if (!brandId.value) return + pressureNetLoading.value = true + try { + const params: any = { + pageNo: pressureNetPageNo.value, + pageSize: pressureNetPageSize.value, + moldBrandId: brandId.value + } + if (pressureNetTime.value && pressureNetTime.value.length === 2) { + params['pressureNetTime[0]'] = pressureNetTime.value[0] + params['pressureNetTime[1]'] = pressureNetTime.value[1] + } + const data = await MoldBrandApi.getPressureNetRecordPage(params) + pressureNetRecordList.value = data?.list ?? [] + pressureNetTotal.value = data?.total ?? 0 + } finally { + pressureNetLoading.value = false + } +} + +const handleQueryPressureNet = () => { + pressureNetPageNo.value = 1 + fetchPressureNetRecords() +} + +const handleResetPressureNet = () => { + pressureNetTime.value = undefined + pressureNetPageNo.value = 1 + fetchPressureNetRecords() +} + const fetchInstallRecords = async () => { if (!brandId.value) return installLoading.value = true @@ -836,6 +928,9 @@ const loadTabData = async (tab: string) => { await getChildMolds() fetchMaintainHistory() break + case 'pressureNet': + fetchPressureNetRecords() + break case 'install': await getChildMolds() fetchInstallRecords() diff --git a/src/views/erp/product/product/ProductForm.vue b/src/views/erp/product/product/ProductForm.vue index e939214f..3899508d 100644 --- a/src/views/erp/product/product/ProductForm.vue +++ b/src/views/erp/product/product/ProductForm.vue @@ -73,6 +73,18 @@ /> + + + + + + + @@ -165,18 +177,6 @@ - - - - - - - diff --git a/src/views/erp/stock/in/components/StockInItemForm.vue b/src/views/erp/stock/in/components/StockInItemForm.vue index 661ef9c3..1bdb41c3 100644 --- a/src/views/erp/stock/in/components/StockInItemForm.vue +++ b/src/views/erp/stock/in/components/StockInItemForm.vue @@ -16,7 +16,14 @@ + + + + + + + + + + + + +
+ +
+ +
-/** tab 切换 */ -const activeName = ref('') -const handleTabClick = (tab: TabsPaneContext) => { - queryParams.categoryId = tab.paneName ? Number(tab.paneName) : undefined - handleQuery() + diff --git a/src/views/erp/stock/stock/index.vue b/src/views/erp/stock/stock/index.vue index 64e074dd..1c7a16e6 100644 --- a/src/views/erp/stock/stock/index.vue +++ b/src/views/erp/stock/stock/index.vue @@ -27,6 +27,22 @@
+ + + + + + - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + import download from '@/utils/download' +import { DICT_TYPE, getDictObj, getIntDictOptions } from '@/utils/dict' import { StockApi, StockVO } from '@/api/erp/stock/stock' import { ProductApi, ProductVO } from '@/api/erp/product/product' import { WarehouseApi, WarehouseVO } from '@/api/erp/stock/warehouse' -import { erpCountTableColumnFormatter } from '@/utils' -import { ProductCategoryApi, ProductCategoryVO } from '@/api/erp/product/category' -import { handleTree } from '@/utils/tree' +import { useDictStoreWithOut } from '@/store/modules/dict' +import { formatDate } from '@/utils/formatTime' +import { isHexColor } from '@/utils/color' /** ERP 产品库存列表 */ defineOptions({ name: 'ErpStock' }) const message = useMessage() // 消息弹窗 const { t } = useI18n() // 国际化 +const dictStore = useDictStoreWithOut() const loading = ref(true) // 列表的加载中 const list = ref([]) // 列表的数据 const total = ref(0) // 列表的总页数 -const queryParams = reactive({ +const queryParams = reactive<{ + pageNo: number + pageSize: number + productId?: number + warehouseId?: number + categoryType?: number +}>({ pageNo: 1, pageSize: 10, productId: undefined, warehouseId: undefined, - categoryId: undefined + categoryType: undefined }) const queryFormRef = ref() // 搜索的表单 const exportLoading = ref(false) // 导出的加载中 const productList = ref([]) // 产品列表 const warehouseList = ref([]) // 仓库列表 -const categoryList = ref([]) // 产品分类列表 -const parentList = ref([]) +const categoryTypeOptions = computed(() => getIntDictOptions(DICT_TYPE.MATERIAL_CLASSIFICATION_TYPE)) + +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 formatStockDisplay = (value: string | undefined) => { + if (!value) return [] + return value + .split(',') + .map((item) => item.trim()) + .filter(Boolean) +} + +const getStockDisplayStyle = (categoryType: number | string | undefined) => { + const dict = getDictObj(DICT_TYPE.MATERIAL_CLASSIFICATION_TYPE, categoryType) + if (dict?.cssClass && isHexColor(dict.cssClass)) { + return { color: dict.cssClass } + } + const colorType = dict?.colorType && !['primary', 'default'].includes(String(dict.colorType)) + ? dict.colorType + : 'primary' + return { color: `var(--el-color-${colorType})` } +} + +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 buildQueryParams = () => { + return Object.fromEntries( + Object.entries(queryParams).filter(([, value]) => value !== undefined && value !== null && value !== '') + ) +} /** 查询列表 */ const getList = async () => { loading.value = true try { - const data = await StockApi.getStockPage(queryParams) + const data = await StockApi.getStockPage(buildQueryParams()) list.value = data.list total.value = data.total } finally { @@ -202,7 +287,7 @@ const handleExport = async () => { exportLoading.value = true const ids = selectionList.value.map((item) => item.id).filter((v) => v != null) const params = { - ...queryParams, + ...buildQueryParams(), ids: ids.length ? ids.join(',') : undefined } const data = await StockApi.exportStock(params) @@ -221,28 +306,25 @@ const handleSelectionChange = (rows: StockVO[]) => { /** 初始化 **/ onMounted(async () => { - queryParams.categoryId = 2 + await dictStore.setDictMap() await getList() // 加载产品、仓库列表 productList.value = await ProductApi.getProductSimpleList() 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 切换 */ -let activeName = '2' -const handleTabClick = (tab: TabsPaneContext) => { - queryParams.categoryId = tab.paneName - handleQuery() +