package system import ( "context" "encoding/json" "strconv" "strings" "management/internal/erpserver/model/dto" "management/internal/erpserver/model/system" "management/internal/erpserver/model/view" "management/internal/erpserver/repository" "management/internal/erpserver/service/util" "management/internal/erpserver/service/v1" "management/internal/pkg/know" ) type menuService struct { *v1.Service repo system.MenuRepository roleService v1.RoleService roleMenuService v1.RoleMenuService } func NewMenuService( service *v1.Service, repo system.MenuRepository, roleService v1.RoleService, roleMenuService v1.RoleMenuService, ) v1.MenuService { return &menuService{ Service: service, repo: repo, roleService: roleService, roleMenuService: roleMenuService, } } func (s *menuService) Create(ctx context.Context, req *system.Menu) error { _, err := s.repo.Create(ctx, req) return err } func (s *menuService) Update(ctx context.Context, req *system.Menu) error { return s.repo.Update(ctx, req) } func (s *menuService) Get(ctx context.Context, id int32) (*system.Menu, error) { return s.repo.Get(ctx, id) } func (s *menuService) GetByUrl(ctx context.Context, url string) (*system.Menu, error) { return s.repo.GetByUrl(ctx, url) } func (s *menuService) All(ctx context.Context) ([]*system.Menu, error) { var res []*system.Menu key := know.GetManageKey(ctx, know.AllMenus) err := util.GetOrSetCache(ctx, s.Redis, key, util.GetCacheExpire(), func() (any, error) { return s.repo.All(ctx) }, &res) return res, err } func (s *menuService) ListMenuTree(ctx context.Context) ([]*view.MenuTree, error) { all, err := s.All(ctx) if err != nil { return nil, err } return toListTree(0, all), nil } func (s *menuService) ListByRoleID(ctx context.Context, roleID int32) ([]*dto.OwnerMenuDto, error) { key := know.GetManageKey(ctx, know.OwnerMenus, roleID) bs, err := s.Redis.GetBytes(ctx, key) if err == nil { var res []*dto.OwnerMenuDto if err := json.Unmarshal(bs, &res); err == nil { return res, nil } } return s.SetListByRoleID(ctx, roleID) } func (s *menuService) SetListByRoleID(ctx context.Context, roleID int32) ([]*dto.OwnerMenuDto, error) { key := know.GetManageKey(ctx, know.OwnerMenus, roleID) menus, err := s.listByRoleID(ctx, roleID) if err != nil { return nil, err } res := toOwnerMenuDto(menus) b, err := json.Marshal(res) if err != nil { return nil, err } _ = s.Redis.Set(ctx, key, b, util.GetCacheExpire()) return res, nil } func (s *menuService) ListByRoleIDToMap(ctx context.Context, roleID int32) (map[string]*dto.OwnerMenuDto, error) { key := know.GetManageKey(ctx, know.OwnerMenusMap, roleID) bs, err := s.Redis.GetBytes(ctx, key) if err == nil { var res map[string]*dto.OwnerMenuDto if err := json.Unmarshal(bs, &res); err == nil { return res, nil } } return s.SetListByRoleIDToMap(ctx, roleID) } func (s *menuService) SetListByRoleIDToMap(ctx context.Context, roleID int32) (map[string]*dto.OwnerMenuDto, error) { key := know.GetManageKey(ctx, know.OwnerMenusMap, roleID) menus, err := s.listByRoleID(ctx, roleID) if err != nil { return nil, err } res := toOwnerMenuDtoMap(menus) b, err := json.Marshal(res) if err != nil { return nil, err } _ = s.Redis.Set(ctx, key, b, util.GetCacheExpire()) return res, nil } func (s *menuService) OwerMenus(ctx context.Context, roleID int32) ([]*dto.MenuUIDto, error) { key := know.GetManageKey(ctx, know.AdminMenus, roleID) bs, err := s.Redis.GetBytes(ctx, key) if err == nil { var res []*dto.MenuUIDto if err := json.Unmarshal(bs, &res); err == nil { return res, nil } } return s.SetOwerMenus(ctx, roleID) } func (s *menuService) SetOwerMenus(ctx context.Context, roleID int32) ([]*dto.MenuUIDto, error) { key := know.GetManageKey(ctx, know.AdminMenus, roleID) menus, err := s.listByRoleID(ctx, roleID) if err != nil { return nil, err } res := convertToUITree(menus, 0) b, err := json.Marshal(res) if err != nil { return nil, err } _ = s.Redis.Set(ctx, key, b, util.GetCacheExpire()) return res, nil } func (s *menuService) MenuViewData(ctx context.Context, roleID int32) ([]*dto.SetMenuDto, error) { // 获取该用户已经有的权限 hs, err := s.listByRoleID(ctx, roleID) if err != nil { return nil, err } all, err := s.All(ctx) if err != nil { return nil, err } return toSetMenuTree(all, hs, 0), nil } func (s *menuService) SetRoleMenu(ctx context.Context, roleID int32, rms []*system.RoleMenu) error { // 开启事务 return repository.Transaction(ctx, s.Log, func(c context.Context) error { // 先删除该角色的所有权限 err := s.roleMenuService.DeleteByRoleID(c, roleID) if err != nil { return err } // 再添加该角色的所有权限 return s.roleMenuService.Create(c, rms) }) } func (s *menuService) RefreshCache(ctx context.Context) error { key := know.GetManageKey(ctx, know.AllMenus) return s.Redis.Del(ctx, key) } func (s *menuService) RebuildParentPath(ctx context.Context) error { return s.repo.RebuildParentPath(ctx) } func (s *menuService) Tree(ctx context.Context, id int32) ([]*view.LayuiTree, error) { all, err := s.All(ctx) if err != nil { return nil, err } return s.toTree(id, all), nil } func (s *menuService) XmSelectTree(ctx context.Context, id int32) ([]*view.XmSelectTree, error) { all, err := s.All(ctx) if err != nil { return nil, err } return s.toXmSelectTree(id, all), nil } // listByRoleID 获取该角色所拥有的菜单集合 func (s *menuService) listByRoleID(ctx context.Context, roleID int32) ([]*system.Menu, error) { role, err := s.roleService.Get(ctx, roleID) if err != nil { return nil, err } res, err := s.repo.All(ctx) if err != nil { return nil, err } if role.Vip { return res, nil } // 通过角色获取所拥有的权限 roleMenus, err := s.roleMenuService.ListByRoleID(ctx, roleID) if err != nil { return nil, err } return findMenu(roleMenus, res), nil } func (s *menuService) toTree(parentId int32, data []*system.Menu) []*view.LayuiTree { var res []*view.LayuiTree for _, v := range data { if v.ParentID == parentId { item := view.LayuiTree{} item.ID = strconv.FormatInt(int64(v.ID), 10) item.Title = v.Name item.Children = s.toTree(v.ID, data) if v.ParentID == 0 { item.Spread = true } res = append(res, &item) } } return res } func (s *menuService) toXmSelectTree(parentId int32, data []*system.Menu) []*view.XmSelectTree { var res []*view.XmSelectTree for _, v := range data { if v.ParentID == parentId { item := view.XmSelectTree{ Name: v.Name, Value: strconv.FormatInt(int64(v.ID), 10), Children: s.toXmSelectTree(v.ID, data), } res = append(res, &item) } } return res } func findMenu(rms []*system.RoleMenu, ms []*system.Menu) []*system.Menu { menuMap := make(map[int32]*system.Menu) for _, m := range ms { menuMap[m.ID] = m } var res []*system.Menu for _, rm := range rms { if m, ok := menuMap[rm.MenuID]; ok { res = append(res, m) } } return res //var res []*system.Menu //for _, rm := range rms { // for _, m := range ms { // if rm.MenuID == m.ID { // res = append(res, m) // } // } //} //return res } func toOwnerMenuDto(ms []*system.Menu) []*dto.OwnerMenuDto { var res []*dto.OwnerMenuDto for _, m := range ms { res = append(res, &dto.OwnerMenuDto{ ID: m.ID, DisplayName: m.DisplayName, Url: m.Url, ParentID: m.ParentID, Avatar: m.Avatar, Style: m.Style, IsList: m.IsList, }) } return res } func toOwnerMenuDtoMap(ms []*system.Menu) map[string]*dto.OwnerMenuDto { res := make(map[string]*dto.OwnerMenuDto) for _, m := range ms { res[m.Url] = &dto.OwnerMenuDto{ ID: m.ID, DisplayName: m.DisplayName, Url: m.Url, ParentID: m.ParentID, Avatar: m.Avatar, Style: m.Style, IsList: m.IsList, } } return res } func convertToUITree(data []*system.Menu, parentID int32) []*dto.MenuUIDto { var root []*dto.MenuUIDto for _, item := range data { if item.ParentID == parentID { if item.IsList { temp := &dto.MenuUIDto{ ID: strings.ToLower(item.Url), Title: item.DisplayName, Icon: item.Avatar, Type: 1, OpenType: "_iframe", // OpenType: "_component", Href: item.Url, } root = append(root, temp) } else { temp := &dto.MenuUIDto{ ID: strconv.Itoa(int(item.ID)), Title: item.DisplayName, Icon: item.Avatar, Type: 0, } temp.Children = convertToUITree(data, item.ID) root = append(root, temp) } } } return root } func toSetMenuTree(data []*system.Menu, ids []*system.Menu, parentID int32) []*dto.SetMenuDto { var res []*dto.SetMenuDto for _, v := range data { if v.ParentID == parentID { isSelect := hasValueInArray(ids, v.ID) if v.IsList { item := dto.SetMenuDto{ ID: v.ID, Name: v.DisplayName, Link: v.Type, IsList: v.IsList, IsSelect: isSelect, } item.Items = []*dto.SetMenuDto{ { ID: v.ID, Name: "列表", Link: "btn", IsList: false, IsSelect: isSelect, Items: toSetMenuTree(data, ids, v.ID), }, } item.Items = append(item.Items, toSetMenuTree(data, ids, v.ID)...) res = append(res, &item) } else { item := dto.SetMenuDto{ ID: v.ID, Name: v.DisplayName, Link: v.Type, IsList: v.IsList, IsSelect: isSelect, Items: toSetMenuTree(data, ids, v.ID), } res = append(res, &item) } } } return res } func hasValueInArray(data []*system.Menu, id int32) bool { for _, v := range data { if v.ID == id { return true } } return false } func toListTree(parentId int32, data []*system.Menu) []*view.MenuTree { var res []*view.MenuTree for _, v := range data { if v.ParentID == parentId { item := view.MenuTree{} item.ID = v.ID item.Name = v.Name item.DisplayName = v.DisplayName item.Url = v.Url item.Type = v.Type item.ParentID = v.ParentID item.ParentPath = v.ParentPath item.Avatar = v.Avatar item.Style = v.Style item.Visible = v.Visible item.IsList = v.IsList item.Status = v.Status item.Sort = v.Sort item.CreatedAt = v.CreatedAt item.UpdatedAt = v.UpdatedAt item.Children = toListTree(v.ID, data) res = append(res, &item) } } return res }