package agent import ( "context" "slices" "git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/consts" "git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/dao" "git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/library/contexts" "git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/library/rolepolicy" "git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/library/xgorm/handler" "git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/model" "git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/model/entity" "git.5iot.com/iotlcm-public/iotlcm-admin-svr/internal/service" "github.com/gogf/gf/v2/util/gconv" ) type sAgentMenu struct { *agentBase } func NewAgentMenu() *sAgentMenu { return &sAgentMenu{ agentBase: newAgentBase(), } } func init() { service.RegisterAgentMenu(NewAgentMenu()) } // AllowedMenuIdsByDeptRole 获取当前机构允许的菜单ID func (s *sAgentMenu) AllowedMenuIdsByDeptRole(ctx context.Context, deptId int64) (menuIds []int64, err error) { if err = s.ensureDeptInScope(ctx, deptId); err != nil { return nil, err } var dept *entity.SysDept err = service.SysDept().Model(ctx, &handler.Option{FilterTenant: true, FilterAuth: false}). Where(dao.SysDept.Columns().DeptId, deptId). Scan(&dept) if err != nil { return nil, err } if dept == nil || dept.DeptRole == 0 { return []int64{}, nil } if dept.DeptRole == consts.SuperAdminRoleId { return s.allMenuIds(ctx) } roleMenus, err := service.SysRole().GetRoleListMenu(ctx, []int64{dept.DeptRole}) if err != nil { return nil, err } for _, item := range roleMenus { menuIds = append(menuIds, item.MenuId) } slices.Sort(menuIds) menuIds = slices.Compact(menuIds) return rolepolicy.RestrictMenus(ctx, dept.TenantId, dept.DeptId, menuIds) } func (s *sAgentMenu) allMenuIds(ctx context.Context) (menuIds []int64, err error) { var menus []*entity.SysMenu err = service.SysMenu().Model(ctx). Where(dao.SysMenu.Columns().Status, consts.SysMenuStatusNormal). Order(dao.SysMenu.Columns().OrderNum, "ASC"). Scan(&menus) if err != nil { return nil, err } for _, item := range menus { menuIds = append(menuIds, item.MenuId) } slices.Sort(menuIds) return slices.Compact(menuIds), nil } func (s *sAgentMenu) getRoleById(ctx context.Context, roleId int64) (role *entity.SysRole, err error) { err = service.SysRole().Model(ctx, &handler.Option{FilterTenant: true, FilterAuth: false}). Where(dao.SysRole.Columns().RoleId, roleId). Scan(&role) return role, err } // filterMenuIdsByAllowed 筛选出当前机构允许的菜单ID func (s *sAgentMenu) filterMenuIdsByAllowed(ctx context.Context, deptId int64, menuIds []int64) (res []int64, err error) { if deptId == 0 { deptId = contexts.GetDeptId(ctx) } allowed, err := s.AllowedMenuIdsByDeptRole(ctx, deptId) if err != nil { return nil, err } allowed, err = s.withMenuAncestors(ctx, allowed) if err != nil { return nil, err } allowedMap := make(map[int64]struct{}, len(allowed)) for _, menuId := range allowed { allowedMap[menuId] = struct{}{} } for _, menuId := range menuIds { if _, ok := allowedMap[menuId]; ok { res = append(res, menuId) } } slices.Sort(res) return slices.Compact(res), nil } func (s *sAgentMenu) AllowedMenuTree(ctx context.Context, deptId int64) (tree []*model.SysMenuTreeModel, menuIds []int64, err error) { deptId = contexts.GetDeptId(ctx) menuIds, err = s.AllowedMenuIdsByDeptRole(ctx, deptId) if err != nil { return nil, nil, err } if len(menuIds) == 0 && !contexts.IsSuperAdmin(ctx) { return []*model.SysMenuTreeModel{}, []int64{}, nil } menuIds, err = s.withMenuAncestors(ctx, menuIds) if err != nil { return nil, nil, err } mod := service.SysMenu().Model(ctx) if !contexts.IsSuperAdmin(ctx) { mod = mod.WhereIn(dao.SysMenu.Columns().MenuId, menuIds) } var menus []*entity.SysMenu err = mod.Where(dao.SysMenu.Columns().Status, consts.SysMenuStatusNormal). Order(dao.SysMenu.Columns().OrderNum, "ASC"). Scan(&menus) if err != nil { return nil, nil, err } tree = s.buildMenuList(menus) return tree, menuIds, nil } func (s *sAgentMenu) withMenuAncestors(ctx context.Context, menuIds []int64) ([]int64, error) { seen := make(map[int64]struct{}, len(menuIds)) queue := append([]int64{}, menuIds...) for _, menuId := range menuIds { seen[menuId] = struct{}{} } for len(queue) > 0 { var menus []*entity.SysMenu err := service.SysMenu().Model(ctx). WhereIn(dao.SysMenu.Columns().MenuId, queue). Scan(&menus) if err != nil { return nil, err } queue = queue[:0] for _, menu := range menus { if menu.ParentId == 0 { continue } if _, ok := seen[menu.ParentId]; ok { continue } seen[menu.ParentId] = struct{}{} queue = append(queue, menu.ParentId) } } res := make([]int64, 0, len(seen)) for menuId := range seen { res = append(res, menuId) } slices.Sort(res) return res, nil } func (s *sAgentMenu) buildMenuList(menus []*entity.SysMenu) (list []*model.SysMenuTreeModel) { for _, menu := range menus { list = append(list, &model.SysMenuTreeModel{ Title: menu.MenuName, Key: gconv.String(menu.MenuId), ParentId: menu.ParentId, MenuId: menu.MenuId, MenuName: menu.MenuName, MenuType: menu.MenuType, Perms: menu.Perms, }) } return list } func (s *sAgentMenu) buildMenuTree(parentId int64, menus []*entity.SysMenu) (tree []*model.SysMenuTreeModel) { for _, menu := range menus { if menu.ParentId != parentId { continue } item := &model.SysMenuTreeModel{ Title: menu.MenuName, Key: gconv.String(menu.MenuId), ParentId: menu.ParentId, MenuId: menu.MenuId, MenuName: menu.MenuName, MenuType: menu.MenuType, Perms: menu.Perms, } item.Children = s.buildMenuTree(menu.MenuId, menus) tree = append(tree, item) } if parentId == 0 && len(tree) == 0 { for _, menu := range menus { item := &model.SysMenuTreeModel{ Title: menu.MenuName, Key: gconv.String(menu.MenuId), ParentId: menu.ParentId, MenuId: menu.MenuId, MenuName: menu.MenuName, MenuType: menu.MenuType, Perms: menu.Perms, } item.Children = s.buildMenuTree(menu.MenuId, menus) tree = append(tree, item) } } return tree }