You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

326 lines
9.3 KiB

3 years ago
/*
* @desc:菜单处理
*
*
* @Date: 2022/3/11 15:07
*/
package service
import (
"context"
"fmt"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/util/gconv"
"tyj_admin/api/v1/system"
"tyj_admin/internal/consts"
"tyj_admin/internal/dao"
"tyj_admin/internal/model"
"tyj_admin/internal/model/do"
"tyj_admin/internal/model/entity"
"tyj_admin/library/liberr"
)
type IRule interface {
GetIsMenuList(ctx context.Context) ([]*model.SysAuthRuleInfoRes, error)
GetMenuList(ctx context.Context) (list []*model.SysAuthRuleInfoRes, err error)
GetIsButtonList(ctx context.Context) ([]*model.SysAuthRuleInfoRes, error)
Add(ctx context.Context, req *system.RuleAddReq) (err error)
Get(ctx context.Context, id uint) (rule *entity.SysAuthRule, err error)
GetMenuRoles(ctx context.Context, id uint) (roleIds []uint, err error)
Update(ctx context.Context, req *system.RuleUpdateReq) (err error)
GetMenuListSearch(ctx context.Context, req *system.RuleSearchReq) (res []*model.SysAuthRuleInfoRes, err error)
GetMenuListTree(pid uint, list []*model.SysAuthRuleInfoRes) []*model.SysAuthRuleTreeRes
DeleteMenuByIds(ctx context.Context, ids []int) (err error)
}
type ruleImpl struct {
}
var ruleService = ruleImpl{}
func Rule() IRule {
return &ruleService
}
func (s *ruleImpl) GetMenuListSearch(ctx context.Context, req *system.RuleSearchReq) (res []*model.SysAuthRuleInfoRes, err error) {
err = g.Try(ctx, func(ctx context.Context) {
m := dao.SysAuthRule.Ctx(ctx)
if req.Title != "" {
m = m.Where("title like ?", "%"+req.Title+"%")
}
if req.Component != "" {
m = m.Where("component like ?", "%"+req.Component+"%")
}
err = m.Fields(model.SysAuthRuleInfoRes{}).Order("weigh desc,id asc").Scan(&res)
liberr.ErrIsNil(ctx, err, "获取菜单失败")
})
return
}
// GetIsMenuList 获取isMenu=0|1
func (s *ruleImpl) GetIsMenuList(ctx context.Context) ([]*model.SysAuthRuleInfoRes, error) {
list, err := s.GetMenuList(ctx)
if err != nil {
return nil, err
}
var gList = make([]*model.SysAuthRuleInfoRes, 0, len(list))
for _, v := range list {
if v.MenuType == 0 || v.MenuType == 1 {
gList = append(gList, v)
}
}
return gList, nil
}
// GetMenuList 获取所有菜单
func (s *ruleImpl) GetMenuList(ctx context.Context) (list []*model.SysAuthRuleInfoRes, err error) {
cache := Cache()
//从缓存获取
iList := cache.GetOrSetFuncLock(ctx, consts.CacheSysAuthMenu, s.getMenuListFromDb, 0, consts.CacheSysAuthTag)
if iList != nil {
err = gconv.Struct(iList, &list)
liberr.ErrIsNil(ctx, err)
}
return
}
// 从数据库获取所有菜单
func (s *ruleImpl) getMenuListFromDb(ctx context.Context) (value interface{}, err error) {
err = g.Try(ctx, func(ctx context.Context) {
var v []*model.SysAuthRuleInfoRes
//从数据库获取
err = dao.SysAuthRule.Ctx(ctx).
Fields(model.SysAuthRuleInfoRes{}).Order("weigh desc,id asc").Scan(&v)
liberr.ErrIsNil(ctx, err, "获取菜单数据失败")
value = v
})
return
}
// GetIsButtonList 获取所有按钮isMenu=2 菜单列表
func (s *ruleImpl) GetIsButtonList(ctx context.Context) ([]*model.SysAuthRuleInfoRes, error) {
list, err := s.GetMenuList(ctx)
if err != nil {
return nil, err
}
var gList = make([]*model.SysAuthRuleInfoRes, 0, len(list))
for _, v := range list {
if v.MenuType == 2 {
gList = append(gList, v)
}
}
return gList, nil
}
// Add 添加菜单
func (s *ruleImpl) Add(ctx context.Context, req *system.RuleAddReq) (err error) {
if s.menuNameExists(ctx, req.Name, 0) {
err = gerror.New("接口规则已经存在")
return
}
err = g.DB().Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
err = g.Try(ctx, func(ctx context.Context) {
//菜单数据
data := do.SysAuthRule{
Pid: req.Pid,
Name: req.Name,
Title: req.Title,
Icon: req.Icon,
Condition: req.Condition,
Remark: req.Remark,
MenuType: req.MenuType,
Weigh: req.Weigh,
IsHide: req.IsHide,
Path: req.Path,
Component: req.Component,
IsLink: req.IsLink,
IsIframe: req.IsIframe,
IsCached: req.IsCached,
Redirect: req.Redirect,
IsAffix: req.IsAffix,
LinkUrl: req.LinkUrl,
}
ruleId, e := dao.SysAuthRule.Ctx(ctx).TX(tx).InsertAndGetId(data)
liberr.ErrIsNil(ctx, e, "添加菜单失败")
e = s.BindRoleRule(ctx, ruleId, req.Roles)
liberr.ErrIsNil(ctx, e, "添加菜单失败")
})
return err
})
if err == nil {
// 删除相关缓存
Cache().Remove(ctx, consts.CacheSysAuthMenu)
}
return
}
// 检查菜单规则是否存在
func (s *ruleImpl) menuNameExists(ctx context.Context, name string, id uint) bool {
m := dao.SysAuthRule.Ctx(ctx).Where("name=?", name)
if id != 0 {
m = m.Where("id!=?", id)
}
c, err := m.Fields(dao.SysAuthRule.Columns().Id).Limit(1).One()
if err != nil {
g.Log().Error(ctx, err)
return false
}
return !c.IsEmpty()
}
// BindRoleRule 绑定角色权限
func (s *ruleImpl) BindRoleRule(ctx context.Context, ruleId interface{}, roleIds []uint) (err error) {
err = g.Try(ctx, func(ctx context.Context) {
enforcer, e := CasbinEnforcer(ctx)
liberr.ErrIsNil(ctx, e)
for _, roleId := range roleIds {
_, err = enforcer.AddPolicy(fmt.Sprintf("%d", roleId), fmt.Sprintf("%d", ruleId), "All")
liberr.ErrIsNil(ctx, err)
}
})
return
}
func (s *ruleImpl) Get(ctx context.Context, id uint) (rule *entity.SysAuthRule, err error) {
err = g.Try(ctx, func(ctx context.Context) {
err = dao.SysAuthRule.Ctx(ctx).WherePri(id).Scan(&rule)
liberr.ErrIsNil(ctx, err, "获取菜单失败")
})
return
}
func (s *ruleImpl) GetMenuRoles(ctx context.Context, id uint) (roleIds []uint, err error) {
err = g.Try(ctx, func(ctx context.Context) {
enforcer, e := CasbinEnforcer(ctx)
liberr.ErrIsNil(ctx, e)
policies := enforcer.GetFilteredNamedPolicy("p", 1, gconv.String(id))
for _, policy := range policies {
roleIds = append(roleIds, gconv.Uint(policy[0]))
}
})
return
}
func (s *ruleImpl) Update(ctx context.Context, req *system.RuleUpdateReq) (err error) {
if s.menuNameExists(ctx, req.Name, req.Id) {
err = gerror.New("接口规则已经存在")
return
}
err = g.DB().Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
err = g.Try(ctx, func(ctx context.Context) {
//菜单数据
data := do.SysAuthRule{
Pid: req.Pid,
Name: req.Name,
Title: req.Title,
Icon: req.Icon,
Condition: req.Condition,
Remark: req.Remark,
MenuType: req.MenuType,
Weigh: req.Weigh,
IsHide: req.IsHide,
Path: req.Path,
Component: req.Component,
IsLink: req.IsLink,
IsIframe: req.IsIframe,
IsCached: req.IsCached,
Redirect: req.Redirect,
IsAffix: req.IsAffix,
LinkUrl: req.LinkUrl,
}
_, e := dao.SysAuthRule.Ctx(ctx).TX(tx).WherePri(req.Id).Update(data)
liberr.ErrIsNil(ctx, e, "添加菜单失败")
e = s.UpdateRoleRule(ctx, req.Id, req.Roles)
liberr.ErrIsNil(ctx, e, "添加菜单失败")
})
return err
})
if err == nil {
// 删除相关缓存
Cache().Remove(ctx, consts.CacheSysAuthMenu)
}
return
}
func (s *ruleImpl) UpdateRoleRule(ctx context.Context, ruleId uint, roleIds []uint) (err error) {
err = g.Try(ctx, func(ctx context.Context) {
enforcer, e := CasbinEnforcer(ctx)
liberr.ErrIsNil(ctx, e)
//删除旧权限
_, e = enforcer.RemoveFilteredPolicy(1, gconv.String(ruleId))
liberr.ErrIsNil(ctx, e)
// 添加新权限
roleIdsStrArr := gconv.Strings(roleIds)
for _, v := range roleIdsStrArr {
_, e = enforcer.AddPolicy(v, gconv.String(ruleId), "All")
liberr.ErrIsNil(ctx, e)
}
})
return
}
func (s *ruleImpl) GetMenuListTree(pid uint, list []*model.SysAuthRuleInfoRes) []*model.SysAuthRuleTreeRes {
tree := make([]*model.SysAuthRuleTreeRes, 0, len(list))
for _, menu := range list {
if menu.Pid == pid {
t := &model.SysAuthRuleTreeRes{
SysAuthRuleInfoRes: menu,
}
child := s.GetMenuListTree(menu.Id, list)
if child != nil {
t.Children = child
}
tree = append(tree, t)
}
}
return tree
}
// DeleteMenuByIds 删除菜单
func (s *ruleImpl) DeleteMenuByIds(ctx context.Context, ids []int) (err error) {
var list []*model.SysAuthRuleInfoRes
list, err = s.GetMenuList(ctx)
if err != nil {
return
}
childrenIds := make([]int, 0, len(list))
for _, id := range ids {
rules := s.FindSonByParentId(list, gconv.Uint(id))
for _, child := range rules {
childrenIds = append(childrenIds, gconv.Int(child.Id))
}
}
ids = append(ids, childrenIds...)
err = g.DB().Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
return g.Try(ctx, func(ctx context.Context) {
_, err = dao.SysAuthRule.Ctx(ctx).Where("id in (?)", ids).Delete()
liberr.ErrIsNil(ctx, err, "删除失败")
//删除权限
enforcer, err := CasbinEnforcer(ctx)
liberr.ErrIsNil(ctx, err)
for _, v := range ids {
_, err = enforcer.RemoveFilteredPolicy(1, gconv.String(v))
liberr.ErrIsNil(ctx, err)
}
// 删除相关缓存
Cache().Remove(ctx, consts.CacheSysAuthMenu)
})
})
return
}
func (s *ruleImpl) FindSonByParentId(list []*model.SysAuthRuleInfoRes, pid uint) []*model.SysAuthRuleInfoRes {
children := make([]*model.SysAuthRuleInfoRes, 0, len(list))
for _, v := range list {
if v.Pid == pid {
children = append(children, v)
fChildren := s.FindSonByParentId(list, v.Id)
children = append(children, fChildren...)
}
}
return children
}