package role import ( "context" "github.com/gogf/gf/v2/errors/gerror" "service.xpcool.com/internal/consts" "service.xpcool.com/internal/dao" "service.xpcool.com/internal/library/response" "service.xpcool.com/internal/model/do" "service.xpcool.com/internal/model/dto" "service.xpcool.com/internal/model/entity" ) // IRoleManage 管理角色及其菜单绑定。 type IRoleManage interface { List(context.Context, dto.PageQuery) ([]*dto.RoleItem, int, error) Create(context.Context, dto.RoleCreateInput) (uint64, error) Update(context.Context, dto.RoleUpdateInput) error Delete(context.Context, uint64) error } type roleManage struct{} var localRoleManage IRoleManage func NewRoleManage() IRoleManage { return &roleManage{} } func RoleManage() IRoleManage { if localRoleManage == nil { panic("RoleManage implementation not registered") } return localRoleManage } func RegisterRoleManage(i IRoleManage) { localRoleManage = i } // ---------------------- Role manage ---------------------- func (s *roleManage) List(ctx context.Context, q dto.PageQuery) ([]*dto.RoleItem, int, error) { total, err := dao.AdminRole.Ctx(ctx).Count() if err != nil { return nil, 0, gerror.Wrap(err, "count roles") } if total == 0 { return nil, 0, nil } var list []entity.AdminRole if err = dao.AdminRole.Ctx(ctx).Page(q.Page, q.Size).OrderAsc("id").Scan(&list); err != nil { return nil, 0, gerror.Wrap(err, "query roles") } items := make([]*dto.RoleItem, 0, len(list)) for i := range list { r := &list[i] menuIds, err := roleMenuIDs(ctx, r.Id) if err != nil { return nil, 0, err } items = append(items, &dto.RoleItem{ Id: r.Id, Code: r.Code, Name: r.Name, Status: r.Status, MenuIds: menuIds, CreatedAt: r.CreatedAt.Layout("2006-01-02 15:04:05"), }) } return items, total, nil } func (s *roleManage) Create(ctx context.Context, in dto.RoleCreateInput) (uint64, error) { count, err := dao.AdminRole.Ctx(ctx).Where(do.AdminRole{Code: in.Code}).Count() if err != nil { return 0, gerror.Wrap(err, "check role code") } if count > 0 { return 0, response.Error(consts.CodeInvalidParam, "role code already exists") } id, err := dao.AdminRole.Ctx(ctx).Data(do.AdminRole{Code: in.Code, Name: in.Name, Status: in.Status}).InsertAndGetId() if err != nil { return 0, gerror.Wrap(err, "insert role") } if err = bindRoleMenus(ctx, uint64(id), in.MenuIds); err != nil { return 0, err } return uint64(id), nil } func (s *roleManage) Update(ctx context.Context, in dto.RoleUpdateInput) error { if _, err := dao.AdminRole.Ctx(ctx).Where(do.AdminRole{Id: in.Id}).Data(do.AdminRole{Name: in.Name, Status: in.Status}).Update(); err != nil { return gerror.Wrap(err, "update role") } return bindRoleMenus(ctx, in.Id, in.MenuIds) } func (s *roleManage) Delete(ctx context.Context, id uint64) error { if _, err := dao.AdminRole.Ctx(ctx).Where(do.AdminRole{Id: id}).Delete(); err != nil { return gerror.Wrap(err, "delete role") } if _, err := dao.AdminRoleMenu.Ctx(ctx).Unscoped().Where(do.AdminRoleMenu{RoleId: id}).Delete(); err != nil { return gerror.Wrap(err, "delete role menu bindings") } if _, err := dao.AdminUserRole.Ctx(ctx).Unscoped().Where(do.AdminUserRole{RoleId: id}).Delete(); err != nil { return gerror.Wrap(err, "delete user role bindings") } return nil } func roleMenuIDs(ctx context.Context, roleID uint64) ([]uint64, error) { var rels []entity.AdminRoleMenu if err := dao.AdminRoleMenu.Ctx(ctx).Where(do.AdminRoleMenu{RoleId: roleID}).Scan(&rels); err != nil { return nil, gerror.Wrap(err, "query role menus") } ids := make([]uint64, 0, len(rels)) for _, r := range rels { ids = append(ids, r.MenuId) } return ids, nil } // bindRoleMenus 全量重绑角色-菜单关系。 func bindRoleMenus(ctx context.Context, roleID uint64, menuIds []uint64) error { if _, err := dao.AdminRoleMenu.Ctx(ctx).Unscoped().Where(do.AdminRoleMenu{RoleId: roleID}).Delete(); err != nil { return gerror.Wrap(err, "clear role menus") } for _, mid := range menuIds { if _, err := dao.AdminRoleMenu.Ctx(ctx).Data(do.AdminRoleMenu{RoleId: roleID, MenuId: mid}).Insert(); err != nil { return gerror.Wrap(err, "bind role menu") } } return nil }