diff --git a/src/api/wms/allocateOrderDetail/types.ts b/src/api/wms/allocateOrderDetail/types.ts index 2d66d80..76e9516 100644 --- a/src/api/wms/allocateOrderDetail/types.ts +++ b/src/api/wms/allocateOrderDetail/types.ts @@ -47,6 +47,36 @@ export interface AllocateOrderDetailForm extends BaseEntity { */ materialId?: string | number; + /** + * 物料编码(仅用于前端显示) + */ + materialCode?: string; + + /** + * 物料名称(仅用于前端显示) + */ + materialName?: string; + + /** + * 批次码(仅用于前端显示) + */ + batchCode?: string; + + /** + * 库位编码(仅用于前端显示) + */ + locationCode?: string; + + /** + * 仓库ID(仅用于前端显示) + */ + storeId?: string | number; + + /** + * 库存数量(仅用于前端显示) + */ + inventoryQty?: number; + /** * 调拨数量 */ diff --git a/src/api/wms/baseMaterialInfo/types.ts b/src/api/wms/baseMaterialInfo/types.ts index 7c29d20..dd0601c 100644 --- a/src/api/wms/baseMaterialInfo/types.ts +++ b/src/api/wms/baseMaterialInfo/types.ts @@ -341,7 +341,7 @@ export interface BaseMaterialInfoForm extends BaseEntity { * 物料大类(字典改为从数据库中获得) */ materialCategoryId: string; - materialCategories: string;//暂时保留 + // materialCategories: string;//暂时保留 /** * 物料小类 diff --git a/src/api/wms/instockDetail/types.ts b/src/api/wms/instockDetail/types.ts index 2c4a3c6..8caf383 100644 --- a/src/api/wms/instockDetail/types.ts +++ b/src/api/wms/instockDetail/types.ts @@ -87,7 +87,7 @@ export interface InstockDetailVO { purchaseQty?: number; /** - * 已入库数量(来自采购订单统计) + * 已入库数量(来自WmsInstockRecord入库记录统计,表示已打印并扫描入库的实际数量) */ instockedQty?: number; @@ -96,6 +96,15 @@ export interface InstockDetailVO { */ remainingQty?: number; + /** + * 每包数量列表(当分包数量>1时使用) + */ + packageQtyList?: number[]; + + /** + * 分包模式(average:平均分包, custom:自定义每包数量) + */ + packageMode?: string; } @@ -183,7 +192,7 @@ export interface InstockDetailForm extends BaseEntity { purchaseQty?: number; /** - * 已入库数量(来自采购订单统计) + * 已入库数量(来自WmsInstockRecord入库记录统计,表示已打印并扫描入库的实际数量) */ instockedQty?: number; @@ -192,6 +201,16 @@ export interface InstockDetailForm extends BaseEntity { */ remainingQty?: number; + /** + * 每包数量列表(当分包数量>1时使用) + */ + packageQtyList?: number[]; + + /** + * 分包模式(average:平均分包, custom:自定义每包数量) + */ + packageMode?: string; + } export interface InstockDetailQuery extends PageQuery { diff --git a/src/views/wms/baseMaterialInfo/index.vue b/src/views/wms/baseMaterialInfo/index.vue index 0d2432e..b6a2e2e 100644 --- a/src/views/wms/baseMaterialInfo/index.vue +++ b/src/views/wms/baseMaterialInfo/index.vue @@ -78,11 +78,14 @@ {{ formatDayHourMinutes(scope.row.minParkingTime) }} - + {{ formatDayHourMinutes(scope.row.maxParkingTime) }} + + + @@ -156,34 +159,7 @@ - - - 天 - - 小时 - - 分钟 - - - - - - - + 天 - - 小时 - - 分钟 + + + + + + + + + + + + + + + + + + + + + + @@ -260,6 +259,7 @@ import { BaseMaterialInfoVO, BaseMaterialInfoQuery, BaseMaterialInfoForm } from // import { getFactoryList } from "@/api/wms/baseFactoryInfo"; import { getBaseMaterialTypeList } from "@/api/wms/baseMaterialType"; import {getBaseMaterialCategoryListInWMS} from "@/api/wms/baseMaterialCategory"; +import { formatDayHourMinutes } from '@/utils/ruoyi'; const { proxy } = getCurrentInstance() as ComponentInternalInstance; const { apply_flag, inner_tube_flag, @@ -307,10 +307,13 @@ const columns = ref([ { key: 5, label: `物料规格`, visible: true }, { key: 6, label: `最小停放时间`, visible: false }, - { key: 7, label: `最大停放时间`, visible: true }, + { key: 7, label: `保质期`, visible: true }, { key: 8, label: `备注`, visible: false }, { key: 9, label: `"是否高价值`, visible: true }, { key: 10, label: `质检要求`, visible: true }, + { key: 11, label: `最大库存`, visible: true }, + { key: 12, label: `最小库存`, visible: true }, + { key: 13, label: `安全库存`, visible: true }, ]); const initFormData: BaseMaterialInfoForm = { @@ -343,9 +346,11 @@ const initFormData: BaseMaterialInfoForm = { purchasePriceUnitId: undefined, approveDate: undefined, erpModifyDate: undefined, + maxStockAmount: undefined, minStockAmount: undefined, safeStockAmount: undefined, + applyFlag: undefined, materialClassfication: undefined, autoOutstockFlag: undefined, @@ -375,6 +380,7 @@ const initFormData: BaseMaterialInfoForm = { isHighValue: undefined, inspectionRequest: undefined, + } const data = reactive>({ form: {...initFormData}, diff --git a/src/views/wms/instockOrderCopy/index.vue b/src/views/wms/instockOrderCopy/index.vue index 1845fce..a7c3df5 100644 --- a/src/views/wms/instockOrderCopy/index.vue +++ b/src/views/wms/instockOrderCopy/index.vue @@ -142,7 +142,7 @@ - + 打印 - - - - - @@ -306,10 +293,10 @@ - + {{ scope.row.instockQty }} - - - - - - - + + + + + + + + + + + + + + + + - + + + + + + 平均分包 + 自定义每包数量 + + + + + + + + 第{{index + 1}}包: + {{qty}}个 + + + 总计:{{averageTotal}} / {{remainingQty}} + + + + + + + + + 第{{index + 1}}包: + + + + 总计:{{totalPackageQty}} / {{remainingQty}} + + + + @@ -657,9 +687,27 @@ const childrenTableInfoVisible = ref(false) const updateDialog = ref(false) const dialogTitle = ref('添加') const dialogForm = ref({ instockType: '', orderNo: '', materialCategoryId: '', warehouseId: '' }); -const parentTableInfoForm = ref({}) -const parentTableApproveForm = ref({}) -const childrenTableInfoForm = ref({}) +const parentTableInfoForm = ref({ + materialCategoryId: '', + instockType: '', + auditBy: '', + warehouseCode: '' +}) +const parentTableApproveForm = ref({ + auditStatus: '', + auditComments: '' +}) +const childrenTableInfoForm = ref({ + materialCode: '', + instockQty: 0, + codeYesNo: '', + printedNum: 0, + splitPackageCount: 1, + printCopies: 1, + packageQtyList: [] as number[], + packageMode: 'average', + batchCode: '' +}) const queryForm = ref({ @@ -669,6 +717,7 @@ const queryForm = ref({ warehouseId: '', instockType: '', instockMethond: '', + auditStatus: '', pageNum: 1, pageSize: 10 }) @@ -697,7 +746,7 @@ const materialList = ref([]); const parentTableLoad = ref(false) const childrenTableLoad = ref(false) const isView = ref(false) -const partntTableSelectCell = ref({}) +const partntTableSelectCell = ref({ instockId: null }) const showSearch = ref(true) const columns = ref([]) @@ -729,19 +778,49 @@ const submitForm = async() => { const copies = Number(childrenTableInfoForm.value.printCopies) || 1 const remaining = remainingQty.value - if (split > remaining) { - ElMessage.error('分包数量不能超过剩余物料量') - return - } - if (split > 1) { - if (remaining % split !== 0) { - ElMessage.error('剩余物料量无法平均分包,请调整分包数量') + // 分包逻辑:根据模式选择数据源 + let finalPackageList = [] + if (packageMode.value === 'average') { + // 平均分包模式:使用平均分包的结果 + finalPackageList = averagePackageList.value + const total = averageTotal.value + if (total > remaining) { + ElMessage.error('平均分包总计不能超过剩余物料量') + return + } + if (total <= 0) { + ElMessage.error('平均分包数量必须大于0') + return + } + } else { + // 自定义模式:使用用户输入的数量 + finalPackageList = packageQtyList.value + const total = totalPackageQty.value + if (total > remaining) { + ElMessage.error('每包数量总计不能超过剩余物料量') + return + } + if (total <= 0) { + ElMessage.error('每包数量必须大于0') + return + } + // 检查是否有空或负数 + if (packageQtyList.value.some(qty => !qty || qty <= 0)) { + ElMessage.error('每包数量必须大于0') + return + } + } + + // 将最终的分包数量传递给后端 + childrenTableInfoForm.value.packageQtyList = finalPackageList + childrenTableInfoForm.value.packageMode = packageMode.value // 传递模式信息 + } else { + // 不分包逻辑 + if (split > remaining) { + ElMessage.error('分包数量不能超过剩余物料量') return } - // 对于分包>1,设置barcodeNum=1(每个包打印1份) - childrenTableInfoForm.value.printCopies = 1 - } else { if (copies < 1) { ElMessage.error('重复打印数量至少为1') return @@ -777,7 +856,7 @@ const generateBatchCode = (form) => { }).join('') } - +//物料大类 let mategoryOptions = ref([]); const getMaterialCategorySelect = async () => { const res = await getBaseMaterialCategoryListInWMS(null); @@ -844,9 +923,9 @@ const reset = () => { instockCode: '', materialCategoryId: '', materialCategoryName: '', - warehouseId: '', instockType: '', instockMethond: routeInstockMethondValue,// 使用保存的路由参数值 + auditStatus: '', pageNum: 1, pageSize: 10 } @@ -875,8 +954,14 @@ const viewDetails = (e) => { // 父表格新增 const parentTableAdd = () => { dialogVisible.value = true; - dialogForm.value = { instockType: '', orderNo: '', materialCategoryId: '', warehouseId: '' }; // Add more if needed + dialogForm.value = { instockType: '', orderNo: '', materialCategoryId: '', warehouseId: '' }; dialogtable.value = []; + // 清空表单验证状态 + setTimeout(() => { + if (dialogFormRef.value) { + dialogFormRef.value.clearValidate(); + } + }, 100); }; // 父表格审批 @@ -886,7 +971,7 @@ const parentTableApprove = async (e) => { updateDialog.value = true } // 父表格修改 -const parentTableUpdate = async (e) => { +const parentTableUpdate = async (e?: any) => { let id = ref(null) if (e) { id.value = e.instockId @@ -899,7 +984,7 @@ const parentTableUpdate = async (e) => { updateDialog.value = true } // 父表格删除 -const parentTableDelete = async (e) => { +const parentTableDelete = async (e?: any) => { const delList = ref([]) if (e) { delList.value = [e.instockId] @@ -953,7 +1038,20 @@ const addDialogTableCell = () => { } // 新增提交 -const dialogSubmit = () => { +const dialogSubmit = async () => { + // 首先进行表单验证 + if (!dialogFormRef.value) { + ElMessage.error('表单引用未找到'); + return; + } + + try { + await dialogFormRef.value.validate(); + } catch (error) { + ElMessage.error('请填写完整的表单信息'); + return; + } + console.log(dialogtable.value) // 将前端行映射为后端明细字段,并进行基本校验与过滤 const detailList = (dialogtable.value || []) @@ -1027,7 +1125,7 @@ const parentTableInfoSubmit = () =>{ const childrenTableUpdate = async (e) => { const detail = (await getInstockDetail(e.instockDetailId)).data const remaining = Number(detail.instockQty) - Number(detail.printedNum || 0) - if(remaining <= 0){ + if(remaining < 1){ ElMessage.error('无剩余数量可打印') return } @@ -1166,10 +1264,12 @@ const handleAssociatePurchaseOrder = async () => { try { // 使用新的API获取带统计数据的采购订单物料列表 - const res = await getWmsPurchaseOrderDetailWithStatistics({ poNo: order.poNo }); + const res = await getWmsPurchaseOrderDetailWithStatistics({ + poNo: order.poNo + }); dialogtable.value = res.data.map(item => ({ poDId: item.poDId, // 添加采购订单物料主键 - materialId: item.materialId, + materialId: item.materialCode, // 修正字段名 materialCode: item.materialCode, materialName: item.materialName, materialSpe: item.materialSpe, @@ -1181,7 +1281,7 @@ const handleAssociatePurchaseOrder = async () => { deliveryQty: item.deliveryQty, // 保存交付数量用于验证 _showQtyInput: true // 标记显示数字输入框 })); - + ElMessage.success('关联采购订单成功,已加载物料列表及库存信息'); } catch (error) { console.error('获取采购订单物料列表失败:', error); @@ -1222,7 +1322,7 @@ const validateQty = (row, val) => { return; } } - + // 对于其他类型,验证不超过交付数量(如果有) if (row.deliveryQty !== undefined && intVal > row.deliveryQty) { row.instockQty = row.deliveryQty; @@ -1232,13 +1332,79 @@ const validateQty = (row, val) => { } }; -// 确保 computed 定义在脚本开头 const remainingQty = computed(() => { const instock = Number(childrenTableInfoForm.value.instockQty) || 0 const printed = Number(childrenTableInfoForm.value.printedNum) || 0 return Math.max(0, instock - printed) // 添加 Math.max 防护负值 }) +// 分包相关的响应式数据 +const packageQtyList = ref([]) +const packageMode = ref('average') // 分包模式:'average' 或 'custom' +const totalPackageQty = computed(() => { + return packageQtyList.value.reduce((sum, qty) => sum + (Number(qty) || 0), 0) +}) + +// 平均分包的数量列表和总数 +const averagePackageList = ref([]) +const averageTotal = computed(() => { + return averagePackageList.value.reduce((sum, qty) => sum + (Number(qty) || 0), 0) +}) + +// 分包数量变化时的处理函数 +const onSplitPackageCountChange = (count) => { + if (count > 1) { + // 默认使用平均分包模式 + packageMode.value = 'average' + + // 初始化数组 + packageQtyList.value = new Array(count).fill(1) + averagePackageList.value = new Array(count).fill(1) + + // 计算平均分包 + calculateAveragePackage(count) + + // 同时初始化自定义数量为平均值(作为备用) + packageQtyList.value = [...averagePackageList.value] + } else { + packageQtyList.value = [] + averagePackageList.value = [] + packageMode.value = 'average' + } +} + +// 计算平均分包数量 +const calculateAveragePackage = (count) => { + const remaining = remainingQty.value + if (remaining > 0 && count > 0) { + const avgQty = Math.floor(remaining / count) + const remainder = remaining % count + + for (let i = 0; i < count; i++) { + averagePackageList.value[i] = avgQty + (i < remainder ? 1 : 0) + } + } +} + +// 分包模式变化时的处理 +const onPackageModeChange = (mode) => { + if (mode === 'custom') { + // 切换到自定义模式时,使用平均分包的结果作为初始值 + packageQtyList.value = [...averagePackageList.value] + } + // 切换到平均模式时不需要特殊处理,因为平均值已经计算好了 +} + +// 验证总数量是否超出限制 +const validateTotalQty = () => { + const total = totalPackageQty.value + const remaining = remainingQty.value + + if (total > remaining) { + ElMessage.warning(`每包数量总计不能超过剩余数量 ${remaining}`) + } +} + const dialogFormRef = ref(); const dialogFormRules = ref({ warehouseId: [{ required: true, message: '请选择仓库', trigger: 'change' }], @@ -1250,7 +1416,7 @@ const isAddDisabled = computed(() => { }); - diff --git a/src/views/wms/instockRecord/index.vue b/src/views/wms/instockRecord/index.vue index 57f9165..10654a7 100644 --- a/src/views/wms/instockRecord/index.vue +++ b/src/views/wms/instockRecord/index.vue @@ -100,12 +100,12 @@ {{ parseTime(scope.row.updateTime, '{y}-{m}-{d} {h}:{i}:{s}') }} - + - + + diff --git a/src/views/wms/outstockOrderCopy/index.vue b/src/views/wms/outstockOrderCopy/index.vue index 9252f6f..84f2ac7 100644 --- a/src/views/wms/outstockOrderCopy/index.vue +++ b/src/views/wms/outstockOrderCopy/index.vue @@ -287,10 +287,10 @@ - + - + @@ -342,11 +342,11 @@ - +