Files
bj_power/bj_power_mes/internal/handler/perm.go
T
SunYF 05b0b8a909 feat: 完成客户第12条需求+多系统改造
1. 新增预警表添加工单号字段,支持按工单号检索预警
2. 添加工单过滤在制品/绩效报表/预警中心查询
3. 补全WMS台账字段口径与权限配置
4. 修复备料单与数量不符处理流程
5. 新增配送进度/库位联动/自动出库功能
6. 修复AGV配送状态更新逻辑
7. 优化退料与库存管理细节
2026-09-19 17:04:58 +08:00

118 lines
5.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package handler
import (
"net/http"
"strings"
"bj_power_mes/common/httpx"
"bj_power_mes/internal/svc"
)
// pathPermMap 请求方法+路径 → 所需按钮级权限码(块2:后端接口兜底校验)。
// 路径中的 :id 统一以 * 结尾匹配。
var pathPermMap = map[string]string{
"POST:/api/v1/product-types": "produce.product:add",
"PUT:/api/v1/product-types": "produce.product:edit",
"DELETE:/api/v1/product-types/*": "produce.product:delete",
"POST:/api/v1/work-orders": "produce.workorder:add",
"PUT:/api/v1/work-orders": "produce.workorder:edit",
"POST:/api/v1/work-orders/status": "produce.workorder:edit",
"POST:/api/v1/work-orders/auto-schedule": "produce.workorder:dailyplan",
"DELETE:/api/v1/work-orders/*": "produce.workorder:delete",
"POST:/api/v1/daily-plans": "produce.workorder:dailyplan",
"PUT:/api/v1/bom": "produce.bom:edit",
"POST:/api/v1/bom/item/delete": "produce.bom:edit",
"POST:/api/v1/bom/import": "produce.bom:edit",
"POST:/api/v1/material-requests/generate": "produce.material:generate",
"POST:/api/v1/material-requests/auto-outbound": "produce.material:outbound",
// 数量不符处理(produce.qty 菜单下:补发/退库/调整关闭)
"POST:/api/v1/qty-reports/handle": "produce.qty:handle",
"POST:/api/v1/plc/send-process": "produce.plc:send",
"POST:/api/v1/process-flows": "produce.processflow:add",
"POST:/api/v1/process-flows/status": "produce.processflow:edit",
"DELETE:/api/v1/process-flows/*": "produce.processflow:delete",
"POST:/api/v1/process-flows/upload": "produce.processflow:upload",
"POST:/api/v1/process-steps": "produce.processflow:edit",
"POST:/api/v1/stations": "produce.station:edit",
"DELETE:/api/v1/stations/*": "produce.station:delete",
// 过程巡检汇总生成《工序间检验记录》(巡检终端操作域)
"POST:/api/v1/inspections/generate-inter-process": "sys.inspect:process",
// 质量检验处置(过程检/完工检不合格处置 退货/返修/退换)
"POST:/api/v1/quality/disposal": "produce.quality:edit",
// 附件中心(sys.attachment 菜单下):删除 / 归档清理属管理动作;
// 列表/预览/下载不设按钮门槛(有菜单权限即可查阅)
"POST:/api/v1/attachment/delete": "sys.attachment:manage",
"POST:/api/v1/attachment/archive": "sys.attachment:manage",
// 装机绑定(报工前扫料/撤销,属报工操作域)
"POST:/api/v1/binds": "produce.scan",
"POST:/api/v1/binds/remove": "produce.scan",
// 账号管理(拆分自原 sys.rbac:usersys.account 菜单下增/改/删)
"POST:/api/v1/users": "sys.account:add",
"PUT:/api/v1/users": "sys.account:edit",
"DELETE:/api/v1/users/*": "sys.account:delete",
// 角色管理(拆分自原 sys.rbac:role/permsys.role 菜单下增/改/删)
"POST:/api/v1/roles": "sys.role:add",
"PUT:/api/v1/roles": "sys.role:edit",
"DELETE:/api/v1/roles/*": "sys.role:delete",
"POST:/api/v1/permissions": "sys.role:perm",
"PUT:/api/v1/permissions": "sys.role:perm",
"DELETE:/api/v1/permissions/*": "sys.role:perm",
}
// userHasPerm 校验当前登录用户是否拥有某权限码(SUPER_ADMIN 或 * 放行)。
// 用户ID 使用 uidFromRequest:优先取 context,缺失时回退解析 Authorization token。
func userHasPerm(r *http.Request, svcCtx *svc.ServiceContext, code string) bool {
if code == "" {
return true
}
userId := uidFromRequest(r, svcCtx)
if userId <= 0 {
return false
}
usr, err := svcCtx.EntClient.User.Get(r.Context(), userId)
if err != nil {
return false
}
role, err := svcCtx.EntClient.Role.Get(r.Context(), usr.RoleId)
if err != nil {
return false
}
if role.Code == "SUPER_ADMIN" {
return true
}
for _, c := range role.PermissionCodes {
if c == "*" || c == code {
return true
}
}
return false
}
// permissionGuard 按钮级权限后端兜底中间件(仅对写操作映射表内的路径生效)
func permissionGuard(svcCtx *svc.ServiceContext) func(http.HandlerFunc) http.HandlerFunc {
return func(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
code, ok := pathPerm(r.Method, r.URL.Path)
if ok && !userHasPerm(r, svcCtx, code) {
httpx.FailHTTP(w, http.StatusForbidden, "无操作权限:"+code)
return
}
next(w, r)
}
}
}
// pathPerm 先按完整路径精确匹配;未命中时把末段替换为 * 再匹配(用于 :id 结尾的路径)。
func pathPerm(method, path string) (string, bool) {
key := method + ":" + strings.TrimSuffix(path, "/")
if code, ok := pathPermMap[key]; ok {
return code, true
}
segs := strings.Split(key, "/")
if len(segs) > 0 {
segs[len(segs)-1] = "*"
}
code, ok := pathPermMap[strings.Join(segs, "/")]
return code, ok
}