fix(stocktake): 盘库扫码改为精确匹配,修复漏匹配与性能问题
问题:
1. 准确性 bug: 前端用 getStockList({pageSize:10, keyword}) 模糊搜索 + find()
当 SKU 前缀相同、目标不在前10条时,误报'未找到该物料库存'
2. 性能: 每次扫码全表 ilike %x% 搜索 3 张表,不走索引
修复:
- 后端 get_stock_info 改为精确匹配(==)优先,未命中再回退模糊搜索
- 新增 GET /inbound/stock/scan 扫码精确匹配接口,返回唯一命中
- 前端 onScanSuccess/handleManualInput 改用 scanStockByBarcode
一次请求直接命中,不再依赖 pageSize:10 + find()
This commit is contained in:
@ -19,6 +19,15 @@ export function getStockList(params: { page?: number; pageSize?: number; keyword
|
||||
})
|
||||
}
|
||||
|
||||
// 扫码精确匹配库存(盘库/出库/借库通用,替代模糊搜索漏匹配问题)
|
||||
export function scanStockByBarcode(barcode: string) {
|
||||
return request({
|
||||
url: '/v1/inbound/stock/scan',
|
||||
method: 'get',
|
||||
params: { barcode }
|
||||
})
|
||||
}
|
||||
|
||||
// 打印出库选单
|
||||
// 修改后: 去掉开头的 /api
|
||||
export function printSelectionList(items: any[]) {
|
||||
|
||||
@ -413,7 +413,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted, onUnmounted, nextTick } from 'vue'
|
||||
import { getStockList, getAllStocktakeItems, getDraftMergedList, updateStocktakeQuantity } from '@/api/inbound/stock'
|
||||
import { getAllStocktakeItems, getDraftMergedList, updateStocktakeQuantity, scanStockByBarcode } from '@/api/inbound/stock'
|
||||
import QrScanner from '@/components/QrScanner/index.vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { Search, VideoPlay, VideoPause, List, Checked, Download, ArrowRight, Cloudy, Edit, EditPen, CameraFilled, Close, WarningFilled } from '@element-plus/icons-vue'
|
||||
@ -736,58 +736,51 @@ const onScanSuccess = async (code: string) => {
|
||||
return
|
||||
}
|
||||
|
||||
// 实时查询后端匹配
|
||||
// ★ 精确匹配查询后端(替代 pageSize:10 模糊搜索 + find(),避免漏匹配)
|
||||
loading.value = true
|
||||
try {
|
||||
const res: any = await getStockList({
|
||||
page: 1,
|
||||
pageSize: 10,
|
||||
keyword: trimCode
|
||||
})
|
||||
const res: any = await scanStockByBarcode(trimCode)
|
||||
|
||||
if (!res || !res.data || !res.data.list || res.data.list.length === 0) {
|
||||
ElMessage.error(`未找到该物料库存: ${trimCode}`)
|
||||
if (navigator.vibrate) navigator.vibrate([200, 50, 200])
|
||||
return
|
||||
}
|
||||
|
||||
// 查找匹配的物料
|
||||
const foundItem = res.data.list.find((i: any) =>
|
||||
i.uuid === trimCode || i.sku === trimCode || i.barcode === trimCode || i.bar_code === trimCode
|
||||
)
|
||||
|
||||
if (!foundItem) {
|
||||
if (!res || !res.data) {
|
||||
ElMessage.error(`未找到该物料库存: ${trimCode}`)
|
||||
if (navigator.vibrate) navigator.vibrate([200, 50, 200])
|
||||
return
|
||||
}
|
||||
|
||||
const foundItem = res.data
|
||||
if (navigator.vibrate) navigator.vibrate(100)
|
||||
|
||||
// 关闭全屏扫码,弹出填数对话框
|
||||
showCamera.value = false
|
||||
|
||||
// 处理数据格式
|
||||
// 处理数据格式(后端已返回 source_table / stock_id / name / standard)
|
||||
const stock = parseFloat(foundItem.stock_quantity || foundItem.qty_stock || 0)
|
||||
const type = foundItem.stock_type || foundItem.type || 'material'
|
||||
const sourceTable = foundItem.source_table || typeToSourceTable(type)
|
||||
const stockId = foundItem.stock_id || foundItem.id
|
||||
const item: StockItem = {
|
||||
...foundItem,
|
||||
name: foundItem.name || foundItem.material_name || foundItem.product_name || '未知物品',
|
||||
standard: foundItem.spec_model || foundItem.standard || foundItem.model || '',
|
||||
standard: foundItem.standard || foundItem.spec_model || foundItem.model || '',
|
||||
sku: foundItem.sku || '',
|
||||
uuid: foundItem.uuid || foundItem.sku || '',
|
||||
bar_code: foundItem.bar_code || foundItem.barcode || '',
|
||||
qty_stock: stock,
|
||||
qty_actual: 1,
|
||||
scanned: true,
|
||||
uniqueKey: `${type}_${foundItem.id}`,
|
||||
source_table: typeToSourceTable(type),
|
||||
stock_id: foundItem.id
|
||||
uniqueKey: `${type}_${stockId}`,
|
||||
source_table: sourceTable,
|
||||
stock_id: stockId
|
||||
}
|
||||
|
||||
openQtyDialog(item)
|
||||
} catch (e) {
|
||||
ElMessage.error('查询库存失败')
|
||||
} catch (e: any) {
|
||||
const msg = e?.msg || e?.message || '查询库存失败'
|
||||
if (msg.includes('未找到')) {
|
||||
ElMessage.error(`未找到该物料库存: ${trimCode}`)
|
||||
} else {
|
||||
ElMessage.error(msg)
|
||||
}
|
||||
console.error(e)
|
||||
} finally {
|
||||
loading.value = false
|
||||
@ -820,48 +813,44 @@ const handleManualInput = async () => {
|
||||
|
||||
loading.value = true
|
||||
try {
|
||||
const res: any = await getStockList({
|
||||
page: 1,
|
||||
pageSize: 10,
|
||||
keyword: code
|
||||
})
|
||||
// ★ 精确匹配查询后端(替代 pageSize:10 模糊搜索 + find())
|
||||
const res: any = await scanStockByBarcode(code)
|
||||
|
||||
if (!res || !res.data || !res.data.list || res.data.list.length === 0) {
|
||||
ElMessage.error(`未找到该物料库存: ${code}`)
|
||||
return
|
||||
}
|
||||
|
||||
const foundItem = res.data.list.find((i: any) =>
|
||||
i.uuid === code || i.sku === code || i.barcode === code || i.bar_code === code
|
||||
)
|
||||
|
||||
if (!foundItem) {
|
||||
if (!res || !res.data) {
|
||||
ElMessage.error(`未找到该物料库存: ${code}`)
|
||||
return
|
||||
}
|
||||
|
||||
const foundItem = res.data
|
||||
if (navigator.vibrate) navigator.vibrate(100)
|
||||
|
||||
const stock = parseFloat(foundItem.stock_quantity || foundItem.qty_stock || 0)
|
||||
const type = foundItem.stock_type || foundItem.type || 'material'
|
||||
const sourceTable = foundItem.source_table || typeToSourceTable(type)
|
||||
const stockId = foundItem.stock_id || foundItem.id
|
||||
const item: StockItem = {
|
||||
...foundItem,
|
||||
name: foundItem.name || foundItem.material_name || foundItem.product_name || '未知物品',
|
||||
standard: foundItem.spec_model || foundItem.standard || foundItem.model || '',
|
||||
standard: foundItem.standard || foundItem.spec_model || foundItem.model || '',
|
||||
sku: foundItem.sku || '',
|
||||
uuid: foundItem.uuid || foundItem.sku || '',
|
||||
bar_code: foundItem.bar_code || foundItem.barcode || '',
|
||||
qty_stock: stock,
|
||||
qty_actual: 1,
|
||||
scanned: true,
|
||||
uniqueKey: `${type}_${foundItem.id}`,
|
||||
source_table: typeToSourceTable(type),
|
||||
stock_id: foundItem.id
|
||||
uniqueKey: `${type}_${stockId}`,
|
||||
source_table: sourceTable,
|
||||
stock_id: stockId
|
||||
}
|
||||
|
||||
openQtyDialog(item)
|
||||
} catch (e) {
|
||||
ElMessage.error('查询库存失败')
|
||||
} catch (e: any) {
|
||||
const msg = e?.msg || e?.message || '查询库存失败'
|
||||
if (msg.includes('未找到')) {
|
||||
ElMessage.error(`未找到该物料库存: ${code}`)
|
||||
} else {
|
||||
ElMessage.error(msg)
|
||||
}
|
||||
console.error(e)
|
||||
} finally {
|
||||
loading.value = false
|
||||
|
||||
Reference in New Issue
Block a user