本提交完成了WMS系统的多维度优化升级: 1. 新增RBAC权限系统,支持角色/菜单/按钮三级权限管控 2. 重构库存盘点、物料管理、区域维护等模块的查询筛选与展示逻辑 3. 优化入库/出库/质检等业务流程,完善数据冗余与业务闭环 4. 移除旧装箱表,将装箱逻辑合并到出库主表 5. 新增前端权限判断工具、导出工具与端到端测试用例 6. 补充完善各类注释与数据库字段说明
18 KiB
北京电力 WMS 项目 · 现状说明(供重新规划)
生成时间:2026-09-03 用途:作为「重新规划」的输入材料,供其他 AI 直接阅读并制定方案 核实方式:全部内容来自实际代码读取(非记忆/推测),关键结论已标注代码位置
一、系统全景
根仓库 D:\hardman\bj_power 下共有 5 个子系统:
| 子系统 | 端口 | 技术 | 职责 | 备注 |
|---|---|---|---|---|
bj_power_wms |
8890 | Go + go-zero + ent | WMS 后端(全部业务逻辑 + PostgreSQL) | 核心系统 |
bj_power_wms_client |
8891 | Go(仅 config/proxy) | 库房客户端:静态托管 + /api 反向代理 |
无业务逻辑,转发到 8890 |
bj_power_mes |
— | Go + ent + frontend | MES 系统(工单、BOM、台账来源) | 独立服务 |
bj_power_workstation |
— | Go + frontend + SQLite | 工位终端 | 独立 DB |
bj_power_dashboard |
— | Vue3 + TS + Vite | 大屏展示(独立构建产物 dist) | 免登录 |
关键架构事实(已核实):
bj_power_wms_client(8891)不是纯前端壳,它是一个 Go 服务,但internal/下只有config和proxy两个包,无 handler、无 ent。- 其配置
etc/bj_power_wms_client.yaml明确:WmsAddr: http://127.0.0.1:8890,请求转发时注入X-API-TOKEN: Hardman_2026。 - 因此:前端页面(8891)看到的
/api/*实际全部由 8890 的 WMS 后端处理。 - 前端源码在
bj_power_wms_client/frontend/,构建产物输出到bj_power_wms_client/web/static。 bj_power_wms(8890)不含go:embed,不内嵌前端,前端由 8891 单独提供。
结论:用户口中的「wms 和 wms 客户端」= 8890(业务后端)+ 8891(客户端壳)。所有功能/权限改造实际上都落在 8890。
二、技术栈
后端(bj_power_wms)
- Go +
go-zero(rest 路由)+entORM - PostgreSQL(
bj_power_wms,账号postgres/postgres) - JWT 鉴权,Header:
Authorization: Bearer {token} - 统一响应包裹
{code, message, data},业务数据一律在data层 - ent 代码生成:
go run -tags entgenerate ./tools(build tagentgenerate,入口tools/generate.go)
前端(bj_power_wms_client/frontend)
- Vue3(
<script setup>)+ Element Plus + Vite - Axios 封装
src/utils/request.js:baseURL: '/api',响应拦截器统一拆data、统一错误提示、401 跳登录 - 路由:
src/router/index.js(history 模式) - 布局/菜单:
src/layouts/MainLayout.vue - 页面:
src/pages/(14 个 .vue) - 页内帮助:每个页面挂
<PageHelp>,文案集中在src/help.js
运行约定
- 服务端口 8890(后端)/ 8891(客户端);登录
admin / 123456 - 前端重建套路(避 Windows EPERM):
mv web/static web/static_bak_<时间戳>→mkdir web/static→npm run build→rm -rf web/static_bak_* - 注意:8890 与 8891 不能同时被两个实例占用;换调试方式前需先结束旧进程。
三、数据模型(ent schema,共 13 张业务表)
bj_power_wms/schema/ 下 14 个文件(mixin.go 仅提供 nowUnix(),非共享 mixin)。
所有表的 created_at 均为 Int64 unix 秒时间戳(不是 time.Time),多数表另有 updated_at。
入库域
- inbound_order(入库单·主表):
inbound_no(唯一)inbound_type(purchase/semi/finished/return)material_codematerial_namemanage_mode(1批次/2SN)batch_nozone_codequantityoperatorremarkcreated_at - inbound_detail(入库明细·子表):
inbound_nosn_codebatch_nomaterial_codequantitycreated_at- 结构件:一批一条(batch_no);精密件:每个 SN 一条明细(可能上万条)
出库域
- outbound_order(出库单·统一主表):
outbound_nooutbound_type(workorder 备料 / general 通用)order_nomaterial_codematerial_namemanage_modebatch_nozone_codequantityoperatorreviewertarget_dockremarkbox_nobox_sn_listcontract_no(装箱信息)created_at - outbound_detail(出库明细·子表):
outbound_nosn_codebatch_nomaterial_codequantityorder_nocreated_at
库存域
- inventory(统一库存表):
manage_modematerial_codematerial_namebatch_nosn_codequantitylocked_qtyquality_statuszone_codestatusproduction_datesupplierinbound_noremarkcreated_atupdated_at- 结构件:按批次一条记录;精密件:每个 SN 一条记录
- inventory_lock(库存锁定):
target_typetarget_idmaterial_codelocked_qtyorder_nostatusexpired_atremarkcreated_atupdated_at
基础数据
- material(物料档案):
code(唯一)nameshort_namespecunitdescriptionmanage_modeis_batch_managedis_serial_managedtemplate_codecreated_atupdated_at - zone(区域):
zone_codezone_namedescriptionstatuscreated_atupdated_at - user(用户):
usernamepassword(bcrypt)real_nameroledeptphoneis_activelast_login_atcreated_atupdated_at
业务扩展
- inspection_record(检验记录):
target_typetarget_idmaterial_codeinspection_typestatusresult_valueinspectorremarkcreated_atupdated_at - order_material_ledger(工单物料台账):
order_nomaterial_codematerial_nametotal_qtyout_qtystatusremarkcreated_atupdated_at - semi_finished(半成品/成品):
snmaterial_codecompleted_processquantityzone_codestatusorder_nocreated_atupdated_at - stocktake(盘点,
stocktake.go内含「盘点单 + 盘点明细」两个 schema):盘点单stocktake_nostatusoperatortotal_targetscreated_atfinished_at;盘点明细target_typetarget_idmaterial_codezone_codebook_qtyscanned_qtydiff_qtycountedupdated_at
四、后端 API 全清单(来自 internal/handler/routes.go)
| 模块 | 接口 |
|---|---|
| 健康/登录 | GET /api/health、POST /api/auth/login |
| 用户 | POST /user/change-password、GET /user/info、GET /user/list、POST /user/create、POST /user/update、POST /user/delete |
| 物料 | POST /material/create、POST /material/update、GET /material/query、GET /material/list、GET /material/detail |
| 入库 | POST /inbound/create、GET /inbound/query、GET /inbound/details(明细分页,新增)、GET /inbound/export、POST /inbound/batch-excel |
| 出库 | POST /outbound/create(备料)、POST /outbound/general(通用)、GET /outbound/query、GET /outbound/export |
| 库存 | GET /stock/query、GET /stock/zone-summary、POST /stock/lock、POST /stock/unlock、POST /stock/deduct、POST /stock/check |
| 检验 | POST /inspection/create、POST /inspection/batch-flip、GET /inspection/query |
| 区域 | POST /zone/create、POST /zone/update、GET /zone/list、GET /zone/picker |
| 盘点 | POST /stocktake/start、POST /stocktake/record、POST /stocktake/finish、GET /stocktake/query |
| 半成品 | POST /semi/inbound、POST /semi/outbound、GET /semi/query |
| 台账/工单 | GET /api/ledger/query、GET /api/orders |
| 大屏 | GET /api/display/overview(免登录) |
| 内部 API | /api/internal/*:ledger/sync、stock/{check,lock,unlock,deduct,query}、semi/{inbound,outbound}(用 X-API-TOKEN 保护,供 MES/工位调用) |
接口风格现状:均为「按业务模块自由命名」,没有统一的 RESTful 资源风格、没有统一分页/排序/过滤参数规范、没有 OpenAPI 文档。
五、前端页面 / 路由 / 菜单
页面(src/pages/,14 个),路由在 router/index.js:
| 路由 | 页面 | 说明 |
|---|---|---|
/login |
Login.vue | 登录 |
/display |
Display.vue | 免登录大屏(全屏无侧栏) |
/ |
Dashboard.vue | 工作台 |
/inbound |
Inbound.vue | 入库管理(列表页:筛选+分页+导出+「批量入库」按钮) |
/inbound-create |
InboundCreate.vue | 批量入库(新 tab 打开,不进侧栏) |
/outbound |
Outbound.vue | 出库管理(tab:工单备料出库 MES / 通用出库) |
/inventory |
Inventory.vue | 库存查询 |
/inspection |
Inspection.vue | 质量检验 |
/stocktake |
Stocktake.vue | 库存盘点 |
/semi |
Semi.vue | 半成品/成品(3 个 tab:入库 / 查询 / 出库) |
/ledger |
Ledger.vue | 备料台账 |
/zone |
BaseData.vue(mode=zone) | 区域维护 |
/material |
BaseData.vue(mode=material) | 物料档案 |
/change-password |
ChangePassword.vue | 修改密码 |
/users |
UserManage.vue | 账号管理 |
侧栏菜单:硬编码在 MainLayout.vue 的 defaultMenus 数组(11 项),每项带 code(如 inbound:view、user:manage),按后端返回的 permissionCodes 过滤显示。
另:每个页面挂 <PageHelp> 组件,帮助文案统一在 src/help.js。
六、核心业务流(现状)
- 入库:
InboundCreate.vue录单 →POST /inbound/create(事务:入库单 + inventory + 入库明细 原子提交)。结构件按批次;精密件按 SN 逐件(SN 全局查重)。支持 Excel 批量导入(POST /inbound/batch-excel,事务化全成功或全失败,支持 batch/SN 双模板)。 - 出库:统一主表
outbound_order,用outbound_type区分:workorder(工单备料出库):受order_material_ledger台账约束,累计出库 ≤ BOM 需求;MES 不可达时/api/orders优雅降级返回空列表。general(通用出库):退料/样品/报废/发货等不挂工单场景。- 装箱信息(
box_no/box_sn_list/contract_no)直接落在出库主表,未单独建表。
- 库存查询:直接查
inventory表。结构件按批次一条记录、精密件每个 SN 一条记录。 - 质量检验:
/api/inspection/*,记录落在inspection_record。 - 盘点:
stocktake发起 → 记录 → 完成(含「差异写回库存」)。 - 闭环跳转:库存页点「入库单号」→ 跳
/inbound?inboundNo=xxx自动预填查询。
七、权限模型现状(对应问题一)
结论:权限是硬编码的,没有数据化。
已核实的事实:
internal/handler/rbac.go第 20-35 行:角色→权限码映射写死在 Go 代码里的rolePermissionsmap,仅 admin / operator / inspector 三个角色。roleOrDefault()把未知角色统一回退为operator。user表只有字符串字段role,没有角色表、没有菜单表、没有按钮权限表。GET /user/info返回permissionCodes(由 role 经 map 映射得出)。- 后端权限校验只有一个
requireAdmin(),硬编码判断role == "admin"(仅用于账号管理类接口)。 - 前端菜单硬编码在
MainLayout.vue的defaultMenus(11 项,各带code),按permissionCodes做显示/隐藏过滤。 - 不存在:角色维护页面、角色增删改接口、菜单配置管理、按钮级权限。
遗留问题:
rolePermissions中仍保留已废弃的"package:view"(装箱功能已合并进出库主表),属脏数据。
八、已确立的设计约定(用户强约束,重新规划时务必遵守)
-
统一主表原则:同类业务必须用「一张主表 + 类型字段区分」,禁止为新增功能另建独立表。
- 正例:出库用
outbound_type(workorder/general) 区分;装箱字段直接落主表。 - 反例:曾因入库拆多表导致无法全量导出,被明确批评。
- 新增能力优先「主表加字段」+ 配套全量导出。
- 正例:出库用
-
单一职责 + 分页(用户称"互联网思维"):每个页面只做一件事。
- 录入/创建页不得内嵌查询列表;查询/列表必须是独立页面(带查询条件、分页、导出)。
- 已落地范例:入库管理
Inbound.vue(列表页)+ 批量入库InboundCreate.vue(新 tab 打开的录入页,不进侧栏)。
-
数据量意识:任何列表/明细/导出必须先估算数据量,禁止无脑全量加载。
- 列表接口每行只带 count,禁止在列表里对每行加载全部子明细(精密件单可上万 SN)。
- 明细必须懒加载 + 分页(如
GET /inbound/details,默认 50/页)。
-
列表规范(用户最新要求,来自《问题记录.md》):
- 搜索条件要合适的方式:该模糊的模糊、该下拉的下拉;去掉笼统的"关键字"搜索。
- 所有列表增加创建时间字段,展示格式
yyyy-MM-dd HH:mm:ss;搜索条件增加创建时间筛选,默认近 3 个月。 - 所有列表增加主键 ID。
-
协作流程:非琐碎改动必须先给详细方案并给出推荐选项,用户确认后再动手。
九、当前待办问题(《问题记录.md》8 项 + 代码核实结果)
以下每条均已对照实际代码核实,便于规划时直接定位。
一、WMS 与 WMS 客户端
- 缺少角色维护 → 核实:权限硬编码在
rbac.go的 map,无角色表、无维护接口、无页面。 - 缺少角色菜单按钮权限 → 核实:菜单硬编码在
MainLayout.vue,仅做显示过滤;无按钮级权限。
二、物料档案(/material → BaseData.vue mode=material)
- 搜索条件不足 → 核实:目前只有一个"关键字"输入框(
BaseData.vue第 181/238 行),未按物料编码/名称/规格/类型拆分。 - 列表缺创建时间 → 核实:
material表有created_at(Int64 unix 秒),但前端列表未展示、无时间筛选。 - 列表缺主键 ID →
material表主键 id 存在,前端未展示。
三、区域维护(/zone → BaseData.vue mode=zone)
同上三点:zone 表有 created_at/updated_at,前端同样只有"关键字"搜索、无创建时间、无 ID 列。
四、备料台账(/ledger)
- 需要填充假数据以便查看展示效果(表:
order_material_ledger)。
五、半成品/成品(/semi → Semi.vue)
- 内嵌 tab 页叫什么 → 核实:
Semi.vue现有 3 个 tab:「半成品/成品入库」「半成品/成品查询」「半成品出库」(Element Plus 组件为el-tabs,通称"标签页/选项卡")。 - 与菜单「出库管理」的区别与关系 → 需重新规划明确职责边界。
六、库存盘点(/stocktake)
- 发起盘点是否锁全部库存?能否选择盘点全库 / 某个物料? → 需设计(当前
stocktake表结构支持按target_type/material_code/zone_code记录明细,但前端流程未暴露选择能力)。 - 缺少物料分布图:无法查看"哪个物料、在哪个货架、每个多少、一共多少"。
七、质量检验(/inspection)
用户评价"设计胡闹、无法闭环"。核实:
Inspection.vue中导出相关代码数量为 0(确实不能导出)。- 现有字段仅:目标类型、已选清单、检验员、检验结论。
- 缺失:检测说明、不合格说明、检验记录闭环、导出能力。
- 表
inspection_record现有字段:target_typetarget_idmaterial_codeinspection_typestatusresult_valueinspectorremarkcreated_atupdated_at。
八、库存查询(/inventory)
用户评价"设计乱七八糟"。核实到两处关键:
- SN 被直接暴露在主列表:
Inventory.vue第 73 行return row.manageMode === 2 ? row.snCode : row.batchNo,即inventory表每条 SN 一行直接展示。用户主张:库存查询应按物料聚合只显示数量,SN 属子表明细,应点击查看。 - 职责边界未定义:「同批次」与「库存查询」如何分工?用户理解——库存查询 = 查物料数量的地方;出入库管理 = 查自己批次的地方。需重新规划确认。
十、已知技术债与风险
| 项 | 说明 |
|---|---|
| 权限硬编码 | 角色/菜单/权限码全在代码里,加角色或改权限需改代码重新部署 |
| 废弃权限码残留 | rolePermissions 中仍有 package:view |
created_at 类型 |
全库为 Int64 unix 秒,前端 fmtTime 需 *1000;统一 yyyy-MM-dd HH:mm:ss 展示需统一处理 |
| 前端无 TypeScript | 全 JS,无类型约束 |
| 无统一列表组件 | 各页面各自实现筛选/表格/分页/导出,风格与能力不一致(这正是"列表乱"的根因) |
| 无统一 API 层 | 页面内直接 request.get('/xxx'),路径散落 |
| 无接口文档 | 无 OpenAPI;接口命名无统一 RESTful 规范;无统一错误码 |
| 库存查询性能 | 精密件每 SN 一条 inventory 记录,量大时列表与渲染压力大 |
| 前端构建 | 需手动 mv 备份 web/static 再 build(Windows EPERM),无脚本化 |
| Git 状态 | 所有改动均未提交 git(用户从未要求 commit) |
十一、给重新规划者的建议输入
重新规划时建议优先处理(按依赖顺序):
- 先定"列表规范"标准件:统一筛选区(模糊/下拉/日期)、统一列(ID + 创建时间
yyyy-MM-dd HH:mm:ss)、统一分页 + 导出、创建时间默认近 3 个月。可抽为通用列表组件/配置,一次性解决物料档案、区域维护、库存查询等多处问题。 - 权限数据化:建角色表 + 菜单表 + 按钮权限表,取代硬编码 map;前端菜单与按钮权限改为按接口下发。
- 库存查询重构:明确"库存=按物料聚合查数量;SN/批次=子表按需下钻",同时解决性能与职责边界(问题八)。
- 质量检验闭环:补齐检验说明/不合格说明字段、检验记录查询与导出(问题七)。
- 盘点能力:支持选择盘点范围(全库/区域/物料),并新增物料分布图(问题六)。
- 职责边界澄清:半成品/成品 与 出库管理 的关系(问题五)。
务必遵守:第八节的 5 条强约束(统一主表、单一职责+分页、数据量意识、列表规范、先方案后改)。