feat: 完成产线与仓储系统多模块迭代升级

本次迭代覆盖MES与WMS核心业务:
1. 新增接驳台托盘传感器读取与AGV对接能力
2. 完善工单排产、备料流程与权限体系拆分
3. 优化看板接口与前端路由、样式
4. 新增操作日志、库存盘点与角色保护逻辑
5. 修复代理地址、BOM保存等已知问题
This commit is contained in:
SunYF
2026-09-04 14:18:53 +08:00
parent c1fc6d32b2
commit b6799c9de4
138 changed files with 20613 additions and 2220 deletions
@@ -2,6 +2,7 @@ package handler
import (
"net/http"
"strconv"
"strings"
"bj_power_wms/ent"
@@ -39,6 +40,8 @@ var seedPermissions = []seedPerm{
{"material:view", "物料档案", "MENU", "/material", "Goods", 100, ""},
{"user:manage", "账号管理", "MENU", "/users", "EditPen", 110, ""},
{"role:manage", "角色管理", "MENU", "/roles", "Key", 120, ""},
{"eventlog:manage", "操作日志", "MENU", "/event-log", "Clock", 130, ""},
{"agv:manage", "AGV配送", "MENU", "/agv", "Van", 135, ""},
// ===== 按钮权限 =====
{"inbound:create", "批量入库", "BUTTON", "", "", 200, "inbound:view"},
{"inbound:import", "Excel导入", "BUTTON", "", "", 201, "inbound:view"},
@@ -64,6 +67,7 @@ var seedPermissions = []seedPerm{
{"role:create", "新增角色", "BUTTON", "", "", 270, "role:manage"},
{"role:edit", "编辑角色", "BUTTON", "", "", 271, "role:manage"},
{"role:delete", "删除角色", "BUTTON", "", "", 272, "role:manage"},
{"agv:dispatch", "下发AGV", "BUTTON", "", "", 280, "agv:manage"},
// 注:导出权限已按菜单拆分(inbound/outbound/inspection/inventory:export),
// 不再使用全局 *:export,以更精细地控制“谁能在哪个菜单导出”。
}
@@ -196,6 +200,11 @@ func seedRbacHandler(ctx *svc.ServiceContext) http.HandlerFunc {
// 清理已废弃的全局 *:export 权限行(迁移后无角色引用,幂等)
_, _ = ctx.EntClient.Permission.Delete().Where(permission.CodeEQ("*:export")).Exec(ctx0())
// 幂等 seed 只在发生真实变更(新增权限/角色/绑定历史用户)时记录日志,避免每次页面加载刷屏
if createdP > 0 || createdR > 0 || bound > 0 {
ctx.EventLog.Write(ctx0(), "rbac.seed", r.Header.Get("X-Username"), "rbac", "",
"RBAC 种子初始化", map[string]any{"permissions": createdP, "roles": createdR, "bound": bound})
}
logx.Infof("rbac seed: 新增权限 %d 条、角色 %d 个、绑定历史用户 %d 个", createdP, createdR, bound)
ok(w, map[string]any{"createdPermissions": createdP, "createdRoles": createdR, "boundUsers": bound})
})
@@ -213,6 +222,25 @@ func listRolesHandler(ctx *svc.ServiceContext) http.HandlerFunc {
})
}
// roleOptionsHandler GET /api/roles/options 角色轻量选项(供账号管理页下拉选择角色)
// 与角色管理页的 /api/roles 解耦:仅需 user:manage 即可读,不要求 role:manage
func roleOptionsHandler(ctx *svc.ServiceContext) http.HandlerFunc {
return requirePerm(ctx, "user:manage", func(w http.ResponseWriter, r *http.Request) {
list, err := ctx.EntClient.Role.Query().Order(ent.Asc("id")).All(ctx0())
if err != nil {
fail(w, http.StatusInternalServerError, err.Error())
return
}
out := make([]map[string]any, 0, len(list))
for _, rl := range list {
out = append(out, map[string]any{
"id": rl.ID, "code": rl.Code, "name": rl.Name,
})
}
ok(w, map[string]any{"list": out})
})
}
// createRoleHandler POST /api/roles 新增角色
func createRoleHandler(ctx *svc.ServiceContext) http.HandlerFunc {
return requirePerm(ctx, "role:create", func(w http.ResponseWriter, r *http.Request) {
@@ -243,6 +271,8 @@ func createRoleHandler(ctx *svc.ServiceContext) http.HandlerFunc {
fail(w, http.StatusInternalServerError, err.Error())
return
}
ctx.EventLog.Write(ctx0(), "role.create", r.Header.Get("X-Username"), "role", strconv.Itoa(rl.ID),
"新增角色 "+req.Name+"("+req.Code+")", map[string]any{"count": len(codes)})
ok(w, rl)
})
}
@@ -286,6 +316,8 @@ func updateRoleHandler(ctx *svc.ServiceContext) http.HandlerFunc {
fail(w, http.StatusInternalServerError, err.Error())
return
}
ctx.EventLog.Write(ctx0(), "role.update", r.Header.Get("X-Username"), "role", strconv.Itoa(req.ID),
"编辑角色 "+target.Name+"("+target.Code+")", map[string]any{"permissionCodes": rl.PermissionCodes})
ok(w, rl)
})
}
@@ -313,6 +345,8 @@ func deleteRoleHandler(ctx *svc.ServiceContext) http.HandlerFunc {
fail(w, http.StatusInternalServerError, err.Error())
return
}
ctx.EventLog.Write(ctx0(), "role.delete", r.Header.Get("X-Username"), "role", strconv.Itoa(req.ID),
"删除角色 "+target.Name+"("+target.Code+")", nil)
ok(w, nil)
})
}