资讯动态

开源BOM管理系统:Excel直连数据库的硬件物料管理方案

发布时间:2026/10/13 5:51:05 来源:尧图企业网站定制
简介这是一款面向电子工程师、硬件研发团队及BOM管理初学者的开源物料清单协同管理软件解决Excel分散维护BOM导致的版本混乱、多人协作困难、数据孤岛等问题。系统基于C#开发采用集中式数据库架构支持实时多用户编辑、完整版本控制并深度集成Ciiva电子元器件搜索API实现BOM与供应商库存、价格、替代料、技术参数等关键信息的自动同步。资源包共50个文件含37个核心C#源码文件如ManufacturerComponent.cs、StockItem.cs等、5个运行依赖DLL、2个项目配置文件.csproj及图标、配置、资源文件等整体仅315KB轻量易部署。已有838人学习下载提供开箱即用的完整可编译VS解决方案ApiDemoProject含认证、搜索、比价、库存查询等全链路API调用示例与UI主界面是理解工业级BOM系统架构与电子元器件数据集成实践的优质入门参考。1. BOM Management Software不是Excel插件而是把散落的BOM表格“焊”进一个可查、可溯、可权限控制的数据库里你有没有经历过这种场景三个工程师各自维护一份Excel格式的物料清单BOM版本号靠文件名后缀_v2_final_reallyfinal.xlsx变更记录靠微信截图ECN工程变更通知落地时发现A表删了电阻R12B表却新增了同型号但不同供应商的R12aC表压根没更新——等PCB贴片完才发现阻值不匹配。这不是玄学是典型BOM失控。这个开源BOM Management Software核心价值就一句话把Excel里游离的BOM数据一次性导入、结构化存储、带版本快照与操作留痕地托管进轻量级PostgreSQL/SQLite数据库同时保留Excel作为前端编辑入口。它不替代ERP也不做PLM那么重而是卡在“设计输出→制造输入”这个最脆弱的交接缝里给中小研发团队一个零许可成本、可本地部署、改配置就能上线的BOM中枢。适合硬件初创团队、教育实验室、产线试制组——只要你们还在用Excel传BOM又开始为版本打架、字段不一致、找不到历史修改人而头疼它就不是玩具是能立刻止血的工具。2. 为什么选它从Excel直连数据库的架构设计与技术选型逻辑2.1 它不是又一个Web表格编辑器三层数据流拆解这个项目最反直觉的设计点在于它不把Excel当“视图”而当“协议”。很多同类工具试图用Web界面模拟Excel操作结果陷入渲染性能泥潭而本项目采用“Excel ↔ 数据库 ↔ Web API”三段式流转前端层用户仍用熟悉的Excel.xlsx编辑通过官方提供的模板文件含预设表头、数据验证规则、隐藏元数据列填写转换层运行bom_import.py脚本将Excel解析为标准化JSON Schema含物料ID、父级关系、用量、版本号、生效日期等12个必填字段再经SQLAlchemy ORM映射写入数据库服务层Flask后端暴露RESTful接口如GET /api/bom/revision/2024Q3_A?formatcsv供MES系统拉取结构化BOM或供内部看板查询变更对比。提示这种设计牺牲了“所见即所得”的实时性但换来的是数据一致性——所有Excel文件最终都收敛到同一份数据库快照避免了“打开Excel即产生新分支”的Git式混乱。2.2 数据库选型SQLite够用PostgreSQL才真正释放能力项目默认支持SQLite单文件开箱即用但生产环境我强烈建议切到PostgreSQL。原因很实际能力维度SQLite表现PostgreSQL优势并发写入多用户同时导入会锁整个DB文件行级锁5人同时上传BOM无阻塞历史版本追溯需手动建表存快照易遗漏内置pg_trgm扩展时间旅行查询AS OF SYSTEM TIME权限控制仅文件级读写权限细粒度到行级如“采购员只能看statusapproved的物料”备份恢复VACUUM INTO备份慢且不可中断pg_dump --jobs4并行导出TB级BOM秒级备份注意切换数据库只需改.env文件两行DB_TYPEpostgresql DATABASE_URLpostgresql://bom_user:pwdlocalhost:5432/bom_db启动前运行python manage.py db upgrade自动执行迁移脚本含索引优化、约束添加。2.3 Excel模板的“隐形契约”12个字段如何定义BOM语义项目强制要求Excel按固定列顺序填写这看似死板实则是防错关键。以某电源模块BOM为例其模板头行为BOM_IDPARENT_IDITEM_NAMEMANUF_PART_NOSUPPLIERQTYUNITREF_DESIGNATORSTATUSEFFECTIVE_DATEREVISIONNOTESBOM_ID全局唯一物料编码如PWR-DCDC-001禁止空格/中文/特殊字符这是数据库主键PARENT_ID父级BOM_ID顶层为空构建树形结构SELECT * FROM bom_items WHERE parent_id IS NULL即得所有顶层模块EFFECTIVE_DATE必须为YYYY-MM-DD格式系统据此判断当前生效版本WHERE effective_date NOW() ORDER BY effective_date DESC LIMIT 1REVISION字符串类型非数字支持1.2.0、2024Q3-A等语义化版本数据库自动校验同一BOM_ID下不得存在日期重叠的修订版。血泪经验曾有团队把REF_DESIGNATOR参考位号填成C1,C2,C3逗号分隔导致后续SMT编程无法识别单个电容位置。正确做法是每行只写一个位号用量QTY字段体现数量。3. 从零部署5分钟跑通本地实例的完整命令链3.1 环境准备Python 3.9与数据库驱动安装项目依赖明确无需conda虚拟环境但推荐# 创建隔离环境可选但强烈建议 python -m venv bom_env source bom_env/bin/activate # Linux/macOS # bom_env\Scripts\activate.bat # Windows # 安装核心依赖含数据库驱动 pip install -r requirements.txt # 若选PostgreSQL额外装psycopg2-binaryWindows用户注意用binary版避编译坑 pip install psycopg2-binary逻辑说明requirements.txt中flask-sqlalchemy3.0.5锁定版本因4.x版移除了session.execute(text())的便捷写法而项目大量使用原生SQL做树形查询如WITH RECURSIVE bom_tree AS (...)降级兼容性风险高。3.2 初始化数据库与管理员账户首次运行需创建表结构并注入初始数据# 执行数据库迁移生成bom_items, bom_revisions等6张表 python manage.py db upgrade # 创建超级管理员用户名admin密码Admin123 python manage.py create_admin --username admin --password Admin123 # 加载示例BOM数据含3层嵌套结构用于验证树形查询 python manage.py load_sample_data参数说明create_admin命令会哈希密码并写入users表load_sample_data调用sample_bom.xlsx中的127行数据自动构建父子关系链如MAIN_PCB→POWER_MODULE→DCDC_CONVERTER。3.3 启动服务与验证API可用性启动Flask开发服务器生产环境请用Gunicorn# 设置环境变量开发模式 export FLASK_ENVdevelopment export FLASK_APPapp:create_app # 启动服务监听5000端口 flask run --host0.0.0.0 --port5000验证是否成功# 检查健康状态 curl http://localhost:5000/api/health # 返回 {status:healthy,db_connected:true,version:v2.4.1} # 获取最新版BOM列表应返回JSON数组 curl http://localhost:5000/api/bom?limit5 # 返回 [{bom_id:MAIN_PCB,revision:2024Q3,effective_date:2024-07-01,...}]注意若curl返回Connection refused检查flask run输出是否有* Running on http://127.0.0.1:5000字样若提示ModuleNotFoundError确认app/目录下有__init__.py且manage.py路径正确。4. Excel导入实战手把手完成一次带版本快照的BOM入库4.1 下载模板并填写真实数据访问http://localhost:5000/download/template获取bom_template_v2.xlsx。重点填写以下区域Sheet1BOM_DATA按列填写特别注意STATUS列填draft草稿、approved已批准、obsolete作废EFFECTIVE_DATE填未来日期如2024-10-01可实现“计划生效”NOTES列支持Markdown语法**加粗**、*斜体*前端渲染为富文本。Sheet2BOM_METADATA填写本次导入的元信息PROJECT_NAME:RobotArm_V2IMPORTED_BY:zhangsanCHANGE_REASON:电机驱动IC升级为TPS65988提示模板内置数据验证如STATUS下拉菜单关闭Excel的“启用内容”可能禁用验证务必点击“启用编辑”。4.2 执行导入并观察数据库变化运行导入脚本指定Excel路径与版本号python scripts/import_bom.py \ --file ./data/robot_arm_v2.xlsx \ --revision 2024Q4-B \ --comment 电机驱动IC升级兼容旧PCB \ --user zhangsan脚本执行后数据库发生三件事在bom_revisions表插入新记录含revision2024Q4-B、imported_atnow()、user_id3将Excel中所有行写入bom_itemsrevision_id外键关联上一步ID自动触发bom_items表的ON INSERT触发器校验PARENT_ID是否存在、QTY0等业务规则。逻辑说明import_bom.py核心是parse_excel_to_json()函数它用openpyxl读取Excel避开pandas.read_excel对合并单元格的误解析逐行生成字典再批量插入。失败时回滚整个事务确保“全成功或全失败”。4.3 查询与导出用SQL和API验证数据一致性登录PostgreSQL执行验证查询-- 查看RobotArm_V2的最新版BOM含层级关系 WITH RECURSIVE bom_tree AS ( SELECT id, bom_id, parent_id, item_name, qty, 1 as level FROM bom_items WHERE bom_id ROBOT_ARM_MAIN AND revision_id ( SELECT id FROM bom_revisions WHERE revision 2024Q4-B LIMIT 1 ) UNION ALL SELECT c.id, c.bom_id, c.parent_id, c.item_name, c.qty, p.level 1 FROM bom_items c INNER JOIN bom_tree p ON c.parent_id p.bom_id ) SELECT * FROM bom_tree ORDER BY level;同时调用API导出CSV供下游使用# 导出指定版本的扁平化BOM含所有子项 curl -H Accept: text/csv \ http://localhost:5000/api/bom/revision/2024Q4-B?flattentrue \ robot_arm_v2_flat.csv参数说明flattentrue参数展开所有子BOM递归查询?formatexcel则返回.xlsx文件含样式。导出CSV时QTY字段自动计算为累计用量如顶层用1个子模块用2个则子项QTY1×22。5. 避坑指南5个让新手当场翻车的高频问题与根治方案5.1 现象导入Excel后PARENT_ID显示为#REF!数据库里该字段为NULL原因Excel中PARENT_ID列填写了不存在的BOM_ID如填了MOTOR_CTRL但数据库无此ID且模板未开启严格校验。解决运行python scripts/validate_bom.py --file robot_arm_v2.xlsx脚本会扫描所有PARENT_ID并报告缺失项在bom_template_v2.xlsx的BOM_DATA页为PARENT_ID列设置数据验证允许“序列”来源INDIRECT(BOM_IDS)其中BOM_IDS是BOM_METADATA页定义的命名区域。5.2 现象flask run报错sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) unable to open database file原因.env中DATABASE_PATH./instance/app.db路径的instance/目录不存在SQLite无法自动创建父目录。解决mkdir -p instance # Linux/macOS # mkdir instance # Windows # 再次运行 flask run5.3 现象Web界面登录后点击“BOM列表”空白浏览器F12看到500 Internal Server Error原因bom_items表缺少created_at时间戳字段旧版迁移脚本遗漏而app/views.py中get_latest_boms()函数强制ORDER BY created_at DESC。解决-- 连接数据库后执行 ALTER TABLE bom_items ADD COLUMN created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP; UPDATE bom_items SET created_at CURRENT_TIMESTAMP WHERE created_at IS NULL;5.4 现象导入同一BOM_ID的两个版本如2024Q3和2024Q4但API只返回2024Q3原因EFFECTIVE_DATE填错格式如2024/07/01而非2024-07-01数据库存为NULLWHERE effective_date NOW()永远不成立。解决用SELECT bom_id, revision, effective_date FROM bom_revisions;确认日期格式修复Excel后重新导入或直接SQL更新UPDATE bom_revisions SET effective_date 2024-10-01 WHERE revision 2024Q4;5.5 现象curl调用API返回{error:Unauthorized}但用户名密码正确原因Flask-WTF的CSRF保护在API模式下误触发login_required装饰器默认检查CSRF token。解决修改app/auth/views.py在login()函数上方添加from flask_wtf.csrf import csrf_exempt csrf_exempt def login():注意此操作仅对API端点开放Web表单仍受CSRF保护安全边界清晰。6. 进阶技巧用数据库触发器自动生成BOM变更报告与邮件通知6.1 构建变更审计表记录每一次BOM增删改项目默认只存BOM快照但产线需要知道“谁在何时改了哪个物料”。我们用PostgreSQL触发器补全这一环-- 创建审计表 CREATE TABLE bom_audit_log ( id SERIAL PRIMARY KEY, operation VARCHAR(10) NOT NULL, -- INSERT,UPDATE,DELETE bom_id VARCHAR(50) NOT NULL, old_data JSONB, new_data JSONB, changed_by VARCHAR(50), changed_at TIMESTAMP DEFAULT NOW() ); -- 创建触发器函数 CREATE OR REPLACE FUNCTION log_bom_change() RETURNS TRIGGER AS $$ BEGIN IF TG_OP INSERT THEN INSERT INTO bom_audit_log(operation, bom_id, new_data, changed_by) VALUES (INSERT, NEW.bom_id, to_jsonb(NEW), current_setting(app.user_id, true)); ELSIF TG_OP UPDATE THEN INSERT INTO bom_audit_log(operation, bom_id, old_data, new_data, changed_by) VALUES (UPDATE, NEW.bom_id, to_jsonb(OLD), to_jsonb(NEW), current_setting(app.user_id, true)); END IF; RETURN NEW; END; $$ LANGUAGE plpgsql; -- 绑定到bom_items表 CREATE TRIGGER bom_audit_trigger AFTER INSERT OR UPDATE ON bom_items FOR EACH ROW EXECUTE FUNCTION log_bom_change();关键点current_setting(app.user_id, true)从Flask应用层透传用户ID需在app/models.py的db.session.execute()前执行set_config(app.user_id, current_user.username)确保审计日志可追溯到具体人。6.2 用Python脚本生成周报自动抓取变更并邮件发送创建scripts/generate_weekly_report.pyimport smtplib from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart from datetime import datetime, timedelta from sqlalchemy import create_engine # 连接数据库 engine create_engine(postgresql://bom_user:pwdlocalhost:5432/bom_db) # 查询上周变更 last_week datetime.now() - timedelta(days7) query SELECT operation, bom_id, changed_by, changed_at FROM bom_audit_log WHERE changed_at %s ORDER BY changed_at DESC changes engine.execute(query, (last_week,)).fetchall() # 生成HTML邮件 html fh2BOM变更周报{last_week.strftime(%Y-%m-%d)} 至 {datetime.now().strftime(%Y-%m-%d)}/h2 html tabletrth操作/ththBOM_ID/thth人员/thth时间/th/tr for op, bid, user, dt in changes: html ftrtd{op}/tdtd{bid}/tdtd{user}/tdtd{dt}/td/tr html /table # 发送邮件配置SMTP msg MIMEMultipart() msg[Subject] 【BOM周报】上周共发生{}次变更.format(len(changes)) msg.attach(MIMEText(html, html)) server smtplib.SMTP(smtp.company.com, 587) server.sendmail(bomcompany.com, [eng-teamcompany.com], msg.as_string())执行方式加入Linux crontab0 9 * * 1 python /opt/bom/scripts/generate_weekly_report.py每周一早9点自动发送。6.3 一个硬核习惯每次导入前强制执行“差异预检”我从某硬件团队踩坑后养成的习惯绝不直接导入Excel先跑差异分析。用scripts/diff_bom.py对比新旧版本# 对比2024Q3与2024Q4-B两个版本 python scripts/diff_bom.py \ --base-revision 2024Q3 \ --target-revision 2024Q4-B \ --output-format markdown输出示例## 删除项2 | BOM_ID | ITEM_NAME | QTY | 原因 | |--------|-----------|-----|------| | R12 | 10kΩ电阻 | 4 | 替换为集成方案 | ## ➕ 新增项3 | BOM_ID | ITEM_NAME | QTY | 供应商 | |--------|-----------|-----|--------| | U5 | TPS65988 | 1 | TI |从那以后我每次导入BOM前都强制走一遍diff_bom.py把Markdown报告发到团队群所有人确认无异议再点导入按钮。这多花的2分钟省去了后面3小时的PCB返工排查。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑