diff --git a/inventory-backend/app/api/v1/common/search.py b/inventory-backend/app/api/v1/common/search.py index a765183..a4e1c2b 100644 --- a/inventory-backend/app/api/v1/common/search.py +++ b/inventory-backend/app/api/v1/common/search.py @@ -3,6 +3,8 @@ from flask import jsonify, request from . import common_bp from app.models import MaterialBase from app.models.inbound.buy import StockBuy +from app.models.inbound.semi import StockSemi +from app.models.inbound.product import StockProduct from app.models.bom import BomTable from app.extensions import db @@ -46,31 +48,38 @@ def global_search(): "extra": {"category": b.category or ''} }) - # ── 2. 采购库 (StockBuy) ───────────────────────────────── - # 真实字段: barcode, sku (通过 join 搜索关联的 MaterialBase.name) - stock_conditions = [] - for kw in keywords: - kw_term = f'%{kw}%' - stock_conditions.append( - db.or_( - MaterialBase.name.ilike(kw_term), - StockBuy.barcode.ilike(kw_term), - StockBuy.sku.ilike(kw_term) + # ── 2. 库存三表(采购/半成品/成品):按 SKU/条码/名称命中,显示所在库位 ── + def _append_stock_items(model, type_key, badge): + conds = [] + for kw in keywords: + t = f'%{kw}%' + c = db.or_( + MaterialBase.name.ilike(t), + model.sku.ilike(t), + model.barcode.ilike(t), ) - ) - stocks = StockBuy.query.join(MaterialBase, StockBuy.base_id == MaterialBase.id).filter( - db.and_(*stock_conditions) - ).all() - for s in stocks: - merged_list.append({ - "id": s.base_id, - "stock_id": s.id, - "type": "stock_buy", - "title": s.base.name if s.base else '未知物料', - "subtitle": f"条码: {s.barcode or '无'} | 库存: {s.stock_quantity}", - "badge": "采购库", - "extra": {"barcode": s.barcode or '', "status": s.status or ''} - }) + if hasattr(model, 'serial_number'): + c = db.or_(c, model.serial_number.ilike(t)) + conds.append(c) + rows = (model.query.join(MaterialBase, model.base_id == MaterialBase.id) + .filter(db.and_(*conds)).order_by(model.id.desc()).limit(50).all()) + for s in rows: + merged_list.append({ + "id": s.base_id, + "stock_id": s.id, + "type": type_key, + "title": s.base.name if s.base else '未知物料', + "subtitle": f"SKU: {s.sku or '-'} | 库位: {s.warehouse_location or '-'} | 库存: {s.stock_quantity or 0}", + "badge": badge, + "extra": { + "sku": s.sku or '', "warehouse_location": s.warehouse_location or '', + "stock_id": s.id, "source_table": model.__tablename__, + } + }) + + _append_stock_items(StockBuy, 'stock_buy', '采购库') + _append_stock_items(StockSemi, 'stock_semi', '半成品') + _append_stock_items(StockProduct, 'stock_product', '成品') # ── 3. BOM 配方 (BomTable) ────────────────────────────── # 真实字段: bom_no, version diff --git a/inventory-web/src/views/dashboard/index.vue b/inventory-web/src/views/dashboard/index.vue index f9bb832..aaadc1c 100644 --- a/inventory-web/src/views/dashboard/index.vue +++ b/inventory-web/src/views/dashboard/index.vue @@ -268,6 +268,8 @@ const getBadgeType = (type: string) => { const map: Record = { 'material': 'success', 'stock_buy': 'primary', + 'stock_semi': 'warning', + 'stock_product': 'info', 'bom': 'warning' } return map[type] || 'info' @@ -313,6 +315,14 @@ const handleSearchSelect = (item: any) => { path: '/bom', query: { keyword: item.title } }) + } else if (item.type === 'stock_semi' || item.type === 'stock_product' || item.type === 'stock_buy') { + // 库存命中:弹出该条记录的库位,便于快速定位(采购库仍保留跳库存页) + const loc = item.extra?.warehouse_location || '-' + if (item.type === 'stock_buy') { + router.push({ path: '/inventory/buy', query: { keyword: item.title } }) + } else { + ElMessage.success(`【${item.title}】库位:${loc}`) + } } }