Browse Source

feat: implement all backend logic for menu, role, org management

master
dark 1 month ago
parent
commit
38f4e740fa
  1. 45
      backend/internal/logic/menu/createmenulogic.go
  2. 26
      backend/internal/logic/menu/deletemenulogic.go
  3. 75
      backend/internal/logic/menu/getcurrentmenuslogic.go
  4. 13
      backend/internal/logic/menu/getmenulistlogic.go
  5. 56
      backend/internal/logic/menu/updatemenulogic.go
  6. 42
      backend/internal/logic/organization/addorgmemberlogic.go
  7. 40
      backend/internal/logic/organization/createorganizationlogic.go
  8. 39
      backend/internal/logic/organization/deleteorganizationlogic.go
  9. 43
      backend/internal/logic/organization/getorganizationlistlogic.go
  10. 41
      backend/internal/logic/organization/getorgmemberslogic.go
  11. 13
      backend/internal/logic/organization/removeorgmemberlogic.go
  12. 55
      backend/internal/logic/organization/updateorganizationlogic.go
  13. 21
      backend/internal/logic/organization/updateorgmemberlogic.go
  14. 45
      backend/internal/logic/profile/getuserorgslogic.go
  15. 45
      backend/internal/logic/profile/switchorglogic.go
  16. 33
      backend/internal/logic/role/createrolelogic.go
  17. 35
      backend/internal/logic/role/deleterolelogic.go
  18. 26
      backend/internal/logic/role/getrolelistlogic.go
  19. 15
      backend/internal/logic/role/getrolemenuslogic.go
  20. 20
      backend/internal/logic/role/setrolemenuslogic.go
  21. 37
      backend/internal/logic/role/updaterolelogic.go
  22. 153
      backend/internal/svc/servicecontext.go

45
backend/internal/logic/menu/createmenulogic.go

@ -5,9 +5,11 @@ package menu
import (
"context"
"fmt"
"github.com/youruser/base/internal/svc"
"github.com/youruser/base/internal/types"
"github.com/youruser/base/model"
"github.com/zeromicro/go-zero/core/logx"
)
@ -28,7 +30,46 @@ func NewCreateMenuLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Create
}
func (l *CreateMenuLogic) CreateMenu(req *types.CreateMenuRequest) (resp *types.MenuItem, err error) {
// todo: add your logic here and delete this line
visible := true
if req.Visible != nil {
visible = *req.Visible
}
menuType := "config"
if req.Type != "" {
menuType = req.Type
}
menu := &model.Menu{
ParentId: req.ParentId,
Name: req.Name,
Path: req.Path,
Icon: req.Icon,
Component: req.Component,
Type: menuType,
SortOrder: req.SortOrder,
Visible: visible,
Status: 1,
}
_, err = model.MenuInsert(l.ctx, l.svcCtx.DB, menu)
if err != nil {
return nil, fmt.Errorf("创建菜单失败: %v", err)
}
return
return &types.MenuItem{
Id: menu.Id,
ParentId: menu.ParentId,
Name: menu.Name,
Path: menu.Path,
Icon: menu.Icon,
Component: menu.Component,
Type: menu.Type,
SortOrder: menu.SortOrder,
Visible: menu.Visible,
Status: menu.Status,
Children: []types.MenuItem{},
CreatedAt: menu.CreatedAt.Format("2006-01-02 15:04:05"),
UpdatedAt: menu.UpdatedAt.Format("2006-01-02 15:04:05"),
}, nil
}

26
backend/internal/logic/menu/deletemenulogic.go

@ -5,9 +5,11 @@ package menu
import (
"context"
"fmt"
"github.com/youruser/base/internal/svc"
"github.com/youruser/base/internal/types"
"github.com/youruser/base/model"
"github.com/zeromicro/go-zero/core/logx"
)
@ -28,7 +30,27 @@ func NewDeleteMenuLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Delete
}
func (l *DeleteMenuLogic) DeleteMenu(req *types.DeleteMenuRequest) (resp *types.Response, err error) {
// todo: add your logic here and delete this line
// 检查是否有子菜单
hasChildren, err := model.MenuHasChildren(l.ctx, l.svcCtx.DB, req.Id)
if err != nil {
return nil, fmt.Errorf("检查子菜单失败: %v", err)
}
if hasChildren {
return &types.Response{
Code: 400,
Message: "该菜单下有子菜单,无法删除",
Success: false,
}, nil
}
err = model.MenuDelete(l.ctx, l.svcCtx.DB, req.Id)
if err != nil {
return nil, fmt.Errorf("删除菜单失败: %v", err)
}
return
return &types.Response{
Code: 0,
Message: "删除成功",
Success: true,
}, nil
}

75
backend/internal/logic/menu/getcurrentmenuslogic.go

@ -5,9 +5,11 @@ package menu
import (
"context"
"fmt"
"github.com/youruser/base/internal/svc"
"github.com/youruser/base/internal/types"
"github.com/youruser/base/model"
"github.com/zeromicro/go-zero/core/logx"
)
@ -28,7 +30,76 @@ func NewGetCurrentMenusLogic(ctx context.Context, svcCtx *svc.ServiceContext) *G
}
func (l *GetCurrentMenusLogic) GetCurrentMenus() (resp *types.MenuListResponse, err error) {
// todo: add your logic here and delete this line
// 获取用户角色
roleStr, _ := l.ctx.Value("role").(string)
if roleStr == "" {
roleStr = model.RoleGuest
}
// 查找角色
role, err := model.RoleFindOneByCode(l.ctx, l.svcCtx.DB, roleStr)
if err != nil {
return nil, fmt.Errorf("角色不存在: %v", err)
}
// 获取角色关联的菜单ID
roleMenuIds, err := model.RoleMenuFindByRoleId(l.ctx, l.svcCtx.DB, role.Id)
if err != nil {
return nil, fmt.Errorf("获取角色菜单失败: %v", err)
}
return
// 构建菜单ID集合用于快速查找
menuIdSet := make(map[int64]bool)
for _, id := range roleMenuIds {
menuIdSet[id] = true
}
// 获取所有菜单
allMenus, err := model.MenuFindAll(l.ctx, l.svcCtx.DB)
if err != nil {
return nil, fmt.Errorf("获取菜单列表失败: %v", err)
}
// 过滤:包含角色关联的菜单或 type=default 且 visible=true
var filteredMenus []model.Menu
for _, m := range allMenus {
if menuIdSet[m.Id] || (m.Type == "default" && m.Visible) {
filteredMenus = append(filteredMenus, m)
}
}
// 构建树形结构
tree := buildMenuTree(filteredMenus, 0)
return &types.MenuListResponse{
List: tree,
}, nil
}
func buildMenuTree(menus []model.Menu, parentId int64) []types.MenuItem {
var tree []types.MenuItem
for _, m := range menus {
if m.ParentId == parentId {
item := types.MenuItem{
Id: m.Id,
ParentId: m.ParentId,
Name: m.Name,
Path: m.Path,
Icon: m.Icon,
Component: m.Component,
Type: m.Type,
SortOrder: m.SortOrder,
Visible: m.Visible,
Status: m.Status,
Children: buildMenuTree(menus, m.Id),
CreatedAt: m.CreatedAt.Format("2006-01-02 15:04:05"),
UpdatedAt: m.UpdatedAt.Format("2006-01-02 15:04:05"),
}
tree = append(tree, item)
}
}
if tree == nil {
tree = []types.MenuItem{}
}
return tree
}

13
backend/internal/logic/menu/getmenulistlogic.go

@ -5,9 +5,11 @@ package menu
import (
"context"
"fmt"
"github.com/youruser/base/internal/svc"
"github.com/youruser/base/internal/types"
"github.com/youruser/base/model"
"github.com/zeromicro/go-zero/core/logx"
)
@ -28,7 +30,14 @@ func NewGetMenuListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetMe
}
func (l *GetMenuListLogic) GetMenuList() (resp *types.MenuListResponse, err error) {
// todo: add your logic here and delete this line
menus, err := model.MenuFindAll(l.ctx, l.svcCtx.DB)
if err != nil {
return nil, fmt.Errorf("获取菜单列表失败: %v", err)
}
tree := buildMenuTree(menus, 0)
return
return &types.MenuListResponse{
List: tree,
}, nil
}

56
backend/internal/logic/menu/updatemenulogic.go

@ -5,9 +5,11 @@ package menu
import (
"context"
"fmt"
"github.com/youruser/base/internal/svc"
"github.com/youruser/base/internal/types"
"github.com/youruser/base/model"
"github.com/zeromicro/go-zero/core/logx"
)
@ -28,7 +30,57 @@ func NewUpdateMenuLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Update
}
func (l *UpdateMenuLogic) UpdateMenu(req *types.UpdateMenuRequest) (resp *types.MenuItem, err error) {
// todo: add your logic here and delete this line
menu, err := model.MenuFindOne(l.ctx, l.svcCtx.DB, req.Id)
if err != nil {
return nil, fmt.Errorf("菜单不存在: %v", err)
}
if req.ParentId != nil {
menu.ParentId = *req.ParentId
}
if req.Name != "" {
menu.Name = req.Name
}
if req.Path != "" {
menu.Path = req.Path
}
if req.Icon != "" {
menu.Icon = req.Icon
}
if req.Component != "" {
menu.Component = req.Component
}
if req.Type != "" {
menu.Type = req.Type
}
if req.SortOrder != nil {
menu.SortOrder = *req.SortOrder
}
if req.Visible != nil {
menu.Visible = *req.Visible
}
if req.Status != nil {
menu.Status = *req.Status
}
err = model.MenuUpdate(l.ctx, l.svcCtx.DB, menu)
if err != nil {
return nil, fmt.Errorf("更新菜单失败: %v", err)
}
return
return &types.MenuItem{
Id: menu.Id,
ParentId: menu.ParentId,
Name: menu.Name,
Path: menu.Path,
Icon: menu.Icon,
Component: menu.Component,
Type: menu.Type,
SortOrder: menu.SortOrder,
Visible: menu.Visible,
Status: menu.Status,
Children: []types.MenuItem{},
CreatedAt: menu.CreatedAt.Format("2006-01-02 15:04:05"),
UpdatedAt: menu.UpdatedAt.Format("2006-01-02 15:04:05"),
}, nil
}

42
backend/internal/logic/organization/addorgmemberlogic.go

@ -5,9 +5,11 @@ package organization
import (
"context"
"fmt"
"github.com/youruser/base/internal/svc"
"github.com/youruser/base/internal/types"
"github.com/youruser/base/model"
"github.com/zeromicro/go-zero/core/logx"
)
@ -28,7 +30,43 @@ func NewAddOrgMemberLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AddO
}
func (l *AddOrgMemberLogic) AddOrgMember(req *types.AddOrgMemberRequest) (resp *types.Response, err error) {
// todo: add your logic here and delete this line
// 验证机构是否存在
_, err = model.OrgFindOne(l.ctx, l.svcCtx.DB, req.Id)
if err != nil {
return nil, fmt.Errorf("机构不存在: %v", err)
}
// 验证用户是否存在
_, err = model.FindOne(l.ctx, l.svcCtx.DB, req.UserId)
if err != nil {
return nil, fmt.Errorf("用户不存在: %v", err)
}
// 检查是否已经是成员
existing, _ := model.UserOrgFindOne(l.ctx, l.svcCtx.DB, req.UserId, req.Id)
if existing != nil {
return &types.Response{
Code: 400,
Message: "该用户已经是该机构成员",
Success: false,
}, nil
}
// 添加成员
uo := &model.UserOrganization{
UserId: req.UserId,
OrgId: req.Id,
RoleId: req.RoleId,
}
_, err = model.UserOrgInsert(l.ctx, l.svcCtx.DB, uo)
if err != nil {
return nil, fmt.Errorf("添加成员失败: %v", err)
}
return
return &types.Response{
Code: 0,
Message: "添加成功",
Success: true,
}, nil
}

40
backend/internal/logic/organization/createorganizationlogic.go

@ -5,9 +5,11 @@ package organization
import (
"context"
"fmt"
"github.com/youruser/base/internal/svc"
"github.com/youruser/base/internal/types"
"github.com/youruser/base/model"
"github.com/zeromicro/go-zero/core/logx"
)
@ -28,7 +30,41 @@ func NewCreateOrganizationLogic(ctx context.Context, svcCtx *svc.ServiceContext)
}
func (l *CreateOrganizationLogic) CreateOrganization(req *types.CreateOrgRequest) (resp *types.OrgInfo, err error) {
// todo: add your logic here and delete this line
// 检查编码唯一性
existing, _ := model.OrgFindOneByCode(l.ctx, l.svcCtx.DB, req.Code)
if existing != nil {
return nil, fmt.Errorf("机构编码 %s 已存在", req.Code)
}
org := &model.Organization{
ParentId: req.ParentId,
Name: req.Name,
Code: req.Code,
Leader: req.Leader,
Phone: req.Phone,
Email: req.Email,
SortOrder: req.SortOrder,
Status: 1,
}
_, err = model.OrgInsert(l.ctx, l.svcCtx.DB, org)
if err != nil {
return nil, fmt.Errorf("创建机构失败: %v", err)
}
return
return &types.OrgInfo{
Id: org.Id,
ParentId: org.ParentId,
Name: org.Name,
Code: org.Code,
Leader: org.Leader,
Phone: org.Phone,
Email: org.Email,
SortOrder: org.SortOrder,
Status: org.Status,
MemberCount: 0,
Children: []types.OrgInfo{},
CreatedAt: org.CreatedAt.Format("2006-01-02 15:04:05"),
UpdatedAt: org.UpdatedAt.Format("2006-01-02 15:04:05"),
}, nil
}

39
backend/internal/logic/organization/deleteorganizationlogic.go

@ -5,9 +5,11 @@ package organization
import (
"context"
"fmt"
"github.com/youruser/base/internal/svc"
"github.com/youruser/base/internal/types"
"github.com/youruser/base/model"
"github.com/zeromicro/go-zero/core/logx"
)
@ -28,7 +30,40 @@ func NewDeleteOrganizationLogic(ctx context.Context, svcCtx *svc.ServiceContext)
}
func (l *DeleteOrganizationLogic) DeleteOrganization(req *types.DeleteOrgRequest) (resp *types.Response, err error) {
// todo: add your logic here and delete this line
// 检查是否有子机构
hasChildren, err := model.OrgHasChildren(l.ctx, l.svcCtx.DB, req.Id)
if err != nil {
return nil, fmt.Errorf("检查子机构失败: %v", err)
}
if hasChildren {
return &types.Response{
Code: 400,
Message: "该机构下有子机构,无法删除",
Success: false,
}, nil
}
// 检查是否有成员
memberCount, err := model.UserOrgCountByOrgId(l.ctx, l.svcCtx.DB, req.Id)
if err != nil {
return nil, fmt.Errorf("检查机构成员失败: %v", err)
}
if memberCount > 0 {
return &types.Response{
Code: 400,
Message: "该机构下有成员,无法删除",
Success: false,
}, nil
}
err = model.OrgDelete(l.ctx, l.svcCtx.DB, req.Id)
if err != nil {
return nil, fmt.Errorf("删除机构失败: %v", err)
}
return
return &types.Response{
Code: 0,
Message: "删除成功",
Success: true,
}, nil
}

43
backend/internal/logic/organization/getorganizationlistlogic.go

@ -5,11 +5,14 @@ package organization
import (
"context"
"fmt"
"github.com/youruser/base/internal/svc"
"github.com/youruser/base/internal/types"
"github.com/youruser/base/model"
"github.com/zeromicro/go-zero/core/logx"
"gorm.io/gorm"
)
type GetOrganizationListLogic struct {
@ -28,7 +31,43 @@ func NewGetOrganizationListLogic(ctx context.Context, svcCtx *svc.ServiceContext
}
func (l *GetOrganizationListLogic) GetOrganizationList() (resp *types.OrgListResponse, err error) {
// todo: add your logic here and delete this line
orgs, err := model.OrgFindAll(l.ctx, l.svcCtx.DB)
if err != nil {
return nil, fmt.Errorf("获取机构列表失败: %v", err)
}
tree := buildOrgTree(l.ctx, l.svcCtx.DB, orgs, 0)
return &types.OrgListResponse{
List: tree,
}, nil
}
return
func buildOrgTree(ctx context.Context, db *gorm.DB, orgs []model.Organization, parentId int64) []types.OrgInfo {
var tree []types.OrgInfo
for _, o := range orgs {
if o.ParentId == parentId {
memberCount, _ := model.UserOrgCountByOrgId(ctx, db, o.Id)
item := types.OrgInfo{
Id: o.Id,
ParentId: o.ParentId,
Name: o.Name,
Code: o.Code,
Leader: o.Leader,
Phone: o.Phone,
Email: o.Email,
SortOrder: o.SortOrder,
Status: o.Status,
MemberCount: memberCount,
Children: buildOrgTree(ctx, db, orgs, o.Id),
CreatedAt: o.CreatedAt.Format("2006-01-02 15:04:05"),
UpdatedAt: o.UpdatedAt.Format("2006-01-02 15:04:05"),
}
tree = append(tree, item)
}
}
if tree == nil {
tree = []types.OrgInfo{}
}
return tree
}

41
backend/internal/logic/organization/getorgmemberslogic.go

@ -5,9 +5,11 @@ package organization
import (
"context"
"fmt"
"github.com/youruser/base/internal/svc"
"github.com/youruser/base/internal/types"
"github.com/youruser/base/model"
"github.com/zeromicro/go-zero/core/logx"
)
@ -28,7 +30,42 @@ func NewGetOrgMembersLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Get
}
func (l *GetOrgMembersLogic) GetOrgMembers(req *types.GetOrgMembersRequest) (resp *types.OrgMembersResponse, err error) {
// todo: add your logic here and delete this line
userOrgs, err := model.UserOrgFindByOrgId(l.ctx, l.svcCtx.DB, req.Id)
if err != nil {
return nil, fmt.Errorf("获取机构成员失败: %v", err)
}
list := make([]types.OrgMember, 0, len(userOrgs))
for _, uo := range userOrgs {
// 查询用户信息
user, err := model.FindOne(l.ctx, l.svcCtx.DB, uo.UserId)
if err != nil {
continue
}
// 查询角色信息
var roleName, roleCode string
if uo.RoleId > 0 {
role, err := model.RoleFindOne(l.ctx, l.svcCtx.DB, uo.RoleId)
if err == nil {
roleName = role.Name
roleCode = role.Code
}
}
list = append(list, types.OrgMember{
UserId: user.Id,
Username: user.Username,
Email: user.Email,
Phone: user.Phone,
RoleId: uo.RoleId,
RoleName: roleName,
RoleCode: roleCode,
CreatedAt: uo.CreatedAt.Format("2006-01-02 15:04:05"),
})
}
return
return &types.OrgMembersResponse{
List: list,
}, nil
}

13
backend/internal/logic/organization/removeorgmemberlogic.go

@ -5,9 +5,11 @@ package organization
import (
"context"
"fmt"
"github.com/youruser/base/internal/svc"
"github.com/youruser/base/internal/types"
"github.com/youruser/base/model"
"github.com/zeromicro/go-zero/core/logx"
)
@ -28,7 +30,14 @@ func NewRemoveOrgMemberLogic(ctx context.Context, svcCtx *svc.ServiceContext) *R
}
func (l *RemoveOrgMemberLogic) RemoveOrgMember(req *types.RemoveOrgMemberRequest) (resp *types.Response, err error) {
// todo: add your logic here and delete this line
err = model.UserOrgDelete(l.ctx, l.svcCtx.DB, req.UserId, req.Id)
if err != nil {
return nil, fmt.Errorf("移除成员失败: %v", err)
}
return
return &types.Response{
Code: 0,
Message: "移除成功",
Success: true,
}, nil
}

55
backend/internal/logic/organization/updateorganizationlogic.go

@ -5,9 +5,11 @@ package organization
import (
"context"
"fmt"
"github.com/youruser/base/internal/svc"
"github.com/youruser/base/internal/types"
"github.com/youruser/base/model"
"github.com/zeromicro/go-zero/core/logx"
)
@ -28,7 +30,56 @@ func NewUpdateOrganizationLogic(ctx context.Context, svcCtx *svc.ServiceContext)
}
func (l *UpdateOrganizationLogic) UpdateOrganization(req *types.UpdateOrgRequest) (resp *types.OrgInfo, err error) {
// todo: add your logic here and delete this line
org, err := model.OrgFindOne(l.ctx, l.svcCtx.DB, req.Id)
if err != nil {
return nil, fmt.Errorf("机构不存在: %v", err)
}
if req.ParentId != nil {
org.ParentId = *req.ParentId
}
if req.Name != "" {
org.Name = req.Name
}
if req.Code != "" {
org.Code = req.Code
}
if req.Leader != "" {
org.Leader = req.Leader
}
if req.Phone != "" {
org.Phone = req.Phone
}
if req.Email != "" {
org.Email = req.Email
}
if req.SortOrder != nil {
org.SortOrder = *req.SortOrder
}
if req.Status != nil {
org.Status = *req.Status
}
err = model.OrgUpdate(l.ctx, l.svcCtx.DB, org)
if err != nil {
return nil, fmt.Errorf("更新机构失败: %v", err)
}
memberCount, _ := model.UserOrgCountByOrgId(l.ctx, l.svcCtx.DB, org.Id)
return
return &types.OrgInfo{
Id: org.Id,
ParentId: org.ParentId,
Name: org.Name,
Code: org.Code,
Leader: org.Leader,
Phone: org.Phone,
Email: org.Email,
SortOrder: org.SortOrder,
Status: org.Status,
MemberCount: memberCount,
Children: []types.OrgInfo{},
CreatedAt: org.CreatedAt.Format("2006-01-02 15:04:05"),
UpdatedAt: org.UpdatedAt.Format("2006-01-02 15:04:05"),
}, nil
}

21
backend/internal/logic/organization/updateorgmemberlogic.go

@ -5,9 +5,11 @@ package organization
import (
"context"
"fmt"
"github.com/youruser/base/internal/svc"
"github.com/youruser/base/internal/types"
"github.com/youruser/base/model"
"github.com/zeromicro/go-zero/core/logx"
)
@ -28,7 +30,22 @@ func NewUpdateOrgMemberLogic(ctx context.Context, svcCtx *svc.ServiceContext) *U
}
func (l *UpdateOrgMemberLogic) UpdateOrgMember(req *types.UpdateOrgMemberRequest) (resp *types.Response, err error) {
// todo: add your logic here and delete this line
// 查找用户-机构关联
uo, err := model.UserOrgFindOne(l.ctx, l.svcCtx.DB, req.UserId, req.Id)
if err != nil {
return nil, fmt.Errorf("该用户不是该机构成员: %v", err)
}
// 更新角色
uo.RoleId = req.RoleId
err = model.UserOrgUpdate(l.ctx, l.svcCtx.DB, uo)
if err != nil {
return nil, fmt.Errorf("更新成员角色失败: %v", err)
}
return
return &types.Response{
Code: 0,
Message: "更新成功",
Success: true,
}, nil
}

45
backend/internal/logic/profile/getuserorgslogic.go

@ -5,9 +5,11 @@ package profile
import (
"context"
"fmt"
"github.com/youruser/base/internal/svc"
"github.com/youruser/base/internal/types"
"github.com/youruser/base/model"
"github.com/zeromicro/go-zero/core/logx"
)
@ -28,7 +30,46 @@ func NewGetUserOrgsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetUs
}
func (l *GetUserOrgsLogic) GetUserOrgs() (resp *types.UserOrgsResponse, err error) {
// todo: add your logic here and delete this line
userId, _ := l.ctx.Value("userId").(int64)
if userId == 0 {
return nil, fmt.Errorf("未获取到用户信息")
}
userOrgs, err := model.UserOrgFindByUserId(l.ctx, l.svcCtx.DB, userId)
if err != nil {
return nil, fmt.Errorf("获取用户机构列表失败: %v", err)
}
list := make([]types.UserOrgInfo, 0, len(userOrgs))
for _, uo := range userOrgs {
// 查询机构信息
org, err := model.OrgFindOne(l.ctx, l.svcCtx.DB, uo.OrgId)
if err != nil {
continue
}
// 查询角色信息
var roleName, roleCode string
var roleId int64
if uo.RoleId > 0 {
role, err := model.RoleFindOne(l.ctx, l.svcCtx.DB, uo.RoleId)
if err == nil {
roleId = role.Id
roleName = role.Name
roleCode = role.Code
}
}
list = append(list, types.UserOrgInfo{
OrgId: org.Id,
OrgName: org.Name,
RoleId: roleId,
RoleName: roleName,
RoleCode: roleCode,
})
}
return
return &types.UserOrgsResponse{
List: list,
}, nil
}

45
backend/internal/logic/profile/switchorglogic.go

@ -5,9 +5,12 @@ package profile
import (
"context"
"fmt"
"github.com/youruser/base/internal/svc"
"github.com/youruser/base/internal/types"
jwtutil "github.com/youruser/base/internal/util/jwt"
"github.com/youruser/base/model"
"github.com/zeromicro/go-zero/core/logx"
)
@ -28,7 +31,45 @@ func NewSwitchOrgLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SwitchO
}
func (l *SwitchOrgLogic) SwitchOrg(req *types.SwitchOrgRequest) (resp *types.SwitchOrgResponse, err error) {
// todo: add your logic here and delete this line
userId, _ := l.ctx.Value("userId").(int64)
username, _ := l.ctx.Value("username").(string)
if userId == 0 {
return nil, fmt.Errorf("未获取到用户信息")
}
// 验证用户属于该机构
userOrg, err := model.UserOrgFindOne(l.ctx, l.svcCtx.DB, userId, req.OrgId)
if err != nil {
return nil, fmt.Errorf("您不属于该机构")
}
// 获取角色编码
roleCode := model.RoleUser // 默认角色
if userOrg.RoleId > 0 {
role, err := model.RoleFindOne(l.ctx, l.svcCtx.DB, userOrg.RoleId)
if err == nil {
roleCode = role.Code
}
}
// 更新用户的 CurrentOrgId
user, err := model.FindOne(l.ctx, l.svcCtx.DB, userId)
if err != nil {
return nil, fmt.Errorf("获取用户信息失败: %v", err)
}
user.CurrentOrgId = req.OrgId
err = model.Update(l.ctx, l.svcCtx.DB, user)
if err != nil {
return nil, fmt.Errorf("更新用户机构失败: %v", err)
}
// 生成新的 JWT Token
token, err := jwtutil.GenerateToken(userId, username, roleCode, req.OrgId)
if err != nil {
return nil, fmt.Errorf("生成Token失败: %v", err)
}
return
return &types.SwitchOrgResponse{
Token: token,
}, nil
}

33
backend/internal/logic/role/createrolelogic.go

@ -5,9 +5,11 @@ package role
import (
"context"
"fmt"
"github.com/youruser/base/internal/svc"
"github.com/youruser/base/internal/types"
"github.com/youruser/base/model"
"github.com/zeromicro/go-zero/core/logx"
)
@ -28,7 +30,34 @@ func NewCreateRoleLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Create
}
func (l *CreateRoleLogic) CreateRole(req *types.CreateRoleRequest) (resp *types.RoleInfo, err error) {
// todo: add your logic here and delete this line
// 检查编码唯一性
existing, _ := model.RoleFindOneByCode(l.ctx, l.svcCtx.DB, req.Code)
if existing != nil {
return nil, fmt.Errorf("角色编码 %s 已存在", req.Code)
}
role := &model.Role{
Name: req.Name,
Code: req.Code,
Description: req.Description,
SortOrder: req.SortOrder,
Status: 1,
}
_, err = model.RoleInsert(l.ctx, l.svcCtx.DB, role)
if err != nil {
return nil, fmt.Errorf("创建角色失败: %v", err)
}
return
return &types.RoleInfo{
Id: role.Id,
Name: role.Name,
Code: role.Code,
Description: role.Description,
IsSystem: role.IsSystem,
SortOrder: role.SortOrder,
Status: role.Status,
CreatedAt: role.CreatedAt.Format("2006-01-02 15:04:05"),
UpdatedAt: role.UpdatedAt.Format("2006-01-02 15:04:05"),
}, nil
}

35
backend/internal/logic/role/deleterolelogic.go

@ -5,9 +5,11 @@ package role
import (
"context"
"fmt"
"github.com/youruser/base/internal/svc"
"github.com/youruser/base/internal/types"
"github.com/youruser/base/model"
"github.com/zeromicro/go-zero/core/logx"
)
@ -28,7 +30,36 @@ func NewDeleteRoleLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Delete
}
func (l *DeleteRoleLogic) DeleteRole(req *types.DeleteRoleRequest) (resp *types.Response, err error) {
// todo: add your logic here and delete this line
// 查找角色
role, err := model.RoleFindOne(l.ctx, l.svcCtx.DB, req.Id)
if err != nil {
return nil, fmt.Errorf("角色不存在: %v", err)
}
// 系统角色不允许删除
if role.IsSystem {
return &types.Response{
Code: 400,
Message: "系统角色不允许删除",
Success: false,
}, nil
}
// 删除角色-菜单关联
err = model.RoleMenuDeleteByRoleId(l.ctx, l.svcCtx.DB, req.Id)
if err != nil {
return nil, fmt.Errorf("删除角色菜单关联失败: %v", err)
}
// 删除角色
err = model.RoleDelete(l.ctx, l.svcCtx.DB, req.Id)
if err != nil {
return nil, fmt.Errorf("删除角色失败: %v", err)
}
return
return &types.Response{
Code: 0,
Message: "删除成功",
Success: true,
}, nil
}

26
backend/internal/logic/role/getrolelistlogic.go

@ -5,9 +5,11 @@ package role
import (
"context"
"fmt"
"github.com/youruser/base/internal/svc"
"github.com/youruser/base/internal/types"
"github.com/youruser/base/model"
"github.com/zeromicro/go-zero/core/logx"
)
@ -28,7 +30,27 @@ func NewGetRoleListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetRo
}
func (l *GetRoleListLogic) GetRoleList() (resp *types.RoleListResponse, err error) {
// todo: add your logic here and delete this line
roles, err := model.RoleFindAll(l.ctx, l.svcCtx.DB)
if err != nil {
return nil, fmt.Errorf("获取角色列表失败: %v", err)
}
list := make([]types.RoleInfo, 0, len(roles))
for _, r := range roles {
list = append(list, types.RoleInfo{
Id: r.Id,
Name: r.Name,
Code: r.Code,
Description: r.Description,
IsSystem: r.IsSystem,
SortOrder: r.SortOrder,
Status: r.Status,
CreatedAt: r.CreatedAt.Format("2006-01-02 15:04:05"),
UpdatedAt: r.UpdatedAt.Format("2006-01-02 15:04:05"),
})
}
return
return &types.RoleListResponse{
List: list,
}, nil
}

15
backend/internal/logic/role/getrolemenuslogic.go

@ -5,9 +5,11 @@ package role
import (
"context"
"fmt"
"github.com/youruser/base/internal/svc"
"github.com/youruser/base/internal/types"
"github.com/youruser/base/model"
"github.com/zeromicro/go-zero/core/logx"
)
@ -28,7 +30,16 @@ func NewGetRoleMenusLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetR
}
func (l *GetRoleMenusLogic) GetRoleMenus(req *types.GetRoleMenusRequest) (resp *types.RoleMenusResponse, err error) {
// todo: add your logic here and delete this line
menuIds, err := model.RoleMenuFindByRoleId(l.ctx, l.svcCtx.DB, req.Id)
if err != nil {
return nil, fmt.Errorf("获取角色菜单失败: %v", err)
}
if menuIds == nil {
menuIds = []int64{}
}
return
return &types.RoleMenusResponse{
MenuIds: menuIds,
}, nil
}

20
backend/internal/logic/role/setrolemenuslogic.go

@ -5,9 +5,11 @@ package role
import (
"context"
"fmt"
"github.com/youruser/base/internal/svc"
"github.com/youruser/base/internal/types"
"github.com/youruser/base/model"
"github.com/zeromicro/go-zero/core/logx"
)
@ -28,7 +30,21 @@ func NewSetRoleMenusLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SetR
}
func (l *SetRoleMenusLogic) SetRoleMenus(req *types.SetRoleMenusRequest) (resp *types.Response, err error) {
// todo: add your logic here and delete this line
// 验证角色是否存在
_, err = model.RoleFindOne(l.ctx, l.svcCtx.DB, req.Id)
if err != nil {
return nil, fmt.Errorf("角色不存在: %v", err)
}
// 全量设置角色的菜单
err = model.RoleMenuSetForRole(l.ctx, l.svcCtx.DB, req.Id, req.MenuIds)
if err != nil {
return nil, fmt.Errorf("设置角色菜单失败: %v", err)
}
return
return &types.Response{
Code: 0,
Message: "设置成功",
Success: true,
}, nil
}

37
backend/internal/logic/role/updaterolelogic.go

@ -5,9 +5,11 @@ package role
import (
"context"
"fmt"
"github.com/youruser/base/internal/svc"
"github.com/youruser/base/internal/types"
"github.com/youruser/base/model"
"github.com/zeromicro/go-zero/core/logx"
)
@ -28,7 +30,38 @@ func NewUpdateRoleLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Update
}
func (l *UpdateRoleLogic) UpdateRole(req *types.UpdateRoleRequest) (resp *types.RoleInfo, err error) {
// todo: add your logic here and delete this line
role, err := model.RoleFindOne(l.ctx, l.svcCtx.DB, req.Id)
if err != nil {
return nil, fmt.Errorf("角色不存在: %v", err)
}
if req.Name != "" {
role.Name = req.Name
}
if req.Description != "" {
role.Description = req.Description
}
if req.SortOrder != nil {
role.SortOrder = *req.SortOrder
}
if req.Status != nil {
role.Status = *req.Status
}
err = model.RoleUpdate(l.ctx, l.svcCtx.DB, role)
if err != nil {
return nil, fmt.Errorf("更新角色失败: %v", err)
}
return
return &types.RoleInfo{
Id: role.Id,
Name: role.Name,
Code: role.Code,
Description: role.Description,
IsSystem: role.IsSystem,
SortOrder: role.SortOrder,
Status: role.Status,
CreatedAt: role.CreatedAt.Format("2006-01-02 15:04:05"),
UpdatedAt: role.UpdatedAt.Format("2006-01-02 15:04:05"),
}, nil
}

153
backend/internal/svc/servicecontext.go

@ -15,6 +15,7 @@ import (
"github.com/youruser/base/internal/config"
"github.com/youruser/base/internal/middleware"
"github.com/youruser/base/internal/storage"
"github.com/youruser/base/model"
"gorm.io/driver/mysql"
@ -50,6 +51,8 @@ type ServiceContext struct {
DB *gorm.DB
// Casbin enforcer
Enforcer *casbin.Enforcer
// 文件存储
Storage storage.Storage
}
func NewServiceContext(c config.Config) *ServiceContext {
@ -61,7 +64,7 @@ func NewServiceContext(c config.Config) *ServiceContext {
}
// 自动迁移表
err = db.AutoMigrate(&model.User{}, &model.Profile{})
err = db.AutoMigrate(&model.User{}, &model.Profile{}, &model.File{}, &model.Menu{}, &model.Role{}, &model.RoleMenu{}, &model.Organization{}, &model.UserOrganization{})
if err != nil {
panic("Failed to migrate database: " + err.Error())
}
@ -75,6 +78,18 @@ func NewServiceContext(c config.Config) *ServiceContext {
// 种子 Casbin 策略
seedCasbinPolicies(enforcer)
// 种子角色、菜单、角色-菜单关联
seedRoles(db)
seedMenus(db)
seedRoleMenus(db)
// 初始化存储
store, err := storage.NewStorage(c.Storage)
if err != nil {
panic("Failed to initialize storage: " + err.Error())
}
log.Printf("[Storage] Initialized with type: %s", c.Storage.Type)
return &ServiceContext{
Config: c,
Cors: middleware.NewCorsMiddleware().Handle,
@ -83,6 +98,7 @@ func NewServiceContext(c config.Config) *ServiceContext {
Authz: middleware.NewAuthzMiddleware(enforcer).Handle,
DB: db,
Enforcer: enforcer,
Storage: store,
}
}
@ -193,6 +209,50 @@ func seedCasbinPolicies(enforcer *casbin.Enforcer) {
// super_admin: 用户删除
{"super_admin", "/api/v1/user/:id", "DELETE"},
// user: 文件管理
{"user", "/api/v1/file/upload", "POST"},
{"user", "/api/v1/files", "GET"},
{"user", "/api/v1/file/:id", "GET"},
{"user", "/api/v1/file/:id/url", "GET"},
{"user", "/api/v1/file/:id", "PUT"},
// super_admin: 文件删除
{"super_admin", "/api/v1/file/:id", "DELETE"},
// user: 个人机构相关
{"user", "/api/v1/profile/orgs", "GET"},
{"user", "/api/v1/profile/current-org", "PUT"},
// admin: 菜单管理(读取)
{"admin", "/api/v1/menus", "GET"},
// super_admin: 菜单管理(增删改)
{"super_admin", "/api/v1/menu", "POST"},
{"super_admin", "/api/v1/menu/:id", "PUT"},
{"super_admin", "/api/v1/menu/:id", "DELETE"},
// admin: 角色管理(读取)
{"admin", "/api/v1/roles", "GET"},
{"admin", "/api/v1/role/:id/menus", "GET"},
// super_admin: 角色管理(增删改)
{"super_admin", "/api/v1/role", "POST"},
{"super_admin", "/api/v1/role/:id", "PUT"},
{"super_admin", "/api/v1/role/:id", "DELETE"},
{"super_admin", "/api/v1/role/:id/menus", "PUT"},
// admin: 机构管理
{"admin", "/api/v1/organizations", "GET"},
{"admin", "/api/v1/organization", "POST"},
{"admin", "/api/v1/organization/:id", "PUT"},
{"admin", "/api/v1/organization/:id/members", "GET"},
{"admin", "/api/v1/organization/:id/member", "POST"},
{"admin", "/api/v1/organization/:id/member/:userId", "PUT"},
{"admin", "/api/v1/organization/:id/member/:userId", "DELETE"},
// super_admin: 机构删除
{"super_admin", "/api/v1/organization/:id", "DELETE"},
}
for _, p := range policies {
@ -204,3 +264,94 @@ func seedCasbinPolicies(enforcer *casbin.Enforcer) {
enforcer.SavePolicy()
log.Println("[Casbin] Policies seeded successfully")
}
// seedRoles 种子系统角色(幂等)
func seedRoles(db *gorm.DB) {
roles := []model.Role{
{Name: "超级管理员", Code: model.RoleSuperAdmin, Description: "系统超级管理员", IsSystem: true, SortOrder: 1, Status: 1},
{Name: "管理员", Code: model.RoleAdmin, Description: "系统管理员", IsSystem: true, SortOrder: 2, Status: 1},
{Name: "普通用户", Code: model.RoleUser, Description: "普通用户", IsSystem: true, SortOrder: 3, Status: 1},
{Name: "访客", Code: model.RoleGuest, Description: "访客", IsSystem: true, SortOrder: 4, Status: 1},
}
for _, r := range roles {
var existing model.Role
if err := db.Where("code = ?", r.Code).First(&existing).Error; err != nil {
db.Create(&r)
}
}
log.Println("[Seed] Roles seeded successfully")
}
// seedMenus 种子默认菜单(幂等)
func seedMenus(db *gorm.DB) {
menus := []model.Menu{
{Name: "我的", Path: "/my", Icon: "User", Type: "default", SortOrder: 1, Visible: true, Status: 1},
{Name: "仪表盘", Path: "/dashboard", Icon: "LayoutDashboard", Type: "config", SortOrder: 2, Visible: true, Status: 1},
{Name: "用户管理", Path: "/users", Icon: "Users", Type: "config", SortOrder: 3, Visible: true, Status: 1},
{Name: "文件管理", Path: "/files", Icon: "FolderOpen", Type: "config", SortOrder: 4, Visible: true, Status: 1},
{Name: "角色管理", Path: "/roles", Icon: "Shield", Type: "config", SortOrder: 5, Visible: true, Status: 1},
{Name: "菜单管理", Path: "/menus", Icon: "Menu", Type: "config", SortOrder: 6, Visible: true, Status: 1},
{Name: "机构管理", Path: "/organizations", Icon: "Building2", Type: "config", SortOrder: 7, Visible: true, Status: 1},
{Name: "设置", Path: "/settings", Icon: "Settings", Type: "default", SortOrder: 8, Visible: true, Status: 1},
}
for _, m := range menus {
var existing model.Menu
if err := db.Where("path = ?", m.Path).First(&existing).Error; err != nil {
db.Create(&m)
}
}
log.Println("[Seed] Menus seeded successfully")
}
// seedRoleMenus 种子角色-菜单关联(幂等)
func seedRoleMenus(db *gorm.DB) {
// 获取所有角色
var roles []model.Role
db.Find(&roles)
// 获取所有菜单
var menus []model.Menu
db.Find(&menus)
if len(roles) == 0 || len(menus) == 0 {
return
}
// 构建菜单分类
var allMenuIds []int64
var defaultMenuIds []int64
for _, m := range menus {
allMenuIds = append(allMenuIds, m.Id)
if m.Type == "default" {
defaultMenuIds = append(defaultMenuIds, m.Id)
}
}
for _, r := range roles {
// 检查角色是否已有菜单关联
var count int64
db.Model(&model.RoleMenu{}).Where("role_id = ?", r.Id).Count(&count)
if count > 0 {
continue
}
var menuIds []int64
switch r.Code {
case model.RoleSuperAdmin, model.RoleAdmin:
menuIds = allMenuIds
case model.RoleUser, model.RoleGuest:
menuIds = defaultMenuIds
}
if len(menuIds) > 0 {
records := make([]model.RoleMenu, 0, len(menuIds))
for _, menuId := range menuIds {
records = append(records, model.RoleMenu{RoleId: r.Id, MenuId: menuId})
}
db.Create(&records)
}
}
log.Println("[Seed] RoleMenus seeded successfully")
}

Loading…
Cancel
Save