diff --git a/api/v1/system/sys_auth_rule.go b/api/v1/system/sys_auth_rule.go index 5cdf29c..16e0a04 100644 --- a/api/v1/system/sys_auth_rule.go +++ b/api/v1/system/sys_auth_rule.go @@ -13,6 +13,18 @@ import ( "github.com/tiger1103/gfast/v3/internal/app/system/model/entity" ) +type RuleSearchReq struct { + g.Meta `path:"/menu/list" tags:"菜单管理" method:"get" summary:"菜单列表"` + Authorization string `p:"Authorization" in:"header" dc:"Bearer {{token}}"` + Title string `p:"menuName" ` + Component string `p:"component"` +} + +type RuleListRes struct { + g.Meta `mime:"application/json"` + Rules []*model.SysAuthRuleTreeRes `json:"rules"` +} + type RuleAddReq struct { g.Meta `path:"/menu/add" tags:"菜单管理" method:"post" summary:"添加菜单"` Authorization string `p:"Authorization" in:"header" dc:"Bearer {{token}}"` @@ -57,6 +69,34 @@ type RuleInfoReq struct { } type RuleInfoRes struct { - g.Meta `mime:"application/json"` - Rule *entity.SysAuthRule `json:"rule"` + g.Meta `mime:"application/json"` + Rule *entity.SysAuthRule `json:"rule"` + RoleIds []uint `json:"roleIds"` +} + +type RuleUpdateReq struct { + g.Meta `path:"/menu/update" tags:"菜单管理" method:"post" summary:"修改菜单"` + Authorization string `p:"Authorization" in:"header" dc:"Bearer {{token}}"` + Id uint `p:"id" v:"required#id必须"` + MenuType uint `p:"menuType" v:"min:0|max:2#菜单类型最小值为:min|菜单类型最大值为:max"` + Pid uint `p:"parentId" v:"min:0"` + Name string `p:"name" v:"required#请填写规则名称"` + Title string `p:"menuName" v:"required|length:1,100#请填写标题|标题长度在:min到:max位"` + Icon string `p:"icon"` + Weigh int `p:"menuSort" ` + Condition string `p:"condition" ` + Remark string `p:"remark" ` + IsHide uint `p:"isHide"` + Path string `p:"path"` + Redirect string `p:"redirect"` // 路由重定向 + Roles []uint `p:"roles"` // 角色ids + Component string `p:"component" v:"required-if:menuType,1#组件路径不能为空"` + IsLink uint `p:"isLink"` + IsIframe uint `p:"isIframe"` + IsCached uint `p:"isKeepAlive"` + IsAffix uint `p:"isAffix"` + LinkUrl string `p:"linkUrl"` +} + +type RuleUpdateRes struct { } diff --git a/go.mod b/go.mod index 9324263..abcb5db 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,6 @@ require ( github.com/gogf/gf/v2 v2.0.4 github.com/mojocn/base64Captcha v1.3.5 github.com/mssola/user_agent v0.5.3 - github.com/tiger1103/gfast-cache v0.0.6 + github.com/tiger1103/gfast-cache v0.0.7 github.com/tiger1103/gfast-token v0.0.9 ) diff --git a/go.sum b/go.sum index 5469896..bf6d67b 100644 --- a/go.sum +++ b/go.sum @@ -85,8 +85,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/tiger1103/gfast-cache v0.0.6 h1:H40Txv6co5bjaRlFQ/ixcMfpgsihhPpNftvCHm7hLpI= -github.com/tiger1103/gfast-cache v0.0.6/go.mod h1:s6cRWyr87wz6IJNGKRV6Ahq9hcuVz8h2PAtGrO66JO8= +github.com/tiger1103/gfast-cache v0.0.7 h1:YRuSFxFdvNlIsHAndS7XjYRLd4tmXGWhvHt9rK0LVT0= +github.com/tiger1103/gfast-cache v0.0.7/go.mod h1:s6cRWyr87wz6IJNGKRV6Ahq9hcuVz8h2PAtGrO66JO8= github.com/tiger1103/gfast-token v0.0.9 h1:+cKNu4zAMZpqaeILy3QIjuEO0HQMXtMSqVGPmhKAP90= github.com/tiger1103/gfast-token v0.0.9/go.mod h1:RnVRqmWD3h4qfTU1vJNXNhQjh2L5ht1vxLnjwShwGuY= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= diff --git a/internal/app/system/controller/sys_auth_rule.go b/internal/app/system/controller/sys_auth_rule.go index 66dca19..3670f9f 100644 --- a/internal/app/system/controller/sys_auth_rule.go +++ b/internal/app/system/controller/sys_auth_rule.go @@ -10,6 +10,7 @@ package controller import ( "context" "github.com/tiger1103/gfast/v3/api/v1/system" + "github.com/tiger1103/gfast/v3/internal/app/system/model" "github.com/tiger1103/gfast/v3/internal/app/system/service" ) @@ -18,6 +19,24 @@ var Menu = menuController{} type menuController struct { } +func (c *menuController) List(ctx context.Context, req *system.RuleSearchReq) (res *system.RuleListRes, err error) { + var list []*model.SysAuthRuleInfoRes + res = &system.RuleListRes{ + Rules: make([]*model.SysAuthRuleTreeRes, 0), + } + list, err = service.Rule().GetMenuListSearch(ctx, req) + if req.Title != "" || req.Component != "" { + for _, menu := range list { + res.Rules = append(res.Rules, &model.SysAuthRuleTreeRes{ + SysAuthRuleInfoRes: menu, + }) + } + } else { + res.Rules = service.Rule().GetMenuListTree(0, list) + } + return +} + func (c *menuController) Add(ctx context.Context, req *system.RuleAddReq) (res *system.RuleAddRes, err error) { err = service.Rule().Add(ctx, req) return @@ -39,5 +58,15 @@ func (c *menuController) GetAddParams(ctx context.Context, req *system.RuleGetPa func (c *menuController) Get(ctx context.Context, req *system.RuleInfoReq) (res *system.RuleInfoRes, err error) { res = new(system.RuleInfoRes) res.Rule, err = service.Rule().Get(ctx, req.Id) + if err != nil { + return + } + res.RoleIds, err = service.Rule().GetMenuRoles(ctx, req.Id) + return +} + +// Update 菜单修改 +func (c *menuController) Update(ctx context.Context, req *system.RuleUpdateReq) (res *system.RuleUpdateRes, err error) { + err = service.Rule().Update(ctx, req) return } diff --git a/internal/app/system/model/sys_auth_rule.go b/internal/app/system/model/sys_auth_rule.go index ebfda65..6e8f1db 100644 --- a/internal/app/system/model/sys_auth_rule.go +++ b/internal/app/system/model/sys_auth_rule.go @@ -28,6 +28,12 @@ type SysAuthRuleInfoRes struct { LinkUrl string `orm:"link_url" json:"linkUrl"` //链接地址 } +// SysAuthRuleTreeRes 菜单树形结构 +type SysAuthRuleTreeRes struct { + *SysAuthRuleInfoRes + Children []*SysAuthRuleTreeRes `json:"children"` +} + type UserMenu struct { Id uint `json:"id"` Pid uint `json:"pid"` diff --git a/internal/app/system/service/sys_auth_rule.go b/internal/app/system/service/sys_auth_rule.go index 54bae56..3caec10 100644 --- a/internal/app/system/service/sys_auth_rule.go +++ b/internal/app/system/service/sys_auth_rule.go @@ -31,6 +31,10 @@ type IRule interface { 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 } type ruleImpl struct { @@ -42,6 +46,21 @@ func Rule() IRule { return IRule(&rule) } +func (s *ruleImpl) GetMenuListSearch(ctx context.Context, req *system.RuleSearchReq) (res []*model.SysAuthRuleInfoRes, err error) { + err = g.Try(func() { + 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) @@ -139,7 +158,7 @@ func (s *ruleImpl) Add(ctx context.Context, req *system.RuleAddReq) (err error) } //检查菜单规则是否存在 -func (s *ruleImpl) menuNameExists(ctx context.Context, name string, id int) bool { +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) @@ -172,3 +191,90 @@ func (s *ruleImpl) Get(ctx context.Context, id uint) (rule *entity.SysAuthRule, }) return } + +func (s *ruleImpl) GetMenuRoles(ctx context.Context, id uint) (roleIds []uint, err error) { + err = g.Try(func() { + enforcer, e := commonService.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(func() { + //菜单数据 + 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 { + // 删除相关缓存 + commonService.Cache(ctx).RemoveByTag(ctx, consts.CacheSysAuthTag) + } + return +} + +func (s *ruleImpl) UpdateRoleRule(ctx context.Context, ruleId uint, roleIds []uint) (err error) { + err = g.Try(func() { + enforcer, e := service.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 +}