Files
crm_uiapp/src/utils/scan.ts
2026-05-15 14:13:33 +08:00

90 lines
3.4 KiB
TypeScript

/**
* 功能说明:定义扫码明细的最小结构,统一扫码页里的重复合并计算输入。
* 适用场景:扫码其它入库、扫码其它出库的条码累计逻辑。
*/
export interface ScanItem {
warehouseId: number
productId: number
count: number
orderItemId?: number
batchNo?: string
locationCode?: string
}
/**
* 功能说明:清洗扫码枪输入的条码文本,去掉回车、换行和前后空白。
* 适用场景:扫码枪通过键盘模拟输入后,页面提交前统一清洗条码值。
* @param raw 原始扫码内容
* @return 清洗后的条码字符串
* 注意事项:扫码枪通常会追加回车,不先清洗会导致条码查产品接口无法命中。
*/
export function normalizeScanCode(raw: string): string {
return (raw || '').replace(/[\r\n]/g, '').trim()
}
/**
* 功能说明:把相机扫码结果统一转换成业务可用条码。
* 适用场景:`uni.scanCode` 返回对象后,与扫码枪输入共用同一套处理流程。
* @param result uni-app 扫码返回结果
* @return 清洗后的条码字符串
* 注意事项:扫码取消、空返回或结构变化时,需要安全降级为空字符串,避免页面直接抛错。
*/
export function normalizeCameraScanResult(result?: { result?: string } | null): string {
return normalizeScanCode(result?.result || '')
}
/**
* 功能说明:生成扫码明细的合并键,决定重复扫码时应该累加到哪一行。
* 适用场景:自由扫码模式按“仓库 + 产品”合并,订单约束模式再附加订单行编号。
* @param item 当前明细
* @param withOrderConstraint 是否启用订单约束模式
* @return 合并键字符串
* 注意事项:订单约束场景若不带订单行编号,会把不同订单行的同一产品错误合并。
*/
export function buildScanMergeKey(item: ScanItem, withOrderConstraint = false): string {
const segments = [String(item.warehouseId), String(item.productId)]
// 订单约束扫码时需要把订单明细编号带入合并键,避免不同订单行误合并。
if (withOrderConstraint) {
segments.push(String(item.orderItemId || 0))
segments.push(item.batchNo || '')
segments.push(item.locationCode || '')
}
return segments.join(':')
}
/**
* 功能说明:将一次新的扫码结果合并到现有明细列表中。
* 适用场景:连续扫到同一产品时自动累计数量,减少仓库人员手工修改次数。
* @param items 当前明细列表
* @param scannedItem 新扫码得到的明细
* @param withOrderConstraint 是否启用订单约束模式
* @return 合并后的新明细列表
* 注意事项:这里返回新数组而不是原地修改,避免页面状态更新不稳定。
*/
export function mergeScannedItem(
items: ScanItem[],
scannedItem: ScanItem,
withOrderConstraint = false,
): ScanItem[] {
const targetKey = buildScanMergeKey(scannedItem, withOrderConstraint)
const existedIndex = items.findIndex(item => buildScanMergeKey(item, withOrderConstraint) === targetKey)
if (existedIndex === -1) {
return [...items, scannedItem]
}
return items.map((item, index) => {
if (index !== existedIndex) {
return item
}
// 命中同一合并键时只累计数量,避免把已录入明细拆成多行,影响 PDA 连续扫码效率。
return {
...item,
count: Number(item.count || 0) + Number(scannedItem.count || 0),
}
})
}