From e08eaff40a7c6806a05697634038894a68362590 Mon Sep 17 00:00:00 2001 From: DXC Date: Tue, 28 Apr 2026 09:23:59 +0800 Subject: [PATCH] =?UTF-8?q?feat(outbound):=20=E5=BA=93=E5=AD=98=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E6=8C=89=E8=A7=84=E6=A0=BC+=E5=BA=93=E4=BD=8D?= =?UTF-8?q?=E8=81=9A=E5=90=88=20+=20BOM=E6=98=8E=E7=BB=86=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- inventory-backend/app/api/v1/inbound/stock.py | 39 ++++++++++++++++--- inventory-web/src/views/material/list.vue | 2 +- .../src/views/outbound/Selection.vue | 7 ++-- 3 files changed, 39 insertions(+), 9 deletions(-) diff --git a/inventory-backend/app/api/v1/inbound/stock.py b/inventory-backend/app/api/v1/inbound/stock.py index 9af96a7..347023d 100644 --- a/inventory-backend/app/api/v1/inbound/stock.py +++ b/inventory-backend/app/api/v1/inbound/stock.py @@ -266,18 +266,47 @@ def get_stock_list(): d['available_quantity'] = d.get('qty_available', d.get('available_quantity', 0)) all_items.append(d) - total = len(all_items) + # ── 按规格+库位聚合(出库选单合并同类项)─────────────────────── + is_aggregated = request.args.get('is_aggregated', 'false').lower() == 'true' + if is_aggregated: + grouped_dict = {} + for item in all_items: + # 核心聚合键:类型 + 规格型号 + 库位 + group_key = f"{item.get('type')}_{item.get('standard')}_{item.get('warehouse_location', '')}" + + if group_key in grouped_dict: + # 累加数量 + existing = grouped_dict[group_key] + existing['available_quantity'] = float(existing.get('available_quantity', 0)) + float(item.get('available_quantity', 0)) + existing['stock_quantity'] = float(existing.get('stock_quantity', 0)) + float(item.get('stock_quantity', 0)) + # 保留 id 列表(出库提交时需用到) + existing_ids = existing.get('_ids', []) + existing_ids.append(item.get('id')) + existing['_ids'] = existing_ids + else: + # 存入代表项 + grouped_dict[group_key] = item.copy() + # 强制统一数据类型以便前端处理 + grouped_dict[group_key]['available_quantity'] = float(item.get('available_quantity', 0)) + grouped_dict[group_key]['stock_quantity'] = float(item.get('stock_quantity', 0)) + grouped_dict[group_key]['_ids'] = [item.get('id')] + + # 替换原列表为聚合后的列表 + all_items = list(grouped_dict.values()) + + # ── 手动切片分页 ──────────────────────────────────────────── + total = len(all_items) start = (page - 1) * pageSize - end = start + pageSize + end = start + pageSize paged = all_items[start:end] return jsonify({ 'msg': '获取成功', 'data': { - 'list': paged, - 'total': total, - 'page': page, + 'list': paged, + 'total': total, + 'page': page, 'pageSize': pageSize } }), 200 diff --git a/inventory-web/src/views/material/list.vue b/inventory-web/src/views/material/list.vue index ab2a463..d05be4a 100644 --- a/inventory-web/src/views/material/list.vue +++ b/inventory-web/src/views/material/list.vue @@ -326,7 +326,7 @@ { const res: any = await getStockList({ page: stockPage.value, pageSize: stockPageSize.value, - keyword: searchKeyword.value.trim() + keyword: searchKeyword.value.trim(), + is_aggregated: true // ★ 触发后端按规格+库位合并 }) // 为每个item添加uniqueKey和确保warehouse_location字段正确映射 stockList.value = (res.data?.list || []).map((item: any) => ({ @@ -649,7 +650,7 @@ watch(selectedBomNo, async (newBomNo) => { return } try { - const detailRes = await getBomDetail(newBomNo) + const detailRes: any = await getBomDetail(newBomNo) currentBomDetail.value = detailRes.data?.children || [] } catch (e) { ElMessage.error('加载 BOM 明细失败') @@ -666,7 +667,7 @@ const confirmBomAdd = async () => { if (currentBomDetail.value.length === 0) { try { - const detailRes = await getBomDetail(selectedBomNo.value) + const detailRes: any = await getBomDetail(selectedBomNo.value) currentBomDetail.value = detailRes.data?.children || [] } catch (e) { ElMessage.error('获取 BOM 详情失败')