

当下AI热潮席卷各行各业,无数软件工程师借着AI赋能,大幅提升开发效率、解锁各类新奇玩法。
不少硬件工程师却总有这样的感受:AI看似离硬件领域十分遥远,仿佛只是软件从业者的专属红利。
但事实并非如此!
硬件开发本就离不开各类辅助工具,而AI的飞速发展,彻底打破了技术壁垒。哪怕是不懂代码的硬件工程师,也能轻松打造适配自身工作场景的专属工具。这波AI赋能,对深耕硬件领域的我们而言,无疑是全新的突破与惊喜。
今天就给大家分享我的实操案例:我基于WorkBuddy搭建了一套电子元器件物料管理系统。全程实操、干货满满,希望能让每一位硬件从业者,都真切感受到AI带来的便捷与高效,看见硬件行业的AI新可能!
正菜开始了:

一、项目概述



电子元器件物料管理系统
开发笔记 —— 全过程回顾与技术总结
编写日期:2026-07-22
技术栈:FastAPI + Vue3 + Element Plus + SQLite


本项目是一个面向硬件研发团队的电子元器件物料管理系统(ERP),核心目标是解决物料编码混乱、参数管理分散、平替选型困难、BOM 导入繁琐等实际痛点。系统采用前后端分离架构:后端基于 FastAPI 提供 RESTful API,前端使用 Vue3 + Element Plus 构建单页应用,数据存储在 SQLite 数据库中(参数以 JSON 列灵活存储)。
截至本文档编写时,系统已具备完整的物料 CRUD、智能编码、平替推荐、参数模板驱动表单、专业 Excel 导出、原始 BOM 批量导入、多级排序、参数查询等核心能力,并通过了 API 自动化测试、前端端到端测试、可访问性审计和性能基准测试。




框架:FastAPI (Uvicorn ASGI),自动生成 OpenAPI 文档
ORM:SQLAlchemy + SQLite,参数字段使用 JSON 类型存储灵活键值对
路由模块:materials / categories / config / bom / io / datasheets / param_templates
服务层:codegen(编码生成)、substitution(平替匹配)、material_import(导入)、ai_extractor(AI 提取)
配置:YAML 驱动(data/config.yaml),支持 LLM(DeepSeek/OpenAI)和搜索引擎(Tavily/Serpapi/Bing)



框架:Vue3 Composition API + Vite 构建工具链
UI 库:Element Plus 组件库,自定义深色主题设计令牌
路由:Vue Router HTML5 History 模式(7 个页面路由)
状态:组件内 reactive/ref,无全局状态库(当前规模无需)
构建产物 dist/ 由 FastAPI StaticFiles 直接托管



系统整体采用经典的前后端分离 SPA 架构,如下图所示:

1 materials
图:系统主界面 —— 物料列表页(侧栏导航 + 数据表格 + 操作区)




物料编码是系统的核心标识,采用"分类码 + 家族号 + 变体号"三段式结构:
格式:CCCC FFFFF VV
│ │ └─ 变体号(2位):同规格不同厂商 → 仅末位不同 → 强平替
│ └─ 家族号(5位):由"分类+关键参数签名"自动生成
└─ 分类码(4位):一级2位+二级2位(如 1001=电阻, 1302=肖特基二极管)
编码设计的精妙之处在于:同规格不同厂商的物料仅变体号不同(末两位),这使得"强平替"的判定变成简单的前缀匹配——同前缀(分类+家族)即视为可直接替换。家族号的生成由 codegen 服务完成,它根据分类码和关键参数的哈希签名自动分配。



平替是硬件工程师最关心的功能之一。系统提供两级平替:
强平替:同前缀(分类码+家族号完全一致),仅变体号不同——可直接替换,零风险
广义平替:同分类、同封装且关键参数相似度 ≥ 0.6——输出差异参数对比表供人工判断
API 端点为 GET /api/materials/{id}/alternatives,返回候选替代料列表及差异分析。平替关系存储在 material_substitutes 表中,也可通过 substitution_rules/ 下的 MD 规则文件扩展。



不同品类的元器件有完全不同的参数集(电阻看阻值/精度/功率,电容看容值/耐压/封装)。系统创新性地采用 Markdown 文件作为参数模板定义源:
模板位置:param_templates/ 目录,按一级分类组织(如 13_二极管.md)
格式约定:



- 生成器:_generator.py 可批量生成/更新模板文件(--force 强制覆盖)
运行时,后端 param_template 服务实时解析 MD 文件;前端 MaterialAdd 组件在选择分类后,动态加载对应模板并渲染必填/可选参数输入框。用户可随时编辑 MD 文件调整参数定义,改完立即生效——无需重启服务。

图:添加物料页面 —— 选择分类后动态加载参数模板表单(普通添加 / AI识别 / Excel批量 三种模式)



物料管理实现了从创建到删除的全生命周期操作:
新增物料
三种录入方式:手动填写(参数模板驱动表单)、AI 自动识别(需配置 LLM Key)、Excel 批量导入
型号查重:blur 时实时调用 GET /api/materials/check-duplicate?model=,命中则弹窗展示已有物料参数
必填校验:后端 _check_required_params 按分类及祖先分类模板收集必填项,缺失返回 HTTP 400 MISSING_REQUIRED
保存流程:前端 try/catch 捕获 400 错误并友好提示用户补全必填项。
编辑与删除
MaterialList 表格增加"操作"列(编辑→跳详情、删除→确认框+DELETE),按钮 @click.stop 防行点击冲突
MaterialDetail 页头部加"删除"按钮(确认+DELETE+返回列表);编辑弹窗早已内置

8 detail
图:物料详情页 —— 展示完整信息(编码/型号/名称/参数/来源/置信度),支持编辑和删除



导出功能经历了从基础到专业的升级迭代。当前版本(format=xlsx)输出多 Sheet 专业报表:
Sheet1 物料清单:标题区 + 冻结窗格(C5) + 自动筛选 + 斑马纹 + 数据手册超链接 + 参数紧凑渲染(k:v) + 替代料列
Sheet2 分类汇总:按分类统计数量/厂商数/占比
Sheet3 替代料对照:强平替 + 广义平替 + 红色"建议补充替代料"提示
CSV 格式保留旧平铺字段兼容。前端"导出 Excel/CSV"按钮无需改动即可生效。



这是一个重要的 Bug 修复案例。系统初始化时 seed_categories() 误将分类码数值当作主键 ID 赋给 parent_id,导致全部 127 个二级分类的父子关系错乱(如肖特基二极管被挂到钽电容下)。
修复方案分两步:
一次性修复脚本 scripts/fix_category_tree.py 按 CATEGORY_TREE 权威树重新对齐 parent_id
修改 seed_categories() 维护 code→id 映射,flush 取真实 ID 再赋子级 parent_id,杜绝复发
验证结果:审计错误数归零;导出中 SS34 分类路径正确显示为「二极管 / 肖特基二极管」。

7 categories
图:分类管理页 —— 展示完整的四级分类树结构(一级→二级→三级→四级)



用户的原始 BOM 数据存放在 原始BOM表/ 目录下(9 个板级 .xls/.xlsx 文件,DGT1000~DGT1500)。这些文件使用 legacy .xls 格式(WPS OLE2),需要 xlrd==1.2.0 解析。
导入规则约定:
源物料编码写入 params.源物料编码 保留溯源
组件按"名称→系统分类"关键词映射(电阻→1001、电容→1101、IC→16xx/20xx 等)
板件型号 DGTxNxx 第 2 位映射到 10 个 PCB 三级分类(330201~330210)
导入器 scripts/import_raw_boms.py 通过 HTTP 调用 API 实现幂等导入(已存在同源编码则复用),顺序调用约 270 次。

6 bom
图:BOM 管理页 —— 已导入的板级 BOM 列表(DGT1000~DGT1500 南网总线系列板卡)



物料列表和 BOM 表均支持多级排序——这是用户高频使用的功能。实现要点:
后端:list_materials 接受 sort 参数,格式 field:order,field2:order2(白名单防注入)
前端:点击列头触发排序;Shift+点击追加为二级排序(使用 MouseEvent.shiftKey 原生属性检测)
UI 反馈:排序层级条以 Chip 形式展示优先级①②③及方向箭头,支持逐层移除×和一键清除
开发过程中经历了几轮调试:最初用 keydown/keyup 监听 shiftHeld 不可靠,最终改为 MouseEvent.shiftKey 原生属性解决。用户曾质疑"制造商没排序",经排查确认功能正常——只是次级排序仅在主排序值相同时才生效,需直接点击制造商列头替换为主排序才能看到效果。



参数查询页面的初版 UI 被用户反馈"太丑"。作为 UI 设计师介入后的完整重设计包括:
查询构建器卡片:条件行带连接轴(AND/OR 标签+竖线)、操作符彩色药丸(等于/包含/大于/小于等)
活跃筛选标签区:已添加的条件以 Tag 形式展示,可单独移除
结果卡:计数指标(匹配数/总物料数)+ 自定义空状态(放大镜图标+引导文案)
设计令牌:套用 main.css 的 CSS 变量体系,720px 断点响应式适配

4 query
图:重设计后的参数查询页 —— 查询构建器(上)+ 结果区域(下),现代化卡片布局



系统经过了全面的质量验证,覆盖以下维度:



使用 httpx 同步客户端覆盖 CRUD / 编码 / 平替 / 导出 / 校验等核心接口
发现并修复 1 个 Bug:gt/lt 过滤对 SI 前缀值(如"5k")抛 500(unguarded float())



Playwright + Edge 浏览器自动化,覆盖主要用户流程
发现 2 个 WCAG 违规:el-select 缺 aria-label(critical)、颜色对比度不足(serious)



API Key 明文存 config.yaml(已知风险,按安全约定不入库)
配置写入接口无 schema 白名单(待后续加固)



首屏加载 < 1.5s 目标(构建优化 + 关键 CSS 内联)
API 响应 P95 < 200ms(SQLite 单机场景下充足)



项目建立了明确的备份约定:


Git 提交到本地 master 分支(不自动 push 远程)
最新提交 dc0820f:21 文件变更(+3552/-488),涵盖全部近期功能迭代
补充提交 79d0256:纳入测试脚本 test_bom_io / test_pcb_rule



SQLite 数据库 data/erp.db 不纳入 Git 跟踪(gitignore 约定 *.db)
时间戳快照:data/erp.db.bak_YYYYMMDD_HHMMSS(最新:20260721_195040,368KB)
每次快照验证:字节级一致 + integrity_check ok + 各表记录数匹配



原始BOM表/:用户决策视为外部输入,仅磁盘一份(不进 git 也不进 db 快照)
临时调试产物(*_check.json 等):正确排除,不污染版本库




JSON 列 vs EAV 模型:选择 JSON 存储参数,牺牲部分查询灵活性换取极致的 schema 灵活性——对品类繁多的元器件场景是正确的取舍
MD 驱动参数模板:让非开发者也能通过编辑 Markdown 文件扩展参数定义,降低运维门槛
HTML5 History vs Hash 路由:选择 History 模式获得更干净的 URL,但要求服务器配置 catch-all(当前开发环境未配置,生产部署需注意)



Git Bash 中文路径:直接 git add 中文文件名会 pathspec 不匹配导致整条命令失败 → 改用 glob 通配符按字节匹配绕过
Element Plus 自闭合标签:.vue 中
自闭合会导致 vite build 报错 → 必须显式闭合 Shift 键检测:keydown/keyup 监听不可靠 → 改用 MouseEvent.shiftKey 原生属性
浏览器缓存:JS 更新后用户看到旧界面 → Vite content hash 强制刷新 + Array.isArray() 防御性写法
分类树 parent_id:seed 时误用 code 当 id → 维护 code→id 映射 + flush 取真实 ID



component_api(LCSC/Digikey):目前仅骨架,未接真实接口
库存出入库、供应商管理:下一阶段规划
WCAG a11y 修复:el-select aria-label + 颜色对比度优化
SPA catch-all 路由:FastAPI 需配置 fallback 返回 index.html 以支持 History 模式直连访问



01_materials.png — 物料列表主页(表格/搜索/导出/操作)
02_sort_single.png — 单级排序演示
03_sort_multi.png — 多级排序演示(Shift+点击)
04_query.png — 参数查询页(重设计后 UI)
05_add.png — 添加物料页(三模式/参数模板/必填校验)
06_bom.png — BOM 管理页(板级列表/查看/删除)
07_categories.png — 分类管理页(四级树结构)
08_detail.png — 物料详情页(完整信息/编辑/删除)
相关内容:
一个人就是一支团队:WorkBuddy 多 Agent 协同工作完全教程
夜雨聆风