export const ITEM_STATUS = Object.freeze({ PENDING: 'pending', PICKED: 'picked', PARTIAL: 'partial', SKIPPED: 'skipped' }) export function createItemStates(items) { return items.reduce((states, item) => { states[item.id] = ITEM_STATUS.PENDING return states }, {}) } export function getPickSummary(items, states, partialQuantities = {}) { const summary = { total: items.length, picked: 0, partial: 0, skipped: 0, pending: 0 } items.forEach((item) => { const status = states[item.id] || ITEM_STATUS.PENDING const quantity = Math.max(1, Number(item.qty || 1)) summary.total += quantity - 1 summary[status] += status === ITEM_STATUS.PARTIAL ? Math.max(0, Number(partialQuantities[item.id] || 0)) : quantity }) summary.processed = summary.picked + summary.partial + summary.skipped summary.progress = summary.total ? Math.round(summary.processed / summary.total * 100) : 0 summary.canSubmit = summary.total > 0 && ( summary.pending === 0 || summary.picked > 0 || summary.partial > 0 ) summary.buttonText = '提交拣货完成' return summary } export function submitStates(items, states) { const nextStates = { ...states } const autoSkippedIds = [] items.forEach((item) => { const status = nextStates[item.id] || ITEM_STATUS.PENDING if (status === ITEM_STATUS.PENDING) { nextStates[item.id] = ITEM_STATUS.SKIPPED autoSkippedIds.push(item.id) } }) return { states: nextStates, autoSkippedIds } } export function classifyScan(items, states, scanCode, scannedBoxCodes = {}) { const item = items.find((entry) => (entry.boxCodes || []).includes(scanCode)) || null if (!item) return { type: 'unknown', item: null } if (scannedBoxCodes[scanCode]) return { type: 'processed', item, status: states[item.id] || ITEM_STATUS.PARTIAL } const status = states[item.id] || ITEM_STATUS.PENDING if (status !== ITEM_STATUS.PICKED && status !== ITEM_STATUS.SKIPPED) return { type: 'pending', item } return { type: 'processed', item, status } }