diff --git a/src/api/erp/stock/check/index.ts b/src/api/erp/stock/check/index.ts index 9de3a893..79482fb9 100644 --- a/src/api/erp/stock/check/index.ts +++ b/src/api/erp/stock/check/index.ts @@ -6,9 +6,11 @@ export interface StockCheckVO { no: string // 盘点单号 checkTime: Date | string // 盘点时间 sourceType?: number | string // 生成来源类型:1-按库存,2-按产品 + categoryType?: number | string // 分类 totalCount: number // 合计数量 totalPrice: number // 合计金额,单位:元 status: number // 状态 + checkStatus?: number | string // 盘点状态:0-未盘点,1-已盘点 auditUserId?: number // 审核人编号 auditUserName?: string // 审核人名称 remark?: string // 备注 @@ -95,6 +97,16 @@ export const StockCheckApi = { }) }, + // 提交库存盘点单 + submitStockCheck: async (data: { id: number; auditUserId?: number; remark?: string }) => { + return await request.put({ url: `/erp/stock-check/submit`, data }) + }, + + // 审核库存盘点单 + auditStockCheck: async (data: { id: number; status: number; remark?: string }) => { + return await request.put({ url: `/erp/stock-check/audit`, data }) + }, + // 删除库存盘点单 deleteStockCheck: async (ids: number[]) => { return await request.delete({ diff --git a/src/api/erp/stock/pallet/index.ts b/src/api/erp/stock/pallet/index.ts new file mode 100644 index 00000000..7bc31c2b --- /dev/null +++ b/src/api/erp/stock/pallet/index.ts @@ -0,0 +1,40 @@ +import request from '@/config/axios' + +export interface PalletVO { + id?: number + code?: string + isCode?: boolean + palletType?: number | string + specification?: string + ratedLoadWeight?: number | string + unit?: string + status?: number | string + warehouseId?: number | string + areaId?: number | string + planCode?: string + productId?: number | string + productCount?: number | string + qrcode?: string + purchaseDate?: string + useDate?: string + remark?: string + createTime?: string +} + +export const PalletApi = { + getPalletPage: async (params: any) => { + return await request.get({ url: `/erp/pallet/page`, params }) + }, + + createPallet: async (data: PalletVO) => { + return await request.post({ url: `/erp/pallet/create`, data }) + }, + + updatePallet: async (params: PalletVO) => { + return await request.put({ url: `/erp/pallet/update`, params }) + }, + + deletePallet: async (id: number) => { + return await request.delete({ url: `/erp/pallet/delete?id=` + id }) + } +} diff --git a/src/api/mes/task/index.ts b/src/api/mes/task/index.ts index 1fdc8407..4770783b 100644 --- a/src/api/mes/task/index.ts +++ b/src/api/mes/task/index.ts @@ -118,6 +118,11 @@ export const TaskApi = { return await request.get({ url: `/mes/task/task-detail/summary?taskId=` + taskId }) }, + // 获取生产任务单默认包装方案 + getTaskDefaultPackagingSchemes: async (taskId: number) => { + return await request.get({ url: `/mes/task/task-detail/default-packaging-schemes`, params: { taskId } }) + }, + // 获得可查询计划的生产任务单列表 getTaskList: async () => { return await request.get({ url: `/mes/task/getTaskList`}) diff --git a/src/locales/en.ts b/src/locales/en.ts index 0d66d18f..c1f74466 100644 --- a/src/locales/en.ts +++ b/src/locales/en.ts @@ -345,6 +345,67 @@ validatorAllowBatchMixRequired: 'Allow batch mix is required', validatorStatusRequired: 'Status is required' }, + Overview: { + materialCategory: 'Material Category', + location: 'Location', + dateRange: 'Date Range', + stockDetail: 'Stock Detail', + recentRecord: 'Recent Stock Records', + more: 'More', + time: 'Time', + material: 'Material', + latestChangeTime: 'Latest Change Time', + stockIn: 'Inbound', + stockOut: 'Outbound', + cards: { + finishedGoods: { + title: 'Finished Goods Stock', + line1: 'SKU: 36', + line2: 'Stock Summary: 128 pallets 42 packs 560 pcs', + line3: 'Completed Inbound Today: 12 pallets 8 packs', + tip: 'Converted by product packaging scheme' + }, + rawMaterial: { + title: 'Raw Material Stock', + line1: 'Materials: 24 types', + line2: 'Weight: 18.6 tons', + line3: 'Liquid: 1,250 L', + line4: 'Pack/Box: 86 drums / 320 packs', + tip: 'Summarized by material measurement mode' + }, + sparePart: { + title: 'Spare Parts Stock', + line1: 'Spare Parts: 128 types', + line2: 'Low Stock: 8 items', + line3: 'Common Parts: 36 items', + line4: 'Sample Stock: cable ties 9 packs 70 pcs', + tip: 'Stock is stored by minimum unit with auxiliary conversion' + }, + todayIn: { + title: 'Inbound Today', + line1: 'Inbound Orders: 18', + line2: 'Detail Lines: 46', + line3: 'Finished Goods: 12 pallets 8 packs', + line4: 'Raw Materials: 3 pallets / 1.2 tons', + line5: 'Spare Parts: 6 packs / 120 pcs' + }, + todayOut: { + title: 'Outbound Today', + line1: 'Outbound Orders: 15', + line2: 'Detail Lines: 38', + line3: 'Raw Material Issue: 820 kg', + line4: 'Spare Parts Issue: 45 pcs', + line5: 'Finished Goods Shipment: 6 pallets 20 packs' + }, + warning: { + title: 'Stock Alerts', + line1: 'Alerts: 18', + line2: 'Raw Materials: 5', + line3: 'Spare Parts: 10', + line4: 'Finished Goods: 3' + } + } + }, Stock: { product: 'Product', warehouse: 'Warehouse', @@ -499,11 +560,27 @@ purchaseUnitConvertQuantity: 'Purchase Convert Qty', defaultSupplier: 'Supplier (Default)', outboundPurpose: 'Outbound Purpose', + outMode: 'Outbound Mode', + outModeWholePallet: 'Whole Pallet', + outModeSplitPallet: 'Split Pallet', relatedOrder: 'Related Order', relatedRepairOrder: 'Related Repair Order', relatedMaintainRecord: 'Related Maintenance Record', + relatedTask: 'Related Task', + taskOrder: 'Task Order', + palletCode: 'Pallet Code', + availablePallets: 'Available Pallets', + selectedPallets: 'Selected Pallets', + packageCount: 'Package Count', + itemCount: 'Item Count', + productInfo: 'Product Info', + productName: 'Product Name', + packagingScheme: 'Packaging Scheme', + packageItemCount: 'Package Item Count', selectRelatedRepairOrder: 'Select Repair Order', selectRelatedMaintainRecord: 'Select Maintenance Record', + selectTaskOrder: 'Select Task Order', + selectPalletCode: 'Select Pallet Code', inputUnitType: 'Unit Input Type', inputCount: 'Purchase Unit Quantity', count: 'Quantity', @@ -511,6 +588,8 @@ totalPrice: 'Total Price', remark: 'Remark', action: 'Action', + selector: 'Select', + selectProduct: 'Select Product', selectCode: 'Select Code', code: 'Code', name: 'Name', @@ -523,12 +602,19 @@ placeholderOutboundPurpose: 'Please select outbound purpose', placeholderRelatedRepairOrder: 'Please select related repair order', placeholderRelatedMaintainRecord: 'Please select related maintenance record', + placeholderTaskOrder: 'Please select task order', + placeholderPalletCode: 'Please select pallet code', placeholderInputUnitType: 'Please select', placeholderCode: 'Please enter code', placeholderName: 'Please enter name', validatorWarehouseRequired: 'Warehouse is required', validatorAreaRequired: 'Please select area', validatorProductRequired: 'Product is required', + validatorTaskRequired: 'Task order is required', + validatorPalletRequired: 'Pallet code is required', + validatorPackageCountRequired: 'Package count is required and must be greater than 0', + validatorOutboundPurposeRequired: 'Outbound purpose is required', + validatorOutModeRequired: 'Outbound mode is required', validatorCountRequired: 'Quantity is required', stockCountExceededWarning: 'Quantity cannot exceed stock. It has been adjusted to stock quantity.' }, @@ -545,13 +631,25 @@ price: 'Amount', totalPrice: 'Total Price', sourceType: 'Source Type', + categoryType: 'Category', sourceTypeStock: 'By Stock', sourceTypeProduct: 'By Product', area: 'Area', checkItem: 'Check Item', stockCount: 'Stock Quantity', actualCount: 'Actual Count', + differenceCount: 'Difference', inventoryCheck: 'Check', + saveDraft: 'Save Draft', + checkStatus: 'Check Status', + checkStatusUnchecked: 'Unchecked', + checkStatusChecked: 'Checked', + submit: 'Submit', + submitRemark: 'Submit Remark', + auditRemark: 'Audit Remark', + auditUserName: 'Auditor', + auditApprove: 'Pass', + auditReject: 'Reject', materialCategory: 'Material Category', materialSubCategory: 'Material Subcategory', standard: 'Standard', @@ -569,20 +667,30 @@ placeholderCheckItem: 'Please select check item', placeholderProductBarCode: 'Please enter material code', placeholderProductName: 'Please enter material name', + placeholderAuditUser: 'Please select auditor', + placeholderSubmitRemark: 'Please enter submit remark', + placeholderAuditRemark: 'Please enter audit remark', placeholderCreator: 'Please select creator', placeholderStatus: 'Please select status', placeholderRemark: 'Please enter remark', placeholderCheckTime: 'Select check time', validatorCheckTimeRequired: 'Check time is required', validatorSourceTypeRequired: 'Please select source type', + validatorCategoryTypeRequired: 'Please select category', validatorSelectWarehouseFirst: 'Please select warehouse first', validatorSelectAreaFirst: 'Please select area first', validatorSelectProductFirst: 'Please select product first', validatorSelectCheckItem: 'Please select check item', + validatorAuditUserRequired: 'Please select auditor', + validatorCompleteCheckInfo: 'Please complete check information first', + confirmActualCountZero: ' actual count is 0. Confirm submit?', confirmApprove: 'Are you sure to approve this check order?', confirmReverseApprove: 'Are you sure to reverse approve this check order?', + submitSuccess: 'Submit success', approveSuccess: 'Approve success', reverseApproveSuccess: 'Reverse approve success', + auditApproveSuccess: 'Pass success', + auditRejectSuccess: 'Reject success', exportName: 'Check Order.xls', list: 'Check Product List', addItem: 'Add Check Product', @@ -693,6 +801,47 @@ validatorPackageQuantityRequired: 'Package quantity is required', validatorPalletPackageQuantityRequired: 'Pallet package quantity is required', validatorStatusRequired: 'Status is required' + }, + Pallet: { + code: 'Pallet Code', + palletType: 'Pallet Type', + specification: 'Specification', + ratedLoadWeight: 'Rated Load', + unit: 'Unit', + status: 'Pallet Status', + warehouseId: 'Warehouse', + areaId: 'Area', + planCode: 'Production Task No.', + productId: 'Product ID', + productCount: 'Product Quantity', + qrcode: 'QR Code', + viewQrcode: 'View QR Code', + qrcodeEmpty: 'No QR code', + qrcodeRefreshConfirm: 'Confirm to refresh this pallet QR code?', + purchaseDate: 'Purchase Date', + useDate: 'Use Date', + remark: 'Remark', + createTime: 'Create Time', + placeholderCode: 'Please enter pallet code', + placeholderPalletType: 'Please enter pallet type', + placeholderSpecification: 'Please enter pallet specification', + placeholderLength: 'Length', + placeholderWidth: 'Width', + placeholderHeight: 'Height', + placeholderRatedLoadWeight: 'Please enter rated load', + placeholderUnit: 'Please enter unit', + placeholderStatus: 'Please select pallet status', + placeholderWarehouseId: 'Please select warehouse', + placeholderAreaId: 'Please select area', + placeholderPlanCode: 'Please enter production task no.', + placeholderProductId: 'Please select product', + placeholderProductCount: 'Please enter product quantity', + placeholderPurchaseDate: 'Please select purchase date', + placeholderUseDate: 'Please select use date', + placeholderRemark: 'Please enter remark', + validatorCodeRequired: 'Pallet code is required', + validatorPalletTypeRequired: 'Pallet type is required', + validatorStatusRequired: 'Pallet status is required' } }, ErpPurchase: { diff --git a/src/locales/zh-CN.ts b/src/locales/zh-CN.ts index 431118c7..bed5862d 100644 --- a/src/locales/zh-CN.ts +++ b/src/locales/zh-CN.ts @@ -345,6 +345,67 @@ validatorAllowBatchMixRequired: '是否允许批次混放不能为空', validatorStatusRequired: '开启状态不能为空' }, + Overview: { + materialCategory: '物料大类', + location: '库位', + dateRange: '日期范围', + stockDetail: '库存明细', + recentRecord: '最近库存流水', + more: '更多', + time: '时间', + material: '物料', + latestChangeTime: '最近变动时间', + stockIn: '入库', + stockOut: '出库', + cards: { + finishedGoods: { + title: '产成品库存', + line1: 'SKU:36', + line2: '库存摘要:128托 42包 560个', + line3: '今日完工入库:12托 8包', + tip: '按产品包装方案换算展示' + }, + rawMaterial: { + title: '原材料库存', + line1: '物料:24种', + line2: '重量类:18.6吨', + line3: '液体类:1,250L', + line4: '包/箱类:86桶 / 320包', + tip: '按物料档案计量方式分别汇总' + }, + sparePart: { + title: '备件库存', + line1: '备件:128种', + line2: '低库存:8项', + line3: '常用件:36项', + line4: '示例库存:扎带 9包70根', + tip: '库存按最小单位保存,页面辅助换算展示' + }, + todayIn: { + title: '今日入库', + line1: '入库单:18张', + line2: '明细行:46行', + line3: '产成品:12托8包', + line4: '原材料:3托 / 1.2吨', + line5: '备件:6包 / 120个' + }, + todayOut: { + title: '今日出库', + line1: '出库单:15张', + line2: '明细行:38行', + line3: '原材料领用:820kg', + line4: '备件领用:45个', + line5: '产成品发货:6托20包' + }, + warning: { + title: '库存预警', + line1: '预警:18条', + line2: '原材料:5', + line3: '备件:10', + line4: '产成品:3' + } + } + }, Stock: { product: '产品', warehouse: '仓库', @@ -499,11 +560,27 @@ purchaseUnitConvertQuantity: '采购换算数量', defaultSupplier: '供应商(默认)', outboundPurpose: '出库用途', + outMode: '出库方式', + outModeWholePallet: '整托出库', + outModeSplitPallet: '拆托出库', relatedOrder: '关联单据', relatedRepairOrder: '关联维修单', relatedMaintainRecord: '关联保养记录', + relatedTask: '关联任务单', + taskOrder: '任务单', + palletCode: '托盘码', + availablePallets: '可选托盘', + selectedPallets: '已选托盘', + packageCount: '包数', + itemCount: '个数', + productInfo: '产品信息', + productName: '产品名称', + packagingScheme: '包装方案', + packageItemCount: '每包个数', selectRelatedRepairOrder: '选择维修单', selectRelatedMaintainRecord: '选择保养记录', + selectTaskOrder: '选择任务单', + selectPalletCode: '选择托盘码', inputUnitType: '单位输入方式', inputCount: '采购单位数量', count: '数量', @@ -511,6 +588,8 @@ totalPrice: '合计金额', remark: '备注', action: '操作', + selector: '选择', + selectProduct: '选择产品', selectCode: '选择编码', code: '编码', name: '名称', @@ -523,12 +602,19 @@ placeholderOutboundPurpose: '请选择出库用途', placeholderRelatedRepairOrder: '请选择关联维修单', placeholderRelatedMaintainRecord: '请选择关联保养记录', + placeholderTaskOrder: '请选择任务单', + placeholderPalletCode: '请选择托盘码', placeholderInputUnitType: '请选择', placeholderCode: '请输入编码', placeholderName: '请输入名称', validatorWarehouseRequired: '仓库不能为空', validatorAreaRequired: '请选择库区', validatorProductRequired: '产品不能为空', + validatorTaskRequired: '任务单不能为空', + validatorPalletRequired: '托盘码不能为空', + validatorPackageCountRequired: '包数不能为空且必须大于0', + validatorOutboundPurposeRequired: '出库用途不能为空', + validatorOutModeRequired: '出库方式不能为空', validatorCountRequired: '产品数量不能为空', stockCountExceededWarning: '数量不能超出库存,已自动调整为库存数量' }, @@ -545,13 +631,25 @@ price: '金额', totalPrice: '合计金额', sourceType: '生成来源', + categoryType: '分类', sourceTypeStock: '按库存', sourceTypeProduct: '按产品', area: '库区', checkItem: '盘点项', stockCount: '库存数量', actualCount: '实盘数量', + differenceCount: '差异', inventoryCheck: '盘点', + saveDraft: '保存草稿', + checkStatus: '盘点状态', + checkStatusUnchecked: '未盘点', + checkStatusChecked: '已盘点', + submit: '提交', + submitRemark: '提交备注', + auditRemark: '审核备注', + auditUserName: '审核人', + auditApprove: '通过', + auditReject: '驳回', materialCategory: '物料大类', materialSubCategory: '物料小类', standard: '规格', @@ -569,20 +667,30 @@ placeholderCheckItem: '请选择盘点项', placeholderProductBarCode: '请输入物料编码', placeholderProductName: '请输入物料名称', + placeholderAuditUser: '请选择审核人', + placeholderSubmitRemark: '请输入提交备注', + placeholderAuditRemark: '请输入审核备注', placeholderCreator: '请选择创建人', placeholderStatus: '请选择状态', placeholderRemark: '请输入备注', placeholderCheckTime: '选择盘点时间', validatorCheckTimeRequired: '盘点时间不能为空', validatorSourceTypeRequired: '请选择生成来源', + validatorCategoryTypeRequired: '请选择分类', validatorSelectWarehouseFirst: '请先选择仓库', validatorSelectAreaFirst: '请先选择库区', validatorSelectProductFirst: '请先选择产品', validatorSelectCheckItem: '请选择盘点项', + validatorAuditUserRequired: '请选择审核人', + validatorCompleteCheckInfo: '请先完善盘点信息', + confirmActualCountZero: '实盘数量为0,确认提交吗?', confirmApprove: '确定审批该盘点单吗?', confirmReverseApprove: '确定反审批该盘点单吗?', + submitSuccess: '提交成功', approveSuccess: '审批成功', reverseApproveSuccess: '反审批成功', + auditApproveSuccess: '通过成功', + auditRejectSuccess: '驳回成功', exportName: '其它盘点单.xls', list: '盘点产品物料清单', addItem: '添加盘点产品', @@ -693,6 +801,47 @@ validatorPackageQuantityRequired: '每包数量不能为空', validatorPalletPackageQuantityRequired: '每托包数不能为空', validatorStatusRequired: '状态不能为空' + }, + Pallet: { + code: '托盘编码', + palletType: '托盘类型', + specification: '规格', + ratedLoadWeight: '额定载重', + unit: '单位', + status: '托盘状态', + warehouseId: '所属仓库', + areaId: '所属库区', + planCode: '生产任务单号', + productId: '产品编号', + productCount: '产品数量', + qrcode: '二维码', + viewQrcode: '查看二维码', + qrcodeEmpty: '暂无二维码', + qrcodeRefreshConfirm: '确认刷新该托盘二维码吗?', + purchaseDate: '采购日期', + useDate: '启用日期', + remark: '备注', + createTime: '创建时间', + placeholderCode: '请输入托盘编码', + placeholderPalletType: '请输入托盘类型', + placeholderSpecification: '请输入托盘规格', + placeholderLength: '长', + placeholderWidth: '宽', + placeholderHeight: '高', + placeholderRatedLoadWeight: '请输入额定载重', + placeholderUnit: '请输入单位', + placeholderStatus: '请选择托盘状态', + placeholderWarehouseId: '请选择所属仓库', + placeholderAreaId: '请选择所属库区', + placeholderPlanCode: '请输入生产任务单号', + placeholderProductId: '请选择产品', + placeholderProductCount: '请输入产品数量', + placeholderPurchaseDate: '请选择采购日期', + placeholderUseDate: '请选择投入使用日期', + placeholderRemark: '请输入备注', + validatorCodeRequired: '托盘编码不能为空', + validatorPalletTypeRequired: '托盘类型不能为空', + validatorStatusRequired: '托盘状态不能为空' } }, ErpPurchase: { diff --git a/src/utils/dict.ts b/src/utils/dict.ts index 427a7797..a6bbdc0c 100644 --- a/src/utils/dict.ts +++ b/src/utils/dict.ts @@ -233,6 +233,8 @@ export enum DICT_TYPE { WAREHOUSE_RECEIVING_STATUS = 'warehouse_receiving_status', // 入库状态 WAREHOUSE_OUTBOUND_STATUS = 'Warehouse_outbound_status', // 出库状态 WAREHOUSE_OUTBOUND_PURPOSE = 'warehouse_outbound_purpose', // 出库用途 + STORAGE_PALLET_TYPES = 'storage_pallet_types', // 仓储托盘类型 + STORAGE_PALLET_STATUS = 'storage_pallet_status', // 仓储托盘状态 SUBMOLD_TYPE = 'submold_type', // 子模具类型 ERP_MAINTAIN_TYPE = 'maintain_type',// ERP 保养类型 diff --git a/src/views/erp/stock/checkExecution/components/StockCheckExecutionForm.vue b/src/views/erp/stock/checkExecution/components/StockCheckExecutionForm.vue index 520fc6a0..2a4f8924 100644 --- a/src/views/erp/stock/checkExecution/components/StockCheckExecutionForm.vue +++ b/src/views/erp/stock/checkExecution/components/StockCheckExecutionForm.vue @@ -14,7 +14,8 @@ :placeholder="t('ErpStock.Check.placeholderCheckTime')" class="!w-1/1" /> - + + {{ t('ErpStock.Check.sourceTypeStock') }} @@ -22,11 +23,25 @@ + + + + + {{ dict.label }} + + + + - + @@ -839,6 +935,10 @@ const resetForm = () => { margin-bottom: 0; } +.stock-check-detail-tabs { + margin-top: 12px; +} + .stock-check-dialog-pagination { padding-top: 12px; padding-bottom: 56px; diff --git a/src/views/erp/stock/checkExecution/index.vue b/src/views/erp/stock/checkExecution/index.vue index fde8217c..97ca0a30 100644 --- a/src/views/erp/stock/checkExecution/index.vue +++ b/src/views/erp/stock/checkExecution/index.vue @@ -97,70 +97,6 @@ @selection-change="handleSelectionChange" > - - - - + + + + - + @@ -257,6 +281,8 @@ import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' import { dateFormatter } from '@/utils/formatTime' import { StockCheckApi, type StockCheckVO } from '@/api/erp/stock/check' import { WarehouseApi, type WarehouseVO } from '@/api/erp/stock/warehouse' +import * as UserApi from '@/api/system/user' +import * as ConfigApi from '@/api/infra/config' import StockCheckExecutionForm from './components/StockCheckExecutionForm.vue' defineOptions({ name: 'ErpStockCheckExecution' }) @@ -269,8 +295,34 @@ const list = ref([]) const total = ref(0) const warehouseList = ref([]) const selectionList = ref([]) +const userList = ref([]) const queryFormRef = ref() const formRef = ref() +const submitFormRef = ref() +const submitDialogVisible = ref(false) +const submitLoading = ref(false) +const submitForm = reactive({ + id: undefined as number | undefined, + auditUserId: undefined as number | undefined, + remark: undefined as string | undefined +}) +const isAuditDisabled = ref(false) +const submitActionText = computed(() => + isAuditDisabled.value ? t('ErpStock.Check.inventoryCheck') : t('ErpStock.Check.submit') +) +const submitRules = computed(() => isAuditDisabled.value ? {} : { + auditUserId: [{ required: true, message: t('ErpStock.Check.validatorAuditUserRequired'), trigger: 'change' }] +}) +const auditDialogVisible = ref(false) +const auditLoading = ref(false) +const auditForm = reactive({ + id: undefined as number | undefined, + status: undefined as number | undefined, + remark: undefined as string | undefined +}) +const auditDialogTitle = computed(() => + auditForm.status === 20 ? t('ErpStock.Check.auditApprove') : t('ErpStock.Check.auditReject') +) const queryParams = reactive({ pageNo: 1, pageSize: 10, @@ -291,6 +343,16 @@ const getList = async () => { } } +const loadAuditConfig = async () => { + try { + const data = await ConfigApi.getConfigPage({ pageNo: 1, pageSize: 10, key: 'inventoryAudit' } as PageParam & { key: string }) + const auditConfig = data?.list?.find((item) => item?.key === 'inventoryAudit') + isAuditDisabled.value = auditConfig?.value === '0' + } catch { + isAuditDisabled.value = false + } +} + const handleQuery = () => { queryParams.pageNo = 1 getList() @@ -322,35 +384,98 @@ const handleSelectionChange = (rows: StockCheckVO[]) => { selectionList.value = rows } +const openSubmitDialog = (row: StockCheckVO) => { + const hasIncompleteItem = (row.items || []).some( + (item) => item.actualCount === undefined || item.actualCount === null || item.actualCount === '' + ) + if (hasIncompleteItem) { + message.warning(t('ErpStock.Check.validatorCompleteCheckInfo')) + return + } + submitForm.id = row.id + submitForm.auditUserId = row.auditUserId + submitForm.remark = undefined + submitDialogVisible.value = true + submitFormRef.value?.clearValidate() +} + +const handleSubmit = async () => { + if (!isAuditDisabled.value) { + await submitFormRef.value.validate() + } + if (!submitForm.id || (!isAuditDisabled.value && !submitForm.auditUserId)) { + return + } + submitLoading.value = true + try { + if (isAuditDisabled.value) { + await StockCheckApi.auditStockCheck({ + id: submitForm.id, + status: 20, + remark: submitForm.remark + }) + message.success(t('ErpStock.Check.auditApproveSuccess')) + submitDialogVisible.value = false + await getList() + return + } + const data: { id: number; auditUserId?: number; remark?: string } = { + id: submitForm.id, + remark: submitForm.remark + } + data.auditUserId = submitForm.auditUserId + await StockCheckApi.submitStockCheck(data) + message.success(t('ErpStock.Check.submitSuccess')) + submitDialogVisible.value = false + await getList() + } finally { + submitLoading.value = false + } +} + +const openAuditDialog = (row: StockCheckVO, status: number) => { + auditForm.id = row.id + auditForm.status = status + auditForm.remark = undefined + auditDialogVisible.value = true +} + +const handleAudit = async () => { + if (!auditForm.id || !auditForm.status) { + return + } + auditLoading.value = true + try { + await StockCheckApi.auditStockCheck({ + id: auditForm.id, + status: auditForm.status, + remark: auditForm.remark + }) + message.success( + auditForm.status === 20 + ? t('ErpStock.Check.auditApproveSuccess') + : t('ErpStock.Check.auditRejectSuccess') + ) + auditDialogVisible.value = false + await getList() + } finally { + auditLoading.value = false + } +} + const getWarehouseNames = (row: StockCheckVO) => { const names = Array.from(new Set((row.items || []).map((item) => item.warehouseName).filter(Boolean))) return names.length ? names.join('、') : '-' } onMounted(async () => { - warehouseList.value = await WarehouseApi.getWarehouseSimpleList() + const [warehouses, users] = await Promise.all([ + WarehouseApi.getWarehouseSimpleList(), + UserApi.getSimpleUserList(), + loadAuditConfig() + ]) + warehouseList.value = warehouses || [] + userList.value = users || [] await getList() }) - - diff --git a/src/views/erp/stock/in/StockInForm.vue b/src/views/erp/stock/in/StockInForm.vue index 812609a5..778f1780 100644 --- a/src/views/erp/stock/in/StockInForm.vue +++ b/src/views/erp/stock/in/StockInForm.vue @@ -285,7 +285,10 @@ const submitForm = async () => { // 提交请求 formLoading.value = true try { - const data = formData.value as unknown as StockInVO + const data = { + ...formData.value, + items: normalizeItemsForSubmit(formData.value.items) + } as unknown as StockInVO if (formType.value === 'create') { await StockInApi.createStockIn(data) message.success(t('common.createSuccess')) @@ -300,6 +303,19 @@ const submitForm = async () => { } } +const normalizeItemsForSubmit = (items: any[] = []) => { + return items.map((item) => { + const { relatedTask, palletId, palletCode, taskCode, taskName, productCode, productUnitName, stockCount, totalPrice, ...rest } = item + const relateTask = item.relateTask === true || item.relateTask === 1 || item.relateTask === '1' + return { + ...rest, + relateTask, + taskId: relateTask ? item.taskId : null, + pallets: Array.isArray(item.pallets) ? item.pallets : [] + } + }) +} + /** 重置表单 */ const resetForm = () => { formData.value = { diff --git a/src/views/erp/stock/in/components/StockInItemForm.vue b/src/views/erp/stock/in/components/StockInItemForm.vue index b2574a5e..4b27c228 100644 --- a/src/views/erp/stock/in/components/StockInItemForm.vue +++ b/src/views/erp/stock/in/components/StockInItemForm.vue @@ -1,7 +1,7 @@ --> - - - - - - - - - - - - - + @@ -168,7 +162,7 @@ + {{ t('ErpStock.In.addItem') }} - + {{ t('common.cancel') }} + + +
+
{{ t('ErpStock.Item.selectTaskOrder') }}
+ + + + + + + {{ t('common.query') }} + + + + + + + + + + + + + + + +
+ +
+
{{ t('ErpStock.Item.selectProduct') }}
+ + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + + + + + + + {{ t('common.query') }} + + + +
+
+
{{ t('ErpStock.Item.availablePallets') }}
+ + + + + + + + + + + +
+ +
+
+
+ + + + + + +
+
+
{{ t('ErpStock.Item.selectedPallets') }}
+ + + + + + + + + + +
+
+ +
+ + diff --git a/src/views/erp/stock/pallet/PalletForm.vue b/src/views/erp/stock/pallet/PalletForm.vue new file mode 100644 index 00000000..83f27307 --- /dev/null +++ b/src/views/erp/stock/pallet/PalletForm.vue @@ -0,0 +1,716 @@ + + + + + diff --git a/src/views/erp/stock/pallet/index.vue b/src/views/erp/stock/pallet/index.vue new file mode 100644 index 00000000..23a5b232 --- /dev/null +++ b/src/views/erp/stock/pallet/index.vue @@ -0,0 +1,223 @@ + + + diff --git a/src/views/mes/task/components/TaskDetailForm.vue b/src/views/mes/task/components/TaskDetailForm.vue index 734b17b1..c2d877a0 100644 --- a/src/views/mes/task/components/TaskDetailForm.vue +++ b/src/views/mes/task/components/TaskDetailForm.vue @@ -210,7 +210,7 @@ const open = async (type: string, id?: number, taskId: number) => { // }, // ] // formData.value.unitId = 5 - productList.value = await ProductApi.getMesProductSimpleList() + productList.value = await ProductApi.getMesProductSimpleList({ categoryType: 1 }) } defineExpose({ open }) // 提供 open 方法,用于打开弹窗