Files
KCGL/inventory-web/src/api/bom.ts
yueli 2556b77530 perf: 系统级性能优化与并发安全修复
## 并发安全修复 (4处)
- scrap.py: 报废执行添加 SELECT FOR UPDATE 悲观锁,消除 TOCTOU 竞态
- stock.py (adjust_stock): 盘点调整添加 for_update=True 行锁
- outbound_service.py: 低库存预警 SMTP 调用移到 commit 之后,避免长事务
- trans_service.py: execute_dispatch 按 (source_table, id) 排序 items,消除死锁风险

## N+1 查询优化 (2处)
- inventory_task.py: _prefetch_inventory_map 单条 UNION ALL+GROUP BY 替代循环内逐条查询(N*4次→2次)
- stock.py (export_stocktake): get_borrowed_qty 批量 GROUP BY 替代逐条 TransBorrow 查询(~18000次→1次)

## BOM 列表性能重构
- bom_service.py: get_bom_list 单条 GROUP BY+string_agg+分页,消除 N+1 循环查询
- bom_service.py: 新增 get_bom_summary (轻量 GROUP BY category+COUNT)
- bom.py: 新增 /api/v1/bom/summary 路由,/list 支持 category 过滤

## Odoo 基础信息懒加载
- base_service.py: 新增 get_odoo_summary (GROUP BY category+COUNT)
- base.py: 新增 /api/v1/inbound/base/odoo-summary 路由
- buyOdoo.vue: 懒加载分组架构 (fetchOdooSummary + loadGroupItems)
- material_base.ts: 新增 getOdooSummary API

## 前端 Bug 修复
- BomManage.vue: 懒加载分组 (fetchBomSummary + loadGroupItems + collapse)
- BomManage.vue: 适配新 API 格式 (res.data.items 替代 res.data)
- buyOdoo.vue: 移除 "点击展开加载" 文字
- Selection.vue + borrow/apply/index.vue: openBomSelect 适配新 API 格式
2026-07-15 17:37:57 +08:00

83 lines
2.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import request from '@/utils/request'
// 获取BOM列表
export function getBomList(params?: any) {
return request({
url: '/v1/bom/list',
method: 'get',
params
})
}
// 获取BOM分组摘要(懒加载用,轻量 GROUP BY category + COUNT)
export function getBomSummary(params?: { keyword?: string }) {
return request({
url: '/v1/bom/summary',
method: 'get',
params
})
}
// 获取BOM详情(含库存信息)
export function getBomWithStock(bomNo: string) {
const trimmed = bomNo.replace(/^\/+|\/+$/g, '');
const encoded = encodeURIComponent(trimmed);
return request({
url: `/v1/bom/stock/${encoded}`,
method: 'get'
})
}
// 获取BOM详情
export function getBomDetail(bomNo: string, version?: string) {
// 去除首尾斜杠,保留中间斜杠并进行 URL 编码
const trimmed = bomNo.replace(/^\/+|\/+$/g, '');
const encoded = encodeURIComponent(trimmed);
const url = version
? `/v1/bom/detail/${encoded}?version=${encodeURIComponent(version)}`
: `/v1/bom/detail/${encoded}`;
return request({
url,
method: 'get'
})
}
// 保存BOM
export function saveBom(data: any) {
return request({
url: '/v1/bom/save',
method: 'post',
data
})
}
// 删除BOM
export function deleteBom(bomNo: string, version: string) {
// 去除首尾斜杠,保留中间斜杠并进行 URL 编码
const trimmed = bomNo.replace(/^\/+|\/+$/g, '');
const encoded = encodeURIComponent(trimmed);
return request({
url: `/v1/bom/${encoded}?version=${encodeURIComponent(version)}`,
method: 'delete'
})
}
// ==========================================
// BOM 草稿相关接口
// ==========================================
// 1. 暂存草稿
export function saveDraft(data: any) {
return request({ url: '/v1/bom/draft/save', method: 'post', data })
}
// 2. 读取草稿详情
export function getDraftDetail(params: { bom_no: string; version?: string }) {
return request({ url: '/v1/bom/draft/detail', method: 'get', params })
}
// 3. 发布草稿
export function publishDraft(data: { bom_no: string; version: string }) {
return request({ url: '/v1/bom/draft/publish', method: 'post', data })
}