2025-06-06 14:31:58 +08:00

448 lines
10 KiB
Go

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/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 {
return s.repo.Create(ctx, req)
}
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 s.Tx.Transaction(ctx, func(ctx context.Context) error {
// 先删除该角色的所有权限
err := s.roleMenuService.DeleteByRoleID(ctx, roleID)
if err != nil {
return err
}
// 再添加该角色的所有权限
return s.roleMenuService.Create(ctx, rms)
})
}
func (s *menuService) RefreshCache(ctx context.Context) error {
var res []*system.Menu
key := know.GetManageKey(ctx, know.AllMenus)
getData := func() (any, error) {
return s.repo.All(ctx)
}
return util.GetOrSetCache(ctx, s.Redis, key, util.GetCacheExpire(), getData, &res)
}
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
}