更新记录

1.0.0(2026-11-01)

首个版本:多级 BOM 展开与用量汇总。子件用量按父级累计 × 本行用量 × (1 + 损耗率) 逐级传递;按料号合并汇总,记录引用次数与首次出现层级;替代组默认只取主料、可切换全部计入;传入料号库存后给出净需求与缺料标记,无库存记录单独标未盘点不判缺料;逐层拆分核对工艺路线;反查给出直接父件、回溯路径与单台成品折算用量;结构体检覆盖循环引用(环路径规范化去重)、重复行、自引用、零用量、缺单位、单位冲突;解析支持逗号与制表符、引号包裹、2 与 2% 两种损耗率写法、有无表头、CRLF;需求清单导出 10 列 CSV 带 BOM。UTS→Kotlin 编译通过(index.kt 1757 行、classes.dex 73,720 字节),67 项回归测试全部通过;真机未执行(测试机未连接,adb devices 为空),市场截图为 H5 渲染并标注示例数据。


平台兼容性

uni-app

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
× √ × × √ × √ × ×
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
× × × × × × × × × × × ×

多级 BOM 展开与物料需求汇总

给做生产备料、缺料跟单、成本核算的你:把多级 BOM 从任意一层料号一路展开到底,按料号汇总总用量。

不是「父子两列查一下用了几个」。真到排产那天,你需要的四件事,这里都有:

  1. 一路展开到底:四层五层的结构一次算完,每级用量相乘、损耗率逐级累乘,不是只看一级;
  2. 按料号合并:同一个螺丝被三个半成品用到,合并成一行总需求,不是散在几十行里自己加;
  3. 有库存就能判断缺不缺:传一份「料号,库存」,直接给出净需求与缺料名单;
  4. 结构有毛病先告诉你:循环引用、同父件重复行、用量为零、缺单位、同一料号单位不一致,一次点出来再展开。

给谁用

  • 物控/计划:排产前算这一个成品要备多少料,先看缺口再去催料;
  • 采购:把缺口清单导成 CSV 交给供应商,不用手工拼表;
  • 工程/工艺:核对 BOM 层级结构,看某一级到底用了什么,找循环引用和重复行;
  • 成本/报价:拿展开后的用量清单做成本核算的输入(金额计算不在本插件范围)。

能做什么

能力 说明
多级展开 从任意料号往下展开,默认 20 层上限,可用 depth 调整
用量累乘 子件用量 = 父级用量 × 本行用量 × (1 + 损耗率),逐级传递
按料号汇总 同一料号被多个父件引用时合并,并记录被引用次数与首次出现层级
替代组 同一父件下同组的多行互为替代,默认只取第一行,可切换为全部计入
库存净需求 传入「料号,库存」后给出库存、净需求与缺料标记
逐层拆分 按层级分组返回,便于核对工艺路线每一级的用量
反查 某个料被哪些父件用到,一路回溯到顶层成品,折算单台成品用量
结构体检 循环引用(规范化路径,同一个圈只报一次)、重复行、自引用、零用量、缺单位、单位冲突
导出 需求清单 CSV(10 列,带 BOM,Excel 双击不乱码)

快速接入

import { explodeBom, whereUsed, checkBomFile, levelsOf } from '@/uni_modules/szhzy-bom-explode'

// 1. 展开:CSV 文本直接给,也可以传文件路径
const r = explodeBom({
  csv: '父件,子件,用量,损耗率,单位,替代组\nLAMP-A20,T8-18W,1,0,支,\n…',
  root: 'LAMP-A20',
  qtyDecimals: 3,
  writeCsv: true,
  fileName: 'LAMP-A20-备料.csv'
})
// r.items   [{ code, unit, qty, directQty, level, sources, stock, net, shortage }]
// r.stats   { rows, items, maxLevel, totalQty, cycles, altSkipped, truncated, shortage }
// r.summary 「LAMP-A20 展开 4 层,9 种料,3 种库存不足」

// 2. 带库存算缺口
const g = explodeBom({
  path: '/storage/emulated/0/Download/BOM-LAMP-A20.csv',
  root: 'LAMP-A20',
  stockCsv: '灯珠-2835,1000\n管壳-1.2M,0'
})
// g.items 里 shortage 为 true 的就是要催的料

// 3. 反查:这个料用在哪些成品上
const w = whereUsed({ csv: bomText, item: '灯珠-2835' })
// w.hits [{ parent, top, qty, unit, path: 'LAMP-A20 > T8-18W > PCBA-18W', perTopQty }]

// 4. 结构体检
const c = checkBomFile({ csv: bomText })
// c.issues [{ kind: 'CYCLE', item: 'A', message: '存在循环引用:A > B > A' }]

所有接口返回统一信封 { ok, code, message, ... },不抛异常。code 取值:SUCCESS、EMPTY、NO_HEADER、NO_ROOT(起始料号没有下级明细)、READ_FAILED、CHARSET_UNSUPPORTED 等。

输入格式

标准的六列,表头名可省(无表头时按列序读):

列 表头可写 说明
父件 父件 / 父项 / 父物料 / parent 上层料号
子件 子件 / 子项 / 子物料 / child 下层料号
用量 用量 / 数量 / 单位用量 / qty 每个父件用几个子件,缺省 1
损耗率 损耗率 / 损耗 / loss 百分数,写 2 或 2% 都是 2%
单位 单位 / 计量单位 / unit 缺省空
替代组 替代组 / 替代 / alt 空表示正常用量行

分隔符支持逗号和制表符(从 Excel 直接复制粘贴过来就是制表符),字段可用双引号包裹,"" 表示引号本身。

参数

参数 类型 默认 说明
csv string — BOM 明细文本,与 path 二选一
path string — BOM 文件路径或 content:// URI
charset string UTF-8 读文件编码,老系统导出的 GBK 直接传 GBK
root string — 展开起点料号(必填,可以是中间层半成品)
depth number 20 最大展开深度,超过置 truncated
qtyDecimals number 3 汇总用量保留小数位
includeAlternatives boolean false 替代组是否全部计入需求
sortBy string code 排序:code 料号 / qty 用量倒序 / level 层级
maxItems number 0 料号条数上限,0 用内置上限(5 万)
stockCsv string — 「料号,库存」两列文本,传入后算净需求
writeCsv boolean false 是否把需求清单写成 CSV
bom boolean true 写 CSV 时是否带 UTF-8 BOM

用量怎么算

一级:子件用量 = BOM 用量 × (1 + 损耗率)
二级:子件用量 = 一级累计用量 × BOM 用量 × (1 + 损耗率)
……

例:成品 1 台 → T8-18W 灯管 1 支(损耗 0%)→ PCBA 1 块(损耗 1%)→ 灯珠 72 颗(损耗 3%), 则单台灯珠需求 = 1 × 1 × 1.01 × 72 × 1.03 = 74.902 颗(保留 3 位)。

验证状态

  • UTS → Kotlin 编译:已执行,compiled successfully(详见 docs/bom-explode/测试记录.md);
  • 纯逻辑回归测试:65 项全部通过,覆盖解析、累乘、替代组、深度上限、循环引用、库存净需求、反查、体检、导出;
  • 真机运行:未执行。开发时测试机未连接(adb devices 为空),Android 平台层的文件读写需要你在自己的设备上跑一次;
  • iOS / 鸿蒙:未实现,仅支持 Android。

购买前必读

  1. 只算数量,不算金额。成本、费率、税率属于报价核算,不在本插件范围;
  2. 不做库存事务。传入的库存是只读快照,插件不会扣减、不会写回;
  3. 替代料默认只取第一行。如果你们的规矩是「替代料按比例分摊」或「主料缺了才用替代」,请用 includeAlternatives 自行取舍,插件不做业务臆测;
  4. 环不会让程序卡死。遇到循环引用会停止该分支下钻并在 issues 里报出来,但不会替你修 BOM;
  5. CSV 是交换格式。BOM 从 ERP/PLM 导出成 CSV 再传进来,比让插件直连数据库更稳,也不需要任何网络权限。

更新日志

见 changelog.md。

隐私、权限声明

1. 本插件需要申请的系统权限列表:

无系统权限。读取调用方用系统文件选择器交过来的文件(路径或 content:// 授权),写出走应用外部私有目录。

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件不采集、不上传任何数据,不访问网络,不写日志。BOM 与库存清单只在本机内存中解析展开;需求清单由调用方决定是否落盘,默认写应用外部私有目录。

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

无

暂无用户评论。