/** * 加工进仓单常量与数据工具 * * 真实接口请求统一注册在 src/common/http.api.js 的 vm.$u.api.fpmProcessInOrder 下。 */ import dayjs from 'dayjs'; export const AUDIT_STATUS = { PENDING: 1, APPROVED: 2, REJECTED: 3, VOIDED: 4, }; export const DRAFT_AUDIT_STATUS = 0; export const DRAFT_AUDIT_STATUS_NAME = '待保存'; export const AUDIT_STATUS_MAP = { 1: '待审核', 2: '已审核', 3: '已驳回', 4: '已作废', }; /** 操作类型:1录入 3删除 */ export const ARRANGE_TYPE = { IN: 1, DEL: 3, }; /** 入仓类型:加工进仓单 */ export const IN_ORDER_TYPE_PROCESS = 5; /** 入仓类型:返修进仓 */ export const IN_ORDER_TYPE_REPAIR = 6; export const IN_ORDER_TYPE_MAP = { [IN_ORDER_TYPE_PROCESS]: '加工进仓单', [IN_ORDER_TYPE_REPAIR]: '返修进仓', }; export const IN_ORDER_TYPE_OPTIONS = [ { value: IN_ORDER_TYPE_PROCESS, label: IN_ORDER_TYPE_MAP[IN_ORDER_TYPE_PROCESS] }, { value: IN_ORDER_TYPE_REPAIR, label: IN_ORDER_TYPE_MAP[IN_ORDER_TYPE_REPAIR] }, ]; /** 默认纸筒重量(公斤,表单展示值) */ export const DEFAULT_PAPER_TUBE_WEIGHT = 1.5; /** 默认包装重量(公斤,表单展示值) */ export const DEFAULT_PACKAGE_WEIGHT = 0.3; /** 往来单位类型:加工单位 */ export const BUSINESS_UNIT_TYPE_PROCESS = 12; /** 成品物理仓类型 */ export const WAREHOUSE_TYPE_FINISHED = 103; /** 默认仓库名称 */ export const DEFAULT_WAREHOUSE_NAME = '成品仓'; export const LIST_PAGE_SIZE = 100; export const STATUS_ACTION_CONFIG = { approve: { status: AUDIT_STATUS.APPROVED, msg: '确认审核该单据?', apiKey: 'statusPass' }, void: { status: AUDIT_STATUS.VOIDED, msg: '确认作废该单据?', apiKey: 'statusCancel' }, unapprove: { status: AUDIT_STATUS.PENDING, msg: '确认消审该单据?', apiKey: 'statusWait' }, }; export function getStatusOptions() { return Object.keys(AUDIT_STATUS_MAP).map((value) => ({ value, label: AUDIT_STATUS_MAP[value], })); } export function mapToSelectOptions(data) { const list = Array.isArray(data) ? data : (data && (data.list || data.items || data.records)) || []; return list.map((item) => ({ value: item.id, label: item.name || item.label || item.code || String(item.id), })); } /** 匹数:后端 ×100 存储 */ export function formatRoll(value) { const n = Number(value || 0) / 100; return Number.isInteger(n) ? n : Number(n.toFixed(2)); } /** 数量(公斤):后端 ×10000 存储 */ export function formatWeightKg(value) { const n = Number(value || 0) / 10000; return Number(n.toFixed(2)); } /** 公斤展示值转后端存储(×10000) */ export function toWeightStorage(value) { return Math.round(Number(value || 0) * 10000); } export function normalizeOrder(order) { if (!order) return null; return { id: order.id, order_no: order.order_no || '', audit_status: order.audit_status, audit_status_name: order.audit_status_name || AUDIT_STATUS_MAP[order.audit_status] || '', process_unit_id: order.process_unit_id || '', process_name: order.process_name || '', warehouse_id: order.warehouse_id || '', warehouse_name: order.warehouse_name || '', sale_system_id: order.sale_system_id || '', sale_system_name: order.sale_system_name || '', in_order_type: order.in_order_type || IN_ORDER_TYPE_PROCESS, in_order_type_name: order.in_order_type_name || IN_ORDER_TYPE_MAP[order.in_order_type] || IN_ORDER_TYPE_MAP[IN_ORDER_TYPE_PROCESS], paper_tube_weight: formatWeightKg(order.paper_tube_weight), package_weight: formatWeightKg(order.package_weight), remark: order.remark || '', warehouse_in_time: (order.warehouse_in_time || '').slice(0, 10), creator_name: order.creator_name || '', create_time: order.create_time || '', auditor_name: order.auditor_name || '', audit_time: order.audit_time || '', total_roll: formatRoll(order.total_roll), total_weight: formatWeightKg(order.total_weight), total_length: formatRoll(order.total_length), item_data: (order.item_data || []).map(normalizeItem), _raw: order, }; } export function normalizeFineCode(fc) { if (!fc) return null; const weightRaw = fc.base_unit_weight != null ? fc.base_unit_weight : (fc.settle_weight != null ? fc.settle_weight : fc.weight); const qrCode = fc.qr_code || fc.long_code || ''; const barCode = fc.bar_code || fc.digital_code || fc.short_code || ''; return { id: fc.id, volume_number: fc.volume_number != null && fc.volume_number !== '' ? String(fc.volume_number) : '', roll: formatRoll(fc.roll), weight: formatWeightKg(weightRaw), bar_code: barCode, qr_code: qrCode, digital_code: fc.digital_code || '', long_code: fc.long_code || '', short_code: fc.short_code || '', dye_factory_dyelot_number: fc.dye_factory_dyelot_number || fc.dyelot_number || '', warehouse_bin_name: fc.warehouse_bin_name || '', shelf_no: fc.shelf_no || '', scan_code: qrCode || barCode || '', paper_tube_weight: fc.paper_tube_weight != null && fc.paper_tube_weight !== '' ? formatWeightKg(fc.paper_tube_weight) : null, package_weight: fc.package_weight != null && fc.package_weight !== '' ? formatWeightKg(fc.package_weight) : null, }; } export function normalizeItem(item) { return { id: item.id, quote_order_no: item.quote_order_no || '', product_code: item.product_code || '', product_name: item.product_name || '', product_color_code: item.product_color_code || '', product_color_name: item.product_color_name || '', dye_factory_dyelot_number: item.dye_factory_dyelot_number || '', dye_factory_color_code: item.dye_factory_color_code || '', in_roll: formatRoll(item.in_roll), in_weight: formatWeightKg(item.in_weight), item_fc_data: (item.item_fc_data || []).map(normalizeFineCode).filter(Boolean), }; } /** * 明细分组:成品编号 → 成品色号 → 细码 */ export function buildItemGroups(items) { const productMap = new Map(); (items || []).forEach((item) => { const productKey = item.product_code || '-'; if (!productMap.has(productKey)) { productMap.set(productKey, { group_key: `p:${productKey}`, product_code: item.product_code || '', product_name: item.product_name || '', in_roll: 0, in_weight: 0, colors: new Map(), }); } const productGroup = productMap.get(productKey); if (!productGroup.product_name && item.product_name) { productGroup.product_name = item.product_name; } const colorKey = item.product_color_code || item.product_color_name || '-'; if (!productGroup.colors.has(colorKey)) { productGroup.colors.set(colorKey, { group_key: `p:${productKey}|c:${colorKey}`, product_color_code: item.product_color_code || '', product_color_name: item.product_color_name || '', quote_order_no: item.quote_order_no || '', dye_factory_dyelot_number: item.dye_factory_dyelot_number || '', in_roll: 0, in_weight: 0, fine_codes: [], }); } const colorGroup = productGroup.colors.get(colorKey); productGroup.in_roll = Number((productGroup.in_roll + Number(item.in_roll || 0)).toFixed(2)); productGroup.in_weight = Number((productGroup.in_weight + Number(item.in_weight || 0)).toFixed(2)); colorGroup.in_roll = Number((colorGroup.in_roll + Number(item.in_roll || 0)).toFixed(2)); colorGroup.in_weight = Number((colorGroup.in_weight + Number(item.in_weight || 0)).toFixed(2)); if (item.quote_order_no) colorGroup.quote_order_no = item.quote_order_no; if (item.dye_factory_dyelot_number) { colorGroup.dye_factory_dyelot_number = item.dye_factory_dyelot_number; } if (!colorGroup.product_color_name && item.product_color_name) { colorGroup.product_color_name = item.product_color_name; } colorGroup.fine_codes.push(...(item.item_fc_data || [])); }); return Array.from(productMap.values()).map((product) => ({ group_key: product.group_key, product_code: product.product_code, product_name: product.product_name, in_roll: product.in_roll, in_weight: product.in_weight, colors: Array.from(product.colors.values()), })); } export function getEmptyScanDetail() { return { quote_order_no: '', dyelot_number: '', volume_number: '', product_code: '', product_color_code: '', order_roll: 0, item_roll: 0, order_weight: 0, item_weight: 0, }; } /** 刚扫细码的数量(公斤存储值):优先细码 weight */ function pickScannedFineWeight(res) { if (!res) return 0; if (res.weight != null && res.weight !== '') return res.weight; if (res.base_unit_weight != null && res.base_unit_weight !== '') return res.base_unit_weight; if (res.settle_weight != null && res.settle_weight !== '') return res.settle_weight; if (res.actually_weight != null && res.actually_weight !== '') return res.actually_weight; return res.item_weight; } /** 从扫码接口返回构建详情区(匹数÷100,数量÷10000) */ export function buildScanDetailFromScanResponse(res) { if (!res) return getEmptyScanDetail(); return { quote_order_no: res.quote_order_no || '', dyelot_number: res.dyelot_number || '', volume_number: res.volume_number != null && res.volume_number !== '' ? String(res.volume_number) : '', product_code: res.product_code || '', product_color_code: res.product_color_code || '', order_roll: formatRoll(res.order_roll != null ? res.order_roll : res.total_roll), item_roll: formatRoll(res.item_roll != null ? res.item_roll : res.roll), order_weight: formatWeightKg(res.order_weight != null ? res.order_weight : res.total_weight), // 本行数量:刚扫这条细码的重量(weight),不是明细行合计 item_weight: formatWeightKg(pickScannedFineWeight(res)), }; } /** 校验纸筒/包装重量(扫码时提交) */ export function validateScanWeights(paperTubeWeight, packageWeight) { if (paperTubeWeight === '' || paperTubeWeight == null) { return '请输入纸筒重量'; } if (Number.isNaN(Number(paperTubeWeight))) return '纸筒重量格式不正确'; if (packageWeight === '' || packageWeight == null) { return '请输入包装重量'; } if (Number.isNaN(Number(packageWeight))) return '包装重量格式不正确'; return ''; } /** 构建扫码请求参数(纸筒/包装重量在扫码时提交,公斤值需 ×10000) */ export function buildScanUpdateParams({ id, scanCode, arrangeType, warehouseBinId, paperTubeWeight, packageWeight, }) { const code = (scanCode || '').trim(); const params = { id: Number(id), arrange_type: arrangeType, paper_tube_weight: toWeightStorage(paperTubeWeight), package_weight: toWeightStorage(packageWeight), }; if (warehouseBinId) { params.warehouse_bin_id = Number(warehouseBinId); } // 长度大于25走二维码,否则走条码 if (code.length > 25) { params.qr_code = code; } else { params.bar_code = code; } return params; } export function buildStatusParam(id) { return { id: String(id) }; } export function formatDisplayTime(value, format = 'YYYY-MM-DD') { if (!value) return ''; const parsed = dayjs(value); return parsed.isValid() ? parsed.format(format) : String(value).slice(0, 10); } export function canScanAtStatus(status) { return [AUDIT_STATUS.PENDING, AUDIT_STATUS.REJECTED].includes(status); } export function isLockedOrderStatus(status) { return [AUDIT_STATUS.APPROVED, AUDIT_STATUS.VOIDED].includes(status); } export function fetchAllOrderList(listFn, params = {}, pageSize = LIST_PAGE_SIZE) { const pickBatch = (res) => { if (Array.isArray(res)) return res; if (!res || typeof res !== 'object') return []; return res.list || res.records || res.items || []; }; const loadPage = (page, acc) => listFn({ ...params, page, size: pageSize }) .then((res) => { const batch = pickBatch(res); if (!batch.length) return acc; // 一次返回超过 pageSize:后端忽略分页,视为全量,避免死循环翻页 if (batch.length > pageSize) return acc.concat(batch); // 翻页后与首页首条相同:后端忽略 page,避免死循环 if ( page > 1 && acc.length && batch[0] && acc[0] && String(batch[0].id) === String(acc[0].id) ) { return acc; } const merged = acc.concat(batch); const total = !Array.isArray(res) && res != null ? Number(res.total) : NaN; if (!Number.isNaN(total) && merged.length >= total) return merged; if (batch.length < pageSize) return merged; return loadPage(page + 1, merged); }); return loadPage(1, []); } export function getFormStatusActionButtons(headerSaved, orderId, status) { if (!headerSaved || !orderId || !canScanAtStatus(status)) return []; return [ { label: '审核', action: 'approve' }, { label: '作废', action: 'void' }, ]; } export function getViewStatusActionButtons(status) { if (status === AUDIT_STATUS.PENDING || status === AUDIT_STATUS.REJECTED) { return [ { label: '编辑', action: 'edit' }, { label: '审核', action: 'approve' }, { label: '作废', action: 'void' }, ]; } if (status === AUDIT_STATUS.APPROVED) { return [{ label: '消审', action: 'unapprove' }]; } return []; } export function orderToFormFields(order) { return { order_no: order.order_no, process_unit_id: order.process_unit_id, process_name: order.process_name, warehouse_id: order.warehouse_id, warehouse_name: order.warehouse_name, sale_system_id: order.sale_system_id, sale_system_name: order.sale_system_name, in_order_type: order.in_order_type || IN_ORDER_TYPE_PROCESS, in_order_type_name: order.in_order_type_name || IN_ORDER_TYPE_MAP[order.in_order_type] || IN_ORDER_TYPE_MAP[IN_ORDER_TYPE_PROCESS], paper_tube_weight: String(DEFAULT_PAPER_TUBE_WEIGHT), package_weight: String(DEFAULT_PACKAGE_WEIGHT), remark: order.remark, item_data: order.item_data, }; } /** 从仓库下拉中选出默认成品仓 */ export function pickDefaultWarehouse(options, loginWarehouseId, loginWarehouseName) { const list = options || []; const byName = list.find((item) => item.label === DEFAULT_WAREHOUSE_NAME); if (byName) return byName; if (loginWarehouseId) { const byId = list.find((item) => String(item.value) === String(loginWarehouseId)); if (byId) return byId; if (loginWarehouseName) { return { value: loginWarehouseId, label: loginWarehouseName }; } } return list[0] || null; } /** * 确认并执行审核状态变更 */ export function confirmOrderStatusAction(vm, { orderId, action, onSuccess }) { const cfg = STATUS_ACTION_CONFIG[action]; if (!cfg || !orderId) return; const api = vm.$u.api.fpmProcessInOrder; const requestFn = api[cfg.apiKey]; if (typeof requestFn !== 'function') return; uni.showModal({ title: '提示', content: cfg.msg, success: (res) => { if (!res.confirm) return; uni.showLoading({ title: '处理中...' }); requestFn(buildStatusParam(orderId)) .then(() => { if (typeof onSuccess === 'function') return onSuccess(); uni.hideLoading(); }) .catch((e) => { uni.hideLoading(); if (vm.showError) vm.showError(e.message || '操作失败'); }); }, }); }